Merging upstream version 4.66.2.
Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
parent
ec03e12832
commit
6759e100fe
61 changed files with 917 additions and 4364 deletions
|
@ -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]
|
||||
|
|
|
@ -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:
|
||||
|
|
12
DEMO.ipynb
12
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",
|
||||
"-|-"
|
||||
]
|
||||
},
|
||||
|
|
4
LICENCE
4
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
|
||||
|
|
26
Makefile
26
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
|
||||
|
|
68
README.rst
68
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
|
||||
|
|
|
@ -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`
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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')
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
128
pyproject.toml
128
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
|
||||
|
|
159
setup.cfg
159
setup.cfg
|
@ -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
|
||||
|
16
setup.py
16
setup.py
|
@ -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)
|
|
@ -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")
|
||||
|
|
|
@ -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))
|
|
@ -1,11 +1,129 @@
|
|||
"""Tests `tqdm.asyncio` on `python>=3.7`."""
|
||||
import sys
|
||||
"""Tests `tqdm.asyncio`."""
|
||||
import asyncio
|
||||
from functools import partial
|
||||
from sys import platform
|
||||
from time import time
|
||||
|
||||
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:
|
||||
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))
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
"""
|
||||
Tests for `tqdm.contrib`.
|
||||
"""
|
||||
import sys
|
||||
|
||||
import pytest
|
||||
|
||||
from tqdm import tqdm
|
||||
|
@ -47,9 +45,6 @@ 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))
|
||||
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
from __future__ import division
|
||||
|
||||
from time import sleep
|
||||
|
||||
from .tests_tqdm import importorskip, mark
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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,7 +138,6 @@ 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
|
||||
|
||||
|
||||
|
@ -151,12 +145,8 @@ 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)
|
||||
|
||||
|
|
|
@ -1,10 +1,7 @@
|
|||
"""Test `tqdm.rich`."""
|
||||
import sys
|
||||
|
||||
from .tests_tqdm import importorskip, mark
|
||||
from .tests_tqdm import importorskip
|
||||
|
||||
|
||||
@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')
|
||||
|
|
|
@ -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
|
||||
assert sum(res) == sum(range(1, 101))
|
||||
|
|
|
@ -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,7 +261,6 @@ 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='ニッポン [ニッポン]: ') == (
|
||||
|
@ -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
|
||||
|
|
51
tests/tests_utils.py
Normal file
51
tests/tests_utils.py
Normal file
|
@ -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()
|
47
tox.ini
47
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
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -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
|
|
@ -1 +0,0 @@
|
|||
|
|
@ -1,2 +0,0 @@
|
|||
[console_scripts]
|
||||
tqdm = tqdm.cli:main
|
|
@ -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
|
|
@ -1 +0,0 @@
|
|||
tqdm
|
|
@ -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
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
__version__ = '4.64.1'
|
|
@ -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.*`",
|
||||
|
|
|
@ -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)
|
||||
|
|
20
tqdm/auto.py
20
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
|
||||
from .asyncio import tqdm as asyncio_tqdm
|
||||
from .std import tqdm as std_tqdm
|
||||
|
||||
if notebook_tqdm != std_tqdm:
|
||||
if notebook_tqdm != std_tqdm:
|
||||
class tqdm(notebook_tqdm, asyncio_tqdm): # pylint: disable=inconsistent-mro
|
||||
pass
|
||||
else:
|
||||
else:
|
||||
tqdm = asyncio_tqdm
|
||||
|
||||
def trange(*args, **kwargs):
|
||||
|
||||
def trange(*args, **kwargs):
|
||||
"""
|
||||
A shortcut for `tqdm.auto.tqdm(range(*args), **kwargs)`.
|
||||
"""
|
||||
return tqdm(range(*args), **kwargs)
|
||||
|
||||
|
||||
__all__ = ["tqdm", "trange"]
|
||||
|
|
12
tqdm/cli.py
12
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+|=|$)')
|
||||
|
||||
|
@ -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`"""
|
||||
|
|
|
@ -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`.
|
||||
|
|
|
@ -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))
|
||||
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):
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
"""
|
||||
Thin wrappers around `itertools`.
|
||||
"""
|
||||
from __future__ import absolute_import
|
||||
|
||||
import itertools
|
||||
|
||||
from ..auto import tqdm as tqdm_auto
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
"""
|
||||
IO/concurrency helpers for `tqdm.contrib`.
|
||||
"""
|
||||
from __future__ import absolute_import
|
||||
|
||||
from collections import deque
|
||||
from concurrent.futures import ThreadPoolExecutor
|
||||
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
from __future__ import absolute_import
|
||||
|
||||
from functools import partial
|
||||
|
||||
from dask.callbacks import Callback
|
||||
|
|
13
tqdm/gui.py
13
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
|
||||
|
|
|
@ -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()
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
10
tqdm/rich.py
10
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
|
||||
|
|
343
tqdm/std.py
343
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)
|
||||
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)
|
||||
|
|
21
tqdm/tk.py
21
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
|
||||
|
|
|
@ -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
|
||||
|
|
107
tqdm/utils.py
107
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):
|
||||
|
|
Loading…
Add table
Reference in a new issue