blob: 4cde5f590cf29043e8a15ad582001025eb27cf96 [file] [log] [blame]
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001"""functools.py - Tools for working with functions and callable objects
Thomas Wouters4d70c3d2006-06-08 14:42:34 +00002"""
3# Python module wrapper for _functools C module
4# to allow utilities written in Python to be added
5# to the functools module.
Łukasz Langa6f692512013-06-05 12:20:24 +02006# Written by Nick Coghlan <ncoghlan at gmail.com>,
7# Raymond Hettinger <python at rcn.com>,
8# and Łukasz Langa <lukasz at langa.pl>.
9# Copyright (C) 2006-2013 Python Software Foundation.
Thomas Wouters73e5a5b2006-06-08 15:35:45 +000010# See C source code for _functools credits/copyright
Thomas Wouters4d70c3d2006-06-08 14:42:34 +000011
Georg Brandl2e7346a2010-07-31 18:09:23 +000012__all__ = ['update_wrapper', 'wraps', 'WRAPPER_ASSIGNMENTS', 'WRAPPER_UPDATES',
Łukasz Langa6f692512013-06-05 12:20:24 +020013 'total_ordering', 'cmp_to_key', 'lru_cache', 'reduce', 'partial',
Pablo Galindo12b71432020-03-02 00:08:29 +000014 'partialmethod', 'singledispatch', 'singledispatchmethod',
15 "cached_property"]
Georg Brandl2e7346a2010-07-31 18:09:23 +000016
Łukasz Langa6f692512013-06-05 12:20:24 +020017from abc import get_cache_token
Raymond Hettingerec0e9102012-03-16 01:16:31 -070018from collections import namedtuple
INADA Naoki9811e802017-09-30 16:13:02 +090019# import types, weakref # Deferred to single_dispatch()
Nick Coghlan457fc9a2016-09-10 20:00:02 +100020from reprlib import recursive_repr
Antoine Pitroua6a4dc82017-09-07 18:56:24 +020021from _thread import RLock
Thomas Wouters4d70c3d2006-06-08 14:42:34 +000022
Raymond Hettingerbc8e81d2012-03-17 00:24:09 -070023
24################################################################################
25### update_wrapper() and wraps() decorator
26################################################################################
27
Thomas Wouters73e5a5b2006-06-08 15:35:45 +000028# update_wrapper() and wraps() are tools to help write
29# wrapper functions that can handle naive introspection
30
Meador Ingeff7f64c2011-12-11 22:37:31 -060031WRAPPER_ASSIGNMENTS = ('__module__', '__name__', '__qualname__', '__doc__',
32 '__annotations__')
Thomas Wouters73e5a5b2006-06-08 15:35:45 +000033WRAPPER_UPDATES = ('__dict__',)
34def update_wrapper(wrapper,
35 wrapped,
36 assigned = WRAPPER_ASSIGNMENTS,
37 updated = WRAPPER_UPDATES):
38 """Update a wrapper function to look like the wrapped function
39
40 wrapper is the function to be updated
41 wrapped is the original function
42 assigned is a tuple naming the attributes assigned directly
43 from the wrapped function to the wrapper function (defaults to
44 functools.WRAPPER_ASSIGNMENTS)
Thomas Wouters89f507f2006-12-13 04:49:30 +000045 updated is a tuple naming the attributes of the wrapper that
Thomas Wouters73e5a5b2006-06-08 15:35:45 +000046 are updated with the corresponding attribute from the wrapped
47 function (defaults to functools.WRAPPER_UPDATES)
48 """
49 for attr in assigned:
Nick Coghlan98876832010-08-17 06:17:18 +000050 try:
51 value = getattr(wrapped, attr)
52 except AttributeError:
53 pass
54 else:
55 setattr(wrapper, attr, value)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +000056 for attr in updated:
Thomas Wouters89f507f2006-12-13 04:49:30 +000057 getattr(wrapper, attr).update(getattr(wrapped, attr, {}))
Nick Coghlan24c05bc2013-07-15 21:13:08 +100058 # Issue #17482: set __wrapped__ last so we don't inadvertently copy it
59 # from the wrapped function when updating __dict__
60 wrapper.__wrapped__ = wrapped
Thomas Wouters73e5a5b2006-06-08 15:35:45 +000061 # Return the wrapper so this can be used as a decorator via partial()
62 return wrapper
63
64def wraps(wrapped,
65 assigned = WRAPPER_ASSIGNMENTS,
66 updated = WRAPPER_UPDATES):
67 """Decorator factory to apply update_wrapper() to a wrapper function
68
69 Returns a decorator that invokes update_wrapper() with the decorated
70 function as the wrapper argument and the arguments to wraps() as the
71 remaining arguments. Default arguments are as for update_wrapper().
72 This is a convenience function to simplify applying partial() to
73 update_wrapper().
74 """
75 return partial(update_wrapper, wrapped=wrapped,
76 assigned=assigned, updated=updated)
Raymond Hettingerc50846a2010-04-05 18:56:31 +000077
Raymond Hettingerbc8e81d2012-03-17 00:24:09 -070078
79################################################################################
80### total_ordering class decorator
81################################################################################
82
Raymond Hettinger0603d302015-01-05 21:52:10 -080083# The total ordering functions all invoke the root magic method directly
84# rather than using the corresponding operator. This avoids possible
85# infinite recursion that could occur when the operator dispatch logic
86# detects a NotImplemented result and then calls a reflected method.
Nick Coghlanf05d9812013-10-02 00:02:03 +100087
Raymond Hettingerffcd8492015-05-12 21:26:37 -070088def _gt_from_lt(self, other, NotImplemented=NotImplemented):
Raymond Hettinger0603d302015-01-05 21:52:10 -080089 'Return a > b. Computed by @total_ordering from (not a < b) and (a != b).'
90 op_result = self.__lt__(other)
Nick Coghlanf05d9812013-10-02 00:02:03 +100091 if op_result is NotImplemented:
Raymond Hettingere5db8632015-01-06 22:16:10 -080092 return op_result
Nick Coghlanf05d9812013-10-02 00:02:03 +100093 return not op_result and self != other
94
Raymond Hettingerffcd8492015-05-12 21:26:37 -070095def _le_from_lt(self, other, NotImplemented=NotImplemented):
Raymond Hettinger0603d302015-01-05 21:52:10 -080096 'Return a <= b. Computed by @total_ordering from (a < b) or (a == b).'
97 op_result = self.__lt__(other)
98 return op_result or self == other
99
Raymond Hettingerffcd8492015-05-12 21:26:37 -0700100def _ge_from_lt(self, other, NotImplemented=NotImplemented):
Raymond Hettinger0603d302015-01-05 21:52:10 -0800101 'Return a >= b. Computed by @total_ordering from (not a < b).'
102 op_result = self.__lt__(other)
103 if op_result is NotImplemented:
Raymond Hettingere5db8632015-01-06 22:16:10 -0800104 return op_result
Raymond Hettinger0603d302015-01-05 21:52:10 -0800105 return not op_result
106
Raymond Hettingerffcd8492015-05-12 21:26:37 -0700107def _ge_from_le(self, other, NotImplemented=NotImplemented):
Raymond Hettinger0603d302015-01-05 21:52:10 -0800108 'Return a >= b. Computed by @total_ordering from (not a <= b) or (a == b).'
109 op_result = self.__le__(other)
Nick Coghlanf05d9812013-10-02 00:02:03 +1000110 if op_result is NotImplemented:
Raymond Hettingere5db8632015-01-06 22:16:10 -0800111 return op_result
Nick Coghlanf05d9812013-10-02 00:02:03 +1000112 return not op_result or self == other
113
Raymond Hettingerffcd8492015-05-12 21:26:37 -0700114def _lt_from_le(self, other, NotImplemented=NotImplemented):
Raymond Hettinger0603d302015-01-05 21:52:10 -0800115 'Return a < b. Computed by @total_ordering from (a <= b) and (a != b).'
116 op_result = self.__le__(other)
Nick Coghlanf05d9812013-10-02 00:02:03 +1000117 if op_result is NotImplemented:
Raymond Hettingere5db8632015-01-06 22:16:10 -0800118 return op_result
Nick Coghlanf05d9812013-10-02 00:02:03 +1000119 return op_result and self != other
120
Raymond Hettingerffcd8492015-05-12 21:26:37 -0700121def _gt_from_le(self, other, NotImplemented=NotImplemented):
Raymond Hettinger0603d302015-01-05 21:52:10 -0800122 'Return a > b. Computed by @total_ordering from (not a <= b).'
123 op_result = self.__le__(other)
124 if op_result is NotImplemented:
Raymond Hettingere5db8632015-01-06 22:16:10 -0800125 return op_result
Raymond Hettinger0603d302015-01-05 21:52:10 -0800126 return not op_result
127
Raymond Hettingerffcd8492015-05-12 21:26:37 -0700128def _lt_from_gt(self, other, NotImplemented=NotImplemented):
Raymond Hettinger0603d302015-01-05 21:52:10 -0800129 'Return a < b. Computed by @total_ordering from (not a > b) and (a != b).'
130 op_result = self.__gt__(other)
131 if op_result is NotImplemented:
Raymond Hettingere5db8632015-01-06 22:16:10 -0800132 return op_result
Raymond Hettinger0603d302015-01-05 21:52:10 -0800133 return not op_result and self != other
134
Raymond Hettingerffcd8492015-05-12 21:26:37 -0700135def _ge_from_gt(self, other, NotImplemented=NotImplemented):
Raymond Hettinger0603d302015-01-05 21:52:10 -0800136 'Return a >= b. Computed by @total_ordering from (a > b) or (a == b).'
137 op_result = self.__gt__(other)
138 return op_result or self == other
139
Raymond Hettingerffcd8492015-05-12 21:26:37 -0700140def _le_from_gt(self, other, NotImplemented=NotImplemented):
Raymond Hettinger0603d302015-01-05 21:52:10 -0800141 'Return a <= b. Computed by @total_ordering from (not a > b).'
142 op_result = self.__gt__(other)
143 if op_result is NotImplemented:
Raymond Hettingere5db8632015-01-06 22:16:10 -0800144 return op_result
Raymond Hettinger0603d302015-01-05 21:52:10 -0800145 return not op_result
146
Raymond Hettingerffcd8492015-05-12 21:26:37 -0700147def _le_from_ge(self, other, NotImplemented=NotImplemented):
Raymond Hettinger0603d302015-01-05 21:52:10 -0800148 'Return a <= b. Computed by @total_ordering from (not a >= b) or (a == b).'
149 op_result = self.__ge__(other)
150 if op_result is NotImplemented:
Raymond Hettingere5db8632015-01-06 22:16:10 -0800151 return op_result
Raymond Hettinger0603d302015-01-05 21:52:10 -0800152 return not op_result or self == other
153
Raymond Hettingerffcd8492015-05-12 21:26:37 -0700154def _gt_from_ge(self, other, NotImplemented=NotImplemented):
Raymond Hettinger0603d302015-01-05 21:52:10 -0800155 'Return a > b. Computed by @total_ordering from (a >= b) and (a != b).'
156 op_result = self.__ge__(other)
157 if op_result is NotImplemented:
Raymond Hettingere5db8632015-01-06 22:16:10 -0800158 return op_result
Raymond Hettinger0603d302015-01-05 21:52:10 -0800159 return op_result and self != other
160
Raymond Hettingerffcd8492015-05-12 21:26:37 -0700161def _lt_from_ge(self, other, NotImplemented=NotImplemented):
Raymond Hettinger0603d302015-01-05 21:52:10 -0800162 'Return a < b. Computed by @total_ordering from (not a >= b).'
163 op_result = self.__ge__(other)
164 if op_result is NotImplemented:
Raymond Hettingere5db8632015-01-06 22:16:10 -0800165 return op_result
Raymond Hettinger0603d302015-01-05 21:52:10 -0800166 return not op_result
Raymond Hettingerc50846a2010-04-05 18:56:31 +0000167
Raymond Hettinger1a8ada82015-01-13 22:57:35 -0800168_convert = {
169 '__lt__': [('__gt__', _gt_from_lt),
170 ('__le__', _le_from_lt),
171 ('__ge__', _ge_from_lt)],
172 '__le__': [('__ge__', _ge_from_le),
173 ('__lt__', _lt_from_le),
174 ('__gt__', _gt_from_le)],
175 '__gt__': [('__lt__', _lt_from_gt),
176 ('__ge__', _ge_from_gt),
177 ('__le__', _le_from_gt)],
178 '__ge__': [('__le__', _le_from_ge),
179 ('__gt__', _gt_from_ge),
180 ('__lt__', _lt_from_ge)]
181}
182
Raymond Hettingerc50846a2010-04-05 18:56:31 +0000183def total_ordering(cls):
Georg Brandle5a26732010-05-19 21:06:36 +0000184 """Class decorator that fills in missing ordering methods"""
Raymond Hettinger3255c632010-09-16 00:31:21 +0000185 # Find user-defined comparisons (not those inherited from object).
Raymond Hettinger15ce0be2017-09-05 09:40:44 -0700186 roots = {op for op in _convert if getattr(cls, op, None) is not getattr(object, op, None)}
Raymond Hettinger56de7e22010-04-10 16:59:03 +0000187 if not roots:
188 raise ValueError('must define at least one ordering operation: < > <= >=')
189 root = max(roots) # prefer __lt__ to __le__ to __gt__ to __ge__
Raymond Hettinger1a8ada82015-01-13 22:57:35 -0800190 for opname, opfunc in _convert[root]:
Raymond Hettingerc50846a2010-04-05 18:56:31 +0000191 if opname not in roots:
192 opfunc.__name__ = opname
Raymond Hettingerc50846a2010-04-05 18:56:31 +0000193 setattr(cls, opname, opfunc)
194 return cls
195
Raymond Hettingerbc8e81d2012-03-17 00:24:09 -0700196
197################################################################################
198### cmp_to_key() function converter
199################################################################################
200
Raymond Hettingerc50846a2010-04-05 18:56:31 +0000201def cmp_to_key(mycmp):
Georg Brandle5a26732010-05-19 21:06:36 +0000202 """Convert a cmp= function into a key= function"""
Raymond Hettingerc50846a2010-04-05 18:56:31 +0000203 class K(object):
Raymond Hettingera0d1d962011-03-21 17:50:28 -0700204 __slots__ = ['obj']
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700205 def __init__(self, obj):
Raymond Hettingerc50846a2010-04-05 18:56:31 +0000206 self.obj = obj
207 def __lt__(self, other):
208 return mycmp(self.obj, other.obj) < 0
209 def __gt__(self, other):
210 return mycmp(self.obj, other.obj) > 0
211 def __eq__(self, other):
212 return mycmp(self.obj, other.obj) == 0
213 def __le__(self, other):
214 return mycmp(self.obj, other.obj) <= 0
215 def __ge__(self, other):
216 return mycmp(self.obj, other.obj) >= 0
Raymond Hettinger003be522011-05-03 11:01:32 -0700217 __hash__ = None
Raymond Hettingerc50846a2010-04-05 18:56:31 +0000218 return K
Georg Brandl2e7346a2010-07-31 18:09:23 +0000219
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700220try:
221 from _functools import cmp_to_key
Brett Cannoncd171c82013-07-04 17:43:24 -0400222except ImportError:
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700223 pass
224
Raymond Hettingerbc8e81d2012-03-17 00:24:09 -0700225
226################################################################################
madman-bobe25d5fc2018-10-25 15:02:10 +0100227### reduce() sequence to a single item
228################################################################################
229
230_initial_missing = object()
231
232def reduce(function, sequence, initial=_initial_missing):
233 """
234 reduce(function, sequence[, initial]) -> value
235
236 Apply a function of two arguments cumulatively to the items of a sequence,
237 from left to right, so as to reduce the sequence to a single value.
238 For example, reduce(lambda x, y: x+y, [1, 2, 3, 4, 5]) calculates
239 ((((1+2)+3)+4)+5). If initial is present, it is placed before the items
240 of the sequence in the calculation, and serves as a default when the
241 sequence is empty.
242 """
243
244 it = iter(sequence)
245
246 if initial is _initial_missing:
247 try:
248 value = next(it)
249 except StopIteration:
250 raise TypeError("reduce() of empty sequence with no initial value") from None
251 else:
252 value = initial
253
254 for element in it:
255 value = function(value, element)
256
257 return value
258
259try:
260 from _functools import reduce
261except ImportError:
262 pass
263
264
265################################################################################
Antoine Pitroub5b37142012-11-13 21:35:40 +0100266### partial() argument application
267################################################################################
268
Nick Coghlanf4cb48a2013-11-03 16:41:46 +1000269# Purely functional, no descriptor behaviour
Nick Coghlan457fc9a2016-09-10 20:00:02 +1000270class partial:
Nick Coghlanf4cb48a2013-11-03 16:41:46 +1000271 """New function with partial application of the given arguments
Antoine Pitroub5b37142012-11-13 21:35:40 +0100272 and keywords.
273 """
Alexander Belopolskye49af342015-03-01 15:08:17 -0500274
Nick Coghlan457fc9a2016-09-10 20:00:02 +1000275 __slots__ = "func", "args", "keywords", "__dict__", "__weakref__"
276
Serhiy Storchaka2085bd02019-06-01 11:00:15 +0300277 def __new__(cls, func, /, *args, **keywords):
Nick Coghlan457fc9a2016-09-10 20:00:02 +1000278 if not callable(func):
279 raise TypeError("the first argument must be callable")
Nick Coghlan457fc9a2016-09-10 20:00:02 +1000280
281 if hasattr(func, "func"):
282 args = func.args + args
Serhiy Storchakada084702019-03-27 08:02:28 +0200283 keywords = {**func.keywords, **keywords}
Nick Coghlan457fc9a2016-09-10 20:00:02 +1000284 func = func.func
285
286 self = super(partial, cls).__new__(cls)
287
288 self.func = func
289 self.args = args
290 self.keywords = keywords
291 return self
292
Serhiy Storchaka2085bd02019-06-01 11:00:15 +0300293 def __call__(self, /, *args, **keywords):
Serhiy Storchakada084702019-03-27 08:02:28 +0200294 keywords = {**self.keywords, **keywords}
295 return self.func(*self.args, *args, **keywords)
Nick Coghlan457fc9a2016-09-10 20:00:02 +1000296
297 @recursive_repr()
298 def __repr__(self):
299 qualname = type(self).__qualname__
300 args = [repr(self.func)]
301 args.extend(repr(x) for x in self.args)
302 args.extend(f"{k}={v!r}" for (k, v) in self.keywords.items())
303 if type(self).__module__ == "functools":
304 return f"functools.{qualname}({', '.join(args)})"
305 return f"{qualname}({', '.join(args)})"
306
307 def __reduce__(self):
308 return type(self), (self.func,), (self.func, self.args,
309 self.keywords or None, self.__dict__ or None)
310
311 def __setstate__(self, state):
312 if not isinstance(state, tuple):
313 raise TypeError("argument to __setstate__ must be a tuple")
314 if len(state) != 4:
315 raise TypeError(f"expected 4 items in state, got {len(state)}")
316 func, args, kwds, namespace = state
317 if (not callable(func) or not isinstance(args, tuple) or
318 (kwds is not None and not isinstance(kwds, dict)) or
319 (namespace is not None and not isinstance(namespace, dict))):
320 raise TypeError("invalid partial state")
321
322 args = tuple(args) # just in case it's a subclass
323 if kwds is None:
324 kwds = {}
325 elif type(kwds) is not dict: # XXX does it need to be *exactly* dict?
326 kwds = dict(kwds)
327 if namespace is None:
328 namespace = {}
329
330 self.__dict__ = namespace
331 self.func = func
332 self.args = args
333 self.keywords = kwds
Antoine Pitroub5b37142012-11-13 21:35:40 +0100334
335try:
336 from _functools import partial
Brett Cannoncd171c82013-07-04 17:43:24 -0400337except ImportError:
Antoine Pitroub5b37142012-11-13 21:35:40 +0100338 pass
339
Nick Coghlanf4cb48a2013-11-03 16:41:46 +1000340# Descriptor version
341class partialmethod(object):
342 """Method descriptor with partial application of the given arguments
343 and keywords.
344
345 Supports wrapping existing descriptors and handles non-descriptor
346 callables as instance methods.
347 """
348
Serhiy Storchaka42a139e2019-04-01 09:16:35 +0300349 def __init__(*args, **keywords):
350 if len(args) >= 2:
351 self, func, *args = args
352 elif not args:
353 raise TypeError("descriptor '__init__' of partialmethod "
354 "needs an argument")
355 elif 'func' in keywords:
356 func = keywords.pop('func')
357 self, *args = args
358 import warnings
359 warnings.warn("Passing 'func' as keyword argument is deprecated",
360 DeprecationWarning, stacklevel=2)
361 else:
362 raise TypeError("type 'partialmethod' takes at least one argument, "
363 "got %d" % (len(args)-1))
364 args = tuple(args)
365
Nick Coghlanf4cb48a2013-11-03 16:41:46 +1000366 if not callable(func) and not hasattr(func, "__get__"):
367 raise TypeError("{!r} is not callable or a descriptor"
368 .format(func))
369
370 # func could be a descriptor like classmethod which isn't callable,
371 # so we can't inherit from partial (it verifies func is callable)
372 if isinstance(func, partialmethod):
373 # flattening is mandatory in order to place cls/self before all
374 # other arguments
375 # it's also more efficient since only one function will be called
376 self.func = func.func
377 self.args = func.args + args
Serhiy Storchakada084702019-03-27 08:02:28 +0200378 self.keywords = {**func.keywords, **keywords}
Nick Coghlanf4cb48a2013-11-03 16:41:46 +1000379 else:
380 self.func = func
381 self.args = args
382 self.keywords = keywords
Serhiy Storchakad53cf992019-05-06 22:40:27 +0300383 __init__.__text_signature__ = '($self, func, /, *args, **keywords)'
Nick Coghlanf4cb48a2013-11-03 16:41:46 +1000384
385 def __repr__(self):
386 args = ", ".join(map(repr, self.args))
387 keywords = ", ".join("{}={!r}".format(k, v)
388 for k, v in self.keywords.items())
389 format_string = "{module}.{cls}({func}, {args}, {keywords})"
390 return format_string.format(module=self.__class__.__module__,
Serhiy Storchaka521e5862014-07-22 15:00:37 +0300391 cls=self.__class__.__qualname__,
Nick Coghlanf4cb48a2013-11-03 16:41:46 +1000392 func=self.func,
393 args=args,
394 keywords=keywords)
395
396 def _make_unbound_method(self):
Serhiy Storchaka2085bd02019-06-01 11:00:15 +0300397 def _method(cls_or_self, /, *args, **keywords):
Serhiy Storchakada084702019-03-27 08:02:28 +0200398 keywords = {**self.keywords, **keywords}
399 return self.func(cls_or_self, *self.args, *args, **keywords)
Nick Coghlanf4cb48a2013-11-03 16:41:46 +1000400 _method.__isabstractmethod__ = self.__isabstractmethod__
Yury Selivanovda5fe4f2014-01-27 17:28:37 -0500401 _method._partialmethod = self
Nick Coghlanf4cb48a2013-11-03 16:41:46 +1000402 return _method
403
Miss Islington (bot)c71ae1a2019-08-29 02:02:51 -0700404 def __get__(self, obj, cls=None):
Nick Coghlanf4cb48a2013-11-03 16:41:46 +1000405 get = getattr(self.func, "__get__", None)
406 result = None
407 if get is not None:
408 new_func = get(obj, cls)
409 if new_func is not self.func:
410 # Assume __get__ returning something new indicates the
411 # creation of an appropriate callable
412 result = partial(new_func, *self.args, **self.keywords)
413 try:
414 result.__self__ = new_func.__self__
415 except AttributeError:
416 pass
417 if result is None:
418 # If the underlying descriptor didn't do anything, treat this
419 # like an instance method
420 result = self._make_unbound_method().__get__(obj, cls)
421 return result
422
423 @property
424 def __isabstractmethod__(self):
425 return getattr(self.func, "__isabstractmethod__", False)
426
Pablo Galindo7cd25432018-10-26 12:19:14 +0100427# Helper functions
428
429def _unwrap_partial(func):
430 while isinstance(func, partial):
431 func = func.func
432 return func
Antoine Pitroub5b37142012-11-13 21:35:40 +0100433
434################################################################################
Raymond Hettingerbc8e81d2012-03-17 00:24:09 -0700435### LRU Cache function decorator
436################################################################################
437
Raymond Hettingerdce583e2012-03-16 22:12:20 -0700438_CacheInfo = namedtuple("CacheInfo", ["hits", "misses", "maxsize", "currsize"])
Nick Coghlan234515a2010-11-30 06:19:46 +0000439
Raymond Hettinger0c9050c2012-06-04 00:21:14 -0700440class _HashedSeq(list):
Raymond Hettingerf96b2b02013-03-08 21:11:55 -0700441 """ This class guarantees that hash() will be called no more than once
442 per element. This is important because the lru_cache() will hash
443 the key multiple times on a cache miss.
444
445 """
446
Raymond Hettinger9acbb602012-04-30 22:32:16 -0700447 __slots__ = 'hashvalue'
448
Raymond Hettinger0c9050c2012-06-04 00:21:14 -0700449 def __init__(self, tup, hash=hash):
450 self[:] = tup
451 self.hashvalue = hash(tup)
Raymond Hettinger9acbb602012-04-30 22:32:16 -0700452
453 def __hash__(self):
454 return self.hashvalue
455
Raymond Hettinger0c9050c2012-06-04 00:21:14 -0700456def _make_key(args, kwds, typed,
457 kwd_mark = (object(),),
Raymond Hettingerd8080c02019-01-26 03:02:00 -0500458 fasttypes = {int, str},
Raymond Hettinger4ee39142017-01-08 17:28:20 -0800459 tuple=tuple, type=type, len=len):
Raymond Hettingerf96b2b02013-03-08 21:11:55 -0700460 """Make a cache key from optionally typed positional and keyword arguments
461
462 The key is constructed in a way that is flat as possible rather than
463 as a nested structure that would take more memory.
464
465 If there is only a single argument and its data type is known to cache
466 its hash value, then that argument is returned without a wrapper. This
467 saves space and improves lookup speed.
468
469 """
Raymond Hettinger55037092017-09-04 17:47:53 -0700470 # All of code below relies on kwds preserving the order input by the user.
471 # Formerly, we sorted() the kwds before looping. The new way is *much*
472 # faster; however, it means that f(x=1, y=2) will now be treated as a
473 # distinct call from f(y=2, x=1) which will be cached separately.
Raymond Hettinger0c9050c2012-06-04 00:21:14 -0700474 key = args
475 if kwds:
Raymond Hettinger0c9050c2012-06-04 00:21:14 -0700476 key += kwd_mark
Raymond Hettinger4ee39142017-01-08 17:28:20 -0800477 for item in kwds.items():
Raymond Hettinger0c9050c2012-06-04 00:21:14 -0700478 key += item
479 if typed:
480 key += tuple(type(v) for v in args)
481 if kwds:
Raymond Hettinger4ee39142017-01-08 17:28:20 -0800482 key += tuple(type(v) for v in kwds.values())
Raymond Hettinger0c9050c2012-06-04 00:21:14 -0700483 elif len(key) == 1 and type(key[0]) in fasttypes:
484 return key[0]
485 return _HashedSeq(key)
486
Raymond Hettinger010ce322012-05-19 21:20:48 -0700487def lru_cache(maxsize=128, typed=False):
Benjamin Peterson1f594ad2010-08-08 13:17:07 +0000488 """Least-recently-used cache decorator.
Georg Brandl2e7346a2010-07-31 18:09:23 +0000489
Raymond Hettingerc79fb0e2010-12-01 03:45:41 +0000490 If *maxsize* is set to None, the LRU features are disabled and the cache
491 can grow without bound.
492
Raymond Hettingercd9fdfd2011-10-20 08:57:45 -0700493 If *typed* is True, arguments of different types will be cached separately.
494 For example, f(3.0) and f(3) will be treated as distinct calls with
495 distinct results.
496
Georg Brandl2e7346a2010-07-31 18:09:23 +0000497 Arguments to the cached function must be hashable.
Raymond Hettinger5fa40c02010-11-25 08:11:57 +0000498
Raymond Hettinger7f7a5a72012-03-30 21:50:40 -0700499 View the cache statistics named tuple (hits, misses, maxsize, currsize)
500 with f.cache_info(). Clear the cache and statistics with f.cache_clear().
Raymond Hettinger00f2f972010-12-01 00:47:56 +0000501 Access the underlying function with f.__wrapped__.
Raymond Hettinger5fa40c02010-11-25 08:11:57 +0000502
Miss Islington (bot)917c6222019-09-16 11:55:04 -0700503 See: http://en.wikipedia.org/wiki/Cache_replacement_policies#Least_recently_used_(LRU)
Georg Brandl2e7346a2010-07-31 18:09:23 +0000504
Benjamin Peterson1f594ad2010-08-08 13:17:07 +0000505 """
Raymond Hettinger1ff50df2012-03-30 13:15:48 -0700506
Raymond Hettinger5fa40c02010-11-25 08:11:57 +0000507 # Users should only access the lru_cache through its public API:
Raymond Hettinger5e20bab2010-11-30 07:13:04 +0000508 # cache_info, cache_clear, and f.__wrapped__
Raymond Hettinger5fa40c02010-11-25 08:11:57 +0000509 # The internals of the lru_cache are encapsulated for thread safety and
510 # to allow the implementation to change (including a possible C version).
511
Raymond Hettingerd8080c02019-01-26 03:02:00 -0500512 if isinstance(maxsize, int):
Raymond Hettingerb8218682019-05-26 11:27:35 -0700513 # Negative maxsize is treated as 0
Raymond Hettingerd8080c02019-01-26 03:02:00 -0500514 if maxsize < 0:
515 maxsize = 0
Raymond Hettingerb8218682019-05-26 11:27:35 -0700516 elif callable(maxsize) and isinstance(typed, bool):
517 # The user_function was passed in directly via the maxsize argument
518 user_function, maxsize = maxsize, 128
519 wrapper = _lru_cache_wrapper(user_function, maxsize, typed, _CacheInfo)
520 return update_wrapper(wrapper, user_function)
Raymond Hettingerd8080c02019-01-26 03:02:00 -0500521 elif maxsize is not None:
Raymond Hettingerb8218682019-05-26 11:27:35 -0700522 raise TypeError(
523 'Expected first argument to be an integer, a callable, or None')
Raymond Hettinger4d588972014-08-12 12:44:52 -0700524
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300525 def decorating_function(user_function):
526 wrapper = _lru_cache_wrapper(user_function, maxsize, typed, _CacheInfo)
527 return update_wrapper(wrapper, user_function)
528
529 return decorating_function
530
531def _lru_cache_wrapper(user_function, maxsize, typed, _CacheInfo):
Raymond Hettinger9f0ab9f2012-04-29 14:55:27 -0700532 # Constants shared by all lru cache instances:
Raymond Hettingerb6b98c02012-04-29 18:09:02 -0700533 sentinel = object() # unique object used to signal cache misses
Raymond Hettinger0c9050c2012-06-04 00:21:14 -0700534 make_key = _make_key # build a key from the function arguments
Raymond Hettinger9f0ab9f2012-04-29 14:55:27 -0700535 PREV, NEXT, KEY, RESULT = 0, 1, 2, 3 # names for the link fields
536
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300537 cache = {}
538 hits = misses = 0
539 full = False
540 cache_get = cache.get # bound method to lookup a key or return None
Raymond Hettingerb2d4b3d2016-12-16 14:59:37 -0800541 cache_len = cache.__len__ # get cache size without calling len()
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300542 lock = RLock() # because linkedlist updates aren't threadsafe
543 root = [] # root of the circular doubly linked list
544 root[:] = [root, root, None, None] # initialize by pointing to self
Raymond Hettinger6e8c8172012-03-16 16:53:05 -0700545
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300546 if maxsize == 0:
Raymond Hettinger7e0c5812012-03-17 15:10:24 -0700547
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300548 def wrapper(*args, **kwds):
Raymond Hettingerffdf1c32019-01-31 15:03:38 -0800549 # No caching -- just a statistics update
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300550 nonlocal misses
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300551 misses += 1
Raymond Hettingerffdf1c32019-01-31 15:03:38 -0800552 result = user_function(*args, **kwds)
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300553 return result
554
555 elif maxsize is None:
556
557 def wrapper(*args, **kwds):
558 # Simple caching without ordering or size limit
559 nonlocal hits, misses
560 key = make_key(args, kwds, typed)
561 result = cache_get(key, sentinel)
562 if result is not sentinel:
563 hits += 1
Raymond Hettinger7e0c5812012-03-17 15:10:24 -0700564 return result
Raymond Hettingerffdf1c32019-01-31 15:03:38 -0800565 misses += 1
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300566 result = user_function(*args, **kwds)
567 cache[key] = result
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300568 return result
Raymond Hettinger7e0c5812012-03-17 15:10:24 -0700569
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300570 else:
Raymond Hettingerbc8e81d2012-03-17 00:24:09 -0700571
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300572 def wrapper(*args, **kwds):
573 # Size limited caching that tracks accesses by recency
574 nonlocal root, hits, misses, full
575 key = make_key(args, kwds, typed)
576 with lock:
577 link = cache_get(key)
578 if link is not None:
579 # Move the link to the front of the circular queue
580 link_prev, link_next, _key, result = link
581 link_prev[NEXT] = link_next
582 link_next[PREV] = link_prev
583 last = root[PREV]
584 last[NEXT] = root[PREV] = link
585 link[PREV] = last
586 link[NEXT] = root
Nick Coghlan234515a2010-11-30 06:19:46 +0000587 hits += 1
Raymond Hettinger4b779b32011-10-15 23:50:42 -0700588 return result
Raymond Hettingerd8080c02019-01-26 03:02:00 -0500589 misses += 1
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300590 result = user_function(*args, **kwds)
591 with lock:
592 if key in cache:
593 # Getting here means that this same key was added to the
594 # cache while the lock was released. Since the link
595 # update is already done, we need only return the
596 # computed result and update the count of misses.
597 pass
598 elif full:
599 # Use the old root to store the new key and result.
600 oldroot = root
601 oldroot[KEY] = key
602 oldroot[RESULT] = result
603 # Empty the oldest link and make it the new root.
604 # Keep a reference to the old key and old result to
605 # prevent their ref counts from going to zero during the
606 # update. That will prevent potentially arbitrary object
607 # clean-up code (i.e. __del__) from running while we're
608 # still adjusting the links.
609 root = oldroot[NEXT]
610 oldkey = root[KEY]
611 oldresult = root[RESULT]
612 root[KEY] = root[RESULT] = None
613 # Now update the cache dictionary.
614 del cache[oldkey]
615 # Save the potentially reentrant cache[key] assignment
616 # for last, after the root and links have been put in
617 # a consistent state.
618 cache[key] = oldroot
619 else:
620 # Put result in a new link at the front of the queue.
621 last = root[PREV]
622 link = [last, root, key, result]
623 last[NEXT] = root[PREV] = cache[key] = link
Raymond Hettingerb2d4b3d2016-12-16 14:59:37 -0800624 # Use the cache_len bound method instead of the len() function
Raymond Hettingeraf56e0e2016-12-16 13:57:40 -0800625 # which could potentially be wrapped in an lru_cache itself.
Raymond Hettingerb2d4b3d2016-12-16 14:59:37 -0800626 full = (cache_len() >= maxsize)
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300627 return result
Raymond Hettingerbc8e81d2012-03-17 00:24:09 -0700628
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300629 def cache_info():
630 """Report cache statistics"""
631 with lock:
Raymond Hettingerb2d4b3d2016-12-16 14:59:37 -0800632 return _CacheInfo(hits, misses, maxsize, cache_len())
Raymond Hettingerbc8e81d2012-03-17 00:24:09 -0700633
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300634 def cache_clear():
635 """Clear the cache and cache statistics"""
636 nonlocal hits, misses, full
637 with lock:
638 cache.clear()
639 root[:] = [root, root, None, None]
640 hits = misses = 0
641 full = False
Georg Brandl2e7346a2010-07-31 18:09:23 +0000642
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300643 wrapper.cache_info = cache_info
644 wrapper.cache_clear = cache_clear
Serhiy Storchakace2295d2015-10-24 09:51:53 +0300645 return wrapper
Nick Coghlan234515a2010-11-30 06:19:46 +0000646
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300647try:
648 from _functools import _lru_cache_wrapper
649except ImportError:
650 pass
Łukasz Langa6f692512013-06-05 12:20:24 +0200651
652
653################################################################################
654### singledispatch() - single-dispatch generic function decorator
655################################################################################
656
Łukasz Langa3720c772013-07-01 16:00:38 +0200657def _c3_merge(sequences):
658 """Merges MROs in *sequences* to a single MRO using the C3 algorithm.
659
660 Adapted from http://www.python.org/download/releases/2.3/mro/.
661
662 """
663 result = []
664 while True:
665 sequences = [s for s in sequences if s] # purge empty sequences
666 if not sequences:
667 return result
668 for s1 in sequences: # find merge candidates among seq heads
669 candidate = s1[0]
670 for s2 in sequences:
671 if candidate in s2[1:]:
672 candidate = None
673 break # reject the current head, it appears later
674 else:
675 break
Yury Selivanov77a8cd62015-08-18 14:20:00 -0400676 if candidate is None:
Łukasz Langa3720c772013-07-01 16:00:38 +0200677 raise RuntimeError("Inconsistent hierarchy")
678 result.append(candidate)
679 # remove the chosen candidate
680 for seq in sequences:
681 if seq[0] == candidate:
682 del seq[0]
683
684def _c3_mro(cls, abcs=None):
685 """Computes the method resolution order using extended C3 linearization.
686
687 If no *abcs* are given, the algorithm works exactly like the built-in C3
688 linearization used for method resolution.
689
690 If given, *abcs* is a list of abstract base classes that should be inserted
691 into the resulting MRO. Unrelated ABCs are ignored and don't end up in the
692 result. The algorithm inserts ABCs where their functionality is introduced,
693 i.e. issubclass(cls, abc) returns True for the class itself but returns
694 False for all its direct base classes. Implicit ABCs for a given class
695 (either registered or inferred from the presence of a special method like
696 __len__) are inserted directly after the last ABC explicitly listed in the
697 MRO of said class. If two implicit ABCs end up next to each other in the
698 resulting MRO, their ordering depends on the order of types in *abcs*.
699
700 """
701 for i, base in enumerate(reversed(cls.__bases__)):
702 if hasattr(base, '__abstractmethods__'):
703 boundary = len(cls.__bases__) - i
704 break # Bases up to the last explicit ABC are considered first.
705 else:
706 boundary = 0
707 abcs = list(abcs) if abcs else []
708 explicit_bases = list(cls.__bases__[:boundary])
709 abstract_bases = []
710 other_bases = list(cls.__bases__[boundary:])
711 for base in abcs:
712 if issubclass(cls, base) and not any(
713 issubclass(b, base) for b in cls.__bases__
714 ):
715 # If *cls* is the class that introduces behaviour described by
716 # an ABC *base*, insert said ABC to its MRO.
717 abstract_bases.append(base)
718 for base in abstract_bases:
719 abcs.remove(base)
720 explicit_c3_mros = [_c3_mro(base, abcs=abcs) for base in explicit_bases]
721 abstract_c3_mros = [_c3_mro(base, abcs=abcs) for base in abstract_bases]
722 other_c3_mros = [_c3_mro(base, abcs=abcs) for base in other_bases]
723 return _c3_merge(
724 [[cls]] +
725 explicit_c3_mros + abstract_c3_mros + other_c3_mros +
726 [explicit_bases] + [abstract_bases] + [other_bases]
727 )
728
729def _compose_mro(cls, types):
730 """Calculates the method resolution order for a given class *cls*.
731
732 Includes relevant abstract base classes (with their respective bases) from
733 the *types* iterable. Uses a modified C3 linearization algorithm.
Łukasz Langa6f692512013-06-05 12:20:24 +0200734
735 """
736 bases = set(cls.__mro__)
Łukasz Langa3720c772013-07-01 16:00:38 +0200737 # Remove entries which are already present in the __mro__ or unrelated.
738 def is_related(typ):
739 return (typ not in bases and hasattr(typ, '__mro__')
740 and issubclass(cls, typ))
741 types = [n for n in types if is_related(n)]
742 # Remove entries which are strict bases of other entries (they will end up
743 # in the MRO anyway.
744 def is_strict_base(typ):
745 for other in types:
746 if typ != other and typ in other.__mro__:
747 return True
748 return False
749 types = [n for n in types if not is_strict_base(n)]
750 # Subclasses of the ABCs in *types* which are also implemented by
751 # *cls* can be used to stabilize ABC ordering.
752 type_set = set(types)
753 mro = []
754 for typ in types:
755 found = []
756 for sub in typ.__subclasses__():
757 if sub not in bases and issubclass(cls, sub):
758 found.append([s for s in sub.__mro__ if s in type_set])
759 if not found:
760 mro.append(typ)
761 continue
762 # Favor subclasses with the biggest number of useful bases
763 found.sort(key=len, reverse=True)
764 for sub in found:
765 for subcls in sub:
766 if subcls not in mro:
767 mro.append(subcls)
768 return _c3_mro(cls, abcs=mro)
Łukasz Langa6f692512013-06-05 12:20:24 +0200769
770def _find_impl(cls, registry):
Łukasz Langa3720c772013-07-01 16:00:38 +0200771 """Returns the best matching implementation from *registry* for type *cls*.
Łukasz Langa6f692512013-06-05 12:20:24 +0200772
Łukasz Langa3720c772013-07-01 16:00:38 +0200773 Where there is no registered implementation for a specific type, its method
774 resolution order is used to find a more generic implementation.
775
776 Note: if *registry* does not contain an implementation for the base
777 *object* type, this function may return None.
Łukasz Langa6f692512013-06-05 12:20:24 +0200778
779 """
780 mro = _compose_mro(cls, registry.keys())
781 match = None
782 for t in mro:
783 if match is not None:
Łukasz Langa3720c772013-07-01 16:00:38 +0200784 # If *match* is an implicit ABC but there is another unrelated,
785 # equally matching implicit ABC, refuse the temptation to guess.
786 if (t in registry and t not in cls.__mro__
787 and match not in cls.__mro__
788 and not issubclass(match, t)):
Łukasz Langa6f692512013-06-05 12:20:24 +0200789 raise RuntimeError("Ambiguous dispatch: {} or {}".format(
790 match, t))
791 break
792 if t in registry:
793 match = t
794 return registry.get(match)
795
796def singledispatch(func):
797 """Single-dispatch generic function decorator.
798
799 Transforms a function into a generic function, which can have different
800 behaviours depending upon the type of its first argument. The decorated
801 function acts as the default implementation, and additional
Łukasz Langa3720c772013-07-01 16:00:38 +0200802 implementations can be registered using the register() attribute of the
803 generic function.
Łukasz Langa6f692512013-06-05 12:20:24 +0200804 """
INADA Naoki9811e802017-09-30 16:13:02 +0900805 # There are many programs that use functools without singledispatch, so we
806 # trade-off making singledispatch marginally slower for the benefit of
807 # making start-up of such applications slightly faster.
808 import types, weakref
809
Łukasz Langa6f692512013-06-05 12:20:24 +0200810 registry = {}
INADA Naoki9811e802017-09-30 16:13:02 +0900811 dispatch_cache = weakref.WeakKeyDictionary()
Łukasz Langa6f692512013-06-05 12:20:24 +0200812 cache_token = None
813
Łukasz Langa3720c772013-07-01 16:00:38 +0200814 def dispatch(cls):
815 """generic_func.dispatch(cls) -> <function implementation>
Łukasz Langa6f692512013-06-05 12:20:24 +0200816
817 Runs the dispatch algorithm to return the best available implementation
Łukasz Langa3720c772013-07-01 16:00:38 +0200818 for the given *cls* registered on *generic_func*.
Łukasz Langa6f692512013-06-05 12:20:24 +0200819
820 """
821 nonlocal cache_token
822 if cache_token is not None:
823 current_token = get_cache_token()
824 if cache_token != current_token:
825 dispatch_cache.clear()
826 cache_token = current_token
827 try:
Łukasz Langa3720c772013-07-01 16:00:38 +0200828 impl = dispatch_cache[cls]
Łukasz Langa6f692512013-06-05 12:20:24 +0200829 except KeyError:
830 try:
Łukasz Langa3720c772013-07-01 16:00:38 +0200831 impl = registry[cls]
Łukasz Langa6f692512013-06-05 12:20:24 +0200832 except KeyError:
Łukasz Langa3720c772013-07-01 16:00:38 +0200833 impl = _find_impl(cls, registry)
834 dispatch_cache[cls] = impl
Łukasz Langa6f692512013-06-05 12:20:24 +0200835 return impl
836
Łukasz Langa3720c772013-07-01 16:00:38 +0200837 def register(cls, func=None):
838 """generic_func.register(cls, func) -> func
Łukasz Langa6f692512013-06-05 12:20:24 +0200839
Łukasz Langa3720c772013-07-01 16:00:38 +0200840 Registers a new implementation for the given *cls* on a *generic_func*.
Łukasz Langa6f692512013-06-05 12:20:24 +0200841
842 """
843 nonlocal cache_token
844 if func is None:
Łukasz Langae5697532017-12-11 13:56:31 -0800845 if isinstance(cls, type):
846 return lambda f: register(cls, f)
847 ann = getattr(cls, '__annotations__', {})
848 if not ann:
849 raise TypeError(
850 f"Invalid first argument to `register()`: {cls!r}. "
851 f"Use either `@register(some_class)` or plain `@register` "
852 f"on an annotated function."
853 )
854 func = cls
855
856 # only import typing if annotation parsing is necessary
857 from typing import get_type_hints
858 argname, cls = next(iter(get_type_hints(func).items()))
Lysandros Nikolaoud6738102019-05-20 00:11:21 +0200859 if not isinstance(cls, type):
860 raise TypeError(
861 f"Invalid annotation for {argname!r}. "
862 f"{cls!r} is not a class."
863 )
Łukasz Langa3720c772013-07-01 16:00:38 +0200864 registry[cls] = func
865 if cache_token is None and hasattr(cls, '__abstractmethods__'):
Łukasz Langa6f692512013-06-05 12:20:24 +0200866 cache_token = get_cache_token()
867 dispatch_cache.clear()
868 return func
869
870 def wrapper(*args, **kw):
Dong-hee Na445f1b32018-07-10 16:26:36 +0900871 if not args:
872 raise TypeError(f'{funcname} requires at least '
873 '1 positional argument')
874
Łukasz Langa6f692512013-06-05 12:20:24 +0200875 return dispatch(args[0].__class__)(*args, **kw)
876
Dong-hee Na445f1b32018-07-10 16:26:36 +0900877 funcname = getattr(func, '__name__', 'singledispatch function')
Łukasz Langa6f692512013-06-05 12:20:24 +0200878 registry[object] = func
879 wrapper.register = register
880 wrapper.dispatch = dispatch
INADA Naoki9811e802017-09-30 16:13:02 +0900881 wrapper.registry = types.MappingProxyType(registry)
Łukasz Langa6f692512013-06-05 12:20:24 +0200882 wrapper._clear_cache = dispatch_cache.clear
883 update_wrapper(wrapper, func)
884 return wrapper
Ethan Smithc6512752018-05-26 16:38:33 -0400885
886
887# Descriptor version
888class singledispatchmethod:
889 """Single-dispatch generic method descriptor.
890
891 Supports wrapping existing descriptors and handles non-descriptor
892 callables as instance methods.
893 """
894
895 def __init__(self, func):
896 if not callable(func) and not hasattr(func, "__get__"):
897 raise TypeError(f"{func!r} is not callable or a descriptor")
898
899 self.dispatcher = singledispatch(func)
900 self.func = func
901
902 def register(self, cls, method=None):
903 """generic_method.register(cls, func) -> func
904
905 Registers a new implementation for the given *cls* on a *generic_method*.
906 """
907 return self.dispatcher.register(cls, func=method)
908
Miss Islington (bot)c71ae1a2019-08-29 02:02:51 -0700909 def __get__(self, obj, cls=None):
Ethan Smithc6512752018-05-26 16:38:33 -0400910 def _method(*args, **kwargs):
911 method = self.dispatcher.dispatch(args[0].__class__)
912 return method.__get__(obj, cls)(*args, **kwargs)
913
914 _method.__isabstractmethod__ = self.__isabstractmethod__
915 _method.register = self.register
916 update_wrapper(_method, self.func)
917 return _method
918
919 @property
920 def __isabstractmethod__(self):
921 return getattr(self.func, '__isabstractmethod__', False)
Carl Meyerd658dea2018-08-28 01:11:56 -0600922
923
924################################################################################
925### cached_property() - computed once per instance, cached as attribute
926################################################################################
927
928_NOT_FOUND = object()
929
930
931class cached_property:
932 def __init__(self, func):
933 self.func = func
934 self.attrname = None
935 self.__doc__ = func.__doc__
936 self.lock = RLock()
937
938 def __set_name__(self, owner, name):
939 if self.attrname is None:
940 self.attrname = name
941 elif name != self.attrname:
942 raise TypeError(
943 "Cannot assign the same cached_property to two different names "
944 f"({self.attrname!r} and {name!r})."
945 )
946
Miss Islington (bot)c71ae1a2019-08-29 02:02:51 -0700947 def __get__(self, instance, owner=None):
Carl Meyerd658dea2018-08-28 01:11:56 -0600948 if instance is None:
949 return self
950 if self.attrname is None:
951 raise TypeError(
952 "Cannot use cached_property instance without calling __set_name__ on it.")
953 try:
954 cache = instance.__dict__
955 except AttributeError: # not all objects have __dict__ (e.g. class defines slots)
956 msg = (
957 f"No '__dict__' attribute on {type(instance).__name__!r} "
958 f"instance to cache {self.attrname!r} property."
959 )
960 raise TypeError(msg) from None
961 val = cache.get(self.attrname, _NOT_FOUND)
962 if val is _NOT_FOUND:
963 with self.lock:
964 # check if another thread filled cache while we awaited lock
965 val = cache.get(self.attrname, _NOT_FOUND)
966 if val is _NOT_FOUND:
967 val = self.func(instance)
968 try:
969 cache[self.attrname] = val
970 except TypeError:
971 msg = (
972 f"The '__dict__' attribute on {type(instance).__name__!r} instance "
973 f"does not support item assignment for caching {self.attrname!r} property."
974 )
975 raise TypeError(msg) from None
976 return val