Skip to content

Commit 33add41

Browse files
authored
Merge branch 'master' into PYTHON-5215
2 parents 28afc38 + 1ffdedc commit 33add41

File tree

11 files changed

+158
-6
lines changed

11 files changed

+158
-6
lines changed

.evergreen/generated_configs/variants.yml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -535,55 +535,71 @@ buildvariants:
535535
display_name: "* MongoDB v4.2"
536536
run_on:
537537
- rhel87-small
538+
expansions:
539+
VERSION: "4.2"
538540
tags: [coverage_tag]
539541
- name: mongodb-v4.4
540542
tasks:
541543
- name: .server-version
542544
display_name: "* MongoDB v4.4"
543545
run_on:
544546
- rhel87-small
547+
expansions:
548+
VERSION: "4.4"
545549
tags: [coverage_tag]
546550
- name: mongodb-v5.0
547551
tasks:
548552
- name: .server-version
549553
display_name: "* MongoDB v5.0"
550554
run_on:
551555
- rhel87-small
556+
expansions:
557+
VERSION: "5.0"
552558
tags: [coverage_tag]
553559
- name: mongodb-v6.0
554560
tasks:
555561
- name: .server-version
556562
display_name: "* MongoDB v6.0"
557563
run_on:
558564
- rhel87-small
565+
expansions:
566+
VERSION: "6.0"
559567
tags: [coverage_tag]
560568
- name: mongodb-v7.0
561569
tasks:
562570
- name: .server-version
563571
display_name: "* MongoDB v7.0"
564572
run_on:
565573
- rhel87-small
574+
expansions:
575+
VERSION: "7.0"
566576
tags: [coverage_tag]
567577
- name: mongodb-v8.0
568578
tasks:
569579
- name: .server-version
570580
display_name: "* MongoDB v8.0"
571581
run_on:
572582
- rhel87-small
583+
expansions:
584+
VERSION: "8.0"
573585
tags: [coverage_tag]
574586
- name: mongodb-rapid
575587
tasks:
576588
- name: .server-version
577589
display_name: "* MongoDB rapid"
578590
run_on:
579591
- rhel87-small
592+
expansions:
593+
VERSION: rapid
580594
tags: [coverage_tag]
581595
- name: mongodb-latest
582596
tasks:
583597
- name: .server-version
584598
display_name: "* MongoDB latest"
585599
run_on:
586600
- rhel87-small
601+
expansions:
602+
VERSION: latest
587603
tags: [coverage_tag]
588604

589605
# Stable api tests

.evergreen/scripts/generate_config.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,11 @@ def create_server_version_variants() -> list[BuildVariant]:
7474
for version in ALL_VERSIONS:
7575
display_name = get_variant_name("* MongoDB", version=version)
7676
variant = create_variant(
77-
[".server-version"], display_name, host=DEFAULT_HOST, tags=["coverage_tag"]
77+
[".server-version"],
78+
display_name,
79+
version=version,
80+
host=DEFAULT_HOST,
81+
tags=["coverage_tag"],
7882
)
7983
variants.append(variant)
8084
return variants

pymongo/asynchronous/collection.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1776,6 +1776,15 @@ def find(self, *args: Any, **kwargs: Any) -> AsyncCursor[_DocumentType]:
17761776
improper type. Returns an instance of
17771777
:class:`~pymongo.asynchronous.cursor.AsyncCursor` corresponding to this query.
17781778
1779+
Cursors are closed automatically when they are exhausted (the last batch of data is retrieved from the database).
1780+
If a cursor is not exhausted, it will be closed automatically upon garbage collection, which leaves resources open but unused for a potentially long period of time.
1781+
To avoid this, best practice is to call :meth:`AsyncCursor.close` when the cursor is no longer needed,
1782+
or use the cursor in a with statement::
1783+
1784+
async with collection.find() as cursor:
1785+
async for doc in cursor:
1786+
print(doc)
1787+
17791788
The :meth:`find` method obeys the :attr:`read_preference` of
17801789
this :class:`AsyncCollection`.
17811790
@@ -2503,6 +2512,15 @@ async def list_indexes(
25032512
...
25042513
SON([('v', 2), ('key', SON([('_id', 1)])), ('name', '_id_')])
25052514
2515+
Cursors are closed automatically when they are exhausted (the last batch of data is retrieved from the database).
2516+
If a cursor is not exhausted, it will be closed automatically upon garbage collection, which leaves resources open but unused for a potentially long period of time.
2517+
To avoid this, best practice is to call :meth:`AsyncCursor.close` when the cursor is no longer needed,
2518+
or use the cursor in a with statement::
2519+
2520+
async with await collection.list_indexes() as cursor:
2521+
async for index in cursor:
2522+
print(index)
2523+
25062524
:param session: a
25072525
:class:`~pymongo.asynchronous.client_session.AsyncClientSession`.
25082526
:param comment: A user-provided comment to attach to this
@@ -2620,6 +2638,15 @@ async def list_search_indexes(
26202638
) -> AsyncCommandCursor[Mapping[str, Any]]:
26212639
"""Return a cursor over search indexes for the current collection.
26222640
2641+
Cursors are closed automatically when they are exhausted (the last batch of data is retrieved from the database).
2642+
If a cursor is not exhausted, it will be closed automatically upon garbage collection, which leaves resources open but unused for a potentially long period of time.
2643+
To avoid this, best practice is to call :meth:`AsyncCursor.close` when the cursor is no longer needed,
2644+
or use the cursor in a with statement::
2645+
2646+
async with await collection.list_search_indexes() as cursor:
2647+
async for index in cursor:
2648+
print(index)
2649+
26232650
:param name: If given, the name of the index to search
26242651
for. Only indexes with matching index names will be returned.
26252652
If not given, all search indexes for the current collection
@@ -2922,6 +2949,15 @@ async def aggregate(
29222949
.. note:: The :attr:`~pymongo.asynchronous.collection.AsyncCollection.write_concern` of
29232950
this collection is automatically applied to this operation.
29242951
2952+
Cursors are closed automatically when they are exhausted (the last batch of data is retrieved from the database).
2953+
If a cursor is not exhausted, it will be closed automatically upon garbage collection, which leaves resources open but unused for a potentially long period of time.
2954+
To avoid this, best practice is to call :meth:`AsyncCursor.close` when the cursor is no longer needed,
2955+
or use the cursor in a with statement::
2956+
2957+
async with await collection.aggregate() as cursor:
2958+
async for operation in cursor:
2959+
print(operation)
2960+
29252961
:param pipeline: a list of aggregation pipeline stages
29262962
:param session: a
29272963
:class:`~pymongo.asynchronous.client_session.AsyncClientSession`.

pymongo/asynchronous/database.py

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -643,15 +643,20 @@ async def aggregate(
643643
.. code-block:: python
644644
645645
# Lists all operations currently running on the server.
646-
with client.admin.aggregate([{"$currentOp": {}}]) as cursor:
647-
for operation in cursor:
646+
async with await client.admin.aggregate([{"$currentOp": {}}]) as cursor:
647+
async for operation in cursor:
648648
print(operation)
649649
650650
The :meth:`aggregate` method obeys the :attr:`read_preference` of this
651651
:class:`AsyncDatabase`, except when ``$out`` or ``$merge`` are used, in
652652
which case :attr:`~pymongo.read_preferences.ReadPreference.PRIMARY`
653653
is used.
654654
655+
Cursors are closed automatically when they are exhausted (the last batch of data is retrieved from the database).
656+
If a cursor is not exhausted, it will be closed automatically upon garbage collection, which leaves resources open but unused for a potentially long period of time.
657+
To avoid this, best practice is to call :meth:`AsyncCursor.close` when the cursor is no longer needed,
658+
or use the cursor in a with statement.
659+
655660
.. note:: This method does not support the 'explain' option. Please
656661
use :meth:`~pymongo.asynchronous.database.AsyncDatabase.command` instead.
657662
@@ -1154,6 +1159,15 @@ async def list_collections(
11541159
) -> AsyncCommandCursor[MutableMapping[str, Any]]:
11551160
"""Get a cursor over the collections of this database.
11561161
1162+
Cursors are closed automatically when they are exhausted (the last batch of data is retrieved from the database).
1163+
If a cursor is not exhausted, it will be closed automatically upon garbage collection, which leaves resources open but unused for a potentially long period of time.
1164+
To avoid this, best practice is to call :meth:`AsyncCursor.close` when the cursor is no longer needed,
1165+
or use the cursor in a with statement::
1166+
1167+
async with await database.list_collections() as cursor:
1168+
async for collection in cursor:
1169+
print(collection)
1170+
11571171
:param session: a
11581172
:class:`~pymongo.asynchronous.client_session.AsyncClientSession`.
11591173
:param filter: A query document to filter the list of

pymongo/asynchronous/mongo_client.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,12 @@ def __init__(
202202
exception (recognizing that the operation failed) and then continue to
203203
execute.
204204
205+
Best practice is to call :meth:`AsyncMongoClient.close` when the client is no longer needed,
206+
or use the client in a with statement::
207+
208+
async with AsyncMongoClient(url) as client:
209+
# Use client here.
210+
205211
The `host` parameter can be a full `mongodb URI
206212
<https://dochub.mongodb.org/core/connections>`_, in addition to
207213
a simple hostname. It can also be a list of hostnames but no more
@@ -2345,6 +2351,15 @@ async def list_databases(
23452351
) -> AsyncCommandCursor[dict[str, Any]]:
23462352
"""Get a cursor over the databases of the connected server.
23472353
2354+
Cursors are closed automatically when they are exhausted (the last batch of data is retrieved from the database).
2355+
If a cursor is not exhausted, it will be closed automatically upon garbage collection, which leaves resources open but unused for a potentially long period of time.
2356+
To avoid this, best practice is to call :meth:`AsyncCursor.close` when the cursor is no longer needed,
2357+
or use the cursor in a with statement::
2358+
2359+
async with await client.list_databases() as cursor:
2360+
async for database in cursor:
2361+
print(database)
2362+
23482363
:param session: a
23492364
:class:`~pymongo.asynchronous.client_session.AsyncClientSession`.
23502365
:param comment: A user-provided comment to attach to this

pymongo/synchronous/collection.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1775,6 +1775,15 @@ def find(self, *args: Any, **kwargs: Any) -> Cursor[_DocumentType]:
17751775
improper type. Returns an instance of
17761776
:class:`~pymongo.cursor.Cursor` corresponding to this query.
17771777
1778+
Cursors are closed automatically when they are exhausted (the last batch of data is retrieved from the database).
1779+
If a cursor is not exhausted, it will be closed automatically upon garbage collection, which leaves resources open but unused for a potentially long period of time.
1780+
To avoid this, best practice is to call :meth:`Cursor.close` when the cursor is no longer needed,
1781+
or use the cursor in a with statement::
1782+
1783+
with collection.find() as cursor:
1784+
for doc in cursor:
1785+
print(doc)
1786+
17781787
The :meth:`find` method obeys the :attr:`read_preference` of
17791788
this :class:`Collection`.
17801789
@@ -2500,6 +2509,15 @@ def list_indexes(
25002509
...
25012510
SON([('v', 2), ('key', SON([('_id', 1)])), ('name', '_id_')])
25022511
2512+
Cursors are closed automatically when they are exhausted (the last batch of data is retrieved from the database).
2513+
If a cursor is not exhausted, it will be closed automatically upon garbage collection, which leaves resources open but unused for a potentially long period of time.
2514+
To avoid this, best practice is to call :meth:`Cursor.close` when the cursor is no longer needed,
2515+
or use the cursor in a with statement::
2516+
2517+
with collection.list_indexes() as cursor:
2518+
for index in cursor:
2519+
print(index)
2520+
25032521
:param session: a
25042522
:class:`~pymongo.client_session.ClientSession`.
25052523
:param comment: A user-provided comment to attach to this
@@ -2617,6 +2635,15 @@ def list_search_indexes(
26172635
) -> CommandCursor[Mapping[str, Any]]:
26182636
"""Return a cursor over search indexes for the current collection.
26192637
2638+
Cursors are closed automatically when they are exhausted (the last batch of data is retrieved from the database).
2639+
If a cursor is not exhausted, it will be closed automatically upon garbage collection, which leaves resources open but unused for a potentially long period of time.
2640+
To avoid this, best practice is to call :meth:`Cursor.close` when the cursor is no longer needed,
2641+
or use the cursor in a with statement::
2642+
2643+
with collection.list_search_indexes() as cursor:
2644+
for index in cursor:
2645+
print(index)
2646+
26202647
:param name: If given, the name of the index to search
26212648
for. Only indexes with matching index names will be returned.
26222649
If not given, all search indexes for the current collection
@@ -2915,6 +2942,15 @@ def aggregate(
29152942
.. note:: The :attr:`~pymongo.collection.Collection.write_concern` of
29162943
this collection is automatically applied to this operation.
29172944
2945+
Cursors are closed automatically when they are exhausted (the last batch of data is retrieved from the database).
2946+
If a cursor is not exhausted, it will be closed automatically upon garbage collection, which leaves resources open but unused for a potentially long period of time.
2947+
To avoid this, best practice is to call :meth:`Cursor.close` when the cursor is no longer needed,
2948+
or use the cursor in a with statement::
2949+
2950+
with collection.aggregate() as cursor:
2951+
for operation in cursor:
2952+
print(operation)
2953+
29182954
:param pipeline: a list of aggregation pipeline stages
29192955
:param session: a
29202956
:class:`~pymongo.client_session.ClientSession`.

pymongo/synchronous/database.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -652,6 +652,11 @@ def aggregate(
652652
which case :attr:`~pymongo.read_preferences.ReadPreference.PRIMARY`
653653
is used.
654654
655+
Cursors are closed automatically when they are exhausted (the last batch of data is retrieved from the database).
656+
If a cursor is not exhausted, it will be closed automatically upon garbage collection, which leaves resources open but unused for a potentially long period of time.
657+
To avoid this, best practice is to call :meth:`Cursor.close` when the cursor is no longer needed,
658+
or use the cursor in a with statement.
659+
655660
.. note:: This method does not support the 'explain' option. Please
656661
use :meth:`~pymongo.database.Database.command` instead.
657662
@@ -1148,6 +1153,15 @@ def list_collections(
11481153
) -> CommandCursor[MutableMapping[str, Any]]:
11491154
"""Get a cursor over the collections of this database.
11501155
1156+
Cursors are closed automatically when they are exhausted (the last batch of data is retrieved from the database).
1157+
If a cursor is not exhausted, it will be closed automatically upon garbage collection, which leaves resources open but unused for a potentially long period of time.
1158+
To avoid this, best practice is to call :meth:`Cursor.close` when the cursor is no longer needed,
1159+
or use the cursor in a with statement::
1160+
1161+
with database.list_collections() as cursor:
1162+
for collection in cursor:
1163+
print(collection)
1164+
11511165
:param session: a
11521166
:class:`~pymongo.client_session.ClientSession`.
11531167
:param filter: A query document to filter the list of

pymongo/synchronous/mongo_client.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,12 @@ def __init__(
199199
exception (recognizing that the operation failed) and then continue to
200200
execute.
201201
202+
Best practice is to call :meth:`MongoClient.close` when the client is no longer needed,
203+
or use the client in a with statement::
204+
205+
with MongoClient(url) as client:
206+
# Use client here.
207+
202208
The `host` parameter can be a full `mongodb URI
203209
<https://dochub.mongodb.org/core/connections>`_, in addition to
204210
a simple hostname. It can also be a list of hostnames but no more
@@ -2335,6 +2341,15 @@ def list_databases(
23352341
) -> CommandCursor[dict[str, Any]]:
23362342
"""Get a cursor over the databases of the connected server.
23372343
2344+
Cursors are closed automatically when they are exhausted (the last batch of data is retrieved from the database).
2345+
If a cursor is not exhausted, it will be closed automatically upon garbage collection, which leaves resources open but unused for a potentially long period of time.
2346+
To avoid this, best practice is to call :meth:`Cursor.close` when the cursor is no longer needed,
2347+
or use the cursor in a with statement::
2348+
2349+
with client.list_databases() as cursor:
2350+
for database in cursor:
2351+
print(database)
2352+
23382353
:param session: a
23392354
:class:`~pymongo.client_session.ClientSession`.
23402355
:param comment: A user-provided comment to attach to this

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ gevent = ["gevent", "cffi>=2.0.0b1;python_version=='3.14'"]
5555
eventlet = ["eventlet"]
5656
coverage = [
5757
"pytest-cov",
58-
"coverage>=5,<=7.10.2"
58+
"coverage>=5,<=7.10.3"
5959
]
6060
mockupdb = [
6161
"mockupdb@git+https://github.com/mongodb-labs/mongo-mockup-db@master"

test/asynchronous/test_pooling.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
import socket
2222
import sys
2323
import time
24-
from test.asynchronous.utils import async_get_pool, async_joinall
24+
from test.asynchronous.utils import async_get_pool, async_joinall, flaky
2525

2626
from bson.codec_options import DEFAULT_CODEC_OPTIONS
2727
from bson.son import SON
@@ -429,6 +429,7 @@ async def find_one():
429429
# maxConnecting = unbounded: 30+ connections in ~0.140+ seconds
430430
print(len(pool.conns))
431431

432+
@flaky(reason="PYTHON-5492")
432433
@async_client_context.require_failCommand_appName
433434
async def test_csot_timeout_message(self):
434435
client = await self.async_rs_or_single_client(appName="connectionTimeoutApp")

0 commit comments

Comments
 (0)