Hello community, here is the log from the commit of package python-tqdm for openSUSE:Factory checked in at 2020-08-01 12:28:19 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-tqdm (Old) and /work/SRC/openSUSE:Factory/.python-tqdm.new.3592 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-tqdm" Sat Aug 1 12:28:19 2020 rev:35 rq:821708 version:4.48.0 Changes: -------- --- /work/SRC/openSUSE:Factory/python-tqdm/python-tqdm.changes 2020-07-06 16:18:49.413231928 +0200 +++ /work/SRC/openSUSE:Factory/.python-tqdm.new.3592/python-tqdm.changes 2020-08-01 12:28:21.450298371 +0200 @@ -1,0 +2,34 @@ +Sat Jul 18 17:53:20 UTC 2020 - Arun Persaud <a...@gmx.de> + +- update to version 4.48.0: + * add tqdm.asyncio (#1004, #772, #91 <- #65) + + supports async iterables (async for row in tqdm(iterable)) + + supports iterables + + supports coroutine.send (tqdm(coroutine).send) + + add as_completed wrapper (for f in tqdm.as_completed(fs)) + * reduce contrib.discord logging verbosity + * fix potential pandas() modifying **kwargs bug + * update documentation + + add missing inline docstrings + + update contributing notes + + update readme + + add to examples/ folder + o async_coroutines + o coroutine_pipe + + standardise variable naming + * add tests + + add benchmark tests against popular alternative libraries + + test new functionality + + more thorough miniters test (#1003) + * misc framework updates + + tidy changelog helper + + add helper bots + o comment-bot /tag + o post-release-bot + - wiki updater + - website updater + o benchmark regressions + - full/thorough test on schedule & release + - quick test on PR + +------------------------------------------------------------------- Old: ---- tqdm-4.47.0.tar.gz New: ---- tqdm-4.48.0.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-tqdm.spec ++++++ --- /var/tmp/diff_new_pack.BPZWfm/_old 2020-08-01 12:28:23.238300045 +0200 +++ /var/tmp/diff_new_pack.BPZWfm/_new 2020-08-01 12:28:23.238300045 +0200 @@ -28,7 +28,7 @@ %bcond_with test %endif Name: python-tqdm%{pkg_suffix} -Version: 4.47.0 +Version: 4.48.0 Release: 0 Summary: An extensible progress meter License: MPL-2.0 AND MIT ++++++ tqdm-4.47.0.tar.gz -> tqdm-4.48.0.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tqdm-4.47.0/CONTRIBUTING.md new/tqdm-4.48.0/CONTRIBUTING.md --- old/tqdm-4.47.0/CONTRIBUTING.md 2020-06-29 00:38:16.000000000 +0200 +++ new/tqdm-4.48.0/CONTRIBUTING.md 2020-07-17 00:03:58.000000000 +0200 @@ -321,16 +321,35 @@ Additionally (less maintained), there exists: - A [wiki] which is publicly editable. -- The [gh-pages project](https://tqdm.github.io/tqdm/) which is built from the +- The [gh-pages project] which is built from the [gh-pages branch](https://github.com/tqdm/tqdm/tree/gh-pages), which is - built using [asv](https://github.com/spacetelescope/asv/). -- The [gh-pages root](https://tqdm.github.io/) which is built from a separate + built using [asv](https://github.com/airspeed-velocity/asv). +- The [gh-pages root] which is built from a separate [github.io repo](https://github.com/tqdm/tqdm.github.io). +[gh-pages project]: https://tqdm.github.io/tqdm/ +[gh-pages root]: https://tqdm.github.io/ + + +## Helper Bots + +There are some helpers in +[.github/workflows](https://github.com/tqdm/tqdm/tree/master/.github/workflows) +to assist with maintenance. + +- Comment Bot + + allows maintainers to write `/tag vM.m.p commit_hash` in an issue/PR to create a tag +- Post Release + + automatically updates the [wiki] + + automatically updates the [gh-pages root] +- Benchmark + + automatically updates the [gh-pages project] + ## QUICK DEV SUMMARY -For experienced devs, once happy with local master: +For experienced devs, once happy with local master, follow the steps below. +Much is automated so really it's steps 1-6, then 12(a). 1. bump version in `tqdm/_version.py` 2. test (`[python setup.py] make alltests`) @@ -338,7 +357,7 @@ 4. `git push` 5. wait for tests to pass a) in case of failure, fix and go back to (2) -6. `git tag vM.m.p && git push --tags` +6. `git tag vM.m.p && git push --tags` or comment `/tag vM.m.p commit_hash` 7. **`[AUTO:TravisCI]`** `[python setup.py] make distclean` 8. **`[AUTO:TravisCI]`** `[python setup.py] make build` 9. **`[AUTO:TravisCI]`** upload to PyPI. either: @@ -352,16 +371,18 @@ a) `make snap`, and b) `snapcraft push tqdm*.snap --release stable` 12. Wait for travis to draft a new release on <https://github.com/tqdm/tqdm/releases> - a) add helpful release notes + a) replace the commit history with helpful release notes, and click publish b) **`[AUTO:TravisCI]`** attach `dist/tqdm-*` binaries (usually only `*.whl*`) -13. **`[SUB]`** run `make` in the `wiki` submodule to update release notes -14. **`[SUB]`** run `make deploy` in the `docs` submodule to update website -15. **`[SUB]`** accept the automated PR in the `feedstock` submodule to update conda +13. **`[SUB][AUTO:GHActions]`** run `make` in the `wiki` submodule to update release notes +14. **`[SUB][AUTO:GHActions]`** run `make deploy` in the `docs` submodule to update website +15. **`[SUB][AUTO:GHActions]`** accept the automated PR in the `feedstock` submodule to update conda +16. **`[AUTO:GHActions]`** update the [gh-pages project] benchmarks + a) `[python setup.py] make testasvfull` + b) `asv gh-pages` Key: -- **`[AUTO:TravisCI]`**: Travis CI should automatically do this after - `git push --tags` (6) -- **`[SUB]`**: Requires one-time `make submodules` to clone - `docs`, `wiki`, and `feedstock` +- **`[AUTO:TravisCI]`**: Travis CI should automatically do this after `git push --tags` (6) +- **`[AUTO:GHActions]`**: GitHub Actions CI should automatically do this after release (12a) +- **`[SUB]`**: Requires one-time `make submodules` to clone `docs`, `wiki`, and `feedstock` diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tqdm-4.47.0/Makefile new/tqdm-4.48.0/Makefile --- old/tqdm-4.47.0/Makefile 2020-06-29 00:38:16.000000000 +0200 +++ new/tqdm-4.48.0/Makefile 2020-07-17 00:03:58.000000000 +0200 @@ -79,7 +79,7 @@ testasvfull: # Test all the commits since the beginning (full test) - asv run -j 8 v1.0.0..master + asv run --skip-existing-commits -j 8 v1.0.0..HEAD @make testasv viewasv: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tqdm-4.47.0/PKG-INFO new/tqdm-4.48.0/PKG-INFO --- old/tqdm-4.47.0/PKG-INFO 2020-06-29 00:38:32.000000000 +0200 +++ new/tqdm-4.48.0/PKG-INFO 2020-07-17 00:04:14.000000000 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: tqdm -Version: 4.47.0 +Version: 4.48.0 Summary: Fast, Extensible Progress Meter Home-page: https://github.com/tqdm/tqdm Maintainer: tqdm developers @@ -551,7 +551,7 @@ Forces refresh [default: True]. """ - def set_postfix(self, ordered_dict=None, refresh=True, **kwargs): + def set_postfix(self, ordered_dict=None, refresh=True, **tqdm_kwargs): """ Set/modify postfix (additional stats) with automatic formatting based on datatype. @@ -586,29 +586,55 @@ (default: ``abs(self.pos)``). """ - def trange(*args, **kwargs): + @classmethod + @contextmanager + def wrapattr(cls, stream, method, total=None, bytes=True, **tqdm_kwargs): + """ + stream : file-like object. + method : str, "read" or "write". The result of ``read()`` and + the first argument of ``write()`` should have a ``len()``. + + >>> with tqdm.wrapattr(file_obj, "read", total=file_obj.size) as fobj: + ... while True: + ... chunk = fobj.read(chunk_size) + ... if not chunk: + ... break + """ + + @classmethod + def pandas(cls, *targs, **tqdm_kwargs): + """Registers the current `tqdm` class with `pandas`.""" + + def trange(*args, **tqdm_kwargs): """ - A shortcut for tqdm(xrange(*args), **kwargs). - On Python3+ range is used instead of xrange. + A shortcut for `tqdm(xrange(*args), **tqdm_kwargs)`. + On Python3+, `range` is used instead of `xrange`. """ - class tqdm.gui.tqdm(tqdm.tqdm): - """Experimental GUI version""" + class tqdm.notebook.tqdm(tqdm.tqdm): + """Experimental IPython/Jupyter Notebook widget.""" - def tqdm.gui.trange(*args, **kwargs): - """Experimental GUI version of trange""" + def tqdm.notebook.trange(*args, **tqdm_kwargs): + """Experimental IPython/Jupyter Notebook widget version of `trange`.""" - class tqdm.notebook.tqdm(tqdm.tqdm): - """Experimental IPython/Jupyter Notebook widget""" + class tqdm.auto.tqdm(tqdm.tqdm): + """Automatically chooses beween `tqdm.notebook` and `tqdm.tqdm`.""" - def tqdm.notebook.trange(*args, **kwargs): - """Experimental IPython/Jupyter Notebook widget version of trange""" + class tqdm.asyncio.tqdm(tqdm.tqdm): + """Asynchronous version.""" + @classmethod + def as_completed(cls, fs, *, loop=None, timeout=None, total=None, + **tqdm_kwargs): + """Wrapper for `asyncio.as_completed`.""" + + class tqdm.gui.tqdm(tqdm.tqdm): + """Experimental GUI version.""" class tqdm.keras.TqdmCallback(keras.callbacks.Callback): - """`keras` callback for epoch and batch progress""" + """`keras` callback for epoch and batch progress.""" def tqdm.contrib.tenumerate(iterable, start=0, total=None, - tqdm_class=tqdm.auto.tqdm, **kwargs): + tqdm_class=tqdm.auto.tqdm, **tqdm_kwargs): """Equivalent of `numpy.ndenumerate` or builtin `enumerate`.""" def tqdm.contrib.tzip(iter1, *iter2plus, **tqdm_kwargs): @@ -624,13 +650,12 @@ - ``tqdm.contrib.itertools``: Thin wrappers around ``itertools`` - ``tqdm.contrib.concurrent``: Thin wrappers around ``concurrent.futures`` + - ``tqdm.contrib.discord``: Posts to `Discord <https://discord.com/>`__ bots + - ``tqdm.contrib.telegram``: Posts to `Telegram <https://telegram.org/>`__ bots - ``tqdm.contrib.bells``: Automagically enables all optional features * ``auto``, ``pandas``, ``discord``, ``telegram`` - - ``tqdm.contrib.discord``: Posts to `Discord <https://discord.com/>`__ bots - - ``tqdm.contrib.telegram``: Posts to `Telegram <https://telegram.org/>`__ bots - Examples and Advanced Usage --------------------------- diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tqdm-4.47.0/README.rst new/tqdm-4.48.0/README.rst --- old/tqdm-4.47.0/README.rst 2020-06-29 00:38:30.000000000 +0200 +++ new/tqdm-4.48.0/README.rst 2020-07-17 00:04:13.000000000 +0200 @@ -543,7 +543,7 @@ Forces refresh [default: True]. """ - def set_postfix(self, ordered_dict=None, refresh=True, **kwargs): + def set_postfix(self, ordered_dict=None, refresh=True, **tqdm_kwargs): """ Set/modify postfix (additional stats) with automatic formatting based on datatype. @@ -578,29 +578,55 @@ (default: ``abs(self.pos)``). """ - def trange(*args, **kwargs): + @classmethod + @contextmanager + def wrapattr(cls, stream, method, total=None, bytes=True, **tqdm_kwargs): + """ + stream : file-like object. + method : str, "read" or "write". The result of ``read()`` and + the first argument of ``write()`` should have a ``len()``. + + >>> with tqdm.wrapattr(file_obj, "read", total=file_obj.size) as fobj: + ... while True: + ... chunk = fobj.read(chunk_size) + ... if not chunk: + ... break + """ + + @classmethod + def pandas(cls, *targs, **tqdm_kwargs): + """Registers the current `tqdm` class with `pandas`.""" + + def trange(*args, **tqdm_kwargs): """ - A shortcut for tqdm(xrange(*args), **kwargs). - On Python3+ range is used instead of xrange. + A shortcut for `tqdm(xrange(*args), **tqdm_kwargs)`. + On Python3+, `range` is used instead of `xrange`. """ - class tqdm.gui.tqdm(tqdm.tqdm): - """Experimental GUI version""" + class tqdm.notebook.tqdm(tqdm.tqdm): + """Experimental IPython/Jupyter Notebook widget.""" - def tqdm.gui.trange(*args, **kwargs): - """Experimental GUI version of trange""" + def tqdm.notebook.trange(*args, **tqdm_kwargs): + """Experimental IPython/Jupyter Notebook widget version of `trange`.""" - class tqdm.notebook.tqdm(tqdm.tqdm): - """Experimental IPython/Jupyter Notebook widget""" + class tqdm.auto.tqdm(tqdm.tqdm): + """Automatically chooses beween `tqdm.notebook` and `tqdm.tqdm`.""" - def tqdm.notebook.trange(*args, **kwargs): - """Experimental IPython/Jupyter Notebook widget version of trange""" + class tqdm.asyncio.tqdm(tqdm.tqdm): + """Asynchronous version.""" + @classmethod + def as_completed(cls, fs, *, loop=None, timeout=None, total=None, + **tqdm_kwargs): + """Wrapper for `asyncio.as_completed`.""" + + class tqdm.gui.tqdm(tqdm.tqdm): + """Experimental GUI version.""" class tqdm.keras.TqdmCallback(keras.callbacks.Callback): - """`keras` callback for epoch and batch progress""" + """`keras` callback for epoch and batch progress.""" def tqdm.contrib.tenumerate(iterable, start=0, total=None, - tqdm_class=tqdm.auto.tqdm, **kwargs): + tqdm_class=tqdm.auto.tqdm, **tqdm_kwargs): """Equivalent of `numpy.ndenumerate` or builtin `enumerate`.""" def tqdm.contrib.tzip(iter1, *iter2plus, **tqdm_kwargs): @@ -616,13 +642,12 @@ - ``tqdm.contrib.itertools``: Thin wrappers around ``itertools`` - ``tqdm.contrib.concurrent``: Thin wrappers around ``concurrent.futures`` +- ``tqdm.contrib.discord``: Posts to `Discord <https://discord.com/>`__ bots +- ``tqdm.contrib.telegram``: Posts to `Telegram <https://telegram.org/>`__ bots - ``tqdm.contrib.bells``: Automagically enables all optional features * ``auto``, ``pandas``, ``discord``, ``telegram`` -- ``tqdm.contrib.discord``: Posts to `Discord <https://discord.com/>`__ bots -- ``tqdm.contrib.telegram``: Posts to `Telegram <https://telegram.org/>`__ bots - Examples and Advanced Usage --------------------------- diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tqdm-4.47.0/examples/async_coroutines.py new/tqdm-4.48.0/examples/async_coroutines.py --- old/tqdm-4.47.0/examples/async_coroutines.py 1970-01-01 01:00:00.000000000 +0100 +++ new/tqdm-4.48.0/examples/async_coroutines.py 2020-07-17 00:03:58.000000000 +0200 @@ -0,0 +1,37 @@ +""" +Asynchronous examples using `asyncio`, `async` and `await` on `python>=3.7`. +""" +import asyncio +from tqdm.asyncio import tqdm, trange + + +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 main(): + N = int(1e6) + async for row in tqdm(trange(N, desc="inner"), desc="outer"): + if row >= N: + break + with tqdm(count(), desc="coroutine", total=N + 2) as pbar: + async for row in pbar: + if row == N: + pbar.send(-10) + elif row < 0: + assert row == -9 + break + # should be under 10 seconds + for i in tqdm.as_completed(list(map(asyncio.sleep, [1] * 10)), + desc="as_completed"): + await i + + +if __name__ == "__main__": + asyncio.run(main()) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tqdm-4.47.0/examples/coroutine_pipe.py new/tqdm-4.48.0/examples/coroutine_pipe.py --- old/tqdm-4.47.0/examples/coroutine_pipe.py 1970-01-01 01:00:00.000000000 +0100 +++ new/tqdm-4.48.0/examples/coroutine_pipe.py 2020-07-17 00:03:58.000000000 +0200 @@ -0,0 +1,68 @@ +""" +Inserting `tqdm` as a "pipe" in a chain of coroutines. +Not to be confused with `asyncio.coroutine`. +""" +from functools import wraps +from tqdm.auto import tqdm + + +def autonext(func): + @wraps(func) + def inner(*args, **kwargs): + res = func(*args, **kwargs) + next(res) + return res + return inner + + +@autonext +def tqdm_pipe(target, **tqdm_kwargs): + """ + Coroutine chain pipe `send()`ing to `target`. + + This: + >>> r = receiver() + >>> p = producer(r) + >>> next(r) + >>> next(p) + + Becomes: + >>> r = receiver() + >>> t = tqdm.pipe(r) + >>> p = producer(t) + >>> next(r) + >>> next(p) + """ + with tqdm(**tqdm_kwargs) as pbar: + while True: + obj = (yield) + target.send(obj) + pbar.update() + + +def source(target): + for i in ["foo", "bar", "baz", "pythonista", "python", "py"]: + target.send(i) + target.close() + + +@autonext +def grep(pattern, target): + while True: + line = (yield) + if pattern in line: + target.send(line) + + +@autonext +def sink(): + while True: + line = (yield) + tqdm.write(line) + + +if __name__ == "__main__": + source( + tqdm_pipe( + grep('python', + sink()))) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tqdm-4.47.0/tqdm/_tqdm_pandas.py new/tqdm-4.48.0/tqdm/_tqdm_pandas.py --- old/tqdm-4.47.0/tqdm/_tqdm_pandas.py 2020-06-29 00:38:16.000000000 +0200 +++ new/tqdm-4.48.0/tqdm/_tqdm_pandas.py 2020-07-17 00:03:58.000000000 +0200 @@ -4,32 +4,10 @@ __all__ = ['tqdm_pandas'] -def tqdm_pandas(tclass, *targs, **tkwargs): +def tqdm_pandas(tclass, **tqdm_kwargs): """ Registers the given `tqdm` instance with `pandas.core.groupby.DataFrameGroupBy.progress_apply`. - It will even close() the `tqdm` instance upon completion. - - Parameters - ---------- - tclass : tqdm class you want to use (eg, tqdm, tqdm_notebook, etc) - targs and tkwargs : arguments for the tqdm instance - - Examples - -------- - >>> import pandas as pd - >>> import numpy as np - >>> from tqdm import tqdm, tqdm_pandas - >>> - >>> df = pd.DataFrame(np.random.randint(0, 100, (100000, 6))) - >>> tqdm_pandas(tqdm, leave=True) # can use tqdm_gui, optional kwargs, etc - >>> # Now you can use `progress_apply` instead of `apply` - >>> df.groupby(0).progress_apply(lambda x: x**2) - - References - ---------- - https://stackoverflow.com/questions/18603270/ - progress-indicator-during-pandas-operations-python """ from tqdm import TqdmDeprecationWarning @@ -37,8 +15,8 @@ 'tqdm_')): # delayed adapter case TqdmDeprecationWarning("""\ Please use `tqdm.pandas(...)` instead of `tqdm_pandas(tqdm, ...)`. -""", fp_write=getattr(tkwargs.get('file', None), 'write', sys.stderr.write)) - tclass.pandas(*targs, **tkwargs) +""", fp_write=getattr(tqdm_kwargs.get('file', None), 'write', sys.stderr.write)) + tclass.pandas(**tqdm_kwargs) else: TqdmDeprecationWarning("""\ Please use `tqdm.pandas(...)` instead of `tqdm_pandas(tqdm(...))`. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tqdm-4.47.0/tqdm/_version.py new/tqdm-4.48.0/tqdm/_version.py --- old/tqdm-4.47.0/tqdm/_version.py 2020-06-29 00:38:16.000000000 +0200 +++ new/tqdm-4.48.0/tqdm/_version.py 2020-07-17 00:03:58.000000000 +0200 @@ -5,7 +5,7 @@ __all__ = ["__version__"] # major, minor, patch, -extra -version_info = 4, 47, 0 +version_info = 4, 48, 0 # Nice string for the version __version__ = '.'.join(map(str, version_info)) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tqdm-4.47.0/tqdm/asyncio.py new/tqdm-4.48.0/tqdm/asyncio.py --- old/tqdm-4.47.0/tqdm/asyncio.py 1970-01-01 01:00:00.000000000 +0100 +++ new/tqdm-4.48.0/tqdm/asyncio.py 2020-07-17 00:03:58.000000000 +0200 @@ -0,0 +1,72 @@ +""" +Asynchronous progressbar decorator for iterators. +Includes a default `range` iterator printing to `stderr`. + +Usage: +>>> from tqdm.asyncio import trange, tqdm +>>> async for i in trange(10): +... ... +""" +from .auto import tqdm as tqdm_auto +import asyncio +__author__ = {"github.com/": ["casperdcl"]} +__all__ = ['tqdm_asyncio', 'tarange', 'tqdm', 'trange'] + + +class tqdm_asyncio(tqdm_auto): + def __init__(self, iterable=None, *args, **kwargs): + super(tqdm_asyncio, self).__init__(iterable, *args, **kwargs) + self.iterable_awaitable = False + if iterable is not None: + if hasattr(iterable, "__anext__"): + self.iterable_next = iterable.__anext__ + self.iterable_awaitable = True + elif hasattr(iterable, "__next__"): + self.iterable_next = iterable.__next__ + else: + self.iterable_iterator = iter(iterable) + self.iterable_next = self.iterable_iterator.__next__ + + def __aiter__(self): + return self + + async def __anext__(self): + try: + if self.iterable_awaitable: + res = await self.iterable_next() + else: + res = self.iterable_next() + self.update() + return res + except StopIteration: + self.close() + raise StopAsyncIteration + except: + self.close() + raise + + def send(self, *args, **kwargs): + return self.iterable.send(*args, **kwargs) + + @classmethod + def as_completed(cls, fs, *, loop=None, timeout=None, total=None, + **tqdm_kwargs): + """ + Wrapper for `asyncio.as_completed`. + """ + if total is None: + total = len(fs) + yield from cls(asyncio.as_completed(fs, loop=loop, timeout=timeout), + total=total, **tqdm_kwargs) + + +def tarange(*args, **kwargs): + """ + A shortcut for `tqdm.asyncio.tqdm(range(*args), **kwargs)`. + """ + return tqdm_asyncio(range(*args), **kwargs) + + +# Aliases +tqdm = tqdm_asyncio +trange = tarange diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tqdm-4.47.0/tqdm/auto.py new/tqdm-4.48.0/tqdm/auto.py --- old/tqdm-4.47.0/tqdm/auto.py 2020-06-29 00:38:16.000000000 +0200 +++ new/tqdm-4.48.0/tqdm/auto.py 2020-07-17 00:03:58.000000000 +0200 @@ -1,3 +1,11 @@ +""" +`tqdm.autonotebook` but without import warnings. + +Usage: +>>> from tqdm.auto import trange, tqdm +>>> for i in trange(10): +... ... +""" import warnings from .std import TqdmExperimentalWarning with warnings.catch_warnings(): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tqdm-4.47.0/tqdm/autonotebook.py new/tqdm-4.48.0/tqdm/autonotebook.py --- old/tqdm-4.47.0/tqdm/autonotebook.py 2020-06-29 00:38:16.000000000 +0200 +++ new/tqdm-4.48.0/tqdm/autonotebook.py 2020-07-17 00:03:58.000000000 +0200 @@ -1,3 +1,11 @@ +""" +Automatically choose between `tqdm.notebook` and `tqdm.std`. + +Usage: +>>> from tqdm.autonotebook import trange, tqdm +>>> for i in trange(10): +... ... +""" import os import sys diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tqdm-4.47.0/tqdm/contrib/bells.py new/tqdm-4.48.0/tqdm/contrib/bells.py --- old/tqdm-4.47.0/tqdm/contrib/bells.py 2020-06-29 00:38:16.000000000 +0200 +++ new/tqdm-4.48.0/tqdm/contrib/bells.py 2020-07-17 00:03:58.000000000 +0200 @@ -1,12 +1,12 @@ """ All the bells & whistles: -- tqdm.auto -- tqdm.tqdm.pandas -- tqdm.contrib.telegram - + uses ${TQDM_TELEGRAM_TOKEN} and ${TQDM_TELEGRAM_CHAT_ID} -- tqdm.contrib.discord - + uses ${TQDM_DISCORD_TOKEN} and ${TQDM_DISCORD_CHANNEL_ID} +- `tqdm.auto` +- `tqdm.tqdm.pandas` +- `tqdm.contrib.telegram` + + uses `${TQDM_TELEGRAM_TOKEN}` and `${TQDM_TELEGRAM_CHAT_ID}` +- `tqdm.contrib.discord` + + uses `${TQDM_DISCORD_TOKEN}` and `${TQDM_DISCORD_CHANNEL_ID}` """ __all__ = ['tqdm', 'trange'] from os import getenv diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tqdm-4.47.0/tqdm/contrib/discord.py new/tqdm-4.48.0/tqdm/contrib/discord.py --- old/tqdm-4.47.0/tqdm/contrib/discord.py 2020-06-29 00:38:16.000000000 +0200 +++ new/tqdm-4.48.0/tqdm/contrib/discord.py 2020-07-17 00:03:58.000000000 +0200 @@ -1,8 +1,17 @@ """ Sends updates to a Discord bot. + +Usage: +>>> from tqdm.contrib.discord import tqdm, trange +>>> for i in tqdm(iterable, token='{token}', channel_id='{channel_id}'): +... ... + +![screenshot]( +https://raw.githubusercontent.com/tqdm/img/src/screenshot-discord.png) """ from __future__ import absolute_import from copy import deepcopy +import logging from os import getenv try: @@ -55,7 +64,7 @@ - create a discord bot (not public, no requirement of OAuth2 code grant, only send message permissions) & invite it to a channel: - https://discordpy.readthedocs.io/en/latest/discord.html + <https://discordpy.readthedocs.io/en/latest/discord.html> - copy the bot `{token}` & `{channel_id}` and paste below >>> from tqdm.contrib.discord import tqdm, trange @@ -76,6 +85,7 @@ See `tqdm.auto.tqdm.__init__` for other parameters. """ kwargs = deepcopy(kwargs) + logging.getLogger("HTTPClient").setLevel(logging.WARNING) self.dio = DiscordIO( kwargs.pop('token', getenv("TQDM_DISCORD_TOKEN")), kwargs.pop('channel_id', getenv("TQDM_DISCORD_CHANNEL_ID"))) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tqdm-4.47.0/tqdm/contrib/telegram.py new/tqdm-4.48.0/tqdm/contrib/telegram.py --- old/tqdm-4.47.0/tqdm/contrib/telegram.py 2020-06-29 00:38:16.000000000 +0200 +++ new/tqdm-4.48.0/tqdm/contrib/telegram.py 2020-07-17 00:03:58.000000000 +0200 @@ -1,5 +1,13 @@ """ Sends updates to a Telegram bot. + +Usage: +>>> from tqdm.contrib.telegram import tqdm, trange +>>> for i in trange(10, token='{token}', chat_id='{chat_id}'): +... ... + +![screenshot]( +https://raw.githubusercontent.com/tqdm/img/src/screenshot-telegram.gif) """ from __future__ import absolute_import from copy import deepcopy @@ -61,10 +69,10 @@ Standard `tqdm.auto.tqdm` but also sends updates to a Telegram Bot. May take a few seconds to create (`__init__`). - - create a bot https://core.telegram.org/bots#6-botfather + - create a bot <https://core.telegram.org/bots#6-botfather> - copy its `{token}` - add the bot to a chat and send it a message such as `/start` - - go to https://api.telegram.org/bot`{token}`/getUpdates to find out + - go to <https://api.telegram.org/bot`{token}`/getUpdates> to find out the `{chat_id}` - paste the `{token}` & `{chat_id}` below diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tqdm-4.47.0/tqdm/gui.py new/tqdm-4.48.0/tqdm/gui.py --- old/tqdm-4.47.0/tqdm/gui.py 2020-06-29 00:38:16.000000000 +0200 +++ new/tqdm-4.48.0/tqdm/gui.py 2020-07-17 00:03:58.000000000 +0200 @@ -1,11 +1,11 @@ """ GUI progressbar decorator for iterators. -Includes a default (x)range iterator printing to stderr. +Includes a default `range` iterator printing to `stderr`. Usage: - >>> from tqdm.gui import trange[, tqdm] - >>> for i in trange(10): #same as: for i in tqdm(xrange(10)) - ... ... +>>> from tqdm.gui import trange, tqdm +>>> for i in trange(10): +... ... """ # future division is important to divide integers and get as # a result precise floating numbers (instead of truncated int) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tqdm-4.47.0/tqdm/notebook.py new/tqdm-4.48.0/tqdm/notebook.py --- old/tqdm-4.47.0/tqdm/notebook.py 2020-06-29 00:38:16.000000000 +0200 +++ new/tqdm-4.48.0/tqdm/notebook.py 2020-07-17 00:03:58.000000000 +0200 @@ -1,11 +1,11 @@ """ IPython/Jupyter Notebook progressbar decorator for iterators. -Includes a default (x)range iterator printing to stderr. +Includes a default `range` iterator printing to `stderr`. Usage: - >>> from tqdm.notebook import trange[, tqdm] - >>> for i in trange(10): #same as: for i in tqdm(xrange(10)) - ... ... +>>> from tqdm.notebook import trange, tqdm +>>> for i in trange(10): +... ... """ # future division is important to divide integers and get as # a result precise floating numbers (instead of truncated int) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tqdm-4.47.0/tqdm/std.py new/tqdm-4.48.0/tqdm/std.py --- old/tqdm-4.47.0/tqdm/std.py 2020-06-29 00:38:16.000000000 +0200 +++ new/tqdm-4.48.0/tqdm/std.py 2020-07-17 00:03:58.000000000 +0200 @@ -1,11 +1,11 @@ """ Customisable progressbar decorator for iterators. -Includes a default (x)range iterator printing to stderr. +Includes a default `range` iterator printing to `stderr`. Usage: - >>> from tqdm import trange[, tqdm] - >>> for i in trange(10): #same as: for i in tqdm(xrange(10)) - ... ... +>>> from tqdm import trange, tqdm +>>> for i in trange(10): +... ... """ from __future__ import absolute_import, division # compatibility functions and utilities @@ -628,9 +628,9 @@ return cls._lock @classmethod - def pandas(tclass, *targs, **tkwargs): + def pandas(cls, **tqdm_kwargs): """ - Registers the given `tqdm` class with + Registers the current `tqdm` class with pandas.core. ( frame.DataFrame | series.Series @@ -639,11 +639,11 @@ ).progress_apply A new instance will be create every time `progress_apply` is called, - and each instance will automatically close() upon completion. + and each instance will automatically `close()` upon completion. Parameters ---------- - targs, tkwargs : arguments for the tqdm instance + tqdm_kwargs : arguments for the tqdm instance Examples -------- @@ -659,8 +659,8 @@ References ---------- - https://stackoverflow.com/questions/18603270/ - progress-indicator-during-pandas-operations-python + <https://stackoverflow.com/questions/18603270/\ + progress-indicator-during-pandas-operations-python> """ from pandas.core.frame import DataFrame from pandas.core.series import Series @@ -698,7 +698,8 @@ except ImportError: # pandas>=0.25.0 PanelGroupBy = None - deprecated_t = [tkwargs.pop('deprecated_t', None)] + tqdm_kwargs = tqdm_kwargs.copy() + deprecated_t = [tqdm_kwargs.pop('deprecated_t', None)] def inner_generator(df_function='apply'): def inner(df, func, *args, **kwargs): @@ -714,7 +715,7 @@ """ # Precompute total iterations - total = tkwargs.pop("total", getattr(df, 'ngroups', None)) + total = tqdm_kwargs.pop("total", getattr(df, 'ngroups', None)) if total is None: # not grouped if df_function == 'applymap': total = df.size @@ -736,7 +737,7 @@ t = deprecated_t[0] deprecated_t[0] = None else: - t = tclass(*targs, total=total, **tkwargs) + t = cls(total=total, **tqdm_kwargs) if len(args) > 0: # *args intentionally not supported (see #244, #299) @@ -1475,7 +1476,7 @@ @classmethod @contextmanager - def wrapattr(tclass, stream, method, total=None, bytes=True, **tkwargs): + def wrapattr(cls, stream, method, total=None, bytes=True, **tqdm_kwargs): """ stream : file-like object. method : str, "read" or "write". The result of `read()` and @@ -1487,7 +1488,7 @@ ... if not chunk: ... break """ - with tclass(total=total, **tkwargs) as t: + with cls(total=total, **tqdm_kwargs) as t: if bytes: t.unit = "B" t.unit_scale = True diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tqdm-4.47.0/tqdm/tests/py37_asyncio.py new/tqdm-4.48.0/tqdm/tests/py37_asyncio.py --- old/tqdm-4.47.0/tqdm/tests/py37_asyncio.py 1970-01-01 01:00:00.000000000 +0100 +++ new/tqdm-4.48.0/tqdm/tests/py37_asyncio.py 2020-07-17 00:03:58.000000000 +0200 @@ -0,0 +1,103 @@ +import asyncio +from functools import partial, wraps +from time import time + +from tests_tqdm import with_setup, pretest, posttest, StringIO, closing +from tqdm.asyncio import tqdm_asyncio, tarange + +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) + + +def with_setup_sync(func): + @with_setup(pretest, posttest) + @wraps(func) + def inner(): + return asyncio.run(func()) + return inner + + +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 + + +@with_setup_sync +async def test_generators(): + """Test asyncio generators""" + with closing(StringIO()) as our_file: + async for row in tqdm(count(), desc="counter", file=our_file): + if row >= 8: + break + assert '9it' in our_file.getvalue() + our_file.seek(0) + our_file.truncate() + + async for row in tqdm(acount(), desc="async_counter", file=our_file): + if row >= 8: + break + assert '9it' in our_file.getvalue() + + +@with_setup_sync +async def test_range(): + """Test asyncio range""" + with closing(StringIO()) as our_file: + async for row 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 row in trange(9, desc="trange", file=our_file): + pass + assert '9/9' in our_file.getvalue() + + +@with_setup_sync +async def test_nested(): + """Test asyncio nested""" + with closing(StringIO()) as our_file: + async for row 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() + + +@with_setup_sync +async def test_coroutines(): + """Test asyncio coroutine.send""" + with closing(StringIO()) as our_file: + with tqdm(count(), file=our_file) as pbar: + async for row in pbar: + if row == 9: + pbar.send(-10) + elif row < 0: + assert row == -9 + break + assert '10it' in our_file.getvalue() + + +@with_setup_sync +async def test_as_completed(): + """Test asyncio as_completed""" + with closing(StringIO()) as our_file: + t = time() + skew = time() - t + for i in as_completed([asyncio.sleep(0.01) for _ in range(100)], + file=our_file): + await i + assert time() - t - 2 * skew < (0.01 * 100) / 2, "Assuming >= 2 cores" + assert '100/100' in our_file.getvalue() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tqdm-4.47.0/tqdm/tests/tests_asyncio.py new/tqdm-4.48.0/tqdm/tests/tests_asyncio.py --- old/tqdm-4.47.0/tqdm/tests/tests_asyncio.py 1970-01-01 01:00:00.000000000 +0100 +++ new/tqdm-4.48.0/tqdm/tests/tests_asyncio.py 2020-07-17 00:03:58.000000000 +0200 @@ -0,0 +1,7 @@ +import sys + +if sys.version_info[:2] > (3, 6): + from py37_asyncio import * # NOQA +else: + from tests_tqdm import SkipTest + raise SkipTest diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tqdm-4.47.0/tqdm/tests/tests_tqdm.py new/tqdm-4.48.0/tqdm/tests/tests_tqdm.py --- old/tqdm-4.47.0/tqdm/tests/tests_tqdm.py 2020-06-29 00:38:16.000000000 +0200 +++ new/tqdm-4.48.0/tqdm/tests/tests_tqdm.py 2020-07-17 00:03:58.000000000 +0200 @@ -676,15 +676,26 @@ def test_min_iters(): """Test miniters""" with closing(StringIO()) as our_file: - for _ in tqdm(_range(3), file=our_file, leave=True, miniters=4): - our_file.write('blank\n') - assert '\nblank\nblank\n' in our_file.getvalue() + for _ in tqdm(_range(3), file=our_file, leave=True, mininterval=0, + miniters=2): + pass + + out = our_file.getvalue() + assert '| 0/3 ' in out + assert '| 1/3 ' not in out + assert '| 2/3 ' in out + assert '| 3/3 ' in out with closing(StringIO()) as our_file: - for _ in tqdm(_range(3), file=our_file, leave=True, miniters=1): - our_file.write('blank\n') - # assume automatic mininterval = 0 means intermediate output - assert '| 3/3 ' in our_file.getvalue() + for _ in tqdm(_range(3), file=our_file, leave=True, mininterval=0, + miniters=1): + pass + + out = our_file.getvalue() + assert '| 0/3 ' in out + assert '| 1/3 ' in out + assert '| 2/3 ' in out + assert '| 3/3 ' in out @with_setup(pretest, posttest) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tqdm-4.47.0/tqdm.egg-info/PKG-INFO new/tqdm-4.48.0/tqdm.egg-info/PKG-INFO --- old/tqdm-4.47.0/tqdm.egg-info/PKG-INFO 2020-06-29 00:38:32.000000000 +0200 +++ new/tqdm-4.48.0/tqdm.egg-info/PKG-INFO 2020-07-17 00:04:14.000000000 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: tqdm -Version: 4.47.0 +Version: 4.48.0 Summary: Fast, Extensible Progress Meter Home-page: https://github.com/tqdm/tqdm Maintainer: tqdm developers @@ -551,7 +551,7 @@ Forces refresh [default: True]. """ - def set_postfix(self, ordered_dict=None, refresh=True, **kwargs): + def set_postfix(self, ordered_dict=None, refresh=True, **tqdm_kwargs): """ Set/modify postfix (additional stats) with automatic formatting based on datatype. @@ -586,29 +586,55 @@ (default: ``abs(self.pos)``). """ - def trange(*args, **kwargs): + @classmethod + @contextmanager + def wrapattr(cls, stream, method, total=None, bytes=True, **tqdm_kwargs): + """ + stream : file-like object. + method : str, "read" or "write". The result of ``read()`` and + the first argument of ``write()`` should have a ``len()``. + + >>> with tqdm.wrapattr(file_obj, "read", total=file_obj.size) as fobj: + ... while True: + ... chunk = fobj.read(chunk_size) + ... if not chunk: + ... break + """ + + @classmethod + def pandas(cls, *targs, **tqdm_kwargs): + """Registers the current `tqdm` class with `pandas`.""" + + def trange(*args, **tqdm_kwargs): """ - A shortcut for tqdm(xrange(*args), **kwargs). - On Python3+ range is used instead of xrange. + A shortcut for `tqdm(xrange(*args), **tqdm_kwargs)`. + On Python3+, `range` is used instead of `xrange`. """ - class tqdm.gui.tqdm(tqdm.tqdm): - """Experimental GUI version""" + class tqdm.notebook.tqdm(tqdm.tqdm): + """Experimental IPython/Jupyter Notebook widget.""" - def tqdm.gui.trange(*args, **kwargs): - """Experimental GUI version of trange""" + def tqdm.notebook.trange(*args, **tqdm_kwargs): + """Experimental IPython/Jupyter Notebook widget version of `trange`.""" - class tqdm.notebook.tqdm(tqdm.tqdm): - """Experimental IPython/Jupyter Notebook widget""" + class tqdm.auto.tqdm(tqdm.tqdm): + """Automatically chooses beween `tqdm.notebook` and `tqdm.tqdm`.""" - def tqdm.notebook.trange(*args, **kwargs): - """Experimental IPython/Jupyter Notebook widget version of trange""" + class tqdm.asyncio.tqdm(tqdm.tqdm): + """Asynchronous version.""" + @classmethod + def as_completed(cls, fs, *, loop=None, timeout=None, total=None, + **tqdm_kwargs): + """Wrapper for `asyncio.as_completed`.""" + + class tqdm.gui.tqdm(tqdm.tqdm): + """Experimental GUI version.""" class tqdm.keras.TqdmCallback(keras.callbacks.Callback): - """`keras` callback for epoch and batch progress""" + """`keras` callback for epoch and batch progress.""" def tqdm.contrib.tenumerate(iterable, start=0, total=None, - tqdm_class=tqdm.auto.tqdm, **kwargs): + tqdm_class=tqdm.auto.tqdm, **tqdm_kwargs): """Equivalent of `numpy.ndenumerate` or builtin `enumerate`.""" def tqdm.contrib.tzip(iter1, *iter2plus, **tqdm_kwargs): @@ -624,13 +650,12 @@ - ``tqdm.contrib.itertools``: Thin wrappers around ``itertools`` - ``tqdm.contrib.concurrent``: Thin wrappers around ``concurrent.futures`` + - ``tqdm.contrib.discord``: Posts to `Discord <https://discord.com/>`__ bots + - ``tqdm.contrib.telegram``: Posts to `Telegram <https://telegram.org/>`__ bots - ``tqdm.contrib.bells``: Automagically enables all optional features * ``auto``, ``pandas``, ``discord``, ``telegram`` - - ``tqdm.contrib.discord``: Posts to `Discord <https://discord.com/>`__ bots - - ``tqdm.contrib.telegram``: Posts to `Telegram <https://telegram.org/>`__ bots - Examples and Advanced Usage --------------------------- diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tqdm-4.47.0/tqdm.egg-info/SOURCES.txt new/tqdm-4.48.0/tqdm.egg-info/SOURCES.txt --- old/tqdm-4.47.0/tqdm.egg-info/SOURCES.txt 2020-06-29 00:38:32.000000000 +0200 +++ new/tqdm-4.48.0/tqdm.egg-info/SOURCES.txt 2020-07-17 00:04:14.000000000 +0200 @@ -11,6 +11,8 @@ setup.py tox.ini examples/7zx.py +examples/async_coroutines.py +examples/coroutine_pipe.py examples/include_no_requirements.py examples/pandas_progress_apply.py examples/parallel_bars.py @@ -29,6 +31,7 @@ tqdm/_tqdm_pandas.py tqdm/_utils.py tqdm/_version.py +tqdm/asyncio.py tqdm/auto.py tqdm/autonotebook.py tqdm/cli.py @@ -52,6 +55,8 @@ tqdm/contrib/itertools.py tqdm/contrib/telegram.py tqdm/contrib/utils_worker.py +tqdm/tests/py37_asyncio.py +tqdm/tests/tests_asyncio.py tqdm/tests/tests_concurrent.py tqdm/tests/tests_contrib.py tqdm/tests/tests_itertools.py