class AgnosticCollection(AgnosticBase): __motor_class_name__ = 'MotorCollection' __delegate_class__ = mongomock.Collection bulk_write = AsyncCommand() count_documents = AsyncRead() create_index = AsyncCommand() create_indexes = AsyncCommand() delete_many = AsyncCommand() delete_one = AsyncCommand() distinct = AsyncRead() drop = AsyncCommand() drop_index = AsyncCommand() drop_indexes = AsyncCommand() estimated_document_count = AsyncCommand() find_one = AsyncRead() find_one_and_delete = AsyncCommand() find_one_and_replace = AsyncCommand() find_one_and_update = AsyncCommand() full_name = ReadOnlyProperty() insert_many = AsyncWrite() insert_one = AsyncCommand() map_reduce = AsyncCommand().wrap(mongomock.Collection) name = ReadOnlyProperty() reindex = AsyncCommand() rename = AsyncCommand() replace_one = AsyncCommand() update_many = AsyncCommand() update_one = AsyncCommand() with_options = DelegateMethod().wrap(mongomock.Collection) def find(self, *args, **kwargs): return AsyncIOMotorCursor(self.delegate.find(*args, **kwargs))
class AgnosticGridOut(AgnosticBase): __delegate_class__ = gridfs.GridOut __motor_class_name__ = 'MotorGridOut' chunk_size = ReadOnlyProperty() close = ReadOnlyProperty() content_type = ReadOnlyProperty() filename = ReadOnlyProperty() length = ReadOnlyProperty() md5 = ReadOnlyProperty() metadata = ReadOnlyProperty() name = ReadOnlyProperty() read = AsyncRead() readable = DelegateMethod() readchunk = AsyncRead() readline = AsyncRead() seek = DelegateMethod() seekable = DelegateMethod() tell = DelegateMethod() upload_date = ReadOnlyProperty() write = DelegateMethod() def __aiter__(self): return self async def __anext__(self): return next(self.delegate) def __getattr__(self, item): return getattr(self.delegate, item)
class AgnosticGridOutCursor(AgnosticBaseCursor): __motor_class_name__ = 'MotorGridOutCursor' __delegate_class__ = gridfs.GridOutCursor count = AsyncRead() distinct = AsyncRead() explain = AsyncRead() limit = MotorCursorChainingMethod() skip = MotorCursorChainingMethod() max_scan = MotorCursorChainingMethod() sort = MotorCursorChainingMethod() hint = MotorCursorChainingMethod() where = MotorCursorChainingMethod() max_time_ms = MotorCursorChainingMethod() min = MotorCursorChainingMethod() max = MotorCursorChainingMethod() comment = MotorCursorChainingMethod() # PyMongo's GridOutCursor inherits __die from Cursor. _Cursor__die = AsyncCommand() def next_object(self): """Get next GridOut object from cursor.""" grid_out = super(self.__class__, self).next_object() if grid_out: grid_out_class = create_class_with_framework( AgnosticGridOut, self._framework, self.__module__) return grid_out_class(self.collection, delegate=grid_out) else: # Exhausted. return None def rewind(self): """Rewind this cursor to its unevaluated state.""" self.delegate.rewind() self.started = False return self def _empty(self): return self.delegate._Cursor__empty def _query_flags(self): return self.delegate._Cursor__query_flags def _data(self): return self.delegate._Cursor__data def _clear_cursor_id(self): self.delegate._Cursor__id = 0 def _close_exhaust_cursor(self): # Exhaust MotorGridOutCursors are prohibited. pass @motor_coroutine def _close(self): yield self._framework.yieldable(self._Cursor__die())
class AgnosticClient(AgnosticBase): __motor_class_name__ = 'MotorClient' __delegate_class__ = mongomock.MongoClient def __init__(self, *args, **kwargs): self._extract_io_loop(kwargs) super(AgnosticBase, self).__init__(mongomock.MongoClient(*args, **kwargs)) close = DelegateMethod() drop_database = AsyncCommand().unwrap('MotorDatabase') get_database = DelegateMethod().wrap(mongomock.Database) get_default_database = DelegateMethod().wrap(mongomock.Database) list_database_names = AsyncRead() server_info = AsyncRead()
class AgnosticGridOutCursor(AgnosticCursorBase): __delegate_class__ = gridfs.grid_file.GridOutCursor __motor_class_name__ = 'MotorGridOutCursor' distinct = AsyncRead() limit = MotorCursorChainingMethod() skip = MotorCursorChainingMethod() sort = MotorCursorChainingMethod() hint = MotorCursorChainingMethod() max_time_ms = MotorCursorChainingMethod()
class AgnosticCursor(AgnosticCursorBase): __delegate_class__ = mongomock.collection.Cursor __motor_class_name__ = 'MotorCursor' alive = ReadOnlyProperty() distinct = AsyncRead() limit = MotorCursorChainingMethod() skip = MotorCursorChainingMethod() sort = MotorCursorChainingMethod() hint = MotorCursorChainingMethod() max_time_ms = MotorCursorChainingMethod()
class AgnosticDatabase(AgnosticBase): __motor_class_name__ = 'MotorDatabase' __delegate_class__ = mongomock.Database command = AsyncCommand() create_collection = AsyncCommand().wrap(mongomock.Collection) dereference = AsyncRead() drop_collection = AsyncCommand().unwrap('MotorCollection') get_collection = DelegateMethod().wrap(mongomock.Collection) list_collection_names = AsyncRead() with_options = DelegateMethod().wrap(mongomock.Database) def __getattr__(self, name): if name.startswith('_'): raise AttributeError("%s has no attribute %r. To access the %s" " collection, use database['%s']." % (self.__class__.__name__, name, name, name)) return self[name] def __getitem__(self, name): return self.wrap(self.delegate[name])
class AgnosticGridFS(_GFSBase): __motor_class_name__ = 'MotorGridFS' __delegate_class__ = gridfs.GridFS find_one = AsyncRead().wrap(grid_file.GridOut) new_file = AsyncRead().wrap(grid_file.GridIn) get = AsyncRead().wrap(grid_file.GridOut) get_version = AsyncRead().wrap(grid_file.GridOut) get_last_version = AsyncRead().wrap(grid_file.GridOut) list = AsyncRead() exists = AsyncRead() delete = AsyncCommand() put = AsyncCommand() def __init__(self, database, collection="fs"): """**DEPRECATED**: Use :class:`MotorGridFSBucket` or :class:`AsyncIOMotorGridFSBucket`. An instance of GridFS on top of a single Database. :Parameters: - `database`: a :class:`~motor.MotorDatabase` - `collection` (optional): A string, name of root collection to use, such as "fs" or "my_files" .. mongodoc:: gridfs .. versionchanged:: 0.2 ``open`` method removed; no longer needed. """ super(self.__class__, self).__init__(database, collection) def find(self, *args, **kwargs): """Query GridFS for files. 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 = fs.find({"filename": "lisa.txt"}, no_cursor_timeout=True) while (yield cursor.fetch_next): grid_out = cursor.next_object() data = yield grid_out.read() This iterates through all versions of "lisa.txt" stored in GridFS. Note that setting no_cursor_timeout 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. :meth:`~motor.MotorGridFS.find` follows a similar interface to :meth:`~motor.MotorCollection.find` in :class:`~motor.MotorCollection`. :Parameters: - `filter` (optional): a SON object specifying elements which must be present for a document to be included in the result set - `skip` (optional): the number of files to omit (from the start of the result set) when returning the results - `limit` (optional): the maximum number of results to return - `no_cursor_timeout` (optional): if False (the default), any returned cursor is closed by the server after 10 minutes of inactivity. If set to True, the returned cursor will never time out on the server. Care should be taken to ensure that cursors with no_cursor_timeout turned on are properly closed. - `sort` (optional): a list of (key, direction) pairs specifying the sort order for this query. See :meth:`~pymongo.cursor.Cursor.sort` for details. Raises :class:`TypeError` if any of the arguments are of improper type. Returns an instance of :class:`~gridfs.grid_file.GridOutCursor` corresponding to this query. .. versionchanged:: 1.0 Removed the read_preference, tag_sets, and secondary_acceptable_latency_ms options. .. versionadded:: 0.2 .. mongodoc:: find """ cursor = self.delegate.find(*args, **kwargs) grid_out_cursor = create_class_with_framework( AgnosticGridOutCursor, self._framework, self.__module__) return grid_out_cursor(cursor, self.collection)
class AgnosticGridOut(object): """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. """ __motor_class_name__ = 'MotorGridOut' __delegate_class__ = gridfs.GridOut _ensure_file = AsyncCommand() _id = MotorGridOutProperty() aliases = MotorGridOutProperty() chunk_size = MotorGridOutProperty() close = MotorGridOutProperty() content_type = MotorGridOutProperty() filename = MotorGridOutProperty() length = MotorGridOutProperty() md5 = MotorGridOutProperty() metadata = MotorGridOutProperty() name = MotorGridOutProperty() read = AsyncRead() readchunk = AsyncRead() readline = AsyncRead() seek = DelegateMethod() tell = DelegateMethod() upload_date = MotorGridOutProperty() def __init__( self, root_collection, file_id=None, file_document=None, delegate=None, ): collection_class = create_class_with_framework( AgnosticCollection, self._framework, self.__module__) if not isinstance(root_collection, collection_class): raise TypeError( "First argument to MotorGridOut must be " "MotorCollection, not %r" % root_collection) if delegate: self.delegate = delegate else: self.delegate = self.__delegate_class__( root_collection.delegate, file_id, file_document) self.io_loop = root_collection.get_io_loop() # python.org/dev/peps/pep-0492/#api-design-and-implementation-revisions if PY352: exec(textwrap.dedent(""" def __aiter__(self): return self async def __anext__(self): chunk = await self.readchunk() if chunk: return chunk raise StopAsyncIteration() """), globals(), locals()) elif PY35: # In Python 3.5.0 and 3.5.1, __aiter__ is a coroutine. exec(textwrap.dedent(""" async def __aiter__(self): return self async def __anext__(self): chunk = await self.readchunk() if chunk: return chunk raise StopAsyncIteration() """), globals(), locals()) def __getattr__(self, item): if not self.delegate._file: raise pymongo.errors.InvalidOperation( "You must call MotorGridOut.open() before accessing " "the %s property" % item) return getattr(self.delegate, item) @coroutine_annotation def open(self, callback=None): """Retrieve this file's attributes from the server. Takes an optional callback, or returns a Future. :Parameters: - `callback`: Optional function taking parameters (self, error) .. versionchanged:: 0.2 :class:`~motor.MotorGridOut` now opens itself on demand, calling ``open`` explicitly is rarely needed. """ return self._framework.future_or_callback(self._ensure_file(), callback, self.get_io_loop(), self) def get_io_loop(self): return self.io_loop @motor_coroutine def stream_to_handler(self, request_handler): """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 = yield motor.MotorGridFSBucket(db()) try: gridout = yield 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) yield gridout.stream_to_handler(self) self.finish() .. seealso:: Tornado `RequestHandler <http://tornadoweb.org/en/stable/web.html#request-handlers>`_ """ written = 0 while written < self.length: # Reading chunk_size at a time minimizes buffering. f = self._framework.yieldable(self.read(self.chunk_size)) yield f chunk = f.result() # write() simply appends the output to a list; flush() sends it # over the network and minimizes buffering in the handler. request_handler.write(chunk) request_handler.flush() written += len(chunk)
class AgnosticGridFS(object): __motor_class_name__ = 'MotorGridFS' __delegate_class__ = _MotorDelegateGridFS new_file = AsyncRead().wrap(grid_file.GridIn) get = AsyncRead().wrap(grid_file.GridOut) get_version = AsyncRead().wrap(grid_file.GridOut) get_last_version = AsyncRead().wrap(grid_file.GridOut) list = AsyncRead() exists = AsyncRead() delete = AsyncCommand() put = AsyncCommand() def __init__(self, database, collection="fs"): """An instance of GridFS on top of a single Database. :Parameters: - `database`: a :class:`~motor.MotorDatabase` - `collection` (optional): A string, name of root collection to use, such as "fs" or "my_files" .. mongodoc:: gridfs .. versionchanged:: 0.2 ``open`` method removed; no longer needed. """ db_class = create_class_with_framework(AgnosticDatabase, self._framework, self.__module__) if not isinstance(database, db_class): raise TypeError("First argument to MotorGridFS must be " "MotorDatabase, not %r" % database) self.io_loop = database.get_io_loop() self.collection = database[collection] self.delegate = self.__delegate_class__(database.delegate, collection, _connect=False) def get_io_loop(self): return self.io_loop def find(self, *args, **kwargs): """Query GridFS for files. 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 = fs.find({"filename": "lisa.txt"}, timeout=False) while (yield cursor.fetch_next): grid_out = cursor.next_object() data = yield grid_out.read() This iterates through all versions of "lisa.txt" stored in GridFS. Note that setting timeout to False 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. :meth:`~motor.MotorGridFS.find` follows a similar interface to :meth:`~motor.MotorCollection.find` in :class:`~motor.MotorCollection`. :Parameters: - `spec` (optional): a SON object specifying elements which must be present for a document to be included in the result set - `skip` (optional): the number of files to omit (from the start of the result set) when returning the results - `limit` (optional): the maximum number of results to return - `timeout` (optional): if True (the default), any returned cursor is closed by the server after 10 minutes of inactivity. If set to False, the returned cursor will never time out on the server. Care should be taken to ensure that cursors with timeout turned off are properly closed. - `sort` (optional): a list of (key, direction) pairs specifying the sort order for this query. See :meth:`~pymongo.cursor.Cursor.sort` for details. - `max_scan` (optional): limit the number of file documents examined when performing the query - `read_preference` (optional): The read preference for this query. - `tag_sets` (optional): The tag sets for this query. - `secondary_acceptable_latency_ms` (optional): Any replica-set member whose ping time is within secondary_acceptable_latency_ms of the nearest member may accept reads. Default 15 milliseconds. **Ignored by mongos** and must be configured on the command line. See the localThreshold_ option for more information. - `compile_re` (optional): if ``False``, don't attempt to compile BSON regex objects into Python regexes. Return instances of :class:`~bson.regex.Regex` instead. Returns an instance of :class:`~motor.MotorGridOutCursor` corresponding to this query. .. versionadded:: 0.2 .. mongodoc:: find .. _localThreshold: http://docs.mongodb.org/manual/reference/mongos/#cmdoption-mongos--localThreshold """ cursor = self.delegate.find(*args, **kwargs) grid_out_cursor = create_class_with_framework(AgnosticGridOutCursor, self._framework, self.__module__) return grid_out_cursor(cursor, self.collection) def wrap(self, obj): if obj.__class__ is grid_file.GridIn: grid_in_class = create_class_with_framework( AgnosticGridIn, self._framework, self.__module__) return grid_in_class(root_collection=self.collection, delegate=obj) elif obj.__class__ is grid_file.GridOut: grid_out_class = create_class_with_framework( AgnosticGridOut, self._framework, self.__module__) return grid_out_class(root_collection=self.collection, delegate=obj) elif obj.__class__ is gridfs.GridOutCursor: grid_out_class = create_class_with_framework( AgnosticGridOutCursor, self._framework, self.__module__) return grid_out_class(cursor=obj, collection=self.collection)
class AgnosticGridOut(object): """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.MotorGridFS`. If it **is** instantiated directly, call :meth:`open`, :meth:`read`, or :meth:`readline` before accessing its attributes. """ __motor_class_name__ = 'MotorGridOut' __delegate_class__ = gridfs.GridOut tell = DelegateMethod() seek = DelegateMethod() read = AsyncRead() readchunk = AsyncRead() readline = AsyncRead() _ensure_file = AsyncCommand() def __init__( self, root_collection, file_id=None, file_document=None, delegate=None, ): collection_class = create_class_with_framework( AgnosticCollection, self._framework) if not isinstance(root_collection, collection_class): raise TypeError( "First argument to MotorGridOut must be " "MotorCollection, not %r" % root_collection) if delegate: self.delegate = delegate else: self.delegate = self.__delegate_class__( root_collection.delegate, file_id, file_document, _connect=False) self.io_loop = root_collection.get_io_loop() def __getattr__(self, item): if not self.delegate._file: raise pymongo.errors.InvalidOperation( "You must call MotorGridOut.open() before accessing " "the %s property" % item) return getattr(self.delegate, item) @motor_coroutine def open(self): """Retrieve this file's attributes from the server. Takes an optional callback, or returns a Future. :Parameters: - `callback`: Optional function taking parameters (self, error) .. versionchanged:: 0.2 :class:`~motor.MotorGridOut` now opens itself on demand, calling ``open`` explicitly is rarely needed. """ yield self._framework.yieldable(self._ensure_file()) raise self._framework.return_value(self) def get_io_loop(self): return self.io_loop @motor_coroutine def stream_to_handler(self, request_handler): """Write the contents of this file to a :class:`tornado.web.RequestHandler`. This method calls `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`. Takes an optional callback, or returns a Future. :Parameters: - `callback`: Optional function taking parameters (self, error) .. code-block:: python class FileHandler(tornado.web.RequestHandler): @tornado.web.asynchronous @gen.coroutine def get(self, filename): db = self.settings['db'] fs = yield motor.MotorGridFS(db()).open() try: gridout = yield fs.get_last_version(filename) except gridfs.NoFile: raise tornado.web.HTTPError(404) self.set_header("Content-Type", gridout.content_type) self.set_header("Content-Length", gridout.length) yield gridout.stream_to_handler(self) self.finish() .. seealso:: Tornado `RequestHandler <http://tornadoweb.org/en/stable/web.html#request-handlers>`_ """ written = 0 while written < self.length: # Reading chunk_size at a time minimizes buffering. chunk = yield self._framework.yieldable(self.read(self.chunk_size)) # write() simply appends the output to a list; flush() sends it # over the network and minimizes buffering in the handler. request_handler.write(chunk) request_handler.flush() written += len(chunk)
class AgnosticGridFS(object): __motor_class_name__ = 'MotorGridFS' __delegate_class__ = gridfs.GridFS new_file = AsyncRead().wrap(grid_file.GridIn) get = AsyncRead().wrap(grid_file.GridOut) get_version = AsyncRead().wrap(grid_file.GridOut) get_last_version = AsyncRead().wrap(grid_file.GridOut) list = AsyncRead() exists = AsyncRead() delete = AsyncCommand() def __init__(self, database, collection="fs"): """ An instance of GridFS on top of a single Database. :Parameters: - `database`: a :class:`~motor.MotorDatabase` - `collection` (optional): A string, name of root collection to use, such as "fs" or "my_files" .. mongodoc:: gridfs .. versionchanged:: 0.2 ``open`` method removed; no longer needed. """ db_class = create_class_with_framework( AgnosticDatabase, self._framework) if not isinstance(database, db_class): raise TypeError("First argument to MotorGridFS must be " "MotorDatabase, not %r" % database) self.io_loop = database.get_io_loop() self.collection = database[collection] self.delegate = self.__delegate_class__( database.delegate, collection, _connect=False) def get_io_loop(self): return self.io_loop @motor_coroutine def put(self, data, **kwargs): """Put data into GridFS as a new file. Equivalent to doing: .. code-block:: python @gen.coroutine def f(data, **kwargs): try: f = yield my_gridfs.new_file(**kwargs) yield f.write(data) finally: yield f.close() `data` can be either an instance of :class:`str` (:class:`bytes` in python 3) or a file-like object providing a :meth:`read` method. If an `encoding` keyword argument is passed, `data` can also be a :class:`unicode` (:class:`str` in python 3) instance, which will be encoded as `encoding` before being written. Any keyword arguments will be passed through to the created file - see :meth:`~MotorGridIn` for possible arguments. 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. - `callback`: Optional function taking parameters (_id, error) - `**kwargs` (optional): keyword arguments for file creation If no callback is provided, returns a Future that resolves to the ``"_id"`` of the created file. Otherwise, executes the callback with arguments (_id, error). Note that PyMongo allows unacknowledged ("w=0") puts to GridFS, but Motor does not. """ # PyMongo's implementation uses requests, so rewrite for Motor. grid_in_class = create_class_with_framework( AgnosticGridIn, self._framework) grid_file = grid_in_class(self.collection, **kwargs) # w >= 1 necessary to avoid running 'filemd5' command before # all data is written, especially with sharding. if 0 == self.collection.write_concern.get('w'): raise pymongo.errors.ConfigurationError( "Motor does not allow unacknowledged put() to GridFS") try: yield self._framework.yieldable(grid_file.write(data)) finally: yield self._framework.yieldable(grid_file.close()) raise self._framework.return_value(grid_file._id) def find(self, *args, **kwargs): """Query GridFS for files. 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 = fs.find({"filename": "lisa.txt"}, timeout=False) while (yield cursor.fetch_next): grid_out = cursor.next_object() data = yield grid_out.read() This iterates through all versions of "lisa.txt" stored in GridFS. Note that setting timeout to False 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. :meth:`~motor.motor_gridfs.MotorGridFS.find` follows a similar interface to :meth:`~motor.core.MotorCollection.find` in :class:`~motor.core.MotorCollection`. :Parameters: - `spec` (optional): a SON object specifying elements which must be present for a document to be included in the result set - `skip` (optional): the number of files to omit (from the start of the result set) when returning the results - `limit` (optional): the maximum number of results to return - `timeout` (optional): if True (the default), any returned cursor is closed by the server after 10 minutes of inactivity. If set to False, the returned cursor will never time out on the server. Care should be taken to ensure that cursors with timeout turned off are properly closed. - `sort` (optional): a list of (key, direction) pairs specifying the sort order for this query. See :meth:`~pymongo.cursor.Cursor.sort` for details. - `max_scan` (optional): limit the number of file documents examined when performing the query - `read_preference` (optional): The read preference for this query. - `tag_sets` (optional): The tag sets for this query. - `secondary_acceptable_latency_ms` (optional): Any replica-set member whose ping time is within secondary_acceptable_latency_ms of the nearest member may accept reads. Default 15 milliseconds. **Ignored by mongos** and must be configured on the command line. See the localThreshold_ option for more information. - `compile_re` (optional): if ``False``, don't attempt to compile BSON regex objects into Python regexes. Return instances of :class:`~bson.regex.Regex` instead. Returns an instance of :class:`~motor.motor_gridfs.MotorGridOutCursor` corresponding to this query. .. versionadded:: 0.2 .. mongodoc:: find .. _localThreshold: http://docs.mongodb.org/manual/reference/mongos/#cmdoption-mongos--localThreshold """ cursor = self.delegate.find(*args, **kwargs) grid_out_cursor = create_class_with_framework( AgnosticGridOutCursor, self._framework) return grid_out_cursor(cursor, self.collection) def wrap(self, obj): if obj.__class__ is grid_file.GridIn: grid_in_class = create_class_with_framework( AgnosticGridIn, self._framework) return grid_in_class( root_collection=self.collection, delegate=obj) elif obj.__class__ is grid_file.GridOut: grid_out_class = create_class_with_framework( AgnosticGridOut, self._framework) return grid_out_class( root_collection=self.collection, delegate=obj) elif obj.__class__ is gridfs.GridOutCursor: grid_out_class = create_class_with_framework( AgnosticGridOutCursor, self._framework) return grid_out_class( cursor=obj, collection=self.collection)
class MotorEngineCursor(AgnosticCursor): __motor_class_name__ = 'MotorEngineCursor' __delegate_class__ = Cursor _Cursor__die = AsyncRead() def rewind(self): """Rewind this cursor to its unevaluated state.""" self.delegate.rewind() self.started = False return self def clone(self): """Get a clone of this cursor.""" return self.__class__(self.delegate.clone(), self.collection) def next_object(self): if not self._buffer_size(): return None return _query_result_2_object( self.collection.mapping_class if hasattr(self.collection, 'mapping_class') else None, next(self.delegate)) def _to_list(self, length, the_list, to_list_future, get_more_result): try: result = get_more_result.result() collection = self.collection fix_outgoing = collection.database.delegate._fix_outgoing if length is None: n = result else: n = min(length, result) mapping_class = self.collection.mapping_class if hasattr( self.collection, 'mapping_class') else None for _ in range(n): result = _query_result_2_object(mapping_class, self._data().popleft()) the_list.append(fix_outgoing(result, collection)) reached_length = (length is not None and len(the_list) >= length) if reached_length or not self.alive: to_list_future.set_result(the_list) else: self._framework.add_future(self.get_io_loop(), self._get_more(), self._to_list, length, the_list, to_list_future) except Exception as exc: to_list_future.set_exception(exc) def __copy__(self): return self.__class__(self.delegate.__copy__(), self.collection) def __deepcopy__(self, memo): return self.__class__(self.delegate.__deepcopy__(memo), self.collection) def _query_flags(self): return self.delegate._Cursor__query_flags def _data(self): return self.delegate._Cursor__data def _clear_cursor_id(self): self.delegate._Cursor__id = 0 def _close_exhaust_cursor(self): if self.delegate._Cursor__exhaust: manager = self.delegate._Cursor__exhaust_mgr if manager.sock: manager.sock.close() manager.close() def _killed(self): return self.delegate._Cursor__killed @motor_coroutine def _close(self): yield self._framework.yieldable(self._Cursor__die())
class MotorEngineCollection(AgnosticCollection): __motor_class_name__ = 'MotorEngineCollection' __delegate_class__ = Collection _async_aggregate = AsyncRead(attr_name='aggregate') _async_aggregate_raw_batches = AsyncRead(attr_name='aggregate_raw_batches') _async_list_indexes = AsyncRead(attr_name='list_indexes') def __init__(self, database, name, codec_options=None, read_preference=None, write_concern=None, read_concern=None, _delegate=None): db_class = create_class_with_framework(MotorEngineDatabase, self._framework, self.__module__) if not isinstance(database, db_class): raise TypeError( "First argument to MotorEngineCollection must be MotorEngineDatabase, not %r" % database) delegate = _delegate or Collection(database.delegate, name, codec_options=codec_options, read_preference=read_preference, write_concern=write_concern, read_concern=read_concern) super(AgnosticBaseProperties, self).__init__(delegate) self.database = database def __getattr__(self, name): if name.startswith('_'): full_name = "%s.%s" % (self.name, name) raise AttributeError( "%s has no attribute %r. To access the %s collection, use database['%s']." % (self.__class__.__name__, name, full_name, full_name)) return self[name] def __getitem__(self, name): collection_class = create_class_with_framework(MotorEngineCollection, self._framework, self.__module__) return collection_class(self.database, self.name + '.' + name) def __call__(self, *args, **kwargs): raise TypeError( "MotorEngineCollection object is not callable. " "If you meant to call the '%s' method on a MotorCollection object " "it is failing because no such method exists." % self.delegate.name) def find(self, *args, **kwargs): if 'callback' in kwargs: raise InvalidOperation( "Pass a callback to each, to_list, or count, not to find.") cursor = self.delegate.find(*unwrap_args_session(args), **unwrap_kwargs_session(kwargs)) cursor_class = create_class_with_framework(MotorEngineCursor, self._framework, self.__module__) return cursor_class(cursor, self) def aggregate(self, pipeline, **kwargs): cursor_class = create_class_with_framework( MotorEngineLatentCommandCursor, self._framework, self.__module__) return cursor_class(self, self._async_aggregate, pipeline, **unwrap_kwargs_session(kwargs)) def watch(self, pipeline=None, full_document='default', resume_after=None, max_await_time_ms=None, batch_size=None, collation=None, start_at_operation_time=None, session=None): cursor_class = create_class_with_framework(AgnosticChangeStream, self._framework, self.__module__) return cursor_class(self, pipeline, full_document, resume_after, max_await_time_ms, batch_size, collation, start_at_operation_time, session) def list_indexes(self, session=None): cursor_class = create_class_with_framework(AgnosticLatentCommandCursor, self._framework, self.__module__) return cursor_class(self, self._async_list_indexes, session=session) def wrap(self, obj): if obj.__class__ is Collection: return self.__class__(self.database, obj.name, _delegate=obj) elif obj.__class__ is Cursor: return MotorEngineCursor(obj, self) elif obj.__class__ is CommandCursor: command_cursor_class = create_class_with_framework( AgnosticCommandCursor, self._framework, self.__module__) return command_cursor_class(obj, self) elif obj.__class__ is ChangeStream: change_stream_class = create_class_with_framework( AgnosticChangeStream, self._framework, self.__module__) return change_stream_class(obj, self) else: return obj def get_io_loop(self): return self.database.get_io_loop()