U
    d                  	   @  s  U 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mZmZ ddlmZ ddlmZmZ ddl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.d/d0d1h	Z)d2e*d3< d d4d5d6d7d8Z+G d9d: d:Z,G d;d< d<e,Z-G d=d> d>e,Z.G d?d@ d@e,Z/G dAdB dBZ0G dCdD dDe0Z1G dEdF dFe0Z2G dGdH dHe0Z3G dIdJ dJe0Z4G dKdL dLZ5G dMdN dNZ6G dOdP dPZ7G dQdR dRe7Z8G dSdT dTe8Z9G dUdV dVe8Z:G dWdX dXe8Z;G dYdZ dZe7Z<G d[d\ d\e7Z=G d]d^ d^e8Z>G d_d` d`e8Z?G dadb dbZ@G dcdd dde@ZAG dedf dfe@ZBG dgdh dhe@ZCG didj djZDG dkdl dleDZEG dmdn dneDZFG dodp dpeDZGG dqdr drZHG dsdt dteHZIG dudv dveHZJG dwdx dxeHZKG dydz dzZLdS ){a  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.

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DictListMappingOptionalSequence)ObjectId)HelloHelloCompat)_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-oblwsawz/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`.
    z'CommandStartedEvent'Noneeventreturnc                 C  s   t dS )zAbstract method to handle a `CommandStartedEvent`.

        :Parameters:
          - `event`: An instance of :class:`CommandStartedEvent`.
        NNotImplementedErrorselfr%   r    r    r!   started   s    zCommandListener.startedz'CommandSucceededEvent'c                 C  s   t dS )zAbstract method to handle a `CommandSucceededEvent`.

        :Parameters:
          - `event`: An instance of :class:`CommandSucceededEvent`.
        Nr'   r)   r    r    r!   	succeeded   s    zCommandListener.succeededz'CommandFailedEvent'c                 C  s   t dS )zAbstract method to handle a `CommandFailedEvent`.

        :Parameters:
          - `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
    z'PoolCreatedEvent'r#   r$   c                 C  s   t dS )zAbstract method to handle a :class:`PoolCreatedEvent`.

        Emitted when a connection Pool is created.

        :Parameters:
          - `event`: An instance of :class:`PoolCreatedEvent`.
        Nr'   r)   r    r    r!   pool_created  s    z#ConnectionPoolListener.pool_createdz'PoolReadyEvent'c                 C  s   t dS )zAbstract method to handle a :class:`PoolReadyEvent`.

        Emitted when a connection Pool is marked ready.

        :Parameters:
          - `event`: An instance of :class:`PoolReadyEvent`.

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

        Emitted when a connection Pool is cleared.

        :Parameters:
          - `event`: An instance of :class:`PoolClearedEvent`.
        Nr'   r)   r    r    r!   pool_cleared$  s    z#ConnectionPoolListener.pool_clearedz'PoolClosedEvent'c                 C  s   t dS )zAbstract method to handle a `PoolClosedEvent`.

        Emitted when a connection Pool is closed.

        :Parameters:
          - `event`: An instance of :class:`PoolClosedEvent`.
        Nr'   r)   r    r    r!   pool_closed.  s    z"ConnectionPoolListener.pool_closedz'ConnectionCreatedEvent'c                 C  s   t dS )zAbstract method to handle a :class:`ConnectionCreatedEvent`.

        Emitted when a connection Pool creates a Connection object.

        :Parameters:
          - `event`: An instance of :class:`ConnectionCreatedEvent`.
        Nr'   r)   r    r    r!   connection_created8  s    z)ConnectionPoolListener.connection_createdz'ConnectionReadyEvent'c                 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.

        :Parameters:
          - `event`: An instance of :class:`ConnectionReadyEvent`.
        Nr'   r)   r    r    r!   connection_readyB  s    	z'ConnectionPoolListener.connection_readyz'ConnectionClosedEvent'c                 C  s   t dS )zAbstract method to handle a :class:`ConnectionClosedEvent`.

        Emitted when a connection Pool closes a connection.

        :Parameters:
          - `event`: An instance of :class:`ConnectionClosedEvent`.
        Nr'   r)   r    r    r!   connection_closedM  s    z(ConnectionPoolListener.connection_closedz 'ConnectionCheckOutStartedEvent'c                 C  s   t dS )zAbstract method to handle a :class:`ConnectionCheckOutStartedEvent`.

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

        :Parameters:
          - `event`: An instance of :class:`ConnectionCheckOutStartedEvent`.
        Nr'   r)   r    r    r!   connection_check_out_startedW  s    z3ConnectionPoolListener.connection_check_out_startedz'ConnectionCheckOutFailedEvent'c                 C  s   t dS )zAbstract method to handle a :class:`ConnectionCheckOutFailedEvent`.

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

        :Parameters:
          - `event`: An instance of :class:`ConnectionCheckOutFailedEvent`.
        Nr'   r)   r    r    r!   connection_check_out_faileda  s    z2ConnectionPoolListener.connection_check_out_failedz'ConnectionCheckedOutEvent'c                 C  s   t dS )zAbstract method to handle a :class:`ConnectionCheckedOutEvent`.

        Emitted when the driver successfully checks out a connection.

        :Parameters:
          - `event`: An instance of :class:`ConnectionCheckedOutEvent`.
        Nr'   r)   r    r    r!   connection_checked_outk  s    z-ConnectionPoolListener.connection_checked_outz'ConnectionCheckedInEvent'c                 C  s   t dS )a  Abstract method to handle a :class:`ConnectionCheckedInEvent`.

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

        :Parameters:
          - `event`: An instance of :class:`ConnectionCheckedInEvent`.
        Nr'   r)   r    r    r!   connection_checked_inu  s    	z,ConnectionPoolListener.connection_checked_inN)r   r   r   r   r0   r1   r2   r3   r4   r5   r6   r7   r8   r9   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S )ServerHeartbeatListenerzAbstract base class for server heartbeat listeners.

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

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

        :Parameters:
          - `event`: An instance of :class:`ServerHeartbeatStartedEvent`.
        Nr'   r)   r    r    r!   r+     s    zServerHeartbeatListener.startedz'ServerHeartbeatSucceededEvent'c                 C  s   t dS )zAbstract method to handle a `ServerHeartbeatSucceededEvent`.

        :Parameters:
          - `event`: An instance of :class:`ServerHeartbeatSucceededEvent`.
        Nr'   r)   r    r    r!   r,     s    z!ServerHeartbeatListener.succeededz'ServerHeartbeatFailedEvent'c                 C  s   t dS )zAbstract method to handle a `ServerHeartbeatFailedEvent`.

        :Parameters:
          - `event`: An instance of :class:`ServerHeartbeatFailedEvent`.
        Nr'   r)   r    r    r!   r-     s    zServerHeartbeatListener.failedNr.   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S )TopologyListenerzAbstract base class for topology monitoring listeners.
    Handles `TopologyOpenedEvent`, `TopologyDescriptionChangedEvent`, and
    `TopologyClosedEvent`.

    .. versionadded:: 3.3
    z'TopologyOpenedEvent'r#   r$   c                 C  s   t dS )zAbstract method to handle a `TopologyOpenedEvent`.

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

        :Parameters:
          - `event`: An instance of :class:`TopologyDescriptionChangedEvent`.
        Nr'   r)   r    r    r!   description_changed  s    z$TopologyListener.description_changedz'TopologyClosedEvent'c                 C  s   t dS )zAbstract method to handle a `TopologyClosedEvent`.

        :Parameters:
          - `event`: An instance of :class:`TopologyClosedEvent`.
        Nr'   r)   r    r    r!   closed  s    zTopologyListener.closedN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S )ServerListenerzAbstract base class for server listeners.
    Handles `ServerOpeningEvent`, `ServerDescriptionChangedEvent`, and
    `ServerClosedEvent`.

    .. versionadded:: 3.3
    z'ServerOpeningEvent'r#   r$   c                 C  s   t dS )zAbstract method to handle a `ServerOpeningEvent`.

        :Parameters:
          - `event`: An instance of :class:`ServerOpeningEvent`.
        Nr'   r)   r    r    r!   r=     s    zServerListener.openedz'ServerDescriptionChangedEvent'c                 C  s   t dS )zAbstract method to handle a `ServerDescriptionChangedEvent`.

        :Parameters:
          - `event`: An instance of :class:`ServerDescriptionChangedEvent`.
        Nr'   r)   r    r    r!   r>     s    z"ServerListener.description_changedz'ServerClosedEvent'c                 C  s   t dS )zAbstract method to handle a `ServerClosedEvent`.

        :Parameters:
          - `event`: An instance of :class:`ServerClosedEvent`.
        Nr'   r)   r    r    r!   r?     s    zServerListener.closedNr@   r    r    r    r!   rA     s   rA   r   int)durr&   c                 C  s   t |  d S )z'Convert duration 'dur' to microseconds.g    .A)rB   total_seconds)rC   r    r    r!   
_to_micros  s    rE   strzSequence[_EventListeners])option	listenersr&   c                 C  s@   t |tjst|  d|D ]}t |tstd| q|S )zValidate event listenersz must be a list or tupleListeners for {} must be either a CommandListener, ServerHeartbeatListener, ServerListener, TopologyListener, or ConnectionPoolListener.)
isinstancer   r   	TypeErrorr   format)rG   rH   listenerr    r    r!   _validate_event_listeners  s    
rN   r#   )rM   r&   c                 C  s   t | tstd| t | tr.tj|  t | trDtj	|  t | t
rZtj|  t | trptj|  t | trtj|  dS )a   Register a global event listener.

    :Parameters:
      - `listener`: A subclasses of :class:`CommandListener`,
        :class:`ServerHeartbeatListener`, :class:`ServerListener`,
        :class:`TopologyListener`, or :class:`ConnectionPoolListener`.
    rI   N)rJ   r   rK   rL   r"   
_LISTENERSr   appendr;   r   rA   r   r<   r   r/   r   )rM   r    r    r!   register  s     





rQ   ZauthenticateZ	saslstartZsaslcontinueZgetnonceZ
createuserZ
updateuserZcopydbgetnonceZcopydbsaslstartZcopydbset_SENSITIVE_COMMANDSz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)rU   rV   r    r    r!   _is_speculative_authenticate(  s    rX   c                   @  s   e Zd ZdZdZ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dS )_CommandEventzBase class for command events.)Z
__cmd_nameZ	__rqst_idZ	__conn_idZ__op_id__service_idNrF   rB   r   Optional[int]Optional[ObjectId]r#   )rU   
request_idconnection_idoperation_id
service_idr&   c                 C  s"   || _ || _|| _|| _|| _d S N)_CommandEvent__cmd_name_CommandEvent__rqst_id_CommandEvent__conn_id_CommandEvent__op_id_CommandEvent__service_id)r*   rU   r]   r^   r_   r`   r    r    r!   __init__6  s
    z_CommandEvent.__init__r&   c                 C  s   | j S )zThe command name.)rb   r*   r    r    r!   rU   D  s    z_CommandEvent.command_namec                 C  s   | j S )z"The request id for this operation.)rc   ri   r    r    r!   r]   I  s    z_CommandEvent.request_idc                 C  s   | j S )z@The address (host, port) of the server this command was sent to.)rd   ri   r    r    r!   r^   N  s    z_CommandEvent.connection_idc                 C  s   | j S )z^The service_id this command was sent to, or ``None``.

        .. versionadded:: 3.12
        )rf   ri   r    r    r!   r`   S  s    z_CommandEvent.service_idc                 C  s   | j S )z(An id for this series of events or None.)re   ri   r    r    r!   r_   [  s    z_CommandEvent.operation_id)N)r   r   r   r   	__slots__rg   propertyrU   r]   r^   r`   r_   r    r    r    r!   rY   1  s    rY   c                	      sj   e Zd ZdZdZ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 )CommandStartedEventa  Event published when a command starts.

    :Parameters:
      - `command`: The command document.
      - `database_name`: The name of the database this command was run against.
      - `request_id`: The request id for this operation.
      - `connection_id`: The address (host, port) of the server this command
        was sent to.
      - `operation_id`: An optional identifier for a series of related events.
      - `service_id`: The service_id this command was sent to, or ``None``.
    )Z__cmdZ__dbNr   rF   rB   r   r[   r\   r#   )commanddatabase_namer]   r^   r_   r`   r&   c           	        sf   |st |dtt|}t j|||||d | }|tksNt||rVi | _n|| _|| _	d S )Nz is not a valid commandr`   )

ValueErrornextitersuperrg   rW   rS   rX   _CommandStartedEvent__cmd_CommandStartedEvent__db)	r*   rm   rn   r]   r^   r_   r`   rU   cmd_name	__class__r    r!   rg   p  s    	    zCommandStartedEvent.__init__rh   c                 C  s   | j S )zThe command document.)rt   ri   r    r    r!   rm     s    zCommandStartedEvent.commandc                 C  s   | j S )z6The name of the database this command was run against.)ru   ri   r    r    r!   rn     s    z!CommandStartedEvent.database_namec                 C  s"   d | jj| j| j| j| j| jS )NzA<{} {} db: {!r}, command: {!r}, operation_id: {}, service_id: {}>)rL   rx   r   r^   rn   rU   r_   r`   ri   r    r    r!   __repr__  s    zCommandStartedEvent.__repr__)N)r   r   r   r   rj   rg   rk   rm   rn   ry   __classcell__r    r    rw   r!   rl   a  s   	  rl   c                
      sl   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ddZddddZ	  Z
S )CommandSucceededEventa  Event published when a command succeeds.

    :Parameters:
      - `duration`: The command duration as a datetime.timedelta.
      - `reply`: The server reply document.
      - `command_name`: The command name.
      - `request_id`: The request id for this operation.
      - `connection_id`: The address (host, port) of the server this command
        was sent to.
      - `operation_id`: An optional identifier for a series of related events.
      - `service_id`: The service_id this command was sent to, or ``None``.
    )__duration_micros__replyNdatetime.timedeltar   rF   rB   r   r[   r\   r#   )durationreplyrU   r]   r^   r_   r`   r&   c           	        sL   t  j|||||d t|| _| }|tks:t||rBi | _n|| _d S Nro   )rs   rg   rE   '_CommandSucceededEvent__duration_microsrW   rS   rX   _CommandSucceededEvent__reply)	r*   r   r   rU   r]   r^   r_   r`   rv   rw   r    r!   rg     s    
    
zCommandSucceededEvent.__init__rh   c                 C  s   | j S z/The duration of this operation in microseconds.)r   ri   r    r    r!   duration_micros  s    z%CommandSucceededEvent.duration_microsc                 C  s   | j S z/The server failure document for this operation.)r   ri   r    r    r!   r     s    zCommandSucceededEvent.replyc                 C  s"   d | jj| j| j| j| j| jS )NzL<{} {} command: {!r}, operation_id: {}, duration_micros: {}, service_id: {}>)rL   rx   r   r^   rU   r_   r   r`   ri   r    r    r!   ry     s    zCommandSucceededEvent.__repr__)N)r   r   r   r   rj   rg   rk   r   r   ry   rz   r    r    rw   r!   r{     s   
 "r{   c                
      sl   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ddZddddZ	  Z
S )CommandFailedEventa  Event published when a command fails.

    :Parameters:
      - `duration`: The command duration as a datetime.timedelta.
      - `failure`: The server reply document.
      - `command_name`: The command name.
      - `request_id`: The request id for this operation.
      - `connection_id`: The address (host, port) of the server this command
        was sent to.
      - `operation_id`: An optional identifier for a series of related events.
      - `service_id`: The service_id this command was sent to, or ``None``.
    )r|   Z	__failureNr~   r   rF   rB   r   r[   r\   r#   )r   failurerU   r]   r^   r_   r`   r&   c                   s*   t  j|||||d t|| _|| _d S r   )rs   rg   rE   $_CommandFailedEvent__duration_micros_CommandFailedEvent__failure)r*   r   r   rU   r]   r^   r_   r`   rw   r    r!   rg     s    
    
zCommandFailedEvent.__init__rh   c                 C  s   | j S r   )r   ri   r    r    r!   r     s    z"CommandFailedEvent.duration_microsc                 C  s   | j S r   )r   ri   r    r    r!   r     s    zCommandFailedEvent.failurec              	   C  s&   d | jj| j| j| j| j| j| jS )Nz[<{} {} command: {!r}, operation_id: {}, duration_micros: {}, failure: {!r}, service_id: {}>)	rL   rx   r   r^   rU   r_   r   r   r`   ri   r    r    r!   ry     s    zCommandFailedEvent.__repr__)N)r   r   r   r   rj   rg   rk   r   r   ry   rz   r    r    rw   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 ra   _PoolEvent__addressr*   r   r    r    r!   rg     s    z_PoolEvent.__init__rh   c                 C  s   | j S )zbThe address (host, port) pair of the server the pool is attempting
        to connect to.
        r   ri   r    r    r!   r     s    z_PoolEvent.addressrF   c                 C  s   | j j d| jdS N())rx   r   r   ri   r    r    r!   ry     s    z_PoolEvent.__repr__N	r   r   r   r   rj   rg   rk   r   ry   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 )PoolCreatedEventzPublished when a Connection Pool is created.

    :Parameters:
     - `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 ra   )rs   rg   _PoolCreatedEvent__options)r*   r   r   rw   r    r!   rg   /  s    zPoolCreatedEvent.__init__rh   c                 C  s   | j S )zCAny non-default pool options that were set on this Connection Pool.)r   ri   r    r    r!   r   3  s    zPoolCreatedEvent.optionsrF   c                 C  s   | j j d| jd| jdS Nr   z, r   )rx   r   r   r   ri   r    r    r!   ry   8  s    zPoolCreatedEvent.__repr__)
r   r   r   r   rj   rg   rk   r   ry   rz   r    r    rw   r!   r   #  s   	r   c                   @  s   e Zd ZdZdZdS )PoolReadyEventzPublished when a Connection Pool is marked ready.

    :Parameters:
     - `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   rj   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 )PoolClearedEventa  Published when a Connection Pool is cleared.

    :Parameters:
     - `address`: The address (host, port) pair of the server this Pool is
       attempting to connect to.
     - `service_id`: The service_id this command was sent to, or ``None``.

    .. versionadded:: 3.9
    )rZ   Nr   r\   r#   r   r`   r&   c                   s   t  | || _d S ra   )rs   rg   _PoolClearedEvent__service_id)r*   r   r`   rw   r    r!   rg   V  s    zPoolClearedEvent.__init__rh   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   ri   r    r    r!   r`   Z  s    zPoolClearedEvent.service_idrF   c                 C  s   | j j d| jd| jdS r   )rx   r   r   r   ri   r    r    r!   ry   d  s    zPoolClearedEvent.__repr__)N)
r   r   r   r   rj   rg   rk   r`   ry   rz   r    r    rw   r!   r   I  s   
	r   c                   @  s   e Zd ZdZdZdS )PoolClosedEventzPublished when a Connection Pool is closed.

    :Parameters:
     - `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!   r   h  s   	r   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   u  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 ra   _ConnectionEvent__addressr   r    r    r!   rg     s    z_ConnectionEvent.__init__rh   c                 C  s   | j S )ziThe address (host, port) pair of the server this connection is
        attempting to connect to.
        r   ri   r    r    r!   r     s    z_ConnectionEvent.addressrF   c                 C  s   | j j d| jdS r   )rx   r   r   ri   r    r    r!   ry     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   rB   r#   r   r^   r&   c                   s   t  | || _d S ra   )rs   rg   !_ConnectionIdEvent__connection_id)r*   r   r^   rw   r    r!   rg     s    z_ConnectionIdEvent.__init__rh   c                 C  s   | j S )zThe ID of the connection.)r   ri   r    r    r!   r^     s    z _ConnectionIdEvent.connection_idrF   c                 C  s   | j j d| jd| jdS r   )rx   r   r   r   ri   r    r    r!   ry     s    z_ConnectionIdEvent.__repr__)
r   r   r   r   rj   rg   rk   r^   ry   rz   r    r    rw   r!   r     s   r   c                   @  s   e Zd ZdZdZdS )ConnectionCreatedEventa  Published when a Connection Pool creates a Connection object.

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

    :Parameters:
     - `address`: The address (host, port) pair of the server this
       Connection is attempting to connect to.
     - `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 )ConnectionReadyEventa3  Published when a Connection has finished its setup, and is ready to use.

    :Parameters:
     - `address`: The address (host, port) pair of the server this
       Connection is attempting to connect to.
     - `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 )ConnectionClosedEventaV  Published when a Connection is closed.

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

    .. versionadded:: 3.9
    Z__reasonr   rB   rF   )r   r^   reasonc                   s   t  || || _d S ra   )rs   rg   _ConnectionClosedEvent__reason)r*   r   r^   r   rw   r    r!   rg     s    zConnectionClosedEvent.__init__rh   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   ri   r    r    r!   r     s    zConnectionClosedEvent.reasonc                 C  s   d | jj| j| j| jS )Nz{}({!r}, {!r}, {!r}))rL   rx   r   r   r^   r   ri   r    r    r!   ry     s    zConnectionClosedEvent.__repr__
r   r   r   r   rj   rg   rk   r   ry   rz   r    r    rw   r!   r     s   r   c                   @  s   e Zd ZdZdZdS )ConnectionCheckOutStartedEventzPublished when the driver starts attempting to check out a connection.

    :Parameters:
     - `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     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 )ConnectionCheckOutFailedEventa.  Published when the driver's attempt to check out a connection fails.

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

    .. versionadded:: 3.9
    r   r   rF   r#   r   r   r&   c                   s   t  | || _d S ra   )rs   rg   &_ConnectionCheckOutFailedEvent__reason)r*   r   r   rw   r    r!   rg     s    z&ConnectionCheckOutFailedEvent.__init__rh   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   ri   r    r    r!   r   #  s    z$ConnectionCheckOutFailedEvent.reasonc                 C  s   | j j d| jd| jdS r   )rx   r   r   r   ri   r    r    r!   ry   ,  s    z&ConnectionCheckOutFailedEvent.__repr__r   r    r    rw   r!   r     s   
r   c                   @  s   e Zd ZdZdZdS )ConnectionCheckedOutEventa*  Published when the driver successfully checks out a connection.

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

    .. versionadded:: 3.9
    r    Nr   r    r    r    r!   r   0  s   
r   c                   @  s   e Zd ZdZdZdS )ConnectionCheckedInEventa*  Published when the driver checks in a Connection into the Pool.

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

    .. versionadded:: 3.9
    r    Nr   r    r    r    r!   r   >  s   
r   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 ra   )_ServerEvent__server_address_ServerEvent__topology_id)r*   r   r   r    r    r!   rg   Q  s    z_ServerEvent.__init__rh   c                 C  s   | j S )z+The address (host, port) pair of the server)r   ri   r    r    r!   r   U  s    z_ServerEvent.server_addressc                 C  s   | j S z>A unique identifier for the topology this server is a part of.)r   ri   r    r    r!   r   Z  s    z_ServerEvent.topology_idrF   c                 C  s   d | jj| j| jS )Nz<{} {} topology_id: {}>)rL   rx   r   r   r   ri   r    r    r!   ry   _  s
    z_ServerEvent.__repr__N)
r   r   r   r   rj   rg   rk   r   r   ry   r    r    r    r!   r   L  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 )ServerDescriptionChangedEventzJPublished 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 ra   )rs   rg   4_ServerDescriptionChangedEvent__previous_description/_ServerDescriptionChangedEvent__new_descriptionr*   r   r   r   rw   r    r!   rg   o  s    z&ServerDescriptionChangedEvent.__init__rh   c                 C  s   | j S )zUThe previous
        :class:`~pymongo.server_description.ServerDescription`.
        )r   ri   r    r    r!   r   y  s    z2ServerDescriptionChangedEvent.previous_descriptionc                 C  s   | j S )zPThe new
        :class:`~pymongo.server_description.ServerDescription`.
        )r   ri   r    r    r!   r     s    z-ServerDescriptionChangedEvent.new_descriptionrF   c                 C  s   d | jj| j| j| jS )Nz <{} {} changed from: {}, to: {}>)rL   rx   r   r   r   r   ri   r    r    r!   ry     s    z&ServerDescriptionChangedEvent.__repr__r   r   r   r   rj   rg   rk   r   r   ry   rz   r    r    rw   r!   r   g  s   
r   c                   @  s   e Zd ZdZdZdS )ServerOpeningEventzEPublished when server is initialized.

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

    .. versionadded:: 3.3
    r    Nr   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 )TopologyEventz+Base class for topology description events.r   r   r#   r   r&   c                 C  s
   || _ d S ra   Z_TopologyEvent__topology_id)r*   r   r    r    r!   rg     s    zTopologyEvent.__init__rh   c                 C  s   | j S r   r   ri   r    r    r!   r     s    zTopologyEvent.topology_idrF   c                 C  s   d| j j d| j dS )N<z topology_id: >)rx   r   r   ri   r    r    r!   ry     s    zTopologyEvent.__repr__N)	r   r   r   r   rj   rg   rk   r   ry   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 )TopologyDescriptionChangedEventzPPublished when the topology description changes.

    .. versionadded:: 3.3
    r   r   r   r#   r   c                   s   t  j|  || _|| _d S ra   )rs   rg   6_TopologyDescriptionChangedEvent__previous_description1_TopologyDescriptionChangedEvent__new_descriptionr   rw   r    r!   rg     s    z(TopologyDescriptionChangedEvent.__init__rh   c                 C  s   | j S )zYThe previous
        :class:`~pymongo.topology_description.TopologyDescription`.
        )r   ri   r    r    r!   r     s    z4TopologyDescriptionChangedEvent.previous_descriptionc                 C  s   | j S )zTThe new
        :class:`~pymongo.topology_description.TopologyDescription`.
        )r   ri   r    r    r!   r     s    z/TopologyDescriptionChangedEvent.new_descriptionrF   c                 C  s   d | jj| j| j| jS )Nz-<{} topology_id: {} changed from: {}, to: {}>)rL   rx   r   r   r   r   ri   r    r    r!   ry     s    z(TopologyDescriptionChangedEvent.__repr__r   r    r    rw   r!   r     s   
r   c                   @  s   e Zd ZdZdZdS )TopologyOpenedEventzKPublished when the topology is initialized.

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

    .. versionadded:: 3.3
    r    Nr   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 )_ServerHeartbeatEventz'Base class for server heartbeat events.r   r   r#   r^   r&   c                 C  s
   || _ d S ra   Z$_ServerHeartbeatEvent__connection_id)r*   r^   r    r    r!   rg     s    z_ServerHeartbeatEvent.__init__rh   c                 C  s   | j S )zSThe address (host, port) of the server this heartbeat was sent
        to.
        r   ri   r    r    r!   r^     s    z#_ServerHeartbeatEvent.connection_idrF   c                 C  s   d| j j d| j dS )Nr    r   )rx   r   r^   ri   r    r    r!   ry     s    z_ServerHeartbeatEvent.__repr__N)	r   r   r   r   rj   rg   rk   r^   ry   r    r    r    r!   r     s   r   c                   @  s   e Zd ZdZdZdS )ServerHeartbeatStartedEventzFPublished when a heartbeat is started.

    .. versionadded:: 3.3
    r    Nr   r    r    r    r!   r     s   r   c                      sx   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ddZ	ddddZ
  ZS )ServerHeartbeatSucceededEventzIFired when the server heartbeat succeeds.

    .. versionadded:: 3.3
    Z
__durationr}   Z	__awaitedFfloatr   r   rT   r#   r   r   r^   awaitedr&   c                   s"   t  | || _|| _|| _d S ra   )rs   rg   (_ServerHeartbeatSucceededEvent__duration%_ServerHeartbeatSucceededEvent__reply'_ServerHeartbeatSucceededEvent__awaitedr*   r   r   r^   r   rw   r    r!   rg     s    z&ServerHeartbeatSucceededEvent.__init__rh   c                 C  s   | j S z/The duration of this heartbeat in microseconds.)r   ri   r    r    r!   r     s    z&ServerHeartbeatSucceededEvent.durationc                 C  s   | j S )z-An instance of :class:`~pymongo.hello.Hello`.)r   ri   r    r    r!   r     s    z#ServerHeartbeatSucceededEvent.replyc                 C  s   | 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.
        )r   ri   r    r    r!   r   $  s    z%ServerHeartbeatSucceededEvent.awaitedrF   c                 C  s   d | jj| j| j| j| jS )Nz,<{} {} duration: {}, awaited: {}, reply: {}>rL   rx   r   r^   r   r   r   ri   r    r    r!   ry   .  s    z&ServerHeartbeatSucceededEvent.__repr__)Fr   r   r   r   rj   rg   rk   r   r   r   ry   rz   r    r    rw   r!   r   
  s    	r   c                      sx   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ddZ	ddddZ
  ZS )ServerHeartbeatFailedEventzxFired when the server heartbeat fails, either with an "ok: 0"
    or a socket exception.

    .. versionadded:: 3.3
    r   Fr   	Exceptionr   rT   r#   r   c                   s"   t  | || _|| _|| _d S ra   )rs   rg   %_ServerHeartbeatFailedEvent__duration"_ServerHeartbeatFailedEvent__reply$_ServerHeartbeatFailedEvent__awaitedr   rw   r    r!   rg   A  s    z#ServerHeartbeatFailedEvent.__init__rh   c                 C  s   | j S r   )r   ri   r    r    r!   r   I  s    z#ServerHeartbeatFailedEvent.durationc                 C  s   | j S )zA subclass of :exc:`Exception`.)r   ri   r    r    r!   r   N  s    z ServerHeartbeatFailedEvent.replyc                 C  s   | j S r   )r   ri   r    r    r!   r   S  s    z"ServerHeartbeatFailedEvent.awaitedrF   c                 C  s   d | jj| j| j| j| jS )Nz.<{} {} duration: {}, awaited: {}, reply: {!r}>r   ri   r    r    r!   ry   ]  s    z#ServerHeartbeatFailedEvent.__repr__)Fr   r    r    rw   r!   r   8  s    	r   c                   @  sL  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dcddddddddddZddd!ddddddddd"	d#d$Zded!dddddddd%d&d'Zddd(d)d*Zdd+d,ddd-d.d/Zdd+d0ddd-d1d2Zdd3dd4d5d6Zdd3dd4d7d8Zd9d9dd3dd:d;d<Zd3dd=d>d?Zd3dd=d@dAZdBdBd3ddCdDdEZddFddGdHdIZdddJdKdLZddddMdNdOZdddJdPdQZddddRdSdTZddddRdUdVZdddddWdXdYZdddJdZd[Zdddd\d]d^Z ddddRd_d`Z!ddddRdadbZ"dS )f_EventListenerszConfigure event listeners for a client instance.

    Any event listeners registered globally are included by default.

    :Parameters:
      - `listeners`: A list of event listeners.
    z"Optional[Sequence[_EventListener]])rH   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 ra   )rO   r   "_EventListeners__command_listenersr   !_EventListeners__server_listenersr   +_EventListeners__server_heartbeat_listenersr   #_EventListeners__topology_listenersr   _EventListeners__cmap_listenersrJ   r"   rP   rA   r;   r<   r/   rT   %_EventListeners__enabled_for_commands#_EventListeners__enabled_for_server-_EventListeners__enabled_for_server_heartbeat%_EventListeners__enabled_for_topology!_EventListeners__enabled_for_cmap)r*   rH   lstr    r    r!   rg   p  s.    




z_EventListeners.__init__rT   rh   c                 C  s   | j S )z-Are any CommandListener instances registered?)r   ri   r    r    r!   enabled_for_commands  s    z$_EventListeners.enabled_for_commandsc                 C  s   | j S )z,Are any ServerListener instances registered?)r   ri   r    r    r!   enabled_for_server  s    z"_EventListeners.enabled_for_serverc                 C  s   | j S )z5Are any ServerHeartbeatListener instances registered?)r   ri   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   ri   r    r    r!   enabled_for_topology  s    z$_EventListeners.enabled_for_topologyc                 C  s   | j S )z4Are any ConnectionPoolListener instances registered?)r   ri   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   ri   r    r    r!   event_listeners  s    z_EventListeners.event_listenersNr   rF   rB   r   r[   r\   r#   )rm   rn   r]   r^   op_idr`   r&   c           	   	   C  sZ   |dkr|}t ||||||d}| jD ].}z|| W q& tk
rR   t  Y q&X q&dS )a  Publish a CommandStartedEvent to all command listeners.

        :Parameters:
          - `command`: The command document.
          - `database_name`: The name of the database this command was run
            against.
          - `request_id`: The request id for this operation.
          - `connection_id`: The address (host, port) of the server this
            command was sent to.
          - `op_id`: The (optional) operation id for this operation.
          - `service_id`: The service_id this command was sent to, or ``None``.
        Nro   )rl   r   r+   r   r   )	r*   rm   rn   r]   r^   r  r`   r%   
subscriberr    r    r!   publish_command_start  s         
z%_EventListeners.publish_command_startFr   )	r   r   rU   r]   r^   r  r`   speculative_hellor&   c	              	   C  sb   |dkr|}|ri }t |||||||}	| jD ].}
z|
|	 W q. tk
rZ   t  Y q.X q.dS )a  Publish a CommandSucceededEvent to all command listeners.

        :Parameters:
          - `duration`: The command duration as a datetime.timedelta.
          - `reply`: The server reply document.
          - `command_name`: The command name.
          - `request_id`: The request id for this operation.
          - `connection_id`: The address (host, port) of the server this
            command was sent to.
          - `op_id`: The (optional) operation id for this operation.
          - `service_id`: The service_id this command was sent to, or ``None``.
          - `speculative_hello`: Was the command sent with speculative auth?
        N)r{   r   r,   r   r   )r*   r   r   rU   r]   r^   r  r`   r	  r%   r  r    r    r!   publish_command_success  s$          
z'_EventListeners.publish_command_success)r   r   rU   r]   r^   r  r`   r&   c           
   	   C  s\   |dkr|}t |||||||d}| jD ].}	z|	| W q( tk
rT   t  Y q(X q(dS )ac  Publish a CommandFailedEvent to all command listeners.

        :Parameters:
          - `duration`: The command duration as a datetime.timedelta.
          - `failure`: The server reply document or failure description
            document.
          - `command_name`: The command name.
          - `request_id`: The request id for this operation.
          - `connection_id`: The address (host, port) of the server this
            command was sent to.
          - `op_id`: The (optional) operation id for this operation.
          - `service_id`: The service_id this command was sent to, or ``None``.
        Nro   )r   r   r-   r   r   )
r*   r   r   rU   r]   r^   r  r`   r%   r  r    r    r!   publish_command_failure  s           
z'_EventListeners.publish_command_failurer   c              	   C  sB   t |}| jD ].}z|| W q tk
r:   t  Y qX qdS )zPublish a ServerHeartbeatStartedEvent to all server heartbeat
        listeners.

        :Parameters:
         - `connection_id`: The address (host, port) pair of the connection.
        N)r   r   r+   r   r   )r*   r^   r%   r  r    r    r!    publish_server_heartbeat_started  s    
z0_EventListeners.publish_server_heartbeat_startedr   r   )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 ServerHeartbeatSucceededEvent to all server heartbeat
        listeners.

        :Parameters:
         - `connection_id`: The address (host, port) pair of the connection.
         - `duration`: The execution time of the event in the highest possible
            resolution for the platform.
         - `reply`: The command reply.
         - `awaited`: True if the response was awaited.
        N)r   r   r,   r   r   r*   r^   r   r   r   r%   r  r    r    r!   "publish_server_heartbeat_succeeded#  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.

        :Parameters:
         - `connection_id`: The address (host, port) pair of the connection.
         - `duration`: The execution time of the event in the highest possible
            resolution for the platform.
         - `reply`: The command reply.
         - `awaited`: True if the response was awaited.
        N)r   r   r-   r   r   r  r    r    r!   publish_server_heartbeat_failed7  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 )a  Publish a ServerOpeningEvent to all server listeners.

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

        :Parameters:
         - `server_address`: The address (host, port) pair of the server.
         - `topology_id`: A unique identifier for the topology this server
           is a part of.
        N)r   r   r?   r   r   r  r    r    r!   publish_server_closedZ  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.

        :Parameters:
         - `previous_description`: The previous server description.
         - `server_address`: The address (host, port) pair of the server.
         - `new_description`: The new server description.
         - `topology_id`: A unique identifier for the topology this server
           is a part of.
        N)r   r   r>   r   r   )r*   r   r   r   r   r%   r  r    r    r!   "publish_server_description_changedi  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.

        :Parameters:
         - `topology_id`: A unique identifier for the topology this server
           is a part of.
        N)r   r   r=   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.

        :Parameters:
         - `topology_id`: A unique identifier for the topology this server
           is a part of.
        N)r   r   r?   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 )aI  Publish a TopologyDescriptionChangedEvent to all topology listeners.

        :Parameters:
         - `previous_description`: The previous topology description.
         - `new_description`: The new topology description.
         - `topology_id`: A unique identifier for the topology this server
           is a part of.
        N)r   r   r>   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)r   r   r0   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)r   r   r1   r   r   r*   r   r%   r  r    r    r!   publish_pool_ready  s    
z"_EventListeners.publish_pool_readyr   c              	   C  sD   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)r   r   r2   r   r   )r*   r   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)r   r   r3   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   r4   r   r   r*   r   r^   r%   r  r    r    r!   publish_connection_created  s    

z*_EventListeners.publish_connection_createdc              	   C  sD   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   r5   r   r   r  r    r    r!   publish_connection_ready  s    

z(_EventListeners.publish_connection_ready)r   r^   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   r6   r   r   )r*   r   r^   r   r%   r  r    r    r!   publish_connection_closed  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   r7   r   r   r  r    r    r!   $publish_connection_check_out_started  s    
z4_EventListeners.publish_connection_check_out_startedr   c              	   C  sD   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)r   r   r8   r   r   )r*   r   r   r%   r  r    r    r!   #publish_connection_check_out_failed  s    

z3_EventListeners.publish_connection_check_out_failedc              	   C  sD   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)r   r   r9   r   r   r  r    r    r!   publish_connection_checked_out  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)r   r   r:   r   r   r  r    r    r!   publish_connection_checked_in  s    

z-_EventListeners.publish_connection_checked_in)NN)NNF)NN)#r   r   r   r   rg   rk   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   g  sV     '    .  "					r   )Mr   
__future__r   datetimecollectionsr   r   typingr   r   r   r   r	   r
   r   Zbson.objectidr   Zpymongo.hellor   r   Zpymongo.helpersr   Zpymongo.typingsr   r   r   Zpymongo.server_descriptionr   Zpymongo.topology_descriptionr   r   rO   r   r"   r/   r;   r<   rA   rE   rN   rQ   rS   __annotations__rX   rY   rl   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!   <module>   s    ,$  "!!	0;;9$)		)			./