From 9138d86b13d07f031175f468d3979f439cef048a Mon Sep 17 00:00:00 2001 From: Bendaoud Date: Thu, 9 Oct 2025 10:42:18 +0200 Subject: [PATCH 1/9] test_scope_behavior.py --- mypy/test/test_scope_behavior.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 mypy/test/test_scope_behavior.py diff --git a/mypy/test/test_scope_behavior.py b/mypy/test/test_scope_behavior.py new file mode 100644 index 000000000000..142525391cdc --- /dev/null +++ b/mypy/test/test_scope_behavior.py @@ -0,0 +1,17 @@ +from mypy.scope import Scope +from mypy.nodes import FuncDef, TypeInfo, SymbolTable + +def test_scope_module_and_function_behavior() -> None: + scope = Scope() + with scope.module_scope("mod1"): + assert scope.current_module_id() == "mod1" + # simulate function + fake_func = FuncDef("f", None, None, None, None) + with scope.function_scope(fake_func): + assert "f" in scope.current_full_target() + # simulate class inside function + fake_class = TypeInfo(SymbolTable(), "C", None) + with scope.class_scope(fake_class): + assert "C" in scope.current_full_target() + # leaving function restores module + assert scope.current_full_target() == "mod1" From 7b2d6df6c1dfda604a3e23d1634acf6eaeb8454a Mon Sep 17 00:00:00 2001 From: lamia Date: Thu, 9 Oct 2025 10:42:30 +0200 Subject: [PATCH 2/9] modification fichier scope.py --- mypy/scope.py | 1 + 1 file changed, 1 insertion(+) diff --git a/mypy/scope.py b/mypy/scope.py index 766048c41180..55f2c126a903 100644 --- a/mypy/scope.py +++ b/mypy/scope.py @@ -60,6 +60,7 @@ def module_scope(self, prefix: str) -> Iterator[None]: self.module = prefix self.classes = [] self.function = None + self.functions=[] # reset the function stack when entering a new module self.ignored = 0 yield assert self.module From 2b1bba258d3678b3152476e52bd01040337c4ca3 Mon Sep 17 00:00:00 2001 From: Bagou Ines Date: Thu, 9 Oct 2025 10:43:29 +0200 Subject: [PATCH 3/9] ajout du test unitaire issue_scope.test --- test-data/unit/issue_scope.test | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 test-data/unit/issue_scope.test diff --git a/test-data/unit/issue_scope.test b/test-data/unit/issue_scope.test new file mode 100644 index 000000000000..2ea013dd4e62 --- /dev/null +++ b/test-data/unit/issue_scope.test @@ -0,0 +1,17 @@ +[case testScopeOptionalIntResolution] +from typing import Optional + +x: Optional[int] = None +y: Optional[int] = None + +def f() -> None: + x = 1 + y = 1 + class C: + reveal_type(x) # should be int + reveal_type(y) # should be Optional[int] + x = 2 + +[out] +note: Revealed type is "builtins.int" +note: Revealed type is "Union[builtins.int, None]" From 8f6c3c2aa1cb4588abdf2c9572ffacce07246123 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 9 Oct 2025 08:46:36 +0000 Subject: [PATCH 4/9] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- mypy/test/test_scope_behavior.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mypy/test/test_scope_behavior.py b/mypy/test/test_scope_behavior.py index 142525391cdc..074285b23c3c 100644 --- a/mypy/test/test_scope_behavior.py +++ b/mypy/test/test_scope_behavior.py @@ -1,5 +1,6 @@ +from mypy.nodes import FuncDef, SymbolTable, TypeInfo from mypy.scope import Scope -from mypy.nodes import FuncDef, TypeInfo, SymbolTable + def test_scope_module_and_function_behavior() -> None: scope = Scope() From 449df98478a08a15b0d55946e736cb2098e23657 Mon Sep 17 00:00:00 2001 From: lamia Date: Thu, 9 Oct 2025 11:02:14 +0200 Subject: [PATCH 5/9] modification2 fichier scope.py --- mypy/scope.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mypy/scope.py b/mypy/scope.py index 55f2c126a903..32aab6a614d6 100644 --- a/mypy/scope.py +++ b/mypy/scope.py @@ -42,7 +42,7 @@ def current_full_target(self) -> str: """Return the current target (may be a class).""" assert self.module if self.function: - return self.function.fullname + return self.function.fullname or "" if self.classes: return self.classes[-1].fullname return self.module From b6d168accdbbec7d5b7ecb851811f7aad2555c51 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 9 Oct 2025 09:18:44 +0000 Subject: [PATCH 6/9] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- mypy/scope.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mypy/scope.py b/mypy/scope.py index 32aab6a614d6..c17bebeb4646 100644 --- a/mypy/scope.py +++ b/mypy/scope.py @@ -60,7 +60,7 @@ def module_scope(self, prefix: str) -> Iterator[None]: self.module = prefix self.classes = [] self.function = None - self.functions=[] # reset the function stack when entering a new module + self.functions = [] # reset the function stack when entering a new module self.ignored = 0 yield assert self.module From ddbe76116b82066997b47ee267e6d8e8088dc469 Mon Sep 17 00:00:00 2001 From: lamia Date: Thu, 4 Dec 2025 11:38:09 +0100 Subject: [PATCH 7/9] Add note explaining that mypy only supports one global python_version per run --- docs/source/config_file.rst | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/docs/source/config_file.rst b/docs/source/config_file.rst index 7abd1f02db68..a6ec18c24b7b 100644 --- a/docs/source/config_file.rst +++ b/docs/source/config_file.rst @@ -437,6 +437,16 @@ Platform configuration This option may only be set in the global section (``[mypy]``). + .. note:: + + **Using multiple Python versions in a monorepo** + + Mypy currently supports only **one global target Python version** per run. + The configuration option :confval:`python_version` can be set **only in the + global section** of the configuration file. This means that a single + invocation of mypy cannot type-check different parts of a monorepo using + different Python versions. + .. confval:: platform :type: string From 51d08a0fd5eeefde42b75511296323933e3b61f0 Mon Sep 17 00:00:00 2001 From: lamia Date: Mon, 8 Dec 2025 09:42:44 +0100 Subject: [PATCH 8/9] =?UTF-8?q?solutions=20propos=C3=A9s=20pour=20differen?= =?UTF-8?q?tes=20versions=20python?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/source/config_file.rst | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/docs/source/config_file.rst b/docs/source/config_file.rst index a6ec18c24b7b..5a8e50e1ffe5 100644 --- a/docs/source/config_file.rst +++ b/docs/source/config_file.rst @@ -447,6 +447,33 @@ Platform configuration invocation of mypy cannot type-check different parts of a monorepo using different Python versions. + If your project contains directories or packages that target different + Python versions, you can use one of the following workarounds: + + * **Run mypy multiple times**, selecting a different version for each + directory. + + Example:: + + mypy --python-version=3.9 src/py39_package + mypy --python-version=3.11 backend/py311 + + * **Use separate configuration files**, each specifying its own + ``python_version``. + + Example:: + + mypy --config-file=mypy_py39.ini src/py39_package + mypy --config-file=mypy_py311.ini backend/ + + * **Use an external build/monorepo tool** (such as Pants, Bazel, or a CI + pipeline) to orchestrate multiple mypy invocations automatically. + + This documentation update clarifies the current limitation and addresses + :issue:`16944`. + + + .. confval:: platform :type: string From f4acafe3807daf71b16215c4dd56677d6c121cc2 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 8 Dec 2025 08:48:16 +0000 Subject: [PATCH 9/9] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- docs/source/config_file.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/source/config_file.rst b/docs/source/config_file.rst index 5a8e50e1ffe5..5ef87b3ce9bc 100644 --- a/docs/source/config_file.rst +++ b/docs/source/config_file.rst @@ -451,16 +451,16 @@ Platform configuration Python versions, you can use one of the following workarounds: * **Run mypy multiple times**, selecting a different version for each - directory. - + directory. + Example:: mypy --python-version=3.9 src/py39_package mypy --python-version=3.11 backend/py311 * **Use separate configuration files**, each specifying its own - ``python_version``. - + ``python_version``. + Example:: mypy --config-file=mypy_py39.ini src/py39_package