https://github.com/python/cpython/commit/5464c8aa9856a65f576f536532ee56310397e109
commit: 5464c8aa9856a65f576f536532ee56310397e109
branch: 3.12
author: Miss Islington (bot) <[email protected]>
committer: serhiy-storchaka <[email protected]>
date: 2024-09-29T08:40:00Z
summary:

[3.12] gh-116850: Fix argparse for namespaces with not directly writable dict 
(GH-124667) (GH-124758)

It now always uses setattr() instead of setting the dict item to modify
the namespace. This allows to use a class as a namespace.
(cherry picked from commit 95e92ef6c74e973ea13d15180190d0fa2af82fbf)

Co-authored-by: Serhiy Storchaka <[email protected]>

files:
A Misc/NEWS.d/next/Library/2024-09-27-15-16-04.gh-issue-116850.dBkR0-.rst
M Lib/argparse.py
M Lib/test/test_argparse.py

diff --git a/Lib/argparse.py b/Lib/argparse.py
index b0ab66ae223a2f..36276d9faac101 100644
--- a/Lib/argparse.py
+++ b/Lib/argparse.py
@@ -1269,7 +1269,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):
diff --git a/Lib/test/test_argparse.py b/Lib/test/test_argparse.py
index e65c65a0816a2d..c173c0a567216a 100644
--- a/Lib/test/test_argparse.py
+++ b/Lib/test/test_argparse.py
@@ -2301,6 +2301,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)
diff --git 
a/Misc/NEWS.d/next/Library/2024-09-27-15-16-04.gh-issue-116850.dBkR0-.rst 
b/Misc/NEWS.d/next/Library/2024-09-27-15-16-04.gh-issue-116850.dBkR0-.rst
new file mode 100644
index 00000000000000..62639a16c52aa0
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2024-09-27-15-16-04.gh-issue-116850.dBkR0-.rst
@@ -0,0 +1,2 @@
+Fix :mod:`argparse` for namespaces with not directly writable dict (e.g.
+classes).

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: [email protected]

Reply via email to