From 6b58d419a1bd62ac94274d108d59980a3eb6f6e0 Mon Sep 17 00:00:00 2001 From: Nikita Sobolev Date: Sat, 22 Apr 2023 08:45:10 +0300 Subject: gh-103556: [inspect.Signature] disallow pos-or-kw params without default after pos-only with default (#103557) --- Lib/inspect.py | 10 +++--- Lib/test/test_inspect.py | 40 ++++++++++++++++++---- .../2023-04-15-12-19-14.gh-issue-103556.TEf-2m.rst | 3 ++ 3 files changed, 41 insertions(+), 12 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2023-04-15-12-19-14.gh-issue-103556.TEf-2m.rst diff --git a/Lib/inspect.py b/Lib/inspect.py index 4242b40..6d1d7b7 100644 --- a/Lib/inspect.py +++ b/Lib/inspect.py @@ -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) diff --git a/Lib/test/test_inspect.py b/Lib/test/test_inspect.py index 6b342b1..42e3d70 100644 --- a/Lib/test/test_inspect.py +++ b/Lib/test/test_inspect.py @@ -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(' {42:'ham'}: pass foo_partial = functools.partial(foo, a=1) diff --git a/Misc/NEWS.d/next/Library/2023-04-15-12-19-14.gh-issue-103556.TEf-2m.rst b/Misc/NEWS.d/next/Library/2023-04-15-12-19-14.gh-issue-103556.TEf-2m.rst new file mode 100644 index 0000000..fe2267b --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-04-15-12-19-14.gh-issue-103556.TEf-2m.rst @@ -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. -- cgit v0.12