def process_import(self, node): """Common code for Import and ImportFrom.""" for alias, (loc, (op, symbol, data)) in zip(node.names, self.match(node)): # If an import is aliased, match() returns only the symbol/loc of # the alias, whereas the indexer also needs access to the unaliased # name in order to reference the imported module. defn = None # type: Optional[Definition] if alias.asname: defn = self.add_local_def( node, name=symbol, target=alias.name, data=data) defloc = self.locs[defn.id].pop() self.locs[defn.id].append(DefLocation(defloc.def_id, loc)) # Shift symbol/loc back to the unaliased name. symbol = alias.name m = re.search("[ ,]" + symbol + r"\b", self.source.line(loc.line)) assert m is not None c, _ = m.span() loc = source.Location(loc.line, c + 1) try: [imported] = _unwrap(data) except ValueError: continue # Unresolved import. if op == "STORE_NAME": # for |import x.y as z| or |from x import y as z| we want {z: x.y} self.add_local_ref(node, name=symbol, data=data, location=loc) if not isinstance(imported, abstract.Module): # Make the from-imported symbol available in the current namespace. remote = Remote(imported.module, name=symbol, resolved=True) if defn: self.aliases[defn.id] = remote self.current_env[symbol] = remote self.typemap[remote.id] = [imported] continue if defn: remote = Remote(imported.full_name, IMPORT_FILE_MARKER, resolved=True) self.aliases[defn.id] = remote self.modules[defn.id] = imported.full_name else: self.modules[self.scope_id() + "." + symbol] = imported.full_name elif op == "IMPORT_NAME": # |import x.y| puts both {x: x} and {x.y: x.y} in modules self.add_local_ref(node, name=symbol, data=data, location=loc) # TODO(slebedev): Reference every import path component. # For example here # # from foo.bar import boo # import foo.bar.boo # # we should reference both foo and foo.bar (in addition to foo.bar.boo). for mod in module_utils.get_all_prefixes(symbol): self.modules[self.scope_id() + "." + mod] = mod
def process_import(self, node, is_from): """Common code for Import and ImportFrom.""" store_ops = get_opcodes(self.traces, node.lineno, "STORE_NAME") import_ops = get_opcodes(self.traces, node.lineno, "IMPORT_NAME") # Only record modules that pytype has resolved in self.modules def is_resolved(defn, symbol, data): return (symbol == defn.name and data and isinstance(data[0], abstract.Module)) def filter_ops(op_list, defn): return [(symbol, data) for _, symbol, data in op_list if is_resolved(defn, symbol, data)] def add_import_ref(name, data, loc): self.add_global_ref(node, name=name, data=data, location=loc, typ="Import") for alias in node.names: name = alias.asname if alias.asname else alias.name # defn, defloc = self.make_def(node, **kwargs) d = self.add_local_def(node, name=name) defloc = self.locs[d.id][-1] loc = defloc.location # tweak the definition location slightly line, _ = loc text = self.source.line(line) c = text.find("import ") if c > -1: # (If we haven't found "import " on the line, give up for now.) self.locs[d.id][-1] = DefLocation(defloc.def_id, (line, c)) if alias.asname or is_from: # for |import x.y as z| or |from x import y as z| we want {z: x.y} for symbol, data in filter_ops(store_ops, d): self.modules[d.id] = data[0].full_name add_import_ref(name=symbol, data=data, loc=loc) else: # |import x.y| puts both {x: x} and {x.y: x.y} in modules for symbol, data in filter_ops(import_ops, d): add_import_ref(name=symbol, data=data, loc=loc) for mod in module_utils.get_all_prefixes(name): # TODO(mdemello): Create references for every element. self.modules[d.scope + "." + mod] = mod
def visit_Import(self, node): store_ops = get_opcodes(self.traces, node.lineno, "STORE_NAME") import_ops = get_opcodes(self.traces, node.lineno, "IMPORT_NAME") for alias in node.names: name = alias.asname if alias.asname else alias.name d = self.add_local_def(node, name=name) # Only record modules that pytype has resolved in self.modules if alias.asname: # for |import x.y as z| we want {z: x.y} for _, symbol, data in store_ops: if (symbol == d.name and data and isinstance(data[0], abstract.Module)): self.modules[d.id] = data[0].full_name else: for _, symbol, data in import_ops: if (symbol == d.name and data and isinstance(data[0], abstract.Module)): # |import x.y| puts both {x: x} and {x.y: x.y} in modules for mod in module_utils.get_all_prefixes(name): self.modules[d.scope + "." + mod] = mod
def process_import(self, node): """Common code for Import and ImportFrom.""" # Only record modules that pytype has resolved in self.modules def is_resolved(data): return data and isinstance(data[0], abstract.Module) def add_import_ref(name, data, loc): self.add_global_ref(node, name=name, data=data, location=loc, typ="Import") for loc, (op, symbol, data) in self.match(node): d = self.add_local_def(node, name=symbol) defloc = self.locs[d.id][-1] # tweak the definition location slightly line, _ = loc text = self.source.line(line) c = text.find("import ") new_loc = source.Location(line, c) if c > -1 else loc self.locs[d.id][-1] = DefLocation(defloc.def_id, new_loc) if not is_resolved(_unwrap(data)): continue elif op == "STORE_NAME": # for |import x.y as z| or |from x import y as z| we want {z: x.y} self.modules[d.id] = _unwrap(data)[0].full_name add_import_ref(name=symbol, data=data, loc=loc) elif op == "IMPORT_NAME": # |import x.y| puts both {x: x} and {x.y: x.y} in modules add_import_ref(name=symbol, data=data, loc=loc) for mod in module_utils.get_all_prefixes(symbol): # TODO(mdemello): Create references for every element. self.modules[d.scope + "." + mod] = mod
def process_import(self, node, is_from): """Common code for Import and ImportFrom.""" store_ops = get_opcodes(self.traces, node.lineno, "STORE_NAME") import_ops = get_opcodes(self.traces, node.lineno, "IMPORT_NAME") # Only record modules that pytype has resolved in self.modules def is_resolved(defn, symbol, data): return (symbol == defn.name and data and isinstance(data[0], abstract.Module)) def filter_ops(op_list, defn): return [(symbol, data) for _, symbol, data in op_list if is_resolved(defn, symbol, data)] def add_import_ref(name, data, loc): self.add_global_ref( node, name=name, data=data, location=loc, typ="Import") for alias in node.names: name = alias.asname if alias.asname else alias.name d = self.add_local_def(node, name=name) loc = self.locs[d.id][-1].location if alias.asname or is_from: # for |import x.y as z| or |from x import y as z| we want {z: x.y} for symbol, data in filter_ops(store_ops, d): self.modules[d.id] = data[0].full_name add_import_ref(name=symbol, data=data, loc=loc) else: # |import x.y| puts both {x: x} and {x.y: x.y} in modules for symbol, data in filter_ops(import_ops, d): add_import_ref(name=symbol, data=data, loc=loc) for mod in module_utils.get_all_prefixes(name): # TODO(mdemello): Create references for every element. self.modules[d.scope + "." + mod] = mod
def add_module_prefixes(self, module_name): for prefix in module_utils.get_all_prefixes(module_name): self._prefixes.add(prefix)