Commits

Ali Gholami Rudi  committed 41c4490

Removing extra trailing spaces all over the place

  • Participants
  • Parent commits f14d79f

Comments (0)

Files changed (87)

 
 Features added in this release:
 
-* 
+*
 
 
 Getting Started

File docs/dev/issues.txt

 * Change method signature
 * Introduce parameter
 * Enhancing refactorings and testing
+* Handling built-in types
 
 Exploring and analyzing possible solutions for:
 
-* Handling built-in types
 * Implicit interfaces
 
 
 Hot Topics
 ==========
 
-* `Storing different return types for different set of arguments`_
 * `Removing PythonRefactoring facade`_
 
 
 * Undo Unification
 
 
-Storing Different Return Types For Different Set Of Arguments
-=============================================================
+Rope's Preference System
+========================
 
-Goals:
+This might show what rope needs::
 
-* Better type inference for function return values and parameters
-* Better builtin type construction
+  class Preferences(object):
 
-Problems:
+      def get_preference(self, name):
+          pass
 
-* Needs more memory
-* Slower module running
-* Slower object infers
+
+  class FilePreferences(object):
+
+      def __init__(self, path):
+          self.path = path
+
+      def get_preference(self, name):
+          pass
+
+
+Issues
+------
+
+* format
+
+  * human readable? yes
+  * python (like emacs and lisp)
+
+    - push or pull model for configurations
+
+  * simple equals
+
+* types
+
+  * strings
+  * lists?
+
+* changable by rope?
+
+
+Having Virtual `PyModule`\s
+===========================
+
+What Do We Gain?
+----------------
+
+After this refactoring we'll be able to mix any of the refactorings
+and move toward bigger refactorings.
+
+* Handling import changes for all modules
+
+  One of the problems we are facing when performing refactorings is
+  that imports need to be changed in some of the modules involved in
+  that refactoring, but since those modules are already changed for
+  that refactoring, it cannot be changed once more easily.
+
+* Performing multiple refactorings in sequence
+
+  For example for performing move method refactoring we can rename the
+  self parameter of the method and then move the method itself.  Then
+  move the imports used.
+
+* Support for bigger refactorings
+
+  Examples:
+
+
+Consequences
+------------
+
+* Complexity of implementation
+
+  After a change the internal representation of project should be
+  updated.  This requires for example changes to
+  `Folder.get_children` and `File.read`.
+
+* Inefficiency because of multiple changes while refactoring
+
+  If in a refactoring we perform 3 changes we might also need to
+  recompute the information calculated in some of the `PyModule`\s
+  3 times.  This seems inefficient.
+
+* Inefficiency due to missing computed information computed locally
+
+  One of the difficulties of having a set of main and many local
+  `PyModule`\s is that when we compute some information in local
+  ones these information might be no longer valid in global pymodules.
+
+
+* Not convincing uses
+
+  Right know the only need for performing multiple refactorings is
+  for changing imports after performing a refactoring and it has been
+  handled using some kind of virtual `PyModule` already.  We could
+  not think of any good refactoring that needs to perform multiple
+  basic refactorings.
+
+* Lots of changes
+
+  This refactoring needs lots of changes to `PyCore` and modules that
+  use it.
+
+* Complex design
+
+  Managing multiple `PyCore`\s and changing `PyObject`\s to work with
+  many of them at the same time seems to be hard.
+
+
+A Bit in Details
+----------------
+
+If we change all refactoring modules to work on a pymodule we would
+probably be able to have a structure like this::
+
+  class PythonProjectFiles(object):
+
+      def resource_to_pyobject(self, resource):
+          pass
+
+      def get_module(self, module_name):
+          pass
+
+
+  class ChangedPythonProjectFiles(PythonProjectFiles):
+
+      def resource_to_pyobject(self, resource):
+          pass
+
+      def get_module(self, module_name):
+          pass
+
+      def file_changed(self, resource, new_content):
+          pass
+
+      def move_resource(self, resource, new_location):
+          pass
+
+      def get_changes(self):
+          pass
+
+
+This way we can perform any number of refactorings in sequence.  But
+it seems as if we should break `PyCore` into two separate classes.
+What's more after this change we would probably be able to remove
+`rope.refactor.change`.  Maybe we can add `Change...` interfaces to
+`ChangedPythonProjectFiles`.
+
+One of the main obstacles for doing this change is that all of the
+`PyObjects` have a reference to the `PyCore` and ask them about
+other modules.  This causes problems because we want all of the
+`PyObjects` to use a local `PyCore`.
+
+What's more computed information might be valid in a local scope
+but might be invalid in the rest of project.
+
+
+Preventing Unnecessary Recomputations
+-------------------------------------
+
+* Using copy on write
+* Updating global `PyCore` after performing changes
+
+
+Simple Implementation
+---------------------
+
+A simple implementation would be possible by using plain and new
+`PythonProjectFiles` from the beginning.  But the performance might
+really hurt if we actually use it but it won't change if we don't.
+So actually it is a extract class refactorings.
+
+
+Inline Method
+=============
+
+* Which of the variables should be renamed?
+* What to do about parameter assignments?
+* What to do about staticmethod and classmethod decorators
+* Moving used imports and importing defining module globals
+* Inlining generators
+* Inner functions
+
+
+Using ASTs For Transformations
+==============================
+
+The main problem with AST nodes is that they only hold the line in
+which statements appear but we need the offset.  If we add offset
+information to AST nodes, we would be able to use them for all of the
+tasks that we do right now using direct operations on program source
+code.
+
+Using ASTs for transforming programs requires making a new AST tree
+or altering the old one and writing AST trees.  We can use the latter
+in the formatter too but it seems a lot of work.
+
+
+What Rope Assumes...
+====================
+
+In order to simplify problems a bit, rope makes some assumptions about
+the source code.  In futures some of this restrictions might be removed.
+
+* All of the modules should use 4 spaces for indenting and no hard tabs.
+* All files that end with ``.py`` are considered to be python files and
+  all others not.
+* Either all files should be under version control or none.
+* All ``*.txt`` files are considered in reST formats.
+* XXX
+
+
+Designing Refactorings to Be Used in IDEs
+=========================================
+
+* Finding available refactorings
+* A better facade
+* Better refactoring categoriztion
+* Making adding new refactorings easier
+
+
+Decisions to Make
+-----------------
+
+* Unifying refactoring interfaces
+* Introducing factories for refactorings;
+  Reduce the dependence to `rope.refactor` modules
+* Removing `rope.refactor.PythonRefactoring`
+
+
+A Common Refactoring Interface
+------------------------------
+
+::
+
+  class Refactoring(object):
+
+      def __init__(self, *args, **kwds):
+      """Getting immediate informations"""
+
+      def get_changes(self, *args, **kwds):
+      """Calculate the changes caused by this refactoring.
+
+      It is passed user provided information.
+      """
+
+      # Other functions for getting information after construction
+      # for helping IDE's.
+
+
+Note that the arguments of `__init__` and `get_changes` are not the
+same for all refactorings.
+
+
+Finding Available Refactorings
+------------------------------
+
+The question we need to answer before proceeding is to decide
+whether this belongs to UI or core.
+
+
+Making Adding New Refactorings Easier
+-------------------------------------
+
+Adding a new refactoring requires changing `Refactoring` facade and
+Adding the new refactoring class.  Duplications:
+
+* Duplicate parameters
+* We have the same refactoring class for inlines, extracts and
+  renames but we have to call their constructors separately.
+
+
+Removing `PythonRefactoring` Facade
+-----------------------------------
+
+* Changing uses of `PythonRefactoring` to use `rope.refactor` modules
+* Adding a place for saving undo information
+* What to do with import utils
+* Documenting the refactorings `rope.refactor` submodules provide
+* Updating references to `PythonRefactoring` and
+  `PyCore.get_refactoring` to use the new objects.
+
+
+Moving Fields/Methods
+=====================
+
+* How tell that a pyname is a class attribute?
+
+  * An attribute should be defined in a class or a method in a class
+  * The holding class for a pyname should consider it as one of its
+    attributes
+
+* Moving defined objects
+
+  * If self is used renaming it and passing it as a second argument?
+  * Moving used imports
+
+Move refactoring should support moving:
+
+=======================  =============
+source                   destination
+=======================  =============
+module                   module
+global class/function    module
+class fields/methods     attribute
+static functions         class
+=======================  =============
+
+The problem of destination might be solved by passing a `PyName`
+or a `PyObject` instead of a `Resource`.  Maybe we can take a
+class as the destination for moving fields and methods instead
+of an attribute.
+
+Maybe we can have separate methods for moving each of above
+groups.::
+
+  move_module(resource, resource)
+  move_global(pyobject, resource)
+  move_attribute(pyobject, pyobject)
+
+
+Object Inference Issues
+=======================
+
+
+Better Object Inference
+-----------------------
+
+Currently rope's object inference mechanisms are simple and there are
+many situations that they are of no use:
+
+* A simple dynamic type inference saves the return types of methods
+* We use a simple static type inference that:
+
+  * Follows assignments
+  * Checks the returned ASTs
+  * Uses method return value and parameter information gained by DOI
+
+We are very interested in supporting:
+
+* Builtin types
+* Implicit interfaces
+
+Possible alternatives:
+
+* Saving the type of local variables when exiting a scope
+* Having a set of functions to record the place they are called
+* Having a flag that lets us save information per instance
+* Saving the result of every call
+* Using static type inference algorithms
+
+
+Rejecting Smalltalk `RefactoringBrowser` Approach
+-------------------------------------------------
+
+We can't use smalltalks approach because it requires the whole
+tests suite to be run before each refactoring and this does not
+seem appealing because it might take a lot of time.
+
+Apart from that if we use a wrapper for a function using python
+runtime mechanisms it is possible to find out from which line
+a function is called, but we cannot always find the offset in that
+file from which this function is called.
+
+Although we cannot find the exact offset an occurrence happens we
+can know the suspected lines and that will help us shorten the
+scope for searching for occurrences considerably.
+
+If we solve these problems we can can use a strategy for finding
+occurrences.  Also Think of other ways of collecting type information.
+
+
+Saving Collected Data
+---------------------
+
+Since resources might change after DTI, we should save collected data
+so that they can be used even if there are small changes in some
+files.  There might be two approaches to this problem.
+
+In the first approach we can make `PyName`\s and `PyObject`\s
+reference objects so that they can be used persistantly.  This
+approach seems hard due to problems that might arise for updating
+`PyName`\s.
+
+The second approach seems easier to implement.  We can save collected
+type information somewhere outside `PyName`\s.  Each time we need a
+`PyName`\'s object we use the stored data.  In this approach we
+should find someway of storing collected data so it can be used even
+if there are some small changes in a resource.  The simplest way of
+saving collected data is the ``(file, lineno)`` tuple.  The other is
+the hierarchical representation and in this approach we save the data
+like ``file.class.method``.
 
 
 Considerations For A New Textual Form
 We can also remove 'none' and 'unknown' with and empty string.
 
 
-Rope's Preference System
-========================
-
-This might show what rope needs::
-
-  class Preferences(object):
-      
-      def get_preference(self, name):
-          pass
-      
-  
-  class FilePreferences(object):
-  
-      def __init__(self, path):
-          self.path = path
-      
-      def get_preference(self, name):
-          pass
-
-
-Issues
-------
-
-* format
-
-  * human readable? yes
-  * python (like emacs and lisp)
-  
-    - push or pull model for configurations
-  
-  * simple equals
-
-* types
-
-  * strings
-  * lists?
-
-* changable by rope?
-
-
-Having Virtual `PyModule`\s
-===========================
-
-What Do We Gain?
-----------------
-
-After this refactoring we'll be able to mix any of the refactorings
-and move toward bigger refactorings.
-
-* Handling import changes for all modules
-
-  One of the problems we are facing when performing refactorings is
-  that imports need to be changed in some of the modules involved in
-  that refactoring, but since those modules are already changed for
-  that refactoring, it cannot be changed once more easily.
-
-* Performing multiple refactorings in sequence
-
-  For example for performing move method refactoring we can rename the
-  self parameter of the method and then move the method itself.  Then
-  move the imports used.
-
-* Support for bigger refactorings
-
-  Examples:
-
-
-Consequences
-------------
-
-* Complexity of implementation
-
-  After a change the internal representation of project should be
-  updated.  This requires for example changes to
-  `Folder.get_children` and `File.read`.
-
-* Inefficiency because of multiple changes while refactoring
-
-  If in a refactoring we perform 3 changes we might also need to
-  recompute the information calculated in some of the `PyModule`\s
-  3 times.  This seems inefficient.
-
-* Inefficiency due to missing computed information computed locally
-
-  One of the difficulties of having a set of main and many local
-  `PyModule`\s is that when we compute some information in local
-  ones these information might be no longer valid in global pymodules.
-  
-
-* Not convincing uses
-
-  Right know the only need for performing multiple refactorings is
-  for changing imports after performing a refactoring and it has been
-  handled using some kind of virtual `PyModule` already.  We could
-  not think of any good refactoring that needs to perform multiple
-  basic refactorings.
-
-* Lots of changes
-  
-  This refactoring needs lots of changes to `PyCore` and modules that
-  use it.
-
-* Complex design
-
-  Managing multiple `PyCore`\s and changing `PyObject`\s to work with
-  many of them at the same time seems to be hard.
-
-
-A Bit in Details
-----------------
-
-If we change all refactoring modules to work on a pymodule we would
-probably be able to have a structure like this::
-  
-  class PythonProjectFiles(object):
-      
-      def resource_to_pyobject(self, resource):
-          pass
-      
-      def get_module(self, module_name):
-          pass
-  
-  
-  class ChangedPythonProjectFiles(PythonProjectFiles):
-      
-      def resource_to_pyobject(self, resource):
-          pass
-      
-      def get_module(self, module_name):
-          pass
-      
-      def file_changed(self, resource, new_content):
-          pass
-      
-      def move_resource(self, resource, new_location):
-          pass
-
-      def get_changes(self):
-          pass
-          
-
-This way we can perform any number of refactorings in sequence.  But
-it seems as if we should break `PyCore` into two separate classes.
-What's more after this change we would probably be able to remove
-`rope.refactor.change`.  Maybe we can add `Change...` interfaces to 
-`ChangedPythonProjectFiles`.
-
-One of the main obstacles for doing this change is that all of the
-`PyObjects` have a reference to the `PyCore` and ask them about
-other modules.  This causes problems because we want all of the
-`PyObjects` to use a local `PyCore`.
-
-What's more computed information might be valid in a local scope
-but might be invalid in the rest of project.
-
-
-Preventing Unnecessary Recomputations
--------------------------------------
-
-* Using copy on write
-* Updating global `PyCore` after performing changes
-
-
-Simple Implementation
----------------------
-
-A simple implementation would be possible by using plain and new
-`PythonProjectFiles` from the beginning.  But the performance might
-really hurt if we actually use it but it won't change if we don't.
-So actually it is a extract class refactorings.
-
-
-Inline Method
-=============
-
-* Which of the variables should be renamed?
-* What to do about parameter assignments?
-* What to do about staticmethod and classmethod decorators
-* Moving used imports and importing defining module globals
-* Inlining generators
-* Inner functions
-
-
-Using ASTs For Transformations
-==============================
-
-The main problem with AST nodes is that they only hold the line in
-which statements appear but we need the offset.  If we add offset
-information to AST nodes, we would be able to use them for all of the
-tasks that we do right now using direct operations on program source
-code.
-
-Using ASTs for transforming programs requires making a new AST tree
-or altering the old one and writing AST trees.  We can use the latter
-in the formatter too but it seems a lot of work.
-
-
-What Rope Assumes...
-====================
-
-In order to simplify problems a bit, rope makes some assumptions about
-the source code.  In futures some of this restrictions might be removed.
-
-* All of the modules should use 4 spaces for indenting and no hard tabs.
-* All files that end with ``.py`` are considered to be python files and
-  all others not.
-* Either all files should be under version control or none.
-* All ``*.txt`` files are considered in reST formats.
-* XXX
-
-
-Designing Refactorings to Be Used in IDEs
-=========================================
-
-* Finding available refactorings
-* A better facade
-* Better refactoring categoriztion
-* Making adding new refactorings easier
-
-
-Decisions to Make
------------------
-
-* Unifying refactoring interfaces
-* Introducing factories for refactorings;
-  Reduce the dependence to `rope.refactor` modules
-* Removing `rope.refactor.PythonRefactoring`
-
-
-A Common Refactoring Interface
-------------------------------
-
-::
-
-  class Refactoring(object):
-      
-      def __init__(self, *args, **kwds):
-      """Getting immediate informations"""
-      
-      def get_changes(self, *args, **kwds):
-      """Calculate the changes caused by this refactoring.
-      
-      It is passed user provided information.
-      """
-      
-      # Other functions for getting information after construction
-      # for helping IDE's.
-
-
-Note that the arguments of `__init__` and `get_changes` are not the
-same for all refactorings.
-
-
-Finding Available Refactorings
-------------------------------
-
-The question we need to answer before proceeding is to decide
-whether this belongs to UI or core.
-
-
-Making Adding New Refactorings Easier
--------------------------------------
-
-Adding a new refactoring requires changing `Refactoring` facade and
-Adding the new refactoring class.  Duplications:
-
-* Duplicate parameters
-* We have the same refactoring class for inlines, extracts and
-  renames but we have to call their constructors separately.
-
-
-Removing `PythonRefactoring` Facade
------------------------------------
-
-* Changing uses of `PythonRefactoring` to use `rope.refactor` modules
-* Adding a place for saving undo information
-* What to do with import utils
-* Documenting the refactorings `rope.refactor` submodules provide
-* Updating references to `PythonRefactoring` and
-  `PyCore.get_refactoring` to use the new objects.
-
-
-Moving Fields/Methods
-=====================
-
-* How tell that a pyname is a class attribute?
-
-  * An attribute should be defined in a class or a method in a class
-  * The holding class for a pyname should consider it as one of its
-    attributes
-
-* Moving defined objects
-
-  * If self is used renaming it and passing it as a second argument?
-  * Moving used imports
-
-Move refactoring should support moving:
-
-=======================  =============
-source                   destination
-=======================  =============
-module                   module
-global class/function    module
-class fields/methods     attribute
-static functions         class
-=======================  =============
-
-The problem of destination might be solved by passing a `PyName`
-or a `PyObject` instead of a `Resource`.  Maybe we can take a
-class as the destination for moving fields and methods instead
-of an attribute.
-
-Maybe we can have separate methods for moving each of above
-groups.::
-  
-  move_module(resource, resource)
-  move_global(pyobject, resource)
-  move_attribute(pyobject, pyobject)
-
-
-Object Inference Issues
-=======================
-
-
-Better Object Inference
------------------------
-
-Currently rope's object inference mechanisms are simple and there are
-many situations that they are of no use:
-
-* A simple dynamic type inference saves the return types of methods
-* We use a simple static type inference that:
-  
-  * Follows assignments
-  * Checks the returned ASTs
-  * Uses method return value and parameter information gained by DOI
-
-We are very interested in supporting:
-
-* Builtin types
-* Implicit interfaces
-
-Possible alternatives:
-
-* Saving the type of local variables when exiting a scope
-* Having a set of functions to record the place they are called
-* Having a flag that lets us save information per instance
-* Saving the result of every call
-* Using static type inference algorithms
-
-
-Rejecting Smalltalk `RefactoringBrowser` Approach
--------------------------------------------------
-
-We can't use smalltalks approach because it requires the whole
-tests suite to be run before each refactoring and this does not
-seem appealing because it might take a lot of time.
-
-Apart from that if we use a wrapper for a function using python
-runtime mechanisms it is possible to find out from which line
-a function is called, but we cannot always find the offset in that
-file from which this function is called.
-
-Although we cannot find the exact offset an occurrence happens we
-can know the suspected lines and that will help us shorten the
-scope for searching for occurrences considerably.
-
-If we solve these problems we can can use a strategy for finding
-occurrences.  Also Think of other ways of collecting type information.
-
-
-Saving Collected Data
----------------------
-
-Since resources might change after DTI, we should save collected data
-so that they can be used even if there are small changes in some
-files.  There might be two approaches to this problem.
-
-In the first approach we can make `PyName`\s and `PyObject`\s
-reference objects so that they can be used persistantly.  This
-approach seems hard due to problems that might arise for updating
-`PyName`\s.
-
-The second approach seems easier to implement.  We can save collected
-type information somewhere outside `PyName`\s.  Each time we need a
-`PyName`\'s object we use the stored data.  In this approach we
-should find someway of storing collected data so it can be used even
-if there are some small changes in a resource.  The simplest way of
-saving collected data is the ``(file, lineno)`` tuple.  The other is
-the hierarchical representation and in this approach we save the data
-like ``file.class.method``.
-
-
 Returned Types Or Objects
 -------------------------
 
 in standard library.
 
 For example::
-  
+
   class A(object):
-      
+
       def a_method(self):
           pass
-  
+
   class B(object):
-      
+
       def a_method(self):
           pass
-    
+
   def a_func(arg):
       arg.a_method()
-  
+
   a_func(A())
   a_func(B())
 
 renaming `A.a_method` should force `B.a_method` to be renamed too.
 
 Or as another example::
-  
+
   a_var = A()
   a_var.a_method()
 
 and the members of this interface are the objects that are passed as
 that arguement.  Another thing to keep in mind is that implicit
 interfaces are extended by inheritance relation, too.  For example::
-  
+
   class C(A):
-      
+
       def a_method(self):
           pass
-  
+
   def a_func(arg):
       arg.a_method()
-  
+
   another_func(C())
 
 Renaming `arg.a_method` not only should rename `C.a_method` but also it
 it should rename `A.a_method`.
 
 We should be careful about situations like::
-  
+
   def a_func(arg):
       if isinstance(arg, A):
           arg.do_something()
           arg.do_some_other_thing()
 
 The other issue is what to do for situations like this::
-  
+
   def a_func(obj1, obj2):
       result = obj1.f(obj2)
       result.g()

File docs/dev/library.txt

 
 The `rope.base.fscommands` module implements the basic file system
 operations that rope needs to perform.  The main reason for the
-existence this module is supporting version control systems.  Have a 
+existence this module is supporting version control systems.  Have a
 look at `FileSystemCommands` and `SubversionCommands` in the same module.
 If you need other version control systems you can write a new class
 providing this interface.  `rope.base.project.Project` accepts a
 invalidate cached information about resources that have been
 removed or changed outside rope you should call `Project.validate`.
 You should pass a resource to this method.  For example::
-  
+
   project.validate(project.get_root_folder())
 
 validates all files and directories in the project.
   u'new_var = 10\n'
   >>> mod2.read()
   u'import mod1\nprint mod1.new_var\n'
-  
+
   # Undoing rename refactoring
   >>> refactoring.undo()
   >>> mod1.read()

File docs/dev/workingon.txt

 Removing `PythonRefactoring`
 ============================
 
-* Changing uses of `PythonRefactoring` to use `rope.refactor` modules
-* Adding a place for saving undo information
-* What to do with import utils
-* Documenting the refactorings `rope.refactor` submodules provide
-* Updating references to `PythonRefactoring` and
+* changing uses of `PythonRefactoring` to use `rope.refactor` modules
+* adding a place for saving undo information
+* what to do with import utils
+* documenting the refactorings `rope.refactor` submodules provide
+* updating references to `PythonRefactoring` and
   `PyCore.get_refactoring` to use the new objects.
 
-
-Storing Different Return Types For Different Set Of Arguments
-=============================================================
-
-- ignoring ``*args`` and ``**kwds`` in runmod
+* do something about long lines
 
 
 Remaining Stories

File docs/index.txt

   * Proposing templates in completions
   * Find occurrences
   * Import tools
-  
+
     * Change relative imports to absolute
     * Change from imports to normal imports
     * Expand ``from ... import *`` imports

File docs/user/overview.txt

 -------------------
 
 Consider we have::
-  
+
   class AClass(object):
-      
+
       def __init__(self):
           self.an_attr = 1
-      
+
       def a_method(self, arg):
           print self.an_attr, arg
-  
+
   a_var = AClass()
   a_var.a_method(a_var.an_attr)
 
 After renaming ``an_attr`` to ``new_attr`` and ``a_method`` to
 ``new_method`` we'll have::
-  
+
   class AClass(object):
-      
+
       def __init__(self):
           self.new_attr = 1
-      
+
       def new_method(self, arg):
           print self.new_attr, arg
-  
+
   a_var = AClass()
   a_var.new_method(a_var.new_attr)
 
 ------------------------------------
 
 We have::
-  
+
   def a_func(a_param):
       print a_param
-  
+
   a_func(a_param=10)
   a_func(10)
 
 After performing rename refactoring on any occurance of ``a_param``
 we will have::
-  
+
   def a_func(new_param):
       print new_param
-  
+
   a_func(new_param=10)
   a_func(10)
 
 ----------------
 
 Consider the project tree is something like::
-  
+
   root/
     mod1.py
     mod2.py
 
 ``mod1.py`` contains::
-  
+
   import mod2
   from mod2 import AClass
-  
+
   mod2.a_func()
   a_var = AClass()
 
 After performing rename refactoring one of the ``mod2`` occurances in
 `mod1` we'll get::
-  
+
   import newmod
   from newmod import AClass
-  
+
   newmod.a_func()
   a_var = AClass()
 
 The position of the mark would be region start and the current
 cursor position would be region end. (You can set the mark as in
 emacs copy and paste with ``C-space``). ::
-  
+
   def a_func():
       a = 1
       b = 2 * a
       c = ${region_start}a * 2 + b * 3${region_end}
-  
+
 After performing extract method we'll have::
 
   def a_func():
       a = 1
       b = 2 * a
       c = new_func(a, b)
-  
+
   def new_func(a, b):
       return a * 2 + b * 3
 
 ====================
 
 ::
-  
+
   class AClass(object):
-      
+
       def __init__(self):
           self.an_attr = 1
-      
+
       def call_a_func(self):
           return a_func()
-  
+
   def a_func():
       return a_func()
-  
+
   a_var = a_func()
   a_var.${codeassist}
-  
+
   another_var = a_var
   another_var.${codeassist}
   another_var.call_a_func().${codeassist}
   def f1(param):
       param.${codeassist}
       f2(param).${codeassist}
-  
+
   def f2(param):
       param.${codeassist}
       return param
 the parameter `param` of `f1`.
 
 ``mod2.py``::
-  
+
   import mod1
-  
+
   class A(object):
-      
+
       def a_method(self):
           pass
-  
+
   a_var = A()
   mod1.f1(a_var)
-  
+
 After running `mod2` module using rope's `Run Module`, we get good
 code assists in `mod1`.
 

File rope/base/builtins.py

 
 
 class List(pyobjects.PyObject):
-    
+
     def __init__(self, holding=None):
         super(List, self).__init__(pyobjects.PyObject.get_base_type('Type'))
         self.holding = holding
             'remove': BuiltinName(BuiltinFunction()),
             'reverse': BuiltinName(BuiltinFunction()),
             'sort': BuiltinName(BuiltinFunction())}
-    
+
     def _new_list(self, args):
         return _create_builtin(args, get_list)
-    
+
     def get_attributes(self):
         return self.attributes
 
 
 
 class Dict(pyobjects.PyObject):
-    
+
     def __init__(self, keys=None, values=None):
         super(Dict, self).__init__(pyobjects.PyObject.get_base_type('Type'))
         self.keys = keys
             'popitem': BuiltinName(BuiltinFunction()),
             'setdefault': BuiltinName(BuiltinFunction()),
             'update': BuiltinName(BuiltinFunction())}
-    
+
     def get_attributes(self):
         return self.attributes
-    
+
     def _new_dict(self, args):
         def do_create(holding):
             type = holding.get_type()
             if isinstance(type, Tuple) and len(type.get_holding_objects()) == 2:
                 return get_dict(*type.get_holding_objects())
         return _create_builtin(args, do_create)
-    
+
 get_dict = _create_builtin_getter(Dict)
 get_dict_type = _create_builtin_type_getter(Dict)
 
 
 class Tuple(pyobjects.PyObject):
-    
+
     def __init__(self, *objects):
         super(Tuple, self).__init__(pyobjects.PyObject.get_base_type('Type'))
         self.objects = objects
             '__getslice__': BuiltinName(BuiltinFunction(pyobjects.PyObject(self))),
             '__new__': BuiltinName(BuiltinFunction(function=self._new_tuple)),
             '__iter__': BuiltinName(BuiltinFunction(Iterator(first)))}
-    
+
     def get_holding_objects(self):
         return self.objects
-    
+
     def get_attributes(self):
         return self.attributes
 
     def _new_tuple(self, args):
         return _create_builtin(args, get_tuple)
 
-    
+
 get_tuple = _create_builtin_getter(Tuple)
 get_tuple_type = _create_builtin_type_getter(Tuple)
 
             'issubset': BuiltinName(BuiltinFunction()),
             'clear': BuiltinName(BuiltinFunction()),
             'update': BuiltinName(BuiltinFunction())}
-    
+
     def get_attributes(self):
         return self.attributes
-    
+
     def _new_set(self, args):
         return _create_builtin(args, get_set)
-    
+
 get_set = _create_builtin_getter(Set)
 get_set_type = _create_builtin_type_getter(Set)
 
 
 class Str(pyobjects.PyObject):
-    
+
     def __init__(self):
         super(Str, self).__init__(pyobjects.PyObject.get_base_type('Type'))
         self_object = pyobjects.PyObject(self)
             'translate': BuiltinName(BuiltinFunction(self_object)),
             'upper': BuiltinName(BuiltinFunction(self_object)),
             'zfill': BuiltinName(BuiltinFunction(self_object))}
-    
+
     def get_attributes(self):
         return self.attributes
 
 
 
 class BuiltinName(pynames.PyName):
-    
+
     def __init__(self, pyobject):
         self.pyobject = pyobject
-    
+
     def get_object(self):
         return self.pyobject
 
 
 class BuiltinFunction(pyobjects.PyObject):
-    
+
     def __init__(self, returned=None, function=None):
         super(BuiltinFunction, self).__init__(
             pyobjects.PyObject.get_base_type('Function'))
         self.returned = returned
         self.function = function
-    
+
     def get_returned_object(self, args=None):
         if self.function is not None:
             return self.function(args)
         self.attributes = {
             'next': BuiltinName(BuiltinFunction(self.holding)),
             '__iter__': BuiltinName(BuiltinFunction(self))}
-    
+
     def get_attributes(self):
         return self.attributes
 
             holding = iter.get_attribute('next').get_object().\
                       get_returned_object()
             return holding
-    
+
 
 def _create_builtin(args, creator):
     passed = args.get_arguments(['sequence'])[0]

File rope/base/codeanalyze.py

 
     def __init__(self, source_code):
         self.source_code = source_code
-    
+
     def _find_word_start(self, offset):
         current_offset = offset
         while current_offset >= 0 and self._is_id_char(current_offset):
             current_offset -= 1;
         return current_offset + 1
-    
+
     def _find_word_end(self, offset):
         current_offset = offset + 1
         while current_offset < len(self.source_code) and \
                 if current_offset >= 0 and self.source_code[current_offset] == '\\':
                     current_offset -= 1
         return current_offset
-    
+
     def get_word_before(self, offset):
         return self.source_code[self._find_word_start(offset - 1):offset]
-    
+
 
     def get_word_at(self, offset):
         offset = self._get_fixed_offset(offset)
             if offset < len(self.source_code) - 1 and self._is_id_char(offset + 1):
                 return offset + 1
         return offset
-    
+
     def _is_id_char(self, offset):
         return self.source_code[offset].isalnum() or self.source_code[offset] == '_'
-    
+
     def _find_string_start(self, offset):
         kind = self.source_code[offset]
         current_offset = offset - 1
         while self.source_code[current_offset] != kind:
             current_offset -= 1
         return current_offset
-    
+
     def _find_parens_start(self, offset):
         current_offset = self._find_last_non_space_char(offset - 1)
         while current_offset >= 0 and self.source_code[current_offset] not in '[({':
         if self._is_id_char(offset):
             return self._find_word_start(offset)
         return old_offset
-    
+
     def _find_primary_without_dot_start(self, offset):
         last_parens = offset
         current_offset = self._find_last_non_space_char(offset)
             last_parens = self._find_parens_start(current_offset)
             current_offset = self._find_last_non_space_char(last_parens - 1)
         if self.source_code[last_parens] == '(' and self._is_id_char(current_offset):
-           return self._find_primary_without_dot_start(current_offset)
-            
+            return self._find_primary_without_dot_start(current_offset)
+
 
         if current_offset > 0 and self.source_code[current_offset] in '\'"':
             return self._find_string_start(current_offset)
               self.source_code[self._find_last_non_space_char(current_offset - 1)] == '.':
             dot_position = self._find_last_non_space_char(current_offset - 1)
             current_offset = self._find_primary_without_dot_start(dot_position - 1)
-            
+
             if not self._is_id_char(current_offset):
                 break
 
         return current_offset
-    
+
     def get_primary_at(self, offset):
         offset = self._get_fixed_offset(offset)
         return self.source_code[self._find_primary_start(offset):
 
     def get_splitted_primary_before(self, offset):
         """returns expression, starting, starting_offset
-        
+
         This function is used in `rope.codeassist.assist` function.
         """
         if offset == 0:
             last_char_position = self._find_last_non_space_char(last_dot_position - 1)
             return (self.source_code[real_start:last_char_position + 1],
                     self.source_code[word_start:offset], word_start)
-    
+
     def _get_line_start(self, offset):
         while offset > 0 and self.source_code[offset] != '\n':
             offset -= 1
         return offset
-    
+
     def _get_line_end(self, offset):
         while offset < len(self.source_code) and self.source_code[offset] != '\n':
             offset += 1
         return offset
-    
+
     def _is_followed_by_equals(self, offset):
         while offset < len(self.source_code) and self.source_code[offset] in ' \\':
             if self.source_code[offset] == '\\':
                 offset = self._get_line_end(offset)
             offset += 1
         if offset + 1 < len(self.source_code) and \
-           self.source_code[offset] == '=' and self.source_code[offset + 1] != '=' :
+           self.source_code[offset] == '=' and self.source_code[offset + 1] != '=':
             return True
         return False
-    
+
     def _is_name_assigned_in_class_body(self, offset):
         word_start = self._find_word_start(offset - 1)
         word_end = self._find_word_end(offset - 1) + 1
         line_start = self._get_line_start(word_start)
         prev_word = self.source_code[line_start:word_start].strip()
         return prev_word in ['def', 'class']
-    
+
     def _find_first_non_space_char(self, offset):
         if offset >= len(self.source_code):
             return len(self.source_code)
                self.source_code[current_offset] == '\\':
                 current_offset += 2
         return current_offset
-    
+
     def is_a_function_being_called(self, offset):
         word_start = self._find_word_start(offset - 1)
         word_end = self._find_word_end(offset - 1) + 1
         return not self.is_a_class_or_function_name_in_header(offset) and \
                next_char < len(self.source_code) and \
                self.source_code[next_char] == '('
-    
+
     def _find_import_pair_end(self, start):
         next_char = self._find_first_non_space_char(start)
         if self.source_code[next_char] == '(':
                     current_offset += 1
                 current_offset += 1
             return current_offset
-    
+
     def is_import_statement(self, offset):
         try:
             last_import = self.source_code.rindex('import ', 0, offset)
         line_start = self._get_line_start(stmt_start)
         prev_word = self.source_code[line_start:stmt_start].strip()
         return prev_word == 'from'
-    
+
     def is_a_name_after_from_import(self, offset):
         try:
             last_from = self.source_code.rindex('from ', 0, offset)
         if from_names >= offset:
             return False
         return self._find_import_pair_end(from_names) >= offset
-    
+
     def is_function_keyword_parameter(self, offset):
         word_end = self._find_word_end(offset)
         if word_end + 1 == len(self.source_code):
         if prev_char - 1 < 0 or self.source_code[prev_char] not in ',(':
             return False
         return True
-    
+
     def find_parens_start_from_inside(self, offset):
         current_offset = offset
         opens = 1
                 opens += 1
             current_offset -= 1
         return current_offset
-    
+
     def is_assigned_here(self, offset):
         operation = self.get_assignment_type(offset)
         operations = ('=', '-=', '+=', '*=', '/=', '%=', '**=',
 
 
 class ScopeNameFinder(object):
-    
+
     def __init__(self, pymodule):
         self.source_code = pymodule.source_code
         self.module_scope = pymodule.get_scope()
            self.word_finder._is_name_assigned_in_class_body(offset):
             return True
         return False
-    
+
     def _is_function_name_in_function_header(self, holding_scope, offset, lineno):
         if lineno == holding_scope.get_start() and \
            holding_scope.pyobject.get_type() == rope.base.pyobjects.PyObject.get_base_type('Function') and \
         name = self.word_finder.get_primary_at(offset)
         result = self.get_pyname_in_scope(holding_scope, name)
         return result
-    
+
     def _find_module(self, module_name):
         current_folder = None
         if self.module_scope.pyobject.get_resource():
 
 def get_pyname_at(pycore, resource, offset):
     """Finds the pyname at the offset
-    
+
     This function is inefficient for multiple calls because of the
     recalculation of initialization data.
     """
 
 class SourceLinesAdapter(Lines):
     """Adapts source_code to Lines interface
-    
+
     Note: The creation of this class is expensive.
-    """    
-    
+    """
+
     def __init__(self, source_code):
         self.source_code = source_code
         self.line_starts = None
         self._initialize_line_starts()
-    
+
     def _initialize_line_starts(self):
         self.line_starts = []
         self.line_starts.append(0)
             if c == '\n':
                 self.line_starts.append(i + 1)
         self.line_starts.append(len(self.source_code) + 1)
-    
+
     def get_line(self, line_number):
         return self.source_code[self.line_starts[line_number - 1]:
                                 self.line_starts[line_number] - 1]
-    
+
     def length(self):
         return len(self.line_starts) - 1
 
 
     def __init__(self, lines):
         self.lines = lines
-    
+
     def get_line(self, line_number):
         return self.lines[line_number - 1]
-    
+
     def length(self):
         return len(self.lines)
 
 
 class LinesToReadline(object):
-    
+
     def __init__(self, lines, start):
         self.lines = lines
         self.current = start
-    
+
     def readline(self):
         if self.current <= self.lines.length():
             self.current += 1
             return self.lines.get_line(self.current - 1) + '\n'
         return ''
-    
+
     def __call__(self):
         return self.readline()
 
 
 class LogicalLineFinder(object):
-    
+
     def __init__(self, lines):
         self.lines = lines
-    
+
     def get_logical_line_in(self, line_number):
         block_start = StatementRangeFinder.get_block_start(
             self.lines, line_number,
                             current_lineno)
                 last_line_start = current_lineno + 1
         return (last_line_start, self.lines.length())
-    
+
     def _get_first_non_empty_line(self, line_number):
         current = line_number
         while current <= self.lines.length():
             pattern = '^\\s*(((def|class|if|elif|except|for|while|with)\\s)|((try|else|finally|except)\\s*:))'
             cls.__block_start_pattern = re.compile(pattern, re.M)
         return cls.__block_start_pattern
-    
+
 
 # XXX: Should we use it
 class xxxStatementRangeFinder(object):
             else:
                 break
         return indents
-    
+
 def count_line_indents(line):
     indents = 0
     for index, char in enumerate(line):

File rope/base/evaluate.py

 
     def visitName(self, node):
         self.result = self.scope.lookup(node.name)
-    
+
     def visitGetattr(self, node):
         pyname = StatementEvaluator.get_statement_result(self.scope, node.expr)
         if pyname is not None:
             if '__new__' in pyobject.get_attributes():
                 new_function = pyobject.get_attribute('__new__').get_object()
                 result = new_function.get_returned_object(args)
-            if result is None:
+            if result is None or \
+               result.get_type() == rope.base.pyobjects.PyObject.get_base_type('Unknown'):
                 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'):
             call_function = pyobject.get_attribute('__call__')
             self.result = rope.base.pynames.AssignedName(
                 pyobject=call_function.get_object().get_returned_object(args))
-    
+
     def visitConst(self, node):
         if isinstance(node.value, (str, unicode)):
             self.result = rope.base.pynames.AssignedName(
                 pyobject=rope.base.builtins.get_str())
-            
+
     def visitAdd(self, node):
         pass
-    
+
     def visitAnd(self, node):
         pass
 
 
     def visitCompare(self, node):
         pass
-    
+
     def visitDict(self, node):
         keys = None
         values = None
             values = self._get_object_for_node(item[1])
         self.result = rope.base.pynames.AssignedName(
             pyobject=rope.base.builtins.get_dict(keys, values))
-    
+
     def visitFloorDiv(self, node):
         pass
-    
+
     def visitList(self, node):
         holding = None
         if node.nodes:
             holding = self._get_object_for_node(node.nodes[0])
         self.result = rope.base.pynames.AssignedName(
             pyobject=rope.base.builtins.get_list(holding))
-    
+
     def visitListComp(self, node):
         pass
 
     def visitMul(self, node):
         pass
-    
+
     def visitNot(self, node):
         pass
-    
+
     def visitOr(self, node):
         pass
-    
+
     def visitPower(self, node):
         pass
-    
+
     def visitRightShift(self, node):
         pass
-    
+
     def visitLeftShift(self, node):
         pass
-    
+
     def visitSlice(self, node):
         self._call_function(node.expr, '__getslice__')
-    
+
     def visitSliceobj(self, node):
         pass
-    
+
     def visitTuple(self, node):
         objects = []
         if len(node.nodes) < 4:
         if pyname is not None:
             pyobject = pyname.get_object()
         return pyobject
-    
+
     def visitSubscript(self, node):
         self._call_function(node.expr, '__getitem__')
 
         evaluator = StatementEvaluator(scope)
         compiler.walk(node, evaluator)
         return evaluator.result
-    
+
     @staticmethod
     def get_string_result(scope, string):
         evaluator = StatementEvaluator(scope)
 
 
 class Arguments(object):
-    
+
     def __init__(self, args, scope):
         self.args = args
         self.scope = scope

File rope/base/fscommands.py

 
 
 class FileSystemCommands(object):
-    
+
     def create_file(self, path):
         open(path, 'w').close()
-    
+
     def create_folder(self, path):
         os.mkdir(path)
-    
+
     def move(self, path, new_location):
         shutil.move(path, new_location)
-    
+
     def remove(self, path):
         if os.path.isfile(path):
             os.remove(path)
 
 
 class SubversionCommands(object):
-    
+
     def __init__(self):
         self.normal_actions = FileSystemCommands()
         self.client = pysvn.Client()
-    
+
     def create_file(self, path):
         self.normal_actions.create_file(path)
         self.client.add(path, force=True)
-    
+
     def create_folder(self, path):
         self.normal_actions.create_folder(path)
         self.client.add(path, force=True)
-    
+
     def move(self, path, new_location):
         self.client.move(path, new_location, force=True)
-    
+
     def remove(self, path):
         self.client.remove(path, force=True)
 
 
 class FileAccess(object):
-    
+
     def read(self, path):
         """Read the content of the file at `path`.
-        
+
         Returns a `Unicode` object
         """
         source_bytes = open(path).read()
         return self._file_data_to_unicode(source_bytes)
-    
+
     def _file_data_to_unicode(self, data):
         encoding = self._conclude_file_encoding(data)
         if encoding is not None:
         except UnicodeDecodeError:
             # Using ``utf-8`` if guessed encoding fails
             return unicode(data, 'utf-8')
-    
+
     def _find_line_end(self, source_bytes, start):
         try:
             return source_bytes.index('\n', start)
         except ValueError:
             return len(source_bytes)
-    
+
     def _get_second_line_end(self, source_bytes):
         line1_end = self._find_line_end(source_bytes, 0)
         if line1_end != len(source_bytes):
             return self._find_line_end(source_bytes, line1_end)
         else:
             return line1_end
-    
+
     encoding_pattern = re.compile(r'coding[=:]\s*([-\w.]+)')
-    
+
     def _conclude_file_encoding(self, source_bytes):
         first_two_lines = source_bytes[:self._get_second_line_end(source_bytes)]
         match = FileAccess.encoding_pattern.search(first_two_lines)
 
     def write(self, path, contents):
         """Write the `contents` to the file at `path`.
-        
+
         contents should be a `Unicode` object.
         """
         file_ = open(path, 'w')

File rope/base/oi/dynamicoi.py

 
 
 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:
             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_textual = _PyObjectToTextual(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 _data_received(self, data):
         path = data[0][1]
         lineno = data[0][2]
         if path in self.files and lineno in self.files[path]:
             organizer = self.files[path][lineno]
             return organizer
-    
+
 
 class _CallInformationOrganizer(object):
-    
+
     def __init__(self, to_textual):
         self.info = {}
         self.to_textual = to_textual
-    
+
     def add_call_information(self, args, returned):
         self.info[args] = returned
-    
+
     def get_parameters(self):
         for args in self.info.keys():
             if len(args) > 0 and args[0] not in ('unknown', 'none'):
         if textual_args in self.info:
             return self.info[textual_args]
         return self._get_default_returned()
-    
+
     def _get_default_returned(self):
         default = ('unknown')
         for returned in self.info.values():
 
 
 class _TextualToPyObject(object):
-    
+
     def __init__(self, project):
         self.project = project
-    
+
     def transform(self, textual):
         """Transform an object from textual form to `PyObject`"""
         type = textual[0]
     def module_to_pyobject(self, textual):
         path = textual[1]
         return self._get_pymodule(path)
-    
+
     def builtin_to_pyobject(self, textual):
         name = textual[1]
         if name == 'str':
             holding = self.transform(textual[2])
             return builtins.get_set(holding)
         return None
-    
+
     def unknown_to_pyobject(self, textual):
         return None
-    
+
     def none_to_pyobject(self, textual):
         return None
-    
+
     def function_to_pyobject(self, textual):
         return self._get_pyobject_at(textual[1], textual[2])
-    
+
     def class_to_pyobject(self, textual):
         path, name = textual[1:]
         pymodule = self._get_pymodule(path)
             if lineno is not None:
                 inner_scope = module_scope.get_inner_scope_for_line(lineno)
                 return inner_scope.pyobject
-    
+
     def instance_to_pyobject(self, textual):
         return pyobjects.PyObject(self.class_to_pyobject(textual))
-    
+
     def _find_occurrence(self, name, source):
         pattern = re.compile(r'^\s*class\s*' + name + r'\b')
         lines = source.split('\n')
         else:
             resource = self.project.get_out_of_project_resource(path)
         return self.project.get_pycore().resource_to_pyobject(resource)
-    
+
     def _get_pyobject_at(self, path, lineno):
         scope = self._get_pymodule(path).get_scope()
         inner_scope = scope.get_inner_scope_for_line(lineno)
 
 
 class _PyObjectToTextual(object):
-    
+
     def __init__(self, project):
         self.project = project
-    
+