o
    h@                     @  s$  d Z ddlmZ ddlmZ ddlmZmZmZm	Z	m
Z
mZmZmZmZ ddlmZmZ ddlmZ ddlmZ ddlmZmZmZ dd	lmZmZmZmZmZ dd
l m!Z! ddl"m#Z# ddl$m%Z%m&Z&m'Z' erzddl(m)Z) ddl*m+Z+ ddl,m-Z- dZ.G dd dee' Z/G dd de/e' Z0dS )z4CommandCursor class to iterate over command results.    )annotations)deque)	TYPE_CHECKINGAnyGenericIteratorMappingNoReturnOptionalSequenceUnion)CodecOptions&_convert_raw_document_lists_to_streams)_csot)_CURSOR_CLOSED_ERRORS)ConnectionFailureInvalidOperationOperationFailure)_CursorAddress_GetMore_OpMsg_OpReply_RawBatchGetMore)PinnedResponse)_ConnectionManager)_Address_DocumentOut_DocumentType)ClientSession)
Collection)
ConnectionTc                   @  sR  e Zd ZdZeZ					dhdiddZdjddZdkddZdlddZ	e
dmd!d"Zdnd%d&Z		dodpd/d0Ze
dld1d2Ze
dqd3d4Ze
drd5d6Ze
dsd7d8Zdtd:d;Zdjd<d=Zdjd>d?Zdjd@dAZdjdBdCZdudFdGZdqdHdIZdvdKdLZdwdNdOZdwdPdQZdxdTdUZdydzdYdZZd{d[d\Zd|d]d^Zd}dbdcZ e!j"dyd~dfdgZ#dS )CommandCursorz)A cursor / iterator over command cursors.r   NF
collectionCollection[_DocumentType]cursor_infoMapping[str, Any]addressOptional[_Address]
batch_sizeintmax_await_time_msOptional[int]sessionOptional[ClientSession]explicit_sessionboolcommentr   returnNonec	           	      C  s   d| _ || _|d | _t|d | _|d| _|| _|| _|| _	| jj
jjj| _|| _|| _| jdk| _|| _| jr?|   d|v rI|d | _n|j| _| | t|tsd|durftdt| dS dS )zCreate a new command cursor.Nid
firstBatchpostBatchResumeTokenr   nsz2max_await_time_ms must be an integer or None, not )	_sock_mgr_collection_idr   _dataget_postbatchresumetoken_address_batch_size_max_await_time_msdatabaseclientoptionstimeout_timeout_session_explicit_session_killed_comment_end_session_nsZ	full_namer(   
isinstancer)   	TypeErrortype	selfr"   r$   r&   r(   r*   r,   r.   r0    rP   U/var/www/html/venv/lib/python3.10/site-packages/pymongo/synchronous/command_cursor.py__init__;   s4   

zCommandCursor.__init__c                 C     |    d S N)_die_no_lockrO   rP   rP   rQ   __del__e      zCommandCursor.__del__CommandCursor[_DocumentType]c                 C  sB   t |tstdt| |dk rtd|dkrdp|| _| S )a  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``.

        :param batch_size: The size of each batch of results requested.
        z#batch_size must be an integer, not r   zbatch_size must be >= 0      )rK   r)   rL   rM   
ValueErrorr>   )rO   r(   rP   rP   rQ   r(   h   s   
zCommandCursor.batch_sizec                 C  s   t | jdkS )z^Returns `True` if the cursor has documents remaining from the
        previous batch.
        r   )lenr:   rV   rP   rP   rQ   	_has_next   s   zCommandCursor._has_nextOptional[Mapping[str, Any]]c                 C     | j S )zlRetrieve the postBatchResumeToken from the response to a
        changeStream aggregate or getMore.
        )r<   rV   rP   rP   rQ   _post_batch_resume_token   s   z&CommandCursor._post_batch_resume_tokenconnr    c                 C  sV   | j jj}|| jsd S | js)|  t|d}| jdkr$|	  d S || _d S d S )NFr   )
r8   r@   rA   Z_should_pin_cursorrE   r7   Z
pin_cursorr   r9   close)rO   rb   rA   Zconn_mgrrP   rP   rQ   _maybe_pin_connection   s   



z#CommandCursor._maybe_pin_connectionresponseUnion[_OpReply, _OpMsg]	cursor_idcodec_optionsCodecOptions[Mapping[str, Any]]user_fieldslegacy_responseSequence[_DocumentOut]c                 C  s   | ||||S rT   )Zunpack_response)rO   re   rg   rh   rj   rk   rP   rP   rQ   _unpack_response   s   zCommandCursor._unpack_responsec                 C  s   t t| jp	| j S )a  Does this cursor have the potential to return more data?

        Even if :attr:`alive` is ``True``, :meth:`next` can raise
        :exc:`StopIteration`. Best to use a for loop::

            for doc in collection.aggregate(pipeline):
                print(doc)

        .. note:: :attr:`alive` can 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:   rG   rV   rP   rP   rQ   alive   s   zCommandCursor.alivec                 C  r`   )zReturns the id of the cursor.)r9   rV   rP   rP   rQ   rg      s   zCommandCursor.cursor_idc                 C  r`   )zUThe (host, port) of the server used, or None.

        .. versionadded:: 3.0
        )r=   rV   rP   rP   rQ   r&      s   zCommandCursor.addressc                 C  s   | j r| jS dS )zmThe cursor's :class:`~pymongo.client_session.ClientSession`, or None.

        .. versionadded:: 3.6
        N)rF   rE   rV   rP   rP   rQ   r,      s   zCommandCursor.session$tuple[int, Optional[_CursorAddress]]c                 C  sP   | j }d| _ | jr |s | j}| jd usJ t| j| j}||fS d}d }||fS )NTr   )rG   r9   r=   r   rJ   )rO   Zalready_killedrg   r&   rP   rP   rQ   _prepare_to_die   s   
zCommandCursor._prepare_to_diec                 C  @   |   \}}| jjj||| j| j| j | jsd| _d| _dS )z,Closes this cursor without acquiring a lock.N)rp   r8   r@   rA   Z_cleanup_cursor_no_lockr7   rE   rF   rO   rg   r&   rP   rP   rQ   rU      s   

zCommandCursor._die_no_lockc                 C  rq   )zCloses this cursor.N)rp   r8   r@   rA   Z_cleanup_cursor_lockr7   rE   rF   rr   rP   rP   rQ   	_die_lock   s   

zCommandCursor._die_lockc                 C  s(   | j r| js| j   d | _ d S d S d S rT   )rE   rF   Z_end_implicit_sessionrV   rP   rP   rQ   rI      s   

zCommandCursor._end_sessionc                 C  s   |    dS )z$Explicitly close / kill this cursor.N)rs   rV   rP   rP   rQ   rc      s   zCommandCursor.close	operationr   c              
   C  s,  | j jj}z|j|| j| jd}W n: ty2 } z|jtv r!d| _	|j
r)|    |    d}~w ty@   d| _	|     tyK   |    w t|tr\| js\t|j|j| _|jrv|jd d }|d }|d| _|d | _n|j}t|jtsJ |jj| _| jdkr|   t|| _dS )	z/Send a getmore message and handle the response.)r&   TNr   cursorZ	nextBatchr5   r3   )r8   r@   rA   Z_run_operationrm   r=   r   coder   rG   rC   rU   rc   r   	ExceptionrK   r   r7   r   rb   Zmore_to_comeZfrom_commanddocsr;   r<   r9   datar   rg   r   r:   )rO   rt   rA   re   excru   Z	documentsrP   rP   rQ   _send_message   sH   






zCommandCursor._send_messagec                 C  s   t | js| jrt | jS | jr?| jdd\}}| j| j}| 	| 
||| j| j| jj|| j| jjj| j| jd| j n|   t | jS )a  Refreshes the cursor with more data from the server.

        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.
        .rZ   F)r]   r:   rG   r9   rJ   splitr8   Z_read_preference_forr,   r{   _getmore_classr>   rh   rE   r@   rA   r?   r7   rH   rs   )rO   ZdbnameZcollnameZ	read_prefrP   rP   rQ   _refresh&  s.   

zCommandCursor._refreshIterator[_DocumentType]c                 C     | S rT   rP   rV   rP   rP   rQ   __iter__H     zCommandCursor.__iter__r   c                 C  s&   | j r| d}|dur|S | j st)zAdvance the cursor.TN)rn   	_try_nextStopIteration)rO   docrP   rP   rQ   nextK  s   
zCommandCursor.nextc                 C  s   |   S rT   )r   rV   rP   rP   rQ   __next__U     zCommandCursor.__next__get_more_allowedOptional[_DocumentType]c                 C  s4   t | js| js|r|   t | jr| j S dS )z<Advance the cursor blocking for at most one getMore command.N)r]   r:   rG   r   popleft)rO   r   rP   rP   rQ   r   X  s
   

zCommandCursor._try_nextresultlisttotalc                 C  sv   t | js| js|   t | jr9|du r"|| j | j  dS ttt | j|D ]
}|| j	  q,dS dS )z4Get all or some available documents from the cursor.NTF)
r]   r:   rG   r   extendclearrangeminappendr   )rO   r   r   _rP   rP   rQ   _next_batcha  s   

zCommandCursor._next_batchc                 C  s   | j ddS )ar  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.

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

        .. versionadded:: 4.5
        T)r   )r   rV   rP   rP   rQ   try_nextp  s   zCommandCursor.try_nextc                 C  r   rT   rP   rV   rP   rP   rQ   	__enter__  r   zCommandCursor.__enter__exc_typeexc_valexc_tbc                 C  rS   rT   )rc   )rO   r   r   r   rP   rP   rQ   __exit__  rX   zCommandCursor.__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, so 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
        rZ   z'to_list() length must be greater than 0Nr   )rK   r)   r\   rn   r   r]   )rO   r   res	remainingrP   rP   rQ   to_list  s   zCommandCursor.to_listr   NNFNr"   r#   r$   r%   r&   r'   r(   r)   r*   r+   r,   r-   r.   r/   r0   r   r1   r2   )r1   r2   )r(   r)   r1   rY   )r1   r/   )r1   r_   )rb   r    r1   r2   NF)re   rf   rg   r+   rh   ri   rj   r_   rk   r/   r1   rl   )r1   r)   )r1   r'   )r1   r-   )r1   ro   )rt   r   r1   r2   )r1   r   )r1   r   )r   r/   r1   r   rT   )r   r   r   r+   r1   r/   )r1   r   )r1   rY   )r   r   r   r   r   r   r1   r2   )r   r+   r1   r   )$__name__
__module____qualname____doc__r   r~   rR   rW   r(   r^   propertyra   rd   rm   rn   rg   r&   r,   rp   rU   rs   rI   rc   r{   r   r   r   r   r   r   r   r   r   r   applyr   rP   rP   rP   rQ   r!   6   sV    
*




	






,
"



	


r!   c                      sH   e Zd ZeZ					d'd( fddZ		d)d*d!d"Zd+d%d&Z  ZS ),RawBatchCommandCursorr   NFr"   r#   r$   r%   r&   r'   r(   r)   r*   r+   r,   r-   r.   r/   r0   r   r1   r2   c	           	   
     s,   | drJ t |||||||| dS )aL  Create a new cursor / iterator over raw batches of BSON data.

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

        .. seealso:: The MongoDB documentation on `cursors <https://dochub.mongodb.org/core/cursors>`_.
        r4   N)r;   superrR   rN   	__class__rP   rQ   rR     s   zRawBatchCommandCursor.__init__re   rf   rg   rh   r   rj   r_   rk   list[Mapping[str, Any]]c                 C  s"   |j ||d}|st|d  |S )N)rj   r   )raw_responser   )rO   re   rg   rh   rj   rk   r   rP   rP   rQ   rm     s   z&RawBatchCommandCursor._unpack_responseindexr	   c                 C  s   t d)Nz0Cannot call __getitem__ on RawBatchCommandCursor)r   )rO   r   rP   rP   rQ   __getitem__  r   z!RawBatchCommandCursor.__getitem__r   r   r   )re   rf   rg   r+   rh   r   rj   r_   rk   r/   r1   r   )r   r)   r1   r	   )	r   r   r   r   r~   rR   rm   r   __classcell__rP   rP   r   rQ   r     s    $r   N)1r   
__future__r   collectionsr   typingr   r   r   r   r   r	   r
   r   r   Zbsonr   r   Zpymongor   Zpymongo.cursor_sharedr   Zpymongo.errorsr   r   r   Zpymongo.messager   r   r   r   r   Zpymongo.responser   Zpymongo.synchronous.cursorr   Zpymongo.typingsr   r   r   Z"pymongo.synchronous.client_sessionr   Zpymongo.synchronous.collectionr   Zpymongo.synchronous.poolr    Z_IS_SYNCr!   r   rP   rP   rP   rQ   <module>   s*   ,  r