Skip to content

Commit 8a5dc60

Browse files
committed
Merge branch 'master' of github.com:mongodb/mongo-python-driver into PYTHON-5413
2 parents 36d1aa7 + 578c6c2 commit 8a5dc60

33 files changed

+706
-50
lines changed

.evergreen/resync-specs.sh

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,9 @@ do
131131
gridfs)
132132
cpjson gridfs/tests gridfs
133133
;;
134+
handshake)
135+
cpjson mongodb-handshake/tests handshake
136+
;;
134137
index|index-management)
135138
cpjson index-management/tests index_management
136139
;;

.github/CODEOWNERS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
* @mongodb/dbx-python

.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@ce28f5bb42b7a9f2c824e633a3f6ee835bab6858 # v3
49+
uses: github/codeql-action/init@39edc492dbe16b1465b0cafca41432d857bdb31a # 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@ce28f5bb42b7a9f2c824e633a3f6ee835bab6858 # v3
66+
uses: github/codeql-action/analyze@39edc492dbe16b1465b0cafca41432d857bdb31a # v3
6767
with:
6868
category: "/language:${{matrix.language}}"

.github/workflows/test-python.yml

Lines changed: 58 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ jobs:
2525
- name: Install just
2626
uses: extractions/setup-just@e33e0265a09d6d736e2ee1e0eb685ef1de4669ff # v3
2727
- name: Install uv
28-
uses: astral-sh/setup-uv@f0ec1fc3b38f5e7cd731bb6ce540c5af426746bb # v5
28+
uses: astral-sh/setup-uv@bd01e18f51369d5a26f1651c3cb451d3417e3bba # v5
2929
with:
3030
enable-cache: true
3131
python-version: "3.9"
@@ -65,7 +65,7 @@ jobs:
6565
- name: Install just
6666
uses: extractions/setup-just@e33e0265a09d6d736e2ee1e0eb685ef1de4669ff # v3
6767
- name: Install uv
68-
uses: astral-sh/setup-uv@f0ec1fc3b38f5e7cd731bb6ce540c5af426746bb # v5
68+
uses: astral-sh/setup-uv@bd01e18f51369d5a26f1651c3cb451d3417e3bba # v5
6969
with:
7070
enable-cache: true
7171
python-version: ${{ matrix.python-version }}
@@ -88,7 +88,7 @@ jobs:
8888
- name: Install just
8989
uses: extractions/setup-just@e33e0265a09d6d736e2ee1e0eb685ef1de4669ff # v3
9090
- name: Install uv
91-
uses: astral-sh/setup-uv@f0ec1fc3b38f5e7cd731bb6ce540c5af426746bb # v5
91+
uses: astral-sh/setup-uv@bd01e18f51369d5a26f1651c3cb451d3417e3bba # v5
9292
with:
9393
enable-cache: true
9494
python-version: "3.9"
@@ -111,7 +111,7 @@ jobs:
111111
with:
112112
persist-credentials: false
113113
- name: Install uv
114-
uses: astral-sh/setup-uv@f0ec1fc3b38f5e7cd731bb6ce540c5af426746bb # v5
114+
uses: astral-sh/setup-uv@bd01e18f51369d5a26f1651c3cb451d3417e3bba # v5
115115
with:
116116
enable-cache: true
117117
python-version: "3.9"
@@ -130,7 +130,7 @@ jobs:
130130
with:
131131
persist-credentials: false
132132
- name: Install uv
133-
uses: astral-sh/setup-uv@f0ec1fc3b38f5e7cd731bb6ce540c5af426746bb # v5
133+
uses: astral-sh/setup-uv@bd01e18f51369d5a26f1651c3cb451d3417e3bba # v5
134134
with:
135135
enable-cache: true
136136
python-version: "3.9"
@@ -152,7 +152,7 @@ jobs:
152152
with:
153153
persist-credentials: false
154154
- name: Install uv
155-
uses: astral-sh/setup-uv@f0ec1fc3b38f5e7cd731bb6ce540c5af426746bb # v5
155+
uses: astral-sh/setup-uv@bd01e18f51369d5a26f1651c3cb451d3417e3bba # v5
156156
with:
157157
enable-cache: true
158158
python-version: "${{matrix.python}}"
@@ -220,3 +220,55 @@ jobs:
220220
which python
221221
pip install -e ".[test]"
222222
PYMONGO_MUST_CONNECT=1 pytest -v -k client_context
223+
224+
test_minimum:
225+
permissions:
226+
contents: read
227+
runs-on: ubuntu-latest
228+
name: Test using minimum dependencies and supported Python
229+
steps:
230+
- uses: actions/checkout@v4
231+
with:
232+
persist-credentials: false
233+
- name: Install uv
234+
uses: astral-sh/setup-uv@bd01e18f51369d5a26f1651c3cb451d3417e3bba # v5
235+
with:
236+
python-version: '3.9'
237+
- name: Start MongoDB
238+
uses: supercharge/mongodb-github-action@90004df786821b6308fb02299e5835d0dae05d0d # 1.12.0
239+
with:
240+
mongodb-version: 6.0
241+
# Async and our test_dns do not support dnspython 1.X, so we don't run async or dns tests here
242+
- name: Run tests
243+
shell: bash
244+
run: |
245+
uv venv
246+
source .venv/bin/activate
247+
uv pip install -e ".[test]" --resolution=lowest-direct
248+
pytest -v test/test_srv_polling.py
249+
250+
test_minimum_for_async:
251+
permissions:
252+
contents: read
253+
runs-on: ubuntu-latest
254+
name: Test async's minimum dependencies and Python
255+
steps:
256+
- uses: actions/checkout@v4
257+
with:
258+
persist-credentials: false
259+
- name: Install uv
260+
uses: astral-sh/setup-uv@bd01e18f51369d5a26f1651c3cb451d3417e3bba # v5
261+
with:
262+
python-version: '3.9'
263+
- name: Start MongoDB
264+
uses: supercharge/mongodb-github-action@90004df786821b6308fb02299e5835d0dae05d0d # 1.12.0
265+
with:
266+
mongodb-version: 6.0
267+
# The lifetime kwarg we use in srv resolution was added to the async resolver API in dnspython 2.1.0
268+
- name: Run tests
269+
shell: bash
270+
run: |
271+
uv venv
272+
source .venv/bin/activate
273+
uv pip install -e ".[test]" --resolution=lowest-direct dnspython==2.1.0 --force-reinstall
274+
pytest -v test/test_srv_polling.py test/test_dns.py test/asynchronous/test_srv_polling.py test/asynchronous/test_dns.py

.github/workflows/zizmor.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,15 @@ jobs:
1818
with:
1919
persist-credentials: false
2020
- name: Setup Rust
21-
uses: actions-rust-lang/setup-rust-toolchain@9d7e65c320fdb52dcd45ffaa68deb6c02c8754d9 # v1
21+
uses: actions-rust-lang/setup-rust-toolchain@fb51252c7ba57d633bc668f941da052e410add48 # v1
2222
- name: Get zizmor
2323
run: cargo install zizmor
2424
- name: Run zizmor 🌈
2525
run: zizmor --format sarif . > results.sarif
2626
env:
2727
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
2828
- name: Upload SARIF file
29-
uses: github/codeql-action/upload-sarif@ce28f5bb42b7a9f2c824e633a3f6ee835bab6858 # v3
29+
uses: github/codeql-action/upload-sarif@39edc492dbe16b1465b0cafca41432d857bdb31a # v3
3030
with:
3131
sarif_file: results.sarif
3232
category: zizmor

CONTRIBUTING.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -467,3 +467,15 @@ partially-converted asynchronous version of the same name to the `test/asynchron
467467
Use this generated file as a starting point for the completed conversion.
468468

469469
The script is used like so: `python tools/convert_test_to_async.py [test_file.py]`
470+
471+
## Generating a flame graph using py-spy
472+
To profile a test script and generate a flame graph, follow these steps:
473+
1. Install `py-spy` if you haven't already:
474+
```bash
475+
pip install py-spy
476+
```
477+
2. Inside your test script, perform any required setup and then loop over the code you want to profile for improved sampling.
478+
3. Run `py-spy record -o <output.svg> -r <sample_rate=100> -- python <path/to/script>` to generate a `.svg` file containing the flame graph.
479+
(Note: on macOS you will need to run this command using `sudo` to allow `py-spy` to attach to the Python process.)
480+
4. If you need to include native code (for example the C extensions), profiling should be done on a Linux system, as macOS and Windows do not support the `--native` option of `py-spy`.
481+
Creating an ubuntu Evergreen spawn host and using `scp` to copy the flamegraph `.svg` file back to your local machine is the best way to do this.

doc/changelog.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ PyMongo 4.14 brings a number of changes including:
77

88
- Added :attr:`bson.codec_options.TypeRegistry.codecs` and :attr:`bson.codec_options.TypeRegistry.fallback_encoder` properties
99
to allow users to directly access the type codecs and fallback encoder for a given :class:`bson.codec_options.TypeRegistry`.
10+
- Added :meth:`pymongo.asynchronous.mongo_client.AsyncMongoClient.append_metadata` and
11+
:meth:`pymongo.mongo_client.MongoClient.append_metadata` to allow instantiated MongoClients to send client metadata
12+
on-demand
1013

1114
- Introduces a minor breaking change. When encoding :class:`bson.binary.BinaryVector`, a ``ValueError`` will be raised
1215
if the 'padding' metadata field is < 0 or > 7, or non-zero for any type other than PACKED_BIT.

hatch_build.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ def initialize(self, version, build_data):
1919
here = Path(__file__).parent.resolve()
2020
sys.path.insert(0, str(here))
2121

22-
subprocess.check_call([sys.executable, "_setup.py", "build_ext", "-i"])
22+
subprocess.run([sys.executable, "_setup.py", "build_ext", "-i"], check=True)
2323

2424
# Ensure wheel is marked as binary and contains the binary files.
2525
build_data["infer_tag"] = True

pymongo/asynchronous/mongo_client.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@
7070
from pymongo.asynchronous.settings import TopologySettings
7171
from pymongo.asynchronous.topology import Topology, _ErrorContext
7272
from pymongo.client_options import ClientOptions
73+
from pymongo.driver_info import DriverInfo
7374
from pymongo.errors import (
7475
AutoReconnect,
7576
BulkWriteError,
@@ -1040,6 +1041,20 @@ async def target() -> bool:
10401041
self._kill_cursors_executor = executor
10411042
self._opened = False
10421043

1044+
def append_metadata(self, driver_info: DriverInfo) -> None:
1045+
"""Appends the given metadata to existing driver metadata.
1046+
1047+
:param driver_info: a :class:`~pymongo.driver_info.DriverInfo`
1048+
1049+
.. versionadded:: 4.14
1050+
"""
1051+
1052+
if not isinstance(driver_info, DriverInfo):
1053+
raise TypeError(
1054+
f"driver_info must be an instance of DriverInfo, not {type(driver_info)}"
1055+
)
1056+
self._options.pool_options._update_metadata(driver_info)
1057+
10431058
def _should_pin_cursor(self, session: Optional[AsyncClientSession]) -> Optional[bool]:
10441059
return self._options.load_balanced and not (session and session.in_transaction)
10451060

pymongo/pool_options.py

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -376,25 +376,33 @@ def __init__(
376376
"async",
377377
)
378378
if driver:
379-
if driver.name:
380-
self.__metadata["driver"]["name"] = "{}|{}".format(
381-
self.__metadata["driver"]["name"],
382-
driver.name,
383-
)
384-
if driver.version:
385-
self.__metadata["driver"]["version"] = "{}|{}".format(
386-
_METADATA["driver"]["version"],
387-
driver.version,
388-
)
389-
if driver.platform:
390-
self.__metadata["platform"] = "{}|{}".format(_METADATA["platform"], driver.platform)
379+
self._update_metadata(driver)
391380

392381
env = _metadata_env()
393382
if env:
394383
self.__metadata["env"] = env
395384

396385
_truncate_metadata(self.__metadata)
397386

387+
def _update_metadata(self, driver: DriverInfo) -> None:
388+
"""Updates the client's metadata"""
389+
390+
metadata = copy.deepcopy(self.__metadata)
391+
if driver.name:
392+
metadata["driver"]["name"] = "{}|{}".format(
393+
metadata["driver"]["name"],
394+
driver.name,
395+
)
396+
if driver.version:
397+
metadata["driver"]["version"] = "{}|{}".format(
398+
metadata["driver"]["version"],
399+
driver.version,
400+
)
401+
if driver.platform:
402+
metadata["platform"] = "{}|{}".format(metadata["platform"], driver.platform)
403+
404+
self.__metadata = metadata
405+
398406
@property
399407
def _credentials(self) -> Optional[MongoCredential]:
400408
"""A :class:`~pymongo.auth.MongoCredentials` instance or None."""

0 commit comments

Comments
 (0)