
    df{I                         d Z ddlZddlZddlZddlZddlZddlmZ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mZ  G d de      Z G d	 d
e      Z G d d      Z G d d      Z G d d      Zd Zy)zDGridFS implementation for Motor, an asynchronous driver for MongoDB.    N)DEFAULT_CHUNK_SIZE	grid_file)
docstrings)AgnosticCollectionAgnosticCursorAgnosticDatabase)AsyncCommand	AsyncReadDelegateMethodReadOnlyPropertycoroutine_annotationcreate_class_with_frameworkc                   H     e Zd ZdZej
                  Z e       Z fdZ	 xZ
S )AgnosticGridOutCursorMotorGridOutCursorc                     t         |          }|r9t        t        | j                  | j
                        } || j                  |      S y)z5**DEPRECATED** - Get next GridOut object from cursor.)delegateN)supernext_objectr   AgnosticGridOut
_framework
__module__
collection)selfgrid_outgrid_out_class	__class__s      K/home/api-vastappli/venv/lib/python3.12/site-packages/motor/motor_gridfs.pyr   z!AgnosticGridOutCursor.next_object+   sF     7&(8$//N "$//HEE     )__name__r   __qualname____motor_class_name__gridfsGridOutCursor__delegate_class__r	   _Cursor__dier   __classcell__)r   s   @r   r   r   $   s(    /--  >L r   r   c                       e Zd ZdZd Zy)MotorGridOutPropertyz<Creates a readonly attribute on the wrapped PyMongo GridOut.c                 h    fd}t        |j                        j                  }t        ||      S )Nc                     | j                   j                  s"t        j                  j	                  dz        t        | j                         S NzBYou must call MotorGridOut.open() before accessing the %s propertyr   _filepymongoerrorsInvalidOperationgetattr)obj	attr_names    r   fgetz3MotorGridOutProperty.create_attribute.<locals>.fget>   sG    <<%%nn55&(12 
 3<<33r   )r5   doc)r2   r%   __doc__property)r   clsr4   r5   r6   s     `  r   create_attributez%MotorGridOutProperty.create_attribute=   s/    	4 c,,i8@@Ts++r   N)r    r   r!   r7   r:    r   r   r)   r)   :   s
    F,r   r)   c                   n   e Zd ZdZdZej                  Z e       Z	 e
       Z e
       Z e
       Z e
       Z e
       Z e
       Z e
       Z e
       Z e
       Z e       Z e       Z e       Z e       Z e       Z e       Z e       Z e
       Z e       Z	 ddZd Z d Z!d Z"e#d        Z$d	 Z%d
 Z&y)r   a  Class to read data out of GridFS.

    MotorGridOut supports the same attributes as PyMongo's
    :class:`~gridfs.grid_file.GridOut`, such as ``_id``, ``content_type``,
    etc.

    You don't need to instantiate this class directly - use the
    methods provided by :class:`~motor.MotorGridFSBucket`. If it **is**
    instantiated directly, call :meth:`open`, :meth:`read`, or
    :meth:`readline` before accessing its attributes.
    MotorGridOutNc                    t        t        | j                  | j                        }t	        ||      st        d|z        |r|| _        n$| j                  |j                  |||      | _        |j                         | _	        y )Nz>First argument to MotorGridOut must be MotorCollection, not %r)session)
r   r   r   r   
isinstance	TypeErrorr   r%   get_io_loopio_loop)r   root_collectionfile_idfile_documentr   r?   collection_classs          r   __init__zAgnosticGridOut.__init__o   s     7
 /+;<*,;< 
 $DM 33(('=' 4 DM '224r   c                     | S Nr;   r   s    r   	__aiter__zAgnosticGridOut.__aiter__   s    r   c                 Z   K   | j                          d {   }|r|S t               7 wrJ   )	readchunkStopAsyncIteration)r   chunks     r   	__anext__zAgnosticGridOut.__anext__   s+     nn&&L "" 's   +)+c                     | j                   j                  s"t        j                  j	                  d|z        t        | j                   |      S r,   r-   )r   items     r   __getattr__zAgnosticGridOut.__getattr__   sB    }}""..11TW[[  t}}d++r   c                 t    | j                   j                  | j                         | j                         |       S )aE  Retrieve this file's attributes from the server.

        Returns a Future.

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

        .. versionchanged:: 0.2
           :class:`~motor.MotorGridOut` now opens itself on demand, calling
           ``open`` explicitly is rarely needed.
        )r   chain_return_value_ensure_filerB   rK   s    r   openzAgnosticGridOut.open   s0     11$2C2C2EtGWGWGY[_``r   c                     | j                   S rJ   rC   rK   s    r   rB   zAgnosticGridOut.get_io_loop       ||r   c                    K   d}|| j                   k  rc| j                  | j                         d{   }|j                  |       |j	                          |t        |      z  }|| j                   k  rbyy7 Ew)a  Write the contents of this file to a
        :class:`tornado.web.RequestHandler`. This method calls
        :meth:`~tornado.web.RequestHandler.flush` on
        the RequestHandler, so ensure all headers have already been set.
        For a more complete example see the implementation of
        :class:`~motor.web.GridFSHandler`.

        .. code-block:: python

            class FileHandler(tornado.web.RequestHandler):
                @tornado.web.asynchronous
                @gen.coroutine
                def get(self, filename):
                    db = self.settings["db"]
                    fs = await motor.MotorGridFSBucket(db())
                    try:
                        gridout = await fs.open_download_stream_by_name(filename)
                    except gridfs.NoFile:
                        raise tornado.web.HTTPError(404)

                    self.set_header("Content-Type", gridout.content_type)
                    self.set_header("Content-Length", gridout.length)
                    await gridout.stream_to_handler(self)
                    self.finish()

        .. seealso:: Tornado `RequestHandler <http://tornadoweb.org/en/stable/web.html#request-handlers>`_
        r   N)lengthread
chunk_sizewriteflushlen)r   request_handlerwrittenrP   s       r   stream_to_handlerz!AgnosticGridOut.stream_to_handler   si     8 #))DOO44E !!%(!!#s5z!G #4s   0A:A8AA:6A:)NNNN)'r    r   r!   r7   r"   r#   GridOutr%   r	   rW   r)   _idaliasesr_   closecontent_typefilenamer]   metadatanamer
   r^   r   readablerN   readlineseekseekabletellupload_dater`   rH   rL   rQ   rT   r   rX   rB   re   r;   r   r   r   r   K   s    
 *>L

 C"$G%'J "E')L#%H!#F#%H!D;DHI{HDHD&(KE Y]5,#, a a%"r   r   c                      e Zd ZdZej
                  Z e       Z e	       Z
 e       Z e	       Z e	       Z e       Z e	       Z e	       Z e	       Z e	       Z e       Z e       Z e       Z e	       Z e       j1                  d      Z e       Z e       j1                  d      Z ed      Z edd      ZddZd	 Zd
 Z d Z!y)AgnosticGridInMotorGridInr=   __exit____setattr__a  
Set an arbitrary metadata attribute on the file. Stores value on the server
as a key-value pair within the file document once the file is closed. If
the file is already closed, calling :meth:`set` will immediately update the file
document on the server.

Metadata set on the file appears as attributes on a
:class:`~motor.MotorGridOut` object created from the file.

:Parameters:
  - `name`: Name of the attribute, will be stored as a key in the file
    document on the server
  - `value`: Value of the attribute
)r4   r6   Nc                     t        t        | j                  | j                        }t	        ||      st        d|z        |j                         | _        |xs  | j                  |j                  fd|i|| _	        y)a  
        Class to write data to GridFS. Application developers should not
        generally need to instantiate this class - see
        :meth:`~motor.MotorGridFSBucket.open_upload_stream`.

        Any of the file level options specified in the `GridFS Spec
        <http://dochub.mongodb.org/core/gridfs/>`_ may be passed as
        keyword arguments. Any additional keyword arguments will be
        set as additional fields on the file document. Valid keyword
        arguments include:

          - ``"_id"``: unique ID for this file (default:
            :class:`~bson.objectid.ObjectId`) - this ``"_id"`` must
            not have already been used for another file

          - ``"filename"``: human name for the file

          - ``"contentType"`` or ``"content_type"``: valid mime-type
            for the file

          - ``"chunkSize"`` or ``"chunk_size"``: size of each of the
            chunks, in bytes (default: 256 kb)

          - ``"encoding"``: encoding used for this file. In Python 2,
            any :class:`unicode` that is written to the file will be
            converted to a :class:`str`. In Python 3, any :class:`str`
            that is written to the file will be converted to
            :class:`bytes`.

        :Parameters:
          - `root_collection`: root collection to write to
          - `session` (optional): a
            :class:`~pymongo.client_session.ClientSession` to use for all
            commands
          - `**kwargs` (optional): file level options (see above)

        .. versionchanged:: 3.0
           Removed support for the `disable_md5` parameter (to match the
           GridIn class in PyMongo).
        .. versionchanged:: 0.2
           ``open`` method removed, no longer needed.
        z=First argument to MotorGridIn must be MotorCollection, not %rr?   N)
r   r   r   r   r@   rA   rB   rC   r%   r   )r   rD   r   r?   kwargsrG   s         r   rH   zAgnosticGridIn.__init__   s    V 7
 /+;<ORaa  '224  
$;D$;$;$$%
.5%
9?%
r   c                    K   | S wrJ   r;   rK   s    r   
__aenter__zAgnosticGridIn.__aenter__3  s     s   c                 F   K   | j                  |||       d {    y 7 wrJ   )_exit)r   exc_typeexc_valexc_tbs       r   	__aexit__zAgnosticGridIn.__aexit__6  s     jj7F333s   !!c                     | j                   S rJ   rZ   rK   s    r   rB   zAgnosticGridIn.get_io_loop9  r[   r   )NN)"r    r   r!   r"   r#   GridInr%   r   rT   r   rg   r	   abortr_   closedri   rj   rk   r]   rm   r^   rn   rq   rs   unwrapr`   	writeable
writelinesr~   setrH   r|   r   rB   r;   r   r   ru   ru      s    ( "K

CNE!#JFNE#%L!HFDDHH"$KN!!.1E I&&~6J$E
C$8
v4r   ru   c                      e Zd ZdZej
                  Z eej                        Z
 eej                        Z eej                        Z eej                        j!                  ej"                        Z eej&                        j!                  ej"                        Z eej,                        j!                  ej.                        Z eej2                        j!                  ej.                        Z eej6                        Z eej:                        Z eej>                        Z de!dddfdZ"d Z#d Zd Z$y)	AgnosticGridFSBucketMotorGridFSBucket)r6   fsNc                    |t        j                  dt        d       |}t        t        | j
                  | j                        }t        ||      st        d| j                   d|      |j                         | _        |j                  |||      | _        | j                  |j                  ||||      | _        y)	a  Create a handle to a GridFS bucket.

        Raises :exc:`~pymongo.errors.ConfigurationError` if `write_concern`
        is not acknowledged.

        This class conforms to the `GridFS API Spec
        <https://github.com/mongodb/specifications/blob/master/source/gridfs/gridfs-spec.rst>`_
        for MongoDB drivers.

        :Parameters:
          - `database`: database to use.
          - `bucket_name` (optional): The name of the bucket. Defaults to 'fs'.
          - `chunk_size_bytes` (optional): The chunk size in bytes. Defaults
            to 255KB.
          - `write_concern` (optional): The
            :class:`~pymongo.write_concern.WriteConcern` to use. If ``None``
            (the default) db.write_concern is used.
          - `read_preference` (optional): The read preference to use. If
            ``None`` (the default) db.read_preference is used.
          - `collection` (optional): Deprecated, an alias for `bucket_name`
            that exists solely to provide backwards compatibility.

        .. versionchanged:: 3.0
           Removed support for the `disable_md5` parameter (to match the
           GridFSBucket class in PyMongo).
        .. versionchanged:: 2.1
           Added support for the `bucket_name`, `chunk_size_bytes`,
           `write_concern`, and `read_preference` parameters.
           Deprecated the `collection` parameter which is now an alias to
           `bucket_name` (to match the GridFSBucket class in PyMongo).
        .. versionadded:: 1.0

        .. mongodoc:: gridfs
        NzCthe "collection" parameter is deprecated, use "bucket_name" instead   )
stacklevelzFirst argument to z must be  MotorDatabase, not )write_concernread_preference)chunk_size_bytesr   r   )warningswarnDeprecationWarningr   r   r   r   r@   rA   r   rB   rC   get_collectionr   r%   r   )r   databasebucket_namer   r   r   r   db_classs           r   rH   zAgnosticGridFSBucket.__init__T  s    X !MMU"
 %K./?RVRaRab(H-$T^^$44QRZQ]^   ++-"11}o 2 
 //-'+ 0 
r   c                     | j                   S rJ   rZ   rK   s    r   rB   z AgnosticGridFSBucket.get_io_loop  r[   r   c                    |j                   t        j                  u r9t        t        | j
                  | j                        } || j                  |      S |j                   t        j                  u r9t        t        | j
                  | j                        } || j                  |      S |j                   t        j                  u r9t        t        | j
                  | j                        } ||| j                        S y )N)rD   r   )cursorr   )r   r   r   r   ru   r   r   r   rf   r   r#   r$   r   )r   r3   grid_in_classr   s       r   wrapzAgnosticGridFSBucket.wrap  s    ==I,,,7M !3OO]]i///8$//N "$//CPP]]f2228%tN "II 3r   c                      | j                   j                  |i |}t        t        | j                  | j
                        } ||| j                        S )aB  Find and return the files collection documents that match ``filter``.

        Returns a cursor that iterates across files matching
        arbitrary queries on the files collection. Can be combined
        with other modifiers for additional control.

        For example::

          cursor = bucket.find({"filename": "lisa.txt"}, no_cursor_timeout=True)
          while (await cursor.fetch_next):
              grid_out = cursor.next_object()
              data = await grid_out.read()

        This iterates through all versions of "lisa.txt" stored in GridFS.
        Note that setting no_cursor_timeout to True may be important to
        prevent the cursor from timing out during long multi-file processing
        work.

        As another example, the call::

          most_recent_three = fs.find().sort("uploadDate", -1).limit(3)

        would return a cursor to the three most recently uploaded files
        in GridFS.

        Follows a similar interface to
        :meth:`~motor.MotorCollection.find`
        in :class:`~motor.MotorCollection`.

        :Parameters:
          - `filter`: Search query.
          - `batch_size` (optional): The number of documents to return per
            batch.
          - `limit` (optional): The maximum number of documents to return.
          - `no_cursor_timeout` (optional): The server normally times out idle
            cursors after an inactivity period (10 minutes) to prevent excess
            memory use. Set this option to True prevent that.
          - `skip` (optional): The number of documents to skip before
            returning.
          - `sort` (optional): The order by which to sort results. Defaults to
            None.
          - `session` (optional): a
            :class:`~pymongo.client_session.ClientSession`, created with
            :meth:`~MotorClient.start_session`.

        If a :class:`~pymongo.client_session.ClientSession` is passed to
        :meth:`find`, all returned :class:`MotorGridOut` instances
        are associated with that session.

        .. versionchanged:: 1.2
           Added session parameter.
        )r   findr   r   r   r   r   )r   argsrz   r   grid_out_cursors        r   r   zAgnosticGridFSBucket.find  sL    j $##T4V45!4??DOO
 vt77r   )%r    r   r!   r"   r#   GridFSBucketr%   r	   r   gridfs_delete_docdeletegridfs_download_to_stream_docdownload_to_stream%gridfs_download_to_stream_by_name_docdownload_to_stream_by_namegridfs_open_download_stream_docr   rf   open_download_stream'gridfs_open_download_stream_by_name_docopen_download_stream_by_namer   gridfs_open_upload_stream_docr   open_upload_stream%gridfs_open_upload_stream_with_id_docopen_upload_stream_with_idgridfs_rename_docrenamegridfs_upload_from_stream_docupload_from_stream%gridfs_upload_from_stream_with_id_docupload_from_stream_with_idr   rH   rB   r   r;   r   r   r   r   =  s6   .,,j::;F%**R*RS!-*2b2b!c'J,V,VW\\ $0>>$
d6>> ! (J,T,TUZZ "0<<"
d6==  j::;F%**R*RS!-*2b2b!c
 +E
NJ,:8r   r   c                 \   t        j                  t        | j                        j	                  d            }|j                  t        | j                        j	                  d             |j                  t        | j                        j	                  d             |j                         S )zCompute the effective hash of a GridOut object for use with an Etag header.

    Create a FIPS-compliant Etag HTTP header hash using sha256
    We use the _id + length + upload_date as a proxy for
    uniqueness to avoid reading the entire file.
    utf8)	hashlibsha256strrg   encodeupdater]   rs   	hexdigest)gridout	grid_hashs     r   _hash_gridoutr     s{     s7;;/66v>?IS(//78S,,-44V<=  r   )r7   r   r   r#   r/   pymongo.errorsr   r   motorr   
motor.corer   r   r   motor.metaprogrammingr	   r
   r   r   r   r   r   r)   r   ru   r   r   r;   r   r   <module>r      su    K      0  K K N ,,+ ,"B" B"Jj jZq8 q8h
!r   