Commits

Ali Gholami Rudi  committed 3cda6a3

Adding rope.refactor.occurances module

  • Participants
  • Parent commits 9170d6c

Comments (0)

Files changed (17)

 ==========
 
 The keybinding will be customizable in future.  Some of these bindings
-are choosen from emacs and some from eclipse.  ('C' stands for Control
+are chosen from emacs and some from eclipse.  ('C' stands for Control
 key and 'M' for Meta(Alt) key.)
 
 =============  ==========================

File docs/done.txt

 ===========
 
 
+> Public Release 0.3m4 : October 1, 2006
+
+
 - Showing function signature in show doc : September 29, 2006
 
 

File docs/issues.txt

 0.3m3
     Done.
 0.3m4
+    Done.
+0.3m5
     Working on.
 
 
 This Release
 ------------
 
-* Separating Structural From Concluded Data
-* Enhanced Import Tools
-* Introduce factory method refactoring
-* Move function/class refactoring
+* ...
 
 
 Hot Topics

File docs/stories.txt

 * Showing function signature when calling
 
 
-* Introduce temporary variable
-
-
 * ``global`` keyword issues for pycore
 
 
 * Handling builtin functions and types
 
 
-* Better list and tree navigation @ 10h
+* Encapsulate field
+
+
+* Better list and tree navigation
   Add filter texts and selection texts to trees and lists.
 
 
-* Introduce redirection
-
-
-* Change method signature
-
-
-* Rename function parameters
-
-
 * Add import
 
 
 * Open Type; C-T
 
 
-* Function to "function object" refactoring
+* Replace method with method object refactoring
 
 
 * Analyzing function decorators
 
 
+* Introduce redirection
+
+
 * Enhancing module running
 
   * Showing running status in the GUI
   * Running last run
 
 
-* Encapsulate field
+* Change method signature @ 24h
 
+  * Add parameter
+  * Remove parameter
+  * Reorder
 
-* Inline method
 
+* Single line extract method and variable @ 10h
 
-* Inline variable
 
+* Inline method @ 20h
 
-* Removing imports from the same module
 
+* Removing imports from the same module @8h
 
-* Move a module or package to another package
 
+> Public Release 0.3m5 : October 15, 2006
 
-> Public Release 0.3m4 : October 1, 2006
+
+* Inline local variable @8h
+
+
+* Rename function parameters @12h
+
+
+* Move a module or package to another package @12h
 
 
 Remaining Stories

File docs/workingon.txt

+Release Planning And Estimation
+===============================
+
+
+* Problems when organizing imports in `ropetests.codeanalyzetest` module
+
 Remaining Stories
 =================
 

File rope/__init__.py

-VERSION = '0.3m4'
+VERSION = '0.3m5'

File rope/codeanalyze.py

         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 is_from_statement_module(self, offset):
-        stmt_start = self._find_primary_start(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)
-            from_import = self.source_code.index(' import ', last_from)
-            from_names = from_import + 8
-        except ValueError:
-            return False
-        next_char = self._find_first_non_space_char(from_names)
+    def _find_import_pair_end(self, start):
+        next_char = self._find_first_non_space_char(start)
         if self.source_code[next_char] == '(':
             try:
-                closing_parens = self.source_code.index(')', next_char)
-                return closing_parens >= offset
+                return self.source_code.index(')', next_char)
             except ValueError:
-                return False
+                return SyntaxError('Unmatched Parens')
         else:
             current_offset = next_char
             while current_offset < len(self.source_code):
                 if self.source_code[current_offset] == '\\':
                     current_offset += 1
                 current_offset += 1
-            return current_offset >= offset
-        return False
+            return current_offset
+        
+    
+    def is_import_statement(self, offset):
+        try:
+            last_import = self.source_code.rindex('import ', 0, offset)
+            import_names = last_import + 8
+        except ValueError:
+            return False
+        return self._find_import_pair_end(import_names) >= offset
+
+    def is_from_statement(self, offset):
+        try:
+            last_from = self.source_code.rindex('from ', 0, offset)
+            from_import = self.source_code.index(' import ', last_from)
+            from_names = from_import + 8
+        except ValueError:
+            return False
+        return self._find_import_pair_end(from_names) >= offset
+
+    def is_from_statement_module(self, offset):
+        stmt_start = self._find_primary_start(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)
+            from_import = self.source_code.index(' import ', last_from)
+            from_names = from_import + 8
+        except ValueError:
+            return False
+        if from_names >= offset:
+            return False
+        return self._find_import_pair_end(from_names) >= offset
 
 
 class StatementEvaluator(object):
         return result
 
 
-def get_name_and_pyname_at(pycore, resource, offset):
-    pymodule = pycore.resource_to_pyobject(resource)
-    source_code = pymodule.source_code
-    word_finder = rope.codeanalyze.WordRangeFinder(source_code)
-    name = word_finder.get_primary_at(offset).split('.')[-1]
-    pyname_finder = rope.codeanalyze.ScopeNameFinder(pymodule)
-    pyname = pyname_finder.get_pyname_at(offset)
-    return (name, pyname)
-
-
 def get_pyname_at(pycore, resource, offset):
     pymodule = pycore.resource_to_pyobject(resource)
     source_code = pymodule.source_code
     pyname = pyname_finder.get_pyname_at(offset)
     return pyname
 
+def get_name_at(pycore, resource, offset):
+    pymodule = pycore.resource_to_pyobject(resource)
+    source_code = pymodule.source_code
+    word_finder = rope.codeanalyze.WordRangeFinder(source_code)
+    name = word_finder.get_primary_at(offset).split('.')[-1]
+    return name
+
 
 class Lines(object):
 

File rope/importutils.py

     
     def transform_froms_to_normal_imports(self, pymodule):
         resource = pymodule.get_resource()
+        pymodule = self._clean_up_imports(pymodule)
+        module_with_imports = self.get_module_with_imports(pymodule)
+        for import_stmt in module_with_imports.get_import_statements():
+            if not self._can_import_be_transformed_to_normal_import(import_stmt.import_info):
+                continue
+            pymodule = self._from_to_normal(pymodule, import_stmt)
+        
+        # Adding normal imports in place of froms
+        module_with_imports = self.get_module_with_imports(pymodule)
+        for import_stmt in module_with_imports.get_import_statements():
+            if self._can_import_be_transformed_to_normal_import(import_stmt.import_info):
+                import_stmt.import_info = \
+                    NormalImport(((import_stmt.import_info.module_name, None),))
+        module_with_imports.remove_duplicates()
+        return module_with_imports.get_changed_source()
+
+    def _from_to_normal(self, pymodule, import_stmt):
+        resource = pymodule.get_resource()
+        from_import = import_stmt.import_info
+        module_name = from_import.module_name
+        imported_pymodule = self.pycore.get_module(module_name)
+        for name, alias in from_import.names_and_aliases:
+            imported = name
+            if alias is not None:
+                imported = alias
+            rename_in_module = rope.refactor.rename.RenameInModule(
+                self.pycore, [imported_pymodule.get_attribute(name)], imported,
+                module_name + '.' + name, replace_primary=True, imports=False)
+            source = rename_in_module.get_changed_module(pymodule=pymodule)
+            if source is not None:
+                pymodule = self.pycore.get_string_module(source, resource)
+        return pymodule
+
+    def _clean_up_imports(self, pymodule):
+        resource = pymodule.get_resource()
         module_with_imports = self.get_module_with_imports(pymodule)
         module_with_imports.expand_stars()
         source = module_with_imports.get_changed_source()
         source = module_with_imports.get_changed_source()
         if source is not None:
             pymodule = self.pycore.get_string_module(source, resource)
-        module_with_imports = self.get_module_with_imports(pymodule)
-        for import_stmt in module_with_imports.get_import_statements():
-            if not self._can_import_be_transformed_to_normal_import(import_stmt.import_info):
-                continue
-            from_import = import_stmt.import_info
-            module_name = from_import.module_name
-            imported_pymodule = self.pycore.get_module(module_name)
-            for name, alias in from_import.names_and_aliases:
-                imported = name
-                if alias is not None:
-                    imported = alias
-                rename_in_module = rope.refactor.rename.RenameInModule(
-                    self.pycore, [imported_pymodule.get_attribute(name)], imported,
-                    module_name + '.' + name, replace_primary=True)
-                source = rename_in_module.get_changed_module(pymodule=pymodule)
-                if source is not None:
-                    pymodule = self.pycore.get_string_module(source,
-                                                             resource)
-        
-        # Adding normal imports in place of froms
-        module_with_imports = self.get_module_with_imports(pymodule)
-        for import_stmt in module_with_imports.get_import_statements():
-            if self._can_import_be_transformed_to_normal_import(import_stmt.import_info):
-                import_stmt.import_info = \
-                    NormalImport(((import_stmt.import_info.module_name, None),))
-        module_with_imports.remove_duplicates()
-        return module_with_imports.get_changed_source()
+        return pymodule
     
     def transform_relative_imports_to_absolute(self, pymodule):
         module_with_imports = self.get_module_with_imports(pymodule)
                 pymodule.get_scope(), name)
             rename_in_module = rope.refactor.rename.RenameInModule(
                 self.pycore, [old_pyname], old_name,
-                absolute_name, replace_primary=True)
+                absolute_name, replace_primary=True, imports=False)
             source = rename_in_module.get_changed_module(pymodule=pymodule)
             if source is not None:
                 pymodule = self.pycore.get_string_module(source, pymodule.get_resource())
     def visitNormalImport(self, import_info):
         self.to_be_absolute.extend(import_info.get_relative_to_absolute_list(
                                    self.pycore, self.current_folder))
-        return import_info.relative_to_absolute_for_aliases(
+        return import_info.relative_to_absolute(
             self.pycore, self.current_folder)
     
     def visitEmptyImport(self, import_info):
         return len(self.names_and_aliases) == 0
 
     def add_import(self, import_info):
-        if isinstance(import_info, self.__class__) and \
-           self._are_name_and_alias_lists_equal(self.names_and_aliases,
+        if not isinstance(import_info, self.__class__):
+            return None
+        # Adding ``import x`` and ``import x.y`` that results ``import x.y``
+        if len(self.names_and_aliases) == len(import_info.names_and_aliases) == 1:
+            imported1 = self.names_and_aliases[0]
+            imported2 = import_info.names_and_aliases[0]
+            if imported1[1] == imported2[1] == None:
+                if imported1[0].startswith(imported2[0] + '.'):
+                    return self
+                if imported2[0].startswith(imported1[0] + '.'):
+                    return import_info
+        # Multiple imports using a single import statement is discouraged
+        # so we won't bother adding them.
+        if self._are_name_and_alias_lists_equal(self.names_and_aliases,
                                                 import_info.names_and_aliases):
             return self
         return None
     
-    def relative_to_absolute_for_aliases(self, pycore, current_folder):
+    def relative_to_absolute(self, pycore, current_folder):
         new_pairs = []
         for name, alias in self.names_and_aliases:
-            if alias is None:
-                new_pairs.append((name, alias))
-                continue
             resource = pycore.find_module(name, current_folder=current_folder)
             if resource is None:
                 new_pairs.append((name, alias))

File rope/objectinfer.py

             return
         for assign_node in reversed(pyname.assigned_asts):
             try:
-                lineno = assign_node.lineno
-                if lineno is None:
-                    lineno = 1
+                lineno = 1
+                if hasattr(assign_node, 'lineno') and assign_node.lineno is not None:
+                    lineno = assign_node.lineno
                 holding_scope = pyname.module.get_scope().\
                                 get_inner_scope_for_line(lineno)
                 resulting_pyname = rope.codeanalyze.StatementEvaluator.\

File rope/pyobjects.py

         if old_pyname is None or not isinstance(old_pyname, AssignedName):
             self.scope_visitor.names[node.name] = AssignedName(
                 module=self.scope_visitor.get_module())
-        self.scope_visitor.names[node.name].assigned_asts.append(self.assigned_ast)
+        if self.assigned_ast:
+            self.scope_visitor.names[node.name].assigned_asts.append(self.assigned_ast)
 
 
 class _ScopeVisitor(object):

File rope/refactor/introduce_factory.py

 
     def introduce_factory(self):
         changes = ChangeSet()
-        class_scope = self.old_pyname.get_object().get_scope()
         self._change_occurances_in_other_modules(changes)
     
+        self._change_resource(changes)
+        return changes
+
+    def _change_resource(self, changes):
+        class_scope = self.old_pyname.get_object().get_scope()
         rename_in_module = rope.refactor.rename.RenameInModule(
             self.pycore, [self.old_pyname], self.old_name, self._get_new_function_name(), True)
         source_code = rename_in_module.get_changed_module(pymodule=self.pymodule)
         if source_code is None:
             source_code = self.pymodule.source_code
         lines = rope.codeanalyze.SourceLinesAdapter(source_code)
+        start = self._get_insertion_offset(class_scope, lines)
+        result = source_code[:start]
+        result += self._get_factory_method(lines, class_scope)
+        result += source_code[start:]
+        changes.add_change(ChangeFileContents(self.resource, result))
+
+    def _get_insertion_offset(self, class_scope, lines):
         start_line = class_scope.get_end()
         if class_scope.get_scopes():
             start_line = class_scope.get_scopes()[-1].get_end()
         start = lines.get_line_end(start_line) + 1
-        result = source_code[:start]
-        result += self._get_factory_method(lines, class_scope)
-        result += source_code[start:]
-        changes.add_change(ChangeFileContents(self.resource, result))
-        return changes
+        return start
 
     def _get_factory_method(self, lines, class_scope):
         if self.global_factory:

File rope/refactor/move.py

     def _rename_in_module(self, pymodule, new_name):
         rename_in_module = rope.refactor.rename.RenameInModule(
             self.pycore, [self.old_pyname], self.old_name,
-            new_name, replace_primary=True)
+            new_name, replace_primary=True, imports=False)
         return rename_in_module.get_changed_module(pymodule=pymodule)
     
     def _add_imports_to_module(self, pymodule, new_imports):

File rope/refactor/occurances.py

+import re
+
+import rope.codeanalyze
+import rope.pynames
+import rope.pyobjects
+import rope.refactor.occurances
+
+
+class OccurrenceFinder(object):
+    
+    def __init__(self, pycore, pynames, name,
+                 function_calls=False, whole_primary=False,
+                 imports=True):
+        self.pycore = pycore
+        self.pynames = pynames
+        self.name = name
+        self.function_calls = function_calls
+        self.whole_primary = whole_primary
+        self.imports = imports
+        self.comment_pattern = OccurrenceFinder.any("comment", [r"#[^\n]*"])
+        sqstring = r"(\b[rR])?'[^'\\\n]*(\\.[^'\\\n]*)*'?"
+        dqstring = r'(\b[rR])?"[^"\\\n]*(\\.[^"\\\n]*)*"?'
+        sq3string = r"(\b[rR])?'''[^'\\]*((\\.|'(?!''))[^'\\]*)*(''')?"
+        dq3string = r'(\b[rR])?"""[^"\\]*((\\.|"(?!""))[^"\\]*)*(""")?'
+        self.string_pattern = OccurrenceFinder.any(
+            "string", [sq3string, dq3string, sqstring, dqstring])
+        self.pattern = self._get_occurance_pattern(self.name)
+    
+    def find_occurances(self, resource=None, pymodule=None):
+        source_code = self._get_source(resource, pymodule)
+        name_finder_creator = rope.refactor.occurances._LazyNameFinderCreator(self.pycore, resource, pymodule)
+        word_finder = rope.codeanalyze.WordRangeFinder(source_code)
+        for match in self.pattern.finditer(source_code):
+            for key, value in match.groupdict().items():
+                if value and key == "occurance":
+                    start = match_start = match.start(key)
+                    end = match_end = match.end(key)
+                    if self.whole_primary:
+                        start = word_finder._find_primary_start(match_start)
+                        end = word_finder._find_word_end(match_start) + 1
+                    if self._is_a_match(name_finder_creator, word_finder,
+                                        match_start):
+                        yield (start, end)
+
+    def _get_source(self, resource, pymodule):
+        if resource is not None:
+            return resource.read()
+        else:
+            return pymodule.source_code
+
+    def _is_a_match(self, name_finder_creator, word_finder, match_start):
+        if self.function_calls and \
+           not word_finder.is_a_function_being_called(match_start + 1):
+            return False
+        if self.whole_primary and \
+           word_finder.is_a_class_or_function_name_in_header(match_start + 1):
+            return False
+        if not self.imports and \
+           (word_finder.is_from_statement(match_start + 1) or
+            word_finder.is_import_statement(match_start + 1)):
+            return False
+        new_pyname = name_finder_creator.get_name_finder().get_pyname_at(match_start + 1)
+        for pyname in self.pynames:
+            if self._are_pynames_the_same(pyname, new_pyname):
+                return True
+        return False
+
+    def _are_pynames_the_same(self, pyname1, pyname2):
+        return pyname1 == pyname2 or \
+               (pyname1 is not None and pyname2 is not None and 
+                pyname1.get_object() == pyname2.get_object() and
+                pyname1.get_definition_location() == pyname2.get_definition_location())
+    
+    def _get_occurance_pattern(self, name):
+        occurance_pattern = OccurrenceFinder.any('occurance', ['\\b' + name + '\\b'])
+        pattern = re.compile(occurance_pattern + "|" + \
+                             self.comment_pattern + "|" + self.string_pattern)
+        return pattern
+
+    @staticmethod
+    def any(name, list_):
+        return "(?P<%s>" % name + "|".join(list_) + ")"
+
+
+class _LazyNameFinderCreator(object):
+    
+    def __init__(self, pycore, resource=None, pymodule=None):
+        self.pycore = pycore
+        self.resource = resource
+        self.pymodule = pymodule
+        self.name_finder = None
+    
+    def get_name_finder(self):
+        if self.name_finder is None:
+            if self.pymodule is None:
+                self.pymodule = self.pycore.resource_to_pyobject(self.resource)
+            self.pyname_finder = rope.codeanalyze.ScopeNameFinder(self.pymodule)
+        return self.pyname_finder

File rope/refactor/rename.py

 import rope.pyobjects
 from rope.refactor.change import (ChangeSet, ChangeFileContents,
                                   MoveResource, CreateFolder)
+import rope.refactor.occurances
 
 class RenameRefactoring(object):
     
         return self._rename(resource, offset, new_name)
     
     def _rename(self, resource, offset, new_name, in_file=False):
-        files = [resource]
-        if not in_file:
-            files = self.pycore.get_python_files()
-        old_name, old_pyname = rope.codeanalyze.\
-                               get_name_and_pyname_at(self.pycore, resource, offset)
-        if old_pyname is None:
+        files = self._get_interesting_files(resource, in_file)
+        old_name = rope.codeanalyze.get_name_at(self.pycore, resource, offset)
+        old_pynames = self._get_old_pynames(offset, resource, in_file, old_name)
+        if not old_pynames:
             return None
-        old_pynames = [old_pyname]
-        if self._is_it_a_class_method(old_pyname) and not in_file:
-            old_pynames = self._get_all_methods_in_hierarchy(old_pyname.get_object().
-                                                             parent, old_name)
         changes = ChangeSet()
         for file_ in files:
             new_content = RenameInModule(self.pycore, old_pynames, old_name, new_name).\
             if new_content is not None:
                 changes.add_change(ChangeFileContents(file_, new_content))
         
-        if old_pyname.get_object().get_type() == rope.pycore.PyObject.get_base_type('Module'):
-            changes.add_change(self._rename_module(old_pyname.get_object(), new_name))
+        if self._is_renaming_a_module(old_pynames):
+            changes.add_change(self._rename_module(old_pynames[0].get_object(), new_name))
         return changes
     
-    def _is_it_a_class_method(self, pyname):
+    def _is_renaming_a_module(self, old_pynames):
+        if len(old_pynames) == 1 and \
+           old_pynames[0].get_object().get_type() == rope.pycore.PyObject.get_base_type('Module'):
+            return True
+        return False
+
+    def _get_old_pynames(self, offset, resource, in_file, old_name):
+        old_pyname = rope.codeanalyze.get_pyname_at(self.pycore, resource,
+                                                    offset)
+        if old_pyname is None:
+            return []
+        if self._is_a_class_method(old_pyname) and not in_file:
+            return self._get_all_methods_in_hierarchy(old_pyname.get_object().
+                                                      parent, old_name)
+        else:
+            return [old_pyname]
+
+    def _get_interesting_files(self, resource, in_file):
+        if not in_file:
+            return self.pycore.get_python_files()
+        return [resource]
+    
+    def _is_a_class_method(self, pyname):
         return isinstance(pyname, rope.pynames.DefinedName) and \
                pyname.get_object().get_type() == rope.pyobjects.PyObject.get_base_type('Function') and \
                pyname.get_object().parent.get_type() == rope.pyobjects.PyObject.get_base_type('Type')
         else:
             new_location = parent_path + '/' + new_name
         return MoveResource(resource, new_location)
-    
+
 
 class RenameInModule(object):
     
     def __init__(self, pycore, old_pynames, old_name, new_name,
-                 only_function_calls=False, replace_primary=False):
-        self.pycore = pycore
-        self.old_pynames = old_pynames
-        self.old_name = old_name
+                 only_function_calls=False, replace_primary=False, imports=True):
+        self.occurances_finder = rope.refactor.occurances.OccurrenceFinder(pycore, old_pynames, old_name,
+                                                  only_function_calls, replace_primary,
+                                                  imports)
         self.new_name = new_name
-        self.only_function_calls = only_function_calls
-        self.replace_primary = replace_primary
-        self.comment_pattern = RenameInModule.any("comment", [r"#[^\n]*"])
-        sqstring = r"(\b[rR])?'[^'\\\n]*(\\.[^'\\\n]*)*'?"
-        dqstring = r'(\b[rR])?"[^"\\\n]*(\\.[^"\\\n]*)*"?'
-        sq3string = r"(\b[rR])?'''[^'\\]*((\\.|'(?!''))[^'\\]*)*(''')?"
-        dq3string = r'(\b[rR])?"""[^"\\]*((\\.|"(?!""))[^"\\]*)*(""")?'
-        self.string_pattern = RenameInModule.any(
-            "string", [sq3string, dq3string, sqstring, dqstring])
-        self.pattern = self._get_occurance_pattern(self.old_name)
     
     def get_changed_module(self, resource=None, pymodule=None):
-        if resource is not None:
-            source_code = resource.read()
-        else:
-            source_code = pymodule.source_code
+        source_code = self._get_source(resource, pymodule)
         result = []
         last_modified_char = 0
-        pyname_finder = None
-        word_finder = rope.codeanalyze.WordRangeFinder(source_code)
-        for match in self.pattern.finditer(source_code):
-            for key, value in match.groupdict().items():
-                if value and key == "occurance":
-                    start = match_start = match.start(key)
-                    end = match_end = match.end(key)
-                    if pyname_finder == None:
-                        pyname_finder = self._create_pyname_finder(source_code, resource, pymodule)
-                    new_pyname = pyname_finder.get_pyname_at(match_start + 1)
-                    
-                    if self.replace_primary:
-                        start = word_finder._find_primary_start(match_start)
-                        end = word_finder._find_word_end(match_start) + 1
-                    if not self._can_we_replace(word_finder, match_start):
-                        continue
-                    for old_pyname in self.old_pynames:
-                        if self._are_pynames_the_same(old_pyname, new_pyname):
-                            result.append(source_code[last_modified_char:start]
-                                          + self.new_name)
-                            last_modified_char = end
+        for start, end in self.occurances_finder.find_occurances(resource, pymodule):
+            result.append(source_code[last_modified_char:start]
+                          + self.new_name)
+            last_modified_char = end
         if last_modified_char != 0:
             result.append(source_code[last_modified_char:])
             return ''.join(result)
         return None
+    
+    def _get_source(self, resource, pymodule):
+        if resource is not None:
+            return resource.read()
+        else:
+            return pymodule.source_code
 
-    def _can_we_replace(self, word_finder, match_start):
-        if self.only_function_calls and \
-           not word_finder.is_a_function_being_called(match_start + 1):
-            return False
-        if self.replace_primary and \
-           (word_finder.is_a_name_after_from_import(match_start + 1) or
-            word_finder.is_a_class_or_function_name_in_header(match_start + 1)):
-            return False
-        return True
-
-    def _create_pyname_finder(self, source_code, resource, pymodule):
-        if resource is not None:
-            pymodule = self.pycore.resource_to_pyobject(resource)
-        pyname_finder = rope.codeanalyze.ScopeNameFinder(pymodule)
-        return pyname_finder
-    
-    def _are_pynames_the_same(self, pyname1, pyname2):
-        return pyname1 == pyname2 or \
-               (pyname1 is not None and pyname2 is not None and 
-                pyname1.get_object() == pyname2.get_object() and
-                pyname1.get_definition_location() == pyname2.get_definition_location())
-    
-    def _get_occurance_pattern(self, name):
-        occurance_pattern = RenameInModule.any('occurance', ['\\b' + name + '\\b'])
-        pattern = re.compile(occurance_pattern + "|" + \
-                             self.comment_pattern + "|" + self.string_pattern)
-        return pattern
-
-    @staticmethod
-    def any(name, list_):
-        return "(?P<%s>" % name + "|".join(list_) + ")"
-

File ropetest/codeanalyzetest.py

                               SourceLinesAdapter, WordRangeFinder, ScopeNameFinder)
 from rope.project import Project
 
+
 class StatementRangeFinderTest(unittest.TestCase):
 
     def setUp(self):
         word_finder = WordRangeFinder('var1 + "# var2".\n  var3')
         self.assertEquals('"# var2".\n  var3',
                           word_finder.get_primary_at(21))
+    
+    def test_import_statement_finding(self):
+        code = 'import mod\na_var = 10\n'
+        word_finder = WordRangeFinder(code)
+        self.assertTrue(word_finder.is_import_statement(code.index('mod') + 1))
+        self.assertFalse(word_finder.is_import_statement(code.index('a_var') + 1))
 
 
 class ScopeNameFinderTest(unittest.TestCase):

File ropetest/importutilstest.py

         self.assertEquals('import pkg2.mod2\nimport pkg2.mod3\nprint pkg2.mod2, pkg2.mod3',
                           module_with_imports.get_changed_source())
 
+    def test_removing_unused_imports_and_common_packages(self):
+        self.mod.write('import pkg1.mod1\nimport pkg1\nprint pkg1, pkg1.mod1\n')
+        pymod = self.pycore.get_module('mod')
+        module_with_imports = self.import_tools.get_module_with_imports(pymod)
+        module_with_imports.remove_unused_imports()
+        self.assertEquals('import pkg1.mod1\nprint pkg1, pkg1.mod1\n',
+                          module_with_imports.get_changed_source())
+
+    def test_removing_unused_imports_and_common_packages_reversed(self):
+        self.mod.write('import pkg1\nimport pkg1.mod1\nprint pkg1, pkg1.mod1\n')
+        pymod = self.pycore.get_module('mod')
+        module_with_imports = self.import_tools.get_module_with_imports(pymod)
+        module_with_imports.remove_duplicates()
+        self.assertEquals('import pkg1.mod1\nprint pkg1, pkg1.mod1\n',
+                          module_with_imports.get_changed_source())
+
     def test_trivial_expanding_star_imports(self):
         self.mod1.write('def a_func():\n    pass\ndef another_func():\n    pass\n')
         self.mod.write('from pkg1.mod1 import *\n')

File ropetest/refactortest.py

         refactored = rename_in_module.get_changed_module(pymodule=pymod)
         self.assertEquals('new_var = 10\nprint (1+new_var)\n', refactored)
     
+    def test_renaming_for_loop_variable(self):
+        code = 'for var in range(10):\n    print var\n'
+        refactored = self.do_local_rename(code, code.find('var') + 1, 'new_var')
+        self.assertEquals('for new_var in range(10):\n    print new_var\n',
+                          refactored)
+    
 
 class ExtractMethodTest(unittest.TestCase):