Script 'mail_helper' called by obssrc
Hello community,
here is the log from the commit of package python-cachetools for
openSUSE:Factory checked in at 2026-06-15 19:39:55
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-cachetools (Old)
and /work/SRC/openSUSE:Factory/.python-cachetools.new.1981 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-cachetools"
Mon Jun 15 19:39:55 2026 rev:34 rq:1359221 version:7.1.4
Changes:
--------
--- /work/SRC/openSUSE:Factory/python-cachetools/python-cachetools.changes
2026-05-12 19:26:17.654156992 +0200
+++
/work/SRC/openSUSE:Factory/.python-cachetools.new.1981/python-cachetools.changes
2026-06-15 19:41:28.714472919 +0200
@@ -1,0 +2,13 @@
+Sun Jun 14 09:45:30 UTC 2026 - Dirk Müller <[email protected]>
+
+- update to 7.1.4:
+ * Minor unit test improvements.
+ * Update build environment.
+ * Minor type stub improvements.
+ * Update build environment.
+ * Minor type stub improvements.
+ * Minor documentation improvements.
+ * Modernize build environment.
+ * Various type stub improvements.
+
+-------------------------------------------------------------------
Old:
----
cachetools-7.1.0.tar.gz
New:
----
cachetools-7.1.4.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-cachetools.spec ++++++
--- /var/tmp/diff_new_pack.guY0n8/_old 2026-06-15 19:41:29.678513316 +0200
+++ /var/tmp/diff_new_pack.guY0n8/_new 2026-06-15 19:41:29.678513316 +0200
@@ -18,7 +18,7 @@
%{?sle15_python_module_pythons}
Name: python-cachetools
-Version: 7.1.0
+Version: 7.1.4
Release: 0
Summary: Extensible memoizing collections and decorators
License: MIT
++++++ cachetools-7.1.0.tar.gz -> cachetools-7.1.4.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/cachetools-7.1.0/CHANGELOG.rst
new/cachetools-7.1.4/CHANGELOG.rst
--- old/cachetools-7.1.0/CHANGELOG.rst 2026-05-01 23:13:44.000000000 +0200
+++ new/cachetools-7.1.4/CHANGELOG.rst 2026-05-22 00:35:03.000000000 +0200
@@ -1,3 +1,35 @@
+v7.1.4 (2026-05-22)
+===================
+
+- Minor unit test improvements.
+
+- Update build environment.
+
+
+v7.1.3 (2026-05-18)
+===================
+
+- Minor type stub improvements.
+
+- Update build environment.
+
+
+v7.1.2 (2026-05-16)
+===================
+
+- Minor type stub improvements.
+
+- Minor documentation improvements.
+
+- Modernize build environment.
+
+
+v7.1.1 (2026-05-03)
+===================
+
+- Various type stub improvements.
+
+
v7.1.0 (2026-05-01)
===================
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/cachetools-7.1.0/MANIFEST.in
new/cachetools-7.1.4/MANIFEST.in
--- old/cachetools-7.1.0/MANIFEST.in 2026-03-09 21:22:39.000000000 +0100
+++ new/cachetools-7.1.4/MANIFEST.in 2026-05-22 00:35:03.000000000 +0200
@@ -1,11 +1,3 @@
-include CHANGELOG.rst
-include LICENSE
-include MANIFEST.in
-include README.rst
-include tox.ini
+prune .github/
+exclude .gitignore
exclude .readthedocs.yaml
-
-recursive-include docs *
-prune docs/_build
-
-recursive-include tests *.py
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/cachetools-7.1.0/PKG-INFO
new/cachetools-7.1.4/PKG-INFO
--- old/cachetools-7.1.0/PKG-INFO 2026-05-01 23:15:48.482225400 +0200
+++ new/cachetools-7.1.4/PKG-INFO 2026-05-22 00:37:58.447413000 +0200
@@ -1,6 +1,6 @@
Metadata-Version: 2.4
Name: cachetools
-Version: 7.1.0
+Version: 7.1.4
Summary: Extensible memoizing collections and decorators
Author-email: Thomas Kemmer <[email protected]>
Maintainer-email: Thomas Kemmer <[email protected]>
@@ -46,19 +46,10 @@
:target: https://codecov.io/gh/tkem/cachetools
:alt: Test coverage
-.. image:: https://img.shields.io/librariesio/sourcerank/pypi/cachetools
- :target: https://libraries.io/pypi/cachetools
- :alt: Libraries.io SourceRank
-
.. image:: https://img.shields.io/github/license/tkem/cachetools
:target: https://raw.github.com/tkem/cachetools/master/LICENSE
:alt: License
-.. image:: https://img.shields.io/badge/code%20style-black-000000.svg
- :target: https://github.com/psf/black
- :alt: Code style: black
-
-
This module provides various memoizing collections and decorators,
including variants of the Python Standard Library's `@lru_cache`_
function decorator.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/cachetools-7.1.0/README.rst
new/cachetools-7.1.4/README.rst
--- old/cachetools-7.1.0/README.rst 2026-05-01 23:13:29.000000000 +0200
+++ new/cachetools-7.1.4/README.rst 2026-05-17 21:35:51.000000000 +0200
@@ -17,19 +17,10 @@
:target: https://codecov.io/gh/tkem/cachetools
:alt: Test coverage
-.. image:: https://img.shields.io/librariesio/sourcerank/pypi/cachetools
- :target: https://libraries.io/pypi/cachetools
- :alt: Libraries.io SourceRank
-
.. image:: https://img.shields.io/github/license/tkem/cachetools
:target: https://raw.github.com/tkem/cachetools/master/LICENSE
:alt: License
-.. image:: https://img.shields.io/badge/code%20style-black-000000.svg
- :target: https://github.com/psf/black
- :alt: Code style: black
-
-
This module provides various memoizing collections and decorators,
including variants of the Python Standard Library's `@lru_cache`_
function decorator.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/cachetools-7.1.0/docs/index.rst
new/cachetools-7.1.4/docs/index.rst
--- old/cachetools-7.1.0/docs/index.rst 2026-03-09 21:21:03.000000000 +0100
+++ new/cachetools-7.1.4/docs/index.rst 2026-05-17 21:35:51.000000000 +0200
@@ -88,6 +88,10 @@
This class evicts items in the order they were added to make space
when necessary.
+ Updating a cache item via :meth:`FIFOCache.__setitem__` will act
+ like a re-insertion, i.e. deleting the item followed by an insert,
+ and therefore will reset the item's position in the cache.
+
.. autoclass:: LFUCache(maxsize, getsizeof=None)
:members: popitem
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/cachetools-7.1.0/pyproject.toml
new/cachetools-7.1.4/pyproject.toml
--- old/cachetools-7.1.0/pyproject.toml 2026-05-01 23:13:29.000000000 +0200
+++ new/cachetools-7.1.4/pyproject.toml 2026-05-22 00:35:03.000000000 +0200
@@ -1,5 +1,5 @@
[build-system]
-requires = ["setuptools >= 61.0.0", "wheel"]
+requires = ["setuptools >= 80", "setuptools-scm >= 8.2"]
build-backend = "setuptools.build_meta"
[project]
@@ -47,17 +47,8 @@
[tool.setuptools.dynamic]
version = {attr = "cachetools.__version__"}
-[tool.flake8]
-max-line-length = 80
-exclude = [".git", ".tox", "build"]
-select = ["C", "E", "F", "W", "B", "B950", "I", "N"]
-# F401: imported but unused (submodule shims)
-# E501: line too long (black)
-# E704: multiple statements on one line (typehints)
-ignore = ["F401", "E501", "E704"]
-
[tool.pyright]
typeCheckingMode = "standard"
-reportFunctionMemberAccess = false
-reportOptionalContextManager = false
-reportOptionalMemberAccess = false
\ No newline at end of file
+reportFunctionMemberAccess = "information"
+reportOptionalContextManager = "warning"
+reportOptionalMemberAccess = "warning"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/cachetools-7.1.0/src/cachetools/__init__.py
new/cachetools-7.1.4/src/cachetools/__init__.py
--- old/cachetools-7.1.0/src/cachetools/__init__.py 2026-05-01
23:13:29.000000000 +0200
+++ new/cachetools-7.1.4/src/cachetools/__init__.py 2026-05-22
00:35:03.000000000 +0200
@@ -12,7 +12,7 @@
"cachedmethod",
)
-__version__ = "7.1.0"
+__version__ = "7.1.4"
import collections
import collections.abc
@@ -23,9 +23,6 @@
from . import keys
-# Typing stubs for this package are provided by typeshed:
-# https://github.com/python/typeshed/tree/main/stubs/cachetools
-
class _DefaultSize:
"""A minimal "fake" dict that returns a constant size 1 for any key."""
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/cachetools-7.1.0/src/cachetools/__init__.pyi
new/cachetools-7.1.4/src/cachetools/__init__.pyi
--- old/cachetools-7.1.0/src/cachetools/__init__.pyi 2026-05-01
23:13:29.000000000 +0200
+++ new/cachetools-7.1.4/src/cachetools/__init__.pyi 2026-05-17
21:35:51.000000000 +0200
@@ -3,10 +3,12 @@
from contextlib import AbstractContextManager
from typing import (
Any,
+ Concatenate,
Final,
Generic,
Literal,
NamedTuple,
+ ParamSpec,
Protocol,
TypeVar,
overload,
@@ -26,11 +28,12 @@
)
__version__: str
+_P = ParamSpec("_P")
+_R = TypeVar("_R")
+_T = TypeVar("_T")
_KT = TypeVar("_KT")
_VT = TypeVar("_VT")
_TT = TypeVar("_TT", default=float)
-_T = TypeVar("_T")
-_R = TypeVar("_R")
_KT2 = TypeVar("_KT2")
_VT2 = TypeVar("_VT2")
@@ -147,19 +150,19 @@
def notify_all(self) -> None: ...
@type_check_only
-class _cached_wrapper(Generic[_R]):
- __wrapped__: Callable[..., _R]
+class _cached_wrapper(Generic[_P, _R]):
+ __wrapped__: Callable[_P, _R]
__name__: str
__doc__: str | None
cache: MutableMapping[Any, Any] | None
cache_key: Callable[..., Any] = ...
cache_lock: AbstractContextManager[Any] | None = None
cache_condition: _AbstractCondition | None = None
- def __call__(self, /, *args: Any, **kwargs: Any) -> _R: ...
+ def __call__(self, /, *args: _P.args, **kwargs: _P.kwargs) -> _R: ...
def cache_clear(self) -> None: ...
@type_check_only
-class _cached_wrapper_info(_cached_wrapper[_R]):
+class _cached_wrapper_info(_cached_wrapper[_P, _R]):
def cache_info(self) -> _CacheInfo: ...
@overload
@@ -168,31 +171,47 @@
key: Callable[..., _KT] = ...,
lock: AbstractContextManager[Any] | None = None,
condition: _AbstractCondition | None = None,
- info: Literal[True] = ...,
-) -> Callable[[Callable[..., _R]], _cached_wrapper_info[_R]]: ...
+ info: Literal[False] = ...,
+) -> Callable[[Callable[_P, _R]], _cached_wrapper[_P, _R]]: ...
@overload
def cached(
cache: MutableMapping[_KT, Any] | None,
key: Callable[..., _KT] = ...,
lock: AbstractContextManager[Any] | None = None,
condition: _AbstractCondition | None = None,
- info: Literal[False] = ...,
-) -> Callable[[Callable[..., _R]], _cached_wrapper[_R]]: ...
+ *,
+ info: Literal[True],
+) -> Callable[[Callable[_P, _R]], _cached_wrapper_info[_P, _R]]: ...
+@overload
+def cached(
+ cache: MutableMapping[_KT, Any] | None,
+ key: Callable[..., _KT],
+ lock: AbstractContextManager[Any] | None,
+ condition: _AbstractCondition | None,
+ info: Literal[True],
+) -> Callable[[Callable[_P, _R]], _cached_wrapper_info[_P, _R]]: ...
@type_check_only
-class _cachedmethod_wrapper(Generic[_R]):
- __wrapped__: Callable[..., _R]
+class _cachedmethod_wrapper(Generic[_P, _R]):
+ __wrapped__: Callable[Concatenate[Any, _P], _R]
__name__: str
__doc__: str | None
- cache: MutableMapping[Any, Any] | None
+ cache: MutableMapping[Any, Any]
cache_key: Callable[..., Any] = ...
cache_lock: AbstractContextManager[Any] | None = None
cache_condition: _AbstractCondition | None = None
- def __call__(self, /, *args: Any, **kwargs: Any) -> _R: ...
+ def __set_name__(self, owner: type, name: str) -> None: ...
+ def __get__(
+ self, obj: Any, objtype: type | None = None
+ ) -> _cachedmethod_wrapper[_P, _R]: ...
+ def __call__(self, /, *args: _P.args, **kwargs: _P.kwargs) -> _R: ...
def cache_clear(self) -> None: ...
@type_check_only
-class _cachedmethod_wrapper_info(_cachedmethod_wrapper[_R]):
+class _cachedmethod_wrapper_info(_cachedmethod_wrapper[_P, _R]):
+ def __get__(
+ self, obj: Any, objtype: type | None = None
+ ) -> _cachedmethod_wrapper_info[_P, _R]: ...
def cache_info(self) -> _CacheInfo: ...
@overload
@@ -201,13 +220,26 @@
key: Callable[..., _KT] = ...,
lock: Callable[[Any], AbstractContextManager[Any]] | None = None,
condition: Callable[[Any], _AbstractCondition] | None = None,
- info: Literal[True] = ...,
-) -> Callable[[Callable[..., _R]], _cachedmethod_wrapper_info[_R]]: ...
+ info: Literal[False] = ...,
+) -> Callable[[Callable[Concatenate[Any, _P], _R]], _cachedmethod_wrapper[_P,
_R]]: ...
@overload
def cachedmethod(
cache: Callable[[Any], MutableMapping[_KT, Any]],
key: Callable[..., _KT] = ...,
lock: Callable[[Any], AbstractContextManager[Any]] | None = None,
condition: Callable[[Any], _AbstractCondition] | None = None,
- info: Literal[False] = ...,
-) -> Callable[[Callable[..., _R]], _cachedmethod_wrapper[_R]]: ...
+ *,
+ info: Literal[True],
+) -> Callable[
+ [Callable[Concatenate[Any, _P], _R]], _cachedmethod_wrapper_info[_P, _R]
+]: ...
+@overload
+def cachedmethod(
+ cache: Callable[[Any], MutableMapping[_KT, Any]],
+ key: Callable[..., _KT],
+ lock: Callable[[Any], AbstractContextManager[Any]] | None,
+ condition: Callable[[Any], _AbstractCondition] | None,
+ info: Literal[True],
+) -> Callable[
+ [Callable[Concatenate[Any, _P], _R]], _cachedmethod_wrapper_info[_P, _R]
+]: ...
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/cachetools-7.1.0/src/cachetools/func.py
new/cachetools-7.1.4/src/cachetools/func.py
--- old/cachetools-7.1.0/src/cachetools/func.py 2026-05-01 23:13:29.000000000
+0200
+++ new/cachetools-7.1.4/src/cachetools/func.py 2026-05-17 21:35:51.000000000
+0200
@@ -2,7 +2,6 @@
__all__ = ("fifo_cache", "lfu_cache", "lru_cache", "rr_cache", "ttl_cache")
-import functools
import math
import random
import time
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/cachetools-7.1.0/src/cachetools/func.pyi
new/cachetools-7.1.4/src/cachetools/func.pyi
--- old/cachetools-7.1.0/src/cachetools/func.pyi 2026-05-01
23:13:29.000000000 +0200
+++ new/cachetools-7.1.4/src/cachetools/func.pyi 2026-05-18
20:09:02.000000000 +0200
@@ -1,19 +1,20 @@
from collections.abc import Callable, Sequence
-from typing import Any, Final, Generic, TypeVar, overload, type_check_only
+from typing import Any, Final, Generic, ParamSpec, TypeVar, overload,
type_check_only
from . import _CacheInfo
__all__: Final = ("fifo_cache", "lfu_cache", "lru_cache", "rr_cache",
"ttl_cache")
+_P = ParamSpec("_P")
_T = TypeVar("_T")
_R = TypeVar("_R")
@type_check_only
-class _cachetools_cache_wrapper(Generic[_R]):
- __wrapped__: Callable[..., _R]
+class _cachetools_cache_wrapper(Generic[_P, _R]):
+ __wrapped__: Callable[_P, _R]
__name__: str
__doc__: str | None
- def __call__(self, /, *args: Any, **kwargs: Any) -> _R: ...
+ def __call__(self, /, *args: _P.args, **kwargs: _P.kwargs) -> _R: ...
def cache_info(self) -> _CacheInfo: ...
def cache_clear(self) -> None: ...
def cache_parameters(self) -> dict[str, Any]: ...
@@ -21,50 +22,50 @@
@overload
def fifo_cache(
maxsize: int | None = 128, typed: bool = False
-) -> Callable[[Callable[..., _R]], _cachetools_cache_wrapper[_R]]: ...
+) -> Callable[[Callable[_P, _R]], _cachetools_cache_wrapper[_P, _R]]: ...
@overload
def fifo_cache(
- maxsize: Callable[..., _R], typed: bool = False
-) -> _cachetools_cache_wrapper[_R]: ...
+ maxsize: Callable[_P, _R], typed: bool = False
+) -> _cachetools_cache_wrapper[_P, _R]: ...
@overload
def lfu_cache(
maxsize: int | None = 128, typed: bool = False
-) -> Callable[[Callable[..., _R]], _cachetools_cache_wrapper[_R]]: ...
+) -> Callable[[Callable[_P, _R]], _cachetools_cache_wrapper[_P, _R]]: ...
@overload
def lfu_cache(
- maxsize: Callable[..., _R], typed: bool = False
-) -> _cachetools_cache_wrapper[_R]: ...
+ maxsize: Callable[_P, _R], typed: bool = False
+) -> _cachetools_cache_wrapper[_P, _R]: ...
@overload
def lru_cache(
maxsize: int | None = 128, typed: bool = False
-) -> Callable[[Callable[..., _R]], _cachetools_cache_wrapper[_R]]: ...
+) -> Callable[[Callable[_P, _R]], _cachetools_cache_wrapper[_P, _R]]: ...
@overload
def lru_cache(
- maxsize: Callable[..., _R], typed: bool = False
-) -> _cachetools_cache_wrapper[_R]: ...
+ maxsize: Callable[_P, _R], typed: bool = False
+) -> _cachetools_cache_wrapper[_P, _R]: ...
@overload
def rr_cache(
maxsize: int | None = 128,
choice: Callable[[Sequence[_T]], _T] = ...,
typed: bool = False,
-) -> Callable[[Callable[..., _R]], _cachetools_cache_wrapper[_R]]: ...
+) -> Callable[[Callable[_P, _R]], _cachetools_cache_wrapper[_P, _R]]: ...
@overload
def rr_cache(
- maxsize: Callable[..., _R],
+ maxsize: Callable[_P, _R],
choice: Callable[[Sequence[_T]], _T] = ...,
typed: bool = False,
-) -> _cachetools_cache_wrapper[_R]: ...
+) -> _cachetools_cache_wrapper[_P, _R]: ...
@overload
def ttl_cache(
maxsize: int | None = 128,
ttl: Any = 600,
timer: Callable[[], _T] = ...,
typed: bool = False,
-) -> Callable[[Callable[..., _R]], _cachetools_cache_wrapper[_R]]: ...
+) -> Callable[[Callable[_P, _R]], _cachetools_cache_wrapper[_P, _R]]: ...
@overload
def ttl_cache(
- maxsize: Callable[..., _R],
+ maxsize: Callable[_P, _R],
ttl: Any = 600,
timer: Callable[[], _T] = ...,
typed: bool = False,
-) -> _cachetools_cache_wrapper[_R]: ...
+) -> _cachetools_cache_wrapper[_P, _R]: ...
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/cachetools-7.1.0/src/cachetools.egg-info/PKG-INFO
new/cachetools-7.1.4/src/cachetools.egg-info/PKG-INFO
--- old/cachetools-7.1.0/src/cachetools.egg-info/PKG-INFO 2026-05-01
23:15:48.000000000 +0200
+++ new/cachetools-7.1.4/src/cachetools.egg-info/PKG-INFO 2026-05-22
00:37:58.000000000 +0200
@@ -1,6 +1,6 @@
Metadata-Version: 2.4
Name: cachetools
-Version: 7.1.0
+Version: 7.1.4
Summary: Extensible memoizing collections and decorators
Author-email: Thomas Kemmer <[email protected]>
Maintainer-email: Thomas Kemmer <[email protected]>
@@ -46,19 +46,10 @@
:target: https://codecov.io/gh/tkem/cachetools
:alt: Test coverage
-.. image:: https://img.shields.io/librariesio/sourcerank/pypi/cachetools
- :target: https://libraries.io/pypi/cachetools
- :alt: Libraries.io SourceRank
-
.. image:: https://img.shields.io/github/license/tkem/cachetools
:target: https://raw.github.com/tkem/cachetools/master/LICENSE
:alt: License
-.. image:: https://img.shields.io/badge/code%20style-black-000000.svg
- :target: https://github.com/psf/black
- :alt: Code style: black
-
-
This module provides various memoizing collections and decorators,
including variants of the Python Standard Library's `@lru_cache`_
function decorator.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/cachetools-7.1.0/tests/__init__.py
new/cachetools-7.1.4/tests/__init__.py
--- old/cachetools-7.1.0/tests/__init__.py 2026-05-01 23:13:29.000000000
+0200
+++ new/cachetools-7.1.4/tests/__init__.py 2026-05-17 21:35:51.000000000
+0200
@@ -1,5 +1,5 @@
from collections.abc import Container, Iterable
-from typing import Any, Protocol, TypeAlias, no_type_check
+from typing import Any, Protocol
import cachetools
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/cachetools-7.1.0/tests/test_cached.py
new/cachetools-7.1.4/tests/test_cached.py
--- old/cachetools-7.1.0/tests/test_cached.py 2026-05-01 23:13:29.000000000
+0200
+++ new/cachetools-7.1.4/tests/test_cached.py 2026-05-17 21:35:51.000000000
+0200
@@ -1,5 +1,4 @@
import unittest
-import warnings
import cachetools
import cachetools.keys
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/cachetools-7.1.0/tests/test_cachedmethod.py
new/cachetools-7.1.4/tests/test_cachedmethod.py
--- old/cachetools-7.1.0/tests/test_cachedmethod.py 2026-05-01
23:13:29.000000000 +0200
+++ new/cachetools-7.1.4/tests/test_cachedmethod.py 2026-05-17
21:35:51.000000000 +0200
@@ -517,7 +517,6 @@
class CacheMethodTest(unittest.TestCase, MethodDecoratorTestMixin):
-
def cache(self, minsize, **kwargs):
return Cache(maxsize=minsize, **kwargs)
@@ -636,13 +635,11 @@
class DictMethodTest(unittest.TestCase, MethodDecoratorTestMixin):
-
def cache(self, minsize, **_kwargs):
return dict()
class WeakRefMethodTest(unittest.TestCase):
-
def test_weakref(self):
import fractions
import gc
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/cachetools-7.1.0/tests/test_threading.py
new/cachetools-7.1.4/tests/test_threading.py
--- old/cachetools-7.1.0/tests/test_threading.py 2026-05-01
23:13:29.000000000 +0200
+++ new/cachetools-7.1.4/tests/test_threading.py 2026-05-22
00:35:03.000000000 +0200
@@ -1,7 +1,6 @@
import threading
import time
import unittest
-from os import environ
from typing import Any
from cachetools import LRUCache, cached, cachedmethod
@@ -17,31 +16,50 @@
return count
[email protected](environ.get("THREADING_TESTS", False), "THREADING_TESTS
not set")
-class ThreadingTest(unittest.TestCase):
+@cached(cache=LRUCache(1), lock=threading.Lock(), info=True)
+def locked_func():
+ global count
+ time.sleep(1.0)
+ count += 1
+ return 42
+
+class ThreadingTest(unittest.TestCase):
NTHREADS = 10
+ TIMEOUT = 10
+
cache: LRUCache[Any, int] = LRUCache(1)
cond = threading.Condition()
+ lock = threading.Lock()
+
count = 0
@cachedmethod(
cache=lambda self: self.cache, condition=lambda self: self.cond,
info=True
)
- def meth(self):
+ def method(self):
+ time.sleep(1.0)
+ self.count += 1
+ return 42
+
+ @cachedmethod(cache=lambda self: self.cache, lock=lambda self: self.lock,
info=True)
+ def locked_method(self):
time.sleep(1.0)
self.count += 1
return 42
def test_cached_stampede(self):
+ global count
+ count = 0
threads = [threading.Thread(target=func) for i in range(0,
self.NTHREADS)]
for t in threads:
t.start()
for t in threads:
- t.join()
+ t.join(timeout=self.TIMEOUT)
+ self.assertFalse(t.is_alive())
self.assertEqual(count, 1)
@@ -50,14 +68,59 @@
self.assertEqual(info.misses, 1)
def test_cachedmethod_stampede(self):
- threads = [threading.Thread(target=self.meth) for i in range(0,
self.NTHREADS)]
+ self.cache = LRUCache(1)
+ self.count = 0
+ threads = [
+ threading.Thread(target=self.method) for i in range(0,
self.NTHREADS)
+ ]
for t in threads:
t.start()
for t in threads:
- t.join()
+ t.join(timeout=self.TIMEOUT)
+ self.assertFalse(t.is_alive())
self.assertEqual(self.count, 1)
- info = self.meth.cache_info()
+ info = self.method.cache_info()
self.assertEqual(info.hits, self.NTHREADS - 1)
self.assertEqual(info.misses, 1)
+
+ def test_cached_locked(self):
+ global count
+ count = 0
+ threads = [
+ threading.Thread(target=locked_func) for i in range(0,
self.NTHREADS)
+ ]
+ for t in threads:
+ t.start()
+ for t in threads:
+ t.join(timeout=self.TIMEOUT)
+ self.assertFalse(t.is_alive())
+
+ # Without condition/stampede prevention, func is called by multiple
+ # threads, but all return the same cached value (42).
+ self.assertGreaterEqual(count, 1)
+
+ info = locked_func.cache_info()
+ self.assertEqual(info.hits + info.misses, self.NTHREADS)
+ self.assertGreaterEqual(info.misses, 1)
+
+ def test_cachedmethod_locked(self):
+ self.cache = LRUCache(1)
+ self.count = 0
+ threads = [
+ threading.Thread(target=self.locked_method) for i in range(0,
self.NTHREADS)
+ ]
+ for t in threads:
+ t.start()
+ for t in threads:
+ t.join(timeout=self.TIMEOUT)
+ self.assertFalse(t.is_alive())
+
+ # Multiple threads may compute the value, but setdefault ensures
+ # the first cached result wins and all return 42.
+ self.assertGreaterEqual(self.count, 1)
+
+ info = self.locked_method.cache_info()
+ self.assertEqual(info.hits + info.misses, self.NTHREADS)
+ self.assertGreaterEqual(info.misses, 1)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/cachetools-7.1.0/tox.ini new/cachetools-7.1.4/tox.ini
--- old/cachetools-7.1.0/tox.ini 2026-05-01 23:13:29.000000000 +0200
+++ new/cachetools-7.1.4/tox.ini 2026-05-22 00:35:03.000000000 +0200
@@ -1,22 +1,13 @@
[tox]
-envlist = check-manifest,docs,doctest,flake8,pyright,py
+envlist = py,docs,doctest,ruff,ruff-format,pyright
[testenv]
deps =
pytest
pytest-cov
-setenv =
- THREADING_TESTS = 1
commands =
py.test --basetemp={envtmpdir} --cov=cachetools --cov-report term-missing
{posargs}
-[testenv:check-manifest]
-deps =
- check-manifest
-commands =
- check-manifest
-skip_install = true
-
[testenv:docs]
deps =
sphinx
@@ -29,15 +20,18 @@
commands =
sphinx-build -W -b doctest -d {envtmpdir}/doctrees docs
{envtmpdir}/doctest
-[testenv:flake8]
+[testenv:ruff]
+deps =
+ ruff
+commands =
+ ruff check {posargs}
+skip_install = true
+
+[testenv:ruff-format]
deps =
- flake8
- flake8-black
- flake8-bugbear
- flake8-import-order
- flake8-pyproject
+ ruff
commands =
- flake8
+ ruff format --diff -q {posargs}
skip_install = true
[testenv:pyright]