
    &g                       % S r SSKJr  SSKrSSKrSSKrSSKJr  SSK	J
r
JrJrJrJrJrJrJrJrJr  SSKJr  SSKJr  SSKJr  SS	KJr  SS
KJrJrJrJrJ r J!r!  SSK"J#r#  SSK$J%r%  SSK&J'r'  SSK(J)r)J*r*  SSK+J,r,  SSK-J.r.  SSK/J0r0  \
(       a  SSK1J2r2  SSK3J4r4  SSK5J6r6  SSK7J8r8J9r9  Sr: " S S5      r; " S S5      r<      S4S jr= " S S5      r> " S S5      r? " S  S!5      r@S5S" jrAS6S# jrB\#\C" S$S%/5      -  rDS&\ES''   S(rFS7S) jrG\" S*5      rH\
(       a  SS+KIJJrJ   " S, S-5      rK " S. S/5      rL " S0 S15      rM " S2 S3\R                  5      rOg)8a  Logical sessions for ordering sequential operations.

.. versionadded:: 3.6

Causally Consistent Reads
=========================

.. code-block:: python

  with client.start_session(causal_consistency=True) as session:
      collection = client.db.collection
      collection.update_one({"_id": 1}, {"$set": {"x": 10}}, session=session)
      secondary_c = collection.with_options(read_preference=ReadPreference.SECONDARY)

      # A secondary read waits for replication of the write.
      secondary_c.find_one({"_id": 1}, session=session)

If `causal_consistency` is True (the default), read operations that use
the session are causally after previous read and write operations. Using a
causally consistent session, an application can read its own writes and is
guaranteed monotonic reads, even when reading from replica set secondaries.

.. seealso:: The MongoDB documentation on `causal-consistency <https://dochub.mongodb.org/core/causal-consistency>`_.

.. _transactions-ref:

Transactions
============

.. versionadded:: 3.7

MongoDB 4.0 adds support for transactions on replica set primaries. A
transaction is associated with a :class:`ClientSession`. To start a transaction
on a session, use :meth:`ClientSession.start_transaction` in a with-statement.
Then, execute an operation within the transaction by passing the session to the
operation:

.. code-block:: python

  orders = client.db.orders
  inventory = client.db.inventory
  with client.start_session() as session:
      with session.start_transaction():
          orders.insert_one({"sku": "abc123", "qty": 100}, session=session)
          inventory.update_one(
              {"sku": "abc123", "qty": {"$gte": 100}},
              {"$inc": {"qty": -100}},
              session=session,
          )

Upon normal completion of ``with session.start_transaction()`` block, the
transaction automatically calls :meth:`ClientSession.commit_transaction`.
If the block exits with an exception, the transaction automatically calls
:meth:`ClientSession.abort_transaction`.

In general, multi-document transactions only support read/write (CRUD)
operations on existing collections. However, MongoDB 4.4 adds support for
creating collections and indexes with some limitations, including an
insert operation that would result in the creation of a new collection.
For a complete description of all the supported and unsupported operations
see the `MongoDB server's documentation for transactions
<http://dochub.mongodb.org/core/transactions>`_.

A session may only have a single active transaction at a time, multiple
transactions on the same session can be executed in sequence.

Sharded Transactions
^^^^^^^^^^^^^^^^^^^^

.. versionadded:: 3.9

PyMongo 3.9 adds support for transactions on sharded clusters running MongoDB
>=4.2. Sharded transactions have the same API as replica set transactions.
When running a transaction against a sharded cluster, the session is
pinned to the mongos server selected for the first operation in the
transaction. All subsequent operations that are part of the same transaction
are routed to the same mongos server. When the transaction is completed, by
running either commitTransaction or abortTransaction, the session is unpinned.

.. seealso:: The MongoDB documentation on `transactions <https://dochub.mongodb.org/core/transactions>`_.

.. _snapshot-reads-ref:

Snapshot Reads
==============

.. versionadded:: 3.12

MongoDB 5.0 adds support for snapshot reads. Snapshot reads are requested by
passing the ``snapshot`` option to
:meth:`~pymongo.mongo_client.MongoClient.start_session`.
If ``snapshot`` is True, all read operations that use this session read data
from the same snapshot timestamp. The server chooses the latest
majority-committed snapshot timestamp when executing the first read operation
using the session. Subsequent reads on this session read from the same
snapshot timestamp. Snapshot reads are also supported when reading from
replica set secondaries.

.. code-block:: python

  # Each read using this session reads data from the same point in time.
  with client.start_session(snapshot=True) as session:
      order = orders.find_one({"sku": "abc123"}, session=session)
      inventory = inventory.find_one({"sku": "abc123"}, session=session)

Snapshot Reads Limitations
^^^^^^^^^^^^^^^^^^^^^^^^^^

Snapshot reads sessions are incompatible with ``causal_consistency=True``.
Only the following read operations are supported in a snapshot reads session:

- :meth:`~pymongo.collection.Collection.find`
- :meth:`~pymongo.collection.Collection.find_one`
- :meth:`~pymongo.collection.Collection.aggregate`
- :meth:`~pymongo.collection.Collection.count_documents`
- :meth:`~pymongo.collection.Collection.distinct` (on unsharded collections)

Classes
=======
    )annotationsN)Mapping)
TYPE_CHECKINGAnyCallableContextManagerr   MutableMappingNoReturnOptionalTypeTypeVar)Binary)Int64)	Timestamp)_csot)ConfigurationErrorConnectionFailureInvalidOperationOperationFailurePyMongoErrorWTimeoutError)_RETRYABLE_ERROR_CODES)_Op)ReadConcern)ReadPreference_ServerMode)SERVER_TYPE)_ConnectionManager)WriteConcern)TracebackType)
Connection)Server)ClusterTime_AddressTc                  v    \ rS rSrSr   S	       S
S jjr\SS j5       r\SS j5       r\SS j5       r	Sr
g)SessionOptions   aH  Options for a new :class:`ClientSession`.

:param causal_consistency: If True, read operations are causally
    ordered within the session. Defaults to True when the ``snapshot``
    option is ``False``.
:param default_transaction_options: The default
    TransactionOptions to use for transactions started on this session.
:param snapshot: If True, then all reads performed using this
    session will read from the same snapshot. This option is incompatible
    with ``causal_consistency=True``. Defaults to ``False``.

.. versionchanged:: 3.12
   Added the ``snapshot`` parameter.
Nc                    U(       a  U(       a  [        S5      eSnOUc  SnXl        Ub/  [        U[        5      (       d  [	        SR                  U5      5      eX l        X0l        g )Nz5snapshot reads do not support causal_consistency=TrueFTzgdefault_transaction_options must be an instance of pymongo.client_session.TransactionOptions, not: {!r})r   _causal_consistency
isinstanceTransactionOptions	TypeErrorformat_default_transaction_options	_snapshot)selfcausal_consistencydefault_transaction_optionssnapshots       gC:\Suresh\moveshuttle\MDcreated\moveengine\venv\Lib\site-packages\pymongo/synchronous/client_session.py__init__SessionOptions.__init__   sr     !()`aa!&'!%#5 &29;MNNKKQ63L  -H)!    c                    U R                   $ )z)Whether causal consistency is configured.)r)   r0   s    r4   r1   !SessionOptions.causal_consistency   s     '''r7   c                    U R                   $ )zgThe default TransactionOptions to use for transactions started on
this session.

.. versionadded:: 3.7
)r.   r9   s    r4   r2   *SessionOptions.default_transaction_options   s     000r7   c                    U R                   $ )z?Whether snapshot reads are configured.

.. versionadded:: 3.12
)r/   r9   s    r4   r3   SessionOptions.snapshot   s     ~~r7   )r)   r.   r/   )NNF)r1   Optional[bool]r2   Optional[TransactionOptions]r3   r?   returnNonerA   bool)rA   r@   )rA   r?   )__name__
__module____qualname____firstlineno____doc__r5   propertyr1   r2   r3   __static_attributes__ r7   r4   r&   r&      sz    " .2DH#(	"*" &B" !	"
 
"0 ( ( 1 1  r7   r&   c                      \ rS rSrSr    S
         SS jjr\SS j5       r\SS j5       r\SS j5       r	\SS j5       r
S	rg)r+      aH  Options for :meth:`ClientSession.start_transaction`.

:param read_concern: The
    :class:`~pymongo.read_concern.ReadConcern` to use for this transaction.
    If ``None`` (the default) the :attr:`read_preference` of
    the :class:`MongoClient` is used.
:param write_concern: The
    :class:`~pymongo.write_concern.WriteConcern` to use for this
    transaction. If ``None`` (the default) the :attr:`read_preference` of
    the :class:`MongoClient` is used.
:param read_preference: The read preference to use. If
    ``None`` (the default) the :attr:`read_preference` of this
    :class:`MongoClient` is used. See :mod:`~pymongo.read_preferences`
    for options. Transactions which read must use
    :attr:`~pymongo.read_preferences.ReadPreference.PRIMARY`.
:param max_commit_time_ms: The maximum amount of time to allow a
    single commitTransaction command to run. This option is an alias for
    maxTimeMS option on the commitTransaction command. If ``None`` (the
    default) maxTimeMS is not used.

.. versionchanged:: 3.9
   Added the ``max_commit_time_ms`` option.

.. versionadded:: 3.7
Nc                   Xl         X l        X0l        X@l        Ub$  [	        U[
        5      (       d  [        SU< 35      eUbD  [	        U[        5      (       d  [        SU< 35      eUR                  (       d  [        SU< 35      eUb$  [	        U[        5      (       d  [        U< S35      eUb-  [	        U[        5      (       d  [        S[        U5       35      eg g )NzKread_concern must be an instance of pymongo.read_concern.ReadConcern, not: zNwrite_concern must be an instance of pymongo.write_concern.WriteConcern, not: z:transactions do not support unacknowledged write concern: zR is not valid for read_preference. See pymongo.read_preferences for valid options.z3max_commit_time_ms must be an integer or None, not )_read_concern_write_concern_read_preference_max_commit_time_msr*   r   r,   r   acknowledgedr   r   inttype)r0   read_concernwrite_concernread_preferencemax_commit_time_mss        r4   r5   TransactionOptions.__init__  s    *+ /#5 #lK88>>J=MO  $m\::@@M?PR  !--(&)+  &o{;;&) *  
 )0#66I$OaJbIcd  7 *r7   c                    U R                   $ )z>This transaction's :class:`~pymongo.read_concern.ReadConcern`.)rP   r9   s    r4   rW   TransactionOptions.read_concern<  s     !!!r7   c                    U R                   $ )z@This transaction's :class:`~pymongo.write_concern.WriteConcern`.)rQ   r9   s    r4   rX    TransactionOptions.write_concernA  s     """r7   c                    U R                   $ )zEThis transaction's :class:`~pymongo.read_preferences.ReadPreference`.)rR   r9   s    r4   rY   "TransactionOptions.read_preferenceF  s     $$$r7   c                    U R                   $ )zVThe maxTimeMS to use when running a commitTransaction command.

.. versionadded:: 3.9
)rS   r9   s    r4   rZ   %TransactionOptions.max_commit_time_msK  s     '''r7   )rS   rP   rR   rQ   NNNN)
rW   Optional[ReadConcern]rX   Optional[WriteConcern]rY   Optional[_ServerMode]rZ   Optional[int]rA   rB   )rA   re   )rA   rf   rA   rg   )rA   rh   )rE   rF   rG   rH   rI   r5   rJ   rW   rX   rY   rZ   rK   rL   r7   r4   r+   r+      s    8 /30415,0'+' .' /	'
 *' 
'R " " # # % % ( (r7   r+   c                ~    U (       a5  Ub2  UR                   (       d!  U R                  (       a  g[        SU< 35      eU $ )zzValidate that an explicit session is not used with an unack'ed write.

Returns the session to use for the next operation.
NzFExplicit sessions are incompatible with unacknowledged write concern: )rT   	_implicitr   )sessionrX   s     r4   _validate_session_write_concernrm   T  sH     $]-G-G   (55B4EG  Nr7   c                  F    \ rS rSrSrSS jrS	S jr        S
S jrSrg)_TransactionContextil  z;Internal transaction context manager for start_transaction.c                    Xl         g N)_TransactionContext__session)r0   rl   s     r4   r5   _TransactionContext.__init__o  s     r7   c                    U $ rq   rL   r9   s    r4   	__enter___TransactionContext.__enter__r      r7   c                    U R                   R                  (       a9  Uc  U R                   R                  5         g U R                   R                  5         g g rq   )rr   in_transactioncommit_transactionabort_transactionr0   exc_typeexc_valexc_tbs       r4   __exit___TransactionContext.__exit__u  s;     >>((113002	 )r7   )	__sessionN)rl   ClientSession)rA   ro   )r}   zOptional[Type[BaseException]]r~   zOptional[BaseException]r   zOptional[TracebackType]rA   rB   )	rE   rF   rG   rH   rI   r5   ru   r   rK   rL   r7   r4   ro   ro   l  s:    E!
3/
3 )
3 (	
3
 

3r7   ro   c                  ,    \ rS rSrSrSrSrSrSrSr	Sr
g	)
	_TxnStatei                    rL   N)rE   rF   rG   rH   NONESTARTINGIN_PROGRESS	COMMITTEDCOMMITTED_EMPTYABORTEDrK   rL   r7   r4   r   r     s     DHKIOGr7   r   c                  r    \ rS rSrSrSS jrSS jrSS jr\SS j5       r	SS jr
SS jrSS	 jrSS
 jrSrg)_Transactioni  zBInternal class to hold transaction information in a ClientSession.c                    Xl         [        R                  U l        SU l        S U l        S U l        S U l        SU l        X l	        g NFr   )
optsr   r   stateshardedpinned_addressconn_mgrrecovery_tokenattemptclient)r0   r   r   s      r4   r5   _Transaction.__init__  s<    	^^
266:"r7   c                \    U R                   [        R                  [        R                  4;   $ rq   )r   r   r   r   r9   s    r4   active_Transaction.active  s"    zzi00)2G2GHHHr7   c                <    U R                   [        R                  :H  $ rq   )r   r   r   r9   s    r4   starting_Transaction.starting  s    zzY////r7   c                |    U R                  5       (       a'  U R                  (       a  U R                  R                  $ g rq   )r   r   connr9   s    r4   pinned_conn_Transaction.pinned_conn  s&    ;;==T]]==%%%r7   c                    SU l         UR                  R                  U l        UR                  R                  [
        R                  :X  a"  UR                  5         [        US5      U l	        g g )NTF)
r   descriptionaddressr   server_typer   LoadBalancerpin_txnr   r   r0   serverr   s      r4   pin_Transaction.pin  sT    $0088))[-E-EELLN.tU;DM Fr7   c                v    S U l         U R                  (       a  U R                  R                  5         S U l        g rq   )r   r   closer9   s    r4   unpin_Transaction.unpin  s(    "==MM!r7   c                x    U R                  5         [        R                  U l        SU l        S U l        SU l        g r   )r   r   r   r   r   r   r   r9   s    r4   reset_Transaction.reset  s,    

^^
"r7   c                    U R                   (       a/  U R                  R                  SS U R                   5        S U l         g g Nr   )r   r   _close_cursor_soonr9   s    r4   __del___Transaction.__del__  s1    == KK**1dDMMB DM	 r7   )r   r   r   r   r   r   r   r   N)r   r@   r   MongoClientrC   rA   zOptional[Connection]r   r"   r   r!   rA   rB   rA   rB   )rE   rF   rG   rH   rI   r5   r   r   rJ   r   r   r   r   r   rK   rL   r7   r4   r   r     s=    LI0  
<!r7   r   c                &    U R                  S5        e )zDRe-raise an exception with the UnknownTransactionCommitResult label.UnknownTransactionCommitResult)_add_error_labelexcs    r4   _reraise_with_unknown_commitr     s    9:	r7   c                N    [        U [        5      =(       a    U R                  S:H  $ )z/Return true if exc is a MaxTimeMSExpired error.2   )r*   r   coder   s    r4   _max_time_expired_errorr     s    c+,?R?r7   @   r   	frozenset_UNKNOWN_COMMIT_ERROR_CODESx   c                @    [         R                  " 5       U -
  [        :  $ )z/Are we within the with_transaction retry limit?)time	monotonic"_WITH_TRANSACTION_RETRY_TIME_LIMIT)
start_times    r4   _within_time_limitr     s    >>j(+MMMr7   _T)r   c                  n   \ rS rSrSr          S+S jrS,S jrS-S jrS,S jrS,S jr	S.S jr
S/S	 jr\S0S
 j5       r\S1S j5       r\S2S j5       r\S3S j5       r\S4S j5       r\S5S j5       rS6S jr    S7           S8S jjr    S7         S9S jjrS,S jrS,S jrS:S jrS;S jrS<S jrS=S jrS>S jrS?S jrS@S jr\SAS j5       r\SAS j5       r \SAS j5       r!\SBS  j5       r"\SCS! j5       r#SDS" jr$S,S# jr%SES$ jr&SFSGS% jjr'          SHS& jr(S,S' jr)SIS( jr*SJS) jr+S*r,g)Kr   i  a  A session for ordering sequential operations.

:class:`ClientSession` instances are **not thread-safe or fork-safe**.
They can only be used by one thread or process at a time. A single
:class:`ClientSession` cannot be used to run multiple operations
concurrently.

Should not be initialized directly by application developers - to create a
:class:`ClientSession`, call
:meth:`~pymongo.mongo_client.MongoClient.start_session`.
c                    Xl         X l        X0l        S U l        S U l        S U l        X@l        [        S U5      U l        g rq   )	_client_server_session_options_cluster_time_operation_time_snapshot_timerk   r   _transaction)r0   r   server_sessionoptionsimplicits        r4   r5   ClientSession.__init__  s@     %+-:>48"!(v6r7   c                "    U R                  SS9  g)z}Finish this session. If a transaction has started, abort it.

It is an error to use the session after the session has ended.
TlockN_end_sessionr9   s    r4   end_sessionClientSession.end_session  s    
 	t$r7   c                >   U R                   b_   U R                  (       a  U R                  5         U R                  5         U R                  R                  U R                   5        S U l         g g ! U R                  R                  U R                   5        S U l         f = frq   )r   ry   r{   _unpinr   _return_server_session)r0   r   s     r4   r   ClientSession._end_session  s|    +,&&**, 33D4H4HI'+$ , 33D4H4HI'+$s   1A. ..Bc                x    U R                   b-  U R                  R                  U R                   5        S U l         g g rq   )r   r   r   r9   s    r4   _end_implicit_session#ClientSession._end_implicit_session  s3    +LL//0D0DE#'D  ,r7   c                4    U R                   c  [        S5      eg )NzCannot use ended session)r   r   r9   s    r4   _check_endedClientSession._check_ended  s    '"#=>> (r7   c                    U $ rq   rL   r9   s    r4   ru   ClientSession.__enter__"  rw   r7   c                "    U R                  SS9  g )NTr   r   r|   s       r4   r   ClientSession.__exit__%  s    t$r7   c                    U R                   $ )zNThe :class:`~pymongo.mongo_client.MongoClient` this session was
created from.
)r   r9   s    r4   r   ClientSession.client(  s    
 ||r7   c                    U R                   $ )z:The :class:`SessionOptions` this session was created with.)r   r9   s    r4   r   ClientSession.options/  s     }}r7   c                    U R                  5         U R                  U R                  R                  R                  5        U R
                  R                  $ )z6A BSON document, the opaque server session identifier.)r   _materializer   topology_descriptionlogical_session_timeout_minutesr   
session_idr9   s    r4   r  ClientSession.session_id4  s@     	$,,;;[[\##...r7   c                    U R                  U R                  R                  R                  5        U R                  R
                  $ )z=The current transaction id for the underlying server session.)r   r   r   r  r   transaction_idr9   s    r4   _transaction_idClientSession._transaction_id;  s4     	$,,;;[[\##222r7   c                    U R                   $ )zJThe cluster time returned by the last operation executed
in this session.
r   r9   s    r4   cluster_timeClientSession.cluster_timeA  s    
 !!!r7   c                    U R                   $ )zLThe operation time returned by the last operation executed
in this session.
r   r9   s    r4   operation_timeClientSession.operation_timeH  s    
 ###r7   c                    U(       a  U$ U R                   R                  nU=(       a    [        X15      nU(       a  U$ [        U R                  U5      $ )z-Return the inherited TransactionOption value.)r   r2   getattrr   )r0   namevaltxn_opts
parent_vals        r4   _inherit_optionClientSession._inherit_optionO  sB    J<<;;9'("9
t{{D))r7   Nc                   [         R                  " 5       n U R                  X#XE5         U" U 5      nU R                  (       d  U$   U R                  5         U$ ! [         ah  nU R                  (       a  U R                  5         [        U[        5      (       a,  UR                  S5      (       a  [        U5      (       a   SnAM  e SnAff = f! [         am  nUR                  S5      (       a&  [        U5      (       a  [        U5      (       d   SnAM  UR                  S5      (       a  [        U5      (       a   SnAO	e SnAff = fGM4  )a  Execute a callback in a transaction.

This method starts a transaction on this session, executes ``callback``
once, and then commits the transaction. For example::

  def callback(session):
      orders = session.client.db.orders
      inventory = session.client.db.inventory
      orders.insert_one({"sku": "abc123", "qty": 100}, session=session)
      inventory.update_one({"sku": "abc123", "qty": {"$gte": 100}},
                           {"$inc": {"qty": -100}}, session=session)

  with client.start_session() as session:
      session.with_transaction(callback)

To pass arbitrary arguments to the ``callback``, wrap your callable
with a ``lambda`` like this::

  def callback(session, custom_arg, custom_kwarg=None):
      # Transaction operations...

  with client.start_session() as session:
      session.with_transaction(
          lambda s: callback(s, "custom_arg", custom_kwarg=1))

In the event of an exception, ``with_transaction`` may retry the commit
or the entire transaction, therefore ``callback`` may be invoked
multiple times by a single call to ``with_transaction``. Developers
should be mindful of this possibility when writing a ``callback`` that
modifies application state or has any other side-effects.
Note that even when the ``callback`` is invoked multiple times,
``with_transaction`` ensures that the transaction will be committed
at-most-once on the server.

The ``callback`` should not attempt to start new transactions, but
should simply run operations meant to be contained within a
transaction. The ``callback`` should also not commit the transaction;
this is handled automatically by ``with_transaction``. If the
``callback`` does commit or abort the transaction without error,
however, ``with_transaction`` will return without taking further
action.

:class:`ClientSession` instances are **not thread-safe or fork-safe**.
Consequently, the ``callback`` must not attempt to execute multiple
operations concurrently.

When ``callback`` raises an exception, ``with_transaction``
automatically aborts the current transaction. When ``callback`` or
:meth:`~ClientSession.commit_transaction` raises an exception that
includes the ``"TransientTransactionError"`` error label,
``with_transaction`` starts a new transaction and re-executes
the ``callback``.

When :meth:`~ClientSession.commit_transaction` raises an exception with
the ``"UnknownTransactionCommitResult"`` error label,
``with_transaction`` retries the commit until the result of the
transaction is known.

This method will cease retrying after 120 seconds has elapsed. This
timeout is not configurable and any exception raised by the
``callback`` or by :meth:`ClientSession.commit_transaction` after the
timeout is reached will be re-raised. Applications that desire a
different timeout duration should not use this method.

:param callback: The callable ``callback`` to run inside a transaction.
    The callable must accept a single argument, this session. Note,
    under certain error conditions the callback may be run multiple
    times.
:param read_concern: The
    :class:`~pymongo.read_concern.ReadConcern` to use for this
    transaction.
:param write_concern: The
    :class:`~pymongo.write_concern.WriteConcern` to use for this
    transaction.
:param read_preference: The read preference to use for this
    transaction. If ``None`` (the default) the :attr:`read_preference`
    of this :class:`Database` is used. See
    :mod:`~pymongo.read_preferences` for options.

:return: The return value of the ``callback``.

.. versionadded:: 3.9
TransientTransactionErrorNr   )r   r   start_transactionBaseExceptionry   r{   r*   r   has_error_labelr   rz   r   )	r0   callbackrW   rX   rY   rZ   r   retr   s	            r4   with_transactionClientSession.with_transactionY  s&   v ^^%
""<dtn &&
++-$ 
I ! 
&&**,sL11++,GHH*:66 
& $ ++,LMM.z:: 7 < < !**+FGGL^"M M 1 sB   A C 
C#ACCC
E6E &E ?E  Ec                H   U R                  5         U R                  R                  (       a  [        S5      eU R                  (       a  [        S5      eU R                  SU5      nU R                  SU5      nU R                  SU5      nUc)  U R                  R                  nU(       a  UR                  n[        XX45      U R                  l
        U R                  R                  5         [        R                  U R                  l        U R                  5         [!        U 5      $ )zStart a multi-statement transaction.

Takes the same arguments as :class:`TransactionOptions`.

.. versionchanged:: 3.9
   Added the ``max_commit_time_ms`` option.

.. versionadded:: 3.7
z3Transactions are not supported in snapshot sessionszTransaction already in progressrW   rX   rY   )r   r   r3   r   ry   r  r2   rZ   r+   r   r   r   r   r   r   _start_retryable_writero   )r0   rW   rX   rY   rZ   r   s         r4   r  ClientSession.start_transaction  s      	<<  "#XYY"#DEE++NLI,,_mL../@/R%<<;;D%)%<%<"!3"
 	!"+"4"4##%"4((r7   c                b   U R                  5         U R                  R                  nU[        R                  L a  [        S5      eU[        R                  [        R                  4;   a   [        R                  U R                  l        gU[        R                  L a  [        S5      eU[        R                  L a  [        R                  U R                  l         U R                  S5        [        R                  U R                  l        g! [         a&  nUR                  S5        [        U5         SnANKSnAf[         a  n[        U5         SnANhSnAf[          a*  nUR"                  [$        ;  a  e [        U5         SnANSnAff = f! [        R                  U R                  l        f = f)z=Commit a multi-statement transaction.

.. versionadded:: 3.7
No transaction startedNz<Cannot call commitTransaction after calling abortTransactioncommitTransactionr  )r   r   r   r   r   r   r   r   r   r   r   _finish_transaction_with_retryr   _remove_error_labelr   r   r   r   r   )r0   r   r   s      r4   rz    ClientSession.commit_transaction  sR   
 	!!''INN""#;<<y))9+D+DEE&/&?&?D#i'''"#abbi))) '0&;&;D#	://0CD( '0&9&9D#' ! 	. ##$?@(-- 	. )-- 	.xx:: )--	. '0&9&9D#sN   D 
F
D61F 6F
EF F
  F F F

F !F.c                   U R                  5         U R                  R                  nU[        R                  L a  [        S5      eU[        R                  L a   [        R                  U R                  l        gU[        R                  L a  [        S5      eU[        R                  [        R                  4;   a  [        S5      e U R                  S5        [        R                  U R                  l        U R                  5         g! [        [        4 a     NBf = f! [        R                  U R                  l        U R                  5         f = f)z<Abort a multi-statement transaction.

.. versionadded:: 3.7
r%  Nz"Cannot call abortTransaction twicez<Cannot call abortTransaction after calling commitTransactionabortTransaction)r   r   r   r   r   r   r   r   r   r   r'  r   r   r   )r0   r   s     r4   r{   ClientSession.abort_transaction3  s
   
 	!!''INN""#;<<i(((&/&7&7D#i'''"#GHHy**I,E,EFF"#abb	//0BC
 '0&7&7D#KKM !"34 		 '0&7&7D#KKMs$   D DD DD 1Ec                ~   ^ ^         SUU 4S jjnT R                   R                  UT SS[        R                  S9$ )zRun commit or abort with one retry after any retryable error.

:param command_name: Either "commitTransaction" or "abortTransaction".
c                (   > TR                  UT5      $ rq   )_finish_transaction)_sessionr   
_retryablecommand_namer0   s      r4   func:ClientSession._finish_transaction_with_retry.<locals>.funcU  s     ++D,??r7   NT)	retryable	operation)r0  Optional[ClientSession]r   r!   r1  rD   rA   dict[str, Any])r   _retry_internalr   ABORT)r0   r2  r3  s   `` r4   r'  ,ClientSession._finish_transaction_with_retryO  s\    	@-	@5?	@MQ	@	@ 	@
 ||++D$X[XaXa+bbr7   c                j   U R                   =R                  S-  sl        U R                   R                  nU(       d   eUR                  nUS0nUS:X  a  UR                  (       a%  [
        R                  " 5       c  UR                  US'   U R                   R                  S:  a7  U(       d   eUR                  nSUS'   UR                  SS5        [        S0 UD6nU R                   R                  (       a  U R                   R                  US'   U R                  R                  R                  XXS	S
9$ )Nr   r&  	maxTimeMSmajoritywwtimeouti'  recoveryTokenT)rl   rX   parse_write_concern_errorrL   )r   r   r   rX   rZ   r   get_timeoutdocument
setdefaultr   r   r   admin_command)r0   r   r2  r   wccmdwc_docs          r4   r/  !ClientSession._finish_transaction\  s   !!Q&!  %%tQ..&&5+<+<+>+F#'#:#:K 
   ((1,	r(s!!*e4!+F+++#'#4#4#C#CC ||!!**tQU + 
 	
r7   c                n    U R                   c  Xl         gUb  US   U R                   S   :  a  Xl         ggg)zInternal cluster time helper.NclusterTimer	  r0   r
  s     r4   _advance_cluster_time#ClientSession._advance_cluster_timew  sC    %!-%M*T-?-?-NN%1" O &r7   c                    [        U[        5      (       d  [        S[        U5       35      e[        UR	                  S5      [
        5      (       d  [        S5      eU R                  U5        g)zUpdate the cluster time for this session.

:param cluster_time: The
    :data:`~pymongo.client_session.ClientSession.cluster_time` from
    another `ClientSession` instance.
z<cluster_time must be a subclass of collections.Mapping, not rM  zInvalid cluster_timeN)r*   _Mappingr,   rV   getr   
ValueErrorrO  rN  s     r4   advance_cluster_time"ClientSession.advance_cluster_time  sc     ,11NtT`OaNbc  ,**=99EE344""<0r7   c                `    U R                   c  Xl         gUb  XR                   :  a  Xl         ggg)zInternal operation time helper.Nr  r0   r  s     r4   _advance_operation_time%ClientSession._advance_operation_time  s6    '#1 ' 4 44'5$ 5 (r7   c                ~    [        U[        5      (       d  [        S[        U5       35      eU R	                  U5        g)zUpdate the operation time for this session.

:param operation_time: The
    :data:`~pymongo.client_session.ClientSession.operation_time` from
    another `ClientSession` instance.
zDoperation_time must be an instance of bson.timestamp.Timestamp, not N)r*   r   r,   rV   rY  rX  s     r4   advance_operation_time$ClientSession.advance_operation_time  s@     .)44VW[\jWkVlm  	$$^4r7   c                   U R                  UR                  S5      5        U R                  UR                  S5      5        U R                  R                  (       a?  U R
                  c2  SU;   a  US   R                  S5      nOUR                  S5      nX l        U R                  (       aF  U R                  R                  (       a*  UR                  S5      nU(       a  X0R                  l	        gggg)z?Process a response to a command that was run with this session.z$clusterTimeoperationTimeNcursoratClusterTimerA  )
rO  rS  rY  r   r3   r   ry   r   r   r   )r0   replyctr   s       r4   _process_responseClientSession._process_response  s    ""599^#<=$$UYY%?@==!!d&9&9&A5 8_((9YY/"$4#4#4#<#<"YY7N3A!!0  $=r7   c                    U R                   SL $ )z!True if this session is finished.N)r   r9   s    r4   	has_endedClientSession.has_ended  s     ##t++r7   c                6    U R                   R                  5       $ )zXTrue if this session has an active multi-statement transaction.

.. versionadded:: 3.10
)r   r   r9   s    r4   ry   ClientSession.in_transaction  s       ''))r7   c                6    U R                   R                  5       $ )z?True if this session is starting a multi-statement transaction.)r   r   r9   s    r4   _starting_transaction#ClientSession._starting_transaction  s       ))++r7   c                n    U R                   R                  5       (       a  U R                   R                  $ g)z3The mongos address this transaction was created on.N)r   r   r   r9   s    r4   _pinned_addressClientSession._pinned_address  s.     ##%%$$333r7   c                .    U R                   R                  $ )z/The connection this transaction was started on.)r   r   r9   s    r4   _pinned_connection ClientSession._pinned_connection  s       ,,,r7   c                :    U R                   R                  X5        g)z@Pin this session to the given Server or to the given connection.N)r   r   r   s      r4   _pinClientSession._pin  s    f+r7   c                8    U R                   R                  5         g)z*Unpin this session from any pinned Server.N)r   r   r9   s    r4   r   ClientSession._unpin  s    !r7   c                    U R                   (       a=  U R                  R                  (       d   eU R                  R                  R                  $ g)z3Return read preference of this transaction or None.N)ry   r   r   rY   r9   s    r4   _txn_read_preference"ClientSession._txn_read_preference  s;    $$))))$$))999r7   c                   [        U R                  [        5      (       ac  U R                  nU R                  R                  R                  U5      U l        UR                  (       a  U R                  R                  5         g g g rq   )r*   r   _EmptyServerSessionr   	_topologyget_server_sessionstarted_retryable_writeinc_transaction_id)r0   r  olds      r4   r   ClientSession._materialize  si    d**,?@@&&C#'<<#9#9#L#L/$D  **$$779 + Ar7   c                   UR                   (       d  U R                  (       d  [        S5      eg U R                  5         U R	                  UR
                  5        U R                  R                  (       a  U R                  X5        [        R                  " 5       U R                  l        U R                  R                  US'   U(       a  U R                  R                  US'   g U R                  (       Ga  U[         R"                  :w  a  [%        SU< 35      eU R&                  R(                  [*        R,                  :X  a  [*        R.                  U R&                  l        SUS'   U R&                  R0                  (       d   eU R&                  R0                  R2                  (       a5  U R&                  R0                  R2                  R4                  nU(       a  XQS'   U R                  X5        U R                  R                  US'   SUS	'   g g )
Nz5Sessions are not supported by this MongoDB deploymentlsid	txnNumberz7read preference in a transaction must be primary, not: TstartTransactionreadConcernF
autocommit)supports_sessionsrk   r   r   r   r  r   r3   _update_read_concernr   r   r   last_user  r  ry   r   PRIMARYr   r   r   r   r   r   r   rW   rD  )r0   commandis_retryablerY   r   rcs         r4   	_apply_toClientSession._apply_to  s    %%>>()`aa$>>?<<  %%g4(,(8%..99#'#7#7#F#FGK ."8"88&MoM`a    &&)*<*<<*3*?*?!!'.2*+((----$$))66**//<<EEB13.))'8#'#7#7#F#FGK $)GL!' r7   c                X    U R                  5         U R                  R                  5         g rq   )r   r   r  r9   s    r4   r"  $ClientSession._start_retryable_write  s     //1r7   c                h   U R                   R                  (       a,  U R                  b  U R                  UR                  S0 5      S'   U R                   R                  (       aP  UR
                  S:  a  [        S5      eUR                  S0 5      nSUS'   U R                  b  U R                  US'   g g g )Nr  afterClusterTime   z+Snapshot reads require MongoDB 5.0 or laterr3   levelra  )r   r1   r  rE  r3   max_wire_versionr   r   )r0   rI  r   r  s       r4   r  "ClientSession._update_read_concern  s    <<**t/B/B/NDHDWDWCNN="-.@A<<  $$r)()VWWr2B$BwK"".&*&9&9?# / !r7   c                    [        S5      e)Nz>A ClientSession cannot be copied, create a new session instead)r,   r9   s    r4   __copy__ClientSession.__copy__#  s    XYYr7   )r   r   rk   r   r   r   r   r   )
r   r   r   r   r   r&   r   rD   rA   rB   r   )r   rD   rA   rB   )rA   r   )r}   r   r~   r   r   r   rA   rB   )rA   r   )rA   r&   )rA   Mapping[str, Any]rA   r   )rA   zOptional[ClusterTime])rA   Optional[Timestamp])r  strr  r   rA   r   rd   )r  zCallable[[ClientSession], _T]rW   re   rX   rf   rY   rg   rZ   rh   rA   r   )
rW   re   rX   rf   rY   rg   rZ   rh   rA   r   )r2  r  rA   r8  )r   r!   r2  r  rA   r8  )r
  zOptional[Mapping[str, Any]]rA   rB   )r
  r  rA   rB   )r  r  rA   rB   )r  r   rA   rB   )rb  r  rA   rB   rC   )rA   zOptional[_Address]r   r   ri   rq   )r  rh   rA   rB   )
r  MutableMapping[str, Any]r  rD   rY   r   r   r!   rA   rB   )rI  r  r   r!   rA   rB   )rA   r
   )-rE   rF   rG   rH   rI   r5   r   r   r   r   ru   r   rJ   r   r   r  r  r
  r  r  r  r  rz   r{   r'  r/  rO  rU  rY  r\  rd  rg  ry   rl  ro  rr  ru  r   rz  r   r  r"  r  r  rK   rL   r7   r4   r   r     s^   
77 7  	7
 7 
7$%
,(?%     / / 3 3
 " " $ $* /30415,0E/E ,E .	E
 /E *E 
ER /30415,0&)+&) .&) /	&)
 *&) 
&)P):V8c
62165B , , * * , ,   - -,":**)** ** %	**
 ** 
**X2	:Zr7   r   c                  6    \ rS rSrSrSS jrSS jrSS jrSrg)r}  i'  dirtyr  c                     SU l         SU l        g )NFr  r9   s    r4   r5   _EmptyServerSession.__init__*  s    
',$r7   c                    SU l         g NTr  r9   s    r4   
mark_dirty_EmptyServerSession.mark_dirty.  s	    
r7   c                    SU l         g r  )r  r9   s    r4   r  &_EmptyServerSession.inc_transaction_id1  s
    '+$r7   Nr   )	rE   rF   rG   rH   	__slots__r5   r  r  rK   rL   r7   r4   r}  r}  '  s    2I-,r7   r}  c                  P    \ rS rSrS	S jrS
S jrSS jr\SS j5       rS
S jr	Sr
g)_ServerSessioni5  c                    S[        [        R                  " 5       R                  S5      0U l        [
        R                  " 5       U l        SU l        SU l	        Xl
        g )Nidr   r   F)r   uuiduuid4bytesr  r   r   r  r  r  
generation)r0   r  s     r4   r5   _ServerSession.__init__6  sC    

(:(:A!>?( 
$r7   c                    SU l         g)zMark this session as dirty.

A server session is marked dirty when a command fails with a network
error. Dirty sessions are later discarded from the server session pool.
TNr  r9   s    r4   r  _ServerSession.mark_dirty>  s     
r7   c                b    Uc  g[         R                  " 5       U R                  -
  nX!S-
  S-  :  $ )NFr   <   )r   r   r  )r0   session_timeout_minutesidle_secondss      r4   	timed_out_ServerSession.timed_outF  s5    "*~~'$--7 :b@@@r7   c                ,    [        U R                  5      $ )zPositive 64-bit integer.)r   r  r9   s    r4   r  _ServerSession.transaction_idO  s     T))**r7   c                .    U =R                   S-  sl         g Nr   )r  r9   s    r4   r  !_ServerSession.inc_transaction_idT  s    !r7   )r  r  r  r  r  N)r  rU   r   )r  rh   rA   rD   r  )rE   rF   rG   rH   r5   r  r  rJ   r  r  rK   rL   r7   r4   r  r  5  s+    %A + +"r7   r  c                  b   ^  \ rS rSrSrS
U 4S jjrSS jrSS jrSS jrSS jr	SS jr
S	rU =r$ )_ServerSessionPooliX  z<Pool of _ServerSession objects.

This class is thread-safe.
c                4   > [         TU ]  " U0 UD6  SU l        g r   )superr5   r  )r0   argskwargs	__class__s      r4   r5   _ServerSessionPool.__init__^  s    $)&)r7   c                N    U =R                   S-  sl         U R                  5         g r  )r  clearr9   s    r4   r   _ServerSessionPool.resetb  s    1

r7   c                    / n  UR                  U R                  5       R                  5        M,  ! [         a     U$ f = frq   )appendpopr  
IndexError)r0   idss     r4   pop_all_ServerSessionPool.pop_allf  sE    

488:001   
s   )0 
>>c                    U R                  U5          U R                  5       nUR                  U5      (       d  U$ M+  ! [         a     Of = f[	        U R
                  5      $ rq   )_clear_stalepopleftr  r  r  r  r0   r  ss      r4   r  %_ServerSessionPool.get_server_sessiono  si     	12 LLN ;;677   
 doo..s   > 
A
Ac                    UR                   U R                   :X  a$  UR                  (       d  U R                  U5        g g g rq   )r  r  
appendleft)r0   r   s     r4   return_server_session(_ServerSessionPool.return_server_session  s4     $$7@T@TOON+ AU7r7   c                      U R                  5       nUR                  U5      (       d  U R                  U5        g M;  ! [         a     g f = frq   )r  r  r  r  r  s      r4   r  _ServerSessionPool._clear_stale  sN    HHJ ;;677A   s   = 
A
	A
)r  )r  r   r  r   r   )rA   zlist[_ServerSession])r  rh   rA   r  )r   r  rA   rB   )r  rh   rA   rB   )rE   rF   rG   rH   rI   r5   r   r  r  r  r  rK   __classcell__)r  s   @r4   r  r  X  s+    
/&,
 
r7   r  )rl   r7  rX   rf   rA   r7  )r   r   rA   r
   )r   r   rA   rD   )r   floatrA   rD   )PrI   
__future__r   collectionsr   r  collections.abcr   rR  typingr   r   r   r   r	   r
   r   r   r   bson.binaryr   
bson.int64r   bson.timestampr   pymongor   pymongo.errorsr   r   r   r   r   r   pymongo.helpers_sharedr   pymongo.operationsr   pymongo.read_concernr   pymongo.read_preferencesr   r   pymongo.server_typer   pymongo.synchronous.cursorr   pymongo.write_concernr   typesr    pymongo.synchronous.poolr!   pymongo.synchronous.serverr"   pymongo.typingsr#   r$   _IS_SYNCr&   r+   rm   ro   r   r   r   r   r   r   __annotations__r   r   r    pymongo.synchronous.mongo_clientr   r   r}  r  dequer  rL   r7   r4   <module>r     sK  wr #    /     $   : " , @ + 9 .#315< <~Y( Y(x$5K03 3, 2! 2!j
@ *@)

C * Y  &) "N
 T]<~Z ~ZB, , "  "F:** :r7   