Source code for impscan.scanner.import_utils

# type: ignore
import ast
from ast import Import as IType
from ast import ImportFrom as IFType
from pathlib import Path

from .module_utils import stdlib_module_names

__all__ = ["get_imported_name_sources", "get_sibling_module_names"]


[docs]def get_imported_name_sources(trunk: list) -> set: import_types = [IType, IFType] stdlib_modules = stdlib_module_names() imports = set() for node in trunk: if type(node) not in import_types: continue if isinstance(node, IType): # import statement has one or more module source(s), typically one # Store module names without further examination imports.update(a.name for a in node.names) else: # import from does not have levels, but may be implicitly relative if node.level > 0: continue # ignore relative imports # 'import from' statement will only be a single module name imports.add(node.module) imports = {i.split(".")[0] if "." in i else i for i in imports} potential_nonstdlib_imports = imports.difference(stdlib_modules) return potential_nonstdlib_imports
[docs]def get_sibling_module_names(target_module_path: Path) -> set: """ Given a source module at `target_module_path`, determine the names of any modules it may import in the local directory: either those files ending in `.py` or directories (which do not need to contain an `__init__.py` due to implicit namespaces). """ names = { f.stem for f in target_module_path.parent.iterdir() if f.name != target_module_path.name if f.is_dir() or f.suffix == ".py" } return names