@@ -42,7 +42,7 @@ class Connection(metaclass=ConnectionMeta):
4242 '_stmt_cache' , '_stmts_to_close' , '_listeners' ,
4343 '_server_version' , '_server_caps' , '_intro_query' ,
4444 '_reset_query' , '_proxy' , '_stmt_exclusive_section' ,
45- '_config' , '_params' , '_addr' , '_notice_callbacks ' )
45+ '_config' , '_params' , '_addr' , '_log_listeners ' )
4646
4747 def __init__ (self , protocol , transport , loop ,
4848 addr : (str , int ) or str ,
@@ -70,7 +70,7 @@ def __init__(self, protocol, transport, loop,
7070 self ._stmts_to_close = set ()
7171
7272 self ._listeners = {}
73- self ._notice_callbacks = set ()
73+ self ._log_listeners = set ()
7474
7575 settings = self ._protocol .get_settings ()
7676 ver_string = settings .server_version
@@ -128,25 +128,30 @@ async def remove_listener(self, channel, callback):
128128 del self ._listeners [channel ]
129129 await self .fetch ('UNLISTEN {}' .format (channel ))
130130
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 .
133133
134134 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.
137137
138138 :param callable callback:
139139 A callable receiving the following arguments:
140140 **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
142144 """
143145 if self .is_closed ():
144146 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.
146151
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 )
150155
151156 def get_server_pid (self ):
152157 """Return the PID of the Postgres server the connection is bound to."""
@@ -975,22 +980,23 @@ async def close(self):
975980 if self .is_closed ():
976981 return
977982 self ._mark_stmts_as_closed ()
978- self ._listeners = {}
983+ self ._listeners .clear ()
984+ self ._log_listeners .clear ()
979985 self ._aborted = True
980986 await self ._protocol .close ()
981- self ._notice_callbacks = set ()
982987
983988 def terminate (self ):
984989 """Terminate the connection without waiting for pending data."""
985990 self ._mark_stmts_as_closed ()
986- self ._listeners = {}
991+ self ._listeners .clear ()
992+ self ._log_listeners .clear ()
987993 self ._aborted = True
988994 self ._protocol .abort ()
989- self ._notice_callbacks = set ()
990995
991996 async def reset (self ):
992997 self ._check_open ()
993998 self ._listeners .clear ()
999+ self ._log_listeners .clear ()
9941000 reset_query = self ._get_reset_query ()
9951001 if reset_query :
9961002 await self .execute (reset_query )
@@ -1068,44 +1074,37 @@ async def cancel():
10681074
10691075 self ._loop .create_task (cancel ())
10701076
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
10771080
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 )
10801082
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 ):
10821089 try :
10831090 cb (con_ref , message )
10841091 except Exception as ex :
10851092 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 ),
10881095 'exception' : ex
10891096 })
10901097
1091- def _notify (self , pid , channel , payload ):
1098+ def _process_notification (self , pid , channel , payload ):
10921099 if channel not in self ._listeners :
10931100 return
10941101
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 ()
11041103 for cb in self ._listeners [channel ]:
11051104 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 )
11071106
1108- def _call_notify_cb (self , cb , con_ref , pid , channel , payload ):
1107+ def _call_listener (self , cb , con_ref , pid , channel , payload ):
11091108 try :
11101109 cb (con_ref , pid , channel , payload )
11111110 except Exception as ex :
@@ -1115,6 +1114,17 @@ def _call_notify_cb(self, cb, con_ref, pid, channel, payload):
11151114 'exception' : ex
11161115 })
11171116
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+
11181128 def _get_reset_query (self ):
11191129 if self ._reset_query is not None :
11201130 return self ._reset_query
0 commit comments