xref: /aosp_15_r20/prebuilts/build-tools/common/py3-stdlib/functools.py (revision cda5da8d549138a6648c5ee6d7a49cf8f4a657be)
1*cda5da8dSAndroid Build Coastguard Worker"""functools.py - Tools for working with functions and callable objects
2*cda5da8dSAndroid Build Coastguard Worker"""
3*cda5da8dSAndroid Build Coastguard Worker# Python module wrapper for _functools C module
4*cda5da8dSAndroid Build Coastguard Worker# to allow utilities written in Python to be added
5*cda5da8dSAndroid Build Coastguard Worker# to the functools module.
6*cda5da8dSAndroid Build Coastguard Worker# Written by Nick Coghlan <ncoghlan at gmail.com>,
7*cda5da8dSAndroid Build Coastguard Worker# Raymond Hettinger <python at rcn.com>,
8*cda5da8dSAndroid Build Coastguard Worker# and Łukasz Langa <lukasz at langa.pl>.
9*cda5da8dSAndroid Build Coastguard Worker#   Copyright (C) 2006-2013 Python Software Foundation.
10*cda5da8dSAndroid Build Coastguard Worker# See C source code for _functools credits/copyright
11*cda5da8dSAndroid Build Coastguard Worker
12*cda5da8dSAndroid Build Coastguard Worker__all__ = ['update_wrapper', 'wraps', 'WRAPPER_ASSIGNMENTS', 'WRAPPER_UPDATES',
13*cda5da8dSAndroid Build Coastguard Worker           'total_ordering', 'cache', 'cmp_to_key', 'lru_cache', 'reduce',
14*cda5da8dSAndroid Build Coastguard Worker           'partial', 'partialmethod', 'singledispatch', 'singledispatchmethod',
15*cda5da8dSAndroid Build Coastguard Worker           'cached_property']
16*cda5da8dSAndroid Build Coastguard Worker
17*cda5da8dSAndroid Build Coastguard Workerfrom abc import get_cache_token
18*cda5da8dSAndroid Build Coastguard Workerfrom collections import namedtuple
19*cda5da8dSAndroid Build Coastguard Worker# import types, weakref  # Deferred to single_dispatch()
20*cda5da8dSAndroid Build Coastguard Workerfrom reprlib import recursive_repr
21*cda5da8dSAndroid Build Coastguard Workerfrom _thread import RLock
22*cda5da8dSAndroid Build Coastguard Workerfrom types import GenericAlias
23*cda5da8dSAndroid Build Coastguard Worker
24*cda5da8dSAndroid Build Coastguard Worker
25*cda5da8dSAndroid Build Coastguard Worker################################################################################
26*cda5da8dSAndroid Build Coastguard Worker### update_wrapper() and wraps() decorator
27*cda5da8dSAndroid Build Coastguard Worker################################################################################
28*cda5da8dSAndroid Build Coastguard Worker
29*cda5da8dSAndroid Build Coastguard Worker# update_wrapper() and wraps() are tools to help write
30*cda5da8dSAndroid Build Coastguard Worker# wrapper functions that can handle naive introspection
31*cda5da8dSAndroid Build Coastguard Worker
32*cda5da8dSAndroid Build Coastguard WorkerWRAPPER_ASSIGNMENTS = ('__module__', '__name__', '__qualname__', '__doc__',
33*cda5da8dSAndroid Build Coastguard Worker                       '__annotations__')
34*cda5da8dSAndroid Build Coastguard WorkerWRAPPER_UPDATES = ('__dict__',)
35*cda5da8dSAndroid Build Coastguard Workerdef update_wrapper(wrapper,
36*cda5da8dSAndroid Build Coastguard Worker                   wrapped,
37*cda5da8dSAndroid Build Coastguard Worker                   assigned = WRAPPER_ASSIGNMENTS,
38*cda5da8dSAndroid Build Coastguard Worker                   updated = WRAPPER_UPDATES):
39*cda5da8dSAndroid Build Coastguard Worker    """Update a wrapper function to look like the wrapped function
40*cda5da8dSAndroid Build Coastguard Worker
41*cda5da8dSAndroid Build Coastguard Worker       wrapper is the function to be updated
42*cda5da8dSAndroid Build Coastguard Worker       wrapped is the original function
43*cda5da8dSAndroid Build Coastguard Worker       assigned is a tuple naming the attributes assigned directly
44*cda5da8dSAndroid Build Coastguard Worker       from the wrapped function to the wrapper function (defaults to
45*cda5da8dSAndroid Build Coastguard Worker       functools.WRAPPER_ASSIGNMENTS)
46*cda5da8dSAndroid Build Coastguard Worker       updated is a tuple naming the attributes of the wrapper that
47*cda5da8dSAndroid Build Coastguard Worker       are updated with the corresponding attribute from the wrapped
48*cda5da8dSAndroid Build Coastguard Worker       function (defaults to functools.WRAPPER_UPDATES)
49*cda5da8dSAndroid Build Coastguard Worker    """
50*cda5da8dSAndroid Build Coastguard Worker    for attr in assigned:
51*cda5da8dSAndroid Build Coastguard Worker        try:
52*cda5da8dSAndroid Build Coastguard Worker            value = getattr(wrapped, attr)
53*cda5da8dSAndroid Build Coastguard Worker        except AttributeError:
54*cda5da8dSAndroid Build Coastguard Worker            pass
55*cda5da8dSAndroid Build Coastguard Worker        else:
56*cda5da8dSAndroid Build Coastguard Worker            setattr(wrapper, attr, value)
57*cda5da8dSAndroid Build Coastguard Worker    for attr in updated:
58*cda5da8dSAndroid Build Coastguard Worker        getattr(wrapper, attr).update(getattr(wrapped, attr, {}))
59*cda5da8dSAndroid Build Coastguard Worker    # Issue #17482: set __wrapped__ last so we don't inadvertently copy it
60*cda5da8dSAndroid Build Coastguard Worker    # from the wrapped function when updating __dict__
61*cda5da8dSAndroid Build Coastguard Worker    wrapper.__wrapped__ = wrapped
62*cda5da8dSAndroid Build Coastguard Worker    # Return the wrapper so this can be used as a decorator via partial()
63*cda5da8dSAndroid Build Coastguard Worker    return wrapper
64*cda5da8dSAndroid Build Coastguard Worker
65*cda5da8dSAndroid Build Coastguard Workerdef wraps(wrapped,
66*cda5da8dSAndroid Build Coastguard Worker          assigned = WRAPPER_ASSIGNMENTS,
67*cda5da8dSAndroid Build Coastguard Worker          updated = WRAPPER_UPDATES):
68*cda5da8dSAndroid Build Coastguard Worker    """Decorator factory to apply update_wrapper() to a wrapper function
69*cda5da8dSAndroid Build Coastguard Worker
70*cda5da8dSAndroid Build Coastguard Worker       Returns a decorator that invokes update_wrapper() with the decorated
71*cda5da8dSAndroid Build Coastguard Worker       function as the wrapper argument and the arguments to wraps() as the
72*cda5da8dSAndroid Build Coastguard Worker       remaining arguments. Default arguments are as for update_wrapper().
73*cda5da8dSAndroid Build Coastguard Worker       This is a convenience function to simplify applying partial() to
74*cda5da8dSAndroid Build Coastguard Worker       update_wrapper().
75*cda5da8dSAndroid Build Coastguard Worker    """
76*cda5da8dSAndroid Build Coastguard Worker    return partial(update_wrapper, wrapped=wrapped,
77*cda5da8dSAndroid Build Coastguard Worker                   assigned=assigned, updated=updated)
78*cda5da8dSAndroid Build Coastguard Worker
79*cda5da8dSAndroid Build Coastguard Worker
80*cda5da8dSAndroid Build Coastguard Worker################################################################################
81*cda5da8dSAndroid Build Coastguard Worker### total_ordering class decorator
82*cda5da8dSAndroid Build Coastguard Worker################################################################################
83*cda5da8dSAndroid Build Coastguard Worker
84*cda5da8dSAndroid Build Coastguard Worker# The total ordering functions all invoke the root magic method directly
85*cda5da8dSAndroid Build Coastguard Worker# rather than using the corresponding operator.  This avoids possible
86*cda5da8dSAndroid Build Coastguard Worker# infinite recursion that could occur when the operator dispatch logic
87*cda5da8dSAndroid Build Coastguard Worker# detects a NotImplemented result and then calls a reflected method.
88*cda5da8dSAndroid Build Coastguard Worker
89*cda5da8dSAndroid Build Coastguard Workerdef _gt_from_lt(self, other):
90*cda5da8dSAndroid Build Coastguard Worker    'Return a > b.  Computed by @total_ordering from (not a < b) and (a != b).'
91*cda5da8dSAndroid Build Coastguard Worker    op_result = type(self).__lt__(self, other)
92*cda5da8dSAndroid Build Coastguard Worker    if op_result is NotImplemented:
93*cda5da8dSAndroid Build Coastguard Worker        return op_result
94*cda5da8dSAndroid Build Coastguard Worker    return not op_result and self != other
95*cda5da8dSAndroid Build Coastguard Worker
96*cda5da8dSAndroid Build Coastguard Workerdef _le_from_lt(self, other):
97*cda5da8dSAndroid Build Coastguard Worker    'Return a <= b.  Computed by @total_ordering from (a < b) or (a == b).'
98*cda5da8dSAndroid Build Coastguard Worker    op_result = type(self).__lt__(self, other)
99*cda5da8dSAndroid Build Coastguard Worker    if op_result is NotImplemented:
100*cda5da8dSAndroid Build Coastguard Worker        return op_result
101*cda5da8dSAndroid Build Coastguard Worker    return op_result or self == other
102*cda5da8dSAndroid Build Coastguard Worker
103*cda5da8dSAndroid Build Coastguard Workerdef _ge_from_lt(self, other):
104*cda5da8dSAndroid Build Coastguard Worker    'Return a >= b.  Computed by @total_ordering from (not a < b).'
105*cda5da8dSAndroid Build Coastguard Worker    op_result = type(self).__lt__(self, other)
106*cda5da8dSAndroid Build Coastguard Worker    if op_result is NotImplemented:
107*cda5da8dSAndroid Build Coastguard Worker        return op_result
108*cda5da8dSAndroid Build Coastguard Worker    return not op_result
109*cda5da8dSAndroid Build Coastguard Worker
110*cda5da8dSAndroid Build Coastguard Workerdef _ge_from_le(self, other):
111*cda5da8dSAndroid Build Coastguard Worker    'Return a >= b.  Computed by @total_ordering from (not a <= b) or (a == b).'
112*cda5da8dSAndroid Build Coastguard Worker    op_result = type(self).__le__(self, other)
113*cda5da8dSAndroid Build Coastguard Worker    if op_result is NotImplemented:
114*cda5da8dSAndroid Build Coastguard Worker        return op_result
115*cda5da8dSAndroid Build Coastguard Worker    return not op_result or self == other
116*cda5da8dSAndroid Build Coastguard Worker
117*cda5da8dSAndroid Build Coastguard Workerdef _lt_from_le(self, other):
118*cda5da8dSAndroid Build Coastguard Worker    'Return a < b.  Computed by @total_ordering from (a <= b) and (a != b).'
119*cda5da8dSAndroid Build Coastguard Worker    op_result = type(self).__le__(self, other)
120*cda5da8dSAndroid Build Coastguard Worker    if op_result is NotImplemented:
121*cda5da8dSAndroid Build Coastguard Worker        return op_result
122*cda5da8dSAndroid Build Coastguard Worker    return op_result and self != other
123*cda5da8dSAndroid Build Coastguard Worker
124*cda5da8dSAndroid Build Coastguard Workerdef _gt_from_le(self, other):
125*cda5da8dSAndroid Build Coastguard Worker    'Return a > b.  Computed by @total_ordering from (not a <= b).'
126*cda5da8dSAndroid Build Coastguard Worker    op_result = type(self).__le__(self, other)
127*cda5da8dSAndroid Build Coastguard Worker    if op_result is NotImplemented:
128*cda5da8dSAndroid Build Coastguard Worker        return op_result
129*cda5da8dSAndroid Build Coastguard Worker    return not op_result
130*cda5da8dSAndroid Build Coastguard Worker
131*cda5da8dSAndroid Build Coastguard Workerdef _lt_from_gt(self, other):
132*cda5da8dSAndroid Build Coastguard Worker    'Return a < b.  Computed by @total_ordering from (not a > b) and (a != b).'
133*cda5da8dSAndroid Build Coastguard Worker    op_result = type(self).__gt__(self, other)
134*cda5da8dSAndroid Build Coastguard Worker    if op_result is NotImplemented:
135*cda5da8dSAndroid Build Coastguard Worker        return op_result
136*cda5da8dSAndroid Build Coastguard Worker    return not op_result and self != other
137*cda5da8dSAndroid Build Coastguard Worker
138*cda5da8dSAndroid Build Coastguard Workerdef _ge_from_gt(self, other):
139*cda5da8dSAndroid Build Coastguard Worker    'Return a >= b.  Computed by @total_ordering from (a > b) or (a == b).'
140*cda5da8dSAndroid Build Coastguard Worker    op_result = type(self).__gt__(self, other)
141*cda5da8dSAndroid Build Coastguard Worker    if op_result is NotImplemented:
142*cda5da8dSAndroid Build Coastguard Worker        return op_result
143*cda5da8dSAndroid Build Coastguard Worker    return op_result or self == other
144*cda5da8dSAndroid Build Coastguard Worker
145*cda5da8dSAndroid Build Coastguard Workerdef _le_from_gt(self, other):
146*cda5da8dSAndroid Build Coastguard Worker    'Return a <= b.  Computed by @total_ordering from (not a > b).'
147*cda5da8dSAndroid Build Coastguard Worker    op_result = type(self).__gt__(self, other)
148*cda5da8dSAndroid Build Coastguard Worker    if op_result is NotImplemented:
149*cda5da8dSAndroid Build Coastguard Worker        return op_result
150*cda5da8dSAndroid Build Coastguard Worker    return not op_result
151*cda5da8dSAndroid Build Coastguard Worker
152*cda5da8dSAndroid Build Coastguard Workerdef _le_from_ge(self, other):
153*cda5da8dSAndroid Build Coastguard Worker    'Return a <= b.  Computed by @total_ordering from (not a >= b) or (a == b).'
154*cda5da8dSAndroid Build Coastguard Worker    op_result = type(self).__ge__(self, other)
155*cda5da8dSAndroid Build Coastguard Worker    if op_result is NotImplemented:
156*cda5da8dSAndroid Build Coastguard Worker        return op_result
157*cda5da8dSAndroid Build Coastguard Worker    return not op_result or self == other
158*cda5da8dSAndroid Build Coastguard Worker
159*cda5da8dSAndroid Build Coastguard Workerdef _gt_from_ge(self, other):
160*cda5da8dSAndroid Build Coastguard Worker    'Return a > b.  Computed by @total_ordering from (a >= b) and (a != b).'
161*cda5da8dSAndroid Build Coastguard Worker    op_result = type(self).__ge__(self, other)
162*cda5da8dSAndroid Build Coastguard Worker    if op_result is NotImplemented:
163*cda5da8dSAndroid Build Coastguard Worker        return op_result
164*cda5da8dSAndroid Build Coastguard Worker    return op_result and self != other
165*cda5da8dSAndroid Build Coastguard Worker
166*cda5da8dSAndroid Build Coastguard Workerdef _lt_from_ge(self, other):
167*cda5da8dSAndroid Build Coastguard Worker    'Return a < b.  Computed by @total_ordering from (not a >= b).'
168*cda5da8dSAndroid Build Coastguard Worker    op_result = type(self).__ge__(self, other)
169*cda5da8dSAndroid Build Coastguard Worker    if op_result is NotImplemented:
170*cda5da8dSAndroid Build Coastguard Worker        return op_result
171*cda5da8dSAndroid Build Coastguard Worker    return not op_result
172*cda5da8dSAndroid Build Coastguard Worker
173*cda5da8dSAndroid Build Coastguard Worker_convert = {
174*cda5da8dSAndroid Build Coastguard Worker    '__lt__': [('__gt__', _gt_from_lt),
175*cda5da8dSAndroid Build Coastguard Worker               ('__le__', _le_from_lt),
176*cda5da8dSAndroid Build Coastguard Worker               ('__ge__', _ge_from_lt)],
177*cda5da8dSAndroid Build Coastguard Worker    '__le__': [('__ge__', _ge_from_le),
178*cda5da8dSAndroid Build Coastguard Worker               ('__lt__', _lt_from_le),
179*cda5da8dSAndroid Build Coastguard Worker               ('__gt__', _gt_from_le)],
180*cda5da8dSAndroid Build Coastguard Worker    '__gt__': [('__lt__', _lt_from_gt),
181*cda5da8dSAndroid Build Coastguard Worker               ('__ge__', _ge_from_gt),
182*cda5da8dSAndroid Build Coastguard Worker               ('__le__', _le_from_gt)],
183*cda5da8dSAndroid Build Coastguard Worker    '__ge__': [('__le__', _le_from_ge),
184*cda5da8dSAndroid Build Coastguard Worker               ('__gt__', _gt_from_ge),
185*cda5da8dSAndroid Build Coastguard Worker               ('__lt__', _lt_from_ge)]
186*cda5da8dSAndroid Build Coastguard Worker}
187*cda5da8dSAndroid Build Coastguard Worker
188*cda5da8dSAndroid Build Coastguard Workerdef total_ordering(cls):
189*cda5da8dSAndroid Build Coastguard Worker    """Class decorator that fills in missing ordering methods"""
190*cda5da8dSAndroid Build Coastguard Worker    # Find user-defined comparisons (not those inherited from object).
191*cda5da8dSAndroid Build Coastguard Worker    roots = {op for op in _convert if getattr(cls, op, None) is not getattr(object, op, None)}
192*cda5da8dSAndroid Build Coastguard Worker    if not roots:
193*cda5da8dSAndroid Build Coastguard Worker        raise ValueError('must define at least one ordering operation: < > <= >=')
194*cda5da8dSAndroid Build Coastguard Worker    root = max(roots)       # prefer __lt__ to __le__ to __gt__ to __ge__
195*cda5da8dSAndroid Build Coastguard Worker    for opname, opfunc in _convert[root]:
196*cda5da8dSAndroid Build Coastguard Worker        if opname not in roots:
197*cda5da8dSAndroid Build Coastguard Worker            opfunc.__name__ = opname
198*cda5da8dSAndroid Build Coastguard Worker            setattr(cls, opname, opfunc)
199*cda5da8dSAndroid Build Coastguard Worker    return cls
200*cda5da8dSAndroid Build Coastguard Worker
201*cda5da8dSAndroid Build Coastguard Worker
202*cda5da8dSAndroid Build Coastguard Worker################################################################################
203*cda5da8dSAndroid Build Coastguard Worker### cmp_to_key() function converter
204*cda5da8dSAndroid Build Coastguard Worker################################################################################
205*cda5da8dSAndroid Build Coastguard Worker
206*cda5da8dSAndroid Build Coastguard Workerdef cmp_to_key(mycmp):
207*cda5da8dSAndroid Build Coastguard Worker    """Convert a cmp= function into a key= function"""
208*cda5da8dSAndroid Build Coastguard Worker    class K(object):
209*cda5da8dSAndroid Build Coastguard Worker        __slots__ = ['obj']
210*cda5da8dSAndroid Build Coastguard Worker        def __init__(self, obj):
211*cda5da8dSAndroid Build Coastguard Worker            self.obj = obj
212*cda5da8dSAndroid Build Coastguard Worker        def __lt__(self, other):
213*cda5da8dSAndroid Build Coastguard Worker            return mycmp(self.obj, other.obj) < 0
214*cda5da8dSAndroid Build Coastguard Worker        def __gt__(self, other):
215*cda5da8dSAndroid Build Coastguard Worker            return mycmp(self.obj, other.obj) > 0
216*cda5da8dSAndroid Build Coastguard Worker        def __eq__(self, other):
217*cda5da8dSAndroid Build Coastguard Worker            return mycmp(self.obj, other.obj) == 0
218*cda5da8dSAndroid Build Coastguard Worker        def __le__(self, other):
219*cda5da8dSAndroid Build Coastguard Worker            return mycmp(self.obj, other.obj) <= 0
220*cda5da8dSAndroid Build Coastguard Worker        def __ge__(self, other):
221*cda5da8dSAndroid Build Coastguard Worker            return mycmp(self.obj, other.obj) >= 0
222*cda5da8dSAndroid Build Coastguard Worker        __hash__ = None
223*cda5da8dSAndroid Build Coastguard Worker    return K
224*cda5da8dSAndroid Build Coastguard Worker
225*cda5da8dSAndroid Build Coastguard Workertry:
226*cda5da8dSAndroid Build Coastguard Worker    from _functools import cmp_to_key
227*cda5da8dSAndroid Build Coastguard Workerexcept ImportError:
228*cda5da8dSAndroid Build Coastguard Worker    pass
229*cda5da8dSAndroid Build Coastguard Worker
230*cda5da8dSAndroid Build Coastguard Worker
231*cda5da8dSAndroid Build Coastguard Worker################################################################################
232*cda5da8dSAndroid Build Coastguard Worker### reduce() sequence to a single item
233*cda5da8dSAndroid Build Coastguard Worker################################################################################
234*cda5da8dSAndroid Build Coastguard Worker
235*cda5da8dSAndroid Build Coastguard Worker_initial_missing = object()
236*cda5da8dSAndroid Build Coastguard Worker
237*cda5da8dSAndroid Build Coastguard Workerdef reduce(function, sequence, initial=_initial_missing):
238*cda5da8dSAndroid Build Coastguard Worker    """
239*cda5da8dSAndroid Build Coastguard Worker    reduce(function, iterable[, initial]) -> value
240*cda5da8dSAndroid Build Coastguard Worker
241*cda5da8dSAndroid Build Coastguard Worker    Apply a function of two arguments cumulatively to the items of a sequence
242*cda5da8dSAndroid Build Coastguard Worker    or iterable, from left to right, so as to reduce the iterable to a single
243*cda5da8dSAndroid Build Coastguard Worker    value.  For example, reduce(lambda x, y: x+y, [1, 2, 3, 4, 5]) calculates
244*cda5da8dSAndroid Build Coastguard Worker    ((((1+2)+3)+4)+5).  If initial is present, it is placed before the items
245*cda5da8dSAndroid Build Coastguard Worker    of the iterable in the calculation, and serves as a default when the
246*cda5da8dSAndroid Build Coastguard Worker    iterable is empty.
247*cda5da8dSAndroid Build Coastguard Worker    """
248*cda5da8dSAndroid Build Coastguard Worker
249*cda5da8dSAndroid Build Coastguard Worker    it = iter(sequence)
250*cda5da8dSAndroid Build Coastguard Worker
251*cda5da8dSAndroid Build Coastguard Worker    if initial is _initial_missing:
252*cda5da8dSAndroid Build Coastguard Worker        try:
253*cda5da8dSAndroid Build Coastguard Worker            value = next(it)
254*cda5da8dSAndroid Build Coastguard Worker        except StopIteration:
255*cda5da8dSAndroid Build Coastguard Worker            raise TypeError(
256*cda5da8dSAndroid Build Coastguard Worker                "reduce() of empty iterable with no initial value") from None
257*cda5da8dSAndroid Build Coastguard Worker    else:
258*cda5da8dSAndroid Build Coastguard Worker        value = initial
259*cda5da8dSAndroid Build Coastguard Worker
260*cda5da8dSAndroid Build Coastguard Worker    for element in it:
261*cda5da8dSAndroid Build Coastguard Worker        value = function(value, element)
262*cda5da8dSAndroid Build Coastguard Worker
263*cda5da8dSAndroid Build Coastguard Worker    return value
264*cda5da8dSAndroid Build Coastguard Worker
265*cda5da8dSAndroid Build Coastguard Workertry:
266*cda5da8dSAndroid Build Coastguard Worker    from _functools import reduce
267*cda5da8dSAndroid Build Coastguard Workerexcept ImportError:
268*cda5da8dSAndroid Build Coastguard Worker    pass
269*cda5da8dSAndroid Build Coastguard Worker
270*cda5da8dSAndroid Build Coastguard Worker
271*cda5da8dSAndroid Build Coastguard Worker################################################################################
272*cda5da8dSAndroid Build Coastguard Worker### partial() argument application
273*cda5da8dSAndroid Build Coastguard Worker################################################################################
274*cda5da8dSAndroid Build Coastguard Worker
275*cda5da8dSAndroid Build Coastguard Worker# Purely functional, no descriptor behaviour
276*cda5da8dSAndroid Build Coastguard Workerclass partial:
277*cda5da8dSAndroid Build Coastguard Worker    """New function with partial application of the given arguments
278*cda5da8dSAndroid Build Coastguard Worker    and keywords.
279*cda5da8dSAndroid Build Coastguard Worker    """
280*cda5da8dSAndroid Build Coastguard Worker
281*cda5da8dSAndroid Build Coastguard Worker    __slots__ = "func", "args", "keywords", "__dict__", "__weakref__"
282*cda5da8dSAndroid Build Coastguard Worker
283*cda5da8dSAndroid Build Coastguard Worker    def __new__(cls, func, /, *args, **keywords):
284*cda5da8dSAndroid Build Coastguard Worker        if not callable(func):
285*cda5da8dSAndroid Build Coastguard Worker            raise TypeError("the first argument must be callable")
286*cda5da8dSAndroid Build Coastguard Worker
287*cda5da8dSAndroid Build Coastguard Worker        if hasattr(func, "func"):
288*cda5da8dSAndroid Build Coastguard Worker            args = func.args + args
289*cda5da8dSAndroid Build Coastguard Worker            keywords = {**func.keywords, **keywords}
290*cda5da8dSAndroid Build Coastguard Worker            func = func.func
291*cda5da8dSAndroid Build Coastguard Worker
292*cda5da8dSAndroid Build Coastguard Worker        self = super(partial, cls).__new__(cls)
293*cda5da8dSAndroid Build Coastguard Worker
294*cda5da8dSAndroid Build Coastguard Worker        self.func = func
295*cda5da8dSAndroid Build Coastguard Worker        self.args = args
296*cda5da8dSAndroid Build Coastguard Worker        self.keywords = keywords
297*cda5da8dSAndroid Build Coastguard Worker        return self
298*cda5da8dSAndroid Build Coastguard Worker
299*cda5da8dSAndroid Build Coastguard Worker    def __call__(self, /, *args, **keywords):
300*cda5da8dSAndroid Build Coastguard Worker        keywords = {**self.keywords, **keywords}
301*cda5da8dSAndroid Build Coastguard Worker        return self.func(*self.args, *args, **keywords)
302*cda5da8dSAndroid Build Coastguard Worker
303*cda5da8dSAndroid Build Coastguard Worker    @recursive_repr()
304*cda5da8dSAndroid Build Coastguard Worker    def __repr__(self):
305*cda5da8dSAndroid Build Coastguard Worker        qualname = type(self).__qualname__
306*cda5da8dSAndroid Build Coastguard Worker        args = [repr(self.func)]
307*cda5da8dSAndroid Build Coastguard Worker        args.extend(repr(x) for x in self.args)
308*cda5da8dSAndroid Build Coastguard Worker        args.extend(f"{k}={v!r}" for (k, v) in self.keywords.items())
309*cda5da8dSAndroid Build Coastguard Worker        if type(self).__module__ == "functools":
310*cda5da8dSAndroid Build Coastguard Worker            return f"functools.{qualname}({', '.join(args)})"
311*cda5da8dSAndroid Build Coastguard Worker        return f"{qualname}({', '.join(args)})"
312*cda5da8dSAndroid Build Coastguard Worker
313*cda5da8dSAndroid Build Coastguard Worker    def __reduce__(self):
314*cda5da8dSAndroid Build Coastguard Worker        return type(self), (self.func,), (self.func, self.args,
315*cda5da8dSAndroid Build Coastguard Worker               self.keywords or None, self.__dict__ or None)
316*cda5da8dSAndroid Build Coastguard Worker
317*cda5da8dSAndroid Build Coastguard Worker    def __setstate__(self, state):
318*cda5da8dSAndroid Build Coastguard Worker        if not isinstance(state, tuple):
319*cda5da8dSAndroid Build Coastguard Worker            raise TypeError("argument to __setstate__ must be a tuple")
320*cda5da8dSAndroid Build Coastguard Worker        if len(state) != 4:
321*cda5da8dSAndroid Build Coastguard Worker            raise TypeError(f"expected 4 items in state, got {len(state)}")
322*cda5da8dSAndroid Build Coastguard Worker        func, args, kwds, namespace = state
323*cda5da8dSAndroid Build Coastguard Worker        if (not callable(func) or not isinstance(args, tuple) or
324*cda5da8dSAndroid Build Coastguard Worker           (kwds is not None and not isinstance(kwds, dict)) or
325*cda5da8dSAndroid Build Coastguard Worker           (namespace is not None and not isinstance(namespace, dict))):
326*cda5da8dSAndroid Build Coastguard Worker            raise TypeError("invalid partial state")
327*cda5da8dSAndroid Build Coastguard Worker
328*cda5da8dSAndroid Build Coastguard Worker        args = tuple(args) # just in case it's a subclass
329*cda5da8dSAndroid Build Coastguard Worker        if kwds is None:
330*cda5da8dSAndroid Build Coastguard Worker            kwds = {}
331*cda5da8dSAndroid Build Coastguard Worker        elif type(kwds) is not dict: # XXX does it need to be *exactly* dict?
332*cda5da8dSAndroid Build Coastguard Worker            kwds = dict(kwds)
333*cda5da8dSAndroid Build Coastguard Worker        if namespace is None:
334*cda5da8dSAndroid Build Coastguard Worker            namespace = {}
335*cda5da8dSAndroid Build Coastguard Worker
336*cda5da8dSAndroid Build Coastguard Worker        self.__dict__ = namespace
337*cda5da8dSAndroid Build Coastguard Worker        self.func = func
338*cda5da8dSAndroid Build Coastguard Worker        self.args = args
339*cda5da8dSAndroid Build Coastguard Worker        self.keywords = kwds
340*cda5da8dSAndroid Build Coastguard Worker
341*cda5da8dSAndroid Build Coastguard Workertry:
342*cda5da8dSAndroid Build Coastguard Worker    from _functools import partial
343*cda5da8dSAndroid Build Coastguard Workerexcept ImportError:
344*cda5da8dSAndroid Build Coastguard Worker    pass
345*cda5da8dSAndroid Build Coastguard Worker
346*cda5da8dSAndroid Build Coastguard Worker# Descriptor version
347*cda5da8dSAndroid Build Coastguard Workerclass partialmethod(object):
348*cda5da8dSAndroid Build Coastguard Worker    """Method descriptor with partial application of the given arguments
349*cda5da8dSAndroid Build Coastguard Worker    and keywords.
350*cda5da8dSAndroid Build Coastguard Worker
351*cda5da8dSAndroid Build Coastguard Worker    Supports wrapping existing descriptors and handles non-descriptor
352*cda5da8dSAndroid Build Coastguard Worker    callables as instance methods.
353*cda5da8dSAndroid Build Coastguard Worker    """
354*cda5da8dSAndroid Build Coastguard Worker
355*cda5da8dSAndroid Build Coastguard Worker    def __init__(self, func, /, *args, **keywords):
356*cda5da8dSAndroid Build Coastguard Worker        if not callable(func) and not hasattr(func, "__get__"):
357*cda5da8dSAndroid Build Coastguard Worker            raise TypeError("{!r} is not callable or a descriptor"
358*cda5da8dSAndroid Build Coastguard Worker                                 .format(func))
359*cda5da8dSAndroid Build Coastguard Worker
360*cda5da8dSAndroid Build Coastguard Worker        # func could be a descriptor like classmethod which isn't callable,
361*cda5da8dSAndroid Build Coastguard Worker        # so we can't inherit from partial (it verifies func is callable)
362*cda5da8dSAndroid Build Coastguard Worker        if isinstance(func, partialmethod):
363*cda5da8dSAndroid Build Coastguard Worker            # flattening is mandatory in order to place cls/self before all
364*cda5da8dSAndroid Build Coastguard Worker            # other arguments
365*cda5da8dSAndroid Build Coastguard Worker            # it's also more efficient since only one function will be called
366*cda5da8dSAndroid Build Coastguard Worker            self.func = func.func
367*cda5da8dSAndroid Build Coastguard Worker            self.args = func.args + args
368*cda5da8dSAndroid Build Coastguard Worker            self.keywords = {**func.keywords, **keywords}
369*cda5da8dSAndroid Build Coastguard Worker        else:
370*cda5da8dSAndroid Build Coastguard Worker            self.func = func
371*cda5da8dSAndroid Build Coastguard Worker            self.args = args
372*cda5da8dSAndroid Build Coastguard Worker            self.keywords = keywords
373*cda5da8dSAndroid Build Coastguard Worker
374*cda5da8dSAndroid Build Coastguard Worker    def __repr__(self):
375*cda5da8dSAndroid Build Coastguard Worker        args = ", ".join(map(repr, self.args))
376*cda5da8dSAndroid Build Coastguard Worker        keywords = ", ".join("{}={!r}".format(k, v)
377*cda5da8dSAndroid Build Coastguard Worker                                 for k, v in self.keywords.items())
378*cda5da8dSAndroid Build Coastguard Worker        format_string = "{module}.{cls}({func}, {args}, {keywords})"
379*cda5da8dSAndroid Build Coastguard Worker        return format_string.format(module=self.__class__.__module__,
380*cda5da8dSAndroid Build Coastguard Worker                                    cls=self.__class__.__qualname__,
381*cda5da8dSAndroid Build Coastguard Worker                                    func=self.func,
382*cda5da8dSAndroid Build Coastguard Worker                                    args=args,
383*cda5da8dSAndroid Build Coastguard Worker                                    keywords=keywords)
384*cda5da8dSAndroid Build Coastguard Worker
385*cda5da8dSAndroid Build Coastguard Worker    def _make_unbound_method(self):
386*cda5da8dSAndroid Build Coastguard Worker        def _method(cls_or_self, /, *args, **keywords):
387*cda5da8dSAndroid Build Coastguard Worker            keywords = {**self.keywords, **keywords}
388*cda5da8dSAndroid Build Coastguard Worker            return self.func(cls_or_self, *self.args, *args, **keywords)
389*cda5da8dSAndroid Build Coastguard Worker        _method.__isabstractmethod__ = self.__isabstractmethod__
390*cda5da8dSAndroid Build Coastguard Worker        _method._partialmethod = self
391*cda5da8dSAndroid Build Coastguard Worker        return _method
392*cda5da8dSAndroid Build Coastguard Worker
393*cda5da8dSAndroid Build Coastguard Worker    def __get__(self, obj, cls=None):
394*cda5da8dSAndroid Build Coastguard Worker        get = getattr(self.func, "__get__", None)
395*cda5da8dSAndroid Build Coastguard Worker        result = None
396*cda5da8dSAndroid Build Coastguard Worker        if get is not None:
397*cda5da8dSAndroid Build Coastguard Worker            new_func = get(obj, cls)
398*cda5da8dSAndroid Build Coastguard Worker            if new_func is not self.func:
399*cda5da8dSAndroid Build Coastguard Worker                # Assume __get__ returning something new indicates the
400*cda5da8dSAndroid Build Coastguard Worker                # creation of an appropriate callable
401*cda5da8dSAndroid Build Coastguard Worker                result = partial(new_func, *self.args, **self.keywords)
402*cda5da8dSAndroid Build Coastguard Worker                try:
403*cda5da8dSAndroid Build Coastguard Worker                    result.__self__ = new_func.__self__
404*cda5da8dSAndroid Build Coastguard Worker                except AttributeError:
405*cda5da8dSAndroid Build Coastguard Worker                    pass
406*cda5da8dSAndroid Build Coastguard Worker        if result is None:
407*cda5da8dSAndroid Build Coastguard Worker            # If the underlying descriptor didn't do anything, treat this
408*cda5da8dSAndroid Build Coastguard Worker            # like an instance method
409*cda5da8dSAndroid Build Coastguard Worker            result = self._make_unbound_method().__get__(obj, cls)
410*cda5da8dSAndroid Build Coastguard Worker        return result
411*cda5da8dSAndroid Build Coastguard Worker
412*cda5da8dSAndroid Build Coastguard Worker    @property
413*cda5da8dSAndroid Build Coastguard Worker    def __isabstractmethod__(self):
414*cda5da8dSAndroid Build Coastguard Worker        return getattr(self.func, "__isabstractmethod__", False)
415*cda5da8dSAndroid Build Coastguard Worker
416*cda5da8dSAndroid Build Coastguard Worker    __class_getitem__ = classmethod(GenericAlias)
417*cda5da8dSAndroid Build Coastguard Worker
418*cda5da8dSAndroid Build Coastguard Worker
419*cda5da8dSAndroid Build Coastguard Worker# Helper functions
420*cda5da8dSAndroid Build Coastguard Worker
421*cda5da8dSAndroid Build Coastguard Workerdef _unwrap_partial(func):
422*cda5da8dSAndroid Build Coastguard Worker    while isinstance(func, partial):
423*cda5da8dSAndroid Build Coastguard Worker        func = func.func
424*cda5da8dSAndroid Build Coastguard Worker    return func
425*cda5da8dSAndroid Build Coastguard Worker
426*cda5da8dSAndroid Build Coastguard Worker################################################################################
427*cda5da8dSAndroid Build Coastguard Worker### LRU Cache function decorator
428*cda5da8dSAndroid Build Coastguard Worker################################################################################
429*cda5da8dSAndroid Build Coastguard Worker
430*cda5da8dSAndroid Build Coastguard Worker_CacheInfo = namedtuple("CacheInfo", ["hits", "misses", "maxsize", "currsize"])
431*cda5da8dSAndroid Build Coastguard Worker
432*cda5da8dSAndroid Build Coastguard Workerclass _HashedSeq(list):
433*cda5da8dSAndroid Build Coastguard Worker    """ This class guarantees that hash() will be called no more than once
434*cda5da8dSAndroid Build Coastguard Worker        per element.  This is important because the lru_cache() will hash
435*cda5da8dSAndroid Build Coastguard Worker        the key multiple times on a cache miss.
436*cda5da8dSAndroid Build Coastguard Worker
437*cda5da8dSAndroid Build Coastguard Worker    """
438*cda5da8dSAndroid Build Coastguard Worker
439*cda5da8dSAndroid Build Coastguard Worker    __slots__ = 'hashvalue'
440*cda5da8dSAndroid Build Coastguard Worker
441*cda5da8dSAndroid Build Coastguard Worker    def __init__(self, tup, hash=hash):
442*cda5da8dSAndroid Build Coastguard Worker        self[:] = tup
443*cda5da8dSAndroid Build Coastguard Worker        self.hashvalue = hash(tup)
444*cda5da8dSAndroid Build Coastguard Worker
445*cda5da8dSAndroid Build Coastguard Worker    def __hash__(self):
446*cda5da8dSAndroid Build Coastguard Worker        return self.hashvalue
447*cda5da8dSAndroid Build Coastguard Worker
448*cda5da8dSAndroid Build Coastguard Workerdef _make_key(args, kwds, typed,
449*cda5da8dSAndroid Build Coastguard Worker             kwd_mark = (object(),),
450*cda5da8dSAndroid Build Coastguard Worker             fasttypes = {int, str},
451*cda5da8dSAndroid Build Coastguard Worker             tuple=tuple, type=type, len=len):
452*cda5da8dSAndroid Build Coastguard Worker    """Make a cache key from optionally typed positional and keyword arguments
453*cda5da8dSAndroid Build Coastguard Worker
454*cda5da8dSAndroid Build Coastguard Worker    The key is constructed in a way that is flat as possible rather than
455*cda5da8dSAndroid Build Coastguard Worker    as a nested structure that would take more memory.
456*cda5da8dSAndroid Build Coastguard Worker
457*cda5da8dSAndroid Build Coastguard Worker    If there is only a single argument and its data type is known to cache
458*cda5da8dSAndroid Build Coastguard Worker    its hash value, then that argument is returned without a wrapper.  This
459*cda5da8dSAndroid Build Coastguard Worker    saves space and improves lookup speed.
460*cda5da8dSAndroid Build Coastguard Worker
461*cda5da8dSAndroid Build Coastguard Worker    """
462*cda5da8dSAndroid Build Coastguard Worker    # All of code below relies on kwds preserving the order input by the user.
463*cda5da8dSAndroid Build Coastguard Worker    # Formerly, we sorted() the kwds before looping.  The new way is *much*
464*cda5da8dSAndroid Build Coastguard Worker    # faster; however, it means that f(x=1, y=2) will now be treated as a
465*cda5da8dSAndroid Build Coastguard Worker    # distinct call from f(y=2, x=1) which will be cached separately.
466*cda5da8dSAndroid Build Coastguard Worker    key = args
467*cda5da8dSAndroid Build Coastguard Worker    if kwds:
468*cda5da8dSAndroid Build Coastguard Worker        key += kwd_mark
469*cda5da8dSAndroid Build Coastguard Worker        for item in kwds.items():
470*cda5da8dSAndroid Build Coastguard Worker            key += item
471*cda5da8dSAndroid Build Coastguard Worker    if typed:
472*cda5da8dSAndroid Build Coastguard Worker        key += tuple(type(v) for v in args)
473*cda5da8dSAndroid Build Coastguard Worker        if kwds:
474*cda5da8dSAndroid Build Coastguard Worker            key += tuple(type(v) for v in kwds.values())
475*cda5da8dSAndroid Build Coastguard Worker    elif len(key) == 1 and type(key[0]) in fasttypes:
476*cda5da8dSAndroid Build Coastguard Worker        return key[0]
477*cda5da8dSAndroid Build Coastguard Worker    return _HashedSeq(key)
478*cda5da8dSAndroid Build Coastguard Worker
479*cda5da8dSAndroid Build Coastguard Workerdef lru_cache(maxsize=128, typed=False):
480*cda5da8dSAndroid Build Coastguard Worker    """Least-recently-used cache decorator.
481*cda5da8dSAndroid Build Coastguard Worker
482*cda5da8dSAndroid Build Coastguard Worker    If *maxsize* is set to None, the LRU features are disabled and the cache
483*cda5da8dSAndroid Build Coastguard Worker    can grow without bound.
484*cda5da8dSAndroid Build Coastguard Worker
485*cda5da8dSAndroid Build Coastguard Worker    If *typed* is True, arguments of different types will be cached separately.
486*cda5da8dSAndroid Build Coastguard Worker    For example, f(3.0) and f(3) will be treated as distinct calls with
487*cda5da8dSAndroid Build Coastguard Worker    distinct results.
488*cda5da8dSAndroid Build Coastguard Worker
489*cda5da8dSAndroid Build Coastguard Worker    Arguments to the cached function must be hashable.
490*cda5da8dSAndroid Build Coastguard Worker
491*cda5da8dSAndroid Build Coastguard Worker    View the cache statistics named tuple (hits, misses, maxsize, currsize)
492*cda5da8dSAndroid Build Coastguard Worker    with f.cache_info().  Clear the cache and statistics with f.cache_clear().
493*cda5da8dSAndroid Build Coastguard Worker    Access the underlying function with f.__wrapped__.
494*cda5da8dSAndroid Build Coastguard Worker
495*cda5da8dSAndroid Build Coastguard Worker    See:  https://en.wikipedia.org/wiki/Cache_replacement_policies#Least_recently_used_(LRU)
496*cda5da8dSAndroid Build Coastguard Worker
497*cda5da8dSAndroid Build Coastguard Worker    """
498*cda5da8dSAndroid Build Coastguard Worker
499*cda5da8dSAndroid Build Coastguard Worker    # Users should only access the lru_cache through its public API:
500*cda5da8dSAndroid Build Coastguard Worker    #       cache_info, cache_clear, and f.__wrapped__
501*cda5da8dSAndroid Build Coastguard Worker    # The internals of the lru_cache are encapsulated for thread safety and
502*cda5da8dSAndroid Build Coastguard Worker    # to allow the implementation to change (including a possible C version).
503*cda5da8dSAndroid Build Coastguard Worker
504*cda5da8dSAndroid Build Coastguard Worker    if isinstance(maxsize, int):
505*cda5da8dSAndroid Build Coastguard Worker        # Negative maxsize is treated as 0
506*cda5da8dSAndroid Build Coastguard Worker        if maxsize < 0:
507*cda5da8dSAndroid Build Coastguard Worker            maxsize = 0
508*cda5da8dSAndroid Build Coastguard Worker    elif callable(maxsize) and isinstance(typed, bool):
509*cda5da8dSAndroid Build Coastguard Worker        # The user_function was passed in directly via the maxsize argument
510*cda5da8dSAndroid Build Coastguard Worker        user_function, maxsize = maxsize, 128
511*cda5da8dSAndroid Build Coastguard Worker        wrapper = _lru_cache_wrapper(user_function, maxsize, typed, _CacheInfo)
512*cda5da8dSAndroid Build Coastguard Worker        wrapper.cache_parameters = lambda : {'maxsize': maxsize, 'typed': typed}
513*cda5da8dSAndroid Build Coastguard Worker        return update_wrapper(wrapper, user_function)
514*cda5da8dSAndroid Build Coastguard Worker    elif maxsize is not None:
515*cda5da8dSAndroid Build Coastguard Worker        raise TypeError(
516*cda5da8dSAndroid Build Coastguard Worker            'Expected first argument to be an integer, a callable, or None')
517*cda5da8dSAndroid Build Coastguard Worker
518*cda5da8dSAndroid Build Coastguard Worker    def decorating_function(user_function):
519*cda5da8dSAndroid Build Coastguard Worker        wrapper = _lru_cache_wrapper(user_function, maxsize, typed, _CacheInfo)
520*cda5da8dSAndroid Build Coastguard Worker        wrapper.cache_parameters = lambda : {'maxsize': maxsize, 'typed': typed}
521*cda5da8dSAndroid Build Coastguard Worker        return update_wrapper(wrapper, user_function)
522*cda5da8dSAndroid Build Coastguard Worker
523*cda5da8dSAndroid Build Coastguard Worker    return decorating_function
524*cda5da8dSAndroid Build Coastguard Worker
525*cda5da8dSAndroid Build Coastguard Workerdef _lru_cache_wrapper(user_function, maxsize, typed, _CacheInfo):
526*cda5da8dSAndroid Build Coastguard Worker    # Constants shared by all lru cache instances:
527*cda5da8dSAndroid Build Coastguard Worker    sentinel = object()          # unique object used to signal cache misses
528*cda5da8dSAndroid Build Coastguard Worker    make_key = _make_key         # build a key from the function arguments
529*cda5da8dSAndroid Build Coastguard Worker    PREV, NEXT, KEY, RESULT = 0, 1, 2, 3   # names for the link fields
530*cda5da8dSAndroid Build Coastguard Worker
531*cda5da8dSAndroid Build Coastguard Worker    cache = {}
532*cda5da8dSAndroid Build Coastguard Worker    hits = misses = 0
533*cda5da8dSAndroid Build Coastguard Worker    full = False
534*cda5da8dSAndroid Build Coastguard Worker    cache_get = cache.get    # bound method to lookup a key or return None
535*cda5da8dSAndroid Build Coastguard Worker    cache_len = cache.__len__  # get cache size without calling len()
536*cda5da8dSAndroid Build Coastguard Worker    lock = RLock()           # because linkedlist updates aren't threadsafe
537*cda5da8dSAndroid Build Coastguard Worker    root = []                # root of the circular doubly linked list
538*cda5da8dSAndroid Build Coastguard Worker    root[:] = [root, root, None, None]     # initialize by pointing to self
539*cda5da8dSAndroid Build Coastguard Worker
540*cda5da8dSAndroid Build Coastguard Worker    if maxsize == 0:
541*cda5da8dSAndroid Build Coastguard Worker
542*cda5da8dSAndroid Build Coastguard Worker        def wrapper(*args, **kwds):
543*cda5da8dSAndroid Build Coastguard Worker            # No caching -- just a statistics update
544*cda5da8dSAndroid Build Coastguard Worker            nonlocal misses
545*cda5da8dSAndroid Build Coastguard Worker            misses += 1
546*cda5da8dSAndroid Build Coastguard Worker            result = user_function(*args, **kwds)
547*cda5da8dSAndroid Build Coastguard Worker            return result
548*cda5da8dSAndroid Build Coastguard Worker
549*cda5da8dSAndroid Build Coastguard Worker    elif maxsize is None:
550*cda5da8dSAndroid Build Coastguard Worker
551*cda5da8dSAndroid Build Coastguard Worker        def wrapper(*args, **kwds):
552*cda5da8dSAndroid Build Coastguard Worker            # Simple caching without ordering or size limit
553*cda5da8dSAndroid Build Coastguard Worker            nonlocal hits, misses
554*cda5da8dSAndroid Build Coastguard Worker            key = make_key(args, kwds, typed)
555*cda5da8dSAndroid Build Coastguard Worker            result = cache_get(key, sentinel)
556*cda5da8dSAndroid Build Coastguard Worker            if result is not sentinel:
557*cda5da8dSAndroid Build Coastguard Worker                hits += 1
558*cda5da8dSAndroid Build Coastguard Worker                return result
559*cda5da8dSAndroid Build Coastguard Worker            misses += 1
560*cda5da8dSAndroid Build Coastguard Worker            result = user_function(*args, **kwds)
561*cda5da8dSAndroid Build Coastguard Worker            cache[key] = result
562*cda5da8dSAndroid Build Coastguard Worker            return result
563*cda5da8dSAndroid Build Coastguard Worker
564*cda5da8dSAndroid Build Coastguard Worker    else:
565*cda5da8dSAndroid Build Coastguard Worker
566*cda5da8dSAndroid Build Coastguard Worker        def wrapper(*args, **kwds):
567*cda5da8dSAndroid Build Coastguard Worker            # Size limited caching that tracks accesses by recency
568*cda5da8dSAndroid Build Coastguard Worker            nonlocal root, hits, misses, full
569*cda5da8dSAndroid Build Coastguard Worker            key = make_key(args, kwds, typed)
570*cda5da8dSAndroid Build Coastguard Worker            with lock:
571*cda5da8dSAndroid Build Coastguard Worker                link = cache_get(key)
572*cda5da8dSAndroid Build Coastguard Worker                if link is not None:
573*cda5da8dSAndroid Build Coastguard Worker                    # Move the link to the front of the circular queue
574*cda5da8dSAndroid Build Coastguard Worker                    link_prev, link_next, _key, result = link
575*cda5da8dSAndroid Build Coastguard Worker                    link_prev[NEXT] = link_next
576*cda5da8dSAndroid Build Coastguard Worker                    link_next[PREV] = link_prev
577*cda5da8dSAndroid Build Coastguard Worker                    last = root[PREV]
578*cda5da8dSAndroid Build Coastguard Worker                    last[NEXT] = root[PREV] = link
579*cda5da8dSAndroid Build Coastguard Worker                    link[PREV] = last
580*cda5da8dSAndroid Build Coastguard Worker                    link[NEXT] = root
581*cda5da8dSAndroid Build Coastguard Worker                    hits += 1
582*cda5da8dSAndroid Build Coastguard Worker                    return result
583*cda5da8dSAndroid Build Coastguard Worker                misses += 1
584*cda5da8dSAndroid Build Coastguard Worker            result = user_function(*args, **kwds)
585*cda5da8dSAndroid Build Coastguard Worker            with lock:
586*cda5da8dSAndroid Build Coastguard Worker                if key in cache:
587*cda5da8dSAndroid Build Coastguard Worker                    # Getting here means that this same key was added to the
588*cda5da8dSAndroid Build Coastguard Worker                    # cache while the lock was released.  Since the link
589*cda5da8dSAndroid Build Coastguard Worker                    # update is already done, we need only return the
590*cda5da8dSAndroid Build Coastguard Worker                    # computed result and update the count of misses.
591*cda5da8dSAndroid Build Coastguard Worker                    pass
592*cda5da8dSAndroid Build Coastguard Worker                elif full:
593*cda5da8dSAndroid Build Coastguard Worker                    # Use the old root to store the new key and result.
594*cda5da8dSAndroid Build Coastguard Worker                    oldroot = root
595*cda5da8dSAndroid Build Coastguard Worker                    oldroot[KEY] = key
596*cda5da8dSAndroid Build Coastguard Worker                    oldroot[RESULT] = result
597*cda5da8dSAndroid Build Coastguard Worker                    # Empty the oldest link and make it the new root.
598*cda5da8dSAndroid Build Coastguard Worker                    # Keep a reference to the old key and old result to
599*cda5da8dSAndroid Build Coastguard Worker                    # prevent their ref counts from going to zero during the
600*cda5da8dSAndroid Build Coastguard Worker                    # update. That will prevent potentially arbitrary object
601*cda5da8dSAndroid Build Coastguard Worker                    # clean-up code (i.e. __del__) from running while we're
602*cda5da8dSAndroid Build Coastguard Worker                    # still adjusting the links.
603*cda5da8dSAndroid Build Coastguard Worker                    root = oldroot[NEXT]
604*cda5da8dSAndroid Build Coastguard Worker                    oldkey = root[KEY]
605*cda5da8dSAndroid Build Coastguard Worker                    oldresult = root[RESULT]
606*cda5da8dSAndroid Build Coastguard Worker                    root[KEY] = root[RESULT] = None
607*cda5da8dSAndroid Build Coastguard Worker                    # Now update the cache dictionary.
608*cda5da8dSAndroid Build Coastguard Worker                    del cache[oldkey]
609*cda5da8dSAndroid Build Coastguard Worker                    # Save the potentially reentrant cache[key] assignment
610*cda5da8dSAndroid Build Coastguard Worker                    # for last, after the root and links have been put in
611*cda5da8dSAndroid Build Coastguard Worker                    # a consistent state.
612*cda5da8dSAndroid Build Coastguard Worker                    cache[key] = oldroot
613*cda5da8dSAndroid Build Coastguard Worker                else:
614*cda5da8dSAndroid Build Coastguard Worker                    # Put result in a new link at the front of the queue.
615*cda5da8dSAndroid Build Coastguard Worker                    last = root[PREV]
616*cda5da8dSAndroid Build Coastguard Worker                    link = [last, root, key, result]
617*cda5da8dSAndroid Build Coastguard Worker                    last[NEXT] = root[PREV] = cache[key] = link
618*cda5da8dSAndroid Build Coastguard Worker                    # Use the cache_len bound method instead of the len() function
619*cda5da8dSAndroid Build Coastguard Worker                    # which could potentially be wrapped in an lru_cache itself.
620*cda5da8dSAndroid Build Coastguard Worker                    full = (cache_len() >= maxsize)
621*cda5da8dSAndroid Build Coastguard Worker            return result
622*cda5da8dSAndroid Build Coastguard Worker
623*cda5da8dSAndroid Build Coastguard Worker    def cache_info():
624*cda5da8dSAndroid Build Coastguard Worker        """Report cache statistics"""
625*cda5da8dSAndroid Build Coastguard Worker        with lock:
626*cda5da8dSAndroid Build Coastguard Worker            return _CacheInfo(hits, misses, maxsize, cache_len())
627*cda5da8dSAndroid Build Coastguard Worker
628*cda5da8dSAndroid Build Coastguard Worker    def cache_clear():
629*cda5da8dSAndroid Build Coastguard Worker        """Clear the cache and cache statistics"""
630*cda5da8dSAndroid Build Coastguard Worker        nonlocal hits, misses, full
631*cda5da8dSAndroid Build Coastguard Worker        with lock:
632*cda5da8dSAndroid Build Coastguard Worker            cache.clear()
633*cda5da8dSAndroid Build Coastguard Worker            root[:] = [root, root, None, None]
634*cda5da8dSAndroid Build Coastguard Worker            hits = misses = 0
635*cda5da8dSAndroid Build Coastguard Worker            full = False
636*cda5da8dSAndroid Build Coastguard Worker
637*cda5da8dSAndroid Build Coastguard Worker    wrapper.cache_info = cache_info
638*cda5da8dSAndroid Build Coastguard Worker    wrapper.cache_clear = cache_clear
639*cda5da8dSAndroid Build Coastguard Worker    return wrapper
640*cda5da8dSAndroid Build Coastguard Worker
641*cda5da8dSAndroid Build Coastguard Workertry:
642*cda5da8dSAndroid Build Coastguard Worker    from _functools import _lru_cache_wrapper
643*cda5da8dSAndroid Build Coastguard Workerexcept ImportError:
644*cda5da8dSAndroid Build Coastguard Worker    pass
645*cda5da8dSAndroid Build Coastguard Worker
646*cda5da8dSAndroid Build Coastguard Worker
647*cda5da8dSAndroid Build Coastguard Worker################################################################################
648*cda5da8dSAndroid Build Coastguard Worker### cache -- simplified access to the infinity cache
649*cda5da8dSAndroid Build Coastguard Worker################################################################################
650*cda5da8dSAndroid Build Coastguard Worker
651*cda5da8dSAndroid Build Coastguard Workerdef cache(user_function, /):
652*cda5da8dSAndroid Build Coastguard Worker    'Simple lightweight unbounded cache.  Sometimes called "memoize".'
653*cda5da8dSAndroid Build Coastguard Worker    return lru_cache(maxsize=None)(user_function)
654*cda5da8dSAndroid Build Coastguard Worker
655*cda5da8dSAndroid Build Coastguard Worker
656*cda5da8dSAndroid Build Coastguard Worker################################################################################
657*cda5da8dSAndroid Build Coastguard Worker### singledispatch() - single-dispatch generic function decorator
658*cda5da8dSAndroid Build Coastguard Worker################################################################################
659*cda5da8dSAndroid Build Coastguard Worker
660*cda5da8dSAndroid Build Coastguard Workerdef _c3_merge(sequences):
661*cda5da8dSAndroid Build Coastguard Worker    """Merges MROs in *sequences* to a single MRO using the C3 algorithm.
662*cda5da8dSAndroid Build Coastguard Worker
663*cda5da8dSAndroid Build Coastguard Worker    Adapted from https://www.python.org/download/releases/2.3/mro/.
664*cda5da8dSAndroid Build Coastguard Worker
665*cda5da8dSAndroid Build Coastguard Worker    """
666*cda5da8dSAndroid Build Coastguard Worker    result = []
667*cda5da8dSAndroid Build Coastguard Worker    while True:
668*cda5da8dSAndroid Build Coastguard Worker        sequences = [s for s in sequences if s]   # purge empty sequences
669*cda5da8dSAndroid Build Coastguard Worker        if not sequences:
670*cda5da8dSAndroid Build Coastguard Worker            return result
671*cda5da8dSAndroid Build Coastguard Worker        for s1 in sequences:   # find merge candidates among seq heads
672*cda5da8dSAndroid Build Coastguard Worker            candidate = s1[0]
673*cda5da8dSAndroid Build Coastguard Worker            for s2 in sequences:
674*cda5da8dSAndroid Build Coastguard Worker                if candidate in s2[1:]:
675*cda5da8dSAndroid Build Coastguard Worker                    candidate = None
676*cda5da8dSAndroid Build Coastguard Worker                    break      # reject the current head, it appears later
677*cda5da8dSAndroid Build Coastguard Worker            else:
678*cda5da8dSAndroid Build Coastguard Worker                break
679*cda5da8dSAndroid Build Coastguard Worker        if candidate is None:
680*cda5da8dSAndroid Build Coastguard Worker            raise RuntimeError("Inconsistent hierarchy")
681*cda5da8dSAndroid Build Coastguard Worker        result.append(candidate)
682*cda5da8dSAndroid Build Coastguard Worker        # remove the chosen candidate
683*cda5da8dSAndroid Build Coastguard Worker        for seq in sequences:
684*cda5da8dSAndroid Build Coastguard Worker            if seq[0] == candidate:
685*cda5da8dSAndroid Build Coastguard Worker                del seq[0]
686*cda5da8dSAndroid Build Coastguard Worker
687*cda5da8dSAndroid Build Coastguard Workerdef _c3_mro(cls, abcs=None):
688*cda5da8dSAndroid Build Coastguard Worker    """Computes the method resolution order using extended C3 linearization.
689*cda5da8dSAndroid Build Coastguard Worker
690*cda5da8dSAndroid Build Coastguard Worker    If no *abcs* are given, the algorithm works exactly like the built-in C3
691*cda5da8dSAndroid Build Coastguard Worker    linearization used for method resolution.
692*cda5da8dSAndroid Build Coastguard Worker
693*cda5da8dSAndroid Build Coastguard Worker    If given, *abcs* is a list of abstract base classes that should be inserted
694*cda5da8dSAndroid Build Coastguard Worker    into the resulting MRO. Unrelated ABCs are ignored and don't end up in the
695*cda5da8dSAndroid Build Coastguard Worker    result. The algorithm inserts ABCs where their functionality is introduced,
696*cda5da8dSAndroid Build Coastguard Worker    i.e. issubclass(cls, abc) returns True for the class itself but returns
697*cda5da8dSAndroid Build Coastguard Worker    False for all its direct base classes. Implicit ABCs for a given class
698*cda5da8dSAndroid Build Coastguard Worker    (either registered or inferred from the presence of a special method like
699*cda5da8dSAndroid Build Coastguard Worker    __len__) are inserted directly after the last ABC explicitly listed in the
700*cda5da8dSAndroid Build Coastguard Worker    MRO of said class. If two implicit ABCs end up next to each other in the
701*cda5da8dSAndroid Build Coastguard Worker    resulting MRO, their ordering depends on the order of types in *abcs*.
702*cda5da8dSAndroid Build Coastguard Worker
703*cda5da8dSAndroid Build Coastguard Worker    """
704*cda5da8dSAndroid Build Coastguard Worker    for i, base in enumerate(reversed(cls.__bases__)):
705*cda5da8dSAndroid Build Coastguard Worker        if hasattr(base, '__abstractmethods__'):
706*cda5da8dSAndroid Build Coastguard Worker            boundary = len(cls.__bases__) - i
707*cda5da8dSAndroid Build Coastguard Worker            break   # Bases up to the last explicit ABC are considered first.
708*cda5da8dSAndroid Build Coastguard Worker    else:
709*cda5da8dSAndroid Build Coastguard Worker        boundary = 0
710*cda5da8dSAndroid Build Coastguard Worker    abcs = list(abcs) if abcs else []
711*cda5da8dSAndroid Build Coastguard Worker    explicit_bases = list(cls.__bases__[:boundary])
712*cda5da8dSAndroid Build Coastguard Worker    abstract_bases = []
713*cda5da8dSAndroid Build Coastguard Worker    other_bases = list(cls.__bases__[boundary:])
714*cda5da8dSAndroid Build Coastguard Worker    for base in abcs:
715*cda5da8dSAndroid Build Coastguard Worker        if issubclass(cls, base) and not any(
716*cda5da8dSAndroid Build Coastguard Worker                issubclass(b, base) for b in cls.__bases__
717*cda5da8dSAndroid Build Coastguard Worker            ):
718*cda5da8dSAndroid Build Coastguard Worker            # If *cls* is the class that introduces behaviour described by
719*cda5da8dSAndroid Build Coastguard Worker            # an ABC *base*, insert said ABC to its MRO.
720*cda5da8dSAndroid Build Coastguard Worker            abstract_bases.append(base)
721*cda5da8dSAndroid Build Coastguard Worker    for base in abstract_bases:
722*cda5da8dSAndroid Build Coastguard Worker        abcs.remove(base)
723*cda5da8dSAndroid Build Coastguard Worker    explicit_c3_mros = [_c3_mro(base, abcs=abcs) for base in explicit_bases]
724*cda5da8dSAndroid Build Coastguard Worker    abstract_c3_mros = [_c3_mro(base, abcs=abcs) for base in abstract_bases]
725*cda5da8dSAndroid Build Coastguard Worker    other_c3_mros = [_c3_mro(base, abcs=abcs) for base in other_bases]
726*cda5da8dSAndroid Build Coastguard Worker    return _c3_merge(
727*cda5da8dSAndroid Build Coastguard Worker        [[cls]] +
728*cda5da8dSAndroid Build Coastguard Worker        explicit_c3_mros + abstract_c3_mros + other_c3_mros +
729*cda5da8dSAndroid Build Coastguard Worker        [explicit_bases] + [abstract_bases] + [other_bases]
730*cda5da8dSAndroid Build Coastguard Worker    )
731*cda5da8dSAndroid Build Coastguard Worker
732*cda5da8dSAndroid Build Coastguard Workerdef _compose_mro(cls, types):
733*cda5da8dSAndroid Build Coastguard Worker    """Calculates the method resolution order for a given class *cls*.
734*cda5da8dSAndroid Build Coastguard Worker
735*cda5da8dSAndroid Build Coastguard Worker    Includes relevant abstract base classes (with their respective bases) from
736*cda5da8dSAndroid Build Coastguard Worker    the *types* iterable. Uses a modified C3 linearization algorithm.
737*cda5da8dSAndroid Build Coastguard Worker
738*cda5da8dSAndroid Build Coastguard Worker    """
739*cda5da8dSAndroid Build Coastguard Worker    bases = set(cls.__mro__)
740*cda5da8dSAndroid Build Coastguard Worker    # Remove entries which are already present in the __mro__ or unrelated.
741*cda5da8dSAndroid Build Coastguard Worker    def is_related(typ):
742*cda5da8dSAndroid Build Coastguard Worker        return (typ not in bases and hasattr(typ, '__mro__')
743*cda5da8dSAndroid Build Coastguard Worker                                 and not isinstance(typ, GenericAlias)
744*cda5da8dSAndroid Build Coastguard Worker                                 and issubclass(cls, typ))
745*cda5da8dSAndroid Build Coastguard Worker    types = [n for n in types if is_related(n)]
746*cda5da8dSAndroid Build Coastguard Worker    # Remove entries which are strict bases of other entries (they will end up
747*cda5da8dSAndroid Build Coastguard Worker    # in the MRO anyway.
748*cda5da8dSAndroid Build Coastguard Worker    def is_strict_base(typ):
749*cda5da8dSAndroid Build Coastguard Worker        for other in types:
750*cda5da8dSAndroid Build Coastguard Worker            if typ != other and typ in other.__mro__:
751*cda5da8dSAndroid Build Coastguard Worker                return True
752*cda5da8dSAndroid Build Coastguard Worker        return False
753*cda5da8dSAndroid Build Coastguard Worker    types = [n for n in types if not is_strict_base(n)]
754*cda5da8dSAndroid Build Coastguard Worker    # Subclasses of the ABCs in *types* which are also implemented by
755*cda5da8dSAndroid Build Coastguard Worker    # *cls* can be used to stabilize ABC ordering.
756*cda5da8dSAndroid Build Coastguard Worker    type_set = set(types)
757*cda5da8dSAndroid Build Coastguard Worker    mro = []
758*cda5da8dSAndroid Build Coastguard Worker    for typ in types:
759*cda5da8dSAndroid Build Coastguard Worker        found = []
760*cda5da8dSAndroid Build Coastguard Worker        for sub in typ.__subclasses__():
761*cda5da8dSAndroid Build Coastguard Worker            if sub not in bases and issubclass(cls, sub):
762*cda5da8dSAndroid Build Coastguard Worker                found.append([s for s in sub.__mro__ if s in type_set])
763*cda5da8dSAndroid Build Coastguard Worker        if not found:
764*cda5da8dSAndroid Build Coastguard Worker            mro.append(typ)
765*cda5da8dSAndroid Build Coastguard Worker            continue
766*cda5da8dSAndroid Build Coastguard Worker        # Favor subclasses with the biggest number of useful bases
767*cda5da8dSAndroid Build Coastguard Worker        found.sort(key=len, reverse=True)
768*cda5da8dSAndroid Build Coastguard Worker        for sub in found:
769*cda5da8dSAndroid Build Coastguard Worker            for subcls in sub:
770*cda5da8dSAndroid Build Coastguard Worker                if subcls not in mro:
771*cda5da8dSAndroid Build Coastguard Worker                    mro.append(subcls)
772*cda5da8dSAndroid Build Coastguard Worker    return _c3_mro(cls, abcs=mro)
773*cda5da8dSAndroid Build Coastguard Worker
774*cda5da8dSAndroid Build Coastguard Workerdef _find_impl(cls, registry):
775*cda5da8dSAndroid Build Coastguard Worker    """Returns the best matching implementation from *registry* for type *cls*.
776*cda5da8dSAndroid Build Coastguard Worker
777*cda5da8dSAndroid Build Coastguard Worker    Where there is no registered implementation for a specific type, its method
778*cda5da8dSAndroid Build Coastguard Worker    resolution order is used to find a more generic implementation.
779*cda5da8dSAndroid Build Coastguard Worker
780*cda5da8dSAndroid Build Coastguard Worker    Note: if *registry* does not contain an implementation for the base
781*cda5da8dSAndroid Build Coastguard Worker    *object* type, this function may return None.
782*cda5da8dSAndroid Build Coastguard Worker
783*cda5da8dSAndroid Build Coastguard Worker    """
784*cda5da8dSAndroid Build Coastguard Worker    mro = _compose_mro(cls, registry.keys())
785*cda5da8dSAndroid Build Coastguard Worker    match = None
786*cda5da8dSAndroid Build Coastguard Worker    for t in mro:
787*cda5da8dSAndroid Build Coastguard Worker        if match is not None:
788*cda5da8dSAndroid Build Coastguard Worker            # If *match* is an implicit ABC but there is another unrelated,
789*cda5da8dSAndroid Build Coastguard Worker            # equally matching implicit ABC, refuse the temptation to guess.
790*cda5da8dSAndroid Build Coastguard Worker            if (t in registry and t not in cls.__mro__
791*cda5da8dSAndroid Build Coastguard Worker                              and match not in cls.__mro__
792*cda5da8dSAndroid Build Coastguard Worker                              and not issubclass(match, t)):
793*cda5da8dSAndroid Build Coastguard Worker                raise RuntimeError("Ambiguous dispatch: {} or {}".format(
794*cda5da8dSAndroid Build Coastguard Worker                    match, t))
795*cda5da8dSAndroid Build Coastguard Worker            break
796*cda5da8dSAndroid Build Coastguard Worker        if t in registry:
797*cda5da8dSAndroid Build Coastguard Worker            match = t
798*cda5da8dSAndroid Build Coastguard Worker    return registry.get(match)
799*cda5da8dSAndroid Build Coastguard Worker
800*cda5da8dSAndroid Build Coastguard Workerdef singledispatch(func):
801*cda5da8dSAndroid Build Coastguard Worker    """Single-dispatch generic function decorator.
802*cda5da8dSAndroid Build Coastguard Worker
803*cda5da8dSAndroid Build Coastguard Worker    Transforms a function into a generic function, which can have different
804*cda5da8dSAndroid Build Coastguard Worker    behaviours depending upon the type of its first argument. The decorated
805*cda5da8dSAndroid Build Coastguard Worker    function acts as the default implementation, and additional
806*cda5da8dSAndroid Build Coastguard Worker    implementations can be registered using the register() attribute of the
807*cda5da8dSAndroid Build Coastguard Worker    generic function.
808*cda5da8dSAndroid Build Coastguard Worker    """
809*cda5da8dSAndroid Build Coastguard Worker    # There are many programs that use functools without singledispatch, so we
810*cda5da8dSAndroid Build Coastguard Worker    # trade-off making singledispatch marginally slower for the benefit of
811*cda5da8dSAndroid Build Coastguard Worker    # making start-up of such applications slightly faster.
812*cda5da8dSAndroid Build Coastguard Worker    import types, weakref
813*cda5da8dSAndroid Build Coastguard Worker
814*cda5da8dSAndroid Build Coastguard Worker    registry = {}
815*cda5da8dSAndroid Build Coastguard Worker    dispatch_cache = weakref.WeakKeyDictionary()
816*cda5da8dSAndroid Build Coastguard Worker    cache_token = None
817*cda5da8dSAndroid Build Coastguard Worker
818*cda5da8dSAndroid Build Coastguard Worker    def dispatch(cls):
819*cda5da8dSAndroid Build Coastguard Worker        """generic_func.dispatch(cls) -> <function implementation>
820*cda5da8dSAndroid Build Coastguard Worker
821*cda5da8dSAndroid Build Coastguard Worker        Runs the dispatch algorithm to return the best available implementation
822*cda5da8dSAndroid Build Coastguard Worker        for the given *cls* registered on *generic_func*.
823*cda5da8dSAndroid Build Coastguard Worker
824*cda5da8dSAndroid Build Coastguard Worker        """
825*cda5da8dSAndroid Build Coastguard Worker        nonlocal cache_token
826*cda5da8dSAndroid Build Coastguard Worker        if cache_token is not None:
827*cda5da8dSAndroid Build Coastguard Worker            current_token = get_cache_token()
828*cda5da8dSAndroid Build Coastguard Worker            if cache_token != current_token:
829*cda5da8dSAndroid Build Coastguard Worker                dispatch_cache.clear()
830*cda5da8dSAndroid Build Coastguard Worker                cache_token = current_token
831*cda5da8dSAndroid Build Coastguard Worker        try:
832*cda5da8dSAndroid Build Coastguard Worker            impl = dispatch_cache[cls]
833*cda5da8dSAndroid Build Coastguard Worker        except KeyError:
834*cda5da8dSAndroid Build Coastguard Worker            try:
835*cda5da8dSAndroid Build Coastguard Worker                impl = registry[cls]
836*cda5da8dSAndroid Build Coastguard Worker            except KeyError:
837*cda5da8dSAndroid Build Coastguard Worker                impl = _find_impl(cls, registry)
838*cda5da8dSAndroid Build Coastguard Worker            dispatch_cache[cls] = impl
839*cda5da8dSAndroid Build Coastguard Worker        return impl
840*cda5da8dSAndroid Build Coastguard Worker
841*cda5da8dSAndroid Build Coastguard Worker    def _is_union_type(cls):
842*cda5da8dSAndroid Build Coastguard Worker        from typing import get_origin, Union
843*cda5da8dSAndroid Build Coastguard Worker        return get_origin(cls) in {Union, types.UnionType}
844*cda5da8dSAndroid Build Coastguard Worker
845*cda5da8dSAndroid Build Coastguard Worker    def _is_valid_dispatch_type(cls):
846*cda5da8dSAndroid Build Coastguard Worker        if isinstance(cls, type):
847*cda5da8dSAndroid Build Coastguard Worker            return True
848*cda5da8dSAndroid Build Coastguard Worker        from typing import get_args
849*cda5da8dSAndroid Build Coastguard Worker        return (_is_union_type(cls) and
850*cda5da8dSAndroid Build Coastguard Worker                all(isinstance(arg, type) for arg in get_args(cls)))
851*cda5da8dSAndroid Build Coastguard Worker
852*cda5da8dSAndroid Build Coastguard Worker    def register(cls, func=None):
853*cda5da8dSAndroid Build Coastguard Worker        """generic_func.register(cls, func) -> func
854*cda5da8dSAndroid Build Coastguard Worker
855*cda5da8dSAndroid Build Coastguard Worker        Registers a new implementation for the given *cls* on a *generic_func*.
856*cda5da8dSAndroid Build Coastguard Worker
857*cda5da8dSAndroid Build Coastguard Worker        """
858*cda5da8dSAndroid Build Coastguard Worker        nonlocal cache_token
859*cda5da8dSAndroid Build Coastguard Worker        if _is_valid_dispatch_type(cls):
860*cda5da8dSAndroid Build Coastguard Worker            if func is None:
861*cda5da8dSAndroid Build Coastguard Worker                return lambda f: register(cls, f)
862*cda5da8dSAndroid Build Coastguard Worker        else:
863*cda5da8dSAndroid Build Coastguard Worker            if func is not None:
864*cda5da8dSAndroid Build Coastguard Worker                raise TypeError(
865*cda5da8dSAndroid Build Coastguard Worker                    f"Invalid first argument to `register()`. "
866*cda5da8dSAndroid Build Coastguard Worker                    f"{cls!r} is not a class or union type."
867*cda5da8dSAndroid Build Coastguard Worker                )
868*cda5da8dSAndroid Build Coastguard Worker            ann = getattr(cls, '__annotations__', {})
869*cda5da8dSAndroid Build Coastguard Worker            if not ann:
870*cda5da8dSAndroid Build Coastguard Worker                raise TypeError(
871*cda5da8dSAndroid Build Coastguard Worker                    f"Invalid first argument to `register()`: {cls!r}. "
872*cda5da8dSAndroid Build Coastguard Worker                    f"Use either `@register(some_class)` or plain `@register` "
873*cda5da8dSAndroid Build Coastguard Worker                    f"on an annotated function."
874*cda5da8dSAndroid Build Coastguard Worker                )
875*cda5da8dSAndroid Build Coastguard Worker            func = cls
876*cda5da8dSAndroid Build Coastguard Worker
877*cda5da8dSAndroid Build Coastguard Worker            # only import typing if annotation parsing is necessary
878*cda5da8dSAndroid Build Coastguard Worker            from typing import get_type_hints
879*cda5da8dSAndroid Build Coastguard Worker            argname, cls = next(iter(get_type_hints(func).items()))
880*cda5da8dSAndroid Build Coastguard Worker            if not _is_valid_dispatch_type(cls):
881*cda5da8dSAndroid Build Coastguard Worker                if _is_union_type(cls):
882*cda5da8dSAndroid Build Coastguard Worker                    raise TypeError(
883*cda5da8dSAndroid Build Coastguard Worker                        f"Invalid annotation for {argname!r}. "
884*cda5da8dSAndroid Build Coastguard Worker                        f"{cls!r} not all arguments are classes."
885*cda5da8dSAndroid Build Coastguard Worker                    )
886*cda5da8dSAndroid Build Coastguard Worker                else:
887*cda5da8dSAndroid Build Coastguard Worker                    raise TypeError(
888*cda5da8dSAndroid Build Coastguard Worker                        f"Invalid annotation for {argname!r}. "
889*cda5da8dSAndroid Build Coastguard Worker                        f"{cls!r} is not a class."
890*cda5da8dSAndroid Build Coastguard Worker                    )
891*cda5da8dSAndroid Build Coastguard Worker
892*cda5da8dSAndroid Build Coastguard Worker        if _is_union_type(cls):
893*cda5da8dSAndroid Build Coastguard Worker            from typing import get_args
894*cda5da8dSAndroid Build Coastguard Worker
895*cda5da8dSAndroid Build Coastguard Worker            for arg in get_args(cls):
896*cda5da8dSAndroid Build Coastguard Worker                registry[arg] = func
897*cda5da8dSAndroid Build Coastguard Worker        else:
898*cda5da8dSAndroid Build Coastguard Worker            registry[cls] = func
899*cda5da8dSAndroid Build Coastguard Worker        if cache_token is None and hasattr(cls, '__abstractmethods__'):
900*cda5da8dSAndroid Build Coastguard Worker            cache_token = get_cache_token()
901*cda5da8dSAndroid Build Coastguard Worker        dispatch_cache.clear()
902*cda5da8dSAndroid Build Coastguard Worker        return func
903*cda5da8dSAndroid Build Coastguard Worker
904*cda5da8dSAndroid Build Coastguard Worker    def wrapper(*args, **kw):
905*cda5da8dSAndroid Build Coastguard Worker        if not args:
906*cda5da8dSAndroid Build Coastguard Worker            raise TypeError(f'{funcname} requires at least '
907*cda5da8dSAndroid Build Coastguard Worker                            '1 positional argument')
908*cda5da8dSAndroid Build Coastguard Worker
909*cda5da8dSAndroid Build Coastguard Worker        return dispatch(args[0].__class__)(*args, **kw)
910*cda5da8dSAndroid Build Coastguard Worker
911*cda5da8dSAndroid Build Coastguard Worker    funcname = getattr(func, '__name__', 'singledispatch function')
912*cda5da8dSAndroid Build Coastguard Worker    registry[object] = func
913*cda5da8dSAndroid Build Coastguard Worker    wrapper.register = register
914*cda5da8dSAndroid Build Coastguard Worker    wrapper.dispatch = dispatch
915*cda5da8dSAndroid Build Coastguard Worker    wrapper.registry = types.MappingProxyType(registry)
916*cda5da8dSAndroid Build Coastguard Worker    wrapper._clear_cache = dispatch_cache.clear
917*cda5da8dSAndroid Build Coastguard Worker    update_wrapper(wrapper, func)
918*cda5da8dSAndroid Build Coastguard Worker    return wrapper
919*cda5da8dSAndroid Build Coastguard Worker
920*cda5da8dSAndroid Build Coastguard Worker
921*cda5da8dSAndroid Build Coastguard Worker# Descriptor version
922*cda5da8dSAndroid Build Coastguard Workerclass singledispatchmethod:
923*cda5da8dSAndroid Build Coastguard Worker    """Single-dispatch generic method descriptor.
924*cda5da8dSAndroid Build Coastguard Worker
925*cda5da8dSAndroid Build Coastguard Worker    Supports wrapping existing descriptors and handles non-descriptor
926*cda5da8dSAndroid Build Coastguard Worker    callables as instance methods.
927*cda5da8dSAndroid Build Coastguard Worker    """
928*cda5da8dSAndroid Build Coastguard Worker
929*cda5da8dSAndroid Build Coastguard Worker    def __init__(self, func):
930*cda5da8dSAndroid Build Coastguard Worker        if not callable(func) and not hasattr(func, "__get__"):
931*cda5da8dSAndroid Build Coastguard Worker            raise TypeError(f"{func!r} is not callable or a descriptor")
932*cda5da8dSAndroid Build Coastguard Worker
933*cda5da8dSAndroid Build Coastguard Worker        self.dispatcher = singledispatch(func)
934*cda5da8dSAndroid Build Coastguard Worker        self.func = func
935*cda5da8dSAndroid Build Coastguard Worker
936*cda5da8dSAndroid Build Coastguard Worker    def register(self, cls, method=None):
937*cda5da8dSAndroid Build Coastguard Worker        """generic_method.register(cls, func) -> func
938*cda5da8dSAndroid Build Coastguard Worker
939*cda5da8dSAndroid Build Coastguard Worker        Registers a new implementation for the given *cls* on a *generic_method*.
940*cda5da8dSAndroid Build Coastguard Worker        """
941*cda5da8dSAndroid Build Coastguard Worker        return self.dispatcher.register(cls, func=method)
942*cda5da8dSAndroid Build Coastguard Worker
943*cda5da8dSAndroid Build Coastguard Worker    def __get__(self, obj, cls=None):
944*cda5da8dSAndroid Build Coastguard Worker        def _method(*args, **kwargs):
945*cda5da8dSAndroid Build Coastguard Worker            method = self.dispatcher.dispatch(args[0].__class__)
946*cda5da8dSAndroid Build Coastguard Worker            return method.__get__(obj, cls)(*args, **kwargs)
947*cda5da8dSAndroid Build Coastguard Worker
948*cda5da8dSAndroid Build Coastguard Worker        _method.__isabstractmethod__ = self.__isabstractmethod__
949*cda5da8dSAndroid Build Coastguard Worker        _method.register = self.register
950*cda5da8dSAndroid Build Coastguard Worker        update_wrapper(_method, self.func)
951*cda5da8dSAndroid Build Coastguard Worker        return _method
952*cda5da8dSAndroid Build Coastguard Worker
953*cda5da8dSAndroid Build Coastguard Worker    @property
954*cda5da8dSAndroid Build Coastguard Worker    def __isabstractmethod__(self):
955*cda5da8dSAndroid Build Coastguard Worker        return getattr(self.func, '__isabstractmethod__', False)
956*cda5da8dSAndroid Build Coastguard Worker
957*cda5da8dSAndroid Build Coastguard Worker
958*cda5da8dSAndroid Build Coastguard Worker################################################################################
959*cda5da8dSAndroid Build Coastguard Worker### cached_property() - computed once per instance, cached as attribute
960*cda5da8dSAndroid Build Coastguard Worker################################################################################
961*cda5da8dSAndroid Build Coastguard Worker
962*cda5da8dSAndroid Build Coastguard Worker_NOT_FOUND = object()
963*cda5da8dSAndroid Build Coastguard Worker
964*cda5da8dSAndroid Build Coastguard Worker
965*cda5da8dSAndroid Build Coastguard Workerclass cached_property:
966*cda5da8dSAndroid Build Coastguard Worker    def __init__(self, func):
967*cda5da8dSAndroid Build Coastguard Worker        self.func = func
968*cda5da8dSAndroid Build Coastguard Worker        self.attrname = None
969*cda5da8dSAndroid Build Coastguard Worker        self.__doc__ = func.__doc__
970*cda5da8dSAndroid Build Coastguard Worker        self.lock = RLock()
971*cda5da8dSAndroid Build Coastguard Worker
972*cda5da8dSAndroid Build Coastguard Worker    def __set_name__(self, owner, name):
973*cda5da8dSAndroid Build Coastguard Worker        if self.attrname is None:
974*cda5da8dSAndroid Build Coastguard Worker            self.attrname = name
975*cda5da8dSAndroid Build Coastguard Worker        elif name != self.attrname:
976*cda5da8dSAndroid Build Coastguard Worker            raise TypeError(
977*cda5da8dSAndroid Build Coastguard Worker                "Cannot assign the same cached_property to two different names "
978*cda5da8dSAndroid Build Coastguard Worker                f"({self.attrname!r} and {name!r})."
979*cda5da8dSAndroid Build Coastguard Worker            )
980*cda5da8dSAndroid Build Coastguard Worker
981*cda5da8dSAndroid Build Coastguard Worker    def __get__(self, instance, owner=None):
982*cda5da8dSAndroid Build Coastguard Worker        if instance is None:
983*cda5da8dSAndroid Build Coastguard Worker            return self
984*cda5da8dSAndroid Build Coastguard Worker        if self.attrname is None:
985*cda5da8dSAndroid Build Coastguard Worker            raise TypeError(
986*cda5da8dSAndroid Build Coastguard Worker                "Cannot use cached_property instance without calling __set_name__ on it.")
987*cda5da8dSAndroid Build Coastguard Worker        try:
988*cda5da8dSAndroid Build Coastguard Worker            cache = instance.__dict__
989*cda5da8dSAndroid Build Coastguard Worker        except AttributeError:  # not all objects have __dict__ (e.g. class defines slots)
990*cda5da8dSAndroid Build Coastguard Worker            msg = (
991*cda5da8dSAndroid Build Coastguard Worker                f"No '__dict__' attribute on {type(instance).__name__!r} "
992*cda5da8dSAndroid Build Coastguard Worker                f"instance to cache {self.attrname!r} property."
993*cda5da8dSAndroid Build Coastguard Worker            )
994*cda5da8dSAndroid Build Coastguard Worker            raise TypeError(msg) from None
995*cda5da8dSAndroid Build Coastguard Worker        val = cache.get(self.attrname, _NOT_FOUND)
996*cda5da8dSAndroid Build Coastguard Worker        if val is _NOT_FOUND:
997*cda5da8dSAndroid Build Coastguard Worker            with self.lock:
998*cda5da8dSAndroid Build Coastguard Worker                # check if another thread filled cache while we awaited lock
999*cda5da8dSAndroid Build Coastguard Worker                val = cache.get(self.attrname, _NOT_FOUND)
1000*cda5da8dSAndroid Build Coastguard Worker                if val is _NOT_FOUND:
1001*cda5da8dSAndroid Build Coastguard Worker                    val = self.func(instance)
1002*cda5da8dSAndroid Build Coastguard Worker                    try:
1003*cda5da8dSAndroid Build Coastguard Worker                        cache[self.attrname] = val
1004*cda5da8dSAndroid Build Coastguard Worker                    except TypeError:
1005*cda5da8dSAndroid Build Coastguard Worker                        msg = (
1006*cda5da8dSAndroid Build Coastguard Worker                            f"The '__dict__' attribute on {type(instance).__name__!r} instance "
1007*cda5da8dSAndroid Build Coastguard Worker                            f"does not support item assignment for caching {self.attrname!r} property."
1008*cda5da8dSAndroid Build Coastguard Worker                        )
1009*cda5da8dSAndroid Build Coastguard Worker                        raise TypeError(msg) from None
1010*cda5da8dSAndroid Build Coastguard Worker        return val
1011*cda5da8dSAndroid Build Coastguard Worker
1012*cda5da8dSAndroid Build Coastguard Worker    __class_getitem__ = classmethod(GenericAlias)
1013