Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
maurosoria
GitHub Repository: maurosoria/dirsearch
Path: blob/master/lib/core/decorators.py
896 views
1
# -*- coding: utf-8 -*-
2
# This program is free software; you can redistribute it and/or modify
3
# it under the terms of the GNU General Public License as published by
4
# the Free Software Foundation; either version 2 of the License, or
5
# (at your option) any later version.
6
#
7
# This program is distributed in the hope that it will be useful,
8
# but WITHOUT ANY WARRANTY; without even the implied warranty of
9
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
# GNU General Public License for more details.
11
#
12
# You should have received a copy of the GNU General Public License
13
# along with this program; if not, write to the Free Software
14
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
15
# MA 02110-1301, USA.
16
#
17
# Author: Mauro Soria
18
19
from __future__ import annotations
20
21
import threading
22
23
from functools import wraps
24
from time import time
25
from typing import Any, Callable, TypeVar
26
from typing_extensions import ParamSpec
27
28
_lock = threading.Lock()
29
_cache: dict[int, tuple[float, Any]] = {}
30
_cache_lock = threading.Lock()
31
32
# https://mypy.readthedocs.io/en/stable/generics.html#declaring-decorators
33
P = ParamSpec("P")
34
T = TypeVar("T")
35
36
37
def cached(timeout: int | float = 100) -> Callable[..., Any]:
38
def _cached(func: Callable[P, T]) -> Callable[P, T]:
39
@wraps(func)
40
def with_caching(*args: P.args, **kwargs: P.kwargs) -> T:
41
key = id(func)
42
for arg in args:
43
key += id(arg)
44
for k, v in kwargs.items():
45
key += id(k) + id(v)
46
47
# If it was cached and the cache timeout hasn't been reached
48
if key in _cache and time() - _cache[key][0] < timeout:
49
return _cache[key][1]
50
51
with _cache_lock:
52
result = func(*args, **kwargs)
53
_cache[key] = (time(), result)
54
55
return result
56
57
return with_caching
58
59
return _cached
60
61
62
def locked(func: Callable[P, T]) -> Callable[P, T]:
63
def with_locking(*args: P.args, **kwargs: P.kwargs) -> T:
64
with _lock:
65
return func(*args, **kwargs)
66
67
return with_locking
68
69