summaryrefslogtreecommitdiffstats
path: root/Lib/test/test_inspect.py
diff options
context:
space:
mode:
authorSerhiy Storchaka <storchaka@gmail.com>2023-09-06 20:55:42 (GMT)
committerGitHub <noreply@github.com>2023-09-06 20:55:42 (GMT)
commit6f3c138dfa868b32d3288898923bbfa388f2fa5d (patch)
tree98098db4d0d2f256f2a17d515c1750a28424166c /Lib/test/test_inspect.py
parent9f0c0a46f00d687e921990ee83894b2f4ce8a6e7 (diff)
downloadcpython-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.py65
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'):