From e4ae535d8f472a9338e392d459996cd4d4098c8e Mon Sep 17 00:00:00 2001 From: Apostol Fet Date: Fri, 6 Dec 2024 00:20:19 +0300 Subject: [PATCH 01/10] Tests to check validation of more than one var positional and var keyword parameters --- Lib/test/test_inspect/test_inspect.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Lib/test/test_inspect/test_inspect.py b/Lib/test/test_inspect/test_inspect.py index a92627a4d60f68..4c06b9d1187f67 100644 --- a/Lib/test/test_inspect/test_inspect.py +++ b/Lib/test/test_inspect/test_inspect.py @@ -2992,6 +2992,14 @@ def test2(pod=42, /): with self.assertRaisesRegex(ValueError, 'follows default argument'): S((pkd, pk)) + second_args = args.replace(name="second_args") + with self.assertRaisesRegex(ValueError, 'more than one var positional parameter'): + S((args, second_args)) + + second_kwargs = kwargs.replace(name="second_kwargs") + with self.assertRaisesRegex(ValueError, 'more than one var keyword parameter'): + S((kwargs, second_kwargs)) + def test_signature_object_pickle(self): def foo(a, b, *, c:1={}, **kw) -> {42:'ham'}: pass foo_partial = functools.partial(foo, a=1) From 8aac6f11befa8ad897303f76a591322a95110b4e Mon Sep 17 00:00:00 2001 From: Apostol Fet Date: Fri, 6 Dec 2024 00:21:36 +0300 Subject: [PATCH 02/10] Added validation for more than one var positional and var keyword parameters --- Lib/inspect.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/Lib/inspect.py b/Lib/inspect.py index e3f74e9f047eaf..f51aab59648b49 100644 --- a/Lib/inspect.py +++ b/Lib/inspect.py @@ -2943,6 +2943,8 @@ def __init__(self, parameters=None, *, return_annotation=_empty, params = OrderedDict() top_kind = _POSITIONAL_ONLY seen_default = False + var_positional_count = 0 + var_keyword_count = 0 for param in parameters: kind = param.kind @@ -2971,6 +2973,18 @@ def __init__(self, parameters=None, *, return_annotation=_empty, # There is a default for this parameter. seen_default = True + if kind == _VAR_POSITIONAL: + var_positional_count += 1 + if var_positional_count > 1: + msg = 'more than one var positional parameter' + raise ValueError(msg) + + if kind == _VAR_KEYWORD: + var_keyword_count += 1 + if var_keyword_count > 1: + msg = 'more than one var keyword parameter' + raise ValueError(msg) + if name in params: msg = 'duplicate parameter name: {!r}'.format(name) raise ValueError(msg) From 64b53a871587f40e3f46e8f28522ee6094dd4105 Mon Sep 17 00:00:00 2001 From: Apostol Fet Date: Fri, 6 Dec 2024 00:41:18 +0300 Subject: [PATCH 03/10] Add name in ACKS --- Misc/ACKS | 1 + 1 file changed, 1 insertion(+) diff --git a/Misc/ACKS b/Misc/ACKS index 913f7c8ecf5f1e..086930666822ad 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -24,6 +24,7 @@ Eitan Adler Anton Afanasyev Ali Afshar Nitika Agarwal +Maxim Ageev Anjani Agrawal Pablo S. Blum de Aguiar Jim Ahlstrom From 97c086c029e8369535031d2edd0c1b3ca08953c1 Mon Sep 17 00:00:00 2001 From: Apostol Fet Date: Fri, 6 Dec 2024 20:22:38 +0300 Subject: [PATCH 04/10] Fix review remarks --- Lib/inspect.py | 18 ++++++++++-------- Lib/test/test_inspect/test_inspect.py | 4 ++-- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/Lib/inspect.py b/Lib/inspect.py index f51aab59648b49..1bb3cffea3e620 100644 --- a/Lib/inspect.py +++ b/Lib/inspect.py @@ -2943,8 +2943,8 @@ def __init__(self, parameters=None, *, return_annotation=_empty, params = OrderedDict() top_kind = _POSITIONAL_ONLY seen_default = False - var_positional_count = 0 - var_keyword_count = 0 + seen_var_positional = False + seen_var_keyword = False for param in parameters: kind = param.kind @@ -2974,17 +2974,19 @@ def __init__(self, parameters=None, *, return_annotation=_empty, seen_default = True if kind == _VAR_POSITIONAL: - var_positional_count += 1 - if var_positional_count > 1: - msg = 'more than one var positional parameter' + if seen_var_positional: + msg = 'more than one var-positional parameter' raise ValueError(msg) + seen_var_positional = True + if kind == _VAR_KEYWORD: - var_keyword_count += 1 - if var_keyword_count > 1: - msg = 'more than one var keyword parameter' + if seen_var_keyword: + msg = 'more than one var-keyword parameter' raise ValueError(msg) + seen_var_keyword = True + if name in params: msg = 'duplicate parameter name: {!r}'.format(name) raise ValueError(msg) diff --git a/Lib/test/test_inspect/test_inspect.py b/Lib/test/test_inspect/test_inspect.py index 4c06b9d1187f67..a7970cbccd3d02 100644 --- a/Lib/test/test_inspect/test_inspect.py +++ b/Lib/test/test_inspect/test_inspect.py @@ -2993,11 +2993,11 @@ def test2(pod=42, /): S((pkd, pk)) second_args = args.replace(name="second_args") - with self.assertRaisesRegex(ValueError, 'more than one var positional parameter'): + with self.assertRaisesRegex(ValueError, 'more than one var-positional parameter'): S((args, second_args)) second_kwargs = kwargs.replace(name="second_kwargs") - with self.assertRaisesRegex(ValueError, 'more than one var keyword parameter'): + with self.assertRaisesRegex(ValueError, 'more than one var-keyword parameter'): S((kwargs, second_kwargs)) def test_signature_object_pickle(self): From a7a190a53801b4193d1b1f67e2318a0cbdd0acde Mon Sep 17 00:00:00 2001 From: "blurb-it[bot]" <43283697+blurb-it[bot]@users.noreply.github.com> Date: Fri, 6 Dec 2024 17:28:56 +0000 Subject: [PATCH 05/10] =?UTF-8?q?=F0=9F=93=9C=F0=9F=A4=96=20Added=20by=20b?= =?UTF-8?q?lurb=5Fit.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../next/Library/2024-12-06-17-28-55.gh-issue-127610.ctv_NP.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 Misc/NEWS.d/next/Library/2024-12-06-17-28-55.gh-issue-127610.ctv_NP.rst diff --git a/Misc/NEWS.d/next/Library/2024-12-06-17-28-55.gh-issue-127610.ctv_NP.rst b/Misc/NEWS.d/next/Library/2024-12-06-17-28-55.gh-issue-127610.ctv_NP.rst new file mode 100644 index 00000000000000..c5ffed7cefe855 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2024-12-06-17-28-55.gh-issue-127610.ctv_NP.rst @@ -0,0 +1 @@ +Added validation for more than one var positional and var keyword parameters in ``inspect.Signature.__init__`` From 0f827ede677c6218f390e9ad5ebea04e2068559d Mon Sep 17 00:00:00 2001 From: Apostol Fet <90645107+ApostolFet@users.noreply.github.com> Date: Sat, 7 Dec 2024 11:20:45 +0300 Subject: [PATCH 06/10] Update Misc/NEWS.d/next/Library/2024-12-06-17-28-55.gh-issue-127610.ctv_NP.rst Co-authored-by: Sergey B Kirpichev --- .../Library/2024-12-06-17-28-55.gh-issue-127610.ctv_NP.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Misc/NEWS.d/next/Library/2024-12-06-17-28-55.gh-issue-127610.ctv_NP.rst b/Misc/NEWS.d/next/Library/2024-12-06-17-28-55.gh-issue-127610.ctv_NP.rst index c5ffed7cefe855..45cee40ca3b60d 100644 --- a/Misc/NEWS.d/next/Library/2024-12-06-17-28-55.gh-issue-127610.ctv_NP.rst +++ b/Misc/NEWS.d/next/Library/2024-12-06-17-28-55.gh-issue-127610.ctv_NP.rst @@ -1 +1,2 @@ -Added validation for more than one var positional and var keyword parameters in ``inspect.Signature.__init__`` +Added validation for more than one var positional and var +keyword parameters in :class:`inspect.Signature`. From 539d7bc05cc9a2a771ca4a372a2b97a9dc1c4361 Mon Sep 17 00:00:00 2001 From: Apostol Fet Date: Sat, 7 Dec 2024 14:39:06 +0300 Subject: [PATCH 07/10] Moved up a new check, using set instead of bool variables --- Lib/inspect.py | 25 +++++++++---------------- Lib/test/test_inspect/test_inspect.py | 7 +++++-- 2 files changed, 14 insertions(+), 18 deletions(-) diff --git a/Lib/inspect.py b/Lib/inspect.py index 1bb3cffea3e620..2d91d42398a39e 100644 --- a/Lib/inspect.py +++ b/Lib/inspect.py @@ -2943,13 +2943,20 @@ def __init__(self, parameters=None, *, return_annotation=_empty, params = OrderedDict() top_kind = _POSITIONAL_ONLY seen_default = False - seen_var_positional = False - seen_var_keyword = False + seen_var_parameters = set() for param in parameters: kind = param.kind name = param.name + if kind in (_VAR_POSITIONAL, _VAR_KEYWORD): + if kind in seen_var_parameters: + msg = 'more than one {} parameter' + msg = msg.format(kind.description) + raise ValueError(msg) + + seen_var_parameters.add(kind) + if kind < top_kind: msg = ( 'wrong parameter order: {} parameter before {} ' @@ -2973,20 +2980,6 @@ def __init__(self, parameters=None, *, return_annotation=_empty, # There is a default for this parameter. seen_default = True - if kind == _VAR_POSITIONAL: - if seen_var_positional: - msg = 'more than one var-positional parameter' - raise ValueError(msg) - - seen_var_positional = True - - if kind == _VAR_KEYWORD: - if seen_var_keyword: - msg = 'more than one var-keyword parameter' - raise ValueError(msg) - - seen_var_keyword = True - if name in params: msg = 'duplicate parameter name: {!r}'.format(name) raise ValueError(msg) diff --git a/Lib/test/test_inspect/test_inspect.py b/Lib/test/test_inspect/test_inspect.py index a7970cbccd3d02..1ecf18bf49fa7e 100644 --- a/Lib/test/test_inspect/test_inspect.py +++ b/Lib/test/test_inspect/test_inspect.py @@ -2993,11 +2993,14 @@ def test2(pod=42, /): S((pkd, pk)) second_args = args.replace(name="second_args") - with self.assertRaisesRegex(ValueError, 'more than one var-positional parameter'): + with self.assertRaisesRegex(ValueError, 'more than one variadic positional parameter'): S((args, second_args)) + with self.assertRaisesRegex(ValueError, 'more than one variadic positional parameter'): + S((args, ko, second_args)) + second_kwargs = kwargs.replace(name="second_kwargs") - with self.assertRaisesRegex(ValueError, 'more than one var-keyword parameter'): + with self.assertRaisesRegex(ValueError, 'more than one variadic keyword parameter'): S((kwargs, second_kwargs)) def test_signature_object_pickle(self): From fb25db298e9b96f980b4ce0d83e54ab7d4fb3f73 Mon Sep 17 00:00:00 2001 From: Apostol Fet <90645107+ApostolFet@users.noreply.github.com> Date: Sat, 7 Dec 2024 14:42:09 +0300 Subject: [PATCH 08/10] Update Misc/NEWS.d/next/Library/2024-12-06-17-28-55.gh-issue-127610.ctv_NP.rst Co-authored-by: Serhiy Storchaka --- .../Library/2024-12-06-17-28-55.gh-issue-127610.ctv_NP.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Misc/NEWS.d/next/Library/2024-12-06-17-28-55.gh-issue-127610.ctv_NP.rst b/Misc/NEWS.d/next/Library/2024-12-06-17-28-55.gh-issue-127610.ctv_NP.rst index 45cee40ca3b60d..83a69bd369a861 100644 --- a/Misc/NEWS.d/next/Library/2024-12-06-17-28-55.gh-issue-127610.ctv_NP.rst +++ b/Misc/NEWS.d/next/Library/2024-12-06-17-28-55.gh-issue-127610.ctv_NP.rst @@ -1,2 +1,2 @@ -Added validation for more than one var positional and var -keyword parameters in :class:`inspect.Signature`. +Added validation for more than one var-positional or +var-keyword parameters in :class:`inspect.Signature`. From 942a448ac10e23786edcd7f120c066b37133d0ed Mon Sep 17 00:00:00 2001 From: Apostol Fet Date: Sat, 7 Dec 2024 15:16:28 +0300 Subject: [PATCH 09/10] Added caption --- .../next/Library/2024-12-06-17-28-55.gh-issue-127610.ctv_NP.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/Misc/NEWS.d/next/Library/2024-12-06-17-28-55.gh-issue-127610.ctv_NP.rst b/Misc/NEWS.d/next/Library/2024-12-06-17-28-55.gh-issue-127610.ctv_NP.rst index 83a69bd369a861..58769029d79977 100644 --- a/Misc/NEWS.d/next/Library/2024-12-06-17-28-55.gh-issue-127610.ctv_NP.rst +++ b/Misc/NEWS.d/next/Library/2024-12-06-17-28-55.gh-issue-127610.ctv_NP.rst @@ -1,2 +1,3 @@ Added validation for more than one var-positional or var-keyword parameters in :class:`inspect.Signature`. +Patch by Maxim Ageev. From 0de21a297bf7a940ced43b084231b39f80b64b61 Mon Sep 17 00:00:00 2001 From: Apostol Fet Date: Sat, 7 Dec 2024 19:00:27 +0300 Subject: [PATCH 10/10] Using f-string instead of the format function --- Lib/inspect.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Lib/inspect.py b/Lib/inspect.py index 2d91d42398a39e..b7d8271f8a471f 100644 --- a/Lib/inspect.py +++ b/Lib/inspect.py @@ -2951,8 +2951,7 @@ def __init__(self, parameters=None, *, return_annotation=_empty, if kind in (_VAR_POSITIONAL, _VAR_KEYWORD): if kind in seen_var_parameters: - msg = 'more than one {} parameter' - msg = msg.format(kind.description) + msg = f'more than one {kind.description} parameter' raise ValueError(msg) seen_var_parameters.add(kind)