diff --git a/gridfs/__init__.py b/gridfs/__init__.py index 25eac1f3d..f6ae8412b 100644 --- a/gridfs/__init__.py +++ b/gridfs/__init__.py @@ -63,6 +63,10 @@ class GridFS(object): which data can be written. Any keyword arguments will be passed through to :meth:`~gridfs.grid_file.GridIn`. + If the ``"_id"`` of the file is manually specified, it must + not already exist in GridFS. Otherwise + :class:`~gridfs.errors.FileExists` is raised. + :Parameters: - `**kwargs` (optional): keyword arguments for file creation @@ -87,6 +91,10 @@ class GridFS(object): :meth:`~gridfs.grid_file.GridIn` for possible arguments. Returns the ``"_id"`` of the created file. + If the ``"_id"`` of the file is manually specified, it must + not already exist in GridFS. Otherwise + :class:`~gridfs.errors.FileExists` is raised. + :Parameters: - `data`: data to be written as a file. - `**kwargs` (optional): keyword arguments for file creation diff --git a/gridfs/errors.py b/gridfs/errors.py index 895ce7b08..c292bb781 100644 --- a/gridfs/errors.py +++ b/gridfs/errors.py @@ -35,6 +35,12 @@ class NoFile(GridFSError): .. versionadded:: 1.6 """ +class FileExists(GridFSError): + """Raised when trying to create a file that already exists. + + .. versionadded:: 1.6+ + """ + class UnsupportedAPI(GridFSError): """Raised when trying to use the old GridFS API. diff --git a/gridfs/grid_file.py b/gridfs/grid_file.py index 042c318ee..c6138c48a 100644 --- a/gridfs/grid_file.py +++ b/gridfs/grid_file.py @@ -23,10 +23,12 @@ except ImportError: from StringIO import StringIO from gridfs.errors import (CorruptGridFile, + FileExists, NoFile, UnsupportedAPI) from pymongo.binary import Binary from pymongo.collection import Collection +from pymongo.errors import DuplicateKeyError from pymongo.objectid import ObjectId try: @@ -93,7 +95,8 @@ class GridIn(object): arguments include: - ``"_id"``: unique ID for this file (default: - :class:`~pymongo.objectid.ObjectId`) + :class:`~pymongo.objectid.ObjectId`) - this ``"_id"`` must + not have already been used for another file - ``"filename"``: human name for the file @@ -192,7 +195,12 @@ class GridIn(object): self._file["md5"] = md5 self._file["length"] = self._position self._file["uploadDate"] = datetime.datetime.utcnow() - return self._coll.files.insert(self._file) + + try: + return self._coll.files.insert(self._file, safe=True) + except DuplicateKeyError: + raise FileExists("file with _id %r already exists" % self._id) + def close(self): """Flush the file and close it. diff --git a/test/test_gridfs.py b/test/test_gridfs.py index 38461d349..b188c67a5 100644 --- a/test/test_gridfs.py +++ b/test/test_gridfs.py @@ -27,7 +27,8 @@ import sys sys.path[0:0] = [""] import gridfs -from gridfs.errors import NoFile +from gridfs.errors import (FileExists, + NoFile) from test_connection import get_connection @@ -182,6 +183,10 @@ class TestGridfs(unittest.TestCase): self.assertEqual(11, self.db.fs.chunks.count()) self.assertEqual("hello world", self.fs.get(oid).read()) + def test_put_duplicate(self): + oid = self.fs.put("hello") + self.assertRaises(FileExists, self.fs.put, "world", _id=oid) + if __name__ == "__main__": unittest.main()