summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.pre-commit-config.yaml12
-rw-r--r--CONTRIBUTING.md48
-rw-r--r--DEMO.ipynb12
-rw-r--r--LICENCE4
-rw-r--r--Makefile26
-rw-r--r--PKG-INFO1581
-rw-r--r--README.rst68
-rw-r--r--environment.yml11
-rw-r--r--examples/7zx.py2
-rw-r--r--examples/async_coroutines.py4
-rw-r--r--examples/parallel_bars.py18
-rw-r--r--examples/redirect_print.py2
-rw-r--r--examples/simple_examples.py7
-rw-r--r--examples/tqdm_wget.py5
-rw-r--r--pyproject.toml128
-rw-r--r--setup.cfg159
-rwxr-xr-xsetup.py16
-rw-r--r--tests/conftest.py18
-rw-r--r--tests/py37_asyncio.py128
-rw-r--r--tests/tests_asyncio.py140
-rw-r--r--tests/tests_contrib.py22
-rw-r--r--tests/tests_contrib_logging.py2
-rw-r--r--tests/tests_dask.py2
-rw-r--r--tests/tests_keras.py18
-rw-r--r--tests/tests_main.py63
-rw-r--r--tests/tests_pandas.py54
-rw-r--r--tests/tests_perf.py38
-rw-r--r--tests/tests_rich.py5
-rw-r--r--tests/tests_synchronisation.py25
-rw-r--r--tests/tests_tqdm.py124
-rw-r--r--tests/tests_utils.py51
-rw-r--r--tox.ini47
-rw-r--r--tqdm.egg-info/PKG-INFO1581
-rw-r--r--tqdm.egg-info/SOURCES.txt88
-rw-r--r--tqdm.egg-info/dependency_links.txt1
-rw-r--r--tqdm.egg-info/entry_points.txt2
-rw-r--r--tqdm.egg-info/requires.txt20
-rw-r--r--tqdm.egg-info/top_level.txt1
-rw-r--r--tqdm/__init__.py5
-rw-r--r--tqdm/_dist_ver.py1
-rw-r--r--tqdm/_utils.py7
-rw-r--r--tqdm/asyncio.py2
-rw-r--r--tqdm/auto.py40
-rw-r--r--tqdm/cli.py74
-rw-r--r--tqdm/contrib/__init__.py16
-rw-r--r--tqdm/contrib/concurrent.py37
-rw-r--r--tqdm/contrib/discord.py12
-rw-r--r--tqdm/contrib/itertools.py2
-rw-r--r--tqdm/contrib/logging.py4
-rw-r--r--tqdm/contrib/slack.py12
-rw-r--r--tqdm/contrib/telegram.py12
-rw-r--r--tqdm/contrib/utils_worker.py2
-rw-r--r--tqdm/dask.py2
-rw-r--r--tqdm/gui.py13
-rw-r--r--tqdm/keras.py4
-rw-r--r--tqdm/notebook.py22
-rw-r--r--tqdm/rich.py10
-rw-r--r--tqdm/std.py345
-rw-r--r--tqdm/tk.py21
-rw-r--r--tqdm/tqdm.16
-rw-r--r--tqdm/utils.py107
61 files changed, 921 insertions, 4368 deletions
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 95b4a82..4de1025 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -2,7 +2,7 @@ default_language_version:
python: python3
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
- rev: v4.1.0
+ rev: v4.5.0
hooks:
- id: check-added-large-files
- id: check-case-conflict
@@ -38,8 +38,8 @@ repos:
- pandas
- pytest-timeout
- pytest-asyncio
-- repo: https://gitlab.com/pycqa/flake8
- rev: 3.9.2
+- repo: https://github.com/PyCQA/flake8
+ rev: 7.0.0
hooks:
- id: flake8
args: [-j8]
@@ -49,14 +49,14 @@ repos:
- flake8-comprehensions
- flake8-debugger
- flake8-isort
+ - flake8-pyproject
- flake8-string-format
- - flake8-type-annotations
- repo: https://github.com/PyCQA/isort
- rev: 5.10.1
+ rev: 5.13.2
hooks:
- id: isort
- repo: https://github.com/kynan/nbstripout
- rev: 0.5.0
+ rev: 0.7.1
hooks:
- id: nbstripout
args: [--keep-count, --keep-output]
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 4cd86d0..533a8ab 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -12,7 +12,7 @@ Makefile:
```
make [<alias>] # on UNIX-like environments
-python setup.py make [<alias>] # if make is unavailable
+python -m pymake [<alias>] # if make is unavailable
```
The latter depends on [`py-make>=0.1.0`](https://github.com/tqdm/py-make).
@@ -51,7 +51,7 @@ However it would be helpful to bear in mind:
* use two spaces between variable name and colon, specify a type, and most likely state that it's optional: `VAR<space><space>:<space>TYPE[, optional]`
* use [default: ...] for default values of keyword arguments
+ will not break backward compatibility unless there is a very good reason
- * e.g. breaking py26 compatibility purely in favour of readability (such as converting `dict(a=1)` to `{'a': 1}`) is not a good enough reason
+ * e.g. breaking py26 compatibility purely in favour of minor readability changes (such as converting `dict(a=1)` to `{'a': 1}`) is not a good enough reason
+ API changes should be discussed carefully
+ remember, with millions of downloads per month, `tqdm` must be extremely fast and reliable
- Any other kind of change may be included in a (possibly new) submodule
@@ -85,7 +85,7 @@ The standard way to run the tests:
- run the following command:
```
-[python setup.py] make test
+[python -m py]make test
# or:
tox --skip-missing-interpreters
```
@@ -97,19 +97,19 @@ versions of Python.)
Note: to install all versions of the Python interpreter that are specified
in [tox.ini](https://github.com/tqdm/tqdm/blob/master/tox.ini),
-you can use `MiniConda` to install a minimal setup. You must also make sure
-that each distribution has an alias to call the Python interpreter:
-`python27` for Python 2.7's interpreter, `python32` for Python 3.2's, etc.
+you can use `MiniConda` to install a minimal setup. You must also ensure
+that each distribution has an alias to call the Python interpreter
+(e.g. `python311` for Python 3.11's interpreter).
### Alternative unit tests with pytest
Alternatively, use `pytest` to run the tests just for the current Python version:
-- install test requirements: `[python setup.py] make install_test`
+- install test requirements: `[python -m py]make install_test`
- run the following command:
```
-[python setup.py] make alltests
+[python -m py]make alltests
```
@@ -118,9 +118,9 @@ Alternatively, use `pytest` to run the tests just for the current Python version
This section is intended for the project's maintainers and describes
how to build and upload a new release. Once again,
-`[python setup.py] make [<alias>]` will help.
+`[python -m py]make [<alias>]` will help.
Also consider `pip install`ing development utilities:
-`[python setup.py] make install_build` at a minimum, or a more thorough `conda env create`.
+`[python -m py]make install_build` at a minimum, or a more thorough `conda env create`.
## Pre-commit Hook
@@ -137,20 +137,20 @@ The `tqdm` repository managers should:
- follow the [Semantic Versioning](https://semver.org) convention for tagging
-## Checking setup.py
+## Checking `pyproject.toml`
-To check that the `setup.py`/`setup.cfg`/`pyproject.toml` file is compliant with PyPI
+To check that the `pyproject.toml` file is compliant with PyPI
requirements (e.g. version number; reStructuredText in `README.rst`) use:
```
-[python setup.py] make testsetup
+[python -m py]make testsetup
```
To upload just metadata (including overwriting mistakenly uploaded metadata)
to PyPI, use:
```
-[python setup.py] make pypimeta
+[python -m py]make pypimeta
```
@@ -199,7 +199,7 @@ git merge --no-ff pr-branch-name
### 4 Test
```
-[python setup.py] make alltests
+[python -m py]make alltests
```
### 5 Push to master
@@ -233,7 +233,7 @@ Manual instructions are given below in case of failure.
Build `tqdm` into a distributable python package:
```
-[python setup.py] make build
+[python -m py]make build
```
This will generate several builds in the `dist/` folder. On non-windows
@@ -243,13 +243,13 @@ Finally, upload everything to PyPI. This can be done easily using the
[twine](https://github.com/pypa/twine) module:
```
-[python setup.py] make pypi
+[python -m py]make pypi
```
Also, the new release can (should) be added to GitHub by creating a new
release from the [web interface](https://github.com/tqdm/tqdm/releases);
uploading packages from the `dist/` folder
-created by `[python setup.py] make build`.
+created by `[python -m py]make build`.
The [wiki] can be automatically updated with GitHub release notes by
running `make` within the wiki repository.
@@ -282,7 +282,7 @@ before the real deployment
- in case of a mistake, you can delete an uploaded release on PyPI, but you
cannot re-upload another with the same version number
- in case of a mistake in the metadata on PyPI (e.g. bad README),
-updating just the metadata is possible: `[python setup.py] make pypimeta`
+updating just the metadata is possible: `[python -m py]make pypimeta`
## Updating Websites
@@ -333,16 +333,16 @@ to assist with maintenance.
For experienced devs, once happy with local master, follow the steps below.
Much is automated so really it's steps 1-5, then 11(a).
-1. test (`[python setup.py] make alltests` or rely on `pre-commit`)
+1. test (`[python -m py]make alltests` or rely on `pre-commit`)
2. `git commit [--amend] # -m "bump version"`
3. `git push`
4. wait for tests to pass
a) in case of failure, fix and go back to (1)
5. `git tag vM.m.p && git push --tags` or comment `/tag vM.m.p commit_hash`
-6. **`[AUTO:GHA]`** `[python setup.py] make distclean`
-7. **`[AUTO:GHA]`** `[python setup.py] make build`
+6. **`[AUTO:GHA]`** `[python -m py]make distclean`
+7. **`[AUTO:GHA]`** `[python -m py]make build`
8. **`[AUTO:GHA]`** upload to PyPI. either:
- a) `[python setup.py] make pypi`, or
+ a) `[python -m py]make pypi`, or
b) `twine upload -s -i $(git config user.signingkey) dist/tqdm-*`
9. **`[AUTO:GHA]`** upload to docker hub:
a) `make -B docker`
@@ -359,7 +359,7 @@ Much is automated so really it's steps 1-5, then 11(a).
13. **`[SUB][AUTO:GHA-rel]`** run `make deploy` in the `docs` submodule to update website
14. **`[SUB][AUTO:GHA-rel]`** accept the automated PR in the `feedstock` submodule to update conda
15. **`[AUTO:GHA-rel]`** update the [gh-pages project] benchmarks
- a) `[python setup.py] make testasvfull`
+ a) `[python -m py]make testasvfull`
b) `asv gh-pages`
Key:
diff --git a/DEMO.ipynb b/DEMO.ipynb
index b892af4..8048cbc 100644
--- a/DEMO.ipynb
+++ b/DEMO.ipynb
@@ -5,12 +5,12 @@
"metadata": {},
"source": [
"<h1 align=\"center\">tqdm</h1>\n",
- "<img src=\"https://img.tqdm.ml/logo.gif\" align=\"left\" />\n",
+ "<img src=\"https://tqdm.github.io/img/logo.gif\" align=\"left\" />\n",
"\n",
"[![Py-Versions](https://img.shields.io/pypi/pyversions/tqdm.svg?logo=python&logoColor=white)](https://pypi.org/project/tqdm)|[![Versions](https://img.shields.io/pypi/v/tqdm.svg)](https://tqdm.github.io/releases)|[![Conda-Forge-Status](https://img.shields.io/conda/v/conda-forge/tqdm.svg?label=conda-forge&logo=conda-forge)](https://anaconda.org/conda-forge/tqdm)|[![Docker](https://img.shields.io/badge/docker-pull-blue.svg?logo=docker&logoColor=white)](https://hub.docker.com/r/tqdm/tqdm)|[![Snapcraft](https://img.shields.io/badge/snap-install-82BEA0.svg?logo=snapcraft)](https://snapcraft.io/tqdm)\n",
"-|-|-|-|-\n",
"\n",
- "[![Build-Status](https://img.shields.io/github/workflow/status/tqdm/tqdm/Test/master?logo=GitHub)](https://github.com/tqdm/tqdm/actions?query=workflow%3ATest)|[![Coverage-Status](https://img.shields.io/coveralls/github/tqdm/tqdm/master?logo=coveralls)](https://coveralls.io/github/tqdm/tqdm)|[![Branch-Coverage-Status](https://codecov.io/gh/tqdm/tqdm/branch/master/graph/badge.svg)](https://codecov.io/gh/tqdm/tqdm)|[![Codacy-Grade](https://app.codacy.com/project/badge/Grade/3f965571598f44549c7818f29cdcf177)](https://www.codacy.com/gh/tqdm/tqdm/dashboard)|[![Libraries-Rank](https://img.shields.io/librariesio/sourcerank/pypi/tqdm.svg?logo=koding&logoColor=white)](https://libraries.io/pypi/tqdm)|[![PyPI-Downloads](https://img.shields.io/pypi/dm/tqdm.svg?label=pypi%20downloads&logo=PyPI&logoColor=white)](https://pepy.tech/project/tqdm)\n",
+ "[![Build-Status](https://img.shields.io/github/actions/workflow/status/tqdm/tqdm/test.yml?branch=master&label=tqdm&logo=GitHub)](https://github.com/tqdm/tqdm/actions/workflows/test.yml)|[![Coverage-Status](https://img.shields.io/coveralls/github/tqdm/tqdm/master?logo=coveralls)](https://coveralls.io/github/tqdm/tqdm)|[![Branch-Coverage-Status](https://codecov.io/gh/tqdm/tqdm/branch/master/graph/badge.svg)](https://codecov.io/gh/tqdm/tqdm)|[![Codacy-Grade](https://app.codacy.com/project/badge/Grade/3f965571598f44549c7818f29cdcf177)](https://www.codacy.com/gh/tqdm/tqdm/dashboard)|[![Libraries-Rank](https://img.shields.io/librariesio/sourcerank/pypi/tqdm.svg?logo=koding&logoColor=white)](https://libraries.io/pypi/tqdm)|[![PyPI-Downloads](https://img.shields.io/pypi/dm/tqdm.svg?label=pypi%20downloads&logo=PyPI&logoColor=white)](https://pepy.tech/project/tqdm)\n",
"-|-|-|-|-|-\n",
"\n",
"[![DOI](https://img.shields.io/badge/DOI-10.5281/zenodo.595120-blue.svg)](https://doi.org/10.5281/zenodo.595120)|[![LICENCE](https://img.shields.io/pypi/l/tqdm.svg)](https://raw.githubusercontent.com/tqdm/tqdm/master/LICENCE)|[![OpenHub-Status](https://www.openhub.net/p/tqdm/widgets/project_thin_badge?format=gif)](https://www.openhub.net/p/tqdm?ref=Thin+badge)|[![binder-demo](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/tqdm/tqdm/master?filepath=DEMO.ipynb)|[![awesome-python](https://awesome.re/mentioned-badge.svg)](https://github.com/vinta/awesome-python)\n",
@@ -40,7 +40,7 @@
"metadata": {},
"source": [
"`trange(N)` can be also used as a convenient shortcut for\n",
- "`tqdm(xrange(N))`."
+ "`tqdm(range(N))`."
]
},
{
@@ -58,7 +58,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
- "![Screenshot](https://img.tqdm.ml/tqdm.gif)|[![Video](https://img.tqdm.ml/video.jpg)](https://tqdm.github.io/video) [![Slides](https://img.tqdm.ml/slides.jpg)](https://tqdm.github.io/PyData2019/slides.html) [![Merch](https://img.tqdm.ml/merch.jpg)](https://tqdm.github.io/merch)\n",
+ "![Screenshot](https://tqdm.github.io/img/tqdm.gif)|[![Video](https://tqdm.github.io/img/video.jpg)](https://tqdm.github.io/video) [![Slides](https://tqdm.github.io/img/slides.jpg)](https://tqdm.github.io/PyData2019/slides.html) [![Merch](https://tqdm.github.io/img/merch.jpg)](https://tqdm.github.io/merch)\n",
"-|-\n",
"\n",
"It can also be executed as a module with pipes:"
@@ -737,7 +737,7 @@
"bars and colour hints (blue: normal, green: completed, red:\n",
"error/interrupt, light blue: no ETA); as demonstrated below.\n",
"\n",
- "![Screenshot-Jupyter3](https://img.tqdm.ml/jupyter-3.gif)\n",
+ "![Screenshot-Jupyter3](https://tqdm.github.io/img/jupyter-3.gif)\n",
"\n",
"The `notebook` version supports percentage or pixels for overall width\n",
"(e.g.: `ncols='100%'` or `ncols='480px'`).\n",
@@ -843,7 +843,7 @@
"specify any file-like object using the `file` argument. For example,\n",
"this can be used to redirect the messages writing to a log file or class.\n",
"\n",
- "[![README-Hits](https://caspersci.uk.to/cgi-bin/hits.cgi?q=tqdm&style=social&r=https://github.com/tqdm/tqdm&l=https://img.tqdm.ml/favicon.png&f=https://img.tqdm.ml/logo.gif)](https://caspersci.uk.to/cgi-bin/hits.cgi?q=tqdm&a=plot&r=https://github.com/tqdm/tqdm&l=https://img.tqdm.ml/favicon.png&f=https://img.tqdm.ml/logo.gif&style=social)|(Since 19 May 2016)\n",
+ "[![README-Hits](https://caspersci.uk.to/cgi-bin/hits.cgi?q=tqdm&style=social&r=https://github.com/tqdm/tqdm&l=https://tqdm.github.io/img/favicon.png&f=https://tqdm.github.io/img/logo.gif)](https://caspersci.uk.to/cgi-bin/hits.cgi?q=tqdm&a=plot&r=https://github.com/tqdm/tqdm&l=https://tqdm.github.io/img/favicon.png&f=https://tqdm.github.io/img/logo.gif&style=social)|(Since 19 May 2016)\n",
"-|-"
]
},
diff --git a/LICENCE b/LICENCE
index 5b3cab7..a8922b1 100644
--- a/LICENCE
+++ b/LICENCE
@@ -7,11 +7,11 @@ Exceptions or notable authors are listed below
in reverse chronological order:
* files: *
- MPLv2.0 2015-2021 (c) Casper da Costa-Luis
+ MPL-2.0 2015-2024 (c) Casper da Costa-Luis
[casperdcl](https://github.com/casperdcl).
* files: tqdm/_tqdm.py
MIT 2016 (c) [PR #96] on behalf of Google Inc.
-* files: tqdm/_tqdm.py setup.py README.rst MANIFEST.in .gitignore
+* files: tqdm/_tqdm.py README.rst .gitignore
MIT 2013 (c) Noam Yorav-Raphael, original author.
[PR #96]: https://github.com/tqdm/tqdm/pull/96
diff --git a/Makefile b/Makefile
index 796f8b0..ab2863c 100644
--- a/Makefile
+++ b/Makefile
@@ -1,4 +1,4 @@
-# IMPORTANT: for compatibility with `python setup.py make [alias]`, ensure:
+# IMPORTANT: for compatibility with `python -m pymake [alias]`, ensure:
# 1. Every alias is preceded by @[+]make (eg: @make alias)
# 2. A maximum of one @make alias or command per line
# see: https://github.com/tqdm/py-make/issues/1
@@ -31,7 +31,7 @@
run
help:
- @python setup.py make -p
+ @python -m pymake -p
alltests:
@+make testcoverage
@@ -58,15 +58,14 @@ testsetup:
@make README.rst
@make tqdm/tqdm.1
@make tqdm/completion.sh
- python setup.py check --metadata --restructuredtext --strict
- python setup.py make none
+ @make help
testnb:
- pytest tests_notebook.ipynb --nbval --nbval-current-env -W=ignore --nbval-sanitize-with=setup.cfg --cov=tqdm.notebook --cov-report=term
+ pytest tests_notebook.ipynb --cov=tqdm.notebook --cov-report=term -W=ignore --nbval --current-env --sanitize-with=.meta/nbval.ini
testcoverage:
@make coverclean
- pytest tests_notebook.ipynb --cov=tqdm --cov-report= --nbval --nbval-current-env --nbval-sanitize-with=setup.cfg -W=ignore
+ pytest tests_notebook.ipynb --cov=tqdm --cov-report= -W=ignore --nbval --current-env --sanitize-with=.meta/nbval.ini
pytest -k "not perf" --cov=tqdm --cov-report=xml --cov-report=term --cov-append --cov-fail-under=80
testperf:
@@ -138,9 +137,9 @@ clean:
@+python -c "import os, glob; [os.remove(i) for i in glob.glob('*.py[co]')]"
@+python -c "import os, glob; [os.remove(i) for i in glob.glob('tests/*.py[co]')]"
@+python -c "import os, glob; [os.remove(i) for i in glob.glob('benchmarks/*.py[co]')]"
+ @+python -c "import os, glob; [os.remove(i) for i in glob.glob('examples/*.py[co]')]"
@+python -c "import os, glob; [os.remove(i) for i in glob.glob('tqdm/*.py[co]')]"
@+python -c "import os, glob; [os.remove(i) for i in glob.glob('tqdm/contrib/*.py[co]')]"
- @+python -c "import os, glob; [os.remove(i) for i in glob.glob('tqdm/examples/*.py[co]')]"
toxclean:
@+python -c "import shutil; shutil.rmtree('.tox', True)"
@@ -152,12 +151,11 @@ submodules:
cd feedstock && git remote add autotick-bot git@github.com:regro-cf-autotick-bot/tqdm-feedstock
install:
- python setup.py install
+ python -m pip install .
install_dev:
- python setup.py develop --uninstall
- python setup.py develop
+ python -m pip install -e .
install_build:
- python -m pip install -r .meta/requirements-dev.txt
+ python -m pip install -r .meta/requirements-build.txt
install_test:
python -m pip install -r .meta/requirements-test.txt
pre-commit install
@@ -165,11 +163,11 @@ install_test:
build:
@make prebuildclean
@make testsetup
- python setup.py sdist bdist_wheel
- # python setup.py bdist_wininst
+ python -m build
+ python -m twine check dist/*
pypi:
- twine upload dist/*
+ python -m twine upload dist/*
buildupload:
@make build
diff --git a/PKG-INFO b/PKG-INFO
deleted file mode 100644
index d796709..0000000
--- a/PKG-INFO
+++ /dev/null
@@ -1,1581 +0,0 @@
-Metadata-Version: 2.1
-Name: tqdm
-Version: 4.64.1
-Summary: Fast, Extensible Progress Meter
-Home-page: https://tqdm.github.io
-Maintainer: tqdm developers
-Maintainer-email: python.tqdm@gmail.com
-License: MPLv2.0, MIT Licences
-Project-URL: Changelog, https://tqdm.github.io/releases
-Project-URL: Source, https://github.com/tqdm/tqdm
-Project-URL: Wiki, https://github.com/tqdm/tqdm/wiki
-Keywords: progressbar,progressmeter,progress,bar,meter,rate,eta,console,terminal,time
-Platform: any
-Classifier: Development Status :: 5 - Production/Stable
-Classifier: Environment :: Console
-Classifier: Environment :: MacOS X
-Classifier: Environment :: Other Environment
-Classifier: Environment :: Win32 (MS Windows)
-Classifier: Environment :: X11 Applications
-Classifier: Framework :: IPython
-Classifier: Framework :: Jupyter
-Classifier: Intended Audience :: Developers
-Classifier: Intended Audience :: Education
-Classifier: Intended Audience :: End Users/Desktop
-Classifier: Intended Audience :: Other Audience
-Classifier: Intended Audience :: System Administrators
-Classifier: License :: OSI Approved :: MIT License
-Classifier: License :: OSI Approved :: Mozilla Public License 2.0 (MPL 2.0)
-Classifier: Operating System :: MacOS
-Classifier: Operating System :: MacOS :: MacOS X
-Classifier: Operating System :: Microsoft
-Classifier: Operating System :: Microsoft :: MS-DOS
-Classifier: Operating System :: Microsoft :: Windows
-Classifier: Operating System :: POSIX
-Classifier: Operating System :: POSIX :: BSD
-Classifier: Operating System :: POSIX :: BSD :: FreeBSD
-Classifier: Operating System :: POSIX :: Linux
-Classifier: Operating System :: POSIX :: SunOS/Solaris
-Classifier: Operating System :: Unix
-Classifier: Programming Language :: Python
-Classifier: Programming Language :: Python :: 2
-Classifier: Programming Language :: Python :: 2.7
-Classifier: Programming Language :: Python :: 3
-Classifier: Programming Language :: Python :: 3.5
-Classifier: Programming Language :: Python :: 3.6
-Classifier: Programming Language :: Python :: 3.7
-Classifier: Programming Language :: Python :: 3.8
-Classifier: Programming Language :: Python :: 3.9
-Classifier: Programming Language :: Python :: 3.10
-Classifier: Programming Language :: Python :: Implementation
-Classifier: Programming Language :: Python :: Implementation :: IronPython
-Classifier: Programming Language :: Python :: Implementation :: PyPy
-Classifier: Programming Language :: Unix Shell
-Classifier: Topic :: Desktop Environment
-Classifier: Topic :: Education :: Computer Aided Instruction (CAI)
-Classifier: Topic :: Education :: Testing
-Classifier: Topic :: Office/Business
-Classifier: Topic :: Other/Nonlisted Topic
-Classifier: Topic :: Software Development :: Build Tools
-Classifier: Topic :: Software Development :: Libraries
-Classifier: Topic :: Software Development :: Libraries :: Python Modules
-Classifier: Topic :: Software Development :: Pre-processors
-Classifier: Topic :: Software Development :: User Interfaces
-Classifier: Topic :: System :: Installation/Setup
-Classifier: Topic :: System :: Logging
-Classifier: Topic :: System :: Monitoring
-Classifier: Topic :: System :: Shells
-Classifier: Topic :: Terminals
-Classifier: Topic :: Utilities
-Provides: tqdm
-Requires-Python: !=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,>=2.7
-Description-Content-Type: text/x-rst
-Provides-Extra: dev
-Provides-Extra: slack
-Provides-Extra: telegram
-Provides-Extra: notebook
-License-File: LICENCE
-
-|Logo|
-
-tqdm
-====
-
-|Py-Versions| |Versions| |Conda-Forge-Status| |Docker| |Snapcraft|
-
-|Build-Status| |Coverage-Status| |Branch-Coverage-Status| |Codacy-Grade| |Libraries-Rank| |PyPI-Downloads|
-
-|LICENCE| |OpenHub-Status| |binder-demo| |awesome-python|
-
-``tqdm`` derives from the Arabic word *taqaddum* (تقدّم) which can mean "progress,"
-and is an abbreviation for "I love you so much" in Spanish (*te quiero demasiado*).
-
-Instantly make your loops show a smart progress meter - just wrap any
-iterable with ``tqdm(iterable)``, and you're done!
-
-.. code:: python
-
- from tqdm import tqdm
- for i in tqdm(range(10000)):
- ...
-
-``76%|████████████████████████        | 7568/10000 [00:33<00:10, 229.00it/s]``
-
-``trange(N)`` can be also used as a convenient shortcut for
-``tqdm(range(N))``.
-
-|Screenshot|
- |Video| |Slides| |Merch|
-
-It can also be executed as a module with pipes:
-
-.. code:: sh
-
- $ seq 9999999 | tqdm --bytes | wc -l
- 75.2MB [00:00, 217MB/s]
- 9999999
-
- $ tar -zcf - docs/ | tqdm --bytes --total `du -sb docs/ | cut -f1` \
- > backup.tgz
- 32%|██████████▍ | 8.89G/27.9G [00:42<01:31, 223MB/s]
-
-Overhead is low -- about 60ns per iteration (80ns with ``tqdm.gui``), and is
-unit tested against performance regression.
-By comparison, the well-established
-`ProgressBar <https://github.com/niltonvolpato/python-progressbar>`__ has
-an 800ns/iter overhead.
-
-In addition to its low overhead, ``tqdm`` uses smart algorithms to predict
-the remaining time and to skip unnecessary iteration displays, which allows
-for a negligible overhead in most cases.
-
-``tqdm`` works on any platform
-(Linux, Windows, Mac, FreeBSD, NetBSD, Solaris/SunOS),
-in any console or in a GUI, and is also friendly with IPython/Jupyter notebooks.
-
-``tqdm`` does not require any dependencies (not even ``curses``!), just
-Python and an environment supporting ``carriage return \r`` and
-``line feed \n`` control characters.
-
-------------------------------------------
-
-.. contents:: Table of contents
- :backlinks: top
- :local:
-
-
-Installation
-------------
-
-Latest PyPI stable release
-~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-|Versions| |PyPI-Downloads| |Libraries-Dependents|
-
-.. code:: sh
-
- pip install tqdm
-
-Latest development release on GitHub
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-|GitHub-Status| |GitHub-Stars| |GitHub-Commits| |GitHub-Forks| |GitHub-Updated|
-
-Pull and install pre-release ``devel`` branch:
-
-.. code:: sh
-
- pip install "git+https://github.com/tqdm/tqdm.git@devel#egg=tqdm"
-
-Latest Conda release
-~~~~~~~~~~~~~~~~~~~~
-
-|Conda-Forge-Status|
-
-.. code:: sh
-
- conda install -c conda-forge tqdm
-
-Latest Snapcraft release
-~~~~~~~~~~~~~~~~~~~~~~~~
-
-|Snapcraft|
-
-There are 3 channels to choose from:
-
-.. code:: sh
-
- snap install tqdm # implies --stable, i.e. latest tagged release
- snap install tqdm --candidate # master branch
- snap install tqdm --edge # devel branch
-
-Note that ``snap`` binaries are purely for CLI use (not ``import``-able), and
-automatically set up ``bash`` tab-completion.
-
-Latest Docker release
-~~~~~~~~~~~~~~~~~~~~~
-
-|Docker|
-
-.. code:: sh
-
- docker pull tqdm/tqdm
- docker run -i --rm tqdm/tqdm --help
-
-Other
-~~~~~
-
-There are other (unofficial) places where ``tqdm`` may be downloaded, particularly for CLI use:
-
-|Repology|
-
-.. |Repology| image:: https://repology.org/badge/tiny-repos/python:tqdm.svg
- :target: https://repology.org/project/python:tqdm/versions
-
-Changelog
----------
-
-The list of all changes is available either on GitHub's Releases:
-|GitHub-Status|, on the
-`wiki <https://github.com/tqdm/tqdm/wiki/Releases>`__, or on the
-`website <https://tqdm.github.io/releases>`__.
-
-
-Usage
------
-
-``tqdm`` is very versatile and can be used in a number of ways.
-The three main ones are given below.
-
-Iterable-based
-~~~~~~~~~~~~~~
-
-Wrap ``tqdm()`` around any iterable:
-
-.. code:: python
-
- from tqdm import tqdm
- from time import sleep
-
- text = ""
- for char in tqdm(["a", "b", "c", "d"]):
- sleep(0.25)
- text = text + char
-
-``trange(i)`` is a special optimised instance of ``tqdm(range(i))``:
-
-.. code:: python
-
- from tqdm import trange
-
- for i in trange(100):
- sleep(0.01)
-
-Instantiation outside of the loop allows for manual control over ``tqdm()``:
-
-.. code:: python
-
- pbar = tqdm(["a", "b", "c", "d"])
- for char in pbar:
- sleep(0.25)
- pbar.set_description("Processing %s" % char)
-
-Manual
-~~~~~~
-
-Manual control of ``tqdm()`` updates using a ``with`` statement:
-
-.. code:: python
-
- with tqdm(total=100) as pbar:
- for i in range(10):
- sleep(0.1)
- pbar.update(10)
-
-If the optional variable ``total`` (or an iterable with ``len()``) is
-provided, predictive stats are displayed.
-
-``with`` is also optional (you can just assign ``tqdm()`` to a variable,
-but in this case don't forget to ``del`` or ``close()`` at the end:
-
-.. code:: python
-
- pbar = tqdm(total=100)
- for i in range(10):
- sleep(0.1)
- pbar.update(10)
- pbar.close()
-
-Module
-~~~~~~
-
-Perhaps the most wonderful use of ``tqdm`` is in a script or on the command
-line. Simply inserting ``tqdm`` (or ``python -m tqdm``) between pipes will pass
-through all ``stdin`` to ``stdout`` while printing progress to ``stderr``.
-
-The example below demonstrate counting the number of lines in all Python files
-in the current directory, with timing information included.
-
-.. code:: sh
-
- $ time find . -name '*.py' -type f -exec cat \{} \; | wc -l
- 857365
-
- real 0m3.458s
- user 0m0.274s
- sys 0m3.325s
-
- $ time find . -name '*.py' -type f -exec cat \{} \; | tqdm | wc -l
- 857366it [00:03, 246471.31it/s]
- 857365
-
- real 0m3.585s
- user 0m0.862s
- sys 0m3.358s
-
-Note that the usual arguments for ``tqdm`` can also be specified.
-
-.. code:: sh
-
- $ find . -name '*.py' -type f -exec cat \{} \; |
- tqdm --unit loc --unit_scale --total 857366 >> /dev/null
- 100%|█████████████████████████████████| 857K/857K [00:04<00:00, 246Kloc/s]
-
-Backing up a large directory?
-
-.. code:: sh
-
- $ tar -zcf - docs/ | tqdm --bytes --total `du -sb docs/ | cut -f1` \
- > backup.tgz
- 44%|██████████████▊ | 153M/352M [00:14<00:18, 11.0MB/s]
-
-This can be beautified further:
-
-.. code:: sh
-
- $ BYTES="$(du -sb docs/ | cut -f1)"
- $ tar -cf - docs/ \
- | tqdm --bytes --total "$BYTES" --desc Processing | gzip \
- | tqdm --bytes --total "$BYTES" --desc Compressed --position 1 \
- > ~/backup.tgz
- Processing: 100%|██████████████████████| 352M/352M [00:14<00:00, 30.2MB/s]
- Compressed: 42%|█████████▎ | 148M/352M [00:14<00:19, 10.9MB/s]
-
-Or done on a file level using 7-zip:
-
-.. code:: sh
-
- $ 7z a -bd -r backup.7z docs/ | grep Compressing \
- | tqdm --total $(find docs/ -type f | wc -l) --unit files \
- | grep -v Compressing
- 100%|██████████████████████████▉| 15327/15327 [01:00<00:00, 712.96files/s]
-
-Pre-existing CLI programs already outputting basic progress information will
-benefit from ``tqdm``'s ``--update`` and ``--update_to`` flags:
-
-.. code:: sh
-
- $ seq 3 0.1 5 | tqdm --total 5 --update_to --null
- 100%|████████████████████████████████████| 5.0/5 [00:00<00:00, 9673.21it/s]
- $ seq 10 | tqdm --update --null # 1 + 2 + ... + 10 = 55 iterations
- 55it [00:00, 90006.52it/s]
-
-FAQ and Known Issues
---------------------
-
-|GitHub-Issues|
-
-The most common issues relate to excessive output on multiple lines, instead
-of a neat one-line progress bar.
-
-- Consoles in general: require support for carriage return (``CR``, ``\r``).
-- Nested progress bars:
-
- * Consoles in general: require support for moving cursors up to the
- previous line. For example,
- `IDLE <https://github.com/tqdm/tqdm/issues/191#issuecomment-230168030>`__,
- `ConEmu <https://github.com/tqdm/tqdm/issues/254>`__ and
- `PyCharm <https://github.com/tqdm/tqdm/issues/203>`__ (also
- `here <https://github.com/tqdm/tqdm/issues/208>`__,
- `here <https://github.com/tqdm/tqdm/issues/307>`__, and
- `here <https://github.com/tqdm/tqdm/issues/454#issuecomment-335416815>`__)
- lack full support.
- * Windows: additionally may require the Python module ``colorama``
- to ensure nested bars stay within their respective lines.
-
-- Unicode:
-
- * Environments which report that they support unicode will have solid smooth
- progressbars. The fallback is an ``ascii``-only bar.
- * Windows consoles often only partially support unicode and thus
- `often require explicit ascii=True <https://github.com/tqdm/tqdm/issues/454#issuecomment-335416815>`__
- (also `here <https://github.com/tqdm/tqdm/issues/499>`__). This is due to
- either normal-width unicode characters being incorrectly displayed as
- "wide", or some unicode characters not rendering.
-
-- Wrapping generators:
-
- * Generator wrapper functions tend to hide the length of iterables.
- ``tqdm`` does not.
- * Replace ``tqdm(enumerate(...))`` with ``enumerate(tqdm(...))`` or
- ``tqdm(enumerate(x), total=len(x), ...)``.
- The same applies to ``numpy.ndenumerate``.
- * Replace ``tqdm(zip(a, b))`` with ``zip(tqdm(a), b)`` or even
- ``zip(tqdm(a), tqdm(b))``.
- * The same applies to ``itertools``.
- * Some useful convenience functions can be found under ``tqdm.contrib``.
-
-- `Hanging pipes in python2 <https://github.com/tqdm/tqdm/issues/359>`__:
- when using ``tqdm`` on the CLI, you may need to use Python 3.5+ for correct
- buffering.
-- `No intermediate output in docker-compose <https://github.com/tqdm/tqdm/issues/771>`__:
- use ``docker-compose run`` instead of ``docker-compose up`` and ``tty: true``.
-
-If you come across any other difficulties, browse and file |GitHub-Issues|.
-
-Documentation
--------------
-
-|Py-Versions| |README-Hits| (Since 19 May 2016)
-
-.. code:: python
-
- class tqdm():
- """
- Decorate an iterable object, returning an iterator which acts exactly
- like the original iterable, but prints a dynamically updating
- progressbar every time a value is requested.
- """
-
- def __init__(self, iterable=None, desc=None, total=None, leave=True,
- file=None, ncols=None, mininterval=0.1,
- maxinterval=10.0, miniters=None, ascii=None, disable=False,
- unit='it', unit_scale=False, dynamic_ncols=False,
- smoothing=0.3, bar_format=None, initial=0, position=None,
- postfix=None, unit_divisor=1000):
-
-Parameters
-~~~~~~~~~~
-
-* iterable : iterable, optional
- Iterable to decorate with a progressbar.
- Leave blank to manually manage the updates.
-* desc : str, optional
- Prefix for the progressbar.
-* total : int or float, optional
- The number of expected iterations. If unspecified,
- len(iterable) is used if possible. If float("inf") or as a last
- resort, only basic progress statistics are displayed
- (no ETA, no progressbar).
- If ``gui`` is True and this parameter needs subsequent updating,
- specify an initial arbitrary large positive number,
- e.g. 9e9.
-* leave : bool, optional
- If [default: True], keeps all traces of the progressbar
- upon termination of iteration.
- If ``None``, will leave only if ``position`` is ``0``.
-* file : ``io.TextIOWrapper`` or ``io.StringIO``, optional
- Specifies where to output the progress messages
- (default: sys.stderr). Uses ``file.write(str)`` and ``file.flush()``
- methods. For encoding, see ``write_bytes``.
-* ncols : int, optional
- The width of the entire output message. If specified,
- dynamically resizes the progressbar to stay within this bound.
- If unspecified, attempts to use environment width. The
- fallback is a meter width of 10 and no limit for the counter and
- statistics. If 0, will not print any meter (only stats).
-* mininterval : float, optional
- Minimum progress display update interval [default: 0.1] seconds.
-* maxinterval : float, optional
- Maximum progress display update interval [default: 10] seconds.
- Automatically adjusts ``miniters`` to correspond to ``mininterval``
- after long display update lag. Only works if ``dynamic_miniters``
- or monitor thread is enabled.
-* miniters : int or float, optional
- Minimum progress display update interval, in iterations.
- If 0 and ``dynamic_miniters``, will automatically adjust to equal
- ``mininterval`` (more CPU efficient, good for tight loops).
- If > 0, will skip display of specified number of iterations.
- Tweak this and ``mininterval`` to get very efficient loops.
- If your progress is erratic with both fast and slow iterations
- (network, skipping items, etc) you should set miniters=1.
-* ascii : bool or str, optional
- If unspecified or False, use unicode (smooth blocks) to fill
- the meter. The fallback is to use ASCII characters " 123456789#".
-* disable : bool, optional
- Whether to disable the entire progressbar wrapper
- [default: False]. If set to None, disable on non-TTY.
-* unit : str, optional
- String that will be used to define the unit of each iteration
- [default: it].
-* unit_scale : bool or int or float, optional
- If 1 or True, the number of iterations will be reduced/scaled
- automatically and a metric prefix following the
- International System of Units standard will be added
- (kilo, mega, etc.) [default: False]. If any other non-zero
- number, will scale ``total`` and ``n``.
-* dynamic_ncols : bool, optional
- If set, constantly alters ``ncols`` and ``nrows`` to the
- environment (allowing for window resizes) [default: False].
-* smoothing : float, optional
- Exponential moving average smoothing factor for speed estimates
- (ignored in GUI mode). Ranges from 0 (average speed) to 1
- (current/instantaneous speed) [default: 0.3].
-* bar_format : str, optional
- Specify a custom bar string formatting. May impact performance.
- [default: '{l_bar}{bar}{r_bar}'], where
- l_bar='{desc}: {percentage:3.0f}%|' and
- r_bar='| {n_fmt}/{total_fmt} [{elapsed}<{remaining}, '
- '{rate_fmt}{postfix}]'
- Possible vars: l_bar, bar, r_bar, n, n_fmt, total, total_fmt,
- percentage, elapsed, elapsed_s, ncols, nrows, desc, unit,
- rate, rate_fmt, rate_noinv, rate_noinv_fmt,
- rate_inv, rate_inv_fmt, postfix, unit_divisor,
- remaining, remaining_s, eta.
- Note that a trailing ": " is automatically removed after {desc}
- if the latter is empty.
-* initial : int or float, optional
- The initial counter value. Useful when restarting a progress
- bar [default: 0]. If using float, consider specifying ``{n:.3f}``
- or similar in ``bar_format``, or specifying ``unit_scale``.
-* position : int, optional
- Specify the line offset to print this bar (starting from 0)
- Automatic if unspecified.
- Useful to manage multiple bars at once (eg, from threads).
-* postfix : dict or ``*``, optional
- Specify additional stats to display at the end of the bar.
- Calls ``set_postfix(**postfix)`` if possible (dict).
-* unit_divisor : float, optional
- [default: 1000], ignored unless ``unit_scale`` is True.
-* write_bytes : bool, optional
- If (default: None) and ``file`` is unspecified,
- bytes will be written in Python 2. If ``True`` will also write
- bytes. In all other cases will default to unicode.
-* lock_args : tuple, optional
- Passed to ``refresh`` for intermediate output
- (initialisation, iterating, and updating).
-* nrows : int, optional
- The screen height. If specified, hides nested bars outside this
- bound. If unspecified, attempts to use environment height.
- The fallback is 20.
-* colour : str, optional
- Bar colour (e.g. 'green', '#00ff00').
-* delay : float, optional
- Don't display until [default: 0] seconds have elapsed.
-
-Extra CLI Options
-~~~~~~~~~~~~~~~~~
-
-* delim : chr, optional
- Delimiting character [default: '\n']. Use '\0' for null.
- N.B.: on Windows systems, Python converts '\n' to '\r\n'.
-* buf_size : int, optional
- String buffer size in bytes [default: 256]
- used when ``delim`` is specified.
-* bytes : bool, optional
- If true, will count bytes, ignore ``delim``, and default
- ``unit_scale`` to True, ``unit_divisor`` to 1024, and ``unit`` to 'B'.
-* tee : bool, optional
- If true, passes ``stdin`` to both ``stderr`` and ``stdout``.
-* update : bool, optional
- If true, will treat input as newly elapsed iterations,
- i.e. numbers to pass to ``update()``. Note that this is slow
- (~2e5 it/s) since every input must be decoded as a number.
-* update_to : bool, optional
- If true, will treat input as total elapsed iterations,
- i.e. numbers to assign to ``self.n``. Note that this is slow
- (~2e5 it/s) since every input must be decoded as a number.
-* null : bool, optional
- If true, will discard input (no stdout).
-* manpath : str, optional
- Directory in which to install tqdm man pages.
-* comppath : str, optional
- Directory in which to place tqdm completion.
-* log : str, optional
- CRITICAL|FATAL|ERROR|WARN(ING)|[default: 'INFO']|DEBUG|NOTSET.
-
-Returns
-~~~~~~~
-
-* out : decorated iterator.
-
-.. code:: python
-
- class tqdm():
- def update(self, n=1):
- """
- Manually update the progress bar, useful for streams
- such as reading files.
- E.g.:
- >>> t = tqdm(total=filesize) # Initialise
- >>> for current_buffer in stream:
- ... ...
- ... t.update(len(current_buffer))
- >>> t.close()
- The last line is highly recommended, but possibly not necessary if
- ``t.update()`` will be called in such a way that ``filesize`` will be
- exactly reached and printed.
-
- Parameters
- ----------
- n : int or float, optional
- Increment to add to the internal counter of iterations
- [default: 1]. If using float, consider specifying ``{n:.3f}``
- or similar in ``bar_format``, or specifying ``unit_scale``.
-
- Returns
- -------
- out : bool or None
- True if a ``display()`` was triggered.
- """
-
- def close(self):
- """Cleanup and (if leave=False) close the progressbar."""
-
- def clear(self, nomove=False):
- """Clear current bar display."""
-
- def refresh(self):
- """
- Force refresh the display of this bar.
-
- Parameters
- ----------
- nolock : bool, optional
- If ``True``, does not lock.
- If [default: ``False``]: calls ``acquire()`` on internal lock.
- lock_args : tuple, optional
- Passed to internal lock's ``acquire()``.
- If specified, will only ``display()`` if ``acquire()`` returns ``True``.
- """
-
- def unpause(self):
- """Restart tqdm timer from last print time."""
-
- def reset(self, total=None):
- """
- Resets to 0 iterations for repeated use.
-
- Consider combining with ``leave=True``.
-
- Parameters
- ----------
- total : int or float, optional. Total to use for the new bar.
- """
-
- def set_description(self, desc=None, refresh=True):
- """
- Set/modify description of the progress bar.
-
- Parameters
- ----------
- desc : str, optional
- refresh : bool, optional
- Forces refresh [default: True].
- """
-
- def set_postfix(self, ordered_dict=None, refresh=True, **tqdm_kwargs):
- """
- Set/modify postfix (additional stats)
- with automatic formatting based on datatype.
-
- Parameters
- ----------
- ordered_dict : dict or OrderedDict, optional
- refresh : bool, optional
- Forces refresh [default: True].
- kwargs : dict, optional
- """
-
- @classmethod
- def write(cls, s, file=sys.stdout, end="\n"):
- """Print a message via tqdm (without overlap with bars)."""
-
- @property
- def format_dict(self):
- """Public API for read-only member access."""
-
- def display(self, msg=None, pos=None):
- """
- Use ``self.sp`` to display ``msg`` in the specified ``pos``.
-
- Consider overloading this function when inheriting to use e.g.:
- ``self.some_frontend(**self.format_dict)`` instead of ``self.sp``.
-
- Parameters
- ----------
- msg : str, optional. What to display (default: ``repr(self)``).
- pos : int, optional. Position to ``moveto``
- (default: ``abs(self.pos)``).
- """
-
- @classmethod
- @contextmanager
- def wrapattr(cls, stream, method, total=None, bytes=True, **tqdm_kwargs):
- """
- stream : file-like object.
- method : str, "read" or "write". The result of ``read()`` and
- the first argument of ``write()`` should have a ``len()``.
-
- >>> with tqdm.wrapattr(file_obj, "read", total=file_obj.size) as fobj:
- ... while True:
- ... chunk = fobj.read(chunk_size)
- ... if not chunk:
- ... break
- """
-
- @classmethod
- def pandas(cls, *targs, **tqdm_kwargs):
- """Registers the current `tqdm` class with `pandas`."""
-
- def trange(*args, **tqdm_kwargs):
- """
- A shortcut for `tqdm(xrange(*args), **tqdm_kwargs)`.
- On Python3+, `range` is used instead of `xrange`.
- """
-
-Convenience Functions
-~~~~~~~~~~~~~~~~~~~~~
-
-.. code:: python
-
- def tqdm.contrib.tenumerate(iterable, start=0, total=None,
- tqdm_class=tqdm.auto.tqdm, **tqdm_kwargs):
- """Equivalent of `numpy.ndenumerate` or builtin `enumerate`."""
-
- def tqdm.contrib.tzip(iter1, *iter2plus, **tqdm_kwargs):
- """Equivalent of builtin `zip`."""
-
- def tqdm.contrib.tmap(function, *sequences, **tqdm_kwargs):
- """Equivalent of builtin `map`."""
-
-Submodules
-~~~~~~~~~~
-
-.. code:: python
-
- class tqdm.notebook.tqdm(tqdm.tqdm):
- """IPython/Jupyter Notebook widget."""
-
- class tqdm.auto.tqdm(tqdm.tqdm):
- """Automatically chooses beween `tqdm.notebook` and `tqdm.tqdm`."""
-
- class tqdm.asyncio.tqdm(tqdm.tqdm):
- """Asynchronous version."""
- @classmethod
- def as_completed(cls, fs, *, loop=None, timeout=None, total=None,
- **tqdm_kwargs):
- """Wrapper for `asyncio.as_completed`."""
-
- class tqdm.gui.tqdm(tqdm.tqdm):
- """Matplotlib GUI version."""
-
- class tqdm.tk.tqdm(tqdm.tqdm):
- """Tkinter GUI version."""
-
- class tqdm.rich.tqdm(tqdm.tqdm):
- """`rich.progress` version."""
-
- class tqdm.keras.TqdmCallback(keras.callbacks.Callback):
- """Keras callback for epoch and batch progress."""
-
- class tqdm.dask.TqdmCallback(dask.callbacks.Callback):
- """Dask callback for task progress."""
-
-
-``contrib``
-+++++++++++
-
-The ``tqdm.contrib`` package also contains experimental modules:
-
-- ``tqdm.contrib.itertools``: Thin wrappers around ``itertools``
-- ``tqdm.contrib.concurrent``: Thin wrappers around ``concurrent.futures``
-- ``tqdm.contrib.slack``: Posts to `Slack <https://slack.com>`__ bots
-- ``tqdm.contrib.discord``: Posts to `Discord <https://discord.com>`__ bots
-- ``tqdm.contrib.telegram``: Posts to `Telegram <https://telegram.org>`__ bots
-- ``tqdm.contrib.bells``: Automagically enables all optional features
-
- * ``auto``, ``pandas``, ``slack``, ``discord``, ``telegram``
-
-Examples and Advanced Usage
----------------------------
-
-- See the `examples <https://github.com/tqdm/tqdm/tree/master/examples>`__
- folder;
-- import the module and run ``help()``;
-- consult the `wiki <https://github.com/tqdm/tqdm/wiki>`__;
-
- * this has an
- `excellent article <https://github.com/tqdm/tqdm/wiki/How-to-make-a-great-Progress-Bar>`__
- on how to make a **great** progressbar;
-
-- check out the `slides from PyData London <https://tqdm.github.io/PyData2019/slides.html>`__, or
-- run the |binder-demo|.
-
-Description and additional stats
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Custom information can be displayed and updated dynamically on ``tqdm`` bars
-with the ``desc`` and ``postfix`` arguments:
-
-.. code:: python
-
- from tqdm import tqdm, trange
- from random import random, randint
- from time import sleep
-
- with trange(10) as t:
- for i in t:
- # Description will be displayed on the left
- t.set_description('GEN %i' % i)
- # Postfix will be displayed on the right,
- # formatted automatically based on argument's datatype
- t.set_postfix(loss=random(), gen=randint(1,999), str='h',
- lst=[1, 2])
- sleep(0.1)
-
- with tqdm(total=10, bar_format="{postfix[0]} {postfix[1][value]:>8.2g}",
- postfix=["Batch", dict(value=0)]) as t:
- for i in range(10):
- sleep(0.1)
- t.postfix[1]["value"] = i / 2
- t.update()
-
-Points to remember when using ``{postfix[...]}`` in the ``bar_format`` string:
-
-- ``postfix`` also needs to be passed as an initial argument in a compatible
- format, and
-- ``postfix`` will be auto-converted to a string if it is a ``dict``-like
- object. To prevent this behaviour, insert an extra item into the dictionary
- where the key is not a string.
-
-Additional ``bar_format`` parameters may also be defined by overriding
-``format_dict``, and the bar itself may be modified using ``ascii``:
-
-.. code:: python
-
- from tqdm import tqdm
- class TqdmExtraFormat(tqdm):
- """Provides a `total_time` format parameter"""
- @property
- def format_dict(self):
- d = super(TqdmExtraFormat, self).format_dict
- total_time = d["elapsed"] * (d["total"] or 0) / max(d["n"], 1)
- d.update(total_time=self.format_interval(total_time) + " in total")
- return d
-
- for i in TqdmExtraFormat(
- range(9), ascii=" .oO0",
- bar_format="{total_time}: {percentage:.0f}%|{bar}{r_bar}"):
- if i == 4:
- break
-
-.. code::
-
- 00:00 in total: 44%|0000. | 4/9 [00:00<00:00, 962.93it/s]
-
-Note that ``{bar}`` also supports a format specifier ``[width][type]``.
-
-- ``width``
-
- * unspecified (default): automatic to fill ``ncols``
- * ``int >= 0``: fixed width overriding ``ncols`` logic
- * ``int < 0``: subtract from the automatic default
-
-- ``type``
-
- * ``a``: ascii (``ascii=True`` override)
- * ``u``: unicode (``ascii=False`` override)
- * ``b``: blank (``ascii=" "`` override)
-
-This means a fixed bar with right-justified text may be created by using:
-``bar_format="{l_bar}{bar:10}|{bar:-10b}right-justified"``
-
-Nested progress bars
-~~~~~~~~~~~~~~~~~~~~
-
-``tqdm`` supports nested progress bars. Here's an example:
-
-.. code:: python
-
- from tqdm.auto import trange
- from time import sleep
-
- for i in trange(4, desc='1st loop'):
- for j in trange(5, desc='2nd loop'):
- for k in trange(50, desc='3rd loop', leave=False):
- sleep(0.01)
-
-For manual control over positioning (e.g. for multi-processing use),
-you may specify ``position=n`` where ``n=0`` for the outermost bar,
-``n=1`` for the next, and so on.
-However, it's best to check if ``tqdm`` can work without manual ``position``
-first.
-
-.. code:: python
-
- from time import sleep
- from tqdm import trange, tqdm
- from multiprocessing import Pool, RLock, freeze_support
-
- L = list(range(9))
-
- def progresser(n):
- interval = 0.001 / (n + 2)
- total = 5000
- text = "#{}, est. {:<04.2}s".format(n, interval * total)
- for _ in trange(total, desc=text, position=n):
- sleep(interval)
-
- if __name__ == '__main__':
- freeze_support() # for Windows support
- tqdm.set_lock(RLock()) # for managing output contention
- p = Pool(initializer=tqdm.set_lock, initargs=(tqdm.get_lock(),))
- p.map(progresser, L)
-
-Note that in Python 3, ``tqdm.write`` is thread-safe:
-
-.. code:: python
-
- from time import sleep
- from tqdm import tqdm, trange
- from concurrent.futures import ThreadPoolExecutor
-
- L = list(range(9))
-
- def progresser(n):
- interval = 0.001 / (n + 2)
- total = 5000
- text = "#{}, est. {:<04.2}s".format(n, interval * total)
- for _ in trange(total, desc=text):
- sleep(interval)
- if n == 6:
- tqdm.write("n == 6 completed.")
- tqdm.write("`tqdm.write()` is thread-safe in py3!")
-
- if __name__ == '__main__':
- with ThreadPoolExecutor() as p:
- p.map(progresser, L)
-
-Hooks and callbacks
-~~~~~~~~~~~~~~~~~~~
-
-``tqdm`` can easily support callbacks/hooks and manual updates.
-Here's an example with ``urllib``:
-
-**``urllib.urlretrieve`` documentation**
-
- | [...]
- | If present, the hook function will be called once
- | on establishment of the network connection and once after each block read
- | thereafter. The hook will be passed three arguments; a count of blocks
- | transferred so far, a block size in bytes, and the total size of the file.
- | [...]
-
-.. code:: python
-
- import urllib, os
- from tqdm import tqdm
- urllib = getattr(urllib, 'request', urllib)
-
- class TqdmUpTo(tqdm):
- """Provides `update_to(n)` which uses `tqdm.update(delta_n)`."""
- def update_to(self, b=1, bsize=1, tsize=None):
- """
- b : int, optional
- Number of blocks transferred so far [default: 1].
- bsize : int, optional
- Size of each block (in tqdm units) [default: 1].
- tsize : int, optional
- Total size (in tqdm units). If [default: None] remains unchanged.
- """
- if tsize is not None:
- self.total = tsize
- return self.update(b * bsize - self.n) # also sets self.n = b * bsize
-
- eg_link = "https://caspersci.uk.to/matryoshka.zip"
- with TqdmUpTo(unit='B', unit_scale=True, unit_divisor=1024, miniters=1,
- desc=eg_link.split('/')[-1]) as t: # all optional kwargs
- urllib.urlretrieve(eg_link, filename=os.devnull,
- reporthook=t.update_to, data=None)
- t.total = t.n
-
-Inspired by `twine#242 <https://github.com/pypa/twine/pull/242>`__.
-Functional alternative in
-`examples/tqdm_wget.py <https://github.com/tqdm/tqdm/blob/master/examples/tqdm_wget.py>`__.
-
-It is recommend to use ``miniters=1`` whenever there is potentially
-large differences in iteration speed (e.g. downloading a file over
-a patchy connection).
-
-**Wrapping read/write methods**
-
-To measure throughput through a file-like object's ``read`` or ``write``
-methods, use ``CallbackIOWrapper``:
-
-.. code:: python
-
- from tqdm.auto import tqdm
- from tqdm.utils import CallbackIOWrapper
-
- with tqdm(total=file_obj.size,
- unit='B', unit_scale=True, unit_divisor=1024) as t:
- fobj = CallbackIOWrapper(t.update, file_obj, "read")
- while True:
- chunk = fobj.read(chunk_size)
- if not chunk:
- break
- t.reset()
- # ... continue to use `t` for something else
-
-Alternatively, use the even simpler ``wrapattr`` convenience function,
-which would condense both the ``urllib`` and ``CallbackIOWrapper`` examples
-down to:
-
-.. code:: python
-
- import urllib, os
- from tqdm import tqdm
-
- eg_link = "https://caspersci.uk.to/matryoshka.zip"
- response = getattr(urllib, 'request', urllib).urlopen(eg_link)
- with tqdm.wrapattr(open(os.devnull, "wb"), "write",
- miniters=1, desc=eg_link.split('/')[-1],
- total=getattr(response, 'length', None)) as fout:
- for chunk in response:
- fout.write(chunk)
-
-The ``requests`` equivalent is nearly identical:
-
-.. code:: python
-
- import requests, os
- from tqdm import tqdm
-
- eg_link = "https://caspersci.uk.to/matryoshka.zip"
- response = requests.get(eg_link, stream=True)
- with tqdm.wrapattr(open(os.devnull, "wb"), "write",
- miniters=1, desc=eg_link.split('/')[-1],
- total=int(response.headers.get('content-length', 0))) as fout:
- for chunk in response.iter_content(chunk_size=4096):
- fout.write(chunk)
-
-**Custom callback**
-
-``tqdm`` is known for intelligently skipping unnecessary displays. To make a
-custom callback take advantage of this, simply use the return value of
-``update()``. This is set to ``True`` if a ``display()`` was triggered.
-
-.. code:: python
-
- from tqdm.auto import tqdm as std_tqdm
-
- def external_callback(*args, **kwargs):
- ...
-
- class TqdmExt(std_tqdm):
- def update(self, n=1):
- displayed = super(TqdmExt, self).update(n)
- if displayed:
- external_callback(**self.format_dict)
- return displayed
-
-``asyncio``
-~~~~~~~~~~~
-
-Note that ``break`` isn't currently caught by asynchronous iterators.
-This means that ``tqdm`` cannot clean up after itself in this case:
-
-.. code:: python
-
- from tqdm.asyncio import tqdm
-
- async for i in tqdm(range(9)):
- if i == 2:
- break
-
-Instead, either call ``pbar.close()`` manually or use the context manager syntax:
-
-.. code:: python
-
- from tqdm.asyncio import tqdm
-
- with tqdm(range(9)) as pbar:
- async for i in pbar:
- if i == 2:
- break
-
-Pandas Integration
-~~~~~~~~~~~~~~~~~~
-
-Due to popular demand we've added support for ``pandas`` -- here's an example
-for ``DataFrame.progress_apply`` and ``DataFrameGroupBy.progress_apply``:
-
-.. code:: python
-
- import pandas as pd
- import numpy as np
- from tqdm import tqdm
-
- df = pd.DataFrame(np.random.randint(0, 100, (100000, 6)))
-
- # Register `pandas.progress_apply` and `pandas.Series.map_apply` with `tqdm`
- # (can use `tqdm.gui.tqdm`, `tqdm.notebook.tqdm`, optional kwargs, etc.)
- tqdm.pandas(desc="my bar!")
-
- # Now you can use `progress_apply` instead of `apply`
- # and `progress_map` instead of `map`
- df.progress_apply(lambda x: x**2)
- # can also groupby:
- # df.groupby(0).progress_apply(lambda x: x**2)
-
-In case you're interested in how this works (and how to modify it for your
-own callbacks), see the
-`examples <https://github.com/tqdm/tqdm/tree/master/examples>`__
-folder or import the module and run ``help()``.
-
-Keras Integration
-~~~~~~~~~~~~~~~~~
-
-A ``keras`` callback is also available:
-
-.. code:: python
-
- from tqdm.keras import TqdmCallback
-
- ...
-
- model.fit(..., verbose=0, callbacks=[TqdmCallback()])
-
-Dask Integration
-~~~~~~~~~~~~~~~~
-
-A ``dask`` callback is also available:
-
-.. code:: python
-
- from tqdm.dask import TqdmCallback
-
- with TqdmCallback(desc="compute"):
- ...
- arr.compute()
-
- # or use callback globally
- cb = TqdmCallback(desc="global")
- cb.register()
- arr.compute()
-
-IPython/Jupyter Integration
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-IPython/Jupyter is supported via the ``tqdm.notebook`` submodule:
-
-.. code:: python
-
- from tqdm.notebook import trange, tqdm
- from time import sleep
-
- for i in trange(3, desc='1st loop'):
- for j in tqdm(range(100), desc='2nd loop'):
- sleep(0.01)
-
-In addition to ``tqdm`` features, the submodule provides a native Jupyter
-widget (compatible with IPython v1-v4 and Jupyter), fully working nested bars
-and colour hints (blue: normal, green: completed, red: error/interrupt,
-light blue: no ETA); as demonstrated below.
-
-|Screenshot-Jupyter1|
-|Screenshot-Jupyter2|
-|Screenshot-Jupyter3|
-
-The ``notebook`` version supports percentage or pixels for overall width
-(e.g.: ``ncols='100%'`` or ``ncols='480px'``).
-
-It is also possible to let ``tqdm`` automatically choose between
-console or notebook versions by using the ``autonotebook`` submodule:
-
-.. code:: python
-
- from tqdm.autonotebook import tqdm
- tqdm.pandas()
-
-Note that this will issue a ``TqdmExperimentalWarning`` if run in a notebook
-since it is not meant to be possible to distinguish between ``jupyter notebook``
-and ``jupyter console``. Use ``auto`` instead of ``autonotebook`` to suppress
-this warning.
-
-Note that notebooks will display the bar in the cell where it was created.
-This may be a different cell from the one where it is used.
-If this is not desired, either
-
-- delay the creation of the bar to the cell where it must be displayed, or
-- create the bar with ``display=False``, and in a later cell call
- ``display(bar.container)``:
-
-.. code:: python
-
- from tqdm.notebook import tqdm
- pbar = tqdm(..., display=False)
-
-.. code:: python
-
- # different cell
- display(pbar.container)
-
-The ``keras`` callback has a ``display()`` method which can be used likewise:
-
-.. code:: python
-
- from tqdm.keras import TqdmCallback
- cbk = TqdmCallback(display=False)
-
-.. code:: python
-
- # different cell
- cbk.display()
- model.fit(..., verbose=0, callbacks=[cbk])
-
-Another possibility is to have a single bar (near the top of the notebook)
-which is constantly re-used (using ``reset()`` rather than ``close()``).
-For this reason, the notebook version (unlike the CLI version) does not
-automatically call ``close()`` upon ``Exception``.
-
-.. code:: python
-
- from tqdm.notebook import tqdm
- pbar = tqdm()
-
-.. code:: python
-
- # different cell
- iterable = range(100)
- pbar.reset(total=len(iterable)) # initialise with new `total`
- for i in iterable:
- pbar.update()
- pbar.refresh() # force print final status but don't `close()`
-
-Custom Integration
-~~~~~~~~~~~~~~~~~~
-
-To change the default arguments (such as making ``dynamic_ncols=True``),
-simply use built-in Python magic:
-
-.. code:: python
-
- from functools import partial
- from tqdm import tqdm as std_tqdm
- tqdm = partial(std_tqdm, dynamic_ncols=True)
-
-For further customisation,
-``tqdm`` may be inherited from to create custom callbacks (as with the
-``TqdmUpTo`` example `above <#hooks-and-callbacks>`__) or for custom frontends
-(e.g. GUIs such as notebook or plotting packages). In the latter case:
-
-1. ``def __init__()`` to call ``super().__init__(..., gui=True)`` to disable
- terminal ``status_printer`` creation.
-2. Redefine: ``close()``, ``clear()``, ``display()``.
-
-Consider overloading ``display()`` to use e.g.
-``self.frontend(**self.format_dict)`` instead of ``self.sp(repr(self))``.
-
-Some submodule examples of inheritance:
-
-- `tqdm/notebook.py <https://github.com/tqdm/tqdm/blob/master/tqdm/notebook.py>`__
-- `tqdm/gui.py <https://github.com/tqdm/tqdm/blob/master/tqdm/gui.py>`__
-- `tqdm/tk.py <https://github.com/tqdm/tqdm/blob/master/tqdm/tk.py>`__
-- `tqdm/contrib/slack.py <https://github.com/tqdm/tqdm/blob/master/tqdm/contrib/slack.py>`__
-- `tqdm/contrib/discord.py <https://github.com/tqdm/tqdm/blob/master/tqdm/contrib/discord.py>`__
-- `tqdm/contrib/telegram.py <https://github.com/tqdm/tqdm/blob/master/tqdm/contrib/telegram.py>`__
-
-Dynamic Monitor/Meter
-~~~~~~~~~~~~~~~~~~~~~
-
-You can use a ``tqdm`` as a meter which is not monotonically increasing.
-This could be because ``n`` decreases (e.g. a CPU usage monitor) or ``total``
-changes.
-
-One example would be recursively searching for files. The ``total`` is the
-number of objects found so far, while ``n`` is the number of those objects which
-are files (rather than folders):
-
-.. code:: python
-
- from tqdm import tqdm
- import os.path
-
- def find_files_recursively(path, show_progress=True):
- files = []
- # total=1 assumes `path` is a file
- t = tqdm(total=1, unit="file", disable=not show_progress)
- if not os.path.exists(path):
- raise IOError("Cannot find:" + path)
-
- def append_found_file(f):
- files.append(f)
- t.update()
-
- def list_found_dir(path):
- """returns os.listdir(path) assuming os.path.isdir(path)"""
- listing = os.listdir(path)
- # subtract 1 since a "file" we found was actually this directory
- t.total += len(listing) - 1
- # fancy way to give info without forcing a refresh
- t.set_postfix(dir=path[-10:], refresh=False)
- t.update(0) # may trigger a refresh
- return listing
-
- def recursively_search(path):
- if os.path.isdir(path):
- for f in list_found_dir(path):
- recursively_search(os.path.join(path, f))
- else:
- append_found_file(path)
-
- recursively_search(path)
- t.set_postfix(dir=path)
- t.close()
- return files
-
-Using ``update(0)`` is a handy way to let ``tqdm`` decide when to trigger a
-display refresh to avoid console spamming.
-
-Writing messages
-~~~~~~~~~~~~~~~~
-
-This is a work in progress (see
-`#737 <https://github.com/tqdm/tqdm/issues/737>`__).
-
-Since ``tqdm`` uses a simple printing mechanism to display progress bars,
-you should not write any message in the terminal using ``print()`` while
-a progressbar is open.
-
-To write messages in the terminal without any collision with ``tqdm`` bar
-display, a ``.write()`` method is provided:
-
-.. code:: python
-
- from tqdm.auto import tqdm, trange
- from time import sleep
-
- bar = trange(10)
- for i in bar:
- # Print using tqdm class method .write()
- sleep(0.1)
- if not (i % 3):
- tqdm.write("Done task %i" % i)
- # Can also use bar.write()
-
-By default, this will print to standard output ``sys.stdout``. but you can
-specify any file-like object using the ``file`` argument. For example, this
-can be used to redirect the messages writing to a log file or class.
-
-Redirecting writing
-~~~~~~~~~~~~~~~~~~~
-
-If using a library that can print messages to the console, editing the library
-by replacing ``print()`` with ``tqdm.write()`` may not be desirable.
-In that case, redirecting ``sys.stdout`` to ``tqdm.write()`` is an option.
-
-To redirect ``sys.stdout``, create a file-like class that will write
-any input string to ``tqdm.write()``, and supply the arguments
-``file=sys.stdout, dynamic_ncols=True``.
-
-A reusable canonical example is given below:
-
-.. code:: python
-
- from time import sleep
- import contextlib
- import sys
- from tqdm import tqdm
- from tqdm.contrib import DummyTqdmFile
-
-
- @contextlib.contextmanager
- def std_out_err_redirect_tqdm():
- orig_out_err = sys.stdout, sys.stderr
- try:
- sys.stdout, sys.stderr = map(DummyTqdmFile, orig_out_err)
- yield orig_out_err[0]
- # Relay exceptions
- except Exception as exc:
- raise exc
- # Always restore sys.stdout/err if necessary
- finally:
- sys.stdout, sys.stderr = orig_out_err
-
- def some_fun(i):
- print("Fee, fi, fo,".split()[i])
-
- # Redirect stdout to tqdm.write() (don't forget the `as save_stdout`)
- with std_out_err_redirect_tqdm() as orig_stdout:
- # tqdm needs the original stdout
- # and dynamic_ncols=True to autodetect console width
- for i in tqdm(range(3), file=orig_stdout, dynamic_ncols=True):
- sleep(.5)
- some_fun(i)
-
- # After the `with`, printing is restored
- print("Done!")
-
-Redirecting ``logging``
-~~~~~~~~~~~~~~~~~~~~~~~
-
-Similar to ``sys.stdout``/``sys.stderr`` as detailed above, console ``logging``
-may also be redirected to ``tqdm.write()``.
-
-Warning: if also redirecting ``sys.stdout``/``sys.stderr``, make sure to
-redirect ``logging`` first if needed.
-
-Helper methods are available in ``tqdm.contrib.logging``. For example:
-
-.. code:: python
-
- import logging
- from tqdm import trange
- from tqdm.contrib.logging import logging_redirect_tqdm
-
- LOG = logging.getLogger(__name__)
-
- if __name__ == '__main__':
- logging.basicConfig(level=logging.INFO)
- with logging_redirect_tqdm():
- for i in trange(9):
- if i == 4:
- LOG.info("console logging redirected to `tqdm.write()`")
- # logging restored
-
-Monitoring thread, intervals and miniters
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-``tqdm`` implements a few tricks to increase efficiency and reduce overhead.
-
-- Avoid unnecessary frequent bar refreshing: ``mininterval`` defines how long
- to wait between each refresh. ``tqdm`` always gets updated in the background,
- but it will display only every ``mininterval``.
-- Reduce number of calls to check system clock/time.
-- ``mininterval`` is more intuitive to configure than ``miniters``.
- A clever adjustment system ``dynamic_miniters`` will automatically adjust
- ``miniters`` to the amount of iterations that fit into time ``mininterval``.
- Essentially, ``tqdm`` will check if it's time to print without actually
- checking time. This behaviour can be still be bypassed by manually setting
- ``miniters``.
-
-However, consider a case with a combination of fast and slow iterations.
-After a few fast iterations, ``dynamic_miniters`` will set ``miniters`` to a
-large number. When iteration rate subsequently slows, ``miniters`` will
-remain large and thus reduce display update frequency. To address this:
-
-- ``maxinterval`` defines the maximum time between display refreshes.
- A concurrent monitoring thread checks for overdue updates and forces one
- where necessary.
-
-The monitoring thread should not have a noticeable overhead, and guarantees
-updates at least every 10 seconds by default.
-This value can be directly changed by setting the ``monitor_interval`` of
-any ``tqdm`` instance (i.e. ``t = tqdm.tqdm(...); t.monitor_interval = 2``).
-The monitor thread may be disabled application-wide by setting
-``tqdm.tqdm.monitor_interval = 0`` before instantiation of any ``tqdm`` bar.
-
-
-Merch
------
-
-You can buy `tqdm branded merch <https://tqdm.github.io/merch>`__ now!
-
-Contributions
--------------
-
-|GitHub-Commits| |GitHub-Issues| |GitHub-PRs| |OpenHub-Status| |GitHub-Contributions| |CII Best Practices|
-
-All source code is hosted on `GitHub <https://github.com/tqdm/tqdm>`__.
-Contributions are welcome.
-
-See the
-`CONTRIBUTING <https://github.com/tqdm/tqdm/blob/master/CONTRIBUTING.md>`__
-file for more information.
-
-Developers who have made significant contributions, ranked by *SLoC*
-(surviving lines of code,
-`git fame <https://github.com/casperdcl/git-fame>`__ ``-wMC --excl '\.(png|gif|jpg)$'``),
-are:
-
-==================== ======================================================== ==== ================================
-Name ID SLoC Notes
-==================== ======================================================== ==== ================================
-Casper da Costa-Luis `casperdcl <https://github.com/casperdcl>`__ ~78% primary maintainer |Gift-Casper|
-Stephen Larroque `lrq3000 <https://github.com/lrq3000>`__ ~10% team member
-Martin Zugnoni `martinzugnoni <https://github.com/martinzugnoni>`__ ~4%
-Daniel Ecer `de-code <https://github.com/de-code>`__ ~2%
-Richard Sheridan `richardsheridan <https://github.com/richardsheridan>`__ ~1%
-Guangshuo Chen `chengs <https://github.com/chengs>`__ ~1%
-Kyle Altendorf `altendky <https://github.com/altendky>`__ <1%
-Matthew Stevens `mjstevens777 <https://github.com/mjstevens777>`__ <1%
-Hadrien Mary `hadim <https://github.com/hadim>`__ <1% team member
-Noam Yorav-Raphael `noamraph <https://github.com/noamraph>`__ <1% original author
-Mikhail Korobov `kmike <https://github.com/kmike>`__ <1% team member
-==================== ======================================================== ==== ================================
-
-Ports to Other Languages
-~~~~~~~~~~~~~~~~~~~~~~~~
-
-A list is available on
-`this wiki page <https://github.com/tqdm/tqdm/wiki/tqdm-ports>`__.
-
-
-LICENCE
--------
-
-Open Source (OSI approved): |LICENCE|
-
-Citation information: |DOI|
-
-|README-Hits| (Since 19 May 2016)
-
-.. |Logo| image:: https://img.tqdm.ml/logo.gif
-.. |Screenshot| image:: https://img.tqdm.ml/tqdm.gif
-.. |Video| image:: https://img.tqdm.ml/video.jpg
- :target: https://tqdm.github.io/video
-.. |Slides| image:: https://img.tqdm.ml/slides.jpg
- :target: https://tqdm.github.io/PyData2019/slides.html
-.. |Merch| image:: https://img.tqdm.ml/merch.jpg
- :target: https://tqdm.github.io/merch
-.. |Build-Status| image:: https://img.shields.io/github/workflow/status/tqdm/tqdm/Test/master?logo=GitHub
- :target: https://github.com/tqdm/tqdm/actions?query=workflow%3ATest
-.. |Coverage-Status| image:: https://img.shields.io/coveralls/github/tqdm/tqdm/master?logo=coveralls
- :target: https://coveralls.io/github/tqdm/tqdm
-.. |Branch-Coverage-Status| image:: https://codecov.io/gh/tqdm/tqdm/branch/master/graph/badge.svg
- :target: https://codecov.io/gh/tqdm/tqdm
-.. |Codacy-Grade| image:: https://app.codacy.com/project/badge/Grade/3f965571598f44549c7818f29cdcf177
- :target: https://www.codacy.com/gh/tqdm/tqdm/dashboard
-.. |CII Best Practices| image:: https://bestpractices.coreinfrastructure.org/projects/3264/badge
- :target: https://bestpractices.coreinfrastructure.org/projects/3264
-.. |GitHub-Status| image:: https://img.shields.io/github/tag/tqdm/tqdm.svg?maxAge=86400&logo=github&logoColor=white
- :target: https://github.com/tqdm/tqdm/releases
-.. |GitHub-Forks| image:: https://img.shields.io/github/forks/tqdm/tqdm.svg?logo=github&logoColor=white
- :target: https://github.com/tqdm/tqdm/network
-.. |GitHub-Stars| image:: https://img.shields.io/github/stars/tqdm/tqdm.svg?logo=github&logoColor=white
- :target: https://github.com/tqdm/tqdm/stargazers
-.. |GitHub-Commits| image:: https://img.shields.io/github/commit-activity/y/tqdm/tqdm.svg?logo=git&logoColor=white
- :target: https://github.com/tqdm/tqdm/graphs/commit-activity
-.. |GitHub-Issues| image:: https://img.shields.io/github/issues-closed/tqdm/tqdm.svg?logo=github&logoColor=white
- :target: https://github.com/tqdm/tqdm/issues?q=
-.. |GitHub-PRs| image:: https://img.shields.io/github/issues-pr-closed/tqdm/tqdm.svg?logo=github&logoColor=white
- :target: https://github.com/tqdm/tqdm/pulls
-.. |GitHub-Contributions| image:: https://img.shields.io/github/contributors/tqdm/tqdm.svg?logo=github&logoColor=white
- :target: https://github.com/tqdm/tqdm/graphs/contributors
-.. |GitHub-Updated| image:: https://img.shields.io/github/last-commit/tqdm/tqdm/master.svg?logo=github&logoColor=white&label=pushed
- :target: https://github.com/tqdm/tqdm/pulse
-.. |Gift-Casper| image:: https://img.shields.io/badge/dynamic/json.svg?color=ff69b4&label=gifts%20received&prefix=%C2%A3&query=%24..sum&url=https%3A%2F%2Fcaspersci.uk.to%2Fgifts.json
- :target: https://cdcl.ml/sponsor
-.. |Versions| image:: https://img.shields.io/pypi/v/tqdm.svg
- :target: https://tqdm.github.io/releases
-.. |PyPI-Downloads| image:: https://img.shields.io/pypi/dm/tqdm.svg?label=pypi%20downloads&logo=PyPI&logoColor=white
- :target: https://pepy.tech/project/tqdm
-.. |Py-Versions| image:: https://img.shields.io/pypi/pyversions/tqdm.svg?logo=python&logoColor=white
- :target: https://pypi.org/project/tqdm
-.. |Conda-Forge-Status| image:: https://img.shields.io/conda/v/conda-forge/tqdm.svg?label=conda-forge&logo=conda-forge
- :target: https://anaconda.org/conda-forge/tqdm
-.. |Snapcraft| image:: https://img.shields.io/badge/snap-install-82BEA0.svg?logo=snapcraft
- :target: https://snapcraft.io/tqdm
-.. |Docker| image:: https://img.shields.io/badge/docker-pull-blue.svg?logo=docker&logoColor=white
- :target: https://hub.docker.com/r/tqdm/tqdm
-.. |Libraries-Rank| image:: https://img.shields.io/librariesio/sourcerank/pypi/tqdm.svg?logo=koding&logoColor=white
- :target: https://libraries.io/pypi/tqdm
-.. |Libraries-Dependents| image:: https://img.shields.io/librariesio/dependent-repos/pypi/tqdm.svg?logo=koding&logoColor=white
- :target: https://github.com/tqdm/tqdm/network/dependents
-.. |OpenHub-Status| image:: https://www.openhub.net/p/tqdm/widgets/project_thin_badge?format=gif
- :target: https://www.openhub.net/p/tqdm?ref=Thin+badge
-.. |awesome-python| image:: https://awesome.re/mentioned-badge.svg
- :target: https://github.com/vinta/awesome-python
-.. |LICENCE| image:: https://img.shields.io/pypi/l/tqdm.svg
- :target: https://raw.githubusercontent.com/tqdm/tqdm/master/LICENCE
-.. |DOI| image:: https://img.shields.io/badge/DOI-10.5281/zenodo.595120-blue.svg
- :target: https://doi.org/10.5281/zenodo.595120
-.. |binder-demo| image:: https://mybinder.org/badge_logo.svg
- :target: https://mybinder.org/v2/gh/tqdm/tqdm/master?filepath=DEMO.ipynb
-.. |Screenshot-Jupyter1| image:: https://img.tqdm.ml/jupyter-1.gif
-.. |Screenshot-Jupyter2| image:: https://img.tqdm.ml/jupyter-2.gif
-.. |Screenshot-Jupyter3| image:: https://img.tqdm.ml/jupyter-3.gif
-.. |README-Hits| image:: https://caspersci.uk.to/cgi-bin/hits.cgi?q=tqdm&style=social&r=https://github.com/tqdm/tqdm&l=https://img.tqdm.ml/favicon.png&f=https://img.tqdm.ml/logo.gif
- :target: https://caspersci.uk.to/cgi-bin/hits.cgi?q=tqdm&a=plot&r=https://github.com/tqdm/tqdm&l=https://img.tqdm.ml/favicon.png&f=https://img.tqdm.ml/logo.gif&style=social
diff --git a/README.rst b/README.rst
index a45f98d..a148cb1 100644
--- a/README.rst
+++ b/README.rst
@@ -255,7 +255,7 @@ This can be beautified further:
.. code:: sh
- $ BYTES="$(du -sb docs/ | cut -f1)"
+ $ BYTES=$(du -sb docs/ | cut -f1)
$ tar -cf - docs/ \
| tqdm --bytes --total "$BYTES" --desc Processing | gzip \
| tqdm --bytes --total "$BYTES" --desc Compressed --position 1 \
@@ -291,6 +291,12 @@ The most common issues relate to excessive output on multiple lines, instead
of a neat one-line progress bar.
- Consoles in general: require support for carriage return (``CR``, ``\r``).
+
+ * Some cloud logging consoles which don't support ``\r`` properly
+ (`cloudwatch <https://github.com/tqdm/tqdm/issues/966>`__,
+ `K8s <https://github.com/tqdm/tqdm/issues/1319>`__) may benefit from
+ ``export TQDM_POSITION=-1``.
+
- Nested progress bars:
* Consoles in general: require support for moving cursors up to the
@@ -327,12 +333,14 @@ of a neat one-line progress bar.
* The same applies to ``itertools``.
* Some useful convenience functions can be found under ``tqdm.contrib``.
-- `Hanging pipes in python2 <https://github.com/tqdm/tqdm/issues/359>`__:
- when using ``tqdm`` on the CLI, you may need to use Python 3.5+ for correct
- buffering.
- `No intermediate output in docker-compose <https://github.com/tqdm/tqdm/issues/771>`__:
use ``docker-compose run`` instead of ``docker-compose up`` and ``tty: true``.
+- Overriding defaults via environment variables:
+ e.g. in CI/cloud jobs, ``export TQDM_MININTERVAL=5`` to avoid log spam.
+ This override logic is handled by the ``tqdm.utils.envwrap`` decorator
+ (useful independent of ``tqdm``).
+
If you come across any other difficulties, browse and file |GitHub-Issues|.
Documentation
@@ -349,12 +357,14 @@ Documentation
progressbar every time a value is requested.
"""
+ @envwrap("TQDM_") # override defaults via env vars
def __init__(self, iterable=None, desc=None, total=None, leave=True,
file=None, ncols=None, mininterval=0.1,
maxinterval=10.0, miniters=None, ascii=None, disable=False,
unit='it', unit_scale=False, dynamic_ncols=False,
smoothing=0.3, bar_format=None, initial=0, position=None,
- postfix=None, unit_divisor=1000):
+ postfix=None, unit_divisor=1000, write_bytes=False,
+ lock_args=None, nrows=None, colour=None, delay=0):
Parameters
~~~~~~~~~~
@@ -450,9 +460,7 @@ Parameters
* unit_divisor : float, optional
[default: 1000], ignored unless ``unit_scale`` is True.
* write_bytes : bool, optional
- If (default: None) and ``file`` is unspecified,
- bytes will be written in Python 2. If ``True`` will also write
- bytes. In all other cases will default to unicode.
+ Whether to write bytes. If (default: False) will write unicode.
* lock_args : tuple, optional
Passed to ``refresh`` for intermediate output
(initialisation, iterating, and updating).
@@ -631,10 +639,7 @@ Returns
"""Registers the current `tqdm` class with `pandas`."""
def trange(*args, **tqdm_kwargs):
- """
- A shortcut for `tqdm(xrange(*args), **tqdm_kwargs)`.
- On Python3+, `range` is used instead of `xrange`.
- """
+ """Shortcut for `tqdm(range(*args), **tqdm_kwargs)`."""
Convenience Functions
~~~~~~~~~~~~~~~~~~~~~
@@ -737,7 +742,7 @@ with the ``desc`` and ``postfix`` arguments:
sleep(0.1)
with tqdm(total=10, bar_format="{postfix[0]} {postfix[1][value]:>8.2g}",
- postfix=["Batch", dict(value=0)]) as t:
+ postfix=["Batch", {"value": 0}]) as t:
for i in range(10):
sleep(0.1)
t.postfix[1]["value"] = i / 2
@@ -825,7 +830,7 @@ first.
def progresser(n):
interval = 0.001 / (n + 2)
total = 5000
- text = "#{}, est. {:<04.2}s".format(n, interval * total)
+ text = f"#{n}, est. {interval * total:<04.2}s"
for _ in trange(total, desc=text, position=n):
sleep(interval)
@@ -848,7 +853,7 @@ Note that in Python 3, ``tqdm.write`` is thread-safe:
def progresser(n):
interval = 0.001 / (n + 2)
total = 5000
- text = "#{}, est. {:<04.2}s".format(n, interval * total)
+ text = f"#{n}, est. {interval * total:<04.2}s"
for _ in trange(total, desc=text):
sleep(interval)
if n == 6:
@@ -1405,16 +1410,17 @@ are:
==================== ======================================================== ==== ================================
Name ID SLoC Notes
==================== ======================================================== ==== ================================
-Casper da Costa-Luis `casperdcl <https://github.com/casperdcl>`__ ~78% primary maintainer |Gift-Casper|
-Stephen Larroque `lrq3000 <https://github.com/lrq3000>`__ ~10% team member
-Martin Zugnoni `martinzugnoni <https://github.com/martinzugnoni>`__ ~4%
+Casper da Costa-Luis `casperdcl <https://github.com/casperdcl>`__ ~80% primary maintainer |Gift-Casper|
+Stephen Larroque `lrq3000 <https://github.com/lrq3000>`__ ~9% team member
+Martin Zugnoni `martinzugnoni <https://github.com/martinzugnoni>`__ ~3%
Daniel Ecer `de-code <https://github.com/de-code>`__ ~2%
Richard Sheridan `richardsheridan <https://github.com/richardsheridan>`__ ~1%
Guangshuo Chen `chengs <https://github.com/chengs>`__ ~1%
+Helio Machado `0x2b3bfa0 <https://github.com/0x2b3bfa0>`__ ~1%
Kyle Altendorf `altendky <https://github.com/altendky>`__ <1%
+Noam Yorav-Raphael `noamraph <https://github.com/noamraph>`__ <1% original author
Matthew Stevens `mjstevens777 <https://github.com/mjstevens777>`__ <1%
Hadrien Mary `hadim <https://github.com/hadim>`__ <1% team member
-Noam Yorav-Raphael `noamraph <https://github.com/noamraph>`__ <1% original author
Mikhail Korobov `kmike <https://github.com/kmike>`__ <1% team member
==================== ======================================================== ==== ================================
@@ -1434,16 +1440,16 @@ Citation information: |DOI|
|README-Hits| (Since 19 May 2016)
-.. |Logo| image:: https://img.tqdm.ml/logo.gif
-.. |Screenshot| image:: https://img.tqdm.ml/tqdm.gif
-.. |Video| image:: https://img.tqdm.ml/video.jpg
+.. |Logo| image:: https://tqdm.github.io/img/logo.gif
+.. |Screenshot| image:: https://tqdm.github.io/img/tqdm.gif
+.. |Video| image:: https://tqdm.github.io/img/video.jpg
:target: https://tqdm.github.io/video
-.. |Slides| image:: https://img.tqdm.ml/slides.jpg
+.. |Slides| image:: https://tqdm.github.io/img/slides.jpg
:target: https://tqdm.github.io/PyData2019/slides.html
-.. |Merch| image:: https://img.tqdm.ml/merch.jpg
+.. |Merch| image:: https://tqdm.github.io/img/merch.jpg
:target: https://tqdm.github.io/merch
-.. |Build-Status| image:: https://img.shields.io/github/workflow/status/tqdm/tqdm/Test/master?logo=GitHub
- :target: https://github.com/tqdm/tqdm/actions?query=workflow%3ATest
+.. |Build-Status| image:: https://img.shields.io/github/actions/workflow/status/tqdm/tqdm/test.yml?branch=master&label=tqdm&logo=GitHub
+ :target: https://github.com/tqdm/tqdm/actions/workflows/test.yml
.. |Coverage-Status| image:: https://img.shields.io/coveralls/github/tqdm/tqdm/master?logo=coveralls
:target: https://coveralls.io/github/tqdm/tqdm
.. |Branch-Coverage-Status| image:: https://codecov.io/gh/tqdm/tqdm/branch/master/graph/badge.svg
@@ -1496,8 +1502,8 @@ Citation information: |DOI|
:target: https://doi.org/10.5281/zenodo.595120
.. |binder-demo| image:: https://mybinder.org/badge_logo.svg
:target: https://mybinder.org/v2/gh/tqdm/tqdm/master?filepath=DEMO.ipynb
-.. |Screenshot-Jupyter1| image:: https://img.tqdm.ml/jupyter-1.gif
-.. |Screenshot-Jupyter2| image:: https://img.tqdm.ml/jupyter-2.gif
-.. |Screenshot-Jupyter3| image:: https://img.tqdm.ml/jupyter-3.gif
-.. |README-Hits| image:: https://caspersci.uk.to/cgi-bin/hits.cgi?q=tqdm&style=social&r=https://github.com/tqdm/tqdm&l=https://img.tqdm.ml/favicon.png&f=https://img.tqdm.ml/logo.gif
- :target: https://caspersci.uk.to/cgi-bin/hits.cgi?q=tqdm&a=plot&r=https://github.com/tqdm/tqdm&l=https://img.tqdm.ml/favicon.png&f=https://img.tqdm.ml/logo.gif&style=social
+.. |Screenshot-Jupyter1| image:: https://tqdm.github.io/img/jupyter-1.gif
+.. |Screenshot-Jupyter2| image:: https://tqdm.github.io/img/jupyter-2.gif
+.. |Screenshot-Jupyter3| image:: https://tqdm.github.io/img/jupyter-3.gif
+.. |README-Hits| image:: https://caspersci.uk.to/cgi-bin/hits.cgi?q=tqdm&style=social&r=https://github.com/tqdm/tqdm&l=https://tqdm.github.io/img/favicon.png&f=https://tqdm.github.io/img/logo.gif
+ :target: https://caspersci.uk.to/cgi-bin/hits.cgi?q=tqdm&a=plot&r=https://github.com/tqdm/tqdm&l=https://tqdm.github.io/img/favicon.png&f=https://tqdm.github.io/img/logo.gif&style=social
diff --git a/environment.yml b/environment.yml
index 871e3e8..e2e6b95 100644
--- a/environment.yml
+++ b/environment.yml
@@ -5,7 +5,7 @@ channels:
- defaults
dependencies:
# base
-- python=3
+- python >=3.7
- pip
- ipykernel
- ipywidgets
@@ -20,7 +20,7 @@ dependencies:
- pytest
- pytest-cov
- pytest-timeout
-- pytest-asyncio # [py>=3.7]
+- pytest-asyncio
- nbval
- coverage
# extras
@@ -28,19 +28,20 @@ dependencies:
- matplotlib # gui
- numpy # pandas, keras, contrib.tenumerate
- pandas
+- pyarrow # pandas
- tensorflow # keras
- slack-sdk # contrib.slack
- requests # contrib.telegram
- rich # rich
- argopt # `cd wiki && pymake`
-- twine # `pymake pypi`
-- wheel # `setup.py bdist_wheel`
+- twine # `pymake check pypi`
+- build # `python -m build`
# `cd docs && pymake`
- mkdocs-material
- pydoc-markdown
- pygments
- pymdown-extensions
- pip:
- - py-make >=0.1.0 # `setup.py make/pymake`
+ - py-make >=0.1.0 # `make/pymake`
- mkdocs-minify-plugin # `cd docs && pymake`
- git+https://github.com/tqdm/jsmin@python3-only#egg=jsmin # `cd docs && pymake`
diff --git a/examples/7zx.py b/examples/7zx.py
index 3d15254..18d7e33 100644
--- a/examples/7zx.py
+++ b/examples/7zx.py
@@ -18,8 +18,6 @@ Options:
NOTSET
-d, --debug-trace Print lots of debugging information (-D NOTSET)
"""
-from __future__ import print_function
-
import io
import logging
import os
diff --git a/examples/async_coroutines.py b/examples/async_coroutines.py
index 40f4f24..3e31905 100644
--- a/examples/async_coroutines.py
+++ b/examples/async_coroutines.py
@@ -1,6 +1,4 @@
-"""
-Asynchronous examples using `asyncio`, `async` and `await` on `python>=3.7`.
-"""
+"""Asynchronous examples using `asyncio`, `async` and `await`."""
import asyncio
from tqdm.asyncio import tqdm, trange
diff --git a/examples/parallel_bars.py b/examples/parallel_bars.py
index 498fd61..b7e1494 100644
--- a/examples/parallel_bars.py
+++ b/examples/parallel_bars.py
@@ -1,6 +1,3 @@
-from __future__ import print_function
-
-import sys
from concurrent.futures import ThreadPoolExecutor
from functools import partial
from multiprocessing import Pool, RLock, freeze_support
@@ -12,21 +9,19 @@ from tqdm.auto import tqdm, trange
from tqdm.contrib.concurrent import process_map, thread_map
NUM_SUBITERS = 9
-PY2 = sys.version_info[:1] <= (2,)
def progresser(n, auto_position=True, write_safe=False, blocking=True, progress=False):
interval = random() * 0.002 / (NUM_SUBITERS - n + 2) # nosec
total = 5000
- text = "#{0}, est. {1:<04.2}s".format(n, interval * total)
+ text = f"#{n}, est. {interval * total:<04.2g}s"
for _ in trange(total, desc=text, disable=not progress,
lock_args=None if blocking else (False,),
position=None if auto_position else n):
sleep(interval)
# NB: may not clear instances with higher `position` upon completion
# since this worker may not know about other bars #796
- if write_safe:
- # we think we know about other bars (currently only py3 threading)
+ if write_safe: # we think we know about other bars
if n == 6:
tqdm.write("n == 6 completed")
return n + 1
@@ -37,7 +32,7 @@ if __name__ == '__main__':
L = list(range(NUM_SUBITERS))[::-1]
print("Simple thread mapping")
- thread_map(partial(progresser, write_safe=not PY2), L, max_workers=4)
+ thread_map(partial(progresser, write_safe=True), L, max_workers=4)
print("Simple process mapping")
process_map(partial(progresser), L, max_workers=4)
@@ -54,8 +49,5 @@ if __name__ == '__main__':
print("Multi-threading")
tqdm.set_lock(TRLock())
- pool_args = {}
- if not PY2:
- pool_args.update(initializer=tqdm.set_lock, initargs=(tqdm.get_lock(),))
- with ThreadPoolExecutor(**pool_args) as p:
- p.map(partial(progresser, progress=True, write_safe=not PY2, blocking=False), L)
+ with ThreadPoolExecutor(initializer=tqdm.set_lock, initargs=(tqdm.get_lock(),)) as p:
+ p.map(partial(progresser, progress=True, write_safe=True, blocking=False), L)
diff --git a/examples/redirect_print.py b/examples/redirect_print.py
index 0f9721e..38e6b4f 100644
--- a/examples/redirect_print.py
+++ b/examples/redirect_print.py
@@ -10,8 +10,6 @@ any input string to `tqdm.write()`, and supply the arguments
A reusable canonical example is given below:
"""
-from __future__ import print_function
-
import contextlib
import sys
from time import sleep
diff --git a/examples/simple_examples.py b/examples/simple_examples.py
index f3401d3..bff1c9e 100644
--- a/examples/simple_examples.py
+++ b/examples/simple_examples.py
@@ -2,7 +2,7 @@
# Simple tqdm examples and profiling
# Benchmark
-for i in _range(int(1e8)):
+for i in range(int(1e8)):
pass
# Basic demo
@@ -33,7 +33,7 @@ try:
except ImportError:
pass
else:
- for i in ProgressBar()(_range(int(1e8))):
+ for i in ProgressBar()(range(int(1e8))):
pass
# Dynamic miniters benchmark
@@ -61,5 +61,4 @@ for _ in trange(16, leave=True):
stmts = filter(None, re.split(r'\n\s*#.*?\n', __doc__))
for s in stmts:
print(s.replace('import tqdm\n', ''))
- print(timeit(stmt='try:\n\t_range = xrange'
- '\nexcept:\n\t_range = range\n' + s, number=1), 'seconds')
+ print(timeit(stmt=s, number=1), 'seconds')
diff --git a/examples/tqdm_wget.py b/examples/tqdm_wget.py
index 8663e5a..ee8b9f3 100644
--- a/examples/tqdm_wget.py
+++ b/examples/tqdm_wget.py
@@ -20,11 +20,8 @@ Options:
The local file path in which to save the url [default: /dev/null].
"""
-try:
- from urllib import request as urllib
-except ImportError: # py2
- import urllib
from os import devnull
+from urllib import request as urllib
from docopt import docopt
diff --git a/pyproject.toml b/pyproject.toml
index 3eb7bbc..6ee6d5e 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -5,3 +5,131 @@ build-backend = "setuptools.build_meta"
[tool.setuptools_scm]
write_to = "tqdm/_dist_ver.py"
write_to_template = "__version__ = '{version}'\n"
+
+[tool.setuptools.packages.find]
+exclude = ["benchmarks", "examples", "tests", "wiki", "docs", "feedstock"]
+
+[project.urls]
+homepage = "https://tqdm.github.io"
+repository = "https://github.com/tqdm/tqdm"
+changelog = "https://tqdm.github.io/releases"
+wiki = "https://github.com/tqdm/tqdm/wiki"
+
+[project]
+name = "tqdm"
+dynamic = ["version"]
+maintainers = [{name = "tqdm developers", email = "devs@tqdm.ml"}]
+description = "Fast, Extensible Progress Meter"
+readme = "README.rst"
+requires-python = ">=3.7"
+keywords = ["progressbar", "progressmeter", "progress", "bar", "meter", "rate", "eta", "console", "terminal", "time"]
+license = {text = "MPL-2.0 AND MIT"}
+classifiers = [
+ "Development Status :: 5 - Production/Stable",
+ "Environment :: Console",
+ "Environment :: MacOS X",
+ "Environment :: Other Environment",
+ "Environment :: Win32 (MS Windows)",
+ "Environment :: X11 Applications",
+ "Framework :: IPython",
+ "Framework :: Jupyter",
+ "Intended Audience :: Developers",
+ "Intended Audience :: Education",
+ "Intended Audience :: End Users/Desktop",
+ "Intended Audience :: Other Audience",
+ "Intended Audience :: System Administrators",
+ "License :: OSI Approved :: MIT License",
+ "License :: OSI Approved :: Mozilla Public License 2.0 (MPL 2.0)",
+ "Operating System :: MacOS",
+ "Operating System :: MacOS :: MacOS X",
+ "Operating System :: Microsoft",
+ "Operating System :: Microsoft :: MS-DOS",
+ "Operating System :: Microsoft :: Windows",
+ "Operating System :: POSIX",
+ "Operating System :: POSIX :: BSD",
+ "Operating System :: POSIX :: BSD :: FreeBSD",
+ "Operating System :: POSIX :: Linux",
+ "Operating System :: POSIX :: SunOS/Solaris",
+ "Operating System :: Unix",
+ "Programming Language :: Python",
+ "Programming Language :: Python :: 3",
+ "Programming Language :: Python :: 3.7",
+ "Programming Language :: Python :: 3.8",
+ "Programming Language :: Python :: 3.9",
+ "Programming Language :: Python :: 3.10",
+ "Programming Language :: Python :: 3.11",
+ "Programming Language :: Python :: 3 :: Only",
+ "Programming Language :: Python :: Implementation",
+ "Programming Language :: Python :: Implementation :: IronPython",
+ "Programming Language :: Python :: Implementation :: PyPy",
+ "Programming Language :: Unix Shell",
+ "Topic :: Desktop Environment",
+ "Topic :: Education :: Computer Aided Instruction (CAI)",
+ "Topic :: Education :: Testing",
+ "Topic :: Office/Business",
+ "Topic :: Other/Nonlisted Topic",
+ "Topic :: Software Development :: Build Tools",
+ "Topic :: Software Development :: Libraries",
+ "Topic :: Software Development :: Libraries :: Python Modules",
+ "Topic :: Software Development :: Pre-processors",
+ "Topic :: Software Development :: User Interfaces",
+ "Topic :: System :: Installation/Setup",
+ "Topic :: System :: Logging",
+ "Topic :: System :: Monitoring",
+ "Topic :: System :: Shells",
+ "Topic :: Terminals",
+ "Topic :: Utilities"]
+dependencies = ['colorama; platform_system == "Windows"']
+
+[project.optional-dependencies]
+dev = ["pytest>=6", "pytest-cov", "pytest-timeout", "pytest-xdist"]
+slack = ["slack-sdk"]
+telegram = ["requests"]
+notebook = ["ipywidgets>=6"]
+
+[project.scripts]
+tqdm = "tqdm.cli:main"
+
+[tool.flake8]
+max_line_length = 99
+exclude = [".git", "__pycache__", "build", "dist", ".eggs", ".asv", ".tox", ".ipynb_checkpoints"]
+
+[tool.yapf]
+spaces_before_comment = [15, 20]
+arithmetic_precedence_indication = true
+allow_split_before_dict_value = false
+coalesce_brackets = true
+column_limit = 99
+each_dict_entry_on_separate_line = false
+space_between_ending_comma_and_closing_bracket = false
+split_before_named_assigns = false
+split_before_closing_bracket = false
+blank_line_before_nested_class_or_def = false
+
+[tool.isort]
+line_length = 99
+multi_line_output = 4
+known_first_party = ["tqdm", "tests"]
+
+[tool.pytest.ini_options]
+minversion = "6.0"
+timeout = 30
+log_level = "INFO"
+markers = ["asyncio", "slow"]
+python_files = ["tests_*.py", "tests_*.ipynb"]
+testpaths = ["tests"]
+addopts = "-v --tb=short -rxs -W=error --durations=0 --durations-min=0.1 --asyncio-mode=strict"
+
+[tool.coverage.run]
+branch = true
+include = ["tqdm/*"]
+omit = [
+ "tqdm/contrib/bells.py",
+ "tqdm/contrib/slack.py",
+ "tqdm/contrib/discord.py",
+ "tqdm/contrib/telegram.py",
+ "tqdm/contrib/utils_worker.py"]
+relative_files = true
+disable_warnings = ["include-ignored"]
+[tool.coverage.report]
+show_missing = true
diff --git a/setup.cfg b/setup.cfg
deleted file mode 100644
index 4fb34f3..0000000
--- a/setup.cfg
+++ /dev/null
@@ -1,159 +0,0 @@
-[metadata]
-name = tqdm
-url = https://tqdm.github.io
-project_urls =
- Changelog=https://tqdm.github.io/releases
- Source=https://github.com/tqdm/tqdm
- Wiki=https://github.com/tqdm/tqdm/wiki
-maintainer = tqdm developers
-maintainer_email = python.tqdm@gmail.com
-license = MPLv2.0, MIT Licences
-license_file = LICENCE
-description = Fast, Extensible Progress Meter
-long_description = file: README.rst
-long_description_content_type = text/x-rst
-keywords = progressbar, progressmeter, progress, bar, meter, rate, eta, console, terminal, time
-platforms = any
-provides = tqdm
-classifiers =
- Development Status :: 5 - Production/Stable
- Environment :: Console
- Environment :: MacOS X
- Environment :: Other Environment
- Environment :: Win32 (MS Windows)
- Environment :: X11 Applications
- Framework :: IPython
- Framework :: Jupyter
- Intended Audience :: Developers
- Intended Audience :: Education
- Intended Audience :: End Users/Desktop
- Intended Audience :: Other Audience
- Intended Audience :: System Administrators
- License :: OSI Approved :: MIT License
- License :: OSI Approved :: Mozilla Public License 2.0 (MPL 2.0)
- Operating System :: MacOS
- Operating System :: MacOS :: MacOS X
- Operating System :: Microsoft
- Operating System :: Microsoft :: MS-DOS
- Operating System :: Microsoft :: Windows
- Operating System :: POSIX
- Operating System :: POSIX :: BSD
- Operating System :: POSIX :: BSD :: FreeBSD
- Operating System :: POSIX :: Linux
- Operating System :: POSIX :: SunOS/Solaris
- Operating System :: Unix
- Programming Language :: Python
- Programming Language :: Python :: 2
- Programming Language :: Python :: 2.7
- Programming Language :: Python :: 3
- Programming Language :: Python :: 3.5
- Programming Language :: Python :: 3.6
- Programming Language :: Python :: 3.7
- Programming Language :: Python :: 3.8
- Programming Language :: Python :: 3.9
- Programming Language :: Python :: 3.10
- Programming Language :: Python :: Implementation
- Programming Language :: Python :: Implementation :: IronPython
- Programming Language :: Python :: Implementation :: PyPy
- Programming Language :: Unix Shell
- Topic :: Desktop Environment
- Topic :: Education :: Computer Aided Instruction (CAI)
- Topic :: Education :: Testing
- Topic :: Office/Business
- Topic :: Other/Nonlisted Topic
- Topic :: Software Development :: Build Tools
- Topic :: Software Development :: Libraries
- Topic :: Software Development :: Libraries :: Python Modules
- Topic :: Software Development :: Pre-processors
- Topic :: Software Development :: User Interfaces
- Topic :: System :: Installation/Setup
- Topic :: System :: Logging
- Topic :: System :: Monitoring
- Topic :: System :: Shells
- Topic :: Terminals
- Topic :: Utilities
-
-[options]
-setup_requires = setuptools>=42; setuptools_scm[toml]>=3.4
-python_requires = >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*
-install_requires =
- colorama; platform_system == 'Windows'
- importlib_resources; python_version < "3.7"
-tests_require = tox
-include_package_data = True
-packages = find:
-
-[options.extras_require]
-dev = py-make>=0.1.0; twine; wheel
-slack = slack-sdk
-telegram = requests
-notebook = ipywidgets>=6
-
-[options.entry_points]
-console_scripts =
- tqdm=tqdm.cli:main
-
-[options.packages.find]
-exclude = benchmarks, tests
-
-[bdist_wheel]
-universal = 1
-
-[flake8]
-max_line_length = 99
-exclude = .asv,.eggs,.tox,.ipynb_checkpoints,build,dist,.git,__pycache__
-
-[pydocstyle]
-add_ignore = D400,D415
-
-[yapf]
-coalesce_brackets = True
-column_limit = 99
-each_dict_entry_on_separate_line = False
-i18n_comment = NOQA
-space_between_ending_comma_and_closing_bracket = False
-split_before_named_assigns = False
-split_before_closing_bracket = False
-
-[isort]
-line_length = 99
-multi_line_output = 4
-known_first_party = tqdm,tests
-
-[tool:pytest]
-timeout = 30
-log_level = INFO
-markers =
- asyncio
- slow
-python_files = tests_*.py tests_*.ipynb
-testpaths = tests
-addopts = -v --tb=short -rxs -W=error --durations=0 --durations-min=0.1 --asyncio-mode=strict
-
-[regex1]
-regex = (?<= )[\s\d.]+(it/s|s/it)
-replace = ??.??it/s
-
-[regex2]
-regex = 00:0[01]<00:0[01]
-replace = 00:00<00:00
-
-[coverage:run]
-branch = True
-include = tqdm/*
-omit =
- tqdm/contrib/bells.py
- tqdm/contrib/slack.py
- tqdm/contrib/discord.py
- tqdm/contrib/telegram.py
- tqdm/contrib/utils_worker.py
-relative_files = True
-disable_warnings = include-ignored
-
-[coverage:report]
-show_missing = True
-
-[egg_info]
-tag_build =
-tag_date = 0
-
diff --git a/setup.py b/setup.py
deleted file mode 100755
index 89dadf5..0000000
--- a/setup.py
+++ /dev/null
@@ -1,16 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-import sys
-from os import path
-
-from setuptools import setup
-
-src_dir = path.abspath(path.dirname(__file__))
-if sys.argv[1].lower().strip() == 'make': # exec Makefile commands
- import pymake
- fpath = path.join(src_dir, 'Makefile')
- pymake.main(['-f', fpath] + sys.argv[2:])
- # Stop to avoid setup.py raising non-standard command error
- sys.exit(0)
-
-setup(use_scm_version=True)
diff --git a/tests/conftest.py b/tests/conftest.py
index 6717044..7960fa0 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -18,24 +18,10 @@ def pretest_posttest():
n = len(tqdm._instances)
if n:
tqdm._instances.clear()
- raise EnvironmentError(
- "{0} `tqdm` instances still in existence PRE-test".format(n))
+ raise EnvironmentError(f"{n} `tqdm` instances still in existence PRE-test")
yield
if getattr(tqdm, "_instances", False):
n = len(tqdm._instances)
if n:
tqdm._instances.clear()
- raise EnvironmentError(
- "{0} `tqdm` instances still in existence POST-test".format(n))
-
-
-if sys.version_info[0] > 2:
- @fixture
- def capsysbin(capsysbinary):
- """alias for capsysbinary (py3)"""
- return capsysbinary
-else:
- @fixture
- def capsysbin(capsys):
- """alias for capsys (py2)"""
- return capsys
+ raise EnvironmentError(f"{n} `tqdm` instances still in existence POST-test")
diff --git a/tests/py37_asyncio.py b/tests/py37_asyncio.py
deleted file mode 100644
index 8bf61e7..0000000
--- a/tests/py37_asyncio.py
+++ /dev/null
@@ -1,128 +0,0 @@
-import asyncio
-from functools import partial
-from sys import platform
-from time import time
-
-from tqdm.asyncio import tarange, tqdm_asyncio
-
-from .tests_tqdm import StringIO, closing, mark
-
-tqdm = partial(tqdm_asyncio, miniters=0, mininterval=0)
-trange = partial(tarange, miniters=0, mininterval=0)
-as_completed = partial(tqdm_asyncio.as_completed, miniters=0, mininterval=0)
-gather = partial(tqdm_asyncio.gather, miniters=0, mininterval=0)
-
-
-def count(start=0, step=1):
- i = start
- while True:
- new_start = yield i
- if new_start is None:
- i += step
- else:
- i = new_start
-
-
-async def acount(*args, **kwargs):
- for i in count(*args, **kwargs):
- yield i
-
-
-@mark.asyncio
-async def test_break():
- """Test asyncio break"""
- pbar = tqdm(count())
- async for _ in pbar:
- break
- pbar.close()
-
-
-@mark.asyncio
-async def test_generators(capsys):
- """Test asyncio generators"""
- with tqdm(count(), desc="counter") as pbar:
- async for i in pbar:
- if i >= 8:
- break
- _, err = capsys.readouterr()
- assert '9it' in err
-
- with tqdm(acount(), desc="async_counter") as pbar:
- async for i in pbar:
- if i >= 8:
- break
- _, err = capsys.readouterr()
- assert '9it' in err
-
-
-@mark.asyncio
-async def test_range():
- """Test asyncio range"""
- with closing(StringIO()) as our_file:
- async for _ in tqdm(range(9), desc="range", file=our_file):
- pass
- assert '9/9' in our_file.getvalue()
- our_file.seek(0)
- our_file.truncate()
-
- async for _ in trange(9, desc="trange", file=our_file):
- pass
- assert '9/9' in our_file.getvalue()
-
-
-@mark.asyncio
-async def test_nested():
- """Test asyncio nested"""
- with closing(StringIO()) as our_file:
- async for _ in tqdm(trange(9, desc="inner", file=our_file),
- desc="outer", file=our_file):
- pass
- assert 'inner: 100%' in our_file.getvalue()
- assert 'outer: 100%' in our_file.getvalue()
-
-
-@mark.asyncio
-async def test_coroutines():
- """Test asyncio coroutine.send"""
- with closing(StringIO()) as our_file:
- with tqdm(count(), file=our_file) as pbar:
- async for i in pbar:
- if i == 9:
- pbar.send(-10)
- elif i < 0:
- assert i == -9
- break
- assert '10it' in our_file.getvalue()
-
-
-@mark.slow
-@mark.asyncio
-@mark.parametrize("tol", [0.2 if platform.startswith("darwin") else 0.1])
-async def test_as_completed(capsys, tol):
- """Test asyncio as_completed"""
- for retry in range(3):
- t = time()
- skew = time() - t
- for i in as_completed([asyncio.sleep(0.01 * i) for i in range(30, 0, -1)]):
- await i
- t = time() - t - 2 * skew
- try:
- assert 0.3 * (1 - tol) < t < 0.3 * (1 + tol), t
- _, err = capsys.readouterr()
- assert '30/30' in err
- except AssertionError:
- if retry == 2:
- raise
-
-
-async def double(i):
- return i * 2
-
-
-@mark.asyncio
-async def test_gather(capsys):
- """Test asyncio gather"""
- res = await gather(*map(double, range(30)))
- _, err = capsys.readouterr()
- assert '30/30' in err
- assert res == list(range(0, 30 * 2, 2))
diff --git a/tests/tests_asyncio.py b/tests/tests_asyncio.py
index 6f08926..bdef569 100644
--- a/tests/tests_asyncio.py
+++ b/tests/tests_asyncio.py
@@ -1,11 +1,129 @@
-"""Tests `tqdm.asyncio` on `python>=3.7`."""
-import sys
-
-if sys.version_info[:2] > (3, 6):
- from .py37_asyncio import * # NOQA, pylint: disable=wildcard-import
-else:
- from .tests_tqdm import skip
- try:
- skip("async not supported", allow_module_level=True)
- except TypeError:
- pass
+"""Tests `tqdm.asyncio`."""
+import asyncio
+from functools import partial
+from sys import platform
+from time import time
+
+from tqdm.asyncio import tarange, tqdm_asyncio
+
+from .tests_tqdm import StringIO, closing, mark
+
+tqdm = partial(tqdm_asyncio, miniters=0, mininterval=0)
+trange = partial(tarange, miniters=0, mininterval=0)
+as_completed = partial(tqdm_asyncio.as_completed, miniters=0, mininterval=0)
+gather = partial(tqdm_asyncio.gather, miniters=0, mininterval=0)
+
+
+def count(start=0, step=1):
+ i = start
+ while True:
+ new_start = yield i
+ if new_start is None:
+ i += step
+ else:
+ i = new_start
+
+
+async def acount(*args, **kwargs):
+ for i in count(*args, **kwargs):
+ yield i
+
+
+@mark.asyncio
+async def test_break():
+ """Test asyncio break"""
+ pbar = tqdm(count())
+ async for _ in pbar:
+ break
+ pbar.close()
+
+
+@mark.asyncio
+async def test_generators(capsys):
+ """Test asyncio generators"""
+ with tqdm(count(), desc="counter") as pbar:
+ async for i in pbar:
+ if i >= 8:
+ break
+ _, err = capsys.readouterr()
+ assert '9it' in err
+
+ with tqdm(acount(), desc="async_counter") as pbar:
+ async for i in pbar:
+ if i >= 8:
+ break
+ _, err = capsys.readouterr()
+ assert '9it' in err
+
+
+@mark.asyncio
+async def test_range():
+ """Test asyncio range"""
+ with closing(StringIO()) as our_file:
+ async for _ in tqdm(range(9), desc="range", file=our_file):
+ pass
+ assert '9/9' in our_file.getvalue()
+ our_file.seek(0)
+ our_file.truncate()
+
+ async for _ in trange(9, desc="trange", file=our_file):
+ pass
+ assert '9/9' in our_file.getvalue()
+
+
+@mark.asyncio
+async def test_nested():
+ """Test asyncio nested"""
+ with closing(StringIO()) as our_file:
+ async for _ in tqdm(trange(9, desc="inner", file=our_file),
+ desc="outer", file=our_file):
+ pass
+ assert 'inner: 100%' in our_file.getvalue()
+ assert 'outer: 100%' in our_file.getvalue()
+
+
+@mark.asyncio
+async def test_coroutines():
+ """Test asyncio coroutine.send"""
+ with closing(StringIO()) as our_file:
+ with tqdm(count(), file=our_file) as pbar:
+ async for i in pbar:
+ if i == 9:
+ pbar.send(-10)
+ elif i < 0:
+ assert i == -9
+ break
+ assert '10it' in our_file.getvalue()
+
+
+@mark.slow
+@mark.asyncio
+@mark.parametrize("tol", [0.2 if platform.startswith("darwin") else 0.1])
+async def test_as_completed(capsys, tol):
+ """Test asyncio as_completed"""
+ for retry in range(3):
+ t = time()
+ skew = time() - t
+ for i in as_completed([asyncio.sleep(0.01 * i) for i in range(30, 0, -1)]):
+ await i
+ t = time() - t - 2 * skew
+ try:
+ assert 0.3 * (1 - tol) < t < 0.3 * (1 + tol), t
+ _, err = capsys.readouterr()
+ assert '30/30' in err
+ except AssertionError:
+ if retry == 2:
+ raise
+
+
+async def double(i):
+ return i * 2
+
+
+@mark.asyncio
+async def test_gather(capsys):
+ """Test asyncio gather"""
+ res = await gather(*map(double, range(30)))
+ _, err = capsys.readouterr()
+ assert '30/30' in err
+ assert res == list(range(0, 30 * 2, 2))
diff --git a/tests/tests_contrib.py b/tests/tests_contrib.py
index 69a1cad..65c8cd5 100644
--- a/tests/tests_contrib.py
+++ b/tests/tests_contrib.py
@@ -1,8 +1,6 @@
"""
Tests for `tqdm.contrib`.
"""
-import sys
-
import pytest
from tqdm import tqdm
@@ -47,12 +45,9 @@ def test_zip(tqdm_kwargs):
with closing(StringIO()) as our_file:
a = range(9)
b = [i + 1 for i in a]
- if sys.version_info[:1] < (3,):
- assert tzip(a, b, file=our_file, **tqdm_kwargs) == zip(a, b)
- else:
- gen = tzip(a, b, file=our_file, **tqdm_kwargs)
- assert gen != list(zip(a, b))
- assert list(gen) == list(zip(a, b))
+ gen = tzip(a, b, file=our_file, **tqdm_kwargs)
+ assert gen != list(zip(a, b))
+ assert list(gen) == list(zip(a, b))
@pytest.mark.parametrize("tqdm_kwargs", [{}, {"tqdm_class": tqdm}])
@@ -61,11 +56,6 @@ def test_map(tqdm_kwargs):
with closing(StringIO()) as our_file:
a = range(9)
b = [i + 1 for i in a]
- if sys.version_info[:1] < (3,):
- assert tmap(lambda x: x + 1, a, file=our_file, **tqdm_kwargs) == map(
- incr, a
- )
- else:
- gen = tmap(lambda x: x + 1, a, file=our_file, **tqdm_kwargs)
- assert gen != b
- assert list(gen) == b
+ gen = tmap(lambda x: x + 1, a, file=our_file, **tqdm_kwargs)
+ assert gen != b
+ assert list(gen) == b
diff --git a/tests/tests_contrib_logging.py b/tests/tests_contrib_logging.py
index 6f675dd..b8d60b6 100644
--- a/tests/tests_contrib_logging.py
+++ b/tests/tests_contrib_logging.py
@@ -1,7 +1,5 @@
# pylint: disable=missing-module-docstring, missing-class-docstring
# pylint: disable=missing-function-docstring, no-self-use
-from __future__ import absolute_import
-
import logging
import logging.handlers
import sys
diff --git a/tests/tests_dask.py b/tests/tests_dask.py
index 8bf4b64..16992bf 100644
--- a/tests/tests_dask.py
+++ b/tests/tests_dask.py
@@ -1,5 +1,3 @@
-from __future__ import division
-
from time import sleep
from .tests_tqdm import importorskip, mark
diff --git a/tests/tests_keras.py b/tests/tests_keras.py
index 220f946..5b7db28 100644
--- a/tests/tests_keras.py
+++ b/tests/tests_keras.py
@@ -1,5 +1,3 @@
-from __future__ import division
-
from .tests_tqdm import importorskip, mark
pytestmark = mark.slow
@@ -41,8 +39,8 @@ def test_keras(capsys):
verbose=0)])
_, res = capsys.readouterr()
assert "training: " in res
- assert "{epochs}/{epochs}".format(epochs=epochs) in res
- assert "{batches}/{batches}".format(batches=batches) not in res
+ assert f"{epochs}/{epochs}" in res
+ assert f"{batches}/{batches}" not in res
# full (epoch and batch) progress
model.fit(
@@ -60,8 +58,8 @@ def test_keras(capsys):
verbose=2)])
_, res = capsys.readouterr()
assert "training: " in res
- assert "{epochs}/{epochs}".format(epochs=epochs) in res
- assert "{batches}/{batches}".format(batches=batches) in res
+ assert f"{epochs}/{epochs}" in res
+ assert f"{batches}/{batches}" in res
# auto-detect epochs and batches
model.fit(
@@ -73,8 +71,8 @@ def test_keras(capsys):
callbacks=[TqdmCallback(desc="training", verbose=2)])
_, res = capsys.readouterr()
assert "training: " in res
- assert "{epochs}/{epochs}".format(epochs=epochs) in res
- assert "{batches}/{batches}".format(batches=batches) in res
+ assert f"{epochs}/{epochs}" in res
+ assert f"{batches}/{batches}" in res
# continue training (start from epoch != 0)
initial_epoch = 3
@@ -89,5 +87,5 @@ def test_keras(capsys):
miniters=1, mininterval=0, maxinterval=0)])
_, res = capsys.readouterr()
assert "training: " in res
- assert "{epochs}/{epochs}".format(epochs=initial_epoch - 1) not in res
- assert "{epochs}/{epochs}".format(epochs=epochs) in res
+ assert f"{initial_epoch - 1}/{initial_epoch - 1}" not in res
+ assert f"{epochs}/{epochs}" in res
diff --git a/tests/tests_main.py b/tests/tests_main.py
index 0523cc7..039ce33 100644
--- a/tests/tests_main.py
+++ b/tests/tests_main.py
@@ -8,17 +8,17 @@ from os import linesep
from tqdm.cli import TqdmKeyError, TqdmTypeError, main
from tqdm.utils import IS_WIN
-from .tests_tqdm import BytesIO, _range, closing, mark, raises
+from .tests_tqdm import BytesIO, closing, mark, raises
def restore_sys(func):
- """Decorates `func(capsysbin)` to save & restore `sys.(stdin|argv)`."""
+ """Decorates `func(capsysbinary)` to save & restore `sys.(stdin|argv)`."""
@wraps(func)
- def inner(capsysbin):
- """function requiring capsysbin which may alter `sys.(stdin|argv)`"""
+ def inner(capsysbinary):
+ """function requiring capsysbinary which may alter `sys.(stdin|argv)`"""
_SYS = sys.stdin, sys.argv
try:
- res = func(capsysbin)
+ res = func(capsysbinary)
finally:
sys.stdin, sys.argv = _SYS
return res
@@ -58,7 +58,7 @@ def test_main_import():
N = 123
_SYS = sys.stdin, sys.argv
# test direct import
- sys.stdin = [str(i).encode() for i in _range(N)]
+ sys.stdin = [str(i).encode() for i in range(N)]
sys.argv = ['', '--desc', 'Test CLI import',
'--ascii', 'True', '--unit_scale', 'True']
try:
@@ -68,19 +68,19 @@ def test_main_import():
@restore_sys
-def test_main_bytes(capsysbin):
+def test_main_bytes(capsysbinary):
"""Test CLI --bytes"""
N = 123
# test --delim
- IN_DATA = '\0'.join(map(str, _range(N))).encode()
+ IN_DATA = '\0'.join(map(str, range(N))).encode()
with closing(BytesIO()) as sys.stdin:
sys.stdin.write(IN_DATA)
# sys.stdin.write(b'\xff') # TODO
sys.stdin.seek(0)
main(sys.stderr, ['--desc', 'Test CLI delim', '--ascii', 'True',
'--delim', r'\0', '--buf_size', '64'])
- out, err = capsysbin.readouterr()
+ out, err = capsysbinary.readouterr()
assert out == IN_DATA
assert str(N) + "it" in err.decode("U8")
@@ -90,27 +90,26 @@ def test_main_bytes(capsysbin):
sys.stdin.write(IN_DATA)
sys.stdin.seek(0)
main(sys.stderr, ['--ascii', '--bytes=True', '--unit_scale', 'False'])
- out, err = capsysbin.readouterr()
+ out, err = capsysbinary.readouterr()
assert out == IN_DATA
assert str(len(IN_DATA)) + "B" in err.decode("U8")
-@mark.skipif(sys.version_info[0] == 2, reason="no caplog on py2")
-def test_main_log(capsysbin, caplog):
+def test_main_log(capsysbinary, caplog):
"""Test CLI --log"""
_SYS = sys.stdin, sys.argv
N = 123
- sys.stdin = [(str(i) + '\n').encode() for i in _range(N)]
+ sys.stdin = [(str(i) + '\n').encode() for i in range(N)]
IN_DATA = b''.join(sys.stdin)
try:
with caplog.at_level(logging.INFO):
main(sys.stderr, ['--log', 'INFO'])
- out, err = capsysbin.readouterr()
+ out, err = capsysbinary.readouterr()
assert norm(out) == IN_DATA and b"123/123" in err
assert not caplog.record_tuples
with caplog.at_level(logging.DEBUG):
main(sys.stderr, ['--log', 'DEBUG'])
- out, err = capsysbin.readouterr()
+ out, err = capsysbinary.readouterr()
assert norm(out) == IN_DATA and b"123/123" in err
assert caplog.record_tuples
finally:
@@ -118,39 +117,39 @@ def test_main_log(capsysbin, caplog):
@restore_sys
-def test_main(capsysbin):
+def test_main(capsysbinary):
"""Test misc CLI options"""
N = 123
- sys.stdin = [(str(i) + '\n').encode() for i in _range(N)]
+ sys.stdin = [(str(i) + '\n').encode() for i in range(N)]
IN_DATA = b''.join(sys.stdin)
# test --tee
main(sys.stderr, ['--mininterval', '0', '--miniters', '1'])
- out, err = capsysbin.readouterr()
+ out, err = capsysbinary.readouterr()
assert norm(out) == IN_DATA and b"123/123" in err
assert N <= len(err.split(b"\r")) < N + 5
len_err = len(err)
main(sys.stderr, ['--tee', '--mininterval', '0', '--miniters', '1'])
- out, err = capsysbin.readouterr()
+ out, err = capsysbinary.readouterr()
assert norm(out) == IN_DATA and b"123/123" in err
# spaces to clear intermediate lines could increase length
assert len_err + len(norm(out)) <= len(err)
# test --null
main(sys.stderr, ['--null'])
- out, err = capsysbin.readouterr()
+ out, err = capsysbinary.readouterr()
assert not out and b"123/123" in err
# test integer --update
main(sys.stderr, ['--update'])
- out, err = capsysbin.readouterr()
+ out, err = capsysbinary.readouterr()
assert norm(out) == IN_DATA
assert (str(N // 2 * N) + "it").encode() in err, "expected arithmetic sum formula"
# test integer --update_to
main(sys.stderr, ['--update-to'])
- out, err = capsysbin.readouterr()
+ out, err = capsysbinary.readouterr()
assert norm(out) == IN_DATA
assert (str(N - 1) + "it").encode() in err
assert (str(N) + "it").encode() not in err
@@ -161,23 +160,23 @@ def test_main(capsysbin):
# test integer --update --delim
sys.stdin.seek(0)
main(sys.stderr, ['--update', '--delim', 'D'])
- out, err = capsysbin.readouterr()
+ out, err = capsysbinary.readouterr()
assert out == IN_DATA.replace(b'\n', b'D')
assert (str(N // 2 * N) + "it").encode() in err, "expected arithmetic sum"
# test integer --update_to --delim
sys.stdin.seek(0)
main(sys.stderr, ['--update-to', '--delim', 'D'])
- out, err = capsysbin.readouterr()
+ out, err = capsysbinary.readouterr()
assert out == IN_DATA.replace(b'\n', b'D')
assert (str(N - 1) + "it").encode() in err
assert (str(N) + "it").encode() not in err
# test float --update_to
- sys.stdin = [(str(i / 2.0) + '\n').encode() for i in _range(N)]
+ sys.stdin = [(str(i / 2.0) + '\n').encode() for i in range(N)]
IN_DATA = b''.join(sys.stdin)
main(sys.stderr, ['--update-to'])
- out, err = capsysbin.readouterr()
+ out, err = capsysbinary.readouterr()
assert norm(out) == IN_DATA
assert (str((N - 1) / 2.0) + "it").encode() in err
assert (str(N / 2.0) + "it").encode() not in err
@@ -213,30 +212,30 @@ def test_comppath(tmp_path):
@restore_sys
-def test_exceptions(capsysbin):
+def test_exceptions(capsysbinary):
"""Test CLI Exceptions"""
N = 123
- sys.stdin = [str(i) + '\n' for i in _range(N)]
+ sys.stdin = [str(i) + '\n' for i in range(N)]
IN_DATA = ''.join(sys.stdin).encode()
with raises(TqdmKeyError, match="bad_arg_u_ment"):
main(sys.stderr, argv=['-ascii', '-unit_scale', '--bad_arg_u_ment', 'foo'])
- out, _ = capsysbin.readouterr()
+ out, _ = capsysbinary.readouterr()
assert norm(out) == IN_DATA
with raises(TqdmTypeError, match="invalid_bool_value"):
main(sys.stderr, argv=['-ascii', '-unit_scale', 'invalid_bool_value'])
- out, _ = capsysbin.readouterr()
+ out, _ = capsysbinary.readouterr()
assert norm(out) == IN_DATA
with raises(TqdmTypeError, match="invalid_int_value"):
main(sys.stderr, argv=['-ascii', '--total', 'invalid_int_value'])
- out, _ = capsysbin.readouterr()
+ out, _ = capsysbinary.readouterr()
assert norm(out) == IN_DATA
with raises(TqdmKeyError, match="Can only have one of --"):
main(sys.stderr, argv=['--update', '--update_to'])
- out, _ = capsysbin.readouterr()
+ out, _ = capsysbinary.readouterr()
assert norm(out) == IN_DATA
# test SystemExits
diff --git a/tests/tests_pandas.py b/tests/tests_pandas.py
index 334a97c..09dff1e 100644
--- a/tests/tests_pandas.py
+++ b/tests/tests_pandas.py
@@ -4,6 +4,7 @@ from .tests_tqdm import StringIO, closing, importorskip, mark, skip
pytestmark = mark.slow
+np = importorskip('numpy')
random = importorskip('numpy.random')
rand = random.rand
randint = random.randint
@@ -39,8 +40,8 @@ def test_pandas_rolling_expanding():
our_file.seek(0)
if our_file.getvalue().count(exres) < 2:
our_file.seek(0)
- raise AssertionError("\nExpected:\n{0}\nIn:\n{1}\n".format(
- exres + " at least twice.", our_file.read()))
+ raise AssertionError(
+ f"\nExpected:\n{exres} at least twice.\nIn:\n{our_file.read()}\n")
def test_pandas_series():
@@ -62,10 +63,11 @@ def test_pandas_series():
our_file.seek(0)
if our_file.getvalue().count(exres) < 2:
our_file.seek(0)
- raise AssertionError("\nExpected:\n{0}\nIn:\n{1}\n".format(
- exres + " at least twice.", our_file.read()))
+ raise AssertionError(
+ f"\nExpected:\n{exres} at least twice.\nIn:\n{our_file.read()}\n")
+@mark.filterwarnings("ignore:DataFrame.applymap has been deprecated:FutureWarning")
def test_pandas_data_frame():
"""Test pandas.DataFrame.progress_apply and .progress_applymap"""
with closing(StringIO()) as our_file:
@@ -80,6 +82,12 @@ def test_pandas_data_frame():
res2 = df.applymap(task_func)
assert res1.equals(res2)
+ # map
+ if hasattr(df, 'map'): # pandas>=2.1.0
+ res1 = df.progress_map(task_func)
+ res2 = df.map(task_func)
+ assert res1.equals(res2)
+
# apply unhashable
res1 = []
df.progress_apply(res1.extend)
@@ -94,8 +102,8 @@ def test_pandas_data_frame():
our_file.seek(0)
if our_file.read().count('100%') < 3:
our_file.seek(0)
- raise AssertionError("\nExpected:\n{0}\nIn:\n{1}\n".format(
- '100% at least three times', our_file.read()))
+ raise AssertionError(
+ f"\nExpected:\n100% at least three times\nIn:\n{our_file.read()}\n")
# apply_map, apply axis=0, apply axis=1
expects = ['20000/20000', '200/200', '100/100']
@@ -103,10 +111,12 @@ def test_pandas_data_frame():
our_file.seek(0)
if our_file.getvalue().count(exres) < 1:
our_file.seek(0)
- raise AssertionError("\nExpected:\n{0}\nIn:\n {1}\n".format(
- exres + " at least once.", our_file.read()))
+ raise AssertionError(
+ f"\nExpected:\n{exres} at least once.\nIn:\n{our_file.read()}\n")
+@mark.filterwarnings(
+ "ignore:DataFrameGroupBy.apply operated on the grouping columns:DeprecationWarning")
def test_pandas_groupby_apply():
"""Test pandas.DataFrame.groupby(...).progress_apply"""
with closing(StringIO()) as our_file:
@@ -119,8 +129,8 @@ def test_pandas_groupby_apply():
dfs.groupby(['a']).progress_apply(lambda x: None)
df2 = df = pd.DataFrame({'a': randint(1, 8, 10000), 'b': rand(10000)})
- res1 = df2.groupby("a").apply(max)
- res2 = df2.groupby("a").progress_apply(max)
+ res1 = df2.groupby("a").apply(np.maximum.reduce)
+ res2 = df2.groupby("a").progress_apply(np.maximum.reduce)
assert res1.equals(res2)
our_file.seek(0)
@@ -130,8 +140,7 @@ def test_pandas_groupby_apply():
nexres = '100%|##########|'
if nexres in our_file.read():
our_file.seek(0)
- raise AssertionError("\nDid not expect:\n{0}\nIn:{1}\n".format(
- nexres, our_file.read()))
+ raise AssertionError(f"\nDid not expect:\n{nexres}\nIn:{our_file.read()}\n")
with closing(StringIO()) as our_file:
tqdm.pandas(file=our_file, leave=True, ascii=True)
@@ -140,26 +149,28 @@ def test_pandas_groupby_apply():
dfs.loc[0] = [2, 1, 1]
dfs['d'] = 100
- expects = ['500/500', '1/1', '4/4', '2/2']
+ expects = ['500/500', '1/1', '4/4', '4/4']
dfs.groupby(dfs.index).progress_apply(lambda x: None)
dfs.groupby('d').progress_apply(lambda x: None)
- dfs.groupby(dfs.columns, axis=1).progress_apply(lambda x: None)
- dfs.groupby([2, 2, 1, 1], axis=1).progress_apply(lambda x: None)
+ dfs.T.groupby(dfs.columns).progress_apply(lambda x: None)
+ dfs.T.groupby([2, 2, 1, 1]).progress_apply(lambda x: None)
our_file.seek(0)
if our_file.read().count('100%') < 4:
our_file.seek(0)
- raise AssertionError("\nExpected:\n{0}\nIn:\n{1}\n".format(
- '100% at least four times', our_file.read()))
+ raise AssertionError(
+ f"\nExpected:\n100% at least four times\nIn:\n{our_file.read()}\n")
for exres in expects:
our_file.seek(0)
if our_file.getvalue().count(exres) < 1:
our_file.seek(0)
- raise AssertionError("\nExpected:\n{0}\nIn:\n {1}\n".format(
- exres + " at least once.", our_file.read()))
+ raise AssertionError(
+ f"\nExpected:\n{exres} at least once.\nIn:\n{our_file.read()}\n")
+@mark.filterwarnings(
+ "ignore:DataFrameGroupBy.apply operated on the grouping columns:DeprecationWarning")
def test_pandas_leave():
"""Test pandas with `leave=True`"""
with closing(StringIO()) as our_file:
@@ -172,8 +183,7 @@ def test_pandas_leave():
exres = '100%|##########| 100/100'
if exres not in our_file.read():
our_file.seek(0)
- raise AssertionError("\nExpected:\n{0}\nIn:{1}\n".format(
- exres, our_file.read()))
+ raise AssertionError(f"\nExpected:\n{exres}\nIn:{our_file.read()}\n")
def test_pandas_apply_args_deprecation():
@@ -195,6 +205,8 @@ def test_pandas_apply_args_deprecation():
"keyword arguments instead"))
+@mark.filterwarnings(
+ "ignore:DataFrameGroupBy.apply operated on the grouping columns:DeprecationWarning")
def test_pandas_deprecation():
"""Test bar object instance as argument deprecation"""
try:
diff --git a/tests/tests_perf.py b/tests/tests_perf.py
index 552a169..a6c4823 100644
--- a/tests/tests_perf.py
+++ b/tests/tests_perf.py
@@ -1,5 +1,3 @@
-from __future__ import division, print_function
-
import sys
from contextlib import contextmanager
from functools import wraps
@@ -14,7 +12,7 @@ except ImportError:
from tqdm import tqdm, trange
-from .tests_tqdm import _range, importorskip, mark, patch_lock, skip
+from .tests_tqdm import importorskip, mark, patch_lock, skip
pytestmark = mark.slow
@@ -98,10 +96,7 @@ def simple_progress(iterable=None, total=None, file=sys.stdout, desc='',
def format_interval(t):
mins, s = divmod(int(t), 60)
h, m = divmod(mins, 60)
- if h:
- return '{0:d}:{1:02d}:{2:02d}'.format(h, m, s)
- else:
- return '{0:02d}:{1:02d}'.format(m, s)
+ return f'{h:d}:{m:02d}:{s:02d}' if h else f'{m:02d}:{s:02d}'
def update_and_print(i=1):
n[0] += i
@@ -143,20 +138,15 @@ def simple_progress(iterable=None, total=None, file=sys.stdout, desc='',
update_and_print(0)
if iterable is not None:
return update_and_yield()
- else:
- return update_and_print
+ return update_and_print
def assert_performance(thresh, name_left, time_left, name_right, time_right):
"""raises if time_left > thresh * time_right"""
if time_left > thresh * time_right:
raise ValueError(
- ('{name[0]}: {time[0]:f}, '
- '{name[1]}: {time[1]:f}, '
- 'ratio {ratio:f} > {thresh:f}').format(
- name=(name_left, name_right),
- time=(time_left, time_right),
- ratio=time_left / time_right, thresh=thresh))
+ f'{name_left}: {time_left:f}, {name_right}: {time_right:f}'
+ f', ratio {time_left / time_right:f} > {thresh:f}')
@retry_on_except()
@@ -173,7 +163,7 @@ def test_iter_basic_overhead():
a = 0
with relative_timer() as time_bench:
- for i in _range(total):
+ for i in range(total):
a += i
sys.stdout.write(str(a))
@@ -188,13 +178,13 @@ def test_manual_basic_overhead():
with tqdm(total=total * 10, leave=True) as t:
a = 0
with relative_timer() as time_tqdm:
- for i in _range(total):
+ for i in range(total):
a += i
t.update(10)
a = 0
with relative_timer() as time_bench:
- for i in _range(total):
+ for i in range(total):
a += i
sys.stdout.write(str(a))
@@ -249,7 +239,7 @@ def test_iter_overhead_hard():
a = 0
with relative_timer() as time_bench:
- for i in _range(total):
+ for i in range(total):
a += i
sys.stdout.write(("%i" % a) * 40)
@@ -265,13 +255,13 @@ def test_manual_overhead_hard():
mininterval=0, maxinterval=0) as t:
a = 0
with relative_timer() as time_tqdm:
- for i in _range(total):
+ for i in range(total):
a += i
t.update(10)
a = 0
with relative_timer() as time_bench:
- for i in _range(total):
+ for i in range(total):
a += i
sys.stdout.write(("%i" % a) * 40)
@@ -292,7 +282,7 @@ def test_iter_overhead_simplebar_hard():
assert a == (total ** 2 - total) / 2.0
a = 0
- s = simple_progress(_range(total), leave=True,
+ s = simple_progress(range(total), leave=True,
miniters=1, mininterval=0)
with relative_timer() as time_bench:
for i in s:
@@ -310,7 +300,7 @@ def test_manual_overhead_simplebar_hard():
mininterval=0, maxinterval=0) as t:
a = 0
with relative_timer() as time_tqdm:
- for i in _range(total):
+ for i in range(total):
a += i
t.update(10)
@@ -318,7 +308,7 @@ def test_manual_overhead_simplebar_hard():
miniters=1, mininterval=0)
a = 0
with relative_timer() as time_bench:
- for i in _range(total):
+ for i in range(total):
a += i
simplebar_update(10)
diff --git a/tests/tests_rich.py b/tests/tests_rich.py
index c75e246..2fff78c 100644
--- a/tests/tests_rich.py
+++ b/tests/tests_rich.py
@@ -1,10 +1,7 @@
"""Test `tqdm.rich`."""
-import sys
+from .tests_tqdm import importorskip
-from .tests_tqdm import importorskip, mark
-
-@mark.skipif(sys.version_info[:3] < (3, 6, 1), reason="`rich` needs py>=3.6.1")
def test_rich_import():
"""Test `tqdm.rich` import"""
importorskip('tqdm.rich')
diff --git a/tests/tests_synchronisation.py b/tests/tests_synchronisation.py
index 7ee55fb..0cd9190 100644
--- a/tests/tests_synchronisation.py
+++ b/tests/tests_synchronisation.py
@@ -1,13 +1,9 @@
-from __future__ import division
-
-import sys
from functools import wraps
from threading import Event
from time import sleep, time
from tqdm import TMonitor, tqdm, trange
-from .tests_perf import retry_on_except
from .tests_tqdm import StringIO, closing, importorskip, patch_lock, skip
@@ -37,18 +33,13 @@ class Time(object):
sleep(0.000001) # sleep to allow interrupt (instead of pass)
-def FakeEvent():
+class FakeEvent(Event):
"""patched `threading.Event` where `wait()` uses `Time.fake_sleep()`"""
- event = Event() # not a class in py2 so can't inherit
-
- def wait(timeout=None):
+ def wait(self, timeout=None):
"""uses Time.fake_sleep"""
if timeout is not None:
Time.fake_sleep(timeout)
- return event.is_set()
-
- event.wait = wait
- return event
+ return self.is_set()
def patch_sleep(func):
@@ -206,19 +197,11 @@ def test_imap():
assert res[-1] == 100
-# py2: locks won't propagate to incr_bar so may cause `AttributeError`
-@retry_on_except(n=3 if sys.version_info < (3,) else 1, check_cpu_time=False)
@patch_lock(thread=True)
def test_threadpool():
"""Test concurrent.futures.ThreadPoolExecutor"""
ThreadPoolExecutor = importorskip('concurrent.futures').ThreadPoolExecutor
with ThreadPoolExecutor(8) as pool:
- try:
- res = list(tqdm(pool.map(incr_bar, range(100)), disable=True))
- except AttributeError:
- if sys.version_info < (3,):
- skip("not supported on py2")
- else:
- raise
+ res = list(tqdm(pool.map(incr_bar, range(100)), disable=True))
assert sum(res) == sum(range(1, 101))
diff --git a/tests/tests_tqdm.py b/tests/tests_tqdm.py
index bba457a..d0ba14f 100644
--- a/tests/tests_tqdm.py
+++ b/tests/tests_tqdm.py
@@ -1,8 +1,6 @@
# -*- coding: utf-8 -*-
# Advice: use repr(our_file.read()) to print the full output of tqdm
# (else '\r' will replace the previous lines and you'll see only the latest.
-from __future__ import print_function
-
import csv
import os
import re
@@ -37,16 +35,6 @@ if getattr(StringIO, '__exit__', False) and getattr(StringIO, '__enter__', False
else:
from contextlib import closing
-try:
- _range = xrange
-except NameError:
- _range = range
-
-try:
- _unicode = unicode
-except NameError:
- _unicode = str
-
nt_and_no_colorama = False
if os.name == 'nt':
try:
@@ -201,6 +189,8 @@ def test_format_num():
assert float(format_num(1337)) == 1337
assert format_num(int(1e6)) == '1e+6'
assert format_num(1239876) == '1' '239' '876'
+ assert format_num(0.00001234) == '1.23e-5'
+ assert format_num(-0.1234) == '-0.123'
def test_format_meter():
@@ -271,11 +261,10 @@ def test_format_meter():
20, 100, 12, ncols=14, rate=8.1,
bar_format=r'{l_bar}{bar}|{n_fmt}/{total_fmt}') == " 20%|" + unich(0x258d) + " |20/100"
# Check wide characters
- if sys.version_info >= (3,):
- assert format_meter(0, 1000, 13, ncols=68, prefix='fullwidth: ') == (
- "fullwidth: 0%| | 0/1000 [00:13<?, ?it/s]")
- assert format_meter(0, 1000, 13, ncols=68, prefix='ニッポン [ニッポン]: ') == (
- "ニッポン [ニッポン]: 0%| | 0/1000 [00:13<?, ?it/s]")
+ assert format_meter(0, 1000, 13, ncols=68, prefix='fullwidth: ') == (
+ "fullwidth: 0%| | 0/1000 [00:13<?, ?it/s]")
+ assert format_meter(0, 1000, 13, ncols=68, prefix='ニッポン [ニッポン]: ') == (
+ "ニッポン [ニッポン]: 0%| | 0/1000 [00:13<?, ?it/s]")
# Check that bar_format can print only {bar} or just one side
assert format_meter(20, 100, 12, ncols=2, rate=8.1,
bar_format=r'{bar}') == unich(0x258d) + " "
@@ -328,11 +317,11 @@ def test_si_format():
def test_bar_formatspec():
"""Test Bar.__format__ spec"""
- assert "{0:5a}".format(Bar(0.3)) == "#5 "
- assert "{0:2}".format(Bar(0.5, charset=" .oO0")) == "0 "
- assert "{0:2a}".format(Bar(0.5, charset=" .oO0")) == "# "
- assert "{0:-6a}".format(Bar(0.5, 10)) == '## '
- assert "{0:2b}".format(Bar(0.5, 10)) == ' '
+ assert f"{Bar(0.3):5a}" == "#5 "
+ assert f"{Bar(0.5, charset=' .oO0'):2}" == "0 "
+ assert f"{Bar(0.5, charset=' .oO0'):2a}" == "# "
+ assert f"{Bar(0.5, 10):-6a}" == '## '
+ assert f"{Bar(0.5, 10):2b}" == ' '
def test_all_defaults():
@@ -401,7 +390,7 @@ def test_iterate_over_csv_rows():
# Create a test csv pseudo file
with closing(StringIO()) as test_csv_file:
writer = csv.writer(test_csv_file)
- for _ in _range(3):
+ for _ in range(3):
writer.writerow(['test'] * 3)
test_csv_file.seek(0)
@@ -415,7 +404,7 @@ def test_iterate_over_csv_rows():
def test_file_output():
"""Test output to arbitrary file-like objects"""
with closing(StringIO()) as our_file:
- for i in tqdm(_range(3), file=our_file):
+ for i in tqdm(range(3), file=our_file):
if i == 1:
our_file.seek(0)
assert '0/3' in our_file.read()
@@ -424,14 +413,14 @@ def test_file_output():
def test_leave_option():
"""Test `leave=True` always prints info about the last iteration"""
with closing(StringIO()) as our_file:
- for _ in tqdm(_range(3), file=our_file, leave=True):
+ for _ in tqdm(range(3), file=our_file, leave=True):
pass
res = our_file.getvalue()
assert '| 3/3 ' in res
assert '\n' == res[-1] # not '\r'
with closing(StringIO()) as our_file2:
- for _ in tqdm(_range(3), file=our_file2, leave=False):
+ for _ in tqdm(range(3), file=our_file2, leave=False):
pass
assert '| 3/3 ' not in our_file2.getvalue()
@@ -452,7 +441,7 @@ def test_trange():
def test_min_interval():
"""Test mininterval"""
with closing(StringIO()) as our_file:
- for _ in tqdm(_range(3), file=our_file, mininterval=1e-10):
+ for _ in tqdm(range(3), file=our_file, mininterval=1e-10):
pass
assert " 0%| | 0/3 [00:00<" in our_file.getvalue()
@@ -484,7 +473,7 @@ def test_max_interval():
t.update(bigstep)
t2.update(bigstep)
# The next iterations should not trigger maxinterval (step 10)
- for _ in _range(4):
+ for _ in range(4):
t.update(smallstep)
t2.update(smallstep)
timer.sleep(1e-5)
@@ -504,7 +493,7 @@ def test_max_interval():
# Increase 10 iterations at once
t.update(bigstep)
# The next iterations should trigger maxinterval (step 5)
- for _ in _range(4):
+ for _ in range(4):
t.update(smallstep)
timer.sleep(1e-2)
@@ -513,7 +502,7 @@ def test_max_interval():
# Test iteration based tqdm with maxinterval effect
timer = DiscreteTimer()
with closing(StringIO()) as our_file:
- with tqdm(_range(total), file=our_file, miniters=None,
+ with tqdm(range(total), file=our_file, miniters=None,
mininterval=1e-5, smoothing=1, maxinterval=1e-4) as t2:
cpu_timify(t2, timer)
@@ -560,9 +549,9 @@ def test_max_interval():
mininterval = 0.1
maxinterval = 10
with closing(StringIO()) as our_file:
- t1 = tqdm(_range(total), file=our_file, miniters=None, smoothing=1,
+ t1 = tqdm(range(total), file=our_file, miniters=None, smoothing=1,
mininterval=mininterval, maxinterval=maxinterval)
- t2 = tqdm(_range(total), file=our_file, miniters=None, smoothing=1,
+ t2 = tqdm(range(total), file=our_file, miniters=None, smoothing=1,
mininterval=0, maxinterval=maxinterval)
cpu_timify(t1, timer1)
@@ -605,7 +594,7 @@ def test_delay():
def test_min_iters():
"""Test miniters"""
with closing(StringIO()) as our_file:
- for _ in tqdm(_range(3), file=our_file, leave=True, mininterval=0, miniters=2):
+ for _ in tqdm(range(3), file=our_file, leave=True, mininterval=0, miniters=2):
pass
out = our_file.getvalue()
@@ -615,7 +604,7 @@ def test_min_iters():
assert '| 3/3 ' in out
with closing(StringIO()) as our_file:
- for _ in tqdm(_range(3), file=our_file, leave=True, mininterval=0, miniters=1):
+ for _ in tqdm(range(3), file=our_file, leave=True, mininterval=0, miniters=1):
pass
out = our_file.getvalue()
@@ -669,7 +658,7 @@ def test_dynamic_min_iters():
# Check iterable based tqdm
with closing(StringIO()) as our_file:
- t = tqdm(_range(10), file=our_file, miniters=None, mininterval=None,
+ t = tqdm(range(10), file=our_file, miniters=None, mininterval=None,
smoothing=0.5)
for _ in t:
pass
@@ -677,7 +666,7 @@ def test_dynamic_min_iters():
# No smoothing
with closing(StringIO()) as our_file:
- t = tqdm(_range(10), file=our_file, miniters=None, mininterval=None,
+ t = tqdm(range(10), file=our_file, miniters=None, mininterval=None,
smoothing=0)
for _ in t:
pass
@@ -685,7 +674,7 @@ def test_dynamic_min_iters():
# No dynamic_miniters (miniters is fixed manually)
with closing(StringIO()) as our_file:
- t = tqdm(_range(10), file=our_file, miniters=1, mininterval=None)
+ t = tqdm(range(10), file=our_file, miniters=1, mininterval=None)
for _ in t:
pass
assert not t.dynamic_miniters
@@ -694,12 +683,12 @@ def test_dynamic_min_iters():
def test_big_min_interval():
"""Test large mininterval"""
with closing(StringIO()) as our_file:
- for _ in tqdm(_range(2), file=our_file, mininterval=1E10):
+ for _ in tqdm(range(2), file=our_file, mininterval=1E10):
pass
assert '50%' not in our_file.getvalue()
with closing(StringIO()) as our_file:
- with tqdm(_range(2), file=our_file, mininterval=1E10) as t:
+ with tqdm(range(2), file=our_file, mininterval=1E10) as t:
t.update()
t.update()
assert '50%' not in our_file.getvalue()
@@ -718,10 +707,10 @@ def test_smoothed_dynamic_min_iters():
timer.sleep(1)
t.update(10)
# The next iterations should be partially skipped
- for _ in _range(2):
+ for _ in range(2):
timer.sleep(1)
t.update(4)
- for _ in _range(20):
+ for _ in range(20):
timer.sleep(1)
t.update()
@@ -750,7 +739,7 @@ def test_smoothed_dynamic_min_iters_with_min_interval():
t.update(10)
timer.sleep(1e-2)
- for _ in _range(4):
+ for _ in range(4):
t.update()
timer.sleep(1e-2)
out = our_file.getvalue()
@@ -758,7 +747,7 @@ def test_smoothed_dynamic_min_iters_with_min_interval():
with closing(StringIO()) as our_file:
# Test iteration-based tqdm
- with tqdm(_range(total), file=our_file, miniters=None,
+ with tqdm(range(total), file=our_file, miniters=None,
mininterval=0.01, smoothing=1, maxinterval=0) as t2:
cpu_timify(t2, timer)
@@ -817,7 +806,7 @@ def _rlock_creation_target():
def test_disable():
"""Test disable"""
with closing(StringIO()) as our_file:
- for _ in tqdm(_range(3), file=our_file, disable=True):
+ for _ in tqdm(range(3), file=our_file, disable=True):
pass
assert our_file.getvalue() == ''
@@ -831,7 +820,7 @@ def test_disable():
def test_infinite_total():
"""Test treatment of infinite total"""
with closing(StringIO()) as our_file:
- for _ in tqdm(_range(3), file=our_file, total=float("inf")):
+ for _ in tqdm(range(3), file=our_file, total=float("inf")):
pass
@@ -852,7 +841,7 @@ def test_nototal():
def test_unit():
"""Test SI unit prefix"""
with closing(StringIO()) as our_file:
- for _ in tqdm(_range(3), file=our_file, miniters=1, unit="bytes"):
+ for _ in tqdm(range(3), file=our_file, miniters=1, unit="bytes"):
pass
assert 'bytes/s' in our_file.getvalue()
@@ -866,7 +855,7 @@ def test_ascii():
# Test ascii bar
with closing(StringIO()) as our_file:
- for _ in tqdm(_range(3), total=15, file=our_file, miniters=1,
+ for _ in tqdm(range(3), total=15, file=our_file, miniters=1,
mininterval=0, ascii=True):
pass
res = our_file.getvalue().strip("\r").split("\r")
@@ -877,7 +866,7 @@ def test_ascii():
# Test unicode bar
with closing(UnicodeIO()) as our_file:
with tqdm(total=15, file=our_file, ascii=False, mininterval=0) as t:
- for _ in _range(3):
+ for _ in range(3):
t.update()
res = our_file.getvalue().strip("\r").split("\r")
assert u"7%|\u258b" in res[1]
@@ -887,7 +876,7 @@ def test_ascii():
# Test custom bar
for bars in [" .oO0", " #"]:
with closing(StringIO()) as our_file:
- for _ in tqdm(_range(len(bars) - 1), file=our_file, miniters=1,
+ for _ in tqdm(range(len(bars) - 1), file=our_file, miniters=1,
mininterval=0, ascii=bars, ncols=27):
pass
res = our_file.getvalue().strip("\r").split("\r")
@@ -949,8 +938,7 @@ def test_close():
res = our_file.getvalue()
assert res[-1] == '\n'
if not res.startswith(exres):
- raise AssertionError("\n<<< Expected:\n{0}\n>>> Got:\n{1}\n===".format(
- exres + ', ...it/s]\n', our_file.getvalue()))
+ raise AssertionError(f"\n<<< Expected:\n{exres}, ...it/s]\n>>> Got:\n{res}\n===")
# Closing after the output stream has closed
with closing(StringIO()) as our_file:
@@ -976,7 +964,7 @@ def test_smoothing():
# -- Test disabling smoothing
with closing(StringIO()) as our_file:
- with tqdm(_range(3), file=our_file, smoothing=None, leave=True) as t:
+ with tqdm(range(3), file=our_file, smoothing=None, leave=True) as t:
cpu_timify(t, timer)
for _ in t:
@@ -987,11 +975,11 @@ def test_smoothing():
# 1st case: no smoothing (only use average)
with closing(StringIO()) as our_file2:
with closing(StringIO()) as our_file:
- t = tqdm(_range(3), file=our_file2, smoothing=None, leave=True,
+ t = tqdm(range(3), file=our_file2, smoothing=None, leave=True,
miniters=1, mininterval=0)
cpu_timify(t, timer)
- with tqdm(_range(3), file=our_file, smoothing=None, leave=True,
+ with tqdm(range(3), file=our_file, smoothing=None, leave=True,
miniters=1, mininterval=0) as t2:
cpu_timify(t2, timer)
@@ -1017,11 +1005,11 @@ def test_smoothing():
# 2nd case: use max smoothing (= instant rate)
with closing(StringIO()) as our_file2:
with closing(StringIO()) as our_file:
- t = tqdm(_range(3), file=our_file2, smoothing=1, leave=True,
+ t = tqdm(range(3), file=our_file2, smoothing=1, leave=True,
miniters=1, mininterval=0)
cpu_timify(t, timer)
- with tqdm(_range(3), file=our_file, smoothing=1, leave=True,
+ with tqdm(range(3), file=our_file, smoothing=1, leave=True,
miniters=1, mininterval=0) as t2:
cpu_timify(t2, timer)
@@ -1040,11 +1028,11 @@ def test_smoothing():
# 3rd case: use medium smoothing
with closing(StringIO()) as our_file2:
with closing(StringIO()) as our_file:
- t = tqdm(_range(3), file=our_file2, smoothing=0.5, leave=True,
+ t = tqdm(range(3), file=our_file2, smoothing=0.5, leave=True,
miniters=1, mininterval=0)
cpu_timify(t, timer)
- t2 = tqdm(_range(3), file=our_file, smoothing=0.5, leave=True,
+ t2 = tqdm(range(3), file=our_file, smoothing=0.5, leave=True,
miniters=1, mininterval=0)
cpu_timify(t2, timer)
@@ -1098,7 +1086,7 @@ def test_bar_format():
with closing(StringIO()) as our_file:
bar_format = r'hello world'
with tqdm(ascii=False, bar_format=bar_format, file=our_file) as t:
- assert isinstance(t.bar_format, _unicode)
+ assert isinstance(t.bar_format, str)
def test_custom_format():
@@ -1127,7 +1115,7 @@ def test_eta(capsys):
bar_format='{l_bar}{eta:%Y-%m-%d}'):
pass
_, err = capsys.readouterr()
- assert "\r100%|{eta:%Y-%m-%d}\n".format(eta=dt.now()) in err
+ assert f"\r100%|{dt.now():%Y-%m-%d}\n" in err
def test_unpause():
@@ -1257,7 +1245,7 @@ def test_position():
t1 = tqdm(desc='pos0 bar', position=0, **kwargs)
t2 = tqdm(desc='pos1 bar', position=1, **kwargs)
t3 = tqdm(desc='pos2 bar', position=2, **kwargs)
- for _ in _range(2):
+ for _ in range(2):
t1.update()
t3.update()
t2.update()
@@ -1360,7 +1348,7 @@ def test_deprecated_gui():
# t.close()
# len(tqdm._instances) += 1 # undo the close() decrement
- t = tqdm(_range(3), gui=True, file=our_file, miniters=1, mininterval=0)
+ t = tqdm(range(3), gui=True, file=our_file, miniters=1, mininterval=0)
try:
for _ in t:
pass
@@ -1735,7 +1723,7 @@ def test_external_write():
def test_unit_scale():
"""Test numeric `unit_scale`"""
with closing(StringIO()) as our_file:
- for _ in tqdm(_range(9), unit_scale=9, file=our_file,
+ for _ in tqdm(range(9), unit_scale=9, file=our_file,
miniters=1, mininterval=0):
pass
out = our_file.getvalue()
@@ -1937,7 +1925,7 @@ def test_screen_shape():
def test_initial():
"""Test `initial`"""
with closing(StringIO()) as our_file:
- for _ in tqdm(_range(9), initial=10, total=19, file=our_file,
+ for _ in tqdm(range(9), initial=10, total=19, file=our_file,
miniters=1, mininterval=0):
pass
out = our_file.getvalue()
@@ -1948,7 +1936,7 @@ def test_initial():
def test_colour():
"""Test `colour`"""
with closing(StringIO()) as our_file:
- for _ in tqdm(_range(9), file=our_file, colour="#beefed"):
+ for _ in tqdm(range(9), file=our_file, colour="#beefed"):
pass
out = our_file.getvalue()
assert '\x1b[38;2;%d;%d;%dm' % (0xbe, 0xef, 0xed) in out
@@ -1961,7 +1949,7 @@ def test_colour():
assert "Unknown colour" in str(w[-1].message)
with closing(StringIO()) as our_file2:
- for _ in tqdm(_range(9), file=our_file2, colour="blue"):
+ for _ in tqdm(range(9), file=our_file2, colour="blue"):
pass
out = our_file2.getvalue()
assert '\x1b[34m' in out
@@ -1977,7 +1965,7 @@ def test_closed():
def test_reversed(capsys):
"""Test reversed()"""
- for _ in reversed(tqdm(_range(9))):
+ for _ in reversed(tqdm(range(9))):
pass
out, err = capsys.readouterr()
assert not out
@@ -1989,7 +1977,7 @@ def test_contains(capsys):
"""Test __contains__ doesn't iterate"""
with tqdm(list(range(9))) as t:
assert 9 not in t
- assert all(i in t for i in _range(9))
+ assert all(i in t for i in range(9))
out, err = capsys.readouterr()
assert not out
assert ' 0%' in err
diff --git a/tests/tests_utils.py b/tests/tests_utils.py
new file mode 100644
index 0000000..6cf1e6c
--- /dev/null
+++ b/tests/tests_utils.py
@@ -0,0 +1,51 @@
+from ast import literal_eval
+from collections import defaultdict
+from typing import Union # py<3.10
+
+from tqdm.utils import envwrap
+
+
+def test_envwrap(monkeypatch):
+ """Test @envwrap (basic)"""
+ monkeypatch.setenv('FUNC_A', "42")
+ monkeypatch.setenv('FUNC_TyPe_HiNt', "1337")
+ monkeypatch.setenv('FUNC_Unused', "x")
+
+ @envwrap("FUNC_")
+ def func(a=1, b=2, type_hint: int = None):
+ return a, b, type_hint
+
+ assert (42, 2, 1337) == func()
+ assert (99, 2, 1337) == func(a=99)
+
+
+def test_envwrap_types(monkeypatch):
+ """Test @envwrap(types)"""
+ monkeypatch.setenv('FUNC_notype', "3.14159")
+
+ @envwrap("FUNC_", types=defaultdict(lambda: literal_eval))
+ def func(notype=None):
+ return notype
+
+ assert 3.14159 == func()
+
+ monkeypatch.setenv('FUNC_number', "1")
+ monkeypatch.setenv('FUNC_string', "1")
+
+ @envwrap("FUNC_", types={'number': int})
+ def nofallback(number=None, string=None):
+ return number, string
+
+ assert 1, "1" == nofallback()
+
+
+def test_envwrap_annotations(monkeypatch):
+ """Test @envwrap with typehints"""
+ monkeypatch.setenv('FUNC_number', "1.1")
+ monkeypatch.setenv('FUNC_string', "1.1")
+
+ @envwrap("FUNC_")
+ def annotated(number: Union[int, float] = None, string: int = None):
+ return number, string
+
+ assert 1.1, "1.1" == annotated()
diff --git a/tox.ini b/tox.ini
index d77a5a8..cd5dc1b 100644
--- a/tox.ini
+++ b/tox.ini
@@ -4,20 +4,16 @@
# and then run "tox" from this directory.
[tox]
-# deprecation warning: py{27,py2,34,35,36}
-envlist=py{27,34,35,36,37,38,39,310,py2,py3}{,-tf}{,-keras}, perf, setup.py
+envlist=py{37,38,39,310,311,py3}{,-tf}{,-keras}, perf, check
isolated_build=True
[gh-actions]
python=
- 2.7: py27
- 3.5: py35
- 3.6: py36
3.7: py37
3.8: py38
3.9: py39
3.10: py310
- pypy-2.7: pypy2
+ 3.11: py311
pypy-3.7: pypy3
[gh-actions:env]
PLATFORM=
@@ -26,12 +22,11 @@ PLATFORM=
[core]
deps=
pytest
- py3{4,5,6}: pytest<7
pytest-cov
pytest-timeout
- py3{7,8,9,10}: pytest-asyncio
- py3{6,7,8,9,10}: ipywidgets
- py3{7,8,9,10}: git+https://github.com/casperdcl/nbval.git@master#egg=nbval
+ pytest-asyncio
+ ipywidgets
+ git+https://github.com/casperdcl/nbval.git@master#egg=nbval
coverage
coveralls
codecov
@@ -41,7 +36,7 @@ commands=
- codacy report -l Python -r coverage.xml --partial
[testenv]
-passenv=TOXENV CI GITHUB_* CODECOV_* COVERALLS_* CODACY_* HOME
+passenv=TOXENV,CI,GITHUB_*,CODECOV_*,COVERALLS_*,CODACY_*,HOME
deps=
{[core]deps}
cython
@@ -49,26 +44,17 @@ deps=
matplotlib
numpy
pandas
+ rich
tf: tensorflow!=2.5.0
- !py27-keras: keras
- py27-keras: keras<2.5
- py35-keras: keras<2.7
- py27-tf: protobuf<3.18
- py3{6,7,8,9,10}: rich
+ keras: keras
commands=
- py3{4,5,6}: pytest --cov=tqdm --cov-report=xml --cov-report=term -k "not perf" -o addopts= -v --tb=short -rxs -W=error --durations=0 --durations-min=0.1
- py3{7,8,9,10}: pytest --cov=tqdm --cov-report= tests_notebook.ipynb --nbval --nbval-current-env -W=ignore --nbval-sanitize-with=setup.cfg
- py3{7,8,9,10}: pytest --cov=tqdm --cov-report=xml --cov-report=term --cov-append -k "not perf"
+ pytest --cov=tqdm --cov-report= -W=ignore tests_notebook.ipynb --nbval --current-env --sanitize-with=.meta/nbval.ini
+ pytest --cov=tqdm --cov-report=xml --cov-report=term --cov-append -k "not perf"
{[core]commands}
allowlist_externals=codacy
-[testenv:py{27,py2}{,-tf}{,-keras}]
-commands=
- pytest --cov=tqdm --cov-report=xml --cov-report=term -k "not perf" -o addopts= -v --tb=short -rxs -W=error --durations=10
- {[core]commands}
-
# no cython/numpy/pandas
-[testenv:py{34,py2,py3}]
+[testenv:pypy3]
deps={[core]deps}
[testenv:perf]
@@ -78,11 +64,12 @@ deps=
pytest-asyncio
commands=pytest -k perf
-[testenv:setup.py]
+[testenv:check]
deps=
- docutils
- pygments
+ build
+ twine
py-make>=0.1.0
commands=
- {envpython} setup.py check --restructuredtext --metadata --strict
- {envpython} setup.py make none
+ {envpython} -m build
+ {envpython} -m twine check dist/*
+ {envpython} -m pymake -h
diff --git a/tqdm.egg-info/PKG-INFO b/tqdm.egg-info/PKG-INFO
deleted file mode 100644
index d796709..0000000
--- a/tqdm.egg-info/PKG-INFO
+++ /dev/null
@@ -1,1581 +0,0 @@
-Metadata-Version: 2.1
-Name: tqdm
-Version: 4.64.1
-Summary: Fast, Extensible Progress Meter
-Home-page: https://tqdm.github.io
-Maintainer: tqdm developers
-Maintainer-email: python.tqdm@gmail.com
-License: MPLv2.0, MIT Licences
-Project-URL: Changelog, https://tqdm.github.io/releases
-Project-URL: Source, https://github.com/tqdm/tqdm
-Project-URL: Wiki, https://github.com/tqdm/tqdm/wiki
-Keywords: progressbar,progressmeter,progress,bar,meter,rate,eta,console,terminal,time
-Platform: any
-Classifier: Development Status :: 5 - Production/Stable
-Classifier: Environment :: Console
-Classifier: Environment :: MacOS X
-Classifier: Environment :: Other Environment
-Classifier: Environment :: Win32 (MS Windows)
-Classifier: Environment :: X11 Applications
-Classifier: Framework :: IPython
-Classifier: Framework :: Jupyter
-Classifier: Intended Audience :: Developers
-Classifier: Intended Audience :: Education
-Classifier: Intended Audience :: End Users/Desktop
-Classifier: Intended Audience :: Other Audience
-Classifier: Intended Audience :: System Administrators
-Classifier: License :: OSI Approved :: MIT License
-Classifier: License :: OSI Approved :: Mozilla Public License 2.0 (MPL 2.0)
-Classifier: Operating System :: MacOS
-Classifier: Operating System :: MacOS :: MacOS X
-Classifier: Operating System :: Microsoft
-Classifier: Operating System :: Microsoft :: MS-DOS
-Classifier: Operating System :: Microsoft :: Windows
-Classifier: Operating System :: POSIX
-Classifier: Operating System :: POSIX :: BSD
-Classifier: Operating System :: POSIX :: BSD :: FreeBSD
-Classifier: Operating System :: POSIX :: Linux
-Classifier: Operating System :: POSIX :: SunOS/Solaris
-Classifier: Operating System :: Unix
-Classifier: Programming Language :: Python
-Classifier: Programming Language :: Python :: 2
-Classifier: Programming Language :: Python :: 2.7
-Classifier: Programming Language :: Python :: 3
-Classifier: Programming Language :: Python :: 3.5
-Classifier: Programming Language :: Python :: 3.6
-Classifier: Programming Language :: Python :: 3.7
-Classifier: Programming Language :: Python :: 3.8
-Classifier: Programming Language :: Python :: 3.9
-Classifier: Programming Language :: Python :: 3.10
-Classifier: Programming Language :: Python :: Implementation
-Classifier: Programming Language :: Python :: Implementation :: IronPython
-Classifier: Programming Language :: Python :: Implementation :: PyPy
-Classifier: Programming Language :: Unix Shell
-Classifier: Topic :: Desktop Environment
-Classifier: Topic :: Education :: Computer Aided Instruction (CAI)
-Classifier: Topic :: Education :: Testing
-Classifier: Topic :: Office/Business
-Classifier: Topic :: Other/Nonlisted Topic
-Classifier: Topic :: Software Development :: Build Tools
-Classifier: Topic :: Software Development :: Libraries
-Classifier: Topic :: Software Development :: Libraries :: Python Modules
-Classifier: Topic :: Software Development :: Pre-processors
-Classifier: Topic :: Software Development :: User Interfaces
-Classifier: Topic :: System :: Installation/Setup
-Classifier: Topic :: System :: Logging
-Classifier: Topic :: System :: Monitoring
-Classifier: Topic :: System :: Shells
-Classifier: Topic :: Terminals
-Classifier: Topic :: Utilities
-Provides: tqdm
-Requires-Python: !=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,>=2.7
-Description-Content-Type: text/x-rst
-Provides-Extra: dev
-Provides-Extra: slack
-Provides-Extra: telegram
-Provides-Extra: notebook
-License-File: LICENCE
-
-|Logo|
-
-tqdm
-====
-
-|Py-Versions| |Versions| |Conda-Forge-Status| |Docker| |Snapcraft|
-
-|Build-Status| |Coverage-Status| |Branch-Coverage-Status| |Codacy-Grade| |Libraries-Rank| |PyPI-Downloads|
-
-|LICENCE| |OpenHub-Status| |binder-demo| |awesome-python|
-
-``tqdm`` derives from the Arabic word *taqaddum* (تقدّم) which can mean "progress,"
-and is an abbreviation for "I love you so much" in Spanish (*te quiero demasiado*).
-
-Instantly make your loops show a smart progress meter - just wrap any
-iterable with ``tqdm(iterable)``, and you're done!
-
-.. code:: python
-
- from tqdm import tqdm
- for i in tqdm(range(10000)):
- ...
-
-``76%|████████████████████████        | 7568/10000 [00:33<00:10, 229.00it/s]``
-
-``trange(N)`` can be also used as a convenient shortcut for
-``tqdm(range(N))``.
-
-|Screenshot|
- |Video| |Slides| |Merch|
-
-It can also be executed as a module with pipes:
-
-.. code:: sh
-
- $ seq 9999999 | tqdm --bytes | wc -l
- 75.2MB [00:00, 217MB/s]
- 9999999
-
- $ tar -zcf - docs/ | tqdm --bytes --total `du -sb docs/ | cut -f1` \
- > backup.tgz
- 32%|██████████▍ | 8.89G/27.9G [00:42<01:31, 223MB/s]
-
-Overhead is low -- about 60ns per iteration (80ns with ``tqdm.gui``), and is
-unit tested against performance regression.
-By comparison, the well-established
-`ProgressBar <https://github.com/niltonvolpato/python-progressbar>`__ has
-an 800ns/iter overhead.
-
-In addition to its low overhead, ``tqdm`` uses smart algorithms to predict
-the remaining time and to skip unnecessary iteration displays, which allows
-for a negligible overhead in most cases.
-
-``tqdm`` works on any platform
-(Linux, Windows, Mac, FreeBSD, NetBSD, Solaris/SunOS),
-in any console or in a GUI, and is also friendly with IPython/Jupyter notebooks.
-
-``tqdm`` does not require any dependencies (not even ``curses``!), just
-Python and an environment supporting ``carriage return \r`` and
-``line feed \n`` control characters.
-
-------------------------------------------
-
-.. contents:: Table of contents
- :backlinks: top
- :local:
-
-
-Installation
-------------
-
-Latest PyPI stable release
-~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-|Versions| |PyPI-Downloads| |Libraries-Dependents|
-
-.. code:: sh
-
- pip install tqdm
-
-Latest development release on GitHub
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-|GitHub-Status| |GitHub-Stars| |GitHub-Commits| |GitHub-Forks| |GitHub-Updated|
-
-Pull and install pre-release ``devel`` branch:
-
-.. code:: sh
-
- pip install "git+https://github.com/tqdm/tqdm.git@devel#egg=tqdm"
-
-Latest Conda release
-~~~~~~~~~~~~~~~~~~~~
-
-|Conda-Forge-Status|
-
-.. code:: sh
-
- conda install -c conda-forge tqdm
-
-Latest Snapcraft release
-~~~~~~~~~~~~~~~~~~~~~~~~
-
-|Snapcraft|
-
-There are 3 channels to choose from:
-
-.. code:: sh
-
- snap install tqdm # implies --stable, i.e. latest tagged release
- snap install tqdm --candidate # master branch
- snap install tqdm --edge # devel branch
-
-Note that ``snap`` binaries are purely for CLI use (not ``import``-able), and
-automatically set up ``bash`` tab-completion.
-
-Latest Docker release
-~~~~~~~~~~~~~~~~~~~~~
-
-|Docker|
-
-.. code:: sh
-
- docker pull tqdm/tqdm
- docker run -i --rm tqdm/tqdm --help
-
-Other
-~~~~~
-
-There are other (unofficial) places where ``tqdm`` may be downloaded, particularly for CLI use:
-
-|Repology|
-
-.. |Repology| image:: https://repology.org/badge/tiny-repos/python:tqdm.svg
- :target: https://repology.org/project/python:tqdm/versions
-
-Changelog
----------
-
-The list of all changes is available either on GitHub's Releases:
-|GitHub-Status|, on the
-`wiki <https://github.com/tqdm/tqdm/wiki/Releases>`__, or on the
-`website <https://tqdm.github.io/releases>`__.
-
-
-Usage
------
-
-``tqdm`` is very versatile and can be used in a number of ways.
-The three main ones are given below.
-
-Iterable-based
-~~~~~~~~~~~~~~
-
-Wrap ``tqdm()`` around any iterable:
-
-.. code:: python
-
- from tqdm import tqdm
- from time import sleep
-
- text = ""
- for char in tqdm(["a", "b", "c", "d"]):
- sleep(0.25)
- text = text + char
-
-``trange(i)`` is a special optimised instance of ``tqdm(range(i))``:
-
-.. code:: python
-
- from tqdm import trange
-
- for i in trange(100):
- sleep(0.01)
-
-Instantiation outside of the loop allows for manual control over ``tqdm()``:
-
-.. code:: python
-
- pbar = tqdm(["a", "b", "c", "d"])
- for char in pbar:
- sleep(0.25)
- pbar.set_description("Processing %s" % char)
-
-Manual
-~~~~~~
-
-Manual control of ``tqdm()`` updates using a ``with`` statement:
-
-.. code:: python
-
- with tqdm(total=100) as pbar:
- for i in range(10):
- sleep(0.1)
- pbar.update(10)
-
-If the optional variable ``total`` (or an iterable with ``len()``) is
-provided, predictive stats are displayed.
-
-``with`` is also optional (you can just assign ``tqdm()`` to a variable,
-but in this case don't forget to ``del`` or ``close()`` at the end:
-
-.. code:: python
-
- pbar = tqdm(total=100)
- for i in range(10):
- sleep(0.1)
- pbar.update(10)
- pbar.close()
-
-Module
-~~~~~~
-
-Perhaps the most wonderful use of ``tqdm`` is in a script or on the command
-line. Simply inserting ``tqdm`` (or ``python -m tqdm``) between pipes will pass
-through all ``stdin`` to ``stdout`` while printing progress to ``stderr``.
-
-The example below demonstrate counting the number of lines in all Python files
-in the current directory, with timing information included.
-
-.. code:: sh
-
- $ time find . -name '*.py' -type f -exec cat \{} \; | wc -l
- 857365
-
- real 0m3.458s
- user 0m0.274s
- sys 0m3.325s
-
- $ time find . -name '*.py' -type f -exec cat \{} \; | tqdm | wc -l
- 857366it [00:03, 246471.31it/s]
- 857365
-
- real 0m3.585s
- user 0m0.862s
- sys 0m3.358s
-
-Note that the usual arguments for ``tqdm`` can also be specified.
-
-.. code:: sh
-
- $ find . -name '*.py' -type f -exec cat \{} \; |
- tqdm --unit loc --unit_scale --total 857366 >> /dev/null
- 100%|█████████████████████████████████| 857K/857K [00:04<00:00, 246Kloc/s]
-
-Backing up a large directory?
-
-.. code:: sh
-
- $ tar -zcf - docs/ | tqdm --bytes --total `du -sb docs/ | cut -f1` \
- > backup.tgz
- 44%|██████████████▊ | 153M/352M [00:14<00:18, 11.0MB/s]
-
-This can be beautified further:
-
-.. code:: sh
-
- $ BYTES="$(du -sb docs/ | cut -f1)"
- $ tar -cf - docs/ \
- | tqdm --bytes --total "$BYTES" --desc Processing | gzip \
- | tqdm --bytes --total "$BYTES" --desc Compressed --position 1 \
- > ~/backup.tgz
- Processing: 100%|██████████████████████| 352M/352M [00:14<00:00, 30.2MB/s]
- Compressed: 42%|█████████▎ | 148M/352M [00:14<00:19, 10.9MB/s]
-
-Or done on a file level using 7-zip:
-
-.. code:: sh
-
- $ 7z a -bd -r backup.7z docs/ | grep Compressing \
- | tqdm --total $(find docs/ -type f | wc -l) --unit files \
- | grep -v Compressing
- 100%|██████████████████████████▉| 15327/15327 [01:00<00:00, 712.96files/s]
-
-Pre-existing CLI programs already outputting basic progress information will
-benefit from ``tqdm``'s ``--update`` and ``--update_to`` flags:
-
-.. code:: sh
-
- $ seq 3 0.1 5 | tqdm --total 5 --update_to --null
- 100%|████████████████████████████████████| 5.0/5 [00:00<00:00, 9673.21it/s]
- $ seq 10 | tqdm --update --null # 1 + 2 + ... + 10 = 55 iterations
- 55it [00:00, 90006.52it/s]
-
-FAQ and Known Issues
---------------------
-
-|GitHub-Issues|
-
-The most common issues relate to excessive output on multiple lines, instead
-of a neat one-line progress bar.
-
-- Consoles in general: require support for carriage return (``CR``, ``\r``).
-- Nested progress bars:
-
- * Consoles in general: require support for moving cursors up to the
- previous line. For example,
- `IDLE <https://github.com/tqdm/tqdm/issues/191#issuecomment-230168030>`__,
- `ConEmu <https://github.com/tqdm/tqdm/issues/254>`__ and
- `PyCharm <https://github.com/tqdm/tqdm/issues/203>`__ (also
- `here <https://github.com/tqdm/tqdm/issues/208>`__,
- `here <https://github.com/tqdm/tqdm/issues/307>`__, and
- `here <https://github.com/tqdm/tqdm/issues/454#issuecomment-335416815>`__)
- lack full support.
- * Windows: additionally may require the Python module ``colorama``
- to ensure nested bars stay within their respective lines.
-
-- Unicode:
-
- * Environments which report that they support unicode will have solid smooth
- progressbars. The fallback is an ``ascii``-only bar.
- * Windows consoles often only partially support unicode and thus
- `often require explicit ascii=True <https://github.com/tqdm/tqdm/issues/454#issuecomment-335416815>`__
- (also `here <https://github.com/tqdm/tqdm/issues/499>`__). This is due to
- either normal-width unicode characters being incorrectly displayed as
- "wide", or some unicode characters not rendering.
-
-- Wrapping generators:
-
- * Generator wrapper functions tend to hide the length of iterables.
- ``tqdm`` does not.
- * Replace ``tqdm(enumerate(...))`` with ``enumerate(tqdm(...))`` or
- ``tqdm(enumerate(x), total=len(x), ...)``.
- The same applies to ``numpy.ndenumerate``.
- * Replace ``tqdm(zip(a, b))`` with ``zip(tqdm(a), b)`` or even
- ``zip(tqdm(a), tqdm(b))``.
- * The same applies to ``itertools``.
- * Some useful convenience functions can be found under ``tqdm.contrib``.
-
-- `Hanging pipes in python2 <https://github.com/tqdm/tqdm/issues/359>`__:
- when using ``tqdm`` on the CLI, you may need to use Python 3.5+ for correct
- buffering.
-- `No intermediate output in docker-compose <https://github.com/tqdm/tqdm/issues/771>`__:
- use ``docker-compose run`` instead of ``docker-compose up`` and ``tty: true``.
-
-If you come across any other difficulties, browse and file |GitHub-Issues|.
-
-Documentation
--------------
-
-|Py-Versions| |README-Hits| (Since 19 May 2016)
-
-.. code:: python
-
- class tqdm():
- """
- Decorate an iterable object, returning an iterator which acts exactly
- like the original iterable, but prints a dynamically updating
- progressbar every time a value is requested.
- """
-
- def __init__(self, iterable=None, desc=None, total=None, leave=True,
- file=None, ncols=None, mininterval=0.1,
- maxinterval=10.0, miniters=None, ascii=None, disable=False,
- unit='it', unit_scale=False, dynamic_ncols=False,
- smoothing=0.3, bar_format=None, initial=0, position=None,
- postfix=None, unit_divisor=1000):
-
-Parameters
-~~~~~~~~~~
-
-* iterable : iterable, optional
- Iterable to decorate with a progressbar.
- Leave blank to manually manage the updates.
-* desc : str, optional
- Prefix for the progressbar.
-* total : int or float, optional
- The number of expected iterations. If unspecified,
- len(iterable) is used if possible. If float("inf") or as a last
- resort, only basic progress statistics are displayed
- (no ETA, no progressbar).
- If ``gui`` is True and this parameter needs subsequent updating,
- specify an initial arbitrary large positive number,
- e.g. 9e9.
-* leave : bool, optional
- If [default: True], keeps all traces of the progressbar
- upon termination of iteration.
- If ``None``, will leave only if ``position`` is ``0``.
-* file : ``io.TextIOWrapper`` or ``io.StringIO``, optional
- Specifies where to output the progress messages
- (default: sys.stderr). Uses ``file.write(str)`` and ``file.flush()``
- methods. For encoding, see ``write_bytes``.
-* ncols : int, optional
- The width of the entire output message. If specified,
- dynamically resizes the progressbar to stay within this bound.
- If unspecified, attempts to use environment width. The
- fallback is a meter width of 10 and no limit for the counter and
- statistics. If 0, will not print any meter (only stats).
-* mininterval : float, optional
- Minimum progress display update interval [default: 0.1] seconds.
-* maxinterval : float, optional
- Maximum progress display update interval [default: 10] seconds.
- Automatically adjusts ``miniters`` to correspond to ``mininterval``
- after long display update lag. Only works if ``dynamic_miniters``
- or monitor thread is enabled.
-* miniters : int or float, optional
- Minimum progress display update interval, in iterations.
- If 0 and ``dynamic_miniters``, will automatically adjust to equal
- ``mininterval`` (more CPU efficient, good for tight loops).
- If > 0, will skip display of specified number of iterations.
- Tweak this and ``mininterval`` to get very efficient loops.
- If your progress is erratic with both fast and slow iterations
- (network, skipping items, etc) you should set miniters=1.
-* ascii : bool or str, optional
- If unspecified or False, use unicode (smooth blocks) to fill
- the meter. The fallback is to use ASCII characters " 123456789#".
-* disable : bool, optional
- Whether to disable the entire progressbar wrapper
- [default: False]. If set to None, disable on non-TTY.
-* unit : str, optional
- String that will be used to define the unit of each iteration
- [default: it].
-* unit_scale : bool or int or float, optional
- If 1 or True, the number of iterations will be reduced/scaled
- automatically and a metric prefix following the
- International System of Units standard will be added
- (kilo, mega, etc.) [default: False]. If any other non-zero
- number, will scale ``total`` and ``n``.
-* dynamic_ncols : bool, optional
- If set, constantly alters ``ncols`` and ``nrows`` to the
- environment (allowing for window resizes) [default: False].
-* smoothing : float, optional
- Exponential moving average smoothing factor for speed estimates
- (ignored in GUI mode). Ranges from 0 (average speed) to 1
- (current/instantaneous speed) [default: 0.3].
-* bar_format : str, optional
- Specify a custom bar string formatting. May impact performance.
- [default: '{l_bar}{bar}{r_bar}'], where
- l_bar='{desc}: {percentage:3.0f}%|' and
- r_bar='| {n_fmt}/{total_fmt} [{elapsed}<{remaining}, '
- '{rate_fmt}{postfix}]'
- Possible vars: l_bar, bar, r_bar, n, n_fmt, total, total_fmt,
- percentage, elapsed, elapsed_s, ncols, nrows, desc, unit,
- rate, rate_fmt, rate_noinv, rate_noinv_fmt,
- rate_inv, rate_inv_fmt, postfix, unit_divisor,
- remaining, remaining_s, eta.
- Note that a trailing ": " is automatically removed after {desc}
- if the latter is empty.
-* initial : int or float, optional
- The initial counter value. Useful when restarting a progress
- bar [default: 0]. If using float, consider specifying ``{n:.3f}``
- or similar in ``bar_format``, or specifying ``unit_scale``.
-* position : int, optional
- Specify the line offset to print this bar (starting from 0)
- Automatic if unspecified.
- Useful to manage multiple bars at once (eg, from threads).
-* postfix : dict or ``*``, optional
- Specify additional stats to display at the end of the bar.
- Calls ``set_postfix(**postfix)`` if possible (dict).
-* unit_divisor : float, optional
- [default: 1000], ignored unless ``unit_scale`` is True.
-* write_bytes : bool, optional
- If (default: None) and ``file`` is unspecified,
- bytes will be written in Python 2. If ``True`` will also write
- bytes. In all other cases will default to unicode.
-* lock_args : tuple, optional
- Passed to ``refresh`` for intermediate output
- (initialisation, iterating, and updating).
-* nrows : int, optional
- The screen height. If specified, hides nested bars outside this
- bound. If unspecified, attempts to use environment height.
- The fallback is 20.
-* colour : str, optional
- Bar colour (e.g. 'green', '#00ff00').
-* delay : float, optional
- Don't display until [default: 0] seconds have elapsed.
-
-Extra CLI Options
-~~~~~~~~~~~~~~~~~
-
-* delim : chr, optional
- Delimiting character [default: '\n']. Use '\0' for null.
- N.B.: on Windows systems, Python converts '\n' to '\r\n'.
-* buf_size : int, optional
- String buffer size in bytes [default: 256]
- used when ``delim`` is specified.
-* bytes : bool, optional
- If true, will count bytes, ignore ``delim``, and default
- ``unit_scale`` to True, ``unit_divisor`` to 1024, and ``unit`` to 'B'.
-* tee : bool, optional
- If true, passes ``stdin`` to both ``stderr`` and ``stdout``.
-* update : bool, optional
- If true, will treat input as newly elapsed iterations,
- i.e. numbers to pass to ``update()``. Note that this is slow
- (~2e5 it/s) since every input must be decoded as a number.
-* update_to : bool, optional
- If true, will treat input as total elapsed iterations,
- i.e. numbers to assign to ``self.n``. Note that this is slow
- (~2e5 it/s) since every input must be decoded as a number.
-* null : bool, optional
- If true, will discard input (no stdout).
-* manpath : str, optional
- Directory in which to install tqdm man pages.
-* comppath : str, optional
- Directory in which to place tqdm completion.
-* log : str, optional
- CRITICAL|FATAL|ERROR|WARN(ING)|[default: 'INFO']|DEBUG|NOTSET.
-
-Returns
-~~~~~~~
-
-* out : decorated iterator.
-
-.. code:: python
-
- class tqdm():
- def update(self, n=1):
- """
- Manually update the progress bar, useful for streams
- such as reading files.
- E.g.:
- >>> t = tqdm(total=filesize) # Initialise
- >>> for current_buffer in stream:
- ... ...
- ... t.update(len(current_buffer))
- >>> t.close()
- The last line is highly recommended, but possibly not necessary if
- ``t.update()`` will be called in such a way that ``filesize`` will be
- exactly reached and printed.
-
- Parameters
- ----------
- n : int or float, optional
- Increment to add to the internal counter of iterations
- [default: 1]. If using float, consider specifying ``{n:.3f}``
- or similar in ``bar_format``, or specifying ``unit_scale``.
-
- Returns
- -------
- out : bool or None
- True if a ``display()`` was triggered.
- """
-
- def close(self):
- """Cleanup and (if leave=False) close the progressbar."""
-
- def clear(self, nomove=False):
- """Clear current bar display."""
-
- def refresh(self):
- """
- Force refresh the display of this bar.
-
- Parameters
- ----------
- nolock : bool, optional
- If ``True``, does not lock.
- If [default: ``False``]: calls ``acquire()`` on internal lock.
- lock_args : tuple, optional
- Passed to internal lock's ``acquire()``.
- If specified, will only ``display()`` if ``acquire()`` returns ``True``.
- """
-
- def unpause(self):
- """Restart tqdm timer from last print time."""
-
- def reset(self, total=None):
- """
- Resets to 0 iterations for repeated use.
-
- Consider combining with ``leave=True``.
-
- Parameters
- ----------
- total : int or float, optional. Total to use for the new bar.
- """
-
- def set_description(self, desc=None, refresh=True):
- """
- Set/modify description of the progress bar.
-
- Parameters
- ----------
- desc : str, optional
- refresh : bool, optional
- Forces refresh [default: True].
- """
-
- def set_postfix(self, ordered_dict=None, refresh=True, **tqdm_kwargs):
- """
- Set/modify postfix (additional stats)
- with automatic formatting based on datatype.
-
- Parameters
- ----------
- ordered_dict : dict or OrderedDict, optional
- refresh : bool, optional
- Forces refresh [default: True].
- kwargs : dict, optional
- """
-
- @classmethod
- def write(cls, s, file=sys.stdout, end="\n"):
- """Print a message via tqdm (without overlap with bars)."""
-
- @property
- def format_dict(self):
- """Public API for read-only member access."""
-
- def display(self, msg=None, pos=None):
- """
- Use ``self.sp`` to display ``msg`` in the specified ``pos``.
-
- Consider overloading this function when inheriting to use e.g.:
- ``self.some_frontend(**self.format_dict)`` instead of ``self.sp``.
-
- Parameters
- ----------
- msg : str, optional. What to display (default: ``repr(self)``).
- pos : int, optional. Position to ``moveto``
- (default: ``abs(self.pos)``).
- """
-
- @classmethod
- @contextmanager
- def wrapattr(cls, stream, method, total=None, bytes=True, **tqdm_kwargs):
- """
- stream : file-like object.
- method : str, "read" or "write". The result of ``read()`` and
- the first argument of ``write()`` should have a ``len()``.
-
- >>> with tqdm.wrapattr(file_obj, "read", total=file_obj.size) as fobj:
- ... while True:
- ... chunk = fobj.read(chunk_size)
- ... if not chunk:
- ... break
- """
-
- @classmethod
- def pandas(cls, *targs, **tqdm_kwargs):
- """Registers the current `tqdm` class with `pandas`."""
-
- def trange(*args, **tqdm_kwargs):
- """
- A shortcut for `tqdm(xrange(*args), **tqdm_kwargs)`.
- On Python3+, `range` is used instead of `xrange`.
- """
-
-Convenience Functions
-~~~~~~~~~~~~~~~~~~~~~
-
-.. code:: python
-
- def tqdm.contrib.tenumerate(iterable, start=0, total=None,
- tqdm_class=tqdm.auto.tqdm, **tqdm_kwargs):
- """Equivalent of `numpy.ndenumerate` or builtin `enumerate`."""
-
- def tqdm.contrib.tzip(iter1, *iter2plus, **tqdm_kwargs):
- """Equivalent of builtin `zip`."""
-
- def tqdm.contrib.tmap(function, *sequences, **tqdm_kwargs):
- """Equivalent of builtin `map`."""
-
-Submodules
-~~~~~~~~~~
-
-.. code:: python
-
- class tqdm.notebook.tqdm(tqdm.tqdm):
- """IPython/Jupyter Notebook widget."""
-
- class tqdm.auto.tqdm(tqdm.tqdm):
- """Automatically chooses beween `tqdm.notebook` and `tqdm.tqdm`."""
-
- class tqdm.asyncio.tqdm(tqdm.tqdm):
- """Asynchronous version."""
- @classmethod
- def as_completed(cls, fs, *, loop=None, timeout=None, total=None,
- **tqdm_kwargs):
- """Wrapper for `asyncio.as_completed`."""
-
- class tqdm.gui.tqdm(tqdm.tqdm):
- """Matplotlib GUI version."""
-
- class tqdm.tk.tqdm(tqdm.tqdm):
- """Tkinter GUI version."""
-
- class tqdm.rich.tqdm(tqdm.tqdm):
- """`rich.progress` version."""
-
- class tqdm.keras.TqdmCallback(keras.callbacks.Callback):
- """Keras callback for epoch and batch progress."""
-
- class tqdm.dask.TqdmCallback(dask.callbacks.Callback):
- """Dask callback for task progress."""
-
-
-``contrib``
-+++++++++++
-
-The ``tqdm.contrib`` package also contains experimental modules:
-
-- ``tqdm.contrib.itertools``: Thin wrappers around ``itertools``
-- ``tqdm.contrib.concurrent``: Thin wrappers around ``concurrent.futures``
-- ``tqdm.contrib.slack``: Posts to `Slack <https://slack.com>`__ bots
-- ``tqdm.contrib.discord``: Posts to `Discord <https://discord.com>`__ bots
-- ``tqdm.contrib.telegram``: Posts to `Telegram <https://telegram.org>`__ bots
-- ``tqdm.contrib.bells``: Automagically enables all optional features
-
- * ``auto``, ``pandas``, ``slack``, ``discord``, ``telegram``
-
-Examples and Advanced Usage
----------------------------
-
-- See the `examples <https://github.com/tqdm/tqdm/tree/master/examples>`__
- folder;
-- import the module and run ``help()``;
-- consult the `wiki <https://github.com/tqdm/tqdm/wiki>`__;
-
- * this has an
- `excellent article <https://github.com/tqdm/tqdm/wiki/How-to-make-a-great-Progress-Bar>`__
- on how to make a **great** progressbar;
-
-- check out the `slides from PyData London <https://tqdm.github.io/PyData2019/slides.html>`__, or
-- run the |binder-demo|.
-
-Description and additional stats
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Custom information can be displayed and updated dynamically on ``tqdm`` bars
-with the ``desc`` and ``postfix`` arguments:
-
-.. code:: python
-
- from tqdm import tqdm, trange
- from random import random, randint
- from time import sleep
-
- with trange(10) as t:
- for i in t:
- # Description will be displayed on the left
- t.set_description('GEN %i' % i)
- # Postfix will be displayed on the right,
- # formatted automatically based on argument's datatype
- t.set_postfix(loss=random(), gen=randint(1,999), str='h',
- lst=[1, 2])
- sleep(0.1)
-
- with tqdm(total=10, bar_format="{postfix[0]} {postfix[1][value]:>8.2g}",
- postfix=["Batch", dict(value=0)]) as t:
- for i in range(10):
- sleep(0.1)
- t.postfix[1]["value"] = i / 2
- t.update()
-
-Points to remember when using ``{postfix[...]}`` in the ``bar_format`` string:
-
-- ``postfix`` also needs to be passed as an initial argument in a compatible
- format, and
-- ``postfix`` will be auto-converted to a string if it is a ``dict``-like
- object. To prevent this behaviour, insert an extra item into the dictionary
- where the key is not a string.
-
-Additional ``bar_format`` parameters may also be defined by overriding
-``format_dict``, and the bar itself may be modified using ``ascii``:
-
-.. code:: python
-
- from tqdm import tqdm
- class TqdmExtraFormat(tqdm):
- """Provides a `total_time` format parameter"""
- @property
- def format_dict(self):
- d = super(TqdmExtraFormat, self).format_dict
- total_time = d["elapsed"] * (d["total"] or 0) / max(d["n"], 1)
- d.update(total_time=self.format_interval(total_time) + " in total")
- return d
-
- for i in TqdmExtraFormat(
- range(9), ascii=" .oO0",
- bar_format="{total_time}: {percentage:.0f}%|{bar}{r_bar}"):
- if i == 4:
- break
-
-.. code::
-
- 00:00 in total: 44%|0000. | 4/9 [00:00<00:00, 962.93it/s]
-
-Note that ``{bar}`` also supports a format specifier ``[width][type]``.
-
-- ``width``
-
- * unspecified (default): automatic to fill ``ncols``
- * ``int >= 0``: fixed width overriding ``ncols`` logic
- * ``int < 0``: subtract from the automatic default
-
-- ``type``
-
- * ``a``: ascii (``ascii=True`` override)
- * ``u``: unicode (``ascii=False`` override)
- * ``b``: blank (``ascii=" "`` override)
-
-This means a fixed bar with right-justified text may be created by using:
-``bar_format="{l_bar}{bar:10}|{bar:-10b}right-justified"``
-
-Nested progress bars
-~~~~~~~~~~~~~~~~~~~~
-
-``tqdm`` supports nested progress bars. Here's an example:
-
-.. code:: python
-
- from tqdm.auto import trange
- from time import sleep
-
- for i in trange(4, desc='1st loop'):
- for j in trange(5, desc='2nd loop'):
- for k in trange(50, desc='3rd loop', leave=False):
- sleep(0.01)
-
-For manual control over positioning (e.g. for multi-processing use),
-you may specify ``position=n`` where ``n=0`` for the outermost bar,
-``n=1`` for the next, and so on.
-However, it's best to check if ``tqdm`` can work without manual ``position``
-first.
-
-.. code:: python
-
- from time import sleep
- from tqdm import trange, tqdm
- from multiprocessing import Pool, RLock, freeze_support
-
- L = list(range(9))
-
- def progresser(n):
- interval = 0.001 / (n + 2)
- total = 5000
- text = "#{}, est. {:<04.2}s".format(n, interval * total)
- for _ in trange(total, desc=text, position=n):
- sleep(interval)
-
- if __name__ == '__main__':
- freeze_support() # for Windows support
- tqdm.set_lock(RLock()) # for managing output contention
- p = Pool(initializer=tqdm.set_lock, initargs=(tqdm.get_lock(),))
- p.map(progresser, L)
-
-Note that in Python 3, ``tqdm.write`` is thread-safe:
-
-.. code:: python
-
- from time import sleep
- from tqdm import tqdm, trange
- from concurrent.futures import ThreadPoolExecutor
-
- L = list(range(9))
-
- def progresser(n):
- interval = 0.001 / (n + 2)
- total = 5000
- text = "#{}, est. {:<04.2}s".format(n, interval * total)
- for _ in trange(total, desc=text):
- sleep(interval)
- if n == 6:
- tqdm.write("n == 6 completed.")
- tqdm.write("`tqdm.write()` is thread-safe in py3!")
-
- if __name__ == '__main__':
- with ThreadPoolExecutor() as p:
- p.map(progresser, L)
-
-Hooks and callbacks
-~~~~~~~~~~~~~~~~~~~
-
-``tqdm`` can easily support callbacks/hooks and manual updates.
-Here's an example with ``urllib``:
-
-**``urllib.urlretrieve`` documentation**
-
- | [...]
- | If present, the hook function will be called once
- | on establishment of the network connection and once after each block read
- | thereafter. The hook will be passed three arguments; a count of blocks
- | transferred so far, a block size in bytes, and the total size of the file.
- | [...]
-
-.. code:: python
-
- import urllib, os
- from tqdm import tqdm
- urllib = getattr(urllib, 'request', urllib)
-
- class TqdmUpTo(tqdm):
- """Provides `update_to(n)` which uses `tqdm.update(delta_n)`."""
- def update_to(self, b=1, bsize=1, tsize=None):
- """
- b : int, optional
- Number of blocks transferred so far [default: 1].
- bsize : int, optional
- Size of each block (in tqdm units) [default: 1].
- tsize : int, optional
- Total size (in tqdm units). If [default: None] remains unchanged.
- """
- if tsize is not None:
- self.total = tsize
- return self.update(b * bsize - self.n) # also sets self.n = b * bsize
-
- eg_link = "https://caspersci.uk.to/matryoshka.zip"
- with TqdmUpTo(unit='B', unit_scale=True, unit_divisor=1024, miniters=1,
- desc=eg_link.split('/')[-1]) as t: # all optional kwargs
- urllib.urlretrieve(eg_link, filename=os.devnull,
- reporthook=t.update_to, data=None)
- t.total = t.n
-
-Inspired by `twine#242 <https://github.com/pypa/twine/pull/242>`__.
-Functional alternative in
-`examples/tqdm_wget.py <https://github.com/tqdm/tqdm/blob/master/examples/tqdm_wget.py>`__.
-
-It is recommend to use ``miniters=1`` whenever there is potentially
-large differences in iteration speed (e.g. downloading a file over
-a patchy connection).
-
-**Wrapping read/write methods**
-
-To measure throughput through a file-like object's ``read`` or ``write``
-methods, use ``CallbackIOWrapper``:
-
-.. code:: python
-
- from tqdm.auto import tqdm
- from tqdm.utils import CallbackIOWrapper
-
- with tqdm(total=file_obj.size,
- unit='B', unit_scale=True, unit_divisor=1024) as t:
- fobj = CallbackIOWrapper(t.update, file_obj, "read")
- while True:
- chunk = fobj.read(chunk_size)
- if not chunk:
- break
- t.reset()
- # ... continue to use `t` for something else
-
-Alternatively, use the even simpler ``wrapattr`` convenience function,
-which would condense both the ``urllib`` and ``CallbackIOWrapper`` examples
-down to:
-
-.. code:: python
-
- import urllib, os
- from tqdm import tqdm
-
- eg_link = "https://caspersci.uk.to/matryoshka.zip"
- response = getattr(urllib, 'request', urllib).urlopen(eg_link)
- with tqdm.wrapattr(open(os.devnull, "wb"), "write",
- miniters=1, desc=eg_link.split('/')[-1],
- total=getattr(response, 'length', None)) as fout:
- for chunk in response:
- fout.write(chunk)
-
-The ``requests`` equivalent is nearly identical:
-
-.. code:: python
-
- import requests, os
- from tqdm import tqdm
-
- eg_link = "https://caspersci.uk.to/matryoshka.zip"
- response = requests.get(eg_link, stream=True)
- with tqdm.wrapattr(open(os.devnull, "wb"), "write",
- miniters=1, desc=eg_link.split('/')[-1],
- total=int(response.headers.get('content-length', 0))) as fout:
- for chunk in response.iter_content(chunk_size=4096):
- fout.write(chunk)
-
-**Custom callback**
-
-``tqdm`` is known for intelligently skipping unnecessary displays. To make a
-custom callback take advantage of this, simply use the return value of
-``update()``. This is set to ``True`` if a ``display()`` was triggered.
-
-.. code:: python
-
- from tqdm.auto import tqdm as std_tqdm
-
- def external_callback(*args, **kwargs):
- ...
-
- class TqdmExt(std_tqdm):
- def update(self, n=1):
- displayed = super(TqdmExt, self).update(n)
- if displayed:
- external_callback(**self.format_dict)
- return displayed
-
-``asyncio``
-~~~~~~~~~~~
-
-Note that ``break`` isn't currently caught by asynchronous iterators.
-This means that ``tqdm`` cannot clean up after itself in this case:
-
-.. code:: python
-
- from tqdm.asyncio import tqdm
-
- async for i in tqdm(range(9)):
- if i == 2:
- break
-
-Instead, either call ``pbar.close()`` manually or use the context manager syntax:
-
-.. code:: python
-
- from tqdm.asyncio import tqdm
-
- with tqdm(range(9)) as pbar:
- async for i in pbar:
- if i == 2:
- break
-
-Pandas Integration
-~~~~~~~~~~~~~~~~~~
-
-Due to popular demand we've added support for ``pandas`` -- here's an example
-for ``DataFrame.progress_apply`` and ``DataFrameGroupBy.progress_apply``:
-
-.. code:: python
-
- import pandas as pd
- import numpy as np
- from tqdm import tqdm
-
- df = pd.DataFrame(np.random.randint(0, 100, (100000, 6)))
-
- # Register `pandas.progress_apply` and `pandas.Series.map_apply` with `tqdm`
- # (can use `tqdm.gui.tqdm`, `tqdm.notebook.tqdm`, optional kwargs, etc.)
- tqdm.pandas(desc="my bar!")
-
- # Now you can use `progress_apply` instead of `apply`
- # and `progress_map` instead of `map`
- df.progress_apply(lambda x: x**2)
- # can also groupby:
- # df.groupby(0).progress_apply(lambda x: x**2)
-
-In case you're interested in how this works (and how to modify it for your
-own callbacks), see the
-`examples <https://github.com/tqdm/tqdm/tree/master/examples>`__
-folder or import the module and run ``help()``.
-
-Keras Integration
-~~~~~~~~~~~~~~~~~
-
-A ``keras`` callback is also available:
-
-.. code:: python
-
- from tqdm.keras import TqdmCallback
-
- ...
-
- model.fit(..., verbose=0, callbacks=[TqdmCallback()])
-
-Dask Integration
-~~~~~~~~~~~~~~~~
-
-A ``dask`` callback is also available:
-
-.. code:: python
-
- from tqdm.dask import TqdmCallback
-
- with TqdmCallback(desc="compute"):
- ...
- arr.compute()
-
- # or use callback globally
- cb = TqdmCallback(desc="global")
- cb.register()
- arr.compute()
-
-IPython/Jupyter Integration
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-IPython/Jupyter is supported via the ``tqdm.notebook`` submodule:
-
-.. code:: python
-
- from tqdm.notebook import trange, tqdm
- from time import sleep
-
- for i in trange(3, desc='1st loop'):
- for j in tqdm(range(100), desc='2nd loop'):
- sleep(0.01)
-
-In addition to ``tqdm`` features, the submodule provides a native Jupyter
-widget (compatible with IPython v1-v4 and Jupyter), fully working nested bars
-and colour hints (blue: normal, green: completed, red: error/interrupt,
-light blue: no ETA); as demonstrated below.
-
-|Screenshot-Jupyter1|
-|Screenshot-Jupyter2|
-|Screenshot-Jupyter3|
-
-The ``notebook`` version supports percentage or pixels for overall width
-(e.g.: ``ncols='100%'`` or ``ncols='480px'``).
-
-It is also possible to let ``tqdm`` automatically choose between
-console or notebook versions by using the ``autonotebook`` submodule:
-
-.. code:: python
-
- from tqdm.autonotebook import tqdm
- tqdm.pandas()
-
-Note that this will issue a ``TqdmExperimentalWarning`` if run in a notebook
-since it is not meant to be possible to distinguish between ``jupyter notebook``
-and ``jupyter console``. Use ``auto`` instead of ``autonotebook`` to suppress
-this warning.
-
-Note that notebooks will display the bar in the cell where it was created.
-This may be a different cell from the one where it is used.
-If this is not desired, either
-
-- delay the creation of the bar to the cell where it must be displayed, or
-- create the bar with ``display=False``, and in a later cell call
- ``display(bar.container)``:
-
-.. code:: python
-
- from tqdm.notebook import tqdm
- pbar = tqdm(..., display=False)
-
-.. code:: python
-
- # different cell
- display(pbar.container)
-
-The ``keras`` callback has a ``display()`` method which can be used likewise:
-
-.. code:: python
-
- from tqdm.keras import TqdmCallback
- cbk = TqdmCallback(display=False)
-
-.. code:: python
-
- # different cell
- cbk.display()
- model.fit(..., verbose=0, callbacks=[cbk])
-
-Another possibility is to have a single bar (near the top of the notebook)
-which is constantly re-used (using ``reset()`` rather than ``close()``).
-For this reason, the notebook version (unlike the CLI version) does not
-automatically call ``close()`` upon ``Exception``.
-
-.. code:: python
-
- from tqdm.notebook import tqdm
- pbar = tqdm()
-
-.. code:: python
-
- # different cell
- iterable = range(100)
- pbar.reset(total=len(iterable)) # initialise with new `total`
- for i in iterable:
- pbar.update()
- pbar.refresh() # force print final status but don't `close()`
-
-Custom Integration
-~~~~~~~~~~~~~~~~~~
-
-To change the default arguments (such as making ``dynamic_ncols=True``),
-simply use built-in Python magic:
-
-.. code:: python
-
- from functools import partial
- from tqdm import tqdm as std_tqdm
- tqdm = partial(std_tqdm, dynamic_ncols=True)
-
-For further customisation,
-``tqdm`` may be inherited from to create custom callbacks (as with the
-``TqdmUpTo`` example `above <#hooks-and-callbacks>`__) or for custom frontends
-(e.g. GUIs such as notebook or plotting packages). In the latter case:
-
-1. ``def __init__()`` to call ``super().__init__(..., gui=True)`` to disable
- terminal ``status_printer`` creation.
-2. Redefine: ``close()``, ``clear()``, ``display()``.
-
-Consider overloading ``display()`` to use e.g.
-``self.frontend(**self.format_dict)`` instead of ``self.sp(repr(self))``.
-
-Some submodule examples of inheritance:
-
-- `tqdm/notebook.py <https://github.com/tqdm/tqdm/blob/master/tqdm/notebook.py>`__
-- `tqdm/gui.py <https://github.com/tqdm/tqdm/blob/master/tqdm/gui.py>`__
-- `tqdm/tk.py <https://github.com/tqdm/tqdm/blob/master/tqdm/tk.py>`__
-- `tqdm/contrib/slack.py <https://github.com/tqdm/tqdm/blob/master/tqdm/contrib/slack.py>`__
-- `tqdm/contrib/discord.py <https://github.com/tqdm/tqdm/blob/master/tqdm/contrib/discord.py>`__
-- `tqdm/contrib/telegram.py <https://github.com/tqdm/tqdm/blob/master/tqdm/contrib/telegram.py>`__
-
-Dynamic Monitor/Meter
-~~~~~~~~~~~~~~~~~~~~~
-
-You can use a ``tqdm`` as a meter which is not monotonically increasing.
-This could be because ``n`` decreases (e.g. a CPU usage monitor) or ``total``
-changes.
-
-One example would be recursively searching for files. The ``total`` is the
-number of objects found so far, while ``n`` is the number of those objects which
-are files (rather than folders):
-
-.. code:: python
-
- from tqdm import tqdm
- import os.path
-
- def find_files_recursively(path, show_progress=True):
- files = []
- # total=1 assumes `path` is a file
- t = tqdm(total=1, unit="file", disable=not show_progress)
- if not os.path.exists(path):
- raise IOError("Cannot find:" + path)
-
- def append_found_file(f):
- files.append(f)
- t.update()
-
- def list_found_dir(path):
- """returns os.listdir(path) assuming os.path.isdir(path)"""
- listing = os.listdir(path)
- # subtract 1 since a "file" we found was actually this directory
- t.total += len(listing) - 1
- # fancy way to give info without forcing a refresh
- t.set_postfix(dir=path[-10:], refresh=False)
- t.update(0) # may trigger a refresh
- return listing
-
- def recursively_search(path):
- if os.path.isdir(path):
- for f in list_found_dir(path):
- recursively_search(os.path.join(path, f))
- else:
- append_found_file(path)
-
- recursively_search(path)
- t.set_postfix(dir=path)
- t.close()
- return files
-
-Using ``update(0)`` is a handy way to let ``tqdm`` decide when to trigger a
-display refresh to avoid console spamming.
-
-Writing messages
-~~~~~~~~~~~~~~~~
-
-This is a work in progress (see
-`#737 <https://github.com/tqdm/tqdm/issues/737>`__).
-
-Since ``tqdm`` uses a simple printing mechanism to display progress bars,
-you should not write any message in the terminal using ``print()`` while
-a progressbar is open.
-
-To write messages in the terminal without any collision with ``tqdm`` bar
-display, a ``.write()`` method is provided:
-
-.. code:: python
-
- from tqdm.auto import tqdm, trange
- from time import sleep
-
- bar = trange(10)
- for i in bar:
- # Print using tqdm class method .write()
- sleep(0.1)
- if not (i % 3):
- tqdm.write("Done task %i" % i)
- # Can also use bar.write()
-
-By default, this will print to standard output ``sys.stdout``. but you can
-specify any file-like object using the ``file`` argument. For example, this
-can be used to redirect the messages writing to a log file or class.
-
-Redirecting writing
-~~~~~~~~~~~~~~~~~~~
-
-If using a library that can print messages to the console, editing the library
-by replacing ``print()`` with ``tqdm.write()`` may not be desirable.
-In that case, redirecting ``sys.stdout`` to ``tqdm.write()`` is an option.
-
-To redirect ``sys.stdout``, create a file-like class that will write
-any input string to ``tqdm.write()``, and supply the arguments
-``file=sys.stdout, dynamic_ncols=True``.
-
-A reusable canonical example is given below:
-
-.. code:: python
-
- from time import sleep
- import contextlib
- import sys
- from tqdm import tqdm
- from tqdm.contrib import DummyTqdmFile
-
-
- @contextlib.contextmanager
- def std_out_err_redirect_tqdm():
- orig_out_err = sys.stdout, sys.stderr
- try:
- sys.stdout, sys.stderr = map(DummyTqdmFile, orig_out_err)
- yield orig_out_err[0]
- # Relay exceptions
- except Exception as exc:
- raise exc
- # Always restore sys.stdout/err if necessary
- finally:
- sys.stdout, sys.stderr = orig_out_err
-
- def some_fun(i):
- print("Fee, fi, fo,".split()[i])
-
- # Redirect stdout to tqdm.write() (don't forget the `as save_stdout`)
- with std_out_err_redirect_tqdm() as orig_stdout:
- # tqdm needs the original stdout
- # and dynamic_ncols=True to autodetect console width
- for i in tqdm(range(3), file=orig_stdout, dynamic_ncols=True):
- sleep(.5)
- some_fun(i)
-
- # After the `with`, printing is restored
- print("Done!")
-
-Redirecting ``logging``
-~~~~~~~~~~~~~~~~~~~~~~~
-
-Similar to ``sys.stdout``/``sys.stderr`` as detailed above, console ``logging``
-may also be redirected to ``tqdm.write()``.
-
-Warning: if also redirecting ``sys.stdout``/``sys.stderr``, make sure to
-redirect ``logging`` first if needed.
-
-Helper methods are available in ``tqdm.contrib.logging``. For example:
-
-.. code:: python
-
- import logging
- from tqdm import trange
- from tqdm.contrib.logging import logging_redirect_tqdm
-
- LOG = logging.getLogger(__name__)
-
- if __name__ == '__main__':
- logging.basicConfig(level=logging.INFO)
- with logging_redirect_tqdm():
- for i in trange(9):
- if i == 4:
- LOG.info("console logging redirected to `tqdm.write()`")
- # logging restored
-
-Monitoring thread, intervals and miniters
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-``tqdm`` implements a few tricks to increase efficiency and reduce overhead.
-
-- Avoid unnecessary frequent bar refreshing: ``mininterval`` defines how long
- to wait between each refresh. ``tqdm`` always gets updated in the background,
- but it will display only every ``mininterval``.
-- Reduce number of calls to check system clock/time.
-- ``mininterval`` is more intuitive to configure than ``miniters``.
- A clever adjustment system ``dynamic_miniters`` will automatically adjust
- ``miniters`` to the amount of iterations that fit into time ``mininterval``.
- Essentially, ``tqdm`` will check if it's time to print without actually
- checking time. This behaviour can be still be bypassed by manually setting
- ``miniters``.
-
-However, consider a case with a combination of fast and slow iterations.
-After a few fast iterations, ``dynamic_miniters`` will set ``miniters`` to a
-large number. When iteration rate subsequently slows, ``miniters`` will
-remain large and thus reduce display update frequency. To address this:
-
-- ``maxinterval`` defines the maximum time between display refreshes.
- A concurrent monitoring thread checks for overdue updates and forces one
- where necessary.
-
-The monitoring thread should not have a noticeable overhead, and guarantees
-updates at least every 10 seconds by default.
-This value can be directly changed by setting the ``monitor_interval`` of
-any ``tqdm`` instance (i.e. ``t = tqdm.tqdm(...); t.monitor_interval = 2``).
-The monitor thread may be disabled application-wide by setting
-``tqdm.tqdm.monitor_interval = 0`` before instantiation of any ``tqdm`` bar.
-
-
-Merch
------
-
-You can buy `tqdm branded merch <https://tqdm.github.io/merch>`__ now!
-
-Contributions
--------------
-
-|GitHub-Commits| |GitHub-Issues| |GitHub-PRs| |OpenHub-Status| |GitHub-Contributions| |CII Best Practices|
-
-All source code is hosted on `GitHub <https://github.com/tqdm/tqdm>`__.
-Contributions are welcome.
-
-See the
-`CONTRIBUTING <https://github.com/tqdm/tqdm/blob/master/CONTRIBUTING.md>`__
-file for more information.
-
-Developers who have made significant contributions, ranked by *SLoC*
-(surviving lines of code,
-`git fame <https://github.com/casperdcl/git-fame>`__ ``-wMC --excl '\.(png|gif|jpg)$'``),
-are:
-
-==================== ======================================================== ==== ================================
-Name ID SLoC Notes
-==================== ======================================================== ==== ================================
-Casper da Costa-Luis `casperdcl <https://github.com/casperdcl>`__ ~78% primary maintainer |Gift-Casper|
-Stephen Larroque `lrq3000 <https://github.com/lrq3000>`__ ~10% team member
-Martin Zugnoni `martinzugnoni <https://github.com/martinzugnoni>`__ ~4%
-Daniel Ecer `de-code <https://github.com/de-code>`__ ~2%
-Richard Sheridan `richardsheridan <https://github.com/richardsheridan>`__ ~1%
-Guangshuo Chen `chengs <https://github.com/chengs>`__ ~1%
-Kyle Altendorf `altendky <https://github.com/altendky>`__ <1%
-Matthew Stevens `mjstevens777 <https://github.com/mjstevens777>`__ <1%
-Hadrien Mary `hadim <https://github.com/hadim>`__ <1% team member
-Noam Yorav-Raphael `noamraph <https://github.com/noamraph>`__ <1% original author
-Mikhail Korobov `kmike <https://github.com/kmike>`__ <1% team member
-==================== ======================================================== ==== ================================
-
-Ports to Other Languages
-~~~~~~~~~~~~~~~~~~~~~~~~
-
-A list is available on
-`this wiki page <https://github.com/tqdm/tqdm/wiki/tqdm-ports>`__.
-
-
-LICENCE
--------
-
-Open Source (OSI approved): |LICENCE|
-
-Citation information: |DOI|
-
-|README-Hits| (Since 19 May 2016)
-
-.. |Logo| image:: https://img.tqdm.ml/logo.gif
-.. |Screenshot| image:: https://img.tqdm.ml/tqdm.gif
-.. |Video| image:: https://img.tqdm.ml/video.jpg
- :target: https://tqdm.github.io/video
-.. |Slides| image:: https://img.tqdm.ml/slides.jpg
- :target: https://tqdm.github.io/PyData2019/slides.html
-.. |Merch| image:: https://img.tqdm.ml/merch.jpg
- :target: https://tqdm.github.io/merch
-.. |Build-Status| image:: https://img.shields.io/github/workflow/status/tqdm/tqdm/Test/master?logo=GitHub
- :target: https://github.com/tqdm/tqdm/actions?query=workflow%3ATest
-.. |Coverage-Status| image:: https://img.shields.io/coveralls/github/tqdm/tqdm/master?logo=coveralls
- :target: https://coveralls.io/github/tqdm/tqdm
-.. |Branch-Coverage-Status| image:: https://codecov.io/gh/tqdm/tqdm/branch/master/graph/badge.svg
- :target: https://codecov.io/gh/tqdm/tqdm
-.. |Codacy-Grade| image:: https://app.codacy.com/project/badge/Grade/3f965571598f44549c7818f29cdcf177
- :target: https://www.codacy.com/gh/tqdm/tqdm/dashboard
-.. |CII Best Practices| image:: https://bestpractices.coreinfrastructure.org/projects/3264/badge
- :target: https://bestpractices.coreinfrastructure.org/projects/3264
-.. |GitHub-Status| image:: https://img.shields.io/github/tag/tqdm/tqdm.svg?maxAge=86400&logo=github&logoColor=white
- :target: https://github.com/tqdm/tqdm/releases
-.. |GitHub-Forks| image:: https://img.shields.io/github/forks/tqdm/tqdm.svg?logo=github&logoColor=white
- :target: https://github.com/tqdm/tqdm/network
-.. |GitHub-Stars| image:: https://img.shields.io/github/stars/tqdm/tqdm.svg?logo=github&logoColor=white
- :target: https://github.com/tqdm/tqdm/stargazers
-.. |GitHub-Commits| image:: https://img.shields.io/github/commit-activity/y/tqdm/tqdm.svg?logo=git&logoColor=white
- :target: https://github.com/tqdm/tqdm/graphs/commit-activity
-.. |GitHub-Issues| image:: https://img.shields.io/github/issues-closed/tqdm/tqdm.svg?logo=github&logoColor=white
- :target: https://github.com/tqdm/tqdm/issues?q=
-.. |GitHub-PRs| image:: https://img.shields.io/github/issues-pr-closed/tqdm/tqdm.svg?logo=github&logoColor=white
- :target: https://github.com/tqdm/tqdm/pulls
-.. |GitHub-Contributions| image:: https://img.shields.io/github/contributors/tqdm/tqdm.svg?logo=github&logoColor=white
- :target: https://github.com/tqdm/tqdm/graphs/contributors
-.. |GitHub-Updated| image:: https://img.shields.io/github/last-commit/tqdm/tqdm/master.svg?logo=github&logoColor=white&label=pushed
- :target: https://github.com/tqdm/tqdm/pulse
-.. |Gift-Casper| image:: https://img.shields.io/badge/dynamic/json.svg?color=ff69b4&label=gifts%20received&prefix=%C2%A3&query=%24..sum&url=https%3A%2F%2Fcaspersci.uk.to%2Fgifts.json
- :target: https://cdcl.ml/sponsor
-.. |Versions| image:: https://img.shields.io/pypi/v/tqdm.svg
- :target: https://tqdm.github.io/releases
-.. |PyPI-Downloads| image:: https://img.shields.io/pypi/dm/tqdm.svg?label=pypi%20downloads&logo=PyPI&logoColor=white
- :target: https://pepy.tech/project/tqdm
-.. |Py-Versions| image:: https://img.shields.io/pypi/pyversions/tqdm.svg?logo=python&logoColor=white
- :target: https://pypi.org/project/tqdm
-.. |Conda-Forge-Status| image:: https://img.shields.io/conda/v/conda-forge/tqdm.svg?label=conda-forge&logo=conda-forge
- :target: https://anaconda.org/conda-forge/tqdm
-.. |Snapcraft| image:: https://img.shields.io/badge/snap-install-82BEA0.svg?logo=snapcraft
- :target: https://snapcraft.io/tqdm
-.. |Docker| image:: https://img.shields.io/badge/docker-pull-blue.svg?logo=docker&logoColor=white
- :target: https://hub.docker.com/r/tqdm/tqdm
-.. |Libraries-Rank| image:: https://img.shields.io/librariesio/sourcerank/pypi/tqdm.svg?logo=koding&logoColor=white
- :target: https://libraries.io/pypi/tqdm
-.. |Libraries-Dependents| image:: https://img.shields.io/librariesio/dependent-repos/pypi/tqdm.svg?logo=koding&logoColor=white
- :target: https://github.com/tqdm/tqdm/network/dependents
-.. |OpenHub-Status| image:: https://www.openhub.net/p/tqdm/widgets/project_thin_badge?format=gif
- :target: https://www.openhub.net/p/tqdm?ref=Thin+badge
-.. |awesome-python| image:: https://awesome.re/mentioned-badge.svg
- :target: https://github.com/vinta/awesome-python
-.. |LICENCE| image:: https://img.shields.io/pypi/l/tqdm.svg
- :target: https://raw.githubusercontent.com/tqdm/tqdm/master/LICENCE
-.. |DOI| image:: https://img.shields.io/badge/DOI-10.5281/zenodo.595120-blue.svg
- :target: https://doi.org/10.5281/zenodo.595120
-.. |binder-demo| image:: https://mybinder.org/badge_logo.svg
- :target: https://mybinder.org/v2/gh/tqdm/tqdm/master?filepath=DEMO.ipynb
-.. |Screenshot-Jupyter1| image:: https://img.tqdm.ml/jupyter-1.gif
-.. |Screenshot-Jupyter2| image:: https://img.tqdm.ml/jupyter-2.gif
-.. |Screenshot-Jupyter3| image:: https://img.tqdm.ml/jupyter-3.gif
-.. |README-Hits| image:: https://caspersci.uk.to/cgi-bin/hits.cgi?q=tqdm&style=social&r=https://github.com/tqdm/tqdm&l=https://img.tqdm.ml/favicon.png&f=https://img.tqdm.ml/logo.gif
- :target: https://caspersci.uk.to/cgi-bin/hits.cgi?q=tqdm&a=plot&r=https://github.com/tqdm/tqdm&l=https://img.tqdm.ml/favicon.png&f=https://img.tqdm.ml/logo.gif&style=social
diff --git a/tqdm.egg-info/SOURCES.txt b/tqdm.egg-info/SOURCES.txt
deleted file mode 100644
index 41d7b89..0000000
--- a/tqdm.egg-info/SOURCES.txt
+++ /dev/null
@@ -1,88 +0,0 @@
-.pre-commit-config.yaml
-.zenodo.json
-CODE_OF_CONDUCT.md
-CONTRIBUTING.md
-DEMO.ipynb
-LICENCE
-Makefile
-README.rst
-environment.yml
-logo.png
-pyproject.toml
-setup.cfg
-setup.py
-tests_notebook.ipynb
-tox.ini
-examples/7zx.py
-examples/async_coroutines.py
-examples/coroutine_pipe.py
-examples/include_no_requirements.py
-examples/pandas_progress_apply.py
-examples/paper.bib
-examples/paper.md
-examples/parallel_bars.py
-examples/redirect_print.py
-examples/simple_examples.py
-examples/tqdm_requests.py
-examples/tqdm_wget.py
-examples/wrapping_generators.py
-tests/__init__.py
-tests/conftest.py
-tests/py37_asyncio.py
-tests/tests_asyncio.py
-tests/tests_concurrent.py
-tests/tests_contrib.py
-tests/tests_contrib_logging.py
-tests/tests_dask.py
-tests/tests_gui.py
-tests/tests_itertools.py
-tests/tests_keras.py
-tests/tests_main.py
-tests/tests_notebook.py
-tests/tests_pandas.py
-tests/tests_perf.py
-tests/tests_rich.py
-tests/tests_synchronisation.py
-tests/tests_tk.py
-tests/tests_tqdm.py
-tests/tests_version.py
-tqdm/__init__.py
-tqdm/__main__.py
-tqdm/_dist_ver.py
-tqdm/_main.py
-tqdm/_monitor.py
-tqdm/_tqdm.py
-tqdm/_tqdm_gui.py
-tqdm/_tqdm_notebook.py
-tqdm/_tqdm_pandas.py
-tqdm/_utils.py
-tqdm/asyncio.py
-tqdm/auto.py
-tqdm/autonotebook.py
-tqdm/cli.py
-tqdm/completion.sh
-tqdm/dask.py
-tqdm/gui.py
-tqdm/keras.py
-tqdm/notebook.py
-tqdm/rich.py
-tqdm/std.py
-tqdm/tk.py
-tqdm/tqdm.1
-tqdm/utils.py
-tqdm/version.py
-tqdm.egg-info/PKG-INFO
-tqdm.egg-info/SOURCES.txt
-tqdm.egg-info/dependency_links.txt
-tqdm.egg-info/entry_points.txt
-tqdm.egg-info/requires.txt
-tqdm.egg-info/top_level.txt
-tqdm/contrib/__init__.py
-tqdm/contrib/bells.py
-tqdm/contrib/concurrent.py
-tqdm/contrib/discord.py
-tqdm/contrib/itertools.py
-tqdm/contrib/logging.py
-tqdm/contrib/slack.py
-tqdm/contrib/telegram.py
-tqdm/contrib/utils_worker.py \ No newline at end of file
diff --git a/tqdm.egg-info/dependency_links.txt b/tqdm.egg-info/dependency_links.txt
deleted file mode 100644
index 8b13789..0000000
--- a/tqdm.egg-info/dependency_links.txt
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/tqdm.egg-info/entry_points.txt b/tqdm.egg-info/entry_points.txt
deleted file mode 100644
index 540e60f..0000000
--- a/tqdm.egg-info/entry_points.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-[console_scripts]
-tqdm = tqdm.cli:main
diff --git a/tqdm.egg-info/requires.txt b/tqdm.egg-info/requires.txt
deleted file mode 100644
index 352f7a3..0000000
--- a/tqdm.egg-info/requires.txt
+++ /dev/null
@@ -1,20 +0,0 @@
-
-[:platform_system == "Windows"]
-colorama
-
-[:python_version < "3.7"]
-importlib_resources
-
-[dev]
-py-make>=0.1.0
-twine
-wheel
-
-[notebook]
-ipywidgets>=6
-
-[slack]
-slack-sdk
-
-[telegram]
-requests
diff --git a/tqdm.egg-info/top_level.txt b/tqdm.egg-info/top_level.txt
deleted file mode 100644
index 78620c4..0000000
--- a/tqdm.egg-info/top_level.txt
+++ /dev/null
@@ -1 +0,0 @@
-tqdm
diff --git a/tqdm/__init__.py b/tqdm/__init__.py
index a021d16..8081f77 100644
--- a/tqdm/__init__.py
+++ b/tqdm/__init__.py
@@ -29,10 +29,7 @@ def tqdm_notebook(*args, **kwargs): # pragma: no cover
def tnrange(*args, **kwargs): # pragma: no cover
- """
- A shortcut for `tqdm.notebook.tqdm(xrange(*args), **kwargs)`.
- On Python3+, `range` is used instead of `xrange`.
- """
+ """Shortcut for `tqdm.notebook.tqdm(range(*args), **kwargs)`."""
from warnings import warn
from .notebook import trange as _tnrange
diff --git a/tqdm/_dist_ver.py b/tqdm/_dist_ver.py
deleted file mode 100644
index 1c2d004..0000000
--- a/tqdm/_dist_ver.py
+++ /dev/null
@@ -1 +0,0 @@
-__version__ = '4.64.1'
diff --git a/tqdm/_utils.py b/tqdm/_utils.py
index 2cf1090..385e849 100644
--- a/tqdm/_utils.py
+++ b/tqdm/_utils.py
@@ -2,10 +2,9 @@ from warnings import warn
from .std import TqdmDeprecationWarning
from .utils import ( # NOQA, pylint: disable=unused-import
- CUR_OS, IS_NIX, IS_WIN, RE_ANSI, Comparable, FormatReplace, SimpleTextIOWrapper, _basestring,
- _environ_cols_wrapper, _is_ascii, _is_utf, _range, _screen_shape_linux, _screen_shape_tput,
- _screen_shape_windows, _screen_shape_wrapper, _supports_unicode, _term_move_up, _unich,
- _unicode, colorama)
+ CUR_OS, IS_NIX, IS_WIN, RE_ANSI, Comparable, FormatReplace, SimpleTextIOWrapper,
+ _environ_cols_wrapper, _is_ascii, _is_utf, _screen_shape_linux, _screen_shape_tput,
+ _screen_shape_windows, _screen_shape_wrapper, _supports_unicode, _term_move_up, colorama)
warn("This function will be removed in tqdm==5.0.0\n"
"Please use `tqdm.utils.*` instead of `tqdm._utils.*`",
diff --git a/tqdm/asyncio.py b/tqdm/asyncio.py
index 97c5f88..ddc89b8 100644
--- a/tqdm/asyncio.py
+++ b/tqdm/asyncio.py
@@ -18,7 +18,7 @@ __all__ = ['tqdm_asyncio', 'tarange', 'tqdm', 'trange']
class tqdm_asyncio(std_tqdm):
"""
- Asynchronous-friendly version of tqdm (Python 3.6+).
+ Asynchronous-friendly version of tqdm.
"""
def __init__(self, iterable=None, *args, **kwargs):
super(tqdm_asyncio, self).__init__(iterable, *args, **kwargs)
diff --git a/tqdm/auto.py b/tqdm/auto.py
index cffca20..206c440 100644
--- a/tqdm/auto.py
+++ b/tqdm/auto.py
@@ -4,7 +4,7 @@ Enables multiple commonly used features.
Method resolution order:
- `tqdm.autonotebook` without import warnings
-- `tqdm.asyncio` on Python3.6+
+- `tqdm.asyncio`
- `tqdm.std` base class
Usage:
@@ -12,7 +12,6 @@ Usage:
>>> for i in trange(10):
... ...
"""
-import sys
import warnings
from .std import TqdmExperimentalWarning
@@ -20,25 +19,22 @@ from .std import TqdmExperimentalWarning
with warnings.catch_warnings():
warnings.simplefilter("ignore", category=TqdmExperimentalWarning)
from .autonotebook import tqdm as notebook_tqdm
- from .autonotebook import trange as notebook_trange
-
-if sys.version_info[:2] < (3, 6):
- tqdm = notebook_tqdm
- trange = notebook_trange
-else: # Python3.6+
- from .asyncio import tqdm as asyncio_tqdm
- from .std import tqdm as std_tqdm
-
- if notebook_tqdm != std_tqdm:
- class tqdm(notebook_tqdm, asyncio_tqdm): # pylint: disable=inconsistent-mro
- pass
- else:
- tqdm = asyncio_tqdm
-
- def trange(*args, **kwargs):
- """
- A shortcut for `tqdm.auto.tqdm(range(*args), **kwargs)`.
- """
- return tqdm(range(*args), **kwargs)
+
+from .asyncio import tqdm as asyncio_tqdm
+from .std import tqdm as std_tqdm
+
+if notebook_tqdm != std_tqdm:
+ class tqdm(notebook_tqdm, asyncio_tqdm): # pylint: disable=inconsistent-mro
+ pass
+else:
+ tqdm = asyncio_tqdm
+
+
+def trange(*args, **kwargs):
+ """
+ A shortcut for `tqdm.auto.tqdm(range(*args), **kwargs)`.
+ """
+ return tqdm(range(*args), **kwargs)
+
__all__ = ["tqdm", "trange"]
diff --git a/tqdm/cli.py b/tqdm/cli.py
index 3ed25fb..1223d49 100644
--- a/tqdm/cli.py
+++ b/tqdm/cli.py
@@ -98,7 +98,7 @@ def posix_pipe(fin, fout, delim=b'\\n', buf_size=256,
# ((opt, type), ... )
-RE_OPTS = re.compile(r'\n {8}(\S+)\s{2,}:\s*([^,]+)')
+RE_OPTS = re.compile(r'\n {4}(\S+)\s{2,}:\s*([^,]+)')
# better split method assuming no positional args
RE_SHLEX = re.compile(r'\s*(?<!\S)--?([^\s=]+)(\s+|=|$)')
@@ -107,37 +107,37 @@ UNSUPPORTED_OPTS = ('iterable', 'gui', 'out', 'file')
# The 8 leading spaces are required for consistency
CLI_EXTRA_DOC = r"""
- Extra CLI Options
- -----------------
- name : type, optional
- TODO: find out why this is needed.
- delim : chr, optional
- Delimiting character [default: '\n']. Use '\0' for null.
- N.B.: on Windows systems, Python converts '\n' to '\r\n'.
- buf_size : int, optional
- String buffer size in bytes [default: 256]
- used when `delim` is specified.
- bytes : bool, optional
- If true, will count bytes, ignore `delim`, and default
- `unit_scale` to True, `unit_divisor` to 1024, and `unit` to 'B'.
- tee : bool, optional
- If true, passes `stdin` to both `stderr` and `stdout`.
- update : bool, optional
- If true, will treat input as newly elapsed iterations,
- i.e. numbers to pass to `update()`. Note that this is slow
- (~2e5 it/s) since every input must be decoded as a number.
- update_to : bool, optional
- If true, will treat input as total elapsed iterations,
- i.e. numbers to assign to `self.n`. Note that this is slow
- (~2e5 it/s) since every input must be decoded as a number.
- null : bool, optional
- If true, will discard input (no stdout).
- manpath : str, optional
- Directory in which to install tqdm man pages.
- comppath : str, optional
- Directory in which to place tqdm completion.
- log : str, optional
- CRITICAL|FATAL|ERROR|WARN(ING)|[default: 'INFO']|DEBUG|NOTSET.
+ Extra CLI Options
+ -----------------
+ name : type, optional
+ TODO: find out why this is needed.
+ delim : chr, optional
+ Delimiting character [default: '\n']. Use '\0' for null.
+ N.B.: on Windows systems, Python converts '\n' to '\r\n'.
+ buf_size : int, optional
+ String buffer size in bytes [default: 256]
+ used when `delim` is specified.
+ bytes : bool, optional
+ If true, will count bytes, ignore `delim`, and default
+ `unit_scale` to True, `unit_divisor` to 1024, and `unit` to 'B'.
+ tee : bool, optional
+ If true, passes `stdin` to both `stderr` and `stdout`.
+ update : bool, optional
+ If true, will treat input as newly elapsed iterations,
+ i.e. numbers to pass to `update()`. Note that this is slow
+ (~2e5 it/s) since every input must be decoded as a number.
+ update_to : bool, optional
+ If true, will treat input as total elapsed iterations,
+ i.e. numbers to assign to `self.n`. Note that this is slow
+ (~2e5 it/s) since every input must be decoded as a number.
+ null : bool, optional
+ If true, will discard input (no stdout).
+ manpath : str, optional
+ Directory in which to install tqdm man pages.
+ comppath : str, optional
+ Directory in which to place tqdm completion.
+ log : str, optional
+ CRITICAL|FATAL|ERROR|WARN(ING)|[default: 'INFO']|DEBUG|NOTSET.
"""
@@ -166,7 +166,7 @@ def main(fp=sys.stderr, argv=None):
logging.basicConfig(level=getattr(logging, logLevel),
format="%(levelname)s:%(module)s:%(lineno)d:%(message)s")
- d = tqdm.__init__.__doc__ + CLI_EXTRA_DOC
+ d = tqdm.__doc__ + CLI_EXTRA_DOC
opt_types = dict(RE_OPTS.findall(d))
# opt_types['delim'] = 'chr'
@@ -199,8 +199,7 @@ Options:
sys.stdout.write(d + '\n')
sys.exit(0)
elif argv and argv[0][:2] != '--':
- sys.stderr.write(
- "Error:Unknown argument:{0}\n{1}".format(argv[0], help_short))
+ sys.stderr.write(f"Error:Unknown argument:{argv[0]}\n{help_short}")
argv = RE_SHLEX.split(' '.join(["tqdm"] + argv))
opts = dict(zip(argv[1::3], argv[3::3]))
@@ -245,12 +244,9 @@ Options:
stdout = getattr(stdout, 'buffer', stdout)
stdin = getattr(sys.stdin, 'buffer', sys.stdin)
if manpath or comppath:
+ from importlib import resources
from os import path
from shutil import copyfile
- try: # py<3.7
- import importlib_resources as resources
- except ImportError:
- from importlib import resources
def cp(name, dst):
"""copy resource `name` to `dst`"""
diff --git a/tqdm/contrib/__init__.py b/tqdm/contrib/__init__.py
index 0b52177..7338c96 100644
--- a/tqdm/contrib/__init__.py
+++ b/tqdm/contrib/__init__.py
@@ -3,11 +3,10 @@ Thin wrappers around common functions.
Subpackages contain potentially unstable extensions.
"""
-import sys
-from functools import wraps
+from warnings import warn
from ..auto import tqdm as tqdm_auto
-from ..std import tqdm
+from ..std import TqdmDeprecationWarning, tqdm
from ..utils import ObjectWrapper
__author__ = {"github.com/": ["casperdcl"]}
@@ -42,12 +41,9 @@ class DummyTqdmFile(ObjectWrapper):
def builtin_iterable(func):
- """Wraps `func()` output in a `list()` in py2"""
- if sys.version_info[:1] < (3,):
- @wraps(func)
- def inner(*args, **kwargs):
- return list(func(*args, **kwargs))
- return inner
+ """Returns `func`"""
+ warn("This function has no effect, and will be removed in tqdm==5.0.0",
+ TqdmDeprecationWarning, stacklevel=2)
return func
@@ -70,7 +66,6 @@ def tenumerate(iterable, start=0, total=None, tqdm_class=tqdm_auto, **tqdm_kwarg
return enumerate(tqdm_class(iterable, total=total, **tqdm_kwargs), start)
-@builtin_iterable
def tzip(iter1, *iter2plus, **tqdm_kwargs):
"""
Equivalent of builtin `zip`.
@@ -85,7 +80,6 @@ def tzip(iter1, *iter2plus, **tqdm_kwargs):
yield i
-@builtin_iterable
def tmap(function, *sequences, **tqdm_kwargs):
"""
Equivalent of builtin `map`.
diff --git a/tqdm/contrib/concurrent.py b/tqdm/contrib/concurrent.py
index ccb5e12..cd81d62 100644
--- a/tqdm/contrib/concurrent.py
+++ b/tqdm/contrib/concurrent.py
@@ -1,32 +1,13 @@
"""
Thin wrappers around `concurrent.futures`.
"""
-from __future__ import absolute_import
-
from contextlib import contextmanager
+from operator import length_hint
+from os import cpu_count
from ..auto import tqdm as tqdm_auto
from ..std import TqdmWarning
-try:
- from operator import length_hint
-except ImportError:
- def length_hint(it, default=0):
- """Returns `len(it)`, falling back to `default`"""
- try:
- return len(it)
- except TypeError:
- return default
-try:
- from os import cpu_count
-except ImportError:
- try:
- from multiprocessing import cpu_count
- except ImportError:
- def cpu_count():
- return 4
-import sys
-
__author__ = {"github.com/": ["casperdcl"]}
__all__ = ['thread_map', 'process_map']
@@ -64,16 +45,10 @@ def _executor_map(PoolExecutor, fn, *iterables, **tqdm_kwargs):
chunksize = kwargs.pop("chunksize", 1)
lock_name = kwargs.pop("lock_name", "")
with ensure_lock(tqdm_class, lock_name=lock_name) as lk:
- pool_kwargs = {'max_workers': max_workers}
- sys_version = sys.version_info[:2]
- if sys_version >= (3, 7):
- # share lock in case workers are already using `tqdm`
- pool_kwargs.update(initializer=tqdm_class.set_lock, initargs=(lk,))
- map_args = {}
- if not (3, 0) < sys_version < (3, 5):
- map_args.update(chunksize=chunksize)
- with PoolExecutor(**pool_kwargs) as ex:
- return list(tqdm_class(ex.map(fn, *iterables, **map_args), **kwargs))
+ # share lock in case workers are already using `tqdm`
+ with PoolExecutor(max_workers=max_workers, initializer=tqdm_class.set_lock,
+ initargs=(lk,)) as ex:
+ return list(tqdm_class(ex.map(fn, *iterables, chunksize=chunksize), **kwargs))
def thread_map(fn, *iterables, **tqdm_kwargs):
diff --git a/tqdm/contrib/discord.py b/tqdm/contrib/discord.py
index 0edd35c..1e41308 100644
--- a/tqdm/contrib/discord.py
+++ b/tqdm/contrib/discord.py
@@ -6,10 +6,8 @@ Usage:
>>> for i in trange(10, token='{token}', channel_id='{channel_id}'):
... ...
-![screenshot](https://img.tqdm.ml/screenshot-discord.png)
+![screenshot](https://tqdm.github.io/img/screenshot-discord.png)
"""
-from __future__ import absolute_import
-
import logging
from os import getenv
@@ -19,7 +17,6 @@ except ImportError:
raise ImportError("Please `pip install disco-py`")
from ..auto import tqdm as tqdm_auto
-from ..utils import _range
from .utils_worker import MonoWorker
__author__ = {"github.com/": ["casperdcl"]}
@@ -113,11 +110,8 @@ class tqdm_discord(tqdm_auto):
def tdrange(*args, **kwargs):
- """
- A shortcut for `tqdm.contrib.discord.tqdm(xrange(*args), **kwargs)`.
- On Python3+, `range` is used instead of `xrange`.
- """
- return tqdm_discord(_range(*args), **kwargs)
+ """Shortcut for `tqdm.contrib.discord.tqdm(range(*args), **kwargs)`."""
+ return tqdm_discord(range(*args), **kwargs)
# Aliases
diff --git a/tqdm/contrib/itertools.py b/tqdm/contrib/itertools.py
index 5f22505..e67651a 100644
--- a/tqdm/contrib/itertools.py
+++ b/tqdm/contrib/itertools.py
@@ -1,8 +1,6 @@
"""
Thin wrappers around `itertools`.
"""
-from __future__ import absolute_import
-
import itertools
from ..auto import tqdm as tqdm_auto
diff --git a/tqdm/contrib/logging.py b/tqdm/contrib/logging.py
index cd9925e..b8eaec5 100644
--- a/tqdm/contrib/logging.py
+++ b/tqdm/contrib/logging.py
@@ -1,14 +1,12 @@
"""
Helper functionality for interoperability with stdlib `logging`.
"""
-from __future__ import absolute_import
-
import logging
import sys
from contextlib import contextmanager
try:
- from typing import Iterator, List, Optional, Type # pylint: disable=unused-import
+ from typing import Iterator, List, Optional, Type # noqa: F401
except ImportError:
pass
diff --git a/tqdm/contrib/slack.py b/tqdm/contrib/slack.py
index b478d92..d4c850c 100644
--- a/tqdm/contrib/slack.py
+++ b/tqdm/contrib/slack.py
@@ -6,10 +6,8 @@ Usage:
>>> for i in trange(10, token='{token}', channel='{channel}'):
... ...
-![screenshot](https://img.tqdm.ml/screenshot-slack.png)
+![screenshot](https://tqdm.github.io/img/screenshot-slack.png)
"""
-from __future__ import absolute_import
-
import logging
from os import getenv
@@ -19,7 +17,6 @@ except ImportError:
raise ImportError("Please `pip install slack-sdk`")
from ..auto import tqdm as tqdm_auto
-from ..utils import _range
from .utils_worker import MonoWorker
__author__ = {"github.com/": ["0x2b3bfa0", "casperdcl"]}
@@ -114,11 +111,8 @@ class tqdm_slack(tqdm_auto):
def tsrange(*args, **kwargs):
- """
- A shortcut for `tqdm.contrib.slack.tqdm(xrange(*args), **kwargs)`.
- On Python3+, `range` is used instead of `xrange`.
- """
- return tqdm_slack(_range(*args), **kwargs)
+ """Shortcut for `tqdm.contrib.slack.tqdm(range(*args), **kwargs)`."""
+ return tqdm_slack(range(*args), **kwargs)
# Aliases
diff --git a/tqdm/contrib/telegram.py b/tqdm/contrib/telegram.py
index 99cbe8c..cbeadf2 100644
--- a/tqdm/contrib/telegram.py
+++ b/tqdm/contrib/telegram.py
@@ -6,10 +6,8 @@ Usage:
>>> for i in trange(10, token='{token}', chat_id='{chat_id}'):
... ...
-![screenshot](https://img.tqdm.ml/screenshot-telegram.gif)
+![screenshot](https://tqdm.github.io/img/screenshot-telegram.gif)
"""
-from __future__ import absolute_import
-
from os import getenv
from warnings import warn
@@ -17,7 +15,6 @@ from requests import Session
from ..auto import tqdm as tqdm_auto
from ..std import TqdmWarning
-from ..utils import _range
from .utils_worker import MonoWorker
__author__ = {"github.com/": ["casperdcl"]}
@@ -147,11 +144,8 @@ class tqdm_telegram(tqdm_auto):
def ttgrange(*args, **kwargs):
- """
- A shortcut for `tqdm.contrib.telegram.tqdm(xrange(*args), **kwargs)`.
- On Python3+, `range` is used instead of `xrange`.
- """
- return tqdm_telegram(_range(*args), **kwargs)
+ """Shortcut for `tqdm.contrib.telegram.tqdm(range(*args), **kwargs)`."""
+ return tqdm_telegram(range(*args), **kwargs)
# Aliases
diff --git a/tqdm/contrib/utils_worker.py b/tqdm/contrib/utils_worker.py
index 17adda6..2a03a2a 100644
--- a/tqdm/contrib/utils_worker.py
+++ b/tqdm/contrib/utils_worker.py
@@ -1,8 +1,6 @@
"""
IO/concurrency helpers for `tqdm.contrib`.
"""
-from __future__ import absolute_import
-
from collections import deque
from concurrent.futures import ThreadPoolExecutor
diff --git a/tqdm/dask.py b/tqdm/dask.py
index 6fc7504..af9926a 100644
--- a/tqdm/dask.py
+++ b/tqdm/dask.py
@@ -1,5 +1,3 @@
-from __future__ import absolute_import
-
from functools import partial
from dask.callbacks import Callback
diff --git a/tqdm/gui.py b/tqdm/gui.py
index 4612701..8bab6ac 100644
--- a/tqdm/gui.py
+++ b/tqdm/gui.py
@@ -8,16 +8,14 @@ Usage:
"""
# future division is important to divide integers and get as
# a result precise floating numbers (instead of truncated int)
-from __future__ import absolute_import, division
-
import re
from warnings import warn
# to inherit from the tqdm class
from .std import TqdmExperimentalWarning
from .std import tqdm as std_tqdm
+
# import compatibility functions and utilities
-from .utils import _range
__author__ = {"github.com/": ["casperdcl", "lrq3000"]}
__all__ = ['tqdm_gui', 'tgrange', 'tqdm', 'trange']
@@ -173,17 +171,14 @@ class tqdm_gui(std_tqdm): # pragma: no cover
"{bar}", "<bar/>")
msg = self.format_meter(**d)
if '<bar/>' in msg:
- msg = "".join(re.split(r'\|?<bar/>\|?', msg, 1))
+ msg = "".join(re.split(r'\|?<bar/>\|?', msg, maxsplit=1))
ax.set_title(msg, fontname="DejaVu Sans Mono", fontsize=11)
self.plt.pause(1e-9)
def tgrange(*args, **kwargs):
- """
- A shortcut for `tqdm.gui.tqdm(xrange(*args), **kwargs)`.
- On Python3+, `range` is used instead of `xrange`.
- """
- return tqdm_gui(_range(*args), **kwargs)
+ """Shortcut for `tqdm.gui.tqdm(range(*args), **kwargs)`."""
+ return tqdm_gui(range(*args), **kwargs)
# Aliases
diff --git a/tqdm/keras.py b/tqdm/keras.py
index 523e62e..cce9467 100644
--- a/tqdm/keras.py
+++ b/tqdm/keras.py
@@ -1,5 +1,3 @@
-from __future__ import absolute_import, division
-
from copy import copy
from functools import partial
@@ -96,7 +94,7 @@ class TqdmCallback(keras.callbacks.Callback):
raise KeyError('Unknown verbosity')
def on_train_end(self, *_, **__):
- if self.verbose:
+ if hasattr(self, 'batch_bar'):
self.batch_bar.close()
self.epoch_bar.close()
diff --git a/tqdm/notebook.py b/tqdm/notebook.py
index ffd0947..6ee43a6 100644
--- a/tqdm/notebook.py
+++ b/tqdm/notebook.py
@@ -7,18 +7,14 @@ Usage:
>>> for i in trange(10):
... ...
"""
-# future division is important to divide integers and get as
-# a result precise floating numbers (instead of truncated int)
-from __future__ import absolute_import, division
-
# import compatibility functions and utilities
import re
import sys
+from html import escape
from weakref import proxy
# to inherit from the tqdm class
from .std import tqdm as std_tqdm
-from .utils import _range
if True: # pragma: no cover
# import IPython/Jupyter base widget and display utilities
@@ -63,12 +59,6 @@ if True: # pragma: no cover
except ImportError:
pass
- # HTML encoding
- try: # Py3
- from html import escape
- except ImportError: # Py2
- from cgi import escape
-
__author__ = {"github.com/": ["lrq3000", "casperdcl", "alexanderkuk"]}
__all__ = ['tqdm_notebook', 'tnrange', 'tqdm', 'trange']
WARN_NOIPYW = ("IProgress not found. Please update jupyter and ipywidgets."
@@ -167,9 +157,10 @@ class tqdm_notebook(std_tqdm):
pbar.value = self.n
if msg:
+ msg = msg.replace(' ', u'\u2007') # fix html space padding
# html escape special characters (like '&')
if '<bar/>' in msg:
- left, right = map(escape, re.split(r'\|?<bar/>\|?', msg, 1))
+ left, right = map(escape, re.split(r'\|?<bar/>\|?', msg, maxsplit=1))
else:
left, right = '', escape(msg)
@@ -317,11 +308,8 @@ class tqdm_notebook(std_tqdm):
def tnrange(*args, **kwargs):
- """
- A shortcut for `tqdm.notebook.tqdm(xrange(*args), **kwargs)`.
- On Python3+, `range` is used instead of `xrange`.
- """
- return tqdm_notebook(_range(*args), **kwargs)
+ """Shortcut for `tqdm.notebook.tqdm(range(*args), **kwargs)`."""
+ return tqdm_notebook(range(*args), **kwargs)
# Aliases
diff --git a/tqdm/rich.py b/tqdm/rich.py
index 69893ff..00e1ddf 100644
--- a/tqdm/rich.py
+++ b/tqdm/rich.py
@@ -6,8 +6,6 @@ Usage:
>>> for i in trange(10):
... ...
"""
-from __future__ import absolute_import
-
from warnings import warn
from rich.progress import (
@@ -15,7 +13,6 @@ from rich.progress import (
from .std import TqdmExperimentalWarning
from .std import tqdm as std_tqdm
-from .utils import _range
__author__ = {"github.com/": ["casperdcl"]}
__all__ = ['tqdm_rich', 'trrange', 'tqdm', 'trange']
@@ -144,11 +141,8 @@ class tqdm_rich(std_tqdm): # pragma: no cover
def trrange(*args, **kwargs):
- """
- A shortcut for `tqdm.rich.tqdm(xrange(*args), **kwargs)`.
- On Python3+, `range` is used instead of `xrange`.
- """
- return tqdm_rich(_range(*args), **kwargs)
+ """Shortcut for `tqdm.rich.tqdm(range(*args), **kwargs)`."""
+ return tqdm_rich(range(*args), **kwargs)
# Aliases
diff --git a/tqdm/std.py b/tqdm/std.py
index 5f9dcca..e58fdca 100644
--- a/tqdm/std.py
+++ b/tqdm/std.py
@@ -7,12 +7,10 @@ Usage:
>>> for i in trange(10):
... ...
"""
-from __future__ import absolute_import, division
-
import sys
from collections import OrderedDict, defaultdict
from contextlib import contextmanager
-from datetime import datetime, timedelta
+from datetime import datetime, timedelta, timezone
from numbers import Number
from time import time
from warnings import warn
@@ -21,8 +19,8 @@ from weakref import WeakSet
from ._monitor import TMonitor
from .utils import (
CallbackIOWrapper, Comparable, DisableOnWriteError, FormatReplace, SimpleTextIOWrapper,
- _basestring, _is_ascii, _range, _screen_shape_wrapper, _supports_unicode, _term_move_up,
- _unich, _unicode, disp_len, disp_trim)
+ _is_ascii, _screen_shape_wrapper, _supports_unicode, _term_move_up, disp_len, disp_trim,
+ envwrap)
__author__ = "https://github.com/tqdm/tqdm#contributions"
__all__ = ['tqdm', 'trange',
@@ -144,7 +142,7 @@ class Bar(object):
+ `b`: blank (`charset=" "` override)
"""
ASCII = " 123456789#"
- UTF = u" " + u''.join(map(_unich, range(0x258F, 0x2587, -1)))
+ UTF = u" " + u''.join(map(chr, range(0x258F, 0x2587, -1)))
BLANK = " "
COLOUR_RESET = '\x1b[0m'
COLOUR_RGB = '\x1b[38;2;%d;%d;%dm'
@@ -249,6 +247,120 @@ class tqdm(Comparable):
Decorate an iterable object, returning an iterator which acts exactly
like the original iterable, but prints a dynamically updating
progressbar every time a value is requested.
+
+ Parameters
+ ----------
+ iterable : iterable, optional
+ Iterable to decorate with a progressbar.
+ Leave blank to manually manage the updates.
+ desc : str, optional
+ Prefix for the progressbar.
+ total : int or float, optional
+ The number of expected iterations. If unspecified,
+ len(iterable) is used if possible. If float("inf") or as a last
+ resort, only basic progress statistics are displayed
+ (no ETA, no progressbar).
+ If `gui` is True and this parameter needs subsequent updating,
+ specify an initial arbitrary large positive number,
+ e.g. 9e9.
+ leave : bool, optional
+ If [default: True], keeps all traces of the progressbar
+ upon termination of iteration.
+ If `None`, will leave only if `position` is `0`.
+ file : `io.TextIOWrapper` or `io.StringIO`, optional
+ Specifies where to output the progress messages
+ (default: sys.stderr). Uses `file.write(str)` and `file.flush()`
+ methods. For encoding, see `write_bytes`.
+ ncols : int, optional
+ The width of the entire output message. If specified,
+ dynamically resizes the progressbar to stay within this bound.
+ If unspecified, attempts to use environment width. The
+ fallback is a meter width of 10 and no limit for the counter and
+ statistics. If 0, will not print any meter (only stats).
+ mininterval : float, optional
+ Minimum progress display update interval [default: 0.1] seconds.
+ maxinterval : float, optional
+ Maximum progress display update interval [default: 10] seconds.
+ Automatically adjusts `miniters` to correspond to `mininterval`
+ after long display update lag. Only works if `dynamic_miniters`
+ or monitor thread is enabled.
+ miniters : int or float, optional
+ Minimum progress display update interval, in iterations.
+ If 0 and `dynamic_miniters`, will automatically adjust to equal
+ `mininterval` (more CPU efficient, good for tight loops).
+ If > 0, will skip display of specified number of iterations.
+ Tweak this and `mininterval` to get very efficient loops.
+ If your progress is erratic with both fast and slow iterations
+ (network, skipping items, etc) you should set miniters=1.
+ ascii : bool or str, optional
+ If unspecified or False, use unicode (smooth blocks) to fill
+ the meter. The fallback is to use ASCII characters " 123456789#".
+ disable : bool, optional
+ Whether to disable the entire progressbar wrapper
+ [default: False]. If set to None, disable on non-TTY.
+ unit : str, optional
+ String that will be used to define the unit of each iteration
+ [default: it].
+ unit_scale : bool or int or float, optional
+ If 1 or True, the number of iterations will be reduced/scaled
+ automatically and a metric prefix following the
+ International System of Units standard will be added
+ (kilo, mega, etc.) [default: False]. If any other non-zero
+ number, will scale `total` and `n`.
+ dynamic_ncols : bool, optional
+ If set, constantly alters `ncols` and `nrows` to the
+ environment (allowing for window resizes) [default: False].
+ smoothing : float, optional
+ Exponential moving average smoothing factor for speed estimates
+ (ignored in GUI mode). Ranges from 0 (average speed) to 1
+ (current/instantaneous speed) [default: 0.3].
+ bar_format : str, optional
+ Specify a custom bar string formatting. May impact performance.
+ [default: '{l_bar}{bar}{r_bar}'], where
+ l_bar='{desc}: {percentage:3.0f}%|' and
+ r_bar='| {n_fmt}/{total_fmt} [{elapsed}<{remaining}, '
+ '{rate_fmt}{postfix}]'
+ Possible vars: l_bar, bar, r_bar, n, n_fmt, total, total_fmt,
+ percentage, elapsed, elapsed_s, ncols, nrows, desc, unit,
+ rate, rate_fmt, rate_noinv, rate_noinv_fmt,
+ rate_inv, rate_inv_fmt, postfix, unit_divisor,
+ remaining, remaining_s, eta.
+ Note that a trailing ": " is automatically removed after {desc}
+ if the latter is empty.
+ initial : int or float, optional
+ The initial counter value. Useful when restarting a progress
+ bar [default: 0]. If using float, consider specifying `{n:.3f}`
+ or similar in `bar_format`, or specifying `unit_scale`.
+ position : int, optional
+ Specify the line offset to print this bar (starting from 0)
+ Automatic if unspecified.
+ Useful to manage multiple bars at once (eg, from threads).
+ postfix : dict or *, optional
+ Specify additional stats to display at the end of the bar.
+ Calls `set_postfix(**postfix)` if possible (dict).
+ unit_divisor : float, optional
+ [default: 1000], ignored unless `unit_scale` is True.
+ write_bytes : bool, optional
+ Whether to write bytes. If (default: False) will write unicode.
+ lock_args : tuple, optional
+ Passed to `refresh` for intermediate output
+ (initialisation, iterating, and updating).
+ nrows : int, optional
+ The screen height. If specified, hides nested bars outside this
+ bound. If unspecified, attempts to use environment height.
+ The fallback is 20.
+ colour : str, optional
+ Bar colour (e.g. 'green', '#00ff00').
+ delay : float, optional
+ Don't display until [default: 0] seconds have elapsed.
+ gui : bool, optional
+ WARNING: internal parameter - do not use.
+ Use tqdm.gui.tqdm(...) instead. If set, will attempt to use
+ matplotlib animations for a graphical output [default: False].
+
+ Returns
+ -------
+ out : decorated iterator.
"""
monitor_interval = 10 # set to 0 to disable the thread
@@ -279,11 +391,11 @@ class tqdm(Comparable):
if abs(num) < 999.5:
if abs(num) < 99.95:
if abs(num) < 9.995:
- return '{0:1.2f}'.format(num) + unit + suffix
- return '{0:2.1f}'.format(num) + unit + suffix
- return '{0:3.0f}'.format(num) + unit + suffix
+ return f'{num:1.2f}{unit}{suffix}'
+ return f'{num:2.1f}{unit}{suffix}'
+ return f'{num:3.0f}{unit}{suffix}'
num /= divisor
- return '{0:3.1f}Y'.format(num) + suffix
+ return f'{num:3.1f}Y{suffix}'
@staticmethod
def format_interval(t):
@@ -302,10 +414,7 @@ class tqdm(Comparable):
"""
mins, s = divmod(int(t), 60)
h, m = divmod(mins, 60)
- if h:
- return '{0:d}:{1:02d}:{2:02d}'.format(h, m, s)
- else:
- return '{0:02d}:{1:02d}'.format(m, s)
+ return f'{h:d}:{m:02d}:{s:02d}' if h else f'{m:02d}:{s:02d}'
@staticmethod
def format_num(n):
@@ -322,7 +431,7 @@ class tqdm(Comparable):
out : str
Formatted number.
"""
- f = '{0:.3g}'.format(n).replace('+0', '+').replace('-0', '-')
+ f = f'{n:.3g}'.replace('e+0', 'e+').replace('e-0', 'e-')
n = str(n)
return f if len(f) < len(n) else n
@@ -340,7 +449,7 @@ class tqdm(Comparable):
getattr(sys.stdout, 'flush', lambda: None)()
def fp_write(s):
- fp.write(_unicode(s))
+ fp.write(str(s))
fp_flush()
last_len = [0]
@@ -442,10 +551,10 @@ class tqdm(Comparable):
rate = (n - initial) / elapsed
inv_rate = 1 / rate if rate else None
format_sizeof = tqdm.format_sizeof
- rate_noinv_fmt = ((format_sizeof(rate) if unit_scale else
- '{0:5.2f}'.format(rate)) if rate else '?') + unit + '/s'
+ rate_noinv_fmt = ((format_sizeof(rate) if unit_scale else f'{rate:5.2f}')
+ if rate else '?') + unit + '/s'
rate_inv_fmt = (
- (format_sizeof(inv_rate) if unit_scale else '{0:5.2f}'.format(inv_rate))
+ (format_sizeof(inv_rate) if unit_scale else f'{inv_rate:5.2f}')
if inv_rate else '?') + 's/' + unit
rate_fmt = rate_inv_fmt if inv_rate and inv_rate > 1 else rate_noinv_fmt
@@ -465,7 +574,7 @@ class tqdm(Comparable):
remaining_str = tqdm.format_interval(remaining) if rate else '?'
try:
eta_dt = (datetime.now() + timedelta(seconds=remaining)
- if rate and total else datetime.utcfromtimestamp(0))
+ if rate and total else datetime.fromtimestamp(0, timezone.utc))
except OverflowError:
eta_dt = datetime.max
@@ -477,26 +586,25 @@ class tqdm(Comparable):
else:
l_bar = ''
- r_bar = '| {0}/{1} [{2}<{3}, {4}{5}]'.format(
- n_fmt, total_fmt, elapsed_str, remaining_str, rate_fmt, postfix)
+ r_bar = f'| {n_fmt}/{total_fmt} [{elapsed_str}<{remaining_str}, {rate_fmt}{postfix}]'
# Custom bar formatting
# Populate a dict with all available progress indicators
- format_dict = dict(
+ format_dict = {
# slight extension of self.format_dict
- n=n, n_fmt=n_fmt, total=total, total_fmt=total_fmt,
- elapsed=elapsed_str, elapsed_s=elapsed,
- ncols=ncols, desc=prefix or '', unit=unit,
- rate=inv_rate if inv_rate and inv_rate > 1 else rate,
- rate_fmt=rate_fmt, rate_noinv=rate,
- rate_noinv_fmt=rate_noinv_fmt, rate_inv=inv_rate,
- rate_inv_fmt=rate_inv_fmt,
- postfix=postfix, unit_divisor=unit_divisor,
- colour=colour,
+ 'n': n, 'n_fmt': n_fmt, 'total': total, 'total_fmt': total_fmt,
+ 'elapsed': elapsed_str, 'elapsed_s': elapsed,
+ 'ncols': ncols, 'desc': prefix or '', 'unit': unit,
+ 'rate': inv_rate if inv_rate and inv_rate > 1 else rate,
+ 'rate_fmt': rate_fmt, 'rate_noinv': rate,
+ 'rate_noinv_fmt': rate_noinv_fmt, 'rate_inv': inv_rate,
+ 'rate_inv_fmt': rate_inv_fmt,
+ 'postfix': postfix, 'unit_divisor': unit_divisor,
+ 'colour': colour,
# plus more useful definitions
- remaining=remaining_str, remaining_s=remaining,
- l_bar=l_bar, r_bar=r_bar, eta=eta_dt,
- **extra_kwargs)
+ 'remaining': remaining_str, 'remaining_s': remaining,
+ 'l_bar': l_bar, 'r_bar': r_bar, 'eta': eta_dt,
+ **extra_kwargs}
# total is known: we can predict some stats
if total:
@@ -504,7 +612,7 @@ class tqdm(Comparable):
frac = n / total
percentage = frac * 100
- l_bar += '{0:3.0f}%|'.format(percentage)
+ l_bar += f'{percentage:3.0f}%|'
if ncols == 0:
return l_bar[:-1] + r_bar[1:]
@@ -513,21 +621,16 @@ class tqdm(Comparable):
if bar_format:
format_dict.update(percentage=percentage)
- # auto-remove colon for empty `desc`
+ # auto-remove colon for empty `{desc}`
if not prefix:
bar_format = bar_format.replace("{desc}: ", '')
else:
bar_format = "{l_bar}{bar}{r_bar}"
full_bar = FormatReplace()
- try:
- nobar = bar_format.format(bar=full_bar, **format_dict)
- except UnicodeEncodeError:
- bar_format = _unicode(bar_format)
- nobar = bar_format.format(bar=full_bar, **format_dict)
+ nobar = bar_format.format(bar=full_bar, **format_dict)
if not full_bar.format_called:
- # no {bar}, we can just format and return
- return nobar
+ return nobar # no `{bar}`; nothing else to do
# Formatting progress bar space available for bar's display
full_bar = Bar(frac,
@@ -535,7 +638,7 @@ class tqdm(Comparable):
charset=Bar.ASCII if ascii is True else ascii or Bar.UTF,
colour=colour)
if not _is_ascii(full_bar.charset) and _is_ascii(bar_format):
- bar_format = _unicode(bar_format)
+ bar_format = str(bar_format)
res = bar_format.format(bar=full_bar, **format_dict)
return disp_trim(res, ncols) if ncols else res
@@ -554,8 +657,8 @@ class tqdm(Comparable):
return disp_trim(res, ncols) if ncols else res
else:
# no total: no progressbar, ETA, just progress stats
- return '{0}{1}{2} [{3}, {4}{5}]'.format(
- (prefix + ": ") if prefix else '', n_fmt, unit, elapsed_str, rate_fmt, postfix)
+ return (f'{(prefix + ": ") if prefix else ""}'
+ f'{n_fmt}{unit} [{elapsed_str}, {rate_fmt}{postfix}]')
def __new__(cls, *_, **__):
instance = object.__new__(cls)
@@ -827,6 +930,8 @@ class tqdm(Comparable):
DataFrame.progress_apply = inner_generator()
DataFrameGroupBy.progress_apply = inner_generator()
DataFrame.progress_applymap = inner_generator('applymap')
+ DataFrame.progress_map = inner_generator('map')
+ DataFrameGroupBy.progress_map = inner_generator('map')
if Panel is not None:
Panel.progress_apply = inner_generator()
@@ -843,133 +948,17 @@ class tqdm(Comparable):
elif _Rolling_and_Expanding is not None:
_Rolling_and_Expanding.progress_apply = inner_generator()
+ # override defaults via env vars
+ @envwrap("TQDM_", is_method=True, types={'total': float, 'ncols': int, 'miniters': float,
+ 'position': int, 'nrows': int})
def __init__(self, iterable=None, desc=None, total=None, leave=True, file=None,
ncols=None, mininterval=0.1, maxinterval=10.0, miniters=None,
ascii=None, disable=False, unit='it', unit_scale=False,
dynamic_ncols=False, smoothing=0.3, bar_format=None, initial=0,
- position=None, postfix=None, unit_divisor=1000, write_bytes=None,
- lock_args=None, nrows=None, colour=None, delay=0, gui=False,
+ position=None, postfix=None, unit_divisor=1000, write_bytes=False,
+ lock_args=None, nrows=None, colour=None, delay=0.0, gui=False,
**kwargs):
- """
- Parameters
- ----------
- iterable : iterable, optional
- Iterable to decorate with a progressbar.
- Leave blank to manually manage the updates.
- desc : str, optional
- Prefix for the progressbar.
- total : int or float, optional
- The number of expected iterations. If unspecified,
- len(iterable) is used if possible. If float("inf") or as a last
- resort, only basic progress statistics are displayed
- (no ETA, no progressbar).
- If `gui` is True and this parameter needs subsequent updating,
- specify an initial arbitrary large positive number,
- e.g. 9e9.
- leave : bool, optional
- If [default: True], keeps all traces of the progressbar
- upon termination of iteration.
- If `None`, will leave only if `position` is `0`.
- file : `io.TextIOWrapper` or `io.StringIO`, optional
- Specifies where to output the progress messages
- (default: sys.stderr). Uses `file.write(str)` and `file.flush()`
- methods. For encoding, see `write_bytes`.
- ncols : int, optional
- The width of the entire output message. If specified,
- dynamically resizes the progressbar to stay within this bound.
- If unspecified, attempts to use environment width. The
- fallback is a meter width of 10 and no limit for the counter and
- statistics. If 0, will not print any meter (only stats).
- mininterval : float, optional
- Minimum progress display update interval [default: 0.1] seconds.
- maxinterval : float, optional
- Maximum progress display update interval [default: 10] seconds.
- Automatically adjusts `miniters` to correspond to `mininterval`
- after long display update lag. Only works if `dynamic_miniters`
- or monitor thread is enabled.
- miniters : int or float, optional
- Minimum progress display update interval, in iterations.
- If 0 and `dynamic_miniters`, will automatically adjust to equal
- `mininterval` (more CPU efficient, good for tight loops).
- If > 0, will skip display of specified number of iterations.
- Tweak this and `mininterval` to get very efficient loops.
- If your progress is erratic with both fast and slow iterations
- (network, skipping items, etc) you should set miniters=1.
- ascii : bool or str, optional
- If unspecified or False, use unicode (smooth blocks) to fill
- the meter. The fallback is to use ASCII characters " 123456789#".
- disable : bool, optional
- Whether to disable the entire progressbar wrapper
- [default: False]. If set to None, disable on non-TTY.
- unit : str, optional
- String that will be used to define the unit of each iteration
- [default: it].
- unit_scale : bool or int or float, optional
- If 1 or True, the number of iterations will be reduced/scaled
- automatically and a metric prefix following the
- International System of Units standard will be added
- (kilo, mega, etc.) [default: False]. If any other non-zero
- number, will scale `total` and `n`.
- dynamic_ncols : bool, optional
- If set, constantly alters `ncols` and `nrows` to the
- environment (allowing for window resizes) [default: False].
- smoothing : float, optional
- Exponential moving average smoothing factor for speed estimates
- (ignored in GUI mode). Ranges from 0 (average speed) to 1
- (current/instantaneous speed) [default: 0.3].
- bar_format : str, optional
- Specify a custom bar string formatting. May impact performance.
- [default: '{l_bar}{bar}{r_bar}'], where
- l_bar='{desc}: {percentage:3.0f}%|' and
- r_bar='| {n_fmt}/{total_fmt} [{elapsed}<{remaining}, '
- '{rate_fmt}{postfix}]'
- Possible vars: l_bar, bar, r_bar, n, n_fmt, total, total_fmt,
- percentage, elapsed, elapsed_s, ncols, nrows, desc, unit,
- rate, rate_fmt, rate_noinv, rate_noinv_fmt,
- rate_inv, rate_inv_fmt, postfix, unit_divisor,
- remaining, remaining_s, eta.
- Note that a trailing ": " is automatically removed after {desc}
- if the latter is empty.
- initial : int or float, optional
- The initial counter value. Useful when restarting a progress
- bar [default: 0]. If using float, consider specifying `{n:.3f}`
- or similar in `bar_format`, or specifying `unit_scale`.
- position : int, optional
- Specify the line offset to print this bar (starting from 0)
- Automatic if unspecified.
- Useful to manage multiple bars at once (eg, from threads).
- postfix : dict or *, optional
- Specify additional stats to display at the end of the bar.
- Calls `set_postfix(**postfix)` if possible (dict).
- unit_divisor : float, optional
- [default: 1000], ignored unless `unit_scale` is True.
- write_bytes : bool, optional
- If (default: None) and `file` is unspecified,
- bytes will be written in Python 2. If `True` will also write
- bytes. In all other cases will default to unicode.
- lock_args : tuple, optional
- Passed to `refresh` for intermediate output
- (initialisation, iterating, and updating).
- nrows : int, optional
- The screen height. If specified, hides nested bars outside this
- bound. If unspecified, attempts to use environment height.
- The fallback is 20.
- colour : str, optional
- Bar colour (e.g. 'green', '#00ff00').
- delay : float, optional
- Don't display until [default: 0] seconds have elapsed.
- gui : bool, optional
- WARNING: internal parameter - do not use.
- Use tqdm.gui.tqdm(...) instead. If set, will attempt to use
- matplotlib animations for a graphical output [default: False].
-
- Returns
- -------
- out : decorated iterator.
- """
- if write_bytes is None:
- write_bytes = file is None and sys.version_info < (3,)
-
+ """see tqdm.tqdm for arguments"""
if file is None:
file = sys.stderr
@@ -1051,7 +1040,7 @@ class tqdm(Comparable):
if bar_format and ascii is not True and not _is_ascii(ascii):
# Convert bar format into unicode since terminal uses unicode
- bar_format = _unicode(bar_format)
+ bar_format = str(bar_format)
if smoothing is None:
smoothing = 0
@@ -1120,9 +1109,6 @@ class tqdm(Comparable):
raise TypeError('bool() undefined when iterable == total == None')
return bool(self.iterable)
- def __nonzero__(self):
- return self.__bool__()
-
def __len__(self):
return (
self.total if self.iterable is None
@@ -1298,7 +1284,7 @@ class tqdm(Comparable):
# annoyingly, _supports_unicode isn't good enough
def fp_write(s):
- self.fp.write(_unicode(s))
+ self.fp.write(str(s))
try:
fp_write('')
@@ -1435,7 +1421,7 @@ class tqdm(Comparable):
if isinstance(postfix[key], Number):
postfix[key] = self.format_num(postfix[key])
# Else for any other type, try to get the string conversion
- elif not isinstance(postfix[key], _basestring):
+ elif not isinstance(postfix[key], str):
postfix[key] = str(postfix[key])
# Else if it's a string, don't need to preprocess anything
# Stitch together to get the final postfix
@@ -1454,7 +1440,7 @@ class tqdm(Comparable):
def moveto(self, n):
# TODO: private method
- self.fp.write(_unicode('\n' * n + _term_move_up() * -n))
+ self.fp.write('\n' * n + _term_move_up() * -n)
getattr(self.fp, 'flush', lambda: None)()
@property
@@ -1534,8 +1520,5 @@ class tqdm(Comparable):
def trange(*args, **kwargs):
- """
- A shortcut for tqdm(xrange(*args), **kwargs).
- On Python3+ range is used instead of xrange.
- """
- return tqdm(_range(*args), **kwargs)
+ """Shortcut for tqdm(range(*args), **kwargs)."""
+ return tqdm(range(*args), **kwargs)
diff --git a/tqdm/tk.py b/tqdm/tk.py
index 92adb51..dfebf5c 100644
--- a/tqdm/tk.py
+++ b/tqdm/tk.py
@@ -6,22 +6,14 @@ Usage:
>>> for i in trange(10):
... ...
"""
-from __future__ import absolute_import, division
-
import re
import sys
+import tkinter
+import tkinter.ttk as ttk
from warnings import warn
-try:
- import tkinter
- import tkinter.ttk as ttk
-except ImportError:
- import Tkinter as tkinter
- import ttk as ttk
-
from .std import TqdmExperimentalWarning, TqdmWarning
from .std import tqdm as std_tqdm
-from .utils import _range
__author__ = {"github.com/": ["richardsheridan", "casperdcl"]}
__all__ = ['tqdm_tk', 'ttkrange', 'tqdm', 'trange']
@@ -143,7 +135,7 @@ class tqdm_tk(std_tqdm): # pragma: no cover
"{bar}", "<bar/>")
msg = self.format_meter(**d)
if '<bar/>' in msg:
- msg = "".join(re.split(r'\|?<bar/>\|?', msg, 1))
+ msg = "".join(re.split(r'\|?<bar/>\|?', msg, maxsplit=1))
self._tk_text_var.set(msg)
if not self._tk_dispatching:
self._tk_window.update()
@@ -195,11 +187,8 @@ class tqdm_tk(std_tqdm): # pragma: no cover
def ttkrange(*args, **kwargs):
- """
- A shortcut for `tqdm.tk.tqdm(xrange(*args), **kwargs)`.
- On Python3+, `range` is used instead of `xrange`.
- """
- return tqdm_tk(_range(*args), **kwargs)
+ """Shortcut for `tqdm.tk.tqdm(range(*args), **kwargs)`."""
+ return tqdm_tk(range(*args), **kwargs)
# Aliases
diff --git a/tqdm/tqdm.1 b/tqdm/tqdm.1
index 0533198..b90ab4b 100644
--- a/tqdm/tqdm.1
+++ b/tqdm/tqdm.1
@@ -204,10 +204,8 @@ float, optional.
.TP
.B \-\-write\-bytes
bool, optional.
-If (default: None) and \f[C]file\f[] is unspecified, bytes will be
-written in Python 2.
-If \f[C]True\f[] will also write bytes.
-In all other cases will default to unicode.
+Whether to write bytes.
+If (default: False) will write unicode.
.RS
.RE
.TP
diff --git a/tqdm/utils.py b/tqdm/utils.py
index 0632b8d..9883fda 100644
--- a/tqdm/utils.py
+++ b/tqdm/utils.py
@@ -4,31 +4,14 @@ General helpers required for `tqdm.std`.
import os
import re
import sys
-from functools import wraps
+from functools import partial, partialmethod, wraps
+from inspect import signature
+# TODO consider using wcswidth third-party package for 0-width characters
+from unicodedata import east_asian_width
from warnings import warn
from weakref import proxy
-# py2/3 compat
-try:
- _range = xrange
-except NameError:
- _range = range
-
-try:
- _unich = unichr
-except NameError:
- _unich = chr
-
-try:
- _unicode = unicode
-except NameError:
- _unicode = str
-
-try:
- _basestring = basestring
-except NameError:
- _basestring = str
-
+_range, _unich, _unicode, _basestring = range, chr, str, str
CUR_OS = sys.platform
IS_WIN = any(CUR_OS.startswith(i) for i in ['win32', 'cygwin'])
IS_NIX = any(CUR_OS.startswith(i) for i in ['aix', 'linux', 'darwin'])
@@ -48,10 +31,78 @@ else:
colorama.init()
+def envwrap(prefix, types=None, is_method=False):
+ """
+ Override parameter defaults via `os.environ[prefix + param_name]`.
+ Maps UPPER_CASE env vars map to lower_case param names.
+ camelCase isn't supported (because Windows ignores case).
+
+ Precedence (highest first):
+
+ - call (`foo(a=3)`)
+ - environ (`FOO_A=2`)
+ - signature (`def foo(a=1)`)
+
+ Parameters
+ ----------
+ prefix : str
+ Env var prefix, e.g. "FOO_"
+ types : dict, optional
+ Fallback mappings `{'param_name': type, ...}` if types cannot be
+ inferred from function signature.
+ Consider using `types=collections.defaultdict(lambda: ast.literal_eval)`.
+ is_method : bool, optional
+ Whether to use `functools.partialmethod`. If (default: False) use `functools.partial`.
+
+ Examples
+ --------
+ ```
+ $ cat foo.py
+ from tqdm.utils import envwrap
+ @envwrap("FOO_")
+ def test(a=1, b=2, c=3):
+ print(f"received: a={a}, b={b}, c={c}")
+
+ $ FOO_A=42 FOO_C=1337 python -c 'import foo; foo.test(c=99)'
+ received: a=42, b=2, c=99
+ ```
+ """
+ if types is None:
+ types = {}
+ i = len(prefix)
+ env_overrides = {k[i:].lower(): v for k, v in os.environ.items() if k.startswith(prefix)}
+ part = partialmethod if is_method else partial
+
+ def wrap(func):
+ params = signature(func).parameters
+ # ignore unknown env vars
+ overrides = {k: v for k, v in env_overrides.items() if k in params}
+ # infer overrides' `type`s
+ for k in overrides:
+ param = params[k]
+ if param.annotation is not param.empty: # typehints
+ for typ in getattr(param.annotation, '__args__', (param.annotation,)):
+ try:
+ overrides[k] = typ(overrides[k])
+ except Exception:
+ pass
+ else:
+ break
+ elif param.default is not None: # type of default value
+ overrides[k] = type(param.default)(overrides[k])
+ else:
+ try: # `types` fallback
+ overrides[k] = types[k](overrides[k])
+ except KeyError: # keep unconverted (`str`)
+ pass
+ return part(func, **overrides)
+ return wrap
+
+
class FormatReplace(object):
"""
>>> a = FormatReplace('something')
- >>> "{:5d}".format(a)
+ >>> f"{a:5d}"
'something'
""" # NOQA: P102
def __init__(self, replace=''):
@@ -320,14 +371,8 @@ def _term_move_up(): # pragma: no cover
return '' if (os.name == 'nt') and (colorama is None) else '\x1b[A'
-try:
- # TODO consider using wcswidth third-party package for 0-width characters
- from unicodedata import east_asian_width
-except ImportError:
- _text_width = len
-else:
- def _text_width(s):
- return sum(2 if east_asian_width(ch) in 'FW' else 1 for ch in _unicode(s))
+def _text_width(s):
+ return sum(2 if east_asian_width(ch) in 'FW' else 1 for ch in str(s))
def disp_len(data):