
    9hK                       S r SSKrSSKrSSKrSSKrSSKrSSKrSSKrSSKrSSK	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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  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r. SSK/r/Sr1S r2S r3 " S S5      r4 " S S\45      r5 " S S\55      r6 " S S5      r7 " S S\45      r8 " S  S!\55      r9 " S" S#\55      r: " S$ S%\45      r; " S& S'\;5      r< " S( S)\<5      r= " S* S+\;5      r> " S, S-\>5      r? " S. S/5      r@ " S0 S1\>5      rA " S2 S3\45      rB " S4 S5\45      rCg! \0 a    Sr/Sr. Nf = f)6zEFramework-agnostic core of Motor, an asynchronous driver for MongoDB.    N)ChangeStream)ClientSession)
Collection)CommandCursorRawBatchCommandCursor)CursorRawBatchCursor)_QUERY_OPTIONS)Database)
DriverInfo)ClientEncryption   )
docstrings)version)
AsyncCommand	AsyncRead
AsyncWriteDelegateMethodMotorCursorChainingMethodReadOnlyPropertycoroutine_annotationcreate_class_with_frameworkunwrap_args_sessionunwrap_kwargs_session)callback_type_errorTFx   c                 @    [         R                  " 5       U -
  [        :  $ )z/Are we within the with_transaction retry limit?)time	monotonic"_WITH_TRANSACTION_RETRY_TIME_LIMIT)
start_times    OC:\Suresh\moveshuttle\MDcreated\moveengine\venv\Lib\site-packages\motor/core.py_within_time_limitr#   B   s    >>j(+MMM    c                 v    [        U [        R                  R                  5      =(       a    U R                  S:H  $ )z/Return true if exc is a MaxTimeMSExpired error.2   )
isinstancepymongoerrorsOperationFailurecode)excs    r"   _max_time_expired_errorr-   G   s&    c7>>::;NBNr$   c                   &    \ rS rSrS rS rS rSrg)AgnosticBaseL   c                     [        XR                  5      (       a;  [        U S5      (       a*  [        US5      (       a  U R                  UR                  :H  $ [        $ )Ndelegate)r'   	__class__hasattrr2   NotImplemented)selfothers     r"   __eq__AgnosticBase.__eq__M   sD    unn--j))z**==ENN22r$   c                     Xl         g Nr2   )r6   r2   s     r"   __init__AgnosticBase.__init__V   s     r$   c                 P    U R                   R                   SU R                  < S3$ )N())r3   __name__r2   r6   s    r"   __repr__AgnosticBase.__repr__Y   s%    ..))*!DMM+<A>>r$   r<   N)rB   
__module____qualname____firstlineno__r8   r=   rD   __static_attributes__ r$   r"   r/   r/   L   s    !?r$   r/   c                   h    \ rS rSr\S\S\4S j5       r\" 5       r	\" 5       r
\" 5       r\" 5       rSrg)AgnosticBaseProperties]   keyreturnc                     U $ r;   rJ   clsrN   s     r"   __class_getitem__(AgnosticBaseProperties.__class_getitem___       
r$   rJ   N)rB   rF   rG   rH   classmethodstrobjectrS   r   codec_optionsread_preferenceread_concernwrite_concernrI   rJ   r$   r"   rL   rL   ]   sD    C F   %&M&(O#%L$&Mr$   rL   c                     ^  \ rS rSrSr\R                  R                  r\	" 5       r
\	" 5       r\" 5       r\" 5       r\" 5       r\" 5       R%                  S5      r\	" 5       r\" \R,                  S9R/                  \5      r\" \R4                  S9R/                  \5      r\	" 5       r\	" 5       r\	" 5       r\" 5       R/                  \5      r \" 5       r!\	" 5       r"\	" 5       r#\	" 5       r$\	" 5       r%\	" 5       r&\" 5       r'\	" 5       r(\" \RR                  S9R/                  \*5      r+\" 5       r,U 4S jr-\.S 5       r/S r0            SS jr1S	 r2S
 r3S rSr4U =r5$ )AgnosticClienti   MotorClientMotorDatabasedocc                   > SU;   a-  UR                  S5      nU R                  R                  U5        OSnX0l        UR	                  SS5        [        S[        U R                  R                  5       5      nUR                  S5      (       a  UR                  S5      n[        U[
        5      (       d  [        S[        U5       S35      eUR                  (       a  S	UR                   3OS
nUR                  (       a  S	UR                   3OS
n[        UR                   S	UR                   3UR                   U 3UR                   U 35      nXBS'   U R                  " U0 UD6n[         T	U ]E  U5        g)a	  Create a new connection to a single MongoDB instance at *host:port*.

Takes the same constructor arguments as
:class:`~pymongo.mongo_client.MongoClient`, as well as:

:Parameters:
  - `io_loop` (optional): Special event loop
    instance to use instead of default.
io_loopNconnectFMotordriverzIncorrect type for `driver` z7; expected value of type pymongo.driver_info.DriverInfo| )pop
_frameworkcheck_event_loop_io_loop
setdefaultr   motor_versionplatform_infogetr'   	TypeErrortyper   platformname__delegate_class__superr=   )
r6   argskwargsre   driver_infoprovided_infoadded_versionadded_platformr2   r3   s
            r"   r=   AgnosticClient.__init__   sk    jj+GOO,,W5G)U+ -9V9V9XY::h"JJx0MmZ88243F2G HM M  <I;P;Pa 5 567VXM=J=S=Sq!7!7 89Y[N$##$Am&8&8%9:&&'7''((89K 'x**D;F;"r$   c                 r    U R                   c  U R                  R                  5       U l         U R                   $ r;   rn   rl   get_event_looprC   s    r"   re   AgnosticClient.io_loop   *    ==  OO::<DM}}r$   c                     U R                   $ r;   re   rC   s    r"   get_io_loopAgnosticClient.get_io_loop       ||r$   c                 t    [        [        U R                  U R                  5      nU" U UUUUUUUUU	U
UU5      $ )a
  Watch changes on this cluster.

Returns a :class:`~MotorChangeStream` cursor which iterates over changes
on all databases in this cluster. Introduced in MongoDB 4.0.

See the documentation for :meth:`MotorCollection.watch` for more
details and examples.

:Parameters:
  - `pipeline` (optional): A list of aggregation pipeline stages to
    append to an initial ``$changeStream`` stage. Not all
    pipeline stages are valid after a ``$changeStream`` stage, see the
    MongoDB documentation on change streams for the supported stages.
  - `full_document` (optional): The fullDocument option to pass
    to the ``$changeStream`` stage. Allowed values: 'updateLookup'.
    When set to 'updateLookup', the change notification for partial
    updates will include both a delta describing the changes to the
    document, as well as a copy of the entire document that was
    changed from some time after the change occurred.
  - `resume_after` (optional): A resume token. If provided, the
    change stream will start returning changes that occur directly
    after the operation specified in the resume token. A resume token
    is the _id value of a change document.
  - `max_await_time_ms` (optional): The maximum time in milliseconds
    for the server to wait for changes before responding to a getMore
    operation.
  - `batch_size` (optional): The maximum number of documents to return
    per batch.
  - `collation` (optional): The :class:`~pymongo.collation.Collation`
    to use for the aggregation.
  - `start_at_operation_time` (optional): If provided, the resulting
    change stream will only return changes that occurred at or after
    the specified :class:`~bson.timestamp.Timestamp`. Requires
    MongoDB >= 4.0.
  - `session` (optional): a
    :class:`~pymongo.client_session.ClientSession`.
  - `start_after` (optional): The same as `resume_after` except that
    `start_after` can resume notifications after an invalidate event.
    This option and `resume_after` are mutually exclusive.
  - `comment` (optional): A user-provided comment to attach to this
    command.
  - `full_document_before_change`: Allowed values: `whenAvailable` and `required`. Change
    events may now result in a `fullDocumentBeforeChange` response field.
  - `show_expanded_events` (optional): Include expanded events such as DDL events like
    `dropIndexes`.

:Returns:
  A :class:`~MotorChangeStream`.

.. versionchanged:: 3.2
   Added ``show_expanded_events`` parameter.

.. versionchanged:: 3.1
   Added ``full_document_before_change`` parameter.

.. versionchanged:: 3.0
   Added ``comment`` parameter.

.. versionchanged:: 2.1
   Added the ``start_after`` parameter.

.. versionadded:: 2.0

.. mongodoc:: changeStreams
r   AgnosticChangeStreamrl   rF   r6   pipelinefull_documentresume_aftermax_await_time_ms
batch_size	collationstart_at_operation_timesessionstart_aftercommentfull_document_before_changeshow_expanded_eventscursor_classs                 r"   watchAgnosticClient.watch   T    ` 3 $//4??

 #' 
 	
r$   c           
          UR                  S5      (       a,  [        U R                  R                   SU< SU SU S35      eX   $ )N_ has no attribute . To access the z database, use client[''].
startswithAttributeErrorr3   rB   r6   rv   s     r"   __getattr__AgnosticClient.__getattr__  sV    ??3 >>**++=dXEUVZU[)$s4 
 zr$   c                 \    [        [        U R                  U R                  5      nU" X5      $ r;   )r   AgnosticDatabaserl   rF   )r6   rv   db_classs      r"   __getitem__AgnosticClient.__getitem__%  s'    ./?RVRaRab##r$   c                    UR                   [        :X  a6  [        [        U R                  U R
                  5      nU" XR                  US9$ UR                   [        :X  a-  [        [        U R                  U R
                  5      nU" X5      $ UR                   [        :X  a-  [        [        U R                  U R
                  5      nU" X5      $ g N	_delegate)r3   r   r   r   rl   rF   rv   r   AgnosticCommandCursorr   AgnosticClientSession)r6   objr   command_cursor_classsession_classs        r"   wrapAgnosticClient.wrap*  s    ==H$2 $//4??H D((c::]]m+#>%t$  (22]]m+7%tM !++ ,r$   rn   NNNNNNNNNNNN)6rB   rF   rG   rH   __motor_class_name__r(   mongo_clientMongoClientrw   r   addressarbitersr   close__hash__r   
bulk_writer   unwrapdrop_databaseoptionsr   get_database_docr   r   get_databaseget_default_database_docget_default_databaseHOST	is_mongos
is_primaryr   list_databaseslist_database_namesnodesPORTprimaryr[   secondariesserver_infotopology_descriptionstart_session_docr   start_session_connectr=   propertyre   r   r   r   r   rI   __classcell__r3   s   @r"   r^   r^   i   s   ( --99 G!HEHJ N))/:M G!j&A&ABGGQL)j.Q.QRWWX`aD "I!#J[%%m4N#+ED G#%L"$K+K+- Z%A%ABGGVM{H'#R  

  $$(!c
J$
, ,r$   r^   c                   *    \ rS rSrSrS rS rS rSrg)_MotorTransactionContexti?  z;Internal transaction context manager for start_transaction.c                     Xl         g r;   _session)r6   r   s     r"   r=   !_MotorTransactionContext.__init__B  s    r$   c                    #    U $ 7fr;   rJ   rC   s    r"   
__aenter__#_MotorTransactionContext.__aenter__E  
        c                    #    U R                   R                  (       aI  Uc#  U R                   R                  5       I S h  vN   g U R                   R                  5       I S h  vN   g g  N) N7fr;   )r   in_transactioncommit_transactionabort_transactionr6   exc_typeexc_valexc_tbs       r"   	__aexit__"_MotorTransactionContext.__aexit__H  sN     ==''mm66888mm55777	 (87s!   <A,A("A,!A*"A,*A,r   N)	rB   rF   rG   rH   __doc__r=   r   r   rI   rJ   r$   r"   r   r   ?  s    E 8r$   r   c                      \ rS rSrSrSr\r\" 5       r	\" 5       r
\" 5       r\" 5       r\" 5       r\" 5       r\" 5       r\" 5       r\" 5       r\" 5       r\" 5       rS rS r    SS jr SS jr\S	 5       rS
 rS rS rS rSr g)r   iP  a  A session for ordering sequential operations.

Do not create an instance of :class:`MotorClientSession` directly; use
:meth:`MotorClient.start_session`:

.. code-block:: python3

  collection = client.db.collection

  async with await client.start_session() as s:
      async with s.start_transaction():
          await collection.delete_one({"x": 1}, session=s)
          await collection.insert_one({"x": 2}, session=s)

.. versionadded:: 2.0
MotorClientSessionc                 6    [         R                  XS9  X l        g )Nr<   )r/   r=   _client)r6   r2   motor_clients      r"   r=   AgnosticClientSession.__init__q  s    d6#r$   c                 6    U R                   R                  5       $ r;   r   r   rC   s    r"   r   !AgnosticClientSession.get_io_loopu      ||''))r$   Nc                   #    [         R                  " 5       n U R                  X#XE5       ISh  vN    U" U 5      I Sh  vN nSSS5      ISh  vN   U R                  (       d  W$   U R                  5       I Sh  vN   W$  NT NE! [         a  nU R                  (       a  U R                  5       I Sh  vN    [        U[        R                  R                  5      (       a>  UR                  S5      (       a(  [        U5      (       a   SnASSS5      ISh  vN    GM  e SnAff = f N! , ISh  vN  (       d  f       N= f N! [        R                  R                   an  nUR                  S5      (       a'  [        U5      (       a  [        U5      (       d   SnAGM=  UR                  S5      (       a  [        U5      (       a   SnAO	e SnAff = fGM  7f)az  Executes an awaitable in a transaction.

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

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

  async with await client.start_session() as session:
      inserted_id = await session.with_transaction(coro)

To pass arbitrary arguments to the ``coro``, wrap it with a
``lambda`` like this::

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

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

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

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

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

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
``coro`` 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.

:Parameters:
  - `coro`: The coroutine to run inside a transaction. The coroutine must
    accept a single argument, this session. Note, under certain error
    conditions the coroutine may be run multiple times.
  - `read_concern` (optional): The
    :class:`~pymongo.read_concern.ReadConcern` to use for this
    transaction.
  - `write_concern` (optional): The
    :class:`~pymongo.write_concern.WriteConcern` to use for this
    transaction.
  - `read_preference` (optional): 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.

:Returns:
  The return value of the ``coro``.

.. versionadded:: 2.1
NTransientTransactionErrorUnknownTransactionCommitResult)r   r   start_transaction	Exceptionr   r   r'   r(   r)   PyMongoErrorhas_error_labelr#   r   r-   )	r6   coror[   r\   rZ   max_commit_time_msr!   retr,   s	            r"   with_transaction&AgnosticClientSession.with_transactionx  s    v ^^%
--_  $T
*C	 " &&
11333$ 
S +  
**"44666"3(C(CDD//0KLL.z:: !   
   . 4~~22 ++,LMM.z:: 7 < < !**+FGGL^"M M 3 s   -GBGD.B BBGD,G*E
 =E>E
 GB
D)$D$6B97AD$D.GDG#D$$D))D.,G.E4D75EGE
 
G(6GG%&GGGGGc                 P    U R                   R                  UUUUS9  [        U 5      $ )a  Start a multi-statement transaction.

Takes the same arguments as
:class:`~pymongo.client_session.TransactionOptions`.

Best used in a context manager block:

.. code-block:: python3

  # Use "await" for start_session, but not for start_transaction.
  async with await client.start_session() as s:
      async with s.start_transaction():
          await collection.delete_one({"x": 1}, session=s)
          await collection.insert_one({"x": 2}, session=s)

)r[   r\   rZ   r  )r2   r   r   )r6   r[   r\   rZ   r  s        r"   r   'AgnosticClientSession.start_transaction   s4    & 	''%'+1	 	( 	
 (--r$   c                     U R                   $ )z8The :class:`~MotorClient` this session was created from.r   rC   s    r"   clientAgnosticClientSession.client       ||r$   c                    #    U $ 7fr;   rJ   rC   s    r"   r    AgnosticClientSession.__aenter__   r   r   c                 D   #    U R                   R                  XU5        g 7fr;   )r2   __exit__r   s       r"   r   AgnosticClientSession.__aexit__#  s     x&9s    c                     [        S5      e)NzMUse Motor sessions like 'async with await client.start_session()', not 'with')r   rC   s    r"   	__enter__AgnosticClientSession.__enter__&  s    [
 	
r$   c                     g r;   rJ   r   s       r"   r  AgnosticClientSession.__exit__+      r$   r
  )NNNN)!rB   rF   rG   rH   r   r   r   rw   r   r   r   end_sessionr   cluster_time	has_endedr   r   operation_time
session_idr   advance_cluster_timeadvance_operation_timer=   r   r  r   r   r  r   r   r  r  rI   rJ   r$   r"   r   r   P  s    " 0&%$.K#%L "I%'N G%'N!#J)++-$* FR _c.6  :

r$   r   c                   (  ^  \ rS rSrSr\r\" 5       r\" 5       r	\
" \R                  S9r\
" 5       R                  \5      r\" 5       r\
" 5       R'                  S5      r\" 5       R                  \5      r\" \R,                  S9r\" 5       R                  \5      r\" 5       r\" 5       R'                  S5      r\" 5       R                  \5      r\" SS9rU 4S jrS r             SS	 jr!      SS
 jr"\#S 5       r$S r%S r&S r'S rS r(Sr)U =r*$ )r   i/  ra   rb   MotorCollection	aggregate	attr_namec                    > Xl         UR                  S5      nUb  UO[        UR                  U40 UD6n[        TU ]  U5        g )Nr   )r   rr   r   r2   rx   r=   )r6   r  rv   rz   r   r2   r3   s         r"   r=   AgnosticDatabase.__init__B  sA    JJ{+	 ) 598FOOUY;d]c;d"r$   c                     [        [        U R                  U R                  5      nU" U S   U R                  U/[        U5      Q70 [        U5      D6$ )a  Execute an aggregation pipeline on this database.

Introduced in MongoDB 3.6.

The aggregation can be run on a secondary if the client is connected
to a replica set and its ``read_preference`` is not :attr:`PRIMARY`.
The :meth:`aggregate` method obeys the :attr:`read_preference` of this
:class:`MotorDatabase`, except when ``$out`` or ``$merge`` are used, in
which case  :attr:`PRIMARY` is used.

All optional `aggregate command`_ parameters should be passed as
keyword arguments to this method. Valid options include, but are not
limited to:

  - `allowDiskUse` (bool): Enables writing to temporary files. When set
    to True, aggregation stages can write data to the _tmp subdirectory
    of the --dbpath directory. The default is False.
  - `maxTimeMS` (int): The maximum amount of time to allow the operation
    to run in milliseconds.
  - `batchSize` (int): The maximum number of documents to return per
    batch. Ignored if the connected mongod or mongos does not support
    returning aggregate results using a cursor.
  - `collation` (optional): An instance of
    :class:`~pymongo.collation.Collation`.
  - `let` (dict): A dict of parameter names and values. Values must be
    constant or closed expressions that do not reference document
    fields. Parameters can then be accessed as variables in an
    aggregate expression context (e.g. ``"$$var"``). This option is
    only supported on MongoDB >= 5.0.

Returns a :class:`MotorCommandCursor` that can be iterated like a
cursor from :meth:`find`::

   async def f():
       # Lists all operations currently running on the server.
       pipeline = [{"$currentOp": {}}]
       async for operation in client.admin.aggregate(pipeline):
           print(operation)

.. note:: This method does not support the 'explain' option. Please
   use :meth:`MotorDatabase.command` instead.

.. note:: The :attr:`MotorDatabase.write_concern` of this database is
   automatically applied to this operation.

.. versionadded:: 2.1

.. _aggregate command:
    https://www.mongodb.com/docs/manual/reference/command/aggregate/
z$cmd.aggregater   AgnosticLatentCommandCursorrl   rF   _async_aggregater   r   r6   r   ry   rz   r   s        r"   r"  AgnosticDatabase.aggregateI  s`    f 3'$//

 !"!!
 !&	

 $F+
 	
r$   c                 t    [        [        U R                  U R                  5      nU" U UUUUUUUUU	U
UU5      $ )a
  Watch changes on this database.

Returns a :class:`~MotorChangeStream` cursor which iterates over changes
on this database. Introduced in MongoDB 4.0.

See the documentation for :meth:`MotorCollection.watch` for more
details and examples.

:Parameters:
  - `pipeline` (optional): A list of aggregation pipeline stages to
    append to an initial ``$changeStream`` stage. Not all
    pipeline stages are valid after a ``$changeStream`` stage, see the
    MongoDB documentation on change streams for the supported stages.
  - `full_document` (optional): The fullDocument option to pass
    to the ``$changeStream`` stage. Allowed values: 'updateLookup'.
    When set to 'updateLookup', the change notification for partial
    updates will include both a delta describing the changes to the
    document, as well as a copy of the entire document that was
    changed from some time after the change occurred.
  - `resume_after` (optional): A resume token. If provided, the
    change stream will start returning changes that occur directly
    after the operation specified in the resume token. A resume token
    is the _id value of a change document.
  - `max_await_time_ms` (optional): The maximum time in milliseconds
    for the server to wait for changes before responding to a getMore
    operation.
  - `batch_size` (optional): The maximum number of documents to return
    per batch.
  - `collation` (optional): The :class:`~pymongo.collation.Collation`
    to use for the aggregation.
  - `start_at_operation_time` (optional): If provided, the resulting
    change stream will only return changes that occurred at or after
    the specified :class:`~bson.timestamp.Timestamp`. Requires
    MongoDB >= 4.0.
  - `session` (optional): a
    :class:`~pymongo.client_session.ClientSession`.
  - `start_after` (optional): The same as `resume_after` except that
    `start_after` can resume notifications after an invalidate event.
    This option and `resume_after` are mutually exclusive.
  - `comment` (optional): A user-provided comment to attach to this
    command.
  - `full_document_before_change`: Allowed values: `whenAvailable` and `required`. Change
     events may now result in a `fullDocumentBeforeChange` response field.
  - `show_expanded_events` (optional): Include expanded events such as DDL events like
    `dropIndexes`.

:Returns:
  A :class:`~MotorChangeStream`.

.. versionchanged:: 3.2
   Added ``show_expanded_events`` parameter.

.. versionchanged:: 3.1
   Added ``full_document_before_change`` parameter.

.. versionchanged:: 3.0
   Added ``comment`` parameter.

.. versionchanged:: 2.1
   Added the ``start_after`` parameter.

.. versionadded:: 2.0

.. mongodoc:: changeStreams
r   r   s                 r"   r   AgnosticDatabase.watch  r   r$   c                 (  ^ ^^#    U4mUTS'   UTS'   UTS'   UTS'   UTS'   UTS'   UUU 4S jn	T R                  5       n
T R                  R                  X5      I Sh  vN n[        [        T R                  T R
                  5      nU" UT 5      $  N27f)	a  Issue a MongoDB command and parse the response as a cursor.

If the response from the server does not include a cursor field, an error will be thrown.

Otherwise, behaves identically to issuing a normal MongoDB command.

:Parameters:
  - `command`: document representing the command to be issued,
    or the name of the command (for simple commands only).

    .. note:: the order of keys in the `command` document is
       significant (the "verb" must come first), so commands
       which require multiple keys (e.g. `findandmodify`)
       should use an instance of :class:`~bson.son.SON` or
       a string and kwargs instead of a Python `dict`.

  - `value` (optional): value to use for the command verb when
    `command` is passed as a string
  - `read_preference` (optional): The read preference for this
    operation. See :mod:`~pymongo.read_preferences` for options.
    If the provided `session` is in a transaction, defaults to the
    read preference configured for the transaction.
    Otherwise, defaults to
    :attr:`~pymongo.read_preferences.ReadPreference.PRIMARY`.
  - `codec_options`: A :class:`~bson.codec_options.CodecOptions`
    instance.
  - `session` (optional): A
    :class:`MotorClientSession`.
  - `comment` (optional): A user-provided comment to attach to future getMores for this
    command.
  - `max_await_time_ms` (optional): The number of ms to wait for more data on future
    getMores for this command.
  - `**kwargs` (optional): additional keyword arguments will
    be added to the command document before it is sent

.. note:: :meth:`command` does **not** obey this Database's
   :attr:`read_preference` or :attr:`codec_options`. You must use the
   ``read_preference`` and ``codec_options`` parameters instead.

.. note:: :meth:`command` does **not** apply any custom TypeDecoders
   when decoding the command response.

.. note:: If this client has been configured to use MongoDB Stable
   API (see :ref:`versioned-api-ref`), then :meth:`command` will
   automatically add API versioning options to the given command.
   Explicitly adding API versioning options in the command and
   declaring an API version on the client is not supported.

.. seealso:: The MongoDB documentation on `commands <https://dochub.mongodb.org/core/commands>`_.
valuerZ   rY   r   r   r   c                  `   > TR                   R                  " [        T 5      0 [        T5      D6$ r;   )r2   cursor_commandr   r   )ry   rz   r6   s   r"   inner.AgnosticDatabase.cursor_command.<locals>.inner3  s/    ==//$T*.CF.K r$   N)r   rl   run_on_executorr   r   rF   )r6   commandr0  rZ   rY   r   r   r   rz   r3  loopcursorr   ry   s   `       `    @r"   r2  AgnosticDatabase.cursor_command  s     z zw$3 !"/#y#y&7"#	
 !66tCC2!4??DOO
 FD)) Ds   ABB3Bc                     U R                   $ )z*This MotorDatabase's :class:`MotorClient`.r
  rC   s    r"   r  AgnosticDatabase.clientA  r  r$   c                     UR                  S5      (       a)  [        U R                  R                   SU< SU S35      eX   $ )Nr   r   r   z$ collection, use database['{name}'].r   r   s     r"   r   AgnosticDatabase.__getattr__F  sP    ??3 >>**++=dXEUVZU[67 
 zr$   c                 \    [        [        U R                  U R                  5      nU" X5      $ r;   )r   AgnosticCollectionrl   rF   r6   rv   collection_classs      r"   r   AgnosticDatabase.__getitem__O  s)    6
  ++r$   c                     U R                   R                  nU R                  R                  R                  nUS:X  a  [        U S35      e[        SU SU S35      e)N	open_synczA.open_sync() is unnecessary Motor 0.2, see changelog for details.z@MotorDatabase object is not callable. If you meant to call the 'z' method on a z4 object it is failing because no such method exists.)r2   rv   r   r3   rB   rs   )r6   ry   rz   database_nameclient_class_names        r"   __call__AgnosticDatabase.__call__V  sx    ** LL22;;K'$% &- - 
 &~6G5H I55
 	
r$   c                    UR                   [        L a6  [        [        U R                  U R
                  5      nU" XR                  US9$ UR                   [        L a%  U R                  U R                  UR                  US9$ UR                   [        L a-  [        [        U R                  U R
                  5      nU" X5      $ U$ r   )r3   r   r   r?  rl   rF   rv   r   r   r   r   )r6   r   klassr   s       r"   r   AgnosticDatabase.wrape  s    ==J&/"DOOT__E xx377]]h&>>$,,C>HH]]m+#>%t$  (22Jr$   c                 6    U R                   R                  5       $ r;   r   rC   s    r"   r   AgnosticDatabase.get_io_loopw  r   r$   r
  r   )r   NNNNN)+rB   rF   rG   rH   r   r   rw   r   r   __bool__r   r   cmd_docr6  r   r   create_collectionr   dereferencer   drop_collectionget_collectionlist_collection_names_doclist_collection_namesr   list_collectionsr   rv   validate_collectionwith_optionsr*  r=   r"  r   r2  r   r  r   r   rG  r   rI   r   r   s   @r"   r   r   /  sR   *!HHz112G$++J7+K"n++,=>O#%**:6N%**N*NO {''6D#+,,->?!#((2L ;7#>
D  $$(!c
P Q*f  ,
$* *r$   r   c                     ^  \ rS rSrSr\r\" 5       r\" 5       r	\
" \R                  S9r\" 5       r\
" \R                   S9r\
" \R$                  S9r\
" 5       r\
" 5       r\
" \R,                  S9r\
" \R0                  S9r\" 5       r\
" \R6                  S9r\
" 5       r\
" 5       r\
" 5       r\
" 5       r \" \RB                  S9r"\
" \RF                  S9r$\
" \RJ                  S9r&\
" \RN                  S9r(\)" 5       r*\" \RV                  S9r,\-" \R\                  S9r/\
" \R`                  S9r1\)" 5       r2\" 5       r3\
" 5       r4\
" \Rj                  S9r6\
" \Rn                  S9r8\
" \Rr                  S9r:\
" 5       r;\" 5       Ry                  \5      r=\" SS9r>\" SS9r?\" SS9r@\" SS9rA     SU 4S	 jjrBS
 rCS rDS rES rFS rGS rHS rI            SS jrJSS jrKS rLS r<S rMSrNU =rO$ )r?  i{  r!  rb   r"  r#  aggregate_raw_batcheslist_indexeslist_search_indexesc           	         > [        [        U R                  U R                  5      n[	        X5      (       d  [        SU-  5      eUb  UO[        UR                  UUUUUS9n	[        T
U ]%  U	5        Xl
        g )Nz?First argument to MotorCollection must be MotorDatabase, not %r)rY   rZ   r\   r[   )r   r   rl   rF   r'   rs   r   r2   rx   r=   database)r6   r^  rv   rY   rZ   r\   r[   r   r   r2   r3   s             r"   r=   AgnosticCollection.__init__  s     //?RVRaRab(--QT\\  $ !!+ /+) 	 	" r$   c           
          UR                  S5      (       a=  U R                   SU 3n[        U R                  R                   SU< SU SU S35      eX   $ )Nr   .r   r   z collection, use database['r   )r   rv   r   r3   rB   )r6   rv   	full_names      r"   r   AgnosticCollection.__getattr__  sj    ??399+Qtf-I >>**++=dXEUV_U`-i[= 
 zr$   c                     [        [        U R                  U R                  5      nU" U R                  U R
                  S-   U-   U R                  U   S9$ )Nra  r   )r   r?  rl   rF   r^  rv   r2   r@  s      r"   r   AgnosticCollection.__getitem__  sL    6
  MM499s?T1T]]4=P
 	
r$   c                 F    [        SU R                  R                  -  5      e)NzMotorCollection object is not callable. If you meant to call the '%s' method on a MotorCollection object it is failing because no such method exists.)rs   r2   rv   r6   ry   rz   s      r"   rG  AgnosticCollection.__call__  s'    57;}}7I7IJ
 	
r$   c                     U R                   R                  " [        U5      0 [        U5      D6n[	        [
        U R                  U R                  5      nU" X05      $ )ak  Create a :class:`MotorCursor`. Same parameters as for
PyMongo's :meth:`~pymongo.collection.Collection.find`.

Note that ``find`` does not require an ``await`` expression, because
``find`` merely creates a
:class:`MotorCursor` without performing any operations on the server.
``MotorCursor`` methods such as :meth:`~MotorCursor.to_list`
perform actual operations.
)r2   findr   r   r   AgnosticCursorrl   rF   r6   ry   rz   r8  r   s        r"   rj  AgnosticCollection.find  sN     ##%8%>`BWX^B_`2>4??TXTcTcdF))r$   c                     U R                   R                  " [        U5      0 [        U5      D6n[	        [
        U R                  U R                  5      nU" X05      $ )aN  Query the database and retrieve batches of raw BSON.

Similar to the :meth:`find` method but returns each batch as bytes.

This example demonstrates how to work with raw batches, but in practice
raw batches should be passed to an external library that can decode
BSON into another data type, rather than used with PyMongo's
:mod:`bson` module.

.. code-block:: python3

  async def get_raw():
      cursor = db.test.find_raw_batches()
      async for batch in cursor:
          print(bson.decode_all(batch))

Note that ``find_raw_batches`` does not support sessions.

.. versionadded:: 2.0
)r2   find_raw_batchesr   r   r   AgnosticRawBatchCursorrl   rF   rl  s        r"   ro  #AgnosticCollection.find_raw_batches  sU    * // &
*?*G
 3"DOOT__
 F))r$   c                     [        [        U R                  U R                  5      nU" U U R                  U/[        U5      Q70 [        U5      D6$ )a  Execute an aggregation pipeline on this collection.

The aggregation can be run on a secondary if the client is connected
to a replica set and its ``read_preference`` is not :attr:`PRIMARY`.

:Parameters:
  - `pipeline`: a single command or list of aggregation commands
  - `session` (optional): a
    :class:`~pymongo.client_session.ClientSession`, created with
    :meth:`~MotorClient.start_session`.
  - `**kwargs`: send arbitrary parameters to the aggregate command

All optional `aggregate command`_ parameters should be passed as
keyword arguments to this method. Valid options include, but are not
limited to:

  - `allowDiskUse` (bool): Enables writing to temporary files. When set
    to True, aggregation stages can write data to the _tmp subdirectory
    of the --dbpath directory. The default is False.
  - `maxTimeMS` (int): The maximum amount of time to allow the operation
    to run in milliseconds.
  - `batchSize` (int): The maximum number of documents to return per
    batch. Ignored if the connected mongod or mongos does not support
    returning aggregate results using a cursor.
  - `collation` (optional): An instance of
    :class:`~pymongo.collation.Collation`.
  - `let` (dict): A dict of parameter names and values. Values must be
    constant or closed expressions that do not reference document
    fields. Parameters can then be accessed as variables in an
    aggregate expression context (e.g. ``"$$var"``). This option is
    only supported on MongoDB >= 5.0.

Returns a :class:`MotorCommandCursor` that can be iterated like a
cursor from :meth:`find`::

  async def f():
      pipeline = [{'$project': {'name': {'$toUpper': '$name'}}}]
      async for doc in collection.aggregate(pipeline):
          print(doc)

Note that this method returns a :class:`MotorCommandCursor` which
lazily runs the aggregate command when first iterated. In order to run
an aggregation with ``$out`` or ``$merge`` the application needs to
iterate the cursor, for example::

   cursor = motor_coll.aggregate([{'$out': 'out'}])
   # Iterate the cursor to run the $out (or $merge) operation.
   await cursor.to_list(length=None)
   # Or more succinctly:
   await motor_coll.aggregate([{'$out': 'out'}]).to_list(length=None)
   # Or:
   async for _ in motor_coll.aggregate([{'$out': 'out'}]):
       pass

:class:`MotorCommandCursor` does not allow the ``explain`` option. To
explain MongoDB's query plan for the aggregation, use
:meth:`MotorDatabase.command`::

  async def f():
      plan = await db.command(
          'aggregate', 'COLLECTION-NAME',
          pipeline=[{'$project': {'x': 1}}],
          explain=True)

      print(plan)

.. versionchanged:: 2.1
   This collection's read concern is now applied to pipelines
   containing the `$out` stage when connected to MongoDB >= 4.2.

.. versionchanged:: 1.0
   :meth:`aggregate` now **always** returns a cursor.

.. versionchanged:: 0.5
   :meth:`aggregate` now returns a cursor by default,
   and the cursor is returned immediately without an ``await``.
   See :ref:`aggregation changes in Motor 0.5 <aggregate_changes_0_5>`.

.. versionchanged:: 0.2
   Added cursor support.

.. _aggregate command:
    https://mongodb.com/docs/manual/applications/aggregation

r(  r+  s        r"   r"  AgnosticCollection.aggregate  sZ    l 3'$//

 !!
 !&	

 $F+
 	
r$   c                     [        [        U R                  U R                  5      nU" X R                  U40 [        U5      D6$ )aa  Perform an aggregation and retrieve batches of raw BSON.

Similar to the :meth:`aggregate` method but returns each batch as bytes.

This example demonstrates how to work with raw batches, but in practice
raw batches should be passed to an external library that can decode
BSON into another data type, rather than used with PyMongo's
:mod:`bson` module.

.. code-block:: python3

  async def get_raw():
      cursor = db.test.aggregate_raw_batches()
      async for batch in cursor:
          print(bson.decode_all(batch))

Note that ``aggregate_raw_batches`` does not support sessions.

.. versionadded:: 2.0
)r   r)  rl   rF   _async_aggregate_raw_batchesr   )r6   r   rz   r   s       r"   rZ  (AgnosticCollection.aggregate_raw_batchesq  sE    * 3'$//

 33X
AVW]A^
 	
r$   c                 t    [        [        U R                  U R                  5      nU" U UUUUUUUUU	U
UU5      $ )a  Watch changes on this collection.

Performs an aggregation with an implicit initial ``$changeStream``
stage and returns a :class:`~MotorChangeStream` cursor which
iterates over changes on this collection.

Introduced in MongoDB 3.6.

A change stream continues waiting indefinitely for matching change
events. Code like the following allows a program to cancel the change
stream and exit.

.. code-block:: python3

  change_stream = None


  async def watch_collection():
      global change_stream

      # Using the change stream in an "async with" block
      # ensures it is canceled promptly if your code breaks
      # from the loop or throws an exception.
      async with db.collection.watch() as change_stream:
          async for change in change_stream:
              print(change)


  # Tornado
  from tornado.ioloop import IOLoop


  def main():
      loop = IOLoop.current()
      # Start watching collection for changes.
      try:
          loop.run_sync(watch_collection)
      except KeyboardInterrupt:
          if change_stream:
              loop.run_sync(change_stream.close)


  # asyncio
  try:
      asyncio.run(watch_collection())
  except KeyboardInterrupt:
      pass

The :class:`~MotorChangeStream` async iterable blocks
until the next change document is returned or an error is raised. If
the :meth:`~MotorChangeStream.next` method encounters
a network error when retrieving a batch from the server, it will
automatically attempt to recreate the cursor such that no change
events are missed. Any error encountered during the resume attempt
indicates there may be an outage and will be raised.

.. code-block:: python3

    try:
        pipeline = [{"$match": {"operationType": "insert"}}]
        async with db.collection.watch(pipeline) as stream:
            async for change in stream:
                print(change)
    except pymongo.errors.PyMongoError:
        # The ChangeStream encountered an unrecoverable error or the
        # resume attempt failed to recreate the cursor.
        logging.error("...")

For a precise description of the resume process see the
`change streams specification`_.

:Parameters:
  - `pipeline` (optional): A list of aggregation pipeline stages to
    append to an initial ``$changeStream`` stage. Not all
    pipeline stages are valid after a ``$changeStream`` stage, see the
    MongoDB documentation on change streams for the supported stages.
  - `full_document` (optional): The fullDocument option to pass
    to the ``$changeStream`` stage. Allowed values: 'updateLookup'.
    When set to 'updateLookup', the change notification for partial
    updates will include both a delta describing the changes to the
    document, as well as a copy of the entire document that was
    changed from some time after the change occurred.
  - `resume_after` (optional): A resume token. If provided, the
    change stream will start returning changes that occur directly
    after the operation specified in the resume token. A resume token
    is the _id value of a change document.
  - `max_await_time_ms` (optional): The maximum time in milliseconds
    for the server to wait for changes before responding to a getMore
    operation.
  - `batch_size` (optional): The maximum number of documents to return
    per batch.
  - `collation` (optional): The :class:`~pymongo.collation.Collation`
    to use for the aggregation.
  - `session` (optional): a
    :class:`~pymongo.client_session.ClientSession`.
  - `start_after` (optional): The same as `resume_after` except that
    `start_after` can resume notifications after an invalidate event.
    This option and `resume_after` are mutually exclusive.
  - `comment` (optional): A user-provided comment to attach to this
    command.
  - `full_document_before_change`: Allowed values: `whenAvailable` and `required`.
    Change events may now result in a `fullDocumentBeforeChange` response field.
  - `show_expanded_events` (optional): Include expanded events such as DDL events
    like `dropIndexes`.

:Returns:
  A :class:`~MotorChangeStream`.

See the :ref:`tornado_change_stream_example`.

.. versionchanged:: 3.2
   Added ``show_expanded_events`` parameter.

.. versionchanged:: 3.1
   Added ``full_document_before_change`` parameter.

.. versionchanged:: 3.0
   Added ``comment`` parameter.

.. versionchanged:: 2.1
   Added the ``start_after`` parameter.

.. versionadded:: 1.2

.. mongodoc:: changeStreams

.. _change streams specification:
    https://github.com/mongodb/specifications/blob/master/source/change-streams/change-streams.rst
r   r   s                 r"   r   AgnosticCollection.watch  sT    ` 3 $//4??

 #' 
 	
r$   c                 v    [        [        U R                  U R                  5      nU" X R                  4SU0UD6$ )a.  Get a cursor over the index documents for this collection. ::

  async def print_indexes():
      async for index in db.test.list_indexes():
          print(index)

If the only index is the default index on ``_id``, this might print::

    SON([('v', 1), ('key', SON([('_id', 1)])), ('name', '_id_')])
r   )r   r)  rl   rF   _async_list_indexes)r6   r   rz   r   s       r"   r[  AgnosticCollection.list_indexes4  s:     3'$//

 D":":VGVvVVr$   c                 x    [        [        U R                  U R                  5      nU" X R                  /UQ70 UD6$ )z?Return a cursor over search indexes for the current collection.)r   r)  rl   rF   _async_list_search_indexes)r6   ry   rz   r   s       r"   r\  &AgnosticCollection.list_search_indexesF  s8    2'$//

 D"A"ASDSFSSr$   c                    UR                   [        L a%  U R                  U R                  UR                  US9$ UR                   [        L a  [        X5      $ UR                   [        L a-  [        [        U R                  U R                  5      nU" X5      $ UR                   [        L a-  [        [        U R                  U R                  5      nU" X5      $ U$ r   )r3   r   r^  rv   r   rk  r   r   r   rl   rF   r   r   )r6   r   r   change_stream_classs       r"   r   AgnosticCollection.wrapO  s    ==J&>>$--S>II]]f$!#,,]]m+#>%t$  (22]]l*"=$doot# 's11Jr$   c                 6    U R                   R                  5       $ r;   )r^  r   rC   s    r"   r   AgnosticCollection.get_io_loopd  s    }}((**r$   )r^  )NNNNNr   r;   )PrB   rF   rG   rH   r   r   rw   r   r   rN  r   r   bulk_write_docr   r   count_documentscreate_index_doccreate_indexcreate_indexes_doccreate_indexescreate_search_indexcreate_search_indexesdelete_many_docdelete_manydelete_one_doc
delete_onedistinctdrop_docdrop
drop_indexdrop_search_indexdrop_indexesestimated_document_countfind_one_docfind_onefind_one_and_delete_docfind_one_and_deletefind_one_and_replace_docfind_one_and_replacefind_one_and_update_docfind_one_and_updater   rb  index_information_docindex_informationr   insert_many_docinsert_manyinsert_one_doc
insert_onerv   r   renamereplace_one_docreplace_oneupdate_many_docupdate_manyupdate_one_doc
update_oneupdate_search_indexr   rX  r*  ru  rz  r}  r=   r   r   rG  rj  ro  r"  rZ  r   r[  r\  r   rI   r   r   s   @r"   r?  r?  {  sK   ,#HH*";";<JkOJ$?$?@L!j&C&CDN&.(N:#=#=>K*";";<J{HJ//0DJ$>L+~Z445H&:+M+MN'J,O,OP&:+M+MN "I!j&F&FG!;!;<K*";";<JDkG^F:#=#=>K:#=#=>K*";";<J&.!#((4L ;7#,7N#O #n=!*5J!K !B	

**<a
F
@  $$(!c
JW$T*+ +r$   r?  c                   ,  ^  \ rS rSrSr\S\S\4S j5       r\	" SS9r
\	" 5       r\" 5       r\" 5       r\" 5       r\" 5       rU 4S jrS	 rS
 r\rS rS rS r\\S 5       5       rS rS rS r\SS j5       rS rS r S r!S r"S r#S r$S r%S r&Sr'U =r($ )AgnosticBaseCursorih  z7Base class for AgnosticCursor and AgnosticCommandCursorrN   rO   c                     U $ r;   rJ   rQ   s     r"   rS   $AgnosticBaseCursor.__class_getitem__l  rU   r$   r   r#  c                 H   > [         TU ]  US9  X l        SU l        SU l        g)a  Don't construct a cursor yourself, but acquire one from methods like
:meth:`MotorCollection.find` or :meth:`MotorCollection.aggregate`.

.. note::
  There is no need to manually close cursors; they are closed
  by the server after being fully iterated
  with :meth:`to_list`, :meth:`each`, or `async for`, or
  automatically closed by the client when the :class:`MotorCursor` is
  cleaned up by the garbage collector.
r<   FN)rx   r=   
collectionstartedclosed)r6   r8  r  r3   s      r"   r=   AgnosticBaseCursor.__init__w  s(     	&)$r$   c                     U $ r;   rJ   rC   s    r"   	__aiter__AgnosticBaseCursor.__aiter__      r$   c                    #    U R                   (       aG  U R                  5       (       d  U R                  5       I Sh  vN (       a  [        U R                  5      $ [
        e N$7f)z+Advance the cursor.

.. versionadded:: 2.2
N)alive_buffer_size	_get_morenextr2   StopAsyncIterationrC   s    r"   r  AgnosticBaseCursor.next  sF     
 ::4,,..8H2H2H&&   3Is   :A#A!%A#c                    #    U $ 7fr;   rJ   rC   s    r"   r   AgnosticBaseCursor.__aenter__  r   r   c                 d   #    U R                   (       a  U R                  5       I S h  vN   g g  N7fr;   r2   r   r   s       r"   r   AgnosticBaseCursor.__aexit__  #     ==**,    %0.0c                     U R                   (       d  [        R                  R                  S5      eSU l        U R                  5       $ )z+Initial query or getMore. Returns a Future.zICan't call get_more() on a MotorCursor that has been exhausted or killed.T)r  r(   r)   InvalidOperationr  _refreshrC   s    r"   r  AgnosticBaseCursor._get_more  s8    zz..11[  }}r$   c                    [         R                  " S[        SS9  U R                  5       (       d!  U R                  (       a  U R                  5       $ U R                  5       (       a<  U R                  R                  U R                  5       5      nUR                  S5        U$ U R                  R                  U R                  5       5      nUR                  S5        U$ )a7  **DEPRECATED** - A Future used with `gen.coroutine`_ to
asynchronously retrieve the next document in the result set,
fetching a batch of documents from the server if necessary.
Resolves to ``False`` if there are no more documents, otherwise
:meth:`next_object` is guaranteed to return a document:

.. doctest:: fetch_next
   :hide:

   >>> _ = MongoClient().test.test_collection.delete_many({})
   >>> collection = MotorClient().test.test_collection

.. attention:: The :attr:`fetch_next` property is deprecated and will
   be removed in Motor 3.0. Use `async for` to iterate elegantly and
   efficiently over :class:`MotorCursor` objects instead.:

   .. doctest:: fetch_next

      >>> async def f():
      ...     await collection.drop()
      ...     await collection.insert_many([{"_id": i} for i in range(5)])
      ...     async for doc in collection.find():
      ...         sys.stdout.write(str(doc["_id"]) + ", ")
      ...     print("done")
      ...
      >>> IOLoop.current().run_sync(f)
      0, 1, 2, 3, 4, done

While it appears that fetch_next retrieves each document from
the server individually, the cursor actually fetches documents
efficiently in `large batches`_. Example usage:

.. doctest:: fetch_next

   >>> async def f():
   ...     await collection.drop()
   ...     await collection.insert_many([{"_id": i} for i in range(5)])
   ...     cursor = collection.find().sort([("_id", 1)])
   ...     while await cursor.fetch_next:
   ...         doc = cursor.next_object()
   ...         sys.stdout.write(str(doc["_id"]) + ", ")
   ...     print("done")
   ...
   >>> IOLoop.current().run_sync(f)
   0, 1, 2, 3, 4, done

.. versionchanged:: 2.2
   Deprecated.

.. _`large batches`: https://www.mongodb.com/docs/manual/tutorial/iterate-a-cursor/#cursor-batches
.. _`gen.coroutine`: http://tornadoweb.org/en/stable/gen.html
zThe fetch_next property is deprecated and may be removed in a future major release. Use `async for` to iterate over Cursor objects instead.   
stacklevelTF)
warningswarnDeprecationWarningr  r  r  rl   
get_futurer   
set_result)r6   futures     r"   
fetch_nextAgnosticBaseCursor.fetch_next  s    n 	+ 	
   ""tzz>>##  __//0@0@0BCFd#M __//0@0@0BCFe$Mr$   c                     [         R                  " S[        SS9  U R                  5       (       d  g[	        U R
                  5      $ )a?  **DEPRECATED** - Get a document from the most recently fetched
batch, or ``None``. See :attr:`fetch_next`.

The :meth:`next_object` method is deprecated and may be removed
in a future major release. Use `async for` to elegantly iterate over
:class:`MotorCursor` objects instead.

.. versionchanged:: 2.2
   Deprecated.
zThe next_object method is deprecated and may be removed in a future major release.  Use `async for` to iterate over Cursor objects instead.r  r  N)r  r  r  r  r  r2   rC   s    r"   next_objectAgnosticBaseCursor.next_object  s@     	+ 	
   ""DMM""r$   c                 T    [        U5      (       d  [        eU R                  US5        g)a  Iterates over all the documents for this cursor.

:meth:`each` returns immediately, and `callback` is executed asynchronously
for each document. `callback` is passed ``(None, None)`` when iteration
is complete.

Cancel iteration early by returning ``False`` from the callback. (Only
``False`` cancels iteration: returning ``None`` or 0 does not.)

.. testsetup:: each

   from tornado.ioloop import IOLoop

   MongoClient().test.test_collection.delete_many({})
   MongoClient().test.test_collection.insert_many([{"_id": i} for i in range(5)])

   collection = MotorClient().test.test_collection

.. doctest:: each

   >>> def each(result, error):
   ...     if error:
   ...         raise error
   ...     elif result:
   ...         sys.stdout.write(str(result["_id"]) + ", ")
   ...     else:
   ...         # Iteration complete
   ...         IOLoop.current().stop()
   ...         print("done")
   ...
   >>> cursor = collection.find().sort([("_id", 1)])
   >>> cursor.each(callback=each)
   >>> IOLoop.current().start()
   0, 1, 2, 3, 4, done

.. note:: Unlike other Motor methods, ``each`` requires a callback and
   does not return a Future, so it cannot be used in a coroutine.
   ``async for`` and :meth:`to_list` are much easier to use.

:Parameters:
 - `callback`: function taking (document, error)
N)callabler   _each_got_more)r6   callbacks     r"   eachAgnosticBaseCursor.each  s&    V !!%%Hd+r$   c                    U(       a   UR                  5         U R                  5       S:  aJ  [        U R                  5      nU" US 5      SL a  g U R
                  (       a  g U R                  5       S:  a  MJ  U R                  (       ag  U R                  (       d  U R                  (       dE  U R                  R                  U R                  5       U R                  5       U R                  U5        g U R                  R                  U R                  5       [        R                   " US S 5      5        g ! [         a  nU" S U5         S nAg S nAff = f)Nr   F)resultr   r  r  r2   r  r  	cursor_idr  rl   
add_futurer   r  r  	call_soon	functoolspartial)r6   r  r  errorrc   s        r"   r  !AgnosticBaseCursor._each_got_more;  s    
 !A%t}}%C T"e+ {{ !A% ::4>>OO&&  "DNN$4d6I6I8
 OO%%d&6&6&8):K:KHVZ\`:ab-  u%s   D0 0
E:	EEc                    Ub4  [        U[        5      (       d  [        SU-  5      eUS:  a  [        S5      eU R	                  5       [
        S   -  (       a  [        R                  R                  S5      eU R                  R                  U R                  5       5      nU R                  (       d  UR                  / 5        U$ / nU R                  R                  U R                  5       U R                  5       U R                   UUU5        U$ )a!  Get a list of documents.

.. testsetup:: to_list

  MongoClient().test.test_collection.delete_many({})
  MongoClient().test.test_collection.insert_many([{"_id": i} for i in range(4)])

  from tornado import ioloop

.. doctest:: to_list

  >>> from motor.motor_tornado import MotorClient
  >>> collection = MotorClient().test.test_collection
  >>>
  >>> async def f():
  ...     cursor = collection.find().sort([("_id", 1)])
  ...     docs = await cursor.to_list(length=2)
  ...     while docs:
  ...         print(docs)
  ...         docs = await cursor.to_list(length=2)
  ...     print("done")
  ...
  >>> ioloop.IOLoop.current().run_sync(f)
  [{'_id': 0}, {'_id': 1}]
  [{'_id': 2}, {'_id': 3}]
  done

:Parameters:
 - `length`: maximum number of documents to return for this call, or
   None

 Returns a Future.

.. versionchanged:: 2.0
   No longer accepts a callback argument.

.. versionchanged:: 0.2
   `callback` must be passed as a keyword argument, like
   ``to_list(10, callback=callback)``, and the
   `length` parameter is no longer optional.
zlength must be an int, not %rr   zlength must be non-negativetailable_cursorz%Can't call to_list on tailable cursor)r'   intrs   
ValueError_query_flagsr
   r(   r)   r  rl   r  r   r  r  r  r  _to_list)r6   lengthr  the_lists       r"   to_listAgnosticBaseCursor.to_listW  s    V fc** ?& HII! !>??0A!BB..112YZZ++D,<,<,>?zzb!  HOO&&  "  r$   c                     UR                  5       nUR                  5       (       a  g Uc  UnO[        U[        U5      -
  U5      n[	        U5       H0  nUR                  U R                  5       R                  5       5        M2     US L=(       a    [        U5      U:  nU(       d  U R                  (       d  UR                  U5        g U R                  R                  U R                  5       U R                  5       U R                  XU5        g ! [         a5  n	UR                  5       (       d  UR!                  U	5         S n	A	g  S n	A	g S n	A	ff = fr;   )r  doneminlenrangeappend_datapopleftr  r  rl   r  r   r  r  r   set_exception)
r6   r  r  r  get_more_resultr  nr   reached_lengthr,   s
             r"   r  AgnosticBaseCursor._to_list  s   	*$++-F{{}}~X.71X

 4 4 67  $4/KCMV4KNTZZ!!(+**$$&(8$--[a  	*;;==$$S)) !	*s$   %D BD AD 
E&EEc                 6    U R                   R                  5       $ r;   )r  r   rC   s    r"   r   AgnosticBaseCursor.get_io_loop  s    **,,r$   c                 r   #    U R                   (       d   SU l         U R                  5       I Sh  vN   gg N7f)zSExplicitly kill this cursor on the server.

Call like::

    await cursor.close()

TN)r  _async_closerC   s    r"   r   AgnosticBaseCursor.close  s/      {{DK##%%% %s   ,757c                 <    U R                   R                  U5        U $ r;   )r2   r   r6   r   s     r"   r   AgnosticBaseCursor.batch_size  s      ,r$   c                 4    [        U R                  5       5      $ r;   )r  r  rC   s    r"   r  AgnosticBaseCursor._buffer_size  s    4::<  r$   c                     [         er;   NotImplementedErrorrC   s    r"   r  AgnosticBaseCursor._query_flags      !!r$   c                     [         er;   r  rC   s    r"   r  AgnosticBaseCursor._data  r  r$   c                     [         er;   r  rC   s    r"   _killedAgnosticBaseCursor._killed  r  r$   )r  r  r  r;   ))rB   rF   rG   rH   r   rV   rW   rX   rS   r   r  r  r   r   r  r  r   r=   r  r  	__anext__r   r   r  r   r   r  r  r  r  r  r  r   r   r   r  r  r  r  rI   r   r   s   @r"   r  r  h  s    A C F   w/L{H G "IE G$! I H  HT#..,`c8 B BH*8-
&!""" "r$   r  c                   f   \ rS rSrSr\r\" 5       r\	" 5       r
\" 5       r\" 5       r\	" 5       r\	" 5       r\	" 5       r\	" 5       r\	" 5       r\	" \R(                  S9r\	" 5       r\	" \R.                  S9r\	" 5       r\	" 5       r\	" 5       r\	" 5       r\	" 5       r\	" 5       rS rS r S r!S r"S r#S	 r$S
 r%Sr&g)rk  i  MotorCursorrb   c                 H    U R                   R                  5         SU l        U $ )z,Rewind this cursor to its unevaluated state.F)r2   rewindr  rC   s    r"   r  AgnosticCursor.rewind  s    r$   c                 j    U R                  U R                  R                  5       U R                  5      $ )zGet a clone of this cursor.)r3   r2   cloner  rC   s    r"   r  AgnosticCursor.clone  s$    ~~dmm113T__EEr$   c                 j    U R                  U R                  R                  5       U R                  5      $ r;   )r3   r2   __copy__r  rC   s    r"   r  AgnosticCursor.__copy__  s$    ~~dmm446HHr$   c                 l    U R                  U R                  R                  U5      U R                  5      $ r;   )r3   r2   __deepcopy__r  )r6   memos     r"   r"  AgnosticCursor.__deepcopy__  s&    ~~dmm88>PPr$   c                 .    U R                   R                  $ r;   )r2   r  rC   s    r"   r  AgnosticCursor._query_flags  s    }})))r$   c                 .    U R                   R                  $ r;   r2   r  rC   s    r"   r  AgnosticCursor._data      }}"""r$   c                 .    U R                   R                  $ r;   r2   r  rC   s    r"   r  AgnosticCursor._killed      }}$$$r$   )r  N)'rB   rF   rG   rH   r   r   rw   r   r   r   r   r   r  explain
add_optionremove_optionlimitskipmax_scanr   cursor_sort_docsorthint	where_docwherer   max_time_msr  maxr   allow_disk_user  r  r  r"  r  r  r  rI   rJ   r$   r"   rk  rk    s    ( G)+I{HkG*,J-/M%'E$&D(*H$)C)CDD$&D%**>*>?E13+-K
#
%C
#
%C')G.0NFIQ*#%r$   rk  c                       \ rS rSrSr\rSrg)rp  i	  MotorRawBatchCursorrJ   N)rB   rF   rG   rH   r   r	   rw   rI   rJ   r$   r"   rp  rp  	  s    0'r$   rp  c                   4    \ rS rSrSr\rS rS rS r	S r
Srg)	r   i  MotorCommandCursorc                    ^ #    U 4S jnT R                  5       nT R                  R                  X!5      I Sh  vN $  N7f)a  Advance the cursor without blocking indefinitely.

This method returns the next document without waiting
indefinitely for data.

If no document is cached locally then this method runs a single
getMore command. If the getMore yields any documents, the next
document is returned, otherwise, if the getMore returns no documents
(because there is no additional data) then ``None`` is returned.

:Returns:
  The next document or ``None`` when no document is available
  after running a single getMore or when the cursor is closed.
c                  8   > T R                   R                  5       $ r;   )r2   try_nextrC   s   r"   r3  -AgnosticCommandCursor.try_next.<locals>.inner"  s    ==))++r$   N)r   rl   r5  )r6   r3  r7  s   `  r"   rC  AgnosticCommandCursor.try_next  s6      	, !__44TAAAAs   5?=?c                     g)Nr   rJ   rC   s    r"   r  "AgnosticCommandCursor._query_flags(  s    r$   c                 .    U R                   R                  $ r;   r(  rC   s    r"   r  AgnosticCommandCursor._data+  r*  r$   c                 .    U R                   R                  $ r;   r,  rC   s    r"   r  AgnosticCommandCursor._killed.  r.  r$   rJ   N)rB   rF   rG   rH   r   r   rw   rC  r  r  r  rI   rJ   r$   r"   r   r     s#    /&B,#%r$   r   c                       \ rS rSrSr\rSrg)AgnosticRawBatchCommandCursori2  MotorRawBatchCommandCursorrJ   N)rB   rF   rG   rH   r   r   rw   rI   rJ   r$   r"   rM  rM  2  s    7.r$   rM  c                   V    \ rS rSrSrSr/ rSrSrSr	Sr
SrSrS rS rS rS	 rS
 rSrg)_LatentCursori7  zCTake the place of a PyMongo CommandCursor until aggregate() begins.TNFc                 &    UR                   U l        g r;   )r2   _collection)r6   r  s     r"   r=   _LatentCursor.__init__C  s    %..r$   c                     g r;   rJ   rg  s      r"   _end_session_LatentCursor._end_sessionF  r  r$   c                     g r;   rJ   rg  s      r"   	_die_lock_LatentCursor._die_lockI  r  r$   c                 ,    [        U R                  5      $ r;   )rP  rR  rC   s    r"   r  _LatentCursor.cloneL  s    T--..r$   c                     g r;   rJ   rC   s    r"   r  _LatentCursor.rewindO  r  r$   )rR  )rB   rF   rG   rH   r   r  r  _idr  	_sock_mgrr   _explicit_sessionr  r=   rU  rX  r  r  rI   rJ   r$   r"   rP  rP  7  sG    MEE
CGIHI//r$   rP  c                   J   ^  \ rS rSrSrU 4S jrS rU 4S jrU 4S jrSr	U =r
$ )r)  iS  MotorLatentCommandCursorc                 \   > [         TU ]  [        U5      U5        X l        X0l        X@l        g r;   )rx   r=   rP  startry   rz   )r6   r  rd  ry   rz   r3   s        r"   r=   $AgnosticLatentCommandCursor.__init__V  s(     	z2J?
	r$   c                 "    XR                   S'   U $ )N	batchSize)rz   r  s     r"   r   &AgnosticLatentCommandCursor.batch_sized  s    #-K r$   c                   > U R                   (       d  SU l         U R                  R                  U R                  5       5      nU R                  " U R
                  0 U R                  D6nS =U l        =U l        U l        U R                  R                  U R                  5       X R                  U5        U$ [        TU ])  5       $ )NT)r  rl   r  r   rd  ry   rz   r  _on_startedrx   r  )r6   original_futurer  r3   s      r"   r  %AgnosticLatentCommandCursor._get_moreh  s    ||DL"oo889I9I9KLOZZ:dkk:F377DJ7T[OO&&  "F,<,<o #"w ""r$   c                    >  UR                  5       nX0l        UR                  5       (       a  g U R                  R                  (       d  U R                  R                  (       d/  UR                  [        U R                  R                  5      5        g [        TU ]!  5       nU R                  R                  X!5        g ! [         a5  nUR                  5       (       d  UR                  U5         S nAg  S nAg S nAff = fr;   )r  r2   r  r  r  r  r  rx   r  rl   chain_futurer   r  )r6   rk  r  pymongo_cursorr,   r3   s        r"   rj  'AgnosticLatentCommandCursor._on_startedx  s    	F $]]_N*M ##%%}}""$--*=*=**3t}}/B/B+CD *,,,VE  	3"''))--c22 *	3s   B> >
C=&C88C=)ry   r2   rz   rd  r  )rB   rF   rG   rH   r   r=   r   r  rj  rI   r   r   s   @r"   r)  r)  S  s$    5# F Fr$   r)  c                      ^  \ rS rSrSr\rSr\" SS9r	\
" 5       r\S\S\4S j5       rU 4S	 jrS
 rS r\S 5       rS rS rS rS r\rS rS rS rS rS rSrU =r $ )r   i  zA change stream cursor.

Should not be called directly by application developers. See
:meth:`~MotorCollection.watch` for example usage.

.. versionadded: 1.2
.. mongodoc:: changeStreams
MotorChangeStreamr   r#  rN   rO   c                     U $ r;   rJ   rQ   s     r"   rS   &AgnosticChangeStream.__class_getitem__  rU   r$   c                 T   > [         TU ]  S S9  Xl        UUUUUUUU	U
UUUS.U l        g )Nr<   )r   r   r   r   r   r   r   r   r   r   r   r   )rx   r=   _target_kwargs)r6   targetr   r   r   r   r   r   r   r   r   r   r   r   r3   s                 r"   r=   AgnosticChangeStream.__init__  sG      	$' *(!2$"'>&+F$8
r$   c                     U R                   (       d?  U R                  R                   R                  " S0 [        U R                  5      D6U l         g g )NrJ   )r2   rv  r   r   rw  rC   s    r"   
_lazy_initAgnosticChangeStream._lazy_init  s:    }} LL1177^:OPTP\P\:]^DM r$   c                 V    U R                  5         U R                  R                  5       $ r;   )r{  r2   rC  rC   s    r"   	_try_nextAgnosticChangeStream._try_next  s    }}%%''r$   c                 R    U R                   (       d  gU R                   R                  $ )zDoes this cursor have the potential to return more data?

.. note:: Even if :attr:`alive` is ``True``, :meth:`next` can raise
    :exc:`StopAsyncIteration` and :meth:`try_next` can return ``None``.

T)r2   r  rC   s    r"   r  AgnosticChangeStream.alive  s     }}}}"""r$   c                    #    U R                   (       a0  U R                  5       I Sh  vN nUb  U$ U R                   (       a  M0  [        5       e N&7f)ap  Advance the cursor.

This method blocks until the next change document is returned or an
unrecoverable error is raised. This method is used when iterating over
all changes in the cursor. For example::

    async def watch_collection():
        resume_token = None
        pipeline = [{'$match': {'operationType': 'insert'}}]
        try:
            async with db.collection.watch(pipeline) as stream:
                async for insert_change in stream:
                    print(insert_change)
                    resume_token = stream.resume_token
        except pymongo.errors.PyMongoError:
            # The ChangeStream encountered an unrecoverable error or the
            # resume attempt failed to recreate the cursor.
            if resume_token is None:
                # There is no usable resume token because there was a
                # failure during ChangeStream initialization.
                logging.error('...')
            else:
                # Use the interrupted ChangeStream's resume token to
                # create a new ChangeStream. The new stream will
                # continue from the last seen insert change without
                # missing any events.
                async with db.collection.watch(
                        pipeline, resume_after=resume_token) as stream:
                    async for insert_change in stream:
                        print(insert_change)

Raises :exc:`StopAsyncIteration` if this change stream is closed.

In addition to using an "async for" loop as shown in the code
example above, you can also iterate the change stream by calling
``await change_stream.next()`` repeatedly.
N)r  rC  r  )r6   rc   s     r"   r  AgnosticChangeStream.next  sB     L jj'C
 jjj
 !""	 (s   %AAAAc                    #    U R                  5       nU R                  R                  XR                  5      I Sh  vN $  N7f)a  Advance the cursor without blocking indefinitely.

This method returns the next change document without waiting
indefinitely for the next change. If no changes are available,
it returns None. For example:

.. code-block:: python3

  while change_stream.alive:
      change = await change_stream.try_next()
      # Note that the ChangeStream's resume token may be updated
      # even when no changes are returned.
      print("Current resume token: %r" % (change_stream.resume_token,))
      if change is not None:
          print("Change document: %r" % (change,))
          continue
      # We end up here when there are no recent changes.
      # Sleep for a while before trying again to avoid flooding
      # the server with getMore requests when no changes are
      # available.
      await asyncio.sleep(10)

If no change document is cached locally then this method runs a single
getMore command. If the getMore yields any documents, the next
document is returned, otherwise, if the getMore returns no documents
(because there have been no changes) then ``None`` is returned.

:Returns:
  The next change document or ``None`` when no document is available
  after running a single getMore or when the cursor is closed.

.. versionadded:: 2.1
N)r   rl   r5  r~  r6   r7  s     r"   rC  AgnosticChangeStream.try_next
  s5     D !__44T>>JJJJs   9AA Ac                 d   #    U R                   (       a  U R                  5       I Sh  vN   gg N7f)zQClose this change stream.

Stops any "async for" loops using this change stream.
N)r2   _closerC   s    r"   r   AgnosticChangeStream.close/  s%     
 ==++- r  c                     U $ r;   rJ   rC   s    r"   r  AgnosticChangeStream.__aiter__7  r  r$   c                    #    U R                   (       d=  U R                  5       nU R                  R                  XR                  5      I S h  vN   U $  N7fr;   )r2   r   rl   r5  r{  r  s     r"   r   AgnosticChangeStream.__aenter__<  sA     }}##%D//11$HHH Is   A
AAAc                 d   #    U R                   (       a  U R                  5       I S h  vN   g g  N7fr;   r  r   s       r"   r   AgnosticChangeStream.__aexit__B  r  r  c                 6    U R                   R                  5       $ r;   )rv  r   rC   s    r"   r    AgnosticChangeStream.get_io_loopF  r   r$   c                     [        S5      e)Nz/Use a change stream in "async with", not "with")RuntimeErrorrC   s    r"   r  AgnosticChangeStream.__enter__I  s    LMMr$   c                     g r;   rJ   r   s       r"   r  AgnosticChangeStream.__exit__L  r  r$   )rw  rv  r2   )!rB   rF   rG   rH   r   r   rw   r   r   r  r   resume_tokenrV   rW   rX   rS   r=   r{  r~  r   r  r  rC  r   r  r  r   r   r   r  r  rI   r   r   s   @r"   r   r     s     &.G,F#%L C F   
D_(
 
# 
#+#Z#KJ  I*N r$   r   c                   X  ^  \ rS rSrSrSr\r\" \	R                  S9r\" 5       r\" 5       r\" 5       r\" \	R                  S9r\" 5       r\" 5       r\" 5       r\" 5       r\" 5       r\" 5       r\S\S\4S j5       r  SU 4S jjr\S	 5       rS
 rS rS r S r!S r"S r#  SS jr$Sr%U =r&$ )AgnosticClientEncryptioniP  z,Explicit client-side field level encryption.MotorClientEncryptionrb   rN   rO   c                     U $ r;   rJ   rQ   s     r"   rS   *AgnosticClientEncryption.__class_getitem__e  rU   r$   c                    > U(       a  U R                   R                  U5        OSnUR                  nU R                  XXtU5      n[        T	U ]  U5        XPl        g)zExplicit client-side field level encryption.

Takes the same constructor arguments as
:class:`pymongo.encryption.ClientEncryption`, as well as:

:Parameters:
  - `io_loop` (optional): Special event loop
    instance to use instead of default.
N)rl   rm   r2   rw   rx   r=   rn   )
r6   kms_providerskey_vault_namespacekey_vault_clientrY   re   kms_tls_optionssync_clientr2   r3   s
            r"   r=   !AgnosticClientEncryption.__init__i  sU    $ OO,,W5G&//**O
 	"r$   c                 r    U R                   c  U R                  R                  5       U l         U R                   $ r;   r   rC   s    r"   re    AgnosticClientEncryption.io_loop  r   r$   c                     U R                   $ r;   r   rC   s    r"   r   $AgnosticClientEncryption.get_io_loop  r   r$   c                    #    U $ 7fr;   rJ   rC   s    r"   r   #AgnosticClientEncryption.__aenter__  r   r   c                 d   #    U R                   (       a  U R                  5       I S h  vN   g g  N7fr;   r  r   s       r"   r   "AgnosticClientEncryption.__aexit__  r  r  c                 H    [        SU R                  R                   S35      e)NzUse z in "async with", not "with")r  r3   rB   rC   s    r"   r  "AgnosticClientEncryption.__enter__  s"    T$.."9"9!::VWXXr$   c                     g r;   rJ   r   s       r"   r  !AgnosticClientEncryption.__exit__  r  r$   c                    #    [        [        U R                  U R                  5      nU" U R                  R                  5       U 5      $ 7fr;   )r   rk  rl   rF   r2   get_keys)r6   r   s     r"   r  !AgnosticClientEncryption.get_keys  s8     2>4??TXTcTcdDMM224d;;s   AA	c           	      6  #    [        [        U R                  U R                  5      nU R	                  5       nU R                  R
                  " UU R                  R                  4UR                  UUUUS.UD6I Sh  vN u  pU" XR                  U	S9U
4$  N7f)a}  Create a collection with encryptedFields.

.. warning::
    This function does not update the encryptedFieldsMap in the client's
    AutoEncryptionOpts, thus the user must create a new client after calling
    this function with the encryptedFields returned.

Normally collection creation is automatic. This method should
only be used to specify options on
creation. :class:`~pymongo.errors.EncryptionError` will be
raised if the collection already exists.

:Parameters:
  - `database`: the database in which to create a collection
  - `name`: the name of the collection to create
  - `encrypted_fields` (dict): Document that describes the encrypted fields for
    Queryable Encryption. For example::

      {
        "escCollection": "enxcol_.encryptedCollection.esc",
        "ecocCollection": "enxcol_.encryptedCollection.ecoc",
        "fields": [
            {
                "path": "firstName",
                "keyId": Binary.from_uuid(UUID('00000000-0000-0000-0000-000000000000')),
                "bsonType": "string",
                "queries": {"queryType": "equality"}
            },
            {
                "path": "ssn",
                "keyId": Binary.from_uuid(UUID('04104104-1041-0410-4104-104104104104')),
                "bsonType": "string"
            }
          ]
      }

    The "keyId" may be set to ``None`` to auto-generate the data keys.
  - `kms_provider` (optional): the KMS provider to be used
  - `master_key` (optional): Identifies a KMS-specific key used to encrypt the
    new data key. If the kmsProvider is "local" the `master_key` is
    not applicable and may be omitted.
  - `**kwargs` (optional): additional keyword arguments are the same as "create_collection".

All optional `create collection command`_ parameters should be passed
as keyword arguments to this method.
See the documentation for :meth:`~pymongo.database.Database.create_collection`
for all valid options.

:Raises:
  - :class:`~pymongo.errors.EncryptedCollectionError`: When either data-key creation or
    creating the collection fails.

.. versionadded:: 3.2

.. _create collection command:
    https://mongodb.com/docs/manual/reference/command/create

)r^  rv   encrypted_fieldskms_provider
master_keyNr   )	r   r?  rl   rF   r   r5  r2   create_encrypted_collectionrv   )r6   r^  rv   r  r  r  rz   rA  r7  collefs              r"   r  4AgnosticClientEncryption.create_encrypted_collection  s     F 7
 !88MM55	
 &&-%!	
 	
 	
  ))tDbHH	
s   A;B=B>Br   )NN)'rB   rF   rG   rH   r   r   r   rw   r   r   create_data_key_doccreate_data_keyencryptencrypt_expressiondecrypt	close_docr   rewrap_many_data_key
delete_keyget_keyadd_key_alt_nameget_key_by_alt_nameremove_key_alt_namerV   rW   rX   rS   r=   r   re   r   r   r   r  r  r  r  rI   r   r   s   @r"   r  r  P  s    62)"z'E'EFOnG%nGZ112E (>JnG#~&.&. C F    :  
Y< QI QIr$   r  )Dr   r  r   r  r(   pymongo.authpymongo.commonpymongo.databasepymongo.errorspymongo.mongo_clientpymongo.change_streamr   pymongo.client_sessionr   pymongo.collectionr   pymongo.command_cursorr   r   pymongo.cursorr   r	   pymongo.cursor_sharedr
   r   pymongo.driver_infor   pymongo.encryptionr   rj   r   r   rp   metaprogrammingr   r   r   r   r   r   r   r   r   r   motor_commonr   HAS_SSLsslImportErrorr    r#   r-   r/   rL   r^   r   r   r   r?  r  rk  rp  r   rM  rP  r)  r   r  rJ   r$   r"   <module>r     su   L          . 0 ) G 1 0 % * /  &   .
 &) "N
O
? ?"	'\ 	'S,+ S,l8 8"\L \~I*- I*X
j+/ j+Zn" n"b-%' -%`(^ (
!%. !%H/$9 /
 89F"7 9Fx~< ~BaI| aIs@  
CGs   E 
EE