Example #1
0
 def _ensure_file(self):
     if not self._file:
         self._file = self.__files.find_one({"_id": self.__file_id},
                                            session=self._session)
         if not self._file:
             raise NoFile("no file in gridfs collection %r with _id %r" %
                          (self.__files, self.__file_id))
    def __init__(self, root_collection, file_id=None, file_document=None):
        """Read a file from GridFS

        Application developers should generally not need to
        instantiate this class directly - instead see the methods
        provided by :class:`~gridfs.GridFS`.

        Either `file_id` or `file_document` must be specified,
        `file_document` will be given priority if present. Raises
        :class:`TypeError` if `root_collection` is not an instance of
        :class:`~pymongo.collection.Collection`.

        :Parameters:
          - `root_collection`: root collection to read from
          - `file_id`: value of ``"_id"`` for the file to read
          - `file_document`: file document from `root_collection.files`

        .. versionadded:: 1.9
           The `file_document` parameter.
        """
        if not isinstance(root_collection, Collection):
            raise TypeError("root_collection must be an "
                            "instance of Collection")

        self.__chunks = root_collection.chunks

        files = root_collection.files
        self._file = file_document or files.find_one({"_id": file_id})

        if not self._file:
            raise NoFile("no file in gridfs collection %r with _id %r" %
                         (files, file_id))

        self.__buffer = EMPTY
        self.__position = 0
Example #3
0
    def delete(self, file_id: Any, session: Optional[ClientSession] = None) -> None:
        """Given an file_id, delete this stored file's files collection document
        and associated chunks from a GridFS bucket.

        For example::

          my_db = MongoClient().test
          fs = GridFSBucket(my_db)
          # Get _id of file to delete
          file_id = fs.upload_from_stream("test_file", "data I want to store!")
          fs.delete(file_id)

        Raises :exc:`~gridfs.errors.NoFile` if no file with file_id exists.

        :Parameters:
          - `file_id`: The _id of the file to be deleted.
          - `session` (optional): a
            :class:`~pymongo.client_session.ClientSession`

        .. versionchanged:: 3.6
           Added ``session`` parameter.
        """
        _disallow_transactions(session)
        res = self._files.delete_one({"_id": file_id}, session=session)
        self._chunks.delete_many({"files_id": file_id}, session=session)
        if not res.deleted_count:
            raise NoFile("no file could be deleted because none matched %s" % file_id)
Example #4
0
    def rename(
        self, file_id: Any, new_filename: str, session: Optional[ClientSession] = None
    ) -> None:
        """Renames the stored file with the specified file_id.

        For example::

          my_db = MongoClient().test
          fs = GridFSBucket(my_db)
          # Get _id of file to rename
          file_id = fs.upload_from_stream("test_file", "data I want to store!")
          fs.rename(file_id, "new_test_name")

        Raises :exc:`~gridfs.errors.NoFile` if no file with file_id exists.

        :Parameters:
          - `file_id`: The _id of the file to be renamed.
          - `new_filename`: The new name of the file.
          - `session` (optional): a
            :class:`~pymongo.client_session.ClientSession`

        .. versionchanged:: 3.6
           Added ``session`` parameter.
        """
        _disallow_transactions(session)
        result = self._files.update_one(
            {"_id": file_id}, {"$set": {"filename": new_filename}}, session=session
        )
        if not result.matched_count:
            raise NoFile(
                "no files could be renamed %r because none "
                "matched file_id %i" % (new_filename, file_id)
            )
Example #5
0
    def get_last_version(self, filename):
        """Get a file from GridFS by ``"filename"``.

        Returns the most recently uploaded file in GridFS with the
        name `filename` as an instance of
        :class:`~gridfs.grid_file.GridOut`. Raises
        :class:`~gridfs.errors.NoFile` if no such file exists.

        An index on ``{filename: 1, uploadDate: -1}`` will
        automatically be created when this method is called the first
        time.

        :Parameters:
          - `filename`: ``"filename"`` of the file to get

        .. versionadded:: 1.6
        """
        self.__files.ensure_index([("filename", ASCENDING),
                                   ("uploadDate", DESCENDING)])

        cursor = self.__files.find({"filename": filename})
        cursor.limit(-1).sort("uploadDate", DESCENDING)
        try:
            grid_file = cursor.next()
            return GridOut(self.__collection, grid_file["_id"])
        except StopIteration:
            raise NoFile("no file in gridfs with filename %r" % filename)
Example #6
0
    def __init__(self, root_collection, file_id):
        """Read a file from GridFS

        Application developers should generally not need to
        instantiate this class directly - instead see the methods
        provided by :class:`~gridfs.GridFS`.

        Raises :class:`TypeError` if `root_collection` is not an instance of
        :class:`~pymongo.collection.Collection`.

        :Parameters:
          - `root_collection`: root collection to read from
          - `file_id`: value of ``"_id"`` for the file to read
        """
        if not isinstance(root_collection, Collection):
            raise TypeError("root_collection must be an "
                            "instance of Collection")

        self.__chunks = root_collection.chunks
        self._file = root_collection.files.find_one({"_id": file_id})

        if not self._file:
            raise NoFile("no file in gridfs collection %r with _id %r" %
                         (root_collection, file_id))

        self.__buffer = ""
        self.__position = 0
Example #7
0
    def get_version(
        self,
        filename: Optional[str] = None,
        version: Optional[int] = -1,
        session: Optional[ClientSession] = None,
        **kwargs: Any
    ) -> GridOut:
        """Get a file from GridFS by ``"filename"`` or metadata fields.

        Returns a version of the file in GridFS whose filename matches
        `filename` and whose metadata fields match the supplied keyword
        arguments, as an instance of :class:`~gridfs.grid_file.GridOut`.

        Version numbering is a convenience atop the GridFS API provided
        by MongoDB. If more than one file matches the query (either by
        `filename` alone, by metadata fields, or by a combination of
        both), then version ``-1`` will be the most recently uploaded
        matching file, ``-2`` the second most recently
        uploaded, etc. Version ``0`` will be the first version
        uploaded, ``1`` the second version, etc. So if three versions
        have been uploaded, then version ``0`` is the same as version
        ``-3``, version ``1`` is the same as version ``-2``, and
        version ``2`` is the same as version ``-1``.

        Raises :class:`~gridfs.errors.NoFile` if no such version of
        that file exists.

        :Parameters:
          - `filename`: ``"filename"`` of the file to get, or `None`
          - `version` (optional): version of the file to get (defaults
            to -1, the most recent version uploaded)
          - `session` (optional): a
            :class:`~pymongo.client_session.ClientSession`
          - `**kwargs` (optional): find files by custom metadata.

        .. versionchanged:: 3.6
           Added ``session`` parameter.

        .. versionchanged:: 3.1
           ``get_version`` no longer ensures indexes.
        """
        query = kwargs
        if filename is not None:
            query["filename"] = filename

        _disallow_transactions(session)
        cursor = self.__files.find(query, session=session)
        if version is None:
            version = -1
        if version < 0:
            skip = abs(version) - 1
            cursor.limit(-1).skip(skip).sort("uploadDate", DESCENDING)
        else:
            cursor.limit(-1).skip(version).sort("uploadDate", ASCENDING)
        try:
            doc = next(cursor)
            return GridOut(self.__collection, file_document=doc, session=session)
        except StopIteration:
            raise NoFile("no version %d for filename %r" % (version, filename))
Example #8
0
    def open_download_stream_by_name(self,
                                     filename,
                                     revision=-1,
                                     session=None):
        """Opens a Stream from which the application can read the contents of
        `filename` and optional `revision`.

        For example::

          my_db = MongoClient().test
          fs = GridFSBucket(my_db)
          grid_out = fs.open_download_stream_by_name("test_file")
          contents = grid_out.read()

        Returns an instance of :class:`~gridfs.grid_file.GridOut`.

        Raises :exc:`~gridfs.errors.NoFile` if no such version of
        that file exists.

        Raises :exc:`~ValueError` filename is not a string.

        :Parameters:
          - `filename`: The name of the file to read from.
          - `revision` (optional): Which revision (documents with the same
            filename and different uploadDate) of the file to retrieve.
            Defaults to -1 (the most recent revision).
          - `session` (optional): a
            :class:`~pymongo.client_session.ClientSession`

        :Note: Revision numbers are defined as follows:

          - 0 = the original stored file
          - 1 = the first revision
          - 2 = the second revision
          - etc...
          - -2 = the second most recent revision
          - -1 = the most recent revision

        .. versionchanged:: 3.6
           Added ``session`` parameter.
        """
        validate_string("filename", filename)

        query = {"filename": filename}

        cursor = self._files.find(query, session=session)
        if revision < 0:
            skip = abs(revision) - 1
            cursor.limit(-1).skip(skip).sort("uploadDate", DESCENDING)
        else:
            cursor.limit(-1).skip(revision).sort("uploadDate", ASCENDING)
        try:
            grid_file = next(cursor)
            return GridOut(self._collection,
                           file_document=grid_file,
                           session=session)
        except StopIteration:
            raise NoFile("no version %d for filename %r" %
                         (revision, filename))
 def _ensure_file(self) -> None:
     if not self._file:
         _disallow_transactions(self._session)
         self._file = self.__files.find_one({"_id": self.__file_id},
                                            session=self._session)
         if not self._file:
             raise NoFile("no file in gridfs collection %r with _id %r" %
                          (self.__files, self.__file_id))
Example #10
0
    def get_version(self, filename=None, version=-1, **kwargs):
        """Get a file from GridFS by ``"filename"`` or metadata fields.

        Returns a version of the file in GridFS whose filename matches
        `filename` and whose metadata fields match the supplied keyword
        arguments, as an instance of :class:`~gridfs.grid_file.GridOut`.

        Version numbering is a convenience atop the GridFS API provided
        by MongoDB. If more than one file matches the query (either by
        `filename` alone, by metadata fields, or by a combination of
        both), then version ``-1`` will be the most recently uploaded
        matching file, ``-2`` the second most recently
        uploaded, etc. Version ``0`` will be the first version
        uploaded, ``1`` the second version, etc. So if three versions
        have been uploaded, then version ``0`` is the same as version
        ``-3``, version ``1`` is the same as version ``-2``, and
        version ``2`` is the same as version ``-1``.

        Raises :class:`~gridfs.errors.NoFile` if no such version of
        that file exists.

        An index on ``{filename: 1, uploadDate: -1}`` will
        automatically be created when this method is called the first
        time.

        :Parameters:
          - `filename`: ``"filename"`` of the file to get, or `None`
          - `version` (optional): version of the file to get (defualts
            to -1, the most recent version uploaded)
          - `**kwargs` (optional): find files by custom metadata.

        .. versionchanged:: 1.11
           `filename` defaults to None;
        .. versionadded:: 1.11
           Accept keyword arguments to find files by custom metadata.
        .. versionadded:: 1.9
        """
        database = self.__database
        if not database.slave_okay and not database.read_preference:
            self.__files.ensure_index([("filename", ASCENDING),
                                       ("uploadDate", DESCENDING)])

        query = kwargs
        if filename is not None:
            query["filename"] = filename

        cursor = self.__files.find(query)
        if version < 0:
            skip = abs(version) - 1
            cursor.limit(-1).skip(skip).sort("uploadDate", DESCENDING)
        else:
            cursor.limit(-1).skip(version).sort("uploadDate", ASCENDING)
        try:
            grid_file = cursor.next()
            return GridOut(self.__collection, file_document=grid_file)
        except StopIteration:
            raise NoFile("no version %d for filename %r" % (version, filename))
Example #11
0
    async def get_version(self,
                          filename=None,
                          version=-1,
                          **kwargs) -> GridOut:
        """Get a file from GridFS by ``"filename"`` or metadata fields.

        Returns a version of the file in GridFS whose filename matches
        `filename` and whose metadata fields match the supplied keyword
        arguments, as an instance of :class:`~gridfs.grid_file.GridOut`.

        Version numbering is a convenience atop the GridFS API provided
        by MongoDB. If more than one file matches the query (either by
        `filename` alone, by metadata fields, or by a combination of
        both), then version ``-1`` will be the most recently uploaded
        matching file, ``-2`` the second most recently
        uploaded, etc. Version ``0`` will be the first version
        uploaded, ``1`` the second version, etc. So if three versions
        have been uploaded, then version ``0`` is the same as version
        ``-3``, version ``1`` is the same as version ``-2``, and
        version ``2`` is the same as version ``-1``.

        Raises :class:`~gridfs.errors.NoFile` if no such version of
        that file exists.

        :Parameters:
          - `filename`: ``"filename"`` of the file to get, or `None`
          - `version` (optional): version of the file to get (defaults
            to -1, the most recent version uploaded)
          - `**kwargs` (optional): find files by custom metadata.
        """
        query = kwargs
        if filename is not None:
            query['filename'] = filename

        cursor = self.__files.find(query)
        if version < 0:
            skip = abs(version) - 1
            cursor.limit(-1).skip(skip).sort('uploadDate', DESCENDING)
        else:
            cursor.limit(-1).skip(version).sort('uploadDate', ASCENDING)
        async for grid_file in cursor:
            return GridOut(self.__collection, file_document=grid_file)
        raise NoFile('no version %d for filename %r' % (version, filename))
Example #12
0
    def get_version(self, filename, version=-1):
        """Get a file from GridFS by ``"filename"``.

        Returns a version of the file in GridFS with the name
        `filename` as an instance of
        :class:`~gridfs.grid_file.GridOut`. Version ``-1`` will be the
        most recently uploaded, ``-2`` the second most recently
        uploaded, etc. Version ``0`` will be the first version
        uploaded, ``1`` the second version, etc. So if three versions
        have been uploaded, then version ``0`` is the same as version
        ``-3``, version ``1`` is the same as version ``-2``, and
        version ``2`` is the same as version ``-1``.

        Raises :class:`~gridfs.errors.NoFile` if no such version of
        that file exists.

        An index on ``{filename: 1, uploadDate: -1}`` will
        automatically be created when this method is called the first
        time.

        :Parameters:
          - `filename`: ``"filename"`` of the file to get
          - `version` (optional): version of the file to get (defualts
            to -1, the most recent version uploaded)

        .. versionadded:: 1.9
        """
        self.__files.ensure_index([("filename", ASCENDING),
                                   ("uploadDate", DESCENDING)])

        cursor = self.__files.find({"filename": filename})
        if version < 0:
            skip = abs(version) - 1
            cursor.limit(-1).skip(skip).sort("uploadDate", DESCENDING)
        else:
            cursor.limit(-1).skip(version).sort("uploadDate", ASCENDING)
        try:
            grid_file = cursor.next()
            return GridOut(self.__collection, grid_file["_id"])
        except StopIteration:
            raise NoFile("no version %d for filename %r" % (version, filename))
Example #13
0
    def delete(self, file_id):
        """Given an file_id, delete this stored file's files collection document
        and associated chunks from a GridFS bucket.

        For example::

          my_db = MongoClient().test
          fs = GridFSBucket(my_db)
          # Get _id of file to delete
         file_id = fs.upload_from_stream("test_file", "data I want to store!")
          fs.delete(file_id)

        Raises :exc:`~gridfs.errors.NoFile` if no file with file_id exists.

        :Parameters:
          -`file_id`: The _id of the file to be deleted.
        """
        res = self._files.delete_one({"_id": file_id})
        self._chunks.delete_many({"files_id": file_id})
        if not res.deleted_count:
            raise NoFile("no file could be deleted because none matched %s" %
                         file_id)
    def rename(self, file_id, new_filename):
        """Renames the stored file with the specified file_id.

        For example::

          my_db = MongoClient().test
          fs = GridFSBucket(my_db)
          # Get _id of file to rename
          file_id = fs.upload_from_stream("test_file", "data I want to store!")
          fs.rename(file_id, "new_test_name")

        Raises :exc:`~gridfs.errors.NoFile` if no file with file_id exists.

        :Parameters:
          - `file_id`: The _id of the file to be renamed.
          - `new_filename`: The new name of the file.
        """
        result = self._files.update_one({"_id": file_id},
                                        {"$set": {"filename": new_filename}})
        if not result.matched_count:
            raise NoFile("no files could be renamed %r because none "
                         "matched file_id %i" % (new_filename, file_id))
Example #15
0
 async def _ensure_file(self):
     if not self._file:
         self._file = await self.__files.find_one({'_id': self.__file_id})
         if not self._file:
             raise NoFile('no file in gridfs collection %r with _id %r' %
                          (self.__files, self.__file_id))