
    FCfh              
         U d Z ddlmZ ddlmZ ddlmZmZmZ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 ddlmZ dd	lmZmZmZ dd
lmZ ddlmZ ddlmZ ddl m!Z!  G d de      Z" e" e#d       Z$e$jJ                  e$jL                  fZ'de(d<   eee   gee   f   Z) G d d      Z*ejV                  e$jL                  ejX                  e$jZ                  ej\                  e$j^                  ej`                  e$j^                  ejb                  e$j^                  iZ2	 	 	 	 	 	 ddZ3	 	 	 	 	 	 ddZ4	 	 	 	 	 	 	 	 	 	 	 	 ddZ5	 	 	 	 	 	 	 	 ddZ6	 	 	 	 	 	 	 	 d dZ7d!dZ8y)"z*Represent a deployment of MongoDB servers.    )annotations)sample)AnyCallableListMappingMutableMapping
NamedTupleOptionalcastMinKey)ObjectId)common)ConfigurationError)ReadPreference_AggWritePref_ServerMode)ServerDescription)	Selection)SERVER_TYPE)_Addressc                  J    e Zd ZU ded<   ded<   ded<   ded<   ded<   ded<   y)	_TopologyTypeintSingleReplicaSetNoPrimaryReplicaSetWithPrimaryShardedUnknownLoadBalancedN)__name__
__module____qualname____annotations__     \/var/www/highfloat_scraper/venv/lib/python3.12/site-packages/pymongo/topology_description.pyr   r   *   s#    KLLr'   r      ztuple[int, int]SRV_POLLING_TOPOLOGIESc                     e Zd Z	 	 	 	 	 	 	 	 	 	 	 	 	 	 ddZddZddZddZddZddZddZ	e
d d       Ze
d!d	       Ze
d"d
       Ze
d#d       Ze
d$d       Ze
d#d       Ze
d%d       Ze
d&d       Ze
d%d       Ze
d#d       Ze
d d       Ze
d d       Zd'dZ	 	 d(	 	 	 	 	 	 	 d)dZej4                  fd*dZd&dZd!dZy)+TopologyDescriptionc                N   || _         || _        || _        || _        || _        || _        d| _        | j                   t        j                  k7  r| j                          | j                  }|sd| _        yt        d |D              rd| _        yt        d |D              | _        y)a  Representation of a deployment of MongoDB servers.

        :param topology_type: initial type
        :param server_descriptions: dict of (address, ServerDescription) for
            all seeds
        :param replica_set_name: replica set name or None
        :param max_set_version: greatest setVersion seen from a primary, or None
        :param max_election_id: greatest electionId seen from a primary, or None
        :param topology_settings: a TopologySettings
        Nc              3  8   K   | ]  }|j                   d u   y wNlogical_session_timeout_minutes.0ss     r(   	<genexpr>z/TopologyDescription.__init__.<locals>.<genexpr>h   s     Uq22d:U   c              3  4   K   | ]  }|j                     y wr/   r0   r2   s     r(   r5   z/TopologyDescription.__init__.<locals>.<genexpr>k   s      +6711+   )_topology_type_replica_set_name_server_descriptions_max_set_version_max_election_id_topology_settings_incompatible_errTOPOLOGY_TYPEr!   _init_incompatible_errreadable_servers_ls_timeout_minutesanymin)selftopology_typeserver_descriptionsreplica_set_namemax_set_versionmax_election_idtopology_settingsrB   s           r(   __init__zTopologyDescription.__init__=   s    & ,!1$7! / / #4 "&-"<"<<'')  00'+D$UDTUU'+D$'* +;K+ (D$r'   c                N   | j                   j                         D ]  }|j                  s|j                  duxr |j                  t        j
                  kD  }|j                  duxr |j                  t        j                  k  }|rEd|j                  d   |j                  d   xs d|j                  t        j
                  fz  | _	        |sd|j                  d   |j                  d   xs d|j                  t        j                  t        j                  fz  | _	         y y)z>Internal compatibility check for non-load balanced topologies.Nz]Server at %s:%d requires wire version %d, but this version of PyMongo only supports up to %d.r      zgServer at %s:%d reports wire version %d, but this version of PyMongo requires at least %d (MongoDB %s).)r;   valuesis_server_type_knownmin_wire_versionr   MAX_SUPPORTED_WIRE_VERSIONmax_wire_versionMIN_SUPPORTED_WIRE_VERSIONaddressr?   MIN_SUPPORTED_SERVER_VERSION)rF   r4   server_too_newserver_too_olds       r(   rA   z*TopologyDescription._init_incompatible_erro   s1   **113 +	A)) ""$. K&&)J)JJ  ""$. K&&)J)JJ  A 		!		!)**99	 &  L 		!		!)**99;; & W+	r'   c                F    | j                   rt        | j                         y)zRaise ConfigurationError if any server is incompatible.

        A server is incompatible if its wire protocol version range does not
        overlap with PyMongo's.
        N)r?   r   rF   s    r(   check_compatiblez$TopologyDescription.check_compatible   s#     !!$T%;%;<< "r'   c                    || j                   v S r/   )r;   )rF   rV   s     r(   
has_serverzTopologyDescription.has_server   s    $3333r'   c                T    | j                   |   j                         }t        | |      S )z;A copy of this description, with one server marked Unknown.)r;   
to_unknownupdated_topology_description)rF   rV   
unknown_sds      r(   reset_serverz TopologyDescription.reset_server   s(    ..w7BBD
+D*==r'   c                6   | j                   t        j                  k(  rt        j                  }n| j                   }| j                  D ci c]  }|t        |       }}t        ||| j                  | j                  | j                  | j                        S c c}w )z<A copy of this description, with all servers marked Unknown.)r9   r@   r   r   r;   r   r,   r:   r<   r=   r>   )rF   rG   rV   sdss       r(   resetzTopologyDescription.reset   s    -"E"EE)==M //M CGB[B[\ww)'22\\"""!!!!##
 	
 ]s   	Bc                6    | j                   j                         S )z[dict of (address,
        :class:`~pymongo.server_description.ServerDescription`).
        )r;   copyr[   s    r(   rH   z'TopologyDescription.server_descriptions   s     ((--//r'   c                    | j                   S )zThe type of this topology.)r9   r[   s    r(   rG   z!TopologyDescription.topology_type   s     """r'   c                <    t         j                  | j                     S )zUThe topology type as a human readable string.

        .. versionadded:: 3.4
        )r@   _fieldsr9   r[   s    r(   topology_type_namez&TopologyDescription.topology_type_name   s     $$T%8%899r'   c                    | j                   S )zThe replica set name.)r:   r[   s    r(   rI   z$TopologyDescription.replica_set_name   s     %%%r'   c                    | j                   S )z1Greatest setVersion seen from a primary, or None.)r<   r[   s    r(   rJ   z#TopologyDescription.max_set_version        $$$r'   c                    | j                   S )z1Greatest electionId seen from a primary, or None.)r=   r[   s    r(   rK   z#TopologyDescription.max_election_id   ro   r'   c                    | j                   S )z)Minimum logical session timeout, or None.)rC   r[   s    r(   r1   z3TopologyDescription.logical_session_timeout_minutes   s     '''r'   c                v    | j                   j                         D cg c]  }|j                  s| c}S c c}w )z)List of Servers of types besides Unknown.)r;   rP   rQ   rF   r4   s     r(   known_serversz!TopologyDescription.known_servers   s/      44;;=XaAWAWXXX   66c                V    t        d | j                  j                         D              S )z7Whether there are any Servers of types besides Unknown.c              3  :   K   | ]  }|j                   s|  y wr/   )rQ   r2   s     r(   r5   z8TopologyDescription.has_known_servers.<locals>.<genexpr>   s     [ADZDZ1[s   )rD   r;   rP   r[   s    r(   has_known_serversz%TopologyDescription.has_known_servers   s$     [d77>>@[[[r'   c                v    | j                   j                         D cg c]  }|j                  s| c}S c c}w )zList of readable Servers.)r;   rP   is_readablers   s     r(   rB   z$TopologyDescription.readable_servers   s-      44;;=OaOOOru   c                X    | j                   }|rt        d | j                   D              S y)z3Minimum of all servers' max wire versions, or None.c              3  4   K   | ]  }|j                     y wr/   )rT   r2   s     r(   r5   z:TopologyDescription.common_wire_version.<locals>.<genexpr>   s     Faq))Fr8   N)rt   rE   rF   serverss     r(   common_wire_versionz'TopologyDescription.common_wire_version   s,     $$F43E3EFFFr'   c                .    | j                   j                  S r/   )r>   heartbeat_frequencyr[   s    r(   r   z'TopologyDescription.heartbeat_frequency  s    &&:::r'   c                .    | j                   j                  S r/   )r>   _srv_max_hostsr[   s    r(   srv_max_hostsz!TopologyDescription.srv_max_hosts  s    &&555r'   c                   |sg S g }|j                   D ]S  }|j                  *d|j                   d|  d|j                    }t        |      |j	                  |j                         U t        |      }| j                  j                  dz  }|j                   D cg c]$  }t        t        |j                        |z
  |k  r|& c}S c c}w )Nzround_trip_time for server z is unexpectedly None: z, servers: g     @@)
rH   round_trip_timerV   r   appendrE   r>   local_threshold_msr   float)rF   	selectionround_trip_timesserverconfig_err_msgfastest	thresholdr4   s           r(   _apply_local_thresholdz*TopologyDescription._apply_local_threshold	  s    I(*33 	<F%%-#>v~~>NNefjekkv  xA  xU  xU  wV  "W(88##F$:$:;		< &'++>>G	 22
UA--.8YF 
 	
 
s   )CNc                   t        |dd      r8| j                  }|r*||j                  k  rt        d||j                  |fz        t	        |t
              r|j                  |        | j                  t        j                  k(  rg S | j                  t        j                  t        j                  fv r| j                  S |r&| j                         j                  |      }|r|gS g S t        j                   |       }| j                  t        j"                  k7  r ||      }|#|r!|j%                   ||j                              }| j'                  |      S )a  List of servers matching the provided selector(s).

        :param selector: a callable that takes a Selection as input and returns
            a Selection as output. For example, an instance of a read
            preference from :mod:`~pymongo.read_preferences`.
        :param address: A server address to select.
        :param custom_selector: A callable that augments server
            selection rules. Accepts a list of
            :class:`~pymongo.server_description.ServerDescription` objects and
            return a list of server descriptions that should be considered
            suitable for the desired operation.

        .. versionadded:: 3.4
        rR   r   zF%s requires min wire version %d, but topology's min wire version is %d)getattrr   rR   r   
isinstancer   selection_hookrG   r@   r    r   r!   rt   rH   getr   from_topology_descriptionr   with_server_descriptionsr   )rF   selectorrV   custom_selector	common_wvdescriptionr   s          r(   apply_selectorz"TopologyDescription.apply_selector  sG   ( 8/300IY)B)BB(*-5x7P7PR[,\] 
 h.##D)!6!66IM$8$8-:T:T#UU%%%22488AK$/K=7R777=	!6!66 +I &9!::	 = =>I **955r'   c                b    t        j                  d|       t        | j                  |            S )a  Does this topology have any readable servers available matching the
        given read preference?

        :param read_preference: an instance of a read preference from
            :mod:`~pymongo.read_preferences`. Defaults to
            :attr:`~pymongo.read_preferences.ReadPreference.PRIMARY`.

        .. note:: When connected directly to a single server this method
          always returns ``True``.

        .. versionadded:: 3.4
        read_preference)r   validate_read_preferencerD   r   )rF   r   s     r(   has_readable_serverz'TopologyDescription.has_readable_serverP  s+     	''(9?K4&&788r'   c                @    | j                  t        j                        S )zDoes this topology have a writable server available?

        .. note:: When connected directly to a single server this method
          always returns ``True``.

        .. versionadded:: 3.4
        )r   r   PRIMARYr[   s    r(   has_writable_serverz'TopologyDescription.has_writable_server`  s     ''(>(>??r'   c                    t        | j                  j                         d       }dj                  | j                  j
                  | j                  j                  | j                  |      S )Nc                    | j                   S r/   )rV   )sds    r(   <lambda>z.TopologyDescription.__repr__.<locals>.<lambda>l  s
    BJJ r'   )keyz-<{} id: {}, topology_type: {}, servers: {!r}>)	sortedr;   rP   format	__class__r"   r>   _topology_idrl   r}   s     r(   __repr__zTopologyDescription.__repr__j  sY    2299;AVW>EENN####00##	
 	
r'   )rG   r   rH   !dict[_Address, ServerDescription]rI   Optional[str]rJ   Optional[int]rK   Optional[ObjectId]rL   r   returnNone)r   r   )rV   r   r   bool)rV   r   r   r,   )r   r,   )r   r   )r   r   )r   str)r   r   )r   r   )r   r   )r   list[ServerDescription])r   r   )r   zOptional[Selection]r   r   )NN)r   r   rV   zOptional[_Address]r   zOptional[_ServerSelector]r   r   )r   r   r   r   )r"   r#   r$   rM   rA   r\   r^   rc   rf   rH   propertyrG   rl   rI   rJ   rK   r1   rt   rx   rB   r   r   r   r   r   r   r   r   r   r   r&   r'   r(   r,   r,   <   s   00 ?0 (	0
 '0 ,0 0 
0d-^=4>

&0 # # : : & & % % % % ( ( Y Y \ \ P P   ; ; 6 6
* '+59	3636 $36 3	36
 
!36j BPAWAW 9 @
r'   r,   c                   |j                   }| j                  }| j                  }| j                  }| j                  }|j
                  }| j                         }|||<   |t        j                  k(  rs|I||j                  k7  r:t        dj                  ||j                              }	|j                  |	      ||<   t        t        j                  ||||| j                        S |t        j                  k(  r|t        j                   t        j"                  fv rEt%        | j                  j&                        dk(  rt        j                  }n=|j)                  |       n+|t        j                  t        j*                  fvr	t,        |   }|t        j.                  k(  r6|t        j0                  t        j                  fvr|j)                  |       nw|t        j2                  k(  r|t        j                   t        j0                  fv r|j)                  |       n/|t        j4                  k(  rt7        |||||      \  }}}}n|t        j8                  t        j:                  t        j<                  fv rt?        |||      \  }}n|t        j@                  k(  r|t        j                   t        j0                  fv r|j)                  |       tC        |      }nr|t        j4                  k(  rt7        |||||      \  }}}}nJ|t        j8                  t        j:                  t        j<                  fv rtE        |||      }ntC        |      }t        |||||| j                        S )an  Return an updated copy of a TopologyDescription.

    :param topology_description: the current TopologyDescription
    :param server_description: a new ServerDescription that resulted from
        a hello call

    Called after attempting (successfully or not) to call hello on the
    server at server_description.address. Does not modify topology_description.
    zeclient is configured to connect to a replica set named '{}' but this node belongs to a set named '{}')errorrO   )#rV   rG   rI   rJ   rK   server_typerH   r@   r   r   r   r`   r,   r>   r    r   
StandaloneLoadBalancerlenseedspopRSGhost_SERVER_TYPE_TO_TOPOLOGY_TYPEr   Mongosr   	RSPrimary_update_rs_from_primaryRSSecondary	RSArbiterRSOther!_update_rs_no_primary_from_memberr   _check_has_primary#_update_rs_with_primary_from_member)
topology_descriptionserver_descriptionrV   rG   set_namerJ   rK   r   re   r   s
             r(   ra   ra     s    !((G )66M#44H*::O*::O$00K 
2
2
4C &CL,,,H0B0S0S$S&AAG0AABE .88u8ECL"   33
 	
 ---;11;3K3KLL'::@@AQF - 4 4  !4!4k6I6I JJ9+FM---{11;3F3FGGGGG	-;;	;;11;3E3EFFGGGK111JaX1?OKG]Ho [44k6K6K[M`M`aa&GX1'#M8 
-==	=;11;3E3EFFGGG.s3MK111JaX1?OKG]Ho [44k6K6K[M`M`aa?XOabM /s3M // r'   c           	        | j                   t        v sJ | j                         }t        |j	                               t        |      k(  r| S t        |j	                               D ]  }||vs|j                  |        | j                  dk7  rmt        |      t        |j	                               z
  }| j                  t        |      z
  }|dkD  r)t        t        |      t        |t        |                  }ng }|D ]  }||vst        |      ||<    t        | j                   || j                  | j                  | j                   | j"                        S )zReturn an updated copy of a TopologyDescription.

    :param topology_description: the current TopologyDescription
    :param seedlist: a list of new seeds new ServerDescription that resulted from
        a hello call
    r   )rG   r*   rH   setkeyslistr   r   r   r   r   rE   r   r,   rI   rJ   rK   r>   )r   seedlistre   rV   	new_hostsn_to_adds         r(   )_updated_topology_description_srv_pollingr     s=     --1GGGG

2
2
4C 388:#h-'## 
# ("GGG ))Q.MC
O3	'55C@a<fY/Xs9~1NOHH 6#,W5CL6 **--,,,,// r'   c                   ||j                   }n9||j                   k7  r*| j                  |j                         t        |       |||fS |j                  |j                  dk  r|j
                  |j                  f}||f}d|vrAd|vr1||k  r,|j                         | |j                  <   t        |       |||fS |j                  }|j
                  ||j
                  |kD  r|j
                  }n|j                  |j
                  f}||f}t        d |D              }t        d |D              }||k  r,|j                         | |j                  <   t        |       |||fS |j                  }|j
                  }| j                         D ]W  }	|	j                  t        j                  u s |	j                  |j                  k7  s:|	j                         | |	j                  <    n |j                  D ]  }
|
| vst        |
      | |
<    t        |       |j                  z
  D ]  }| j                  |        t        |       |||fS )ag  Update topology description from a primary's hello response.

    Pass in a dict of ServerDescriptions, current replica set name, the
    ServerDescription we are processing, and the TopologyDescription's
    max_set_version and max_election_id if any.

    Returns (new topology type, new replica_set_name, new max_set_version,
    new max_election_id).
    N   c              3  8   K   | ]  }|
t               n|  y wr/   r   r3   is     r(   r5   z*_update_rs_from_primary.<locals>.<genexpr>>       ![1ai&(Q">![r6   c              3  8   K   | ]  }|
t               n|  y wr/   r   r   s     r(   r5   z*_update_rs_from_primary.<locals>.<genexpr>?  r   r6   )rI   r   rV   r   rT   set_versionelection_idr`   tuplerP   r   r   r   	all_hostsr   r   )re   rI   r   rJ   rK   new_election_tuplemax_election_tuplenew_election_safemax_election_safer   new_addressaddrs               r(   r   r     sp     ->>	/@@	@ 	"**+!#&(8/?ZZ**26H6Y6Y\^6^%7%C%CEWEcEc$d%4o$F))--2DGY2Y2D2O2O2Q&../)#.0@/Sbbb0<<O))5#'9'E'E'W0<<O/;;=O=[=[[,o=!![HZ![[!![HZ![[00.@.K.K.MC"**+%c*,<o^^0<<O0<<O **, 	+"7"77"4"<"<< #)"3"3"5C 	 *33 >c!0=C>
 C-777 
 s#%5XXr'   c                
   |J ||j                   k7  r&| j                  |j                         t	        |       S |j                  r4|j                  |j                  k7  r| j                  |j                         t	        |       S )zRS with known primary. Process a response from a non-primary.

    Pass in a dict of ServerDescriptions, current replica set name, and the
    ServerDescription we are processing.

    Returns new topology type.
    )rI   r   rV   mer   )re   rI   r   s      r(   r   r   b  s     '''->>>"**+
 c""	 
		#5#=#=ASAVAV#V"**+ c""r'   c                l   t         j                  }||j                  }n.||j                  k7  r| j                  |j                         ||fS |j
                  D ]  }|| vst        |      | |<    |j                  r4|j                  |j                  k7  r| j                  |j                         ||fS )zRS without known primary. Update from a non-primary's response.

    Pass in a dict of ServerDescriptions, current replica set name, and the
    ServerDescription we are processing.

    Returns (new topology type, new replica_set_name).
    )r@   r   rI   r   rV   r   r   r   )re   rI   r   rG   rV   s        r(   r   r   y  s     "55M->>	/@@	@"**+... &// 6#,W5CL6 !3!;!;?Q?T?T!T"**+***r'   c                    | j                         D ]1  }|j                  t        j                  k(  s!t        j
                  c S  t        j                  S )zCurrent topology type is ReplicaSetWithPrimary. Is primary still known?

    Pass in a dict of ServerDescriptions.

    Returns new topology type.
    )rP   r   r   r   r@   r   r   )re   r4   s     r(   r   r     sE     ZZ\ 1==K111 6661 000r'   N)r   r,   r   r   r   r,   )r   r,   r   zlist[tuple[str, Any]]r   r,   )re   +MutableMapping[_Address, ServerDescription]rI   r   r   r   rJ   r   rK   r   r   z<tuple[int, Optional[str], Optional[int], Optional[ObjectId]])re   r   rI   r   r   r   r   r   )re   r   rI   r   r   r   r   ztuple[int, Optional[str]])re   z$Mapping[_Address, ServerDescription]r   r   )9__doc__
__future__r   randomr   typingr   r   r   r   r	   r
   r   r   bson.min_keyr   bson.objectidr   pymongor   pymongo.errorsr   pymongo.read_preferencesr   r   r   pymongo.server_descriptionr   pymongo.server_selectorsr   pymongo.server_typer   pymongo.typingsr   r   ranger@   r    r   r*   r%   _ServerSelectorr,   r   r   r   r   r   r   r   r   ra   r   r   r   r   r   r&   r'   r(   <module>r      s   1 " 	 	 	   "  - O O 8 . + $J  uQx( ,9+@+@-BWBW*X  X D!234d;L6MMNv
 v
x	 --=>>]>>=<<::! e-eCTeeP(-(9N((VKY	4KY#KY *KY #	KY
 (KY BKY\#	4### *# 		#.+	4+#+ *+ 	+@1r'   