def _analyse(self, path: str, log: bool = True): """ Load a Python file and analyses its syntax :param path: the path of the Python file to compile :param log: if compiler errors should be logged. """ self._analyser = Analyser.analyse(path, log)
def _analyse(self, path: str, root_folder: str = None, log: bool = True): """ Load a Python file and analyses its syntax :param path: the path of the Python file to compile :param root_folder: the root path of the project :param log: if compiler errors should be logged. """ self._analyser = Analyser.analyse(path, log=log, root=root_folder)
def __init__(self, import_target: str): self.can_be_imported: bool = False self._import_identifier: str = import_target try: module_origin: str = importlib.util.find_spec(import_target).origin except BaseException: return path: List[str] = module_origin.split(os.sep) self.path: str = module_origin.replace(os.sep, '/') super().__init__(ast.Module(body=[]), path[-1]) if import_target == 'typing': self.symbols.update( {symbol_id: symbol for symbol_id, symbol in self._get_types_from_typing_lib().items() if symbol_id not in Type.builtin_types() }) self.can_be_imported = True else: import re inside_python_folder = any(re.search(r'python(\d\.?)*', folder.lower()) for folder in path) updated_tree = None if 'boa3' in path and '/'.join(path[path.index('boa3'):]).startswith('boa3/builtin'): pkg_start_index = path.index('builtin') + 1 if path[pkg_start_index] == path[-1]: self.symbols = self._get_boa3_builtin_symbols() else: pkg = import_target.split('.') pkg = pkg[pkg.index('builtin') + 1:] self.symbols = self._get_boa3_builtin_package(pkg) self.can_be_imported = True elif not (inside_python_folder and 'lib' in path): # TODO: only user modules and typing lib imports are implemented try: from boa3.analyser.analyser import Analyser analyser = Analyser.analyse(module_origin) # include only imported symbols if analyser.is_analysed: self.symbols.update( {symbol_id: symbol for symbol_id, symbol in analyser.symbol_table.items() if symbol_id not in Type.all_types() }) updated_tree = analyser.ast_tree self.can_be_imported = analyser.is_analysed except FileNotFoundError: self.can_be_imported = False if updated_tree is not None: self._tree = updated_tree
def _find_package(self, module_origin: str, origin_file: Optional[str] = None): path: List[str] = module_origin.split(os.sep) package = imports.builtin.get_package(self._import_identifier) if hasattr(package, 'symbols'): if hasattr(package, 'inner_packages'): # when have symbol and packages with the same id, prioritize symbol self.symbols: Dict[str, ISymbol] = package.inner_packages self.symbols.update(package.symbols) else: self.symbols = package.symbols self.can_be_imported = True self.is_builtin_import = True return if (os.path.commonpath([self.path, constants.BOA_PACKAGE_PATH ]) != constants.BOA_PACKAGE_PATH or ('boa3' in path and constants.PATH_SEPARATOR.join( path[path.index('boa3'):]).startswith('boa3/builtin'))): # doesn't analyse boa3.builtin packages that aren't included in the imports.builtin as an user module # TODO: refactor when importing from user modules is accepted import re inside_python_folder = any( re.search(r'python(\d\.?)*', folder.lower()) for folder in path) updated_tree = None if not (inside_python_folder and 'lib' in path): # check circular imports to avoid recursions inside the compiler if self.path in self._import_stack: self.recursive_import = True return # TODO: only user modules and typing lib imports are implemented try: if self.path in self._imported_files: analyser = self._imported_files[self.path] else: from boa3.analyser.analyser import Analyser origin = origin_file.replace(os.sep, constants.PATH_SEPARATOR) files = self._import_stack files.append(origin) if self.is_namespace_package: analyser = Analyser(self.tree, module_origin, self.root_folder, self._log) if self._include_inner_packages(analyser): analyser.is_analysed = True self._imported_files[self.path] = analyser else: analyser = Analyser.analyse( module_origin, root=self.root_folder, imported_files=self._imported_files, import_stack=files, log=self._log) self._include_inner_packages(analyser) if analyser.is_analysed: self._imported_files[self.path] = analyser # include only imported symbols if analyser.is_analysed: for symbol_id, symbol in analyser.symbol_table.items(): if symbol_id not in Type.all_types(): if not self._get_from_entry: symbol.defined_by_entry = False self.symbols[symbol_id] = symbol self.errors.extend(analyser.errors) self.warnings.extend(analyser.warnings) updated_tree = analyser.ast_tree self.analyser = analyser self.can_be_imported = analyser.is_analysed except FileNotFoundError: self.can_be_imported = False if updated_tree is not None: self._tree = updated_tree