diff options
| author | Raoni Timo <raoni@relume.io> | 2026-04-30 10:57:27 -0300 |
|---|---|---|
| committer | Jacob Walls <jacobtylerwalls@gmail.com> | 2026-04-30 19:52:11 -0400 |
| commit | 9f790ef1a0f356cf6342b5d57bbaeac35aed0d9f (patch) | |
| tree | 1e14aebd1bce0831ca9353be104a219d430f71fd | |
| parent | 8726605e2d48fd733ae224344a11cc2163012f2d (diff) | |
Setting "check" in OPTIONS["pool"] previously raised TypeError because the
PostgreSQL backend always passed check= to ConnectionPool() and unpacked
**pool_options on top, regardless of CONN_HEALTH_CHECKS. The user's callable
now takes precedence via setdefault(); pool_options is copied first to avoid
mutating the user's settings dict.
| -rw-r--r-- | AUTHORS | 1 | ||||
| -rw-r--r-- | django/db/backends/postgresql/base.py | 6 | ||||
| -rw-r--r-- | tests/backends/postgresql/tests.py | 27 |
3 files changed, 33 insertions, 1 deletions
@@ -891,6 +891,7 @@ answer newbie questions, and generally made Django that much better: Ramon Saraiva <ramonsaraiva@gmail.com> Ram Rachum <ram@rachum.com> Randy Barlow <randy@electronsweatshop.com> + Raoni Timo <raoni@relume.io> Raphaël Barrois <raphael.barrois@m4x.org> Raphael Michel <mail@raphaelmichel.de> Raúl Cumplido <raulcumplido@gmail.com> diff --git a/django/db/backends/postgresql/base.py b/django/db/backends/postgresql/base.py index 42b37ab3c2..16cf7f84e6 100644 --- a/django/db/backends/postgresql/base.py +++ b/django/db/backends/postgresql/base.py @@ -216,11 +216,15 @@ class DatabaseWrapper(BaseDatabaseWrapper): # Ensure we run in autocommit, Django properly sets it later on. connect_kwargs["autocommit"] = True enable_checks = self.settings_dict["CONN_HEALTH_CHECKS"] + # Copy to avoid mutating the user's settings dict. + pool_options = {**pool_options} + pool_options.setdefault( + "check", ConnectionPool.check_connection if enable_checks else None + ) pool = ConnectionPool( kwargs=connect_kwargs, open=False, # Do not open the pool during startup. configure=self._configure_connection, - check=ConnectionPool.check_connection if enable_checks else None, **pool_options, ) # setdefault() ensures that multiple threads don't set this in diff --git a/tests/backends/postgresql/tests.py b/tests/backends/postgresql/tests.py index e03c37cb57..9afa6020a3 100644 --- a/tests/backends/postgresql/tests.py +++ b/tests/backends/postgresql/tests.py @@ -326,6 +326,33 @@ class Tests(TestCase): new_connection.close_pool() @unittest.skipUnless(is_psycopg3, "psycopg3 specific test") + def test_pool_check_can_be_overridden(self): + def custom_check(conn): + pass + + new_connection = no_pool_connection(alias="default_pool") + new_connection.settings_dict["OPTIONS"]["pool"] = {"check": custom_check} + + for enable_checks in (True, False): + with self.subTest(CONN_HEALTH_CHECKS=enable_checks): + new_connection.settings_dict["CONN_HEALTH_CHECKS"] = enable_checks + try: + self.assertIs(new_connection.pool._check, custom_check) + finally: + new_connection.close_pool() + + @unittest.skipUnless(is_psycopg3, "psycopg3 specific test") + def test_pool_options_not_mutated(self): + pool_options = {"min_size": 0, "max_size": 2} + new_connection = no_pool_connection(alias="default_pool") + new_connection.settings_dict["OPTIONS"]["pool"] = pool_options + try: + self.assertIsNotNone(new_connection.pool) + finally: + new_connection.close_pool() + self.assertEqual(pool_options, {"min_size": 0, "max_size": 2}) + + @unittest.skipUnless(is_psycopg3, "psycopg3 specific test") def test_cannot_open_new_connection_in_atomic_block(self): new_connection = no_pool_connection(alias="default_pool") new_connection.settings_dict["OPTIONS"]["pool"] = True |
