Commits

Anonymous committed 93a289d

Adding edit ~/.rope action

  • Participants
  • Parent commits b68bb3d

Comments (0)

Files changed (24)

docs/dev/issues.txt

 We can do::
 
   new_file = project.get_file('my_folder/my_file.txt')
-  new_file.create(create_directories=False)
+  new_file.create(create_folders=False)
 
 
 Rope's Preference System
           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
 ===========================
 

docs/dev/workingon.txt

 Saving Preferences
 ==================
 
-- Adding normal keybinding
-- Writing ``~/.rope`` if it does not exist
-- Renaming `rope.ui.codeassist` to `rope.ui.codeactions`
+- Allowing changes to be saved in no project
+- `PyCoreTest.test_not_leaking_for_vars_inside_parent_scope`;
+  For-loop variables leak in the parent scope
+- Singleton `NoProject`
+- Adding a ``Edit "~/.rope"`` action; ``C-x c``
+- Changing UI modules to default to `NoProject` rather than `None`
+- Providing code assists in `NoProject`
 
-* Adding a ``Edit "~/.rope"`` action
+* Convert every `os.path.sep` to ``/`` in `NoProject`
 
 
 Remaining Small Stories

docs/user/overview.txt

 project history             C-x p h
 --------------------------  -------------  -------------
 code-assist(auto-complete)  M-/            C-space
-go to definition location   C-c C-g        F3
+go to definition location   C-c g          F3
 show doc                    C-c C-d        F2
 show quick outline          C-c C-o        C-o
 correct line indentation    C-i            C-i

rope/base/oi/dynamicoi.py

+import marshal
 import os
 import re
 import socket
 import subprocess
 import sys
-import cPickle as pickle
-import marshal
 import tempfile
 import threading
 
-import rope
-from rope.base import pyobjects
-from rope.base import builtins
+import cPickle as pickle
+
+from rope.base import pyobjects, builtins
+import rope.base.project
 
 
 class DynamicObjectInference(object):
                 relative_path = relative_path[1:]
             resource = self.project.get_resource(relative_path)
         else:
-            resource = self.project.get_out_of_project_resource(path)
+            resource = rope.base.project.get_no_project().get_resource(path)
         return self.project.get_pycore().resource_to_pyobject(resource)
 
     def _get_pyobject_at(self, path, lineno):

rope/base/oi/runmod.py

             return ('unknown',)
 
         def _object_to_persisted_form(self, object_):
-            if object_ == None:
+            if object_ is None:
                 return ('none',)
             if isinstance(object_, types.CodeType):
                 return self._get_persisted_code(object_)

rope/base/project.py

         self.file_access = rope.base.fscommands.FileAccess()
         self._history = rope.base.history.History(maxundos=100)
         self.operations = rope.base.change._ResourceOperations(self, fscommands)
+        self.pycore = rope.base.pycore.PyCore(self)
 
     def get_resource(self, resource_name):
         """Get a resource in a project.
         if observer in self.observers:
             self.observers.remove(observer)
 
+    def do(self, changes):
+        """Apply the changes in a `ChangeSet`
+
+        Most of the time you call this function for committing the
+        changes for a refactoring.
+        """
+        self.history.do(changes)
+
+    def get_pycore(self):
+        return self.pycore
+
     def _get_resource_path(self, name):
         pass
 
         if fscommands is None:
             fscommands = rope.base.fscommands.create_fscommands(self._address)
         super(Project, self).__init__(fscommands)
-        self.pycore = rope.base.pycore.PyCore(self)
-        self.no_project = NoProject()
 
     root = property(lambda self: self.get_resource(''))
 
                 result.extend(self._get_files_recursively(folder))
         return result
 
-    def get_pycore(self):
-        return self.pycore
-
-    def get_out_of_project_resource(self, path):
-        return self.no_project.get_resource(path)
-
-    def do(self, changes):
-        """Apply the changes in a `ChangeSet`
-
-        Most of the time you call this function for committing the
-        changes for a refactoring.
-        """
-        self.history.do(changes)
-
 
 class NoProject(_Project):
-    """A null object for holding out of project files"""
+    """A null object for holding out of project files.
+
+    This class is singleton use `get_no_project` global function
+    """
 
     def __init__(self):
         fscommands = rope.base.fscommands.FileSystemCommands()
+        self.root = None
         super(NoProject, self).__init__(fscommands)
 
     def _get_resource_path(self, name):
     def get_resource(self, name):
         return super(NoProject, self).get_resource(os.path.abspath(name))
 
+    def get_files(self):
+        return []
+
+    _no_project = None
+
+
+def get_no_project():
+    if NoProject._no_project is None:
+        NoProject._no_project = NoProject()
+    return NoProject._no_project
+
 
 class Resource(object):
     """Represents files and folders in a project"""

rope/base/pycore.py

         result = []
         for src in sys.path:
             try:
-                src_folder = self.project.get_out_of_project_resource(src)
+                src_folder = rope.base.project.get_no_project().get_resource(src)
                 result.append(src_folder)
             except rope.base.exceptions.RopeError:
                 pass
 
     def get_source_folders(self):
         """Returns project source folders"""
+        if self.project.root is None:
+            return []
         return self._find_source_folders(self.project.root)
 
     def resource_to_pyobject(self, resource):

rope/base/pyobjects.py

         raise AttributeNotFoundError('Attribute %s not found' % name)
 
     def get_scope(self):
-        if self.scope == None:
+        if self.scope is None:
             self.scope = self._create_scope()
         return self.scope
 
                 assignment = pynames._Assignment(self.assigned_ast, index)
             self._assigned(name, assignment)
 
+
 class _ForAssignVisitor(_AssignVisitor):
 
     def __init__(self, scope_visitor, assigned):
         self.names[node.name] = DefinedName(pyobject)
         if len(node.argnames) > 0:
             new_visitor = _ClassInitVisitor(self, node.argnames[0])
-            compiler.walk(node, new_visitor)
+            for child in node.getChildNodes():
+                compiler.walk(child, new_visitor)
 
     def visitClass(self, node):
         self.names[node.name] = DefinedName(PyClass(self.pycore, node,
     def visitAssName(self, node):
         pass
 
+    def visitFunction(self, node):
+        pass
+
+    def visitClass(self, node):
+        pass
+
+    def visitFor(self, node):
+        pass
+
 
 class IsBeingInferredError(RopeError):
     pass

rope/base/pyscopes.py

 
         The returned scopes should be sorted by the order they appear
         """
-        if self.scopes == None:
+        if self.scopes is None:
             self.scopes = self._create_scopes()
         return self.scopes
 
         self.returned_asts = None
 
     def _get_names(self):
-        if self.names == None:
+        if self.names is None:
             self._visit_function()
         return self.names
 
     def _visit_function(self):
-        if self.names == None:
+        if self.names is None:
             new_visitor = rope.base.pyobjects._FunctionVisitor(self.pycore,
                                                                self.pyobject)
             for n in self.pyobject._get_ast().getChildNodes():
             self.returned_asts = new_visitor.returned_asts
 
     def _get_returned_asts(self):
-        if self.names == None:
+        if self.names is None:
             self._visit_function()
         return self.returned_asts
 

rope/refactor/importutils/actions.py

         if len(import_info.names_and_aliases) == len(self.import_info.names_and_aliases) == 1:
             imported1 = import_info.names_and_aliases[0]
             imported2 = self.import_info.names_and_aliases[0]
-            if imported1[1] == imported2[1] == None:
+            if imported1[1] == imported2[1] is None:
                 if imported1[0].startswith(imported2[0] + '.'):
                     return True
                 if imported2[0].startswith(imported1[0] + '.'):

rope/ui/codeactions.py

 
 actions.append(SimpleAction('code_assist', do_code_assist, 'M-slash',
                             MenuAddress(['Code', 'Code Assist (Auto-Complete)'], 'c'), ['python']))
-actions.append(SimpleAction('goto_definition', do_goto_definition, 'C-c C-g',
+actions.append(SimpleAction('goto_definition', do_goto_definition, 'C-c g',
                             MenuAddress(['Code', 'Goto Definition'], 'g'), ['python']))
 actions.append(SimpleAction('show_doc', do_show_doc, 'C-c C-d',
                             MenuAddress(['Code', 'Show Doc'], 's'), ['python']))
 import rope.ui.keybinder
 import rope.ui.statusbar
 from rope.base.exceptions import RopeError
-from rope.base.project import Project
+from rope.base.project import Project, get_no_project
 from rope.ui import editingcontexts
 from rope.ui.extension import ActionContext
 from rope.ui.menubar import MenuBarManager
             context.key_binding = rope.ui.keybinder.KeyBinder(
                 self.status_bar_manager)
         self.root.protocol('WM_DELETE_WINDOW', self._close_project_and_exit)
-        self.project = None
+        self.project = get_no_project()
         self.rebound_keys = {}
         self.actions = []
 
     def _load_dot_rope(self):
         dot_rope = os.path.expanduser('~%s.rope' % os.path.sep)
         if not os.path.exists(dot_rope):
-            import rope.ui.dot_rope
-            import inspect
-            text = inspect.getsource(rope.ui.dot_rope)
-            output = open(dot_rope, 'w')
-            output.write(text)
-            output.close()
+            write_dot_rope(dot_rope)
         run_globals = {}
         run_globals.update({'__name__': '__main__',
                             '__builtins__': __builtins__,
                             '__file__': dot_rope})
         execfile(dot_rope, run_globals)
 
-    def open_file(self, fileName):
-        if self.project is None:
+    def open_file(self, file_name):
+        if self.project is get_no_project():
             raise RopeError('No project is open')
-        file_ = self.project.get_resource(fileName)
+        file_ = self.project.get_resource(file_name)
         return self.editor_manager.get_resource_editor(file_)
 
     def activate_editor(self, editor):
             editor.save()
 
     def create_file(self, file_name):
-        if self.project is None:
+        if self.project is  get_no_project():
             raise RopeError('No project is open')
         try:
             last_slash = file_name.rindex('/')
     def close_project(self):
         while self.editor_manager.active_editor is not None:
             self.close_active_editor()
-        self.project = None
+        self.project = get_no_project()
 
     def create_folder(self, folder_name):
         try:
         else:
             self.root['menu'] = editingcontexts.none.menu
 
+    _core = None
+
     @staticmethod
     def get_core():
         """Get the singleton instance of Core"""
-        if not hasattr(Core, '_core'):
-            Core._core = Core()
-        return Core._core
+        result = Core._core
+        if result is None:
+            result = Core._core = Core()
+        return result
 
 
 def get_core():
     return Core.get_core()
+
+
+def write_dot_rope(dot_rope):
+    import rope.ui.dot_rope
+    import inspect
+    text = inspect.getsource(rope.ui.dot_rope)
+    output = open(dot_rope, 'w')
+    output.write(text)
+    output.close()

rope/ui/dot_rope.py

 # The default ~/.rope file for *rope*.
+#
+# You can edit this file using rope itself.
+#
+# Note: Since this file is not inside a project you cannot perform
+#   refactorings on it.
+#
 import rope.ui.core
 
 

rope/ui/editactions.py

 import Tkinter
+import os.path
 
 import rope.ui.core
 import rope.base.project
 
 
 def show_history(context):
-    if context.project is None:
+    if not context.project:
         return
     toplevel = Tkinter.Toplevel()
     toplevel.title('File History')
     context.editor.swap_mark_and_insert()
 
 
+_no_project = rope.base.project.NoProject()
+def edit_dot_rope(context):
+    resource = _no_project.get_resource(
+        os.path.expanduser('~%s.rope' % os.path.sep))
+    editor_manager = context.get_core().get_editor_manager()
+    editor_manager.get_resource_editor(resource, mode='python')
+
+
 core = rope.ui.core.Core.get_core()
 core._add_menu_cascade(MenuAddress(['Edit'], 'e'), ['all', 'none'])
 actions = []
 actions.append(SimpleAction('search_backward', backward_search, 'C-r',
                             MenuAddress(['Edit', 'Backward Search'], 'b', 3), ['all']))
 
+actions.append(SimpleAction('edit_dot_rope', edit_dot_rope, 'C-x c',
+                            MenuAddress(['Edit', 'Edit ~/.rope'], None, 4), ['all', 'none']))
+
+
 for action in actions:
     core.register_action(action)

rope/ui/editorpile.py

         self.editors.insert(0, editor)
         self.core._editor_changed()
 
-    def get_resource_editor(self, file_, readonly=False):
+    def get_resource_editor(self, file_, readonly=False, mode=None):
         for editor in self.editors:
             if editor.get_file() == file_:
                 self.buttons[editor].invoke()
                 return editor
         editor = rope.ui.fileeditor.FileEditor(
             self.core.get_open_project(), file_,
-            rope.ui.editor.GraphicalEditorFactory(self.editor_frame), readonly)
+            rope.ui.editor.GraphicalEditorFactory(self.editor_frame),
+            readonly=readonly, mode=mode)
         editor.get_editor().set_status_bar_manager(self.core.status_bar_manager)
         editor.add_change_observer(self._editor_was_changed)
         self.editors.append(editor)

rope/ui/fileactions.py

         pass
 
 def _check_if_project_is_open(core):
-    if not core.project:
+    if core.project is rope.base.project.get_no_project():
         tkMessageBox.showerror(parent=core.root, title='No Open Project',
                                message='No project is open')
         return False

rope/ui/fileeditor.py

 
 class FileEditor(object):
 
-    def __init__(self, project, file_, editor_factory, readonly=False):
+    def __init__(self, project, file_, editor_factory,
+                 readonly=False, mode=None):
         self.file = file_
         self.project = project
         editingcontext = None
-        if self.file.name.endswith('.py'):
+        if self.file.name.endswith('.py') or mode == 'python':
             editingcontext = editingcontexts.python
-        elif self.file.name.endswith('.txt'):
+        elif self.file.name.endswith('.txt') or mode == 'rest':
             editingcontext = editingcontexts.rest
         else:
             editingcontext = editingcontexts.others

rope/ui/helpactions.py

+import os.path
 import sys
-import os.path
+
 import Tkinter
 
-from rope.base.project import NoProject
 import rope.ui.core
+from rope.ui.extension import SimpleAction
 from rope.ui.menubar import MenuAddress
-from rope.ui.extension import SimpleAction
+from rope.base import project
 
-_no_project = NoProject()
 
 def show_about_dialog(context):
     toplevel = Tkinter.Toplevel()
 def show_doc(context, name):
     rope_package = (os.path.dirname(sys.modules['rope'].__file__))
     # Checking whether rope is installed or not
+    no_project = project.get_no_project()
     if 'docs' in os.listdir(rope_package):
         root = rope_package
-        resource = _no_project.get_resource(root + '/docs/' + name.split('/')[-1])
+        resource = no_project.get_resource(root + '/docs/' + name.split('/')[-1])
     else:
         root = os.path.dirname(rope_package)
-        resource = _no_project.get_resource(root + '/' + name)
+        resource = no_project.get_resource(root + '/' + name)
     editor_manager = context.get_core().get_editor_manager()
     editor_manager.get_resource_editor(resource, readonly=True)
 

rope/ui/highlighter.py

 
     def highlights(self, text, start, end):
         """Generates highlighted ranges as (start, end, style) tuples"""
-        if end == None:
+        if end is None:
             end = len(text)
         for match in self._get_pattern().finditer(text[start:end]):
             for key, value in match.groupdict().items():

rope/ui/menubar.py

         return -1
 
     def _find_location(self, name, group):
-        if group == None:
+        if group is None:
             group = 0
         index = 0
         current_group = 0

rope/ui/testview.py

 import Tkinter
 from SimpleXMLRPCServer import SimpleXMLRPCServer
 
+import rope.base.project
 from rope.ui.uihelpers import DescriptionList
 import rope.ui.runtest
 
                 pass
         try:
             server.register_instance(self.result)
-            run_test_py = self.project.get_out_of_project_resource(
+            run_test_py = rope.base.project.get_no_project().get_resource(
                 inspect.getsourcefile(rope.ui.runtest))
             self.process = self.project.get_pycore().run_module(
                 run_test_py, args=[str(rpc_port), self.resource.real_path])

rope/ui/uihelpers.py

         self.list.bind('<Alt-n>', lambda event: self.move_down())
 
     def insert_entry(self, entry, index=None):
-        if index == None:
+        if index is None:
             index = self.get_active_index()
         self.entries.insert(index, entry)
         self.list.insert(index, self.handle.entry_to_string(entry))
             self.list.selection_set(0)
 
     def remove_entry(self, index=None):
-        if index == None:
+        if index is None:
             index = self.get_active_index()
         result = self.entries[index]
         self.list.delete(index)
             self._select_entry(old_selection)
 
     def add_entry(self, entry, index=None, level=0):
-        if index == None:
+        if index is None:
             index = self.list.size()
         self.nodes.insert(index, _TreeNodeInformation(entry, level=level))
         self.list.insert(index, 4 * level * '  ' +

ropetest/projecttest.py

 import unittest
 import os
 
-from rope.base.project import Project, FilteredResourceObserver
+from rope.base.project import Project, NoProject, FilteredResourceObserver
 from rope.base.exceptions import RopeError
 from ropetest import testutils
 
         testutils.remove_recursively(self.project_root)
         self._make_sample_project()
         self.project = Project(self.project_root)
+        self.no_project = NoProject()
 
     def _make_sample_project(self):
         self.sample_file = 'sample_file.txt'
         testutils.remove_recursively(self.test_directory)
         os.mkdir(self.test_directory)
         self.project = Project(self.project_root)
+        self.no_project = NoProject()
 
     def tearDown(self):
         testutils.remove_recursively(self.project_root)
         sample_file = file(sample_file_path, 'w')
         sample_file.write('sample content\n')
         sample_file.close()
-        sample_resource = self.project.get_out_of_project_resource(sample_file_path)
+        sample_resource = self.no_project.get_resource(sample_file_path)
         self.assertEquals('sample content\n', sample_resource.read())
 
     def test_simple_out_of_project_folder(self):
         sample_folder_path = os.path.join(self.test_directory, 'sample_folder')
         os.mkdir(sample_folder_path)
-        sample_folder = self.project.get_out_of_project_resource(sample_folder_path)
+        sample_folder = self.no_project.get_resource(sample_folder_path)
         self.assertEquals([], sample_folder.get_children())
 
         sample_file_path = os.path.join(sample_folder_path, 'sample.txt')
         file(sample_file_path, 'w').close()
-        sample_resource = self.project.get_out_of_project_resource(sample_file_path)
+        sample_resource = self.no_project.get_resource(sample_file_path)
         self.assertEquals(sample_resource, sample_folder.get_children()[0])
 
     def test_using_absolute_path(self):
         sample_file_path = os.path.join(self.test_directory, 'sample.txt')
         file(sample_file_path, 'w').close()
-        normal_sample_resource = self.project.get_out_of_project_resource(sample_file_path)
+        normal_sample_resource = self.no_project.get_resource(sample_file_path)
         absolute_sample_resource = \
-            self.project.get_out_of_project_resource(os.path.abspath(sample_file_path))
+            self.no_project.get_resource(os.path.abspath(sample_file_path))
         self.assertEquals(normal_sample_resource, absolute_sample_resource)
 
     def test_folder_get_child(self):
         sample_folder_path = os.path.join(self.test_directory, 'sample_folder')
         os.mkdir(sample_folder_path)
-        sample_folder = self.project.get_out_of_project_resource(sample_folder_path)
+        sample_folder = self.no_project.get_resource(sample_folder_path)
         self.assertEquals([], sample_folder.get_children())
 
         sample_file_path = os.path.join(sample_folder_path, 'sample.txt')
         file(sample_file_path, 'w').close()
-        sample_resource = self.project.get_out_of_project_resource(sample_file_path)
+        sample_resource = self.no_project.get_resource(sample_file_path)
         self.assertTrue(sample_folder.has_child('sample.txt'))
         self.assertFalse(sample_folder.has_child('doesnothave.txt'))
         self.assertEquals(sample_resource, sample_folder.get_child('sample.txt'))

ropetest/pycoretest.py

         local_var = func_scope.get_name('a_var')
         self.assertEquals(global_var, local_var)
 
+    def test_not_leaking_for_vars_inside_parent_scope(self):
+        mod = self.pycore.create_module(self.project.root, 'mod')
+        mod.write('class C(object):\n    def f(self):\n'
+                  '        for my_var1, my_var2 in []:\n            pass\n')
+        pymod = self.pycore.resource_to_pyobject(mod)
+        c_class = pymod.get_attribute('C').get_object()
+        self.assertFalse('my_var1' in c_class.get_attributes())
+        self.assertFalse('my_var2' in c_class.get_attributes())
+
+    def test_not_leaking_for_vars_inside_parent_scope2(self):
+        mod = self.pycore.create_module(self.project.root, 'mod')
+        mod.write('class C(object):\n    def f(self):\n'
+                  '        for my_var in []:\n            pass\n')
+        pymod = self.pycore.resource_to_pyobject(mod)
+        c_class = pymod.get_attribute('C').get_object()
+        self.assertFalse('my_var' in c_class.get_attributes())
+
 
 class PyCoreInProjectsTest(unittest.TestCase):