def replacement_map_from_symbol_table( old: SymbolTable, new: SymbolTable, prefix: str) -> Dict[SymbolNode, SymbolNode]: """Create a new-to-old object identity map by comparing two symbol table revisions. Both symbol tables must refer to revisions of the same module id. The symbol tables are compared recursively (recursing into nested class symbol tables), but only within the given module prefix. Don't recurse into other modules accessible through the symbol table. """ replacements = {} # type: Dict[SymbolNode, SymbolNode] for name, node in old.items(): if (name in new and (node.kind == MDEF or node.node and get_prefix(node.node.fullname()) == prefix)): new_node = new[name] if (type(new_node.node) == type(node.node) # noqa and new_node.node and node.node and new_node.node.fullname() == node.node.fullname() and new_node.kind == node.kind): replacements[new_node.node] = node.node if isinstance(node.node, TypeInfo) and isinstance(new_node.node, TypeInfo): type_repl = replacement_map_from_symbol_table( node.node.names, new_node.node.names, prefix) replacements.update(type_repl) return replacements
def snapshot_symbol_table(name_prefix: str, table: SymbolTable) -> Dict[str, SnapshotItem]: """Create a snapshot description that represents the state of a symbol table. The snapshot has a representation based on nested tuples and dicts that makes it easy and fast to find differences. Only "shallow" state is included in the snapshot -- references to things defined in other modules are represented just by the names of the targets. """ result: Dict[str, SnapshotItem] = {} for name, symbol in table.items(): node = symbol.node # TODO: cross_ref? fullname = node.fullname if node else None common = (fullname, symbol.kind, symbol.module_public) if isinstance(node, MypyFile): # This is a cross-reference to another module. # If the reference is busted because the other module is missing, # the node will be a "stale_info" TypeInfo produced by fixup, # but that doesn't really matter to us here. result[name] = ('Moduleref', common) elif isinstance(node, TypeVarExpr): result[name] = ('TypeVar', node.variance, [snapshot_type(value) for value in node.values], snapshot_type(node.upper_bound)) elif isinstance(node, TypeAlias): result[name] = ('TypeAlias', node.alias_tvars, node.normalized, node.no_args, snapshot_optional_type(node.target)) elif isinstance(node, ParamSpecExpr): result[name] = ('ParamSpec', node.variance, snapshot_type(node.upper_bound)) else: assert symbol.kind != UNBOUND_IMPORTED if node and get_prefix(node.fullname) != name_prefix: # This is a cross-reference to a node defined in another module. result[name] = ('CrossRef', common) else: result[name] = snapshot_definition(node, common) return result
def replacement_map_from_symbol_table( old: SymbolTable, new: SymbolTable, prefix: str) -> Dict[SymbolNode, SymbolNode]: replacements = {} # type: Dict[SymbolNode, SymbolNode] for name, node in old.items(): if (name in new and (node.kind == MDEF or node.node and get_prefix(node.node.fullname()) == prefix)): new_node = new[name] if (type(new_node.node) == type(node.node) # noqa and new_node.node and node.node and new_node.node.fullname() == node.node.fullname() and new_node.kind == node.kind): replacements[new_node.node] = node.node if isinstance(node.node, TypeInfo) and isinstance(new_node.node, TypeInfo): type_repl = replacement_map_from_symbol_table( node.node.names, new_node.node.names, prefix) replacements.update(type_repl) return replacements
def snapshot_symbol_table(name_prefix: str, table: SymbolTable) -> Dict[str, SnapshotItem]: """Create a snapshot description that represents the state of a symbol table. The snapshot has a representation based on nested tuples and dicts that makes it easy and fast to find differences. Only "shallow" state is included in the snapshot -- references to things defined in other modules are represented just by the names of the targets. """ result = {} # type: Dict[str, SnapshotItem] for name, symbol in table.items(): node = symbol.node # TODO: cross_ref? fullname = node.fullname() if node else None common = (fullname, symbol.kind, symbol.module_public) if symbol.kind == MODULE_REF: # This is a cross-reference to another module. # If the reference is busted because the other module is missing, # the node will be a "stale_info" TypeInfo produced by fixup, # but that doesn't really matter to us here. result[name] = ('Moduleref', common) elif symbol.kind == TVAR: assert isinstance(node, TypeVarExpr) result[name] = ('TypeVar', node.variance, [snapshot_type(value) for value in node.values], snapshot_type(node.upper_bound)) elif isinstance(symbol.node, TypeAlias): result[name] = ('TypeAlias', symbol.node.alias_tvars, symbol.node.normalized, symbol.node.no_args, snapshot_optional_type(symbol.node.target)) else: assert symbol.kind != UNBOUND_IMPORTED if node and get_prefix(node.fullname()) != name_prefix: # This is a cross-reference to a node defined in another module. result[name] = ('CrossRef', common) else: result[name] = snapshot_definition(node, common) return result
def snapshot_symbol_table(name_prefix: str, table: SymbolTable) -> Dict[str, SnapshotItem]: """Create a snapshot description that represents the state of a symbol table. The snapshot has a representation based on nested tuples and dicts that makes it easy and fast to find differences. Only "shallow" state is included in the snapshot -- references to things defined in other modules are represented just by the names of the targers. """ result = {} # type: Dict[str, SnapshotItem] for name, symbol in table.items(): node = symbol.node # TODO: cross_ref? fullname = node.fullname() if node else None common = (fullname, symbol.kind, symbol.module_public) if symbol.kind == MODULE_REF: # This is a cross-reference to another module. assert isinstance(node, MypyFile) result[name] = ('Moduleref', common) elif symbol.kind == TVAR: assert isinstance(node, TypeVarExpr) result[name] = ('TypeVar', node.variance, [snapshot_type(value) for value in node.values], snapshot_type(node.upper_bound)) elif symbol.kind == TYPE_ALIAS: result[name] = ('TypeAlias', symbol.alias_tvars, snapshot_optional_type(symbol.type_override)) else: assert symbol.kind != UNBOUND_IMPORTED if node and get_prefix(node.fullname()) != name_prefix: # This is a cross-reference to a node defined in another module. result[name] = ('CrossRef', common, symbol.normalized) else: result[name] = snapshot_definition(node, common) return result