
    h                        d dl Z d dlZd dlZd dlZd dlZd dlZd dlZd dlZd dlm	Z
mZmZ d dlmZ d dlmZmZmZ d dlmZ d dlmZmZmZ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&m'Z' d d	l(m)Z)m*Z*m+Z+m,Z,m-Z-m.Z.m/Z/m0Z0m1Z1m2Z2 d d
l3m4Z4 d dl5m6Z7 d dl8m9Z9m:Z: d dl;m<Z<m=Z= d dl>m?Z? d dl@mAZA d dlBmCZC d dlDmEZE 	 d dlFmGZG d ZH	 d dlLmLZLmMZMmNZNmOZO d ZPdZQdZRdZSej                  dk(  rG	 d dlTZUd ZV	  eUj                  eUj                  d      5 ZY eVeYd d!      ZZ eVeYd"d#      Z[ddd       d$ Z]nd% Z^d& Z] ed' ed(d)efg      fg      Z_ej                  j                  d*      rej                  dd+ d,k  r1d-j                   ej                         D  cg c]  } | r|  c}       Zdn ej                         Zd ed. ej                         fd/edfd0 ej                         fd) ej                         fg      e_d1<   nej                  d2k(  rX ed. ej                         fd/ ej                         fd0 ej                         fd) ej                         d    fg      e_d1<   n|ej                  dk(  r ed. ej                         fd/d-j                   ej                          ej                         f      fd0 ej                         fd)d3j                   ej                         d4d5       fg      e_d1<   nej                  j                  d6      r0 ej                         d7   \  ZdZkZl ed.edfd/edfd0elfd)ekfg      e_d1<   n ej                   ej                          ej                          ej                               Zo ed. ej                         fd/d-j                  eodd+ D  cg c]  } | s| 	 c}       fd0 ej                         fd)eod+   fg      e_d1<    ej                         j                  d8      rjd-j                   ej                         d9j                   eeqej                              d:d9j                   eeqej                              z  f      e_d;<   nej                  j                  d6      ryd-j                   ej                         d9j                   eeqej                              d<d-j                   ej                          ej                         f      z  f      e_d;<   nEd-j                   ej                         d9j                   eeqej                              f      e_d;<   d=j                  d>       dNd?Zt G d@ dAeu      ZvdB ZwdC Zx G dD dEeu      Zy G dF dGeu      ZzdH Z{dI Z| G dJ dKe2      Z} G dL dM      Z~y# eI$ r   eJed      rej                  rd ZHnd ZHY w xY w# eI$ r d ZPY w xY w# eI$ r d dlUZUY w xY w# 1 sw Y   xY w# e\$ r d!ZZd#Z[Y w xY wc c} w c c} w )O    N)SSLErrorHAS_SNIIPADDR_SAFE)DEFAULT_CODEC_OPTIONS)imap
itervalues_unicode)SON)authhelpersthread_util__version__)_validate_session_write_concern)	MAX_BSON_SIZEMAX_IDLE_TIME_SECMAX_MESSAGE_SIZEMAX_POOL_SIZEMAX_WIRE_VERSIONMAX_WRITE_BATCH_SIZEMIN_POOL_SIZEORDERED_TYPESWAIT_QUEUE_TIMEOUT)
AutoReconnectCertificateErrorConnectionFailureConfigurationErrorInvalidOperationDocumentTooLargeNetworkTimeoutNotMasterErrorOperationFailurePyMongoError)IsMaster)time)ConnectionCheckOutFailedReasonConnectionClosedReason)commandreceive_message)ReadPreference)SERVER_TYPE)SocketChecker)match_hostname)
ip_addressc                 X    	 t        t        |              y# t        t        f$ r Y yw xY wNTF)r-   r	   
ValueErrorUnicodeErroraddresss    O/var/www/html/ranktracker/api/venv/lib/python3.12/site-packages/pymongo/pool.pyis_ip_addressr5   F   s.    	x()L) 		s    ))	inet_ptonc                     	 t        j                  |        y# t         j                  $ rB 	 t        j                  t         j                  |        Y y# t         j                  $ r Y Y yw xY ww xY wr/   )socket	inet_atonerrorr6   AF_INET6r2   s    r4   r5   r5   O   s_    !   )<< !!$$V__g>|| ! !	!s&    A-$AA)%A-(A))A-c                 n    	 t        j                  |        y# t         j                  $ r	 d| v rY yY yw xY w)NT:F)r8   r9   r:   r2   s    r4   r5   r5   ^   s:      )<< '>  s    44fcntlF_GETFDF_SETFD
FD_CLOEXECc                 T    t        | t              }t        | t        |t        z         y)z8Set the close-on-exec flag on the given file descriptor.Nr>   )fdflagss     r4   _set_non_inheritable_non_atomicrF   q   s    b'"b'5:-.    c                      y)z6Dummy function for platforms that don't provide fcntl.N )dummys    r4   rF   rF   y   s    rG   x   
   	   win32c                 z    	 t        j                  | |      \  }}t        |      S # t        t        f$ r |cY S w xY wN)winregQueryValueExintOSErrorr0   )keynamedefaultvalue_s        r4   _queryrZ      sB    	**35HE1u:$ 	 N	s   #& ::z2SYSTEM\CurrentControlSet\Services\Tcpip\ParametersKeepAliveTimei m KeepAliveInterval  c                     t        t        t        dz        }t        t        t        dz        }|t        k  s	|t        k  r$| j                  t        j                  d||f       y y )Nr]      )min_WINDOWS_TCP_IDLE_MS_MAX_TCP_KEEPIDLE_WINDOWS_TCP_INTERVAL_MS_MAX_TCP_KEEPINTVLioctlr8   SIO_KEEPALIVE_VALS)sockidle_msinterval_mss      r4   _set_keepalive_timesrj      s_    *,=,DE2,t35**66JJv007K02 7rG   c                    t        t        |      rYt        t        |      }	 | j                  t        j                  |      }||kD  r"| j                  t        j                  ||       y y y # t        j                  $ r Y y w xY wrP   )hasattrr8   getattr
getsockoptIPPROTO_TCP
setsockoptr:   )rg   
tcp_option	max_valuesockoptrW   s        r4   _set_tcp_optionrt      su    6:&fj1G //&*<*<gFY&OOF$6$6K ' ' << s   AA+ +B Bc                 j    t        | dt               t        | dt               t        | dt               y )NTCP_KEEPIDLETCP_KEEPINTVLTCP_KEEPCNT)rt   rb   rd   _MAX_TCP_KEEPCNTrg   s    r4   rj   rj      s)    n.?@o/ABm-=>rG   driver)rV   PyMongoversionlinux   )       typerV   architectureosdarwin-r_   r   javaPyPy.z(Python %s)platformz(%s)fooidnac                     | \  }}|	d|||fz  }n|d|}|r||z   }t        |t        j                        rt        |      t        |t              rdt        |      v rt        |      t        |      )z9Convert a socket.error to ConnectionFailure and raise it.z	%s:%d: %sz: z	timed out)
isinstancer8   timeoutr   	_SSLErrorstrr   )r3   r:   
msg_prefixhostportmsgs         r4   _raise_connection_failurer   
  s    JD$T4//&3%(S!!	E9	%+U*C S!!C  rG   c                   4   e Zd ZdZeeeddeddddddddfdZe	d        Z
e	d        Ze	d        Ze	d        Ze	d	        Ze	d
        Ze	d        Ze	d        Ze	d        Ze	d        Ze	d        Ze	d        Ze	d        Ze	d        Ze	d        Ze	d        Zy)PoolOptions)__max_pool_size__min_pool_size__max_idle_time_seconds__connect_timeout__socket_timeout__wait_queue_timeout__wait_queue_multiple__ssl_context__ssl_match_hostname__socket_keepalive__event_listeners	__appname__driver
__metadata__compression_settingsNTc                 p   || _         || _        || _        || _        || _        || _        || _        || _        |	| _        |
| _	        || _
        || _        || _        || _        t        j                  t               | _        |rd|i| j"                  d<   |r|j$                  r+t         d   d   d|j$                  | j"                  d   d<   |j&                  r+t         d   d   d|j&                  | j"                  d   d<   |j(                  r&t         d   d|j(                  | j"                  d<   y y y )NrV   applicationr{   |r}   r   )_PoolOptions__max_pool_size_PoolOptions__min_pool_size#_PoolOptions__max_idle_time_seconds_PoolOptions__connect_timeout_PoolOptions__socket_timeout _PoolOptions__wait_queue_timeout!_PoolOptions__wait_queue_multiple_PoolOptions__ssl_context _PoolOptions__ssl_match_hostname_PoolOptions__socket_keepalive_PoolOptions__event_listeners_PoolOptions__appname_PoolOptions__driver"_PoolOptions__compression_settingscopydeepcopy	_METADATA_PoolOptions__metadatarV   r}   r   )selfmax_pool_sizemin_pool_sizemax_idle_time_secondsconnect_timeoutsocket_timeoutwait_queue_timeoutwait_queue_multiplessl_contextssl_match_hostnamesocket_keepaliveevent_listenersappnamer{   compression_settingss                  r4   __init__zPoolOptions.__init__+  s+     -,'<$!0 .$6!%8"($6!"2!0 &:#--	2.4g->DOOM* {{h'/5>)&1~~h'	2FNN8D))4j)6??/<
+  rG   c                 &   i }| j                   t        k7  r| j                   |d<   | j                  t        k7  r| j                  |d<   | j                  t
        k7  r| j                  dz  |d<   | j                  t        k7  r| j                  dz  |d<   |S )zqThe non-default options this pool was created with.

        Added for CMAP's :class:`PoolCreatedEvent`.
        maxPoolSizeminPoolSizer]   maxIdleTimeMSwaitQueueTimeoutMS)r   r   r   r   r   r   r   r   )r   optss     r4   non_default_optionszPoolOptions.non_default_optionsY  s     =0"&"6"6D=0"&"6"6D''+<<$($@$@4$GD!$$(::)-)B)BT)ID%&rG   c                     | j                   S )aQ  The maximum allowable number of concurrent connections to each
        connected server. Requests to a server will block if there are
        `maxPoolSize` outstanding connections to the requested server.
        Defaults to 100. Cannot be 0.

        When a server's pool has reached `max_pool_size`, operations for that
        server block waiting for a socket to be returned to the pool. If
        ``waitQueueTimeoutMS`` is set, a blocked operation will raise
        :exc:`~pymongo.errors.ConnectionFailure` after a timeout.
        By default ``waitQueueTimeoutMS`` is not set.
        )r   r   s    r4   r   zPoolOptions.max_pool_sizej  s     ###rG   c                     | j                   S )zThe minimum required number of concurrent connections that the pool
        will maintain to each connected server. Default is 0.
        )r   r   s    r4   r   zPoolOptions.min_pool_sizey  s    
 ###rG   c                     | j                   S )zThe maximum number of seconds that a connection can remain
        idle in the pool before being removed and replaced. Defaults to
        `None` (no limit).
        )r   r   s    r4   r   z!PoolOptions.max_idle_time_seconds  s     +++rG   c                     | j                   S )zGHow long a connection can take to be opened before timing out.
        )r   r   s    r4   r   zPoolOptions.connect_timeout       %%%rG   c                     | j                   S )zKHow long a send or receive on a socket can take before timing out.
        )r   r   s    r4   r   zPoolOptions.socket_timeout  s     $$$rG   c                     | j                   S )zhHow long a thread will wait for a socket from the pool if the pool
        has no free sockets.
        )r   r   s    r4   r   zPoolOptions.wait_queue_timeout  s    
 (((rG   c                     | j                   S )ztMultiplied by max_pool_size to give the number of threads allowed
        to wait for a socket at one time.
        )r   r   s    r4   r   zPoolOptions.wait_queue_multiple  s    
 )))rG   c                     | j                   S )z(An SSLContext instance or None.
        )r   r   s    r4   r   zPoolOptions.ssl_context  s     !!!rG   c                     | j                   S )zCCall ssl.match_hostname if cert_reqs is not ssl.CERT_NONE.
        )r   r   s    r4   r   zPoolOptions.ssl_match_hostname  s     (((rG   c                     | j                   S )zZWhether to send periodic messages to determine if a connection
        is closed.
        )r   r   s    r4   r   zPoolOptions.socket_keepalive  s    
 &&&rG   c                     | j                   S )z;An instance of pymongo.monitoring._EventListeners.
        )r   r   s    r4   r   zPoolOptions.event_listeners  r   rG   c                     | j                   S )zMThe application name, for sending with ismaster in server handshake.
        )r   r   s    r4   r   zPoolOptions.appname  s     ~~rG   c                     | j                   S )zIDriver name and version, for sending with ismaster in handshake.
        )r   r   s    r4   r{   zPoolOptions.driver  s     }}rG   c                     | j                   S rP   )r   r   s    r4   r   z PoolOptions.compression_settings  s    ***rG   c                 6    | j                   j                         S )zLA dict of metadata about the application, driver, os, and platform.
        )r   r   r   s    r4   metadatazPoolOptions.metadata  s     ##%%rG   )__name__
__module____qualname__	__slots__r   r   r   r   r   propertyr   r   r   r   r   r   r   r   r   r   r   r   r   r{   r   r   rI   rG   r4   r   r   !  sv   +I &3,'8$ $9K%)t$(4!%tD&*,<\    $ $ $ $ , , & &
 % %
 ) ) * * " "
 ) )
 ' ' & &
  
  
 + + & &rG   r   c                 r    | r5| j                         D ]"  }|j                  dk(  s|j                  s |c S  y)zDReturn one credential that needs mechanism negotiation, if any.
    DEFAULTN)values	mechanismusernameall_credentialscredss     r4   _negotiate_credsr     s;     $++- 	E)+	 rG   c                     | rAt        |       dk(  r3t        t        |             }t        j                  j                  |      S y)zAReturn the _AuthContext to use for speculative auth, if any.
    r_   N)lennextr   r   _AuthContextfrom_credentialsr   s     r4   _speculative_contextr     s<     3/14Z01  11%88rG   c                   (    e Zd Zd Zd Zed        Zy)_CancellationContextc                     d| _         y NF
_cancelledr   s    r4   r   z_CancellationContext.__init__  s	    rG   c                     d| _         y)zCancel this context.TNr   r   s    r4   cancelz_CancellationContext.cancel  s	    rG   c                     | j                   S )zWas cancel called?r   r   s    r4   	cancelledz_CancellationContext.cancelled  s     rG   N)r   r   r   r   r  r   r  rI   rG   r4   r   r     s        rG   r   c                       e Zd ZdZd ZddZd Zd Zdej                  e
dddddddddddddfd	Zd
 Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zy)
SocketInfozStore a socket with some metadata.

    :Parameters:
      - `sock`: a raw socket object
      - `pool`: a Pool instance
      - `address`: the server's (host, port)
      - `id`: the id of this socket in it's pool
    c                    || _         || _        || _        t               | _        d| _        t               | _        d| _        d| _	        t        | _        t        | _        t        | _        t         | _        d| _        d| _        d| _        |j*                  j,                  | _        |j0                  | _        |j*                  j2                  | _        d | _        t7               | _        i | _        i | _        |j>                  | _        d| _         d | _!        |jD                  stG               | _!        |j*                  | _        d| _$        y r   )%rg   r3   idsetauthsetclosed_timelast_checkin_timeperformed_handshakeis_writabler   max_wire_versionr   max_bson_sizer   max_message_sizer   max_write_batch_sizesupports_sessions	is_mongosop_msg_enabledr   r   	listenersenabled_for_cmapr   compression_contextr+   socket_checkernegotiated_mechanismsauth_ctx
generationreadycancel_context	handshaker   more_to_come)r   rg   poolr3   r  s        r4   r   zSocketInfo.__init__  s   	u!&#(   0* 0$8!!&#22 $ 5 5$(II$B$B!#' +o &(" //
"~~"6"8DII	!rG   Nc                 *    | j                  d d d |      S rP   )	_ismaster)r   r   s     r4   ismasterzSocketInfo.ismaster!  s    ~~dD$@@rG   c                    t        dg      }| j                   }d}|rFd| _        | j                  j                  |d<   | j                  r|| j                  j
                  |d<   nb|`||d<   t        |dz        |d<   d}| j                  j                  r2| j                  j                  | j                  j                  |z          | j                  d	k\  r|||d
<   t        |      }|r|j                  dz   |j                  z   |d<   t        |      }	|	r|	j                         |d<   | j!                  d|d|      }
t#        |
|      }|j$                  | _        |j                  | _
        |j&                  | _        |j(                  | _        |j*                  | _        |j,                  d u| _        |j0                  t2        j4                  k(  | _        |r8| j                  r,| j                  j9                  |j
                        }|| _        |j                  d	k\  | _        |r|j>                  | j@                  |<   |	r:|	jC                  |       |	jE                         r|	| jF                  |	jH                  <   |S )N)r%  r_   FTclientcompressiontopologyVersionr]   maxAwaitTimeMS   z$clusterTimer   saslSupportedMechsspeculativeAuthenticateadmin)publish_eventsexhaust_allowed)	awaitable)%r
   r  r   r   r   compressorsrS   r   rg   
settimeoutr  r   sourcer   r   speculate_commandr'   r#   r  r  r  r  logical_session_timeout_minutesr  server_typer*   Mongosr  get_compression_contextr  r  sasl_supported_mechsr  parse_responsespeculate_succeededr  credentials)r   cluster_timetopology_versionheartbeat_frequencyr   cmdperforming_handshaker1  r   r  docr%  ctxs                r4   r$  zSocketInfo._ismaster$  s[   ?#$#'#;#;;	'+D$ II..CM((%)%>%>%J%JM")%5C!"$'(;D(@$AC !Iyy((		$$II--0CCE   A%,*B".C !1(-s(:U^^(KC$%'8-5-G-G-IC)*ll7C+4  6C95#// ( 9 9%33 ( 9 9$,$A$A!44D@ 	!--1C1CCD$=$=++CC$$&C'*D$&771<080M0MD&&u-##H-++-6>h223rG   c                     | j                  d       }|j                  | _        |j                         }|d   }t        j                  || j
                         |S )Nr   )r(   r!  unpack_responser   _check_command_responser  )r   replyunpacked_docsresponse_docs       r4   _next_replyzSocketInfo._next_reply\  sT    $$T*!..--/$Q'''d6K6KLrG   FTc                    | j                  ||       t        ||
      }t        |t              st	        |      }|	r?| j
                  dk  r0|	j                  s$t        d|	j                  | j
                  fz        |
|
j                  s|t        d      | j
                  dk\  r|
r|
j                  s|
j                  |d<   n| j
                  dk  r|t        d      |r|j                  |||       | j                  |||       |r| j                  nd}|
xr |
j                   }| j                  r| j!                  |       	 t#        | |||| j$                  ||||||| j&                  ||| j(                  |	||| j*                  | j                  |||      S # t,        $ r  t.        $ r}| j1                  |       Y d}~yd}~ww xY w)	aF  Execute a command or raise an error.

        :Parameters:
          - `dbname`: name of the database on which to run the command
          - `spec`: a command document as a dict, SON, or mapping object
          - `slave_ok`: whether to set the SlaveOkay wire protocol bit
          - `read_preference`: a read preference
          - `codec_options`: a CodecOptions instance
          - `check`: raise OperationFailure if there are errors
          - `allowable_errors`: errors to ignore if `check` is True
          - `check_keys`: if True, check `spec` for invalid keys
          - `read_concern`: The read concern for this command.
          - `write_concern`: The write concern for this command.
          - `parse_write_concern_error`: Whether to parse the
            ``writeConcernError`` field in the command response.
          - `collation`: The collation for this command.
          - `session`: optional ClientSession instance.
          - `client`: optional MongoClient for gossipping $clusterTime.
          - `retryable_write`: True if this command is a retryable write.
          - `publish_events`: Should we publish events for this command?
          - `user_fields` (optional): Response fields that should be decoded
            using the TypeDecoders from codec_options, passed to
            bson._decode_all_selective.
           zDread concern level of %s is not valid with a max wire version of %d.Nz3Collation is unsupported for unacknowledged writes.r   writeConcernz5Must be connected to MongoDB 3.4+ to use a collation.)parse_write_concern_error	collationcompression_ctx
use_op_msgunacknowledgeduser_fieldsr0  )validate_sessionr   r   r   r
   r  ok_for_legacyr   levelacknowledgedis_server_defaultdocument	_apply_tosend_cluster_timer  r  _raise_if_not_writabler'   r  r3   r  r  r!   BaseExceptionr   )r   dbnamespecslave_okread_preferencecodec_optionscheckallowable_errors
check_keysread_concernwrite_concernrO  rP  sessionr'  retryable_writer/  rT  r0  r  rS  r:   s                         r4   r'   zSocketInfo.commandd  s   L 	fg.1'=I $.t9DT22Q6$22$1%%t'<'<=>? ? %)C)C!$EG G!!Q&!33#0#9#9D ""Q&9+@$GI I dO_EtWf5&4DNN$	&I}/I/I+I''7	24x>>?M"FE3C<<Y--|5N%.+/+C+C&*&9&9*8'2+:< <   	 	2**511	2s   AF G,GGc                     | j                   )|| j                   kD  rt        d|| j                   fz        	 | j                  j                  |       y# t        $ r}| j                  |       Y d}~yd}~ww xY w)z}Send a raw BSON message or raise ConnectionFailure.

        If a network exception is raised, the socket is closed.
        NzfBSON document too large (%d bytes) - the connected server supports BSON document sizes up to %d bytes.)r  r   rg   sendallr^  r   )r   messagemax_doc_sizer:   s       r4   send_messagezSocketInfo.send_message  s{    
 * 4#5#55"?t11234 4
	2IIg& 	2**511	2s   A 	A7A22A7c                     	 t        | || j                        S # t        $ r}| j                  |       Y d}~yd}~ww xY w)zzReceive a raw BSON message or raise ConnectionFailure.

        If any exception is raised, the socket is closed.
        N)r(   r  r^  r   )r   
request_idr:   s      r4   r(   zSocketInfo.receive_message  s=    
	2"4T5J5JKK 	2**511	2s    	=8=c                 B    |r| j                   st        ddddd      yy)z]Raise NotMasterError on unacknowledged write if this socket is not
        writable.
        z
not masterr   i{'  )okerrmsgcodeN)r  r    )r   rS  s     r4   r]  z!SocketInfo._raise_if_not_writable  s4     $"2"2 <0@ A A #3>rG   c                     | j                  |        | j                  ||       |r?| j                  |      }t        j                  |j                         | j                        S y)a  Send OP_INSERT, etc., optionally returning response as a dict.

        Can raise ConnectionFailure or OperationFailure.

        :Parameters:
          - `request_id`: an int.
          - `msg`: bytes, an OP_INSERT, OP_UPDATE, or OP_DELETE message,
            perhaps with a getlasterror command appended.
          - `max_doc_size`: size in bytes of the largest document in `msg`.
          - `with_last_error`: True if a getlasterror command is appended.
        N)r]  ro  r(   r   _check_gle_responsecommand_responser  )r   rq  r   rn  with_last_errorrH  s         r4   legacy_writezSocketInfo.legacy_write  sf     	##$78#|,((4E..u/E/E/G/3/D/DF F rG   c                     | j                  |d       | j                  |      }|j                         }t        j                  || j
                         |S )zSend "insert" etc. command, returning response as a dict.

        Can raise ConnectionFailure or OperationFailure.

        :Parameters:
          - `request_id`: an int.
          - `msg`: bytes, the command message.
        r   )ro  r(   rx  r   rG  r  )r   rq  r   rH  results        r4   write_commandzSocketInfo.write_command  sO     	#q!$$Z0'') 	''0E0EFrG   c                    |s| j                   rt        t        |            }| j                   j                         }||z
  D ]=  }t	        j
                  |j                  |        | j                   j                  |       ? ||z
  D ]  }| j                  |        | j                  sEd| _	        | j                  r1| j                  j                  | j                  | j                         yyy)a   Update this socket's authentication.

        Log in or out to bring this socket's credentials up to date with
        those provided. Can raise ConnectionFailure or OperationFailure.

        :Parameters:
          - `all_credentials`: dict, maps auth source to MongoCredential.
        TN)r
  r	  r   r   r   logoutr4  discardauthenticater  r  r  publish_connection_readyr3   r  )r   r   cachedr
  r=  s        r4   
check_authzSocketInfo.check_auth  s     dllO45Fll'')G  '/ 2K..5$$[12  &/ /!!+./
 zzDJ$$77dggN % rG   c                     t        j                  ||        | j                  j                  |       | j                  j                  |d       | j                  j                  |d       y)zLog in to the server and store these credentials in `authset`.

        Can raise ConnectionFailure or OperationFailure.

        :Parameters:
          - `credentials`: A MongoCredential.
        N)r   r  r
  addr  popr  )r   r=  s     r4   r  zSocketInfo.authenticate"  sP     	+t,%""&&{D9+t,rG   c                     |r>|j                   |urt        d      |j                  | j                  k7  rt        d      yy)zValidate this session before use with client.

        Raises error if this session is logged in as a different user or
        the client is not the one that created the session.
        z9Can only use session with the MongoClient that started itzBCannot use session after authenticating with different credentialsN)_clientr   _authsetr
  )r   r'  ri  s      r4   rU  zSocketInfo.validate_session0  sU     f,&"# # 4<</&#$ $ 0 rG   c                     | j                   ry| j                          |r?| j                  r2| j                  j	                  | j
                  | j                  |       yyy)z$Close this connection with a reason.N)r  _close_socketr  r  publish_connection_closedr3   r  )r   reasons     r4   close_socketzSocketInfo.close_socket@  sK    ;;d++NN44dggv/ ,6rG   c                     | j                   ryd| _         | j                  r| j                  j                          	 | j                  j	                          y# t
        $ r Y yw xY w)zClose this connection.NT)r  r  r  rg   close	Exceptionr   s    r4   r  zSocketInfo._close_socketI  sS    ;;&&(	IIOO 		s   A 	A#"A#c                 L    | j                   j                  | j                        S )z?Return True if we know socket has been closed, False otherwise.)r  socket_closedrg   r   s    r4   r  zSocketInfo.socket_closedW  s    ""00;;rG   c                 N    | j                   dk\  r|r|j                  ||       yyy)z$Add cluster time for MongoDB >= 3.6.r+  N)r  _send_cluster_time)r   r'   ri  r'  s       r4   r\  zSocketInfo.send_cluster_time[  s*      A%&%%gw7 +1%rG   c                 "    t               | _        y rP   r  r  r   s    r4   update_last_checkin_timez#SocketInfo.update_last_checkin_time`  s    !&rG   c                     || _         y rP   )r  )r   r  s     r4   update_is_writablezSocketInfo.update_is_writablec  s
    &rG   c                 0    t               | j                  z
  S )z9Seconds since this socket was last checked into its pool.r  r   s    r4   idle_time_secondszSocketInfo.idle_time_secondsf  s    w////rG   c                     | j                  t        j                         t        |t        t
        t        f      rt        | j                  |       y  rP   )	r  r&   ERRORr   IOErrorrT   r   r   r3   )r   r:   s     r4   r   z$SocketInfo._raise_connection_failurej  s;     	0667egw	:;%dllE:rG   c                 4    | j                   |j                   k(  S rP   rz   r   others     r4   __eq__zSocketInfo.__eq__  s    yyEJJ&&rG   c                     | |k(   S rP   rI   r  s     r4   __ne__zSocketInfo.__ne__  s    5=  rG   c                 ,    t        | j                        S rP   )hashrg   r   s    r4   __hash__zSocketInfo.__hash__  s    DIIrG   c                 t    dt        | j                        d| j                  xr dxs ddt        |       S )NzSocketInfo()z CLOSED z at )reprrg   r  r  r   s    r4   __repr__zSocketInfo.__repr__  s2    OKK%I++tH
 	
rG   rP   ) r   r   r   __doc__r   r%  r$  rK  r)   PRIMARYr   r'   ro  r(   r]  rz  r}  r  r  rU  r  r  r  r\  r  r  r  r   r  r  r  r  rI   rG   r4   r  r    s    #"JA6p .3 . 6 634!%%!"*/ %#  %W2r2"2AF("O8-$ /<8
)'0*'!
rG   r  c           
         | \  }}|j                  d      rkt        t        d      st        d      t        j                  t        j                        }t        |j                                	 |j                  |       |S t        j                  }t        j                  r|dk7  rt        j                  }d}t        j                  |||t        j                        D ]  }|\  }}	}
}}	 t        j                  ||	t        t        dd      z  |
      }t        |j                                	 |j!                  t        j"                  t        j$                  d       |j'                  |j(                         |j!                  t        j*                  t        j,                  |j.                         |j.                  rt1        |       |j                  |       |c S  ||t        j                  d	      # t        j                  $ r |j                           w xY w# t        j                  $ r t        j                  ||	|
      }Y 8w xY w# t        j                  $ r}|}|j                          Y d}~d}~ww xY w)
zGiven (host, port) and PoolOptions, connect and return a socket object.

    Can raise socket.error.

    This is a modified version of create_connection from CPython >= 2.7.
    z.sockAF_UNIXz-UNIX-sockets are not supported on this system	localhostNSOCK_CLOEXECr   r_   zgetaddrinfo failed)endswithrl   r8   r   r  rF   filenoconnectr:   r  AF_INEThas_ipv6	AF_UNSPECgetaddrinfoSOCK_STREAMrm   rp   ro   TCP_NODELAYr3  r   
SOL_SOCKETSO_KEEPALIVEr   rj   )r3   optionsr   r   rg   familyerrresafsocktypeprotorJ   saes                 r4   _create_connectionr    s    JD$ }}Wvy)# %5 6 6}}V^^,'6	LLK ^^F4;.!!
C!!$ff6H6HI ),&HeUB	6==Hwv~qAA5JD 	(6	OOF..0B0BAFOOG334OOF--v/B/B#446''$T*LLK-6 	 ll/00] || 	JJL	( || 	6 ==Xu5D	6 || 	CJJLL	s7   /G7 +)H.B,I7%H*IIJ #I;;J c                 `   t        | |      }|j                  }|| d   }	 t        r%t        |      rt        r|j                  ||      }n|j                  |      }|j                  r5t        |dd      s(|j                  r	 t        |j!                         |       |j#                  |j$                         |S # t        $ r |j                           t        t        t        f$ r'}|j                          t        | |d       Y d}~d}~ww xY w# t        $ r |j                           w xY w)zGiven (host, port) and PoolOptions, return a configured socket.

    Can raise socket.error, ConnectionFailure, or CertificateError.

    Sets socket's SSL and timeout options.
    Nr   )server_hostnamezSSL handshake failed: check_hostnameF)hostname)r  r   	_HAVE_SNIr5   _IPADDR_SAFEwrap_socketr   r  r  rT   r   r   verify_moderm   r   r,   getpeercertr3  r   )r3   r  rg   r   r   excs         r4   _configured_socketr    s    gw/D%%Kqz	N -"5"..tT.J"..t4 ##%5u=**t//1DA
 	OOG**+K+   	JJL ), 	NJJL &gs4LMM	N $ 

s#   <B; D ;-D(D

DD-c                       e Zd ZdZy)_PoolClosedErrorzZInternal error raised when a thread tries to get a connection from a
    closed pool.
    N)r   r   r   r  rI   rG   r4   r  r    s     	rG   r  c                   ~    e Zd ZddZd Zd Zd Zd Zd ZddZ	e
j                  dd	       Zd
 Zd Zd Zd Zd Zy)Poolc                 j   d| _         t        j                         | _        t	        j
                         | _        d| _        d| _        d| _	        d| _
        d| _        t        j                         | _        || _        || _        || _        | j"                  xr: | j                   j$                  duxr  | j                   j$                  j&                  | _        | j                   j(                  | j                   j*                  d}n-| j                   j*                  | j                   j(                  z  }t-        j.                  | j                   j*                  |      | _        | j&                  rE| j                   j$                  j3                  | j                  | j                   j4                         yy)z
        :Parameters:
          - `address`: a (hostname, port) tuple
          - `options`: a PoolOptions instance
          - `handshake`: whether to call ismaster for each new SocketInfo
        r_   r   FN)_check_interval_secondscollectionsdequesockets	threadingLocklockactive_socketsnext_connection_idr  r  r  r   getpidpidr3   r   r   r   r  r   r   r   create_semaphore_socket_semaphorepublish_pool_createdr   )r   r3   r  r   max_waiterss        r4   r   zPool.__init__  s]    ()$ #((*NN$	"# 99;	"  ;		))5;		)):: 	
 II))1		''/K 		''$))*G*GG  "-!=!=II##["2  II%%::dii;;= !rG   c                    | j                   5  | j                  r
	 d d d        y | xj                  dz  c_        t        j                         | _        | j                  t        j                         c}| _        d| _	        |rd| _        d d d        | j                  j                  }|rOD ]!  }|j                  t        j                         # | j                  r|j!                  | j"                         y y | j                  r|j%                  | j"                         D ]!  }|j                  t        j&                         # y # 1 sw Y   xY w)Nr_   r   T)r  r  r  r   r  r  r  r  r  r  r   r   r  r&   POOL_CLOSEDr  publish_pool_closedr3   publish_pool_clearedSTALE)r   r  r  r  	sock_infos        r4   _resetzPool._reset?  s   YY 	#{{	# 	# OOq Oyy{DH$(LL+2C2C2E!GT\"#D"	# II--	 $ K	&&'='I'IJK$$--dll; % $$..t||<$ E	&&'='C'CDE-	# 	#s   EA$EEc                     || _         | j                  5  | j                  D ]  } |j                  | j                            	 ddd       y# 1 sw Y   yxY w)zXUpdates the is_writable attribute on all sockets currently in the
        Pool.
        N)r  r  r  r  )r   r  r8   s      r4   r  zPool.update_is_writableY  sQ     'YY 	<,, <)))$*:*:;<	< 	< 	<s   .AAc                 (    | j                  d       y )NFr  r  r   s    r4   resetz
Pool.resetb  s    % rG   c                 (    | j                  d       y )NTr  r  r   s    r4   r  z
Pool.closee  s    $rG   c                    | j                   j                  | j                  5  | j                  r| j                  d   j	                         | j                   j                  kD  rz| j                  j                         }|j                  t        j                         | j                  r5| j                  d   j	                         | j                   j                  kD  rzddd       	 | j                  5  t        | j                        | j                  z   | j                   j                  k\  r
	 ddd       y	 ddd       | j                  j                  d      sy	 | j                  |      }| j                  5  | j                  |k7  rC|j                  t        j                          	 ddd       | j                  j#                          y| j                  j%                  |       ddd       | j                  j#                          %# 1 sw Y   0xY w# 1 sw Y   xY w# 1 sw Y   >xY w# | j                  j#                          w xY w)zRemoves stale sockets then adds new ones if pool is too small and
        has not been reset. The `reference_generation` argument specifies the
        `generation` at the point in time this operation was requested on the
        pool.
        Nr   F)r   r   r  r  r  r  r  r&   IDLEr   r  r   r  acquirer  r  r  release
appendleft)r   reference_generationr   r  s       r4   remove_stale_socketszPool.remove_stale_socketsh  s    99**6 H||||B'99;dii>]>]] $ 0 0 2I**+A+F+FG ||||B'99;dii>]>]]H  %(;(;;		//0 	 0 ))11%8
1 LL9	YY 7 *>>!../E/K/KL7 &&..0 LL++I67 &&..0) H H 7 7 &&..0sH   B:H3;HH1 :0H%*H1 H%(H1 HH"%H.*H1 1INc                 F   | j                   5  | j                  }| xj                  dz  c_        ddd       | j                  j                  }| j                  r|j                  | j                         	 t        | j                  | j                        }t#        || | j                        }| j$                  r"|j'                  |       |j(                  | _        	 |j+                  |       |S # 1 sw Y   xY w# t        $ rn}| j                  r+|j                  | j                  t        j                         t        |t        t        t        f      rt!        | j                  |        d}~ww xY w# t        $ r! |j-                  t        j                          w xY w)zConnect to Mongo and return a new SocketInfo.

        Can raise ConnectionFailure or CertificateError.

        Note that the pool does not keep a reference to the socket -- you
        must call return_socket() when you're done with it.
        r_   N)r  r  r   r   r  publish_connection_createdr3   r  r  r  r&   r  r   r  rT   r   r   r  r   r%  r  r  r  )r   r   conn_idr  rg   r:   r  s          r4   r  zPool.connect  s^    YY 	)--G##q(#	) II--	  00wG
	%dllDII>D tT4<<A	>>/(44D	  1
 ?	) 	)  	$$33LL'+A+G+GI %'7I!>?)$,,>	"  	""#9#?#?@	s0   "C06 C< E6 0C9<	E3A)E..E36*F c              #   l  K   | j                   j                  }| j                  r|j                  | j                         | j                  |      }| j                  r&|j                  | j                  |j                         	 | |s| j                  |       yy#  | j                  |        xY ww)a,  Get a socket from the pool. Use with a "with" statement.

        Returns a :class:`SocketInfo` object wrapping a connected
        :class:`socket.socket`.

        This method should always be used in a with-statement::

            with pool.get_socket(credentials, checkout) as socket_info:
                socket_info.send_message(msg)
                data = socket_info.receive_message(op_code, request_id)

        The socket is logged in or out as needed to match ``all_credentials``
        using the correct authentication mechanism for the server's wire
        protocol version.

        Can raise ConnectionFailure or OperationFailure.

        :Parameters:
          - `all_credentials`: dict, maps auth source to MongoCredential.
          - `checkout` (optional): keep socket checked out.
        N)	r   r   r  $publish_connection_check_out_startedr3   _get_socketpublish_connection_checked_outr  return_socket)r   r   checkoutr  r  s        r4   
get_socketzPool.get_socket  s     . II--	  ::4<<H$$_5	  44ill,	.O ""9- 	y)s   BB4B B4B11B4c                    | j                   t        j                         k7  r| j                          | j                  rU| j
                  r>| j                  j                  j                  | j                  t        j                         t        d      | j                  j                  d| j                  j                        s| j!                          d}d}	 | j"                  5  | xj$                  dz  c_        d}ddd       |G	 | j"                  5  | j&                  j)                         }ddd       | j+                  |      rd}	 |G|j1                  |       |S # 1 sw Y   exY w# 1 sw Y   ?xY w# t,        $ r | j/                  |      }Y Jw xY w# t2        $ r |r|j5                  t6        j8                         | j                  j;                          |r7| j"                  5  | xj$                  dz  c_        ddd       n# 1 sw Y   nxY w| j
                  r>| j                  j                  j                  | j                  t        j<                          w xY w)z8Get or create a SocketInfo. Can raise ConnectionFailure.z?Attempted to check out a connection from closed connection poolTNFr_   )r  r   r  r  r  r  r   r   #publish_connection_check_out_failedr3   r%   r  r  r  r  r   _raise_wait_queue_timeoutr  r  r  popleft	_perished
IndexErrorr  r  r  r  r&   r  r  
CONN_ERROR)r   r   r  incrementeds       r4   r  zPool._get_socket  s	   
 88ryy{"JJL;;$$		))MMLL"@"L"LN" 
 %%--dii224**, 		 ###q(#"# #) ;$(LL$8$8$:	; ~~i0$(	 #   1  =# #; ;! > $_ =I>  	&&'='C'CD""**,YY -''1,'- - - $$		))MMLL"@"K"KM	s   F $E <
F E8 E,.E8 6F F  E)%F ,E51E8 8FF FF AI!*H	 	I!	H	AI!c                 H   | j                   j                  }| j                  r&|j                  | j                  |j
                         | j                  t        j                         k7  r| j                          n| j                  r |j                  t        j                         n|j                  s| j                  5  |j                  | j                  k7  r |j                  t        j                          nF|j#                          |j%                  | j&                         | j(                  j+                  |       ddd       | j,                  j/                          | j                  5  | xj0                  dz  c_        ddd       y# 1 sw Y   NxY w# 1 sw Y   yxY w)zReturn the socket to the pool, or if it's closed discard it.

        :Parameters:
          - `sock_info`: The socket to check into the pool.
        Nr_   )r   r   r  publish_connection_checked_inr3   r  r  r   r  r  r  r  r&   r  r  r  r  r  r  r  r  r  r  r  r  )r   r  r  s      r4   r  zPool.return_socket  s1    II--	  33DLL),,O88ryy{"JJL{{&&'='I'IJ%%YY ; !++t>!../E/K/KL!::<!44T5E5EF//	:; 	&&(YY 	%1$	% 	%; ;	% 	%s   ?B F-FFF!c                    |j                         }| j                  j                  9|| j                  j                  kD  r |j                  t        j
                         y| j                  Nd| j                  k(  s|| j                  kD  r0|j                         r |j                  t        j                         y|j                  | j                  k7  r |j                  t        j                         yy)a  Return True and close the connection if it is "perished".

        This side-effecty function checks if this socket has been idle for
        for longer than the max idle time, or if the socket has been closed by
        some external network error, or if the socket's generation is outdated.

        Checking sockets lets us avoid seeing *some*
        :class:`~pymongo.errors.AutoReconnect` exceptions on server
        hiccups, etc. We only check if the socket was closed by an external
        error if it has been > 1 second since the socket was checked into the
        pool, to keep performance reasonable - we can't avoid AutoReconnects
        completely anyway.
        Tr   F)r  r   r   r  r&   r  r  r  r  r  r  )r   r  r  s      r4   r  zPool._perished4  s     &779II++7!DII$C$CC""#9#>#>?((4T111!D$@$@@&&(&&'='C'CD4??2""#9#?#?@rG   c                    | j                   j                  }| j                  r*|j                  | j                  t
        j                         t        d| j                   j                  d| j                   j                        )NzMTimed out while checking out a connection from connection pool with max_size z and wait_queue_timeout )
r   r   r  r  r3   r%   TIMEOUTr   r   r   )r   r  s     r4   r	  zPool._raise_wait_queue_timeoutV  si    II--	  99<DDF 		'')E)EGH 	HrG   c                 H    | j                   D ]  }|j                  d         y rP   )r  r  )r   r  s     r4   __del__zPool.__del__`  s%      	)I""4(	)rG   )TrP   )F)r   r   r   r   r  r  r  r  r  r  
contextlibcontextmanagerr  r  r  r  r	  r  rI   rG   r4   r  r    s`    .=`E4<! !1F'R '. '.R7r%: DH)rG   r  rP   )r  r   r   r   r8   sysr  r  pymongo.ssl_supportr   r   r   r  r   r  bsonr   bson.py3compatr   r   r	   bson.sonr
   pymongor   r   r   r   pymongo.client_sessionr   pymongo.commonr   r   r   r   r   r   r   r   r   pymongo.errorsr   r   r   r   r   r   r   r    r!   r"   pymongo.ismasterr#   pymongo.monotonicr$   r  pymongo.monitoringr%   r&   pymongo.networkr'   r(   pymongo.read_preferencesr)   pymongo.server_typer*   pymongo.socket_checkerr+   pymongo.ssl_match_hostnamer,   	ipaddressr-   r5   ImportErrorrl   r  r?   r@   rA   rB   rF   rb   rd   ry   _winregrQ   rZ   OpenKeyHKEY_LOCAL_MACHINErU   ra   rc   rT   rj   rt   r   
startswithversion_infojoinlinux_distribution_namesystemmachiner  mac_ver	win32_verjava_ver_ver_archsystem_aliasr}   _aliasedpython_implementationr   pypy_version_infoencoder   objectr   r   r   r   r  r  r  r  r  )parts   0r4   <module>rA     sO     	   
  ! !
 ' 5 5  ; ; B0 0 0	* 	* 	* & +8. 3 + 0 5)$R99/    <<7 
(V^^))EG 	NJM#)##H '-c3F'M$		N2?
 s')[)ABCD 	 <<7#
f$5(557A4;?  A B  !	"#		)))+,	$H$$&' IdO 	\\X	"#	"#	)))+, 
$H$$&q)* IdO 	\\W	"#	?8??,.>h.>.>.@ABC	)))+,	CHH/X//1!A678 IdO 	\\V$***,R0E4				D IdO %x$$+8++-/?x/?/?/ACH	"#	HRaLADD4ABC	)))+,	HQK 	 IdO "8!!#..v6HH	'	'	'	)	$sC112	3	$sC,<,<"=>	>	@AIj 	\\V$HH	'	'	'	)	$sC,,-	.	#((OHOO-/?x/?/?/ABC	C	EFIj
  HH	'	'	'	)	$sC,,-	.	01Ij f !.n&& n&b6 Z
 Z
zB1J-`	| 	W) W)E  !v{#	!	%!R  	  	N 	N
  (  '#' 	(RA\ Bsr   6	V  W %W -W- 
W W- W=*X2X!V>=V>WW	WW W*%W- -	W:9W: