PYTHON-3120 Set up flake8 linting (#868)
This commit is contained in:
parent
1a90e477cf
commit
a0fe7c03af
30
.flake8
Normal file
30
.flake8
Normal file
@ -0,0 +1,30 @@
|
||||
[flake8]
|
||||
max-line-length = 100
|
||||
enable-extensions = G
|
||||
extend-ignore =
|
||||
G200, G202,
|
||||
# black adds spaces around ':'
|
||||
E203,
|
||||
# E501 line too long (let black handle line length)
|
||||
E501
|
||||
# B305 `.next()` is not a thing on Python 3
|
||||
B305
|
||||
per-file-ignores =
|
||||
# E402 module level import not at top of file
|
||||
pymongo/__init__.py: E402
|
||||
|
||||
# G004 Logging statement uses f-string
|
||||
pymongo/event_loggers.py: G004
|
||||
|
||||
# E402 module level import not at top of file
|
||||
# B011 Do not call assert False since python -O removes these calls
|
||||
# F405 'Foo' may be undefined, or defined from star imports
|
||||
# E741 ambiguous variable name
|
||||
# B007 Loop control variable 'foo' not used within the loop body
|
||||
# F403 'from foo import *' used; unable to detect undefined names
|
||||
# B001 Do not use bare `except:`
|
||||
# E722 do not use bare 'except'
|
||||
# E731 do not assign a lambda expression, use a def
|
||||
# F811 redefinition of unused 'foo' from line XXX
|
||||
# F841 local variable 'foo' is assigned to but never used
|
||||
test/*: E402, B011, F405, E741, B007, F403, B001, E722, E731, F811, F841
|
||||
4
.github/workflows/test-python.yml
vendored
4
.github/workflows/test-python.yml
vendored
@ -31,6 +31,8 @@ jobs:
|
||||
uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
cache: 'pip'
|
||||
cache-dependency-path: 'setup.py'
|
||||
- name: Start MongoDB
|
||||
uses: supercharge/mongodb-github-action@1.7.0
|
||||
with:
|
||||
@ -53,6 +55,8 @@ jobs:
|
||||
uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
cache: 'pip'
|
||||
cache-dependency-path: 'setup.py'
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install -U pip mypy
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
|
||||
repos:
|
||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||
rev: v3.4.0
|
||||
rev: v4.1.0
|
||||
hooks:
|
||||
- id: check-added-large-files
|
||||
- id: check-case-conflict
|
||||
@ -24,17 +24,36 @@ repos:
|
||||
args: [--line-length=100]
|
||||
|
||||
- repo: https://github.com/PyCQA/isort
|
||||
rev: 5.7.0
|
||||
rev: 5.10.1
|
||||
hooks:
|
||||
- id: isort
|
||||
files: \.py$
|
||||
args: [--profile=black]
|
||||
|
||||
- repo: https://gitlab.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',
|
||||
]
|
||||
|
||||
# We use the Python version instead of the original version which seems to require Docker
|
||||
# https://github.com/koalaman/shellcheck-precommit
|
||||
- repo: https://github.com/shellcheck-py/shellcheck-py
|
||||
rev: v0.8.0.1
|
||||
rev: v0.8.0.4
|
||||
hooks:
|
||||
- id: shellcheck
|
||||
name: shellcheck
|
||||
args: ["--severity=warning"]
|
||||
|
||||
- repo: https://github.com/sirosen/check-jsonschema
|
||||
rev: 0.11.0
|
||||
hooks:
|
||||
- id: check-jsonschema
|
||||
name: "Check GitHub Workflows"
|
||||
files: ^\.github/workflows/
|
||||
types: [yaml]
|
||||
args: ["--schemafile", "https://json.schemastore.org/github-workflow"]
|
||||
|
||||
@ -84,7 +84,7 @@ from typing import (
|
||||
cast,
|
||||
)
|
||||
|
||||
from bson.binary import (
|
||||
from bson.binary import ( # noqa: F401
|
||||
ALL_UUID_SUBTYPES,
|
||||
CSHARP_LEGACY,
|
||||
JAVA_LEGACY,
|
||||
@ -513,7 +513,7 @@ def _bson_to_dict(data: Any, opts: Any) -> Any:
|
||||
|
||||
|
||||
if _USE_C:
|
||||
_bson_to_dict = _cbson._bson_to_dict
|
||||
_bson_to_dict = _cbson._bson_to_dict # noqa: F811
|
||||
|
||||
|
||||
_PACK_FLOAT = struct.Struct("<d").pack
|
||||
@ -543,15 +543,15 @@ def _make_c_string_check(string: Union[str, bytes]) -> bytes:
|
||||
"""Make a 'C' string, checking for embedded NUL characters."""
|
||||
if isinstance(string, bytes):
|
||||
if b"\x00" in string:
|
||||
raise InvalidDocument("BSON keys / regex patterns must not " "contain a NUL character")
|
||||
raise InvalidDocument("BSON keys / regex patterns must not contain a NUL character")
|
||||
try:
|
||||
_utf_8_decode(string, None, True)
|
||||
return string + b"\x00"
|
||||
except UnicodeError:
|
||||
raise InvalidStringData("strings in documents must be valid " "UTF-8: %r" % string)
|
||||
raise InvalidStringData("strings in documents must be valid UTF-8: %r" % string)
|
||||
else:
|
||||
if "\x00" in string:
|
||||
raise InvalidDocument("BSON keys / regex patterns must not " "contain a NUL character")
|
||||
raise InvalidDocument("BSON keys / regex patterns must not contain a NUL character")
|
||||
return cast(bytes, _utf_8_encode(string)[0]) + b"\x00"
|
||||
|
||||
|
||||
@ -562,7 +562,7 @@ def _make_c_string(string: Union[str, bytes]) -> bytes:
|
||||
_utf_8_decode(string, None, True)
|
||||
return string + b"\x00"
|
||||
except UnicodeError:
|
||||
raise InvalidStringData("strings in documents must be valid " "UTF-8: %r" % string)
|
||||
raise InvalidStringData("strings in documents must be valid UTF-8: %r" % string)
|
||||
else:
|
||||
return cast(bytes, _utf_8_encode(string)[0]) + b"\x00"
|
||||
|
||||
@ -571,7 +571,7 @@ def _make_name(string: str) -> bytes:
|
||||
"""Make a 'C' string suitable for a BSON key."""
|
||||
# Keys can only be text in python 3.
|
||||
if "\x00" in string:
|
||||
raise InvalidDocument("BSON keys / regex patterns must not " "contain a NUL character")
|
||||
raise InvalidDocument("BSON keys / regex patterns must not contain a NUL character")
|
||||
return cast(bytes, _utf_8_encode(string)[0]) + b"\x00"
|
||||
|
||||
|
||||
@ -846,7 +846,7 @@ def _name_value_to_bson(
|
||||
def _element_to_bson(key: Any, value: Any, check_keys: bool, opts: Any) -> bytes:
|
||||
"""Encode a single key, value pair."""
|
||||
if not isinstance(key, str):
|
||||
raise InvalidDocument("documents must have only string keys, " "key was %r" % (key,))
|
||||
raise InvalidDocument("documents must have only string keys, key was %r" % (key,))
|
||||
if check_keys:
|
||||
if key.startswith("$"):
|
||||
raise InvalidDocument("key %r must not start with '$'" % (key,))
|
||||
@ -876,7 +876,7 @@ def _dict_to_bson(doc: Any, check_keys: bool, opts: Any, top_level: bool = True)
|
||||
|
||||
|
||||
if _USE_C:
|
||||
_dict_to_bson = _cbson._dict_to_bson
|
||||
_dict_to_bson = _cbson._dict_to_bson # noqa: F811
|
||||
|
||||
|
||||
def _millis_to_datetime(millis: int, opts: Any) -> datetime.datetime:
|
||||
@ -1032,7 +1032,7 @@ def decode_all(
|
||||
|
||||
|
||||
if _USE_C:
|
||||
decode_all = _cbson.decode_all
|
||||
decode_all = _cbson.decode_all # noqa: F811
|
||||
|
||||
|
||||
def _decode_selective(rawdoc: Any, fields: Any, codec_options: Any) -> Mapping[Any, Any]:
|
||||
|
||||
@ -260,7 +260,7 @@ class Binary(bytes):
|
||||
|
||||
if uuid_representation not in ALL_UUID_REPRESENTATIONS:
|
||||
raise ValueError(
|
||||
"uuid_representation must be a value " "from bson.binary.UuidRepresentation"
|
||||
"uuid_representation must be a value from bson.binary.UuidRepresentation"
|
||||
)
|
||||
|
||||
if uuid_representation == UuidRepresentation.UNSPECIFIED:
|
||||
@ -310,7 +310,7 @@ class Binary(bytes):
|
||||
|
||||
if uuid_representation not in ALL_UUID_REPRESENTATIONS:
|
||||
raise ValueError(
|
||||
"uuid_representation must be a value from " "bson.binary.UuidRepresentation"
|
||||
"uuid_representation must be a value from bson.binary.UuidRepresentation"
|
||||
)
|
||||
|
||||
if uuid_representation == UuidRepresentation.UNSPECIFIED:
|
||||
|
||||
@ -23,12 +23,10 @@ from typing import (
|
||||
Any,
|
||||
Callable,
|
||||
Dict,
|
||||
Generic,
|
||||
Iterable,
|
||||
MutableMapping,
|
||||
Optional,
|
||||
Type,
|
||||
TypeVar,
|
||||
Union,
|
||||
cast,
|
||||
)
|
||||
@ -312,10 +310,10 @@ class CodecOptions(_options_base):
|
||||
raise TypeError("tz_aware must be True or False")
|
||||
if uuid_representation not in ALL_UUID_REPRESENTATIONS:
|
||||
raise ValueError(
|
||||
"uuid_representation must be a value " "from bson.binary.UuidRepresentation"
|
||||
"uuid_representation must be a value from bson.binary.UuidRepresentation"
|
||||
)
|
||||
if not isinstance(unicode_decode_error_handler, (str, None)): # type: ignore
|
||||
raise ValueError("unicode_decode_error_handler must be a string " "or None")
|
||||
raise ValueError("unicode_decode_error_handler must be a string or None")
|
||||
if tzinfo is not None:
|
||||
if not isinstance(tzinfo, datetime.tzinfo):
|
||||
raise TypeError("tzinfo must be an instance of datetime.tzinfo")
|
||||
|
||||
@ -35,7 +35,7 @@ class DBRef(object):
|
||||
collection: str,
|
||||
id: Any,
|
||||
database: Optional[str] = None,
|
||||
_extra: Mapping[str, Any] = {},
|
||||
_extra: Optional[Mapping[str, Any]] = None,
|
||||
**kwargs: Any
|
||||
) -> None:
|
||||
"""Initialize a new :class:`DBRef`.
|
||||
@ -63,7 +63,7 @@ class DBRef(object):
|
||||
self.__collection = collection
|
||||
self.__id = id
|
||||
self.__database = database
|
||||
kwargs.update(_extra)
|
||||
kwargs.update(_extra or {})
|
||||
self.__kwargs = kwargs
|
||||
|
||||
@property
|
||||
|
||||
@ -283,7 +283,7 @@ class JSONOptions(CodecOptions):
|
||||
self.json_mode = json_mode
|
||||
if self.json_mode == JSONMode.RELAXED:
|
||||
if strict_number_long:
|
||||
raise ValueError("Cannot specify strict_number_long=True with" " JSONMode.RELAXED")
|
||||
raise ValueError("Cannot specify strict_number_long=True with JSONMode.RELAXED")
|
||||
if datetime_representation not in (None, DatetimeRepresentation.ISO8601):
|
||||
raise ValueError(
|
||||
"datetime_representation must be DatetimeRepresentation."
|
||||
@ -296,7 +296,7 @@ class JSONOptions(CodecOptions):
|
||||
self.strict_uuid = True
|
||||
elif self.json_mode == JSONMode.CANONICAL:
|
||||
if strict_number_long not in (None, True):
|
||||
raise ValueError("Cannot specify strict_number_long=False with" " JSONMode.RELAXED")
|
||||
raise ValueError("Cannot specify strict_number_long=False with JSONMode.RELAXED")
|
||||
if datetime_representation not in (None, DatetimeRepresentation.NUMBERLONG):
|
||||
raise ValueError(
|
||||
"datetime_representation must be DatetimeRepresentation."
|
||||
@ -581,11 +581,9 @@ def _parse_canonical_binary(doc: Any, json_options: JSONOptions) -> Union[Binary
|
||||
if not isinstance(b64, str):
|
||||
raise TypeError("$binary base64 must be a string: %s" % (doc,))
|
||||
if not isinstance(subtype, str) or len(subtype) > 2:
|
||||
raise TypeError("$binary subType must be a string at most 2 " "characters: %s" % (doc,))
|
||||
raise TypeError("$binary subType must be a string at most 2 characters: %s" % (doc,))
|
||||
if len(binary) != 2:
|
||||
raise TypeError(
|
||||
'$binary must include only "base64" and "subType" ' "components: %s" % (doc,)
|
||||
)
|
||||
raise TypeError('$binary must include only "base64" and "subType" components: %s' % (doc,))
|
||||
|
||||
data = base64.b64decode(b64.encode())
|
||||
return _binary_or_uuid(data, int(subtype, 16), json_options)
|
||||
@ -686,7 +684,7 @@ def _parse_canonical_regex(doc: Any) -> Regex:
|
||||
opts = regex["options"]
|
||||
if not isinstance(opts, str):
|
||||
raise TypeError(
|
||||
"Bad $regularExpression options, options must be " "string, was type %s" % (type(opts))
|
||||
"Bad $regularExpression options, options must be string, was type %s" % (type(opts))
|
||||
)
|
||||
return Regex(regex["pattern"], opts)
|
||||
|
||||
|
||||
@ -204,7 +204,7 @@ class ObjectId(object):
|
||||
_raise_invalid_id(oid)
|
||||
else:
|
||||
raise TypeError(
|
||||
"id must be an instance of (bytes, str, ObjectId), " "not %s" % (type(oid),)
|
||||
"id must be an instance of (bytes, str, ObjectId), not %s" % (type(oid),)
|
||||
)
|
||||
|
||||
@property
|
||||
|
||||
@ -51,8 +51,7 @@ blobs to disk, using raw BSON documents provides better speed and avoids the
|
||||
overhead of decoding or encoding BSON.
|
||||
"""
|
||||
|
||||
from collections.abc import Mapping as _Mapping
|
||||
from typing import Any, ItemsView, Iterator, Mapping, Optional, cast
|
||||
from typing import Any, ItemsView, Iterator, Mapping, Optional
|
||||
|
||||
from bson import _get_object_size, _raw_to_dict
|
||||
from bson.codec_options import _RAW_BSON_DOCUMENT_MARKER
|
||||
|
||||
@ -15,7 +15,7 @@
|
||||
"""Timezone related utilities for BSON."""
|
||||
|
||||
from datetime import datetime, timedelta, tzinfo
|
||||
from typing import Any, Optional, Tuple, Union
|
||||
from typing import Optional, Tuple, Union
|
||||
|
||||
ZERO: timedelta = timedelta(0)
|
||||
|
||||
|
||||
@ -9,7 +9,7 @@ import sys
|
||||
|
||||
sys.path[0:0] = [os.path.abspath("..")]
|
||||
|
||||
import pymongo
|
||||
import pymongo # noqa
|
||||
|
||||
# -- General configuration -----------------------------------------------------
|
||||
|
||||
|
||||
@ -59,7 +59,7 @@ def run(framework_name, *args):
|
||||
|
||||
# Run the tests.
|
||||
sys.argv[:] = ["setup.py", "test"] + list(args)
|
||||
import setup
|
||||
import setup # noqa
|
||||
|
||||
|
||||
def main():
|
||||
@ -87,7 +87,7 @@ python %s --help-frameworks.""" % (
|
||||
list_frameworks()
|
||||
sys.exit()
|
||||
else:
|
||||
assert False, "unhandled option"
|
||||
raise AssertionError("unhandled option")
|
||||
|
||||
if not args:
|
||||
print(usage)
|
||||
|
||||
@ -35,11 +35,10 @@ from gridfs.grid_file import (
|
||||
)
|
||||
from pymongo import ASCENDING, DESCENDING
|
||||
from pymongo.client_session import ClientSession
|
||||
from pymongo.collation import Collation
|
||||
from pymongo.collection import Collection
|
||||
from pymongo.common import UNAUTHORIZED_CODES, validate_string
|
||||
from pymongo.common import validate_string
|
||||
from pymongo.database import Database
|
||||
from pymongo.errors import ConfigurationError, OperationFailure
|
||||
from pymongo.errors import ConfigurationError
|
||||
from pymongo.read_preferences import _ServerMode
|
||||
from pymongo.write_concern import WriteConcern
|
||||
|
||||
@ -83,7 +82,7 @@ class GridFS(object):
|
||||
database = _clear_entity_type_registry(database)
|
||||
|
||||
if not database.write_concern.acknowledged:
|
||||
raise ConfigurationError("database must use " "acknowledged write_concern")
|
||||
raise ConfigurationError("database must use acknowledged write_concern")
|
||||
|
||||
self.__collection = database[collection]
|
||||
self.__files = self.__collection.files
|
||||
|
||||
@ -17,7 +17,7 @@ import datetime
|
||||
import io
|
||||
import math
|
||||
import os
|
||||
from typing import Any, Iterable, List, Mapping, Optional, cast
|
||||
from typing import Any, Iterable, List, Mapping, Optional
|
||||
|
||||
from bson.binary import Binary
|
||||
from bson.int64 import Int64
|
||||
@ -172,10 +172,10 @@ class GridIn(object):
|
||||
:attr:`~pymongo.collection.Collection.write_concern`
|
||||
"""
|
||||
if not isinstance(root_collection, Collection):
|
||||
raise TypeError("root_collection must be an " "instance of Collection")
|
||||
raise TypeError("root_collection must be an instance of Collection")
|
||||
|
||||
if not root_collection.write_concern.acknowledged:
|
||||
raise ConfigurationError("root_collection must use " "acknowledged write_concern")
|
||||
raise ConfigurationError("root_collection must use acknowledged write_concern")
|
||||
_disallow_transactions(session)
|
||||
|
||||
# Handle alternative naming
|
||||
@ -240,7 +240,7 @@ class GridIn(object):
|
||||
"uploadDate", "Date that this file was uploaded.", closed_only=True
|
||||
)
|
||||
md5: Optional[str] = _grid_in_property(
|
||||
"md5", "MD5 of the contents of this file " "if an md5 sum was created.", closed_only=True
|
||||
"md5", "MD5 of the contents of this file if an md5 sum was created.", closed_only=True
|
||||
)
|
||||
|
||||
_buffer: io.BytesIO
|
||||
@ -356,7 +356,7 @@ class GridIn(object):
|
||||
try:
|
||||
data = data.encode(self.encoding)
|
||||
except AttributeError:
|
||||
raise TypeError("must specify an encoding for file in " "order to write str")
|
||||
raise TypeError("must specify an encoding for file in order to write str")
|
||||
read = io.BytesIO(data).read
|
||||
|
||||
if self._buffer.tell() > 0:
|
||||
@ -365,7 +365,7 @@ class GridIn(object):
|
||||
if space:
|
||||
try:
|
||||
to_write = read(space)
|
||||
except:
|
||||
except BaseException:
|
||||
self.abort()
|
||||
raise
|
||||
self._buffer.write(to_write)
|
||||
@ -447,7 +447,7 @@ class GridOut(io.IOBase):
|
||||
from the server. Metadata is fetched when first needed.
|
||||
"""
|
||||
if not isinstance(root_collection, Collection):
|
||||
raise TypeError("root_collection must be an " "instance of Collection")
|
||||
raise TypeError("root_collection must be an instance of Collection")
|
||||
_disallow_transactions(session)
|
||||
|
||||
root_collection = _clear_entity_type_registry(root_collection)
|
||||
@ -477,7 +477,7 @@ class GridOut(io.IOBase):
|
||||
"metadata", "Metadata attached to this file."
|
||||
)
|
||||
md5: Optional[str] = _grid_out_property(
|
||||
"md5", "MD5 of the contents of this file " "if an md5 sum was created."
|
||||
"md5", "MD5 of the contents of this file if an md5 sum was created."
|
||||
)
|
||||
|
||||
_file: Any
|
||||
@ -886,7 +886,6 @@ class GridOutCursor(Cursor):
|
||||
def next(self) -> GridOut:
|
||||
"""Get next GridOut object from cursor."""
|
||||
_disallow_transactions(self.session)
|
||||
# Work around "super is not iterable" issue in Python 3.x
|
||||
next_file = super(GridOutCursor, self).next()
|
||||
return GridOut(self.__root_collection, file_document=next_file, session=self.session)
|
||||
|
||||
|
||||
@ -69,11 +69,14 @@ version = __version__
|
||||
|
||||
"""Current version of PyMongo."""
|
||||
|
||||
from pymongo.collection import ReturnDocument
|
||||
from pymongo.common import MAX_SUPPORTED_WIRE_VERSION, MIN_SUPPORTED_WIRE_VERSION
|
||||
from pymongo.cursor import CursorType
|
||||
from pymongo.mongo_client import MongoClient
|
||||
from pymongo.operations import (
|
||||
from pymongo.collection import ReturnDocument # noqa: F401
|
||||
from pymongo.common import ( # noqa: F401
|
||||
MAX_SUPPORTED_WIRE_VERSION,
|
||||
MIN_SUPPORTED_WIRE_VERSION,
|
||||
)
|
||||
from pymongo.cursor import CursorType # noqa: F401
|
||||
from pymongo.mongo_client import MongoClient # noqa: F401
|
||||
from pymongo.operations import ( # noqa: F401
|
||||
DeleteMany,
|
||||
DeleteOne,
|
||||
IndexModel,
|
||||
@ -82,14 +85,14 @@ from pymongo.operations import (
|
||||
UpdateMany,
|
||||
UpdateOne,
|
||||
)
|
||||
from pymongo.read_preferences import ReadPreference
|
||||
from pymongo.write_concern import WriteConcern
|
||||
from pymongo.read_preferences import ReadPreference # noqa: F401
|
||||
from pymongo.write_concern import WriteConcern # noqa: F401
|
||||
|
||||
|
||||
def has_c() -> bool:
|
||||
"""Is the C extension installed?"""
|
||||
try:
|
||||
from pymongo import _cmessage # type: ignore[attr-defined]
|
||||
from pymongo import _cmessage # type: ignore[attr-defined] # noqa: F401
|
||||
|
||||
return True
|
||||
except ImportError:
|
||||
|
||||
@ -43,7 +43,7 @@ class _AggregationCommand(object):
|
||||
):
|
||||
if "explain" in options:
|
||||
raise ConfigurationError(
|
||||
"The explain option is not supported. " "Use Database.command instead."
|
||||
"The explain option is not supported. Use Database.command instead."
|
||||
)
|
||||
|
||||
self._target = target
|
||||
|
||||
@ -121,7 +121,7 @@ def _build_credentials_tuple(mech, source, user, passwd, extra, database):
|
||||
if passwd is not None:
|
||||
raise ConfigurationError("Passwords are not supported by MONGODB-X509")
|
||||
if source is not None and source != "$external":
|
||||
raise ValueError("authentication source must be " "$external or None for MONGODB-X509")
|
||||
raise ValueError("authentication source must be $external or None for MONGODB-X509")
|
||||
# Source is always $external, user can be None.
|
||||
return MongoCredential(mech, "$external", user, None, None, None)
|
||||
elif mech == "MONGODB-AWS":
|
||||
@ -129,7 +129,7 @@ def _build_credentials_tuple(mech, source, user, passwd, extra, database):
|
||||
raise ConfigurationError("username without a password is not supported by MONGODB-AWS")
|
||||
if source is not None and source != "$external":
|
||||
raise ConfigurationError(
|
||||
"authentication source must be " "$external or None for MONGODB-AWS"
|
||||
"authentication source must be $external or None for MONGODB-AWS"
|
||||
)
|
||||
|
||||
properties = extra.get("authmechanismproperties", {})
|
||||
@ -302,7 +302,7 @@ def _authenticate_gssapi(credentials, sock_info):
|
||||
"""Authenticate using GSSAPI."""
|
||||
if not HAVE_KERBEROS:
|
||||
raise ConfigurationError(
|
||||
'The "kerberos" module must be ' "installed to use GSSAPI authentication."
|
||||
'The "kerberos" module must be installed to use GSSAPI authentication.'
|
||||
)
|
||||
|
||||
try:
|
||||
@ -351,7 +351,7 @@ def _authenticate_gssapi(credentials, sock_info):
|
||||
# 0 == continue, 1 == complete, -1 == error
|
||||
# Only authGSSClientStep can return 0.
|
||||
if kerberos.authGSSClientStep(ctx, "") != 0:
|
||||
raise OperationFailure("Unknown kerberos " "failure in step function.")
|
||||
raise OperationFailure("Unknown kerberos failure in step function.")
|
||||
|
||||
# Start a SASL conversation with mongod/s
|
||||
# Note: pykerberos deals with base64 encoded byte strings.
|
||||
@ -372,7 +372,7 @@ def _authenticate_gssapi(credentials, sock_info):
|
||||
for _ in range(10):
|
||||
result = kerberos.authGSSClientStep(ctx, str(response["payload"]))
|
||||
if result == -1:
|
||||
raise OperationFailure("Unknown kerberos " "failure in step function.")
|
||||
raise OperationFailure("Unknown kerberos failure in step function.")
|
||||
|
||||
payload = kerberos.authGSSClientResponse(ctx) or ""
|
||||
|
||||
@ -388,15 +388,15 @@ def _authenticate_gssapi(credentials, sock_info):
|
||||
if result == kerberos.AUTH_GSS_COMPLETE:
|
||||
break
|
||||
else:
|
||||
raise OperationFailure("Kerberos " "authentication failed to complete.")
|
||||
raise OperationFailure("Kerberos authentication failed to complete.")
|
||||
|
||||
# Once the security context is established actually authenticate.
|
||||
# See RFC 4752, Section 3.1, last two paragraphs.
|
||||
if kerberos.authGSSClientUnwrap(ctx, str(response["payload"])) != 1:
|
||||
raise OperationFailure("Unknown kerberos " "failure during GSS_Unwrap step.")
|
||||
raise OperationFailure("Unknown kerberos failure during GSS_Unwrap step.")
|
||||
|
||||
if kerberos.authGSSClientWrap(ctx, kerberos.authGSSClientResponse(ctx), username) != 1:
|
||||
raise OperationFailure("Unknown kerberos " "failure during GSS_Wrap step.")
|
||||
raise OperationFailure("Unknown kerberos failure during GSS_Wrap step.")
|
||||
|
||||
payload = kerberos.authGSSClientResponse(ctx)
|
||||
cmd = SON(
|
||||
|
||||
@ -26,7 +26,6 @@ from pymongo.client_session import _validate_session_write_concern
|
||||
from pymongo.collation import validate_collation_or_none
|
||||
from pymongo.common import (
|
||||
validate_is_document_type,
|
||||
validate_is_mapping,
|
||||
validate_ok_for_replace,
|
||||
validate_ok_for_update,
|
||||
)
|
||||
@ -476,7 +475,7 @@ class _Bulk(object):
|
||||
# Cannot have both unacknowledged writes and bypass document validation.
|
||||
if self.bypass_doc_val:
|
||||
raise OperationFailure(
|
||||
"Cannot set bypass_document_validation with" " unacknowledged write concern"
|
||||
"Cannot set bypass_document_validation with unacknowledged write concern"
|
||||
)
|
||||
|
||||
if self.ordered:
|
||||
@ -488,7 +487,7 @@ class _Bulk(object):
|
||||
if not self.ops:
|
||||
raise InvalidOperation("No operations to execute")
|
||||
if self.executed:
|
||||
raise InvalidOperation("Bulk operations can " "only be executed once.")
|
||||
raise InvalidOperation("Bulk operations can only be executed once.")
|
||||
self.executed = True
|
||||
write_concern = write_concern or self.collection.write_concern
|
||||
session = _validate_session_write_concern(session, write_concern)
|
||||
|
||||
@ -15,7 +15,7 @@
|
||||
"""Watch changes on a collection, a database, or the entire cluster."""
|
||||
|
||||
import copy
|
||||
from typing import TYPE_CHECKING, Any, Dict, Generic, Iterator, Mapping, Optional, Union
|
||||
from typing import TYPE_CHECKING, Any, Dict, Generic, Mapping, Optional, Union
|
||||
|
||||
from bson import _bson_to_dict
|
||||
from bson.raw_bson import RawBSONDocument
|
||||
@ -363,7 +363,7 @@ class ChangeStream(Generic[_DocumentType]):
|
||||
except KeyError:
|
||||
self.close()
|
||||
raise InvalidOperation(
|
||||
"Cannot provide resume functionality when the resume " "token is missing."
|
||||
"Cannot provide resume functionality when the resume token is missing."
|
||||
)
|
||||
|
||||
# If this is the last change document from the current batch, cache the
|
||||
|
||||
@ -192,7 +192,7 @@ class SessionOptions(object):
|
||||
) -> None:
|
||||
if snapshot:
|
||||
if causal_consistency:
|
||||
raise ConfigurationError("snapshot reads do not support " "causal_consistency=True")
|
||||
raise ConfigurationError("snapshot reads do not support causal_consistency=True")
|
||||
causal_consistency = False
|
||||
elif causal_consistency is None:
|
||||
causal_consistency = True
|
||||
@ -717,7 +717,7 @@ class ClientSession(Generic[_DocumentType]):
|
||||
self._check_ended()
|
||||
|
||||
if self.options.snapshot:
|
||||
raise InvalidOperation("Transactions are not supported in " "snapshot sessions")
|
||||
raise InvalidOperation("Transactions are not supported in snapshot sessions")
|
||||
|
||||
if self.in_transaction:
|
||||
raise InvalidOperation("Transaction already in progress")
|
||||
@ -885,7 +885,7 @@ class ClientSession(Generic[_DocumentType]):
|
||||
another `ClientSession` instance.
|
||||
"""
|
||||
if not isinstance(operation_time, Timestamp):
|
||||
raise TypeError("operation_time must be an instance " "of bson.timestamp.Timestamp")
|
||||
raise TypeError("operation_time must be an instance of bson.timestamp.Timestamp")
|
||||
self._advance_operation_time(operation_time)
|
||||
|
||||
def _process_response(self, reply):
|
||||
|
||||
@ -221,4 +221,4 @@ def validate_collation_or_none(
|
||||
return value.document
|
||||
if isinstance(value, dict):
|
||||
return value
|
||||
raise TypeError("collation must be a dict, an instance of collation.Collation, " "or None.")
|
||||
raise TypeError("collation must be a dict, an instance of collation.Collation, or None.")
|
||||
|
||||
@ -29,7 +29,6 @@ from typing import (
|
||||
Union,
|
||||
)
|
||||
|
||||
from bson.code import Code
|
||||
from bson.codec_options import CodecOptions
|
||||
from bson.objectid import ObjectId
|
||||
from bson.raw_bson import RawBSONDocument
|
||||
@ -204,11 +203,11 @@ class Collection(common.BaseObject, Generic[_DocumentType]):
|
||||
if not name or ".." in name:
|
||||
raise InvalidName("collection names cannot be empty")
|
||||
if "$" in name and not (name.startswith("oplog.$main") or name.startswith("$cmd")):
|
||||
raise InvalidName("collection names must not " "contain '$': %r" % name)
|
||||
raise InvalidName("collection names must not contain '$': %r" % name)
|
||||
if name[0] == "." or name[-1] == ".":
|
||||
raise InvalidName("collection names must not start " "or end with '.': %r" % name)
|
||||
raise InvalidName("collection names must not start or end with '.': %r" % name)
|
||||
if "\x00" in name:
|
||||
raise InvalidName("collection names must not contain the " "null character")
|
||||
raise InvalidName("collection names must not contain the null character")
|
||||
collation = validate_collation_or_none(kwargs.pop("collation", None))
|
||||
|
||||
self.__database: Database[_DocumentType] = database
|
||||
@ -1873,7 +1872,7 @@ class Collection(common.BaseObject, Generic[_DocumentType]):
|
||||
for index in indexes:
|
||||
if not isinstance(index, IndexModel):
|
||||
raise TypeError(
|
||||
"%r is not an instance of " "pymongo.operations.IndexModel" % (index,)
|
||||
"%r is not an instance of pymongo.operations.IndexModel" % (index,)
|
||||
)
|
||||
document = index.document
|
||||
names.append(document["name"])
|
||||
@ -2725,7 +2724,7 @@ class Collection(common.BaseObject, Generic[_DocumentType]):
|
||||
common.validate_is_mapping("filter", filter)
|
||||
if not isinstance(return_document, bool):
|
||||
raise ValueError(
|
||||
"return_document must be " "ReturnDocument.BEFORE or ReturnDocument.AFTER"
|
||||
"return_document must be ReturnDocument.BEFORE or ReturnDocument.AFTER"
|
||||
)
|
||||
collation = validate_collation_or_none(kwargs.pop("collation", None))
|
||||
cmd = SON([("findAndModify", self.__name), ("query", filter), ("new", return_document)])
|
||||
@ -2751,7 +2750,7 @@ class Collection(common.BaseObject, Generic[_DocumentType]):
|
||||
if array_filters is not None:
|
||||
if not acknowledged:
|
||||
raise ConfigurationError(
|
||||
"arrayFilters is unsupported for unacknowledged " "writes."
|
||||
"arrayFilters is unsupported for unacknowledged writes."
|
||||
)
|
||||
cmd["arrayFilters"] = list(array_filters)
|
||||
if hint is not None:
|
||||
|
||||
@ -15,7 +15,7 @@
|
||||
"""CommandCursor class to iterate over command results."""
|
||||
|
||||
from collections import deque
|
||||
from typing import TYPE_CHECKING, Any, Generic, Iterator, Mapping, Optional, Tuple
|
||||
from typing import TYPE_CHECKING, Any, Generic, Iterator, Mapping, Optional
|
||||
|
||||
from bson import _convert_raw_document_lists_to_streams
|
||||
from pymongo.cursor import _CURSOR_CLOSED_ERRORS, _SocketManager
|
||||
|
||||
@ -30,7 +30,6 @@ from typing import (
|
||||
Tuple,
|
||||
Type,
|
||||
Union,
|
||||
cast,
|
||||
)
|
||||
from urllib.parse import unquote_plus
|
||||
|
||||
@ -180,7 +179,7 @@ def validate_boolean_or_string(option: str, value: Any) -> bool:
|
||||
"""Validates that value is True, False, 'true', or 'false'."""
|
||||
if isinstance(value, str):
|
||||
if value not in ("true", "false"):
|
||||
raise ValueError("The value of %s must be " "'true' or 'false'" % (option,))
|
||||
raise ValueError("The value of %s must be 'true' or 'false'" % (option,))
|
||||
return value == "true"
|
||||
return validate_boolean(option, value)
|
||||
|
||||
@ -193,7 +192,7 @@ def validate_integer(option: str, value: Any) -> int:
|
||||
try:
|
||||
return int(value)
|
||||
except ValueError:
|
||||
raise ValueError("The value of %s must be " "an integer" % (option,))
|
||||
raise ValueError("The value of %s must be an integer" % (option,))
|
||||
raise TypeError("Wrong type for %s, value must be an integer" % (option,))
|
||||
|
||||
|
||||
@ -201,7 +200,7 @@ def validate_positive_integer(option: str, value: Any) -> int:
|
||||
"""Validate that 'value' is a positive integer, which does not include 0."""
|
||||
val = validate_integer(option, value)
|
||||
if val <= 0:
|
||||
raise ValueError("The value of %s must be " "a positive integer" % (option,))
|
||||
raise ValueError("The value of %s must be a positive integer" % (option,))
|
||||
return val
|
||||
|
||||
|
||||
@ -209,7 +208,7 @@ def validate_non_negative_integer(option: str, value: Any) -> int:
|
||||
"""Validate that 'value' is a positive integer or 0."""
|
||||
val = validate_integer(option, value)
|
||||
if val < 0:
|
||||
raise ValueError("The value of %s must be " "a non negative integer" % (option,))
|
||||
raise ValueError("The value of %s must be a non negative integer" % (option,))
|
||||
return val
|
||||
|
||||
|
||||
@ -242,7 +241,7 @@ def validate_string(option: str, value: Any) -> str:
|
||||
"""Validates that 'value' is an instance of `str`."""
|
||||
if isinstance(value, str):
|
||||
return value
|
||||
raise TypeError("Wrong type for %s, value must be an instance of " "str" % (option,))
|
||||
raise TypeError("Wrong type for %s, value must be an instance of str" % (option,))
|
||||
|
||||
|
||||
def validate_string_or_none(option: str, value: Any) -> Optional[str]:
|
||||
@ -261,7 +260,7 @@ def validate_int_or_basestring(option: str, value: Any) -> Union[int, str]:
|
||||
return int(value)
|
||||
except ValueError:
|
||||
return value
|
||||
raise TypeError("Wrong type for %s, value must be an " "integer or a string" % (option,))
|
||||
raise TypeError("Wrong type for %s, value must be an integer or a string" % (option,))
|
||||
|
||||
|
||||
def validate_non_negative_int_or_basestring(option: Any, value: Any) -> Union[int, str]:
|
||||
@ -275,7 +274,7 @@ def validate_non_negative_int_or_basestring(option: Any, value: Any) -> Union[in
|
||||
return value
|
||||
return validate_non_negative_integer(option, val)
|
||||
raise TypeError(
|
||||
"Wrong type for %s, value must be an " "non negative integer or a string" % (option,)
|
||||
"Wrong type for %s, value must be an non negative integer or a string" % (option,)
|
||||
)
|
||||
|
||||
|
||||
@ -294,7 +293,7 @@ def validate_positive_float(option: str, value: Any) -> float:
|
||||
# float('inf') doesn't work in 2.4 or 2.5 on Windows, so just cap floats at
|
||||
# one billion - this is a reasonable approximation for infinity
|
||||
if not 0 < value < 1e9:
|
||||
raise ValueError("%s must be greater than 0 and " "less than one billion" % (option,))
|
||||
raise ValueError("%s must be greater than 0 and less than one billion" % (option,))
|
||||
return value
|
||||
|
||||
|
||||
@ -402,7 +401,7 @@ def validate_read_preference_tags(name: str, value: Any) -> List[Dict[str, str]]
|
||||
tags[unquote_plus(key)] = unquote_plus(val)
|
||||
tag_sets.append(tags)
|
||||
except Exception:
|
||||
raise ValueError("%r not a valid " "value for %s" % (tag_set, name))
|
||||
raise ValueError("%r not a valid value for %s" % (tag_set, name))
|
||||
return tag_sets
|
||||
|
||||
|
||||
@ -735,7 +734,7 @@ def validate_auth_option(option: str, value: Any) -> Tuple[str, Any]:
|
||||
"""Validate optional authentication parameters."""
|
||||
lower, value = validate(option, value)
|
||||
if lower not in _AUTH_OPTIONS:
|
||||
raise ConfigurationError("Unknown " "authentication option: %s" % (option,))
|
||||
raise ConfigurationError("Unknown authentication option: %s" % (option,))
|
||||
return option, value
|
||||
|
||||
|
||||
@ -762,12 +761,12 @@ def get_validated_options(
|
||||
validated_options: MutableMapping[str, Any]
|
||||
if isinstance(options, _CaseInsensitiveDictionary):
|
||||
validated_options = _CaseInsensitiveDictionary()
|
||||
get_normed_key = lambda x: x
|
||||
get_setter_key = lambda x: options.cased_key(x)
|
||||
get_normed_key = lambda x: x # noqa: E731
|
||||
get_setter_key = lambda x: options.cased_key(x) # noqa: E731
|
||||
else:
|
||||
validated_options = {}
|
||||
get_normed_key = lambda x: x.lower()
|
||||
get_setter_key = lambda x: x
|
||||
get_normed_key = lambda x: x.lower() # noqa: E731
|
||||
get_setter_key = lambda x: x # noqa: E731
|
||||
|
||||
for opt, value in options.items():
|
||||
normed_key = get_normed_key(opt)
|
||||
@ -804,9 +803,7 @@ class BaseObject(object):
|
||||
) -> None:
|
||||
|
||||
if not isinstance(codec_options, CodecOptions):
|
||||
raise TypeError(
|
||||
"codec_options must be an instance of " "bson.codec_options.CodecOptions"
|
||||
)
|
||||
raise TypeError("codec_options must be an instance of bson.codec_options.CodecOptions")
|
||||
self.__codec_options = codec_options
|
||||
|
||||
if not isinstance(read_preference, _ServerMode):
|
||||
@ -819,14 +816,12 @@ class BaseObject(object):
|
||||
|
||||
if not isinstance(write_concern, WriteConcern):
|
||||
raise TypeError(
|
||||
"write_concern must be an instance of " "pymongo.write_concern.WriteConcern"
|
||||
"write_concern must be an instance of pymongo.write_concern.WriteConcern"
|
||||
)
|
||||
self.__write_concern = write_concern
|
||||
|
||||
if not isinstance(read_concern, ReadConcern):
|
||||
raise TypeError(
|
||||
"read_concern must be an instance of " "pymongo.read_concern.ReadConcern"
|
||||
)
|
||||
raise TypeError("read_concern must be an instance of pymongo.read_concern.ReadConcern")
|
||||
self.__read_concern = read_concern
|
||||
|
||||
@property
|
||||
|
||||
@ -82,7 +82,7 @@ def validate_compressors(dummy, value):
|
||||
def validate_zlib_compression_level(option, value):
|
||||
try:
|
||||
level = int(value)
|
||||
except:
|
||||
except Exception:
|
||||
raise TypeError("%s must be an integer, not %r." % (option, value))
|
||||
if level < -1 or level > 9:
|
||||
raise ValueError("%s must be between -1 and 9, not %d." % (option, level))
|
||||
|
||||
@ -25,7 +25,6 @@ from typing import (
|
||||
Iterable,
|
||||
List,
|
||||
Mapping,
|
||||
MutableMapping,
|
||||
Optional,
|
||||
Sequence,
|
||||
Tuple,
|
||||
@ -277,7 +276,7 @@ class Cursor(Generic[_DocumentType]):
|
||||
# Exhaust cursor support
|
||||
if cursor_type == CursorType.EXHAUST:
|
||||
if self.__collection.database.client.is_mongos:
|
||||
raise InvalidOperation("Exhaust cursors are " "not supported by mongos")
|
||||
raise InvalidOperation("Exhaust cursors are not supported by mongos")
|
||||
if limit:
|
||||
raise InvalidOperation("Can't use limit and exhaust together.")
|
||||
self.__exhaust = True
|
||||
@ -509,7 +508,7 @@ class Cursor(Generic[_DocumentType]):
|
||||
if self.__limit:
|
||||
raise InvalidOperation("Can't use limit and exhaust together.")
|
||||
if self.__collection.database.client.is_mongos:
|
||||
raise InvalidOperation("Exhaust cursors are " "not supported by mongos")
|
||||
raise InvalidOperation("Exhaust cursors are not supported by mongos")
|
||||
self.__exhaust = True
|
||||
|
||||
self.__query_flags |= mask
|
||||
@ -730,14 +729,14 @@ class Cursor(Generic[_DocumentType]):
|
||||
skip = 0
|
||||
if index.start is not None:
|
||||
if index.start < 0:
|
||||
raise IndexError("Cursor instances do not support " "negative indices")
|
||||
raise IndexError("Cursor instances do not support negative indices")
|
||||
skip = index.start
|
||||
|
||||
if index.stop is not None:
|
||||
limit = index.stop - skip
|
||||
if limit < 0:
|
||||
raise IndexError(
|
||||
"stop index must be greater than start " "index for slice %r" % index
|
||||
"stop index must be greater than start index for slice %r" % index
|
||||
)
|
||||
if limit == 0:
|
||||
self.__empty = True
|
||||
@ -750,7 +749,7 @@ class Cursor(Generic[_DocumentType]):
|
||||
|
||||
if isinstance(index, int):
|
||||
if index < 0:
|
||||
raise IndexError("Cursor instances do not support negative " "indices")
|
||||
raise IndexError("Cursor instances do not support negative indices")
|
||||
clone = self.clone()
|
||||
clone.skip(index + self.__skip)
|
||||
clone.limit(-1) # use a hard limit
|
||||
@ -758,7 +757,7 @@ class Cursor(Generic[_DocumentType]):
|
||||
for doc in clone:
|
||||
return doc
|
||||
raise IndexError("no such item for Cursor instance")
|
||||
raise TypeError("index %r cannot be applied to Cursor " "instances" % index)
|
||||
raise TypeError("index %r cannot be applied to Cursor instances" % index)
|
||||
|
||||
def max_scan(self, max_scan: Optional[int]) -> "Cursor[_DocumentType]":
|
||||
"""**DEPRECATED** - Limit the number of documents to scan when
|
||||
|
||||
@ -70,7 +70,7 @@ if sys.platform == "win32":
|
||||
_silence_resource_warning(popen)
|
||||
except FileNotFoundError as exc:
|
||||
warnings.warn(
|
||||
f"Failed to start {args[0]}: is it on your $PATH?\n" f"Original exception: {exc}",
|
||||
f"Failed to start {args[0]}: is it on your $PATH?\nOriginal exception: {exc}",
|
||||
RuntimeWarning,
|
||||
stacklevel=2,
|
||||
)
|
||||
@ -96,7 +96,7 @@ else:
|
||||
)
|
||||
except FileNotFoundError as exc:
|
||||
warnings.warn(
|
||||
f"Failed to start {args[0]}: is it on your $PATH?\n" f"Original exception: {exc}",
|
||||
f"Failed to start {args[0]}: is it on your $PATH?\nOriginal exception: {exc}",
|
||||
RuntimeWarning,
|
||||
stacklevel=2,
|
||||
)
|
||||
|
||||
@ -47,7 +47,7 @@ def _check_name(name):
|
||||
|
||||
for invalid_char in [" ", ".", "$", "/", "\\", "\x00", '"']:
|
||||
if invalid_char in name:
|
||||
raise InvalidName("database names cannot contain the " "character %r" % invalid_char)
|
||||
raise InvalidName("database names cannot contain the character %r" % invalid_char)
|
||||
|
||||
|
||||
if TYPE_CHECKING:
|
||||
@ -966,7 +966,7 @@ class Database(common.BaseObject, Generic[_DocumentType]):
|
||||
name = name.name
|
||||
|
||||
if not isinstance(name, str):
|
||||
raise TypeError("name_or_collection must be an instance of str or " "Collection")
|
||||
raise TypeError("name_or_collection must be an instance of str or Collection")
|
||||
cmd = SON([("validate", name), ("scandata", scandata), ("full", full)])
|
||||
if comment is not None:
|
||||
cmd["comment"] = comment
|
||||
@ -988,7 +988,7 @@ class Database(common.BaseObject, Generic[_DocumentType]):
|
||||
if "result" in res:
|
||||
info = res["result"]
|
||||
if info.find("exception") != -1 or info.find("corrupt") != -1:
|
||||
raise CollectionInvalid("%s invalid: " "%s" % (name, info))
|
||||
raise CollectionInvalid("%s invalid: %s" % (name, info))
|
||||
elif not res.get("valid", False):
|
||||
valid = False
|
||||
break
|
||||
|
||||
@ -21,7 +21,7 @@ from typing import Any, Mapping, Optional, Sequence
|
||||
|
||||
try:
|
||||
from pymongocrypt.auto_encrypter import AutoEncrypter
|
||||
from pymongocrypt.errors import MongoCryptError
|
||||
from pymongocrypt.errors import MongoCryptError # noqa: F401
|
||||
from pymongocrypt.explicit_encrypter import ExplicitEncrypter
|
||||
from pymongocrypt.mongocrypt import MongoCryptOptions
|
||||
from pymongocrypt.state_machine import MongoCryptCallback
|
||||
@ -440,9 +440,7 @@ class ClientEncryption(object):
|
||||
)
|
||||
|
||||
if not isinstance(codec_options, CodecOptions):
|
||||
raise TypeError(
|
||||
"codec_options must be an instance of " "bson.codec_options.CodecOptions"
|
||||
)
|
||||
raise TypeError("codec_options must be an instance of bson.codec_options.CodecOptions")
|
||||
|
||||
self._kms_providers = kms_providers
|
||||
self._key_vault_namespace = key_vault_namespace
|
||||
|
||||
@ -14,11 +14,10 @@
|
||||
|
||||
"""Support for automatic client-side field level encryption."""
|
||||
|
||||
import copy
|
||||
from typing import TYPE_CHECKING, Any, List, Mapping, Optional
|
||||
|
||||
try:
|
||||
import pymongocrypt
|
||||
import pymongocrypt # noqa: F401
|
||||
|
||||
_HAVE_PYMONGOCRYPT = True
|
||||
except ImportError:
|
||||
|
||||
@ -15,7 +15,7 @@
|
||||
"""Exceptions raised by PyMongo."""
|
||||
from typing import Any, Iterable, List, Mapping, Optional, Sequence, Tuple, Union
|
||||
|
||||
from bson.errors import *
|
||||
from bson.errors import InvalidDocument
|
||||
|
||||
try:
|
||||
# CPython 3.7+
|
||||
|
||||
@ -43,25 +43,25 @@ class CommandLogger(monitoring.CommandListener):
|
||||
|
||||
def started(self, event: monitoring.CommandStartedEvent) -> None:
|
||||
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: monitoring.CommandSucceededEvent) -> None:
|
||||
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: monitoring.CommandFailedEvent) -> None:
|
||||
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,7 +77,7 @@ class ServerLogger(monitoring.ServerListener):
|
||||
"""
|
||||
|
||||
def opened(self, event: monitoring.ServerOpeningEvent) -> None:
|
||||
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: monitoring.ServerDescriptionChangedEvent) -> None:
|
||||
previous_server_type = event.previous_description.server_type
|
||||
@ -85,15 +85,13 @@ class ServerLogger(monitoring.ServerListener):
|
||||
if new_server_type != previous_server_type:
|
||||
# server_type_name was added in PyMongo 3.4
|
||||
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: monitoring.ServerClosedEvent) -> None:
|
||||
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}")
|
||||
|
||||
|
||||
class HeartbeatLogger(monitoring.ServerHeartbeatListener):
|
||||
@ -108,19 +106,19 @@ class HeartbeatLogger(monitoring.ServerHeartbeatListener):
|
||||
"""
|
||||
|
||||
def started(self, event: monitoring.ServerHeartbeatStartedEvent) -> None:
|
||||
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: monitoring.ServerHeartbeatSucceededEvent) -> None:
|
||||
# The reply.document attribute was added in PyMongo 3.4.
|
||||
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: monitoring.ServerHeartbeatFailedEvent) -> None:
|
||||
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}"
|
||||
)
|
||||
|
||||
|
||||
@ -136,20 +134,18 @@ class TopologyLogger(monitoring.TopologyListener):
|
||||
"""
|
||||
|
||||
def opened(self, event: monitoring.TopologyOpenedEvent) -> None:
|
||||
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: monitoring.TopologyDescriptionChangedEvent) -> None:
|
||||
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:
|
||||
# topology_type_name was added in PyMongo 3.4
|
||||
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}"
|
||||
)
|
||||
# The has_writable_server and has_readable_server methods
|
||||
# were added in PyMongo 3.4.
|
||||
@ -159,7 +155,7 @@ class TopologyLogger(monitoring.TopologyListener):
|
||||
logging.warning("No readable servers available.")
|
||||
|
||||
def closed(self, event: monitoring.TopologyClosedEvent) -> None:
|
||||
logging.info("Topology with id {0.topology_id} " "closed".format(event))
|
||||
logging.info(f"Topology with id {event.topology_id} closed")
|
||||
|
||||
|
||||
class ConnectionPoolLogger(monitoring.ConnectionPoolListener):
|
||||
@ -181,53 +177,45 @@ class ConnectionPoolLogger(monitoring.ConnectionPoolListener):
|
||||
"""
|
||||
|
||||
def pool_created(self, event: monitoring.PoolCreatedEvent) -> None:
|
||||
logging.info("[pool {0.address}] pool created".format(event))
|
||||
logging.info(f"[pool {event.address}] pool created")
|
||||
|
||||
def pool_ready(self, event):
|
||||
logging.info("[pool {0.address}] pool ready".format(event))
|
||||
logging.info(f"[pool {event.address}] pool ready")
|
||||
|
||||
def pool_cleared(self, event: monitoring.PoolClearedEvent) -> None:
|
||||
logging.info("[pool {0.address}] pool cleared".format(event))
|
||||
logging.info(f"[pool {event.address}] pool cleared")
|
||||
|
||||
def pool_closed(self, event: monitoring.PoolClosedEvent) -> None:
|
||||
logging.info("[pool {0.address}] pool closed".format(event))
|
||||
logging.info(f"[pool {event.address}] pool closed")
|
||||
|
||||
def connection_created(self, event: monitoring.ConnectionCreatedEvent) -> None:
|
||||
logging.info(
|
||||
"[pool {0.address}][conn #{0.connection_id}] " "connection created".format(event)
|
||||
)
|
||||
logging.info(f"[pool {event.address}][conn #{event.connection_id}] connection created")
|
||||
|
||||
def connection_ready(self, event: monitoring.ConnectionReadyEvent) -> None:
|
||||
logging.info(
|
||||
"[pool {0.address}][conn #{0.connection_id}] "
|
||||
"connection setup succeeded".format(event)
|
||||
f"[pool {event.address}][conn #{event.connection_id}] connection setup succeeded"
|
||||
)
|
||||
|
||||
def connection_closed(self, event: monitoring.ConnectionClosedEvent) -> None:
|
||||
logging.info(
|
||||
"[pool {0.address}][conn #{0.connection_id}] "
|
||||
"connection closed, reason: "
|
||||
"{0.reason}".format(event)
|
||||
f"[pool {event.address}][conn #{event.connection_id}] "
|
||||
f'connection closed, reason: "{event.reason}"'
|
||||
)
|
||||
|
||||
def connection_check_out_started(
|
||||
self, event: monitoring.ConnectionCheckOutStartedEvent
|
||||
) -> None:
|
||||
logging.info("[pool {0.address}] connection check out " "started".format(event))
|
||||
logging.info(f"[pool {event.address}] connection check out started")
|
||||
|
||||
def connection_check_out_failed(self, event: monitoring.ConnectionCheckOutFailedEvent) -> None:
|
||||
logging.info(
|
||||
"[pool {0.address}] connection check out " "failed, reason: {0.reason}".format(event)
|
||||
)
|
||||
logging.info(f"[pool {event.address}] connection check out failed, reason: {event.reason}")
|
||||
|
||||
def connection_checked_out(self, event: monitoring.ConnectionCheckedOutEvent) -> None:
|
||||
logging.info(
|
||||
"[pool {0.address}][conn #{0.connection_id}] "
|
||||
"connection checked out of pool".format(event)
|
||||
f"[pool {event.address}][conn #{event.connection_id}] connection checked out of pool"
|
||||
)
|
||||
|
||||
def connection_checked_in(self, event: monitoring.ConnectionCheckedInEvent) -> None:
|
||||
logging.info(
|
||||
"[pool {0.address}][conn #{0.connection_id}] "
|
||||
"connection checked into pool".format(event)
|
||||
f"[pool {event.address}][conn #{event.connection_id}] connection checked into pool"
|
||||
)
|
||||
|
||||
@ -86,9 +86,7 @@ def _index_list(key_or_list, direction=None):
|
||||
if isinstance(key_or_list, abc.ItemsView):
|
||||
return list(key_or_list)
|
||||
elif not isinstance(key_or_list, (list, tuple)):
|
||||
raise TypeError(
|
||||
"if no direction is specified, " "key_or_list must be an instance of list"
|
||||
)
|
||||
raise TypeError("if no direction is specified, key_or_list must be an instance of list")
|
||||
return key_or_list
|
||||
|
||||
|
||||
@ -104,7 +102,7 @@ def _index_document(index_list):
|
||||
"mean %r?" % list(index_list.items())
|
||||
)
|
||||
elif not isinstance(index_list, (list, tuple)):
|
||||
raise TypeError("must use a list of (key, direction) pairs, " "not: " + repr(index_list))
|
||||
raise TypeError("must use a list of (key, direction) pairs, not: " + repr(index_list))
|
||||
if not len(index_list):
|
||||
raise ValueError("key_or_list must not be the empty list")
|
||||
|
||||
@ -237,11 +235,11 @@ def _fields_list_to_dict(fields, option_name):
|
||||
if isinstance(fields, (abc.Sequence, abc.Set)):
|
||||
if not all(isinstance(field, str) for field in fields):
|
||||
raise TypeError(
|
||||
"%s must be a list of key names, each an " "instance of str" % (option_name,)
|
||||
"%s must be a list of key names, each an instance of str" % (option_name,)
|
||||
)
|
||||
return dict.fromkeys(fields, 1)
|
||||
|
||||
raise TypeError("%s must be a mapping or " "list of key names" % (option_name,))
|
||||
raise TypeError("%s must be a mapping or list of key names" % (option_name,))
|
||||
|
||||
|
||||
def _handle_exception():
|
||||
|
||||
@ -638,7 +638,7 @@ def _op_msg_uncompressed(flags, command, identifier, docs, opts):
|
||||
|
||||
|
||||
if _use_c:
|
||||
_op_msg_uncompressed = _cmessage._op_msg
|
||||
_op_msg_uncompressed = _cmessage._op_msg # noqa: F811
|
||||
|
||||
|
||||
def _op_msg(flags, command, dbname, read_preference, opts, ctx=None):
|
||||
@ -712,7 +712,7 @@ def _query_uncompressed(
|
||||
|
||||
|
||||
if _use_c:
|
||||
_query_uncompressed = _cmessage._query_message
|
||||
_query_uncompressed = _cmessage._query_message # noqa: F811
|
||||
|
||||
|
||||
def _query(
|
||||
@ -754,7 +754,7 @@ def _get_more_uncompressed(collection_name, num_to_return, cursor_id):
|
||||
|
||||
|
||||
if _use_c:
|
||||
_get_more_uncompressed = _cmessage._get_more_message
|
||||
_get_more_uncompressed = _cmessage._get_more_message # noqa: F811
|
||||
|
||||
|
||||
def _get_more(collection_name, num_to_return, cursor_id, ctx=None):
|
||||
@ -1085,7 +1085,7 @@ def _encode_batched_op_msg(operation, command, docs, ack, opts, ctx):
|
||||
|
||||
|
||||
if _use_c:
|
||||
_encode_batched_op_msg = _cmessage._encode_batched_op_msg
|
||||
_encode_batched_op_msg = _cmessage._encode_batched_op_msg # noqa: F811
|
||||
|
||||
|
||||
def _batched_op_msg_compressed(operation, command, docs, ack, opts, ctx):
|
||||
@ -1120,7 +1120,7 @@ def _batched_op_msg(operation, command, docs, ack, opts, ctx):
|
||||
|
||||
|
||||
if _use_c:
|
||||
_batched_op_msg = _cmessage._batched_op_msg
|
||||
_batched_op_msg = _cmessage._batched_op_msg # noqa: F811
|
||||
|
||||
|
||||
def _do_batched_op_msg(namespace, operation, command, docs, opts, ctx):
|
||||
@ -1149,7 +1149,7 @@ def _encode_batched_write_command(namespace, operation, command, docs, opts, ctx
|
||||
|
||||
|
||||
if _use_c:
|
||||
_encode_batched_write_command = _cmessage._encode_batched_write_command
|
||||
_encode_batched_write_command = _cmessage._encode_batched_write_command # noqa: F811
|
||||
|
||||
|
||||
def _batched_write_command_impl(namespace, operation, command, docs, opts, ctx, buf):
|
||||
@ -1348,7 +1348,7 @@ class _OpMsg(object):
|
||||
self.flags = flags
|
||||
self.payload_document = payload_document
|
||||
|
||||
def raw_response(self, cursor_id=None, user_fields={}):
|
||||
def raw_response(self, cursor_id=None, user_fields={}): # noqa: B006
|
||||
"""
|
||||
cursor_id is ignored
|
||||
user_fields is used to determine which fields must not be decoded
|
||||
@ -1395,12 +1395,12 @@ class _OpMsg(object):
|
||||
flags, first_payload_type, first_payload_size = cls.UNPACK_FROM(msg)
|
||||
if flags != 0:
|
||||
if flags & cls.CHECKSUM_PRESENT:
|
||||
raise ProtocolError("Unsupported OP_MSG flag checksumPresent: " "0x%x" % (flags,))
|
||||
raise ProtocolError("Unsupported OP_MSG flag checksumPresent: 0x%x" % (flags,))
|
||||
|
||||
if flags ^ cls.MORE_TO_COME:
|
||||
raise ProtocolError("Unsupported OP_MSG flags: 0x%x" % (flags,))
|
||||
if first_payload_type != 0:
|
||||
raise ProtocolError("Unsupported OP_MSG payload type: " "0x%x" % (first_payload_type,))
|
||||
raise ProtocolError("Unsupported OP_MSG payload type: 0x%x" % (first_payload_type,))
|
||||
|
||||
if len(msg) != first_payload_size + 5:
|
||||
raise ProtocolError("Unsupported OP_MSG reply: >1 section")
|
||||
|
||||
@ -52,7 +52,6 @@ from typing import (
|
||||
cast,
|
||||
)
|
||||
|
||||
import bson
|
||||
from bson.codec_options import DEFAULT_CODEC_OPTIONS, CodecOptions, TypeRegistry
|
||||
from bson.son import SON
|
||||
from bson.timestamp import Timestamp
|
||||
@ -687,7 +686,7 @@ class MongoClient(common.BaseObject, Generic[_DocumentType]):
|
||||
srv_service_name = keyword_opts.get("srvservicename")
|
||||
srv_max_hosts = keyword_opts.get("srvmaxhosts")
|
||||
if len([h for h in host if "/" in h]) > 1:
|
||||
raise ConfigurationError("host must not contain multiple MongoDB " "URIs")
|
||||
raise ConfigurationError("host must not contain multiple MongoDB URIs")
|
||||
for entity in host:
|
||||
# A hostname can only include a-z, 0-9, '-' and '.'. If we find a '/'
|
||||
# it must be a URI,
|
||||
@ -1165,7 +1164,7 @@ class MongoClient(common.BaseObject, Generic[_DocumentType]):
|
||||
and sock_info.max_wire_version < 8
|
||||
):
|
||||
raise ConfigurationError(
|
||||
"Auto-encryption requires a minimum MongoDB version " "of 4.2"
|
||||
"Auto-encryption requires a minimum MongoDB version of 4.2"
|
||||
)
|
||||
yield sock_info
|
||||
|
||||
@ -1229,7 +1228,7 @@ class MongoClient(common.BaseObject, Generic[_DocumentType]):
|
||||
|
||||
def _socket_for_reads(self, read_preference, session):
|
||||
assert read_preference is not None, "read_preference must not be None"
|
||||
topology = self._get_topology()
|
||||
_ = self._get_topology()
|
||||
server = self._select_server(read_preference, session)
|
||||
return self._socket_from_server(read_preference, server, session)
|
||||
|
||||
@ -1814,7 +1813,7 @@ class MongoClient(common.BaseObject, Generic[_DocumentType]):
|
||||
name = name.name
|
||||
|
||||
if not isinstance(name, str):
|
||||
raise TypeError("name_or_database must be an instance " "of str or a Database")
|
||||
raise TypeError("name_or_database must be an instance of str or a Database")
|
||||
|
||||
with self._socket_for_writes(session) as sock_info:
|
||||
self[name]._command(
|
||||
|
||||
@ -633,7 +633,7 @@ class CommandStartedEvent(_CommandEvent):
|
||||
super(CommandStartedEvent, self).__init__(
|
||||
command_name, request_id, connection_id, operation_id, service_id=service_id
|
||||
)
|
||||
cmd_name, cmd_doc = command_name.lower(), command[command_name]
|
||||
cmd_name = command_name.lower()
|
||||
if cmd_name in _SENSITIVE_COMMANDS or _is_speculative_authenticate(cmd_name, command):
|
||||
self.__cmd: Mapping[str, Any] = {}
|
||||
else:
|
||||
@ -651,7 +651,7 @@ class CommandStartedEvent(_CommandEvent):
|
||||
return self.__db
|
||||
|
||||
def __repr__(self):
|
||||
return ("<%s %s db: %r, command: %r, operation_id: %s, " "service_id: %s>") % (
|
||||
return ("<%s %s db: %r, command: %r, operation_id: %s, service_id: %s>") % (
|
||||
self.__class__.__name__,
|
||||
self.connection_id,
|
||||
self.database_name,
|
||||
@ -708,7 +708,7 @@ class CommandSucceededEvent(_CommandEvent):
|
||||
return self.__reply
|
||||
|
||||
def __repr__(self):
|
||||
return ("<%s %s command: %r, operation_id: %s, duration_micros: %s, " "service_id: %s>") % (
|
||||
return ("<%s %s command: %r, operation_id: %s, duration_micros: %s, service_id: %s>") % (
|
||||
self.__class__.__name__,
|
||||
self.connection_id,
|
||||
self.command_name,
|
||||
|
||||
@ -210,10 +210,10 @@ def receive_message(sock_info, request_id, max_message_size=MAX_MESSAGE_SIZE):
|
||||
# No request_id for exhaust cursor "getMore".
|
||||
if request_id is not None:
|
||||
if request_id != response_to:
|
||||
raise ProtocolError("Got response id %r but expected " "%r" % (response_to, request_id))
|
||||
raise ProtocolError("Got response id %r but expected %r" % (response_to, request_id))
|
||||
if length <= 16:
|
||||
raise ProtocolError(
|
||||
"Message length (%r) not longer than standard " "message header size (16)" % (length,)
|
||||
"Message length (%r) not longer than standard message header size (16)" % (length,)
|
||||
)
|
||||
if length > max_message_size:
|
||||
raise ProtocolError(
|
||||
@ -231,7 +231,7 @@ def receive_message(sock_info, request_id, max_message_size=MAX_MESSAGE_SIZE):
|
||||
try:
|
||||
unpack_reply = _UNPACK_REPLY[op_code]
|
||||
except KeyError:
|
||||
raise ProtocolError("Got opcode %r but expected " "%r" % (op_code, _UNPACK_REPLY.keys()))
|
||||
raise ProtocolError("Got opcode %r but expected %r" % (op_code, _UNPACK_REPLY.keys()))
|
||||
return unpack_reply(data)
|
||||
|
||||
|
||||
@ -272,7 +272,7 @@ def _receive_data_on_socket(sock_info, length, deadline):
|
||||
try:
|
||||
wait_for_read(sock_info, deadline)
|
||||
chunk_length = sock_info.sock.recv_into(mv[bytes_read:])
|
||||
except (IOError, OSError) as exc:
|
||||
except (IOError, OSError) as exc: # noqa: B014
|
||||
if _errno_from_exception(exc) == errno.EINTR:
|
||||
continue
|
||||
raise
|
||||
|
||||
@ -124,7 +124,7 @@ class PeriodicExecutor(object):
|
||||
if not self._target():
|
||||
self._stopped = True
|
||||
break
|
||||
except:
|
||||
except BaseException:
|
||||
with self._lock:
|
||||
self._stopped = True
|
||||
self._thread_will_exit = True
|
||||
|
||||
@ -72,7 +72,7 @@ def is_ip_address(address):
|
||||
try:
|
||||
ipaddress.ip_address(address)
|
||||
return True
|
||||
except (ValueError, UnicodeError):
|
||||
except (ValueError, UnicodeError): # noqa: B014
|
||||
return False
|
||||
|
||||
|
||||
@ -857,9 +857,7 @@ class SocketInfo(object):
|
||||
"""
|
||||
if session:
|
||||
if session._client is not client:
|
||||
raise InvalidOperation(
|
||||
"Can only use session with the MongoClient that" " started it"
|
||||
)
|
||||
raise InvalidOperation("Can only use session with the MongoClient that started it")
|
||||
|
||||
def close_socket(self, reason):
|
||||
"""Close this connection with a reason."""
|
||||
@ -963,7 +961,7 @@ def _create_connection(address, options):
|
||||
# Check if dealing with a unix domain socket
|
||||
if host.endswith(".sock"):
|
||||
if not hasattr(socket, "AF_UNIX"):
|
||||
raise ConnectionFailure("UNIX-sockets are not supported " "on this system")
|
||||
raise ConnectionFailure("UNIX-sockets are not supported on this system")
|
||||
sock = socket.socket(socket.AF_UNIX)
|
||||
# SOCK_CLOEXEC not supported for Unix sockets.
|
||||
_set_non_inheritable_non_atomic(sock.fileno())
|
||||
@ -1045,7 +1043,7 @@ def _configured_socket(address, options):
|
||||
# Raise _CertificateError directly like we do after match_hostname
|
||||
# below.
|
||||
raise
|
||||
except (IOError, OSError, _SSLError) as exc:
|
||||
except (IOError, OSError, _SSLError) as exc: # noqa: B014
|
||||
sock.close()
|
||||
# We raise AutoReconnect for transient and permanent SSL handshake
|
||||
# failures alike. Permanent handshake failures, like protocol
|
||||
@ -1246,8 +1244,8 @@ class Pool:
|
||||
"""
|
||||
self.is_writable = is_writable
|
||||
with self.lock:
|
||||
for socket in self.sockets:
|
||||
socket.update_is_writable(self.is_writable)
|
||||
for _socket in self.sockets:
|
||||
_socket.update_is_writable(self.is_writable)
|
||||
|
||||
def reset(self, service_id=None):
|
||||
self._reset(close=False, service_id=service_id)
|
||||
@ -1386,7 +1384,7 @@ class Pool:
|
||||
listeners.publish_connection_checked_out(self.address, sock_info.id)
|
||||
try:
|
||||
yield sock_info
|
||||
except:
|
||||
except BaseException:
|
||||
# Exception in caller. Ensure the connection gets returned.
|
||||
# Note that when pinned is True, the session owns the
|
||||
# connection and it is responsible for checking the connection
|
||||
@ -1433,7 +1431,7 @@ class Pool:
|
||||
self.address, ConnectionCheckOutFailedReason.POOL_CLOSED
|
||||
)
|
||||
raise _PoolClosedError(
|
||||
"Attempted to check out a connection from closed connection " "pool"
|
||||
"Attempted to check out a connection from closed connection pool"
|
||||
)
|
||||
|
||||
with self.lock:
|
||||
|
||||
@ -75,7 +75,7 @@ def _is_ip_address(address):
|
||||
try:
|
||||
_ip_address(address)
|
||||
return True
|
||||
except (ValueError, UnicodeError):
|
||||
except (ValueError, UnicodeError): # noqa: B014
|
||||
return False
|
||||
|
||||
|
||||
@ -145,7 +145,7 @@ class _sslConn(_SSL.Connection):
|
||||
# XXX: It's not clear if this can actually happen. PyOpenSSL
|
||||
# doesn't appear to have any interrupt handling, nor any interrupt
|
||||
# errors for OpenSSL connections.
|
||||
except (IOError, OSError) as exc:
|
||||
except (IOError, OSError) as exc: # noqa: B014
|
||||
if _errno_from_exception(exc) == _EINTR:
|
||||
continue
|
||||
raise
|
||||
|
||||
@ -49,8 +49,7 @@ def _validate_tag_sets(tag_sets):
|
||||
raise TypeError(("Tag sets %r invalid, must be a sequence") % (tag_sets,))
|
||||
if len(tag_sets) == 0:
|
||||
raise ValueError(
|
||||
("Tag sets %r invalid, must be None or contain at least one set of" " tags")
|
||||
% (tag_sets,)
|
||||
("Tag sets %r invalid, must be None or contain at least one set of tags") % (tag_sets,)
|
||||
)
|
||||
|
||||
for tags in tag_sets:
|
||||
@ -500,10 +499,10 @@ def make_read_preference(
|
||||
) -> _ServerMode:
|
||||
if mode == _PRIMARY:
|
||||
if tag_sets not in (None, [{}]):
|
||||
raise ConfigurationError("Read preference primary " "cannot be combined with tags")
|
||||
raise ConfigurationError("Read preference primary cannot be combined with tags")
|
||||
if max_staleness != -1:
|
||||
raise ConfigurationError(
|
||||
"Read preference primary cannot be " "combined with maxStalenessSeconds"
|
||||
"Read preference primary cannot be combined with maxStalenessSeconds"
|
||||
)
|
||||
return Primary()
|
||||
return _ALL_READ_PREFERENCES[mode](tag_sets, max_staleness) # type: ignore
|
||||
|
||||
@ -13,7 +13,7 @@
|
||||
# limitations under the License.
|
||||
|
||||
"""Result class definitions."""
|
||||
from typing import Any, Dict, List, Mapping, Optional, Sequence, cast
|
||||
from typing import Any, Dict, List, Optional, cast
|
||||
|
||||
from pymongo.errors import InvalidOperation
|
||||
|
||||
|
||||
@ -21,7 +21,6 @@ from pymongo.errors import NotPrimaryError, OperationFailure
|
||||
from pymongo.helpers import _check_command_response
|
||||
from pymongo.message import _convert_exception, _OpMsg
|
||||
from pymongo.response import PinnedResponse, Response
|
||||
from pymongo.server_type import SERVER_TYPE
|
||||
|
||||
_CURSOR_DOC_FIELDS = {"cursor": {"firstBatch": 1, "nextBatch": 1}}
|
||||
|
||||
|
||||
@ -15,7 +15,7 @@
|
||||
"""Represent one server the driver is connected to."""
|
||||
|
||||
import time
|
||||
from typing import Any, Dict, Mapping, Optional, Set, Tuple, cast
|
||||
from typing import Any, Dict, Mapping, Optional, Set, Tuple
|
||||
|
||||
from bson import EPOCH_NAIVE
|
||||
from bson.objectid import ObjectId
|
||||
|
||||
@ -17,7 +17,7 @@
|
||||
import errno
|
||||
import select
|
||||
import sys
|
||||
from typing import Any, Optional, Union
|
||||
from typing import Any, Optional
|
||||
|
||||
# PYTHON-2320: Jython does not fully support poll on SSL sockets,
|
||||
# https://bugs.jython.org/issue2900
|
||||
|
||||
@ -31,10 +31,10 @@ IS_PYOPENSSL = False
|
||||
# Base Exception class
|
||||
SSLError = _ssl.SSLError
|
||||
|
||||
from ssl import SSLContext
|
||||
from ssl import SSLContext # noqa: F401,E402
|
||||
|
||||
if hasattr(_ssl, "VERIFY_CRL_CHECK_LEAF"):
|
||||
from ssl import VERIFY_CRL_CHECK_LEAF
|
||||
from ssl import VERIFY_CRL_CHECK_LEAF # noqa: F401
|
||||
# Python 3.7 uses OpenSSL's hostname matching implementation
|
||||
# making it the obvious version to start using SSLConext.check_hostname.
|
||||
# Python 3.6 might have been a good version, but it suffers
|
||||
|
||||
@ -34,7 +34,7 @@ if HAVE_SSL:
|
||||
# CPython ssl module constants to configure certificate verification
|
||||
# at a high level. This is legacy behavior, but requires us to
|
||||
# import the ssl module even if we're only using it for this purpose.
|
||||
import ssl as _stdlibssl
|
||||
import ssl as _stdlibssl # noqa
|
||||
from ssl import CERT_NONE, CERT_REQUIRED
|
||||
|
||||
HAS_SNI = _ssl.HAS_SNI
|
||||
@ -79,7 +79,7 @@ if HAVE_SSL:
|
||||
if _ssl.IS_PYOPENSSL:
|
||||
raise ConfigurationError("tlsCRLFile cannot be used with PyOpenSSL")
|
||||
# Match the server's behavior.
|
||||
setattr(ctx, "verify_flags", getattr(_ssl, "VERIFY_CRL_CHECK_LEAF", 0))
|
||||
setattr(ctx, "verify_flags", getattr(_ssl, "VERIFY_CRL_CHECK_LEAF", 0)) # noqa
|
||||
ctx.load_verify_locations(crlfile)
|
||||
if ca_certs is not None:
|
||||
ctx.load_verify_locations(ca_certs)
|
||||
|
||||
@ -17,13 +17,11 @@ from typing import (
|
||||
TYPE_CHECKING,
|
||||
Any,
|
||||
Dict,
|
||||
List,
|
||||
Mapping,
|
||||
MutableMapping,
|
||||
Optional,
|
||||
Sequence,
|
||||
Tuple,
|
||||
Type,
|
||||
TypeVar,
|
||||
Union,
|
||||
)
|
||||
|
||||
@ -15,19 +15,8 @@
|
||||
|
||||
"""Tools to parse and validate a MongoDB URI."""
|
||||
import re
|
||||
import sys
|
||||
import warnings
|
||||
from typing import (
|
||||
Any,
|
||||
Dict,
|
||||
List,
|
||||
Mapping,
|
||||
MutableMapping,
|
||||
Optional,
|
||||
Tuple,
|
||||
Union,
|
||||
cast,
|
||||
)
|
||||
from typing import Any, Dict, List, Mapping, MutableMapping, Optional, Tuple, Union
|
||||
from urllib.parse import unquote_plus
|
||||
|
||||
from pymongo.client_options import _parse_ssl_options
|
||||
@ -107,7 +96,7 @@ def parse_ipv6_literal_host(
|
||||
"""
|
||||
if entity.find("]") == -1:
|
||||
raise ValueError(
|
||||
"an IPv6 address literal must be " "enclosed in '[' and ']' according " "to RFC 2732."
|
||||
"an IPv6 address literal must be enclosed in '[' and ']' according to RFC 2732."
|
||||
)
|
||||
i = entity.find("]:")
|
||||
if i == -1:
|
||||
@ -196,7 +185,7 @@ def _handle_security_options(options):
|
||||
if tlsinsecure is not None:
|
||||
for opt in _IMPLICIT_TLSINSECURE_OPTS:
|
||||
if opt in options:
|
||||
err_msg = "URI options %s and %s cannot be specified " "simultaneously."
|
||||
err_msg = "URI options %s and %s cannot be specified simultaneously."
|
||||
raise InvalidURI(
|
||||
err_msg % (options.cased_key("tlsinsecure"), options.cased_key(opt))
|
||||
)
|
||||
@ -205,7 +194,7 @@ def _handle_security_options(options):
|
||||
tlsallowinvalidcerts = options.get("tlsallowinvalidcertificates")
|
||||
if tlsallowinvalidcerts is not None:
|
||||
if "tlsdisableocspendpointcheck" in options:
|
||||
err_msg = "URI options %s and %s cannot be specified " "simultaneously."
|
||||
err_msg = "URI options %s and %s cannot be specified simultaneously."
|
||||
raise InvalidURI(
|
||||
err_msg
|
||||
% ("tlsallowinvalidcertificates", options.cased_key("tlsdisableocspendpointcheck"))
|
||||
@ -218,7 +207,7 @@ def _handle_security_options(options):
|
||||
if tlscrlfile is not None:
|
||||
for opt in ("tlsinsecure", "tlsallowinvalidcertificates", "tlsdisableocspendpointcheck"):
|
||||
if options.get(opt) is True:
|
||||
err_msg = "URI option %s=True cannot be specified when " "CRL checking is enabled."
|
||||
err_msg = "URI option %s=True cannot be specified when CRL checking is enabled."
|
||||
raise InvalidURI(err_msg % (opt,))
|
||||
|
||||
if "ssl" in options and "tls" in options:
|
||||
@ -231,7 +220,7 @@ def _handle_security_options(options):
|
||||
return val
|
||||
|
||||
if truth_value(options.get("ssl")) != truth_value(options.get("tls")):
|
||||
err_msg = "Can not specify conflicting values for URI options %s " "and %s."
|
||||
err_msg = "Can not specify conflicting values for URI options %s and %s."
|
||||
raise InvalidURI(err_msg % (options.cased_key("ssl"), options.cased_key("tls")))
|
||||
|
||||
return options
|
||||
@ -252,7 +241,7 @@ def _handle_option_deprecations(options):
|
||||
if mode == "renamed":
|
||||
newoptname = message
|
||||
if newoptname in options:
|
||||
warn_msg = "Deprecated option '%s' ignored in favor of " "'%s'."
|
||||
warn_msg = "Deprecated option '%s' ignored in favor of '%s'."
|
||||
warnings.warn(
|
||||
warn_msg % (options.cased_key(optname), options.cased_key(newoptname)),
|
||||
DeprecationWarning,
|
||||
@ -378,7 +367,7 @@ def split_hosts(hosts: str, default_port: Optional[int] = DEFAULT_PORT) -> List[
|
||||
nodes = []
|
||||
for entity in hosts.split(","):
|
||||
if not entity:
|
||||
raise ConfigurationError("Empty host " "(or extra comma in host list).")
|
||||
raise ConfigurationError("Empty host (or extra comma in host list).")
|
||||
port = default_port
|
||||
# Unix socket entities don't have ports
|
||||
if entity.endswith(".sock"):
|
||||
@ -486,7 +475,7 @@ def parse_uri(
|
||||
scheme_free = uri[SRV_SCHEME_LEN:]
|
||||
else:
|
||||
raise InvalidURI(
|
||||
"Invalid URI scheme: URI must " "begin with '%s' or '%s'" % (SCHEME, SRV_SCHEME)
|
||||
"Invalid URI scheme: URI must begin with '%s' or '%s'" % (SCHEME, SRV_SCHEME)
|
||||
)
|
||||
|
||||
if not scheme_free:
|
||||
@ -504,7 +493,7 @@ def parse_uri(
|
||||
path_part = ""
|
||||
|
||||
if not path_part and "?" in host_part:
|
||||
raise InvalidURI("A '/' is required between " "the host list and any options.")
|
||||
raise InvalidURI("A '/' is required between the host list and any options.")
|
||||
|
||||
if path_part:
|
||||
dbase, _, opts = path_part.partition("?")
|
||||
@ -528,9 +517,7 @@ def parse_uri(
|
||||
hosts = host_part
|
||||
|
||||
if "/" in hosts:
|
||||
raise InvalidURI(
|
||||
"Any '/' in a unix domain socket must be" " percent-encoded: %s" % host_part
|
||||
)
|
||||
raise InvalidURI("Any '/' in a unix domain socket must be percent-encoded: %s" % host_part)
|
||||
|
||||
hosts = unquote_plus(hosts)
|
||||
fqdn = None
|
||||
@ -538,11 +525,11 @@ def parse_uri(
|
||||
if is_srv:
|
||||
if options.get("directConnection"):
|
||||
raise ConfigurationError(
|
||||
"Cannot specify directConnection=true with " "%s URIs" % (SRV_SCHEME,)
|
||||
"Cannot specify directConnection=true with %s URIs" % (SRV_SCHEME,)
|
||||
)
|
||||
nodes = split_hosts(hosts, default_port=None)
|
||||
if len(nodes) != 1:
|
||||
raise InvalidURI("%s URIs must include one, " "and only one, hostname" % (SRV_SCHEME,))
|
||||
raise InvalidURI("%s URIs must include one, and only one, hostname" % (SRV_SCHEME,))
|
||||
fqdn, port = nodes[0]
|
||||
if port is not None:
|
||||
raise InvalidURI("%s URIs must not include a port number" % (SRV_SCHEME,))
|
||||
@ -557,7 +544,7 @@ def parse_uri(
|
||||
parsed_dns_options = split_options(dns_options, validate, warn, normalize)
|
||||
if set(parsed_dns_options) - _ALLOWED_TXT_OPTS:
|
||||
raise ConfigurationError(
|
||||
"Only authSource, replicaSet, and loadBalanced are " "supported from DNS"
|
||||
"Only authSource, replicaSet, and loadBalanced are supported from DNS"
|
||||
)
|
||||
for opt, val in parsed_dns_options.items():
|
||||
if opt not in options:
|
||||
@ -570,11 +557,11 @@ def parse_uri(
|
||||
options["tls"] = True if validate else "true"
|
||||
elif not is_srv and options.get("srvServiceName") is not None:
|
||||
raise ConfigurationError(
|
||||
"The srvServiceName option is only allowed " "with 'mongodb+srv://' URIs"
|
||||
"The srvServiceName option is only allowed with 'mongodb+srv://' URIs"
|
||||
)
|
||||
elif not is_srv and srv_max_hosts:
|
||||
raise ConfigurationError(
|
||||
"The srvMaxHosts option is only allowed " "with 'mongodb+srv://' URIs"
|
||||
"The srvMaxHosts option is only allowed with 'mongodb+srv://' URIs"
|
||||
)
|
||||
else:
|
||||
nodes = split_hosts(hosts, default_port=default_port)
|
||||
|
||||
@ -73,7 +73,7 @@ class WriteConcern(object):
|
||||
if not isinstance(fsync, bool):
|
||||
raise TypeError("fsync must be True or False")
|
||||
if j and fsync:
|
||||
raise ConfigurationError("Can't set both j " "and fsync at the same time")
|
||||
raise ConfigurationError("Can't set both j and fsync at the same time")
|
||||
self.__document["fsync"] = fsync
|
||||
|
||||
if w == 0 and j is True:
|
||||
|
||||
15
setup.py
15
setup.py
@ -10,11 +10,10 @@ if sys.version_info[:2] < (3, 6):
|
||||
|
||||
# Hack to silence atexit traceback in some Python versions
|
||||
try:
|
||||
import multiprocessing
|
||||
import multiprocessing # noqa: F401
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
from setuptools import __version__ as _setuptools_version
|
||||
from setuptools import setup
|
||||
|
||||
if sys.version_info[:2] < (3, 10):
|
||||
@ -41,7 +40,7 @@ f = open("README.rst")
|
||||
try:
|
||||
try:
|
||||
readme_content = f.read()
|
||||
except:
|
||||
except BaseException:
|
||||
readme_content = ""
|
||||
finally:
|
||||
f.close()
|
||||
@ -152,7 +151,7 @@ class doc(Command):
|
||||
|
||||
try:
|
||||
os.makedirs(path)
|
||||
except:
|
||||
except BaseException:
|
||||
pass
|
||||
|
||||
sphinx_args = ["-E", "-b", mode, "doc", path]
|
||||
@ -169,7 +168,7 @@ class doc(Command):
|
||||
raise RuntimeError("documentation step '%s' failed" % (mode,))
|
||||
|
||||
sys.stdout.write(
|
||||
"\nDocumentation step '%s' performed, results here:\n" " %s/\n" % (mode, path)
|
||||
"\nDocumentation step '%s' performed, results here:\n %s/\n" % (mode, path)
|
||||
)
|
||||
|
||||
|
||||
@ -232,7 +231,7 @@ https://pymongo.readthedocs.io/en/stable/installation.html#osx
|
||||
self.warning_message
|
||||
% (
|
||||
"Extension modules",
|
||||
"There was an issue with " "your platform configuration" " - see above.",
|
||||
"There was an issue with your platform configuration - see above.",
|
||||
)
|
||||
)
|
||||
|
||||
@ -246,8 +245,8 @@ https://pymongo.readthedocs.io/en/stable/installation.html#osx
|
||||
warnings.warn(
|
||||
self.warning_message
|
||||
% (
|
||||
"The %s extension " "module" % (name,),
|
||||
"The output above " "this warning shows how " "the compilation " "failed.",
|
||||
"The %s extension module" % (name,),
|
||||
"The output above this warning shows how the compilation failed.",
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
@ -20,7 +20,6 @@ import os
|
||||
import socket
|
||||
import sys
|
||||
import threading
|
||||
import time
|
||||
import traceback
|
||||
import unittest
|
||||
import warnings
|
||||
@ -34,7 +33,7 @@ except (ImportError, ValueError):
|
||||
HAVE_XML = False
|
||||
|
||||
try:
|
||||
import ipaddress
|
||||
import ipaddress # noqa
|
||||
|
||||
HAVE_IPADDRESS = True
|
||||
except ImportError:
|
||||
@ -667,7 +666,7 @@ class ClientContext(object):
|
||||
"""
|
||||
return self._require(
|
||||
lambda: self.supports_secondary_read_pref,
|
||||
"This cluster does not support secondary read " "preference",
|
||||
"This cluster does not support secondary read preference",
|
||||
)
|
||||
|
||||
def require_no_replica_set(self, func):
|
||||
@ -757,7 +756,7 @@ class ClientContext(object):
|
||||
return True
|
||||
return False
|
||||
|
||||
def require_cluster_type(self, topologies=[]):
|
||||
def require_cluster_type(self, topologies=[]): # noqa
|
||||
"""Run a test only if the client is connected to a cluster that
|
||||
conforms to one of the specified topologies. Acceptable topologies
|
||||
are 'single', 'replicaset', and 'sharded'."""
|
||||
@ -825,7 +824,7 @@ class ClientContext(object):
|
||||
"""Run a test only if the hostname 'server' is resolvable."""
|
||||
return self._require(
|
||||
lambda: self.server_is_resolvable,
|
||||
"No hosts entry for 'server'. Cannot validate " "hostname in the certificate",
|
||||
"No hosts entry for 'server'. Cannot validate hostname in the certificate",
|
||||
func=func,
|
||||
)
|
||||
|
||||
@ -1125,9 +1124,9 @@ def test_cases(suite):
|
||||
# Helper method to workaround https://bugs.python.org/issue21724
|
||||
def clear_warning_registry():
|
||||
"""Clear the __warningregistry__ for all modules."""
|
||||
for name, module in list(sys.modules.items()):
|
||||
for _, module in list(sys.modules.items()):
|
||||
if hasattr(module, "__warningregistry__"):
|
||||
setattr(module, "__warningregistry__", {})
|
||||
setattr(module, "__warningregistry__", {}) # noqa
|
||||
|
||||
|
||||
class SystemCertsPatcher(object):
|
||||
|
||||
@ -25,7 +25,7 @@ import pymongo
|
||||
from pymongo.ssl_support import HAS_SNI
|
||||
|
||||
try:
|
||||
import dns
|
||||
import dns # noqa
|
||||
|
||||
HAS_DNS = True
|
||||
except ImportError:
|
||||
@ -120,7 +120,7 @@ class TestAtlasConnect(unittest.TestCase):
|
||||
duplicates = [names for names in uri_to_names.values() if len(names) > 1]
|
||||
self.assertFalse(
|
||||
duplicates,
|
||||
"Error: the following env variables have " "duplicate values: %s" % (duplicates,),
|
||||
"Error: the following env variables have duplicate values: %s" % (duplicates,),
|
||||
)
|
||||
|
||||
|
||||
|
||||
@ -28,7 +28,7 @@ class TestClusterTime(unittest.TestCase):
|
||||
server = MockupDB()
|
||||
|
||||
# First test all commands include $clusterTime with wire version 6.
|
||||
responder = server.autoresponds(
|
||||
_ = server.autoresponds(
|
||||
"ismaster",
|
||||
{
|
||||
"minWireVersion": 0,
|
||||
|
||||
@ -33,7 +33,7 @@ def test_hello_with_option(self, protocol, **kwargs):
|
||||
|
||||
def respond(r):
|
||||
# Only save the very first request from the driver.
|
||||
if self.handshake_req == None:
|
||||
if self.handshake_req is None:
|
||||
self.handshake_req = r
|
||||
load_balanced_kwargs = {"serviceId": ObjectId()} if kwargs.get("loadBalanced") else {}
|
||||
return r.reply(
|
||||
@ -261,7 +261,7 @@ class TestHandshake(unittest.TestCase):
|
||||
self.addCleanup(client.close)
|
||||
self.assertRaises(OperationFailure, client.db.collection.find_one, {"a": 1})
|
||||
self.assertTrue(
|
||||
self.found_auth_msg, "Could not find authentication " "command with correct protocol"
|
||||
self.found_auth_msg, "Could not find authentication command with correct protocol"
|
||||
)
|
||||
|
||||
|
||||
|
||||
@ -16,7 +16,7 @@
|
||||
|
||||
import unittest
|
||||
|
||||
from mockupdb import MockupDB, OpGetMore, going
|
||||
from mockupdb import MockupDB, going
|
||||
|
||||
from bson import SON
|
||||
from pymongo import MongoClient
|
||||
|
||||
@ -18,7 +18,7 @@ import time
|
||||
import unittest
|
||||
from queue import Queue
|
||||
|
||||
from mockupdb import MockupDB, OpMsg, go
|
||||
from mockupdb import MockupDB, go
|
||||
from operations import upgrades
|
||||
|
||||
from pymongo import MongoClient
|
||||
|
||||
@ -15,10 +15,9 @@
|
||||
import itertools
|
||||
import unittest
|
||||
|
||||
from mockupdb import MockupDB, OpMsg, go, going
|
||||
from mockupdb import MockupDB, OpMsg, going
|
||||
from operations import operations
|
||||
|
||||
from bson import SON
|
||||
from pymongo import MongoClient, ReadPreference
|
||||
from pymongo.read_preferences import (
|
||||
_MONGOS_MODES,
|
||||
|
||||
@ -13,7 +13,6 @@
|
||||
# limitations under the License.
|
||||
|
||||
import unittest
|
||||
from queue import Queue
|
||||
|
||||
from mockupdb import Future, MockupDB, OpReply, going, wait_until
|
||||
|
||||
|
||||
@ -48,15 +48,9 @@ def create_slave_ok_single_test(mode, server_type, ismaster, operation):
|
||||
ismaster_with_version["minWireVersion"] = 2
|
||||
ismaster_with_version["maxWireVersion"] = 6
|
||||
self.server.autoresponds("ismaster", **ismaster_with_version)
|
||||
if operation.op_type == "always-use-secondary":
|
||||
slave_ok = True
|
||||
elif operation.op_type == "may-use-secondary":
|
||||
slave_ok = mode != "primary" or server_type != "mongos"
|
||||
elif operation.op_type == "must-use-primary":
|
||||
slave_ok = server_type != "mongos"
|
||||
else:
|
||||
assert False, "unrecognized op_type %r" % operation.op_type
|
||||
|
||||
self.assertIn(
|
||||
operation.op_type, ("always-use-secondary", "may-use-secondary", "must-use-primary")
|
||||
)
|
||||
pref = make_read_preference(read_pref_mode_from_name(mode), tag_sets=None)
|
||||
|
||||
client = MongoClient(self.server.uri, read_preference=pref)
|
||||
|
||||
@ -25,7 +25,7 @@ repository_path = os.path.normpath(os.path.join(this_path, '..', '..'))
|
||||
sys.path.insert(0, repository_path)
|
||||
|
||||
import pymongo
|
||||
from pymongo.hello import HelloCompat
|
||||
from pymongo.hello import HelloCompat # noqa
|
||||
from pymongo.mongo_client import MongoClient
|
||||
|
||||
client = MongoClient()
|
||||
@ -33,7 +33,7 @@ collection = client.test.test
|
||||
ndocs = 20
|
||||
collection.drop()
|
||||
collection.insert_many([{'i': i} for i in range(ndocs)])
|
||||
client.close() # Discard main thread's request socket.
|
||||
client.close() # Discard main thread's request socket.
|
||||
client = MongoClient()
|
||||
collection = client.test.test
|
||||
|
||||
|
||||
@ -40,7 +40,7 @@ else:
|
||||
|
||||
|
||||
def _connect(options):
|
||||
uri = ("mongodb://localhost:27017/?serverSelectionTimeoutMS=%s" "&tlsCAFile=%s&%s") % (
|
||||
uri = ("mongodb://localhost:27017/?serverSelectionTimeoutMS=%s&tlsCAFile=%s&%s") % (
|
||||
TIMEOUT_MS,
|
||||
CA_FILE,
|
||||
options,
|
||||
|
||||
@ -21,11 +21,10 @@ from urllib.parse import quote_plus
|
||||
|
||||
sys.path[0:0] = [""]
|
||||
|
||||
from test import IntegrationTest, SkipTest, Version, client_context, unittest
|
||||
from test import IntegrationTest, SkipTest, client_context, unittest
|
||||
from test.utils import (
|
||||
AllowListEventListener,
|
||||
delay,
|
||||
get_pool,
|
||||
ignore_deprecations,
|
||||
rs_or_single_client,
|
||||
rs_or_single_client_noauth,
|
||||
@ -119,14 +118,14 @@ class TestGSSAPI(unittest.TestCase):
|
||||
def test_gssapi_simple(self):
|
||||
assert GSSAPI_PRINCIPAL is not None
|
||||
if GSSAPI_PASS is not None:
|
||||
uri = "mongodb://%s:%s@%s:%d/?authMechanism=" "GSSAPI" % (
|
||||
uri = "mongodb://%s:%s@%s:%d/?authMechanism=GSSAPI" % (
|
||||
quote_plus(GSSAPI_PRINCIPAL),
|
||||
GSSAPI_PASS,
|
||||
GSSAPI_HOST,
|
||||
GSSAPI_PORT,
|
||||
)
|
||||
else:
|
||||
uri = "mongodb://%s@%s:%d/?authMechanism=" "GSSAPI" % (
|
||||
uri = "mongodb://%s@%s:%d/?authMechanism=GSSAPI" % (
|
||||
quote_plus(GSSAPI_PRINCIPAL),
|
||||
GSSAPI_HOST,
|
||||
GSSAPI_PORT,
|
||||
@ -266,7 +265,7 @@ class TestSASLPlain(unittest.TestCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
if not SASL_HOST or not SASL_USER or not SASL_PASS:
|
||||
raise SkipTest("Must set SASL_HOST, " "SASL_USER, and SASL_PASS to test SASL")
|
||||
raise SkipTest("Must set SASL_HOST, SASL_USER, and SASL_PASS to test SASL")
|
||||
|
||||
def test_sasl_plain(self):
|
||||
|
||||
@ -282,7 +281,7 @@ class TestSASLPlain(unittest.TestCase):
|
||||
|
||||
assert SASL_USER is not None
|
||||
assert SASL_PASS is not None
|
||||
uri = "mongodb://%s:%s@%s:%d/?authMechanism=PLAIN;" "authSource=%s" % (
|
||||
uri = "mongodb://%s:%s@%s:%d/?authMechanism=PLAIN;authSource=%s" % (
|
||||
quote_plus(SASL_USER),
|
||||
quote_plus(SASL_PASS),
|
||||
SASL_HOST,
|
||||
@ -305,7 +304,7 @@ class TestSASLPlain(unittest.TestCase):
|
||||
)
|
||||
client.ldap.test.find_one()
|
||||
|
||||
uri = "mongodb://%s:%s@%s:%d/?authMechanism=PLAIN;" "authSource=%s;replicaSet=%s" % (
|
||||
uri = "mongodb://%s:%s@%s:%d/?authMechanism=PLAIN;authSource=%s;replicaSet=%s" % (
|
||||
quote_plus(SASL_USER),
|
||||
quote_plus(SASL_PASS),
|
||||
SASL_HOST,
|
||||
@ -318,7 +317,7 @@ class TestSASLPlain(unittest.TestCase):
|
||||
|
||||
def test_sasl_plain_bad_credentials(self):
|
||||
def auth_string(user, password):
|
||||
uri = "mongodb://%s:%s@%s:%d/?authMechanism=PLAIN;" "authSource=%s" % (
|
||||
uri = "mongodb://%s:%s@%s:%d/?authMechanism=PLAIN;authSource=%s" % (
|
||||
quote_plus(user),
|
||||
quote_plus(password),
|
||||
SASL_HOST,
|
||||
@ -484,7 +483,7 @@ class TestSCRAM(IntegrationTest):
|
||||
|
||||
if client_context.is_rs:
|
||||
host, port = client_context.host, client_context.port
|
||||
uri = "mongodb://both:pwd@%s:%d/testscram" "?replicaSet=%s" % (
|
||||
uri = "mongodb://both:pwd@%s:%d/testscram?replicaSet=%s" % (
|
||||
host,
|
||||
port,
|
||||
client_context.replica_set_name,
|
||||
@ -641,7 +640,7 @@ class TestAuthURIOptions(IntegrationTest):
|
||||
self.assertTrue(db.command("dbstats"))
|
||||
|
||||
# Test authSource
|
||||
uri = "mongodb://user:pass@%s:%d" "/pymongo_test2?authSource=pymongo_test" % (host, port)
|
||||
uri = "mongodb://user:pass@%s:%d/pymongo_test2?authSource=pymongo_test" % (host, port)
|
||||
client = rs_or_single_client_noauth(uri)
|
||||
self.assertRaises(OperationFailure, client.pymongo_test2.command, "dbstats")
|
||||
self.assertTrue(client.pymongo_test.command("dbstats"))
|
||||
|
||||
@ -19,14 +19,12 @@ import base64
|
||||
import copy
|
||||
import mmap
|
||||
import pickle
|
||||
import platform
|
||||
import sys
|
||||
import uuid
|
||||
|
||||
sys.path[0:0] = [""]
|
||||
|
||||
from test import IntegrationTest, client_context, unittest
|
||||
from test.utils import ignore_deprecations
|
||||
|
||||
import bson
|
||||
from bson import decode, encode
|
||||
|
||||
@ -204,35 +204,33 @@ class TestBSON(unittest.TestCase):
|
||||
self.assertInvalid(b"\x07\x00\x00\x00\x02a\x00\x78\x56\x34\x12")
|
||||
self.assertInvalid(b"\x09\x00\x00\x00\x10a\x00\x05\x00")
|
||||
self.assertInvalid(b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00")
|
||||
self.assertInvalid(b"\x13\x00\x00\x00\x02foo\x00" b"\x04\x00\x00\x00bar\x00\x00")
|
||||
self.assertInvalid(b"\x13\x00\x00\x00\x02foo\x00\x04\x00\x00\x00bar\x00\x00")
|
||||
self.assertInvalid(
|
||||
b"\x18\x00\x00\x00\x03foo\x00\x0f\x00\x00" b"\x00\x10bar\x00\xff\xff\xff\x7f\x00\x00"
|
||||
)
|
||||
self.assertInvalid(
|
||||
b"\x15\x00\x00\x00\x03foo\x00\x0c" b"\x00\x00\x00\x08bar\x00\x01\x00\x00"
|
||||
b"\x18\x00\x00\x00\x03foo\x00\x0f\x00\x00\x00\x10bar\x00\xff\xff\xff\x7f\x00\x00"
|
||||
)
|
||||
self.assertInvalid(b"\x15\x00\x00\x00\x03foo\x00\x0c\x00\x00\x00\x08bar\x00\x01\x00\x00")
|
||||
self.assertInvalid(
|
||||
b"\x1c\x00\x00\x00\x03foo\x00"
|
||||
b"\x12\x00\x00\x00\x02bar\x00"
|
||||
b"\x05\x00\x00\x00baz\x00\x00\x00"
|
||||
)
|
||||
self.assertInvalid(b"\x10\x00\x00\x00\x02a\x00" b"\x04\x00\x00\x00abc\xff\x00")
|
||||
self.assertInvalid(b"\x10\x00\x00\x00\x02a\x00\x04\x00\x00\x00abc\xff\x00")
|
||||
|
||||
def test_bad_string_lengths(self):
|
||||
self.assertInvalid(b"\x0c\x00\x00\x00\x02\x00" b"\x00\x00\x00\x00\x00\x00")
|
||||
self.assertInvalid(b"\x12\x00\x00\x00\x02\x00" b"\xff\xff\xff\xfffoobar\x00\x00")
|
||||
self.assertInvalid(b"\x0c\x00\x00\x00\x0e\x00" b"\x00\x00\x00\x00\x00\x00")
|
||||
self.assertInvalid(b"\x12\x00\x00\x00\x0e\x00" b"\xff\xff\xff\xfffoobar\x00\x00")
|
||||
self.assertInvalid(b"\x0c\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00")
|
||||
self.assertInvalid(b"\x12\x00\x00\x00\x02\x00\xff\xff\xff\xfffoobar\x00\x00")
|
||||
self.assertInvalid(b"\x0c\x00\x00\x00\x0e\x00\x00\x00\x00\x00\x00\x00")
|
||||
self.assertInvalid(b"\x12\x00\x00\x00\x0e\x00\xff\xff\xff\xfffoobar\x00\x00")
|
||||
self.assertInvalid(
|
||||
b"\x18\x00\x00\x00\x0c\x00" b"\x00\x00\x00\x00\x00RY\xb5j" b"\xfa[\xd8A\xd6X]\x99\x00"
|
||||
b"\x18\x00\x00\x00\x0c\x00\x00\x00\x00\x00\x00RY\xb5j\xfa[\xd8A\xd6X]\x99\x00"
|
||||
)
|
||||
self.assertInvalid(
|
||||
b"\x1e\x00\x00\x00\x0c\x00"
|
||||
b"\xff\xff\xff\xfffoobar\x00"
|
||||
b"RY\xb5j\xfa[\xd8A\xd6X]\x99\x00"
|
||||
)
|
||||
self.assertInvalid(b"\x0c\x00\x00\x00\r\x00" b"\x00\x00\x00\x00\x00\x00")
|
||||
self.assertInvalid(b"\x0c\x00\x00\x00\r\x00" b"\xff\xff\xff\xff\x00\x00")
|
||||
self.assertInvalid(b"\x0c\x00\x00\x00\r\x00\x00\x00\x00\x00\x00\x00")
|
||||
self.assertInvalid(b"\x0c\x00\x00\x00\r\x00\xff\xff\xff\xff\x00\x00")
|
||||
self.assertInvalid(
|
||||
b"\x1c\x00\x00\x00\x0f\x00"
|
||||
b"\x15\x00\x00\x00\x00\x00"
|
||||
@ -393,9 +391,7 @@ class TestBSON(unittest.TestCase):
|
||||
def test_data_timestamp(self):
|
||||
self.assertEqual(
|
||||
{"test": Timestamp(4, 20)},
|
||||
decode(
|
||||
b"\x13\x00\x00\x00\x11\x74\x65\x73\x74\x00\x14" b"\x00\x00\x00\x04\x00\x00\x00\x00"
|
||||
),
|
||||
decode(b"\x13\x00\x00\x00\x11\x74\x65\x73\x74\x00\x14\x00\x00\x00\x04\x00\x00\x00\x00"),
|
||||
)
|
||||
|
||||
def test_basic_encode(self):
|
||||
@ -414,29 +410,29 @@ class TestBSON(unittest.TestCase):
|
||||
)
|
||||
self.assertEqual(
|
||||
encode({"mike": 100}),
|
||||
b"\x0F\x00\x00\x00\x10\x6D\x69\x6B\x65\x00\x64\x00" b"\x00\x00\x00",
|
||||
b"\x0F\x00\x00\x00\x10\x6D\x69\x6B\x65\x00\x64\x00\x00\x00\x00",
|
||||
)
|
||||
self.assertEqual(
|
||||
encode({"hello": 1.5}),
|
||||
b"\x14\x00\x00\x00\x01\x68\x65\x6C\x6C\x6F\x00\x00" b"\x00\x00\x00\x00\x00\xF8\x3F\x00",
|
||||
b"\x14\x00\x00\x00\x01\x68\x65\x6C\x6C\x6F\x00\x00\x00\x00\x00\x00\x00\xF8\x3F\x00",
|
||||
)
|
||||
self.assertEqual(
|
||||
encode({"true": True}), b"\x0C\x00\x00\x00\x08\x74\x72\x75\x65\x00\x01\x00"
|
||||
)
|
||||
self.assertEqual(
|
||||
encode({"false": False}), b"\x0D\x00\x00\x00\x08\x66\x61\x6C\x73\x65\x00\x00" b"\x00"
|
||||
encode({"false": False}), b"\x0D\x00\x00\x00\x08\x66\x61\x6C\x73\x65\x00\x00\x00"
|
||||
)
|
||||
self.assertEqual(
|
||||
encode({"empty": []}),
|
||||
b"\x11\x00\x00\x00\x04\x65\x6D\x70\x74\x79\x00\x05" b"\x00\x00\x00\x00\x00",
|
||||
b"\x11\x00\x00\x00\x04\x65\x6D\x70\x74\x79\x00\x05\x00\x00\x00\x00\x00",
|
||||
)
|
||||
self.assertEqual(
|
||||
encode({"none": {}}),
|
||||
b"\x10\x00\x00\x00\x03\x6E\x6F\x6E\x65\x00\x05\x00" b"\x00\x00\x00\x00",
|
||||
b"\x10\x00\x00\x00\x03\x6E\x6F\x6E\x65\x00\x05\x00\x00\x00\x00\x00",
|
||||
)
|
||||
self.assertEqual(
|
||||
encode({"test": Binary(b"test", 0)}),
|
||||
b"\x14\x00\x00\x00\x05\x74\x65\x73\x74\x00\x04\x00" b"\x00\x00\x00\x74\x65\x73\x74\x00",
|
||||
b"\x14\x00\x00\x00\x05\x74\x65\x73\x74\x00\x04\x00\x00\x00\x00\x74\x65\x73\x74\x00",
|
||||
)
|
||||
self.assertEqual(
|
||||
encode({"test": Binary(b"test", 2)}),
|
||||
@ -445,24 +441,24 @@ class TestBSON(unittest.TestCase):
|
||||
)
|
||||
self.assertEqual(
|
||||
encode({"test": Binary(b"test", 128)}),
|
||||
b"\x14\x00\x00\x00\x05\x74\x65\x73\x74\x00\x04\x00" b"\x00\x00\x80\x74\x65\x73\x74\x00",
|
||||
b"\x14\x00\x00\x00\x05\x74\x65\x73\x74\x00\x04\x00\x00\x00\x80\x74\x65\x73\x74\x00",
|
||||
)
|
||||
self.assertEqual(encode({"test": None}), b"\x0B\x00\x00\x00\x0A\x74\x65\x73\x74\x00\x00")
|
||||
self.assertEqual(
|
||||
encode({"date": datetime.datetime(2007, 1, 8, 0, 30, 11)}),
|
||||
b"\x13\x00\x00\x00\x09\x64\x61\x74\x65\x00\x38\xBE" b"\x1C\xFF\x0F\x01\x00\x00\x00",
|
||||
b"\x13\x00\x00\x00\x09\x64\x61\x74\x65\x00\x38\xBE\x1C\xFF\x0F\x01\x00\x00\x00",
|
||||
)
|
||||
self.assertEqual(
|
||||
encode({"regex": re.compile(b"a*b", re.IGNORECASE)}),
|
||||
b"\x12\x00\x00\x00\x0B\x72\x65\x67\x65\x78\x00\x61" b"\x2A\x62\x00\x69\x00\x00",
|
||||
b"\x12\x00\x00\x00\x0B\x72\x65\x67\x65\x78\x00\x61\x2A\x62\x00\x69\x00\x00",
|
||||
)
|
||||
self.assertEqual(
|
||||
encode({"$where": Code("test")}),
|
||||
b"\x16\x00\x00\x00\r$where\x00\x05\x00\x00\x00test" b"\x00\x00",
|
||||
b"\x16\x00\x00\x00\r$where\x00\x05\x00\x00\x00test\x00\x00",
|
||||
)
|
||||
self.assertEqual(
|
||||
encode({"$field": Code("function(){ return true;}", scope=None)}),
|
||||
b"+\x00\x00\x00\r$field\x00\x1a\x00\x00\x00" b"function(){ return true;}\x00\x00",
|
||||
b"+\x00\x00\x00\r$field\x00\x1a\x00\x00\x00function(){ return true;}\x00\x00",
|
||||
)
|
||||
self.assertEqual(
|
||||
encode({"$field": Code("return function(){ return x; }", scope={"x": False})}),
|
||||
@ -496,7 +492,7 @@ class TestBSON(unittest.TestCase):
|
||||
part = "type %r for fieldname 'foo'" % (b"\x14",)
|
||||
docs = [
|
||||
b"\x0e\x00\x00\x00\x14foo\x00\x01\x00\x00\x00\x00",
|
||||
(b"\x16\x00\x00\x00\x04foo\x00\x0c\x00\x00\x00\x140" b"\x00\x01\x00\x00\x00\x00\x00"),
|
||||
(b"\x16\x00\x00\x00\x04foo\x00\x0c\x00\x00\x00\x140\x00\x01\x00\x00\x00\x00\x00"),
|
||||
(
|
||||
b" \x00\x00\x00\x04bar\x00\x16\x00\x00\x00\x030\x00\x0e\x00\x00"
|
||||
b"\x00\x14foo\x00\x01\x00\x00\x00\x00\x00\x00"
|
||||
@ -518,7 +514,7 @@ class TestBSON(unittest.TestCase):
|
||||
# not support creation of the DBPointer type, but will decode
|
||||
# DBPointer to DBRef.
|
||||
|
||||
bs = b"\x18\x00\x00\x00\x0c\x00\x01\x00\x00" b"\x00\x00RY\xb5j\xfa[\xd8A\xd6X]\x99\x00"
|
||||
bs = b"\x18\x00\x00\x00\x0c\x00\x01\x00\x00\x00\x00RY\xb5j\xfa[\xd8A\xd6X]\x99\x00"
|
||||
|
||||
self.assertEqual({"": DBRef("", ObjectId("5259b56afa5bd841d6585d99"))}, decode(bs))
|
||||
|
||||
@ -785,9 +781,7 @@ class TestBSON(unittest.TestCase):
|
||||
self.assertEqual(0, bson_re1.flags)
|
||||
|
||||
doc1 = {"r": bson_re1}
|
||||
doc1_bson = (
|
||||
b"\x11\x00\x00\x00" b"\x0br\x00[\\w-\\.]\x00\x00" b"\x00" # document length # r: regex
|
||||
) # document terminator
|
||||
doc1_bson = b"\x11\x00\x00\x00\x0br\x00[\\w-\\.]\x00\x00\x00" # document length # r: regex # document terminator
|
||||
|
||||
self.assertEqual(doc1_bson, encode(doc1))
|
||||
self.assertEqual(doc1, decode(doc1_bson))
|
||||
@ -798,9 +792,7 @@ class TestBSON(unittest.TestCase):
|
||||
|
||||
doc2_with_re = {"r": re2}
|
||||
doc2_with_bson_re = {"r": bson_re2}
|
||||
doc2_bson = (
|
||||
b"\x11\x00\x00\x00" b"\x0br\x00.*\x00imsux\x00" b"\x00" # document length # r: regex
|
||||
) # document terminator
|
||||
doc2_bson = b"\x11\x00\x00\x00\x0br\x00.*\x00imsux\x00\x00" # document length # r: regex # document terminator
|
||||
|
||||
self.assertEqual(doc2_bson, encode(doc2_with_re))
|
||||
self.assertEqual(doc2_bson, encode(doc2_with_bson_re))
|
||||
@ -917,7 +909,7 @@ class TestBSON(unittest.TestCase):
|
||||
|
||||
def test_timestamp_highorder_bits(self):
|
||||
doc = {"a": Timestamp(0xFFFFFFFF, 0xFFFFFFFF)}
|
||||
doc_bson = b"\x10\x00\x00\x00" b"\x11a\x00\xff\xff\xff\xff\xff\xff\xff\xff" b"\x00"
|
||||
doc_bson = b"\x10\x00\x00\x00\x11a\x00\xff\xff\xff\xff\xff\xff\xff\xff\x00"
|
||||
self.assertEqual(doc_bson, encode(doc))
|
||||
self.assertEqual(doc, decode(doc_bson))
|
||||
|
||||
|
||||
@ -208,13 +208,13 @@ def create_test(case_spec):
|
||||
# Null bytes are validated when encoding to BSON.
|
||||
if "Null" in description:
|
||||
to_bson(doc)
|
||||
raise AssertionError("exception not raised for test " "case: " + description)
|
||||
raise AssertionError("exception not raised for test case: " + description)
|
||||
except (ValueError, KeyError, TypeError, InvalidId, InvalidDocument):
|
||||
pass
|
||||
elif bson_type == "0x05":
|
||||
try:
|
||||
decode_extjson(parse_error_case["string"])
|
||||
raise AssertionError("exception not raised for test " "case: " + description)
|
||||
raise AssertionError("exception not raised for test case: " + description)
|
||||
except (TypeError, ValueError):
|
||||
pass
|
||||
else:
|
||||
|
||||
@ -26,7 +26,6 @@ import struct
|
||||
import sys
|
||||
import threading
|
||||
import time
|
||||
import warnings
|
||||
from typing import Type, no_type_check
|
||||
|
||||
sys.path[0:0] = [""]
|
||||
@ -88,7 +87,6 @@ from pymongo.errors import (
|
||||
ServerSelectionTimeoutError,
|
||||
WriteConcernError,
|
||||
)
|
||||
from pymongo.hello import HelloCompat
|
||||
from pymongo.mongo_client import MongoClient
|
||||
from pymongo.monitoring import ServerHeartbeatListener, ServerHeartbeatStartedEvent
|
||||
from pymongo.pool import _METADATA, PoolOptions, SocketInfo
|
||||
@ -99,10 +97,7 @@ from pymongo.server_type import SERVER_TYPE
|
||||
from pymongo.settings import TOPOLOGY_TYPE
|
||||
from pymongo.srv_resolver import _HAVE_DNSPYTHON
|
||||
from pymongo.topology import _ErrorContext
|
||||
from pymongo.topology_description import (
|
||||
TopologyDescription,
|
||||
_updated_topology_description_srv_polling,
|
||||
)
|
||||
from pymongo.topology_description import TopologyDescription
|
||||
from pymongo.write_concern import WriteConcern
|
||||
|
||||
|
||||
@ -279,7 +274,7 @@ class ClientUnitTest(unittest.TestCase):
|
||||
MongoClient("mongodb://host/?readpreferencetags=dc:east")
|
||||
|
||||
with self.assertRaises(ConfigurationError):
|
||||
MongoClient("mongodb://host/?" "readpreference=primary&readpreferencetags=dc:east")
|
||||
MongoClient("mongodb://host/?readpreference=primary&readpreferencetags=dc:east")
|
||||
|
||||
def test_read_preference(self):
|
||||
c = rs_or_single_client(
|
||||
@ -394,7 +389,7 @@ class ClientUnitTest(unittest.TestCase):
|
||||
|
||||
def test_uri_option_precedence(self):
|
||||
# Ensure kwarg options override connection string options.
|
||||
uri = "mongodb://localhost/?ssl=true&replicaSet=name" "&readPreference=primary"
|
||||
uri = "mongodb://localhost/?ssl=true&replicaSet=name&readPreference=primary"
|
||||
c = MongoClient(uri, ssl=False, replicaSet="newname", readPreference="secondaryPreferred")
|
||||
clopts = c._MongoClient__options
|
||||
opts = clopts._options
|
||||
@ -590,7 +585,7 @@ class TestClient(IntegrationTest):
|
||||
with server._pool.get_socket() as sock_info:
|
||||
pass
|
||||
self.assertEqual(1, len(server._pool.sockets))
|
||||
time.sleep(1) # Sleep so that the socket becomes stale.
|
||||
time.sleep(1) # Sleep so that the socket becomes stale.
|
||||
|
||||
with server._pool.get_socket() as new_sock_info:
|
||||
self.assertNotEqual(sock_info, new_sock_info)
|
||||
@ -712,7 +707,7 @@ class TestClient(IntegrationTest):
|
||||
|
||||
def test_repr(self):
|
||||
# Used to test 'eval' below.
|
||||
import bson
|
||||
import bson # noqa: F401
|
||||
|
||||
client = MongoClient(
|
||||
"mongodb://localhost:27017,localhost:27018/?replicaSet=replset"
|
||||
@ -723,9 +718,7 @@ class TestClient(IntegrationTest):
|
||||
|
||||
the_repr = repr(client)
|
||||
self.assertIn("MongoClient(host=", the_repr)
|
||||
self.assertIn(
|
||||
"document_class=bson.son.SON, " "tz_aware=False, " "connect=False, ", the_repr
|
||||
)
|
||||
self.assertIn("document_class=bson.son.SON, tz_aware=False, connect=False, ", the_repr)
|
||||
self.assertIn("connecttimeoutms=12345", the_repr)
|
||||
self.assertIn("replicaset='replset'", the_repr)
|
||||
self.assertIn("w=1", the_repr)
|
||||
@ -744,7 +737,7 @@ class TestClient(IntegrationTest):
|
||||
)
|
||||
the_repr = repr(client)
|
||||
self.assertIn("MongoClient(host=", the_repr)
|
||||
self.assertIn("document_class=dict, " "tz_aware=False, " "connect=False, ", the_repr)
|
||||
self.assertIn("document_class=dict, tz_aware=False, connect=False, ", the_repr)
|
||||
self.assertIn("connecttimeoutms=12345", the_repr)
|
||||
self.assertIn("replicaset='replset'", the_repr)
|
||||
self.assertIn("sockettimeoutms=None", the_repr)
|
||||
@ -1651,7 +1644,7 @@ class TestClient(IntegrationTest):
|
||||
)
|
||||
self.assertEqual(client._topology_settings.srv_service_name, "customname")
|
||||
client = MongoClient(
|
||||
"mongodb+srv://user:password@test22.test.build.10gen.cc" "/?srvServiceName=customname",
|
||||
"mongodb+srv://user:password@test22.test.build.10gen.cc/?srvServiceName=customname",
|
||||
connect=False,
|
||||
)
|
||||
self.assertEqual(client._topology_settings.srv_service_name, "customname")
|
||||
@ -1864,7 +1857,7 @@ class TestMongoClientFailover(MockClientTest):
|
||||
# Fail over.
|
||||
c.kill_host("a:1")
|
||||
c.mock_primary = "b:2"
|
||||
wait_until(lambda: c.address == ("b", 2), "wait for server " "address to be " "updated")
|
||||
wait_until(lambda: c.address == ("b", 2), "wait for server address to be updated")
|
||||
# a:1 not longer in nodes.
|
||||
self.assertLess(len(c.nodes), 3)
|
||||
|
||||
|
||||
@ -49,7 +49,7 @@ class TestClientContext(unittest.TestCase):
|
||||
|
||||
self.assertFalse(
|
||||
client_context.test_commands_enabled,
|
||||
"enableTestCommands must be disabled when " "PYMONGO_DISABLE_TEST_COMMANDS is set.",
|
||||
"enableTestCommands must be disabled when PYMONGO_DISABLE_TEST_COMMANDS is set.",
|
||||
)
|
||||
|
||||
def test_setdefaultencoding_worked(self):
|
||||
|
||||
@ -16,7 +16,6 @@
|
||||
|
||||
import os
|
||||
import sys
|
||||
import threading
|
||||
import time
|
||||
|
||||
sys.path[0:0] = [""]
|
||||
@ -25,7 +24,6 @@ from test import IntegrationTest, client_knobs, unittest
|
||||
from test.pymongo_mocks import DummyMonitor
|
||||
from test.utils import (
|
||||
CMAPListener,
|
||||
OvertCommandListener,
|
||||
TestCreator,
|
||||
camel_to_snake,
|
||||
client_context,
|
||||
|
||||
@ -246,8 +246,7 @@ class TestCollection(IntegrationTest):
|
||||
db = self.db
|
||||
with self.assertRaisesRegex(
|
||||
ConfigurationError,
|
||||
"Must be connected to MongoDB 4\.4\+ to use the commitQuorum "
|
||||
"option for createIndexes",
|
||||
r"Must be connected to MongoDB 4\.4\+ to use the commitQuorum option for createIndexes",
|
||||
):
|
||||
db.coll.create_indexes([IndexModel("a")], commitQuorum="majority")
|
||||
|
||||
@ -1511,7 +1510,7 @@ class TestCollection(IntegrationTest):
|
||||
# batchSize - 1
|
||||
self.assertEqual(4, len(cursor._CommandCursor__data)) # type: ignore
|
||||
# Exhaust the cursor. There shouldn't be any errors.
|
||||
for doc in cursor:
|
||||
for _doc in cursor:
|
||||
pass
|
||||
|
||||
def test_aggregation_cursor_alive(self):
|
||||
@ -1898,7 +1897,8 @@ class TestCollection(IntegrationTest):
|
||||
with self.assertRaises(TypeError):
|
||||
c.update_many({}, {"$set": {"a": 1}}, array_filters={}) # type: ignore[arg-type]
|
||||
with self.assertRaises(TypeError):
|
||||
c.find_one_and_update({}, {"$set": {"a": 1}}, array_filters={}) # type: ignore[arg-type]
|
||||
update = {"$set": {"a": 1}}
|
||||
c.find_one_and_update({}, update, array_filters={}) # type: ignore[arg-type]
|
||||
|
||||
def test_array_filters_unacknowledged(self):
|
||||
c_w0 = self.db.test.with_options(write_concern=WriteConcern(w=0))
|
||||
|
||||
@ -21,12 +21,7 @@ import sys
|
||||
sys.path[0:0] = [""]
|
||||
|
||||
from test import client_context, unittest
|
||||
from test.utils import (
|
||||
EventListener,
|
||||
parse_read_preference,
|
||||
rs_or_single_client,
|
||||
wait_until,
|
||||
)
|
||||
from test.utils import EventListener, parse_read_preference, rs_or_single_client
|
||||
|
||||
import pymongo
|
||||
from bson import json_util
|
||||
|
||||
@ -16,23 +16,16 @@
|
||||
|
||||
import inspect
|
||||
import sys
|
||||
from collections import defaultdict
|
||||
from typing import Any, Union
|
||||
|
||||
sys.path[0:0] = [""]
|
||||
|
||||
from test import IntegrationTest, SkipTest, client_context, unittest
|
||||
from test import IntegrationTest, client_context, unittest
|
||||
from test.utils import EventListener, rs_or_single_client
|
||||
|
||||
from bson.dbref import DBRef
|
||||
from pymongo.collection import Collection
|
||||
from pymongo.command_cursor import CommandCursor
|
||||
from pymongo.database import Database
|
||||
from pymongo.mongo_client import MongoClient
|
||||
from pymongo.operations import IndexModel
|
||||
from pymongo.read_concern import ReadConcern
|
||||
from pymongo.read_preferences import ReadPreference
|
||||
from pymongo.write_concern import WriteConcern
|
||||
|
||||
|
||||
class Empty(object):
|
||||
@ -47,7 +40,9 @@ class Empty(object):
|
||||
|
||||
|
||||
class TestComment(IntegrationTest):
|
||||
def _test_ops(self, helpers, already_supported, listener, db=Empty(), coll=Empty()):
|
||||
def _test_ops(
|
||||
self, helpers, already_supported, listener, db=Empty(), coll=Empty() # noqa: B008
|
||||
):
|
||||
results = listener.results
|
||||
for h, args in helpers:
|
||||
c = "testing comment with " + h.__name__
|
||||
@ -56,7 +51,7 @@ class TestComment(IntegrationTest):
|
||||
results.clear()
|
||||
kwargs = {"comment": cc}
|
||||
if h == coll.rename:
|
||||
tmp = db.get_collection("temp_temp_temp").drop()
|
||||
_ = db.get_collection("temp_temp_temp").drop()
|
||||
destruct_coll = db.get_collection("test_temp")
|
||||
destruct_coll.insert_one({})
|
||||
maybe_cursor = destruct_coll.rename(*args, **kwargs)
|
||||
|
||||
@ -19,7 +19,7 @@ import sys
|
||||
|
||||
sys.path[0:0] = [""]
|
||||
|
||||
from test import IntegrationTest, client_context, unittest
|
||||
from test import IntegrationTest, unittest
|
||||
from test.utils import (
|
||||
TestCreator,
|
||||
camel_to_snake,
|
||||
|
||||
@ -39,12 +39,7 @@ from bson.son import SON
|
||||
from pymongo import ASCENDING, DESCENDING
|
||||
from pymongo.collation import Collation
|
||||
from pymongo.cursor import Cursor, CursorType
|
||||
from pymongo.errors import (
|
||||
ConfigurationError,
|
||||
ExecutionTimeout,
|
||||
InvalidOperation,
|
||||
OperationFailure,
|
||||
)
|
||||
from pymongo.errors import ExecutionTimeout, InvalidOperation, OperationFailure
|
||||
from pymongo.read_concern import ReadConcern
|
||||
from pymongo.read_preferences import ReadPreference
|
||||
from pymongo.write_concern import WriteConcern
|
||||
@ -355,7 +350,7 @@ class TestCursor(IntegrationTest):
|
||||
)
|
||||
|
||||
spec = [("num", DESCENDING)]
|
||||
index = db.test.create_index(spec)
|
||||
_ = db.test.create_index(spec)
|
||||
|
||||
first = next(db.test.find())
|
||||
self.assertEqual(0, first.get("num"))
|
||||
@ -763,7 +758,7 @@ class TestCursor(IntegrationTest):
|
||||
self.assertEqual([8, 9], [a["x"] for a in cursor])
|
||||
|
||||
a = db.test.find()
|
||||
b = a.where("this.x > 3")
|
||||
_ = a.where("this.x > 3")
|
||||
for _ in a:
|
||||
break
|
||||
self.assertRaises(InvalidOperation, a.where, "this.x < 3")
|
||||
|
||||
@ -545,9 +545,7 @@ class TestTypeRegistry(unittest.TestCase):
|
||||
)
|
||||
|
||||
def test_initialize_fail(self):
|
||||
err_msg = (
|
||||
"Expected an instance of TypeEncoder, TypeDecoder, " "or TypeCodec, got .* instead"
|
||||
)
|
||||
err_msg = "Expected an instance of TypeEncoder, TypeDecoder, or TypeCodec, got .* instead"
|
||||
with self.assertRaisesRegex(TypeError, err_msg):
|
||||
TypeRegistry(self.codecs) # type: ignore[arg-type]
|
||||
|
||||
|
||||
@ -28,8 +28,6 @@ from test.utils import (
|
||||
rs_or_single_client,
|
||||
)
|
||||
|
||||
from pymongo.auth import MECHANISMS
|
||||
|
||||
# Location of JSON test specifications.
|
||||
_TEST_PATH = os.path.join(os.path.dirname(os.path.realpath(__file__)), "data_lake")
|
||||
|
||||
@ -42,7 +40,7 @@ class TestDataLakeMustConnect(IntegrationTest):
|
||||
|
||||
self.assertTrue(
|
||||
client_context.is_data_lake,
|
||||
"client context.is_data_lake must be True when " "DATA_LAKE is set",
|
||||
"client context.is_data_lake must be True when DATA_LAKE is set",
|
||||
)
|
||||
|
||||
|
||||
|
||||
@ -14,22 +14,18 @@
|
||||
|
||||
"""Test the database module."""
|
||||
|
||||
import datetime
|
||||
import re
|
||||
import sys
|
||||
from typing import Any, List, Mapping
|
||||
|
||||
sys.path[0:0] = [""]
|
||||
|
||||
from test import IntegrationTest, SkipTest, client_context, unittest
|
||||
from test import IntegrationTest, client_context, unittest
|
||||
from test.test_custom_types import DECIMAL_CODECOPTS
|
||||
from test.utils import (
|
||||
IMPOSSIBLE_WRITE_CONCERN,
|
||||
DeprecationFilter,
|
||||
OvertCommandListener,
|
||||
ignore_deprecations,
|
||||
rs_or_single_client,
|
||||
server_started_with_auth,
|
||||
wait_until,
|
||||
)
|
||||
|
||||
@ -44,7 +40,6 @@ from pymongo.collection import Collection
|
||||
from pymongo.database import Database
|
||||
from pymongo.errors import (
|
||||
CollectionInvalid,
|
||||
ConfigurationError,
|
||||
ExecutionTimeout,
|
||||
InvalidName,
|
||||
OperationFailure,
|
||||
|
||||
@ -69,7 +69,7 @@ class TestDBRef(unittest.TestCase):
|
||||
self.assertEqual(repr(DBRef("coll", 5, foo="bar")), "DBRef('coll', 5, foo='bar')")
|
||||
self.assertEqual(
|
||||
repr(DBRef("coll", ObjectId("1234567890abcdef12345678"), "foo")),
|
||||
"DBRef('coll', ObjectId('1234567890abcdef12345678'), " "'foo')",
|
||||
"DBRef('coll', ObjectId('1234567890abcdef12345678'), 'foo')",
|
||||
)
|
||||
|
||||
def test_equality(self):
|
||||
|
||||
@ -284,7 +284,7 @@ class TestIgnoreStaleErrors(IntegrationTest):
|
||||
def insert_command(i):
|
||||
try:
|
||||
client.test.command("insert", "test", documents=[{"i": i}])
|
||||
except AutoReconnect as exc:
|
||||
except AutoReconnect:
|
||||
pass
|
||||
|
||||
threads = []
|
||||
|
||||
@ -77,7 +77,7 @@ def create_test(test_case):
|
||||
options["tls"] = options.pop("ssl")
|
||||
parsed_options = test_case.get("parsed_options")
|
||||
# See DRIVERS-1324, unless tls is explicitly set to False we need TLS.
|
||||
needs_tls = not (options and (options.get("ssl") == False or options.get("tls") == False))
|
||||
needs_tls = not (options and (options.get("ssl") is False or options.get("tls") is False))
|
||||
if needs_tls and not client_context.tls:
|
||||
self.skipTest("this test requires a TLS cluster")
|
||||
if not needs_tls and client_context.tls:
|
||||
|
||||
@ -718,7 +718,7 @@ class TestDataKeyDoubleEncryption(EncryptionIntegrationTest):
|
||||
MASTER_KEYS = {
|
||||
"aws": {
|
||||
"region": "us-east-1",
|
||||
"key": "arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-" "4bd9-9f25-e30687b580d0",
|
||||
"key": "arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0",
|
||||
},
|
||||
"azure": {
|
||||
"keyVaultEndpoint": "key-vault-csfle.vault.azure.net",
|
||||
@ -1259,7 +1259,7 @@ class TestCustomEndpoint(EncryptionIntegrationTest):
|
||||
{
|
||||
"region": "us-east-1",
|
||||
"key": (
|
||||
"arn:aws:kms:us-east-1:579766882180:key/" "89fcc2c4-08b0-4bd9-9f25-e30687b580d0"
|
||||
"arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0"
|
||||
),
|
||||
},
|
||||
)
|
||||
@ -1271,7 +1271,7 @@ class TestCustomEndpoint(EncryptionIntegrationTest):
|
||||
{
|
||||
"region": "us-east-1",
|
||||
"key": (
|
||||
"arn:aws:kms:us-east-1:579766882180:key/" "89fcc2c4-08b0-4bd9-9f25-e30687b580d0"
|
||||
"arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0"
|
||||
),
|
||||
"endpoint": "kms.us-east-1.amazonaws.com",
|
||||
},
|
||||
@ -1284,7 +1284,7 @@ class TestCustomEndpoint(EncryptionIntegrationTest):
|
||||
{
|
||||
"region": "us-east-1",
|
||||
"key": (
|
||||
"arn:aws:kms:us-east-1:579766882180:key/" "89fcc2c4-08b0-4bd9-9f25-e30687b580d0"
|
||||
"arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0"
|
||||
),
|
||||
"endpoint": "kms.us-east-1.amazonaws.com:443",
|
||||
},
|
||||
@ -1294,9 +1294,7 @@ class TestCustomEndpoint(EncryptionIntegrationTest):
|
||||
def test_04_aws_endpoint_invalid_port(self):
|
||||
master_key = {
|
||||
"region": "us-east-1",
|
||||
"key": (
|
||||
"arn:aws:kms:us-east-1:579766882180:key/" "89fcc2c4-08b0-4bd9-9f25-e30687b580d0"
|
||||
),
|
||||
"key": ("arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0"),
|
||||
"endpoint": "kms.us-east-1.amazonaws.com:12345",
|
||||
}
|
||||
with self.assertRaises(EncryptionError) as ctx:
|
||||
@ -1307,9 +1305,7 @@ class TestCustomEndpoint(EncryptionIntegrationTest):
|
||||
def test_05_aws_endpoint_wrong_region(self):
|
||||
master_key = {
|
||||
"region": "us-east-1",
|
||||
"key": (
|
||||
"arn:aws:kms:us-east-1:579766882180:key/" "89fcc2c4-08b0-4bd9-9f25-e30687b580d0"
|
||||
),
|
||||
"key": ("arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0"),
|
||||
"endpoint": "kms.us-east-2.amazonaws.com",
|
||||
}
|
||||
# The full error should be something like:
|
||||
@ -1323,9 +1319,7 @@ class TestCustomEndpoint(EncryptionIntegrationTest):
|
||||
def test_06_aws_endpoint_invalid_host(self):
|
||||
master_key = {
|
||||
"region": "us-east-1",
|
||||
"key": (
|
||||
"arn:aws:kms:us-east-1:579766882180:key/" "89fcc2c4-08b0-4bd9-9f25-e30687b580d0"
|
||||
),
|
||||
"key": ("arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0"),
|
||||
"endpoint": "doesnotexist.invalid",
|
||||
}
|
||||
with self.assertRaisesRegex(EncryptionError, self.invalid_host_error):
|
||||
@ -1583,9 +1577,9 @@ class TestDeadlockProse(EncryptionIntegrationTest):
|
||||
event_listeners=[self.client_listener, self.topology_listener],
|
||||
)
|
||||
|
||||
if auto_encryption_opts._bypass_auto_encryption == True:
|
||||
if auto_encryption_opts._bypass_auto_encryption is True:
|
||||
self.client_test.db.coll.insert_one({"_id": 0, "encrypted": self.ciphertext})
|
||||
elif auto_encryption_opts._bypass_auto_encryption == False:
|
||||
elif auto_encryption_opts._bypass_auto_encryption is False:
|
||||
client_encrypted.db.coll.insert_one({"_id": 0, "encrypted": "string0"})
|
||||
else:
|
||||
raise RuntimeError("bypass_auto_encryption must be a bool")
|
||||
@ -1825,7 +1819,7 @@ class TestKmsTLSProse(EncryptionIntegrationTest):
|
||||
def test_invalid_kms_certificate_expired(self):
|
||||
key = {
|
||||
"region": "us-east-1",
|
||||
"key": "arn:aws:kms:us-east-1:579766882180:key/" "89fcc2c4-08b0-4bd9-9f25-e30687b580d0",
|
||||
"key": "arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0",
|
||||
"endpoint": "mongodb://127.0.0.1:8000",
|
||||
}
|
||||
# Some examples:
|
||||
@ -1837,7 +1831,7 @@ class TestKmsTLSProse(EncryptionIntegrationTest):
|
||||
def test_invalid_hostname_in_kms_certificate(self):
|
||||
key = {
|
||||
"region": "us-east-1",
|
||||
"key": "arn:aws:kms:us-east-1:579766882180:key/" "89fcc2c4-08b0-4bd9-9f25-e30687b580d0",
|
||||
"key": "arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0",
|
||||
"endpoint": "mongodb://127.0.0.1:8001",
|
||||
}
|
||||
# Some examples:
|
||||
|
||||
@ -49,11 +49,11 @@ class TestErrors(PyMongoTestCase):
|
||||
if sys.implementation.name == "pypy" and sys.implementation.version < (7, 3, 7):
|
||||
# PyPy used to display unicode in repr differently.
|
||||
self.assertEqual(
|
||||
"unicode \U0001f40d, full error: {" "'errmsg': 'unicode \\U0001f40d'}", str(exc)
|
||||
"unicode \U0001f40d, full error: {'errmsg': 'unicode \\U0001f40d'}", str(exc)
|
||||
)
|
||||
else:
|
||||
self.assertEqual(
|
||||
"unicode \U0001f40d, full error: {" "'errmsg': 'unicode \U0001f40d'}", str(exc)
|
||||
"unicode \U0001f40d, full error: {'errmsg': 'unicode \U0001f40d'}", str(exc)
|
||||
)
|
||||
try:
|
||||
raise exc
|
||||
|
||||
@ -945,9 +945,7 @@ class TestTransactionExamples(IntegrationTest):
|
||||
except (ConnectionFailure, OperationFailure) as exc:
|
||||
# Can retry commit
|
||||
if exc.has_error_label("UnknownTransactionCommitResult"):
|
||||
print(
|
||||
"UnknownTransactionCommitResult, retrying " "commit operation ..."
|
||||
)
|
||||
print("UnknownTransactionCommitResult, retrying commit operation ...")
|
||||
continue
|
||||
else:
|
||||
print("Error during commit ...")
|
||||
@ -970,11 +968,11 @@ class TestTransactionExamples(IntegrationTest):
|
||||
txn_func(session) # performs transaction
|
||||
break
|
||||
except (ConnectionFailure, OperationFailure) as exc:
|
||||
print("Transaction aborted. Caught exception during " "transaction.")
|
||||
print("Transaction aborted. Caught exception during transaction.")
|
||||
|
||||
# If transient error, retry the whole transaction
|
||||
if exc.has_error_label("TransientTransactionError"):
|
||||
print("TransientTransactionError, retrying" "transaction ...")
|
||||
print("TransientTransactionError, retrying transaction ...")
|
||||
continue
|
||||
else:
|
||||
raise
|
||||
@ -1000,7 +998,7 @@ class TestTransactionExamples(IntegrationTest):
|
||||
except (ConnectionFailure, OperationFailure) as exc:
|
||||
# Can retry commit
|
||||
if exc.has_error_label("UnknownTransactionCommitResult"):
|
||||
print("UnknownTransactionCommitResult, retrying " "commit operation ...")
|
||||
print("UnknownTransactionCommitResult, retrying commit operation ...")
|
||||
continue
|
||||
else:
|
||||
print("Error during commit ...")
|
||||
@ -1036,7 +1034,7 @@ class TestTransactionExamples(IntegrationTest):
|
||||
except (ConnectionFailure, OperationFailure) as exc:
|
||||
# If transient error, retry the whole transaction
|
||||
if exc.has_error_label("TransientTransactionError"):
|
||||
print("TransientTransactionError, retrying " "transaction ...")
|
||||
print("TransientTransactionError, retrying transaction ...")
|
||||
continue
|
||||
else:
|
||||
raise
|
||||
@ -1051,7 +1049,7 @@ class TestTransactionExamples(IntegrationTest):
|
||||
except (ConnectionFailure, OperationFailure) as exc:
|
||||
# Can retry commit
|
||||
if exc.has_error_label("UnknownTransactionCommitResult"):
|
||||
print("UnknownTransactionCommitResult, retrying " "commit operation ...")
|
||||
print("UnknownTransactionCommitResult, retrying commit operation ...")
|
||||
continue
|
||||
else:
|
||||
print("Error during commit ...")
|
||||
@ -1282,7 +1280,7 @@ class TestVersionedApiExamples(IntegrationTest):
|
||||
|
||||
with self.assertRaisesRegex(
|
||||
OperationFailure,
|
||||
"Provided apiStrict:true, but the command " "count is not in API Version 1",
|
||||
"Provided apiStrict:true, but the command count is not in API Version 1",
|
||||
):
|
||||
client.db.command("count", "sales", query={})
|
||||
# Start Versioned API Example 6
|
||||
|
||||
@ -580,7 +580,7 @@ Bye"""
|
||||
self.assertEqual([b"hello world"], list(g))
|
||||
|
||||
def test_read_unaligned_buffer_size(self):
|
||||
in_data = b"This is a text that doesn't " b"quite fit in a single 16-byte chunk."
|
||||
in_data = b"This is a text that doesn't quite fit in a single 16-byte chunk."
|
||||
f = GridIn(self.db.fs, chunkSize=16)
|
||||
f.write(in_data)
|
||||
f.close()
|
||||
|
||||
@ -399,7 +399,7 @@ class TestGridfs(IntegrationTest):
|
||||
def test_download_to_stream_by_name(self):
|
||||
file1 = BytesIO(b"hello world")
|
||||
# Test with one chunk.
|
||||
oid = self.fs.upload_from_stream("one_chunk", file1)
|
||||
_ = self.fs.upload_from_stream("one_chunk", file1)
|
||||
self.assertEqual(1, self.db.fs.chunks.count_documents({}))
|
||||
file2 = BytesIO()
|
||||
self.fs.download_to_stream_by_name("one_chunk", file2)
|
||||
|
||||
@ -15,7 +15,6 @@
|
||||
"""Test the monitoring of the server heartbeats."""
|
||||
|
||||
import sys
|
||||
import threading
|
||||
|
||||
sys.path[0:0] = [""]
|
||||
|
||||
|
||||
@ -331,7 +331,7 @@ class TestJsonUtil(unittest.TestCase):
|
||||
json_util.dumps(doc, json_options=LEGACY_JSON_OPTIONS),
|
||||
)
|
||||
self.assertEqual(
|
||||
'{"uuid": ' '{"$binary": "9HrBC1jMQ3KlZw4CssPUeQ==", "$type": "03"}}',
|
||||
'{"uuid": {"$binary": "9HrBC1jMQ3KlZw4CssPUeQ==", "$type": "03"}}',
|
||||
json_util.dumps(
|
||||
doc,
|
||||
json_options=STRICT_JSON_OPTIONS.with_options(
|
||||
@ -340,7 +340,7 @@ class TestJsonUtil(unittest.TestCase):
|
||||
),
|
||||
)
|
||||
self.assertEqual(
|
||||
'{"uuid": ' '{"$binary": "9HrBC1jMQ3KlZw4CssPUeQ==", "$type": "04"}}',
|
||||
'{"uuid": {"$binary": "9HrBC1jMQ3KlZw4CssPUeQ==", "$type": "04"}}',
|
||||
json_util.dumps(
|
||||
doc,
|
||||
json_options=JSONOptions(
|
||||
@ -351,7 +351,7 @@ class TestJsonUtil(unittest.TestCase):
|
||||
self.assertEqual(
|
||||
doc,
|
||||
json_util.loads(
|
||||
'{"uuid": ' '{"$binary": "9HrBC1jMQ3KlZw4CssPUeQ==", "$type": "03"}}',
|
||||
'{"uuid": {"$binary": "9HrBC1jMQ3KlZw4CssPUeQ==", "$type": "03"}}',
|
||||
json_options=uuid_legacy_opts,
|
||||
),
|
||||
)
|
||||
@ -364,7 +364,7 @@ class TestJsonUtil(unittest.TestCase):
|
||||
self.assertEqual(
|
||||
doc,
|
||||
json_util.loads(
|
||||
'{"uuid": ' '{"$binary": "9HrBC1jMQ3KlZw4CssPUeQ==", "$type": "04"}}',
|
||||
'{"uuid": {"$binary": "9HrBC1jMQ3KlZw4CssPUeQ==", "$type": "04"}}',
|
||||
json_options=options,
|
||||
),
|
||||
)
|
||||
@ -420,32 +420,32 @@ class TestJsonUtil(unittest.TestCase):
|
||||
json_bin_dump = json_util.dumps(md5_type_dict, json_options=LEGACY_JSON_OPTIONS)
|
||||
# Check order.
|
||||
self.assertEqual(
|
||||
'{"md5": {"$binary": "IG43GK8JL9HRL4DK53HMrA==",' + ' "$type": "05"}}', json_bin_dump
|
||||
'{"md5": {"$binary": "IG43GK8JL9HRL4DK53HMrA==", "$type": "05"}}', json_bin_dump
|
||||
)
|
||||
|
||||
self.assertEqual(
|
||||
md5_type_dict,
|
||||
json_util.loads('{"md5": {"$type": 5, "$binary":' ' "IG43GK8JL9HRL4DK53HMrA=="}}'),
|
||||
json_util.loads('{"md5": {"$type": 5, "$binary": "IG43GK8JL9HRL4DK53HMrA=="}}'),
|
||||
)
|
||||
|
||||
json_bin_dump = json_util.dumps(custom_type_dict, json_options=LEGACY_JSON_OPTIONS)
|
||||
self.assertIn('"$type": "80"', json_bin_dump)
|
||||
self.assertEqual(
|
||||
custom_type_dict,
|
||||
json_util.loads('{"custom": {"$type": 128, "$binary":' ' "aGVsbG8="}}'),
|
||||
json_util.loads('{"custom": {"$type": 128, "$binary": "aGVsbG8="}}'),
|
||||
)
|
||||
|
||||
# Handle mongoexport where subtype >= 128
|
||||
self.assertEqual(
|
||||
128,
|
||||
json_util.loads('{"custom": {"$type": "ffffff80", "$binary":' ' "aGVsbG8="}}')[
|
||||
json_util.loads('{"custom": {"$type": "ffffff80", "$binary": "aGVsbG8="}}')[
|
||||
"custom"
|
||||
].subtype,
|
||||
)
|
||||
|
||||
self.assertEqual(
|
||||
255,
|
||||
json_util.loads('{"custom": {"$type": "ffffffff", "$binary":' ' "aGVsbG8="}}')[
|
||||
json_util.loads('{"custom": {"$type": "ffffffff", "$binary": "aGVsbG8="}}')[
|
||||
"custom"
|
||||
].subtype,
|
||||
)
|
||||
|
||||
@ -158,7 +158,7 @@ class PoolLocker(ExceptionCatchingThread):
|
||||
# Wait for the unlock flag.
|
||||
unlock_pool = self.unlock.wait(10)
|
||||
if not unlock_pool:
|
||||
raise Exception("timed out waiting for unlock signal:" " deadlock?")
|
||||
raise Exception("timed out waiting for unlock signal: deadlock?")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
@ -52,21 +52,21 @@ class TestMaxStaleness(unittest.TestCase):
|
||||
|
||||
with self.assertRaises(ConfigurationError):
|
||||
# Read pref "primary" can't be used with max staleness.
|
||||
MongoClient("mongodb://a/?readPreference=primary&" "maxStalenessSeconds=120")
|
||||
MongoClient("mongodb://a/?readPreference=primary&maxStalenessSeconds=120")
|
||||
|
||||
client = MongoClient("mongodb://host/?maxStalenessSeconds=-1")
|
||||
self.assertEqual(-1, client.read_preference.max_staleness)
|
||||
|
||||
client = MongoClient("mongodb://host/?readPreference=primary&" "maxStalenessSeconds=-1")
|
||||
client = MongoClient("mongodb://host/?readPreference=primary&maxStalenessSeconds=-1")
|
||||
self.assertEqual(-1, client.read_preference.max_staleness)
|
||||
|
||||
client = MongoClient("mongodb://host/?readPreference=secondary&" "maxStalenessSeconds=120")
|
||||
client = MongoClient("mongodb://host/?readPreference=secondary&maxStalenessSeconds=120")
|
||||
self.assertEqual(120, client.read_preference.max_staleness)
|
||||
|
||||
client = MongoClient("mongodb://a/?readPreference=secondary&" "maxStalenessSeconds=1")
|
||||
client = MongoClient("mongodb://a/?readPreference=secondary&maxStalenessSeconds=1")
|
||||
self.assertEqual(1, client.read_preference.max_staleness)
|
||||
|
||||
client = MongoClient("mongodb://a/?readPreference=secondary&" "maxStalenessSeconds=-1")
|
||||
client = MongoClient("mongodb://a/?readPreference=secondary&maxStalenessSeconds=-1")
|
||||
self.assertEqual(-1, client.read_preference.max_staleness)
|
||||
|
||||
client = MongoClient(maxStalenessSeconds=-1, readPreference="nearest")
|
||||
@ -84,9 +84,7 @@ class TestMaxStaleness(unittest.TestCase):
|
||||
|
||||
with warnings.catch_warnings(record=True) as ctx:
|
||||
warnings.simplefilter("always")
|
||||
client = MongoClient(
|
||||
"mongodb://host/?maxStalenessSeconds=1.5" "&readPreference=nearest"
|
||||
)
|
||||
client = MongoClient("mongodb://host/?maxStalenessSeconds=1.5&readPreference=nearest")
|
||||
|
||||
# Option was ignored.
|
||||
self.assertEqual(-1, client.read_preference.max_staleness)
|
||||
@ -101,7 +99,7 @@ class TestMaxStaleness(unittest.TestCase):
|
||||
|
||||
with warnings.catch_warnings(record=True) as ctx:
|
||||
warnings.simplefilter("always")
|
||||
client = MongoClient("mongodb://host/?maxStalenessSeconds=0" "&readPreference=nearest")
|
||||
client = MongoClient("mongodb://host/?maxStalenessSeconds=0&readPreference=nearest")
|
||||
|
||||
# Option was ignored.
|
||||
self.assertEqual(-1, client.read_preference.max_staleness)
|
||||
|
||||
@ -16,19 +16,12 @@ import copy
|
||||
import datetime
|
||||
import sys
|
||||
import time
|
||||
import warnings
|
||||
from typing import Any
|
||||
|
||||
sys.path[0:0] = [""]
|
||||
|
||||
from test import IntegrationTest, client_context, client_knobs, sanitize_cmd, unittest
|
||||
from test.utils import (
|
||||
EventListener,
|
||||
get_pool,
|
||||
rs_or_single_client,
|
||||
single_client,
|
||||
wait_until,
|
||||
)
|
||||
from test.utils import EventListener, rs_or_single_client, single_client, wait_until
|
||||
|
||||
from bson.int64 import Int64
|
||||
from bson.objectid import ObjectId
|
||||
@ -781,7 +774,7 @@ class TestCommandMonitoring(IntegrationTest):
|
||||
|
||||
# delete_one
|
||||
self.listener.results.clear()
|
||||
res2 = coll.delete_one({"x": 3})
|
||||
_ = coll.delete_one({"x": 3})
|
||||
results = self.listener.results
|
||||
started = results["started"][0]
|
||||
succeeded = results["succeeded"][0]
|
||||
@ -1242,19 +1235,19 @@ class TestEventClasses(unittest.TestCase):
|
||||
event = monitoring.ServerOpeningEvent(server_address, topology_id)
|
||||
self.assertEqual(
|
||||
repr(event),
|
||||
"<ServerOpeningEvent ('localhost', 27017) " "topology_id: 000000000000000000000001>",
|
||||
"<ServerOpeningEvent ('localhost', 27017) topology_id: 000000000000000000000001>",
|
||||
)
|
||||
event = monitoring.ServerDescriptionChangedEvent(
|
||||
"PREV", "NEW", server_address, topology_id # type: ignore[arg-type]
|
||||
)
|
||||
self.assertEqual(
|
||||
repr(event),
|
||||
"<ServerDescriptionChangedEvent ('localhost', 27017) " "changed from: PREV, to: NEW>",
|
||||
"<ServerDescriptionChangedEvent ('localhost', 27017) changed from: PREV, to: NEW>",
|
||||
)
|
||||
event = monitoring.ServerClosedEvent(server_address, topology_id)
|
||||
self.assertEqual(
|
||||
repr(event),
|
||||
"<ServerClosedEvent ('localhost', 27017) " "topology_id: 000000000000000000000001>",
|
||||
"<ServerClosedEvent ('localhost', 27017) topology_id: 000000000000000000000001>",
|
||||
)
|
||||
|
||||
def test_topology_event_repr(self):
|
||||
|
||||
@ -16,7 +16,6 @@
|
||||
sample client code that uses PyMongo typings."""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import unittest
|
||||
from typing import Any, Dict, Iterable, List
|
||||
|
||||
|
||||
@ -320,7 +320,7 @@ class TestPooling(_TestPoolingBase):
|
||||
pool = self.create_pool(max_pool_size=1, wait_queue_timeout=wait_queue_timeout)
|
||||
self.addCleanup(pool.close)
|
||||
|
||||
with pool.get_socket() as sock_info:
|
||||
with pool.get_socket():
|
||||
start = time.time()
|
||||
with self.assertRaises(ConnectionFailure):
|
||||
with pool.get_socket():
|
||||
|
||||
@ -24,7 +24,7 @@ from pymongo.saslprep import saslprep
|
||||
class TestSASLprep(unittest.TestCase):
|
||||
def test_saslprep(self):
|
||||
try:
|
||||
import stringprep
|
||||
import stringprep # noqa
|
||||
except ImportError:
|
||||
self.assertRaises(TypeError, saslprep, "anything...")
|
||||
# Bytes strings are ignored.
|
||||
|
||||
@ -98,13 +98,13 @@ def compare_events(expected_dict, actual):
|
||||
)
|
||||
|
||||
if not compare_server_descriptions(expected["newDescription"], actual.new_description):
|
||||
return (False, "New ServerDescription incorrect in" " ServerDescriptionChangedEvent")
|
||||
return (False, "New ServerDescription incorrect in ServerDescriptionChangedEvent")
|
||||
if not compare_server_descriptions(
|
||||
expected["previousDescription"], actual.previous_description
|
||||
):
|
||||
return (
|
||||
False,
|
||||
"Previous ServerDescription incorrect in" " ServerDescriptionChangedEvent",
|
||||
"Previous ServerDescription incorrect in ServerDescriptionChangedEvent",
|
||||
)
|
||||
|
||||
elif expected_type == "server_closed_event":
|
||||
@ -125,19 +125,19 @@ def compare_events(expected_dict, actual):
|
||||
if not isinstance(actual, monitoring.TopologyDescriptionChangedEvent):
|
||||
return (
|
||||
False,
|
||||
"Expected TopologyDescriptionChangedEvent," " got %s" % (actual.__class__),
|
||||
"Expected TopologyDescriptionChangedEvent, got %s" % (actual.__class__),
|
||||
)
|
||||
if not compare_topology_descriptions(expected["newDescription"], actual.new_description):
|
||||
return (
|
||||
False,
|
||||
"New TopologyDescription incorrect in " "TopologyDescriptionChangedEvent",
|
||||
"New TopologyDescription incorrect in TopologyDescriptionChangedEvent",
|
||||
)
|
||||
if not compare_topology_descriptions(
|
||||
expected["previousDescription"], actual.previous_description
|
||||
):
|
||||
return (
|
||||
False,
|
||||
"Previous TopologyDescription incorrect in" " TopologyDescriptionChangedEvent",
|
||||
"Previous TopologyDescription incorrect in TopologyDescriptionChangedEvent",
|
||||
)
|
||||
|
||||
elif expected_type == "topology_closed_event":
|
||||
|
||||
@ -170,7 +170,7 @@ class TestServerDescription(unittest.TestCase):
|
||||
def test_repr(self):
|
||||
s = parse_hello_response({"ok": 1, "msg": "isdbgrid"})
|
||||
self.assertEqual(
|
||||
repr(s), "<ServerDescription ('localhost', 27017)" " server_type: Mongos, rtt: None>"
|
||||
repr(s), "<ServerDescription ('localhost', 27017) server_type: Mongos, rtt: None>"
|
||||
)
|
||||
|
||||
def test_topology_version(self):
|
||||
|
||||
@ -145,7 +145,7 @@ class TestSession(IntegrationTest):
|
||||
kw = copy.copy(kw)
|
||||
kw["session"] = s
|
||||
with self.assertRaisesRegex(
|
||||
InvalidOperation, "Can only use session with the MongoClient" " that started it"
|
||||
InvalidOperation, "Can only use session with the MongoClient that started it"
|
||||
):
|
||||
f(*args, **kw)
|
||||
|
||||
|
||||
@ -154,8 +154,8 @@ class TestSON(unittest.TestCase):
|
||||
self.assertIn(1, test_son)
|
||||
self.assertTrue(2 in test_son, "in failed")
|
||||
self.assertFalse(22 in test_son, "in succeeded when it shouldn't")
|
||||
self.assertTrue(test_son.has_key(2), "has_key failed")
|
||||
self.assertFalse(test_son.has_key(22), "has_key succeeded when it shouldn't")
|
||||
self.assertTrue(test_son.has_key(2), "has_key failed") # noqa
|
||||
self.assertFalse(test_son.has_key(22), "has_key succeeded when it shouldn't") # noqa
|
||||
|
||||
def test_clears(self):
|
||||
"""
|
||||
|
||||
@ -96,7 +96,7 @@ class TestSrvPolling(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
if not _HAVE_DNSPYTHON:
|
||||
raise unittest.SkipTest("SRV polling tests require the dnspython " "module")
|
||||
raise unittest.SkipTest("SRV polling tests require the dnspython module")
|
||||
# Patch timeouts to ensure short rescan SRV interval.
|
||||
self.client_knobs = client_knobs(
|
||||
heartbeat_frequency=WAIT_TIME,
|
||||
@ -318,7 +318,7 @@ class TestSrvPolling(unittest.TestCase):
|
||||
|
||||
with SrvPollingKnobs(ttl_time=WAIT_TIME, min_srv_rescan_interval=WAIT_TIME):
|
||||
client = MongoClient(
|
||||
"mongodb+srv://test22.test.build.10gen.cc/?srvServiceName" "=customname"
|
||||
"mongodb+srv://test22.test.build.10gen.cc/?srvServiceName=customname"
|
||||
)
|
||||
with SrvPollingKnobs(nodelist_callback=nodelist_callback):
|
||||
self.assert_nodelist_change(response, client)
|
||||
|
||||
@ -40,12 +40,12 @@ from pymongo.write_concern import WriteConcern
|
||||
_HAVE_PYOPENSSL = False
|
||||
try:
|
||||
# All of these must be available to use PyOpenSSL
|
||||
import OpenSSL
|
||||
import requests
|
||||
import service_identity
|
||||
import OpenSSL # noqa
|
||||
import requests # noqa
|
||||
import service_identity # noqa
|
||||
|
||||
# Ensure service_identity>=18.1 is installed
|
||||
from service_identity.pyopenssl import verify_ip_address
|
||||
from service_identity.pyopenssl import verify_ip_address # noqa
|
||||
|
||||
from pymongo.ocsp_support import _load_trusted_ca_certs
|
||||
|
||||
@ -79,9 +79,7 @@ _PY37PLUS = sys.version_info[:2] >= (3, 7)
|
||||
|
||||
|
||||
class TestClientSSL(unittest.TestCase):
|
||||
@unittest.skipIf(
|
||||
HAVE_SSL, "The ssl module is available, can't test what " "happens without it."
|
||||
)
|
||||
@unittest.skipIf(HAVE_SSL, "The ssl module is available, can't test what happens without it.")
|
||||
def test_no_ssl_module(self):
|
||||
# Explicit
|
||||
self.assertRaises(ConfigurationError, MongoClient, ssl=True)
|
||||
@ -406,7 +404,7 @@ class TestSSL(IntegrationTest):
|
||||
)
|
||||
)
|
||||
|
||||
uri_fmt = "mongodb://localhost/?ssl=true&" "tlsCAFile=%s&serverSelectionTimeoutMS=100"
|
||||
uri_fmt = "mongodb://localhost/?ssl=true&tlsCAFile=%s&serverSelectionTimeoutMS=100"
|
||||
connected(MongoClient(uri_fmt % (CA_PEM,), **self.credentials)) # type: ignore
|
||||
|
||||
uri_fmt = (
|
||||
@ -569,7 +567,7 @@ class TestSSL(IntegrationTest):
|
||||
else:
|
||||
self.assertEqual(names, ["authenticate", "find"])
|
||||
|
||||
uri = "mongodb://%s@%s:%d/?authMechanism=" "MONGODB-X509" % (
|
||||
uri = "mongodb://%s@%s:%d/?authMechanism=MONGODB-X509" % (
|
||||
quote_plus(MONGODB_X509_USERNAME),
|
||||
host,
|
||||
port,
|
||||
@ -589,7 +587,7 @@ class TestSSL(IntegrationTest):
|
||||
# No error
|
||||
client.pymongo_test.test.find_one()
|
||||
# Auth should fail if username and certificate do not match
|
||||
uri = "mongodb://%s@%s:%d/?authMechanism=" "MONGODB-X509" % (
|
||||
uri = "mongodb://%s@%s:%d/?authMechanism=MONGODB-X509" % (
|
||||
quote_plus("not the username"),
|
||||
host,
|
||||
port,
|
||||
@ -617,7 +615,7 @@ class TestSSL(IntegrationTest):
|
||||
bad_client.pymongo_test.test.find_one()
|
||||
|
||||
# Invalid certificate (using CA certificate as client certificate)
|
||||
uri = "mongodb://%s@%s:%d/?authMechanism=" "MONGODB-X509" % (
|
||||
uri = "mongodb://%s@%s:%d/?authMechanism=MONGODB-X509" % (
|
||||
quote_plus(MONGODB_X509_USERNAME),
|
||||
host,
|
||||
port,
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user