From a37d49efca339c8c7a6c2a31bbd7375bd97b78bb Mon Sep 17 00:00:00 2001 From: Marc Mueller <30130371+cdce8p@users.noreply.github.com> Date: Wed, 28 May 2025 17:13:54 +0200 Subject: [PATCH 1/3] Provide a better fallback value for the python_version option --- mypy/config_parser.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/mypy/config_parser.py b/mypy/config_parser.py index 0e033471d2e9..f7cd981e1917 100644 --- a/mypy/config_parser.py +++ b/mypy/config_parser.py @@ -28,6 +28,14 @@ _INI_PARSER_CALLABLE: _TypeAlias = Callable[[Any], _CONFIG_VALUE_TYPES] +class VersionTypeError(argparse.ArgumentTypeError): + """Provide a fallback value if the Python version is unsupported.""" + + def __init__(self, *args: Any, fallback: tuple[int, int]) -> None: + self.fallback = fallback + super().__init__(*args) + + def parse_version(v: str | float) -> tuple[int, int]: m = re.match(r"\A(\d)\.(\d+)\Z", str(v)) if not m: @@ -44,7 +52,7 @@ def parse_version(v: str | float) -> tuple[int, int]: if isinstance(v, float): msg += ". You may need to put quotes around your Python version" - raise argparse.ArgumentTypeError(msg) + raise VersionTypeError(msg, fallback=defaults.PYTHON3_VERSION_MIN) else: raise argparse.ArgumentTypeError( f"Python major version '{major}' out of range (must be 3)" @@ -548,6 +556,9 @@ def parse_section( continue try: v = ct(section.get(key)) + except VersionTypeError as err: + print(f"{prefix}{key}: {err}", file=stderr) + v = err.fallback except argparse.ArgumentTypeError as err: print(f"{prefix}{key}: {err}", file=stderr) continue From 8cfbe9ce9b0cc054076d6a39f87e92b27e3b92d2 Mon Sep 17 00:00:00 2001 From: Marc Mueller <30130371+cdce8p@users.noreply.github.com> Date: Wed, 28 May 2025 18:29:11 +0200 Subject: [PATCH 2/3] Fix mypyc tests --- mypy/config_parser.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mypy/config_parser.py b/mypy/config_parser.py index f7cd981e1917..e5c0dc893c76 100644 --- a/mypy/config_parser.py +++ b/mypy/config_parser.py @@ -556,9 +556,9 @@ def parse_section( continue try: v = ct(section.get(key)) - except VersionTypeError as err: - print(f"{prefix}{key}: {err}", file=stderr) - v = err.fallback + except VersionTypeError as err_version: + print(f"{prefix}{key}: {err_version}", file=stderr) + v = err_version.fallback except argparse.ArgumentTypeError as err: print(f"{prefix}{key}: {err}", file=stderr) continue From 99dd45cce2878775c58dd3da55c9cab8a54daab9 Mon Sep 17 00:00:00 2001 From: Marc Mueller <30130371+cdce8p@users.noreply.github.com> Date: Mon, 2 Jun 2025 00:39:17 +0200 Subject: [PATCH 3/3] Add test case --- test-data/unit/cmdline.test | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/test-data/unit/cmdline.test b/test-data/unit/cmdline.test index 012e1e6b7fe6..4fda85d83c1b 100644 --- a/test-data/unit/cmdline.test +++ b/test-data/unit/cmdline.test @@ -440,6 +440,20 @@ python_version = 3.9 python_version = 3.13 [out] +[case testPythonVersionFallback] +# cmd: mypy main.py +[file main.py] +import sys +if sys.version_info == (3, 9): # Update here when bumping the min Python version! + reveal_type("good") +[file mypy.ini] +\[mypy] +python_version = 3.8 +[out] +mypy.ini: [mypy]: python_version: Python 3.8 is not supported (must be 3.9 or higher) +main.py:3: note: Revealed type is "Literal['good']?" +== Return code: 0 + -- This should be a dumping ground for tests of plugins that are sensitive to -- typeshed changes. [case testTypeshedSensitivePlugins]