Commits

Ali Gholami Rudi  committed 82ce987

Added Project.find_module
from module import name or *

  • Participants
  • Parent commits f8e5139

Comments (0)

Files changed (8)

File docs/stories.txt

 * Find occurances @ 5
 
 
-* Open Type @ 2
-
-
 * Configuring keys @ 2
 
 
   Add a graphical view for running tests.
 
 
+* Open Type @ 2
+
+
 * Enhance open dialog @ 1
 
 
 * Auto-completing function parameter names when calling @ 2
 
 
-* Lambdas and auto-completion @ 1
+* Control blocks and auto-completion @ 1
+  Completions for for-loop, except, lambda and with variables
 
 
 * Auto completion type @ 3
   * Sorting proposals
 
 
+* Auto completing and comments and strings @ 1
+
+
 * Auto completion after "."s @ 3
   * Auto-completing "self."s
 
 
-* Auto completing and comments and strings @ 1
-
-
 > Public release 0.2 : June 4, 2006
 
 

File docs/workingon.txt

---- Auto-completion should ignore current statement @ 2 ---
-  What if the statement in current line is spread in more than one line.
+*** Auto-complete from-import imported objects @ 3 ***
 
-- More tests for explicit and implicit continuations
-? Transform big unextractible methods into method objects
-- Not proposing variables defined after current line in the same scope
-- Ignoring """ or ''' string content
-- scopes_count does not work because there might be loops and other blocks
+- Add Project.find_module(module_name) which should return a list
+- Resource.__hash__
+- imports inside functions
+- from module import *
+- Add new TestCase to runtests.py
 
+* Star in functions
+* from mod import * should not import names starting with an underscore
+* from package import package
+? from name import *: loads everything without starting underscore or __all__
+? Packages: First look in the __init__.py module for that name and if
+  it did not exist, look for submodules or packages
+? Reduce the duplication in visitors in codeassist.py
 
+? Better version number selection
 ? Add rope.scopes module
-? Completions for for-loop, except, lambda, with variables
+? Completions are context dependant
 ? Remote pair programming support
-? Completions are context dependant
 ? Separating ui modules and packages
     ? Decide which modules are the domain and which are the presentation
     ? Should editing tools access Editor directly? Which of them?

File rope/codeassist.py

 
 
 class _FunctionScopeVisitor(object):
-    def __init__(self, starting, start_line):
+    def __init__(self, project, starting, start_line):
+        self.project = project
         self.starting = starting
         self.scope = _Scope(start_line, {}, [])
 
             if imported.startswith(self.starting):
                 self.scope.var_dict[imported] = CompletionProposal(imported, 'module')
 
+    def visitFrom(self, node):
+        global_names = _get_global_names_in_module(self.project, node.modname)
+        if node.names[0][0] == '*':
+            for (name, kind) in global_names.iteritems():
+                if name.startswith(self.starting):
+                    self.scope.var_dict[name] = CompletionProposal(name, kind)
+            return
+        for (name, alias) in node.names:
+            imported = name
+            if alias is not None:
+                imported = alias
+            if imported.startswith(self.starting):
+                if global_names.has_key(name):
+                    self.scope.var_dict[imported] = CompletionProposal(imported, global_names[name])
+                else:
+                    self.scope.var_dict[imported] = CompletionProposal(imported, 'unknown')
+
     def visitAssName(self, node):
         if node.name.startswith(self.starting):
             self.scope.var_dict[node.name] = CompletionProposal(node.name, 'local_variable')
     def visitFunction(self, node):
         if node.name.startswith(self.starting):
             self.scope.var_dict[node.name] = CompletionProposal(node.name, 'function')
-        new_visitor = _FunctionScopeVisitor.walk_function(self.starting, node)
+        new_visitor = _FunctionScopeVisitor.walk_function(self.project, self.starting, node)
         self.scope.children.append(new_visitor.scope)
 
     def visitClass(self, node):
         if node.name.startswith(self.starting):
             self.result[node.name] = CompletionProposal(node.name, 'class')
-        new_visitor = _ClassScopeVisitor.walk_class(self.starting, node)
+        new_visitor = _ClassScopeVisitor.walk_class(self.project, self.starting, node)
         self.scope.children.append(new_visitor.scope)
 
     @staticmethod
-    def walk_function(starting, function_node):
-        new_visitor = _FunctionScopeVisitor(starting, function_node.lineno)
+    def walk_function(project, starting, function_node):
+        new_visitor = _FunctionScopeVisitor(project, starting, function_node.lineno)
         for arg in function_node.argnames:
             if arg.startswith(starting):
                 new_visitor.scope.var_dict[arg] = CompletionProposal(arg, 'local_variable')
 
 
 class _ClassScopeVisitor(object):
-    def __init__(self, starting, start_line):
+    def __init__(self, project, starting, start_line):
+        self.project = project
         self.starting = starting
         self.scope = _Scope(start_line, {}, [])
 
         pass
 
     def visitFunction(self, node):
-        new_visitor = _FunctionScopeVisitor.walk_function(self.starting, node)
+        new_visitor = _FunctionScopeVisitor.walk_function(self.project, self.starting, node)
         self.scope.children.append(new_visitor.scope)
 
     def visitClass(self, node):
-        new_visitor = _ClassScopeVisitor.walk_class(self.starting, node)
+        new_visitor = _ClassScopeVisitor.walk_class(self.project, self.starting, node)
         self.scope.children.append(new_visitor.scope)
 
     @staticmethod
-    def walk_class(starting, class_node):
-        new_visitor = _ClassScopeVisitor(starting, class_node.lineno)
+    def walk_class(project, starting, class_node):
+        new_visitor = _ClassScopeVisitor(project, starting, class_node.lineno)
         for node in class_node.getChildNodes():
             compiler.walk(node, new_visitor)
         return new_visitor
 
 
+def _get_global_names_in_module(project, modname):
+    found_modules = project.find_module(modname)
+    if not found_modules:
+        return {}
+    
+    result = {}
+    class _GlobalModuleVisitor(object):
+        def visitFunction(self, node):
+            result[node.name] = 'function'
+        def visitClass(self, node):
+            result[node.name] =  'class'
+        def visitAssName(self, node):
+            result[node.name] = 'global_variable'
+    ast = compiler.parse(found_modules[0].read())
+    compiler.walk(ast, _GlobalModuleVisitor())
+    return result
+    
+
 class _GlobalScopeVisitor(object):
     
-    def __init__(self, starting):
+    def __init__(self, project, starting):
+        self.project = project
         self.starting = starting
         self.scope = _Scope(0, {}, [])
 
             if imported.startswith(self.starting):
                 self.scope.var_dict[imported] = CompletionProposal(imported, 'module')
 
+    def visitFrom(self, node):
+        global_names = _get_global_names_in_module(self.project, node.modname)
+        if node.names[0][0] == '*':
+            for (name, kind) in global_names.iteritems():
+                if name.startswith(self.starting):
+                    self.scope.var_dict[name] = CompletionProposal(name, kind)
+            return
+        for (name, alias) in node.names:
+            imported = name
+            if alias is not None:
+                imported = alias
+            if imported.startswith(self.starting):
+                if global_names.has_key(name):
+                    self.scope.var_dict[imported] = CompletionProposal(imported, global_names[name])
+                else:
+                    self.scope.var_dict[imported] = CompletionProposal(imported, 'unknown')
+
     def visitAssName(self, node):
         if node.name.startswith(self.starting):
             self.scope.var_dict[node.name] = CompletionProposal(node.name, 'global_variable')
     def visitFunction(self, node):
         if node.name.startswith(self.starting):
             self.scope.var_dict[node.name] = CompletionProposal(node.name, 'function')
-        new_visitor = _FunctionScopeVisitor.walk_function(self.starting, node)
+        new_visitor = _FunctionScopeVisitor.walk_function(self.project, self.starting, node)
         self.scope.children.append(new_visitor.scope)
 
     def visitClass(self, node):
         if node.name.startswith(self.starting):
             self.scope.var_dict[node.name] = CompletionProposal(node.name, 'class')
-        new_visitor = _ClassScopeVisitor.walk_class(self.starting, node)
+        new_visitor = _ClassScopeVisitor.walk_class(self.project, self.starting, node)
         self.scope.children.append(new_visitor.scope)
 
 
 
 
 class CodeAssist(ICodeAssist):
-    def __init__(self, indentation_length=4):
-        self.indentation_length = indentation_length
+    def __init__(self, project):
+        self.project = project
         self.builtins = [str(name) for name in dir(__builtin__)
                          if not name.startswith('_')]
         import keyword
             code_ast = compiler.parse(commented_source_code)
         except SyntaxError, e:
             raise RopeSyntaxError(e)
-        visitor = _GlobalScopeVisitor(starting)
+        visitor = _GlobalScopeVisitor(self.project, starting)
         compiler.walk(code_ast, visitor)
         result = self._get_all_completions(visitor.scope, lines, lineno)
         if len(starting) > 0:

File rope/editor.py

             mark = self.text.index('mark')
             self.set_mark()
             self.text.mark_set(INSERT, mark)
+            self.text.see(INSERT)
         except TclError:
             pass
 

File rope/project.py

             os.mkdir(self.root)
         elif not os.path.isdir(self.root):
             raise RopeException('Project root exists and is not a directory')
-        self.code_assist = rope.codeassist.CodeAssist()
+        self.code_assist = rope.codeassist.CodeAssist(self)
 
     def get_root_folder(self):
         return Folder(self, '')
         return False
 
     def _find_source_folders(self, folder):
-        for resource in folder.get_files():
-            if resource.get_name().endswith('.py'):
-                return [folder]
         for resource in folder.get_folders():
             if self._is_package(resource):
                 return [folder]
         result = []
+        for resource in folder.get_files():
+            if resource.get_name().endswith('.py'):
+                result.append(folder)
         for resource in folder.get_folders():
             result.extend(self._find_source_folders(resource))
         return result
         created_package.create_file('__init__.py')
         return created_package
 
+    def find_module(self, module_name):
+        source_folders = self.get_source_folders()
+        packages = module_name.split('.')
+        result = []
+        for src in source_folders:
+            current_resource = src
+            found = True
+            for pkg in packages[:-1]:
+                try:
+                    if not current_resource.is_folder():
+                        found = False
+                        break
+                    current_resource = current_resource.get_child(pkg)
+                except RopeException, e:
+                    found = False
+                    break
+            try:
+                if current_resource.is_folder():
+                    current_resource = current_resource.get_child(packages[-1] + '.py')
+                else:
+                    found = False
+            except RopeException, e:
+                found = False
+            if found:
+                result.append(current_resource)
+        return result
+
+
     def get_code_assist(self):
         return self.code_assist
 
             return False
         return self.get_path() == resource.get_path()
 
+    def __hash__(self, resource):
+        return hash(self.get_path())
+
     def _get_real_path(self):
         return self.project._get_resource_path(self.fileName)
 
             return False
         return self.get_path() == resource.get_path()
 
+    def __hash__(self, resource):
+        return hash(self.get_path())
+
     def get_project(self):
         return self.project
 

File ropetest/codeassisttest.py

+import os
 import unittest
 
 from rope.codeassist import CodeAssist, RopeSyntaxError
+from rope.project import Project
+
+def _remove_recursively(file):
+    for root, dirs, files in os.walk(file, topdown=False):
+        for name in files:
+            os.remove(os.path.join(root, name))
+        for name in dirs:
+            os.rmdir(os.path.join(root, name))
+    os.rmdir(file)
 
 class CodeAssistTest(unittest.TestCase):
     def setUp(self):
         super(CodeAssistTest, self).setUp()
-        self.assist = CodeAssist()
+        self.project_root = 'sample_project'
+        os.mkdir(self.project_root)
+        self.project = Project(self.project_root)
+        self.assist = self.project.get_code_assist()
         
     def tearDown(self):
+        _remove_recursively(self.project_root)
         super(CodeAssistTest, self).tearDown()
 
     def test_simple_assist(self):
         self.assert_proposal_in_result('my_var', 'global_variable', result)
 
 
+class CodeAssistInProjectsTest(unittest.TestCase):
+    def setUp(self):
+        super(CodeAssistInProjectsTest, self).setUp()
+        self.project_root = 'sample_project'
+        os.mkdir(self.project_root)
+        self.project = Project(self.project_root)
+        samplemod = self.project.create_module(self.project.get_root_folder(), 'samplemod')
+        samplemod.write("class SampleClass(object):\n    def sample_method():\n        pass" + \
+                        "\n\ndef sample_func():\n    pass\nsample_var = 10\n")
+        self.assist = self.project.get_code_assist()
+
+    def assert_proposal_in_result(self, completion, kind, result):
+        for proposal in result.proposals:
+            if proposal.completion == completion and proposal.kind == kind:
+                return
+        self.fail('completion <%s> not proposed' % completion)
+
+
+    def assert_proposal_not_in_result(self, completion, kind, result):
+        for proposal in result.proposals:
+            if proposal.completion == completion and proposal.kind == kind:
+                self.fail('completion <%s> was proposed' % completion)
+
+
+    def tearDown(self):
+        _remove_recursively(self.project_root)
+        super(self.__class__, self).tearDown()
+
+    def test_simple_import(self):
+        code = 'import samplemod\nsample'
+        result = self.assist.complete_code(code, len(code))
+        self.assert_proposal_in_result('samplemod', 'module', result)
+
+    def test_from_import_class(self):
+        code = 'from samplemod import SampleClass\nSample'
+        result = self.assist.complete_code(code, len(code))
+        self.assert_proposal_in_result('SampleClass', 'class', result)
+
+    def test_from_import_function(self):
+        code = 'from samplemod import sample_func\nsample'
+        result = self.assist.complete_code(code, len(code))
+        self.assert_proposal_in_result('sample_func', 'function', result)
+
+    def test_from_import_variable(self):
+        code = 'from samplemod import sample_var\nsample'
+        result = self.assist.complete_code(code, len(code))
+        self.assert_proposal_in_result('sample_var', 'global_variable', result)
+
+    def test_from_imports_inside_functions(self):
+        code = 'def f():\n    from samplemod import SampleClass\n    Sample'
+        result = self.assist.complete_code(code, len(code))
+        self.assert_proposal_in_result('SampleClass', 'class', result)
+
+    def test_from_import_only_imports_imported(self):
+        code = 'from samplemod import sample_func\nSample'
+        result = self.assist.complete_code(code, len(code))
+        self.assert_proposal_not_in_result('SampleClass', 'class', result)
+
+    def test_from_import_star(self):
+        code = 'from samplemod import *\nSample'
+        result = self.assist.complete_code(code, len(code))
+        self.assert_proposal_in_result('SampleClass', 'class', result)
+        code = 'from samplemod import *\nsample'
+        result = self.assist.complete_code(code, len(code))
+        self.assert_proposal_in_result('sample_func', 'function', result)
+        self.assert_proposal_in_result('sample_var', 'global_variable', result)
+
+
 if __name__ == '__main__':
     unittest.main()

File ropetest/projecttest.py

         self.assertTrue(src in source_folders)
         self.assertTrue(test in source_folders)
 
+    def test_multi_source_folders2(self):
+        mod1 = self.project.create_module(self.project.get_root_folder(), 'mod1')
+        src = self.project.get_root_folder().create_folder('src')
+        package = self.project.create_package(src, 'package')
+        mod2 = self.project.create_module(package, 'mod2')
+        source_folders = self.project.get_source_folders()
+        self.assertEquals(2, len(source_folders))
+        self.assertTrue(self.project.get_root_folder() in source_folders and \
+                        src in source_folders)
+
     def test_ignoring_dot_star_folders_in_get_files(self):
         root = self.project.get_root_address()
         dot_test = os.path.join(root, '.test')
         nested_package = self.project.create_package(src, 'pkg1.pkg2')
         self.assertEquals(self.project.get_resource('src/pkg1/pkg2'), nested_package)
 
+    def test_find_module(self):
+        src = self.project.get_root_folder().create_folder('src')
+        samplemod = self.project.create_module(src, 'samplemod')
+        found_modules = self.project.find_module('samplemod')
+        self.assertEquals(1, len(found_modules))
+        self.assertEquals(samplemod, found_modules[0])
+
+    def test_find_nested_module(self):
+        src = self.project.get_root_folder().create_folder('src')
+        samplepkg = self.project.create_package(src, 'samplepkg')
+        samplemod = self.project.create_module(samplepkg, 'samplemod')
+        found_modules = self.project.find_module('samplepkg.samplemod')
+        self.assertEquals(1, len(found_modules))
+        self.assertEquals(samplemod, found_modules[0])
+
+    def test_find_multiple_module(self):
+        src = self.project.get_root_folder().create_folder('src')
+        samplemod1 = self.project.create_module(src, 'samplemod')
+        samplemod2 = self.project.create_module(self.project.get_root_folder(), 'samplemod')
+        test = self.project.get_root_folder().create_folder('test')
+        samplemod3 = self.project.create_module(test, 'samplemod')
+        found_modules = self.project.find_module('samplemod')
+        self.assertEquals(3, len(found_modules))
+        self.assertTrue(samplemod1 in found_modules and samplemod2 in found_modules and \
+                        samplemod3 in found_modules)
+
 
 class FileFinderTest(unittest.TestCase):
     def setUp(self):
     result.addTests(unittest.makeSuite(ropetest.highlighttest.HighlightTest))
     result.addTests(unittest.makeSuite(ropetest.indentertest.PythonCodeIndenterTest))
     result.addTests(unittest.makeSuite(ropetest.codeassisttest.CodeAssistTest))
+    result.addTests(unittest.makeSuite(ropetest.codeassisttest.CodeAssistInProjectsTest))
     result.addTests(unittest.makeSuite(ropetest.statusbartest.StatusBarTest))
     runner = unittest.TextTestRunner()
     runner.run(result)