diff options
author | Serhiy Storchaka <storchaka@gmail.com> | 2023-09-06 20:55:42 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-09-06 20:55:42 (GMT) |
commit | 6f3c138dfa868b32d3288898923bbfa388f2fa5d (patch) | |
tree | 98098db4d0d2f256f2a17d515c1750a28424166c /Lib/test/test_inspect.py | |
parent | 9f0c0a46f00d687e921990ee83894b2f4ce8a6e7 (diff) | |
download | cpython-6f3c138dfa868b32d3288898923bbfa388f2fa5d.zip cpython-6f3c138dfa868b32d3288898923bbfa388f2fa5d.tar.gz cpython-6f3c138dfa868b32d3288898923bbfa388f2fa5d.tar.bz2 |
gh-108751: Add copy.replace() function (GH-108752)
It creates a modified copy of an object by calling the object's
__replace__() method.
It is a generalization of dataclasses.replace(), named tuple's _replace()
method and replace() methods in various classes, and supports all these
stdlib classes.
Diffstat (limited to 'Lib/test/test_inspect.py')
-rw-r--r-- | Lib/test/test_inspect.py | 65 |
1 files changed, 61 insertions, 4 deletions
diff --git a/Lib/test/test_inspect.py b/Lib/test/test_inspect.py index 78ef817..2fb356a 100644 --- a/Lib/test/test_inspect.py +++ b/Lib/test/test_inspect.py @@ -1,6 +1,7 @@ import asyncio import builtins import collections +import copy import datetime import functools import importlib @@ -3830,6 +3831,28 @@ class TestSignatureObject(unittest.TestCase): P('bar', P.VAR_POSITIONAL)])), '(foo, /, *bar)') + def test_signature_replace_parameters(self): + def test(a, b) -> 42: + pass + + sig = inspect.signature(test) + parameters = sig.parameters + sig = sig.replace(parameters=list(parameters.values())[1:]) + self.assertEqual(list(sig.parameters), ['b']) + self.assertEqual(sig.parameters['b'], parameters['b']) + self.assertEqual(sig.return_annotation, 42) + sig = sig.replace(parameters=()) + self.assertEqual(dict(sig.parameters), {}) + + sig = inspect.signature(test) + parameters = sig.parameters + sig = copy.replace(sig, parameters=list(parameters.values())[1:]) + self.assertEqual(list(sig.parameters), ['b']) + self.assertEqual(sig.parameters['b'], parameters['b']) + self.assertEqual(sig.return_annotation, 42) + sig = copy.replace(sig, parameters=()) + self.assertEqual(dict(sig.parameters), {}) + def test_signature_replace_anno(self): def test() -> 42: pass @@ -3843,6 +3866,15 @@ class TestSignatureObject(unittest.TestCase): self.assertEqual(sig.return_annotation, 42) self.assertEqual(sig, inspect.signature(test)) + sig = inspect.signature(test) + sig = copy.replace(sig, return_annotation=None) + self.assertIs(sig.return_annotation, None) + sig = copy.replace(sig, return_annotation=sig.empty) + self.assertIs(sig.return_annotation, sig.empty) + sig = copy.replace(sig, return_annotation=42) + self.assertEqual(sig.return_annotation, 42) + self.assertEqual(sig, inspect.signature(test)) + def test_signature_replaced(self): def test(): pass @@ -4187,41 +4219,66 @@ class TestParameterObject(unittest.TestCase): p = inspect.Parameter('foo', default=42, kind=inspect.Parameter.KEYWORD_ONLY) - self.assertIsNot(p, p.replace()) - self.assertEqual(p, p.replace()) + self.assertIsNot(p.replace(), p) + self.assertEqual(p.replace(), p) + self.assertIsNot(copy.replace(p), p) + self.assertEqual(copy.replace(p), p) p2 = p.replace(annotation=1) self.assertEqual(p2.annotation, 1) p2 = p2.replace(annotation=p2.empty) - self.assertEqual(p, p2) + self.assertEqual(p2, p) + p3 = copy.replace(p, annotation=1) + self.assertEqual(p3.annotation, 1) + p3 = copy.replace(p3, annotation=p3.empty) + self.assertEqual(p3, p) p2 = p2.replace(name='bar') self.assertEqual(p2.name, 'bar') self.assertNotEqual(p2, p) + p3 = copy.replace(p3, name='bar') + self.assertEqual(p3.name, 'bar') + self.assertNotEqual(p3, p) with self.assertRaisesRegex(ValueError, 'name is a required attribute'): p2 = p2.replace(name=p2.empty) + with self.assertRaisesRegex(ValueError, + 'name is a required attribute'): + p3 = copy.replace(p3, name=p3.empty) p2 = p2.replace(name='foo', default=None) self.assertIs(p2.default, None) self.assertNotEqual(p2, p) + p3 = copy.replace(p3, name='foo', default=None) + self.assertIs(p3.default, None) + self.assertNotEqual(p3, p) p2 = p2.replace(name='foo', default=p2.empty) self.assertIs(p2.default, p2.empty) - + p3 = copy.replace(p3, name='foo', default=p3.empty) + self.assertIs(p3.default, p3.empty) p2 = p2.replace(default=42, kind=p2.POSITIONAL_OR_KEYWORD) self.assertEqual(p2.kind, p2.POSITIONAL_OR_KEYWORD) self.assertNotEqual(p2, p) + p3 = copy.replace(p3, default=42, kind=p3.POSITIONAL_OR_KEYWORD) + self.assertEqual(p3.kind, p3.POSITIONAL_OR_KEYWORD) + self.assertNotEqual(p3, p) with self.assertRaisesRegex(ValueError, "value <class 'inspect._empty'> " "is not a valid Parameter.kind"): p2 = p2.replace(kind=p2.empty) + with self.assertRaisesRegex(ValueError, + "value <class 'inspect._empty'> " + "is not a valid Parameter.kind"): + p3 = copy.replace(p3, kind=p3.empty) p2 = p2.replace(kind=p2.KEYWORD_ONLY) self.assertEqual(p2, p) + p3 = copy.replace(p3, kind=p3.KEYWORD_ONLY) + self.assertEqual(p3, p) def test_signature_parameter_positional_only(self): with self.assertRaisesRegex(TypeError, 'name must be a str'): |