cachetools 6.2.1__tar.gz → 6.2.3__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. {cachetools-6.2.1 → cachetools-6.2.3}/CHANGELOG.rst +21 -0
  2. {cachetools-6.2.1/src/cachetools.egg-info → cachetools-6.2.3}/PKG-INFO +8 -7
  3. {cachetools-6.2.1 → cachetools-6.2.3}/README.rst +2 -0
  4. {cachetools-6.2.1 → cachetools-6.2.3}/docs/index.rst +8 -2
  5. cachetools-6.2.3/pyproject.toml +52 -0
  6. cachetools-6.2.3/setup.cfg +4 -0
  7. {cachetools-6.2.1 → cachetools-6.2.3}/src/cachetools/__init__.py +17 -10
  8. {cachetools-6.2.1 → cachetools-6.2.3}/src/cachetools/_cached.py +8 -3
  9. {cachetools-6.2.1 → cachetools-6.2.3}/src/cachetools/keys.py +4 -3
  10. {cachetools-6.2.1 → cachetools-6.2.3/src/cachetools.egg-info}/PKG-INFO +8 -7
  11. {cachetools-6.2.1 → cachetools-6.2.3}/src/cachetools.egg-info/SOURCES.txt +0 -2
  12. {cachetools-6.2.1 → cachetools-6.2.3}/tox.ini +1 -0
  13. cachetools-6.2.1/pyproject.toml +0 -3
  14. cachetools-6.2.1/setup.cfg +0 -50
  15. cachetools-6.2.1/setup.py +0 -3
  16. {cachetools-6.2.1 → cachetools-6.2.3}/LICENSE +0 -0
  17. {cachetools-6.2.1 → cachetools-6.2.3}/MANIFEST.in +0 -0
  18. {cachetools-6.2.1 → cachetools-6.2.3}/docs/conf.py +0 -0
  19. {cachetools-6.2.1 → cachetools-6.2.3}/src/cachetools/_cachedmethod.py +0 -0
  20. {cachetools-6.2.1 → cachetools-6.2.3}/src/cachetools/func.py +0 -0
  21. {cachetools-6.2.1 → cachetools-6.2.3}/src/cachetools.egg-info/dependency_links.txt +0 -0
  22. {cachetools-6.2.1 → cachetools-6.2.3}/src/cachetools.egg-info/top_level.txt +0 -0
  23. {cachetools-6.2.1 → cachetools-6.2.3}/tests/__init__.py +0 -0
  24. {cachetools-6.2.1 → cachetools-6.2.3}/tests/test_cache.py +0 -0
  25. {cachetools-6.2.1 → cachetools-6.2.3}/tests/test_cached.py +0 -0
  26. {cachetools-6.2.1 → cachetools-6.2.3}/tests/test_cachedmethod.py +0 -0
  27. {cachetools-6.2.1 → cachetools-6.2.3}/tests/test_fifo.py +0 -0
  28. {cachetools-6.2.1 → cachetools-6.2.3}/tests/test_func.py +0 -0
  29. {cachetools-6.2.1 → cachetools-6.2.3}/tests/test_keys.py +0 -0
  30. {cachetools-6.2.1 → cachetools-6.2.3}/tests/test_lfu.py +0 -0
  31. {cachetools-6.2.1 → cachetools-6.2.3}/tests/test_lru.py +0 -0
  32. {cachetools-6.2.1 → cachetools-6.2.3}/tests/test_rr.py +0 -0
  33. {cachetools-6.2.1 → cachetools-6.2.3}/tests/test_tlru.py +0 -0
  34. {cachetools-6.2.1 → cachetools-6.2.3}/tests/test_ttl.py +0 -0
@@ -1,3 +1,24 @@
1
+ v6.2.3 (2025-12-12)
2
+ ===================
3
+
4
+ - Improve documentation regarding ``@cachedmethod`` with ``condition``
5
+ parameter.
6
+
7
+ - Minor style and readability improvements.
8
+
9
+ - Modernize build environment.
10
+
11
+ - Update CI environment.
12
+
13
+
14
+ v6.2.2 (2025-11-13)
15
+ ===================
16
+
17
+ - Minor improvements from GitHub Copilot code review.
18
+
19
+ - Improve documentation.
20
+
21
+
1
22
  v6.2.1 (2025-10-12)
2
23
  ===================
3
24
 
@@ -1,15 +1,13 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cachetools
3
- Version: 6.2.1
3
+ Version: 6.2.3
4
4
  Summary: Extensible memoizing collections and decorators
5
- Home-page: https://github.com/tkem/cachetools/
6
- Author: Thomas Kemmer
7
- Author-email: tkemmer@computer.org
8
- License: MIT
5
+ Author-email: Thomas Kemmer <tkemmer@computer.org>
6
+ Maintainer-email: Thomas Kemmer <tkemmer@computer.org>
7
+ License-Expression: MIT
8
+ Project-URL: Homepage, https://github.com/tkem/cachetools/
9
9
  Classifier: Development Status :: 5 - Production/Stable
10
- Classifier: Environment :: Other Environment
11
10
  Classifier: Intended Audience :: Developers
12
- Classifier: License :: OSI Approved :: MIT License
13
11
  Classifier: Operating System :: OS Independent
14
12
  Classifier: Programming Language :: Python
15
13
  Classifier: Programming Language :: Python :: 3
@@ -21,6 +19,7 @@ Classifier: Programming Language :: Python :: 3.13
21
19
  Classifier: Programming Language :: Python :: 3.14
22
20
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
23
21
  Requires-Python: >=3.9
22
+ Description-Content-Type: text/x-rst
24
23
  License-File: LICENSE
25
24
  Dynamic: license-file
26
25
 
@@ -117,6 +116,7 @@ Related Projects
117
116
  ------------------------------------------------------------------------
118
117
 
119
118
  - asyncache_: Helpers to use cachetools_ with asyncio.
119
+ - cachetools-async_: Helpers to use cachetools_ with asyncio.
120
120
  - cacheing_: Pure Python Cacheing Library.
121
121
  - CacheToolsUtils_: Stackable cache classes for sharing, encryption,
122
122
  statistics *and more* on top of cachetools_, redis_ and memcached_.
@@ -146,6 +146,7 @@ Licensed under the `MIT License`_.
146
146
  .. _MIT License: https://raw.github.com/tkem/cachetools/master/LICENSE
147
147
 
148
148
  .. _asyncache: https://pypi.org/project/asyncache/
149
+ .. _cachetools-async: https://pypi.org/project/cachetools-async/
149
150
  .. _cacheing: https://pypi.org/project/cacheing/
150
151
  .. _CacheToolsUtils: https://pypi.org/project/CacheToolsUtils/
151
152
  .. _shelved-cache: https://pypi.org/project/shelved-cache/
@@ -91,6 +91,7 @@ Related Projects
91
91
  ------------------------------------------------------------------------
92
92
 
93
93
  - asyncache_: Helpers to use cachetools_ with asyncio.
94
+ - cachetools-async_: Helpers to use cachetools_ with asyncio.
94
95
  - cacheing_: Pure Python Cacheing Library.
95
96
  - CacheToolsUtils_: Stackable cache classes for sharing, encryption,
96
97
  statistics *and more* on top of cachetools_, redis_ and memcached_.
@@ -120,6 +121,7 @@ Licensed under the `MIT License`_.
120
121
  .. _MIT License: https://raw.github.com/tkem/cachetools/master/LICENSE
121
122
 
122
123
  .. _asyncache: https://pypi.org/project/asyncache/
124
+ .. _cachetools-async: https://pypi.org/project/cachetools-async/
123
125
  .. _cacheing: https://pypi.org/project/cacheing/
124
126
  .. _CacheToolsUtils: https://pypi.org/project/CacheToolsUtils/
125
127
  .. _shelved-cache: https://pypi.org/project/shelved-cache/
@@ -232,7 +232,7 @@ With :class:`TTLCache` and :class:`TLRUCache`, items may also be
232
232
  removed after they expire. In this case, :meth:`popitem` will *not*
233
233
  be called, but :meth:`expire` will be called from the next mutating
234
234
  operation and will return an iterable of the expired `(key, value)`
235
- pairs. By overrding :meth:`expire`, a subclass will be able to track
235
+ pairs. By overriding :meth:`expire`, a subclass will be able to track
236
236
  expired items:
237
237
 
238
238
  .. doctest::
@@ -492,7 +492,7 @@ often called with the same arguments:
492
492
  might expect, and also the use of positional vs. keyword arguments
493
493
  may lead to surprising results. In the example below, `foo()`,
494
494
  `foo(1)` and `foo(a=1)` are treated as different function
495
- invocations, with seperately cached results:
495
+ invocations, with separately cached results:
496
496
 
497
497
  .. doctest::
498
498
  :pyversion: >= 3
@@ -555,6 +555,12 @@ often called with the same arguments:
555
555
  function, :func:`cachetools.keys.methodkey`, ignores its first
556
556
  argument, i.e. :const:`self`. This has mostly historical reasons,
557
557
  but also ensures that :const:`self` does not have to be hashable.
558
+
559
+ .. note::
560
+
561
+ Using :func:`cachedmethod` with a `condition` currently *does*
562
+ require :const:`self` be hashable, though.
563
+
558
564
  You may provide a different `key` function,
559
565
  e.g. :func:`cachetools.keys.hashkey`, if you need :const:`self` to
560
566
  be part of the cache key.
@@ -0,0 +1,52 @@
1
+ [build-system]
2
+ requires = ["setuptools >= 61.0.0", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "cachetools"
7
+ dynamic = ["version"]
8
+ description = "Extensible memoizing collections and decorators"
9
+ authors = [
10
+ {name = "Thomas Kemmer", email = "tkemmer@computer.org"}
11
+ ]
12
+ maintainers = [
13
+ {name = "Thomas Kemmer", email = "tkemmer@computer.org"}
14
+ ]
15
+ readme = "README.rst"
16
+ license = "MIT"
17
+ license-files = ["LICENSE"]
18
+ requires-python = ">= 3.9"
19
+ classifiers = [
20
+ "Development Status :: 5 - Production/Stable",
21
+ "Intended Audience :: Developers",
22
+ "Operating System :: OS Independent",
23
+ "Programming Language :: Python",
24
+ "Programming Language :: Python :: 3",
25
+ "Programming Language :: Python :: 3.9",
26
+ "Programming Language :: Python :: 3.10",
27
+ "Programming Language :: Python :: 3.11",
28
+ "Programming Language :: Python :: 3.12",
29
+ "Programming Language :: Python :: 3.13",
30
+ "Programming Language :: Python :: 3.14",
31
+ "Topic :: Software Development :: Libraries :: Python Modules",
32
+ ]
33
+
34
+ [project.urls]
35
+ Homepage = "https://github.com/tkem/cachetools/"
36
+
37
+ [tool.setuptools]
38
+ package-dir = {"" = "src"}
39
+
40
+ [tool.setuptools.packages.find]
41
+ where = ["src"]
42
+
43
+ [tool.setuptools.dynamic]
44
+ version = {attr = "cachetools.__version__"}
45
+
46
+ [tool.flake8]
47
+ max-line-length = 80
48
+ exclude = [".git", ".tox", "build"]
49
+ select = ["C", "E", "F", "W", "B", "B950", "I", "N"]
50
+ # F401: imported but unused (submodule shims)
51
+ # E501: line too long (black)
52
+ ignore = ["F401", "E501"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -12,7 +12,7 @@ __all__ = (
12
12
  "cachedmethod",
13
13
  )
14
14
 
15
- __version__ = "6.2.1"
15
+ __version__ = "6.2.3"
16
16
 
17
17
  import collections
18
18
  import collections.abc
@@ -27,13 +27,13 @@ from . import keys
27
27
  class _DefaultSize:
28
28
  __slots__ = ()
29
29
 
30
- def __getitem__(self, _):
30
+ def __getitem__(self, _key):
31
31
  return 1
32
32
 
33
- def __setitem__(self, _, value):
34
- assert value == 1
33
+ def __setitem__(self, _key, _value):
34
+ pass
35
35
 
36
- def pop(self, _):
36
+ def pop(self, _key):
37
37
  return 1
38
38
 
39
39
 
@@ -55,7 +55,7 @@ class Cache(collections.abc.MutableMapping):
55
55
 
56
56
  def __repr__(self):
57
57
  return "%s(%s, maxsize=%r, currsize=%r)" % (
58
- self.__class__.__name__,
58
+ type(self).__name__,
59
59
  repr(self.__data),
60
60
  self.__maxsize,
61
61
  self.__currsize,
@@ -100,6 +100,12 @@ class Cache(collections.abc.MutableMapping):
100
100
  def __len__(self):
101
101
  return len(self.__data)
102
102
 
103
+ # Note that we cannot simply inherit get(), pop() and setdefault()
104
+ # from MutableMapping, since these rely on __getitem__ throwing a
105
+ # KeyError on cache miss. This is not the case if __missing__ is
106
+ # implemented for a Cache subclass, so we have to roll our own,
107
+ # somewhat less elegant versions.
108
+
103
109
  def get(self, key, default=None):
104
110
  if key in self:
105
111
  return self[key]
@@ -148,9 +154,9 @@ class FIFOCache(Cache):
148
154
 
149
155
  def __setitem__(self, key, value, cache_setitem=Cache.__setitem__):
150
156
  cache_setitem(self, key, value)
151
- try:
157
+ if key in self.__order:
152
158
  self.__order.move_to_end(key)
153
- except KeyError:
159
+ else:
154
160
  self.__order[key] = None
155
161
 
156
162
  def __delitem__(self, key, cache_delitem=Cache.__delitem__):
@@ -198,7 +204,8 @@ class LFUCache(Cache):
198
204
  def __setitem__(self, key, value, cache_setitem=Cache.__setitem__):
199
205
  cache_setitem(self, key, value)
200
206
  if key in self.__links:
201
- return self.__touch(key)
207
+ self.__touch(key)
208
+ return
202
209
  root = self.__root
203
210
  link = root.next
204
211
  if link.count != 1:
@@ -642,7 +649,7 @@ class TLRUCache(_TimedCache):
642
649
  try:
643
650
  key = next(iter(self.__items))
644
651
  except StopIteration:
645
- raise KeyError("%s is empty" % self.__class__.__name__) from None
652
+ raise KeyError("%s is empty" % type(self).__name__) from None
646
653
  else:
647
654
  return (key, self.pop(key))
648
655
 
@@ -63,7 +63,9 @@ def _locked_info(func, cache, key, lock, info):
63
63
  v = func(*args, **kwargs)
64
64
  with lock:
65
65
  try:
66
- # in case of a race, prefer the item already in the cache
66
+ # In case of a race condition, i.e. if another thread
67
+ # stored a value for this key while we were calling
68
+ # func(), prefer the cached value.
67
69
  return cache.setdefault(k, v)
68
70
  except ValueError:
69
71
  return v # value too large
@@ -107,8 +109,11 @@ def _unlocked_info(func, cache, key, info):
107
109
  cache.clear()
108
110
  hits = misses = 0
109
111
 
112
+ def cache_info():
113
+ return info(hits, misses)
114
+
110
115
  wrapper.cache_clear = cache_clear
111
- wrapper.cache_info = lambda: info(hits, misses)
116
+ wrapper.cache_info = cache_info
112
117
  return wrapper
113
118
 
114
119
 
@@ -173,7 +178,7 @@ def _locked(func, cache, key, lock):
173
178
  v = func(*args, **kwargs)
174
179
  with lock:
175
180
  try:
176
- # in case of a race, prefer the item already in the cache
181
+ # possible race condition: see above
177
182
  return cache.setdefault(k, v)
178
183
  except ValueError:
179
184
  return v # value too large
@@ -29,8 +29,8 @@ class _HashedTuple(tuple):
29
29
  return {}
30
30
 
31
31
 
32
- # used for separating keyword arguments; we do not use an object
33
- # instance here so identity is preserved when pickling/unpickling
32
+ # A sentinel for separating args from kwargs. Using the class itself
33
+ # ensures uniqueness and preserves identity when pickling/unpickling.
34
34
  _kwmark = (_HashedTuple,)
35
35
 
36
36
 
@@ -38,7 +38,7 @@ def hashkey(*args, **kwargs):
38
38
  """Return a cache key for the specified hashable arguments."""
39
39
 
40
40
  if kwargs:
41
- return _HashedTuple(args + sum(sorted(kwargs.items()), _kwmark))
41
+ return _HashedTuple(args + _kwmark + tuple(sorted(kwargs.items())))
42
42
  else:
43
43
  return _HashedTuple(args)
44
44
 
@@ -53,6 +53,7 @@ def typedkey(*args, **kwargs):
53
53
 
54
54
  key = hashkey(*args, **kwargs)
55
55
  key += tuple(type(v) for v in args)
56
+ # TODO: avoid iterating twice over kwargs
56
57
  key += tuple(type(v) for _, v in sorted(kwargs.items()))
57
58
  return key
58
59
 
@@ -1,15 +1,13 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cachetools
3
- Version: 6.2.1
3
+ Version: 6.2.3
4
4
  Summary: Extensible memoizing collections and decorators
5
- Home-page: https://github.com/tkem/cachetools/
6
- Author: Thomas Kemmer
7
- Author-email: tkemmer@computer.org
8
- License: MIT
5
+ Author-email: Thomas Kemmer <tkemmer@computer.org>
6
+ Maintainer-email: Thomas Kemmer <tkemmer@computer.org>
7
+ License-Expression: MIT
8
+ Project-URL: Homepage, https://github.com/tkem/cachetools/
9
9
  Classifier: Development Status :: 5 - Production/Stable
10
- Classifier: Environment :: Other Environment
11
10
  Classifier: Intended Audience :: Developers
12
- Classifier: License :: OSI Approved :: MIT License
13
11
  Classifier: Operating System :: OS Independent
14
12
  Classifier: Programming Language :: Python
15
13
  Classifier: Programming Language :: Python :: 3
@@ -21,6 +19,7 @@ Classifier: Programming Language :: Python :: 3.13
21
19
  Classifier: Programming Language :: Python :: 3.14
22
20
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
23
21
  Requires-Python: >=3.9
22
+ Description-Content-Type: text/x-rst
24
23
  License-File: LICENSE
25
24
  Dynamic: license-file
26
25
 
@@ -117,6 +116,7 @@ Related Projects
117
116
  ------------------------------------------------------------------------
118
117
 
119
118
  - asyncache_: Helpers to use cachetools_ with asyncio.
119
+ - cachetools-async_: Helpers to use cachetools_ with asyncio.
120
120
  - cacheing_: Pure Python Cacheing Library.
121
121
  - CacheToolsUtils_: Stackable cache classes for sharing, encryption,
122
122
  statistics *and more* on top of cachetools_, redis_ and memcached_.
@@ -146,6 +146,7 @@ Licensed under the `MIT License`_.
146
146
  .. _MIT License: https://raw.github.com/tkem/cachetools/master/LICENSE
147
147
 
148
148
  .. _asyncache: https://pypi.org/project/asyncache/
149
+ .. _cachetools-async: https://pypi.org/project/cachetools-async/
149
150
  .. _cacheing: https://pypi.org/project/cacheing/
150
151
  .. _CacheToolsUtils: https://pypi.org/project/CacheToolsUtils/
151
152
  .. _shelved-cache: https://pypi.org/project/shelved-cache/
@@ -3,8 +3,6 @@ LICENSE
3
3
  MANIFEST.in
4
4
  README.rst
5
5
  pyproject.toml
6
- setup.cfg
7
- setup.py
8
6
  tox.ini
9
7
  docs/conf.py
10
8
  docs/index.rst
@@ -33,6 +33,7 @@ deps =
33
33
  flake8-black
34
34
  flake8-bugbear
35
35
  flake8-import-order
36
+ flake8-pyproject
36
37
  commands =
37
38
  flake8
38
39
  skip_install = true
@@ -1,3 +0,0 @@
1
- [build-system]
2
- requires = ["setuptools >= 46.4.0", "wheel"]
3
- build-backend = "setuptools.build_meta"
@@ -1,50 +0,0 @@
1
- [metadata]
2
- name = cachetools
3
- version = attr: cachetools.__version__
4
- url = https://github.com/tkem/cachetools/
5
- author = Thomas Kemmer
6
- author_email = tkemmer@computer.org
7
- license = MIT
8
- license_files = LICENSE
9
- description = Extensible memoizing collections and decorators
10
- long_description = file: README.rst
11
- classifiers =
12
- Development Status :: 5 - Production/Stable
13
- Environment :: Other Environment
14
- Intended Audience :: Developers
15
- License :: OSI Approved :: MIT License
16
- Operating System :: OS Independent
17
- Programming Language :: Python
18
- Programming Language :: Python :: 3
19
- Programming Language :: Python :: 3.9
20
- Programming Language :: Python :: 3.10
21
- Programming Language :: Python :: 3.11
22
- Programming Language :: Python :: 3.12
23
- Programming Language :: Python :: 3.13
24
- Programming Language :: Python :: 3.14
25
- Topic :: Software Development :: Libraries :: Python Modules
26
-
27
- [options]
28
- package_dir =
29
- = src
30
- packages = find:
31
- python_requires = >= 3.9
32
-
33
- [options.packages.find]
34
- where = src
35
-
36
- [flake8]
37
- max-line-length = 80
38
- exclude = .git, .tox, build
39
- select = C, E, F, W, B, B950, I, N
40
- ignore = F401, E501
41
-
42
- [build_sphinx]
43
- source-dir = docs/
44
- build-dir = docs/_build
45
- all_files = 1
46
-
47
- [egg_info]
48
- tag_build =
49
- tag_date = 0
50
-
cachetools-6.2.1/setup.py DELETED
@@ -1,3 +0,0 @@
1
- from setuptools import setup
2
-
3
- setup()
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes