diff --git a/mypy/build.py b/mypy/build.py index d52b54e3c024d..ab25c6a0ad232 100644 --- a/mypy/build.py +++ b/mypy/build.py @@ -787,12 +787,25 @@ class ModuleType: class ImportContext: + """ + Describes module import context + + Do we already discovered implementation? + What kind of module we discovered? + """ def __init__(self) -> None: self.has_py = False # type: bool self.type = None # type: Optional[int] + # Paths can contain only one ".py" path, but multiple stubs self.paths = [] # type: List[str] def maybe_add_path(self, path: str, type: int) -> None: + """ + Add path to import context. + Modifies self.paths in case if arguments satisfy import context state + """ + assert path.endswith(('/',) + tuple(PYTHON_EXTENSIONS)) + if self.type is not None and self.type != type: return None @@ -817,6 +830,8 @@ def maybe_add_path(self, path: str, type: int) -> None: self.paths.append(path) def _verify_module(self, path: str) -> bool: + # At this point we already know that that it's valid python path + # We only need to check file existence if not is_file(path): return False @@ -860,6 +875,10 @@ def find_module(self, id: str) -> Optional[str]: return None def find_modules_recursive(self, module: str) -> List[BuildSource]: + """ + Discover module and all it's children + Remove duplicates from discovered paths + """ hits = set() # type: Set[str] result = [] # type: List[BuildSource] for src in self._find_modules_recursive(module): @@ -903,6 +922,9 @@ def _collect_paths(self, paths: List[str], last_comp: str) -> List[str]: sepinit = '__init__' ctx = ImportContext() + # Detect modules in following order: package, module, namespace. + # First hit determines module type, consistency of paths to given type + # ensured in ImportContext for path_item in paths: if is_module_path(path_item): continue