diff options
author | Lars Wirzenius <liw@liw.fi> | 2010-07-07 09:20:10 +1200 |
---|---|---|
committer | Lars Wirzenius <liw@liw.fi> | 2010-07-07 09:20:10 +1200 |
commit | dc830c6e3bdaa9f2caf766a541a33767c14eacc3 (patch) | |
tree | 97e1be607f431c0ab791c022b98d606720bceee9 | |
parent | 3a1ecab53b935e6c794d1080939884286a119320 (diff) | |
download | python-ttystatus-dc830c6e3bdaa9f2caf766a541a33767c14eacc3.tar.gz |
Change update methods to only cache information and compute minimal things.
Add a format() method that actually do the heavy duty lifting,
such as string formatting, which is only needed during actual
output.
-rw-r--r-- | ttystatus/bytesize.py | 12 | ||||
-rw-r--r-- | ttystatus/counter.py | 6 | ||||
-rw-r--r-- | ttystatus/elapsed.py | 11 | ||||
-rw-r--r-- | ttystatus/index.py | 22 | ||||
-rw-r--r-- | ttystatus/index_tests.py | 2 | ||||
-rw-r--r-- | ttystatus/literal.py | 2 | ||||
-rw-r--r-- | ttystatus/pathname.py | 24 | ||||
-rw-r--r-- | ttystatus/percent.py | 19 | ||||
-rw-r--r-- | ttystatus/progressbar.py | 27 | ||||
-rw-r--r-- | ttystatus/remtime.py | 31 | ||||
-rw-r--r-- | ttystatus/remtime_tests.py | 1 | ||||
-rw-r--r-- | ttystatus/string.py | 3 | ||||
-rw-r--r-- | ttystatus/widget.py | 29 |
13 files changed, 118 insertions, 71 deletions
diff --git a/ttystatus/bytesize.py b/ttystatus/bytesize.py index 56c6d4c..f47d453 100644 --- a/ttystatus/bytesize.py +++ b/ttystatus/bytesize.py @@ -23,10 +23,10 @@ class ByteSize(ttystatus.Widget): def __init__(self, name): self.name = name - self.value = self.format(0) self.interesting_keys = [name] + self._bytes = 0 - def format(self, bytes): + def format(self): units = ( (1024**4, 2, 'TiB'), (1024**3, 2, 'GiB'), @@ -35,11 +35,11 @@ class ByteSize(ttystatus.Widget): ) for factor, decimals, unit in units: - if bytes >= factor: + if self._bytes >= factor: return '%.*f %s' % (decimals, - float(bytes) / float(factor), + float(self._bytes) / float(factor), unit) - return '%d B' % bytes + return '%d B' % self._bytes def update(self, master, width): - self.value = self.format(master[self.name]) + self._bytes = master[self.name] diff --git a/ttystatus/counter.py b/ttystatus/counter.py index 770b5e7..5d3e11f 100644 --- a/ttystatus/counter.py +++ b/ttystatus/counter.py @@ -25,12 +25,12 @@ class Counter(ttystatus.Widget): self.name = name self.prev = None self.count = 0 - self.value = '0' self.interesting_keys = [name] + + def format(self): + return str(self.count) def update(self, master, width): if master[self.name] != self.prev: self.prev = master[self.name] self.count += 1 - self.value = str(self.count) - diff --git a/ttystatus/elapsed.py b/ttystatus/elapsed.py index c9bfc42..e9a9a85 100644 --- a/ttystatus/elapsed.py +++ b/ttystatus/elapsed.py @@ -25,14 +25,15 @@ class ElapsedTime(ttystatus.Widget): def __init__(self): self.started = None - self.value = self.format(0) - self.interesting_keys = [] + self.interesting_keys = [] # FIXME: Need to declare interest in all keys? + self.secs = 0 def get_time(self): # pragma: no cover '''Wrapper around time.time() for unit tests to override.''' return time.time() - def format(self, secs): + def format(self): + secs = self.secs hours = secs / 3600 secs %= 3600 mins = secs / 60 @@ -42,6 +43,4 @@ class ElapsedTime(ttystatus.Widget): def update(self, master, width): if self.started is None: self.started = self.get_time() - secs = self.get_time() - self.started - self.value = self.format(secs) - + self.secs = self.get_time() - self.started diff --git a/ttystatus/index.py b/ttystatus/index.py index a9e1541..941165a 100644 --- a/ttystatus/index.py +++ b/ttystatus/index.py @@ -24,18 +24,18 @@ class Index(ttystatus.Widget): def __init__(self, name, listname): self.name = name self.listname = listname - self.value = self.format(0, 0) self.interesting_keys = [name, listname] + self.value = None + self.listvalue = [] - def format(self, index, listlen): - return '%d/%d' % (index, listlen) - - def update(self, master, width): - value = master[self.name] - listvalue = master[self.listname] + def format(self): try: - index = listvalue.index(value) + 1 + index = self.listvalue.index(self.value) + 1 except ValueError: - pass - else: - self.value = self.format(index, len(listvalue)) + index = 0 + return '%d/%d' % (index, len(self.listvalue)) + + def update(self, master, width): + self.value = master[self.name] + self.listvalue = master[self.listname] + diff --git a/ttystatus/index_tests.py b/ttystatus/index_tests.py index 9d825b3..3c91903 100644 --- a/ttystatus/index_tests.py +++ b/ttystatus/index_tests.py @@ -33,5 +33,5 @@ class IndexTests(unittest.TestCase): def test_handles_value_not_in_list(self): self.w.update({ 'foo': 'xxx', 'foos': ['a', 'x', 'b'] }, 999) - self.assertEqual(str(self.w), '0/0') + self.assertEqual(str(self.w), '0/3') diff --git a/ttystatus/literal.py b/ttystatus/literal.py index a1ffa18..5c41b69 100644 --- a/ttystatus/literal.py +++ b/ttystatus/literal.py @@ -25,3 +25,5 @@ class Literal(ttystatus.Widget): self.value = string self.interesting_keys = [] + def format(self): + return self.value diff --git a/ttystatus/pathname.py b/ttystatus/pathname.py index 0cc8106..0f5fb43 100644 --- a/ttystatus/pathname.py +++ b/ttystatus/pathname.py @@ -28,14 +28,20 @@ class Pathname(ttystatus.Widget): def __init__(self, key): self._key = key self.interesting_keys = [key] - self.value = '' - - def update(self, master, width): - v = master.get(self._key, '') - if len(v) > width: + self.pathname = '' + self.width = 0 + + def format(self): + v = self.pathname + if len(v) > self.width: ellipsis = '...' - if len(ellipsis) < width: - v = ellipsis + v[-(width - len(ellipsis)):] + if len(ellipsis) < self.width: + v = ellipsis + v[-(self.width - len(ellipsis)):] else: - v = v[-width:] - self.value = v + v = v[-self.width:] + return v + + def update(self, master, width): + self.pathname = master.get(self._key, '') + self.width = width + diff --git a/ttystatus/percent.py b/ttystatus/percent.py index fec0dfc..8914f41 100644 --- a/ttystatus/percent.py +++ b/ttystatus/percent.py @@ -25,18 +25,19 @@ class PercentDone(ttystatus.Widget): self.done_name = done_name self.total_name = total_name self.decimals = decimals - self.value = self.format(0, 1) + self.done = 0 + self.total = 1 self.interesting_keys = [done_name, total_name] - def format(self, done, total): + def format(self): try: - done = float(done) - total = float(total) + done = float(self.done) + total = float(self.total) except ValueError: - return self.value - else: - return '%.*f %%' % (self.decimals, 100.0 * done / total) + done = 0 + total = 1 + return '%.*f %%' % (self.decimals, 100.0 * done / total) def update(self, master, width): - self.value = self.format(master[self.done_name], - master[self.total_name]) + self.done = master[self.done_name] + self.total = master[self.total_name] diff --git a/ttystatus/progressbar.py b/ttystatus/progressbar.py index 23574f7..e8549f2 100644 --- a/ttystatus/progressbar.py +++ b/ttystatus/progressbar.py @@ -25,16 +25,27 @@ class ProgressBar(ttystatus.Widget): self.done_name = done_name self.total_name = total_name self.interesting_keys = [done_name, total_name] - self.value = '' - - def update(self, master, width): - done = float(master.get(self.done_name, 0)) - total = float(master.get(self.total_name, 1) or 0) + self.done = 0 + self.total = 1 + self.width = 0 + + def format(self): + try: + done = float(self.done) + total = float(self.total) + except ValueError: + done = 0 + total = 1 if total == 0: fraction = 0 else: fraction = done / total - n_stars = int(round(fraction * width)) - n_dashes = int(width - n_stars) - self.value = ('#' * n_stars) + ('-' * n_dashes) + n_stars = int(round(fraction * self.width)) + n_dashes = int(self.width - n_stars) + return ('#' * n_stars) + ('-' * n_dashes) + + def update(self, master, width): + self.done = master[self.done_name] + self.total = master[self.total_name] + self.width = width diff --git a/ttystatus/remtime.py b/ttystatus/remtime.py index e2ee684..fd0d07c 100644 --- a/ttystatus/remtime.py +++ b/ttystatus/remtime.py @@ -28,8 +28,9 @@ class RemainingTime(ttystatus.Widget): self.total_name = total_name self.started = None self.default = '--h--m--s' - self.value = self.default self.interesting_keys = [done_name, total_name] + self.done = 0 + self.total = 1 def get_time(self): # pragma: no cover '''Return current time. @@ -41,24 +42,22 @@ class RemainingTime(ttystatus.Widget): return time.time() - def format(self, secs): - hours = secs / (60 * 60) - secs %= (60 * 60) - mins = secs / 60 - secs %= 60 - return '%02dh%02dm%02ds' % (hours, mins, secs) - - def update(self, master, width): + def format(self): if self.started is None: self.started = self.get_time() duration = self.get_time() - self.started if duration >= 1.0: - done = float(master.get(self.done_name, 0) or 0) - total = float(master.get(self.total_name, 0) or 0) - speed = done / duration - remaining = total - done + speed = self.done / duration + remaining = self.total - self.done if speed > 0: secs = remaining / speed - self.value = self.format(secs) - else: - self.value = self.default + hours = secs / (60 * 60) + secs %= (60 * 60) + mins = secs / 60 + secs %= 60 + return '%02dh%02dm%02ds' % (hours, mins, secs) + return self.default + + def update(self, master, width): + self.done = master[self.done_name] + self.total = master[self.total_name] diff --git a/ttystatus/remtime_tests.py b/ttystatus/remtime_tests.py index 6c6f452..2c67345 100644 --- a/ttystatus/remtime_tests.py +++ b/ttystatus/remtime_tests.py @@ -29,6 +29,7 @@ class RemainingTimeTests(unittest.TestCase): self.assertEqual(str(self.w), '--h--m--s') def test_estimates_and_formats_correctly(self): + self.assertEqual(str(self.w), '--h--m--s') self.w.update({ 'done': 0, 'total': 100 }, 999) self.w.get_time = lambda: 5.0 self.w.update({ 'done': 5, 'total': 100 }, 999) diff --git a/ttystatus/string.py b/ttystatus/string.py index f80c0ec..1dc3023 100644 --- a/ttystatus/string.py +++ b/ttystatus/string.py @@ -25,6 +25,9 @@ class String(ttystatus.Widget): self._key = key self.interesting_keys = [key] self.value = '' + + def format(self): + return self.value def update(self, master, width): self.value = master[self._key] diff --git a/ttystatus/widget.py b/ttystatus/widget.py index c3cb214..0f03365 100644 --- a/ttystatus/widget.py +++ b/ttystatus/widget.py @@ -23,14 +23,39 @@ class Widget(object): master TerminalStatus widget. They return the formatted string via __str__. + A widget's value may be derived from values stored in the TerminalStatus + widget (called master). Each such value has a key. Computing a widget's + value is a two-step process: when the values associated with keys + are updated, the widget's update() method is called to notify it of + this. update() may compute intermediate values, such as maintain a + counter of the number of changes. It should avoid costly operations + that are only needed when the widget's formatted value is needed. + Those should go into the format() method instead. Thus, update() would + update a counter, format() would create a string representing the + counter. + + This is necessary because actual on-screen updates only happen + every so often, not every time a value in the master changes, and + often the string formatting part is expensive. + Widgets must have an attribute 'interesting_keys', listing the - keys it is interested in, and 'value', for the formatted value. + keys it is interested in. ''' def __str__(self): '''Return current value to be displayed for this widget.''' - return self.value + return self.format() + + def format(self): + '''Format the current value. + + This will be called only when the value actually needs to be + formatted. + + ''' + + return '' def update(self, master, width): '''Update displayed value for widget, from values in master. |