Commits

Anonymous committed 84e4863

Added rope.base.oi.staticoi

Comments (0)

Files changed (10)

docs/dev/workingon.txt

 Storing Different Return Types For Different Set Of Arguments
 =============================================================
 
-- lists
-- tuples
-- sets
-- dicts
+- renaming `_get_returned_object` to `get_returned_object`
+- change `dynamicoi` to store return value for each set of parameters
 
-* keywords
-* Transforming `PyObject`\s to textual form for lookups
-* Change `dynamicoi` to store return value for each set of parameters
+* transforming `PyObject`\s to textual form for lookups
+* keywords and `Arguments` objects
 * `PyFunction`'s ``returned_object`` cache is no longer useful
-* Change calls to `_get_returned_object` in the `rope.base.evaluate`
-* Renaming `_get_returned_object` to `get_returned_object`
+* ignoring ``*args`` and ``**kwds`` in runmod
 
+* Handling the return type of generator functions
 
 Possible Refactorings
 =====================
 
-* Refactoring `rope.base.oi`; add `ObjectInferenceStrategy`
 * Refactoring `rope.refactor`; remove `PythonRefactoring`
 
 

rope/base/builtins.py

         self.returned = returned
         self.function = function
     
-    def _get_returned_object(self, args=None):
+    def get_returned_object(self, args=None):
         if self.function is not None:
             return self.function(args)
         return self.returned
     def get_attributes(self):
         return self.attributes
 
-    def _get_returned_object(self):
+    def get_returned_object(self):
         return self.holding
 
 def _infer_sequence_type(seq):
     if '__iter__' in seq.get_attributes():
         iter = seq.get_attribute('__iter__').get_object().\
-               _get_returned_object()
+               get_returned_object()
         if 'next' in iter.get_attributes():
             holding = iter.get_attribute('next').get_object().\
-                      _get_returned_object()
+                      get_returned_object()
             return holding
     
 

rope/base/evaluate.py

             result = None
             if '__new__' in pyobject.get_attributes():
                 new_function = pyobject.get_attribute('__new__').get_object()
-                result = new_function._get_returned_object(args)
+                result = new_function.get_returned_object(args)
             if result is None:
                 result = rope.base.pyobjects.PyObject(pyobject)
             self.result = rope.base.pynames.AssignedName(pyobject=result)
         elif pyobject.get_type() == rope.base.pyobjects.PyObject.get_base_type('Function'):
             self.result = rope.base.pynames.AssignedName(
-                pyobject=pyobject._get_returned_object(args))
+                pyobject=pyobject.get_returned_object(args))
         elif '__call__' in pyobject.get_attributes():
             call_function = pyobject.get_attribute('__call__')
             self.result = rope.base.pynames.AssignedName(
-                pyobject=call_function.get_object()._get_returned_object(args))
+                pyobject=call_function.get_object().get_returned_object(args))
     
     def visitConst(self, node):
         if isinstance(node.value, (str, unicode)):
         if function_name in pyobject.get_attributes():
             call_function = pyobject.get_attribute(function_name)
             self.result = rope.base.pynames.AssignedName(
-                pyobject=call_function.get_object()._get_returned_object())
+                pyobject=call_function.get_object().get_returned_object())
 
     @staticmethod
     def get_statement_result(scope, node):

rope/base/oi/dynamicoi.py

 import os
 import re
+import socket
 import subprocess
 import sys
-import socket
 import cPickle as pickle
 import marshal
 import tempfile
 class DynamicObjectInference(object):
     
     def __init__(self, pycore):
+        self.info = pycore.call_info
+        self.to_pyobject = _TextualToPyObject(pycore.project)
+    
+    def infer_returned_object(self, pyobject, args):
+        organizer = self.info.find_organizer(pyobject)
+        if organizer:
+            return self.to_pyobject.transform(organizer.get_returned_object())
+
+    def infer_parameter_objects(self, pyobject):
+        organizer = self.info.find_organizer(pyobject)
+        if organizer and organizer.args is not None:
+            pyobjects = [self.to_pyobject.transform(parameter)
+                         for parameter in organizer.get_parameters()]
+            return pyobjects
+    
+    def infer_assigned_object(self, pyname):
+        pass
+    
+    def infer_for_object(self, pyname):
+        pass
+
+
+class CallInformationCollector(object):
+    
+    def __init__(self, pycore):
         self.pycore = pycore
         self.files = {}
-        self.to_pyobject = _TextualToPyObject(self.pycore.project)
     
     def run_module(self, resource, args=None, stdin=None, stdout=None):
         """Return a PythonFileRunner for controlling the process"""
         return PythonFileRunner(self.pycore, resource, args, stdin,
                                 stdout, self._data_received)
     
-    def infer_returned_object(self, pyobject):
-        organizer = self._find_organizer(pyobject)
-        if organizer:
-            return self.to_pyobject.transform(organizer.returned)
-
-    def infer_parameter_objects(self, pyobject):
-        organizer = self._find_organizer(pyobject)
-        if organizer and organizer.args is not None:
-            pyobjects = [self.to_pyobject.transform(parameter)
-                         for parameter in organizer.args]
-            return pyobjects
-    
-    def _find_organizer(self, pyobject):
-        resource = pyobject.get_module().get_resource()
-        if resource is None:
-            return
-        path = os.path.abspath(resource._get_real_path())
-        lineno = pyobject._get_ast().lineno
-        if path in self.files and lineno in self.files[path]:
-            organizer = self.files[path][lineno]
-            return organizer
-    
     def _data_received(self, data):
         path = data[0][1]
         lineno = data[0][2]
             self.files[path][lineno] = _CallInformationOrganizer()
         self.files[path][lineno].add_call_information(data[1], data[2])
 
+    def find_organizer(self, pyobject):
+        resource = pyobject.get_module().get_resource()
+        if resource is None:
+            return
+        path = os.path.abspath(resource._get_real_path())
+        lineno = pyobject._get_ast().lineno
+        if path in self.files and lineno in self.files[path]:
+            organizer = self.files[path][lineno]
+            return organizer
+    
 
 class _CallInformationOrganizer(object):
     
     def __init__(self):
         self.args = None
         self.returned = None
+        self.info = {}
     
     def add_call_information(self, args, returned):
+        self.info[args] = returned
         if self.returned is None or (args and args[0][0] not in ('unknown', 'none')):
             self.args = args
         if self.returned is None or returned[0] not in ('unknown', 'none'):
             self.returned = returned
+    
+    def get_parameters(self):
+        return self.args
 
+    def get_returned_object(self, arguments=None):
+        return self.returned
+
+
+class _PyObjectToTextual(object):
+    
+    def __init__(self, project):
+        pass
+    
+    def transform(self, pyobject):
+        """Transform a `PyObject` to textual form"""
+        if pyobject is None:
+            return ('none')
+        type = type(pyobject)
+        method = getattr(self, type + '_to_textual')
+        return method(textual)
+
+    def PyObject_to_textual(self, pyobject):
+        pass
+
+    def PyFunction_to_textual(self, pyobject):
+        pass
+    
+    def PyClass_to_textual(self, pyobject):
+        pass
+    
+    def PyModule_to_textual(self, pyobject):
+        pass
+    
+    def PyPackage_to_textual(self, pyobject):
+        pass
+    
+    def List_to_textual(self, pyobject):
+        pass
+    
+    def Dict_to_textual(self, pyobject):
+        pass
+    
+    def Tuple_to_textual(self, pyobject):
+        pass
+    
+    def Set_to_textual(self, pyobject):
+        pass
+    
+    def Str_to_textual(self, pyobject):
+        pass
+    
 
 class _TextualToPyObject(object):
     

rope/base/oi/objectinfer.py

 from rope.base import builtins
 import rope.base.codeanalyze
 import rope.base.evaluate
+import rope.base.oi.staticoi
 
 
 class ObjectInfer(object):
 
     def __init__(self, pycore):
-        self.pycore = pycore
+        self.ois = [rope.base.oi.staticoi.StaticObjectInference(),
+                    rope.base.oi.dynamicoi.DynamicObjectInference(pycore)]
     
-    def infer_object(self, pyname):
-        """Infers the `PyObject` this `PyName` references"""
-        if not pyname.assignments:
-            return
-        for assignment in reversed(pyname.assignments):
-            result = self._infer_assignment(assignment, pyname.module)
+    def infer_assigned_object(self, pyname):
+        """Infer the `PyObject` this `PyName` references"""
+        for oi in self.ois:
+            result = oi.infer_assigned_object(pyname)
             if result is not None:
                 return result
     
-    def _infer_assignment(self, assignment, pymodule):
-        try:
-            pyname = self._infer_pyname_for_assign_node(
-                assignment.ast_node, pymodule)
-            if pyname is None:
-                return None
-            return self._infer_assignment_object(assignment, pyname.get_object())
-        except IsBeingInferredException:
-            pass
-
-    def _infer_assignment_object(self, assignment, pyobject):
-        if assignment.index is not None and isinstance(pyobject.get_type(),
-                                                       builtins.Tuple):
-            holdings = pyobject.get_type().get_holding_objects()
-            return holdings[min(len(holdings) - 1, assignment.index)]
-        if assignment.index is not None and isinstance(pyobject.get_type(),
-                                                       builtins.List):
-            return pyobject.get_type().holding
-        return pyobject
+    def infer_for_object(self, pyname):
+        """Infer the `PyObject` this for variable `PyName` references"""
+        for oi in self.ois:
+            result = oi.infer_for_object(pyname)
+            if result is not None:
+                return result
     
-    def _infer_pyname_for_assign_node(self, assign_node, pymodule):
-        try:
-            lineno = 1
-            if hasattr(assign_node, 'lineno') and assign_node.lineno is not None:
-                lineno = assign_node.lineno
-            holding_scope = pymodule.get_scope().get_inner_scope_for_line(lineno)
-            return rope.base.evaluate.StatementEvaluator.\
-                   get_statement_result(holding_scope, assign_node)
-        except IsBeingInferredException:
-            pass
-        
-
-    def infer_for_object(self, pyname):
-        """Infers the `PyObject` this `PyName` references"""
-        list_pyname = self._infer_pyname_for_assign_node(
-            pyname.assignment.ast_node, pyname.module)
-        resulting_pyname = self._call_function(
-            self._call_function(list_pyname, '__iter__'), 'next')
-        if resulting_pyname is None:
-            return None
-        return self._infer_assignment_object(pyname.assignment,
-                                             resulting_pyname.get_object())
-    
-    def _call_function(self, pyname, function_name):
-        if pyname is None:
-            return
-        pyobject = pyname.get_object()
-        if function_name in pyobject.get_attributes():
-            call_function = pyobject.get_attribute(function_name)
-            return rope.base.pynames.AssignedName(
-                pyobject=call_function.get_object()._get_returned_object())
-
-    def infer_returned_object(self, pyobject):
-        """Infers the `PyObject` this callable `PyObject` returns after calling"""
-        dynamically_inferred = self.pycore.dynamicoi.\
-                               infer_returned_object(pyobject)
-        if dynamically_inferred is not None:
-            return dynamically_inferred
-        scope = pyobject.get_scope()
-        if not scope._get_returned_asts():
-            return
-        for returned_node in reversed(scope._get_returned_asts()):
-            try:
-                resulting_pyname = rope.base.evaluate.StatementEvaluator.\
-                                   get_statement_result(scope, returned_node)
-                if resulting_pyname is None:
-                    return None
-                return resulting_pyname.get_object()
-            except IsBeingInferredException:
-                pass
+    def infer_returned_object(self, pyobject, args):
+        """Infer the `PyObject` this callable `PyObject` returns after calling"""
+        for oi in reversed(self.ois):
+            result = oi.infer_returned_object(pyobject, args)
+            if result is not None:
+                return result
     
     def infer_parameter_objects(self, pyobject):
-        """Infers the `PyObject` of parameters of this callable `PyObject`"""
-        dynamically_inferred_object = self.pycore.dynamicoi.infer_parameter_objects(pyobject)
-        if dynamically_inferred_object is not None:
-            return dynamically_inferred_object
-        
+        """Infer the `PyObject`\s of parameters of this callable `PyObject`"""
+        for oi in self.ois:
+            result = oi.infer_parameter_objects(pyobject)
+            if result is not None:
+                return result

rope/base/oi/runmod.py

                 self.sender = _FileSender(send_info)
         
             def global_trace(frame, event, arg):
-                # HACK: Ignoring out to in calls
-                # XXX: This might ignore some information
+                # HACK: Ignoring out->in calls
+                # This might lose some information
                 if self._is_an_interesting_call(frame):
                     return self.on_function_call
             sys.settrace(global_trace)
                 pass
             try:
                 data = (self._object_to_persisted_form(frame.f_code),
-                        args, returned)
+                        tuple(args), returned)
                 self.sender.send_data(data)
             except (TypeError):
                 pass

rope/base/oi/staticoi.py

+import rope.base.pyobjects
+
+
+class StaticObjectInference(object):
+
+    def __init__(self):
+        pass
+    
+    def infer_assigned_object(self, pyname):
+        if not pyname.assignments:
+            return
+        for assignment in reversed(pyname.assignments):
+            result = self._infer_assignment(assignment, pyname.module)
+            if result is not None:
+                return result
+    
+    def _infer_assignment(self, assignment, pymodule):
+        try:
+            pyname = self._infer_pyname_for_assign_node(
+                assignment.ast_node, pymodule)
+            if pyname is None:
+                return None
+            return self._infer_assignment_object(assignment, pyname.get_object())
+        except rope.base.pyobjects.rope.base.pyobjects.IsBeingInferredException:
+            pass
+
+    def _infer_assignment_object(self, assignment, pyobject):
+        if assignment.index is not None and isinstance(pyobject.get_type(),
+                                                       rope.base.builtins.Tuple):
+            holdings = pyobject.get_type().get_holding_objects()
+            return holdings[min(len(holdings) - 1, assignment.index)]
+        if assignment.index is not None and isinstance(pyobject.get_type(),
+                                                       rope.base.builtins.List):
+            return pyobject.get_type().holding
+        return pyobject
+    
+    def _infer_pyname_for_assign_node(self, assign_node, pymodule):
+        try:
+            lineno = 1
+            if hasattr(assign_node, 'lineno') and assign_node.lineno is not None:
+                lineno = assign_node.lineno
+            holding_scope = pymodule.get_scope().get_inner_scope_for_line(lineno)
+            return rope.base.pyobjects.rope.base.evaluate.StatementEvaluator.\
+                   get_statement_result(holding_scope, assign_node)
+        except rope.base.pyobjects.rope.base.pyobjects.IsBeingInferredException:
+            pass
+        
+
+    def infer_for_object(self, pyname):
+        """Infers the `PyObject` this `PyName` references"""
+        list_pyname = self._infer_pyname_for_assign_node(
+            pyname.assignment.ast_node, pyname.module)
+        resulting_pyname = self._call_function(
+            self._call_function(list_pyname, '__iter__'), 'next')
+        if resulting_pyname is None:
+            return None
+        return self._infer_assignment_object(pyname.assignment,
+                                             resulting_pyname.get_object())
+    
+    def _call_function(self, pyname, function_name):
+        if pyname is None:
+            return
+        pyobject = pyname.get_object()
+        if function_name in pyobject.get_attributes():
+            call_function = pyobject.get_attribute(function_name)
+            return rope.base.pyobjects.rope.base.pynames.AssignedName(
+                pyobject=call_function.get_object().get_returned_object())
+
+    def infer_returned_object(self, pyobject, args):
+        scope = pyobject.get_scope()
+        if not scope._get_returned_asts():
+            return
+        for returned_node in reversed(scope._get_returned_asts()):
+            try:
+                resulting_pyname = rope.base.pyobjects.rope.base.evaluate.StatementEvaluator.\
+                                   get_statement_result(scope, returned_node)
+                if resulting_pyname is None:
+                    return None
+                return resulting_pyname.get_object()
+            except rope.base.pyobjects.rope.base.pyobjects.IsBeingInferredException:
+                pass
+    
+    def infer_parameter_objects(self, pyobject):
+        pass

rope/base/pycore.py

     def __init__(self, project):
         self.project = project
         self.module_map = {}
+        self.call_info = rope.base.oi.dynamicoi.CallInformationCollector(self)
         self.object_infer = rope.base.oi.objectinfer.ObjectInfer(self)
         self.refactoring = rope.refactor.PythonRefactoring(self)
-        self.dynamicoi = rope.base.oi.dynamicoi.DynamicObjectInference(self)
         self.classes = None
         observer = rope.base.project.ResourceObserver(
             self._invalidate_resource_cache, self._invalidate_resource_cache)
             module._invalidate_concluded_data()
 
     def run_module(self, resource, args=None, stdin=None, stdout=None):
-        runner = self.dynamicoi.run_module(resource, args, stdin, stdout)
+        runner = self.call_info.run_module(resource, args, stdin, stdout)
         runner.add_finishing_observer(self._invalidate_all_concluded_data)
         runner.run()
         return runner

rope/base/pynames.py

             self.is_being_inferred = True
             try:
                 object_infer = self.module.pycore._get_object_infer()
-                inferred_object = object_infer.infer_object(self)
+                inferred_object = object_infer.infer_assigned_object(self)
                 self.pyobject.set(inferred_object)
             finally:
                 self.is_being_inferred = False
     
     def get_object(self):
         if self.pyobject.get() is None:
-            self.pyobject.set(self.pyfunction._get_parameter(self.index))
+            self.pyobject.set(self.pyfunction.get_parameter(self.index))
         return self.pyobject.get()
     
     def get_definition_location(self):

rope/base/pyobjects.py

             self.parameter_pynames.set(result)
         return self.parameter_pynames.get()
     
-    def _get_parameter(self, index):
+    def get_parameter(self, index):
         if not self.parameter_pyobjects.get():
             self.parameter_pyobjects.set(self._get_parameter_pyobjects())
         return self.parameter_pyobjects.get()[index]
     
-    def _get_returned_object(self, args=None):
+    def get_returned_object(self, args=None):
         if self.is_being_inferred:
             raise IsBeingInferredException('Circular assignments')
         if self.returned_object.get() is None:
             self.is_being_inferred = True
             try:
                 object_infer = self.pycore._get_object_infer()
-                inferred_object = object_infer.infer_returned_object(self)
+                inferred_object = object_infer.infer_returned_object(self, args)
                 self.returned_object.set(inferred_object)
             finally:
                 self.is_being_inferred = False
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.