Commits

Anonymous committed dfcde5f

objectinfer: using AssignedName for with, for and except variables

  • Participants
  • Parent commits a72abaa

Comments (0)

Files changed (7)

File rope/base/builtins.py

         return context.get_per_name()
 
     def _iterator_get(self, context):
-        return Iterator(self._list_get(context))
+        return get_iterator(self._list_get(context))
 
     def _self_get(self, context):
         return get_list(self._list_get(context))

File rope/base/evaluate.py

     result = {}
     names = astutils.get_name_levels(targets)
     for name, levels in names:
-        assignment = rope.base.pynames.AssignmentValue(assigned, levels)
+        assignment = rope.base.pynames.AssignmentValue(
+            assigned, levels, evaluation, eval_type)
         def _eval(assignment=assignment):
             result = rope.base.oi.objectinfer.evaluate_object(
                 assignment, evaluation, module, lineno)
             if result is not None and eval_type:
                 result = pyobjects.PyObject(type_=result)
             return result
-        result[name] = rope.base.pynames.EvaluatedName(_eval, module, lineno)
+        pyname = rope.base.pynamesdef.AssignedName(lineno, module)
+        pyname.assignments.append(assignment)
+        result[name] = pyname
     return result

File rope/base/oi/objectinfer.py

             result.append(statically_inferred[parameter_index])
     return result
 
-@_ignore_inferred
-def _infer_assignment(assignment, pymodule):
-    pyobject = _infer_pyobject_for_assign_node(
-        assignment.ast_node, pymodule)
-    if pyobject is None:
-        return None
-    return _infer_assignment_object(assignment, pyobject)
-
-def _infer_assignment_object(assignment, pyobject):
-    for index in assignment.levels:
-        if isinstance(pyobject.get_type(), rope.base.builtins.Tuple):
-            holdings = pyobject.get_type().get_holding_objects()
-            if holdings:
-                pyobject = holdings[min(len(holdings) - 1, index)]
-            else:
-                pyobject = None
-        elif isinstance(pyobject.get_type(), rope.base.builtins.List):
-            pyobject = pyobject.get_type().holding
-        else:
-            pyobject = None
-        if pyobject is None:
-            break
-    return pyobject
-
-@_ignore_inferred
-def _infer_pyobject_for_assign_node(assign_node, pymodule, lineno=None):
-    if lineno is None:
-        lineno = _get_lineno_for_node(assign_node)
-    holding_scope = pymodule.get_scope().get_inner_scope_for_line(lineno)
-    primary, pyname = evaluate.get_primary_and_result(holding_scope,
-                                                      assign_node)
-    if pyname is not None:
-        result = pyname.get_object()
-        if isinstance(result.get_type(), rope.base.builtins.Property) and \
-           holding_scope.get_kind() == 'Class':
-            arg = rope.base.pynames.UnboundName(
-                rope.base.pyobjects.PyObject(holding_scope.pyobject))
-            return result.get_type().get_property_object(
-                evaluate.ObjectArguments([arg]))
-        return result
-
-@_ignore_inferred
-def _infer_pyname_for_assign_node(assign_node, pymodule, lineno=None):
-    if lineno is None:
-        lineno = _get_lineno_for_node(assign_node)
-    holding_scope = pymodule.get_scope().get_inner_scope_for_line(lineno)
-    return evaluate.get_statement_result(holding_scope, assign_node)
-
-def _get_lineno_for_node(assign_node):
-    if hasattr(assign_node, 'lineno') and \
-       assign_node.lineno is not None:
-        return assign_node.lineno
-    return 1
-
-@_ignore_inferred
-def evaluate_object(assignment, evaluation, module, lineno):
-    node = assignment.ast_node
-    pyobject = _infer_pyobject_for_assign_node(node, module, lineno)
-    pyname = _infer_pyname_for_assign_node(node, module, lineno)
-    new_pyname = pyname
-    tokens = evaluation.split('.')
-    for token in tokens:
-        call = token.endswith('()')
-        if call:
-            token = token[:-2]
-        if token:
-            pyname = new_pyname
-            new_pyname = _get_attribute(pyobject, token)
-            if new_pyname is not None:
-                pyobject = new_pyname.get_object()
-        if pyobject is not None and call:
-            if isinstance(pyobject, rope.base.pyobjects.AbstractFunction):
-                args = evaluate.ObjectArguments([pyname])
-                pyobject = pyobject.get_returned_object(args)
-            else:
-                pyobject = None
-        if pyobject is None:
-            break
-    if pyname is None or pyobject is None:
-        return pyobject
-    return _infer_assignment_object(assignment, pyobject)
-
-def _get_attribute(pyobject, name):
-    if pyobject is not None and name in pyobject:
-        return pyobject[name]
-
-
 def _infer_returned(pyobject, args):
     if args:
         # HACK: Setting parameter objects manually
 def _parameter_objects(pyobject):
     params = pyobject.get_param_names(special_args=False)
     return [rope.base.pyobjects.get_unknown()] * len(params)
+
+# handling `rope.base.pynames.AssignmentValue`
+
+@_ignore_inferred
+def _infer_assignment(assignment, pymodule):
+    result = _follow_pyname(assignment, pymodule)
+    if result is None:
+        return None
+    pyname, pyobject = result
+    pyobject = _follow_evaluations(assignment, pyname, pyobject)
+    if pyobject is None:
+        return None
+    return _follow_levels(assignment, pyobject)
+
+def _follow_levels(assignment, pyobject):
+    for index in assignment.levels:
+        if isinstance(pyobject.get_type(), rope.base.builtins.Tuple):
+            holdings = pyobject.get_type().get_holding_objects()
+            if holdings:
+                pyobject = holdings[min(len(holdings) - 1, index)]
+            else:
+                pyobject = None
+        elif isinstance(pyobject.get_type(), rope.base.builtins.List):
+            pyobject = pyobject.get_type().holding
+        else:
+            pyobject = None
+        if pyobject is None:
+            break
+    return pyobject
+
+@_ignore_inferred
+def _follow_pyname(assignment, pymodule, lineno=None):
+    assign_node = assignment.ast_node
+    if lineno is None:
+        lineno = _get_lineno_for_node(assign_node)
+    holding_scope = pymodule.get_scope().get_inner_scope_for_line(lineno)
+    pyname = evaluate.get_statement_result(holding_scope, assign_node)
+    if pyname is not None:
+        result = pyname.get_object()
+        if isinstance(result.get_type(), rope.base.builtins.Property) and \
+           holding_scope.get_kind() == 'Class':
+            arg = rope.base.pynames.UnboundName(
+                rope.base.pyobjects.PyObject(holding_scope.pyobject))
+            return pyname, result.get_type().get_property_object(
+                evaluate.ObjectArguments([arg]))
+        return pyname, result
+
+@_ignore_inferred
+def _follow_evaluations(assignment, pyname, pyobject):
+    new_pyname = pyname
+    tokens = assignment.evaluation.split('.')
+    for token in tokens:
+        call = token.endswith('()')
+        if call:
+            token = token[:-2]
+        if token:
+            pyname = new_pyname
+            new_pyname = _get_attribute(pyobject, token)
+            if new_pyname is not None:
+                pyobject = new_pyname.get_object()
+        if pyobject is not None and call:
+            if isinstance(pyobject, rope.base.pyobjects.AbstractFunction):
+                args = evaluate.ObjectArguments([pyname])
+                pyobject = pyobject.get_returned_object(args)
+            else:
+                pyobject = None
+        if pyobject is None:
+            break
+    if pyobject is not None and assignment.assign_type:
+        return rope.base.pyobjects.PyObject(pyobject)
+    return pyobject
+
+
+def _get_lineno_for_node(assign_node):
+    if hasattr(assign_node, 'lineno') and \
+       assign_node.lineno is not None:
+        return assign_node.lineno
+    return 1
+
+def _get_attribute(pyobject, name):
+    if pyobject is not None and name in pyobject:
+        return pyobject[name]

File rope/base/pynames.py

 class AssignmentValue(object):
     """An assigned expression"""
 
-    def __init__(self, ast_node, levels=None):
+    def __init__(self, ast_node, levels=None, evaluation='',
+                 assign_type=False):
         """The `level` is `None` for simple assignments and is
         a list of numbers for tuple assignments for example in::
 
             self.levels = []
         else:
             self.levels = levels
+        self.evaluation = evaluation
+        self.assign_type = assign_type
 
     def get_lineno(self):
         return self.ast_node.lineno

File ropetest/advanced_oi_test.py

         self.assertEquals(c_class, a_var.get_type())
 
     def test_static_oi_for_lists_per_object_for_iters(self):
-        code = 'class C(object):\n    pass\nl = []\n' \
-               'l.append(C())\nfor c in l:\n    a_var = c\n'
+        code = 'class C(object):\n    pass\n' \
+               'l = []\nl.append(C())\n' \
+               'for c in l:\n    a_var = c\n'
         self.mod.write(code)
         self.pycore.analyze_module(self.mod)
         pymod = self.pycore.resource_to_pyobject(self.mod)

File ropetest/objectinfertest.py

         self.assertEquals(c2_class, b_var.get_type())
 
     def test_we_know_the_type_of_catched_exceptions(self):
+        code = 'class MyError(Exception):\n    pass\n' \
+               'try:\n    raise MyError()\n' \
+               'except MyError, e:\n    pass\n'
         mod = self.pycore.get_string_module(
-            'class MyError(Exception):\n    pass\n'
-            'try:\n    raise MyError()\nexcept MyError, e:\n    pass\n')
+            code)
         my_error = mod['MyError'].get_object()
         e_var = mod['e'].get_object()
         self.assertEquals(my_error, e_var.get_type())

File ropetest/pycoretest.py

 
     @testutils.run_only_for_25
     def test_with_statement_variable_type(self):
-        code = 'class A(object):\n    def __enter__(self):        return self\n'\
+        code = 'class A(object):\n' \
+               '    def __enter__(self):        return self\n'\
                '    def __exit__(self, type, value, tb):\n        pass\n'\
                'with A() as var:    pass\n'
         if sys.version_info < (2, 6, 0):