Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Namespaces refactor part 2 #5690

Merged
merged 8 commits into from
Sep 29, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 2 additions & 7 deletions mypy/build.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,6 @@ def is_source(self, file: MypyFile) -> bool:
def build(sources: List[BuildSource],
options: Options,
alt_lib_path: Optional[str] = None,
bin_dir: Optional[str] = None,
flush_errors: Optional[Callable[[List[str], bool], None]] = None,
fscache: Optional[FileSystemCache] = None,
) -> BuildResult:
Expand All @@ -144,8 +143,6 @@ def build(sources: List[BuildSource],
options: build options
alt_lib_path: an additional directory for looking up library modules
(takes precedence over other directories)
bin_dir: directory containing the mypy script, used for finding data
directories; if omitted, use '.' as the data directory
flush_errors: optional function to flush errors after a file is processed
fscache: optionally a file-system cacher

Expand All @@ -160,8 +157,7 @@ def default_flush_errors(new_messages: List[str], is_serious: bool) -> None:
flush_errors = flush_errors or default_flush_errors

try:
result = _build(sources, options, alt_lib_path, bin_dir,
flush_errors, fscache)
result = _build(sources, options, alt_lib_path, flush_errors, fscache)
result.errors = messages
return result
except CompileError as e:
Expand All @@ -178,7 +174,6 @@ def default_flush_errors(new_messages: List[str], is_serious: bool) -> None:
def _build(sources: List[BuildSource],
options: Options,
alt_lib_path: Optional[str],
bin_dir: Optional[str],
flush_errors: Callable[[List[str], bool], None],
fscache: Optional[FileSystemCache],
) -> BuildResult:
Expand Down Expand Up @@ -424,7 +419,7 @@ class BuildManager(BuildManagerBase):

Attributes:
data_dir: Mypy data directory (contains stubs)
lib_path: Library path for looking up modules
search_paths: SearchPaths instance indicating where to look for modules
modules: Mapping of module ID to MypyFile (shared by the passes)
semantic_analyzer:
Semantic analyzer, pass 2
Expand Down
20 changes: 11 additions & 9 deletions mypy/dmypy_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
from mypy.dmypy_util import STATUS_FILE, receive
from mypy.fscache import FileSystemCache
from mypy.fswatcher import FileSystemWatcher, FileData
from mypy.modulefinder import BuildSource, compute_search_paths
from mypy.options import Options
from mypy.typestate import reset_global_state
from mypy.version import __version__
Expand Down Expand Up @@ -231,7 +232,7 @@ def cmd_stop(self) -> Dict[str, object]:
"""Stop daemon."""
return {}

last_sources = None # type: List[mypy.build.BuildSource]
last_sources = None # type: List[BuildSource]

def cmd_run(self, version: str, args: Sequence[str]) -> Dict[str, object]:
"""Check a list of files, triggering a restart if needed."""
Expand Down Expand Up @@ -264,7 +265,7 @@ def cmd_recheck(self) -> Dict[str, object]:
return {'error': "Command 'recheck' is only valid after a 'check' command"}
return self.check(self.last_sources)

def check(self, sources: List[mypy.build.BuildSource]) -> Dict[str, Any]:
def check(self, sources: List[BuildSource]) -> Dict[str, Any]:
"""Check using fine-grained incremental mode."""
if not self.fine_grained_manager:
res = self.initialize_fine_grained(sources)
Expand All @@ -273,7 +274,7 @@ def check(self, sources: List[mypy.build.BuildSource]) -> Dict[str, Any]:
self.fscache.flush()
return res

def initialize_fine_grained(self, sources: List[mypy.build.BuildSource]) -> Dict[str, Any]:
def initialize_fine_grained(self, sources: List[BuildSource]) -> Dict[str, Any]:
self.fswatcher = FileSystemWatcher(self.fscache)
self.update_sources(sources)
try:
Expand Down Expand Up @@ -326,15 +327,16 @@ def initialize_fine_grained(self, sources: List[mypy.build.BuildSource]) -> Dict
status = 1 if messages else 0
return {'out': ''.join(s + '\n' for s in messages), 'err': '', 'status': status}

def fine_grained_increment(self, sources: List[mypy.build.BuildSource]) -> Dict[str, Any]:
def fine_grained_increment(self, sources: List[BuildSource]) -> Dict[str, Any]:
assert self.fine_grained_manager is not None
manager = self.fine_grained_manager.manager

t0 = time.time()
self.update_sources(sources)
changed, removed = self.find_changed(sources)
manager.search_paths = mypy.build.compute_search_paths(
sources, manager.options, manager.data_dir, mypy.build.FileSystemCache())
# TODO: Why create a new FileSystemCache rather than using self.fscache?
manager.search_paths = compute_search_paths(
sources, manager.options, manager.data_dir, FileSystemCache())
t1 = time.time()
messages = self.fine_grained_manager.update(changed, removed)
t2 = time.time()
Expand All @@ -345,12 +347,12 @@ def fine_grained_increment(self, sources: List[mypy.build.BuildSource]) -> Dict[
self.previous_sources = sources
return {'out': ''.join(s + '\n' for s in messages), 'err': '', 'status': status}

def update_sources(self, sources: List[mypy.build.BuildSource]) -> None:
def update_sources(self, sources: List[BuildSource]) -> None:
paths = [source.path for source in sources if source.path is not None]
self.fswatcher.add_watched_paths(paths)

def find_changed(self, sources: List[mypy.build.BuildSource]) -> Tuple[List[Tuple[str, str]],
List[Tuple[str, str]]]:
def find_changed(self, sources: List[BuildSource]) -> Tuple[List[Tuple[str, str]],
List[Tuple[str, str]]]:
changed_paths = self.fswatcher.find_changed()
# Find anything that has been added or modified
changed = [(source.module, source.path)
Expand Down
34 changes: 3 additions & 31 deletions mypy/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,10 +65,6 @@ def main(script_path: Optional[str], args: Optional[List[str]] = None) -> None:

t0 = time.time()
# To log stat() calls: os.stat = stat_proxy
if script_path:
bin_dir = find_bin_directory(script_path) # type: Optional[str]
else:
bin_dir = None
sys.setrecursionlimit(2 ** 14)
if args is None:
args = sys.argv[1:]
Expand All @@ -90,10 +86,11 @@ def flush_errors(new_messages: List[str], serious: bool) -> None:

serious = False
blockers = False
res = None
try:
# Keep a dummy reference (res) for memory profiling below, as otherwise
# the result could be freed.
res = type_check_only(sources, bin_dir, options, flush_errors, fscache) # noqa
res = build.build(sources, options, None, flush_errors, fscache)
except CompileError as e:
blockers = True
if not e.use_stdout:
Expand All @@ -111,6 +108,7 @@ def flush_errors(new_messages: List[str], serious: bool) -> None:
if MEM_PROFILE:
from mypy.memprofile import print_memory_profile
print_memory_profile()
del res # Now it's safe to delete

code = 0
if messages:
Expand All @@ -124,20 +122,6 @@ def flush_errors(new_messages: List[str], serious: bool) -> None:
sys.exit(code)


def find_bin_directory(script_path: str) -> str:
"""Find the directory that contains this script.

This is used by build to find stubs and other data files.
"""
# Follow up to 5 symbolic links (cap to avoid cycles).
for i in range(5):
if os.path.islink(script_path):
script_path = readlinkabs(script_path)
else:
break
return os.path.dirname(script_path)


def readlinkabs(link: str) -> str:
"""Return an absolute path to symbolic link destination."""
# Adapted from code by Greg Smith.
Expand All @@ -148,18 +132,6 @@ def readlinkabs(link: str) -> str:
return os.path.join(os.path.dirname(link), path)


def type_check_only(sources: List[BuildSource], bin_dir: Optional[str],
options: Options,
flush_errors: Optional[Callable[[List[str], bool], None]],
fscache: FileSystemCache) -> BuildResult:
# Type-check the program and dependencies.
return build.build(sources=sources,
bin_dir=bin_dir,
options=options,
flush_errors=flush_errors,
fscache=fscache)


class SplitNamespace(argparse.Namespace):
def __init__(self, standard_namespace: object, alt_namespace: object, alt_prefix: str) -> None:
self.__dict__['_standard_namespace'] = standard_namespace
Expand Down
8 changes: 4 additions & 4 deletions mypy/modulefinder.py
Original file line number Diff line number Diff line change
Expand Up @@ -320,10 +320,10 @@ def make_abspath(path: str, root: str) -> str:


def compute_search_paths(sources: List[BuildSource],
options: Options,
data_dir: str,
fscache: FileSystemCache,
alt_lib_path: Optional[str] = None) -> SearchPaths:
options: Options,
data_dir: str,
fscache: FileSystemCache,
alt_lib_path: Optional[str] = None) -> SearchPaths:
"""Compute the search paths as specified in PEP 561.

There are the following 4 members created:
Expand Down
3 changes: 2 additions & 1 deletion mypy/server/update.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,9 +119,10 @@
)

from mypy.build import (
BuildManager, State, BuildSource, BuildResult, Graph, load_graph,
BuildManager, State, BuildResult, Graph, load_graph,
process_fresh_modules, DEBUG_FINE_GRAINED,
)
from mypy.modulefinder import BuildSource
from mypy.checker import FineGrainedDeferredNode
from mypy.errors import CompileError
from mypy.nodes import (
Expand Down
20 changes: 11 additions & 9 deletions mypy/test/testcheck.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

from mypy import build
from mypy.build import Graph
from mypy.modulefinder import BuildSource, SearchPaths
from mypy.modulefinder import BuildSource, SearchPaths, FindModuleCache
from mypy.test.config import test_temp_dir, test_data_prefix
from mypy.test.data import DataDrivenTestCase, DataSuite, FileOperation, UpdateFile
from mypy.test.helpers import (
Expand Down Expand Up @@ -271,13 +271,14 @@ def parse_module(self,
Return a list of tuples (module name, file name, program text).
"""
m = re.search('# cmd: mypy -m ([a-zA-Z0-9_. ]+)$', program_text, flags=re.MULTILINE)
regex = '# cmd{}: mypy -m ([a-zA-Z0-9_. ]+)$'.format(incremental_step)
alt_m = re.search(regex, program_text, flags=re.MULTILINE)
if alt_m is not None and incremental_step > 1:
# Optionally return a different command if in a later step
# of incremental mode, otherwise default to reusing the
# original cmd.
m = alt_m
if incremental_step > 1:
alt_regex = '# cmd{}: mypy -m ([a-zA-Z0-9_. ]+)$'.format(incremental_step)
alt_m = re.search(alt_regex, program_text, flags=re.MULTILINE)
if alt_m is not None:
# Optionally return a different command if in a later step
# of incremental mode, otherwise default to reusing the
# original cmd.
m = alt_m

if m:
# The test case wants to use a non-default main
Expand All @@ -286,8 +287,9 @@ def parse_module(self,
module_names = m.group(1)
out = []
search_paths = SearchPaths((test_temp_dir,), (), (), ())
cache = FindModuleCache(search_paths)
for module_name in module_names.split(' '):
path = build.FindModuleCache(search_paths).find_module(module_name)
path = cache.find_module(module_name)
assert path is not None, "Can't find ad hoc case file"
with open(path) as f:
program_text = f.read()
Expand Down