
    Ii^                       S r SSKJr  SSKrSSKrSSKrSSKJrJrJ	r	J
r
JrJrJrJr  SSKJr  SSKJr  SSKJrJrJrJrJr  SSKJrJr  SS	KJrJr  SS
KJ r   \(       a  SSK!J"r"  Sr#\$" \#5      r%Sr&\$" \&5      r'Sr(S&S jr)S'S jr*      S(S jr+\(4S)S jjr,1 Skr-S*S jr.S+S jr/S+S jr0S+S jr1S,S-S jjr2 S.         S/S jjr3\(4S0S jjr4\Rj                  " S\Rl                  " S5      -   S-   5      r7\8" / S Q5      r9S1S! jr:\(SSSSSS4                 S2S" jjr;S3S# jr<\=S$:X  a=  SSK>r> \>R|                  " \;" \R~                  S%   5      5        \R                  " S5        gg! \ a  r@\A" \@5         Sr@C@N'Sr@C@ff = f)4zTools to parse and validate a MongoDB URI.

.. seealso:: This module is compatible with both the synchronous and asynchronous PyMongo APIs.
    )annotationsN)TYPE_CHECKINGAnyMappingMutableMappingOptionalSizedUnioncast)unquote_plus)_parse_ssl_options)INTERNAL_URI_OPTION_NAME_MAPSRV_SERVICE_NAMEURI_OPTIONS_DEPRECATION_MAP_CaseInsensitiveDictionaryget_validated_options)ConfigurationError
InvalidURI)_have_dnspython_SrvResolver)_Address)
SSLContextz
mongodb://zmongodb+srv://ii  c                ~    [        [        U 5      5       H%  nX   S:X  d  M  XUS-    n[        U5      U:X  d  M%    g   g)zCheck for unescaped percent signs.

:param s: A string. `s` can have things like '%25', '%2525',
       and '%E2%85%A8' but cannot have unquoted percent like '%foo'.
%   TF)rangelenr   )sisubs      8/venv/lib/python3.13/site-packages/pymongo/uri_parser.py_unquoted_percentr"   ;   sC     3q6]43;A,C C C'      c                    SU ;   d%  U R                  S5      S:  d  [        U 5      (       a  [        S5      eU R                  S5      u  pnU(       d  [        S5      e[	        U5      [	        U5      4$ )aB  Validates the format of user information in a MongoDB URI.
Reserved characters that are gen-delimiters (":", "/", "?", "#", "[",
"]", "@") as per RFC 3986 must be escaped.

Returns a 2-tuple containing the unescaped username followed
by the unescaped password.

:param userinfo: A string of the form <username>:<password>
@:   zXUsername and password must be escaped according to RFC 3986, use urllib.parse.quote_plusz'The empty string is not valid username.)countr"   r   	partitionr   )userinfouser_passwds       r!   parse_userinfor.   K   sr     h(..-15Fx5P5P4
 	

 ((-ODVBCC|F333r#   c                    U R                  S5      S:X  a  [        S5      eU R                  S5      nUS:X  a  U SS U4$ U SU XS-   S 4$ )a  Validates an IPv6 literal host:port string.

Returns a 2-tuple of IPv6 literal followed by port where
port is default_port if it wasn't specified in entity.

:param entity: A string that represents an IPv6 literal enclosed
                in braces (e.g. '[::1]' or '[::1]:27017').
:param default_port: The port number to use when one wasn't
                      specified in entity.
]zNan IPv6 address literal must be enclosed in '[' and ']' according to RFC 2732.z]:r'      N)find
ValueError)entitydefault_portr   s      r!   parse_ipv6_literal_hostr7   c   sf     {{32\
 	
 	DABwa|\))!A;1uw''r#   c                z   U nUnU S   S:X  a  [        X5      u  p#ObU R                  S5      (       a  X4$ U R                  S5      S:w  a4  U R                  S5      S:  a  [	        S5      eUR                  SS5      u  p#[        U[        5      (       a  UR                  5       (       dO  [        S U 5       5      (       a-  U H'  nUR                  5       (       d  M  [	        S	U< 35      e   [	        S
5      e[        U5      S:  d  [        U5      S::  a  [	        S5      e[        U5      nUR                  5       U4$ )aU  Validates a host string

Returns a 2-tuple of host followed by port where port is default_port
if it wasn't specified in the string.

:param entity: A host or host:port string where host could be a
                hostname or IP address.
:param default_port: The port number to use when one wasn't
                      specified in entity.
r   [.sockr&   r1   r'   zReserved characters such as ':' must be escaped according RFC 2396. An IPv6 address literal must be enclosed in '[' and ']' according to RFC 2732.c              3  n   #    U  H+  oR                  5       =(       d    UR                  5       v   M-     g 7f)N)isspaceisdigit).0cs     r!   	<genexpr>parse_host.<locals>.<genexpr>   s"     <t!99;-!))+-ts   35z$Port contains whitespace character: zPort contains non-digit characters. Hint: username and password must be escaped according to RFC 3986, use urllib.parse.quote_plusi  z+Port must be an integer between 0 and 65535)r7   endswithr3   r(   r4   split
isinstancestrr=   allr<   intlower)r5   r6   hostportr?   s        r!   
parse_hostrK   z   s.    D&2DayC,VB
d		!	!##	S	R	<<q 1  ZZQ'
$||~~<t<<<Ayy{{(+OPQu)UVV  8  t9uD	QJKK4y ::<r#   >   tlsallowinvalidhostnamestlsallowinvalidcertificatestlsdisableocspendpointcheckc                f   [        5       nU R                  U5       H  nUR                  S5      u  pEUR                  5       S:X  a#  UR                  U/ 5      R	                  U5        MM  XB;   a  [
        R                  " SU S3SS9  UR                  5       S:X  a  UnO[        U5      nXbU'   M     U$ )zHelper method for split_options which creates the options dict.
Also handles the creation of a list for the URI tag_sets/
readpreferencetags portion, and the use of a unicode options string.
=readpreferencetagszDuplicate URI option 'z'.r2   
stacklevelauthmechanismproperties)r   rC   rH   
setdefaultappendwarningswarnr   )optsdelimoptionsurioptkeyvaluevals          r!   _parse_optionsr`      s    
 )*G**U#\\#&
99;..sB'..u5~ 6se2>1Myy{77"5)CL $ Nr#   c                   U R                  S5      nUbA  [         H7  nX ;   d  M
  Sn[        X0R                  S5      U R                  U5      4-  5      e   U R                  S5      nUb1  SU ;   a!  Sn[        USU R                  S5      4-  5      eUSL a  SU S'   U R                  S5      nUb-  S H'  nU R                  U5      SL d  M  Sn[        X24-  5      e   S	U ;   aj  S
U ;   ad  SS jnU" U R                  S	5      5      U" U R                  S
5      5      :w  a/  Sn[        X0R                  S	5      U R                  S
5      4-  5      eU $ )zRaise appropriate errors when conflicting TLS options are present in
the options dictionary.

:param options: Instance of _CaseInsensitiveDictionary containing
      MongoDB URI options.
tlsinsecurez9URI options %s and %s cannot be specified simultaneously.rM   rN   T
tlscrlfile)rb   rM   rN   zDURI option %s=True cannot be specified when CRL checking is enabled.ssltlsc                J    U S;   a  U S:H  $ [        U [        5      (       a  U $ U $ )N)truefalserg   )rD   bool)r_   s    r!   truth_value-_handle_security_options.<locals>.truth_value   s,    ''f}$#t$$
Jr#   z=Can not specify conflicting values for URI options %s and %s.)r_   r   returnr   )get_IMPLICIT_TLSINSECURE_OPTSr   	cased_key)r[   rb   opterr_msgtlsallowinvalidcertsrc   rj   s          r!   _handle_security_optionsrs      sv    ++m,K-C~U 00?ARARSVAWXX  . #;;'DE'(G3QG0'2C2CDa2bcd   4'59G12 \*J`C{{34'` 6!122 a
 EW,	 w{{5)*k'++e:L.MMUGW(9(9%(@'BSBSTYBZ'[[\\Nr#   c                   [        U 5       H  nU[        ;   d  M  [        U   u  p#US:X  a  UnX@;   aQ  Sn[        R                  " XPR	                  U5      U R	                  U5      4-  [
        SS9  U R                  U5        Mx  Sn[        R                  " XPR	                  U5      U4-  [
        SS9  M  US:X  d  M  Sn[        R                  " XPR	                  U5      U4-  [
        SS9  M     U $ )a'  Issue appropriate warnings when deprecated options are present in the
options dictionary. Removes deprecated option key, value pairs if the
options dictionary is found to also have the renamed option.

:param options: Instance of _CaseInsensitiveDictionary containing
      MongoDB URI options.
renamedz0Deprecated option '%s' ignored in favor of '%s'.r2   rR   z,Option '%s' is deprecated, use '%s' instead.removedzOption '%s' is deprecated. %s.)listr   rW   rX   ro   DeprecationWarningpop)r[   optnamemodemessage
newoptnamewarn_msgs         r!   _handle_option_deprecationsr      s     =117@MDy $
(QHMM $5$5g$>@Q@QR\@]#^^*#$
 KK(I 1 1' :JGG& 
 "; 1 1' :GDD& - !8 Nr#   c                    U R                  S5      nUb  [         H  nXU'   M	     [        U 5       H2  n[        R                   " US5      nUc  M  U R	                  U5      X'   M4     U $ )zNormalizes option names in the options dictionary by converting them to
their internally-used names.

:param options: Instance of _CaseInsensitiveDictionary containing
      MongoDB URI options.
rb   N)rm   rn   rw   r   ry   )r[   rb   rp   rz   intnames        r!   _normalize_optionsr   '  si     ++m,K-C&CL . =.227DA&{{73G !
 Nr#   Fc                    [        X5      $ )a  Validates and normalizes options passed in a MongoDB URI.

Returns a new dictionary of validated and normalized options. If warn is
False then errors will be thrown for invalid options, otherwise they will
be ignored and a warning will be issued.

:param opts: A dict of MongoDB URI options.
:param warn: If ``True`` then warnings will be logged and
      invalid options will be ignored. Otherwise invalid options will
      cause errors.
)r   )rY   rX   s     r!   validate_optionsr   =  s     !,,r#   Tc                   U R                  S5      nU R                  S5      n US:  a  US:  a  [        S5      eUS:  a  [        U S5      nO;US:  a  [        U S5      nO(U R                  S5      S:w  a  [        U S5      nO[        e[	        U5      n[        U5      nU(       a  [        U5      nU(       a9  [        [        [        Xb5      5      nUR                  S	5      S
:X  a  [        S5      eU$ ! [         a    [        S5      Sef = f)a  Takes the options portion of a MongoDB URI, validates each option
and returns the options in a dictionary.

:param opt: A string representing MongoDB URI options.
:param validate: If ``True`` (the default), validate and normalize all
      options.
:param warn: If ``False`` (the default), suppress all warnings raised
      during validation of options.
:param normalize: If ``True`` (the default), renames all options to their
      internally-used names.
&;r   z.Can not mix '&' and ';' for option separators.rP   r1   Nz(MongoDB URI options are key=value pairs.
authsource z1the authSource database cannot be an empty string)r3   r   r`   r4   rs   r   r   r   r   r   rm   )rY   validaterX   	normalizeand_idxsemi_idxr[   s          r!   split_optionsr   L  s    iinGyy~HOa<HMMNN\$T3/G]$T3/GYYs^r!$T40G 'w/G)'2G$W-13CG3RS;;|$*PQQN  OCD$NOs   )C3 C3 !!C3 C3 3D
c                    / nU R                  S5       HI  nU(       d  [        S5      eUnUR                  S5      (       a  SnUR                  [	        X45      5        MK     U$ )a  Takes a string of the form host1[:port],host2[:port]... and
splits it into (host, port) tuples. If [:port] isn't present the
default_port is used.

Returns a set of 2-tuples containing the host name (or IP) followed by
port number.

:param hosts: A string of the form host1[:port],host2[:port],...
:param default_port: The port number to use when one wasn't specified
      for a host.
,z)Empty host (or extra comma in host list).r:   N)rC   r   rB   rV   rK   )hostsr6   nodesr5   rJ   s        r!   split_hostsr   y  s\     E++c"$%PQQ??7##DZ-. # Lr#   r9   z/ "$r0   )r   
authSource
replicaset
replicaSetloadbalancedloadBalancedc                J   [        U 5      S:  a!  UR                  S5      (       a  [        S5      eUR                  S5      (       a]  [        U 5      S:  a  [        S5      eUR                  S5      (       a  [        S5      eUR                  S5      (       a  [        S5      eg g )	Nr'   directconnectionz8Cannot specify multiple hosts with directConnection=truer   z4Cannot specify multiple hosts with loadBalanced=truez;Cannot specify directConnection=true with loadBalanced=truer   z0Cannot specify replicaSet with loadBalanced=true)r   rm   r   )r   r[   s     r!   _check_optionsr     s    
5zA~'++&899 ![\\{{>""u:>$%[\\;;)**$%bcc;;|$$$%WXX % #r#   c                   U R                  [        5      (       a  SnU [        S n	OvU R                  [        5      (       aB  [	        5       (       d'  [
        R                  =(       d    Sn
[        SU
-  5      eSnU [        S n	O[        S[         S[         S35      eU	(       d  [        S	5      eSnSnSnSn[        5       nU	R                  S
5      u  nnnSU;   a  UR                  S5      u  nnnOUnU(       aN  [        U5      nSU;   a  UR                  SS5      u  p[        R                  U5      (       a  [        SU-  5      eOSnU(       a  UR!                  [#        UX#U5      5        Uc  UR%                  S[&        5      nSU;   a#  UR)                  S5      u  nnn[+        U5      u  pOUnSU;   a  [        SU-  5      e[        U5      nSnU=(       d    UR%                  S5      nU(       Ga  UR%                  S5      (       a  [        S[         S35      e[-        USS9n[/        U5      S:w  a  [        [         S35      eUS   u  nnUb  [        [         S35      eU=(       d    UR%                  S5      n[1        UXVU5      nUR3                  5       nUR5                  5       nU(       aV  [#        UX#U5      n[7        U5      [8        -
  (       a  [        S5      eUR;                  5        H  u  nnUU;  d  M  UUU'   M     UR%                  S5      (       a  U(       a  [        S5      eUR%                  S5      (       a  U(       a  [        S5      eS U;  a  S!U;  a  U(       a  SOS"US '   OGU(       d  UR%                  S5      b  [        S#5      eU(       d  U(       a  [        S$5      e[-        UUS9n[=        UU5        UUUUUUUS%.$ )&a  Parse and validate a MongoDB URI.

Returns a dict of the form::

    {
        'nodelist': <list of (host, port) tuples>,
        'username': <username> or None,
        'password': <password> or None,
        'database': <database name> or None,
        'collection': <collection name> or None,
        'options': <dict of MongoDB URI options>,
        'fqdn': <fqdn of the MongoDB+SRV URI> or None
    }

If the URI scheme is "mongodb+srv://" DNS SRV and TXT lookups will be done
to build nodelist and options.

:param uri: The MongoDB URI to parse.
:param default_port: The port number to use when one wasn't specified
      for a host in the URI.
:param validate: If ``True`` (the default), validate and
      normalize all options. Default: ``True``.
:param warn: When validating, if ``True`` then will warn
      the user then ignore any invalid options or values. If ``False``,
      validation will error when options are unsupported or values are
      invalid. Default: ``False``.
:param normalize: If ``True``, convert names of URI options
      to their internally-used names. Default: ``True``.
:param connect_timeout: The maximum time in milliseconds to
      wait for a response from the DNS server.
:param srv_service_name: A custom SRV service name

.. versionchanged:: 4.6
   The delimiting slash (``/``) between hosts and connection options is now optional.
   For example, "mongodb://example.com?tls=true" is now a valid URI.

.. versionchanged:: 4.0
   To better follow RFC 3986, unquoted percent signs ("%") are no longer
   supported.

.. versionchanged:: 3.9
    Added the ``normalize`` parameter.

.. versionchanged:: 3.6
    Added support for mongodb+srv:// URIs.

.. versionchanged:: 3.5
    Return the original value of the ``readPreference`` MongoDB URI option
    instead of the validated read preference mode.

.. versionchanged:: 3.1
    ``warn`` added so invalid options can be ignored.
FNpythonzThe "dnspython" module must be installed to use mongodb+srv:// URIs. To fix this error install pymongo again:
 %s -m pip install pymongo>=4.3Tz)Invalid URI scheme: URI must begin with 'z' or ''z)Must provide at least one hostname or IP.?/.r'   zBad database name "%s"srvServiceNamer%   z;Any '/' in a unix domain socket must be percent-encoded: %ssrvMaxHostsdirectConnectionz*Cannot specify directConnection=true with z URIs)r6   z. URIs must include one, and only one, hostnamer   z$ URIs must not include a port numberconnectTimeoutMSzDOnly authSource, replicaSet, and loadBalanced are supported from DNSr   z0You cannot specify loadBalanced with srvMaxHostsr   z.You cannot specify replicaSet with srvMaxHostsre   rd   rg   zDThe srvServiceName option is only allowed with 'mongodb+srv://' URIszAThe srvMaxHosts option is only allowed with 'mongodb+srv://' URIs)nodelistusernamepassworddatabase
collectionr[   fqdn)
startswithSCHEME
SCHEME_LEN
SRV_SCHEMEr   sys
executabler   SRV_SCHEME_LENr   r   r)   r   rC   _BAD_DB_CHARSsearchupdater   rm   r   
rpartitionr.   r   r   r   	get_hostsget_optionsset_ALLOWED_TXT_OPTSitemsr   )urir6   r   rX   r   connect_timeoutsrv_service_namesrv_max_hostsis_srvscheme_freepython_pathr+   r-   dbaser   r[   host_plus_db_partr,   rY   	host_partr*   r   r   r   rJ   dns_resolverdns_optionsparsed_dns_optionsrp   r_   s                                 r!   	parse_urir     s   ~ ~~f*+&	
	#	#  ..4HK$1 5@A  ./*DVHFS]R^^_`aaDEEDFEJ(*G!,!6!6s!;q$
/99#>	1e%	U#%< %C 3E&&5=>> ' }T89EF";;'79IJ
i&11#6!U%h/f
e|VYbbccED!?W[[%?M;;)**$'QR\Q]]b%cddE5u:?
|+YZ[[1X
d
|+OPQQ *LW[[9K-L#D/][&&("..0!.{HI!V%&)::(Z  /446Sg%#&GCL 7 ;;~&&=OPP;;|$$MNNE$8%-T6GEN$45A R
 	
  O
 	
 E=5'"   r#   c                   U (       d  0 $ [        U [        5      (       d  [        S5      e0 nU R                  5        H  u  p#[        U[        5      (       d  [        SU S35      eUR	                  SS5        [        U5      n[        U5      n[        U5      n[        [
        [        U5      5      n[        U5      u  pVUc  [        S5      eU(       a  [        S5      eS H  nXt;   a  [        S	U 35      eXQU'   M     M     U$ )
z!Parse KMS TLS connection options.zkms_tls_options must be a dictzkms_tls_options["z"] must be a dictre   Tz!TLS is required for KMS providerszInsecure TLS options prohibited)tlsInsecuretlsAllowInvalidCertificatestlsAllowInvalidHostnames$tlsDisableCertificateRevocationCheckz!Insecure TLS options prohibited: )rD   dict	TypeErrorr   rU   r   rs   r   r   r   r   r   )kms_tls_optionscontextsproviderr[   rY   ssl_contextallow_invalid_hostnamesns           r!   _parse_kms_tls_optionsr   W  s   	ot,,899H,224'4((/z9JKLL5$')'2'-!$'.0@0FG/A$/G,$%HII"$%FGG
A y(+LQC)PQQ!,X
 5. Or#   __main__r'   )r   rE   rl   ri   )r*   rE   rl   ztuple[str, str])r5   rE   r6   Optional[int]rl   z%tuple[str, Optional[Union[str, int]]])r5   rE   r6   r   rl   r   )rY   rE   rZ   Optional[str]rl   r   )r[   r   rl   r   )F)rY   Mapping[str, Any]rX   ri   rl   MutableMapping[str, Any])TFT)
rY   rE   r   ri   rX   ri   r   ri   rl   r   )r   rE   r6   r   rl   zlist[_Address])r   r	   r[   r   rl   None)r   rE   r6   r   r   ri   rX   ri   r   ri   r   zOptional[float]r   r   r   r   rl   zdict[str, Any])r   zOptional[Mapping[str, Any]]rl   zdict[str, SSLContext])C__doc__
__future__r   rer   rW   typingr   r   r   r   r   r	   r
   r   urllib.parser   pymongo.client_optionsr   pymongo.commonr   r   r   r   r   pymongo.errorsr   r   pymongo.srv_resolverr   r   pymongo.typingsr   pymongo.pyopenssl_contextr   r   r   r   r   r   DEFAULT_PORTr"   r.   r7   rK   rn   r`   rs   r   r   r   r   r   compileescaper   	frozensetr   r   r   r   __name__pprintargvexcprintexit r#   r!   <module>r      s    # 	 
 	 	 	 & 5  : > $4	[

Z 40((,(*(. ;G 0h ,2j$N,-  MQ*
**,0*EI**Z ;G 4 

37!33c9:\ 
Y  #/'+&*#'l	ll l 	l
 l %l $l !l l^B zi,- HHQK 
  c

s   7%E0 0F6FF