Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/cachetools/_cached.py: 48%
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1"""Function decorator helpers."""
3import functools
6def _condition_info(func, cache, key, lock, cond, info):
7 hits = misses = 0
8 pending = set()
10 def wrapper(*args, **kwargs):
11 nonlocal hits, misses
12 k = key(*args, **kwargs)
13 with lock:
14 cond.wait_for(lambda: k not in pending)
15 try:
16 result = cache[k]
17 hits += 1
18 return result
19 except KeyError:
20 pending.add(k)
21 misses += 1
22 try:
23 v = func(*args, **kwargs)
24 with lock:
25 try:
26 cache[k] = v
27 except ValueError:
28 pass # value too large
29 return v
30 finally:
31 with lock:
32 pending.remove(k)
33 cond.notify_all()
35 def cache_clear():
36 nonlocal hits, misses
37 with lock:
38 cache.clear()
39 hits = misses = 0
41 def cache_info():
42 with lock:
43 return info(hits, misses)
45 wrapper.cache_clear = cache_clear
46 wrapper.cache_info = cache_info
47 return wrapper
50def _locked_info(func, cache, key, lock, info):
51 hits = misses = 0
53 def wrapper(*args, **kwargs):
54 nonlocal hits, misses
55 k = key(*args, **kwargs)
56 with lock:
57 try:
58 result = cache[k]
59 hits += 1
60 return result
61 except KeyError:
62 misses += 1
63 v = func(*args, **kwargs)
64 with lock:
65 try:
66 # In case of a race condition, i.e. if another thread
67 # stored a value for this key while we were calling
68 # func(), prefer the cached value.
69 return cache.setdefault(k, v)
70 except ValueError:
71 return v # value too large
73 def cache_clear():
74 nonlocal hits, misses
75 with lock:
76 cache.clear()
77 hits = misses = 0
79 def cache_info():
80 with lock:
81 return info(hits, misses)
83 wrapper.cache_clear = cache_clear
84 wrapper.cache_info = cache_info
85 return wrapper
88def _unlocked_info(func, cache, key, info):
89 hits = misses = 0
91 def wrapper(*args, **kwargs):
92 nonlocal hits, misses
93 k = key(*args, **kwargs)
94 try:
95 result = cache[k]
96 hits += 1
97 return result
98 except KeyError:
99 misses += 1
100 v = func(*args, **kwargs)
101 try:
102 cache[k] = v
103 except ValueError:
104 pass # value too large
105 return v
107 def cache_clear():
108 nonlocal hits, misses
109 cache.clear()
110 hits = misses = 0
112 wrapper.cache_clear = cache_clear
113 wrapper.cache_info = lambda: info(hits, misses)
114 return wrapper
117def _uncached_info(func, info):
118 misses = 0
120 def wrapper(*args, **kwargs):
121 nonlocal misses
122 misses += 1
123 return func(*args, **kwargs)
125 def cache_clear():
126 nonlocal misses
127 misses = 0
129 wrapper.cache_clear = cache_clear
130 wrapper.cache_info = lambda: info(0, misses)
131 return wrapper
134def _condition(func, cache, key, lock, cond):
135 pending = set()
137 def wrapper(*args, **kwargs):
138 k = key(*args, **kwargs)
139 with lock:
140 cond.wait_for(lambda: k not in pending)
141 try:
142 result = cache[k]
143 return result
144 except KeyError:
145 pending.add(k)
146 try:
147 v = func(*args, **kwargs)
148 with lock:
149 try:
150 cache[k] = v
151 except ValueError:
152 pass # value too large
153 return v
154 finally:
155 with lock:
156 pending.remove(k)
157 cond.notify_all()
159 def cache_clear():
160 with lock:
161 cache.clear()
163 wrapper.cache_clear = cache_clear
164 return wrapper
167def _locked(func, cache, key, lock):
168 def wrapper(*args, **kwargs):
169 k = key(*args, **kwargs)
170 with lock:
171 try:
172 return cache[k]
173 except KeyError:
174 pass # key not found
175 v = func(*args, **kwargs)
176 with lock:
177 try:
178 # possible race condition: see above
179 return cache.setdefault(k, v)
180 except ValueError:
181 return v # value too large
183 def cache_clear():
184 with lock:
185 cache.clear()
187 wrapper.cache_clear = cache_clear
188 return wrapper
191def _unlocked(func, cache, key):
192 def wrapper(*args, **kwargs):
193 k = key(*args, **kwargs)
194 try:
195 return cache[k]
196 except KeyError:
197 pass # key not found
198 v = func(*args, **kwargs)
199 try:
200 cache[k] = v
201 except ValueError:
202 pass # value too large
203 return v
205 wrapper.cache_clear = lambda: cache.clear()
206 return wrapper
209def _uncached(func):
210 def wrapper(*args, **kwargs):
211 return func(*args, **kwargs)
213 wrapper.cache_clear = lambda: None
214 return wrapper
217def _wrapper(func, cache, key, lock=None, cond=None, info=None):
218 if info is not None:
219 if cache is None:
220 wrapper = _uncached_info(func, info)
221 elif cond is not None and lock is not None:
222 wrapper = _condition_info(func, cache, key, lock, cond, info)
223 elif cond is not None:
224 wrapper = _condition_info(func, cache, key, cond, cond, info)
225 elif lock is not None:
226 wrapper = _locked_info(func, cache, key, lock, info)
227 else:
228 wrapper = _unlocked_info(func, cache, key, info)
229 else:
230 if cache is None:
231 wrapper = _uncached(func)
232 elif cond is not None and lock is not None:
233 wrapper = _condition(func, cache, key, lock, cond)
234 elif cond is not None:
235 wrapper = _condition(func, cache, key, cond, cond)
236 elif lock is not None:
237 wrapper = _locked(func, cache, key, lock)
238 else:
239 wrapper = _unlocked(func, cache, key)
240 wrapper.cache_info = None
242 wrapper.cache = cache
243 wrapper.cache_key = key
244 wrapper.cache_lock = lock if lock is not None else cond
245 wrapper.cache_condition = cond
247 return functools.update_wrapper(wrapper, func)