Script 'mail_helper' called by obssrc
Hello community,
here is the log from the commit of package python-psycopg-pool for
openSUSE:Factory checked in at 2026-10-20 12:40:15
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-psycopg-pool (Old)
and /work/SRC/openSUSE:Factory/.python-psycopg-pool.new.3698736 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-psycopg-pool"
Tue Oct 20 12:40:15 2026 rev:6 rq:1386238 version:3.3.3
Changes:
--------
--- /work/SRC/openSUSE:Factory/python-psycopg-pool/python-psycopg-pool.changes
2026-01-28 15:15:57.980022191 +0100
+++
/work/SRC/openSUSE:Factory/.python-psycopg-pool.new.3698736/python-psycopg-pool.changes
2026-10-20 12:41:42.098975380 +0200
@@ -1,0 +2,20 @@
+Sat Oct 17 15:32:56 UTC 2026 - Andrea Manzini <[email protected]>
+
+- Update to 3.3.3:
+ * Fix sync pool workers terminating after 24 hours with no task
+ to run (ticket #1419).
+- Changes from 3.3.2:
+ * Propagate cancellation and other base exceptions raised in
+ connection check (ticket #1401).
+ * Declare compatibility with Python 3.15.
+- Changes from 3.3.1:
+ * Fix residual race condition catching asyncio.CancelledError on
+ connection (ticket #1275).
+ * Fix race condition constructing the lock that makes sync
+ ConnectionPool.open() thread-safe (ticket #1300).
+ * Raise PoolClosed instead of generic OperationalError on pool
+ reopening attempt (ticket #1295).
+- Bump python-setuptools BuildRequires minimum version to 80.3.1
+ to match upstream pyproject.toml.
+
+-------------------------------------------------------------------
Old:
----
psycopg_pool-3.3.0.tar.gz
New:
----
psycopg_pool-3.3.3.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-psycopg-pool.spec ++++++
--- /var/tmp/diff_new_pack.Sop9Tj/_old 2026-10-20 12:41:43.008013425 +0200
+++ /var/tmp/diff_new_pack.Sop9Tj/_new 2026-10-20 12:41:43.012013593 +0200
@@ -18,14 +18,14 @@
%{?sle15_python_module_pythons}
Name: python-psycopg-pool
-Version: 3.3.0
+Version: 3.3.3
Release: 0
Summary: Connection Pool for Psycopg
License: LGPL-3.0-only
URL: https://psycopg.org/psycopg3/
-Source:
https://files.pythonhosted.org/packages/source/p/psycopg-pool/psycopg_pool-%{version}.tar.gz
+Source:
https://files.pythonhosted.org/packages/source/p/psycopg_pool/psycopg_pool-%{version}.tar.gz
BuildRequires: %{python_module pip}
-BuildRequires: %{python_module setuptools >= 49.2.0}
+BuildRequires: %{python_module setuptools >= 80.3.1}
BuildRequires: %{python_module wheel >= 0.37}
BuildRequires: fdupes
BuildRequires: python-rpm-macros
++++++ psycopg_pool-3.3.0.tar.gz -> psycopg_pool-3.3.3.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/psycopg_pool-3.3.0/PKG-INFO
new/psycopg_pool-3.3.3/PKG-INFO
--- old/psycopg_pool-3.3.0/PKG-INFO 2025-12-01 04:37:42.109674700 +0100
+++ new/psycopg_pool-3.3.3/PKG-INFO 2026-09-22 17:50:41.969243800 +0200
@@ -1,6 +1,6 @@
Metadata-Version: 2.4
Name: psycopg-pool
-Version: 3.3.0
+Version: 3.3.3
Summary: Connection Pool for Psycopg
Author-email: Daniele Varrazzo <[email protected]>
License-Expression: LGPL-3.0-only
@@ -21,6 +21,7 @@
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
+Classifier: Programming Language :: Python :: 3.15
Classifier: Programming Language :: Python :: Implementation :: CPython
Classifier: Programming Language :: Python :: Implementation :: PyPy
Classifier: Topic :: Database
@@ -33,7 +34,7 @@
Requires-Dist: typing-extensions>=4.6
Provides-Extra: test
Requires-Dist: anyio>=4.0; extra == "test"
-Requires-Dist: mypy>=1.14; extra == "test"
+Requires-Dist: mypy>=2.1.0; extra == "test"
Requires-Dist: pproxy>=2.7; extra == "test"
Requires-Dist: pytest>=6.2.5; extra == "test"
Requires-Dist: pytest-cov>=3.0; extra == "test"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/psycopg_pool-3.3.0/psycopg_pool/_acompat.py
new/psycopg_pool-3.3.3/psycopg_pool/_acompat.py
--- old/psycopg_pool-3.3.0/psycopg_pool/_acompat.py 2025-12-01
04:37:38.000000000 +0100
+++ new/psycopg_pool-3.3.3/psycopg_pool/_acompat.py 2026-09-22
17:50:38.591066800 +0200
@@ -50,11 +50,19 @@
A Queue subclass with an interruptible get() method.
"""
+ # Time to spend in a single wait. Expposed for testing purpose,
+ # in order to inject a timeout.
+ _WAIT_INTERVAL = 10.0 * 60.0
+
def get(self, block: bool = True, timeout: float | None = None) -> T:
- # Always specify a timeout to make the wait interruptible.
- if timeout is None:
- timeout = 24.0 * 60.0 * 60.0
- return super().get(block, timeout)
+ if not block or timeout is not None:
+ return super().get(block, timeout)
+
+ while True:
+ try:
+ return super().get(True, self._WAIT_INTERVAL)
+ except queue.Empty:
+ pass
class AEvent(asyncio.Event):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/psycopg_pool-3.3.0/psycopg_pool/base.py
new/psycopg_pool-3.3.3/psycopg_pool/base.py
--- old/psycopg_pool-3.3.0/psycopg_pool/base.py 2025-12-01 04:37:38.000000000
+0100
+++ new/psycopg_pool-3.3.3/psycopg_pool/base.py 2026-09-22 17:50:38.591066800
+0200
@@ -11,8 +11,6 @@
from typing import TYPE_CHECKING, Any
from collections import Counter, deque
-from psycopg import errors as e
-
from .errors import PoolClosed
if TYPE_CHECKING:
@@ -126,15 +124,13 @@
if max_size < min_size:
raise ValueError("max_size must be greater or equal than min_size")
if min_size == max_size == 0:
- raise ValueError("if min_size is 0 max_size must be greater or
than 0")
+ raise ValueError("if min_size is 0 max_size must be greater than
0")
return min_size, max_size
def _check_open(self) -> None:
if self._closed and self._opened:
- raise e.OperationalError(
- "pool has already been opened/closed and cannot be reused"
- )
+ raise PoolClosed("pool has already been opened/closed and cannot
be reused")
def _check_open_getconn(self) -> None:
if self._closed:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/psycopg_pool-3.3.0/psycopg_pool/pool.py
new/psycopg_pool-3.3.3/psycopg_pool/pool.py
--- old/psycopg_pool-3.3.0/psycopg_pool/pool.py 2025-12-01 04:37:38.000000000
+0100
+++ new/psycopg_pool-3.3.3/psycopg_pool/pool.py 2026-09-22 17:50:38.591066800
+0200
@@ -16,7 +16,7 @@
from types import TracebackType
from typing import Any, Generic, cast
from weakref import ref
-from contextlib import contextmanager
+from contextlib import contextmanager, suppress
from collections import deque
from collections.abc import Iterator
@@ -105,6 +105,10 @@
num_workers=num_workers,
)
+ # Construct the lock during single-threaded `__init__` so that
+ # threads concurrently calling `open()` can't race on it.
+ self._lock = Lock()
+
if open is None:
open = self._open_implicit = True
@@ -222,8 +226,13 @@
conn = self._getconn_unchecked(deadline - monotonic())
try:
self._check_connection(conn)
- except CLIENT_EXCEPTIONS:
+ except Exception:
self._putconn(conn, from_getconn=True)
+ except BaseException:
+ # Cancellation, KeyboardInterrupt etc.: don't lose the
+ # connection, but don't try again either.
+ self._putconn(conn, from_getconn=True)
+ raise
else:
logger.info("connection given by %r", self.name)
return conn
@@ -261,6 +270,8 @@
try:
conn = pos.wait(timeout=timeout)
except CLIENT_EXCEPTIONS:
+ if pos.conn:
+ self.run_task(ReturnConnection(self, pos.conn,
from_getconn=True))
self._stats[self._REQUESTS_ERRORS] += 1
raise
finally:
@@ -378,8 +389,6 @@
because the pool was initialized with *open* = `!True`) but you cannot
currently re-open a closed pool.
"""
- # Make sure the lock is created after there is an event loop
- self._ensure_lock()
with self._lock:
self._open()
@@ -393,9 +402,6 @@
self._check_open()
- # A lock has been most likely, but not necessarily, created in
`open()`.
- self._ensure_lock()
-
# Create these objects now to attach them to the right loop.
# See #219
self._tasks = Queue()
@@ -407,17 +413,6 @@
self._start_workers()
self._start_initial_tasks()
- def _ensure_lock(self) -> None:
- """Make sure the pool lock is created.
-
- In async code, also make sure that the loop is running.
- """
-
- try:
- self._lock
- except AttributeError:
- self._lock = Lock()
-
def _start_workers(self) -> None:
self._sched_runner = spawn(self._sched.run,
name=f"{self.name}-scheduler")
assert not self._workers
@@ -573,7 +568,9 @@
try:
conn.execute("")
finally:
- conn.autocommit = False
+ # Avoid clobbering an exception if the connection is closed
+ with suppress(Exception):
+ conn.autocommit = False
def reconnect_failed(self) -> None:
"""
@@ -894,11 +891,11 @@
except CLIENT_EXCEPTIONS as ex:
self.error = ex
- if self.conn:
- return self.conn
- else:
- assert self.error
+ if self.error:
raise self.error
+ else:
+ assert self.conn
+ return self.conn
def set(self, conn: CT) -> bool:
"""Signal the client waiting that a connection is ready.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/psycopg_pool-3.3.0/psycopg_pool/pool_async.py
new/psycopg_pool-3.3.3/psycopg_pool/pool_async.py
--- old/psycopg_pool-3.3.0/psycopg_pool/pool_async.py 2025-12-01
04:37:38.000000000 +0100
+++ new/psycopg_pool-3.3.3/psycopg_pool/pool_async.py 2026-09-22
17:50:38.591236000 +0200
@@ -13,7 +13,7 @@
from types import TracebackType
from typing import Any, Generic, cast
from weakref import ref
-from contextlib import asynccontextmanager
+from contextlib import asynccontextmanager, suppress
from collections import deque
from collections.abc import AsyncIterator
@@ -117,6 +117,10 @@
if True: # ASYNC
if open:
self._warn_open_async()
+ else:
+ # Construct the lock during single-threaded `__init__` so that
+ # threads concurrently calling `open()` can't race on it.
+ self._lock = ALock()
if open is None:
open = self._open_implicit = True
@@ -259,8 +263,13 @@
conn = await self._getconn_unchecked(deadline - monotonic())
try:
await self._check_connection(conn)
- except CLIENT_EXCEPTIONS:
+ except Exception:
await self._putconn(conn, from_getconn=True)
+ except BaseException:
+ # Cancellation, KeyboardInterrupt etc.: don't lose the
+ # connection, but don't try again either.
+ await self._putconn(conn, from_getconn=True)
+ raise
else:
logger.info("connection given by %r", self.name)
return conn
@@ -298,6 +307,8 @@
try:
conn = await pos.wait(timeout=timeout)
except CLIENT_EXCEPTIONS:
+ if pos.conn:
+ self.run_task(ReturnConnection(self, pos.conn,
from_getconn=True))
self._stats[self._REQUESTS_ERRORS] += 1
raise
finally:
@@ -416,8 +427,9 @@
because the pool was initialized with *open* = `!True`) but you cannot
currently re-open a closed pool.
"""
- # Make sure the lock is created after there is an event loop
- self._ensure_lock()
+ if True: # ASYNC
+ # Make sure the lock is created after there is an event loop
+ self._ensure_lock()
async with self._lock:
self._open()
@@ -431,8 +443,10 @@
self._check_open()
- # A lock has been most likely, but not necessarily, created in
`open()`.
- self._ensure_lock()
+ if True: # ASYNC
+ # A lock has been most likely, but not necessarily, created
+ # in `open()`. The sync pool creates it in `__init__()`.
+ self._ensure_lock()
# Create these objects now to attach them to the right loop.
# See #219
@@ -445,12 +459,16 @@
self._start_workers()
self._start_initial_tasks()
- def _ensure_lock(self) -> None:
- """Make sure the pool lock is created.
+ if True: # ASYNC
+
+ def _ensure_lock(self) -> None:
+ """Make sure the pool lock is created and the loop is running."""
+ try:
+ self._lock
+ return
+ except AttributeError:
+ pass
- In async code, also make sure that the loop is running.
- """
- if True: # ASYNC
try:
asyncio.get_running_loop()
except RuntimeError:
@@ -458,9 +476,6 @@
f"{type(self).__name__} open with no running loop"
) from None
- try:
- self._lock
- except AttributeError:
self._lock = ALock()
def _start_workers(self) -> None:
@@ -622,13 +637,17 @@
try:
await conn.execute("")
finally:
- await conn.set_autocommit(False)
+ # Avoid clobbering an exception if the connection is closed
+ with suppress(Exception):
+ await conn.set_autocommit(False)
else:
conn.autocommit = True
try:
conn.execute("")
finally:
- conn.autocommit = False
+ # Avoid clobbering an exception if the connection is closed
+ with suppress(Exception):
+ conn.autocommit = False
async def reconnect_failed(self) -> None:
"""
@@ -957,11 +976,11 @@
except CLIENT_EXCEPTIONS as ex:
self.error = ex
- if self.conn:
- return self.conn
- else:
- assert self.error
+ if self.error:
raise self.error
+ else:
+ assert self.conn
+ return self.conn
async def set(self, conn: ACT) -> bool:
"""Signal the client waiting that a connection is ready.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/psycopg_pool-3.3.0/psycopg_pool.egg-info/PKG-INFO
new/psycopg_pool-3.3.3/psycopg_pool.egg-info/PKG-INFO
--- old/psycopg_pool-3.3.0/psycopg_pool.egg-info/PKG-INFO 2025-12-01
04:37:42.000000000 +0100
+++ new/psycopg_pool-3.3.3/psycopg_pool.egg-info/PKG-INFO 2026-09-22
17:50:41.952676500 +0200
@@ -1,6 +1,6 @@
Metadata-Version: 2.4
Name: psycopg-pool
-Version: 3.3.0
+Version: 3.3.3
Summary: Connection Pool for Psycopg
Author-email: Daniele Varrazzo <[email protected]>
License-Expression: LGPL-3.0-only
@@ -21,6 +21,7 @@
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
+Classifier: Programming Language :: Python :: 3.15
Classifier: Programming Language :: Python :: Implementation :: CPython
Classifier: Programming Language :: Python :: Implementation :: PyPy
Classifier: Topic :: Database
@@ -33,7 +34,7 @@
Requires-Dist: typing-extensions>=4.6
Provides-Extra: test
Requires-Dist: anyio>=4.0; extra == "test"
-Requires-Dist: mypy>=1.14; extra == "test"
+Requires-Dist: mypy>=2.1.0; extra == "test"
Requires-Dist: pproxy>=2.7; extra == "test"
Requires-Dist: pytest>=6.2.5; extra == "test"
Requires-Dist: pytest-cov>=3.0; extra == "test"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/psycopg_pool-3.3.0/psycopg_pool.egg-info/requires.txt
new/psycopg_pool-3.3.3/psycopg_pool.egg-info/requires.txt
--- old/psycopg_pool-3.3.0/psycopg_pool.egg-info/requires.txt 2025-12-01
04:37:42.000000000 +0100
+++ new/psycopg_pool-3.3.3/psycopg_pool.egg-info/requires.txt 2026-09-22
17:50:41.953518600 +0200
@@ -2,7 +2,7 @@
[test]
anyio>=4.0
-mypy>=1.14
+mypy>=2.1.0
pproxy>=2.7
pytest>=6.2.5
pytest-cov>=3.0
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/psycopg_pool-3.3.0/pyproject.toml
new/psycopg_pool-3.3.3/pyproject.toml
--- old/psycopg_pool-3.3.0/pyproject.toml 2025-12-01 04:37:38.000000000
+0100
+++ new/psycopg_pool-3.3.3/pyproject.toml 2026-09-22 17:50:38.591236000
+0200
@@ -7,7 +7,7 @@
description = "Connection Pool for Psycopg"
# STOP AND READ! if you change:
-version = "3.3.0"
+version = "3.3.3"
# also change:
# - `docs/news_pool.rst` to declare this version current or unreleased
@@ -25,6 +25,7 @@
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
"Programming Language :: Python :: 3.14",
+ "Programming Language :: Python :: 3.15",
"Programming Language :: Python :: Implementation :: CPython",
"Programming Language :: Python :: Implementation :: PyPy",
"Topic :: Database",
@@ -56,7 +57,7 @@
[project.optional-dependencies]
test = [
"anyio >= 4.0",
- "mypy >= 1.14",
+ "mypy >= 2.1.0",
"pproxy >= 2.7",
"pytest >= 6.2.5",
"pytest-cov >= 3.0",