MOTOR-1194 Replace flake8 and isort with ruff (#231)

* adopt ruff

* fixups

* cleanup

* update traceback
This commit is contained in:
Steven Silvester 2023-10-20 13:45:21 -05:00 committed by GitHub
parent 0ed06b65ac
commit 684279ed0a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
47 changed files with 242 additions and 255 deletions

31
.flake8
View File

@ -1,31 +0,0 @@
[flake8]
max-line-length = 100
enable-extensions = G
extend-ignore =
G200, G202, G001
# black adds spaces around ':'
E203,
# E501 line too long (let black handle line length)
E501
# B305 `.next()` is not a thing on Python 3. Use the `next()` builtin. For Python 2 compatibility, use `six.next()`.
B305
per-file-ignores =
# F841 local variable 'foo' is assigned to but never used
# E731 do not assign a lambda expression, use a def
# F811 redefinition of unused 'foo' from line XXX
test/*/test_examples.py: F841,E731,F811
# F811 redefinition of unused 'foo' from line XXX
# B011 Do not call assert False since python -O removes these calls. Instead callers should raise AssertionError().
test/*: F811,B011
# E402 module level import not at top of file
doc/examples/monitoring_example.py: E402
# F403 'from foo import *' used; unable to detect undefined names
# F401 'foo' imported but unused
synchro/__init__.py: F403,F401
# F401 'foo' imported but unused
motor/__init__.py: F401

View File

@ -23,22 +23,12 @@ repos:
files: \.(py|pyi)$
args: [--line-length=100]
- repo: https://github.com/PyCQA/isort
rev: 5.12.0
- repo: https://github.com/astral-sh/ruff-pre-commit
# Ruff version.
rev: v0.1.1
hooks:
- id: isort
files: \.(py|pyi)$
args: [--profile=black]
- repo: https://github.com/pycqa/flake8
rev: 3.9.2
hooks:
- id: flake8
additional_dependencies: [
'flake8-bugbear==20.1.4',
'flake8-logging-format==0.6.0',
'flake8-implicit-str-concat==0.2.0',
]
- id: ruff
args: ["--fix", "--show-fixes"]
# We use the Python version instead of the original version which seems to require Docker
# https://github.com/koalaman/shellcheck-precommit

View File

@ -1,9 +1,7 @@
# -*- coding: utf-8 -*-
#
# Motor documentation build configuration file
#
# This file is execfile()d with the current directory set to its containing dir.
import os
import sys

View File

@ -1,10 +1,9 @@
"""Gratefully adapted from aiohttp, provides coroutine support to autodoc."""
from sphinx import addnodes
from sphinx.domains.python import PyFunction, PyMethod
class PyCoroutineMixin(object):
class PyCoroutineMixin:
def handle_signature(self, sig, signode):
ret = super().handle_signature(sig, signode)
signode.insert(0, addnodes.desc_annotation("coroutine ", "coroutine "))

View File

@ -31,7 +31,7 @@ async def page_handler(request):
document = await db.pages.find_one(page_name)
if not document:
return web.HTTPNotFound(text="No page named {!r}".format(page_name))
return web.HTTPNotFound(text=f"No page named {page_name!r}")
return web.Response(body=document["body"].encode(), content_type="text/html")

View File

@ -74,7 +74,7 @@ async def main():
await create_json_schema_file(kms_providers, key_vault_namespace, key_vault_client)
# Load the JSON Schema and construct the local schema_map option.
with open("jsonSchema.json", "r") as file:
with open("jsonSchema.json") as file:
json_schema_string = file.read()
json_schema = json_util.loads(json_schema_string)
schema_map = {encrypted_namespace: json_schema}
@ -91,10 +91,10 @@ async def main():
await coll.insert_one({"encryptedField": "123456789"})
decrypted_doc = await coll.find_one()
print("Decrypted document: %s" % (decrypted_doc,))
print(f"Decrypted document: {decrypted_doc}")
unencrypted_coll = AsyncIOMotorClient()[db_name][coll_name]
encrypted_doc = await unencrypted_coll.find_one()
print("Encrypted document: %s" % (encrypted_doc,))
print(f"Encrypted document: {encrypted_doc}")
if __name__ == "__main__":

View File

@ -64,9 +64,9 @@ async def main():
await coll.insert_one({"encryptedField": encrypted_field})
# Automatically decrypts any encrypted fields.
doc = await coll.find_one()
print("Decrypted document: %s" % (doc,))
print(f"Decrypted document: {doc}")
unencrypted_coll = AsyncIOMotorClient().test.coll
print("Encrypted document: %s" % (await unencrypted_coll.find_one(),))
print(f"Encrypted document: {await unencrypted_coll.find_one()}")
# Cleanup resources.
await client_encryption.close()

View File

@ -54,11 +54,11 @@ async def main():
)
await coll.insert_one({"encryptedField": encrypted_field})
doc = await coll.find_one()
print("Encrypted document: %s" % (doc,))
print(f"Encrypted document: {doc}")
# Explicitly decrypt the field:
doc["encryptedField"] = await client_encryption.decrypt(doc["encryptedField"])
print("Decrypted document: %s" % (doc,))
print(f"Decrypted document: {doc}")
# Cleanup resources.
await client_encryption.close()

View File

@ -27,25 +27,25 @@ logging.basicConfig(stream=sys.stdout, level=logging.INFO)
class CommandLogger(monitoring.CommandListener):
def started(self, event):
logging.info(
"Command {0.command_name} with request id "
"{0.request_id} started on server "
"{0.connection_id}".format(event)
f"Command {event.command_name} with request id "
f"{event.request_id} started on server "
f"{event.connection_id}"
)
def succeeded(self, event):
logging.info(
"Command {0.command_name} with request id "
"{0.request_id} on server {0.connection_id} "
"succeeded in {0.duration_micros} "
"microseconds".format(event)
f"Command {event.command_name} with request id "
f"{event.request_id} on server {event.connection_id} "
f"succeeded in {event.duration_micros} "
"microseconds"
)
def failed(self, event):
logging.info(
"Command {0.command_name} with request id "
"{0.request_id} on server {0.connection_id} "
"failed in {0.duration_micros} "
"microseconds".format(event)
f"Command {event.command_name} with request id "
f"{event.request_id} on server {event.connection_id} "
f"failed in {event.duration_micros} "
"microseconds"
)
@ -77,22 +77,20 @@ ioloop.IOLoop.current().run_sync(do_insert)
# server logger start
class ServerLogger(monitoring.ServerListener):
def opened(self, event):
logging.info("Server {0.server_address} added to topology {0.topology_id}".format(event))
logging.info(f"Server {event.server_address} added to topology {event.topology_id}")
def description_changed(self, event):
previous_server_type = event.previous_description.server_type
new_server_type = event.new_description.server_type
if new_server_type != previous_server_type:
logging.info(
"Server {0.server_address} changed type from "
"{0.previous_description.server_type_name} to "
"{0.new_description.server_type_name}".format(event)
f"Server {event.server_address} changed type from "
f"{event.previous_description.server_type_name} to "
f"{event.new_description.server_type_name}"
)
def closed(self, event):
logging.warning(
"Server {0.server_address} removed from topology {0.topology_id}".format(event)
)
logging.warning(f"Server {event.server_address} removed from topology {event.topology_id}")
monitoring.register(ServerLogger())
@ -102,21 +100,21 @@ monitoring.register(ServerLogger())
# topology logger start
class TopologyLogger(monitoring.TopologyListener):
def opened(self, event):
logging.info("Topology with id {0.topology_id} opened".format(event))
logging.info(f"Topology with id {event.topology_id} opened")
def description_changed(self, event):
logging.info("Topology description updated for topology id {0.topology_id}".format(event))
logging.info(f"Topology description updated for topology id {event.topology_id}")
previous_topology_type = event.previous_description.topology_type
new_topology_type = event.new_description.topology_type
if new_topology_type != previous_topology_type:
logging.info(
"Topology {0.topology_id} changed type from "
"{0.previous_description.topology_type_name} to "
"{0.new_description.topology_type_name}".format(event)
f"Topology {event.topology_id} changed type from "
f"{event.previous_description.topology_type_name} to "
f"{event.new_description.topology_type_name}"
)
def closed(self, event):
logging.info("Topology with id {0.topology_id} closed".format(event))
logging.info(f"Topology with id {event.topology_id} closed")
monitoring.register(TopologyLogger())
@ -126,18 +124,18 @@ monitoring.register(TopologyLogger())
# heartbeat logger start
class HeartbeatLogger(monitoring.ServerHeartbeatListener):
def started(self, event):
logging.info("Heartbeat sent to server {0.connection_id}".format(event))
logging.info(f"Heartbeat sent to server {event.connection_id}")
def succeeded(self, event):
logging.info(
"Heartbeat to server {0.connection_id} "
f"Heartbeat to server {event.connection_id} "
"succeeded with reply "
"{0.reply.document}".format(event)
f"{event.reply.document}"
)
def failed(self, event):
logging.warning(
"Heartbeat to server {0.connection_id} failed with error {0.reply}".format(event)
f"Heartbeat to server {event.connection_id} failed with error {event.reply}"
)

View File

@ -86,14 +86,14 @@ async def main():
await coll.insert_one({"encryptedField": "123456789"})
decrypted_doc = await coll.find_one()
print("Decrypted document: %s" % (decrypted_doc,))
print(f"Decrypted document: {decrypted_doc}")
unencrypted_coll = AsyncIOMotorClient()[db_name][coll_name]
encrypted_doc = await unencrypted_coll.find_one()
print("Encrypted document: %s" % (encrypted_doc,))
print(f"Encrypted document: {encrypted_doc}")
try:
await unencrypted_coll.insert_one({"encryptedField": "123456789"})
except OperationFailure as exc:
print("Unencrypted insert failed: %s" % (exc.details,))
print(f"Unencrypted insert failed: {exc.details}")
if __name__ == "__main__":

View File

@ -73,11 +73,8 @@ class ChangesHandler(tornado.websocket.WebSocketHandler):
data = data.encode("utf-8")
html_id = urlsafe_b64encode(data).decode().rstrip("=")
change.pop("_id")
change["html"] = '<div id="change-%s"><pre>%s</pre></div>' % (
html_id,
tornado.escape.xhtml_escape(pformat(change)),
)
change_pre = tornado.escape.xhtml_escape(pformat(change))
change["html"] = f'<div id="change-{html_id}"><pre>{change_pre}</pre></div>'
change["html_id"] = html_id
ChangesHandler.send_change(change)
ChangesHandler.update_cache(change)
@ -97,7 +94,7 @@ async def watch(collection):
def main():
tornado.options.parse_command_line()
if "." not in options.ns:
sys.stderr.write('Invalid ns "%s", must contain a "."' % (options.ns,))
sys.stderr.write(f'Invalid ns "{options.ns}", must contain a "."')
sys.exit(1)
db_name, collection_name = options.ns.split(".", 1)

View File

@ -32,7 +32,7 @@ def has_node_of_type(root, klass):
if isinstance(root, klass):
return True
for child in root.children:
for child in root.children: # noqa: SIM110
if has_node_of_type(child, klass):
return True
@ -90,7 +90,7 @@ def process_motor_nodes(app, doctree):
if desc_content_node.line is None and obj_motor_info["is_pymongo_docstring"]:
maybe_warn_about_code_block(name, desc_content_node)
if obj_motor_info["is_async_method"]:
if obj_motor_info["is_async_method"]: # noqa: SIM102
# Might be a handwritten RST with "coroutine" already.
if not has_coro_annotation(signature_node):
coro_annotation = addnodes.desc_annotation(
@ -125,9 +125,9 @@ def get_motor_attr(motor_class, name, *defargs):
attr = safe_getattr(motor_class, name, *defargs)
# Store some info for process_motor_nodes()
full_name = "%s.%s.%s" % (motor_class.__module__, motor_class.__name__, name)
full_name = f"{motor_class.__module__}.{motor_class.__name__}.{name}"
full_name_legacy = "motor.%s.%s.%s" % (motor_class.__module__, motor_class.__name__, name)
full_name_legacy = f"motor.{motor_class.__module__}.{motor_class.__name__}.{name}"
# These sub-attributes are set in motor.asynchronize()
has_coroutine_annotation = getattr(attr, "coroutine_annotation", False)

View File

@ -13,18 +13,17 @@
# limitations under the License.
"""Motor, an asynchronous driver for MongoDB."""
from ._version import get_version_string, version, version_tuple # noqa
from ._version import get_version_string, version, version_tuple # noqa: F401
"""Current version of Motor."""
try:
import tornado # type: ignore
import tornado # type:ignore[import]
except ImportError:
tornado = None
else:
# For backwards compatibility with Motor 0.4, export Motor's Tornado classes
# at module root. This may change in the future.
from .motor_tornado import * # noqa: F403
from .motor_tornado import __all__
from .motor_tornado import __all__ # noqa: F401

View File

@ -13,7 +13,6 @@
# limitations under the License.
"""Version-related data for motor."""
version_tuple = (3, 4, 0, ".dev0")

View File

@ -106,7 +106,6 @@ def set_extra_headers(response, gridout):
- `gridout`: The :class:`~motor.motor_asyncio.AsyncIOMotorGridOut` we
will serve to the client
"""
pass
def _config_error(request):
@ -188,8 +187,8 @@ class AIOHTTPGridFS:
try:
gridout = await self._get_gridfs_file(self._bucket, filename, request)
except gridfs.NoFile:
raise aiohttp.web.HTTPNotFound(text=request.path)
except gridfs.NoFile as e:
raise aiohttp.web.HTTPNotFound(text=request.path) from e
resp = aiohttp.web.StreamResponse()

View File

@ -13,7 +13,6 @@
# limitations under the License.
"""Framework-agnostic core of Motor, an asynchronous driver for MongoDB."""
import functools
import time
import warnings
@ -73,7 +72,7 @@ def _max_time_expired_error(exc):
return isinstance(exc, pymongo.errors.OperationFailure) and exc.code == 50
class AgnosticBase(object):
class AgnosticBase:
def __eq__(self, other):
if (
isinstance(other, self.__class__)
@ -87,7 +86,7 @@ class AgnosticBase(object):
self.delegate = delegate
def __repr__(self):
return "%s(%r)" % (self.__class__.__name__, self.delegate)
return f"{self.__class__.__name__}({self.delegate!r})"
class AgnosticBaseProperties(AgnosticBase):
@ -213,9 +212,10 @@ class AgnosticClient(AgnosticBaseProperties):
This option and `resume_after` are mutually exclusive.
- `comment` (optional): A user-provided comment to attach to this
command.
- `full_document_before_change`: Allowed values: `whenAvailable` and `required`. Change events
may now result in a `fullDocumentBeforeChange` response field.
- `show_expanded_events` (optional): Include expanded events such as DDL events like `dropIndexes`.
- `full_document_before_change`: Allowed values: `whenAvailable` and `required`. Change
events may now result in a `fullDocumentBeforeChange` response field.
- `show_expanded_events` (optional): Include expanded events such as DDL events like
`dropIndexes`.
:Returns:
A :class:`~MotorChangeStream`.
@ -260,8 +260,8 @@ class AgnosticClient(AgnosticBaseProperties):
def __getattr__(self, name):
if name.startswith("_"):
raise AttributeError(
"%s has no attribute %r. To access the %s"
" database, use client['%s']." % (self.__class__.__name__, name, name, name)
f"{self.__class__.__name__} has no attribute {name!r}. To access the {name}"
f" database, use client['{name}']."
)
return self[name]
@ -292,7 +292,7 @@ class AgnosticClient(AgnosticBaseProperties):
return session_class(obj, self)
class _MotorTransactionContext(object):
class _MotorTransactionContext:
"""Internal transaction context manager for start_transaction."""
def __init__(self, session):
@ -678,9 +678,10 @@ class AgnosticDatabase(AgnosticBaseProperties):
This option and `resume_after` are mutually exclusive.
- `comment` (optional): A user-provided comment to attach to this
command.
- `full_document_before_change`: Allowed values: `whenAvailable` and `required`. Change events
may now result in a `fullDocumentBeforeChange` response field.
- `show_expanded_events` (optional): Include expanded events such as DDL events like `dropIndexes`.
- `full_document_before_change`: Allowed values: `whenAvailable` and `required`. Change
events may now result in a `fullDocumentBeforeChange` response field.
- `show_expanded_events` (optional): Include expanded events such as DDL events like
`dropIndexes`.
:Returns:
A :class:`~MotorChangeStream`.
@ -763,7 +764,8 @@ class AgnosticDatabase(AgnosticBaseProperties):
:class:`MotorClientSession`.
- `comment` (optional): A user-provided comment to attach to future getMores for this
command.
- `max_await_time_ms` (optional): The number of ms to wait for more data on future getMores for this command.
- `max_await_time_ms` (optional): The number of ms to wait for more data on future
getMores for this command.
- `**kwargs` (optional): additional keyword arguments will
be added to the command document before it is sent
@ -812,8 +814,8 @@ class AgnosticDatabase(AgnosticBaseProperties):
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)
f"{self.__class__.__name__} has no attribute {name!r}. To access the {name}"
" collection, use database['{name}']."
)
return self[name]
@ -830,14 +832,14 @@ class AgnosticDatabase(AgnosticBaseProperties):
client_class_name = self._client.__class__.__name__
if database_name == "open_sync":
raise TypeError(
"%s.open_sync() is unnecessary Motor 0.2, "
"see changelog for details." % client_class_name
f"{client_class_name}.open_sync() is unnecessary Motor 0.2, "
"see changelog for details."
)
raise TypeError(
"MotorDatabase object is not callable. If you meant to "
"call the '%s' method on a %s object it is "
"failing because no such method exists." % (database_name, client_class_name)
f"call the '{database_name}' method on a {client_class_name} object it is "
"failing because no such method exists."
)
def wrap(self, obj):
@ -940,11 +942,10 @@ class AgnosticCollection(AgnosticBaseProperties):
def __getattr__(self, name):
# Dotted collection name, like "foo.bar".
if name.startswith("_"):
full_name = "%s.%s" % (self.name, name)
full_name = f"{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)
f"{self.__class__.__name__} has no attribute {name!r}. To access the {full_name}"
f" collection, use database['{full_name}']."
)
return self[name]
@ -1250,9 +1251,10 @@ class AgnosticCollection(AgnosticBaseProperties):
This option and `resume_after` are mutually exclusive.
- `comment` (optional): A user-provided comment to attach to this
command.
- `full_document_before_change`: Allowed values: `whenAvailable` and `required`. Change events
may now result in a `fullDocumentBeforeChange` response field.
- `show_expanded_events` (optional): Include expanded events such as DDL events like `dropIndexes`.
- `full_document_before_change`: Allowed values: `whenAvailable` and `required`.
Change events may now result in a `fullDocumentBeforeChange` response field.
- `show_expanded_events` (optional): Include expanded events such as DDL events
like `dropIndexes`.
:Returns:
A :class:`~MotorChangeStream`.
@ -1809,7 +1811,7 @@ class AgnosticRawBatchCommandCursor(AgnosticCommandCursor):
__delegate_class__ = RawBatchCommandCursor
class _LatentCursor(object):
class _LatentCursor:
"""Take the place of a PyMongo CommandCursor until aggregate() begins."""
alive = True
@ -2151,7 +2153,7 @@ class AgnosticClientEncryption(AgnosticBase):
await self.close()
def __enter__(self):
raise RuntimeError('Use {} in "async with", not "with"'.format(self.__class__.__name__))
raise RuntimeError(f'Use {self.__class__.__name__} in "async with", not "with"')
def __exit__(self, exc_type, exc_val, exc_tb):
pass
@ -2173,8 +2175,8 @@ class AgnosticClientEncryption(AgnosticBase):
.. warning::
This function does not update the encryptedFieldsMap in the client's
AutoEncryptionOpts, thus the user must create a new client after calling this function with
the encryptedFields returned.
AutoEncryptionOpts, thus the user must create a new client after calling
this function with the encryptedFields returned.
Normally collection creation is automatic. This method should
only be used to specify options on
@ -2214,10 +2216,12 @@ class AgnosticClientEncryption(AgnosticBase):
All optional `create collection command`_ parameters should be passed
as keyword arguments to this method.
See the documentation for :meth:`~pymongo.database.Database.create_collection` for all valid options.
See the documentation for :meth:`~pymongo.database.Database.create_collection`
for all valid options.
:Raises:
- :class:`~pymongo.errors.EncryptedCollectionError`: When either data-key creation or creating the collection fails.
- :class:`~pymongo.errors.EncryptedCollectionError`: When either data-key creation or
creating the collection fails.
.. versionadded:: 3.2

View File

@ -19,25 +19,17 @@ from __future__ import annotations
from asyncio import Future
from typing import (
Any,
Awaitable,
Callable,
Collection,
Coroutine,
Dict,
FrozenSet,
Iterable,
List,
Mapping,
MutableMapping,
NoReturn,
Optional,
Sequence,
Set,
Tuple,
Type,
TypeVar,
Union,
overload,
)
import pymongo.common
@ -86,7 +78,7 @@ _CodecDocumentType = TypeVar("_CodecDocumentType", bound=Mapping[str, Any])
def _within_time_limit(start_time: float) -> bool: ...
def _max_time_expired_error(exc: Exception) -> bool: ...
class AgnosticBase(object):
class AgnosticBase:
delegate: Any
def __eq__(self, other: Any) -> bool: ...
@ -101,10 +93,10 @@ class AgnosticBaseProperties(AgnosticBase):
class AgnosticClient(AgnosticBaseProperties):
__motor_class_name__: str
__delegate_class__: Type[pymongo.MongoClient]
__delegate_class__: type[pymongo.MongoClient]
def address(self) -> Optional[Tuple[str, int]]: ...
def arbiters(self) -> Set[Tuple[str, int]]: ...
def address(self) -> Optional[tuple[str, int]]: ...
def arbiters(self) -> set[tuple[str, int]]: ...
def close(self) -> None: ...
def __hash__(self) -> int: ...
async def drop_database(
@ -145,15 +137,15 @@ class AgnosticClient(AgnosticBaseProperties):
self,
session: Optional[AgnosticClientSession] = None,
comment: Optional[Any] = None,
) -> List[str]: ...
def nodes(self) -> FrozenSet[_Address]: ...
) -> list[str]: ...
def nodes(self) -> frozenset[_Address]: ...
PORT: int
def primary(self) -> Optional[Tuple[str, int]]: ...
def primary(self) -> Optional[tuple[str, int]]: ...
read_concern: ReadConcern
def secondaries(self) -> Set[Tuple[str, int]]: ...
def secondaries(self) -> set[tuple[str, int]]: ...
async def server_info(
self, session: Optional[AgnosticClientSession] = None
) -> Dict[str, Any]: ...
) -> dict[str, Any]: ...
def topology_description(self) -> TopologyDescription: ...
async def start_session(
self,
@ -197,7 +189,7 @@ class _MotorTransactionContext:
class AgnosticClientSession(AgnosticBase):
__motor_class_name__: str
__delegate_class__: Type[ClientSession]
__delegate_class__: type[ClientSession]
async def commit_transaction(self) -> None: ...
async def abort_transaction(self) -> None: ...
@ -236,7 +228,7 @@ class AgnosticClientSession(AgnosticBase):
class AgnosticDatabase(AgnosticBaseProperties):
__motor_class_name__: str
__delegate_class__: Type[Database]
__delegate_class__: type[Database]
def __hash__(self) -> int: ...
def __bool__(self) -> int: ...
@ -262,7 +254,7 @@ class AgnosticDatabase(AgnosticBaseProperties):
session: Optional[AgnosticClientSession] = None,
comment: Optional[Any] = None,
**kwargs: Any,
) -> Union[Dict[str, Any], _CodecDocumentType]: ...
) -> Union[dict[str, Any], _CodecDocumentType]: ...
async def create_collection(
self,
name: str,
@ -287,7 +279,7 @@ class AgnosticDatabase(AgnosticBaseProperties):
session: Optional[AgnosticClientSession] = None,
comment: Optional[Any] = None,
encrypted_fields: Optional[Mapping[str, Any]] = None,
) -> Dict[str, Any]: ...
) -> dict[str, Any]: ...
async def get_collection(
self,
name: str,
@ -302,7 +294,7 @@ class AgnosticDatabase(AgnosticBaseProperties):
filter: Optional[Mapping[str, Any]] = None,
comment: Optional[Any] = None,
**kwargs: Any,
) -> List[str]: ...
) -> list[str]: ...
async def list_collections(
self,
session: Optional[AgnosticClientSession] = None,
@ -319,7 +311,7 @@ class AgnosticDatabase(AgnosticBaseProperties):
session: Optional[AgnosticClientSession] = None,
background: Optional[bool] = None,
comment: Optional[Any] = None,
) -> Dict[str, Any]: ...
) -> dict[str, Any]: ...
def with_options(
self,
codec_options: Optional[CodecOptions[_DocumentTypeArg]] = None,
@ -359,7 +351,7 @@ class AgnosticDatabase(AgnosticBaseProperties):
class AgnosticCollection(AgnosticBaseProperties):
__motor_class_name__: str
__delegate_class__: Type[Collection]
__delegate_class__: type[Collection]
def __hash__(self) -> int: ...
def __bool__(self) -> bool: ...
@ -392,7 +384,7 @@ class AgnosticCollection(AgnosticBaseProperties):
session: Optional[AgnosticClientSession] = None,
comment: Optional[Any] = None,
**kwargs: Any,
) -> List[str]: ...
) -> list[str]: ...
async def delete_many(
self,
filter: Mapping[str, Any],
@ -418,7 +410,7 @@ class AgnosticCollection(AgnosticBaseProperties):
session: Optional[AgnosticClientSession] = None,
comment: Optional[Any] = None,
**kwargs: Any,
) -> List[Any]: ...
) -> list[Any]: ...
async def drop(
self,
session: Optional[AgnosticClientSession] = None,
@ -575,11 +567,11 @@ class AgnosticCollection(AgnosticBaseProperties):
) -> str: ...
async def create_search_indexes(
self,
models: List[SearchIndexModel],
models: list[SearchIndexModel],
session: Optional[AgnosticClientSession] = None,
comment: Optional[Any] = None,
**kwargs: Any,
) -> List[str]: ...
) -> list[str]: ...
async def drop_search_index(
self,
name: str,
@ -659,8 +651,8 @@ class AgnosticBaseCursor(AgnosticBase):
def next_object(self) -> Any: ...
def each(self, callback: Callable) -> None: ...
def _each_got_more(self, callback: Callable, future: Any) -> None: ...
def to_list(self, length: int) -> Future[List]: ...
def _to_list(self, length: int, the_list: List, future: Any, get_more_result: Any) -> None: ...
def to_list(self, length: int) -> Future[list]: ...
def _to_list(self, length: int, the_list: list, future: Any, get_more_result: Any) -> None: ...
def get_io_loop(self) -> Any: ...
def batch_size(self, batch_size: int) -> AgnosticBaseCursor: ...
def _buffer_size(self) -> int: ...
@ -671,9 +663,9 @@ class AgnosticBaseCursor(AgnosticBase):
class AgnosticCursor(AgnosticBaseCursor):
__motor_class_name__: str
__delegate_class__: Type[Cursor]
__delegate_class__: type[Cursor]
def collation(self, collation: Optional[_CollationIn]) -> AgnosticCursor: ...
async def distinct(self, key: str) -> List: ...
async def distinct(self, key: str) -> list: ...
async def explain(self) -> _DocumentType: ...
def add_option(self, mask: int) -> AgnosticCursor: ...
def remove_option(self, mask: int) -> AgnosticCursor: ...
@ -701,11 +693,11 @@ class AgnosticCursor(AgnosticBaseCursor):
class AgnosticRawBatchCursor(AgnosticCursor):
__motor_class_name__: str
__delegate_class__: Type[RawBatchCursor]
__delegate_class__: type[RawBatchCursor]
class AgnosticCommandCursor(AgnosticBaseCursor):
__motor_class_name__: str
__delegate_class__: Type[CommandCursor]
__delegate_class__: type[CommandCursor]
def _query_flags(self) -> int: ...
def _data(self) -> Any: ...
@ -713,7 +705,7 @@ class AgnosticCommandCursor(AgnosticBaseCursor):
class AgnosticRawBatchCommandCursor(AgnosticCommandCursor):
__motor_class_name__: str
__delegate_class__: Type[RawBatchCommandCursor]
__delegate_class__: type[RawBatchCommandCursor]
class _LatentCursor:
def __init__(self, collection: AgnosticCollection): ...
@ -729,7 +721,7 @@ class AgnosticLatentCommandCursor(AgnosticCommandCursor):
class AgnosticChangeStream(AgnosticBase):
__motor_class_name__: str
__delegate_class__: Type[ChangeStream]
__delegate_class__: type[ChangeStream]
async def _close(self) -> None: ...
def resume_token(self) -> Optional[Mapping[str, Any]]: ...
@ -767,7 +759,7 @@ class AgnosticChangeStream(AgnosticBase):
class AgnosticClientEncryption(AgnosticBase):
__motor_class_name__: str
__delegate_class__: Type[ClientEncryption]
__delegate_class__: type[ClientEncryption]
def __init__(
self,
kms_providers: Mapping[str, Any],
@ -835,4 +827,4 @@ class AgnosticClientEncryption(AgnosticBase):
kms_provider: Optional[str] = None,
master_key: Optional[Mapping[str, Any]] = None,
**kwargs: Any,
) -> Tuple[AgnosticCollection, Mapping[str, Any]]: ...
) -> tuple[AgnosticCollection, Mapping[str, Any]]: ...

View File

@ -11,8 +11,6 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
get_database_doc = """
Get a :class:`MotorDatabase` with the given name and options.

View File

@ -16,8 +16,6 @@
See "Frameworks" in the Developer Guide.
"""
import asyncio
import asyncio.tasks
import functools
@ -68,7 +66,7 @@ _EXECUTOR = ThreadPoolExecutor(max_workers=max_workers)
def _reset_global_executor():
"""Re-initialize the global ThreadPoolExecutor"""
global _EXECUTOR
global _EXECUTOR # noqa: PLW0603
_EXECUTOR = ThreadPoolExecutor(max_workers=max_workers)

View File

@ -63,7 +63,7 @@ _EXECUTOR = ThreadPoolExecutor(max_workers=max_workers)
def _reset_global_executor():
"""Re-initialize the global ThreadPoolExecutor"""
global _EXECUTOR
global _EXECUTOR # noqa: PLW0603
_EXECUTOR = ThreadPoolExecutor(max_workers=max_workers)
@ -148,4 +148,4 @@ def yieldable(future):
def platform_info():
return "Tornado %s" % (tornado_version,)
return f"Tornado {tornado_version}"

View File

@ -13,7 +13,6 @@
# limitations under the License.
"""Dynamic class-creation for Motor."""
import functools
import inspect
from typing import Any, Callable, Dict
@ -121,7 +120,7 @@ def coroutine_annotation(f):
return f
class MotorAttributeFactory(object):
class MotorAttributeFactory:
"""Used by Motor classes to mark attributes that delegate in some way to
PyMongo. At module import time, create_class_with_framework calls
create_attribute() for each attr to create the final class attribute.

View File

@ -13,5 +13,4 @@
# limitations under the License.
"""Common code to support all async frameworks."""
callback_type_error = TypeError("callback must be a callable")

View File

@ -13,7 +13,6 @@
# limitations under the License.
"""GridFS implementation for Motor, an asynchronous driver for MongoDB."""
import hashlib
import warnings
@ -73,7 +72,7 @@ class MotorGridOutProperty(ReadOnlyProperty):
return property(fget=fget, doc=doc)
class AgnosticGridOut(object):
class AgnosticGridOut:
"""Class to read data out of GridFS.
MotorGridOut supports the same attributes as PyMongo's
@ -206,7 +205,7 @@ class AgnosticGridOut(object):
written += len(chunk)
class AgnosticGridIn(object):
class AgnosticGridIn:
__motor_class_name__ = "MotorGridIn"
__delegate_class__ = gridfs.GridIn
@ -315,7 +314,7 @@ Metadata set on the file appears as attributes on a
return self.io_loop
class AgnosticGridFSBucket(object):
class AgnosticGridFSBucket:
__motor_class_name__ = "MotorGridFSBucket"
__delegate_class__ = gridfs.GridFSBucket
@ -394,7 +393,7 @@ class AgnosticGridFSBucket(object):
if not isinstance(database, db_class):
raise TypeError(
"First argument to %s must be MotorDatabase, not %r" % (self.__class__, database)
f"First argument to {self.__class__} must be MotorDatabase, not {database!r}"
)
self.io_loop = database.get_io_loop()

View File

@ -16,7 +16,7 @@
import datetime
import os
from typing import Any, Iterable, List, Mapping, NoReturn, Optional, Type
from typing import Any, Iterable, Mapping, NoReturn, Optional
from bson import ObjectId
from gridfs import DEFAULT_CHUNK_SIZE, GridFSBucket, GridIn, GridOut, GridOutCursor
@ -40,11 +40,11 @@ class AgnosticGridOutCursor(AgnosticCursor):
async def _Cursor__die(self, synchronous: bool = False) -> None: ...
def next_object(self) -> AgnosticGridOutCursor: ...
class AgnosticGridOut(object):
class AgnosticGridOut:
__motor_class_name__: str
__delegate_class__: Type[GridOut]
__delegate_class__: type[GridOut]
_id: Any
aliases: Optional[List[str]]
aliases: Optional[list[str]]
chunk_size: int
filename: Optional[str]
name: Optional[str]
@ -77,9 +77,9 @@ class AgnosticGridOut(object):
def get_io_loop(self) -> Any: ...
async def stream_to_handler(self, request_handler: Any) -> None: ...
class AgnosticGridIn(object):
class AgnosticGridIn:
__motor_class_name__: str
__delegate_class__: Type[GridIn]
__delegate_class__: type[GridIn]
__getattr__: Any
_id: Any
filename: str
@ -111,9 +111,9 @@ class AgnosticGridIn(object):
async def __aexit__(self, exc_type: Any, exc_val: Any, exc_tb: Any) -> None: ...
def get_io_loop(self) -> Any: ...
class AgnosticGridFSBucket(object):
class AgnosticGridFSBucket:
__motor_class_name__: str
__delegate_class__: Type[GridFSBucket]
__delegate_class__: type[GridFSBucket]
async def delete(
self, file_id: Any, session: Optional[AgnosticClientSession] = None
) -> None: ...

View File

@ -13,7 +13,6 @@
# limitations under the License.
"""Utilities for using Motor with Tornado web applications."""
import datetime
import email.utils
import mimetypes
@ -97,7 +96,7 @@ class GridFSHandler(tornado.web.RequestHandler):
try:
gridout = await self.get_gridfs_file(fs, path, self.request)
except gridfs.NoFile:
raise tornado.web.HTTPError(404)
raise tornado.web.HTTPError(404) from None
# If-Modified-Since header is only good to the second.
modified = gridout.upload_date.replace(microsecond=0)
@ -175,4 +174,3 @@ class GridFSHandler(tornado.web.RequestHandler):
def set_extra_headers(self, path, gridout):
"""For subclass to add extra headers to the response"""
pass

View File

@ -80,3 +80,63 @@ version = {attr = "motor._version.version"}
[tool.setuptools.packages.find]
include = ["motor"]
[tool.ruff]
target-version = "py37"
line-length = 100
select = [
"E", "F", "W", # flake8
"B", # flake8-bugbear
"I", # isort
"ARG", # flake8-unused-arguments
"C4", # flake8-comprehensions
"EM", # flake8-errmsg
"ICN", # flake8-import-conventions
"ISC", # flake8-implicit-str-concat
"G", # flake8-logging-format
"PGH", # pygrep-hooks
"PIE", # flake8-pie
"PL", # pylint
"PT", # flake8-pytest-style
"PTH", # flake8-use-pathlib
"RUF", # Ruff-specific
"S", # flake8-bandit
"SIM", # flake8-simplify
"T20", # flake8-print
"UP", # pyupgrade
"YTT", # flake8-2020
"EXE", # flake8-executable
]
extend-ignore = [
"ARG001", # Unused function argument
"UP007", # Use `X | Y` for type annotation
"EM101", # Exception must not use a string literal, assign to variable first
"EM102", # Exception must not use an f-string literal, assign to variable first
"G004", # Logging statement uses f-string"
"PLR", # Too many arguments to function call, etc.
"SIM108", # Use ternary operator"
"SIM105", # Use `contextlib.suppress(OSError)` instead of `try`-`except`-`pass`
"ARG002", # Unused method argument:
"S101", # Use of `assert` detected
"RUF012", # Mutable class attributes should be annotated with `typing.ClassVar`
]
unfixable = [
"RUF100", # Unused noqa
"T20", # Removes print statements
"F841", # Removes unused variables
"F401"
]
exclude = []
flake8-unused-arguments.ignore-variadic-names = true
dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?)|dummy.*)$"
[tool.ruff.per-file-ignores]
"test/*.py" = ["PT009", "ARG", "E402", "PT027", "UP031",
"B904", "C405", "SIM", "PLR", "PTH", "B018", "C4",
"S", "E501", "T201", "E731", "F841", "F811",
"B011", "PT015", "E721"]
"synchro/__init__.py" = ["F403", "B904", "F401"]
"doc/*.py" = [ "T201", "PTH"]
"motor/docstrings.py" = [ "E501", ]
"doc/examples/*.py" = [ "E402", ]

View File

@ -12,5 +12,5 @@ filterwarnings =
ignore: The fetch_next property is deprecated:DeprecationWarning
ignore:The next_object method is deprecated:DeprecationWarning
ignore:unclosed <ssl.SSLSocket:ResourceWarning
ignore:datetime.utcfromtimestamp:DeprecationWarning
ignore:datetime.utcnow:DeprecationWarning
ignore:datetime.datetime.utcfromtimestamp:DeprecationWarning
ignore:datetime.datetime.utcnow:DeprecationWarning

View File

@ -194,13 +194,13 @@ def unwrap_synchro(fn):
return obj
args = [_unwrap_obj(arg) for arg in args]
kwargs = dict([(key, _unwrap_obj(value)) for key, value in kwargs.items()])
kwargs = dict([(key, _unwrap_obj(value)) for key, value in kwargs.items()]) # noqa: C404
return fn(*args, **kwargs)
return _unwrap_synchro
class SynchroAttr(object):
class SynchroAttr:
# Name can be set by SynchroMeta if Sync() is used directly in class defn.
def __init__(self, name=None):
self.name = name
@ -298,7 +298,7 @@ class SynchroMeta(type):
# Set DelegateProperties' and SynchroProperties' names.
for name, attr in attrs.items():
if isinstance(attr, (MotorAttributeFactory, SynchroAttr)):
if isinstance(attr, (MotorAttributeFactory, SynchroAttr)): # noqa: SIM102
if attr.name is None:
attr.name = name
@ -646,12 +646,12 @@ class GridOutCursor(Cursor):
__next__ = next
class CursorManager(object):
class CursorManager:
# Motor doesn't support cursor managers, just avoid ImportError.
pass
class BulkOperationBuilder(object):
class BulkOperationBuilder:
pass
@ -695,7 +695,7 @@ class GridIn(Synchro):
return self.synchronize(self.delegate.__aexit__)(exc_type, exc_val, exc_tb)
class SynchroGridOutProperty(object):
class SynchroGridOutProperty:
def __init__(self, name):
self.name = name
@ -777,7 +777,7 @@ class AutoEncryptionOpts(encryption_options.AutoEncryptionOpts):
def __init__(self, kms_providers, key_vault_namespace, key_vault_client=None, **kwargs):
if key_vault_client is not None:
key_vault_client = key_vault_client.delegate.delegate
super(AutoEncryptionOpts, self).__init__(
super().__init__(
kms_providers, key_vault_namespace, key_vault_client=key_vault_client, **kwargs
)

View File

@ -348,7 +348,7 @@ if __name__ == "__main__":
if os.environ.get("CHECK_EXCLUDE_PATTERNS"):
unused_module_pats = set(excluded_modules) - excluded_modules_matched
assert not unused_module_pats, "Unused module patterns: %s" % (unused_module_pats,)
assert not unused_module_pats, "Unused module patterns: {unused_module_pats}"
unused_test_pats = set(excluded_tests) - excluded_tests_matched
assert not unused_test_pats, "Unused test patterns: %s" % (unused_test_pats,)
assert not unused_test_pats, f"Unused test patterns: {unused_test_pats}"

View File

@ -31,7 +31,7 @@ except ImportError:
pass
class MockRequestHandler(object):
class MockRequestHandler:
"""For testing MotorGridOut.stream_to_handler."""
def __init__(self):

View File

@ -6,7 +6,7 @@ import logging
_LoggingWatcher = collections.namedtuple("_LoggingWatcher", ["records", "output"])
class _BaseTestCaseContext(object):
class _BaseTestCaseContext:
def __init__(self, test_case):
self.test_case = test_case
@ -70,12 +70,10 @@ class _AssertLogsContext(_BaseTestCaseContext):
return False
if len(self.watcher.records) == 0:
self._raiseFailure(
"no logs of level {0} or higher triggered on {1}".format(
self.level_name, self.logger.name
)
f"no logs of level {self.level_name} or higher triggered on {self.logger.name}"
)
class AssertLogsMixin(object):
class AssertLogsMixin:
def assertLogs(self, logger=None, level=None):
return _AssertLogsContext(self, logger, level)

View File

@ -30,7 +30,7 @@ from mockupdb import MockupDB
from motor import motor_asyncio
class _TestMethodWrapper(object):
class _TestMethodWrapper:
"""Wraps a test method to raise an error if it returns a value.
This is mainly used to detect undecorated generators (if a test

View File

@ -122,7 +122,7 @@ class TestAsyncIOCollection(AsyncIOTestCase):
await collection.insert_many([{"_id": 1}, {"_id": 2}, {"_id": 3}]) # Already exists
# First insert should have succeeded, but not second or third.
self.assertEqual(set([1, 2]), set((await collection.distinct("_id"))))
self.assertEqual(set([1, 2]), set(await collection.distinct("_id")))
@asyncio_test
async def test_delete_one(self):

View File

@ -318,7 +318,7 @@ class TestAsyncIOCursor(AsyncIOMockServerTestCase):
request = await self.run_thread(server.receives, "find", "coll")
request.replies({"cursor": {"id": 123, "ns": "db.coll", "firstBatch": [{"_id": 1}]}})
self.assertTrue((await future))
self.assertTrue(await future)
self.assertEqual(123, cursor.cursor_id)
future = asyncio.ensure_future(cursor.close())
@ -333,7 +333,7 @@ class TestAsyncIOCursor(AsyncIOMockServerTestCase):
# it's killed on the server.
self.assertTrue(cursor.alive)
self.assertEqual({"_id": 1}, cursor.next_object())
self.assertFalse((await cursor.fetch_next))
self.assertFalse(await cursor.fetch_next)
self.assertFalse(cursor.alive)
@asyncio_test
@ -367,7 +367,6 @@ class TestAsyncIOCursor(AsyncIOMockServerTestCase):
if error:
future.set_exception(error)
elif result:
pass
results.append(result)
else:
# Complete

View File

@ -118,8 +118,8 @@ class TestAsyncIODatabase(AsyncIOTestCase):
await db.validate_collection(db.test.doesnotexist)
await db.test.insert_one({"dummy": "object"})
self.assertTrue((await db.validate_collection("test")))
self.assertTrue((await db.validate_collection(db.test)))
self.assertTrue(await db.validate_collection("test"))
self.assertTrue(await db.validate_collection(db.test))
def test_get_collection(self):
codec_options = CodecOptions(tz_aware=True, uuid_representation=JAVA_LEGACY)

View File

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
# Copyright 2012-2015 MongoDB, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
@ -107,16 +106,16 @@ class MotorGridFileTest(AsyncIOTestCase):
g = motor_asyncio.AsyncIOMotorGridOut(self.db.fs, f._id)
# This is starting to look like Lisp.
self.assertEqual(3, len((await g.readchunk())))
self.assertEqual(3, len(await g.readchunk()))
self.assertEqual(2, len((await g.read(2))))
self.assertEqual(1, len((await g.readchunk())))
self.assertEqual(2, len(await g.read(2)))
self.assertEqual(1, len(await g.readchunk()))
self.assertEqual(3, len((await g.read(3))))
self.assertEqual(3, len(await g.read(3)))
self.assertEqual(1, len((await g.readchunk())))
self.assertEqual(1, len(await g.readchunk()))
self.assertEqual(0, len((await g.readchunk())))
self.assertEqual(0, len(await g.readchunk()))
@asyncio_test
async def test_gridout_open_exc_info(self):

View File

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
# Copyright 2016 MongoDB, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");

View File

@ -51,7 +51,7 @@ class MotorIPv6Test(AsyncIOTestCase):
cx = self.asyncio_client(uri=cx_string)
collection = cx.motor_test.test_collection
await collection.insert_one({"dummy": "object"})
self.assertTrue((await collection.find_one({"dummy": "object"})))
self.assertTrue(await collection.find_one({"dummy": "object"}))
if __name__ == "__main__":

View File

@ -97,13 +97,13 @@ def is_server_resolvable():
try:
socket.gethostbyname("server")
return True
except socket.error:
except OSError:
return False
finally:
socket.setdefaulttimeout(socket_timeout)
class TestEnvironment(object):
class TestEnvironment:
__test__ = False
def __init__(self):

View File

@ -120,7 +120,7 @@ class MotorCollectionTest(MotorTest):
await collection.insert_many([{"_id": 1}, {"_id": 2}, {"_id": 3}]) # Already exists
# First insert should have succeeded, but not second or third.
self.assertEqual(set([1, 2]), set((await collection.distinct("_id"))))
self.assertEqual(set([1, 2]), set(await collection.distinct("_id")))
@gen_test
async def test_delete_one(self):

View File

@ -57,7 +57,7 @@ class MotorCoreTest(MotorTest):
@gen_test
async def test_client_session_attrs(self):
self.assertEqual(
attrs(env.sync_cx.start_session()), attrs((await self.cx.start_session())) - motor_only
attrs(env.sync_cx.start_session()), attrs(await self.cx.start_session()) - motor_only
)
def test_database_attrs(self):

View File

@ -275,7 +275,7 @@ class MotorCursorTest(MotorMockServerTest):
request = await self.run_thread(server.receives, "find", "coll")
request.replies({"cursor": {"id": 123, "ns": "db.coll", "firstBatch": [{"_id": 1}]}})
self.assertTrue((await fetch_next))
self.assertTrue(await fetch_next)
async def mock_kill_cursors():
request = await self.run_thread(server.receives, "killCursors", "coll")
@ -287,7 +287,7 @@ class MotorCursorTest(MotorMockServerTest):
# it's killed on the server.
self.assertTrue(cursor.alive)
self.assertEqual({"_id": 1}, cursor.next_object())
self.assertFalse((await cursor.fetch_next))
self.assertFalse(await cursor.fetch_next)
self.assertFalse(cursor.alive)
@gen_test
@ -321,7 +321,6 @@ class MotorCursorTest(MotorMockServerTest):
if error:
future.set_exception(error)
elif result:
pass
results.append(result)
else:
# Complete

View File

@ -126,8 +126,8 @@ class MotorDatabaseTest(MotorTest):
await db.validate_collection(db.test.doesnotexist)
await db.test.insert_one({"dummy": "object"})
self.assertTrue((await db.validate_collection("test")))
self.assertTrue((await db.validate_collection(db.test)))
self.assertTrue(await db.validate_collection("test"))
self.assertTrue(await db.validate_collection(db.test))
def test_get_collection(self):
codec_options = CodecOptions(tz_aware=True, uuid_representation=JAVA_LEGACY)

View File

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
# Copyright 2012-2015 MongoDB, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
@ -106,16 +105,16 @@ class MotorGridFileTest(MotorTest):
g = motor.MotorGridOut(self.db.fs, f._id)
# This is starting to look like Lisp.
self.assertEqual(3, len((await g.readchunk())))
self.assertEqual(3, len(await g.readchunk()))
self.assertEqual(2, len((await g.read(2))))
self.assertEqual(1, len((await g.readchunk())))
self.assertEqual(2, len(await g.read(2)))
self.assertEqual(1, len(await g.readchunk()))
self.assertEqual(3, len((await g.read(3))))
self.assertEqual(3, len(await g.read(3)))
self.assertEqual(1, len((await g.readchunk())))
self.assertEqual(1, len(await g.readchunk()))
self.assertEqual(0, len((await g.readchunk())))
self.assertEqual(0, len(await g.readchunk()))
@gen_test
async def test_gridout_open_exc_info(self):

View File

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
# Copyright 2016 MongoDB, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");

View File

@ -54,7 +54,7 @@ class MotorIPv6Test(MotorTest):
cx = motor.MotorClient(cx_string, io_loop=self.io_loop)
collection = cx.motor_test.test_collection
await collection.insert_one({"dummy": "object"})
self.assertTrue((await collection.find_one({"dummy": "object"})))
self.assertTrue(await collection.find_one({"dummy": "object"}))
if __name__ == "__main__":

View File

@ -29,7 +29,7 @@ from tornado.testing import gen_test
from motor import core
class PatchSessionTimeout(object):
class PatchSessionTimeout:
"""Patches the client_session's with_transaction timeout for testing."""
def __init__(self, mock_timeout):