o
    hV                     @  s  d Z ddlmZ ddlZddl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 ddlmZmZ erBdd	lmZ dd
lmZ dZdZdZdZdZdZe	eef Zee	eef  Zd;ddZd<ddZ d=ddZ!d>dd 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(G d-d. d.Z)e$e%e&e'e(fZ*	/d?d@d1d2Z+d3Z,G d4d5 d5Z-dAd7d8Z.G d9d: d:Z/dS )BzUtilities for choosing which member of a replica set to read from.

.. seealso:: This module is compatible with both the synchronous and asynchronous PyMongo APIs.
    )annotationsN)abc)TYPE_CHECKINGAnyMappingOptionalSequence)max_staleness_selectors)ConfigurationError) member_with_tags_server_selector#secondary_with_tags_server_selector)	Selection)TopologyDescription            )primaryZprimaryPreferredZ	secondaryZsecondaryPreferredZnearesttag_setsOptional[_TagSets]returnc                 C  st   | du r| S t | ttfstd| dt| dkr#td| d| D ]}t |tjs5td|dq%t| S )z$Validate tag sets for a MongoClient.Nz	Tag sets z invalid, must be a sequencer   z: invalid, must be None or contain at least one set of tagszTag set zg invalid, must be an instance of dict, bson.son.SON or other type that inherits from collection.Mapping)
isinstancelisttuple	TypeErrorlen
ValueErrorr   r   )r   tags r   K/var/www/html/venv/lib/python3.10/site-packages/pymongo/read_preferences.py_validate_tag_sets9   s   

r    max_stalenessr   strc                 C  s   d|  S )Nz6maxStalenessSeconds must be a positive integer, not %sr   r!   r   r   r   _invalid_max_staleness_msgP   s   r$   intc                 C  s:   | dkrdS t | tstt| | dkrtt| | S )zValidate max_staleness.r   )r   r%   r   r$   r   r#   r   r   r   _validate_max_stalenessU   s   
r'   hedgeOptional[_Hedge]c                 C  s8   | du rdS t | tstd| tjdtdd | S )zValidate hedge.Nz hedge must be a dictionary, not The read preference 'hedge' option is deprecated in PyMongo 4.12+ because hedged reads are deprecated in MongoDB version 8.0+. Support for 'hedge' will be removed in PyMongo 5.0.r   
stacklevel)r   dictr   warningswarnDeprecationWarning)r(   r   r   r   _validate_hedgec   s   
r1   c                   @  s   e Zd ZdZdZ			d6d7ddZed8ddZed8ddZed9ddZ	ed:ddZ
ed;ddZed:ddZed<dd Zed:d!d"Zd8d#d$Zd=d(d)Zd=d*d+Zd9d,d-Zd>d0d1Zd?d4d5ZdS )@_ServerModez$Base class for all read preferences.)Z__mongos_modeZ__modeZ
__tag_setsZ__max_stalenessZ__hedgeNr&   moder%   r   r   r!   r(   r)   r   Nonec                 C  s2   t | | _|| _t|| _t|| _t|| _d S N)	_MONGOS_MODES_ServerMode__mongos_mode_ServerMode__moder    _ServerMode__tag_setsr'   _ServerMode__max_stalenessr1   _ServerMode__hedge)selfr3   r   r!   r(   r   r   r   __init__x   s
   


z_ServerMode.__init__r"   c                 C  s   | j jS )z!The name of this read preference.)	__class____name__r<   r   r   r   name   s   z_ServerMode.namec                 C     | j S )z(The mongos mode of this read preference.)r7   r@   r   r   r   mongos_mode      z_ServerMode.mongos_modedict[str, Any]c                 C  sT   d| j i}| jdi gfvr| j|d< | jdkr| j|d< | jdi fvr(| j|d< |S )zRead preference as a document.r3   Nr   r&   ZmaxStalenessSecondsr(   )r7   r9   r:   r;   )r<   docr   r   r   document   s   




z_ServerMode.documentc                 C  rB   )z*The mode of this read preference instance.)r8   r@   r   r   r   r3      rD   z_ServerMode.mode_TagSetsc                 C  s   | j rt| j S i gS )aW  Set ``tag_sets`` to a list of dictionaries like [{'dc': 'ny'}] to
        read only from members whose ``dc`` tag has the value ``"ny"``.
        To specify a priority-order for tag sets, provide a list of
        tag sets: ``[{'dc': 'ny'}, {'dc': 'la'}, {}]``. A final, empty tag
        set, ``{}``, means "read from any member that matches the mode,
        ignoring tags." MongoClient tries each set of tags in turn
        until it finds a set of tags with at least one matching member.
        For example, to only send a query to an analytic node::

           Nearest(tag_sets=[{"node":"analytics"}])

        Or using :class:`SecondaryPreferred`::

           SecondaryPreferred(tag_sets=[{"node":"analytics"}])

           .. seealso:: `Data-Center Awareness
               <https://www.mongodb.com/docs/manual/data-center-awareness/>`_
        )r9   r   r@   r   r   r   r      s   z_ServerMode.tag_setsc                 C  rB   )zThe maximum estimated length of time (in seconds) a replica set
        secondary can fall behind the primary in replication before it will
        no longer be selected for operations, or -1 for no maximum.
        r:   r@   r   r   r   r!      s   z_ServerMode.max_stalenessc                 C  s    | j durtjdtdd | j S )am  **DEPRECATED** - The read preference 'hedge' option is deprecated in PyMongo 4.12+ because hedged reads are deprecated in MongoDB version 8.0+. Support for 'hedge' will be removed in PyMongo 5.0.

        The read preference ``hedge`` parameter.

        A dictionary that configures how the server will perform hedged reads.
        It consists of the following keys:

        - ``enabled``: Enables or disables hedged reads in sharded clusters.

        Hedged reads are automatically enabled in MongoDB 4.4+ when using a
        ``nearest`` read preference. To explicitly enable hedged reads, set
        the ``enabled`` key  to ``true``::

            >>> Nearest(hedge={'enabled': True})

        To explicitly disable hedged reads, set the ``enabled`` key  to
        ``False``::

            >>> Nearest(hedge={'enabled': False})

        .. versionadded:: 3.11
        Nr*   r   r+   )r;   r.   r/   r0   r@   r   r   r   r(      s   
z_ServerMode.hedgec                 C  s   | j dkrdS dS )a  The wire protocol version the server must support.

        Some read preferences impose version requirements on all servers (e.g.
        maxStalenessSeconds requires MongoDB 3.4 / maxWireVersion 5).

        All servers' maxWireVersion must be at least this read preference's
        `min_wire_version`, or the driver raises
        :exc:`~pymongo.errors.ConfigurationError`.
        r&   r      rI   r@   r   r   r   min_wire_version   s   z_ServerMode.min_wire_versionc                 C  s   d | j| j| j| jS )Nz1{}(tag_sets={!r}, max_staleness={!r}, hedge={!r}))formatrA   r9   r:   r;   r@   r   r   r   __repr__   s   z_ServerMode.__repr__otherr   boolc                 C  s>   t |tr| j|jko| j|jko| j|jko| j|jkS tS r5   )r   r2   r3   r   r!   r(   NotImplementedr<   rN   r   r   r   __eq__   s   



z_ServerMode.__eq__c                 C  s
   | |k S r5   r   rQ   r   r   r   __ne__      
z_ServerMode.__ne__c                 C  s   | j | j| j| jdS )zeReturn value of object for pickling.

        Needed explicitly because __slots__() defined.
        )r3   r   r!   r(   )r8   r9   r:   r;   r@   r   r   r   __getstate__   s
   z_ServerMode.__getstate__valueMapping[str, Any]c                 C  sD   |d | _ t| j  | _t|d | _t|d | _t|d | _dS )zRestore from pickling.r3   r   r!   r(   N)	r8   r6   r7   r    r9   r'   r:   r1   r;   )r<   rV   r   r   r   __setstate__  s
   
z_ServerMode.__setstate__	selectionr   c                 C  s   |S r5   r   r<   rY   r   r   r   __call__     z_ServerMode.__call__Nr&   N)
r3   r%   r   r   r!   r%   r(   r)   r   r4   r   r"   )r   rE   )r   r%   )r   rH   )r   r)   rN   r   r   rO   )rV   rW   r   r4   rY   r   r   r   )r?   
__module____qualname____doc__	__slots__r=   propertyrA   rC   rG   r3   r   r!   r(   rK   rM   rR   rS   rU   rX   r[   r   r   r   r   r2   s   s:    





r2   c                      sD   e Zd ZdZdZd fddZdd	d
ZdddZdddZ  Z	S )PrimaryaG  Primary read preference.

    * When directly connected to one mongod queries are allowed if the server
      is standalone or a replica set primary.
    * When connected to a mongos queries are sent to the primary of a shard.
    * When connected to a replica set queries are sent to the primary of
      the replica set.
    r   r   r4   c                   s   t  t d S r5   )superr=   _PRIMARYr@   r>   r   r   r=   $  s   zPrimary.__init__rY   r   c                 C  s   |j S z*Apply this read preference to a Selection.)primary_selectionrZ   r   r   r   r[   '     zPrimary.__call__r"   c                 C  s   dS )Nz	Primary()r   r@   r   r   r   rM   +  r\   zPrimary.__repr__rN   r   rO   c                 C  s   t |tr
|jtkS tS r5   )r   r2   r3   rh   rP   rQ   r   r   r   rR   .  s   

zPrimary.__eq__r   r4   r`   r^   r_   )
r?   ra   rb   rc   rd   r=   r[   rM   rR   __classcell__r   r   ri   r   rf     s    	

rf   c                      8   e Zd ZdZdZ			dd fddZdddZ  ZS )PrimaryPreferreda  PrimaryPreferred read preference.

    * When directly connected to one mongod queries are allowed to standalone
      servers, to a replica set primary, or to replica set secondaries.
    * When connected to a mongos queries are sent to the primary of a shard if
      available, otherwise a shard secondary.
    * When connected to a replica set queries are sent to the primary if
      available, otherwise a secondary.

    .. note:: When a :class:`~pymongo.mongo_client.MongoClient` is first
      created reads will be routed to an available secondary until the
      primary of the replica set is discovered.

    :param tag_sets: The :attr:`~tag_sets` to use if the primary is not
        available.
    :param max_staleness: (integer, in seconds) The maximum estimated
        length of time a replica set secondary can fall behind the primary in
        replication before it will no longer be selected for operations.
        Default -1, meaning no maximum. If it is set, it must be at least
        90 seconds.
    :param hedge: **DEPRECATED** - The :attr:`~hedge` for this read preference.

    .. versionchanged:: 3.11
       Added ``hedge`` parameter.
    r   Nr&   r   r   r!   r%   r(   r)   r   r4   c                      t  t||| d S r5   )rg   r=   _PRIMARY_PREFERREDr<   r   r!   r(   ri   r   r   r=   Q     zPrimaryPreferred.__init__rY   r   c                 C  s"   |j r|jS t| jt| j|S z(Apply this read preference to Selection.)r   rk   r   r   r	   selectr!   rZ   r   r   r   r[   Y  s
   zPrimaryPreferred.__call__r]   r   r   r!   r%   r(   r)   r   r4   r`   r?   ra   rb   rc   rd   r=   r[   rn   r   r   ri   r   rp   4  s    rp   c                      ro   )	Secondarya  Secondary read preference.

    * When directly connected to one mongod queries are allowed to standalone
      servers, to a replica set primary, or to replica set secondaries.
    * When connected to a mongos queries are distributed among shard
      secondaries. An error is raised if no secondaries are available.
    * When connected to a replica set queries are distributed among
      secondaries. An error is raised if no secondaries are available.

    :param tag_sets: The :attr:`~tag_sets` for this read preference.
    :param max_staleness: (integer, in seconds) The maximum estimated
        length of time a replica set secondary can fall behind the primary in
        replication before it will no longer be selected for operations.
        Default -1, meaning no maximum. If it is set, it must be at least
        90 seconds.
    :param hedge: **DEPRECATED** - The :attr:`~hedge` for this read preference.

    .. versionchanged:: 3.11
       Added ``hedge`` parameter.
    r   Nr&   r   r   r!   r%   r(   r)   r   r4   c                   rq   r5   )rg   r=   
_SECONDARYrs   ri   r   r   r=   {  rt   zSecondary.__init__rY   r   c                 C     t | jt| j|S ru   )r   r   r	   rv   r!   rZ   r   r   r   r[        zSecondary.__call__r]   rw   r`   rx   r   r   ri   r   ry   c      ry   c                      ro   )SecondaryPreferreda  SecondaryPreferred read preference.

    * When directly connected to one mongod queries are allowed to standalone
      servers, to a replica set primary, or to replica set secondaries.
    * When connected to a mongos queries are distributed among shard
      secondaries, or the shard primary if no secondary is available.
    * When connected to a replica set queries are distributed among
      secondaries, or the primary if no secondary is available.

    .. note:: When a :class:`~pymongo.mongo_client.MongoClient` is first
      created reads will be routed to the primary of the replica set until
      an available secondary is discovered.

    :param tag_sets: The :attr:`~tag_sets` for this read preference.
    :param max_staleness: (integer, in seconds) The maximum estimated
        length of time a replica set secondary can fall behind the primary in
        replication before it will no longer be selected for operations.
        Default -1, meaning no maximum. If it is set, it must be at least
        90 seconds.
    :param hedge: **DEPRECATED** - The :attr:`~hedge` for this read preference.

    .. versionchanged:: 3.11
       Added ``hedge`` parameter.
    r   Nr&   r   r   r!   r%   r(   r)   r   r4   c                   rq   r5   )rg   r=   _SECONDARY_PREFERREDrs   ri   r   r   r=     rt   zSecondaryPreferred.__init__rY   r   c                 C  s$   t | jt| j|}|r|S |jS ru   )r   r   r	   rv   r!   rk   )r<   rY   Zsecondariesr   r   r   r[     s   zSecondaryPreferred.__call__r]   rw   r`   rx   r   r   ri   r   r~     s    r~   c                      ro   )Nearestay  Nearest read preference.

    * When directly connected to one mongod queries are allowed to standalone
      servers, to a replica set primary, or to replica set secondaries.
    * When connected to a mongos queries are distributed among all members of
      a shard.
    * When connected to a replica set queries are distributed among all
      members.

    :param tag_sets: The :attr:`~tag_sets` for this read preference.
    :param max_staleness: (integer, in seconds) The maximum estimated
        length of time a replica set secondary can fall behind the primary in
        replication before it will no longer be selected for operations.
        Default -1, meaning no maximum. If it is set, it must be at least
        90 seconds.
    :param hedge: **DEPRECATED** - The :attr:`~hedge` for this read preference.

    .. versionchanged:: 3.11
       Added ``hedge`` parameter.
    r   Nr&   r   r   r!   r%   r(   r)   r   r4   c                   rq   r5   )rg   r=   _NEARESTrs   ri   r   r   r=     rt   zNearest.__init__rY   r   c                 C  r{   ru   )r   r   r	   rv   r!   rZ   r   r   r   r[     r|   zNearest.__call__r]   rw   r`   rx   r   r   ri   r   r     r}   r   c                   @  sF   e Zd ZdZdZdddZdddZdddZdddZdddZ	dS )_AggWritePrefzAgg $out/$merge write preference.

    * If there are readable servers and there is any pre-5.0 server, use
      primary read preference.
    * Otherwise use `pref` read preference.

    :param pref: The read preference to use on MongoDB 5.0+.
    )prefeffective_prefr   r2   c                 C  s   || _ tj| _d S r5   )r   ReadPreferencePRIMARYr   )r<   r   r   r   r   r=     s   z_AggWritePref.__init__topology_descriptionr   r   r4   c                 C  s6   |j }|tjr|r|dk rtj| _d S | j| _d S )N   )Zcommon_wire_versionZhas_readable_serverr   PRIMARY_PREFERREDr   r   r   )r<   r   Z	common_wvr   r   r   selection_hook  s   
z_AggWritePref.selection_hookrY   r   c                 C  s
   |  |S rj   )r   rZ   r   r   r   r[        
z_AggWritePref.__call__r"   c                 C  s   d| j dS )Nz_AggWritePref(pref=))r   r@   r   r   r   rM      s   z_AggWritePref.__repr__rA   r   c                 C  s   t | j|S r5   )getattrr   )r<   rA   r   r   r   __getattr__  s   z_AggWritePref.__getattr__N)r   r2   )r   r   r   r4   r`   r^   )rA   r"   r   r   )
r?   ra   rb   rc   rd   r=   r   r[   rM   r   r   r   r   r   r     s    	



r   r&   r3   c                 C  sB   | t kr|d i gfvrtd|dkrtdt S t|  ||S )Nz4Read preference primary cannot be combined with tagsr&   zCRead preference primary cannot be combined with maxStalenessSeconds)rh   r
   rf   _ALL_READ_PREFERENCES)r3   r   r!   r   r   r   make_read_preference  s   r   )r   r   	SECONDARYSECONDARY_PREFERREDNEARESTc                   @  s.   e Zd ZdZe Ze Ze Z	e
 Ze ZdS )r   a  An enum that defines some commonly used read preference modes.

    Apps can also create a custom read preference, for example::

       Nearest(tag_sets=[{"node":"analytics"}])

    See :doc:`/examples/high_availability` for code examples.

    A read preference is used in three cases:

    :class:`~pymongo.mongo_client.MongoClient` connected to a single mongod:

    - ``PRIMARY``: Queries are allowed if the server is standalone or a replica
      set primary.
    - All other modes allow queries to standalone servers, to a replica set
      primary, or to replica set secondaries.

    :class:`~pymongo.mongo_client.MongoClient` initialized with the
    ``replicaSet`` option:

    - ``PRIMARY``: Read from the primary. This is the default, and provides the
      strongest consistency. If no primary is available, raise
      :class:`~pymongo.errors.AutoReconnect`.

    - ``PRIMARY_PREFERRED``: Read from the primary if available, or if there is
      none, read from a secondary.

    - ``SECONDARY``: Read from a secondary. If no secondary is available,
      raise :class:`~pymongo.errors.AutoReconnect`.

    - ``SECONDARY_PREFERRED``: Read from a secondary if available, otherwise
      from the primary.

    - ``NEAREST``: Read from any member.

    :class:`~pymongo.mongo_client.MongoClient` connected to a mongos, with a
    sharded cluster of replica sets:

    - ``PRIMARY``: Read from the primary of the shard, or raise
      :class:`~pymongo.errors.OperationFailure` if there is none.
      This is the default.

    - ``PRIMARY_PREFERRED``: Read from the primary of the shard, or if there is
      none, read from a secondary of the shard.

    - ``SECONDARY``: Read from a secondary of the shard, or raise
      :class:`~pymongo.errors.OperationFailure` if there is none.

    - ``SECONDARY_PREFERRED``: Read from a secondary of the shard if available,
      otherwise from the shard primary.

    - ``NEAREST``: Read from any shard member.
    N)r?   ra   rb   rc   rf   r   rp   r   ry   r   r~   r   r   r   r   r   r   r   r   #  s    6
r   rA   c                 C  s
   t | S )z2Get the read preference mode from mongos/uri name.)r6   index)rA   r   r   r   read_pref_mode_from_namea  r   r   c                   @  sB   e Zd ZU dZded< dddZdd
dZdddZdddZdS )MovingAveragez0Tracks an exponentially-weighted moving average.Optional[float]averager   r4   c                 C  
   d | _ d S r5   r   r@   r   r   r   r=   k  rT   zMovingAverage.__init__samplefloatc                 C  sB   |dk rt d| | jd u r|| _d S d| j d|  | _d S )Nr   zduration cannot be negative g?g?)r   r   )r<   r   r   r   r   
add_samplen  s
   

zMovingAverage.add_samplec                 C  rB   )z6Get the calculated average, or None if no samples yet.r   r@   r   r   r   getx  rl   zMovingAverage.getc                 C  r   r5   r   r@   r   r   r   reset|  rT   zMovingAverage.resetNrm   )r   r   r   r4   )r   r   )	r?   ra   rb   rc   __annotations__r=   r   r   r   r   r   r   r   r   f  s   
 



r   )r   r   r   r   )r!   r   r   r"   )r!   r   r   r%   )r(   r)   r   r)   )r&   )r3   r%   r   r   r!   r%   r   r2   )rA   r"   r   r%   )0rc   
__future__r   r.   collectionsr   typingr   r   r   r   r   Zpymongor	   Zpymongo.errorsr
   Zpymongo.server_selectorsr   r   r   Zpymongo.topology_descriptionr   rh   rr   rz   r   r   r6   r"   Z_HedgerH   r    r$   r'   r1   r2   rf   rp   ry   r~   r   r   r   r   Z_MODESr   r   r   r   r   r   r   <module>   sL   



 &/'0'(	
>