Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bpo-33197: Update error message of invalid inspect.Parameters #6636

Merged
merged 1 commit into from
May 29, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 31 additions & 16 deletions Lib/inspect.py
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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
Expand All @@ -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:])

Expand Down Expand Up @@ -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
Expand Down
25 changes: 22 additions & 3 deletions Lib/test/test_inspect.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down Expand Up @@ -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'):
Expand Down Expand Up @@ -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)
Expand All @@ -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(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Update error message when constructing invalid inspect.Parameters
Patch by Dong-hee Na.