Skip to content

Commit

Permalink
Merge branch 'master' into PYTHON-4927
Browse files Browse the repository at this point in the history
  • Loading branch information
NoahStapp authored Nov 1, 2024
2 parents 9c0c54b + 9f53f29 commit 606eaa6
Show file tree
Hide file tree
Showing 34 changed files with 262 additions and 333 deletions.
55 changes: 55 additions & 0 deletions .github/workflows/create-release-branch.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
name: Create Release Branch

on:
workflow_dispatch:
inputs:
branch_name:
description: The name of the new branch
required: true
version:
description: The version to set on the branch
required: true
base_ref:
description: The base reference for the branch
push_changes:
description: Whether to push the changes
default: "true"

concurrency:
group: create-branch-${{ github.ref }}
cancel-in-progress: true

defaults:
run:
shell: bash -eux {0}

jobs:
create-branch:
environment: release
runs-on: ubuntu-latest
permissions:
id-token: write
contents: write
outputs:
version: ${{ steps.pre-publish.outputs.version }}
steps:
- uses: mongodb-labs/drivers-github-tools/secure-checkout@v2
with:
app_id: ${{ vars.APP_ID }}
private_key: ${{ secrets.APP_PRIVATE_KEY }}
- uses: mongodb-labs/drivers-github-tools/setup@v2
with:
aws_role_arn: ${{ secrets.AWS_ROLE_ARN }}
aws_region_name: ${{ vars.AWS_REGION_NAME }}
aws_secret_id: ${{ secrets.AWS_SECRET_ID }}
artifactory_username: ${{ vars.ARTIFACTORY_USERNAME }}
- uses: mongodb-labs/drivers-github-tools/create-branch@v2
id: create-branch
with:
branch_name: ${{ inputs.branch_name }}
version: ${{ inputs.version }}
base_ref: ${{ inputs.base_ref }}
push_changes: ${{ inputs.push_changes }}
version_bump_script: hatch version
evergreen_project: mongo-python-driver-release
release_workflow_path: ./.github/workflows/release-python.yml
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
45 changes: 24 additions & 21 deletions bson/json_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
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):
Expand Down Expand Up @@ -617,25 +617,28 @@ def _parse_canonical_datetime(
raise TypeError(f"Bad $date, extra field(s): {doc}")
# mongoexport 2.6 and newer
if isinstance(dtm, str):
# Parse offset
if dtm[-1] == "Z":
dt = dtm[:-1]
offset = "Z"
elif dtm[-6] in ("+", "-") and dtm[-3] == ":":
# (+|-)HH:MM
dt = dtm[:-6]
offset = dtm[-6:]
elif dtm[-5] in ("+", "-"):
# (+|-)HHMM
dt = dtm[:-5]
offset = dtm[-5:]
elif dtm[-3] in ("+", "-"):
# (+|-)HH
dt = dtm[:-3]
offset = dtm[-3:]
else:
dt = dtm
offset = ""
try:
# Parse offset
if dtm[-1] == "Z":
dt = dtm[:-1]
offset = "Z"
elif dtm[-6] in ("+", "-") and dtm[-3] == ":":
# (+|-)HH:MM
dt = dtm[:-6]
offset = dtm[-6:]
elif dtm[-5] in ("+", "-"):
# (+|-)HHMM
dt = dtm[:-5]
offset = dtm[-5:]
elif dtm[-3] in ("+", "-"):
# (+|-)HH
dt = dtm[:-3]
offset = dtm[-3:]
else:
dt = dtm
offset = ""
except IndexError as exc:
raise ValueError(f"time data {dtm!r} does not match ISO-8601 datetime format") from exc

# Parse the optional factional seconds portion.
dot_index = dt.rfind(".")
Expand Down Expand Up @@ -848,7 +851,7 @@ def _encode_datetimems(obj: Any, json_options: JSONOptions) -> dict:
):
return _encode_datetime(obj.as_datetime(), json_options)
elif json_options.datetime_representation == DatetimeRepresentation.LEGACY:
return {"$date": str(int(obj))}
return {"$date": int(obj)}
return {"$date": {"$numberLong": str(int(obj))}}


Expand Down
2 changes: 1 addition & 1 deletion doc/api/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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::
Expand Down
18 changes: 14 additions & 4 deletions doc/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -23,6 +24,15 @@ 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.
- Fixed a bug in :const:`bson.json_util.dumps` where a :class:`bson.datetime_ms.DatetimeMS` would
be incorrectly encoded as ``'{"$date": "X"}'`` instead of ``'{"$date": X}'`` when using the
legacy MongoDB Extended JSON datetime representation.
- Fixed a bug where :const:`bson.json_util.loads` would raise an IndexError when parsing an invalid
``"$date"`` instead of a ValueError.

Issues Resolved
...............
Expand Down Expand Up @@ -1022,7 +1032,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)
--------------------------------------
Expand Down Expand Up @@ -1557,7 +1567,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
Expand All @@ -1581,7 +1591,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
Expand Down Expand Up @@ -1943,7 +1953,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
Expand Down
2 changes: 1 addition & 1 deletion doc/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@
# 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/",
Expand Down
2 changes: 1 addition & 1 deletion doc/developer/periodic_executor.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
21 changes: 1 addition & 20 deletions doc/examples/authentication.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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:[email protected]/?authSource=the_database&authMechanism=MONGODB-CR"
>>> client = MongoClient(uri)

Default Authentication Mechanism
--------------------------------

Expand Down Expand Up @@ -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:[email protected]/?authMechanism=PLAIN"
Expand Down
2 changes: 1 addition & 1 deletion doc/examples/uuid.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions doc/migrate-to-pymongo4.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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
..........................................
Expand Down
16 changes: 0 additions & 16 deletions pymongo/asynchronous/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -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]
Expand Down
49 changes: 5 additions & 44 deletions pymongo/asynchronous/client_bulk.py
Original file line number Diff line number Diff line change
Expand Up @@ -681,11 +681,11 @@ async def retryable_bulk(
_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
Expand All @@ -704,8 +704,8 @@ async def execute_command_unack_unordered(
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]
Expand All @@ -723,43 +723,6 @@ async def execute_command_unack_unordered(

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,
Expand All @@ -775,9 +738,7 @@ async def execute_no_results(
"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,
Expand Down
Loading

0 comments on commit 606eaa6

Please sign in to comment.