Skip to content

Commit 2a80cda

Browse files
committed
Merge branch 'master' of github.com:mongodb/mongo-python-driver
2 parents ccc5dfc + 2759379 commit 2a80cda

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+711
-653
lines changed

.github/workflows/codeql.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ jobs:
4646

4747
# Initializes the CodeQL tools for scanning.
4848
- name: Initialize CodeQL
49-
uses: github/codeql-action/init@60168efe1c415ce0f5521ea06d5c2062adbeed1b # v3
49+
uses: github/codeql-action/init@ff0a06e83cb2de871e5a09832bc6a81e7276941f # v3
5050
with:
5151
languages: ${{ matrix.language }}
5252
build-mode: ${{ matrix.build-mode }}
@@ -63,6 +63,6 @@ jobs:
6363
pip install -e .
6464
6565
- name: Perform CodeQL Analysis
66-
uses: github/codeql-action/analyze@60168efe1c415ce0f5521ea06d5c2062adbeed1b # v3
66+
uses: github/codeql-action/analyze@ff0a06e83cb2de871e5a09832bc6a81e7276941f # v3
6767
with:
6868
category: "/language:${{matrix.language}}"

.github/workflows/zizmor.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ jobs:
2626
env:
2727
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
2828
- name: Upload SARIF file
29-
uses: github/codeql-action/upload-sarif@60168efe1c415ce0f5521ea06d5c2062adbeed1b # v3
29+
uses: github/codeql-action/upload-sarif@ff0a06e83cb2de871e5a09832bc6a81e7276941f # v3
3030
with:
3131
sarif_file: results.sarif
3232
category: zizmor

CONTRIBUTING.md

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -384,7 +384,14 @@ If you are running one of the `no-responder` tests, omit the `run-server` step.
384384
- Regenerate the test variants and tasks using `pre-commit run --all-files generate-config`.
385385
- Make sure to add instructions for running the test suite to `CONTRIBUTING.md`.
386386

387-
## Re-sync Spec Tests
387+
## Specification Tests
388+
389+
The MongoDB [specifications repository](https://github.com/mongodb/specifications)
390+
holds in progress and completed specifications for features of MongoDB, drivers,
391+
and associated products. PyMongo supports the [Unified Test Format](https://jira.mongodb.org/browse/DRIVERS-709)
392+
for running specification tests to confirm PyMongo behaves as expected.
393+
394+
### Resynchronizing the Specification Tests
388395

389396
If you would like to re-sync the copy of the specification tests in the
390397
PyMongo repository with that which is inside the [specifications

_setup.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,11 @@ def build_extension(self, ext):
130130
except ValueError:
131131
pass
132132
ext_modules = []
133-
elif sys.platform.startswith("java") or sys.platform == "cli" or "PyPy" in sys.version:
133+
elif (
134+
sys.platform.startswith("java")
135+
or sys.platform == "cli"
136+
or sys.implementation.name in ("pypy", "graalpy")
137+
):
134138
sys.stdout.write(
135139
"""
136140
*****************************************************\n

bson/codec_options.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,16 @@ def __init__(
160160
f"Expected an instance of {TypeEncoder.__name__}, {TypeDecoder.__name__}, or {TypeCodec.__name__}, got {codec!r} instead"
161161
)
162162

163+
@property
164+
def codecs(self) -> list[TypeEncoder | TypeDecoder | TypeCodec]:
165+
"""The list of type codecs in this registry."""
166+
return self.__type_codecs
167+
168+
@property
169+
def fallback_encoder(self) -> Optional[_Fallback]:
170+
"""The fallback encoder in this registry."""
171+
return self._fallback_encoder
172+
163173
def _validate_type_encoder(self, codec: _Codec) -> None:
164174
from bson import _BUILT_IN_TYPES
165175

doc/changelog.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
11
Changelog
22
=========
33

4+
Changes in Version 4.14.0 (XXXX/XX/XX)
5+
--------------------------------------
6+
PyMongo 4.14 brings a number of changes including:
7+
8+
- Added :attr:`bson.codec_options.TypeRegistry.codecs` and :attr:`bson.codec_options.TypeRegistry.fallback_encoder` properties
9+
to allow users to directly access the type codecs and fallback encoder for a given :class:`bson.codec_options.TypeRegistry`.
10+
411
Changes in Version 4.13.0 (2025/05/14)
512
--------------------------------------
613

test/asynchronous/test_bulk.py

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ def assertEqualUpsert(self, expected, actual):
9494
self.assertEqual(expected["index"], actual["index"])
9595
if expected["_id"] == "...":
9696
# Unspecified value.
97-
self.assertTrue("_id" in actual)
97+
self.assertIn("_id", actual)
9898
else:
9999
self.assertEqual(expected["_id"], actual["_id"])
100100

@@ -107,15 +107,15 @@ def assertEqualWriteError(self, expected, actual):
107107
self.assertEqual(expected["code"], actual["code"])
108108
if expected["errmsg"] == "...":
109109
# Unspecified value.
110-
self.assertTrue("errmsg" in actual)
110+
self.assertIn("errmsg", actual)
111111
else:
112112
self.assertEqual(expected["errmsg"], actual["errmsg"])
113113

114114
expected_op = expected["op"].copy()
115115
actual_op = actual["op"].copy()
116116
if expected_op.get("_id") == "...":
117117
# Unspecified _id.
118-
self.assertTrue("_id" in actual_op)
118+
self.assertIn("_id", actual_op)
119119
actual_op.pop("_id")
120120
expected_op.pop("_id")
121121

@@ -160,7 +160,7 @@ async def _test_update_many(self, update):
160160
result = await self.coll.bulk_write([UpdateMany({}, update)])
161161
self.assertEqualResponse(expected, result.bulk_api_result)
162162
self.assertEqual(2, result.matched_count)
163-
self.assertTrue(result.modified_count in (2, None))
163+
self.assertIn(result.modified_count, (2, None))
164164

165165
async def test_update_many(self):
166166
await self._test_update_many({"$set": {"foo": "bar"}})
@@ -201,7 +201,7 @@ async def _test_update_one(self, update):
201201
result = await self.coll.bulk_write([UpdateOne({}, update)])
202202
self.assertEqualResponse(expected, result.bulk_api_result)
203203
self.assertEqual(1, result.matched_count)
204-
self.assertTrue(result.modified_count in (1, None))
204+
self.assertIn(result.modified_count, (1, None))
205205

206206
async def test_update_one(self):
207207
await self._test_update_one({"$set": {"foo": "bar"}})
@@ -227,7 +227,7 @@ async def test_replace_one(self):
227227
result = await self.coll.bulk_write([ReplaceOne({}, {"foo": "bar"})])
228228
self.assertEqualResponse(expected, result.bulk_api_result)
229229
self.assertEqual(1, result.matched_count)
230-
self.assertTrue(result.modified_count in (1, None))
230+
self.assertIn(result.modified_count, (1, None))
231231

232232
async def test_remove(self):
233233
# Test removing all documents, ordered.
@@ -281,7 +281,7 @@ async def test_upsert(self):
281281
self.assertEqual(1, result.upserted_count)
282282
assert result.upserted_ids is not None
283283
self.assertEqual(1, len(result.upserted_ids))
284-
self.assertTrue(isinstance(result.upserted_ids.get(0), ObjectId))
284+
self.assertIsInstance(result.upserted_ids.get(0), ObjectId)
285285

286286
self.assertEqual(await self.coll.count_documents({"foo": "bar"}), 1)
287287

@@ -998,7 +998,7 @@ async def test_write_concern_failure_ordered(self):
998998

999999
failed = details["writeConcernErrors"][0]
10001000
self.assertEqual(64, failed["code"])
1001-
self.assertTrue(isinstance(failed["errmsg"], str))
1001+
self.assertIsInstance(failed["errmsg"], str)
10021002

10031003
await self.coll.delete_many({})
10041004
await self.coll.create_index("a", unique=True)
@@ -1037,7 +1037,7 @@ async def test_write_concern_failure_ordered(self):
10371037

10381038
self.assertTrue(len(details["writeConcernErrors"]) > 1)
10391039
failed = details["writeErrors"][0]
1040-
self.assertTrue("duplicate" in failed["errmsg"])
1040+
self.assertIn("duplicate", failed["errmsg"])
10411041

10421042
@async_client_context.require_version_max(7, 1) # PYTHON-4560
10431043
@async_client_context.require_replica_set
@@ -1105,12 +1105,12 @@ async def test_write_concern_failure_unordered(self):
11051105
failed = details["writeErrors"][0]
11061106
self.assertEqual(2, failed["index"])
11071107
self.assertEqual(11000, failed["code"])
1108-
self.assertTrue(isinstance(failed["errmsg"], str))
1108+
self.assertIsInstance(failed["errmsg"], str)
11091109
self.assertEqual(1, failed["op"]["a"])
11101110

11111111
failed = details["writeConcernErrors"][0]
11121112
self.assertEqual(64, failed["code"])
1113-
self.assertTrue(isinstance(failed["errmsg"], str))
1113+
self.assertIsInstance(failed["errmsg"], str)
11141114

11151115
upserts = details["upserted"]
11161116
self.assertEqual(1, len(upserts))

test/asynchronous/test_client.py

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,7 @@ def make_db(base, name):
214214
self.assertRaises(InvalidName, make_db, self.client, "te/t")
215215
self.assertRaises(InvalidName, make_db, self.client, "te st")
216216

217-
self.assertTrue(isinstance(self.client.test, AsyncDatabase))
217+
self.assertIsInstance(self.client.test, AsyncDatabase)
218218
self.assertEqual(self.client.test, self.client["test"])
219219
self.assertEqual(self.client.test, AsyncDatabase(self.client, "test"))
220220

@@ -228,7 +228,7 @@ def test_get_database(self):
228228
self.assertEqual(write_concern, db.write_concern)
229229

230230
def test_getattr(self):
231-
self.assertTrue(isinstance(self.client["_does_not_exist"], AsyncDatabase))
231+
self.assertIsInstance(self.client["_does_not_exist"], AsyncDatabase)
232232

233233
with self.assertRaises(AttributeError) as context:
234234
self.client._does_not_exist
@@ -674,7 +674,7 @@ async def test_max_idle_time_reaper_default(self):
674674
async with server._pool.checkout() as conn:
675675
pass
676676
self.assertEqual(1, len(server._pool.conns))
677-
self.assertTrue(conn in server._pool.conns)
677+
self.assertIn(conn, server._pool.conns)
678678

679679
async def test_max_idle_time_reaper_removes_stale_minPoolSize(self):
680680
with client_knobs(kill_cursor_frequency=0.1):
@@ -752,7 +752,7 @@ async def test_min_pool_size(self):
752752
lambda: len(server._pool.conns) == 10,
753753
"a closed socket gets replaced from the pool",
754754
)
755-
self.assertFalse(conn in server._pool.conns)
755+
self.assertNotIn(conn, server._pool.conns)
756756

757757
async def test_max_idle_time_checkout(self):
758758
# Use high frequency to test _get_socket_no_auth.
@@ -769,8 +769,8 @@ async def test_max_idle_time_checkout(self):
769769
async with server._pool.checkout() as new_con:
770770
self.assertNotEqual(conn, new_con)
771771
self.assertEqual(1, len(server._pool.conns))
772-
self.assertFalse(conn in server._pool.conns)
773-
self.assertTrue(new_con in server._pool.conns)
772+
self.assertNotIn(conn, server._pool.conns)
773+
self.assertIn(new_con, server._pool.conns)
774774

775775
# Test that connections are reused if maxIdleTimeMS is not set.
776776
client = await self.async_rs_or_single_client()
@@ -1032,8 +1032,8 @@ async def test_list_database_names(self):
10321032
cmd_names = [doc["name"] for doc in cmd_docs]
10331033

10341034
db_names = await self.client.list_database_names()
1035-
self.assertTrue("pymongo_test" in db_names)
1036-
self.assertTrue("pymongo_test_mike" in db_names)
1035+
self.assertIn("pymongo_test", db_names)
1036+
self.assertIn("pymongo_test_mike", db_names)
10371037
self.assertEqual(db_names, cmd_names)
10381038

10391039
async def test_drop_database(self):
@@ -1257,9 +1257,9 @@ async def test_unix_socket(self):
12571257
client = await self.async_rs_or_single_client(uri)
12581258
await client.pymongo_test.test.insert_one({"dummy": "object"})
12591259
dbs = await client.list_database_names()
1260-
self.assertTrue("pymongo_test" in dbs)
1260+
self.assertIn("pymongo_test", dbs)
12611261

1262-
self.assertTrue(mongodb_socket in repr(client))
1262+
self.assertIn(mongodb_socket, repr(client))
12631263

12641264
# Confirm it fails with a missing socket.
12651265
with self.assertRaises(ConnectionFailure):
@@ -1274,15 +1274,15 @@ async def test_document_class(self):
12741274
await db.test.insert_one({"x": 1})
12751275

12761276
self.assertEqual(dict, c.codec_options.document_class)
1277-
self.assertTrue(isinstance(await db.test.find_one(), dict))
1278-
self.assertFalse(isinstance(await db.test.find_one(), SON))
1277+
self.assertIsInstance(await db.test.find_one(), dict)
1278+
self.assertNotIsInstance(await db.test.find_one(), SON)
12791279

12801280
c = await self.async_rs_or_single_client(document_class=SON)
12811281

12821282
db = c.pymongo_test
12831283

12841284
self.assertEqual(SON, c.codec_options.document_class)
1285-
self.assertTrue(isinstance(await db.test.find_one(), SON))
1285+
self.assertIsInstance(await db.test.find_one(), SON)
12861286

12871287
async def test_timeouts(self):
12881288
client = await self.async_rs_or_single_client(
@@ -1431,8 +1431,8 @@ async def test_ipv6(self):
14311431
await client.pymongo_test_bernie.test.insert_one({"dummy": "object"})
14321432

14331433
dbs = await client.list_database_names()
1434-
self.assertTrue("pymongo_test" in dbs)
1435-
self.assertTrue("pymongo_test_bernie" in dbs)
1434+
self.assertIn("pymongo_test", dbs)
1435+
self.assertIn("pymongo_test_bernie", dbs)
14361436

14371437
async def test_contextlib(self):
14381438
client = await self.async_rs_or_single_client()

0 commit comments

Comments
 (0)