17db96d56Sopenharmony_ciimport abc
27db96d56Sopenharmony_ciimport builtins
37db96d56Sopenharmony_ciimport collections
47db96d56Sopenharmony_ciimport collections.abc
57db96d56Sopenharmony_ciimport copy
67db96d56Sopenharmony_cifrom itertools import permutations
77db96d56Sopenharmony_ciimport pickle
87db96d56Sopenharmony_cifrom random import choice
97db96d56Sopenharmony_ciimport sys
107db96d56Sopenharmony_cifrom test import support
117db96d56Sopenharmony_ciimport threading
127db96d56Sopenharmony_ciimport time
137db96d56Sopenharmony_ciimport typing
147db96d56Sopenharmony_ciimport unittest
157db96d56Sopenharmony_ciimport unittest.mock
167db96d56Sopenharmony_ciimport os
177db96d56Sopenharmony_ciimport weakref
187db96d56Sopenharmony_ciimport gc
197db96d56Sopenharmony_cifrom weakref import proxy
207db96d56Sopenharmony_ciimport contextlib
217db96d56Sopenharmony_ci
227db96d56Sopenharmony_cifrom test.support import import_helper
237db96d56Sopenharmony_cifrom test.support import threading_helper
247db96d56Sopenharmony_cifrom test.support.script_helper import assert_python_ok
257db96d56Sopenharmony_ci
267db96d56Sopenharmony_ciimport functools
277db96d56Sopenharmony_ci
287db96d56Sopenharmony_cipy_functools = import_helper.import_fresh_module('functools',
297db96d56Sopenharmony_ci                                                 blocked=['_functools'])
307db96d56Sopenharmony_cic_functools = import_helper.import_fresh_module('functools')
317db96d56Sopenharmony_ci
327db96d56Sopenharmony_cidecimal = import_helper.import_fresh_module('decimal', fresh=['_decimal'])
337db96d56Sopenharmony_ci
347db96d56Sopenharmony_ci@contextlib.contextmanager
357db96d56Sopenharmony_cidef replaced_module(name, replacement):
367db96d56Sopenharmony_ci    original_module = sys.modules[name]
377db96d56Sopenharmony_ci    sys.modules[name] = replacement
387db96d56Sopenharmony_ci    try:
397db96d56Sopenharmony_ci        yield
407db96d56Sopenharmony_ci    finally:
417db96d56Sopenharmony_ci        sys.modules[name] = original_module
427db96d56Sopenharmony_ci
437db96d56Sopenharmony_cidef capture(*args, **kw):
447db96d56Sopenharmony_ci    """capture all positional and keyword arguments"""
457db96d56Sopenharmony_ci    return args, kw
467db96d56Sopenharmony_ci
477db96d56Sopenharmony_ci
487db96d56Sopenharmony_cidef signature(part):
497db96d56Sopenharmony_ci    """ return the signature of a partial object """
507db96d56Sopenharmony_ci    return (part.func, part.args, part.keywords, part.__dict__)
517db96d56Sopenharmony_ci
527db96d56Sopenharmony_ciclass MyTuple(tuple):
537db96d56Sopenharmony_ci    pass
547db96d56Sopenharmony_ci
557db96d56Sopenharmony_ciclass BadTuple(tuple):
567db96d56Sopenharmony_ci    def __add__(self, other):
577db96d56Sopenharmony_ci        return list(self) + list(other)
587db96d56Sopenharmony_ci
597db96d56Sopenharmony_ciclass MyDict(dict):
607db96d56Sopenharmony_ci    pass
617db96d56Sopenharmony_ci
627db96d56Sopenharmony_ci
637db96d56Sopenharmony_ciclass TestPartial:
647db96d56Sopenharmony_ci
657db96d56Sopenharmony_ci    def test_basic_examples(self):
667db96d56Sopenharmony_ci        p = self.partial(capture, 1, 2, a=10, b=20)
677db96d56Sopenharmony_ci        self.assertTrue(callable(p))
687db96d56Sopenharmony_ci        self.assertEqual(p(3, 4, b=30, c=40),
697db96d56Sopenharmony_ci                         ((1, 2, 3, 4), dict(a=10, b=30, c=40)))
707db96d56Sopenharmony_ci        p = self.partial(map, lambda x: x*10)
717db96d56Sopenharmony_ci        self.assertEqual(list(p([1,2,3,4])), [10, 20, 30, 40])
727db96d56Sopenharmony_ci
737db96d56Sopenharmony_ci    def test_attributes(self):
747db96d56Sopenharmony_ci        p = self.partial(capture, 1, 2, a=10, b=20)
757db96d56Sopenharmony_ci        # attributes should be readable
767db96d56Sopenharmony_ci        self.assertEqual(p.func, capture)
777db96d56Sopenharmony_ci        self.assertEqual(p.args, (1, 2))
787db96d56Sopenharmony_ci        self.assertEqual(p.keywords, dict(a=10, b=20))
797db96d56Sopenharmony_ci
807db96d56Sopenharmony_ci    def test_argument_checking(self):
817db96d56Sopenharmony_ci        self.assertRaises(TypeError, self.partial)     # need at least a func arg
827db96d56Sopenharmony_ci        try:
837db96d56Sopenharmony_ci            self.partial(2)()
847db96d56Sopenharmony_ci        except TypeError:
857db96d56Sopenharmony_ci            pass
867db96d56Sopenharmony_ci        else:
877db96d56Sopenharmony_ci            self.fail('First arg not checked for callability')
887db96d56Sopenharmony_ci
897db96d56Sopenharmony_ci    def test_protection_of_callers_dict_argument(self):
907db96d56Sopenharmony_ci        # a caller's dictionary should not be altered by partial
917db96d56Sopenharmony_ci        def func(a=10, b=20):
927db96d56Sopenharmony_ci            return a
937db96d56Sopenharmony_ci        d = {'a':3}
947db96d56Sopenharmony_ci        p = self.partial(func, a=5)
957db96d56Sopenharmony_ci        self.assertEqual(p(**d), 3)
967db96d56Sopenharmony_ci        self.assertEqual(d, {'a':3})
977db96d56Sopenharmony_ci        p(b=7)
987db96d56Sopenharmony_ci        self.assertEqual(d, {'a':3})
997db96d56Sopenharmony_ci
1007db96d56Sopenharmony_ci    def test_kwargs_copy(self):
1017db96d56Sopenharmony_ci        # Issue #29532: Altering a kwarg dictionary passed to a constructor
1027db96d56Sopenharmony_ci        # should not affect a partial object after creation
1037db96d56Sopenharmony_ci        d = {'a': 3}
1047db96d56Sopenharmony_ci        p = self.partial(capture, **d)
1057db96d56Sopenharmony_ci        self.assertEqual(p(), ((), {'a': 3}))
1067db96d56Sopenharmony_ci        d['a'] = 5
1077db96d56Sopenharmony_ci        self.assertEqual(p(), ((), {'a': 3}))
1087db96d56Sopenharmony_ci
1097db96d56Sopenharmony_ci    def test_arg_combinations(self):
1107db96d56Sopenharmony_ci        # exercise special code paths for zero args in either partial
1117db96d56Sopenharmony_ci        # object or the caller
1127db96d56Sopenharmony_ci        p = self.partial(capture)
1137db96d56Sopenharmony_ci        self.assertEqual(p(), ((), {}))
1147db96d56Sopenharmony_ci        self.assertEqual(p(1,2), ((1,2), {}))
1157db96d56Sopenharmony_ci        p = self.partial(capture, 1, 2)
1167db96d56Sopenharmony_ci        self.assertEqual(p(), ((1,2), {}))
1177db96d56Sopenharmony_ci        self.assertEqual(p(3,4), ((1,2,3,4), {}))
1187db96d56Sopenharmony_ci
1197db96d56Sopenharmony_ci    def test_kw_combinations(self):
1207db96d56Sopenharmony_ci        # exercise special code paths for no keyword args in
1217db96d56Sopenharmony_ci        # either the partial object or the caller
1227db96d56Sopenharmony_ci        p = self.partial(capture)
1237db96d56Sopenharmony_ci        self.assertEqual(p.keywords, {})
1247db96d56Sopenharmony_ci        self.assertEqual(p(), ((), {}))
1257db96d56Sopenharmony_ci        self.assertEqual(p(a=1), ((), {'a':1}))
1267db96d56Sopenharmony_ci        p = self.partial(capture, a=1)
1277db96d56Sopenharmony_ci        self.assertEqual(p.keywords, {'a':1})
1287db96d56Sopenharmony_ci        self.assertEqual(p(), ((), {'a':1}))
1297db96d56Sopenharmony_ci        self.assertEqual(p(b=2), ((), {'a':1, 'b':2}))
1307db96d56Sopenharmony_ci        # keyword args in the call override those in the partial object
1317db96d56Sopenharmony_ci        self.assertEqual(p(a=3, b=2), ((), {'a':3, 'b':2}))
1327db96d56Sopenharmony_ci
1337db96d56Sopenharmony_ci    def test_positional(self):
1347db96d56Sopenharmony_ci        # make sure positional arguments are captured correctly
1357db96d56Sopenharmony_ci        for args in [(), (0,), (0,1), (0,1,2), (0,1,2,3)]:
1367db96d56Sopenharmony_ci            p = self.partial(capture, *args)
1377db96d56Sopenharmony_ci            expected = args + ('x',)
1387db96d56Sopenharmony_ci            got, empty = p('x')
1397db96d56Sopenharmony_ci            self.assertTrue(expected == got and empty == {})
1407db96d56Sopenharmony_ci
1417db96d56Sopenharmony_ci    def test_keyword(self):
1427db96d56Sopenharmony_ci        # make sure keyword arguments are captured correctly
1437db96d56Sopenharmony_ci        for a in ['a', 0, None, 3.5]:
1447db96d56Sopenharmony_ci            p = self.partial(capture, a=a)
1457db96d56Sopenharmony_ci            expected = {'a':a,'x':None}
1467db96d56Sopenharmony_ci            empty, got = p(x=None)
1477db96d56Sopenharmony_ci            self.assertTrue(expected == got and empty == ())
1487db96d56Sopenharmony_ci
1497db96d56Sopenharmony_ci    def test_no_side_effects(self):
1507db96d56Sopenharmony_ci        # make sure there are no side effects that affect subsequent calls
1517db96d56Sopenharmony_ci        p = self.partial(capture, 0, a=1)
1527db96d56Sopenharmony_ci        args1, kw1 = p(1, b=2)
1537db96d56Sopenharmony_ci        self.assertTrue(args1 == (0,1) and kw1 == {'a':1,'b':2})
1547db96d56Sopenharmony_ci        args2, kw2 = p()
1557db96d56Sopenharmony_ci        self.assertTrue(args2 == (0,) and kw2 == {'a':1})
1567db96d56Sopenharmony_ci
1577db96d56Sopenharmony_ci    def test_error_propagation(self):
1587db96d56Sopenharmony_ci        def f(x, y):
1597db96d56Sopenharmony_ci            x / y
1607db96d56Sopenharmony_ci        self.assertRaises(ZeroDivisionError, self.partial(f, 1, 0))
1617db96d56Sopenharmony_ci        self.assertRaises(ZeroDivisionError, self.partial(f, 1), 0)
1627db96d56Sopenharmony_ci        self.assertRaises(ZeroDivisionError, self.partial(f), 1, 0)
1637db96d56Sopenharmony_ci        self.assertRaises(ZeroDivisionError, self.partial(f, y=0), 1)
1647db96d56Sopenharmony_ci
1657db96d56Sopenharmony_ci    def test_weakref(self):
1667db96d56Sopenharmony_ci        f = self.partial(int, base=16)
1677db96d56Sopenharmony_ci        p = proxy(f)
1687db96d56Sopenharmony_ci        self.assertEqual(f.func, p.func)
1697db96d56Sopenharmony_ci        f = None
1707db96d56Sopenharmony_ci        support.gc_collect()  # For PyPy or other GCs.
1717db96d56Sopenharmony_ci        self.assertRaises(ReferenceError, getattr, p, 'func')
1727db96d56Sopenharmony_ci
1737db96d56Sopenharmony_ci    def test_with_bound_and_unbound_methods(self):
1747db96d56Sopenharmony_ci        data = list(map(str, range(10)))
1757db96d56Sopenharmony_ci        join = self.partial(str.join, '')
1767db96d56Sopenharmony_ci        self.assertEqual(join(data), '0123456789')
1777db96d56Sopenharmony_ci        join = self.partial(''.join)
1787db96d56Sopenharmony_ci        self.assertEqual(join(data), '0123456789')
1797db96d56Sopenharmony_ci
1807db96d56Sopenharmony_ci    def test_nested_optimization(self):
1817db96d56Sopenharmony_ci        partial = self.partial
1827db96d56Sopenharmony_ci        inner = partial(signature, 'asdf')
1837db96d56Sopenharmony_ci        nested = partial(inner, bar=True)
1847db96d56Sopenharmony_ci        flat = partial(signature, 'asdf', bar=True)
1857db96d56Sopenharmony_ci        self.assertEqual(signature(nested), signature(flat))
1867db96d56Sopenharmony_ci
1877db96d56Sopenharmony_ci    def test_nested_partial_with_attribute(self):
1887db96d56Sopenharmony_ci        # see issue 25137
1897db96d56Sopenharmony_ci        partial = self.partial
1907db96d56Sopenharmony_ci
1917db96d56Sopenharmony_ci        def foo(bar):
1927db96d56Sopenharmony_ci            return bar
1937db96d56Sopenharmony_ci
1947db96d56Sopenharmony_ci        p = partial(foo, 'first')
1957db96d56Sopenharmony_ci        p2 = partial(p, 'second')
1967db96d56Sopenharmony_ci        p2.new_attr = 'spam'
1977db96d56Sopenharmony_ci        self.assertEqual(p2.new_attr, 'spam')
1987db96d56Sopenharmony_ci
1997db96d56Sopenharmony_ci    def test_repr(self):
2007db96d56Sopenharmony_ci        args = (object(), object())
2017db96d56Sopenharmony_ci        args_repr = ', '.join(repr(a) for a in args)
2027db96d56Sopenharmony_ci        kwargs = {'a': object(), 'b': object()}
2037db96d56Sopenharmony_ci        kwargs_reprs = ['a={a!r}, b={b!r}'.format_map(kwargs),
2047db96d56Sopenharmony_ci                        'b={b!r}, a={a!r}'.format_map(kwargs)]
2057db96d56Sopenharmony_ci        if self.partial in (c_functools.partial, py_functools.partial):
2067db96d56Sopenharmony_ci            name = 'functools.partial'
2077db96d56Sopenharmony_ci        else:
2087db96d56Sopenharmony_ci            name = self.partial.__name__
2097db96d56Sopenharmony_ci
2107db96d56Sopenharmony_ci        f = self.partial(capture)
2117db96d56Sopenharmony_ci        self.assertEqual(f'{name}({capture!r})', repr(f))
2127db96d56Sopenharmony_ci
2137db96d56Sopenharmony_ci        f = self.partial(capture, *args)
2147db96d56Sopenharmony_ci        self.assertEqual(f'{name}({capture!r}, {args_repr})', repr(f))
2157db96d56Sopenharmony_ci
2167db96d56Sopenharmony_ci        f = self.partial(capture, **kwargs)
2177db96d56Sopenharmony_ci        self.assertIn(repr(f),
2187db96d56Sopenharmony_ci                      [f'{name}({capture!r}, {kwargs_repr})'
2197db96d56Sopenharmony_ci                       for kwargs_repr in kwargs_reprs])
2207db96d56Sopenharmony_ci
2217db96d56Sopenharmony_ci        f = self.partial(capture, *args, **kwargs)
2227db96d56Sopenharmony_ci        self.assertIn(repr(f),
2237db96d56Sopenharmony_ci                      [f'{name}({capture!r}, {args_repr}, {kwargs_repr})'
2247db96d56Sopenharmony_ci                       for kwargs_repr in kwargs_reprs])
2257db96d56Sopenharmony_ci
2267db96d56Sopenharmony_ci    def test_recursive_repr(self):
2277db96d56Sopenharmony_ci        if self.partial in (c_functools.partial, py_functools.partial):
2287db96d56Sopenharmony_ci            name = 'functools.partial'
2297db96d56Sopenharmony_ci        else:
2307db96d56Sopenharmony_ci            name = self.partial.__name__
2317db96d56Sopenharmony_ci
2327db96d56Sopenharmony_ci        f = self.partial(capture)
2337db96d56Sopenharmony_ci        f.__setstate__((f, (), {}, {}))
2347db96d56Sopenharmony_ci        try:
2357db96d56Sopenharmony_ci            self.assertEqual(repr(f), '%s(...)' % (name,))
2367db96d56Sopenharmony_ci        finally:
2377db96d56Sopenharmony_ci            f.__setstate__((capture, (), {}, {}))
2387db96d56Sopenharmony_ci
2397db96d56Sopenharmony_ci        f = self.partial(capture)
2407db96d56Sopenharmony_ci        f.__setstate__((capture, (f,), {}, {}))
2417db96d56Sopenharmony_ci        try:
2427db96d56Sopenharmony_ci            self.assertEqual(repr(f), '%s(%r, ...)' % (name, capture,))
2437db96d56Sopenharmony_ci        finally:
2447db96d56Sopenharmony_ci            f.__setstate__((capture, (), {}, {}))
2457db96d56Sopenharmony_ci
2467db96d56Sopenharmony_ci        f = self.partial(capture)
2477db96d56Sopenharmony_ci        f.__setstate__((capture, (), {'a': f}, {}))
2487db96d56Sopenharmony_ci        try:
2497db96d56Sopenharmony_ci            self.assertEqual(repr(f), '%s(%r, a=...)' % (name, capture,))
2507db96d56Sopenharmony_ci        finally:
2517db96d56Sopenharmony_ci            f.__setstate__((capture, (), {}, {}))
2527db96d56Sopenharmony_ci
2537db96d56Sopenharmony_ci    def test_pickle(self):
2547db96d56Sopenharmony_ci        with self.AllowPickle():
2557db96d56Sopenharmony_ci            f = self.partial(signature, ['asdf'], bar=[True])
2567db96d56Sopenharmony_ci            f.attr = []
2577db96d56Sopenharmony_ci            for proto in range(pickle.HIGHEST_PROTOCOL + 1):
2587db96d56Sopenharmony_ci                f_copy = pickle.loads(pickle.dumps(f, proto))
2597db96d56Sopenharmony_ci                self.assertEqual(signature(f_copy), signature(f))
2607db96d56Sopenharmony_ci
2617db96d56Sopenharmony_ci    def test_copy(self):
2627db96d56Sopenharmony_ci        f = self.partial(signature, ['asdf'], bar=[True])
2637db96d56Sopenharmony_ci        f.attr = []
2647db96d56Sopenharmony_ci        f_copy = copy.copy(f)
2657db96d56Sopenharmony_ci        self.assertEqual(signature(f_copy), signature(f))
2667db96d56Sopenharmony_ci        self.assertIs(f_copy.attr, f.attr)
2677db96d56Sopenharmony_ci        self.assertIs(f_copy.args, f.args)
2687db96d56Sopenharmony_ci        self.assertIs(f_copy.keywords, f.keywords)
2697db96d56Sopenharmony_ci
2707db96d56Sopenharmony_ci    def test_deepcopy(self):
2717db96d56Sopenharmony_ci        f = self.partial(signature, ['asdf'], bar=[True])
2727db96d56Sopenharmony_ci        f.attr = []
2737db96d56Sopenharmony_ci        f_copy = copy.deepcopy(f)
2747db96d56Sopenharmony_ci        self.assertEqual(signature(f_copy), signature(f))
2757db96d56Sopenharmony_ci        self.assertIsNot(f_copy.attr, f.attr)
2767db96d56Sopenharmony_ci        self.assertIsNot(f_copy.args, f.args)
2777db96d56Sopenharmony_ci        self.assertIsNot(f_copy.args[0], f.args[0])
2787db96d56Sopenharmony_ci        self.assertIsNot(f_copy.keywords, f.keywords)
2797db96d56Sopenharmony_ci        self.assertIsNot(f_copy.keywords['bar'], f.keywords['bar'])
2807db96d56Sopenharmony_ci
2817db96d56Sopenharmony_ci    def test_setstate(self):
2827db96d56Sopenharmony_ci        f = self.partial(signature)
2837db96d56Sopenharmony_ci        f.__setstate__((capture, (1,), dict(a=10), dict(attr=[])))
2847db96d56Sopenharmony_ci
2857db96d56Sopenharmony_ci        self.assertEqual(signature(f),
2867db96d56Sopenharmony_ci                         (capture, (1,), dict(a=10), dict(attr=[])))
2877db96d56Sopenharmony_ci        self.assertEqual(f(2, b=20), ((1, 2), {'a': 10, 'b': 20}))
2887db96d56Sopenharmony_ci
2897db96d56Sopenharmony_ci        f.__setstate__((capture, (1,), dict(a=10), None))
2907db96d56Sopenharmony_ci
2917db96d56Sopenharmony_ci        self.assertEqual(signature(f), (capture, (1,), dict(a=10), {}))
2927db96d56Sopenharmony_ci        self.assertEqual(f(2, b=20), ((1, 2), {'a': 10, 'b': 20}))
2937db96d56Sopenharmony_ci
2947db96d56Sopenharmony_ci        f.__setstate__((capture, (1,), None, None))
2957db96d56Sopenharmony_ci        #self.assertEqual(signature(f), (capture, (1,), {}, {}))
2967db96d56Sopenharmony_ci        self.assertEqual(f(2, b=20), ((1, 2), {'b': 20}))
2977db96d56Sopenharmony_ci        self.assertEqual(f(2), ((1, 2), {}))
2987db96d56Sopenharmony_ci        self.assertEqual(f(), ((1,), {}))
2997db96d56Sopenharmony_ci
3007db96d56Sopenharmony_ci        f.__setstate__((capture, (), {}, None))
3017db96d56Sopenharmony_ci        self.assertEqual(signature(f), (capture, (), {}, {}))
3027db96d56Sopenharmony_ci        self.assertEqual(f(2, b=20), ((2,), {'b': 20}))
3037db96d56Sopenharmony_ci        self.assertEqual(f(2), ((2,), {}))
3047db96d56Sopenharmony_ci        self.assertEqual(f(), ((), {}))
3057db96d56Sopenharmony_ci
3067db96d56Sopenharmony_ci    def test_setstate_errors(self):
3077db96d56Sopenharmony_ci        f = self.partial(signature)
3087db96d56Sopenharmony_ci        self.assertRaises(TypeError, f.__setstate__, (capture, (), {}))
3097db96d56Sopenharmony_ci        self.assertRaises(TypeError, f.__setstate__, (capture, (), {}, {}, None))
3107db96d56Sopenharmony_ci        self.assertRaises(TypeError, f.__setstate__, [capture, (), {}, None])
3117db96d56Sopenharmony_ci        self.assertRaises(TypeError, f.__setstate__, (None, (), {}, None))
3127db96d56Sopenharmony_ci        self.assertRaises(TypeError, f.__setstate__, (capture, None, {}, None))
3137db96d56Sopenharmony_ci        self.assertRaises(TypeError, f.__setstate__, (capture, [], {}, None))
3147db96d56Sopenharmony_ci        self.assertRaises(TypeError, f.__setstate__, (capture, (), [], None))
3157db96d56Sopenharmony_ci
3167db96d56Sopenharmony_ci    def test_setstate_subclasses(self):
3177db96d56Sopenharmony_ci        f = self.partial(signature)
3187db96d56Sopenharmony_ci        f.__setstate__((capture, MyTuple((1,)), MyDict(a=10), None))
3197db96d56Sopenharmony_ci        s = signature(f)
3207db96d56Sopenharmony_ci        self.assertEqual(s, (capture, (1,), dict(a=10), {}))
3217db96d56Sopenharmony_ci        self.assertIs(type(s[1]), tuple)
3227db96d56Sopenharmony_ci        self.assertIs(type(s[2]), dict)
3237db96d56Sopenharmony_ci        r = f()
3247db96d56Sopenharmony_ci        self.assertEqual(r, ((1,), {'a': 10}))
3257db96d56Sopenharmony_ci        self.assertIs(type(r[0]), tuple)
3267db96d56Sopenharmony_ci        self.assertIs(type(r[1]), dict)
3277db96d56Sopenharmony_ci
3287db96d56Sopenharmony_ci        f.__setstate__((capture, BadTuple((1,)), {}, None))
3297db96d56Sopenharmony_ci        s = signature(f)
3307db96d56Sopenharmony_ci        self.assertEqual(s, (capture, (1,), {}, {}))
3317db96d56Sopenharmony_ci        self.assertIs(type(s[1]), tuple)
3327db96d56Sopenharmony_ci        r = f(2)
3337db96d56Sopenharmony_ci        self.assertEqual(r, ((1, 2), {}))
3347db96d56Sopenharmony_ci        self.assertIs(type(r[0]), tuple)
3357db96d56Sopenharmony_ci
3367db96d56Sopenharmony_ci    def test_recursive_pickle(self):
3377db96d56Sopenharmony_ci        with self.AllowPickle():
3387db96d56Sopenharmony_ci            f = self.partial(capture)
3397db96d56Sopenharmony_ci            f.__setstate__((f, (), {}, {}))
3407db96d56Sopenharmony_ci            try:
3417db96d56Sopenharmony_ci                for proto in range(pickle.HIGHEST_PROTOCOL + 1):
3427db96d56Sopenharmony_ci                    with self.assertRaises(RecursionError):
3437db96d56Sopenharmony_ci                        pickle.dumps(f, proto)
3447db96d56Sopenharmony_ci            finally:
3457db96d56Sopenharmony_ci                f.__setstate__((capture, (), {}, {}))
3467db96d56Sopenharmony_ci
3477db96d56Sopenharmony_ci            f = self.partial(capture)
3487db96d56Sopenharmony_ci            f.__setstate__((capture, (f,), {}, {}))
3497db96d56Sopenharmony_ci            try:
3507db96d56Sopenharmony_ci                for proto in range(pickle.HIGHEST_PROTOCOL + 1):
3517db96d56Sopenharmony_ci                    f_copy = pickle.loads(pickle.dumps(f, proto))
3527db96d56Sopenharmony_ci                    try:
3537db96d56Sopenharmony_ci                        self.assertIs(f_copy.args[0], f_copy)
3547db96d56Sopenharmony_ci                    finally:
3557db96d56Sopenharmony_ci                        f_copy.__setstate__((capture, (), {}, {}))
3567db96d56Sopenharmony_ci            finally:
3577db96d56Sopenharmony_ci                f.__setstate__((capture, (), {}, {}))
3587db96d56Sopenharmony_ci
3597db96d56Sopenharmony_ci            f = self.partial(capture)
3607db96d56Sopenharmony_ci            f.__setstate__((capture, (), {'a': f}, {}))
3617db96d56Sopenharmony_ci            try:
3627db96d56Sopenharmony_ci                for proto in range(pickle.HIGHEST_PROTOCOL + 1):
3637db96d56Sopenharmony_ci                    f_copy = pickle.loads(pickle.dumps(f, proto))
3647db96d56Sopenharmony_ci                    try:
3657db96d56Sopenharmony_ci                        self.assertIs(f_copy.keywords['a'], f_copy)
3667db96d56Sopenharmony_ci                    finally:
3677db96d56Sopenharmony_ci                        f_copy.__setstate__((capture, (), {}, {}))
3687db96d56Sopenharmony_ci            finally:
3697db96d56Sopenharmony_ci                f.__setstate__((capture, (), {}, {}))
3707db96d56Sopenharmony_ci
3717db96d56Sopenharmony_ci    # Issue 6083: Reference counting bug
3727db96d56Sopenharmony_ci    def test_setstate_refcount(self):
3737db96d56Sopenharmony_ci        class BadSequence:
3747db96d56Sopenharmony_ci            def __len__(self):
3757db96d56Sopenharmony_ci                return 4
3767db96d56Sopenharmony_ci            def __getitem__(self, key):
3777db96d56Sopenharmony_ci                if key == 0:
3787db96d56Sopenharmony_ci                    return max
3797db96d56Sopenharmony_ci                elif key == 1:
3807db96d56Sopenharmony_ci                    return tuple(range(1000000))
3817db96d56Sopenharmony_ci                elif key in (2, 3):
3827db96d56Sopenharmony_ci                    return {}
3837db96d56Sopenharmony_ci                raise IndexError
3847db96d56Sopenharmony_ci
3857db96d56Sopenharmony_ci        f = self.partial(object)
3867db96d56Sopenharmony_ci        self.assertRaises(TypeError, f.__setstate__, BadSequence())
3877db96d56Sopenharmony_ci
3887db96d56Sopenharmony_ci@unittest.skipUnless(c_functools, 'requires the C _functools module')
3897db96d56Sopenharmony_ciclass TestPartialC(TestPartial, unittest.TestCase):
3907db96d56Sopenharmony_ci    if c_functools:
3917db96d56Sopenharmony_ci        partial = c_functools.partial
3927db96d56Sopenharmony_ci
3937db96d56Sopenharmony_ci    class AllowPickle:
3947db96d56Sopenharmony_ci        def __enter__(self):
3957db96d56Sopenharmony_ci            return self
3967db96d56Sopenharmony_ci        def __exit__(self, type, value, tb):
3977db96d56Sopenharmony_ci            return False
3987db96d56Sopenharmony_ci
3997db96d56Sopenharmony_ci    def test_attributes_unwritable(self):
4007db96d56Sopenharmony_ci        # attributes should not be writable
4017db96d56Sopenharmony_ci        p = self.partial(capture, 1, 2, a=10, b=20)
4027db96d56Sopenharmony_ci        self.assertRaises(AttributeError, setattr, p, 'func', map)
4037db96d56Sopenharmony_ci        self.assertRaises(AttributeError, setattr, p, 'args', (1, 2))
4047db96d56Sopenharmony_ci        self.assertRaises(AttributeError, setattr, p, 'keywords', dict(a=1, b=2))
4057db96d56Sopenharmony_ci
4067db96d56Sopenharmony_ci        p = self.partial(hex)
4077db96d56Sopenharmony_ci        try:
4087db96d56Sopenharmony_ci            del p.__dict__
4097db96d56Sopenharmony_ci        except TypeError:
4107db96d56Sopenharmony_ci            pass
4117db96d56Sopenharmony_ci        else:
4127db96d56Sopenharmony_ci            self.fail('partial object allowed __dict__ to be deleted')
4137db96d56Sopenharmony_ci
4147db96d56Sopenharmony_ci    def test_manually_adding_non_string_keyword(self):
4157db96d56Sopenharmony_ci        p = self.partial(capture)
4167db96d56Sopenharmony_ci        # Adding a non-string/unicode keyword to partial kwargs
4177db96d56Sopenharmony_ci        p.keywords[1234] = 'value'
4187db96d56Sopenharmony_ci        r = repr(p)
4197db96d56Sopenharmony_ci        self.assertIn('1234', r)
4207db96d56Sopenharmony_ci        self.assertIn("'value'", r)
4217db96d56Sopenharmony_ci        with self.assertRaises(TypeError):
4227db96d56Sopenharmony_ci            p()
4237db96d56Sopenharmony_ci
4247db96d56Sopenharmony_ci    def test_keystr_replaces_value(self):
4257db96d56Sopenharmony_ci        p = self.partial(capture)
4267db96d56Sopenharmony_ci
4277db96d56Sopenharmony_ci        class MutatesYourDict(object):
4287db96d56Sopenharmony_ci            def __str__(self):
4297db96d56Sopenharmony_ci                p.keywords[self] = ['sth2']
4307db96d56Sopenharmony_ci                return 'astr'
4317db96d56Sopenharmony_ci
4327db96d56Sopenharmony_ci        # Replacing the value during key formatting should keep the original
4337db96d56Sopenharmony_ci        # value alive (at least long enough).
4347db96d56Sopenharmony_ci        p.keywords[MutatesYourDict()] = ['sth']
4357db96d56Sopenharmony_ci        r = repr(p)
4367db96d56Sopenharmony_ci        self.assertIn('astr', r)
4377db96d56Sopenharmony_ci        self.assertIn("['sth']", r)
4387db96d56Sopenharmony_ci
4397db96d56Sopenharmony_ci
4407db96d56Sopenharmony_ciclass TestPartialPy(TestPartial, unittest.TestCase):
4417db96d56Sopenharmony_ci    partial = py_functools.partial
4427db96d56Sopenharmony_ci
4437db96d56Sopenharmony_ci    class AllowPickle:
4447db96d56Sopenharmony_ci        def __init__(self):
4457db96d56Sopenharmony_ci            self._cm = replaced_module("functools", py_functools)
4467db96d56Sopenharmony_ci        def __enter__(self):
4477db96d56Sopenharmony_ci            return self._cm.__enter__()
4487db96d56Sopenharmony_ci        def __exit__(self, type, value, tb):
4497db96d56Sopenharmony_ci            return self._cm.__exit__(type, value, tb)
4507db96d56Sopenharmony_ci
4517db96d56Sopenharmony_ciif c_functools:
4527db96d56Sopenharmony_ci    class CPartialSubclass(c_functools.partial):
4537db96d56Sopenharmony_ci        pass
4547db96d56Sopenharmony_ci
4557db96d56Sopenharmony_ciclass PyPartialSubclass(py_functools.partial):
4567db96d56Sopenharmony_ci    pass
4577db96d56Sopenharmony_ci
4587db96d56Sopenharmony_ci@unittest.skipUnless(c_functools, 'requires the C _functools module')
4597db96d56Sopenharmony_ciclass TestPartialCSubclass(TestPartialC):
4607db96d56Sopenharmony_ci    if c_functools:
4617db96d56Sopenharmony_ci        partial = CPartialSubclass
4627db96d56Sopenharmony_ci
4637db96d56Sopenharmony_ci    # partial subclasses are not optimized for nested calls
4647db96d56Sopenharmony_ci    test_nested_optimization = None
4657db96d56Sopenharmony_ci
4667db96d56Sopenharmony_ciclass TestPartialPySubclass(TestPartialPy):
4677db96d56Sopenharmony_ci    partial = PyPartialSubclass
4687db96d56Sopenharmony_ci
4697db96d56Sopenharmony_ciclass TestPartialMethod(unittest.TestCase):
4707db96d56Sopenharmony_ci
4717db96d56Sopenharmony_ci    class A(object):
4727db96d56Sopenharmony_ci        nothing = functools.partialmethod(capture)
4737db96d56Sopenharmony_ci        positional = functools.partialmethod(capture, 1)
4747db96d56Sopenharmony_ci        keywords = functools.partialmethod(capture, a=2)
4757db96d56Sopenharmony_ci        both = functools.partialmethod(capture, 3, b=4)
4767db96d56Sopenharmony_ci        spec_keywords = functools.partialmethod(capture, self=1, func=2)
4777db96d56Sopenharmony_ci
4787db96d56Sopenharmony_ci        nested = functools.partialmethod(positional, 5)
4797db96d56Sopenharmony_ci
4807db96d56Sopenharmony_ci        over_partial = functools.partialmethod(functools.partial(capture, c=6), 7)
4817db96d56Sopenharmony_ci
4827db96d56Sopenharmony_ci        static = functools.partialmethod(staticmethod(capture), 8)
4837db96d56Sopenharmony_ci        cls = functools.partialmethod(classmethod(capture), d=9)
4847db96d56Sopenharmony_ci
4857db96d56Sopenharmony_ci    a = A()
4867db96d56Sopenharmony_ci
4877db96d56Sopenharmony_ci    def test_arg_combinations(self):
4887db96d56Sopenharmony_ci        self.assertEqual(self.a.nothing(), ((self.a,), {}))
4897db96d56Sopenharmony_ci        self.assertEqual(self.a.nothing(5), ((self.a, 5), {}))
4907db96d56Sopenharmony_ci        self.assertEqual(self.a.nothing(c=6), ((self.a,), {'c': 6}))
4917db96d56Sopenharmony_ci        self.assertEqual(self.a.nothing(5, c=6), ((self.a, 5), {'c': 6}))
4927db96d56Sopenharmony_ci
4937db96d56Sopenharmony_ci        self.assertEqual(self.a.positional(), ((self.a, 1), {}))
4947db96d56Sopenharmony_ci        self.assertEqual(self.a.positional(5), ((self.a, 1, 5), {}))
4957db96d56Sopenharmony_ci        self.assertEqual(self.a.positional(c=6), ((self.a, 1), {'c': 6}))
4967db96d56Sopenharmony_ci        self.assertEqual(self.a.positional(5, c=6), ((self.a, 1, 5), {'c': 6}))
4977db96d56Sopenharmony_ci
4987db96d56Sopenharmony_ci        self.assertEqual(self.a.keywords(), ((self.a,), {'a': 2}))
4997db96d56Sopenharmony_ci        self.assertEqual(self.a.keywords(5), ((self.a, 5), {'a': 2}))
5007db96d56Sopenharmony_ci        self.assertEqual(self.a.keywords(c=6), ((self.a,), {'a': 2, 'c': 6}))
5017db96d56Sopenharmony_ci        self.assertEqual(self.a.keywords(5, c=6), ((self.a, 5), {'a': 2, 'c': 6}))
5027db96d56Sopenharmony_ci
5037db96d56Sopenharmony_ci        self.assertEqual(self.a.both(), ((self.a, 3), {'b': 4}))
5047db96d56Sopenharmony_ci        self.assertEqual(self.a.both(5), ((self.a, 3, 5), {'b': 4}))
5057db96d56Sopenharmony_ci        self.assertEqual(self.a.both(c=6), ((self.a, 3), {'b': 4, 'c': 6}))
5067db96d56Sopenharmony_ci        self.assertEqual(self.a.both(5, c=6), ((self.a, 3, 5), {'b': 4, 'c': 6}))
5077db96d56Sopenharmony_ci
5087db96d56Sopenharmony_ci        self.assertEqual(self.A.both(self.a, 5, c=6), ((self.a, 3, 5), {'b': 4, 'c': 6}))
5097db96d56Sopenharmony_ci
5107db96d56Sopenharmony_ci        self.assertEqual(self.a.spec_keywords(), ((self.a,), {'self': 1, 'func': 2}))
5117db96d56Sopenharmony_ci
5127db96d56Sopenharmony_ci    def test_nested(self):
5137db96d56Sopenharmony_ci        self.assertEqual(self.a.nested(), ((self.a, 1, 5), {}))
5147db96d56Sopenharmony_ci        self.assertEqual(self.a.nested(6), ((self.a, 1, 5, 6), {}))
5157db96d56Sopenharmony_ci        self.assertEqual(self.a.nested(d=7), ((self.a, 1, 5), {'d': 7}))
5167db96d56Sopenharmony_ci        self.assertEqual(self.a.nested(6, d=7), ((self.a, 1, 5, 6), {'d': 7}))
5177db96d56Sopenharmony_ci
5187db96d56Sopenharmony_ci        self.assertEqual(self.A.nested(self.a, 6, d=7), ((self.a, 1, 5, 6), {'d': 7}))
5197db96d56Sopenharmony_ci
5207db96d56Sopenharmony_ci    def test_over_partial(self):
5217db96d56Sopenharmony_ci        self.assertEqual(self.a.over_partial(), ((self.a, 7), {'c': 6}))
5227db96d56Sopenharmony_ci        self.assertEqual(self.a.over_partial(5), ((self.a, 7, 5), {'c': 6}))
5237db96d56Sopenharmony_ci        self.assertEqual(self.a.over_partial(d=8), ((self.a, 7), {'c': 6, 'd': 8}))
5247db96d56Sopenharmony_ci        self.assertEqual(self.a.over_partial(5, d=8), ((self.a, 7, 5), {'c': 6, 'd': 8}))
5257db96d56Sopenharmony_ci
5267db96d56Sopenharmony_ci        self.assertEqual(self.A.over_partial(self.a, 5, d=8), ((self.a, 7, 5), {'c': 6, 'd': 8}))
5277db96d56Sopenharmony_ci
5287db96d56Sopenharmony_ci    def test_bound_method_introspection(self):
5297db96d56Sopenharmony_ci        obj = self.a
5307db96d56Sopenharmony_ci        self.assertIs(obj.both.__self__, obj)
5317db96d56Sopenharmony_ci        self.assertIs(obj.nested.__self__, obj)
5327db96d56Sopenharmony_ci        self.assertIs(obj.over_partial.__self__, obj)
5337db96d56Sopenharmony_ci        self.assertIs(obj.cls.__self__, self.A)
5347db96d56Sopenharmony_ci        self.assertIs(self.A.cls.__self__, self.A)
5357db96d56Sopenharmony_ci
5367db96d56Sopenharmony_ci    def test_unbound_method_retrieval(self):
5377db96d56Sopenharmony_ci        obj = self.A
5387db96d56Sopenharmony_ci        self.assertFalse(hasattr(obj.both, "__self__"))
5397db96d56Sopenharmony_ci        self.assertFalse(hasattr(obj.nested, "__self__"))
5407db96d56Sopenharmony_ci        self.assertFalse(hasattr(obj.over_partial, "__self__"))
5417db96d56Sopenharmony_ci        self.assertFalse(hasattr(obj.static, "__self__"))
5427db96d56Sopenharmony_ci        self.assertFalse(hasattr(self.a.static, "__self__"))
5437db96d56Sopenharmony_ci
5447db96d56Sopenharmony_ci    def test_descriptors(self):
5457db96d56Sopenharmony_ci        for obj in [self.A, self.a]:
5467db96d56Sopenharmony_ci            with self.subTest(obj=obj):
5477db96d56Sopenharmony_ci                self.assertEqual(obj.static(), ((8,), {}))
5487db96d56Sopenharmony_ci                self.assertEqual(obj.static(5), ((8, 5), {}))
5497db96d56Sopenharmony_ci                self.assertEqual(obj.static(d=8), ((8,), {'d': 8}))
5507db96d56Sopenharmony_ci                self.assertEqual(obj.static(5, d=8), ((8, 5), {'d': 8}))
5517db96d56Sopenharmony_ci
5527db96d56Sopenharmony_ci                self.assertEqual(obj.cls(), ((self.A,), {'d': 9}))
5537db96d56Sopenharmony_ci                self.assertEqual(obj.cls(5), ((self.A, 5), {'d': 9}))
5547db96d56Sopenharmony_ci                self.assertEqual(obj.cls(c=8), ((self.A,), {'c': 8, 'd': 9}))
5557db96d56Sopenharmony_ci                self.assertEqual(obj.cls(5, c=8), ((self.A, 5), {'c': 8, 'd': 9}))
5567db96d56Sopenharmony_ci
5577db96d56Sopenharmony_ci    def test_overriding_keywords(self):
5587db96d56Sopenharmony_ci        self.assertEqual(self.a.keywords(a=3), ((self.a,), {'a': 3}))
5597db96d56Sopenharmony_ci        self.assertEqual(self.A.keywords(self.a, a=3), ((self.a,), {'a': 3}))
5607db96d56Sopenharmony_ci
5617db96d56Sopenharmony_ci    def test_invalid_args(self):
5627db96d56Sopenharmony_ci        with self.assertRaises(TypeError):
5637db96d56Sopenharmony_ci            class B(object):
5647db96d56Sopenharmony_ci                method = functools.partialmethod(None, 1)
5657db96d56Sopenharmony_ci        with self.assertRaises(TypeError):
5667db96d56Sopenharmony_ci            class B:
5677db96d56Sopenharmony_ci                method = functools.partialmethod()
5687db96d56Sopenharmony_ci        with self.assertRaises(TypeError):
5697db96d56Sopenharmony_ci            class B:
5707db96d56Sopenharmony_ci                method = functools.partialmethod(func=capture, a=1)
5717db96d56Sopenharmony_ci
5727db96d56Sopenharmony_ci    def test_repr(self):
5737db96d56Sopenharmony_ci        self.assertEqual(repr(vars(self.A)['both']),
5747db96d56Sopenharmony_ci                         'functools.partialmethod({}, 3, b=4)'.format(capture))
5757db96d56Sopenharmony_ci
5767db96d56Sopenharmony_ci    def test_abstract(self):
5777db96d56Sopenharmony_ci        class Abstract(abc.ABCMeta):
5787db96d56Sopenharmony_ci
5797db96d56Sopenharmony_ci            @abc.abstractmethod
5807db96d56Sopenharmony_ci            def add(self, x, y):
5817db96d56Sopenharmony_ci                pass
5827db96d56Sopenharmony_ci
5837db96d56Sopenharmony_ci            add5 = functools.partialmethod(add, 5)
5847db96d56Sopenharmony_ci
5857db96d56Sopenharmony_ci        self.assertTrue(Abstract.add.__isabstractmethod__)
5867db96d56Sopenharmony_ci        self.assertTrue(Abstract.add5.__isabstractmethod__)
5877db96d56Sopenharmony_ci
5887db96d56Sopenharmony_ci        for func in [self.A.static, self.A.cls, self.A.over_partial, self.A.nested, self.A.both]:
5897db96d56Sopenharmony_ci            self.assertFalse(getattr(func, '__isabstractmethod__', False))
5907db96d56Sopenharmony_ci
5917db96d56Sopenharmony_ci    def test_positional_only(self):
5927db96d56Sopenharmony_ci        def f(a, b, /):
5937db96d56Sopenharmony_ci            return a + b
5947db96d56Sopenharmony_ci
5957db96d56Sopenharmony_ci        p = functools.partial(f, 1)
5967db96d56Sopenharmony_ci        self.assertEqual(p(2), f(1, 2))
5977db96d56Sopenharmony_ci
5987db96d56Sopenharmony_ci
5997db96d56Sopenharmony_ciclass TestUpdateWrapper(unittest.TestCase):
6007db96d56Sopenharmony_ci
6017db96d56Sopenharmony_ci    def check_wrapper(self, wrapper, wrapped,
6027db96d56Sopenharmony_ci                      assigned=functools.WRAPPER_ASSIGNMENTS,
6037db96d56Sopenharmony_ci                      updated=functools.WRAPPER_UPDATES):
6047db96d56Sopenharmony_ci        # Check attributes were assigned
6057db96d56Sopenharmony_ci        for name in assigned:
6067db96d56Sopenharmony_ci            self.assertIs(getattr(wrapper, name), getattr(wrapped, name))
6077db96d56Sopenharmony_ci        # Check attributes were updated
6087db96d56Sopenharmony_ci        for name in updated:
6097db96d56Sopenharmony_ci            wrapper_attr = getattr(wrapper, name)
6107db96d56Sopenharmony_ci            wrapped_attr = getattr(wrapped, name)
6117db96d56Sopenharmony_ci            for key in wrapped_attr:
6127db96d56Sopenharmony_ci                if name == "__dict__" and key == "__wrapped__":
6137db96d56Sopenharmony_ci                    # __wrapped__ is overwritten by the update code
6147db96d56Sopenharmony_ci                    continue
6157db96d56Sopenharmony_ci                self.assertIs(wrapped_attr[key], wrapper_attr[key])
6167db96d56Sopenharmony_ci        # Check __wrapped__
6177db96d56Sopenharmony_ci        self.assertIs(wrapper.__wrapped__, wrapped)
6187db96d56Sopenharmony_ci
6197db96d56Sopenharmony_ci
6207db96d56Sopenharmony_ci    def _default_update(self):
6217db96d56Sopenharmony_ci        def f(a:'This is a new annotation'):
6227db96d56Sopenharmony_ci            """This is a test"""
6237db96d56Sopenharmony_ci            pass
6247db96d56Sopenharmony_ci        f.attr = 'This is also a test'
6257db96d56Sopenharmony_ci        f.__wrapped__ = "This is a bald faced lie"
6267db96d56Sopenharmony_ci        def wrapper(b:'This is the prior annotation'):
6277db96d56Sopenharmony_ci            pass
6287db96d56Sopenharmony_ci        functools.update_wrapper(wrapper, f)
6297db96d56Sopenharmony_ci        return wrapper, f
6307db96d56Sopenharmony_ci
6317db96d56Sopenharmony_ci    def test_default_update(self):
6327db96d56Sopenharmony_ci        wrapper, f = self._default_update()
6337db96d56Sopenharmony_ci        self.check_wrapper(wrapper, f)
6347db96d56Sopenharmony_ci        self.assertIs(wrapper.__wrapped__, f)
6357db96d56Sopenharmony_ci        self.assertEqual(wrapper.__name__, 'f')
6367db96d56Sopenharmony_ci        self.assertEqual(wrapper.__qualname__, f.__qualname__)
6377db96d56Sopenharmony_ci        self.assertEqual(wrapper.attr, 'This is also a test')
6387db96d56Sopenharmony_ci        self.assertEqual(wrapper.__annotations__['a'], 'This is a new annotation')
6397db96d56Sopenharmony_ci        self.assertNotIn('b', wrapper.__annotations__)
6407db96d56Sopenharmony_ci
6417db96d56Sopenharmony_ci    @unittest.skipIf(sys.flags.optimize >= 2,
6427db96d56Sopenharmony_ci                     "Docstrings are omitted with -O2 and above")
6437db96d56Sopenharmony_ci    def test_default_update_doc(self):
6447db96d56Sopenharmony_ci        wrapper, f = self._default_update()
6457db96d56Sopenharmony_ci        self.assertEqual(wrapper.__doc__, 'This is a test')
6467db96d56Sopenharmony_ci
6477db96d56Sopenharmony_ci    def test_no_update(self):
6487db96d56Sopenharmony_ci        def f():
6497db96d56Sopenharmony_ci            """This is a test"""
6507db96d56Sopenharmony_ci            pass
6517db96d56Sopenharmony_ci        f.attr = 'This is also a test'
6527db96d56Sopenharmony_ci        def wrapper():
6537db96d56Sopenharmony_ci            pass
6547db96d56Sopenharmony_ci        functools.update_wrapper(wrapper, f, (), ())
6557db96d56Sopenharmony_ci        self.check_wrapper(wrapper, f, (), ())
6567db96d56Sopenharmony_ci        self.assertEqual(wrapper.__name__, 'wrapper')
6577db96d56Sopenharmony_ci        self.assertNotEqual(wrapper.__qualname__, f.__qualname__)
6587db96d56Sopenharmony_ci        self.assertEqual(wrapper.__doc__, None)
6597db96d56Sopenharmony_ci        self.assertEqual(wrapper.__annotations__, {})
6607db96d56Sopenharmony_ci        self.assertFalse(hasattr(wrapper, 'attr'))
6617db96d56Sopenharmony_ci
6627db96d56Sopenharmony_ci    def test_selective_update(self):
6637db96d56Sopenharmony_ci        def f():
6647db96d56Sopenharmony_ci            pass
6657db96d56Sopenharmony_ci        f.attr = 'This is a different test'
6667db96d56Sopenharmony_ci        f.dict_attr = dict(a=1, b=2, c=3)
6677db96d56Sopenharmony_ci        def wrapper():
6687db96d56Sopenharmony_ci            pass
6697db96d56Sopenharmony_ci        wrapper.dict_attr = {}
6707db96d56Sopenharmony_ci        assign = ('attr',)
6717db96d56Sopenharmony_ci        update = ('dict_attr',)
6727db96d56Sopenharmony_ci        functools.update_wrapper(wrapper, f, assign, update)
6737db96d56Sopenharmony_ci        self.check_wrapper(wrapper, f, assign, update)
6747db96d56Sopenharmony_ci        self.assertEqual(wrapper.__name__, 'wrapper')
6757db96d56Sopenharmony_ci        self.assertNotEqual(wrapper.__qualname__, f.__qualname__)
6767db96d56Sopenharmony_ci        self.assertEqual(wrapper.__doc__, None)
6777db96d56Sopenharmony_ci        self.assertEqual(wrapper.attr, 'This is a different test')
6787db96d56Sopenharmony_ci        self.assertEqual(wrapper.dict_attr, f.dict_attr)
6797db96d56Sopenharmony_ci
6807db96d56Sopenharmony_ci    def test_missing_attributes(self):
6817db96d56Sopenharmony_ci        def f():
6827db96d56Sopenharmony_ci            pass
6837db96d56Sopenharmony_ci        def wrapper():
6847db96d56Sopenharmony_ci            pass
6857db96d56Sopenharmony_ci        wrapper.dict_attr = {}
6867db96d56Sopenharmony_ci        assign = ('attr',)
6877db96d56Sopenharmony_ci        update = ('dict_attr',)
6887db96d56Sopenharmony_ci        # Missing attributes on wrapped object are ignored
6897db96d56Sopenharmony_ci        functools.update_wrapper(wrapper, f, assign, update)
6907db96d56Sopenharmony_ci        self.assertNotIn('attr', wrapper.__dict__)
6917db96d56Sopenharmony_ci        self.assertEqual(wrapper.dict_attr, {})
6927db96d56Sopenharmony_ci        # Wrapper must have expected attributes for updating
6937db96d56Sopenharmony_ci        del wrapper.dict_attr
6947db96d56Sopenharmony_ci        with self.assertRaises(AttributeError):
6957db96d56Sopenharmony_ci            functools.update_wrapper(wrapper, f, assign, update)
6967db96d56Sopenharmony_ci        wrapper.dict_attr = 1
6977db96d56Sopenharmony_ci        with self.assertRaises(AttributeError):
6987db96d56Sopenharmony_ci            functools.update_wrapper(wrapper, f, assign, update)
6997db96d56Sopenharmony_ci
7007db96d56Sopenharmony_ci    @support.requires_docstrings
7017db96d56Sopenharmony_ci    @unittest.skipIf(sys.flags.optimize >= 2,
7027db96d56Sopenharmony_ci                     "Docstrings are omitted with -O2 and above")
7037db96d56Sopenharmony_ci    def test_builtin_update(self):
7047db96d56Sopenharmony_ci        # Test for bug #1576241
7057db96d56Sopenharmony_ci        def wrapper():
7067db96d56Sopenharmony_ci            pass
7077db96d56Sopenharmony_ci        functools.update_wrapper(wrapper, max)
7087db96d56Sopenharmony_ci        self.assertEqual(wrapper.__name__, 'max')
7097db96d56Sopenharmony_ci        self.assertTrue(wrapper.__doc__.startswith('max('))
7107db96d56Sopenharmony_ci        self.assertEqual(wrapper.__annotations__, {})
7117db96d56Sopenharmony_ci
7127db96d56Sopenharmony_ci
7137db96d56Sopenharmony_ciclass TestWraps(TestUpdateWrapper):
7147db96d56Sopenharmony_ci
7157db96d56Sopenharmony_ci    def _default_update(self):
7167db96d56Sopenharmony_ci        def f():
7177db96d56Sopenharmony_ci            """This is a test"""
7187db96d56Sopenharmony_ci            pass
7197db96d56Sopenharmony_ci        f.attr = 'This is also a test'
7207db96d56Sopenharmony_ci        f.__wrapped__ = "This is still a bald faced lie"
7217db96d56Sopenharmony_ci        @functools.wraps(f)
7227db96d56Sopenharmony_ci        def wrapper():
7237db96d56Sopenharmony_ci            pass
7247db96d56Sopenharmony_ci        return wrapper, f
7257db96d56Sopenharmony_ci
7267db96d56Sopenharmony_ci    def test_default_update(self):
7277db96d56Sopenharmony_ci        wrapper, f = self._default_update()
7287db96d56Sopenharmony_ci        self.check_wrapper(wrapper, f)
7297db96d56Sopenharmony_ci        self.assertEqual(wrapper.__name__, 'f')
7307db96d56Sopenharmony_ci        self.assertEqual(wrapper.__qualname__, f.__qualname__)
7317db96d56Sopenharmony_ci        self.assertEqual(wrapper.attr, 'This is also a test')
7327db96d56Sopenharmony_ci
7337db96d56Sopenharmony_ci    @unittest.skipIf(sys.flags.optimize >= 2,
7347db96d56Sopenharmony_ci                     "Docstrings are omitted with -O2 and above")
7357db96d56Sopenharmony_ci    def test_default_update_doc(self):
7367db96d56Sopenharmony_ci        wrapper, _ = self._default_update()
7377db96d56Sopenharmony_ci        self.assertEqual(wrapper.__doc__, 'This is a test')
7387db96d56Sopenharmony_ci
7397db96d56Sopenharmony_ci    def test_no_update(self):
7407db96d56Sopenharmony_ci        def f():
7417db96d56Sopenharmony_ci            """This is a test"""
7427db96d56Sopenharmony_ci            pass
7437db96d56Sopenharmony_ci        f.attr = 'This is also a test'
7447db96d56Sopenharmony_ci        @functools.wraps(f, (), ())
7457db96d56Sopenharmony_ci        def wrapper():
7467db96d56Sopenharmony_ci            pass
7477db96d56Sopenharmony_ci        self.check_wrapper(wrapper, f, (), ())
7487db96d56Sopenharmony_ci        self.assertEqual(wrapper.__name__, 'wrapper')
7497db96d56Sopenharmony_ci        self.assertNotEqual(wrapper.__qualname__, f.__qualname__)
7507db96d56Sopenharmony_ci        self.assertEqual(wrapper.__doc__, None)
7517db96d56Sopenharmony_ci        self.assertFalse(hasattr(wrapper, 'attr'))
7527db96d56Sopenharmony_ci
7537db96d56Sopenharmony_ci    def test_selective_update(self):
7547db96d56Sopenharmony_ci        def f():
7557db96d56Sopenharmony_ci            pass
7567db96d56Sopenharmony_ci        f.attr = 'This is a different test'
7577db96d56Sopenharmony_ci        f.dict_attr = dict(a=1, b=2, c=3)
7587db96d56Sopenharmony_ci        def add_dict_attr(f):
7597db96d56Sopenharmony_ci            f.dict_attr = {}
7607db96d56Sopenharmony_ci            return f
7617db96d56Sopenharmony_ci        assign = ('attr',)
7627db96d56Sopenharmony_ci        update = ('dict_attr',)
7637db96d56Sopenharmony_ci        @functools.wraps(f, assign, update)
7647db96d56Sopenharmony_ci        @add_dict_attr
7657db96d56Sopenharmony_ci        def wrapper():
7667db96d56Sopenharmony_ci            pass
7677db96d56Sopenharmony_ci        self.check_wrapper(wrapper, f, assign, update)
7687db96d56Sopenharmony_ci        self.assertEqual(wrapper.__name__, 'wrapper')
7697db96d56Sopenharmony_ci        self.assertNotEqual(wrapper.__qualname__, f.__qualname__)
7707db96d56Sopenharmony_ci        self.assertEqual(wrapper.__doc__, None)
7717db96d56Sopenharmony_ci        self.assertEqual(wrapper.attr, 'This is a different test')
7727db96d56Sopenharmony_ci        self.assertEqual(wrapper.dict_attr, f.dict_attr)
7737db96d56Sopenharmony_ci
7747db96d56Sopenharmony_ci
7757db96d56Sopenharmony_ciclass TestReduce:
7767db96d56Sopenharmony_ci    def test_reduce(self):
7777db96d56Sopenharmony_ci        class Squares:
7787db96d56Sopenharmony_ci            def __init__(self, max):
7797db96d56Sopenharmony_ci                self.max = max
7807db96d56Sopenharmony_ci                self.sofar = []
7817db96d56Sopenharmony_ci
7827db96d56Sopenharmony_ci            def __len__(self):
7837db96d56Sopenharmony_ci                return len(self.sofar)
7847db96d56Sopenharmony_ci
7857db96d56Sopenharmony_ci            def __getitem__(self, i):
7867db96d56Sopenharmony_ci                if not 0 <= i < self.max: raise IndexError
7877db96d56Sopenharmony_ci                n = len(self.sofar)
7887db96d56Sopenharmony_ci                while n <= i:
7897db96d56Sopenharmony_ci                    self.sofar.append(n*n)
7907db96d56Sopenharmony_ci                    n += 1
7917db96d56Sopenharmony_ci                return self.sofar[i]
7927db96d56Sopenharmony_ci        def add(x, y):
7937db96d56Sopenharmony_ci            return x + y
7947db96d56Sopenharmony_ci        self.assertEqual(self.reduce(add, ['a', 'b', 'c'], ''), 'abc')
7957db96d56Sopenharmony_ci        self.assertEqual(
7967db96d56Sopenharmony_ci            self.reduce(add, [['a', 'c'], [], ['d', 'w']], []),
7977db96d56Sopenharmony_ci            ['a','c','d','w']
7987db96d56Sopenharmony_ci        )
7997db96d56Sopenharmony_ci        self.assertEqual(self.reduce(lambda x, y: x*y, range(2,8), 1), 5040)
8007db96d56Sopenharmony_ci        self.assertEqual(
8017db96d56Sopenharmony_ci            self.reduce(lambda x, y: x*y, range(2,21), 1),
8027db96d56Sopenharmony_ci            2432902008176640000
8037db96d56Sopenharmony_ci        )
8047db96d56Sopenharmony_ci        self.assertEqual(self.reduce(add, Squares(10)), 285)
8057db96d56Sopenharmony_ci        self.assertEqual(self.reduce(add, Squares(10), 0), 285)
8067db96d56Sopenharmony_ci        self.assertEqual(self.reduce(add, Squares(0), 0), 0)
8077db96d56Sopenharmony_ci        self.assertRaises(TypeError, self.reduce)
8087db96d56Sopenharmony_ci        self.assertRaises(TypeError, self.reduce, 42, 42)
8097db96d56Sopenharmony_ci        self.assertRaises(TypeError, self.reduce, 42, 42, 42)
8107db96d56Sopenharmony_ci        self.assertEqual(self.reduce(42, "1"), "1") # func is never called with one item
8117db96d56Sopenharmony_ci        self.assertEqual(self.reduce(42, "", "1"), "1") # func is never called with one item
8127db96d56Sopenharmony_ci        self.assertRaises(TypeError, self.reduce, 42, (42, 42))
8137db96d56Sopenharmony_ci        self.assertRaises(TypeError, self.reduce, add, []) # arg 2 must not be empty sequence with no initial value
8147db96d56Sopenharmony_ci        self.assertRaises(TypeError, self.reduce, add, "")
8157db96d56Sopenharmony_ci        self.assertRaises(TypeError, self.reduce, add, ())
8167db96d56Sopenharmony_ci        self.assertRaises(TypeError, self.reduce, add, object())
8177db96d56Sopenharmony_ci
8187db96d56Sopenharmony_ci        class TestFailingIter:
8197db96d56Sopenharmony_ci            def __iter__(self):
8207db96d56Sopenharmony_ci                raise RuntimeError
8217db96d56Sopenharmony_ci        self.assertRaises(RuntimeError, self.reduce, add, TestFailingIter())
8227db96d56Sopenharmony_ci
8237db96d56Sopenharmony_ci        self.assertEqual(self.reduce(add, [], None), None)
8247db96d56Sopenharmony_ci        self.assertEqual(self.reduce(add, [], 42), 42)
8257db96d56Sopenharmony_ci
8267db96d56Sopenharmony_ci        class BadSeq:
8277db96d56Sopenharmony_ci            def __getitem__(self, index):
8287db96d56Sopenharmony_ci                raise ValueError
8297db96d56Sopenharmony_ci        self.assertRaises(ValueError, self.reduce, 42, BadSeq())
8307db96d56Sopenharmony_ci
8317db96d56Sopenharmony_ci    # Test reduce()'s use of iterators.
8327db96d56Sopenharmony_ci    def test_iterator_usage(self):
8337db96d56Sopenharmony_ci        class SequenceClass:
8347db96d56Sopenharmony_ci            def __init__(self, n):
8357db96d56Sopenharmony_ci                self.n = n
8367db96d56Sopenharmony_ci            def __getitem__(self, i):
8377db96d56Sopenharmony_ci                if 0 <= i < self.n:
8387db96d56Sopenharmony_ci                    return i
8397db96d56Sopenharmony_ci                else:
8407db96d56Sopenharmony_ci                    raise IndexError
8417db96d56Sopenharmony_ci
8427db96d56Sopenharmony_ci        from operator import add
8437db96d56Sopenharmony_ci        self.assertEqual(self.reduce(add, SequenceClass(5)), 10)
8447db96d56Sopenharmony_ci        self.assertEqual(self.reduce(add, SequenceClass(5), 42), 52)
8457db96d56Sopenharmony_ci        self.assertRaises(TypeError, self.reduce, add, SequenceClass(0))
8467db96d56Sopenharmony_ci        self.assertEqual(self.reduce(add, SequenceClass(0), 42), 42)
8477db96d56Sopenharmony_ci        self.assertEqual(self.reduce(add, SequenceClass(1)), 0)
8487db96d56Sopenharmony_ci        self.assertEqual(self.reduce(add, SequenceClass(1), 42), 42)
8497db96d56Sopenharmony_ci
8507db96d56Sopenharmony_ci        d = {"one": 1, "two": 2, "three": 3}
8517db96d56Sopenharmony_ci        self.assertEqual(self.reduce(add, d), "".join(d.keys()))
8527db96d56Sopenharmony_ci
8537db96d56Sopenharmony_ci
8547db96d56Sopenharmony_ci@unittest.skipUnless(c_functools, 'requires the C _functools module')
8557db96d56Sopenharmony_ciclass TestReduceC(TestReduce, unittest.TestCase):
8567db96d56Sopenharmony_ci    if c_functools:
8577db96d56Sopenharmony_ci        reduce = c_functools.reduce
8587db96d56Sopenharmony_ci
8597db96d56Sopenharmony_ci
8607db96d56Sopenharmony_ciclass TestReducePy(TestReduce, unittest.TestCase):
8617db96d56Sopenharmony_ci    reduce = staticmethod(py_functools.reduce)
8627db96d56Sopenharmony_ci
8637db96d56Sopenharmony_ci
8647db96d56Sopenharmony_ciclass TestCmpToKey:
8657db96d56Sopenharmony_ci
8667db96d56Sopenharmony_ci    def test_cmp_to_key(self):
8677db96d56Sopenharmony_ci        def cmp1(x, y):
8687db96d56Sopenharmony_ci            return (x > y) - (x < y)
8697db96d56Sopenharmony_ci        key = self.cmp_to_key(cmp1)
8707db96d56Sopenharmony_ci        self.assertEqual(key(3), key(3))
8717db96d56Sopenharmony_ci        self.assertGreater(key(3), key(1))
8727db96d56Sopenharmony_ci        self.assertGreaterEqual(key(3), key(3))
8737db96d56Sopenharmony_ci
8747db96d56Sopenharmony_ci        def cmp2(x, y):
8757db96d56Sopenharmony_ci            return int(x) - int(y)
8767db96d56Sopenharmony_ci        key = self.cmp_to_key(cmp2)
8777db96d56Sopenharmony_ci        self.assertEqual(key(4.0), key('4'))
8787db96d56Sopenharmony_ci        self.assertLess(key(2), key('35'))
8797db96d56Sopenharmony_ci        self.assertLessEqual(key(2), key('35'))
8807db96d56Sopenharmony_ci        self.assertNotEqual(key(2), key('35'))
8817db96d56Sopenharmony_ci
8827db96d56Sopenharmony_ci    def test_cmp_to_key_arguments(self):
8837db96d56Sopenharmony_ci        def cmp1(x, y):
8847db96d56Sopenharmony_ci            return (x > y) - (x < y)
8857db96d56Sopenharmony_ci        key = self.cmp_to_key(mycmp=cmp1)
8867db96d56Sopenharmony_ci        self.assertEqual(key(obj=3), key(obj=3))
8877db96d56Sopenharmony_ci        self.assertGreater(key(obj=3), key(obj=1))
8887db96d56Sopenharmony_ci        with self.assertRaises((TypeError, AttributeError)):
8897db96d56Sopenharmony_ci            key(3) > 1    # rhs is not a K object
8907db96d56Sopenharmony_ci        with self.assertRaises((TypeError, AttributeError)):
8917db96d56Sopenharmony_ci            1 < key(3)    # lhs is not a K object
8927db96d56Sopenharmony_ci        with self.assertRaises(TypeError):
8937db96d56Sopenharmony_ci            key = self.cmp_to_key()             # too few args
8947db96d56Sopenharmony_ci        with self.assertRaises(TypeError):
8957db96d56Sopenharmony_ci            key = self.cmp_to_key(cmp1, None)   # too many args
8967db96d56Sopenharmony_ci        key = self.cmp_to_key(cmp1)
8977db96d56Sopenharmony_ci        with self.assertRaises(TypeError):
8987db96d56Sopenharmony_ci            key()                                    # too few args
8997db96d56Sopenharmony_ci        with self.assertRaises(TypeError):
9007db96d56Sopenharmony_ci            key(None, None)                          # too many args
9017db96d56Sopenharmony_ci
9027db96d56Sopenharmony_ci    def test_bad_cmp(self):
9037db96d56Sopenharmony_ci        def cmp1(x, y):
9047db96d56Sopenharmony_ci            raise ZeroDivisionError
9057db96d56Sopenharmony_ci        key = self.cmp_to_key(cmp1)
9067db96d56Sopenharmony_ci        with self.assertRaises(ZeroDivisionError):
9077db96d56Sopenharmony_ci            key(3) > key(1)
9087db96d56Sopenharmony_ci
9097db96d56Sopenharmony_ci        class BadCmp:
9107db96d56Sopenharmony_ci            def __lt__(self, other):
9117db96d56Sopenharmony_ci                raise ZeroDivisionError
9127db96d56Sopenharmony_ci        def cmp1(x, y):
9137db96d56Sopenharmony_ci            return BadCmp()
9147db96d56Sopenharmony_ci        with self.assertRaises(ZeroDivisionError):
9157db96d56Sopenharmony_ci            key(3) > key(1)
9167db96d56Sopenharmony_ci
9177db96d56Sopenharmony_ci    def test_obj_field(self):
9187db96d56Sopenharmony_ci        def cmp1(x, y):
9197db96d56Sopenharmony_ci            return (x > y) - (x < y)
9207db96d56Sopenharmony_ci        key = self.cmp_to_key(mycmp=cmp1)
9217db96d56Sopenharmony_ci        self.assertEqual(key(50).obj, 50)
9227db96d56Sopenharmony_ci
9237db96d56Sopenharmony_ci    def test_sort_int(self):
9247db96d56Sopenharmony_ci        def mycmp(x, y):
9257db96d56Sopenharmony_ci            return y - x
9267db96d56Sopenharmony_ci        self.assertEqual(sorted(range(5), key=self.cmp_to_key(mycmp)),
9277db96d56Sopenharmony_ci                         [4, 3, 2, 1, 0])
9287db96d56Sopenharmony_ci
9297db96d56Sopenharmony_ci    def test_sort_int_str(self):
9307db96d56Sopenharmony_ci        def mycmp(x, y):
9317db96d56Sopenharmony_ci            x, y = int(x), int(y)
9327db96d56Sopenharmony_ci            return (x > y) - (x < y)
9337db96d56Sopenharmony_ci        values = [5, '3', 7, 2, '0', '1', 4, '10', 1]
9347db96d56Sopenharmony_ci        values = sorted(values, key=self.cmp_to_key(mycmp))
9357db96d56Sopenharmony_ci        self.assertEqual([int(value) for value in values],
9367db96d56Sopenharmony_ci                         [0, 1, 1, 2, 3, 4, 5, 7, 10])
9377db96d56Sopenharmony_ci
9387db96d56Sopenharmony_ci    def test_hash(self):
9397db96d56Sopenharmony_ci        def mycmp(x, y):
9407db96d56Sopenharmony_ci            return y - x
9417db96d56Sopenharmony_ci        key = self.cmp_to_key(mycmp)
9427db96d56Sopenharmony_ci        k = key(10)
9437db96d56Sopenharmony_ci        self.assertRaises(TypeError, hash, k)
9447db96d56Sopenharmony_ci        self.assertNotIsInstance(k, collections.abc.Hashable)
9457db96d56Sopenharmony_ci
9467db96d56Sopenharmony_ci
9477db96d56Sopenharmony_ci@unittest.skipUnless(c_functools, 'requires the C _functools module')
9487db96d56Sopenharmony_ciclass TestCmpToKeyC(TestCmpToKey, unittest.TestCase):
9497db96d56Sopenharmony_ci    if c_functools:
9507db96d56Sopenharmony_ci        cmp_to_key = c_functools.cmp_to_key
9517db96d56Sopenharmony_ci
9527db96d56Sopenharmony_ci    @support.cpython_only
9537db96d56Sopenharmony_ci    def test_disallow_instantiation(self):
9547db96d56Sopenharmony_ci        # Ensure that the type disallows instantiation (bpo-43916)
9557db96d56Sopenharmony_ci        support.check_disallow_instantiation(
9567db96d56Sopenharmony_ci            self, type(c_functools.cmp_to_key(None))
9577db96d56Sopenharmony_ci        )
9587db96d56Sopenharmony_ci
9597db96d56Sopenharmony_ci
9607db96d56Sopenharmony_ciclass TestCmpToKeyPy(TestCmpToKey, unittest.TestCase):
9617db96d56Sopenharmony_ci    cmp_to_key = staticmethod(py_functools.cmp_to_key)
9627db96d56Sopenharmony_ci
9637db96d56Sopenharmony_ci
9647db96d56Sopenharmony_ciclass TestTotalOrdering(unittest.TestCase):
9657db96d56Sopenharmony_ci
9667db96d56Sopenharmony_ci    def test_total_ordering_lt(self):
9677db96d56Sopenharmony_ci        @functools.total_ordering
9687db96d56Sopenharmony_ci        class A:
9697db96d56Sopenharmony_ci            def __init__(self, value):
9707db96d56Sopenharmony_ci                self.value = value
9717db96d56Sopenharmony_ci            def __lt__(self, other):
9727db96d56Sopenharmony_ci                return self.value < other.value
9737db96d56Sopenharmony_ci            def __eq__(self, other):
9747db96d56Sopenharmony_ci                return self.value == other.value
9757db96d56Sopenharmony_ci        self.assertTrue(A(1) < A(2))
9767db96d56Sopenharmony_ci        self.assertTrue(A(2) > A(1))
9777db96d56Sopenharmony_ci        self.assertTrue(A(1) <= A(2))
9787db96d56Sopenharmony_ci        self.assertTrue(A(2) >= A(1))
9797db96d56Sopenharmony_ci        self.assertTrue(A(2) <= A(2))
9807db96d56Sopenharmony_ci        self.assertTrue(A(2) >= A(2))
9817db96d56Sopenharmony_ci        self.assertFalse(A(1) > A(2))
9827db96d56Sopenharmony_ci
9837db96d56Sopenharmony_ci    def test_total_ordering_le(self):
9847db96d56Sopenharmony_ci        @functools.total_ordering
9857db96d56Sopenharmony_ci        class A:
9867db96d56Sopenharmony_ci            def __init__(self, value):
9877db96d56Sopenharmony_ci                self.value = value
9887db96d56Sopenharmony_ci            def __le__(self, other):
9897db96d56Sopenharmony_ci                return self.value <= other.value
9907db96d56Sopenharmony_ci            def __eq__(self, other):
9917db96d56Sopenharmony_ci                return self.value == other.value
9927db96d56Sopenharmony_ci        self.assertTrue(A(1) < A(2))
9937db96d56Sopenharmony_ci        self.assertTrue(A(2) > A(1))
9947db96d56Sopenharmony_ci        self.assertTrue(A(1) <= A(2))
9957db96d56Sopenharmony_ci        self.assertTrue(A(2) >= A(1))
9967db96d56Sopenharmony_ci        self.assertTrue(A(2) <= A(2))
9977db96d56Sopenharmony_ci        self.assertTrue(A(2) >= A(2))
9987db96d56Sopenharmony_ci        self.assertFalse(A(1) >= A(2))
9997db96d56Sopenharmony_ci
10007db96d56Sopenharmony_ci    def test_total_ordering_gt(self):
10017db96d56Sopenharmony_ci        @functools.total_ordering
10027db96d56Sopenharmony_ci        class A:
10037db96d56Sopenharmony_ci            def __init__(self, value):
10047db96d56Sopenharmony_ci                self.value = value
10057db96d56Sopenharmony_ci            def __gt__(self, other):
10067db96d56Sopenharmony_ci                return self.value > other.value
10077db96d56Sopenharmony_ci            def __eq__(self, other):
10087db96d56Sopenharmony_ci                return self.value == other.value
10097db96d56Sopenharmony_ci        self.assertTrue(A(1) < A(2))
10107db96d56Sopenharmony_ci        self.assertTrue(A(2) > A(1))
10117db96d56Sopenharmony_ci        self.assertTrue(A(1) <= A(2))
10127db96d56Sopenharmony_ci        self.assertTrue(A(2) >= A(1))
10137db96d56Sopenharmony_ci        self.assertTrue(A(2) <= A(2))
10147db96d56Sopenharmony_ci        self.assertTrue(A(2) >= A(2))
10157db96d56Sopenharmony_ci        self.assertFalse(A(2) < A(1))
10167db96d56Sopenharmony_ci
10177db96d56Sopenharmony_ci    def test_total_ordering_ge(self):
10187db96d56Sopenharmony_ci        @functools.total_ordering
10197db96d56Sopenharmony_ci        class A:
10207db96d56Sopenharmony_ci            def __init__(self, value):
10217db96d56Sopenharmony_ci                self.value = value
10227db96d56Sopenharmony_ci            def __ge__(self, other):
10237db96d56Sopenharmony_ci                return self.value >= other.value
10247db96d56Sopenharmony_ci            def __eq__(self, other):
10257db96d56Sopenharmony_ci                return self.value == other.value
10267db96d56Sopenharmony_ci        self.assertTrue(A(1) < A(2))
10277db96d56Sopenharmony_ci        self.assertTrue(A(2) > A(1))
10287db96d56Sopenharmony_ci        self.assertTrue(A(1) <= A(2))
10297db96d56Sopenharmony_ci        self.assertTrue(A(2) >= A(1))
10307db96d56Sopenharmony_ci        self.assertTrue(A(2) <= A(2))
10317db96d56Sopenharmony_ci        self.assertTrue(A(2) >= A(2))
10327db96d56Sopenharmony_ci        self.assertFalse(A(2) <= A(1))
10337db96d56Sopenharmony_ci
10347db96d56Sopenharmony_ci    def test_total_ordering_no_overwrite(self):
10357db96d56Sopenharmony_ci        # new methods should not overwrite existing
10367db96d56Sopenharmony_ci        @functools.total_ordering
10377db96d56Sopenharmony_ci        class A(int):
10387db96d56Sopenharmony_ci            pass
10397db96d56Sopenharmony_ci        self.assertTrue(A(1) < A(2))
10407db96d56Sopenharmony_ci        self.assertTrue(A(2) > A(1))
10417db96d56Sopenharmony_ci        self.assertTrue(A(1) <= A(2))
10427db96d56Sopenharmony_ci        self.assertTrue(A(2) >= A(1))
10437db96d56Sopenharmony_ci        self.assertTrue(A(2) <= A(2))
10447db96d56Sopenharmony_ci        self.assertTrue(A(2) >= A(2))
10457db96d56Sopenharmony_ci
10467db96d56Sopenharmony_ci    def test_no_operations_defined(self):
10477db96d56Sopenharmony_ci        with self.assertRaises(ValueError):
10487db96d56Sopenharmony_ci            @functools.total_ordering
10497db96d56Sopenharmony_ci            class A:
10507db96d56Sopenharmony_ci                pass
10517db96d56Sopenharmony_ci
10527db96d56Sopenharmony_ci    def test_notimplemented(self):
10537db96d56Sopenharmony_ci        # Verify NotImplemented results are correctly handled
10547db96d56Sopenharmony_ci        @functools.total_ordering
10557db96d56Sopenharmony_ci        class ImplementsLessThan:
10567db96d56Sopenharmony_ci            def __init__(self, value):
10577db96d56Sopenharmony_ci                self.value = value
10587db96d56Sopenharmony_ci            def __eq__(self, other):
10597db96d56Sopenharmony_ci                if isinstance(other, ImplementsLessThan):
10607db96d56Sopenharmony_ci                    return self.value == other.value
10617db96d56Sopenharmony_ci                return False
10627db96d56Sopenharmony_ci            def __lt__(self, other):
10637db96d56Sopenharmony_ci                if isinstance(other, ImplementsLessThan):
10647db96d56Sopenharmony_ci                    return self.value < other.value
10657db96d56Sopenharmony_ci                return NotImplemented
10667db96d56Sopenharmony_ci
10677db96d56Sopenharmony_ci        @functools.total_ordering
10687db96d56Sopenharmony_ci        class ImplementsLessThanEqualTo:
10697db96d56Sopenharmony_ci            def __init__(self, value):
10707db96d56Sopenharmony_ci                self.value = value
10717db96d56Sopenharmony_ci            def __eq__(self, other):
10727db96d56Sopenharmony_ci                if isinstance(other, ImplementsLessThanEqualTo):
10737db96d56Sopenharmony_ci                    return self.value == other.value
10747db96d56Sopenharmony_ci                return False
10757db96d56Sopenharmony_ci            def __le__(self, other):
10767db96d56Sopenharmony_ci                if isinstance(other, ImplementsLessThanEqualTo):
10777db96d56Sopenharmony_ci                    return self.value <= other.value
10787db96d56Sopenharmony_ci                return NotImplemented
10797db96d56Sopenharmony_ci
10807db96d56Sopenharmony_ci        @functools.total_ordering
10817db96d56Sopenharmony_ci        class ImplementsGreaterThan:
10827db96d56Sopenharmony_ci            def __init__(self, value):
10837db96d56Sopenharmony_ci                self.value = value
10847db96d56Sopenharmony_ci            def __eq__(self, other):
10857db96d56Sopenharmony_ci                if isinstance(other, ImplementsGreaterThan):
10867db96d56Sopenharmony_ci                    return self.value == other.value
10877db96d56Sopenharmony_ci                return False
10887db96d56Sopenharmony_ci            def __gt__(self, other):
10897db96d56Sopenharmony_ci                if isinstance(other, ImplementsGreaterThan):
10907db96d56Sopenharmony_ci                    return self.value > other.value
10917db96d56Sopenharmony_ci                return NotImplemented
10927db96d56Sopenharmony_ci
10937db96d56Sopenharmony_ci        @functools.total_ordering
10947db96d56Sopenharmony_ci        class ImplementsGreaterThanEqualTo:
10957db96d56Sopenharmony_ci            def __init__(self, value):
10967db96d56Sopenharmony_ci                self.value = value
10977db96d56Sopenharmony_ci            def __eq__(self, other):
10987db96d56Sopenharmony_ci                if isinstance(other, ImplementsGreaterThanEqualTo):
10997db96d56Sopenharmony_ci                    return self.value == other.value
11007db96d56Sopenharmony_ci                return False
11017db96d56Sopenharmony_ci            def __ge__(self, other):
11027db96d56Sopenharmony_ci                if isinstance(other, ImplementsGreaterThanEqualTo):
11037db96d56Sopenharmony_ci                    return self.value >= other.value
11047db96d56Sopenharmony_ci                return NotImplemented
11057db96d56Sopenharmony_ci
11067db96d56Sopenharmony_ci        self.assertIs(ImplementsLessThan(1).__le__(1), NotImplemented)
11077db96d56Sopenharmony_ci        self.assertIs(ImplementsLessThan(1).__gt__(1), NotImplemented)
11087db96d56Sopenharmony_ci        self.assertIs(ImplementsLessThan(1).__ge__(1), NotImplemented)
11097db96d56Sopenharmony_ci        self.assertIs(ImplementsLessThanEqualTo(1).__lt__(1), NotImplemented)
11107db96d56Sopenharmony_ci        self.assertIs(ImplementsLessThanEqualTo(1).__gt__(1), NotImplemented)
11117db96d56Sopenharmony_ci        self.assertIs(ImplementsLessThanEqualTo(1).__ge__(1), NotImplemented)
11127db96d56Sopenharmony_ci        self.assertIs(ImplementsGreaterThan(1).__lt__(1), NotImplemented)
11137db96d56Sopenharmony_ci        self.assertIs(ImplementsGreaterThan(1).__gt__(1), NotImplemented)
11147db96d56Sopenharmony_ci        self.assertIs(ImplementsGreaterThan(1).__ge__(1), NotImplemented)
11157db96d56Sopenharmony_ci        self.assertIs(ImplementsGreaterThanEqualTo(1).__lt__(1), NotImplemented)
11167db96d56Sopenharmony_ci        self.assertIs(ImplementsGreaterThanEqualTo(1).__le__(1), NotImplemented)
11177db96d56Sopenharmony_ci        self.assertIs(ImplementsGreaterThanEqualTo(1).__gt__(1), NotImplemented)
11187db96d56Sopenharmony_ci
11197db96d56Sopenharmony_ci    def test_type_error_when_not_implemented(self):
11207db96d56Sopenharmony_ci        # bug 10042; ensure stack overflow does not occur
11217db96d56Sopenharmony_ci        # when decorated types return NotImplemented
11227db96d56Sopenharmony_ci        @functools.total_ordering
11237db96d56Sopenharmony_ci        class ImplementsLessThan:
11247db96d56Sopenharmony_ci            def __init__(self, value):
11257db96d56Sopenharmony_ci                self.value = value
11267db96d56Sopenharmony_ci            def __eq__(self, other):
11277db96d56Sopenharmony_ci                if isinstance(other, ImplementsLessThan):
11287db96d56Sopenharmony_ci                    return self.value == other.value
11297db96d56Sopenharmony_ci                return False
11307db96d56Sopenharmony_ci            def __lt__(self, other):
11317db96d56Sopenharmony_ci                if isinstance(other, ImplementsLessThan):
11327db96d56Sopenharmony_ci                    return self.value < other.value
11337db96d56Sopenharmony_ci                return NotImplemented
11347db96d56Sopenharmony_ci
11357db96d56Sopenharmony_ci        @functools.total_ordering
11367db96d56Sopenharmony_ci        class ImplementsGreaterThan:
11377db96d56Sopenharmony_ci            def __init__(self, value):
11387db96d56Sopenharmony_ci                self.value = value
11397db96d56Sopenharmony_ci            def __eq__(self, other):
11407db96d56Sopenharmony_ci                if isinstance(other, ImplementsGreaterThan):
11417db96d56Sopenharmony_ci                    return self.value == other.value
11427db96d56Sopenharmony_ci                return False
11437db96d56Sopenharmony_ci            def __gt__(self, other):
11447db96d56Sopenharmony_ci                if isinstance(other, ImplementsGreaterThan):
11457db96d56Sopenharmony_ci                    return self.value > other.value
11467db96d56Sopenharmony_ci                return NotImplemented
11477db96d56Sopenharmony_ci
11487db96d56Sopenharmony_ci        @functools.total_ordering
11497db96d56Sopenharmony_ci        class ImplementsLessThanEqualTo:
11507db96d56Sopenharmony_ci            def __init__(self, value):
11517db96d56Sopenharmony_ci                self.value = value
11527db96d56Sopenharmony_ci            def __eq__(self, other):
11537db96d56Sopenharmony_ci                if isinstance(other, ImplementsLessThanEqualTo):
11547db96d56Sopenharmony_ci                    return self.value == other.value
11557db96d56Sopenharmony_ci                return False
11567db96d56Sopenharmony_ci            def __le__(self, other):
11577db96d56Sopenharmony_ci                if isinstance(other, ImplementsLessThanEqualTo):
11587db96d56Sopenharmony_ci                    return self.value <= other.value
11597db96d56Sopenharmony_ci                return NotImplemented
11607db96d56Sopenharmony_ci
11617db96d56Sopenharmony_ci        @functools.total_ordering
11627db96d56Sopenharmony_ci        class ImplementsGreaterThanEqualTo:
11637db96d56Sopenharmony_ci            def __init__(self, value):
11647db96d56Sopenharmony_ci                self.value = value
11657db96d56Sopenharmony_ci            def __eq__(self, other):
11667db96d56Sopenharmony_ci                if isinstance(other, ImplementsGreaterThanEqualTo):
11677db96d56Sopenharmony_ci                    return self.value == other.value
11687db96d56Sopenharmony_ci                return False
11697db96d56Sopenharmony_ci            def __ge__(self, other):
11707db96d56Sopenharmony_ci                if isinstance(other, ImplementsGreaterThanEqualTo):
11717db96d56Sopenharmony_ci                    return self.value >= other.value
11727db96d56Sopenharmony_ci                return NotImplemented
11737db96d56Sopenharmony_ci
11747db96d56Sopenharmony_ci        @functools.total_ordering
11757db96d56Sopenharmony_ci        class ComparatorNotImplemented:
11767db96d56Sopenharmony_ci            def __init__(self, value):
11777db96d56Sopenharmony_ci                self.value = value
11787db96d56Sopenharmony_ci            def __eq__(self, other):
11797db96d56Sopenharmony_ci                if isinstance(other, ComparatorNotImplemented):
11807db96d56Sopenharmony_ci                    return self.value == other.value
11817db96d56Sopenharmony_ci                return False
11827db96d56Sopenharmony_ci            def __lt__(self, other):
11837db96d56Sopenharmony_ci                return NotImplemented
11847db96d56Sopenharmony_ci
11857db96d56Sopenharmony_ci        with self.subTest("LT < 1"), self.assertRaises(TypeError):
11867db96d56Sopenharmony_ci            ImplementsLessThan(-1) < 1
11877db96d56Sopenharmony_ci
11887db96d56Sopenharmony_ci        with self.subTest("LT < LE"), self.assertRaises(TypeError):
11897db96d56Sopenharmony_ci            ImplementsLessThan(0) < ImplementsLessThanEqualTo(0)
11907db96d56Sopenharmony_ci
11917db96d56Sopenharmony_ci        with self.subTest("LT < GT"), self.assertRaises(TypeError):
11927db96d56Sopenharmony_ci            ImplementsLessThan(1) < ImplementsGreaterThan(1)
11937db96d56Sopenharmony_ci
11947db96d56Sopenharmony_ci        with self.subTest("LE <= LT"), self.assertRaises(TypeError):
11957db96d56Sopenharmony_ci            ImplementsLessThanEqualTo(2) <= ImplementsLessThan(2)
11967db96d56Sopenharmony_ci
11977db96d56Sopenharmony_ci        with self.subTest("LE <= GE"), self.assertRaises(TypeError):
11987db96d56Sopenharmony_ci            ImplementsLessThanEqualTo(3) <= ImplementsGreaterThanEqualTo(3)
11997db96d56Sopenharmony_ci
12007db96d56Sopenharmony_ci        with self.subTest("GT > GE"), self.assertRaises(TypeError):
12017db96d56Sopenharmony_ci            ImplementsGreaterThan(4) > ImplementsGreaterThanEqualTo(4)
12027db96d56Sopenharmony_ci
12037db96d56Sopenharmony_ci        with self.subTest("GT > LT"), self.assertRaises(TypeError):
12047db96d56Sopenharmony_ci            ImplementsGreaterThan(5) > ImplementsLessThan(5)
12057db96d56Sopenharmony_ci
12067db96d56Sopenharmony_ci        with self.subTest("GE >= GT"), self.assertRaises(TypeError):
12077db96d56Sopenharmony_ci            ImplementsGreaterThanEqualTo(6) >= ImplementsGreaterThan(6)
12087db96d56Sopenharmony_ci
12097db96d56Sopenharmony_ci        with self.subTest("GE >= LE"), self.assertRaises(TypeError):
12107db96d56Sopenharmony_ci            ImplementsGreaterThanEqualTo(7) >= ImplementsLessThanEqualTo(7)
12117db96d56Sopenharmony_ci
12127db96d56Sopenharmony_ci        with self.subTest("GE when equal"):
12137db96d56Sopenharmony_ci            a = ComparatorNotImplemented(8)
12147db96d56Sopenharmony_ci            b = ComparatorNotImplemented(8)
12157db96d56Sopenharmony_ci            self.assertEqual(a, b)
12167db96d56Sopenharmony_ci            with self.assertRaises(TypeError):
12177db96d56Sopenharmony_ci                a >= b
12187db96d56Sopenharmony_ci
12197db96d56Sopenharmony_ci        with self.subTest("LE when equal"):
12207db96d56Sopenharmony_ci            a = ComparatorNotImplemented(9)
12217db96d56Sopenharmony_ci            b = ComparatorNotImplemented(9)
12227db96d56Sopenharmony_ci            self.assertEqual(a, b)
12237db96d56Sopenharmony_ci            with self.assertRaises(TypeError):
12247db96d56Sopenharmony_ci                a <= b
12257db96d56Sopenharmony_ci
12267db96d56Sopenharmony_ci    def test_pickle(self):
12277db96d56Sopenharmony_ci        for proto in range(pickle.HIGHEST_PROTOCOL + 1):
12287db96d56Sopenharmony_ci            for name in '__lt__', '__gt__', '__le__', '__ge__':
12297db96d56Sopenharmony_ci                with self.subTest(method=name, proto=proto):
12307db96d56Sopenharmony_ci                    method = getattr(Orderable_LT, name)
12317db96d56Sopenharmony_ci                    method_copy = pickle.loads(pickle.dumps(method, proto))
12327db96d56Sopenharmony_ci                    self.assertIs(method_copy, method)
12337db96d56Sopenharmony_ci
12347db96d56Sopenharmony_ci
12357db96d56Sopenharmony_ci    def test_total_ordering_for_metaclasses_issue_44605(self):
12367db96d56Sopenharmony_ci
12377db96d56Sopenharmony_ci        @functools.total_ordering
12387db96d56Sopenharmony_ci        class SortableMeta(type):
12397db96d56Sopenharmony_ci            def __new__(cls, name, bases, ns):
12407db96d56Sopenharmony_ci                return super().__new__(cls, name, bases, ns)
12417db96d56Sopenharmony_ci
12427db96d56Sopenharmony_ci            def __lt__(self, other):
12437db96d56Sopenharmony_ci                if not isinstance(other, SortableMeta):
12447db96d56Sopenharmony_ci                    pass
12457db96d56Sopenharmony_ci                return self.__name__ < other.__name__
12467db96d56Sopenharmony_ci
12477db96d56Sopenharmony_ci            def __eq__(self, other):
12487db96d56Sopenharmony_ci                if not isinstance(other, SortableMeta):
12497db96d56Sopenharmony_ci                    pass
12507db96d56Sopenharmony_ci                return self.__name__ == other.__name__
12517db96d56Sopenharmony_ci
12527db96d56Sopenharmony_ci        class B(metaclass=SortableMeta):
12537db96d56Sopenharmony_ci            pass
12547db96d56Sopenharmony_ci
12557db96d56Sopenharmony_ci        class A(metaclass=SortableMeta):
12567db96d56Sopenharmony_ci            pass
12577db96d56Sopenharmony_ci
12587db96d56Sopenharmony_ci        self.assertTrue(A < B)
12597db96d56Sopenharmony_ci        self.assertFalse(A > B)
12607db96d56Sopenharmony_ci
12617db96d56Sopenharmony_ci
12627db96d56Sopenharmony_ci@functools.total_ordering
12637db96d56Sopenharmony_ciclass Orderable_LT:
12647db96d56Sopenharmony_ci    def __init__(self, value):
12657db96d56Sopenharmony_ci        self.value = value
12667db96d56Sopenharmony_ci    def __lt__(self, other):
12677db96d56Sopenharmony_ci        return self.value < other.value
12687db96d56Sopenharmony_ci    def __eq__(self, other):
12697db96d56Sopenharmony_ci        return self.value == other.value
12707db96d56Sopenharmony_ci
12717db96d56Sopenharmony_ci
12727db96d56Sopenharmony_ciclass TestCache:
12737db96d56Sopenharmony_ci    # This tests that the pass-through is working as designed.
12747db96d56Sopenharmony_ci    # The underlying functionality is tested in TestLRU.
12757db96d56Sopenharmony_ci
12767db96d56Sopenharmony_ci    def test_cache(self):
12777db96d56Sopenharmony_ci        @self.module.cache
12787db96d56Sopenharmony_ci        def fib(n):
12797db96d56Sopenharmony_ci            if n < 2:
12807db96d56Sopenharmony_ci                return n
12817db96d56Sopenharmony_ci            return fib(n-1) + fib(n-2)
12827db96d56Sopenharmony_ci        self.assertEqual([fib(n) for n in range(16)],
12837db96d56Sopenharmony_ci            [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610])
12847db96d56Sopenharmony_ci        self.assertEqual(fib.cache_info(),
12857db96d56Sopenharmony_ci            self.module._CacheInfo(hits=28, misses=16, maxsize=None, currsize=16))
12867db96d56Sopenharmony_ci        fib.cache_clear()
12877db96d56Sopenharmony_ci        self.assertEqual(fib.cache_info(),
12887db96d56Sopenharmony_ci            self.module._CacheInfo(hits=0, misses=0, maxsize=None, currsize=0))
12897db96d56Sopenharmony_ci
12907db96d56Sopenharmony_ci
12917db96d56Sopenharmony_ciclass TestLRU:
12927db96d56Sopenharmony_ci
12937db96d56Sopenharmony_ci    def test_lru(self):
12947db96d56Sopenharmony_ci        def orig(x, y):
12957db96d56Sopenharmony_ci            return 3 * x + y
12967db96d56Sopenharmony_ci        f = self.module.lru_cache(maxsize=20)(orig)
12977db96d56Sopenharmony_ci        hits, misses, maxsize, currsize = f.cache_info()
12987db96d56Sopenharmony_ci        self.assertEqual(maxsize, 20)
12997db96d56Sopenharmony_ci        self.assertEqual(currsize, 0)
13007db96d56Sopenharmony_ci        self.assertEqual(hits, 0)
13017db96d56Sopenharmony_ci        self.assertEqual(misses, 0)
13027db96d56Sopenharmony_ci
13037db96d56Sopenharmony_ci        domain = range(5)
13047db96d56Sopenharmony_ci        for i in range(1000):
13057db96d56Sopenharmony_ci            x, y = choice(domain), choice(domain)
13067db96d56Sopenharmony_ci            actual = f(x, y)
13077db96d56Sopenharmony_ci            expected = orig(x, y)
13087db96d56Sopenharmony_ci            self.assertEqual(actual, expected)
13097db96d56Sopenharmony_ci        hits, misses, maxsize, currsize = f.cache_info()
13107db96d56Sopenharmony_ci        self.assertTrue(hits > misses)
13117db96d56Sopenharmony_ci        self.assertEqual(hits + misses, 1000)
13127db96d56Sopenharmony_ci        self.assertEqual(currsize, 20)
13137db96d56Sopenharmony_ci
13147db96d56Sopenharmony_ci        f.cache_clear()   # test clearing
13157db96d56Sopenharmony_ci        hits, misses, maxsize, currsize = f.cache_info()
13167db96d56Sopenharmony_ci        self.assertEqual(hits, 0)
13177db96d56Sopenharmony_ci        self.assertEqual(misses, 0)
13187db96d56Sopenharmony_ci        self.assertEqual(currsize, 0)
13197db96d56Sopenharmony_ci        f(x, y)
13207db96d56Sopenharmony_ci        hits, misses, maxsize, currsize = f.cache_info()
13217db96d56Sopenharmony_ci        self.assertEqual(hits, 0)
13227db96d56Sopenharmony_ci        self.assertEqual(misses, 1)
13237db96d56Sopenharmony_ci        self.assertEqual(currsize, 1)
13247db96d56Sopenharmony_ci
13257db96d56Sopenharmony_ci        # Test bypassing the cache
13267db96d56Sopenharmony_ci        self.assertIs(f.__wrapped__, orig)
13277db96d56Sopenharmony_ci        f.__wrapped__(x, y)
13287db96d56Sopenharmony_ci        hits, misses, maxsize, currsize = f.cache_info()
13297db96d56Sopenharmony_ci        self.assertEqual(hits, 0)
13307db96d56Sopenharmony_ci        self.assertEqual(misses, 1)
13317db96d56Sopenharmony_ci        self.assertEqual(currsize, 1)
13327db96d56Sopenharmony_ci
13337db96d56Sopenharmony_ci        # test size zero (which means "never-cache")
13347db96d56Sopenharmony_ci        @self.module.lru_cache(0)
13357db96d56Sopenharmony_ci        def f():
13367db96d56Sopenharmony_ci            nonlocal f_cnt
13377db96d56Sopenharmony_ci            f_cnt += 1
13387db96d56Sopenharmony_ci            return 20
13397db96d56Sopenharmony_ci        self.assertEqual(f.cache_info().maxsize, 0)
13407db96d56Sopenharmony_ci        f_cnt = 0
13417db96d56Sopenharmony_ci        for i in range(5):
13427db96d56Sopenharmony_ci            self.assertEqual(f(), 20)
13437db96d56Sopenharmony_ci        self.assertEqual(f_cnt, 5)
13447db96d56Sopenharmony_ci        hits, misses, maxsize, currsize = f.cache_info()
13457db96d56Sopenharmony_ci        self.assertEqual(hits, 0)
13467db96d56Sopenharmony_ci        self.assertEqual(misses, 5)
13477db96d56Sopenharmony_ci        self.assertEqual(currsize, 0)
13487db96d56Sopenharmony_ci
13497db96d56Sopenharmony_ci        # test size one
13507db96d56Sopenharmony_ci        @self.module.lru_cache(1)
13517db96d56Sopenharmony_ci        def f():
13527db96d56Sopenharmony_ci            nonlocal f_cnt
13537db96d56Sopenharmony_ci            f_cnt += 1
13547db96d56Sopenharmony_ci            return 20
13557db96d56Sopenharmony_ci        self.assertEqual(f.cache_info().maxsize, 1)
13567db96d56Sopenharmony_ci        f_cnt = 0
13577db96d56Sopenharmony_ci        for i in range(5):
13587db96d56Sopenharmony_ci            self.assertEqual(f(), 20)
13597db96d56Sopenharmony_ci        self.assertEqual(f_cnt, 1)
13607db96d56Sopenharmony_ci        hits, misses, maxsize, currsize = f.cache_info()
13617db96d56Sopenharmony_ci        self.assertEqual(hits, 4)
13627db96d56Sopenharmony_ci        self.assertEqual(misses, 1)
13637db96d56Sopenharmony_ci        self.assertEqual(currsize, 1)
13647db96d56Sopenharmony_ci
13657db96d56Sopenharmony_ci        # test size two
13667db96d56Sopenharmony_ci        @self.module.lru_cache(2)
13677db96d56Sopenharmony_ci        def f(x):
13687db96d56Sopenharmony_ci            nonlocal f_cnt
13697db96d56Sopenharmony_ci            f_cnt += 1
13707db96d56Sopenharmony_ci            return x*10
13717db96d56Sopenharmony_ci        self.assertEqual(f.cache_info().maxsize, 2)
13727db96d56Sopenharmony_ci        f_cnt = 0
13737db96d56Sopenharmony_ci        for x in 7, 9, 7, 9, 7, 9, 8, 8, 8, 9, 9, 9, 8, 8, 8, 7:
13747db96d56Sopenharmony_ci            #    *  *              *                          *
13757db96d56Sopenharmony_ci            self.assertEqual(f(x), x*10)
13767db96d56Sopenharmony_ci        self.assertEqual(f_cnt, 4)
13777db96d56Sopenharmony_ci        hits, misses, maxsize, currsize = f.cache_info()
13787db96d56Sopenharmony_ci        self.assertEqual(hits, 12)
13797db96d56Sopenharmony_ci        self.assertEqual(misses, 4)
13807db96d56Sopenharmony_ci        self.assertEqual(currsize, 2)
13817db96d56Sopenharmony_ci
13827db96d56Sopenharmony_ci    def test_lru_no_args(self):
13837db96d56Sopenharmony_ci        @self.module.lru_cache
13847db96d56Sopenharmony_ci        def square(x):
13857db96d56Sopenharmony_ci            return x ** 2
13867db96d56Sopenharmony_ci
13877db96d56Sopenharmony_ci        self.assertEqual(list(map(square, [10, 20, 10])),
13887db96d56Sopenharmony_ci                         [100, 400, 100])
13897db96d56Sopenharmony_ci        self.assertEqual(square.cache_info().hits, 1)
13907db96d56Sopenharmony_ci        self.assertEqual(square.cache_info().misses, 2)
13917db96d56Sopenharmony_ci        self.assertEqual(square.cache_info().maxsize, 128)
13927db96d56Sopenharmony_ci        self.assertEqual(square.cache_info().currsize, 2)
13937db96d56Sopenharmony_ci
13947db96d56Sopenharmony_ci    def test_lru_bug_35780(self):
13957db96d56Sopenharmony_ci        # C version of the lru_cache was not checking to see if
13967db96d56Sopenharmony_ci        # the user function call has already modified the cache
13977db96d56Sopenharmony_ci        # (this arises in recursive calls and in multi-threading).
13987db96d56Sopenharmony_ci        # This cause the cache to have orphan links not referenced
13997db96d56Sopenharmony_ci        # by the cache dictionary.
14007db96d56Sopenharmony_ci
14017db96d56Sopenharmony_ci        once = True                 # Modified by f(x) below
14027db96d56Sopenharmony_ci
14037db96d56Sopenharmony_ci        @self.module.lru_cache(maxsize=10)
14047db96d56Sopenharmony_ci        def f(x):
14057db96d56Sopenharmony_ci            nonlocal once
14067db96d56Sopenharmony_ci            rv = f'.{x}.'
14077db96d56Sopenharmony_ci            if x == 20 and once:
14087db96d56Sopenharmony_ci                once = False
14097db96d56Sopenharmony_ci                rv = f(x)
14107db96d56Sopenharmony_ci            return rv
14117db96d56Sopenharmony_ci
14127db96d56Sopenharmony_ci        # Fill the cache
14137db96d56Sopenharmony_ci        for x in range(15):
14147db96d56Sopenharmony_ci            self.assertEqual(f(x), f'.{x}.')
14157db96d56Sopenharmony_ci        self.assertEqual(f.cache_info().currsize, 10)
14167db96d56Sopenharmony_ci
14177db96d56Sopenharmony_ci        # Make a recursive call and make sure the cache remains full
14187db96d56Sopenharmony_ci        self.assertEqual(f(20), '.20.')
14197db96d56Sopenharmony_ci        self.assertEqual(f.cache_info().currsize, 10)
14207db96d56Sopenharmony_ci
14217db96d56Sopenharmony_ci    def test_lru_bug_36650(self):
14227db96d56Sopenharmony_ci        # C version of lru_cache was treating a call with an empty **kwargs
14237db96d56Sopenharmony_ci        # dictionary as being distinct from a call with no keywords at all.
14247db96d56Sopenharmony_ci        # This did not result in an incorrect answer, but it did trigger
14257db96d56Sopenharmony_ci        # an unexpected cache miss.
14267db96d56Sopenharmony_ci
14277db96d56Sopenharmony_ci        @self.module.lru_cache()
14287db96d56Sopenharmony_ci        def f(x):
14297db96d56Sopenharmony_ci            pass
14307db96d56Sopenharmony_ci
14317db96d56Sopenharmony_ci        f(0)
14327db96d56Sopenharmony_ci        f(0, **{})
14337db96d56Sopenharmony_ci        self.assertEqual(f.cache_info().hits, 1)
14347db96d56Sopenharmony_ci
14357db96d56Sopenharmony_ci    def test_lru_hash_only_once(self):
14367db96d56Sopenharmony_ci        # To protect against weird reentrancy bugs and to improve
14377db96d56Sopenharmony_ci        # efficiency when faced with slow __hash__ methods, the
14387db96d56Sopenharmony_ci        # LRU cache guarantees that it will only call __hash__
14397db96d56Sopenharmony_ci        # only once per use as an argument to the cached function.
14407db96d56Sopenharmony_ci
14417db96d56Sopenharmony_ci        @self.module.lru_cache(maxsize=1)
14427db96d56Sopenharmony_ci        def f(x, y):
14437db96d56Sopenharmony_ci            return x * 3 + y
14447db96d56Sopenharmony_ci
14457db96d56Sopenharmony_ci        # Simulate the integer 5
14467db96d56Sopenharmony_ci        mock_int = unittest.mock.Mock()
14477db96d56Sopenharmony_ci        mock_int.__mul__ = unittest.mock.Mock(return_value=15)
14487db96d56Sopenharmony_ci        mock_int.__hash__ = unittest.mock.Mock(return_value=999)
14497db96d56Sopenharmony_ci
14507db96d56Sopenharmony_ci        # Add to cache:  One use as an argument gives one call
14517db96d56Sopenharmony_ci        self.assertEqual(f(mock_int, 1), 16)
14527db96d56Sopenharmony_ci        self.assertEqual(mock_int.__hash__.call_count, 1)
14537db96d56Sopenharmony_ci        self.assertEqual(f.cache_info(), (0, 1, 1, 1))
14547db96d56Sopenharmony_ci
14557db96d56Sopenharmony_ci        # Cache hit: One use as an argument gives one additional call
14567db96d56Sopenharmony_ci        self.assertEqual(f(mock_int, 1), 16)
14577db96d56Sopenharmony_ci        self.assertEqual(mock_int.__hash__.call_count, 2)
14587db96d56Sopenharmony_ci        self.assertEqual(f.cache_info(), (1, 1, 1, 1))
14597db96d56Sopenharmony_ci
14607db96d56Sopenharmony_ci        # Cache eviction: No use as an argument gives no additional call
14617db96d56Sopenharmony_ci        self.assertEqual(f(6, 2), 20)
14627db96d56Sopenharmony_ci        self.assertEqual(mock_int.__hash__.call_count, 2)
14637db96d56Sopenharmony_ci        self.assertEqual(f.cache_info(), (1, 2, 1, 1))
14647db96d56Sopenharmony_ci
14657db96d56Sopenharmony_ci        # Cache miss: One use as an argument gives one additional call
14667db96d56Sopenharmony_ci        self.assertEqual(f(mock_int, 1), 16)
14677db96d56Sopenharmony_ci        self.assertEqual(mock_int.__hash__.call_count, 3)
14687db96d56Sopenharmony_ci        self.assertEqual(f.cache_info(), (1, 3, 1, 1))
14697db96d56Sopenharmony_ci
14707db96d56Sopenharmony_ci    def test_lru_reentrancy_with_len(self):
14717db96d56Sopenharmony_ci        # Test to make sure the LRU cache code isn't thrown-off by
14727db96d56Sopenharmony_ci        # caching the built-in len() function.  Since len() can be
14737db96d56Sopenharmony_ci        # cached, we shouldn't use it inside the lru code itself.
14747db96d56Sopenharmony_ci        old_len = builtins.len
14757db96d56Sopenharmony_ci        try:
14767db96d56Sopenharmony_ci            builtins.len = self.module.lru_cache(4)(len)
14777db96d56Sopenharmony_ci            for i in [0, 0, 1, 2, 3, 3, 4, 5, 6, 1, 7, 2, 1]:
14787db96d56Sopenharmony_ci                self.assertEqual(len('abcdefghijklmn'[:i]), i)
14797db96d56Sopenharmony_ci        finally:
14807db96d56Sopenharmony_ci            builtins.len = old_len
14817db96d56Sopenharmony_ci
14827db96d56Sopenharmony_ci    def test_lru_star_arg_handling(self):
14837db96d56Sopenharmony_ci        # Test regression that arose in ea064ff3c10f
14847db96d56Sopenharmony_ci        @self.module.lru_cache()
14857db96d56Sopenharmony_ci        def f(*args):
14867db96d56Sopenharmony_ci            return args
14877db96d56Sopenharmony_ci
14887db96d56Sopenharmony_ci        self.assertEqual(f(1, 2), (1, 2))
14897db96d56Sopenharmony_ci        self.assertEqual(f((1, 2)), ((1, 2),))
14907db96d56Sopenharmony_ci
14917db96d56Sopenharmony_ci    def test_lru_type_error(self):
14927db96d56Sopenharmony_ci        # Regression test for issue #28653.
14937db96d56Sopenharmony_ci        # lru_cache was leaking when one of the arguments
14947db96d56Sopenharmony_ci        # wasn't cacheable.
14957db96d56Sopenharmony_ci
14967db96d56Sopenharmony_ci        @self.module.lru_cache(maxsize=None)
14977db96d56Sopenharmony_ci        def infinite_cache(o):
14987db96d56Sopenharmony_ci            pass
14997db96d56Sopenharmony_ci
15007db96d56Sopenharmony_ci        @self.module.lru_cache(maxsize=10)
15017db96d56Sopenharmony_ci        def limited_cache(o):
15027db96d56Sopenharmony_ci            pass
15037db96d56Sopenharmony_ci
15047db96d56Sopenharmony_ci        with self.assertRaises(TypeError):
15057db96d56Sopenharmony_ci            infinite_cache([])
15067db96d56Sopenharmony_ci
15077db96d56Sopenharmony_ci        with self.assertRaises(TypeError):
15087db96d56Sopenharmony_ci            limited_cache([])
15097db96d56Sopenharmony_ci
15107db96d56Sopenharmony_ci    def test_lru_with_maxsize_none(self):
15117db96d56Sopenharmony_ci        @self.module.lru_cache(maxsize=None)
15127db96d56Sopenharmony_ci        def fib(n):
15137db96d56Sopenharmony_ci            if n < 2:
15147db96d56Sopenharmony_ci                return n
15157db96d56Sopenharmony_ci            return fib(n-1) + fib(n-2)
15167db96d56Sopenharmony_ci        self.assertEqual([fib(n) for n in range(16)],
15177db96d56Sopenharmony_ci            [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610])
15187db96d56Sopenharmony_ci        self.assertEqual(fib.cache_info(),
15197db96d56Sopenharmony_ci            self.module._CacheInfo(hits=28, misses=16, maxsize=None, currsize=16))
15207db96d56Sopenharmony_ci        fib.cache_clear()
15217db96d56Sopenharmony_ci        self.assertEqual(fib.cache_info(),
15227db96d56Sopenharmony_ci            self.module._CacheInfo(hits=0, misses=0, maxsize=None, currsize=0))
15237db96d56Sopenharmony_ci
15247db96d56Sopenharmony_ci    def test_lru_with_maxsize_negative(self):
15257db96d56Sopenharmony_ci        @self.module.lru_cache(maxsize=-10)
15267db96d56Sopenharmony_ci        def eq(n):
15277db96d56Sopenharmony_ci            return n
15287db96d56Sopenharmony_ci        for i in (0, 1):
15297db96d56Sopenharmony_ci            self.assertEqual([eq(n) for n in range(150)], list(range(150)))
15307db96d56Sopenharmony_ci        self.assertEqual(eq.cache_info(),
15317db96d56Sopenharmony_ci            self.module._CacheInfo(hits=0, misses=300, maxsize=0, currsize=0))
15327db96d56Sopenharmony_ci
15337db96d56Sopenharmony_ci    def test_lru_with_exceptions(self):
15347db96d56Sopenharmony_ci        # Verify that user_function exceptions get passed through without
15357db96d56Sopenharmony_ci        # creating a hard-to-read chained exception.
15367db96d56Sopenharmony_ci        # http://bugs.python.org/issue13177
15377db96d56Sopenharmony_ci        for maxsize in (None, 128):
15387db96d56Sopenharmony_ci            @self.module.lru_cache(maxsize)
15397db96d56Sopenharmony_ci            def func(i):
15407db96d56Sopenharmony_ci                return 'abc'[i]
15417db96d56Sopenharmony_ci            self.assertEqual(func(0), 'a')
15427db96d56Sopenharmony_ci            with self.assertRaises(IndexError) as cm:
15437db96d56Sopenharmony_ci                func(15)
15447db96d56Sopenharmony_ci            self.assertIsNone(cm.exception.__context__)
15457db96d56Sopenharmony_ci            # Verify that the previous exception did not result in a cached entry
15467db96d56Sopenharmony_ci            with self.assertRaises(IndexError):
15477db96d56Sopenharmony_ci                func(15)
15487db96d56Sopenharmony_ci
15497db96d56Sopenharmony_ci    def test_lru_with_types(self):
15507db96d56Sopenharmony_ci        for maxsize in (None, 128):
15517db96d56Sopenharmony_ci            @self.module.lru_cache(maxsize=maxsize, typed=True)
15527db96d56Sopenharmony_ci            def square(x):
15537db96d56Sopenharmony_ci                return x * x
15547db96d56Sopenharmony_ci            self.assertEqual(square(3), 9)
15557db96d56Sopenharmony_ci            self.assertEqual(type(square(3)), type(9))
15567db96d56Sopenharmony_ci            self.assertEqual(square(3.0), 9.0)
15577db96d56Sopenharmony_ci            self.assertEqual(type(square(3.0)), type(9.0))
15587db96d56Sopenharmony_ci            self.assertEqual(square(x=3), 9)
15597db96d56Sopenharmony_ci            self.assertEqual(type(square(x=3)), type(9))
15607db96d56Sopenharmony_ci            self.assertEqual(square(x=3.0), 9.0)
15617db96d56Sopenharmony_ci            self.assertEqual(type(square(x=3.0)), type(9.0))
15627db96d56Sopenharmony_ci            self.assertEqual(square.cache_info().hits, 4)
15637db96d56Sopenharmony_ci            self.assertEqual(square.cache_info().misses, 4)
15647db96d56Sopenharmony_ci
15657db96d56Sopenharmony_ci    def test_lru_cache_typed_is_not_recursive(self):
15667db96d56Sopenharmony_ci        cached = self.module.lru_cache(typed=True)(repr)
15677db96d56Sopenharmony_ci
15687db96d56Sopenharmony_ci        self.assertEqual(cached(1), '1')
15697db96d56Sopenharmony_ci        self.assertEqual(cached(True), 'True')
15707db96d56Sopenharmony_ci        self.assertEqual(cached(1.0), '1.0')
15717db96d56Sopenharmony_ci        self.assertEqual(cached(0), '0')
15727db96d56Sopenharmony_ci        self.assertEqual(cached(False), 'False')
15737db96d56Sopenharmony_ci        self.assertEqual(cached(0.0), '0.0')
15747db96d56Sopenharmony_ci
15757db96d56Sopenharmony_ci        self.assertEqual(cached((1,)), '(1,)')
15767db96d56Sopenharmony_ci        self.assertEqual(cached((True,)), '(1,)')
15777db96d56Sopenharmony_ci        self.assertEqual(cached((1.0,)), '(1,)')
15787db96d56Sopenharmony_ci        self.assertEqual(cached((0,)), '(0,)')
15797db96d56Sopenharmony_ci        self.assertEqual(cached((False,)), '(0,)')
15807db96d56Sopenharmony_ci        self.assertEqual(cached((0.0,)), '(0,)')
15817db96d56Sopenharmony_ci
15827db96d56Sopenharmony_ci        class T(tuple):
15837db96d56Sopenharmony_ci            pass
15847db96d56Sopenharmony_ci
15857db96d56Sopenharmony_ci        self.assertEqual(cached(T((1,))), '(1,)')
15867db96d56Sopenharmony_ci        self.assertEqual(cached(T((True,))), '(1,)')
15877db96d56Sopenharmony_ci        self.assertEqual(cached(T((1.0,))), '(1,)')
15887db96d56Sopenharmony_ci        self.assertEqual(cached(T((0,))), '(0,)')
15897db96d56Sopenharmony_ci        self.assertEqual(cached(T((False,))), '(0,)')
15907db96d56Sopenharmony_ci        self.assertEqual(cached(T((0.0,))), '(0,)')
15917db96d56Sopenharmony_ci
15927db96d56Sopenharmony_ci    def test_lru_with_keyword_args(self):
15937db96d56Sopenharmony_ci        @self.module.lru_cache()
15947db96d56Sopenharmony_ci        def fib(n):
15957db96d56Sopenharmony_ci            if n < 2:
15967db96d56Sopenharmony_ci                return n
15977db96d56Sopenharmony_ci            return fib(n=n-1) + fib(n=n-2)
15987db96d56Sopenharmony_ci        self.assertEqual(
15997db96d56Sopenharmony_ci            [fib(n=number) for number in range(16)],
16007db96d56Sopenharmony_ci            [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610]
16017db96d56Sopenharmony_ci        )
16027db96d56Sopenharmony_ci        self.assertEqual(fib.cache_info(),
16037db96d56Sopenharmony_ci            self.module._CacheInfo(hits=28, misses=16, maxsize=128, currsize=16))
16047db96d56Sopenharmony_ci        fib.cache_clear()
16057db96d56Sopenharmony_ci        self.assertEqual(fib.cache_info(),
16067db96d56Sopenharmony_ci            self.module._CacheInfo(hits=0, misses=0, maxsize=128, currsize=0))
16077db96d56Sopenharmony_ci
16087db96d56Sopenharmony_ci    def test_lru_with_keyword_args_maxsize_none(self):
16097db96d56Sopenharmony_ci        @self.module.lru_cache(maxsize=None)
16107db96d56Sopenharmony_ci        def fib(n):
16117db96d56Sopenharmony_ci            if n < 2:
16127db96d56Sopenharmony_ci                return n
16137db96d56Sopenharmony_ci            return fib(n=n-1) + fib(n=n-2)
16147db96d56Sopenharmony_ci        self.assertEqual([fib(n=number) for number in range(16)],
16157db96d56Sopenharmony_ci            [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610])
16167db96d56Sopenharmony_ci        self.assertEqual(fib.cache_info(),
16177db96d56Sopenharmony_ci            self.module._CacheInfo(hits=28, misses=16, maxsize=None, currsize=16))
16187db96d56Sopenharmony_ci        fib.cache_clear()
16197db96d56Sopenharmony_ci        self.assertEqual(fib.cache_info(),
16207db96d56Sopenharmony_ci            self.module._CacheInfo(hits=0, misses=0, maxsize=None, currsize=0))
16217db96d56Sopenharmony_ci
16227db96d56Sopenharmony_ci    def test_kwargs_order(self):
16237db96d56Sopenharmony_ci        # PEP 468: Preserving Keyword Argument Order
16247db96d56Sopenharmony_ci        @self.module.lru_cache(maxsize=10)
16257db96d56Sopenharmony_ci        def f(**kwargs):
16267db96d56Sopenharmony_ci            return list(kwargs.items())
16277db96d56Sopenharmony_ci        self.assertEqual(f(a=1, b=2), [('a', 1), ('b', 2)])
16287db96d56Sopenharmony_ci        self.assertEqual(f(b=2, a=1), [('b', 2), ('a', 1)])
16297db96d56Sopenharmony_ci        self.assertEqual(f.cache_info(),
16307db96d56Sopenharmony_ci            self.module._CacheInfo(hits=0, misses=2, maxsize=10, currsize=2))
16317db96d56Sopenharmony_ci
16327db96d56Sopenharmony_ci    def test_lru_cache_decoration(self):
16337db96d56Sopenharmony_ci        def f(zomg: 'zomg_annotation'):
16347db96d56Sopenharmony_ci            """f doc string"""
16357db96d56Sopenharmony_ci            return 42
16367db96d56Sopenharmony_ci        g = self.module.lru_cache()(f)
16377db96d56Sopenharmony_ci        for attr in self.module.WRAPPER_ASSIGNMENTS:
16387db96d56Sopenharmony_ci            self.assertEqual(getattr(g, attr), getattr(f, attr))
16397db96d56Sopenharmony_ci
16407db96d56Sopenharmony_ci    @threading_helper.requires_working_threading()
16417db96d56Sopenharmony_ci    def test_lru_cache_threaded(self):
16427db96d56Sopenharmony_ci        n, m = 5, 11
16437db96d56Sopenharmony_ci        def orig(x, y):
16447db96d56Sopenharmony_ci            return 3 * x + y
16457db96d56Sopenharmony_ci        f = self.module.lru_cache(maxsize=n*m)(orig)
16467db96d56Sopenharmony_ci        hits, misses, maxsize, currsize = f.cache_info()
16477db96d56Sopenharmony_ci        self.assertEqual(currsize, 0)
16487db96d56Sopenharmony_ci
16497db96d56Sopenharmony_ci        start = threading.Event()
16507db96d56Sopenharmony_ci        def full(k):
16517db96d56Sopenharmony_ci            start.wait(10)
16527db96d56Sopenharmony_ci            for _ in range(m):
16537db96d56Sopenharmony_ci                self.assertEqual(f(k, 0), orig(k, 0))
16547db96d56Sopenharmony_ci
16557db96d56Sopenharmony_ci        def clear():
16567db96d56Sopenharmony_ci            start.wait(10)
16577db96d56Sopenharmony_ci            for _ in range(2*m):
16587db96d56Sopenharmony_ci                f.cache_clear()
16597db96d56Sopenharmony_ci
16607db96d56Sopenharmony_ci        orig_si = sys.getswitchinterval()
16617db96d56Sopenharmony_ci        support.setswitchinterval(1e-6)
16627db96d56Sopenharmony_ci        try:
16637db96d56Sopenharmony_ci            # create n threads in order to fill cache
16647db96d56Sopenharmony_ci            threads = [threading.Thread(target=full, args=[k])
16657db96d56Sopenharmony_ci                       for k in range(n)]
16667db96d56Sopenharmony_ci            with threading_helper.start_threads(threads):
16677db96d56Sopenharmony_ci                start.set()
16687db96d56Sopenharmony_ci
16697db96d56Sopenharmony_ci            hits, misses, maxsize, currsize = f.cache_info()
16707db96d56Sopenharmony_ci            if self.module is py_functools:
16717db96d56Sopenharmony_ci                # XXX: Why can be not equal?
16727db96d56Sopenharmony_ci                self.assertLessEqual(misses, n)
16737db96d56Sopenharmony_ci                self.assertLessEqual(hits, m*n - misses)
16747db96d56Sopenharmony_ci            else:
16757db96d56Sopenharmony_ci                self.assertEqual(misses, n)
16767db96d56Sopenharmony_ci                self.assertEqual(hits, m*n - misses)
16777db96d56Sopenharmony_ci            self.assertEqual(currsize, n)
16787db96d56Sopenharmony_ci
16797db96d56Sopenharmony_ci            # create n threads in order to fill cache and 1 to clear it
16807db96d56Sopenharmony_ci            threads = [threading.Thread(target=clear)]
16817db96d56Sopenharmony_ci            threads += [threading.Thread(target=full, args=[k])
16827db96d56Sopenharmony_ci                        for k in range(n)]
16837db96d56Sopenharmony_ci            start.clear()
16847db96d56Sopenharmony_ci            with threading_helper.start_threads(threads):
16857db96d56Sopenharmony_ci                start.set()
16867db96d56Sopenharmony_ci        finally:
16877db96d56Sopenharmony_ci            sys.setswitchinterval(orig_si)
16887db96d56Sopenharmony_ci
16897db96d56Sopenharmony_ci    @threading_helper.requires_working_threading()
16907db96d56Sopenharmony_ci    def test_lru_cache_threaded2(self):
16917db96d56Sopenharmony_ci        # Simultaneous call with the same arguments
16927db96d56Sopenharmony_ci        n, m = 5, 7
16937db96d56Sopenharmony_ci        start = threading.Barrier(n+1)
16947db96d56Sopenharmony_ci        pause = threading.Barrier(n+1)
16957db96d56Sopenharmony_ci        stop = threading.Barrier(n+1)
16967db96d56Sopenharmony_ci        @self.module.lru_cache(maxsize=m*n)
16977db96d56Sopenharmony_ci        def f(x):
16987db96d56Sopenharmony_ci            pause.wait(10)
16997db96d56Sopenharmony_ci            return 3 * x
17007db96d56Sopenharmony_ci        self.assertEqual(f.cache_info(), (0, 0, m*n, 0))
17017db96d56Sopenharmony_ci        def test():
17027db96d56Sopenharmony_ci            for i in range(m):
17037db96d56Sopenharmony_ci                start.wait(10)
17047db96d56Sopenharmony_ci                self.assertEqual(f(i), 3 * i)
17057db96d56Sopenharmony_ci                stop.wait(10)
17067db96d56Sopenharmony_ci        threads = [threading.Thread(target=test) for k in range(n)]
17077db96d56Sopenharmony_ci        with threading_helper.start_threads(threads):
17087db96d56Sopenharmony_ci            for i in range(m):
17097db96d56Sopenharmony_ci                start.wait(10)
17107db96d56Sopenharmony_ci                stop.reset()
17117db96d56Sopenharmony_ci                pause.wait(10)
17127db96d56Sopenharmony_ci                start.reset()
17137db96d56Sopenharmony_ci                stop.wait(10)
17147db96d56Sopenharmony_ci                pause.reset()
17157db96d56Sopenharmony_ci                self.assertEqual(f.cache_info(), (0, (i+1)*n, m*n, i+1))
17167db96d56Sopenharmony_ci
17177db96d56Sopenharmony_ci    @threading_helper.requires_working_threading()
17187db96d56Sopenharmony_ci    def test_lru_cache_threaded3(self):
17197db96d56Sopenharmony_ci        @self.module.lru_cache(maxsize=2)
17207db96d56Sopenharmony_ci        def f(x):
17217db96d56Sopenharmony_ci            time.sleep(.01)
17227db96d56Sopenharmony_ci            return 3 * x
17237db96d56Sopenharmony_ci        def test(i, x):
17247db96d56Sopenharmony_ci            with self.subTest(thread=i):
17257db96d56Sopenharmony_ci                self.assertEqual(f(x), 3 * x, i)
17267db96d56Sopenharmony_ci        threads = [threading.Thread(target=test, args=(i, v))
17277db96d56Sopenharmony_ci                   for i, v in enumerate([1, 2, 2, 3, 2])]
17287db96d56Sopenharmony_ci        with threading_helper.start_threads(threads):
17297db96d56Sopenharmony_ci            pass
17307db96d56Sopenharmony_ci
17317db96d56Sopenharmony_ci    def test_need_for_rlock(self):
17327db96d56Sopenharmony_ci        # This will deadlock on an LRU cache that uses a regular lock
17337db96d56Sopenharmony_ci
17347db96d56Sopenharmony_ci        @self.module.lru_cache(maxsize=10)
17357db96d56Sopenharmony_ci        def test_func(x):
17367db96d56Sopenharmony_ci            'Used to demonstrate a reentrant lru_cache call within a single thread'
17377db96d56Sopenharmony_ci            return x
17387db96d56Sopenharmony_ci
17397db96d56Sopenharmony_ci        class DoubleEq:
17407db96d56Sopenharmony_ci            'Demonstrate a reentrant lru_cache call within a single thread'
17417db96d56Sopenharmony_ci            def __init__(self, x):
17427db96d56Sopenharmony_ci                self.x = x
17437db96d56Sopenharmony_ci            def __hash__(self):
17447db96d56Sopenharmony_ci                return self.x
17457db96d56Sopenharmony_ci            def __eq__(self, other):
17467db96d56Sopenharmony_ci                if self.x == 2:
17477db96d56Sopenharmony_ci                    test_func(DoubleEq(1))
17487db96d56Sopenharmony_ci                return self.x == other.x
17497db96d56Sopenharmony_ci
17507db96d56Sopenharmony_ci        test_func(DoubleEq(1))                      # Load the cache
17517db96d56Sopenharmony_ci        test_func(DoubleEq(2))                      # Load the cache
17527db96d56Sopenharmony_ci        self.assertEqual(test_func(DoubleEq(2)),    # Trigger a re-entrant __eq__ call
17537db96d56Sopenharmony_ci                         DoubleEq(2))               # Verify the correct return value
17547db96d56Sopenharmony_ci
17557db96d56Sopenharmony_ci    def test_lru_method(self):
17567db96d56Sopenharmony_ci        class X(int):
17577db96d56Sopenharmony_ci            f_cnt = 0
17587db96d56Sopenharmony_ci            @self.module.lru_cache(2)
17597db96d56Sopenharmony_ci            def f(self, x):
17607db96d56Sopenharmony_ci                self.f_cnt += 1
17617db96d56Sopenharmony_ci                return x*10+self
17627db96d56Sopenharmony_ci        a = X(5)
17637db96d56Sopenharmony_ci        b = X(5)
17647db96d56Sopenharmony_ci        c = X(7)
17657db96d56Sopenharmony_ci        self.assertEqual(X.f.cache_info(), (0, 0, 2, 0))
17667db96d56Sopenharmony_ci
17677db96d56Sopenharmony_ci        for x in 1, 2, 2, 3, 1, 1, 1, 2, 3, 3:
17687db96d56Sopenharmony_ci            self.assertEqual(a.f(x), x*10 + 5)
17697db96d56Sopenharmony_ci        self.assertEqual((a.f_cnt, b.f_cnt, c.f_cnt), (6, 0, 0))
17707db96d56Sopenharmony_ci        self.assertEqual(X.f.cache_info(), (4, 6, 2, 2))
17717db96d56Sopenharmony_ci
17727db96d56Sopenharmony_ci        for x in 1, 2, 1, 1, 1, 1, 3, 2, 2, 2:
17737db96d56Sopenharmony_ci            self.assertEqual(b.f(x), x*10 + 5)
17747db96d56Sopenharmony_ci        self.assertEqual((a.f_cnt, b.f_cnt, c.f_cnt), (6, 4, 0))
17757db96d56Sopenharmony_ci        self.assertEqual(X.f.cache_info(), (10, 10, 2, 2))
17767db96d56Sopenharmony_ci
17777db96d56Sopenharmony_ci        for x in 2, 1, 1, 1, 1, 2, 1, 3, 2, 1:
17787db96d56Sopenharmony_ci            self.assertEqual(c.f(x), x*10 + 7)
17797db96d56Sopenharmony_ci        self.assertEqual((a.f_cnt, b.f_cnt, c.f_cnt), (6, 4, 5))
17807db96d56Sopenharmony_ci        self.assertEqual(X.f.cache_info(), (15, 15, 2, 2))
17817db96d56Sopenharmony_ci
17827db96d56Sopenharmony_ci        self.assertEqual(a.f.cache_info(), X.f.cache_info())
17837db96d56Sopenharmony_ci        self.assertEqual(b.f.cache_info(), X.f.cache_info())
17847db96d56Sopenharmony_ci        self.assertEqual(c.f.cache_info(), X.f.cache_info())
17857db96d56Sopenharmony_ci
17867db96d56Sopenharmony_ci    def test_pickle(self):
17877db96d56Sopenharmony_ci        cls = self.__class__
17887db96d56Sopenharmony_ci        for f in cls.cached_func[0], cls.cached_meth, cls.cached_staticmeth:
17897db96d56Sopenharmony_ci            for proto in range(pickle.HIGHEST_PROTOCOL + 1):
17907db96d56Sopenharmony_ci                with self.subTest(proto=proto, func=f):
17917db96d56Sopenharmony_ci                    f_copy = pickle.loads(pickle.dumps(f, proto))
17927db96d56Sopenharmony_ci                    self.assertIs(f_copy, f)
17937db96d56Sopenharmony_ci
17947db96d56Sopenharmony_ci    def test_copy(self):
17957db96d56Sopenharmony_ci        cls = self.__class__
17967db96d56Sopenharmony_ci        def orig(x, y):
17977db96d56Sopenharmony_ci            return 3 * x + y
17987db96d56Sopenharmony_ci        part = self.module.partial(orig, 2)
17997db96d56Sopenharmony_ci        funcs = (cls.cached_func[0], cls.cached_meth, cls.cached_staticmeth,
18007db96d56Sopenharmony_ci                 self.module.lru_cache(2)(part))
18017db96d56Sopenharmony_ci        for f in funcs:
18027db96d56Sopenharmony_ci            with self.subTest(func=f):
18037db96d56Sopenharmony_ci                f_copy = copy.copy(f)
18047db96d56Sopenharmony_ci                self.assertIs(f_copy, f)
18057db96d56Sopenharmony_ci
18067db96d56Sopenharmony_ci    def test_deepcopy(self):
18077db96d56Sopenharmony_ci        cls = self.__class__
18087db96d56Sopenharmony_ci        def orig(x, y):
18097db96d56Sopenharmony_ci            return 3 * x + y
18107db96d56Sopenharmony_ci        part = self.module.partial(orig, 2)
18117db96d56Sopenharmony_ci        funcs = (cls.cached_func[0], cls.cached_meth, cls.cached_staticmeth,
18127db96d56Sopenharmony_ci                 self.module.lru_cache(2)(part))
18137db96d56Sopenharmony_ci        for f in funcs:
18147db96d56Sopenharmony_ci            with self.subTest(func=f):
18157db96d56Sopenharmony_ci                f_copy = copy.deepcopy(f)
18167db96d56Sopenharmony_ci                self.assertIs(f_copy, f)
18177db96d56Sopenharmony_ci
18187db96d56Sopenharmony_ci    def test_lru_cache_parameters(self):
18197db96d56Sopenharmony_ci        @self.module.lru_cache(maxsize=2)
18207db96d56Sopenharmony_ci        def f():
18217db96d56Sopenharmony_ci            return 1
18227db96d56Sopenharmony_ci        self.assertEqual(f.cache_parameters(), {'maxsize': 2, "typed": False})
18237db96d56Sopenharmony_ci
18247db96d56Sopenharmony_ci        @self.module.lru_cache(maxsize=1000, typed=True)
18257db96d56Sopenharmony_ci        def f():
18267db96d56Sopenharmony_ci            return 1
18277db96d56Sopenharmony_ci        self.assertEqual(f.cache_parameters(), {'maxsize': 1000, "typed": True})
18287db96d56Sopenharmony_ci
18297db96d56Sopenharmony_ci    def test_lru_cache_weakrefable(self):
18307db96d56Sopenharmony_ci        @self.module.lru_cache
18317db96d56Sopenharmony_ci        def test_function(x):
18327db96d56Sopenharmony_ci            return x
18337db96d56Sopenharmony_ci
18347db96d56Sopenharmony_ci        class A:
18357db96d56Sopenharmony_ci            @self.module.lru_cache
18367db96d56Sopenharmony_ci            def test_method(self, x):
18377db96d56Sopenharmony_ci                return (self, x)
18387db96d56Sopenharmony_ci
18397db96d56Sopenharmony_ci            @staticmethod
18407db96d56Sopenharmony_ci            @self.module.lru_cache
18417db96d56Sopenharmony_ci            def test_staticmethod(x):
18427db96d56Sopenharmony_ci                return (self, x)
18437db96d56Sopenharmony_ci
18447db96d56Sopenharmony_ci        refs = [weakref.ref(test_function),
18457db96d56Sopenharmony_ci                weakref.ref(A.test_method),
18467db96d56Sopenharmony_ci                weakref.ref(A.test_staticmethod)]
18477db96d56Sopenharmony_ci
18487db96d56Sopenharmony_ci        for ref in refs:
18497db96d56Sopenharmony_ci            self.assertIsNotNone(ref())
18507db96d56Sopenharmony_ci
18517db96d56Sopenharmony_ci        del A
18527db96d56Sopenharmony_ci        del test_function
18537db96d56Sopenharmony_ci        gc.collect()
18547db96d56Sopenharmony_ci
18557db96d56Sopenharmony_ci        for ref in refs:
18567db96d56Sopenharmony_ci            self.assertIsNone(ref())
18577db96d56Sopenharmony_ci
18587db96d56Sopenharmony_ci
18597db96d56Sopenharmony_ci@py_functools.lru_cache()
18607db96d56Sopenharmony_cidef py_cached_func(x, y):
18617db96d56Sopenharmony_ci    return 3 * x + y
18627db96d56Sopenharmony_ci
18637db96d56Sopenharmony_ci@c_functools.lru_cache()
18647db96d56Sopenharmony_cidef c_cached_func(x, y):
18657db96d56Sopenharmony_ci    return 3 * x + y
18667db96d56Sopenharmony_ci
18677db96d56Sopenharmony_ci
18687db96d56Sopenharmony_ciclass TestLRUPy(TestLRU, unittest.TestCase):
18697db96d56Sopenharmony_ci    module = py_functools
18707db96d56Sopenharmony_ci    cached_func = py_cached_func,
18717db96d56Sopenharmony_ci
18727db96d56Sopenharmony_ci    @module.lru_cache()
18737db96d56Sopenharmony_ci    def cached_meth(self, x, y):
18747db96d56Sopenharmony_ci        return 3 * x + y
18757db96d56Sopenharmony_ci
18767db96d56Sopenharmony_ci    @staticmethod
18777db96d56Sopenharmony_ci    @module.lru_cache()
18787db96d56Sopenharmony_ci    def cached_staticmeth(x, y):
18797db96d56Sopenharmony_ci        return 3 * x + y
18807db96d56Sopenharmony_ci
18817db96d56Sopenharmony_ci
18827db96d56Sopenharmony_ciclass TestLRUC(TestLRU, unittest.TestCase):
18837db96d56Sopenharmony_ci    module = c_functools
18847db96d56Sopenharmony_ci    cached_func = c_cached_func,
18857db96d56Sopenharmony_ci
18867db96d56Sopenharmony_ci    @module.lru_cache()
18877db96d56Sopenharmony_ci    def cached_meth(self, x, y):
18887db96d56Sopenharmony_ci        return 3 * x + y
18897db96d56Sopenharmony_ci
18907db96d56Sopenharmony_ci    @staticmethod
18917db96d56Sopenharmony_ci    @module.lru_cache()
18927db96d56Sopenharmony_ci    def cached_staticmeth(x, y):
18937db96d56Sopenharmony_ci        return 3 * x + y
18947db96d56Sopenharmony_ci
18957db96d56Sopenharmony_ci
18967db96d56Sopenharmony_ciclass TestSingleDispatch(unittest.TestCase):
18977db96d56Sopenharmony_ci    def test_simple_overloads(self):
18987db96d56Sopenharmony_ci        @functools.singledispatch
18997db96d56Sopenharmony_ci        def g(obj):
19007db96d56Sopenharmony_ci            return "base"
19017db96d56Sopenharmony_ci        def g_int(i):
19027db96d56Sopenharmony_ci            return "integer"
19037db96d56Sopenharmony_ci        g.register(int, g_int)
19047db96d56Sopenharmony_ci        self.assertEqual(g("str"), "base")
19057db96d56Sopenharmony_ci        self.assertEqual(g(1), "integer")
19067db96d56Sopenharmony_ci        self.assertEqual(g([1,2,3]), "base")
19077db96d56Sopenharmony_ci
19087db96d56Sopenharmony_ci    def test_mro(self):
19097db96d56Sopenharmony_ci        @functools.singledispatch
19107db96d56Sopenharmony_ci        def g(obj):
19117db96d56Sopenharmony_ci            return "base"
19127db96d56Sopenharmony_ci        class A:
19137db96d56Sopenharmony_ci            pass
19147db96d56Sopenharmony_ci        class C(A):
19157db96d56Sopenharmony_ci            pass
19167db96d56Sopenharmony_ci        class B(A):
19177db96d56Sopenharmony_ci            pass
19187db96d56Sopenharmony_ci        class D(C, B):
19197db96d56Sopenharmony_ci            pass
19207db96d56Sopenharmony_ci        def g_A(a):
19217db96d56Sopenharmony_ci            return "A"
19227db96d56Sopenharmony_ci        def g_B(b):
19237db96d56Sopenharmony_ci            return "B"
19247db96d56Sopenharmony_ci        g.register(A, g_A)
19257db96d56Sopenharmony_ci        g.register(B, g_B)
19267db96d56Sopenharmony_ci        self.assertEqual(g(A()), "A")
19277db96d56Sopenharmony_ci        self.assertEqual(g(B()), "B")
19287db96d56Sopenharmony_ci        self.assertEqual(g(C()), "A")
19297db96d56Sopenharmony_ci        self.assertEqual(g(D()), "B")
19307db96d56Sopenharmony_ci
19317db96d56Sopenharmony_ci    def test_register_decorator(self):
19327db96d56Sopenharmony_ci        @functools.singledispatch
19337db96d56Sopenharmony_ci        def g(obj):
19347db96d56Sopenharmony_ci            return "base"
19357db96d56Sopenharmony_ci        @g.register(int)
19367db96d56Sopenharmony_ci        def g_int(i):
19377db96d56Sopenharmony_ci            return "int %s" % (i,)
19387db96d56Sopenharmony_ci        self.assertEqual(g(""), "base")
19397db96d56Sopenharmony_ci        self.assertEqual(g(12), "int 12")
19407db96d56Sopenharmony_ci        self.assertIs(g.dispatch(int), g_int)
19417db96d56Sopenharmony_ci        self.assertIs(g.dispatch(object), g.dispatch(str))
19427db96d56Sopenharmony_ci        # Note: in the assert above this is not g.
19437db96d56Sopenharmony_ci        # @singledispatch returns the wrapper.
19447db96d56Sopenharmony_ci
19457db96d56Sopenharmony_ci    def test_wrapping_attributes(self):
19467db96d56Sopenharmony_ci        @functools.singledispatch
19477db96d56Sopenharmony_ci        def g(obj):
19487db96d56Sopenharmony_ci            "Simple test"
19497db96d56Sopenharmony_ci            return "Test"
19507db96d56Sopenharmony_ci        self.assertEqual(g.__name__, "g")
19517db96d56Sopenharmony_ci        if sys.flags.optimize < 2:
19527db96d56Sopenharmony_ci            self.assertEqual(g.__doc__, "Simple test")
19537db96d56Sopenharmony_ci
19547db96d56Sopenharmony_ci    @unittest.skipUnless(decimal, 'requires _decimal')
19557db96d56Sopenharmony_ci    @support.cpython_only
19567db96d56Sopenharmony_ci    def test_c_classes(self):
19577db96d56Sopenharmony_ci        @functools.singledispatch
19587db96d56Sopenharmony_ci        def g(obj):
19597db96d56Sopenharmony_ci            return "base"
19607db96d56Sopenharmony_ci        @g.register(decimal.DecimalException)
19617db96d56Sopenharmony_ci        def _(obj):
19627db96d56Sopenharmony_ci            return obj.args
19637db96d56Sopenharmony_ci        subn = decimal.Subnormal("Exponent < Emin")
19647db96d56Sopenharmony_ci        rnd = decimal.Rounded("Number got rounded")
19657db96d56Sopenharmony_ci        self.assertEqual(g(subn), ("Exponent < Emin",))
19667db96d56Sopenharmony_ci        self.assertEqual(g(rnd), ("Number got rounded",))
19677db96d56Sopenharmony_ci        @g.register(decimal.Subnormal)
19687db96d56Sopenharmony_ci        def _(obj):
19697db96d56Sopenharmony_ci            return "Too small to care."
19707db96d56Sopenharmony_ci        self.assertEqual(g(subn), "Too small to care.")
19717db96d56Sopenharmony_ci        self.assertEqual(g(rnd), ("Number got rounded",))
19727db96d56Sopenharmony_ci
19737db96d56Sopenharmony_ci    def test_compose_mro(self):
19747db96d56Sopenharmony_ci        # None of the examples in this test depend on haystack ordering.
19757db96d56Sopenharmony_ci        c = collections.abc
19767db96d56Sopenharmony_ci        mro = functools._compose_mro
19777db96d56Sopenharmony_ci        bases = [c.Sequence, c.MutableMapping, c.Mapping, c.Set]
19787db96d56Sopenharmony_ci        for haystack in permutations(bases):
19797db96d56Sopenharmony_ci            m = mro(dict, haystack)
19807db96d56Sopenharmony_ci            self.assertEqual(m, [dict, c.MutableMapping, c.Mapping,
19817db96d56Sopenharmony_ci                                 c.Collection, c.Sized, c.Iterable,
19827db96d56Sopenharmony_ci                                 c.Container, object])
19837db96d56Sopenharmony_ci        bases = [c.Container, c.Mapping, c.MutableMapping, collections.OrderedDict]
19847db96d56Sopenharmony_ci        for haystack in permutations(bases):
19857db96d56Sopenharmony_ci            m = mro(collections.ChainMap, haystack)
19867db96d56Sopenharmony_ci            self.assertEqual(m, [collections.ChainMap, c.MutableMapping, c.Mapping,
19877db96d56Sopenharmony_ci                                 c.Collection, c.Sized, c.Iterable,
19887db96d56Sopenharmony_ci                                 c.Container, object])
19897db96d56Sopenharmony_ci
19907db96d56Sopenharmony_ci        # If there's a generic function with implementations registered for
19917db96d56Sopenharmony_ci        # both Sized and Container, passing a defaultdict to it results in an
19927db96d56Sopenharmony_ci        # ambiguous dispatch which will cause a RuntimeError (see
19937db96d56Sopenharmony_ci        # test_mro_conflicts).
19947db96d56Sopenharmony_ci        bases = [c.Container, c.Sized, str]
19957db96d56Sopenharmony_ci        for haystack in permutations(bases):
19967db96d56Sopenharmony_ci            m = mro(collections.defaultdict, [c.Sized, c.Container, str])
19977db96d56Sopenharmony_ci            self.assertEqual(m, [collections.defaultdict, dict, c.Sized,
19987db96d56Sopenharmony_ci                                 c.Container, object])
19997db96d56Sopenharmony_ci
20007db96d56Sopenharmony_ci        # MutableSequence below is registered directly on D. In other words, it
20017db96d56Sopenharmony_ci        # precedes MutableMapping which means single dispatch will always
20027db96d56Sopenharmony_ci        # choose MutableSequence here.
20037db96d56Sopenharmony_ci        class D(collections.defaultdict):
20047db96d56Sopenharmony_ci            pass
20057db96d56Sopenharmony_ci        c.MutableSequence.register(D)
20067db96d56Sopenharmony_ci        bases = [c.MutableSequence, c.MutableMapping]
20077db96d56Sopenharmony_ci        for haystack in permutations(bases):
20087db96d56Sopenharmony_ci            m = mro(D, bases)
20097db96d56Sopenharmony_ci            self.assertEqual(m, [D, c.MutableSequence, c.Sequence, c.Reversible,
20107db96d56Sopenharmony_ci                                 collections.defaultdict, dict, c.MutableMapping, c.Mapping,
20117db96d56Sopenharmony_ci                                 c.Collection, c.Sized, c.Iterable, c.Container,
20127db96d56Sopenharmony_ci                                 object])
20137db96d56Sopenharmony_ci
20147db96d56Sopenharmony_ci        # Container and Callable are registered on different base classes and
20157db96d56Sopenharmony_ci        # a generic function supporting both should always pick the Callable
20167db96d56Sopenharmony_ci        # implementation if a C instance is passed.
20177db96d56Sopenharmony_ci        class C(collections.defaultdict):
20187db96d56Sopenharmony_ci            def __call__(self):
20197db96d56Sopenharmony_ci                pass
20207db96d56Sopenharmony_ci        bases = [c.Sized, c.Callable, c.Container, c.Mapping]
20217db96d56Sopenharmony_ci        for haystack in permutations(bases):
20227db96d56Sopenharmony_ci            m = mro(C, haystack)
20237db96d56Sopenharmony_ci            self.assertEqual(m, [C, c.Callable, collections.defaultdict, dict, c.Mapping,
20247db96d56Sopenharmony_ci                                 c.Collection, c.Sized, c.Iterable,
20257db96d56Sopenharmony_ci                                 c.Container, object])
20267db96d56Sopenharmony_ci
20277db96d56Sopenharmony_ci    def test_register_abc(self):
20287db96d56Sopenharmony_ci        c = collections.abc
20297db96d56Sopenharmony_ci        d = {"a": "b"}
20307db96d56Sopenharmony_ci        l = [1, 2, 3]
20317db96d56Sopenharmony_ci        s = {object(), None}
20327db96d56Sopenharmony_ci        f = frozenset(s)
20337db96d56Sopenharmony_ci        t = (1, 2, 3)
20347db96d56Sopenharmony_ci        @functools.singledispatch
20357db96d56Sopenharmony_ci        def g(obj):
20367db96d56Sopenharmony_ci            return "base"
20377db96d56Sopenharmony_ci        self.assertEqual(g(d), "base")
20387db96d56Sopenharmony_ci        self.assertEqual(g(l), "base")
20397db96d56Sopenharmony_ci        self.assertEqual(g(s), "base")
20407db96d56Sopenharmony_ci        self.assertEqual(g(f), "base")
20417db96d56Sopenharmony_ci        self.assertEqual(g(t), "base")
20427db96d56Sopenharmony_ci        g.register(c.Sized, lambda obj: "sized")
20437db96d56Sopenharmony_ci        self.assertEqual(g(d), "sized")
20447db96d56Sopenharmony_ci        self.assertEqual(g(l), "sized")
20457db96d56Sopenharmony_ci        self.assertEqual(g(s), "sized")
20467db96d56Sopenharmony_ci        self.assertEqual(g(f), "sized")
20477db96d56Sopenharmony_ci        self.assertEqual(g(t), "sized")
20487db96d56Sopenharmony_ci        g.register(c.MutableMapping, lambda obj: "mutablemapping")
20497db96d56Sopenharmony_ci        self.assertEqual(g(d), "mutablemapping")
20507db96d56Sopenharmony_ci        self.assertEqual(g(l), "sized")
20517db96d56Sopenharmony_ci        self.assertEqual(g(s), "sized")
20527db96d56Sopenharmony_ci        self.assertEqual(g(f), "sized")
20537db96d56Sopenharmony_ci        self.assertEqual(g(t), "sized")
20547db96d56Sopenharmony_ci        g.register(collections.ChainMap, lambda obj: "chainmap")
20557db96d56Sopenharmony_ci        self.assertEqual(g(d), "mutablemapping")  # irrelevant ABCs registered
20567db96d56Sopenharmony_ci        self.assertEqual(g(l), "sized")
20577db96d56Sopenharmony_ci        self.assertEqual(g(s), "sized")
20587db96d56Sopenharmony_ci        self.assertEqual(g(f), "sized")
20597db96d56Sopenharmony_ci        self.assertEqual(g(t), "sized")
20607db96d56Sopenharmony_ci        g.register(c.MutableSequence, lambda obj: "mutablesequence")
20617db96d56Sopenharmony_ci        self.assertEqual(g(d), "mutablemapping")
20627db96d56Sopenharmony_ci        self.assertEqual(g(l), "mutablesequence")
20637db96d56Sopenharmony_ci        self.assertEqual(g(s), "sized")
20647db96d56Sopenharmony_ci        self.assertEqual(g(f), "sized")
20657db96d56Sopenharmony_ci        self.assertEqual(g(t), "sized")
20667db96d56Sopenharmony_ci        g.register(c.MutableSet, lambda obj: "mutableset")
20677db96d56Sopenharmony_ci        self.assertEqual(g(d), "mutablemapping")
20687db96d56Sopenharmony_ci        self.assertEqual(g(l), "mutablesequence")
20697db96d56Sopenharmony_ci        self.assertEqual(g(s), "mutableset")
20707db96d56Sopenharmony_ci        self.assertEqual(g(f), "sized")
20717db96d56Sopenharmony_ci        self.assertEqual(g(t), "sized")
20727db96d56Sopenharmony_ci        g.register(c.Mapping, lambda obj: "mapping")
20737db96d56Sopenharmony_ci        self.assertEqual(g(d), "mutablemapping")  # not specific enough
20747db96d56Sopenharmony_ci        self.assertEqual(g(l), "mutablesequence")
20757db96d56Sopenharmony_ci        self.assertEqual(g(s), "mutableset")
20767db96d56Sopenharmony_ci        self.assertEqual(g(f), "sized")
20777db96d56Sopenharmony_ci        self.assertEqual(g(t), "sized")
20787db96d56Sopenharmony_ci        g.register(c.Sequence, lambda obj: "sequence")
20797db96d56Sopenharmony_ci        self.assertEqual(g(d), "mutablemapping")
20807db96d56Sopenharmony_ci        self.assertEqual(g(l), "mutablesequence")
20817db96d56Sopenharmony_ci        self.assertEqual(g(s), "mutableset")
20827db96d56Sopenharmony_ci        self.assertEqual(g(f), "sized")
20837db96d56Sopenharmony_ci        self.assertEqual(g(t), "sequence")
20847db96d56Sopenharmony_ci        g.register(c.Set, lambda obj: "set")
20857db96d56Sopenharmony_ci        self.assertEqual(g(d), "mutablemapping")
20867db96d56Sopenharmony_ci        self.assertEqual(g(l), "mutablesequence")
20877db96d56Sopenharmony_ci        self.assertEqual(g(s), "mutableset")
20887db96d56Sopenharmony_ci        self.assertEqual(g(f), "set")
20897db96d56Sopenharmony_ci        self.assertEqual(g(t), "sequence")
20907db96d56Sopenharmony_ci        g.register(dict, lambda obj: "dict")
20917db96d56Sopenharmony_ci        self.assertEqual(g(d), "dict")
20927db96d56Sopenharmony_ci        self.assertEqual(g(l), "mutablesequence")
20937db96d56Sopenharmony_ci        self.assertEqual(g(s), "mutableset")
20947db96d56Sopenharmony_ci        self.assertEqual(g(f), "set")
20957db96d56Sopenharmony_ci        self.assertEqual(g(t), "sequence")
20967db96d56Sopenharmony_ci        g.register(list, lambda obj: "list")
20977db96d56Sopenharmony_ci        self.assertEqual(g(d), "dict")
20987db96d56Sopenharmony_ci        self.assertEqual(g(l), "list")
20997db96d56Sopenharmony_ci        self.assertEqual(g(s), "mutableset")
21007db96d56Sopenharmony_ci        self.assertEqual(g(f), "set")
21017db96d56Sopenharmony_ci        self.assertEqual(g(t), "sequence")
21027db96d56Sopenharmony_ci        g.register(set, lambda obj: "concrete-set")
21037db96d56Sopenharmony_ci        self.assertEqual(g(d), "dict")
21047db96d56Sopenharmony_ci        self.assertEqual(g(l), "list")
21057db96d56Sopenharmony_ci        self.assertEqual(g(s), "concrete-set")
21067db96d56Sopenharmony_ci        self.assertEqual(g(f), "set")
21077db96d56Sopenharmony_ci        self.assertEqual(g(t), "sequence")
21087db96d56Sopenharmony_ci        g.register(frozenset, lambda obj: "frozen-set")
21097db96d56Sopenharmony_ci        self.assertEqual(g(d), "dict")
21107db96d56Sopenharmony_ci        self.assertEqual(g(l), "list")
21117db96d56Sopenharmony_ci        self.assertEqual(g(s), "concrete-set")
21127db96d56Sopenharmony_ci        self.assertEqual(g(f), "frozen-set")
21137db96d56Sopenharmony_ci        self.assertEqual(g(t), "sequence")
21147db96d56Sopenharmony_ci        g.register(tuple, lambda obj: "tuple")
21157db96d56Sopenharmony_ci        self.assertEqual(g(d), "dict")
21167db96d56Sopenharmony_ci        self.assertEqual(g(l), "list")
21177db96d56Sopenharmony_ci        self.assertEqual(g(s), "concrete-set")
21187db96d56Sopenharmony_ci        self.assertEqual(g(f), "frozen-set")
21197db96d56Sopenharmony_ci        self.assertEqual(g(t), "tuple")
21207db96d56Sopenharmony_ci
21217db96d56Sopenharmony_ci    def test_c3_abc(self):
21227db96d56Sopenharmony_ci        c = collections.abc
21237db96d56Sopenharmony_ci        mro = functools._c3_mro
21247db96d56Sopenharmony_ci        class A(object):
21257db96d56Sopenharmony_ci            pass
21267db96d56Sopenharmony_ci        class B(A):
21277db96d56Sopenharmony_ci            def __len__(self):
21287db96d56Sopenharmony_ci                return 0   # implies Sized
21297db96d56Sopenharmony_ci        @c.Container.register
21307db96d56Sopenharmony_ci        class C(object):
21317db96d56Sopenharmony_ci            pass
21327db96d56Sopenharmony_ci        class D(object):
21337db96d56Sopenharmony_ci            pass   # unrelated
21347db96d56Sopenharmony_ci        class X(D, C, B):
21357db96d56Sopenharmony_ci            def __call__(self):
21367db96d56Sopenharmony_ci                pass   # implies Callable
21377db96d56Sopenharmony_ci        expected = [X, c.Callable, D, C, c.Container, B, c.Sized, A, object]
21387db96d56Sopenharmony_ci        for abcs in permutations([c.Sized, c.Callable, c.Container]):
21397db96d56Sopenharmony_ci            self.assertEqual(mro(X, abcs=abcs), expected)
21407db96d56Sopenharmony_ci        # unrelated ABCs don't appear in the resulting MRO
21417db96d56Sopenharmony_ci        many_abcs = [c.Mapping, c.Sized, c.Callable, c.Container, c.Iterable]
21427db96d56Sopenharmony_ci        self.assertEqual(mro(X, abcs=many_abcs), expected)
21437db96d56Sopenharmony_ci
21447db96d56Sopenharmony_ci    def test_false_meta(self):
21457db96d56Sopenharmony_ci        # see issue23572
21467db96d56Sopenharmony_ci        class MetaA(type):
21477db96d56Sopenharmony_ci            def __len__(self):
21487db96d56Sopenharmony_ci                return 0
21497db96d56Sopenharmony_ci        class A(metaclass=MetaA):
21507db96d56Sopenharmony_ci            pass
21517db96d56Sopenharmony_ci        class AA(A):
21527db96d56Sopenharmony_ci            pass
21537db96d56Sopenharmony_ci        @functools.singledispatch
21547db96d56Sopenharmony_ci        def fun(a):
21557db96d56Sopenharmony_ci            return 'base A'
21567db96d56Sopenharmony_ci        @fun.register(A)
21577db96d56Sopenharmony_ci        def _(a):
21587db96d56Sopenharmony_ci            return 'fun A'
21597db96d56Sopenharmony_ci        aa = AA()
21607db96d56Sopenharmony_ci        self.assertEqual(fun(aa), 'fun A')
21617db96d56Sopenharmony_ci
21627db96d56Sopenharmony_ci    def test_mro_conflicts(self):
21637db96d56Sopenharmony_ci        c = collections.abc
21647db96d56Sopenharmony_ci        @functools.singledispatch
21657db96d56Sopenharmony_ci        def g(arg):
21667db96d56Sopenharmony_ci            return "base"
21677db96d56Sopenharmony_ci        class O(c.Sized):
21687db96d56Sopenharmony_ci            def __len__(self):
21697db96d56Sopenharmony_ci                return 0
21707db96d56Sopenharmony_ci        o = O()
21717db96d56Sopenharmony_ci        self.assertEqual(g(o), "base")
21727db96d56Sopenharmony_ci        g.register(c.Iterable, lambda arg: "iterable")
21737db96d56Sopenharmony_ci        g.register(c.Container, lambda arg: "container")
21747db96d56Sopenharmony_ci        g.register(c.Sized, lambda arg: "sized")
21757db96d56Sopenharmony_ci        g.register(c.Set, lambda arg: "set")
21767db96d56Sopenharmony_ci        self.assertEqual(g(o), "sized")
21777db96d56Sopenharmony_ci        c.Iterable.register(O)
21787db96d56Sopenharmony_ci        self.assertEqual(g(o), "sized")   # because it's explicitly in __mro__
21797db96d56Sopenharmony_ci        c.Container.register(O)
21807db96d56Sopenharmony_ci        self.assertEqual(g(o), "sized")   # see above: Sized is in __mro__
21817db96d56Sopenharmony_ci        c.Set.register(O)
21827db96d56Sopenharmony_ci        self.assertEqual(g(o), "set")     # because c.Set is a subclass of
21837db96d56Sopenharmony_ci                                          # c.Sized and c.Container
21847db96d56Sopenharmony_ci        class P:
21857db96d56Sopenharmony_ci            pass
21867db96d56Sopenharmony_ci        p = P()
21877db96d56Sopenharmony_ci        self.assertEqual(g(p), "base")
21887db96d56Sopenharmony_ci        c.Iterable.register(P)
21897db96d56Sopenharmony_ci        self.assertEqual(g(p), "iterable")
21907db96d56Sopenharmony_ci        c.Container.register(P)
21917db96d56Sopenharmony_ci        with self.assertRaises(RuntimeError) as re_one:
21927db96d56Sopenharmony_ci            g(p)
21937db96d56Sopenharmony_ci        self.assertIn(
21947db96d56Sopenharmony_ci            str(re_one.exception),
21957db96d56Sopenharmony_ci            (("Ambiguous dispatch: <class 'collections.abc.Container'> "
21967db96d56Sopenharmony_ci              "or <class 'collections.abc.Iterable'>"),
21977db96d56Sopenharmony_ci             ("Ambiguous dispatch: <class 'collections.abc.Iterable'> "
21987db96d56Sopenharmony_ci              "or <class 'collections.abc.Container'>")),
21997db96d56Sopenharmony_ci        )
22007db96d56Sopenharmony_ci        class Q(c.Sized):
22017db96d56Sopenharmony_ci            def __len__(self):
22027db96d56Sopenharmony_ci                return 0
22037db96d56Sopenharmony_ci        q = Q()
22047db96d56Sopenharmony_ci        self.assertEqual(g(q), "sized")
22057db96d56Sopenharmony_ci        c.Iterable.register(Q)
22067db96d56Sopenharmony_ci        self.assertEqual(g(q), "sized")   # because it's explicitly in __mro__
22077db96d56Sopenharmony_ci        c.Set.register(Q)
22087db96d56Sopenharmony_ci        self.assertEqual(g(q), "set")     # because c.Set is a subclass of
22097db96d56Sopenharmony_ci                                          # c.Sized and c.Iterable
22107db96d56Sopenharmony_ci        @functools.singledispatch
22117db96d56Sopenharmony_ci        def h(arg):
22127db96d56Sopenharmony_ci            return "base"
22137db96d56Sopenharmony_ci        @h.register(c.Sized)
22147db96d56Sopenharmony_ci        def _(arg):
22157db96d56Sopenharmony_ci            return "sized"
22167db96d56Sopenharmony_ci        @h.register(c.Container)
22177db96d56Sopenharmony_ci        def _(arg):
22187db96d56Sopenharmony_ci            return "container"
22197db96d56Sopenharmony_ci        # Even though Sized and Container are explicit bases of MutableMapping,
22207db96d56Sopenharmony_ci        # this ABC is implicitly registered on defaultdict which makes all of
22217db96d56Sopenharmony_ci        # MutableMapping's bases implicit as well from defaultdict's
22227db96d56Sopenharmony_ci        # perspective.
22237db96d56Sopenharmony_ci        with self.assertRaises(RuntimeError) as re_two:
22247db96d56Sopenharmony_ci            h(collections.defaultdict(lambda: 0))
22257db96d56Sopenharmony_ci        self.assertIn(
22267db96d56Sopenharmony_ci            str(re_two.exception),
22277db96d56Sopenharmony_ci            (("Ambiguous dispatch: <class 'collections.abc.Container'> "
22287db96d56Sopenharmony_ci              "or <class 'collections.abc.Sized'>"),
22297db96d56Sopenharmony_ci             ("Ambiguous dispatch: <class 'collections.abc.Sized'> "
22307db96d56Sopenharmony_ci              "or <class 'collections.abc.Container'>")),
22317db96d56Sopenharmony_ci        )
22327db96d56Sopenharmony_ci        class R(collections.defaultdict):
22337db96d56Sopenharmony_ci            pass
22347db96d56Sopenharmony_ci        c.MutableSequence.register(R)
22357db96d56Sopenharmony_ci        @functools.singledispatch
22367db96d56Sopenharmony_ci        def i(arg):
22377db96d56Sopenharmony_ci            return "base"
22387db96d56Sopenharmony_ci        @i.register(c.MutableMapping)
22397db96d56Sopenharmony_ci        def _(arg):
22407db96d56Sopenharmony_ci            return "mapping"
22417db96d56Sopenharmony_ci        @i.register(c.MutableSequence)
22427db96d56Sopenharmony_ci        def _(arg):
22437db96d56Sopenharmony_ci            return "sequence"
22447db96d56Sopenharmony_ci        r = R()
22457db96d56Sopenharmony_ci        self.assertEqual(i(r), "sequence")
22467db96d56Sopenharmony_ci        class S:
22477db96d56Sopenharmony_ci            pass
22487db96d56Sopenharmony_ci        class T(S, c.Sized):
22497db96d56Sopenharmony_ci            def __len__(self):
22507db96d56Sopenharmony_ci                return 0
22517db96d56Sopenharmony_ci        t = T()
22527db96d56Sopenharmony_ci        self.assertEqual(h(t), "sized")
22537db96d56Sopenharmony_ci        c.Container.register(T)
22547db96d56Sopenharmony_ci        self.assertEqual(h(t), "sized")   # because it's explicitly in the MRO
22557db96d56Sopenharmony_ci        class U:
22567db96d56Sopenharmony_ci            def __len__(self):
22577db96d56Sopenharmony_ci                return 0
22587db96d56Sopenharmony_ci        u = U()
22597db96d56Sopenharmony_ci        self.assertEqual(h(u), "sized")   # implicit Sized subclass inferred
22607db96d56Sopenharmony_ci                                          # from the existence of __len__()
22617db96d56Sopenharmony_ci        c.Container.register(U)
22627db96d56Sopenharmony_ci        # There is no preference for registered versus inferred ABCs.
22637db96d56Sopenharmony_ci        with self.assertRaises(RuntimeError) as re_three:
22647db96d56Sopenharmony_ci            h(u)
22657db96d56Sopenharmony_ci        self.assertIn(
22667db96d56Sopenharmony_ci            str(re_three.exception),
22677db96d56Sopenharmony_ci            (("Ambiguous dispatch: <class 'collections.abc.Container'> "
22687db96d56Sopenharmony_ci              "or <class 'collections.abc.Sized'>"),
22697db96d56Sopenharmony_ci             ("Ambiguous dispatch: <class 'collections.abc.Sized'> "
22707db96d56Sopenharmony_ci              "or <class 'collections.abc.Container'>")),
22717db96d56Sopenharmony_ci        )
22727db96d56Sopenharmony_ci        class V(c.Sized, S):
22737db96d56Sopenharmony_ci            def __len__(self):
22747db96d56Sopenharmony_ci                return 0
22757db96d56Sopenharmony_ci        @functools.singledispatch
22767db96d56Sopenharmony_ci        def j(arg):
22777db96d56Sopenharmony_ci            return "base"
22787db96d56Sopenharmony_ci        @j.register(S)
22797db96d56Sopenharmony_ci        def _(arg):
22807db96d56Sopenharmony_ci            return "s"
22817db96d56Sopenharmony_ci        @j.register(c.Container)
22827db96d56Sopenharmony_ci        def _(arg):
22837db96d56Sopenharmony_ci            return "container"
22847db96d56Sopenharmony_ci        v = V()
22857db96d56Sopenharmony_ci        self.assertEqual(j(v), "s")
22867db96d56Sopenharmony_ci        c.Container.register(V)
22877db96d56Sopenharmony_ci        self.assertEqual(j(v), "container")   # because it ends up right after
22887db96d56Sopenharmony_ci                                              # Sized in the MRO
22897db96d56Sopenharmony_ci
22907db96d56Sopenharmony_ci    def test_cache_invalidation(self):
22917db96d56Sopenharmony_ci        from collections import UserDict
22927db96d56Sopenharmony_ci        import weakref
22937db96d56Sopenharmony_ci
22947db96d56Sopenharmony_ci        class TracingDict(UserDict):
22957db96d56Sopenharmony_ci            def __init__(self, *args, **kwargs):
22967db96d56Sopenharmony_ci                super(TracingDict, self).__init__(*args, **kwargs)
22977db96d56Sopenharmony_ci                self.set_ops = []
22987db96d56Sopenharmony_ci                self.get_ops = []
22997db96d56Sopenharmony_ci            def __getitem__(self, key):
23007db96d56Sopenharmony_ci                result = self.data[key]
23017db96d56Sopenharmony_ci                self.get_ops.append(key)
23027db96d56Sopenharmony_ci                return result
23037db96d56Sopenharmony_ci            def __setitem__(self, key, value):
23047db96d56Sopenharmony_ci                self.set_ops.append(key)
23057db96d56Sopenharmony_ci                self.data[key] = value
23067db96d56Sopenharmony_ci            def clear(self):
23077db96d56Sopenharmony_ci                self.data.clear()
23087db96d56Sopenharmony_ci
23097db96d56Sopenharmony_ci        td = TracingDict()
23107db96d56Sopenharmony_ci        with support.swap_attr(weakref, "WeakKeyDictionary", lambda: td):
23117db96d56Sopenharmony_ci            c = collections.abc
23127db96d56Sopenharmony_ci            @functools.singledispatch
23137db96d56Sopenharmony_ci            def g(arg):
23147db96d56Sopenharmony_ci                return "base"
23157db96d56Sopenharmony_ci            d = {}
23167db96d56Sopenharmony_ci            l = []
23177db96d56Sopenharmony_ci            self.assertEqual(len(td), 0)
23187db96d56Sopenharmony_ci            self.assertEqual(g(d), "base")
23197db96d56Sopenharmony_ci            self.assertEqual(len(td), 1)
23207db96d56Sopenharmony_ci            self.assertEqual(td.get_ops, [])
23217db96d56Sopenharmony_ci            self.assertEqual(td.set_ops, [dict])
23227db96d56Sopenharmony_ci            self.assertEqual(td.data[dict], g.registry[object])
23237db96d56Sopenharmony_ci            self.assertEqual(g(l), "base")
23247db96d56Sopenharmony_ci            self.assertEqual(len(td), 2)
23257db96d56Sopenharmony_ci            self.assertEqual(td.get_ops, [])
23267db96d56Sopenharmony_ci            self.assertEqual(td.set_ops, [dict, list])
23277db96d56Sopenharmony_ci            self.assertEqual(td.data[dict], g.registry[object])
23287db96d56Sopenharmony_ci            self.assertEqual(td.data[list], g.registry[object])
23297db96d56Sopenharmony_ci            self.assertEqual(td.data[dict], td.data[list])
23307db96d56Sopenharmony_ci            self.assertEqual(g(l), "base")
23317db96d56Sopenharmony_ci            self.assertEqual(g(d), "base")
23327db96d56Sopenharmony_ci            self.assertEqual(td.get_ops, [list, dict])
23337db96d56Sopenharmony_ci            self.assertEqual(td.set_ops, [dict, list])
23347db96d56Sopenharmony_ci            g.register(list, lambda arg: "list")
23357db96d56Sopenharmony_ci            self.assertEqual(td.get_ops, [list, dict])
23367db96d56Sopenharmony_ci            self.assertEqual(len(td), 0)
23377db96d56Sopenharmony_ci            self.assertEqual(g(d), "base")
23387db96d56Sopenharmony_ci            self.assertEqual(len(td), 1)
23397db96d56Sopenharmony_ci            self.assertEqual(td.get_ops, [list, dict])
23407db96d56Sopenharmony_ci            self.assertEqual(td.set_ops, [dict, list, dict])
23417db96d56Sopenharmony_ci            self.assertEqual(td.data[dict],
23427db96d56Sopenharmony_ci                             functools._find_impl(dict, g.registry))
23437db96d56Sopenharmony_ci            self.assertEqual(g(l), "list")
23447db96d56Sopenharmony_ci            self.assertEqual(len(td), 2)
23457db96d56Sopenharmony_ci            self.assertEqual(td.get_ops, [list, dict])
23467db96d56Sopenharmony_ci            self.assertEqual(td.set_ops, [dict, list, dict, list])
23477db96d56Sopenharmony_ci            self.assertEqual(td.data[list],
23487db96d56Sopenharmony_ci                             functools._find_impl(list, g.registry))
23497db96d56Sopenharmony_ci            class X:
23507db96d56Sopenharmony_ci                pass
23517db96d56Sopenharmony_ci            c.MutableMapping.register(X)   # Will not invalidate the cache,
23527db96d56Sopenharmony_ci                                           # not using ABCs yet.
23537db96d56Sopenharmony_ci            self.assertEqual(g(d), "base")
23547db96d56Sopenharmony_ci            self.assertEqual(g(l), "list")
23557db96d56Sopenharmony_ci            self.assertEqual(td.get_ops, [list, dict, dict, list])
23567db96d56Sopenharmony_ci            self.assertEqual(td.set_ops, [dict, list, dict, list])
23577db96d56Sopenharmony_ci            g.register(c.Sized, lambda arg: "sized")
23587db96d56Sopenharmony_ci            self.assertEqual(len(td), 0)
23597db96d56Sopenharmony_ci            self.assertEqual(g(d), "sized")
23607db96d56Sopenharmony_ci            self.assertEqual(len(td), 1)
23617db96d56Sopenharmony_ci            self.assertEqual(td.get_ops, [list, dict, dict, list])
23627db96d56Sopenharmony_ci            self.assertEqual(td.set_ops, [dict, list, dict, list, dict])
23637db96d56Sopenharmony_ci            self.assertEqual(g(l), "list")
23647db96d56Sopenharmony_ci            self.assertEqual(len(td), 2)
23657db96d56Sopenharmony_ci            self.assertEqual(td.get_ops, [list, dict, dict, list])
23667db96d56Sopenharmony_ci            self.assertEqual(td.set_ops, [dict, list, dict, list, dict, list])
23677db96d56Sopenharmony_ci            self.assertEqual(g(l), "list")
23687db96d56Sopenharmony_ci            self.assertEqual(g(d), "sized")
23697db96d56Sopenharmony_ci            self.assertEqual(td.get_ops, [list, dict, dict, list, list, dict])
23707db96d56Sopenharmony_ci            self.assertEqual(td.set_ops, [dict, list, dict, list, dict, list])
23717db96d56Sopenharmony_ci            g.dispatch(list)
23727db96d56Sopenharmony_ci            g.dispatch(dict)
23737db96d56Sopenharmony_ci            self.assertEqual(td.get_ops, [list, dict, dict, list, list, dict,
23747db96d56Sopenharmony_ci                                          list, dict])
23757db96d56Sopenharmony_ci            self.assertEqual(td.set_ops, [dict, list, dict, list, dict, list])
23767db96d56Sopenharmony_ci            c.MutableSet.register(X)       # Will invalidate the cache.
23777db96d56Sopenharmony_ci            self.assertEqual(len(td), 2)   # Stale cache.
23787db96d56Sopenharmony_ci            self.assertEqual(g(l), "list")
23797db96d56Sopenharmony_ci            self.assertEqual(len(td), 1)
23807db96d56Sopenharmony_ci            g.register(c.MutableMapping, lambda arg: "mutablemapping")
23817db96d56Sopenharmony_ci            self.assertEqual(len(td), 0)
23827db96d56Sopenharmony_ci            self.assertEqual(g(d), "mutablemapping")
23837db96d56Sopenharmony_ci            self.assertEqual(len(td), 1)
23847db96d56Sopenharmony_ci            self.assertEqual(g(l), "list")
23857db96d56Sopenharmony_ci            self.assertEqual(len(td), 2)
23867db96d56Sopenharmony_ci            g.register(dict, lambda arg: "dict")
23877db96d56Sopenharmony_ci            self.assertEqual(g(d), "dict")
23887db96d56Sopenharmony_ci            self.assertEqual(g(l), "list")
23897db96d56Sopenharmony_ci            g._clear_cache()
23907db96d56Sopenharmony_ci            self.assertEqual(len(td), 0)
23917db96d56Sopenharmony_ci
23927db96d56Sopenharmony_ci    def test_annotations(self):
23937db96d56Sopenharmony_ci        @functools.singledispatch
23947db96d56Sopenharmony_ci        def i(arg):
23957db96d56Sopenharmony_ci            return "base"
23967db96d56Sopenharmony_ci        @i.register
23977db96d56Sopenharmony_ci        def _(arg: collections.abc.Mapping):
23987db96d56Sopenharmony_ci            return "mapping"
23997db96d56Sopenharmony_ci        @i.register
24007db96d56Sopenharmony_ci        def _(arg: "collections.abc.Sequence"):
24017db96d56Sopenharmony_ci            return "sequence"
24027db96d56Sopenharmony_ci        self.assertEqual(i(None), "base")
24037db96d56Sopenharmony_ci        self.assertEqual(i({"a": 1}), "mapping")
24047db96d56Sopenharmony_ci        self.assertEqual(i([1, 2, 3]), "sequence")
24057db96d56Sopenharmony_ci        self.assertEqual(i((1, 2, 3)), "sequence")
24067db96d56Sopenharmony_ci        self.assertEqual(i("str"), "sequence")
24077db96d56Sopenharmony_ci
24087db96d56Sopenharmony_ci        # Registering classes as callables doesn't work with annotations,
24097db96d56Sopenharmony_ci        # you need to pass the type explicitly.
24107db96d56Sopenharmony_ci        @i.register(str)
24117db96d56Sopenharmony_ci        class _:
24127db96d56Sopenharmony_ci            def __init__(self, arg):
24137db96d56Sopenharmony_ci                self.arg = arg
24147db96d56Sopenharmony_ci
24157db96d56Sopenharmony_ci            def __eq__(self, other):
24167db96d56Sopenharmony_ci                return self.arg == other
24177db96d56Sopenharmony_ci        self.assertEqual(i("str"), "str")
24187db96d56Sopenharmony_ci
24197db96d56Sopenharmony_ci    def test_method_register(self):
24207db96d56Sopenharmony_ci        class A:
24217db96d56Sopenharmony_ci            @functools.singledispatchmethod
24227db96d56Sopenharmony_ci            def t(self, arg):
24237db96d56Sopenharmony_ci                self.arg = "base"
24247db96d56Sopenharmony_ci            @t.register(int)
24257db96d56Sopenharmony_ci            def _(self, arg):
24267db96d56Sopenharmony_ci                self.arg = "int"
24277db96d56Sopenharmony_ci            @t.register(str)
24287db96d56Sopenharmony_ci            def _(self, arg):
24297db96d56Sopenharmony_ci                self.arg = "str"
24307db96d56Sopenharmony_ci        a = A()
24317db96d56Sopenharmony_ci
24327db96d56Sopenharmony_ci        a.t(0)
24337db96d56Sopenharmony_ci        self.assertEqual(a.arg, "int")
24347db96d56Sopenharmony_ci        aa = A()
24357db96d56Sopenharmony_ci        self.assertFalse(hasattr(aa, 'arg'))
24367db96d56Sopenharmony_ci        a.t('')
24377db96d56Sopenharmony_ci        self.assertEqual(a.arg, "str")
24387db96d56Sopenharmony_ci        aa = A()
24397db96d56Sopenharmony_ci        self.assertFalse(hasattr(aa, 'arg'))
24407db96d56Sopenharmony_ci        a.t(0.0)
24417db96d56Sopenharmony_ci        self.assertEqual(a.arg, "base")
24427db96d56Sopenharmony_ci        aa = A()
24437db96d56Sopenharmony_ci        self.assertFalse(hasattr(aa, 'arg'))
24447db96d56Sopenharmony_ci
24457db96d56Sopenharmony_ci    def test_staticmethod_register(self):
24467db96d56Sopenharmony_ci        class A:
24477db96d56Sopenharmony_ci            @functools.singledispatchmethod
24487db96d56Sopenharmony_ci            @staticmethod
24497db96d56Sopenharmony_ci            def t(arg):
24507db96d56Sopenharmony_ci                return arg
24517db96d56Sopenharmony_ci            @t.register(int)
24527db96d56Sopenharmony_ci            @staticmethod
24537db96d56Sopenharmony_ci            def _(arg):
24547db96d56Sopenharmony_ci                return isinstance(arg, int)
24557db96d56Sopenharmony_ci            @t.register(str)
24567db96d56Sopenharmony_ci            @staticmethod
24577db96d56Sopenharmony_ci            def _(arg):
24587db96d56Sopenharmony_ci                return isinstance(arg, str)
24597db96d56Sopenharmony_ci        a = A()
24607db96d56Sopenharmony_ci
24617db96d56Sopenharmony_ci        self.assertTrue(A.t(0))
24627db96d56Sopenharmony_ci        self.assertTrue(A.t(''))
24637db96d56Sopenharmony_ci        self.assertEqual(A.t(0.0), 0.0)
24647db96d56Sopenharmony_ci
24657db96d56Sopenharmony_ci    def test_classmethod_register(self):
24667db96d56Sopenharmony_ci        class A:
24677db96d56Sopenharmony_ci            def __init__(self, arg):
24687db96d56Sopenharmony_ci                self.arg = arg
24697db96d56Sopenharmony_ci
24707db96d56Sopenharmony_ci            @functools.singledispatchmethod
24717db96d56Sopenharmony_ci            @classmethod
24727db96d56Sopenharmony_ci            def t(cls, arg):
24737db96d56Sopenharmony_ci                return cls("base")
24747db96d56Sopenharmony_ci            @t.register(int)
24757db96d56Sopenharmony_ci            @classmethod
24767db96d56Sopenharmony_ci            def _(cls, arg):
24777db96d56Sopenharmony_ci                return cls("int")
24787db96d56Sopenharmony_ci            @t.register(str)
24797db96d56Sopenharmony_ci            @classmethod
24807db96d56Sopenharmony_ci            def _(cls, arg):
24817db96d56Sopenharmony_ci                return cls("str")
24827db96d56Sopenharmony_ci
24837db96d56Sopenharmony_ci        self.assertEqual(A.t(0).arg, "int")
24847db96d56Sopenharmony_ci        self.assertEqual(A.t('').arg, "str")
24857db96d56Sopenharmony_ci        self.assertEqual(A.t(0.0).arg, "base")
24867db96d56Sopenharmony_ci
24877db96d56Sopenharmony_ci    def test_callable_register(self):
24887db96d56Sopenharmony_ci        class A:
24897db96d56Sopenharmony_ci            def __init__(self, arg):
24907db96d56Sopenharmony_ci                self.arg = arg
24917db96d56Sopenharmony_ci
24927db96d56Sopenharmony_ci            @functools.singledispatchmethod
24937db96d56Sopenharmony_ci            @classmethod
24947db96d56Sopenharmony_ci            def t(cls, arg):
24957db96d56Sopenharmony_ci                return cls("base")
24967db96d56Sopenharmony_ci
24977db96d56Sopenharmony_ci        @A.t.register(int)
24987db96d56Sopenharmony_ci        @classmethod
24997db96d56Sopenharmony_ci        def _(cls, arg):
25007db96d56Sopenharmony_ci            return cls("int")
25017db96d56Sopenharmony_ci        @A.t.register(str)
25027db96d56Sopenharmony_ci        @classmethod
25037db96d56Sopenharmony_ci        def _(cls, arg):
25047db96d56Sopenharmony_ci            return cls("str")
25057db96d56Sopenharmony_ci
25067db96d56Sopenharmony_ci        self.assertEqual(A.t(0).arg, "int")
25077db96d56Sopenharmony_ci        self.assertEqual(A.t('').arg, "str")
25087db96d56Sopenharmony_ci        self.assertEqual(A.t(0.0).arg, "base")
25097db96d56Sopenharmony_ci
25107db96d56Sopenharmony_ci    def test_abstractmethod_register(self):
25117db96d56Sopenharmony_ci        class Abstract(metaclass=abc.ABCMeta):
25127db96d56Sopenharmony_ci
25137db96d56Sopenharmony_ci            @functools.singledispatchmethod
25147db96d56Sopenharmony_ci            @abc.abstractmethod
25157db96d56Sopenharmony_ci            def add(self, x, y):
25167db96d56Sopenharmony_ci                pass
25177db96d56Sopenharmony_ci
25187db96d56Sopenharmony_ci        self.assertTrue(Abstract.add.__isabstractmethod__)
25197db96d56Sopenharmony_ci        self.assertTrue(Abstract.__dict__['add'].__isabstractmethod__)
25207db96d56Sopenharmony_ci
25217db96d56Sopenharmony_ci        with self.assertRaises(TypeError):
25227db96d56Sopenharmony_ci            Abstract()
25237db96d56Sopenharmony_ci
25247db96d56Sopenharmony_ci    def test_type_ann_register(self):
25257db96d56Sopenharmony_ci        class A:
25267db96d56Sopenharmony_ci            @functools.singledispatchmethod
25277db96d56Sopenharmony_ci            def t(self, arg):
25287db96d56Sopenharmony_ci                return "base"
25297db96d56Sopenharmony_ci            @t.register
25307db96d56Sopenharmony_ci            def _(self, arg: int):
25317db96d56Sopenharmony_ci                return "int"
25327db96d56Sopenharmony_ci            @t.register
25337db96d56Sopenharmony_ci            def _(self, arg: str):
25347db96d56Sopenharmony_ci                return "str"
25357db96d56Sopenharmony_ci        a = A()
25367db96d56Sopenharmony_ci
25377db96d56Sopenharmony_ci        self.assertEqual(a.t(0), "int")
25387db96d56Sopenharmony_ci        self.assertEqual(a.t(''), "str")
25397db96d56Sopenharmony_ci        self.assertEqual(a.t(0.0), "base")
25407db96d56Sopenharmony_ci
25417db96d56Sopenharmony_ci    def test_staticmethod_type_ann_register(self):
25427db96d56Sopenharmony_ci        class A:
25437db96d56Sopenharmony_ci            @functools.singledispatchmethod
25447db96d56Sopenharmony_ci            @staticmethod
25457db96d56Sopenharmony_ci            def t(arg):
25467db96d56Sopenharmony_ci                return arg
25477db96d56Sopenharmony_ci            @t.register
25487db96d56Sopenharmony_ci            @staticmethod
25497db96d56Sopenharmony_ci            def _(arg: int):
25507db96d56Sopenharmony_ci                return isinstance(arg, int)
25517db96d56Sopenharmony_ci            @t.register
25527db96d56Sopenharmony_ci            @staticmethod
25537db96d56Sopenharmony_ci            def _(arg: str):
25547db96d56Sopenharmony_ci                return isinstance(arg, str)
25557db96d56Sopenharmony_ci        a = A()
25567db96d56Sopenharmony_ci
25577db96d56Sopenharmony_ci        self.assertTrue(A.t(0))
25587db96d56Sopenharmony_ci        self.assertTrue(A.t(''))
25597db96d56Sopenharmony_ci        self.assertEqual(A.t(0.0), 0.0)
25607db96d56Sopenharmony_ci
25617db96d56Sopenharmony_ci    def test_classmethod_type_ann_register(self):
25627db96d56Sopenharmony_ci        class A:
25637db96d56Sopenharmony_ci            def __init__(self, arg):
25647db96d56Sopenharmony_ci                self.arg = arg
25657db96d56Sopenharmony_ci
25667db96d56Sopenharmony_ci            @functools.singledispatchmethod
25677db96d56Sopenharmony_ci            @classmethod
25687db96d56Sopenharmony_ci            def t(cls, arg):
25697db96d56Sopenharmony_ci                return cls("base")
25707db96d56Sopenharmony_ci            @t.register
25717db96d56Sopenharmony_ci            @classmethod
25727db96d56Sopenharmony_ci            def _(cls, arg: int):
25737db96d56Sopenharmony_ci                return cls("int")
25747db96d56Sopenharmony_ci            @t.register
25757db96d56Sopenharmony_ci            @classmethod
25767db96d56Sopenharmony_ci            def _(cls, arg: str):
25777db96d56Sopenharmony_ci                return cls("str")
25787db96d56Sopenharmony_ci
25797db96d56Sopenharmony_ci        self.assertEqual(A.t(0).arg, "int")
25807db96d56Sopenharmony_ci        self.assertEqual(A.t('').arg, "str")
25817db96d56Sopenharmony_ci        self.assertEqual(A.t(0.0).arg, "base")
25827db96d56Sopenharmony_ci
25837db96d56Sopenharmony_ci    def test_method_wrapping_attributes(self):
25847db96d56Sopenharmony_ci        class A:
25857db96d56Sopenharmony_ci            @functools.singledispatchmethod
25867db96d56Sopenharmony_ci            def func(self, arg: int) -> str:
25877db96d56Sopenharmony_ci                """My function docstring"""
25887db96d56Sopenharmony_ci                return str(arg)
25897db96d56Sopenharmony_ci            @functools.singledispatchmethod
25907db96d56Sopenharmony_ci            @classmethod
25917db96d56Sopenharmony_ci            def cls_func(cls, arg: int) -> str:
25927db96d56Sopenharmony_ci                """My function docstring"""
25937db96d56Sopenharmony_ci                return str(arg)
25947db96d56Sopenharmony_ci            @functools.singledispatchmethod
25957db96d56Sopenharmony_ci            @staticmethod
25967db96d56Sopenharmony_ci            def static_func(arg: int) -> str:
25977db96d56Sopenharmony_ci                """My function docstring"""
25987db96d56Sopenharmony_ci                return str(arg)
25997db96d56Sopenharmony_ci
26007db96d56Sopenharmony_ci        for meth in (
26017db96d56Sopenharmony_ci            A.func,
26027db96d56Sopenharmony_ci            A().func,
26037db96d56Sopenharmony_ci            A.cls_func,
26047db96d56Sopenharmony_ci            A().cls_func,
26057db96d56Sopenharmony_ci            A.static_func,
26067db96d56Sopenharmony_ci            A().static_func
26077db96d56Sopenharmony_ci        ):
26087db96d56Sopenharmony_ci            with self.subTest(meth=meth):
26097db96d56Sopenharmony_ci                self.assertEqual(meth.__doc__, 'My function docstring')
26107db96d56Sopenharmony_ci                self.assertEqual(meth.__annotations__['arg'], int)
26117db96d56Sopenharmony_ci
26127db96d56Sopenharmony_ci        self.assertEqual(A.func.__name__, 'func')
26137db96d56Sopenharmony_ci        self.assertEqual(A().func.__name__, 'func')
26147db96d56Sopenharmony_ci        self.assertEqual(A.cls_func.__name__, 'cls_func')
26157db96d56Sopenharmony_ci        self.assertEqual(A().cls_func.__name__, 'cls_func')
26167db96d56Sopenharmony_ci        self.assertEqual(A.static_func.__name__, 'static_func')
26177db96d56Sopenharmony_ci        self.assertEqual(A().static_func.__name__, 'static_func')
26187db96d56Sopenharmony_ci
26197db96d56Sopenharmony_ci    def test_double_wrapped_methods(self):
26207db96d56Sopenharmony_ci        def classmethod_friendly_decorator(func):
26217db96d56Sopenharmony_ci            wrapped = func.__func__
26227db96d56Sopenharmony_ci            @classmethod
26237db96d56Sopenharmony_ci            @functools.wraps(wrapped)
26247db96d56Sopenharmony_ci            def wrapper(*args, **kwargs):
26257db96d56Sopenharmony_ci                return wrapped(*args, **kwargs)
26267db96d56Sopenharmony_ci            return wrapper
26277db96d56Sopenharmony_ci
26287db96d56Sopenharmony_ci        class WithoutSingleDispatch:
26297db96d56Sopenharmony_ci            @classmethod
26307db96d56Sopenharmony_ci            @contextlib.contextmanager
26317db96d56Sopenharmony_ci            def cls_context_manager(cls, arg: int) -> str:
26327db96d56Sopenharmony_ci                try:
26337db96d56Sopenharmony_ci                    yield str(arg)
26347db96d56Sopenharmony_ci                finally:
26357db96d56Sopenharmony_ci                    return 'Done'
26367db96d56Sopenharmony_ci
26377db96d56Sopenharmony_ci            @classmethod_friendly_decorator
26387db96d56Sopenharmony_ci            @classmethod
26397db96d56Sopenharmony_ci            def decorated_classmethod(cls, arg: int) -> str:
26407db96d56Sopenharmony_ci                return str(arg)
26417db96d56Sopenharmony_ci
26427db96d56Sopenharmony_ci        class WithSingleDispatch:
26437db96d56Sopenharmony_ci            @functools.singledispatchmethod
26447db96d56Sopenharmony_ci            @classmethod
26457db96d56Sopenharmony_ci            @contextlib.contextmanager
26467db96d56Sopenharmony_ci            def cls_context_manager(cls, arg: int) -> str:
26477db96d56Sopenharmony_ci                """My function docstring"""
26487db96d56Sopenharmony_ci                try:
26497db96d56Sopenharmony_ci                    yield str(arg)
26507db96d56Sopenharmony_ci                finally:
26517db96d56Sopenharmony_ci                    return 'Done'
26527db96d56Sopenharmony_ci
26537db96d56Sopenharmony_ci            @functools.singledispatchmethod
26547db96d56Sopenharmony_ci            @classmethod_friendly_decorator
26557db96d56Sopenharmony_ci            @classmethod
26567db96d56Sopenharmony_ci            def decorated_classmethod(cls, arg: int) -> str:
26577db96d56Sopenharmony_ci                """My function docstring"""
26587db96d56Sopenharmony_ci                return str(arg)
26597db96d56Sopenharmony_ci
26607db96d56Sopenharmony_ci        # These are sanity checks
26617db96d56Sopenharmony_ci        # to test the test itself is working as expected
26627db96d56Sopenharmony_ci        with WithoutSingleDispatch.cls_context_manager(5) as foo:
26637db96d56Sopenharmony_ci            without_single_dispatch_foo = foo
26647db96d56Sopenharmony_ci
26657db96d56Sopenharmony_ci        with WithSingleDispatch.cls_context_manager(5) as foo:
26667db96d56Sopenharmony_ci            single_dispatch_foo = foo
26677db96d56Sopenharmony_ci
26687db96d56Sopenharmony_ci        self.assertEqual(without_single_dispatch_foo, single_dispatch_foo)
26697db96d56Sopenharmony_ci        self.assertEqual(single_dispatch_foo, '5')
26707db96d56Sopenharmony_ci
26717db96d56Sopenharmony_ci        self.assertEqual(
26727db96d56Sopenharmony_ci            WithoutSingleDispatch.decorated_classmethod(5),
26737db96d56Sopenharmony_ci            WithSingleDispatch.decorated_classmethod(5)
26747db96d56Sopenharmony_ci        )
26757db96d56Sopenharmony_ci
26767db96d56Sopenharmony_ci        self.assertEqual(WithSingleDispatch.decorated_classmethod(5), '5')
26777db96d56Sopenharmony_ci
26787db96d56Sopenharmony_ci        # Behavioural checks now follow
26797db96d56Sopenharmony_ci        for method_name in ('cls_context_manager', 'decorated_classmethod'):
26807db96d56Sopenharmony_ci            with self.subTest(method=method_name):
26817db96d56Sopenharmony_ci                self.assertEqual(
26827db96d56Sopenharmony_ci                    getattr(WithSingleDispatch, method_name).__name__,
26837db96d56Sopenharmony_ci                    getattr(WithoutSingleDispatch, method_name).__name__
26847db96d56Sopenharmony_ci                )
26857db96d56Sopenharmony_ci
26867db96d56Sopenharmony_ci                self.assertEqual(
26877db96d56Sopenharmony_ci                    getattr(WithSingleDispatch(), method_name).__name__,
26887db96d56Sopenharmony_ci                    getattr(WithoutSingleDispatch(), method_name).__name__
26897db96d56Sopenharmony_ci                )
26907db96d56Sopenharmony_ci
26917db96d56Sopenharmony_ci        for meth in (
26927db96d56Sopenharmony_ci            WithSingleDispatch.cls_context_manager,
26937db96d56Sopenharmony_ci            WithSingleDispatch().cls_context_manager,
26947db96d56Sopenharmony_ci            WithSingleDispatch.decorated_classmethod,
26957db96d56Sopenharmony_ci            WithSingleDispatch().decorated_classmethod
26967db96d56Sopenharmony_ci        ):
26977db96d56Sopenharmony_ci            with self.subTest(meth=meth):
26987db96d56Sopenharmony_ci                self.assertEqual(meth.__doc__, 'My function docstring')
26997db96d56Sopenharmony_ci                self.assertEqual(meth.__annotations__['arg'], int)
27007db96d56Sopenharmony_ci
27017db96d56Sopenharmony_ci        self.assertEqual(
27027db96d56Sopenharmony_ci            WithSingleDispatch.cls_context_manager.__name__,
27037db96d56Sopenharmony_ci            'cls_context_manager'
27047db96d56Sopenharmony_ci        )
27057db96d56Sopenharmony_ci        self.assertEqual(
27067db96d56Sopenharmony_ci            WithSingleDispatch().cls_context_manager.__name__,
27077db96d56Sopenharmony_ci            'cls_context_manager'
27087db96d56Sopenharmony_ci        )
27097db96d56Sopenharmony_ci        self.assertEqual(
27107db96d56Sopenharmony_ci            WithSingleDispatch.decorated_classmethod.__name__,
27117db96d56Sopenharmony_ci            'decorated_classmethod'
27127db96d56Sopenharmony_ci        )
27137db96d56Sopenharmony_ci        self.assertEqual(
27147db96d56Sopenharmony_ci            WithSingleDispatch().decorated_classmethod.__name__,
27157db96d56Sopenharmony_ci            'decorated_classmethod'
27167db96d56Sopenharmony_ci        )
27177db96d56Sopenharmony_ci
27187db96d56Sopenharmony_ci    def test_invalid_registrations(self):
27197db96d56Sopenharmony_ci        msg_prefix = "Invalid first argument to `register()`: "
27207db96d56Sopenharmony_ci        msg_suffix = (
27217db96d56Sopenharmony_ci            ". Use either `@register(some_class)` or plain `@register` on an "
27227db96d56Sopenharmony_ci            "annotated function."
27237db96d56Sopenharmony_ci        )
27247db96d56Sopenharmony_ci        @functools.singledispatch
27257db96d56Sopenharmony_ci        def i(arg):
27267db96d56Sopenharmony_ci            return "base"
27277db96d56Sopenharmony_ci        with self.assertRaises(TypeError) as exc:
27287db96d56Sopenharmony_ci            @i.register(42)
27297db96d56Sopenharmony_ci            def _(arg):
27307db96d56Sopenharmony_ci                return "I annotated with a non-type"
27317db96d56Sopenharmony_ci        self.assertTrue(str(exc.exception).startswith(msg_prefix + "42"))
27327db96d56Sopenharmony_ci        self.assertTrue(str(exc.exception).endswith(msg_suffix))
27337db96d56Sopenharmony_ci        with self.assertRaises(TypeError) as exc:
27347db96d56Sopenharmony_ci            @i.register
27357db96d56Sopenharmony_ci            def _(arg):
27367db96d56Sopenharmony_ci                return "I forgot to annotate"
27377db96d56Sopenharmony_ci        self.assertTrue(str(exc.exception).startswith(msg_prefix +
27387db96d56Sopenharmony_ci            "<function TestSingleDispatch.test_invalid_registrations.<locals>._"
27397db96d56Sopenharmony_ci        ))
27407db96d56Sopenharmony_ci        self.assertTrue(str(exc.exception).endswith(msg_suffix))
27417db96d56Sopenharmony_ci
27427db96d56Sopenharmony_ci        with self.assertRaises(TypeError) as exc:
27437db96d56Sopenharmony_ci            @i.register
27447db96d56Sopenharmony_ci            def _(arg: typing.Iterable[str]):
27457db96d56Sopenharmony_ci                # At runtime, dispatching on generics is impossible.
27467db96d56Sopenharmony_ci                # When registering implementations with singledispatch, avoid
27477db96d56Sopenharmony_ci                # types from `typing`. Instead, annotate with regular types
27487db96d56Sopenharmony_ci                # or ABCs.
27497db96d56Sopenharmony_ci                return "I annotated with a generic collection"
27507db96d56Sopenharmony_ci        self.assertTrue(str(exc.exception).startswith(
27517db96d56Sopenharmony_ci            "Invalid annotation for 'arg'."
27527db96d56Sopenharmony_ci        ))
27537db96d56Sopenharmony_ci        self.assertTrue(str(exc.exception).endswith(
27547db96d56Sopenharmony_ci            'typing.Iterable[str] is not a class.'
27557db96d56Sopenharmony_ci        ))
27567db96d56Sopenharmony_ci
27577db96d56Sopenharmony_ci        with self.assertRaises(TypeError) as exc:
27587db96d56Sopenharmony_ci            @i.register
27597db96d56Sopenharmony_ci            def _(arg: typing.Union[int, typing.Iterable[str]]):
27607db96d56Sopenharmony_ci                return "Invalid Union"
27617db96d56Sopenharmony_ci        self.assertTrue(str(exc.exception).startswith(
27627db96d56Sopenharmony_ci            "Invalid annotation for 'arg'."
27637db96d56Sopenharmony_ci        ))
27647db96d56Sopenharmony_ci        self.assertTrue(str(exc.exception).endswith(
27657db96d56Sopenharmony_ci            'typing.Union[int, typing.Iterable[str]] not all arguments are classes.'
27667db96d56Sopenharmony_ci        ))
27677db96d56Sopenharmony_ci
27687db96d56Sopenharmony_ci    def test_invalid_positional_argument(self):
27697db96d56Sopenharmony_ci        @functools.singledispatch
27707db96d56Sopenharmony_ci        def f(*args):
27717db96d56Sopenharmony_ci            pass
27727db96d56Sopenharmony_ci        msg = 'f requires at least 1 positional argument'
27737db96d56Sopenharmony_ci        with self.assertRaisesRegex(TypeError, msg):
27747db96d56Sopenharmony_ci            f()
27757db96d56Sopenharmony_ci
27767db96d56Sopenharmony_ci    def test_union(self):
27777db96d56Sopenharmony_ci        @functools.singledispatch
27787db96d56Sopenharmony_ci        def f(arg):
27797db96d56Sopenharmony_ci            return "default"
27807db96d56Sopenharmony_ci
27817db96d56Sopenharmony_ci        @f.register
27827db96d56Sopenharmony_ci        def _(arg: typing.Union[str, bytes]):
27837db96d56Sopenharmony_ci            return "typing.Union"
27847db96d56Sopenharmony_ci
27857db96d56Sopenharmony_ci        @f.register
27867db96d56Sopenharmony_ci        def _(arg: int | float):
27877db96d56Sopenharmony_ci            return "types.UnionType"
27887db96d56Sopenharmony_ci
27897db96d56Sopenharmony_ci        self.assertEqual(f([]), "default")
27907db96d56Sopenharmony_ci        self.assertEqual(f(""), "typing.Union")
27917db96d56Sopenharmony_ci        self.assertEqual(f(b""), "typing.Union")
27927db96d56Sopenharmony_ci        self.assertEqual(f(1), "types.UnionType")
27937db96d56Sopenharmony_ci        self.assertEqual(f(1.0), "types.UnionType")
27947db96d56Sopenharmony_ci
27957db96d56Sopenharmony_ci    def test_union_conflict(self):
27967db96d56Sopenharmony_ci        @functools.singledispatch
27977db96d56Sopenharmony_ci        def f(arg):
27987db96d56Sopenharmony_ci            return "default"
27997db96d56Sopenharmony_ci
28007db96d56Sopenharmony_ci        @f.register
28017db96d56Sopenharmony_ci        def _(arg: typing.Union[str, bytes]):
28027db96d56Sopenharmony_ci            return "typing.Union"
28037db96d56Sopenharmony_ci
28047db96d56Sopenharmony_ci        @f.register
28057db96d56Sopenharmony_ci        def _(arg: int | str):
28067db96d56Sopenharmony_ci            return "types.UnionType"
28077db96d56Sopenharmony_ci
28087db96d56Sopenharmony_ci        self.assertEqual(f([]), "default")
28097db96d56Sopenharmony_ci        self.assertEqual(f(""), "types.UnionType")  # last one wins
28107db96d56Sopenharmony_ci        self.assertEqual(f(b""), "typing.Union")
28117db96d56Sopenharmony_ci        self.assertEqual(f(1), "types.UnionType")
28127db96d56Sopenharmony_ci
28137db96d56Sopenharmony_ci    def test_union_None(self):
28147db96d56Sopenharmony_ci        @functools.singledispatch
28157db96d56Sopenharmony_ci        def typing_union(arg):
28167db96d56Sopenharmony_ci            return "default"
28177db96d56Sopenharmony_ci
28187db96d56Sopenharmony_ci        @typing_union.register
28197db96d56Sopenharmony_ci        def _(arg: typing.Union[str, None]):
28207db96d56Sopenharmony_ci            return "typing.Union"
28217db96d56Sopenharmony_ci
28227db96d56Sopenharmony_ci        self.assertEqual(typing_union(1), "default")
28237db96d56Sopenharmony_ci        self.assertEqual(typing_union(""), "typing.Union")
28247db96d56Sopenharmony_ci        self.assertEqual(typing_union(None), "typing.Union")
28257db96d56Sopenharmony_ci
28267db96d56Sopenharmony_ci        @functools.singledispatch
28277db96d56Sopenharmony_ci        def types_union(arg):
28287db96d56Sopenharmony_ci            return "default"
28297db96d56Sopenharmony_ci
28307db96d56Sopenharmony_ci        @types_union.register
28317db96d56Sopenharmony_ci        def _(arg: int | None):
28327db96d56Sopenharmony_ci            return "types.UnionType"
28337db96d56Sopenharmony_ci
28347db96d56Sopenharmony_ci        self.assertEqual(types_union(""), "default")
28357db96d56Sopenharmony_ci        self.assertEqual(types_union(1), "types.UnionType")
28367db96d56Sopenharmony_ci        self.assertEqual(types_union(None), "types.UnionType")
28377db96d56Sopenharmony_ci
28387db96d56Sopenharmony_ci    def test_register_genericalias(self):
28397db96d56Sopenharmony_ci        @functools.singledispatch
28407db96d56Sopenharmony_ci        def f(arg):
28417db96d56Sopenharmony_ci            return "default"
28427db96d56Sopenharmony_ci
28437db96d56Sopenharmony_ci        with self.assertRaisesRegex(TypeError, "Invalid first argument to "):
28447db96d56Sopenharmony_ci            f.register(list[int], lambda arg: "types.GenericAlias")
28457db96d56Sopenharmony_ci        with self.assertRaisesRegex(TypeError, "Invalid first argument to "):
28467db96d56Sopenharmony_ci            f.register(typing.List[int], lambda arg: "typing.GenericAlias")
28477db96d56Sopenharmony_ci        with self.assertRaisesRegex(TypeError, "Invalid first argument to "):
28487db96d56Sopenharmony_ci            f.register(list[int] | str, lambda arg: "types.UnionTypes(types.GenericAlias)")
28497db96d56Sopenharmony_ci        with self.assertRaisesRegex(TypeError, "Invalid first argument to "):
28507db96d56Sopenharmony_ci            f.register(typing.List[float] | bytes, lambda arg: "typing.Union[typing.GenericAlias]")
28517db96d56Sopenharmony_ci
28527db96d56Sopenharmony_ci        self.assertEqual(f([1]), "default")
28537db96d56Sopenharmony_ci        self.assertEqual(f([1.0]), "default")
28547db96d56Sopenharmony_ci        self.assertEqual(f(""), "default")
28557db96d56Sopenharmony_ci        self.assertEqual(f(b""), "default")
28567db96d56Sopenharmony_ci
28577db96d56Sopenharmony_ci    def test_register_genericalias_decorator(self):
28587db96d56Sopenharmony_ci        @functools.singledispatch
28597db96d56Sopenharmony_ci        def f(arg):
28607db96d56Sopenharmony_ci            return "default"
28617db96d56Sopenharmony_ci
28627db96d56Sopenharmony_ci        with self.assertRaisesRegex(TypeError, "Invalid first argument to "):
28637db96d56Sopenharmony_ci            f.register(list[int])
28647db96d56Sopenharmony_ci        with self.assertRaisesRegex(TypeError, "Invalid first argument to "):
28657db96d56Sopenharmony_ci            f.register(typing.List[int])
28667db96d56Sopenharmony_ci        with self.assertRaisesRegex(TypeError, "Invalid first argument to "):
28677db96d56Sopenharmony_ci            f.register(list[int] | str)
28687db96d56Sopenharmony_ci        with self.assertRaisesRegex(TypeError, "Invalid first argument to "):
28697db96d56Sopenharmony_ci            f.register(typing.List[int] | str)
28707db96d56Sopenharmony_ci
28717db96d56Sopenharmony_ci    def test_register_genericalias_annotation(self):
28727db96d56Sopenharmony_ci        @functools.singledispatch
28737db96d56Sopenharmony_ci        def f(arg):
28747db96d56Sopenharmony_ci            return "default"
28757db96d56Sopenharmony_ci
28767db96d56Sopenharmony_ci        with self.assertRaisesRegex(TypeError, "Invalid annotation for 'arg'"):
28777db96d56Sopenharmony_ci            @f.register
28787db96d56Sopenharmony_ci            def _(arg: list[int]):
28797db96d56Sopenharmony_ci                return "types.GenericAlias"
28807db96d56Sopenharmony_ci        with self.assertRaisesRegex(TypeError, "Invalid annotation for 'arg'"):
28817db96d56Sopenharmony_ci            @f.register
28827db96d56Sopenharmony_ci            def _(arg: typing.List[float]):
28837db96d56Sopenharmony_ci                return "typing.GenericAlias"
28847db96d56Sopenharmony_ci        with self.assertRaisesRegex(TypeError, "Invalid annotation for 'arg'"):
28857db96d56Sopenharmony_ci            @f.register
28867db96d56Sopenharmony_ci            def _(arg: list[int] | str):
28877db96d56Sopenharmony_ci                return "types.UnionType(types.GenericAlias)"
28887db96d56Sopenharmony_ci        with self.assertRaisesRegex(TypeError, "Invalid annotation for 'arg'"):
28897db96d56Sopenharmony_ci            @f.register
28907db96d56Sopenharmony_ci            def _(arg: typing.List[float] | bytes):
28917db96d56Sopenharmony_ci                return "typing.Union[typing.GenericAlias]"
28927db96d56Sopenharmony_ci
28937db96d56Sopenharmony_ci        self.assertEqual(f([1]), "default")
28947db96d56Sopenharmony_ci        self.assertEqual(f([1.0]), "default")
28957db96d56Sopenharmony_ci        self.assertEqual(f(""), "default")
28967db96d56Sopenharmony_ci        self.assertEqual(f(b""), "default")
28977db96d56Sopenharmony_ci
28987db96d56Sopenharmony_ci
28997db96d56Sopenharmony_ciclass CachedCostItem:
29007db96d56Sopenharmony_ci    _cost = 1
29017db96d56Sopenharmony_ci
29027db96d56Sopenharmony_ci    def __init__(self):
29037db96d56Sopenharmony_ci        self.lock = py_functools.RLock()
29047db96d56Sopenharmony_ci
29057db96d56Sopenharmony_ci    @py_functools.cached_property
29067db96d56Sopenharmony_ci    def cost(self):
29077db96d56Sopenharmony_ci        """The cost of the item."""
29087db96d56Sopenharmony_ci        with self.lock:
29097db96d56Sopenharmony_ci            self._cost += 1
29107db96d56Sopenharmony_ci        return self._cost
29117db96d56Sopenharmony_ci
29127db96d56Sopenharmony_ci
29137db96d56Sopenharmony_ciclass OptionallyCachedCostItem:
29147db96d56Sopenharmony_ci    _cost = 1
29157db96d56Sopenharmony_ci
29167db96d56Sopenharmony_ci    def get_cost(self):
29177db96d56Sopenharmony_ci        """The cost of the item."""
29187db96d56Sopenharmony_ci        self._cost += 1
29197db96d56Sopenharmony_ci        return self._cost
29207db96d56Sopenharmony_ci
29217db96d56Sopenharmony_ci    cached_cost = py_functools.cached_property(get_cost)
29227db96d56Sopenharmony_ci
29237db96d56Sopenharmony_ci
29247db96d56Sopenharmony_ciclass CachedCostItemWait:
29257db96d56Sopenharmony_ci
29267db96d56Sopenharmony_ci    def __init__(self, event):
29277db96d56Sopenharmony_ci        self._cost = 1
29287db96d56Sopenharmony_ci        self.lock = py_functools.RLock()
29297db96d56Sopenharmony_ci        self.event = event
29307db96d56Sopenharmony_ci
29317db96d56Sopenharmony_ci    @py_functools.cached_property
29327db96d56Sopenharmony_ci    def cost(self):
29337db96d56Sopenharmony_ci        self.event.wait(1)
29347db96d56Sopenharmony_ci        with self.lock:
29357db96d56Sopenharmony_ci            self._cost += 1
29367db96d56Sopenharmony_ci        return self._cost
29377db96d56Sopenharmony_ci
29387db96d56Sopenharmony_ci
29397db96d56Sopenharmony_ciclass CachedCostItemWithSlots:
29407db96d56Sopenharmony_ci    __slots__ = ('_cost')
29417db96d56Sopenharmony_ci
29427db96d56Sopenharmony_ci    def __init__(self):
29437db96d56Sopenharmony_ci        self._cost = 1
29447db96d56Sopenharmony_ci
29457db96d56Sopenharmony_ci    @py_functools.cached_property
29467db96d56Sopenharmony_ci    def cost(self):
29477db96d56Sopenharmony_ci        raise RuntimeError('never called, slots not supported')
29487db96d56Sopenharmony_ci
29497db96d56Sopenharmony_ci
29507db96d56Sopenharmony_ciclass TestCachedProperty(unittest.TestCase):
29517db96d56Sopenharmony_ci    def test_cached(self):
29527db96d56Sopenharmony_ci        item = CachedCostItem()
29537db96d56Sopenharmony_ci        self.assertEqual(item.cost, 2)
29547db96d56Sopenharmony_ci        self.assertEqual(item.cost, 2) # not 3
29557db96d56Sopenharmony_ci
29567db96d56Sopenharmony_ci    def test_cached_attribute_name_differs_from_func_name(self):
29577db96d56Sopenharmony_ci        item = OptionallyCachedCostItem()
29587db96d56Sopenharmony_ci        self.assertEqual(item.get_cost(), 2)
29597db96d56Sopenharmony_ci        self.assertEqual(item.cached_cost, 3)
29607db96d56Sopenharmony_ci        self.assertEqual(item.get_cost(), 4)
29617db96d56Sopenharmony_ci        self.assertEqual(item.cached_cost, 3)
29627db96d56Sopenharmony_ci
29637db96d56Sopenharmony_ci    @threading_helper.requires_working_threading()
29647db96d56Sopenharmony_ci    def test_threaded(self):
29657db96d56Sopenharmony_ci        go = threading.Event()
29667db96d56Sopenharmony_ci        item = CachedCostItemWait(go)
29677db96d56Sopenharmony_ci
29687db96d56Sopenharmony_ci        num_threads = 3
29697db96d56Sopenharmony_ci
29707db96d56Sopenharmony_ci        orig_si = sys.getswitchinterval()
29717db96d56Sopenharmony_ci        sys.setswitchinterval(1e-6)
29727db96d56Sopenharmony_ci        try:
29737db96d56Sopenharmony_ci            threads = [
29747db96d56Sopenharmony_ci                threading.Thread(target=lambda: item.cost)
29757db96d56Sopenharmony_ci                for k in range(num_threads)
29767db96d56Sopenharmony_ci            ]
29777db96d56Sopenharmony_ci            with threading_helper.start_threads(threads):
29787db96d56Sopenharmony_ci                go.set()
29797db96d56Sopenharmony_ci        finally:
29807db96d56Sopenharmony_ci            sys.setswitchinterval(orig_si)
29817db96d56Sopenharmony_ci
29827db96d56Sopenharmony_ci        self.assertEqual(item.cost, 2)
29837db96d56Sopenharmony_ci
29847db96d56Sopenharmony_ci    def test_object_with_slots(self):
29857db96d56Sopenharmony_ci        item = CachedCostItemWithSlots()
29867db96d56Sopenharmony_ci        with self.assertRaisesRegex(
29877db96d56Sopenharmony_ci                TypeError,
29887db96d56Sopenharmony_ci                "No '__dict__' attribute on 'CachedCostItemWithSlots' instance to cache 'cost' property.",
29897db96d56Sopenharmony_ci        ):
29907db96d56Sopenharmony_ci            item.cost
29917db96d56Sopenharmony_ci
29927db96d56Sopenharmony_ci    def test_immutable_dict(self):
29937db96d56Sopenharmony_ci        class MyMeta(type):
29947db96d56Sopenharmony_ci            @py_functools.cached_property
29957db96d56Sopenharmony_ci            def prop(self):
29967db96d56Sopenharmony_ci                return True
29977db96d56Sopenharmony_ci
29987db96d56Sopenharmony_ci        class MyClass(metaclass=MyMeta):
29997db96d56Sopenharmony_ci            pass
30007db96d56Sopenharmony_ci
30017db96d56Sopenharmony_ci        with self.assertRaisesRegex(
30027db96d56Sopenharmony_ci            TypeError,
30037db96d56Sopenharmony_ci            "The '__dict__' attribute on 'MyMeta' instance does not support item assignment for caching 'prop' property.",
30047db96d56Sopenharmony_ci        ):
30057db96d56Sopenharmony_ci            MyClass.prop
30067db96d56Sopenharmony_ci
30077db96d56Sopenharmony_ci    def test_reuse_different_names(self):
30087db96d56Sopenharmony_ci        """Disallow this case because decorated function a would not be cached."""
30097db96d56Sopenharmony_ci        with self.assertRaises(RuntimeError) as ctx:
30107db96d56Sopenharmony_ci            class ReusedCachedProperty:
30117db96d56Sopenharmony_ci                @py_functools.cached_property
30127db96d56Sopenharmony_ci                def a(self):
30137db96d56Sopenharmony_ci                    pass
30147db96d56Sopenharmony_ci
30157db96d56Sopenharmony_ci                b = a
30167db96d56Sopenharmony_ci
30177db96d56Sopenharmony_ci        self.assertEqual(
30187db96d56Sopenharmony_ci            str(ctx.exception.__context__),
30197db96d56Sopenharmony_ci            str(TypeError("Cannot assign the same cached_property to two different names ('a' and 'b')."))
30207db96d56Sopenharmony_ci        )
30217db96d56Sopenharmony_ci
30227db96d56Sopenharmony_ci    def test_reuse_same_name(self):
30237db96d56Sopenharmony_ci        """Reusing a cached_property on different classes under the same name is OK."""
30247db96d56Sopenharmony_ci        counter = 0
30257db96d56Sopenharmony_ci
30267db96d56Sopenharmony_ci        @py_functools.cached_property
30277db96d56Sopenharmony_ci        def _cp(_self):
30287db96d56Sopenharmony_ci            nonlocal counter
30297db96d56Sopenharmony_ci            counter += 1
30307db96d56Sopenharmony_ci            return counter
30317db96d56Sopenharmony_ci
30327db96d56Sopenharmony_ci        class A:
30337db96d56Sopenharmony_ci            cp = _cp
30347db96d56Sopenharmony_ci
30357db96d56Sopenharmony_ci        class B:
30367db96d56Sopenharmony_ci            cp = _cp
30377db96d56Sopenharmony_ci
30387db96d56Sopenharmony_ci        a = A()
30397db96d56Sopenharmony_ci        b = B()
30407db96d56Sopenharmony_ci
30417db96d56Sopenharmony_ci        self.assertEqual(a.cp, 1)
30427db96d56Sopenharmony_ci        self.assertEqual(b.cp, 2)
30437db96d56Sopenharmony_ci        self.assertEqual(a.cp, 1)
30447db96d56Sopenharmony_ci
30457db96d56Sopenharmony_ci    def test_set_name_not_called(self):
30467db96d56Sopenharmony_ci        cp = py_functools.cached_property(lambda s: None)
30477db96d56Sopenharmony_ci        class Foo:
30487db96d56Sopenharmony_ci            pass
30497db96d56Sopenharmony_ci
30507db96d56Sopenharmony_ci        Foo.cp = cp
30517db96d56Sopenharmony_ci
30527db96d56Sopenharmony_ci        with self.assertRaisesRegex(
30537db96d56Sopenharmony_ci                TypeError,
30547db96d56Sopenharmony_ci                "Cannot use cached_property instance without calling __set_name__ on it.",
30557db96d56Sopenharmony_ci        ):
30567db96d56Sopenharmony_ci            Foo().cp
30577db96d56Sopenharmony_ci
30587db96d56Sopenharmony_ci    def test_access_from_class(self):
30597db96d56Sopenharmony_ci        self.assertIsInstance(CachedCostItem.cost, py_functools.cached_property)
30607db96d56Sopenharmony_ci
30617db96d56Sopenharmony_ci    def test_doc(self):
30627db96d56Sopenharmony_ci        self.assertEqual(CachedCostItem.cost.__doc__, "The cost of the item.")
30637db96d56Sopenharmony_ci
30647db96d56Sopenharmony_ci
30657db96d56Sopenharmony_ciif __name__ == '__main__':
30667db96d56Sopenharmony_ci    unittest.main()
3067