pax_global_header00006660000000000000000000000064143302366100014510gustar00rootroot0000000000000052 comment=19795af6a0c9fc3774cc05982ecefb7936107d3f python-progressbar-4.3b.0/000077500000000000000000000000001433023661000155265ustar00rootroot00000000000000python-progressbar-4.3b.0/.coveragerc000066400000000000000000000006211433023661000176460ustar00rootroot00000000000000[run] branch = True source = progressbar tests omit = */mock/* */nose/* .tox/* [paths] source = progressbar [report] fail_under = 100 exclude_lines = pragma: no cover @abc.abstractmethod def __repr__ if self.debug: if settings.DEBUG raise AssertionError raise NotImplementedError if 0: if __name__ == .__main__.: if types.TYPE_CHECKING: python-progressbar-4.3b.0/.github/000077500000000000000000000000001433023661000170665ustar00rootroot00000000000000python-progressbar-4.3b.0/.github/FUNDING.yml000066400000000000000000000000161433023661000207000ustar00rootroot00000000000000github: WoLpH python-progressbar-4.3b.0/.github/ci-reporter.yml000066400000000000000000000006431433023661000220470ustar00rootroot00000000000000# Set to false to create a new comment instead of updating the app's first one updateComment: true # Use a custom string, or set to false to disable before: "✨ Good work on this PR so far! ✨ Unfortunately, the [ build]() is failing as of . Here's the output:" # Use a custom string, or set to false to disable after: "I'm sure you can fix it! If you need help, don't hesitate to ask a maintainer of the project!" python-progressbar-4.3b.0/.github/stale.yml000066400000000000000000000013331433023661000207210ustar00rootroot00000000000000# Number of days of inactivity before an issue becomes stale daysUntilStale: 60 # Number of days of inactivity before a stale issue is closed daysUntilClose: 7 # Issues with these labels will never be considered stale exemptLabels: - in-progress - help-wanted - pinned - security - enhancement # Label to use when marking an issue as stale staleLabel: no-activity # Comment to post when marking an issue as stale. Set to `false` to disable markComment: > This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions. # Comment to post when closing a stale issue. Set to `false` to disable closeComment: false python-progressbar-4.3b.0/.github/workflows/000077500000000000000000000000001433023661000211235ustar00rootroot00000000000000python-progressbar-4.3b.0/.github/workflows/main.yml000066400000000000000000000010401433023661000225650ustar00rootroot00000000000000name: tox on: push: pull_request: workflow_dispatch: jobs: build: runs-on: ubuntu-latest timeout-minutes: 10 strategy: matrix: python-version: ['3.7', '3.8', '3.9', '3.10'] steps: - uses: actions/checkout@v3 - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v4 with: python-version: ${{ matrix.python-version }} - name: Install dependencies run: | python -m pip install --upgrade pip tox - name: Test with tox run: tox python-progressbar-4.3b.0/.gitignore000066400000000000000000000007141433023661000175200ustar00rootroot00000000000000# Byte-compiled / optimized / DLL files __pycache__/ *.py[cod] # C extensions *.so # Distribution / packaging .Python env/ build/ develop-eggs/ dist/ eggs/ lib/ lib64/ parts/ sdist/ var/ *.egg-info/ .installed.cfg *.egg # Installer logs pip-log.txt pip-delete-this-directory.txt # Unit test / coverage reports htmlcov/ .tox/ .coverage .cache nosetests.xml coverage.xml # Translations *.mo *.pot # Django stuff: *.log # Sphinx documentation docs/_build/ python-progressbar-4.3b.0/.pre-commit-config.yaml000066400000000000000000000005671433023661000220170ustar00rootroot00000000000000# See https://pre-commit.com for more information # See https://pre-commit.com/hooks.html for more hooks repos: - repo: https://github.com/pre-commit/pre-commit-hooks rev: v2.4.0 hooks: - id: trailing-whitespace - id: check-yaml - id: check-added-large-files - repo: https://gitlab.com/pycqa/flake8 rev: 3.7.9 hooks: - id: flake8 python-progressbar-4.3b.0/.travis.yml000066400000000000000000000013101433023661000176320ustar00rootroot00000000000000dist: xenial sudo: false language: python python: - '2.7' - '3.4' - '3.5' - '3.6' - '3.7' - '3.8' - pypy install: - pip install -U . - pip install -U -r tests/requirements.txt before_script: flake8 progressbar tests examples.py script: - py.test - python examples.py after_success: - coveralls - pip install codecov - codecov before_deploy: "python setup.py sdist bdist_wheel" deploy: provider: releases api_key: secure: DmqlCoHxPh5465T5DQgdFE7Peqy7MVF034n7t/hpV2Lf4LH9fHUo2r1dpICpBIxRuDNCXtM3PJLk59OMqCchpcAlC7VkH6dTOLpigk/IXYtlJVr3cXQUEC0gmPuFsrZ/fpWUR0PBfUD/fBA0RW64xFZ6ksfc+76tdQrKj1appz0= file: dist/* file_glob: true skip_cleanup: true on: tags: true repo: WoLpH/python-progressbar python-progressbar-4.3b.0/CHANGES.rst000066400000000000000000000004741433023661000173350ustar00rootroot00000000000000========= Changelog ========= For the most recent changes to the Python Progressbar please look at the Git releases or the commit log: - https://github.com/WoLpH/python-progressbar/releases - https://github.com/WoLpH/python-progressbar/commits/develop Hint: click on the `...` button to see the change message. python-progressbar-4.3b.0/CONTRIBUTING.rst000066400000000000000000000070651433023661000201770ustar00rootroot00000000000000============ Contributing ============ Contributions are welcome, and they are greatly appreciated! Every little bit helps, and credit will always be given. You can contribute in many ways: Types of Contributions ---------------------- Report Bugs ~~~~~~~~~~~ Report bugs at https://github.com/WoLpH/python-progressbar/issues. If you are reporting a bug, please include: * Your operating system name and version. * Any details about your local setup that might be helpful in troubleshooting. * Detailed steps to reproduce the bug. Fix Bugs ~~~~~~~~ Look through the GitHub issues for bugs. Anything tagged with "bug" is open to whoever wants to implement it. Implement Features ~~~~~~~~~~~~~~~~~~ Look through the GitHub issues for features. Anything tagged with "feature" is open to whoever wants to implement it. Write Documentation ~~~~~~~~~~~~~~~~~~~ Python Progressbar could always use more documentation, whether as part of the official Python Progressbar docs, in docstrings, or even on the web in blog posts, articles, and such. Submit Feedback ~~~~~~~~~~~~~~~ The best way to send feedback is to file an issue at https://github.com/WoLpH/python-progressbar/issues. If you are proposing a feature: * Explain in detail how it would work. * Keep the scope as narrow as possible, to make it easier to implement. * Remember that this is a volunteer-driven project, and that contributions are welcome :) Get Started! ------------ Ready to contribute? Here's how to set up `python-progressbar` for local development. 1. Fork the `python-progressbar` repo on GitHub. 2. Clone your fork locally:: $ git clone --branch develop git@github.com:your_name_here/python-progressbar.git 3. Install your local copy into a virtualenv. Assuming you have virtualenvwrapper installed, this is how you set up your fork for local development:: $ mkvirtualenv progressbar $ cd progressbar/ $ pip install -e . 4. Create a branch for local development with `git-flow-avh`_:: $ git-flow feature start name-of-your-bugfix-or-feature Or without git-flow: $ git checkout -b feature/name-of-your-bugfix-or-feature Now you can make your changes locally. 5. When you're done making changes, check that your changes pass flake8 and the tests, including testing other Python versions with tox:: $ flake8 progressbar tests $ py.test $ tox To get flake8 and tox, just pip install them into your virtualenv using the requirements file. $ pip install -r tests/requirements.txt 6. Commit your changes and push your branch to GitHub with `git-flow-avh`_:: $ git add . $ git commit -m "Your detailed description of your changes." $ git-flow feature publish Or without git-flow: $ git add . $ git commit -m "Your detailed description of your changes." $ git push -u origin feature/name-of-your-bugfix-or-feature 7. Submit a pull request through the GitHub website. Pull Request Guidelines ----------------------- Before you submit a pull request, check that it meets these guidelines: 1. The pull request should include tests. 2. If the pull request adds functionality, the docs should be updated. Put your new functionality into a function with a docstring, and add the feature to the list in README.rst. 3. The pull request should work for Python 2.7, 3.3, and for PyPy. Check https://travis-ci.org/WoLpH/python-progressbar/pull_requests and make sure that the tests pass for all supported Python versions. Tips ---- To run a subset of tests:: $ py.test tests/some_test.py .. _git-flow-avh: https://github.com/petervanderdoes/gitflow python-progressbar-4.3b.0/ISSUE_TEMPLATE000066400000000000000000000006071433023661000176370ustar00rootroot00000000000000#### Description Description of the problem #### Code If applicable, code to reproduce the issue and/or the stacktrace of the issue #### Versions - Python version: `import sys; print(sys.version)` - Python distribution/environment: CPython/Anaconda/IPython/IDLE - Operating System: Windows 10, Ubuntu Linux, etc. - Package version: `import progressbar; print(progressbar.__version__)` python-progressbar-4.3b.0/LICENSE000066400000000000000000000027441433023661000165420ustar00rootroot00000000000000Copyright (c) 2022, Rick van Hattem (Wolph) All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Python Progressbar nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. python-progressbar-4.3b.0/MANIFEST.in000066400000000000000000000003771433023661000172730ustar00rootroot00000000000000include AUTHORS.rst include CHANGES.rst include CONTRIBUTING.rst include LICENSE include README.rst include examples.py include requirements.txt include Makefile include pytest.ini recursive-include tests * recursive-exclude *.pyc recursive-exclude *.pyo python-progressbar-4.3b.0/README.rst000066400000000000000000000266121433023661000172240ustar00rootroot00000000000000############################################################################## Text progress bar library for Python. ############################################################################## Build status: .. image:: https://github.com/WoLpH/python-progressbar/actions/workflows/main.yml/badge.svg :alt: python-progressbar test status :target: https://github.com/WoLpH/python-progressbar/actions Coverage: .. image:: https://coveralls.io/repos/WoLpH/python-progressbar/badge.svg?branch=master :target: https://coveralls.io/r/WoLpH/python-progressbar?branch=master ****************************************************************************** Install ****************************************************************************** The package can be installed through `pip` (this is the recommended method): pip install progressbar2 Or if `pip` is not available, `easy_install` should work as well: easy_install progressbar2 Or download the latest release from Pypi (https://pypi.python.org/pypi/progressbar2) or Github. Note that the releases on Pypi are signed with my GPG key (https://pgp.mit.edu/pks/lookup?op=vindex&search=0xE81444E9CE1F695D) and can be checked using GPG: gpg --verify progressbar2-.tar.gz.asc progressbar2-.tar.gz ****************************************************************************** Introduction ****************************************************************************** A text progress bar is typically used to display the progress of a long running operation, providing a visual cue that processing is underway. The progressbar is based on the old Python progressbar package that was published on the now defunct Google Code. Since that project was completely abandoned by its developer and the developer did not respond to email, I decided to fork the package. This package is still backwards compatible with the original progressbar package so you can safely use it as a drop-in replacement for existing project. The ProgressBar class manages the current progress, and the format of the line is given by a number of widgets. A widget is an object that may display differently depending on the state of the progress bar. There are many types of widgets: - `AbsoluteETA `_ - `AdaptiveETA `_ - `AdaptiveTransferSpeed `_ - `AnimatedMarker `_ - `Bar `_ - `BouncingBar `_ - `Counter `_ - `CurrentTime `_ - `DataSize `_ - `DynamicMessage `_ - `ETA `_ - `FileTransferSpeed `_ - `FormatCustomText `_ - `FormatLabel `_ - `FormatLabelBar `_ - `GranularBar `_ - `Percentage `_ - `PercentageLabelBar `_ - `ReverseBar `_ - `RotatingMarker `_ - `SimpleProgress `_ - `Timer `_ The progressbar module is very easy to use, yet very powerful. It will also automatically enable features like auto-resizing when the system supports it. ****************************************************************************** Known issues ****************************************************************************** Due to limitations in both the IDLE shell and the Jetbrains (Pycharm) shells this progressbar cannot function properly within those. - The IDLE editor doesn't support these types of progress bars at all: https://bugs.python.org/issue23220 - The Jetbrains (Pycharm) editors partially work but break with fast output. As a workaround make sure you only write to either `sys.stdout` (regular print) or `sys.stderr` at the same time. If you do plan to use both, make sure you wait about ~200 milliseconds for the next output or it will break regularly. Linked issue: https://github.com/WoLpH/python-progressbar/issues/115 - Jupyter notebooks buffer `sys.stdout` which can cause mixed output. This issue can be resolved easily using: `import sys; sys.stdout.flush()`. Linked issue: https://github.com/WoLpH/python-progressbar/issues/173 ****************************************************************************** Links ****************************************************************************** * Documentation - https://progressbar-2.readthedocs.org/en/latest/ * Source - https://github.com/WoLpH/python-progressbar * Bug reports - https://github.com/WoLpH/python-progressbar/issues * Package homepage - https://pypi.python.org/pypi/progressbar2 * My blog - https://w.wol.ph/ ****************************************************************************** Usage ****************************************************************************** There are many ways to use Python Progressbar, you can see a few basic examples here but there are many more in the examples file. Wrapping an iterable ============================================================================== .. code:: python import time import progressbar for i in progressbar.progressbar(range(100)): time.sleep(0.02) Progressbars with logging ============================================================================== Progressbars with logging require `stderr` redirection _before_ the `StreamHandler` is initialized. To make sure the `stderr` stream has been redirected on time make sure to call `progressbar.streams.wrap_stderr()` before you initialize the `logger`. One option to force early initialization is by using the `WRAP_STDERR` environment variable, on Linux/Unix systems this can be done through: .. code:: sh # WRAP_STDERR=true python your_script.py If you need to flush manually while wrapping, you can do so using: .. code:: python import progressbar progressbar.streams.flush() In most cases the following will work as well, as long as you initialize the `StreamHandler` after the wrapping has taken place. .. code:: python import time import logging import progressbar progressbar.streams.wrap_stderr() logging.basicConfig() for i in progressbar.progressbar(range(10)): logging.error('Got %d', i) time.sleep(0.2) Context wrapper ============================================================================== .. code:: python import time import progressbar with progressbar.ProgressBar(max_value=10) as bar: for i in range(10): time.sleep(0.1) bar.update(i) Combining progressbars with print output ============================================================================== .. code:: python import time import progressbar for i in progressbar.progressbar(range(100), redirect_stdout=True): print('Some text', i) time.sleep(0.1) Progressbar with unknown length ============================================================================== .. code:: python import time import progressbar bar = progressbar.ProgressBar(max_value=progressbar.UnknownLength) for i in range(20): time.sleep(0.1) bar.update(i) Bar with custom widgets ============================================================================== .. code:: python import time import progressbar widgets=[ ' [', progressbar.Timer(), '] ', progressbar.Bar(), ' (', progressbar.ETA(), ') ', ] for i in progressbar.progressbar(range(20), widgets=widgets): time.sleep(0.1) Bar with wide Chinese (or other multibyte) characters ============================================================================== .. code:: python # vim: fileencoding=utf-8 import time import progressbar def custom_len(value): # These characters take up more space characters = { '进': 2, '度': 2, } total = 0 for c in value: total += characters.get(c, 1) return total bar = progressbar.ProgressBar( widgets=[ '进度: ', progressbar.Bar(), ' ', progressbar.Counter(format='%(value)02d/%(max_value)d'), ], len_func=custom_len, ) for i in bar(range(10)): time.sleep(0.1) Showing multiple (threaded) independent progress bars in parallel ============================================================================== While this method works fine and will continue to work fine, a smarter and fully automatic version of this is currently being made: https://github.com/WoLpH/python-progressbar/issues/176 .. code:: python import random import sys import threading import time import progressbar output_lock = threading.Lock() class LineOffsetStreamWrapper: UP = '\033[F' DOWN = '\033[B' def __init__(self, lines=0, stream=sys.stderr): self.stream = stream self.lines = lines def write(self, data): with output_lock: self.stream.write(self.UP * self.lines) self.stream.write(data) self.stream.write(self.DOWN * self.lines) self.stream.flush() def __getattr__(self, name): return getattr(self.stream, name) bars = [] for i in range(5): bars.append( progressbar.ProgressBar( fd=LineOffsetStreamWrapper(i), max_value=1000, ) ) if i: print('Reserve a line for the progressbar') class Worker(threading.Thread): def __init__(self, bar): super().__init__() self.bar = bar def run(self): for i in range(1000): time.sleep(random.random() / 100) self.bar.update(i) for bar in bars: Worker(bar).start() python-progressbar-4.3b.0/appveyor.yml000066400000000000000000000015651433023661000201250ustar00rootroot00000000000000# What Python version is installed where: # http://www.appveyor.com/docs/installed-software#python environment: matrix: - PYTHON: "C:\\Python27" TOX_ENV: "py27" - PYTHON: "C:\\Python34" TOX_ENV: "py34" - PYTHON: "C:\\Python35" TOX_ENV: "py35" - PYTHON: "C:\\Python36" TOX_ENV: "py36" init: - "%PYTHON%/python -V" - "%PYTHON%/python -c \"import struct;print( 8 * struct.calcsize(\'P\'))\"" install: - "%PYTHON%/Scripts/easy_install -U pip" - "%PYTHON%/Scripts/pip install tox" - "%PYTHON%/Scripts/pip install wheel" build: false # Not a C# project, build stuff at the test step instead. test_script: - "%PYTHON%/Scripts/tox -e %TOX_ENV%" after_test: - "%PYTHON%/python setup.py bdist_wheel" - ps: "ls dist" artifacts: - path: dist\* #on_success: # - TODO: upload the content of dist/*.whl to a public wheelhouse python-progressbar-4.3b.0/circle.yml000066400000000000000000000001431433023661000175100ustar00rootroot00000000000000dependencies: pre: - pip install -r tests/requirements.txt test: override: - py.test python-progressbar-4.3b.0/docs/000077500000000000000000000000001433023661000164565ustar00rootroot00000000000000python-progressbar-4.3b.0/docs/.gitignore000066400000000000000000000000071433023661000204430ustar00rootroot00000000000000_build python-progressbar-4.3b.0/docs/Makefile000066400000000000000000000151761433023661000201300ustar00rootroot00000000000000# Makefile for Sphinx documentation # # You can set these variables from the command line. SPHINXOPTS = SPHINXBUILD = sphinx-build PAPER = BUILDDIR = _build # User-friendly check for sphinx-build ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1) $(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/) endif # Internal variables. PAPEROPT_a4 = -D latex_paper_size=a4 PAPEROPT_letter = -D latex_paper_size=letter ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . # the i18n builder cannot share the environment and doctrees with the others I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . .PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext help: @echo "Please use \`make ' where is one of" @echo " html to make standalone HTML files" @echo " dirhtml to make HTML files named index.html in directories" @echo " singlehtml to make a single large HTML file" @echo " pickle to make pickle files" @echo " json to make JSON files" @echo " htmlhelp to make HTML files and a HTML help project" @echo " qthelp to make HTML files and a qthelp project" @echo " devhelp to make HTML files and a Devhelp project" @echo " epub to make an epub" @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" @echo " latexpdf to make LaTeX files and run them through pdflatex" @echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx" @echo " text to make text files" @echo " man to make manual pages" @echo " texinfo to make Texinfo files" @echo " info to make Texinfo files and run them through makeinfo" @echo " gettext to make PO message catalogs" @echo " changes to make an overview of all changed/added/deprecated items" @echo " xml to make Docutils-native XML files" @echo " pseudoxml to make pseudoxml-XML files for display purposes" @echo " linkcheck to check all external links for integrity" @echo " doctest to run all doctests embedded in the documentation (if enabled)" clean: rm -rf $(BUILDDIR)/* html: $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." dirhtml: $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." singlehtml: $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml @echo @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." pickle: $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle @echo @echo "Build finished; now you can process the pickle files." json: $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json @echo @echo "Build finished; now you can process the JSON files." htmlhelp: $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp @echo @echo "Build finished; now you can run HTML Help Workshop with the" \ ".hhp project file in $(BUILDDIR)/htmlhelp." qthelp: $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp @echo @echo "Build finished; now you can run "qcollectiongenerator" with the" \ ".qhcp project file in $(BUILDDIR)/qthelp, like this:" @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/ProgressBar.qhcp" @echo "To view the help file:" @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/ProgressBar.qhc" devhelp: $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp @echo @echo "Build finished." @echo "To view the help file:" @echo "# mkdir -p $$HOME/.local/share/devhelp/ProgressBar" @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/ProgressBar" @echo "# devhelp" epub: $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub @echo @echo "Build finished. The epub file is in $(BUILDDIR)/epub." latex: $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." @echo "Run \`make' in that directory to run these through (pdf)latex" \ "(use \`make latexpdf' here to do that automatically)." latexpdf: $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo "Running LaTeX files through pdflatex..." $(MAKE) -C $(BUILDDIR)/latex all-pdf @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." latexpdfja: $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo "Running LaTeX files through platex and dvipdfmx..." $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." text: $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text @echo @echo "Build finished. The text files are in $(BUILDDIR)/text." man: $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man @echo @echo "Build finished. The manual pages are in $(BUILDDIR)/man." texinfo: $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo @echo @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." @echo "Run \`make' in that directory to run these through makeinfo" \ "(use \`make info' here to do that automatically)." info: $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo @echo "Running Texinfo files through makeinfo..." make -C $(BUILDDIR)/texinfo info @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." gettext: $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale @echo @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." changes: $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes @echo @echo "The overview file is in $(BUILDDIR)/changes." linkcheck: $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck @echo @echo "Link check complete; look for any errors in the above output " \ "or in $(BUILDDIR)/linkcheck/output.txt." doctest: $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest @echo "Testing of doctests in the sources finished, look at the " \ "results in $(BUILDDIR)/doctest/output.txt." xml: $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml @echo @echo "Build finished. The XML files are in $(BUILDDIR)/xml." pseudoxml: $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml @echo @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml." python-progressbar-4.3b.0/docs/_theme/000077500000000000000000000000001433023661000177175ustar00rootroot00000000000000python-progressbar-4.3b.0/docs/_theme/LICENSE000066400000000000000000000035521433023661000207310ustar00rootroot00000000000000Modifications: Copyright (c) 2012 Rick van Hattem. Original Projects: Copyright (c) 2010 Kenneth Reitz. Copyright (c) 2010 by Armin Ronacher. Some rights reserved. Redistribution and use in source and binary forms of the theme, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * The names of the contributors may not be used to endorse or promote products derived from this software without specific prior written permission. We kindly ask you to only use these themes in an unmodified manner just for Flask and Flask-related products, not for unrelated projects. If you like the visual style and want to use it for your own projects, please consider making some larger changes to the themes (such as changing font faces, sizes, colors or margins). THIS THEME IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS THEME, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. python-progressbar-4.3b.0/docs/_theme/flask_theme_support.py000066400000000000000000000114171433023661000243530ustar00rootroot00000000000000# flasky extensions. flasky pygments style based on tango style from pygments.style import Style from pygments.token import Keyword, Name, Comment, String, Error, \ Number, Operator, Generic, Whitespace, Punctuation, Other, Literal class FlaskyStyle(Style): background_color = "#f8f8f8" default_style = "" styles = { # No corresponding class for the following: # Text: "", # class: '' Whitespace: "underline #f8f8f8", # class: 'w' Error: "#a40000 border:#ef2929", # class: 'err' Other: "#000000", # class 'x' Comment: "italic #8f5902", # class: 'c' Comment.Preproc: "noitalic", # class: 'cp' Keyword: "bold #004461", # class: 'k' Keyword.Constant: "bold #004461", # class: 'kc' Keyword.Declaration: "bold #004461", # class: 'kd' Keyword.Namespace: "bold #004461", # class: 'kn' Keyword.Pseudo: "bold #004461", # class: 'kp' Keyword.Reserved: "bold #004461", # class: 'kr' Keyword.Type: "bold #004461", # class: 'kt' Operator: "#582800", # class: 'o' Operator.Word: "bold #004461", # class: 'ow' - like keywords Punctuation: "bold #000000", # class: 'p' # because special names such as Name.Class, Name.Function, etc. # are not recognized as such later in the parsing, we choose them # to look the same as ordinary variables. Name: "#000000", # class: 'n' Name.Attribute: "#c4a000", # class: 'na' - to be revised Name.Builtin: "#004461", # class: 'nb' Name.Builtin.Pseudo: "#3465a4", # class: 'bp' Name.Class: "#000000", # class: 'nc' - to be revised Name.Constant: "#000000", # class: 'no' - to be revised Name.Decorator: "#888", # class: 'nd' - to be revised Name.Entity: "#ce5c00", # class: 'ni' Name.Exception: "bold #cc0000", # class: 'ne' Name.Function: "#000000", # class: 'nf' Name.Property: "#000000", # class: 'py' Name.Label: "#f57900", # class: 'nl' Name.Namespace: "#000000", # class: 'nn' - to be revised Name.Other: "#000000", # class: 'nx' Name.Tag: "bold #004461", # class: 'nt' - like a keyword Name.Variable: "#000000", # class: 'nv' - to be revised Name.Variable.Class: "#000000", # class: 'vc' - to be revised Name.Variable.Global: "#000000", # class: 'vg' - to be revised Name.Variable.Instance: "#000000", # class: 'vi' - to be revised Number: "#990000", # class: 'm' Literal: "#000000", # class: 'l' Literal.Date: "#000000", # class: 'ld' String: "#4e9a06", # class: 's' String.Backtick: "#4e9a06", # class: 'sb' String.Char: "#4e9a06", # class: 'sc' String.Doc: "italic #8f5902", # class: 'sd' - like a comment String.Double: "#4e9a06", # class: 's2' String.Escape: "#4e9a06", # class: 'se' String.Heredoc: "#4e9a06", # class: 'sh' String.Interpol: "#4e9a06", # class: 'si' String.Other: "#4e9a06", # class: 'sx' String.Regex: "#4e9a06", # class: 'sr' String.Single: "#4e9a06", # class: 's1' String.Symbol: "#4e9a06", # class: 'ss' Generic: "#000000", # class: 'g' Generic.Deleted: "#a40000", # class: 'gd' Generic.Emph: "italic #000000", # class: 'ge' Generic.Error: "#ef2929", # class: 'gr' Generic.Heading: "bold #000080", # class: 'gh' Generic.Inserted: "#00A000", # class: 'gi' Generic.Output: "#888", # class: 'go' Generic.Prompt: "#745334", # class: 'gp' Generic.Strong: "bold #000000", # class: 'gs' Generic.Subheading: "bold #800080", # class: 'gu' Generic.Traceback: "bold #a40000", # class: 'gt' } python-progressbar-4.3b.0/docs/_theme/wolph/000077500000000000000000000000001433023661000210505ustar00rootroot00000000000000python-progressbar-4.3b.0/docs/_theme/wolph/layout.html000066400000000000000000000017271433023661000232620ustar00rootroot00000000000000{%- extends "basic/layout.html" %} {%- block extrahead %} {{ super() }} {% if theme_touch_icon %} {% endif %} {% endblock %} {%- block relbar2 %}{% endblock %} {%- block footer %} {%- endblock %} python-progressbar-4.3b.0/docs/_theme/wolph/relations.html000066400000000000000000000011161433023661000237350ustar00rootroot00000000000000

Related Topics

python-progressbar-4.3b.0/docs/_theme/wolph/static/000077500000000000000000000000001433023661000223375ustar00rootroot00000000000000python-progressbar-4.3b.0/docs/_theme/wolph/static/flasky.css_t000066400000000000000000000156061433023661000246750ustar00rootroot00000000000000/* * flasky.css_t * ~~~~~~~~~~~~ * * :copyright: Copyright 2010 by Armin Ronacher. Modifications by Kenneth Reitz. * :license: Flask Design License, see LICENSE for details. */ {% set page_width = '940px' %} {% set sidebar_width = '220px' %} @import url("basic.css"); /* -- page layout ----------------------------------------------------------- */ body { font-family: 'goudy old style', 'minion pro', 'bell mt', Georgia, 'Hiragino Mincho Pro'; font-size: 17px; background-color: white; color: #000; margin: 0; padding: 0; } div.document { width: {{ page_width }}; margin: 30px auto 0 auto; } div.documentwrapper { float: left; width: 100%; } div.bodywrapper { margin: 0 0 0 {{ sidebar_width }}; } div.sphinxsidebar { width: {{ sidebar_width }}; } hr { border: 1px solid #B1B4B6; } div.body { background-color: #ffffff; color: #3E4349; padding: 0 30px 0 30px; } img.floatingflask { padding: 0 0 10px 10px; float: right; } div.footer { width: {{ page_width }}; margin: 20px auto 30px auto; font-size: 14px; color: #888; text-align: right; } div.footer a { color: #888; } div.related { display: none; } div.sphinxsidebar a { color: #444; text-decoration: none; border-bottom: 1px dotted #999; } div.sphinxsidebar a:hover { border-bottom: 1px solid #999; } div.sphinxsidebar { font-size: 14px; line-height: 1.5; } div.sphinxsidebarwrapper { padding: 0px 10px; } div.sphinxsidebarwrapper p.logo { padding: 0 0 20px 0; margin: 0; text-align: center; } div.sphinxsidebar h3, div.sphinxsidebar h4 { font-family: 'Garamond', 'Georgia', serif; color: #555; font-size: 24px; font-weight: normal; margin: 0 0 5px 0; padding: 0; } div.sphinxsidebar h4 { font-size: 20px; } div.sphinxsidebar h3 a { color: #444; } div.sphinxsidebar p.logo a, div.sphinxsidebar h3 a, div.sphinxsidebar p.logo a:hover, div.sphinxsidebar h3 a:hover { border: none; } div.sphinxsidebar p { color: #555; margin: 10px 0; } div.sphinxsidebar ul { margin: 10px 0; padding: 0; color: #000; } div.sphinxsidebar input[type="text"] { width: 160px!important; } div.sphinxsidebar input { border: 1px solid #ccc; font-family: 'Georgia', serif; font-size: 1em; } /* -- body styles ----------------------------------------------------------- */ a { color: #004B6B; text-decoration: underline; } a:hover { color: #6D4100; text-decoration: underline; } div.body h1, div.body h2, div.body h3, div.body h4, div.body h5, div.body h6 { font-family: 'Garamond', 'Georgia', serif; font-weight: normal; margin: 30px 0px 10px 0px; padding: 0; } div.body h1 { margin-top: 0; padding-top: 0; font-size: 240%; } div.body h2 { font-size: 180%; } div.body h3 { font-size: 150%; } div.body h4 { font-size: 130%; } div.body h5 { font-size: 100%; } div.body h6 { font-size: 100%; } a.headerlink { color: #ddd; padding: 0 4px; text-decoration: none; } a.headerlink:hover { color: #444; background: #eaeaea; } div.body p, div.body dd, div.body li { line-height: 1.4em; } div.admonition { background: #fafafa; margin: 20px -30px; padding: 10px 30px; border-top: 1px solid #ccc; border-bottom: 1px solid #ccc; } div.admonition tt.xref, div.admonition a tt { border-bottom: 1px solid #fafafa; } dd div.admonition { margin-left: -60px; padding-left: 60px; } div.admonition p.admonition-title { font-family: 'Garamond', 'Georgia', serif; font-weight: normal; font-size: 24px; margin: 0 0 10px 0; padding: 0; line-height: 1; } div.admonition p.last { margin-bottom: 0; } div.highlight { background-color: white; } dt:target, .highlight { background: #FAF3E8; } div.note { background-color: #eee; border: 1px solid #ccc; } div.seealso { background-color: #ffc; border: 1px solid #ff6; } div.topic { background-color: #eee; } p.admonition-title { display: inline; } p.admonition-title:after { content: ":"; } pre, tt { font-family: 'Consolas', 'Menlo', 'Deja Vu Sans Mono', 'Bitstream Vera Sans Mono', monospace; font-size: 0.9em; } img.screenshot { } tt.descname, tt.descclassname { font-size: 0.95em; } tt.descname { padding-right: 0.08em; } img.screenshot { -moz-box-shadow: 2px 2px 4px #eee; -webkit-box-shadow: 2px 2px 4px #eee; box-shadow: 2px 2px 4px #eee; } table.docutils { border: 1px solid #888; -moz-box-shadow: 2px 2px 4px #eee; -webkit-box-shadow: 2px 2px 4px #eee; box-shadow: 2px 2px 4px #eee; } table.docutils td, table.docutils th { border: 1px solid #888; padding: 0.25em 0.7em; } table.field-list, table.footnote { border: none; -moz-box-shadow: none; -webkit-box-shadow: none; box-shadow: none; } table.footnote { margin: 15px 0; width: 100%; border: 1px solid #eee; background: #fdfdfd; font-size: 0.9em; } table.footnote + table.footnote { margin-top: -15px; border-top: none; } table.field-list th { padding: 0 0.8em 0 0; } table.field-list td { padding: 0; } table.footnote td.label { width: 0px; padding: 0.3em 0 0.3em 0.5em; } table.footnote td { padding: 0.3em 0.5em; } dl { margin: 0; padding: 0; } dl dd { margin-left: 30px; } blockquote { margin: 0 0 0 30px; padding: 0; } ul, ol { margin: 10px 0 10px 30px; padding: 0; } pre { background: #eee; padding: 7px 30px; margin: 15px -30px; line-height: 1.3em; } dl pre, blockquote pre, li pre { margin-left: -60px; padding-left: 60px; } dl dl pre { margin-left: -90px; padding-left: 90px; } tt { background-color: #ecf0f3; color: #222; /* padding: 1px 2px; */ } tt.xref, a tt { background-color: #FBFBFB; border-bottom: 1px solid white; } a.reference { text-decoration: none; border-bottom: 1px dotted #004B6B; } a.reference:hover { border-bottom: 1px solid #6D4100; } a.footnote-reference { text-decoration: none; font-size: 0.7em; vertical-align: top; border-bottom: 1px dotted #004B6B; } a.footnote-reference:hover { border-bottom: 1px solid #6D4100; } a:hover tt { background: #EEE; } /* scrollbars */ ::-webkit-scrollbar { width: 6px; height: 6px; } ::-webkit-scrollbar-button:start:decrement, ::-webkit-scrollbar-button:end:increment { display: block; height: 10px; } ::-webkit-scrollbar-button:vertical:increment { background-color: #fff; } ::-webkit-scrollbar-track-piece { background-color: #eee; -webkit-border-radius: 3px; } ::-webkit-scrollbar-thumb:vertical { height: 50px; background-color: #ccc; -webkit-border-radius: 3px; } ::-webkit-scrollbar-thumb:horizontal { width: 50px; background-color: #ccc; -webkit-border-radius: 3px; } /* misc. */ .revsys-inline { display: none!important; } python-progressbar-4.3b.0/docs/_theme/wolph/static/small_flask.css000066400000000000000000000017201433023661000253410ustar00rootroot00000000000000/* * small_flask.css_t * ~~~~~~~~~~~~~~~~~ * * :copyright: Copyright 2010 by Armin Ronacher. * :license: Flask Design License, see LICENSE for details. */ body { margin: 0; padding: 20px 30px; } div.documentwrapper { float: none; background: white; } div.sphinxsidebar { display: block; float: none; width: 102.5%; margin: 50px -30px -20px -30px; padding: 10px 20px; background: #333; color: white; } div.sphinxsidebar h3, div.sphinxsidebar h4, div.sphinxsidebar p, div.sphinxsidebar h3 a { color: white; } div.sphinxsidebar a { color: #aaa; } div.sphinxsidebar p.logo { display: none; } div.document { width: 100%; margin: 0; } div.related { display: block; margin: 0; padding: 10px 0 20px 0; } div.related ul, div.related ul li { margin: 0; padding: 0; } div.footer { display: none; } div.bodywrapper { margin: 0; } div.body { min-height: 0; padding: 0; } python-progressbar-4.3b.0/docs/_theme/wolph/theme.conf000066400000000000000000000001711433023661000230200ustar00rootroot00000000000000[theme] inherit = basic stylesheet = flasky.css pygments_style = flask_theme_support.FlaskyStyle [options] touch_icon = python-progressbar-4.3b.0/docs/conf.py000066400000000000000000000241161433023661000177610ustar00rootroot00000000000000# -*- coding: utf-8 -*- # # Progress Bar documentation build configuration file, created by # sphinx-quickstart on Tue Aug 20 11:47:33 2013. # # This file is execfile()d with the current directory set to its containing dir. # # Note that not all possible configuration values are present in this # autogenerated file. # # All configuration values have a default; values that are commented out # serve to show the default. import os import sys import datetime # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. sys.path.insert(0, os.path.abspath('..')) from progressbar import __about__ as metadata # -- General configuration ----------------------------------------------- # If your documentation needs a minimal Sphinx version, state it here. # needs_sphinx = '1.0' # Add any Sphinx extension module names here, as strings. They can be extensions # coming with Sphinx (named 'sphinx.ext.*') or your custom ones. extensions = [ 'sphinx.ext.autodoc', 'sphinx.ext.doctest', 'sphinx.ext.intersphinx', 'sphinx.ext.todo', 'sphinx.ext.coverage', 'sphinx.ext.mathjax', 'sphinx.ext.ifconfig', 'sphinx.ext.viewcode', 'sphinx.ext.napoleon', ] suppress_warnings = [ 'image.nonlocal_uri', ] needs_sphinx = '1.4' # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] # The suffix of source filenames. source_suffix = '.rst' # The encoding of source files. # source_encoding = 'utf-8-sig' # The master toctree document. master_doc = 'index' # General information about the project. project = u'Progress Bar' project_slug = ''.join(project.capitalize().split()) copyright = u'%s, %s' % ( datetime.date.today().year, metadata.__author__, ) # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the # built documents. # # The short X.Y version. version = metadata.__version__ # The full version, including alpha/beta/rc tags. release = metadata.__version__ # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. # language = None # There are two options for replacing |today|: either, you set today to some # non-false value, then it is used: # today = '' # Else, today_fmt is used as the format for a strftime call. # today_fmt = '%B %d, %Y' # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. exclude_patterns = ['_build'] # The reST default role (used for this markup: `text`) to use for all documents. # default_role = None # If true, '()' will be appended to :func: etc. cross-reference text. # add_function_parentheses = True # If true, the current module name will be prepended to all description # unit titles (such as .. function::). # add_module_names = True # If true, sectionauthor and moduleauthor directives will be shown in the # output. They are ignored by default. show_authors = True # The name of the Pygments (syntax highlighting) style to use. pygments_style = 'sphinx' # A list of ignored prefixes for module index sorting. # modindex_common_prefix = [] # If true, keep warnings as "system message" paragraphs in the built documents. # keep_warnings = False # -- Options for HTML output --------------------------------------------- # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. html_theme = 'wolph' # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the # documentation. # html_theme_options = {} # Add any paths that contain custom themes here, relative to this directory. html_theme_path = ['_theme'] # The name for this set of Sphinx documents. If None, it defaults to # " v documentation". # html_title = None # A shorter title for the navigation bar. Default is the same as html_title. # html_short_title = None # The name of an image file (relative to this directory) to place at the top # of the sidebar. # html_logo = None # The name of an image file (within the static path) to use as favicon of the # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 # pixels large. # html_favicon = None # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". html_static_path = ['_static'] # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, # using the given strftime format. # html_last_updated_fmt = '%b %d, %Y' # If true, SmartyPants will be used to convert quotes and dashes to # typographically correct entities. # html_use_smartypants = True # Custom sidebar templates, maps document names to template names. # html_sidebars = {} # Additional templates that should be rendered to pages, maps page names to # template names. # html_additional_pages = {} # If false, no module index is generated. # html_domain_indices = True # If false, no index is generated. # html_use_index = True # If true, the index is split into individual pages for each letter. # html_split_index = False # If true, links to the reST sources are added to the pages. # html_show_sourcelink = True # If true, "Created using Sphinx" is shown in the HTML footer. Default is True. # html_show_sphinx = True # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. # html_show_copyright = True # If true, an OpenSearch description file will be output, and all pages will # contain a tag referring to it. The value of this option must be the # base URL from which the finished HTML is served. # html_use_opensearch = '' # This is the file name suffix for HTML files (e.g. ".xhtml"). # html_file_suffix = None # Output file base name for HTML help builder. htmlhelp_basename = '%sdoc' % project_slug # -- Options for LaTeX output -------------------------------------------- latex_elements = { # The paper size ('letterpaper' or 'a4paper'). #'papersize': 'letterpaper', # The font size ('10pt', '11pt' or '12pt'). #'pointsize': '10pt', # Additional stuff for the LaTeX preamble. #'preamble': '', } # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, author, documentclass [howto/manual]). latex_documents = [ ('index', '%s.tex' % project_slug, u'%s Documentation' % project, metadata.__author__, 'manual'), ] # The name of an image file (relative to this directory) to place at the top of # the title page. # latex_logo = None # For "manual" documents, if this is true, then toplevel headings are parts, # not chapters. # latex_use_parts = False # If true, show page references after internal links. # latex_show_pagerefs = False # If true, show URL addresses after external links. # latex_show_urls = False # Documents to append as an appendix to all manuals. # latex_appendices = [] # If false, no module index is generated. # latex_domain_indices = True # -- Options for manual page output -------------------------------------- # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). man_pages = [ ('index', project_slug.lower(), u'%s Documentation' % project, [metadata.__author__], 1) ] # If true, show URL addresses after external links. # man_show_urls = False # -- Options for Texinfo output ------------------------------------------ # Grouping the document tree into Texinfo files. List of tuples # (source start file, target name, title, author, # dir menu entry, description, category) texinfo_documents = [ ('index', project_slug, u'%s Documentation' % project, metadata.__author__, project_slug, 'One line description of project.', 'Miscellaneous'), ] # Documents to append as an appendix to all manuals. # texinfo_appendices = [] # If false, no module index is generated. # texinfo_domain_indices = True # How to display URL addresses: 'footnote', 'no', or 'inline'. # texinfo_show_urls = 'footnote' # If true, do not generate a @detailmenu in the "Top" node's menu. # texinfo_no_detailmenu = False # -- Options for Epub output --------------------------------------------- # Bibliographic Dublin Core info. epub_title = project epub_author = metadata.__author__ epub_publisher = metadata.__author__ epub_copyright = copyright # The language of the text. It defaults to the language option # or en if the language is not set. # epub_language = '' # The scheme of the identifier. Typical schemes are ISBN or URL. # epub_scheme = '' # The unique identifier of the text. This can be a ISBN number # or the project homepage. # epub_identifier = '' # A unique identification for the text. # epub_uid = '' # A tuple containing the cover image and cover page html template filenames. # epub_cover = () # A sequence of (type, uri, title) tuples for the guide element of content.opf. # epub_guide = () # HTML files that should be inserted before the pages created by sphinx. # The format is a list of tuples containing the path and title. # epub_pre_files = [] # HTML files shat should be inserted after the pages created by sphinx. # The format is a list of tuples containing the path and title. # epub_post_files = [] # A list of files that should not be packed into the epub file. # epub_exclude_files = [] # The depth of the table of contents in toc.ncx. # epub_tocdepth = 3 # Allow duplicate toc entries. # epub_tocdup = True # Fix unsupported image types using the PIL. # epub_fix_images = False # Scale large images. # epub_max_image_width = 0 # If 'no', URL addresses will not be shown. # epub_show_urls = 'inline' # If false, no index is generated. # epub_use_index = True # Example configuration for intersphinx: refer to the Python standard library. intersphinx_mapping = {'http://docs.python.org/': None} python-progressbar-4.3b.0/docs/contributing.rst000066400000000000000000000000411433023661000217120ustar00rootroot00000000000000.. include:: ../CONTRIBUTING.rst python-progressbar-4.3b.0/docs/examples.rst000066400000000000000000000001021433023661000210170ustar00rootroot00000000000000Examples =================== .. literalinclude:: ../examples.py python-progressbar-4.3b.0/docs/history.rst000066400000000000000000000001261433023661000207100ustar00rootroot00000000000000.. _history: ======= History ======= .. include:: ../CHANGES.rst :start-line: 5 python-progressbar-4.3b.0/docs/index.rst000066400000000000000000000007221433023661000203200ustar00rootroot00000000000000======================================== Welcome to Progress Bar's documentation! ======================================== .. toctree:: :maxdepth: 4 usage examples contributing installation progressbar.shortcuts progressbar.bar progressbar.base progressbar.utils progressbar.widgets history .. include:: ../README.rst ****************** Indices and tables ****************** * :ref:`genindex` * :ref:`modindex` * :ref:`search` python-progressbar-4.3b.0/docs/installation.rst000066400000000000000000000004121433023661000217060ustar00rootroot00000000000000============ Installation ============ At the command line:: $ pip install progressbar2 Or if you don't have pip:: $ easy_install progressbar2 Or, if you have virtualenvwrapper installed:: $ mkvirtualenv progressbar2 $ pip install progressbar2 python-progressbar-4.3b.0/docs/make.bat000066400000000000000000000145051433023661000200700ustar00rootroot00000000000000@ECHO OFF REM Command file for Sphinx documentation if "%SPHINXBUILD%" == "" ( set SPHINXBUILD=sphinx-build ) set BUILDDIR=_build set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% . set I18NSPHINXOPTS=%SPHINXOPTS% . if NOT "%PAPER%" == "" ( set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS% set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS% ) if "%1" == "" goto help if "%1" == "help" ( :help echo.Please use `make ^` where ^ is one of echo. html to make standalone HTML files echo. dirhtml to make HTML files named index.html in directories echo. singlehtml to make a single large HTML file echo. pickle to make pickle files echo. json to make JSON files echo. htmlhelp to make HTML files and a HTML help project echo. qthelp to make HTML files and a qthelp project echo. devhelp to make HTML files and a Devhelp project echo. epub to make an epub echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter echo. text to make text files echo. man to make manual pages echo. texinfo to make Texinfo files echo. gettext to make PO message catalogs echo. changes to make an overview over all changed/added/deprecated items echo. xml to make Docutils-native XML files echo. pseudoxml to make pseudoxml-XML files for display purposes echo. linkcheck to check all external links for integrity echo. doctest to run all doctests embedded in the documentation if enabled goto end ) if "%1" == "clean" ( for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i del /q /s %BUILDDIR%\* goto end ) %SPHINXBUILD% 2> nul if errorlevel 9009 ( echo. echo.The 'sphinx-build' command was not found. Make sure you have Sphinx echo.installed, then set the SPHINXBUILD environment variable to point echo.to the full path of the 'sphinx-build' executable. Alternatively you echo.may add the Sphinx directory to PATH. echo. echo.If you don't have Sphinx installed, grab it from echo.http://sphinx-doc.org/ exit /b 1 ) if "%1" == "html" ( %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html if errorlevel 1 exit /b 1 echo. echo.Build finished. The HTML pages are in %BUILDDIR%/html. goto end ) if "%1" == "dirhtml" ( %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml if errorlevel 1 exit /b 1 echo. echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml. goto end ) if "%1" == "singlehtml" ( %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml if errorlevel 1 exit /b 1 echo. echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml. goto end ) if "%1" == "pickle" ( %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle if errorlevel 1 exit /b 1 echo. echo.Build finished; now you can process the pickle files. goto end ) if "%1" == "json" ( %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json if errorlevel 1 exit /b 1 echo. echo.Build finished; now you can process the JSON files. goto end ) if "%1" == "htmlhelp" ( %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp if errorlevel 1 exit /b 1 echo. echo.Build finished; now you can run HTML Help Workshop with the ^ .hhp project file in %BUILDDIR%/htmlhelp. goto end ) if "%1" == "qthelp" ( %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp if errorlevel 1 exit /b 1 echo. echo.Build finished; now you can run "qcollectiongenerator" with the ^ .qhcp project file in %BUILDDIR%/qthelp, like this: echo.^> qcollectiongenerator %BUILDDIR%\qthelp\progressbar.qhcp echo.To view the help file: echo.^> assistant -collectionFile %BUILDDIR%\qthelp\progressbar.ghc goto end ) if "%1" == "devhelp" ( %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp if errorlevel 1 exit /b 1 echo. echo.Build finished. goto end ) if "%1" == "epub" ( %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub if errorlevel 1 exit /b 1 echo. echo.Build finished. The epub file is in %BUILDDIR%/epub. goto end ) if "%1" == "latex" ( %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex if errorlevel 1 exit /b 1 echo. echo.Build finished; the LaTeX files are in %BUILDDIR%/latex. goto end ) if "%1" == "latexpdf" ( %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex cd %BUILDDIR%/latex make all-pdf cd %BUILDDIR%/.. echo. echo.Build finished; the PDF files are in %BUILDDIR%/latex. goto end ) if "%1" == "latexpdfja" ( %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex cd %BUILDDIR%/latex make all-pdf-ja cd %BUILDDIR%/.. echo. echo.Build finished; the PDF files are in %BUILDDIR%/latex. goto end ) if "%1" == "text" ( %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text if errorlevel 1 exit /b 1 echo. echo.Build finished. The text files are in %BUILDDIR%/text. goto end ) if "%1" == "man" ( %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man if errorlevel 1 exit /b 1 echo. echo.Build finished. The manual pages are in %BUILDDIR%/man. goto end ) if "%1" == "texinfo" ( %SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo if errorlevel 1 exit /b 1 echo. echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo. goto end ) if "%1" == "gettext" ( %SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale if errorlevel 1 exit /b 1 echo. echo.Build finished. The message catalogs are in %BUILDDIR%/locale. goto end ) if "%1" == "changes" ( %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes if errorlevel 1 exit /b 1 echo. echo.The overview file is in %BUILDDIR%/changes. goto end ) if "%1" == "linkcheck" ( %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck if errorlevel 1 exit /b 1 echo. echo.Link check complete; look for any errors in the above output ^ or in %BUILDDIR%/linkcheck/output.txt. goto end ) if "%1" == "doctest" ( %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest if errorlevel 1 exit /b 1 echo. echo.Testing of doctests in the sources finished, look at the ^ results in %BUILDDIR%/doctest/output.txt. goto end ) if "%1" == "xml" ( %SPHINXBUILD% -b xml %ALLSPHINXOPTS% %BUILDDIR%/xml if errorlevel 1 exit /b 1 echo. echo.Build finished. The XML files are in %BUILDDIR%/xml. goto end ) if "%1" == "pseudoxml" ( %SPHINXBUILD% -b pseudoxml %ALLSPHINXOPTS% %BUILDDIR%/pseudoxml if errorlevel 1 exit /b 1 echo. echo.Build finished. The pseudo-XML files are in %BUILDDIR%/pseudoxml. goto end ) :end python-progressbar-4.3b.0/docs/progressbar.bar.rst000066400000000000000000000002441433023661000223040ustar00rootroot00000000000000progressbar.bar module ====================== .. automodule:: progressbar.bar :members: :undoc-members: :show-inheritance: :member-order: bysource python-progressbar-4.3b.0/docs/progressbar.base.rst000066400000000000000000000002131433023661000224460ustar00rootroot00000000000000progressbar.base module ======================= .. automodule:: progressbar.base :members: :undoc-members: :show-inheritance: python-progressbar-4.3b.0/docs/progressbar.shortcuts.rst000066400000000000000000000002341433023661000235750ustar00rootroot00000000000000progressbar\.shortcuts module ============================= .. automodule:: progressbar.shortcuts :members: :undoc-members: :show-inheritance: python-progressbar-4.3b.0/docs/progressbar.utils.rst000066400000000000000000000002161433023661000226770ustar00rootroot00000000000000progressbar.utils module ======================== .. automodule:: progressbar.utils :members: :undoc-members: :show-inheritance: python-progressbar-4.3b.0/docs/progressbar.widgets.rst000066400000000000000000000002241433023661000232040ustar00rootroot00000000000000progressbar.widgets module ========================== .. automodule:: progressbar.widgets :members: :undoc-members: :show-inheritance: python-progressbar-4.3b.0/docs/requirements.txt000066400000000000000000000000201433023661000217320ustar00rootroot00000000000000-e.[docs,tests] python-progressbar-4.3b.0/docs/usage.rst000066400000000000000000000031531433023661000203160ustar00rootroot00000000000000======== Usage ======== There are many ways to use Python Progressbar, you can see a few basic examples here but there are many more in the :doc:`examples` file. Wrapping an iterable ------------------------------------------------------------------------------ :: import time import progressbar bar = progressbar.ProgressBar() for i in bar(range(100)): time.sleep(0.02) Context wrapper ------------------------------------------------------------------------------ :: import time import progressbar with progressbar.ProgressBar(max_value=10) as bar: for i in range(10): time.sleep(0.1) bar.update(i) Combining progressbars with print output ------------------------------------------------------------------------------ :: import time import progressbar bar = progressbar.ProgressBar(redirect_stdout=True) for i in range(100): print 'Some text', i time.sleep(0.1) bar.update(i) Progressbar with unknown length ------------------------------------------------------------------------------ :: import time import progressbar bar = progressbar.ProgressBar(max_value=progressbar.UnknownLength) for i in range(20): time.sleep(0.1) bar.update(i) Bar with custom widgets ------------------------------------------------------------------------------ :: import time import progressbar bar = progressbar.ProgressBar(widgets=[ ' [', progressbar.Timer(), '] ', progressbar.Bar(), ' (', progressbar.ETA(), ') ', ]) for i in bar(range(20)): time.sleep(0.1) python-progressbar-4.3b.0/examples.py000066400000000000000000000454771433023661000177370ustar00rootroot00000000000000#!/usr/bin/python # -*- coding: utf-8 -*- import functools import random import sys import time import progressbar examples = [] def example(fn): '''Wrap the examples so they generate readable output''' @functools.wraps(fn) def wrapped(*args, **kwargs): try: sys.stdout.write('Running: %s\n' % fn.__name__) fn(*args, **kwargs) sys.stdout.write('\n') except KeyboardInterrupt: sys.stdout.write('\nSkipping example.\n\n') # Sleep a bit to make killing the script easier time.sleep(0.2) examples.append(wrapped) return wrapped @example def fast_example(): ''' Updates bar really quickly to cause flickering ''' with progressbar.ProgressBar(widgets=[progressbar.Bar()]) as bar: for i in range(100): bar.update(int(i / 10), force=True) @example def shortcut_example(): for i in progressbar.progressbar(range(10)): time.sleep(0.1) @example def prefixed_shortcut_example(): for i in progressbar.progressbar(range(10), prefix='Hi: '): time.sleep(0.1) @example def templated_shortcut_example(): for i in progressbar.progressbar(range(10), suffix='{seconds_elapsed:.1}'): time.sleep(0.1) @example def with_example_stdout_redirection(): with progressbar.ProgressBar(max_value=10, redirect_stdout=True) as p: for i in range(10): if i % 3 == 0: print('Some print statement %i' % i) # do something p.update(i) time.sleep(0.1) @example def basic_widget_example(): widgets = [progressbar.Percentage(), progressbar.Bar()] bar = progressbar.ProgressBar(widgets=widgets, max_value=10).start() for i in range(10): # do something time.sleep(0.1) bar.update(i + 1) bar.finish() @example def color_bar_example(): widgets = [ '\x1b[33mColorful example\x1b[39m', progressbar.Percentage(), progressbar.Bar(marker='\x1b[32m#\x1b[39m'), ] bar = progressbar.ProgressBar(widgets=widgets, max_value=10).start() for i in range(10): # do something time.sleep(0.1) bar.update(i + 1) bar.finish() @example def color_bar_animated_marker_example(): widgets = [ # Colored animated marker with colored fill: progressbar.Bar(marker=progressbar.AnimatedMarker( fill='x', # fill='█', fill_wrap='\x1b[32m{}\x1b[39m', marker_wrap='\x1b[31m{}\x1b[39m', )), ] bar = progressbar.ProgressBar(widgets=widgets, max_value=10).start() for i in range(10): # do something time.sleep(0.1) bar.update(i + 1) bar.finish() @example def multi_range_bar_example(): markers = [ '\x1b[32m█\x1b[39m', # Done '\x1b[33m#\x1b[39m', # Processing '\x1b[31m.\x1b[39m', # Scheduling ' ' # Not started ] widgets = [progressbar.MultiRangeBar("amounts", markers=markers)] amounts = [0] * (len(markers) - 1) + [25] with progressbar.ProgressBar(widgets=widgets, max_value=10).start() as bar: while True: incomplete_items = [ idx for idx, amount in enumerate(amounts) for i in range(amount) if idx != 0 ] if not incomplete_items: break which = random.choice(incomplete_items) amounts[which] -= 1 amounts[which - 1] += 1 bar.update(amounts=amounts, force=True) time.sleep(0.02) @example def multi_progress_bar_example(left=True): jobs = [ # Each job takes between 1 and 10 steps to complete [0, random.randint(1, 10)] for i in range(25) # 25 jobs total ] widgets = [ progressbar.Percentage(), ' ', progressbar.MultiProgressBar('jobs', fill_left=left), ] max_value = sum([total for progress, total in jobs]) with progressbar.ProgressBar(widgets=widgets, max_value=max_value) as bar: while True: incomplete_jobs = [ idx for idx, (progress, total) in enumerate(jobs) if progress < total ] if not incomplete_jobs: break which = random.choice(incomplete_jobs) jobs[which][0] += 1 progress = sum([progress for progress, total in jobs]) bar.update(progress, jobs=jobs, force=True) time.sleep(0.02) @example def granular_progress_example(): widgets = [ progressbar.GranularBar(markers=" ▏▎▍▌▋▊▉█", left='', right='|'), progressbar.GranularBar(markers=" ▁▂▃▄▅▆▇█", left='', right='|'), progressbar.GranularBar(markers=" ▖▌▛█", left='', right='|'), progressbar.GranularBar(markers=" ░▒▓█", left='', right='|'), progressbar.GranularBar(markers=" ⡀⡄⡆⡇⣇⣧⣷⣿", left='', right='|'), progressbar.GranularBar(markers=" .oO", left='', right=''), ] for i in progressbar.progressbar(list(range(100)), widgets=widgets): time.sleep(0.03) for i in progressbar.progressbar(iter(range(100)), widgets=widgets): time.sleep(0.03) @example def percentage_label_bar_example(): widgets = [progressbar.PercentageLabelBar()] bar = progressbar.ProgressBar(widgets=widgets, max_value=10).start() for i in range(10): # do something time.sleep(0.1) bar.update(i + 1) bar.finish() @example def file_transfer_example(): widgets = [ 'Test: ', progressbar.Percentage(), ' ', progressbar.Bar(marker=progressbar.RotatingMarker()), ' ', progressbar.ETA(), ' ', progressbar.FileTransferSpeed(), ] bar = progressbar.ProgressBar(widgets=widgets, max_value=1000).start() for i in range(100): # do something bar.update(10 * i + 1) bar.finish() @example def custom_file_transfer_example(): class CrazyFileTransferSpeed(progressbar.FileTransferSpeed): ''' It's bigger between 45 and 80 percent ''' def update(self, bar): if 45 < bar.percentage() < 80: return 'Bigger Now ' + progressbar.FileTransferSpeed.update( self, bar) else: return progressbar.FileTransferSpeed.update(self, bar) widgets = [ CrazyFileTransferSpeed(), ' <<<', progressbar.Bar(), '>>> ', progressbar.Percentage(), ' ', progressbar.ETA(), ] bar = progressbar.ProgressBar(widgets=widgets, max_value=1000) # maybe do something bar.start() for i in range(200): # do something bar.update(5 * i + 1) bar.finish() @example def double_bar_example(): widgets = [ progressbar.Bar('>'), ' ', progressbar.ETA(), ' ', progressbar.ReverseBar('<'), ] bar = progressbar.ProgressBar(widgets=widgets, max_value=1000).start() for i in range(100): # do something bar.update(10 * i + 1) time.sleep(0.01) bar.finish() @example def basic_file_transfer(): widgets = [ 'Test: ', progressbar.Percentage(), ' ', progressbar.Bar(marker='0', left='[', right=']'), ' ', progressbar.ETA(), ' ', progressbar.FileTransferSpeed(), ] bar = progressbar.ProgressBar(widgets=widgets, max_value=500) bar.start() # Go beyond the max_value for i in range(100, 501, 50): time.sleep(0.1) bar.update(i) bar.finish() @example def simple_progress(): bar = progressbar.ProgressBar( widgets=[progressbar.SimpleProgress()], max_value=17, ).start() for i in range(17): time.sleep(0.1) bar.update(i + 1) bar.finish() @example def basic_progress(): bar = progressbar.ProgressBar().start() for i in range(10): time.sleep(0.1) bar.update(i + 1) bar.finish() @example def progress_with_automatic_max(): # Progressbar can guess max_value automatically. bar = progressbar.ProgressBar() for i in bar(range(8)): time.sleep(0.1) @example def progress_with_unavailable_max(): # Progressbar can't guess max_value. bar = progressbar.ProgressBar(max_value=8) for i in bar((i for i in range(8))): time.sleep(0.1) @example def animated_marker(): bar = progressbar.ProgressBar( widgets=['Working: ', progressbar.AnimatedMarker()]) for i in bar((i for i in range(5))): time.sleep(0.1) @example def filling_bar_animated_marker(): bar = progressbar.ProgressBar(widgets=[ progressbar.Bar( marker=progressbar.AnimatedMarker(fill='#'), ), ]) for i in bar(range(15)): time.sleep(0.1) @example def counter_and_timer(): widgets = ['Processed: ', progressbar.Counter('Counter: %(value)05d'), ' lines (', progressbar.Timer(), ')'] bar = progressbar.ProgressBar(widgets=widgets) for i in bar((i for i in range(15))): time.sleep(0.1) @example def format_label(): widgets = [progressbar.FormatLabel( 'Processed: %(value)d lines (in: %(elapsed)s)')] bar = progressbar.ProgressBar(widgets=widgets) for i in bar((i for i in range(15))): time.sleep(0.1) @example def animated_balloons(): widgets = ['Balloon: ', progressbar.AnimatedMarker(markers='.oO@* ')] bar = progressbar.ProgressBar(widgets=widgets) for i in bar((i for i in range(24))): time.sleep(0.1) @example def animated_arrows(): # You may need python 3.x to see this correctly try: widgets = ['Arrows: ', progressbar.AnimatedMarker(markers='←↖↑↗→↘↓↙')] bar = progressbar.ProgressBar(widgets=widgets) for i in bar((i for i in range(24))): time.sleep(0.1) except UnicodeError: sys.stdout.write('Unicode error: skipping example') @example def animated_filled_arrows(): # You may need python 3.x to see this correctly try: widgets = ['Arrows: ', progressbar.AnimatedMarker(markers='◢◣◤◥')] bar = progressbar.ProgressBar(widgets=widgets) for i in bar((i for i in range(24))): time.sleep(0.1) except UnicodeError: sys.stdout.write('Unicode error: skipping example') @example def animated_wheels(): # You may need python 3.x to see this correctly try: widgets = ['Wheels: ', progressbar.AnimatedMarker(markers='◐◓◑◒')] bar = progressbar.ProgressBar(widgets=widgets) for i in bar((i for i in range(24))): time.sleep(0.1) except UnicodeError: sys.stdout.write('Unicode error: skipping example') @example def format_label_bouncer(): widgets = [ progressbar.FormatLabel('Bouncer: value %(value)d - '), progressbar.BouncingBar(), ] bar = progressbar.ProgressBar(widgets=widgets) for i in bar((i for i in range(100))): time.sleep(0.01) @example def format_label_rotating_bouncer(): widgets = [progressbar.FormatLabel('Animated Bouncer: value %(value)d - '), progressbar.BouncingBar(marker=progressbar.RotatingMarker())] bar = progressbar.ProgressBar(widgets=widgets) for i in bar((i for i in range(18))): time.sleep(0.1) @example def with_right_justify(): with progressbar.ProgressBar(max_value=10, term_width=20, left_justify=False) as progress: assert progress.term_width is not None for i in range(10): progress.update(i) @example def exceeding_maximum(): with progressbar.ProgressBar(max_value=1) as progress: try: progress.update(2) except ValueError: pass @example def reaching_maximum(): progress = progressbar.ProgressBar(max_value=1) try: progress.update(1) except RuntimeError: pass @example def stdout_redirection(): with progressbar.ProgressBar(redirect_stdout=True) as progress: print('', file=sys.stdout) progress.update(0) @example def stderr_redirection(): with progressbar.ProgressBar(redirect_stderr=True) as progress: print('', file=sys.stderr) progress.update(0) @example def negative_maximum(): try: with progressbar.ProgressBar(max_value=-1) as progress: progress.start() except ValueError: pass @example def rotating_bouncing_marker(): widgets = [progressbar.BouncingBar(marker=progressbar.RotatingMarker())] with progressbar.ProgressBar(widgets=widgets, max_value=20, term_width=10) as progress: for i in range(20): time.sleep(0.1) progress.update(i) widgets = [progressbar.BouncingBar(marker=progressbar.RotatingMarker(), fill_left=False)] with progressbar.ProgressBar(widgets=widgets, max_value=20, term_width=10) as progress: for i in range(20): time.sleep(0.1) progress.update(i) @example def incrementing_bar(): bar = progressbar.ProgressBar(widgets=[ progressbar.Percentage(), progressbar.Bar(), ], max_value=10).start() for i in range(10): # do something time.sleep(0.1) bar += 1 bar.finish() @example def increment_bar_with_output_redirection(): widgets = [ 'Test: ', progressbar.Percentage(), ' ', progressbar.Bar(marker=progressbar.RotatingMarker()), ' ', progressbar.ETA(), ' ', progressbar.FileTransferSpeed(), ] bar = progressbar.ProgressBar(widgets=widgets, max_value=100, redirect_stdout=True).start() for i in range(10): # do something time.sleep(0.01) bar += 10 print('Got', i) bar.finish() @example def eta_types_demonstration(): widgets = [ progressbar.Percentage(), ' ETA: ', progressbar.ETA(), ' Adaptive ETA: ', progressbar.AdaptiveETA(), ' Absolute ETA: ', progressbar.AbsoluteETA(), ' Transfer Speed: ', progressbar.FileTransferSpeed(), ' Adaptive Transfer Speed: ', progressbar.AdaptiveTransferSpeed(), ' ', progressbar.Bar(), ] bar = progressbar.ProgressBar(widgets=widgets, max_value=500) bar.start() for i in range(500): if i < 100: time.sleep(0.02) elif i > 400: time.sleep(0.1) else: time.sleep(0.01) bar.update(i + 1) bar.finish() @example def adaptive_eta_without_value_change(): # Testing progressbar.AdaptiveETA when the value doesn't actually change bar = progressbar.ProgressBar(widgets=[ progressbar.AdaptiveETA(), progressbar.AdaptiveTransferSpeed(), ], max_value=2, poll_interval=0.0001) bar.start() for i in range(100): bar.update(1) time.sleep(0.1) bar.finish() @example def iterator_with_max_value(): # Testing using progressbar as an iterator with a max value bar = progressbar.ProgressBar() for n in bar(iter(range(100)), 100): # iter range is a way to get an iterator in both python 2 and 3 pass @example def eta(): widgets = [ 'Test: ', progressbar.Percentage(), ' | ETA: ', progressbar.ETA(), ' | AbsoluteETA: ', progressbar.AbsoluteETA(), ' | AdaptiveETA: ', progressbar.AdaptiveETA(), ] bar = progressbar.ProgressBar(widgets=widgets, max_value=50).start() for i in range(50): time.sleep(0.1) bar.update(i + 1) bar.finish() @example def variables(): # Use progressbar.Variable to keep track of some parameter(s) during # your calculations widgets = [ progressbar.Percentage(), progressbar.Bar(), progressbar.Variable('loss'), ', ', progressbar.Variable('username', width=12, precision=12), ] with progressbar.ProgressBar(max_value=100, widgets=widgets) as bar: min_so_far = 1 for i in range(100): time.sleep(0.01) val = random.random() if val < min_so_far: min_so_far = val bar.update(i, loss=min_so_far, username='Some user') @example def user_variables(): tasks = { 'Download': [ 'SDK', 'IDE', 'Dependencies', ], 'Build': [ 'Compile', 'Link', ], 'Test': [ 'Unit tests', 'Integration tests', 'Regression tests', ], 'Deploy': [ 'Send to server', 'Restart server', ], } num_subtasks = sum(len(x) for x in tasks.values()) with progressbar.ProgressBar( prefix='{variables.task} >> {variables.subtask}', variables={'task': '--', 'subtask': '--'}, max_value=10 * num_subtasks) as bar: for tasks_name, subtasks in tasks.items(): for subtask_name in subtasks: for i in range(10): bar.update(bar.value + 1, task=tasks_name, subtask=subtask_name) time.sleep(0.1) @example def format_custom_text(): format_custom_text = progressbar.FormatCustomText( 'Spam: %(spam).1f kg, eggs: %(eggs)d', dict( spam=0.25, eggs=3, ), ) bar = progressbar.ProgressBar(widgets=[ format_custom_text, ' :: ', progressbar.Percentage(), ]) for i in bar(range(25)): format_custom_text.update_mapping(eggs=i * 2) time.sleep(0.1) @example def simple_api_example(): bar = progressbar.ProgressBar(widget_kwargs=dict(fill='█')) for i in bar(range(200)): time.sleep(0.02) @example def ETA_on_generators(): def gen(): for x in range(200): yield None widgets = [progressbar.AdaptiveETA(), ' ', progressbar.ETA(), ' ', progressbar.Timer()] bar = progressbar.ProgressBar(widgets=widgets) for i in bar(gen()): time.sleep(0.02) @example def percentage_on_generators(): def gen(): for x in range(200): yield None widgets = [progressbar.Counter(), ' ', progressbar.Percentage(), ' ', progressbar.SimpleProgress(), ' '] bar = progressbar.ProgressBar(widgets=widgets) for i in bar(gen()): time.sleep(0.02) def test(*tests): if tests: for example in examples: for test in tests: if test in example.__name__: example() break else: print('Skipping', example.__name__) else: for example in examples: example() if __name__ == '__main__': try: test(*sys.argv[1:]) except KeyboardInterrupt: sys.stdout('\nQuitting examples.\n') python-progressbar-4.3b.0/progressbar/000077500000000000000000000000001433023661000200575ustar00rootroot00000000000000python-progressbar-4.3b.0/progressbar/__about__.py000066400000000000000000000017511433023661000223430ustar00rootroot00000000000000'''Text progress bar library for Python. A text progress bar is typically used to display the progress of a long running operation, providing a visual cue that processing is underway. The ProgressBar class manages the current progress, and the format of the line is given by a number of widgets. A widget is an object that may display differently depending on the state of the progress bar. The progressbar module is very easy to use, yet very powerful. It will also automatically enable features like auto-resizing when the system supports it. ''' __title__ = 'Python Progressbar' __package_name__ = 'progressbar2' __author__ = 'Rick van Hattem (Wolph)' __description__ = ' '.join( ''' A Python Progressbar library to provide visual (yet text based) progress to long running operations. '''.strip().split() ) __email__ = 'wolph@wol.ph' __version__ = '4.3b.0' __license__ = 'BSD' __copyright__ = 'Copyright 2015 Rick van Hattem (Wolph)' __url__ = 'https://github.com/WoLpH/python-progressbar' python-progressbar-4.3b.0/progressbar/__init__.py000066400000000000000000000035601433023661000221740ustar00rootroot00000000000000from datetime import date from .__about__ import __author__ from .__about__ import __version__ from .bar import DataTransferBar from .bar import NullBar from .bar import ProgressBar from .base import UnknownLength from .shortcuts import progressbar from .utils import len_color from .utils import streams from .widgets import AbsoluteETA from .widgets import AdaptiveETA from .widgets import AdaptiveTransferSpeed from .widgets import AnimatedMarker from .widgets import Bar from .widgets import BouncingBar from .widgets import Counter from .widgets import CurrentTime from .widgets import DataSize from .widgets import DynamicMessage from .widgets import ETA from .widgets import FileTransferSpeed from .widgets import FormatCustomText from .widgets import FormatLabel from .widgets import FormatLabelBar from .widgets import GranularBar from .widgets import MultiProgressBar from .widgets import MultiRangeBar from .widgets import Percentage from .widgets import PercentageLabelBar from .widgets import ReverseBar from .widgets import RotatingMarker from .widgets import SimpleProgress from .widgets import Timer from .widgets import Variable from .widgets import VariableMixin __date__ = str(date.today()) __all__ = [ 'progressbar', 'len_color', 'streams', 'Timer', 'ETA', 'AdaptiveETA', 'AbsoluteETA', 'DataSize', 'FileTransferSpeed', 'AdaptiveTransferSpeed', 'AnimatedMarker', 'Counter', 'Percentage', 'FormatLabel', 'SimpleProgress', 'Bar', 'ReverseBar', 'BouncingBar', 'UnknownLength', 'ProgressBar', 'DataTransferBar', 'RotatingMarker', 'VariableMixin', 'MultiRangeBar', 'MultiProgressBar', 'GranularBar', 'FormatLabelBar', 'PercentageLabelBar', 'Variable', 'DynamicMessage', 'FormatCustomText', 'CurrentTime', 'NullBar', '__author__', '__version__', ] python-progressbar-4.3b.0/progressbar/bar.py000066400000000000000000001042421433023661000212000ustar00rootroot00000000000000from __future__ import annotations import abc import logging import os import sys import time import timeit import warnings from copy import deepcopy from datetime import datetime from typing import Type import math from python_utils import converters, types from . import ( base, utils, widgets, widgets as widgets_module, # Avoid name collision ) logger = logging.getLogger(__name__) # float also accepts integers and longs but we don't want an explicit union # due to type checking complexity T = float class ProgressBarMixinBase(abc.ABC): _started = False _finished = False _last_update_time: types.Optional[float] = None #: The terminal width. This should be automatically detected but will #: fall back to 80 if auto detection is not possible. term_width: int = 80 #: The widgets to render, defaults to the result of `default_widget()` widgets: types.List[widgets_module.WidgetBase] #: When going beyond the max_value, raise an error if True or silently #: ignore otherwise max_error: bool #: Prefix the progressbar with the given string prefix: types.Optional[str] #: Suffix the progressbar with the given string suffix: types.Optional[str] #: Justify to the left if `True` or the right if `False` left_justify: bool #: The default keyword arguments for the `default_widgets` if no widgets #: are configured widget_kwargs: types.Dict[str, types.Any] #: Custom length function for multibyte characters such as CJK # mypy and pyright can't agree on what the correct one is... so we'll # need to use a helper function :( # custom_len: types.Callable[['ProgressBarMixinBase', str], int] custom_len: types.Callable[[str], int] #: The time the progress bar was started initial_start_time: types.Optional[datetime] #: The interval to poll for updates in seconds if there are updates poll_interval: types.Optional[float] #: The minimum interval to poll for updates in seconds even if there are #: no updates min_poll_interval: float #: Current progress (min_value <= value <= max_value) value: T #: The minimum/start value for the progress bar min_value: T #: Maximum (and final) value. Beyond this value an error will be raised #: unless the `max_error` parameter is `False`. max_value: T | types.Type[base.UnknownLength] #: The time the progressbar reached `max_value` or when `finish()` was #: called. end_time: types.Optional[datetime] #: The time `start()` was called or iteration started. start_time: types.Optional[datetime] #: Seconds between `start_time` and last call to `update()` seconds_elapsed: float #: Extra data for widgets with persistent state. This is used by #: sampling widgets for example. Since widgets can be shared between #: multiple progressbars we need to store the state with the progressbar. extra: types.Dict[str, types.Any] def get_last_update_time(self) -> types.Optional[datetime]: if self._last_update_time: return datetime.fromtimestamp(self._last_update_time) else: return None def set_last_update_time(self, value: types.Optional[datetime]): if value: self._last_update_time = time.mktime(value.timetuple()) else: self._last_update_time = None last_update_time = property(get_last_update_time, set_last_update_time) def __init__(self, **kwargs): pass def start(self, **kwargs): self._started = True def update(self, value=None): pass def finish(self): # pragma: no cover self._finished = True def __del__(self): if not self._finished and self._started: # pragma: no cover try: self.finish() except Exception: # Never raise during cleanup. We're too late now logging.debug( 'Exception raised during ProgressBar cleanup', exc_info=True, ) def __getstate__(self): return self.__dict__ def data(self) -> types.Dict[str, types.Any]: raise NotImplementedError() class ProgressBarBase(types.Iterable, ProgressBarMixinBase): pass class DefaultFdMixin(ProgressBarMixinBase): # The file descriptor to write to. Defaults to `sys.stderr` fd: base.IO = sys.stderr #: Set the terminal to be ANSI compatible. If a terminal is ANSI #: compatible we will automatically enable `colors` and disable #: `line_breaks`. is_ansi_terminal: bool = False #: Whether to print line breaks. This is useful for logging the #: progressbar. When disabled the current line is overwritten. line_breaks: bool = True #: Enable or disable colors. Defaults to auto detection enable_colors: bool = False def __init__( self, fd: base.IO = sys.stderr, is_terminal: bool | None = None, line_breaks: bool | None = None, enable_colors: bool | None = None, **kwargs, ): if fd is sys.stdout: fd = utils.streams.original_stdout elif fd is sys.stderr: fd = utils.streams.original_stderr self.fd = fd self.is_ansi_terminal = utils.is_ansi_terminal(fd) # Check if this is an interactive terminal self.is_terminal = utils.is_terminal( fd, is_terminal or self.is_ansi_terminal ) # Check if it should overwrite the current line (suitable for # iteractive terminals) or write line breaks (suitable for log files) if line_breaks is None: line_breaks = utils.env_flag( 'PROGRESSBAR_LINE_BREAKS', not self.is_terminal ) self.line_breaks = bool(line_breaks) # Check if ANSI escape characters are enabled (suitable for iteractive # terminals), or should be stripped off (suitable for log files) if enable_colors is None: enable_colors = utils.env_flag( 'PROGRESSBAR_ENABLE_COLORS', self.is_ansi_terminal ) self.enable_colors = bool(enable_colors) ProgressBarMixinBase.__init__(self, **kwargs) def update(self, *args, **kwargs): ProgressBarMixinBase.update(self, *args, **kwargs) line: str = converters.to_unicode(self._format_line()) if not self.enable_colors: line = utils.no_color(line) if self.line_breaks: line = line.rstrip() + '\n' else: line = '\r' + line try: # pragma: no cover self.fd.write(line) except UnicodeEncodeError: # pragma: no cover self.fd.write(line.encode('ascii', 'replace')) def finish(self, *args, **kwargs): # pragma: no cover if self._finished: return end = kwargs.pop('end', '\n') ProgressBarMixinBase.finish(self, *args, **kwargs) if end and not self.line_breaks: self.fd.write(end) self.fd.flush() def _format_line(self): 'Joins the widgets and justifies the line' widgets = ''.join(self._to_unicode(self._format_widgets())) if self.left_justify: return widgets.ljust(self.term_width) else: return widgets.rjust(self.term_width) def _format_widgets(self): result = [] expanding = [] width = self.term_width data = self.data() for index, widget in enumerate(self.widgets): if isinstance( widget, widgets.WidgetBase ) and not widget.check_size(self): continue elif isinstance(widget, widgets.AutoWidthWidgetBase): result.append(widget) expanding.insert(0, index) elif isinstance(widget, str): result.append(widget) width -= self.custom_len(widget) # type: ignore else: widget_output = converters.to_unicode(widget(self, data)) result.append(widget_output) width -= self.custom_len(widget_output) # type: ignore count = len(expanding) while expanding: portion = max(int(math.ceil(width * 1.0 / count)), 0) index = expanding.pop() widget = result[index] count -= 1 widget_output = widget(self, data, portion) width -= self.custom_len(widget_output) # type: ignore result[index] = widget_output return result @classmethod def _to_unicode(cls, args): for arg in args: yield converters.to_unicode(arg) class ResizableMixin(ProgressBarMixinBase): def __init__(self, term_width: int | None = None, **kwargs): ProgressBarMixinBase.__init__(self, **kwargs) self.signal_set = False if term_width: self.term_width = term_width else: # pragma: no cover try: self._handle_resize() import signal self._prev_handle = signal.getsignal(signal.SIGWINCH) signal.signal(signal.SIGWINCH, self._handle_resize) self.signal_set = True except Exception: pass def _handle_resize(self, signum=None, frame=None): 'Tries to catch resize signals sent from the terminal.' w, h = utils.get_terminal_size() self.term_width = w def finish(self): # pragma: no cover ProgressBarMixinBase.finish(self) if self.signal_set: try: import signal signal.signal(signal.SIGWINCH, self._prev_handle) except Exception: # pragma no cover pass class StdRedirectMixin(DefaultFdMixin): redirect_stderr: bool = False redirect_stdout: bool = False stdout: utils.WrappingIO | base.IO stderr: utils.WrappingIO | base.IO _stdout: base.IO _stderr: base.IO def __init__( self, redirect_stderr: bool = False, redirect_stdout: bool = False, **kwargs, ): DefaultFdMixin.__init__(self, **kwargs) self.redirect_stderr = redirect_stderr self.redirect_stdout = redirect_stdout self._stdout = self.stdout = sys.stdout self._stderr = self.stderr = sys.stderr def start(self, *args, **kwargs): if self.redirect_stdout: utils.streams.wrap_stdout() if self.redirect_stderr: utils.streams.wrap_stderr() self._stdout = utils.streams.original_stdout self._stderr = utils.streams.original_stderr self.stdout = utils.streams.stdout self.stderr = utils.streams.stderr utils.streams.start_capturing(self) DefaultFdMixin.start(self, *args, **kwargs) def update(self, value: types.Optional[float] = None): if not self.line_breaks and utils.streams.needs_clear(): self.fd.write('\r' + ' ' * self.term_width + '\r') utils.streams.flush() DefaultFdMixin.update(self, value=value) def finish(self, end='\n'): DefaultFdMixin.finish(self, end=end) utils.streams.stop_capturing(self) if self.redirect_stdout: utils.streams.unwrap_stdout() if self.redirect_stderr: utils.streams.unwrap_stderr() class ProgressBar( StdRedirectMixin, ResizableMixin, ProgressBarBase, ): '''The ProgressBar class which updates and prints the bar. Args: min_value (int): The minimum/start value for the progress bar max_value (int): The maximum/end value for the progress bar. Defaults to `_DEFAULT_MAXVAL` widgets (list): The widgets to render, defaults to the result of `default_widget()` left_justify (bool): Justify to the left if `True` or the right if `False` initial_value (int): The value to start with poll_interval (float): The update interval in seconds. Note that if your widgets include timers or animations, the actual interval may be smaller (faster updates). Also note that updates never happens faster than `min_poll_interval` which can be used for reduced output in logs min_poll_interval (float): The minimum update interval in seconds. The bar will _not_ be updated faster than this, despite changes in the progress, unless `force=True`. This is limited to be at least `_MINIMUM_UPDATE_INTERVAL`. If available, it is also bound by the environment variable PROGRESSBAR_MINIMUM_UPDATE_INTERVAL widget_kwargs (dict): The default keyword arguments for widgets custom_len (function): Method to override how the line width is calculated. When using non-latin characters the width calculation might be off by default max_error (bool): When True the progressbar will raise an error if it goes beyond it's set max_value. Otherwise the max_value is simply raised when needed prefix (str): Prefix the progressbar with the given string suffix (str): Prefix the progressbar with the given string variables (dict): User-defined variables variables that can be used from a label using `format='{variables.my_var}'`. These values can be updated using `bar.update(my_var='newValue')` This can also be used to set initial values for variables' widgets A common way of using it is like: >>> progress = ProgressBar().start() >>> for i in range(100): ... progress.update(i + 1) ... # do something ... >>> progress.finish() You can also use a ProgressBar as an iterator: >>> progress = ProgressBar() >>> some_iterable = range(100) >>> for i in progress(some_iterable): ... # do something ... pass ... Since the progress bar is incredibly customizable you can specify different widgets of any type in any order. You can even write your own widgets! However, since there are already a good number of widgets you should probably play around with them before moving on to create your own widgets. The term_width parameter represents the current terminal width. If the parameter is set to an integer then the progress bar will use that, otherwise it will attempt to determine the terminal width falling back to 80 columns if the width cannot be determined. When implementing a widget's update method you are passed a reference to the current progress bar. As a result, you have access to the ProgressBar's methods and attributes. Although there is nothing preventing you from changing the ProgressBar you should treat it as read only. ''' _iterable: types.Optional[types.Iterator] _DEFAULT_MAXVAL: Type[base.UnknownLength] = base.UnknownLength # update every 50 milliseconds (up to a 20 times per second) _MINIMUM_UPDATE_INTERVAL: float = 0.050 _last_update_time: types.Optional[float] = None def __init__( self, min_value: T = 0, max_value: T | types.Type[base.UnknownLength] | None = None, widgets: types.Optional[types.List[widgets_module.WidgetBase]] = None, left_justify: bool = True, initial_value: T = 0, poll_interval: types.Optional[float] = None, widget_kwargs: types.Optional[types.Dict[str, types.Any]] = None, custom_len: types.Callable[[str], int] = utils.len_color, max_error=True, prefix=None, suffix=None, variables=None, min_poll_interval=None, **kwargs, ): ''' Initializes a progress bar with sane defaults ''' StdRedirectMixin.__init__(self, **kwargs) ResizableMixin.__init__(self, **kwargs) ProgressBarBase.__init__(self, **kwargs) if not max_value and kwargs.get('maxval') is not None: warnings.warn( 'The usage of `maxval` is deprecated, please use ' '`max_value` instead', DeprecationWarning, ) max_value = kwargs.get('maxval') if not poll_interval and kwargs.get('poll'): warnings.warn( 'The usage of `poll` is deprecated, please use ' '`poll_interval` instead', DeprecationWarning, ) poll_interval = kwargs.get('poll') if max_value: # mypy doesn't understand that a boolean check excludes # `UnknownLength` if min_value > max_value: # type: ignore raise ValueError( 'Max value needs to be bigger than the min ' 'value' ) self.min_value = min_value # Legacy issue, `max_value` can be `None` before execution. After # that it either has a value or is `UnknownLength` self.max_value = max_value # type: ignore self.max_error = max_error # Only copy the widget if it's safe to copy. Most widgets are so we # assume this to be true self.widgets = [] for widget in widgets or []: if getattr(widget, 'copy', True): widget = deepcopy(widget) self.widgets.append(widget) self.prefix = prefix self.suffix = suffix self.widget_kwargs = widget_kwargs or {} self.left_justify = left_justify self.value = initial_value self._iterable = None self.custom_len = custom_len # type: ignore self.initial_start_time = kwargs.get('start_time') self.init() # Convert a given timedelta to a floating point number as internal # interval. We're not using timedelta's internally for two reasons: # 1. Backwards compatibility (most important one) # 2. Performance. Even though the amount of time it takes to compare a # timedelta with a float versus a float directly is negligible, this # comparison is run for _every_ update. With billions of updates # (downloading a 1GiB file for example) this adds up. poll_interval = utils.deltas_to_seconds(poll_interval, default=None) min_poll_interval = utils.deltas_to_seconds( min_poll_interval, default=None ) self._MINIMUM_UPDATE_INTERVAL = ( utils.deltas_to_seconds(self._MINIMUM_UPDATE_INTERVAL) or self._MINIMUM_UPDATE_INTERVAL ) # Note that the _MINIMUM_UPDATE_INTERVAL sets the minimum in case of # low values. self.poll_interval = poll_interval self.min_poll_interval = max( min_poll_interval or self._MINIMUM_UPDATE_INTERVAL, self._MINIMUM_UPDATE_INTERVAL, float(os.environ.get('PROGRESSBAR_MINIMUM_UPDATE_INTERVAL', 0)), ) # type: ignore # A dictionary of names that can be used by Variable and FormatWidget self.variables = utils.AttributeDict(variables or {}) for widget in self.widgets: if isinstance(widget, widgets_module.VariableMixin): if widget.name not in self.variables: self.variables[widget.name] = None @property def dynamic_messages(self): # pragma: no cover return self.variables @dynamic_messages.setter def dynamic_messages(self, value): # pragma: no cover self.variables = value def init(self): ''' (re)initialize values to original state so the progressbar can be used (again) ''' self.previous_value = None self.last_update_time = None self.start_time = None self.updates = 0 self.end_time = None self.extra = dict() self._last_update_timer = timeit.default_timer() @property def percentage(self): '''Return current percentage, returns None if no max_value is given >>> progress = ProgressBar() >>> progress.max_value = 10 >>> progress.min_value = 0 >>> progress.value = 0 >>> progress.percentage 0.0 >>> >>> progress.value = 1 >>> progress.percentage 10.0 >>> progress.value = 10 >>> progress.percentage 100.0 >>> progress.min_value = -10 >>> progress.percentage 100.0 >>> progress.value = 0 >>> progress.percentage 50.0 >>> progress.value = 5 >>> progress.percentage 75.0 >>> progress.value = -5 >>> progress.percentage 25.0 >>> progress.max_value = None >>> progress.percentage ''' if self.max_value is None or self.max_value is base.UnknownLength: return None elif self.max_value: todo = self.value - self.min_value total = self.max_value - self.min_value # type: ignore percentage = 100.0 * todo / total else: percentage = 100.0 return percentage def data(self) -> types.Dict[str, types.Any]: ''' Returns: dict: - `max_value`: The maximum value (can be None with iterators) - `start_time`: Start time of the widget - `last_update_time`: Last update time of the widget - `end_time`: End time of the widget - `value`: The current value - `previous_value`: The previous value - `updates`: The total update count - `total_seconds_elapsed`: The seconds since the bar started - `seconds_elapsed`: The seconds since the bar started modulo 60 - `minutes_elapsed`: The minutes since the bar started modulo 60 - `hours_elapsed`: The hours since the bar started modulo 24 - `days_elapsed`: The hours since the bar started - `time_elapsed`: The raw elapsed `datetime.timedelta` object - `percentage`: Percentage as a float or `None` if no max_value is available - `dynamic_messages`: Deprecated, use `variables` instead. - `variables`: Dictionary of user-defined variables for the :py:class:`~progressbar.widgets.Variable`'s ''' self._last_update_time = time.time() self._last_update_timer = timeit.default_timer() elapsed = self.last_update_time - self.start_time # type: ignore # For Python 2.7 and higher we have _`timedelta.total_seconds`, but we # want to support older versions as well total_seconds_elapsed = utils.deltas_to_seconds(elapsed) return dict( # The maximum value (can be None with iterators) max_value=self.max_value, # Start time of the widget start_time=self.start_time, # Last update time of the widget last_update_time=self.last_update_time, # End time of the widget end_time=self.end_time, # The current value value=self.value, # The previous value previous_value=self.previous_value, # The total update count updates=self.updates, # The seconds since the bar started total_seconds_elapsed=total_seconds_elapsed, # The seconds since the bar started modulo 60 seconds_elapsed=(elapsed.seconds % 60) + (elapsed.microseconds / 1000000.0), # The minutes since the bar started modulo 60 minutes_elapsed=(elapsed.seconds / 60) % 60, # The hours since the bar started modulo 24 hours_elapsed=(elapsed.seconds / (60 * 60)) % 24, # The hours since the bar started days_elapsed=(elapsed.seconds / (60 * 60 * 24)), # The raw elapsed `datetime.timedelta` object time_elapsed=elapsed, # Percentage as a float or `None` if no max_value is available percentage=self.percentage, # Dictionary of user-defined # :py:class:`progressbar.widgets.Variable`'s variables=self.variables, # Deprecated alias for `variables` dynamic_messages=self.variables, ) def default_widgets(self): if self.max_value: return [ widgets.Percentage(**self.widget_kwargs), ' ', widgets.SimpleProgress( format='(%s)' % widgets.SimpleProgress.DEFAULT_FORMAT, **self.widget_kwargs, ), ' ', widgets.Bar(**self.widget_kwargs), ' ', widgets.Timer(**self.widget_kwargs), ' ', widgets.AdaptiveETA(**self.widget_kwargs), ] else: return [ widgets.AnimatedMarker(**self.widget_kwargs), ' ', widgets.BouncingBar(**self.widget_kwargs), ' ', widgets.Counter(**self.widget_kwargs), ' ', widgets.Timer(**self.widget_kwargs), ] def __call__(self, iterable, max_value=None): 'Use a ProgressBar to iterate through an iterable' if max_value is not None: self.max_value = max_value elif self.max_value is None: try: self.max_value = len(iterable) except TypeError: # pragma: no cover self.max_value = base.UnknownLength self._iterable = iter(iterable) return self def __iter__(self): return self def __next__(self): try: if self._iterable is None: # pragma: no cover value = self.value else: value = next(self._iterable) if self.start_time is None: self.start() else: self.update(self.value + 1) return value except StopIteration: self.finish() raise except GeneratorExit: # pragma: no cover self.finish(dirty=True) raise def __exit__(self, exc_type, exc_value, traceback): self.finish(dirty=bool(exc_type)) def __enter__(self): return self # Create an alias so that Python 2.x won't complain about not being # an iterator. next = __next__ def __iadd__(self, value): 'Updates the ProgressBar by adding a new value.' return self.increment(value) def increment(self, value=1, *args, **kwargs): self.update(self.value + value, *args, **kwargs) return self def _needs_update(self): 'Returns whether the ProgressBar should redraw the line.' delta = timeit.default_timer() - self._last_update_timer if delta < self.min_poll_interval: # Prevent updating too often return False elif self.poll_interval and delta > self.poll_interval: # Needs to redraw timers and animations return True # Update if value increment is not large enough to # add more bars to progressbar (according to current # terminal width) try: divisor: float = self.max_value / self.term_width # type: ignore value_divisor = self.value // divisor # type: ignore pvalue_divisor = self.previous_value // divisor # type: ignore if value_divisor != pvalue_divisor: return True except Exception: # ignore any division errors pass # No need to redraw yet return False def update(self, value=None, force=False, **kwargs): 'Updates the ProgressBar to a new value.' if self.start_time is None: self.start() return self.update(value, force=force, **kwargs) if value is not None and value is not base.UnknownLength: if self.max_value is base.UnknownLength: # Can't compare against unknown lengths so just update pass elif self.min_value <= value <= self.max_value: # pragma: no cover # Correct value, let's accept pass elif self.max_error: raise ValueError( 'Value %s is out of range, should be between %s and %s' % (value, self.min_value, self.max_value) ) else: self.max_value = value self.previous_value = self.value self.value = value # Save the updated values for dynamic messages variables_changed = False for key in kwargs: if key not in self.variables: raise TypeError( 'update() got an unexpected keyword ' + 'argument {0!r}'.format(key) ) elif self.variables[key] != kwargs[key]: self.variables[key] = kwargs[key] variables_changed = True if self._needs_update() or variables_changed or force: self.updates += 1 ResizableMixin.update(self, value=value) ProgressBarBase.update(self, value=value) StdRedirectMixin.update(self, value=value) # Only flush if something was actually written self.fd.flush() def start(self, max_value=None, init=True): '''Starts measuring time, and prints the bar at 0%. It returns self so you can use it like this: Args: max_value (int): The maximum value of the progressbar reinit (bool): Initialize the progressbar, this is useful if you wish to reuse the same progressbar but can be disabled if data needs to be passed along to the next run >>> pbar = ProgressBar().start() >>> for i in range(100): ... # do something ... pbar.update(i+1) ... >>> pbar.finish() ''' if init: self.init() # Prevent multiple starts if self.start_time is not None: # pragma: no cover return self if max_value is not None: self.max_value = max_value if self.max_value is None: self.max_value = self._DEFAULT_MAXVAL StdRedirectMixin.start(self, max_value=max_value) ResizableMixin.start(self, max_value=max_value) ProgressBarBase.start(self, max_value=max_value) # Constructing the default widgets is only done when we know max_value if not self.widgets: self.widgets = self.default_widgets() if self.prefix: self.widgets.insert( 0, widgets.FormatLabel(self.prefix, new_style=True) ) # Unset the prefix variable after applying so an extra start() # won't keep copying it self.prefix = None if self.suffix: self.widgets.append( widgets.FormatLabel(self.suffix, new_style=True) ) # Unset the suffix variable after applying so an extra start() # won't keep copying it self.suffix = None for widget in self.widgets: interval: int | float | None = utils.deltas_to_seconds( getattr(widget, 'INTERVAL', None), default=None, ) if interval is not None: self.poll_interval = min( self.poll_interval or interval, interval, ) self.num_intervals = max(100, self.term_width) # The `next_update` is kept for compatibility with external libs: # https://github.com/WoLpH/python-progressbar/issues/207 self.next_update = 0 if ( self.max_value is not base.UnknownLength and self.max_value is not None and self.max_value < 0 # type: ignore ): raise ValueError('max_value out of range, got %r' % self.max_value) now = datetime.now() self.start_time = self.initial_start_time or now self.last_update_time = now self._last_update_timer = timeit.default_timer() self.update(self.min_value, force=True) return self def finish(self, end='\n', dirty=False): ''' Puts the ProgressBar bar in the finished state. Also flushes and disables output buffering if this was the last progressbar running. Args: end (str): The string to end the progressbar with, defaults to a newline dirty (bool): When True the progressbar kept the current state and won't be set to 100 percent ''' if not dirty: self.end_time = datetime.now() self.update(self.max_value, force=True) StdRedirectMixin.finish(self, end=end) ResizableMixin.finish(self) ProgressBarBase.finish(self) @property def currval(self): ''' Legacy method to make progressbar-2 compatible with the original progressbar package ''' warnings.warn( 'The usage of `currval` is deprecated, please use ' '`value` instead', DeprecationWarning, ) return self.value class DataTransferBar(ProgressBar): '''A progress bar with sensible defaults for downloads etc. This assumes that the values its given are numbers of bytes. ''' def default_widgets(self): if self.max_value: return [ widgets.Percentage(), ' of ', widgets.DataSize('max_value'), ' ', widgets.Bar(), ' ', widgets.Timer(), ' ', widgets.AdaptiveETA(), ] else: return [ widgets.AnimatedMarker(), ' ', widgets.DataSize(), ' ', widgets.Timer(), ] class NullBar(ProgressBar): ''' Progress bar that does absolutely nothing. Useful for single verbosity flags ''' def start(self, *args, **kwargs): return self def update(self, *args, **kwargs): return self def finish(self, *args, **kwargs): return self python-progressbar-4.3b.0/progressbar/base.py000066400000000000000000000010621433023661000213420ustar00rootroot00000000000000# -*- mode: python; coding: utf-8 -*- from python_utils import types class FalseMeta(type): def __bool__(self): # pragma: no cover return False def __cmp__(self, other): # pragma: no cover return -1 __nonzero__ = __bool__ class UnknownLength(metaclass=FalseMeta): pass class Undefined(metaclass=FalseMeta): pass try: # pragma: no cover IO = types.IO # type: ignore TextIO = types.TextIO # type: ignore except AttributeError: from typing.io import IO, TextIO # type: ignore assert IO assert TextIO python-progressbar-4.3b.0/progressbar/py.typed000066400000000000000000000000001433023661000215440ustar00rootroot00000000000000python-progressbar-4.3b.0/progressbar/shortcuts.py000066400000000000000000000006261433023661000224730ustar00rootroot00000000000000from . import bar def progressbar( iterator, min_value=0, max_value=None, widgets=None, prefix=None, suffix=None, **kwargs ): progressbar = bar.ProgressBar( min_value=min_value, max_value=max_value, widgets=widgets, prefix=prefix, suffix=suffix, **kwargs ) for result in progressbar(iterator): yield result python-progressbar-4.3b.0/progressbar/utils.py000066400000000000000000000357341433023661000216050ustar00rootroot00000000000000from __future__ import annotations import atexit import datetime import io import logging import os import re import sys from types import TracebackType from typing import Iterable, Iterator, Type from python_utils import types from python_utils.converters import scale_1024 from python_utils.terminal import get_terminal_size from python_utils.time import epoch, format_time, timedelta_to_seconds from progressbar import base if types.TYPE_CHECKING: from .bar import ProgressBar, ProgressBarMixinBase assert timedelta_to_seconds assert get_terminal_size assert format_time assert scale_1024 assert epoch StringT = types.TypeVar('StringT', bound=types.StringTypes) ANSI_TERMS = ( '([xe]|bv)term', '(sco)?ansi', 'cygwin', 'konsole', 'linux', 'rxvt', 'screen', 'tmux', 'vt(10[02]|220|320)', ) ANSI_TERM_RE = re.compile('^({})'.format('|'.join(ANSI_TERMS)), re.IGNORECASE) def is_ansi_terminal( fd: base.IO, is_terminal: bool | None = None ) -> bool: # pragma: no cover if is_terminal is None: # Jupyter Notebooks define this variable and support progress bars if 'JPY_PARENT_PID' in os.environ: is_terminal = True # This works for newer versions of pycharm only. older versions there # is no way to check. elif os.environ.get('PYCHARM_HOSTED') == '1' and not os.environ.get( 'PYTEST_CURRENT_TEST' ): is_terminal = True if is_terminal is None: # check if we are writing to a terminal or not. typically a file object # is going to return False if the instance has been overridden and # isatty has not been defined we have no way of knowing so we will not # use ansi. ansi terminals will typically define one of the 2 # environment variables. try: is_tty = fd.isatty() # Try and match any of the huge amount of Linux/Unix ANSI consoles if is_tty and ANSI_TERM_RE.match(os.environ.get('TERM', '')): is_terminal = True # ANSICON is a Windows ANSI compatible console elif 'ANSICON' in os.environ: is_terminal = True else: is_terminal = None except Exception: is_terminal = False return bool(is_terminal) def is_terminal(fd: base.IO, is_terminal: bool | None = None) -> bool: if is_terminal is None: # Full ansi support encompasses what we expect from a terminal is_terminal = is_ansi_terminal(fd) or None if is_terminal is None: # Allow a environment variable override is_terminal = env_flag('PROGRESSBAR_IS_TERMINAL', None) if is_terminal is None: # pragma: no cover # Bare except because a lot can go wrong on different systems. If we do # get a TTY we know this is a valid terminal try: is_terminal = fd.isatty() except Exception: is_terminal = False return bool(is_terminal) def deltas_to_seconds( *deltas, default: types.Optional[types.Type[ValueError]] = ValueError, ) -> int | float | None: ''' Convert timedeltas and seconds as int to seconds as float while coalescing >>> deltas_to_seconds(datetime.timedelta(seconds=1, milliseconds=234)) 1.234 >>> deltas_to_seconds(123) 123.0 >>> deltas_to_seconds(1.234) 1.234 >>> deltas_to_seconds(None, 1.234) 1.234 >>> deltas_to_seconds(0, 1.234) 0.0 >>> deltas_to_seconds() Traceback (most recent call last): ... ValueError: No valid deltas passed to `deltas_to_seconds` >>> deltas_to_seconds(None) Traceback (most recent call last): ... ValueError: No valid deltas passed to `deltas_to_seconds` >>> deltas_to_seconds(default=0.0) 0.0 ''' for delta in deltas: if delta is None: continue if isinstance(delta, datetime.timedelta): return timedelta_to_seconds(delta) elif not isinstance(delta, float): return float(delta) else: return delta if default is ValueError: raise ValueError('No valid deltas passed to `deltas_to_seconds`') else: # mypy doesn't understand the `default is ValueError` check return default # type: ignore def no_color(value: StringT) -> StringT: ''' Return the `value` without ANSI escape codes >>> no_color(b'\u001b[1234]abc') == b'abc' True >>> str(no_color(u'\u001b[1234]abc')) 'abc' >>> str(no_color('\u001b[1234]abc')) 'abc' ''' if isinstance(value, bytes): pattern: bytes = '\\\u001b\\[.*?[@-~]'.encode() return re.sub(pattern, b'', value) # type: ignore else: return re.sub(u'\x1b\\[.*?[@-~]', '', value) # type: ignore def len_color(value: types.StringTypes) -> int: ''' Return the length of `value` without ANSI escape codes >>> len_color(b'\u001b[1234]abc') 3 >>> len_color(u'\u001b[1234]abc') 3 >>> len_color('\u001b[1234]abc') 3 ''' return len(no_color(value)) def env_flag(name: str, default: bool | None = None) -> bool | None: ''' Accepts environt variables formatted as y/n, yes/no, 1/0, true/false, on/off, and returns it as a boolean If the environment variable is not defined, or has an unknown value, returns `default` ''' v = os.getenv(name) if v and v.lower() in ('y', 'yes', 't', 'true', 'on', '1'): return True if v and v.lower() in ('n', 'no', 'f', 'false', 'off', '0'): return False return default class WrappingIO: buffer: io.StringIO target: base.IO capturing: bool listeners: set needs_clear: bool = False def __init__( self, target: base.IO, capturing: bool = False, listeners: types.Optional[types.Set[ProgressBar]] = None, ) -> None: self.buffer = io.StringIO() self.target = target self.capturing = capturing self.listeners = listeners or set() self.needs_clear = False def write(self, value: str) -> int: ret = 0 if self.capturing: ret += self.buffer.write(value) if '\n' in value: # pragma: no branch self.needs_clear = True for listener in self.listeners: # pragma: no branch listener.update() else: ret += self.target.write(value) if '\n' in value: # pragma: no branch self.flush_target() return ret def flush(self) -> None: self.buffer.flush() def _flush(self) -> None: value = self.buffer.getvalue() if value: self.flush() self.target.write(value) self.buffer.seek(0) self.buffer.truncate(0) self.needs_clear = False # when explicitly flushing, always flush the target as well self.flush_target() def flush_target(self) -> None: # pragma: no cover if not self.target.closed and getattr(self.target, 'flush'): self.target.flush() def __enter__(self) -> WrappingIO: return self def fileno(self) -> int: return self.target.fileno() def isatty(self) -> bool: return self.target.isatty() def read(self, n: int = -1) -> str: return self.target.read(n) def readable(self) -> bool: return self.target.readable() def readline(self, limit: int = -1) -> str: return self.target.readline(limit) def readlines(self, hint: int = -1) -> list[str]: return self.target.readlines(hint) def seek(self, offset: int, whence: int = os.SEEK_SET) -> int: return self.target.seek(offset, whence) def seekable(self) -> bool: return self.target.seekable() def tell(self) -> int: return self.target.tell() def truncate(self, size: types.Optional[int] = None) -> int: return self.target.truncate(size) def writable(self) -> bool: return self.target.writable() def writelines(self, lines: Iterable[str]) -> None: return self.target.writelines(lines) def close(self) -> None: self.flush() self.target.close() def __next__(self) -> str: return self.target.__next__() def __iter__(self) -> Iterator[str]: return self.target.__iter__() def __exit__( self, __t: Type[BaseException] | None, __value: BaseException | None, __traceback: TracebackType | None, ) -> None: self.close() class StreamWrapper: '''Wrap stdout and stderr globally''' stdout: base.TextIO | WrappingIO stderr: base.TextIO | WrappingIO original_excepthook: types.Callable[ [ types.Type[BaseException], BaseException, TracebackType | None, ], None, ] # original_excepthook: types.Callable[ # [ # types.Type[BaseException], # BaseException, TracebackType | None, # ], None] | None wrapped_stdout: int = 0 wrapped_stderr: int = 0 wrapped_excepthook: int = 0 capturing: int = 0 listeners: set def __init__(self): self.stdout = self.original_stdout = sys.stdout self.stderr = self.original_stderr = sys.stderr self.original_excepthook = sys.excepthook self.wrapped_stdout = 0 self.wrapped_stderr = 0 self.wrapped_excepthook = 0 self.capturing = 0 self.listeners = set() if env_flag('WRAP_STDOUT', default=False): # pragma: no cover self.wrap_stdout() if env_flag('WRAP_STDERR', default=False): # pragma: no cover self.wrap_stderr() def start_capturing(self, bar: ProgressBarMixinBase | None = None) -> None: if bar: # pragma: no branch self.listeners.add(bar) self.capturing += 1 self.update_capturing() def stop_capturing(self, bar: ProgressBarMixinBase | None = None) -> None: if bar: # pragma: no branch try: self.listeners.remove(bar) except KeyError: pass self.capturing -= 1 self.update_capturing() def update_capturing(self) -> None: # pragma: no cover if isinstance(self.stdout, WrappingIO): self.stdout.capturing = self.capturing > 0 if isinstance(self.stderr, WrappingIO): self.stderr.capturing = self.capturing > 0 if self.capturing <= 0: self.flush() def wrap(self, stdout: bool = False, stderr: bool = False) -> None: if stdout: self.wrap_stdout() if stderr: self.wrap_stderr() def wrap_stdout(self) -> WrappingIO: self.wrap_excepthook() if not self.wrapped_stdout: self.stdout = sys.stdout = WrappingIO( # type: ignore self.original_stdout, listeners=self.listeners ) self.wrapped_stdout += 1 return sys.stdout # type: ignore def wrap_stderr(self) -> WrappingIO: self.wrap_excepthook() if not self.wrapped_stderr: self.stderr = sys.stderr = WrappingIO( # type: ignore self.original_stderr, listeners=self.listeners ) self.wrapped_stderr += 1 return sys.stderr # type: ignore def unwrap_excepthook(self) -> None: if self.wrapped_excepthook: self.wrapped_excepthook -= 1 sys.excepthook = self.original_excepthook def wrap_excepthook(self) -> None: if not self.wrapped_excepthook: logger.debug('wrapping excepthook') self.wrapped_excepthook += 1 sys.excepthook = self.excepthook def unwrap(self, stdout: bool = False, stderr: bool = False) -> None: if stdout: self.unwrap_stdout() if stderr: self.unwrap_stderr() def unwrap_stdout(self) -> None: if self.wrapped_stdout > 1: self.wrapped_stdout -= 1 else: sys.stdout = self.original_stdout self.wrapped_stdout = 0 def unwrap_stderr(self) -> None: if self.wrapped_stderr > 1: self.wrapped_stderr -= 1 else: sys.stderr = self.original_stderr self.wrapped_stderr = 0 def needs_clear(self) -> bool: # pragma: no cover stdout_needs_clear = getattr(self.stdout, 'needs_clear', False) stderr_needs_clear = getattr(self.stderr, 'needs_clear', False) return stderr_needs_clear or stdout_needs_clear def flush(self) -> None: if self.wrapped_stdout: # pragma: no branch if isinstance(self.stdout, WrappingIO): # pragma: no branch try: self.stdout._flush() except io.UnsupportedOperation: # pragma: no cover self.wrapped_stdout = False logger.warning( 'Disabling stdout redirection, %r is not seekable', sys.stdout, ) if self.wrapped_stderr: # pragma: no branch if isinstance(self.stderr, WrappingIO): # pragma: no branch try: self.stderr._flush() except io.UnsupportedOperation: # pragma: no cover self.wrapped_stderr = False logger.warning( 'Disabling stderr redirection, %r is not seekable', sys.stderr, ) def excepthook(self, exc_type, exc_value, exc_traceback): self.original_excepthook(exc_type, exc_value, exc_traceback) self.flush() class AttributeDict(dict): ''' A dict that can be accessed with .attribute >>> attrs = AttributeDict(spam=123) # Reading >>> attrs['spam'] 123 >>> attrs.spam 123 # Read after update using attribute >>> attrs.spam = 456 >>> attrs['spam'] 456 >>> attrs.spam 456 # Read after update using dict access >>> attrs['spam'] = 123 >>> attrs['spam'] 123 >>> attrs.spam 123 # Read after update using dict access >>> del attrs.spam >>> attrs['spam'] Traceback (most recent call last): ... KeyError: 'spam' >>> attrs.spam Traceback (most recent call last): ... AttributeError: No such attribute: spam >>> del attrs.spam Traceback (most recent call last): ... AttributeError: No such attribute: spam ''' def __getattr__(self, name: str) -> int: if name in self: return self[name] else: raise AttributeError("No such attribute: " + name) def __setattr__(self, name: str, value: int) -> None: self[name] = value def __delattr__(self, name: str) -> None: if name in self: del self[name] else: raise AttributeError("No such attribute: " + name) logger = logging.getLogger(__name__) streams = StreamWrapper() atexit.register(streams.flush) python-progressbar-4.3b.0/progressbar/widgets.py000066400000000000000000001175051433023661000221100ustar00rootroot00000000000000# -*- coding: utf-8 -*- from __future__ import annotations import abc import datetime import functools import pprint import sys import typing from python_utils import converters, types from . import base, utils if types.TYPE_CHECKING: from .bar import ProgressBarMixinBase MAX_DATE = datetime.date.max MAX_TIME = datetime.time.max MAX_DATETIME = datetime.datetime.max Data = types.Dict[str, types.Any] FormatString = typing.Optional[str] def string_or_lambda(input_): if isinstance(input_, str): def render_input(progress, data, width): return input_ % data return render_input else: return input_ def create_wrapper(wrapper): '''Convert a wrapper tuple or format string to a format string >>> create_wrapper('') >>> print(create_wrapper('a{}b')) a{}b >>> print(create_wrapper(('a', 'b'))) a{}b ''' if isinstance(wrapper, tuple) and len(wrapper) == 2: a, b = wrapper wrapper = (a or '') + '{}' + (b or '') elif not wrapper: return if isinstance(wrapper, str): assert '{}' in wrapper, 'Expected string with {} for formatting' else: raise RuntimeError( 'Pass either a begin/end string as a tuple or a' ' template string with {}' ) return wrapper def wrapper(function, wrapper_): '''Wrap the output of a function in a template string or a tuple with begin/end strings ''' wrapper_ = create_wrapper(wrapper_) if not wrapper_: return function @functools.wraps(function) def wrap(*args, **kwargs): return wrapper_.format(function(*args, **kwargs)) return wrap def create_marker(marker, wrap=None): def _marker(progress, data, width): if ( progress.max_value is not base.UnknownLength and progress.max_value > 0 ): length = int(progress.value / progress.max_value * width) return marker * length else: return marker if isinstance(marker, str): marker = converters.to_unicode(marker) assert ( utils.len_color(marker) == 1 ), 'Markers are required to be 1 char' return wrapper(_marker, wrap) else: return wrapper(marker, wrap) class FormatWidgetMixin(abc.ABC): '''Mixin to format widgets using a formatstring Variables available: - max_value: The maximum value (can be None with iterators) - value: The current value - total_seconds_elapsed: The seconds since the bar started - seconds_elapsed: The seconds since the bar started modulo 60 - minutes_elapsed: The minutes since the bar started modulo 60 - hours_elapsed: The hours since the bar started modulo 24 - days_elapsed: The hours since the bar started - time_elapsed: Shortcut for HH:MM:SS time since the bar started including days - percentage: Percentage as a float ''' def __init__(self, format: str, new_style: bool = False, **kwargs): self.new_style = new_style self.format = format def get_format( self, progress: ProgressBarMixinBase, data: Data, format: types.Optional[str] = None, ) -> str: return format or self.format def __call__( self, progress: ProgressBarMixinBase, data: Data, format: types.Optional[str] = None, ) -> str: '''Formats the widget into a string''' format = self.get_format(progress, data, format) try: if self.new_style: return format.format(**data) else: return format % data except (TypeError, KeyError): print('Error while formatting %r' % format, file=sys.stderr) pprint.pprint(data, stream=sys.stderr) raise class WidthWidgetMixin(abc.ABC): '''Mixing to make sure widgets are only visible if the screen is within a specified size range so the progressbar fits on both large and small screens. Variables available: - min_width: Only display the widget if at least `min_width` is left - max_width: Only display the widget if at most `max_width` is left >>> class Progress: ... term_width = 0 >>> WidthWidgetMixin(5, 10).check_size(Progress) False >>> Progress.term_width = 5 >>> WidthWidgetMixin(5, 10).check_size(Progress) True >>> Progress.term_width = 10 >>> WidthWidgetMixin(5, 10).check_size(Progress) True >>> Progress.term_width = 11 >>> WidthWidgetMixin(5, 10).check_size(Progress) False ''' def __init__(self, min_width=None, max_width=None, **kwargs): self.min_width = min_width self.max_width = max_width def check_size(self, progress: ProgressBarMixinBase): if self.min_width and self.min_width > progress.term_width: return False elif self.max_width and self.max_width < progress.term_width: return False else: return True class WidgetBase(WidthWidgetMixin, metaclass=abc.ABCMeta): '''The base class for all widgets The ProgressBar will call the widget's update value when the widget should be updated. The widget's size may change between calls, but the widget may display incorrectly if the size changes drastically and repeatedly. The INTERVAL timedelta informs the ProgressBar that it should be updated more often because it is time sensitive. The widgets are only visible if the screen is within a specified size range so the progressbar fits on both large and small screens. WARNING: Widgets can be shared between multiple progressbars so any state information specific to a progressbar should be stored within the progressbar instead of the widget. Variables available: - min_width: Only display the widget if at least `min_width` is left - max_width: Only display the widget if at most `max_width` is left - weight: Widgets with a higher `weigth` will be calculated before widgets with a lower one - copy: Copy this widget when initializing the progress bar so the progressbar can be reused. Some widgets such as the FormatCustomText require the shared state so this needs to be optional ''' copy = True @abc.abstractmethod def __call__(self, progress: ProgressBarMixinBase, data: Data) -> str: '''Updates the widget. progress - a reference to the calling ProgressBar ''' class AutoWidthWidgetBase(WidgetBase, metaclass=abc.ABCMeta): '''The base class for all variable width widgets. This widget is much like the \\hfill command in TeX, it will expand to fill the line. You can use more than one in the same line, and they will all have the same width, and together will fill the line. ''' @abc.abstractmethod def __call__( self, progress: ProgressBarMixinBase, data: Data, width: int = 0, ) -> str: '''Updates the widget providing the total width the widget must fill. progress - a reference to the calling ProgressBar width - The total width the widget must fill ''' class TimeSensitiveWidgetBase(WidgetBase, metaclass=abc.ABCMeta): '''The base class for all time sensitive widgets. Some widgets like timers would become out of date unless updated at least every `INTERVAL` ''' INTERVAL = datetime.timedelta(milliseconds=100) class FormatLabel(FormatWidgetMixin, WidgetBase): '''Displays a formatted label >>> label = FormatLabel('%(value)s', min_width=5, max_width=10) >>> class Progress: ... pass >>> label = FormatLabel('{value} :: {value:^6}', new_style=True) >>> str(label(Progress, dict(value='test'))) 'test :: test ' ''' mapping = { 'finished': ('end_time', None), 'last_update': ('last_update_time', None), 'max': ('max_value', None), 'seconds': ('seconds_elapsed', None), 'start': ('start_time', None), 'elapsed': ('total_seconds_elapsed', utils.format_time), 'value': ('value', None), } def __init__(self, format: str, **kwargs): FormatWidgetMixin.__init__(self, format=format, **kwargs) WidgetBase.__init__(self, **kwargs) def __call__( self, progress: ProgressBarMixinBase, data: Data, format: types.Optional[str] = None, ): for name, (key, transform) in self.mapping.items(): try: if transform is None: data[name] = data[key] else: data[name] = transform(data[key]) except (KeyError, ValueError, IndexError): # pragma: no cover pass return FormatWidgetMixin.__call__(self, progress, data, format) class Timer(FormatLabel, TimeSensitiveWidgetBase): '''WidgetBase which displays the elapsed seconds.''' def __init__(self, format='Elapsed Time: %(elapsed)s', **kwargs): if '%s' in format and '%(elapsed)s' not in format: format = format.replace('%s', '%(elapsed)s') FormatLabel.__init__(self, format=format, **kwargs) TimeSensitiveWidgetBase.__init__(self, **kwargs) # This is exposed as a static method for backwards compatibility format_time = staticmethod(utils.format_time) class SamplesMixin(TimeSensitiveWidgetBase, metaclass=abc.ABCMeta): ''' Mixing for widgets that average multiple measurements Note that samples can be either an integer or a timedelta to indicate a certain amount of time >>> class progress: ... last_update_time = datetime.datetime.now() ... value = 1 ... extra = dict() >>> samples = SamplesMixin(samples=2) >>> samples(progress, None, True) (None, None) >>> progress.last_update_time += datetime.timedelta(seconds=1) >>> samples(progress, None, True) == (datetime.timedelta(seconds=1), 0) True >>> progress.last_update_time += datetime.timedelta(seconds=1) >>> samples(progress, None, True) == (datetime.timedelta(seconds=1), 0) True >>> samples = SamplesMixin(samples=datetime.timedelta(seconds=1)) >>> _, value = samples(progress, None) >>> value [1, 1] >>> samples(progress, None, True) == (datetime.timedelta(seconds=1), 0) True ''' def __init__( self, samples=datetime.timedelta(seconds=2), key_prefix=None, **kwargs, ): self.samples = samples self.key_prefix = ( key_prefix if key_prefix else self.__class__.__name__ ) + '_' TimeSensitiveWidgetBase.__init__(self, **kwargs) def get_sample_times(self, progress: ProgressBarMixinBase, data: Data): return progress.extra.setdefault(self.key_prefix + 'sample_times', []) def get_sample_values(self, progress: ProgressBarMixinBase, data: Data): return progress.extra.setdefault(self.key_prefix + 'sample_values', []) def __call__( self, progress: ProgressBarMixinBase, data: Data, delta: bool = False ): sample_times = self.get_sample_times(progress, data) sample_values = self.get_sample_values(progress, data) if sample_times: sample_time = sample_times[-1] else: sample_time = datetime.datetime.min if progress.last_update_time - sample_time > self.INTERVAL: # Add a sample but limit the size to `num_samples` sample_times.append(progress.last_update_time) sample_values.append(progress.value) if isinstance(self.samples, datetime.timedelta): minimum_time = progress.last_update_time - self.samples minimum_value = sample_values[-1] while ( sample_times[2:] and minimum_time > sample_times[1] and minimum_value > sample_values[1] ): sample_times.pop(0) sample_values.pop(0) else: if len(sample_times) > self.samples: sample_times.pop(0) sample_values.pop(0) if delta: delta_time = sample_times[-1] - sample_times[0] delta_value = sample_values[-1] - sample_values[0] if delta_time: return delta_time, delta_value else: return None, None else: return sample_times, sample_values class ETA(Timer): '''WidgetBase which attempts to estimate the time of arrival.''' def __init__( self, format_not_started='ETA: --:--:--', format_finished='Time: %(elapsed)8s', format='ETA: %(eta)8s', format_zero='ETA: 00:00:00', format_NA='ETA: N/A', **kwargs, ): if '%s' in format and '%(eta)s' not in format: format = format.replace('%s', '%(eta)s') Timer.__init__(self, **kwargs) self.format_not_started = format_not_started self.format_finished = format_finished self.format = format self.format_zero = format_zero self.format_NA = format_NA def _calculate_eta( self, progress: ProgressBarMixinBase, data: Data, value, elapsed ): '''Updates the widget to show the ETA or total time when finished.''' if elapsed: # The max() prevents zero division errors per_item = elapsed.total_seconds() / max(value, 1e-6) remaining = progress.max_value - data['value'] eta_seconds = remaining * per_item else: eta_seconds = 0 return eta_seconds def __call__( self, progress: ProgressBarMixinBase, data: Data, value=None, elapsed=None, ): '''Updates the widget to show the ETA or total time when finished.''' if value is None: value = data['value'] if elapsed is None: elapsed = data['time_elapsed'] ETA_NA = False try: data['eta_seconds'] = self._calculate_eta( progress, data, value=value, elapsed=elapsed ) except TypeError: data['eta_seconds'] = None ETA_NA = True data['eta'] = None if data['eta_seconds']: try: data['eta'] = utils.format_time(data['eta_seconds']) except (ValueError, OverflowError): # pragma: no cover pass if data['value'] == progress.min_value: format = self.format_not_started elif progress.end_time: format = self.format_finished elif data['eta']: format = self.format elif ETA_NA: format = self.format_NA else: format = self.format_zero return Timer.__call__(self, progress, data, format=format) class AbsoluteETA(ETA): '''Widget which attempts to estimate the absolute time of arrival.''' def _calculate_eta( self, progress: ProgressBarMixinBase, data: Data, value, elapsed ): eta_seconds = ETA._calculate_eta(self, progress, data, value, elapsed) now = datetime.datetime.now() try: return now + datetime.timedelta(seconds=eta_seconds) except OverflowError: # pragma: no cover return datetime.datetime.max def __init__( self, format_not_started='Estimated finish time: ----/--/-- --:--:--', format_finished='Finished at: %(elapsed)s', format='Estimated finish time: %(eta)s', **kwargs, ): ETA.__init__( self, format_not_started=format_not_started, format_finished=format_finished, format=format, **kwargs, ) class AdaptiveETA(ETA, SamplesMixin): '''WidgetBase which attempts to estimate the time of arrival. Uses a sampled average of the speed based on the 10 last updates. Very convenient for resuming the progress halfway. ''' def __init__(self, **kwargs): ETA.__init__(self, **kwargs) SamplesMixin.__init__(self, **kwargs) def __call__( self, progress: ProgressBarMixinBase, data: Data, value=None, elapsed=None, ): elapsed, value = SamplesMixin.__call__( self, progress, data, delta=True ) if not elapsed: value = None elapsed = 0 return ETA.__call__(self, progress, data, value=value, elapsed=elapsed) class DataSize(FormatWidgetMixin, WidgetBase): ''' Widget for showing an amount of data transferred/processed. Automatically formats the value (assumed to be a count of bytes) with an appropriate sized unit, based on the IEC binary prefixes (powers of 1024). ''' def __init__( self, variable='value', format='%(scaled)5.1f %(prefix)s%(unit)s', unit='B', prefixes=('', 'Ki', 'Mi', 'Gi', 'Ti', 'Pi', 'Ei', 'Zi', 'Yi'), **kwargs, ): self.variable = variable self.unit = unit self.prefixes = prefixes FormatWidgetMixin.__init__(self, format=format, **kwargs) WidgetBase.__init__(self, **kwargs) def __call__( self, progress: ProgressBarMixinBase, data: Data, format: types.Optional[str] = None, ): value = data[self.variable] if value is not None: scaled, power = utils.scale_1024(value, len(self.prefixes)) else: scaled = power = 0 data['scaled'] = scaled data['prefix'] = self.prefixes[power] data['unit'] = self.unit return FormatWidgetMixin.__call__(self, progress, data, format) class FileTransferSpeed(FormatWidgetMixin, TimeSensitiveWidgetBase): ''' Widget for showing the current transfer speed (useful for file transfers). ''' def __init__( self, format='%(scaled)5.1f %(prefix)s%(unit)-s/s', inverse_format='%(scaled)5.1f s/%(prefix)s%(unit)-s', unit='B', prefixes=('', 'Ki', 'Mi', 'Gi', 'Ti', 'Pi', 'Ei', 'Zi', 'Yi'), **kwargs, ): self.unit = unit self.prefixes = prefixes self.inverse_format = inverse_format FormatWidgetMixin.__init__(self, format=format, **kwargs) TimeSensitiveWidgetBase.__init__(self, **kwargs) def _speed(self, value, elapsed): speed = float(value) / elapsed return utils.scale_1024(speed, len(self.prefixes)) def __call__( self, progress: ProgressBarMixinBase, data, value=None, total_seconds_elapsed=None, ): '''Updates the widget with the current SI prefixed speed.''' if value is None: value = data['value'] elapsed = utils.deltas_to_seconds( total_seconds_elapsed, data['total_seconds_elapsed'] ) if ( value is not None and elapsed is not None and elapsed > 2e-6 and value > 2e-6 ): # =~ 0 scaled, power = self._speed(value, elapsed) else: scaled = power = 0 data['unit'] = self.unit if power == 0 and scaled < 0.1: if scaled > 0: scaled = 1 / scaled data['scaled'] = scaled data['prefix'] = self.prefixes[0] return FormatWidgetMixin.__call__( self, progress, data, self.inverse_format ) else: data['scaled'] = scaled data['prefix'] = self.prefixes[power] return FormatWidgetMixin.__call__(self, progress, data) class AdaptiveTransferSpeed(FileTransferSpeed, SamplesMixin): '''Widget for showing the transfer speed based on the last X samples''' def __init__(self, **kwargs): FileTransferSpeed.__init__(self, **kwargs) SamplesMixin.__init__(self, **kwargs) def __call__( self, progress: ProgressBarMixinBase, data, value=None, total_seconds_elapsed=None, ): elapsed, value = SamplesMixin.__call__( self, progress, data, delta=True ) return FileTransferSpeed.__call__(self, progress, data, value, elapsed) class AnimatedMarker(TimeSensitiveWidgetBase): '''An animated marker for the progress bar which defaults to appear as if it were rotating. ''' def __init__( self, markers='|/-\\', default=None, fill='', marker_wrap=None, fill_wrap=None, **kwargs, ): self.markers = markers self.marker_wrap = create_wrapper(marker_wrap) self.default = default or markers[0] self.fill_wrap = create_wrapper(fill_wrap) self.fill = create_marker(fill, self.fill_wrap) if fill else None WidgetBase.__init__(self, **kwargs) def __call__(self, progress: ProgressBarMixinBase, data: Data, width=None): '''Updates the widget to show the next marker or the first marker when finished''' if progress.end_time: return self.default marker = self.markers[data['updates'] % len(self.markers)] if self.marker_wrap: marker = self.marker_wrap.format(marker) if self.fill: # Cut the last character so we can replace it with our marker fill = self.fill( progress, data, width - progress.custom_len(marker), # type: ignore ) else: fill = '' # Python 3 returns an int when indexing bytes if isinstance(marker, int): # pragma: no cover marker = bytes(marker) fill = fill.encode() else: # cast fill to the same type as marker fill = type(marker)(fill) return fill + marker # type: ignore # Alias for backwards compatibility RotatingMarker = AnimatedMarker class Counter(FormatWidgetMixin, WidgetBase): '''Displays the current count''' def __init__(self, format='%(value)d', **kwargs): FormatWidgetMixin.__init__(self, format=format, **kwargs) WidgetBase.__init__(self, format=format, **kwargs) def __call__( self, progress: ProgressBarMixinBase, data: Data, format=None ): return FormatWidgetMixin.__call__(self, progress, data, format) class Percentage(FormatWidgetMixin, WidgetBase): '''Displays the current percentage as a number with a percent sign.''' def __init__(self, format='%(percentage)3d%%', na='N/A%%', **kwargs): self.na = na FormatWidgetMixin.__init__(self, format=format, **kwargs) WidgetBase.__init__(self, format=format, **kwargs) def get_format( self, progress: ProgressBarMixinBase, data: Data, format=None ): # If percentage is not available, display N/A% percentage = data.get('percentage', base.Undefined) if not percentage and percentage != 0: return self.na return FormatWidgetMixin.get_format(self, progress, data, format) class SimpleProgress(FormatWidgetMixin, WidgetBase): '''Returns progress as a count of the total (e.g.: "5 of 47")''' max_width_cache: dict[ types.Union[str, tuple[float, float | types.Type[base.UnknownLength]]], types.Optional[int], ] DEFAULT_FORMAT = '%(value_s)s of %(max_value_s)s' def __init__(self, format=DEFAULT_FORMAT, **kwargs): FormatWidgetMixin.__init__(self, format=format, **kwargs) WidgetBase.__init__(self, format=format, **kwargs) self.max_width_cache = dict() self.max_width_cache['default'] = self.max_width or 0 def __call__( self, progress: ProgressBarMixinBase, data: Data, format=None ): # If max_value is not available, display N/A if data.get('max_value'): data['max_value_s'] = data.get('max_value') else: data['max_value_s'] = 'N/A' # if value is not available it's the zeroth iteration if data.get('value'): data['value_s'] = data['value'] else: data['value_s'] = 0 formatted = FormatWidgetMixin.__call__( self, progress, data, format=format ) # Guess the maximum width from the min and max value key = progress.min_value, progress.max_value max_width: types.Optional[int] = self.max_width_cache.get( key, self.max_width ) if not max_width: temporary_data = data.copy() for value in key: if value is None: # pragma: no cover continue temporary_data['value'] = value width = progress.custom_len( FormatWidgetMixin.__call__( self, progress, temporary_data, format=format ) ) if width: # pragma: no branch max_width = max(max_width or 0, width) self.max_width_cache[key] = max_width # Adjust the output to have a consistent size in all cases if max_width: # pragma: no branch formatted = formatted.rjust(max_width) return formatted class Bar(AutoWidthWidgetBase): '''A progress bar which stretches to fill the line.''' def __init__( self, marker='#', left='|', right='|', fill=' ', fill_left=True, marker_wrap=None, **kwargs, ): '''Creates a customizable progress bar. The callable takes the same parameters as the `__call__` method marker - string or callable object to use as a marker left - string or callable object to use as a left border right - string or callable object to use as a right border fill - character to use for the empty part of the progress bar fill_left - whether to fill from the left or the right ''' self.marker = create_marker(marker, marker_wrap) self.left = string_or_lambda(left) self.right = string_or_lambda(right) self.fill = string_or_lambda(fill) self.fill_left = fill_left AutoWidthWidgetBase.__init__(self, **kwargs) def __call__( self, progress: ProgressBarMixinBase, data: Data, width: int = 0, ): '''Updates the progress bar and its subcomponents''' left = converters.to_unicode(self.left(progress, data, width)) right = converters.to_unicode(self.right(progress, data, width)) width -= progress.custom_len(left) + progress.custom_len(right) marker = converters.to_unicode(self.marker(progress, data, width)) fill = converters.to_unicode(self.fill(progress, data, width)) # Make sure we ignore invisible characters when filling width += len(marker) - progress.custom_len(marker) if self.fill_left: marker = marker.ljust(width, fill) else: marker = marker.rjust(width, fill) return left + marker + right class ReverseBar(Bar): '''A bar which has a marker that goes from right to left''' def __init__( self, marker='#', left='|', right='|', fill=' ', fill_left=False, **kwargs, ): '''Creates a customizable progress bar. marker - string or updatable object to use as a marker left - string or updatable object to use as a left border right - string or updatable object to use as a right border fill - character to use for the empty part of the progress bar fill_left - whether to fill from the left or the right ''' Bar.__init__( self, marker=marker, left=left, right=right, fill=fill, fill_left=fill_left, **kwargs, ) class BouncingBar(Bar, TimeSensitiveWidgetBase): '''A bar which has a marker which bounces from side to side.''' INTERVAL = datetime.timedelta(milliseconds=100) def __call__( self, progress: ProgressBarMixinBase, data: Data, width: int = 0, ): '''Updates the progress bar and its subcomponents''' left = converters.to_unicode(self.left(progress, data, width)) right = converters.to_unicode(self.right(progress, data, width)) width -= progress.custom_len(left) + progress.custom_len(right) marker = converters.to_unicode(self.marker(progress, data, width)) fill = converters.to_unicode(self.fill(progress, data, width)) if width: # pragma: no branch value = int( data['total_seconds_elapsed'] / self.INTERVAL.total_seconds() ) a = value % width b = width - a - 1 if value % (width * 2) >= width: a, b = b, a if self.fill_left: marker = a * fill + marker + b * fill else: marker = b * fill + marker + a * fill return left + marker + right class FormatCustomText(FormatWidgetMixin, WidgetBase): mapping: types.Dict[str, types.Any] = {} copy = False def __init__( self, format: str, mapping: types.Optional[types.Dict[str, types.Any]] = None, **kwargs, ): self.format = format self.mapping = mapping or self.mapping FormatWidgetMixin.__init__(self, format=format, **kwargs) WidgetBase.__init__(self, **kwargs) def update_mapping(self, **mapping: types.Dict[str, types.Any]): self.mapping.update(mapping) def __call__( self, progress: ProgressBarMixinBase, data: Data, format: types.Optional[str] = None, ): return FormatWidgetMixin.__call__( self, progress, self.mapping, format or self.format ) class VariableMixin: '''Mixin to display a custom user variable''' def __init__(self, name, **kwargs): if not isinstance(name, str): raise TypeError('Variable(): argument must be a string') if len(name.split()) > 1: raise ValueError('Variable(): argument must be single word') self.name = name class MultiRangeBar(Bar, VariableMixin): ''' A bar with multiple sub-ranges, each represented by a different symbol The various ranges are represented on a user-defined variable, formatted as .. code-block:: python [ ['Symbol1', amount1], ['Symbol2', amount2], ... ] ''' def __init__(self, name, markers, **kwargs): VariableMixin.__init__(self, name) Bar.__init__(self, **kwargs) self.markers = [string_or_lambda(marker) for marker in markers] def get_values(self, progress: ProgressBarMixinBase, data: Data): return data['variables'][self.name] or [] def __call__( self, progress: ProgressBarMixinBase, data: Data, width: int = 0, ): '''Updates the progress bar and its subcomponents''' left = converters.to_unicode(self.left(progress, data, width)) right = converters.to_unicode(self.right(progress, data, width)) width -= progress.custom_len(left) + progress.custom_len(right) values = self.get_values(progress, data) values_sum = sum(values) if width and values_sum: middle = '' values_accumulated = 0 width_accumulated = 0 for marker, value in zip(self.markers, values): marker = converters.to_unicode(marker(progress, data, width)) assert progress.custom_len(marker) == 1 values_accumulated += value item_width = int(values_accumulated / values_sum * width) item_width -= width_accumulated width_accumulated += item_width middle += item_width * marker else: fill = converters.to_unicode(self.fill(progress, data, width)) assert progress.custom_len(fill) == 1 middle = fill * width return left + middle + right class MultiProgressBar(MultiRangeBar): def __init__( self, name, # NOTE: the markers are not whitespace even though some # terminals don't show the characters correctly! markers=' ▁▂▃▄▅▆▇█', **kwargs, ): MultiRangeBar.__init__( self, name=name, markers=list(reversed(markers)), **kwargs, ) def get_values(self, progress: ProgressBarMixinBase, data: Data): ranges = [0.0] * len(self.markers) for value in data['variables'][self.name] or []: if not isinstance(value, (int, float)): # Progress is (value, max) progress_value, progress_max = value value = float(progress_value) / float(progress_max) if not 0 <= value <= 1: raise ValueError( 'Range value needs to be in the range [0..1], got %s' % value ) range_ = value * (len(ranges) - 1) pos = int(range_) frac = range_ % 1 ranges[pos] += 1 - frac if frac: ranges[pos + 1] += frac if self.fill_left: ranges = list(reversed(ranges)) return ranges class GranularMarkers: smooth = ' ▏▎▍▌▋▊▉█' bar = ' ▁▂▃▄▅▆▇█' snake = ' ▖▌▛█' fade_in = ' ░▒▓█' dots = ' ⡀⡄⡆⡇⣇⣧⣷⣿' growing_circles = ' .oO' class GranularBar(AutoWidthWidgetBase): '''A progressbar that can display progress at a sub-character granularity by using multiple marker characters. Examples of markers: - Smooth: ` ▏▎▍▌▋▊▉█` (default) - Bar: ` ▁▂▃▄▅▆▇█` - Snake: ` ▖▌▛█` - Fade in: ` ░▒▓█` - Dots: ` ⡀⡄⡆⡇⣇⣧⣷⣿` - Growing circles: ` .oO` The markers can be accessed through GranularMarkers. GranularMarkers.dots for example ''' def __init__( self, markers=GranularMarkers.smooth, left='|', right='|', **kwargs, ): '''Creates a customizable progress bar. markers - string of characters to use as granular progress markers. The first character should represent 0% and the last 100%. Ex: ` .oO`. left - string or callable object to use as a left border right - string or callable object to use as a right border ''' self.markers = markers self.left = string_or_lambda(left) self.right = string_or_lambda(right) AutoWidthWidgetBase.__init__(self, **kwargs) def __call__( self, progress: ProgressBarMixinBase, data: Data, width: int = 0, ): left = converters.to_unicode(self.left(progress, data, width)) right = converters.to_unicode(self.right(progress, data, width)) width -= progress.custom_len(left) + progress.custom_len(right) max_value = progress.max_value # mypy doesn't get that the first part of the if statement makes sure # we get the correct type if ( max_value is not base.UnknownLength and max_value > 0 # type: ignore ): percent = progress.value / max_value # type: ignore else: percent = 0 num_chars = percent * width marker = self.markers[-1] * int(num_chars) marker_idx = int((num_chars % 1) * (len(self.markers) - 1)) if marker_idx: marker += self.markers[marker_idx] marker = converters.to_unicode(marker) # Make sure we ignore invisible characters when filling width += len(marker) - progress.custom_len(marker) marker = marker.ljust(width, self.markers[0]) return left + marker + right class FormatLabelBar(FormatLabel, Bar): '''A bar which has a formatted label in the center.''' def __init__(self, format, **kwargs): FormatLabel.__init__(self, format, **kwargs) Bar.__init__(self, **kwargs) def __call__( # type: ignore self, progress: ProgressBarMixinBase, data: Data, width: int = 0, format: FormatString = None, ): center = FormatLabel.__call__(self, progress, data, format=format) bar = Bar.__call__(self, progress, data, width) # Aligns the center of the label to the center of the bar center_len = progress.custom_len(center) center_left = int((width - center_len) / 2) center_right = center_left + center_len return bar[:center_left] + center + bar[center_right:] class PercentageLabelBar(Percentage, FormatLabelBar): '''A bar which displays the current percentage in the center.''' # %3d adds an extra space that makes it look off-center # %2d keeps the label somewhat consistently in-place def __init__(self, format='%(percentage)2d%%', na='N/A%%', **kwargs): Percentage.__init__(self, format, na=na, **kwargs) FormatLabelBar.__init__(self, format, **kwargs) def __call__( # type: ignore self, progress: ProgressBarMixinBase, data: Data, width: int = 0, format: FormatString = None, ): return super().__call__(progress, data, width, format=format) class Variable(FormatWidgetMixin, VariableMixin, WidgetBase): '''Displays a custom variable.''' def __init__( self, name, format='{name}: {formatted_value}', width=6, precision=3, **kwargs, ): '''Creates a Variable associated with the given name.''' self.format = format self.width = width self.precision = precision VariableMixin.__init__(self, name=name) WidgetBase.__init__(self, **kwargs) def __call__( self, progress: ProgressBarMixinBase, data: Data, format: types.Optional[str] = None, ): value = data['variables'][self.name] context = data.copy() context['value'] = value context['name'] = self.name context['width'] = self.width context['precision'] = self.precision try: # Make sure to try and cast the value first, otherwise the # formatting will generate warnings/errors on newer Python releases value = float(value) fmt = '{value:{width}.{precision}}' context['formatted_value'] = fmt.format(**context) except (TypeError, ValueError): if value: context['formatted_value'] = '{value:{width}}'.format( **context ) else: context['formatted_value'] = '-' * self.width return self.format.format(**context) class DynamicMessage(Variable): '''Kept for backwards compatibility, please use `Variable` instead.''' pass class CurrentTime(FormatWidgetMixin, TimeSensitiveWidgetBase): '''Widget which displays the current (date)time with seconds resolution.''' INTERVAL = datetime.timedelta(seconds=1) def __init__( self, format='Current Time: %(current_time)s', microseconds=False, **kwargs, ): self.microseconds = microseconds FormatWidgetMixin.__init__(self, format=format, **kwargs) TimeSensitiveWidgetBase.__init__(self, **kwargs) def __call__( self, progress: ProgressBarMixinBase, data: Data, format: types.Optional[str] = None, ): data['current_time'] = self.current_time() data['current_datetime'] = self.current_datetime() return FormatWidgetMixin.__call__(self, progress, data, format=format) def current_datetime(self): now = datetime.datetime.now() if not self.microseconds: now = now.replace(microsecond=0) return now def current_time(self): return self.current_datetime().time() python-progressbar-4.3b.0/pyrightconfig.json000066400000000000000000000001531433023661000212740ustar00rootroot00000000000000{ "include": [ "progressbar" ], "exclude": [ "examples" ], "ignore": [ "docs" ], } python-progressbar-4.3b.0/pytest.ini000066400000000000000000000006231433023661000175600ustar00rootroot00000000000000[pytest] python_files = progressbar/*.py tests/*.py addopts = --cov progressbar --cov-report term-missing --cov-report html --no-cov-on-fail --doctest-modules norecursedirs = .svn _build tmp* docs build dist .ropeproject .tox filterwarnings = ignore::DeprecationWarning markers = no_freezegun: Disable automatic freezegun wrapping python-progressbar-4.3b.0/setup.cfg000066400000000000000000000001311433023661000173420ustar00rootroot00000000000000[metadata] description-file = README.rst [bdist_wheel] universal = 1 [upload] sign = 1 python-progressbar-4.3b.0/setup.py000066400000000000000000000041331433023661000172410ustar00rootroot00000000000000#!/usr/bin/env python # -*- coding: utf-8 -*- import os import sys from setuptools import setup, find_packages # To prevent importing about and thereby breaking the coverage info we use this # exec hack about = {} with open('progressbar/__about__.py', encoding='utf8') as fp: exec(fp.read(), about) install_reqs = [] if sys.argv[-1] == 'info': for k, v in about.items(): print('%s: %s' % (k, v)) sys.exit() if os.path.isfile('README.rst'): with open('README.rst') as fh: readme = fh.read() else: readme = \ 'See http://pypi.python.org/pypi/%(__package_name__)s/' % about if __name__ == '__main__': setup( name='progressbar2', version=about['__version__'], author=about['__author__'], author_email=about['__email__'], description=about['__description__'], url=about['__url__'], license=about['__license__'], keywords=about['__title__'], packages=find_packages(exclude=['docs']), long_description=readme, include_package_data=True, install_requires=[ 'python-utils>=3.4.5', ], setup_requires=['setuptools'], zip_safe=False, extras_require={ 'docs': [ 'sphinx>=1.8.5', ], 'tests': [ 'flake8>=3.7.7', 'pytest>=4.6.9', 'pytest-cov>=2.6.1', 'pytest-mypy', 'freezegun>=0.3.11', 'sphinx>=1.8.5', 'dill>=0.3.6', ], }, python_requires='>=3.7.0', classifiers=[ 'Development Status :: 6 - Mature', 'Intended Audience :: Developers', 'License :: OSI Approved :: BSD License', 'Natural Language :: English', 'Programming Language :: Python :: 3.7', 'Programming Language :: Python :: 3.8', 'Programming Language :: Python :: 3.9', 'Programming Language :: Python :: 3.10', 'Programming Language :: Python :: Implementation :: PyPy', ], ) python-progressbar-4.3b.0/tests/000077500000000000000000000000001433023661000166705ustar00rootroot00000000000000python-progressbar-4.3b.0/tests/conftest.py000066400000000000000000000022201433023661000210630ustar00rootroot00000000000000import time import timeit import pytest import logging import freezegun import progressbar from datetime import datetime LOG_LEVELS = { '0': logging.ERROR, '1': logging.WARNING, '2': logging.INFO, '3': logging.DEBUG, } def pytest_configure(config): logging.basicConfig( level=LOG_LEVELS.get(config.option.verbose, logging.DEBUG)) @pytest.fixture(autouse=True) def small_interval(monkeypatch): # Remove the update limit for tests by default monkeypatch.setattr( progressbar.ProgressBar, '_MINIMUM_UPDATE_INTERVAL', 1e-6) monkeypatch.setattr(timeit, 'default_timer', time.time) @pytest.fixture(autouse=True) def sleep_faster(monkeypatch): # The timezone offset in seconds, add 10 seconds to make sure we don't # accidently get the wrong hour offset_seconds = (datetime.now() - datetime.utcnow()).seconds + 10 offset_hours = int(offset_seconds / 3600) freeze_time = freezegun.freeze_time(tz_offset=offset_hours) with freeze_time as fake_time: monkeypatch.setattr('time.sleep', fake_time.tick) monkeypatch.setattr('timeit.default_timer', time.time) yield freeze_time python-progressbar-4.3b.0/tests/original_examples.py000066400000000000000000000145651433023661000227570ustar00rootroot00000000000000#!/usr/bin/python # -*- coding: utf-8 -*- import sys import time from progressbar import AnimatedMarker, Bar, BouncingBar, Counter, ETA, \ AdaptiveETA, FileTransferSpeed, FormatLabel, Percentage, \ ProgressBar, ReverseBar, RotatingMarker, \ SimpleProgress, Timer, UnknownLength examples = [] def example(fn): try: name = 'Example %d' % int(fn.__name__[7:]) except: name = fn.__name__ def wrapped(): try: sys.stdout.write('Running: %s\n' % name) fn() sys.stdout.write('\n') except KeyboardInterrupt: sys.stdout.write('\nSkipping example.\n\n') examples.append(wrapped) return wrapped @example def example0(): pbar = ProgressBar(widgets=[Percentage(), Bar()], maxval=300).start() for i in range(300): time.sleep(0.01) pbar.update(i+1) pbar.finish() @example def example1(): widgets = ['Test: ', Percentage(), ' ', Bar(marker=RotatingMarker()), ' ', ETA(), ' ', FileTransferSpeed()] pbar = ProgressBar(widgets=widgets, maxval=10000).start() for i in range(1000): # do something pbar.update(10*i+1) pbar.finish() @example def example2(): class CrazyFileTransferSpeed(FileTransferSpeed): """It's bigger between 45 and 80 percent.""" def update(self, pbar): if 45 < pbar.percentage() < 80: return 'Bigger Now ' + FileTransferSpeed.update(self,pbar) else: return FileTransferSpeed.update(self,pbar) widgets = [CrazyFileTransferSpeed(),' <<<', Bar(), '>>> ', Percentage(),' ', ETA()] pbar = ProgressBar(widgets=widgets, maxval=10000) # maybe do something pbar.start() for i in range(2000): # do something pbar.update(5*i+1) pbar.finish() @example def example3(): widgets = [Bar('>'), ' ', ETA(), ' ', ReverseBar('<')] pbar = ProgressBar(widgets=widgets, maxval=10000).start() for i in range(1000): # do something pbar.update(10*i+1) pbar.finish() @example def example4(): widgets = ['Test: ', Percentage(), ' ', Bar(marker='0',left='[',right=']'), ' ', ETA(), ' ', FileTransferSpeed()] pbar = ProgressBar(widgets=widgets, maxval=500) pbar.start() for i in range(100,500+1,50): time.sleep(0.2) pbar.update(i) pbar.finish() @example def example5(): pbar = ProgressBar(widgets=[SimpleProgress()], maxval=17).start() for i in range(17): time.sleep(0.2) pbar.update(i + 1) pbar.finish() @example def example6(): pbar = ProgressBar().start() for i in range(100): time.sleep(0.01) pbar.update(i + 1) pbar.finish() @example def example7(): pbar = ProgressBar() # Progressbar can guess maxval automatically. for i in pbar(range(80)): time.sleep(0.01) @example def example8(): pbar = ProgressBar(maxval=80) # Progressbar can't guess maxval. for i in pbar((i for i in range(80))): time.sleep(0.01) @example def example9(): pbar = ProgressBar(widgets=['Working: ', AnimatedMarker()]) for i in pbar((i for i in range(50))): time.sleep(.08) @example def example10(): widgets = ['Processed: ', Counter(), ' lines (', Timer(), ')'] pbar = ProgressBar(widgets=widgets) for i in pbar((i for i in range(150))): time.sleep(0.1) @example def example11(): widgets = [FormatLabel('Processed: %(value)d lines (in: %(elapsed)s)')] pbar = ProgressBar(widgets=widgets) for i in pbar((i for i in range(150))): time.sleep(0.1) @example def example12(): widgets = ['Balloon: ', AnimatedMarker(markers='.oO@* ')] pbar = ProgressBar(widgets=widgets) for i in pbar((i for i in range(24))): time.sleep(0.3) @example def example13(): # You may need python 3.x to see this correctly try: widgets = ['Arrows: ', AnimatedMarker(markers='←↖↑↗→↘↓↙')] pbar = ProgressBar(widgets=widgets) for i in pbar((i for i in range(24))): time.sleep(0.3) except UnicodeError: sys.stdout.write('Unicode error: skipping example') @example def example14(): # You may need python 3.x to see this correctly try: widgets = ['Arrows: ', AnimatedMarker(markers='◢◣◤◥')] pbar = ProgressBar(widgets=widgets) for i in pbar((i for i in range(24))): time.sleep(0.3) except UnicodeError: sys.stdout.write('Unicode error: skipping example') @example def example15(): # You may need python 3.x to see this correctly try: widgets = ['Wheels: ', AnimatedMarker(markers='◐◓◑◒')] pbar = ProgressBar(widgets=widgets) for i in pbar((i for i in range(24))): time.sleep(0.3) except UnicodeError: sys.stdout.write('Unicode error: skipping example') @example def example16(): widgets = [FormatLabel('Bouncer: value %(value)d - '), BouncingBar()] pbar = ProgressBar(widgets=widgets) for i in pbar((i for i in range(180))): time.sleep(0.05) @example def example17(): widgets = [FormatLabel('Animated Bouncer: value %(value)d - '), BouncingBar(marker=RotatingMarker())] pbar = ProgressBar(widgets=widgets) for i in pbar((i for i in range(180))): time.sleep(0.05) @example def example18(): widgets = [Percentage(), ' ', Bar(), ' ', ETA(), ' ', AdaptiveETA()] pbar = ProgressBar(widgets=widgets, maxval=500) pbar.start() for i in range(500): time.sleep(0.01 + (i < 100) * 0.01 + (i > 400) * 0.9) pbar.update(i + 1) pbar.finish() @example def example19(): pbar = ProgressBar() for i in pbar([]): pass pbar.finish() @example def example20(): """Widgets that behave differently when length is unknown""" widgets = ['[When length is unknown at first]', ' Progress: ', SimpleProgress(), ', Percent: ', Percentage(), ' ', ETA(), ' ', AdaptiveETA()] pbar = ProgressBar(widgets=widgets, maxval=UnknownLength) pbar.start() for i in range(20): time.sleep(0.5) if i == 10: pbar.maxval = 20 pbar.update(i + 1) pbar.finish() if __name__ == '__main__': try: for example in examples: example() except KeyboardInterrupt: sys.stdout.write('\nQuitting examples.\n') python-progressbar-4.3b.0/tests/requirements.txt000066400000000000000000000000131433023661000221460ustar00rootroot00000000000000-e.[tests] python-progressbar-4.3b.0/tests/test_backwards_compatibility.py000066400000000000000000000005671433023661000252030ustar00rootroot00000000000000import time import progressbar def test_progressbar_1_widgets(): widgets = [ progressbar.AdaptiveETA(format="Time left: %s"), progressbar.Timer(format="Time passed: %s"), progressbar.Bar() ] bar = progressbar.ProgressBar(widgets=widgets, max_value=100).start() for i in range(1, 101): bar.update(i) time.sleep(0.1) python-progressbar-4.3b.0/tests/test_custom_widgets.py000066400000000000000000000041401433023661000233400ustar00rootroot00000000000000import time import progressbar class CrazyFileTransferSpeed(progressbar.FileTransferSpeed): "It's bigger between 45 and 80 percent" def update(self, pbar): if 45 < pbar.percentage() < 80: return 'Bigger Now ' + progressbar.FileTransferSpeed.update(self, pbar) else: return progressbar.FileTransferSpeed.update(self, pbar) def test_crazy_file_transfer_speed_widget(): widgets = [ # CrazyFileTransferSpeed(), ' <<<', progressbar.Bar(), '>>> ', progressbar.Percentage(), ' ', progressbar.ETA(), ] p = progressbar.ProgressBar(widgets=widgets, max_value=1000) # maybe do something p.start() for i in range(0, 200, 5): # do something time.sleep(0.1) p.update(i + 1) p.finish() def test_variable_widget_widget(): widgets = [ ' [', progressbar.Timer(), '] ', progressbar.Bar(), ' (', progressbar.ETA(), ') ', progressbar.Variable('loss'), progressbar.Variable('text'), progressbar.Variable('error', precision=None), progressbar.Variable('missing'), progressbar.Variable('predefined'), ] p = progressbar.ProgressBar(widgets=widgets, max_value=1000, variables=dict(predefined='predefined')) p.start() print('time', time, time.sleep) for i in range(0, 200, 5): time.sleep(0.1) p.update(i + 1, loss=.5, text='spam', error=1) i += 1 p.update(i, text=None) i += 1 p.update(i, text=False) i += 1 p.update(i, text=True, error='a') p.finish() def test_format_custom_text_widget(): widget = progressbar.FormatCustomText( 'Spam: %(spam).1f kg, eggs: %(eggs)d', dict( spam=0.25, eggs=3, ), ) bar = progressbar.ProgressBar(widgets=[ widget, ]) for i in bar(range(5)): widget.update_mapping(eggs=i * 2) assert widget.mapping['eggs'] == bar.widgets[0].mapping['eggs'] python-progressbar-4.3b.0/tests/test_data.py000066400000000000000000000010361433023661000212120ustar00rootroot00000000000000import pytest import progressbar @pytest.mark.parametrize('value,expected', [ (None, ' 0.0 B'), (1, ' 1.0 B'), (2 ** 10 - 1, '1023.0 B'), (2 ** 10 + 0, ' 1.0 KiB'), (2 ** 20, ' 1.0 MiB'), (2 ** 30, ' 1.0 GiB'), (2 ** 40, ' 1.0 TiB'), (2 ** 50, ' 1.0 PiB'), (2 ** 60, ' 1.0 EiB'), (2 ** 70, ' 1.0 ZiB'), (2 ** 80, ' 1.0 YiB'), (2 ** 90, '1024.0 YiB'), ]) def test_data_size(value, expected): widget = progressbar.DataSize() assert widget(None, dict(value=value)) == expected python-progressbar-4.3b.0/tests/test_data_transfer_bar.py000066400000000000000000000005501433023661000237420ustar00rootroot00000000000000import progressbar from progressbar import DataTransferBar def test_known_length(): dtb = DataTransferBar().start(max_value=50) for i in range(50): dtb.update(i) dtb.finish() def test_unknown_length(): dtb = DataTransferBar().start(max_value=progressbar.UnknownLength) for i in range(50): dtb.update(i) dtb.finish() python-progressbar-4.3b.0/tests/test_dill_pickle.py000066400000000000000000000005141433023661000225540ustar00rootroot00000000000000import dill import progressbar def test_dill(): bar = progressbar.ProgressBar() assert bar._started is False assert bar._finished is False assert dill.pickles(bar) is False assert bar._started is False # Should be false because it never should have started/initialized assert bar._finished is False python-progressbar-4.3b.0/tests/test_empty.py000066400000000000000000000003251433023661000214370ustar00rootroot00000000000000import progressbar def test_empty_list(): for x in progressbar.ProgressBar()([]): print(x) def test_empty_iterator(): for x in progressbar.ProgressBar(max_value=0)(iter([])): print(x) python-progressbar-4.3b.0/tests/test_end.py000066400000000000000000000020411433023661000210440ustar00rootroot00000000000000import pytest import progressbar @pytest.fixture(autouse=True) def large_interval(monkeypatch): # Remove the update limit for tests by default monkeypatch.setattr( progressbar.ProgressBar, '_MINIMUM_UPDATE_INTERVAL', 0.1) def test_end(): m = 24514315 p = progressbar.ProgressBar( widgets=[progressbar.Percentage(), progressbar.Bar()], max_value=m ) for x in range(0, m, 8192): p.update(x) data = p.data() assert data['percentage'] < 100. p.finish() data = p.data() assert data['percentage'] >= 100. assert p.value == m def test_end_100(monkeypatch): assert progressbar.ProgressBar._MINIMUM_UPDATE_INTERVAL == 0.1 p = progressbar.ProgressBar( widgets=[progressbar.Percentage(), progressbar.Bar()], max_value=103, ) for x in range(0, 102): p.update(x) data = p.data() import pprint pprint.pprint(data) assert data['percentage'] < 100. p.finish() data = p.data() assert data['percentage'] >= 100. python-progressbar-4.3b.0/tests/test_failure.py000066400000000000000000000054651433023661000217420ustar00rootroot00000000000000import time import pytest import progressbar def test_missing_format_values(): with pytest.raises(KeyError): p = progressbar.ProgressBar( widgets=[progressbar.widgets.FormatLabel('%(x)s')], ) p.update(5) def test_max_smaller_than_min(): with pytest.raises(ValueError): progressbar.ProgressBar(min_value=10, max_value=5) def test_no_max_value(): '''Looping up to 5 without max_value? No problem''' p = progressbar.ProgressBar() p.start() for i in range(5): time.sleep(1) p.update(i) def test_correct_max_value(): '''Looping up to 5 when max_value is 10? No problem''' p = progressbar.ProgressBar(max_value=10) for i in range(5): time.sleep(1) p.update(i) def test_minus_max_value(): '''negative max_value, shouldn't work''' p = progressbar.ProgressBar(min_value=-2, max_value=-1) with pytest.raises(ValueError): p.update(-1) def test_zero_max_value(): '''max_value of zero, it could happen''' p = progressbar.ProgressBar(max_value=0) p.update(0) with pytest.raises(ValueError): p.update(1) def test_one_max_value(): '''max_value of one, another corner case''' p = progressbar.ProgressBar(max_value=1) p.update(0) p.update(0) p.update(1) with pytest.raises(ValueError): p.update(2) def test_changing_max_value(): '''Changing max_value? No problem''' p = progressbar.ProgressBar(max_value=10)(range(20), max_value=20) for i in p: time.sleep(1) def test_backwards(): '''progressbar going backwards''' p = progressbar.ProgressBar(max_value=1) p.update(1) p.update(0) def test_incorrect_max_value(): '''Looping up to 10 when max_value is 5? This is madness!''' p = progressbar.ProgressBar(max_value=5) for i in range(5): time.sleep(1) p.update(i) with pytest.raises(ValueError): for i in range(5, 10): time.sleep(1) p.update(i) def test_deprecated_maxval(): with pytest.warns(DeprecationWarning): progressbar.ProgressBar(maxval=5) def test_deprecated_poll(): with pytest.warns(DeprecationWarning): progressbar.ProgressBar(poll=5) def test_deprecated_currval(): with pytest.warns(DeprecationWarning): bar = progressbar.ProgressBar(max_value=5) bar.update(2) assert bar.currval == 2 def test_unexpected_update_keyword_arg(): p = progressbar.ProgressBar(max_value=10) with pytest.raises(TypeError): for i in range(10): time.sleep(1) p.update(i, foo=10) def test_variable_not_str(): with pytest.raises(TypeError): progressbar.Variable(1) def test_variable_too_many_strs(): with pytest.raises(ValueError): progressbar.Variable('too long') python-progressbar-4.3b.0/tests/test_flush.py000066400000000000000000000005661433023661000214310ustar00rootroot00000000000000import time import progressbar def test_flush(): '''Left justify using the terminal width''' p = progressbar.ProgressBar(poll_interval=0.001) for i in range(10): print('pre-updates', p.updates) p.update(i) print('need update?', p._needs_update()) if i > 5: time.sleep(0.1) print('post-updates', p.updates) python-progressbar-4.3b.0/tests/test_iterators.py000066400000000000000000000027011433023661000223150ustar00rootroot00000000000000import time import pytest import progressbar def test_list(): '''Progressbar can guess max_value automatically.''' p = progressbar.ProgressBar() for i in p(range(10)): time.sleep(0.001) def test_iterator_with_max_value(): '''Progressbar can't guess max_value.''' p = progressbar.ProgressBar(max_value=10) for i in p((i for i in range(10))): time.sleep(0.001) def test_iterator_without_max_value_error(): '''Progressbar can't guess max_value.''' p = progressbar.ProgressBar() for i in p((i for i in range(10))): time.sleep(0.001) assert p.max_value is progressbar.UnknownLength def test_iterator_without_max_value(): '''Progressbar can't guess max_value.''' p = progressbar.ProgressBar(widgets=[ progressbar.AnimatedMarker(), progressbar.FormatLabel('%(value)d'), progressbar.BouncingBar(), progressbar.BouncingBar(marker=progressbar.RotatingMarker()), ]) for i in p((i for i in range(10))): time.sleep(0.001) def test_iterator_with_incorrect_max_value(): '''Progressbar can't guess max_value.''' p = progressbar.ProgressBar(max_value=10) with pytest.raises(ValueError): for i in p((i for i in range(20))): time.sleep(0.001) def test_adding_value(): p = progressbar.ProgressBar(max_value=10) p.start() p.update(5) p += 2 p.increment(2) with pytest.raises(ValueError): p += 5 python-progressbar-4.3b.0/tests/test_large_values.py000066400000000000000000000006101433023661000227470ustar00rootroot00000000000000import time import progressbar def test_large_max_value(): with progressbar.ProgressBar(max_value=1e10) as bar: for i in range(10): bar.update(i) time.sleep(0.1) def test_value_beyond_max_value(): with progressbar.ProgressBar(max_value=10, max_error=False) as bar: for i in range(20): bar.update(i) time.sleep(0.01) python-progressbar-4.3b.0/tests/test_misc.py000066400000000000000000000005411433023661000212340ustar00rootroot00000000000000from progressbar import __about__ def test_about(): assert __about__.__title__ assert __about__.__package_name__ assert __about__.__author__ assert __about__.__description__ assert __about__.__email__ assert __about__.__version__ assert __about__.__license__ assert __about__.__copyright__ assert __about__.__url__ python-progressbar-4.3b.0/tests/test_monitor_progress.py000066400000000000000000000230771433023661000237250ustar00rootroot00000000000000import os import pprint import progressbar pytest_plugins = 'pytester' SCRIPT = ''' import sys sys.path.append({progressbar_path!r}) import time import timeit import freezegun import progressbar with freezegun.freeze_time() as fake_time: timeit.default_timer = time.time with progressbar.ProgressBar(widgets={widgets}, **{kwargs!r}) as bar: bar._MINIMUM_UPDATE_INTERVAL = 1e-9 for i in bar({items}): {loop_code} ''' def _create_script(widgets=None, items=list(range(9)), loop_code='fake_time.tick(1)', term_width=60, **kwargs): kwargs['term_width'] = term_width # Reindent the loop code indent = '\n ' loop_code = loop_code.strip('\n').split('\n') dedent = len(loop_code[0]) - len(loop_code[0].lstrip()) for i, line in enumerate(loop_code): loop_code[i] = line[dedent:] script = SCRIPT.format( items=items, widgets=widgets, kwargs=kwargs, loop_code=indent.join(loop_code), progressbar_path=os.path.dirname(os.path.dirname( progressbar.__file__)), ) print('# Script:') print('#' * 78) print(script) print('#' * 78) return script def test_list_example(testdir): ''' Run the simple example code in a python subprocess and then compare its stderr to what we expect to see from it. We run it in a subprocess to best capture its stderr. We expect to see match_lines in order in the output. This test is just a sanity check to ensure that the progress bar progresses from 1 to 10, it does not make sure that the ''' result = testdir.runpython(testdir.makepyfile(_create_script( term_width=65, ))) result.stderr.lines = [l.rstrip() for l in result.stderr.lines if l.strip()] pprint.pprint(result.stderr.lines, width=70) result.stderr.fnmatch_lines([ ' 0% (0 of 9) | | Elapsed Time: ?:00:00 ETA: --:--:--', ' 11% (1 of 9) |# | Elapsed Time: ?:00:01 ETA: ?:00:08', ' 22% (2 of 9) |## | Elapsed Time: ?:00:02 ETA: ?:00:07', ' 33% (3 of 9) |#### | Elapsed Time: ?:00:03 ETA: ?:00:06', ' 44% (4 of 9) |##### | Elapsed Time: ?:00:04 ETA: ?:00:05', ' 55% (5 of 9) |###### | Elapsed Time: ?:00:05 ETA: ?:00:04', ' 66% (6 of 9) |######## | Elapsed Time: ?:00:06 ETA: ?:00:03', ' 77% (7 of 9) |######### | Elapsed Time: ?:00:07 ETA: ?:00:02', ' 88% (8 of 9) |########## | Elapsed Time: ?:00:08 ETA: ?:00:01', '100% (9 of 9) |############| Elapsed Time: ?:00:09 Time: ?:00:09', ]) def test_generator_example(testdir): ''' Run the simple example code in a python subprocess and then compare its stderr to what we expect to see from it. We run it in a subprocess to best capture its stderr. We expect to see match_lines in order in the output. This test is just a sanity check to ensure that the progress bar progresses from 1 to 10, it does not make sure that the ''' result = testdir.runpython(testdir.makepyfile(_create_script( items='iter(range(9))', ))) result.stderr.lines = [l for l in result.stderr.lines if l.strip()] pprint.pprint(result.stderr.lines, width=70) lines = [] for i in range(9): lines.append( r'[/\\|\-]\s+\|\s*#\s*\| %(i)d Elapsed Time: \d:00:%(i)02d' % dict(i=i)) result.stderr.re_match_lines(lines) def test_rapid_updates(testdir): ''' Run some example code that updates 10 times, then sleeps .1 seconds, this is meant to test that the progressbar progresses normally with this sample code, since there were issues with it in the past ''' result = testdir.runpython(testdir.makepyfile(_create_script( term_width=60, items=list(range(10)), loop_code=''' if i < 5: fake_time.tick(1) else: fake_time.tick(2) ''' ))) result.stderr.lines = [l for l in result.stderr.lines if l.strip()] pprint.pprint(result.stderr.lines, width=70) result.stderr.fnmatch_lines([ ' 0% (0 of 10) | | Elapsed Time: ?:00:00 ETA: --:--:--', ' 10% (1 of 10) | | Elapsed Time: ?:00:01 ETA: ?:00:09', ' 20% (2 of 10) |# | Elapsed Time: ?:00:02 ETA: ?:00:08', ' 30% (3 of 10) |# | Elapsed Time: ?:00:03 ETA: ?:00:07', ' 40% (4 of 10) |## | Elapsed Time: ?:00:04 ETA: ?:00:06', ' 50% (5 of 10) |### | Elapsed Time: ?:00:05 ETA: ?:00:05', ' 60% (6 of 10) |### | Elapsed Time: ?:00:07 ETA: ?:00:06', ' 70% (7 of 10) |#### | Elapsed Time: ?:00:09 ETA: ?:00:06', ' 80% (8 of 10) |#### | Elapsed Time: ?:00:11 ETA: ?:00:04', ' 90% (9 of 10) |##### | Elapsed Time: ?:00:13 ETA: ?:00:02', '100% (10 of 10) |#####| Elapsed Time: ?:00:15 Time: ?:00:15' ]) def test_non_timed(testdir): result = testdir.runpython(testdir.makepyfile(_create_script( widgets='[progressbar.Percentage(), progressbar.Bar()]', items=list(range(5)), ))) result.stderr.lines = [l for l in result.stderr.lines if l.strip()] pprint.pprint(result.stderr.lines, width=70) result.stderr.fnmatch_lines([ ' 0%| |', ' 20%|########## |', ' 40%|##################### |', ' 60%|################################ |', ' 80%|########################################### |', '100%|######################################################|', ]) def test_line_breaks(testdir): result = testdir.runpython(testdir.makepyfile(_create_script( widgets='[progressbar.Percentage(), progressbar.Bar()]', line_breaks=True, items=list(range(5)), ))) pprint.pprint(result.stderr.str(), width=70) assert result.stderr.str() == u'\n'.join(( u' 0%| |', u' 20%|########## |', u' 40%|##################### |', u' 60%|################################ |', u' 80%|########################################### |', u'100%|######################################################|', u'100%|######################################################|', )) def test_no_line_breaks(testdir): result = testdir.runpython(testdir.makepyfile(_create_script( widgets='[progressbar.Percentage(), progressbar.Bar()]', line_breaks=False, items=list(range(5)), ))) pprint.pprint(result.stderr.lines, width=70) assert result.stderr.lines == [ u'', u' 0%| |', u' 20%|########## |', u' 40%|##################### |', u' 60%|################################ |', u' 80%|########################################### |', u'100%|######################################################|', u'', u'100%|######################################################|' ] def test_percentage_label_bar(testdir): result = testdir.runpython(testdir.makepyfile(_create_script( widgets='[progressbar.PercentageLabelBar()]', line_breaks=False, items=list(range(5)), ))) pprint.pprint(result.stderr.lines, width=70) assert result.stderr.lines == [ u'', u'| 0% |', u'|########### 20% |', u'|####################### 40% |', u'|###########################60%#### |', u'|###########################80%################ |', u'|###########################100%###########################|', u'', u'|###########################100%###########################|' ] def test_granular_bar(testdir): result = testdir.runpython(testdir.makepyfile(_create_script( widgets='[progressbar.GranularBar(markers=" .oO")]', line_breaks=False, items=list(range(5)), ))) pprint.pprint(result.stderr.lines, width=70) assert result.stderr.lines == [ u'', u'| |', u'|OOOOOOOOOOO. |', u'|OOOOOOOOOOOOOOOOOOOOOOO |', u'|OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOo |', u'|OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO. |', u'|OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO|', u'', u'|OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO|' ] def test_colors(testdir): kwargs = dict( items=range(1), widgets=['\033[92mgreen\033[0m'], ) result = testdir.runpython(testdir.makepyfile(_create_script( enable_colors=True, **kwargs))) pprint.pprint(result.stderr.lines, width=70) assert result.stderr.lines == [u'\x1b[92mgreen\x1b[0m'] * 3 result = testdir.runpython(testdir.makepyfile(_create_script( enable_colors=False, **kwargs))) pprint.pprint(result.stderr.lines, width=70) assert result.stderr.lines == [u'green'] * 3 python-progressbar-4.3b.0/tests/test_multibar.py000066400000000000000000000007451433023661000221260ustar00rootroot00000000000000import pytest import progressbar def test_multi_progress_bar_out_of_range(): widgets = [ progressbar.MultiProgressBar('multivalues'), ] bar = progressbar.ProgressBar(widgets=widgets, max_value=10) with pytest.raises(ValueError): bar.update(multivalues=[123]) with pytest.raises(ValueError): bar.update(multivalues=[-1]) def test_multi_progress_bar_fill_left(): import examples return examples.multi_progress_bar_example(False) python-progressbar-4.3b.0/tests/test_progressbar.py000066400000000000000000000030701433023661000226320ustar00rootroot00000000000000import time import pytest import progressbar import original_examples # Import hack to allow for parallel Tox try: import examples except ImportError: import sys sys.path.append('..') import examples sys.path.remove('..') def test_examples(monkeypatch): for example in examples.examples: try: example() except ValueError: pass @pytest.mark.filterwarnings('ignore:.*maxval.*:DeprecationWarning') @pytest.mark.parametrize('example', original_examples.examples) def test_original_examples(example, monkeypatch): monkeypatch.setattr(progressbar.ProgressBar, '_MINIMUM_UPDATE_INTERVAL', 1) monkeypatch.setattr(time, 'sleep', lambda t: None) example() @pytest.mark.parametrize('example', examples.examples) def test_examples_nullbar(monkeypatch, example): # Patch progressbar to use null bar instead of regular progress bar monkeypatch.setattr(progressbar, 'ProgressBar', progressbar.NullBar) assert progressbar.ProgressBar._MINIMUM_UPDATE_INTERVAL < 0.0001 example() def test_reuse(): import progressbar bar = progressbar.ProgressBar() bar.start() for i in range(10): bar.update(i) bar.finish() bar.start(init=True) for i in range(10): bar.update(i) bar.finish() bar.start(init=False) for i in range(10): bar.update(i) bar.finish() def test_dirty(): import progressbar bar = progressbar.ProgressBar() bar.start() for i in range(10): bar.update(i) bar.finish(dirty=True) python-progressbar-4.3b.0/tests/test_samples.py000066400000000000000000000070021433023661000217440ustar00rootroot00000000000000import time from datetime import timedelta from datetime import datetime import progressbar from progressbar import widgets def test_numeric_samples(): samples = 5 samples_widget = widgets.SamplesMixin(samples=samples) bar = progressbar.ProgressBar(widgets=[samples_widget]) # Force updates in all cases samples_widget.INTERVAL = timedelta(0) start = datetime(2000, 1, 1) bar.value = 1 bar.last_update_time = start + timedelta(seconds=bar.value) assert samples_widget(bar, None, True) == (None, None) for i in range(2, 6): bar.value = i bar.last_update_time = start + timedelta(seconds=i) assert samples_widget(bar, None, True) == (timedelta(0, i - 1), i - 1) bar.value = 8 bar.last_update_time = start + timedelta(seconds=bar.value) assert samples_widget(bar, None, True) == (timedelta(0, 6), 6) bar.value = 10 bar.last_update_time = start + timedelta(seconds=bar.value) assert samples_widget(bar, None, True) == (timedelta(0, 7), 7) bar.value = 20 bar.last_update_time = start + timedelta(seconds=bar.value) assert samples_widget(bar, None, True) == (timedelta(0, 16), 16) assert samples_widget(bar, None)[1] == [4, 5, 8, 10, 20] def test_timedelta_samples(): samples = timedelta(seconds=5) samples_widget = widgets.SamplesMixin(samples=samples) bar = progressbar.ProgressBar(widgets=[samples_widget]) # Force updates in all cases samples_widget.INTERVAL = timedelta(0) start = datetime(2000, 1, 1) bar.value = 1 bar.last_update_time = start + timedelta(seconds=bar.value) assert samples_widget(bar, None, True) == (None, None) for i in range(2, 6): time.sleep(1) bar.value = i bar.last_update_time = start + timedelta(seconds=i) assert samples_widget(bar, None, True) == (timedelta(0, i - 1), i - 1) bar.value = 8 bar.last_update_time = start + timedelta(seconds=bar.value) assert samples_widget(bar, None, True) == (timedelta(0, 6), 6) bar.last_update_time = start + timedelta(seconds=bar.value) bar.value = 8 assert samples_widget(bar, None, True) == (timedelta(0, 6), 6) bar.value = 10 bar.last_update_time = start + timedelta(seconds=bar.value) assert samples_widget(bar, None, True) == (timedelta(0, 6), 6) bar.value = 20 bar.last_update_time = start + timedelta(seconds=bar.value) assert samples_widget(bar, None, True) == (timedelta(0, 10), 10) assert samples_widget(bar, None)[1] == [10, 20] def test_timedelta_no_update(): samples = timedelta(seconds=0.1) samples_widget = widgets.SamplesMixin(samples=samples) bar = progressbar.ProgressBar(widgets=[samples_widget]) bar.update() assert samples_widget(bar, None, True) == (None, None) assert samples_widget(bar, None, False)[1] == [0] assert samples_widget(bar, None, True) == (None, None) assert samples_widget(bar, None, False)[1] == [0] time.sleep(1) assert samples_widget(bar, None, True) == (None, None) assert samples_widget(bar, None, False)[1] == [0] bar.update(1) assert samples_widget(bar, None, True) == (timedelta(0, 1), 1) assert samples_widget(bar, None, False)[1] == [0, 1] time.sleep(1) bar.update(2) assert samples_widget(bar, None, True) == (timedelta(0, 1), 1) assert samples_widget(bar, None, False)[1] == [1, 2] time.sleep(0.01) bar.update(3) assert samples_widget(bar, None, True) == (timedelta(0, 1), 1) assert samples_widget(bar, None, False)[1] == [1, 2] python-progressbar-4.3b.0/tests/test_speed.py000066400000000000000000000014231433023661000214010ustar00rootroot00000000000000import pytest import progressbar @pytest.mark.parametrize('total_seconds_elapsed,value,expected', [ (1, 0, ' 0.0 s/B'), (1, 0.01, '100.0 s/B'), (1, 0.1, ' 0.1 B/s'), (1, 1, ' 1.0 B/s'), (1, 2 ** 10 - 1, '1023.0 B/s'), (1, 2 ** 10 + 0, ' 1.0 KiB/s'), (1, 2 ** 20, ' 1.0 MiB/s'), (1, 2 ** 30, ' 1.0 GiB/s'), (1, 2 ** 40, ' 1.0 TiB/s'), (1, 2 ** 50, ' 1.0 PiB/s'), (1, 2 ** 60, ' 1.0 EiB/s'), (1, 2 ** 70, ' 1.0 ZiB/s'), (1, 2 ** 80, ' 1.0 YiB/s'), (1, 2 ** 90, '1024.0 YiB/s'), ]) def test_file_transfer_speed(total_seconds_elapsed, value, expected): widget = progressbar.FileTransferSpeed() assert widget(None, dict( total_seconds_elapsed=total_seconds_elapsed, value=value, )) == expected python-progressbar-4.3b.0/tests/test_stream.py000066400000000000000000000045271433023661000216040ustar00rootroot00000000000000import io import sys import pytest import progressbar def test_nowrap(): # Make sure we definitely unwrap for i in range(5): progressbar.streams.unwrap(stderr=True, stdout=True) stdout = sys.stdout stderr = sys.stderr progressbar.streams.wrap() assert stdout == sys.stdout assert stderr == sys.stderr progressbar.streams.unwrap() assert stdout == sys.stdout assert stderr == sys.stderr # Make sure we definitely unwrap for i in range(5): progressbar.streams.unwrap(stderr=True, stdout=True) def test_wrap(): # Make sure we definitely unwrap for i in range(5): progressbar.streams.unwrap(stderr=True, stdout=True) stdout = sys.stdout stderr = sys.stderr progressbar.streams.wrap(stderr=True, stdout=True) assert stdout != sys.stdout assert stderr != sys.stderr # Wrap again stdout = sys.stdout stderr = sys.stderr progressbar.streams.wrap(stderr=True, stdout=True) assert stdout == sys.stdout assert stderr == sys.stderr # Make sure we definitely unwrap for i in range(5): progressbar.streams.unwrap(stderr=True, stdout=True) def test_excepthook(): progressbar.streams.wrap(stderr=True, stdout=True) try: raise RuntimeError() except RuntimeError: progressbar.streams.excepthook(*sys.exc_info()) progressbar.streams.unwrap_excepthook() progressbar.streams.unwrap_excepthook() def test_fd_as_io_stream(): stream = io.StringIO() with progressbar.ProgressBar(fd=stream) as pb: for i in range(101): pb.update(i) stream.close() def test_no_newlines(): kwargs = dict( redirect_stderr=True, redirect_stdout=True, line_breaks=False, is_terminal=True, ) with progressbar.ProgressBar(**kwargs) as bar: for i in range(5): bar.update(i) for i in range(5, 10): try: print('\n\n', file=progressbar.streams.stdout) print('\n\n', file=progressbar.streams.stderr) except ValueError: pass bar.update(i) @pytest.mark.parametrize('stream', [sys.__stdout__, sys.__stderr__]) def test_fd_as_standard_streams(stream): with progressbar.ProgressBar(fd=stream) as pb: for i in range(101): pb.update(i) python-progressbar-4.3b.0/tests/test_terminal.py000066400000000000000000000077501433023661000221250ustar00rootroot00000000000000import sys import time import signal import progressbar from datetime import timedelta def test_left_justify(): '''Left justify using the terminal width''' p = progressbar.ProgressBar( widgets=[progressbar.BouncingBar(marker=progressbar.RotatingMarker())], max_value=100, term_width=20, left_justify=True) assert p.term_width is not None for i in range(100): p.update(i) def test_right_justify(): '''Right justify using the terminal width''' p = progressbar.ProgressBar( widgets=[progressbar.BouncingBar(marker=progressbar.RotatingMarker())], max_value=100, term_width=20, left_justify=False) assert p.term_width is not None for i in range(100): p.update(i) def test_auto_width(monkeypatch): '''Right justify using the terminal width''' def ioctl(*args): return '\xbf\x00\xeb\x00\x00\x00\x00\x00' def fake_signal(signal, func): pass try: import fcntl monkeypatch.setattr(fcntl, 'ioctl', ioctl) monkeypatch.setattr(signal, 'signal', fake_signal) p = progressbar.ProgressBar( widgets=[ progressbar.BouncingBar(marker=progressbar.RotatingMarker())], max_value=100, left_justify=True, term_width=None) assert p.term_width is not None for i in range(100): p.update(i) except ImportError: pass # Skip on Windows def test_fill_right(): '''Right justify using the terminal width''' p = progressbar.ProgressBar( widgets=[progressbar.BouncingBar(fill_left=False)], max_value=100, term_width=20) assert p.term_width is not None for i in range(100): p.update(i) def test_fill_left(): '''Right justify using the terminal width''' p = progressbar.ProgressBar( widgets=[progressbar.BouncingBar(fill_left=True)], max_value=100, term_width=20) assert p.term_width is not None for i in range(100): p.update(i) def test_no_fill(monkeypatch): '''Simply bounce within the terminal width''' bar = progressbar.BouncingBar() bar.INTERVAL = timedelta(seconds=1) p = progressbar.ProgressBar( widgets=[bar], max_value=progressbar.UnknownLength, term_width=20) assert p.term_width is not None for i in range(30): p.update(i, force=True) # Fake the start time so we can actually emulate a moving progress bar p.start_time = p.start_time - timedelta(seconds=i) def test_stdout_redirection(): p = progressbar.ProgressBar(fd=sys.stdout, max_value=10, redirect_stdout=True) for i in range(10): print('', file=sys.stdout) p.update(i) def test_double_stdout_redirection(): p = progressbar.ProgressBar(max_value=10, redirect_stdout=True) p2 = progressbar.ProgressBar(max_value=10, redirect_stdout=True) for i in range(10): print('', file=sys.stdout) p.update(i) p2.update(i) def test_stderr_redirection(): p = progressbar.ProgressBar(max_value=10, redirect_stderr=True) for i in range(10): print('', file=sys.stderr) p.update(i) def test_stdout_stderr_redirection(): p = progressbar.ProgressBar(max_value=10, redirect_stdout=True, redirect_stderr=True) p.start() for i in range(10): time.sleep(0.01) print('', file=sys.stdout) print('', file=sys.stderr) p.update(i) p.finish() def test_resize(monkeypatch): def ioctl(*args): return '\xbf\x00\xeb\x00\x00\x00\x00\x00' def fake_signal(signal, func): pass try: import fcntl monkeypatch.setattr(fcntl, 'ioctl', ioctl) monkeypatch.setattr(signal, 'signal', fake_signal) p = progressbar.ProgressBar(max_value=10) p.start() for i in range(10): p.update(i) p._handle_resize() p.finish() except ImportError: pass # Skip on Windows python-progressbar-4.3b.0/tests/test_timed.py000066400000000000000000000104371433023661000214100ustar00rootroot00000000000000import time import datetime import progressbar def test_timer(): '''Testing (Adaptive)ETA when the value doesn't actually change''' widgets = [ progressbar.Timer(), ] p = progressbar.ProgressBar(max_value=2, widgets=widgets, poll_interval=0.0001) p.start() p.update() p.update(1) p._needs_update() time.sleep(0.001) p.update(1) p.finish() def test_eta(): '''Testing (Adaptive)ETA when the value doesn't actually change''' widgets = [ progressbar.ETA(), ] p = progressbar.ProgressBar(min_value=0, max_value=2, widgets=widgets, poll_interval=0.0001) p.start() time.sleep(0.001) p.update(0) time.sleep(0.001) p.update(1) time.sleep(0.001) p.update(1) time.sleep(0.001) p.update(2) time.sleep(0.001) p.finish() time.sleep(0.001) p.update(2) def test_adaptive_eta(): '''Testing (Adaptive)ETA when the value doesn't actually change''' widgets = [ progressbar.AdaptiveETA(), ] widgets[0].INTERVAL = datetime.timedelta(microseconds=1) p = progressbar.ProgressBar( max_value=2, samples=2, widgets=widgets, poll_interval=0.0001, ) p.start() for i in range(20): p.update(1) time.sleep(0.001) p.finish() def test_adaptive_transfer_speed(): '''Testing (Adaptive)ETA when the value doesn't actually change''' widgets = [ progressbar.AdaptiveTransferSpeed(), ] p = progressbar.ProgressBar(max_value=2, widgets=widgets, poll_interval=0.0001) p.start() p.update(1) time.sleep(0.001) p.update(1) p.finish() def test_etas(monkeypatch): '''Compare file transfer speed to adaptive transfer speed''' n = 10 interval = datetime.timedelta(seconds=1) widgets = [ progressbar.FileTransferSpeed(), progressbar.AdaptiveTransferSpeed(samples=n / 2), ] datas = [] # Capture the output sent towards the `_speed` method def calculate_eta(self, value, elapsed): '''Capture the widget output''' data = dict( value=value, elapsed=int(elapsed), ) datas.append(data) return 0, 0 monkeypatch.setattr(progressbar.FileTransferSpeed, '_speed', calculate_eta) monkeypatch.setattr(progressbar.AdaptiveTransferSpeed, '_speed', calculate_eta) for widget in widgets: widget.INTERVAL = interval p = progressbar.ProgressBar( max_value=n, widgets=widgets, poll_interval=interval, ) # Run the first few samples at a low speed and speed up later so we can # compare the results from both widgets for i in range(n): p.update(i) if i > n / 2: time.sleep(1) else: time.sleep(10) p.finish() # Due to weird travis issues, the actual testing is disabled for now # import pprint # pprint.pprint(datas[::2]) # pprint.pprint(datas[1::2]) # for i, (a, b) in enumerate(zip(datas[::2], datas[1::2])): # # Because the speed is identical initially, the results should be the # # same for adaptive and regular transfer speed. Only when the speed # # changes we should start see a lot of differences between the two # if i < (n / 2 - 1): # assert a['elapsed'] == b['elapsed'] # if i > (n / 2 + 1): # assert a['elapsed'] > b['elapsed'] def test_non_changing_eta(): '''Testing (Adaptive)ETA when the value doesn't actually change''' widgets = [ progressbar.AdaptiveETA(), progressbar.ETA(), progressbar.AdaptiveTransferSpeed(), ] p = progressbar.ProgressBar(max_value=2, widgets=widgets, poll_interval=0.0001) p.start() p.update(1) time.sleep(0.001) p.update(1) p.finish() def test_eta_not_available(): """ When ETA is not available (data coming from a generator), ETAs should not raise exceptions. """ def gen(): for x in range(200): yield x widgets = [progressbar.AdaptiveETA(), progressbar.ETA()] bar = progressbar.ProgressBar(widgets=widgets) for i in bar(gen()): pass python-progressbar-4.3b.0/tests/test_timer.py000066400000000000000000000025361433023661000214270ustar00rootroot00000000000000import pytest from datetime import timedelta import progressbar @pytest.mark.parametrize('poll_interval,expected', [ (1, 1), (timedelta(seconds=1), 1), (0.001, 0.001), (timedelta(microseconds=1000), 0.001), ]) @pytest.mark.parametrize('parameter', [ 'poll_interval', 'min_poll_interval', ]) def test_poll_interval(parameter, poll_interval, expected): # Test int, float and timedelta intervals bar = progressbar.ProgressBar(**{parameter: poll_interval}) assert getattr(bar, parameter) == expected @pytest.mark.parametrize('interval', [ 1, timedelta(seconds=1), ]) def test_intervals(monkeypatch, interval): monkeypatch.setattr(progressbar.ProgressBar, '_MINIMUM_UPDATE_INTERVAL', interval) bar = progressbar.ProgressBar(max_value=100) # Initially there should be no last_update_time assert bar.last_update_time is None # After updating there should be a last_update_time bar.update(1) assert bar.last_update_time # We should not need an update if the time is nearly the same as before last_update_time = bar.last_update_time bar.update(2) assert bar.last_update_time == last_update_time # We should need an update if we're beyond the poll_interval bar._last_update_time -= 2 bar.update(3) assert bar.last_update_time != last_update_time python-progressbar-4.3b.0/tests/test_unicode.py000066400000000000000000000014031433023661000217250ustar00rootroot00000000000000# -*- coding: utf-8 -*- import time import pytest import progressbar from python_utils import converters @pytest.mark.parametrize('name,markers', [ ('line arrows', u'←↖↑↗→↘↓↙'), ('block arrows', u'◢◣◤◥'), ('wheels', u'◐◓◑◒'), ]) @pytest.mark.parametrize('as_unicode', [True, False]) def test_markers(name, markers, as_unicode): if as_unicode: markers = converters.to_unicode(markers) else: markers = converters.to_str(markers) widgets = [ '%s: ' % name.capitalize(), progressbar.AnimatedMarker(markers=markers), ] bar = progressbar.ProgressBar(widgets=widgets) bar._MINIMUM_UPDATE_INTERVAL = 1e-12 for i in bar((i for i in range(24))): time.sleep(0.001) python-progressbar-4.3b.0/tests/test_unknown_length.py000066400000000000000000000016661433023661000233520ustar00rootroot00000000000000import progressbar def test_unknown_length(): pb = progressbar.ProgressBar(widgets=[progressbar.AnimatedMarker()], max_value=progressbar.UnknownLength) assert pb.max_value is progressbar.UnknownLength def test_unknown_length_default_widgets(): # The default widgets picked should work without a known max_value pb = progressbar.ProgressBar(max_value=progressbar.UnknownLength).start() for i in range(60): pb.update(i) pb.finish() def test_unknown_length_at_start(): # The default widgets should be picked after we call .start() pb = progressbar.ProgressBar().start(max_value=progressbar.UnknownLength) for i in range(60): pb.update(i) pb.finish() pb2 = progressbar.ProgressBar().start(max_value=progressbar.UnknownLength) for w in pb2.widgets: print(type(w), repr(w)) assert any([isinstance(w, progressbar.Bar) for w in pb2.widgets]) python-progressbar-4.3b.0/tests/test_utils.py000066400000000000000000000047621433023661000214520ustar00rootroot00000000000000import io import pytest import progressbar @pytest.mark.parametrize('value,expected', [ (None, None), ('', None), ('1', True), ('y', True), ('t', True), ('yes', True), ('true', True), ('0', False), ('n', False), ('f', False), ('no', False), ('false', False), ]) def test_env_flag(value, expected, monkeypatch): if value is not None: monkeypatch.setenv('TEST_ENV', value) assert progressbar.utils.env_flag('TEST_ENV') == expected if value: monkeypatch.setenv('TEST_ENV', value.upper()) assert progressbar.utils.env_flag('TEST_ENV') == expected monkeypatch.undo() def test_is_terminal(monkeypatch): fd = io.StringIO() monkeypatch.delenv('PROGRESSBAR_IS_TERMINAL', raising=False) monkeypatch.delenv('JPY_PARENT_PID', raising=False) assert progressbar.utils.is_terminal(fd) is False assert progressbar.utils.is_terminal(fd, True) is True assert progressbar.utils.is_terminal(fd, False) is False monkeypatch.setenv('JPY_PARENT_PID', '123') assert progressbar.utils.is_terminal(fd) is True monkeypatch.delenv('JPY_PARENT_PID') # Sanity check assert progressbar.utils.is_terminal(fd) is False monkeypatch.setenv('PROGRESSBAR_IS_TERMINAL', 'true') assert progressbar.utils.is_terminal(fd) is True monkeypatch.setenv('PROGRESSBAR_IS_TERMINAL', 'false') assert progressbar.utils.is_terminal(fd) is False monkeypatch.delenv('PROGRESSBAR_IS_TERMINAL') # Sanity check assert progressbar.utils.is_terminal(fd) is False def test_is_ansi_terminal(monkeypatch): fd = io.StringIO() monkeypatch.delenv('PROGRESSBAR_IS_TERMINAL', raising=False) monkeypatch.delenv('JPY_PARENT_PID', raising=False) assert progressbar.utils.is_ansi_terminal(fd) is False assert progressbar.utils.is_ansi_terminal(fd, True) is True assert progressbar.utils.is_ansi_terminal(fd, False) is False monkeypatch.setenv('JPY_PARENT_PID', '123') assert progressbar.utils.is_ansi_terminal(fd) is True monkeypatch.delenv('JPY_PARENT_PID') # Sanity check assert progressbar.utils.is_ansi_terminal(fd) is False monkeypatch.setenv('PROGRESSBAR_IS_TERMINAL', 'true') assert progressbar.utils.is_ansi_terminal(fd) is False monkeypatch.setenv('PROGRESSBAR_IS_TERMINAL', 'false') assert progressbar.utils.is_ansi_terminal(fd) is False monkeypatch.delenv('PROGRESSBAR_IS_TERMINAL') # Sanity check assert progressbar.utils.is_ansi_terminal(fd) is False python-progressbar-4.3b.0/tests/test_widgets.py000066400000000000000000000147521433023661000217600ustar00rootroot00000000000000import time import pytest import progressbar max_values = [None, 10, progressbar.UnknownLength] def test_create_wrapper(): with pytest.raises(AssertionError): progressbar.widgets.create_wrapper('ab') with pytest.raises(RuntimeError): progressbar.widgets.create_wrapper(123) def test_widgets_small_values(): widgets = [ 'Test: ', progressbar.Percentage(), ' ', progressbar.Bar(marker=progressbar.RotatingMarker()), ' ', progressbar.ETA(), ' ', progressbar.AbsoluteETA(), ' ', progressbar.FileTransferSpeed(), ] p = progressbar.ProgressBar(widgets=widgets, max_value=10).start() p.update(0) for i in range(10): time.sleep(1) p.update(i + 1) p.finish() @pytest.mark.parametrize('max_value', [10 ** 6, 10 ** 8]) def test_widgets_large_values(max_value): widgets = [ 'Test: ', progressbar.Percentage(), ' ', progressbar.Bar(marker=progressbar.RotatingMarker()), ' ', progressbar.ETA(), ' ', progressbar.AbsoluteETA(), ' ', progressbar.FileTransferSpeed(), ] p = progressbar.ProgressBar(widgets=widgets, max_value=max_value).start() for i in range(0, 10 ** 6, 10 ** 4): time.sleep(1) p.update(i + 1) p.finish() def test_format_widget(): widgets = [] for mapping in progressbar.FormatLabel.mapping: widgets.append(progressbar.FormatLabel('%%(%s)r' % mapping)) p = progressbar.ProgressBar(widgets=widgets) for i in p(range(10)): time.sleep(1) @pytest.mark.parametrize('max_value', [None, 10]) def test_all_widgets_small_values(max_value): widgets = [ progressbar.Timer(), progressbar.ETA(), progressbar.AdaptiveETA(), progressbar.AbsoluteETA(), progressbar.DataSize(), progressbar.FileTransferSpeed(), progressbar.AdaptiveTransferSpeed(), progressbar.AnimatedMarker(), progressbar.Counter(), progressbar.Percentage(), progressbar.FormatLabel('%(value)d'), progressbar.SimpleProgress(), progressbar.Bar(), progressbar.ReverseBar(), progressbar.BouncingBar(), progressbar.CurrentTime(), progressbar.CurrentTime(microseconds=False), progressbar.CurrentTime(microseconds=True), ] p = progressbar.ProgressBar(widgets=widgets, max_value=max_value) for i in range(10): time.sleep(1) p.update(i + 1) p.finish() @pytest.mark.parametrize('max_value', [10 ** 6, 10 ** 7]) def test_all_widgets_large_values(max_value): widgets = [ progressbar.Timer(), progressbar.ETA(), progressbar.AdaptiveETA(), progressbar.AbsoluteETA(), progressbar.DataSize(), progressbar.FileTransferSpeed(), progressbar.AdaptiveTransferSpeed(), progressbar.AnimatedMarker(), progressbar.Counter(), progressbar.Percentage(), progressbar.FormatLabel('%(value)d/%(max_value)d'), progressbar.SimpleProgress(), progressbar.Bar(fill=lambda progress, data, width: '#'), progressbar.ReverseBar(), progressbar.BouncingBar(), progressbar.FormatCustomText('Custom %(text)s', dict(text='text')), ] p = progressbar.ProgressBar(widgets=widgets, max_value=max_value) p.update() time.sleep(1) p.update() for i in range(0, 10 ** 6, 10 ** 4): time.sleep(1) p.update(i) @pytest.mark.parametrize('min_width', [None, 1, 2, 80, 120]) @pytest.mark.parametrize('term_width', [1, 2, 80, 120]) def test_all_widgets_min_width(min_width, term_width): widgets = [ progressbar.Timer(min_width=min_width), progressbar.ETA(min_width=min_width), progressbar.AdaptiveETA(min_width=min_width), progressbar.AbsoluteETA(min_width=min_width), progressbar.DataSize(min_width=min_width), progressbar.FileTransferSpeed(min_width=min_width), progressbar.AdaptiveTransferSpeed(min_width=min_width), progressbar.AnimatedMarker(min_width=min_width), progressbar.Counter(min_width=min_width), progressbar.Percentage(min_width=min_width), progressbar.FormatLabel('%(value)d', min_width=min_width), progressbar.SimpleProgress(min_width=min_width), progressbar.Bar(min_width=min_width), progressbar.ReverseBar(min_width=min_width), progressbar.BouncingBar(min_width=min_width), progressbar.FormatCustomText('Custom %(text)s', dict(text='text'), min_width=min_width), progressbar.DynamicMessage('custom', min_width=min_width), progressbar.CurrentTime(min_width=min_width), ] p = progressbar.ProgressBar(widgets=widgets, term_width=term_width) p.update(0) p.update() for widget in p._format_widgets(): if min_width and min_width > term_width: assert widget == '' else: assert widget != '' @pytest.mark.parametrize('max_width', [None, 1, 2, 80, 120]) @pytest.mark.parametrize('term_width', [1, 2, 80, 120]) def test_all_widgets_max_width(max_width, term_width): widgets = [ progressbar.Timer(max_width=max_width), progressbar.ETA(max_width=max_width), progressbar.AdaptiveETA(max_width=max_width), progressbar.AbsoluteETA(max_width=max_width), progressbar.DataSize(max_width=max_width), progressbar.FileTransferSpeed(max_width=max_width), progressbar.AdaptiveTransferSpeed(max_width=max_width), progressbar.AnimatedMarker(max_width=max_width), progressbar.Counter(max_width=max_width), progressbar.Percentage(max_width=max_width), progressbar.FormatLabel('%(value)d', max_width=max_width), progressbar.SimpleProgress(max_width=max_width), progressbar.Bar(max_width=max_width), progressbar.ReverseBar(max_width=max_width), progressbar.BouncingBar(max_width=max_width), progressbar.FormatCustomText('Custom %(text)s', dict(text='text'), max_width=max_width), progressbar.DynamicMessage('custom', max_width=max_width), progressbar.CurrentTime(max_width=max_width), ] p = progressbar.ProgressBar(widgets=widgets, term_width=term_width) p.update(0) p.update() for widget in p._format_widgets(): if max_width and max_width < term_width: assert widget == '' else: assert widget != '' python-progressbar-4.3b.0/tests/test_with.py000066400000000000000000000006551433023661000212620ustar00rootroot00000000000000import progressbar def test_with(): with progressbar.ProgressBar(max_value=10) as p: for i in range(10): p.update(i) def test_with_stdout_redirection(): with progressbar.ProgressBar(max_value=10, redirect_stdout=True) as p: for i in range(10): p.update(i) def test_with_extra_start(): with progressbar.ProgressBar(max_value=10) as p: p.start() p.start() python-progressbar-4.3b.0/tests/test_wrappingio.py000066400000000000000000000026411433023661000224630ustar00rootroot00000000000000import io import sys import pytest from progressbar import utils def test_wrappingio(): # Test the wrapping of our version of sys.stdout` ` q fd = utils.WrappingIO(sys.stdout) assert fd.fileno() assert not fd.isatty() assert not fd.read() assert not fd.readline() assert not fd.readlines() assert fd.readable() assert not fd.seek(0) assert fd.seekable() assert not fd.tell() assert not fd.truncate() assert fd.writable() assert fd.write('test') assert not fd.writelines(['test']) with pytest.raises(StopIteration): next(fd) with pytest.raises(StopIteration): next(iter(fd)) def test_wrapping_stringio(): # Test the wrapping of our version of sys.stdout` ` q string_io = io.StringIO() fd = utils.WrappingIO(string_io) with fd: with pytest.raises(io.UnsupportedOperation): fd.fileno() assert not fd.isatty() assert not fd.read() assert not fd.readline() assert not fd.readlines() assert fd.readable() assert not fd.seek(0) assert fd.seekable() assert not fd.tell() assert not fd.truncate() assert fd.writable() assert fd.write('test') assert not fd.writelines(['test']) with pytest.raises(StopIteration): next(fd) with pytest.raises(StopIteration): next(iter(fd)) python-progressbar-4.3b.0/tox.ini000066400000000000000000000025571433023661000170520ustar00rootroot00000000000000[tox] envlist = py37, py38, py39, py310, flake8, docs, black, mypy, pyright skip_missing_interpreters = True [testenv] basepython = py36: python3.6 py37: python3.7 py38: python3.8 py39: python3.9 py310: python3.10 pypy3: pypy3 deps = -r{toxinidir}/tests/requirements.txt commands = py.test --basetemp="{envtmpdir}" --confcutdir=.. {posargs} changedir = tests [testenv:flake8] changedir = basepython = python3 deps = flake8 commands = flake8 {toxinidir}/progressbar {toxinidir}/tests {toxinidir}/examples.py [testenv:mypy] changedir = basepython = python3 deps = mypy commands = mypy {toxinidir}/progressbar [testenv:pyright] changedir = basepython = python3 deps = pyright commands = pyright {toxinidir}/progressbar [testenv:black] basepython = python3 deps = black commands = black --skip-string-normalization --line-length 79 {toxinidir}/progressbar [testenv:docs] changedir = basepython = python3 deps = -r{toxinidir}/docs/requirements.txt whitelist_externals = rm cd mkdir commands = rm -f docs/modules.rst mkdir -p docs/_static sphinx-apidoc -e -o docs/ progressbar rm -f docs/modules.rst rm -f docs/progressbar.rst sphinx-build -W -b html -d docs/_build/doctrees docs docs/_build/html {posargs} [flake8] ignore = W391, W504, E741, W503, E131 exclude = docs, progressbar/six.py tests/original_examples.py