Skip to content

Commit 8eb006e

Browse files
committed
Make sure that ArgumentParser instances are pickleable
1 parent 945bf8c commit 8eb006e

File tree

3 files changed

+36
-4
lines changed

3 files changed

+36
-4
lines changed

Lib/argparse.py

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

150150

151+
def _identity(value):
152+
# Defined at module scope so that ArgumentParser instances are pickleable.
153+
return value
154+
155+
151156
# ===============
152157
# Formatting Help
153158
# ===============
@@ -199,7 +204,7 @@ def _set_color(self, color, *, file=None):
199204
self._decolor = decolor
200205
else:
201206
self._theme = get_theme(force_no_color=True).argparse
202-
self._decolor = lambda text: text
207+
self._decolor = _identity
203208

204209
# ===============================
205210
# Section and indentation methods
@@ -1981,9 +1986,7 @@ def __init__(self,
19811986
self._subparsers = None
19821987

19831988
# register types
1984-
def identity(string):
1985-
return string
1986-
self.register('type', None, identity)
1989+
self.register('type', None, _identity)
19871990

19881991
# add help argument if necessary
19891992
# (using explicit default to override global argument_default)

Lib/test/test_argparse.py

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

8282

83+
class TestArgumentParserPickleable(unittest.TestCase):
84+
85+
@mock.patch.dict(os.environ, {'NO_COLOR': 'true'})
86+
def test_pickle_roundtrip(self):
87+
import pickle
88+
parser = argparse.ArgumentParser()
89+
parser.add_argument('--foo', type=int, default=42)
90+
parser.add_argument('bar', nargs='?', default='baz')
91+
# Try to pickle and unpickle the parser
92+
parser2 = pickle.loads(pickle.dumps(parser))
93+
# Check that the round-tripped parser still works
94+
ns = parser2.parse_args(['--foo', '123', 'quux'])
95+
self.assertEqual(ns.foo, 123)
96+
self.assertEqual(ns.bar, 'quux')
97+
ns2 = parser2.parse_args([])
98+
self.assertEqual(ns2.foo, 42)
99+
self.assertEqual(ns2.bar, 'baz')
100+
101+
83102
class TestCase(unittest.TestCase):
84103

85104
def setUp(self):
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
Make sure that ``argparse.ArgumentParser`` is pickleable.
2+
3+
#.. section: Documentation #.. section: Tests #.. section: Build #..
4+
section: Windows #.. section: macOS #.. section: IDLE #.. section:
5+
Tools/Demos #.. section: C API
6+
7+
# Write your Misc/NEWS.d entry below. It should be a simple ReST paragraph.
8+
# Don't start with "- Issue #<n>: " or "- gh-issue-<n>: " or that sort of
9+
stuff.
10+
###########################################################################

0 commit comments

Comments
 (0)