|
4 | 4 | import copyreg |
5 | 5 | import weakref |
6 | 6 | import abc |
7 | | -from operator import le, lt, ge, gt, eq, ne |
| 7 | +from operator import le, lt, ge, gt, eq, ne, attrgetter |
8 | 8 |
|
9 | 9 | import unittest |
10 | 10 | from test import support |
@@ -903,7 +903,89 @@ def m(self): |
903 | 903 | g.b() |
904 | 904 |
|
905 | 905 |
|
| 906 | +class TestReplace(unittest.TestCase): |
| 907 | + |
| 908 | + def test_unsupported(self): |
| 909 | + self.assertRaises(TypeError, copy.replace, 1) |
| 910 | + self.assertRaises(TypeError, copy.replace, []) |
| 911 | + self.assertRaises(TypeError, copy.replace, {}) |
| 912 | + def f(): pass |
| 913 | + self.assertRaises(TypeError, copy.replace, f) |
| 914 | + class A: pass |
| 915 | + self.assertRaises(TypeError, copy.replace, A) |
| 916 | + self.assertRaises(TypeError, copy.replace, A()) |
| 917 | + |
| 918 | + def test_replace_method(self): |
| 919 | + class A: |
| 920 | + def __new__(cls, x, y=0): |
| 921 | + self = object.__new__(cls) |
| 922 | + self.x = x |
| 923 | + self.y = y |
| 924 | + return self |
| 925 | + |
| 926 | + def __init__(self, *args, **kwargs): |
| 927 | + self.z = self.x + self.y |
| 928 | + |
| 929 | + def __replace__(self, **changes): |
| 930 | + x = changes.get('x', self.x) |
| 931 | + y = changes.get('y', self.y) |
| 932 | + return type(self)(x, y) |
| 933 | + |
| 934 | + attrs = attrgetter('x', 'y', 'z') |
| 935 | + a = A(11, 22) |
| 936 | + self.assertEqual(attrs(copy.replace(a)), (11, 22, 33)) |
| 937 | + self.assertEqual(attrs(copy.replace(a, x=1)), (1, 22, 23)) |
| 938 | + self.assertEqual(attrs(copy.replace(a, y=2)), (11, 2, 13)) |
| 939 | + self.assertEqual(attrs(copy.replace(a, x=1, y=2)), (1, 2, 3)) |
| 940 | + |
| 941 | + # TODO: RUSTPYTHON |
| 942 | + @unittest.expectedFailure |
| 943 | + def test_namedtuple(self): |
| 944 | + from collections import namedtuple |
| 945 | + from typing import NamedTuple |
| 946 | + PointFromCall = namedtuple('Point', 'x y', defaults=(0,)) |
| 947 | + class PointFromInheritance(PointFromCall): |
| 948 | + pass |
| 949 | + class PointFromClass(NamedTuple): |
| 950 | + x: int |
| 951 | + y: int = 0 |
| 952 | + for Point in (PointFromCall, PointFromInheritance, PointFromClass): |
| 953 | + with self.subTest(Point=Point): |
| 954 | + p = Point(11, 22) |
| 955 | + self.assertIsInstance(p, Point) |
| 956 | + self.assertEqual(copy.replace(p), (11, 22)) |
| 957 | + self.assertIsInstance(copy.replace(p), Point) |
| 958 | + self.assertEqual(copy.replace(p, x=1), (1, 22)) |
| 959 | + self.assertEqual(copy.replace(p, y=2), (11, 2)) |
| 960 | + self.assertEqual(copy.replace(p, x=1, y=2), (1, 2)) |
| 961 | + with self.assertRaisesRegex(TypeError, 'unexpected field name'): |
| 962 | + copy.replace(p, x=1, error=2) |
| 963 | + |
| 964 | + # TODO: RUSTPYTHON |
| 965 | + @unittest.expectedFailure |
| 966 | + def test_dataclass(self): |
| 967 | + from dataclasses import dataclass |
| 968 | + @dataclass |
| 969 | + class C: |
| 970 | + x: int |
| 971 | + y: int = 0 |
| 972 | + |
| 973 | + attrs = attrgetter('x', 'y') |
| 974 | + c = C(11, 22) |
| 975 | + self.assertEqual(attrs(copy.replace(c)), (11, 22)) |
| 976 | + self.assertEqual(attrs(copy.replace(c, x=1)), (1, 22)) |
| 977 | + self.assertEqual(attrs(copy.replace(c, y=2)), (11, 2)) |
| 978 | + self.assertEqual(attrs(copy.replace(c, x=1, y=2)), (1, 2)) |
| 979 | + with self.assertRaisesRegex(TypeError, 'unexpected keyword argument'): |
| 980 | + copy.replace(c, x=1, error=2) |
| 981 | + |
| 982 | + |
| 983 | +class MiscTestCase(unittest.TestCase): |
| 984 | + def test__all__(self): |
| 985 | + support.check__all__(self, copy, not_exported={"dispatch_table", "error"}) |
| 986 | + |
906 | 987 | def global_foo(x, y): return x+y |
907 | 988 |
|
| 989 | + |
908 | 990 | if __name__ == "__main__": |
909 | 991 | unittest.main() |
0 commit comments