Rev 3019: Add bzrlib.progress.KnownLengthTask. in http://people.ubuntu.com/~robertc/baz2.0/nested-pb

Robert Collins robertc at robertcollins.net
Tue Nov 20 01:03:02 GMT 2007


At http://people.ubuntu.com/~robertc/baz2.0/nested-pb

------------------------------------------------------------
revno: 3019
revision-id:robertc at robertcollins.net-20071120010256-vj0q61gjvejvnhfa
parent: robertc at robertcollins.net-20071120004328-qn0tgv4op1d0qzck
committer: Robert Collins <robertc at robertcollins.net>
branch nick: pb.simplify
timestamp: Tue 2007-11-20 12:02:56 +1100
message:
  Add bzrlib.progress.KnownLengthTask.
modified:
  bzrlib/progress.py             progress.py-20050610070202-df9faaab791964c0
  bzrlib/tests/test_progress.py  test_progress.py-20060308160359-978c397bc79b7fda
=== modified file 'bzrlib/progress.py'
--- a/bzrlib/progress.py	2007-11-20 00:43:28 +0000
+++ b/bzrlib/progress.py	2007-11-20 01:02:56 +0000
@@ -30,7 +30,9 @@
 Interesting classes for plugins and gui's that need to interoperate with this
 module:
 
- * CountedTask: The most basic item of work.
+ * Tassk: The most basic item of work.
+  * CountedTask: Work with an unknown total.
+  * KnownLengthTask: Work when we know the total amount to do.
  * TaskDisplay: Display of a Task.
   * SilentTaskDisplay: For headless operations.
   * DotsTaskDisplay: For non-TTY file stream display.
@@ -129,6 +131,27 @@
         return self.current
 
 
+class KnownLengthTask(CountedTask):
+    """A task which can be worked on with a known total amount to perform.
+    
+    An example of such is a fetch operation where we are copying a calculated
+    number of revisions. While each revision may be of unknown size, we can
+    provide a reasonable estimate of progress by counting from 0 to the total
+    revision count that we are copying.
+    """
+
+    def __init__(self, message, total):
+        CountedTask.__init__(self, message)
+        self.total = total
+
+    def percent_complete(self):
+        """Return the percentage of the task that has been completed."""
+        result = self.current/float(self.total)
+        if result > 1.0:
+            result = 1.0
+        return result
+
+
 class ProgressBarStack(object):
     """A stack of progress bars."""
 

=== modified file 'bzrlib/tests/test_progress.py'
--- a/bzrlib/tests/test_progress.py	2007-11-20 00:43:28 +0000
+++ b/bzrlib/tests/test_progress.py	2007-11-20 01:02:56 +0000
@@ -24,6 +24,7 @@
         DotsProgressBar,
         DotsTaskDisplay,
         DummyProgress,
+        KnownLengthTask,
         ProgressBarStack,
         SilentTaskDisplay,
         TTYProgressBar,
@@ -341,6 +342,59 @@
         self.assertEqual(1.0, task.current)
 
 
+class TestKnownLengthTask(TestCase):
+
+    def assertEqualFloat(self, left, right):
+        """Assert that two floats are within 0.000001 of each other."""
+        difference = left - right
+        if abs(difference) < 0.000001:
+            return
+        self.fail("%s != %s" % (left, right))
+
+    def test_construct_with_message(self):
+        message = 'transferring'
+        task = KnownLengthTask(message, 1)
+        self.assertEqual(message, task.get_message())
+        self.assertEqual(1, task.tick_size)
+        self.assertEqual(0, task.current)
+        self.assertEqual(1, task.total)
+
+    def test_tick_default(self):
+        task = KnownLengthTask('', 1)
+        self.assertEqual(0, task.current)
+        self.assertEqual(1, task.tick())
+        self.assertEqual(1, task.current)
+
+    def test_tick_float(self):
+        task = KnownLengthTask('', 1)
+        self.assertEqual(0, task.current)
+        task.tick_size = 0.5
+        self.assertEqual(0.5, task.tick())
+        self.assertEqual(0.5, task.current)
+        self.assertEqual(1.0, task.tick())
+        self.assertEqual(1.0, task.current)
+
+    def test_percent_complete(self):
+        task = KnownLengthTask('', 1)
+        # Choose a tick size which will not sum to 100% to test rounding at the
+        # top.
+        task.tick_size = 0.23
+        self.assertEqualFloat(0.0, task.percent_complete())
+        task.tick()
+        self.assertEqualFloat(0.23, task.percent_complete())
+        task.tick()
+        self.assertEqualFloat(0.46, task.percent_complete())
+        task.tick()
+        self.assertEqualFloat(0.69, task.percent_complete())
+        task.tick()
+        self.assertEqualFloat(0.92, task.percent_complete())
+        # At > 100% it is capped. Alternatively we could error to enforce good
+        # api usage (should be rounding down not up to give monotonic
+        # behaviour, but this seems nice to clients of the api for now.
+        task.tick()
+        self.assertEqual(1.0, task.percent_complete())
+
+
 class TestSilentTaskDisplay(TestCase):
 
     def test_construct(self):



More information about the bazaar-commits mailing list