def __init__(self, name, module=None, level=0, module_dir=None): """Parameters are the name for the module (mandatory), and the ast.Module node (optional) in the case the current module is the main one. This differentiation is needed to avoid mangling function name for functions defined in the main module. """ self.is_main_module = True self.node = module self.module_dir = module_dir if self.node is None: from pythran.frontend import raw_parse # Not main module, parse now the imported module self.is_main_module = False self.node = raw_parse(self.getsource(name, module_dir, level)) assert isinstance(self.node, ast.Module) # Recursively add filename information to all nodes, for debug msg add_filename_field(self.node, name + ".py") # Mangle function imported, unless it is the main module self.to_be_mangled = not self.is_main_module self.name = name # Functions defined in this module and imported by another one. # This dict is used at the end of the process to gather functions to be # prepend at the beginning of the main pythran module self.exported_functions = dict() self.dependent_modules = dict() # Top-level function declared in this module self.functions = dict() # Functions imported as "from somemodule import func as func_alias" self.imported_functions = dict() # Regular module import. Keys are alias and values are module names self.imported_modules = dict() # Collect top-level functions and imports for decl in self.node.body: if isinstance(decl, ast.FunctionDef): # regular functions self.functions[decl.name] = decl elif isinstance(decl, ast.Import): # Module import for alias in decl.names: asname = alias.asname or alias.name self.imported_modules[asname] = alias.name elif isinstance(decl, ast.ImportFrom): # Function import module_name = decl.module module_level = decl.level for alias in decl.names: func_name = alias.name asname = alias.asname or func_name self.imported_functions[asname] = (module_level, module_name, func_name, None) elif isinstance(decl, ast.Assign): # FIXME : We ignore import of globals pass elif isinstance(decl, ast.Expr): # FIXME : We ignore expr ?? pass else: raise PythranSyntaxError('Unsupported top-level statement', decl)
def getsource(name, module_dir, level): # Try to load py file module_base = name.replace('.', os.path.sep) + '.py' if module_dir is None: assert level <= 0, "Cannot use relative path without module_dir" module_file = module_base else: module_file = os.path.sep.join( ([module_dir] + ['..'] * (level - 1) + [module_base])) try: with open(module_file, 'r') as fp: from pythran.frontend import raw_parse node = raw_parse(fp.read()) add_filename_field(node, name + ".py") return node except IOError: raise PythranSyntaxError("Module '{}' not found.".format(name))
def getsource(name, module_dir, level): # Try to load py file module_base = name.replace('.', os.path.sep) + '.py' if module_dir is None: assert level <= 0, "Cannot use relative path without module_dir" module_file = module_base else: module_file = os.path.sep.join(([module_dir] + ['..'] * (level - 1) + [module_base])) try: with open(module_file, 'r') as fp: from pythran.frontend import raw_parse node = raw_parse(fp.read()) add_filename_field(node, name + ".py") return node except IOError: raise PythranSyntaxError("Module '{}' not found." .format(name))