File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -118,7 +118,8 @@ Class and object methods can also be cached. Cachier will automatically ignore t
118118 return result
119119
120120 # Instance method relies on object attribute, NOT good to cache
121- @cachier (allow_non_static_methods = True )
121+ # @cachier() would raise TypeError here -- this is intentional
122+ @cachier ()
122123 def bad_usage (self , arg_1 , arg_2 ):
123124 return arg_1 + arg_2 + self .arg_3
124125
Original file line number Diff line number Diff line change @@ -131,7 +131,9 @@ def set_global_params(**params: Any) -> None:
131131 'cleanup_interval', and 'caching_enabled'. In some cores, if the
132132 decorator was created without concrete value for 'wait_for_calc_timeout',
133133 calls that check calculation timeouts will fall back to the global
134- 'wait_for_calc_timeout' as well.
134+ 'wait_for_calc_timeout' as well. 'allow_non_static_methods'
135+ (decoration-time only) controls whether instance methods are
136+ permitted; it is read once when @cachier is applied, not on each call.
135137
136138 Note that ``allow_non_static_methods`` is a **decoration-time**
137139 parameter: it is checked once when the ``@cachier`` decorator is
Original file line number Diff line number Diff line change @@ -374,11 +374,11 @@ def _cachier_decorator(func):
374374 raise TypeError (
375375 f"@cachier cannot decorate instance method "
376376 f"'{ func .__qualname__ } ' because the 'self' parameter is "
377- f "excluded from cache-key computation and all instances "
378- f "would share a single cache. Pass allow_non_static_methods=True "
379- f "to the decorator or call "
380- f "set_global_params(allow_non_static_methods=True) if "
381- f "cross-instance cache sharing is intentional."
377+ "excluded from cache-key computation and all instances "
378+ "would share a single cache. Pass allow_non_static_methods=True "
379+ "to the decorator or call "
380+ "set_global_params(allow_non_static_methods=True) if "
381+ "cross-instance cache sharing is intentional."
382382 )
383383
384384 is_coroutine = inspect .iscoroutinefunction (func )
Original file line number Diff line number Diff line change @@ -62,7 +62,7 @@ def set_func(self, func):
6262 -----
6363 Detection is name-based: only ``func_params[0] == "self"`` is
6464 checked. ``@classmethod`` functions whose first parameter is
65- conventionally named ``cls`` are ** not** detected as methods --
65+ conventionally named ``cls`` are not detected as methods --
6666 this is a known gap.
6767
6868 """
Original file line number Diff line number Diff line change @@ -315,6 +315,15 @@ async def async_method(self, x):
315315
316316 obj1 .async_method .clear_cache ()
317317
318+ async def test_guard_raises_without_opt_in (self ):
319+ """Test that @cachier raises TypeError for async instance methods without opt-in."""
320+ with pytest .raises (TypeError , match = "allow_non_static_methods" ):
321+
322+ class MyClass :
323+ @cachier (backend = "memory" )
324+ async def async_method (self , x ):
325+ return x
326+
318327
319328# =============================================================================
320329# Sync Function Compatibility Tests
Original file line number Diff line number Diff line change 11"""Smoke tests for cachier - fast, no external service dependencies."""
22
33import datetime
4+ import hashlib
5+ import pickle
46
57import pytest
68
@@ -186,9 +188,6 @@ def test_classmethod_not_guarded():
186188 # ``cls``.
187189 def _hash_ignore_cls (args , kwds ):
188190 filtered = {k : v for k , v in kwds .items () if k != "cls" }
189- import hashlib
190- import pickle
191-
192191 return hashlib .sha256 (pickle .dumps ((args , sorted (filtered .items ())))).hexdigest ()
193192
194193 class Foo :
You can’t perform that action at this time.
0 commit comments