]> crepu.dev Git - config.git/blob - djavu-asus/emacs/elpy/rpc-venv/lib/python3.11/site-packages/jedi/cache.py
1ff452013f8bfa90753296dea65a79f4e56a2689
[config.git] / djavu-asus / emacs / elpy / rpc-venv / lib / python3.11 / site-packages / jedi / cache.py
1 """
2 This caching is very important for speed and memory optimizations. There's
3 nothing really spectacular, just some decorators. The following cache types are
4 available:
5
6 - ``time_cache`` can be used to cache something for just a limited time span,
7 which can be useful if there's user interaction and the user cannot react
8 faster than a certain time.
9
10 This module is one of the reasons why |jedi| is not thread-safe. As you can see
11 there are global variables, which are holding the cache information. Some of
12 these variables are being cleaned after every API usage.
13 """
14 import time
15 from functools import wraps
16 from typing import Any, Dict, Tuple
17
18 from jedi import settings
19 from parso.cache import parser_cache
20
21 _time_caches: Dict[str, Dict[Any, Tuple[float, Any]]] = {}
22
23
24 def clear_time_caches(delete_all: bool = False) -> None:
25 """ Jedi caches many things, that should be completed after each completion
26 finishes.
27
28 :param delete_all: Deletes also the cache that is normally not deleted,
29 like parser cache, which is important for faster parsing.
30 """
31 global _time_caches
32
33 if delete_all:
34 for cache in _time_caches.values():
35 cache.clear()
36 parser_cache.clear()
37 else:
38 # normally just kill the expired entries, not all
39 for tc in _time_caches.values():
40 # check time_cache for expired entries
41 for key, (t, value) in list(tc.items()):
42 if t < time.time():
43 # delete expired entries
44 del tc[key]
45
46
47 def signature_time_cache(time_add_setting):
48 """
49 This decorator works as follows: Call it with a setting and after that
50 use the function with a callable that returns the key.
51 But: This function is only called if the key is not available. After a
52 certain amount of time (`time_add_setting`) the cache is invalid.
53
54 If the given key is None, the function will not be cached.
55 """
56 def _temp(key_func):
57 dct = {}
58 _time_caches[time_add_setting] = dct
59
60 def wrapper(*args, **kwargs):
61 generator = key_func(*args, **kwargs)
62 key = next(generator)
63 try:
64 expiry, value = dct[key]
65 if expiry > time.time():
66 return value
67 except KeyError:
68 pass
69
70 value = next(generator)
71 time_add = getattr(settings, time_add_setting)
72 if key is not None:
73 dct[key] = time.time() + time_add, value
74 return value
75 return wrapper
76 return _temp
77
78
79 def time_cache(seconds):
80 def decorator(func):
81 cache = {}
82
83 @wraps(func)
84 def wrapper(*args, **kwargs):
85 key = (args, frozenset(kwargs.items()))
86 try:
87 created, result = cache[key]
88 if time.time() < created + seconds:
89 return result
90 except KeyError:
91 pass
92 result = func(*args, **kwargs)
93 cache[key] = time.time(), result
94 return result
95
96 wrapper.clear_cache = lambda: cache.clear()
97 return wrapper
98
99 return decorator
100
101
102 def memoize_method(method):
103 """A normal memoize function."""
104 @wraps(method)
105 def wrapper(self, *args, **kwargs):
106 cache_dict = self.__dict__.setdefault('_memoize_method_dct', {})
107 dct = cache_dict.setdefault(method, {})
108 key = (args, frozenset(kwargs.items()))
109 try:
110 return dct[key]
111 except KeyError:
112 result = method(self, *args, **kwargs)
113 dct[key] = result
114 return result
115 return wrapper