[Python-checkins] bpo-33197: Update a error message of invalid inspect.Parameters. (GH-6636) (GH-7204)

Yury Selivanov webhook-mailer at python.org
Tue May 29 11:43:58 EDT 2018


https://github.com/python/cpython/commit/cb055bcc2bbfa5dcc6b0332305918a2118d9ebbc
commit: cb055bcc2bbfa5dcc6b0332305918a2118d9ebbc
branch: 3.7
author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com>
committer: Yury Selivanov <yury at magic.io>
date: 2018-05-29T11:43:54-04:00
summary:

bpo-33197: Update a error message of invalid inspect.Parameters. (GH-6636) (GH-7204)

(cherry picked from commit a9cab433bbf02f3a1de59d14dc8f583181ffe2d5)

Co-authored-by: Dong-hee Na <donghee.na92 at gmail.com>

files:
A Misc/NEWS.d/next/Library/2018-04-29-23-56-20.bpo-33197.dgRLqr.rst
M Lib/inspect.py
M Lib/test/test_inspect.py

diff --git a/Lib/inspect.py b/Lib/inspect.py
index f2719923e1ae..022cc1922c7a 100644
--- a/Lib/inspect.py
+++ b/Lib/inspect.py
@@ -2402,6 +2402,16 @@ def __str__(self):
 _KEYWORD_ONLY            = _ParameterKind.KEYWORD_ONLY
 _VAR_KEYWORD             = _ParameterKind.VAR_KEYWORD
 
+_PARAM_NAME_MAPPING = {
+    _POSITIONAL_ONLY: 'positional-only',
+    _POSITIONAL_OR_KEYWORD: 'positional or keyword',
+    _VAR_POSITIONAL: 'variadic positional',
+    _KEYWORD_ONLY: 'keyword-only',
+    _VAR_KEYWORD: 'variadic keyword'
+}
+
+_get_paramkind_descr = _PARAM_NAME_MAPPING.__getitem__
+
 
 class Parameter:
     """Represents a parameter in a function signature.
@@ -2436,15 +2446,14 @@ class Parameter:
     empty = _empty
 
     def __init__(self, name, kind, *, default=_empty, annotation=_empty):
-
-        if kind not in (_POSITIONAL_ONLY, _POSITIONAL_OR_KEYWORD,
-                        _VAR_POSITIONAL, _KEYWORD_ONLY, _VAR_KEYWORD):
-            raise ValueError("invalid value for 'Parameter.kind' attribute")
-        self._kind = kind
-
+        try:
+            self._kind = _ParameterKind(kind)
+        except ValueError:
+            raise ValueError(f'value {kind!r} is not a valid Parameter.kind')
         if default is not _empty:
-            if kind in (_VAR_POSITIONAL, _VAR_KEYWORD):
-                msg = '{} parameters cannot have default values'.format(kind)
+            if self._kind in (_VAR_POSITIONAL, _VAR_KEYWORD):
+                msg = '{} parameters cannot have default values'
+                msg = msg.format(_get_paramkind_descr(self._kind))
                 raise ValueError(msg)
         self._default = default
         self._annotation = annotation
@@ -2453,19 +2462,21 @@ def __init__(self, name, kind, *, default=_empty, annotation=_empty):
             raise ValueError('name is a required attribute for Parameter')
 
         if not isinstance(name, str):
-            raise TypeError("name must be a str, not a {!r}".format(name))
+            msg = 'name must be a str, not a {}'.format(type(name).__name__)
+            raise TypeError(msg)
 
         if name[0] == '.' and name[1:].isdigit():
             # These are implicit arguments generated by comprehensions. In
             # order to provide a friendlier interface to users, we recast
             # their name as "implicitN" and treat them as positional-only.
             # See issue 19611.
-            if kind != _POSITIONAL_OR_KEYWORD:
-                raise ValueError(
-                    'implicit arguments must be passed in as {}'.format(
-                        _POSITIONAL_OR_KEYWORD
-                    )
+            if self._kind != _POSITIONAL_OR_KEYWORD:
+                msg = (
+                    'implicit arguments must be passed as '
+                    'positional or keyword arguments, not {}'
                 )
+                msg = msg.format(_get_paramkind_descr(self._kind))
+                raise ValueError(msg)
             self._kind = _POSITIONAL_ONLY
             name = 'implicit{}'.format(name[1:])
 
@@ -2736,8 +2747,12 @@ def __init__(self, parameters=None, *, return_annotation=_empty,
                     name = param.name
 
                     if kind < top_kind:
-                        msg = 'wrong parameter order: {!r} before {!r}'
-                        msg = msg.format(top_kind, kind)
+                        msg = (
+                            'wrong parameter order: {} parameter before {} '
+                            'parameter'
+                        )
+                        msg = msg.format(_get_paramkind_descr(top_kind),
+                                         _get_paramkind_descr(kind))
                         raise ValueError(msg)
                     elif kind > top_kind:
                         kind_defaults = False
diff --git a/Lib/test/test_inspect.py b/Lib/test/test_inspect.py
index 3481a57ec833..ff6f01454513 100644
--- a/Lib/test/test_inspect.py
+++ b/Lib/test/test_inspect.py
@@ -1444,6 +1444,20 @@ def f6(a, b, c):
         with self.assertRaisesRegex(TypeError, "'a', 'b' and 'c'"):
             inspect.getcallargs(f6)
 
+        # bpo-33197
+        with self.assertRaisesRegex(ValueError,
+                                    'variadic keyword parameters cannot'
+                                    ' have default values'):
+            inspect.Parameter("foo", kind=inspect.Parameter.VAR_KEYWORD,
+                              default=42)
+        with self.assertRaisesRegex(ValueError,
+                                    "value 5 is not a valid Parameter.kind"):
+            inspect.Parameter("bar", kind=5, default=42)
+
+        with self.assertRaisesRegex(TypeError,
+                                   'name must be a str, not a int'):
+            inspect.Parameter(123, kind=4)
+
 class TestGetcallargsMethods(TestGetcallargsFunctions):
 
     def setUp(self):
@@ -3044,7 +3058,8 @@ def test_signature_parameter_object(self):
         self.assertIs(p.annotation, p.empty)
         self.assertEqual(p.kind, inspect.Parameter.POSITIONAL_ONLY)
 
-        with self.assertRaisesRegex(ValueError, 'invalid value'):
+        with self.assertRaisesRegex(ValueError, "value '123' is "
+                                    "not a valid Parameter.kind"):
             inspect.Parameter('foo', default=10, kind='123')
 
         with self.assertRaisesRegex(ValueError, 'not a valid parameter name'):
@@ -3134,7 +3149,9 @@ def test_signature_parameter_replace(self):
         self.assertEqual(p2.kind, p2.POSITIONAL_OR_KEYWORD)
         self.assertNotEqual(p2, p)
 
-        with self.assertRaisesRegex(ValueError, 'invalid value for'):
+        with self.assertRaisesRegex(ValueError,
+                                    "value <class 'inspect._empty'> "
+                                    "is not a valid Parameter.kind"):
             p2 = p2.replace(kind=p2.empty)
 
         p2 = p2.replace(kind=p2.KEYWORD_ONLY)
@@ -3147,7 +3164,9 @@ def test_signature_parameter_positional_only(self):
     @cpython_only
     def test_signature_parameter_implicit(self):
         with self.assertRaisesRegex(ValueError,
-                                    'implicit arguments must be passed in as'):
+                                    'implicit arguments must be passed as '
+                                    'positional or keyword arguments, '
+                                    'not positional-only'):
             inspect.Parameter('.0', kind=inspect.Parameter.POSITIONAL_ONLY)
 
         param = inspect.Parameter(
diff --git a/Misc/NEWS.d/next/Library/2018-04-29-23-56-20.bpo-33197.dgRLqr.rst b/Misc/NEWS.d/next/Library/2018-04-29-23-56-20.bpo-33197.dgRLqr.rst
new file mode 100644
index 000000000000..1bbb44b2fc39
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2018-04-29-23-56-20.bpo-33197.dgRLqr.rst
@@ -0,0 +1,2 @@
+Update error message when constructing invalid inspect.Parameters
+Patch by Dong-hee Na.



More information about the Python-checkins mailing list