def from_scope_node(scope_node, child_is_funcdef=None, is_nested=True, node_is_object=False): if scope_node == base_node: return base_context is_funcdef = scope_node.type in ('funcdef', 'lambdef') parent_scope = parser_utils.get_parent_scope(scope_node) parent_context = from_scope_node(parent_scope, child_is_funcdef=is_funcdef) if is_funcdef: if isinstance(parent_context, AnonymousInstance): func = BoundMethod( self, parent_context, parent_context.class_context, parent_context.parent_context, scope_node ) else: func = er.FunctionContext( self, parent_context, scope_node ) if is_nested and not node_is_object: return func.get_function_execution() return func elif scope_node.type == 'classdef': class_context = er.ClassContext(self, scope_node, parent_context) if child_is_funcdef: # anonymous instance return AnonymousInstance(self, parent_context, class_context) else: return class_context elif scope_node.type == 'comp_for': if node.start_pos >= scope_node.children[-1].start_pos: return parent_context return iterable.CompForContext.from_comp_for(parent_context, scope_node) raise Exception("There's a scope that was not managed.")
def _eval_element_not_cached(self, context, element): debug.dbg('eval_element %s@%s', element, element.start_pos) types = set() typ = element.type if typ in ('name', 'number', 'string', 'atom'): types = self.eval_atom(context, element) elif typ == 'keyword': # For False/True/None if element.value in ('False', 'True', 'None'): types.add(compiled.builtin_from_name(self, element.value)) # else: print e.g. could be evaluated like this in Python 2.7 elif typ == 'lambdef': types = set([er.FunctionContext(self, context, element)]) elif typ == 'expr_stmt': types = self.eval_statement(context, element) elif typ in ('power', 'atom_expr'): first_child = element.children[0] if not (first_child.type == 'keyword' and first_child.value == 'await'): types = self.eval_atom(context, first_child) for trailer in element.children[1:]: if trailer == '**': # has a power operation. right = self.eval_element(context, element.children[2]) types = set(precedence.calculate(self, context, types, trailer, right)) break types = self.eval_trailer(context, types, trailer) elif typ in ('testlist_star_expr', 'testlist',): # The implicit tuple in statements. types = set([iterable.SequenceLiteralContext(self, context, element)]) elif typ in ('not_test', 'factor'): types = self.eval_element(context, element.children[-1]) for operator in element.children[:-1]: types = set(precedence.factor_calculate(self, types, operator)) elif typ == 'test': # `x if foo else y` case. types = (self.eval_element(context, element.children[0]) | self.eval_element(context, element.children[-1])) elif typ == 'operator': # Must be an ellipsis, other operators are not evaluated. # In Python 2 ellipsis is coded as three single dot tokens, not # as one token 3 dot token. assert element.value in ('.', '...') types = set([compiled.create(self, Ellipsis)]) elif typ == 'dotted_name': types = self.eval_atom(context, element.children[0]) for next_name in element.children[2::2]: # TODO add search_global=True? types = unite( typ.py__getattribute__(next_name, name_context=context) for typ in types ) types = types elif typ == 'eval_input': types = self._eval_element_not_cached(context, element.children[0]) elif typ == 'annassign': types = pep0484._evaluate_for_annotation(context, element.children[1]) else: types = precedence.calculate_children(self, context, element.children) debug.dbg('eval_element result %s', types) return types
def parent(self): context = self._name.parent_context if context is None: return None if isinstance(context, er.FunctionExecutionContext): # TODO the function context should be a part of the function # execution context. context = er.FunctionContext( self._evaluator, context.parent_context, context.tree_node) return Definition(self._evaluator, context.name)
def goto_definitions(self, context, name): def_ = name.get_definition() is_simple_name = name.parent.type not in ('power', 'trailer') if is_simple_name: if name.parent.type == 'classdef' and name.parent.name == name: return [er.ClassContext(self, name.parent, context)] elif name.parent.type == 'funcdef': return [er.FunctionContext(self, context, name.parent)] elif name.parent.type == 'file_input': raise NotImplementedError if def_.type == 'expr_stmt' and name in def_.get_defined_names(): return self.eval_statement(context, def_, name) elif def_.type == 'for_stmt': container_types = self.eval_element(context, def_.children[3]) for_types = iterable.py__iter__types(self, container_types, def_.children[3]) return finder.check_tuple_assignments(self, for_types, name) elif def_.type in ('import_from', 'import_name'): return imports.infer_import(context, name) return helpers.evaluate_call_of_leaf(context, name)
def goto_definitions(self, context, name): def_ = name.get_definition(import_name_always=True) if def_ is not None: type_ = def_.type if type_ == 'classdef': return [er.ClassContext(self, name.parent, context)] elif type_ == 'funcdef': return [er.FunctionContext(self, context, name.parent)] if type_ == 'expr_stmt': is_simple_name = name.parent.type not in ('power', 'trailer') if is_simple_name: return self.eval_statement(context, def_, name) if type_ == 'for_stmt': container_types = self.eval_element(context, def_.children[3]) cn = ContextualizedNode(context, def_.children[3]) for_types = iterable.py__iter__types(self, container_types, cn) c_node = ContextualizedName(context, name) return finder.check_tuple_assignments(self, c_node, for_types) if type_ in ('import_from', 'import_name'): return imports.infer_import(context, name) return helpers.evaluate_call_of_leaf(context, name)
def _apply_decorators(evaluator, context, node): """ Returns the function, that should to be executed in the end. This is also the places where the decorators are processed. """ if node.type == 'classdef': decoratee_context = er.ClassContext(evaluator, parent_context=context, classdef=node) else: decoratee_context = er.FunctionContext(evaluator, parent_context=context, funcdef=node) initial = values = set([decoratee_context]) for dec in reversed(node.get_decorators()): debug.dbg('decorator: %s %s', dec, values) dec_values = context.eval_node(dec.children[1]) trailer_nodes = dec.children[2:-1] if trailer_nodes: # Create a trailer and evaluate it. trailer = tree.PythonNode('trailer', trailer_nodes) trailer.parent = dec dec_values = evaluator.eval_trailer(context, dec_values, trailer) if not len(dec_values): debug.warning('decorator not found: %s on %s', dec, node) return initial values = unite( dec_value.execute(param.ValuesArguments([values])) for dec_value in dec_values) if not len(values): debug.warning('not possible to resolve wrappers found %s', node) return initial debug.dbg('decorator end %s', values) return values