bump version, merge branch 'slack'

This commit is contained in:
Casper da Costa-Luis 2022-04-04 02:25:29 +01:00
commit 4f208e7255
No known key found for this signature in database
GPG Key ID: F5126E5FBD2512AD
7 changed files with 148 additions and 9 deletions

View File

@ -473,11 +473,12 @@ The ``tqdm.contrib`` package also contains experimental modules:
- ``tqdm.contrib.itertools``: Thin wrappers around ``itertools``
- ``tqdm.contrib.concurrent``: Thin wrappers around ``concurrent.futures``
- ``tqdm.contrib.slack``: Posts to `Slack <https://slack.com>`__ bots
- ``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``
* ``auto``, ``pandas``, ``slack``, ``discord``, ``telegram``
Examples and Advanced Usage
---------------------------
@ -965,8 +966,9 @@ Some submodule examples of inheritance:
- `tqdm/notebook.py <https://github.com/tqdm/tqdm/blob/master/tqdm/notebook.py>`__
- `tqdm/gui.py <https://github.com/tqdm/tqdm/blob/master/tqdm/gui.py>`__
- `tqdm/tk.py <https://github.com/tqdm/tqdm/blob/master/tqdm/tk.py>`__
- `tqdm/contrib/telegram.py <https://github.com/tqdm/tqdm/blob/master/tqdm/contrib/telegram.py>`__
- `tqdm/contrib/slack.py <https://github.com/tqdm/tqdm/blob/master/tqdm/contrib/slack.py>`__
- `tqdm/contrib/discord.py <https://github.com/tqdm/tqdm/blob/master/tqdm/contrib/discord.py>`__
- `tqdm/contrib/telegram.py <https://github.com/tqdm/tqdm/blob/master/tqdm/contrib/telegram.py>`__
Dynamic Monitor/Meter
~~~~~~~~~~~~~~~~~~~~~

View File

@ -692,11 +692,12 @@ The ``tqdm.contrib`` package also contains experimental modules:
- ``tqdm.contrib.itertools``: Thin wrappers around ``itertools``
- ``tqdm.contrib.concurrent``: Thin wrappers around ``concurrent.futures``
- ``tqdm.contrib.slack``: Posts to `Slack <https://slack.com>`__ bots
- ``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``
* ``auto``, ``pandas``, ``slack``, ``discord``, ``telegram``
Examples and Advanced Usage
---------------------------
@ -1184,8 +1185,9 @@ Some submodule examples of inheritance:
- `tqdm/notebook.py <https://github.com/tqdm/tqdm/blob/master/tqdm/notebook.py>`__
- `tqdm/gui.py <https://github.com/tqdm/tqdm/blob/master/tqdm/gui.py>`__
- `tqdm/tk.py <https://github.com/tqdm/tqdm/blob/master/tqdm/tk.py>`__
- `tqdm/contrib/telegram.py <https://github.com/tqdm/tqdm/blob/master/tqdm/contrib/telegram.py>`__
- `tqdm/contrib/slack.py <https://github.com/tqdm/tqdm/blob/master/tqdm/contrib/slack.py>`__
- `tqdm/contrib/discord.py <https://github.com/tqdm/tqdm/blob/master/tqdm/contrib/discord.py>`__
- `tqdm/contrib/telegram.py <https://github.com/tqdm/tqdm/blob/master/tqdm/contrib/telegram.py>`__
Dynamic Monitor/Meter
~~~~~~~~~~~~~~~~~~~~~

View File

@ -29,6 +29,7 @@ dependencies:
- numpy # pandas, keras, contrib.tenumerate
- pandas
- tensorflow # keras
- slack-sdk # contrib.slack
- requests # contrib.telegram
- rich # rich
- argopt # `cd wiki && pymake`
@ -36,10 +37,10 @@ dependencies:
- wheel # `setup.py bdist_wheel`
# `cd docs && pymake`
- mkdocs-material
- pydoc-markdown >=4.6.0
- pydoc-markdown
- pygments
- pymdown-extensions
- pip:
- py-make >=0.1.0 # `setup.py 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`

View File

@ -84,6 +84,7 @@ 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]
@ -137,6 +138,7 @@ 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

View File

@ -12,7 +12,9 @@ __all__ = ['tqdm', 'trange']
import warnings
from os import getenv
if getenv("TQDM_TELEGRAM_TOKEN") and getenv("TQDM_TELEGRAM_CHAT_ID"):
if getenv("TQDM_SLACK_TOKEN") and getenv("TQDM_SLACK_CHANNEL"):
from .slack import tqdm, trange
elif getenv("TQDM_TELEGRAM_TOKEN") and getenv("TQDM_TELEGRAM_CHAT_ID"):
from .telegram import tqdm, trange
elif getenv("TQDM_DISCORD_TOKEN") and getenv("TQDM_DISCORD_CHANNEL_ID"):
from .discord import tqdm, trange

View File

@ -3,7 +3,7 @@ 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}'):
>>> for i in trange(10, token='{token}', channel_id='{channel_id}'):
... ...
![screenshot](https://img.tqdm.ml/screenshot-discord.png)
@ -39,6 +39,7 @@ class DiscordIO(MonoWorker):
self.message = client.api.channels_messages_create(channel_id, self.text)
except Exception as e:
tqdm_auto.write(str(e))
self.message = None
def write(self, s):
"""Replaces internal `message`'s text with `s`."""
@ -47,9 +48,12 @@ class DiscordIO(MonoWorker):
s = s.replace('\r', '').strip()
if s == self.text:
return # skip duplicate message
message = self.message
if message is None:
return
self.text = s
try:
future = self.submit(self.message.edit, '`' + s + '`')
future = self.submit(message.edit, '`' + s + '`')
except Exception as e:
tqdm_auto.write(str(e))
else:

126
tqdm/contrib/slack.py Normal file
View File

@ -0,0 +1,126 @@
"""
Sends updates to a Slack app.
Usage:
>>> from tqdm.contrib.slack import tqdm, trange
>>> for i in trange(10, token='{token}', channel='{channel}'):
... ...
![screenshot](https://img.tqdm.ml/screenshot-slack.png)
"""
from __future__ import absolute_import
import logging
from os import getenv
try:
from slack_sdk import WebClient
except ImportError:
raise ImportError("Please `pip install slack-sdk`")
from ..auto import tqdm as tqdm_auto
from ..utils import _range
from .utils_worker import MonoWorker
__author__ = {"github.com/": ["0x2b3bfa0", "casperdcl"]}
__all__ = ['SlackIO', 'tqdm_slack', 'tsrange', 'tqdm', 'trange']
class SlackIO(MonoWorker):
"""Non-blocking file-like IO using a Slack app."""
def __init__(self, token, channel):
"""Creates a new message in the given `channel`."""
super(SlackIO, self).__init__()
self.client = WebClient(token=token)
self.text = self.__class__.__name__
try:
self.message = self.client.chat_postMessage(channel=channel, text=self.text)
except Exception as e:
tqdm_auto.write(str(e))
self.message = None
def write(self, s):
"""Replaces internal `message`'s text with `s`."""
if not s:
s = "..."
s = s.replace('\r', '').strip()
if s == self.text:
return # skip duplicate message
message = self.message
if message is None:
return
self.text = s
try:
future = self.submit(self.client.chat_update, channel=message['channel'],
ts=message['ts'], text='`' + s + '`')
except Exception as e:
tqdm_auto.write(str(e))
else:
return future
class tqdm_slack(tqdm_auto):
"""
Standard `tqdm.auto.tqdm` but also sends updates to a Slack app.
May take a few seconds to create (`__init__`).
- create a Slack app with the `chat:write` scope & invite it to a
channel: <https://api.slack.com/authentication/basics>
- copy the bot `{token}` & `{channel}` and paste below
>>> from tqdm.contrib.slack import tqdm, trange
>>> for i in tqdm(iterable, token='{token}', channel='{channel}'):
... ...
"""
def __init__(self, *args, **kwargs):
"""
Parameters
----------
token : str, required. Slack token
[default: ${TQDM_SLACK_TOKEN}].
channel : int, required. Slack channel
[default: ${TQDM_SLACK_CHANNEL}].
mininterval : float, optional.
Minimum of [default: 1.5] to avoid rate limit.
See `tqdm.auto.tqdm.__init__` for other parameters.
"""
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")))
kwargs['mininterval'] = max(1.5, kwargs.get('mininterval', 1.5))
super(tqdm_slack, self).__init__(*args, **kwargs)
def display(self, **kwargs):
super(tqdm_slack, self).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:
fmt['bar_format'] = '{l_bar}`{bar:10}`{r_bar}'
if fmt['ascii'] is False:
fmt['ascii'] = [":black_square:", ":small_blue_diamond:", ":large_blue_diamond:",
":large_blue_square:"]
fmt['ncols'] = 336
self.sio.write(self.format_meter(**fmt))
def clear(self, *args, **kwargs):
super(tqdm_slack, self).clear(*args, **kwargs)
if not self.disable:
self.sio.write("")
def tsrange(*args, **kwargs):
"""
A shortcut for `tqdm.contrib.slack.tqdm(xrange(*args), **kwargs)`.
On Python3+, `range` is used instead of `xrange`.
"""
return tqdm_slack(_range(*args), **kwargs)
# Aliases
tqdm = tqdm_slack
trange = tsrange