diff --git a/gridfs/__init__.py b/gridfs/__init__.py index 39d720873..ff37636a7 100644 --- a/gridfs/__init__.py +++ b/gridfs/__init__.py @@ -27,6 +27,7 @@ from gridfs.grid_file import (GridIn, from pymongo import (ASCENDING, DESCENDING) from pymongo.database import Database +from pymongo.errors import ConfigurationError class GridFS(object): @@ -48,11 +49,19 @@ class GridFS(object): - `connect` (optional): whether to begin connecting the client in the background + .. versionchanged:: 3.0 + `database` must use an acknowledged + :attr:`~pymongo.database.Database.write_concern` + .. mongodoc:: gridfs """ if not isinstance(database, Database): raise TypeError("database must be an instance of Database") + if not database.write_concern.acknowledged: + raise ConfigurationError('database must use ' + 'acknowledged write_concern') + self.__database = database self.__collection = database[collection] self.__files = self.__collection.files @@ -210,7 +219,7 @@ class GridFS(object): def delete(self, file_id): """Delete a file from GridFS by ``"_id"``. - Removes all data belonging to the file with ``"_id"``: + Deletes all data belonging to the file with ``"_id"``: `file_id`. .. warning:: Any processes/threads reading from the file while @@ -225,9 +234,8 @@ class GridFS(object): - `file_id`: ``"_id"`` of the file to delete """ self.__ensure_index_files_id() - self.__files.remove({"_id": file_id}, - **self.__files._get_wc_override()) - self.__chunks.remove({"files_id": file_id}) + self.__files.delete_many({"_id": file_id}) + self.__chunks.delete_one({"files_id": file_id}) def list(self): """List the names of all files stored in this instance of diff --git a/gridfs/grid_file.py b/gridfs/grid_file.py index e615bd5bb..f1b2ddb93 100644 --- a/gridfs/grid_file.py +++ b/gridfs/grid_file.py @@ -27,7 +27,7 @@ from gridfs.errors import (CorruptGridFile, from pymongo import ASCENDING from pymongo.collection import Collection from pymongo.cursor import Cursor -from pymongo.errors import DuplicateKeyError, InvalidOperation +from pymongo.errors import ConfigurationError, DuplicateKeyError from pymongo.read_preferences import ReadPreference try: @@ -62,9 +62,8 @@ def _grid_in_property(field_name, docstring, read_only=False, def setter(self, value): if self._closed: - self._coll.files.update({"_id": self._file["_id"]}, - {"$set": {field_name: value}}, - **self._coll._get_wc_override()) + self._coll.files.update_one({"_id": self._file["_id"]}, + {"$set": {field_name: value}}) self._file[field_name] = value if read_only: @@ -135,12 +134,18 @@ class GridIn(object): - `**kwargs` (optional): file level options (see above) .. versionchanged:: 3.0 - w=0 writes to GridFS are now prohibited. + `root_collection` must use an acknowledged + :attr:`~pymongo.collection.Collection.write_concern` """ if not isinstance(root_collection, Collection): raise TypeError("root_collection must be an " "instance of Collection") + # With w=0, 'filemd5' might run before the final chunks are written. + if not root_collection.write_concern.acknowledged: + raise ConfigurationError('root_collection must use ' + 'acknowledged write_concern') + # Handle alternative naming if "content_type" in kwargs: kwargs["contentType"] = kwargs.pop("content_type") @@ -204,9 +209,8 @@ class GridIn(object): # them now. self._file[name] = value if self._closed: - self._coll.files.update({"_id": self._file["_id"]}, - {"$set": {name: value}}, - **self._coll._get_wc_override()) + self._coll.files.update_one({"_id": self._file["_id"]}, + {"$set": {name: value}}) def __flush_data(self, data): """Flush `data` to a chunk. @@ -224,7 +228,7 @@ class GridIn(object): "data": Binary(data)} try: - self._chunks.insert(chunk) + self._chunks.insert_one(chunk) except DuplicateKeyError: self._raise_file_exists(self._file['_id']) self._chunk_number += 1 @@ -252,8 +256,7 @@ class GridIn(object): self._file["length"] = self._position self._file["uploadDate"] = datetime.datetime.utcnow() - return self._coll.files.insert(self._file, - **self._coll._get_wc_override()) + return self._coll.files.insert_one(self._file) except DuplicateKeyError: self._raise_file_exists(self._id) @@ -296,10 +299,6 @@ class GridIn(object): if self._closed: raise ValueError("cannot write to a closed file") - # With w=0, 'filemd5' might run before the final chunks are written. - if not self._coll.write_concern.acknowledged: - raise InvalidOperation('Cannot write file to GridFS with w=0') - try: # file-like read = data.read diff --git a/test/test_grid_file.py b/test/test_grid_file.py index 1850554f3..40b4d684b 100644 --- a/test/test_grid_file.py +++ b/test/test_grid_file.py @@ -32,7 +32,7 @@ from gridfs.grid_file import (DEFAULT_CHUNK_SIZE, GridOutCursor) from gridfs.errors import NoFile from pymongo import MongoClient -from pymongo.errors import ConnectionFailure, InvalidOperation +from pymongo.errors import ConfigurationError, ConnectionFailure from test import (client_knobs, IntegrationTest, host, @@ -610,10 +610,8 @@ Bye""")) def test_unacknowledged(self): # w=0 is prohibited. - infile = GridIn(rs_or_single_client(w=0).pymongo_test.fs) - - with self.assertRaises(InvalidOperation): - infile.write(b'data') + with self.assertRaises(ConfigurationError): + GridIn(rs_or_single_client(w=0).pymongo_test.fs) if __name__ == "__main__": diff --git a/test/test_gridfs.py b/test/test_gridfs.py index 845c38e4e..c4ed57d8d 100644 --- a/test/test_gridfs.py +++ b/test/test_gridfs.py @@ -26,7 +26,7 @@ import gridfs from bson.py3compat import u, StringIO, string_type from pymongo.mongo_client import MongoClient -from pymongo.errors import ConnectionFailure, InvalidOperation +from pymongo.errors import ConfigurationError, ConnectionFailure from pymongo.read_preferences import ReadPreference from gridfs.errors import (FileExists, NoFile) @@ -433,10 +433,8 @@ class TestGridfs(IntegrationTest): def test_unacknowledged(self): # w=0 is prohibited. - fs = gridfs.GridFS(rs_or_single_client(w=0).pymongo_test) - - with self.assertRaises(InvalidOperation): - fs.put(b'data') + with self.assertRaises(ConfigurationError): + gridfs.GridFS(rs_or_single_client(w=0).pymongo_test) class TestGridfsReplicaSet(TestReplicaSetClientBase):