8000 Turn mypyc on for ~all substantial code (#6851) · python/mypy@10ad1af · GitHub
[go: up one dir, main page]

Skip to content
8000

Commit 10ad1af

Browse files
authored
Turn mypyc on for ~all substantial code (#6851)
With *args support landed (and a few other recent improvements), we can now turn mypyc on for basically everything. This includes: * `BuildManagerBase` goes away and gets merged back into `BuildManager`. `mypyc_hacks.py` is removed * `main.py` can be compiled. (`SplitNamespace` needs to be pulled out because it uses `__getattr__/__setattr__` in ways we don't support yet) * dmypy can be compiled. Unfortunately extension modules can't be run as scripts, so we move `dmypy.py` to `dmypy/client.py` and add an interpreted `dmypy/__main__.py` * A few other minor modules get added in
1 parent 6fb41f7 commit 10ad1af

File tree

10 files changed

+102
-100
lines changed

10 files changed

+102
-100
lines changed

mypy/api.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@
4545
import sys
4646
from io import StringIO
4747
from typing import List, Tuple, Union, TextIO, Callable
48-
from mypy_extensions import DefaultArg
4948

5049

5150
def _run(main_wrapper: Callable[[TextIO, TextIO], None]) -> Tuple[str, str, int]:
@@ -70,5 +69,5 @@ def run(args: List[str]) -> Tuple[str, str, int]:
7069

7170

7271
def run_dmypy(args: List[str]) -> Tuple[str, str, int]:
73-
from mypy.dmypy import main
72+
from mypy.dmypy.client import main
7473
return _run(lambda stdout, stderr: main(args))

mypy/build.py

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -62,8 +62,6 @@
6262
from mypy.typestate import TypeState, reset_global_state
6363
from mypy.renaming import VariableRenameVisitor
6464

65-
from mypy.mypyc_hacks import BuildManagerBase
66-
6765

6866
# Switch to True to produce debug output related to fine-grained incremental
6967
# mode only that is useful during development. This produces only a subset of
@@ -455,7 +453,7 @@ def find_config_file_line_number(path: str, section: str, setting_name: str) ->
455453
return -1
456454

457455

458-
class BuildManager(BuildManagerBase):
456+
class BuildManager:
459457
"""This class holds shared state for building a mypy program.
460458
461459
It is used to coordinate parsing, import processing, semantic
@@ -512,7 +510,9 @@ def __init__(self, data_dir: str,
512510
stdout: TextIO,
513511
stderr: TextIO,
514512
) -> None:
515-
super().__init__(stdout, stderr)
513+
self.stats = {} # type: Dict[str, Any] # Values are ints or floats
514+
self.stdout = stdout
515+
self.stderr = stderr
516516
self.start_time = time.time()
517517
self.data_dir = data_dir
518518
self.errors = errors
@@ -748,6 +748,41 @@ def report_file(self,
748748
if self.reports is not None and self.source_set.is_source(file):
749749
self.reports.file(file, type_map, options)
750750

751+
def verbosity(self) -> int:
752+
return self.options.verbosity
753+
754+
def log(self, *message: str) -> None:
755+
if self.verbosity() >= 1:
756+
if message:
757+
print('LOG: ', *message, file=self.stderr)
758+
else:
759+
print(file=self.stderr)
760+
self.stderr.flush()
761+
762+
def log_fine_grained(self, *message: str) -> None:
763+
import mypy.build
764+
if self.verbosity() >= 1:
765+
self.log('fine-grained:', *message)
766+
elif mypy.build.DEBUG_FINE_GRAINED:
767+
# Output log in a simplified format that is quick to browse.
768+
if message:
769+
print(*message, file=self.stderr)
770+
else:
771+
print(file=self.stderr)
772+
self.stderr.flush()
773+
9E88
774+
def trace(self, *message: str) -> None:
775+
if self.verbosity() >= 2:
776+
print('TRACE:', *message, file=self.stderr)
777+
self.stderr.flush()
778+
779+
def add_stats(self, **kwds: Any) -> None:
780+
for key, value in kwds.items():
781+
if key in self.stats:
782+
self.stats[key] += value
783+
else:
784+
self.stats[key] = value
785+
751786
def stats_summary(self) -> Mapping[str, object]:
752787
return self.stats
753788

mypy/dmypy/__init__.py

Whitespace-only changes.

mypy/dmypy/__main__.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
from mypy.dmypy.client import console_entry
2+
3+
if __name__ == '__main__':
4+
console_entry()

mypy/dmypy.py renamed to mypy/dmypy/client.py

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@ def __init__(self, prog: str) -> None:
3131
super().__init__(prog=prog, max_help_position=30)
3232

3333

34-
parser = argparse.ArgumentParser(description="Client for mypy daemon mode",
34+
parser = argparse.ArgumentParser(prog='dmypy',
35+
description="Client for mypy daemon mode",
3536
fromfile_prefix_chars='@')
3637
parser.set_defaults(action=None)
3738
parser.add_argument('--status-file', default=DEFAULT_STATUS_FILE,
@@ -460,7 +461,7 @@ def request(status_file: str, command: str, *, timeout: Optional[int] = None,
460461
"""
461462
response = {} # type: Dict[str, str]
462463
args = dict(kwds)
463-
args.update(command=command)
464+
args['command'] = command
464465
bdata = json.dumps(args).encode('utf8')
465466
_, name = get_status(status_file)
466467
try:
@@ -537,7 +538,3 @@ def is_running(status_file: str) -> bool:
537538
# Run main().
538539
def console_entry() -> None:
539540
main(sys.argv[1:])
540-
541-
542-
if __name__ == '__main__':
543-
console_entry()

mypy/dmypy_server.py

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -519,15 +519,11 @@ def _find_changed(self, sources: List[BuildSource],
519519
def cmd_suggest(self,
520520
function: str,
521521
callsites: bool,
522-
# We'd like to just use **kwargs here and save some duplication but
523-
# mypyc doesn't support it yet...
524-
json: bool,
525-
no_errors: bool,
526-
no_any: bool) -> Dict[str, object]:
522+
**kwargs: bool) -> Dict[str, object]:
527523
"""Suggest a signature for a function."""
528524
if not self.fine_grained_manager:
529525
return {'error': "Command 'suggest' is only valid after a 'check' command"}
530-
engine = SuggestionEngine(self.fine_grained_manager, json, no_errors, no_any)
526+
engine = SuggestionEngine(self.fine_grained_manager, **kwargs)
531527
try:
532528
if callsites:
533529
out = engine.suggest_callsites(function)

mypy/main.py

Lines changed: 6 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
from mypy.errors import CompileError
2424
from mypy.options import Options, BuildType, PER_MODULE_OPTIONS
2525
from mypy.config_parser import parse_version, parse_config_file
26+
from mypy.split_namespace import SplitNamespace
2627

2728
from mypy.version import __version__
2829

@@ -123,28 +124,6 @@ def flush_errors(new_messages: List[str], serious: bool) -> None:
123124
sys.exit(code)
124125

125126

126-
class SplitNamespace(argparse.Namespace):
127-
def __init__(self, standard_namespace: object, alt_namespace: object, alt_prefix: str) -> None:
128-
self.__dict__['_standard_namespace'] = standard_namespace
129-
self.__dict__['_alt_namespace'] = alt_namespace
130-
self.__dict__['_alt_prefix'] = alt_prefix
131-
132-
def _get(self) -> Tuple[Any, Any]:
133-
return (self._standard_namespace, self._alt_namespace)
134-
135-
def __setattr__(self, name: str, value: Any) -> None:
136-
if name.startswith(self._alt_prefix):
137-
setattr(self._alt_namespace, name[len(self._alt_prefix):], value)
138-
else:
139-
setattr(self._standard_namespace, name, value)
140-
141-
def __getattr__(self, name: str) -> Any:
142-
if name.startswith(self._alt_prefix):
143-
return getattr(self._alt_namespace, name[len(self._alt_prefix):])
144-
else:
145-
return getattr(self._standard_namespace, name)
146-
147-
148127
# Make the help output a little less jarring.
149128
class AugmentedHelpFormatter(argparse.RawDescriptionHelpFormatter):
150129
def __init__(self, prog: str) -> None:
@@ -799,8 +778,11 @@ def add_invertible_flag(flag: str,
799778
else:
800779
try:
801780
targets = create_source_list(special_opts.files, options, fscache)
802-
except InvalidSourceList as e:
803-
fail(str(e), stderr)
781+
# Variable named e2 instead of e to work around mypyc bug #620
782+
# which causes issues when using the same variable to catch
783+
# exceptions of different types.
784+
except InvalidSourceList as e2:
785+
fail(str(e2), stderr)
804786
return targets, options
805787

806788

mypy/mypyc_hacks.py

Lines changed: 0 additions & 47 deletions
This file was deleted.

mypy/split_namespace.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
"""Split namespace for argparse to allow separating options by prefix.
2+
3+
We use this to direct some options to an Options object and some to a
4+
regular namespace.
5+
"""
6+
7+
# In its own file largely because mypyc doesn't support its use of
8+
# __getattr__/__setattr__ and has some issues with __dict__
9+
10+
import argparse
11+
12+
from typing import Tuple, Any
13+
14+
15+
class SplitNamespace(argparse.Namespace):
16+
def __init__(self, standard_namespace: object, alt_namespace: object, alt_prefix: str) -> None:
17+
self.__dict__['_standard_namespace'] = standard_namespace
18+
self.__dict__['_alt_namespace'] = alt_namespace
19+
self.__dict__['_alt_prefix'] = alt_prefix
20+
21+
def _get(self) -> Tuple[Any, Any]:
22+
return (self._standard_namespace, self._alt_namespace)
23+
24+
def __setattr__(self, name: str, value: Any) -> None:
25+
if name.startswith(self._alt_prefix):
26+
setattr(self._alt_namespace, name[len(self._alt_prefix):], value)
27+
else:
28+
setattr(self._standard_namespace, name, value)
29+
30+
def __getattr__(self, name: str) -> Any:
31+
if name.startswith(self._alt_prefix):
32+
return getattr(self._alt_namespace, name[len(self._alt_prefix):])
33+
else:
34+
return getattr(self._standard_namespace, name)

setup.py

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -86,20 +86,22 @@ def run(self):
8686

8787
if USE_MYPYC:
8888
MYPYC_BLACKLIST = (
89-
# Designed to collect things that can't be compiled
90-
'mypyc_hacks.py',
91-
'interpreted_plugin.py',
92-
93-
# Can't be compiled because they need to be runnable as scripts
89+
# Need to be runnable as scripts
9490
'__main__.py',
9591
'sitepkgs.py',
92+
'dmypy/__main__.py',
93+
94+
# Needs to be interpreted to provide a hook to interpreted plugins
95+
'interpreted_plugin.py',
96+
97< BF93 span class="diff-text-marker">+
# Uses __getattr__/__setattr__
98+
'split_namespace.py',
9699

97-
# Can't be compiled because something goes wrong
100+
# Lies to mypy about code reachability
98101
'bogus_type.py',
99-
'dmypy.py',
100-
'gclogger.py',
101-
'main.py',
102-
'memprofile.py',
102+
103+
# We don't populate __file__ properly at the top level or something?
104+
# Also I think there would be problems with how we generate version.py.
103105
'version.py',
104106
)
105107

@@ -169,7 +171,7 @@ def run(self):
169171
package_data={'mypy': package_data},
170172
entry_points={'console_scripts': ['mypy=mypy.__main__:console_entry',
171173
'stubgen=mypy.stubgen:main',
172-
'dmypy=mypy.dmypy:console_entry',
174+
'dmypy=mypy.dmypy.client:console_entry',
173175
]},
174176
classifiers=classifiers,
175177
cmdclass=cmdclass,

0 commit comments

Comments
 (0)
0