Voice et bot modif

This commit is contained in:
pi 2026-06-16 17:09:34 +00:00
parent 189d56026b
commit 7333a22bcd
10774 changed files with 634644 additions and 933308 deletions

View file

@ -76,8 +76,7 @@ def tzip(iter1, *iter2plus, **tqdm_kwargs):
"""
kwargs = tqdm_kwargs.copy()
tqdm_class = kwargs.pop("tqdm_class", tqdm_auto)
for i in zip(tqdm_class(iter1, **kwargs), *iter2plus):
yield i
yield from zip(tqdm_class(iter1, **kwargs), *iter2plus)
def tmap(function, *sequences, **tqdm_kwargs):

View file

@ -3,6 +3,8 @@ Even more features than `tqdm.auto` (all the bells & whistles):
- `tqdm.auto`
- `tqdm.tqdm.pandas`
- `tqdm.contrib.slack`
+ uses `${TQDM_SLACK_TOKEN}` and `${TQDM_SLACK_CHANNEL}`
- `tqdm.contrib.telegram`
+ uses `${TQDM_TELEGRAM_TOKEN}` and `${TQDM_TELEGRAM_CHAT_ID}`
- `tqdm.contrib.discord`

View file

@ -8,7 +8,6 @@ Usage:
![screenshot](https://tqdm.github.io/img/screenshot-discord.png)
"""
from os import getenv
from warnings import warn
from requests import Session
@ -16,6 +15,7 @@ from requests.utils import default_user_agent
from ..auto import tqdm as tqdm_auto
from ..std import TqdmWarning
from ..utils import envwrap
from ..version import __version__
from .utils_worker import MonoWorker
@ -25,7 +25,7 @@ __all__ = ['DiscordIO', 'tqdm_discord', 'tdrange', 'tqdm', 'trange']
class DiscordIO(MonoWorker):
"""Non-blocking file-like IO using a Discord Bot."""
API = "https://discord.com/api/v10"
API = 'https://discord.com/api/v10'
UA = f"tqdm (https://tqdm.github.io, {__version__}) {default_user_agent()}"
def __init__(self, token, channel_id):
@ -40,21 +40,23 @@ class DiscordIO(MonoWorker):
@property
def message_id(self):
if hasattr(self, '_message_id'):
return self._message_id
return self._message_id # pylint: disable=access-member-before-definition
try:
res = self.session.post(
req = 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()
json={'content': f"`{self.text}`"})
res = req.json()
req.raise_for_status()
except Exception as e:
tqdm_auto.write(str(e))
else:
if res.get('error_code') == 429:
if req.status_code == 429:
warn("Creation rate limit: try increasing `mininterval`.",
TqdmWarning, stacklevel=2)
else:
self._message_id = res['id']
return self._message_id
tqdm_auto.write(str(e))
else:
self._message_id = res['id']
return self._message_id
def write(self, s):
"""Replaces internal `message_id`'s text with `s`."""
@ -91,7 +93,7 @@ class DiscordIO(MonoWorker):
return future
class tqdm_discord(tqdm_auto):
class tqdm_discord(tqdm_auto): # pylint: disable=inconsistent-mro
"""
Standard `tqdm.auto.tqdm` but also sends updates to a Discord Bot.
May take a few seconds to create (`__init__`).
@ -105,7 +107,8 @@ class tqdm_discord(tqdm_auto):
>>> for i in tqdm(iterable, token='{token}', channel_id='{channel_id}'):
... ...
"""
def __init__(self, *args, **kwargs):
@envwrap("tqdm", "discord", is_method=True)
def __init__(self, *args, token=None, channel_id=None, **kwargs):
"""
Parameters
----------
@ -118,19 +121,15 @@ class tqdm_discord(tqdm_auto):
"""
if not kwargs.get('disable'):
kwargs = kwargs.copy()
self.dio = DiscordIO(
kwargs.pop('token', getenv('TQDM_DISCORD_TOKEN')),
kwargs.pop('channel_id', getenv('TQDM_DISCORD_CHANNEL_ID')))
self.dio = DiscordIO(token, channel_id)
super().__init__(*args, **kwargs)
def display(self, **kwargs):
def display(self, **kwargs): # pylint: disable=arguments-differ
super().display(**kwargs)
fmt = self.format_dict
if fmt.get('bar_format', None):
fmt['bar_format'] = fmt['bar_format'].replace(
'<bar/>', '{bar:10u}').replace('{bar}', '{bar:10u}')
else:
fmt['bar_format'] = '{l_bar}{bar:10u}{r_bar}'
self.dio.write(self.format_meter(**fmt))
def clear(self, *args, **kwargs):

View file

@ -6,30 +6,96 @@ import itertools
from ..auto import tqdm as tqdm_auto
__author__ = {"github.com/": ["casperdcl"]}
__all__ = ['product']
__all__ = [
'chain', 'product', 'permutations', 'combinations', 'combinations_with_replacement', 'batched']
def product(*iterables, **tqdm_kwargs):
"""
Equivalent of `itertools.product`.
def chain(*iterables, total=None, tqdm_class=tqdm_auto, **kwargs):
"""Equivalent of `itertools.chain`."""
if total is None:
try:
total = sum(map(len, iterables))
except (TypeError, AttributeError):
pass
return tqdm_class(itertools.chain(*iterables), total=total, **kwargs)
Parameters
----------
tqdm_class : [default: tqdm.auto.tqdm].
"""
kwargs = tqdm_kwargs.copy()
tqdm_class = kwargs.pop("tqdm_class", tqdm_auto)
try:
lens = list(map(len, iterables))
except TypeError:
total = None
else:
total = 1
for i in lens:
total *= i
kwargs.setdefault("total", total)
with tqdm_class(**kwargs) as t:
it = itertools.product(*iterables)
for i in it:
yield i
t.update()
def product(*iterables, repeat=1, total=None, tqdm_class=tqdm_auto, **kwargs):
"""Equivalent of `itertools.product`."""
if total is None:
try:
lens = list(map(len, iterables))
except (TypeError, AttributeError):
pass
else: # py>=3.8: math.prod(lens) ** repeat
total = 1
for i in lens:
total *= i
total **= repeat
for i in tqdm_class(itertools.product(*iterables, repeat=repeat), total=total, **kwargs):
yield i
def permutations(iterable, r=None, total=None, tqdm_class=tqdm_auto, **kwargs):
"""Equivalent of `itertools.permutations`."""
if total is None:
try:
n = len(iterable)
except (TypeError, AttributeError):
pass
else:
r = n if r is None else r
if r > n:
total = 0
else: # py>=3.8: math.perm(n, r)
total = 1
for i in range(n, n-r, -1):
total *= i
return tqdm_class(itertools.permutations(iterable, r), total=total, **kwargs)
def combinations(iterable, r, total=None, tqdm_class=tqdm_auto, **kwargs):
"""Equivalent of `itertools.combinations`."""
if total is None:
try:
n = len(iterable)
except (TypeError, AttributeError):
pass
else:
if r > n:
total = 0
else: # py>=3.8: math.comb(n, r)
total = 1
for i in range(n, n-r, -1):
total *= i
for i in range(1, r+1):
total //= i
return tqdm_class(itertools.combinations(iterable, r), total=total, **kwargs)
def combinations_with_replacement(iterable, r, total=None, tqdm_class=tqdm_auto, **kwargs):
"""Equivalent of `itertools.combinations_with_replacement`."""
if total is None:
try:
n = len(iterable)
except (TypeError, AttributeError):
pass
else:
total = 1
for i in range(n+r-1, n-1, -1):
total *= i
for i in range(1, r+1):
total //= i
return tqdm_class(itertools.combinations_with_replacement(iterable, r), total=total, **kwargs)
def batched(iterable, n, total=None, tqdm_class=tqdm_auto, **kwargs):
"""Equivalent of `itertools.batched`."""
if total is None:
try:
total = len(iterable)
except (TypeError, AttributeError):
pass
return tqdm_class(itertools.batched(iterable, n), unit_scale=n,
total=(total+n-1) // n if total is not None else None,
**kwargs)

View file

@ -9,7 +9,6 @@ Usage:
![screenshot](https://tqdm.github.io/img/screenshot-slack.png)
"""
import logging
from os import getenv
try:
from slack_sdk import WebClient
@ -17,6 +16,7 @@ except ImportError:
raise ImportError("Please `pip install slack-sdk`")
from ..auto import tqdm as tqdm_auto
from ..utils import envwrap
from .utils_worker import MonoWorker
__author__ = {"github.com/": ["0x2b3bfa0", "casperdcl"]}
@ -56,7 +56,7 @@ class SlackIO(MonoWorker):
return future
class tqdm_slack(tqdm_auto):
class tqdm_slack(tqdm_auto): # pylint: disable=inconsistent-mro
"""
Standard `tqdm.auto.tqdm` but also sends updates to a Slack app.
May take a few seconds to create (`__init__`).
@ -68,7 +68,8 @@ class tqdm_slack(tqdm_auto):
>>> for i in tqdm(iterable, token='{token}', channel='{channel}'):
... ...
"""
def __init__(self, *args, **kwargs):
@envwrap("tqdm", "slack", is_method=True)
def __init__(self, *args, token=None, channel=None, **kwargs):
"""
Parameters
----------
@ -84,19 +85,17 @@ class tqdm_slack(tqdm_auto):
if not kwargs.get('disable'):
kwargs = kwargs.copy()
logging.getLogger("HTTPClient").setLevel(logging.WARNING)
self.sio = SlackIO(
kwargs.pop('token', getenv("TQDM_SLACK_TOKEN")),
kwargs.pop('channel', getenv("TQDM_SLACK_CHANNEL")))
self.sio = SlackIO(token, channel)
kwargs['mininterval'] = max(1.5, kwargs.get('mininterval', 1.5))
super().__init__(*args, **kwargs)
def display(self, **kwargs):
def display(self, **kwargs): # pylint: disable=arguments-differ
super().display(**kwargs)
fmt = self.format_dict
if fmt.get('bar_format', None):
fmt['bar_format'] = fmt['bar_format'].replace(
'<bar/>', '`{bar:10}`').replace('{bar}', '`{bar:10u}`')
else:
elif self.total:
fmt['bar_format'] = '{l_bar}`{bar:10}`{r_bar}'
if fmt['ascii'] is False:
fmt['ascii'] = [":black_square:", ":small_blue_diamond:", ":large_blue_diamond:",

View file

@ -8,13 +8,13 @@ Usage:
![screenshot](https://tqdm.github.io/img/screenshot-telegram.gif)
"""
from os import getenv
from warnings import warn
from requests import Session
from ..auto import tqdm as tqdm_auto
from ..std import TqdmWarning
from ..utils import envwrap
from .utils_worker import MonoWorker
__author__ = {"github.com/": ["casperdcl"]}
@ -37,21 +37,23 @@ class TelegramIO(MonoWorker):
@property
def message_id(self):
if hasattr(self, '_message_id'):
return self._message_id
return self._message_id # pylint: disable=access-member-before-definition
try:
res = self.session.post(
self.API + '%s/sendMessage' % self.token,
data={'text': '`' + self.text + '`', 'chat_id': self.chat_id,
'parse_mode': 'MarkdownV2'}).json()
req = self.session.post(
f'{self.API}{self.token}/sendMessage',
data={'text': f"`{self.text}`", 'chat_id': self.chat_id,
'parse_mode': 'MarkdownV2'})
res = req.json()
req.raise_for_status()
except Exception as e:
tqdm_auto.write(str(e))
else:
if res.get('error_code') == 429:
if req.status_code == 429:
warn("Creation rate limit: try increasing `mininterval`.",
TqdmWarning, stacklevel=2)
else:
self._message_id = res['result']['message_id']
return self._message_id
tqdm_auto.write(str(e))
else:
self._message_id = res['result']['message_id']
return self._message_id
def write(self, s):
"""Replaces internal `message_id`'s text with `s`."""
@ -66,8 +68,8 @@ class TelegramIO(MonoWorker):
self.text = s
try:
future = self.submit(
self.session.post, self.API + '%s/editMessageText' % self.token,
data={'text': '`' + s + '`', 'chat_id': self.chat_id,
self.session.post, f'{self.API}{self.token}/editMessageText',
data={'text': f"`{s}`", 'chat_id': self.chat_id,
'message_id': message_id, 'parse_mode': 'MarkdownV2'})
except Exception as e:
tqdm_auto.write(str(e))
@ -78,7 +80,7 @@ class TelegramIO(MonoWorker):
"""Deletes internal `message_id`."""
try:
future = self.submit(
self.session.post, self.API + '%s/deleteMessage' % self.token,
self.session.post, '{self.API}{self.token}/deleteMessage',
data={'chat_id': self.chat_id, 'message_id': self.message_id})
except Exception as e:
tqdm_auto.write(str(e))
@ -86,7 +88,7 @@ class TelegramIO(MonoWorker):
return future
class tqdm_telegram(tqdm_auto):
class tqdm_telegram(tqdm_auto): # pylint: disable=inconsistent-mro
"""
Standard `tqdm.auto.tqdm` but also sends updates to a Telegram Bot.
May take a few seconds to create (`__init__`).
@ -102,7 +104,8 @@ class tqdm_telegram(tqdm_auto):
>>> for i in tqdm(iterable, token='{token}', chat_id='{chat_id}'):
... ...
"""
def __init__(self, *args, **kwargs):
@envwrap("tqdm", "telegram", is_method=True)
def __init__(self, *args, token=None, chat_id=None, **kwargs):
"""
Parameters
----------
@ -115,19 +118,15 @@ class tqdm_telegram(tqdm_auto):
"""
if not kwargs.get('disable'):
kwargs = kwargs.copy()
self.tgio = TelegramIO(
kwargs.pop('token', getenv('TQDM_TELEGRAM_TOKEN')),
kwargs.pop('chat_id', getenv('TQDM_TELEGRAM_CHAT_ID')))
self.tgio = TelegramIO(token, chat_id)
super().__init__(*args, **kwargs)
def display(self, **kwargs):
def display(self, **kwargs): # pylint: disable=arguments-differ
super().display(**kwargs)
fmt = self.format_dict
if fmt.get('bar_format', None):
fmt['bar_format'] = fmt['bar_format'].replace(
'<bar/>', '{bar:10u}').replace('{bar}', '{bar:10u}')
else:
fmt['bar_format'] = '{l_bar}{bar:10u}{r_bar}'
self.tgio.write(self.format_meter(**fmt))
def clear(self, *args, **kwargs):

View file

@ -10,7 +10,7 @@ __author__ = {"github.com/": ["casperdcl"]}
__all__ = ['MonoWorker']
class MonoWorker(object):
class MonoWorker:
"""
Supports one running task and one waiting task.
The waiting task is the most recent submitted (others are discarded).