U
    d7                     @  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mZ ddlmZmZ ddlmZ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#m$Z$m%Z% erddl&m'Z' ddl(m)Z) ddl*m+Z+ G dd dee% Z,G dd de,ee% Z-dS )z4CommandCursor class to iterate over command results.    )annotations)deque)
TYPE_CHECKINGAnyGenericIteratorListMappingNoReturnOptionalSequenceUnion)CodecOptions&_convert_raw_document_lists_to_streams)_CURSOR_CLOSED_ERRORS_ConnectionManager)ConnectionFailureInvalidOperationOperationFailure)_CursorAddress_GetMore_OpMsg_OpReply_RawBatchGetMore)PinnedResponse)_Address_DocumentOut_DocumentType)ClientSession)
Collection)
Connectionc                   @  s  e Zd ZdZeZdMddddd	d
dddd	ddZddddZdNdddddZdddddZ	ddddZ
dddddZdddd Zed!dd"d#Zd$dd%d&d'Zd(dd)d*d+ZdOd,d	d-d!dd.d/d0d1Zddd2d3Zeddd4d5Zeddd6d7Zeddd8d9Zed
dd:d;Zd<dd=d>Zd?dd@dAZeZddBdCdDdEZdBddFdGZdddHdIZdddddJdKdLZdS )PCommandCursorz)A cursor / iterator over command cursors.r   NFCollection[_DocumentType]Mapping[str, Any]Optional[_Address]intOptional[int]Optional[ClientSession]boolr   None	
collectioncursor_infoaddress
batch_sizemax_await_time_mssessionexplicit_sessioncommentreturnc	           	      C  s   d| _ || _|d | _t|d | _|d| _|| _|| _|| _	|| _
|| _| jdk| _|| _| jrp| d d|kr|d | _n|j| _| | t|ts|dk	rtddS )	zCreate a new command cursor.Nid
firstBatchpostBatchResumeTokenr   Tnsz,max_await_time_ms must be an integer or None)_CommandCursor__sock_mgr_CommandCursor__collection_CommandCursor__idr   _CommandCursor__dataget$_CommandCursor__postbatchresumetoken_CommandCursor__address_CommandCursor__batch_size!_CommandCursor__max_await_time_ms_CommandCursor__session _CommandCursor__explicit_session_CommandCursor__killed_CommandCursor__comment_CommandCursor__end_session_CommandCursor__nsZ	full_namer.   
isinstancer%   	TypeError	selfr+   r,   r-   r.   r/   r0   r1   r2    rK   :/tmp/pip-unpacked-wheel-oblwsawz/pymongo/command_cursor.py__init__2   s,    


zCommandCursor.__init__)r3   c                 C  s   |    d S N_CommandCursor__dierJ   rK   rK   rL   __del__Y   s    zCommandCursor.__del__)synchronousr3   c                 C  sx   | j }d| _ | jr:|s:| j}| jdk	s*tt| j| j}nd}d}| jjj	|||| j
| j| j | jsnd| _d| _
dS )zCloses this cursor.TNr   )rC   r:   r>   AssertionErrorr   rF   r9   databaseclientZ_cleanup_cursorr8   rA   rB   )rJ   rS   Zalready_killed	cursor_idr-   rK   rK   rL   Z__die\   s&    

zCommandCursor.__diec                 C  s$   | j r | js | j j|d d | _ d S )N)lock)rA   rB   Z_end_session)rJ   rS   rK   rK   rL   Z__end_sessiont   s    zCommandCursor.__end_sessionc                 C  s   |  d dS )z$Explicitly close / kill this cursor.TNrO   rQ   rK   rK   rL   closey   s    zCommandCursor.closez'CommandCursor[_DocumentType]')r.   r3   c                 C  s8   t |tstd|dk r"td|dkr.dp0|| _| 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``.

        :Parameters:
          - `batch_size`: The size of each batch of results requested.
        zbatch_size must be an integerr   zbatch_size must be >= 0      )rG   r%   rH   
ValueErrorr?   )rJ   r.   rK   rK   rL   r.   }   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;   rQ   rK   rK   rL   	_has_next   s    zCommandCursor._has_nextOptional[Mapping[str, Any]]c                 C  s   | j S )zlRetrieve the postBatchResumeToken from the response to a
        changeStream aggregate or getMore.
        )r=   rQ   rK   rK   rL   _post_batch_resume_token   s    z&CommandCursor._post_batch_resume_tokenr    )connr3   c                 C  sP   | j jj}|| jsd S | jsL|  t|d}| jdkrF|	  n|| _d S )NFr   )
r9   rU   rV   Z_should_pin_cursorrA   r8   Z
pin_cursorr   r:   rY   )rJ   ra   rV   Zconn_mgrrK   rK   rL   _maybe_pin_connection   s    



z#CommandCursor._maybe_pin_connectionr   )	operationr3   c              
   C  s6  | j jj}z|j|| j| jd}W nz tk
r^ } z|jtkrDd| _	| 
   W 5 d}~X Y n@ tk
r   d| _	| 
   Y n tk
r   | 
   Y nX t|tr| jst|j|j| _|jr|jd d }|d }|d| _|d | _n"|j}t|jts
t|jj| _| jdkr(| 
  t|| _dS )	z/Send a getmore message and handle the response.)r-   TNr   cursorZ	nextBatchr6   r4   )r9   rU   rV   Z_run_operation_unpack_responser>   r   coder   rC   rY   r   	ExceptionrG   r   r8   r   ra   Zmore_to_comeZfrom_commandZdocsr<   r=   r:   datar   rT   rW   r   r;   )rJ   rc   rV   responseexcrd   Z	documentsrK   rK   rL   Z__send_message   sB    
  



zCommandCursor.__send_messageUnion[_OpReply, _OpMsg]zCodecOptions[Mapping[str, Any]]zSequence[_DocumentOut]ri   rW   codec_optionsuser_fieldslegacy_responser3   c                 C  s   | ||||S rN   )Zunpack_response)rJ   ri   rW   rm   rn   ro   rK   rK   rL   re      s    zCommandCursor._unpack_responsec                 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
| d 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   FT)r]   r;   rC   r:   rF   splitr9   Z_read_preference_forr0   _CommandCursor__send_message_getmore_classr?   rm   rA   rU   rV   r@   r8   rD   rP   )rJ   ZdbnameZcollnameZ	read_prefrK   rK   rL   _refresh   s.    

zCommandCursor._refreshc                 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;   rC   rQ   rK   rK   rL   alive  s    zCommandCursor.alivec                 C  s   | j S )zReturns the id of the cursor.)r:   rQ   rK   rK   rL   rW     s    zCommandCursor.cursor_idc                 C  s   | j S )zUThe (host, port) of the server used, or None.

        .. versionadded:: 3.0
        )r>   rQ   rK   rK   rL   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)rB   rA   rQ   rK   rK   rL   r0   #  s    zCommandCursor.sessionzIterator[_DocumentType]c                 C  s   | S rN   rK   rQ   rK   rK   rL   __iter__-  s    zCommandCursor.__iter__r   c                 C  s&   | j r| d}|dk	r |S q tdS )zAdvance the cursor.TN)ru   	_try_nextStopIteration)rJ   docrK   rK   rL   next0  s
    
zCommandCursor.nextzOptional[_DocumentType])get_more_allowedr3   c                 C  s8   t | js| js|r|   t | jr0| j S dS dS )z<Advance the cursor blocking for at most one getMore command.N)r]   r;   rC   rt   popleft)rJ   r{   rK   rK   rL   rw   <  s
    

zCommandCursor._try_nextc                 C  s   | j ddS )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.

        .. versionadded:: 4.5
        T)r{   )rw   rQ   rK   rK   rL   try_nextE  s    zCommandCursor.try_nextc                 C  s   | S rN   rK   rQ   rK   rK   rL   	__enter__X  s    zCommandCursor.__enter__)exc_typeexc_valexc_tbr3   c                 C  s   |    d S rN   )rY   )rJ   r   r   r   rK   rK   rL   __exit__[  s    zCommandCursor.__exit__)r   NNFN)F)NF)__name__
__module____qualname____doc__r   rs   rM   rR   rP   rE   rY   r.   r^   propertyr`   rb   rr   re   rt   ru   rW   r-   r0   rv   rz   __next__rw   r}   r~   r   rK   rK   rK   rL   r!   -   sJ         '.  
"	
	r!   c                      sb   e Zd ZeZddddddd	d
ddd	 fddZdddddd
ddddZdddddZ  ZS )RawBatchCommandCursorr   NFr"   r#   r$   r%   r&   r'   r(   r   r)   r*   c	           	   
     s,   | drt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>`_.
        r5   N)r<   rT   superrM   rI   	__class__rK   rL   rM   b  s    zRawBatchCommandCursor.__init__rk   r   r_   zList[Mapping[str, Any]]rl   c                 C  s"   |j ||d}|st|d  |S )N)rn   r   )raw_responser   )rJ   ri   rW   rm   rn   ro   r   rK   rK   rL   re     s    z&RawBatchCommandCursor._unpack_responser
   )indexr3   c                 C  s   t dd S )Nz)Cannot call __getitem__ on RawBatchCursor)r   )rJ   r   rK   rK   rL   __getitem__  s    z!RawBatchCommandCursor.__getitem__)r   NNFN)NF)	r   r   r   r   rs   rM   re   r   __classcell__rK   rK   r   rL   r   _  s        $$  r   N).r   
__future__r   collectionsr   typingr   r   r   r   r   r	   r
   r   r   r   Zbsonr   r   Zpymongo.cursorr   r   Zpymongo.errorsr   r   r   Zpymongo.messager   r   r   r   r   Zpymongo.responser   Zpymongo.typingsr   r   r   Zpymongo.client_sessionr   Zpymongo.collectionr   Zpymongo.poolr    r!   r   rK   rK   rK   rL   <module>   s"   0  4