]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-155043: Support copy.replace() for argparse.Namespace (#155049)
authorSerhiy Storchaka <storchaka@gmail.com>
Wed, 5 Aug 2026 16:14:01 +0000 (19:14 +0300)
committerGitHub <noreply@github.com>
Wed, 5 Aug 2026 16:14:01 +0000 (09:14 -0700)
Doc/library/argparse.rst
Lib/argparse.py
Lib/test/test_argparse.py
Misc/NEWS.d/next/Library/2026-08-01-19-04-00.gh-issue-155043.Ar1Nsp.rst [new file with mode: 0644]

index e4a5f4d109b4992c62fccb897ab272781dd34f8c..8ae96311026f33fa06f550024fca582095d471ab 100644 (file)
@@ -1679,6 +1679,12 @@ The Namespace object
    Simple class used by default by :meth:`~ArgumentParser.parse_args` to create
    an object holding attributes and return it.
 
+   :class:`!Namespace` objects support :func:`copy.replace`,
+   which returns a copy of the object with the specified attributes replaced.
+
+   .. versionchanged:: next
+      Added support for :func:`copy.replace`.
+
    This class is deliberately simple, just an :class:`object` subclass with a
    readable string representation. If you prefer to have dict-like view of the
    attributes, you can use the standard Python idiom, :func:`vars`::
index 25994d7a389efac683a56766c81568a60f194aec..fe9fde7f65830fb6c46fadeaea7a951af2de8598 100644 (file)
@@ -1545,6 +1545,12 @@ class Namespace(_AttributeHolder):
     def __contains__(self, key):
         return key in self.__dict__
 
+    def __replace__(self, /, **changes):
+        new = self.__class__()
+        new.__dict__.update(self.__dict__)
+        new.__dict__.update(changes)
+        return new
+
 
 class _ActionsContainer(object):
 
index ae02cd11804e50756f47b950412a081adeef2826..950671e4395cd4da59023b83e50eb707ba324dbe 100644 (file)
@@ -2,6 +2,7 @@
 
 import _colorize
 import contextlib
+import copy
 import functools
 import io
 import operator
@@ -6267,6 +6268,19 @@ class TestNamespace(TestCase):
         self.assertIs(ns.__eq__(None), NotImplemented)
         self.assertIs(ns.__ne__(None), NotImplemented)
 
+    def test_replace(self):
+        ns = argparse.Namespace(a=1, b=2)
+        new = copy.replace(ns, b=3, c=4)
+        self.assertIsInstance(new, argparse.Namespace)
+        self.assertEqual(new, argparse.Namespace(a=1, b=3, c=4))
+        self.assertEqual(ns, argparse.Namespace(a=1, b=2))
+
+        class MyNamespace(argparse.Namespace):
+            pass
+        new = copy.replace(MyNamespace(a=1), a=2)
+        self.assertIsInstance(new, MyNamespace)
+        self.assertEqual(new.a, 2)
+
 
 # ===================
 # File encoding tests
diff --git a/Misc/NEWS.d/next/Library/2026-08-01-19-04-00.gh-issue-155043.Ar1Nsp.rst b/Misc/NEWS.d/next/Library/2026-08-01-19-04-00.gh-issue-155043.Ar1Nsp.rst
new file mode 100644 (file)
index 0000000..715b0a1
--- /dev/null
@@ -0,0 +1 @@
+:class:`argparse.Namespace` objects now support :func:`copy.replace`.