
    _iY                       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 ddlmZmZ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& e'g d          Z(dGdZ)dHdZ*dIdZ+e&fdJdZ,h dZ-dKd$Z.dLd&Z/dLd'Z0dLd(Z1dMdNd-Z2	 dOdPd1Z3e&fdQd4Z4 ej5        d5 ej6        d6          z   d7z             Z7 e'g d8          Z8dRd<Z9dSdAZ:e&d.d)d.dfdTdEZ;dUdFZ<dS )VzTools 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)_have_dnspython)_parse_ssl_options)INTERNAL_URI_OPTION_NAME_MAPURI_OPTIONS_DEPRECATION_MAP_CaseInsensitiveDictionaryget_validated_options)ConfigurationError
InvalidURI)_Address)
SSLContextz
mongodb://zmongodb+srv://ii  ).appnameauthMechanismauthMechanismProperties
authSourcecompressorsconnectTimeoutMSdirectConnectionheartbeatFrequencyMSjournalloadBalancedlocalThresholdMSmaxIdleTimeMSmaxPoolSizemaxConnectingmaxStalenessSecondsminPoolSize	proxyHost	proxyPortproxyUsernameproxyPasswordreadConcernLevelreadPreferencereadPreferenceTags
replicaSet
retryReadsretryWritesserverMonitoringModeserverSelectionTimeoutMSserverSelectionTryOncesocketTimeoutMSsrvMaxHostssrvServiceNamessltlstlsAllowInvalidCertificatestlsAllowInvalidHostnames	tlsCAFiletlsCertificateKeyFiletlsCertificateKeyFilePassword$tlsDisableCertificateRevocationChecktlsDisableOCSPEndpointChecktlsInsecurewwaitQueueTimeoutMS
wTimeoutMSzlibCompressionLevelsstrreturnboolc                    t          t          |                     D ]1}| |         dk    r#| ||dz            }t          |          |k    r dS 2dS )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   )rE   isubs      <D:\Nbitz\venv\Lib\site-packages\pymongo/uri_parser_shared.py_unquoted_percentrQ   m   s_     3q66]]  Q43;;AAI,C C  C''tt5    userinfotuple[str, str]c                   d| v s(|                      d          dk    st          |           rt          d          |                     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)countrQ   r   	partitionr   )rS   user_passwds       rP   parse_userinfor^   }   s     h(..--115Fx5P5P14
 
 	

 ((--OD!V CABBB|F3333rR   entitydefault_portOptional[int]%tuple[str, Optional[Union[str, int]]]c                    |                      d          dk    rt          d          |                      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]:rX      N)find
ValueError)r_   r`   rN   s      rP   parse_ipv6_literal_hostri      s~     {{32\
 
 	
 	DABwwad|\))!A#;q1uww''rR   r   c                   | }|}| d         dk    rt          | |          \  }}ns|                     d          r| |fS |                     d          dk    rA|                     d          dk    rt	          d          |                    dd          \  }}t          |t                    r|                                sSt          d |D                       r+|D ](}|
                                rt	          d	|          )t	          d
          t          |          dk    st          |          dk    rt	          d          t          |          }|                                |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   [.sockrW   re   rX   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  f   K   | ],}|                                 p|                                V  -d S N)isspaceisdigit).0cs     rP   	<genexpr>zparse_host.<locals>.<genexpr>   s7      <<!199;;-!))++<<<<<<rR   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)ri   endswithrg   rY   rh   split
isinstancerF   rp   allro   intlower)r_   r`   hostportrr   s        rP   
parse_hostr|      s    D&2DayC,V\BB
dd		!	! 
(|##	S		R		<<q  1   ZZQ''
d$ ||~~ 	<<t<<<<< W W WAyy{{ W()UPQ)U)UVVVW
 8   t99uD		QJKKK4yy ::<<rR   >   tlsallowinvalidhostnamestlsallowinvalidcertificatestlsdisableocspendpointcheckoptsdelimOptional[str]r   c                   t                      }|                     |          D ]}|                    d          \  }}|                                dk    r*|                    |g                               |           \||v rt          j        d| dd           |                                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'.rf   
stacklevelauthmechanismproperties)r   ru   ry   
setdefaultappendwarningswarnr   )r   r   optionsurioptkeyvaluevals          rP   _parse_optionsr      s    
 )**G**U##  \\#&&
U99;;...sB''..u5555g~~>s>>>1MMMMyy{{777"5))GCLLNrR   r   c                   |                      d          }|Jt          D ]B}|| v r<d}t          ||                     d          |                     |          fz            C|                      d          }|6d| v r)d}t          |d|                     d          fz            |du rd| d<   |                      d          }|1dD ].}|                      |          du rd	}t          ||fz            /d
| v rd| v r~dd} ||                      d
                     ||                      d                    k    r<d}t          ||                     d
          |                     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.
    tlsinsecureNz9URI options %s and %s cannot be specified simultaneously.r~   r   T
tlscrlfile)r   r~   r   zDURI option %s=True cannot be specified when CRL checking is enabled.r7   r8   r   r   rG   c                H    | dv r| dk    S t          | t                    r| S | S )N)truefalser   )rv   rH   )r   s    rP   truth_valuez-_handle_security_options.<locals>.truth_value$  s4    '''f}$#t$$ 
JrR   z=Can not specify conflicting values for URI options %s and %s.)r   r   rG   r   )get_IMPLICIT_TLSINSECURE_OPTSr   	cased_key)r   r   opterr_msgtlsallowinvalidcertsr   r   s          rP   _handle_security_optionsr      s    ++m,,K- 	 	Cg~~U w00??ARARSVAWAWXX    #;;'DEE'(G33QG0'2C2CDa2b2bcd    4''59G12 \**J` 	3 	3C{{34''` C6!1222 ( EW,,	 	 	 	 ;w{{5))**kk'++e:L:L.M.MMMUGW(9(9%(@(@'BSBSTYBZBZ'[[\\\NrR   c                   t          |           D ]}|t          v rt          |         \  }}|dk    r|}|| v r_d}t          j        ||                     |          |                     |          fz  t
          d           |                     |           d}t          j        ||                     |          |fz  t
          d           |dk    r6d}t          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'.rf   r   z,Option '%s' is deprecated, use '%s' instead.removedzOption '%s' is deprecated. %s.)listr   r   r   r   DeprecationWarningpop)r   optnamemodemessage
newoptnamewarn_msgs         rP   _handle_option_deprecationsr   2  sK    ==  1117@MD'y  $
((QHM G$5$5g$>$>@Q@QR\@]@]#^^*#$   
 KK(((I 1 1' : :JGG&     
 ""; 1 1' : :GDD&     NrR   c                    |                      d          }|t          D ]}|| |<   t          |           D ]1}t          j         |d          }||                     |          | |<   2| 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)r   r   r   r   r   )r   r   r   r   intnames        rP   _normalize_optionsr   Y  s~     ++m,,K- 	' 	'C&GCLL== 4 4.27DAA&{{733GGNrR   FMapping[str, Any]r   MutableMapping[str, Any]c                "    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   )r   r   s     rP   validate_optionsr   o  s     !t,,,rR   Tvalidate	normalizec                   |                      d          }|                      d          }	 |dk    r|dk    rt          d          |dk    rt          | d          }nH|dk    rt          | d          }n1|                      d          dk    rt          | d          }nt          n# t          $ r t          d          dw xY wt	          |          }t          |          }|rt          |          }|rKt          t          t          ||                    }|
                    d	          d
k    rt          d          |S )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 separatorsr   re   Nz'MongoDB URI options are key=value pairs
authsource z1the authSource database cannot be an empty string)rg   r   r   rh   r   r   r   r   r   r   r   )r   r   r   r   and_idxsemi_idxr   s          rP   split_optionsr   ~  sY    iinnGyy~~HNa<<HMMLMMM\\$T3//GG]]$T3//GGYYs^^r!!$T400GG N N NBCCMN 'w//G)'22G .$W-- R13CGT3R3RSS;;|$$**PQQQNs   A:B' 'Chostslist[_Address]c                    g }|                      d          D ]O}|st          d          |}|                    d          rd}|                    t	          ||                     P|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)rl   N)ru   r   rt   r   r|   )r   r`   nodesr_   r{   s        rP   split_hostsr     s~     E++c"" / / 	Q$%OPPP??7## 	DZ--....LrR   rk   z/ "$rd   )r   r   
replicasetr.   loadbalancedr    r   r	   Nonec                v   t          |           dk    r$|                    d          rt          d          |                    d          rjt          |           dk    rt          d          |                    d          rt          d          |                    d          rt          d          d S d S )	NrX   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)rM   r   r   )r   r   s     rP   _check_optionsr     s    
5zzA~~'++&899~ ![\\\{{>"" Yu::>>$%[\\\;;)** 	d$%bccc;;|$$ 	Y$%WXXXY Y
	Y 	YrR   kms_tls_optionsOptional[Mapping[str, Any]]is_syncdict[str, SSLContext]c                R   | si S t          | t                    st          d          i }|                                 D ]\  }}t          |t                    st          d| d          |                    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 dictr8   TNz!TLS is required for KMS providerszInsecure TLS options prohibited)r@   r9   r:   r>   z!Insecure TLS options prohibited: )rv   dict	TypeErroritemsr   r   r   r   r   r   r   r   )	r   r   contextsproviderr   r   ssl_contextallow_invalid_hostnamesns	            rP   _parse_kms_tls_optionsr     sh   
  	ot,, :8999H,2244 - -''4(( 	MKKKKLLL5$''')'22'--!$''.0@0F0FGG/A$/P/P,,$%HIII" 	H$%FGGG
 	- 	-A Dyy()PQ)P)PQQQ!,HX	- OrR   urisrv_max_hostsdict[str, Any]c                   |                      t                    rd}| t          d          }nz|                      t                    r@t	                      s t
          j        pd}t          d|z            d}| t          d          }n t          dt           dt           d          |st          d          d }	d }
d }d }t                      }|                    d	          \  }}}d
|v r|                    d
          \  }}}n|}|rYt          |          }d|v r|                    dd          \  }}t                              |          rt          d|z            nd }|r%|                    t#          ||||                     d|v r,|                    d          \  }}}t'          |          \  }	}
n|}d
|v rt          d|z            t          |          }d }|p|                    d          }|r|                    d          rt          dt           d          t+          |d           }t-          |          dk    rt          t           d          |d         \  }}|t          t           d          nJ|s$|                    d          t          d          |s|rt          d          t+          ||          }t/          ||           ||	|
||||dS )NF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?/.rX   zBad database name "%s"rV   z;Any '/' in a unix domain socket must be percent-encoded: %sr5   r   z*Cannot specify directConnection=true with z URIs)r`   z. URIs must include one, and only one, hostnamer   z$ URIs must not include a port numberr6   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   rZ   r   ru   _BAD_DB_CHARSsearchupdater   
rpartitionr^   r   r   rM   r   )r   r`   r   r   r   r   is_srvscheme_freepython_pathr[   r]   dbaser   r   host_plus_db_partr\   r   	host_partrS   r   r   r   r{   s                          rP   _validate_urir     s    ~~f b*++&	
	#	# b   	.4HK$1 5@A   .//*`V``S]```aaa ECDDDDFEJ(**G!,!6!6s!;!;q$
/99#>>	1ee%	 U##%<< %C 3 3E:&& 	?5=>>>	?  G}T8T9EEFFF
i&11#66!U%h//ff
e||VYbbcccED!?W[[%?%?M >;;)** 	e$%cR\%c%c%cdddE555u::??
ZZZ[[[1X
d
PPPQQQ  	>$455A R
 
 	
  > > O
 
 	
 E===5'"""    rR   c                    i }t           D ]8}|                                | v r | |         ||<   |                     |           9|                                 D ]
\  }}|||<   |S rn   )URI_OPTIONSry   r   r   )r   case_sensitiveoptionkvs        rP   _make_options_case_sensitiver   ^  sx    N    <<>>W$$%,V_N6"KK  1qrR   )rE   rF   rG   rH   )rS   rF   rG   rT   )r_   rF   r`   ra   rG   rb   )r_   rF   r`   ra   rG   r   )r   rF   r   r   rG   r   )r   r   rG   r   )F)r   r   r   rH   rG   r   )TFT)
r   rF   r   rH   r   rH   r   rH   rG   r   )r   rF   r`   ra   rG   r   )r   r	   r   r   rG   r   )r   r   r   rH   rG   r   )r   rF   r`   ra   r   rH   r   rH   r   rH   r   ra   rG   r   )r   r   rG   r   )=__doc__
__future__r   rer   r   typingr   r   r   r   r   r	   r
   r   urllib.parser   !pymongo.asynchronous.srv_resolverr   pymongo.client_optionsr   pymongo.commonr   r   r   r   pymongo.errorsr   r   pymongo.typingsr   pymongo.pyopenssl_contextr   r   rM   r   r   r   DEFAULT_PORT	frozensetr   rQ   r^   ri   r|   r   r   r   r   r   r   r   r   compileescaper   _ALLOWED_TXT_OPTSr   r   r   r    rR   rP   <module>r     s~     # " " " " " 				 



 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 & % % % % % = = = = = = 5 5 5 5 5 5            : 9 9 9 9 9 9 9 $ $ $ $ $ $ 5444444	S[[

Zi/ / /1 1h    4 4 4 40( ( ( (. ;G 0 0 0 0 0h      ,2 2 2 2j$ $ $ $N   ,- - - - -  MQ* * * * *Z ;G     4 
37!3!33c9::I\\\  
Y Y Y Y! ! ! !L #/#'] ] ] ] ]@     rR   