Merge branch 'master' of github.com:mongodb/mongo-python-driver

This commit is contained in:
Steven Silvester 2024-10-30 19:54:38 -05:00
commit 7eafd5dd72
No known key found for this signature in database
GPG Key ID: B1BF5EC3A8B32F91
32 changed files with 157 additions and 310 deletions

View File

@ -11,7 +11,7 @@ The PyMongo distribution contains tools for interacting with MongoDB
database from Python. The `bson` package is an implementation of the
[BSON format](http://bsonspec.org) for Python. The `pymongo` package is
a native Python driver for MongoDB. The `gridfs` package is a
[gridfs](https://github.com/mongodb/specifications/blob/master/source/gridfs/gridfs-spec.rst/)
[gridfs](https://github.com/mongodb/specifications/blob/master/source/gridfs/gridfs-spec.md/)
implementation on top of `pymongo`.
PyMongo supports MongoDB 4.0, 4.2, 4.4, 5.0, 6.0, 7.0, and 8.0.

View File

@ -22,7 +22,7 @@ is emitted and parsed, with the default being the Relaxed Extended JSON format.
when :const:`CANONICAL_JSON_OPTIONS` or :const:`LEGACY_JSON_OPTIONS` is
provided, respectively.
.. _Extended JSON: https://github.com/mongodb/specifications/blob/master/source/extended-json.rst
.. _Extended JSON: https://github.com/mongodb/specifications/blob/master/source/extended-json/extended-json.md
Example usage (deserialization):

View File

@ -6,7 +6,7 @@ interacting with MongoDB. :mod:`bson` is an implementation of the
`BSON format <http://bsonspec.org>`_, :mod:`pymongo` is a
full-featured driver for MongoDB, and :mod:`gridfs` is a set of tools
for working with the `GridFS
<https://github.com/mongodb/specifications/blob/master/source/gridfs/gridfs-spec.rst/>`_ storage
<https://github.com/mongodb/specifications/blob/master/source/gridfs/gridfs-spec.md/>`_ storage
specification.
.. toctree::

View File

@ -12,6 +12,7 @@ PyMongo 4.11 brings a number of changes including:
- Dropped support for Python 3.8.
- Dropped support for MongoDB 3.6.
- Dropped support for the MONGODB-CR authenticate mechanism, which is no longer supported by MongoDB 4.0+.
- Added support for free-threaded Python with the GIL disabled. For more information see:
`Free-threaded CPython <https://docs.python.org/3.13/whatsnew/3.13.html#whatsnew313-free-threaded-cpython>`_.
- :attr:`~pymongo.asynchronous.mongo_client.AsyncMongoClient.address` and
@ -23,6 +24,10 @@ PyMongo 4.11 brings a number of changes including:
:meth:`~pymongo.collection.Collection.update_one`, :meth:`~pymongo.collection.Collection.replace_one`,
:class:`~pymongo.operations.UpdateOne`, and
:class:`~pymongo.operations.UpdateMany`,
- :meth:`~pymongo.mongo_client.MongoClient.bulk_write` and
:meth:`~pymongo.asynchronous.mongo_client.AsyncMongoClient.bulk_write` now throw an error
when ``ordered=True`` or ``verboseResults=True`` are used with unacknowledged writes.
These are unavoidable breaking changes.
Issues Resolved
...............
@ -1022,7 +1027,7 @@ See the `PyMongo 4.0 release notes in JIRA`_ for the list of resolved issues
in this release.
.. _PyMongo 4.0 release notes in JIRA: https://jira.mongodb.org/secure/ReleaseNote.jspa?projectId=10004&version=18463
.. _DBRef specification: https://github.com/mongodb/specifications/blob/5a8c8d7/source/dbref.rst
.. _DBRef specification: https://github.com/mongodb/specifications/blob/master/source/dbref/dbref.md
Changes in Version 3.13.0 (2022/11/01)
--------------------------------------
@ -1557,7 +1562,7 @@ Unavoidable breaking changes:
bumped to 1.16.0. This is a breaking change for applications that use
PyMongo's SRV support with a version of ``dnspython`` older than 1.16.0.
.. _URI options specification: https://github.com/mongodb/specifications/blob/master/source/uri-options/uri-options.rst
.. _URI options specification: https://github.com/mongodb/specifications/blob/master/source/uri-options/uri-options.md
Issues Resolved
@ -1581,7 +1586,7 @@ Changes in Version 3.8.0 (2019/04/22)
must upgrade to PyPy3.5+.
- :class:`~bson.objectid.ObjectId` now implements the `ObjectID specification
version 0.2 <https://github.com/mongodb/specifications/blob/master/source/objectid.rst>`_.
version 0.2 <https://github.com/mongodb/specifications/blob/master/source/bson-objectid/objectid.md>`_.
- For better performance and to better follow the GridFS spec,
:class:`~gridfs.grid_file.GridOut` now uses a single cursor to read all the
chunks in the file. Previously, each chunk in the file was queried
@ -1943,7 +1948,7 @@ Highlights include:
:class:`~pymongo.operations.UpdateOne`, and
:class:`~pymongo.operations.UpdateMany`.
- Implemented the `MongoDB Extended JSON
<https://github.com/mongodb/specifications/blob/master/source/extended-json.rst>`_
<https://github.com/mongodb/specifications/blob/master/source/extended-json/extended-json.md>`_
specification.
- :class:`~bson.decimal128.Decimal128` now works when cdecimal is installed.
- PyMongo is now tested against a wider array of operating systems and CPU

View File

@ -85,7 +85,7 @@ pygments_style = "sphinx"
# wiki.centos.org has been flakey.
# sourceforge.net is giving a 403 error, but is still accessible from the browser.
linkcheck_ignore = [
"https://github.com/mongodb/specifications/blob/master/source/server-discovery-and-monitoring/server-monitoring.rst#requesting-an-immediate-check",
"https://github.com/mongodb/specifications/blob/master/source/server-discovery-and-monitoring/server-monitoring.md#requesting-an-immediate-check",
"https://github.com/mongodb/libmongocrypt/blob/master/bindings/python/README.rst#installing-from-source",
r"https://wiki.centos.org/[\w/]*",
r"http://sourceforge.net/",

View File

@ -106,7 +106,7 @@ Thus the current design of periodic executors is surprisingly simple: they
do a simple ``time.sleep`` for a half-second, check if it is time to wake or
terminate, and sleep again.
.. _Server Discovery And Monitoring Spec: https://github.com/mongodb/specifications/blob/master/source/server-discovery-and-monitoring/server-monitoring.rst#requesting-an-immediate-check
.. _Server Discovery And Monitoring Spec: https://github.com/mongodb/specifications/blob/master/source/server-discovery-and-monitoring/server-monitoring.md#requesting-an-immediate-check
.. _PYTHON-863: https://jira.mongodb.org/browse/PYTHON-863

View File

@ -76,24 +76,6 @@ For best performance on Python versions older than 2.7.8 install `backports.pbkd
.. _backports.pbkdf2: https://pypi.python.org/pypi/backports.pbkdf2/
MONGODB-CR
----------
.. warning:: MONGODB-CR was deprecated with the release of MongoDB 3.6 and
is no longer supported by MongoDB 4.0.
Before MongoDB 3.0 the default authentication mechanism was MONGODB-CR,
the "MongoDB Challenge-Response" protocol::
>>> from pymongo import MongoClient
>>> client = MongoClient('example.com',
... username='user',
... password='password',
... authMechanism='MONGODB-CR')
>>>
>>> uri = "mongodb://user:password@example.com/?authSource=the_database&authMechanism=MONGODB-CR"
>>> client = MongoClient(uri)
Default Authentication Mechanism
--------------------------------
@ -221,8 +203,7 @@ SASL PLAIN (RFC 4616)
MongoDB Enterprise Edition version 2.6 and newer support the SASL PLAIN
authentication mechanism, initially intended for delegating authentication
to an LDAP server. Using the PLAIN mechanism is very similar to MONGODB-CR.
These examples use the $external virtual database for LDAP support::
to an LDAP server. These examples use the $external virtual database for LDAP support::
>>> from pymongo import MongoClient
>>> uri = "mongodb://user:password@example.com/?authMechanism=PLAIN"

View File

@ -84,7 +84,7 @@ Finally, the same UUID would historically be serialized by the Java driver as::
.. note:: For in-depth information about the the byte-order historically
used by different drivers, see the `Handling of Native UUID Types
Specification
<https://github.com/mongodb/specifications/blob/master/source/uuid.rst>`_.
<https://github.com/mongodb/specifications/blob/master/source/bson-binary-uuid/uuid.md>`_.
This difference in the byte-order of UUIDs encoded by different drivers can
result in highly unintuitive behavior in some scenarios. We detail two such

View File

@ -118,7 +118,7 @@ Renamed URI options
Several deprecated URI options have been renamed to the standardized
option names defined in the
`URI options specification <https://github.com/mongodb/specifications/blob/master/source/uri-options/uri-options.rst>`_.
`URI options specification <https://github.com/mongodb/specifications/blob/master/source/uri-options/uri-options.md>`_.
The old option names and their renamed equivalents are summarized in the table
below. Some renamed options have different semantics from the option being
replaced as noted in the 'Migration Notes' column.
@ -965,7 +965,7 @@ correct type. Otherwise the document is returned as normal. Previously, any
subdocument containing a ``$ref`` field would be decoded as a
:class:`~bson.dbref.DBRef`.
.. _DBRef specification: https://github.com/mongodb/specifications/blob/5a8c8d7/source/dbref.rst
.. _DBRef specification: https://github.com/mongodb/specifications/blob/master/source/dbref/dbref.md
Encoding a UUID raises an error by default
..........................................

View File

@ -329,21 +329,6 @@ async def _authenticate_x509(credentials: MongoCredential, conn: AsyncConnection
await conn.command("$external", cmd)
async def _authenticate_mongo_cr(credentials: MongoCredential, conn: AsyncConnection) -> None:
"""Authenticate using MONGODB-CR."""
source = credentials.source
username = credentials.username
password = credentials.password
# Get a nonce
response = await conn.command(source, {"getnonce": 1})
nonce = response["nonce"]
key = _auth_key(nonce, username, password)
# Actually authenticate
query = {"authenticate": 1, "user": username, "nonce": nonce, "key": key}
await conn.command(source, query)
async def _authenticate_default(credentials: MongoCredential, conn: AsyncConnection) -> None:
if conn.max_wire_version >= 7:
if conn.negotiated_mechs:
@ -365,7 +350,6 @@ async def _authenticate_default(credentials: MongoCredential, conn: AsyncConnect
_AUTH_MAP: Mapping[str, Callable[..., Coroutine[Any, Any, None]]] = {
"GSSAPI": _authenticate_gssapi,
"MONGODB-CR": _authenticate_mongo_cr,
"MONGODB-X509": _authenticate_x509,
"MONGODB-AWS": _authenticate_aws,
"MONGODB-OIDC": _authenticate_oidc, # type:ignore[dict-item]

View File

@ -681,11 +681,11 @@ class _AsyncClientBulk:
_throw_client_bulk_write_exception(full_result, self.verbose_results)
return full_result
async def execute_command_unack_unordered(
async def execute_command_unack(
self,
conn: AsyncConnection,
) -> None:
"""Execute commands with OP_MSG and w=0 writeConcern, unordered."""
"""Execute commands with OP_MSG and w=0 writeConcern. Always unordered."""
db_name = "admin"
cmd_name = "bulkWrite"
listeners = self.client._event_listeners
@ -704,8 +704,8 @@ class _AsyncClientBulk:
while self.idx_offset < self.total_ops:
# Construct the server command, specifying the relevant options.
cmd = {"bulkWrite": 1}
cmd["errorsOnly"] = not self.verbose_results
cmd["ordered"] = self.ordered # type: ignore[assignment]
cmd["errorsOnly"] = True
cmd["ordered"] = False
if self.bypass_doc_val is not None:
cmd["bypassDocumentValidation"] = self.bypass_doc_val
cmd["writeConcern"] = {"w": 0} # type: ignore[assignment]
@ -723,43 +723,6 @@ class _AsyncClientBulk:
self.idx_offset += len(to_send_ops)
async def execute_command_unack_ordered(
self,
conn: AsyncConnection,
) -> None:
"""Execute commands with OP_MSG and w=0 WriteConcern, ordered."""
full_result: MutableMapping[str, Any] = {
"anySuccessful": False,
"error": None,
"writeErrors": [],
"writeConcernErrors": [],
"nInserted": 0,
"nUpserted": 0,
"nMatched": 0,
"nModified": 0,
"nDeleted": 0,
"insertResults": {},
"updateResults": {},
"deleteResults": {},
}
# Ordered bulk writes have to be acknowledged so that we stop
# processing at the first error, even when the application
# specified unacknowledged writeConcern.
initial_write_concern = WriteConcern()
op_id = _randint()
try:
await self._execute_command(
initial_write_concern,
None,
conn,
op_id,
False,
full_result,
self.write_concern,
)
except OperationFailure:
pass
async def execute_no_results(
self,
conn: AsyncConnection,
@ -775,9 +738,7 @@ class _AsyncClientBulk:
"Cannot set bypass_document_validation with unacknowledged write concern"
)
if self.ordered:
return await self.execute_command_unack_ordered(conn)
return await self.execute_command_unack_unordered(conn)
return await self.execute_command_unack(conn)
async def execute(
self,

View File

@ -221,7 +221,7 @@ class AsyncMongoClient(common.BaseObject, Generic[_DocumentType]):
<https://en.wikipedia.org/wiki/TXT_record>`_. See the
`Initial DNS Seedlist Discovery spec
<https://github.com/mongodb/specifications/blob/master/source/
initial-dns-seedlist-discovery/initial-dns-seedlist-discovery.rst>`_
initial-dns-seedlist-discovery/initial-dns-seedlist-discovery.md>`_
for more details. Note that the use of SRV URIs implicitly enables
TLS support. Pass tls=false in the URI to override.
@ -367,7 +367,7 @@ class AsyncMongoClient(common.BaseObject, Generic[_DocumentType]):
:meth:`~pymongo.asynchronous.collection.AsyncCollection.aggregate` using the ``$out``
pipeline operator and any operation with an unacknowledged write
concern (e.g. {w: 0})). See
https://github.com/mongodb/specifications/blob/master/source/retryable-writes/retryable-writes.rst
https://github.com/mongodb/specifications/blob/master/source/retryable-writes/retryable-writes.md
- `retryReads`: (boolean) Whether supported read operations
executed within this AsyncMongoClient will be retried once after a
network error. Defaults to ``True``.
@ -394,7 +394,7 @@ class AsyncMongoClient(common.BaseObject, Generic[_DocumentType]):
transient errors such as network failures, database upgrades, and
replica set failovers. For an exact definition of which errors
trigger a retry, see the `retryable reads specification
<https://github.com/mongodb/specifications/blob/master/source/retryable-reads/retryable-reads.rst>`_.
<https://github.com/mongodb/specifications/blob/master/source/retryable-reads/retryable-reads.md>`_.
- `compressors`: Comma separated list of compressors for wire
protocol compression. The list is used to negotiate a compressor

View File

@ -34,7 +34,6 @@ from pymongo.errors import ConfigurationError
MECHANISMS = frozenset(
[
"GSSAPI",
"MONGODB-CR",
"MONGODB-OIDC",
"MONGODB-X509",
"MONGODB-AWS",
@ -78,7 +77,7 @@ MongoCredential = namedtuple(
GSSAPIProperties = namedtuple(
"GSSAPIProperties", ["service_name", "canonicalize_host_name", "service_realm"]
"GSSAPIProperties", ["service_name", "canonicalize_host_name", "service_realm", "service_host"]
)
"""Mechanism properties for GSSAPI authentication."""
@ -87,6 +86,16 @@ _AWSProperties = namedtuple("_AWSProperties", ["aws_session_token"])
"""Mechanism properties for MONGODB-AWS authentication."""
def _validate_canonicalize_host_name(value: str | bool) -> str | bool:
valid_names = [False, True, "none", "forward", "forwardAndReverse"]
if value in ["true", "false", True, False]:
return value in ["true", True]
if value not in valid_names:
raise ValueError(f"CANONICALIZE_HOST_NAME '{value}' not in valid options: {valid_names}")
return value
def _build_credentials_tuple(
mech: str,
source: Optional[str],
@ -103,12 +112,15 @@ def _build_credentials_tuple(
raise ValueError("authentication source must be $external or None for GSSAPI")
properties = extra.get("authmechanismproperties", {})
service_name = properties.get("SERVICE_NAME", "mongodb")
canonicalize = bool(properties.get("CANONICALIZE_HOST_NAME", False))
service_host = properties.get("SERVICE_HOST", None)
canonicalize = properties.get("CANONICALIZE_HOST_NAME", "false")
canonicalize = _validate_canonicalize_host_name(canonicalize)
service_realm = properties.get("SERVICE_REALM")
props = GSSAPIProperties(
service_name=service_name,
canonicalize_host_name=canonicalize,
service_realm=service_realm,
service_host=service_host,
)
# Source is always $external.
return MongoCredential(mech, "$external", user, passwd, props, None)

View File

@ -139,6 +139,9 @@ SRV_SERVICE_NAME = "mongodb"
# Default value for serverMonitoringMode
SERVER_MONITORING_MODE = "auto" # poll/stream/auto
# Auth mechanism properties that must raise an error instead of warning if they invalidate.
_MECH_PROP_MUST_RAISE = ["CANONICALIZE_HOST_NAME"]
def partition_node(node: str) -> tuple[str, int]:
"""Split a host:port string into (host, int(port)) pair."""
@ -423,6 +426,7 @@ def validate_read_preference_tags(name: str, value: Any) -> list[dict[str, str]]
_MECHANISM_PROPS = frozenset(
[
"SERVICE_NAME",
"SERVICE_HOST",
"CANONICALIZE_HOST_NAME",
"SERVICE_REALM",
"AWS_SESSION_TOKEN",
@ -476,7 +480,9 @@ def validate_auth_mechanism_properties(option: str, value: Any) -> dict[str, Uni
)
if key == "CANONICALIZE_HOST_NAME":
props[key] = validate_boolean_or_string(key, val)
from pymongo.auth_shared import _validate_canonicalize_host_name
props[key] = _validate_canonicalize_host_name(val)
else:
props[key] = val
@ -867,6 +873,10 @@ def get_validated_options(
validator = _get_validator(opt, URI_OPTIONS_VALIDATOR_MAP, normed_key=normed_key)
validated = validator(opt, value)
except (ValueError, TypeError, ConfigurationError) as exc:
if normed_key == "authmechanismproperties" and any(
p in str(exc) for p in _MECH_PROP_MUST_RAISE
):
raise
if warn:
warnings.warn(str(exc), stacklevel=2)
else:

View File

@ -216,7 +216,7 @@ def _metadata_env() -> dict[str, Any]:
_MAX_METADATA_SIZE = 512
# See: https://github.com/mongodb/specifications/blob/5112bcc/source/mongodb-handshake/handshake.rst#limitations
# See: https://github.com/mongodb/specifications/blob/master/source/mongodb-handshake/handshake.md#limitations
def _truncate_metadata(metadata: MutableMapping[str, Any]) -> None:
"""Perform metadata truncation."""
if len(bson.encode(metadata)) <= _MAX_METADATA_SIZE:

View File

@ -326,21 +326,6 @@ def _authenticate_x509(credentials: MongoCredential, conn: Connection) -> None:
conn.command("$external", cmd)
def _authenticate_mongo_cr(credentials: MongoCredential, conn: Connection) -> None:
"""Authenticate using MONGODB-CR."""
source = credentials.source
username = credentials.username
password = credentials.password
# Get a nonce
response = conn.command(source, {"getnonce": 1})
nonce = response["nonce"]
key = _auth_key(nonce, username, password)
# Actually authenticate
query = {"authenticate": 1, "user": username, "nonce": nonce, "key": key}
conn.command(source, query)
def _authenticate_default(credentials: MongoCredential, conn: Connection) -> None:
if conn.max_wire_version >= 7:
if conn.negotiated_mechs:
@ -360,7 +345,6 @@ def _authenticate_default(credentials: MongoCredential, conn: Connection) -> Non
_AUTH_MAP: Mapping[str, Callable[..., None]] = {
"GSSAPI": _authenticate_gssapi,
"MONGODB-CR": _authenticate_mongo_cr,
"MONGODB-X509": _authenticate_x509,
"MONGODB-AWS": _authenticate_aws,
"MONGODB-OIDC": _authenticate_oidc, # type:ignore[dict-item]

View File

@ -679,11 +679,11 @@ class _ClientBulk:
_throw_client_bulk_write_exception(full_result, self.verbose_results)
return full_result
def execute_command_unack_unordered(
def execute_command_unack(
self,
conn: Connection,
) -> None:
"""Execute commands with OP_MSG and w=0 writeConcern, unordered."""
"""Execute commands with OP_MSG and w=0 writeConcern. Always unordered."""
db_name = "admin"
cmd_name = "bulkWrite"
listeners = self.client._event_listeners
@ -702,8 +702,8 @@ class _ClientBulk:
while self.idx_offset < self.total_ops:
# Construct the server command, specifying the relevant options.
cmd = {"bulkWrite": 1}
cmd["errorsOnly"] = not self.verbose_results
cmd["ordered"] = self.ordered # type: ignore[assignment]
cmd["errorsOnly"] = True
cmd["ordered"] = False
if self.bypass_doc_val is not None:
cmd["bypassDocumentValidation"] = self.bypass_doc_val
cmd["writeConcern"] = {"w": 0} # type: ignore[assignment]
@ -721,43 +721,6 @@ class _ClientBulk:
self.idx_offset += len(to_send_ops)
def execute_command_unack_ordered(
self,
conn: Connection,
) -> None:
"""Execute commands with OP_MSG and w=0 WriteConcern, ordered."""
full_result: MutableMapping[str, Any] = {
"anySuccessful": False,
"error": None,
"writeErrors": [],
"writeConcernErrors": [],
"nInserted": 0,
"nUpserted": 0,
"nMatched": 0,
"nModified": 0,
"nDeleted": 0,
"insertResults": {},
"updateResults": {},
"deleteResults": {},
}
# Ordered bulk writes have to be acknowledged so that we stop
# processing at the first error, even when the application
# specified unacknowledged writeConcern.
initial_write_concern = WriteConcern()
op_id = _randint()
try:
self._execute_command(
initial_write_concern,
None,
conn,
op_id,
False,
full_result,
self.write_concern,
)
except OperationFailure:
pass
def execute_no_results(
self,
conn: Connection,
@ -773,9 +736,7 @@ class _ClientBulk:
"Cannot set bypass_document_validation with unacknowledged write concern"
)
if self.ordered:
return self.execute_command_unack_ordered(conn)
return self.execute_command_unack_unordered(conn)
return self.execute_command_unack(conn)
def execute(
self,

View File

@ -216,7 +216,7 @@ class MongoClient(common.BaseObject, Generic[_DocumentType]):
<https://en.wikipedia.org/wiki/TXT_record>`_. See the
`Initial DNS Seedlist Discovery spec
<https://github.com/mongodb/specifications/blob/master/source/
initial-dns-seedlist-discovery/initial-dns-seedlist-discovery.rst>`_
initial-dns-seedlist-discovery/initial-dns-seedlist-discovery.md>`_
for more details. Note that the use of SRV URIs implicitly enables
TLS support. Pass tls=false in the URI to override.
@ -365,7 +365,7 @@ class MongoClient(common.BaseObject, Generic[_DocumentType]):
:meth:`~pymongo.collection.Collection.aggregate` using the ``$out``
pipeline operator and any operation with an unacknowledged write
concern (e.g. {w: 0})). See
https://github.com/mongodb/specifications/blob/master/source/retryable-writes/retryable-writes.rst
https://github.com/mongodb/specifications/blob/master/source/retryable-writes/retryable-writes.md
- `retryReads`: (boolean) Whether supported read operations
executed within this MongoClient will be retried once after a
network error. Defaults to ``True``.
@ -392,7 +392,7 @@ class MongoClient(common.BaseObject, Generic[_DocumentType]):
transient errors such as network failures, database upgrades, and
replica set failovers. For an exact definition of which errors
trigger a retry, see the `retryable reads specification
<https://github.com/mongodb/specifications/blob/master/source/retryable-reads/retryable-reads.rst>`_.
<https://github.com/mongodb/specifications/blob/master/source/retryable-reads/retryable-reads.md>`_.
- `compressors`: Comma separated list of compressors for wire
protocol compression. The list is used to negotiate a compressor

View File

@ -375,7 +375,7 @@ class TestSCRAMSHA1(AsyncIntegrationTest):
await db.command("dbstats")
# https://github.com/mongodb/specifications/blob/master/source/auth/auth.rst#scram-sha-256-and-mechanism-negotiation
# https://github.com/mongodb/specifications/blob/master/source/auth/auth.md#scram-sha-256-and-mechanism-negotiation
class TestSCRAM(AsyncIntegrationTest):
@async_client_context.require_auth
@async_client_context.require_version_min(3, 7, 2)

View File

@ -1610,7 +1610,7 @@ class TestGCPEncryption(AzureGCPEncryptionTestMixin, AsyncEncryptionIntegrationT
return await self._test_automatic(expected_document_extjson, {"secret_gcp": "string0"})
# https://github.com/mongodb/specifications/blob/master/source/client-side-encryption/tests/README.rst#deadlock-tests
# https://github.com/mongodb/specifications/blob/master/source/client-side-encryption/tests/README.md#deadlock-tests
class TestDeadlockProse(AsyncEncryptionIntegrationTest):
async def asyncSetUp(self):
self.client_test = await self.async_rs_or_single_client(
@ -1837,7 +1837,7 @@ class TestDeadlockProse(AsyncEncryptionIntegrationTest):
self.assertEqual(len(self.topology_listener.results["opened"]), 1)
# https://github.com/mongodb/specifications/blob/master/source/client-side-encryption/tests/README.rst#14-decryption-events
# https://github.com/mongodb/specifications/blob/master/source/client-side-encryption/tests/README.md#14-decryption-events
class TestDecryptProse(AsyncEncryptionIntegrationTest):
async def asyncSetUp(self):
self.client = async_client_context.client
@ -1909,7 +1909,7 @@ class TestDecryptProse(AsyncEncryptionIntegrationTest):
self.assertEqual(event.reply["cursor"]["firstBatch"][0]["encrypted"], self.cipher_text)
# https://github.com/mongodb/specifications/blob/master/source/client-side-encryption/tests/README.rst#bypass-spawning-mongocryptd
# https://github.com/mongodb/specifications/blob/master/source/client-side-encryption/tests/README.md#bypass-spawning-mongocryptd
class TestBypassSpawningMongocryptdProse(AsyncEncryptionIntegrationTest):
@unittest.skipIf(
os.environ.get("TEST_CRYPT_SHARED"),
@ -1990,7 +1990,7 @@ class TestBypassSpawningMongocryptdProse(AsyncEncryptionIntegrationTest):
with self.assertRaises(ServerSelectionTimeoutError):
await no_mongocryptd_client.db.command("ping")
# https://github.com/mongodb/specifications/blob/master/source/client-side-encryption/tests/README.rst#20-bypass-creating-mongocryptd-client-when-shared-library-is-loaded
# https://github.com/mongodb/specifications/blob/master/source/client-side-encryption/tests/README.md#20-bypass-creating-mongocryptd-client-when-shared-library-is-loaded
@unittest.skipUnless(os.environ.get("TEST_CRYPT_SHARED"), "crypt_shared lib is not installed")
async def test_client_via_loading_shared_library(self):
connection_established = False
@ -2066,7 +2066,7 @@ class TestKmsTLSProse(AsyncEncryptionIntegrationTest):
await self.client_encrypted.create_data_key("aws", master_key=key)
# https://github.com/mongodb/specifications/blob/master/source/client-side-encryption/tests/README.rst#kms-tls-options-tests
# https://github.com/mongodb/specifications/blob/master/source/client-side-encryption/tests/README.md#kms-tls-options-tests
class TestKmsTLSOptions(AsyncEncryptionIntegrationTest):
@unittest.skipUnless(any(AWS_CREDS.values()), "AWS environment credentials are not set")
async def asyncSetUp(self):
@ -2272,7 +2272,7 @@ class TestKmsTLSOptions(AsyncEncryptionIntegrationTest):
await self.client_encryption_with_names.create_data_key("kmip:with_tls")
# https://github.com/mongodb/specifications/blob/50e26fe/source/client-side-encryption/tests/README.rst#unique-index-on-keyaltnames
# https://github.com/mongodb/specifications/blob/50e26fe/source/client-side-encryption/tests/README.md#unique-index-on-keyaltnames
class TestUniqueIndexOnKeyAltNamesProse(AsyncEncryptionIntegrationTest):
async def asyncSetUp(self):
self.client = async_client_context.client
@ -2303,7 +2303,7 @@ class TestUniqueIndexOnKeyAltNamesProse(AsyncEncryptionIntegrationTest):
assert key_doc["keyAltNames"] == ["def"]
# https://github.com/mongodb/specifications/blob/d4c9432/source/client-side-encryption/tests/README.rst#explicit-encryption
# https://github.com/mongodb/specifications/blob/d4c9432/source/client-side-encryption/tests/README.md#explicit-encryption
class TestExplicitQueryableEncryption(AsyncEncryptionIntegrationTest):
@async_client_context.require_no_standalone
@async_client_context.require_version_min(7, 0, -1)
@ -2423,7 +2423,7 @@ class TestExplicitQueryableEncryption(AsyncEncryptionIntegrationTest):
self.assertEqual(decrypted, val)
# https://github.com/mongodb/specifications/blob/072601/source/client-side-encryption/tests/README.rst#rewrap
# https://github.com/mongodb/specifications/blob/072601/source/client-side-encryption/tests/README.md#rewrap
class TestRewrapWithSeparateClientEncryption(AsyncEncryptionIntegrationTest):
MASTER_KEYS: Mapping[str, Mapping[str, Any]] = {
"aws": {
@ -2505,7 +2505,7 @@ class TestRewrapWithSeparateClientEncryption(AsyncEncryptionIntegrationTest):
)
# https://github.com/mongodb/specifications/blob/5cf3ed/source/client-side-encryption/tests/README.rst#on-demand-aws-credentials
# https://github.com/mongodb/specifications/blob/5cf3ed/source/client-side-encryption/tests/README.md#on-demand-aws-credentials
class TestOnDemandAWSCredentials(AsyncEncryptionIntegrationTest):
async def asyncSetUp(self):
await super().asyncSetUp()
@ -2869,7 +2869,7 @@ class TestRangeQueryDefaultsProse(AsyncEncryptionIntegrationTest):
assert len(payload) > len(self.payload_defaults)
# https://github.com/mongodb/specifications/blob/master/source/client-side-encryption/tests/README.rst#automatic-data-encryption-keys
# https://github.com/mongodb/specifications/blob/master/source/client-side-encryption/tests/README.md#automatic-data-encryption-keys
class TestAutomaticDecryptionKeys(AsyncEncryptionIntegrationTest):
@async_client_context.require_no_standalone
@async_client_context.require_version_min(7, 0, -1)

View File

@ -14,7 +14,7 @@
"""Unified test format runner.
https://github.com/mongodb/specifications/blob/master/source/unified-test-format/unified-test-format.rst
https://github.com/mongodb/specifications/blob/master/source/unified-test-format/unified-test-format.md
"""
from __future__ import annotations
@ -431,7 +431,7 @@ class UnifiedSpecTestMixinV1(AsyncIntegrationTest):
"""Mixin class to run test cases from test specification files.
Assumes that tests conform to the `unified test format
<https://github.com/mongodb/specifications/blob/master/source/unified-test-format/unified-test-format.rst>`_.
<https://github.com/mongodb/specifications/blob/master/source/unified-test-format/unified-test-format.md>`_.
Specification of the test suite being currently run is available as
a class attribute ``TEST_SPEC``.

View File

@ -80,7 +80,7 @@
},
{
"description": "should accept generic mechanism property (GSSAPI)",
"uri": "mongodb://user%40DOMAIN.COM@localhost/?authMechanism=GSSAPI&authMechanismProperties=SERVICE_NAME:other,CANONICALIZE_HOST_NAME:true",
"uri": "mongodb://user%40DOMAIN.COM@localhost/?authMechanism=GSSAPI&authMechanismProperties=SERVICE_NAME:other,CANONICALIZE_HOST_NAME:forward,SERVICE_HOST:example.com",
"valid": true,
"credential": {
"username": "user@DOMAIN.COM",
@ -89,10 +89,46 @@
"mechanism": "GSSAPI",
"mechanism_properties": {
"SERVICE_NAME": "other",
"CANONICALIZE_HOST_NAME": true
"SERVICE_HOST": "example.com",
"CANONICALIZE_HOST_NAME": "forward"
}
}
},
{
"description": "should accept forwardAndReverse hostname canonicalization (GSSAPI)",
"uri": "mongodb://user%40DOMAIN.COM@localhost/?authMechanism=GSSAPI&authMechanismProperties=SERVICE_NAME:other,CANONICALIZE_HOST_NAME:forwardAndReverse",
"valid": true,
"credential": {
"username": "user@DOMAIN.COM",
"password": null,
"source": "$external",
"mechanism": "GSSAPI",
"mechanism_properties": {
"SERVICE_NAME": "other",
"CANONICALIZE_HOST_NAME": "forwardAndReverse"
}
}
},
{
"description": "should accept no hostname canonicalization (GSSAPI)",
"uri": "mongodb://user%40DOMAIN.COM@localhost/?authMechanism=GSSAPI&authMechanismProperties=SERVICE_NAME:other,CANONICALIZE_HOST_NAME:none",
"valid": true,
"credential": {
"username": "user@DOMAIN.COM",
"password": null,
"source": "$external",
"mechanism": "GSSAPI",
"mechanism_properties": {
"SERVICE_NAME": "other",
"CANONICALIZE_HOST_NAME": "none"
}
}
},
{
"description": "must raise an error when the hostname canonicalization is invalid",
"uri": "mongodb://user%40DOMAIN.COM@localhost/?authMechanism=GSSAPI&authMechanismProperties=SERVICE_NAME:other,CANONICALIZE_HOST_NAME:invalid",
"valid": false
},
{
"description": "should accept the password (GSSAPI)",
"uri": "mongodb://user%40DOMAIN.COM:password@localhost/?authMechanism=GSSAPI&authSource=$external",
@ -127,47 +163,6 @@
"uri": "mongodb://localhost/?authMechanism=GSSAPI",
"valid": false
},
{
"description": "should recognize the mechanism (MONGODB-CR)",
"uri": "mongodb://user:password@localhost/?authMechanism=MONGODB-CR",
"valid": true,
"credential": {
"username": "user",
"password": "password",
"source": "admin",
"mechanism": "MONGODB-CR",
"mechanism_properties": null
}
},
{
"description": "should use the database when no authSource is specified (MONGODB-CR)",
"uri": "mongodb://user:password@localhost/foo?authMechanism=MONGODB-CR",
"valid": true,
"credential": {
"username": "user",
"password": "password",
"source": "foo",
"mechanism": "MONGODB-CR",
"mechanism_properties": null
}
},
{
"description": "should use the authSource when specified (MONGODB-CR)",
"uri": "mongodb://user:password@localhost/foo?authMechanism=MONGODB-CR&authSource=bar",
"valid": true,
"credential": {
"username": "user",
"password": "password",
"source": "bar",
"mechanism": "MONGODB-CR",
"mechanism_properties": null
}
},
{
"description": "should throw an exception if no username is supplied (MONGODB-CR)",
"uri": "mongodb://localhost/?authMechanism=MONGODB-CR",
"valid": false
},
{
"description": "should recognize the mechanism (MONGODB-X509)",
"uri": "mongodb://CN%3DmyName%2COU%3DmyOrgUnit%2CO%3DmyOrg%2CL%3DmyLocality%2CST%3DmyState%2CC%3DmyCountry@localhost/?authMechanism=MONGODB-X509",
@ -474,14 +469,14 @@
}
},
{
"description": "should throw an exception if username and password is specified for test environment (MONGODB-OIDC)",
"description": "should throw an exception if supplied a password (MONGODB-OIDC)",
"uri": "mongodb://user:pass@localhost/?authMechanism=MONGODB-OIDC&authMechanismProperties=ENVIRONMENT:test",
"valid": false,
"credential": null
},
{
"description": "should throw an exception if username is specified for test environment (MONGODB-OIDC)",
"uri": "mongodb://principalName@localhost/?authMechanism=MONGODB-OIDC&ENVIRONMENT:test",
"description": "should throw an exception if username is specified for test (MONGODB-OIDC)",
"uri": "mongodb://principalName@localhost/?authMechanism=MONGODB-OIDC&authMechanismProperties=ENVIRONMENT:test",
"valid": false,
"credential": null
},
@ -492,11 +487,17 @@
"credential": null
},
{
"description": "should throw an exception if neither provider nor callbacks specified (MONGODB-OIDC)",
"description": "should throw an exception if neither environment nor callbacks specified (MONGODB-OIDC)",
"uri": "mongodb://localhost/?authMechanism=MONGODB-OIDC",
"valid": false,
"credential": null
},
{
"description": "should throw an exception when unsupported auth property is specified (MONGODB-OIDC)",
"uri": "mongodb://localhost/?authMechanism=MONGODB-OIDC&authMechanismProperties=UnsupportedProperty:unexisted",
"valid": false,
"credential": null
},
{
"description": "should recognise the mechanism with azure provider (MONGODB-OIDC)",
"uri": "mongodb://localhost/?authMechanism=MONGODB-OIDC&authMechanismProperties=ENVIRONMENT:azure,TOKEN_RESOURCE:foo",
@ -627,4 +628,4 @@
"credential": null
}
]
}
}

View File

@ -220,29 +220,8 @@
"options": null
},
{
"description": "Escaped user info and database (MONGODB-CR)",
"uri": "mongodb://%24am:f%3Azzb%40z%2Fz%3D@127.0.0.1/admin%3F?authMechanism=MONGODB-CR",
"valid": true,
"warning": false,
"hosts": [
{
"type": "ipv4",
"host": "127.0.0.1",
"port": null
}
],
"auth": {
"username": "$am",
"password": "f:zzb@z/z=",
"db": "admin?"
},
"options": {
"authmechanism": "MONGODB-CR"
}
},
{
"description": "Subdelimiters in user/pass don't need escaping (MONGODB-CR)",
"uri": "mongodb://!$&'()*+,;=:!$&'()*+,;=@127.0.0.1/admin?authMechanism=MONGODB-CR",
"description": "Subdelimiters in user/pass don't need escaping (PLAIN)",
"uri": "mongodb://!$&'()*+,;=:!$&'()*+,;=@127.0.0.1/admin?authMechanism=PLAIN",
"valid": true,
"warning": false,
"hosts": [
@ -258,7 +237,7 @@
"db": "admin"
},
"options": {
"authmechanism": "MONGODB-CR"
"authmechanism": "PLAIN"
}
},
{
@ -284,7 +263,7 @@
},
{
"description": "Escaped username (GSSAPI)",
"uri": "mongodb://user%40EXAMPLE.COM:secret@localhost/?authMechanismProperties=SERVICE_NAME:other,CANONICALIZE_HOST_NAME:true&authMechanism=GSSAPI",
"uri": "mongodb://user%40EXAMPLE.COM:secret@localhost/?authMechanismProperties=SERVICE_NAME:other,CANONICALIZE_HOST_NAME:forward,SERVICE_HOST:example.com&authMechanism=GSSAPI",
"valid": true,
"warning": false,
"hosts": [
@ -303,7 +282,8 @@
"authmechanism": "GSSAPI",
"authmechanismproperties": {
"SERVICE_NAME": "other",
"CANONICALIZE_HOST_NAME": true
"SERVICE_HOST": "example.com",
"CANONICALIZE_HOST_NAME": "forward"
}
}
},

View File

@ -2,7 +2,7 @@
"tests": [
{
"description": "Option names are normalized to lowercase",
"uri": "mongodb://alice:secret@example.com/admin?AUTHMechanism=MONGODB-CR",
"uri": "mongodb://alice:secret@example.com/admin?AUTHMechanism=PLAIN",
"valid": true,
"warning": false,
"hosts": [
@ -18,7 +18,7 @@
"db": "admin"
},
"options": {
"authmechanism": "MONGODB-CR"
"authmechanism": "PLAIN"
}
},
{

View File

@ -218,50 +218,19 @@ class TestHandshake(unittest.TestCase):
request.ok(
"ismaster",
True,
saslSupportedMechs=["SCRAM-SHA-256"],
# Unsupported auth mech should be ignored.
saslSupportedMechs=["SCRAM-SHA-256", "does_not_exist"],
speculativeAuthenticate=auth,
minWireVersion=2,
maxWireVersion=MIN_SUPPORTED_WIRE_VERSION,
)
# Authentication should immediately fail with:
# OperationFailure: Server returned an invalid nonce.
with self.assertRaises(OperationFailure):
with self.assertRaises(OperationFailure) as cm:
future()
self.assertEqual(str(cm.exception), "Server returned an invalid nonce.")
return
def test_client_handshake_saslSupportedMechs_unknown(self):
server = MockupDB()
server.run()
self.addCleanup(server.stop)
primary_response = OpReply(
"ismaster",
True,
minWireVersion=2,
maxWireVersion=MIN_SUPPORTED_WIRE_VERSION,
saslSupportedMechs=["SCRAM-SHA-256", "does_not_exist"],
)
client = MongoClient(
server.uri, authmechanism="PLAIN", username="username", password="password"
)
self.addCleanup(client.close)
# New monitoring connections send data during handshake.
heartbeat = server.receives("ismaster")
heartbeat.ok(primary_response)
future = go(client.db.command, "whatever")
for request in server:
if request.matches("ismaster"):
request.ok(primary_response)
elif request.matches("saslStart"):
request.ok("saslStart", True, conversationId=1, payload=b"", done=True, ok=1)
else:
request.ok()
future()
return
def test_handshake_load_balanced(self):
self.hello_with_option_helper(OpMsg, loadBalanced=True)
with self.assertRaisesRegex(AssertionError, "does not match"):

View File

@ -373,7 +373,7 @@ class TestSCRAMSHA1(IntegrationTest):
db.command("dbstats")
# https://github.com/mongodb/specifications/blob/master/source/auth/auth.rst#scram-sha-256-and-mechanism-negotiation
# https://github.com/mongodb/specifications/blob/master/source/auth/auth.md#scram-sha-256-and-mechanism-negotiation
class TestSCRAM(IntegrationTest):
@client_context.require_auth
@client_context.require_version_min(3, 7, 2)

View File

@ -128,7 +128,7 @@ class TestDBRef(unittest.TestCase):
self.assertNotEqual(hash(dbref_1a), hash(dbref_2a))
# https://github.com/mongodb/specifications/blob/master/source/dbref.rst#test-plan
# https://github.com/mongodb/specifications/blob/master/source/dbref/dbref.md#test-plan
class TestDBRefSpec(unittest.TestCase):
def test_decoding_1_2_3(self):
doc: Any

View File

@ -1604,7 +1604,7 @@ class TestGCPEncryption(AzureGCPEncryptionTestMixin, EncryptionIntegrationTest):
return self._test_automatic(expected_document_extjson, {"secret_gcp": "string0"})
# https://github.com/mongodb/specifications/blob/master/source/client-side-encryption/tests/README.rst#deadlock-tests
# https://github.com/mongodb/specifications/blob/master/source/client-side-encryption/tests/README.md#deadlock-tests
class TestDeadlockProse(EncryptionIntegrationTest):
def setUp(self):
self.client_test = self.rs_or_single_client(
@ -1829,7 +1829,7 @@ class TestDeadlockProse(EncryptionIntegrationTest):
self.assertEqual(len(self.topology_listener.results["opened"]), 1)
# https://github.com/mongodb/specifications/blob/master/source/client-side-encryption/tests/README.rst#14-decryption-events
# https://github.com/mongodb/specifications/blob/master/source/client-side-encryption/tests/README.md#14-decryption-events
class TestDecryptProse(EncryptionIntegrationTest):
def setUp(self):
self.client = client_context.client
@ -1901,7 +1901,7 @@ class TestDecryptProse(EncryptionIntegrationTest):
self.assertEqual(event.reply["cursor"]["firstBatch"][0]["encrypted"], self.cipher_text)
# https://github.com/mongodb/specifications/blob/master/source/client-side-encryption/tests/README.rst#bypass-spawning-mongocryptd
# https://github.com/mongodb/specifications/blob/master/source/client-side-encryption/tests/README.md#bypass-spawning-mongocryptd
class TestBypassSpawningMongocryptdProse(EncryptionIntegrationTest):
@unittest.skipIf(
os.environ.get("TEST_CRYPT_SHARED"),
@ -1982,7 +1982,7 @@ class TestBypassSpawningMongocryptdProse(EncryptionIntegrationTest):
with self.assertRaises(ServerSelectionTimeoutError):
no_mongocryptd_client.db.command("ping")
# https://github.com/mongodb/specifications/blob/master/source/client-side-encryption/tests/README.rst#20-bypass-creating-mongocryptd-client-when-shared-library-is-loaded
# https://github.com/mongodb/specifications/blob/master/source/client-side-encryption/tests/README.md#20-bypass-creating-mongocryptd-client-when-shared-library-is-loaded
@unittest.skipUnless(os.environ.get("TEST_CRYPT_SHARED"), "crypt_shared lib is not installed")
def test_client_via_loading_shared_library(self):
connection_established = False
@ -2058,7 +2058,7 @@ class TestKmsTLSProse(EncryptionIntegrationTest):
self.client_encrypted.create_data_key("aws", master_key=key)
# https://github.com/mongodb/specifications/blob/master/source/client-side-encryption/tests/README.rst#kms-tls-options-tests
# https://github.com/mongodb/specifications/blob/master/source/client-side-encryption/tests/README.md#kms-tls-options-tests
class TestKmsTLSOptions(EncryptionIntegrationTest):
@unittest.skipUnless(any(AWS_CREDS.values()), "AWS environment credentials are not set")
def setUp(self):
@ -2264,7 +2264,7 @@ class TestKmsTLSOptions(EncryptionIntegrationTest):
self.client_encryption_with_names.create_data_key("kmip:with_tls")
# https://github.com/mongodb/specifications/blob/50e26fe/source/client-side-encryption/tests/README.rst#unique-index-on-keyaltnames
# https://github.com/mongodb/specifications/blob/50e26fe/source/client-side-encryption/tests/README.md#unique-index-on-keyaltnames
class TestUniqueIndexOnKeyAltNamesProse(EncryptionIntegrationTest):
def setUp(self):
self.client = client_context.client
@ -2293,7 +2293,7 @@ class TestUniqueIndexOnKeyAltNamesProse(EncryptionIntegrationTest):
assert key_doc["keyAltNames"] == ["def"]
# https://github.com/mongodb/specifications/blob/d4c9432/source/client-side-encryption/tests/README.rst#explicit-encryption
# https://github.com/mongodb/specifications/blob/d4c9432/source/client-side-encryption/tests/README.md#explicit-encryption
class TestExplicitQueryableEncryption(EncryptionIntegrationTest):
@client_context.require_no_standalone
@client_context.require_version_min(7, 0, -1)
@ -2407,7 +2407,7 @@ class TestExplicitQueryableEncryption(EncryptionIntegrationTest):
self.assertEqual(decrypted, val)
# https://github.com/mongodb/specifications/blob/072601/source/client-side-encryption/tests/README.rst#rewrap
# https://github.com/mongodb/specifications/blob/072601/source/client-side-encryption/tests/README.md#rewrap
class TestRewrapWithSeparateClientEncryption(EncryptionIntegrationTest):
MASTER_KEYS: Mapping[str, Mapping[str, Any]] = {
"aws": {
@ -2489,7 +2489,7 @@ class TestRewrapWithSeparateClientEncryption(EncryptionIntegrationTest):
)
# https://github.com/mongodb/specifications/blob/5cf3ed/source/client-side-encryption/tests/README.rst#on-demand-aws-credentials
# https://github.com/mongodb/specifications/blob/5cf3ed/source/client-side-encryption/tests/README.md#on-demand-aws-credentials
class TestOnDemandAWSCredentials(EncryptionIntegrationTest):
def setUp(self):
super().setUp()
@ -2851,7 +2851,7 @@ class TestRangeQueryDefaultsProse(EncryptionIntegrationTest):
assert len(payload) > len(self.payload_defaults)
# https://github.com/mongodb/specifications/blob/master/source/client-side-encryption/tests/README.rst#automatic-data-encryption-keys
# https://github.com/mongodb/specifications/blob/master/source/client-side-encryption/tests/README.md#automatic-data-encryption-keys
class TestAutomaticDecryptionKeys(EncryptionIntegrationTest):
@client_context.require_no_standalone
@client_context.require_version_min(7, 0, -1)

View File

@ -142,7 +142,7 @@ class TestStreamingProtocol(IntegrationTest):
@client_context.require_failCommand_appName
def test_monitor_waits_after_server_check_error(self):
# This test implements:
# https://github.com/mongodb/specifications/blob/6c5b2ac/source/server-discovery-and-monitoring/server-discovery-and-monitoring-tests.rst#monitors-sleep-at-least-minheartbeatfreqencyms-between-checks
# https://github.com/mongodb/specifications/blob/master/source/server-discovery-and-monitoring/server-discovery-and-monitoring-tests.md#monitors-sleep-at-least-minheartbeatfreqencyms-between-checks
fail_hello = {
"mode": {"times": 5},
"data": {

View File

@ -142,7 +142,6 @@ class TestURI(unittest.TestCase):
self.assertEqual({"fsync": True}, split_options("fsync=true"))
self.assertEqual({"fsync": False}, split_options("fsync=false"))
self.assertEqual({"authmechanism": "GSSAPI"}, split_options("authMechanism=GSSAPI"))
self.assertEqual({"authmechanism": "MONGODB-CR"}, split_options("authMechanism=MONGODB-CR"))
self.assertEqual(
{"authmechanism": "SCRAM-SHA-1"}, split_options("authMechanism=SCRAM-SHA-1")
)
@ -295,30 +294,30 @@ class TestURI(unittest.TestCase):
# Various authentication tests
res = copy.deepcopy(orig)
res["options"] = {"authmechanism": "MONGODB-CR"}
res["options"] = {"authmechanism": "SCRAM-SHA-256"}
res["username"] = "user"
res["password"] = "password"
self.assertEqual(
res, parse_uri("mongodb://user:password@localhost/?authMechanism=MONGODB-CR")
res, parse_uri("mongodb://user:password@localhost/?authMechanism=SCRAM-SHA-256")
)
res = copy.deepcopy(orig)
res["options"] = {"authmechanism": "MONGODB-CR", "authsource": "bar"}
res["options"] = {"authmechanism": "SCRAM-SHA-256", "authsource": "bar"}
res["username"] = "user"
res["password"] = "password"
res["database"] = "foo"
self.assertEqual(
res,
parse_uri(
"mongodb://user:password@localhost/foo?authSource=bar;authMechanism=MONGODB-CR"
"mongodb://user:password@localhost/foo?authSource=bar;authMechanism=SCRAM-SHA-256"
),
)
res = copy.deepcopy(orig)
res["options"] = {"authmechanism": "MONGODB-CR"}
res["options"] = {"authmechanism": "SCRAM-SHA-256"}
res["username"] = "user"
res["password"] = ""
self.assertEqual(res, parse_uri("mongodb://user:@localhost/?authMechanism=MONGODB-CR"))
self.assertEqual(res, parse_uri("mongodb://user:@localhost/?authMechanism=SCRAM-SHA-256"))
res = copy.deepcopy(orig)
res["username"] = "user@domain.com"

View File

@ -14,7 +14,7 @@
"""Unified test format runner.
https://github.com/mongodb/specifications/blob/master/source/unified-test-format/unified-test-format.rst
https://github.com/mongodb/specifications/blob/master/source/unified-test-format/unified-test-format.md
"""
from __future__ import annotations
@ -431,7 +431,7 @@ class UnifiedSpecTestMixinV1(IntegrationTest):
"""Mixin class to run test cases from test specification files.
Assumes that tests conform to the `unified test format
<https://github.com/mongodb/specifications/blob/master/source/unified-test-format/unified-test-format.rst>`_.
<https://github.com/mongodb/specifications/blob/master/source/unified-test-format/unified-test-format.md>`_.
Specification of the test suite being currently run is available as
a class attribute ``TEST_SPEC``.

View File

@ -14,7 +14,7 @@
"""Shared utility functions and constants for the unified test format runner.
https://github.com/mongodb/specifications/blob/master/source/unified-test-format/unified-test-format.rst
https://github.com/mongodb/specifications/blob/master/source/unified-test-format/unified-test-format.md
"""
from __future__ import annotations