
    ]*iSt              
         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mZ dd	l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#  G d de      Z$ e$ e%d       Z&e&jN                  e&jP                  fZ)de*d<   eee   gee   f   Z+ G d d      Z,e!jZ                  e&jP                  e!j\                  e&j^                  e!j`                  e&jb                  e!jd                  e&jb                  e!jf                  e&jb                  iZ4	 	 	 	 	 	 ddZ5	 	 	 	 	 	 ddZ6	 	 	 	 	 	 	 	 	 	 	 	 ddZ7	 	 	 	 	 	 	 	 ddZ8	 	 	 	 	 	 	 	 d dZ9d!dZ:y)"zRepresent a deployment of MongoDB servers.

.. seealso:: This module is compatible with both the synchronous and asynchronous PyMongo APIs.
    )annotations)sample)AnyCallableListMappingMutableMapping
NamedTupleOptionalcastMinKey)ObjectId)common)ConfigurationErrorPyMongoError)Primary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__     V/home/alumno/antonio/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e
d"d       Zd)dZ	 d*	 	 	 d+dZ	 	 	 d,	 	 	 	 	 	 	 	 	 d-dZej8                  fd.dZd(dZd#dZy)/TopologyDescriptionc                   || _         || _        || _        || _        || _        t        | j                  j                               | _        || _        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>l   s     Uq22d:U   c              3  4   K   | ]  }|j                     y wr1   r2   r4   s     r*   r7   z/TopologyDescription.__init__.<locals>.<genexpr>o   s      +6711+   )_topology_type_replica_set_name_server_descriptions_max_set_version_max_election_idlistvalues_candidate_servers_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_settingsrG   s           r*   __init__zTopologyDescription.__init__@   s    & ,!1$7! / /"&t'@'@'G'G'I"J #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=   rA   is_server_type_knownmin_wire_versionr   MAX_SUPPORTED_WIRE_VERSIONmax_wire_versionMIN_SUPPORTED_WIRE_VERSIONaddressrD   MIN_SUPPORTED_SERVER_VERSION)rK   r6   server_too_newserver_too_olds       r*   rF   z*TopologyDescription._init_incompatible_errs   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)rD   r   rK   s    r*   check_compatiblez$TopologyDescription.check_compatible   s#     !!$T%;%;<< "r)   c                    || j                   v S r1   )r=   )rK   rZ   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)rK   rZ   
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.)r;   rE   r    r   r=   r   r.   r<   r>   r?   rC   )rK   rL   rZ   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*   rM   z'TopologyDescription.server_descriptions   s     ((--//r)   c                    | j                   S )zThe type of this topology.)r;   r_   s    r*   rL   z!TopologyDescription.topology_type   s     """r)   c                <    t         j                  | j                     S )zUThe topology type as a human readable string.

        .. versionadded:: 3.4
        )rE   _fieldsr;   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*   rN   z$TopologyDescription.replica_set_name   s     %%%r)   c                    | j                   S )z1Greatest setVersion seen from a primary, or None.)r>   r_   s    r*   rO   z#TopologyDescription.max_set_version        $$$r)   c                    | j                   S )z1Greatest electionId seen from a primary, or None.)r?   r_   s    r*   rP   z#TopologyDescription.max_election_id   rs   r)   c                    | j                   S )z)Minimum logical session timeout, or None.)rH   r_   s    r*   r3   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=   rA   rU   rK   r6   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r1   )rU   r4   s     r*   r7   z8TopologyDescription.has_known_servers.<locals>.<genexpr>   s     [ADZDZ1[s   )rI   r=   rA   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=   rA   is_readablerw   s     r*   rG   z$TopologyDescription.readable_servers   s-      44;;=OaOOOry   c                    | j                   S )z0List of Servers excluding deprioritized servers.)rB   r_   s    r*   candidate_serversz%TopologyDescription.candidate_servers   s     &&&r)   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r1   )rX   r4   s     r*   r7   z:TopologyDescription.common_wire_version.<locals>.<genexpr>  s     Faq))Fr:   N)rx   rJ   rK   serverss     r*   common_wire_versionz'TopologyDescription.common_wire_version  s,     $$F43E3EFFFr)   c                .    | j                   j                  S r1   )rC   heartbeat_frequencyr_   s    r*   r   z'TopologyDescription.heartbeat_frequency
  s    &&:::r)   c                .    | j                   j                  S r1   )rC   _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     @@)
rM   round_trip_timerZ   r   appendrJ   rC   local_threshold_msr   float)rK   	selectionround_trip_timesserverconfig_err_msgfastest	thresholdr6   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                    |s| j                   | _        y|D ch c]  }|j                   }}| j                   D cg c]  }|j                  |vr| }}|xs | j                   | _        yc c}w c c}w )zBFilter out deprioritized servers from a list of server candidates.N)rx   rB   rZ   )rK   deprioritized_serverssddeprioritized_addressesr   filtereds         r*   _filter_serversz#TopologyDescription._filter_servers$  s     %&*&8&8D#<Q&Rbrzz&R#&R #00>>)@@ H 
 '/&D$2D2DD# 'Ss
   A+A0c                   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 |r2| j                         j                  |      }|r|j                  r|gS g S | j!                  |       | j                  t        j"                  k(  rt%        |      t&        u rx| j(                  D ]0  }|j*                  t,        j.                  k(  s!|g}|r ||      }|c S  |r5|D ]0  }|j*                  t,        j.                  k(  s!|g}|r ||      }|c S  g S t1        j2                  |       }	| j                  t        j4                  k7  r: ||	      }	|	s0|r.| j!                  d       t1        j2                  |       }	 ||	      }	|#|	r!|	j7                   ||	j                              }	| j9                  |	      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
        rV   r   zF%s requires min wire version %d, but topology's min wire version is %dN)getattrr   rV   r   
isinstancer   selection_hookrL   rE   r"   r   r#   rx   rM   getrU   r   r    typer   rB   server_typer   	RSPrimaryr   from_topology_descriptionr!   with_server_descriptionsr   )
rK   selectorrZ   custom_selectorr   	common_wvdescriptionr   ri   r   s
             r*   apply_selectorz"TopologyDescription.apply_selector3  s3   * 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$/K4T4TK=\Z\\23!D!DDh[bIb-- >>[%:%::$C&-c2J %/ #B~~)>)>>!d*"1#"6C"
# I77=	!6!66 +I!6$$T*%??E	$Y/	 &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_preferencerI   r   )rK   r   s     r*   has_readable_serverz'TopologyDescription.has_readable_server  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 r1   )rZ   )r   s    r*   <lambda>z.TopologyDescription.__repr__.<locals>.<lambda>  s
    BJJ r)   )keyz-<{} id: {}, topology_type: {}, servers: {!r}>)	sortedr=   rA   format	__class__r$   rC   _topology_idrp   r   s     r*   __repr__zTopologyDescription.__repr__  sY    2299;AVW>EENN####00##	
 	
r)   )rL   r   rM   !dict[_Address, ServerDescription]rN   Optional[str]rO   Optional[int]rP   Optional[ObjectId]rQ   r   returnNone)r   r   )rZ   r   r   bool)rZ   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   r1   )r   !Optional[list[ServerDescription]]r   r   )NNN)
r   r   rZ   zOptional[_Address]r   zOptional[_ServerSelector]r   r   r   r   )r   r   r   r   ) r$   r%   r&   rR   rF   r`   rb   rg   rj   rM   propertyrL   rp   rN   rO   rP   r3   rx   r|   rG   r   r   r   r   r   r   r   r   r   r   r   r   r(   r)   r*   r.   r.   ?   s   11 ?1 (	1
 '1 ,1 1 
1f-^=4>

&0 # # : : & & % % % % ( ( Y Y \ \ P P ' '   ; ; 6 6
& JNE%FE	E$ '+59CGM6M6 $M6 3	M6
  AM6 
!M6^ 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 '{}')errorrT   )#rZ   rL   rN   rO   rP   r   rM   rE   r   r   r   rd   r.   rC   r"   r   
StandaloneLoadBalancerlenseedspopRSGhost_SERVER_TYPE_TO_TOPOLOGY_TYPEr!   Mongosr   r   _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_descriptionrZ   rL   set_namerO   rP   r   ri   r   s
             r*   re   re     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   )rL   r,   rM   setkeysr@   r   r   r   r   r   rJ   r   r.   rN   rO   rP   rC   )r   seedlistri   rZ   	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rQd|vrA||k  r<|j                  t        d| d|             | |j                  <   t        |       |||fS |j                  }|j
                  ||j
                  |kD  r|j
                  }n|j                  |j
                  f}||f}t        d |D              }t        d |D              }||k  r<|j                  t        d| d|             | |j                  <   t        |       |||fS |j                  }|j
                  }| j                         D ]a  }	|	j                  t        j                  u s |	j                  |j                  k7  s:|	j                  t        d            | |	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   z<primary marked stale due to electionId/setVersion mismatch, z is stale compared to c              3  8   K   | ]  }|
t               n|  y wr1   r   r5   is     r*   r7   z*_update_rs_from_primary.<locals>.<genexpr>t       ![1ai&(Q">![r8   c              3  8   K   | ]  }|
t               n|  y wr1   r   r   s     r*   r7   z*_update_rs_from_primary.<locals>.<genexpr>u  r   r8   z6primary marked stale due to discovery of newer primary)rN   r   rZ   r   rX   set_versionelection_idrd   r   tuplerA   r   r   r   	all_hostsr   r   )ri   rN   r   rO   rP   new_election_tuplemax_election_tuplenew_election_safemax_election_safer   new_addressaddrs               r*   r   r   F  s     ->>	/@@	@ 	"**+!#&(8/?ZZ**26H6Y6Y\^6^%7%C%CEWEcEc$d%4o$F))--2DGY2Y2D2O2O VWiVj  kA  BT  AU  V3&../
 *#.0@/Sbbb0<<O))5#'9'E'E'W0<<O/;;=O=[=[[,o=!![HZ![[!![HZ![[00.@.K.KRSeRff|  ~P  }Q  R/C"**+
 &c*,<o^^0<<O0<<O **, +"7"77"4"<"<< #)"3"3UV#C
  *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.
    )rN   r   rZ   mer   )ri   rN   r   s      r*   r   r     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).
    )rE   r   rN   r   rZ   r   r   r   )ri   rN   r   rL   rZ   s        r*   r   r     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.
    )rA   r   r   r   rE   r    r   )ri   r6   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.   )ri   +MutableMapping[_Address, ServerDescription]rN   r   r   r   rO   r   rP   r   r   z<tuple[int, Optional[str], Optional[int], Optional[ObjectId]])ri   r   rN   r   r   r   r   r   )ri   r   rN   r   r   r   r   ztuple[int, Optional[str]])ri   z$Mapping[_Address, ServerDescription]r   r   );__doc__
__future__r   randomr   typingr   r   r   r   r	   r
   r   r   bson.min_keyr   bson.objectidr   pymongor   pymongo.errorsr   r   pymongo.read_preferencesr   r   r   r   pymongo.server_descriptionr   pymongo.server_selectorsr   pymongo.server_typer   pymongo.typingsr   r   rangerE   r"   r!   r,   r'   _ServerSelectorr.   r   r   r    r   r   r   r   r   re   r   r   r   r   r   r(   r)   r*   <module>r     s   # 	 	 	   "  ; X X 8 . + $J  uQx( ,9+@+@-BWBW*X  X D!234d;L6MMNe
 e
V --=>>]>>=<<::! e-eCTeeP(-(9N((VUY	4UY#UY *UY #	UY
 (UY BUYp#	4### *# 		#.+	4+#+ *+ 	+@1r)   