U
    ~fh                     @  sv  d Z ddlmZ ddlZddlmZmZ ddlmZm	Z	m
Z
mZmZ ddlmZ ddlmZmZ ddlmZmZ dd	lmZmZ erdd
lmZ ddlmZ ddlmZ eddZeg g g g g ZG dd dZG dd deZ G dd deZ!G dd deZ"G dd deZ#G dd deZ$dddddZ%d d!d!d"d#d$Z&dd%d&d'd(Z'd d)d*d+d,d-Z(G d.d/ d/Z)G d0d1 d1e)Z*G d2d3 d3e)Z+G d4d5 d5e)Z,G d6d7 d7Z-G d8d9 d9e-Z.G d:d; d;e-Z/G d<d= d=e-Z0G d>d? d?e-Z1G d@dA dAZ2G dBdC dCZ3G dDdE dEZ4G dFdG dGe4Z5G dHdI dIe5Z6G dJdK dKe5Z7G dLdM dMe6Z8G dNdO dOe5Z9G dPdQ dQe4Z:G dRdS dSe6Z;G dTdU dUe6Z<G dVdW dWe5Z=G dXdY dYZ>G dZd[ d[e>Z?G d\d] d]e>Z@G d^d_ d_e>ZAG d`da daZBG dbdc dceBZCG ddde deeBZDG dfdg dgeBZEG dhdi diZFG djdk dkeFZGG dldm dmeFZHG dndo doeFZIG dpdq dqZJdS )ra  Tools to monitor driver events.

.. versionadded:: 3.1

.. attention:: Starting in PyMongo 3.11, the monitoring classes outlined below
    are included in the PyMongo distribution under the
    :mod:`~pymongo.event_loggers` submodule.

.. seealso:: This module is compatible with both the synchronous and asynchronous PyMongo APIs.


Use :func:`register` to register global listeners for specific events.
Listeners must inherit from one of the abstract classes below and implement
the correct functions for that class.

For example, a simple command logger might be implemented like this::

    import logging

    from pymongo import monitoring

    class CommandLogger(monitoring.CommandListener):

        def started(self, event):
            logging.info("Command {0.command_name} with request id "
                         "{0.request_id} started on server "
                         "{0.connection_id}".format(event))

        def succeeded(self, event):
            logging.info("Command {0.command_name} with request id "
                         "{0.request_id} on server {0.connection_id} "
                         "succeeded in {0.duration_micros} "
                         "microseconds".format(event))

        def failed(self, event):
            logging.info("Command {0.command_name} with request id "
                         "{0.request_id} on server {0.connection_id} "
                         "failed in {0.duration_micros} "
                         "microseconds".format(event))

    monitoring.register(CommandLogger())

Server discovery and monitoring events are also available. For example::

    class ServerLogger(monitoring.ServerListener):

        def opened(self, event):
            logging.info("Server {0.server_address} added to topology "
                         "{0.topology_id}".format(event))

        def description_changed(self, event):
            previous_server_type = event.previous_description.server_type
            new_server_type = event.new_description.server_type
            if new_server_type != previous_server_type:
                # server_type_name was added in PyMongo 3.4
                logging.info(
                    "Server {0.server_address} changed type from "
                    "{0.previous_description.server_type_name} to "
                    "{0.new_description.server_type_name}".format(event))

        def closed(self, event):
            logging.warning("Server {0.server_address} removed from topology "
                            "{0.topology_id}".format(event))


    class HeartbeatLogger(monitoring.ServerHeartbeatListener):

        def started(self, event):
            logging.info("Heartbeat sent to server "
                         "{0.connection_id}".format(event))

        def succeeded(self, event):
            # The reply.document attribute was added in PyMongo 3.4.
            logging.info("Heartbeat to server {0.connection_id} "
                         "succeeded with reply "
                         "{0.reply.document}".format(event))

        def failed(self, event):
            logging.warning("Heartbeat to server {0.connection_id} "
                            "failed with error {0.reply}".format(event))

    class TopologyLogger(monitoring.TopologyListener):

        def opened(self, event):
            logging.info("Topology with id {0.topology_id} "
                         "opened".format(event))

        def description_changed(self, event):
            logging.info("Topology description updated for "
                         "topology id {0.topology_id}".format(event))
            previous_topology_type = event.previous_description.topology_type
            new_topology_type = event.new_description.topology_type
            if new_topology_type != previous_topology_type:
                # topology_type_name was added in PyMongo 3.4
                logging.info(
                    "Topology {0.topology_id} changed type from "
                    "{0.previous_description.topology_type_name} to "
                    "{0.new_description.topology_type_name}".format(event))
            # The has_writable_server and has_readable_server methods
            # were added in PyMongo 3.4.
            if not event.new_description.has_writable_server():
                logging.warning("No writable servers available.")
            if not event.new_description.has_readable_server():
                logging.warning("No readable servers available.")

        def closed(self, event):
            logging.info("Topology with id {0.topology_id} "
                         "closed".format(event))

Connection monitoring and pooling events are also available. For example::

    class ConnectionPoolLogger(ConnectionPoolListener):

        def pool_created(self, event):
            logging.info("[pool {0.address}] pool created".format(event))

        def pool_ready(self, event):
            logging.info("[pool {0.address}] pool is ready".format(event))

        def pool_cleared(self, event):
            logging.info("[pool {0.address}] pool cleared".format(event))

        def pool_closed(self, event):
            logging.info("[pool {0.address}] pool closed".format(event))

        def connection_created(self, event):
            logging.info("[pool {0.address}][connection #{0.connection_id}] "
                         "connection created".format(event))

        def connection_ready(self, event):
            logging.info("[pool {0.address}][connection #{0.connection_id}] "
                         "connection setup succeeded".format(event))

        def connection_closed(self, event):
            logging.info("[pool {0.address}][connection #{0.connection_id}] "
                         "connection closed, reason: "
                         "{0.reason}".format(event))

        def connection_check_out_started(self, event):
            logging.info("[pool {0.address}] connection check out "
                         "started".format(event))

        def connection_check_out_failed(self, event):
            logging.info("[pool {0.address}] connection check out "
                         "failed, reason: {0.reason}".format(event))

        def connection_checked_out(self, event):
            logging.info("[pool {0.address}][connection #{0.connection_id}] "
                         "connection checked out of pool".format(event))

        def connection_checked_in(self, event):
            logging.info("[pool {0.address}][connection #{0.connection_id}] "
                         "connection checked into pool".format(event))


Event listeners can also be registered per instance of
:class:`~pymongo.mongo_client.MongoClient`::

    client = MongoClient(event_listeners=[CommandLogger()])

Note that previously registered global listeners are automatically included
when configuring per client event listeners. Registering a new global listener
will not add that listener to existing client instances.

.. note:: Events are delivered **synchronously**. Application threads block
  waiting for event handlers (e.g. :meth:`~CommandListener.started`) to
  return. Care must be taken to ensure that your event handlers are efficient
  enough to not adversely affect overall application performance.

.. warning:: The command documents published through this API are *not* copies.
  If you intend to modify them in any way you must copy them in your event
  handler first.
    )annotationsN)abc
namedtuple)TYPE_CHECKINGAnyMappingOptionalSequence)ObjectId)HelloHelloCompat)_SENSITIVE_COMMANDS_handle_exception)_Address_DocumentOut)	timedelta)ServerDescription)TopologyDescription
_Listeners)command_listenersserver_listenersserver_heartbeat_listenerstopology_listenerscmap_listenersc                   @  s   e Zd ZdZdS )_EventListenerz,Abstract base class for all event listeners.N)__name__
__module____qualname____doc__ r   r   6/tmp/pip-unpacked-wheel-36gvocj8/pymongo/monitoring.pyr      s   r   c                   @  s@   e Zd ZdZdddddZddddd	Zd
ddddZdS )CommandListenerzAbstract base class for command listeners.

    Handles `CommandStartedEvent`, `CommandSucceededEvent`,
    and `CommandFailedEvent`.
    CommandStartedEventNoneeventreturnc                 C  s   t dS )zAbstract method to handle a `CommandStartedEvent`.

        :param event: An instance of :class:`CommandStartedEvent`.
        NNotImplementedErrorselfr%   r   r   r    started   s    zCommandListener.startedCommandSucceededEventc                 C  s   t dS )zAbstract method to handle a `CommandSucceededEvent`.

        :param event: An instance of :class:`CommandSucceededEvent`.
        Nr'   r)   r   r   r    	succeeded   s    zCommandListener.succeededCommandFailedEventc                 C  s   t dS )z}Abstract method to handle a `CommandFailedEvent`.

        :param event: An instance of :class:`CommandFailedEvent`.
        Nr'   r)   r   r   r    failed   s    zCommandListener.failedNr   r   r   r   r+   r-   r/   r   r   r   r    r!      s   r!   c                   @  s   e Zd ZdZdddddZddddd	Zd
ddddZdddddZdddddZdddddZ	dddddZ
dddddZdddddZdddd d!Zd"ddd#d$Zd%S )&ConnectionPoolListenera-  Abstract base class for connection pool listeners.

    Handles all of the connection pool events defined in the Connection
    Monitoring and Pooling Specification:
    :class:`PoolCreatedEvent`, :class:`PoolClearedEvent`,
    :class:`PoolClosedEvent`, :class:`ConnectionCreatedEvent`,
    :class:`ConnectionReadyEvent`, :class:`ConnectionClosedEvent`,
    :class:`ConnectionCheckOutStartedEvent`,
    :class:`ConnectionCheckOutFailedEvent`,
    :class:`ConnectionCheckedOutEvent`,
    and :class:`ConnectionCheckedInEvent`.

    .. versionadded:: 3.9
    PoolCreatedEventr#   r$   c                 C  s   t dS )zAbstract method to handle a :class:`PoolCreatedEvent`.

        Emitted when a connection Pool is created.

        :param event: An instance of :class:`PoolCreatedEvent`.
        Nr'   r)   r   r   r    pool_created  s    z#ConnectionPoolListener.pool_createdPoolReadyEventc                 C  s   t dS )zAbstract method to handle a :class:`PoolReadyEvent`.

        Emitted when a connection Pool is marked ready.

        :param event: An instance of :class:`PoolReadyEvent`.

        .. versionadded:: 4.0
        Nr'   r)   r   r   r    
pool_ready  s    	z!ConnectionPoolListener.pool_readyPoolClearedEventc                 C  s   t dS )zAbstract method to handle a `PoolClearedEvent`.

        Emitted when a connection Pool is cleared.

        :param event: An instance of :class:`PoolClearedEvent`.
        Nr'   r)   r   r   r    pool_cleared"  s    z#ConnectionPoolListener.pool_clearedPoolClosedEventc                 C  s   t dS )zAbstract method to handle a `PoolClosedEvent`.

        Emitted when a connection Pool is closed.

        :param event: An instance of :class:`PoolClosedEvent`.
        Nr'   r)   r   r   r    pool_closed+  s    z"ConnectionPoolListener.pool_closedConnectionCreatedEventc                 C  s   t dS )zAbstract method to handle a :class:`ConnectionCreatedEvent`.

        Emitted when a connection Pool creates a Connection object.

        :param event: An instance of :class:`ConnectionCreatedEvent`.
        Nr'   r)   r   r   r    connection_created4  s    z)ConnectionPoolListener.connection_createdConnectionReadyEventc                 C  s   t dS )zAbstract method to handle a :class:`ConnectionReadyEvent`.

        Emitted when a connection has finished its setup, and is now ready to
        use.

        :param event: An instance of :class:`ConnectionReadyEvent`.
        Nr'   r)   r   r   r    connection_ready=  s    z'ConnectionPoolListener.connection_readyConnectionClosedEventc                 C  s   t dS )zAbstract method to handle a :class:`ConnectionClosedEvent`.

        Emitted when a connection Pool closes a connection.

        :param event: An instance of :class:`ConnectionClosedEvent`.
        Nr'   r)   r   r   r    connection_closedG  s    z(ConnectionPoolListener.connection_closedConnectionCheckOutStartedEventc                 C  s   t dS )zAbstract method to handle a :class:`ConnectionCheckOutStartedEvent`.

        Emitted when the driver starts attempting to check out a connection.

        :param event: An instance of :class:`ConnectionCheckOutStartedEvent`.
        Nr'   r)   r   r   r    connection_check_out_startedP  s    z3ConnectionPoolListener.connection_check_out_startedConnectionCheckOutFailedEventc                 C  s   t dS )zAbstract method to handle a :class:`ConnectionCheckOutFailedEvent`.

        Emitted when the driver's attempt to check out a connection fails.

        :param event: An instance of :class:`ConnectionCheckOutFailedEvent`.
        Nr'   r)   r   r   r    connection_check_out_failedY  s    z2ConnectionPoolListener.connection_check_out_failedConnectionCheckedOutEventc                 C  s   t dS )zAbstract method to handle a :class:`ConnectionCheckedOutEvent`.

        Emitted when the driver successfully checks out a connection.

        :param event: An instance of :class:`ConnectionCheckedOutEvent`.
        Nr'   r)   r   r   r    connection_checked_outb  s    z-ConnectionPoolListener.connection_checked_outConnectionCheckedInEventc                 C  s   t dS )zAbstract method to handle a :class:`ConnectionCheckedInEvent`.

        Emitted when the driver checks in a connection back to the connection
        Pool.

        :param event: An instance of :class:`ConnectionCheckedInEvent`.
        Nr'   r)   r   r   r    connection_checked_ink  s    z,ConnectionPoolListener.connection_checked_inN)r   r   r   r   r3   r5   r7   r9   r;   r=   r?   rA   rC   rE   rG   r   r   r   r    r1      s   				
				r1   c                   @  s@   e Zd ZdZdddddZddddd	Zd
ddddZdS )ServerHeartbeatListenerzAbstract base class for server heartbeat listeners.

    Handles `ServerHeartbeatStartedEvent`, `ServerHeartbeatSucceededEvent`,
    and `ServerHeartbeatFailedEvent`.

    .. versionadded:: 3.3
    ServerHeartbeatStartedEventr#   r$   c                 C  s   t dS )zAbstract method to handle a `ServerHeartbeatStartedEvent`.

        :param event: An instance of :class:`ServerHeartbeatStartedEvent`.
        Nr'   r)   r   r   r    r+     s    zServerHeartbeatListener.startedServerHeartbeatSucceededEventc                 C  s   t dS )zAbstract method to handle a `ServerHeartbeatSucceededEvent`.

        :param event: An instance of :class:`ServerHeartbeatSucceededEvent`.
        Nr'   r)   r   r   r    r-     s    z!ServerHeartbeatListener.succeededServerHeartbeatFailedEventc                 C  s   t dS )zAbstract method to handle a `ServerHeartbeatFailedEvent`.

        :param event: An instance of :class:`ServerHeartbeatFailedEvent`.
        Nr'   r)   r   r   r    r/     s    zServerHeartbeatListener.failedNr0   r   r   r   r    rH   v  s   rH   c                   @  s@   e Zd ZdZdddddZddddd	Zd
ddddZdS )TopologyListenerzAbstract base class for topology monitoring listeners.
    Handles `TopologyOpenedEvent`, `TopologyDescriptionChangedEvent`, and
    `TopologyClosedEvent`.

    .. versionadded:: 3.3
    TopologyOpenedEventr#   r$   c                 C  s   t dS )zAbstract method to handle a `TopologyOpenedEvent`.

        :param event: An instance of :class:`TopologyOpenedEvent`.
        Nr'   r)   r   r   r    opened  s    zTopologyListener.openedTopologyDescriptionChangedEventc                 C  s   t dS )zAbstract method to handle a `TopologyDescriptionChangedEvent`.

        :param event: An instance of :class:`TopologyDescriptionChangedEvent`.
        Nr'   r)   r   r   r    description_changed  s    z$TopologyListener.description_changedTopologyClosedEventc                 C  s   t dS )zAbstract method to handle a `TopologyClosedEvent`.

        :param event: An instance of :class:`TopologyClosedEvent`.
        Nr'   r)   r   r   r    closed  s    zTopologyListener.closedNr   r   r   r   rN   rP   rR   r   r   r   r    rL     s   rL   c                   @  s@   e Zd ZdZdddddZddddd	Zd
ddddZdS )ServerListenerzAbstract base class for server listeners.
    Handles `ServerOpeningEvent`, `ServerDescriptionChangedEvent`, and
    `ServerClosedEvent`.

    .. versionadded:: 3.3
    ServerOpeningEventr#   r$   c                 C  s   t dS )z}Abstract method to handle a `ServerOpeningEvent`.

        :param event: An instance of :class:`ServerOpeningEvent`.
        Nr'   r)   r   r   r    rN     s    zServerListener.openedServerDescriptionChangedEventc                 C  s   t dS )zAbstract method to handle a `ServerDescriptionChangedEvent`.

        :param event: An instance of :class:`ServerDescriptionChangedEvent`.
        Nr'   r)   r   r   r    rP     s    z"ServerListener.description_changedServerClosedEventc                 C  s   t dS )z{Abstract method to handle a `ServerClosedEvent`.

        :param event: An instance of :class:`ServerClosedEvent`.
        Nr'   r)   r   r   r    rR     s    zServerListener.closedNrS   r   r   r   r    rT     s   rT   r   int)durr&   c                 C  s   t |  d S )z'Convert duration 'dur' to microseconds.g    .A)rX   total_seconds)rY   r   r   r    
_to_micros  s    r[   strzSequence[_EventListeners])option	listenersr&   c                 C  sB   t |tjst|  d|D ]}t |tstd|  dq|S )zValidate event listenersz must be a list or tupleListeners for x must be either a CommandListener, ServerHeartbeatListener, ServerListener, TopologyListener, or ConnectionPoolListener.)
isinstancer   r	   	TypeErrorr   )r]   r^   listenerr   r   r    _validate_event_listeners  s    

rd   r#   )rc   r&   c                 C  s   t | tstd|  dt | tr0tj|  t | trFtj|  t | t	r\tj
|  t | trrtj|  t | trtj|  dS )zRegister a global event listener.

    :param listener: A subclasses of :class:`CommandListener`,
        :class:`ServerHeartbeatListener`, :class:`ServerListener`,
        :class:`TopologyListener`, or :class:`ConnectionPoolListener`.
    r_   r`   N)ra   r   rb   r!   
_LISTENERSr   appendrH   r   rT   r   rL   r   r1   r   )rc   r   r   r    register  s    






rg   zMapping[str, Any]bool)command_namedocr&   c                 C  s"   |   dtjfkrd|krdS dS )NZhelloZspeculativeAuthenticateTF)lowerr   Z
LEGACY_CMD)ri   rj   r   r   r    _is_speculative_authenticate  s    rl   c                
   @  s   e Zd ZdZdZdddddd	ddd
dddZeddddZeddddZeddddZ	ed	dddZ
eddddZeddddZeddddZdS )_CommandEventzBase class for command events.)Z
__cmd_nameZ	__rqst_idZ	__conn_idZ__op_id__service_idZ__dbZ__server_conn_idN r\   rX   r   Optional[int]Optional[ObjectId]r#   )ri   
request_idconnection_idoperation_id
service_iddatabase_nameserver_connection_idr&   c                 C  s.   || _ || _|| _|| _|| _|| _|| _d S N)_CommandEvent__cmd_name_CommandEvent__rqst_id_CommandEvent__conn_id_CommandEvent__op_id_CommandEvent__service_id_CommandEvent__db_CommandEvent__server_conn_id)r*   ri   rr   rs   rt   ru   rv   rw   r   r   r    __init__  s    
z_CommandEvent.__init__r&   c                 C  s   | j S )zThe command name.)ry   r*   r   r   r    ri   +  s    z_CommandEvent.command_namec                 C  s   | j S )z"The request id for this operation.)rz   r   r   r   r    rr   0  s    z_CommandEvent.request_idc                 C  s   | j S )z@The address (host, port) of the server this command was sent to.)r{   r   r   r   r    rs   5  s    z_CommandEvent.connection_idc                 C  s   | j S )z^The service_id this command was sent to, or ``None``.

        .. versionadded:: 3.12
        )r}   r   r   r   r    ru   :  s    z_CommandEvent.service_idc                 C  s   | j S )z(An id for this series of events or None.)r|   r   r   r   r    rt   B  s    z_CommandEvent.operation_idc                 C  s   | j S )z^The database_name this command was sent to, or ``""``.

        .. versionadded:: 4.6
        )r~   r   r   r   r    rv   G  s    z_CommandEvent.database_namec                 C  s   | j S )zThe server-side connection id for the connection this command was sent on, or ``None``.

        .. versionadded:: 4.7
        )r   r   r   r   r    rw   O  s    z"_CommandEvent.server_connection_id)Nro   N)r   r   r   r   	__slots__r   propertyri   rr   rs   ru   rt   rv   rw   r   r   r   r    rm     s(      rm   c                
      sp   e Zd ZdZdZddddddd	dd
d fddZeddddZedd fddZddddZ	  Z
S )r"   a  Event published when a command starts.

    :param command: The command document.
    :param database_name: The name of the database this command was run against.
    :param request_id: The request id for this operation.
    :param connection_id: The address (host, port) of the server this command
        was sent to.
    :param operation_id: An optional identifier for a series of related events.
    :param service_id: The service_id this command was sent to, or ``None``.
    )Z__cmdNr   r\   rX   r   rp   rq   r#   )commandrv   rr   rs   rt   ru   rw   r&   c           
   	     sd   |st |dtt|}t j|||||||d | }	|	tksRt|	|rZi | _n|| _d S )Nz is not a valid commandru   rv   rw   )	
ValueErrornextitersuperr   rk   r   rl   _CommandStartedEvent__cmd)
r*   r   rv   rr   rs   rt   ru   rw   ri   cmd_name	__class__r   r    r   f  s     
	zCommandStartedEvent.__init__r   c                 C  s   | j S )zThe command document.)r   r   r   r   r    r     s    zCommandStartedEvent.commandc                   s   t  jS )z6The name of the database this command was run against.)r   rv   r   r   r   r    rv     s    z!CommandStartedEvent.database_namec              	   C  s&   d | jj| j| j| j| j| j| jS )Nz[<{} {} db: {!r}, command: {!r}, operation_id: {}, service_id: {}, server_connection_id: {}>)	formatr   r   rs   rv   ri   rt   ru   rw   r   r   r   r    __repr__  s    zCommandStartedEvent.__repr__)NN)r   r   r   r   r   r   r   r   rv   r   __classcell__r   r   r   r    r"   X  s   	  "r"   c                      sp   e Zd ZdZdZdddddd	d
ddd
dd
 fddZeddddZeddddZddddZ	  Z
S )r,   aO  Event published when a command succeeds.

    :param duration: The command duration as a datetime.timedelta.
    :param reply: The server reply document.
    :param command_name: The command name.
    :param request_id: The request id for this operation.
    :param connection_id: The address (host, port) of the server this command
        was sent to.
    :param operation_id: An optional identifier for a series of related events.
    :param service_id: The service_id this command was sent to, or ``None``.
    :param database_name: The database this command was sent to, or ``""``.
    )__duration_micros__replyNro   datetime.timedeltar   r\   rX   r   rp   rq   r#   )
durationreplyri   rr   rs   rt   ru   rv   rw   r&   c
              	     sP   t  j|||||||	d t|| _| }
|
tks>t|
|rFi | _n|| _d S Nr   )r   r   r[   '_CommandSucceededEvent__duration_microsrk   r   rl   _CommandSucceededEvent__reply)r*   r   r   ri   rr   rs   rt   ru   rv   rw   r   r   r   r    r     s    	
zCommandSucceededEvent.__init__r   c                 C  s   | j S z/The duration of this operation in microseconds.)r   r   r   r   r    duration_micros  s    z%CommandSucceededEvent.duration_microsc                 C  s   | j S z/The server failure document for this operation.)r   r   r   r   r    r     s    zCommandSucceededEvent.replyc              
   C  s*   d | jj| j| j| j| j| j| j| j	S )Nzp<{} {} db: {!r}, command: {!r}, operation_id: {}, duration_micros: {}, service_id: {}, server_connection_id: {}>)
r   r   r   rs   rv   ri   rt   r   ru   rw   r   r   r   r    r     s    zCommandSucceededEvent.__repr__)Nro   N)r   r   r   r   r   r   r   r   r   r   r   r   r   r   r    r,     s   
   &r,   c                      sp   e Zd ZdZdZdddddd	d
ddd
dd
 fddZeddddZeddddZddddZ	  Z
S )r.   aN  Event published when a command fails.

    :param duration: The command duration as a datetime.timedelta.
    :param failure: The server reply document.
    :param command_name: The command name.
    :param request_id: The request id for this operation.
    :param connection_id: The address (host, port) of the server this command
        was sent to.
    :param operation_id: An optional identifier for a series of related events.
    :param service_id: The service_id this command was sent to, or ``None``.
    :param database_name: The database this command was sent to, or ``""``.
    )r   Z	__failureNro   r   r   r\   rX   r   rp   rq   r#   )
r   failureri   rr   rs   rt   ru   rv   rw   r&   c
           
   	     s.   t  j|||||||	d t|| _|| _d S r   )r   r   r[   $_CommandFailedEvent__duration_micros_CommandFailedEvent__failure)
r*   r   r   ri   rr   rs   rt   ru   rv   rw   r   r   r    r     s    	
zCommandFailedEvent.__init__r   c                 C  s   | j S r   )r   r   r   r   r    r     s    z"CommandFailedEvent.duration_microsc                 C  s   | j S r   )r   r   r   r   r    r     s    zCommandFailedEvent.failurec                 C  s.   d | jj| j| j| j| j| j| j| j	| j
	S )Nz<{} {} db: {!r}, command: {!r}, operation_id: {}, duration_micros: {}, failure: {!r}, service_id: {}, server_connection_id: {}>)r   r   r   rs   rv   ri   rt   r   r   ru   rw   r   r   r   r    r     s    zCommandFailedEvent.__repr__)Nro   N)r   r   r   r   r   r   r   r   r   r   r   r   r   r   r    r.     s   
   &r.   c                   @  sD   e Zd ZdZdZdddddZeddd	d
ZddddZdS )
_PoolEventzBase class for pool events.Z	__addressr   r#   addressr&   c                 C  s
   || _ d S rx   _PoolEvent__addressr*   r   r   r   r    r   (  s    z_PoolEvent.__init__r   c                 C  s   | j S )zbThe address (host, port) pair of the server the pool is attempting
        to connect to.
        r   r   r   r   r    r   +  s    z_PoolEvent.addressr\   c                 C  s   | j j d| jdS N())r   r   r   r   r   r   r    r   2  s    z_PoolEvent.__repr__N	r   r   r   r   r   r   r   r   r   r   r   r   r    r   #  s   r   c                      sN   e Zd ZdZdZdddd fddZedd	d
dZdd	ddZ  Z	S )r2   zPublished when a Connection Pool is created.

    :param address: The address (host, port) pair of the server this Pool is
       attempting to connect to.

    .. versionadded:: 3.9
    )Z	__optionsr   dict[str, Any]r#   r   optionsr&   c                   s   t  | || _d S rx   )r   r   _PoolCreatedEvent__options)r*   r   r   r   r   r    r   A  s    zPoolCreatedEvent.__init__r   c                 C  s   | j S )zCAny non-default pool options that were set on this Connection Pool.)r   r   r   r   r    r   E  s    zPoolCreatedEvent.optionsr\   c                 C  s   | j j d| jd| jdS Nr   z, r   )r   r   r   r   r   r   r   r    r   J  s    zPoolCreatedEvent.__repr__)
r   r   r   r   r   r   r   r   r   r   r   r   r   r    r2   6  s   r2   c                   @  s   e Zd ZdZdZdS )r4   zPublished when a Connection Pool is marked ready.

    :param address: The address (host, port) pair of the server this Pool is
       attempting to connect to.

    .. versionadded:: 4.0
    r   Nr   r   r   r   r   r   r   r   r    r4   N  s   r4   c                      sd   e Zd ZdZdZdddddd	 fd
dZeddddZeddddZddddZ	  Z
S )r6   aw  Published when a Connection Pool is cleared.

    :param address: The address (host, port) pair of the server this Pool is
       attempting to connect to.
    :param service_id: The service_id this command was sent to, or ``None``.
    :param interrupt_connections: True if all active connections were interrupted by the Pool during clearing.

    .. versionadded:: 3.9
    )rn   Z__interrupt_connectionsNFr   rq   rh   r#   r   ru   interrupt_connectionsr&   c                   s   t  | || _|| _d S rx   )r   r   _PoolClearedEvent__service_id(_PoolClearedEvent__interrupt_connections)r*   r   ru   r   r   r   r    r   g  s    zPoolClearedEvent.__init__r   c                 C  s   | j S )zConnections with this service_id are cleared.

        When service_id is ``None``, all connections in the pool are cleared.

        .. versionadded:: 3.12
        )r   r   r   r   r    ru   q  s    zPoolClearedEvent.service_idc                 C  s   | j S )zdIf True, active connections are interrupted during clearing.

        .. versionadded:: 4.7
        )r   r   r   r   r    r   {  s    z&PoolClearedEvent.interrupt_connectionsr\   c                 C  s&   | j j d| jd| jd| jdS r   )r   r   r   r   r   r   r   r   r    r     s    zPoolClearedEvent.__repr__)NF)r   r   r   r   r   r   r   ru   r   r   r   r   r   r   r    r6   Z  s   
  
	r6   c                   @  s   e Zd ZdZdZdS )r8   zPublished when a Connection Pool is closed.

    :param address: The address (host, port) pair of the server this Pool is
       attempting to connect to.

    .. versionadded:: 3.9
    r   Nr   r   r   r   r    r8     s   r8   c                   @  s    e Zd ZdZdZdZdZdZdS )ConnectionClosedReasonzqAn enum that defines values for `reason` on a
    :class:`ConnectionClosedEvent`.

    .. versionadded:: 3.9
    staleZidleerror
poolClosedN)r   r   r   r   ZSTALEZIDLEERRORPOOL_CLOSEDr   r   r   r    r     s   r   c                   @  s   e Zd ZdZdZdZdZdS )ConnectionCheckOutFailedReasonzyAn enum that defines values for `reason` on a
    :class:`ConnectionCheckOutFailedEvent`.

    .. versionadded:: 3.9
    timeoutr   ZconnectionErrorN)r   r   r   r   TIMEOUTr   Z
CONN_ERRORr   r   r   r    r     s
   r   c                   @  sD   e Zd ZdZdZdddddZeddd	d
ZddddZdS )_ConnectionEventz)Private base class for connection events.r   r   r#   r   c                 C  s
   || _ d S rx   _ConnectionEvent__addressr   r   r   r    r     s    z_ConnectionEvent.__init__r   c                 C  s   | j S )ziThe address (host, port) pair of the server this connection is
        attempting to connect to.
        r   r   r   r   r    r     s    z_ConnectionEvent.addressr\   c                 C  s   | j j d| jdS r   )r   r   r   r   r   r   r    r     s    z_ConnectionEvent.__repr__Nr   r   r   r   r    r     s   r   c                      sN   e Zd ZdZdZdddd fddZedd	d
dZdd	ddZ  Z	S )_ConnectionIdEventz4Private base class for connection events with an id.)__connection_idr   rX   r#   r   rs   r&   c                   s   t  | || _d S rx   )r   r   !_ConnectionIdEvent__connection_id)r*   r   rs   r   r   r    r     s    z_ConnectionIdEvent.__init__r   c                 C  s   | j S )zThe ID of the connection.)r   r   r   r   r    rs     s    z _ConnectionIdEvent.connection_idr\   c                 C  s   | j j d| jd| jdS r   )r   r   r   r   r   r   r   r    r     s    z_ConnectionIdEvent.__repr__)
r   r   r   r   r   r   r   rs   r   r   r   r   r   r    r     s   r   c                      sP   e Zd ZdZdZddddd fdd	Zedd
ddZdd
ddZ  Z	S )_ConnectionDurationEventz9Private base class for connection events with a duration.)
__durationr   rX   Optional[float]r#   r   rs   r   r&   c                   s   t  || || _d S rx   )r   r   "_ConnectionDurationEvent__duration)r*   r   rs   r   r   r   r    r     s    z!_ConnectionDurationEvent.__init__r   c                 C  s   | j S )zMThe duration of the connection event.

        .. versionadded:: 4.7
        )r   r   r   r   r    r     s    z!_ConnectionDurationEvent.durationr\   c                 C  s&   | j j d| jd| jd| jdS r   )r   r   r   rs   r   r   r   r   r    r     s    z!_ConnectionDurationEvent.__repr__)
r   r   r   r   r   r   r   r   r   r   r   r   r   r    r     s   r   c                   @  s   e Zd ZdZdZdS )r:   a  Published when a Connection Pool creates a Connection object.

    NOTE: This connection is not ready for use until the
    :class:`ConnectionReadyEvent` is published.

    :param address: The address (host, port) pair of the server this
       Connection is attempting to connect to.
    :param connection_id: The integer ID of the Connection in this Pool.

    .. versionadded:: 3.9
    r   Nr   r   r   r   r    r:     s   r:   c                   @  s   e Zd ZdZdZdS )r<   a&  Published when a Connection has finished its setup, and is ready to use.

    :param address: The address (host, port) pair of the server this
       Connection is attempting to connect to.
    :param connection_id: The integer ID of the Connection in this Pool.

    .. versionadded:: 3.9
    r   Nr   r   r   r   r    r<     s   	r<   c                      sN   e Zd ZdZdZdddd fddZedd	d
dZdd	ddZ  Z	S )r>   aK  Published when a Connection is closed.

    :param address: The address (host, port) pair of the server this
       Connection is attempting to connect to.
    :param connection_id: The integer ID of the Connection in this Pool.
    :param reason: A reason explaining why this connection was closed.

    .. versionadded:: 3.9
    Z__reasonr   rX   r\   )r   rs   reasonc                   s   t  || || _d S rx   )r   r   _ConnectionClosedEvent__reason)r*   r   rs   r   r   r   r    r     s    zConnectionClosedEvent.__init__r   c                 C  s   | j S )zA reason explaining why this connection was closed.

        The reason must be one of the strings from the
        :class:`ConnectionClosedReason` enum.
        )r   r   r   r   r    r   #  s    zConnectionClosedEvent.reasonc                 C  s   d | jj| j| j| jS )Nz{}({!r}, {!r}, {!r}))r   r   r   r   rs   r   r   r   r   r    r   ,  s    zConnectionClosedEvent.__repr__
r   r   r   r   r   r   r   r   r   r   r   r   r   r    r>     s   
r>   c                   @  s   e Zd ZdZdZdS )r@   zPublished when the driver starts attempting to check out a connection.

    :param address: The address (host, port) pair of the server this
       Connection is attempting to connect to.

    .. versionadded:: 3.9
    r   Nr   r   r   r   r    r@   5  s   r@   c                      sP   e Zd ZdZdZddddd fdd	Zedd
ddZdd
ddZ  Z	S )rB   a!  Published when the driver's attempt to check out a connection fails.

    :param address: The address (host, port) pair of the server this
       Connection is attempting to connect to.
    :param reason: A reason explaining why connection check out failed.

    .. versionadded:: 3.9
    r   r   r\   r   r#   r   r   r   r&   c                   s   t  j|d|d || _d S )Nr   )r   rs   r   )r   r   &_ConnectionCheckOutFailedEvent__reason)r*   r   r   r   r   r   r    r   M  s    z&ConnectionCheckOutFailedEvent.__init__r   c                 C  s   | j S )zA reason explaining why connection check out failed.

        The reason must be one of the strings from the
        :class:`ConnectionCheckOutFailedReason` enum.
        )r   r   r   r   r    r   Q  s    z$ConnectionCheckOutFailedEvent.reasonc                 C  s&   | j j d| jd| jd| jdS r   )r   r   r   r   r   r   r   r   r    r   Z  s    z&ConnectionCheckOutFailedEvent.__repr__r   r   r   r   r    rB   A  s   	rB   c                   @  s   e Zd ZdZdZdS )rD   a  Published when the driver successfully checks out a connection.

    :param address: The address (host, port) pair of the server this
       Connection is attempting to connect to.
    :param connection_id: The integer ID of the Connection in this Pool.

    .. versionadded:: 3.9
    r   Nr   r   r   r   r    rD   ^  s   	rD   c                   @  s   e Zd ZdZdZdS )rF   a  Published when the driver checks in a Connection into the Pool.

    :param address: The address (host, port) pair of the server this
       Connection is attempting to connect to.
    :param connection_id: The integer ID of the Connection in this Pool.

    .. versionadded:: 3.9
    r   Nr   r   r   r   r    rF   k  s   	rF   c                   @  sX   e Zd ZdZdZddddddZedd	d
dZedd	ddZdd	ddZ	dS )_ServerEventzBase class for server events.)Z__server_address__topology_idr   r
   r#   server_addresstopology_idr&   c                 C  s   || _ || _d S rx   )_ServerEvent__server_address_ServerEvent__topology_id)r*   r   r   r   r   r    r   }  s    z_ServerEvent.__init__r   c                 C  s   | j S )z+The address (host, port) pair of the server)r   r   r   r   r    r     s    z_ServerEvent.server_addressc                 C  s   | j S z>A unique identifier for the topology this server is a part of.)r   r   r   r   r    r     s    z_ServerEvent.topology_idr\   c                 C  s    d| j j d| j d| j dS )N<  topology_id: >)r   r   r   r   r   r   r   r    r     s    z_ServerEvent.__repr__N)
r   r   r   r   r   r   r   r   r   r   r   r   r   r    r   x  s   r   c                      sb   e Zd ZdZdZddddd fddZedd	d
dZedd	ddZdd	ddZ	  Z
S )rV   zJPublished when server description changes.

    .. versionadded:: 3.3
    Z__previous_descriptionZ__new_descriptionr   r   r#   previous_descriptionnew_descriptionargsr&   c                   s   t  j|  || _|| _d S rx   )r   r   4_ServerDescriptionChangedEvent__previous_description/_ServerDescriptionChangedEvent__new_descriptionr*   r   r   r   r   r   r    r     s    z&ServerDescriptionChangedEvent.__init__r   c                 C  s   | j S )zUThe previous
        :class:`~pymongo.server_description.ServerDescription`.
        )r   r   r   r   r    r     s    z2ServerDescriptionChangedEvent.previous_descriptionc                 C  s   | j S )zPThe new
        :class:`~pymongo.server_description.ServerDescription`.
        )r   r   r   r   r    r     s    z-ServerDescriptionChangedEvent.new_descriptionr\   c                 C  s   d | jj| j| j| jS )Nz <{} {} changed from: {}, to: {}>)r   r   r   r   r   r   r   r   r   r    r     s    z&ServerDescriptionChangedEvent.__repr__r   r   r   r   r   r   r   r   r   r   r   r   r   r   r    rV     s   
rV   c                   @  s   e Zd ZdZdZdS )rU   zEPublished when server is initialized.

    .. versionadded:: 3.3
    r   Nr   r   r   r   r    rU     s   rU   c                   @  s   e Zd ZdZdZdS )rW   z@Published when server is closed.

    .. versionadded:: 3.3
    r   Nr   r   r   r   r    rW     s   rW   c                   @  sD   e Zd ZdZdZdddddZeddd	d
ZddddZdS )TopologyEventz+Base class for topology description events.)r   r
   r#   r   r&   c                 C  s
   || _ d S rx   Z_TopologyEvent__topology_id)r*   r   r   r   r    r     s    zTopologyEvent.__init__r   c                 C  s   | j S r   r   r   r   r   r    r     s    zTopologyEvent.topology_idr\   c                 C  s   d| j j d| j dS )Nr   r   r   )r   r   r   r   r   r   r    r     s    zTopologyEvent.__repr__N)	r   r   r   r   r   r   r   r   r   r   r   r   r    r     s   r   c                      sb   e Zd ZdZdZddddd fddZedd	d
dZedd	ddZdd	ddZ	  Z
S )rO   zPPublished when the topology description changes.

    .. versionadded:: 3.3
    r   r   r   r#   r   c                   s   t  j|  || _|| _d S rx   )r   r   6_TopologyDescriptionChangedEvent__previous_description1_TopologyDescriptionChangedEvent__new_descriptionr   r   r   r    r     s    z(TopologyDescriptionChangedEvent.__init__r   c                 C  s   | j S )zYThe previous
        :class:`~pymongo.topology_description.TopologyDescription`.
        )r   r   r   r   r    r     s    z4TopologyDescriptionChangedEvent.previous_descriptionc                 C  s   | j S )zTThe new
        :class:`~pymongo.topology_description.TopologyDescription`.
        )r   r   r   r   r    r     s    z/TopologyDescriptionChangedEvent.new_descriptionr\   c                 C  s   d | jj| j| j| jS )Nz-<{} topology_id: {} changed from: {}, to: {}>)r   r   r   r   r   r   r   r   r   r    r     s    z(TopologyDescriptionChangedEvent.__repr__r   r   r   r   r    rO     s   
rO   c                   @  s   e Zd ZdZdZdS )rM   zKPublished when the topology is initialized.

    .. versionadded:: 3.3
    r   Nr   r   r   r   r    rM     s   rM   c                   @  s   e Zd ZdZdZdS )rQ   zFPublished when the topology is closed.

    .. versionadded:: 3.3
    r   Nr   r   r   r   r    rQ     s   rQ   c                   @  sZ   e Zd ZdZdZddddddd	Zedd
ddZedd
ddZdd
ddZ	dS )_ServerHeartbeatEventz'Base class for server heartbeat events.)r   Z	__awaitedFr   rh   r#   rs   awaitedr&   c                 C  s   || _ || _d S rx   )$_ServerHeartbeatEvent__connection_id_ServerHeartbeatEvent__awaited)r*   rs   r   r   r   r    r     s    z_ServerHeartbeatEvent.__init__r   c                 C  s   | j S )zSThe address (host, port) of the server this heartbeat was sent
        to.
        )r   r   r   r   r    rs     s    z#_ServerHeartbeatEvent.connection_idc                 C  s   | j S )zgWhether the heartbeat was issued as an awaitable hello command.

        .. versionadded:: 4.6
        )r   r   r   r   r    r   &  s    z_ServerHeartbeatEvent.awaitedr\   c                 C  s    d| j j d| j d| j dS )Nr   r   z
 awaited: r   )r   r   rs   r   r   r   r   r    r   .  s    z_ServerHeartbeatEvent.__repr__N)F)
r   r   r   r   r   r   r   rs   r   r   r   r   r   r    r     s   r   c                   @  s   e Zd ZdZdZdS )rI   zFPublished when a heartbeat is started.

    .. versionadded:: 3.3
    r   Nr   r   r   r   r    rI   2  s   rI   c                      s|   e Zd ZdZdZddddddd	 fd
dZeddddZeddddZedd fddZ	ddddZ
  ZS )rJ   zIFired when the server heartbeat succeeds.

    .. versionadded:: 3.3
    r   r   Ffloatr   r   rh   r#   r   r   rs   r   r&   c                   s   t  || || _|| _d S rx   )r   r   (_ServerHeartbeatSucceededEvent__duration%_ServerHeartbeatSucceededEvent__replyr*   r   r   rs   r   r   r   r    r   C  s    z&ServerHeartbeatSucceededEvent.__init__r   c                 C  s   | j S z/The duration of this heartbeat in microseconds.)r   r   r   r   r    r   J  s    z&ServerHeartbeatSucceededEvent.durationc                 C  s   | j S )z-An instance of :class:`~pymongo.hello.Hello`.)r   r   r   r   r    r   O  s    z#ServerHeartbeatSucceededEvent.replyc                   s   t  jS zWhether the heartbeat was awaited.

        If true, then :meth:`duration` reflects the sum of the round trip time
        to the server and the time that the server waited before sending a
        response.

        .. versionadded:: 3.11
        r   r   r   r   r   r    r   T  s    
z%ServerHeartbeatSucceededEvent.awaitedr\   c                 C  s   d | jj| j| j| j| jS )Nz,<{} {} duration: {}, awaited: {}, reply: {}>r   r   r   rs   r   r   r   r   r   r   r    r   `  s    z&ServerHeartbeatSucceededEvent.__repr__)Fr   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r    rJ   ;  s    rJ   c                      s|   e Zd ZdZdZddddddd	 fd
dZeddddZeddddZedd fddZ	ddddZ
  ZS )rK   zxFired when the server heartbeat fails, either with an "ok: 0"
    or a socket exception.

    .. versionadded:: 3.3
    r   Fr   	Exceptionr   rh   r#   r   c                   s   t  || || _|| _d S rx   )r   r   %_ServerHeartbeatFailedEvent__duration"_ServerHeartbeatFailedEvent__replyr   r   r   r    r   s  s    z#ServerHeartbeatFailedEvent.__init__r   c                 C  s   | j S r   )r   r   r   r   r    r   z  s    z#ServerHeartbeatFailedEvent.durationc                 C  s   | j S )zA subclass of :exc:`Exception`.)r   r   r   r   r    r     s    z ServerHeartbeatFailedEvent.replyc                   s   t  jS r   r   r   r   r   r    r     s    
z"ServerHeartbeatFailedEvent.awaitedr\   c                 C  s   d | jj| j| j| j| jS )Nz.<{} {} duration: {}, awaited: {}, reply: {!r}>r   r   r   r   r    r     s    z#ServerHeartbeatFailedEvent.__repr__)Fr   r   r   r   r    rK   j  s    rK   c                   @  sb  e Zd ZdZddddZedddd	Zeddd
dZeddddZeddddZ	eddddZ
ddddZdedddddddddddZdfd"ddddddddddd#d$d%Zdgd"dddddddddd&
d'd(Zdddd)d*d+Zdd,d-ddd.d/d0Zdd,d1ddd.d2d3Zdd4dd5d6d7Zdd4dd5d8d9Zd:d:dd4dd;d<d=Zd4dd>d?d@Zd4dd>dAdBZdCdCd4ddDdEdFZddGddHdIdJZdddKdLdMZdhdddddNdOdPZdddKdQdRZddddSdTdUZddd,ddVdWdXZdddddYdZd[ZdddKd\d]Zddd,dd^d_d`Z ddd,ddVdadbZ!ddddSdcddZ"dS )i_EventListenerszConfigure event listeners for a client instance.

    Any event listeners registered globally are included by default.

    :param listeners: A list of event listeners.
    z"Optional[Sequence[_EventListener]])r^   c                 C  s  t jd d  | _t jd d  | _t j}|d d  | _t jd d  | _t j	d d  | _
|d k	r|D ]r}t|trz| j| t|tr| j| t|tr| j| t|tr| j| t|tr`| j
| q`t| j| _t| j| _t| j| _t| j| _t| j
| _d S rx   )re   r   "_EventListeners__command_listenersr   !_EventListeners__server_listenersr   +_EventListeners__server_heartbeat_listenersr   #_EventListeners__topology_listenersr   _EventListeners__cmap_listenersra   r!   rf   rT   rH   rL   r1   rh   %_EventListeners__enabled_for_commands#_EventListeners__enabled_for_server-_EventListeners__enabled_for_server_heartbeat%_EventListeners__enabled_for_topology!_EventListeners__enabled_for_cmap)r*   r^   lstr   r   r    r     s.    




z_EventListeners.__init__rh   r   c                 C  s   | j S )z-Are any CommandListener instances registered?)r  r   r   r   r    enabled_for_commands  s    z$_EventListeners.enabled_for_commandsc                 C  s   | j S )z,Are any ServerListener instances registered?)r  r   r   r   r    enabled_for_server  s    z"_EventListeners.enabled_for_serverc                 C  s   | j S )z5Are any ServerHeartbeatListener instances registered?)r  r   r   r   r    enabled_for_server_heartbeat  s    z,_EventListeners.enabled_for_server_heartbeatc                 C  s   | j S )z.Are any TopologyListener instances registered?)r  r   r   r   r    enabled_for_topology  s    z$_EventListeners.enabled_for_topologyc                 C  s   | j S )z4Are any ConnectionPoolListener instances registered?)r  r   r   r   r    enabled_for_cmap  s    z _EventListeners.enabled_for_cmapzlist[_EventListeners]c                 C  s   | j | j | j | j | j S )z#List of registered event listeners.)r   r   r   r  r  r   r   r   r    event_listeners  s    z_EventListeners.event_listenersNr   r\   rX   r   rp   rq   r#   )r   rv   rr   rs   rw   op_idru   r&   c           
   	   C  s\   |dkr|}t |||||||d}| jD ].}	z|	| W q( tk
rT   t  Y q(X q(dS )a  Publish a CommandStartedEvent to all command listeners.

        :param command: The command document.
        :param database_name: The name of the database this command was run
            against.
        :param request_id: The request id for this operation.
        :param connection_id: The address (host, port) of the server this
            command was sent to.
        :param op_id: The (optional) operation id for this operation.
        :param service_id: The service_id this command was sent to, or ``None``.
        N)ru   rw   )r"   r   r+   r   r   )
r*   r   rv   rr   rs   rw   r  ru   r%   
subscriberr   r   r    publish_command_start  s     	
z%_EventListeners.publish_command_startFro   r   )r   r   ri   rr   rs   rw   r  ru   speculative_hellorv   r&   c                 C  sh   |dkr|}|	ri }t ||||||||
|d	}| jD ].}z|| W q4 tk
r`   t  Y q4X q4dS )a  Publish a CommandSucceededEvent to all command listeners.

        :param duration: The command duration as a datetime.timedelta.
        :param reply: The server reply document.
        :param command_name: The command name.
        :param request_id: The request id for this operation.
        :param connection_id: The address (host, port) of the server this
            command was sent to.
        :param op_id: The (optional) operation id for this operation.
        :param service_id: The service_id this command was sent to, or ``None``.
        :param speculative_hello: Was the command sent with speculative auth?
        :param database_name: The database this command was sent to, or ``""``.
        N)rv   rw   )r,   r   r-   r   r   )r*   r   r   ri   rr   rs   rw   r  ru   r  rv   r%   r  r   r   r    publish_command_success  s(    
z'_EventListeners.publish_command_success)
r   r   ri   rr   rs   rw   r  ru   rv   r&   c
                 C  s`   |dkr|}t ||||||||	|d	}
| jD ].}z||
 W q, tk
rX   t  Y q,X q,dS )a  Publish a CommandFailedEvent to all command listeners.

        :param duration: The command duration as a datetime.timedelta.
        :param failure: The server reply document or failure description
            document.
        :param command_name: The command name.
        :param request_id: The request id for this operation.
        :param connection_id: The address (host, port) of the server this
            command was sent to.
        :param op_id: The (optional) operation id for this operation.
        :param service_id: The service_id this command was sent to, or ``None``.
        :param database_name: The database this command was sent to, or ``""``.
        Nr   )r.   r   r/   r   r   )r*   r   r   ri   rr   rs   rw   r  ru   rv   r%   r  r   r   r    publish_command_failure5  s$    
z'_EventListeners.publish_command_failurer   c              	   C  sD   t ||}| jD ].}z|| W q tk
r<   t  Y qX qdS )zPublish a ServerHeartbeatStartedEvent to all server heartbeat
        listeners.

        :param connection_id: The address (host, port) pair of the connection.
        :param awaited: True if this heartbeat is part of an awaitable hello command.
        N)rI   r   r+   r   r   )r*   rs   r   r%   r  r   r   r     publish_server_heartbeat_starteda  s    

z0_EventListeners.publish_server_heartbeat_startedr   r   )rs   r   r   r   r&   c              	   C  sH   t ||||}| jD ].}z|| W q tk
r@   t  Y qX qdS )a  Publish a ServerHeartbeatSucceededEvent to all server heartbeat
        listeners.

        :param connection_id: The address (host, port) pair of the connection.
        :param duration: The execution time of the event in the highest possible
            resolution for the platform.
        :param reply: The command reply.
        :param awaited: True if the response was awaited.
        N)rJ   r   r-   r   r   r*   rs   r   r   r   r%   r  r   r   r    "publish_server_heartbeat_succeededo  s    
z2_EventListeners.publish_server_heartbeat_succeededr   c              	   C  sH   t ||||}| jD ].}z|| W q tk
r@   t  Y qX qdS )a  Publish a ServerHeartbeatFailedEvent to all server heartbeat
        listeners.

        :param connection_id: The address (host, port) pair of the connection.
        :param duration: The execution time of the event in the highest possible
            resolution for the platform.
        :param reply: The command reply.
        :param awaited: True if the response was awaited.
        N)rK   r   r/   r   r   r  r   r   r    publish_server_heartbeat_failed  s    
z/_EventListeners.publish_server_heartbeat_failedr
   r   c              	   C  sD   t ||}| jD ].}z|| W q tk
r<   t  Y qX qdS )zPublish a ServerOpeningEvent to all server listeners.

        :param server_address: The address (host, port) pair of the server.
        :param topology_id: A unique identifier for the topology this server
           is a part of.
        N)rU   r   rN   r   r   r*   r   r   r%   r  r   r   r    publish_server_opened  s    

z%_EventListeners.publish_server_openedc              	   C  sD   t ||}| jD ].}z|| W q tk
r<   t  Y qX qdS )zPublish a ServerClosedEvent to all server listeners.

        :param server_address: The address (host, port) pair of the server.
        :param topology_id: A unique identifier for the topology this server
           is a part of.
        N)rW   r   rR   r   r   r  r   r   r    publish_server_closed  s    

z%_EventListeners.publish_server_closedr   )r   r   r   r   r&   c              	   C  sH   t ||||}| jD ].}z|| W q tk
r@   t  Y qX qdS )a~  Publish a ServerDescriptionChangedEvent to all server listeners.

        :param previous_description: The previous server description.
        :param server_address: The address (host, port) pair of the server.
        :param new_description: The new server description.
        :param topology_id: A unique identifier for the topology this server
           is a part of.
        N)rV   r   rP   r   r   )r*   r   r   r   r   r%   r  r   r   r    "publish_server_description_changed  s       
z2_EventListeners.publish_server_description_changedr   c              	   C  sB   t |}| jD ].}z|| W q tk
r:   t  Y qX qdS )zPublish a TopologyOpenedEvent to all topology listeners.

        :param topology_id: A unique identifier for the topology this server
           is a part of.
        N)rM   r  rN   r   r   r*   r   r%   r  r   r   r    publish_topology_opened  s    
z'_EventListeners.publish_topology_openedc              	   C  sB   t |}| jD ].}z|| W q tk
r:   t  Y qX qdS )zPublish a TopologyClosedEvent to all topology listeners.

        :param topology_id: A unique identifier for the topology this server
           is a part of.
        N)rQ   r  rR   r   r   r  r   r   r    publish_topology_closed  s    
z'_EventListeners.publish_topology_closedr   )r   r   r   r&   c              	   C  sF   t |||}| jD ].}z|| W q tk
r>   t  Y qX qdS )a:  Publish a TopologyDescriptionChangedEvent to all topology listeners.

        :param previous_description: The previous topology description.
        :param new_description: The new topology description.
        :param topology_id: A unique identifier for the topology this server
           is a part of.
        N)rO   r  rP   r   r   )r*   r   r   r   r%   r  r   r   r    $publish_topology_description_changed  s    
z4_EventListeners.publish_topology_description_changedr   r   c              	   C  sD   t ||}| jD ].}z|| W q tk
r<   t  Y qX qdS )z:Publish a :class:`PoolCreatedEvent` to all pool listeners.N)r2   r  r3   r   r   )r*   r   r   r%   r  r   r   r    publish_pool_created  s    

z$_EventListeners.publish_pool_createdr   c              	   C  sB   t |}| jD ].}z|| W q tk
r:   t  Y qX qdS )z8Publish a :class:`PoolReadyEvent` to all pool listeners.N)r4   r  r5   r   r   r*   r   r%   r  r   r   r    publish_pool_ready   s    
z"_EventListeners.publish_pool_readyr   c              	   C  sF   t |||}| jD ].}z|| W q tk
r>   t  Y qX qdS )z:Publish a :class:`PoolClearedEvent` to all pool listeners.N)r6   r  r7   r   r   )r*   r   ru   r   r%   r  r   r   r    publish_pool_cleared	  s    
z$_EventListeners.publish_pool_clearedc              	   C  sB   t |}| jD ].}z|| W q tk
r:   t  Y qX qdS )z9Publish a :class:`PoolClosedEvent` to all pool listeners.N)r8   r  r9   r   r   r"  r   r   r    publish_pool_closed  s    
z#_EventListeners.publish_pool_closedr   c              	   C  sD   t ||}| jD ].}z|| W q tk
r<   t  Y qX qdS )zWPublish a :class:`ConnectionCreatedEvent` to all connection
        listeners.
        N)r:   r  r;   r   r   r*   r   rs   r%   r  r   r   r    publish_connection_created   s    

z*_EventListeners.publish_connection_createdr   c              	   C  sF   t |||}| jD ].}z|| W q tk
r>   t  Y qX qdS )zDPublish a :class:`ConnectionReadyEvent` to all connection listeners.N)r<   r  r=   r   r   r*   r   rs   r   r%   r  r   r   r    publish_connection_ready+  s    
z(_EventListeners.publish_connection_ready)r   rs   r   r&   c              	   C  sF   t |||}| jD ].}z|| W q tk
r>   t  Y qX qdS )zVPublish a :class:`ConnectionClosedEvent` to all connection
        listeners.
        N)r>   r  r?   r   r   )r*   r   rs   r   r%   r  r   r   r    publish_connection_closed6  s    
z)_EventListeners.publish_connection_closedc              	   C  sB   t |}| jD ].}z|| W q tk
r:   t  Y qX qdS )z_Publish a :class:`ConnectionCheckOutStartedEvent` to all connection
        listeners.
        N)r@   r  rA   r   r   r"  r   r   r    $publish_connection_check_out_startedA  s    
z4_EventListeners.publish_connection_check_out_startedr   c              	   C  sF   t |||}| jD ].}z|| W q tk
r>   t  Y qX qdS )z^Publish a :class:`ConnectionCheckOutFailedEvent` to all connection
        listeners.
        N)rB   r  rC   r   r   )r*   r   r   r   r%   r  r   r   r    #publish_connection_check_out_failedL  s    
z3_EventListeners.publish_connection_check_out_failedc              	   C  sF   t |||}| jD ].}z|| W q tk
r>   t  Y qX qdS )zZPublish a :class:`ConnectionCheckedOutEvent` to all connection
        listeners.
        N)rD   r  rE   r   r   r(  r   r   r    publish_connection_checked_outY  s    
z._EventListeners.publish_connection_checked_outc              	   C  sD   t ||}| jD ].}z|| W q tk
r<   t  Y qX qdS )zYPublish a :class:`ConnectionCheckedInEvent` to all connection
        listeners.
        N)rF   r  rG   r   r   r&  r   r   r    publish_connection_checked_inf  s    

z-_EventListeners.publish_connection_checked_in)NN)NNFro   )NNro   )F)#r   r   r   r   r   r   r	  r
  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r   r!  r#  r$  r%  r'  r)  r*  r+  r,  r-  r.  r   r   r   r    r     s\     .    $9   ",	 	r   )Kr   
__future__r   datetimecollectionsr   r   typingr   r   r   r   r	   Zbson.objectidr
   Zpymongo.hellor   r   Zpymongo.helpers_sharedr   r   Zpymongo.typingsr   r   r   Zpymongo.server_descriptionr   Zpymongo.topology_descriptionr   r   re   r   r!   r1   rH   rL   rT   r[   rd   rg   rl   rm   r"   r,   r.   r   r2   r4   r6   r8   r   r   r   r   r   r:   r<   r>   r@   rB   rD   rF   r   rV   rU   rW   r   rO   rM   rQ   r   rI   rJ   rK   r   r   r   r   r    <module>   s|    /x	LCEC-#)		)			/0