summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLars Wirzenius <liw@liw.fi>2010-07-07 09:20:10 +1200
committerLars Wirzenius <liw@liw.fi>2010-07-07 09:20:10 +1200
commitdc830c6e3bdaa9f2caf766a541a33767c14eacc3 (patch)
tree97e1be607f431c0ab791c022b98d606720bceee9
parent3a1ecab53b935e6c794d1080939884286a119320 (diff)
downloadpython-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.py12
-rw-r--r--ttystatus/counter.py6
-rw-r--r--ttystatus/elapsed.py11
-rw-r--r--ttystatus/index.py22
-rw-r--r--ttystatus/index_tests.py2
-rw-r--r--ttystatus/literal.py2
-rw-r--r--ttystatus/pathname.py24
-rw-r--r--ttystatus/percent.py19
-rw-r--r--ttystatus/progressbar.py27
-rw-r--r--ttystatus/remtime.py31
-rw-r--r--ttystatus/remtime_tests.py1
-rw-r--r--ttystatus/string.py3
-rw-r--r--ttystatus/widget.py29
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.