thds.core 1.44.20250730010425__py3-none-any.whl → 1.44.20250730172116__py3-none-any.whl

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.

Potentially problematic release.


This version of thds.core might be problematic. Click here for more details.

thds/core/cache.py CHANGED
@@ -12,7 +12,7 @@ else: # pragma: no cover
12
12
  from typing_extensions import ParamSpec
13
13
 
14
14
 
15
- class _HashedTuple(tuple):
15
+ class HashedTuple(tuple):
16
16
  """A tuple that ensures that `hash` will be called no more than once
17
17
  per element, since cache decorators will hash the key multiple
18
18
  times on a cache miss. See also `_HashedSeq` in the standard
@@ -27,11 +27,11 @@ class _HashedTuple(tuple):
27
27
  self.__hashvalue = hashvalue = hash(self)
28
28
  return hashvalue
29
29
 
30
- def __add__(self, other, add=tuple.__add__) -> "_HashedTuple":
31
- return _HashedTuple(add(self, other))
30
+ def __add__(self, other, add=tuple.__add__) -> "HashedTuple":
31
+ return HashedTuple(add(self, other))
32
32
 
33
- def __radd__(self, other, add=tuple.__add__) -> "_HashedTuple":
34
- return _HashedTuple(add(other, self))
33
+ def __radd__(self, other, add=tuple.__add__) -> "HashedTuple":
34
+ return HashedTuple(add(other, self))
35
35
 
36
36
  def __getstate__(self) -> ty.Dict:
37
37
  return {}
@@ -39,23 +39,23 @@ class _HashedTuple(tuple):
39
39
 
40
40
  # used for separating keyword arguments; we do not use an object
41
41
  # instance here so identity is preserved when pickling/unpickling
42
- _kwmark = (_HashedTuple,)
42
+ _kwmark = (HashedTuple,)
43
43
 
44
44
 
45
- def hashkey(args: tuple, kwargs: ty.Mapping) -> _HashedTuple:
45
+ def hashkey(args: tuple, kwargs: ty.Mapping) -> HashedTuple:
46
46
  """Return a cache key for the specified hashable arguments."""
47
47
 
48
48
  if kwargs:
49
- return _HashedTuple(args + sum(sorted(kwargs.items()), _kwmark))
49
+ return HashedTuple(args + sum(sorted(kwargs.items()), _kwmark))
50
50
  else:
51
- return _HashedTuple(args)
51
+ return HashedTuple(args)
52
52
 
53
53
 
54
54
  # above keying code borrowed from `cachetools`: https://github.com/tkem/cachetools/tree/master
55
55
  # I have added some type information
56
56
 
57
57
 
58
- def make_bound_hashkey(func: ty.Callable) -> ty.Callable[..., _HashedTuple]:
58
+ def make_bound_hashkey(func: ty.Callable) -> ty.Callable[..., HashedTuple]:
59
59
  """Makes a hashkey function that binds its `*args, **kwargs` to the function signature of `func`.
60
60
 
61
61
  The resulting bound hashkey function makes cache keys that are robust to variations in how arguments are passed to
@@ -63,7 +63,7 @@ def make_bound_hashkey(func: ty.Callable) -> ty.Callable[..., _HashedTuple]:
63
63
  """
64
64
  signature = inspect.signature(func)
65
65
 
66
- def bound_hashkey(args: tuple, kwargs: ty.Mapping) -> _HashedTuple:
66
+ def bound_hashkey(args: tuple, kwargs: ty.Mapping) -> HashedTuple:
67
67
  bound_arguments = signature.bind(*args, **kwargs)
68
68
  bound_arguments.apply_defaults()
69
69
  return hashkey(bound_arguments.args, bound_arguments.kwargs)
@@ -85,11 +85,11 @@ _R = ty.TypeVar("_R")
85
85
 
86
86
  def _locking_factory(
87
87
  cache_lock: proto.ContextManager,
88
- make_func_lock: ty.Callable[[_HashedTuple], proto.ContextManager],
88
+ make_func_lock: ty.Callable[[HashedTuple], proto.ContextManager],
89
89
  ) -> ty.Callable[[ty.Callable[_P, _R]], ty.Callable[_P, _R]]:
90
90
  def decorator(func: ty.Callable[_P, _R]) -> ty.Callable[_P, _R]:
91
- cache: ty.Dict[_HashedTuple, _R] = {}
92
- keys_to_func_locks: ty.Dict[_HashedTuple, proto.ContextManager] = {}
91
+ cache: ty.Dict[HashedTuple, _R] = {}
92
+ keys_to_func_locks: ty.Dict[HashedTuple, proto.ContextManager] = {}
93
93
  hits = misses = 0
94
94
  bound_hashkey = make_bound_hashkey(func)
95
95
  sentinel = ty.cast(_R, object()) # unique object used to signal cache misses
@@ -120,7 +120,7 @@ def _locking_factory(
120
120
  result = func(*args, **kwargs)
121
121
  cache[key] = result
122
122
 
123
- del keys_to_func_locks[key]
123
+ keys_to_func_locks.pop(key, None) # this allows for the use of reentrant locks
124
124
  return result
125
125
 
126
126
  def cache_info() -> _CacheInfo:
@@ -154,7 +154,7 @@ def locking(
154
154
  func: None = ...,
155
155
  *,
156
156
  cache_lock: ty.Optional[proto.ContextManager] = ...,
157
- make_func_lock: ty.Optional[ty.Callable[[_HashedTuple], proto.ContextManager]] = ...,
157
+ make_func_lock: ty.Optional[ty.Callable[[HashedTuple], proto.ContextManager]] = ...,
158
158
  ) -> ty.Callable[[ty.Callable[_P, _R]], ty.Callable[_P, _R]]:
159
159
  ... # pragma: no cover
160
160
 
@@ -167,7 +167,7 @@ def locking(
167
167
  func: ty.Optional[ty.Callable[_P, _R]] = None,
168
168
  *,
169
169
  cache_lock: ty.Optional[proto.ContextManager] = None,
170
- make_func_lock: ty.Optional[ty.Callable[[_HashedTuple], proto.ContextManager]] = None,
170
+ make_func_lock: ty.Optional[ty.Callable[[HashedTuple], proto.ContextManager]] = None,
171
171
  ):
172
172
  """A threadsafe, simple, unbounded cache.
173
173
 
@@ -189,7 +189,7 @@ def locking(
189
189
  usage that is not worth the cost.
190
190
  """
191
191
 
192
- def default_make_func_lock(_key: _HashedTuple) -> threading.Lock:
192
+ def default_make_func_lock(_key: HashedTuple) -> threading.Lock:
193
193
  return threading.Lock()
194
194
 
195
195
  decorator = _locking_factory(
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: thds.core
3
- Version: 1.44.20250730010425
3
+ Version: 1.44.20250730172116
4
4
  Summary: Core utilities.
5
5
  Author-email: Trilliant Health <info@trillianthealth.com>
6
6
  License: MIT
@@ -1,6 +1,6 @@
1
1
  thds/core/__init__.py,sha256=p5ZTz0yURvtiJlUspnI6aMb9nIekTkzU8sqr8HrnyiM,968
2
2
  thds/core/ansi_esc.py,sha256=QZ3CptZbX4N_hyP2IgqfTbNt9tBPaqy7ReTMQIzGbrc,870
3
- thds/core/cache.py,sha256=nL0oAyZrhPqyBBLevnOWSWVoEBrftaG3aE6Qq6tvmAA,7153
3
+ thds/core/cache.py,sha256=VGotQHrwxotgWL91oisQbK0fIxvp_5okA4tDQmnc-y0,7188
4
4
  thds/core/calgitver.py,sha256=6ioH5MGE65l_Dp924oD5CWrLyxKgmhtn46YwGxFpHfM,2497
5
5
  thds/core/cm.py,sha256=WZB8eQU0DaBYj9s97nc3PuCtai9guovfyiQH68zhLzY,1086
6
6
  thds/core/concurrency.py,sha256=NQunF_tJ_z8cfVyhzkTPlb-nZrgu-vIk9_3XffgscKQ,3520
@@ -73,8 +73,8 @@ thds/core/sqlite/structured.py,sha256=SvZ67KcVcVdmpR52JSd52vMTW2ALUXmlHEeD-VrzWV
73
73
  thds/core/sqlite/types.py,sha256=oUkfoKRYNGDPZRk29s09rc9ha3SCk2SKr_K6WKebBFs,1308
74
74
  thds/core/sqlite/upsert.py,sha256=BmKK6fsGVedt43iY-Lp7dnAu8aJ1e9CYlPVEQR2pMj4,5827
75
75
  thds/core/sqlite/write.py,sha256=z0219vDkQDCnsV0WLvsj94keItr7H4j7Y_evbcoBrWU,3458
76
- thds_core-1.44.20250730010425.dist-info/METADATA,sha256=DFQJY-wqZJBlDl6RKkEWb0g-VG1inNZBleXJd-ultXA,2216
77
- thds_core-1.44.20250730010425.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
78
- thds_core-1.44.20250730010425.dist-info/entry_points.txt,sha256=bOCOVhKZv7azF3FvaWX6uxE6yrjK6FcjqhtxXvLiFY8,161
79
- thds_core-1.44.20250730010425.dist-info/top_level.txt,sha256=LTZaE5SkWJwv9bwOlMbIhiS-JWQEEIcjVYnJrt-CriY,5
80
- thds_core-1.44.20250730010425.dist-info/RECORD,,
76
+ thds_core-1.44.20250730172116.dist-info/METADATA,sha256=Yv8xV6o0RXAO6pA6E831iY7JMQrNoZ_szLCmjZxWYss,2216
77
+ thds_core-1.44.20250730172116.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
78
+ thds_core-1.44.20250730172116.dist-info/entry_points.txt,sha256=bOCOVhKZv7azF3FvaWX6uxE6yrjK6FcjqhtxXvLiFY8,161
79
+ thds_core-1.44.20250730172116.dist-info/top_level.txt,sha256=LTZaE5SkWJwv9bwOlMbIhiS-JWQEEIcjVYnJrt-CriY,5
80
+ thds_core-1.44.20250730172116.dist-info/RECORD,,