Skip to content

Commit

Permalink
pythongh-116850: Fix argparse for namespaces with not directly writab…
Browse files Browse the repository at this point in the history
…le dict

It now always uses setattr() instead of setting the dict item to modify
the namespace. This allows to use a class as a namespace.
  • Loading branch information
serhiy-storchaka committed Sep 27, 2024
1 parent 3a0e7f5 commit 3c1a58f
Show file tree
Hide file tree
Showing 3 changed files with 16 additions and 1 deletion.
3 changes: 2 additions & 1 deletion Lib/argparse.py
Original file line number Diff line number Diff line change
Expand Up @@ -1224,7 +1224,8 @@ def __call__(self, parser, namespace, values, option_string=None):
setattr(namespace, key, value)

if arg_strings:
vars(namespace).setdefault(_UNRECOGNIZED_ARGS_ATTR, [])
if not hasattr(namespace, _UNRECOGNIZED_ARGS_ATTR):
setattr(namespace, _UNRECOGNIZED_ARGS_ATTR, [])
getattr(namespace, _UNRECOGNIZED_ARGS_ATTR).extend(arg_strings)

class _ExtendAction(_AppendAction):
Expand Down
12 changes: 12 additions & 0 deletions Lib/test/test_argparse.py
Original file line number Diff line number Diff line change
Expand Up @@ -2312,6 +2312,18 @@ def test_parse_known_args(self):
(NS(foo=False, bar=0.5, w=7, x='b'), ['-W', '-X', 'Y', 'Z']),
)

def test_parse_known_args_to_class_namespace(self):
class C:
pass
self.assertEqual(
self.parser.parse_known_args('0.5 1 b -w 7 -p'.split(), namespace=C),
(C, ['-p']),
)
self.assertIs(C.foo, False)
self.assertEqual(C.bar, 0.5)
self.assertEqual(C.w, 7)
self.assertEqual(C.x, 'b')

def test_parse_known_args_with_single_dash_option(self):
parser = ErrorRaisingArgumentParser()
parser.add_argument('-k', '--known', action='count', default=0)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Fix :mod:`argparse` for namespaces with not directly writable dict (e.g.
classes).

0 comments on commit 3c1a58f

Please sign in to comment.