1. zjes
  2. rope_py3k

Commits

Ali Gholami Rudi  committed 4dbd1b3

Using TaskHandle for history actions

  • Participants
  • Parent commits 11988bc
  • Branches trunk

Comments (0)

Files changed (23)

File README.txt

View file
  • Ignore whitespace
 New Features
 ============
 
-* `Stoppable refactorings`_
-* `Basic implicit interfaces`_
-* `Spell-Checker`_
-* `Automatic SOI analysis`_
-* `Renaming occurrences in strings and comments`_
-* Faster occurrence finding
-
-Basic Implicit Interfaces
--------------------------
-
-Implicit interfaces are the interfaces that you don't explicitly
-define; But you expect a group of classes to have some common
-attributes.  These kinds of interfaces are very common in dynamic
-languages; Since we only have implementation inheritance and not
-interface inheritance.  For instance::
-
-  class A(object):
-
-      def count(self):
-          pass
-
-  class B(object):
-
-      def count(self):
-          pass
-
-  def count_for(arg):
-      return arg.count()
-
-  count_for(A())
-  count_for(B())
-
-Here we know that there is an implicit interface defined by the
-function `count_for` that provides `count()`.  Here when we rename
-`A.count()` we expect `B.count()` to be renamed, too.  Currently rope
-supports a basic form of implicit interfaces.  When you try to rename
-an attribute of a parameter, rope renames that attribute for all
-objects that have been passed to that function in different call
-sites.  That is renaming the occurrence of `count` in `count_for`
-function to `newcount` will result in::
-
-  class A(object):
-
-      def newcount(self):
-          pass
-
-  class B(object):
-
-      def newcount(self):
-          pass
-
-  def count_for(arg):
-      return arg.newcount()
-
-  count_for(A())
-  count_for(B())
-
-
-This also works for change method signature.  Note that this feature
-relies on rope's object inference mechanisms to find out the
-parameters that are passed to a function.  Also see the `automatic SOI
-analysis`_ that is added in this release.
-
-Renaming Occurrences In Strings And Comments
---------------------------------------------
-
-You can tell rope to rename all occurrences of a name in comments and
-strings.  This can be done in rename refactoring dialog by selecting
-its radio button or by passing ``docs=True`` to `Rename.get_changes()`
-method when using rope as a library.  Rope renames names in comments
-and strings only when the name is visible there.  For example in::
-
-  def f():
-      a_var = 1
-      print 'a_var = %s' % a_var
-
-  # f prints a_var
-
-after we rename the `a_var` local variable in `f()` to `new_var` we
-would get::
-
-  def f():
-      new_var = 1
-      print 'new_var = %s' % new_var
-
-  # f prints a_var
-
-This makes it safe to assume that this option does not perform wrong
-renames most of the time and for this reason it is by default on in
-the UI (though not in `Rename.get_changes()`).
-
-Stoppable Refactorings
-----------------------
-
-Another notable new feature is stoppable refactorings.  Some
-refactorings might take a long time to finish (based on the size of
-your project).  Rope now shows a dialog that has a progress bar and a
-stop button for these refactorings.  You can also use this feature
-when using rope as a library.  The `get_changes()` method of these
-refactorings take a new parameter called `task_handle`.  If you want
-to monitor or stop these refactoring you can pass a `rope.refactor.
-taskhandle.TaskHandle` to this method.  See `rope.refactor.taskhandle`
-module for more information.
-
-Automatic SOI Analysis
-----------------------
-
-Maybe the most important internal feature added in this release is
-automatic static object inference analysis.  When turned on, it
-analyzes the changed scopes of a file when saving for obtaining object
-information; So this might make saving files a bit more time
-consuming.  This feature is by default turned on, but you can turn it
-off by editing your project ``config.py`` file (available in
-``${your_project_root}/.ropeproject/config.py``, if you're new to
-rope), though that is not recommended.
-
-Spell-Checker
--------------
-
-The new spell-checker uses ispell/aspell if available.  You can use
-``M-$`` like emacs for checking current word.  You can also use ``C-x
-$ r`` and ``C-x $ b`` for spell-checking region and buffer.
+*
 
 
 Getting Started

File docs/dev/workingon.txt

View file
  • Ignore whitespace
 Small Stories
 =============
 
+- Moving `rope.refactor.taskhandle` to `rope.base`
+- Using `TaskHandle` for `History.do()`;
+
 * Refactor `rope.refactor.move`
 
   * nothing is cached; such as OccurrenceFinder
   * Extract class _Mover
-  * Changing modules look similar
+  * Changing resources for move module/global look similar
 
 * Better local history: Showing older versions of files; filtered history
-* Using `TaskHandle` for `History.do()`;
-  moving `rope.refactor.taskhandle` to `rope.base`
 * Should syntax errors in files stop refactorings?
 
 * Validating callinfo

File docs/user/overview.txt

View file
  • Ignore whitespace
 froms to imports            C-c i i
 handle long imports         C-c i l
 --------------------------  -------------  -------------
-Generate variable           C-c n v        M-G v
-Generate function/method    C-c n f        M-G f
-Generate class              C-c n c        M-G c
-Generate module             C-c n m        M-G m
-Generate package            C-c n p        M-G p
+generate variable           C-c n v        M-G v
+generate function/method    C-c n f        M-G f
+generate class              C-c n c        M-G c
+generate module             C-c n m        M-G m
+generate package            C-c n p        M-G p
+--------------------------  -------------  -------------
+spell-check word            M-$
+spell-check buffer          C-x $ b
+spell-check region          C-x $ r
 --------------------------  -------------  -------------
 about                       C-h a
 README                      C-h r
     newmod.py
 
 
+Renaming Occurrences In Strings And Comments
+--------------------------------------------
+
+You can tell rope to rename all occurrences of a name in comments and
+strings.  This can be done in rename refactoring dialog by selecting
+its radio button or by passing ``docs=True`` to `Rename.get_changes()`
+method when using rope as a library.  Rope renames names in comments
+and strings only when the name is visible there.  For example in::
+
+  def f():
+      a_var = 1
+      print 'a_var = %s' % a_var
+
+  # f prints a_var
+
+after we rename the `a_var` local variable in `f()` to `new_var` we
+would get::
+
+  def f():
+      new_var = 1
+      print 'new_var = %s' % new_var
+
+  # f prints a_var
+
+This makes it safe to assume that this option does not perform wrong
+renames most of the time and for this reason it is by default on in
+the UI (though not in `Rename.get_changes()`).
+
+
 Move Method Refactoring
 -----------------------
 
 length more than 27 characters to be long.
 
 
+Stoppable Refactorings
+----------------------
+
+Another notable new feature is stoppable refactorings.  Some
+refactorings might take a long time to finish (based on the size of
+your project).  Rope now shows a dialog that has a progress bar and a
+stop button for these refactorings.  You can also use this feature
+when using rope as a library.  The `get_changes()` method of these
+refactorings take a new parameter called `task_handle`.  If you want
+to monitor or stop these refactoring you can pass a `rope.refactor.
+taskhandle.TaskHandle` to this method.  See `rope.refactor.taskhandle`
+module for more information.
+
+Basic Implicit Interfaces
+-------------------------
+
+Implicit interfaces are the interfaces that you don't explicitly
+define; But you expect a group of classes to have some common
+attributes.  These kinds of interfaces are very common in dynamic
+languages; Since we only have implementation inheritance and not
+interface inheritance.  For instance::
+
+  class A(object):
+
+      def count(self):
+          pass
+
+  class B(object):
+
+      def count(self):
+          pass
+
+  def count_for(arg):
+      return arg.count()
+
+  count_for(A())
+  count_for(B())
+
+Here we know that there is an implicit interface defined by the
+function `count_for` that provides `count()`.  Here when we rename
+`A.count()` we expect `B.count()` to be renamed, too.  Currently rope
+supports a basic form of implicit interfaces.  When you try to rename
+an attribute of a parameter, rope renames that attribute for all
+objects that have been passed to that function in different call
+sites.  That is renaming the occurrence of `count` in `count_for`
+function to `newcount` will result in::
+
+  class A(object):
+
+      def newcount(self):
+          pass
+
+  class B(object):
+
+      def newcount(self):
+          pass
+
+  def count_for(arg):
+      return arg.newcount()
+
+  count_for(A())
+  count_for(B())
+
+
+This also works for change method signature.  Note that this feature
+relies on rope's object inference mechanisms to find out the
+parameters that are passed to a function.
+
+
 Basic Object Inference
 ======================
 
   mod1.func(mod1.C2()).${codeassist}
 
 
+Automatic SOI Analysis
+----------------------
+
+Maybe the most important internal feature added in this release is
+automatic static object inference analysis.  When turned on, it
+analyzes the changed scopes of a file when saving for obtaining object
+information; So this might make saving files a bit more time
+consuming.  This feature is by default turned on, but you can turn it
+off by editing your project ``config.py`` file (available in
+``${your_project_root}/.ropeproject/config.py``, if you're new to
+rope), though that is not recommended.
+
+
 Outline
 =======
 
 see and select changes to be undone in any order.  Note that undoing
 changes in project history undoes the changes it depends on, too.
 
+
+Spell-Checker
+=============
+
+The new spell-checker uses ispell/aspell if available.  You can use
+``M-$`` like emacs for checking current word.  You can also use ``C-x
+$ r`` and ``C-x $ b`` for spell-checking region and buffer.

File rope/__init__.py

View file
  • Ignore whitespace
 """rope, a python refactoring library and IDE"""
 
-VERSION = '0.5m5'
+VERSION = '0.5rc1'

File rope/base/change.py

View file
  • Ignore whitespace
+import datetime
 import difflib
 import os
 import time
-import datetime
 
+from rope.base import taskhandle
 from rope.base.exceptions import RopeError
 from rope.base.fscommands import FileSystemCommands
 
 
 class Change(object):
 
-    def do(self, resource_operations):
+    def do(self, job_set=None):
         pass
 
-    def undo(self, resource_operations):
+    def undo(self, job_set=None):
         pass
 
     def get_description(self):
         self.description = description
         self.time = timestamp
 
-    def do(self):
+    def do(self, job_set=taskhandle.NullJobSet()):
         try:
             done = []
             for change in self.changes:
-                change.do()
+                change.do(job_set)
                 done.append(change)
             self.time = time.time()
         except Exception:
                 change.undo()
             raise
 
-    def undo(self):
+    def undo(self, job_set=taskhandle.NullJobSet()):
         try:
             done = []
             for change in reversed(self.changes):
-                change.undo()
+                change.undo(job_set)
                 done.append(change)
         except Exception:
             for change in done:
         return result
 
 
+def _handle_job_set(function):
+    """A decorator for handling `taskhandle.JobSet`\s
+    
+    A decorator for handling `taskhandle.JobSet`\s for `do` and `undo`
+    methods of `Change`\s.
+    """
+    def call(self, job_set=taskhandle.NullJobSet()):
+        job_set.started_job(str(self))
+        function(self)
+        job_set.finished_job()
+    return call
+
+
 class ChangeContents(Change):
 
     def __init__(self, resource, new_content, old_content=None):
                 self.old_content = self.resource.read()
         self.operations = self.resource.project.operations
 
+    @_handle_job_set
     def do(self):
         if self.old_content is None:
             self.old_content = self.resource.read()
         self.operations.write_file(self.resource, self.new_content)
 
+    @_handle_job_set
     def undo(self):
         self.operations.write_file(self.resource, self.old_content)
 
         else:
             self.new_resource = self.project.get_file(new_location)
 
+    @_handle_job_set
     def do(self):
         self.operations.move(self.old_resource, self.new_resource.path)
 
+    @_handle_job_set
     def undo(self):
         self.operations.move(self.new_resource, self.old_resource.path)
 
     def __str__(self):
-        return 'Move <%s>' % self.old_location
+        return 'Move <%s>' % self.old_resource.path
 
     def get_description(self):
         return 'Move <%s> to <%s>' % (self.old_resource.path,
         self.resource = resource
         self.operations = self.resource.project.operations
 
+    @_handle_job_set
     def do(self):
         self.operations.create(self.resource)
 
+    @_handle_job_set
     def undo(self):
         self.operations.remove(self.resource)
 
         self.resource = resource
         self.operations = resource.project.operations
 
+    @_handle_job_set
     def do(self):
         self.operations.remove(self.resource)
 
     # TODO: Undoing remove operations
+    @_handle_job_set
     def undo(self):
         raise NotImplementedError(
             'Undoing `RemoveResource` is not implemented yet.')
         return [self.resource]
 
 
+def count_changes(change):
+    """Counts the number of basic changes a `Change` will make"""
+    if isinstance(change, ChangeSet):
+        result = 0
+        for child in change.changes:
+            result += count_changes(child)
+        return result
+    return 1
+
+def create_job_set(task_handle, change):
+    return task_handle.create_job_set(str(change), count_changes(change))
+
+
 class _ResourceOperations(object):
 
     def __init__(self, project, fscommands):

File rope/base/history.py

View file
  • Ignore whitespace
-from rope.base import exceptions, change
+from rope.base import exceptions, change, taskhandle
 import cPickle as pickle
 
 
 
     history_file = property(_get_history_file)
 
-    def do(self, changes):
+    def do(self, changes, task_handle=taskhandle.NullTaskHandle()):
         self.current_change = changes
         try:
-            changes.do()
+            changes.do(change.create_job_set(task_handle, changes))
         finally:
             self.current_change = None
         if self._is_change_interesting(changes):
                 return True
         return False
 
-    def undo(self, change=None):
+    def undo(self, change=None, task_handle=taskhandle.NullTaskHandle()):
         if not self._undo_list:
             raise exceptions.HistoryError('Undo list is empty')
         if change is None:
         dependencies = self.find_dependencies(change)
         self._move_front(dependencies)
         index = self.undo_list.index(change)
-        self._perform_undos(len(self.undo_list) - index)
+        self._perform_undos(len(self.undo_list) - index, task_handle)
 
     def _move_front(self, changes):
         for change in changes:
         return _FindChangeDependencies(self.undo_list[index:]).\
                find_dependencies()
 
-    def _perform_undos(self, count):
+    def _perform_undos(self, count, task_handle):
         for i in range(count):
             self.current_change = self.undo_list[-1]
             try:
-                self.current_change.undo()
+                job_set = change.create_job_set(task_handle,
+                                                self.current_change)
+                self.current_change.undo(job_set)
             finally:
                 self.current_change = None
             self.redo_list.append(self.undo_list.pop())
 
-    def redo(self):
+    def redo(self, task_handle=taskhandle.NullTaskHandle()):
         if not self.redo_list:
             raise exceptions.HistoryError('Redo list is empty')
         self.current_change = self.redo_list[-1]
         try:
-            self.current_change.do()
+            job_set = change.create_job_set(task_handle, self.current_change)
+            self.current_change.do(job_set=job_set)
         finally:
             self.current_change = None
         self.undo_list.append(self.redo_list.pop())

File rope/base/project.py

View file
  • Ignore whitespace
 import rope.base.history
 import rope.base.prefs
 import rope.base.pycore
+from rope.base import taskhandle
 from rope.base.exceptions import RopeError
 from rope.base.resources import File, Folder
 
         if observer in self.observers:
             self.observers.remove(observer)
 
-    def do(self, changes):
+    def do(self, changes, task_handle=taskhandle.NullTaskHandle()):
         """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)
+        self.history.do(changes, task_handle=task_handle)
 
     def get_pycore(self):
         if self._pycore is None:

File rope/base/taskhandle.py

View file
  • Ignore whitespace
+from rope.base import exceptions
+
+
+class TaskHandle(object):
+
+    def __init__(self, name='Task'):
+        self.name = name
+        self.stopped = False
+        self.job_sets = []
+        self.observers = []
+
+    def is_stopped(self):
+        return self.stopped
+
+    def stop(self):
+        self.stopped = True
+        self._inform_observers()
+
+    def create_job_set(self, name='JobSet', count=None):
+        result = JobSet(self, name=name, count=count)
+        self.job_sets.append(result)
+        self._inform_observers()
+        return result
+
+    def get_job_sets(self):
+        return self.job_sets
+
+    def add_observer(self, observer):
+        """Register an observer for this task handle
+
+        The observer is notified whenever the task is stopped or
+        a job gets finished.
+        """
+        self.observers.append(observer)
+
+    def _inform_observers(self):
+        for observer in list(self.observers):
+            observer()
+
+
+class JobSet(object):
+
+    def __init__(self, handle, name, count):
+        self.handle = handle
+        self.name = name
+        self.count = count
+        self.done = 0
+        self.job_name = None
+
+    def started_job(self, name):
+        self.check_status()
+        self.job_name = name
+        self.handle._inform_observers()
+
+    def finished_job(self):
+        self.check_status()
+        self.handle._inform_observers()
+        self.job_name = None
+        self.done += 1
+
+    def check_status(self):
+        if self.handle.is_stopped():
+            raise exceptions.InterruptedTaskError()
+
+    def get_active_job_name(self):
+        return self.job_name
+
+    def get_percent_done(self):
+        if self.count is not None:
+            percent = self.done * 100 / self.count
+            return min(percent, 100)
+
+    def get_name(self):
+        return self.name
+
+
+class NullTaskHandle(object):
+
+    def __init__(self):
+        pass
+
+    def is_stopped(self):
+        return False
+
+    def stop(self):
+        pass
+
+    def create_job_set(self, *args, **kwds):
+        return NullJobSet()
+
+    def get_job_sets(self):
+        return []
+
+    def add_observer(self, observer):
+        pass
+
+
+class NullJobSet(object):
+
+    def started_job(self, name):
+        pass
+
+    def finished_job(self):
+        pass
+
+    def check_status(self):
+        pass
+
+    def get_active_job_name(self):
+        pass
+
+    def get_percent_done(self):
+        pass
+
+    def get_name(self):
+        pass

File rope/ide/codeassist.py

View file
  • Ignore whitespace
 import re
 
 import rope.base.codeanalyze
-from rope.base import pyobjects, pynames
+from rope.base import pyobjects, pynames, taskhandle
 from rope.base.codeanalyze import (StatementRangeFinder, ArrayLinesAdapter,
                                    WordRangeFinder, ScopeNameFinder,
                                    SourceLinesAdapter, BadIdentifierError)
 from rope.base.exceptions import RopeError
 from rope.ide import pydoc
-from rope.refactor import occurrences, functionutils, taskhandle
+from rope.refactor import occurrences, functionutils
 
 
 class RopeSyntaxError(RopeError):

File rope/refactor/__init__.py

View file
  • Ignore whitespace
 4. perform the refactoring.
 
 In ``0.5m5`` release the `get_changes()` method of some time
-consuming refactorings take an optional `rope.refactor.taskhandle.
+consuming refactorings take an optional `rope.base.taskhandle.
 TaskHandle` parameter.  You can use this object for stopping or
 monitoring the progress of refactorings.
 

File rope/refactor/change_signature.py

View file
  • Ignore whitespace
 import copy
 
 import rope.base.exceptions
-from rope.base import pyobjects, codeanalyze
+from rope.base import pyobjects, codeanalyze, taskhandle
 from rope.base.change import ChangeContents, ChangeSet
-from rope.refactor import (occurrences, sourceutils, functionutils,
-                           rename, taskhandle)
+from rope.refactor import occurrences, sourceutils, functionutils, rename
 
 
 class ChangeSignature(object):

File rope/refactor/encapsulate_field.py

View file
  • Ignore whitespace
 import rope.base.codeanalyze
-from rope.base import pynames
+from rope.base import pynames, taskhandle
 from rope.base.change import ChangeSet, ChangeContents
-from rope.refactor import sourceutils, taskhandle
+from rope.refactor import sourceutils
 
 
 class EncapsulateField(object):

File rope/refactor/inline.py

View file
  • Ignore whitespace
 
 import rope.base.exceptions
 import rope.refactor.functionutils
-from rope.base import pynames, pyobjects, codeanalyze
+from rope.base import pynames, pyobjects, codeanalyze, taskhandle
 from rope.base.change import ChangeSet, ChangeContents
-from rope.refactor import occurrences, rename, sourceutils, taskhandle
+from rope.refactor import occurrences, rename, sourceutils
 
 
 class Inline(object):

File rope/refactor/introduce_factory.py

View file
  • Ignore whitespace
 import rope.base.exceptions
 import rope.base.pyobjects
 import rope.refactor.importutils
+from rope.base import taskhandle
 from rope.base.change import (ChangeSet, ChangeContents)
-from rope.refactor import rename, occurrences, sourceutils, taskhandle
+from rope.refactor import rename, occurrences, sourceutils
 
 
 class IntroduceFactoryRefactoring(object):

File rope/refactor/move.py

View file
  • Ignore whitespace
 based on inputs.
 
 """
-from rope.base import pyobjects, codeanalyze, exceptions, pynames
+from rope.base import pyobjects, codeanalyze, exceptions, pynames, taskhandle
 from rope.base.change import ChangeSet, ChangeContents, MoveResource
 from rope.refactor import (importutils, rename, occurrences, sourceutils,
-                           functionutils, inline, taskhandle)
+                           functionutils, inline)
 
 
 def create_move(project, resource, offset=None):

File rope/refactor/rename.py

View file
  • Ignore whitespace
 import rope.refactor
-from rope.base import exceptions, codeanalyze, pyobjects, pynames
+from rope.base import exceptions, codeanalyze, pyobjects, pynames, taskhandle
 from rope.base.change import ChangeSet, ChangeContents, MoveResource
-from rope.refactor import occurrences, sourceutils, taskhandle
+from rope.refactor import occurrences, sourceutils
 
 
 class Rename(object):

File rope/refactor/taskhandle.py

  • Ignore whitespace
-import rope.base
-import rope.refactor
-
-
-class TaskHandle(object):
-
-    def __init__(self, name='Task'):
-        self.name = name
-        self.stopped = False
-        self.job_sets = []
-        self.observers = []
-
-    def is_stopped(self):
-        return self.stopped
-
-    def stop(self):
-        self.stopped = True
-        self._inform_observers()
-
-    def create_job_set(self, name='JobSet', count=None):
-        result = JobSet(self, name=name, count=count)
-        self.job_sets.append(result)
-        self._inform_observers()
-        return result
-
-    def get_job_sets(self):
-        return self.job_sets
-
-    def add_observer(self, observer):
-        """Register an observer for this task handle
-
-        The observer is notified whenever the task is stopped or
-        a job gets finished.
-        """
-        self.observers.append(observer)
-
-    def _inform_observers(self):
-        for observer in list(self.observers):
-            observer()
-
-
-class JobSet(object):
-
-    def __init__(self, handle, name, count):
-        self.handle = handle
-        self.name = name
-        self.count = count
-        self.done = 0
-        self.job_name = None
-
-    def started_job(self, name):
-        self.check_status()
-        self.job_name = name
-        self.handle._inform_observers()
-
-    def finished_job(self):
-        self.handle._inform_observers()
-        self.job_name = None
-        self.done += 1
-
-    def check_status(self):
-        if self.handle.is_stopped():
-            raise rope.base.exceptions.InterruptedTaskError()
-
-    def get_active_job_name(self):
-        return self.job_name
-
-    def get_percent_done(self):
-        if self.count is not None:
-            percent = self.done * 100 / self.count
-            return min(percent, 100)
-
-    def get_name(self):
-        return self.name
-
-
-class NullTaskHandle(object):
-
-    def __init__(self):
-        pass
-
-    def is_stopped(self):
-        return False
-
-    def stop(self):
-        pass
-
-    def create_job_set(self, *args, **kwds):
-        return NullJobSet()
-
-    def get_job_sets(self):
-        return []
-
-    def add_observer(self, observer):
-        pass
-
-
-class NullJobSet(object):
-
-    def started_job(self, name):
-        pass
-
-    def finished_job(self):
-        pass
-
-    def check_status(self):
-        pass
-
-    def get_active_job_name(self):
-        pass
-
-    def get_percent_done(self):
-        pass
-
-    def get_name(self):
-        pass

File rope/ui/actionhelpers.py

View file
  • Ignore whitespace
 import rope.base.project
 import rope.refactor.change_signature
 import rope.ui.uihelpers
-import rope.refactor.taskhandle
+import rope.base.taskhandle
 
 
 class StoppableTaskRunner(object):
         self.title = title
 
     def __call__(self):
-        handle = rope.refactor.taskhandle.TaskHandle(self.title)
+        handle = rope.base.taskhandle.TaskHandle(self.title)
         toplevel = Tkinter.Toplevel()
         toplevel.title('Performing Task ' + self.title)
         frame = Tkinter.Frame(toplevel)
         def update_progress():
             job_sets = handle.get_job_sets()
             if job_sets:
-                job_set = job_sets[0]
+                job_set = job_sets[-1]
                 text = ''
                 if job_set.get_name() is not None:
                     text += job_set.get_name()
                 'Task <%s> was interrupted' % self.title)
         return calculate.result
 
+def simple_stoppable(description):
+    def decorator(function):
+        def caller():
+            def do_call(handle):
+                return function(handle)
+            return StoppableTaskRunner(do_call, description)()
+        return caller
+    return decorator
+
 
 def check_project(core):
     if core.project is rope.base.project.get_no_project():

File rope/ui/dot_rope.py

View file
  • Ignore whitespace
     core.rebind_action('remember_location', 'M-M b')
     core.rebind_action('memorize_string', 'M-M s')
     core.rebind_action('remember_string', 'M-M i')
+    core.rebind_action('spellcheck_word', None)
+    core.rebind_action('spellcheck_buffer', None)
+    core.rebind_action('spellcheck_region', None)
 
     core.rebind_action('code_assist', 'C-space')
     core.rebind_action('goto_definition', 'F3')

File rope/ui/fileactions.py

View file
  • Ignore whitespace
 import rope.ui.actionhelpers
 import rope.ui.core
 from rope.ui import uihelpers
-from rope.ui.actionhelpers import ConfirmEditorsAreSaved
+from rope.ui.actionhelpers import ConfirmEditorsAreSaved, simple_stoppable
+                                   
 from rope.ui.extension import SimpleAction
 from rope.ui.menubar import MenuAddress
 from rope.ui.uihelpers import (TreeViewHandle, TreeView, find_item_dialog,
         change = enhanced_list.get_selected()
         if change is None:
             return
-        def undo():
-            context.project.history.undo(change)
+        @simple_stoppable("Undo Changes")
+        def undo(handle):
+            context.project.history.undo(change, task_handle=handle)
         _confirm_action(
             'Undoing Project Change',
             'Undoing <%s>\n\n' % str(change) +
         history = context.project.history
         if not history.undo_list:
             return
-        def undo():
-            history.undo()
+        @simple_stoppable('Undo Change')
+        def undo(task_handle):
+            history.undo(task_handle=task_handle)
         _confirm_action(
             'Undoing Project Change',
             'Undoing <%s>\n\n' % str(history.undo_list[-1]) +
         history = context.project.history
         if not history.redo_list:
             return
-        def redo():
-            history.redo()
+        @simple_stoppable('Redo Change')
+        def redo(handle):
+            history.redo(task_handle=handle)
         _confirm_action(
             'Redoing Project Change',
             'Redoing <%s>\n\n' % str(history.redo_list[-1]) +

File rope/ui/fileeditor.py

View file
  • Ignore whitespace
         #    self.editor.getWidget()['state'] = Tkinter.DISABLED
 
     def _register_observers(self):
-        callback = self._file_was_modified
+        modified = self._file_was_modified
+        moved = self._file_was_removed
         self.observer = FilteredResourceObserver(
-            ResourceObserver(changed=callback, moved=callback, removed=callback),
+            ResourceObserver(changed=modified, moved=moved, removed=moved),
             [self.file])
         if self.project is not None:
             self.project.add_observer(self.observer)
 
     def close(self):
         self._remove_observers()
-

File rope/ui/refactor.py

View file
  • Ignore whitespace
         frame.grid()
 
     def commit(self):
-        self.project.do(self.changes)
+        def commit(handle):
+            self.project.do(self.changes, task_handle=handle)
+        StoppableTaskRunner(commit, "Committing Changes")()
 
 
 class RefactoringDialog(object):

File ropetest/refactor/__init__.py

View file
  • Ignore whitespace
 from rope.refactor.localtofield import LocalToField
 from rope.refactor.method_object import MethodObject
 from ropetest import testutils
-import rope.refactor.taskhandle
+import rope.base.taskhandle
 
 
 class MethodObjectTest(unittest.TestCase):
 class TaskHandleTest(unittest.TestCase):
 
     def test_trivial_case(self):
-        handle = rope.refactor.taskhandle.TaskHandle()
+        handle = rope.base.taskhandle.TaskHandle()
         self.assertFalse(handle.is_stopped())
 
     def test_stopping(self):
-        handle = rope.refactor.taskhandle.TaskHandle()
+        handle = rope.base.taskhandle.TaskHandle()
         handle.stop()
         self.assertTrue(handle.is_stopped())
 
     def test_job_sets(self):
-        handle = rope.refactor.taskhandle.TaskHandle()
+        handle = rope.base.taskhandle.TaskHandle()
         jobs = handle.create_job_set()
         self.assertEquals([jobs], handle.get_job_sets())
 
     def test_starting_and_finishing_jobs(self):
-        handle = rope.refactor.taskhandle.TaskHandle()
+        handle = rope.base.taskhandle.TaskHandle()
         jobs = handle.create_job_set(name='test job set', count=1)
         jobs.started_job('job1')
         jobs.finished_job()
 
     @testutils.assert_raises(InterruptedTaskError)
     def test_test_checking_status(self):
-        handle = rope.refactor.taskhandle.TaskHandle()
+        handle = rope.base.taskhandle.TaskHandle()
         jobs = handle.create_job_set()
         handle.stop()
         jobs.check_status()
 
     @testutils.assert_raises(InterruptedTaskError)
     def test_test_checking_status_when_starting(self):
-        handle = rope.refactor.taskhandle.TaskHandle()
+        handle = rope.base.taskhandle.TaskHandle()
         jobs = handle.create_job_set()
         handle.stop()
         jobs.started_job('job1')
 
     def test_calling_the_observer_after_stopping(self):
-        handle = rope.refactor.taskhandle.TaskHandle()
+        handle = rope.base.taskhandle.TaskHandle()
         observer = _MockTaskObserver()
         handle.add_observer(observer)
         handle.stop()
         self.assertEquals(1, observer.called)
 
     def test_calling_the_observer_after_creating_job_sets(self):
-        handle = rope.refactor.taskhandle.TaskHandle()
+        handle = rope.base.taskhandle.TaskHandle()
         observer = _MockTaskObserver()
         handle.add_observer(observer)
         jobs = handle.create_job_set()
         self.assertEquals(1, observer.called)
 
     def test_calling_the_observer_when_starting_and_finishing_jobs(self):
-        handle = rope.refactor.taskhandle.TaskHandle()
+        handle = rope.base.taskhandle.TaskHandle()
         observer = _MockTaskObserver()
         handle.add_observer(observer)
         jobs = handle.create_job_set(name='test job set', count=1)
         self.assertEquals(3, observer.called)
 
     def test_job_set_get_percent_done(self):
-        handle = rope.refactor.taskhandle.TaskHandle()
+        handle = rope.base.taskhandle.TaskHandle()
         jobs = handle.create_job_set(name='test job set', count=2)
         self.assertEquals(0, jobs.get_percent_done())
         jobs.started_job('job1')
         self.assertEquals(100, jobs.get_percent_done())
 
     def test_getting_job_name(self):
-        handle = rope.refactor.taskhandle.TaskHandle()
+        handle = rope.base.taskhandle.TaskHandle()
         jobs = handle.create_job_set(name='test job set', count=1)
         self.assertEquals('test job set', jobs.get_name())
         self.assertEquals(None, jobs.get_active_job_name())