Skip to content

Commit 0cdf70c

Browse files
committed
Improve type hints.
1 parent 9f277ef commit 0cdf70c

2 files changed

Lines changed: 41 additions & 6 deletions

File tree

src/cachetools/__init__.pyi

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ __all__: Final = (
2525
"TTLCache",
2626
"cached",
2727
"cachedmethod",
28+
"cachedproperty",
2829
)
2930
__version__: str
3031

@@ -243,3 +244,17 @@ def cachedmethod(
243244
) -> Callable[
244245
[Callable[Concatenate[Any, _P], _R]], _cachedmethod_wrapper_info[_P, _R]
245246
]: ...
247+
248+
@type_check_only
249+
class _cachedproperty_wrapper(Generic[_R]):
250+
__wrapped__: Callable[[Any], _R]
251+
__name__: str
252+
__doc__: str | None
253+
def __set_name__(self, owner: type, name: str) -> None: ...
254+
def __get__(self, obj: Any, objtype: type | None = None) -> _R: ...
255+
256+
def cachedproperty(
257+
ttl: Any | None = ...,
258+
timer: Callable[[], Any] = ...,
259+
lock: AbstractContextManager[Any] | None = ...,
260+
) -> Callable[[Callable[[Any], _R]], _cachedproperty_wrapper[_R]]: ...

src/cachetools/_cachedproperty.py

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ def __set_name__(self, owner, name):
2121
)
2222

2323
def __get__(self, obj, objtype=None):
24-
wrapper = self.Wrapper(obj) # FIXME: wrapper may also be a value?!?
24+
wrapper = self.Wrapper(obj) # type: ignore
2525
if obj is None:
2626
# e.g. mocking with autospec=True in unittest.mock
2727
pass
@@ -54,6 +54,8 @@ def __get__(self, obj, objtype=None):
5454
return wrapper
5555

5656

57+
# TODO: Consider renaming this to _DummyLock (cf. "dummy_threading"), move to some import .py,
58+
# and also use this in other decorators (after doing some timing), to reduce multiple variants
5759
class _DefaultLock:
5860
def __enter__(_self):
5961
pass
@@ -65,17 +67,35 @@ def __exit__(_self, _exc_type, _exc_value, _traceback):
6567
_default_lock = _DefaultLock()
6668

6769

68-
def _ttl_property(ttl, timer, lock):
69-
pass
70+
def _ttl_property(method, ttl, timer, lock):
71+
class Descriptor(_DescriptorBase):
72+
class Wrapper:
73+
def __init__(self, obj):
74+
pass
7075

76+
def __call__(self, *args, **kwargs):
77+
pass
7178

72-
def _property(lock):
73-
pass
79+
return Descriptor()
80+
81+
82+
def _property(method, lock):
83+
class Descriptor(_DescriptorBase):
84+
class Wrapper:
85+
def __init__(self, obj):
86+
pass
87+
88+
def __call__(self, *args, **kwargs):
89+
pass
90+
91+
return Descriptor()
7492

7593

7694
def _wrapper(method, ttl, timer, lock=_default_lock):
7795
if ttl is not None:
7896
wrapper = _ttl_property(method, ttl, timer, lock)
7997
else:
8098
wrapper = _property(method, lock)
81-
return functools.update_wrapper(wrapper, method)
99+
# functools.update_wrapper() will not accept descriptor (decorator) as wrapper
100+
# https://github.com/python/typeshed/issues/9846
101+
return functools.update_wrapper(wrapper, method) # type: ignore

0 commit comments

Comments
 (0)