././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1751348015.6533575 progress-1.6.1/0000755000076500000240000000000015030671460012740 5ustar00verigakstaff././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1595248832.0 progress-1.6.1/LICENSE0000644000076500000240000000141113705310300013730 0ustar00verigakstaff# Copyright (c) 2012 Georgios Verigakis # # Permission to use, copy, modify, and distribute this software for any # purpose with or without fee is hereby granted, provided that the above # copyright notice and this permission notice appear in all copies. # # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1751348015.6530194 progress-1.6.1/PKG-INFO0000644000076500000240000001036515030671460014042 0ustar00verigakstaffMetadata-Version: 2.4 Name: progress Version: 1.6.1 Summary: Easy to use progress bars Author-email: Georgios Verigakis Maintainer-email: Georgios Verigakis License-Expression: ISC Project-URL: Homepage, https://github.com/verigak/progress/ Project-URL: Repository, https://github.com/verigak/progress.git Project-URL: Issues, https://github.com/verigak/progress/issues Keywords: progress,bar Classifier: Environment :: Console Classifier: Intended Audience :: Developers Classifier: Programming Language :: Python :: 3.6 Classifier: Programming Language :: Python :: 3.7 Classifier: Programming Language :: Python :: 3.8 Classifier: Programming Language :: Python :: 3.9 Classifier: Programming Language :: Python :: 3.10 Classifier: Programming Language :: Python :: 3.11 Classifier: Programming Language :: Python :: 3.12 Classifier: Programming Language :: Python :: 3.13 Requires-Python: >=3.6 Description-Content-Type: text/x-rst License-File: LICENSE Dynamic: license-file Easy progress reporting for Python ================================== |pypi| |demo| .. |pypi| image:: https://img.shields.io/pypi/v/progress.svg :target: https://pypi.org/project/progress/ .. |demo| image:: https://raw.github.com/verigak/progress/master/demo.gif :alt: Demo Bars ---- There are 7 progress bars to choose from: - ``Bar`` - ``ChargingBar`` - ``FillingSquaresBar`` - ``FillingCirclesBar`` - ``IncrementalBar`` - ``PixelBar`` - ``ShadyBar`` To use them, just call ``next`` to advance and ``finish`` to finish: .. code-block:: python from progress.bar import Bar bar = Bar('Processing', max=20) for i in range(20): # Do some work bar.next() bar.finish() or use any bar of this class as a context manager: .. code-block:: python from progress.bar import Bar with Bar('Processing', max=20) as bar: for i in range(20): # Do some work bar.next() The result will be a bar like the following: :: Processing |############# | 42/100 To simplify the common case where the work is done in an iterator, you can use the ``iter`` method: .. code-block:: python for i in Bar('Processing').iter(it): # Do some work Progress bars are very customizable, you can change their width, their fill character, their suffix and more: .. code-block:: python bar = Bar('Loading', fill='@', suffix='%(percent)d%%') This will produce a bar like the following: :: Loading |@@@@@@@@@@@@@ | 42% You can use a number of template arguments in ``message`` and ``suffix``: ========== ================================ Name Value ========== ================================ index current value max maximum value remaining max - index progress index / max percent progress * 100 avg simple moving average time per item (in seconds) elapsed elapsed time in seconds elapsed_td elapsed as a timedelta (useful for printing as a string) eta avg * remaining eta_td eta as a timedelta (useful for printing as a string) ========== ================================ Instead of passing all configuration options on instantiation, you can create your custom subclass: .. code-block:: python class FancyBar(Bar): message = 'Loading' fill = '*' suffix = '%(percent).1f%% - %(eta)ds' You can also override any of the arguments or create your own: .. code-block:: python class SlowBar(Bar): suffix = '%(remaining_hours)d hours remaining' @property def remaining_hours(self): return self.eta // 3600 Spinners ======== For actions with an unknown number of steps you can use a spinner: .. code-block:: python from progress.spinner import Spinner spinner = Spinner('Loading ') while state != 'FINISHED': # Do some work spinner.next() There are 5 predefined spinners: - ``Spinner`` - ``PieSpinner`` - ``MoonSpinner`` - ``LineSpinner`` - ``PixelSpinner`` Installation ============ Download from PyPi .. code-block:: shell pip install progress Other ===== There are a number of other classes available too, please check the source or subclass one of them to create your own. License ======= progress is licensed under ISC ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1751347616.0 progress-1.6.1/README.rst0000644000076500000240000000637015030670640014434 0ustar00verigakstaffEasy progress reporting for Python ================================== |pypi| |demo| .. |pypi| image:: https://img.shields.io/pypi/v/progress.svg :target: https://pypi.org/project/progress/ .. |demo| image:: https://raw.github.com/verigak/progress/master/demo.gif :alt: Demo Bars ---- There are 7 progress bars to choose from: - ``Bar`` - ``ChargingBar`` - ``FillingSquaresBar`` - ``FillingCirclesBar`` - ``IncrementalBar`` - ``PixelBar`` - ``ShadyBar`` To use them, just call ``next`` to advance and ``finish`` to finish: .. code-block:: python from progress.bar import Bar bar = Bar('Processing', max=20) for i in range(20): # Do some work bar.next() bar.finish() or use any bar of this class as a context manager: .. code-block:: python from progress.bar import Bar with Bar('Processing', max=20) as bar: for i in range(20): # Do some work bar.next() The result will be a bar like the following: :: Processing |############# | 42/100 To simplify the common case where the work is done in an iterator, you can use the ``iter`` method: .. code-block:: python for i in Bar('Processing').iter(it): # Do some work Progress bars are very customizable, you can change their width, their fill character, their suffix and more: .. code-block:: python bar = Bar('Loading', fill='@', suffix='%(percent)d%%') This will produce a bar like the following: :: Loading |@@@@@@@@@@@@@ | 42% You can use a number of template arguments in ``message`` and ``suffix``: ========== ================================ Name Value ========== ================================ index current value max maximum value remaining max - index progress index / max percent progress * 100 avg simple moving average time per item (in seconds) elapsed elapsed time in seconds elapsed_td elapsed as a timedelta (useful for printing as a string) eta avg * remaining eta_td eta as a timedelta (useful for printing as a string) ========== ================================ Instead of passing all configuration options on instantiation, you can create your custom subclass: .. code-block:: python class FancyBar(Bar): message = 'Loading' fill = '*' suffix = '%(percent).1f%% - %(eta)ds' You can also override any of the arguments or create your own: .. code-block:: python class SlowBar(Bar): suffix = '%(remaining_hours)d hours remaining' @property def remaining_hours(self): return self.eta // 3600 Spinners ======== For actions with an unknown number of steps you can use a spinner: .. code-block:: python from progress.spinner import Spinner spinner = Spinner('Loading ') while state != 'FINISHED': # Do some work spinner.next() There are 5 predefined spinners: - ``Spinner`` - ``PieSpinner`` - ``MoonSpinner`` - ``LineSpinner`` - ``PixelSpinner`` Installation ============ Download from PyPi .. code-block:: shell pip install progress Other ===== There are a number of other classes available too, please check the source or subclass one of them to create your own. License ======= progress is licensed under ISC ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1751348015.6510699 progress-1.6.1/progress/0000755000076500000240000000000015030671460014604 5ustar00verigakstaff././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1751347616.0 progress-1.6.1/progress/__init__.py0000644000076500000240000001226015030670640016715 0ustar00verigakstaff# Copyright (c) 2012 Georgios Verigakis # # Permission to use, copy, modify, and distribute this software for any # purpose with or without fee is hereby granted, provided that the above # copyright notice and this permission notice appear in all copies. # # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN # 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, print_function from collections import deque from datetime import timedelta from math import ceil from sys import stderr try: from time import monotonic except ImportError: from time import time as monotonic __version__ = '1.6.1' 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, message='', **kwargs): self.index = 0 self.start_ts = monotonic() self.avg = 0 self._avg_update_ts = self.start_ts self._ts = self.start_ts self._xput = deque(maxlen=self.sma_window) for key, val in kwargs.items(): setattr(self, key, val) self._max_width = 0 self._hidden_cursor = False self.message = message if self.file and self.is_tty(): if self.hide_cursor: print(HIDE_CURSOR, end='', file=self.file) self._hidden_cursor = True self.writeln('') def __del__(self): if self._hidden_cursor: print(SHOW_CURSOR, end='', file=self.file) def __getitem__(self, key): if key.startswith('_'): return None return getattr(self, key, None) @property def elapsed(self): return int(monotonic() - self.start_ts) @property def elapsed_td(self): return timedelta(seconds=self.elapsed) def update_avg(self, n, dt): if n > 0: xput_len = len(self._xput) self._xput.append(dt / n) now = monotonic() # update when we're still filling _xput, then after every second if (xput_len < self.sma_window or now - self._avg_update_ts > 1): self.avg = sum(self._xput) / len(self._xput) self._avg_update_ts = now def update(self): pass def start(self): pass def writeln(self, line): if self.file and self.is_tty(): width = len(line) if width < self._max_width: # Add padding to cover previous contents line += ' ' * (self._max_width - width) else: self._max_width = width print('\r' + line, end='', file=self.file) self.file.flush() def finish(self): if self.file and self.is_tty(): print(file=self.file) if self._hidden_cursor: print(SHOW_CURSOR, end='', file=self.file) self._hidden_cursor = False def is_tty(self): try: return self.file.isatty() if self.check_tty else True except AttributeError: msg = "%s has no attribute 'isatty'. Try setting check_tty=False." % self raise AttributeError(msg) def next(self, n=1): now = monotonic() dt = now - self._ts self.update_avg(n, dt) self._ts = now self.index = self.index + n self.update() def iter(self, it): self.iter_value = None with self: for x in it: self.iter_value = x yield x self.next() del self.iter_value def __enter__(self): self.start() return self def __exit__(self, exc_type, exc_val, exc_tb): self.finish() class Progress(Infinite): def __init__(self, *args, **kwargs): super(Progress, self).__init__(*args, **kwargs) self.max = kwargs.get('max', 100) @property def eta(self): return int(ceil(self.avg * self.remaining)) @property def eta_td(self): return timedelta(seconds=self.eta) @property def percent(self): return self.progress * 100 @property def progress(self): if self.max == 0: return 0 return min(1, self.index / self.max) @property def remaining(self): return max(self.max - self.index, 0) def start(self): self.update() def goto(self, index): incr = index - self.index self.next(incr) def iter(self, it): try: self.max = len(it) except TypeError: pass self.iter_value = None with self: for x in it: self.iter_value = x yield x self.next() del self.iter_value ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1595248798.0 progress-1.6.1/progress/bar.py0000644000076500000240000000557613705310236015735 0ustar00verigakstaff# -*- coding: utf-8 -*- # Copyright (c) 2012 Georgios Verigakis # # Permission to use, copy, modify, and distribute this software for any # purpose with or without fee is hereby granted, provided that the above # copyright notice and this permission notice appear in all copies. # # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN # 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 unicode_literals import sys from . import Progress from .colors import color class Bar(Progress): width = 32 suffix = '%(index)d/%(max)d' bar_prefix = ' |' bar_suffix = '| ' empty_fill = ' ' fill = '#' color = None def update(self): filled_length = int(self.width * self.progress) empty_length = self.width - filled_length message = self.message % self bar = color(self.fill * filled_length, fg=self.color) empty = self.empty_fill * empty_length suffix = self.suffix % self line = ''.join([message, self.bar_prefix, bar, empty, self.bar_suffix, suffix]) self.writeln(line) class ChargingBar(Bar): suffix = '%(percent)d%%' bar_prefix = ' ' bar_suffix = ' ' empty_fill = '∙' fill = '█' class FillingSquaresBar(ChargingBar): empty_fill = '▢' fill = '▣' class FillingCirclesBar(ChargingBar): empty_fill = '◯' fill = '◉' class IncrementalBar(Bar): if sys.platform.startswith('win'): phases = (u' ', u'▌', u'█') else: phases = (' ', '▏', '▎', '▍', '▌', '▋', '▊', '▉', '█') def update(self): nphases = len(self.phases) filled_len = self.width * self.progress nfull = int(filled_len) # Number of full chars phase = int((filled_len - nfull) * nphases) # Phase of last char nempty = self.width - nfull # Number of empty chars message = self.message % self bar = color(self.phases[-1] * nfull, fg=self.color) current = self.phases[phase] if phase > 0 else '' empty = self.empty_fill * max(0, nempty - len(current)) suffix = self.suffix % self line = ''.join([message, self.bar_prefix, bar, current, empty, self.bar_suffix, suffix]) self.writeln(line) class PixelBar(IncrementalBar): phases = ('⡀', '⡄', '⡆', '⡇', '⣇', '⣧', '⣷', '⣿') class ShadyBar(IncrementalBar): phases = (' ', '░', '▒', '▓', '█') ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1595248281.0 progress-1.6.1/progress/colors.py0000644000076500000240000000513713705307231016464 0ustar00verigakstaff# -*- coding: utf-8 -*- # Copyright (c) 2020 Georgios Verigakis # # Permission to use, copy, modify, and distribute this software for any # purpose with or without fee is hereby granted, provided that the above # copyright notice and this permission notice appear in all copies. # # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. from functools import partial COLORS = ('black', 'red', 'green', 'yellow', 'blue', 'magenta', 'cyan', 'white') STYLES = ('bold', 'faint', 'italic', 'underline', 'blink', 'blink2', 'negative', 'concealed', 'crossed') def color(s, fg=None, bg=None, style=None): sgr = [] if fg: if fg in COLORS: sgr.append(str(30 + COLORS.index(fg))) elif isinstance(fg, int) and 0 <= fg <= 255: sgr.append('38;5;%d' % int(fg)) else: raise Exception('Invalid color "%s"' % fg) if bg: if bg in COLORS: sgr.append(str(40 + COLORS.index(bg))) elif isinstance(bg, int) and 0 <= bg <= 255: sgr.append('48;5;%d' % bg) else: raise Exception('Invalid color "%s"' % bg) if style: for st in style.split('+'): if st in STYLES: sgr.append(str(1 + STYLES.index(st))) else: raise Exception('Invalid style "%s"' % st) if sgr: prefix = '\x1b[' + ';'.join(sgr) + 'm' suffix = '\x1b[0m' return prefix + s + suffix else: return s # Foreground shortcuts black = partial(color, fg='black') red = partial(color, fg='red') green = partial(color, fg='green') yellow = partial(color, fg='yellow') blue = partial(color, fg='blue') magenta = partial(color, fg='magenta') cyan = partial(color, fg='cyan') white = partial(color, fg='white') # Style shortcuts bold = partial(color, style='bold') faint = partial(color, style='faint') italic = partial(color, style='italic') underline = partial(color, style='underline') blink = partial(color, style='blink') blink2 = partial(color, style='blink2') negative = partial(color, style='negative') concealed = partial(color, style='concealed') crossed = partial(color, style='crossed') ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1595248804.0 progress-1.6.1/progress/counter.py0000644000076500000240000000311513705310244016632 0ustar00verigakstaff# -*- coding: utf-8 -*- # Copyright (c) 2012 Georgios Verigakis # # Permission to use, copy, modify, and distribute this software for any # purpose with or without fee is hereby granted, provided that the above # copyright notice and this permission notice appear in all copies. # # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN # 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 unicode_literals from . import Infinite, Progress class Counter(Infinite): def update(self): message = self.message % self line = ''.join([message, str(self.index)]) self.writeln(line) class Countdown(Progress): def update(self): message = self.message % self line = ''.join([message, str(self.remaining)]) self.writeln(line) class Stack(Progress): phases = (' ', '▁', '▂', '▃', '▄', '▅', '▆', '▇', '█') def update(self): nphases = len(self.phases) i = min(nphases - 1, int(self.progress * nphases)) message = self.message % self line = ''.join([message, self.phases[i]]) self.writeln(line) class Pie(Stack): phases = ('○', '◔', '◑', '◕', '●') ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1595248807.0 progress-1.6.1/progress/spinner.py0000644000076500000240000000266513705310247016645 0ustar00verigakstaff# -*- coding: utf-8 -*- # Copyright (c) 2012 Georgios Verigakis # # Permission to use, copy, modify, and distribute this software for any # purpose with or without fee is hereby granted, provided that the above # copyright notice and this permission notice appear in all copies. # # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN # 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 unicode_literals from . import Infinite class Spinner(Infinite): phases = ('-', '\\', '|', '/') hide_cursor = True def update(self): i = self.index % len(self.phases) message = self.message % self line = ''.join([message, self.phases[i]]) self.writeln(line) class PieSpinner(Spinner): phases = ['◷', '◶', '◵', '◴'] class MoonSpinner(Spinner): phases = ['◑', '◒', '◐', '◓'] class LineSpinner(Spinner): phases = ['⎺', '⎻', '⎼', '⎽', '⎼', '⎻'] class PixelSpinner(Spinner): phases = ['⣾', '⣷', '⣯', '⣟', '⡿', '⢿', '⣻', '⣽'] ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1751348015.6526184 progress-1.6.1/progress.egg-info/0000755000076500000240000000000015030671460016276 5ustar00verigakstaff././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1751348015.0 progress-1.6.1/progress.egg-info/PKG-INFO0000644000076500000240000001036515030671457017406 0ustar00verigakstaffMetadata-Version: 2.4 Name: progress Version: 1.6.1 Summary: Easy to use progress bars Author-email: Georgios Verigakis Maintainer-email: Georgios Verigakis License-Expression: ISC Project-URL: Homepage, https://github.com/verigak/progress/ Project-URL: Repository, https://github.com/verigak/progress.git Project-URL: Issues, https://github.com/verigak/progress/issues Keywords: progress,bar Classifier: Environment :: Console Classifier: Intended Audience :: Developers Classifier: Programming Language :: Python :: 3.6 Classifier: Programming Language :: Python :: 3.7 Classifier: Programming Language :: Python :: 3.8 Classifier: Programming Language :: Python :: 3.9 Classifier: Programming Language :: Python :: 3.10 Classifier: Programming Language :: Python :: 3.11 Classifier: Programming Language :: Python :: 3.12 Classifier: Programming Language :: Python :: 3.13 Requires-Python: >=3.6 Description-Content-Type: text/x-rst License-File: LICENSE Dynamic: license-file Easy progress reporting for Python ================================== |pypi| |demo| .. |pypi| image:: https://img.shields.io/pypi/v/progress.svg :target: https://pypi.org/project/progress/ .. |demo| image:: https://raw.github.com/verigak/progress/master/demo.gif :alt: Demo Bars ---- There are 7 progress bars to choose from: - ``Bar`` - ``ChargingBar`` - ``FillingSquaresBar`` - ``FillingCirclesBar`` - ``IncrementalBar`` - ``PixelBar`` - ``ShadyBar`` To use them, just call ``next`` to advance and ``finish`` to finish: .. code-block:: python from progress.bar import Bar bar = Bar('Processing', max=20) for i in range(20): # Do some work bar.next() bar.finish() or use any bar of this class as a context manager: .. code-block:: python from progress.bar import Bar with Bar('Processing', max=20) as bar: for i in range(20): # Do some work bar.next() The result will be a bar like the following: :: Processing |############# | 42/100 To simplify the common case where the work is done in an iterator, you can use the ``iter`` method: .. code-block:: python for i in Bar('Processing').iter(it): # Do some work Progress bars are very customizable, you can change their width, their fill character, their suffix and more: .. code-block:: python bar = Bar('Loading', fill='@', suffix='%(percent)d%%') This will produce a bar like the following: :: Loading |@@@@@@@@@@@@@ | 42% You can use a number of template arguments in ``message`` and ``suffix``: ========== ================================ Name Value ========== ================================ index current value max maximum value remaining max - index progress index / max percent progress * 100 avg simple moving average time per item (in seconds) elapsed elapsed time in seconds elapsed_td elapsed as a timedelta (useful for printing as a string) eta avg * remaining eta_td eta as a timedelta (useful for printing as a string) ========== ================================ Instead of passing all configuration options on instantiation, you can create your custom subclass: .. code-block:: python class FancyBar(Bar): message = 'Loading' fill = '*' suffix = '%(percent).1f%% - %(eta)ds' You can also override any of the arguments or create your own: .. code-block:: python class SlowBar(Bar): suffix = '%(remaining_hours)d hours remaining' @property def remaining_hours(self): return self.eta // 3600 Spinners ======== For actions with an unknown number of steps you can use a spinner: .. code-block:: python from progress.spinner import Spinner spinner = Spinner('Loading ') while state != 'FINISHED': # Do some work spinner.next() There are 5 predefined spinners: - ``Spinner`` - ``PieSpinner`` - ``MoonSpinner`` - ``LineSpinner`` - ``PixelSpinner`` Installation ============ Download from PyPi .. code-block:: shell pip install progress Other ===== There are a number of other classes available too, please check the source or subclass one of them to create your own. License ======= progress is licensed under ISC ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1751348015.0 progress-1.6.1/progress.egg-info/SOURCES.txt0000644000076500000240000000042215030671457020166 0ustar00verigakstaffLICENSE README.rst pyproject.toml test_progress.py progress/__init__.py progress/bar.py progress/colors.py progress/counter.py progress/spinner.py progress.egg-info/PKG-INFO progress.egg-info/SOURCES.txt progress.egg-info/dependency_links.txt progress.egg-info/top_level.txt././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1751348015.0 progress-1.6.1/progress.egg-info/dependency_links.txt0000644000076500000240000000000115030671457022352 0ustar00verigakstaff ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1751348015.0 progress-1.6.1/progress.egg-info/top_level.txt0000644000076500000240000000001115030671457021026 0ustar00verigakstaffprogress ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1751347616.0 progress-1.6.1/pyproject.toml0000644000076500000240000000225415030670640015656 0ustar00verigakstaff[build-system] requires = ["setuptools >= 77.0.3"] build-backend = "setuptools.build_meta" [project] name = "progress" dynamic = ["version"] description = "Easy to use progress bars" readme = "README.rst" authors = [{ name = "Georgios Verigakis", email = "verigak@gmail.com" }] maintainers = [{ name = "Georgios Verigakis", email = "verigak@gmail.com" }] license = "ISC" license-files = ["LICENSE"] requires-python = ">=3.6" keywords = ["progress", "bar"] classifiers = [ "Environment :: Console", "Intended Audience :: Developers", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", ] [project.urls] Homepage = "https://github.com/verigak/progress/" Repository = "https://github.com/verigak/progress.git" Issues = "https://github.com/verigak/progress/issues" [tool.setuptools] packages = ["progress"] [tool.setuptools.dynamic] version = {attr = "progress.__version__"} ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1751348015.6534755 progress-1.6.1/setup.cfg0000644000076500000240000000004615030671460014561 0ustar00verigakstaff[egg_info] tag_build = tag_date = 0 ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1751347616.0 progress-1.6.1/test_progress.py0000755000076500000240000000314415030670640016221 0ustar00verigakstaff#!/usr/bin/env python from __future__ import print_function import random import time from progress.bar import (Bar, ChargingBar, FillingSquaresBar, FillingCirclesBar, IncrementalBar, PixelBar, ShadyBar) from progress.spinner import (Spinner, PieSpinner, MoonSpinner, LineSpinner, PixelSpinner) from progress.counter import Counter, Countdown, Stack, Pie from progress.colors import bold def sleep(): t = 0.01 t += t * random.uniform(-0.1, 0.1) # Add some variance time.sleep(t) for bar_cls in (Bar, ChargingBar, FillingSquaresBar, FillingCirclesBar): suffix = '%(index)d/%(max)d [%(elapsed)d / %(eta)d / %(eta_td)s] (%(iter_value)s)' bar = bar_cls(bar_cls.__name__, suffix=suffix) for i in bar.iter(range(200, 400)): sleep() for bar_cls in (IncrementalBar, PixelBar, ShadyBar): suffix = '%(percent)d%% [%(elapsed_td)s / %(eta)d / %(eta_td)s]' with bar_cls(bar_cls.__name__, suffix=suffix, max=200) as bar: for i in range(200): bar.next() sleep() bar = IncrementalBar(bold('Colored'), color='green') for i in bar.iter(range(200)): sleep() for spin in (Spinner, PieSpinner, MoonSpinner, LineSpinner, PixelSpinner): for i in spin(spin.__name__ + ' %(index)d ').iter(range(100)): sleep() for singleton in (Counter, Countdown, Stack, Pie): for i in singleton(singleton.__name__ + ' ').iter(range(100)): sleep() bar = IncrementalBar('Random', suffix='%(index)d') for i in range(100): bar.goto(random.randint(0, 100)) sleep() bar.finish()