Skip to content

Commit 2f7634c

Browse files
mauvilsajohnslavikaisksavannahostrowski
authored
gh-144782: Make sure that ArgumentParser instances are pickleable (#144783)
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>
1 parent 18c04f2 commit 2f7634c

File tree

3 files changed

+28
-4
lines changed

3 files changed

+28
-4
lines changed

Lib/argparse.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,10 @@ def _copy_items(items):
148148
return copy.copy(items)
149149

150150

151+
def _identity(value):
152+
return value
153+
154+
151155
# ===============
152156
# Formatting Help
153157
# ===============
@@ -199,7 +203,7 @@ def _set_color(self, color, *, file=None):
199203
self._decolor = decolor
200204
else:
201205
self._theme = get_theme(force_no_color=True).argparse
202-
self._decolor = lambda text: text
206+
self._decolor = _identity
203207

204208
# ===============================
205209
# Section and indentation methods
@@ -1981,9 +1985,7 @@ def __init__(self,
19811985
self._subparsers = None
19821986

19831987
# register types
1984-
def identity(string):
1985-
return string
1986-
self.register('type', None, identity)
1988+
self.register('type', None, _identity)
19871989

19881990
# add help argument if necessary
19891991
# (using explicit default to override global argument_default)

Lib/test/test_argparse.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,27 @@ def test_skip_invalid_stdout(self):
8080
self.assertRegex(mocked_stderr.getvalue(), r'usage:')
8181

8282

83+
class TestArgumentParserPickleable(unittest.TestCase):
84+
85+
@force_not_colorized
86+
def test_pickle_roundtrip(self):
87+
import pickle
88+
parser = argparse.ArgumentParser(exit_on_error=False)
89+
parser.add_argument('--foo', type=int, default=42)
90+
parser.add_argument('bar', nargs='?', default='baz')
91+
for proto in range(pickle.HIGHEST_PROTOCOL + 1):
92+
with self.subTest(protocol=proto):
93+
# Try to pickle and unpickle the parser
94+
parser2 = pickle.loads(pickle.dumps(parser, protocol=proto))
95+
# Check that the round-tripped parser still works
96+
ns = parser2.parse_args(['--foo', '123', 'quux'])
97+
self.assertEqual(ns.foo, 123)
98+
self.assertEqual(ns.bar, 'quux')
99+
ns2 = parser2.parse_args([])
100+
self.assertEqual(ns2.foo, 42)
101+
self.assertEqual(ns2.bar, 'baz')
102+
103+
83104
class TestCase(unittest.TestCase):
84105

85106
def setUp(self):
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix :class:`argparse.ArgumentParser` to be :mod:`pickleable <pickle>`.

0 commit comments

Comments
 (0)