Skip to content
Merged
5 changes: 5 additions & 0 deletions doc/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,13 @@ Bug fixes
default ``UNSPECIFIED`` UUID representation, and raise
:class:`~bson.errors.InvalidBSON` when UUID conversion is requested
(`PYTHON-6172`_).
- Fixed a bug where ``MongoClient(maxPoolSize=0, minPoolSize>0)`` raised
``ValueError``, even though ``maxPoolSize=0`` means "no limit". The
``minPoolSize <= maxPoolSize`` validation now treats both ``0`` and ``None``
as unlimited (`PYTHON-6149`_).

.. _PYTHON-6172: https://jira.mongodb.org/browse/PYTHON-6172
.. _PYTHON-6149: https://jira.mongodb.org/browse/PYTHON-6149

Changes in Version 4.19.0 (2026/10/14)
--------------------------------------
Expand Down
3 changes: 2 additions & 1 deletion pymongo/client_options.py
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,8 @@ def _parse_pool_options(
max_pool_size = options.get("maxpoolsize", common.MAX_POOL_SIZE)
min_pool_size = options.get("minpoolsize", common.MIN_POOL_SIZE)
max_idle_time_seconds = options.get("maxidletimems", common.MAX_IDLE_TIME_SEC)
if max_pool_size is not None and min_pool_size > max_pool_size:
# A maxPoolSize of 0 or None means no limit.
if max_pool_size and min_pool_size > max_pool_size:
raise ValueError("minPoolSize must be smaller or equal to maxPoolSize")
connect_timeout = options.get("connecttimeoutms", common.CONNECT_TIMEOUT)
socket_timeout = options.get("sockettimeoutms")
Expand Down
2 changes: 1 addition & 1 deletion pymongo/pool_options.py
Original file line number Diff line number Diff line change
Expand Up @@ -498,7 +498,7 @@ def max_pool_size(self) -> float:
"""The maximum allowable number of concurrent connections to each
connected server. Requests to a server will block if there are
`maxPoolSize` outstanding connections to the requested server.
Defaults to 100. Cannot be 0.
Defaults to 100. A value of 0 or ``None`` means no limit.

When a server's pool has reached `max_pool_size`, operations for that
server block waiting for a socket to be returned to the pool. If
Expand Down
19 changes: 19 additions & 0 deletions test/asynchronous/test_pooling.py
Original file line number Diff line number Diff line change
Expand Up @@ -200,9 +200,28 @@ async def test_max_pool_size_validation(self):

self.assertRaises(ValueError, AsyncMongoClient, host=host, port=port, maxPoolSize="foo")

self.assertRaises(
ValueError, AsyncMongoClient, host=host, port=port, maxPoolSize=10, minPoolSize=20
)

c = AsyncMongoClient(host=host, port=port, maxPoolSize=100, connect=False)
self.assertEqual(c.options.pool_options.max_pool_size, 100)

async def test_max_pool_size_no_limit_with_min_pool_size(self):
# A maxPoolSize of 0 or None means no limit, so minPoolSize must
# still be allowed (PYTHON-6149).
host, port = await async_client_context.host, await async_client_context.port
for max_pool_size in (0, None):
c = AsyncMongoClient(
host=host,
port=port,
maxPoolSize=max_pool_size,
minPoolSize=5,
connect=False,
)
self.assertEqual(c.options.pool_options.max_pool_size, max_pool_size)
self.assertEqual(c.options.pool_options.min_pool_size, 5)

async def test_no_disconnect(self):
await run_cases(self.c, [NonUnique, Unique, InsertOneAndFind])

Expand Down
19 changes: 19 additions & 0 deletions test/test_pooling.py
Original file line number Diff line number Diff line change
Expand Up @@ -200,9 +200,28 @@ def test_max_pool_size_validation(self):

self.assertRaises(ValueError, MongoClient, host=host, port=port, maxPoolSize="foo")

self.assertRaises(
ValueError, MongoClient, host=host, port=port, maxPoolSize=10, minPoolSize=20
)

c = MongoClient(host=host, port=port, maxPoolSize=100, connect=False)
self.assertEqual(c.options.pool_options.max_pool_size, 100)

def test_max_pool_size_no_limit_with_min_pool_size(self):
# A maxPoolSize of 0 or None means no limit, so minPoolSize must
# still be allowed (PYTHON-6149).
host, port = client_context.host, client_context.port
for max_pool_size in (0, None):
c = MongoClient(
host=host,
port=port,
maxPoolSize=max_pool_size,
minPoolSize=5,
connect=False,
)
self.assertEqual(c.options.pool_options.max_pool_size, max_pool_size)
self.assertEqual(c.options.pool_options.min_pool_size, 5)

def test_no_disconnect(self):
run_cases(self.c, [NonUnique, Unique, InsertOneAndFind])

Expand Down
Loading