]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-144782: Make sure that ArgumentParser instances are pickleable (#144783)
authorMauricio Villegas <5780272+mauvilsa@users.noreply.github.com>
Tue, 17 Feb 2026 02:28:21 +0000 (03:28 +0100)
committerGitHub <noreply@github.com>
Tue, 17 Feb 2026 02:28:21 +0000 (18:28 -0800)
Co-authored-by: Bartosz Sławecki <bartosz@ilikepython.com>
Co-authored-by: AN Long <aisk@users.noreply.github.com>
Co-authored-by: Savannah Ostrowski <savannah@python.org>
Lib/argparse.py
Lib/test/test_argparse.py
Misc/NEWS.d/next/Library/2026-02-13-14-20-10.gh-issue-144782.0Y8TKj.rst [new file with mode: 0644]

index 0494b545f2f1d3d885129d7832057811cf96957d..296a210ad832da124c6f2ad44d403fdf56640132 100644 (file)
@@ -148,6 +148,10 @@ def _copy_items(items):
     return copy.copy(items)
 
 
+def _identity(value):
+    return value
+
+
 # ===============
 # Formatting Help
 # ===============
@@ -199,7 +203,7 @@ class HelpFormatter(object):
             self._decolor = decolor
         else:
             self._theme = get_theme(force_no_color=True).argparse
-            self._decolor = lambda text: text
+            self._decolor = _identity
 
     # ===============================
     # Section and indentation methods
@@ -1981,9 +1985,7 @@ class ArgumentParser(_AttributeHolder, _ActionsContainer):
         self._subparsers = None
 
         # register types
-        def identity(string):
-            return string
-        self.register('type', None, identity)
+        self.register('type', None, _identity)
 
         # add help argument if necessary
         # (using explicit default to override global argument_default)
index 78f02f70b9f0fc86ad4191e2ee775c2e217503f8..4526efe4b80ef4ab42b4b0b2367d789452056a99 100644 (file)
@@ -80,6 +80,27 @@ class StdStreamTest(unittest.TestCase):
                 self.assertRegex(mocked_stderr.getvalue(), r'usage:')
 
 
+class TestArgumentParserPickleable(unittest.TestCase):
+
+    @force_not_colorized
+    def test_pickle_roundtrip(self):
+        import pickle
+        parser = argparse.ArgumentParser(exit_on_error=False)
+        parser.add_argument('--foo', type=int, default=42)
+        parser.add_argument('bar', nargs='?', default='baz')
+        for proto in range(pickle.HIGHEST_PROTOCOL + 1):
+            with self.subTest(protocol=proto):
+                # Try to pickle and unpickle the parser
+                parser2 = pickle.loads(pickle.dumps(parser, protocol=proto))
+                # Check that the round-tripped parser still works
+                ns = parser2.parse_args(['--foo', '123', 'quux'])
+                self.assertEqual(ns.foo, 123)
+                self.assertEqual(ns.bar, 'quux')
+                ns2 = parser2.parse_args([])
+                self.assertEqual(ns2.foo, 42)
+                self.assertEqual(ns2.bar, 'baz')
+
+
 class TestCase(unittest.TestCase):
 
     def setUp(self):
diff --git a/Misc/NEWS.d/next/Library/2026-02-13-14-20-10.gh-issue-144782.0Y8TKj.rst b/Misc/NEWS.d/next/Library/2026-02-13-14-20-10.gh-issue-144782.0Y8TKj.rst
new file mode 100644 (file)
index 0000000..871005f
--- /dev/null
@@ -0,0 +1 @@
+Fix :class:`argparse.ArgumentParser` to be :mod:`pickleable <pickle>`.