
    FCfx\                       d Z ddlmZ ddlZddlZddl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mZmZmZmZ ddlmZmZ dd	lmZmZ dd
lm Z  erddl!m"Z" dZ# e$e#      Z%dZ& e$e&      Z'dZ(d&dZ)d'dZ*	 	 	 	 	 	 d(dZ+e(fd)dZ,h dZ-d*dZ.d+dZ/d+dZ0d+dZ1d,d-dZ2	 d.	 	 	 	 	 	 	 	 	 d/dZ3e(fd0dZ4 ejj                  d ejl                  d      z   dz         Z7 e8g d       Z9d1d!Z:e(ddddddf	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 d2d"Z;d3d#Z<e=d$k(  r=ddl>Z>	  e>j|                   e;ej~                  d%                 ej                  d       yy# e$ rZ@ eAe@       Y dZ@[@&dZ@[@ww xY w)4z*Tools to parse and validate a MongoDB URI.    )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                x    t        t        |             D ]#  }| |   dk(  s| ||dz    }t        |      |k(  s# y y)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      R/var/www/highfloat_scraper/venv/lib/python3.12/site-packages/pymongo/uri_parser.py_unquoted_percentr"   8   sL     3q6] Q43;AA,C C C'     c                    d| v s| j                  d      dkD  st        |       rt        d      | j                  d      \  }}}|st        d      t	        |      t	        |      fS )aZ  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.   H   sq     h(..-15Fx5P4
 	

 ((-OD!VBCC|F333r#   c                    | j                  d      dk(  rt        d      | j                  d      }|dk(  r| dd |fS | d| | |dz   d fS )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   `   sh     {{32\
 	
 	DABwa|\))!A;q1uw''r#   c                   | }|}| d   dk(  rt        | |      \  }}n]| j                  d      r| |fS | j                  d      dk7  r4| j                  d      dkD  rt	        d      |j                  dd      \  }}t        |t              rE|j                         rt        |      dkD  st        |      dk  rt	        d	|      t        |      }|j                         |fS )
aq  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.i  z-Port must be an integer between 0 and 65535: )r7   endswithr3   r(   r4   split
isinstancestrisdigitintlower)r5   r6   hostports       r!   
parse_hostrD   w   s     D&2DayC,V\B
d		!|##	S	R	<<q 1  ZZQ'
d$||~TU!2c$i1nLTHUVV4y ::<r#   >   tlsallowinvalidhostnamestlsallowinvalidcertificatestlsdisableocspendpointcheckc                b   t               }| j                  |      D ]  }|j                  d      \  }}|j                         dk(  r"|j                  |g       j	                  |       L||v rt        j                  d| dd       |j                         dk(  r|}nt        |      }|||<    |S )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   r<   rA   
setdefaultappendwarningswarnr   )optsdelimoptionsurioptkeyvaluevals          r!   _parse_optionsrY      s    
 )*G**U# \\#&
U99;..sB'..u5g~ 6se2>1Myy{77"5)GCL Nr#   c                ~   | j                  d      }|?t        D ]6  }|| v sd}t        || j                  d      | j                  |      fz         | j                  d      }|.d| v r!d}t        |d| j                  d      fz        |du rd| d<   | j                  d      }|+dD ]&  }| j                  |      du sd}t        ||fz         d	| v rgd
| v rcdd} || j                  d	             || j                  d
            k7  r0d}t        || j                  d	      | j                  d
      fz        | S )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.rF   rG   T
tlscrlfile)r[   rF   rG   zDURI option %s=True cannot be specified when CRL checking is enabled.ssltlsc                <    | dv r| dk(  S t        | t              r| S | S )N)truefalser`   )r=   bool)rX   s    r!   truth_valuez-_handle_security_options.<locals>.truth_value   s)    ''f}$#t$
Jr#   z=Can not specify conflicting values for URI options %s and %s.)rX   r   returnr   )get_IMPLICIT_TLSINSECURE_OPTSr   	cased_key)rT   r[   opterr_msgtlsallowinvalidcertsr\   rc   s          r!   _handle_security_optionsrk      s    ++m,K- 	Cg~U w00?ARARSVAWXX 	 #;;'DE'(G3QG0'2C2CDa2bcd   4'59G12 \*J` 	3C{{34'` C6!122	3
 EW,	 w{{5)*k'++e:L.MMUGW(9(9%(@'BSBSTYBZ'[[\\Nr#   c                   t        |       D ]  }|t        v st        |   \  }}|dk(  r|}|| v rSd}t        j                  || j	                  |      | j	                  |      fz  t
        d       | j                  |       vd}t        j                  || j	                  |      |fz  t
        d       |dk(  sd}t        j                  || j	                  |      |fz  t
        d        | S )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   rK   z,Option '%s' is deprecated, use '%s' instead.removedzOption '%s' is deprecated. %s.)listr   rP   rQ   rg   DeprecationWarningpop)rT   optnamemodemessage
newoptnamewarn_msgs         r!   _handle_option_deprecationsrw      s     = 117@MD'y $
(QHMM G$5$5g$>@Q@QR\@]#^^*#$
 KK(I 1 1' :JGG& 
 "; 1 1' :GDD& -8 Nr#   c                    | j                  d      }|t        D ]  }|| |<   	 t        |       D ]/  }t        j                   |d      }|| j	                  |      | |<   1 | S )zNormalizes option names in the options dictionary by converting them to
    their internally-used names.

    :param options: Instance of _CaseInsensitiveDictionary containing
          MongoDB URI options.
    r[   N)re   rf   ro   r   rq   )rT   r[   rh   rr   intnames        r!   _normalize_optionsrz     sw     ++m,K- 	'C&GCL	' = 4.227DA&{{73GG4
 Nr#   Fc                    t        | |      S )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   )rR   rQ   s     r!   validate_optionsr|   -  s     !t,,r#   Tc                   | j                  d      }| j                  d      }	 |dk\  r|dk\  rt        d      |dk\  rt        | d      }n9|dk\  rt        | d      }n'| j                  d      dk7  rt        | d      }nt        t	        |      }t        |      }|rt        |      }|r9t        t        t        ||            }|j                  d	      d
k(  rt        d      |S # t        $ r t        d      dw xY w)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.rI   r1   Nz(MongoDB URI options are key=value pairs.
authsource z1the authSource database cannot be an empty string)r3   r   rY   r4   rk   rw   rz   r   r   r|   re   )rR   validaterQ   	normalizeand_idxsemi_idxrT   s          r!   split_optionsr   <  s    iinGyy~HOa<HMMNN\$T3/G]$T3/GYYs^r!$T40G 'w/G)'2G$W-13CGT3RS;;|$*PQQN  OCD$NOs   A C$ $C:c                    g }| j                  d      D ]?  }|st        d      |}|j                  d      rd}|j                  t	        ||             A |S )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)r<   r   r;   rO   rD   )hostsr6   nodesr5   rC   s        r!   split_hostsr   i  s`     E++c" /$%PQQ??7#DZ-./ Lr#   r9   z/ "$r0   )r   
authSource
replicaset
replicaSetloadbalancedloadBalancedc                   t        |       dkD  r|j                  d      rt        d      |j                  d      rRt        |       dkD  rt        d      |j                  d      rt        d      |j                  d      rt        d      y y )	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   re   r   )r   rT   s     r!   _check_optionsr     s    
5zA~'++&89 ![\\{{>"u:>$%[\\;;)*$%bcc;;|$$%WXX % #r#   c                   | j                  t              rd}| t        d }	nc| j                  t              r4t        s"t
        j                  xs d}
t        d|
z        d}| t        d }	nt        dt         dt         d      |	st        d	      d}d}d}d}t               }|	j                  d
      \  }}}|s|}d}|r|j                  d      \  }}}n|j                  d      \  }}}|rGt        |      }d|v r|j                  dd      \  }}t        j                  |      rt        d|z        d}|r|j!                  t#        ||||             ||j%                  dt&              }d|v r$|j)                  d      \  }}}t+        |      \  }}n|}d
|v rt        d|z        t        |      }d}|xs |j%                  d      }|rM|j%                  d      rt        dt         d      t-        |d      }t/        |      dk7  rt        t         d      |d   \  }}|t        t         d      |xs |j%                  d      }t1        ||||      }|j3                         }|j5                         }|rMt#        ||||      }t7        |      t8        z
  rt        d      |j;                         D ]  \  }}||vs|||<    |j%                  d      r|rt        d      |j%                  d      r|rt        d       d!|vrHd"|vrD|rdnd#|d!<   n:|s|j%                  d      t        d$      |s|rt        d%      t-        ||      }t=        ||       |||||||d&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   ?.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 srvMaxHostsr^   r]   r`   zDThe srvServiceName option is only allowed with 'mongodb+srv://' URIszAThe srvMaxHosts option is only allowed with 'mongodb+srv://' URIs)nodelistusernamepassworddatabase
collectionrT   fqdn)
startswithSCHEME
SCHEME_LEN
SRV_SCHEMEr   sys
executabler   SRV_SCHEME_LENr   r   r)   r   r<   _BAD_DB_CHARSsearchupdater   re   r   
rpartitionr.   r   r   r   	get_hostsget_optionsset_ALLOWED_TXT_OPTSitemsr   )urir6   r   rQ   r   connect_timeoutsrv_service_namesrv_max_hostsis_srvscheme_freepython_pathr+   r-   dbaser   rT   	host_partr,   	path_partrR   r*   r   r   r   rC   dns_resolverdns_optionsparsed_dns_optionsrh   rX   s                                 r!   	parse_urir     s   ~ ~~f*+&	
	#..4HK$1 5@A  ./*DVHFS]R^^_`aaDEEDFEJ(*G)33C8Iq)		",,S1q$ '005	1dU#%< %C 3E:&5=>>}T8T9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/;K][&&("..0!.{HdI!V%&)::(Z  /446 'Sg%#&GCL' ;;~&=OPP;;|$MNNE$8%-T6GEN$45A R
 	
  O
 	
 E=5'"   r#   c                   | si S t        | t              st        d      i }| j                         D ]  \  }}t        |t              st        d| d      |j	                  dd       t        |      }t        |      }t        |      }t        t
        t        |            }t        |      \  }}|t        d      |rt        d      dD ]  }||v rt        d	|       |||<     |S )
z!Parse KMS TLS connection options.zkms_tls_options must be a dictzkms_tls_options["z"] must be a dictr^   Tz!TLS is required for KMS providerszInsecure TLS options prohibited)tlsInsecuretlsAllowInvalidCertificatestlsAllowInvalidHostnames$tlsDisableCertificateRevocationCheckz!Insecure TLS options prohibited: )r=   dict	TypeErrorr   rN   r   rk   rz   r   r|   r   r   )kms_tls_optionscontextsproviderrT   rR   ssl_contextallow_invalid_hostnamesns           r!   _parse_kms_tls_optionsr   L  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 Dy(+LQC)PQQ!,HX	--. Or#   __main__r'   )r   r>   rd   rb   )r*   r>   rd   ztuple[str, str])r5   r>   r6   Optional[int]rd   z%tuple[str, Optional[Union[str, int]]])r5   r>   r6   r   rd   r   )rR   r>   rS   Optional[str]rd   r   )rT   r   rd   r   )F)rR   Mapping[str, Any]rQ   rb   rd   MutableMapping[str, Any])TFT)
rR   r>   r   rb   rQ   rb   r   rb   rd   r   )r   r>   r6   r   rd   zlist[_Address])r   r	   rT   r   rd   None)r   r>   r6   r   r   rb   rQ   rb   r   rb   r   zOptional[float]r   r   r   r   rd   zdict[str, Any])r   zOptional[Mapping[str, Any]]rd   zdict[str, SSLContext])C__doc__
__future__r   rer   rP   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   rD   rf   rY   rk   rw   rz   r|   r   r   compileescaper   	frozensetr   r   r   r   __name__pprintargvexcprintexit r#   r!   <module>r      s    1 " 	 
 	 	 	 & 5  : > $4	[

Z 40((,(*(. ;G #N ,2j$N,-  MQ*
**,0*EI**Z ;G 4 

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

s   %E E.E))E.