mirror of https://github.com/python/cpython
gh-103556: [inspect.Signature] disallow pos-or-kw params without default after pos-only with default (#103557)
This commit is contained in:
parent
7d20783d45
commit
6b58d419a1
|
@ -3006,7 +3006,7 @@ class Signature:
|
|||
if __validate_parameters__:
|
||||
params = OrderedDict()
|
||||
top_kind = _POSITIONAL_ONLY
|
||||
kind_defaults = False
|
||||
seen_default = False
|
||||
|
||||
for param in parameters:
|
||||
kind = param.kind
|
||||
|
@ -3021,21 +3021,19 @@ class Signature:
|
|||
kind.description)
|
||||
raise ValueError(msg)
|
||||
elif kind > top_kind:
|
||||
kind_defaults = False
|
||||
top_kind = kind
|
||||
|
||||
if kind in (_POSITIONAL_ONLY, _POSITIONAL_OR_KEYWORD):
|
||||
if param.default is _empty:
|
||||
if kind_defaults:
|
||||
if seen_default:
|
||||
# No default for this parameter, but the
|
||||
# previous parameter of the same kind had
|
||||
# a default
|
||||
# previous parameter of had a default
|
||||
msg = 'non-default argument follows default ' \
|
||||
'argument'
|
||||
raise ValueError(msg)
|
||||
else:
|
||||
# There is a default for this parameter.
|
||||
kind_defaults = True
|
||||
seen_default = True
|
||||
|
||||
if name in params:
|
||||
msg = 'duplicate parameter name: {!r}'.format(name)
|
||||
|
|
|
@ -2463,18 +2463,43 @@ class TestSignatureObject(unittest.TestCase):
|
|||
self.assertEqual(str(S()), '()')
|
||||
self.assertEqual(repr(S().parameters), 'mappingproxy(OrderedDict())')
|
||||
|
||||
def test(po, pk, pod=42, pkd=100, *args, ko, **kwargs):
|
||||
def test(po, /, pk, pkd=100, *args, ko, kod=10, **kwargs):
|
||||
pass
|
||||
|
||||
sig = inspect.signature(test)
|
||||
po = sig.parameters['po'].replace(kind=P.POSITIONAL_ONLY)
|
||||
pod = sig.parameters['pod'].replace(kind=P.POSITIONAL_ONLY)
|
||||
self.assertTrue(repr(sig).startswith('<Signature'))
|
||||
self.assertTrue('(po, /, pk' in repr(sig))
|
||||
|
||||
# We need two functions, because it is impossible to represent
|
||||
# all param kinds in a single one.
|
||||
def test2(pod=42, /):
|
||||
pass
|
||||
|
||||
sig2 = inspect.signature(test2)
|
||||
self.assertTrue(repr(sig2).startswith('<Signature'))
|
||||
self.assertTrue('(pod=42, /)' in repr(sig2))
|
||||
|
||||
po = sig.parameters['po']
|
||||
pod = sig2.parameters['pod']
|
||||
pk = sig.parameters['pk']
|
||||
pkd = sig.parameters['pkd']
|
||||
args = sig.parameters['args']
|
||||
ko = sig.parameters['ko']
|
||||
kod = sig.parameters['kod']
|
||||
kwargs = sig.parameters['kwargs']
|
||||
|
||||
S((po, pk, args, ko, kwargs))
|
||||
S((po, pk, ko, kod))
|
||||
S((po, pod, ko))
|
||||
S((po, pod, kod))
|
||||
S((pod, ko, kod))
|
||||
S((pod, kod))
|
||||
S((pod, args, kod, kwargs))
|
||||
# keyword-only parameters without default values
|
||||
# can follow keyword-only parameters with default values:
|
||||
S((kod, ko))
|
||||
S((kod, ko, kwargs))
|
||||
S((args, kod, ko))
|
||||
|
||||
with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
|
||||
S((pk, po, args, ko, kwargs))
|
||||
|
@ -2495,15 +2520,18 @@ class TestSignatureObject(unittest.TestCase):
|
|||
with self.assertRaisesRegex(ValueError, 'follows default argument'):
|
||||
S((pod, po))
|
||||
|
||||
with self.assertRaisesRegex(ValueError, 'follows default argument'):
|
||||
S((pod, pk))
|
||||
|
||||
with self.assertRaisesRegex(ValueError, 'follows default argument'):
|
||||
S((po, pod, pk))
|
||||
|
||||
with self.assertRaisesRegex(ValueError, 'follows default argument'):
|
||||
S((po, pkd, pk))
|
||||
|
||||
with self.assertRaisesRegex(ValueError, 'follows default argument'):
|
||||
S((pkd, pk))
|
||||
|
||||
self.assertTrue(repr(sig).startswith('<Signature'))
|
||||
self.assertTrue('(po, pk' in repr(sig))
|
||||
|
||||
def test_signature_object_pickle(self):
|
||||
def foo(a, b, *, c:1={}, **kw) -> {42:'ham'}: pass
|
||||
foo_partial = functools.partial(foo, a=1)
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
Now creating :class:`inspect.Signature` objects with positional-only
|
||||
parameter with a default followed by a positional-or-keyword parameter
|
||||
without one is impossible.
|
Loading…
Reference in New Issue