bpo-33197: Update a error message of invalid inspect.Parameters. (GH-6636)
This commit is contained in:
parent
9551f77192
commit
a9cab433bb
|
@ -2402,6 +2402,16 @@ _VAR_POSITIONAL = _ParameterKind.VAR_POSITIONAL
|
||||||
_KEYWORD_ONLY = _ParameterKind.KEYWORD_ONLY
|
_KEYWORD_ONLY = _ParameterKind.KEYWORD_ONLY
|
||||||
_VAR_KEYWORD = _ParameterKind.VAR_KEYWORD
|
_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:
|
class Parameter:
|
||||||
"""Represents a parameter in a function signature.
|
"""Represents a parameter in a function signature.
|
||||||
|
@ -2436,15 +2446,14 @@ class Parameter:
|
||||||
empty = _empty
|
empty = _empty
|
||||||
|
|
||||||
def __init__(self, name, kind, *, default=_empty, annotation=_empty):
|
def __init__(self, name, kind, *, default=_empty, annotation=_empty):
|
||||||
|
try:
|
||||||
if kind not in (_POSITIONAL_ONLY, _POSITIONAL_OR_KEYWORD,
|
self._kind = _ParameterKind(kind)
|
||||||
_VAR_POSITIONAL, _KEYWORD_ONLY, _VAR_KEYWORD):
|
except ValueError:
|
||||||
raise ValueError("invalid value for 'Parameter.kind' attribute")
|
raise ValueError(f'value {kind!r} is not a valid Parameter.kind')
|
||||||
self._kind = kind
|
|
||||||
|
|
||||||
if default is not _empty:
|
if default is not _empty:
|
||||||
if kind in (_VAR_POSITIONAL, _VAR_KEYWORD):
|
if self._kind in (_VAR_POSITIONAL, _VAR_KEYWORD):
|
||||||
msg = '{} parameters cannot have default values'.format(kind)
|
msg = '{} parameters cannot have default values'
|
||||||
|
msg = msg.format(_get_paramkind_descr(self._kind))
|
||||||
raise ValueError(msg)
|
raise ValueError(msg)
|
||||||
self._default = default
|
self._default = default
|
||||||
self._annotation = annotation
|
self._annotation = annotation
|
||||||
|
@ -2453,19 +2462,21 @@ class Parameter:
|
||||||
raise ValueError('name is a required attribute for Parameter')
|
raise ValueError('name is a required attribute for Parameter')
|
||||||
|
|
||||||
if not isinstance(name, str):
|
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():
|
if name[0] == '.' and name[1:].isdigit():
|
||||||
# These are implicit arguments generated by comprehensions. In
|
# These are implicit arguments generated by comprehensions. In
|
||||||
# order to provide a friendlier interface to users, we recast
|
# order to provide a friendlier interface to users, we recast
|
||||||
# their name as "implicitN" and treat them as positional-only.
|
# their name as "implicitN" and treat them as positional-only.
|
||||||
# See issue 19611.
|
# See issue 19611.
|
||||||
if kind != _POSITIONAL_OR_KEYWORD:
|
if self._kind != _POSITIONAL_OR_KEYWORD:
|
||||||
raise ValueError(
|
msg = (
|
||||||
'implicit arguments must be passed in as {}'.format(
|
'implicit arguments must be passed as '
|
||||||
_POSITIONAL_OR_KEYWORD
|
'positional or keyword arguments, not {}'
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
msg = msg.format(_get_paramkind_descr(self._kind))
|
||||||
|
raise ValueError(msg)
|
||||||
self._kind = _POSITIONAL_ONLY
|
self._kind = _POSITIONAL_ONLY
|
||||||
name = 'implicit{}'.format(name[1:])
|
name = 'implicit{}'.format(name[1:])
|
||||||
|
|
||||||
|
@ -2736,8 +2747,12 @@ class Signature:
|
||||||
name = param.name
|
name = param.name
|
||||||
|
|
||||||
if kind < top_kind:
|
if kind < top_kind:
|
||||||
msg = 'wrong parameter order: {!r} before {!r}'
|
msg = (
|
||||||
msg = msg.format(top_kind, kind)
|
'wrong parameter order: {} parameter before {} '
|
||||||
|
'parameter'
|
||||||
|
)
|
||||||
|
msg = msg.format(_get_paramkind_descr(top_kind),
|
||||||
|
_get_paramkind_descr(kind))
|
||||||
raise ValueError(msg)
|
raise ValueError(msg)
|
||||||
elif kind > top_kind:
|
elif kind > top_kind:
|
||||||
kind_defaults = False
|
kind_defaults = False
|
||||||
|
|
|
@ -1499,6 +1499,20 @@ class TestGetcallargsFunctions(unittest.TestCase):
|
||||||
with self.assertRaisesRegex(TypeError, "'a', 'b' and 'c'"):
|
with self.assertRaisesRegex(TypeError, "'a', 'b' and 'c'"):
|
||||||
inspect.getcallargs(f6)
|
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):
|
class TestGetcallargsMethods(TestGetcallargsFunctions):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
|
@ -3099,7 +3113,8 @@ class TestParameterObject(unittest.TestCase):
|
||||||
self.assertIs(p.annotation, p.empty)
|
self.assertIs(p.annotation, p.empty)
|
||||||
self.assertEqual(p.kind, inspect.Parameter.POSITIONAL_ONLY)
|
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')
|
inspect.Parameter('foo', default=10, kind='123')
|
||||||
|
|
||||||
with self.assertRaisesRegex(ValueError, 'not a valid parameter name'):
|
with self.assertRaisesRegex(ValueError, 'not a valid parameter name'):
|
||||||
|
@ -3189,7 +3204,9 @@ class TestParameterObject(unittest.TestCase):
|
||||||
self.assertEqual(p2.kind, p2.POSITIONAL_OR_KEYWORD)
|
self.assertEqual(p2.kind, p2.POSITIONAL_OR_KEYWORD)
|
||||||
self.assertNotEqual(p2, p)
|
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.empty)
|
||||||
|
|
||||||
p2 = p2.replace(kind=p2.KEYWORD_ONLY)
|
p2 = p2.replace(kind=p2.KEYWORD_ONLY)
|
||||||
|
@ -3202,7 +3219,9 @@ class TestParameterObject(unittest.TestCase):
|
||||||
@cpython_only
|
@cpython_only
|
||||||
def test_signature_parameter_implicit(self):
|
def test_signature_parameter_implicit(self):
|
||||||
with self.assertRaisesRegex(ValueError,
|
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)
|
inspect.Parameter('.0', kind=inspect.Parameter.POSITIONAL_ONLY)
|
||||||
|
|
||||||
param = inspect.Parameter(
|
param = inspect.Parameter(
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
Update error message when constructing invalid inspect.Parameters
|
||||||
|
Patch by Dong-hee Na.
|
Loading…
Reference in New Issue