blob: 5cab497d264037b6dae2d647ce13a1f75663ef5d [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',
Raymond Hettinger21cdb712020-05-11 17:00:53 -070013 'total_ordering', 'cache', 'cmp_to_key', 'lru_cache', 'reduce',
Hakan Çelik217dce92020-03-02 00:01:34 +030014 'partial', 'partialmethod', 'singledispatch', 'singledispatchmethod',
Nikita Sobolevbd87a7f2020-03-11 03:32:15 +030015 '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
Ethan Smithcecf0492020-04-13 21:53:04 -070022from types import GenericAlias
Thomas Wouters4d70c3d2006-06-08 14:42:34 +000023
Raymond Hettingerbc8e81d2012-03-17 00:24:09 -070024
25################################################################################
26### update_wrapper() and wraps() decorator
27################################################################################
28
Thomas Wouters73e5a5b2006-06-08 15:35:45 +000029# update_wrapper() and wraps() are tools to help write
30# wrapper functions that can handle naive introspection
31
Meador Ingeff7f64c2011-12-11 22:37:31 -060032WRAPPER_ASSIGNMENTS = ('__module__', '__name__', '__qualname__', '__doc__',
33 '__annotations__')
Thomas Wouters73e5a5b2006-06-08 15:35:45 +000034WRAPPER_UPDATES = ('__dict__',)
35def update_wrapper(wrapper,
36 wrapped,
37 assigned = WRAPPER_ASSIGNMENTS,
38 updated = WRAPPER_UPDATES):
39 """Update a wrapper function to look like the wrapped function
40
41 wrapper is the function to be updated
42 wrapped is the original function
43 assigned is a tuple naming the attributes assigned directly
44 from the wrapped function to the wrapper function (defaults to
45 functools.WRAPPER_ASSIGNMENTS)
Thomas Wouters89f507f2006-12-13 04:49:30 +000046 updated is a tuple naming the attributes of the wrapper that
Thomas Wouters73e5a5b2006-06-08 15:35:45 +000047 are updated with the corresponding attribute from the wrapped
48 function (defaults to functools.WRAPPER_UPDATES)
49 """
50 for attr in assigned:
Nick Coghlan98876832010-08-17 06:17:18 +000051 try:
52 value = getattr(wrapped, attr)
53 except AttributeError:
54 pass
55 else:
56 setattr(wrapper, attr, value)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +000057 for attr in updated:
Thomas Wouters89f507f2006-12-13 04:49:30 +000058 getattr(wrapper, attr).update(getattr(wrapped, attr, {}))
Nick Coghlan24c05bc2013-07-15 21:13:08 +100059 # Issue #17482: set __wrapped__ last so we don't inadvertently copy it
60 # from the wrapped function when updating __dict__
61 wrapper.__wrapped__ = wrapped
Thomas Wouters73e5a5b2006-06-08 15:35:45 +000062 # Return the wrapper so this can be used as a decorator via partial()
63 return wrapper
64
65def wraps(wrapped,
66 assigned = WRAPPER_ASSIGNMENTS,
67 updated = WRAPPER_UPDATES):
68 """Decorator factory to apply update_wrapper() to a wrapper function
69
70 Returns a decorator that invokes update_wrapper() with the decorated
71 function as the wrapper argument and the arguments to wraps() as the
72 remaining arguments. Default arguments are as for update_wrapper().
73 This is a convenience function to simplify applying partial() to
74 update_wrapper().
75 """
76 return partial(update_wrapper, wrapped=wrapped,
77 assigned=assigned, updated=updated)
Raymond Hettingerc50846a2010-04-05 18:56:31 +000078
Raymond Hettingerbc8e81d2012-03-17 00:24:09 -070079
80################################################################################
81### total_ordering class decorator
82################################################################################
83
Raymond Hettinger0603d302015-01-05 21:52:10 -080084# The total ordering functions all invoke the root magic method directly
85# rather than using the corresponding operator. This avoids possible
86# infinite recursion that could occur when the operator dispatch logic
87# detects a NotImplemented result and then calls a reflected method.
Nick Coghlanf05d9812013-10-02 00:02:03 +100088
Raymond Hettingerffcd8492015-05-12 21:26:37 -070089def _gt_from_lt(self, other, NotImplemented=NotImplemented):
Raymond Hettinger0603d302015-01-05 21:52:10 -080090 'Return a > b. Computed by @total_ordering from (not a < b) and (a != b).'
91 op_result = self.__lt__(other)
Nick Coghlanf05d9812013-10-02 00:02:03 +100092 if op_result is NotImplemented:
Raymond Hettingere5db8632015-01-06 22:16:10 -080093 return op_result
Nick Coghlanf05d9812013-10-02 00:02:03 +100094 return not op_result and self != other
95
Raymond Hettingerffcd8492015-05-12 21:26:37 -070096def _le_from_lt(self, other, NotImplemented=NotImplemented):
Raymond Hettinger0603d302015-01-05 21:52:10 -080097 'Return a <= b. Computed by @total_ordering from (a < b) or (a == b).'
98 op_result = self.__lt__(other)
MojoVampire469325c2020-03-03 18:50:17 +000099 if op_result is NotImplemented:
100 return op_result
Raymond Hettinger0603d302015-01-05 21:52:10 -0800101 return op_result or self == other
102
Raymond Hettingerffcd8492015-05-12 21:26:37 -0700103def _ge_from_lt(self, other, NotImplemented=NotImplemented):
Raymond Hettinger0603d302015-01-05 21:52:10 -0800104 'Return a >= b. Computed by @total_ordering from (not a < b).'
105 op_result = self.__lt__(other)
106 if op_result is NotImplemented:
Raymond Hettingere5db8632015-01-06 22:16:10 -0800107 return op_result
Raymond Hettinger0603d302015-01-05 21:52:10 -0800108 return not op_result
109
Raymond Hettingerffcd8492015-05-12 21:26:37 -0700110def _ge_from_le(self, other, NotImplemented=NotImplemented):
Raymond Hettinger0603d302015-01-05 21:52:10 -0800111 'Return a >= b. Computed by @total_ordering from (not a <= b) or (a == b).'
112 op_result = self.__le__(other)
Nick Coghlanf05d9812013-10-02 00:02:03 +1000113 if op_result is NotImplemented:
Raymond Hettingere5db8632015-01-06 22:16:10 -0800114 return op_result
Nick Coghlanf05d9812013-10-02 00:02:03 +1000115 return not op_result or self == other
116
Raymond Hettingerffcd8492015-05-12 21:26:37 -0700117def _lt_from_le(self, other, NotImplemented=NotImplemented):
Raymond Hettinger0603d302015-01-05 21:52:10 -0800118 'Return a < b. Computed by @total_ordering from (a <= b) and (a != b).'
119 op_result = self.__le__(other)
Nick Coghlanf05d9812013-10-02 00:02:03 +1000120 if op_result is NotImplemented:
Raymond Hettingere5db8632015-01-06 22:16:10 -0800121 return op_result
Nick Coghlanf05d9812013-10-02 00:02:03 +1000122 return op_result and self != other
123
Raymond Hettingerffcd8492015-05-12 21:26:37 -0700124def _gt_from_le(self, other, NotImplemented=NotImplemented):
Raymond Hettinger0603d302015-01-05 21:52:10 -0800125 'Return a > b. Computed by @total_ordering from (not a <= b).'
126 op_result = self.__le__(other)
127 if op_result is NotImplemented:
Raymond Hettingere5db8632015-01-06 22:16:10 -0800128 return op_result
Raymond Hettinger0603d302015-01-05 21:52:10 -0800129 return not op_result
130
Raymond Hettingerffcd8492015-05-12 21:26:37 -0700131def _lt_from_gt(self, other, NotImplemented=NotImplemented):
Raymond Hettinger0603d302015-01-05 21:52:10 -0800132 'Return a < b. Computed by @total_ordering from (not a > b) and (a != b).'
133 op_result = self.__gt__(other)
134 if op_result is NotImplemented:
Raymond Hettingere5db8632015-01-06 22:16:10 -0800135 return op_result
Raymond Hettinger0603d302015-01-05 21:52:10 -0800136 return not op_result and self != other
137
Raymond Hettingerffcd8492015-05-12 21:26:37 -0700138def _ge_from_gt(self, other, NotImplemented=NotImplemented):
Raymond Hettinger0603d302015-01-05 21:52:10 -0800139 'Return a >= b. Computed by @total_ordering from (a > b) or (a == b).'
140 op_result = self.__gt__(other)
MojoVampire469325c2020-03-03 18:50:17 +0000141 if op_result is NotImplemented:
142 return op_result
Raymond Hettinger0603d302015-01-05 21:52:10 -0800143 return op_result or self == other
144
Raymond Hettingerffcd8492015-05-12 21:26:37 -0700145def _le_from_gt(self, other, NotImplemented=NotImplemented):
Raymond Hettinger0603d302015-01-05 21:52:10 -0800146 'Return a <= b. Computed by @total_ordering from (not a > b).'
147 op_result = self.__gt__(other)
148 if op_result is NotImplemented:
Raymond Hettingere5db8632015-01-06 22:16:10 -0800149 return op_result
Raymond Hettinger0603d302015-01-05 21:52:10 -0800150 return not op_result
151
Raymond Hettingerffcd8492015-05-12 21:26:37 -0700152def _le_from_ge(self, other, NotImplemented=NotImplemented):
Raymond Hettinger0603d302015-01-05 21:52:10 -0800153 'Return a <= b. Computed by @total_ordering from (not a >= b) or (a == b).'
154 op_result = self.__ge__(other)
155 if op_result is NotImplemented:
Raymond Hettingere5db8632015-01-06 22:16:10 -0800156 return op_result
Raymond Hettinger0603d302015-01-05 21:52:10 -0800157 return not op_result or self == other
158
Raymond Hettingerffcd8492015-05-12 21:26:37 -0700159def _gt_from_ge(self, other, NotImplemented=NotImplemented):
Raymond Hettinger0603d302015-01-05 21:52:10 -0800160 'Return a > b. Computed by @total_ordering from (a >= b) and (a != b).'
161 op_result = self.__ge__(other)
162 if op_result is NotImplemented:
Raymond Hettingere5db8632015-01-06 22:16:10 -0800163 return op_result
Raymond Hettinger0603d302015-01-05 21:52:10 -0800164 return op_result and self != other
165
Raymond Hettingerffcd8492015-05-12 21:26:37 -0700166def _lt_from_ge(self, other, NotImplemented=NotImplemented):
Raymond Hettinger0603d302015-01-05 21:52:10 -0800167 'Return a < b. Computed by @total_ordering from (not a >= b).'
168 op_result = self.__ge__(other)
169 if op_result is NotImplemented:
Raymond Hettingere5db8632015-01-06 22:16:10 -0800170 return op_result
Raymond Hettinger0603d302015-01-05 21:52:10 -0800171 return not op_result
Raymond Hettingerc50846a2010-04-05 18:56:31 +0000172
Raymond Hettinger1a8ada82015-01-13 22:57:35 -0800173_convert = {
174 '__lt__': [('__gt__', _gt_from_lt),
175 ('__le__', _le_from_lt),
176 ('__ge__', _ge_from_lt)],
177 '__le__': [('__ge__', _ge_from_le),
178 ('__lt__', _lt_from_le),
179 ('__gt__', _gt_from_le)],
180 '__gt__': [('__lt__', _lt_from_gt),
181 ('__ge__', _ge_from_gt),
182 ('__le__', _le_from_gt)],
183 '__ge__': [('__le__', _le_from_ge),
184 ('__gt__', _gt_from_ge),
185 ('__lt__', _lt_from_ge)]
186}
187
Raymond Hettingerc50846a2010-04-05 18:56:31 +0000188def total_ordering(cls):
Georg Brandle5a26732010-05-19 21:06:36 +0000189 """Class decorator that fills in missing ordering methods"""
Raymond Hettinger3255c632010-09-16 00:31:21 +0000190 # Find user-defined comparisons (not those inherited from object).
Raymond Hettinger15ce0be2017-09-05 09:40:44 -0700191 roots = {op for op in _convert if getattr(cls, op, None) is not getattr(object, op, None)}
Raymond Hettinger56de7e22010-04-10 16:59:03 +0000192 if not roots:
193 raise ValueError('must define at least one ordering operation: < > <= >=')
194 root = max(roots) # prefer __lt__ to __le__ to __gt__ to __ge__
Raymond Hettinger1a8ada82015-01-13 22:57:35 -0800195 for opname, opfunc in _convert[root]:
Raymond Hettingerc50846a2010-04-05 18:56:31 +0000196 if opname not in roots:
197 opfunc.__name__ = opname
Raymond Hettingerc50846a2010-04-05 18:56:31 +0000198 setattr(cls, opname, opfunc)
199 return cls
200
Raymond Hettingerbc8e81d2012-03-17 00:24:09 -0700201
202################################################################################
203### cmp_to_key() function converter
204################################################################################
205
Raymond Hettingerc50846a2010-04-05 18:56:31 +0000206def cmp_to_key(mycmp):
Georg Brandle5a26732010-05-19 21:06:36 +0000207 """Convert a cmp= function into a key= function"""
Raymond Hettingerc50846a2010-04-05 18:56:31 +0000208 class K(object):
Raymond Hettingera0d1d962011-03-21 17:50:28 -0700209 __slots__ = ['obj']
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700210 def __init__(self, obj):
Raymond Hettingerc50846a2010-04-05 18:56:31 +0000211 self.obj = obj
212 def __lt__(self, other):
213 return mycmp(self.obj, other.obj) < 0
214 def __gt__(self, other):
215 return mycmp(self.obj, other.obj) > 0
216 def __eq__(self, other):
217 return mycmp(self.obj, other.obj) == 0
218 def __le__(self, other):
219 return mycmp(self.obj, other.obj) <= 0
220 def __ge__(self, other):
221 return mycmp(self.obj, other.obj) >= 0
Raymond Hettinger003be522011-05-03 11:01:32 -0700222 __hash__ = None
Raymond Hettingerc50846a2010-04-05 18:56:31 +0000223 return K
Georg Brandl2e7346a2010-07-31 18:09:23 +0000224
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700225try:
226 from _functools import cmp_to_key
Brett Cannoncd171c82013-07-04 17:43:24 -0400227except ImportError:
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700228 pass
229
Raymond Hettingerbc8e81d2012-03-17 00:24:09 -0700230
231################################################################################
madman-bobe25d5fc2018-10-25 15:02:10 +0100232### reduce() sequence to a single item
233################################################################################
234
235_initial_missing = object()
236
237def reduce(function, sequence, initial=_initial_missing):
238 """
239 reduce(function, sequence[, initial]) -> value
240
241 Apply a function of two arguments cumulatively to the items of a sequence,
242 from left to right, so as to reduce the sequence to a single value.
243 For example, reduce(lambda x, y: x+y, [1, 2, 3, 4, 5]) calculates
244 ((((1+2)+3)+4)+5). If initial is present, it is placed before the items
245 of the sequence in the calculation, and serves as a default when the
246 sequence is empty.
247 """
248
249 it = iter(sequence)
250
251 if initial is _initial_missing:
252 try:
253 value = next(it)
254 except StopIteration:
255 raise TypeError("reduce() of empty sequence with no initial value") from None
256 else:
257 value = initial
258
259 for element in it:
260 value = function(value, element)
261
262 return value
263
264try:
265 from _functools import reduce
266except ImportError:
267 pass
268
269
270################################################################################
Antoine Pitroub5b37142012-11-13 21:35:40 +0100271### partial() argument application
272################################################################################
273
Nick Coghlanf4cb48a2013-11-03 16:41:46 +1000274# Purely functional, no descriptor behaviour
Nick Coghlan457fc9a2016-09-10 20:00:02 +1000275class partial:
Nick Coghlanf4cb48a2013-11-03 16:41:46 +1000276 """New function with partial application of the given arguments
Antoine Pitroub5b37142012-11-13 21:35:40 +0100277 and keywords.
278 """
Alexander Belopolskye49af342015-03-01 15:08:17 -0500279
Nick Coghlan457fc9a2016-09-10 20:00:02 +1000280 __slots__ = "func", "args", "keywords", "__dict__", "__weakref__"
281
Serhiy Storchaka2085bd02019-06-01 11:00:15 +0300282 def __new__(cls, func, /, *args, **keywords):
Nick Coghlan457fc9a2016-09-10 20:00:02 +1000283 if not callable(func):
284 raise TypeError("the first argument must be callable")
Nick Coghlan457fc9a2016-09-10 20:00:02 +1000285
286 if hasattr(func, "func"):
287 args = func.args + args
Serhiy Storchakada084702019-03-27 08:02:28 +0200288 keywords = {**func.keywords, **keywords}
Nick Coghlan457fc9a2016-09-10 20:00:02 +1000289 func = func.func
290
291 self = super(partial, cls).__new__(cls)
292
293 self.func = func
294 self.args = args
295 self.keywords = keywords
296 return self
297
Serhiy Storchaka2085bd02019-06-01 11:00:15 +0300298 def __call__(self, /, *args, **keywords):
Serhiy Storchakada084702019-03-27 08:02:28 +0200299 keywords = {**self.keywords, **keywords}
300 return self.func(*self.args, *args, **keywords)
Nick Coghlan457fc9a2016-09-10 20:00:02 +1000301
302 @recursive_repr()
303 def __repr__(self):
304 qualname = type(self).__qualname__
305 args = [repr(self.func)]
306 args.extend(repr(x) for x in self.args)
307 args.extend(f"{k}={v!r}" for (k, v) in self.keywords.items())
308 if type(self).__module__ == "functools":
309 return f"functools.{qualname}({', '.join(args)})"
310 return f"{qualname}({', '.join(args)})"
311
312 def __reduce__(self):
313 return type(self), (self.func,), (self.func, self.args,
314 self.keywords or None, self.__dict__ or None)
315
316 def __setstate__(self, state):
317 if not isinstance(state, tuple):
318 raise TypeError("argument to __setstate__ must be a tuple")
319 if len(state) != 4:
320 raise TypeError(f"expected 4 items in state, got {len(state)}")
321 func, args, kwds, namespace = state
322 if (not callable(func) or not isinstance(args, tuple) or
323 (kwds is not None and not isinstance(kwds, dict)) or
324 (namespace is not None and not isinstance(namespace, dict))):
325 raise TypeError("invalid partial state")
326
327 args = tuple(args) # just in case it's a subclass
328 if kwds is None:
329 kwds = {}
330 elif type(kwds) is not dict: # XXX does it need to be *exactly* dict?
331 kwds = dict(kwds)
332 if namespace is None:
333 namespace = {}
334
335 self.__dict__ = namespace
336 self.func = func
337 self.args = args
338 self.keywords = kwds
Antoine Pitroub5b37142012-11-13 21:35:40 +0100339
340try:
341 from _functools import partial
Brett Cannoncd171c82013-07-04 17:43:24 -0400342except ImportError:
Antoine Pitroub5b37142012-11-13 21:35:40 +0100343 pass
344
Nick Coghlanf4cb48a2013-11-03 16:41:46 +1000345# Descriptor version
346class partialmethod(object):
347 """Method descriptor with partial application of the given arguments
348 and keywords.
349
350 Supports wrapping existing descriptors and handles non-descriptor
351 callables as instance methods.
352 """
353
Serhiy Storchaka142566c2019-06-05 18:22:31 +0300354 def __init__(self, func, /, *args, **keywords):
Nick Coghlanf4cb48a2013-11-03 16:41:46 +1000355 if not callable(func) and not hasattr(func, "__get__"):
356 raise TypeError("{!r} is not callable or a descriptor"
357 .format(func))
358
359 # func could be a descriptor like classmethod which isn't callable,
360 # so we can't inherit from partial (it verifies func is callable)
361 if isinstance(func, partialmethod):
362 # flattening is mandatory in order to place cls/self before all
363 # other arguments
364 # it's also more efficient since only one function will be called
365 self.func = func.func
366 self.args = func.args + args
Serhiy Storchakada084702019-03-27 08:02:28 +0200367 self.keywords = {**func.keywords, **keywords}
Nick Coghlanf4cb48a2013-11-03 16:41:46 +1000368 else:
369 self.func = func
370 self.args = args
371 self.keywords = keywords
372
373 def __repr__(self):
374 args = ", ".join(map(repr, self.args))
375 keywords = ", ".join("{}={!r}".format(k, v)
376 for k, v in self.keywords.items())
377 format_string = "{module}.{cls}({func}, {args}, {keywords})"
378 return format_string.format(module=self.__class__.__module__,
Serhiy Storchaka521e5862014-07-22 15:00:37 +0300379 cls=self.__class__.__qualname__,
Nick Coghlanf4cb48a2013-11-03 16:41:46 +1000380 func=self.func,
381 args=args,
382 keywords=keywords)
383
384 def _make_unbound_method(self):
Serhiy Storchaka2085bd02019-06-01 11:00:15 +0300385 def _method(cls_or_self, /, *args, **keywords):
Serhiy Storchakada084702019-03-27 08:02:28 +0200386 keywords = {**self.keywords, **keywords}
387 return self.func(cls_or_self, *self.args, *args, **keywords)
Nick Coghlanf4cb48a2013-11-03 16:41:46 +1000388 _method.__isabstractmethod__ = self.__isabstractmethod__
Yury Selivanovda5fe4f2014-01-27 17:28:37 -0500389 _method._partialmethod = self
Nick Coghlanf4cb48a2013-11-03 16:41:46 +1000390 return _method
391
Raymond Hettinger0dac68f2019-08-29 01:27:42 -0700392 def __get__(self, obj, cls=None):
Nick Coghlanf4cb48a2013-11-03 16:41:46 +1000393 get = getattr(self.func, "__get__", None)
394 result = None
395 if get is not None:
396 new_func = get(obj, cls)
397 if new_func is not self.func:
398 # Assume __get__ returning something new indicates the
399 # creation of an appropriate callable
400 result = partial(new_func, *self.args, **self.keywords)
401 try:
402 result.__self__ = new_func.__self__
403 except AttributeError:
404 pass
405 if result is None:
406 # If the underlying descriptor didn't do anything, treat this
407 # like an instance method
408 result = self._make_unbound_method().__get__(obj, cls)
409 return result
410
411 @property
412 def __isabstractmethod__(self):
413 return getattr(self.func, "__isabstractmethod__", False)
414
Ethan Smithcecf0492020-04-13 21:53:04 -0700415 __class_getitem__ = classmethod(GenericAlias)
416
417
Pablo Galindo7cd25432018-10-26 12:19:14 +0100418# Helper functions
419
420def _unwrap_partial(func):
421 while isinstance(func, partial):
422 func = func.func
423 return func
Antoine Pitroub5b37142012-11-13 21:35:40 +0100424
425################################################################################
Raymond Hettingerbc8e81d2012-03-17 00:24:09 -0700426### LRU Cache function decorator
427################################################################################
428
Raymond Hettingerdce583e2012-03-16 22:12:20 -0700429_CacheInfo = namedtuple("CacheInfo", ["hits", "misses", "maxsize", "currsize"])
Nick Coghlan234515a2010-11-30 06:19:46 +0000430
Raymond Hettinger0c9050c2012-06-04 00:21:14 -0700431class _HashedSeq(list):
Raymond Hettingerf96b2b02013-03-08 21:11:55 -0700432 """ This class guarantees that hash() will be called no more than once
433 per element. This is important because the lru_cache() will hash
434 the key multiple times on a cache miss.
435
436 """
437
Raymond Hettinger9acbb602012-04-30 22:32:16 -0700438 __slots__ = 'hashvalue'
439
Raymond Hettinger0c9050c2012-06-04 00:21:14 -0700440 def __init__(self, tup, hash=hash):
441 self[:] = tup
442 self.hashvalue = hash(tup)
Raymond Hettinger9acbb602012-04-30 22:32:16 -0700443
444 def __hash__(self):
445 return self.hashvalue
446
Raymond Hettinger0c9050c2012-06-04 00:21:14 -0700447def _make_key(args, kwds, typed,
448 kwd_mark = (object(),),
Raymond Hettingerd8080c02019-01-26 03:02:00 -0500449 fasttypes = {int, str},
Raymond Hettinger4ee39142017-01-08 17:28:20 -0800450 tuple=tuple, type=type, len=len):
Raymond Hettingerf96b2b02013-03-08 21:11:55 -0700451 """Make a cache key from optionally typed positional and keyword arguments
452
453 The key is constructed in a way that is flat as possible rather than
454 as a nested structure that would take more memory.
455
456 If there is only a single argument and its data type is known to cache
457 its hash value, then that argument is returned without a wrapper. This
458 saves space and improves lookup speed.
459
460 """
Raymond Hettinger55037092017-09-04 17:47:53 -0700461 # All of code below relies on kwds preserving the order input by the user.
462 # Formerly, we sorted() the kwds before looping. The new way is *much*
463 # faster; however, it means that f(x=1, y=2) will now be treated as a
464 # distinct call from f(y=2, x=1) which will be cached separately.
Raymond Hettinger0c9050c2012-06-04 00:21:14 -0700465 key = args
466 if kwds:
Raymond Hettinger0c9050c2012-06-04 00:21:14 -0700467 key += kwd_mark
Raymond Hettinger4ee39142017-01-08 17:28:20 -0800468 for item in kwds.items():
Raymond Hettinger0c9050c2012-06-04 00:21:14 -0700469 key += item
470 if typed:
471 key += tuple(type(v) for v in args)
472 if kwds:
Raymond Hettinger4ee39142017-01-08 17:28:20 -0800473 key += tuple(type(v) for v in kwds.values())
Raymond Hettinger0c9050c2012-06-04 00:21:14 -0700474 elif len(key) == 1 and type(key[0]) in fasttypes:
475 return key[0]
476 return _HashedSeq(key)
477
Raymond Hettinger010ce322012-05-19 21:20:48 -0700478def lru_cache(maxsize=128, typed=False):
Benjamin Peterson1f594ad2010-08-08 13:17:07 +0000479 """Least-recently-used cache decorator.
Georg Brandl2e7346a2010-07-31 18:09:23 +0000480
Raymond Hettingerc79fb0e2010-12-01 03:45:41 +0000481 If *maxsize* is set to None, the LRU features are disabled and the cache
482 can grow without bound.
483
Raymond Hettingercd9fdfd2011-10-20 08:57:45 -0700484 If *typed* is True, arguments of different types will be cached separately.
485 For example, f(3.0) and f(3) will be treated as distinct calls with
486 distinct results.
487
Georg Brandl2e7346a2010-07-31 18:09:23 +0000488 Arguments to the cached function must be hashable.
Raymond Hettinger5fa40c02010-11-25 08:11:57 +0000489
Raymond Hettinger7f7a5a72012-03-30 21:50:40 -0700490 View the cache statistics named tuple (hits, misses, maxsize, currsize)
491 with f.cache_info(). Clear the cache and statistics with f.cache_clear().
Raymond Hettinger00f2f972010-12-01 00:47:56 +0000492 Access the underlying function with f.__wrapped__.
Raymond Hettinger5fa40c02010-11-25 08:11:57 +0000493
amist336b3062019-09-16 21:36:14 +0300494 See: http://en.wikipedia.org/wiki/Cache_replacement_policies#Least_recently_used_(LRU)
Georg Brandl2e7346a2010-07-31 18:09:23 +0000495
Benjamin Peterson1f594ad2010-08-08 13:17:07 +0000496 """
Raymond Hettinger1ff50df2012-03-30 13:15:48 -0700497
Raymond Hettinger5fa40c02010-11-25 08:11:57 +0000498 # Users should only access the lru_cache through its public API:
Raymond Hettinger5e20bab2010-11-30 07:13:04 +0000499 # cache_info, cache_clear, and f.__wrapped__
Raymond Hettinger5fa40c02010-11-25 08:11:57 +0000500 # The internals of the lru_cache are encapsulated for thread safety and
501 # to allow the implementation to change (including a possible C version).
502
Raymond Hettingerd8080c02019-01-26 03:02:00 -0500503 if isinstance(maxsize, int):
Raymond Hettingerb8218682019-05-26 11:27:35 -0700504 # Negative maxsize is treated as 0
Raymond Hettingerd8080c02019-01-26 03:02:00 -0500505 if maxsize < 0:
506 maxsize = 0
Raymond Hettingerb8218682019-05-26 11:27:35 -0700507 elif callable(maxsize) and isinstance(typed, bool):
508 # The user_function was passed in directly via the maxsize argument
509 user_function, maxsize = maxsize, 128
510 wrapper = _lru_cache_wrapper(user_function, maxsize, typed, _CacheInfo)
Manjusaka051ff522019-11-12 15:30:18 +0800511 wrapper.cache_parameters = lambda : {'maxsize': maxsize, 'typed': typed}
Raymond Hettingerb8218682019-05-26 11:27:35 -0700512 return update_wrapper(wrapper, user_function)
Raymond Hettingerd8080c02019-01-26 03:02:00 -0500513 elif maxsize is not None:
Raymond Hettingerb8218682019-05-26 11:27:35 -0700514 raise TypeError(
515 'Expected first argument to be an integer, a callable, or None')
Raymond Hettinger4d588972014-08-12 12:44:52 -0700516
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300517 def decorating_function(user_function):
518 wrapper = _lru_cache_wrapper(user_function, maxsize, typed, _CacheInfo)
Manjusaka051ff522019-11-12 15:30:18 +0800519 wrapper.cache_parameters = lambda : {'maxsize': maxsize, 'typed': typed}
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300520 return update_wrapper(wrapper, user_function)
521
522 return decorating_function
523
524def _lru_cache_wrapper(user_function, maxsize, typed, _CacheInfo):
Raymond Hettinger9f0ab9f2012-04-29 14:55:27 -0700525 # Constants shared by all lru cache instances:
Raymond Hettingerb6b98c02012-04-29 18:09:02 -0700526 sentinel = object() # unique object used to signal cache misses
Raymond Hettinger0c9050c2012-06-04 00:21:14 -0700527 make_key = _make_key # build a key from the function arguments
Raymond Hettinger9f0ab9f2012-04-29 14:55:27 -0700528 PREV, NEXT, KEY, RESULT = 0, 1, 2, 3 # names for the link fields
529
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300530 cache = {}
531 hits = misses = 0
532 full = False
533 cache_get = cache.get # bound method to lookup a key or return None
Raymond Hettingerb2d4b3d2016-12-16 14:59:37 -0800534 cache_len = cache.__len__ # get cache size without calling len()
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300535 lock = RLock() # because linkedlist updates aren't threadsafe
536 root = [] # root of the circular doubly linked list
537 root[:] = [root, root, None, None] # initialize by pointing to self
Raymond Hettinger6e8c8172012-03-16 16:53:05 -0700538
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300539 if maxsize == 0:
Raymond Hettinger7e0c5812012-03-17 15:10:24 -0700540
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300541 def wrapper(*args, **kwds):
Raymond Hettingerffdf1c32019-01-31 15:03:38 -0800542 # No caching -- just a statistics update
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300543 nonlocal misses
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300544 misses += 1
Raymond Hettingerffdf1c32019-01-31 15:03:38 -0800545 result = user_function(*args, **kwds)
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300546 return result
547
548 elif maxsize is None:
549
550 def wrapper(*args, **kwds):
551 # Simple caching without ordering or size limit
552 nonlocal hits, misses
553 key = make_key(args, kwds, typed)
554 result = cache_get(key, sentinel)
555 if result is not sentinel:
556 hits += 1
Raymond Hettinger7e0c5812012-03-17 15:10:24 -0700557 return result
Raymond Hettingerffdf1c32019-01-31 15:03:38 -0800558 misses += 1
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300559 result = user_function(*args, **kwds)
560 cache[key] = result
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300561 return result
Raymond Hettinger7e0c5812012-03-17 15:10:24 -0700562
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300563 else:
Raymond Hettingerbc8e81d2012-03-17 00:24:09 -0700564
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300565 def wrapper(*args, **kwds):
566 # Size limited caching that tracks accesses by recency
567 nonlocal root, hits, misses, full
568 key = make_key(args, kwds, typed)
569 with lock:
570 link = cache_get(key)
571 if link is not None:
572 # Move the link to the front of the circular queue
573 link_prev, link_next, _key, result = link
574 link_prev[NEXT] = link_next
575 link_next[PREV] = link_prev
576 last = root[PREV]
577 last[NEXT] = root[PREV] = link
578 link[PREV] = last
579 link[NEXT] = root
Nick Coghlan234515a2010-11-30 06:19:46 +0000580 hits += 1
Raymond Hettinger4b779b32011-10-15 23:50:42 -0700581 return result
Raymond Hettingerd8080c02019-01-26 03:02:00 -0500582 misses += 1
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300583 result = user_function(*args, **kwds)
584 with lock:
585 if key in cache:
586 # Getting here means that this same key was added to the
587 # cache while the lock was released. Since the link
588 # update is already done, we need only return the
589 # computed result and update the count of misses.
590 pass
591 elif full:
592 # Use the old root to store the new key and result.
593 oldroot = root
594 oldroot[KEY] = key
595 oldroot[RESULT] = result
596 # Empty the oldest link and make it the new root.
597 # Keep a reference to the old key and old result to
598 # prevent their ref counts from going to zero during the
599 # update. That will prevent potentially arbitrary object
600 # clean-up code (i.e. __del__) from running while we're
601 # still adjusting the links.
602 root = oldroot[NEXT]
603 oldkey = root[KEY]
604 oldresult = root[RESULT]
605 root[KEY] = root[RESULT] = None
606 # Now update the cache dictionary.
607 del cache[oldkey]
608 # Save the potentially reentrant cache[key] assignment
609 # for last, after the root and links have been put in
610 # a consistent state.
611 cache[key] = oldroot
612 else:
613 # Put result in a new link at the front of the queue.
614 last = root[PREV]
615 link = [last, root, key, result]
616 last[NEXT] = root[PREV] = cache[key] = link
Raymond Hettingerb2d4b3d2016-12-16 14:59:37 -0800617 # Use the cache_len bound method instead of the len() function
Raymond Hettingeraf56e0e2016-12-16 13:57:40 -0800618 # which could potentially be wrapped in an lru_cache itself.
Raymond Hettingerb2d4b3d2016-12-16 14:59:37 -0800619 full = (cache_len() >= maxsize)
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300620 return result
Raymond Hettingerbc8e81d2012-03-17 00:24:09 -0700621
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300622 def cache_info():
623 """Report cache statistics"""
624 with lock:
Raymond Hettingerb2d4b3d2016-12-16 14:59:37 -0800625 return _CacheInfo(hits, misses, maxsize, cache_len())
Raymond Hettingerbc8e81d2012-03-17 00:24:09 -0700626
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300627 def cache_clear():
628 """Clear the cache and cache statistics"""
629 nonlocal hits, misses, full
630 with lock:
631 cache.clear()
632 root[:] = [root, root, None, None]
633 hits = misses = 0
634 full = False
Georg Brandl2e7346a2010-07-31 18:09:23 +0000635
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300636 wrapper.cache_info = cache_info
637 wrapper.cache_clear = cache_clear
Serhiy Storchakace2295d2015-10-24 09:51:53 +0300638 return wrapper
Nick Coghlan234515a2010-11-30 06:19:46 +0000639
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300640try:
641 from _functools import _lru_cache_wrapper
642except ImportError:
643 pass
Łukasz Langa6f692512013-06-05 12:20:24 +0200644
645
646################################################################################
Raymond Hettinger21cdb712020-05-11 17:00:53 -0700647### cache -- simplified access to the infinity cache
648################################################################################
649
650def cache(user_function, /):
651 'Simple lightweight unbounded cache. Sometimes called "memoize".'
652 return lru_cache(maxsize=None)(user_function)
653
654
655################################################################################
Łukasz Langa6f692512013-06-05 12:20:24 +0200656### singledispatch() - single-dispatch generic function decorator
657################################################################################
658
Łukasz Langa3720c772013-07-01 16:00:38 +0200659def _c3_merge(sequences):
660 """Merges MROs in *sequences* to a single MRO using the C3 algorithm.
661
662 Adapted from http://www.python.org/download/releases/2.3/mro/.
663
664 """
665 result = []
666 while True:
667 sequences = [s for s in sequences if s] # purge empty sequences
668 if not sequences:
669 return result
670 for s1 in sequences: # find merge candidates among seq heads
671 candidate = s1[0]
672 for s2 in sequences:
673 if candidate in s2[1:]:
674 candidate = None
675 break # reject the current head, it appears later
676 else:
677 break
Yury Selivanov77a8cd62015-08-18 14:20:00 -0400678 if candidate is None:
Łukasz Langa3720c772013-07-01 16:00:38 +0200679 raise RuntimeError("Inconsistent hierarchy")
680 result.append(candidate)
681 # remove the chosen candidate
682 for seq in sequences:
683 if seq[0] == candidate:
684 del seq[0]
685
686def _c3_mro(cls, abcs=None):
687 """Computes the method resolution order using extended C3 linearization.
688
689 If no *abcs* are given, the algorithm works exactly like the built-in C3
690 linearization used for method resolution.
691
692 If given, *abcs* is a list of abstract base classes that should be inserted
693 into the resulting MRO. Unrelated ABCs are ignored and don't end up in the
694 result. The algorithm inserts ABCs where their functionality is introduced,
695 i.e. issubclass(cls, abc) returns True for the class itself but returns
696 False for all its direct base classes. Implicit ABCs for a given class
697 (either registered or inferred from the presence of a special method like
698 __len__) are inserted directly after the last ABC explicitly listed in the
699 MRO of said class. If two implicit ABCs end up next to each other in the
700 resulting MRO, their ordering depends on the order of types in *abcs*.
701
702 """
703 for i, base in enumerate(reversed(cls.__bases__)):
704 if hasattr(base, '__abstractmethods__'):
705 boundary = len(cls.__bases__) - i
706 break # Bases up to the last explicit ABC are considered first.
707 else:
708 boundary = 0
709 abcs = list(abcs) if abcs else []
710 explicit_bases = list(cls.__bases__[:boundary])
711 abstract_bases = []
712 other_bases = list(cls.__bases__[boundary:])
713 for base in abcs:
714 if issubclass(cls, base) and not any(
715 issubclass(b, base) for b in cls.__bases__
716 ):
717 # If *cls* is the class that introduces behaviour described by
718 # an ABC *base*, insert said ABC to its MRO.
719 abstract_bases.append(base)
720 for base in abstract_bases:
721 abcs.remove(base)
722 explicit_c3_mros = [_c3_mro(base, abcs=abcs) for base in explicit_bases]
723 abstract_c3_mros = [_c3_mro(base, abcs=abcs) for base in abstract_bases]
724 other_c3_mros = [_c3_mro(base, abcs=abcs) for base in other_bases]
725 return _c3_merge(
726 [[cls]] +
727 explicit_c3_mros + abstract_c3_mros + other_c3_mros +
728 [explicit_bases] + [abstract_bases] + [other_bases]
729 )
730
731def _compose_mro(cls, types):
732 """Calculates the method resolution order for a given class *cls*.
733
734 Includes relevant abstract base classes (with their respective bases) from
735 the *types* iterable. Uses a modified C3 linearization algorithm.
Łukasz Langa6f692512013-06-05 12:20:24 +0200736
737 """
738 bases = set(cls.__mro__)
Łukasz Langa3720c772013-07-01 16:00:38 +0200739 # Remove entries which are already present in the __mro__ or unrelated.
740 def is_related(typ):
741 return (typ not in bases and hasattr(typ, '__mro__')
742 and issubclass(cls, typ))
743 types = [n for n in types if is_related(n)]
744 # Remove entries which are strict bases of other entries (they will end up
745 # in the MRO anyway.
746 def is_strict_base(typ):
747 for other in types:
748 if typ != other and typ in other.__mro__:
749 return True
750 return False
751 types = [n for n in types if not is_strict_base(n)]
752 # Subclasses of the ABCs in *types* which are also implemented by
753 # *cls* can be used to stabilize ABC ordering.
754 type_set = set(types)
755 mro = []
756 for typ in types:
757 found = []
758 for sub in typ.__subclasses__():
759 if sub not in bases and issubclass(cls, sub):
760 found.append([s for s in sub.__mro__ if s in type_set])
761 if not found:
762 mro.append(typ)
763 continue
764 # Favor subclasses with the biggest number of useful bases
765 found.sort(key=len, reverse=True)
766 for sub in found:
767 for subcls in sub:
768 if subcls not in mro:
769 mro.append(subcls)
770 return _c3_mro(cls, abcs=mro)
Łukasz Langa6f692512013-06-05 12:20:24 +0200771
772def _find_impl(cls, registry):
Łukasz Langa3720c772013-07-01 16:00:38 +0200773 """Returns the best matching implementation from *registry* for type *cls*.
Łukasz Langa6f692512013-06-05 12:20:24 +0200774
Łukasz Langa3720c772013-07-01 16:00:38 +0200775 Where there is no registered implementation for a specific type, its method
776 resolution order is used to find a more generic implementation.
777
778 Note: if *registry* does not contain an implementation for the base
779 *object* type, this function may return None.
Łukasz Langa6f692512013-06-05 12:20:24 +0200780
781 """
782 mro = _compose_mro(cls, registry.keys())
783 match = None
784 for t in mro:
785 if match is not None:
Łukasz Langa3720c772013-07-01 16:00:38 +0200786 # If *match* is an implicit ABC but there is another unrelated,
787 # equally matching implicit ABC, refuse the temptation to guess.
788 if (t in registry and t not in cls.__mro__
789 and match not in cls.__mro__
790 and not issubclass(match, t)):
Łukasz Langa6f692512013-06-05 12:20:24 +0200791 raise RuntimeError("Ambiguous dispatch: {} or {}".format(
792 match, t))
793 break
794 if t in registry:
795 match = t
796 return registry.get(match)
797
798def singledispatch(func):
799 """Single-dispatch generic function decorator.
800
801 Transforms a function into a generic function, which can have different
802 behaviours depending upon the type of its first argument. The decorated
803 function acts as the default implementation, and additional
Łukasz Langa3720c772013-07-01 16:00:38 +0200804 implementations can be registered using the register() attribute of the
805 generic function.
Łukasz Langa6f692512013-06-05 12:20:24 +0200806 """
INADA Naoki9811e802017-09-30 16:13:02 +0900807 # There are many programs that use functools without singledispatch, so we
808 # trade-off making singledispatch marginally slower for the benefit of
809 # making start-up of such applications slightly faster.
810 import types, weakref
811
Łukasz Langa6f692512013-06-05 12:20:24 +0200812 registry = {}
INADA Naoki9811e802017-09-30 16:13:02 +0900813 dispatch_cache = weakref.WeakKeyDictionary()
Łukasz Langa6f692512013-06-05 12:20:24 +0200814 cache_token = None
815
Łukasz Langa3720c772013-07-01 16:00:38 +0200816 def dispatch(cls):
817 """generic_func.dispatch(cls) -> <function implementation>
Łukasz Langa6f692512013-06-05 12:20:24 +0200818
819 Runs the dispatch algorithm to return the best available implementation
Łukasz Langa3720c772013-07-01 16:00:38 +0200820 for the given *cls* registered on *generic_func*.
Łukasz Langa6f692512013-06-05 12:20:24 +0200821
822 """
823 nonlocal cache_token
824 if cache_token is not None:
825 current_token = get_cache_token()
826 if cache_token != current_token:
827 dispatch_cache.clear()
828 cache_token = current_token
829 try:
Łukasz Langa3720c772013-07-01 16:00:38 +0200830 impl = dispatch_cache[cls]
Łukasz Langa6f692512013-06-05 12:20:24 +0200831 except KeyError:
832 try:
Łukasz Langa3720c772013-07-01 16:00:38 +0200833 impl = registry[cls]
Łukasz Langa6f692512013-06-05 12:20:24 +0200834 except KeyError:
Łukasz Langa3720c772013-07-01 16:00:38 +0200835 impl = _find_impl(cls, registry)
836 dispatch_cache[cls] = impl
Łukasz Langa6f692512013-06-05 12:20:24 +0200837 return impl
838
Łukasz Langa3720c772013-07-01 16:00:38 +0200839 def register(cls, func=None):
840 """generic_func.register(cls, func) -> func
Łukasz Langa6f692512013-06-05 12:20:24 +0200841
Łukasz Langa3720c772013-07-01 16:00:38 +0200842 Registers a new implementation for the given *cls* on a *generic_func*.
Łukasz Langa6f692512013-06-05 12:20:24 +0200843
844 """
845 nonlocal cache_token
846 if func is None:
Łukasz Langae5697532017-12-11 13:56:31 -0800847 if isinstance(cls, type):
848 return lambda f: register(cls, f)
849 ann = getattr(cls, '__annotations__', {})
850 if not ann:
851 raise TypeError(
852 f"Invalid first argument to `register()`: {cls!r}. "
853 f"Use either `@register(some_class)` or plain `@register` "
854 f"on an annotated function."
855 )
856 func = cls
857
858 # only import typing if annotation parsing is necessary
859 from typing import get_type_hints
860 argname, cls = next(iter(get_type_hints(func).items()))
Lysandros Nikolaoud6738102019-05-20 00:11:21 +0200861 if not isinstance(cls, type):
862 raise TypeError(
863 f"Invalid annotation for {argname!r}. "
864 f"{cls!r} is not a class."
865 )
Łukasz Langa3720c772013-07-01 16:00:38 +0200866 registry[cls] = func
867 if cache_token is None and hasattr(cls, '__abstractmethods__'):
Łukasz Langa6f692512013-06-05 12:20:24 +0200868 cache_token = get_cache_token()
869 dispatch_cache.clear()
870 return func
871
872 def wrapper(*args, **kw):
Dong-hee Na445f1b32018-07-10 16:26:36 +0900873 if not args:
874 raise TypeError(f'{funcname} requires at least '
875 '1 positional argument')
876
Łukasz Langa6f692512013-06-05 12:20:24 +0200877 return dispatch(args[0].__class__)(*args, **kw)
878
Dong-hee Na445f1b32018-07-10 16:26:36 +0900879 funcname = getattr(func, '__name__', 'singledispatch function')
Łukasz Langa6f692512013-06-05 12:20:24 +0200880 registry[object] = func
881 wrapper.register = register
882 wrapper.dispatch = dispatch
INADA Naoki9811e802017-09-30 16:13:02 +0900883 wrapper.registry = types.MappingProxyType(registry)
Łukasz Langa6f692512013-06-05 12:20:24 +0200884 wrapper._clear_cache = dispatch_cache.clear
885 update_wrapper(wrapper, func)
886 return wrapper
Ethan Smithc6512752018-05-26 16:38:33 -0400887
888
889# Descriptor version
890class singledispatchmethod:
891 """Single-dispatch generic method descriptor.
892
893 Supports wrapping existing descriptors and handles non-descriptor
894 callables as instance methods.
895 """
896
897 def __init__(self, func):
898 if not callable(func) and not hasattr(func, "__get__"):
899 raise TypeError(f"{func!r} is not callable or a descriptor")
900
901 self.dispatcher = singledispatch(func)
902 self.func = func
903
904 def register(self, cls, method=None):
905 """generic_method.register(cls, func) -> func
906
907 Registers a new implementation for the given *cls* on a *generic_method*.
908 """
909 return self.dispatcher.register(cls, func=method)
910
Raymond Hettinger0dac68f2019-08-29 01:27:42 -0700911 def __get__(self, obj, cls=None):
Ethan Smithc6512752018-05-26 16:38:33 -0400912 def _method(*args, **kwargs):
913 method = self.dispatcher.dispatch(args[0].__class__)
914 return method.__get__(obj, cls)(*args, **kwargs)
915
916 _method.__isabstractmethod__ = self.__isabstractmethod__
917 _method.register = self.register
918 update_wrapper(_method, self.func)
919 return _method
920
921 @property
922 def __isabstractmethod__(self):
923 return getattr(self.func, '__isabstractmethod__', False)
Carl Meyerd658dea2018-08-28 01:11:56 -0600924
925
926################################################################################
927### cached_property() - computed once per instance, cached as attribute
928################################################################################
929
930_NOT_FOUND = object()
931
932
933class cached_property:
934 def __init__(self, func):
935 self.func = func
936 self.attrname = None
937 self.__doc__ = func.__doc__
938 self.lock = RLock()
939
940 def __set_name__(self, owner, name):
941 if self.attrname is None:
942 self.attrname = name
943 elif name != self.attrname:
944 raise TypeError(
945 "Cannot assign the same cached_property to two different names "
946 f"({self.attrname!r} and {name!r})."
947 )
948
Raymond Hettinger0dac68f2019-08-29 01:27:42 -0700949 def __get__(self, instance, owner=None):
Carl Meyerd658dea2018-08-28 01:11:56 -0600950 if instance is None:
951 return self
952 if self.attrname is None:
953 raise TypeError(
954 "Cannot use cached_property instance without calling __set_name__ on it.")
955 try:
956 cache = instance.__dict__
957 except AttributeError: # not all objects have __dict__ (e.g. class defines slots)
958 msg = (
959 f"No '__dict__' attribute on {type(instance).__name__!r} "
960 f"instance to cache {self.attrname!r} property."
961 )
962 raise TypeError(msg) from None
963 val = cache.get(self.attrname, _NOT_FOUND)
964 if val is _NOT_FOUND:
965 with self.lock:
966 # check if another thread filled cache while we awaited lock
967 val = cache.get(self.attrname, _NOT_FOUND)
968 if val is _NOT_FOUND:
969 val = self.func(instance)
970 try:
971 cache[self.attrname] = val
972 except TypeError:
973 msg = (
974 f"The '__dict__' attribute on {type(instance).__name__!r} instance "
975 f"does not support item assignment for caching {self.attrname!r} property."
976 )
977 raise TypeError(msg) from None
978 return val
Ethan Smithcecf0492020-04-13 21:53:04 -0700979
980 __class_getitem__ = classmethod(GenericAlias)