Path: blob/master/elisp/emacs-for-python/rope-dist/rope/base/evaluate.py
1418 views
import rope.base.builtins1import rope.base.pynames2import rope.base.pyobjects3from rope.base import ast, astutils, exceptions, pyobjects, arguments, worder456BadIdentifierError = exceptions.BadIdentifierError78def eval_location(pymodule, offset):9"""Find the pyname at the offset"""10return eval_location2(pymodule, offset)[1]111213def eval_location2(pymodule, offset):14"""Find the primary and pyname at offset"""15pyname_finder = ScopeNameFinder(pymodule)16return pyname_finder.get_primary_and_pyname_at(offset)171819def eval_node(scope, node):20"""Evaluate a `ast.AST` node and return a PyName2122Return `None` if the expression cannot be evaluated.23"""24return eval_node2(scope, node)[1]252627def eval_node2(scope, node):28evaluator = StatementEvaluator(scope)29ast.walk(node, evaluator)30return evaluator.old_result, evaluator.result313233def eval_str(holding_scope, name):34return eval_str2(holding_scope, name)[1]353637def eval_str2(holding_scope, name):38try:39# parenthesizing for handling cases like 'a_var.\nattr'40node = ast.parse('(%s)' % name)41except SyntaxError:42raise BadIdentifierError('Not a resolvable python identifier selected.')43return eval_node2(holding_scope, node)444546class ScopeNameFinder(object):4748def __init__(self, pymodule):49self.module_scope = pymodule.get_scope()50self.lines = pymodule.lines51self.worder = worder.Worder(pymodule.source_code, True)5253def _is_defined_in_class_body(self, holding_scope, offset, lineno):54if lineno == holding_scope.get_start() and \55holding_scope.parent is not None and \56holding_scope.parent.get_kind() == 'Class' and \57self.worder.is_a_class_or_function_name_in_header(offset):58return True59if lineno != holding_scope.get_start() and \60holding_scope.get_kind() == 'Class' and \61self.worder.is_name_assigned_in_class_body(offset):62return True63return False6465def _is_function_name_in_function_header(self, scope, offset, lineno):66if scope.get_start() <= lineno <= scope.get_body_start() and \67scope.get_kind() == 'Function' and \68self.worder.is_a_class_or_function_name_in_header(offset):69return True70return False7172def get_pyname_at(self, offset):73return self.get_primary_and_pyname_at(offset)[1]7475def get_primary_and_pyname_at(self, offset):76lineno = self.lines.get_line_number(offset)77holding_scope = self.module_scope.get_inner_scope_for_line(lineno)78# function keyword parameter79if self.worder.is_function_keyword_parameter(offset):80keyword_name = self.worder.get_word_at(offset)81pyobject = self.get_enclosing_function(offset)82if isinstance(pyobject, pyobjects.PyFunction):83return (None, pyobject.get_parameters().get(keyword_name, None))84# class body85if self._is_defined_in_class_body(holding_scope, offset, lineno):86class_scope = holding_scope87if lineno == holding_scope.get_start():88class_scope = holding_scope.parent89name = self.worder.get_primary_at(offset).strip()90try:91return (None, class_scope.pyobject[name])92except rope.base.exceptions.AttributeNotFoundError:93return (None, None)94# function header95if self._is_function_name_in_function_header(holding_scope, offset, lineno):96name = self.worder.get_primary_at(offset).strip()97return (None, holding_scope.parent[name])98# from statement module99if self.worder.is_from_statement_module(offset):100module = self.worder.get_primary_at(offset)101module_pyname = self._find_module(module)102return (None, module_pyname)103if self.worder.is_from_aliased(offset):104name = self.worder.get_from_aliased(offset)105else:106name = self.worder.get_primary_at(offset)107return eval_str2(holding_scope, name)108109def get_enclosing_function(self, offset):110function_parens = self.worder.find_parens_start_from_inside(offset)111try:112function_pyname = self.get_pyname_at(function_parens - 1)113except BadIdentifierError:114function_pyname = None115if function_pyname is not None:116pyobject = function_pyname.get_object()117if isinstance(pyobject, pyobjects.AbstractFunction):118return pyobject119elif isinstance(pyobject, pyobjects.AbstractClass) and \120'__init__' in pyobject:121return pyobject['__init__'].get_object()122elif '__call__' in pyobject:123return pyobject['__call__'].get_object()124return None125126def _find_module(self, module_name):127dots = 0128while module_name[dots] == '.':129dots += 1130return rope.base.pynames.ImportedModule(131self.module_scope.pyobject, module_name[dots:], dots)132133134class StatementEvaluator(object):135136def __init__(self, scope):137self.scope = scope138self.result = None139self.old_result = None140141def _Name(self, node):142self.result = self.scope.lookup(node.id)143144def _Attribute(self, node):145pyname = eval_node(self.scope, node.value)146if pyname is None:147pyname = rope.base.pynames.UnboundName()148self.old_result = pyname149if pyname.get_object() != rope.base.pyobjects.get_unknown():150try:151self.result = pyname.get_object()[node.attr]152except exceptions.AttributeNotFoundError:153self.result = None154155def _Call(self, node):156primary, pyobject = self._get_primary_and_object_for_node(node.func)157if pyobject is None:158return159def _get_returned(pyobject):160args = arguments.create_arguments(primary, pyobject,161node, self.scope)162return pyobject.get_returned_object(args)163if isinstance(pyobject, rope.base.pyobjects.AbstractClass):164result = None165if '__new__' in pyobject:166new_function = pyobject['__new__'].get_object()167result = _get_returned(new_function)168if result is None or \169result == rope.base.pyobjects.get_unknown():170result = rope.base.pyobjects.PyObject(pyobject)171self.result = rope.base.pynames.UnboundName(pyobject=result)172return173174pyfunction = None175if isinstance(pyobject, rope.base.pyobjects.AbstractFunction):176pyfunction = pyobject177elif '__call__' in pyobject:178pyfunction = pyobject['__call__'].get_object()179if pyfunction is not None:180self.result = rope.base.pynames.UnboundName(181pyobject=_get_returned(pyfunction))182183def _Str(self, node):184self.result = rope.base.pynames.UnboundName(185pyobject=rope.base.builtins.get_str())186187def _Num(self, node):188type_name = type(node.n).__name__189self.result = self._get_builtin_name(type_name)190191def _get_builtin_name(self, type_name):192pytype = rope.base.builtins.builtins[type_name].get_object()193return rope.base.pynames.UnboundName(194rope.base.pyobjects.PyObject(pytype))195196def _BinOp(self, node):197self.result = rope.base.pynames.UnboundName(198self._get_object_for_node(node.left))199200def _BoolOp(self, node):201self.result = rope.base.pynames.UnboundName(202self._get_object_for_node(node.values[0]))203204def _Repr(self, node):205self.result = self._get_builtin_name('str')206207def _UnaryOp(self, node):208self.result = rope.base.pynames.UnboundName(209self._get_object_for_node(node.operand))210211def _Compare(self, node):212self.result = self._get_builtin_name('bool')213214def _Dict(self, node):215keys = None216values = None217if node.keys:218keys = self._get_object_for_node(node.keys[0])219values = self._get_object_for_node(node.values[0])220self.result = rope.base.pynames.UnboundName(221pyobject=rope.base.builtins.get_dict(keys, values))222223def _List(self, node):224holding = None225if node.elts:226holding = self._get_object_for_node(node.elts[0])227self.result = rope.base.pynames.UnboundName(228pyobject=rope.base.builtins.get_list(holding))229230def _ListComp(self, node):231pyobject = self._what_does_comprehension_hold(node)232self.result = rope.base.pynames.UnboundName(233pyobject=rope.base.builtins.get_list(pyobject))234235def _GeneratorExp(self, node):236pyobject = self._what_does_comprehension_hold(node)237self.result = rope.base.pynames.UnboundName(238pyobject=rope.base.builtins.get_iterator(pyobject))239240def _what_does_comprehension_hold(self, node):241scope = self._make_comprehension_scope(node)242pyname = eval_node(scope, node.elt)243return pyname.get_object() if pyname is not None else None244245def _make_comprehension_scope(self, node):246scope = self.scope247module = scope.pyobject.get_module()248names = {}249for comp in node.generators:250new_names = _get_evaluated_names(comp.target, comp.iter, module,251'.__iter__().next()', node.lineno)252names.update(new_names)253return rope.base.pyscopes.TemporaryScope(scope.pycore, scope, names)254255def _Tuple(self, node):256objects = []257if len(node.elts) < 4:258for stmt in node.elts:259pyobject = self._get_object_for_node(stmt)260objects.append(pyobject)261else:262objects.append(self._get_object_for_node(node.elts[0]))263self.result = rope.base.pynames.UnboundName(264pyobject=rope.base.builtins.get_tuple(*objects))265266def _get_object_for_node(self, stmt):267pyname = eval_node(self.scope, stmt)268pyobject = None269if pyname is not None:270pyobject = pyname.get_object()271return pyobject272273def _get_primary_and_object_for_node(self, stmt):274primary, pyname = eval_node2(self.scope, stmt)275pyobject = None276if pyname is not None:277pyobject = pyname.get_object()278return primary, pyobject279280def _Subscript(self, node):281if isinstance(node.slice, ast.Index):282self._call_function(node.value, '__getitem__',283[node.slice.value])284elif isinstance(node.slice, ast.Slice):285self._call_function(node.value, '__getslice__')286287def _call_function(self, node, function_name, other_args=None):288pyname = eval_node(self.scope, node)289if pyname is not None:290pyobject = pyname.get_object()291else:292return293if function_name in pyobject:294called = pyobject[function_name].get_object()295if not called or not isinstance(called, pyobjects.AbstractFunction):296return297args = [node]298if other_args:299args += other_args300arguments_ = arguments.Arguments(args, self.scope)301self.result = rope.base.pynames.UnboundName(302pyobject=called.get_returned_object(arguments_))303304def _Lambda(self, node):305self.result = rope.base.pynames.UnboundName(306pyobject=rope.base.builtins.Lambda(node, self.scope))307308309def _get_evaluated_names(targets, assigned, module, evaluation, lineno):310result = {}311for name, levels in astutils.get_name_levels(targets):312assignment = rope.base.pynames.AssignmentValue(assigned, levels,313evaluation)314# XXX: this module should not access `rope.base.pynamesdef`!315pyname = rope.base.pynamesdef.AssignedName(lineno, module)316pyname.assignments.append(assignment)317result[name] = pyname318return result319320321