├── ods_dump_telegram_channel ├── __init__.py ├── ping_telegram_bot.py ├── utils.py └── dump_to_telegram_bot.py ├── config.yml ├── .pre-commit-config.yaml ├── pyproject.toml ├── LICENSE ├── .gitignore ├── README.md └── poetry.lock /ods_dump_telegram_channel/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /config.yml: -------------------------------------------------------------------------------- 1 | data: 2 | path_to_ods_slack_dump: "/Users/kashnitskiyy/Documents/data/opendatascience_Slack_export_Mar_12_2015_Jan_17_2022/" 3 | ods_channel_name: "_jobs" 4 | 5 | telegram: 6 | path_to_telegram_bot_secret_file: "/Users/kashnitskiyy/scrt/ods_jobs_dump_bot" 7 | telegram_chat_id: -1001788210074 8 | -------------------------------------------------------------------------------- /ods_dump_telegram_channel/ping_telegram_bot.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | 3 | import telegram 4 | 5 | with open("/Users/kashnitskiyy/scrt/ods_jobs_dump_bot") as f: 6 | TOKEN = f.read().strip() 7 | 8 | 9 | async def main(): 10 | bot = telegram.Bot(TOKEN) 11 | async with bot: 12 | print(await bot.get_me()) 13 | 14 | 15 | # async def main(): 16 | # bot = telegram.Bot(TOKEN) 17 | # async with bot: 18 | # print((await bot.get_updates())[0]) 19 | 20 | # async def main(): 21 | # bot = telegram.Bot(TOKEN) 22 | # async with bot: 23 | # await bot.send_message(text='Hi John!', chat_id=297791890) 24 | 25 | if __name__ == "__main__": 26 | asyncio.run(main()) 27 | -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | repos: 2 | - repo: https://github.com/pre-commit/pre-commit-hooks 3 | rev: v4.0.1 4 | hooks: 5 | - id: check-added-large-files 6 | - id: check-docstring-first 7 | - id: check-yaml 8 | - id: end-of-file-fixer 9 | - id: trailing-whitespace 10 | - repo: https://github.com/psf/black 11 | rev: 22.3.0 12 | hooks: 13 | - id: black 14 | args: ["--line-length=119"] 15 | - repo: https://gitlab.com/pycqa/flake8 16 | rev: 3.9.2 17 | hooks: 18 | - id: flake8 19 | args: ["--ignore=E501,W503", "--max-line-length=119"] 20 | - repo: https://github.com/pycqa/isort 21 | rev: 5.10.1 22 | hooks: 23 | - id: isort 24 | name: isort (python) 25 | args: ["--profile", "black"] 26 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.poetry] 2 | name = "ods-dump-telegram-channel" 3 | version = "0.1.0" 4 | description = "Send Slack ODS dump to a Telegram bot" 5 | authors = ["Yury Kashnitsky "] 6 | license = "MIT" 7 | 8 | [tool.poetry.dependencies] 9 | python = ">=3.9,<4" 10 | 11 | async-timeout = "^4.0.2" 12 | python-telegram-bot = "^20.0a4" 13 | PyYAML = "^6.0" 14 | requests = "^2.28.1" 15 | tqdm = "^4.64.1" 16 | 17 | [tool.poetry.dev-dependencies] 18 | black = "^22.3.0" 19 | flake8 = "^3.7.9" 20 | pylint = "^2.12.2" 21 | pytest = "^5.2" 22 | pytest-cov = "^2.8.1" 23 | pytest-html = "^2.1.0" 24 | 25 | [tool.black] 26 | line-length = 119 27 | target-version = ['py38', 'py39'] 28 | include = '\.pyi?$' 29 | exclude = ''' 30 | /( 31 | | \.git 32 | | \.tox 33 | | \*venv 34 | )/ 35 | ''' 36 | 37 | [build-system] 38 | requires = ["poetry-core>=1.0.0"] 39 | build-backend = "poetry.core.masonry.api" 40 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Yury Kashnitsky 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /ods_dump_telegram_channel/utils.py: -------------------------------------------------------------------------------- 1 | import re 2 | from pathlib import Path 3 | from typing import Any, Dict 4 | 5 | import yaml 6 | 7 | 8 | def get_project_root() -> Path: 9 | """ 10 | Return a Path object pointing to the project root directory. 11 | :return: Path 12 | """ 13 | return Path(__file__).parent.parent 14 | 15 | 16 | def load_config_params() -> Dict[str, Any]: 17 | """ 18 | Loads global project configuration params defined in the `config.yaml` file. 19 | :return: a nested dictionary corresponding to the `config.yaml` file. 20 | """ 21 | project_root: Path = get_project_root() 22 | with open(project_root / "config.yml") as f: 23 | params: Dict[str, Any] = yaml.load(f, Loader=yaml.FullLoader) 24 | return params 25 | 26 | 27 | def process_to_html(message: str, user_dict: Dict[str, str]): 28 | """ 29 | 30 | :param message: message text 31 | :param user_dict: a dictionary mapping Slack User IDs to their nicknames 32 | :return: HTML-formatted message 33 | """ 34 | 35 | # replace user mentions 36 | message = re.sub( 37 | r"\<@.+\>", 38 | lambda x: user_dict.get(x.group(0).strip("<>@"), "USER") if x.group(0) else x.group(), 39 | message, 40 | ) 41 | 42 | # format URLs: -> url 43 | message_with_links = re.sub( 44 | r"^[^\S\n]*\< |\<([^*\r\n]*)\>", 45 | lambda x: f'{x.group(1)}' if x.group(1) else x.group(), 46 | message, 47 | flags=re.M, 48 | ) 49 | 50 | # format bolded text to HTML: *blabla* -> 51 | bolded_message_with_links = re.sub( 52 | r"^[^\S\n]*\* |\*([^*\r\n]*)\*", 53 | lambda x: f"{x.group(1)}" if x.group(1) else x.group(), 54 | message_with_links, 55 | flags=re.M, 56 | ) 57 | 58 | return bolded_message_with_links 59 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | pip-wheel-metadata/ 24 | share/python-wheels/ 25 | *.egg-info/ 26 | .installed.cfg 27 | *.egg 28 | MANIFEST 29 | 30 | # PyInstaller 31 | # Usually these files are written by a python script from a template 32 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 33 | *.manifest 34 | *.spec 35 | 36 | # Installer logs 37 | pip-log.txt 38 | pip-delete-this-directory.txt 39 | 40 | # Unit test / coverage reports 41 | htmlcov/ 42 | .tox/ 43 | .nox/ 44 | .coverage 45 | .coverage.* 46 | .cache 47 | nosetests.xml 48 | coverage.xml 49 | *.cover 50 | *.py,cover 51 | .hypothesis/ 52 | .pytest_cache/ 53 | 54 | # Translations 55 | *.mo 56 | *.pot 57 | 58 | # Django stuff: 59 | *.log 60 | local_settings.py 61 | db.sqlite3 62 | db.sqlite3-journal 63 | 64 | # Flask stuff: 65 | instance/ 66 | .webassets-cache 67 | 68 | # Scrapy stuff: 69 | .scrapy 70 | 71 | # Sphinx documentation 72 | docs/_build/ 73 | 74 | # PyBuilder 75 | target/ 76 | 77 | # Jupyter Notebook 78 | .ipynb_checkpoints 79 | 80 | # IPython 81 | profile_default/ 82 | ipython_config.py 83 | 84 | # pyenv 85 | .python-version 86 | 87 | # pipenv 88 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 89 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 90 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 91 | # install all needed dependencies. 92 | #Pipfile.lock 93 | 94 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 95 | __pypackages__/ 96 | 97 | # Celery stuff 98 | celerybeat-schedule 99 | celerybeat.pid 100 | 101 | # SageMath parsed files 102 | *.sage.py 103 | 104 | # Environments 105 | .env 106 | .venv 107 | env/ 108 | venv/ 109 | ENV/ 110 | env.bak/ 111 | venv.bak/ 112 | 113 | # Spyder project settings 114 | .spyderproject 115 | .spyproject 116 | 117 | # Rope project settings 118 | .ropeproject 119 | 120 | # mkdocs documentation 121 | /site 122 | 123 | # mypy 124 | .mypy_cache/ 125 | .dmypy.json 126 | dmypy.json 127 | 128 | # Pyre type checker 129 | .pyre/ 130 | 131 | # custom 132 | .DS_Store 133 | .idea/ 134 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Sending ODS Slack dump to a Telegram channel 2 | 3 | OpenDataScience [ods.ai](https://ods.ai/) is an international Data Science community, mostly Russian-speaking. As a result of Feb 2022 disaster ODS Slack got under sanctions and can no longer register new users. Also, messages and files in [ODS Slack](https://opendatascience.slack.com/) older than 90 days are hidden (there's ongoing activity with migrating the community to [Matrix](https://chat.ods.ai/#/)). Luckily, we have some dumps. This repo helps to send messages from ODS Slack dump to a Telegram channel. 4 | 5 | This code is used to populate the [ODS jobs dump](https://t.me/ods_jobs_dump_bot) Telegram bot, and it can be used for any other dumped Slack channel (**#theory\_and\_practice, #article_essence**, etc.) 6 | 7 | ## Setting up the environment 8 | 9 | - Install Poetry with Python >= 3.9; 10 | - Run `poetry install` to set up a virtual environment for the project and install all dependencies. 11 | 12 | ## Specifying the Telegram channel ID 13 | 14 | - Specify your channel ID in `config.yml` under `telegram` -> `telegram_chat_id`. You can get your ID via [@username_to_id_bot](https://t.me/username_to_id_bot). 15 | 16 | ## Downloading the dump 17 | 18 | The ODS Slack dump that I got spans 2015-04-14 to 2022-01-17. [Download link](https://disk.yandex.ru/d/Iz6qREJTrYItqw) (~500 Mb zipped, 3.3 Gb unzipped) 19 | 20 | - Downlod a Slack dump, unpack it and specify the path in `config.yml` under `data` -> `path_to_ods_slack_dump`; 21 | - Put the channel name of interest (e.g. "_jobs") in `config.yml` under `data` -> `ods_channel_name`. 22 | 23 | ## Sending messages from the dump to the bot 24 | 25 | - Customize the code of the `ods_dump_telegram_channel.dump_to_telegram_bot.get_posts` function, e.g. you might want to add replies to messages, not only original posts. You might also show the number of reactions, etc; 26 | - Run `poetry run python -m ods_dump_telegram_channel.dump_to_telegram_bot`. 27 | 28 | ## Caveates 29 | 30 | Some of the caveates are mentiones in the source code of `ods_dump_telegram_channel.dump_to_telegram_bot.py` as TODOs. Current drawbacks: 31 | 32 | - formatting to HTML is not complete, there are some issues, and I only formatted bolded text, user mentions, and hyperlinks, the rest is shown as plain text; 33 | - Messages are limited to 4096 chars (that's not enough for e.g. posts in **#article_essence** where valuable content goes into a thread as well as the main post). It'd be nice to implement sending replies from a Slack thread as replies to a Telegram message, 34 | - the code is quite slow, an asynchrounous version is commited to the [`feature/send_async_messages`](https://github.com/Yorko/ods_dump_telegram_channel/tree/feature/send_async_messages) branch, however, it also hits timeouts (e.g. telegram.error.RetryAfter: Flood control exceeded). 35 | -------------------------------------------------------------------------------- /ods_dump_telegram_channel/dump_to_telegram_bot.py: -------------------------------------------------------------------------------- 1 | import json 2 | import time 3 | from pathlib import Path 4 | from typing import Any, Dict, List 5 | 6 | import requests 7 | from tqdm import tqdm 8 | 9 | from ods_dump_telegram_channel.utils import load_config_params, process_to_html 10 | 11 | 12 | def get_user_dict(path_to_dump: Path, filename: str = "users.json"): 13 | """ 14 | 15 | :param path_to_dump: path to local Slack dump 16 | :param filename: filename with users info 17 | :return: a dictionary mapping Slack User IDs to their nicknames 18 | """ 19 | with open(path_to_dump / filename) as f: 20 | full_user_dict_list = json.load(f) 21 | 22 | user_dict = {user_dict["id"]: user_dict["name"] for user_dict in full_user_dict_list} 23 | 24 | return user_dict 25 | 26 | 27 | def get_posts( 28 | path_to_dump: Path, 29 | user_dict: Dict[str, str], 30 | channel: str, 31 | add_replies: bool = False, 32 | max_length: int = 3800, 33 | min_length: int = 300, 34 | ) -> List[str]: 35 | posts = [] 36 | 37 | for filename in sorted((path_to_dump / channel).glob("*.json")): 38 | with open(str(filename)) as f: 39 | 40 | post_date = filename.stem 41 | content = json.load(f) 42 | 43 | content_dict = { 44 | f"{entry['user']}_{entry['ts']}": { 45 | "real_name": entry["user_profile"]["real_name"], 46 | "text": entry["text"], 47 | } 48 | for entry in content 49 | if entry.get("user") and entry.get("user_profile") 50 | } 51 | 52 | for entry in content: 53 | 54 | # obligatory fields 55 | if not (entry.get("reply_count") and entry.get("reactions") and entry.get("user_profile")): 56 | continue 57 | 58 | author, text = entry["user_profile"]["real_name"], entry["text"] 59 | 60 | post = f"POSTED BY *{author}* on {post_date}:\n{text}" 61 | 62 | if len(post) < min_length: 63 | continue 64 | 65 | # Nice try but posts get too long with replies, while Telegram can 66 | # send messages up to 4096 tokens. 67 | # TODO: figure out how to send messages as replies 68 | if add_replies: 69 | # Adding only today's replies 70 | today_reply_ids = [f"{reply['user']}_{reply['ts']}" for reply in entry["replies"]] 71 | if set(content_dict.keys()).intersection(today_reply_ids): 72 | post += "\n\nTHREAD:\n" 73 | 74 | for reply in entry["replies"]: 75 | reply_id = f"{reply['user']}_{reply['ts']}" 76 | if not content_dict.get(reply_id): 77 | continue 78 | post += "-" * 16 + "\n" + content_dict[reply_id]["real_name"] + "\n" 79 | post += ( 80 | process_to_html(content_dict[reply_id]["text"], user_dict=user_dict) + "\n" + "-" * 16 81 | ) 82 | 83 | posts.append(post[:max_length]) 84 | 85 | return posts 86 | 87 | 88 | def send_with_sleep( 89 | messages: List[str], 90 | user_dict, 91 | token: str, 92 | chat_id: str, 93 | short_pause_sec: int = 1, 94 | long_pause_sec: int = 120, 95 | send_as_html: bool = True, 96 | ): 97 | 98 | for message in tqdm(messages, total=len(messages)): 99 | 100 | html_message = process_to_html(message, user_dict=user_dict) 101 | url = f"https://api.telegram.org/bot{token}/sendMessage?chat_id={chat_id}&text={html_message}" 102 | if send_as_html: 103 | html_url = url + "&parse_mode=html" 104 | resp = requests.get(html_url).json() 105 | 106 | # TODO: implement nice retries 107 | if resp.get("error_code") == 400: 108 | print("sending as raw text") 109 | url = f"https://api.telegram.org/bot{token}/sendMessage?chat_id={chat_id}&text={message}" 110 | resp = requests.get(url).json() 111 | elif resp.get("error_code") == 429: 112 | print(f"Sleeping {long_pause_sec} sec.") 113 | time.sleep(long_pause_sec) 114 | # TODO: here we can still hit an error, retries needed 115 | resp = requests.get(html_url).json() 116 | print(resp) 117 | 118 | time.sleep(short_pause_sec) 119 | 120 | 121 | def main(): 122 | # loading project-wide configuration params 123 | params: Dict[str, Any] = load_config_params() 124 | path_to_dump = Path(params["data"]["path_to_ods_slack_dump"]) 125 | with open(params["telegram"]["path_to_telegram_bot_secret_file"]) as f: 126 | telegram_token = f.read().strip() 127 | telegram_chat_id = params["telegram"]["telegram_chat_id"] 128 | 129 | # get a dictionary with user nicknames 130 | user_dict = get_user_dict(path_to_dump=path_to_dump) 131 | 132 | # get all posts from the channel 133 | posts = get_posts( 134 | path_to_dump=path_to_dump, 135 | user_dict=user_dict, 136 | channel=params["data"]["ods_channel_name"], 137 | ) 138 | 139 | # send posts to a Telegram bot 140 | send_with_sleep(messages=posts, token=telegram_token, chat_id=telegram_chat_id, user_dict=user_dict) 141 | 142 | 143 | if __name__ == "__main__": 144 | main() 145 | -------------------------------------------------------------------------------- /poetry.lock: -------------------------------------------------------------------------------- 1 | [[package]] 2 | name = "anyio" 3 | version = "3.6.1" 4 | description = "High level compatibility layer for multiple asynchronous event loop implementations" 5 | category = "main" 6 | optional = false 7 | python-versions = ">=3.6.2" 8 | 9 | [package.dependencies] 10 | idna = ">=2.8" 11 | sniffio = ">=1.1" 12 | 13 | [package.extras] 14 | doc = ["packaging", "sphinx-rtd-theme", "sphinx-autodoc-typehints (>=1.2.0)"] 15 | test = ["coverage[toml] (>=4.5)", "hypothesis (>=4.0)", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "contextlib2", "uvloop (<0.15)", "mock (>=4)", "uvloop (>=0.15)"] 16 | trio = ["trio (>=0.16)"] 17 | 18 | [[package]] 19 | name = "apscheduler" 20 | version = "3.9.1" 21 | description = "In-process task scheduler with Cron-like capabilities" 22 | category = "main" 23 | optional = false 24 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4" 25 | 26 | [package.dependencies] 27 | pytz = "*" 28 | six = ">=1.4.0" 29 | tzlocal = ">=2.0,<3.0.0 || >=4.0.0" 30 | 31 | [package.extras] 32 | asyncio = ["trollius"] 33 | doc = ["sphinx", "sphinx-rtd-theme"] 34 | gevent = ["gevent"] 35 | mongodb = ["pymongo (>=3.0)"] 36 | redis = ["redis (>=3.0)"] 37 | rethinkdb = ["rethinkdb (>=2.4.0)"] 38 | sqlalchemy = ["sqlalchemy (>=0.8)"] 39 | testing = ["pytest", "pytest-cov", "pytest-tornado5", "mock", "pytest-asyncio (<0.6)", "pytest-asyncio"] 40 | tornado = ["tornado (>=4.3)"] 41 | twisted = ["twisted"] 42 | zookeeper = ["kazoo"] 43 | 44 | [[package]] 45 | name = "astroid" 46 | version = "2.12.9" 47 | description = "An abstract syntax tree for Python with inference support." 48 | category = "dev" 49 | optional = false 50 | python-versions = ">=3.7.2" 51 | 52 | [package.dependencies] 53 | lazy-object-proxy = ">=1.4.0" 54 | typing-extensions = {version = ">=3.10", markers = "python_version < \"3.10\""} 55 | wrapt = [ 56 | {version = ">=1.11,<2", markers = "python_version < \"3.11\""}, 57 | {version = ">=1.14,<2", markers = "python_version >= \"3.11\""}, 58 | ] 59 | 60 | [[package]] 61 | name = "async-timeout" 62 | version = "4.0.2" 63 | description = "Timeout context manager for asyncio programs" 64 | category = "main" 65 | optional = false 66 | python-versions = ">=3.6" 67 | 68 | [[package]] 69 | name = "atomicwrites" 70 | version = "1.4.1" 71 | description = "Atomic file writes." 72 | category = "dev" 73 | optional = false 74 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" 75 | 76 | [[package]] 77 | name = "attrs" 78 | version = "22.1.0" 79 | description = "Classes Without Boilerplate" 80 | category = "dev" 81 | optional = false 82 | python-versions = ">=3.5" 83 | 84 | [package.extras] 85 | dev = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "mypy (>=0.900,!=0.940)", "pytest-mypy-plugins", "zope.interface", "furo", "sphinx", "sphinx-notfound-page", "pre-commit", "cloudpickle"] 86 | docs = ["furo", "sphinx", "zope.interface", "sphinx-notfound-page"] 87 | tests = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "mypy (>=0.900,!=0.940)", "pytest-mypy-plugins", "zope.interface", "cloudpickle"] 88 | tests_no_zope = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "mypy (>=0.900,!=0.940)", "pytest-mypy-plugins", "cloudpickle"] 89 | 90 | [[package]] 91 | name = "black" 92 | version = "22.8.0" 93 | description = "The uncompromising code formatter." 94 | category = "dev" 95 | optional = false 96 | python-versions = ">=3.6.2" 97 | 98 | [package.dependencies] 99 | click = ">=8.0.0" 100 | mypy-extensions = ">=0.4.3" 101 | pathspec = ">=0.9.0" 102 | platformdirs = ">=2" 103 | tomli = {version = ">=1.1.0", markers = "python_full_version < \"3.11.0a7\""} 104 | typing-extensions = {version = ">=3.10.0.0", markers = "python_version < \"3.10\""} 105 | 106 | [package.extras] 107 | colorama = ["colorama (>=0.4.3)"] 108 | d = ["aiohttp (>=3.7.4)"] 109 | jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"] 110 | uvloop = ["uvloop (>=0.15.2)"] 111 | 112 | [[package]] 113 | name = "cachetools" 114 | version = "5.2.0" 115 | description = "Extensible memoizing collections and decorators" 116 | category = "main" 117 | optional = false 118 | python-versions = "~=3.7" 119 | 120 | [[package]] 121 | name = "certifi" 122 | version = "2022.6.15" 123 | description = "Python package for providing Mozilla's CA Bundle." 124 | category = "main" 125 | optional = false 126 | python-versions = ">=3.6" 127 | 128 | [[package]] 129 | name = "charset-normalizer" 130 | version = "2.1.1" 131 | description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." 132 | category = "main" 133 | optional = false 134 | python-versions = ">=3.6.0" 135 | 136 | [package.extras] 137 | unicode_backport = ["unicodedata2"] 138 | 139 | [[package]] 140 | name = "click" 141 | version = "8.1.3" 142 | description = "Composable command line interface toolkit" 143 | category = "dev" 144 | optional = false 145 | python-versions = ">=3.7" 146 | 147 | [package.dependencies] 148 | colorama = {version = "*", markers = "platform_system == \"Windows\""} 149 | 150 | [[package]] 151 | name = "colorama" 152 | version = "0.4.5" 153 | description = "Cross-platform colored terminal text." 154 | category = "main" 155 | optional = false 156 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" 157 | 158 | [[package]] 159 | name = "coverage" 160 | version = "6.4.4" 161 | description = "Code coverage measurement for Python" 162 | category = "dev" 163 | optional = false 164 | python-versions = ">=3.7" 165 | 166 | [package.extras] 167 | toml = ["tomli"] 168 | 169 | [[package]] 170 | name = "dill" 171 | version = "0.3.5.1" 172 | description = "serialize all of python" 173 | category = "dev" 174 | optional = false 175 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*, !=3.6.*" 176 | 177 | [package.extras] 178 | graph = ["objgraph (>=1.7.2)"] 179 | 180 | [[package]] 181 | name = "flake8" 182 | version = "3.9.2" 183 | description = "the modular source code checker: pep8 pyflakes and co" 184 | category = "dev" 185 | optional = false 186 | python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" 187 | 188 | [package.dependencies] 189 | mccabe = ">=0.6.0,<0.7.0" 190 | pycodestyle = ">=2.7.0,<2.8.0" 191 | pyflakes = ">=2.3.0,<2.4.0" 192 | 193 | [[package]] 194 | name = "h11" 195 | version = "0.12.0" 196 | description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" 197 | category = "main" 198 | optional = false 199 | python-versions = ">=3.6" 200 | 201 | [[package]] 202 | name = "httpcore" 203 | version = "0.15.0" 204 | description = "A minimal low-level HTTP client." 205 | category = "main" 206 | optional = false 207 | python-versions = ">=3.7" 208 | 209 | [package.dependencies] 210 | anyio = ">=3.0.0,<4.0.0" 211 | certifi = "*" 212 | h11 = ">=0.11,<0.13" 213 | sniffio = ">=1.0.0,<2.0.0" 214 | 215 | [package.extras] 216 | http2 = ["h2 (>=3,<5)"] 217 | socks = ["socksio (>=1.0.0,<2.0.0)"] 218 | 219 | [[package]] 220 | name = "httpx" 221 | version = "0.23.0" 222 | description = "The next generation HTTP client." 223 | category = "main" 224 | optional = false 225 | python-versions = ">=3.7" 226 | 227 | [package.dependencies] 228 | certifi = "*" 229 | httpcore = ">=0.15.0,<0.16.0" 230 | rfc3986 = {version = ">=1.3,<2", extras = ["idna2008"]} 231 | sniffio = "*" 232 | 233 | [package.extras] 234 | brotli = ["brotlicffi", "brotli"] 235 | cli = ["click (>=8.0.0,<9.0.0)", "rich (>=10,<13)", "pygments (>=2.0.0,<3.0.0)"] 236 | http2 = ["h2 (>=3,<5)"] 237 | socks = ["socksio (>=1.0.0,<2.0.0)"] 238 | 239 | [[package]] 240 | name = "idna" 241 | version = "3.3" 242 | description = "Internationalized Domain Names in Applications (IDNA)" 243 | category = "main" 244 | optional = false 245 | python-versions = ">=3.5" 246 | 247 | [[package]] 248 | name = "isort" 249 | version = "5.10.1" 250 | description = "A Python utility / library to sort Python imports." 251 | category = "dev" 252 | optional = false 253 | python-versions = ">=3.6.1,<4.0" 254 | 255 | [package.extras] 256 | pipfile_deprecated_finder = ["pipreqs", "requirementslib"] 257 | requirements_deprecated_finder = ["pipreqs", "pip-api"] 258 | colors = ["colorama (>=0.4.3,<0.5.0)"] 259 | plugins = ["setuptools"] 260 | 261 | [[package]] 262 | name = "lazy-object-proxy" 263 | version = "1.7.1" 264 | description = "A fast and thorough lazy object proxy." 265 | category = "dev" 266 | optional = false 267 | python-versions = ">=3.6" 268 | 269 | [[package]] 270 | name = "mccabe" 271 | version = "0.6.1" 272 | description = "McCabe checker, plugin for flake8" 273 | category = "dev" 274 | optional = false 275 | python-versions = "*" 276 | 277 | [[package]] 278 | name = "more-itertools" 279 | version = "8.14.0" 280 | description = "More routines for operating on iterables, beyond itertools" 281 | category = "dev" 282 | optional = false 283 | python-versions = ">=3.5" 284 | 285 | [[package]] 286 | name = "mypy-extensions" 287 | version = "0.4.3" 288 | description = "Experimental type system extensions for programs checked with the mypy typechecker." 289 | category = "dev" 290 | optional = false 291 | python-versions = "*" 292 | 293 | [[package]] 294 | name = "packaging" 295 | version = "21.3" 296 | description = "Core utilities for Python packages" 297 | category = "dev" 298 | optional = false 299 | python-versions = ">=3.6" 300 | 301 | [package.dependencies] 302 | pyparsing = ">=2.0.2,<3.0.5 || >3.0.5" 303 | 304 | [[package]] 305 | name = "pathspec" 306 | version = "0.10.1" 307 | description = "Utility library for gitignore style pattern matching of file paths." 308 | category = "dev" 309 | optional = false 310 | python-versions = ">=3.7" 311 | 312 | [[package]] 313 | name = "platformdirs" 314 | version = "2.5.2" 315 | description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." 316 | category = "dev" 317 | optional = false 318 | python-versions = ">=3.7" 319 | 320 | [package.extras] 321 | docs = ["furo (>=2021.7.5b38)", "proselint (>=0.10.2)", "sphinx-autodoc-typehints (>=1.12)", "sphinx (>=4)"] 322 | test = ["appdirs (==1.4.4)", "pytest-cov (>=2.7)", "pytest-mock (>=3.6)", "pytest (>=6)"] 323 | 324 | [[package]] 325 | name = "pluggy" 326 | version = "0.13.1" 327 | description = "plugin and hook calling mechanisms for python" 328 | category = "dev" 329 | optional = false 330 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" 331 | 332 | [package.extras] 333 | dev = ["pre-commit", "tox"] 334 | 335 | [[package]] 336 | name = "py" 337 | version = "1.11.0" 338 | description = "library with cross-python path, ini-parsing, io, code, log facilities" 339 | category = "dev" 340 | optional = false 341 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" 342 | 343 | [[package]] 344 | name = "pycodestyle" 345 | version = "2.7.0" 346 | description = "Python style guide checker" 347 | category = "dev" 348 | optional = false 349 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" 350 | 351 | [[package]] 352 | name = "pyflakes" 353 | version = "2.3.1" 354 | description = "passive checker of Python programs" 355 | category = "dev" 356 | optional = false 357 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" 358 | 359 | [[package]] 360 | name = "pylint" 361 | version = "2.15.2" 362 | description = "python code static checker" 363 | category = "dev" 364 | optional = false 365 | python-versions = ">=3.7.2" 366 | 367 | [package.dependencies] 368 | astroid = ">=2.12.9,<=2.14.0-dev0" 369 | colorama = {version = ">=0.4.5", markers = "sys_platform == \"win32\""} 370 | dill = ">=0.2" 371 | isort = ">=4.2.5,<6" 372 | mccabe = ">=0.6,<0.8" 373 | platformdirs = ">=2.2.0" 374 | tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} 375 | tomlkit = ">=0.10.1" 376 | typing-extensions = {version = ">=3.10.0", markers = "python_version < \"3.10\""} 377 | 378 | [package.extras] 379 | spelling = ["pyenchant (>=3.2,<4.0)"] 380 | testutils = ["gitpython (>3)"] 381 | 382 | [[package]] 383 | name = "pyparsing" 384 | version = "3.0.9" 385 | description = "pyparsing module - Classes and methods to define and execute parsing grammars" 386 | category = "dev" 387 | optional = false 388 | python-versions = ">=3.6.8" 389 | 390 | [package.extras] 391 | diagrams = ["railroad-diagrams", "jinja2"] 392 | 393 | [[package]] 394 | name = "pytest" 395 | version = "5.4.3" 396 | description = "pytest: simple powerful testing with Python" 397 | category = "dev" 398 | optional = false 399 | python-versions = ">=3.5" 400 | 401 | [package.dependencies] 402 | atomicwrites = {version = ">=1.0", markers = "sys_platform == \"win32\""} 403 | attrs = ">=17.4.0" 404 | colorama = {version = "*", markers = "sys_platform == \"win32\""} 405 | more-itertools = ">=4.0.0" 406 | packaging = "*" 407 | pluggy = ">=0.12,<1.0" 408 | py = ">=1.5.0" 409 | wcwidth = "*" 410 | 411 | [package.extras] 412 | checkqa-mypy = ["mypy (==v0.761)"] 413 | testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "requests", "xmlschema"] 414 | 415 | [[package]] 416 | name = "pytest-cov" 417 | version = "2.12.1" 418 | description = "Pytest plugin for measuring coverage." 419 | category = "dev" 420 | optional = false 421 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" 422 | 423 | [package.dependencies] 424 | coverage = ">=5.2.1" 425 | pytest = ">=4.6" 426 | toml = "*" 427 | 428 | [package.extras] 429 | testing = ["fields", "hunter", "process-tests", "six", "pytest-xdist", "virtualenv"] 430 | 431 | [[package]] 432 | name = "pytest-html" 433 | version = "2.1.1" 434 | description = "pytest plugin for generating HTML reports" 435 | category = "dev" 436 | optional = false 437 | python-versions = ">=3.6" 438 | 439 | [package.dependencies] 440 | pytest = ">=5.0" 441 | pytest-metadata = "*" 442 | 443 | [[package]] 444 | name = "pytest-metadata" 445 | version = "2.0.2" 446 | description = "pytest plugin for test session metadata" 447 | category = "dev" 448 | optional = false 449 | python-versions = ">=3.7,<4.0" 450 | 451 | [package.dependencies] 452 | pytest = ">=3.0.0,<8.0.0" 453 | 454 | [[package]] 455 | name = "python-telegram-bot" 456 | version = "20.0a4" 457 | description = "We have made you a wrapper you can't refuse" 458 | category = "main" 459 | optional = false 460 | python-versions = ">=3.7" 461 | 462 | [package.dependencies] 463 | APScheduler = ">=3.9.1,<3.10.0" 464 | cachetools = ">=5.2.0,<5.3.0" 465 | httpx = ">=0.23.0,<0.24.0" 466 | pytz = ">=2018.6" 467 | tornado = ">=6.2,<7.0" 468 | 469 | [package.extras] 470 | passport = ["cryptography (>=3.0,!=3.4,!=3.4.1,!=3.4.2,!=3.4.3)"] 471 | rate-limiter = ["aiolimiter (>=1.0.0,<1.1.0)"] 472 | socks = ["httpx"] 473 | 474 | [[package]] 475 | name = "pytz" 476 | version = "2022.2.1" 477 | description = "World timezone definitions, modern and historical" 478 | category = "main" 479 | optional = false 480 | python-versions = "*" 481 | 482 | [[package]] 483 | name = "pytz-deprecation-shim" 484 | version = "0.1.0.post0" 485 | description = "Shims to make deprecation of pytz easier" 486 | category = "main" 487 | optional = false 488 | python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7" 489 | 490 | [package.dependencies] 491 | tzdata = {version = "*", markers = "python_version >= \"3.6\""} 492 | 493 | [[package]] 494 | name = "pyyaml" 495 | version = "6.0" 496 | description = "YAML parser and emitter for Python" 497 | category = "main" 498 | optional = false 499 | python-versions = ">=3.6" 500 | 501 | [[package]] 502 | name = "requests" 503 | version = "2.28.1" 504 | description = "Python HTTP for Humans." 505 | category = "main" 506 | optional = false 507 | python-versions = ">=3.7, <4" 508 | 509 | [package.dependencies] 510 | certifi = ">=2017.4.17" 511 | charset-normalizer = ">=2,<3" 512 | idna = ">=2.5,<4" 513 | urllib3 = ">=1.21.1,<1.27" 514 | 515 | [package.extras] 516 | socks = ["PySocks (>=1.5.6,!=1.5.7)"] 517 | use_chardet_on_py3 = ["chardet (>=3.0.2,<6)"] 518 | 519 | [[package]] 520 | name = "rfc3986" 521 | version = "1.5.0" 522 | description = "Validating URI References per RFC 3986" 523 | category = "main" 524 | optional = false 525 | python-versions = "*" 526 | 527 | [package.dependencies] 528 | idna = {version = "*", optional = true, markers = "extra == \"idna2008\""} 529 | 530 | [package.extras] 531 | idna2008 = ["idna"] 532 | 533 | [[package]] 534 | name = "six" 535 | version = "1.16.0" 536 | description = "Python 2 and 3 compatibility utilities" 537 | category = "main" 538 | optional = false 539 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" 540 | 541 | [[package]] 542 | name = "sniffio" 543 | version = "1.3.0" 544 | description = "Sniff out which async library your code is running under" 545 | category = "main" 546 | optional = false 547 | python-versions = ">=3.7" 548 | 549 | [[package]] 550 | name = "toml" 551 | version = "0.10.2" 552 | description = "Python Library for Tom's Obvious, Minimal Language" 553 | category = "dev" 554 | optional = false 555 | python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" 556 | 557 | [[package]] 558 | name = "tomli" 559 | version = "2.0.1" 560 | description = "A lil' TOML parser" 561 | category = "dev" 562 | optional = false 563 | python-versions = ">=3.7" 564 | 565 | [[package]] 566 | name = "tomlkit" 567 | version = "0.11.4" 568 | description = "Style preserving TOML library" 569 | category = "dev" 570 | optional = false 571 | python-versions = ">=3.6,<4.0" 572 | 573 | [[package]] 574 | name = "tornado" 575 | version = "6.2" 576 | description = "Tornado is a Python web framework and asynchronous networking library, originally developed at FriendFeed." 577 | category = "main" 578 | optional = false 579 | python-versions = ">= 3.7" 580 | 581 | [[package]] 582 | name = "tqdm" 583 | version = "4.64.1" 584 | description = "Fast, Extensible Progress Meter" 585 | category = "main" 586 | optional = false 587 | python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,>=2.7" 588 | 589 | [package.dependencies] 590 | colorama = {version = "*", markers = "platform_system == \"Windows\""} 591 | 592 | [package.extras] 593 | dev = ["py-make (>=0.1.0)", "twine", "wheel"] 594 | notebook = ["ipywidgets (>=6)"] 595 | slack = ["slack-sdk"] 596 | telegram = ["requests"] 597 | 598 | [[package]] 599 | name = "typing-extensions" 600 | version = "4.3.0" 601 | description = "Backported and Experimental Type Hints for Python 3.7+" 602 | category = "dev" 603 | optional = false 604 | python-versions = ">=3.7" 605 | 606 | [[package]] 607 | name = "tzdata" 608 | version = "2022.2" 609 | description = "Provider of IANA time zone data" 610 | category = "main" 611 | optional = false 612 | python-versions = ">=2" 613 | 614 | [[package]] 615 | name = "tzlocal" 616 | version = "4.2" 617 | description = "tzinfo object for the local timezone" 618 | category = "main" 619 | optional = false 620 | python-versions = ">=3.6" 621 | 622 | [package.dependencies] 623 | pytz-deprecation-shim = "*" 624 | tzdata = {version = "*", markers = "platform_system == \"Windows\""} 625 | 626 | [package.extras] 627 | devenv = ["black", "pyroma", "pytest-cov", "zest.releaser"] 628 | test = ["pytest-mock (>=3.3)", "pytest (>=4.3)"] 629 | 630 | [[package]] 631 | name = "urllib3" 632 | version = "1.26.12" 633 | description = "HTTP library with thread-safe connection pooling, file post, and more." 634 | category = "main" 635 | optional = false 636 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*, <4" 637 | 638 | [package.extras] 639 | brotli = ["brotlicffi (>=0.8.0)", "brotli (>=1.0.9)", "brotlipy (>=0.6.0)"] 640 | secure = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "certifi", "urllib3-secure-extra", "ipaddress"] 641 | socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] 642 | 643 | [[package]] 644 | name = "wcwidth" 645 | version = "0.2.5" 646 | description = "Measures the displayed width of unicode strings in a terminal" 647 | category = "dev" 648 | optional = false 649 | python-versions = "*" 650 | 651 | [[package]] 652 | name = "wrapt" 653 | version = "1.14.1" 654 | description = "Module for decorators, wrappers and monkey patching." 655 | category = "dev" 656 | optional = false 657 | python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" 658 | 659 | [metadata] 660 | lock-version = "1.1" 661 | python-versions = ">=3.9,<4" 662 | content-hash = "b2dd870f1ffad01794e54c9200545e38a27b708b2dbfec7e1dba0cafc2c2e020" 663 | 664 | [metadata.files] 665 | anyio = [] 666 | apscheduler = [] 667 | astroid = [] 668 | async-timeout = [ 669 | {file = "async-timeout-4.0.2.tar.gz", hash = "sha256:2163e1640ddb52b7a8c80d0a67a08587e5d245cc9c553a74a847056bc2976b15"}, 670 | {file = "async_timeout-4.0.2-py3-none-any.whl", hash = "sha256:8ca1e4fcf50d07413d66d1a5e416e42cfdf5851c981d679a09851a6853383b3c"}, 671 | ] 672 | atomicwrites = [] 673 | attrs = [] 674 | black = [] 675 | cachetools = [] 676 | certifi = [ 677 | {file = "certifi-2022.6.15-py3-none-any.whl", hash = "sha256:fe86415d55e84719d75f8b69414f6438ac3547d2078ab91b67e779ef69378412"}, 678 | {file = "certifi-2022.6.15.tar.gz", hash = "sha256:84c85a9078b11105f04f3036a9482ae10e4621616db313fe045dd24743a0820d"}, 679 | ] 680 | charset-normalizer = [] 681 | click = [ 682 | {file = "click-8.1.3-py3-none-any.whl", hash = "sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48"}, 683 | {file = "click-8.1.3.tar.gz", hash = "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e"}, 684 | ] 685 | colorama = [ 686 | {file = "colorama-0.4.5-py2.py3-none-any.whl", hash = "sha256:854bf444933e37f5824ae7bfc1e98d5bce2ebe4160d46b5edf346a89358e99da"}, 687 | {file = "colorama-0.4.5.tar.gz", hash = "sha256:e6c6b4334fc50988a639d9b98aa429a0b57da6e17b9a44f0451f930b6967b7a4"}, 688 | ] 689 | coverage = [] 690 | dill = [ 691 | {file = "dill-0.3.5.1-py2.py3-none-any.whl", hash = "sha256:33501d03270bbe410c72639b350e941882a8b0fd55357580fbc873fba0c59302"}, 692 | {file = "dill-0.3.5.1.tar.gz", hash = "sha256:d75e41f3eff1eee599d738e76ba8f4ad98ea229db8b085318aa2b3333a208c86"}, 693 | ] 694 | flake8 = [ 695 | {file = "flake8-3.9.2-py2.py3-none-any.whl", hash = "sha256:bf8fd333346d844f616e8d47905ef3a3384edae6b4e9beb0c5101e25e3110907"}, 696 | {file = "flake8-3.9.2.tar.gz", hash = "sha256:07528381786f2a6237b061f6e96610a4167b226cb926e2aa2b6b1d78057c576b"}, 697 | ] 698 | h11 = [] 699 | httpcore = [] 700 | httpx = [] 701 | idna = [ 702 | {file = "idna-3.3-py3-none-any.whl", hash = "sha256:84d9dd047ffa80596e0f246e2eab0b391788b0503584e8945f2368256d2735ff"}, 703 | {file = "idna-3.3.tar.gz", hash = "sha256:9d643ff0a55b762d5cdb124b8eaa99c66322e2157b69160bc32796e824360e6d"}, 704 | ] 705 | isort = [ 706 | {file = "isort-5.10.1-py3-none-any.whl", hash = "sha256:6f62d78e2f89b4500b080fe3a81690850cd254227f27f75c3a0c491a1f351ba7"}, 707 | {file = "isort-5.10.1.tar.gz", hash = "sha256:e8443a5e7a020e9d7f97f1d7d9cd17c88bcb3bc7e218bf9cf5095fe550be2951"}, 708 | ] 709 | lazy-object-proxy = [ 710 | {file = "lazy-object-proxy-1.7.1.tar.gz", hash = "sha256:d609c75b986def706743cdebe5e47553f4a5a1da9c5ff66d76013ef396b5a8a4"}, 711 | {file = "lazy_object_proxy-1.7.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:bb8c5fd1684d60a9902c60ebe276da1f2281a318ca16c1d0a96db28f62e9166b"}, 712 | {file = "lazy_object_proxy-1.7.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a57d51ed2997e97f3b8e3500c984db50a554bb5db56c50b5dab1b41339b37e36"}, 713 | {file = "lazy_object_proxy-1.7.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fd45683c3caddf83abbb1249b653a266e7069a09f486daa8863fb0e7496a9fdb"}, 714 | {file = "lazy_object_proxy-1.7.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:8561da8b3dd22d696244d6d0d5330618c993a215070f473b699e00cf1f3f6443"}, 715 | {file = "lazy_object_proxy-1.7.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fccdf7c2c5821a8cbd0a9440a456f5050492f2270bd54e94360cac663398739b"}, 716 | {file = "lazy_object_proxy-1.7.1-cp310-cp310-win32.whl", hash = "sha256:898322f8d078f2654d275124a8dd19b079080ae977033b713f677afcfc88e2b9"}, 717 | {file = "lazy_object_proxy-1.7.1-cp310-cp310-win_amd64.whl", hash = "sha256:85b232e791f2229a4f55840ed54706110c80c0a210d076eee093f2b2e33e1bfd"}, 718 | {file = "lazy_object_proxy-1.7.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:46ff647e76f106bb444b4533bb4153c7370cdf52efc62ccfc1a28bdb3cc95442"}, 719 | {file = "lazy_object_proxy-1.7.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:12f3bb77efe1367b2515f8cb4790a11cffae889148ad33adad07b9b55e0ab22c"}, 720 | {file = "lazy_object_proxy-1.7.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c19814163728941bb871240d45c4c30d33b8a2e85972c44d4e63dd7107faba44"}, 721 | {file = "lazy_object_proxy-1.7.1-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:e40f2013d96d30217a51eeb1db28c9ac41e9d0ee915ef9d00da639c5b63f01a1"}, 722 | {file = "lazy_object_proxy-1.7.1-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:2052837718516a94940867e16b1bb10edb069ab475c3ad84fd1e1a6dd2c0fcfc"}, 723 | {file = "lazy_object_proxy-1.7.1-cp36-cp36m-win32.whl", hash = "sha256:6a24357267aa976abab660b1d47a34aaf07259a0c3859a34e536f1ee6e76b5bb"}, 724 | {file = "lazy_object_proxy-1.7.1-cp36-cp36m-win_amd64.whl", hash = "sha256:6aff3fe5de0831867092e017cf67e2750c6a1c7d88d84d2481bd84a2e019ec35"}, 725 | {file = "lazy_object_proxy-1.7.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:6a6e94c7b02641d1311228a102607ecd576f70734dc3d5e22610111aeacba8a0"}, 726 | {file = "lazy_object_proxy-1.7.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c4ce15276a1a14549d7e81c243b887293904ad2d94ad767f42df91e75fd7b5b6"}, 727 | {file = "lazy_object_proxy-1.7.1-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e368b7f7eac182a59ff1f81d5f3802161932a41dc1b1cc45c1f757dc876b5d2c"}, 728 | {file = "lazy_object_proxy-1.7.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:6ecbb350991d6434e1388bee761ece3260e5228952b1f0c46ffc800eb313ff42"}, 729 | {file = "lazy_object_proxy-1.7.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:553b0f0d8dbf21890dd66edd771f9b1b5f51bd912fa5f26de4449bfc5af5e029"}, 730 | {file = "lazy_object_proxy-1.7.1-cp37-cp37m-win32.whl", hash = "sha256:c7a683c37a8a24f6428c28c561c80d5f4fd316ddcf0c7cab999b15ab3f5c5c69"}, 731 | {file = "lazy_object_proxy-1.7.1-cp37-cp37m-win_amd64.whl", hash = "sha256:df2631f9d67259dc9620d831384ed7732a198eb434eadf69aea95ad18c587a28"}, 732 | {file = "lazy_object_proxy-1.7.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:07fa44286cda977bd4803b656ffc1c9b7e3bc7dff7d34263446aec8f8c96f88a"}, 733 | {file = "lazy_object_proxy-1.7.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4dca6244e4121c74cc20542c2ca39e5c4a5027c81d112bfb893cf0790f96f57e"}, 734 | {file = "lazy_object_proxy-1.7.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:91ba172fc5b03978764d1df5144b4ba4ab13290d7bab7a50f12d8117f8630c38"}, 735 | {file = "lazy_object_proxy-1.7.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:043651b6cb706eee4f91854da4a089816a6606c1428fd391573ef8cb642ae4f7"}, 736 | {file = "lazy_object_proxy-1.7.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:b9e89b87c707dd769c4ea91f7a31538888aad05c116a59820f28d59b3ebfe25a"}, 737 | {file = "lazy_object_proxy-1.7.1-cp38-cp38-win32.whl", hash = "sha256:9d166602b525bf54ac994cf833c385bfcc341b364e3ee71e3bf5a1336e677b55"}, 738 | {file = "lazy_object_proxy-1.7.1-cp38-cp38-win_amd64.whl", hash = "sha256:8f3953eb575b45480db6568306893f0bd9d8dfeeebd46812aa09ca9579595148"}, 739 | {file = "lazy_object_proxy-1.7.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:dd7ed7429dbb6c494aa9bc4e09d94b778a3579be699f9d67da7e6804c422d3de"}, 740 | {file = "lazy_object_proxy-1.7.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:70ed0c2b380eb6248abdef3cd425fc52f0abd92d2b07ce26359fcbc399f636ad"}, 741 | {file = "lazy_object_proxy-1.7.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7096a5e0c1115ec82641afbdd70451a144558ea5cf564a896294e346eb611be1"}, 742 | {file = "lazy_object_proxy-1.7.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:f769457a639403073968d118bc70110e7dce294688009f5c24ab78800ae56dc8"}, 743 | {file = "lazy_object_proxy-1.7.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:39b0e26725c5023757fc1ab2a89ef9d7ab23b84f9251e28f9cc114d5b59c1b09"}, 744 | {file = "lazy_object_proxy-1.7.1-cp39-cp39-win32.whl", hash = "sha256:2130db8ed69a48a3440103d4a520b89d8a9405f1b06e2cc81640509e8bf6548f"}, 745 | {file = "lazy_object_proxy-1.7.1-cp39-cp39-win_amd64.whl", hash = "sha256:677ea950bef409b47e51e733283544ac3d660b709cfce7b187f5ace137960d61"}, 746 | {file = "lazy_object_proxy-1.7.1-pp37.pp38-none-any.whl", hash = "sha256:d66906d5785da8e0be7360912e99c9188b70f52c422f9fc18223347235691a84"}, 747 | ] 748 | mccabe = [ 749 | {file = "mccabe-0.6.1-py2.py3-none-any.whl", hash = "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42"}, 750 | {file = "mccabe-0.6.1.tar.gz", hash = "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"}, 751 | ] 752 | more-itertools = [] 753 | mypy-extensions = [ 754 | {file = "mypy_extensions-0.4.3-py2.py3-none-any.whl", hash = "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d"}, 755 | {file = "mypy_extensions-0.4.3.tar.gz", hash = "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"}, 756 | ] 757 | packaging = [ 758 | {file = "packaging-21.3-py3-none-any.whl", hash = "sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522"}, 759 | {file = "packaging-21.3.tar.gz", hash = "sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb"}, 760 | ] 761 | pathspec = [] 762 | platformdirs = [ 763 | {file = "platformdirs-2.5.2-py3-none-any.whl", hash = "sha256:027d8e83a2d7de06bbac4e5ef7e023c02b863d7ea5d079477e722bb41ab25788"}, 764 | {file = "platformdirs-2.5.2.tar.gz", hash = "sha256:58c8abb07dcb441e6ee4b11d8df0ac856038f944ab98b7be6b27b2a3c7feef19"}, 765 | ] 766 | pluggy = [ 767 | {file = "pluggy-0.13.1-py2.py3-none-any.whl", hash = "sha256:966c145cd83c96502c3c3868f50408687b38434af77734af1e9ca461a4081d2d"}, 768 | {file = "pluggy-0.13.1.tar.gz", hash = "sha256:15b2acde666561e1298d71b523007ed7364de07029219b604cf808bfa1c765b0"}, 769 | ] 770 | py = [ 771 | {file = "py-1.11.0-py2.py3-none-any.whl", hash = "sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378"}, 772 | {file = "py-1.11.0.tar.gz", hash = "sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719"}, 773 | ] 774 | pycodestyle = [ 775 | {file = "pycodestyle-2.7.0-py2.py3-none-any.whl", hash = "sha256:514f76d918fcc0b55c6680472f0a37970994e07bbb80725808c17089be302068"}, 776 | {file = "pycodestyle-2.7.0.tar.gz", hash = "sha256:c389c1d06bf7904078ca03399a4816f974a1d590090fecea0c63ec26ebaf1cef"}, 777 | ] 778 | pyflakes = [ 779 | {file = "pyflakes-2.3.1-py2.py3-none-any.whl", hash = "sha256:7893783d01b8a89811dd72d7dfd4d84ff098e5eed95cfa8905b22bbffe52efc3"}, 780 | {file = "pyflakes-2.3.1.tar.gz", hash = "sha256:f5bc8ecabc05bb9d291eb5203d6810b49040f6ff446a756326104746cc00c1db"}, 781 | ] 782 | pylint = [] 783 | pyparsing = [ 784 | {file = "pyparsing-3.0.9-py3-none-any.whl", hash = "sha256:5026bae9a10eeaefb61dab2f09052b9f4307d44aee4eda64b309723d8d206bbc"}, 785 | {file = "pyparsing-3.0.9.tar.gz", hash = "sha256:2b020ecf7d21b687f219b71ecad3631f644a47f01403fa1d1036b0c6416d70fb"}, 786 | ] 787 | pytest = [ 788 | {file = "pytest-5.4.3-py3-none-any.whl", hash = "sha256:5c0db86b698e8f170ba4582a492248919255fcd4c79b1ee64ace34301fb589a1"}, 789 | {file = "pytest-5.4.3.tar.gz", hash = "sha256:7979331bfcba207414f5e1263b5a0f8f521d0f457318836a7355531ed1a4c7d8"}, 790 | ] 791 | pytest-cov = [ 792 | {file = "pytest-cov-2.12.1.tar.gz", hash = "sha256:261ceeb8c227b726249b376b8526b600f38667ee314f910353fa318caa01f4d7"}, 793 | {file = "pytest_cov-2.12.1-py2.py3-none-any.whl", hash = "sha256:261bb9e47e65bd099c89c3edf92972865210c36813f80ede5277dceb77a4a62a"}, 794 | ] 795 | pytest-html = [ 796 | {file = "pytest-html-2.1.1.tar.gz", hash = "sha256:6a4ac391e105e391208e3eb9bd294a60dd336447fd8e1acddff3a6de7f4e57c5"}, 797 | {file = "pytest_html-2.1.1-py2.py3-none-any.whl", hash = "sha256:9e4817e8be8ddde62e8653c8934d0f296b605da3d2277a052f762c56a8b32df2"}, 798 | ] 799 | pytest-metadata = [] 800 | python-telegram-bot = [] 801 | pytz = [] 802 | pytz-deprecation-shim = [ 803 | {file = "pytz_deprecation_shim-0.1.0.post0-py2.py3-none-any.whl", hash = "sha256:8314c9692a636c8eb3bda879b9f119e350e93223ae83e70e80c31675a0fdc1a6"}, 804 | {file = "pytz_deprecation_shim-0.1.0.post0.tar.gz", hash = "sha256:af097bae1b616dde5c5744441e2ddc69e74dfdcb0c263129610d85b87445a59d"}, 805 | ] 806 | pyyaml = [ 807 | {file = "PyYAML-6.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53"}, 808 | {file = "PyYAML-6.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9df7ed3b3d2e0ecfe09e14741b857df43adb5a3ddadc919a2d94fbdf78fea53c"}, 809 | {file = "PyYAML-6.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:77f396e6ef4c73fdc33a9157446466f1cff553d979bd00ecb64385760c6babdc"}, 810 | {file = "PyYAML-6.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a80a78046a72361de73f8f395f1f1e49f956c6be882eed58505a15f3e430962b"}, 811 | {file = "PyYAML-6.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f84fbc98b019fef2ee9a1cb3ce93e3187a6df0b2538a651bfb890254ba9f90b5"}, 812 | {file = "PyYAML-6.0-cp310-cp310-win32.whl", hash = "sha256:2cd5df3de48857ed0544b34e2d40e9fac445930039f3cfe4bcc592a1f836d513"}, 813 | {file = "PyYAML-6.0-cp310-cp310-win_amd64.whl", hash = "sha256:daf496c58a8c52083df09b80c860005194014c3698698d1a57cbcfa182142a3a"}, 814 | {file = "PyYAML-6.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:897b80890765f037df3403d22bab41627ca8811ae55e9a722fd0392850ec4d86"}, 815 | {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:50602afada6d6cbfad699b0c7bb50d5ccffa7e46a3d738092afddc1f9758427f"}, 816 | {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:48c346915c114f5fdb3ead70312bd042a953a8ce5c7106d5bfb1a5254e47da92"}, 817 | {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:98c4d36e99714e55cfbaaee6dd5badbc9a1ec339ebfc3b1f52e293aee6bb71a4"}, 818 | {file = "PyYAML-6.0-cp36-cp36m-win32.whl", hash = "sha256:0283c35a6a9fbf047493e3a0ce8d79ef5030852c51e9d911a27badfde0605293"}, 819 | {file = "PyYAML-6.0-cp36-cp36m-win_amd64.whl", hash = "sha256:07751360502caac1c067a8132d150cf3d61339af5691fe9e87803040dbc5db57"}, 820 | {file = "PyYAML-6.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:819b3830a1543db06c4d4b865e70ded25be52a2e0631ccd2f6a47a2822f2fd7c"}, 821 | {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:473f9edb243cb1935ab5a084eb238d842fb8f404ed2193a915d1784b5a6b5fc0"}, 822 | {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0ce82d761c532fe4ec3f87fc45688bdd3a4c1dc5e0b4a19814b9009a29baefd4"}, 823 | {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:231710d57adfd809ef5d34183b8ed1eeae3f76459c18fb4a0b373ad56bedcdd9"}, 824 | {file = "PyYAML-6.0-cp37-cp37m-win32.whl", hash = "sha256:c5687b8d43cf58545ade1fe3e055f70eac7a5a1a0bf42824308d868289a95737"}, 825 | {file = "PyYAML-6.0-cp37-cp37m-win_amd64.whl", hash = "sha256:d15a181d1ecd0d4270dc32edb46f7cb7733c7c508857278d3d378d14d606db2d"}, 826 | {file = "PyYAML-6.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0b4624f379dab24d3725ffde76559cff63d9ec94e1736b556dacdfebe5ab6d4b"}, 827 | {file = "PyYAML-6.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:213c60cd50106436cc818accf5baa1aba61c0189ff610f64f4a3e8c6726218ba"}, 828 | {file = "PyYAML-6.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9fa600030013c4de8165339db93d182b9431076eb98eb40ee068700c9c813e34"}, 829 | {file = "PyYAML-6.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:277a0ef2981ca40581a47093e9e2d13b3f1fbbeffae064c1d21bfceba2030287"}, 830 | {file = "PyYAML-6.0-cp38-cp38-win32.whl", hash = "sha256:d4eccecf9adf6fbcc6861a38015c2a64f38b9d94838ac1810a9023a0609e1b78"}, 831 | {file = "PyYAML-6.0-cp38-cp38-win_amd64.whl", hash = "sha256:1e4747bc279b4f613a09eb64bba2ba602d8a6664c6ce6396a4d0cd413a50ce07"}, 832 | {file = "PyYAML-6.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:055d937d65826939cb044fc8c9b08889e8c743fdc6a32b33e2390f66013e449b"}, 833 | {file = "PyYAML-6.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e61ceaab6f49fb8bdfaa0f92c4b57bcfbea54c09277b1b4f7ac376bfb7a7c174"}, 834 | {file = "PyYAML-6.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d67d839ede4ed1b28a4e8909735fc992a923cdb84e618544973d7dfc71540803"}, 835 | {file = "PyYAML-6.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cba8c411ef271aa037d7357a2bc8f9ee8b58b9965831d9e51baf703280dc73d3"}, 836 | {file = "PyYAML-6.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:40527857252b61eacd1d9af500c3337ba8deb8fc298940291486c465c8b46ec0"}, 837 | {file = "PyYAML-6.0-cp39-cp39-win32.whl", hash = "sha256:b5b9eccad747aabaaffbc6064800670f0c297e52c12754eb1d976c57e4f74dcb"}, 838 | {file = "PyYAML-6.0-cp39-cp39-win_amd64.whl", hash = "sha256:b3d267842bf12586ba6c734f89d1f5b871df0273157918b0ccefa29deb05c21c"}, 839 | {file = "PyYAML-6.0.tar.gz", hash = "sha256:68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2"}, 840 | ] 841 | requests = [] 842 | rfc3986 = [] 843 | six = [ 844 | {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, 845 | {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, 846 | ] 847 | sniffio = [] 848 | toml = [ 849 | {file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"}, 850 | {file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"}, 851 | ] 852 | tomli = [ 853 | {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, 854 | {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, 855 | ] 856 | tomlkit = [] 857 | tornado = [] 858 | tqdm = [] 859 | typing-extensions = [] 860 | tzdata = [] 861 | tzlocal = [ 862 | {file = "tzlocal-4.2-py3-none-any.whl", hash = "sha256:89885494684c929d9191c57aa27502afc87a579be5cdd3225c77c463ea043745"}, 863 | {file = "tzlocal-4.2.tar.gz", hash = "sha256:ee5842fa3a795f023514ac2d801c4a81d1743bbe642e3940143326b3a00addd7"}, 864 | ] 865 | urllib3 = [] 866 | wcwidth = [ 867 | {file = "wcwidth-0.2.5-py2.py3-none-any.whl", hash = "sha256:beb4802a9cebb9144e99086eff703a642a13d6a0052920003a230f3294bbe784"}, 868 | {file = "wcwidth-0.2.5.tar.gz", hash = "sha256:c4d647b99872929fdb7bdcaa4fbe7f01413ed3d98077df798530e5b04f116c83"}, 869 | ] 870 | wrapt = [ 871 | {file = "wrapt-1.14.1-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:1b376b3f4896e7930f1f772ac4b064ac12598d1c38d04907e696cc4d794b43d3"}, 872 | {file = "wrapt-1.14.1-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:903500616422a40a98a5a3c4ff4ed9d0066f3b4c951fa286018ecdf0750194ef"}, 873 | {file = "wrapt-1.14.1-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:5a9a0d155deafd9448baff28c08e150d9b24ff010e899311ddd63c45c2445e28"}, 874 | {file = "wrapt-1.14.1-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:ddaea91abf8b0d13443f6dac52e89051a5063c7d014710dcb4d4abb2ff811a59"}, 875 | {file = "wrapt-1.14.1-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:36f582d0c6bc99d5f39cd3ac2a9062e57f3cf606ade29a0a0d6b323462f4dd87"}, 876 | {file = "wrapt-1.14.1-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:7ef58fb89674095bfc57c4069e95d7a31cfdc0939e2a579882ac7d55aadfd2a1"}, 877 | {file = "wrapt-1.14.1-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:e2f83e18fe2f4c9e7db597e988f72712c0c3676d337d8b101f6758107c42425b"}, 878 | {file = "wrapt-1.14.1-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:ee2b1b1769f6707a8a445162ea16dddf74285c3964f605877a20e38545c3c462"}, 879 | {file = "wrapt-1.14.1-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:833b58d5d0b7e5b9832869f039203389ac7cbf01765639c7309fd50ef619e0b1"}, 880 | {file = "wrapt-1.14.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:80bb5c256f1415f747011dc3604b59bc1f91c6e7150bd7db03b19170ee06b320"}, 881 | {file = "wrapt-1.14.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:07f7a7d0f388028b2df1d916e94bbb40624c59b48ecc6cbc232546706fac74c2"}, 882 | {file = "wrapt-1.14.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:02b41b633c6261feff8ddd8d11c711df6842aba629fdd3da10249a53211a72c4"}, 883 | {file = "wrapt-1.14.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2fe803deacd09a233e4762a1adcea5db5d31e6be577a43352936179d14d90069"}, 884 | {file = "wrapt-1.14.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:257fd78c513e0fb5cdbe058c27a0624c9884e735bbd131935fd49e9fe719d310"}, 885 | {file = "wrapt-1.14.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:4fcc4649dc762cddacd193e6b55bc02edca674067f5f98166d7713b193932b7f"}, 886 | {file = "wrapt-1.14.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:11871514607b15cfeb87c547a49bca19fde402f32e2b1c24a632506c0a756656"}, 887 | {file = "wrapt-1.14.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:8ad85f7f4e20964db4daadcab70b47ab05c7c1cf2a7c1e51087bfaa83831854c"}, 888 | {file = "wrapt-1.14.1-cp310-cp310-win32.whl", hash = "sha256:a9a52172be0b5aae932bef82a79ec0a0ce87288c7d132946d645eba03f0ad8a8"}, 889 | {file = "wrapt-1.14.1-cp310-cp310-win_amd64.whl", hash = "sha256:6d323e1554b3d22cfc03cd3243b5bb815a51f5249fdcbb86fda4bf62bab9e164"}, 890 | {file = "wrapt-1.14.1-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:43ca3bbbe97af00f49efb06e352eae40434ca9d915906f77def219b88e85d907"}, 891 | {file = "wrapt-1.14.1-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:6b1a564e6cb69922c7fe3a678b9f9a3c54e72b469875aa8018f18b4d1dd1adf3"}, 892 | {file = "wrapt-1.14.1-cp35-cp35m-manylinux2010_i686.whl", hash = "sha256:00b6d4ea20a906c0ca56d84f93065b398ab74b927a7a3dbd470f6fc503f95dc3"}, 893 | {file = "wrapt-1.14.1-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:a85d2b46be66a71bedde836d9e41859879cc54a2a04fad1191eb50c2066f6e9d"}, 894 | {file = "wrapt-1.14.1-cp35-cp35m-win32.whl", hash = "sha256:dbcda74c67263139358f4d188ae5faae95c30929281bc6866d00573783c422b7"}, 895 | {file = "wrapt-1.14.1-cp35-cp35m-win_amd64.whl", hash = "sha256:b21bb4c09ffabfa0e85e3a6b623e19b80e7acd709b9f91452b8297ace2a8ab00"}, 896 | {file = "wrapt-1.14.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:9e0fd32e0148dd5dea6af5fee42beb949098564cc23211a88d799e434255a1f4"}, 897 | {file = "wrapt-1.14.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9736af4641846491aedb3c3f56b9bc5568d92b0692303b5a305301a95dfd38b1"}, 898 | {file = "wrapt-1.14.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5b02d65b9ccf0ef6c34cba6cf5bf2aab1bb2f49c6090bafeecc9cd81ad4ea1c1"}, 899 | {file = "wrapt-1.14.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21ac0156c4b089b330b7666db40feee30a5d52634cc4560e1905d6529a3897ff"}, 900 | {file = "wrapt-1.14.1-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:9f3e6f9e05148ff90002b884fbc2a86bd303ae847e472f44ecc06c2cd2fcdb2d"}, 901 | {file = "wrapt-1.14.1-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:6e743de5e9c3d1b7185870f480587b75b1cb604832e380d64f9504a0535912d1"}, 902 | {file = "wrapt-1.14.1-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:d79d7d5dc8a32b7093e81e97dad755127ff77bcc899e845f41bf71747af0c569"}, 903 | {file = "wrapt-1.14.1-cp36-cp36m-win32.whl", hash = "sha256:81b19725065dcb43df02b37e03278c011a09e49757287dca60c5aecdd5a0b8ed"}, 904 | {file = "wrapt-1.14.1-cp36-cp36m-win_amd64.whl", hash = "sha256:b014c23646a467558be7da3d6b9fa409b2c567d2110599b7cf9a0c5992b3b471"}, 905 | {file = "wrapt-1.14.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:88bd7b6bd70a5b6803c1abf6bca012f7ed963e58c68d76ee20b9d751c74a3248"}, 906 | {file = "wrapt-1.14.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b5901a312f4d14c59918c221323068fad0540e34324925c8475263841dbdfe68"}, 907 | {file = "wrapt-1.14.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d77c85fedff92cf788face9bfa3ebaa364448ebb1d765302e9af11bf449ca36d"}, 908 | {file = "wrapt-1.14.1-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8d649d616e5c6a678b26d15ece345354f7c2286acd6db868e65fcc5ff7c24a77"}, 909 | {file = "wrapt-1.14.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:7d2872609603cb35ca513d7404a94d6d608fc13211563571117046c9d2bcc3d7"}, 910 | {file = "wrapt-1.14.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:ee6acae74a2b91865910eef5e7de37dc6895ad96fa23603d1d27ea69df545015"}, 911 | {file = "wrapt-1.14.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:2b39d38039a1fdad98c87279b48bc5dce2c0ca0d73483b12cb72aa9609278e8a"}, 912 | {file = "wrapt-1.14.1-cp37-cp37m-win32.whl", hash = "sha256:60db23fa423575eeb65ea430cee741acb7c26a1365d103f7b0f6ec412b893853"}, 913 | {file = "wrapt-1.14.1-cp37-cp37m-win_amd64.whl", hash = "sha256:709fe01086a55cf79d20f741f39325018f4df051ef39fe921b1ebe780a66184c"}, 914 | {file = "wrapt-1.14.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:8c0ce1e99116d5ab21355d8ebe53d9460366704ea38ae4d9f6933188f327b456"}, 915 | {file = "wrapt-1.14.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:e3fb1677c720409d5f671e39bac6c9e0e422584e5f518bfd50aa4cbbea02433f"}, 916 | {file = "wrapt-1.14.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:642c2e7a804fcf18c222e1060df25fc210b9c58db7c91416fb055897fc27e8cc"}, 917 | {file = "wrapt-1.14.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7b7c050ae976e286906dd3f26009e117eb000fb2cf3533398c5ad9ccc86867b1"}, 918 | {file = "wrapt-1.14.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ef3f72c9666bba2bab70d2a8b79f2c6d2c1a42a7f7e2b0ec83bb2f9e383950af"}, 919 | {file = "wrapt-1.14.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:01c205616a89d09827986bc4e859bcabd64f5a0662a7fe95e0d359424e0e071b"}, 920 | {file = "wrapt-1.14.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:5a0f54ce2c092aaf439813735584b9537cad479575a09892b8352fea5e988dc0"}, 921 | {file = "wrapt-1.14.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:2cf71233a0ed05ccdabe209c606fe0bac7379fdcf687f39b944420d2a09fdb57"}, 922 | {file = "wrapt-1.14.1-cp38-cp38-win32.whl", hash = "sha256:aa31fdcc33fef9eb2552cbcbfee7773d5a6792c137b359e82879c101e98584c5"}, 923 | {file = "wrapt-1.14.1-cp38-cp38-win_amd64.whl", hash = "sha256:d1967f46ea8f2db647c786e78d8cc7e4313dbd1b0aca360592d8027b8508e24d"}, 924 | {file = "wrapt-1.14.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3232822c7d98d23895ccc443bbdf57c7412c5a65996c30442ebe6ed3df335383"}, 925 | {file = "wrapt-1.14.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:988635d122aaf2bdcef9e795435662bcd65b02f4f4c1ae37fbee7401c440b3a7"}, 926 | {file = "wrapt-1.14.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9cca3c2cdadb362116235fdbd411735de4328c61425b0aa9f872fd76d02c4e86"}, 927 | {file = "wrapt-1.14.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d52a25136894c63de15a35bc0bdc5adb4b0e173b9c0d07a2be9d3ca64a332735"}, 928 | {file = "wrapt-1.14.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:40e7bc81c9e2b2734ea4bc1aceb8a8f0ceaac7c5299bc5d69e37c44d9081d43b"}, 929 | {file = "wrapt-1.14.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:b9b7a708dd92306328117d8c4b62e2194d00c365f18eff11a9b53c6f923b01e3"}, 930 | {file = "wrapt-1.14.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:6a9a25751acb379b466ff6be78a315e2b439d4c94c1e99cb7266d40a537995d3"}, 931 | {file = "wrapt-1.14.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:34aa51c45f28ba7f12accd624225e2b1e5a3a45206aa191f6f9aac931d9d56fe"}, 932 | {file = "wrapt-1.14.1-cp39-cp39-win32.whl", hash = "sha256:dee0ce50c6a2dd9056c20db781e9c1cfd33e77d2d569f5d1d9321c641bb903d5"}, 933 | {file = "wrapt-1.14.1-cp39-cp39-win_amd64.whl", hash = "sha256:dee60e1de1898bde3b238f18340eec6148986da0455d8ba7848d50470a7a32fb"}, 934 | {file = "wrapt-1.14.1.tar.gz", hash = "sha256:380a85cf89e0e69b7cfbe2ea9f765f004ff419f34194018a6827ac0e3edfed4d"}, 935 | ] 936 | --------------------------------------------------------------------------------