1
0
Fork 0

Merging upstream version 4.67.0.

Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
Daniel Baumann 2025-02-05 19:22:32 +01:00
parent 4ecd0d1838
commit 93eea9a9cb
Signed by: daniel
GPG key ID: FBB4F0E80A80222F
9 changed files with 82 additions and 43 deletions

View file

@ -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.6.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.21
- repo: https://github.com/PyCQA/flake8 - repo: https://github.com/PyCQA/flake8
rev: 7.1.0 rev: 7.1.1
hooks: hooks:
- id: flake8 - id: flake8
args: [-j8] args: [-j8]

View file

@ -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://tqdm.github.io/img/favicon.png&f=https://tqdm.github.io/img/logo.gif)](https://caspersci.uk.to/cgi-bin/hits.cgi?q=tqdm&a=plot&r=https://github.com/tqdm/tqdm&l=https://tqdm.github.io/img/favicon.png&f=https://tqdm.github.io/img/logo.gif&style=social)|(Since 19 May 2016)\n", "[![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",
"-|-" "-|-"
] ]
}, },

View file

@ -61,11 +61,11 @@ testsetup:
@make help @make help
testnb: testnb:
pytest tests_notebook.ipynb --cov=tqdm.notebook --cov-report=term -W=ignore --nbval --current-env --sanitize-with=.meta/nbval.ini 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= -W=ignore --nbval --current-env --sanitize-with=.meta/nbval.ini 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:

View file

@ -1505,5 +1505,5 @@ Citation information: |DOI|
.. |Screenshot-Jupyter1| image:: https://tqdm.github.io/img/jupyter-1.gif .. |Screenshot-Jupyter1| image:: https://tqdm.github.io/img/jupyter-1.gif
.. |Screenshot-Jupyter2| image:: https://tqdm.github.io/img/jupyter-2.gif .. |Screenshot-Jupyter2| image:: https://tqdm.github.io/img/jupyter-2.gif
.. |Screenshot-Jupyter3| image:: https://tqdm.github.io/img/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://tqdm.github.io/img/favicon.png&f=https://tqdm.github.io/img/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://tqdm.github.io/img/favicon.png&f=https://tqdm.github.io/img/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

View file

@ -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,

View file

@ -24,6 +24,7 @@ readme = "README.rst"
requires-python = ">=3.7" requires-python = ">=3.7"
keywords = ["progressbar", "progressmeter", "progress", "bar", "meter", "rate", "eta", "console", "terminal", "time"] keywords = ["progressbar", "progressmeter", "progress", "bar", "meter", "rate", "eta", "console", "terminal", "time"]
license = {text = "MPL-2.0 AND MIT"} license = {text = "MPL-2.0 AND MIT"}
# Trove classifiers (https://pypi.org/pypi?%3Aaction=list_classifiers)
classifiers = [ classifiers = [
"Development Status :: 5 - Production/Stable", "Development Status :: 5 - Production/Stable",
"Environment :: Console", "Environment :: Console",
@ -84,6 +85,7 @@ dependencies = ['colorama; platform_system == "Windows"']
[project.optional-dependencies] [project.optional-dependencies]
dev = ["pytest>=6", "pytest-cov", "pytest-timeout", "pytest-xdist"] dev = ["pytest>=6", "pytest-cov", "pytest-timeout", "pytest-xdist"]
discord = ["requests"]
slack = ["slack-sdk"] slack = ["slack-sdk"]
telegram = ["requests"] telegram = ["requests"]
notebook = ["ipywidgets>=6"] notebook = ["ipywidgets>=6"]
@ -120,6 +122,7 @@ markers = ["asyncio", "slow"]
python_files = ["tests_*.py", "tests_*.ipynb"] python_files = ["tests_*.py", "tests_*.ipynb"]
testpaths = ["tests"] testpaths = ["tests"]
addopts = "-v --tb=short -rxs -W=error --durations=0 --durations-min=0.1 --asyncio-mode=strict" 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] [tool.coverage.run]
branch = true branch = true

View file

@ -49,7 +49,7 @@ deps=
tf: tensorflow!=2.5.0 tf: tensorflow!=2.5.0
keras: keras keras: keras
commands= commands=
pytest --cov=tqdm --cov-report= -W=ignore tests_notebook.ipynb --nbval --current-env --sanitize-with=.meta/nbval.ini pytest --cov=tqdm --cov-report= -W=ignore tests_notebook.ipynb --nbval --nbval-current-env --nbval-sanitize-with=.meta/nbval.ini
pytest --cov=tqdm --cov-report=xml --cov-report=term --cov-append -k "not perf" pytest --cov=tqdm --cov-report=xml --cov-report=term --cov-append -k "not perf"
{[core]commands} {[core]commands}
allowlist_externals=codacy allowlist_externals=codacy

View file

@ -258,22 +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:
try: # py<3.9
import importlib_resources as resources
except ImportError:
from importlib import resources from importlib import resources
from os import path from pathlib import Path
from shutil import copyfile
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

View file

@ -8,49 +8,83 @@ Usage:
![screenshot](https://tqdm.github.io/img/screenshot-discord.png) ![screenshot](https://tqdm.github.io/img/screenshot-discord.png)
""" """
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 ..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().__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:
@ -75,22 +109,18 @@ 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().__init__(*args, **kwargs)
def display(self, **kwargs): def display(self, **kwargs):
@ -108,6 +138,13 @@ class tqdm_discord(tqdm_auto):
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)`.""" """Shortcut for `tqdm.contrib.discord.tqdm(range(*args), **kwargs)`."""