From c54f82a88e9592afd6bd0232f50a121acb1238e9 Mon Sep 17 00:00:00 2001 From: Lars Wirzenius Date: Sun, 15 Apr 2012 15:29:01 +0100 Subject: Improve widget split between updating and rendering a) don't use format, use __str__, since nothing calls format directly b) don't declare interest in keys; just don't compute rendered value in update method, only when actually rendering (in __str__) c) don't pass in the available width to update, since that is only relevant during rendering (this will need to be fixed later, currently we don't get width at all) --- ttystatus/bytesize.py | 10 +++++----- ttystatus/bytesize_tests.py | 14 ++++++------- ttystatus/bytespeed.py | 5 ++--- ttystatus/bytespeed_tests.py | 14 ++++++------- ttystatus/counter.py | 5 ++--- ttystatus/counter_tests.py | 10 +++++----- ttystatus/elapsed.py | 5 ++--- ttystatus/elapsed_tests.py | 6 +++--- ttystatus/index.py | 5 ++--- ttystatus/index_tests.py | 4 ++-- ttystatus/integer.py | 5 ++--- ttystatus/integer_tests.py | 4 ++-- ttystatus/literal.py | 3 +-- ttystatus/pathname.py | 16 +++------------ ttystatus/pathname_tests.py | 21 ++------------------ ttystatus/percent.py | 5 ++--- ttystatus/percent_tests.py | 6 +++--- ttystatus/progressbar.py | 11 ++++------- ttystatus/progressbar_tests.py | 20 +++++++++---------- ttystatus/remtime.py | 5 ++--- ttystatus/remtime_tests.py | 16 +++++++-------- ttystatus/status.py | 12 +---------- ttystatus/status_tests.py | 16 --------------- ttystatus/string.py | 5 ++--- ttystatus/string_tests.py | 4 ++-- ttystatus/widget.py | 45 +++++++++++------------------------------- 26 files changed, 93 insertions(+), 179 deletions(-) diff --git a/ttystatus/bytesize.py b/ttystatus/bytesize.py index f47d453..4c338aa 100644 --- a/ttystatus/bytesize.py +++ b/ttystatus/bytesize.py @@ -23,10 +23,12 @@ class ByteSize(ttystatus.Widget): def __init__(self, name): self.name = name - self.interesting_keys = [name] self._bytes = 0 + + def update(self, ts): + self._bytes = ts[self.name] - def format(self): + def __str__(self): units = ( (1024**4, 2, 'TiB'), (1024**3, 2, 'GiB'), @@ -40,6 +42,4 @@ class ByteSize(ttystatus.Widget): float(self._bytes) / float(factor), unit) return '%d B' % self._bytes - - def update(self, master, width): - self._bytes = master[self.name] + diff --git a/ttystatus/bytesize_tests.py b/ttystatus/bytesize_tests.py index 11958f4..d1dd94d 100644 --- a/ttystatus/bytesize_tests.py +++ b/ttystatus/bytesize_tests.py @@ -28,30 +28,30 @@ class ByteSizeTests(unittest.TestCase): self.assertEqual(str(self.w), '0 B') def test_formats_zero_bytes_correctly(self): - self.w.update({ 'foo': 0 }, 999) + self.w.update({ 'foo': 0 }) self.assertEqual(str(self.w), '0 B') def test_formats_one_bytes_correctly(self): - self.w.update({ 'foo': 1 }, 999) + self.w.update({ 'foo': 1 }) self.assertEqual(str(self.w), '1 B') def test_formats_1023_bytes_correctly(self): - self.w.update({ 'foo': 1023 }, 999) + self.w.update({ 'foo': 1023 }) self.assertEqual(str(self.w), '1023 B') def test_formats_1024_bytes_correctly(self): - self.w.update({ 'foo': 1024 }, 999) + self.w.update({ 'foo': 1024 }) self.assertEqual(str(self.w), '1.0 KiB') def test_formats_1_MiB_bytes_correctly(self): - self.w.update({ 'foo': 1024**2 }, 999) + self.w.update({ 'foo': 1024**2 }) self.assertEqual(str(self.w), '1.00 MiB') def test_formats_1_GiB_bytes_correctly(self): - self.w.update({ 'foo': 1024**3 }, 999) + self.w.update({ 'foo': 1024**3 }) self.assertEqual(str(self.w), '1.00 GiB') def test_formats_1_TiB_bytes_correctly(self): - self.w.update({ 'foo': 1024**4 }, 999) + self.w.update({ 'foo': 1024**4 }) self.assertEqual(str(self.w), '1.00 TiB') diff --git a/ttystatus/bytespeed.py b/ttystatus/bytespeed.py index 7f54b86..cc62300 100644 --- a/ttystatus/bytespeed.py +++ b/ttystatus/bytespeed.py @@ -25,7 +25,6 @@ class ByteSpeed(ttystatus.Widget): def __init__(self, name): self.name = name - self.interesting_keys = [name] self._bytes = 0 self._started = None @@ -34,7 +33,7 @@ class ByteSpeed(ttystatus.Widget): return time.time() - def format(self): + def __str__(self): units = ( (1024**4, 2, 'TiB/s'), (1024**3, 2, 'GiB/s'), @@ -55,7 +54,7 @@ class ByteSpeed(ttystatus.Widget): unit) return '%.0f B/s' % speed - def update(self, master, width): + def update(self, master): if self._started is None: self._started = self.now() self._bytes = master[self.name] diff --git a/ttystatus/bytespeed_tests.py b/ttystatus/bytespeed_tests.py index 4c481fe..369c2f6 100644 --- a/ttystatus/bytespeed_tests.py +++ b/ttystatus/bytespeed_tests.py @@ -28,27 +28,27 @@ class ByteSpeedTests(unittest.TestCase): self.assertEqual(str(self.w), '0 B/s') def test_formats_zero_bytes_correctly(self): - self.w.update({ 'foo': 0 }, 999) + self.w.update({ 'foo': 0 }) self.assertEqual(str(self.w), '0 B/s') def test_formats_one_byte_per_second_correctly(self): self.w.now = lambda: 1 - self.w.update({ 'foo': 0 }, 999) + self.w.update({ 'foo': 0 }) self.w.now = lambda: 2 - self.w.update({ 'foo': 1 }, 999) + self.w.update({ 'foo': 1 }) self.assertEqual(str(self.w), '1 B/s') def test_formats_ten_bytes_per_second_correctly(self): self.w.now = lambda: 1 - self.w.update({ 'foo': 0 }, 999) + self.w.update({ 'foo': 0 }) self.w.now = lambda: 11 - self.w.update({ 'foo': 100 }, 999) + self.w.update({ 'foo': 100 }) self.assertEqual(str(self.w), '10 B/s') def test_formats_ten_tibs_per_second_correctly(self): self.w.now = lambda: 1 - self.w.update({ 'foo': 0 }, 999) + self.w.update({ 'foo': 0 }) self.w.now = lambda: 2 - self.w.update({ 'foo': 10 * 1024**4 }, 999) + self.w.update({ 'foo': 10 * 1024**4 }) self.assertEqual(str(self.w), '10.00 TiB/s') diff --git a/ttystatus/counter.py b/ttystatus/counter.py index 5d3e11f..5b92791 100644 --- a/ttystatus/counter.py +++ b/ttystatus/counter.py @@ -25,12 +25,11 @@ class Counter(ttystatus.Widget): self.name = name self.prev = None self.count = 0 - self.interesting_keys = [name] - def format(self): + def __str__(self): return str(self.count) - def update(self, master, width): + def update(self, master): if master[self.name] != self.prev: self.prev = master[self.name] self.count += 1 diff --git a/ttystatus/counter_tests.py b/ttystatus/counter_tests.py index 866bcbd..f7dc3e1 100644 --- a/ttystatus/counter_tests.py +++ b/ttystatus/counter_tests.py @@ -28,16 +28,16 @@ class CounterTests(unittest.TestCase): self.assertEqual(str(self.w), '0') def test_counts_one_change(self): - self.w.update({ 'foo': 'a' }, 999) + self.w.update({ 'foo': 'a' }) self.assertEqual(str(self.w), '1') def test_counts_two_changes(self): - self.w.update({ 'foo': 'a' }, 999) - self.w.update({ 'foo': 'b' }, 999) + self.w.update({ 'foo': 'a' }) + self.w.update({ 'foo': 'b' }) self.assertEqual(str(self.w), '2') def test_does_not_count_if_value_does_not_change(self): - self.w.update({ 'foo': 'a' }, 999) - self.w.update({ 'foo': 'a' }, 999) + self.w.update({ 'foo': 'a' }) + self.w.update({ 'foo': 'a' }) self.assertEqual(str(self.w), '1') diff --git a/ttystatus/elapsed.py b/ttystatus/elapsed.py index 2032e6e..242c092 100644 --- a/ttystatus/elapsed.py +++ b/ttystatus/elapsed.py @@ -25,14 +25,13 @@ class ElapsedTime(ttystatus.Widget): def __init__(self): self.started = None - self.interesting_keys = None 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): + def __str__(self): secs = self.secs hours = secs / 3600 secs %= 3600 @@ -40,7 +39,7 @@ class ElapsedTime(ttystatus.Widget): secs %= 60 return '%02dh%02dm%02ds' % (hours, mins, secs) - def update(self, master, width): + def update(self, master): if self.started is None: self.started = self.get_time() self.secs = self.get_time() - self.started diff --git a/ttystatus/elapsed_tests.py b/ttystatus/elapsed_tests.py index dc2bfe7..9c82acb 100644 --- a/ttystatus/elapsed_tests.py +++ b/ttystatus/elapsed_tests.py @@ -29,13 +29,13 @@ class ElapsedtimeTests(unittest.TestCase): def test_shows_zero_after_first_update(self): self.w.get_time = lambda: 1 - self.w.update({}, 999) + self.w.update({}) self.assertEqual(str(self.w), '00h00m00s') def test_shows_one_one_one_after_second_update(self): self.w.get_time = lambda: 0 - self.w.update({}, 999) + self.w.update({}) self.w.get_time = lambda: 60*60 + 60 + 1 - self.w.update({}, 999) + self.w.update({}) self.assertEqual(str(self.w), '01h01m01s') diff --git a/ttystatus/index.py b/ttystatus/index.py index 941165a..daa13df 100644 --- a/ttystatus/index.py +++ b/ttystatus/index.py @@ -24,18 +24,17 @@ class Index(ttystatus.Widget): def __init__(self, name, listname): self.name = name self.listname = listname - self.interesting_keys = [name, listname] self.value = None self.listvalue = [] - def format(self): + def __str__(self): try: index = self.listvalue.index(self.value) + 1 except ValueError: index = 0 return '%d/%d' % (index, len(self.listvalue)) - def update(self, master, width): + def update(self, master): self.value = master[self.name] self.listvalue = master[self.listname] diff --git a/ttystatus/index_tests.py b/ttystatus/index_tests.py index 3c91903..d3d420e 100644 --- a/ttystatus/index_tests.py +++ b/ttystatus/index_tests.py @@ -28,10 +28,10 @@ class IndexTests(unittest.TestCase): self.assertEqual(str(self.w), '0/0') def test_gets_index_right(self): - self.w.update({ 'foo': 'x', 'foos': ['a', 'x', 'b'] }, 999) + self.w.update({ 'foo': 'x', 'foos': ['a', 'x', 'b'] }) self.assertEqual(str(self.w), '2/3') def test_handles_value_not_in_list(self): - self.w.update({ 'foo': 'xxx', 'foos': ['a', 'x', 'b'] }, 999) + self.w.update({ 'foo': 'xxx', 'foos': ['a', 'x', 'b'] }) self.assertEqual(str(self.w), '0/3') diff --git a/ttystatus/integer.py b/ttystatus/integer.py index b86dbe0..b02a79f 100644 --- a/ttystatus/integer.py +++ b/ttystatus/integer.py @@ -23,13 +23,12 @@ class Integer(ttystatus.Widget): def __init__(self, key): self._key = key - self.interesting_keys = [key] self.value = '#' - def format(self): + def __str__(self): return self.value - def update(self, master, width): + def update(self, master): try: self.value = str(int(master[self._key])) except ValueError: diff --git a/ttystatus/integer_tests.py b/ttystatus/integer_tests.py index a3f04fe..f5b3f54 100644 --- a/ttystatus/integer_tests.py +++ b/ttystatus/integer_tests.py @@ -28,10 +28,10 @@ class IntegerTests(unittest.TestCase): self.assertEqual(str(self.w), '#') def test_updates(self): - self.w.update({'foo': 123}, 999) + self.w.update({'foo': 123}) self.assertEqual(str(self.w), '123') def test_becomes_error_symbol_if_value_is_not_integer(self): - self.w.update({'foo': 'bar'}, 999) + self.w.update({'foo': 'bar'}) self.assertEqual(str(self.w), '#') diff --git a/ttystatus/literal.py b/ttystatus/literal.py index 5c41b69..d0a1dc7 100644 --- a/ttystatus/literal.py +++ b/ttystatus/literal.py @@ -23,7 +23,6 @@ class Literal(ttystatus.Widget): def __init__(self, string): self.value = string - self.interesting_keys = [] - def format(self): + def __str__(self): return self.value diff --git a/ttystatus/pathname.py b/ttystatus/pathname.py index 0f5fb43..a8b8253 100644 --- a/ttystatus/pathname.py +++ b/ttystatus/pathname.py @@ -27,21 +27,11 @@ class Pathname(ttystatus.Widget): def __init__(self, key): self._key = key - self.interesting_keys = [key] self.pathname = '' - self.width = 0 - def format(self): - v = self.pathname - if len(v) > self.width: - ellipsis = '...' - if len(ellipsis) < self.width: - v = ellipsis + v[-(self.width - len(ellipsis)):] - else: - v = v[-self.width:] - return v + def __str__(self): + return self.pathname - def update(self, master, width): + def update(self, master): self.pathname = master.get(self._key, '') - self.width = width diff --git a/ttystatus/pathname_tests.py b/ttystatus/pathname_tests.py index f0c54d5..f9e62ef 100644 --- a/ttystatus/pathname_tests.py +++ b/ttystatus/pathname_tests.py @@ -28,26 +28,9 @@ class PathnameTests(unittest.TestCase): self.assertEqual(str(self.w), '') def test_updates(self): - self.w.update({'foo': 'bar'}, 999) + self.w.update({'foo': 'bar'}) self.assertEqual(str(self.w), 'bar') def test_handles_update_to_other_value(self): - self.w.update({'other': 1}, 999) + self.w.update({'other': 1}) self.assertEqual(str(self.w), '') - - def test_truncates_from_beginning(self): - self.w.update({'foo': 'foobar'}, 5) - self.assertEqual(str(self.w), '...ar') - - def test_does_not_truncate_for_exact_fit(self): - self.w.update({'foo': 'foobar'}, 6) - self.assertEqual(str(self.w), 'foobar') - - def test_does_not_add_ellipsis_if_it_will_not_fit(self): - self.w.update({'foo': 'foobar'}, 3) - self.assertEqual(str(self.w), 'bar') - - def test_adds_ellipsis_if_it_just_fits(self): - self.w.update({'foo': 'foobar'}, 4) - self.assertEqual(str(self.w), '...r') - diff --git a/ttystatus/percent.py b/ttystatus/percent.py index af2935c..840c047 100644 --- a/ttystatus/percent.py +++ b/ttystatus/percent.py @@ -27,9 +27,8 @@ class PercentDone(ttystatus.Widget): self.decimals = decimals self.done = 0 self.total = 1 - self.interesting_keys = [done_name, total_name] - def format(self): + def __str__(self): try: done = float(self.done) total = float(self.total) @@ -40,6 +39,6 @@ class PercentDone(ttystatus.Widget): total = 1 return '%.*f %%' % (self.decimals, 100.0 * done / total) - def update(self, master, width): + def update(self, master): self.done = master[self.done_name] self.total = master[self.total_name] diff --git a/ttystatus/percent_tests.py b/ttystatus/percent_tests.py index 29c7cb4..5f46498 100644 --- a/ttystatus/percent_tests.py +++ b/ttystatus/percent_tests.py @@ -28,14 +28,14 @@ class PercentDoneTests(unittest.TestCase): self.assertEqual(str(self.w), '0.0 %') def test_sets_value(self): - self.w.update({ 'done': 50, 'total': 100 }, 999) + self.w.update({ 'done': 50, 'total': 100 }) self.assertEqual(str(self.w), '50.0 %') def test_handles_empty_strings_as_values(self): - self.w.update({ 'done': '', 'total': '' }, 999) + self.w.update({ 'done': '', 'total': '' }) self.assertEqual(str(self.w), '0.0 %') def test_handles_zero_total(self): - self.w.update({ 'done': 0, 'total': 0 }, 999) + self.w.update({ 'done': 0, 'total': 0 }) self.assertEqual(str(self.w), '0.0 %') diff --git a/ttystatus/progressbar.py b/ttystatus/progressbar.py index e8549f2..d8189d3 100644 --- a/ttystatus/progressbar.py +++ b/ttystatus/progressbar.py @@ -21,15 +21,14 @@ class ProgressBar(ttystatus.Widget): '''Display a progress bar.''' - def __init__(self, done_name, total_name): + def __init__(self, done_name, total_name, width): self.done_name = done_name self.total_name = total_name - self.interesting_keys = [done_name, total_name] self.done = 0 self.total = 1 - self.width = 0 + self.width = width - def format(self): + def __str__(self): try: done = float(self.done) total = float(self.total) @@ -44,8 +43,6 @@ class ProgressBar(ttystatus.Widget): n_dashes = int(self.width - n_stars) return ('#' * n_stars) + ('-' * n_dashes) - def update(self, master, width): + def update(self, master): self.done = master[self.done_name] self.total = master[self.total_name] - self.width = width - diff --git a/ttystatus/progressbar_tests.py b/ttystatus/progressbar_tests.py index 0e3bf5a..a229f46 100644 --- a/ttystatus/progressbar_tests.py +++ b/ttystatus/progressbar_tests.py @@ -22,40 +22,40 @@ import ttystatus class ProgressBarTests(unittest.TestCase): def setUp(self): - self.w = ttystatus.ProgressBar('done', 'total') + self.w = ttystatus.ProgressBar('done', 'total', 10) def test_sets_initial_value_to_empty(self): - self.assertEqual(str(self.w), '') + self.assertEqual(str(self.w), '-' * 10) def test_shows_zero_percent_for_empty_string_total(self): - self.w.update({ 'done': 1, 'total': '' }, 10) + self.w.update({ 'done': 1, 'total': '' }) self.assertEqual(str(self.w), '-' * 10) def test_shows_zero_percent_for_zero_total(self): - self.w.update({ 'done': 1, 'total': 0 }, 10) + self.w.update({ 'done': 1, 'total': 0 }) self.assertEqual(str(self.w), '-' * 10) def test_shows_zero_percent_correctly(self): - self.w.update({ 'done': 0, 'total': 100 }, 10) + self.w.update({ 'done': 0, 'total': 100 }) self.assertEqual(str(self.w), '-' * 10) def test_shows_one_percent_correctly(self): - self.w.update({ 'done': 1, 'total': 100 }, 10) + self.w.update({ 'done': 1, 'total': 100 }) self.assertEqual(str(self.w), '-' * 10) def test_shows_ten_percent_correctly(self): - self.w.update({ 'done': 10, 'total': 100 }, 10) + self.w.update({ 'done': 10, 'total': 100 }) self.assertEqual(str(self.w), '#' + '-' * 9) def test_shows_ninety_percent_correctly(self): - self.w.update({ 'done': 90, 'total': 100 }, 10) + self.w.update({ 'done': 90, 'total': 100 }) self.assertEqual(str(self.w), '#' * 9 + '-') def test_shows_ninety_ine_percent_correctly(self): - self.w.update({ 'done': 99, 'total': 100 }, 10) + self.w.update({ 'done': 99, 'total': 100 }) self.assertEqual(str(self.w), '#' * 10) def test_shows_one_hundred_percent_correctly(self): - self.w.update({ 'done': 100, 'total': 100 }, 10) + self.w.update({ 'done': 100, 'total': 100 }) self.assertEqual(str(self.w), '#' * 10) diff --git a/ttystatus/remtime.py b/ttystatus/remtime.py index fd0d07c..9d90895 100644 --- a/ttystatus/remtime.py +++ b/ttystatus/remtime.py @@ -28,7 +28,6 @@ class RemainingTime(ttystatus.Widget): self.total_name = total_name self.started = None self.default = '--h--m--s' - self.interesting_keys = [done_name, total_name] self.done = 0 self.total = 1 @@ -42,7 +41,7 @@ class RemainingTime(ttystatus.Widget): return time.time() - def format(self): + def __str__(self): if self.started is None: self.started = self.get_time() duration = self.get_time() - self.started @@ -58,6 +57,6 @@ class RemainingTime(ttystatus.Widget): return '%02dh%02dm%02ds' % (hours, mins, secs) return self.default - def update(self, master, width): + def update(self, master): 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 2c67345..dced388 100644 --- a/ttystatus/remtime_tests.py +++ b/ttystatus/remtime_tests.py @@ -30,26 +30,26 @@ class RemainingTimeTests(unittest.TestCase): 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.update({ 'done': 0, 'total': 100 }) self.w.get_time = lambda: 5.0 - self.w.update({ 'done': 5, 'total': 100 }, 999) + self.w.update({ 'done': 5, 'total': 100 }) self.assertEqual(str(self.w), '00h01m35s') self.w.get_time = lambda: 10.0 - self.w.update({ 'done': 5, 'total': 100 }, 999) + self.w.update({ 'done': 5, 'total': 100 }) self.assertEqual(str(self.w), '00h03m10s') self.w.get_time = lambda: 20.0 - self.w.update({ 'done': 80, 'total': 100 }, 999) + self.w.update({ 'done': 80, 'total': 100 }) self.assertEqual(str(self.w), '00h00m05s') def test_handles_zero_speed(self): - self.w.update({ 'done': 0, 'total': 100 }, 999) + self.w.update({ 'done': 0, 'total': 100 }) self.w.get_time = lambda: 5.0 - self.w.update({ 'done': 0, 'total': 100 }, 999) + self.w.update({ 'done': 0, 'total': 100 }) self.assertEqual(str(self.w), '--h--m--s') def test_handles_empty_strings_for_done_and_total(self): - self.w.update({ 'done': '', 'total': '' }, 999) + self.w.update({ 'done': '', 'total': '' }) self.w.get_time = lambda: 5.0 - self.w.update({ 'done': '', 'total': '' }, 999) + self.w.update({ 'done': '', 'total': '' }) self.assertEqual(str(self.w), '--h--m--s') diff --git a/ttystatus/status.py b/ttystatus/status.py index 25fd1c1..ca1f873 100644 --- a/ttystatus/status.py +++ b/ttystatus/status.py @@ -39,11 +39,6 @@ class TerminalStatus(object): def add(self, widget): '''Add a new widget to the status display.''' self._widgets.append(widget) - if widget.interesting_keys is None: - self._wildcards += [widget] - else: - for key in widget.interesting_keys: - self._interests[key] = self._interests.get(key, []) + [widget] def format(self, format_string): '''Add new widgets based on format string. @@ -61,9 +56,6 @@ class TerminalStatus(object): '''Remove all widgets.''' self._widgets = [] self._values = dict() - self._interests = dict() - self._wildcards = list() - self._latest_width = None self._m.clear() def __getitem__(self, key): @@ -82,10 +74,8 @@ class TerminalStatus(object): def _format(self): '''Format and output all widgets.''' - width = self._m.width for w in self._widgets: - w.update(self, width) - width -= len(str(w)) + w.update(self) self._m.write(''.join(str(w) for w in self._widgets)) def increase(self, key, delta): diff --git a/ttystatus/status_tests.py b/ttystatus/status_tests.py index 3583028..d333404 100644 --- a/ttystatus/status_tests.py +++ b/ttystatus/status_tests.py @@ -63,22 +63,6 @@ class TerminalStatusTests(unittest.TestCase): self.ts.add(w) self.assertEqual(self.ts._widgets, [w]) - def test_adds_widget_as_interested_in_keys(self): - class W(ttystatus.Widget): - def __init__(self): - self.interesting_keys = ['foo'] - w = W() - self.ts.add(w) - self.assert_(w in self.ts._interests['foo']) - - def test_adds_widget_to_wildcards(self): - class W(ttystatus.Widget): - def __init__(self): - self.interesting_keys = None - w = W() - self.ts.add(w) - self.assert_(w in self.ts._wildcards) - def test_adds_widgets_from_format_string(self): self.ts.format('hello, %String(name)') self.assertEqual(len(self.ts._widgets), 2) diff --git a/ttystatus/string.py b/ttystatus/string.py index 32a76ea..a23a8e5 100644 --- a/ttystatus/string.py +++ b/ttystatus/string.py @@ -23,11 +23,10 @@ class String(ttystatus.Widget): def __init__(self, key): self._key = key - self.interesting_keys = [key] self.value = '' - def format(self): + def __str__(self): return str(self.value) - def update(self, master, width): + def update(self, master): self.value = master[self._key] diff --git a/ttystatus/string_tests.py b/ttystatus/string_tests.py index 39f480a..aad21f5 100644 --- a/ttystatus/string_tests.py +++ b/ttystatus/string_tests.py @@ -28,9 +28,9 @@ class StringTests(unittest.TestCase): self.assertEqual(str(self.s), '') def test_updates(self): - self.s.update({'foo': 'bar'}, 999) + self.s.update({'foo': 'bar'}) self.assertEqual(str(self.s), 'bar') def test_handles_non_string_value(self): - self.s.update({'foo': 123}, 999) + self.s.update({'foo': 123}) self.assertEqual(str(self.s), '123') diff --git a/ttystatus/widget.py b/ttystatus/widget.py index 0f03365..17c2df4 100644 --- a/ttystatus/widget.py +++ b/ttystatus/widget.py @@ -18,36 +18,20 @@ class Widget(object): '''Base class for ttystatus widgets. - Widgets are responsible for formatting part of the output. They - get a value or values either directly from the user, or from the - master TerminalStatus widget. They return the formatted string - via __str__. + Widgets display stuff on screen. The value may depend on data provided + by the user (at creation time), or may be computed from one or more + values in the TerminalStatus object to which the widget object belongs. - 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. + There are two steps: - 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. + * the widget `update` method is called by TerminalStatus whenever + any of the values change + * the widget `__str__` method is called by TerminalStatus when it is + time to display things ''' - + def __str__(self): - '''Return current value to be displayed for this widget.''' - return self.format() - - def format(self): '''Format the current value. This will be called only when the value actually needs to be @@ -57,11 +41,6 @@ class Widget(object): return '' - def update(self, master, width): - '''Update displayed value for widget, from values in master. - - 'width' gives the width for which the widget should aim to fit. - It is OK if it does not: for some widgets there is no way to - adjust to a smaller size. - - ''' + def update(self, terminal_status): + '''React to changes in values stored in a TerminalStatus.''' + -- cgit v1.2.1 From 9123ef968f09aab58746679dd86d837ea1566aa3 Mon Sep 17 00:00:00 2001 From: Lars Wirzenius Date: Sun, 15 Apr 2012 15:29:57 +0100 Subject: Fix usage of ProgressBar in example --- example.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/example.py b/example.py index 5814fbc..9401704 100644 --- a/example.py +++ b/example.py @@ -47,7 +47,7 @@ def main(): ts.add(ttystatus.Literal(' done) ')) ts.add(ttystatus.RemainingTime('done', 'total')) ts.add(ttystatus.Literal(' ')) - ts.add(ttystatus.ProgressBar('done', 'total')) + ts.add(ttystatus.ProgressBar('done', 'total', 16)) ts['pathnames'] = pathnames ts['done'] = 0 ts['total'] = len(pathnames) -- cgit v1.2.1 From 679fb17bad17d85c950d258b713050a8e293ccd4 Mon Sep 17 00:00:00 2001 From: Lars Wirzenius Date: Sun, 15 Apr 2012 15:32:09 +0100 Subject: Add test to verify widget updates happen without rendering --- ttystatus/status_tests.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/ttystatus/status_tests.py b/ttystatus/status_tests.py index d333404..03a0499 100644 --- a/ttystatus/status_tests.py +++ b/ttystatus/status_tests.py @@ -122,3 +122,11 @@ class TerminalStatusTests(unittest.TestCase): self.ts.enable() self.assert_(self.ts._m.enabled) + def test_counts_correctly_even_without_rendering(self): + w = ttystatus.Counter('value') + n = 42 + self.ts.add(w) + for i in range(n): + self.ts['value'] = i + self.assertEqual(str(w), str(n)) + -- cgit v1.2.1 From 07c8fb7f7add9248492672b00f9078e55cf28292 Mon Sep 17 00:00:00 2001 From: Lars Wirzenius Date: Sun, 15 Apr 2012 15:33:07 +0100 Subject: Actually update widgets when values change Also, don't update them when rendering. --- ttystatus/status.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ttystatus/status.py b/ttystatus/status.py index ca1f873..772273b 100644 --- a/ttystatus/status.py +++ b/ttystatus/status.py @@ -69,13 +69,13 @@ class TerminalStatus(object): def __setitem__(self, key, value): '''Set value for key.''' self._values[key] = value + for w in self._widgets: + w.update(self) if self._m.time_to_write(): self._format() def _format(self): '''Format and output all widgets.''' - for w in self._widgets: - w.update(self) self._m.write(''.join(str(w) for w in self._widgets)) def increase(self, key, delta): -- cgit v1.2.1 From 11a5adc06df5001d589ddfc80717e0e9586e0b3a Mon Sep 17 00:00:00 2001 From: Lars Wirzenius Date: Sun, 15 Apr 2012 15:33:39 +0100 Subject: Refactor: change name of _factor to _render This is clearer, and avoids having both format and _format methods. --- ttystatus/status.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ttystatus/status.py b/ttystatus/status.py index 772273b..e45c774 100644 --- a/ttystatus/status.py +++ b/ttystatus/status.py @@ -72,9 +72,9 @@ class TerminalStatus(object): for w in self._widgets: w.update(self) if self._m.time_to_write(): - self._format() + self._render() - def _format(self): + def _render(self): '''Format and output all widgets.''' self._m.write(''.join(str(w) for w in self._widgets)) @@ -92,7 +92,7 @@ class TerminalStatus(object): def finish(self): '''Finish status display.''' - self._format() + self._render() self._m.finish() def disable(self): -- cgit v1.2.1 From 5cf3c6ea230fab510fb44aa113066a5eb69183f8 Mon Sep 17 00:00:00 2001 From: Lars Wirzenius Date: Sun, 15 Apr 2012 15:37:21 +0100 Subject: Fix Integer() to not render in update --- ttystatus/integer.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/ttystatus/integer.py b/ttystatus/integer.py index b02a79f..1b27126 100644 --- a/ttystatus/integer.py +++ b/ttystatus/integer.py @@ -23,14 +23,14 @@ class Integer(ttystatus.Widget): def __init__(self, key): self._key = key - self.value = '#' + self.value = None def __str__(self): - return self.value + try: + return str(int(self.value)) + except (TypeError, ValueError): + return '#' def update(self, master): - try: - self.value = str(int(master[self._key])) - except ValueError: - self.value = '#' + self.value = master[self._key] -- cgit v1.2.1 From 9cb92e835f1b37a5e5a30c0fdbc76ab3bb220f89 Mon Sep 17 00:00:00 2001 From: Lars Wirzenius Date: Sun, 15 Apr 2012 15:46:33 +0100 Subject: Change __str__ to render We'll want to pass in arguments to render (i.e., width), so using __str__ is not going to be appropriate. --- ttystatus/bytesize.py | 2 +- ttystatus/bytesize_tests.py | 16 ++++++++-------- ttystatus/bytespeed.py | 2 +- ttystatus/bytespeed_tests.py | 10 +++++----- ttystatus/counter.py | 2 +- ttystatus/counter_tests.py | 8 ++++---- ttystatus/elapsed.py | 2 +- ttystatus/elapsed_tests.py | 6 +++--- ttystatus/fmt_tests.py | 8 ++++---- ttystatus/index.py | 2 +- ttystatus/index_tests.py | 6 +++--- ttystatus/integer.py | 2 +- ttystatus/integer_tests.py | 6 +++--- ttystatus/literal.py | 2 +- ttystatus/literal_tests.py | 2 +- ttystatus/pathname.py | 2 +- ttystatus/pathname_tests.py | 6 +++--- ttystatus/percent.py | 2 +- ttystatus/percent_tests.py | 8 ++++---- ttystatus/progressbar.py | 2 +- ttystatus/progressbar_tests.py | 18 +++++++++--------- ttystatus/remtime.py | 2 +- ttystatus/remtime_tests.py | 14 +++++++------- ttystatus/status.py | 2 +- ttystatus/status_tests.py | 6 +++--- ttystatus/string.py | 2 +- ttystatus/string_tests.py | 6 +++--- ttystatus/widget.py | 7 +++++-- 28 files changed, 78 insertions(+), 75 deletions(-) diff --git a/ttystatus/bytesize.py b/ttystatus/bytesize.py index 4c338aa..b5a8059 100644 --- a/ttystatus/bytesize.py +++ b/ttystatus/bytesize.py @@ -28,7 +28,7 @@ class ByteSize(ttystatus.Widget): def update(self, ts): self._bytes = ts[self.name] - def __str__(self): + def render(self): units = ( (1024**4, 2, 'TiB'), (1024**3, 2, 'GiB'), diff --git a/ttystatus/bytesize_tests.py b/ttystatus/bytesize_tests.py index d1dd94d..e6ce761 100644 --- a/ttystatus/bytesize_tests.py +++ b/ttystatus/bytesize_tests.py @@ -25,33 +25,33 @@ class ByteSizeTests(unittest.TestCase): self.w = ttystatus.ByteSize('foo') def test_formats_zero_bytes_without_update(self): - self.assertEqual(str(self.w), '0 B') + self.assertEqual(self.w.render(), '0 B') def test_formats_zero_bytes_correctly(self): self.w.update({ 'foo': 0 }) - self.assertEqual(str(self.w), '0 B') + self.assertEqual(self.w.render(), '0 B') def test_formats_one_bytes_correctly(self): self.w.update({ 'foo': 1 }) - self.assertEqual(str(self.w), '1 B') + self.assertEqual(self.w.render(), '1 B') def test_formats_1023_bytes_correctly(self): self.w.update({ 'foo': 1023 }) - self.assertEqual(str(self.w), '1023 B') + self.assertEqual(self.w.render(), '1023 B') def test_formats_1024_bytes_correctly(self): self.w.update({ 'foo': 1024 }) - self.assertEqual(str(self.w), '1.0 KiB') + self.assertEqual(self.w.render(), '1.0 KiB') def test_formats_1_MiB_bytes_correctly(self): self.w.update({ 'foo': 1024**2 }) - self.assertEqual(str(self.w), '1.00 MiB') + self.assertEqual(self.w.render(), '1.00 MiB') def test_formats_1_GiB_bytes_correctly(self): self.w.update({ 'foo': 1024**3 }) - self.assertEqual(str(self.w), '1.00 GiB') + self.assertEqual(self.w.render(), '1.00 GiB') def test_formats_1_TiB_bytes_correctly(self): self.w.update({ 'foo': 1024**4 }) - self.assertEqual(str(self.w), '1.00 TiB') + self.assertEqual(self.w.render(), '1.00 TiB') diff --git a/ttystatus/bytespeed.py b/ttystatus/bytespeed.py index cc62300..d7e8b78 100644 --- a/ttystatus/bytespeed.py +++ b/ttystatus/bytespeed.py @@ -33,7 +33,7 @@ class ByteSpeed(ttystatus.Widget): return time.time() - def __str__(self): + def render(self): units = ( (1024**4, 2, 'TiB/s'), (1024**3, 2, 'GiB/s'), diff --git a/ttystatus/bytespeed_tests.py b/ttystatus/bytespeed_tests.py index 369c2f6..b56afc3 100644 --- a/ttystatus/bytespeed_tests.py +++ b/ttystatus/bytespeed_tests.py @@ -25,30 +25,30 @@ class ByteSpeedTests(unittest.TestCase): self.w = ttystatus.ByteSpeed('foo') def test_formats_zero_speed_without_update(self): - self.assertEqual(str(self.w), '0 B/s') + self.assertEqual(self.w.render(), '0 B/s') def test_formats_zero_bytes_correctly(self): self.w.update({ 'foo': 0 }) - self.assertEqual(str(self.w), '0 B/s') + self.assertEqual(self.w.render(), '0 B/s') def test_formats_one_byte_per_second_correctly(self): self.w.now = lambda: 1 self.w.update({ 'foo': 0 }) self.w.now = lambda: 2 self.w.update({ 'foo': 1 }) - self.assertEqual(str(self.w), '1 B/s') + self.assertEqual(self.w.render(), '1 B/s') def test_formats_ten_bytes_per_second_correctly(self): self.w.now = lambda: 1 self.w.update({ 'foo': 0 }) self.w.now = lambda: 11 self.w.update({ 'foo': 100 }) - self.assertEqual(str(self.w), '10 B/s') + self.assertEqual(self.w.render(), '10 B/s') def test_formats_ten_tibs_per_second_correctly(self): self.w.now = lambda: 1 self.w.update({ 'foo': 0 }) self.w.now = lambda: 2 self.w.update({ 'foo': 10 * 1024**4 }) - self.assertEqual(str(self.w), '10.00 TiB/s') + self.assertEqual(self.w.render(), '10.00 TiB/s') diff --git a/ttystatus/counter.py b/ttystatus/counter.py index 5b92791..ae61fa0 100644 --- a/ttystatus/counter.py +++ b/ttystatus/counter.py @@ -26,7 +26,7 @@ class Counter(ttystatus.Widget): self.prev = None self.count = 0 - def __str__(self): + def render(self): return str(self.count) def update(self, master): diff --git a/ttystatus/counter_tests.py b/ttystatus/counter_tests.py index f7dc3e1..638de6a 100644 --- a/ttystatus/counter_tests.py +++ b/ttystatus/counter_tests.py @@ -25,19 +25,19 @@ class CounterTests(unittest.TestCase): self.w = ttystatus.Counter('foo') def test_counts_zero_initially(self): - self.assertEqual(str(self.w), '0') + self.assertEqual(self.w.render(), '0') def test_counts_one_change(self): self.w.update({ 'foo': 'a' }) - self.assertEqual(str(self.w), '1') + self.assertEqual(self.w.render(), '1') def test_counts_two_changes(self): self.w.update({ 'foo': 'a' }) self.w.update({ 'foo': 'b' }) - self.assertEqual(str(self.w), '2') + self.assertEqual(self.w.render(), '2') def test_does_not_count_if_value_does_not_change(self): self.w.update({ 'foo': 'a' }) self.w.update({ 'foo': 'a' }) - self.assertEqual(str(self.w), '1') + self.assertEqual(self.w.render(), '1') diff --git a/ttystatus/elapsed.py b/ttystatus/elapsed.py index 242c092..3a85303 100644 --- a/ttystatus/elapsed.py +++ b/ttystatus/elapsed.py @@ -31,7 +31,7 @@ class ElapsedTime(ttystatus.Widget): '''Wrapper around time.time() for unit tests to override.''' return time.time() - def __str__(self): + def render(self): secs = self.secs hours = secs / 3600 secs %= 3600 diff --git a/ttystatus/elapsed_tests.py b/ttystatus/elapsed_tests.py index 9c82acb..3197a77 100644 --- a/ttystatus/elapsed_tests.py +++ b/ttystatus/elapsed_tests.py @@ -25,17 +25,17 @@ class ElapsedtimeTests(unittest.TestCase): self.w = ttystatus.ElapsedTime() def test_shows_zero_initially(self): - self.assertEqual(str(self.w), '00h00m00s') + self.assertEqual(self.w.render(), '00h00m00s') def test_shows_zero_after_first_update(self): self.w.get_time = lambda: 1 self.w.update({}) - self.assertEqual(str(self.w), '00h00m00s') + self.assertEqual(self.w.render(), '00h00m00s') def test_shows_one_one_one_after_second_update(self): self.w.get_time = lambda: 0 self.w.update({}) self.w.get_time = lambda: 60*60 + 60 + 1 self.w.update({}) - self.assertEqual(str(self.w), '01h01m01s') + self.assertEqual(self.w.render(), '01h01m01s') diff --git a/ttystatus/fmt_tests.py b/ttystatus/fmt_tests.py index af39948..422a7fe 100644 --- a/ttystatus/fmt_tests.py +++ b/ttystatus/fmt_tests.py @@ -32,13 +32,13 @@ class FormatTests(unittest.TestCase): x = ttystatus.fmt.parse('hello, world') self.assertEqual(len(x), 1) self.assertEqual(type(x[0]), ttystatus.Literal) - self.assertEqual(str(x[0]), 'hello, world') + self.assertEqual(x[0].render(), 'hello, world') def test_parses_escaped_pecent(self): x = ttystatus.fmt.parse('%%') self.assertEqual(len(x), 1) self.assertEqual(type(x[0]), ttystatus.Literal) - self.assertEqual(str(x[0]), '%') + self.assertEqual(x[0].render(), '%') def test_parses_parameterless_widget(self): x = ttystatus.fmt.parse('%ElapsedTime()') @@ -60,12 +60,12 @@ class FormatTests(unittest.TestCase): self.assertEqual(len(x), 4) self.assertEqual(type(x[0]), ttystatus.Literal) - self.assertEqual(str(x[0]), 'hello, ') + self.assertEqual(x[0].render(), 'hello, ') self.assertEqual(type(x[1]), ttystatus.String) self.assertEqual(type(x[2]), ttystatus.Literal) - self.assertEqual(str(x[2]), ': ') + self.assertEqual(x[2].render(), ': ') self.assertEqual(type(x[3]), ttystatus.ElapsedTime) diff --git a/ttystatus/index.py b/ttystatus/index.py index daa13df..3e73502 100644 --- a/ttystatus/index.py +++ b/ttystatus/index.py @@ -27,7 +27,7 @@ class Index(ttystatus.Widget): self.value = None self.listvalue = [] - def __str__(self): + def render(self): try: index = self.listvalue.index(self.value) + 1 except ValueError: diff --git a/ttystatus/index_tests.py b/ttystatus/index_tests.py index d3d420e..05d2db7 100644 --- a/ttystatus/index_tests.py +++ b/ttystatus/index_tests.py @@ -25,13 +25,13 @@ class IndexTests(unittest.TestCase): self.w = ttystatus.Index('foo', 'foos') def test_is_zero_initially(self): - self.assertEqual(str(self.w), '0/0') + self.assertEqual(self.w.render(), '0/0') def test_gets_index_right(self): self.w.update({ 'foo': 'x', 'foos': ['a', 'x', 'b'] }) - self.assertEqual(str(self.w), '2/3') + self.assertEqual(self.w.render(), '2/3') def test_handles_value_not_in_list(self): self.w.update({ 'foo': 'xxx', 'foos': ['a', 'x', 'b'] }) - self.assertEqual(str(self.w), '0/3') + self.assertEqual(self.w.render(), '0/3') diff --git a/ttystatus/integer.py b/ttystatus/integer.py index 1b27126..7def9ff 100644 --- a/ttystatus/integer.py +++ b/ttystatus/integer.py @@ -25,7 +25,7 @@ class Integer(ttystatus.Widget): self._key = key self.value = None - def __str__(self): + def render(self): try: return str(int(self.value)) except (TypeError, ValueError): diff --git a/ttystatus/integer_tests.py b/ttystatus/integer_tests.py index f5b3f54..9ea8054 100644 --- a/ttystatus/integer_tests.py +++ b/ttystatus/integer_tests.py @@ -25,13 +25,13 @@ class IntegerTests(unittest.TestCase): self.w = ttystatus.Integer('foo') def test_is_error_initially(self): - self.assertEqual(str(self.w), '#') + self.assertEqual(self.w.render(), '#') def test_updates(self): self.w.update({'foo': 123}) - self.assertEqual(str(self.w), '123') + self.assertEqual(self.w.render(), '123') def test_becomes_error_symbol_if_value_is_not_integer(self): self.w.update({'foo': 'bar'}) - self.assertEqual(str(self.w), '#') + self.assertEqual(self.w.render(), '#') diff --git a/ttystatus/literal.py b/ttystatus/literal.py index d0a1dc7..fa09ceb 100644 --- a/ttystatus/literal.py +++ b/ttystatus/literal.py @@ -24,5 +24,5 @@ class Literal(ttystatus.Widget): def __init__(self, string): self.value = string - def __str__(self): + def render(self): return self.value diff --git a/ttystatus/literal_tests.py b/ttystatus/literal_tests.py index 969439d..73c8964 100644 --- a/ttystatus/literal_tests.py +++ b/ttystatus/literal_tests.py @@ -23,4 +23,4 @@ class LiteralTests(unittest.TestCase): def test_sets_value_correctly(self): literal = ttystatus.Literal('foo') - self.assertEqual(str(literal), 'foo') + self.assertEqual(literal.render(), 'foo') diff --git a/ttystatus/pathname.py b/ttystatus/pathname.py index a8b8253..0ecf4a7 100644 --- a/ttystatus/pathname.py +++ b/ttystatus/pathname.py @@ -29,7 +29,7 @@ class Pathname(ttystatus.Widget): self._key = key self.pathname = '' - def __str__(self): + def render(self): return self.pathname def update(self, master): diff --git a/ttystatus/pathname_tests.py b/ttystatus/pathname_tests.py index f9e62ef..7f09de0 100644 --- a/ttystatus/pathname_tests.py +++ b/ttystatus/pathname_tests.py @@ -25,12 +25,12 @@ class PathnameTests(unittest.TestCase): self.w = ttystatus.Pathname('foo') def test_is_empty_initially(self): - self.assertEqual(str(self.w), '') + self.assertEqual(self.w.render(), '') def test_updates(self): self.w.update({'foo': 'bar'}) - self.assertEqual(str(self.w), 'bar') + self.assertEqual(self.w.render(), 'bar') def test_handles_update_to_other_value(self): self.w.update({'other': 1}) - self.assertEqual(str(self.w), '') + self.assertEqual(self.w.render(), '') diff --git a/ttystatus/percent.py b/ttystatus/percent.py index 840c047..117fecc 100644 --- a/ttystatus/percent.py +++ b/ttystatus/percent.py @@ -28,7 +28,7 @@ class PercentDone(ttystatus.Widget): self.done = 0 self.total = 1 - def __str__(self): + def render(self): try: done = float(self.done) total = float(self.total) diff --git a/ttystatus/percent_tests.py b/ttystatus/percent_tests.py index 5f46498..c7d8d64 100644 --- a/ttystatus/percent_tests.py +++ b/ttystatus/percent_tests.py @@ -25,17 +25,17 @@ class PercentDoneTests(unittest.TestCase): self.w = ttystatus.PercentDone('done', 'total', decimals=1) def test_shows_zero_value_initially(self): - self.assertEqual(str(self.w), '0.0 %') + self.assertEqual(self.w.render(), '0.0 %') def test_sets_value(self): self.w.update({ 'done': 50, 'total': 100 }) - self.assertEqual(str(self.w), '50.0 %') + self.assertEqual(self.w.render(), '50.0 %') def test_handles_empty_strings_as_values(self): self.w.update({ 'done': '', 'total': '' }) - self.assertEqual(str(self.w), '0.0 %') + self.assertEqual(self.w.render(), '0.0 %') def test_handles_zero_total(self): self.w.update({ 'done': 0, 'total': 0 }) - self.assertEqual(str(self.w), '0.0 %') + self.assertEqual(self.w.render(), '0.0 %') diff --git a/ttystatus/progressbar.py b/ttystatus/progressbar.py index d8189d3..54ca99f 100644 --- a/ttystatus/progressbar.py +++ b/ttystatus/progressbar.py @@ -28,7 +28,7 @@ class ProgressBar(ttystatus.Widget): self.total = 1 self.width = width - def __str__(self): + def render(self): try: done = float(self.done) total = float(self.total) diff --git a/ttystatus/progressbar_tests.py b/ttystatus/progressbar_tests.py index a229f46..8c7c261 100644 --- a/ttystatus/progressbar_tests.py +++ b/ttystatus/progressbar_tests.py @@ -25,37 +25,37 @@ class ProgressBarTests(unittest.TestCase): self.w = ttystatus.ProgressBar('done', 'total', 10) def test_sets_initial_value_to_empty(self): - self.assertEqual(str(self.w), '-' * 10) + self.assertEqual(self.w.render(), '-' * 10) def test_shows_zero_percent_for_empty_string_total(self): self.w.update({ 'done': 1, 'total': '' }) - self.assertEqual(str(self.w), '-' * 10) + self.assertEqual(self.w.render(), '-' * 10) def test_shows_zero_percent_for_zero_total(self): self.w.update({ 'done': 1, 'total': 0 }) - self.assertEqual(str(self.w), '-' * 10) + self.assertEqual(self.w.render(), '-' * 10) def test_shows_zero_percent_correctly(self): self.w.update({ 'done': 0, 'total': 100 }) - self.assertEqual(str(self.w), '-' * 10) + self.assertEqual(self.w.render(), '-' * 10) def test_shows_one_percent_correctly(self): self.w.update({ 'done': 1, 'total': 100 }) - self.assertEqual(str(self.w), '-' * 10) + self.assertEqual(self.w.render(), '-' * 10) def test_shows_ten_percent_correctly(self): self.w.update({ 'done': 10, 'total': 100 }) - self.assertEqual(str(self.w), '#' + '-' * 9) + self.assertEqual(self.w.render(), '#' + '-' * 9) def test_shows_ninety_percent_correctly(self): self.w.update({ 'done': 90, 'total': 100 }) - self.assertEqual(str(self.w), '#' * 9 + '-') + self.assertEqual(self.w.render(), '#' * 9 + '-') def test_shows_ninety_ine_percent_correctly(self): self.w.update({ 'done': 99, 'total': 100 }) - self.assertEqual(str(self.w), '#' * 10) + self.assertEqual(self.w.render(), '#' * 10) def test_shows_one_hundred_percent_correctly(self): self.w.update({ 'done': 100, 'total': 100 }) - self.assertEqual(str(self.w), '#' * 10) + self.assertEqual(self.w.render(), '#' * 10) diff --git a/ttystatus/remtime.py b/ttystatus/remtime.py index 9d90895..50529e6 100644 --- a/ttystatus/remtime.py +++ b/ttystatus/remtime.py @@ -41,7 +41,7 @@ class RemainingTime(ttystatus.Widget): return time.time() - def __str__(self): + def render(self): if self.started is None: self.started = self.get_time() duration = self.get_time() - self.started diff --git a/ttystatus/remtime_tests.py b/ttystatus/remtime_tests.py index dced388..df6bced 100644 --- a/ttystatus/remtime_tests.py +++ b/ttystatus/remtime_tests.py @@ -26,30 +26,30 @@ class RemainingTimeTests(unittest.TestCase): self.w.get_time = lambda: 0.0 def test_is_dashes_initially(self): - self.assertEqual(str(self.w), '--h--m--s') + self.assertEqual(self.w.render(), '--h--m--s') def test_estimates_and_formats_correctly(self): - self.assertEqual(str(self.w), '--h--m--s') + self.assertEqual(self.w.render(), '--h--m--s') self.w.update({ 'done': 0, 'total': 100 }) self.w.get_time = lambda: 5.0 self.w.update({ 'done': 5, 'total': 100 }) - self.assertEqual(str(self.w), '00h01m35s') + self.assertEqual(self.w.render(), '00h01m35s') self.w.get_time = lambda: 10.0 self.w.update({ 'done': 5, 'total': 100 }) - self.assertEqual(str(self.w), '00h03m10s') + self.assertEqual(self.w.render(), '00h03m10s') self.w.get_time = lambda: 20.0 self.w.update({ 'done': 80, 'total': 100 }) - self.assertEqual(str(self.w), '00h00m05s') + self.assertEqual(self.w.render(), '00h00m05s') def test_handles_zero_speed(self): self.w.update({ 'done': 0, 'total': 100 }) self.w.get_time = lambda: 5.0 self.w.update({ 'done': 0, 'total': 100 }) - self.assertEqual(str(self.w), '--h--m--s') + self.assertEqual(self.w.render(), '--h--m--s') def test_handles_empty_strings_for_done_and_total(self): self.w.update({ 'done': '', 'total': '' }) self.w.get_time = lambda: 5.0 self.w.update({ 'done': '', 'total': '' }) - self.assertEqual(str(self.w), '--h--m--s') + self.assertEqual(self.w.render(), '--h--m--s') diff --git a/ttystatus/status.py b/ttystatus/status.py index e45c774..526029b 100644 --- a/ttystatus/status.py +++ b/ttystatus/status.py @@ -76,7 +76,7 @@ class TerminalStatus(object): def _render(self): '''Format and output all widgets.''' - self._m.write(''.join(str(w) for w in self._widgets)) + self._m.write(''.join(w.render() for w in self._widgets)) def increase(self, key, delta): '''Increase value for a key by a given amount.''' diff --git a/ttystatus/status_tests.py b/ttystatus/status_tests.py index 03a0499..bb581f6 100644 --- a/ttystatus/status_tests.py +++ b/ttystatus/status_tests.py @@ -94,9 +94,9 @@ class TerminalStatusTests(unittest.TestCase): def test_updates_widgets_when_value_is_set(self): w = ttystatus.String('foo') self.ts.add(w) - self.assertEqual(str(w), '') + self.assertEqual(w.render(), '') self.ts['foo'] = 'bar' - self.assertEqual(str(w), 'bar') + self.assertEqual(w.render(), 'bar') def test_increases_value(self): self.ts['foo'] = 10 @@ -128,5 +128,5 @@ class TerminalStatusTests(unittest.TestCase): self.ts.add(w) for i in range(n): self.ts['value'] = i - self.assertEqual(str(w), str(n)) + self.assertEqual(w.render(), str(n)) diff --git a/ttystatus/string.py b/ttystatus/string.py index a23a8e5..90fb48b 100644 --- a/ttystatus/string.py +++ b/ttystatus/string.py @@ -25,7 +25,7 @@ class String(ttystatus.Widget): self._key = key self.value = '' - def __str__(self): + def render(self): return str(self.value) def update(self, master): diff --git a/ttystatus/string_tests.py b/ttystatus/string_tests.py index aad21f5..b377f37 100644 --- a/ttystatus/string_tests.py +++ b/ttystatus/string_tests.py @@ -25,12 +25,12 @@ class StringTests(unittest.TestCase): self.s = ttystatus.String('foo') def test_is_empty_initially(self): - self.assertEqual(str(self.s), '') + self.assertEqual(self.s.render(), '') def test_updates(self): self.s.update({'foo': 'bar'}) - self.assertEqual(str(self.s), 'bar') + self.assertEqual(self.s.render(), 'bar') def test_handles_non_string_value(self): self.s.update({'foo': 123}) - self.assertEqual(str(self.s), '123') + self.assertEqual(self.s.render(), '123') diff --git a/ttystatus/widget.py b/ttystatus/widget.py index 17c2df4..9fccc29 100644 --- a/ttystatus/widget.py +++ b/ttystatus/widget.py @@ -26,12 +26,15 @@ class Widget(object): * the widget `update` method is called by TerminalStatus whenever any of the values change - * the widget `__str__` method is called by TerminalStatus when it is + * the widget `render` method is called by TerminalStatus when it is time to display things - + ''' def __str__(self): + raise NotImplementedError() + + def render(self): '''Format the current value. This will be called only when the value actually needs to be -- cgit v1.2.1 From b3cd2a40dc74bb33753c5c04bab06b5e93086d64 Mon Sep 17 00:00:00 2001 From: Lars Wirzenius Date: Sun, 15 Apr 2012 19:08:23 +0100 Subject: Add width argument to render() method --- ttystatus/bytesize.py | 4 +++- ttystatus/bytesize_tests.py | 19 +++++++++++-------- ttystatus/bytespeed.py | 4 +++- ttystatus/bytespeed_tests.py | 13 ++++++++----- ttystatus/counter.py | 4 +++- ttystatus/counter_tests.py | 11 +++++++---- ttystatus/elapsed.py | 2 +- ttystatus/elapsed_tests.py | 9 ++++++--- ttystatus/fmt_tests.py | 8 ++++---- ttystatus/index.py | 4 +++- ttystatus/index_tests.py | 9 ++++++--- ttystatus/integer.py | 4 +++- ttystatus/integer_tests.py | 9 ++++++--- ttystatus/literal.py | 2 +- ttystatus/literal_tests.py | 9 +++++++-- ttystatus/pathname.py | 4 +++- ttystatus/pathname_tests.py | 9 ++++++--- ttystatus/percent.py | 4 +++- ttystatus/percent_tests.py | 11 +++++++---- ttystatus/progressbar.py | 11 ++++++----- ttystatus/progressbar_tests.py | 24 ++++++++++++++---------- ttystatus/remtime.py | 2 +- ttystatus/remtime_tests.py | 17 ++++++++++------- ttystatus/status.py | 2 +- ttystatus/status_tests.py | 6 +++--- ttystatus/string.py | 4 +++- ttystatus/string_tests.py | 9 ++++++--- ttystatus/widget.py | 17 ++++++++++++++++- 28 files changed, 151 insertions(+), 80 deletions(-) diff --git a/ttystatus/bytesize.py b/ttystatus/bytesize.py index b5a8059..13ee68b 100644 --- a/ttystatus/bytesize.py +++ b/ttystatus/bytesize.py @@ -20,6 +20,8 @@ import ttystatus class ByteSize(ttystatus.Widget): '''Display data size in bytes, KiB, etc.''' + + static_width = False def __init__(self, name): self.name = name @@ -28,7 +30,7 @@ class ByteSize(ttystatus.Widget): def update(self, ts): self._bytes = ts[self.name] - def render(self): + def render(self, width): units = ( (1024**4, 2, 'TiB'), (1024**3, 2, 'GiB'), diff --git a/ttystatus/bytesize_tests.py b/ttystatus/bytesize_tests.py index e6ce761..15a0ff5 100644 --- a/ttystatus/bytesize_tests.py +++ b/ttystatus/bytesize_tests.py @@ -24,34 +24,37 @@ class ByteSizeTests(unittest.TestCase): def setUp(self): self.w = ttystatus.ByteSize('foo') + def test_is_not_static_width(self): + self.assertFalse(self.w.static_width) + def test_formats_zero_bytes_without_update(self): - self.assertEqual(self.w.render(), '0 B') + self.assertEqual(self.w.render(0), '0 B') def test_formats_zero_bytes_correctly(self): self.w.update({ 'foo': 0 }) - self.assertEqual(self.w.render(), '0 B') + self.assertEqual(self.w.render(0), '0 B') def test_formats_one_bytes_correctly(self): self.w.update({ 'foo': 1 }) - self.assertEqual(self.w.render(), '1 B') + self.assertEqual(self.w.render(0), '1 B') def test_formats_1023_bytes_correctly(self): self.w.update({ 'foo': 1023 }) - self.assertEqual(self.w.render(), '1023 B') + self.assertEqual(self.w.render(0), '1023 B') def test_formats_1024_bytes_correctly(self): self.w.update({ 'foo': 1024 }) - self.assertEqual(self.w.render(), '1.0 KiB') + self.assertEqual(self.w.render(0), '1.0 KiB') def test_formats_1_MiB_bytes_correctly(self): self.w.update({ 'foo': 1024**2 }) - self.assertEqual(self.w.render(), '1.00 MiB') + self.assertEqual(self.w.render(0), '1.00 MiB') def test_formats_1_GiB_bytes_correctly(self): self.w.update({ 'foo': 1024**3 }) - self.assertEqual(self.w.render(), '1.00 GiB') + self.assertEqual(self.w.render(0), '1.00 GiB') def test_formats_1_TiB_bytes_correctly(self): self.w.update({ 'foo': 1024**4 }) - self.assertEqual(self.w.render(), '1.00 TiB') + self.assertEqual(self.w.render(0), '1.00 TiB') diff --git a/ttystatus/bytespeed.py b/ttystatus/bytespeed.py index d7e8b78..3331069 100644 --- a/ttystatus/bytespeed.py +++ b/ttystatus/bytespeed.py @@ -22,6 +22,8 @@ import ttystatus class ByteSpeed(ttystatus.Widget): '''Display data size in bytes, KiB, etc.''' + + static_width = False def __init__(self, name): self.name = name @@ -33,7 +35,7 @@ class ByteSpeed(ttystatus.Widget): return time.time() - def render(self): + def render(self, width): units = ( (1024**4, 2, 'TiB/s'), (1024**3, 2, 'GiB/s'), diff --git a/ttystatus/bytespeed_tests.py b/ttystatus/bytespeed_tests.py index b56afc3..9bcc1e0 100644 --- a/ttystatus/bytespeed_tests.py +++ b/ttystatus/bytespeed_tests.py @@ -24,31 +24,34 @@ class ByteSpeedTests(unittest.TestCase): def setUp(self): self.w = ttystatus.ByteSpeed('foo') + def test_is_not_static_width(self): + self.assertFalse(self.w.static_width) + def test_formats_zero_speed_without_update(self): - self.assertEqual(self.w.render(), '0 B/s') + self.assertEqual(self.w.render(0), '0 B/s') def test_formats_zero_bytes_correctly(self): self.w.update({ 'foo': 0 }) - self.assertEqual(self.w.render(), '0 B/s') + self.assertEqual(self.w.render(0), '0 B/s') def test_formats_one_byte_per_second_correctly(self): self.w.now = lambda: 1 self.w.update({ 'foo': 0 }) self.w.now = lambda: 2 self.w.update({ 'foo': 1 }) - self.assertEqual(self.w.render(), '1 B/s') + self.assertEqual(self.w.render(0), '1 B/s') def test_formats_ten_bytes_per_second_correctly(self): self.w.now = lambda: 1 self.w.update({ 'foo': 0 }) self.w.now = lambda: 11 self.w.update({ 'foo': 100 }) - self.assertEqual(self.w.render(), '10 B/s') + self.assertEqual(self.w.render(0), '10 B/s') def test_formats_ten_tibs_per_second_correctly(self): self.w.now = lambda: 1 self.w.update({ 'foo': 0 }) self.w.now = lambda: 2 self.w.update({ 'foo': 10 * 1024**4 }) - self.assertEqual(self.w.render(), '10.00 TiB/s') + self.assertEqual(self.w.render(0), '10.00 TiB/s') diff --git a/ttystatus/counter.py b/ttystatus/counter.py index ae61fa0..d37ed90 100644 --- a/ttystatus/counter.py +++ b/ttystatus/counter.py @@ -21,12 +21,14 @@ class Counter(ttystatus.Widget): '''Display a count of how many times a value has changed.''' + static_width = False + def __init__(self, name): self.name = name self.prev = None self.count = 0 - def render(self): + def render(self, width): return str(self.count) def update(self, master): diff --git a/ttystatus/counter_tests.py b/ttystatus/counter_tests.py index 638de6a..cadadea 100644 --- a/ttystatus/counter_tests.py +++ b/ttystatus/counter_tests.py @@ -24,20 +24,23 @@ class CounterTests(unittest.TestCase): def setUp(self): self.w = ttystatus.Counter('foo') + def test_is_not_static_width(self): + self.assertFalse(self.w.static_width) + def test_counts_zero_initially(self): - self.assertEqual(self.w.render(), '0') + self.assertEqual(self.w.render(0), '0') def test_counts_one_change(self): self.w.update({ 'foo': 'a' }) - self.assertEqual(self.w.render(), '1') + self.assertEqual(self.w.render(0), '1') def test_counts_two_changes(self): self.w.update({ 'foo': 'a' }) self.w.update({ 'foo': 'b' }) - self.assertEqual(self.w.render(), '2') + self.assertEqual(self.w.render(0), '2') def test_does_not_count_if_value_does_not_change(self): self.w.update({ 'foo': 'a' }) self.w.update({ 'foo': 'a' }) - self.assertEqual(self.w.render(), '1') + self.assertEqual(self.w.render(0), '1') diff --git a/ttystatus/elapsed.py b/ttystatus/elapsed.py index 3a85303..cb75722 100644 --- a/ttystatus/elapsed.py +++ b/ttystatus/elapsed.py @@ -31,7 +31,7 @@ class ElapsedTime(ttystatus.Widget): '''Wrapper around time.time() for unit tests to override.''' return time.time() - def render(self): + def render(self, width): secs = self.secs hours = secs / 3600 secs %= 3600 diff --git a/ttystatus/elapsed_tests.py b/ttystatus/elapsed_tests.py index 3197a77..b87d57c 100644 --- a/ttystatus/elapsed_tests.py +++ b/ttystatus/elapsed_tests.py @@ -24,18 +24,21 @@ class ElapsedtimeTests(unittest.TestCase): def setUp(self): self.w = ttystatus.ElapsedTime() + def test_is_static_width(self): + self.assertTrue(self.w.static_width) + def test_shows_zero_initially(self): - self.assertEqual(self.w.render(), '00h00m00s') + self.assertEqual(self.w.render(0), '00h00m00s') def test_shows_zero_after_first_update(self): self.w.get_time = lambda: 1 self.w.update({}) - self.assertEqual(self.w.render(), '00h00m00s') + self.assertEqual(self.w.render(0), '00h00m00s') def test_shows_one_one_one_after_second_update(self): self.w.get_time = lambda: 0 self.w.update({}) self.w.get_time = lambda: 60*60 + 60 + 1 self.w.update({}) - self.assertEqual(self.w.render(), '01h01m01s') + self.assertEqual(self.w.render(0), '01h01m01s') diff --git a/ttystatus/fmt_tests.py b/ttystatus/fmt_tests.py index 422a7fe..310f131 100644 --- a/ttystatus/fmt_tests.py +++ b/ttystatus/fmt_tests.py @@ -32,13 +32,13 @@ class FormatTests(unittest.TestCase): x = ttystatus.fmt.parse('hello, world') self.assertEqual(len(x), 1) self.assertEqual(type(x[0]), ttystatus.Literal) - self.assertEqual(x[0].render(), 'hello, world') + self.assertEqual(x[0].render(0), 'hello, world') def test_parses_escaped_pecent(self): x = ttystatus.fmt.parse('%%') self.assertEqual(len(x), 1) self.assertEqual(type(x[0]), ttystatus.Literal) - self.assertEqual(x[0].render(), '%') + self.assertEqual(x[0].render(0), '%') def test_parses_parameterless_widget(self): x = ttystatus.fmt.parse('%ElapsedTime()') @@ -60,12 +60,12 @@ class FormatTests(unittest.TestCase): self.assertEqual(len(x), 4) self.assertEqual(type(x[0]), ttystatus.Literal) - self.assertEqual(x[0].render(), 'hello, ') + self.assertEqual(x[0].render(0), 'hello, ') self.assertEqual(type(x[1]), ttystatus.String) self.assertEqual(type(x[2]), ttystatus.Literal) - self.assertEqual(x[2].render(), ': ') + self.assertEqual(x[2].render(0), ': ') self.assertEqual(type(x[3]), ttystatus.ElapsedTime) diff --git a/ttystatus/index.py b/ttystatus/index.py index 3e73502..0158037 100644 --- a/ttystatus/index.py +++ b/ttystatus/index.py @@ -21,13 +21,15 @@ class Index(ttystatus.Widget): '''Display the position of a value in a list of values.''' + static_width = False + def __init__(self, name, listname): self.name = name self.listname = listname self.value = None self.listvalue = [] - def render(self): + def render(self, render): try: index = self.listvalue.index(self.value) + 1 except ValueError: diff --git a/ttystatus/index_tests.py b/ttystatus/index_tests.py index 05d2db7..ccc4d4c 100644 --- a/ttystatus/index_tests.py +++ b/ttystatus/index_tests.py @@ -24,14 +24,17 @@ class IndexTests(unittest.TestCase): def setUp(self): self.w = ttystatus.Index('foo', 'foos') + def test_is_not_static_width(self): + self.assertFalse(self.w.static_width) + def test_is_zero_initially(self): - self.assertEqual(self.w.render(), '0/0') + self.assertEqual(self.w.render(0), '0/0') def test_gets_index_right(self): self.w.update({ 'foo': 'x', 'foos': ['a', 'x', 'b'] }) - self.assertEqual(self.w.render(), '2/3') + self.assertEqual(self.w.render(0), '2/3') def test_handles_value_not_in_list(self): self.w.update({ 'foo': 'xxx', 'foos': ['a', 'x', 'b'] }) - self.assertEqual(self.w.render(), '0/3') + self.assertEqual(self.w.render(0), '0/3') diff --git a/ttystatus/integer.py b/ttystatus/integer.py index 7def9ff..7995bee 100644 --- a/ttystatus/integer.py +++ b/ttystatus/integer.py @@ -21,11 +21,13 @@ class Integer(ttystatus.Widget): '''Display a value as an integer.''' + static_width = False + def __init__(self, key): self._key = key self.value = None - def render(self): + def render(self, width): try: return str(int(self.value)) except (TypeError, ValueError): diff --git a/ttystatus/integer_tests.py b/ttystatus/integer_tests.py index 9ea8054..e064621 100644 --- a/ttystatus/integer_tests.py +++ b/ttystatus/integer_tests.py @@ -24,14 +24,17 @@ class IntegerTests(unittest.TestCase): def setUp(self): self.w = ttystatus.Integer('foo') + def test_is_not_static_width(self): + self.assertFalse(self.w.static_width) + def test_is_error_initially(self): - self.assertEqual(self.w.render(), '#') + self.assertEqual(self.w.render(0), '#') def test_updates(self): self.w.update({'foo': 123}) - self.assertEqual(self.w.render(), '123') + self.assertEqual(self.w.render(0), '123') def test_becomes_error_symbol_if_value_is_not_integer(self): self.w.update({'foo': 'bar'}) - self.assertEqual(self.w.render(), '#') + self.assertEqual(self.w.render(0), '#') diff --git a/ttystatus/literal.py b/ttystatus/literal.py index fa09ceb..cdeb4d7 100644 --- a/ttystatus/literal.py +++ b/ttystatus/literal.py @@ -24,5 +24,5 @@ class Literal(ttystatus.Widget): def __init__(self, string): self.value = string - def render(self): + def render(self, width): return self.value diff --git a/ttystatus/literal_tests.py b/ttystatus/literal_tests.py index 73c8964..b1e4537 100644 --- a/ttystatus/literal_tests.py +++ b/ttystatus/literal_tests.py @@ -21,6 +21,11 @@ import ttystatus class LiteralTests(unittest.TestCase): + def setUp(self): + self.w = ttystatus.Literal('foo') + + def test_is_static_width(self): + self.assertTrue(self.w.static_width) + def test_sets_value_correctly(self): - literal = ttystatus.Literal('foo') - self.assertEqual(literal.render(), 'foo') + self.assertEqual(self.w.render(0), 'foo') diff --git a/ttystatus/pathname.py b/ttystatus/pathname.py index 0ecf4a7..bf5fe5a 100644 --- a/ttystatus/pathname.py +++ b/ttystatus/pathname.py @@ -24,12 +24,14 @@ class Pathname(ttystatus.Widget): If it won't fit completely, truncate from the beginning of the string. ''' + + static_width = False def __init__(self, key): self._key = key self.pathname = '' - def render(self): + def render(self, render): return self.pathname def update(self, master): diff --git a/ttystatus/pathname_tests.py b/ttystatus/pathname_tests.py index 7f09de0..1191f43 100644 --- a/ttystatus/pathname_tests.py +++ b/ttystatus/pathname_tests.py @@ -24,13 +24,16 @@ class PathnameTests(unittest.TestCase): def setUp(self): self.w = ttystatus.Pathname('foo') + def test_is_not_static_width(self): + self.assertFalse(self.w.static_width) + def test_is_empty_initially(self): - self.assertEqual(self.w.render(), '') + self.assertEqual(self.w.render(0), '') def test_updates(self): self.w.update({'foo': 'bar'}) - self.assertEqual(self.w.render(), 'bar') + self.assertEqual(self.w.render(0), 'bar') def test_handles_update_to_other_value(self): self.w.update({'other': 1}) - self.assertEqual(self.w.render(), '') + self.assertEqual(self.w.render(0), '') diff --git a/ttystatus/percent.py b/ttystatus/percent.py index 117fecc..1a60c23 100644 --- a/ttystatus/percent.py +++ b/ttystatus/percent.py @@ -20,6 +20,8 @@ import ttystatus class PercentDone(ttystatus.Widget): '''Display percent of task done.''' + + static_width = False def __init__(self, done_name, total_name, decimals=0): self.done_name = done_name @@ -28,7 +30,7 @@ class PercentDone(ttystatus.Widget): self.done = 0 self.total = 1 - def render(self): + def render(self, render): try: done = float(self.done) total = float(self.total) diff --git a/ttystatus/percent_tests.py b/ttystatus/percent_tests.py index c7d8d64..9ffe0b9 100644 --- a/ttystatus/percent_tests.py +++ b/ttystatus/percent_tests.py @@ -24,18 +24,21 @@ class PercentDoneTests(unittest.TestCase): def setUp(self): self.w = ttystatus.PercentDone('done', 'total', decimals=1) + def test_is_not_static_width(self): + self.assertFalse(self.w.static_width) + def test_shows_zero_value_initially(self): - self.assertEqual(self.w.render(), '0.0 %') + self.assertEqual(self.w.render(0), '0.0 %') def test_sets_value(self): self.w.update({ 'done': 50, 'total': 100 }) - self.assertEqual(self.w.render(), '50.0 %') + self.assertEqual(self.w.render(0), '50.0 %') def test_handles_empty_strings_as_values(self): self.w.update({ 'done': '', 'total': '' }) - self.assertEqual(self.w.render(), '0.0 %') + self.assertEqual(self.w.render(0), '0.0 %') def test_handles_zero_total(self): self.w.update({ 'done': 0, 'total': 0 }) - self.assertEqual(self.w.render(), '0.0 %') + self.assertEqual(self.w.render(0), '0.0 %') diff --git a/ttystatus/progressbar.py b/ttystatus/progressbar.py index 54ca99f..cd0f1a3 100644 --- a/ttystatus/progressbar.py +++ b/ttystatus/progressbar.py @@ -20,15 +20,16 @@ import ttystatus class ProgressBar(ttystatus.Widget): '''Display a progress bar.''' + + static_width = False - def __init__(self, done_name, total_name, width): + def __init__(self, done_name, total_name): self.done_name = done_name self.total_name = total_name self.done = 0 self.total = 1 - self.width = width - def render(self): + def render(self, width): try: done = float(self.done) total = float(self.total) @@ -39,8 +40,8 @@ class ProgressBar(ttystatus.Widget): fraction = 0 else: fraction = done / total - n_stars = int(round(fraction * self.width)) - n_dashes = int(self.width - n_stars) + n_stars = int(round(fraction * width)) + n_dashes = int(width - n_stars) return ('#' * n_stars) + ('-' * n_dashes) def update(self, master): diff --git a/ttystatus/progressbar_tests.py b/ttystatus/progressbar_tests.py index 8c7c261..a5dd425 100644 --- a/ttystatus/progressbar_tests.py +++ b/ttystatus/progressbar_tests.py @@ -22,40 +22,44 @@ import ttystatus class ProgressBarTests(unittest.TestCase): def setUp(self): - self.w = ttystatus.ProgressBar('done', 'total', 10) + self.w = ttystatus.ProgressBar('done', 'total') + self.width = 10 + + def test_is_not_static_width(self): + self.assertFalse(self.w.static_width) def test_sets_initial_value_to_empty(self): - self.assertEqual(self.w.render(), '-' * 10) + self.assertEqual(self.w.render(self.width), '-' * 10) def test_shows_zero_percent_for_empty_string_total(self): self.w.update({ 'done': 1, 'total': '' }) - self.assertEqual(self.w.render(), '-' * 10) + self.assertEqual(self.w.render(self.width), '-' * 10) def test_shows_zero_percent_for_zero_total(self): self.w.update({ 'done': 1, 'total': 0 }) - self.assertEqual(self.w.render(), '-' * 10) + self.assertEqual(self.w.render(self.width), '-' * 10) def test_shows_zero_percent_correctly(self): self.w.update({ 'done': 0, 'total': 100 }) - self.assertEqual(self.w.render(), '-' * 10) + self.assertEqual(self.w.render(self.width), '-' * 10) def test_shows_one_percent_correctly(self): self.w.update({ 'done': 1, 'total': 100 }) - self.assertEqual(self.w.render(), '-' * 10) + self.assertEqual(self.w.render(self.width), '-' * 10) def test_shows_ten_percent_correctly(self): self.w.update({ 'done': 10, 'total': 100 }) - self.assertEqual(self.w.render(), '#' + '-' * 9) + self.assertEqual(self.w.render(self.width), '#' + '-' * 9) def test_shows_ninety_percent_correctly(self): self.w.update({ 'done': 90, 'total': 100 }) - self.assertEqual(self.w.render(), '#' * 9 + '-') + self.assertEqual(self.w.render(self.width), '#' * 9 + '-') def test_shows_ninety_ine_percent_correctly(self): self.w.update({ 'done': 99, 'total': 100 }) - self.assertEqual(self.w.render(), '#' * 10) + self.assertEqual(self.w.render(self.width), '#' * 10) def test_shows_one_hundred_percent_correctly(self): self.w.update({ 'done': 100, 'total': 100 }) - self.assertEqual(self.w.render(), '#' * 10) + self.assertEqual(self.w.render(self.width), '#' * 10) diff --git a/ttystatus/remtime.py b/ttystatus/remtime.py index 50529e6..cbf55bd 100644 --- a/ttystatus/remtime.py +++ b/ttystatus/remtime.py @@ -41,7 +41,7 @@ class RemainingTime(ttystatus.Widget): return time.time() - def render(self): + def render(self, render): if self.started is None: self.started = self.get_time() duration = self.get_time() - self.started diff --git a/ttystatus/remtime_tests.py b/ttystatus/remtime_tests.py index df6bced..90afd42 100644 --- a/ttystatus/remtime_tests.py +++ b/ttystatus/remtime_tests.py @@ -25,31 +25,34 @@ class RemainingTimeTests(unittest.TestCase): self.w = ttystatus.RemainingTime('done', 'total') self.w.get_time = lambda: 0.0 + def test_is_static_width(self): + self.assertTrue(self.w.static_width) + def test_is_dashes_initially(self): - self.assertEqual(self.w.render(), '--h--m--s') + self.assertEqual(self.w.render(0), '--h--m--s') def test_estimates_and_formats_correctly(self): - self.assertEqual(self.w.render(), '--h--m--s') + self.assertEqual(self.w.render(0), '--h--m--s') self.w.update({ 'done': 0, 'total': 100 }) self.w.get_time = lambda: 5.0 self.w.update({ 'done': 5, 'total': 100 }) - self.assertEqual(self.w.render(), '00h01m35s') + self.assertEqual(self.w.render(0), '00h01m35s') self.w.get_time = lambda: 10.0 self.w.update({ 'done': 5, 'total': 100 }) - self.assertEqual(self.w.render(), '00h03m10s') + self.assertEqual(self.w.render(0), '00h03m10s') self.w.get_time = lambda: 20.0 self.w.update({ 'done': 80, 'total': 100 }) - self.assertEqual(self.w.render(), '00h00m05s') + self.assertEqual(self.w.render(0), '00h00m05s') def test_handles_zero_speed(self): self.w.update({ 'done': 0, 'total': 100 }) self.w.get_time = lambda: 5.0 self.w.update({ 'done': 0, 'total': 100 }) - self.assertEqual(self.w.render(), '--h--m--s') + self.assertEqual(self.w.render(0), '--h--m--s') def test_handles_empty_strings_for_done_and_total(self): self.w.update({ 'done': '', 'total': '' }) self.w.get_time = lambda: 5.0 self.w.update({ 'done': '', 'total': '' }) - self.assertEqual(self.w.render(), '--h--m--s') + self.assertEqual(self.w.render(0), '--h--m--s') diff --git a/ttystatus/status.py b/ttystatus/status.py index 526029b..8365017 100644 --- a/ttystatus/status.py +++ b/ttystatus/status.py @@ -76,7 +76,7 @@ class TerminalStatus(object): def _render(self): '''Format and output all widgets.''' - self._m.write(''.join(w.render() for w in self._widgets)) + self._m.write(''.join(w.render(1) for w in self._widgets)) def increase(self, key, delta): '''Increase value for a key by a given amount.''' diff --git a/ttystatus/status_tests.py b/ttystatus/status_tests.py index bb581f6..500cde2 100644 --- a/ttystatus/status_tests.py +++ b/ttystatus/status_tests.py @@ -94,9 +94,9 @@ class TerminalStatusTests(unittest.TestCase): def test_updates_widgets_when_value_is_set(self): w = ttystatus.String('foo') self.ts.add(w) - self.assertEqual(w.render(), '') + self.assertEqual(w.render(0), '') self.ts['foo'] = 'bar' - self.assertEqual(w.render(), 'bar') + self.assertEqual(w.render(0), 'bar') def test_increases_value(self): self.ts['foo'] = 10 @@ -128,5 +128,5 @@ class TerminalStatusTests(unittest.TestCase): self.ts.add(w) for i in range(n): self.ts['value'] = i - self.assertEqual(w.render(), str(n)) + self.assertEqual(w.render(0), str(n)) diff --git a/ttystatus/string.py b/ttystatus/string.py index 90fb48b..92fbf88 100644 --- a/ttystatus/string.py +++ b/ttystatus/string.py @@ -20,12 +20,14 @@ import ttystatus class String(ttystatus.Widget): '''Display a value as a string.''' + + static_width = False def __init__(self, key): self._key = key self.value = '' - def render(self): + def render(self, render): return str(self.value) def update(self, master): diff --git a/ttystatus/string_tests.py b/ttystatus/string_tests.py index b377f37..faa266b 100644 --- a/ttystatus/string_tests.py +++ b/ttystatus/string_tests.py @@ -24,13 +24,16 @@ class StringTests(unittest.TestCase): def setUp(self): self.s = ttystatus.String('foo') + def test_is_not_static_width(self): + self.assertFalse(self.s.static_width) + def test_is_empty_initially(self): - self.assertEqual(self.s.render(), '') + self.assertEqual(self.s.render(0), '') def test_updates(self): self.s.update({'foo': 'bar'}) - self.assertEqual(self.s.render(), 'bar') + self.assertEqual(self.s.render(0), 'bar') def test_handles_non_string_value(self): self.s.update({'foo': 123}) - self.assertEqual(self.s.render(), '123') + self.assertEqual(self.s.render(0), '123') diff --git a/ttystatus/widget.py b/ttystatus/widget.py index 9fccc29..9d14683 100644 --- a/ttystatus/widget.py +++ b/ttystatus/widget.py @@ -28,14 +28,29 @@ class Widget(object): any of the values change * the widget `render` method is called by TerminalStatus when it is time to display things + + Widgets may have a static size, or their size may vary. The + ``static_width`` property reveals this. This affects rendering: + static sized widgets are rendered at their one static size; variable + sized widgets are shrunk, if necessary, to make everything fit into + the available space. If it's not possible to shrink enough, widgets + are rendered from beginning until the space is full: variable sized + widgets are rendered as small as possible in this case. ''' + static_width = True + def __str__(self): raise NotImplementedError() - def render(self): + def render(self, width): '''Format the current value. + + ``width`` is the available width for the widget. It need not use + all of it. If it's not possible for the widget to render itself + small enough to fit into the given width, it may return a larger + string, but the caller will probably truncate it. This will be called only when the value actually needs to be formatted. -- cgit v1.2.1 From 8620de40bf5d5a223acc37d5cc9ed55aa022314c Mon Sep 17 00:00:00 2001 From: Lars Wirzenius Date: Sun, 15 Apr 2012 19:19:53 +0100 Subject: Fix rendering to adjust to available space --- ttystatus/status.py | 29 ++++++++++++++++++++++++----- ttystatus/status_tests.py | 8 ++++++++ 2 files changed, 32 insertions(+), 5 deletions(-) diff --git a/ttystatus/status.py b/ttystatus/status.py index 8365017..b0b93dd 100644 --- a/ttystatus/status.py +++ b/ttystatus/status.py @@ -72,12 +72,31 @@ class TerminalStatus(object): for w in self._widgets: w.update(self) if self._m.time_to_write(): - self._render() + self._write() def _render(self): - '''Format and output all widgets.''' - self._m.write(''.join(w.render(1) for w in self._widgets)) - + '''Render current state of all widgets.''' + + remaining = self._m.width + + texts = [None] * len(self._widgets) + + for i, w in enumerate(self._widgets): + if w.static_width: + texts[i] = w.render(0) + remaining -= len(texts[i]) + + for i, w in enumerate(self._widgets): + if not w.static_width: + texts[i] = w.render(remaining) + remaining -= len(texts[i]) + + return ''.join(texts) + + def _write(self): + '''Render and output current state of all widgets.''' + self._m.write(self._render()) + def increase(self, key, delta): '''Increase value for a key by a given amount.''' self[key] = (self[key] or 0) + delta @@ -92,7 +111,7 @@ class TerminalStatus(object): def finish(self): '''Finish status display.''' - self._render() + self._write() self._m.finish() def disable(self): diff --git a/ttystatus/status_tests.py b/ttystatus/status_tests.py index 500cde2..aa8c021 100644 --- a/ttystatus/status_tests.py +++ b/ttystatus/status_tests.py @@ -130,3 +130,11 @@ class TerminalStatusTests(unittest.TestCase): self.ts['value'] = i self.assertEqual(w.render(0), str(n)) + def test_renders_everything_when_there_is_space(self): + w1 = ttystatus.Literal('foo') + w2 = ttystatus.ProgressBar('done', 'total') + self.ts.add(w1) + self.ts.add(w2) + text = self.ts._render() + self.assertEqual(len(text), self.ts._m.width) + -- cgit v1.2.1 From 6204db8f52e77fd18dd681b65452ef2103dfa688 Mon Sep 17 00:00:00 2001 From: Lars Wirzenius Date: Sun, 15 Apr 2012 19:20:12 +0100 Subject: Fix example to create ProgressBar correctly (again) Undoing previous change, yay. --- example.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/example.py b/example.py index 9401704..5814fbc 100644 --- a/example.py +++ b/example.py @@ -47,7 +47,7 @@ def main(): ts.add(ttystatus.Literal(' done) ')) ts.add(ttystatus.RemainingTime('done', 'total')) ts.add(ttystatus.Literal(' ')) - ts.add(ttystatus.ProgressBar('done', 'total', 16)) + ts.add(ttystatus.ProgressBar('done', 'total')) ts['pathnames'] = pathnames ts['done'] = 0 ts['total'] = len(pathnames) -- cgit v1.2.1 From 82d2b7b8950a43f2055353ad9259cad6506b142e Mon Sep 17 00:00:00 2001 From: Lars Wirzenius Date: Sun, 15 Apr 2012 19:22:25 +0100 Subject: Limit rendered text to available width --- ttystatus/status.py | 2 +- ttystatus/status_tests.py | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/ttystatus/status.py b/ttystatus/status.py index b0b93dd..b98fecd 100644 --- a/ttystatus/status.py +++ b/ttystatus/status.py @@ -91,7 +91,7 @@ class TerminalStatus(object): texts[i] = w.render(remaining) remaining -= len(texts[i]) - return ''.join(texts) + return (''.join(texts))[:self._m.width] def _write(self): '''Render and output current state of all widgets.''' diff --git a/ttystatus/status_tests.py b/ttystatus/status_tests.py index aa8c021..ab27ca9 100644 --- a/ttystatus/status_tests.py +++ b/ttystatus/status_tests.py @@ -138,3 +138,12 @@ class TerminalStatusTests(unittest.TestCase): text = self.ts._render() self.assertEqual(len(text), self.ts._m.width) + def test_renders_from_beginning_if_there_is_not_enough_space(self): + w1 = ttystatus.Literal('foo') + w2 = ttystatus.Literal('bar') + self.ts.add(w1) + self.ts.add(w2) + self.ts._m.width = 4 + text = self.ts._render() + self.assertEqual(text, 'foob') + -- cgit v1.2.1 From 88d494d0045df84f89a01be8c7df2c195635a057 Mon Sep 17 00:00:00 2001 From: Lars Wirzenius Date: Sun, 15 Apr 2012 19:23:44 +0100 Subject: Add test for rendering variable size widgets smaller if space is constrained --- ttystatus/status_tests.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/ttystatus/status_tests.py b/ttystatus/status_tests.py index ab27ca9..ef8959a 100644 --- a/ttystatus/status_tests.py +++ b/ttystatus/status_tests.py @@ -147,3 +147,14 @@ class TerminalStatusTests(unittest.TestCase): text = self.ts._render() self.assertEqual(text, 'foob') + def test_renders_variable_size_width_according_to_space_keep_static(self): + w1 = ttystatus.Literal('foo') + w2 = ttystatus.ProgressBar('done', 'total') + w3 = ttystatus.Literal('bar') + self.ts.add(w1) + self.ts.add(w2) + self.ts.add(w3) + self.ts._m.width = 9 + text = self.ts._render() + self.assertEqual(text, 'foo---bar') + -- cgit v1.2.1 From 194fa11664ce1aff4c14097fe1e733c19873d8b2 Mon Sep 17 00:00:00 2001 From: Lars Wirzenius Date: Sun, 15 Apr 2012 19:25:31 +0100 Subject: Fix Pathname to render from end instead of beginning --- ttystatus/pathname.py | 4 ++-- ttystatus/pathname_tests.py | 11 ++++++++--- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/ttystatus/pathname.py b/ttystatus/pathname.py index bf5fe5a..0fbdbd7 100644 --- a/ttystatus/pathname.py +++ b/ttystatus/pathname.py @@ -31,8 +31,8 @@ class Pathname(ttystatus.Widget): self._key = key self.pathname = '' - def render(self, render): - return self.pathname + def render(self, width): + return self.pathname[-width:] def update(self, master): self.pathname = master.get(self._key, '') diff --git a/ttystatus/pathname_tests.py b/ttystatus/pathname_tests.py index 1191f43..70d6c1e 100644 --- a/ttystatus/pathname_tests.py +++ b/ttystatus/pathname_tests.py @@ -28,12 +28,17 @@ class PathnameTests(unittest.TestCase): self.assertFalse(self.w.static_width) def test_is_empty_initially(self): - self.assertEqual(self.w.render(0), '') + self.assertEqual(self.w.render(10), '') def test_updates(self): self.w.update({'foo': 'bar'}) - self.assertEqual(self.w.render(0), 'bar') + self.assertEqual(self.w.render(10), 'bar') def test_handles_update_to_other_value(self): self.w.update({'other': 1}) - self.assertEqual(self.w.render(0), '') + self.assertEqual(self.w.render(10), '') + + def test_truncates_from_beginning(self): + self.w.update({'foo': '/this/is/a/path'}) + self.assertEqual(self.w.render(6), 'a/path') + -- cgit v1.2.1 From 1a4675e03b42fcf276cf6a160480010cb36ca88c Mon Sep 17 00:00:00 2001 From: Lars Wirzenius Date: Sun, 15 Apr 2012 19:28:02 +0100 Subject: Update NEWS --- NEWS | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/NEWS b/NEWS index 31f8482..63dcdb9 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,11 @@ NEWS file for ttystatus ======================= +Version 0.17, released UNRELEASED +--------------------------------- + +* Committed genocide towards whole civilizations of rendering problems. + Version 0.16, released 2012-04-08 --------------------------------- -- cgit v1.2.1