Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit bed9fa4

Browse files
authored
Add Final annotations to mypy code itself (#5623)
This adds `Final` annotations to most module-level and class-level names I have found. Some of these are important to get performance boost after compiling with mypyc, other are just added for completeness. This PR also makes two runtime changes: * `TypeOfAny` switched from an enum to using small integer constants, this is important for performance * `binder.BindableTypes` is now inlined in two `isinstance()` checks. I first made it `Final`, but then realised that it will be much more efficient to just inline it, since these `isinstance()` checks are in a hot code path. Note: after a new version of `typing_extensions` is released on PyPI we can skip all the `if MYPY: ...` checks. The corresponding mypyc PR is mypyc/mypyc#439
1 parent eb509c2 commit bed9fa4

38 files changed

Lines changed: 404 additions & 287 deletions

mypy/binder.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
from mypy.nodes import IndexExpr, MemberExpr, NameExpr
1616

1717

18-
BindableTypes = (IndexExpr, MemberExpr, NameExpr)
1918
BindableExpression = Union[IndexExpr, MemberExpr, NameExpr]
2019

2120

@@ -129,7 +128,7 @@ def _get(self, key: Key, index: int=-1) -> Optional[Type]:
129128
return None
130129

131130
def put(self, expr: Expression, typ: Type) -> None:
132-
if not isinstance(expr, BindableTypes):
131+
if not isinstance(expr, (IndexExpr, MemberExpr, NameExpr)):
133132
return
134133
if not literal(expr):
135134
return
@@ -248,7 +247,7 @@ def assign_type(self, expr: Expression,
248247
# just collect the types.
249248
self.type_assignments[expr].append((type, declared_type))
250249
return
251-
if not isinstance(expr, BindableTypes):
250+
if not isinstance(expr, (IndexExpr, MemberExpr, NameExpr)):
252251
return None
253252
if not literal(expr):
254253
return

mypy/build.py

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
MYPY = False
3636
if MYPY:
3737
from typing import ClassVar
38+
from typing_extensions import Final
3839

3940
from mypy import sitepkgs
4041
from mypy.nodes import (MypyFile, ImportBase, Import, ImportFrom, ImportAll)
@@ -67,10 +68,10 @@
6768
# mode only that is useful during development. This produces only a subset of
6869
# output compared to --verbose output. We use a global flag to enable this so
6970
# that it's easy to enable this when running tests.
70-
DEBUG_FINE_GRAINED = False
71+
DEBUG_FINE_GRAINED = False # type: Final
7172

7273

73-
PYTHON_EXTENSIONS = ['.pyi', '.py']
74+
PYTHON_EXTENSIONS = ['.pyi', '.py'] # type: Final
7475

7576

7677
Graph = Dict[str, 'State']
@@ -484,12 +485,12 @@ def cache_meta_from_dict(meta: Dict[str, Any],
484485
# Priorities used for imports. (Here, top-level includes inside a class.)
485486
# These are used to determine a more predictable order in which the
486487
# nodes in an import cycle are processed.
487-
PRI_HIGH = 5 # top-level "from X import blah"
488-
PRI_MED = 10 # top-level "import X"
489-
PRI_LOW = 20 # either form inside a function
490-
PRI_MYPY = 25 # inside "if MYPY" or "if TYPE_CHECKING"
491-
PRI_INDIRECT = 30 # an indirect dependency
492-
PRI_ALL = 99 # include all priorities
488+
PRI_HIGH = 5 # type: Final # top-level "from X import blah"
489+
PRI_MED = 10 # type: Final # top-level "import X"
490+
PRI_LOW = 20 # type: Final # either form inside a function
491+
PRI_MYPY = 25 # type: Final # inside "if MYPY" or "if TYPE_CHECKING"
492+
PRI_INDIRECT = 30 # type: Final # an indirect dependency
493+
PRI_ALL = 99 # type: Final # include all priorities
493494

494495

495496
def import_priority(imp: ImportBase, toplevel_priority: int) -> int:

mypy/checker.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,10 +63,14 @@
6363

6464
from mypy import experiments
6565

66+
MYPY = False
67+
if MYPY:
68+
from typing_extensions import Final
69+
6670

6771
T = TypeVar('T')
6872

69-
DEFAULT_LAST_PASS = 1 # Pass numbers start at 0
73+
DEFAULT_LAST_PASS = 1 # type: Final # Pass numbers start at 0
7074

7175

7276
# A node which is postponed to be processed during the next pass.

mypy/checkexpr.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
MYPY = False
1010
if MYPY:
1111
from typing import ClassVar
12+
from typing_extensions import Final
1213

1314
from mypy.errors import report_internal_error
1415
from mypy.typeanal import (
@@ -71,7 +72,7 @@
7172
# may cause performance issues. The reason is that although union math algorithm we use
7273
# nicely captures most corner cases, its worst case complexity is exponential,
7374
# see https://github.com/python/mypy/pull/5255#discussion_r196896335 for discussion.
74-
MAX_UNIONS = 5
75+
MAX_UNIONS = 5 # type: Final
7576

7677

7778
class TooManyUnions(Exception):

mypy/checkstrformat.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,13 @@
1010
from mypy.nodes import (
1111
StrExpr, BytesExpr, UnicodeExpr, TupleExpr, DictExpr, Context, Expression, StarExpr
1212
)
13-
if False:
13+
14+
MYPY = False
15+
if MYPY:
1416
# break import cycle only needed for mypy
1517
import mypy.checker
1618
import mypy.checkexpr
19+
from typing_extensions import Final
1720
from mypy import messages
1821
from mypy.messages import MessageBuilder
1922

@@ -32,7 +35,7 @@ def compile_format_re() -> Pattern[str]:
3235
return re.compile(format_re)
3336

3437

35-
FORMAT_RE = compile_format_re()
38+
FORMAT_RE = compile_format_re() # type: Final
3639

3740

3841
class ConversionSpecifier:

mypy/constraints.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,13 @@
1313
from mypy.sametypes import is_same_type
1414
from mypy.erasetype import erase_typevars
1515

16+
MYPY = False
17+
if MYPY:
18+
from typing_extensions import Final
1619

17-
SUBTYPE_OF = 0 # type: int
18-
SUPERTYPE_OF = 1 # type: int
20+
21+
SUBTYPE_OF = 0 # type: Final[int]
22+
SUPERTYPE_OF = 1 # type: Final[int]
1923

2024

2125
class Constraint:

mypy/defaults.py

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
1-
PYTHON2_VERSION = (2, 7)
2-
PYTHON3_VERSION = (3, 6)
3-
PYTHON3_VERSION_MIN = (3, 4)
4-
CACHE_DIR = '.mypy_cache'
5-
CONFIG_FILE = 'mypy.ini'
6-
SHARED_CONFIG_FILES = ('setup.cfg',)
7-
USER_CONFIG_FILES = ('~/.mypy.ini',)
8-
CONFIG_FILES = (CONFIG_FILE,) + SHARED_CONFIG_FILES + USER_CONFIG_FILES
1+
MYPY = False
2+
if MYPY:
3+
from typing_extensions import Final
4+
5+
PYTHON2_VERSION = (2, 7) # type: Final
6+
PYTHON3_VERSION = (3, 6) # type: Final
7+
PYTHON3_VERSION_MIN = (3, 4) # type: Final
8+
CACHE_DIR = '.mypy_cache' # type: Final
9+
CONFIG_FILE = 'mypy.ini' # type: Final
10+
SHARED_CONFIG_FILES = ('setup.cfg',) # type: Final
11+
USER_CONFIG_FILES = ('~/.mypy.ini',) # type: Final
12+
CONFIG_FILES = (CONFIG_FILE,) + SHARED_CONFIG_FILES + USER_CONFIG_FILES # type: Final

mypy/dmypy_server.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,12 @@
2828
from mypy.typestate import reset_global_state
2929
from mypy.version import __version__
3030

31+
MYPY = False
32+
if MYPY:
33+
from typing_extensions import Final
3134

32-
MEM_PROFILE = False # If True, dump memory profile after initialization
35+
36+
MEM_PROFILE = False # type: Final # If True, dump memory profile after initialization
3337

3438

3539
def daemonize(func: Callable[[], None], log_file: Optional[str] = None) -> int:
@@ -83,7 +87,7 @@ def daemonize(func: Callable[[], None], log_file: Optional[str] = None) -> int:
8387

8488
# Server code.
8589

86-
SOCKET_NAME = 'dmypy.sock'
90+
SOCKET_NAME = 'dmypy.sock' # type: Final
8791

8892

8993
def process_start_options(flags: List[str], allow_sources: bool) -> Options:
@@ -382,7 +386,7 @@ def cmd_hang(self) -> Dict[str, object]:
382386
# Misc utilities.
383387

384388

385-
MiB = 2**20
389+
MiB = 2**20 # type: Final
386390

387391

388392
def get_meminfo() -> Dict[str, Any]:

mypy/dmypy_util.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,11 @@
88

99
from typing import Any
1010

11-
STATUS_FILE = '.dmypy.json'
11+
MYPY = False
12+
if MYPY:
13+
from typing_extensions import Final
14+
15+
STATUS_FILE = '.dmypy.json' # type: Final
1216

1317

1418
def receive(sock: socket.socket) -> Any:

mypy/fastparse.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
MYPY = False
88
if MYPY:
99
import typing # for typing.Type, which conflicts with types.Type
10-
from typing import ClassVar
10+
from typing_extensions import Final
1111

1212
from mypy.sharedparse import (
1313
special_function_elide_names, argument_elide_name,
@@ -65,11 +65,11 @@
6565

6666
# There is no way to create reasonable fallbacks at this stage,
6767
# they must be patched later.
68-
MISSING_FALLBACK = FakeInfo("fallback can't be filled out until semanal")
69-
_dummy_fallback = Instance(MISSING_FALLBACK, [], -1)
68+
MISSING_FALLBACK = FakeInfo("fallback can't be filled out until semanal") # type: Final
69+
_dummy_fallback = Instance(MISSING_FALLBACK, [], -1) # type: Final
7070

71-
TYPE_COMMENT_SYNTAX_ERROR = 'syntax error in type comment'
72-
TYPE_COMMENT_AST_ERROR = 'invalid type comment or annotation'
71+
TYPE_COMMENT_SYNTAX_ERROR = 'syntax error in type comment' # type: Final
72+
TYPE_COMMENT_AST_ERROR = 'invalid type comment or annotation' # type: Final
7373

7474

7575
# Older versions of typing don't allow using overload outside stubs,
@@ -223,7 +223,7 @@ def translate_stmt_list(self, l: Sequence[ast3.AST]) -> List[Statement]:
223223
ast3.BitXor: '^',
224224
ast3.BitAnd: '&',
225225
ast3.FloorDiv: '//'
226-
} # type: ClassVar[Dict[typing.Type[ast3.AST], str]]
226+
} # type: Final[Dict[typing.Type[ast3.AST], str]]
227227

228228
def from_operator(self, op: ast3.operator) -> str:
229229
op_name = ASTConverter.op_map.get(type(op))
@@ -243,7 +243,7 @@ def from_operator(self, op: ast3.operator) -> str:
243243
ast3.IsNot: 'is not',
244244
ast3.In: 'in',
245245
ast3.NotIn: 'not in'
246-
} # type: ClassVar[Dict[typing.Type[ast3.AST], str]]
246+
} # type: Final[Dict[typing.Type[ast3.AST], str]]
247247

248248
def from_comp_operator(self, op: ast3.cmpop) -> str:
249249
op_name = ASTConverter.comp_op_map.get(type(op))

0 commit comments

Comments
 (0)