Skip to content

Commit 5b3190a

Browse files
committed
Put type checker global state in separate module
1 parent 4b08554 commit 5b3190a

File tree

6 files changed

+41
-23
lines changed

6 files changed

+41
-23
lines changed

mypy/checker.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
from mypy import errorcodes as codes, join, message_registry, nodes, operators
1414
from mypy.binder import ConditionalTypeBinder, Frame, get_declaration
1515
from mypy.checker_shared import CheckerScope, TypeCheckerSharedApi, TypeRange
16+
from mypy.checker_state import checker_state
1617
from mypy.checkmember import (
1718
MemberContext,
1819
analyze_class_attribute_access,
@@ -455,7 +456,7 @@ def check_first_pass(self) -> None:
455456
Deferred functions will be processed by check_second_pass().
456457
"""
457458
self.recurse_into_functions = True
458-
with state.strict_optional_set(self.options.strict_optional), state.type_checker_set(self):
459+
with state.strict_optional_set(self.options.strict_optional), checker_state.set(self):
459460
self.errors.set_file(
460461
self.path, self.tree.fullname, scope=self.tscope, options=self.options
461462
)
@@ -496,7 +497,7 @@ def check_second_pass(
496497
This goes through deferred nodes, returning True if there were any.
497498
"""
498499
self.recurse_into_functions = True
499-
with state.strict_optional_set(self.options.strict_optional), state.type_checker_set(self):
500+
with state.strict_optional_set(self.options.strict_optional), checker_state.set(self):
500501
if not todo and not self.deferred_nodes:
501502
return False
502503
self.errors.set_file(

mypy/checker_state.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
from __future__ import annotations
2+
3+
from collections.abc import Iterator
4+
from contextlib import contextmanager
5+
from typing import Final
6+
7+
from mypy.checker_shared import TypeCheckerSharedApi
8+
9+
# This is global mutable state. Don't add anything here unless there's a very
10+
# good reason.
11+
12+
13+
class TypeCheckerState:
14+
# Wrap this in a class since it's faster that using a module-level attribute.
15+
16+
def __init__(self, type_checker: TypeCheckerSharedApi | None) -> None:
17+
# Value varies by file being processed
18+
self.type_checker = type_checker
19+
20+
@contextmanager
21+
def set(self, value: TypeCheckerSharedApi) -> Iterator[None]:
22+
saved = self.type_checker
23+
self.type_checker = value
24+
try:
25+
yield
26+
finally:
27+
self.type_checker = saved
28+
29+
30+
checker_state: Final = TypeCheckerState(type_checker=None)

mypy/expandtype.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
from typing import Final, TypeVar, cast, overload
55

66
from mypy.nodes import ARG_STAR, FakeInfo, Var
7+
from mypy.state import state
78
from mypy.types import (
89
ANY_STRATEGY,
910
AnyType,
@@ -543,8 +544,6 @@ def remove_trivial(types: Iterable[Type]) -> list[Type]:
543544
* Remove everything else if there is an `object`
544545
* Remove strict duplicate types
545546
"""
546-
from mypy.state import state
547-
548547
removed_none = False
549548
new_types = []
550549
all_types = set()

mypy/state.py

Lines changed: 4 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,16 @@
44
from contextlib import contextmanager
55
from typing import Final
66

7-
from mypy.checker_shared import TypeCheckerSharedApi
8-
97
# These are global mutable state. Don't add anything here unless there's a very
108
# good reason.
119

1210

13-
class SubtypeState:
11+
class StrictOptionalState:
1412
# Wrap this in a class since it's faster that using a module-level attribute.
1513

16-
def __init__(self, strict_optional: bool, type_checker: TypeCheckerSharedApi | None) -> None:
17-
# Values vary by file being processed
14+
def __init__(self, strict_optional: bool) -> None:
15+
# Value varies by file being processed
1816
self.strict_optional = strict_optional
19-
self.type_checker = type_checker
2017

2118
@contextmanager
2219
def strict_optional_set(self, value: bool) -> Iterator[None]:
@@ -27,15 +24,6 @@ def strict_optional_set(self, value: bool) -> Iterator[None]:
2724
finally:
2825
self.strict_optional = saved
2926

30-
@contextmanager
31-
def type_checker_set(self, value: TypeCheckerSharedApi) -> Iterator[None]:
32-
saved = self.type_checker
33-
self.type_checker = value
34-
try:
35-
yield
36-
finally:
37-
self.type_checker = saved
38-
3927

40-
state: Final = SubtypeState(strict_optional=True, type_checker=None)
28+
state: Final = StrictOptionalState(strict_optional=True)
4129
find_occurrences: tuple[str, str] | None = None

mypy/subtypes.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import mypy.applytype
99
import mypy.constraints
1010
import mypy.typeops
11+
from mypy.checker_state import checker_state
1112
from mypy.erasetype import erase_type
1213
from mypy.expandtype import (
1314
expand_self_type,
@@ -1267,7 +1268,7 @@ def find_member(
12671268
class_obj: bool = False,
12681269
is_lvalue: bool = False,
12691270
) -> Type | None:
1270-
type_checker = state.type_checker
1271+
type_checker = checker_state.type_checker
12711272
if type_checker is None:
12721273
# Unfortunately, there are many scenarios where someone calls is_subtype() before
12731274
# type checking phase. In this case we fallback to old (incomplete) logic.

mypy/types.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
SymbolNode,
3333
)
3434
from mypy.options import Options
35+
from mypy.state import state
3536
from mypy.util import IdMapper
3637

3738
T = TypeVar("T")
@@ -2978,8 +2979,6 @@ def accept(self, visitor: TypeVisitor[T]) -> T:
29782979

29792980
def relevant_items(self) -> list[Type]:
29802981
"""Removes NoneTypes from Unions when strict Optional checking is off."""
2981-
from mypy.state import state
2982-
29832982
if state.strict_optional:
29842983
return self.items
29852984
else:

0 commit comments

Comments
 (0)