From e7c3481b071d0b11ba863ecdacf3b814c5b6bca2 Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Tue, 12 Apr 2022 12:14:22 +0100 Subject: [PATCH 1/2] Drop some literal types from argparse (add_argument) These were introduced in #7329 and they cause false positives in code that used to be accepted before. There was a false positive in https://github.com/pycqa/pylint (encountered in https://github.com/python/mypy/pull/12321) and I also saw false positives in an internal codebase. I suggest not using literal types here, since they can be kind of awkward to annotate in callers that don't pass a literal string. Rrequiring callers to write annotations like `Literal["?", "*", "+", "...", "A...", "==SUPPRESS=="]` is not very user friendly. --- stdlib/argparse.pyi | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/stdlib/argparse.pyi b/stdlib/argparse.pyi index ad54660cc45d..5c58ba85cd0c 100644 --- a/stdlib/argparse.pyi +++ b/stdlib/argparse.pyi @@ -106,11 +106,8 @@ class _ActionsContainer: def add_argument( self, *name_or_flags: str, - action: Literal[ - "store", "store_const", "store_true", "store_false", "append", "append_const", "count", "help", "version", "extend" - ] - | type[Action] = ..., - nargs: int | Literal["?", "*", "+", "...", "A...", "==SUPPRESS=="] | _SUPPRESS_T = ..., + action: str | type[Action] = ..., + nargs: int | str | _SUPPRESS_T = ..., const: Any = ..., default: Any = ..., type: Callable[[str], _T] | FileType = ..., From 2e448925fea3b39f5e8d9a54b0829123f69214d0 Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Wed, 13 Apr 2022 12:09:31 +0100 Subject: [PATCH 2/2] Define aliases and include literal types in comments --- stdlib/argparse.pyi | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/stdlib/argparse.pyi b/stdlib/argparse.pyi index 5c58ba85cd0c..0a56aa4f4b59 100644 --- a/stdlib/argparse.pyi +++ b/stdlib/argparse.pyi @@ -62,6 +62,15 @@ _T = TypeVar("_T") _ActionT = TypeVar("_ActionT", bound=Action) _ArgumentParserT = TypeVar("_ArgumentParserT", bound=ArgumentParser) _N = TypeVar("_N") +# more precisely, Literal["store", "store_const", "store_true", +# "store_false", "append", "append_const", "count", "help", "version", +# "extend"], but using this would make it hard to annotate callers +# that don't use a literal argument +_ActionStr = str +# more precisely, Literal["?", "*", "+", "...", "A...", +# "==SUPPRESS=="], but using this would make it hard to annotate +# callers that don't use a literal argument +_NArgsStr = str ONE_OR_MORE: Literal["+"] OPTIONAL: Literal["?"] @@ -106,8 +115,8 @@ class _ActionsContainer: def add_argument( self, *name_or_flags: str, - action: str | type[Action] = ..., - nargs: int | str | _SUPPRESS_T = ..., + action: _ActionStr | type[Action] = ..., + nargs: int | _NArgsStr | _SUPPRESS_T = ..., const: Any = ..., default: Any = ..., type: Callable[[str], _T] | FileType = ...,