Commits

Anonymous committed c0f9886

Support for *args and **kwds
Fixed problems with from import invalidation
Docs for builtins
Adding object and type builtin types
Enhanced returned object SOI

  • Participants
  • Parent commits 2d5ab63

Comments (0)

Files changed (26)

docs/dev/done.txt

 ===========
 
 
+- Enhanced returned object static object inference : March 8, 2007
+
+
+- Enhanced static object inference : March 8, 2007
+
+
+- Handling ``*args`` and ``**kwds`` arguments : March 7, 2007
+
+
+- Showing pydoc for some of builtin types and functions : March 7, 2007
+
+
 > Public Release 0.5m2 : March 4, 2007
 
 

docs/dev/issues.txt

 * `Allowing non-existent resources`_
 * `Python's implicit interfaces`_
 * `Having virtual PyModules`_
-* `Redefining function/class definitions`_
+* `Getting ready for Python 3.0`_
 * Indexing source files for faster occurrence finding
 * Faster module running
 * Saving hard to compute information like class hierarchies to files
 * Finding available refactorings
-* Getting ready for Python 3.0
 
 
 Better SOI
 ==========
 
 To improve our static object inference mechanisms I propose to add a
-new feature to rope to perform enhanced SOI.  Rope actually analyzes
+new feature to rope to perform enhanced SOI.  Rope analyzes
 all function calls in a module and saves the information in
 `rope.base.oi.callinfo.CallInforManager` class.
 
 we'll decide about that.
 
 
+Either Removing 'Unknown's or `None`\s
+--------------------------------------
+
+The problem is that for indicating an unknown `PyName` rope
+sometimes uses ``PyObject(get_base_type('Unknown'))`` and sometimes
+sometimes uses `None`\s.  I propose to remove one of these two.
+
+
+Refactoring The Way `CallInfoManager` Works
+-------------------------------------------
+
+Probably we should move callinfo to the ObjectInfer.
+
+* If the return type for the exact parameter exists return it
+* If it does not exist
+
+  * Try to determine the output statically
+  * SOI was succesful save the result in callinfo
+  * Otherwise return the default returned
+
+* Not overwriting the returned type with `called_with_params`
+
+
+Static Returned Object Inference
+--------------------------------
+
+This, if implemented, will complete our last piece of iterative
+static object inference.  The goal is to say what a function might
+return when we have the parameters passed to it.
+
+Since we're passed the object parameters hold, we can perform a
+better returned object SOI.  We can do that by giving parameters
+the passed objects and infer the object of local names once more.
+
+Actually we have to perform two things.  We have to ask scope
+`PyName`\s to forget their concluded data and change the
+parameters to return what we want.
+
+One dirty way of making this work is setting `PyFunction.
+parameter_objects` manually.  But this is not thread safe and
+might have other unwanted effects.
+
+* Parameterizing function scope names to their parameters objects
+* Caching old result
+* Saving information in callinfo
+* Not giving inaccurate information
+
+
+Holding Per Name Information
+----------------------------
+
+We can change our type DB to add this feature.::
+
+  objectdb.add_per_object(scope, name, function_name, parameters)
+
+* Forcing `create_arguments` to pass the implicit object for
+  builtin functions.
+
+
 Using New Concluded Data
 ------------------------
 
 function parameters that is not true.  Retrying SOI everytime
 names with unknown objects are encountered seem unefficient, too.
 
+To fix the inefficiency problem maybe we can invalidate the
+concluded data on the module that is going to be analyzed and the
+modules that rely on that.  Perhaps we have to do that for DOI, too.
+This approach seem to work better but does not solve the problem of
+function scopes.
 
-Eliminating `get_base_type`
----------------------------
-
-There are some methods that basic types objects should implement.
-I propose to add new classes for preventing direct access to
-`get_base_type`.
-
-We can use ``isinstance(x, Function)`` instead of
-``x.get_type() == get_base_type('Function')``.
-
-As you see the only reason for the existence of these new classes is
-documentation.  The other advantage is better distinction between
-between defined objects and others.  Actually these new classes
-should have been interfaces but currently python does not support
-them.
-
-These changes will ease adding docs to builtin types.
+Currently analyze module is changed to invalidate concluded data
+both before and after analyzing modules.
 
 
 Function Scopes
 scope.  Maybe we can change pynames to support function scopes.
 
 
-Static Returned Object Inference
---------------------------------
-
-Since we're passed the object parameters hold, we can perform a
-better returned object SOI.  We can do that by giving parameters
-the passed objects and infer the object of local names once more.
-
-Actually we have to perform two things.  We have to ask scope
-`PyName`\s to forget their concluded data and change the
-parameters to return what we want.
-
-* Parameterizing function scope names to their parameters objects
-* Caching old result
-* Merging information with DOI
-
-
-Holding Per Name Information
-----------------------------
-
-We can change our type DB to add new feature.::
-
-  objectdb.add_per_object(pyname, function_name, parameters)
-
-Our main problem is how to save the `PyName`\s.
-Our object DB can save the information based on the definition
-location and the name of the passed pyname. (What to do for
-``self.x, x = d``?)
-
-* Forcing `create_arguments` to pass the implicit object for
-  builtin functions.
-
-
 Invalidating Object DB Data
 ---------------------------
 
 Or maybe we can use a strategy object for searching.
 
 
+Getting ready for Python 3.0
+============================
+
+* Changing print to function in tests
+* Not supporting old relative imports
+* `iter.__next__()` instead of `iter.next()`
+* Supporting `bytes`, `input`
+* Removing nonexistent dict methods and methods that will return sets
+* Chaning imports after library reorganization
+* Show function annotations in pydocs
+* ``nonlocal``
+* ``except xxx as yyy``
+* ``...``
+* Supporting keyword only arguments
+* Set literals and comprehension ``{1, 2, 3}`` and ``{x for x in range(10)}``
+* Renamed function attributes; ``f.func_whatever`` to ``f.__whatever``
+* Use new function signature
+
+
 Allowing Non-Existent Resources
 ===============================
 

docs/dev/stories.txt

 
 
 > Public Release 0.5m3 : March 18, 2007
-
-
-* Enhanced returned object static object inference
-
-
-* Enhanced parameter static object inference

docs/dev/workingon.txt

-Better Parameter SOI
-====================
+Better Returned Object SOI
+==========================
 
-- Preventing OI recursions
+- Problems for from import invalidation
+- Implementing `AbstractXxx.get_doc()`
+- Adding `object` and `type` builtins
+- Docs for builtin functions
+- Checking `PyDefinedObject._get_ast()` usages
+- Adding `AbstractClass.get_name()` and `AbstractFunction.get_name()`
+- Not using `PyFunction.parameters`
+- Handling ``*args`` and ``**kwds`` arguments
+- Returned object SOI
+- Returning different values with args
+- Fixing DOI tests that passed because of enhanced SOI
+- Saving back in our callinfo
 
-* Eliminating `get_base_type()`
-* Using `AbstractXxx.get_doc()`
+* Should `ParameterName` save information?
+
 * What to do about 'Unknown' base type
-* Docs for builtin functions and properties
-* Cleaning up `pyobjects`
-* Checking `PyDefinedObject._get_ast()` usages
+* Either changing all `None` pynames to unknowns or the reverse
+
+* Removing occurrences of to ``pyfunction._get_ast().flags``
+* Not sending ``*args`` and ``**kwds`` in DOI
+* Not proposing invalid textuals in `_CallInformationOrganizer`
+* Cleaning up `rope.base.pyobjects`
 * Renaming `PyDefinedObject._get_ast()` to `get_ast()`
+* Is `rope.base` supposed to be thread safe?  which parts?
 
+* Evaluate function parameter defaults in staticoi?
 * Is throwing `IsBeingInferredException` a good thing?  Can't we
   return something instead?
 * Duplication between `AssignedName` and `EvaluatedName`, `PyFunction`
 * Not ignoring the first argument for builtin types
 * What to do for builtin functions
 
-* Adding `object` base object
-* Adding `object` and `type` builtins
+* Generator list comprehension support
 * Showing the pydoc of superclass methods in show pydoc if it overrides them
+* Showing superclass show pydoc
 * Update `rope.base.oi` docs
-* Invalidating old concluded data
 * Using sqlite3 to prevent holding information in memory? mocks?
 * Enhancing object textual form to include new types
-* Goto definition for builtins raises exception
-* `evalutate.get...` was changed to `rope.base.evaluate.get...` in moving
-* Move failed to import old module
 
 * ``enable_doi`` config
 * Completion in module entries
 * Faster find file in large projects
 * Decorators and method refactorings
-* Unifying ``x.get_type() == get_base_type('y')``, ``isinstance(x, PyY)``
 * Document how to move fields
 
 
 * Showing properties in quick outline
 * Changing ``C-a C-a`` to move to the first character in the line
 * ``M-a`` and ``M-e``
+* ``C-l`` and ``M-r``
 * Comments should be indented
 * Decide when to use `difflib` in `Editor.set_text` based on the
   number of changes

rope/base/builtins.py

     return _get_builtin
 
 
-class List(pyobjects.AbstractClass):
+class BuiltinClass(pyobjects.AbstractClass):
+
+    def __init__(self, builtin):
+        super(BuiltinClass, self).__init__()
+        self.builtin = builtin
+
+    def get_doc(self):
+        return self.builtin.__doc__
+
+    def get_name(self):
+        return self.builtin.__name__
+
+
+class List(BuiltinClass):
 
     def __init__(self, holding=None):
-        super(List, self).__init__()
+        super(List, self).__init__(list)
         self.holding = holding
-        self.attributes = {
-            '__getitem__': BuiltinName(BuiltinFunction(self.holding)),
-            '__getslice__': BuiltinName(BuiltinFunction(pyobjects.PyObject(self))),
-            'pop': BuiltinName(BuiltinFunction(self.holding)),
-            '__iter__': BuiltinName(BuiltinFunction(Iterator(self.holding))),
-            '__new__': BuiltinName(BuiltinFunction(function=self._new_list)),
-            'append': BuiltinName(BuiltinFunction()),
-            'count': BuiltinName(BuiltinFunction()),
-            'extend': BuiltinName(BuiltinFunction()),
-            'index': BuiltinName(BuiltinFunction()),
-            'insert': BuiltinName(BuiltinFunction()),
-            'remove': BuiltinName(BuiltinFunction()),
-            'reverse': BuiltinName(BuiltinFunction()),
-            'sort': BuiltinName(BuiltinFunction())}
+        self.attributes = {}
+        def add(name, returned=None, function=None):
+            self.attributes[name] = BuiltinName(
+                BuiltinFunction(returned=returned, function=function,
+                                builtin=getattr(list, name)))
+
+        add('__getitem__', self.holding)
+        add('__getslice__', pyobjects.PyObject(self))
+        add('pop', self.holding)
+        add('__iter__', Iterator(self.holding))
+        add('__new__', function=self._new_list)
+        add('append')
+        add('count')
+        add('extend')
+        add('index')
+        add('insert')
+        add('remove')
+        add('reverse')
+        add('sort')
 
     def _new_list(self, args):
         return _create_builtin(args, get_list)
     def get_attributes(self):
         return self.attributes
 
+
 get_list = _create_builtin_getter(List)
 get_list_type = _create_builtin_type_getter(List)
 
 
-class Dict(pyobjects.AbstractClass):
+class Dict(BuiltinClass):
 
     def __init__(self, keys=None, values=None):
-        super(Dict, self).__init__()
+        super(Dict, self).__init__(dict)
         self.keys = keys
         self.values = values
         item = get_tuple(self.keys, self.values)
-        self.attributes = {
-            '__getitem__': BuiltinName(BuiltinFunction(self.values)),
-            '__iter__': BuiltinName(BuiltinFunction(Iterator(self.keys))),
-            '__new__': BuiltinName(BuiltinFunction(function=self._new_dict)),
-            'pop': BuiltinName(BuiltinFunction(self.values)),
-            'get': BuiltinName(BuiltinFunction(self.keys)),
-            'keys': BuiltinName(BuiltinFunction(List(self.keys))),
-            'values': BuiltinName(BuiltinFunction(List(self.values))),
-            'iterkeys': BuiltinName(BuiltinFunction(Iterator(self.keys))),
-            'itervalues': BuiltinName(BuiltinFunction(Iterator(self.values))),
-            'items': BuiltinName(BuiltinFunction(List(item))),
-            'iteritems': BuiltinName(BuiltinFunction(Iterator(item))),
-            'copy': BuiltinName(BuiltinFunction(pyobjects.PyObject(self))),
-            'clear': BuiltinName(BuiltinFunction()),
-            'has_key': BuiltinName(BuiltinFunction()),
-            'popitem': BuiltinName(BuiltinFunction()),
-            'setdefault': BuiltinName(BuiltinFunction()),
-            'update': BuiltinName(BuiltinFunction())}
+        self.attributes = {}
+        def add(name, returned=None, function=None):
+            self.attributes[name] = BuiltinName(
+                BuiltinFunction(returned=returned, function=function,
+                                builtin=getattr(dict, name)))
+        add('__getitem__', self.values)
+        add('__iter__', Iterator(self.keys))
+        add('__new__', function=self._new_dict)
+        add('pop', self.values)
+        add('get', self.keys)
+        add('keys', List(self.keys))
+        add('values', List(self.values))
+        add('iterkeys', Iterator(self.keys))
+        add('itervalues', Iterator(self.values))
+        add('items', List(item))
+        add('iteritems', Iterator(item))
+        add('copy', pyobjects.PyObject(self))
+        add('clear')
+        add('has_key')
+        add('popitem')
+        add('setdefault')
+        add('update')
 
     def get_attributes(self):
         return self.attributes
 get_dict_type = _create_builtin_type_getter(Dict)
 
 
-class Tuple(pyobjects.AbstractClass):
+class Tuple(BuiltinClass):
 
     def __init__(self, *objects):
-        super(Tuple, self).__init__()
+        super(Tuple, self).__init__(tuple)
         self.objects = objects
         first = None
         if objects:
 get_tuple_type = _create_builtin_type_getter(Tuple)
 
 
-class Set(pyobjects.AbstractClass):
+class Set(BuiltinClass):
 
     def __init__(self, holding=None):
-        super(Set, self).__init__()
+        super(Set, self).__init__(set)
         self.holding = holding
-        self.attributes = {
-            'pop': BuiltinName(BuiltinFunction(self.holding)),
-            '__iter__': BuiltinName(BuiltinFunction(Iterator(self.holding))),
-            '__new__': BuiltinName(BuiltinFunction(function=self._new_set)),
-            'add': BuiltinName(BuiltinFunction()),
-            'copy': BuiltinName(BuiltinFunction(pyobjects.PyObject(self))),
-            'difference': BuiltinName(BuiltinFunction(pyobjects.PyObject(self))),
-            'intersection': BuiltinName(BuiltinFunction(pyobjects.PyObject(self))),
-            'difference_update': BuiltinName(BuiltinFunction()),
-            'symmetric_difference': BuiltinName(BuiltinFunction(pyobjects.PyObject(self))),
-            'symmetric_difference_update': BuiltinName(BuiltinFunction()),
-            'union': BuiltinName(BuiltinFunction(pyobjects.PyObject(self))),
-            'discard': BuiltinName(BuiltinFunction()),
-            'remove': BuiltinName(BuiltinFunction()),
-            'issuperset': BuiltinName(BuiltinFunction()),
-            'issubset': BuiltinName(BuiltinFunction()),
-            'clear': BuiltinName(BuiltinFunction()),
-            'update': BuiltinName(BuiltinFunction())}
+        self.attributes = {}
+        def add(name, returned=None, function=None):
+            self.attributes[name] = BuiltinName(
+                BuiltinFunction(returned=returned, function=function,
+                                builtin=getattr(set, name)))
+        add('pop', self.holding)
+        add('__iter__', Iterator(self.holding))
+        add('__new__', function=self._new_set)
+        add('add')
+        add('copy', pyobjects.PyObject(self))
+        add('difference', pyobjects.PyObject(self))
+        add('intersection', pyobjects.PyObject(self))
+        add('difference_update'),
+        add('symmetric_difference', pyobjects.PyObject(self))
+        add('symmetric_difference_update')
+        add('union', pyobjects.PyObject(self))
+        add('discard')
+        add('remove')
+        add('issuperset')
+        add('issubset')
+        add('clear')
+        add('update')
 
     def get_attributes(self):
         return self.attributes
 
+    def get_doc(self):
+        return set.__doc__
+
     def _new_set(self, args):
         return _create_builtin(args, get_set)
 
 get_set_type = _create_builtin_type_getter(Set)
 
 
-class Str(pyobjects.AbstractClass):
+class Str(BuiltinClass):
 
     def __init__(self):
-        super(Str, self).__init__()
+        super(Str, self).__init__(str)
         self_object = pyobjects.PyObject(self)
-        self.attributes = {
-            '__getitem__': BuiltinName(BuiltinFunction(self_object)),
-            '__getslice__': BuiltinName(BuiltinFunction(self_object)),
-            '__iter__': BuiltinName(BuiltinFunction(Iterator(self_object))),
-            'captialize': BuiltinName(BuiltinFunction(self_object)),
-            'center': BuiltinName(BuiltinFunction(self_object)),
-            'count': BuiltinName(BuiltinFunction()),
-            'decode': BuiltinName(BuiltinFunction(self_object)),
-            'encode': BuiltinName(BuiltinFunction(self_object)),
-            'endswith': BuiltinName(BuiltinFunction()),
-            'expandtabs': BuiltinName(BuiltinFunction(self_object)),
-            'find': BuiltinName(BuiltinFunction()),
-            'index': BuiltinName(BuiltinFunction()),
-            'isalnum': BuiltinName(BuiltinFunction()),
-            'isalpha': BuiltinName(BuiltinFunction()),
-            'isdigit': BuiltinName(BuiltinFunction()),
-            'islower': BuiltinName(BuiltinFunction()),
-            'isspace': BuiltinName(BuiltinFunction()),
-            'istitle': BuiltinName(BuiltinFunction()),
-            'isupper': BuiltinName(BuiltinFunction()),
-            'join': BuiltinName(BuiltinFunction(self_object)),
-            'ljust': BuiltinName(BuiltinFunction(self_object)),
-            'lower': BuiltinName(BuiltinFunction(self_object)),
-            'lstrip': BuiltinName(BuiltinFunction(self_object)),
-            'replace': BuiltinName(BuiltinFunction(self_object)),
-            'rfind': BuiltinName(BuiltinFunction()),
-            'rindex': BuiltinName(BuiltinFunction()),
-            'rjust': BuiltinName(BuiltinFunction(self_object)),
-            'rsplit': BuiltinName(BuiltinFunction(get_list(self_object))),
-            'rstrip': BuiltinName(BuiltinFunction(self_object)),
-            'split': BuiltinName(BuiltinFunction(get_list(self_object))),
-            'splitlines': BuiltinName(BuiltinFunction(get_list(self_object))),
-            'startswith': BuiltinName(BuiltinFunction(self_object)),
-            'strip': BuiltinName(BuiltinFunction(self_object)),
-            'swapcase': BuiltinName(BuiltinFunction(self_object)),
-            'title': BuiltinName(BuiltinFunction(self_object)),
-            'translate': BuiltinName(BuiltinFunction(self_object)),
-            'upper': BuiltinName(BuiltinFunction(self_object)),
-            'zfill': BuiltinName(BuiltinFunction(self_object))}
+        self.attributes = {}
+        def add(name, returned=None, function=None):
+            builtin = getattr(str, name, None)
+            self.attributes[name] = BuiltinName(
+                BuiltinFunction(returned=returned, function=function, builtin=builtin))
+        add('__getitem__', self_object)
+        add('__getslice__', self_object)
+        add('__iter__', Iterator(self_object))
+	add('captialize', self_object)
+        add('center', self_object)
+        add('count'),
+        add('decode', self_object)
+        add('encode', self_object)
+        add('endswith')
+        add('expandtabs', self_object)
+        add('find')
+        add('index')
+        add('isalnum')
+        add('isalpha')
+        add('isdigit')
+        add('islower')
+        add('isspace')
+        add('istitle')
+        add('isupper')
+        add('join', self_object)
+        add('ljust', self_object)
+        add('lower', self_object)
+        add('lstrip', self_object)
+        add('replace', self_object)
+        add('rfind')
+        add('rindex')
+        add('rjust', self_object)
+        add('rsplit', get_list(self_object))
+        add('rstrip', self_object)
+        add('split', get_list(self_object))
+        add('splitlines', get_list(self_object))
+        add('startswith', self_object)
+        add('strip', self_object)
+        add('swapcase', self_object)
+        add('title', self_object)
+        add('translate', self_object)
+        add('upper', self_object)
+        add('zfill', self_object)
 
     def get_attributes(self):
         return self.attributes
 
+    def get_doc(self):
+        return str.__doc__
+
+
 get_str = _create_builtin_getter(Str)
 get_str_type = _create_builtin_type_getter(Str)
 
     def get_object(self):
         return self.pyobject
 
+    def get_definition_location(self):
+        return (None, None)
 
 class BuiltinFunction(pyobjects.AbstractFunction):
 
-    def __init__(self, returned=None, function=None):
+    def __init__(self, returned=None, function=None, builtin=None):
         super(BuiltinFunction, self).__init__()
         self.returned = returned
         self.function = function
+        self.builtin = builtin
 
     def get_returned_object(self, args=None):
         if self.function is not None:
             return self.function(args)
         return self.returned
 
+    def get_doc(self):
+        if self.builtin:
+            return self.builtin.__doc__
+
+    def get_name(self):
+        if self.builtin:
+            return self.builtin.__name__
+
 
 class Iterator(pyobjects.AbstractClass):
 
         return self.holding
 
 
-class File(pyobjects.AbstractClass):
-    
+class File(BuiltinClass):
+
     def __init__(self):
-        super(File, self).__init__()
+        super(File, self).__init__(file)
         self_object = pyobjects.PyObject(self)
         str_object = get_str()
         str_list = get_list(get_str())
-        self.attributes = {
-            '__iter__': BuiltinName(BuiltinFunction(Iterator(str_object))),
-            'close': BuiltinName(BuiltinFunction()),
-            'flush': BuiltinName(BuiltinFunction()),
-            'lineno': BuiltinName(BuiltinFunction()),
-            'isatty': BuiltinName(BuiltinFunction()),
-            'next': BuiltinName(BuiltinFunction(str_object)),
-            'read': BuiltinName(BuiltinFunction(str_object)),
-            'readline': BuiltinName(BuiltinFunction(str_object)),
-            'readlines': BuiltinName(BuiltinFunction(str_list)),
-            'seek': BuiltinName(BuiltinFunction()),
-            'tell': BuiltinName(BuiltinFunction()),
-            'truncate': BuiltinName(BuiltinFunction()),
-            'write': BuiltinName(BuiltinFunction()),
-            'writelines': BuiltinName(BuiltinFunction())}
+        self.attributes = {}
+        def add(name, returned=None, function=None):
+            builtin = getattr(file, name, None)
+            self.attributes[name] = BuiltinName(
+                BuiltinFunction(returned=returned, function=function, builtin=builtin))
+        add('__iter__')
+        add('close')
+        add('flush')
+        add('lineno')
+        add('isatty')
+        add('next', str_object)
+        add('read', str_object)
+        add('readline', str_object)
+        add('readlines', str_list)
+        add('seek')
+        add('tell')
+        add('truncate')
+        add('write')
+        add('writelines')
 
     def get_attributes(self):
         return self.attributes
 
+    def get_doc(self):
+        return file.__doc__
+
 get_file = _create_builtin_getter(File)
 get_file_type = _create_builtin_type_getter(File)
 
 
-class Property(pyobjects.AbstractClass):
+class Property(BuiltinClass):
 
     def __init__(self, fget=None, fset=None, fdel=None, fdoc=None):
-        super(Property, self).__init__()
+        super(Property, self).__init__(property)
         self._fget = fget
+        self._fdoc = fdoc
         self.attributes = {
             'fget': BuiltinName(BuiltinFunction()),
             'fset': BuiltinName(BuiltinFunction()),
         return {}
 
 
+class BuiltinObject(BuiltinClass):
+
+    def __init__(self):
+        super(BuiltinObject, self).__init__(object)
+
+
+class BuiltinType(BuiltinClass):
+
+    def __init__(self):
+        super(BuiltinType, self).__init__(type)
+
+
 def _infer_sequence_type(seq):
     if '__iter__' in seq.get_attributes():
         iter = seq.get_attribute('__iter__').get_object().\
     'file': BuiltinName(get_file_type()),
     'open': BuiltinName(get_file_type()),
     'unicode': BuiltinName(get_str_type()),
-    'range': BuiltinName(BuiltinFunction(function=_range_function)),
-    'reversed': BuiltinName(BuiltinFunction(function=_reversed_function)),
-    'sorted': BuiltinName(BuiltinFunction(function=_sorted_function)),
-    'super': BuiltinName(BuiltinFunction(function=_super_function)),
-    'property': BuiltinName(BuiltinFunction(function=_property_function)),
-    'zip': BuiltinName(BuiltinFunction(function=_zip_function)),
-    'enumerate': BuiltinName(BuiltinFunction(function=_enumerate_function))}
+    'range': BuiltinName(BuiltinFunction(function=_range_function, builtin=range)),
+    'reversed': BuiltinName(BuiltinFunction(function=_reversed_function, builtin=reversed)),
+    'sorted': BuiltinName(BuiltinFunction(function=_sorted_function, builtin=sorted)),
+    'super': BuiltinName(BuiltinFunction(function=_super_function, builtin=super)),
+    'property': BuiltinName(BuiltinFunction(function=_property_function, builtin=property)),
+    'zip': BuiltinName(BuiltinFunction(function=_zip_function, builtin=zip)),
+    'enumerate': BuiltinName(BuiltinFunction(function=_enumerate_function, builtin=enumerate)),
+    'object': BuiltinName(BuiltinObject()),
+    'type': BuiltinName(BuiltinType())}

rope/base/oi/callinfo.py

+import compiler.consts
 import os
 import re
 
         self.to_textual = _PyObjectToTextual(pycore.project)
         self.to_pyobject = _TextualToPyObject(pycore.project)
 
-    def get_returned_object(self, pyobject, args):
+    def get_returned(self, pyobject, args):
         organizer = self.find_organizer(pyobject)
         if organizer:
-            return self.to_pyobject.transform(organizer.get_returned_object(
+            return self.to_pyobject.transform(organizer.get_returned(
                                               pyobject, args))
 
+    def get_exact_returned(self, pyobject, args):
+        organizer = self.find_organizer(pyobject)
+        if organizer:
+            return self.to_pyobject.transform(
+                organizer.get_exact_returned(pyobject, args))
+
     def get_parameter_objects(self, pyobject):
         organizer = self.find_organizer(pyobject)
         if organizer is not None:
     def doi_data_received(self, data):
         self._save_data(data[0], data[1], data[2])
 
-    def function_called(self, pyfunction, params):
+    def function_called(self, pyfunction, params, returned=None):
         function_text = self.to_textual.transform(pyfunction)
         params_text = tuple([self.to_textual.transform(param)
                              for param in params])
-        self._save_data(function_text, params_text)
+        returned_text = ('unknown',)
+        if returned is not None:
+            returned_text = self.to_textual.transform(returned)
+        self._save_data(function_text, params_text, returned_text)
 
     def _save_data(self, function, args, returned=('unknown',)):
         path = function[1]
                 return args
         return self.info.keys()[0]
 
-    def get_returned_object(self, pyfunction, args):
-        if len(self.info) <= 1 or args is None:
-            return self._get_default_returned()
-        parameters = list(pyfunction.parameters)
-        if pyfunction._get_ast().flags & 0x4:
+    def get_returned(self, pyfunction, args):
+        result = self.get_exact_returned(pyfunction, args)
+        if result != ('unknown',):
+            return result
+        return self._get_default_returned()
+
+    def get_exact_returned(self, pyfunction, args):
+        if len(self.info) == 0 or args is None:
+            return ('unknown',)
+        parameters = list(pyfunction.get_param_names())
+        if pyfunction._get_ast().flags & compiler.consts.CO_VARKEYWORDS:
             del parameters[-1]
-        if pyfunction._get_ast().flags & 0x8:
+        if pyfunction._get_ast().flags & compiler.consts.CO_VARARGS:
             del parameters[-1]
         arguments = args.get_arguments(parameters)[:len(parameters)]
         textual_args = tuple([self.to_textual.transform(arg)
                               for arg in arguments])
-        if textual_args in self.info:
+        if self.info.get(textual_args, ('unknown',)) != ('unknown',):
             return self.info[textual_args]
-        return self._get_default_returned()
+        return ('unknown',)
 
     def _get_default_returned(self):
-        default = ('unknown')
         for returned in self.info.values():
-            if returned not in ('unknown', 'none'):
+            if returned[0] not in ('unknown'):
                 return returned
-            default = returned
-        return default
+        return ('unknown',)
 
 
 class _PyObjectToTextual(object):
 
     def PyClass_to_textual(self, pyobject):
         return ('class', self._get_pymodule_path(pyobject.get_module()),
-                pyobject._get_ast().name)
+                pyobject.get_name())
 
     def PyModule_to_textual(self, pyobject):
         return ('module', self._get_pymodule_path(pyobject))

rope/base/oi/dynamicoi.py

         self.info = pycore.call_info
 
     def infer_returned_object(self, pyobject, args):
-        return self.info.get_returned_object(pyobject, args)
+        return self.info.get_returned(pyobject, args)
 
     def infer_parameter_objects(self, pyobject):
         return self.info.get_parameter_objects(pyobject)

rope/base/oi/objectinfer.py

     def __init__(self, pycore):
         self.soi = staticoi.StaticObjectInference(pycore)
         self.doi = dynamicoi.DynamicObjectInference(pycore)
+        self.call_info = pycore.call_info
         self.ois = [self.soi, self.doi]
 
     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
+        result = self.call_info.get_exact_returned(pyobject, args)
+        if result is not None:
+            return result
+        result = self.soi.infer_returned_object(pyobject, args)
+        if result is not None:
+            if args and pyobject.get_module().get_resource() is not None:
+                params = args.get_arguments(self.soi._get_normal_params(pyobject))
+                self.call_info.function_called(pyobject, params, result)
+            return result
+        return self.call_info.get_returned(pyobject, args)
 
     def infer_parameter_objects(self, pyobject):
         """Infer the `PyObject`\s of parameters of this callable `PyObject`"""

rope/base/oi/staticoi.py

 import compiler.ast
+import compiler.consts
 
 import rope.base
 from rope.base import pyobjects, evaluate
         self.pycore = pycore
 
     def infer_returned_object(self, pyobject, args):
+        if args:
+            # HACK: Setting parameter objects manually
+            # This is not thread safe and might cause problems if `args`
+            # is not a good call example
+            pyobject._set_parameter_pyobjects(
+                args.get_arguments(self._get_normal_params(pyobject)))
         scope = pyobject.get_scope()
         if not scope._get_returned_asts():
             return
                 objects.append(self._get_unknown())
             elif self._is_classmethod_decorator(pyobject.decorators.nodes[0]):
                 objects.append(pyobject.parent)
-            elif pyobject.parameters[0] == 'self':
+            elif pyobject.get_param_names()[0] == 'self':
                 objects.append(pyobjects.PyObject(pyobject.parent))
-            else:
-                objects.append(self._get_unknown())
-        else:
-            objects.append(self._get_unknown())
-        for parameter in pyobject.parameters[1:]:
+        params = self._get_normal_params(pyobject)
+        for parameter in params[len(objects):]:
             objects.append(self._get_unknown())
         return objects
 
+    def _get_normal_params(self, pyobject):
+        node = pyobject._get_ast()
+        params = list(node.argnames)
+        if node.flags & compiler.consts.CO_VARKEYWORDS:
+            del params[-1]
+        if node.flags & compiler.consts.CO_VARARGS:
+            del params[-1]
+        return params
+
     def _get_unknown(self):
         return pyobjects.PyObject(pyobjects.get_base_type('Unknown'))
 
             return
         args = evaluate.create_arguments(pyfunction, node, scope)
         self.pycore.call_info.function_called(
-            pyfunction, args.get_arguments(pyfunction.parameters))
+            pyfunction, args.get_arguments(pyfunction.get_param_names()))

rope/base/pycore.py

 
         """
         pymodule = self.resource_to_pyobject(resource)
+        pymodule._invalidate_concluded_data()
         self.object_infer.soi.analyze_module(pymodule)
+        pymodule._invalidate_concluded_data()
 
     def get_subclasses(self, pyclass):
         if self.classes is None:

rope/base/pynames.py

     def __init__(self, pyfunction, index):
         self.pyfunction = pyfunction
         self.index = index
-        self.pyobject = _get_concluded_data(self.pyfunction.get_module())
 
     def get_object(self):
-        if self.pyobject.get() is None:
-            self.pyobject.set(self.pyfunction.get_parameter(self.index))
-        if self.pyobject.get() is None:
-            self.pyobject.set(rope.base.pyobjects.PyObject(
-                              rope.base.pyobjects.get_base_type('Unknown')))
-        return self.pyobject.get()
+        result = self.pyfunction.get_parameter(self.index)
+        if result is None:
+            result = rope.base.pyobjects.PyObject(
+                rope.base.pyobjects.get_base_type('Unknown'))
+        return result
 
     def get_definition_location(self):
         return (self.pyfunction.get_module(), self.pyfunction._get_ast().lineno)
             pycore = self.importing_module.pycore
             if self.resource is not None:
                 self.pymodule.set(pycore.resource_to_pyobject(self.resource))
-                self.pymodule.get()._add_dependant(self.importing_module)
             elif self.module_name is not None:
                 try:
                     if self.level == 0:
                                           self.level))
                 except ModuleNotFoundError:
                     pass
+            if self.pymodule.get() is not None:
+                self.pymodule.get()._add_dependant(self.importing_module)
         return self.pymodule.get()
 
     def get_object(self):

rope/base/pyobjects.py

     def __init__(self):
         super(AbstractClass, self).__init__(get_base_type('Type'))
 
+    def get_name(self):
+        pass
+
     def get_doc(self):
         pass
 
     def __init__(self):
         super(AbstractFunction, self).__init__(get_base_type('Function'))
 
+    def get_name(self):
+        pass
+
     def get_doc(self):
         pass
 
             current_object = current_object.parent
         return current_object
 
+    def get_doc(self):
+        return self._get_ast().doc
+
     def _create_structural_attributes(self):
         return {}
 
         self.is_being_inferred = False
         self.are_args_being_inferred = False
         self.parameter_pyobjects = self.get_module()._get_concluded_data()
-        self.parameter_pynames = self.get_module()._get_concluded_data()
+        self.parameter_pynames = None
 
     def _create_structural_attributes(self):
         return {}
             self.are_args_being_inferred = False
         return pyobjects
 
+    def _set_parameter_pyobjects(self, pyobjects):
+        if len(pyobjects) < len(self.parameters):
+            if self._get_ast().flags & 0x4:
+                pyobjects.append(rope.base.builtins.get_list())
+            if self._get_ast().flags & 0x8:
+                pyobjects.append(rope.base.builtins.get_dict())
+        self.parameter_pyobjects.set(pyobjects)
+
     def get_parameters(self):
-        if self.parameter_pynames.get() is None:
+        if self.parameter_pynames is None:
             result = {}
             for index, name in enumerate(self.parameters):
                 result[name] = ParameterName(self, index)
-            self.parameter_pynames.set(result)
-        return self.parameter_pynames.get()
+            self.parameter_pynames = result
+        return self.parameter_pynames
 
     def get_parameter(self, index):
         if not self.parameter_pyobjects.get():
-            self.parameter_pyobjects.set(self._get_parameter_pyobjects())
+            self._set_parameter_pyobjects(self._get_parameter_pyobjects())
         return self.parameter_pyobjects.get()[index]
 
     def get_returned_object(self, args=None):
             return PyObject(get_base_type('Unknown'))
         return result
 
+    def get_name(self):
+        return self._get_ast().name
+
+    def get_param_names(self):
+        return self.parameters
+
 
 class PyClass(PyDefinedObject, AbstractClass):
 
             self._superclasses = self._get_bases()
         return self._superclasses
 
+    def get_name(self):
+        return self._get_ast().name
+
     def _create_structural_attributes(self):
         new_visitor = _ClassVisitor(self.pycore, self)
         for n in self.ast_node.getChildNodes():

rope/ide/codeassist.py

             return 'variable'
         if isinstance(pyname, pynames.DefinedName):
             pyobject = pyname.get_object()
-            if isinstance(pyobject, pyobjects.PyFunction):
+            if isinstance(pyobject, pyobjects.AbstractFunction):
                 return 'function'
             else:
                 return 'class'
                 return {}
             if function_pyname is not None:
                 pyobject = function_pyname.get_object()
-                if isinstance(pyobject, pyobjects.PyFunction):
+                if isinstance(pyobject, pyobjects.AbstractFunction):
                     pass
                 elif isinstance(pyobject, pyobjects.AbstractClass) and \
                      '__init__' in pyobject.get_attributes():
                     pyobject = pyobject.get_attribute('__init__').get_object()
                 elif '__call__' in pyobject.get_attributes():
                     pyobject = pyobject.get_attribute('__call__').get_object()
-                if isinstance(pyobject, pyobjects.PyFunction):
-                    function_info = functionutils.DefinitionInfo.read(pyobject)
+                if isinstance(pyobject, pyobjects.AbstractFunction):
+                    param_names = []
+                    if isinstance(pyobject, pyobjects.PyFunction):
+                        function_info = functionutils.DefinitionInfo.read(pyobject)
+                        param_names.extend([name for name, default
+                                            in function_info.args_with_defaults])
+                    else:
+                        param_names = pyobject.get_param_names()
                     result = {}
-                    for name, default in function_info.args_with_defaults:
+                    for name in param_names:
                         if name.startswith(self.starting):
                             result[name + '='] = CompletionProposal(
                                 name + '=', 'parameter_keyword')
         if element is None:
             return None
         pyobject = element.get_object()
-        if isinstance(pyobject, pyobjects.PyDefinedObject):
-            if isinstance(pyobject, pyobjects.PyFunction):
-                return _get_function_docstring(pyobject)
-            elif isinstance(pyobject, pyobjects.PyClass):
-                return _get_class_docstring(pyobject)
-            else:
-                return _trim_docstring(pyobject._get_ast().doc)
+        if isinstance(pyobject, pyobjects.AbstractFunction):
+            return _get_function_docstring(pyobject)
+        elif isinstance(pyobject, pyobjects.AbstractClass):
+            return _get_class_docstring(pyobject)
+        elif isinstance(pyobject, pyobjects.AbstractModule):
+            return _trim_docstring(pyobject.get_doc())
         return None
 
     def find_occurrences(self, resource, offset):
     return pycore.get_string_module(source_code, resource=resource)
 
 def _get_class_docstring(pyclass):
-    node = pyclass._get_ast()
-    doc = 'class %s\n\n' % node.name + _trim_docstring(node.doc)
+    doc = 'class %s\n\n' % pyclass.get_name() + _trim_docstring(pyclass.get_doc())
 
     if '__init__' in pyclass.get_attributes():
         init = pyclass.get_attribute('__init__').get_object()
-        if isinstance(init, pyobjects.PyDefinedObject):
+        if isinstance(init, pyobjects.AbstractFunction):
             doc += '\n\n' + _get_function_docstring(init)
     return doc
 
 def _get_function_docstring(pyfunction):
     signature = _get_function_signature(pyfunction)
 
-    return signature + '\n\n' + _trim_docstring(pyfunction._get_ast().doc)
+    return signature + '\n\n' + _trim_docstring(pyfunction.get_doc())
 
 def _get_function_signature(pyfunction):
-    info = functionutils.DefinitionInfo.read(pyfunction)
-    return info.to_string()
+    if isinstance(pyfunction, pyobjects.PyFunction):
+        info = functionutils.DefinitionInfo.read(pyfunction)
+        return info.to_string()
+    else:
+        return '%s(%s)' % (pyfunction.get_name(),
+                           ', '.join(pyfunction.get_param_names()))
 
 def _trim_docstring(docstring):
     """The sample code from :PEP:`257`"""

rope/refactor/functionutils.py

 import rope.base.exceptions
 import rope.base.pyobjects
+import compiler.consts
 from rope.base import codeanalyze
 
 
     def _read(pyfunction, code):
         scope = pyfunction.get_scope()
         parent = scope.parent
-        parameter_names = pyfunction.parameters
+        parameter_names = pyfunction.get_param_names()
         is_method = len(parameter_names) > 0 and \
                     (parent is not None and parent.pyobject == pyfunction.
                      get_parameters()[parameter_names[0]].get_object().get_type()) and \

rope/refactor/inline.py

         return paramdict
 
     def get_function_name(self):
-        return self.pyfunction._get_ast().name
+        return self.pyfunction.get_name()
 
     def get_definition(self, call, returns=False):
         # caching already calculated definitions

rope/refactor/introduce_factory.py

            not isinstance(self.old_pyname.get_object(), rope.base.pyobjects.PyClass):
             raise rope.base.exceptions.RefactoringError(
                 'Introduce factory should be performed on a class.')
-        self.old_name = self.old_pyname.get_object()._get_ast().name
+        self.old_name = self.old_pyname.get_object().get_name()
         self.pymodule = self.old_pyname.get_object().get_module()
         self.resource = self.pymodule.get_resource()
 

rope/refactor/localtofield.py

                 'The field %s already exists' % name)
 
     def _get_field_name(self, pyfunction, name):
-        self_name = pyfunction.parameters[0]
+        self_name = pyfunction.get_param_names()[0]
         new_name = self_name + '.' + name
         return new_name
 

rope/refactor/method_object.py

         return '%s\n%s\n' % (header, body)
 
     def _get_parameter_names(self):
-        info = functionutils.DefinitionInfo.read(self.pyfunction)
-        result = []
-        for arg, default in info.args_with_defaults:
-            result.append(arg)
-        if info.args_arg:
-            result.append(info.args_arg)
-        if info.keywords_arg:
-            result.append(info.keywords_arg)
-        return result
+        return self.pyfunction.get_param_names()

rope/refactor/move.py

         return result[result.index('\n') + 1:]
 
     def _get_self_name(self):
-        definition_info = functionutils.DefinitionInfo.read(self.pyfunction)
-        return definition_info.args_with_defaults[0][0]
+        return self.pyfunction.get_param_names()[0]
 
     def _get_new_header(self, name):
         header = 'def %s(self' % name
     def __init__(self, project, resource, offset):
         pycore = project.pycore
         pyname = codeanalyze.get_pyname_at(pycore, resource, offset)
-        old_name = pyname.get_object()._get_ast().name
+        old_name = pyname.get_object().get_name()
         pymodule = pyname.get_object().get_module()
         source = pymodule.get_resource()
 

rope/refactor/occurrences.py

         if type(pyname1) not in (pynames.ImportedModule, pynames.ImportedName) and \
            type(pyname2) not in (pynames.ImportedModule, pynames.ImportedName):
             return False
-        return pyname1.get_object() == pyname2.get_object() and \
-               pyname1.get_definition_location() == pyname2.get_definition_location()
+        return pyname1.get_definition_location() == pyname2.get_definition_location() and \
+               pyname1.get_object() == pyname2.get_object()
 
 
 class _OccurrenceToolsCreator(object):

rope/refactor/sourceutils.py

     lines = pymodule.lines
     logical_lines = codeanalyze.LogicalLineFinder(lines)
     start_line = logical_lines.get_logical_line_in(scope.get_start())[1] + 1
-    if defined._get_ast().doc is not None:
+    if defined.get_doc() is not None:
         start_line = logical_lines.get_logical_line_in(start_line)[1] + 1
     start = lines.get_line_start(start_line)
     end = min(lines.get_line_end(scope.get_end()) + 1,

rope/ui/dot_rope.py

 core.add('templates', ('set_field', "self.${field}${cursor} = ${field}\n"))
 
 
-# Adding you're own `Action`\s:
+# Adding your own `Action`\s:
 # If you're interested in adding your own actions to rope you can do so
-# like this.  For more information see `rope.ui.extension` module.
+# like this.
+# Plugins can use this interface for registering their actions.  For
+# more information see `rope.ui.extension` module.
 
 from rope.ui.extension import SimpleAction
 
 def say_hello(context):
-    print 'Hello Actions!'
+    print 'Hello Action!'
 
 hello_action = SimpleAction('hello_action', say_hello, 'C-h h')
 core.register_action(hello_action)

ropetest/builtintest.py

 
 import rope.base.project
 import ropetest
-from rope.base import pyobjects
+from rope.base import pyobjects, builtins
 
 
 class BuiltinTypesTest(unittest.TestCase):
         a_var = pymod.get_attribute('a_var').get_object()
         self.assertEquals(c_class, a_var.get_type())
 
+    def test_builtin_class_get_name(self):
+        self.assertEquals('object',
+                          rope.base.builtins.builtins['object'].get_object().get_name())
+        self.assertEquals('property',
+                          rope.base.builtins.builtins['property'].get_object().get_name())
+
+    def test_star_args_and_double_star_args(self):
+        self.mod.write('def func(p, *args, **kwds):\n    pass\n')
+        pymod = self.pycore.resource_to_pyobject(self.mod)
+        func_scope = pymod.get_attribute('func').get_object().get_scope()
+        args = func_scope.get_name('args').get_object()
+        kwds = func_scope.get_name('kwds').get_object()
+        self.assertTrue(isinstance(args.get_type(), builtins.List))
+        self.assertTrue(isinstance(kwds.get_type(), builtins.Dict))
+
 
 if __name__ == '__main__':
     unittest.main()

ropetest/codeassisttest.py

         src = 'import mod\nmod'
         self.assertEquals('a module', self.assist.get_doc(src, len(src) - 1))
 
+    def test_get_pydoc_for_builtins(self):
+        src = 'print(object)\n'
+        self.assertTrue(self.assist.get_doc(src, src.index('obj')) is not None)
+
     # TODO: should comment till the end of scope and not block
     def xxx_test_not_proposing_variables_defined_till_the_end_of_scope(self):
         code = 'if True:\n    a_v\na_var = 10\n'
         result = self.assist.assist(code, len(code))
         self.assert_completion_in_result('p=', 'parameter_keyword', result)
 
-    def test_proposing_function_keywords_when_calling_with_no_nothing_after_parens(self):
+    def test_proposing_function_keywords_when_calling_with_no_nothing_after_parens2(self):
         code = 'def f(p):\n    pass\ndef g():\n    h = f\n    f('
         result = self.assist.assist(code, len(code))
         self.assert_completion_in_result('p=', 'parameter_keyword', result)

ropetest/objectinfertest.py

         except RuntimeError, e:
             self.fail(str(e))
 
+    def test_static_oi_for_infering_returned_types_from_functions_based_on_parameters(self):
+        code = 'class C(object):\n    pass\ndef func(p):\n    return p\n' \
+               'a_var = func(C())\n'
+        self.mod.write(code)
+        pymod = self.pycore.resource_to_pyobject(self.mod)
+        c_class = pymod.get_attribute('C').get_object()
+        a_var = pymod.get_attribute('a_var').get_object()
+        self.assertEquals(c_class, a_var.get_type())
+
+    def test_a_function_with_different_returns(self):
+        code = 'class C1(object):\n    pass\nclass C2(object):\n    pass\n' \
+               'def a_func(arg):\n    return arg\n' \
+               'a = a_func(C1())\nb = a_func(C2())\n'
+        self.mod.write(code)
+        pymod = self.pycore.resource_to_pyobject(self.mod)
+        c1_class = pymod.get_attribute('C1').get_object()
+        c2_class = pymod.get_attribute('C2').get_object()
+        a_var = pymod.get_attribute('a').get_object()
+        b_var = pymod.get_attribute('b').get_object()
+        self.assertEquals(c1_class, a_var.get_type())
+        self.assertEquals(c2_class, b_var.get_type())
+
+    # TODO: Requires saving per object data
+    def xxx_test_static_oi_for_lists_depending_on_append_function(self):
+        code = 'class C(object):\n    pass\nl = list()\n' \
+               'l.append(C())\na_var = l[0]\n'
+        self.mod.write(code)
+        self.pycore.analyze_module(self.mod)
+        pymod = self.pycore.resource_to_pyobject(self.mod)
+        c_class = pymod.get_attribute('C').get_object()
+        a_var = pymod.get_attribute('a_var').get_object()
+        self.assertEquals(c_class, a_var.get_type())
+
 
 class DynamicOITest(unittest.TestCase):
 
 
     def test_simple_dti(self):
         mod = self.pycore.create_module(self.project.root, 'mod')
-        code = 'def a_func(arg):\n    return arg\n' \
+        code = 'def a_func(arg):\n    return eval("arg")\n' \
                'a_var = a_func(a_func)\n'
         mod.write(code)
         self.pycore.run_module(mod).wait_process()
     def test_module_dti(self):
         mod1 = self.pycore.create_module(self.project.root, 'mod1')
         mod2 = self.pycore.create_module(self.project.root, 'mod2')
-        code = 'import mod1\ndef a_func(arg):\n    return arg\n' \
+        code = 'import mod1\ndef a_func(arg):\n    return eval("arg")\n' \
                'a_var = a_func(mod1)\n'
         mod2.write(code)
         self.pycore.run_module(mod2).wait_process()
         mod2 = self.pycore.create_module(self.project.root, 'mod2')
         code1 = 'class AClass(object):\n    pass\n'
         code2 = 'from mod1 import AClass\n' \
-               '\ndef a_func(arg):\n    return arg\n' \
+               '\ndef a_func(arg):\n    return eval("arg")\n' \
                'a_var = a_func(AClass)\n'
         mod1.write(code1)
         mod2.write(code2)
     def test_class_dti(self):
         mod = self.pycore.create_module(self.project.root, 'mod')
         code = 'class AClass(object):\n    pass\n' \
-               '\ndef a_func(arg):\n    return arg\n' \
+               '\ndef a_func(arg):\n    return eval("arg")\n' \
                'a_var = a_func(AClass)\n'
         mod.write(code)
         self.pycore.run_module(mod).wait_process()
     def test_instance_dti(self):
         mod = self.pycore.create_module(self.project.root, 'mod')
         code = 'class AClass(object):\n    pass\n' \
-               '\ndef a_func(arg):\n    return arg()\n' \
+               '\ndef a_func(arg):\n    return eval("arg()")\n' \
                'a_var = a_func(AClass)\n'
         mod.write(code)
         self.pycore.run_module(mod).wait_process()
 
     def test_method_dti(self):
         mod = self.pycore.create_module(self.project.root, 'mod')
-        code = 'class AClass(object):\n    def a_method(self, arg):\n        return arg()\n' \
+        code = 'class AClass(object):\n    def a_method(self, arg):\n        return eval("arg()")\n' \
                'an_instance = AClass()\n' \
                'a_var = an_instance.a_method(AClass)\n'
         mod.write(code)
 
     def test_classes_with_the_same_name(self):
         mod = self.pycore.create_module(self.project.root, 'mod')
-        code = 'def a_func(arg):\n    class AClass(object):\n        pass\n    return arg\n' \
+        code = 'def a_func(arg):\n    class AClass(object):\n        pass\n    return eval("arg")\n' \
                'class AClass(object):\n    pass\n' \
                'a_var = a_func(AClass)\n'
         mod.write(code)
     def test_nested_classes(self):
         mod = self.pycore.create_module(self.project.root, 'mod')
         code = 'def a_func():\n    class AClass(object):\n        pass\n    return AClass\n' \
-               'def another_func(arg):\n    return arg\n' \
+               'def another_func(arg):\n    return eval("arg")\n' \
                'a_var = another_func(a_func())\n'
         mod.write(code)
         self.pycore.run_module(mod).wait_process()
 
     def test_dti_and_concluded_data_invalidation(self):
         mod = self.pycore.create_module(self.project.root, 'mod')
-        code = 'def a_func(arg):\n    return arg\n' \
+        code = 'def a_func(arg):\n    return eval("arg")\n' \
                'a_var = a_func(a_func)\n'
         mod.write(code)
         pymod = self.pycore.resource_to_pyobject(mod)
 
     def test_list_objects_and_dynamicoi(self):
         mod = self.pycore.create_module(self.project.root, 'mod')
-        code = 'class C(object):\n    pass\ndef a_func(arg):\n    return arg\n' \
+        code = 'class C(object):\n    pass\ndef a_func(arg):\n    return eval("arg")\n' \
                'a_var = a_func([C()])[0]\n'
         mod.write(code)
         self.pycore.run_module(mod).wait_process()
 
     def test_for_loops_and_dynamicoi(self):
         mod = self.pycore.create_module(self.project.root, 'mod')
-        code = 'class C(object):\n    pass\ndef a_func(arg):\n    return arg\n' \
+        code = 'class C(object):\n    pass\ndef a_func(arg):\n    return eval("arg")\n' \
                'for c in a_func([C()]):\n    a_var = c\n'
         mod.write(code)
         self.pycore.run_module(mod).wait_process()
     def test_dict_objects_and_dynamicoi(self):
         mod = self.pycore.create_module(self.project.root, 'mod')
         code = 'class C(object):\n    pass\n' \
-               'def a_func(arg):\n    return arg\n' \
+               'def a_func(arg):\n    return eval("arg")\n' \
                'a_var = a_func({1: C()})[1]\n'
         mod.write(code)
         self.pycore.run_module(mod).wait_process()
     def test_dict_keys_and_dynamicoi(self):
         mod = self.pycore.create_module(self.project.root, 'mod')
         code = 'class C(object):\n    pass\n' \
-               'def a_func(arg):\n    return arg\n' \
+               'def a_func(arg):\n    return eval("arg")\n' \
                'a_var = a_func({C(): 1}).keys()[0]\n'
         mod.write(code)
         self.pycore.run_module(mod).wait_process()
     def test_dict_keys_and_dynamicoi2(self):
         mod = self.pycore.create_module(self.project.root, 'mod')
         code = 'class C1(object):\n    pass\nclass C2(object):\n    pass\n' \
-               'def a_func(arg):\n    return arg\n' \
+               'def a_func(arg):\n    return eval("arg")\n' \
                'a, b = a_func((C1(), C2()))\n'
         mod.write(code)
         self.pycore.run_module(mod).wait_process()
 
     def test_strs_and_dynamicoi(self):
         mod = self.pycore.create_module(self.project.root, 'mod')
-        code = 'def a_func(arg):\n    return arg\n' \
+        code = 'def a_func(arg):\n    return eval("arg")\n' \
                'a_var = a_func("hey")\n'
         mod.write(code)
         self.pycore.run_module(mod).wait_process()
     def test_a_function_with_different_returns(self):
         mod = self.pycore.create_module(self.project.root, 'mod')
         code = 'class C1(object):\n    pass\nclass C2(object):\n    pass\n' \
-               'def a_func(arg):\n    return arg\n' \
+               'def a_func(arg):\n    return eval("arg")\n' \
                'a = a_func(C1())\nb = a_func(C2())\n'
         mod.write(code)
         self.pycore.run_module(mod).wait_process()

ropetest/pycoretest.py

                                             ' *param3, **param4):\n    pass')
         sample_function = mod.get_attribute('sample_function')
         self.assertEquals(['param1', 'param2', 'param3', 'param4'],
-                          sample_function.get_object().parameters)
+                          sample_function.get_object().get_param_names())
 
     # FIXME: Not found modules
     def xxx_test_not_found_module_is_module(self):
         string_module = self.pycore.get_string_module('from mod import a_func\n')
         self.assertEquals(None, string_module.get_resource())
 
-    def test_get_pyname_definition_location_class(self):
+    def test_get_pyname_definition_location_class2(self):
         mod = self.pycore.get_string_module('class AClass(object):\n    def __init__(self):\n' + \
                                             '        self.an_attr = 10\n')
         a_class = mod.get_attribute('AClass').get_object()
         mod.write(contents)
         self.pycore.get_module('mod')
 
-    def test_file_encoding_reading(self):
+    def test_file_encoding_reading2(self):
         contents = 'a_var = 1\ndef a_func():\n    global a_var\n'
         mod = self.pycore.get_string_module(contents)
         global_var = mod.get_attribute('a_var')
         c_class = pymod.get_attribute('C').get_object()
         self.assertFalse('var1' in c_class.get_attributes())
 
-    def test_not_leaking_tuple_assigned_names_inside_parent_scope(self):
-        mod = self.pycore.create_module(self.project.root, 'mod')
-        mod.write('class C(object):\n    def f(self):\n'
-                  '        var1, var2 = range(2)\n')
-        pymod = self.pycore.resource_to_pyobject(mod)
-        c_class = pymod.get_attribute('C').get_object()
-        self.assertFalse('var1' in c_class.get_attributes())
-
     @testutils.run_only_for_25
     def test_with_statement_variables(self):
         code = 'import threading\nwith threading.lock() as var:    pass\n'
         self.assertEquals(mod1_object.get_attribute('a_func').get_object(),
                           mod2_object.get_attribute('a_func').get_object())
 
+    def test_invalidating_cache_for_from_imports_after_resource_change(self):
+        mod1 = self.pycore.create_module(self.project.root, 'mod1')
+        mod2 = self.pycore.create_module(self.project.root, 'mod2')
+        mod2.write('def a_func():\n    print(1)\n')
+        mod1.write('from mod2 import a_func\na_func()\n')
+
+        pymod1 = self.pycore.get_module('mod1')
+        pymod2 = self.pycore.get_module('mod2')
+        self.assertEquals(pymod1.get_attribute('a_func').get_object(),
+                          pymod2.get_attribute('a_func').get_object())
+        mod2.write(mod2.read() + '\n')
+        pymod2 = self.pycore.get_module('mod2')
+        self.assertEquals(pymod1.get_attribute('a_func').get_object(),
+                          pymod2.get_attribute('a_func').get_object())
+
 
 class ClassHierarchyTest(unittest.TestCase):