diff --git a/progress/__init__.py b/progress/__init__.py index 827b0cd..122406f 100644 --- a/progress/__init__.py +++ b/progress/__init__.py @@ -12,7 +12,7 @@ # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -from __future__ import division +from __future__ import division, print_function from collections import deque from datetime import timedelta @@ -23,12 +23,17 @@ from time import time __version__ = '1.4' +HIDE_CURSOR = '\x1b[?25l' +SHOW_CURSOR = '\x1b[?25h' + class Infinite(object): file = stderr sma_window = 10 # Simple Moving Average window + check_tty = True + hide_cursor = True - def __init__(self, *args, **kwargs): + def __init__(self, message='', **kwargs): self.index = 0 self.start_ts = time() self.avg = 0 @@ -37,6 +42,15 @@ class Infinite(object): for key, val in kwargs.items(): setattr(self, key, val) + self._width = 0 + self.message = message + + if self.file and self.is_tty(): + if self.hide_cursor: + print(HIDE_CURSOR, end='', file=self.file) + print(self.message, end='', file=self.file) + self.file.flush() + def __getitem__(self, key): if key.startswith('_'): return None @@ -61,8 +75,31 @@ class Infinite(object): def start(self): pass + def clearln(self): + if self.file and self.is_tty(): + print('\r\x1b[K', end='', file=self.file) + + def write(self, s): + if self.file and self.is_tty(): + line = self.message + s.ljust(self._width) + print('\r' + line, end='', file=self.file) + self._width = max(self._width, len(s)) + self.file.flush() + + def writeln(self, line): + if self.file and self.is_tty(): + self.clearln() + print(line, end='', file=self.file) + self.file.flush() + def finish(self): - pass + if self.file and self.is_tty(): + print(file=self.file) + if self.hide_cursor: + print(SHOW_CURSOR, end='', file=self.file) + + def is_tty(self): + return self.file.isatty() if self.check_tty else True def next(self, n=1): now = time() diff --git a/progress/bar.py b/progress/bar.py index 025e61c..8819efd 100644 --- a/progress/bar.py +++ b/progress/bar.py @@ -19,18 +19,15 @@ from __future__ import unicode_literals import sys from . import Progress -from .helpers import WritelnMixin -class Bar(WritelnMixin, Progress): +class Bar(Progress): width = 32 - message = '' suffix = '%(index)d/%(max)d' bar_prefix = ' |' bar_suffix = '| ' empty_fill = ' ' fill = '#' - hide_cursor = True def update(self): filled_length = int(self.width * self.progress) diff --git a/progress/counter.py b/progress/counter.py index 6b45a1e..d955ca4 100644 --- a/progress/counter.py +++ b/progress/counter.py @@ -16,27 +16,20 @@ from __future__ import unicode_literals from . import Infinite, Progress -from .helpers import WriteMixin -class Counter(WriteMixin, Infinite): - message = '' - hide_cursor = True - +class Counter(Infinite): def update(self): self.write(str(self.index)) -class Countdown(WriteMixin, Progress): - hide_cursor = True - +class Countdown(Progress): def update(self): self.write(str(self.remaining)) -class Stack(WriteMixin, Progress): +class Stack(Progress): phases = (' ', '▁', '▂', '▃', '▄', '▅', '▆', '▇', '█') - hide_cursor = True def update(self): nphases = len(self.phases) diff --git a/progress/helpers.py b/progress/helpers.py index 530927e..af9e083 100644 --- a/progress/helpers.py +++ b/progress/helpers.py @@ -12,76 +12,6 @@ # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -from __future__ import print_function - - -HIDE_CURSOR = '\x1b[?25l' -SHOW_CURSOR = '\x1b[?25h' - - -class WriteMixin(object): - check_tty = True - hide_cursor = False - - def __init__(self, message=None, **kwargs): - super(WriteMixin, self).__init__(**kwargs) - self._width = 0 - if message: - self.message = message - - if self.file and self.is_tty(): - if self.hide_cursor: - print(HIDE_CURSOR, end='', file=self.file) - print(self.message, end='', file=self.file) - self.file.flush() - - def write(self, s): - if self.file and self.is_tty(): - line = self.message + s.ljust(self._width) - print('\r' + line, end='', file=self.file) - self._width = max(self._width, len(s)) - self.file.flush() - - def finish(self): - if self.file and self.is_tty() and self.hide_cursor: - print(SHOW_CURSOR, end='', file=self.file) - - def is_tty(self): - return self.file.isatty() if self.check_tty else True - - -class WritelnMixin(object): - check_tty = True - hide_cursor = False - - def __init__(self, message=None, **kwargs): - super(WritelnMixin, self).__init__(**kwargs) - if message: - self.message = message - - if self.file and self.is_tty() and self.hide_cursor: - print(HIDE_CURSOR, end='', file=self.file) - - def clearln(self): - if self.file and self.is_tty(): - print('\r\x1b[K', end='', file=self.file) - - def writeln(self, line): - if self.file and self.is_tty(): - self.clearln() - print(line, end='', file=self.file) - self.file.flush() - - def finish(self): - if self.file and self.is_tty(): - print(file=self.file) - if self.hide_cursor: - print(SHOW_CURSOR, end='', file=self.file) - - def is_tty(self): - return self.file.isatty() if self.check_tty else True - - from signal import signal, SIGINT from sys import exit diff --git a/progress/spinner.py b/progress/spinner.py index 464c7b2..4e100ca 100644 --- a/progress/spinner.py +++ b/progress/spinner.py @@ -16,11 +16,9 @@ from __future__ import unicode_literals from . import Infinite -from .helpers import WriteMixin -class Spinner(WriteMixin, Infinite): - message = '' +class Spinner(Infinite): phases = ('-', '\\', '|', '/') hide_cursor = True @@ -40,5 +38,6 @@ class MoonSpinner(Spinner): class LineSpinner(Spinner): phases = ['⎺', '⎻', '⎼', '⎽', '⎼', '⎻'] + class PixelSpinner(Spinner): - phases = ['⣾','⣷', '⣯', '⣟', '⡿', '⢿', '⣻', '⣽'] + phases = ['⣾', '⣷', '⣯', '⣟', '⡿', '⢿', '⣻', '⣽'] diff --git a/test_progress.py b/test_progress.py index 5064190..356efd3 100755 --- a/test_progress.py +++ b/test_progress.py @@ -35,12 +35,10 @@ for bar_cls in (IncrementalBar, PixelBar, ShadyBar): for spin in (Spinner, PieSpinner, MoonSpinner, LineSpinner, PixelSpinner): for i in spin(spin.__name__ + ' ').iter(range(100)): sleep() - print() for singleton in (Counter, Countdown, Stack, Pie): for i in singleton(singleton.__name__ + ' ').iter(range(100)): sleep() - print() bar = IncrementalBar('Random', suffix='%(index)d') for i in range(100):