@@ -42,7 +42,7 @@ class Connection(metaclass=ConnectionMeta):
42
42
'_stmt_cache' , '_stmts_to_close' , '_listeners' ,
43
43
'_server_version' , '_server_caps' , '_intro_query' ,
44
44
'_reset_query' , '_proxy' , '_stmt_exclusive_section' ,
45
- '_config' , '_params' , '_addr' , '_notice_callbacks ' )
45
+ '_config' , '_params' , '_addr' , '_log_listeners ' )
46
46
47
47
def __init__ (self , protocol , transport , loop ,
48
48
addr : (str , int ) or str ,
@@ -70,7 +70,7 @@ def __init__(self, protocol, transport, loop,
70
70
self ._stmts_to_close = set ()
71
71
72
72
self ._listeners = {}
73
- self ._notice_callbacks = set ()
73
+ self ._log_listeners = set ()
74
74
75
75
settings = self ._protocol .get_settings ()
76
76
ver_string = settings .server_version
@@ -128,25 +128,30 @@ async def remove_listener(self, channel, callback):
128
128
del self ._listeners [channel ]
129
129
await self .fetch ('UNLISTEN {}' .format (channel ))
130
130
131
- def add_notice_callback (self , callback ):
132
- """Add a callback for Postgres notices (NOTICE, DEBUG, LOG etc.) .
131
+ def add_log_listener (self , callback ):
132
+ """Add a listener for Postgres log messages .
133
133
134
134
It will be called when asyncronous NoticeResponse is received
135
- from the connection. Possible message types are: WARNING, NOTICE, DEBUG,
136
- INFO, or LOG.
135
+ from the connection. Possible message types are: WARNING, NOTICE,
136
+ DEBUG, INFO, or LOG.
137
137
138
138
:param callable callback:
139
139
A callable receiving the following arguments:
140
140
**connection**: a Connection the callback is registered with;
141
- **message**: the `exceptions.PostgresNotice` message.
141
+ **message**: the `exceptions.PostgresLogMessage` message.
142
+
143
+ .. versionadded:: 0.12.0
142
144
"""
143
145
if self .is_closed ():
144
146
raise exceptions .InterfaceError ('connection is closed' )
145
- self ._notice_callbacks .add (callback )
147
+ self ._log_listeners .add (callback )
148
+
149
+ def remove_log_listener (self , callback ):
150
+ """Remove a listening callback for log messages.
146
151
147
- def remove_notice_callback ( self , callback ):
148
- """Remove a callback for notices."""
149
- self ._notice_callbacks .discard (callback )
152
+ .. versionadded:: 0.12.0
153
+ """
154
+ self ._log_listeners .discard (callback )
150
155
151
156
def get_server_pid (self ):
152
157
"""Return the PID of the Postgres server the connection is bound to."""
@@ -975,22 +980,23 @@ async def close(self):
975
980
if self .is_closed ():
976
981
return
977
982
self ._mark_stmts_as_closed ()
978
- self ._listeners = {}
983
+ self ._listeners .clear ()
984
+ self ._log_listeners .clear ()
979
985
self ._aborted = True
980
986
await self ._protocol .close ()
981
- self ._notice_callbacks = set ()
982
987
983
988
def terminate (self ):
984
989
"""Terminate the connection without waiting for pending data."""
985
990
self ._mark_stmts_as_closed ()
986
- self ._listeners = {}
991
+ self ._listeners .clear ()
992
+ self ._log_listeners .clear ()
987
993
self ._aborted = True
988
994
self ._protocol .abort ()
989
- self ._notice_callbacks = set ()
990
995
991
996
async def reset (self ):
992
997
self ._check_open ()
993
998
self ._listeners .clear ()
999
+ self ._log_listeners .clear ()
994
1000
reset_query = self ._get_reset_query ()
995
1001
if reset_query :
996
1002
await self .execute (reset_query )
@@ -1068,44 +1074,37 @@ async def cancel():
1068
1074
1069
1075
self ._loop .create_task (cancel ())
1070
1076
1071
- def _notice (self , message ):
1072
- if self ._proxy is None :
1073
- con_ref = self
1074
- else :
1075
- # See the comment in the `_notify` below.
1076
- con_ref = self ._proxy
1077
+ def _process_log_message (self , fields , last_query ):
1078
+ if not self ._log_listeners :
1079
+ return
1077
1080
1078
- for cb in self ._notice_callbacks :
1079
- self ._loop .call_soon (self ._call_notice_cb , cb , con_ref , message )
1081
+ message = exceptions .PostgresLogMessage .new (fields , query = last_query )
1080
1082
1081
- def _call_notice_cb (self , cb , con_ref , message ):
1083
+ con_ref = self ._unwrap ()
1084
+ for cb in self ._log_listeners :
1085
+ self ._loop .call_soon (
1086
+ self ._call_log_listener , cb , con_ref , message )
1087
+
1088
+ def _call_log_listener (self , cb , con_ref , message ):
1082
1089
try :
1083
1090
cb (con_ref , message )
1084
1091
except Exception as ex :
1085
1092
self ._loop .call_exception_handler ({
1086
- 'message' : 'Unhandled exception in asyncpg notice message '
1087
- 'callback {!r}' .format (cb ),
1093
+ 'message' : 'Unhandled exception in asyncpg log message '
1094
+ 'listener callback {!r}' .format (cb ),
1088
1095
'exception' : ex
1089
1096
})
1090
1097
1091
- def _notify (self , pid , channel , payload ):
1098
+ def _process_notification (self , pid , channel , payload ):
1092
1099
if channel not in self ._listeners :
1093
1100
return
1094
1101
1095
- if self ._proxy is None :
1096
- con_ref = self
1097
- else :
1098
- # `_proxy` is not None when the connection is a member
1099
- # of a connection pool. Which means that the user is working
1100
- # with a `PoolConnectionProxy` instance, and expects to see it
1101
- # (and not the actual Connection) in their event callbacks.
1102
- con_ref = self ._proxy
1103
-
1102
+ con_ref = self ._unwrap ()
1104
1103
for cb in self ._listeners [channel ]:
1105
1104
self ._loop .call_soon (
1106
- self ._call_notify_cb , cb , con_ref , pid , channel , payload )
1105
+ self ._call_listener , cb , con_ref , pid , channel , payload )
1107
1106
1108
- def _call_notify_cb (self , cb , con_ref , pid , channel , payload ):
1107
+ def _call_listener (self , cb , con_ref , pid , channel , payload ):
1109
1108
try :
1110
1109
cb (con_ref , pid , channel , payload )
1111
1110
except Exception as ex :
@@ -1115,6 +1114,17 @@ def _call_notify_cb(self, cb, con_ref, pid, channel, payload):
1115
1114
'exception' : ex
1116
1115
})
1117
1116
1117
+ def _unwrap (self ):
1118
+ if self ._proxy is None :
1119
+ con_ref = self
1120
+ else :
1121
+ # `_proxy` is not None when the connection is a member
1122
+ # of a connection pool. Which means that the user is working
1123
+ # with a `PoolConnectionProxy` instance, and expects to see it
1124
+ # (and not the actual Connection) in their event callbacks.
1125
+ con_ref = self ._proxy
1126
+ return con_ref
1127
+
1118
1128
def _get_reset_query (self ):
1119
1129
if self ._reset_query is not None :
1120
1130
return self ._reset_query
0 commit comments