o
    'h?                     @  s  d Z ddlmZ ddlZddlZddlmZ ddlmZm	Z	m
Z
mZmZmZmZmZmZmZmZmZ ddlmZmZ ddlmZ ddlmZ dd	lmZmZ dd
lmZ ddl m!Z!m"Z" ddl#m$Z$m%Z%m&Z&m'Z'm(Z( ddl)m*Z*m+Z+m,Z, ddl-m.Z. ddl/m0Z0m1Z1m2Z2m3Z3m4Z4m5Z5m6Z6 ddl7m8Z8 ddl9m:Z: ddl;m<Z<m=Z=m>Z>m?Z? ddl@mAZA erddlBmCZC ddlDmEZE ddlFmGZG ddlHmIZI ddlJmKZK ddlLmMZM dZNG dd dZOG dd de
e? ZPG dd  d ePe
e? ZQdS )!z1Cursor class to iterate over Mongo query results.    )annotationsN)deque)TYPE_CHECKINGAnyGenericIterableListMappingNoReturnOptionalSequenceUnioncastoverload)RE_TYPE&_convert_raw_document_lists_to_streams)Code)SON)_csothelpers_shared)validate_collation_or_none)validate_is_document_typevalidate_is_mapping)_CURSOR_CLOSED_ERRORS_QUERY_OPTIONS
CursorType_Hint_Sort)ConnectionFailureInvalidOperationOperationFailure)_create_lock)_CursorAddress_GetMore_OpMsg_OpReply_Query_RawBatchGetMore_RawBatchQuery)PinnedResponsenext)_Address_CollationIn_DocumentOut_DocumentType)validate_boolean)SupportsItems)CodecOptions)_ServerMode)ClientSession)
Collection)
ConnectionTc                   @  s.   e Zd ZdZdddZdd
dZdddZdS )_ConnectionManagerz?Used with exhaust cursors to ensure the connection is returned.connr6   more_to_comeboolc                 C  s   || _ || _t | _d S N)r8   r9   r!   _lock)selfr8   r9    r>   V/var/www/html/olx_land/venv/lib/python3.10/site-packages/pymongo/synchronous/cursor.py__init__M   s   z_ConnectionManager.__init__returnNonec                 C  s
   || _ d S r;   )r9   )r=   r9   r>   r>   r?   update_exhaustR   s   
z!_ConnectionManager.update_exhaustc                 C  s   | j r| j   d| _ dS dS )z9Return this instance's connection to the connection pool.N)r8   unpinr=   r>   r>   r?   closeU   s   

z_ConnectionManager.closeN)r8   r6   r9   r:   )r9   r:   rA   rB   rA   rB   )__name__
__module____qualname____doc__r@   rC   rF   r>   r>   r>   r?   r7   J   s
    

r7   c                   @  s  e Zd ZeZeZdddddejdddddddddddddddddfdd*d+Z	dd,d-Z
edd.d/Zedd0d1Zdd2d3Zdd5d6Zddd;d<Zdd=d>Zdd@dAZddBdCZddEdFZddGdHZddIdJZddKdLZddMdNZddOdPZddQdRZddTdUZeddXdYZedd[dYZdd^dYZdd_d`ZddcddZddedfZ 	dddkdlZ!ddmdnZ"ddodpZ#ddqdrZ$ddtduZ%ddxdyZ&ddzd{Z'		ddddZ(dddZ)edddZ*edddZ+edddZ,edddZ-dddZ.dddZ/eddddZ0e	ddddZ0	ddddZ0dddZ1dddZ2dddZ3dddZ4dddZ5dddZ6dddZ7dddZ8dddZ9ddddZ:dddZ;dddZ<dddĄZ=dddɄZ>e?j@dddd̈́ZAdS )CursorNr   F
collectionCollection[_DocumentType]filterOptional[Mapping[str, Any]]
projection1Optional[Union[Mapping[str, Any], Iterable[str]]]skipintlimitno_cursor_timeoutr:   cursor_typesortOptional[_Sort]allow_partial_resultsoplog_replay
batch_size	collationOptional[_CollationIn]hintOptional[_Hint]max_scanOptional[int]max_time_msmaxmin
return_keyOptional[bool]show_record_idsnapshotcommentOptional[Any]sessionOptional[ClientSession]allow_disk_useletrA   rB   c                 C  s  || _ d| _d| _d| _d| _|  |r|| _d| _nd| _d| _|p#i }td| t|t	s7t
dt| t|t	sEt
dt| td| |rW| jsWtjdtd	d
 |tjtjtjtjfvrgtdtd|	 td|
 t|t	st
dt| |dk rtd|durtd|}|durt|d}|durtd| || _|| _|du| _|| _|| _|| _|| _|rt |pd| _!|| _"d| _#|| _$|| _%| j j&j'j(j)| _*d| _+|| _,|| _-t.|| _/|| _0|| _1|| _2|| _3|  | 4| d| _5t6 | _7d| _8d| _9|j:| _;d| _<|j=| _>|| _?|| _@|r#|  j?tAd O  _?|	r/|  j?tAd O  _?|
r;|  j?tAd O  _?|j&jB| _C|jB| _DtErPd| _F| G  dS |tjk| _d| _FdS )a
  Create a new cursor.

        Should not be called directly by application developers - see
        :meth:`~pymongo.collection.Collection.find` instead.

        .. seealso:: The MongoDB documentation on `cursors <https://dochub.mongodb.org/core/cursors>`_.
        NFTrO   z%skip must be an instance of int, not z&limit must be an instance of int, not rV   zuse an explicit session with no_cursor_timeout=True otherwise the cursor may still timeout after 30 minutes, for more info see https://mongodb.com/docs/v4.4/reference/method/cursor.noCursorTimeout/#session-idle-timeout-overrides-nocursortimeout   )
stacklevelz!not a valid value for cursor_typerZ   r[   #batch_size must be an integer, not r   batch_size must be >= 0rn   rQ   ro   
no_timeoutpartial)H_collection_id_exhaust	_sock_mgr_killed_session_explicit_sessionr   
isinstancerT   	TypeErrortyper0   warningswarnUserWarningr   NON_TAILABLETAILABLETAILABLE_AWAITEXHAUST
ValueErrorr   _fields_list_to_dictr   _let_spec_has_filter_projection_skip_limit_batch_size_index_document	_ordering	_max_scan_explain_comment_max_time_msdatabaseclientoptionstimeout_timeout_max_await_time_ms_max_minr   
_collation_return_key_show_record_id_allow_disk_use	_snapshot	_set_hint_emptyr   _data_address
_retrievedcodec_options_codec_options_read_preferenceread_concern_read_concern_query_flags_cursor_typer   name_dbname	_collname_IS_SYNC_exhaust_checked_supports_exhaust)r=   rM   rO   rQ   rS   rU   rV   rW   rX   rZ   r[   r\   r]   r_   ra   rc   rd   re   rf   rh   ri   rj   rl   rn   ro   specr>   r>   r?   r@   `   s   $















zCursor.__init__c                 C  s<   | j tjkr| jjjjrtd| jrtdd| _	d S d S )N+Exhaust cursors are not supported by mongos%Can't use limit and exhaust together.T)
r   r   r   rv   r   r   	is_mongosr   r   rx   rE   r>   r>   r?   r      s   
zCursor._supports_exhaustc                 C     | j S )zdThe :class:`~pymongo.collection.Collection` that this
        :class:`Cursor` is iterating.
        )rv   rE   r>   r>   r?   rM     s   zCursor.collectionc                 C  r   )z)The number of documents retrieved so far.)r   rE   r>   r>   r?   	retrieved	  s   zCursor.retrievedc                 C     |    d S r;   )_die_no_lockrE   r>   r>   r?   __del__     zCursor.__del__Cursor[_DocumentType]c                 C  s
   |  dS )a  Get a clone of this cursor.

        Returns a new Cursor instance with options matching those that have
        been set on the current instance. The clone will be completely
        unevaluated, even if the current instance has been partially or
        completely evaluated.
        T_clonerE   r>   r>   r?   clone  s   
zCursor.cloneTdeepcopybaseOptional[Cursor]c                   s\   |s| j r| | j}n| d}d  fdd| j D }|r&| |}|j| |S )zInternal clone helper.N)r   rQ   rS   rU   rc   max_await_time_msrj   rd   re   orderingexplainr_   r\   ra   query_flagsr]   emptyrh   rf   rn   ri   exhaust
has_filterrW   c                   s0   i | ]\}}| d r|dd  v r||qS )_   N)
startswith).0kvvalues_to_cloner>   r?   
<dictcomp>=  s    z!Cursor._clone.<locals>.<dictcomp>)r|   _clone_baser{   __dict__items	_deepcopyupdate)r=   r   r   datar>   r   r?   r     s   


zCursor._clonec                 C  s   | j | j|dS )zACreates an empty Cursor object for information to be copied into.)rl   )	__class__rv   )r=   rl   r>   r>   r?   r   E  s   zCursor._clone_baseMapping[str, Any]c                 C  s8  i }| j r
| j |d< | jrd|d< | jr| j|d< | jr!| j|d< | jr)| j|d< | jr1| j|d< | jdur;| j|d	< | jrC| j|d
< | jrK| j|d< | j	durU| j	|d< | j
dur_| j
|d< | jduri| j|d< |rt| j}d|vrxd|i}|| |S d| jv rt| jdkstt| jdkrd| jiS | jS )z Get the spec to use for a query.z$orderbyTz$explainz$hintro   z$commentz$maxScanNz
$maxTimeMSz$maxz$minz
$returnKeyz$showDiskLocz	$snapshotz$queryqueryr   )r   r   _hintr   r   r   r   r   r   r   r   r   dictr   r   lenr+   iter)r=   	operatorsr   r>   r>   r?   _query_specI  sD   
















*
zCursor._query_specc                 C  s   | j s| jdurtddS )z;Check if it is okay to chain more options onto this cursor.Nz(cannot set options after executing query)r   rw   r   rE   r>   r>   r?   _check_okay_to_chain{  s   zCursor._check_okay_to_chainmaskc                 C  sj   t |tstdt| |   |td @ r,| jrtd| jj	j
jr)tdd| _|  j|O  _| S )zsSet arbitrary query flags using a bitmask.

        To set the tailable flag:
        cursor.add_option(2)
        mask must be an int, not r   r   r   T)r}   rT   r~   r   r   r   r   r   rv   r   r   r   rx   r   r=   r   r>   r>   r?   
add_option  s   
zCursor.add_optionc                 C  sJ   t |tstdt| |   |td @ rd| _|  j| M  _| S )zzUnset arbitrary query flags using a bitmask.

        To unset the tailable flag:
        cursor.remove_option(2)
        r   r   F)r}   rT   r~   r   r   r   rx   r   r   r>   r>   r?   remove_option  s   
zCursor.remove_optionc                 C  s.   t |tstdt| |   || _| S )a  Specifies whether MongoDB can use temporary disk files while
        processing a blocking sort operation.

        Raises :exc:`TypeError` if `allow_disk_use` is not a boolean.

        .. note:: `allow_disk_use` requires server version **>= 4.4**

        :param allow_disk_use: if True, MongoDB may use temporary
            disk files to store data exceeding the system memory limit while
            processing a blocking sort operation.

        .. versionadded:: 3.11
        z#allow_disk_use must be a bool, not )r}   r:   r~   r   r   r   )r=   rn   r>   r>   r?   rn     s
   
zCursor.allow_disk_usec                 C  sB   t |tstdt| | jrtd|   d| _|| _| S )a  Limits the number of results to be returned by this cursor.

        Raises :exc:`TypeError` if `limit` is not an integer. Raises
        :exc:`~pymongo.errors.InvalidOperation` if this :class:`Cursor`
        has already been used. The last `limit` applied to this cursor
        takes precedence. A limit of ``0`` is equivalent to no limit.

        :param limit: the number of results to return

        .. seealso:: The MongoDB documentation on `limit <https://dochub.mongodb.org/core/limit>`_.
        zlimit must be an integer, not r   F)	r}   rT   r~   r   rx   r   r   r   r   )r=   rU   r>   r>   r?   rU     s   
zCursor.limitc                 C  >   t |tstdt| |dk rtd|   || _| S )af  Limits the number of documents returned in one batch. Each batch
        requires a round trip to the server. It can be adjusted to optimize
        performance and limit data transfer.

        .. note:: batch_size can not override MongoDB's internal limits on the
           amount of data it will return to the client in a single batch (i.e
           if you set batch size to 1,000,000,000, MongoDB will currently only
           return 4-16MB of results per batch).

        Raises :exc:`TypeError` if `batch_size` is not an integer.
        Raises :exc:`ValueError` if `batch_size` is less than ``0``.
        Raises :exc:`~pymongo.errors.InvalidOperation` if this
        :class:`Cursor` has already been used. The last `batch_size`
        applied to this cursor takes precedence.

        :param batch_size: The size of each batch of results requested.
        rr   r   rs   )r}   rT   r~   r   r   r   r   )r=   r\   r>   r>   r?   r\     s   
zCursor.batch_sizec                 C  r   )a  Skips the first `skip` results of this cursor.

        Raises :exc:`TypeError` if `skip` is not an integer. Raises
        :exc:`ValueError` if `skip` is less than ``0``. Raises
        :exc:`~pymongo.errors.InvalidOperation` if this :class:`Cursor` has
        already been used. The last `skip` applied to this cursor takes
        precedence.

        :param skip: the number of results to skip
        zskip must be an integer, not r   zskip must be >= 0)r}   rT   r~   r   r   r   r   )r=   rS   r>   r>   r?   rS     s   
zCursor.skipc                 C  s6   t |ts|durtdt| |   || _| S )a  Specifies a time limit for a query operation. If the specified
        time is exceeded, the operation will be aborted and
        :exc:`~pymongo.errors.ExecutionTimeout` is raised. If `max_time_ms`
        is ``None`` no limit is applied.

        Raises :exc:`TypeError` if `max_time_ms` is not an integer or ``None``.
        Raises :exc:`~pymongo.errors.InvalidOperation` if this :class:`Cursor`
        has already been used.

        :param max_time_ms: the time limit after which the operation is aborted
        Nz,max_time_ms must be an integer or None, not )r}   rT   r~   r   r   r   )r=   rc   r>   r>   r?   rc     s
   zCursor.max_time_msr   c                 C  sB   t |ts|durtdt| |   | jtj@ r|| _| S )aS  Specifies a time limit for a getMore operation on a
        :attr:`~pymongo.cursor.CursorType.TAILABLE_AWAIT` cursor. For all other
        types of cursor max_await_time_ms is ignored.

        Raises :exc:`TypeError` if `max_await_time_ms` is not an integer or
        ``None``. Raises :exc:`~pymongo.errors.InvalidOperation` if this
        :class:`Cursor` has already been used.

        .. note:: `max_await_time_ms` requires server version **>= 3.2**

        :param max_await_time_ms: the time limit after which the operation is
            aborted

        .. versionadded:: 3.2
        Nz2max_await_time_ms must be an integer or None, not )	r}   rT   r~   r   r   r   r   r   r   )r=   r   r>   r>   r?   r     s   zCursor.max_await_time_msindexr/   c                 C     d S r;   r>   r=   r   r>   r>   r?   __getitem__-     zCursor.__getitem__slicec                 C  r   r;   r>   r   r>   r>   r?   r   1  r   Union[int, slice]+Union[_DocumentType, Cursor[_DocumentType]]c                 C  s  t r|   d| _t|trP|jdurtdd}|jdur*|jdk r'td|j}|jdurF|j| }|dk r>td| |dkrEd| _nd}|| _	|| _
| S t|tr|dk r]td|  }||| j	  |d | jtj M  _|D ]}|  S td	td
| td)aI  Get a single document or a slice of documents from this cursor.

        .. warning:: A :class:`~Cursor` is not a Python :class:`list`. Each
          index access or slice requires that a new query be run using skip
          and limit. Do not iterate the cursor using index accesses.
          The following example is **extremely inefficient** and may return
          surprising results::

            cursor = db.collection.find()
            # Warning: This runs a new query for each document.
            # Don't do this!
            for idx in range(10):
                print(cursor[idx])

        Raises :class:`~pymongo.errors.InvalidOperation` if this
        cursor has already been used.

        To get a single document use an integral index, e.g.::

          >>> db.test.find()[50]

        An :class:`IndexError` will be raised if the index is negative
        or greater than the amount of documents in this cursor. Any
        limit previously applied to this cursor will be ignored.

        To get a slice of documents use a slice index, e.g.::

          >>> db.test.find()[20:25]

        This will return this cursor with a limit of ``5`` and skip of
        ``20`` applied.  Using a slice index will override any prior
        limits or skips applied to this cursor (including those
        applied through previous calls to this method). Raises
        :class:`IndexError` when the slice has a step, a negative
        start value, or a stop value less than or equal to the start
        value.

        :param index: An integer or slice index to be applied to this cursor
        FNz+Cursor instances do not support slice stepsr   z0Cursor instances do not support negative indicesz8stop index must be greater than start index for slice %rTz no such item for Cursor instancez.index %r cannot be applied to Cursor instancesz Cursor does not support indexing)r   r   r   r}   r   step
IndexErrorstartstopr   r   rT   r   rS   rU   r   r   r   r~   )r=   r   rS   rU   r   docr>   r>   r?   r   5  sH   (







c                 C     |    || _| S )a1  **DEPRECATED** - Limit the number of documents to scan when
        performing the query.

        Raises :class:`~pymongo.errors.InvalidOperation` if this
        cursor has already been used. Only the last :meth:`max_scan`
        applied to this cursor has any effect.

        :param max_scan: the maximum number of documents to scan

        .. versionchanged:: 3.7
          Deprecated :meth:`max_scan`. Support for this option is deprecated in
          MongoDB 4.0. Use :meth:`max_time_ms` instead to limit server side
          execution time.
        )r   r   )r=   ra   r>   r>   r?   ra     s   zCursor.max_scanr   r   c                 C  6   t |ttfstdt| |   t|| _| S )a!  Adds ``max`` operator that specifies upper bound for specific index.

        When using ``max``, :meth:`~hint` should also be configured to ensure
        the query uses the expected index and starting in MongoDB 4.2
        :meth:`~hint` will be required.

        :param spec: a list of field, limit pairs specifying the exclusive
            upper bound for all keys of a specific index in order.

        .. versionchanged:: 3.8
           Deprecated cursors that use ``max`` without a :meth:`~hint`.

        .. versionadded:: 2.7
        /spec must be an instance of list or tuple, not )r}   listtupler~   r   r   r   r   r=   r   r>   r>   r?   rd     
   
z
Cursor.maxc                 C  r   )a!  Adds ``min`` operator that specifies lower bound for specific index.

        When using ``min``, :meth:`~hint` should also be configured to ensure
        the query uses the expected index and starting in MongoDB 4.2
        :meth:`~hint` will be required.

        :param spec: a list of field, limit pairs specifying the inclusive
            lower bound for all keys of a specific index in order.

        .. versionchanged:: 3.8
           Deprecated cursors that use ``min`` without a :meth:`~hint`.

        .. versionadded:: 2.7
        r   )r}   r   r   r~   r   r   r   r   r   r>   r>   r?   re     r   z
Cursor.minkey_or_listr   	directionOptional[Union[int, str]]c                 C  s$   |    t||}t|| _| S )a  Sorts this cursor's results.

        Pass a field name and a direction, either
        :data:`~pymongo.ASCENDING` or :data:`~pymongo.DESCENDING`.::

            for doc in collection.find().sort('field', pymongo.ASCENDING):
                print(doc)

        To sort by multiple fields, pass a list of (key, direction) pairs.
        If just a name is given, :data:`~pymongo.ASCENDING` will be inferred::

            for doc in collection.find().sort([
                    'field1',
                    ('field2', pymongo.DESCENDING)]):
                print(doc)

        Text search results can be sorted by relevance::

            cursor = db.test.find(
                {'$text': {'$search': 'some words'}},
                {'score': {'$meta': 'textScore'}})

            # Sort by 'score' field.
            cursor.sort([('score', {'$meta': 'textScore'})])

            for doc in cursor:
                print(doc)

        For more advanced text search functionality, see MongoDB's
        `Atlas Search <https://docs.atlas.mongodb.com/atlas-search/>`_.

        Raises :class:`~pymongo.errors.InvalidOperation` if this cursor has
        already been used. Only the last :meth:`sort` applied to this
        cursor has any effect.

        :param key_or_list: a single key or a list of (key, direction)
            pairs specifying the keys to sort on
        :param direction: only used if `key_or_list` is a single
            key, if not given :data:`~pymongo.ASCENDING` is assumed
        )r   r   _index_listr   r   )r=   r  r  keysr>   r>   r?   rX     s   +zCursor.sortc                 C  s*   |   }d|_|jrt|j |_t|S )a  Returns an explain plan record for this cursor.

        .. note:: This method uses the default verbosity mode of the
          `explain command
          <https://mongodb.com/docs/manual/reference/command/explain/>`_,
          ``allPlansExecution``. To use a different verbosity use
          :meth:`~pymongo.database.Database.command` to run the explain
          command directly.

        .. seealso:: The MongoDB documentation on `explain <https://dochub.mongodb.org/core/explain>`_.
        T)r   r   r   absr+   )r=   cr>   r>   r?   r     s
   zCursor.explainc                 C  s6   |d u r	d | _ d S t|tr|| _ d S t|| _ d S r;   )r   r}   strr   r   r   r>   r>   r?   r   
  s   

zCursor._set_hintc                 C  s   |    | | | S )a  Adds a 'hint', telling Mongo the proper index to use for the query.

        Judicious use of hints can greatly improve query
        performance. When doing a query on multiple fields (at least
        one of which is indexed) pass the indexed field as a hint to
        the query. Raises :class:`~pymongo.errors.OperationFailure` if the
        provided hint requires an index that does not exist on this collection,
        and raises :class:`~pymongo.errors.InvalidOperation` if this cursor has
        already been used.

        `index` should be an index as passed to
        :meth:`~pymongo.collection.Collection.create_index`
        (e.g. ``[('field', ASCENDING)]``) or the name of the index.
        If `index` is ``None`` any existing hint for this query is
        cleared. The last hint applied to this cursor takes precedence
        over all others.

        :param index: index to hint on (as an index specifier)
        )r   r   r   r>   r>   r?   r_     s   
zCursor.hintr   c                 C  r   )a"  Adds a 'comment' to the cursor.

        http://mongodb.com/docs/manual/reference/operator/comment/

        :param comment: A string to attach to the query to help interpret and
            trace the operation in the server logs and in profile data.

        .. versionadded:: 2.7
        )r   r   )r=   rj   r>   r>   r?   rj   ,  s   
zCursor.commentcodeUnion[str, Code]c                 C  sJ   |    t|tst|}| jrt| j}ntt| j}||d< || _| S )a  Adds a `$where`_ clause to this query.

        The `code` argument must be an instance of :class:`str` or
        :class:`~bson.code.Code` containing a JavaScript expression.
        This expression will be evaluated for each document scanned.
        Only those documents for which the expression evaluates to
        *true* will be returned as results. The keyword *this* refers
        to the object currently being scanned. For example::

            # Find all documents where field "a" is less than "b" plus "c".
            for doc in db.test.find().where('this.a < (this.b + this.c)'):
                print(doc)

        Raises :class:`TypeError` if `code` is not an instance of
        :class:`str`. Raises :class:`~pymongo.errors.InvalidOperation` if this
        :class:`Cursor` has already been used. Only the last call to
        :meth:`where` applied to a :class:`Cursor` has any effect.

        .. note:: MongoDB 4.4 drops support for :class:`~bson.code.Code`
          with scope variables. Consider using `$expr`_ instead.

        :param code: JavaScript expression to use as a filter

        .. _$expr: https://mongodb.com/docs/manual/reference/operator/query/expr/
        .. _$where: https://mongodb.com/docs/manual/reference/operator/query/where/
        z$where)r   r}   r   r   r   r   r   )r=   r	  r   r>   r>   r?   where:  s   
zCursor.wherec                 C  s   |    t|| _| S )a  Adds a :class:`~pymongo.collation.Collation` to this query.

        Raises :exc:`TypeError` if `collation` is not an instance of
        :class:`~pymongo.collation.Collation` or a ``dict``. Raises
        :exc:`~pymongo.errors.InvalidOperation` if this :class:`Cursor` has
        already been used. Only the last collation applied to this cursor has
        any effect.

        :param collation: An instance of :class:`~pymongo.collation.Collation`.
        )r   r   r   )r=   r]   r>   r>   r?   r]   d  s   
zCursor.collationresponseUnion[_OpReply, _OpMsg]	cursor_idr   r2   user_fieldslegacy_responseSequence[_DocumentOut]c                 C  s   | ||||S r;   )unpack_response)r=   r  r  r   r  r  r>   r>   r?   _unpack_responses  s   zCursor._unpack_responser3   c                 C  s    | j d u r| j| j| _ | j S r;   )r   rv   _read_preference_forrl   rE   r>   r>   r?   _get_read_preference}  s   
zCursor._get_read_preferencec                 C  s   t t| jp	| j S )a  Does this cursor have the potential to return more data?

        This is mostly useful with `tailable cursors
        <https://www.mongodb.com/docs/manual/core/tailable-cursors/>`_
        since they will stop iterating even though they *may* return more
        results in the future.

        With regular cursors, simply use a for loop instead of :attr:`alive`::

            for doc in collection.find():
                print(doc)

        .. note:: Even if :attr:`alive` is True, :meth:`next` can raise
          :exc:`StopIteration`. :attr:`alive` can also be True while iterating
          a cursor from a failed server. In this case :attr:`alive` will
          return False after :meth:`next` fails to retrieve the next batch
          of results from the server.
        )r:   r   r   rz   rE   r>   r>   r?   alive  s   zCursor.alivec                 C  r   )zDReturns the id of the cursor

        .. versionadded:: 2.2
        )rw   rE   r>   r>   r?   r    s   zCursor.cursor_idOptional[tuple[str, Any]]c                 C  r   )zzThe (host, port) of the server used, or None.

        .. versionchanged:: 3.0
           Renamed from "conn_id".
        )r   rE   r>   r>   r?   address  s   zCursor.addressc                 C  s   | j r| jS dS )zmThe cursor's :class:`~pymongo.client_session.ClientSession`, or None.

        .. versionadded:: 3.6
        N)r|   r{   rE   r>   r>   r?   rl     s   zCursor.sessionc                 C     | j ddS )zKSupport function for `copy.copy()`.

        .. versionadded:: 2.4
        Fr   r   rE   r>   r>   r?   __copy__     zCursor.__copy__memoc                 C  r  )zOSupport function for `copy.deepcopy()`.

        .. versionadded:: 2.4
        Tr  r   )r=   r  r>   r>   r?   __deepcopy__  r  zCursor.__deepcopy__xr   &Optional[dict[int, Union[list, dict]]]r   c                 C  r   r;   r>   r=   r  r  r>   r>   r?   r     r   zCursor._deepcopyr1   r   c                 C  r   r;   r>   r!  r>   r>   r?   r     s   Union[Iterable, SupportsItems]Union[list, dict]c           	      C  s   t |dsg dt|}}}ni dtd| }}}|du r#i }t|}||v r/|| S |||< |D ]9\}}t|ttfrLt|tsL| 	||}nt|t
sWt||}|r_|| q5t|t
sjt||}|||< q5|S )zDeepcopy helper for the data dictionary or list.

        Regular expressions cannot be deep copied but as they are immutable we
        don't have to copy them when cloning.
        r   TFr1   N)hasattr	enumerater   r   idr}   r   r   r   r   r   copyr   append)	r=   r  r  yis_listiteratorval_idkeyvaluer>   r>   r?   r     s(   




already_killed$tuple[int, Optional[_CursorAddress]]c                 C  sV   d| _ | jr#|s#| j}| jd usJ t| j| j d| j }||fS d}d }||fS )NT.r   )rz   rw   r   r"   r   r   r=   r/  r  r  r>   r>   r?   _prepare_to_die  s   
zCursor._prepare_to_diec                 C  b   z| j }W n
 ty   Y dS w | |\}}| jjj||| j| j| j	 | j	s,d| _d| _dS )z,Closes this cursor without acquiring a lock.N)
rz   AttributeErrorr3  rv   r   r   _cleanup_cursor_no_lockry   r{   r|   r2  r>   r>   r?   r     s   


zCursor._die_no_lockc                 C  r4  )zCloses this cursor.N)
rz   r5  r3  rv   r   r   _cleanup_cursor_lockry   r{   r|   r2  r>   r>   r?   	_die_lock  s    


zCursor._die_lockc                 C  s   |    dS )z$Explicitly close / kill this cursor.N)r8  rE   r>   r>   r?   rF     s   zCursor.closer-  r  c                 C  sf   i }| j r
| j |d< | jdur| j|d< | jr| j|d< | jdur&| j|d< | jj|fd| ji|S )aO  Get a list of distinct values for `key` among all documents
        in the result set of this query.

        Raises :class:`TypeError` if `key` is not an instance of
        :class:`str`.

        The :meth:`distinct` method obeys the
        :attr:`~pymongo.collection.Collection.read_preference` of the
        :class:`~pymongo.collection.Collection` instance on which
        :meth:`~pymongo.collection.Collection.find` was called.

        :param key: name of key for which we want to get the distinct values

        .. seealso:: :meth:`pymongo.collection.Collection.distinct`
        r   N	maxTimeMSrj   r]   rl   )r   r   r   r   rv   distinctr{   )r=   r-  r   r>   r>   r?   r:  #  s   





zCursor.distinct	operationUnion[_Query, _GetMore]c           
   
   C  s,  | j jj}|jr| jrtdz|j|| j| jd}W nP t	yR } z+|j
tv s+| jr.d| _|jr6|   n|   |j
tv rM| jtd @ rMW Y d}~dS  d}~w ty`   d| _|     tyk   |    w |j| _t|tr| jst|j|j| _|j}|j}|jr|dkr|d d }|d	 | _|d
kr|d }|d}	|	r|	 dd\| _!| _"n|d }t#|| _$|  j%t&|7  _%n-d| _t#|| _$|  j%t&|7  _%nt|j't(sJ |j'j)| _t#|| _$|  j%|j'j*7  _%| jdkr|   | j+r| jr| j+| j%kr|   dS dS dS dS )a#  Send a query or getmore operation and handles the response.

        If operation is ``None`` this is an exhaust cursor, which reads
        the next result batch off the exhaust socket instead of
        sending getMore messages to the server.

        Can raise ConnectionFailure.
        z.exhaust cursors do not support auto encryption)r  Ttailable_cursorNr   r   cursorr&  find
firstBatchnsr1  r   	nextBatch),rv   r   r   
_encrypterrx   r   _run_operationr  r   r    r	  r   rz   r   r   rF   r   r   r   BaseExceptionr  r}   r)   ry   r7   r8   r9   r   docsfrom_commandrw   getsplitr   r   r   r   r   r   r   r%   r  number_returnedr   )
r=   r;  r   r  exccmd_namerF  r>  	documentsrA  r>   r>   r?   _send_message?  st   
	











zCursor._send_messagec                 C  s8  t | js| jrt | jS | js| jjj | _| jdu r[| j	s#| j
r*| js*td| | j| jjj| jj| j|  | j| j|  | j| j| j| j| j| jjj| j| j}| | n<| jr| jrq| j| j }| jrpt|| j}n| j}| | j| j || j| j|  | j| jjj| j!| j"| j| j#}| | t | jS )a  Refreshes the cursor with more data from Mongo.

        Returns the length of self._data after refresh. Will exit early if
        self._data is already non-empty. Raises OperationFailure when the
        cursor cannot be refreshed due to an error on the query.
        NzoPassing a 'hint' is required when using the min/max query option to ensure the query utilizes the correct index)$r   r   rz   r{   rv   r   r   _ensure_sessionrw   r   r   r   r   _query_classr   r   r   r   r   r   r  r   r   r   r   r   rx   rN  r   re   _getmore_classr   r   r   ry   r   )r=   qrU   gr>   r>   r?   _refresh  sf   



zCursor._refreshc                 C  s,   |    t | _d| _d| _d| _d| _| S )a  Rewind this cursor to its unevaluated state.

        Reset this cursor if it has been partially or completely evaluated.
        Any options that are present on the cursor will remain in effect.
        Future iterating performed on this cursor will cause new queries to
        be sent to the server, even if the resultant data has already been
        retrieved by this cursor.
        Nr   F)rF   r   r   rw   r   r   rz   rE   r>   r>   r?   rewind  s   	zCursor.rewindc                 C  s>   | j s
d| _ |   | jrtt| js|  r| j S t)zAdvance the cursor.T)r   r   r   StopIterationr   r   rT  popleftrE   r>   r>   r?   r+     s   
zCursor.nextresulttotalc                 C  s   | j s
d| _ |   | jrdS t| js|  r@|du r)|| j | j  dS tt	t| j|D ]
}|
| j  q3dS dS )z*Get all or some documents from the cursor.TFN)r   r   r   r   r   rT  extendclearrangere   r(  rW  )r=   rX  rY  r   r>   r>   r?   _next_batch  s   
zCursor._next_batchc                 C  s   |   S r;   r*   rE   r>   r>   r?   __next__     zCursor.__next__c                 C     | S r;   r>   rE   r>   r>   r?   __iter__     zCursor.__iter__c                 C  r`  r;   r>   rE   r>   r>   r?   	__enter__	  rb  zCursor.__enter__exc_typeexc_valexc_tbc                 C  r   r;   )rF   )r=   rd  re  rf  r>   r>   r?   __exit__  r   zCursor.__exit__lengthlist[_DocumentType]c                 C  sf   g }|}t |tr|dk rtd| jr1| ||s	 |S |dur.|t| }|dkr.	 |S | js|S )ak  Converts the contents of this cursor to a list more efficiently than ``[doc for doc in cursor]``.

        To use::

          >>> cursor.to_list()

        Or, to read at most n items from the cursor::

          >>> cursor.to_list(n)

        If the cursor is empty or has no more results, an empty list will be returned.

        .. versionadded:: 4.9
        r   z'to_list() length must be greater than 0Nr   )r}   rT   r   r  r]  r   )r=   rh  res	remainingr>   r>   r?   to_list  s   zCursor.to_list)2rM   rN   rO   rP   rQ   rR   rS   rT   rU   rT   rV   r:   rW   rT   rX   rY   rZ   r:   r[   r:   r\   rT   r]   r^   r_   r`   ra   rb   rc   rb   rd   rY   re   rY   rf   rg   rh   rg   ri   rg   rj   rk   rl   rm   rn   rg   ro   rg   rA   rB   rG   )rA   rN   )rA   rT   )rA   r   )TN)r   r:   r   r   rA   rL   )rl   rm   rA   rL   )rA   r   )r   rT   rA   r   )rn   r:   rA   r   )rU   rT   rA   r   )r\   rT   rA   r   )rS   rT   rA   r   )rc   rb   rA   r   )r   rb   rA   r   )r   rT   rA   r/   )r   r   rA   r   )r   r   rA   r   )ra   rb   rA   r   )r   r   rA   r   r;   )r  r   r  r  rA   r   rA   r/   )r   r`   rA   rB   )r   r`   rA   r   )rj   r   rA   r   )r	  r
  rA   r   )r]   r^   rA   r   NF)r  r  r  rb   r   r2   r  rP   r  r:   rA   r  )rA   r3   )rA   r:   )rA   rb   )rA   r  )rA   rm   )r  r   rA   r   )r  r   r  r   rA   r   )r  r1   r  r   rA   r   )r  r"  r  r   rA   r#  )r/  r:   rA   r0  )r-  r  rA   r   )r;  r<  rA   rB   )rX  r   rY  rb   rA   r:   )rd  r   re  r   rf  r   rA   rB   )rh  rb   rA   ri  )BrH   rI   rJ   r&   rP  r#   rQ  r   r   r@   r   propertyrM   r   r   r   r   r   r   r   r   r   rn   rU   r\   rS   rc   r   r   r   ra   rd   re   rX   r   r   r_   rj   r  r]   r  r  r  r  r  rl   r  r  r   r3  r   r8  rF   r:  rN  rT  rU  r+   r]  r^  ra  rc  rg  r   applyrl  r>   r>   r>   r?   rL   \   s     
	



*

2









R


0





*


	

#





T
@




rL   c                      sN   e Zd ZdZeZeZd! fd	d
Z		d"d#ddZ	d$ddZ
d%dd Z  ZS )&RawBatchCursorzFA cursor / iterator over raw batches of BSON data from a query result.rM   rN   argsr   kwargsrA   rB   c                   s   t  j|g|R i | dS )aG  Create a new cursor / iterator over raw batches of BSON data.

        Should not be called directly by application developers -
        see :meth:`~pymongo.collection.Collection.find_raw_batches`
        instead.

        .. seealso:: The MongoDB documentation on `cursors <https://dochub.mongodb.org/core/cursors>`_.
        N)superr@   )r=   rM   rr  rs  r   r>   r?   r@   3  s   	zRawBatchCursor.__init__NFr  r  r  rb   r   CodecOptions[Mapping[str, Any]]r  rP   r  r:   list[_DocumentOut]c                 C  s,   |j ||d}|st|d  ttd |S )N)r  r   r.   )raw_responser   r   r   )r=   r  r  r   r  r  rx  r>   r>   r?   r  >  s   zRawBatchCursor._unpack_responser/   c                 C  s   | j dt| jd}| S )zReturns an explain plan record for this cursor.

        .. seealso:: The MongoDB documentation on `explain <https://dochub.mongodb.org/core/explain>`_.
        T)r   r   )r   rL   rM   r   )r=   r   r>   r>   r?   r   M  s   zRawBatchCursor.explainr   r
   c                 C  s   t d)Nz)Cannot call __getitem__ on RawBatchCursor)r   r   r>   r>   r?   r   U  r_  zRawBatchCursor.__getitem__)rM   rN   rr  r   rs  r   rA   rB   rn  )r  r  r  rb   r   rv  r  rP   r  r:   rA   rw  rm  )r   r   rA   r
   )rH   rI   rJ   rK   r(   rP  r'   rQ  r@   r  r   r   __classcell__r>   r>   ru  r?   rq  -  s    
rq  )RrK   
__future__r   r'  r   collectionsr   typingr   r   r   r   r   r	   r
   r   r   r   r   r   bsonr   r   	bson.coder   bson.sonr   pymongor   r   pymongo.collationr   pymongo.commonr   r   pymongo.cursor_sharedr   r   r   r   r   pymongo.errorsr   r   r    pymongo.lockr!   pymongo.messager"   r#   r$   r%   r&   r'   r(   pymongo.responser)   pymongo.synchronous.helpersr+   pymongo.typingsr,   r-   r.   r/   pymongo.write_concernr0   	_typeshedr1   bson.codec_optionsr2   pymongo.read_preferencesr3   "pymongo.synchronous.client_sessionr4   pymongo.synchronous.collectionr5   pymongo.synchronous.poolr6   r   r7   rL   rq  r>   r>   r>   r?   <module>   sP   8$	         Z