Compare commits
5 commits
2da88b2fbc
...
9769cec287
Author | SHA1 | Date | |
---|---|---|---|
9769cec287 | |||
b09a1c9c3a | |||
579fccd9fa | |||
49887fb75a | |||
ee135df3b4 |
62 changed files with 1067 additions and 4461 deletions
|
@ -2,7 +2,7 @@ default_language_version:
|
||||||
python: python3
|
python: python3
|
||||||
repos:
|
repos:
|
||||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||||
rev: v4.1.0
|
rev: v5.0.0
|
||||||
hooks:
|
hooks:
|
||||||
- id: check-added-large-files
|
- id: check-added-large-files
|
||||||
- id: check-case-conflict
|
- id: check-case-conflict
|
||||||
|
@ -37,9 +37,9 @@ repos:
|
||||||
- numpy
|
- numpy
|
||||||
- pandas
|
- pandas
|
||||||
- pytest-timeout
|
- pytest-timeout
|
||||||
- pytest-asyncio
|
- pytest-asyncio>=0.24
|
||||||
- repo: https://gitlab.com/pycqa/flake8
|
- repo: https://github.com/PyCQA/flake8
|
||||||
rev: 3.9.2
|
rev: 7.1.1
|
||||||
hooks:
|
hooks:
|
||||||
- id: flake8
|
- id: flake8
|
||||||
args: [-j8]
|
args: [-j8]
|
||||||
|
@ -49,14 +49,14 @@ repos:
|
||||||
- flake8-comprehensions
|
- flake8-comprehensions
|
||||||
- flake8-debugger
|
- flake8-debugger
|
||||||
- flake8-isort
|
- flake8-isort
|
||||||
|
- flake8-pyproject
|
||||||
- flake8-string-format
|
- flake8-string-format
|
||||||
- flake8-type-annotations
|
|
||||||
- repo: https://github.com/PyCQA/isort
|
- repo: https://github.com/PyCQA/isort
|
||||||
rev: 5.10.1
|
rev: 5.13.2
|
||||||
hooks:
|
hooks:
|
||||||
- id: isort
|
- id: isort
|
||||||
- repo: https://github.com/kynan/nbstripout
|
- repo: https://github.com/kynan/nbstripout
|
||||||
rev: 0.5.0
|
rev: 0.7.1
|
||||||
hooks:
|
hooks:
|
||||||
- id: nbstripout
|
- id: nbstripout
|
||||||
args: [--keep-count, --keep-output]
|
args: [--keep-count, --keep-output]
|
||||||
|
|
|
@ -12,7 +12,7 @@ Makefile:
|
||||||
|
|
||||||
```
|
```
|
||||||
make [<alias>] # on UNIX-like environments
|
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).
|
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 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
|
* use [default: ...] for default values of keyword arguments
|
||||||
+ will not break backward compatibility unless there is a very good reason
|
+ 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
|
+ API changes should be discussed carefully
|
||||||
+ remember, with millions of downloads per month, `tqdm` must be extremely fast and reliable
|
+ 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
|
- 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:
|
- run the following command:
|
||||||
|
|
||||||
```
|
```
|
||||||
[python setup.py] make test
|
[python -m py]make test
|
||||||
# or:
|
# or:
|
||||||
tox --skip-missing-interpreters
|
tox --skip-missing-interpreters
|
||||||
```
|
```
|
||||||
|
@ -97,19 +97,19 @@ versions of Python.)
|
||||||
|
|
||||||
Note: to install all versions of the Python interpreter that are specified
|
Note: to install all versions of the Python interpreter that are specified
|
||||||
in [tox.ini](https://github.com/tqdm/tqdm/blob/master/tox.ini),
|
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
|
you can use `MiniConda` to install a minimal setup. You must also ensure
|
||||||
that each distribution has an alias to call the Python interpreter:
|
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.
|
(e.g. `python312` for Python 3.12's interpreter).
|
||||||
|
|
||||||
### Alternative unit tests with pytest
|
### Alternative unit tests with pytest
|
||||||
|
|
||||||
Alternatively, use `pytest` to run the tests just for the current Python version:
|
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:
|
- 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
|
This section is intended for the project's maintainers and describes
|
||||||
how to build and upload a new release. Once again,
|
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:
|
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
|
## Pre-commit Hook
|
||||||
|
@ -137,20 +137,20 @@ The `tqdm` repository managers should:
|
||||||
- follow the [Semantic Versioning](https://semver.org) convention for tagging
|
- 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:
|
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 upload just metadata (including overwriting mistakenly uploaded metadata)
|
||||||
to PyPI, use:
|
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
|
### 4 Test
|
||||||
|
|
||||||
```
|
```
|
||||||
[python setup.py] make alltests
|
[python -m py]make alltests
|
||||||
```
|
```
|
||||||
|
|
||||||
### 5 Push to master
|
### 5 Push to master
|
||||||
|
@ -233,7 +233,7 @@ Manual instructions are given below in case of failure.
|
||||||
Build `tqdm` into a distributable python package:
|
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
|
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:
|
[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
|
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);
|
release from the [web interface](https://github.com/tqdm/tqdm/releases);
|
||||||
uploading packages from the `dist/` folder
|
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
|
The [wiki] can be automatically updated with GitHub release notes by
|
||||||
running `make` within the wiki repository.
|
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
|
- in case of a mistake, you can delete an uploaded release on PyPI, but you
|
||||||
cannot re-upload another with the same version number
|
cannot re-upload another with the same version number
|
||||||
- in case of a mistake in the metadata on PyPI (e.g. bad README),
|
- 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
|
## Updating Websites
|
||||||
|
@ -333,16 +333,16 @@ to assist with maintenance.
|
||||||
For experienced devs, once happy with local master, follow the steps below.
|
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).
|
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"`
|
2. `git commit [--amend] # -m "bump version"`
|
||||||
3. `git push`
|
3. `git push`
|
||||||
4. wait for tests to pass
|
4. wait for tests to pass
|
||||||
a) in case of failure, fix and go back to (1)
|
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`
|
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`
|
6. **`[AUTO:GHA]`** `[python -m py]make distclean`
|
||||||
7. **`[AUTO:GHA]`** `[python setup.py] make build`
|
7. **`[AUTO:GHA]`** `[python -m py]make build`
|
||||||
8. **`[AUTO:GHA]`** upload to PyPI. either:
|
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-*`
|
b) `twine upload -s -i $(git config user.signingkey) dist/tqdm-*`
|
||||||
9. **`[AUTO:GHA]`** upload to docker hub:
|
9. **`[AUTO:GHA]`** upload to docker hub:
|
||||||
a) `make -B docker`
|
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
|
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
|
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
|
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`
|
b) `asv gh-pages`
|
||||||
|
|
||||||
Key:
|
Key:
|
||||||
|
|
14
DEMO.ipynb
14
DEMO.ipynb
|
@ -5,12 +5,12 @@
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"source": [
|
"source": [
|
||||||
"<h1 align=\"center\">tqdm</h1>\n",
|
"<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",
|
"\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",
|
"[![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",
|
||||||
"\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",
|
||||||
"\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",
|
"[![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": {},
|
"metadata": {},
|
||||||
"source": [
|
"source": [
|
||||||
"`trange(N)` can be also used as a convenient shortcut for\n",
|
"`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",
|
"cell_type": "markdown",
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"source": [
|
"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",
|
||||||
"\n",
|
"\n",
|
||||||
"It can also be executed as a module with pipes:"
|
"It can also be executed as a module with pipes:"
|
||||||
|
@ -413,7 +413,7 @@
|
||||||
" \"\"\"Provides a `total_time` format parameter\"\"\"\n",
|
" \"\"\"Provides a `total_time` format parameter\"\"\"\n",
|
||||||
" @property\n",
|
" @property\n",
|
||||||
" def format_dict(self):\n",
|
" def format_dict(self):\n",
|
||||||
" d = super(TqdmExtraFormat, self).format_dict\n",
|
" d = super().format_dict\n",
|
||||||
" total_time = d[\"elapsed\"] * (d[\"total\"] or 0) / max(d[\"n\"], 1)\n",
|
" total_time = d[\"elapsed\"] * (d[\"total\"] or 0) / max(d[\"n\"], 1)\n",
|
||||||
" d.update(total_time=self.format_interval(total_time) + \" in total\")\n",
|
" d.update(total_time=self.format_interval(total_time) + \" in total\")\n",
|
||||||
" return d\n",
|
" return d\n",
|
||||||
|
@ -737,7 +737,7 @@
|
||||||
"bars and colour hints (blue: normal, green: completed, red:\n",
|
"bars and colour hints (blue: normal, green: completed, red:\n",
|
||||||
"error/interrupt, light blue: no ETA); as demonstrated below.\n",
|
"error/interrupt, light blue: no ETA); as demonstrated below.\n",
|
||||||
"\n",
|
"\n",
|
||||||
"![Screenshot-Jupyter3](https://img.tqdm.ml/jupyter-3.gif)\n",
|
"![Screenshot-Jupyter3](https://tqdm.github.io/img/jupyter-3.gif)\n",
|
||||||
"\n",
|
"\n",
|
||||||
"The `notebook` version supports percentage or pixels for overall width\n",
|
"The `notebook` version supports percentage or pixels for overall width\n",
|
||||||
"(e.g.: `ncols='100%'` or `ncols='480px'`).\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",
|
"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",
|
"this can be used to redirect the messages writing to a log file or class.\n",
|
||||||
"\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://cgi.cdcl.ml/hits?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://cgi.cdcl.ml/hits?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:
|
in reverse chronological order:
|
||||||
|
|
||||||
* files: *
|
* 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).
|
[casperdcl](https://github.com/casperdcl).
|
||||||
* files: tqdm/_tqdm.py
|
* files: tqdm/_tqdm.py
|
||||||
MIT 2016 (c) [PR #96] on behalf of Google Inc.
|
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.
|
MIT 2013 (c) Noam Yorav-Raphael, original author.
|
||||||
|
|
||||||
[PR #96]: https://github.com/tqdm/tqdm/pull/96
|
[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)
|
# 1. Every alias is preceded by @[+]make (eg: @make alias)
|
||||||
# 2. A maximum of one @make alias or command per line
|
# 2. A maximum of one @make alias or command per line
|
||||||
# see: https://github.com/tqdm/py-make/issues/1
|
# see: https://github.com/tqdm/py-make/issues/1
|
||||||
|
@ -31,7 +31,7 @@
|
||||||
run
|
run
|
||||||
|
|
||||||
help:
|
help:
|
||||||
@python setup.py make -p
|
@python -m pymake -p
|
||||||
|
|
||||||
alltests:
|
alltests:
|
||||||
@+make testcoverage
|
@+make testcoverage
|
||||||
|
@ -58,15 +58,14 @@ testsetup:
|
||||||
@make README.rst
|
@make README.rst
|
||||||
@make tqdm/tqdm.1
|
@make tqdm/tqdm.1
|
||||||
@make tqdm/completion.sh
|
@make tqdm/completion.sh
|
||||||
python setup.py check --metadata --restructuredtext --strict
|
@make help
|
||||||
python setup.py make none
|
|
||||||
|
|
||||||
testnb:
|
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 --nbval-current-env --nbval-sanitize-with=.meta/nbval.ini
|
||||||
|
|
||||||
testcoverage:
|
testcoverage:
|
||||||
@make coverclean
|
@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 --nbval-current-env --nbval-sanitize-with=.meta/nbval.ini
|
||||||
pytest -k "not perf" --cov=tqdm --cov-report=xml --cov-report=term --cov-append --cov-fail-under=80
|
pytest -k "not perf" --cov=tqdm --cov-report=xml --cov-report=term --cov-append --cov-fail-under=80
|
||||||
|
|
||||||
testperf:
|
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('*.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('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('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/*.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/contrib/*.py[co]')]"
|
||||||
@+python -c "import os, glob; [os.remove(i) for i in glob.glob('tqdm/examples/*.py[co]')]"
|
|
||||||
toxclean:
|
toxclean:
|
||||||
@+python -c "import shutil; shutil.rmtree('.tox', True)"
|
@+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
|
cd feedstock && git remote add autotick-bot git@github.com:regro-cf-autotick-bot/tqdm-feedstock
|
||||||
|
|
||||||
install:
|
install:
|
||||||
python setup.py install
|
python -m pip install .
|
||||||
install_dev:
|
install_dev:
|
||||||
python setup.py develop --uninstall
|
python -m pip install -e .
|
||||||
python setup.py develop
|
|
||||||
install_build:
|
install_build:
|
||||||
python -m pip install -r .meta/requirements-dev.txt
|
python -m pip install -r .meta/requirements-build.txt
|
||||||
install_test:
|
install_test:
|
||||||
python -m pip install -r .meta/requirements-test.txt
|
python -m pip install -r .meta/requirements-test.txt
|
||||||
pre-commit install
|
pre-commit install
|
||||||
|
@ -165,11 +163,11 @@ install_test:
|
||||||
build:
|
build:
|
||||||
@make prebuildclean
|
@make prebuildclean
|
||||||
@make testsetup
|
@make testsetup
|
||||||
python setup.py sdist bdist_wheel
|
python -m build
|
||||||
# python setup.py bdist_wininst
|
python -m twine check dist/*
|
||||||
|
|
||||||
pypi:
|
pypi:
|
||||||
twine upload dist/*
|
python -m twine upload dist/*
|
||||||
|
|
||||||
buildupload:
|
buildupload:
|
||||||
@make build
|
@make build
|
||||||
|
|
72
README.rst
72
README.rst
|
@ -255,7 +255,7 @@ This can be beautified further:
|
||||||
|
|
||||||
.. code:: sh
|
.. code:: sh
|
||||||
|
|
||||||
$ BYTES="$(du -sb docs/ | cut -f1)"
|
$ BYTES=$(du -sb docs/ | cut -f1)
|
||||||
$ tar -cf - docs/ \
|
$ tar -cf - docs/ \
|
||||||
| tqdm --bytes --total "$BYTES" --desc Processing | gzip \
|
| tqdm --bytes --total "$BYTES" --desc Processing | gzip \
|
||||||
| tqdm --bytes --total "$BYTES" --desc Compressed --position 1 \
|
| 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.
|
of a neat one-line progress bar.
|
||||||
|
|
||||||
- Consoles in general: require support for carriage return (``CR``, ``\r``).
|
- 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:
|
- Nested progress bars:
|
||||||
|
|
||||||
* Consoles in general: require support for moving cursors up to the
|
* 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``.
|
* The same applies to ``itertools``.
|
||||||
* Some useful convenience functions can be found under ``tqdm.contrib``.
|
* 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>`__:
|
- `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``.
|
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|.
|
If you come across any other difficulties, browse and file |GitHub-Issues|.
|
||||||
|
|
||||||
Documentation
|
Documentation
|
||||||
|
@ -349,12 +357,14 @@ Documentation
|
||||||
progressbar every time a value is requested.
|
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,
|
def __init__(self, iterable=None, desc=None, total=None, leave=True,
|
||||||
file=None, ncols=None, mininterval=0.1,
|
file=None, ncols=None, mininterval=0.1,
|
||||||
maxinterval=10.0, miniters=None, ascii=None, disable=False,
|
maxinterval=10.0, miniters=None, ascii=None, disable=False,
|
||||||
unit='it', unit_scale=False, dynamic_ncols=False,
|
unit='it', unit_scale=False, dynamic_ncols=False,
|
||||||
smoothing=0.3, bar_format=None, initial=0, position=None,
|
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
|
Parameters
|
||||||
~~~~~~~~~~
|
~~~~~~~~~~
|
||||||
|
@ -450,9 +460,7 @@ Parameters
|
||||||
* unit_divisor : float, optional
|
* unit_divisor : float, optional
|
||||||
[default: 1000], ignored unless ``unit_scale`` is True.
|
[default: 1000], ignored unless ``unit_scale`` is True.
|
||||||
* write_bytes : bool, optional
|
* write_bytes : bool, optional
|
||||||
If (default: None) and ``file`` is unspecified,
|
Whether to write bytes. If (default: False) will write unicode.
|
||||||
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
|
* lock_args : tuple, optional
|
||||||
Passed to ``refresh`` for intermediate output
|
Passed to ``refresh`` for intermediate output
|
||||||
(initialisation, iterating, and updating).
|
(initialisation, iterating, and updating).
|
||||||
|
@ -631,10 +639,7 @@ Returns
|
||||||
"""Registers the current `tqdm` class with `pandas`."""
|
"""Registers the current `tqdm` class with `pandas`."""
|
||||||
|
|
||||||
def trange(*args, **tqdm_kwargs):
|
def trange(*args, **tqdm_kwargs):
|
||||||
"""
|
"""Shortcut for `tqdm(range(*args), **tqdm_kwargs)`."""
|
||||||
A shortcut for `tqdm(xrange(*args), **tqdm_kwargs)`.
|
|
||||||
On Python3+, `range` is used instead of `xrange`.
|
|
||||||
"""
|
|
||||||
|
|
||||||
Convenience Functions
|
Convenience Functions
|
||||||
~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
@ -737,7 +742,7 @@ with the ``desc`` and ``postfix`` arguments:
|
||||||
sleep(0.1)
|
sleep(0.1)
|
||||||
|
|
||||||
with tqdm(total=10, bar_format="{postfix[0]} {postfix[1][value]:>8.2g}",
|
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):
|
for i in range(10):
|
||||||
sleep(0.1)
|
sleep(0.1)
|
||||||
t.postfix[1]["value"] = i / 2
|
t.postfix[1]["value"] = i / 2
|
||||||
|
@ -761,7 +766,7 @@ Additional ``bar_format`` parameters may also be defined by overriding
|
||||||
"""Provides a `total_time` format parameter"""
|
"""Provides a `total_time` format parameter"""
|
||||||
@property
|
@property
|
||||||
def format_dict(self):
|
def format_dict(self):
|
||||||
d = super(TqdmExtraFormat, self).format_dict
|
d = super().format_dict
|
||||||
total_time = d["elapsed"] * (d["total"] or 0) / max(d["n"], 1)
|
total_time = d["elapsed"] * (d["total"] or 0) / max(d["n"], 1)
|
||||||
d.update(total_time=self.format_interval(total_time) + " in total")
|
d.update(total_time=self.format_interval(total_time) + " in total")
|
||||||
return d
|
return d
|
||||||
|
@ -825,7 +830,7 @@ first.
|
||||||
def progresser(n):
|
def progresser(n):
|
||||||
interval = 0.001 / (n + 2)
|
interval = 0.001 / (n + 2)
|
||||||
total = 5000
|
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):
|
for _ in trange(total, desc=text, position=n):
|
||||||
sleep(interval)
|
sleep(interval)
|
||||||
|
|
||||||
|
@ -848,7 +853,7 @@ Note that in Python 3, ``tqdm.write`` is thread-safe:
|
||||||
def progresser(n):
|
def progresser(n):
|
||||||
interval = 0.001 / (n + 2)
|
interval = 0.001 / (n + 2)
|
||||||
total = 5000
|
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):
|
for _ in trange(total, desc=text):
|
||||||
sleep(interval)
|
sleep(interval)
|
||||||
if n == 6:
|
if n == 6:
|
||||||
|
@ -977,7 +982,7 @@ custom callback take advantage of this, simply use the return value of
|
||||||
|
|
||||||
class TqdmExt(std_tqdm):
|
class TqdmExt(std_tqdm):
|
||||||
def update(self, n=1):
|
def update(self, n=1):
|
||||||
displayed = super(TqdmExt, self).update(n)
|
displayed = super().update(n)
|
||||||
if displayed:
|
if displayed:
|
||||||
external_callback(**self.format_dict)
|
external_callback(**self.format_dict)
|
||||||
return displayed
|
return displayed
|
||||||
|
@ -1405,16 +1410,17 @@ are:
|
||||||
==================== ======================================================== ==== ================================
|
==================== ======================================================== ==== ================================
|
||||||
Name ID SLoC Notes
|
Name ID SLoC Notes
|
||||||
==================== ======================================================== ==== ================================
|
==================== ======================================================== ==== ================================
|
||||||
Casper da Costa-Luis `casperdcl <https://github.com/casperdcl>`__ ~78% primary maintainer |Gift-Casper|
|
Casper da Costa-Luis `casperdcl <https://github.com/casperdcl>`__ ~80% primary maintainer |Gift-Casper|
|
||||||
Stephen Larroque `lrq3000 <https://github.com/lrq3000>`__ ~10% team member
|
Stephen Larroque `lrq3000 <https://github.com/lrq3000>`__ ~9% team member
|
||||||
Martin Zugnoni `martinzugnoni <https://github.com/martinzugnoni>`__ ~4%
|
Martin Zugnoni `martinzugnoni <https://github.com/martinzugnoni>`__ ~3%
|
||||||
Daniel Ecer `de-code <https://github.com/de-code>`__ ~2%
|
Daniel Ecer `de-code <https://github.com/de-code>`__ ~2%
|
||||||
Richard Sheridan `richardsheridan <https://github.com/richardsheridan>`__ ~1%
|
Richard Sheridan `richardsheridan <https://github.com/richardsheridan>`__ ~1%
|
||||||
Guangshuo Chen `chengs <https://github.com/chengs>`__ ~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%
|
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%
|
Matthew Stevens `mjstevens777 <https://github.com/mjstevens777>`__ <1%
|
||||||
Hadrien Mary `hadim <https://github.com/hadim>`__ <1% team member
|
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
|
Mikhail Korobov `kmike <https://github.com/kmike>`__ <1% team member
|
||||||
==================== ======================================================== ==== ================================
|
==================== ======================================================== ==== ================================
|
||||||
|
|
||||||
|
@ -1434,16 +1440,16 @@ Citation information: |DOI|
|
||||||
|
|
||||||
|README-Hits| (Since 19 May 2016)
|
|README-Hits| (Since 19 May 2016)
|
||||||
|
|
||||||
.. |Logo| image:: https://img.tqdm.ml/logo.gif
|
.. |Logo| image:: https://tqdm.github.io/img/logo.gif
|
||||||
.. |Screenshot| image:: https://img.tqdm.ml/tqdm.gif
|
.. |Screenshot| image:: https://tqdm.github.io/img/tqdm.gif
|
||||||
.. |Video| image:: https://img.tqdm.ml/video.jpg
|
.. |Video| image:: https://tqdm.github.io/img/video.jpg
|
||||||
:target: https://tqdm.github.io/video
|
: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
|
: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
|
:target: https://tqdm.github.io/merch
|
||||||
.. |Build-Status| image:: https://img.shields.io/github/workflow/status/tqdm/tqdm/Test/master?logo=GitHub
|
.. |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?query=workflow%3ATest
|
:target: https://github.com/tqdm/tqdm/actions/workflows/test.yml
|
||||||
.. |Coverage-Status| image:: https://img.shields.io/coveralls/github/tqdm/tqdm/master?logo=coveralls
|
.. |Coverage-Status| image:: https://img.shields.io/coveralls/github/tqdm/tqdm/master?logo=coveralls
|
||||||
:target: https://coveralls.io/github/tqdm/tqdm
|
:target: https://coveralls.io/github/tqdm/tqdm
|
||||||
.. |Branch-Coverage-Status| image:: https://codecov.io/gh/tqdm/tqdm/branch/master/graph/badge.svg
|
.. |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
|
:target: https://doi.org/10.5281/zenodo.595120
|
||||||
.. |binder-demo| image:: https://mybinder.org/badge_logo.svg
|
.. |binder-demo| image:: https://mybinder.org/badge_logo.svg
|
||||||
:target: https://mybinder.org/v2/gh/tqdm/tqdm/master?filepath=DEMO.ipynb
|
:target: https://mybinder.org/v2/gh/tqdm/tqdm/master?filepath=DEMO.ipynb
|
||||||
.. |Screenshot-Jupyter1| image:: https://img.tqdm.ml/jupyter-1.gif
|
.. |Screenshot-Jupyter1| image:: https://tqdm.github.io/img/jupyter-1.gif
|
||||||
.. |Screenshot-Jupyter2| image:: https://img.tqdm.ml/jupyter-2.gif
|
.. |Screenshot-Jupyter2| image:: https://tqdm.github.io/img/jupyter-2.gif
|
||||||
.. |Screenshot-Jupyter3| image:: https://img.tqdm.ml/jupyter-3.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://img.tqdm.ml/favicon.png&f=https://img.tqdm.ml/logo.gif
|
.. |README-Hits| image:: https://cgi.cdcl.ml/hits?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://img.tqdm.ml/favicon.png&f=https://img.tqdm.ml/logo.gif&style=social
|
:target: https://cgi.cdcl.ml/hits?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
|
- defaults
|
||||||
dependencies:
|
dependencies:
|
||||||
# base
|
# base
|
||||||
- python=3
|
- python >=3.7
|
||||||
- pip
|
- pip
|
||||||
- ipykernel
|
- ipykernel
|
||||||
- ipywidgets
|
- ipywidgets
|
||||||
|
@ -20,27 +20,28 @@ dependencies:
|
||||||
- pytest
|
- pytest
|
||||||
- pytest-cov
|
- pytest-cov
|
||||||
- pytest-timeout
|
- pytest-timeout
|
||||||
- pytest-asyncio # [py>=3.7]
|
- pytest-asyncio>=0.24
|
||||||
- nbval
|
|
||||||
- coverage
|
- coverage
|
||||||
# extras
|
# extras
|
||||||
- dask # dask
|
- dask # dask
|
||||||
- matplotlib # gui
|
- matplotlib # gui
|
||||||
- numpy # pandas, keras, contrib.tenumerate
|
- numpy # pandas, keras, contrib.tenumerate
|
||||||
- pandas
|
- pandas
|
||||||
|
- pyarrow # pandas
|
||||||
- tensorflow # keras
|
- tensorflow # keras
|
||||||
- slack-sdk # contrib.slack
|
- slack-sdk # contrib.slack
|
||||||
- requests # contrib.telegram
|
- requests # contrib.telegram
|
||||||
- rich # rich
|
- rich # rich
|
||||||
- argopt # `cd wiki && pymake`
|
- argopt # `cd wiki && pymake`
|
||||||
- twine # `pymake pypi`
|
- twine # `pymake check pypi`
|
||||||
- wheel # `setup.py bdist_wheel`
|
- python-build # `python -m build`
|
||||||
# `cd docs && pymake`
|
# `cd docs && pymake`
|
||||||
- mkdocs-material
|
- mkdocs-material
|
||||||
- pydoc-markdown
|
|
||||||
- pygments
|
- pygments
|
||||||
- pymdown-extensions
|
- pymdown-extensions
|
||||||
- pip:
|
- pip:
|
||||||
- py-make >=0.1.0 # `setup.py make/pymake`
|
- git+https://github.com/casperdcl/nbval.git@master#egg=nbval # tests (native)
|
||||||
|
- py-make >=0.1.0 # `make/pymake`
|
||||||
- mkdocs-minify-plugin # `cd docs && pymake`
|
- mkdocs-minify-plugin # `cd docs && pymake`
|
||||||
- git+https://github.com/tqdm/jsmin@python3-only#egg=jsmin # `cd docs && pymake`
|
- git+https://github.com/tqdm/jsmin@fix-pip#egg=jsmin # `cd docs && pymake`
|
||||||
|
- pydoc-markdown >=4.6 # `cd docs && pymake`
|
||||||
|
|
|
@ -18,8 +18,6 @@ Options:
|
||||||
NOTSET
|
NOTSET
|
||||||
-d, --debug-trace Print lots of debugging information (-D NOTSET)
|
-d, --debug-trace Print lots of debugging information (-D NOTSET)
|
||||||
"""
|
"""
|
||||||
from __future__ import print_function
|
|
||||||
|
|
||||||
import io
|
import io
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
|
|
|
@ -1,6 +1,4 @@
|
||||||
"""
|
"""Asynchronous examples using `asyncio`, `async` and `await`."""
|
||||||
Asynchronous examples using `asyncio`, `async` and `await` on `python>=3.7`.
|
|
||||||
"""
|
|
||||||
import asyncio
|
import asyncio
|
||||||
|
|
||||||
from tqdm.asyncio import tqdm, trange
|
from tqdm.asyncio import tqdm, trange
|
||||||
|
|
|
@ -126,7 +126,7 @@
|
||||||
@misc{hits,
|
@misc{hits,
|
||||||
year="2019",
|
year="2019",
|
||||||
title="{tqdm} hits",
|
title="{tqdm} hits",
|
||||||
url="https://caspersci.uk.to/cgi-bin/hits.cgi?q=tqdm&a=plot",
|
url="https://cgi.cdcl.ml/hits?q=tqdm&a=plot",
|
||||||
author="Casper O. {da Costa-Luis}"
|
author="Casper O. {da Costa-Luis}"
|
||||||
}
|
}
|
||||||
@book{miller,
|
@book{miller,
|
||||||
|
|
|
@ -1,6 +1,3 @@
|
||||||
from __future__ import print_function
|
|
||||||
|
|
||||||
import sys
|
|
||||||
from concurrent.futures import ThreadPoolExecutor
|
from concurrent.futures import ThreadPoolExecutor
|
||||||
from functools import partial
|
from functools import partial
|
||||||
from multiprocessing import Pool, RLock, freeze_support
|
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
|
from tqdm.contrib.concurrent import process_map, thread_map
|
||||||
|
|
||||||
NUM_SUBITERS = 9
|
NUM_SUBITERS = 9
|
||||||
PY2 = sys.version_info[:1] <= (2,)
|
|
||||||
|
|
||||||
|
|
||||||
def progresser(n, auto_position=True, write_safe=False, blocking=True, progress=False):
|
def progresser(n, auto_position=True, write_safe=False, blocking=True, progress=False):
|
||||||
interval = random() * 0.002 / (NUM_SUBITERS - n + 2) # nosec
|
interval = random() * 0.002 / (NUM_SUBITERS - n + 2) # nosec
|
||||||
total = 5000
|
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,
|
for _ in trange(total, desc=text, disable=not progress,
|
||||||
lock_args=None if blocking else (False,),
|
lock_args=None if blocking else (False,),
|
||||||
position=None if auto_position else n):
|
position=None if auto_position else n):
|
||||||
sleep(interval)
|
sleep(interval)
|
||||||
# NB: may not clear instances with higher `position` upon completion
|
# NB: may not clear instances with higher `position` upon completion
|
||||||
# since this worker may not know about other bars #796
|
# since this worker may not know about other bars #796
|
||||||
if write_safe:
|
if write_safe: # we think we know about other bars
|
||||||
# we think we know about other bars (currently only py3 threading)
|
|
||||||
if n == 6:
|
if n == 6:
|
||||||
tqdm.write("n == 6 completed")
|
tqdm.write("n == 6 completed")
|
||||||
return n + 1
|
return n + 1
|
||||||
|
@ -37,7 +32,7 @@ if __name__ == '__main__':
|
||||||
L = list(range(NUM_SUBITERS))[::-1]
|
L = list(range(NUM_SUBITERS))[::-1]
|
||||||
|
|
||||||
print("Simple thread mapping")
|
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")
|
print("Simple process mapping")
|
||||||
process_map(partial(progresser), L, max_workers=4)
|
process_map(partial(progresser), L, max_workers=4)
|
||||||
|
@ -54,8 +49,5 @@ if __name__ == '__main__':
|
||||||
|
|
||||||
print("Multi-threading")
|
print("Multi-threading")
|
||||||
tqdm.set_lock(TRLock())
|
tqdm.set_lock(TRLock())
|
||||||
pool_args = {}
|
with ThreadPoolExecutor(initializer=tqdm.set_lock, initargs=(tqdm.get_lock(),)) as p:
|
||||||
if not PY2:
|
p.map(partial(progresser, progress=True, write_safe=True, blocking=False), L)
|
||||||
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)
|
|
||||||
|
|
|
@ -10,8 +10,6 @@ any input string to `tqdm.write()`, and supply the arguments
|
||||||
|
|
||||||
A reusable canonical example is given below:
|
A reusable canonical example is given below:
|
||||||
"""
|
"""
|
||||||
from __future__ import print_function
|
|
||||||
|
|
||||||
import contextlib
|
import contextlib
|
||||||
import sys
|
import sys
|
||||||
from time import sleep
|
from time import sleep
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
# Simple tqdm examples and profiling
|
# Simple tqdm examples and profiling
|
||||||
|
|
||||||
# Benchmark
|
# Benchmark
|
||||||
for i in _range(int(1e8)):
|
for i in range(int(1e8)):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
# Basic demo
|
# Basic demo
|
||||||
|
@ -33,7 +33,7 @@ try:
|
||||||
except ImportError:
|
except ImportError:
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
for i in ProgressBar()(_range(int(1e8))):
|
for i in ProgressBar()(range(int(1e8))):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
# Dynamic miniters benchmark
|
# Dynamic miniters benchmark
|
||||||
|
@ -61,5 +61,4 @@ for _ in trange(16, leave=True):
|
||||||
stmts = filter(None, re.split(r'\n\s*#.*?\n', __doc__))
|
stmts = filter(None, re.split(r'\n\s*#.*?\n', __doc__))
|
||||||
for s in stmts:
|
for s in stmts:
|
||||||
print(s.replace('import tqdm\n', ''))
|
print(s.replace('import tqdm\n', ''))
|
||||||
print(timeit(stmt='try:\n\t_range = xrange'
|
print(timeit(stmt=s, number=1), 'seconds')
|
||||||
'\nexcept:\n\t_range = range\n' + s, number=1), 'seconds')
|
|
||||||
|
|
|
@ -20,11 +20,8 @@ Options:
|
||||||
The local file path in which to save the url [default: /dev/null].
|
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 os import devnull
|
||||||
|
from urllib import request as urllib
|
||||||
|
|
||||||
from docopt import docopt
|
from docopt import docopt
|
||||||
|
|
||||||
|
|
132
pyproject.toml
132
pyproject.toml
|
@ -5,3 +5,135 @@ build-backend = "setuptools.build_meta"
|
||||||
[tool.setuptools_scm]
|
[tool.setuptools_scm]
|
||||||
write_to = "tqdm/_dist_ver.py"
|
write_to = "tqdm/_dist_ver.py"
|
||||||
write_to_template = "__version__ = '{version}'\n"
|
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"}
|
||||||
|
# Trove classifiers (https://pypi.org/pypi?%3Aaction=list_classifiers)
|
||||||
|
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.12",
|
||||||
|
"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-asyncio>=0.24", "nbval"]
|
||||||
|
discord = ["requests"]
|
||||||
|
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"
|
||||||
|
asyncio_default_fixture_loop_scope = "function"
|
||||||
|
|
||||||
|
[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)
|
n = len(tqdm._instances)
|
||||||
if n:
|
if n:
|
||||||
tqdm._instances.clear()
|
tqdm._instances.clear()
|
||||||
raise EnvironmentError(
|
raise EnvironmentError(f"{n} `tqdm` instances still in existence PRE-test")
|
||||||
"{0} `tqdm` instances still in existence PRE-test".format(n))
|
|
||||||
yield
|
yield
|
||||||
if getattr(tqdm, "_instances", False):
|
if getattr(tqdm, "_instances", False):
|
||||||
n = len(tqdm._instances)
|
n = len(tqdm._instances)
|
||||||
if n:
|
if n:
|
||||||
tqdm._instances.clear()
|
tqdm._instances.clear()
|
||||||
raise EnvironmentError(
|
raise EnvironmentError(f"{n} `tqdm` instances still in existence POST-test")
|
||||||
"{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
|
|
||||||
|
|
|
@ -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,133 @@
|
||||||
"""Tests `tqdm.asyncio` on `python>=3.7`."""
|
"""Tests `tqdm.asyncio`."""
|
||||||
import sys
|
import asyncio
|
||||||
|
from functools import partial
|
||||||
|
from sys import platform
|
||||||
|
from time import time
|
||||||
|
|
||||||
if sys.version_info[:2] > (3, 6):
|
from tqdm.asyncio import tarange, tqdm_asyncio
|
||||||
from .py37_asyncio import * # NOQA, pylint: disable=wildcard-import
|
|
||||||
|
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:
|
else:
|
||||||
from .tests_tqdm import skip
|
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
|
||||||
|
|
||||||
|
acounter = acount()
|
||||||
try:
|
try:
|
||||||
skip("async not supported", allow_module_level=True)
|
with tqdm(acounter, desc="async_counter") as pbar:
|
||||||
except TypeError:
|
async for i in pbar:
|
||||||
|
if i >= 8:
|
||||||
|
break
|
||||||
|
finally:
|
||||||
|
await acounter.aclose()
|
||||||
|
_, 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
|
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`.
|
Tests for `tqdm.contrib`.
|
||||||
"""
|
"""
|
||||||
import sys
|
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from tqdm import tqdm
|
from tqdm import tqdm
|
||||||
|
@ -47,9 +45,6 @@ def test_zip(tqdm_kwargs):
|
||||||
with closing(StringIO()) as our_file:
|
with closing(StringIO()) as our_file:
|
||||||
a = range(9)
|
a = range(9)
|
||||||
b = [i + 1 for i in a]
|
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)
|
gen = tzip(a, b, file=our_file, **tqdm_kwargs)
|
||||||
assert gen != list(zip(a, b))
|
assert gen != list(zip(a, b))
|
||||||
assert list(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:
|
with closing(StringIO()) as our_file:
|
||||||
a = range(9)
|
a = range(9)
|
||||||
b = [i + 1 for i in a]
|
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)
|
gen = tmap(lambda x: x + 1, a, file=our_file, **tqdm_kwargs)
|
||||||
assert gen != b
|
assert gen != b
|
||||||
assert list(gen) == b
|
assert list(gen) == b
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
# pylint: disable=missing-module-docstring, missing-class-docstring
|
# pylint: disable=missing-module-docstring, missing-class-docstring
|
||||||
# pylint: disable=missing-function-docstring, no-self-use
|
# pylint: disable=missing-function-docstring, no-self-use
|
||||||
from __future__ import absolute_import
|
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
import logging.handlers
|
import logging.handlers
|
||||||
import sys
|
import sys
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
from __future__ import division
|
|
||||||
|
|
||||||
from time import sleep
|
from time import sleep
|
||||||
|
|
||||||
from .tests_tqdm import importorskip, mark
|
from .tests_tqdm import importorskip, mark
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
from __future__ import division
|
|
||||||
|
|
||||||
from .tests_tqdm import importorskip, mark
|
from .tests_tqdm import importorskip, mark
|
||||||
|
|
||||||
pytestmark = mark.slow
|
pytestmark = mark.slow
|
||||||
|
@ -41,8 +39,8 @@ def test_keras(capsys):
|
||||||
verbose=0)])
|
verbose=0)])
|
||||||
_, res = capsys.readouterr()
|
_, res = capsys.readouterr()
|
||||||
assert "training: " in res
|
assert "training: " in res
|
||||||
assert "{epochs}/{epochs}".format(epochs=epochs) in res
|
assert f"{epochs}/{epochs}" in res
|
||||||
assert "{batches}/{batches}".format(batches=batches) not in res
|
assert f"{batches}/{batches}" not in res
|
||||||
|
|
||||||
# full (epoch and batch) progress
|
# full (epoch and batch) progress
|
||||||
model.fit(
|
model.fit(
|
||||||
|
@ -60,8 +58,8 @@ def test_keras(capsys):
|
||||||
verbose=2)])
|
verbose=2)])
|
||||||
_, res = capsys.readouterr()
|
_, res = capsys.readouterr()
|
||||||
assert "training: " in res
|
assert "training: " in res
|
||||||
assert "{epochs}/{epochs}".format(epochs=epochs) in res
|
assert f"{epochs}/{epochs}" in res
|
||||||
assert "{batches}/{batches}".format(batches=batches) in res
|
assert f"{batches}/{batches}" in res
|
||||||
|
|
||||||
# auto-detect epochs and batches
|
# auto-detect epochs and batches
|
||||||
model.fit(
|
model.fit(
|
||||||
|
@ -73,8 +71,8 @@ def test_keras(capsys):
|
||||||
callbacks=[TqdmCallback(desc="training", verbose=2)])
|
callbacks=[TqdmCallback(desc="training", verbose=2)])
|
||||||
_, res = capsys.readouterr()
|
_, res = capsys.readouterr()
|
||||||
assert "training: " in res
|
assert "training: " in res
|
||||||
assert "{epochs}/{epochs}".format(epochs=epochs) in res
|
assert f"{epochs}/{epochs}" in res
|
||||||
assert "{batches}/{batches}".format(batches=batches) in res
|
assert f"{batches}/{batches}" in res
|
||||||
|
|
||||||
# continue training (start from epoch != 0)
|
# continue training (start from epoch != 0)
|
||||||
initial_epoch = 3
|
initial_epoch = 3
|
||||||
|
@ -89,5 +87,5 @@ def test_keras(capsys):
|
||||||
miniters=1, mininterval=0, maxinterval=0)])
|
miniters=1, mininterval=0, maxinterval=0)])
|
||||||
_, res = capsys.readouterr()
|
_, res = capsys.readouterr()
|
||||||
assert "training: " in res
|
assert "training: " in res
|
||||||
assert "{epochs}/{epochs}".format(epochs=initial_epoch - 1) not in res
|
assert f"{initial_epoch - 1}/{initial_epoch - 1}" not in res
|
||||||
assert "{epochs}/{epochs}".format(epochs=epochs) 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.cli import TqdmKeyError, TqdmTypeError, main
|
||||||
from tqdm.utils import IS_WIN
|
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):
|
def restore_sys(func):
|
||||||
"""Decorates `func(capsysbin)` to save & restore `sys.(stdin|argv)`."""
|
"""Decorates `func(capsysbinary)` to save & restore `sys.(stdin|argv)`."""
|
||||||
@wraps(func)
|
@wraps(func)
|
||||||
def inner(capsysbin):
|
def inner(capsysbinary):
|
||||||
"""function requiring capsysbin which may alter `sys.(stdin|argv)`"""
|
"""function requiring capsysbinary which may alter `sys.(stdin|argv)`"""
|
||||||
_SYS = sys.stdin, sys.argv
|
_SYS = sys.stdin, sys.argv
|
||||||
try:
|
try:
|
||||||
res = func(capsysbin)
|
res = func(capsysbinary)
|
||||||
finally:
|
finally:
|
||||||
sys.stdin, sys.argv = _SYS
|
sys.stdin, sys.argv = _SYS
|
||||||
return res
|
return res
|
||||||
|
@ -58,7 +58,7 @@ def test_main_import():
|
||||||
N = 123
|
N = 123
|
||||||
_SYS = sys.stdin, sys.argv
|
_SYS = sys.stdin, sys.argv
|
||||||
# test direct import
|
# 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',
|
sys.argv = ['', '--desc', 'Test CLI import',
|
||||||
'--ascii', 'True', '--unit_scale', 'True']
|
'--ascii', 'True', '--unit_scale', 'True']
|
||||||
try:
|
try:
|
||||||
|
@ -68,19 +68,19 @@ def test_main_import():
|
||||||
|
|
||||||
|
|
||||||
@restore_sys
|
@restore_sys
|
||||||
def test_main_bytes(capsysbin):
|
def test_main_bytes(capsysbinary):
|
||||||
"""Test CLI --bytes"""
|
"""Test CLI --bytes"""
|
||||||
N = 123
|
N = 123
|
||||||
|
|
||||||
# test --delim
|
# 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:
|
with closing(BytesIO()) as sys.stdin:
|
||||||
sys.stdin.write(IN_DATA)
|
sys.stdin.write(IN_DATA)
|
||||||
# sys.stdin.write(b'\xff') # TODO
|
# sys.stdin.write(b'\xff') # TODO
|
||||||
sys.stdin.seek(0)
|
sys.stdin.seek(0)
|
||||||
main(sys.stderr, ['--desc', 'Test CLI delim', '--ascii', 'True',
|
main(sys.stderr, ['--desc', 'Test CLI delim', '--ascii', 'True',
|
||||||
'--delim', r'\0', '--buf_size', '64'])
|
'--delim', r'\0', '--buf_size', '64'])
|
||||||
out, err = capsysbin.readouterr()
|
out, err = capsysbinary.readouterr()
|
||||||
assert out == IN_DATA
|
assert out == IN_DATA
|
||||||
assert str(N) + "it" in err.decode("U8")
|
assert str(N) + "it" in err.decode("U8")
|
||||||
|
|
||||||
|
@ -90,27 +90,26 @@ def test_main_bytes(capsysbin):
|
||||||
sys.stdin.write(IN_DATA)
|
sys.stdin.write(IN_DATA)
|
||||||
sys.stdin.seek(0)
|
sys.stdin.seek(0)
|
||||||
main(sys.stderr, ['--ascii', '--bytes=True', '--unit_scale', 'False'])
|
main(sys.stderr, ['--ascii', '--bytes=True', '--unit_scale', 'False'])
|
||||||
out, err = capsysbin.readouterr()
|
out, err = capsysbinary.readouterr()
|
||||||
assert out == IN_DATA
|
assert out == IN_DATA
|
||||||
assert str(len(IN_DATA)) + "B" in err.decode("U8")
|
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(capsysbinary, caplog):
|
||||||
def test_main_log(capsysbin, caplog):
|
|
||||||
"""Test CLI --log"""
|
"""Test CLI --log"""
|
||||||
_SYS = sys.stdin, sys.argv
|
_SYS = sys.stdin, sys.argv
|
||||||
N = 123
|
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)
|
IN_DATA = b''.join(sys.stdin)
|
||||||
try:
|
try:
|
||||||
with caplog.at_level(logging.INFO):
|
with caplog.at_level(logging.INFO):
|
||||||
main(sys.stderr, ['--log', '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 norm(out) == IN_DATA and b"123/123" in err
|
||||||
assert not caplog.record_tuples
|
assert not caplog.record_tuples
|
||||||
with caplog.at_level(logging.DEBUG):
|
with caplog.at_level(logging.DEBUG):
|
||||||
main(sys.stderr, ['--log', '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 norm(out) == IN_DATA and b"123/123" in err
|
||||||
assert caplog.record_tuples
|
assert caplog.record_tuples
|
||||||
finally:
|
finally:
|
||||||
|
@ -118,39 +117,39 @@ def test_main_log(capsysbin, caplog):
|
||||||
|
|
||||||
|
|
||||||
@restore_sys
|
@restore_sys
|
||||||
def test_main(capsysbin):
|
def test_main(capsysbinary):
|
||||||
"""Test misc CLI options"""
|
"""Test misc CLI options"""
|
||||||
N = 123
|
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)
|
IN_DATA = b''.join(sys.stdin)
|
||||||
|
|
||||||
# test --tee
|
# test --tee
|
||||||
main(sys.stderr, ['--mininterval', '0', '--miniters', '1'])
|
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 norm(out) == IN_DATA and b"123/123" in err
|
||||||
assert N <= len(err.split(b"\r")) < N + 5
|
assert N <= len(err.split(b"\r")) < N + 5
|
||||||
|
|
||||||
len_err = len(err)
|
len_err = len(err)
|
||||||
main(sys.stderr, ['--tee', '--mininterval', '0', '--miniters', '1'])
|
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
|
assert norm(out) == IN_DATA and b"123/123" in err
|
||||||
# spaces to clear intermediate lines could increase length
|
# spaces to clear intermediate lines could increase length
|
||||||
assert len_err + len(norm(out)) <= len(err)
|
assert len_err + len(norm(out)) <= len(err)
|
||||||
|
|
||||||
# test --null
|
# test --null
|
||||||
main(sys.stderr, ['--null'])
|
main(sys.stderr, ['--null'])
|
||||||
out, err = capsysbin.readouterr()
|
out, err = capsysbinary.readouterr()
|
||||||
assert not out and b"123/123" in err
|
assert not out and b"123/123" in err
|
||||||
|
|
||||||
# test integer --update
|
# test integer --update
|
||||||
main(sys.stderr, ['--update'])
|
main(sys.stderr, ['--update'])
|
||||||
out, err = capsysbin.readouterr()
|
out, err = capsysbinary.readouterr()
|
||||||
assert norm(out) == IN_DATA
|
assert norm(out) == IN_DATA
|
||||||
assert (str(N // 2 * N) + "it").encode() in err, "expected arithmetic sum formula"
|
assert (str(N // 2 * N) + "it").encode() in err, "expected arithmetic sum formula"
|
||||||
|
|
||||||
# test integer --update_to
|
# test integer --update_to
|
||||||
main(sys.stderr, ['--update-to'])
|
main(sys.stderr, ['--update-to'])
|
||||||
out, err = capsysbin.readouterr()
|
out, err = capsysbinary.readouterr()
|
||||||
assert norm(out) == IN_DATA
|
assert norm(out) == IN_DATA
|
||||||
assert (str(N - 1) + "it").encode() in err
|
assert (str(N - 1) + "it").encode() in err
|
||||||
assert (str(N) + "it").encode() not in err
|
assert (str(N) + "it").encode() not in err
|
||||||
|
@ -161,23 +160,23 @@ def test_main(capsysbin):
|
||||||
# test integer --update --delim
|
# test integer --update --delim
|
||||||
sys.stdin.seek(0)
|
sys.stdin.seek(0)
|
||||||
main(sys.stderr, ['--update', '--delim', 'D'])
|
main(sys.stderr, ['--update', '--delim', 'D'])
|
||||||
out, err = capsysbin.readouterr()
|
out, err = capsysbinary.readouterr()
|
||||||
assert out == IN_DATA.replace(b'\n', b'D')
|
assert out == IN_DATA.replace(b'\n', b'D')
|
||||||
assert (str(N // 2 * N) + "it").encode() in err, "expected arithmetic sum"
|
assert (str(N // 2 * N) + "it").encode() in err, "expected arithmetic sum"
|
||||||
|
|
||||||
# test integer --update_to --delim
|
# test integer --update_to --delim
|
||||||
sys.stdin.seek(0)
|
sys.stdin.seek(0)
|
||||||
main(sys.stderr, ['--update-to', '--delim', 'D'])
|
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 out == IN_DATA.replace(b'\n', b'D')
|
||||||
assert (str(N - 1) + "it").encode() in err
|
assert (str(N - 1) + "it").encode() in err
|
||||||
assert (str(N) + "it").encode() not in err
|
assert (str(N) + "it").encode() not in err
|
||||||
|
|
||||||
# test float --update_to
|
# 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)
|
IN_DATA = b''.join(sys.stdin)
|
||||||
main(sys.stderr, ['--update-to'])
|
main(sys.stderr, ['--update-to'])
|
||||||
out, err = capsysbin.readouterr()
|
out, err = capsysbinary.readouterr()
|
||||||
assert norm(out) == IN_DATA
|
assert norm(out) == IN_DATA
|
||||||
assert (str((N - 1) / 2.0) + "it").encode() in err
|
assert (str((N - 1) / 2.0) + "it").encode() in err
|
||||||
assert (str(N / 2.0) + "it").encode() not in err
|
assert (str(N / 2.0) + "it").encode() not in err
|
||||||
|
@ -213,30 +212,30 @@ def test_comppath(tmp_path):
|
||||||
|
|
||||||
|
|
||||||
@restore_sys
|
@restore_sys
|
||||||
def test_exceptions(capsysbin):
|
def test_exceptions(capsysbinary):
|
||||||
"""Test CLI Exceptions"""
|
"""Test CLI Exceptions"""
|
||||||
N = 123
|
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()
|
IN_DATA = ''.join(sys.stdin).encode()
|
||||||
|
|
||||||
with raises(TqdmKeyError, match="bad_arg_u_ment"):
|
with raises(TqdmKeyError, match="bad_arg_u_ment"):
|
||||||
main(sys.stderr, argv=['-ascii', '-unit_scale', '--bad_arg_u_ment', 'foo'])
|
main(sys.stderr, argv=['-ascii', '-unit_scale', '--bad_arg_u_ment', 'foo'])
|
||||||
out, _ = capsysbin.readouterr()
|
out, _ = capsysbinary.readouterr()
|
||||||
assert norm(out) == IN_DATA
|
assert norm(out) == IN_DATA
|
||||||
|
|
||||||
with raises(TqdmTypeError, match="invalid_bool_value"):
|
with raises(TqdmTypeError, match="invalid_bool_value"):
|
||||||
main(sys.stderr, argv=['-ascii', '-unit_scale', 'invalid_bool_value'])
|
main(sys.stderr, argv=['-ascii', '-unit_scale', 'invalid_bool_value'])
|
||||||
out, _ = capsysbin.readouterr()
|
out, _ = capsysbinary.readouterr()
|
||||||
assert norm(out) == IN_DATA
|
assert norm(out) == IN_DATA
|
||||||
|
|
||||||
with raises(TqdmTypeError, match="invalid_int_value"):
|
with raises(TqdmTypeError, match="invalid_int_value"):
|
||||||
main(sys.stderr, argv=['-ascii', '--total', 'invalid_int_value'])
|
main(sys.stderr, argv=['-ascii', '--total', 'invalid_int_value'])
|
||||||
out, _ = capsysbin.readouterr()
|
out, _ = capsysbinary.readouterr()
|
||||||
assert norm(out) == IN_DATA
|
assert norm(out) == IN_DATA
|
||||||
|
|
||||||
with raises(TqdmKeyError, match="Can only have one of --"):
|
with raises(TqdmKeyError, match="Can only have one of --"):
|
||||||
main(sys.stderr, argv=['--update', '--update_to'])
|
main(sys.stderr, argv=['--update', '--update_to'])
|
||||||
out, _ = capsysbin.readouterr()
|
out, _ = capsysbinary.readouterr()
|
||||||
assert norm(out) == IN_DATA
|
assert norm(out) == IN_DATA
|
||||||
|
|
||||||
# test SystemExits
|
# test SystemExits
|
||||||
|
|
|
@ -4,6 +4,7 @@ from .tests_tqdm import StringIO, closing, importorskip, mark, skip
|
||||||
|
|
||||||
pytestmark = mark.slow
|
pytestmark = mark.slow
|
||||||
|
|
||||||
|
np = importorskip('numpy')
|
||||||
random = importorskip('numpy.random')
|
random = importorskip('numpy.random')
|
||||||
rand = random.rand
|
rand = random.rand
|
||||||
randint = random.randint
|
randint = random.randint
|
||||||
|
@ -39,8 +40,8 @@ def test_pandas_rolling_expanding():
|
||||||
our_file.seek(0)
|
our_file.seek(0)
|
||||||
if our_file.getvalue().count(exres) < 2:
|
if our_file.getvalue().count(exres) < 2:
|
||||||
our_file.seek(0)
|
our_file.seek(0)
|
||||||
raise AssertionError("\nExpected:\n{0}\nIn:\n{1}\n".format(
|
raise AssertionError(
|
||||||
exres + " at least twice.", our_file.read()))
|
f"\nExpected:\n{exres} at least twice.\nIn:\n{our_file.read()}\n")
|
||||||
|
|
||||||
|
|
||||||
def test_pandas_series():
|
def test_pandas_series():
|
||||||
|
@ -62,10 +63,11 @@ def test_pandas_series():
|
||||||
our_file.seek(0)
|
our_file.seek(0)
|
||||||
if our_file.getvalue().count(exres) < 2:
|
if our_file.getvalue().count(exres) < 2:
|
||||||
our_file.seek(0)
|
our_file.seek(0)
|
||||||
raise AssertionError("\nExpected:\n{0}\nIn:\n{1}\n".format(
|
raise AssertionError(
|
||||||
exres + " at least twice.", our_file.read()))
|
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():
|
def test_pandas_data_frame():
|
||||||
"""Test pandas.DataFrame.progress_apply and .progress_applymap"""
|
"""Test pandas.DataFrame.progress_apply and .progress_applymap"""
|
||||||
with closing(StringIO()) as our_file:
|
with closing(StringIO()) as our_file:
|
||||||
|
@ -80,6 +82,12 @@ def test_pandas_data_frame():
|
||||||
res2 = df.applymap(task_func)
|
res2 = df.applymap(task_func)
|
||||||
assert res1.equals(res2)
|
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
|
# apply unhashable
|
||||||
res1 = []
|
res1 = []
|
||||||
df.progress_apply(res1.extend)
|
df.progress_apply(res1.extend)
|
||||||
|
@ -94,8 +102,8 @@ def test_pandas_data_frame():
|
||||||
our_file.seek(0)
|
our_file.seek(0)
|
||||||
if our_file.read().count('100%') < 3:
|
if our_file.read().count('100%') < 3:
|
||||||
our_file.seek(0)
|
our_file.seek(0)
|
||||||
raise AssertionError("\nExpected:\n{0}\nIn:\n{1}\n".format(
|
raise AssertionError(
|
||||||
'100% at least three times', our_file.read()))
|
f"\nExpected:\n100% at least three times\nIn:\n{our_file.read()}\n")
|
||||||
|
|
||||||
# apply_map, apply axis=0, apply axis=1
|
# apply_map, apply axis=0, apply axis=1
|
||||||
expects = ['20000/20000', '200/200', '100/100']
|
expects = ['20000/20000', '200/200', '100/100']
|
||||||
|
@ -103,10 +111,12 @@ def test_pandas_data_frame():
|
||||||
our_file.seek(0)
|
our_file.seek(0)
|
||||||
if our_file.getvalue().count(exres) < 1:
|
if our_file.getvalue().count(exres) < 1:
|
||||||
our_file.seek(0)
|
our_file.seek(0)
|
||||||
raise AssertionError("\nExpected:\n{0}\nIn:\n {1}\n".format(
|
raise AssertionError(
|
||||||
exres + " at least once.", our_file.read()))
|
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():
|
def test_pandas_groupby_apply():
|
||||||
"""Test pandas.DataFrame.groupby(...).progress_apply"""
|
"""Test pandas.DataFrame.groupby(...).progress_apply"""
|
||||||
with closing(StringIO()) as our_file:
|
with closing(StringIO()) as our_file:
|
||||||
|
@ -119,8 +129,8 @@ def test_pandas_groupby_apply():
|
||||||
dfs.groupby(['a']).progress_apply(lambda x: None)
|
dfs.groupby(['a']).progress_apply(lambda x: None)
|
||||||
|
|
||||||
df2 = df = pd.DataFrame({'a': randint(1, 8, 10000), 'b': rand(10000)})
|
df2 = df = pd.DataFrame({'a': randint(1, 8, 10000), 'b': rand(10000)})
|
||||||
res1 = df2.groupby("a").apply(max)
|
res1 = df2.groupby("a").apply(np.maximum.reduce)
|
||||||
res2 = df2.groupby("a").progress_apply(max)
|
res2 = df2.groupby("a").progress_apply(np.maximum.reduce)
|
||||||
assert res1.equals(res2)
|
assert res1.equals(res2)
|
||||||
|
|
||||||
our_file.seek(0)
|
our_file.seek(0)
|
||||||
|
@ -130,8 +140,7 @@ def test_pandas_groupby_apply():
|
||||||
nexres = '100%|##########|'
|
nexres = '100%|##########|'
|
||||||
if nexres in our_file.read():
|
if nexres in our_file.read():
|
||||||
our_file.seek(0)
|
our_file.seek(0)
|
||||||
raise AssertionError("\nDid not expect:\n{0}\nIn:{1}\n".format(
|
raise AssertionError(f"\nDid not expect:\n{nexres}\nIn:{our_file.read()}\n")
|
||||||
nexres, our_file.read()))
|
|
||||||
|
|
||||||
with closing(StringIO()) as our_file:
|
with closing(StringIO()) as our_file:
|
||||||
tqdm.pandas(file=our_file, leave=True, ascii=True)
|
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.loc[0] = [2, 1, 1]
|
||||||
dfs['d'] = 100
|
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(dfs.index).progress_apply(lambda x: None)
|
||||||
dfs.groupby('d').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.T.groupby(dfs.columns).progress_apply(lambda x: None)
|
||||||
dfs.groupby([2, 2, 1, 1], axis=1).progress_apply(lambda x: None)
|
dfs.T.groupby([2, 2, 1, 1]).progress_apply(lambda x: None)
|
||||||
|
|
||||||
our_file.seek(0)
|
our_file.seek(0)
|
||||||
if our_file.read().count('100%') < 4:
|
if our_file.read().count('100%') < 4:
|
||||||
our_file.seek(0)
|
our_file.seek(0)
|
||||||
raise AssertionError("\nExpected:\n{0}\nIn:\n{1}\n".format(
|
raise AssertionError(
|
||||||
'100% at least four times', our_file.read()))
|
f"\nExpected:\n100% at least four times\nIn:\n{our_file.read()}\n")
|
||||||
|
|
||||||
for exres in expects:
|
for exres in expects:
|
||||||
our_file.seek(0)
|
our_file.seek(0)
|
||||||
if our_file.getvalue().count(exres) < 1:
|
if our_file.getvalue().count(exres) < 1:
|
||||||
our_file.seek(0)
|
our_file.seek(0)
|
||||||
raise AssertionError("\nExpected:\n{0}\nIn:\n {1}\n".format(
|
raise AssertionError(
|
||||||
exres + " at least once.", our_file.read()))
|
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():
|
def test_pandas_leave():
|
||||||
"""Test pandas with `leave=True`"""
|
"""Test pandas with `leave=True`"""
|
||||||
with closing(StringIO()) as our_file:
|
with closing(StringIO()) as our_file:
|
||||||
|
@ -172,8 +183,7 @@ def test_pandas_leave():
|
||||||
exres = '100%|##########| 100/100'
|
exres = '100%|##########| 100/100'
|
||||||
if exres not in our_file.read():
|
if exres not in our_file.read():
|
||||||
our_file.seek(0)
|
our_file.seek(0)
|
||||||
raise AssertionError("\nExpected:\n{0}\nIn:{1}\n".format(
|
raise AssertionError(f"\nExpected:\n{exres}\nIn:{our_file.read()}\n")
|
||||||
exres, our_file.read()))
|
|
||||||
|
|
||||||
|
|
||||||
def test_pandas_apply_args_deprecation():
|
def test_pandas_apply_args_deprecation():
|
||||||
|
@ -195,6 +205,8 @@ def test_pandas_apply_args_deprecation():
|
||||||
"keyword arguments instead"))
|
"keyword arguments instead"))
|
||||||
|
|
||||||
|
|
||||||
|
@mark.filterwarnings(
|
||||||
|
"ignore:DataFrameGroupBy.apply operated on the grouping columns:DeprecationWarning")
|
||||||
def test_pandas_deprecation():
|
def test_pandas_deprecation():
|
||||||
"""Test bar object instance as argument deprecation"""
|
"""Test bar object instance as argument deprecation"""
|
||||||
try:
|
try:
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
from __future__ import division, print_function
|
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
from contextlib import contextmanager
|
from contextlib import contextmanager
|
||||||
from functools import wraps
|
from functools import wraps
|
||||||
|
@ -14,7 +12,7 @@ except ImportError:
|
||||||
|
|
||||||
from tqdm import tqdm, trange
|
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
|
pytestmark = mark.slow
|
||||||
|
|
||||||
|
@ -98,10 +96,7 @@ def simple_progress(iterable=None, total=None, file=sys.stdout, desc='',
|
||||||
def format_interval(t):
|
def format_interval(t):
|
||||||
mins, s = divmod(int(t), 60)
|
mins, s = divmod(int(t), 60)
|
||||||
h, m = divmod(mins, 60)
|
h, m = divmod(mins, 60)
|
||||||
if h:
|
return f'{h:d}:{m:02d}:{s:02d}' if h else f'{m:02d}:{s:02d}'
|
||||||
return '{0:d}:{1:02d}:{2:02d}'.format(h, m, s)
|
|
||||||
else:
|
|
||||||
return '{0:02d}:{1:02d}'.format(m, s)
|
|
||||||
|
|
||||||
def update_and_print(i=1):
|
def update_and_print(i=1):
|
||||||
n[0] += i
|
n[0] += i
|
||||||
|
@ -143,7 +138,6 @@ def simple_progress(iterable=None, total=None, file=sys.stdout, desc='',
|
||||||
update_and_print(0)
|
update_and_print(0)
|
||||||
if iterable is not None:
|
if iterable is not None:
|
||||||
return update_and_yield()
|
return update_and_yield()
|
||||||
else:
|
|
||||||
return update_and_print
|
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"""
|
"""raises if time_left > thresh * time_right"""
|
||||||
if time_left > thresh * time_right:
|
if time_left > thresh * time_right:
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
('{name[0]}: {time[0]:f}, '
|
f'{name_left}: {time_left:f}, {name_right}: {time_right:f}'
|
||||||
'{name[1]}: {time[1]:f}, '
|
f', ratio {time_left / time_right:f} > {thresh:f}')
|
||||||
'ratio {ratio:f} > {thresh:f}').format(
|
|
||||||
name=(name_left, name_right),
|
|
||||||
time=(time_left, time_right),
|
|
||||||
ratio=time_left / time_right, thresh=thresh))
|
|
||||||
|
|
||||||
|
|
||||||
@retry_on_except()
|
@retry_on_except()
|
||||||
|
@ -173,7 +163,7 @@ def test_iter_basic_overhead():
|
||||||
|
|
||||||
a = 0
|
a = 0
|
||||||
with relative_timer() as time_bench:
|
with relative_timer() as time_bench:
|
||||||
for i in _range(total):
|
for i in range(total):
|
||||||
a += i
|
a += i
|
||||||
sys.stdout.write(str(a))
|
sys.stdout.write(str(a))
|
||||||
|
|
||||||
|
@ -188,13 +178,13 @@ def test_manual_basic_overhead():
|
||||||
with tqdm(total=total * 10, leave=True) as t:
|
with tqdm(total=total * 10, leave=True) as t:
|
||||||
a = 0
|
a = 0
|
||||||
with relative_timer() as time_tqdm:
|
with relative_timer() as time_tqdm:
|
||||||
for i in _range(total):
|
for i in range(total):
|
||||||
a += i
|
a += i
|
||||||
t.update(10)
|
t.update(10)
|
||||||
|
|
||||||
a = 0
|
a = 0
|
||||||
with relative_timer() as time_bench:
|
with relative_timer() as time_bench:
|
||||||
for i in _range(total):
|
for i in range(total):
|
||||||
a += i
|
a += i
|
||||||
sys.stdout.write(str(a))
|
sys.stdout.write(str(a))
|
||||||
|
|
||||||
|
@ -249,7 +239,7 @@ def test_iter_overhead_hard():
|
||||||
|
|
||||||
a = 0
|
a = 0
|
||||||
with relative_timer() as time_bench:
|
with relative_timer() as time_bench:
|
||||||
for i in _range(total):
|
for i in range(total):
|
||||||
a += i
|
a += i
|
||||||
sys.stdout.write(("%i" % a) * 40)
|
sys.stdout.write(("%i" % a) * 40)
|
||||||
|
|
||||||
|
@ -265,13 +255,13 @@ def test_manual_overhead_hard():
|
||||||
mininterval=0, maxinterval=0) as t:
|
mininterval=0, maxinterval=0) as t:
|
||||||
a = 0
|
a = 0
|
||||||
with relative_timer() as time_tqdm:
|
with relative_timer() as time_tqdm:
|
||||||
for i in _range(total):
|
for i in range(total):
|
||||||
a += i
|
a += i
|
||||||
t.update(10)
|
t.update(10)
|
||||||
|
|
||||||
a = 0
|
a = 0
|
||||||
with relative_timer() as time_bench:
|
with relative_timer() as time_bench:
|
||||||
for i in _range(total):
|
for i in range(total):
|
||||||
a += i
|
a += i
|
||||||
sys.stdout.write(("%i" % a) * 40)
|
sys.stdout.write(("%i" % a) * 40)
|
||||||
|
|
||||||
|
@ -292,7 +282,7 @@ def test_iter_overhead_simplebar_hard():
|
||||||
assert a == (total ** 2 - total) / 2.0
|
assert a == (total ** 2 - total) / 2.0
|
||||||
|
|
||||||
a = 0
|
a = 0
|
||||||
s = simple_progress(_range(total), leave=True,
|
s = simple_progress(range(total), leave=True,
|
||||||
miniters=1, mininterval=0)
|
miniters=1, mininterval=0)
|
||||||
with relative_timer() as time_bench:
|
with relative_timer() as time_bench:
|
||||||
for i in s:
|
for i in s:
|
||||||
|
@ -310,7 +300,7 @@ def test_manual_overhead_simplebar_hard():
|
||||||
mininterval=0, maxinterval=0) as t:
|
mininterval=0, maxinterval=0) as t:
|
||||||
a = 0
|
a = 0
|
||||||
with relative_timer() as time_tqdm:
|
with relative_timer() as time_tqdm:
|
||||||
for i in _range(total):
|
for i in range(total):
|
||||||
a += i
|
a += i
|
||||||
t.update(10)
|
t.update(10)
|
||||||
|
|
||||||
|
@ -318,7 +308,7 @@ def test_manual_overhead_simplebar_hard():
|
||||||
miniters=1, mininterval=0)
|
miniters=1, mininterval=0)
|
||||||
a = 0
|
a = 0
|
||||||
with relative_timer() as time_bench:
|
with relative_timer() as time_bench:
|
||||||
for i in _range(total):
|
for i in range(total):
|
||||||
a += i
|
a += i
|
||||||
simplebar_update(10)
|
simplebar_update(10)
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,7 @@
|
||||||
"""Test `tqdm.rich`."""
|
"""Test `tqdm.rich`."""
|
||||||
import sys
|
from .tests_tqdm import importorskip
|
||||||
|
|
||||||
from .tests_tqdm import importorskip, mark
|
|
||||||
|
|
||||||
|
|
||||||
@mark.skipif(sys.version_info[:3] < (3, 6, 1), reason="`rich` needs py>=3.6.1")
|
|
||||||
def test_rich_import():
|
def test_rich_import():
|
||||||
"""Test `tqdm.rich` import"""
|
"""Test `tqdm.rich` import"""
|
||||||
importorskip('tqdm.rich')
|
importorskip('tqdm.rich')
|
||||||
|
|
|
@ -1,13 +1,9 @@
|
||||||
from __future__ import division
|
|
||||||
|
|
||||||
import sys
|
|
||||||
from functools import wraps
|
from functools import wraps
|
||||||
from threading import Event
|
from threading import Event
|
||||||
from time import sleep, time
|
from time import sleep, time
|
||||||
|
|
||||||
from tqdm import TMonitor, tqdm, trange
|
from tqdm import TMonitor, tqdm, trange
|
||||||
|
|
||||||
from .tests_perf import retry_on_except
|
|
||||||
from .tests_tqdm import StringIO, closing, importorskip, patch_lock, skip
|
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)
|
sleep(0.000001) # sleep to allow interrupt (instead of pass)
|
||||||
|
|
||||||
|
|
||||||
def FakeEvent():
|
class FakeEvent(Event):
|
||||||
"""patched `threading.Event` where `wait()` uses `Time.fake_sleep()`"""
|
"""patched `threading.Event` where `wait()` uses `Time.fake_sleep()`"""
|
||||||
event = Event() # not a class in py2 so can't inherit
|
def wait(self, timeout=None):
|
||||||
|
|
||||||
def wait(timeout=None):
|
|
||||||
"""uses Time.fake_sleep"""
|
"""uses Time.fake_sleep"""
|
||||||
if timeout is not None:
|
if timeout is not None:
|
||||||
Time.fake_sleep(timeout)
|
Time.fake_sleep(timeout)
|
||||||
return event.is_set()
|
return self.is_set()
|
||||||
|
|
||||||
event.wait = wait
|
|
||||||
return event
|
|
||||||
|
|
||||||
|
|
||||||
def patch_sleep(func):
|
def patch_sleep(func):
|
||||||
|
@ -206,19 +197,11 @@ def test_imap():
|
||||||
assert res[-1] == 100
|
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)
|
@patch_lock(thread=True)
|
||||||
def test_threadpool():
|
def test_threadpool():
|
||||||
"""Test concurrent.futures.ThreadPoolExecutor"""
|
"""Test concurrent.futures.ThreadPoolExecutor"""
|
||||||
ThreadPoolExecutor = importorskip('concurrent.futures').ThreadPoolExecutor
|
ThreadPoolExecutor = importorskip('concurrent.futures').ThreadPoolExecutor
|
||||||
|
|
||||||
with ThreadPoolExecutor(8) as pool:
|
with ThreadPoolExecutor(8) as pool:
|
||||||
try:
|
|
||||||
res = list(tqdm(pool.map(incr_bar, range(100)), disable=True))
|
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))
|
assert sum(res) == sum(range(1, 101))
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
# Advice: use repr(our_file.read()) to print the full output of tqdm
|
# 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.
|
# (else '\r' will replace the previous lines and you'll see only the latest.
|
||||||
from __future__ import print_function
|
|
||||||
|
|
||||||
import csv
|
import csv
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
|
@ -37,16 +35,6 @@ if getattr(StringIO, '__exit__', False) and getattr(StringIO, '__enter__', False
|
||||||
else:
|
else:
|
||||||
from contextlib import closing
|
from contextlib import closing
|
||||||
|
|
||||||
try:
|
|
||||||
_range = xrange
|
|
||||||
except NameError:
|
|
||||||
_range = range
|
|
||||||
|
|
||||||
try:
|
|
||||||
_unicode = unicode
|
|
||||||
except NameError:
|
|
||||||
_unicode = str
|
|
||||||
|
|
||||||
nt_and_no_colorama = False
|
nt_and_no_colorama = False
|
||||||
if os.name == 'nt':
|
if os.name == 'nt':
|
||||||
try:
|
try:
|
||||||
|
@ -119,7 +107,7 @@ def cpu_timify(t, timer=None):
|
||||||
class UnicodeIO(IOBase):
|
class UnicodeIO(IOBase):
|
||||||
"""Unicode version of StringIO"""
|
"""Unicode version of StringIO"""
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super(UnicodeIO, self).__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
self.encoding = 'U8' # io.StringIO supports unicode, but no encoding
|
self.encoding = 'U8' # io.StringIO supports unicode, but no encoding
|
||||||
self.text = ''
|
self.text = ''
|
||||||
self.cursor = 0
|
self.cursor = 0
|
||||||
|
@ -201,6 +189,8 @@ def test_format_num():
|
||||||
assert float(format_num(1337)) == 1337
|
assert float(format_num(1337)) == 1337
|
||||||
assert format_num(int(1e6)) == '1e+6'
|
assert format_num(int(1e6)) == '1e+6'
|
||||||
assert format_num(1239876) == '1' '239' '876'
|
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():
|
def test_format_meter():
|
||||||
|
@ -271,7 +261,6 @@ def test_format_meter():
|
||||||
20, 100, 12, ncols=14, rate=8.1,
|
20, 100, 12, ncols=14, rate=8.1,
|
||||||
bar_format=r'{l_bar}{bar}|{n_fmt}/{total_fmt}') == " 20%|" + unich(0x258d) + " |20/100"
|
bar_format=r'{l_bar}{bar}|{n_fmt}/{total_fmt}') == " 20%|" + unich(0x258d) + " |20/100"
|
||||||
# Check wide characters
|
# Check wide characters
|
||||||
if sys.version_info >= (3,):
|
|
||||||
assert format_meter(0, 1000, 13, ncols=68, prefix='fullwidth: ') == (
|
assert format_meter(0, 1000, 13, ncols=68, prefix='fullwidth: ') == (
|
||||||
"fullwidth: 0%| | 0/1000 [00:13<?, ?it/s]")
|
"fullwidth: 0%| | 0/1000 [00:13<?, ?it/s]")
|
||||||
assert format_meter(0, 1000, 13, ncols=68, prefix='ニッポン [ニッポン]: ') == (
|
assert format_meter(0, 1000, 13, ncols=68, prefix='ニッポン [ニッポン]: ') == (
|
||||||
|
@ -328,11 +317,11 @@ def test_si_format():
|
||||||
|
|
||||||
def test_bar_formatspec():
|
def test_bar_formatspec():
|
||||||
"""Test Bar.__format__ spec"""
|
"""Test Bar.__format__ spec"""
|
||||||
assert "{0:5a}".format(Bar(0.3)) == "#5 "
|
assert f"{Bar(0.3):5a}" == "#5 "
|
||||||
assert "{0:2}".format(Bar(0.5, charset=" .oO0")) == "0 "
|
assert f"{Bar(0.5, charset=' .oO0'):2}" == "0 "
|
||||||
assert "{0:2a}".format(Bar(0.5, charset=" .oO0")) == "# "
|
assert f"{Bar(0.5, charset=' .oO0'):2a}" == "# "
|
||||||
assert "{0:-6a}".format(Bar(0.5, 10)) == '## '
|
assert f"{Bar(0.5, 10):-6a}" == '## '
|
||||||
assert "{0:2b}".format(Bar(0.5, 10)) == ' '
|
assert f"{Bar(0.5, 10):2b}" == ' '
|
||||||
|
|
||||||
|
|
||||||
def test_all_defaults():
|
def test_all_defaults():
|
||||||
|
@ -353,7 +342,7 @@ def test_all_defaults():
|
||||||
class WriteTypeChecker(BytesIO):
|
class WriteTypeChecker(BytesIO):
|
||||||
"""File-like to assert the expected type is written"""
|
"""File-like to assert the expected type is written"""
|
||||||
def __init__(self, expected_type):
|
def __init__(self, expected_type):
|
||||||
super(WriteTypeChecker, self).__init__()
|
super().__init__()
|
||||||
self.expected_type = expected_type
|
self.expected_type = expected_type
|
||||||
|
|
||||||
def write(self, s):
|
def write(self, s):
|
||||||
|
@ -401,7 +390,7 @@ def test_iterate_over_csv_rows():
|
||||||
# Create a test csv pseudo file
|
# Create a test csv pseudo file
|
||||||
with closing(StringIO()) as test_csv_file:
|
with closing(StringIO()) as test_csv_file:
|
||||||
writer = csv.writer(test_csv_file)
|
writer = csv.writer(test_csv_file)
|
||||||
for _ in _range(3):
|
for _ in range(3):
|
||||||
writer.writerow(['test'] * 3)
|
writer.writerow(['test'] * 3)
|
||||||
test_csv_file.seek(0)
|
test_csv_file.seek(0)
|
||||||
|
|
||||||
|
@ -415,7 +404,7 @@ def test_iterate_over_csv_rows():
|
||||||
def test_file_output():
|
def test_file_output():
|
||||||
"""Test output to arbitrary file-like objects"""
|
"""Test output to arbitrary file-like objects"""
|
||||||
with closing(StringIO()) as our_file:
|
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:
|
if i == 1:
|
||||||
our_file.seek(0)
|
our_file.seek(0)
|
||||||
assert '0/3' in our_file.read()
|
assert '0/3' in our_file.read()
|
||||||
|
@ -424,14 +413,14 @@ def test_file_output():
|
||||||
def test_leave_option():
|
def test_leave_option():
|
||||||
"""Test `leave=True` always prints info about the last iteration"""
|
"""Test `leave=True` always prints info about the last iteration"""
|
||||||
with closing(StringIO()) as our_file:
|
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
|
pass
|
||||||
res = our_file.getvalue()
|
res = our_file.getvalue()
|
||||||
assert '| 3/3 ' in res
|
assert '| 3/3 ' in res
|
||||||
assert '\n' == res[-1] # not '\r'
|
assert '\n' == res[-1] # not '\r'
|
||||||
|
|
||||||
with closing(StringIO()) as our_file2:
|
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
|
pass
|
||||||
assert '| 3/3 ' not in our_file2.getvalue()
|
assert '| 3/3 ' not in our_file2.getvalue()
|
||||||
|
|
||||||
|
@ -452,7 +441,7 @@ def test_trange():
|
||||||
def test_min_interval():
|
def test_min_interval():
|
||||||
"""Test mininterval"""
|
"""Test mininterval"""
|
||||||
with closing(StringIO()) as our_file:
|
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
|
pass
|
||||||
assert " 0%| | 0/3 [00:00<" in our_file.getvalue()
|
assert " 0%| | 0/3 [00:00<" in our_file.getvalue()
|
||||||
|
|
||||||
|
@ -484,7 +473,7 @@ def test_max_interval():
|
||||||
t.update(bigstep)
|
t.update(bigstep)
|
||||||
t2.update(bigstep)
|
t2.update(bigstep)
|
||||||
# The next iterations should not trigger maxinterval (step 10)
|
# The next iterations should not trigger maxinterval (step 10)
|
||||||
for _ in _range(4):
|
for _ in range(4):
|
||||||
t.update(smallstep)
|
t.update(smallstep)
|
||||||
t2.update(smallstep)
|
t2.update(smallstep)
|
||||||
timer.sleep(1e-5)
|
timer.sleep(1e-5)
|
||||||
|
@ -504,7 +493,7 @@ def test_max_interval():
|
||||||
# Increase 10 iterations at once
|
# Increase 10 iterations at once
|
||||||
t.update(bigstep)
|
t.update(bigstep)
|
||||||
# The next iterations should trigger maxinterval (step 5)
|
# The next iterations should trigger maxinterval (step 5)
|
||||||
for _ in _range(4):
|
for _ in range(4):
|
||||||
t.update(smallstep)
|
t.update(smallstep)
|
||||||
timer.sleep(1e-2)
|
timer.sleep(1e-2)
|
||||||
|
|
||||||
|
@ -513,7 +502,7 @@ def test_max_interval():
|
||||||
# Test iteration based tqdm with maxinterval effect
|
# Test iteration based tqdm with maxinterval effect
|
||||||
timer = DiscreteTimer()
|
timer = DiscreteTimer()
|
||||||
with closing(StringIO()) as our_file:
|
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:
|
mininterval=1e-5, smoothing=1, maxinterval=1e-4) as t2:
|
||||||
cpu_timify(t2, timer)
|
cpu_timify(t2, timer)
|
||||||
|
|
||||||
|
@ -560,9 +549,9 @@ def test_max_interval():
|
||||||
mininterval = 0.1
|
mininterval = 0.1
|
||||||
maxinterval = 10
|
maxinterval = 10
|
||||||
with closing(StringIO()) as our_file:
|
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)
|
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)
|
mininterval=0, maxinterval=maxinterval)
|
||||||
|
|
||||||
cpu_timify(t1, timer1)
|
cpu_timify(t1, timer1)
|
||||||
|
@ -605,7 +594,7 @@ def test_delay():
|
||||||
def test_min_iters():
|
def test_min_iters():
|
||||||
"""Test miniters"""
|
"""Test miniters"""
|
||||||
with closing(StringIO()) as our_file:
|
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
|
pass
|
||||||
|
|
||||||
out = our_file.getvalue()
|
out = our_file.getvalue()
|
||||||
|
@ -615,7 +604,7 @@ def test_min_iters():
|
||||||
assert '| 3/3 ' in out
|
assert '| 3/3 ' in out
|
||||||
|
|
||||||
with closing(StringIO()) as our_file:
|
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
|
pass
|
||||||
|
|
||||||
out = our_file.getvalue()
|
out = our_file.getvalue()
|
||||||
|
@ -669,7 +658,7 @@ def test_dynamic_min_iters():
|
||||||
|
|
||||||
# Check iterable based tqdm
|
# Check iterable based tqdm
|
||||||
with closing(StringIO()) as our_file:
|
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)
|
smoothing=0.5)
|
||||||
for _ in t:
|
for _ in t:
|
||||||
pass
|
pass
|
||||||
|
@ -677,7 +666,7 @@ def test_dynamic_min_iters():
|
||||||
|
|
||||||
# No smoothing
|
# No smoothing
|
||||||
with closing(StringIO()) as our_file:
|
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)
|
smoothing=0)
|
||||||
for _ in t:
|
for _ in t:
|
||||||
pass
|
pass
|
||||||
|
@ -685,7 +674,7 @@ def test_dynamic_min_iters():
|
||||||
|
|
||||||
# No dynamic_miniters (miniters is fixed manually)
|
# No dynamic_miniters (miniters is fixed manually)
|
||||||
with closing(StringIO()) as our_file:
|
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:
|
for _ in t:
|
||||||
pass
|
pass
|
||||||
assert not t.dynamic_miniters
|
assert not t.dynamic_miniters
|
||||||
|
@ -694,12 +683,12 @@ def test_dynamic_min_iters():
|
||||||
def test_big_min_interval():
|
def test_big_min_interval():
|
||||||
"""Test large mininterval"""
|
"""Test large mininterval"""
|
||||||
with closing(StringIO()) as our_file:
|
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
|
pass
|
||||||
assert '50%' not in our_file.getvalue()
|
assert '50%' not in our_file.getvalue()
|
||||||
|
|
||||||
with closing(StringIO()) as our_file:
|
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()
|
||||||
t.update()
|
t.update()
|
||||||
assert '50%' not in our_file.getvalue()
|
assert '50%' not in our_file.getvalue()
|
||||||
|
@ -718,10 +707,10 @@ def test_smoothed_dynamic_min_iters():
|
||||||
timer.sleep(1)
|
timer.sleep(1)
|
||||||
t.update(10)
|
t.update(10)
|
||||||
# The next iterations should be partially skipped
|
# The next iterations should be partially skipped
|
||||||
for _ in _range(2):
|
for _ in range(2):
|
||||||
timer.sleep(1)
|
timer.sleep(1)
|
||||||
t.update(4)
|
t.update(4)
|
||||||
for _ in _range(20):
|
for _ in range(20):
|
||||||
timer.sleep(1)
|
timer.sleep(1)
|
||||||
t.update()
|
t.update()
|
||||||
|
|
||||||
|
@ -750,7 +739,7 @@ def test_smoothed_dynamic_min_iters_with_min_interval():
|
||||||
|
|
||||||
t.update(10)
|
t.update(10)
|
||||||
timer.sleep(1e-2)
|
timer.sleep(1e-2)
|
||||||
for _ in _range(4):
|
for _ in range(4):
|
||||||
t.update()
|
t.update()
|
||||||
timer.sleep(1e-2)
|
timer.sleep(1e-2)
|
||||||
out = our_file.getvalue()
|
out = our_file.getvalue()
|
||||||
|
@ -758,7 +747,7 @@ def test_smoothed_dynamic_min_iters_with_min_interval():
|
||||||
|
|
||||||
with closing(StringIO()) as our_file:
|
with closing(StringIO()) as our_file:
|
||||||
# Test iteration-based tqdm
|
# 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:
|
mininterval=0.01, smoothing=1, maxinterval=0) as t2:
|
||||||
cpu_timify(t2, timer)
|
cpu_timify(t2, timer)
|
||||||
|
|
||||||
|
@ -817,7 +806,7 @@ def _rlock_creation_target():
|
||||||
def test_disable():
|
def test_disable():
|
||||||
"""Test disable"""
|
"""Test disable"""
|
||||||
with closing(StringIO()) as our_file:
|
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
|
pass
|
||||||
assert our_file.getvalue() == ''
|
assert our_file.getvalue() == ''
|
||||||
|
|
||||||
|
@ -831,7 +820,7 @@ def test_disable():
|
||||||
def test_infinite_total():
|
def test_infinite_total():
|
||||||
"""Test treatment of infinite total"""
|
"""Test treatment of infinite total"""
|
||||||
with closing(StringIO()) as our_file:
|
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
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
@ -852,7 +841,7 @@ def test_nototal():
|
||||||
def test_unit():
|
def test_unit():
|
||||||
"""Test SI unit prefix"""
|
"""Test SI unit prefix"""
|
||||||
with closing(StringIO()) as our_file:
|
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
|
pass
|
||||||
assert 'bytes/s' in our_file.getvalue()
|
assert 'bytes/s' in our_file.getvalue()
|
||||||
|
|
||||||
|
@ -866,7 +855,7 @@ def test_ascii():
|
||||||
|
|
||||||
# Test ascii bar
|
# Test ascii bar
|
||||||
with closing(StringIO()) as our_file:
|
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):
|
mininterval=0, ascii=True):
|
||||||
pass
|
pass
|
||||||
res = our_file.getvalue().strip("\r").split("\r")
|
res = our_file.getvalue().strip("\r").split("\r")
|
||||||
|
@ -877,7 +866,7 @@ def test_ascii():
|
||||||
# Test unicode bar
|
# Test unicode bar
|
||||||
with closing(UnicodeIO()) as our_file:
|
with closing(UnicodeIO()) as our_file:
|
||||||
with tqdm(total=15, file=our_file, ascii=False, mininterval=0) as t:
|
with tqdm(total=15, file=our_file, ascii=False, mininterval=0) as t:
|
||||||
for _ in _range(3):
|
for _ in range(3):
|
||||||
t.update()
|
t.update()
|
||||||
res = our_file.getvalue().strip("\r").split("\r")
|
res = our_file.getvalue().strip("\r").split("\r")
|
||||||
assert u"7%|\u258b" in res[1]
|
assert u"7%|\u258b" in res[1]
|
||||||
|
@ -887,7 +876,7 @@ def test_ascii():
|
||||||
# Test custom bar
|
# Test custom bar
|
||||||
for bars in [" .oO0", " #"]:
|
for bars in [" .oO0", " #"]:
|
||||||
with closing(StringIO()) as our_file:
|
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):
|
mininterval=0, ascii=bars, ncols=27):
|
||||||
pass
|
pass
|
||||||
res = our_file.getvalue().strip("\r").split("\r")
|
res = our_file.getvalue().strip("\r").split("\r")
|
||||||
|
@ -949,8 +938,7 @@ def test_close():
|
||||||
res = our_file.getvalue()
|
res = our_file.getvalue()
|
||||||
assert res[-1] == '\n'
|
assert res[-1] == '\n'
|
||||||
if not res.startswith(exres):
|
if not res.startswith(exres):
|
||||||
raise AssertionError("\n<<< Expected:\n{0}\n>>> Got:\n{1}\n===".format(
|
raise AssertionError(f"\n<<< Expected:\n{exres}, ...it/s]\n>>> Got:\n{res}\n===")
|
||||||
exres + ', ...it/s]\n', our_file.getvalue()))
|
|
||||||
|
|
||||||
# Closing after the output stream has closed
|
# Closing after the output stream has closed
|
||||||
with closing(StringIO()) as our_file:
|
with closing(StringIO()) as our_file:
|
||||||
|
@ -976,7 +964,7 @@ def test_smoothing():
|
||||||
|
|
||||||
# -- Test disabling smoothing
|
# -- Test disabling smoothing
|
||||||
with closing(StringIO()) as our_file:
|
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)
|
cpu_timify(t, timer)
|
||||||
|
|
||||||
for _ in t:
|
for _ in t:
|
||||||
|
@ -987,11 +975,11 @@ def test_smoothing():
|
||||||
# 1st case: no smoothing (only use average)
|
# 1st case: no smoothing (only use average)
|
||||||
with closing(StringIO()) as our_file2:
|
with closing(StringIO()) as our_file2:
|
||||||
with closing(StringIO()) as our_file:
|
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)
|
miniters=1, mininterval=0)
|
||||||
cpu_timify(t, timer)
|
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:
|
miniters=1, mininterval=0) as t2:
|
||||||
cpu_timify(t2, timer)
|
cpu_timify(t2, timer)
|
||||||
|
|
||||||
|
@ -1017,11 +1005,11 @@ def test_smoothing():
|
||||||
# 2nd case: use max smoothing (= instant rate)
|
# 2nd case: use max smoothing (= instant rate)
|
||||||
with closing(StringIO()) as our_file2:
|
with closing(StringIO()) as our_file2:
|
||||||
with closing(StringIO()) as our_file:
|
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)
|
miniters=1, mininterval=0)
|
||||||
cpu_timify(t, timer)
|
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:
|
miniters=1, mininterval=0) as t2:
|
||||||
cpu_timify(t2, timer)
|
cpu_timify(t2, timer)
|
||||||
|
|
||||||
|
@ -1040,11 +1028,11 @@ def test_smoothing():
|
||||||
# 3rd case: use medium smoothing
|
# 3rd case: use medium smoothing
|
||||||
with closing(StringIO()) as our_file2:
|
with closing(StringIO()) as our_file2:
|
||||||
with closing(StringIO()) as our_file:
|
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)
|
miniters=1, mininterval=0)
|
||||||
cpu_timify(t, timer)
|
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)
|
miniters=1, mininterval=0)
|
||||||
cpu_timify(t2, timer)
|
cpu_timify(t2, timer)
|
||||||
|
|
||||||
|
@ -1098,7 +1086,7 @@ def test_bar_format():
|
||||||
with closing(StringIO()) as our_file:
|
with closing(StringIO()) as our_file:
|
||||||
bar_format = r'hello world'
|
bar_format = r'hello world'
|
||||||
with tqdm(ascii=False, bar_format=bar_format, file=our_file) as t:
|
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():
|
def test_custom_format():
|
||||||
|
@ -1107,7 +1095,7 @@ def test_custom_format():
|
||||||
"""Provides a `total_time` format parameter"""
|
"""Provides a `total_time` format parameter"""
|
||||||
@property
|
@property
|
||||||
def format_dict(self):
|
def format_dict(self):
|
||||||
d = super(TqdmExtraFormat, self).format_dict
|
d = super().format_dict
|
||||||
total_time = d["elapsed"] * (d["total"] or 0) / max(d["n"], 1)
|
total_time = d["elapsed"] * (d["total"] or 0) / max(d["n"], 1)
|
||||||
d.update(total_time=self.format_interval(total_time) + " in total")
|
d.update(total_time=self.format_interval(total_time) + " in total")
|
||||||
return d
|
return d
|
||||||
|
@ -1127,7 +1115,7 @@ def test_eta(capsys):
|
||||||
bar_format='{l_bar}{eta:%Y-%m-%d}'):
|
bar_format='{l_bar}{eta:%Y-%m-%d}'):
|
||||||
pass
|
pass
|
||||||
_, err = capsys.readouterr()
|
_, 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():
|
def test_unpause():
|
||||||
|
@ -1257,7 +1245,7 @@ def test_position():
|
||||||
t1 = tqdm(desc='pos0 bar', position=0, **kwargs)
|
t1 = tqdm(desc='pos0 bar', position=0, **kwargs)
|
||||||
t2 = tqdm(desc='pos1 bar', position=1, **kwargs)
|
t2 = tqdm(desc='pos1 bar', position=1, **kwargs)
|
||||||
t3 = tqdm(desc='pos2 bar', position=2, **kwargs)
|
t3 = tqdm(desc='pos2 bar', position=2, **kwargs)
|
||||||
for _ in _range(2):
|
for _ in range(2):
|
||||||
t1.update()
|
t1.update()
|
||||||
t3.update()
|
t3.update()
|
||||||
t2.update()
|
t2.update()
|
||||||
|
@ -1360,7 +1348,7 @@ def test_deprecated_gui():
|
||||||
# t.close()
|
# t.close()
|
||||||
# len(tqdm._instances) += 1 # undo the close() decrement
|
# 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:
|
try:
|
||||||
for _ in t:
|
for _ in t:
|
||||||
pass
|
pass
|
||||||
|
@ -1735,7 +1723,7 @@ def test_external_write():
|
||||||
def test_unit_scale():
|
def test_unit_scale():
|
||||||
"""Test numeric `unit_scale`"""
|
"""Test numeric `unit_scale`"""
|
||||||
with closing(StringIO()) as our_file:
|
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):
|
miniters=1, mininterval=0):
|
||||||
pass
|
pass
|
||||||
out = our_file.getvalue()
|
out = our_file.getvalue()
|
||||||
|
@ -1937,7 +1925,7 @@ def test_screen_shape():
|
||||||
def test_initial():
|
def test_initial():
|
||||||
"""Test `initial`"""
|
"""Test `initial`"""
|
||||||
with closing(StringIO()) as our_file:
|
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):
|
miniters=1, mininterval=0):
|
||||||
pass
|
pass
|
||||||
out = our_file.getvalue()
|
out = our_file.getvalue()
|
||||||
|
@ -1948,7 +1936,7 @@ def test_initial():
|
||||||
def test_colour():
|
def test_colour():
|
||||||
"""Test `colour`"""
|
"""Test `colour`"""
|
||||||
with closing(StringIO()) as our_file:
|
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
|
pass
|
||||||
out = our_file.getvalue()
|
out = our_file.getvalue()
|
||||||
assert '\x1b[38;2;%d;%d;%dm' % (0xbe, 0xef, 0xed) in out
|
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)
|
assert "Unknown colour" in str(w[-1].message)
|
||||||
|
|
||||||
with closing(StringIO()) as our_file2:
|
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
|
pass
|
||||||
out = our_file2.getvalue()
|
out = our_file2.getvalue()
|
||||||
assert '\x1b[34m' in out
|
assert '\x1b[34m' in out
|
||||||
|
@ -1977,7 +1965,7 @@ def test_closed():
|
||||||
|
|
||||||
def test_reversed(capsys):
|
def test_reversed(capsys):
|
||||||
"""Test reversed()"""
|
"""Test reversed()"""
|
||||||
for _ in reversed(tqdm(_range(9))):
|
for _ in reversed(tqdm(range(9))):
|
||||||
pass
|
pass
|
||||||
out, err = capsys.readouterr()
|
out, err = capsys.readouterr()
|
||||||
assert not out
|
assert not out
|
||||||
|
@ -1989,7 +1977,7 @@ def test_contains(capsys):
|
||||||
"""Test __contains__ doesn't iterate"""
|
"""Test __contains__ doesn't iterate"""
|
||||||
with tqdm(list(range(9))) as t:
|
with tqdm(list(range(9))) as t:
|
||||||
assert 9 not in 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()
|
out, err = capsys.readouterr()
|
||||||
assert not out
|
assert not out
|
||||||
assert ' 0%' in err
|
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()
|
48
tox.ini
48
tox.ini
|
@ -4,20 +4,17 @@
|
||||||
# and then run "tox" from this directory.
|
# and then run "tox" from this directory.
|
||||||
|
|
||||||
[tox]
|
[tox]
|
||||||
# deprecation warning: py{27,py2,34,35,36}
|
envlist=py{37,38,39,310,311,312,py3}{,-tf}{,-keras}, perf, check
|
||||||
envlist=py{27,34,35,36,37,38,39,310,py2,py3}{,-tf}{,-keras}, perf, setup.py
|
|
||||||
isolated_build=True
|
isolated_build=True
|
||||||
|
|
||||||
[gh-actions]
|
[gh-actions]
|
||||||
python=
|
python=
|
||||||
2.7: py27
|
|
||||||
3.5: py35
|
|
||||||
3.6: py36
|
|
||||||
3.7: py37
|
3.7: py37
|
||||||
3.8: py38
|
3.8: py38
|
||||||
3.9: py39
|
3.9: py39
|
||||||
3.10: py310
|
3.10: py310
|
||||||
pypy-2.7: pypy2
|
3.11: py311
|
||||||
|
3.12: py312
|
||||||
pypy-3.7: pypy3
|
pypy-3.7: pypy3
|
||||||
[gh-actions:env]
|
[gh-actions:env]
|
||||||
PLATFORM=
|
PLATFORM=
|
||||||
|
@ -26,12 +23,11 @@ PLATFORM=
|
||||||
[core]
|
[core]
|
||||||
deps=
|
deps=
|
||||||
pytest
|
pytest
|
||||||
py3{4,5,6}: pytest<7
|
|
||||||
pytest-cov
|
pytest-cov
|
||||||
pytest-timeout
|
pytest-timeout
|
||||||
py3{7,8,9,10}: pytest-asyncio
|
pytest-asyncio
|
||||||
py3{6,7,8,9,10}: ipywidgets
|
ipywidgets
|
||||||
py3{7,8,9,10}: git+https://github.com/casperdcl/nbval.git@master#egg=nbval
|
git+https://github.com/casperdcl/nbval.git@master#egg=nbval
|
||||||
coverage
|
coverage
|
||||||
coveralls
|
coveralls
|
||||||
codecov
|
codecov
|
||||||
|
@ -41,7 +37,7 @@ commands=
|
||||||
- codacy report -l Python -r coverage.xml --partial
|
- codacy report -l Python -r coverage.xml --partial
|
||||||
|
|
||||||
[testenv]
|
[testenv]
|
||||||
passenv=TOXENV CI GITHUB_* CODECOV_* COVERALLS_* CODACY_* HOME
|
passenv=TOXENV,CI,GITHUB_*,CODECOV_*,COVERALLS_*,CODACY_*,HOME
|
||||||
deps=
|
deps=
|
||||||
{[core]deps}
|
{[core]deps}
|
||||||
cython
|
cython
|
||||||
|
@ -49,26 +45,17 @@ deps=
|
||||||
matplotlib
|
matplotlib
|
||||||
numpy
|
numpy
|
||||||
pandas
|
pandas
|
||||||
|
rich
|
||||||
tf: tensorflow!=2.5.0
|
tf: tensorflow!=2.5.0
|
||||||
!py27-keras: keras
|
keras: keras
|
||||||
py27-keras: keras<2.5
|
|
||||||
py35-keras: keras<2.7
|
|
||||||
py27-tf: protobuf<3.18
|
|
||||||
py3{6,7,8,9,10}: rich
|
|
||||||
commands=
|
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
|
pytest --cov=tqdm --cov-report= -W=ignore tests_notebook.ipynb --nbval --nbval-current-env --nbval-sanitize-with=.meta/nbval.ini
|
||||||
py3{7,8,9,10}: pytest --cov=tqdm --cov-report= tests_notebook.ipynb --nbval --nbval-current-env -W=ignore --nbval-sanitize-with=setup.cfg
|
pytest --cov=tqdm --cov-report=xml --cov-report=term --cov-append -k "not perf"
|
||||||
py3{7,8,9,10}: pytest --cov=tqdm --cov-report=xml --cov-report=term --cov-append -k "not perf"
|
|
||||||
{[core]commands}
|
{[core]commands}
|
||||||
allowlist_externals=codacy
|
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
|
# no cython/numpy/pandas
|
||||||
[testenv:py{34,py2,py3}]
|
[testenv:pypy3]
|
||||||
deps={[core]deps}
|
deps={[core]deps}
|
||||||
|
|
||||||
[testenv:perf]
|
[testenv:perf]
|
||||||
|
@ -78,11 +65,12 @@ deps=
|
||||||
pytest-asyncio
|
pytest-asyncio
|
||||||
commands=pytest -k perf
|
commands=pytest -k perf
|
||||||
|
|
||||||
[testenv:setup.py]
|
[testenv:check]
|
||||||
deps=
|
deps=
|
||||||
docutils
|
build
|
||||||
pygments
|
twine
|
||||||
py-make>=0.1.0
|
py-make>=0.1.0
|
||||||
commands=
|
commands=
|
||||||
{envpython} setup.py check --restructuredtext --metadata --strict
|
{envpython} -m build
|
||||||
{envpython} setup.py make none
|
{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
|
def tnrange(*args, **kwargs): # pragma: no cover
|
||||||
"""
|
"""Shortcut for `tqdm.notebook.tqdm(range(*args), **kwargs)`."""
|
||||||
A shortcut for `tqdm.notebook.tqdm(xrange(*args), **kwargs)`.
|
|
||||||
On Python3+, `range` is used instead of `xrange`.
|
|
||||||
"""
|
|
||||||
from warnings import warn
|
from warnings import warn
|
||||||
|
|
||||||
from .notebook import trange as _tnrange
|
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 .std import TqdmDeprecationWarning
|
||||||
from .utils import ( # NOQA, pylint: disable=unused-import
|
from .utils import ( # NOQA, pylint: disable=unused-import
|
||||||
CUR_OS, IS_NIX, IS_WIN, RE_ANSI, Comparable, FormatReplace, SimpleTextIOWrapper, _basestring,
|
CUR_OS, IS_NIX, IS_WIN, RE_ANSI, Comparable, FormatReplace, SimpleTextIOWrapper,
|
||||||
_environ_cols_wrapper, _is_ascii, _is_utf, _range, _screen_shape_linux, _screen_shape_tput,
|
_environ_cols_wrapper, _is_ascii, _is_utf, _screen_shape_linux, _screen_shape_tput,
|
||||||
_screen_shape_windows, _screen_shape_wrapper, _supports_unicode, _term_move_up, _unich,
|
_screen_shape_windows, _screen_shape_wrapper, _supports_unicode, _term_move_up, colorama)
|
||||||
_unicode, colorama)
|
|
||||||
|
|
||||||
warn("This function will be removed in tqdm==5.0.0\n"
|
warn("This function will be removed in tqdm==5.0.0\n"
|
||||||
"Please use `tqdm.utils.*` instead of `tqdm._utils.*`",
|
"Please use `tqdm.utils.*` instead of `tqdm._utils.*`",
|
||||||
|
|
|
@ -18,10 +18,10 @@ __all__ = ['tqdm_asyncio', 'tarange', 'tqdm', 'trange']
|
||||||
|
|
||||||
class tqdm_asyncio(std_tqdm):
|
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):
|
def __init__(self, iterable=None, *args, **kwargs):
|
||||||
super(tqdm_asyncio, self).__init__(iterable, *args, **kwargs)
|
super().__init__(iterable, *args, **kwargs)
|
||||||
self.iterable_awaitable = False
|
self.iterable_awaitable = False
|
||||||
if iterable is not None:
|
if iterable is not None:
|
||||||
if hasattr(iterable, "__anext__"):
|
if hasattr(iterable, "__anext__"):
|
||||||
|
|
10
tqdm/auto.py
10
tqdm/auto.py
|
@ -4,7 +4,7 @@ Enables multiple commonly used features.
|
||||||
Method resolution order:
|
Method resolution order:
|
||||||
|
|
||||||
- `tqdm.autonotebook` without import warnings
|
- `tqdm.autonotebook` without import warnings
|
||||||
- `tqdm.asyncio` on Python3.6+
|
- `tqdm.asyncio`
|
||||||
- `tqdm.std` base class
|
- `tqdm.std` base class
|
||||||
|
|
||||||
Usage:
|
Usage:
|
||||||
|
@ -12,7 +12,6 @@ Usage:
|
||||||
>>> for i in trange(10):
|
>>> for i in trange(10):
|
||||||
... ...
|
... ...
|
||||||
"""
|
"""
|
||||||
import sys
|
|
||||||
import warnings
|
import warnings
|
||||||
|
|
||||||
from .std import TqdmExperimentalWarning
|
from .std import TqdmExperimentalWarning
|
||||||
|
@ -20,12 +19,7 @@ from .std import TqdmExperimentalWarning
|
||||||
with warnings.catch_warnings():
|
with warnings.catch_warnings():
|
||||||
warnings.simplefilter("ignore", category=TqdmExperimentalWarning)
|
warnings.simplefilter("ignore", category=TqdmExperimentalWarning)
|
||||||
from .autonotebook import tqdm as notebook_tqdm
|
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 .asyncio import tqdm as asyncio_tqdm
|
||||||
from .std import tqdm as std_tqdm
|
from .std import tqdm as std_tqdm
|
||||||
|
|
||||||
|
@ -35,10 +29,12 @@ else: # Python3.6+
|
||||||
else:
|
else:
|
||||||
tqdm = asyncio_tqdm
|
tqdm = asyncio_tqdm
|
||||||
|
|
||||||
|
|
||||||
def trange(*args, **kwargs):
|
def trange(*args, **kwargs):
|
||||||
"""
|
"""
|
||||||
A shortcut for `tqdm.auto.tqdm(range(*args), **kwargs)`.
|
A shortcut for `tqdm.auto.tqdm(range(*args), **kwargs)`.
|
||||||
"""
|
"""
|
||||||
return tqdm(range(*args), **kwargs)
|
return tqdm(range(*args), **kwargs)
|
||||||
|
|
||||||
|
|
||||||
__all__ = ["tqdm", "trange"]
|
__all__ = ["tqdm", "trange"]
|
||||||
|
|
55
tqdm/cli.py
55
tqdm/cli.py
|
@ -5,6 +5,7 @@ import logging
|
||||||
import re
|
import re
|
||||||
import sys
|
import sys
|
||||||
from ast import literal_eval as numeric
|
from ast import literal_eval as numeric
|
||||||
|
from textwrap import indent
|
||||||
|
|
||||||
from .std import TqdmKeyError, TqdmTypeError, tqdm
|
from .std import TqdmKeyError, TqdmTypeError, tqdm
|
||||||
from .version import __version__
|
from .version import __version__
|
||||||
|
@ -21,23 +22,34 @@ def cast(val, typ):
|
||||||
return cast(val, t)
|
return cast(val, t)
|
||||||
except TqdmTypeError:
|
except TqdmTypeError:
|
||||||
pass
|
pass
|
||||||
raise TqdmTypeError(val + ' : ' + typ)
|
raise TqdmTypeError(f"{val} : {typ}")
|
||||||
|
|
||||||
# sys.stderr.write('\ndebug | `val:type`: `' + val + ':' + typ + '`.\n')
|
# sys.stderr.write('\ndebug | `val:type`: `' + val + ':' + typ + '`.\n')
|
||||||
if typ == 'bool':
|
if typ == 'bool':
|
||||||
if (val == 'True') or (val == ''):
|
if (val == 'True') or (val == ''):
|
||||||
return True
|
return True
|
||||||
elif val == 'False':
|
if val == 'False':
|
||||||
return False
|
return False
|
||||||
else:
|
|
||||||
raise TqdmTypeError(val + ' : ' + typ)
|
raise TqdmTypeError(val + ' : ' + typ)
|
||||||
try:
|
|
||||||
return eval(typ + '("' + val + '")')
|
|
||||||
except Exception:
|
|
||||||
if typ == 'chr':
|
if typ == 'chr':
|
||||||
return chr(ord(eval('"' + val + '"'))).encode()
|
if len(val) == 1:
|
||||||
else:
|
return val.encode()
|
||||||
raise TqdmTypeError(val + ' : ' + typ)
|
if re.match(r"^\\\w+$", val):
|
||||||
|
return eval(f'"{val}"').encode()
|
||||||
|
raise TqdmTypeError(f"{val} : {typ}")
|
||||||
|
if typ == 'str':
|
||||||
|
return val
|
||||||
|
if typ == 'int':
|
||||||
|
try:
|
||||||
|
return int(val)
|
||||||
|
except ValueError as exc:
|
||||||
|
raise TqdmTypeError(f"{val} : {typ}") from exc
|
||||||
|
if typ == 'float':
|
||||||
|
try:
|
||||||
|
return float(val)
|
||||||
|
except ValueError as exc:
|
||||||
|
raise TqdmTypeError(f"{val} : {typ}") from exc
|
||||||
|
raise TqdmTypeError(f"{val} : {typ}")
|
||||||
|
|
||||||
|
|
||||||
def posix_pipe(fin, fout, delim=b'\\n', buf_size=256,
|
def posix_pipe(fin, fout, delim=b'\\n', buf_size=256,
|
||||||
|
@ -98,7 +110,7 @@ def posix_pipe(fin, fout, delim=b'\\n', buf_size=256,
|
||||||
|
|
||||||
|
|
||||||
# ((opt, type), ... )
|
# ((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
|
# better split method assuming no positional args
|
||||||
RE_SHLEX = re.compile(r'\s*(?<!\S)--?([^\s=]+)(\s+|=|$)')
|
RE_SHLEX = re.compile(r'\s*(?<!\S)--?([^\s=]+)(\s+|=|$)')
|
||||||
|
|
||||||
|
@ -166,7 +178,9 @@ def main(fp=sys.stderr, argv=None):
|
||||||
logging.basicConfig(level=getattr(logging, logLevel),
|
logging.basicConfig(level=getattr(logging, logLevel),
|
||||||
format="%(levelname)s:%(module)s:%(lineno)d:%(message)s")
|
format="%(levelname)s:%(module)s:%(lineno)d:%(message)s")
|
||||||
|
|
||||||
d = tqdm.__init__.__doc__ + CLI_EXTRA_DOC
|
# py<3.13 doesn't dedent docstrings
|
||||||
|
d = (tqdm.__doc__ if sys.version_info < (3, 13)
|
||||||
|
else indent(tqdm.__doc__, " ")) + CLI_EXTRA_DOC
|
||||||
|
|
||||||
opt_types = dict(RE_OPTS.findall(d))
|
opt_types = dict(RE_OPTS.findall(d))
|
||||||
# opt_types['delim'] = 'chr'
|
# opt_types['delim'] = 'chr'
|
||||||
|
@ -199,8 +213,7 @@ Options:
|
||||||
sys.stdout.write(d + '\n')
|
sys.stdout.write(d + '\n')
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
elif argv and argv[0][:2] != '--':
|
elif argv and argv[0][:2] != '--':
|
||||||
sys.stderr.write(
|
sys.stderr.write(f"Error:Unknown argument:{argv[0]}\n{help_short}")
|
||||||
"Error:Unknown argument:{0}\n{1}".format(argv[0], help_short))
|
|
||||||
|
|
||||||
argv = RE_SHLEX.split(' '.join(["tqdm"] + argv))
|
argv = RE_SHLEX.split(' '.join(["tqdm"] + argv))
|
||||||
opts = dict(zip(argv[1::3], argv[3::3]))
|
opts = dict(zip(argv[1::3], argv[3::3]))
|
||||||
|
@ -245,25 +258,21 @@ Options:
|
||||||
stdout = getattr(stdout, 'buffer', stdout)
|
stdout = getattr(stdout, 'buffer', stdout)
|
||||||
stdin = getattr(sys.stdin, 'buffer', sys.stdin)
|
stdin = getattr(sys.stdin, 'buffer', sys.stdin)
|
||||||
if manpath or comppath:
|
if manpath or comppath:
|
||||||
from os import path
|
try: # py<3.9
|
||||||
from shutil import copyfile
|
|
||||||
try: # py<3.7
|
|
||||||
import importlib_resources as resources
|
import importlib_resources as resources
|
||||||
except ImportError:
|
except ImportError:
|
||||||
from importlib import resources
|
from importlib import resources
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
def cp(name, dst):
|
def cp(name, dst):
|
||||||
"""copy resource `name` to `dst`"""
|
"""copy resource `name` to `dst`"""
|
||||||
if hasattr(resources, 'files'):
|
fi = resources.files('tqdm') / name
|
||||||
copyfile(str(resources.files('tqdm') / name), dst)
|
dst.write_bytes(fi.read_bytes())
|
||||||
else: # py<3.9
|
|
||||||
with resources.path('tqdm', name) as src:
|
|
||||||
copyfile(str(src), dst)
|
|
||||||
log.info("written:%s", dst)
|
log.info("written:%s", dst)
|
||||||
if manpath is not None:
|
if manpath is not None:
|
||||||
cp('tqdm.1', path.join(manpath, 'tqdm.1'))
|
cp('tqdm.1', Path(manpath) / 'tqdm.1')
|
||||||
if comppath is not None:
|
if comppath is not None:
|
||||||
cp('completion.sh', path.join(comppath, 'tqdm_completion.sh'))
|
cp('completion.sh', Path(comppath) / 'tqdm_completion.sh')
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
if tee:
|
if tee:
|
||||||
stdout_write = stdout.write
|
stdout_write = stdout.write
|
||||||
|
|
|
@ -3,11 +3,10 @@ Thin wrappers around common functions.
|
||||||
|
|
||||||
Subpackages contain potentially unstable extensions.
|
Subpackages contain potentially unstable extensions.
|
||||||
"""
|
"""
|
||||||
import sys
|
from warnings import warn
|
||||||
from functools import wraps
|
|
||||||
|
|
||||||
from ..auto import tqdm as tqdm_auto
|
from ..auto import tqdm as tqdm_auto
|
||||||
from ..std import tqdm
|
from ..std import TqdmDeprecationWarning, tqdm
|
||||||
from ..utils import ObjectWrapper
|
from ..utils import ObjectWrapper
|
||||||
|
|
||||||
__author__ = {"github.com/": ["casperdcl"]}
|
__author__ = {"github.com/": ["casperdcl"]}
|
||||||
|
@ -18,7 +17,7 @@ class DummyTqdmFile(ObjectWrapper):
|
||||||
"""Dummy file-like that will write to tqdm"""
|
"""Dummy file-like that will write to tqdm"""
|
||||||
|
|
||||||
def __init__(self, wrapped):
|
def __init__(self, wrapped):
|
||||||
super(DummyTqdmFile, self).__init__(wrapped)
|
super().__init__(wrapped)
|
||||||
self._buf = []
|
self._buf = []
|
||||||
|
|
||||||
def write(self, x, nolock=False):
|
def write(self, x, nolock=False):
|
||||||
|
@ -42,12 +41,9 @@ class DummyTqdmFile(ObjectWrapper):
|
||||||
|
|
||||||
|
|
||||||
def builtin_iterable(func):
|
def builtin_iterable(func):
|
||||||
"""Wraps `func()` output in a `list()` in py2"""
|
"""Returns `func`"""
|
||||||
if sys.version_info[:1] < (3,):
|
warn("This function has no effect, and will be removed in tqdm==5.0.0",
|
||||||
@wraps(func)
|
TqdmDeprecationWarning, stacklevel=2)
|
||||||
def inner(*args, **kwargs):
|
|
||||||
return list(func(*args, **kwargs))
|
|
||||||
return inner
|
|
||||||
return func
|
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)
|
return enumerate(tqdm_class(iterable, total=total, **tqdm_kwargs), start)
|
||||||
|
|
||||||
|
|
||||||
@builtin_iterable
|
|
||||||
def tzip(iter1, *iter2plus, **tqdm_kwargs):
|
def tzip(iter1, *iter2plus, **tqdm_kwargs):
|
||||||
"""
|
"""
|
||||||
Equivalent of builtin `zip`.
|
Equivalent of builtin `zip`.
|
||||||
|
@ -85,7 +80,6 @@ def tzip(iter1, *iter2plus, **tqdm_kwargs):
|
||||||
yield i
|
yield i
|
||||||
|
|
||||||
|
|
||||||
@builtin_iterable
|
|
||||||
def tmap(function, *sequences, **tqdm_kwargs):
|
def tmap(function, *sequences, **tqdm_kwargs):
|
||||||
"""
|
"""
|
||||||
Equivalent of builtin `map`.
|
Equivalent of builtin `map`.
|
||||||
|
|
|
@ -1,32 +1,13 @@
|
||||||
"""
|
"""
|
||||||
Thin wrappers around `concurrent.futures`.
|
Thin wrappers around `concurrent.futures`.
|
||||||
"""
|
"""
|
||||||
from __future__ import absolute_import
|
|
||||||
|
|
||||||
from contextlib import contextmanager
|
from contextlib import contextmanager
|
||||||
|
from operator import length_hint
|
||||||
|
from os import cpu_count
|
||||||
|
|
||||||
from ..auto import tqdm as tqdm_auto
|
from ..auto import tqdm as tqdm_auto
|
||||||
from ..std import TqdmWarning
|
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"]}
|
__author__ = {"github.com/": ["casperdcl"]}
|
||||||
__all__ = ['thread_map', 'process_map']
|
__all__ = ['thread_map', 'process_map']
|
||||||
|
|
||||||
|
@ -64,16 +45,10 @@ def _executor_map(PoolExecutor, fn, *iterables, **tqdm_kwargs):
|
||||||
chunksize = kwargs.pop("chunksize", 1)
|
chunksize = kwargs.pop("chunksize", 1)
|
||||||
lock_name = kwargs.pop("lock_name", "")
|
lock_name = kwargs.pop("lock_name", "")
|
||||||
with ensure_lock(tqdm_class, lock_name=lock_name) as lk:
|
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`
|
# share lock in case workers are already using `tqdm`
|
||||||
pool_kwargs.update(initializer=tqdm_class.set_lock, initargs=(lk,))
|
with PoolExecutor(max_workers=max_workers, initializer=tqdm_class.set_lock,
|
||||||
map_args = {}
|
initargs=(lk,)) as ex:
|
||||||
if not (3, 0) < sys_version < (3, 5):
|
return list(tqdm_class(ex.map(fn, *iterables, chunksize=chunksize), **kwargs))
|
||||||
map_args.update(chunksize=chunksize)
|
|
||||||
with PoolExecutor(**pool_kwargs) as ex:
|
|
||||||
return list(tqdm_class(ex.map(fn, *iterables, **map_args), **kwargs))
|
|
||||||
|
|
||||||
|
|
||||||
def thread_map(fn, *iterables, **tqdm_kwargs):
|
def thread_map(fn, *iterables, **tqdm_kwargs):
|
||||||
|
|
|
@ -6,54 +6,85 @@ Usage:
|
||||||
>>> for i in trange(10, token='{token}', channel_id='{channel_id}'):
|
>>> 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
|
from os import getenv
|
||||||
|
from warnings import warn
|
||||||
|
|
||||||
try:
|
from requests import Session
|
||||||
from disco.client import Client, ClientConfig
|
from requests.utils import default_user_agent
|
||||||
except ImportError:
|
|
||||||
raise ImportError("Please `pip install disco-py`")
|
|
||||||
|
|
||||||
from ..auto import tqdm as tqdm_auto
|
from ..auto import tqdm as tqdm_auto
|
||||||
from ..utils import _range
|
from ..std import TqdmWarning
|
||||||
|
from ..version import __version__
|
||||||
from .utils_worker import MonoWorker
|
from .utils_worker import MonoWorker
|
||||||
|
|
||||||
__author__ = {"github.com/": ["casperdcl"]}
|
__author__ = {"github.com/": ["casperdcl", "guigoruiz1"]}
|
||||||
__all__ = ['DiscordIO', 'tqdm_discord', 'tdrange', 'tqdm', 'trange']
|
__all__ = ['DiscordIO', 'tqdm_discord', 'tdrange', 'tqdm', 'trange']
|
||||||
|
|
||||||
|
|
||||||
class DiscordIO(MonoWorker):
|
class DiscordIO(MonoWorker):
|
||||||
"""Non-blocking file-like IO using a Discord Bot."""
|
"""Non-blocking file-like IO using a Discord Bot."""
|
||||||
|
API = "https://discord.com/api/v10"
|
||||||
|
UA = f"tqdm (https://tqdm.github.io, {__version__}) {default_user_agent()}"
|
||||||
|
|
||||||
def __init__(self, token, channel_id):
|
def __init__(self, token, channel_id):
|
||||||
"""Creates a new message in the given `channel_id`."""
|
"""Creates a new message in the given `channel_id`."""
|
||||||
super(DiscordIO, self).__init__()
|
super().__init__()
|
||||||
config = ClientConfig()
|
self.token = token
|
||||||
config.token = token
|
self.channel_id = channel_id
|
||||||
client = Client(config)
|
self.session = Session()
|
||||||
self.text = self.__class__.__name__
|
self.text = self.__class__.__name__
|
||||||
|
self.message_id
|
||||||
|
|
||||||
|
@property
|
||||||
|
def message_id(self):
|
||||||
|
if hasattr(self, '_message_id'):
|
||||||
|
return self._message_id
|
||||||
try:
|
try:
|
||||||
self.message = client.api.channels_messages_create(channel_id, self.text)
|
res = self.session.post(
|
||||||
|
f'{self.API}/channels/{self.channel_id}/messages',
|
||||||
|
headers={'Authorization': f'Bot {self.token}', 'User-Agent': self.UA},
|
||||||
|
json={'content': f"`{self.text}`"}).json()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
tqdm_auto.write(str(e))
|
tqdm_auto.write(str(e))
|
||||||
self.message = None
|
else:
|
||||||
|
if res.get('error_code') == 429:
|
||||||
|
warn("Creation rate limit: try increasing `mininterval`.",
|
||||||
|
TqdmWarning, stacklevel=2)
|
||||||
|
else:
|
||||||
|
self._message_id = res['id']
|
||||||
|
return self._message_id
|
||||||
|
|
||||||
def write(self, s):
|
def write(self, s):
|
||||||
"""Replaces internal `message`'s text with `s`."""
|
"""Replaces internal `message_id`'s text with `s`."""
|
||||||
if not s:
|
if not s:
|
||||||
s = "..."
|
s = "..."
|
||||||
s = s.replace('\r', '').strip()
|
s = s.replace('\r', '').strip()
|
||||||
if s == self.text:
|
if s == self.text:
|
||||||
return # skip duplicate message
|
return # avoid duplicate message Bot error
|
||||||
message = self.message
|
message_id = self.message_id
|
||||||
if message is None:
|
if message_id is None:
|
||||||
return
|
return
|
||||||
self.text = s
|
self.text = s
|
||||||
try:
|
try:
|
||||||
future = self.submit(message.edit, '`' + s + '`')
|
future = self.submit(
|
||||||
|
self.session.patch,
|
||||||
|
f'{self.API}/channels/{self.channel_id}/messages/{message_id}',
|
||||||
|
headers={'Authorization': f'Bot {self.token}', 'User-Agent': self.UA},
|
||||||
|
json={'content': f"`{self.text}`"})
|
||||||
|
except Exception as e:
|
||||||
|
tqdm_auto.write(str(e))
|
||||||
|
else:
|
||||||
|
return future
|
||||||
|
|
||||||
|
def delete(self):
|
||||||
|
"""Deletes internal `message_id`."""
|
||||||
|
try:
|
||||||
|
future = self.submit(
|
||||||
|
self.session.delete,
|
||||||
|
f'{self.API}/channels/{self.channel_id}/messages/{self.message_id}',
|
||||||
|
headers={'Authorization': f'Bot {self.token}', 'User-Agent': self.UA})
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
tqdm_auto.write(str(e))
|
tqdm_auto.write(str(e))
|
||||||
else:
|
else:
|
||||||
|
@ -78,26 +109,22 @@ class tqdm_discord(tqdm_auto):
|
||||||
"""
|
"""
|
||||||
Parameters
|
Parameters
|
||||||
----------
|
----------
|
||||||
token : str, required. Discord token
|
token : str, required. Discord bot token
|
||||||
[default: ${TQDM_DISCORD_TOKEN}].
|
[default: ${TQDM_DISCORD_TOKEN}].
|
||||||
channel_id : int, required. Discord channel ID
|
channel_id : int, required. Discord channel ID
|
||||||
[default: ${TQDM_DISCORD_CHANNEL_ID}].
|
[default: ${TQDM_DISCORD_CHANNEL_ID}].
|
||||||
mininterval : float, optional.
|
|
||||||
Minimum of [default: 1.5] to avoid rate limit.
|
|
||||||
|
|
||||||
See `tqdm.auto.tqdm.__init__` for other parameters.
|
See `tqdm.auto.tqdm.__init__` for other parameters.
|
||||||
"""
|
"""
|
||||||
if not kwargs.get('disable'):
|
if not kwargs.get('disable'):
|
||||||
kwargs = kwargs.copy()
|
kwargs = kwargs.copy()
|
||||||
logging.getLogger("HTTPClient").setLevel(logging.WARNING)
|
|
||||||
self.dio = DiscordIO(
|
self.dio = DiscordIO(
|
||||||
kwargs.pop('token', getenv("TQDM_DISCORD_TOKEN")),
|
kwargs.pop('token', getenv('TQDM_DISCORD_TOKEN')),
|
||||||
kwargs.pop('channel_id', getenv("TQDM_DISCORD_CHANNEL_ID")))
|
kwargs.pop('channel_id', getenv('TQDM_DISCORD_CHANNEL_ID')))
|
||||||
kwargs['mininterval'] = max(1.5, kwargs.get('mininterval', 1.5))
|
super().__init__(*args, **kwargs)
|
||||||
super(tqdm_discord, self).__init__(*args, **kwargs)
|
|
||||||
|
|
||||||
def display(self, **kwargs):
|
def display(self, **kwargs):
|
||||||
super(tqdm_discord, self).display(**kwargs)
|
super().display(**kwargs)
|
||||||
fmt = self.format_dict
|
fmt = self.format_dict
|
||||||
if fmt.get('bar_format', None):
|
if fmt.get('bar_format', None):
|
||||||
fmt['bar_format'] = fmt['bar_format'].replace(
|
fmt['bar_format'] = fmt['bar_format'].replace(
|
||||||
|
@ -107,17 +134,21 @@ class tqdm_discord(tqdm_auto):
|
||||||
self.dio.write(self.format_meter(**fmt))
|
self.dio.write(self.format_meter(**fmt))
|
||||||
|
|
||||||
def clear(self, *args, **kwargs):
|
def clear(self, *args, **kwargs):
|
||||||
super(tqdm_discord, self).clear(*args, **kwargs)
|
super().clear(*args, **kwargs)
|
||||||
if not self.disable:
|
if not self.disable:
|
||||||
self.dio.write("")
|
self.dio.write("")
|
||||||
|
|
||||||
|
def close(self):
|
||||||
|
if self.disable:
|
||||||
|
return
|
||||||
|
super().close()
|
||||||
|
if not (self.leave or (self.leave is None and self.pos == 0)):
|
||||||
|
self.dio.delete()
|
||||||
|
|
||||||
|
|
||||||
def tdrange(*args, **kwargs):
|
def tdrange(*args, **kwargs):
|
||||||
"""
|
"""Shortcut for `tqdm.contrib.discord.tqdm(range(*args), **kwargs)`."""
|
||||||
A shortcut for `tqdm.contrib.discord.tqdm(xrange(*args), **kwargs)`.
|
return tqdm_discord(range(*args), **kwargs)
|
||||||
On Python3+, `range` is used instead of `xrange`.
|
|
||||||
"""
|
|
||||||
return tqdm_discord(_range(*args), **kwargs)
|
|
||||||
|
|
||||||
|
|
||||||
# Aliases
|
# Aliases
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
"""
|
"""
|
||||||
Thin wrappers around `itertools`.
|
Thin wrappers around `itertools`.
|
||||||
"""
|
"""
|
||||||
from __future__ import absolute_import
|
|
||||||
|
|
||||||
import itertools
|
import itertools
|
||||||
|
|
||||||
from ..auto import tqdm as tqdm_auto
|
from ..auto import tqdm as tqdm_auto
|
||||||
|
|
|
@ -1,14 +1,12 @@
|
||||||
"""
|
"""
|
||||||
Helper functionality for interoperability with stdlib `logging`.
|
Helper functionality for interoperability with stdlib `logging`.
|
||||||
"""
|
"""
|
||||||
from __future__ import absolute_import
|
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
import sys
|
import sys
|
||||||
from contextlib import contextmanager
|
from contextlib import contextmanager
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from typing import Iterator, List, Optional, Type # pylint: disable=unused-import
|
from typing import Iterator, List, Optional, Type # noqa: F401
|
||||||
except ImportError:
|
except ImportError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -20,7 +18,7 @@ class _TqdmLoggingHandler(logging.StreamHandler):
|
||||||
self,
|
self,
|
||||||
tqdm_class=std_tqdm # type: Type[std_tqdm]
|
tqdm_class=std_tqdm # type: Type[std_tqdm]
|
||||||
):
|
):
|
||||||
super(_TqdmLoggingHandler, self).__init__()
|
super().__init__()
|
||||||
self.tqdm_class = tqdm_class
|
self.tqdm_class = tqdm_class
|
||||||
|
|
||||||
def emit(self, record):
|
def emit(self, record):
|
||||||
|
|
|
@ -6,10 +6,8 @@ Usage:
|
||||||
>>> for i in trange(10, token='{token}', channel='{channel}'):
|
>>> 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
|
import logging
|
||||||
from os import getenv
|
from os import getenv
|
||||||
|
|
||||||
|
@ -19,7 +17,6 @@ except ImportError:
|
||||||
raise ImportError("Please `pip install slack-sdk`")
|
raise ImportError("Please `pip install slack-sdk`")
|
||||||
|
|
||||||
from ..auto import tqdm as tqdm_auto
|
from ..auto import tqdm as tqdm_auto
|
||||||
from ..utils import _range
|
|
||||||
from .utils_worker import MonoWorker
|
from .utils_worker import MonoWorker
|
||||||
|
|
||||||
__author__ = {"github.com/": ["0x2b3bfa0", "casperdcl"]}
|
__author__ = {"github.com/": ["0x2b3bfa0", "casperdcl"]}
|
||||||
|
@ -30,7 +27,7 @@ class SlackIO(MonoWorker):
|
||||||
"""Non-blocking file-like IO using a Slack app."""
|
"""Non-blocking file-like IO using a Slack app."""
|
||||||
def __init__(self, token, channel):
|
def __init__(self, token, channel):
|
||||||
"""Creates a new message in the given `channel`."""
|
"""Creates a new message in the given `channel`."""
|
||||||
super(SlackIO, self).__init__()
|
super().__init__()
|
||||||
self.client = WebClient(token=token)
|
self.client = WebClient(token=token)
|
||||||
self.text = self.__class__.__name__
|
self.text = self.__class__.__name__
|
||||||
try:
|
try:
|
||||||
|
@ -91,10 +88,10 @@ class tqdm_slack(tqdm_auto):
|
||||||
kwargs.pop('token', getenv("TQDM_SLACK_TOKEN")),
|
kwargs.pop('token', getenv("TQDM_SLACK_TOKEN")),
|
||||||
kwargs.pop('channel', getenv("TQDM_SLACK_CHANNEL")))
|
kwargs.pop('channel', getenv("TQDM_SLACK_CHANNEL")))
|
||||||
kwargs['mininterval'] = max(1.5, kwargs.get('mininterval', 1.5))
|
kwargs['mininterval'] = max(1.5, kwargs.get('mininterval', 1.5))
|
||||||
super(tqdm_slack, self).__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
|
|
||||||
def display(self, **kwargs):
|
def display(self, **kwargs):
|
||||||
super(tqdm_slack, self).display(**kwargs)
|
super().display(**kwargs)
|
||||||
fmt = self.format_dict
|
fmt = self.format_dict
|
||||||
if fmt.get('bar_format', None):
|
if fmt.get('bar_format', None):
|
||||||
fmt['bar_format'] = fmt['bar_format'].replace(
|
fmt['bar_format'] = fmt['bar_format'].replace(
|
||||||
|
@ -108,17 +105,14 @@ class tqdm_slack(tqdm_auto):
|
||||||
self.sio.write(self.format_meter(**fmt))
|
self.sio.write(self.format_meter(**fmt))
|
||||||
|
|
||||||
def clear(self, *args, **kwargs):
|
def clear(self, *args, **kwargs):
|
||||||
super(tqdm_slack, self).clear(*args, **kwargs)
|
super().clear(*args, **kwargs)
|
||||||
if not self.disable:
|
if not self.disable:
|
||||||
self.sio.write("")
|
self.sio.write("")
|
||||||
|
|
||||||
|
|
||||||
def tsrange(*args, **kwargs):
|
def tsrange(*args, **kwargs):
|
||||||
"""
|
"""Shortcut for `tqdm.contrib.slack.tqdm(range(*args), **kwargs)`."""
|
||||||
A shortcut for `tqdm.contrib.slack.tqdm(xrange(*args), **kwargs)`.
|
return tqdm_slack(range(*args), **kwargs)
|
||||||
On Python3+, `range` is used instead of `xrange`.
|
|
||||||
"""
|
|
||||||
return tqdm_slack(_range(*args), **kwargs)
|
|
||||||
|
|
||||||
|
|
||||||
# Aliases
|
# Aliases
|
||||||
|
|
|
@ -6,10 +6,8 @@ Usage:
|
||||||
>>> for i in trange(10, token='{token}', chat_id='{chat_id}'):
|
>>> 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 os import getenv
|
||||||
from warnings import warn
|
from warnings import warn
|
||||||
|
|
||||||
|
@ -17,7 +15,6 @@ from requests import Session
|
||||||
|
|
||||||
from ..auto import tqdm as tqdm_auto
|
from ..auto import tqdm as tqdm_auto
|
||||||
from ..std import TqdmWarning
|
from ..std import TqdmWarning
|
||||||
from ..utils import _range
|
|
||||||
from .utils_worker import MonoWorker
|
from .utils_worker import MonoWorker
|
||||||
|
|
||||||
__author__ = {"github.com/": ["casperdcl"]}
|
__author__ = {"github.com/": ["casperdcl"]}
|
||||||
|
@ -30,7 +27,7 @@ class TelegramIO(MonoWorker):
|
||||||
|
|
||||||
def __init__(self, token, chat_id):
|
def __init__(self, token, chat_id):
|
||||||
"""Creates a new message in the given `chat_id`."""
|
"""Creates a new message in the given `chat_id`."""
|
||||||
super(TelegramIO, self).__init__()
|
super().__init__()
|
||||||
self.token = token
|
self.token = token
|
||||||
self.chat_id = chat_id
|
self.chat_id = chat_id
|
||||||
self.session = Session()
|
self.session = Session()
|
||||||
|
@ -121,10 +118,10 @@ class tqdm_telegram(tqdm_auto):
|
||||||
self.tgio = TelegramIO(
|
self.tgio = TelegramIO(
|
||||||
kwargs.pop('token', getenv('TQDM_TELEGRAM_TOKEN')),
|
kwargs.pop('token', getenv('TQDM_TELEGRAM_TOKEN')),
|
||||||
kwargs.pop('chat_id', getenv('TQDM_TELEGRAM_CHAT_ID')))
|
kwargs.pop('chat_id', getenv('TQDM_TELEGRAM_CHAT_ID')))
|
||||||
super(tqdm_telegram, self).__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
|
|
||||||
def display(self, **kwargs):
|
def display(self, **kwargs):
|
||||||
super(tqdm_telegram, self).display(**kwargs)
|
super().display(**kwargs)
|
||||||
fmt = self.format_dict
|
fmt = self.format_dict
|
||||||
if fmt.get('bar_format', None):
|
if fmt.get('bar_format', None):
|
||||||
fmt['bar_format'] = fmt['bar_format'].replace(
|
fmt['bar_format'] = fmt['bar_format'].replace(
|
||||||
|
@ -134,24 +131,21 @@ class tqdm_telegram(tqdm_auto):
|
||||||
self.tgio.write(self.format_meter(**fmt))
|
self.tgio.write(self.format_meter(**fmt))
|
||||||
|
|
||||||
def clear(self, *args, **kwargs):
|
def clear(self, *args, **kwargs):
|
||||||
super(tqdm_telegram, self).clear(*args, **kwargs)
|
super().clear(*args, **kwargs)
|
||||||
if not self.disable:
|
if not self.disable:
|
||||||
self.tgio.write("")
|
self.tgio.write("")
|
||||||
|
|
||||||
def close(self):
|
def close(self):
|
||||||
if self.disable:
|
if self.disable:
|
||||||
return
|
return
|
||||||
super(tqdm_telegram, self).close()
|
super().close()
|
||||||
if not (self.leave or (self.leave is None and self.pos == 0)):
|
if not (self.leave or (self.leave is None and self.pos == 0)):
|
||||||
self.tgio.delete()
|
self.tgio.delete()
|
||||||
|
|
||||||
|
|
||||||
def ttgrange(*args, **kwargs):
|
def ttgrange(*args, **kwargs):
|
||||||
"""
|
"""Shortcut for `tqdm.contrib.telegram.tqdm(range(*args), **kwargs)`."""
|
||||||
A shortcut for `tqdm.contrib.telegram.tqdm(xrange(*args), **kwargs)`.
|
return tqdm_telegram(range(*args), **kwargs)
|
||||||
On Python3+, `range` is used instead of `xrange`.
|
|
||||||
"""
|
|
||||||
return tqdm_telegram(_range(*args), **kwargs)
|
|
||||||
|
|
||||||
|
|
||||||
# Aliases
|
# Aliases
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
"""
|
"""
|
||||||
IO/concurrency helpers for `tqdm.contrib`.
|
IO/concurrency helpers for `tqdm.contrib`.
|
||||||
"""
|
"""
|
||||||
from __future__ import absolute_import
|
|
||||||
|
|
||||||
from collections import deque
|
from collections import deque
|
||||||
from concurrent.futures import ThreadPoolExecutor
|
from concurrent.futures import ThreadPoolExecutor
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
from __future__ import absolute_import
|
|
||||||
|
|
||||||
from functools import partial
|
from functools import partial
|
||||||
|
|
||||||
from dask.callbacks import Callback
|
from dask.callbacks import Callback
|
||||||
|
@ -22,7 +20,7 @@ class TqdmCallback(Callback):
|
||||||
tqdm_kwargs : optional
|
tqdm_kwargs : optional
|
||||||
Any other arguments used for all bars.
|
Any other arguments used for all bars.
|
||||||
"""
|
"""
|
||||||
super(TqdmCallback, self).__init__(start=start, pretask=pretask)
|
super().__init__(start=start, pretask=pretask)
|
||||||
if tqdm_kwargs:
|
if tqdm_kwargs:
|
||||||
tqdm_class = partial(tqdm_class, **tqdm_kwargs)
|
tqdm_class = partial(tqdm_class, **tqdm_kwargs)
|
||||||
self.tqdm_class = tqdm_class
|
self.tqdm_class = tqdm_class
|
||||||
|
|
32
tqdm/gui.py
32
tqdm/gui.py
|
@ -8,16 +8,14 @@ Usage:
|
||||||
"""
|
"""
|
||||||
# future division is important to divide integers and get as
|
# future division is important to divide integers and get as
|
||||||
# a result precise floating numbers (instead of truncated int)
|
# a result precise floating numbers (instead of truncated int)
|
||||||
from __future__ import absolute_import, division
|
|
||||||
|
|
||||||
import re
|
import re
|
||||||
from warnings import warn
|
from warnings import warn
|
||||||
|
|
||||||
# to inherit from the tqdm class
|
# to inherit from the tqdm class
|
||||||
from .std import TqdmExperimentalWarning
|
from .std import TqdmExperimentalWarning
|
||||||
from .std import tqdm as std_tqdm
|
from .std import tqdm as std_tqdm
|
||||||
|
|
||||||
# import compatibility functions and utilities
|
# import compatibility functions and utilities
|
||||||
from .utils import _range
|
|
||||||
|
|
||||||
__author__ = {"github.com/": ["casperdcl", "lrq3000"]}
|
__author__ = {"github.com/": ["casperdcl", "lrq3000"]}
|
||||||
__all__ = ['tqdm_gui', 'tgrange', 'tqdm', 'trange']
|
__all__ = ['tqdm_gui', 'tgrange', 'tqdm', 'trange']
|
||||||
|
@ -34,7 +32,7 @@ class tqdm_gui(std_tqdm): # pragma: no cover
|
||||||
kwargs = kwargs.copy()
|
kwargs = kwargs.copy()
|
||||||
kwargs['gui'] = True
|
kwargs['gui'] = True
|
||||||
colour = kwargs.pop('colour', 'g')
|
colour = kwargs.pop('colour', 'g')
|
||||||
super(tqdm_gui, self).__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
|
|
||||||
if self.disable:
|
if self.disable:
|
||||||
return
|
return
|
||||||
|
@ -124,6 +122,7 @@ class tqdm_gui(std_tqdm): # pragma: no cover
|
||||||
ax = self.ax
|
ax = self.ax
|
||||||
line1 = self.line1
|
line1 = self.line1
|
||||||
line2 = self.line2
|
line2 = self.line2
|
||||||
|
hspan = getattr(self, 'hspan', None)
|
||||||
# instantaneous rate
|
# instantaneous rate
|
||||||
y = delta_it / delta_t
|
y = delta_it / delta_t
|
||||||
# overall rate
|
# overall rate
|
||||||
|
@ -150,18 +149,10 @@ class tqdm_gui(std_tqdm): # pragma: no cover
|
||||||
if total:
|
if total:
|
||||||
line1.set_data(xdata, ydata)
|
line1.set_data(xdata, ydata)
|
||||||
line2.set_data(xdata, zdata)
|
line2.set_data(xdata, zdata)
|
||||||
try:
|
if hspan:
|
||||||
poly_lims = self.hspan.get_xy()
|
hspan.set_xy((0, ymin))
|
||||||
except AttributeError:
|
hspan.set_height(ymax - ymin)
|
||||||
self.hspan = self.plt.axhspan(0, 0.001, xmin=0, xmax=0, color='g')
|
hspan.set_width(n / total)
|
||||||
poly_lims = self.hspan.get_xy()
|
|
||||||
poly_lims[0, 1] = ymin
|
|
||||||
poly_lims[1, 1] = ymax
|
|
||||||
poly_lims[2] = [n / total, ymax]
|
|
||||||
poly_lims[3] = [poly_lims[2, 0], ymin]
|
|
||||||
if len(poly_lims) > 4:
|
|
||||||
poly_lims[4, 1] = ymin
|
|
||||||
self.hspan.set_xy(poly_lims)
|
|
||||||
else:
|
else:
|
||||||
t_ago = [cur_t - i for i in xdata]
|
t_ago = [cur_t - i for i in xdata]
|
||||||
line1.set_data(t_ago, ydata)
|
line1.set_data(t_ago, ydata)
|
||||||
|
@ -173,17 +164,14 @@ class tqdm_gui(std_tqdm): # pragma: no cover
|
||||||
"{bar}", "<bar/>")
|
"{bar}", "<bar/>")
|
||||||
msg = self.format_meter(**d)
|
msg = self.format_meter(**d)
|
||||||
if '<bar/>' in msg:
|
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)
|
ax.set_title(msg, fontname="DejaVu Sans Mono", fontsize=11)
|
||||||
self.plt.pause(1e-9)
|
self.plt.pause(1e-9)
|
||||||
|
|
||||||
|
|
||||||
def tgrange(*args, **kwargs):
|
def tgrange(*args, **kwargs):
|
||||||
"""
|
"""Shortcut for `tqdm.gui.tqdm(range(*args), **kwargs)`."""
|
||||||
A shortcut for `tqdm.gui.tqdm(xrange(*args), **kwargs)`.
|
return tqdm_gui(range(*args), **kwargs)
|
||||||
On Python3+, `range` is used instead of `xrange`.
|
|
||||||
"""
|
|
||||||
return tqdm_gui(_range(*args), **kwargs)
|
|
||||||
|
|
||||||
|
|
||||||
# Aliases
|
# Aliases
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
from __future__ import absolute_import, division
|
|
||||||
|
|
||||||
from copy import copy
|
from copy import copy
|
||||||
from functools import partial
|
from functools import partial
|
||||||
|
|
||||||
|
@ -96,7 +94,7 @@ class TqdmCallback(keras.callbacks.Callback):
|
||||||
raise KeyError('Unknown verbosity')
|
raise KeyError('Unknown verbosity')
|
||||||
|
|
||||||
def on_train_end(self, *_, **__):
|
def on_train_end(self, *_, **__):
|
||||||
if self.verbose:
|
if hasattr(self, 'batch_bar'):
|
||||||
self.batch_bar.close()
|
self.batch_bar.close()
|
||||||
self.epoch_bar.close()
|
self.epoch_bar.close()
|
||||||
|
|
||||||
|
|
|
@ -7,18 +7,14 @@ Usage:
|
||||||
>>> for i in trange(10):
|
>>> 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 compatibility functions and utilities
|
||||||
import re
|
import re
|
||||||
import sys
|
import sys
|
||||||
|
from html import escape
|
||||||
from weakref import proxy
|
from weakref import proxy
|
||||||
|
|
||||||
# to inherit from the tqdm class
|
# to inherit from the tqdm class
|
||||||
from .std import tqdm as std_tqdm
|
from .std import tqdm as std_tqdm
|
||||||
from .utils import _range
|
|
||||||
|
|
||||||
if True: # pragma: no cover
|
if True: # pragma: no cover
|
||||||
# import IPython/Jupyter base widget and display utilities
|
# import IPython/Jupyter base widget and display utilities
|
||||||
|
@ -63,12 +59,6 @@ if True: # pragma: no cover
|
||||||
except ImportError:
|
except ImportError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
# HTML encoding
|
|
||||||
try: # Py3
|
|
||||||
from html import escape
|
|
||||||
except ImportError: # Py2
|
|
||||||
from cgi import escape
|
|
||||||
|
|
||||||
__author__ = {"github.com/": ["lrq3000", "casperdcl", "alexanderkuk"]}
|
__author__ = {"github.com/": ["lrq3000", "casperdcl", "alexanderkuk"]}
|
||||||
__all__ = ['tqdm_notebook', 'tnrange', 'tqdm', 'trange']
|
__all__ = ['tqdm_notebook', 'tnrange', 'tqdm', 'trange']
|
||||||
WARN_NOIPYW = ("IProgress not found. Please update jupyter and ipywidgets."
|
WARN_NOIPYW = ("IProgress not found. Please update jupyter and ipywidgets."
|
||||||
|
@ -90,7 +80,7 @@ class TqdmHBox(HBox):
|
||||||
def __repr__(self, pretty=False):
|
def __repr__(self, pretty=False):
|
||||||
pbar = getattr(self, 'pbar', None)
|
pbar = getattr(self, 'pbar', None)
|
||||||
if pbar is None:
|
if pbar is None:
|
||||||
return super(TqdmHBox, self).__repr__()
|
return super().__repr__()
|
||||||
return pbar.format_meter(**self._json_(pretty))
|
return pbar.format_meter(**self._json_(pretty))
|
||||||
|
|
||||||
def _repr_pretty_(self, pp, *_, **__):
|
def _repr_pretty_(self, pp, *_, **__):
|
||||||
|
@ -167,9 +157,10 @@ class tqdm_notebook(std_tqdm):
|
||||||
pbar.value = self.n
|
pbar.value = self.n
|
||||||
|
|
||||||
if msg:
|
if msg:
|
||||||
|
msg = msg.replace(' ', u'\u2007') # fix html space padding
|
||||||
# html escape special characters (like '&')
|
# html escape special characters (like '&')
|
||||||
if '<bar/>' in msg:
|
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:
|
else:
|
||||||
left, right = '', escape(msg)
|
left, right = '', escape(msg)
|
||||||
|
|
||||||
|
@ -229,7 +220,7 @@ class tqdm_notebook(std_tqdm):
|
||||||
kwargs['disable'] = bool(kwargs.get('disable', False))
|
kwargs['disable'] = bool(kwargs.get('disable', False))
|
||||||
colour = kwargs.pop('colour', None)
|
colour = kwargs.pop('colour', None)
|
||||||
display_here = kwargs.pop('display', True)
|
display_here = kwargs.pop('display', True)
|
||||||
super(tqdm_notebook, self).__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
if self.disable or not kwargs['gui']:
|
if self.disable or not kwargs['gui']:
|
||||||
self.disp = lambda *_, **__: None
|
self.disp = lambda *_, **__: None
|
||||||
return
|
return
|
||||||
|
@ -255,7 +246,7 @@ class tqdm_notebook(std_tqdm):
|
||||||
|
|
||||||
def __iter__(self):
|
def __iter__(self):
|
||||||
try:
|
try:
|
||||||
it = super(tqdm_notebook, self).__iter__()
|
it = super().__iter__()
|
||||||
for obj in it:
|
for obj in it:
|
||||||
# return super(tqdm...) will not catch exception
|
# return super(tqdm...) will not catch exception
|
||||||
yield obj
|
yield obj
|
||||||
|
@ -268,7 +259,7 @@ class tqdm_notebook(std_tqdm):
|
||||||
|
|
||||||
def update(self, n=1):
|
def update(self, n=1):
|
||||||
try:
|
try:
|
||||||
return super(tqdm_notebook, self).update(n=n)
|
return super().update(n=n)
|
||||||
# NB: except ... [ as ...] breaks IPython async KeyboardInterrupt
|
# NB: except ... [ as ...] breaks IPython async KeyboardInterrupt
|
||||||
except: # NOQA
|
except: # NOQA
|
||||||
# cannot catch KeyboardInterrupt when using manual tqdm
|
# cannot catch KeyboardInterrupt when using manual tqdm
|
||||||
|
@ -281,7 +272,7 @@ class tqdm_notebook(std_tqdm):
|
||||||
def close(self):
|
def close(self):
|
||||||
if self.disable:
|
if self.disable:
|
||||||
return
|
return
|
||||||
super(tqdm_notebook, self).close()
|
super().close()
|
||||||
# Try to detect if there was an error or KeyboardInterrupt
|
# Try to detect if there was an error or KeyboardInterrupt
|
||||||
# in manual mode: if n < total, things probably got wrong
|
# in manual mode: if n < total, things probably got wrong
|
||||||
if self.total and self.n < self.total:
|
if self.total and self.n < self.total:
|
||||||
|
@ -306,22 +297,19 @@ class tqdm_notebook(std_tqdm):
|
||||||
total : int or float, optional. Total to use for the new bar.
|
total : int or float, optional. Total to use for the new bar.
|
||||||
"""
|
"""
|
||||||
if self.disable:
|
if self.disable:
|
||||||
return super(tqdm_notebook, self).reset(total=total)
|
return super().reset(total=total)
|
||||||
_, pbar, _ = self.container.children
|
_, pbar, _ = self.container.children
|
||||||
pbar.bar_style = ''
|
pbar.bar_style = ''
|
||||||
if total is not None:
|
if total is not None:
|
||||||
pbar.max = total
|
pbar.max = total
|
||||||
if not self.total and self.ncols is None: # no longer unknown total
|
if not self.total and self.ncols is None: # no longer unknown total
|
||||||
pbar.layout.width = None # reset width
|
pbar.layout.width = None # reset width
|
||||||
return super(tqdm_notebook, self).reset(total=total)
|
return super().reset(total=total)
|
||||||
|
|
||||||
|
|
||||||
def tnrange(*args, **kwargs):
|
def tnrange(*args, **kwargs):
|
||||||
"""
|
"""Shortcut for `tqdm.notebook.tqdm(range(*args), **kwargs)`."""
|
||||||
A shortcut for `tqdm.notebook.tqdm(xrange(*args), **kwargs)`.
|
return tqdm_notebook(range(*args), **kwargs)
|
||||||
On Python3+, `range` is used instead of `xrange`.
|
|
||||||
"""
|
|
||||||
return tqdm_notebook(_range(*args), **kwargs)
|
|
||||||
|
|
||||||
|
|
||||||
# Aliases
|
# Aliases
|
||||||
|
|
17
tqdm/rich.py
17
tqdm/rich.py
|
@ -6,8 +6,6 @@ Usage:
|
||||||
>>> for i in trange(10):
|
>>> for i in trange(10):
|
||||||
... ...
|
... ...
|
||||||
"""
|
"""
|
||||||
from __future__ import absolute_import
|
|
||||||
|
|
||||||
from warnings import warn
|
from warnings import warn
|
||||||
|
|
||||||
from rich.progress import (
|
from rich.progress import (
|
||||||
|
@ -15,7 +13,6 @@ from rich.progress import (
|
||||||
|
|
||||||
from .std import TqdmExperimentalWarning
|
from .std import TqdmExperimentalWarning
|
||||||
from .std import tqdm as std_tqdm
|
from .std import tqdm as std_tqdm
|
||||||
from .utils import _range
|
|
||||||
|
|
||||||
__author__ = {"github.com/": ["casperdcl"]}
|
__author__ = {"github.com/": ["casperdcl"]}
|
||||||
__all__ = ['tqdm_rich', 'trrange', 'tqdm', 'trange']
|
__all__ = ['tqdm_rich', 'trrange', 'tqdm', 'trange']
|
||||||
|
@ -93,7 +90,7 @@ class tqdm_rich(std_tqdm): # pragma: no cover
|
||||||
kwargs['disable'] = bool(kwargs.get('disable', False))
|
kwargs['disable'] = bool(kwargs.get('disable', False))
|
||||||
progress = kwargs.pop('progress', None)
|
progress = kwargs.pop('progress', None)
|
||||||
options = kwargs.pop('options', {}).copy()
|
options = kwargs.pop('options', {}).copy()
|
||||||
super(tqdm_rich, self).__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
|
|
||||||
if self.disable:
|
if self.disable:
|
||||||
return
|
return
|
||||||
|
@ -119,7 +116,8 @@ class tqdm_rich(std_tqdm): # pragma: no cover
|
||||||
def close(self):
|
def close(self):
|
||||||
if self.disable:
|
if self.disable:
|
||||||
return
|
return
|
||||||
super(tqdm_rich, self).close()
|
self.display() # print 100%, vis #1306
|
||||||
|
super().close()
|
||||||
self._prog.__exit__(None, None, None)
|
self._prog.__exit__(None, None, None)
|
||||||
|
|
||||||
def clear(self, *_, **__):
|
def clear(self, *_, **__):
|
||||||
|
@ -140,15 +138,12 @@ class tqdm_rich(std_tqdm): # pragma: no cover
|
||||||
"""
|
"""
|
||||||
if hasattr(self, '_prog'):
|
if hasattr(self, '_prog'):
|
||||||
self._prog.reset(total=total)
|
self._prog.reset(total=total)
|
||||||
super(tqdm_rich, self).reset(total=total)
|
super().reset(total=total)
|
||||||
|
|
||||||
|
|
||||||
def trrange(*args, **kwargs):
|
def trrange(*args, **kwargs):
|
||||||
"""
|
"""Shortcut for `tqdm.rich.tqdm(range(*args), **kwargs)`."""
|
||||||
A shortcut for `tqdm.rich.tqdm(xrange(*args), **kwargs)`.
|
return tqdm_rich(range(*args), **kwargs)
|
||||||
On Python3+, `range` is used instead of `xrange`.
|
|
||||||
"""
|
|
||||||
return tqdm_rich(_range(*args), **kwargs)
|
|
||||||
|
|
||||||
|
|
||||||
# Aliases
|
# Aliases
|
||||||
|
|
345
tqdm/std.py
345
tqdm/std.py
|
@ -7,12 +7,10 @@ Usage:
|
||||||
>>> for i in trange(10):
|
>>> for i in trange(10):
|
||||||
... ...
|
... ...
|
||||||
"""
|
"""
|
||||||
from __future__ import absolute_import, division
|
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
from collections import OrderedDict, defaultdict
|
from collections import OrderedDict, defaultdict
|
||||||
from contextlib import contextmanager
|
from contextlib import contextmanager
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta, timezone
|
||||||
from numbers import Number
|
from numbers import Number
|
||||||
from time import time
|
from time import time
|
||||||
from warnings import warn
|
from warnings import warn
|
||||||
|
@ -21,8 +19,8 @@ from weakref import WeakSet
|
||||||
from ._monitor import TMonitor
|
from ._monitor import TMonitor
|
||||||
from .utils import (
|
from .utils import (
|
||||||
CallbackIOWrapper, Comparable, DisableOnWriteError, FormatReplace, SimpleTextIOWrapper,
|
CallbackIOWrapper, Comparable, DisableOnWriteError, FormatReplace, SimpleTextIOWrapper,
|
||||||
_basestring, _is_ascii, _range, _screen_shape_wrapper, _supports_unicode, _term_move_up,
|
_is_ascii, _screen_shape_wrapper, _supports_unicode, _term_move_up, disp_len, disp_trim,
|
||||||
_unich, _unicode, disp_len, disp_trim)
|
envwrap)
|
||||||
|
|
||||||
__author__ = "https://github.com/tqdm/tqdm#contributions"
|
__author__ = "https://github.com/tqdm/tqdm#contributions"
|
||||||
__all__ = ['tqdm', 'trange',
|
__all__ = ['tqdm', 'trange',
|
||||||
|
@ -48,7 +46,7 @@ class TqdmWarning(Warning):
|
||||||
if fp_write is not None:
|
if fp_write is not None:
|
||||||
fp_write("\n" + self.__class__.__name__ + ": " + str(msg).rstrip() + '\n')
|
fp_write("\n" + self.__class__.__name__ + ": " + str(msg).rstrip() + '\n')
|
||||||
else:
|
else:
|
||||||
super(TqdmWarning, self).__init__(msg, *a, **k)
|
super().__init__(msg, *a, **k)
|
||||||
|
|
||||||
|
|
||||||
class TqdmExperimentalWarning(TqdmWarning, FutureWarning):
|
class TqdmExperimentalWarning(TqdmWarning, FutureWarning):
|
||||||
|
@ -144,7 +142,7 @@ class Bar(object):
|
||||||
+ `b`: blank (`charset=" "` override)
|
+ `b`: blank (`charset=" "` override)
|
||||||
"""
|
"""
|
||||||
ASCII = " 123456789#"
|
ASCII = " 123456789#"
|
||||||
UTF = u" " + u''.join(map(_unich, range(0x258F, 0x2587, -1)))
|
UTF = u" " + u''.join(map(chr, range(0x258F, 0x2587, -1)))
|
||||||
BLANK = " "
|
BLANK = " "
|
||||||
COLOUR_RESET = '\x1b[0m'
|
COLOUR_RESET = '\x1b[0m'
|
||||||
COLOUR_RGB = '\x1b[38;2;%d;%d;%dm'
|
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
|
Decorate an iterable object, returning an iterator which acts exactly
|
||||||
like the original iterable, but prints a dynamically updating
|
like the original iterable, but prints a dynamically updating
|
||||||
progressbar every time a value is requested.
|
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
|
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) < 999.5:
|
||||||
if abs(num) < 99.95:
|
if abs(num) < 99.95:
|
||||||
if abs(num) < 9.995:
|
if abs(num) < 9.995:
|
||||||
return '{0:1.2f}'.format(num) + unit + suffix
|
return f'{num:1.2f}{unit}{suffix}'
|
||||||
return '{0:2.1f}'.format(num) + unit + suffix
|
return f'{num:2.1f}{unit}{suffix}'
|
||||||
return '{0:3.0f}'.format(num) + unit + suffix
|
return f'{num:3.0f}{unit}{suffix}'
|
||||||
num /= divisor
|
num /= divisor
|
||||||
return '{0:3.1f}Y'.format(num) + suffix
|
return f'{num:3.1f}Y{suffix}'
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def format_interval(t):
|
def format_interval(t):
|
||||||
|
@ -302,10 +414,7 @@ class tqdm(Comparable):
|
||||||
"""
|
"""
|
||||||
mins, s = divmod(int(t), 60)
|
mins, s = divmod(int(t), 60)
|
||||||
h, m = divmod(mins, 60)
|
h, m = divmod(mins, 60)
|
||||||
if h:
|
return f'{h:d}:{m:02d}:{s:02d}' if h else f'{m:02d}:{s:02d}'
|
||||||
return '{0:d}:{1:02d}:{2:02d}'.format(h, m, s)
|
|
||||||
else:
|
|
||||||
return '{0:02d}:{1:02d}'.format(m, s)
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def format_num(n):
|
def format_num(n):
|
||||||
|
@ -322,7 +431,7 @@ class tqdm(Comparable):
|
||||||
out : str
|
out : str
|
||||||
Formatted number.
|
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)
|
n = str(n)
|
||||||
return f if len(f) < len(n) else n
|
return f if len(f) < len(n) else n
|
||||||
|
|
||||||
|
@ -340,7 +449,7 @@ class tqdm(Comparable):
|
||||||
getattr(sys.stdout, 'flush', lambda: None)()
|
getattr(sys.stdout, 'flush', lambda: None)()
|
||||||
|
|
||||||
def fp_write(s):
|
def fp_write(s):
|
||||||
fp.write(_unicode(s))
|
fp.write(str(s))
|
||||||
fp_flush()
|
fp_flush()
|
||||||
|
|
||||||
last_len = [0]
|
last_len = [0]
|
||||||
|
@ -442,10 +551,10 @@ class tqdm(Comparable):
|
||||||
rate = (n - initial) / elapsed
|
rate = (n - initial) / elapsed
|
||||||
inv_rate = 1 / rate if rate else None
|
inv_rate = 1 / rate if rate else None
|
||||||
format_sizeof = tqdm.format_sizeof
|
format_sizeof = tqdm.format_sizeof
|
||||||
rate_noinv_fmt = ((format_sizeof(rate) if unit_scale else
|
rate_noinv_fmt = ((format_sizeof(rate) if unit_scale else f'{rate:5.2f}')
|
||||||
'{0:5.2f}'.format(rate)) if rate else '?') + unit + '/s'
|
if rate else '?') + unit + '/s'
|
||||||
rate_inv_fmt = (
|
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
|
if inv_rate else '?') + 's/' + unit
|
||||||
rate_fmt = rate_inv_fmt if inv_rate and inv_rate > 1 else rate_noinv_fmt
|
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 '?'
|
remaining_str = tqdm.format_interval(remaining) if rate else '?'
|
||||||
try:
|
try:
|
||||||
eta_dt = (datetime.now() + timedelta(seconds=remaining)
|
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:
|
except OverflowError:
|
||||||
eta_dt = datetime.max
|
eta_dt = datetime.max
|
||||||
|
|
||||||
|
@ -477,26 +586,25 @@ class tqdm(Comparable):
|
||||||
else:
|
else:
|
||||||
l_bar = ''
|
l_bar = ''
|
||||||
|
|
||||||
r_bar = '| {0}/{1} [{2}<{3}, {4}{5}]'.format(
|
r_bar = f'| {n_fmt}/{total_fmt} [{elapsed_str}<{remaining_str}, {rate_fmt}{postfix}]'
|
||||||
n_fmt, total_fmt, elapsed_str, remaining_str, rate_fmt, postfix)
|
|
||||||
|
|
||||||
# Custom bar formatting
|
# Custom bar formatting
|
||||||
# Populate a dict with all available progress indicators
|
# Populate a dict with all available progress indicators
|
||||||
format_dict = dict(
|
format_dict = {
|
||||||
# slight extension of self.format_dict
|
# slight extension of self.format_dict
|
||||||
n=n, n_fmt=n_fmt, total=total, total_fmt=total_fmt,
|
'n': n, 'n_fmt': n_fmt, 'total': total, 'total_fmt': total_fmt,
|
||||||
elapsed=elapsed_str, elapsed_s=elapsed,
|
'elapsed': elapsed_str, 'elapsed_s': elapsed,
|
||||||
ncols=ncols, desc=prefix or '', unit=unit,
|
'ncols': ncols, 'desc': prefix or '', 'unit': unit,
|
||||||
rate=inv_rate if inv_rate and inv_rate > 1 else rate,
|
'rate': inv_rate if inv_rate and inv_rate > 1 else rate,
|
||||||
rate_fmt=rate_fmt, rate_noinv=rate,
|
'rate_fmt': rate_fmt, 'rate_noinv': rate,
|
||||||
rate_noinv_fmt=rate_noinv_fmt, rate_inv=inv_rate,
|
'rate_noinv_fmt': rate_noinv_fmt, 'rate_inv': inv_rate,
|
||||||
rate_inv_fmt=rate_inv_fmt,
|
'rate_inv_fmt': rate_inv_fmt,
|
||||||
postfix=postfix, unit_divisor=unit_divisor,
|
'postfix': postfix, 'unit_divisor': unit_divisor,
|
||||||
colour=colour,
|
'colour': colour,
|
||||||
# plus more useful definitions
|
# plus more useful definitions
|
||||||
remaining=remaining_str, remaining_s=remaining,
|
'remaining': remaining_str, 'remaining_s': remaining,
|
||||||
l_bar=l_bar, r_bar=r_bar, eta=eta_dt,
|
'l_bar': l_bar, 'r_bar': r_bar, 'eta': eta_dt,
|
||||||
**extra_kwargs)
|
**extra_kwargs}
|
||||||
|
|
||||||
# total is known: we can predict some stats
|
# total is known: we can predict some stats
|
||||||
if total:
|
if total:
|
||||||
|
@ -504,7 +612,7 @@ class tqdm(Comparable):
|
||||||
frac = n / total
|
frac = n / total
|
||||||
percentage = frac * 100
|
percentage = frac * 100
|
||||||
|
|
||||||
l_bar += '{0:3.0f}%|'.format(percentage)
|
l_bar += f'{percentage:3.0f}%|'
|
||||||
|
|
||||||
if ncols == 0:
|
if ncols == 0:
|
||||||
return l_bar[:-1] + r_bar[1:]
|
return l_bar[:-1] + r_bar[1:]
|
||||||
|
@ -513,21 +621,16 @@ class tqdm(Comparable):
|
||||||
if bar_format:
|
if bar_format:
|
||||||
format_dict.update(percentage=percentage)
|
format_dict.update(percentage=percentage)
|
||||||
|
|
||||||
# auto-remove colon for empty `desc`
|
# auto-remove colon for empty `{desc}`
|
||||||
if not prefix:
|
if not prefix:
|
||||||
bar_format = bar_format.replace("{desc}: ", '')
|
bar_format = bar_format.replace("{desc}: ", '')
|
||||||
else:
|
else:
|
||||||
bar_format = "{l_bar}{bar}{r_bar}"
|
bar_format = "{l_bar}{bar}{r_bar}"
|
||||||
|
|
||||||
full_bar = FormatReplace()
|
full_bar = FormatReplace()
|
||||||
try:
|
|
||||||
nobar = bar_format.format(bar=full_bar, **format_dict)
|
|
||||||
except UnicodeEncodeError:
|
|
||||||
bar_format = _unicode(bar_format)
|
|
||||||
nobar = bar_format.format(bar=full_bar, **format_dict)
|
nobar = bar_format.format(bar=full_bar, **format_dict)
|
||||||
if not full_bar.format_called:
|
if not full_bar.format_called:
|
||||||
# no {bar}, we can just format and return
|
return nobar # no `{bar}`; nothing else to do
|
||||||
return nobar
|
|
||||||
|
|
||||||
# Formatting progress bar space available for bar's display
|
# Formatting progress bar space available for bar's display
|
||||||
full_bar = Bar(frac,
|
full_bar = Bar(frac,
|
||||||
|
@ -535,7 +638,7 @@ class tqdm(Comparable):
|
||||||
charset=Bar.ASCII if ascii is True else ascii or Bar.UTF,
|
charset=Bar.ASCII if ascii is True else ascii or Bar.UTF,
|
||||||
colour=colour)
|
colour=colour)
|
||||||
if not _is_ascii(full_bar.charset) and _is_ascii(bar_format):
|
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)
|
res = bar_format.format(bar=full_bar, **format_dict)
|
||||||
return disp_trim(res, ncols) if ncols else res
|
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
|
return disp_trim(res, ncols) if ncols else res
|
||||||
else:
|
else:
|
||||||
# no total: no progressbar, ETA, just progress stats
|
# no total: no progressbar, ETA, just progress stats
|
||||||
return '{0}{1}{2} [{3}, {4}{5}]'.format(
|
return (f'{(prefix + ": ") if prefix else ""}'
|
||||||
(prefix + ": ") if prefix else '', n_fmt, unit, elapsed_str, rate_fmt, postfix)
|
f'{n_fmt}{unit} [{elapsed_str}, {rate_fmt}{postfix}]')
|
||||||
|
|
||||||
def __new__(cls, *_, **__):
|
def __new__(cls, *_, **__):
|
||||||
instance = object.__new__(cls)
|
instance = object.__new__(cls)
|
||||||
|
@ -827,6 +930,8 @@ class tqdm(Comparable):
|
||||||
DataFrame.progress_apply = inner_generator()
|
DataFrame.progress_apply = inner_generator()
|
||||||
DataFrameGroupBy.progress_apply = inner_generator()
|
DataFrameGroupBy.progress_apply = inner_generator()
|
||||||
DataFrame.progress_applymap = inner_generator('applymap')
|
DataFrame.progress_applymap = inner_generator('applymap')
|
||||||
|
DataFrame.progress_map = inner_generator('map')
|
||||||
|
DataFrameGroupBy.progress_map = inner_generator('map')
|
||||||
|
|
||||||
if Panel is not None:
|
if Panel is not None:
|
||||||
Panel.progress_apply = inner_generator()
|
Panel.progress_apply = inner_generator()
|
||||||
|
@ -843,133 +948,17 @@ class tqdm(Comparable):
|
||||||
elif _Rolling_and_Expanding is not None:
|
elif _Rolling_and_Expanding is not None:
|
||||||
_Rolling_and_Expanding.progress_apply = inner_generator()
|
_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,
|
def __init__(self, iterable=None, desc=None, total=None, leave=True, file=None,
|
||||||
ncols=None, mininterval=0.1, maxinterval=10.0, miniters=None,
|
ncols=None, mininterval=0.1, maxinterval=10.0, miniters=None,
|
||||||
ascii=None, disable=False, unit='it', unit_scale=False,
|
ascii=None, disable=False, unit='it', unit_scale=False,
|
||||||
dynamic_ncols=False, smoothing=0.3, bar_format=None, initial=0,
|
dynamic_ncols=False, smoothing=0.3, bar_format=None, initial=0,
|
||||||
position=None, postfix=None, unit_divisor=1000, write_bytes=None,
|
position=None, postfix=None, unit_divisor=1000, write_bytes=False,
|
||||||
lock_args=None, nrows=None, colour=None, delay=0, gui=False,
|
lock_args=None, nrows=None, colour=None, delay=0.0, gui=False,
|
||||||
**kwargs):
|
**kwargs):
|
||||||
"""
|
"""see tqdm.tqdm for arguments"""
|
||||||
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,)
|
|
||||||
|
|
||||||
if file is None:
|
if file is None:
|
||||||
file = sys.stderr
|
file = sys.stderr
|
||||||
|
|
||||||
|
@ -1051,7 +1040,7 @@ class tqdm(Comparable):
|
||||||
|
|
||||||
if bar_format and ascii is not True and not _is_ascii(ascii):
|
if bar_format and ascii is not True and not _is_ascii(ascii):
|
||||||
# Convert bar format into unicode since terminal uses unicode
|
# Convert bar format into unicode since terminal uses unicode
|
||||||
bar_format = _unicode(bar_format)
|
bar_format = str(bar_format)
|
||||||
|
|
||||||
if smoothing is None:
|
if smoothing is None:
|
||||||
smoothing = 0
|
smoothing = 0
|
||||||
|
@ -1120,9 +1109,6 @@ class tqdm(Comparable):
|
||||||
raise TypeError('bool() undefined when iterable == total == None')
|
raise TypeError('bool() undefined when iterable == total == None')
|
||||||
return bool(self.iterable)
|
return bool(self.iterable)
|
||||||
|
|
||||||
def __nonzero__(self):
|
|
||||||
return self.__bool__()
|
|
||||||
|
|
||||||
def __len__(self):
|
def __len__(self):
|
||||||
return (
|
return (
|
||||||
self.total if self.iterable is None
|
self.total if self.iterable is None
|
||||||
|
@ -1298,7 +1284,7 @@ class tqdm(Comparable):
|
||||||
|
|
||||||
# annoyingly, _supports_unicode isn't good enough
|
# annoyingly, _supports_unicode isn't good enough
|
||||||
def fp_write(s):
|
def fp_write(s):
|
||||||
self.fp.write(_unicode(s))
|
self.fp.write(str(s))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
fp_write('')
|
fp_write('')
|
||||||
|
@ -1435,7 +1421,7 @@ class tqdm(Comparable):
|
||||||
if isinstance(postfix[key], Number):
|
if isinstance(postfix[key], Number):
|
||||||
postfix[key] = self.format_num(postfix[key])
|
postfix[key] = self.format_num(postfix[key])
|
||||||
# Else for any other type, try to get the string conversion
|
# 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])
|
postfix[key] = str(postfix[key])
|
||||||
# Else if it's a string, don't need to preprocess anything
|
# Else if it's a string, don't need to preprocess anything
|
||||||
# Stitch together to get the final postfix
|
# Stitch together to get the final postfix
|
||||||
|
@ -1454,7 +1440,7 @@ class tqdm(Comparable):
|
||||||
|
|
||||||
def moveto(self, n):
|
def moveto(self, n):
|
||||||
# TODO: private method
|
# 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)()
|
getattr(self.fp, 'flush', lambda: None)()
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
@ -1534,8 +1520,5 @@ class tqdm(Comparable):
|
||||||
|
|
||||||
|
|
||||||
def trange(*args, **kwargs):
|
def trange(*args, **kwargs):
|
||||||
"""
|
"""Shortcut for tqdm(range(*args), **kwargs)."""
|
||||||
A shortcut for tqdm(xrange(*args), **kwargs).
|
return tqdm(range(*args), **kwargs)
|
||||||
On Python3+ range is used instead of xrange.
|
|
||||||
"""
|
|
||||||
return tqdm(_range(*args), **kwargs)
|
|
||||||
|
|
23
tqdm/tk.py
23
tqdm/tk.py
|
@ -6,22 +6,14 @@ Usage:
|
||||||
>>> for i in trange(10):
|
>>> for i in trange(10):
|
||||||
... ...
|
... ...
|
||||||
"""
|
"""
|
||||||
from __future__ import absolute_import, division
|
|
||||||
|
|
||||||
import re
|
import re
|
||||||
import sys
|
import sys
|
||||||
from warnings import warn
|
|
||||||
|
|
||||||
try:
|
|
||||||
import tkinter
|
import tkinter
|
||||||
import tkinter.ttk as ttk
|
import tkinter.ttk as ttk
|
||||||
except ImportError:
|
from warnings import warn
|
||||||
import Tkinter as tkinter
|
|
||||||
import ttk as ttk
|
|
||||||
|
|
||||||
from .std import TqdmExperimentalWarning, TqdmWarning
|
from .std import TqdmExperimentalWarning, TqdmWarning
|
||||||
from .std import tqdm as std_tqdm
|
from .std import tqdm as std_tqdm
|
||||||
from .utils import _range
|
|
||||||
|
|
||||||
__author__ = {"github.com/": ["richardsheridan", "casperdcl"]}
|
__author__ = {"github.com/": ["richardsheridan", "casperdcl"]}
|
||||||
__all__ = ['tqdm_tk', 'ttkrange', 'tqdm', 'trange']
|
__all__ = ['tqdm_tk', 'ttkrange', 'tqdm', 'trange']
|
||||||
|
@ -61,7 +53,7 @@ class tqdm_tk(std_tqdm): # pragma: no cover
|
||||||
grab = kwargs.pop('grab', False)
|
grab = kwargs.pop('grab', False)
|
||||||
tk_parent = kwargs.pop('tk_parent', None)
|
tk_parent = kwargs.pop('tk_parent', None)
|
||||||
self._cancel_callback = kwargs.pop('cancel_callback', None)
|
self._cancel_callback = kwargs.pop('cancel_callback', None)
|
||||||
super(tqdm_tk, self).__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
|
|
||||||
if self.disable:
|
if self.disable:
|
||||||
return
|
return
|
||||||
|
@ -143,7 +135,7 @@ class tqdm_tk(std_tqdm): # pragma: no cover
|
||||||
"{bar}", "<bar/>")
|
"{bar}", "<bar/>")
|
||||||
msg = self.format_meter(**d)
|
msg = self.format_meter(**d)
|
||||||
if '<bar/>' in msg:
|
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)
|
self._tk_text_var.set(msg)
|
||||||
if not self._tk_dispatching:
|
if not self._tk_dispatching:
|
||||||
self._tk_window.update()
|
self._tk_window.update()
|
||||||
|
@ -180,7 +172,7 @@ class tqdm_tk(std_tqdm): # pragma: no cover
|
||||||
self._tk_pbar.configure(maximum=100, mode="indeterminate")
|
self._tk_pbar.configure(maximum=100, mode="indeterminate")
|
||||||
else:
|
else:
|
||||||
self._tk_pbar.configure(maximum=total, mode="determinate")
|
self._tk_pbar.configure(maximum=total, mode="determinate")
|
||||||
super(tqdm_tk, self).reset(total=total)
|
super().reset(total=total)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _tk_dispatching_helper():
|
def _tk_dispatching_helper():
|
||||||
|
@ -195,11 +187,8 @@ class tqdm_tk(std_tqdm): # pragma: no cover
|
||||||
|
|
||||||
|
|
||||||
def ttkrange(*args, **kwargs):
|
def ttkrange(*args, **kwargs):
|
||||||
"""
|
"""Shortcut for `tqdm.tk.tqdm(range(*args), **kwargs)`."""
|
||||||
A shortcut for `tqdm.tk.tqdm(xrange(*args), **kwargs)`.
|
return tqdm_tk(range(*args), **kwargs)
|
||||||
On Python3+, `range` is used instead of `xrange`.
|
|
||||||
"""
|
|
||||||
return tqdm_tk(_range(*args), **kwargs)
|
|
||||||
|
|
||||||
|
|
||||||
# Aliases
|
# Aliases
|
||||||
|
|
|
@ -204,10 +204,8 @@ float, optional.
|
||||||
.TP
|
.TP
|
||||||
.B \-\-write\-bytes
|
.B \-\-write\-bytes
|
||||||
bool, optional.
|
bool, optional.
|
||||||
If (default: None) and \f[C]file\f[] is unspecified, bytes will be
|
Whether to write bytes.
|
||||||
written in Python 2.
|
If (default: False) will write unicode.
|
||||||
If \f[C]True\f[] will also write bytes.
|
|
||||||
In all other cases will default to unicode.
|
|
||||||
.RS
|
.RS
|
||||||
.RE
|
.RE
|
||||||
.TP
|
.TP
|
||||||
|
|
113
tqdm/utils.py
113
tqdm/utils.py
|
@ -4,34 +4,17 @@ General helpers required for `tqdm.std`.
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
import sys
|
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 warnings import warn
|
||||||
from weakref import proxy
|
from weakref import proxy
|
||||||
|
|
||||||
# py2/3 compat
|
_range, _unich, _unicode, _basestring = range, chr, str, str
|
||||||
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
|
|
||||||
|
|
||||||
CUR_OS = sys.platform
|
CUR_OS = sys.platform
|
||||||
IS_WIN = any(CUR_OS.startswith(i) for i in ['win32', 'cygwin'])
|
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'])
|
IS_NIX = any(CUR_OS.startswith(i) for i in ['aix', 'linux', 'darwin', 'freebsd'])
|
||||||
RE_ANSI = re.compile(r"\x1b\[[;\d]*[A-Za-z]")
|
RE_ANSI = re.compile(r"\x1b\[[;\d]*[A-Za-z]")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -48,10 +31,78 @@ else:
|
||||||
colorama.init()
|
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):
|
class FormatReplace(object):
|
||||||
"""
|
"""
|
||||||
>>> a = FormatReplace('something')
|
>>> a = FormatReplace('something')
|
||||||
>>> "{:5d}".format(a)
|
>>> f"{a:5d}"
|
||||||
'something'
|
'something'
|
||||||
""" # NOQA: P102
|
""" # NOQA: P102
|
||||||
def __init__(self, replace=''):
|
def __init__(self, replace=''):
|
||||||
|
@ -116,7 +167,7 @@ class SimpleTextIOWrapper(ObjectWrapper):
|
||||||
"""
|
"""
|
||||||
# pylint: disable=too-few-public-methods
|
# pylint: disable=too-few-public-methods
|
||||||
def __init__(self, wrapped, encoding):
|
def __init__(self, wrapped, encoding):
|
||||||
super(SimpleTextIOWrapper, self).__init__(wrapped)
|
super().__init__(wrapped)
|
||||||
self.wrapper_setattr('encoding', encoding)
|
self.wrapper_setattr('encoding', encoding)
|
||||||
|
|
||||||
def write(self, s):
|
def write(self, s):
|
||||||
|
@ -160,7 +211,7 @@ class DisableOnWriteError(ObjectWrapper):
|
||||||
return inner
|
return inner
|
||||||
|
|
||||||
def __init__(self, wrapped, tqdm_instance):
|
def __init__(self, wrapped, tqdm_instance):
|
||||||
super(DisableOnWriteError, self).__init__(wrapped)
|
super().__init__(wrapped)
|
||||||
if hasattr(wrapped, 'write'):
|
if hasattr(wrapped, 'write'):
|
||||||
self.wrapper_setattr(
|
self.wrapper_setattr(
|
||||||
'write', self.disable_on_exception(tqdm_instance, wrapped.write))
|
'write', self.disable_on_exception(tqdm_instance, wrapped.write))
|
||||||
|
@ -178,7 +229,7 @@ class CallbackIOWrapper(ObjectWrapper):
|
||||||
Wrap a given `file`-like object's `read()` or `write()` to report
|
Wrap a given `file`-like object's `read()` or `write()` to report
|
||||||
lengths to the given `callback`
|
lengths to the given `callback`
|
||||||
"""
|
"""
|
||||||
super(CallbackIOWrapper, self).__init__(stream)
|
super().__init__(stream)
|
||||||
func = getattr(stream, method)
|
func = getattr(stream, method)
|
||||||
if method == "write":
|
if method == "write":
|
||||||
@wraps(func)
|
@wraps(func)
|
||||||
|
@ -320,14 +371,8 @@ def _term_move_up(): # pragma: no cover
|
||||||
return '' if (os.name == 'nt') and (colorama is None) else '\x1b[A'
|
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):
|
def _text_width(s):
|
||||||
return sum(2 if east_asian_width(ch) in 'FW' else 1 for ch in _unicode(s))
|
return sum(2 if east_asian_width(ch) in 'FW' else 1 for ch in str(s))
|
||||||
|
|
||||||
|
|
||||||
def disp_len(data):
|
def disp_len(data):
|
||||||
|
|
Loading…
Add table
Reference in a new issue