diff --git a/.replit b/.replit new file mode 100644 index 0000000..90cbc7e --- /dev/null +++ b/.replit @@ -0,0 +1,107 @@ +# The command that runs the program. +run = ["python3", "main.py"] +# The primary language of the repl. There can be others, though! +language = "python3" +# The main file, which will be shown by default in the editor. +entrypoint = "main.py" +# A list of globs that specify which files and directories should +# be hidden in the workspace. +hidden = ["venv", ".config", "**/__pycache__", "**/.mypy_cache", "**/*.pyc"] + +# Specifies which nix channel to use when building the environment. +[nix] +channel = "stable-21_11" + +# Per-language configuration: python3 +[languages.python3] +# Treats all files that end with `.py` as Python. +pattern = "**/*.py" +# Tells the workspace editor to syntax-highlight these files as +# Python. +syntax = "python" + + # The command needed to start the Language Server Protocol. For + # linting and formatting. + [languages.python3.languageServer] + start = ["pyls"] + +# The command to start the interpreter. +[interpreter] + [interpreter.command] + args = [ + "stderred", + "--", + "prybar-python3", + "-q", + "--ps1", + "\u0001\u001b[33m\u0002\u0001\u001b[00m\u0002 ", + "-i", + ] + +# The environment variables needed to correctly start Python and use the +# package proxy. +[env] +VIRTUAL_ENV = "/home/runner/${REPL_SLUG}/venv" +PATH = "${VIRTUAL_ENV}/bin" +PYTHONPATH="${VIRTUAL_ENV}/lib/python3.8/site-packages" +REPLIT_POETRY_PYPI_REPOSITORY="https://package-proxy.replit.com/pypi/" +MPLBACKEND="TkAgg" + +# Enable unit tests. This is only supported for a few languages. +[unitTest] +language = "python3" + +# Add a debugger! +[debugger] +support = true + + # How to start the debugger. + [debugger.interactive] + transport = "localhost:0" + startCommand = ["dap-python", "main.py"] + + # How to communicate with the debugger. + [debugger.interactive.integratedAdapter] + dapTcpAddress = "localhost:0" + + # How to tell the debugger to start a debugging session. + [debugger.interactive.initializeMessage] + command = "initialize" + type = "request" + + [debugger.interactive.initializeMessage.arguments] + adapterID = "debugpy" + clientID = "replit" + clientName = "replit.com" + columnsStartAt1 = true + linesStartAt1 = true + locale = "en-us" + pathFormat = "path" + supportsInvalidatedEvent = true + supportsProgressReporting = true + supportsRunInTerminalRequest = true + supportsVariablePaging = true + supportsVariableType = true + + # How to tell the debugger to start the debuggee application. + [debugger.interactive.launchMessage] + command = "attach" + type = "request" + + [debugger.interactive.launchMessage.arguments] + logging = {} + +# Configures the packager. +[packager] +# Search packages in PyPI. +language = "python3" +# Never attempt to install `unit_tests`. If there are packages that are being +# guessed wrongly, add them here. +ignoredPackages = ["unit_tests"] + + [packager.features] + enabledForHosting = false + # Enable searching packages from the sidebar. + packageSearch = true + # Enable guessing what packages are needed from the code. + guessImports = true diff --git a/__pycache__/html_page.cpython-38.pyc b/__pycache__/html_page.cpython-38.pyc new file mode 100644 index 0000000..ca089e4 Binary files /dev/null and b/__pycache__/html_page.cpython-38.pyc differ diff --git a/__pycache__/keep_alive.cpython-38.pyc b/__pycache__/keep_alive.cpython-38.pyc new file mode 100644 index 0000000..fbe666a Binary files /dev/null and b/__pycache__/keep_alive.cpython-38.pyc differ diff --git a/docs/README.md b/docs/README.md index 2cbdf44..5fed330 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,12 +1,12 @@ -# Insert Title +# MiBot -[![GitHub license](https://img.shields.io/github/license/clcmo/web?style=for-the-badge)](https://github.com/clcmo/web) -[![GitHub stars](https://img.shields.io/github/stars/clcmo/web?style=for-the-badge)](https://github.com/clcmo/web/stargazers) -[![GitHub forks](https://img.shields.io/github/forks/clcmo/web?style=for-the-badge)](https://github.com/clcmo/web/network) -[![GitHub issues](https://img.shields.io/github/issues/clcmo/web?style=for-the-badge)](https://github.com/clcmo/web/issues) +[![GitHub license](https://img.shields.io/github/license/clcmo/MiBot?style=for-the-badge)](https://github.com/clcmo/MiBot) +[![GitHub stars](https://img.shields.io/github/stars/clcmo/MiBot?style=for-the-badge)](https://github.com/clcmo/MiBot/stargazers) +[![GitHub forks](https://img.shields.io/github/forks/clcmo/MiBot?style=for-the-badge)](https://github.com/clcmo/MiBot/network) +[![GitHub issues](https://img.shields.io/github/issues/clcmo/MiBot?style=for-the-badge)](https://github.com/clcmo/MiBot/issues) [![GitHub donate](https://img.shields.io/github/sponsors/clcmo?color=pink&style=for-the-badge)](https://github.com/sponsors/clcmo) -Description about the project +Create a Motivational Bot for Discord, using the knowledge acquired from the [Free Bootcamp tutorial](https://www.freecodecamp.org/portuguese/news/tutorial-de-criacao-de-bot-para-o-discord-em-python/). Insert screenshot to inform what the visualization will be like diff --git a/keep_alive.py b/keep_alive.py new file mode 100644 index 0000000..231f933 --- /dev/null +++ b/keep_alive.py @@ -0,0 +1,16 @@ +from flask import Flask +from threading import Thread +import webbrowser + +app = Flask('') + +@app.route('/') +def home(): + return "Hello, It Works!" + +def run(): + app.run(host='0.0.0.0',port=8080) + +def keep_alive(): + t = Thread(target=run) + t.start() diff --git a/main.py b/main.py new file mode 100644 index 0000000..bcd238f --- /dev/null +++ b/main.py @@ -0,0 +1,105 @@ +import os +import discord +import requests +import json +import random +from replit import db +from keep_alive import keep_alive + +my_secret = os.getenv('TOKEN') + +client = discord.Client() + +sad_words = ["sad", "depressed", "unhappy", "angry", "miserable"] + +starter_encouragements = [ + "Cheer up!", "Hang in there.", "You are a great person / bot!" +] + +cool_words = ["happy", "kind", "cheer", "great", "beautiful"] + +if "responding" not in db.keys(): + db["responding"] = True + + +def get_quote(): + response = requests.get("https://zenquotes.io/api/random") + json_data = json.loads(response.text) + quote = json_data[0]["q"] + " -" + json_data[0]["a"] + return (quote) + + +def update_encouragements(encouraging_message): + if "encouragements" in db.keys(): + encouragements = db["encouragements"] + encouragements.append(encouraging_message) + db["encouragements"] = encouragements + else: + db["encouragements"] = [encouraging_message] + + +def delete_encouragment(index): + encouragements = db["encouragements"] + if len(encouragements) > index: + del encouragements[index] + db["encouragements"] = encouragements + + +@client.event +async def on_ready(): + print("We have logged in as {0.user}".format(client)) + + +@client.event +async def on_message(message): + if message.author == client.user: + return + + msg = message.content + + if msg.startswith("$inspire"): + quote = get_quote() + await message.channel.send(quote) + + if db["responding"]: + options = starter_encouragements + if "encouragements" in db.keys(): + options = options + db["encouragements"] + + if any(word in msg for word in sad_words): + await message.channel.send(random.choice(options)) + if any(word in msg for word in cool_words): + await message.channel.send(random.choice(options)) + + if msg.startswith("$new"): + encouraging_message = msg.split("$new ", 1)[1] + update_encouragements(encouraging_message) + await message.channel.send("New encouraging message added.") + + if msg.startswith("$del"): + encouragements = [] + if "encouragements" in db.keys(): + index = int(msg.split("$del", 1)[1]) + delete_encouragment(index) + encouragements = db["encouragements"] + await message.channel.send(encouragements) + + if msg.startswith("$list"): + encouragements = [] + if "encouragements" in db.keys(): + encouragements = db["encouragements"] + await message.channel.send(encouragements) + + if msg.startswith("$responding"): + value = msg.split("$responding ", 1)[1] + + if value.lower() == "true": + db["responding"] = True + await message.channel.send("Responding is on.") + else: + db["responding"] = False + await message.channel.send("Responding is off.") + + +keep_alive() +client.run(my_secret) \ No newline at end of file diff --git a/poetry.lock b/poetry.lock new file mode 100644 index 0000000..26f685d --- /dev/null +++ b/poetry.lock @@ -0,0 +1,579 @@ +[[package]] +name = "aiohttp" +version = "3.7.4.post0" +description = "Async http client/server framework (asyncio)" +category = "main" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +async-timeout = ">=3.0,<4.0" +attrs = ">=17.3.0" +chardet = ">=2.0,<5.0" +multidict = ">=4.5,<7.0" +typing-extensions = ">=3.6.5" +yarl = ">=1.0,<2.0" + +[package.extras] +speedups = ["aiodns", "brotlipy", "cchardet"] + +[[package]] +name = "async-timeout" +version = "3.0.1" +description = "Timeout context manager for asyncio programs" +category = "main" +optional = false +python-versions = ">=3.5.3" + +[[package]] +name = "attrs" +version = "21.4.0" +description = "Classes Without Boilerplate" +category = "main" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" + +[package.extras] +dev = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "zope.interface", "furo", "sphinx", "sphinx-notfound-page", "pre-commit", "cloudpickle"] +docs = ["furo", "sphinx", "zope.interface", "sphinx-notfound-page"] +tests = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "zope.interface", "cloudpickle"] +tests_no_zope = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "cloudpickle"] + +[[package]] +name = "certifi" +version = "2021.10.8" +description = "Python package for providing Mozilla's CA Bundle." +category = "main" +optional = false +python-versions = "*" + +[[package]] +name = "chardet" +version = "4.0.0" +description = "Universal encoding detector for Python 2 and 3" +category = "main" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" + +[[package]] +name = "charset-normalizer" +version = "2.0.12" +description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." +category = "main" +optional = false +python-versions = ">=3.5.0" + +[package.extras] +unicode_backport = ["unicodedata2"] + +[[package]] +name = "click" +version = "8.0.4" +description = "Composable command line interface toolkit" +category = "main" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +colorama = {version = "*", markers = "platform_system == \"Windows\""} + +[[package]] +name = "colorama" +version = "0.4.4" +description = "Cross-platform colored terminal text." +category = "main" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" + +[[package]] +name = "discord" +version = "1.7.3" +description = "A mirror package for discord.py. Please install that instead." +category = "main" +optional = false +python-versions = "*" + +[package.dependencies] +"discord.py" = ">=1.7.3" + +[[package]] +name = "discord.py" +version = "1.7.3" +description = "A Python wrapper for the Discord API" +category = "main" +optional = false +python-versions = ">=3.5.3" + +[package.dependencies] +aiohttp = ">=3.6.0,<3.8.0" + +[package.extras] +docs = ["sphinx (==3.0.3)", "sphinxcontrib-trio (==1.1.2)", "sphinxcontrib-websupport"] +voice = ["PyNaCl (>=1.3.0,<1.5)"] + +[[package]] +name = "flask" +version = "2.0.3" +description = "A simple framework for building complex web applications." +category = "main" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +click = ">=7.1.2" +itsdangerous = ">=2.0" +Jinja2 = ">=3.0" +Werkzeug = ">=2.0" + +[package.extras] +async = ["asgiref (>=3.2)"] +dotenv = ["python-dotenv"] + +[[package]] +name = "idna" +version = "3.3" +description = "Internationalized Domain Names in Applications (IDNA)" +category = "main" +optional = false +python-versions = ">=3.5" + +[[package]] +name = "itsdangerous" +version = "2.1.1" +description = "Safely pass data to untrusted environments and back." +category = "main" +optional = false +python-versions = ">=3.7" + +[[package]] +name = "jinja2" +version = "3.0.3" +description = "A very fast and expressive template engine." +category = "main" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +MarkupSafe = ">=2.0" + +[package.extras] +i18n = ["Babel (>=2.7)"] + +[[package]] +name = "markupsafe" +version = "2.1.1" +description = "Safely add untrusted strings to HTML/XML markup." +category = "main" +optional = false +python-versions = ">=3.7" + +[[package]] +name = "multidict" +version = "6.0.2" +description = "multidict implementation" +category = "main" +optional = false +python-versions = ">=3.7" + +[[package]] +name = "numpy" +version = "1.22.3" +description = "NumPy is the fundamental package for array computing with Python." +category = "main" +optional = false +python-versions = ">=3.8" + +[[package]] +name = "replit" +version = "3.2.4" +description = "A library for interacting with features of repl.it" +category = "main" +optional = false +python-versions = ">=3.8,<4.0" + +[package.dependencies] +aiohttp = ">=3.6.2,<4.0.0" +Flask = ">=2.0.0,<3.0.0" +requests = ">=2.25.1,<3.0.0" +typing_extensions = ">=3.7.4,<4.0.0" +Werkzeug = ">=2.0.0,<3.0.0" + +[[package]] +name = "requests" +version = "2.27.1" +description = "Python HTTP for Humans." +category = "main" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" + +[package.dependencies] +certifi = ">=2017.4.17" +charset-normalizer = {version = ">=2.0.0,<2.1.0", markers = "python_version >= \"3\""} +idna = {version = ">=2.5,<4", markers = "python_version >= \"3\""} +urllib3 = ">=1.21.1,<1.27" + +[package.extras] +socks = ["PySocks (>=1.5.6,!=1.5.7)", "win-inet-pton"] +use_chardet_on_py3 = ["chardet (>=3.0.2,<5)"] + +[[package]] +name = "typing-extensions" +version = "3.10.0.2" +description = "Backported and Experimental Type Hints for Python 3.5+" +category = "main" +optional = false +python-versions = "*" + +[[package]] +name = "urllib3" +version = "1.26.8" +description = "HTTP library with thread-safe connection pooling, file post, and more." +category = "main" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4" + +[package.extras] +brotli = ["brotlipy (>=0.6.0)"] +secure = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "certifi", "ipaddress"] +socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] + +[[package]] +name = "werkzeug" +version = "2.0.3" +description = "The comprehensive WSGI web application library." +category = "main" +optional = false +python-versions = ">=3.6" + +[package.extras] +watchdog = ["watchdog"] + +[[package]] +name = "yarl" +version = "1.7.2" +description = "Yet another URL library" +category = "main" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +idna = ">=2.0" +multidict = ">=4.0" + +[metadata] +lock-version = "1.1" +python-versions = ">=3.8.0,<3.9" +content-hash = "4a16182a3e61b3d3fff7acd72cf2de4218edae1cf74c6b48bdd196e6be9c2a88" + +[metadata.files] +aiohttp = [ + {file = "aiohttp-3.7.4.post0-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:3cf75f7cdc2397ed4442594b935a11ed5569961333d49b7539ea741be2cc79d5"}, + {file = "aiohttp-3.7.4.post0-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:4b302b45040890cea949ad092479e01ba25911a15e648429c7c5aae9650c67a8"}, + {file = "aiohttp-3.7.4.post0-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:fe60131d21b31fd1a14bd43e6bb88256f69dfc3188b3a89d736d6c71ed43ec95"}, + {file = "aiohttp-3.7.4.post0-cp36-cp36m-manylinux2014_i686.whl", hash = "sha256:393f389841e8f2dfc86f774ad22f00923fdee66d238af89b70ea314c4aefd290"}, + {file = "aiohttp-3.7.4.post0-cp36-cp36m-manylinux2014_ppc64le.whl", hash = "sha256:c6e9dcb4cb338d91a73f178d866d051efe7c62a7166653a91e7d9fb18274058f"}, + {file = "aiohttp-3.7.4.post0-cp36-cp36m-manylinux2014_s390x.whl", hash = "sha256:5df68496d19f849921f05f14f31bd6ef53ad4b00245da3195048c69934521809"}, + {file = "aiohttp-3.7.4.post0-cp36-cp36m-manylinux2014_x86_64.whl", hash = "sha256:0563c1b3826945eecd62186f3f5c7d31abb7391fedc893b7e2b26303b5a9f3fe"}, + {file = "aiohttp-3.7.4.post0-cp36-cp36m-win32.whl", hash = "sha256:3d78619672183be860b96ed96f533046ec97ca067fd46ac1f6a09cd9b7484287"}, + {file = "aiohttp-3.7.4.post0-cp36-cp36m-win_amd64.whl", hash = "sha256:f705e12750171c0ab4ef2a3c76b9a4024a62c4103e3a55dd6f99265b9bc6fcfc"}, + {file = "aiohttp-3.7.4.post0-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:230a8f7e24298dea47659251abc0fd8b3c4e38a664c59d4b89cca7f6c09c9e87"}, + {file = "aiohttp-3.7.4.post0-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:2e19413bf84934d651344783c9f5e22dee452e251cfd220ebadbed2d9931dbf0"}, + {file = "aiohttp-3.7.4.post0-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:e4b2b334e68b18ac9817d828ba44d8fcb391f6acb398bcc5062b14b2cbeac970"}, + {file = "aiohttp-3.7.4.post0-cp37-cp37m-manylinux2014_i686.whl", hash = "sha256:d012ad7911653a906425d8473a1465caa9f8dea7fcf07b6d870397b774ea7c0f"}, + {file = "aiohttp-3.7.4.post0-cp37-cp37m-manylinux2014_ppc64le.whl", hash = "sha256:40eced07f07a9e60e825554a31f923e8d3997cfc7fb31dbc1328c70826e04cde"}, + {file = "aiohttp-3.7.4.post0-cp37-cp37m-manylinux2014_s390x.whl", hash = "sha256:209b4a8ee987eccc91e2bd3ac36adee0e53a5970b8ac52c273f7f8fd4872c94c"}, + {file = "aiohttp-3.7.4.post0-cp37-cp37m-manylinux2014_x86_64.whl", hash = "sha256:14762875b22d0055f05d12abc7f7d61d5fd4fe4642ce1a249abdf8c700bf1fd8"}, + {file = "aiohttp-3.7.4.post0-cp37-cp37m-win32.whl", hash = "sha256:7615dab56bb07bff74bc865307aeb89a8bfd9941d2ef9d817b9436da3a0ea54f"}, + {file = "aiohttp-3.7.4.post0-cp37-cp37m-win_amd64.whl", hash = "sha256:d9e13b33afd39ddeb377eff2c1c4f00544e191e1d1dee5b6c51ddee8ea6f0cf5"}, + {file = "aiohttp-3.7.4.post0-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:547da6cacac20666422d4882cfcd51298d45f7ccb60a04ec27424d2f36ba3eaf"}, + {file = "aiohttp-3.7.4.post0-cp38-cp38-manylinux1_i686.whl", hash = "sha256:af9aa9ef5ba1fd5b8c948bb11f44891968ab30356d65fd0cc6707d989cd521df"}, + {file = "aiohttp-3.7.4.post0-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:64322071e046020e8797117b3658b9c2f80e3267daec409b350b6a7a05041213"}, + {file = "aiohttp-3.7.4.post0-cp38-cp38-manylinux2014_i686.whl", hash = "sha256:bb437315738aa441251214dad17428cafda9cdc9729499f1d6001748e1d432f4"}, + {file = "aiohttp-3.7.4.post0-cp38-cp38-manylinux2014_ppc64le.whl", hash = "sha256:e54962802d4b8b18b6207d4a927032826af39395a3bd9196a5af43fc4e60b009"}, + {file = "aiohttp-3.7.4.post0-cp38-cp38-manylinux2014_s390x.whl", hash = "sha256:a00bb73540af068ca7390e636c01cbc4f644961896fa9363154ff43fd37af2f5"}, + {file = "aiohttp-3.7.4.post0-cp38-cp38-manylinux2014_x86_64.whl", hash = "sha256:79ebfc238612123a713a457d92afb4096e2148be17df6c50fb9bf7a81c2f8013"}, + {file = "aiohttp-3.7.4.post0-cp38-cp38-win32.whl", hash = "sha256:515dfef7f869a0feb2afee66b957cc7bbe9ad0cdee45aec7fdc623f4ecd4fb16"}, + {file = "aiohttp-3.7.4.post0-cp38-cp38-win_amd64.whl", hash = "sha256:114b281e4d68302a324dd33abb04778e8557d88947875cbf4e842c2c01a030c5"}, + {file = "aiohttp-3.7.4.post0-cp39-cp39-macosx_10_14_x86_64.whl", hash = "sha256:7b18b97cf8ee5452fa5f4e3af95d01d84d86d32c5e2bfa260cf041749d66360b"}, + {file = "aiohttp-3.7.4.post0-cp39-cp39-manylinux1_i686.whl", hash = "sha256:15492a6368d985b76a2a5fdd2166cddfea5d24e69eefed4630cbaae5c81d89bd"}, + {file = "aiohttp-3.7.4.post0-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:bdb230b4943891321e06fc7def63c7aace16095be7d9cf3b1e01be2f10fba439"}, + {file = "aiohttp-3.7.4.post0-cp39-cp39-manylinux2014_i686.whl", hash = "sha256:cffe3ab27871bc3ea47df5d8f7013945712c46a3cc5a95b6bee15887f1675c22"}, + {file = "aiohttp-3.7.4.post0-cp39-cp39-manylinux2014_ppc64le.whl", hash = "sha256:f881853d2643a29e643609da57b96d5f9c9b93f62429dcc1cbb413c7d07f0e1a"}, + {file = "aiohttp-3.7.4.post0-cp39-cp39-manylinux2014_s390x.whl", hash = "sha256:a5ca29ee66f8343ed336816c553e82d6cade48a3ad702b9ffa6125d187e2dedb"}, + {file = "aiohttp-3.7.4.post0-cp39-cp39-manylinux2014_x86_64.whl", hash = "sha256:17c073de315745a1510393a96e680d20af8e67e324f70b42accbd4cb3315c9fb"}, + {file = "aiohttp-3.7.4.post0-cp39-cp39-win32.whl", hash = "sha256:932bb1ea39a54e9ea27fc9232163059a0b8855256f4052e776357ad9add6f1c9"}, + {file = "aiohttp-3.7.4.post0-cp39-cp39-win_amd64.whl", hash = "sha256:02f46fc0e3c5ac58b80d4d56eb0a7c7d97fcef69ace9326289fb9f1955e65cfe"}, + {file = "aiohttp-3.7.4.post0.tar.gz", hash = "sha256:493d3299ebe5f5a7c66b9819eacdcfbbaaf1a8e84911ddffcdc48888497afecf"}, +] +async-timeout = [ + {file = "async-timeout-3.0.1.tar.gz", hash = "sha256:0c3c816a028d47f659d6ff5c745cb2acf1f966da1fe5c19c77a70282b25f4c5f"}, + {file = "async_timeout-3.0.1-py3-none-any.whl", hash = "sha256:4291ca197d287d274d0b6cb5d6f8f8f82d434ed288f962539ff18cc9012f9ea3"}, +] +attrs = [ + {file = "attrs-21.4.0-py2.py3-none-any.whl", hash = "sha256:2d27e3784d7a565d36ab851fe94887c5eccd6a463168875832a1be79c82828b4"}, + {file = "attrs-21.4.0.tar.gz", hash = "sha256:626ba8234211db98e869df76230a137c4c40a12d72445c45d5f5b716f076e2fd"}, +] +certifi = [ + {file = "certifi-2021.10.8-py2.py3-none-any.whl", hash = "sha256:d62a0163eb4c2344ac042ab2bdf75399a71a2d8c7d47eac2e2ee91b9d6339569"}, + {file = "certifi-2021.10.8.tar.gz", hash = "sha256:78884e7c1d4b00ce3cea67b44566851c4343c120abd683433ce934a68ea58872"}, +] +chardet = [ + {file = "chardet-4.0.0-py2.py3-none-any.whl", hash = "sha256:f864054d66fd9118f2e67044ac8981a54775ec5b67aed0441892edb553d21da5"}, + {file = "chardet-4.0.0.tar.gz", hash = "sha256:0d6f53a15db4120f2b08c94f11e7d93d2c911ee118b6b30a04ec3ee8310179fa"}, +] +charset-normalizer = [ + {file = "charset-normalizer-2.0.12.tar.gz", hash = "sha256:2857e29ff0d34db842cd7ca3230549d1a697f96ee6d3fb071cfa6c7393832597"}, + {file = "charset_normalizer-2.0.12-py3-none-any.whl", hash = "sha256:6881edbebdb17b39b4eaaa821b438bf6eddffb4468cf344f09f89def34a8b1df"}, +] +click = [ + {file = "click-8.0.4-py3-none-any.whl", hash = "sha256:6a7a62563bbfabfda3a38f3023a1db4a35978c0abd76f6c9605ecd6554d6d9b1"}, + {file = "click-8.0.4.tar.gz", hash = "sha256:8458d7b1287c5fb128c90e23381cf99dcde74beaf6c7ff6384ce84d6fe090adb"}, +] +colorama = [ + {file = "colorama-0.4.4-py2.py3-none-any.whl", hash = "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"}, + {file = "colorama-0.4.4.tar.gz", hash = "sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b"}, +] +discord = [ + {file = "discord-1.7.3-py3-none-any.whl", hash = "sha256:248d728356e149c818a81b94659047a19305ea1623d4810bbb342f6b7df55f36"}, + {file = "discord-1.7.3.tar.gz", hash = "sha256:846dd3d66888c2e0a8bd9120d8778a0fe088c003a7f6451668497f14e322a304"}, +] +"discord.py" = [ + {file = "discord.py-1.7.3-py3-none-any.whl", hash = "sha256:c6f64db136de0e18e090f6752ea68bdd4ab0a61b82dfe7acecefa22d6477bb0c"}, + {file = "discord.py-1.7.3.tar.gz", hash = "sha256:462cd0fe307aef8b29cbfa8dd613e548ae4b2cb581d46da9ac0d46fb6ea19408"}, +] +flask = [ + {file = "Flask-2.0.3-py3-none-any.whl", hash = "sha256:59da8a3170004800a2837844bfa84d49b022550616070f7cb1a659682b2e7c9f"}, + {file = "Flask-2.0.3.tar.gz", hash = "sha256:e1120c228ca2f553b470df4a5fa927ab66258467526069981b3eb0a91902687d"}, +] +idna = [ + {file = "idna-3.3-py3-none-any.whl", hash = "sha256:84d9dd047ffa80596e0f246e2eab0b391788b0503584e8945f2368256d2735ff"}, + {file = "idna-3.3.tar.gz", hash = "sha256:9d643ff0a55b762d5cdb124b8eaa99c66322e2157b69160bc32796e824360e6d"}, +] +itsdangerous = [ + {file = "itsdangerous-2.1.1-py3-none-any.whl", hash = "sha256:935642cd4b987cdbee7210080004033af76306757ff8b4c0a506a4b6e06f02cf"}, + {file = "itsdangerous-2.1.1.tar.gz", hash = "sha256:7b7d3023cd35d9cb0c1fd91392f8c95c6fa02c59bf8ad64b8849be3401b95afb"}, +] +jinja2 = [ + {file = "Jinja2-3.0.3-py3-none-any.whl", hash = "sha256:077ce6014f7b40d03b47d1f1ca4b0fc8328a692bd284016f806ed0eaca390ad8"}, + {file = "Jinja2-3.0.3.tar.gz", hash = "sha256:611bb273cd68f3b993fabdc4064fc858c5b47a973cb5aa7999ec1ba405c87cd7"}, +] +markupsafe = [ + {file = "MarkupSafe-2.1.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:86b1f75c4e7c2ac2ccdaec2b9022845dbb81880ca318bb7a0a01fbf7813e3812"}, + {file = "MarkupSafe-2.1.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f121a1420d4e173a5d96e47e9a0c0dcff965afdf1626d28de1460815f7c4ee7a"}, + {file = "MarkupSafe-2.1.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a49907dd8420c5685cfa064a1335b6754b74541bbb3706c259c02ed65b644b3e"}, + {file = "MarkupSafe-2.1.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:10c1bfff05d95783da83491be968e8fe789263689c02724e0c691933c52994f5"}, + {file = "MarkupSafe-2.1.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b7bd98b796e2b6553da7225aeb61f447f80a1ca64f41d83612e6139ca5213aa4"}, + {file = "MarkupSafe-2.1.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:b09bf97215625a311f669476f44b8b318b075847b49316d3e28c08e41a7a573f"}, + {file = "MarkupSafe-2.1.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:694deca8d702d5db21ec83983ce0bb4b26a578e71fbdbd4fdcd387daa90e4d5e"}, + {file = "MarkupSafe-2.1.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:efc1913fd2ca4f334418481c7e595c00aad186563bbc1ec76067848c7ca0a933"}, + {file = "MarkupSafe-2.1.1-cp310-cp310-win32.whl", hash = "sha256:4a33dea2b688b3190ee12bd7cfa29d39c9ed176bda40bfa11099a3ce5d3a7ac6"}, + {file = "MarkupSafe-2.1.1-cp310-cp310-win_amd64.whl", hash = "sha256:dda30ba7e87fbbb7eab1ec9f58678558fd9a6b8b853530e176eabd064da81417"}, + {file = "MarkupSafe-2.1.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:671cd1187ed5e62818414afe79ed29da836dde67166a9fac6d435873c44fdd02"}, + {file = "MarkupSafe-2.1.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3799351e2336dc91ea70b034983ee71cf2f9533cdff7c14c90ea126bfd95d65a"}, + {file = "MarkupSafe-2.1.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e72591e9ecd94d7feb70c1cbd7be7b3ebea3f548870aa91e2732960fa4d57a37"}, + {file = "MarkupSafe-2.1.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6fbf47b5d3728c6aea2abb0589b5d30459e369baa772e0f37a0320185e87c980"}, + {file = "MarkupSafe-2.1.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:d5ee4f386140395a2c818d149221149c54849dfcfcb9f1debfe07a8b8bd63f9a"}, + {file = "MarkupSafe-2.1.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:bcb3ed405ed3222f9904899563d6fc492ff75cce56cba05e32eff40e6acbeaa3"}, + {file = "MarkupSafe-2.1.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:e1c0b87e09fa55a220f058d1d49d3fb8df88fbfab58558f1198e08c1e1de842a"}, + {file = "MarkupSafe-2.1.1-cp37-cp37m-win32.whl", hash = "sha256:8dc1c72a69aa7e082593c4a203dcf94ddb74bb5c8a731e4e1eb68d031e8498ff"}, + {file = "MarkupSafe-2.1.1-cp37-cp37m-win_amd64.whl", hash = "sha256:97a68e6ada378df82bc9f16b800ab77cbf4b2fada0081794318520138c088e4a"}, + {file = "MarkupSafe-2.1.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:e8c843bbcda3a2f1e3c2ab25913c80a3c5376cd00c6e8c4a86a89a28c8dc5452"}, + {file = "MarkupSafe-2.1.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0212a68688482dc52b2d45013df70d169f542b7394fc744c02a57374a4207003"}, + {file = "MarkupSafe-2.1.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8e576a51ad59e4bfaac456023a78f6b5e6e7651dcd383bcc3e18d06f9b55d6d1"}, + {file = "MarkupSafe-2.1.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4b9fe39a2ccc108a4accc2676e77da025ce383c108593d65cc909add5c3bd601"}, + {file = "MarkupSafe-2.1.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:96e37a3dc86e80bf81758c152fe66dbf60ed5eca3d26305edf01892257049925"}, + {file = "MarkupSafe-2.1.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:6d0072fea50feec76a4c418096652f2c3238eaa014b2f94aeb1d56a66b41403f"}, + {file = "MarkupSafe-2.1.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:089cf3dbf0cd6c100f02945abeb18484bd1ee57a079aefd52cffd17fba910b88"}, + {file = "MarkupSafe-2.1.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6a074d34ee7a5ce3effbc526b7083ec9731bb3cbf921bbe1d3005d4d2bdb3a63"}, + {file = "MarkupSafe-2.1.1-cp38-cp38-win32.whl", hash = "sha256:421be9fbf0ffe9ffd7a378aafebbf6f4602d564d34be190fc19a193232fd12b1"}, + {file = "MarkupSafe-2.1.1-cp38-cp38-win_amd64.whl", hash = "sha256:fc7b548b17d238737688817ab67deebb30e8073c95749d55538ed473130ec0c7"}, + {file = "MarkupSafe-2.1.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:e04e26803c9c3851c931eac40c695602c6295b8d432cbe78609649ad9bd2da8a"}, + {file = "MarkupSafe-2.1.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b87db4360013327109564f0e591bd2a3b318547bcef31b468a92ee504d07ae4f"}, + {file = "MarkupSafe-2.1.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:99a2a507ed3ac881b975a2976d59f38c19386d128e7a9a18b7df6fff1fd4c1d6"}, + {file = "MarkupSafe-2.1.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:56442863ed2b06d19c37f94d999035e15ee982988920e12a5b4ba29b62ad1f77"}, + {file = "MarkupSafe-2.1.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3ce11ee3f23f79dbd06fb3d63e2f6af7b12db1d46932fe7bd8afa259a5996603"}, + {file = "MarkupSafe-2.1.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:33b74d289bd2f5e527beadcaa3f401e0df0a89927c1559c8566c066fa4248ab7"}, + {file = "MarkupSafe-2.1.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:43093fb83d8343aac0b1baa75516da6092f58f41200907ef92448ecab8825135"}, + {file = "MarkupSafe-2.1.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8e3dcf21f367459434c18e71b2a9532d96547aef8a871872a5bd69a715c15f96"}, + {file = "MarkupSafe-2.1.1-cp39-cp39-win32.whl", hash = "sha256:d4306c36ca495956b6d568d276ac11fdd9c30a36f1b6eb928070dc5360b22e1c"}, + {file = "MarkupSafe-2.1.1-cp39-cp39-win_amd64.whl", hash = "sha256:46d00d6cfecdde84d40e572d63735ef81423ad31184100411e6e3388d405e247"}, + {file = "MarkupSafe-2.1.1.tar.gz", hash = "sha256:7f91197cc9e48f989d12e4e6fbc46495c446636dfc81b9ccf50bb0ec74b91d4b"}, +] +multidict = [ + {file = "multidict-6.0.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:0b9e95a740109c6047602f4db4da9949e6c5945cefbad34a1299775ddc9a62e2"}, + {file = "multidict-6.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ac0e27844758d7177989ce406acc6a83c16ed4524ebc363c1f748cba184d89d3"}, + {file = "multidict-6.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:041b81a5f6b38244b34dc18c7b6aba91f9cdaf854d9a39e5ff0b58e2b5773b9c"}, + {file = "multidict-6.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5fdda29a3c7e76a064f2477c9aab1ba96fd94e02e386f1e665bca1807fc5386f"}, + {file = "multidict-6.0.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3368bf2398b0e0fcbf46d85795adc4c259299fec50c1416d0f77c0a843a3eed9"}, + {file = "multidict-6.0.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f4f052ee022928d34fe1f4d2bc743f32609fb79ed9c49a1710a5ad6b2198db20"}, + {file = "multidict-6.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:225383a6603c086e6cef0f2f05564acb4f4d5f019a4e3e983f572b8530f70c88"}, + {file = "multidict-6.0.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:50bd442726e288e884f7be9071016c15a8742eb689a593a0cac49ea093eef0a7"}, + {file = "multidict-6.0.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:47e6a7e923e9cada7c139531feac59448f1f47727a79076c0b1ee80274cd8eee"}, + {file = "multidict-6.0.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:0556a1d4ea2d949efe5fd76a09b4a82e3a4a30700553a6725535098d8d9fb672"}, + {file = "multidict-6.0.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:626fe10ac87851f4cffecee161fc6f8f9853f0f6f1035b59337a51d29ff3b4f9"}, + {file = "multidict-6.0.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:8064b7c6f0af936a741ea1efd18690bacfbae4078c0c385d7c3f611d11f0cf87"}, + {file = "multidict-6.0.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:2d36e929d7f6a16d4eb11b250719c39560dd70545356365b494249e2186bc389"}, + {file = "multidict-6.0.2-cp310-cp310-win32.whl", hash = "sha256:fcb91630817aa8b9bc4a74023e4198480587269c272c58b3279875ed7235c293"}, + {file = "multidict-6.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:8cbf0132f3de7cc6c6ce00147cc78e6439ea736cee6bca4f068bcf892b0fd658"}, + {file = "multidict-6.0.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:05f6949d6169878a03e607a21e3b862eaf8e356590e8bdae4227eedadacf6e51"}, + {file = "multidict-6.0.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e2c2e459f7050aeb7c1b1276763364884595d47000c1cddb51764c0d8976e608"}, + {file = "multidict-6.0.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d0509e469d48940147e1235d994cd849a8f8195e0bca65f8f5439c56e17872a3"}, + {file = "multidict-6.0.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:514fe2b8d750d6cdb4712346a2c5084a80220821a3e91f3f71eec11cf8d28fd4"}, + {file = "multidict-6.0.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:19adcfc2a7197cdc3987044e3f415168fc5dc1f720c932eb1ef4f71a2067e08b"}, + {file = "multidict-6.0.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b9d153e7f1f9ba0b23ad1568b3b9e17301e23b042c23870f9ee0522dc5cc79e8"}, + {file = "multidict-6.0.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:aef9cc3d9c7d63d924adac329c33835e0243b5052a6dfcbf7732a921c6e918ba"}, + {file = "multidict-6.0.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:4571f1beddff25f3e925eea34268422622963cd8dc395bb8778eb28418248e43"}, + {file = "multidict-6.0.2-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:d48b8ee1d4068561ce8033d2c344cf5232cb29ee1a0206a7b828c79cbc5982b8"}, + {file = "multidict-6.0.2-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:45183c96ddf61bf96d2684d9fbaf6f3564d86b34cb125761f9a0ef9e36c1d55b"}, + {file = "multidict-6.0.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:75bdf08716edde767b09e76829db8c1e5ca9d8bb0a8d4bd94ae1eafe3dac5e15"}, + {file = "multidict-6.0.2-cp37-cp37m-win32.whl", hash = "sha256:a45e1135cb07086833ce969555df39149680e5471c04dfd6a915abd2fc3f6dbc"}, + {file = "multidict-6.0.2-cp37-cp37m-win_amd64.whl", hash = "sha256:6f3cdef8a247d1eafa649085812f8a310e728bdf3900ff6c434eafb2d443b23a"}, + {file = "multidict-6.0.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:0327292e745a880459ef71be14e709aaea2f783f3537588fb4ed09b6c01bca60"}, + {file = "multidict-6.0.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:e875b6086e325bab7e680e4316d667fc0e5e174bb5611eb16b3ea121c8951b86"}, + {file = "multidict-6.0.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:feea820722e69451743a3d56ad74948b68bf456984d63c1a92e8347b7b88452d"}, + {file = "multidict-6.0.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9cc57c68cb9139c7cd6fc39f211b02198e69fb90ce4bc4a094cf5fe0d20fd8b0"}, + {file = "multidict-6.0.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:497988d6b6ec6ed6f87030ec03280b696ca47dbf0648045e4e1d28b80346560d"}, + {file = "multidict-6.0.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:89171b2c769e03a953d5969b2f272efa931426355b6c0cb508022976a17fd376"}, + {file = "multidict-6.0.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:684133b1e1fe91eda8fa7447f137c9490a064c6b7f392aa857bba83a28cfb693"}, + {file = "multidict-6.0.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fd9fc9c4849a07f3635ccffa895d57abce554b467d611a5009ba4f39b78a8849"}, + {file = "multidict-6.0.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:e07c8e79d6e6fd37b42f3250dba122053fddb319e84b55dd3a8d6446e1a7ee49"}, + {file = "multidict-6.0.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:4070613ea2227da2bfb2c35a6041e4371b0af6b0be57f424fe2318b42a748516"}, + {file = "multidict-6.0.2-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:47fbeedbf94bed6547d3aa632075d804867a352d86688c04e606971595460227"}, + {file = "multidict-6.0.2-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:5774d9218d77befa7b70d836004a768fb9aa4fdb53c97498f4d8d3f67bb9cfa9"}, + {file = "multidict-6.0.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:2957489cba47c2539a8eb7ab32ff49101439ccf78eab724c828c1a54ff3ff98d"}, + {file = "multidict-6.0.2-cp38-cp38-win32.whl", hash = "sha256:e5b20e9599ba74391ca0cfbd7b328fcc20976823ba19bc573983a25b32e92b57"}, + {file = "multidict-6.0.2-cp38-cp38-win_amd64.whl", hash = "sha256:8004dca28e15b86d1b1372515f32eb6f814bdf6f00952699bdeb541691091f96"}, + {file = "multidict-6.0.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:2e4a0785b84fb59e43c18a015ffc575ba93f7d1dbd272b4cdad9f5134b8a006c"}, + {file = "multidict-6.0.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6701bf8a5d03a43375909ac91b6980aea74b0f5402fbe9428fc3f6edf5d9677e"}, + {file = "multidict-6.0.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a007b1638e148c3cfb6bf0bdc4f82776cef0ac487191d093cdc316905e504071"}, + {file = "multidict-6.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:07a017cfa00c9890011628eab2503bee5872f27144936a52eaab449be5eaf032"}, + {file = "multidict-6.0.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c207fff63adcdf5a485969131dc70e4b194327666b7e8a87a97fbc4fd80a53b2"}, + {file = "multidict-6.0.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:373ba9d1d061c76462d74e7de1c0c8e267e9791ee8cfefcf6b0b2495762c370c"}, + {file = "multidict-6.0.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bfba7c6d5d7c9099ba21f84662b037a0ffd4a5e6b26ac07d19e423e6fdf965a9"}, + {file = "multidict-6.0.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:19d9bad105dfb34eb539c97b132057a4e709919ec4dd883ece5838bcbf262b80"}, + {file = "multidict-6.0.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:de989b195c3d636ba000ee4281cd03bb1234635b124bf4cd89eeee9ca8fcb09d"}, + {file = "multidict-6.0.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:7c40b7bbece294ae3a87c1bc2abff0ff9beef41d14188cda94ada7bcea99b0fb"}, + {file = "multidict-6.0.2-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:d16cce709ebfadc91278a1c005e3c17dd5f71f5098bfae1035149785ea6e9c68"}, + {file = "multidict-6.0.2-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:a2c34a93e1d2aa35fbf1485e5010337c72c6791407d03aa5f4eed920343dd360"}, + {file = "multidict-6.0.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:feba80698173761cddd814fa22e88b0661e98cb810f9f986c54aa34d281e4937"}, + {file = "multidict-6.0.2-cp39-cp39-win32.whl", hash = "sha256:23b616fdc3c74c9fe01d76ce0d1ce872d2d396d8fa8e4899398ad64fb5aa214a"}, + {file = "multidict-6.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:4bae31803d708f6f15fd98be6a6ac0b6958fcf68fda3c77a048a4f9073704aae"}, + {file = "multidict-6.0.2.tar.gz", hash = "sha256:5ff3bd75f38e4c43f1f470f2df7a4d430b821c4ce22be384e1459cb57d6bb013"}, +] +numpy = [ + {file = "numpy-1.22.3-cp310-cp310-macosx_10_14_x86_64.whl", hash = "sha256:92bfa69cfbdf7dfc3040978ad09a48091143cffb778ec3b03fa170c494118d75"}, + {file = "numpy-1.22.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8251ed96f38b47b4295b1ae51631de7ffa8260b5b087808ef09a39a9d66c97ab"}, + {file = "numpy-1.22.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:48a3aecd3b997bf452a2dedb11f4e79bc5bfd21a1d4cc760e703c31d57c84b3e"}, + {file = "numpy-1.22.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a3bae1a2ed00e90b3ba5f7bd0a7c7999b55d609e0c54ceb2b076a25e345fa9f4"}, + {file = "numpy-1.22.3-cp310-cp310-win32.whl", hash = "sha256:f950f8845b480cffe522913d35567e29dd381b0dc7e4ce6a4a9f9156417d2430"}, + {file = "numpy-1.22.3-cp310-cp310-win_amd64.whl", hash = "sha256:08d9b008d0156c70dc392bb3ab3abb6e7a711383c3247b410b39962263576cd4"}, + {file = "numpy-1.22.3-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:201b4d0552831f7250a08d3b38de0d989d6f6e4658b709a02a73c524ccc6ffce"}, + {file = "numpy-1.22.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:f8c1f39caad2c896bc0018f699882b345b2a63708008be29b1f355ebf6f933fe"}, + {file = "numpy-1.22.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:568dfd16224abddafb1cbcce2ff14f522abe037268514dd7e42c6776a1c3f8e5"}, + {file = "numpy-1.22.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ca688e1b9b95d80250bca34b11a05e389b1420d00e87a0d12dc45f131f704a1"}, + {file = "numpy-1.22.3-cp38-cp38-win32.whl", hash = "sha256:e7927a589df200c5e23c57970bafbd0cd322459aa7b1ff73b7c2e84d6e3eae62"}, + {file = "numpy-1.22.3-cp38-cp38-win_amd64.whl", hash = "sha256:07a8c89a04997625236c5ecb7afe35a02af3896c8aa01890a849913a2309c676"}, + {file = "numpy-1.22.3-cp39-cp39-macosx_10_14_x86_64.whl", hash = "sha256:2c10a93606e0b4b95c9b04b77dc349b398fdfbda382d2a39ba5a822f669a0123"}, + {file = "numpy-1.22.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:fade0d4f4d292b6f39951b6836d7a3c7ef5b2347f3c420cd9820a1d90d794802"}, + {file = "numpy-1.22.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5bfb1bb598e8229c2d5d48db1860bcf4311337864ea3efdbe1171fb0c5da515d"}, + {file = "numpy-1.22.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:97098b95aa4e418529099c26558eeb8486e66bd1e53a6b606d684d0c3616b168"}, + {file = "numpy-1.22.3-cp39-cp39-win32.whl", hash = "sha256:fdf3c08bce27132395d3c3ba1503cac12e17282358cb4bddc25cc46b0aca07aa"}, + {file = "numpy-1.22.3-cp39-cp39-win_amd64.whl", hash = "sha256:639b54cdf6aa4f82fe37ebf70401bbb74b8508fddcf4797f9fe59615b8c5813a"}, + {file = "numpy-1.22.3-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c34ea7e9d13a70bf2ab64a2532fe149a9aced424cd05a2c4ba662fd989e3e45f"}, + {file = "numpy-1.22.3.zip", hash = "sha256:dbc7601a3b7472d559dc7b933b18b4b66f9aa7452c120e87dfb33d02008c8a18"}, +] +replit = [ + {file = "replit-3.2.4-py3-none-any.whl", hash = "sha256:4fa5895e1e090ba23c179641bc88ab0486d1bea696515aa3147fce55733e29e1"}, + {file = "replit-3.2.4.tar.gz", hash = "sha256:39c660d57c479d321f143a04d75d1297accf24fc91c0113f56d6a279b20e9427"}, +] +requests = [ + {file = "requests-2.27.1-py2.py3-none-any.whl", hash = "sha256:f22fa1e554c9ddfd16e6e41ac79759e17be9e492b3587efa038054674760e72d"}, + {file = "requests-2.27.1.tar.gz", hash = "sha256:68d7c56fd5a8999887728ef304a6d12edc7be74f1cfa47714fc8b414525c9a61"}, +] +typing-extensions = [ + {file = "typing_extensions-3.10.0.2-py2-none-any.whl", hash = "sha256:d8226d10bc02a29bcc81df19a26e56a9647f8b0a6d4a83924139f4a8b01f17b7"}, + {file = "typing_extensions-3.10.0.2-py3-none-any.whl", hash = "sha256:f1d25edafde516b146ecd0613dabcc61409817af4766fbbcfb8d1ad4ec441a34"}, + {file = "typing_extensions-3.10.0.2.tar.gz", hash = "sha256:49f75d16ff11f1cd258e1b988ccff82a3ca5570217d7ad8c5f48205dd99a677e"}, +] +urllib3 = [ + {file = "urllib3-1.26.8-py2.py3-none-any.whl", hash = "sha256:000ca7f471a233c2251c6c7023ee85305721bfdf18621ebff4fd17a8653427ed"}, + {file = "urllib3-1.26.8.tar.gz", hash = "sha256:0e7c33d9a63e7ddfcb86780aac87befc2fbddf46c58dbb487e0855f7ceec283c"}, +] +werkzeug = [ + {file = "Werkzeug-2.0.3-py3-none-any.whl", hash = "sha256:1421ebfc7648a39a5c58c601b154165d05cf47a3cd0ccb70857cbdacf6c8f2b8"}, + {file = "Werkzeug-2.0.3.tar.gz", hash = "sha256:b863f8ff057c522164b6067c9e28b041161b4be5ba4d0daceeaa50a163822d3c"}, +] +yarl = [ + {file = "yarl-1.7.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:f2a8508f7350512434e41065684076f640ecce176d262a7d54f0da41d99c5a95"}, + {file = "yarl-1.7.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:da6df107b9ccfe52d3a48165e48d72db0eca3e3029b5b8cb4fe6ee3cb870ba8b"}, + {file = "yarl-1.7.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a1d0894f238763717bdcfea74558c94e3bc34aeacd3351d769460c1a586a8b05"}, + {file = "yarl-1.7.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dfe4b95b7e00c6635a72e2d00b478e8a28bfb122dc76349a06e20792eb53a523"}, + {file = "yarl-1.7.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c145ab54702334c42237a6c6c4cc08703b6aa9b94e2f227ceb3d477d20c36c63"}, + {file = "yarl-1.7.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1ca56f002eaf7998b5fcf73b2421790da9d2586331805f38acd9997743114e98"}, + {file = "yarl-1.7.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:1d3d5ad8ea96bd6d643d80c7b8d5977b4e2fb1bab6c9da7322616fd26203d125"}, + {file = "yarl-1.7.2-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:167ab7f64e409e9bdd99333fe8c67b5574a1f0495dcfd905bc7454e766729b9e"}, + {file = "yarl-1.7.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:95a1873b6c0dd1c437fb3bb4a4aaa699a48c218ac7ca1e74b0bee0ab16c7d60d"}, + {file = "yarl-1.7.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:6152224d0a1eb254f97df3997d79dadd8bb2c1a02ef283dbb34b97d4f8492d23"}, + {file = "yarl-1.7.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:5bb7d54b8f61ba6eee541fba4b83d22b8a046b4ef4d8eb7f15a7e35db2e1e245"}, + {file = "yarl-1.7.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:9c1f083e7e71b2dd01f7cd7434a5f88c15213194df38bc29b388ccdf1492b739"}, + {file = "yarl-1.7.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:f44477ae29025d8ea87ec308539f95963ffdc31a82f42ca9deecf2d505242e72"}, + {file = "yarl-1.7.2-cp310-cp310-win32.whl", hash = "sha256:cff3ba513db55cc6a35076f32c4cdc27032bd075c9faef31fec749e64b45d26c"}, + {file = "yarl-1.7.2-cp310-cp310-win_amd64.whl", hash = "sha256:c9c6d927e098c2d360695f2e9d38870b2e92e0919be07dbe339aefa32a090265"}, + {file = "yarl-1.7.2-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:9b4c77d92d56a4c5027572752aa35082e40c561eec776048330d2907aead891d"}, + {file = "yarl-1.7.2-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c01a89a44bb672c38f42b49cdb0ad667b116d731b3f4c896f72302ff77d71656"}, + {file = "yarl-1.7.2-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c19324a1c5399b602f3b6e7db9478e5b1adf5cf58901996fc973fe4fccd73eed"}, + {file = "yarl-1.7.2-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3abddf0b8e41445426d29f955b24aeecc83fa1072be1be4e0d194134a7d9baee"}, + {file = "yarl-1.7.2-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:6a1a9fe17621af43e9b9fcea8bd088ba682c8192d744b386ee3c47b56eaabb2c"}, + {file = "yarl-1.7.2-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:8b0915ee85150963a9504c10de4e4729ae700af11df0dc5550e6587ed7891e92"}, + {file = "yarl-1.7.2-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:29e0656d5497733dcddc21797da5a2ab990c0cb9719f1f969e58a4abac66234d"}, + {file = "yarl-1.7.2-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:bf19725fec28452474d9887a128e98dd67eee7b7d52e932e6949c532d820dc3b"}, + {file = "yarl-1.7.2-cp36-cp36m-musllinux_1_1_ppc64le.whl", hash = "sha256:d6f3d62e16c10e88d2168ba2d065aa374e3c538998ed04996cd373ff2036d64c"}, + {file = "yarl-1.7.2-cp36-cp36m-musllinux_1_1_s390x.whl", hash = "sha256:ac10bbac36cd89eac19f4e51c032ba6b412b3892b685076f4acd2de18ca990aa"}, + {file = "yarl-1.7.2-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:aa32aaa97d8b2ed4e54dc65d241a0da1c627454950f7d7b1f95b13985afd6c5d"}, + {file = "yarl-1.7.2-cp36-cp36m-win32.whl", hash = "sha256:87f6e082bce21464857ba58b569370e7b547d239ca22248be68ea5d6b51464a1"}, + {file = "yarl-1.7.2-cp36-cp36m-win_amd64.whl", hash = "sha256:ac35ccde589ab6a1870a484ed136d49a26bcd06b6a1c6397b1967ca13ceb3913"}, + {file = "yarl-1.7.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:a467a431a0817a292121c13cbe637348b546e6ef47ca14a790aa2fa8cc93df63"}, + {file = "yarl-1.7.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6ab0c3274d0a846840bf6c27d2c60ba771a12e4d7586bf550eefc2df0b56b3b4"}, + {file = "yarl-1.7.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d260d4dc495c05d6600264a197d9d6f7fc9347f21d2594926202fd08cf89a8ba"}, + {file = "yarl-1.7.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fc4dd8b01a8112809e6b636b00f487846956402834a7fd59d46d4f4267181c41"}, + {file = "yarl-1.7.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:c1164a2eac148d85bbdd23e07dfcc930f2e633220f3eb3c3e2a25f6148c2819e"}, + {file = "yarl-1.7.2-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:67e94028817defe5e705079b10a8438b8cb56e7115fa01640e9c0bb3edf67332"}, + {file = "yarl-1.7.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:89ccbf58e6a0ab89d487c92a490cb5660d06c3a47ca08872859672f9c511fc52"}, + {file = "yarl-1.7.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:8cce6f9fa3df25f55521fbb5c7e4a736683148bcc0c75b21863789e5185f9185"}, + {file = "yarl-1.7.2-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:211fcd65c58bf250fb994b53bc45a442ddc9f441f6fec53e65de8cba48ded986"}, + {file = "yarl-1.7.2-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:c10ea1e80a697cf7d80d1ed414b5cb8f1eec07d618f54637067ae3c0334133c4"}, + {file = "yarl-1.7.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:52690eb521d690ab041c3919666bea13ab9fbff80d615ec16fa81a297131276b"}, + {file = "yarl-1.7.2-cp37-cp37m-win32.whl", hash = "sha256:695ba021a9e04418507fa930d5f0704edbce47076bdcfeeaba1c83683e5649d1"}, + {file = "yarl-1.7.2-cp37-cp37m-win_amd64.whl", hash = "sha256:c17965ff3706beedafd458c452bf15bac693ecd146a60a06a214614dc097a271"}, + {file = "yarl-1.7.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:fce78593346c014d0d986b7ebc80d782b7f5e19843ca798ed62f8e3ba8728576"}, + {file = "yarl-1.7.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:c2a1ac41a6aa980db03d098a5531f13985edcb451bcd9d00670b03129922cd0d"}, + {file = "yarl-1.7.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:39d5493c5ecd75c8093fa7700a2fb5c94fe28c839c8e40144b7ab7ccba6938c8"}, + {file = "yarl-1.7.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1eb6480ef366d75b54c68164094a6a560c247370a68c02dddb11f20c4c6d3c9d"}, + {file = "yarl-1.7.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5ba63585a89c9885f18331a55d25fe81dc2d82b71311ff8bd378fc8004202ff6"}, + {file = "yarl-1.7.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e39378894ee6ae9f555ae2de332d513a5763276a9265f8e7cbaeb1b1ee74623a"}, + {file = "yarl-1.7.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:c0910c6b6c31359d2f6184828888c983d54d09d581a4a23547a35f1d0b9484b1"}, + {file = "yarl-1.7.2-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:6feca8b6bfb9eef6ee057628e71e1734caf520a907b6ec0d62839e8293e945c0"}, + {file = "yarl-1.7.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:8300401dc88cad23f5b4e4c1226f44a5aa696436a4026e456fe0e5d2f7f486e6"}, + {file = "yarl-1.7.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:788713c2896f426a4e166b11f4ec538b5736294ebf7d5f654ae445fd44270832"}, + {file = "yarl-1.7.2-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:fd547ec596d90c8676e369dd8a581a21227fe9b4ad37d0dc7feb4ccf544c2d59"}, + {file = "yarl-1.7.2-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:737e401cd0c493f7e3dd4db72aca11cfe069531c9761b8ea474926936b3c57c8"}, + {file = "yarl-1.7.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:baf81561f2972fb895e7844882898bda1eef4b07b5b385bcd308d2098f1a767b"}, + {file = "yarl-1.7.2-cp38-cp38-win32.whl", hash = "sha256:ede3b46cdb719c794427dcce9d8beb4abe8b9aa1e97526cc20de9bd6583ad1ef"}, + {file = "yarl-1.7.2-cp38-cp38-win_amd64.whl", hash = "sha256:cc8b7a7254c0fc3187d43d6cb54b5032d2365efd1df0cd1749c0c4df5f0ad45f"}, + {file = "yarl-1.7.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:580c1f15500e137a8c37053e4cbf6058944d4c114701fa59944607505c2fe3a0"}, + {file = "yarl-1.7.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3ec1d9a0d7780416e657f1e405ba35ec1ba453a4f1511eb8b9fbab81cb8b3ce1"}, + {file = "yarl-1.7.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3bf8cfe8856708ede6a73907bf0501f2dc4e104085e070a41f5d88e7faf237f3"}, + {file = "yarl-1.7.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1be4bbb3d27a4e9aa5f3df2ab61e3701ce8fcbd3e9846dbce7c033a7e8136746"}, + {file = "yarl-1.7.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:534b047277a9a19d858cde163aba93f3e1677d5acd92f7d10ace419d478540de"}, + {file = "yarl-1.7.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c6ddcd80d79c96eb19c354d9dca95291589c5954099836b7c8d29278a7ec0bda"}, + {file = "yarl-1.7.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:9bfcd43c65fbb339dc7086b5315750efa42a34eefad0256ba114cd8ad3896f4b"}, + {file = "yarl-1.7.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f64394bd7ceef1237cc604b5a89bf748c95982a84bcd3c4bbeb40f685c810794"}, + {file = "yarl-1.7.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:044daf3012e43d4b3538562da94a88fb12a6490652dbc29fb19adfa02cf72eac"}, + {file = "yarl-1.7.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:368bcf400247318382cc150aaa632582d0780b28ee6053cd80268c7e72796dec"}, + {file = "yarl-1.7.2-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:bab827163113177aee910adb1f48ff7af31ee0289f434f7e22d10baf624a6dfe"}, + {file = "yarl-1.7.2-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:0cba38120db72123db7c58322fa69e3c0efa933040ffb586c3a87c063ec7cae8"}, + {file = "yarl-1.7.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:59218fef177296451b23214c91ea3aba7858b4ae3306dde120224cfe0f7a6ee8"}, + {file = "yarl-1.7.2-cp39-cp39-win32.whl", hash = "sha256:1edc172dcca3f11b38a9d5c7505c83c1913c0addc99cd28e993efeaafdfaa18d"}, + {file = "yarl-1.7.2-cp39-cp39-win_amd64.whl", hash = "sha256:797c2c412b04403d2da075fb93c123df35239cd7b4cc4e0cd9e5839b73f52c58"}, + {file = "yarl-1.7.2.tar.gz", hash = "sha256:45399b46d60c253327a460e99856752009fcee5f5d3c80b2f7c0cae1c38d56dd"}, +] diff --git a/public/main.html b/public/main.html new file mode 100644 index 0000000..3925eba --- /dev/null +++ b/public/main.html @@ -0,0 +1,3 @@ + +

Hello

+ \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..f8136b0 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,19 @@ +[tool.poetry] +name = "python-template" +version = "0.1.0" +description = "" +authors = ["Your Name "] + +[tool.poetry.dependencies] +python = ">=3.8.0,<3.9" +numpy = "^1.22.2" +replit = "^3.2.4" +requests = "^2.27.1" +discord = "^1.7.3" +Flask = "^2.0.3" + +[tool.poetry.dev-dependencies] + +[build-system] +requires = ["poetry-core>=1.0.0"] +build-backend = "poetry.core.masonry.api" \ No newline at end of file diff --git a/replit.nix b/replit.nix new file mode 100644 index 0000000..4f1aec1 --- /dev/null +++ b/replit.nix @@ -0,0 +1,18 @@ +{ pkgs }: { + deps = [ + pkgs.python38Full + ]; + env = { + PYTHON_LD_LIBRARY_PATH = pkgs.lib.makeLibraryPath [ + # Neded for pandas / numpy + pkgs.stdenv.cc.cc.lib + pkgs.zlib + # Needed for pygame + pkgs.glib + # Needed for matplotlib + pkgs.xorg.libX11 + ]; + PYTHONBIN = "${pkgs.python38Full}/bin/python3.8"; + LANG = "en_US.UTF-8"; + }; +} \ No newline at end of file diff --git a/venv/lib64/python3.8/site-packages/Flask-2.0.3.dist-info/INSTALLER b/venv/lib64/python3.8/site-packages/Flask-2.0.3.dist-info/INSTALLER new file mode 100644 index 0000000..a1b589e --- /dev/null +++ b/venv/lib64/python3.8/site-packages/Flask-2.0.3.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/venv/lib64/python3.8/site-packages/Flask-2.0.3.dist-info/METADATA b/venv/lib64/python3.8/site-packages/Flask-2.0.3.dist-info/METADATA new file mode 100644 index 0000000..d617f5f --- /dev/null +++ b/venv/lib64/python3.8/site-packages/Flask-2.0.3.dist-info/METADATA @@ -0,0 +1,125 @@ +Metadata-Version: 2.1 +Name: Flask +Version: 2.0.3 +Summary: A simple framework for building complex web applications. +Home-page: https://palletsprojects.com/p/flask +Author: Armin Ronacher +Author-email: armin.ronacher@active-4.com +Maintainer: Pallets +Maintainer-email: contact@palletsprojects.com +License: BSD-3-Clause +Project-URL: Donate, https://palletsprojects.com/donate +Project-URL: Documentation, https://flask.palletsprojects.com/ +Project-URL: Changes, https://flask.palletsprojects.com/changes/ +Project-URL: Source Code, https://github.com/pallets/flask/ +Project-URL: Issue Tracker, https://github.com/pallets/flask/issues/ +Project-URL: Twitter, https://twitter.com/PalletsTeam +Project-URL: Chat, https://discord.gg/pallets +Platform: UNKNOWN +Classifier: Development Status :: 5 - Production/Stable +Classifier: Environment :: Web Environment +Classifier: Framework :: Flask +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: BSD License +Classifier: Operating System :: OS Independent +Classifier: Programming Language :: Python +Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content +Classifier: Topic :: Internet :: WWW/HTTP :: WSGI +Classifier: Topic :: Internet :: WWW/HTTP :: WSGI :: Application +Classifier: Topic :: Software Development :: Libraries :: Application Frameworks +Requires-Python: >=3.6 +Description-Content-Type: text/x-rst +License-File: LICENSE.rst +Requires-Dist: Werkzeug (>=2.0) +Requires-Dist: Jinja2 (>=3.0) +Requires-Dist: itsdangerous (>=2.0) +Requires-Dist: click (>=7.1.2) +Provides-Extra: async +Requires-Dist: asgiref (>=3.2) ; extra == 'async' +Provides-Extra: dotenv +Requires-Dist: python-dotenv ; extra == 'dotenv' + +Flask +===== + +Flask is a lightweight `WSGI`_ web application framework. It is designed +to make getting started quick and easy, with the ability to scale up to +complex applications. It began as a simple wrapper around `Werkzeug`_ +and `Jinja`_ and has become one of the most popular Python web +application frameworks. + +Flask offers suggestions, but doesn't enforce any dependencies or +project layout. It is up to the developer to choose the tools and +libraries they want to use. There are many extensions provided by the +community that make adding new functionality easy. + +.. _WSGI: https://wsgi.readthedocs.io/ +.. _Werkzeug: https://werkzeug.palletsprojects.com/ +.. _Jinja: https://jinja.palletsprojects.com/ + + +Installing +---------- + +Install and update using `pip`_: + +.. code-block:: text + + $ pip install -U Flask + +.. _pip: https://pip.pypa.io/en/stable/getting-started/ + + +A Simple Example +---------------- + +.. code-block:: python + + # save this as app.py + from flask import Flask + + app = Flask(__name__) + + @app.route("/") + def hello(): + return "Hello, World!" + +.. code-block:: text + + $ flask run + * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit) + + +Contributing +------------ + +For guidance on setting up a development environment and how to make a +contribution to Flask, see the `contributing guidelines`_. + +.. _contributing guidelines: https://github.com/pallets/flask/blob/main/CONTRIBUTING.rst + + +Donate +------ + +The Pallets organization develops and supports Flask and the libraries +it uses. In order to grow the community of contributors and users, and +allow the maintainers to devote more time to the projects, `please +donate today`_. + +.. _please donate today: https://palletsprojects.com/donate + + +Links +----- + +- Documentation: https://flask.palletsprojects.com/ +- Changes: https://flask.palletsprojects.com/changes/ +- PyPI Releases: https://pypi.org/project/Flask/ +- Source Code: https://github.com/pallets/flask/ +- Issue Tracker: https://github.com/pallets/flask/issues/ +- Website: https://palletsprojects.com/p/flask/ +- Twitter: https://twitter.com/PalletsTeam +- Chat: https://discord.gg/pallets + + diff --git a/venv/lib64/python3.8/site-packages/Flask-2.0.3.dist-info/RECORD b/venv/lib64/python3.8/site-packages/Flask-2.0.3.dist-info/RECORD new file mode 100644 index 0000000..4ecc093 --- /dev/null +++ b/venv/lib64/python3.8/site-packages/Flask-2.0.3.dist-info/RECORD @@ -0,0 +1,53 @@ +../../../bin/flask,sha256=QYgeCqTAn_3fWCfQnj5HXC9fs-blcYQh2_94j-UlPoE,227 +Flask-2.0.3.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +Flask-2.0.3.dist-info/LICENSE.rst,sha256=SJqOEQhQntmKN7uYPhHg9-HTHwvY-Zp5yESOf_N9B-o,1475 +Flask-2.0.3.dist-info/METADATA,sha256=jK50YtxZfODLQP_GF1sNH6dOXRCI5bBLrAc7pWQwuXw,3839 +Flask-2.0.3.dist-info/RECORD,, +Flask-2.0.3.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +Flask-2.0.3.dist-info/WHEEL,sha256=G16H4A3IeoQmnOrYV4ueZGKSjhipXx8zc8nu9FGlvMA,92 +Flask-2.0.3.dist-info/direct_url.json,sha256=vezzzEhDxsJLTfWoszWXVMCAfp5oc5RJ5iinbGUHLpU,173 +Flask-2.0.3.dist-info/entry_points.txt,sha256=s3MqQpduU25y4dq3ftBYD6bMVdVnbMpZP-sUNw0zw0k,41 +Flask-2.0.3.dist-info/top_level.txt,sha256=dvi65F6AeGWVU0TBpYiC04yM60-FX1gJFkK31IKQr5c,6 +flask/__init__.py,sha256=ubQS5Xt6LMjPSwGO3Jksi5yx8AyuU0vT_VdHjt0j97A,2251 +flask/__main__.py,sha256=bYt9eEaoRQWdejEHFD8REx9jxVEdZptECFsV7F49Ink,30 +flask/__pycache__/__init__.cpython-38.pyc,, +flask/__pycache__/__main__.cpython-38.pyc,, +flask/__pycache__/app.cpython-38.pyc,, +flask/__pycache__/blueprints.cpython-38.pyc,, +flask/__pycache__/cli.cpython-38.pyc,, +flask/__pycache__/config.cpython-38.pyc,, +flask/__pycache__/ctx.cpython-38.pyc,, +flask/__pycache__/debughelpers.cpython-38.pyc,, +flask/__pycache__/globals.cpython-38.pyc,, +flask/__pycache__/helpers.cpython-38.pyc,, +flask/__pycache__/logging.cpython-38.pyc,, +flask/__pycache__/scaffold.cpython-38.pyc,, +flask/__pycache__/sessions.cpython-38.pyc,, +flask/__pycache__/signals.cpython-38.pyc,, +flask/__pycache__/templating.cpython-38.pyc,, +flask/__pycache__/testing.cpython-38.pyc,, +flask/__pycache__/typing.cpython-38.pyc,, +flask/__pycache__/views.cpython-38.pyc,, +flask/__pycache__/wrappers.cpython-38.pyc,, +flask/app.py,sha256=ectBbi9hGmVHAse5TNcFQZIDRkDAxYUAnLgfuKD0Xws,81975 +flask/blueprints.py,sha256=AkAVXZ_MMkjwjklzCAMdBNowTiM0wVQPynnUnXjTL2M,23781 +flask/cli.py,sha256=9v7FDIwWZ3QZsR6ka-qMYzMxSThfmQ4PEA4lkI38R6c,32287 +flask/config.py,sha256=70Uyjh1Jzb9MfTCT7NDhuZWAzyIEu-TIyk6-22MP3zQ,11285 +flask/ctx.py,sha256=Rmw5VOFQdbomLoCQPbU_0FbQkuB56CtpnQVU4yzXYB8,17589 +flask/debughelpers.py,sha256=W82-xrRmodjopBngI9roYH-q08EbQwN2HEGfDAi6SA0,6184 +flask/globals.py,sha256=cWd-R2hUH3VqPhnmQNww892tQS6Yjqg_wg8UvW1M7NM,1723 +flask/helpers.py,sha256=kstplLDtD0Isobilp87Lfmwq1tk2spnHjUf_O5-EhoE,30618 +flask/json/__init__.py,sha256=_YIqOsy8YOSyoLbplFtNcKvF5kwNKenmJ87Ub2Myc0k,12104 +flask/json/__pycache__/__init__.cpython-38.pyc,, +flask/json/__pycache__/tag.cpython-38.pyc,, +flask/json/tag.py,sha256=fys3HBLssWHuMAIJuTcf2K0bCtosePBKXIWASZEEjnU,8857 +flask/logging.py,sha256=1o_hirVGqdj7SBdETnhX7IAjklG89RXlrwz_2CjzQQE,2273 +flask/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +flask/scaffold.py,sha256=fM9mRy7QBh9fhJ0VTogVx900dDa5oxz8FOw6OK5F-TU,32796 +flask/sessions.py,sha256=46jK4JlcdeBiYbDWTZJn_6u8EqDV-ByRdhlKrbgFi5M,15714 +flask/signals.py,sha256=H7QwDciK-dtBxinjKpexpglP0E6k0MJILiFWTItfmqU,2136 +flask/templating.py,sha256=l96VD39JQ0nue4Bcj7wZ4-FWWs-ppLxvgBCpwDQ4KAk,5626 +flask/testing.py,sha256=T3mr2PLQEkfxoftSTxmGfTtb_FSX3PgfGT8DUGNPWuk,10840 +flask/typing.py,sha256=L5JMltVjj8fovGS1hrMpb13IPfsFDESCCnpRN5CPT4U,1844 +flask/views.py,sha256=nhq31TRB5Z-z2mjFGZACaaB2Et5XPCmWhWxJxOvLWww,5948 +flask/wrappers.py,sha256=VndbHPRBSUUOejmd2Y3ydkoCVUtsS2OJIdJEVIkBVD8,5604 diff --git a/venv/lib64/python3.8/site-packages/Flask-2.0.3.dist-info/REQUESTED b/venv/lib64/python3.8/site-packages/Flask-2.0.3.dist-info/REQUESTED new file mode 100644 index 0000000..e69de29 diff --git a/venv/lib64/python3.8/site-packages/Flask-2.0.3.dist-info/direct_url.json b/venv/lib64/python3.8/site-packages/Flask-2.0.3.dist-info/direct_url.json new file mode 100644 index 0000000..f033626 --- /dev/null +++ b/venv/lib64/python3.8/site-packages/Flask-2.0.3.dist-info/direct_url.json @@ -0,0 +1 @@ +{"archive_info": {}, "url": "file:///home/runner/.cache/pypoetry/artifacts/cd/4b/12/2ef50ad12f8373130d91ea66343bfa1fb25be1e5b370671bbcca3bf5a1/Flask-2.0.3-py3-none-any.whl"} \ No newline at end of file diff --git a/venv/lib64/python3.8/site-packages/Flask-2.0.3.dist-info/entry_points.txt b/venv/lib64/python3.8/site-packages/Flask-2.0.3.dist-info/entry_points.txt new file mode 100644 index 0000000..137232d --- /dev/null +++ b/venv/lib64/python3.8/site-packages/Flask-2.0.3.dist-info/entry_points.txt @@ -0,0 +1,2 @@ +[console_scripts] +flask = flask.cli:main diff --git a/venv/lib64/python3.8/site-packages/SecretStorage-3.3.1.dist-info/RECORD b/venv/lib64/python3.8/site-packages/SecretStorage-3.3.1.dist-info/RECORD new file mode 100644 index 0000000..20ad0fe --- /dev/null +++ b/venv/lib64/python3.8/site-packages/SecretStorage-3.3.1.dist-info/RECORD @@ -0,0 +1,21 @@ +SecretStorage-3.3.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +SecretStorage-3.3.1.dist-info/LICENSE,sha256=cPa_yndjPDXvohgyjtpUhtcFTCkU1hggmA43h5dSCiU,1504 +SecretStorage-3.3.1.dist-info/METADATA,sha256=ozeU7sep7B1qsoQ4UrHv6CdsUPNrJWZ6_TRmocPSnHI,3943 +SecretStorage-3.3.1.dist-info/RECORD,, +SecretStorage-3.3.1.dist-info/WHEEL,sha256=g4nMs7d-Xl9-xC9XovUrsDHGXt-FT0E17Yqo92DEfvY,92 +SecretStorage-3.3.1.dist-info/top_level.txt,sha256=hveSi1OWGaEt3kEVbjmZ0M-ASPxi6y-nTPVa-d3c0B4,14 +secretstorage/__init__.py,sha256=pHaVJFUsWYM7EQv3VeqZkZqhan8ndIQMP4mQ7pDXgOA,3180 +secretstorage/__pycache__/__init__.cpython-38.pyc,, +secretstorage/__pycache__/collection.cpython-38.pyc,, +secretstorage/__pycache__/defines.cpython-38.pyc,, +secretstorage/__pycache__/dhcrypto.cpython-38.pyc,, +secretstorage/__pycache__/exceptions.cpython-38.pyc,, +secretstorage/__pycache__/item.cpython-38.pyc,, +secretstorage/__pycache__/util.cpython-38.pyc,, +secretstorage/collection.py,sha256=vaep-OCM65Z7xznmH25jQWCJ_fLaZ2RpY5pIdNZJz6U,8408 +secretstorage/defines.py,sha256=x2lf3W2Ks8TV52tldb-Fn1u_Rmd5-AfeXBx2HzeGXy0,824 +secretstorage/dhcrypto.py,sha256=MVeCaOEbjda4YnXWPcq4VU_eIMUvJtGiEsWUCXC7PJo,2417 +secretstorage/exceptions.py,sha256=MEgrgRxY7-iW_QI3FH7WN3JGupA-Fzl8_r1-Y3XwwHU,1576 +secretstorage/item.py,sha256=3NJzakoFWeg59kFjgzGRGlvgg3BgrgT-56QMrFVL9fw,5241 +secretstorage/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +secretstorage/util.py,sha256=mXIlvP_phVO6BbN4KH8sYW0dfEFxhbr0hEViGTzJcAY,6002 diff --git a/venv/lib64/python3.8/site-packages/aiohttp/__init__.py b/venv/lib64/python3.8/site-packages/aiohttp/__init__.py new file mode 100644 index 0000000..23cd5c9 --- /dev/null +++ b/venv/lib64/python3.8/site-packages/aiohttp/__init__.py @@ -0,0 +1,217 @@ +__version__ = "3.7.4" + +from typing import Tuple + +from . import hdrs as hdrs +from .client import ( + BaseConnector as BaseConnector, + ClientConnectionError as ClientConnectionError, + ClientConnectorCertificateError as ClientConnectorCertificateError, + ClientConnectorError as ClientConnectorError, + ClientConnectorSSLError as ClientConnectorSSLError, + ClientError as ClientError, + ClientHttpProxyError as ClientHttpProxyError, + ClientOSError as ClientOSError, + ClientPayloadError as ClientPayloadError, + ClientProxyConnectionError as ClientProxyConnectionError, + ClientRequest as ClientRequest, + ClientResponse as ClientResponse, + ClientResponseError as ClientResponseError, + ClientSession as ClientSession, + ClientSSLError as ClientSSLError, + ClientTimeout as ClientTimeout, + ClientWebSocketResponse as ClientWebSocketResponse, + ContentTypeError as ContentTypeError, + Fingerprint as Fingerprint, + InvalidURL as InvalidURL, + NamedPipeConnector as NamedPipeConnector, + RequestInfo as RequestInfo, + ServerConnectionError as ServerConnectionError, + ServerDisconnectedError as ServerDisconnectedError, + ServerFingerprintMismatch as ServerFingerprintMismatch, + ServerTimeoutError as ServerTimeoutError, + TCPConnector as TCPConnector, + TooManyRedirects as TooManyRedirects, + UnixConnector as UnixConnector, + WSServerHandshakeError as WSServerHandshakeError, + request as request, +) +from .cookiejar import CookieJar as CookieJar, DummyCookieJar as DummyCookieJar +from .formdata import FormData as FormData +from .helpers import BasicAuth as BasicAuth, ChainMapProxy as ChainMapProxy +from .http import ( + HttpVersion as HttpVersion, + HttpVersion10 as HttpVersion10, + HttpVersion11 as HttpVersion11, + WebSocketError as WebSocketError, + WSCloseCode as WSCloseCode, + WSMessage as WSMessage, + WSMsgType as WSMsgType, +) +from .multipart import ( + BadContentDispositionHeader as BadContentDispositionHeader, + BadContentDispositionParam as BadContentDispositionParam, + BodyPartReader as BodyPartReader, + MultipartReader as MultipartReader, + MultipartWriter as MultipartWriter, + content_disposition_filename as content_disposition_filename, + parse_content_disposition as parse_content_disposition, +) +from .payload import ( + PAYLOAD_REGISTRY as PAYLOAD_REGISTRY, + AsyncIterablePayload as AsyncIterablePayload, + BufferedReaderPayload as BufferedReaderPayload, + BytesIOPayload as BytesIOPayload, + BytesPayload as BytesPayload, + IOBasePayload as IOBasePayload, + JsonPayload as JsonPayload, + Payload as Payload, + StringIOPayload as StringIOPayload, + StringPayload as StringPayload, + TextIOPayload as TextIOPayload, + get_payload as get_payload, + payload_type as payload_type, +) +from .payload_streamer import streamer as streamer +from .resolver import ( + AsyncResolver as AsyncResolver, + DefaultResolver as DefaultResolver, + ThreadedResolver as ThreadedResolver, +) +from .signals import Signal as Signal +from .streams import ( + EMPTY_PAYLOAD as EMPTY_PAYLOAD, + DataQueue as DataQueue, + EofStream as EofStream, + FlowControlDataQueue as FlowControlDataQueue, + StreamReader as StreamReader, +) +from .tracing import ( + TraceConfig as TraceConfig, + TraceConnectionCreateEndParams as TraceConnectionCreateEndParams, + TraceConnectionCreateStartParams as TraceConnectionCreateStartParams, + TraceConnectionQueuedEndParams as TraceConnectionQueuedEndParams, + TraceConnectionQueuedStartParams as TraceConnectionQueuedStartParams, + TraceConnectionReuseconnParams as TraceConnectionReuseconnParams, + TraceDnsCacheHitParams as TraceDnsCacheHitParams, + TraceDnsCacheMissParams as TraceDnsCacheMissParams, + TraceDnsResolveHostEndParams as TraceDnsResolveHostEndParams, + TraceDnsResolveHostStartParams as TraceDnsResolveHostStartParams, + TraceRequestChunkSentParams as TraceRequestChunkSentParams, + TraceRequestEndParams as TraceRequestEndParams, + TraceRequestExceptionParams as TraceRequestExceptionParams, + TraceRequestRedirectParams as TraceRequestRedirectParams, + TraceRequestStartParams as TraceRequestStartParams, + TraceResponseChunkReceivedParams as TraceResponseChunkReceivedParams, +) + +__all__: Tuple[str, ...] = ( + "hdrs", + # client + "BaseConnector", + "ClientConnectionError", + "ClientConnectorCertificateError", + "ClientConnectorError", + "ClientConnectorSSLError", + "ClientError", + "ClientHttpProxyError", + "ClientOSError", + "ClientPayloadError", + "ClientProxyConnectionError", + "ClientResponse", + "ClientRequest", + "ClientResponseError", + "ClientSSLError", + "ClientSession", + "ClientTimeout", + "ClientWebSocketResponse", + "ContentTypeError", + "Fingerprint", + "InvalidURL", + "RequestInfo", + "ServerConnectionError", + "ServerDisconnectedError", + "ServerFingerprintMismatch", + "ServerTimeoutError", + "TCPConnector", + "TooManyRedirects", + "UnixConnector", + "NamedPipeConnector", + "WSServerHandshakeError", + "request", + # cookiejar + "CookieJar", + "DummyCookieJar", + # formdata + "FormData", + # helpers + "BasicAuth", + "ChainMapProxy", + # http + "HttpVersion", + "HttpVersion10", + "HttpVersion11", + "WSMsgType", + "WSCloseCode", + "WSMessage", + "WebSocketError", + # multipart + "BadContentDispositionHeader", + "BadContentDispositionParam", + "BodyPartReader", + "MultipartReader", + "MultipartWriter", + "content_disposition_filename", + "parse_content_disposition", + # payload + "AsyncIterablePayload", + "BufferedReaderPayload", + "BytesIOPayload", + "BytesPayload", + "IOBasePayload", + "JsonPayload", + "PAYLOAD_REGISTRY", + "Payload", + "StringIOPayload", + "StringPayload", + "TextIOPayload", + "get_payload", + "payload_type", + # payload_streamer + "streamer", + # resolver + "AsyncResolver", + "DefaultResolver", + "ThreadedResolver", + # signals + "Signal", + "DataQueue", + "EMPTY_PAYLOAD", + "EofStream", + "FlowControlDataQueue", + "StreamReader", + # tracing + "TraceConfig", + "TraceConnectionCreateEndParams", + "TraceConnectionCreateStartParams", + "TraceConnectionQueuedEndParams", + "TraceConnectionQueuedStartParams", + "TraceConnectionReuseconnParams", + "TraceDnsCacheHitParams", + "TraceDnsCacheMissParams", + "TraceDnsResolveHostEndParams", + "TraceDnsResolveHostStartParams", + "TraceRequestChunkSentParams", + "TraceRequestEndParams", + "TraceRequestExceptionParams", + "TraceRequestRedirectParams", + "TraceRequestStartParams", + "TraceResponseChunkReceivedParams", +) + +try: + from .worker import GunicornUVLoopWebWorker, GunicornWebWorker + + __all__ += ("GunicornWebWorker", "GunicornUVLoopWebWorker") +except ImportError: # pragma: no cover + pass diff --git a/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/__init__.cpython-38.pyc b/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/__init__.cpython-38.pyc new file mode 100644 index 0000000..4b24e13 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/__init__.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/abc.cpython-38.pyc b/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/abc.cpython-38.pyc new file mode 100644 index 0000000..e1c772d Binary files /dev/null and b/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/abc.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/base_protocol.cpython-38.pyc b/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/base_protocol.cpython-38.pyc new file mode 100644 index 0000000..19971f0 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/base_protocol.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/client.cpython-38.pyc b/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/client.cpython-38.pyc new file mode 100644 index 0000000..51d6fb7 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/client.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/client_exceptions.cpython-38.pyc b/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/client_exceptions.cpython-38.pyc new file mode 100644 index 0000000..ee3b706 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/client_exceptions.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/client_proto.cpython-38.pyc b/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/client_proto.cpython-38.pyc new file mode 100644 index 0000000..d568b39 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/client_proto.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/client_reqrep.cpython-38.pyc b/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/client_reqrep.cpython-38.pyc new file mode 100644 index 0000000..290aac1 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/client_reqrep.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/client_ws.cpython-38.pyc b/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/client_ws.cpython-38.pyc new file mode 100644 index 0000000..6cfb0c7 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/client_ws.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/connector.cpython-38.pyc b/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/connector.cpython-38.pyc new file mode 100644 index 0000000..afdf518 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/connector.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/cookiejar.cpython-38.pyc b/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/cookiejar.cpython-38.pyc new file mode 100644 index 0000000..31ecdf9 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/cookiejar.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/formdata.cpython-38.pyc b/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/formdata.cpython-38.pyc new file mode 100644 index 0000000..ccf2d22 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/formdata.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/frozenlist.cpython-38.pyc b/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/frozenlist.cpython-38.pyc new file mode 100644 index 0000000..7e8a7cb Binary files /dev/null and b/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/frozenlist.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/hdrs.cpython-38.pyc b/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/hdrs.cpython-38.pyc new file mode 100644 index 0000000..7ed0b48 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/hdrs.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/helpers.cpython-38.pyc b/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/helpers.cpython-38.pyc new file mode 100644 index 0000000..ddb476c Binary files /dev/null and b/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/helpers.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/http.cpython-38.pyc b/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/http.cpython-38.pyc new file mode 100644 index 0000000..013de80 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/http.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/http_exceptions.cpython-38.pyc b/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/http_exceptions.cpython-38.pyc new file mode 100644 index 0000000..aee6841 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/http_exceptions.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/http_parser.cpython-38.pyc b/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/http_parser.cpython-38.pyc new file mode 100644 index 0000000..9dbf522 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/http_parser.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/http_websocket.cpython-38.pyc b/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/http_websocket.cpython-38.pyc new file mode 100644 index 0000000..3f24403 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/http_websocket.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/http_writer.cpython-38.pyc b/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/http_writer.cpython-38.pyc new file mode 100644 index 0000000..919a48b Binary files /dev/null and b/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/http_writer.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/locks.cpython-38.pyc b/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/locks.cpython-38.pyc new file mode 100644 index 0000000..93187f4 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/locks.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/log.cpython-38.pyc b/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/log.cpython-38.pyc new file mode 100644 index 0000000..0d99cf5 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/log.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/multipart.cpython-38.pyc b/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/multipart.cpython-38.pyc new file mode 100644 index 0000000..da3346d Binary files /dev/null and b/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/multipart.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/payload.cpython-38.pyc b/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/payload.cpython-38.pyc new file mode 100644 index 0000000..8142c3f Binary files /dev/null and b/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/payload.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/payload_streamer.cpython-38.pyc b/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/payload_streamer.cpython-38.pyc new file mode 100644 index 0000000..d6c4776 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/payload_streamer.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/pytest_plugin.cpython-38.pyc b/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/pytest_plugin.cpython-38.pyc new file mode 100644 index 0000000..9cb9c56 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/pytest_plugin.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/resolver.cpython-38.pyc b/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/resolver.cpython-38.pyc new file mode 100644 index 0000000..313f807 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/resolver.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/signals.cpython-38.pyc b/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/signals.cpython-38.pyc new file mode 100644 index 0000000..e29fb5f Binary files /dev/null and b/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/signals.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/streams.cpython-38.pyc b/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/streams.cpython-38.pyc new file mode 100644 index 0000000..35b3bbc Binary files /dev/null and b/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/streams.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/tcp_helpers.cpython-38.pyc b/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/tcp_helpers.cpython-38.pyc new file mode 100644 index 0000000..1c9f9a8 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/tcp_helpers.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/test_utils.cpython-38.pyc b/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/test_utils.cpython-38.pyc new file mode 100644 index 0000000..b03931e Binary files /dev/null and b/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/test_utils.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/tracing.cpython-38.pyc b/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/tracing.cpython-38.pyc new file mode 100644 index 0000000..95f07c5 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/tracing.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/typedefs.cpython-38.pyc b/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/typedefs.cpython-38.pyc new file mode 100644 index 0000000..8e9cdac Binary files /dev/null and b/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/typedefs.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/web.cpython-38.pyc b/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/web.cpython-38.pyc new file mode 100644 index 0000000..eecd5f5 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/web.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/web_app.cpython-38.pyc b/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/web_app.cpython-38.pyc new file mode 100644 index 0000000..ead30b2 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/web_app.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/web_exceptions.cpython-38.pyc b/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/web_exceptions.cpython-38.pyc new file mode 100644 index 0000000..a4f23dc Binary files /dev/null and b/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/web_exceptions.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/web_fileresponse.cpython-38.pyc b/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/web_fileresponse.cpython-38.pyc new file mode 100644 index 0000000..7b82a35 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/web_fileresponse.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/web_log.cpython-38.pyc b/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/web_log.cpython-38.pyc new file mode 100644 index 0000000..bd3a853 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/web_log.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/web_middlewares.cpython-38.pyc b/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/web_middlewares.cpython-38.pyc new file mode 100644 index 0000000..00f6adf Binary files /dev/null and b/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/web_middlewares.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/web_protocol.cpython-38.pyc b/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/web_protocol.cpython-38.pyc new file mode 100644 index 0000000..b453db4 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/web_protocol.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/web_request.cpython-38.pyc b/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/web_request.cpython-38.pyc new file mode 100644 index 0000000..e246b41 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/web_request.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/web_response.cpython-38.pyc b/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/web_response.cpython-38.pyc new file mode 100644 index 0000000..7fd80de Binary files /dev/null and b/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/web_response.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/web_routedef.cpython-38.pyc b/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/web_routedef.cpython-38.pyc new file mode 100644 index 0000000..bc0b70b Binary files /dev/null and b/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/web_routedef.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/web_runner.cpython-38.pyc b/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/web_runner.cpython-38.pyc new file mode 100644 index 0000000..700c933 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/web_runner.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/web_server.cpython-38.pyc b/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/web_server.cpython-38.pyc new file mode 100644 index 0000000..797f87d Binary files /dev/null and b/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/web_server.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/web_urldispatcher.cpython-38.pyc b/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/web_urldispatcher.cpython-38.pyc new file mode 100644 index 0000000..f45fe6a Binary files /dev/null and b/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/web_urldispatcher.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/web_ws.cpython-38.pyc b/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/web_ws.cpython-38.pyc new file mode 100644 index 0000000..15eab92 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/web_ws.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/worker.cpython-38.pyc b/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/worker.cpython-38.pyc new file mode 100644 index 0000000..9457a7a Binary files /dev/null and b/venv/lib64/python3.8/site-packages/aiohttp/__pycache__/worker.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/aiohttp/_frozenlist.cpython-38-x86_64-linux-gnu.so b/venv/lib64/python3.8/site-packages/aiohttp/_frozenlist.cpython-38-x86_64-linux-gnu.so new file mode 100644 index 0000000..a60c2e4 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/aiohttp/_frozenlist.cpython-38-x86_64-linux-gnu.so differ diff --git a/venv/lib64/python3.8/site-packages/aiohttp/_helpers.cpython-38-x86_64-linux-gnu.so b/venv/lib64/python3.8/site-packages/aiohttp/_helpers.cpython-38-x86_64-linux-gnu.so new file mode 100644 index 0000000..c567aa9 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/aiohttp/_helpers.cpython-38-x86_64-linux-gnu.so differ diff --git a/venv/lib64/python3.8/site-packages/aiohttp/_http_parser.cpython-38-x86_64-linux-gnu.so b/venv/lib64/python3.8/site-packages/aiohttp/_http_parser.cpython-38-x86_64-linux-gnu.so new file mode 100644 index 0000000..696e4c7 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/aiohttp/_http_parser.cpython-38-x86_64-linux-gnu.so differ diff --git a/venv/lib64/python3.8/site-packages/aiohttp/_http_writer.cpython-38-x86_64-linux-gnu.so b/venv/lib64/python3.8/site-packages/aiohttp/_http_writer.cpython-38-x86_64-linux-gnu.so new file mode 100644 index 0000000..56347c0 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/aiohttp/_http_writer.cpython-38-x86_64-linux-gnu.so differ diff --git a/venv/lib64/python3.8/site-packages/aiohttp/_websocket.cpython-38-x86_64-linux-gnu.so b/venv/lib64/python3.8/site-packages/aiohttp/_websocket.cpython-38-x86_64-linux-gnu.so new file mode 100644 index 0000000..ea4b09b Binary files /dev/null and b/venv/lib64/python3.8/site-packages/aiohttp/_websocket.cpython-38-x86_64-linux-gnu.so differ diff --git a/venv/lib64/python3.8/site-packages/aiohttp/http_parser.py b/venv/lib64/python3.8/site-packages/aiohttp/http_parser.py new file mode 100644 index 0000000..71ba815 --- /dev/null +++ b/venv/lib64/python3.8/site-packages/aiohttp/http_parser.py @@ -0,0 +1,901 @@ +import abc +import asyncio +import collections +import re +import string +import zlib +from enum import IntEnum +from typing import Any, List, Optional, Tuple, Type, Union + +from multidict import CIMultiDict, CIMultiDictProxy, istr +from yarl import URL + +from . import hdrs +from .base_protocol import BaseProtocol +from .helpers import NO_EXTENSIONS, BaseTimerContext +from .http_exceptions import ( + BadStatusLine, + ContentEncodingError, + ContentLengthError, + InvalidHeader, + LineTooLong, + TransferEncodingError, +) +from .http_writer import HttpVersion, HttpVersion10 +from .log import internal_logger +from .streams import EMPTY_PAYLOAD, StreamReader +from .typedefs import RawHeaders + +try: + import brotli + + HAS_BROTLI = True +except ImportError: # pragma: no cover + HAS_BROTLI = False + + +__all__ = ( + "HeadersParser", + "HttpParser", + "HttpRequestParser", + "HttpResponseParser", + "RawRequestMessage", + "RawResponseMessage", +) + +ASCIISET = set(string.printable) + +# See https://tools.ietf.org/html/rfc7230#section-3.1.1 +# and https://tools.ietf.org/html/rfc7230#appendix-B +# +# method = token +# tchar = "!" / "#" / "$" / "%" / "&" / "'" / "*" / "+" / "-" / "." / +# "^" / "_" / "`" / "|" / "~" / DIGIT / ALPHA +# token = 1*tchar +METHRE = re.compile(r"[!#$%&'*+\-.^_`|~0-9A-Za-z]+") +VERSRE = re.compile(r"HTTP/(\d+).(\d+)") +HDRRE = re.compile(rb"[\x00-\x1F\x7F()<>@,;:\[\]={} \t\\\\\"]") + +RawRequestMessage = collections.namedtuple( + "RawRequestMessage", + [ + "method", + "path", + "version", + "headers", + "raw_headers", + "should_close", + "compression", + "upgrade", + "chunked", + "url", + ], +) + +RawResponseMessage = collections.namedtuple( + "RawResponseMessage", + [ + "version", + "code", + "reason", + "headers", + "raw_headers", + "should_close", + "compression", + "upgrade", + "chunked", + ], +) + + +class ParseState(IntEnum): + + PARSE_NONE = 0 + PARSE_LENGTH = 1 + PARSE_CHUNKED = 2 + PARSE_UNTIL_EOF = 3 + + +class ChunkState(IntEnum): + PARSE_CHUNKED_SIZE = 0 + PARSE_CHUNKED_CHUNK = 1 + PARSE_CHUNKED_CHUNK_EOF = 2 + PARSE_MAYBE_TRAILERS = 3 + PARSE_TRAILERS = 4 + + +class HeadersParser: + def __init__( + self, + max_line_size: int = 8190, + max_headers: int = 32768, + max_field_size: int = 8190, + ) -> None: + self.max_line_size = max_line_size + self.max_headers = max_headers + self.max_field_size = max_field_size + + def parse_headers( + self, lines: List[bytes] + ) -> Tuple["CIMultiDictProxy[str]", RawHeaders]: + headers = CIMultiDict() # type: CIMultiDict[str] + raw_headers = [] + + lines_idx = 1 + line = lines[1] + line_count = len(lines) + + while line: + # Parse initial header name : value pair. + try: + bname, bvalue = line.split(b":", 1) + except ValueError: + raise InvalidHeader(line) from None + + bname = bname.strip(b" \t") + bvalue = bvalue.lstrip() + if HDRRE.search(bname): + raise InvalidHeader(bname) + if len(bname) > self.max_field_size: + raise LineTooLong( + "request header name {}".format( + bname.decode("utf8", "xmlcharrefreplace") + ), + str(self.max_field_size), + str(len(bname)), + ) + + header_length = len(bvalue) + + # next line + lines_idx += 1 + line = lines[lines_idx] + + # consume continuation lines + continuation = line and line[0] in (32, 9) # (' ', '\t') + + if continuation: + bvalue_lst = [bvalue] + while continuation: + header_length += len(line) + if header_length > self.max_field_size: + raise LineTooLong( + "request header field {}".format( + bname.decode("utf8", "xmlcharrefreplace") + ), + str(self.max_field_size), + str(header_length), + ) + bvalue_lst.append(line) + + # next line + lines_idx += 1 + if lines_idx < line_count: + line = lines[lines_idx] + if line: + continuation = line[0] in (32, 9) # (' ', '\t') + else: + line = b"" + break + bvalue = b"".join(bvalue_lst) + else: + if header_length > self.max_field_size: + raise LineTooLong( + "request header field {}".format( + bname.decode("utf8", "xmlcharrefreplace") + ), + str(self.max_field_size), + str(header_length), + ) + + bvalue = bvalue.strip() + name = bname.decode("utf-8", "surrogateescape") + value = bvalue.decode("utf-8", "surrogateescape") + + headers.add(name, value) + raw_headers.append((bname, bvalue)) + + return (CIMultiDictProxy(headers), tuple(raw_headers)) + + +class HttpParser(abc.ABC): + def __init__( + self, + protocol: Optional[BaseProtocol] = None, + loop: Optional[asyncio.AbstractEventLoop] = None, + limit: int = 2 ** 16, + max_line_size: int = 8190, + max_headers: int = 32768, + max_field_size: int = 8190, + timer: Optional[BaseTimerContext] = None, + code: Optional[int] = None, + method: Optional[str] = None, + readall: bool = False, + payload_exception: Optional[Type[BaseException]] = None, + response_with_body: bool = True, + read_until_eof: bool = False, + auto_decompress: bool = True, + ) -> None: + self.protocol = protocol + self.loop = loop + self.max_line_size = max_line_size + self.max_headers = max_headers + self.max_field_size = max_field_size + self.timer = timer + self.code = code + self.method = method + self.readall = readall + self.payload_exception = payload_exception + self.response_with_body = response_with_body + self.read_until_eof = read_until_eof + + self._lines = [] # type: List[bytes] + self._tail = b"" + self._upgraded = False + self._payload = None + self._payload_parser = None # type: Optional[HttpPayloadParser] + self._auto_decompress = auto_decompress + self._limit = limit + self._headers_parser = HeadersParser(max_line_size, max_headers, max_field_size) + + @abc.abstractmethod + def parse_message(self, lines: List[bytes]) -> Any: + pass + + def feed_eof(self) -> Any: + if self._payload_parser is not None: + self._payload_parser.feed_eof() + self._payload_parser = None + else: + # try to extract partial message + if self._tail: + self._lines.append(self._tail) + + if self._lines: + if self._lines[-1] != "\r\n": + self._lines.append(b"") + try: + return self.parse_message(self._lines) + except Exception: + return None + + def feed_data( + self, + data: bytes, + SEP: bytes = b"\r\n", + EMPTY: bytes = b"", + CONTENT_LENGTH: istr = hdrs.CONTENT_LENGTH, + METH_CONNECT: str = hdrs.METH_CONNECT, + SEC_WEBSOCKET_KEY1: istr = hdrs.SEC_WEBSOCKET_KEY1, + ) -> Tuple[List[Any], bool, bytes]: + + messages = [] + + if self._tail: + data, self._tail = self._tail + data, b"" + + data_len = len(data) + start_pos = 0 + loop = self.loop + + while start_pos < data_len: + + # read HTTP message (request/response line + headers), \r\n\r\n + # and split by lines + if self._payload_parser is None and not self._upgraded: + pos = data.find(SEP, start_pos) + # consume \r\n + if pos == start_pos and not self._lines: + start_pos = pos + 2 + continue + + if pos >= start_pos: + # line found + self._lines.append(data[start_pos:pos]) + start_pos = pos + 2 + + # \r\n\r\n found + if self._lines[-1] == EMPTY: + try: + msg = self.parse_message(self._lines) + finally: + self._lines.clear() + + # payload length + length = msg.headers.get(CONTENT_LENGTH) + if length is not None: + try: + length = int(length) + except ValueError: + raise InvalidHeader(CONTENT_LENGTH) + if length < 0: + raise InvalidHeader(CONTENT_LENGTH) + + # do not support old websocket spec + if SEC_WEBSOCKET_KEY1 in msg.headers: + raise InvalidHeader(SEC_WEBSOCKET_KEY1) + + self._upgraded = msg.upgrade + + method = getattr(msg, "method", self.method) + + assert self.protocol is not None + # calculate payload + if ( + (length is not None and length > 0) + or msg.chunked + and not msg.upgrade + ): + payload = StreamReader( + self.protocol, + timer=self.timer, + loop=loop, + limit=self._limit, + ) + payload_parser = HttpPayloadParser( + payload, + length=length, + chunked=msg.chunked, + method=method, + compression=msg.compression, + code=self.code, + readall=self.readall, + response_with_body=self.response_with_body, + auto_decompress=self._auto_decompress, + ) + if not payload_parser.done: + self._payload_parser = payload_parser + elif method == METH_CONNECT: + payload = StreamReader( + self.protocol, + timer=self.timer, + loop=loop, + limit=self._limit, + ) + self._upgraded = True + self._payload_parser = HttpPayloadParser( + payload, + method=msg.method, + compression=msg.compression, + readall=True, + auto_decompress=self._auto_decompress, + ) + else: + if ( + getattr(msg, "code", 100) >= 199 + and length is None + and self.read_until_eof + ): + payload = StreamReader( + self.protocol, + timer=self.timer, + loop=loop, + limit=self._limit, + ) + payload_parser = HttpPayloadParser( + payload, + length=length, + chunked=msg.chunked, + method=method, + compression=msg.compression, + code=self.code, + readall=True, + response_with_body=self.response_with_body, + auto_decompress=self._auto_decompress, + ) + if not payload_parser.done: + self._payload_parser = payload_parser + else: + payload = EMPTY_PAYLOAD # type: ignore + + messages.append((msg, payload)) + else: + self._tail = data[start_pos:] + data = EMPTY + break + + # no parser, just store + elif self._payload_parser is None and self._upgraded: + assert not self._lines + break + + # feed payload + elif data and start_pos < data_len: + assert not self._lines + assert self._payload_parser is not None + try: + eof, data = self._payload_parser.feed_data(data[start_pos:]) + except BaseException as exc: + if self.payload_exception is not None: + self._payload_parser.payload.set_exception( + self.payload_exception(str(exc)) + ) + else: + self._payload_parser.payload.set_exception(exc) + + eof = True + data = b"" + + if eof: + start_pos = 0 + data_len = len(data) + self._payload_parser = None + continue + else: + break + + if data and start_pos < data_len: + data = data[start_pos:] + else: + data = EMPTY + + return messages, self._upgraded, data + + def parse_headers( + self, lines: List[bytes] + ) -> Tuple[ + "CIMultiDictProxy[str]", RawHeaders, Optional[bool], Optional[str], bool, bool + ]: + """Parses RFC 5322 headers from a stream. + + Line continuations are supported. Returns list of header name + and value pairs. Header name is in upper case. + """ + headers, raw_headers = self._headers_parser.parse_headers(lines) + close_conn = None + encoding = None + upgrade = False + chunked = False + + # keep-alive + conn = headers.get(hdrs.CONNECTION) + if conn: + v = conn.lower() + if v == "close": + close_conn = True + elif v == "keep-alive": + close_conn = False + elif v == "upgrade": + upgrade = True + + # encoding + enc = headers.get(hdrs.CONTENT_ENCODING) + if enc: + enc = enc.lower() + if enc in ("gzip", "deflate", "br"): + encoding = enc + + # chunking + te = headers.get(hdrs.TRANSFER_ENCODING) + if te and "chunked" in te.lower(): + chunked = True + + return (headers, raw_headers, close_conn, encoding, upgrade, chunked) + + def set_upgraded(self, val: bool) -> None: + """Set connection upgraded (to websocket) mode. + :param bool val: new state. + """ + self._upgraded = val + + +class HttpRequestParser(HttpParser): + """Read request status line. Exception .http_exceptions.BadStatusLine + could be raised in case of any errors in status line. + Returns RawRequestMessage. + """ + + def parse_message(self, lines: List[bytes]) -> Any: + # request line + line = lines[0].decode("utf-8", "surrogateescape") + try: + method, path, version = line.split(None, 2) + except ValueError: + raise BadStatusLine(line) from None + + if len(path) > self.max_line_size: + raise LineTooLong( + "Status line is too long", str(self.max_line_size), str(len(path)) + ) + + path_part, _hash_separator, url_fragment = path.partition("#") + path_part, _question_mark_separator, qs_part = path_part.partition("?") + + # method + if not METHRE.match(method): + raise BadStatusLine(method) + + # version + try: + if version.startswith("HTTP/"): + n1, n2 = version[5:].split(".", 1) + version_o = HttpVersion(int(n1), int(n2)) + else: + raise BadStatusLine(version) + except Exception: + raise BadStatusLine(version) + + # read headers + ( + headers, + raw_headers, + close, + compression, + upgrade, + chunked, + ) = self.parse_headers(lines) + + if close is None: # then the headers weren't set in the request + if version_o <= HttpVersion10: # HTTP 1.0 must asks to not close + close = True + else: # HTTP 1.1 must ask to close. + close = False + + return RawRequestMessage( + method, + path, + version_o, + headers, + raw_headers, + close, + compression, + upgrade, + chunked, + # NOTE: `yarl.URL.build()` is used to mimic what the Cython-based + # NOTE: parser does, otherwise it results into the same + # NOTE: HTTP Request-Line input producing different + # NOTE: `yarl.URL()` objects + URL.build( + path=path_part, + query_string=qs_part, + fragment=url_fragment, + encoded=True, + ), + ) + + +class HttpResponseParser(HttpParser): + """Read response status line and headers. + + BadStatusLine could be raised in case of any errors in status line. + Returns RawResponseMessage""" + + def parse_message(self, lines: List[bytes]) -> Any: + line = lines[0].decode("utf-8", "surrogateescape") + try: + version, status = line.split(None, 1) + except ValueError: + raise BadStatusLine(line) from None + + try: + status, reason = status.split(None, 1) + except ValueError: + reason = "" + + if len(reason) > self.max_line_size: + raise LineTooLong( + "Status line is too long", str(self.max_line_size), str(len(reason)) + ) + + # version + match = VERSRE.match(version) + if match is None: + raise BadStatusLine(line) + version_o = HttpVersion(int(match.group(1)), int(match.group(2))) + + # The status code is a three-digit number + try: + status_i = int(status) + except ValueError: + raise BadStatusLine(line) from None + + if status_i > 999: + raise BadStatusLine(line) + + # read headers + ( + headers, + raw_headers, + close, + compression, + upgrade, + chunked, + ) = self.parse_headers(lines) + + if close is None: + close = version_o <= HttpVersion10 + + return RawResponseMessage( + version_o, + status_i, + reason.strip(), + headers, + raw_headers, + close, + compression, + upgrade, + chunked, + ) + + +class HttpPayloadParser: + def __init__( + self, + payload: StreamReader, + length: Optional[int] = None, + chunked: bool = False, + compression: Optional[str] = None, + code: Optional[int] = None, + method: Optional[str] = None, + readall: bool = False, + response_with_body: bool = True, + auto_decompress: bool = True, + ) -> None: + self._length = 0 + self._type = ParseState.PARSE_NONE + self._chunk = ChunkState.PARSE_CHUNKED_SIZE + self._chunk_size = 0 + self._chunk_tail = b"" + self._auto_decompress = auto_decompress + self.done = False + + # payload decompression wrapper + if response_with_body and compression and self._auto_decompress: + real_payload = DeflateBuffer( + payload, compression + ) # type: Union[StreamReader, DeflateBuffer] + else: + real_payload = payload + + # payload parser + if not response_with_body: + # don't parse payload if it's not expected to be received + self._type = ParseState.PARSE_NONE + real_payload.feed_eof() + self.done = True + + elif chunked: + self._type = ParseState.PARSE_CHUNKED + elif length is not None: + self._type = ParseState.PARSE_LENGTH + self._length = length + if self._length == 0: + real_payload.feed_eof() + self.done = True + else: + if readall and code != 204: + self._type = ParseState.PARSE_UNTIL_EOF + elif method in ("PUT", "POST"): + internal_logger.warning( # pragma: no cover + "Content-Length or Transfer-Encoding header is required" + ) + self._type = ParseState.PARSE_NONE + real_payload.feed_eof() + self.done = True + + self.payload = real_payload + + def feed_eof(self) -> None: + if self._type == ParseState.PARSE_UNTIL_EOF: + self.payload.feed_eof() + elif self._type == ParseState.PARSE_LENGTH: + raise ContentLengthError( + "Not enough data for satisfy content length header." + ) + elif self._type == ParseState.PARSE_CHUNKED: + raise TransferEncodingError( + "Not enough data for satisfy transfer length header." + ) + + def feed_data( + self, chunk: bytes, SEP: bytes = b"\r\n", CHUNK_EXT: bytes = b";" + ) -> Tuple[bool, bytes]: + # Read specified amount of bytes + if self._type == ParseState.PARSE_LENGTH: + required = self._length + chunk_len = len(chunk) + + if required >= chunk_len: + self._length = required - chunk_len + self.payload.feed_data(chunk, chunk_len) + if self._length == 0: + self.payload.feed_eof() + return True, b"" + else: + self._length = 0 + self.payload.feed_data(chunk[:required], required) + self.payload.feed_eof() + return True, chunk[required:] + + # Chunked transfer encoding parser + elif self._type == ParseState.PARSE_CHUNKED: + if self._chunk_tail: + chunk = self._chunk_tail + chunk + self._chunk_tail = b"" + + while chunk: + + # read next chunk size + if self._chunk == ChunkState.PARSE_CHUNKED_SIZE: + pos = chunk.find(SEP) + if pos >= 0: + i = chunk.find(CHUNK_EXT, 0, pos) + if i >= 0: + size_b = chunk[:i] # strip chunk-extensions + else: + size_b = chunk[:pos] + + try: + size = int(bytes(size_b), 16) + except ValueError: + exc = TransferEncodingError( + chunk[:pos].decode("ascii", "surrogateescape") + ) + self.payload.set_exception(exc) + raise exc from None + + chunk = chunk[pos + 2 :] + if size == 0: # eof marker + self._chunk = ChunkState.PARSE_MAYBE_TRAILERS + else: + self._chunk = ChunkState.PARSE_CHUNKED_CHUNK + self._chunk_size = size + self.payload.begin_http_chunk_receiving() + else: + self._chunk_tail = chunk + return False, b"" + + # read chunk and feed buffer + if self._chunk == ChunkState.PARSE_CHUNKED_CHUNK: + required = self._chunk_size + chunk_len = len(chunk) + + if required > chunk_len: + self._chunk_size = required - chunk_len + self.payload.feed_data(chunk, chunk_len) + return False, b"" + else: + self._chunk_size = 0 + self.payload.feed_data(chunk[:required], required) + chunk = chunk[required:] + self._chunk = ChunkState.PARSE_CHUNKED_CHUNK_EOF + self.payload.end_http_chunk_receiving() + + # toss the CRLF at the end of the chunk + if self._chunk == ChunkState.PARSE_CHUNKED_CHUNK_EOF: + if chunk[:2] == SEP: + chunk = chunk[2:] + self._chunk = ChunkState.PARSE_CHUNKED_SIZE + else: + self._chunk_tail = chunk + return False, b"" + + # if stream does not contain trailer, after 0\r\n + # we should get another \r\n otherwise + # trailers needs to be skiped until \r\n\r\n + if self._chunk == ChunkState.PARSE_MAYBE_TRAILERS: + head = chunk[:2] + if head == SEP: + # end of stream + self.payload.feed_eof() + return True, chunk[2:] + # Both CR and LF, or only LF may not be received yet. It is + # expected that CRLF or LF will be shown at the very first + # byte next time, otherwise trailers should come. The last + # CRLF which marks the end of response might not be + # contained in the same TCP segment which delivered the + # size indicator. + if not head: + return False, b"" + if head == SEP[:1]: + self._chunk_tail = head + return False, b"" + self._chunk = ChunkState.PARSE_TRAILERS + + # read and discard trailer up to the CRLF terminator + if self._chunk == ChunkState.PARSE_TRAILERS: + pos = chunk.find(SEP) + if pos >= 0: + chunk = chunk[pos + 2 :] + self._chunk = ChunkState.PARSE_MAYBE_TRAILERS + else: + self._chunk_tail = chunk + return False, b"" + + # Read all bytes until eof + elif self._type == ParseState.PARSE_UNTIL_EOF: + self.payload.feed_data(chunk, len(chunk)) + + return False, b"" + + +class DeflateBuffer: + """DeflateStream decompress stream and feed data into specified stream.""" + + def __init__(self, out: StreamReader, encoding: Optional[str]) -> None: + self.out = out + self.size = 0 + self.encoding = encoding + self._started_decoding = False + + if encoding == "br": + if not HAS_BROTLI: # pragma: no cover + raise ContentEncodingError( + "Can not decode content-encoding: brotli (br). " + "Please install `brotlipy`" + ) + self.decompressor = brotli.Decompressor() + else: + zlib_mode = 16 + zlib.MAX_WBITS if encoding == "gzip" else zlib.MAX_WBITS + self.decompressor = zlib.decompressobj(wbits=zlib_mode) + + def set_exception(self, exc: BaseException) -> None: + self.out.set_exception(exc) + + def feed_data(self, chunk: bytes, size: int) -> None: + if not size: + return + + self.size += size + + # RFC1950 + # bits 0..3 = CM = 0b1000 = 8 = "deflate" + # bits 4..7 = CINFO = 1..7 = windows size. + if ( + not self._started_decoding + and self.encoding == "deflate" + and chunk[0] & 0xF != 8 + ): + # Change the decoder to decompress incorrectly compressed data + # Actually we should issue a warning about non-RFC-compliant data. + self.decompressor = zlib.decompressobj(wbits=-zlib.MAX_WBITS) + + try: + chunk = self.decompressor.decompress(chunk) + except Exception: + raise ContentEncodingError( + "Can not decode content-encoding: %s" % self.encoding + ) + + self._started_decoding = True + + if chunk: + self.out.feed_data(chunk, len(chunk)) + + def feed_eof(self) -> None: + chunk = self.decompressor.flush() + + if chunk or self.size > 0: + self.out.feed_data(chunk, len(chunk)) + if self.encoding == "deflate" and not self.decompressor.eof: + raise ContentEncodingError("deflate") + + self.out.feed_eof() + + def begin_http_chunk_receiving(self) -> None: + self.out.begin_http_chunk_receiving() + + def end_http_chunk_receiving(self) -> None: + self.out.end_http_chunk_receiving() + + +HttpRequestParserPy = HttpRequestParser +HttpResponseParserPy = HttpResponseParser +RawRequestMessagePy = RawRequestMessage +RawResponseMessagePy = RawResponseMessage + +try: + if not NO_EXTENSIONS: + from ._http_parser import ( # type: ignore + HttpRequestParser, + HttpResponseParser, + RawRequestMessage, + RawResponseMessage, + ) + + HttpRequestParserC = HttpRequestParser + HttpResponseParserC = HttpResponseParser + RawRequestMessageC = RawRequestMessage + RawResponseMessageC = RawResponseMessage +except ImportError: # pragma: no cover + pass diff --git a/venv/lib64/python3.8/site-packages/aiohttp/web_middlewares.py b/venv/lib64/python3.8/site-packages/aiohttp/web_middlewares.py new file mode 100644 index 0000000..8a8967e --- /dev/null +++ b/venv/lib64/python3.8/site-packages/aiohttp/web_middlewares.py @@ -0,0 +1,121 @@ +import re +from typing import TYPE_CHECKING, Awaitable, Callable, Tuple, Type, TypeVar + +from .web_exceptions import HTTPPermanentRedirect, _HTTPMove +from .web_request import Request +from .web_response import StreamResponse +from .web_urldispatcher import SystemRoute + +__all__ = ( + "middleware", + "normalize_path_middleware", +) + +if TYPE_CHECKING: # pragma: no cover + from .web_app import Application + +_Func = TypeVar("_Func") + + +async def _check_request_resolves(request: Request, path: str) -> Tuple[bool, Request]: + alt_request = request.clone(rel_url=path) + + match_info = await request.app.router.resolve(alt_request) + alt_request._match_info = match_info # type: ignore + + if match_info.http_exception is None: + return True, alt_request + + return False, request + + +def middleware(f: _Func) -> _Func: + f.__middleware_version__ = 1 # type: ignore + return f + + +_Handler = Callable[[Request], Awaitable[StreamResponse]] +_Middleware = Callable[[Request, _Handler], Awaitable[StreamResponse]] + + +def normalize_path_middleware( + *, + append_slash: bool = True, + remove_slash: bool = False, + merge_slashes: bool = True, + redirect_class: Type[_HTTPMove] = HTTPPermanentRedirect +) -> _Middleware: + """ + Middleware factory which produces a middleware that normalizes + the path of a request. By normalizing it means: + + - Add or remove a trailing slash to the path. + - Double slashes are replaced by one. + + The middleware returns as soon as it finds a path that resolves + correctly. The order if both merge and append/remove are enabled is + 1) merge slashes + 2) append/remove slash + 3) both merge slashes and append/remove slash. + If the path resolves with at least one of those conditions, it will + redirect to the new path. + + Only one of `append_slash` and `remove_slash` can be enabled. If both + are `True` the factory will raise an assertion error + + If `append_slash` is `True` the middleware will append a slash when + needed. If a resource is defined with trailing slash and the request + comes without it, it will append it automatically. + + If `remove_slash` is `True`, `append_slash` must be `False`. When enabled + the middleware will remove trailing slashes and redirect if the resource + is defined + + If merge_slashes is True, merge multiple consecutive slashes in the + path into one. + """ + + correct_configuration = not (append_slash and remove_slash) + assert correct_configuration, "Cannot both remove and append slash" + + @middleware + async def impl(request: Request, handler: _Handler) -> StreamResponse: + if isinstance(request.match_info.route, SystemRoute): + paths_to_check = [] + if "?" in request.raw_path: + path, query = request.raw_path.split("?", 1) + query = "?" + query + else: + query = "" + path = request.raw_path + + if merge_slashes: + paths_to_check.append(re.sub("//+", "/", path)) + if append_slash and not request.path.endswith("/"): + paths_to_check.append(path + "/") + if remove_slash and request.path.endswith("/"): + paths_to_check.append(path[:-1]) + if merge_slashes and append_slash: + paths_to_check.append(re.sub("//+", "/", path + "/")) + if merge_slashes and remove_slash: + merged_slashes = re.sub("//+", "/", path) + paths_to_check.append(merged_slashes[:-1]) + + for path in paths_to_check: + path = re.sub("^//+", "/", path) # SECURITY: GHSA-v6wp-4m6f-gcjg + resolves, request = await _check_request_resolves(request, path) + if resolves: + raise redirect_class(request.raw_path + query) + + return await handler(request) + + return impl + + +def _fix_request_current_app(app: "Application") -> _Middleware: + @middleware + async def impl(request: Request, handler: _Handler) -> StreamResponse: + with request.match_info.set_current_app(app): + return await handler(request) + + return impl diff --git a/venv/lib64/python3.8/site-packages/async_timeout/__pycache__/__init__.cpython-38.pyc b/venv/lib64/python3.8/site-packages/async_timeout/__pycache__/__init__.cpython-38.pyc new file mode 100644 index 0000000..0318c7d Binary files /dev/null and b/venv/lib64/python3.8/site-packages/async_timeout/__pycache__/__init__.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/attrs/__pycache__/__init__.cpython-38.pyc b/venv/lib64/python3.8/site-packages/attrs/__pycache__/__init__.cpython-38.pyc new file mode 100644 index 0000000..b97efe2 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/attrs/__pycache__/__init__.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/attrs/__pycache__/converters.cpython-38.pyc b/venv/lib64/python3.8/site-packages/attrs/__pycache__/converters.cpython-38.pyc new file mode 100644 index 0000000..1dca73a Binary files /dev/null and b/venv/lib64/python3.8/site-packages/attrs/__pycache__/converters.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/attrs/__pycache__/exceptions.cpython-38.pyc b/venv/lib64/python3.8/site-packages/attrs/__pycache__/exceptions.cpython-38.pyc new file mode 100644 index 0000000..8bc3181 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/attrs/__pycache__/exceptions.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/attrs/__pycache__/filters.cpython-38.pyc b/venv/lib64/python3.8/site-packages/attrs/__pycache__/filters.cpython-38.pyc new file mode 100644 index 0000000..6599fb7 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/attrs/__pycache__/filters.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/attrs/__pycache__/setters.cpython-38.pyc b/venv/lib64/python3.8/site-packages/attrs/__pycache__/setters.cpython-38.pyc new file mode 100644 index 0000000..7b17065 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/attrs/__pycache__/setters.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/attrs/__pycache__/validators.cpython-38.pyc b/venv/lib64/python3.8/site-packages/attrs/__pycache__/validators.cpython-38.pyc new file mode 100644 index 0000000..f060b8c Binary files /dev/null and b/venv/lib64/python3.8/site-packages/attrs/__pycache__/validators.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/backports.entry_points_selectable-1.1.1.dist-info/RECORD b/venv/lib64/python3.8/site-packages/backports.entry_points_selectable-1.1.1.dist-info/RECORD new file mode 100644 index 0000000..d3c81e3 --- /dev/null +++ b/venv/lib64/python3.8/site-packages/backports.entry_points_selectable-1.1.1.dist-info/RECORD @@ -0,0 +1,10 @@ +backports.entry_points_selectable-1.1.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +backports.entry_points_selectable-1.1.1.dist-info/LICENSE,sha256=2z8CRrH5J48VhFuZ_sR4uLUG63ZIeZNyL4xuJUKF-vg,1050 +backports.entry_points_selectable-1.1.1.dist-info/METADATA,sha256=JR4LLuqLGDNbRXwyrJ8o2UscKfiDPSp-XMy-Fo23Ccw,4014 +backports.entry_points_selectable-1.1.1.dist-info/RECORD,, +backports.entry_points_selectable-1.1.1.dist-info/WHEEL,sha256=WzZ8cwjh8l0jtULNjYq1Hpr-WCqCRgPr--TX4P5I1Wo,110 +backports.entry_points_selectable-1.1.1.dist-info/top_level.txt,sha256=cGjaLMOoBR1FK0ApojtzWVmViTtJ7JGIK_HwXiEsvtU,10 +backports/__init__.py,sha256=iOEMwnlORWezdO8-2vxBIPSR37D7JGjluZ8f55vzxls,81 +backports/__pycache__/__init__.cpython-38.pyc,, +backports/__pycache__/entry_points_selectable.cpython-38.pyc,, +backports/entry_points_selectable.py,sha256=p6WRKhYFNocmWtTassxkXAbSwyqO01hJMq60y4rPyxE,7444 diff --git a/venv/lib64/python3.8/site-packages/cachy-0.3.0.dist-info/RECORD b/venv/lib64/python3.8/site-packages/cachy-0.3.0.dist-info/RECORD new file mode 100644 index 0000000..b3fa65d --- /dev/null +++ b/venv/lib64/python3.8/site-packages/cachy-0.3.0.dist-info/RECORD @@ -0,0 +1,53 @@ +cachy-0.3.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +cachy-0.3.0.dist-info/LICENSE,sha256=eddrvsOJnRZIIWOjZcf2XoenKZk6HWX5YPQYHi7LgaA,1062 +cachy-0.3.0.dist-info/METADATA,sha256=KK9dg-znFQygldlGs2epsfIRu37fMgVaQCO6Vi5TjGs,1472 +cachy-0.3.0.dist-info/RECORD,, +cachy-0.3.0.dist-info/WHEEL,sha256=k_UtF7DeTKrUqc0FULNabrogAWgCy8zJZKQiwD2AkC4,89 +cachy/__init__.py,sha256=y41ImV85TJlxPUkY7wNYgAhG2VQEo5_g_03WbczZ5_E,124 +cachy/__pycache__/__init__.cpython-38.pyc,, +cachy/__pycache__/cache_manager.cpython-38.pyc,, +cachy/__pycache__/helpers.cpython-38.pyc,, +cachy/__pycache__/redis_tagged_cache.cpython-38.pyc,, +cachy/__pycache__/repository.cpython-38.pyc,, +cachy/__pycache__/tag_set.cpython-38.pyc,, +cachy/__pycache__/tagged_cache.cpython-38.pyc,, +cachy/__pycache__/utils.cpython-38.pyc,, +cachy/cache_manager.py,sha256=-eL3UqPRy6uTGqyYzZmqGkYt8PrxhIx9ziu8uZIWIWQ,7339 +cachy/contracts/__init__.py,sha256=O9CT1B2F-cVB8elT0EoCJbgkcffjvlmqteqavs4giDg,25 +cachy/contracts/__pycache__/__init__.cpython-38.pyc,, +cachy/contracts/__pycache__/factory.cpython-38.pyc,, +cachy/contracts/__pycache__/repository.cpython-38.pyc,, +cachy/contracts/__pycache__/store.cpython-38.pyc,, +cachy/contracts/__pycache__/taggable_store.cpython-38.pyc,, +cachy/contracts/factory.py,sha256=F6USJ2ooGjTOFNS8gqmKxg8LHK3SZ2RgcbBxQI1QYsE,323 +cachy/contracts/repository.py,sha256=-3eqnXR8j5MiRIPlOYpec1X9DuIYNFbf_pn86XO8oDM,2942 +cachy/contracts/store.py,sha256=oxQWQEwiHIDOQj1b7CGnztrQdeFFHG5iAEVluZ-bAh8,2594 +cachy/contracts/taggable_store.py,sha256=ObQILbeu_CLBKV17r1dn3IJWjoPi4WiNboFKW7JW6RA,497 +cachy/helpers.py,sha256=pDSGH7MD2ARvumlPl6KhycFHIP_QQk5KsWRA6Vfs08U,101 +cachy/redis_tagged_cache.py,sha256=FZ8mmAd0y-QmXc7DCA0W-oJkUT7HgX-xX82QOosJV-E,2171 +cachy/repository.py,sha256=ZZHdMXeUrxvT2PJSmL9hTqeUr7fUkq527UvrZ3aQMyg,8250 +cachy/serializers/__init__.py,sha256=RuQDghzeLKWxWs8YKju6dOp75AsTcookQqOjYj9nfjs,202 +cachy/serializers/__pycache__/__init__.cpython-38.pyc,, +cachy/serializers/__pycache__/json_serializer.cpython-38.pyc,, +cachy/serializers/__pycache__/msgpack_serializer.cpython-38.pyc,, +cachy/serializers/__pycache__/pickle_serializer.cpython-38.pyc,, +cachy/serializers/__pycache__/serializer.cpython-38.pyc,, +cachy/serializers/json_serializer.py,sha256=UNjSMa0auB9cVI-Ru6NB5dtvXKqSQ1Ne66fllOLwxT0,683 +cachy/serializers/msgpack_serializer.py,sha256=UX31MOUri5KwgECKOczoTaWAeJfvVeVQujKXz560xyI,814 +cachy/serializers/pickle_serializer.py,sha256=Hc-OOLQnLfOCvYGdRO3umd2z38MNjz7IUBPLI0Ksecc,848 +cachy/serializers/serializer.py,sha256=d_1G10DNG0Myq4tO43T1RmESyZjRRiHubhKsI21D4no,513 +cachy/stores/__init__.py,sha256=9kcnXzYQl9SU9EOYfMeTZH5bT7H1y2mPZkHYuIahZDk,207 +cachy/stores/__pycache__/__init__.cpython-38.pyc,, +cachy/stores/__pycache__/dict_store.cpython-38.pyc,, +cachy/stores/__pycache__/file_store.cpython-38.pyc,, +cachy/stores/__pycache__/memcached_store.cpython-38.pyc,, +cachy/stores/__pycache__/null_store.cpython-38.pyc,, +cachy/stores/__pycache__/redis_store.cpython-38.pyc,, +cachy/stores/dict_store.py,sha256=Y8QN_yg3yzq6QxaX24Sg62lRLt0qODTV-XdVuosaNpw,3700 +cachy/stores/file_store.py,sha256=5RakbtGquztkcPBtYGg7GQ64R0lG9638zFgwbZ2TcvQ,5806 +cachy/stores/memcached_store.py,sha256=hZ1bMNDqj49eRKN3rCpO80j4XVfm1jbddyFRWIXGXRA,2984 +cachy/stores/null_store.py,sha256=2kYMfN4G9TlrAH7YMx60TT3BmNwfEA2z1AezMJcL_gk,2026 +cachy/stores/redis_store.py,sha256=0qHMDEDXxo0BIwPa1kjrSCJaeFTTipabo4yQTTSzivs,3318 +cachy/tag_set.py,sha256=R7kJUapYsd5zsnQ4MoWL9E9XgCuhUGdHXwcccpJEtwM,1665 +cachy/tagged_cache.py,sha256=A7yl7jVdMyITIM8P3aL-X_OAuEmHQP8XPz2jNMdtbzM,5835 +cachy/utils.py,sha256=w2JpCwjLDE-GpdUyuRnkQA4hXyj-cml9etZ4ReuSQGQ,1309 diff --git a/venv/lib64/python3.8/site-packages/cachy/__pycache__/__init__.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cachy/__pycache__/__init__.cpython-38.pyc new file mode 100644 index 0000000..9a6b358 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cachy/__pycache__/__init__.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cachy/__pycache__/cache_manager.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cachy/__pycache__/cache_manager.cpython-38.pyc new file mode 100644 index 0000000..b9b4afe Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cachy/__pycache__/cache_manager.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cachy/__pycache__/helpers.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cachy/__pycache__/helpers.cpython-38.pyc new file mode 100644 index 0000000..eae6d5f Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cachy/__pycache__/helpers.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cachy/__pycache__/redis_tagged_cache.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cachy/__pycache__/redis_tagged_cache.cpython-38.pyc new file mode 100644 index 0000000..1d72018 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cachy/__pycache__/redis_tagged_cache.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cachy/__pycache__/repository.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cachy/__pycache__/repository.cpython-38.pyc new file mode 100644 index 0000000..0533cc2 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cachy/__pycache__/repository.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cachy/__pycache__/tag_set.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cachy/__pycache__/tag_set.cpython-38.pyc new file mode 100644 index 0000000..14f050b Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cachy/__pycache__/tag_set.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cachy/__pycache__/tagged_cache.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cachy/__pycache__/tagged_cache.cpython-38.pyc new file mode 100644 index 0000000..e29406b Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cachy/__pycache__/tagged_cache.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cachy/__pycache__/utils.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cachy/__pycache__/utils.cpython-38.pyc new file mode 100644 index 0000000..30029c9 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cachy/__pycache__/utils.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cachy/contracts/__pycache__/__init__.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cachy/contracts/__pycache__/__init__.cpython-38.pyc new file mode 100644 index 0000000..0dac16d Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cachy/contracts/__pycache__/__init__.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cachy/contracts/__pycache__/factory.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cachy/contracts/__pycache__/factory.cpython-38.pyc new file mode 100644 index 0000000..a7b9ef8 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cachy/contracts/__pycache__/factory.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cachy/contracts/__pycache__/repository.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cachy/contracts/__pycache__/repository.cpython-38.pyc new file mode 100644 index 0000000..9518a08 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cachy/contracts/__pycache__/repository.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cachy/contracts/__pycache__/store.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cachy/contracts/__pycache__/store.cpython-38.pyc new file mode 100644 index 0000000..5502822 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cachy/contracts/__pycache__/store.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cachy/contracts/__pycache__/taggable_store.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cachy/contracts/__pycache__/taggable_store.cpython-38.pyc new file mode 100644 index 0000000..abfa15a Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cachy/contracts/__pycache__/taggable_store.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cachy/serializers/__pycache__/__init__.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cachy/serializers/__pycache__/__init__.cpython-38.pyc new file mode 100644 index 0000000..eb58723 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cachy/serializers/__pycache__/__init__.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cachy/serializers/__pycache__/json_serializer.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cachy/serializers/__pycache__/json_serializer.cpython-38.pyc new file mode 100644 index 0000000..fc70718 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cachy/serializers/__pycache__/json_serializer.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cachy/serializers/__pycache__/msgpack_serializer.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cachy/serializers/__pycache__/msgpack_serializer.cpython-38.pyc new file mode 100644 index 0000000..35a8fea Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cachy/serializers/__pycache__/msgpack_serializer.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cachy/serializers/__pycache__/pickle_serializer.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cachy/serializers/__pycache__/pickle_serializer.cpython-38.pyc new file mode 100644 index 0000000..ce86f92 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cachy/serializers/__pycache__/pickle_serializer.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cachy/serializers/__pycache__/serializer.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cachy/serializers/__pycache__/serializer.cpython-38.pyc new file mode 100644 index 0000000..ff05273 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cachy/serializers/__pycache__/serializer.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cachy/stores/__pycache__/__init__.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cachy/stores/__pycache__/__init__.cpython-38.pyc new file mode 100644 index 0000000..10f9ae1 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cachy/stores/__pycache__/__init__.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cachy/stores/__pycache__/dict_store.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cachy/stores/__pycache__/dict_store.cpython-38.pyc new file mode 100644 index 0000000..870ef85 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cachy/stores/__pycache__/dict_store.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cachy/stores/__pycache__/file_store.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cachy/stores/__pycache__/file_store.cpython-38.pyc new file mode 100644 index 0000000..efd83ca Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cachy/stores/__pycache__/file_store.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cachy/stores/__pycache__/memcached_store.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cachy/stores/__pycache__/memcached_store.cpython-38.pyc new file mode 100644 index 0000000..fccf351 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cachy/stores/__pycache__/memcached_store.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cachy/stores/__pycache__/null_store.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cachy/stores/__pycache__/null_store.cpython-38.pyc new file mode 100644 index 0000000..c9c74e4 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cachy/stores/__pycache__/null_store.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cachy/stores/__pycache__/redis_store.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cachy/stores/__pycache__/redis_store.cpython-38.pyc new file mode 100644 index 0000000..9b20e6c Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cachy/stores/__pycache__/redis_store.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/certifi-2021.10.8.dist-info/RECORD b/venv/lib64/python3.8/site-packages/certifi-2021.10.8.dist-info/RECORD new file mode 100644 index 0000000..8bc571d --- /dev/null +++ b/venv/lib64/python3.8/site-packages/certifi-2021.10.8.dist-info/RECORD @@ -0,0 +1,13 @@ +certifi-2021.10.8.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +certifi-2021.10.8.dist-info/LICENSE,sha256=vp2C82ES-Hp_HXTs1Ih-FGe7roh4qEAEoAEXseR1o-I,1049 +certifi-2021.10.8.dist-info/METADATA,sha256=iB_zbT1uX_8_NC7iGv0YEB-9b3idhQwHrFTSq8R1kD8,2994 +certifi-2021.10.8.dist-info/RECORD,, +certifi-2021.10.8.dist-info/WHEEL,sha256=ADKeyaGyKF5DwBNE0sRE5pvW-bSkFMJfBuhzZ3rceP4,110 +certifi-2021.10.8.dist-info/top_level.txt,sha256=KMu4vUCfsjLrkPbSNdgdekS-pVJzBAJFO__nI8NF6-U,8 +certifi/__init__.py,sha256=xWdRgntT3j1V95zkRipGOg_A1UfEju2FcpujhysZLRI,62 +certifi/__main__.py,sha256=xBBoj905TUWBLRGANOcf7oi6e-3dMP4cEoG9OyMs11g,243 +certifi/__pycache__/__init__.cpython-38.pyc,, +certifi/__pycache__/__main__.cpython-38.pyc,, +certifi/__pycache__/core.cpython-38.pyc,, +certifi/cacert.pem,sha256=-og4Keu4zSpgL5shwfhd4kz0eUnVILzrGCi0zRy2kGw,265969 +certifi/core.py,sha256=V0uyxKOYdz6ulDSusclrLmjbPgOXsD0BnEf0SQ7OnoE,2303 diff --git a/venv/lib64/python3.8/site-packages/cffi/__pycache__/__init__.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cffi/__pycache__/__init__.cpython-38.pyc new file mode 100644 index 0000000..9da4ec9 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cffi/__pycache__/__init__.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cffi/__pycache__/api.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cffi/__pycache__/api.cpython-38.pyc new file mode 100644 index 0000000..c876083 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cffi/__pycache__/api.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cffi/__pycache__/backend_ctypes.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cffi/__pycache__/backend_ctypes.cpython-38.pyc new file mode 100644 index 0000000..bc6d860 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cffi/__pycache__/backend_ctypes.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cffi/__pycache__/cffi_opcode.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cffi/__pycache__/cffi_opcode.cpython-38.pyc new file mode 100644 index 0000000..5326bc9 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cffi/__pycache__/cffi_opcode.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cffi/__pycache__/commontypes.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cffi/__pycache__/commontypes.cpython-38.pyc new file mode 100644 index 0000000..29e4d4b Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cffi/__pycache__/commontypes.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cffi/__pycache__/cparser.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cffi/__pycache__/cparser.cpython-38.pyc new file mode 100644 index 0000000..d1b09fe Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cffi/__pycache__/cparser.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cffi/__pycache__/error.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cffi/__pycache__/error.cpython-38.pyc new file mode 100644 index 0000000..17e2924 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cffi/__pycache__/error.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cffi/__pycache__/ffiplatform.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cffi/__pycache__/ffiplatform.cpython-38.pyc new file mode 100644 index 0000000..78a62c8 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cffi/__pycache__/ffiplatform.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cffi/__pycache__/lock.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cffi/__pycache__/lock.cpython-38.pyc new file mode 100644 index 0000000..f3c6f46 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cffi/__pycache__/lock.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cffi/__pycache__/model.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cffi/__pycache__/model.cpython-38.pyc new file mode 100644 index 0000000..caa9ac7 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cffi/__pycache__/model.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cffi/__pycache__/pkgconfig.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cffi/__pycache__/pkgconfig.cpython-38.pyc new file mode 100644 index 0000000..a82b7ea Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cffi/__pycache__/pkgconfig.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cffi/__pycache__/recompiler.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cffi/__pycache__/recompiler.cpython-38.pyc new file mode 100644 index 0000000..ec1d31f Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cffi/__pycache__/recompiler.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cffi/__pycache__/setuptools_ext.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cffi/__pycache__/setuptools_ext.cpython-38.pyc new file mode 100644 index 0000000..f8473f4 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cffi/__pycache__/setuptools_ext.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cffi/__pycache__/vengine_cpy.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cffi/__pycache__/vengine_cpy.cpython-38.pyc new file mode 100644 index 0000000..052206d Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cffi/__pycache__/vengine_cpy.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cffi/__pycache__/vengine_gen.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cffi/__pycache__/vengine_gen.cpython-38.pyc new file mode 100644 index 0000000..9a8d4dc Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cffi/__pycache__/vengine_gen.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cffi/__pycache__/verifier.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cffi/__pycache__/verifier.cpython-38.pyc new file mode 100644 index 0000000..c4a6316 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cffi/__pycache__/verifier.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/chardet-3.0.4.dist-info/INSTALLER b/venv/lib64/python3.8/site-packages/chardet-3.0.4.dist-info/INSTALLER new file mode 100644 index 0000000..a1b589e --- /dev/null +++ b/venv/lib64/python3.8/site-packages/chardet-3.0.4.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/venv/lib64/python3.8/site-packages/chardet-3.0.4.dist-info/RECORD b/venv/lib64/python3.8/site-packages/chardet-3.0.4.dist-info/RECORD new file mode 100644 index 0000000..03a9c74 --- /dev/null +++ b/venv/lib64/python3.8/site-packages/chardet-3.0.4.dist-info/RECORD @@ -0,0 +1,91 @@ +../../../bin/chardetect,sha256=xGOtRC9bH4Njk5bR4U6EseCjckcXHcCD7m6lwrycVOk,240 +chardet-3.0.4.dist-info/DESCRIPTION.rst,sha256=PQ4sBsMyKFZkjC6QpmbpLn0UtCNyeb-ZqvCGEgyZMGk,2174 +chardet-3.0.4.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +chardet-3.0.4.dist-info/METADATA,sha256=RV_2I4B1Z586DL8oVO5Kp7X5bUdQ5EuKAvNoAEF8wSw,3239 +chardet-3.0.4.dist-info/RECORD,, +chardet-3.0.4.dist-info/WHEEL,sha256=o2k-Qa-RMNIJmUdIc7KU6VWR_ErNRbWNlxDIpl7lm34,110 +chardet-3.0.4.dist-info/entry_points.txt,sha256=fAMmhu5eJ-zAJ-smfqQwRClQ3-nozOCmvJ6-E8lgGJo,60 +chardet-3.0.4.dist-info/metadata.json,sha256=0htbRM18ujyGZDdfowgAqj6Hq2eQtwzwyhaEveKntgo,1375 +chardet-3.0.4.dist-info/top_level.txt,sha256=AowzBbZy4x8EirABDdJSLJZMkJ_53iIag8xfKR6D7kI,8 +chardet/__init__.py,sha256=YsP5wQlsHJ2auF1RZJfypiSrCA7_bQiRm3ES_NI76-Y,1559 +chardet/__pycache__/__init__.cpython-38.pyc,, +chardet/__pycache__/big5freq.cpython-38.pyc,, +chardet/__pycache__/big5prober.cpython-38.pyc,, +chardet/__pycache__/chardistribution.cpython-38.pyc,, +chardet/__pycache__/charsetgroupprober.cpython-38.pyc,, +chardet/__pycache__/charsetprober.cpython-38.pyc,, +chardet/__pycache__/codingstatemachine.cpython-38.pyc,, +chardet/__pycache__/compat.cpython-38.pyc,, +chardet/__pycache__/cp949prober.cpython-38.pyc,, +chardet/__pycache__/enums.cpython-38.pyc,, +chardet/__pycache__/escprober.cpython-38.pyc,, +chardet/__pycache__/escsm.cpython-38.pyc,, +chardet/__pycache__/eucjpprober.cpython-38.pyc,, +chardet/__pycache__/euckrfreq.cpython-38.pyc,, +chardet/__pycache__/euckrprober.cpython-38.pyc,, +chardet/__pycache__/euctwfreq.cpython-38.pyc,, +chardet/__pycache__/euctwprober.cpython-38.pyc,, +chardet/__pycache__/gb2312freq.cpython-38.pyc,, +chardet/__pycache__/gb2312prober.cpython-38.pyc,, +chardet/__pycache__/hebrewprober.cpython-38.pyc,, +chardet/__pycache__/jisfreq.cpython-38.pyc,, +chardet/__pycache__/jpcntx.cpython-38.pyc,, +chardet/__pycache__/langbulgarianmodel.cpython-38.pyc,, +chardet/__pycache__/langcyrillicmodel.cpython-38.pyc,, +chardet/__pycache__/langgreekmodel.cpython-38.pyc,, +chardet/__pycache__/langhebrewmodel.cpython-38.pyc,, +chardet/__pycache__/langhungarianmodel.cpython-38.pyc,, +chardet/__pycache__/langthaimodel.cpython-38.pyc,, +chardet/__pycache__/langturkishmodel.cpython-38.pyc,, +chardet/__pycache__/latin1prober.cpython-38.pyc,, +chardet/__pycache__/mbcharsetprober.cpython-38.pyc,, +chardet/__pycache__/mbcsgroupprober.cpython-38.pyc,, +chardet/__pycache__/mbcssm.cpython-38.pyc,, +chardet/__pycache__/sbcharsetprober.cpython-38.pyc,, +chardet/__pycache__/sbcsgroupprober.cpython-38.pyc,, +chardet/__pycache__/sjisprober.cpython-38.pyc,, +chardet/__pycache__/universaldetector.cpython-38.pyc,, +chardet/__pycache__/utf8prober.cpython-38.pyc,, +chardet/__pycache__/version.cpython-38.pyc,, +chardet/big5freq.py,sha256=D_zK5GyzoVsRes0HkLJziltFQX0bKCLOrFe9_xDvO_8,31254 +chardet/big5prober.py,sha256=kBxHbdetBpPe7xrlb-e990iot64g_eGSLd32lB7_h3M,1757 +chardet/chardistribution.py,sha256=3woWS62KrGooKyqz4zQSnjFbJpa6V7g02daAibTwcl8,9411 +chardet/charsetgroupprober.py,sha256=6bDu8YIiRuScX4ca9Igb0U69TA2PGXXDej6Cc4_9kO4,3787 +chardet/charsetprober.py,sha256=KSmwJErjypyj0bRZmC5F5eM7c8YQgLYIjZXintZNstg,5110 +chardet/cli/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1 +chardet/cli/__pycache__/__init__.cpython-38.pyc,, +chardet/cli/__pycache__/chardetect.cpython-38.pyc,, +chardet/cli/chardetect.py,sha256=YBO8L4mXo0WR6_-Fjh_8QxPBoEBNqB9oNxNrdc54AQs,2738 +chardet/codingstatemachine.py,sha256=VYp_6cyyki5sHgXDSZnXW4q1oelHc3cu9AyQTX7uug8,3590 +chardet/compat.py,sha256=PKTzHkSbtbHDqS9PyujMbX74q1a8mMpeQTDVsQhZMRw,1134 +chardet/cp949prober.py,sha256=TZ434QX8zzBsnUvL_8wm4AQVTZ2ZkqEEQL_lNw9f9ow,1855 +chardet/enums.py,sha256=Aimwdb9as1dJKZaFNUH2OhWIVBVd6ZkJJ_WK5sNY8cU,1661 +chardet/escprober.py,sha256=kkyqVg1Yw3DIOAMJ2bdlyQgUFQhuHAW8dUGskToNWSc,3950 +chardet/escsm.py,sha256=RuXlgNvTIDarndvllNCk5WZBIpdCxQ0kcd9EAuxUh84,10510 +chardet/eucjpprober.py,sha256=iD8Jdp0ISRjgjiVN7f0e8xGeQJ5GM2oeZ1dA8nbSeUw,3749 +chardet/euckrfreq.py,sha256=-7GdmvgWez4-eO4SuXpa7tBiDi5vRXQ8WvdFAzVaSfo,13546 +chardet/euckrprober.py,sha256=MqFMTQXxW4HbzIpZ9lKDHB3GN8SP4yiHenTmf8g_PxY,1748 +chardet/euctwfreq.py,sha256=No1WyduFOgB5VITUA7PLyC5oJRNzRyMbBxaKI1l16MA,31621 +chardet/euctwprober.py,sha256=13p6EP4yRaxqnP4iHtxHOJ6R2zxHq1_m8hTRjzVZ95c,1747 +chardet/gb2312freq.py,sha256=JX8lsweKLmnCwmk8UHEQsLgkr_rP_kEbvivC4qPOrlc,20715 +chardet/gb2312prober.py,sha256=gGvIWi9WhDjE-xQXHvNIyrnLvEbMAYgyUSZ65HUfylw,1754 +chardet/hebrewprober.py,sha256=c3SZ-K7hvyzGY6JRAZxJgwJ_sUS9k0WYkvMY00YBYFo,13838 +chardet/jisfreq.py,sha256=vpmJv2Bu0J8gnMVRPHMFefTRvo_ha1mryLig8CBwgOg,25777 +chardet/jpcntx.py,sha256=PYlNqRUQT8LM3cT5FmHGP0iiscFlTWED92MALvBungo,19643 +chardet/langbulgarianmodel.py,sha256=1HqQS9Pbtnj1xQgxitJMvw8X6kKr5OockNCZWfEQrPE,12839 +chardet/langcyrillicmodel.py,sha256=LODajvsetH87yYDDQKA2CULXUH87tI223dhfjh9Zx9c,17948 +chardet/langgreekmodel.py,sha256=8YAW7bU8YwSJap0kIJSbPMw1BEqzGjWzqcqf0WgUKAA,12688 +chardet/langhebrewmodel.py,sha256=JSnqmE5E62tDLTPTvLpQsg5gOMO4PbdWRvV7Avkc0HA,11345 +chardet/langhungarianmodel.py,sha256=RhapYSG5l0ZaO-VV4Fan5sW0WRGQqhwBM61yx3yxyOA,12592 +chardet/langthaimodel.py,sha256=8l0173Gu_W6G8mxmQOTEF4ls2YdE7FxWf3QkSxEGXJQ,11290 +chardet/langturkishmodel.py,sha256=W22eRNJsqI6uWAfwXSKVWWnCerYqrI8dZQTm_M0lRFk,11102 +chardet/latin1prober.py,sha256=S2IoORhFk39FEFOlSFWtgVybRiP6h7BlLldHVclNkU8,5370 +chardet/mbcharsetprober.py,sha256=AR95eFH9vuqSfvLQZN-L5ijea25NOBCoXqw8s5O9xLQ,3413 +chardet/mbcsgroupprober.py,sha256=h6TRnnYq2OxG1WdD5JOyxcdVpn7dG0q-vB8nWr5mbh4,2012 +chardet/mbcssm.py,sha256=SY32wVIF3HzcjY3BaEspy9metbNSKxIIB0RKPn7tjpI,25481 +chardet/sbcharsetprober.py,sha256=LDSpCldDCFlYwUkGkwD2oFxLlPWIWXT09akH_2PiY74,5657 +chardet/sbcsgroupprober.py,sha256=1IprcCB_k1qfmnxGC6MBbxELlKqD3scW6S8YIwdeyXA,3546 +chardet/sjisprober.py,sha256=IIt-lZj0WJqK4rmUZzKZP4GJlE8KUEtFYVuY96ek5MQ,3774 +chardet/universaldetector.py,sha256=qL0174lSZE442eB21nnktT9_VcAye07laFWUeUrjttY,12485 +chardet/utf8prober.py,sha256=IdD8v3zWOsB8OLiyPi-y_fqwipRFxV9Nc1eKBLSuIEw,2766 +chardet/version.py,sha256=sp3B08mrDXB-pf3K9fqJ_zeDHOCLC8RrngQyDFap_7g,242 diff --git a/venv/lib64/python3.8/site-packages/chardet/__pycache__/__init__.cpython-38.pyc b/venv/lib64/python3.8/site-packages/chardet/__pycache__/__init__.cpython-38.pyc new file mode 100644 index 0000000..a6cc37b Binary files /dev/null and b/venv/lib64/python3.8/site-packages/chardet/__pycache__/__init__.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/chardet/__pycache__/big5freq.cpython-38.pyc b/venv/lib64/python3.8/site-packages/chardet/__pycache__/big5freq.cpython-38.pyc new file mode 100644 index 0000000..955be46 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/chardet/__pycache__/big5freq.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/chardet/__pycache__/big5prober.cpython-38.pyc b/venv/lib64/python3.8/site-packages/chardet/__pycache__/big5prober.cpython-38.pyc new file mode 100644 index 0000000..c572337 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/chardet/__pycache__/big5prober.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/chardet/__pycache__/chardistribution.cpython-38.pyc b/venv/lib64/python3.8/site-packages/chardet/__pycache__/chardistribution.cpython-38.pyc new file mode 100644 index 0000000..289b47a Binary files /dev/null and b/venv/lib64/python3.8/site-packages/chardet/__pycache__/chardistribution.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/chardet/__pycache__/charsetgroupprober.cpython-38.pyc b/venv/lib64/python3.8/site-packages/chardet/__pycache__/charsetgroupprober.cpython-38.pyc new file mode 100644 index 0000000..0c5cf12 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/chardet/__pycache__/charsetgroupprober.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/chardet/__pycache__/charsetprober.cpython-38.pyc b/venv/lib64/python3.8/site-packages/chardet/__pycache__/charsetprober.cpython-38.pyc new file mode 100644 index 0000000..1d779e4 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/chardet/__pycache__/charsetprober.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/chardet/__pycache__/codingstatemachine.cpython-38.pyc b/venv/lib64/python3.8/site-packages/chardet/__pycache__/codingstatemachine.cpython-38.pyc new file mode 100644 index 0000000..58c2b6c Binary files /dev/null and b/venv/lib64/python3.8/site-packages/chardet/__pycache__/codingstatemachine.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/chardet/__pycache__/compat.cpython-38.pyc b/venv/lib64/python3.8/site-packages/chardet/__pycache__/compat.cpython-38.pyc new file mode 100644 index 0000000..51381b3 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/chardet/__pycache__/compat.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/chardet/__pycache__/cp949prober.cpython-38.pyc b/venv/lib64/python3.8/site-packages/chardet/__pycache__/cp949prober.cpython-38.pyc new file mode 100644 index 0000000..935761c Binary files /dev/null and b/venv/lib64/python3.8/site-packages/chardet/__pycache__/cp949prober.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/chardet/__pycache__/enums.cpython-38.pyc b/venv/lib64/python3.8/site-packages/chardet/__pycache__/enums.cpython-38.pyc new file mode 100644 index 0000000..1ca3954 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/chardet/__pycache__/enums.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/chardet/__pycache__/escprober.cpython-38.pyc b/venv/lib64/python3.8/site-packages/chardet/__pycache__/escprober.cpython-38.pyc new file mode 100644 index 0000000..a849b2d Binary files /dev/null and b/venv/lib64/python3.8/site-packages/chardet/__pycache__/escprober.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/chardet/__pycache__/escsm.cpython-38.pyc b/venv/lib64/python3.8/site-packages/chardet/__pycache__/escsm.cpython-38.pyc new file mode 100644 index 0000000..8573cd6 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/chardet/__pycache__/escsm.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/chardet/__pycache__/eucjpprober.cpython-38.pyc b/venv/lib64/python3.8/site-packages/chardet/__pycache__/eucjpprober.cpython-38.pyc new file mode 100644 index 0000000..b15d222 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/chardet/__pycache__/eucjpprober.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/chardet/__pycache__/euckrfreq.cpython-38.pyc b/venv/lib64/python3.8/site-packages/chardet/__pycache__/euckrfreq.cpython-38.pyc new file mode 100644 index 0000000..1dc4770 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/chardet/__pycache__/euckrfreq.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/chardet/__pycache__/euckrprober.cpython-38.pyc b/venv/lib64/python3.8/site-packages/chardet/__pycache__/euckrprober.cpython-38.pyc new file mode 100644 index 0000000..b0c0f6f Binary files /dev/null and b/venv/lib64/python3.8/site-packages/chardet/__pycache__/euckrprober.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/chardet/__pycache__/euctwfreq.cpython-38.pyc b/venv/lib64/python3.8/site-packages/chardet/__pycache__/euctwfreq.cpython-38.pyc new file mode 100644 index 0000000..1a197f6 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/chardet/__pycache__/euctwfreq.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/chardet/__pycache__/euctwprober.cpython-38.pyc b/venv/lib64/python3.8/site-packages/chardet/__pycache__/euctwprober.cpython-38.pyc new file mode 100644 index 0000000..7f87e8e Binary files /dev/null and b/venv/lib64/python3.8/site-packages/chardet/__pycache__/euctwprober.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/chardet/__pycache__/gb2312freq.cpython-38.pyc b/venv/lib64/python3.8/site-packages/chardet/__pycache__/gb2312freq.cpython-38.pyc new file mode 100644 index 0000000..b3443c0 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/chardet/__pycache__/gb2312freq.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/chardet/__pycache__/gb2312prober.cpython-38.pyc b/venv/lib64/python3.8/site-packages/chardet/__pycache__/gb2312prober.cpython-38.pyc new file mode 100644 index 0000000..bce1ac1 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/chardet/__pycache__/gb2312prober.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/chardet/__pycache__/hebrewprober.cpython-38.pyc b/venv/lib64/python3.8/site-packages/chardet/__pycache__/hebrewprober.cpython-38.pyc new file mode 100644 index 0000000..c198fba Binary files /dev/null and b/venv/lib64/python3.8/site-packages/chardet/__pycache__/hebrewprober.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/chardet/__pycache__/jisfreq.cpython-38.pyc b/venv/lib64/python3.8/site-packages/chardet/__pycache__/jisfreq.cpython-38.pyc new file mode 100644 index 0000000..112a274 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/chardet/__pycache__/jisfreq.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/chardet/__pycache__/jpcntx.cpython-38.pyc b/venv/lib64/python3.8/site-packages/chardet/__pycache__/jpcntx.cpython-38.pyc new file mode 100644 index 0000000..339b5fb Binary files /dev/null and b/venv/lib64/python3.8/site-packages/chardet/__pycache__/jpcntx.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/chardet/__pycache__/langbulgarianmodel.cpython-38.pyc b/venv/lib64/python3.8/site-packages/chardet/__pycache__/langbulgarianmodel.cpython-38.pyc new file mode 100644 index 0000000..1a23197 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/chardet/__pycache__/langbulgarianmodel.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/chardet/__pycache__/langcyrillicmodel.cpython-38.pyc b/venv/lib64/python3.8/site-packages/chardet/__pycache__/langcyrillicmodel.cpython-38.pyc new file mode 100644 index 0000000..eb83a80 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/chardet/__pycache__/langcyrillicmodel.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/chardet/__pycache__/langgreekmodel.cpython-38.pyc b/venv/lib64/python3.8/site-packages/chardet/__pycache__/langgreekmodel.cpython-38.pyc new file mode 100644 index 0000000..bff548c Binary files /dev/null and b/venv/lib64/python3.8/site-packages/chardet/__pycache__/langgreekmodel.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/chardet/__pycache__/langhebrewmodel.cpython-38.pyc b/venv/lib64/python3.8/site-packages/chardet/__pycache__/langhebrewmodel.cpython-38.pyc new file mode 100644 index 0000000..f4ae693 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/chardet/__pycache__/langhebrewmodel.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/chardet/__pycache__/langhungarianmodel.cpython-38.pyc b/venv/lib64/python3.8/site-packages/chardet/__pycache__/langhungarianmodel.cpython-38.pyc new file mode 100644 index 0000000..f5206bb Binary files /dev/null and b/venv/lib64/python3.8/site-packages/chardet/__pycache__/langhungarianmodel.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/chardet/__pycache__/langthaimodel.cpython-38.pyc b/venv/lib64/python3.8/site-packages/chardet/__pycache__/langthaimodel.cpython-38.pyc new file mode 100644 index 0000000..33e00bd Binary files /dev/null and b/venv/lib64/python3.8/site-packages/chardet/__pycache__/langthaimodel.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/chardet/__pycache__/langturkishmodel.cpython-38.pyc b/venv/lib64/python3.8/site-packages/chardet/__pycache__/langturkishmodel.cpython-38.pyc new file mode 100644 index 0000000..87732d2 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/chardet/__pycache__/langturkishmodel.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/chardet/__pycache__/latin1prober.cpython-38.pyc b/venv/lib64/python3.8/site-packages/chardet/__pycache__/latin1prober.cpython-38.pyc new file mode 100644 index 0000000..61873e6 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/chardet/__pycache__/latin1prober.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/chardet/__pycache__/mbcharsetprober.cpython-38.pyc b/venv/lib64/python3.8/site-packages/chardet/__pycache__/mbcharsetprober.cpython-38.pyc new file mode 100644 index 0000000..4507696 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/chardet/__pycache__/mbcharsetprober.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/chardet/__pycache__/mbcsgroupprober.cpython-38.pyc b/venv/lib64/python3.8/site-packages/chardet/__pycache__/mbcsgroupprober.cpython-38.pyc new file mode 100644 index 0000000..88a9948 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/chardet/__pycache__/mbcsgroupprober.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/chardet/__pycache__/mbcssm.cpython-38.pyc b/venv/lib64/python3.8/site-packages/chardet/__pycache__/mbcssm.cpython-38.pyc new file mode 100644 index 0000000..38b4b1c Binary files /dev/null and b/venv/lib64/python3.8/site-packages/chardet/__pycache__/mbcssm.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/chardet/__pycache__/sbcharsetprober.cpython-38.pyc b/venv/lib64/python3.8/site-packages/chardet/__pycache__/sbcharsetprober.cpython-38.pyc new file mode 100644 index 0000000..94e0da0 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/chardet/__pycache__/sbcharsetprober.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/chardet/__pycache__/sbcsgroupprober.cpython-38.pyc b/venv/lib64/python3.8/site-packages/chardet/__pycache__/sbcsgroupprober.cpython-38.pyc new file mode 100644 index 0000000..73ac214 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/chardet/__pycache__/sbcsgroupprober.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/chardet/__pycache__/sjisprober.cpython-38.pyc b/venv/lib64/python3.8/site-packages/chardet/__pycache__/sjisprober.cpython-38.pyc new file mode 100644 index 0000000..518e7dd Binary files /dev/null and b/venv/lib64/python3.8/site-packages/chardet/__pycache__/sjisprober.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/chardet/__pycache__/universaldetector.cpython-38.pyc b/venv/lib64/python3.8/site-packages/chardet/__pycache__/universaldetector.cpython-38.pyc new file mode 100644 index 0000000..4fc08a2 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/chardet/__pycache__/universaldetector.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/chardet/__pycache__/utf8prober.cpython-38.pyc b/venv/lib64/python3.8/site-packages/chardet/__pycache__/utf8prober.cpython-38.pyc new file mode 100644 index 0000000..0ba3757 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/chardet/__pycache__/utf8prober.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/chardet/__pycache__/version.cpython-38.pyc b/venv/lib64/python3.8/site-packages/chardet/__pycache__/version.cpython-38.pyc new file mode 100644 index 0000000..50e2121 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/chardet/__pycache__/version.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/chardet/cli/__pycache__/__init__.cpython-38.pyc b/venv/lib64/python3.8/site-packages/chardet/cli/__pycache__/__init__.cpython-38.pyc new file mode 100644 index 0000000..4b11595 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/chardet/cli/__pycache__/__init__.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/chardet/cli/__pycache__/chardetect.cpython-38.pyc b/venv/lib64/python3.8/site-packages/chardet/cli/__pycache__/chardetect.cpython-38.pyc new file mode 100644 index 0000000..8a246a1 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/chardet/cli/__pycache__/chardetect.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cleo/__pycache__/__init__.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cleo/__pycache__/__init__.cpython-38.pyc new file mode 100644 index 0000000..abb4e98 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cleo/__pycache__/__init__.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cleo/__pycache__/_compat.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cleo/__pycache__/_compat.cpython-38.pyc new file mode 100644 index 0000000..8db2e14 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cleo/__pycache__/_compat.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cleo/__pycache__/application.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cleo/__pycache__/application.cpython-38.pyc new file mode 100644 index 0000000..d3b6e77 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cleo/__pycache__/application.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cleo/__pycache__/helpers.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cleo/__pycache__/helpers.cpython-38.pyc new file mode 100644 index 0000000..8496f43 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cleo/__pycache__/helpers.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cleo/__pycache__/parser.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cleo/__pycache__/parser.cpython-38.pyc new file mode 100644 index 0000000..95a9b2d Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cleo/__pycache__/parser.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cleo/commands/__pycache__/__init__.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cleo/commands/__pycache__/__init__.cpython-38.pyc new file mode 100644 index 0000000..920fdde Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cleo/commands/__pycache__/__init__.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cleo/commands/__pycache__/base_command.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cleo/commands/__pycache__/base_command.cpython-38.pyc new file mode 100644 index 0000000..90f6255 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cleo/commands/__pycache__/base_command.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cleo/commands/__pycache__/command.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cleo/commands/__pycache__/command.cpython-38.pyc new file mode 100644 index 0000000..3f7b9a0 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cleo/commands/__pycache__/command.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cleo/commands/__pycache__/completions_command.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cleo/commands/__pycache__/completions_command.cpython-38.pyc new file mode 100644 index 0000000..28fa4d1 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cleo/commands/__pycache__/completions_command.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cleo/commands/completions/__pycache__/__init__.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cleo/commands/completions/__pycache__/__init__.cpython-38.pyc new file mode 100644 index 0000000..75446b7 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cleo/commands/completions/__pycache__/__init__.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cleo/commands/completions/__pycache__/templates.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cleo/commands/completions/__pycache__/templates.cpython-38.pyc new file mode 100644 index 0000000..a058b68 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cleo/commands/completions/__pycache__/templates.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cleo/config/__pycache__/__init__.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cleo/config/__pycache__/__init__.cpython-38.pyc new file mode 100644 index 0000000..59afa8c Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cleo/config/__pycache__/__init__.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cleo/config/__pycache__/application_config.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cleo/config/__pycache__/application_config.cpython-38.pyc new file mode 100644 index 0000000..ccbfc3a Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cleo/config/__pycache__/application_config.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cleo/io/__pycache__/__init__.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cleo/io/__pycache__/__init__.cpython-38.pyc new file mode 100644 index 0000000..dee60e4 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cleo/io/__pycache__/__init__.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cleo/io/__pycache__/buffered_io.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cleo/io/__pycache__/buffered_io.cpython-38.pyc new file mode 100644 index 0000000..a936df0 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cleo/io/__pycache__/buffered_io.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cleo/io/__pycache__/console_io.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cleo/io/__pycache__/console_io.cpython-38.pyc new file mode 100644 index 0000000..75a203f Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cleo/io/__pycache__/console_io.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cleo/io/__pycache__/io_mixin.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cleo/io/__pycache__/io_mixin.cpython-38.pyc new file mode 100644 index 0000000..32d2472 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cleo/io/__pycache__/io_mixin.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cleo/testers/__pycache__/__init__.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cleo/testers/__pycache__/__init__.cpython-38.pyc new file mode 100644 index 0000000..1622999 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cleo/testers/__pycache__/__init__.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cleo/testers/__pycache__/application_tester.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cleo/testers/__pycache__/application_tester.cpython-38.pyc new file mode 100644 index 0000000..d47fcc6 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cleo/testers/__pycache__/application_tester.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cleo/testers/__pycache__/command_tester.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cleo/testers/__pycache__/command_tester.cpython-38.pyc new file mode 100644 index 0000000..be304a1 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cleo/testers/__pycache__/command_tester.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/clikit-0.6.2.dist-info/RECORD b/venv/lib64/python3.8/site-packages/clikit-0.6.2.dist-info/RECORD new file mode 100644 index 0000000..b2253f9 --- /dev/null +++ b/venv/lib64/python3.8/site-packages/clikit-0.6.2.dist-info/RECORD @@ -0,0 +1,255 @@ +clikit-0.6.2.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +clikit-0.6.2.dist-info/LICENSE,sha256=8vm0YLpxnaZiat0mTTeC8nWk_3qrZ3vtoIszCRHiOts,1062 +clikit-0.6.2.dist-info/METADATA,sha256=VQIBgL3IqQgxgXx87aCwJD8YktAA1q3aRyfwuJr2fr4,1581 +clikit-0.6.2.dist-info/RECORD,, +clikit-0.6.2.dist-info/WHEEL,sha256=BcHwX75L5o9y8NN94BU-O_IP_7AP-vrh-M6RWGoded0,87 +clikit/__init__.py,sha256=672ya2xDu_gkHfPFkW8oh4YATmywus0kDO_H5-IvsCw,208 +clikit/__pycache__/__init__.cpython-38.pyc,, +clikit/__pycache__/console_application.cpython-38.pyc,, +clikit/adapter/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +clikit/adapter/__pycache__/__init__.cpython-38.pyc,, +clikit/adapter/__pycache__/style_converter.cpython-38.pyc,, +clikit/adapter/style_converter.py,sha256=jdauKvcNCaSF_LatoaO942wU00Sh24aY-74hq4IEcR8,860 +clikit/api/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +clikit/api/__pycache__/__init__.cpython-38.pyc,, +clikit/api/__pycache__/exceptions.cpython-38.pyc,, +clikit/api/application/__init__.py,sha256=FoOc_AS7QiydMuCon44T4ZiOCyIEjr27cH5uT618-OE,37 +clikit/api/application/__pycache__/__init__.cpython-38.pyc,, +clikit/api/application/__pycache__/application.cpython-38.pyc,, +clikit/api/application/application.py,sha256=Tv2Me8HWf44ULl7kh59qctwvnr-rr1nP4fo-S5XbR68,1775 +clikit/api/args/__init__.py,sha256=sZQSI_WC4tcrpqsuxnEcAYeS1ZbcOTxWJYgI9sheTcs,89 +clikit/api/args/__pycache__/__init__.cpython-38.pyc,, +clikit/api/args/__pycache__/args.cpython-38.pyc,, +clikit/api/args/__pycache__/args_parser.cpython-38.pyc,, +clikit/api/args/__pycache__/exceptions.cpython-38.pyc,, +clikit/api/args/__pycache__/raw_args.cpython-38.pyc,, +clikit/api/args/args.py,sha256=3OQ5m6dWfShmQxbNqwgAJg9gsx20dASMd4S7C_IFP5Y,3837 +clikit/api/args/args_parser.py,sha256=chddl-5uf83oreakhusFWAFWZstuTgdTIbslWHY_Q1M,350 +clikit/api/args/exceptions.py,sha256=FSRjsZQJHf2EhDDLQZG3ehy7KnDVYnFjGgDNTvilZZA,1999 +clikit/api/args/format/__init__.py,sha256=GgBjypUc6-OOeOXxZcavu5l7Qu_OdlqKcusTGHZHIZE,225 +clikit/api/args/format/__pycache__/__init__.cpython-38.pyc,, +clikit/api/args/format/__pycache__/abstract_option.cpython-38.pyc,, +clikit/api/args/format/__pycache__/args_format.cpython-38.pyc,, +clikit/api/args/format/__pycache__/args_format_builder.cpython-38.pyc,, +clikit/api/args/format/__pycache__/argument.cpython-38.pyc,, +clikit/api/args/format/__pycache__/command_name.cpython-38.pyc,, +clikit/api/args/format/__pycache__/command_option.cpython-38.pyc,, +clikit/api/args/format/__pycache__/option.cpython-38.pyc,, +clikit/api/args/format/abstract_option.py,sha256=zzqZ7dhBy-ZQKPyM-ixf-1dkvhD2h34xXhuS2gRLsfc,4360 +clikit/api/args/format/args_format.py,sha256=da0dG9Q79t-_j-m_LoThPA7w5HIvjYs55Gvrn2lhQ2c,8371 +clikit/api/args/format/args_format_builder.py,sha256=VaJl79nHpdnqz6fm6eJmuCAJNtBkjDKN8bWBq89lKQw,11308 +clikit/api/args/format/argument.py,sha256=mMYpY--eJqd5CNQpHrLGPFzVohMVXcg7-CnQtu2RR_E,5222 +clikit/api/args/format/command_name.py,sha256=R5mHuudJ0sKy47qVBMpQhI2cBaDdqTvvATsWRgJQo14,828 +clikit/api/args/format/command_option.py,sha256=tBMRIm2eAVEpYDh_GPmyDbhKq9xpjvn7g8bpWWyrXqg,1792 +clikit/api/args/format/option.py,sha256=NbSSFjH6ujR0a16_AZf-mT3dcYnozGW5dANidoEiNDA,5312 +clikit/api/args/raw_args.py,sha256=lmtJHySybizLekRblhyfjApOGg50da2GlQc0Eh02yHc,812 +clikit/api/command/__init__.py,sha256=0791MZSWZM0hNoIp54JgGEolyRxZVvbrshEmrGneAbo,79 +clikit/api/command/__pycache__/__init__.cpython-38.pyc,, +clikit/api/command/__pycache__/command.cpython-38.pyc,, +clikit/api/command/__pycache__/command_collection.cpython-38.pyc,, +clikit/api/command/__pycache__/exceptions.cpython-38.pyc,, +clikit/api/command/command.py,sha256=n4CyIcKpA02tL-u_hagjN5NQy3tbGHGiJLGu_VLxNag,5500 +clikit/api/command/command_collection.py,sha256=DgOihRbOFw9YxAo0DJlKXLdic_J2160eqCRCK1HJ5Fw,1930 +clikit/api/command/exceptions.py,sha256=cur-caKkWd7PkKgOjL725CwrO4lUGXOtE1zo1vx2ugY,683 +clikit/api/config/__init__.py,sha256=eyPIKClyLxlsbmAGfRAmUT1ZnnqNmiXNYd8mMMtZn30,92 +clikit/api/config/__pycache__/__init__.cpython-38.pyc,, +clikit/api/config/__pycache__/application_config.cpython-38.pyc,, +clikit/api/config/__pycache__/command_config.cpython-38.pyc,, +clikit/api/config/__pycache__/config.cpython-38.pyc,, +clikit/api/config/application_config.py,sha256=N_LDUeYWbBv_GNNuv1W4GovBGUGCQvT-jWNbr0TUr2E,7640 +clikit/api/config/command_config.py,sha256=9hO6llUVX0x2z13EkAJB06XJruZBzbiEA9CJo8K7kaA,7280 +clikit/api/config/config.py,sha256=2ifrvAYJ7XnUj2-hmP8azD8tjGvooPnRHadZymBzHJk,4101 +clikit/api/event/__init__.py,sha256=iK44q99DJj6jI3-FSTbg87ZKSDQKpxuZfjhDazzElHk,315 +clikit/api/event/__pycache__/__init__.cpython-38.pyc,, +clikit/api/event/__pycache__/config_event.cpython-38.pyc,, +clikit/api/event/__pycache__/console_events.cpython-38.pyc,, +clikit/api/event/__pycache__/event.cpython-38.pyc,, +clikit/api/event/__pycache__/event_dispatcher.cpython-38.pyc,, +clikit/api/event/__pycache__/pre_handle_event.cpython-38.pyc,, +clikit/api/event/__pycache__/pre_resolve_event.cpython-38.pyc,, +clikit/api/event/config_event.py,sha256=gQVVvrRueYvV0z3OQCNR7Fhi84MgjjBVW0zn6Ha7UVI,384 +clikit/api/event/console_events.py,sha256=RHK8n_BGZZ3toZBrqgaEGk1Wg-dLz760h17dg1uO7bc,74 +clikit/api/event/event.py,sha256=pJPgJesyg5JX8PPA2-zi5kHUk3AbDXXgCyIYBuGtJmo,328 +clikit/api/event/event_dispatcher.py,sha256=RZvQ1BiYj4l3cb5H0crn6YRT5_T_oOO8cXq0qEIbusg,3055 +clikit/api/event/pre_handle_event.py,sha256=EoFIuh1I_R0T5vF7je0dDVG9pU5PYNhNZjHsAOPdcEU,1166 +clikit/api/event/pre_resolve_event.py,sha256=vs6LUs0Yq1pJKCcqjw7X2xcf6gip75BQXpKtMYwu_u8,1049 +clikit/api/exceptions.py,sha256=vWBJqhYXNFBgg4rIIKN07hPiA42HmvqUSz1j9s1N6oA,97 +clikit/api/formatter/__init__.py,sha256=qyU1_SK11VRjYiwty4WTK9g5XtftpTHMPG7YUOsmW_8,90 +clikit/api/formatter/__pycache__/__init__.cpython-38.pyc,, +clikit/api/formatter/__pycache__/formatter.cpython-38.pyc,, +clikit/api/formatter/__pycache__/style.cpython-38.pyc,, +clikit/api/formatter/__pycache__/style_set.cpython-38.pyc,, +clikit/api/formatter/formatter.py,sha256=mWprIFsHO6DYF0vrA8H7FACr-GnEruTLsY-Y1W8Czgs,665 +clikit/api/formatter/style.py,sha256=lmvl2iEc26IWQO-bhS5JJT-Gemt1mkMG_xfQD2mcvC0,2810 +clikit/api/formatter/style_set.py,sha256=9MJO-uadkgbUkMtxyynlUpvh9-9DezEuEU0CN2ig-no,981 +clikit/api/io/__init__.py,sha256=wFO8kFY6aNF0NycVG4AYe5J_A5LtFv8O6ivFQJJk-SU,187 +clikit/api/io/__pycache__/__init__.cpython-38.pyc,, +clikit/api/io/__pycache__/flags.cpython-38.pyc,, +clikit/api/io/__pycache__/input.cpython-38.pyc,, +clikit/api/io/__pycache__/input_stream.cpython-38.pyc,, +clikit/api/io/__pycache__/io.cpython-38.pyc,, +clikit/api/io/__pycache__/io_exception.cpython-38.pyc,, +clikit/api/io/__pycache__/output.cpython-38.pyc,, +clikit/api/io/__pycache__/output_stream.cpython-38.pyc,, +clikit/api/io/__pycache__/section_output.cpython-38.pyc,, +clikit/api/io/flags.py,sha256=BxVtAqib2JKrxa8enKb7jgPHrbowS3Jh1wpmM1Uxwe8,254 +clikit/api/io/input.py,sha256=TmKlYFDII96sH3oM_7JAYn6x7i4Mq8imRrOItVcmzLM,1867 +clikit/api/io/input_stream.py,sha256=vPrnCvz7DYubNqUCt6ggzUgSXa-PoGi8ifKKcaDest0,731 +clikit/api/io/io.py,sha256=_t1qM3sWJB6nky1s77fl7R8Zqq2vSEgI6HowdWJ9jH0,6991 +clikit/api/io/io_exception.py,sha256=23tAhDkTgMpZw3AVHAQtwDsLxrMcSEmFDqhAj0zaU1M,92 +clikit/api/io/output.py,sha256=wuqKMJ0nsga5Brx0i1rSsSwqttnkYNrbSRqX7fs7Gjw,6291 +clikit/api/io/output_stream.py,sha256=37S8vcrlh1GJgwWKN05w3N9Us1mvDj-uJuNfDeSD1U0,857 +clikit/api/io/section_output.py,sha256=sRj6HRSCHm6RrI_m4UEDImshBDO45EniRXbhQeekVBY,3088 +clikit/api/resolver/__init__.py,sha256=8Jatu87gG0XzW9Gc6u-W4TWbtsnDJvsTc_fitbIYJwA,92 +clikit/api/resolver/__pycache__/__init__.cpython-38.pyc,, +clikit/api/resolver/__pycache__/command_resolver.cpython-38.pyc,, +clikit/api/resolver/__pycache__/exceptions.cpython-38.pyc,, +clikit/api/resolver/__pycache__/resolved_command.cpython-38.pyc,, +clikit/api/resolver/command_resolver.py,sha256=tJzXF9CmCkYuHmeq3rCJ848gDcOZwE-eqCUGAKUV4lg,344 +clikit/api/resolver/exceptions.py,sha256=s5syhgaE4KsacyBfPj3wLCBIqSp4QdYfqT02btZ8o34,779 +clikit/api/resolver/resolved_command.py,sha256=mS0sHUQ-P9BMRv6eP-iCvfsdOeEVbqmCuB-FitsIpps,447 +clikit/args/__init__.py,sha256=YuDLMbpDBTRRX8RsDGFwqp9Qi83P0x_U2s9pAQQguRs,119 +clikit/args/__pycache__/__init__.cpython-38.pyc,, +clikit/args/__pycache__/argv_args.cpython-38.pyc,, +clikit/args/__pycache__/default_args_parser.cpython-38.pyc,, +clikit/args/__pycache__/string_args.cpython-38.pyc,, +clikit/args/__pycache__/token_parser.cpython-38.pyc,, +clikit/args/argv_args.py,sha256=7FiSchlyhz40VzsYK7uJsaSO4XD9x05chjDVLKAppwI,1262 +clikit/args/default_args_parser.py,sha256=B_F9Mn3G8RC6dPRPxKT2qlfsq7Vk0o-KVslXObl0oy8,11723 +clikit/args/inputs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +clikit/args/inputs/__pycache__/__init__.cpython-38.pyc,, +clikit/args/string_args.py,sha256=YSQnT9_KSKqnNwibwJ6VhDBFJ9VIbwBA88iMrIH2ScI,1067 +clikit/args/token_parser.py,sha256=8LW5qEck6mEwcwgfPBwwGTo1tfu88q5P7zNDFIrvRRQ,3031 +clikit/config/__init__.py,sha256=dxmVY0lZ0-Htf-Kkm7MnrFW541lkeeIBnQG10Q5y0LI,65 +clikit/config/__pycache__/__init__.cpython-38.pyc,, +clikit/config/__pycache__/default_application_config.cpython-38.pyc,, +clikit/config/default_application_config.py,sha256=lhKuZosg23WQ9V4H7nsNoVckCVXc18E13sxMAjqZK5w,5874 +clikit/console_application.py,sha256=quUwTfCWa402UgJLp3Lyn-6f4v8KUFyAhsdGIMecQbg,6000 +clikit/formatter/__init__.py,sha256=5goy4-OUK8L7uUmsrpkFLdQjlRAqktlYyzu1D5qYMmI,175 +clikit/formatter/__pycache__/__init__.cpython-38.pyc,, +clikit/formatter/__pycache__/ansi_formatter.cpython-38.pyc,, +clikit/formatter/__pycache__/default_style_set.cpython-38.pyc,, +clikit/formatter/__pycache__/null_formatter.cpython-38.pyc,, +clikit/formatter/__pycache__/plain_formatter.cpython-38.pyc,, +clikit/formatter/ansi_formatter.py,sha256=1PI5JSHWVXuTmFIM0LUaGtpYNAFbJ-_fuCAD4STLF-8,1868 +clikit/formatter/default_style_set.py,sha256=FByMJFRdM4sBTusTQUM3tm8AWD0c9jKSSS4EdFLGyZM,600 +clikit/formatter/null_formatter.py,sha256=S13YSVuwaoqpcWr-wnGg0DcvegSC7HJ-c-uVMSnUjbw,496 +clikit/formatter/plain_formatter.py,sha256=AFGtMvG_2bUpfKia7I8zxEKZzLd2nJlU0C5hcGldXCg,1533 +clikit/handler/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +clikit/handler/__pycache__/__init__.cpython-38.pyc,, +clikit/handler/__pycache__/callback_handler.cpython-38.pyc,, +clikit/handler/callback_handler.py,sha256=mkmYrJKbU9sEsQBXe5xV-V4o6EZUz-76vy2Z54M09lY,385 +clikit/handler/help/__init__.py,sha256=g6dt8GiW2Nw6S2KDpGB86L4H9fnvmQY4ha9IphC9AJU,47 +clikit/handler/help/__pycache__/__init__.cpython-38.pyc,, +clikit/handler/help/__pycache__/help_handler.cpython-38.pyc,, +clikit/handler/help/__pycache__/help_text_handler.cpython-38.pyc,, +clikit/handler/help/help_handler.py,sha256=oILYXTH4H8GQUyTCCdL27V1X9BVyYbsgduuXP_HrRps,238 +clikit/handler/help/help_text_handler.py,sha256=50fAdymanRcJG-QKuLK1Wu1pryYjB0zYTHgohrveHi0,862 +clikit/io/__init__.py,sha256=CFfM1isCq0Ox3jcgKy_ti36LjEIKb-WCqQLV4Ek5hP4,98 +clikit/io/__pycache__/__init__.cpython-38.pyc,, +clikit/io/__pycache__/buffered_io.cpython-38.pyc,, +clikit/io/__pycache__/console_io.cpython-38.pyc,, +clikit/io/__pycache__/null_io.cpython-38.pyc,, +clikit/io/buffered_io.py,sha256=ONUdINgS6TdAdUZm58kiQre89qrV4f0caQbYszLM-Oo,1662 +clikit/io/console_io.py,sha256=YLq0LiTZkJMCaNvY5zfFrHaUaNclCUovi2ru-I-LQig,1605 +clikit/io/input_stream/__init__.py,sha256=vn5CqtOFVFzTFufMZmqE9JR2DMQfv7kEUxJ3EIOKnSQ,204 +clikit/io/input_stream/__pycache__/__init__.cpython-38.pyc,, +clikit/io/input_stream/__pycache__/null_input_stream.cpython-38.pyc,, +clikit/io/input_stream/__pycache__/standard_input_stream.cpython-38.pyc,, +clikit/io/input_stream/__pycache__/stream_input_stream.cpython-38.pyc,, +clikit/io/input_stream/__pycache__/string_input_stream.cpython-38.pyc,, +clikit/io/input_stream/null_input_stream.py,sha256=oX5Q-RXznMBaIGYMIdWXJ_7MKUDlTK_iHCsrpwfWcec,717 +clikit/io/input_stream/standard_input_stream.py,sha256=Q1EusqAASNZBNkqj8KlQ4R-zEzjtZ6uhFokqv1BNhs4,289 +clikit/io/input_stream/stream_input_stream.py,sha256=HRwmNsi6rQ64jniCA4REkabKPfrN_PlB0cFyDxSOakM,1429 +clikit/io/input_stream/string_input_stream.py,sha256=1-5Zcb2d9LWFeERQlcFybNXhG8UFGtXtDoh1LzgIzcQ,879 +clikit/io/null_io.py,sha256=3EeBEC1kDgUeE6J2qa1bjHQplkqjwCTlgho1ZLvnZ9w,494 +clikit/io/output_stream/__init__.py,sha256=ZNqXJn6KLAB58ZPw24wHz0jOVgvfoluHa6WwwKBivBY,267 +clikit/io/output_stream/__pycache__/__init__.cpython-38.pyc,, +clikit/io/output_stream/__pycache__/buffered_output_stream.cpython-38.pyc,, +clikit/io/output_stream/__pycache__/error_output_stream.cpython-38.pyc,, +clikit/io/output_stream/__pycache__/null_output_stream.cpython-38.pyc,, +clikit/io/output_stream/__pycache__/standard_output_stream.cpython-38.pyc,, +clikit/io/output_stream/__pycache__/stream_output_stream.cpython-38.pyc,, +clikit/io/output_stream/buffered_output_stream.py,sha256=U9L9epHTfAj3Zxwsw0lEwKFoTBuSnMNuU_TDjSf_vZc,1315 +clikit/io/output_stream/error_output_stream.py,sha256=yyoW9GX3vKDawDQt5PnXyvrvY8_18nP5jKXYvsnnuiQ,287 +clikit/io/output_stream/null_output_stream.py,sha256=GF_2uHunXMQXvdZXSzTwzDHDAanNwGs8eivljK3EiMM,799 +clikit/io/output_stream/standard_output_stream.py,sha256=IzKfjNrH3yMokxQOwWNrpUynuNPbaFjlJqT0enNsU1w,296 +clikit/io/output_stream/stream_output_stream.py,sha256=3vig_hyp0dODsoQkzq4fojSG3wlmieWV_zamCn2TX-U,3314 +clikit/resolver/__init__.py,sha256=Px1AAiadk2G-y-zaZzxQQGOZn3EPTnVh7s9iDn4riyg,46 +clikit/resolver/__pycache__/__init__.cpython-38.pyc,, +clikit/resolver/__pycache__/default_resolver.cpython-38.pyc,, +clikit/resolver/__pycache__/help_resolver.cpython-38.pyc,, +clikit/resolver/__pycache__/resolve_result.cpython-38.pyc,, +clikit/resolver/default_resolver.py,sha256=qrRq3EuP3caXg5wcVz6rlzs-JWqMYeqsdXvPNF29nCU,5684 +clikit/resolver/help_resolver.py,sha256=_A78t21jZLsHYDFDict0-sgha_V_sBS9tzie8kBMHVc,1036 +clikit/resolver/resolve_result.py,sha256=DiSzIMeo01-rzfaZ1ARKk9HQuLm8CkKuYqSeoCDr28A,1394 +clikit/ui/__init__.py,sha256=60I_pzuR0mkk9uBc_oLK78uo1VLcSnqk55HU8muONag,66 +clikit/ui/__pycache__/__init__.cpython-38.pyc,, +clikit/ui/__pycache__/component.cpython-38.pyc,, +clikit/ui/__pycache__/rectangle.cpython-38.pyc,, +clikit/ui/alignment/__init__.py,sha256=z6aQyThJze0J1Pk0mNXCVlW8Ipk52n0rfviV4EHSA5w,44 +clikit/ui/alignment/__pycache__/__init__.cpython-38.pyc,, +clikit/ui/alignment/__pycache__/label_alignment.cpython-38.pyc,, +clikit/ui/alignment/label_alignment.py,sha256=W2Gnw2FNJHkrIeH2pcJYrPlI5FG2xnIRuYL5zNNCMEg,1212 +clikit/ui/component.py,sha256=6kXOcriR5JawgA4XRHaJ0Ue-Klj6MeI0V0GlK2JyBCM,229 +clikit/ui/components/__init__.py,sha256=tPsp8TeueoiQHeCPlw6ridPJ5WS5lLwk4iNhf3Zu58U,515 +clikit/ui/components/__pycache__/__init__.cpython-38.pyc,, +clikit/ui/components/__pycache__/border_util.cpython-38.pyc,, +clikit/ui/components/__pycache__/cell_wrapper.cpython-38.pyc,, +clikit/ui/components/__pycache__/choice_question.cpython-38.pyc,, +clikit/ui/components/__pycache__/confirmation_question.cpython-38.pyc,, +clikit/ui/components/__pycache__/empty_line.cpython-38.pyc,, +clikit/ui/components/__pycache__/exception_trace.cpython-38.pyc,, +clikit/ui/components/__pycache__/labeled_paragraph.cpython-38.pyc,, +clikit/ui/components/__pycache__/name_version.cpython-38.pyc,, +clikit/ui/components/__pycache__/paragraph.cpython-38.pyc,, +clikit/ui/components/__pycache__/progress_bar.cpython-38.pyc,, +clikit/ui/components/__pycache__/progress_indicator.cpython-38.pyc,, +clikit/ui/components/__pycache__/question.cpython-38.pyc,, +clikit/ui/components/__pycache__/table.cpython-38.pyc,, +clikit/ui/components/border_util.py,sha256=NqkT5mwJfg9jbxZ4I_IX9X26mMfGSIYWuRZ7RQPGTjI,4840 +clikit/ui/components/cell_wrapper.py,sha256=5OFhcsXYyHoTGDc4oNLhs9-hAzOcNBBDQxjlB4DKFlQ,7243 +clikit/ui/components/choice_question.py,sha256=J1-9YMPlOliKPiFieuvNQdB-XuCEbZao7089QtzaxXE,4148 +clikit/ui/components/confirmation_question.py,sha256=_GJtLWjxSyUvW7gKAbRO9pzjb4KTEjKbJb9dKeJyu9k,992 +clikit/ui/components/empty_line.py,sha256=jGEfFp12wpGRboEPr_BxEpust_vYEoK6kD3eseG9RY8,218 +clikit/ui/components/exception_trace.py,sha256=GUCWdyF9gAVm8yCxKZsiRmypAUG1ef0_bt_YBvE04To,15913 +clikit/ui/components/labeled_paragraph.py,sha256=gPO8eqKokwF2UN4zwC8l0QAKN3spdd631W6niboEJO8,1990 +clikit/ui/components/name_version.py,sha256=Wj1h0V5YlWDaLIgld5HOurBJMDObbK2lh-S4lA1MoH8,880 +clikit/ui/components/paragraph.py,sha256=XD4CFVWVtisRUQil8BrgScvJ6boqvDxH85m0AHTUsZs,688 +clikit/ui/components/progress_bar.py,sha256=C8xEIOrtvH2w38f1va1BKIj5Or--C_3bS7S7Kn3XWDc,12664 +clikit/ui/components/progress_indicator.py,sha256=FIJ78hbtirvAUZKmCchM0LQaNlPBdwxkBSMM6Cc9VLA,5470 +clikit/ui/components/question.py,sha256=zRZzdtkHrorbZ_34bJyov1nYhwkWMKREfiFrxut9MGo,7607 +clikit/ui/components/table.py,sha256=jn77Mj6Ur6YOmZltaBq772ou2slmRUqP-CvtZn0B5Rw,5232 +clikit/ui/help/__init__.py,sha256=PE4DRHjZpUNQ_oVZtDgYkkg4ryT3zJgPzpkVnFVR8Xg,84 +clikit/ui/help/__pycache__/__init__.cpython-38.pyc,, +clikit/ui/help/__pycache__/abstract_help.cpython-38.pyc,, +clikit/ui/help/__pycache__/application_help.cpython-38.pyc,, +clikit/ui/help/__pycache__/command_help.cpython-38.pyc,, +clikit/ui/help/abstract_help.py,sha256=61pjHbV0z-ajdRqi5bDXmeIoduhIuBY5Q92TghL8MzU,5482 +clikit/ui/help/application_help.py,sha256=gC4XiwLKuCZSZqvkVfHF11QUtCtlVSR3iyCFXHfRXxg,3437 +clikit/ui/help/command_help.py,sha256=XTcqms6r-6MJRxfpwZxQrBidb8wAgK8FFVU2nyUV1GU,6056 +clikit/ui/layout/__init__.py,sha256=FwOogbjZsOLTotD0PlxYNIZsuzki29Yxy21VtZm8Hks,38 +clikit/ui/layout/__pycache__/__init__.cpython-38.pyc,, +clikit/ui/layout/__pycache__/block_layout.cpython-38.pyc,, +clikit/ui/layout/block_layout.py,sha256=QC-w2bR5cSghF89GlzE6Mcw4UMwynS1ShiafwS6At9w,1262 +clikit/ui/rectangle.py,sha256=N9a9cGix0dlf-4jsGm66EgIjTctSnZXHNxv5c_yYniY,89 +clikit/ui/style/__init__.py,sha256=sWYW20D0opwjM8zyqxeIgXQFdlx6YU9yhjHiILPtLVw,69 +clikit/ui/style/__pycache__/__init__.cpython-38.pyc,, +clikit/ui/style/__pycache__/alignment.cpython-38.pyc,, +clikit/ui/style/__pycache__/border_style.cpython-38.pyc,, +clikit/ui/style/__pycache__/table_style.cpython-38.pyc,, +clikit/ui/style/alignment.py,sha256=-BWCOyYJ4fiL1P8PCpUVnZarp7iMCfpOj11nQ05Z5LY,110 +clikit/ui/style/border_style.py,sha256=TSwHfFMVfpJHkWJaKW0n8PzBDOHZRP8QZ3SlRRomXp4,2540 +clikit/ui/style/table_style.py,sha256=rwLbwkBUyKAenLt2jcv5gWEsVmNZJ4QMGfasRiH3FVg,2303 +clikit/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +clikit/utils/__pycache__/__init__.cpython-38.pyc,, +clikit/utils/__pycache__/_compat.cpython-38.pyc,, +clikit/utils/__pycache__/command.cpython-38.pyc,, +clikit/utils/__pycache__/string.cpython-38.pyc,, +clikit/utils/__pycache__/terminal.cpython-38.pyc,, +clikit/utils/__pycache__/time.cpython-38.pyc,, +clikit/utils/_compat.py,sha256=E2hkXMnWifngCqoOgd5V3NeP3qhQFytPfTkfZwQehP0,1814 +clikit/utils/command.py,sha256=KzWMqmV5KO4Up_e9duIOT7F9AqJB1QGOxxWfwboXxlA,1296 +clikit/utils/string.py,sha256=jaoiWhqO5vRax2jgyO6YvEBgHUIDH7NIhPGcjTvaCiI,2442 +clikit/utils/terminal.py,sha256=VhnUJBuIYtuBQiQGSTgTOLSBaXJ1anepxF0uh_AoElE,3696 +clikit/utils/time.py,sha256=fJrFL3pNwn1DUPF0ML_GuL9Fw27eHKt9szwA5EnEeQY,476 diff --git a/venv/lib64/python3.8/site-packages/cryptography-35.0.0.dist-info/RECORD b/venv/lib64/python3.8/site-packages/cryptography-35.0.0.dist-info/RECORD new file mode 100644 index 0000000..99460a6 --- /dev/null +++ b/venv/lib64/python3.8/site-packages/cryptography-35.0.0.dist-info/RECORD @@ -0,0 +1,184 @@ +cryptography-35.0.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +cryptography-35.0.0.dist-info/LICENSE,sha256=Q9rSzHUqtyHNmp827OcPtTq3cTVR8tPYaU2OjFoG1uI,323 +cryptography-35.0.0.dist-info/LICENSE.APACHE,sha256=qsc7MUj20dcRHbyjIJn2jSbGRMaBOuHk8F9leaomY_4,11360 +cryptography-35.0.0.dist-info/LICENSE.BSD,sha256=YCxMdILeZHndLpeTzaJ15eY9dz2s0eymiSMqtwCPtPs,1532 +cryptography-35.0.0.dist-info/LICENSE.PSF,sha256=aT7ApmKzn5laTyUrA6YiKUVHDBtvEsoCkY5O_g32S58,2415 +cryptography-35.0.0.dist-info/METADATA,sha256=zZa1iL6QuaIYXKGIUSWbpAHq7Au8WvwXNRai8NiBm_k,5411 +cryptography-35.0.0.dist-info/RECORD,, +cryptography-35.0.0.dist-info/WHEEL,sha256=9yjAS7Go4YyoRic4z08Pd2x_haRFlnlQ7mHzG4ikAes,112 +cryptography-35.0.0.dist-info/top_level.txt,sha256=zYbdX67v4JFZPfsaNue7ZV4-mgoRqYCAhMsNgt22LqA,22 +cryptography/__about__.py,sha256=5880_FiRxxAFrYOHgHw5kq-ckSChngziy8KbwdtR6uU,417 +cryptography/__init__.py,sha256=ZkGC0RcrTYfnPlvOf9KmT-jGQ5iaA_hWG0Ei0EsIZwk,347 +cryptography/__pycache__/__about__.cpython-38.pyc,, +cryptography/__pycache__/__init__.cpython-38.pyc,, +cryptography/__pycache__/exceptions.cpython-38.pyc,, +cryptography/__pycache__/fernet.cpython-38.pyc,, +cryptography/__pycache__/utils.cpython-38.pyc,, +cryptography/exceptions.py,sha256=TxKhSY9gEZi1P_2eFO1A2LWwzeGMvpPn8rcchIKS7fE,1209 +cryptography/fernet.py,sha256=Brm2owvVHgq73N8KgmPwKPEt9rBFzvoGD4OMb9qem-Y,6676 +cryptography/hazmat/__init__.py,sha256=OYlvgprzULzZlsf3yYTsd6VUVyQmpsbHjgJdNnsyRwE,418 +cryptography/hazmat/__pycache__/__init__.cpython-38.pyc,, +cryptography/hazmat/__pycache__/_oid.cpython-38.pyc,, +cryptography/hazmat/_oid.py,sha256=VHMc8J_wmnFdIglsZO1JSROZat6FcV8PmZZJhLo45TU,14960 +cryptography/hazmat/backends/__init__.py,sha256=eSGB-hZdol_ol8otjYBi7gIoH78eiUCOTDVs2gV6IbY,699 +cryptography/hazmat/backends/__pycache__/__init__.cpython-38.pyc,, +cryptography/hazmat/backends/__pycache__/interfaces.cpython-38.pyc,, +cryptography/hazmat/backends/interfaces.py,sha256=nTJiBNdciii0RCt1UCsOYtsik0hAgoWhDmNEdc9dN1c,12330 +cryptography/hazmat/backends/openssl/__init__.py,sha256=7rpz1Z3eV9vZy_d2iLrwC8Oz0vEruDFrjJlc6W2ZDXA,271 +cryptography/hazmat/backends/openssl/__pycache__/__init__.cpython-38.pyc,, +cryptography/hazmat/backends/openssl/__pycache__/aead.cpython-38.pyc,, +cryptography/hazmat/backends/openssl/__pycache__/backend.cpython-38.pyc,, +cryptography/hazmat/backends/openssl/__pycache__/ciphers.cpython-38.pyc,, +cryptography/hazmat/backends/openssl/__pycache__/cmac.cpython-38.pyc,, +cryptography/hazmat/backends/openssl/__pycache__/decode_asn1.cpython-38.pyc,, +cryptography/hazmat/backends/openssl/__pycache__/dh.cpython-38.pyc,, +cryptography/hazmat/backends/openssl/__pycache__/dsa.cpython-38.pyc,, +cryptography/hazmat/backends/openssl/__pycache__/ec.cpython-38.pyc,, +cryptography/hazmat/backends/openssl/__pycache__/ed25519.cpython-38.pyc,, +cryptography/hazmat/backends/openssl/__pycache__/ed448.cpython-38.pyc,, +cryptography/hazmat/backends/openssl/__pycache__/encode_asn1.cpython-38.pyc,, +cryptography/hazmat/backends/openssl/__pycache__/hashes.cpython-38.pyc,, +cryptography/hazmat/backends/openssl/__pycache__/hmac.cpython-38.pyc,, +cryptography/hazmat/backends/openssl/__pycache__/poly1305.cpython-38.pyc,, +cryptography/hazmat/backends/openssl/__pycache__/rsa.cpython-38.pyc,, +cryptography/hazmat/backends/openssl/__pycache__/utils.cpython-38.pyc,, +cryptography/hazmat/backends/openssl/__pycache__/x25519.cpython-38.pyc,, +cryptography/hazmat/backends/openssl/__pycache__/x448.cpython-38.pyc,, +cryptography/hazmat/backends/openssl/__pycache__/x509.cpython-38.pyc,, +cryptography/hazmat/backends/openssl/aead.py,sha256=zt8ZQ-JethHblWEfwAnB5-09JIL9K8qU1NXwPTjeVYA,5700 +cryptography/hazmat/backends/openssl/backend.py,sha256=fmXuIA2ZHkPNhqCQequOwW15jQdGWDkOPA6KQ0I80s8,107367 +cryptography/hazmat/backends/openssl/ciphers.py,sha256=jveXyZ9k0mTH7wp-4LUobN2HLYDGVcUb9RVumbU_kDY,10205 +cryptography/hazmat/backends/openssl/cmac.py,sha256=KXcwF1XlY0Ew6sTBqPj0I1vr62dfMwCjeV3qBosIw8s,2846 +cryptography/hazmat/backends/openssl/decode_asn1.py,sha256=FmR255NmhrIoBCccqe1rpBfZGH1lJcxiHMGWJB-fDcs,1176 +cryptography/hazmat/backends/openssl/dh.py,sha256=IbrUkIHANDPPp6jG-UaUBbCBaBcsbv-faq4L86ue5_s,11209 +cryptography/hazmat/backends/openssl/dsa.py,sha256=2xqKXe8hd3e0USiXzrdwGT38fVENy7H1dTimF0igIAE,10707 +cryptography/hazmat/backends/openssl/ec.py,sha256=LLXNW8anl1WmSNYkEdy-OlFMPCHwvkD_WV0UD2czqZA,12854 +cryptography/hazmat/backends/openssl/ed25519.py,sha256=bSlMfJedRoyzZXoJeaehj_0H_j6Ye5doQHgnib602-Q,5789 +cryptography/hazmat/backends/openssl/ed448.py,sha256=dpJf1zt_o8vfVcXYi_PD8d9H-jBbYEp-d6ZIYDKlC1s,5743 +cryptography/hazmat/backends/openssl/encode_asn1.py,sha256=1P7T7dVYDfmCm25XaMN4Tku1Iahmbn89F7RWeJT5hBo,23483 +cryptography/hazmat/backends/openssl/hashes.py,sha256=wx4SllcOscA0LHcHAZ3v6kOerLcZZO7gr7wVcIDtyKI,3098 +cryptography/hazmat/backends/openssl/hmac.py,sha256=jdiNrruBI8LG_1xrTW_pzP3V4EfmvWIGU9mV9wMtrEY,2941 +cryptography/hazmat/backends/openssl/poly1305.py,sha256=0hJDAb4pl9dJ_2xgt-XkNfyFA6U_IFXCe5jzOg7gkG0,2327 +cryptography/hazmat/backends/openssl/rsa.py,sha256=_SrvlAwnzlXo72-NWMif0FmJMySkh8oGdQom1ou77NI,21358 +cryptography/hazmat/backends/openssl/utils.py,sha256=2yO_PVh6mBQbRPC2U0ksmC2SQrAhmHSbay696SyOeLo,2342 +cryptography/hazmat/backends/openssl/x25519.py,sha256=kCnWzuchrJn1Nne4zeotKvlkMty9p3VuM8y1EWo70vQ,4622 +cryptography/hazmat/backends/openssl/x448.py,sha256=8OKYMNXDR7UlViU3sNIH5qmLMGP7J-F3OeEaRK0aots,4141 +cryptography/hazmat/backends/openssl/x509.py,sha256=VXH-yh0Onjv63Zlb774WmViExEuRV1rARz9Lm5-8Qp0,2085 +cryptography/hazmat/bindings/__init__.py,sha256=s9oKCQ2ycFdXoERdS1imafueSkBsL9kvbyfghaauZ9Y,180 +cryptography/hazmat/bindings/__pycache__/__init__.cpython-38.pyc,, +cryptography/hazmat/bindings/_openssl.abi3.so,sha256=XEQzkf285jcTYevb5tHzeKfBjHHCbhJ5IGBRBZkgUtU,6589152 +cryptography/hazmat/bindings/_rust.abi3.so,sha256=dgE6e2kGvhwAcsxGbb8ukCfvYr1hBeWIhLrQ8Ie_TQo,3312240 +cryptography/hazmat/bindings/_rust/__init__.pyi,sha256=ga5QLYp8MmumQB-Rp4TGHq_NAqONcXTrLm2712TZ9Ms,103 +cryptography/hazmat/bindings/_rust/asn1.pyi,sha256=sjHGn5ZQDBG9pOHYjfm2j3WYfs_2W3tPBok_TGs1FVA,582 +cryptography/hazmat/bindings/_rust/ocsp.pyi,sha256=g8dWhhJZBciU-4hWvJS-Y5xdSbzhxHRVD60MBEpQcAc,226 +cryptography/hazmat/bindings/_rust/x509.pyi,sha256=WqkJoSvtdlh4ppjtO30xa6zPCckwRjD7Fiks3Og3X6c,863 +cryptography/hazmat/bindings/openssl/__init__.py,sha256=s9oKCQ2ycFdXoERdS1imafueSkBsL9kvbyfghaauZ9Y,180 +cryptography/hazmat/bindings/openssl/__pycache__/__init__.cpython-38.pyc,, +cryptography/hazmat/bindings/openssl/__pycache__/_conditional.cpython-38.pyc,, +cryptography/hazmat/bindings/openssl/__pycache__/binding.cpython-38.pyc,, +cryptography/hazmat/bindings/openssl/_conditional.py,sha256=BcqYjIat6uaCJjRhkB07QNk-neiJ7TYgDbpyzOteX-4,7895 +cryptography/hazmat/bindings/openssl/binding.py,sha256=NdDV1tgUzeJj5CB5LZQ4-Ml1UrZmJ-YEuxTaJnbOack,7408 +cryptography/hazmat/primitives/__init__.py,sha256=s9oKCQ2ycFdXoERdS1imafueSkBsL9kvbyfghaauZ9Y,180 +cryptography/hazmat/primitives/__pycache__/__init__.cpython-38.pyc,, +cryptography/hazmat/primitives/__pycache__/_asymmetric.cpython-38.pyc,, +cryptography/hazmat/primitives/__pycache__/_cipheralgorithm.cpython-38.pyc,, +cryptography/hazmat/primitives/__pycache__/_serialization.cpython-38.pyc,, +cryptography/hazmat/primitives/__pycache__/cmac.cpython-38.pyc,, +cryptography/hazmat/primitives/__pycache__/constant_time.cpython-38.pyc,, +cryptography/hazmat/primitives/__pycache__/hashes.cpython-38.pyc,, +cryptography/hazmat/primitives/__pycache__/hmac.cpython-38.pyc,, +cryptography/hazmat/primitives/__pycache__/keywrap.cpython-38.pyc,, +cryptography/hazmat/primitives/__pycache__/padding.cpython-38.pyc,, +cryptography/hazmat/primitives/__pycache__/poly1305.cpython-38.pyc,, +cryptography/hazmat/primitives/_asymmetric.py,sha256=nVJwmxkakirAXfFp410pC4kY_CinzN5FSJwhEn2IE34,485 +cryptography/hazmat/primitives/_cipheralgorithm.py,sha256=sV8-SjhhY4WtHsaLI7e2x4o2cYAAqP8YWBjhC6k1u10,1000 +cryptography/hazmat/primitives/_serialization.py,sha256=OC_uXC5cNHucoOkHuTsZbfcQ9bvZs1cq7b18TcJu4Es,1341 +cryptography/hazmat/primitives/asymmetric/__init__.py,sha256=p69vOT3TH9cC7CBRiPsJBkXWfEU10Y0V537jrbHTW0U,956 +cryptography/hazmat/primitives/asymmetric/__pycache__/__init__.cpython-38.pyc,, +cryptography/hazmat/primitives/asymmetric/__pycache__/dh.cpython-38.pyc,, +cryptography/hazmat/primitives/asymmetric/__pycache__/dsa.cpython-38.pyc,, +cryptography/hazmat/primitives/asymmetric/__pycache__/ec.cpython-38.pyc,, +cryptography/hazmat/primitives/asymmetric/__pycache__/ed25519.cpython-38.pyc,, +cryptography/hazmat/primitives/asymmetric/__pycache__/ed448.cpython-38.pyc,, +cryptography/hazmat/primitives/asymmetric/__pycache__/padding.cpython-38.pyc,, +cryptography/hazmat/primitives/asymmetric/__pycache__/rsa.cpython-38.pyc,, +cryptography/hazmat/primitives/asymmetric/__pycache__/types.cpython-38.pyc,, +cryptography/hazmat/primitives/asymmetric/__pycache__/utils.cpython-38.pyc,, +cryptography/hazmat/primitives/asymmetric/__pycache__/x25519.cpython-38.pyc,, +cryptography/hazmat/primitives/asymmetric/__pycache__/x448.cpython-38.pyc,, +cryptography/hazmat/primitives/asymmetric/dh.py,sha256=5G8CuY86RKBm8ZWZFbsfURNOEuFkVjUYFHwdgG1A4rU,6554 +cryptography/hazmat/primitives/asymmetric/dsa.py,sha256=Kyzjbz3Gz9PH1XdUR2zDS8s2WIK9CBmx-V8VWQg9fO0,8363 +cryptography/hazmat/primitives/asymmetric/ec.py,sha256=A_ryk10REbwC4nciF4uUDQqrdI4EPs54ZFGgfaPGlk0,15000 +cryptography/hazmat/primitives/asymmetric/ed25519.py,sha256=1qOl1UWV_-cXKHhwlFSyPBdhpx2HMDRukkI6eI5i8vM,2728 +cryptography/hazmat/primitives/asymmetric/ed448.py,sha256=oR-j4jGcWUnGxWi1GygHxVZbgkSOKHsR6y1E3Lf6wYM,2647 +cryptography/hazmat/primitives/asymmetric/padding.py,sha256=QAcY756FgQgkRTUwHUKN1TfMhjEmsu4KwS1yKwN6RKI,2145 +cryptography/hazmat/primitives/asymmetric/rsa.py,sha256=pMcXyxPHRWEoN9jCN5LYKisLcIbwJMEPIb4mIQvRFIU,12103 +cryptography/hazmat/primitives/asymmetric/types.py,sha256=cF9k9hsiQG1CT34-JNLNFC5N0uMUX5bilnT9ewFsljI,644 +cryptography/hazmat/primitives/asymmetric/utils.py,sha256=uX3yo4ngIHdp9f6P5AEYmOwiuSVpQ4mL_h8kyP_HHy8,742 +cryptography/hazmat/primitives/asymmetric/x25519.py,sha256=-nbaGlgT1sufO9Ic-urwKDql8Da0U3GL6hZJIMqHgVc,2588 +cryptography/hazmat/primitives/asymmetric/x448.py,sha256=V3lxb1VOiRTa3bzVUC3uZat2ogfExUOdktCIGUUMZ2Y,2556 +cryptography/hazmat/primitives/ciphers/__init__.py,sha256=Qp78Y3PDSRfwp7DDa3pezlLrED_QFhic_LvDw4LM9ZQ,646 +cryptography/hazmat/primitives/ciphers/__pycache__/__init__.cpython-38.pyc,, +cryptography/hazmat/primitives/ciphers/__pycache__/aead.cpython-38.pyc,, +cryptography/hazmat/primitives/ciphers/__pycache__/algorithms.cpython-38.pyc,, +cryptography/hazmat/primitives/ciphers/__pycache__/base.cpython-38.pyc,, +cryptography/hazmat/primitives/ciphers/__pycache__/modes.cpython-38.pyc,, +cryptography/hazmat/primitives/ciphers/aead.py,sha256=8kesdxzga3--fpfEpryq3maK8YolOwiUl_pmfSDBYkA,6863 +cryptography/hazmat/primitives/ciphers/algorithms.py,sha256=e2o7CuWULhBB-DoSb9GXUZk1RRSWE1R9kNEA7dhlu_U,4148 +cryptography/hazmat/primitives/ciphers/base.py,sha256=YmreM20iR-vmwV23zoTWaJuxmyR5h2KP4r0OsjPmU08,7007 +cryptography/hazmat/primitives/ciphers/modes.py,sha256=-1VPWPiKwcNZwKnKxhibro_qhDHpygYEQ5yCvbzrVfI,7429 +cryptography/hazmat/primitives/cmac.py,sha256=AQgoYywf-mXZCXE0KB3BiCcWcgPgaLctBOvvCx-Z_Y8,2235 +cryptography/hazmat/primitives/constant_time.py,sha256=6bkW00QjhKusdgsQbexXhMlGX0XRN59XNmxWS2W38NA,387 +cryptography/hazmat/primitives/hashes.py,sha256=IVRp8vl6jDnLEsy4vXwki_inX4l6V39dx6vIrfvIr3k,6367 +cryptography/hazmat/primitives/hmac.py,sha256=m-53Lq59EoSloUzmx9Qty4OSh2bN9akjp0ohKurYBGI,2423 +cryptography/hazmat/primitives/kdf/__init__.py,sha256=DcZhzfLG8d8IYBH771lGTVU5S87OQDpu3nrfOwZnsmA,715 +cryptography/hazmat/primitives/kdf/__pycache__/__init__.cpython-38.pyc,, +cryptography/hazmat/primitives/kdf/__pycache__/concatkdf.cpython-38.pyc,, +cryptography/hazmat/primitives/kdf/__pycache__/hkdf.cpython-38.pyc,, +cryptography/hazmat/primitives/kdf/__pycache__/kbkdf.cpython-38.pyc,, +cryptography/hazmat/primitives/kdf/__pycache__/pbkdf2.cpython-38.pyc,, +cryptography/hazmat/primitives/kdf/__pycache__/scrypt.cpython-38.pyc,, +cryptography/hazmat/primitives/kdf/__pycache__/x963kdf.cpython-38.pyc,, +cryptography/hazmat/primitives/kdf/concatkdf.py,sha256=HrPWadThIgyktYGwrz6MKLinWXDZTz1c-kxoOmmprcM,4614 +cryptography/hazmat/primitives/kdf/hkdf.py,sha256=MZS8iwscL-FQVd2ayuqeNoEuVAwLbwd8_GlOd5lMYWY,3871 +cryptography/hazmat/primitives/kdf/kbkdf.py,sha256=SsO8RlzPLzhHuOlfG0S_zW039dZiaVsTT6M7VLr_p98,8283 +cryptography/hazmat/primitives/kdf/pbkdf2.py,sha256=pgtc2gm1RPV1O2IMRzlsD0NXjqpP2LxiRsozkSteEEY,2313 +cryptography/hazmat/primitives/kdf/scrypt.py,sha256=xG3S0sMuQufEIrzCoeIqwvv9MafvrhJEkDQ6A1NKJB4,2348 +cryptography/hazmat/primitives/kdf/x963kdf.py,sha256=KcP_PfIfz0opzbEiVYG8ECxN8aGtO_GG_mGmg7Lo1zU,2494 +cryptography/hazmat/primitives/keywrap.py,sha256=L4RqzLVFSwCDfvY1G8ZQVcn8SrPMsC88c-0U_86wmRA,6179 +cryptography/hazmat/primitives/padding.py,sha256=Kuelp5tzUgJnBpMKgn2XN7_mprC7lxscKbupAPivclM,6187 +cryptography/hazmat/primitives/poly1305.py,sha256=_Dtv6oCMn94rAhQ6pjie9mO_MiDLVL5It3Z5sdpCU3c,1711 +cryptography/hazmat/primitives/serialization/__init__.py,sha256=RALEthF7wRjlMyTvSq09XmKQey74tsSdDCCsDaD6yQU,1129 +cryptography/hazmat/primitives/serialization/__pycache__/__init__.cpython-38.pyc,, +cryptography/hazmat/primitives/serialization/__pycache__/base.cpython-38.pyc,, +cryptography/hazmat/primitives/serialization/__pycache__/pkcs12.cpython-38.pyc,, +cryptography/hazmat/primitives/serialization/__pycache__/pkcs7.cpython-38.pyc,, +cryptography/hazmat/primitives/serialization/__pycache__/ssh.cpython-38.pyc,, +cryptography/hazmat/primitives/serialization/base.py,sha256=WAgaOSQordQ6EBXm_JMc-5hNkxwqDfmea7Zg5fC8pZ8,1725 +cryptography/hazmat/primitives/serialization/pkcs12.py,sha256=MT_JTVam_mLAqc1ifVpzjo87mDAz43EU50sIvJ-t3rg,2367 +cryptography/hazmat/primitives/serialization/pkcs7.py,sha256=khs1nvWTTN-Ctaqfqj2QSUDrXyzzXhrp_EwC8j6YrXI,5326 +cryptography/hazmat/primitives/serialization/ssh.py,sha256=GoCJk7fDDwcBrSKhQI-37NZy_ZPtCeTWsFskleWElTg,22442 +cryptography/hazmat/primitives/twofactor/__init__.py,sha256=ZHo4zwWidFP2RWFl8luiNuYkVMZPghzx54izPNSCtD4,222 +cryptography/hazmat/primitives/twofactor/__pycache__/__init__.cpython-38.pyc,, +cryptography/hazmat/primitives/twofactor/__pycache__/hotp.cpython-38.pyc,, +cryptography/hazmat/primitives/twofactor/__pycache__/totp.cpython-38.pyc,, +cryptography/hazmat/primitives/twofactor/hotp.py,sha256=14sLX8Mxvjv6FSF56LrB92gEdwM8WP1pn3Mxg3dE_mY,3629 +cryptography/hazmat/primitives/twofactor/totp.py,sha256=udOohvi33C_GLqQK-PB9PGFtsv5SlcoX1BvVlIicoI0,1895 +cryptography/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +cryptography/utils.py,sha256=Ns-hs0cAZnOLE_bEeUrDgqrVi5hdPZ78GXwLByM3TyQ,5437 +cryptography/x509/__init__.py,sha256=fuXhiCA_Th9v1R1LEbF3SZvJG_oIHE_TDLEoT5QPPec,7588 +cryptography/x509/__pycache__/__init__.cpython-38.pyc,, +cryptography/x509/__pycache__/base.cpython-38.pyc,, +cryptography/x509/__pycache__/certificate_transparency.cpython-38.pyc,, +cryptography/x509/__pycache__/extensions.cpython-38.pyc,, +cryptography/x509/__pycache__/general_name.cpython-38.pyc,, +cryptography/x509/__pycache__/name.cpython-38.pyc,, +cryptography/x509/__pycache__/ocsp.cpython-38.pyc,, +cryptography/x509/__pycache__/oid.cpython-38.pyc,, +cryptography/x509/base.py,sha256=p9zkQB07005yXa2d2Xzp-oXIClDmqcrmcpQqZtpsgSk,31546 +cryptography/x509/certificate_transparency.py,sha256=Elm_-GGA6k9zrcm5KYVY5uTirDsvGc_BUuTLR7Hu-K4,1119 +cryptography/x509/extensions.py,sha256=DsV3Om5PSaz6hLIjYIRdTQdCDNF_bS2E5s4Tr4aZ64k,64465 +cryptography/x509/general_name.py,sha256=6h7QnFSllwfkYEZpwNDhqJZ5p4ng3f5UOFz-47gkY6Q,8147 +cryptography/x509/name.py,sha256=nXqeAsWG5VHD-JDrjy-rcMGLXRzwzYYUa_FIT1ofW5E,9529 +cryptography/x509/ocsp.py,sha256=1kgLbBov4pUBqTRtGhGmJb5eX_id24nkntbbiSHFmB0,14792 +cryptography/x509/oid.py,sha256=CLIlQwzE3PQXMvkKep4JbzVUaRDl_stwcX_U6-s2cNw,794 diff --git a/venv/lib64/python3.8/site-packages/cryptography/__pycache__/__about__.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cryptography/__pycache__/__about__.cpython-38.pyc new file mode 100644 index 0000000..8af8eec Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cryptography/__pycache__/__about__.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cryptography/__pycache__/__init__.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cryptography/__pycache__/__init__.cpython-38.pyc new file mode 100644 index 0000000..609c2e3 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cryptography/__pycache__/__init__.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cryptography/__pycache__/exceptions.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cryptography/__pycache__/exceptions.cpython-38.pyc new file mode 100644 index 0000000..5dbd9cc Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cryptography/__pycache__/exceptions.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cryptography/__pycache__/fernet.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cryptography/__pycache__/fernet.cpython-38.pyc new file mode 100644 index 0000000..a8e01de Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cryptography/__pycache__/fernet.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cryptography/__pycache__/utils.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cryptography/__pycache__/utils.cpython-38.pyc new file mode 100644 index 0000000..c537628 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cryptography/__pycache__/utils.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cryptography/hazmat/__pycache__/__init__.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cryptography/hazmat/__pycache__/__init__.cpython-38.pyc new file mode 100644 index 0000000..06a065f Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cryptography/hazmat/__pycache__/__init__.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cryptography/hazmat/__pycache__/_oid.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cryptography/hazmat/__pycache__/_oid.cpython-38.pyc new file mode 100644 index 0000000..4324897 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cryptography/hazmat/__pycache__/_oid.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cryptography/hazmat/backends/__pycache__/__init__.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cryptography/hazmat/backends/__pycache__/__init__.cpython-38.pyc new file mode 100644 index 0000000..c036d15 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cryptography/hazmat/backends/__pycache__/__init__.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cryptography/hazmat/backends/__pycache__/interfaces.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cryptography/hazmat/backends/__pycache__/interfaces.cpython-38.pyc new file mode 100644 index 0000000..4e4e585 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cryptography/hazmat/backends/__pycache__/interfaces.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cryptography/hazmat/backends/openssl/__pycache__/__init__.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cryptography/hazmat/backends/openssl/__pycache__/__init__.cpython-38.pyc new file mode 100644 index 0000000..6c3b91f Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cryptography/hazmat/backends/openssl/__pycache__/__init__.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cryptography/hazmat/backends/openssl/__pycache__/aead.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cryptography/hazmat/backends/openssl/__pycache__/aead.cpython-38.pyc new file mode 100644 index 0000000..5607490 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cryptography/hazmat/backends/openssl/__pycache__/aead.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cryptography/hazmat/backends/openssl/__pycache__/backend.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cryptography/hazmat/backends/openssl/__pycache__/backend.cpython-38.pyc new file mode 100644 index 0000000..1c34d0d Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cryptography/hazmat/backends/openssl/__pycache__/backend.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cryptography/hazmat/backends/openssl/__pycache__/ciphers.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cryptography/hazmat/backends/openssl/__pycache__/ciphers.cpython-38.pyc new file mode 100644 index 0000000..196bf6b Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cryptography/hazmat/backends/openssl/__pycache__/ciphers.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cryptography/hazmat/backends/openssl/__pycache__/cmac.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cryptography/hazmat/backends/openssl/__pycache__/cmac.cpython-38.pyc new file mode 100644 index 0000000..d1f61a7 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cryptography/hazmat/backends/openssl/__pycache__/cmac.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cryptography/hazmat/backends/openssl/__pycache__/decode_asn1.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cryptography/hazmat/backends/openssl/__pycache__/decode_asn1.cpython-38.pyc new file mode 100644 index 0000000..9651709 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cryptography/hazmat/backends/openssl/__pycache__/decode_asn1.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cryptography/hazmat/backends/openssl/__pycache__/dh.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cryptography/hazmat/backends/openssl/__pycache__/dh.cpython-38.pyc new file mode 100644 index 0000000..e34a4b0 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cryptography/hazmat/backends/openssl/__pycache__/dh.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cryptography/hazmat/backends/openssl/__pycache__/dsa.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cryptography/hazmat/backends/openssl/__pycache__/dsa.cpython-38.pyc new file mode 100644 index 0000000..96a69c0 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cryptography/hazmat/backends/openssl/__pycache__/dsa.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cryptography/hazmat/backends/openssl/__pycache__/ec.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cryptography/hazmat/backends/openssl/__pycache__/ec.cpython-38.pyc new file mode 100644 index 0000000..4419fd1 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cryptography/hazmat/backends/openssl/__pycache__/ec.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cryptography/hazmat/backends/openssl/__pycache__/ed25519.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cryptography/hazmat/backends/openssl/__pycache__/ed25519.cpython-38.pyc new file mode 100644 index 0000000..cad0e3b Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cryptography/hazmat/backends/openssl/__pycache__/ed25519.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cryptography/hazmat/backends/openssl/__pycache__/ed448.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cryptography/hazmat/backends/openssl/__pycache__/ed448.cpython-38.pyc new file mode 100644 index 0000000..bcec59a Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cryptography/hazmat/backends/openssl/__pycache__/ed448.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cryptography/hazmat/backends/openssl/__pycache__/encode_asn1.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cryptography/hazmat/backends/openssl/__pycache__/encode_asn1.cpython-38.pyc new file mode 100644 index 0000000..af75b8f Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cryptography/hazmat/backends/openssl/__pycache__/encode_asn1.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cryptography/hazmat/backends/openssl/__pycache__/hashes.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cryptography/hazmat/backends/openssl/__pycache__/hashes.cpython-38.pyc new file mode 100644 index 0000000..ff5812a Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cryptography/hazmat/backends/openssl/__pycache__/hashes.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cryptography/hazmat/backends/openssl/__pycache__/hmac.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cryptography/hazmat/backends/openssl/__pycache__/hmac.cpython-38.pyc new file mode 100644 index 0000000..eea07fa Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cryptography/hazmat/backends/openssl/__pycache__/hmac.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cryptography/hazmat/backends/openssl/__pycache__/poly1305.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cryptography/hazmat/backends/openssl/__pycache__/poly1305.cpython-38.pyc new file mode 100644 index 0000000..799cc17 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cryptography/hazmat/backends/openssl/__pycache__/poly1305.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cryptography/hazmat/backends/openssl/__pycache__/rsa.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cryptography/hazmat/backends/openssl/__pycache__/rsa.cpython-38.pyc new file mode 100644 index 0000000..c6d3bd8 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cryptography/hazmat/backends/openssl/__pycache__/rsa.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cryptography/hazmat/backends/openssl/__pycache__/utils.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cryptography/hazmat/backends/openssl/__pycache__/utils.cpython-38.pyc new file mode 100644 index 0000000..f59a65f Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cryptography/hazmat/backends/openssl/__pycache__/utils.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cryptography/hazmat/backends/openssl/__pycache__/x25519.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cryptography/hazmat/backends/openssl/__pycache__/x25519.cpython-38.pyc new file mode 100644 index 0000000..089c623 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cryptography/hazmat/backends/openssl/__pycache__/x25519.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cryptography/hazmat/backends/openssl/__pycache__/x448.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cryptography/hazmat/backends/openssl/__pycache__/x448.cpython-38.pyc new file mode 100644 index 0000000..e0e18ac Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cryptography/hazmat/backends/openssl/__pycache__/x448.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cryptography/hazmat/backends/openssl/__pycache__/x509.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cryptography/hazmat/backends/openssl/__pycache__/x509.cpython-38.pyc new file mode 100644 index 0000000..1cafdae Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cryptography/hazmat/backends/openssl/__pycache__/x509.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cryptography/hazmat/bindings/__pycache__/__init__.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cryptography/hazmat/bindings/__pycache__/__init__.cpython-38.pyc new file mode 100644 index 0000000..fc00c83 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cryptography/hazmat/bindings/__pycache__/__init__.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cryptography/hazmat/bindings/openssl/__pycache__/__init__.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cryptography/hazmat/bindings/openssl/__pycache__/__init__.cpython-38.pyc new file mode 100644 index 0000000..08d8ba6 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cryptography/hazmat/bindings/openssl/__pycache__/__init__.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cryptography/hazmat/bindings/openssl/__pycache__/_conditional.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cryptography/hazmat/bindings/openssl/__pycache__/_conditional.cpython-38.pyc new file mode 100644 index 0000000..8ed4b03 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cryptography/hazmat/bindings/openssl/__pycache__/_conditional.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cryptography/hazmat/bindings/openssl/__pycache__/binding.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cryptography/hazmat/bindings/openssl/__pycache__/binding.cpython-38.pyc new file mode 100644 index 0000000..7a715db Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cryptography/hazmat/bindings/openssl/__pycache__/binding.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/__pycache__/__init__.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/__pycache__/__init__.cpython-38.pyc new file mode 100644 index 0000000..173e50b Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/__pycache__/__init__.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/__pycache__/_asymmetric.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/__pycache__/_asymmetric.cpython-38.pyc new file mode 100644 index 0000000..531c714 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/__pycache__/_asymmetric.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/__pycache__/_cipheralgorithm.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/__pycache__/_cipheralgorithm.cpython-38.pyc new file mode 100644 index 0000000..af66452 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/__pycache__/_cipheralgorithm.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/__pycache__/_serialization.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/__pycache__/_serialization.cpython-38.pyc new file mode 100644 index 0000000..a782bfe Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/__pycache__/_serialization.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/__pycache__/cmac.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/__pycache__/cmac.cpython-38.pyc new file mode 100644 index 0000000..2227b55 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/__pycache__/cmac.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/__pycache__/constant_time.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/__pycache__/constant_time.cpython-38.pyc new file mode 100644 index 0000000..caa3f09 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/__pycache__/constant_time.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/__pycache__/hashes.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/__pycache__/hashes.cpython-38.pyc new file mode 100644 index 0000000..ef7f531 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/__pycache__/hashes.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/__pycache__/hmac.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/__pycache__/hmac.cpython-38.pyc new file mode 100644 index 0000000..7f3b024 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/__pycache__/hmac.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/__pycache__/keywrap.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/__pycache__/keywrap.cpython-38.pyc new file mode 100644 index 0000000..b3eec79 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/__pycache__/keywrap.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/__pycache__/padding.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/__pycache__/padding.cpython-38.pyc new file mode 100644 index 0000000..bad0168 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/__pycache__/padding.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/__pycache__/poly1305.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/__pycache__/poly1305.cpython-38.pyc new file mode 100644 index 0000000..afb8645 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/__pycache__/poly1305.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/asymmetric/__pycache__/__init__.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/asymmetric/__pycache__/__init__.cpython-38.pyc new file mode 100644 index 0000000..9756744 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/asymmetric/__pycache__/__init__.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/asymmetric/__pycache__/dh.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/asymmetric/__pycache__/dh.cpython-38.pyc new file mode 100644 index 0000000..286ede8 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/asymmetric/__pycache__/dh.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/asymmetric/__pycache__/dsa.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/asymmetric/__pycache__/dsa.cpython-38.pyc new file mode 100644 index 0000000..bf53e4e Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/asymmetric/__pycache__/dsa.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/asymmetric/__pycache__/ec.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/asymmetric/__pycache__/ec.cpython-38.pyc new file mode 100644 index 0000000..b942597 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/asymmetric/__pycache__/ec.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/asymmetric/__pycache__/ed25519.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/asymmetric/__pycache__/ed25519.cpython-38.pyc new file mode 100644 index 0000000..c65674a Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/asymmetric/__pycache__/ed25519.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/asymmetric/__pycache__/ed448.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/asymmetric/__pycache__/ed448.cpython-38.pyc new file mode 100644 index 0000000..db0d97e Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/asymmetric/__pycache__/ed448.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/asymmetric/__pycache__/padding.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/asymmetric/__pycache__/padding.cpython-38.pyc new file mode 100644 index 0000000..7da6217 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/asymmetric/__pycache__/padding.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/asymmetric/__pycache__/rsa.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/asymmetric/__pycache__/rsa.cpython-38.pyc new file mode 100644 index 0000000..402c58a Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/asymmetric/__pycache__/rsa.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/asymmetric/__pycache__/types.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/asymmetric/__pycache__/types.cpython-38.pyc new file mode 100644 index 0000000..567e7d2 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/asymmetric/__pycache__/types.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/asymmetric/__pycache__/utils.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/asymmetric/__pycache__/utils.cpython-38.pyc new file mode 100644 index 0000000..742e9e0 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/asymmetric/__pycache__/utils.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/asymmetric/__pycache__/x25519.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/asymmetric/__pycache__/x25519.cpython-38.pyc new file mode 100644 index 0000000..ae0dfe1 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/asymmetric/__pycache__/x25519.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/asymmetric/__pycache__/x448.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/asymmetric/__pycache__/x448.cpython-38.pyc new file mode 100644 index 0000000..7f0ce26 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/asymmetric/__pycache__/x448.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/ciphers/__pycache__/__init__.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/ciphers/__pycache__/__init__.cpython-38.pyc new file mode 100644 index 0000000..7d98bf7 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/ciphers/__pycache__/__init__.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/ciphers/__pycache__/aead.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/ciphers/__pycache__/aead.cpython-38.pyc new file mode 100644 index 0000000..a5f5bf3 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/ciphers/__pycache__/aead.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/ciphers/__pycache__/algorithms.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/ciphers/__pycache__/algorithms.cpython-38.pyc new file mode 100644 index 0000000..1d95849 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/ciphers/__pycache__/algorithms.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/ciphers/__pycache__/base.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/ciphers/__pycache__/base.cpython-38.pyc new file mode 100644 index 0000000..b2ff2d2 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/ciphers/__pycache__/base.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/ciphers/__pycache__/modes.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/ciphers/__pycache__/modes.cpython-38.pyc new file mode 100644 index 0000000..15d0e0b Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/ciphers/__pycache__/modes.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/kdf/__pycache__/__init__.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/kdf/__pycache__/__init__.cpython-38.pyc new file mode 100644 index 0000000..1dc5145 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/kdf/__pycache__/__init__.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/kdf/__pycache__/concatkdf.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/kdf/__pycache__/concatkdf.cpython-38.pyc new file mode 100644 index 0000000..d43c455 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/kdf/__pycache__/concatkdf.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/kdf/__pycache__/hkdf.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/kdf/__pycache__/hkdf.cpython-38.pyc new file mode 100644 index 0000000..dc779dc Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/kdf/__pycache__/hkdf.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/kdf/__pycache__/kbkdf.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/kdf/__pycache__/kbkdf.cpython-38.pyc new file mode 100644 index 0000000..4e7fe2e Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/kdf/__pycache__/kbkdf.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/kdf/__pycache__/pbkdf2.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/kdf/__pycache__/pbkdf2.cpython-38.pyc new file mode 100644 index 0000000..f78f422 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/kdf/__pycache__/pbkdf2.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/kdf/__pycache__/scrypt.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/kdf/__pycache__/scrypt.cpython-38.pyc new file mode 100644 index 0000000..0edf9ce Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/kdf/__pycache__/scrypt.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/kdf/__pycache__/x963kdf.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/kdf/__pycache__/x963kdf.cpython-38.pyc new file mode 100644 index 0000000..6b33d1e Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/kdf/__pycache__/x963kdf.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/serialization/__pycache__/__init__.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/serialization/__pycache__/__init__.cpython-38.pyc new file mode 100644 index 0000000..deca47b Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/serialization/__pycache__/__init__.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/serialization/__pycache__/base.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/serialization/__pycache__/base.cpython-38.pyc new file mode 100644 index 0000000..887ccdb Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/serialization/__pycache__/base.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/serialization/__pycache__/pkcs12.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/serialization/__pycache__/pkcs12.cpython-38.pyc new file mode 100644 index 0000000..c503a6d Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/serialization/__pycache__/pkcs12.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/serialization/__pycache__/pkcs7.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/serialization/__pycache__/pkcs7.cpython-38.pyc new file mode 100644 index 0000000..bd7f158 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/serialization/__pycache__/pkcs7.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/serialization/__pycache__/ssh.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/serialization/__pycache__/ssh.cpython-38.pyc new file mode 100644 index 0000000..af87f41 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/serialization/__pycache__/ssh.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/twofactor/__pycache__/__init__.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/twofactor/__pycache__/__init__.cpython-38.pyc new file mode 100644 index 0000000..6a8bf7d Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/twofactor/__pycache__/__init__.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/twofactor/__pycache__/hotp.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/twofactor/__pycache__/hotp.cpython-38.pyc new file mode 100644 index 0000000..5873690 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/twofactor/__pycache__/hotp.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/twofactor/__pycache__/totp.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/twofactor/__pycache__/totp.cpython-38.pyc new file mode 100644 index 0000000..d78ff3a Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cryptography/hazmat/primitives/twofactor/__pycache__/totp.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cryptography/x509/__pycache__/__init__.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cryptography/x509/__pycache__/__init__.cpython-38.pyc new file mode 100644 index 0000000..4a30fb5 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cryptography/x509/__pycache__/__init__.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cryptography/x509/__pycache__/base.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cryptography/x509/__pycache__/base.cpython-38.pyc new file mode 100644 index 0000000..576c01b Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cryptography/x509/__pycache__/base.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cryptography/x509/__pycache__/certificate_transparency.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cryptography/x509/__pycache__/certificate_transparency.cpython-38.pyc new file mode 100644 index 0000000..9c0dcfe Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cryptography/x509/__pycache__/certificate_transparency.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cryptography/x509/__pycache__/extensions.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cryptography/x509/__pycache__/extensions.cpython-38.pyc new file mode 100644 index 0000000..d742c45 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cryptography/x509/__pycache__/extensions.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cryptography/x509/__pycache__/general_name.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cryptography/x509/__pycache__/general_name.cpython-38.pyc new file mode 100644 index 0000000..0447f34 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cryptography/x509/__pycache__/general_name.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cryptography/x509/__pycache__/name.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cryptography/x509/__pycache__/name.cpython-38.pyc new file mode 100644 index 0000000..9dee33d Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cryptography/x509/__pycache__/name.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cryptography/x509/__pycache__/ocsp.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cryptography/x509/__pycache__/ocsp.cpython-38.pyc new file mode 100644 index 0000000..964d7b0 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cryptography/x509/__pycache__/ocsp.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/cryptography/x509/__pycache__/oid.cpython-38.pyc b/venv/lib64/python3.8/site-packages/cryptography/x509/__pycache__/oid.cpython-38.pyc new file mode 100644 index 0000000..7aa09f2 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/cryptography/x509/__pycache__/oid.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/__pycache__/__init__.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/__pycache__/__init__.cpython-38.pyc new file mode 100644 index 0000000..fe6b3fb Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/__pycache__/__init__.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/__pycache__/__main__.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/__pycache__/__main__.cpython-38.pyc new file mode 100644 index 0000000..ac3eecb Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/__pycache__/__main__.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/__pycache__/_version.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/__pycache__/_version.cpython-38.pyc new file mode 100644 index 0000000..cdc07d5 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/__pycache__/_version.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/__pycache__/__init__.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/__pycache__/__init__.cpython-38.pyc new file mode 100644 index 0000000..8c9c368 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/__pycache__/__init__.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/__pycache__/_pydevd_packaging.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/__pycache__/_pydevd_packaging.cpython-38.pyc new file mode 100644 index 0000000..a51a833 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/__pycache__/_pydevd_packaging.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/__pycache__/_util.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/__pycache__/_util.cpython-38.pyc new file mode 100644 index 0000000..08e4d04 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/__pycache__/_util.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/__pycache__/force_pydevd.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/__pycache__/force_pydevd.cpython-38.pyc new file mode 100644 index 0000000..ba9fa80 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/__pycache__/force_pydevd.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/__pycache__/pydev_app_engine_debug_startup.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/__pycache__/pydev_app_engine_debug_startup.cpython-38.pyc new file mode 100644 index 0000000..73c5b69 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/__pycache__/pydev_app_engine_debug_startup.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/__pycache__/pydev_coverage.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/__pycache__/pydev_coverage.cpython-38.pyc new file mode 100644 index 0000000..043d0ff Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/__pycache__/pydev_coverage.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/__pycache__/pydev_pysrc.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/__pycache__/pydev_pysrc.cpython-38.pyc new file mode 100644 index 0000000..307d13f Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/__pycache__/pydev_pysrc.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/__pycache__/pydev_run_in_console.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/__pycache__/pydev_run_in_console.cpython-38.pyc new file mode 100644 index 0000000..4a106f7 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/__pycache__/pydev_run_in_console.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/__pycache__/pydevconsole.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/__pycache__/pydevconsole.cpython-38.pyc new file mode 100644 index 0000000..6d88a28 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/__pycache__/pydevconsole.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/__pycache__/pydevd.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/__pycache__/pydevd.cpython-38.pyc new file mode 100644 index 0000000..0beeb70 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/__pycache__/pydevd.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/__pycache__/pydevd_file_utils.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/__pycache__/pydevd_file_utils.cpython-38.pyc new file mode 100644 index 0000000..29ba27e Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/__pycache__/pydevd_file_utils.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/__pycache__/pydevd_tracing.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/__pycache__/pydevd_tracing.cpython-38.pyc new file mode 100644 index 0000000..3f2db5a Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/__pycache__/pydevd_tracing.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/__pycache__/setup_cython.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/__pycache__/setup_cython.cpython-38.pyc new file mode 100644 index 0000000..678fd83 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/__pycache__/setup_cython.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydev_bundle/__pycache__/__init__.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydev_bundle/__pycache__/__init__.cpython-38.pyc new file mode 100644 index 0000000..3349abe Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydev_bundle/__pycache__/__init__.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydev_bundle/__pycache__/_pydev_calltip_util.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydev_bundle/__pycache__/_pydev_calltip_util.cpython-38.pyc new file mode 100644 index 0000000..81bdb99 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydev_bundle/__pycache__/_pydev_calltip_util.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydev_bundle/__pycache__/_pydev_completer.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydev_bundle/__pycache__/_pydev_completer.cpython-38.pyc new file mode 100644 index 0000000..6a3dc7e Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydev_bundle/__pycache__/_pydev_completer.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydev_bundle/__pycache__/_pydev_filesystem_encoding.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydev_bundle/__pycache__/_pydev_filesystem_encoding.cpython-38.pyc new file mode 100644 index 0000000..6502558 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydev_bundle/__pycache__/_pydev_filesystem_encoding.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydev_bundle/__pycache__/_pydev_getopt.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydev_bundle/__pycache__/_pydev_getopt.cpython-38.pyc new file mode 100644 index 0000000..f45c3e8 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydev_bundle/__pycache__/_pydev_getopt.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydev_bundle/__pycache__/_pydev_imports_tipper.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydev_bundle/__pycache__/_pydev_imports_tipper.cpython-38.pyc new file mode 100644 index 0000000..f92a0b9 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydev_bundle/__pycache__/_pydev_imports_tipper.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydev_bundle/__pycache__/_pydev_jy_imports_tipper.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydev_bundle/__pycache__/_pydev_jy_imports_tipper.cpython-38.pyc new file mode 100644 index 0000000..4d2a714 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydev_bundle/__pycache__/_pydev_jy_imports_tipper.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydev_bundle/__pycache__/_pydev_log.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydev_bundle/__pycache__/_pydev_log.cpython-38.pyc new file mode 100644 index 0000000..8da8173 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydev_bundle/__pycache__/_pydev_log.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydev_bundle/__pycache__/_pydev_tipper_common.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydev_bundle/__pycache__/_pydev_tipper_common.cpython-38.pyc new file mode 100644 index 0000000..3354292 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydev_bundle/__pycache__/_pydev_tipper_common.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydev_bundle/__pycache__/pydev_console_utils.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydev_bundle/__pycache__/pydev_console_utils.cpython-38.pyc new file mode 100644 index 0000000..4155109 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydev_bundle/__pycache__/pydev_console_utils.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydev_bundle/__pycache__/pydev_import_hook.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydev_bundle/__pycache__/pydev_import_hook.cpython-38.pyc new file mode 100644 index 0000000..2262b48 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydev_bundle/__pycache__/pydev_import_hook.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydev_bundle/__pycache__/pydev_imports.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydev_bundle/__pycache__/pydev_imports.cpython-38.pyc new file mode 100644 index 0000000..2b4c5a1 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydev_bundle/__pycache__/pydev_imports.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydev_bundle/__pycache__/pydev_ipython_console.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydev_bundle/__pycache__/pydev_ipython_console.cpython-38.pyc new file mode 100644 index 0000000..f2f1e96 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydev_bundle/__pycache__/pydev_ipython_console.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydev_bundle/__pycache__/pydev_ipython_console_011.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydev_bundle/__pycache__/pydev_ipython_console_011.cpython-38.pyc new file mode 100644 index 0000000..fb1f534 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydev_bundle/__pycache__/pydev_ipython_console_011.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydev_bundle/__pycache__/pydev_is_thread_alive.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydev_bundle/__pycache__/pydev_is_thread_alive.cpython-38.pyc new file mode 100644 index 0000000..6225e90 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydev_bundle/__pycache__/pydev_is_thread_alive.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydev_bundle/__pycache__/pydev_localhost.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydev_bundle/__pycache__/pydev_localhost.cpython-38.pyc new file mode 100644 index 0000000..c2bebc6 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydev_bundle/__pycache__/pydev_localhost.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydev_bundle/__pycache__/pydev_log.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydev_bundle/__pycache__/pydev_log.cpython-38.pyc new file mode 100644 index 0000000..2ef8df1 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydev_bundle/__pycache__/pydev_log.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydev_bundle/__pycache__/pydev_monkey.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydev_bundle/__pycache__/pydev_monkey.cpython-38.pyc new file mode 100644 index 0000000..239e5a7 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydev_bundle/__pycache__/pydev_monkey.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydev_bundle/__pycache__/pydev_monkey_qt.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydev_bundle/__pycache__/pydev_monkey_qt.cpython-38.pyc new file mode 100644 index 0000000..03756a6 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydev_bundle/__pycache__/pydev_monkey_qt.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydev_bundle/__pycache__/pydev_override.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydev_bundle/__pycache__/pydev_override.cpython-38.pyc new file mode 100644 index 0000000..284f014 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydev_bundle/__pycache__/pydev_override.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydev_bundle/__pycache__/pydev_umd.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydev_bundle/__pycache__/pydev_umd.cpython-38.pyc new file mode 100644 index 0000000..ace3603 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydev_bundle/__pycache__/pydev_umd.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydev_bundle/__pycache__/pydev_versioncheck.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydev_bundle/__pycache__/pydev_versioncheck.cpython-38.pyc new file mode 100644 index 0000000..73f5e11 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydev_bundle/__pycache__/pydev_versioncheck.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydev_imps/__pycache__/__init__.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydev_imps/__pycache__/__init__.cpython-38.pyc new file mode 100644 index 0000000..91be32e Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydev_imps/__pycache__/__init__.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydev_imps/__pycache__/_pydev_BaseHTTPServer.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydev_imps/__pycache__/_pydev_BaseHTTPServer.cpython-38.pyc new file mode 100644 index 0000000..c0b5a29 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydev_imps/__pycache__/_pydev_BaseHTTPServer.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydev_imps/__pycache__/_pydev_execfile.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydev_imps/__pycache__/_pydev_execfile.cpython-38.pyc new file mode 100644 index 0000000..d16b557 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydev_imps/__pycache__/_pydev_execfile.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydev_imps/__pycache__/_pydev_saved_modules.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydev_imps/__pycache__/_pydev_saved_modules.cpython-38.pyc new file mode 100644 index 0000000..a9eb0db Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydev_imps/__pycache__/_pydev_saved_modules.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydev_imps/__pycache__/_pydev_sys_patch.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydev_imps/__pycache__/_pydev_sys_patch.cpython-38.pyc new file mode 100644 index 0000000..d0e4aaa Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydev_imps/__pycache__/_pydev_sys_patch.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydev_runfiles/__pycache__/__init__.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydev_runfiles/__pycache__/__init__.cpython-38.pyc new file mode 100644 index 0000000..48e2116 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydev_runfiles/__pycache__/__init__.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydev_runfiles/__pycache__/pydev_runfiles.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydev_runfiles/__pycache__/pydev_runfiles.cpython-38.pyc new file mode 100644 index 0000000..2f34377 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydev_runfiles/__pycache__/pydev_runfiles.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydev_runfiles/__pycache__/pydev_runfiles_coverage.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydev_runfiles/__pycache__/pydev_runfiles_coverage.cpython-38.pyc new file mode 100644 index 0000000..ccadf5d Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydev_runfiles/__pycache__/pydev_runfiles_coverage.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydev_runfiles/__pycache__/pydev_runfiles_nose.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydev_runfiles/__pycache__/pydev_runfiles_nose.cpython-38.pyc new file mode 100644 index 0000000..38d6021 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydev_runfiles/__pycache__/pydev_runfiles_nose.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydev_runfiles/__pycache__/pydev_runfiles_parallel.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydev_runfiles/__pycache__/pydev_runfiles_parallel.cpython-38.pyc new file mode 100644 index 0000000..9907024 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydev_runfiles/__pycache__/pydev_runfiles_parallel.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydev_runfiles/__pycache__/pydev_runfiles_parallel_client.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydev_runfiles/__pycache__/pydev_runfiles_parallel_client.cpython-38.pyc new file mode 100644 index 0000000..25934e7 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydev_runfiles/__pycache__/pydev_runfiles_parallel_client.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydev_runfiles/__pycache__/pydev_runfiles_pytest2.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydev_runfiles/__pycache__/pydev_runfiles_pytest2.cpython-38.pyc new file mode 100644 index 0000000..af1a7a1 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydev_runfiles/__pycache__/pydev_runfiles_pytest2.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydev_runfiles/__pycache__/pydev_runfiles_unittest.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydev_runfiles/__pycache__/pydev_runfiles_unittest.cpython-38.pyc new file mode 100644 index 0000000..4dae75c Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydev_runfiles/__pycache__/pydev_runfiles_unittest.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydev_runfiles/__pycache__/pydev_runfiles_xml_rpc.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydev_runfiles/__pycache__/pydev_runfiles_xml_rpc.cpython-38.pyc new file mode 100644 index 0000000..9d519c1 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydev_runfiles/__pycache__/pydev_runfiles_xml_rpc.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/__init__.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/__init__.cpython-38.pyc new file mode 100644 index 0000000..ff55eb3 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/__init__.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_additional_thread_info.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_additional_thread_info.cpython-38.pyc new file mode 100644 index 0000000..a715aa4 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_additional_thread_info.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_additional_thread_info_regular.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_additional_thread_info_regular.cpython-38.pyc new file mode 100644 index 0000000..363b6f8 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_additional_thread_info_regular.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_api.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_api.cpython-38.pyc new file mode 100644 index 0000000..471c1e2 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_api.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_breakpoints.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_breakpoints.cpython-38.pyc new file mode 100644 index 0000000..6919bb0 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_breakpoints.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_code_to_source.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_code_to_source.cpython-38.pyc new file mode 100644 index 0000000..6f53671 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_code_to_source.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_collect_bytecode_info.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_collect_bytecode_info.cpython-38.pyc new file mode 100644 index 0000000..417ced7 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_collect_bytecode_info.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_comm.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_comm.cpython-38.pyc new file mode 100644 index 0000000..e5cfa3f Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_comm.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_comm_constants.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_comm_constants.cpython-38.pyc new file mode 100644 index 0000000..85a3e18 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_comm_constants.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_command_line_handling.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_command_line_handling.cpython-38.pyc new file mode 100644 index 0000000..76c613f Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_command_line_handling.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_console.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_console.cpython-38.pyc new file mode 100644 index 0000000..841c166 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_console.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_constants.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_constants.cpython-38.pyc new file mode 100644 index 0000000..b3a4f25 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_constants.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_custom_frames.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_custom_frames.cpython-38.pyc new file mode 100644 index 0000000..8c823a8 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_custom_frames.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_cython_wrapper.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_cython_wrapper.cpython-38.pyc new file mode 100644 index 0000000..ecd8b5b Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_cython_wrapper.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_daemon_thread.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_daemon_thread.cpython-38.pyc new file mode 100644 index 0000000..0a10c93 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_daemon_thread.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_defaults.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_defaults.cpython-38.pyc new file mode 100644 index 0000000..b7f596c Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_defaults.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_dont_trace.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_dont_trace.cpython-38.pyc new file mode 100644 index 0000000..de1e232 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_dont_trace.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_dont_trace_files.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_dont_trace_files.cpython-38.pyc new file mode 100644 index 0000000..42ab65c Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_dont_trace_files.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_exec2.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_exec2.cpython-38.pyc new file mode 100644 index 0000000..4506784 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_exec2.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_extension_api.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_extension_api.cpython-38.pyc new file mode 100644 index 0000000..ec03c52 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_extension_api.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_extension_utils.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_extension_utils.cpython-38.pyc new file mode 100644 index 0000000..95e12d4 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_extension_utils.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_filtering.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_filtering.cpython-38.pyc new file mode 100644 index 0000000..5fb47ad Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_filtering.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_frame.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_frame.cpython-38.pyc new file mode 100644 index 0000000..2f21f0f Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_frame.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_frame_utils.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_frame_utils.cpython-38.pyc new file mode 100644 index 0000000..882014f Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_frame_utils.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_import_class.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_import_class.cpython-38.pyc new file mode 100644 index 0000000..f9b3570 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_import_class.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_io.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_io.cpython-38.pyc new file mode 100644 index 0000000..5445c89 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_io.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_json_debug_options.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_json_debug_options.cpython-38.pyc new file mode 100644 index 0000000..5f8b046 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_json_debug_options.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_net_command.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_net_command.cpython-38.pyc new file mode 100644 index 0000000..c577519 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_net_command.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_net_command_factory_json.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_net_command_factory_json.cpython-38.pyc new file mode 100644 index 0000000..a5251a1 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_net_command_factory_json.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_net_command_factory_xml.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_net_command_factory_xml.cpython-38.pyc new file mode 100644 index 0000000..43e7c82 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_net_command_factory_xml.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_plugin_utils.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_plugin_utils.cpython-38.pyc new file mode 100644 index 0000000..e768ac8 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_plugin_utils.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_process_net_command.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_process_net_command.cpython-38.pyc new file mode 100644 index 0000000..702cb63 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_process_net_command.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_process_net_command_json.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_process_net_command_json.cpython-38.pyc new file mode 100644 index 0000000..ef6375b Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_process_net_command_json.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_referrers.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_referrers.cpython-38.pyc new file mode 100644 index 0000000..963fa6e Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_referrers.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_reload.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_reload.cpython-38.pyc new file mode 100644 index 0000000..b89cb88 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_reload.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_resolver.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_resolver.cpython-38.pyc new file mode 100644 index 0000000..f55b158 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_resolver.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_safe_repr.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_safe_repr.cpython-38.pyc new file mode 100644 index 0000000..40e4440 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_safe_repr.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_save_locals.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_save_locals.cpython-38.pyc new file mode 100644 index 0000000..779765a Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_save_locals.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_signature.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_signature.cpython-38.pyc new file mode 100644 index 0000000..5d3a23e Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_signature.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_source_mapping.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_source_mapping.cpython-38.pyc new file mode 100644 index 0000000..62bf204 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_source_mapping.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_stackless.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_stackless.cpython-38.pyc new file mode 100644 index 0000000..e2e85fa Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_stackless.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_suspended_frames.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_suspended_frames.cpython-38.pyc new file mode 100644 index 0000000..cd85168 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_suspended_frames.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_thread_lifecycle.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_thread_lifecycle.cpython-38.pyc new file mode 100644 index 0000000..52ad4b9 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_thread_lifecycle.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_timeout.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_timeout.cpython-38.pyc new file mode 100644 index 0000000..9fe3621 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_timeout.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_trace_api.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_trace_api.cpython-38.pyc new file mode 100644 index 0000000..c3292b3 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_trace_api.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_trace_dispatch.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_trace_dispatch.cpython-38.pyc new file mode 100644 index 0000000..6c3c4e3 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_trace_dispatch.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_trace_dispatch_regular.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_trace_dispatch_regular.cpython-38.pyc new file mode 100644 index 0000000..d8da523 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_trace_dispatch_regular.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_traceproperty.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_traceproperty.cpython-38.pyc new file mode 100644 index 0000000..d906361 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_traceproperty.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_utils.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_utils.cpython-38.pyc new file mode 100644 index 0000000..d298872 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_utils.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_vars.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_vars.cpython-38.pyc new file mode 100644 index 0000000..64454f7 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_vars.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_vm_type.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_vm_type.cpython-38.pyc new file mode 100644 index 0000000..00d1e1a Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_vm_type.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_xml.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_xml.cpython-38.pyc new file mode 100644 index 0000000..73d58da Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/__pycache__/pydevd_xml.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/_debug_adapter/__pycache__/__init__.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/_debug_adapter/__pycache__/__init__.cpython-38.pyc new file mode 100644 index 0000000..1119bf6 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/_debug_adapter/__pycache__/__init__.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/_debug_adapter/__pycache__/__main__pydevd_gen_debug_adapter_protocol.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/_debug_adapter/__pycache__/__main__pydevd_gen_debug_adapter_protocol.cpython-38.pyc new file mode 100644 index 0000000..eaf3cb4 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/_debug_adapter/__pycache__/__main__pydevd_gen_debug_adapter_protocol.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/_debug_adapter/__pycache__/pydevd_base_schema.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/_debug_adapter/__pycache__/pydevd_base_schema.cpython-38.pyc new file mode 100644 index 0000000..630f7a7 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/_debug_adapter/__pycache__/pydevd_base_schema.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/_debug_adapter/__pycache__/pydevd_schema.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/_debug_adapter/__pycache__/pydevd_schema.cpython-38.pyc new file mode 100644 index 0000000..f630e28 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/_debug_adapter/__pycache__/pydevd_schema.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/_debug_adapter/__pycache__/pydevd_schema_log.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/_debug_adapter/__pycache__/pydevd_schema_log.cpython-38.pyc new file mode 100644 index 0000000..5571bf4 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_bundle/_debug_adapter/__pycache__/pydevd_schema_log.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_frame_eval/__pycache__/__init__.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_frame_eval/__pycache__/__init__.cpython-38.pyc new file mode 100644 index 0000000..ebfc8b4 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_frame_eval/__pycache__/__init__.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_frame_eval/__pycache__/pydevd_frame_eval_cython_wrapper.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_frame_eval/__pycache__/pydevd_frame_eval_cython_wrapper.cpython-38.pyc new file mode 100644 index 0000000..45cb717 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_frame_eval/__pycache__/pydevd_frame_eval_cython_wrapper.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_frame_eval/__pycache__/pydevd_frame_eval_main.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_frame_eval/__pycache__/pydevd_frame_eval_main.cpython-38.pyc new file mode 100644 index 0000000..1ea491f Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_frame_eval/__pycache__/pydevd_frame_eval_main.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_frame_eval/__pycache__/pydevd_frame_tracing.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_frame_eval/__pycache__/pydevd_frame_tracing.cpython-38.pyc new file mode 100644 index 0000000..1d5862a Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_frame_eval/__pycache__/pydevd_frame_tracing.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_frame_eval/__pycache__/pydevd_modify_bytecode.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_frame_eval/__pycache__/pydevd_modify_bytecode.cpython-38.pyc new file mode 100644 index 0000000..f92f3ca Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_frame_eval/__pycache__/pydevd_modify_bytecode.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/__pycache__/__init__.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/__pycache__/__init__.cpython-38.pyc new file mode 100644 index 0000000..0cb19af Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/__pycache__/__init__.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/__pycache__/pydevd_fix_code.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/__pycache__/pydevd_fix_code.cpython-38.pyc new file mode 100644 index 0000000..f40f755 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/__pycache__/pydevd_fix_code.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode/__pycache__/__init__.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode/__pycache__/__init__.cpython-38.pyc new file mode 100644 index 0000000..0eb91d1 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode/__pycache__/__init__.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode/__pycache__/bytecode.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode/__pycache__/bytecode.cpython-38.pyc new file mode 100644 index 0000000..a9aa3bc Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode/__pycache__/bytecode.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode/__pycache__/cfg.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode/__pycache__/cfg.cpython-38.pyc new file mode 100644 index 0000000..804f547 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode/__pycache__/cfg.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode/__pycache__/concrete.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode/__pycache__/concrete.cpython-38.pyc new file mode 100644 index 0000000..abdd758 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode/__pycache__/concrete.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode/__pycache__/flags.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode/__pycache__/flags.cpython-38.pyc new file mode 100644 index 0000000..4c6fbf0 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode/__pycache__/flags.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode/__pycache__/instr.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode/__pycache__/instr.cpython-38.pyc new file mode 100644 index 0000000..69a3c2e Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode/__pycache__/instr.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode/__pycache__/peephole_opt.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode/__pycache__/peephole_opt.cpython-38.pyc new file mode 100644 index 0000000..960b0fe Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode/__pycache__/peephole_opt.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode/tests/__pycache__/__init__.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode/tests/__pycache__/__init__.cpython-38.pyc new file mode 100644 index 0000000..38713b6 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode/tests/__pycache__/__init__.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode/tests/__pycache__/test_bytecode.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode/tests/__pycache__/test_bytecode.cpython-38.pyc new file mode 100644 index 0000000..67ffc39 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode/tests/__pycache__/test_bytecode.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode/tests/__pycache__/test_cfg.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode/tests/__pycache__/test_cfg.cpython-38.pyc new file mode 100644 index 0000000..d6b5cf0 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode/tests/__pycache__/test_cfg.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode/tests/__pycache__/test_code.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode/tests/__pycache__/test_code.cpython-38.pyc new file mode 100644 index 0000000..b810ebb Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode/tests/__pycache__/test_code.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode/tests/__pycache__/test_concrete.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode/tests/__pycache__/test_concrete.cpython-38.pyc new file mode 100644 index 0000000..ad2ebfa Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode/tests/__pycache__/test_concrete.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode/tests/__pycache__/test_flags.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode/tests/__pycache__/test_flags.cpython-38.pyc new file mode 100644 index 0000000..e5da284 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode/tests/__pycache__/test_flags.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode/tests/__pycache__/test_instr.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode/tests/__pycache__/test_instr.cpython-38.pyc new file mode 100644 index 0000000..c7eae53 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode/tests/__pycache__/test_instr.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode/tests/__pycache__/test_misc.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode/tests/__pycache__/test_misc.cpython-38.pyc new file mode 100644 index 0000000..442b530 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode/tests/__pycache__/test_misc.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode/tests/__pycache__/test_peephole_opt.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode/tests/__pycache__/test_peephole_opt.cpython-38.pyc new file mode 100644 index 0000000..1a1522f Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/_pydevd_frame_eval/vendored/bytecode/tests/__pycache__/test_peephole_opt.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydev_ipython/__pycache__/__init__.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydev_ipython/__pycache__/__init__.cpython-38.pyc new file mode 100644 index 0000000..842edcf Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydev_ipython/__pycache__/__init__.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydev_ipython/__pycache__/inputhook.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydev_ipython/__pycache__/inputhook.cpython-38.pyc new file mode 100644 index 0000000..2de566f Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydev_ipython/__pycache__/inputhook.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydev_ipython/__pycache__/inputhookglut.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydev_ipython/__pycache__/inputhookglut.cpython-38.pyc new file mode 100644 index 0000000..ba6f3c1 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydev_ipython/__pycache__/inputhookglut.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydev_ipython/__pycache__/inputhookgtk.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydev_ipython/__pycache__/inputhookgtk.cpython-38.pyc new file mode 100644 index 0000000..08f49f7 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydev_ipython/__pycache__/inputhookgtk.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydev_ipython/__pycache__/inputhookgtk3.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydev_ipython/__pycache__/inputhookgtk3.cpython-38.pyc new file mode 100644 index 0000000..90ee3a7 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydev_ipython/__pycache__/inputhookgtk3.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydev_ipython/__pycache__/inputhookpyglet.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydev_ipython/__pycache__/inputhookpyglet.cpython-38.pyc new file mode 100644 index 0000000..7fd6735 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydev_ipython/__pycache__/inputhookpyglet.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydev_ipython/__pycache__/inputhookqt4.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydev_ipython/__pycache__/inputhookqt4.cpython-38.pyc new file mode 100644 index 0000000..a0f798e Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydev_ipython/__pycache__/inputhookqt4.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydev_ipython/__pycache__/inputhookqt5.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydev_ipython/__pycache__/inputhookqt5.cpython-38.pyc new file mode 100644 index 0000000..d133ede Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydev_ipython/__pycache__/inputhookqt5.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydev_ipython/__pycache__/inputhooktk.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydev_ipython/__pycache__/inputhooktk.cpython-38.pyc new file mode 100644 index 0000000..d427c19 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydev_ipython/__pycache__/inputhooktk.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydev_ipython/__pycache__/inputhookwx.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydev_ipython/__pycache__/inputhookwx.cpython-38.pyc new file mode 100644 index 0000000..d5459c5 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydev_ipython/__pycache__/inputhookwx.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydev_ipython/__pycache__/matplotlibtools.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydev_ipython/__pycache__/matplotlibtools.cpython-38.pyc new file mode 100644 index 0000000..51a89f3 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydev_ipython/__pycache__/matplotlibtools.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydev_ipython/__pycache__/qt.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydev_ipython/__pycache__/qt.cpython-38.pyc new file mode 100644 index 0000000..e5fbb28 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydev_ipython/__pycache__/qt.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydev_ipython/__pycache__/qt_for_kernel.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydev_ipython/__pycache__/qt_for_kernel.cpython-38.pyc new file mode 100644 index 0000000..6e6beff Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydev_ipython/__pycache__/qt_for_kernel.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydev_ipython/__pycache__/qt_loaders.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydev_ipython/__pycache__/qt_loaders.cpython-38.pyc new file mode 100644 index 0000000..d39dd1a Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydev_ipython/__pycache__/qt_loaders.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydev_ipython/__pycache__/version.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydev_ipython/__pycache__/version.cpython-38.pyc new file mode 100644 index 0000000..46c3280 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydev_ipython/__pycache__/version.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydev_sitecustomize/__pycache__/sitecustomize.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydev_sitecustomize/__pycache__/sitecustomize.cpython-38.pyc new file mode 100644 index 0000000..de66f19 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydev_sitecustomize/__pycache__/sitecustomize.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/__pycache__/_always_live_program.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/__pycache__/_always_live_program.cpython-38.pyc new file mode 100644 index 0000000..cc234db Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/__pycache__/_always_live_program.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/__pycache__/_test_attach_to_process.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/__pycache__/_test_attach_to_process.cpython-38.pyc new file mode 100644 index 0000000..bc803f8 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/__pycache__/_test_attach_to_process.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/__pycache__/_test_attach_to_process_linux.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/__pycache__/_test_attach_to_process_linux.cpython-38.pyc new file mode 100644 index 0000000..9b2ab2f Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/__pycache__/_test_attach_to_process_linux.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/__pycache__/add_code_to_python_process.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/__pycache__/add_code_to_python_process.cpython-38.pyc new file mode 100644 index 0000000..98ffdce Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/__pycache__/add_code_to_python_process.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/__pycache__/attach_pydevd.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/__pycache__/attach_pydevd.cpython-38.pyc new file mode 100644 index 0000000..771f36b Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/__pycache__/attach_pydevd.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/__pycache__/attach_script.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/__pycache__/attach_script.cpython-38.pyc new file mode 100644 index 0000000..4fd96af Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/__pycache__/attach_script.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/linux_and_mac/__pycache__/lldb_prepare.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/linux_and_mac/__pycache__/lldb_prepare.cpython-38.pyc new file mode 100644 index 0000000..1c656aa Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/linux_and_mac/__pycache__/lldb_prepare.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/winappdbg/__pycache__/__init__.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/winappdbg/__pycache__/__init__.cpython-38.pyc new file mode 100644 index 0000000..a72732a Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/winappdbg/__pycache__/__init__.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/winappdbg/__pycache__/breakpoint.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/winappdbg/__pycache__/breakpoint.cpython-38.pyc new file mode 100644 index 0000000..e65c5a0 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/winappdbg/__pycache__/breakpoint.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/winappdbg/__pycache__/compat.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/winappdbg/__pycache__/compat.cpython-38.pyc new file mode 100644 index 0000000..28aa579 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/winappdbg/__pycache__/compat.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/winappdbg/__pycache__/crash.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/winappdbg/__pycache__/crash.cpython-38.pyc new file mode 100644 index 0000000..27d4dc5 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/winappdbg/__pycache__/crash.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/winappdbg/__pycache__/debug.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/winappdbg/__pycache__/debug.cpython-38.pyc new file mode 100644 index 0000000..fee14a6 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/winappdbg/__pycache__/debug.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/winappdbg/__pycache__/disasm.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/winappdbg/__pycache__/disasm.cpython-38.pyc new file mode 100644 index 0000000..8faf007 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/winappdbg/__pycache__/disasm.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/winappdbg/__pycache__/event.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/winappdbg/__pycache__/event.cpython-38.pyc new file mode 100644 index 0000000..c697d0e Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/winappdbg/__pycache__/event.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/winappdbg/__pycache__/interactive.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/winappdbg/__pycache__/interactive.cpython-38.pyc new file mode 100644 index 0000000..8e1c76f Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/winappdbg/__pycache__/interactive.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/winappdbg/__pycache__/module.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/winappdbg/__pycache__/module.cpython-38.pyc new file mode 100644 index 0000000..d665d4a Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/winappdbg/__pycache__/module.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/winappdbg/__pycache__/process.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/winappdbg/__pycache__/process.cpython-38.pyc new file mode 100644 index 0000000..d989282 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/winappdbg/__pycache__/process.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/winappdbg/__pycache__/registry.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/winappdbg/__pycache__/registry.cpython-38.pyc new file mode 100644 index 0000000..5c4dccd Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/winappdbg/__pycache__/registry.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/winappdbg/__pycache__/search.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/winappdbg/__pycache__/search.cpython-38.pyc new file mode 100644 index 0000000..a467e03 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/winappdbg/__pycache__/search.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/winappdbg/__pycache__/sql.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/winappdbg/__pycache__/sql.cpython-38.pyc new file mode 100644 index 0000000..c55fefb Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/winappdbg/__pycache__/sql.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/winappdbg/__pycache__/system.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/winappdbg/__pycache__/system.cpython-38.pyc new file mode 100644 index 0000000..a0a343d Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/winappdbg/__pycache__/system.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/winappdbg/__pycache__/textio.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/winappdbg/__pycache__/textio.cpython-38.pyc new file mode 100644 index 0000000..47cc46e Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/winappdbg/__pycache__/textio.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/winappdbg/__pycache__/thread.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/winappdbg/__pycache__/thread.cpython-38.pyc new file mode 100644 index 0000000..c9662aa Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/winappdbg/__pycache__/thread.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/winappdbg/__pycache__/util.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/winappdbg/__pycache__/util.cpython-38.pyc new file mode 100644 index 0000000..d8b2372 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/winappdbg/__pycache__/util.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/winappdbg/__pycache__/window.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/winappdbg/__pycache__/window.cpython-38.pyc new file mode 100644 index 0000000..6a8d3c0 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/winappdbg/__pycache__/window.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/winappdbg/plugins/__pycache__/__init__.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/winappdbg/plugins/__pycache__/__init__.cpython-38.pyc new file mode 100644 index 0000000..e73d2c9 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/winappdbg/plugins/__pycache__/__init__.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/winappdbg/plugins/__pycache__/do_symfix.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/winappdbg/plugins/__pycache__/do_symfix.cpython-38.pyc new file mode 100644 index 0000000..83b4e04 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/winappdbg/plugins/__pycache__/do_symfix.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/winappdbg/win32/__pycache__/__init__.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/winappdbg/win32/__pycache__/__init__.cpython-38.pyc new file mode 100644 index 0000000..c73e4e1 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/winappdbg/win32/__pycache__/__init__.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/winappdbg/win32/__pycache__/advapi32.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/winappdbg/win32/__pycache__/advapi32.cpython-38.pyc new file mode 100644 index 0000000..7b034e3 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/winappdbg/win32/__pycache__/advapi32.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/winappdbg/win32/__pycache__/context_amd64.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/winappdbg/win32/__pycache__/context_amd64.cpython-38.pyc new file mode 100644 index 0000000..2286423 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/winappdbg/win32/__pycache__/context_amd64.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/winappdbg/win32/__pycache__/context_i386.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/winappdbg/win32/__pycache__/context_i386.cpython-38.pyc new file mode 100644 index 0000000..4533127 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/winappdbg/win32/__pycache__/context_i386.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/winappdbg/win32/__pycache__/dbghelp.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/winappdbg/win32/__pycache__/dbghelp.cpython-38.pyc new file mode 100644 index 0000000..067b1f5 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/winappdbg/win32/__pycache__/dbghelp.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/winappdbg/win32/__pycache__/defines.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/winappdbg/win32/__pycache__/defines.cpython-38.pyc new file mode 100644 index 0000000..fc123a7 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/winappdbg/win32/__pycache__/defines.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/winappdbg/win32/__pycache__/gdi32.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/winappdbg/win32/__pycache__/gdi32.cpython-38.pyc new file mode 100644 index 0000000..615d281 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/winappdbg/win32/__pycache__/gdi32.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/winappdbg/win32/__pycache__/kernel32.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/winappdbg/win32/__pycache__/kernel32.cpython-38.pyc new file mode 100644 index 0000000..b74b068 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/winappdbg/win32/__pycache__/kernel32.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/winappdbg/win32/__pycache__/ntdll.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/winappdbg/win32/__pycache__/ntdll.cpython-38.pyc new file mode 100644 index 0000000..f566cdc Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/winappdbg/win32/__pycache__/ntdll.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/winappdbg/win32/__pycache__/peb_teb.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/winappdbg/win32/__pycache__/peb_teb.cpython-38.pyc new file mode 100644 index 0000000..2d5bee0 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/winappdbg/win32/__pycache__/peb_teb.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/winappdbg/win32/__pycache__/psapi.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/winappdbg/win32/__pycache__/psapi.cpython-38.pyc new file mode 100644 index 0000000..f7bbfe4 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/winappdbg/win32/__pycache__/psapi.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/winappdbg/win32/__pycache__/shell32.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/winappdbg/win32/__pycache__/shell32.cpython-38.pyc new file mode 100644 index 0000000..46c4a29 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/winappdbg/win32/__pycache__/shell32.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/winappdbg/win32/__pycache__/shlwapi.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/winappdbg/win32/__pycache__/shlwapi.cpython-38.pyc new file mode 100644 index 0000000..30dad2a Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/winappdbg/win32/__pycache__/shlwapi.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/winappdbg/win32/__pycache__/user32.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/winappdbg/win32/__pycache__/user32.cpython-38.pyc new file mode 100644 index 0000000..149f5a3 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/winappdbg/win32/__pycache__/user32.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/winappdbg/win32/__pycache__/version.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/winappdbg/win32/__pycache__/version.cpython-38.pyc new file mode 100644 index 0000000..4a3396e Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/winappdbg/win32/__pycache__/version.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/winappdbg/win32/__pycache__/wtsapi32.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/winappdbg/win32/__pycache__/wtsapi32.cpython-38.pyc new file mode 100644 index 0000000..9d6d86f Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_attach_to_process/winappdbg/win32/__pycache__/wtsapi32.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_concurrency_analyser/__pycache__/__init__.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_concurrency_analyser/__pycache__/__init__.cpython-38.pyc new file mode 100644 index 0000000..700fe8d Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_concurrency_analyser/__pycache__/__init__.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_concurrency_analyser/__pycache__/pydevd_concurrency_logger.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_concurrency_analyser/__pycache__/pydevd_concurrency_logger.cpython-38.pyc new file mode 100644 index 0000000..a829c56 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_concurrency_analyser/__pycache__/pydevd_concurrency_logger.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_concurrency_analyser/__pycache__/pydevd_thread_wrappers.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_concurrency_analyser/__pycache__/pydevd_thread_wrappers.cpython-38.pyc new file mode 100644 index 0000000..0a673ac Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_concurrency_analyser/__pycache__/pydevd_thread_wrappers.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_plugins/__pycache__/__init__.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_plugins/__pycache__/__init__.cpython-38.pyc new file mode 100644 index 0000000..43643d2 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_plugins/__pycache__/__init__.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_plugins/__pycache__/django_debug.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_plugins/__pycache__/django_debug.cpython-38.pyc new file mode 100644 index 0000000..475217e Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_plugins/__pycache__/django_debug.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_plugins/__pycache__/jinja2_debug.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_plugins/__pycache__/jinja2_debug.cpython-38.pyc new file mode 100644 index 0000000..7aba086 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_plugins/__pycache__/jinja2_debug.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_plugins/extensions/__pycache__/__init__.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_plugins/extensions/__pycache__/__init__.cpython-38.pyc new file mode 100644 index 0000000..89f117c Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_plugins/extensions/__pycache__/__init__.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_plugins/extensions/types/__pycache__/__init__.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_plugins/extensions/types/__pycache__/__init__.cpython-38.pyc new file mode 100644 index 0000000..e8d704c Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_plugins/extensions/types/__pycache__/__init__.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_plugins/extensions/types/__pycache__/pydevd_helpers.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_plugins/extensions/types/__pycache__/pydevd_helpers.cpython-38.pyc new file mode 100644 index 0000000..955c83c Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_plugins/extensions/types/__pycache__/pydevd_helpers.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_plugins/extensions/types/__pycache__/pydevd_plugin_numpy_types.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_plugins/extensions/types/__pycache__/pydevd_plugin_numpy_types.cpython-38.pyc new file mode 100644 index 0000000..4e22e96 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_plugins/extensions/types/__pycache__/pydevd_plugin_numpy_types.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_plugins/extensions/types/__pycache__/pydevd_plugins_django_form_str.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_plugins/extensions/types/__pycache__/pydevd_plugins_django_form_str.cpython-38.pyc new file mode 100644 index 0000000..49bca91 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/_vendored/pydevd/pydevd_plugins/extensions/types/__pycache__/pydevd_plugins_django_form_str.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/adapter/__pycache__/__init__.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/adapter/__pycache__/__init__.cpython-38.pyc new file mode 100644 index 0000000..9ee7a77 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/adapter/__pycache__/__init__.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/adapter/__pycache__/__main__.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/adapter/__pycache__/__main__.cpython-38.pyc new file mode 100644 index 0000000..37e9208 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/adapter/__pycache__/__main__.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/adapter/__pycache__/clients.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/adapter/__pycache__/clients.cpython-38.pyc new file mode 100644 index 0000000..4917192 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/adapter/__pycache__/clients.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/adapter/__pycache__/components.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/adapter/__pycache__/components.cpython-38.pyc new file mode 100644 index 0000000..62489bb Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/adapter/__pycache__/components.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/adapter/__pycache__/launchers.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/adapter/__pycache__/launchers.cpython-38.pyc new file mode 100644 index 0000000..95af5c7 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/adapter/__pycache__/launchers.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/adapter/__pycache__/servers.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/adapter/__pycache__/servers.cpython-38.pyc new file mode 100644 index 0000000..f924cd4 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/adapter/__pycache__/servers.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/adapter/__pycache__/sessions.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/adapter/__pycache__/sessions.cpython-38.pyc new file mode 100644 index 0000000..860e1e0 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/adapter/__pycache__/sessions.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/common/__pycache__/__init__.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/common/__pycache__/__init__.cpython-38.pyc new file mode 100644 index 0000000..957401b Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/common/__pycache__/__init__.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/common/__pycache__/compat.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/common/__pycache__/compat.cpython-38.pyc new file mode 100644 index 0000000..2f2e71c Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/common/__pycache__/compat.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/common/__pycache__/fmt.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/common/__pycache__/fmt.cpython-38.pyc new file mode 100644 index 0000000..12ebfb0 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/common/__pycache__/fmt.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/common/__pycache__/json.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/common/__pycache__/json.cpython-38.pyc new file mode 100644 index 0000000..6e30351 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/common/__pycache__/json.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/common/__pycache__/log.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/common/__pycache__/log.cpython-38.pyc new file mode 100644 index 0000000..e36f43c Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/common/__pycache__/log.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/common/__pycache__/messaging.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/common/__pycache__/messaging.cpython-38.pyc new file mode 100644 index 0000000..260d2a6 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/common/__pycache__/messaging.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/common/__pycache__/modules.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/common/__pycache__/modules.cpython-38.pyc new file mode 100644 index 0000000..5c6e6d5 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/common/__pycache__/modules.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/common/__pycache__/singleton.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/common/__pycache__/singleton.cpython-38.pyc new file mode 100644 index 0000000..fd07e46 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/common/__pycache__/singleton.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/common/__pycache__/sockets.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/common/__pycache__/sockets.cpython-38.pyc new file mode 100644 index 0000000..4240887 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/common/__pycache__/sockets.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/common/__pycache__/stacks.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/common/__pycache__/stacks.cpython-38.pyc new file mode 100644 index 0000000..a2c06f3 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/common/__pycache__/stacks.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/common/__pycache__/timestamp.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/common/__pycache__/timestamp.cpython-38.pyc new file mode 100644 index 0000000..511745a Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/common/__pycache__/timestamp.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/common/__pycache__/util.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/common/__pycache__/util.cpython-38.pyc new file mode 100644 index 0000000..8d9d21d Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/common/__pycache__/util.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/launcher/__pycache__/__init__.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/launcher/__pycache__/__init__.cpython-38.pyc new file mode 100644 index 0000000..7406e34 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/launcher/__pycache__/__init__.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/launcher/__pycache__/__main__.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/launcher/__pycache__/__main__.cpython-38.pyc new file mode 100644 index 0000000..f27dc46 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/launcher/__pycache__/__main__.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/launcher/__pycache__/debuggee.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/launcher/__pycache__/debuggee.cpython-38.pyc new file mode 100644 index 0000000..49756b1 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/launcher/__pycache__/debuggee.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/launcher/__pycache__/handlers.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/launcher/__pycache__/handlers.cpython-38.pyc new file mode 100644 index 0000000..37746fc Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/launcher/__pycache__/handlers.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/launcher/__pycache__/output.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/launcher/__pycache__/output.cpython-38.pyc new file mode 100644 index 0000000..3ea39d3 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/launcher/__pycache__/output.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/launcher/__pycache__/winapi.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/launcher/__pycache__/winapi.cpython-38.pyc new file mode 100644 index 0000000..93d0006 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/launcher/__pycache__/winapi.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/server/__pycache__/__init__.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/server/__pycache__/__init__.cpython-38.pyc new file mode 100644 index 0000000..50adc8d Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/server/__pycache__/__init__.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/server/__pycache__/api.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/server/__pycache__/api.cpython-38.pyc new file mode 100644 index 0000000..1811369 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/server/__pycache__/api.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/server/__pycache__/attach_pid_injected.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/server/__pycache__/attach_pid_injected.cpython-38.pyc new file mode 100644 index 0000000..6761f26 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/server/__pycache__/attach_pid_injected.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/debugpy/server/__pycache__/cli.cpython-38.pyc b/venv/lib64/python3.8/site-packages/debugpy/server/__pycache__/cli.cpython-38.pyc new file mode 100644 index 0000000..baf20d8 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/debugpy/server/__pycache__/cli.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/discord-1.7.3.dist-info/INSTALLER b/venv/lib64/python3.8/site-packages/discord-1.7.3.dist-info/INSTALLER new file mode 100644 index 0000000..a1b589e --- /dev/null +++ b/venv/lib64/python3.8/site-packages/discord-1.7.3.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/venv/lib64/python3.8/site-packages/discord-1.7.3.dist-info/METADATA b/venv/lib64/python3.8/site-packages/discord-1.7.3.dist-info/METADATA new file mode 100644 index 0000000..c6af761 --- /dev/null +++ b/venv/lib64/python3.8/site-packages/discord-1.7.3.dist-info/METADATA @@ -0,0 +1,16 @@ +Metadata-Version: 2.1 +Name: discord +Version: 1.7.3 +Summary: A mirror package for discord.py. Please install that instead. +Home-page: https://github.com/Rapptz/discord.py +Author: Rapptz +License: UNKNOWN +Platform: UNKNOWN +Description-Content-Type: text/markdown +Requires-Dist: discord.py (>=1.7.3) + +### This is a mirror package! + +It is recommended to install `discord.py` instead. + + diff --git a/venv/lib64/python3.8/site-packages/discord-1.7.3.dist-info/RECORD b/venv/lib64/python3.8/site-packages/discord-1.7.3.dist-info/RECORD new file mode 100644 index 0000000..b268436 --- /dev/null +++ b/venv/lib64/python3.8/site-packages/discord-1.7.3.dist-info/RECORD @@ -0,0 +1,7 @@ +discord-1.7.3.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +discord-1.7.3.dist-info/METADATA,sha256=n_9Ixt5dzxkh1D1fpEw-Rp6R_xpulL13WhThIskWQ8U,381 +discord-1.7.3.dist-info/RECORD,, +discord-1.7.3.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +discord-1.7.3.dist-info/WHEEL,sha256=OqRkF0eY5GHssMorFjlbTIq072vpHpF60fIQA6lS9xA,92 +discord-1.7.3.dist-info/direct_url.json,sha256=odZKKWfc7LgqU3GotYGpiA5Nm3eyTu6-kUI3VXm4Qes,175 +discord-1.7.3.dist-info/top_level.txt,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1 diff --git a/venv/lib64/python3.8/site-packages/discord-1.7.3.dist-info/REQUESTED b/venv/lib64/python3.8/site-packages/discord-1.7.3.dist-info/REQUESTED new file mode 100644 index 0000000..e69de29 diff --git a/venv/lib64/python3.8/site-packages/discord-1.7.3.dist-info/direct_url.json b/venv/lib64/python3.8/site-packages/discord-1.7.3.dist-info/direct_url.json new file mode 100644 index 0000000..e044fb0 --- /dev/null +++ b/venv/lib64/python3.8/site-packages/discord-1.7.3.dist-info/direct_url.json @@ -0,0 +1 @@ +{"archive_info": {}, "url": "file:///home/runner/.cache/pypoetry/artifacts/0f/cc/0e/0dd848b2518df98bf9b6e4de7030042dd09e0aa66d5bdb982bf67023fe/discord-1.7.3-py3-none-any.whl"} \ No newline at end of file diff --git a/venv/lib64/python3.8/site-packages/discord/__init__.py b/venv/lib64/python3.8/site-packages/discord/__init__.py new file mode 100644 index 0000000..e2c8101 --- /dev/null +++ b/venv/lib64/python3.8/site-packages/discord/__init__.py @@ -0,0 +1,67 @@ +# -*- coding: utf-8 -*- + +""" +Discord API Wrapper +~~~~~~~~~~~~~~~~~~~ + +A basic wrapper for the Discord API. + +:copyright: (c) 2015-present Rapptz +:license: MIT, see LICENSE for more details. + +""" + +__title__ = 'discord' +__author__ = 'Rapptz' +__license__ = 'MIT' +__copyright__ = 'Copyright 2015-present Rapptz' +__version__ = '1.7.3' + +__path__ = __import__('pkgutil').extend_path(__path__, __name__) + +from collections import namedtuple +import logging + +from .client import Client +from .appinfo import AppInfo +from .user import User, ClientUser, Profile +from .emoji import Emoji +from .partial_emoji import PartialEmoji +from .activity import * +from .channel import * +from .guild import Guild +from .flags import * +from .relationship import Relationship +from .member import Member, VoiceState +from .message import * +from .asset import Asset +from .errors import * +from .calls import CallMessage, GroupCall +from .permissions import Permissions, PermissionOverwrite +from .role import Role, RoleTags +from .file import File +from .colour import Color, Colour +from .integrations import Integration, IntegrationAccount +from .invite import Invite, PartialInviteChannel, PartialInviteGuild +from .template import Template +from .widget import Widget, WidgetMember, WidgetChannel +from .object import Object +from .reaction import Reaction +from . import utils, opus, abc +from .enums import * +from .embeds import Embed +from .mentions import AllowedMentions +from .shard import AutoShardedClient, ShardInfo +from .player import * +from .webhook import * +from .voice_client import VoiceClient, VoiceProtocol +from .audit_logs import AuditLogChanges, AuditLogEntry, AuditLogDiff +from .raw_models import * +from .team import * +from .sticker import Sticker + +VersionInfo = namedtuple('VersionInfo', 'major minor micro releaselevel serial') + +version_info = VersionInfo(major=1, minor=7, micro=3, releaselevel='final', serial=0) + +logging.getLogger(__name__).addHandler(logging.NullHandler()) diff --git a/venv/lib64/python3.8/site-packages/discord/__main__.py b/venv/lib64/python3.8/site-packages/discord/__main__.py new file mode 100644 index 0000000..9252835 --- /dev/null +++ b/venv/lib64/python3.8/site-packages/discord/__main__.py @@ -0,0 +1,305 @@ +# -*- coding: utf-8 -*- + +""" +The MIT License (MIT) + +Copyright (c) 2015-present Rapptz + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. +""" + +import argparse +import sys +from pathlib import Path + +import discord +import pkg_resources +import aiohttp +import platform + +def show_version(): + entries = [] + + entries.append('- Python v{0.major}.{0.minor}.{0.micro}-{0.releaselevel}'.format(sys.version_info)) + version_info = discord.version_info + entries.append('- discord.py v{0.major}.{0.minor}.{0.micro}-{0.releaselevel}'.format(version_info)) + if version_info.releaselevel != 'final': + pkg = pkg_resources.get_distribution('discord.py') + if pkg: + entries.append(' - discord.py pkg_resources: v{0}'.format(pkg.version)) + + entries.append('- aiohttp v{0.__version__}'.format(aiohttp)) + uname = platform.uname() + entries.append('- system info: {0.system} {0.release} {0.version}'.format(uname)) + print('\n'.join(entries)) + +def core(parser, args): + if args.version: + show_version() + +bot_template = """#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +from discord.ext import commands +import discord +import config + +class Bot(commands.{base}): + def __init__(self, **kwargs): + super().__init__(command_prefix=commands.when_mentioned_or('{prefix}'), **kwargs) + for cog in config.cogs: + try: + self.load_extension(cog) + except Exception as exc: + print('Could not load extension {{0}} due to {{1.__class__.__name__}}: {{1}}'.format(cog, exc)) + + async def on_ready(self): + print('Logged on as {{0}} (ID: {{0.id}})'.format(self.user)) + + +bot = Bot() + +# write general commands here + +bot.run(config.token) +""" + +gitignore_template = """# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +env/ +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +*.egg-info/ +.installed.cfg +*.egg + +# Our configuration files +config.py +""" + +cog_template = '''# -*- coding: utf-8 -*- + +from discord.ext import commands +import discord + +class {name}(commands.Cog{attrs}): + """The description for {name} goes here.""" + + def __init__(self, bot): + self.bot = bot +{extra} +def setup(bot): + bot.add_cog({name}(bot)) +''' + +cog_extras = ''' + def cog_unload(self): + # clean up logic goes here + pass + + async def cog_check(self, ctx): + # checks that apply to every command in here + return True + + async def bot_check(self, ctx): + # checks that apply to every command to the bot + return True + + async def bot_check_once(self, ctx): + # check that apply to every command but is guaranteed to be called only once + return True + + async def cog_command_error(self, ctx, error): + # error handling to every command in here + pass + + async def cog_before_invoke(self, ctx): + # called before a command is called here + pass + + async def cog_after_invoke(self, ctx): + # called after a command is called here + pass + +''' + + +# certain file names and directory names are forbidden +# see: https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247%28v=vs.85%29.aspx +# although some of this doesn't apply to Linux, we might as well be consistent +_base_table = { + '<': '-', + '>': '-', + ':': '-', + '"': '-', + # '/': '-', these are fine + # '\\': '-', + '|': '-', + '?': '-', + '*': '-', +} + +# NUL (0) and 1-31 are disallowed +_base_table.update((chr(i), None) for i in range(32)) + +translation_table = str.maketrans(_base_table) + +def to_path(parser, name, *, replace_spaces=False): + if isinstance(name, Path): + return name + + if sys.platform == 'win32': + forbidden = ('CON', 'PRN', 'AUX', 'NUL', 'COM1', 'COM2', 'COM3', 'COM4', 'COM5', 'COM6', 'COM7', \ + 'COM8', 'COM9', 'LPT1', 'LPT2', 'LPT3', 'LPT4', 'LPT5', 'LPT6', 'LPT7', 'LPT8', 'LPT9') + if len(name) <= 4 and name.upper() in forbidden: + parser.error('invalid directory name given, use a different one') + + name = name.translate(translation_table) + if replace_spaces: + name = name.replace(' ', '-') + return Path(name) + +def newbot(parser, args): + new_directory = to_path(parser, args.directory) / to_path(parser, args.name) + + # as a note exist_ok for Path is a 3.5+ only feature + # since we already checked above that we're >3.5 + try: + new_directory.mkdir(exist_ok=True, parents=True) + except OSError as exc: + parser.error('could not create our bot directory ({})'.format(exc)) + + cogs = new_directory / 'cogs' + + try: + cogs.mkdir(exist_ok=True) + init = cogs / '__init__.py' + init.touch() + except OSError as exc: + print('warning: could not create cogs directory ({})'.format(exc)) + + try: + with open(str(new_directory / 'config.py'), 'w', encoding='utf-8') as fp: + fp.write('token = "place your token here"\ncogs = []\n') + except OSError as exc: + parser.error('could not create config file ({})'.format(exc)) + + try: + with open(str(new_directory / 'bot.py'), 'w', encoding='utf-8') as fp: + base = 'Bot' if not args.sharded else 'AutoShardedBot' + fp.write(bot_template.format(base=base, prefix=args.prefix)) + except OSError as exc: + parser.error('could not create bot file ({})'.format(exc)) + + if not args.no_git: + try: + with open(str(new_directory / '.gitignore'), 'w', encoding='utf-8') as fp: + fp.write(gitignore_template) + except OSError as exc: + print('warning: could not create .gitignore file ({})'.format(exc)) + + print('successfully made bot at', new_directory) + +def newcog(parser, args): + cog_dir = to_path(parser, args.directory) + try: + cog_dir.mkdir(exist_ok=True) + except OSError as exc: + print('warning: could not create cogs directory ({})'.format(exc)) + + directory = cog_dir / to_path(parser, args.name) + directory = directory.with_suffix('.py') + try: + with open(str(directory), 'w', encoding='utf-8') as fp: + attrs = '' + extra = cog_extras if args.full else '' + if args.class_name: + name = args.class_name + else: + name = str(directory.stem) + if '-' in name or '_' in name: + translation = str.maketrans('-_', ' ') + name = name.translate(translation).title().replace(' ', '') + else: + name = name.title() + + if args.display_name: + attrs += ', name="{}"'.format(args.display_name) + if args.hide_commands: + attrs += ', command_attrs=dict(hidden=True)' + fp.write(cog_template.format(name=name, extra=extra, attrs=attrs)) + except OSError as exc: + parser.error('could not create cog file ({})'.format(exc)) + else: + print('successfully made cog at', directory) + +def add_newbot_args(subparser): + parser = subparser.add_parser('newbot', help='creates a command bot project quickly') + parser.set_defaults(func=newbot) + + parser.add_argument('name', help='the bot project name') + parser.add_argument('directory', help='the directory to place it in (default: .)', nargs='?', default=Path.cwd()) + parser.add_argument('--prefix', help='the bot prefix (default: $)', default='$', metavar='') + parser.add_argument('--sharded', help='whether to use AutoShardedBot', action='store_true') + parser.add_argument('--no-git', help='do not create a .gitignore file', action='store_true', dest='no_git') + +def add_newcog_args(subparser): + parser = subparser.add_parser('newcog', help='creates a new cog template quickly') + parser.set_defaults(func=newcog) + + parser.add_argument('name', help='the cog name') + parser.add_argument('directory', help='the directory to place it in (default: cogs)', nargs='?', default=Path('cogs')) + parser.add_argument('--class-name', help='the class name of the cog (default: )', dest='class_name') + parser.add_argument('--display-name', help='the cog name (default: )') + parser.add_argument('--hide-commands', help='whether to hide all commands in the cog', action='store_true') + parser.add_argument('--full', help='add all special methods as well', action='store_true') + +def parse_args(): + parser = argparse.ArgumentParser(prog='discord', description='Tools for helping with discord.py') + parser.add_argument('-v', '--version', action='store_true', help='shows the library version') + parser.set_defaults(func=core) + + subparser = parser.add_subparsers(dest='subcommand', title='subcommands') + add_newbot_args(subparser) + add_newcog_args(subparser) + return parser, parser.parse_args() + +def main(): + parser, args = parse_args() + args.func(parser, args) + +if __name__ == '__main__': + main() diff --git a/venv/lib64/python3.8/site-packages/discord/__pycache__/__init__.cpython-38.pyc b/venv/lib64/python3.8/site-packages/discord/__pycache__/__init__.cpython-38.pyc new file mode 100644 index 0000000..ecfafb3 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/discord/__pycache__/__init__.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/discord/__pycache__/__main__.cpython-38.pyc b/venv/lib64/python3.8/site-packages/discord/__pycache__/__main__.cpython-38.pyc new file mode 100644 index 0000000..0aacd77 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/discord/__pycache__/__main__.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/discord/__pycache__/abc.cpython-38.pyc b/venv/lib64/python3.8/site-packages/discord/__pycache__/abc.cpython-38.pyc new file mode 100644 index 0000000..f2d245e Binary files /dev/null and b/venv/lib64/python3.8/site-packages/discord/__pycache__/abc.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/discord/__pycache__/activity.cpython-38.pyc b/venv/lib64/python3.8/site-packages/discord/__pycache__/activity.cpython-38.pyc new file mode 100644 index 0000000..b7e4ba5 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/discord/__pycache__/activity.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/discord/__pycache__/appinfo.cpython-38.pyc b/venv/lib64/python3.8/site-packages/discord/__pycache__/appinfo.cpython-38.pyc new file mode 100644 index 0000000..d83c3ad Binary files /dev/null and b/venv/lib64/python3.8/site-packages/discord/__pycache__/appinfo.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/discord/__pycache__/asset.cpython-38.pyc b/venv/lib64/python3.8/site-packages/discord/__pycache__/asset.cpython-38.pyc new file mode 100644 index 0000000..27833e2 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/discord/__pycache__/asset.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/discord/__pycache__/audit_logs.cpython-38.pyc b/venv/lib64/python3.8/site-packages/discord/__pycache__/audit_logs.cpython-38.pyc new file mode 100644 index 0000000..dbdacc9 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/discord/__pycache__/audit_logs.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/discord/__pycache__/backoff.cpython-38.pyc b/venv/lib64/python3.8/site-packages/discord/__pycache__/backoff.cpython-38.pyc new file mode 100644 index 0000000..9c431e3 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/discord/__pycache__/backoff.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/discord/__pycache__/calls.cpython-38.pyc b/venv/lib64/python3.8/site-packages/discord/__pycache__/calls.cpython-38.pyc new file mode 100644 index 0000000..895b6dd Binary files /dev/null and b/venv/lib64/python3.8/site-packages/discord/__pycache__/calls.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/discord/__pycache__/channel.cpython-38.pyc b/venv/lib64/python3.8/site-packages/discord/__pycache__/channel.cpython-38.pyc new file mode 100644 index 0000000..4c49223 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/discord/__pycache__/channel.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/discord/__pycache__/client.cpython-38.pyc b/venv/lib64/python3.8/site-packages/discord/__pycache__/client.cpython-38.pyc new file mode 100644 index 0000000..fd2e20e Binary files /dev/null and b/venv/lib64/python3.8/site-packages/discord/__pycache__/client.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/discord/__pycache__/colour.cpython-38.pyc b/venv/lib64/python3.8/site-packages/discord/__pycache__/colour.cpython-38.pyc new file mode 100644 index 0000000..5f211db Binary files /dev/null and b/venv/lib64/python3.8/site-packages/discord/__pycache__/colour.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/discord/__pycache__/context_managers.cpython-38.pyc b/venv/lib64/python3.8/site-packages/discord/__pycache__/context_managers.cpython-38.pyc new file mode 100644 index 0000000..6624b0d Binary files /dev/null and b/venv/lib64/python3.8/site-packages/discord/__pycache__/context_managers.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/discord/__pycache__/embeds.cpython-38.pyc b/venv/lib64/python3.8/site-packages/discord/__pycache__/embeds.cpython-38.pyc new file mode 100644 index 0000000..5265e1e Binary files /dev/null and b/venv/lib64/python3.8/site-packages/discord/__pycache__/embeds.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/discord/__pycache__/emoji.cpython-38.pyc b/venv/lib64/python3.8/site-packages/discord/__pycache__/emoji.cpython-38.pyc new file mode 100644 index 0000000..39f670d Binary files /dev/null and b/venv/lib64/python3.8/site-packages/discord/__pycache__/emoji.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/discord/__pycache__/enums.cpython-38.pyc b/venv/lib64/python3.8/site-packages/discord/__pycache__/enums.cpython-38.pyc new file mode 100644 index 0000000..5d1851a Binary files /dev/null and b/venv/lib64/python3.8/site-packages/discord/__pycache__/enums.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/discord/__pycache__/errors.cpython-38.pyc b/venv/lib64/python3.8/site-packages/discord/__pycache__/errors.cpython-38.pyc new file mode 100644 index 0000000..b6f51d1 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/discord/__pycache__/errors.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/discord/__pycache__/file.cpython-38.pyc b/venv/lib64/python3.8/site-packages/discord/__pycache__/file.cpython-38.pyc new file mode 100644 index 0000000..3308bcf Binary files /dev/null and b/venv/lib64/python3.8/site-packages/discord/__pycache__/file.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/discord/__pycache__/flags.cpython-38.pyc b/venv/lib64/python3.8/site-packages/discord/__pycache__/flags.cpython-38.pyc new file mode 100644 index 0000000..df6cf4c Binary files /dev/null and b/venv/lib64/python3.8/site-packages/discord/__pycache__/flags.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/discord/__pycache__/gateway.cpython-38.pyc b/venv/lib64/python3.8/site-packages/discord/__pycache__/gateway.cpython-38.pyc new file mode 100644 index 0000000..d221d8d Binary files /dev/null and b/venv/lib64/python3.8/site-packages/discord/__pycache__/gateway.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/discord/__pycache__/guild.cpython-38.pyc b/venv/lib64/python3.8/site-packages/discord/__pycache__/guild.cpython-38.pyc new file mode 100644 index 0000000..11fdd76 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/discord/__pycache__/guild.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/discord/__pycache__/http.cpython-38.pyc b/venv/lib64/python3.8/site-packages/discord/__pycache__/http.cpython-38.pyc new file mode 100644 index 0000000..b75c506 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/discord/__pycache__/http.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/discord/__pycache__/integrations.cpython-38.pyc b/venv/lib64/python3.8/site-packages/discord/__pycache__/integrations.cpython-38.pyc new file mode 100644 index 0000000..a61fad0 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/discord/__pycache__/integrations.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/discord/__pycache__/invite.cpython-38.pyc b/venv/lib64/python3.8/site-packages/discord/__pycache__/invite.cpython-38.pyc new file mode 100644 index 0000000..3e0a650 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/discord/__pycache__/invite.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/discord/__pycache__/iterators.cpython-38.pyc b/venv/lib64/python3.8/site-packages/discord/__pycache__/iterators.cpython-38.pyc new file mode 100644 index 0000000..8e7f2a4 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/discord/__pycache__/iterators.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/discord/__pycache__/member.cpython-38.pyc b/venv/lib64/python3.8/site-packages/discord/__pycache__/member.cpython-38.pyc new file mode 100644 index 0000000..1f38f44 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/discord/__pycache__/member.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/discord/__pycache__/mentions.cpython-38.pyc b/venv/lib64/python3.8/site-packages/discord/__pycache__/mentions.cpython-38.pyc new file mode 100644 index 0000000..4c75b1e Binary files /dev/null and b/venv/lib64/python3.8/site-packages/discord/__pycache__/mentions.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/discord/__pycache__/message.cpython-38.pyc b/venv/lib64/python3.8/site-packages/discord/__pycache__/message.cpython-38.pyc new file mode 100644 index 0000000..4aa48ce Binary files /dev/null and b/venv/lib64/python3.8/site-packages/discord/__pycache__/message.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/discord/__pycache__/mixins.cpython-38.pyc b/venv/lib64/python3.8/site-packages/discord/__pycache__/mixins.cpython-38.pyc new file mode 100644 index 0000000..44759d4 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/discord/__pycache__/mixins.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/discord/__pycache__/object.cpython-38.pyc b/venv/lib64/python3.8/site-packages/discord/__pycache__/object.cpython-38.pyc new file mode 100644 index 0000000..5815b12 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/discord/__pycache__/object.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/discord/__pycache__/oggparse.cpython-38.pyc b/venv/lib64/python3.8/site-packages/discord/__pycache__/oggparse.cpython-38.pyc new file mode 100644 index 0000000..95b8614 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/discord/__pycache__/oggparse.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/discord/__pycache__/opus.cpython-38.pyc b/venv/lib64/python3.8/site-packages/discord/__pycache__/opus.cpython-38.pyc new file mode 100644 index 0000000..115ddee Binary files /dev/null and b/venv/lib64/python3.8/site-packages/discord/__pycache__/opus.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/discord/__pycache__/partial_emoji.cpython-38.pyc b/venv/lib64/python3.8/site-packages/discord/__pycache__/partial_emoji.cpython-38.pyc new file mode 100644 index 0000000..9fcf5ff Binary files /dev/null and b/venv/lib64/python3.8/site-packages/discord/__pycache__/partial_emoji.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/discord/__pycache__/permissions.cpython-38.pyc b/venv/lib64/python3.8/site-packages/discord/__pycache__/permissions.cpython-38.pyc new file mode 100644 index 0000000..157ef44 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/discord/__pycache__/permissions.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/discord/__pycache__/player.cpython-38.pyc b/venv/lib64/python3.8/site-packages/discord/__pycache__/player.cpython-38.pyc new file mode 100644 index 0000000..cfc18c4 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/discord/__pycache__/player.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/discord/__pycache__/raw_models.cpython-38.pyc b/venv/lib64/python3.8/site-packages/discord/__pycache__/raw_models.cpython-38.pyc new file mode 100644 index 0000000..f8d5a81 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/discord/__pycache__/raw_models.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/discord/__pycache__/reaction.cpython-38.pyc b/venv/lib64/python3.8/site-packages/discord/__pycache__/reaction.cpython-38.pyc new file mode 100644 index 0000000..0ff1e89 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/discord/__pycache__/reaction.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/discord/__pycache__/relationship.cpython-38.pyc b/venv/lib64/python3.8/site-packages/discord/__pycache__/relationship.cpython-38.pyc new file mode 100644 index 0000000..c9fa5d0 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/discord/__pycache__/relationship.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/discord/__pycache__/role.cpython-38.pyc b/venv/lib64/python3.8/site-packages/discord/__pycache__/role.cpython-38.pyc new file mode 100644 index 0000000..1f00d26 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/discord/__pycache__/role.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/discord/__pycache__/shard.cpython-38.pyc b/venv/lib64/python3.8/site-packages/discord/__pycache__/shard.cpython-38.pyc new file mode 100644 index 0000000..4c1611c Binary files /dev/null and b/venv/lib64/python3.8/site-packages/discord/__pycache__/shard.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/discord/__pycache__/state.cpython-38.pyc b/venv/lib64/python3.8/site-packages/discord/__pycache__/state.cpython-38.pyc new file mode 100644 index 0000000..c7be6a5 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/discord/__pycache__/state.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/discord/__pycache__/sticker.cpython-38.pyc b/venv/lib64/python3.8/site-packages/discord/__pycache__/sticker.cpython-38.pyc new file mode 100644 index 0000000..218c2f4 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/discord/__pycache__/sticker.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/discord/__pycache__/team.cpython-38.pyc b/venv/lib64/python3.8/site-packages/discord/__pycache__/team.cpython-38.pyc new file mode 100644 index 0000000..ea79aac Binary files /dev/null and b/venv/lib64/python3.8/site-packages/discord/__pycache__/team.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/discord/__pycache__/template.cpython-38.pyc b/venv/lib64/python3.8/site-packages/discord/__pycache__/template.cpython-38.pyc new file mode 100644 index 0000000..71cbf43 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/discord/__pycache__/template.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/discord/__pycache__/user.cpython-38.pyc b/venv/lib64/python3.8/site-packages/discord/__pycache__/user.cpython-38.pyc new file mode 100644 index 0000000..16076b7 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/discord/__pycache__/user.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/discord/__pycache__/utils.cpython-38.pyc b/venv/lib64/python3.8/site-packages/discord/__pycache__/utils.cpython-38.pyc new file mode 100644 index 0000000..e07c3a6 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/discord/__pycache__/utils.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/discord/__pycache__/voice_client.cpython-38.pyc b/venv/lib64/python3.8/site-packages/discord/__pycache__/voice_client.cpython-38.pyc new file mode 100644 index 0000000..833e49f Binary files /dev/null and b/venv/lib64/python3.8/site-packages/discord/__pycache__/voice_client.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/discord/__pycache__/webhook.cpython-38.pyc b/venv/lib64/python3.8/site-packages/discord/__pycache__/webhook.cpython-38.pyc new file mode 100644 index 0000000..f71e35f Binary files /dev/null and b/venv/lib64/python3.8/site-packages/discord/__pycache__/webhook.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/discord/__pycache__/widget.cpython-38.pyc b/venv/lib64/python3.8/site-packages/discord/__pycache__/widget.cpython-38.pyc new file mode 100644 index 0000000..3593626 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/discord/__pycache__/widget.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/discord/abc.py b/venv/lib64/python3.8/site-packages/discord/abc.py new file mode 100644 index 0000000..0e48a2f --- /dev/null +++ b/venv/lib64/python3.8/site-packages/discord/abc.py @@ -0,0 +1,1294 @@ +# -*- coding: utf-8 -*- + +""" +The MIT License (MIT) + +Copyright (c) 2015-present Rapptz + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. +""" + +import abc +import sys +import copy +import asyncio + +from .iterators import HistoryIterator +from .context_managers import Typing +from .enums import ChannelType +from .errors import InvalidArgument, ClientException +from .mentions import AllowedMentions +from .permissions import PermissionOverwrite, Permissions +from .role import Role +from .invite import Invite +from .file import File +from .voice_client import VoiceClient, VoiceProtocol +from . import utils + +class _Undefined: + def __repr__(self): + return 'see-below' + +_undefined = _Undefined() + +class Snowflake(metaclass=abc.ABCMeta): + """An ABC that details the common operations on a Discord model. + + Almost all :ref:`Discord models ` meet this + abstract base class. + + If you want to create a snowflake on your own, consider using + :class:`.Object`. + + Attributes + ----------- + id: :class:`int` + The model's unique ID. + """ + __slots__ = () + + @property + @abc.abstractmethod + def created_at(self): + """:class:`datetime.datetime`: Returns the model's creation time as a naive datetime in UTC.""" + raise NotImplementedError + + @classmethod + def __subclasshook__(cls, C): + if cls is Snowflake: + mro = C.__mro__ + for attr in ('created_at', 'id'): + for base in mro: + if attr in base.__dict__: + break + else: + return NotImplemented + return True + return NotImplemented + +class User(metaclass=abc.ABCMeta): + """An ABC that details the common operations on a Discord user. + + The following implement this ABC: + + - :class:`~discord.User` + - :class:`~discord.ClientUser` + - :class:`~discord.Member` + + This ABC must also implement :class:`~discord.abc.Snowflake`. + + Attributes + ----------- + name: :class:`str` + The user's username. + discriminator: :class:`str` + The user's discriminator. + avatar: Optional[:class:`str`] + The avatar hash the user has. + bot: :class:`bool` + If the user is a bot account. + """ + __slots__ = () + + @property + @abc.abstractmethod + def display_name(self): + """:class:`str`: Returns the user's display name.""" + raise NotImplementedError + + @property + @abc.abstractmethod + def mention(self): + """:class:`str`: Returns a string that allows you to mention the given user.""" + raise NotImplementedError + + @classmethod + def __subclasshook__(cls, C): + if cls is User: + if Snowflake.__subclasshook__(C) is NotImplemented: + return NotImplemented + + mro = C.__mro__ + for attr in ('display_name', 'mention', 'name', 'avatar', 'discriminator', 'bot'): + for base in mro: + if attr in base.__dict__: + break + else: + return NotImplemented + return True + return NotImplemented + +class PrivateChannel(metaclass=abc.ABCMeta): + """An ABC that details the common operations on a private Discord channel. + + The following implement this ABC: + + - :class:`~discord.DMChannel` + - :class:`~discord.GroupChannel` + + This ABC must also implement :class:`~discord.abc.Snowflake`. + + Attributes + ----------- + me: :class:`~discord.ClientUser` + The user presenting yourself. + """ + __slots__ = () + + @classmethod + def __subclasshook__(cls, C): + if cls is PrivateChannel: + if Snowflake.__subclasshook__(C) is NotImplemented: + return NotImplemented + + mro = C.__mro__ + for base in mro: + if 'me' in base.__dict__: + return True + return NotImplemented + return NotImplemented + +class _Overwrites: + __slots__ = ('id', 'allow', 'deny', 'type') + + def __init__(self, **kwargs): + self.id = kwargs.pop('id') + self.allow = int(kwargs.pop('allow_new', 0)) + self.deny = int(kwargs.pop('deny_new', 0)) + self.type = sys.intern(kwargs.pop('type')) + + def _asdict(self): + return { + 'id': self.id, + 'allow': str(self.allow), + 'deny': str(self.deny), + 'type': self.type, + } + +class GuildChannel: + """An ABC that details the common operations on a Discord guild channel. + + The following implement this ABC: + + - :class:`~discord.TextChannel` + - :class:`~discord.VoiceChannel` + - :class:`~discord.CategoryChannel` + - :class:`~discord.StageChannel` + + This ABC must also implement :class:`~discord.abc.Snowflake`. + + Attributes + ----------- + name: :class:`str` + The channel name. + guild: :class:`~discord.Guild` + The guild the channel belongs to. + position: :class:`int` + The position in the channel list. This is a number that starts at 0. + e.g. the top channel is position 0. + """ + __slots__ = () + + def __str__(self): + return self.name + + @property + def _sorting_bucket(self): + raise NotImplementedError + + async def _move(self, position, parent_id=None, lock_permissions=False, *, reason): + if position < 0: + raise InvalidArgument('Channel position cannot be less than 0.') + + http = self._state.http + bucket = self._sorting_bucket + channels = [c for c in self.guild.channels if c._sorting_bucket == bucket] + + channels.sort(key=lambda c: c.position) + + try: + # remove ourselves from the channel list + channels.remove(self) + except ValueError: + # not there somehow lol + return + else: + index = next((i for i, c in enumerate(channels) if c.position >= position), len(channels)) + # add ourselves at our designated position + channels.insert(index, self) + + payload = [] + for index, c in enumerate(channels): + d = {'id': c.id, 'position': index} + if parent_id is not _undefined and c.id == self.id: + d.update(parent_id=parent_id, lock_permissions=lock_permissions) + payload.append(d) + + await http.bulk_channel_update(self.guild.id, payload, reason=reason) + self.position = position + if parent_id is not _undefined: + self.category_id = int(parent_id) if parent_id else None + + async def _edit(self, options, reason): + try: + parent = options.pop('category') + except KeyError: + parent_id = _undefined + else: + parent_id = parent and parent.id + + try: + options['rate_limit_per_user'] = options.pop('slowmode_delay') + except KeyError: + pass + + try: + rtc_region = options.pop('rtc_region') + except KeyError: + pass + else: + options['rtc_region'] = None if rtc_region is None else str(rtc_region) + + lock_permissions = options.pop('sync_permissions', False) + + try: + position = options.pop('position') + except KeyError: + if parent_id is not _undefined: + if lock_permissions: + category = self.guild.get_channel(parent_id) + options['permission_overwrites'] = [c._asdict() for c in category._overwrites] + options['parent_id'] = parent_id + elif lock_permissions and self.category_id is not None: + # if we're syncing permissions on a pre-existing channel category without changing it + # we need to update the permissions to point to the pre-existing category + category = self.guild.get_channel(self.category_id) + options['permission_overwrites'] = [c._asdict() for c in category._overwrites] + else: + await self._move(position, parent_id=parent_id, lock_permissions=lock_permissions, reason=reason) + + overwrites = options.get('overwrites', None) + if overwrites is not None: + perms = [] + for target, perm in overwrites.items(): + if not isinstance(perm, PermissionOverwrite): + raise InvalidArgument('Expected PermissionOverwrite received {0.__name__}'.format(type(perm))) + + allow, deny = perm.pair() + payload = { + 'allow': allow.value, + 'deny': deny.value, + 'id': target.id + } + + if isinstance(target, Role): + payload['type'] = 'role' + else: + payload['type'] = 'member' + + perms.append(payload) + options['permission_overwrites'] = perms + + try: + ch_type = options['type'] + except KeyError: + pass + else: + if not isinstance(ch_type, ChannelType): + raise InvalidArgument('type field must be of type ChannelType') + options['type'] = ch_type.value + + if options: + data = await self._state.http.edit_channel(self.id, reason=reason, **options) + self._update(self.guild, data) + + def _fill_overwrites(self, data): + self._overwrites = [] + everyone_index = 0 + everyone_id = self.guild.id + + for index, overridden in enumerate(data.get('permission_overwrites', [])): + overridden_id = int(overridden.pop('id')) + self._overwrites.append(_Overwrites(id=overridden_id, **overridden)) + + if overridden['type'] == 'member': + continue + + if overridden_id == everyone_id: + # the @everyone role is not guaranteed to be the first one + # in the list of permission overwrites, however the permission + # resolution code kind of requires that it is the first one in + # the list since it is special. So we need the index so we can + # swap it to be the first one. + everyone_index = index + + # do the swap + tmp = self._overwrites + if tmp: + tmp[everyone_index], tmp[0] = tmp[0], tmp[everyone_index] + + @property + def changed_roles(self): + """List[:class:`~discord.Role`]: Returns a list of roles that have been overridden from + their default values in the :attr:`~discord.Guild.roles` attribute.""" + ret = [] + g = self.guild + for overwrite in filter(lambda o: o.type == 'role', self._overwrites): + role = g.get_role(overwrite.id) + if role is None: + continue + + role = copy.copy(role) + role.permissions.handle_overwrite(overwrite.allow, overwrite.deny) + ret.append(role) + return ret + + @property + def mention(self): + """:class:`str`: The string that allows you to mention the channel.""" + return '<#%s>' % self.id + + @property + def created_at(self): + """:class:`datetime.datetime`: Returns the channel's creation time in UTC.""" + return utils.snowflake_time(self.id) + + def overwrites_for(self, obj): + """Returns the channel-specific overwrites for a member or a role. + + Parameters + ----------- + obj: Union[:class:`~discord.Role`, :class:`~discord.abc.User`] + The role or user denoting + whose overwrite to get. + + Returns + --------- + :class:`~discord.PermissionOverwrite` + The permission overwrites for this object. + """ + + if isinstance(obj, User): + predicate = lambda p: p.type == 'member' + elif isinstance(obj, Role): + predicate = lambda p: p.type == 'role' + else: + predicate = lambda p: True + + for overwrite in filter(predicate, self._overwrites): + if overwrite.id == obj.id: + allow = Permissions(overwrite.allow) + deny = Permissions(overwrite.deny) + return PermissionOverwrite.from_pair(allow, deny) + + return PermissionOverwrite() + + @property + def overwrites(self): + """Returns all of the channel's overwrites. + + This is returned as a dictionary where the key contains the target which + can be either a :class:`~discord.Role` or a :class:`~discord.Member` and the value is the + overwrite as a :class:`~discord.PermissionOverwrite`. + + Returns + -------- + Mapping[Union[:class:`~discord.Role`, :class:`~discord.Member`], :class:`~discord.PermissionOverwrite`] + The channel's permission overwrites. + """ + ret = {} + for ow in self._overwrites: + allow = Permissions(ow.allow) + deny = Permissions(ow.deny) + overwrite = PermissionOverwrite.from_pair(allow, deny) + + if ow.type == 'role': + target = self.guild.get_role(ow.id) + elif ow.type == 'member': + target = self.guild.get_member(ow.id) + + # TODO: There is potential data loss here in the non-chunked + # case, i.e. target is None because get_member returned nothing. + # This can be fixed with a slight breaking change to the return type, + # i.e. adding discord.Object to the list of it + # However, for now this is an acceptable compromise. + if target is not None: + ret[target] = overwrite + return ret + + @property + def category(self): + """Optional[:class:`~discord.CategoryChannel`]: The category this channel belongs to. + + If there is no category then this is ``None``. + """ + return self.guild.get_channel(self.category_id) + + @property + def permissions_synced(self): + """:class:`bool`: Whether or not the permissions for this channel are synced with the + category it belongs to. + + If there is no category then this is ``False``. + + .. versionadded:: 1.3 + """ + category = self.guild.get_channel(self.category_id) + return bool(category and category.overwrites == self.overwrites) + + def permissions_for(self, member): + """Handles permission resolution for the current :class:`~discord.Member`. + + This function takes into consideration the following cases: + + - Guild owner + - Guild roles + - Channel overrides + - Member overrides + + Parameters + ---------- + member: :class:`~discord.Member` + The member to resolve permissions for. + + Returns + ------- + :class:`~discord.Permissions` + The resolved permissions for the member. + """ + + # The current cases can be explained as: + # Guild owner get all permissions -- no questions asked. Otherwise... + # The @everyone role gets the first application. + # After that, the applied roles that the user has in the channel + # (or otherwise) are then OR'd together. + # After the role permissions are resolved, the member permissions + # have to take into effect. + # After all that is done.. you have to do the following: + + # If manage permissions is True, then all permissions are set to True. + + # The operation first takes into consideration the denied + # and then the allowed. + + if self.guild.owner_id == member.id: + return Permissions.all() + + default = self.guild.default_role + base = Permissions(default.permissions.value) + roles = member._roles + get_role = self.guild.get_role + + # Apply guild roles that the member has. + for role_id in roles: + role = get_role(role_id) + if role is not None: + base.value |= role._permissions + + # Guild-wide Administrator -> True for everything + # Bypass all channel-specific overrides + if base.administrator: + return Permissions.all() + + # Apply @everyone allow/deny first since it's special + try: + maybe_everyone = self._overwrites[0] + if maybe_everyone.id == self.guild.id: + base.handle_overwrite(allow=maybe_everyone.allow, deny=maybe_everyone.deny) + remaining_overwrites = self._overwrites[1:] + else: + remaining_overwrites = self._overwrites + except IndexError: + remaining_overwrites = self._overwrites + + denies = 0 + allows = 0 + + # Apply channel specific role permission overwrites + for overwrite in remaining_overwrites: + if overwrite.type == 'role' and roles.has(overwrite.id): + denies |= overwrite.deny + allows |= overwrite.allow + + base.handle_overwrite(allow=allows, deny=denies) + + # Apply member specific permission overwrites + for overwrite in remaining_overwrites: + if overwrite.type == 'member' and overwrite.id == member.id: + base.handle_overwrite(allow=overwrite.allow, deny=overwrite.deny) + break + + # if you can't send a message in a channel then you can't have certain + # permissions as well + if not base.send_messages: + base.send_tts_messages = False + base.mention_everyone = False + base.embed_links = False + base.attach_files = False + + # if you can't read a channel then you have no permissions there + if not base.read_messages: + denied = Permissions.all_channel() + base.value &= ~denied.value + + return base + + async def delete(self, *, reason=None): + """|coro| + + Deletes the channel. + + You must have :attr:`~Permissions.manage_channels` permission to use this. + + Parameters + ----------- + reason: Optional[:class:`str`] + The reason for deleting this channel. + Shows up on the audit log. + + Raises + ------- + ~discord.Forbidden + You do not have proper permissions to delete the channel. + ~discord.NotFound + The channel was not found or was already deleted. + ~discord.HTTPException + Deleting the channel failed. + """ + await self._state.http.delete_channel(self.id, reason=reason) + + async def set_permissions(self, target, *, overwrite=_undefined, reason=None, **permissions): + r"""|coro| + + Sets the channel specific permission overwrites for a target in the + channel. + + The ``target`` parameter should either be a :class:`~discord.Member` or a + :class:`~discord.Role` that belongs to guild. + + The ``overwrite`` parameter, if given, must either be ``None`` or + :class:`~discord.PermissionOverwrite`. For convenience, you can pass in + keyword arguments denoting :class:`~discord.Permissions` attributes. If this is + done, then you cannot mix the keyword arguments with the ``overwrite`` + parameter. + + If the ``overwrite`` parameter is ``None``, then the permission + overwrites are deleted. + + You must have the :attr:`~Permissions.manage_roles` permission to use this. + + Examples + ---------- + + Setting allow and deny: :: + + await message.channel.set_permissions(message.author, read_messages=True, + send_messages=False) + + Deleting overwrites :: + + await channel.set_permissions(member, overwrite=None) + + Using :class:`~discord.PermissionOverwrite` :: + + overwrite = discord.PermissionOverwrite() + overwrite.send_messages = False + overwrite.read_messages = True + await channel.set_permissions(member, overwrite=overwrite) + + Parameters + ----------- + target: Union[:class:`~discord.Member`, :class:`~discord.Role`] + The member or role to overwrite permissions for. + overwrite: Optional[:class:`~discord.PermissionOverwrite`] + The permissions to allow and deny to the target, or ``None`` to + delete the overwrite. + \*\*permissions + A keyword argument list of permissions to set for ease of use. + Cannot be mixed with ``overwrite``. + reason: Optional[:class:`str`] + The reason for doing this action. Shows up on the audit log. + + Raises + ------- + ~discord.Forbidden + You do not have permissions to edit channel specific permissions. + ~discord.HTTPException + Editing channel specific permissions failed. + ~discord.NotFound + The role or member being edited is not part of the guild. + ~discord.InvalidArgument + The overwrite parameter invalid or the target type was not + :class:`~discord.Role` or :class:`~discord.Member`. + """ + + http = self._state.http + + if isinstance(target, User): + perm_type = 'member' + elif isinstance(target, Role): + perm_type = 'role' + else: + raise InvalidArgument('target parameter must be either Member or Role') + + if isinstance(overwrite, _Undefined): + if len(permissions) == 0: + raise InvalidArgument('No overwrite provided.') + try: + overwrite = PermissionOverwrite(**permissions) + except (ValueError, TypeError): + raise InvalidArgument('Invalid permissions given to keyword arguments.') + else: + if len(permissions) > 0: + raise InvalidArgument('Cannot mix overwrite and keyword arguments.') + + # TODO: wait for event + + if overwrite is None: + await http.delete_channel_permissions(self.id, target.id, reason=reason) + elif isinstance(overwrite, PermissionOverwrite): + (allow, deny) = overwrite.pair() + await http.edit_channel_permissions(self.id, target.id, allow.value, deny.value, perm_type, reason=reason) + else: + raise InvalidArgument('Invalid overwrite type provided.') + + async def _clone_impl(self, base_attrs, *, name=None, reason=None): + base_attrs['permission_overwrites'] = [ + x._asdict() for x in self._overwrites + ] + base_attrs['parent_id'] = self.category_id + base_attrs['name'] = name or self.name + guild_id = self.guild.id + cls = self.__class__ + data = await self._state.http.create_channel(guild_id, self.type.value, reason=reason, **base_attrs) + obj = cls(state=self._state, guild=self.guild, data=data) + + # temporarily add it to the cache + self.guild._channels[obj.id] = obj + return obj + + async def clone(self, *, name=None, reason=None): + """|coro| + + Clones this channel. This creates a channel with the same properties + as this channel. + + You must have the :attr:`~discord.Permissions.manage_channels` permission to + do this. + + .. versionadded:: 1.1 + + Parameters + ------------ + name: Optional[:class:`str`] + The name of the new channel. If not provided, defaults to this + channel name. + reason: Optional[:class:`str`] + The reason for cloning this channel. Shows up on the audit log. + + Raises + ------- + ~discord.Forbidden + You do not have the proper permissions to create this channel. + ~discord.HTTPException + Creating the channel failed. + + Returns + -------- + :class:`.abc.GuildChannel` + The channel that was created. + """ + raise NotImplementedError + + async def move(self, **kwargs): + """|coro| + + A rich interface to help move a channel relative to other channels. + + If exact position movement is required, :meth:`edit` should be used instead. + + You must have the :attr:`~discord.Permissions.manage_channels` permission to + do this. + + .. note:: + + Voice channels will always be sorted below text channels. + This is a Discord limitation. + + .. versionadded:: 1.7 + + Parameters + ------------ + beginning: :class:`bool` + Whether to move the channel to the beginning of the + channel list (or category if given). + This is mutually exclusive with ``end``, ``before``, and ``after``. + end: :class:`bool` + Whether to move the channel to the end of the + channel list (or category if given). + This is mutually exclusive with ``beginning``, ``before``, and ``after``. + before: :class:`~discord.abc.Snowflake` + The channel that should be before our current channel. + This is mutually exclusive with ``beginning``, ``end``, and ``after``. + after: :class:`~discord.abc.Snowflake` + The channel that should be after our current channel. + This is mutually exclusive with ``beginning``, ``end``, and ``before``. + offset: :class:`int` + The number of channels to offset the move by. For example, + an offset of ``2`` with ``beginning=True`` would move + it 2 after the beginning. A positive number moves it below + while a negative number moves it above. Note that this + number is relative and computed after the ``beginning``, + ``end``, ``before``, and ``after`` parameters. + category: Optional[:class:`~discord.abc.Snowflake`] + The category to move this channel under. + If ``None`` is given then it moves it out of the category. + This parameter is ignored if moving a category channel. + sync_permissions: :class:`bool` + Whether to sync the permissions with the category (if given). + reason: :class:`str` + The reason for the move. + + Raises + ------- + InvalidArgument + An invalid position was given or a bad mix of arguments were passed. + Forbidden + You do not have permissions to move the channel. + HTTPException + Moving the channel failed. + """ + + if not kwargs: + return + + beginning, end = kwargs.get('beginning'), kwargs.get('end') + before, after = kwargs.get('before'), kwargs.get('after') + offset = kwargs.get('offset', 0) + if sum(bool(a) for a in (beginning, end, before, after)) > 1: + raise InvalidArgument('Only one of [before, after, end, beginning] can be used.') + + bucket = self._sorting_bucket + parent_id = kwargs.get('category', ...) + if parent_id not in (..., None): + parent_id = parent_id.id + channels = [ + ch + for ch in self.guild.channels + if ch._sorting_bucket == bucket + and ch.category_id == parent_id + ] + else: + channels = [ + ch + for ch in self.guild.channels + if ch._sorting_bucket == bucket + and ch.category_id == self.category_id + ] + + channels.sort(key=lambda c: (c.position, c.id)) + + try: + # Try to remove ourselves from the channel list + channels.remove(self) + except ValueError: + # If we're not there then it's probably due to not being in the category + pass + + index = None + if beginning: + index = 0 + elif end: + index = len(channels) + elif before: + index = next((i for i, c in enumerate(channels) if c.id == before.id), None) + elif after: + index = next((i + 1 for i, c in enumerate(channels) if c.id == after.id), None) + + if index is None: + raise InvalidArgument('Could not resolve appropriate move position') + + channels.insert(max((index + offset), 0), self) + payload = [] + lock_permissions = kwargs.get('sync_permissions', False) + reason = kwargs.get('reason') + for index, channel in enumerate(channels): + d = { 'id': channel.id, 'position': index } + if parent_id is not ... and channel.id == self.id: + d.update(parent_id=parent_id, lock_permissions=lock_permissions) + payload.append(d) + + await self._state.http.bulk_channel_update(self.guild.id, payload, reason=reason) + + + async def create_invite(self, *, reason=None, **fields): + """|coro| + + Creates an instant invite from a text or voice channel. + + You must have the :attr:`~Permissions.create_instant_invite` permission to + do this. + + Parameters + ------------ + max_age: :class:`int` + How long the invite should last in seconds. If it's 0 then the invite + doesn't expire. Defaults to ``0``. + max_uses: :class:`int` + How many uses the invite could be used for. If it's 0 then there + are unlimited uses. Defaults to ``0``. + temporary: :class:`bool` + Denotes that the invite grants temporary membership + (i.e. they get kicked after they disconnect). Defaults to ``False``. + unique: :class:`bool` + Indicates if a unique invite URL should be created. Defaults to True. + If this is set to ``False`` then it will return a previously created + invite. + reason: Optional[:class:`str`] + The reason for creating this invite. Shows up on the audit log. + + Raises + ------- + ~discord.HTTPException + Invite creation failed. + + ~discord.NotFound + The channel that was passed is a category or an invalid channel. + + Returns + -------- + :class:`~discord.Invite` + The invite that was created. + """ + + data = await self._state.http.create_invite(self.id, reason=reason, **fields) + return Invite.from_incomplete(data=data, state=self._state) + + async def invites(self): + """|coro| + + Returns a list of all active instant invites from this channel. + + You must have :attr:`~Permissions.manage_channels` to get this information. + + Raises + ------- + ~discord.Forbidden + You do not have proper permissions to get the information. + ~discord.HTTPException + An error occurred while fetching the information. + + Returns + ------- + List[:class:`~discord.Invite`] + The list of invites that are currently active. + """ + + state = self._state + data = await state.http.invites_from_channel(self.id) + result = [] + + for invite in data: + invite['channel'] = self + invite['guild'] = self.guild + result.append(Invite(state=state, data=invite)) + + return result + +class Messageable(metaclass=abc.ABCMeta): + """An ABC that details the common operations on a model that can send messages. + + The following implement this ABC: + + - :class:`~discord.TextChannel` + - :class:`~discord.DMChannel` + - :class:`~discord.GroupChannel` + - :class:`~discord.User` + - :class:`~discord.Member` + - :class:`~discord.ext.commands.Context` + """ + + __slots__ = () + + @abc.abstractmethod + async def _get_channel(self): + raise NotImplementedError + + async def send(self, content=None, *, tts=False, embed=None, file=None, + files=None, delete_after=None, nonce=None, + allowed_mentions=None, reference=None, + mention_author=None): + """|coro| + + Sends a message to the destination with the content given. + + The content must be a type that can convert to a string through ``str(content)``. + If the content is set to ``None`` (the default), then the ``embed`` parameter must + be provided. + + To upload a single file, the ``file`` parameter should be used with a + single :class:`~discord.File` object. To upload multiple files, the ``files`` + parameter should be used with a :class:`list` of :class:`~discord.File` objects. + **Specifying both parameters will lead to an exception**. + + If the ``embed`` parameter is provided, it must be of type :class:`~discord.Embed` and + it must be a rich embed type. + + Parameters + ------------ + content: :class:`str` + The content of the message to send. + tts: :class:`bool` + Indicates if the message should be sent using text-to-speech. + embed: :class:`~discord.Embed` + The rich embed for the content. + file: :class:`~discord.File` + The file to upload. + files: List[:class:`~discord.File`] + A list of files to upload. Must be a maximum of 10. + nonce: :class:`int` + The nonce to use for sending this message. If the message was successfully sent, + then the message will have a nonce with this value. + delete_after: :class:`float` + If provided, the number of seconds to wait in the background + before deleting the message we just sent. If the deletion fails, + then it is silently ignored. + allowed_mentions: :class:`~discord.AllowedMentions` + Controls the mentions being processed in this message. If this is + passed, then the object is merged with :attr:`~discord.Client.allowed_mentions`. + The merging behaviour only overrides attributes that have been explicitly passed + to the object, otherwise it uses the attributes set in :attr:`~discord.Client.allowed_mentions`. + If no object is passed at all then the defaults given by :attr:`~discord.Client.allowed_mentions` + are used instead. + + .. versionadded:: 1.4 + + reference: Union[:class:`~discord.Message`, :class:`~discord.MessageReference`] + A reference to the :class:`~discord.Message` to which you are replying, this can be created using + :meth:`~discord.Message.to_reference` or passed directly as a :class:`~discord.Message`. You can control + whether this mentions the author of the referenced message using the :attr:`~discord.AllowedMentions.replied_user` + attribute of ``allowed_mentions`` or by setting ``mention_author``. + + .. versionadded:: 1.6 + + mention_author: Optional[:class:`bool`] + If set, overrides the :attr:`~discord.AllowedMentions.replied_user` attribute of ``allowed_mentions``. + + .. versionadded:: 1.6 + + Raises + -------- + ~discord.HTTPException + Sending the message failed. + ~discord.Forbidden + You do not have the proper permissions to send the message. + ~discord.InvalidArgument + The ``files`` list is not of the appropriate size, + you specified both ``file`` and ``files``, + or the ``reference`` object is not a :class:`~discord.Message` + or :class:`~discord.MessageReference`. + + Returns + --------- + :class:`~discord.Message` + The message that was sent. + """ + + channel = await self._get_channel() + state = self._state + content = str(content) if content is not None else None + if embed is not None: + embed = embed.to_dict() + + if allowed_mentions is not None: + if state.allowed_mentions is not None: + allowed_mentions = state.allowed_mentions.merge(allowed_mentions).to_dict() + else: + allowed_mentions = allowed_mentions.to_dict() + else: + allowed_mentions = state.allowed_mentions and state.allowed_mentions.to_dict() + + if mention_author is not None: + allowed_mentions = allowed_mentions or AllowedMentions().to_dict() + allowed_mentions['replied_user'] = bool(mention_author) + + if reference is not None: + try: + reference = reference.to_message_reference_dict() + except AttributeError: + raise InvalidArgument('reference parameter must be Message or MessageReference') from None + + if file is not None and files is not None: + raise InvalidArgument('cannot pass both file and files parameter to send()') + + if file is not None: + if not isinstance(file, File): + raise InvalidArgument('file parameter must be File') + + try: + data = await state.http.send_files(channel.id, files=[file], allowed_mentions=allowed_mentions, + content=content, tts=tts, embed=embed, nonce=nonce, + message_reference=reference) + finally: + file.close() + + elif files is not None: + if len(files) > 10: + raise InvalidArgument('files parameter must be a list of up to 10 elements') + elif not all(isinstance(file, File) for file in files): + raise InvalidArgument('files parameter must be a list of File') + + try: + data = await state.http.send_files(channel.id, files=files, content=content, tts=tts, + embed=embed, nonce=nonce, allowed_mentions=allowed_mentions, + message_reference=reference) + finally: + for f in files: + f.close() + else: + data = await state.http.send_message(channel.id, content, tts=tts, embed=embed, + nonce=nonce, allowed_mentions=allowed_mentions, + message_reference=reference) + + ret = state.create_message(channel=channel, data=data) + if delete_after is not None: + await ret.delete(delay=delete_after) + return ret + + async def trigger_typing(self): + """|coro| + + Triggers a *typing* indicator to the destination. + + *Typing* indicator will go away after 10 seconds, or after a message is sent. + """ + + channel = await self._get_channel() + await self._state.http.send_typing(channel.id) + + def typing(self): + """Returns a context manager that allows you to type for an indefinite period of time. + + This is useful for denoting long computations in your bot. + + .. note:: + + This is both a regular context manager and an async context manager. + This means that both ``with`` and ``async with`` work with this. + + Example Usage: :: + + async with channel.typing(): + # do expensive stuff here + await channel.send('done!') + + """ + return Typing(self) + + async def fetch_message(self, id): + """|coro| + + Retrieves a single :class:`~discord.Message` from the destination. + + This can only be used by bot accounts. + + Parameters + ------------ + id: :class:`int` + The message ID to look for. + + Raises + -------- + ~discord.NotFound + The specified message was not found. + ~discord.Forbidden + You do not have the permissions required to get a message. + ~discord.HTTPException + Retrieving the message failed. + + Returns + -------- + :class:`~discord.Message` + The message asked for. + """ + + channel = await self._get_channel() + data = await self._state.http.get_message(channel.id, id) + return self._state.create_message(channel=channel, data=data) + + async def pins(self): + """|coro| + + Retrieves all messages that are currently pinned in the channel. + + .. note:: + + Due to a limitation with the Discord API, the :class:`.Message` + objects returned by this method do not contain complete + :attr:`.Message.reactions` data. + + Raises + ------- + ~discord.HTTPException + Retrieving the pinned messages failed. + + Returns + -------- + List[:class:`~discord.Message`] + The messages that are currently pinned. + """ + + channel = await self._get_channel() + state = self._state + data = await state.http.pins_from(channel.id) + return [state.create_message(channel=channel, data=m) for m in data] + + def history(self, *, limit=100, before=None, after=None, around=None, oldest_first=None): + """Returns an :class:`~discord.AsyncIterator` that enables receiving the destination's message history. + + You must have :attr:`~Permissions.read_message_history` permissions to use this. + + Examples + --------- + + Usage :: + + counter = 0 + async for message in channel.history(limit=200): + if message.author == client.user: + counter += 1 + + Flattening into a list: :: + + messages = await channel.history(limit=123).flatten() + # messages is now a list of Message... + + All parameters are optional. + + Parameters + ----------- + limit: Optional[:class:`int`] + The number of messages to retrieve. + If ``None``, retrieves every message in the channel. Note, however, + that this would make it a slow operation. + before: Optional[Union[:class:`~discord.abc.Snowflake`, :class:`datetime.datetime`]] + Retrieve messages before this date or message. + If a date is provided it must be a timezone-naive datetime representing UTC time. + after: Optional[Union[:class:`~discord.abc.Snowflake`, :class:`datetime.datetime`]] + Retrieve messages after this date or message. + If a date is provided it must be a timezone-naive datetime representing UTC time. + around: Optional[Union[:class:`~discord.abc.Snowflake`, :class:`datetime.datetime`]] + Retrieve messages around this date or message. + If a date is provided it must be a timezone-naive datetime representing UTC time. + When using this argument, the maximum limit is 101. Note that if the limit is an + even number then this will return at most limit + 1 messages. + oldest_first: Optional[:class:`bool`] + If set to ``True``, return messages in oldest->newest order. Defaults to ``True`` if + ``after`` is specified, otherwise ``False``. + + Raises + ------ + ~discord.Forbidden + You do not have permissions to get channel message history. + ~discord.HTTPException + The request to get message history failed. + + Yields + ------- + :class:`~discord.Message` + The message with the message data parsed. + """ + return HistoryIterator(self, limit=limit, before=before, after=after, around=around, oldest_first=oldest_first) + +class Connectable(metaclass=abc.ABCMeta): + """An ABC that details the common operations on a channel that can + connect to a voice server. + + The following implement this ABC: + + - :class:`~discord.VoiceChannel` + """ + __slots__ = () + + @abc.abstractmethod + def _get_voice_client_key(self): + raise NotImplementedError + + @abc.abstractmethod + def _get_voice_state_pair(self): + raise NotImplementedError + + async def connect(self, *, timeout=60.0, reconnect=True, cls=VoiceClient): + """|coro| + + Connects to voice and creates a :class:`VoiceClient` to establish + your connection to the voice server. + + Parameters + ----------- + timeout: :class:`float` + The timeout in seconds to wait for the voice endpoint. + reconnect: :class:`bool` + Whether the bot should automatically attempt + a reconnect if a part of the handshake fails + or the gateway goes down. + cls: Type[:class:`VoiceProtocol`] + A type that subclasses :class:`~discord.VoiceProtocol` to connect with. + Defaults to :class:`~discord.VoiceClient`. + + Raises + ------- + asyncio.TimeoutError + Could not connect to the voice channel in time. + ~discord.ClientException + You are already connected to a voice channel. + ~discord.opus.OpusNotLoaded + The opus library has not been loaded. + + Returns + -------- + :class:`~discord.VoiceProtocol` + A voice client that is fully connected to the voice server. + """ + + key_id, _ = self._get_voice_client_key() + state = self._state + + if state._get_voice_client(key_id): + raise ClientException('Already connected to a voice channel.') + + client = state._get_client() + voice = cls(client, self) + + if not isinstance(voice, VoiceProtocol): + raise TypeError('Type must meet VoiceProtocol abstract base class.') + + state._add_voice_client(key_id, voice) + + try: + await voice.connect(timeout=timeout, reconnect=reconnect) + except asyncio.TimeoutError: + try: + await voice.disconnect(force=True) + except Exception: + # we don't care if disconnect failed because connection failed + pass + raise # re-raise + + return voice diff --git a/venv/lib64/python3.8/site-packages/discord/activity.py b/venv/lib64/python3.8/site-packages/discord/activity.py new file mode 100644 index 0000000..cf5192a --- /dev/null +++ b/venv/lib64/python3.8/site-packages/discord/activity.py @@ -0,0 +1,773 @@ +# -*- coding: utf-8 -*- + +""" +The MIT License (MIT) + +Copyright (c) 2015-present Rapptz + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. +""" + +import datetime + +from .asset import Asset +from .enums import ActivityType, try_enum +from .colour import Colour +from .partial_emoji import PartialEmoji +from .utils import _get_as_snowflake + +__all__ = ( + 'BaseActivity', + 'Activity', + 'Streaming', + 'Game', + 'Spotify', + 'CustomActivity', +) + +"""If curious, this is the current schema for an activity. + +It's fairly long so I will document it here: + +All keys are optional. + +state: str (max: 128), +details: str (max: 128) +timestamps: dict + start: int (min: 1) + end: int (min: 1) +assets: dict + large_image: str (max: 32) + large_text: str (max: 128) + small_image: str (max: 32) + small_text: str (max: 128) +party: dict + id: str (max: 128), + size: List[int] (max-length: 2) + elem: int (min: 1) +secrets: dict + match: str (max: 128) + join: str (max: 128) + spectate: str (max: 128) +instance: bool +application_id: str +name: str (max: 128) +url: str +type: int +sync_id: str +session_id: str +flags: int + +There are also activity flags which are mostly uninteresting for the library atm. + +t.ActivityFlags = { + INSTANCE: 1, + JOIN: 2, + SPECTATE: 4, + JOIN_REQUEST: 8, + SYNC: 16, + PLAY: 32 +} +""" + +class BaseActivity: + """The base activity that all user-settable activities inherit from. + A user-settable activity is one that can be used in :meth:`Client.change_presence`. + + The following types currently count as user-settable: + + - :class:`Activity` + - :class:`Game` + - :class:`Streaming` + - :class:`CustomActivity` + + Note that although these types are considered user-settable by the library, + Discord typically ignores certain combinations of activity depending on + what is currently set. This behaviour may change in the future so there are + no guarantees on whether Discord will actually let you set these types. + + .. versionadded:: 1.3 + """ + __slots__ = ('_created_at',) + + def __init__(self, **kwargs): + self._created_at = kwargs.pop('created_at', None) + + @property + def created_at(self): + """Optional[:class:`datetime.datetime`]: When the user started doing this activity in UTC. + + .. versionadded:: 1.3 + """ + if self._created_at is not None: + return datetime.datetime.utcfromtimestamp(self._created_at / 1000) + +class Activity(BaseActivity): + """Represents an activity in Discord. + + This could be an activity such as streaming, playing, listening + or watching. + + For memory optimisation purposes, some activities are offered in slimmed + down versions: + + - :class:`Game` + - :class:`Streaming` + + Attributes + ------------ + application_id: :class:`int` + The application ID of the game. + name: :class:`str` + The name of the activity. + url: :class:`str` + A stream URL that the activity could be doing. + type: :class:`ActivityType` + The type of activity currently being done. + state: :class:`str` + The user's current state. For example, "In Game". + details: :class:`str` + The detail of the user's current activity. + timestamps: :class:`dict` + A dictionary of timestamps. It contains the following optional keys: + + - ``start``: Corresponds to when the user started doing the + activity in milliseconds since Unix epoch. + - ``end``: Corresponds to when the user will finish doing the + activity in milliseconds since Unix epoch. + + assets: :class:`dict` + A dictionary representing the images and their hover text of an activity. + It contains the following optional keys: + + - ``large_image``: A string representing the ID for the large image asset. + - ``large_text``: A string representing the text when hovering over the large image asset. + - ``small_image``: A string representing the ID for the small image asset. + - ``small_text``: A string representing the text when hovering over the small image asset. + + party: :class:`dict` + A dictionary representing the activity party. It contains the following optional keys: + + - ``id``: A string representing the party ID. + - ``size``: A list of up to two integer elements denoting (current_size, maximum_size). + emoji: Optional[:class:`PartialEmoji`] + The emoji that belongs to this activity. + """ + + __slots__ = ('state', 'details', '_created_at', 'timestamps', 'assets', 'party', + 'flags', 'sync_id', 'session_id', 'type', 'name', 'url', + 'application_id', 'emoji') + + def __init__(self, **kwargs): + super().__init__(**kwargs) + self.state = kwargs.pop('state', None) + self.details = kwargs.pop('details', None) + self.timestamps = kwargs.pop('timestamps', {}) + self.assets = kwargs.pop('assets', {}) + self.party = kwargs.pop('party', {}) + self.application_id = _get_as_snowflake(kwargs, 'application_id') + self.name = kwargs.pop('name', None) + self.url = kwargs.pop('url', None) + self.flags = kwargs.pop('flags', 0) + self.sync_id = kwargs.pop('sync_id', None) + self.session_id = kwargs.pop('session_id', None) + self.type = try_enum(ActivityType, kwargs.pop('type', -1)) + emoji = kwargs.pop('emoji', None) + if emoji is not None: + self.emoji = PartialEmoji.from_dict(emoji) + else: + self.emoji = None + + def __repr__(self): + attrs = ( + 'type', + 'name', + 'url', + 'details', + 'application_id', + 'session_id', + 'emoji', + ) + mapped = ' '.join('%s=%r' % (attr, getattr(self, attr)) for attr in attrs) + return '' % mapped + + def to_dict(self): + ret = {} + for attr in self.__slots__: + value = getattr(self, attr, None) + if value is None: + continue + + if isinstance(value, dict) and len(value) == 0: + continue + + ret[attr] = value + ret['type'] = int(self.type) + if self.emoji: + ret['emoji'] = self.emoji.to_dict() + return ret + + @property + def start(self): + """Optional[:class:`datetime.datetime`]: When the user started doing this activity in UTC, if applicable.""" + try: + return datetime.datetime.utcfromtimestamp(self.timestamps['start'] / 1000) + except KeyError: + return None + + @property + def end(self): + """Optional[:class:`datetime.datetime`]: When the user will stop doing this activity in UTC, if applicable.""" + try: + return datetime.datetime.utcfromtimestamp(self.timestamps['end'] / 1000) + except KeyError: + return None + + @property + def large_image_url(self): + """Optional[:class:`str`]: Returns a URL pointing to the large image asset of this activity if applicable.""" + if self.application_id is None: + return None + + try: + large_image = self.assets['large_image'] + except KeyError: + return None + else: + return Asset.BASE + '/app-assets/{0}/{1}.png'.format(self.application_id, large_image) + + @property + def small_image_url(self): + """Optional[:class:`str`]: Returns a URL pointing to the small image asset of this activity if applicable.""" + if self.application_id is None: + return None + + try: + small_image = self.assets['small_image'] + except KeyError: + return None + else: + return Asset.BASE + '/app-assets/{0}/{1}.png'.format(self.application_id, small_image) + @property + def large_image_text(self): + """Optional[:class:`str`]: Returns the large image asset hover text of this activity if applicable.""" + return self.assets.get('large_text', None) + + @property + def small_image_text(self): + """Optional[:class:`str`]: Returns the small image asset hover text of this activity if applicable.""" + return self.assets.get('small_text', None) + + +class Game(BaseActivity): + """A slimmed down version of :class:`Activity` that represents a Discord game. + + This is typically displayed via **Playing** on the official Discord client. + + .. container:: operations + + .. describe:: x == y + + Checks if two games are equal. + + .. describe:: x != y + + Checks if two games are not equal. + + .. describe:: hash(x) + + Returns the game's hash. + + .. describe:: str(x) + + Returns the game's name. + + Parameters + ----------- + name: :class:`str` + The game's name. + start: Optional[:class:`datetime.datetime`] + A naive UTC timestamp representing when the game started. Keyword-only parameter. Ignored for bots. + end: Optional[:class:`datetime.datetime`] + A naive UTC timestamp representing when the game ends. Keyword-only parameter. Ignored for bots. + + Attributes + ----------- + name: :class:`str` + The game's name. + """ + + __slots__ = ('name', '_end', '_start') + + def __init__(self, name, **extra): + super().__init__(**extra) + self.name = name + + try: + timestamps = extra['timestamps'] + except KeyError: + self._extract_timestamp(extra, 'start') + self._extract_timestamp(extra, 'end') + else: + self._start = timestamps.get('start', 0) + self._end = timestamps.get('end', 0) + + def _extract_timestamp(self, data, key): + try: + dt = data[key] + except KeyError: + setattr(self, '_' + key, 0) + else: + setattr(self, '_' + key, dt.timestamp() * 1000.0) + + @property + def type(self): + """:class:`ActivityType`: Returns the game's type. This is for compatibility with :class:`Activity`. + + It always returns :attr:`ActivityType.playing`. + """ + return ActivityType.playing + + @property + def start(self): + """Optional[:class:`datetime.datetime`]: When the user started playing this game in UTC, if applicable.""" + if self._start: + return datetime.datetime.utcfromtimestamp(self._start / 1000) + return None + + @property + def end(self): + """Optional[:class:`datetime.datetime`]: When the user will stop playing this game in UTC, if applicable.""" + if self._end: + return datetime.datetime.utcfromtimestamp(self._end / 1000) + return None + + def __str__(self): + return str(self.name) + + def __repr__(self): + return ''.format(self) + + def to_dict(self): + timestamps = {} + if self._start: + timestamps['start'] = self._start + + if self._end: + timestamps['end'] = self._end + + return { + 'type': ActivityType.playing.value, + 'name': str(self.name), + 'timestamps': timestamps + } + + def __eq__(self, other): + return isinstance(other, Game) and other.name == self.name + + def __ne__(self, other): + return not self.__eq__(other) + + def __hash__(self): + return hash(self.name) + +class Streaming(BaseActivity): + """A slimmed down version of :class:`Activity` that represents a Discord streaming status. + + This is typically displayed via **Streaming** on the official Discord client. + + .. container:: operations + + .. describe:: x == y + + Checks if two streams are equal. + + .. describe:: x != y + + Checks if two streams are not equal. + + .. describe:: hash(x) + + Returns the stream's hash. + + .. describe:: str(x) + + Returns the stream's name. + + Attributes + ----------- + platform: :class:`str` + Where the user is streaming from (ie. YouTube, Twitch). + + .. versionadded:: 1.3 + + name: Optional[:class:`str`] + The stream's name. + details: Optional[:class:`str`] + An alias for :attr:`name` + game: Optional[:class:`str`] + The game being streamed. + + .. versionadded:: 1.3 + + url: :class:`str` + The stream's URL. + assets: :class:`dict` + A dictionary comprising of similar keys than those in :attr:`Activity.assets`. + """ + + __slots__ = ('platform', 'name', 'game', 'url', 'details', 'assets') + + def __init__(self, *, name, url, **extra): + super().__init__(**extra) + self.platform = name + self.name = extra.pop('details', name) + self.game = extra.pop('state', None) + self.url = url + self.details = extra.pop('details', self.name) # compatibility + self.assets = extra.pop('assets', {}) + + @property + def type(self): + """:class:`ActivityType`: Returns the game's type. This is for compatibility with :class:`Activity`. + + It always returns :attr:`ActivityType.streaming`. + """ + return ActivityType.streaming + + def __str__(self): + return str(self.name) + + def __repr__(self): + return ''.format(self) + + @property + def twitch_name(self): + """Optional[:class:`str`]: If provided, the twitch name of the user streaming. + + This corresponds to the ``large_image`` key of the :attr:`Streaming.assets` + dictionary if it starts with ``twitch:``. Typically set by the Discord client. + """ + + try: + name = self.assets['large_image'] + except KeyError: + return None + else: + return name[7:] if name[:7] == 'twitch:' else None + + def to_dict(self): + ret = { + 'type': ActivityType.streaming.value, + 'name': str(self.name), + 'url': str(self.url), + 'assets': self.assets + } + if self.details: + ret['details'] = self.details + return ret + + def __eq__(self, other): + return isinstance(other, Streaming) and other.name == self.name and other.url == self.url + + def __ne__(self, other): + return not self.__eq__(other) + + def __hash__(self): + return hash(self.name) + +class Spotify: + """Represents a Spotify listening activity from Discord. This is a special case of + :class:`Activity` that makes it easier to work with the Spotify integration. + + .. container:: operations + + .. describe:: x == y + + Checks if two activities are equal. + + .. describe:: x != y + + Checks if two activities are not equal. + + .. describe:: hash(x) + + Returns the activity's hash. + + .. describe:: str(x) + + Returns the string 'Spotify'. + """ + + __slots__ = ('_state', '_details', '_timestamps', '_assets', '_party', '_sync_id', '_session_id', + '_created_at') + + def __init__(self, **data): + self._state = data.pop('state', None) + self._details = data.pop('details', None) + self._timestamps = data.pop('timestamps', {}) + self._assets = data.pop('assets', {}) + self._party = data.pop('party', {}) + self._sync_id = data.pop('sync_id') + self._session_id = data.pop('session_id') + self._created_at = data.pop('created_at', None) + + @property + def type(self): + """:class:`ActivityType`: Returns the activity's type. This is for compatibility with :class:`Activity`. + + It always returns :attr:`ActivityType.listening`. + """ + return ActivityType.listening + + @property + def created_at(self): + """Optional[:class:`datetime.datetime`]: When the user started listening in UTC. + + .. versionadded:: 1.3 + """ + if self._created_at is not None: + return datetime.datetime.utcfromtimestamp(self._created_at / 1000) + + @property + def colour(self): + """:class:`Colour`: Returns the Spotify integration colour, as a :class:`Colour`. + + There is an alias for this named :attr:`color`""" + return Colour(0x1db954) + + @property + def color(self): + """:class:`Colour`: Returns the Spotify integration colour, as a :class:`Colour`. + + There is an alias for this named :attr:`colour`""" + return self.colour + + def to_dict(self): + return { + 'flags': 48, # SYNC | PLAY + 'name': 'Spotify', + 'assets': self._assets, + 'party': self._party, + 'sync_id': self._sync_id, + 'session_id': self._session_id, + 'timestamps': self._timestamps, + 'details': self._details, + 'state': self._state + } + + @property + def name(self): + """:class:`str`: The activity's name. This will always return "Spotify".""" + return 'Spotify' + + def __eq__(self, other): + return (isinstance(other, Spotify) and other._session_id == self._session_id + and other._sync_id == self._sync_id and other.start == self.start) + + def __ne__(self, other): + return not self.__eq__(other) + + def __hash__(self): + return hash(self._session_id) + + def __str__(self): + return 'Spotify' + + def __repr__(self): + return ''.format(self) + + @property + def title(self): + """:class:`str`: The title of the song being played.""" + return self._details + + @property + def artists(self): + """List[:class:`str`]: The artists of the song being played.""" + return self._state.split('; ') + + @property + def artist(self): + """:class:`str`: The artist of the song being played. + + This does not attempt to split the artist information into + multiple artists. Useful if there's only a single artist. + """ + return self._state + + @property + def album(self): + """:class:`str`: The album that the song being played belongs to.""" + return self._assets.get('large_text', '') + + @property + def album_cover_url(self): + """:class:`str`: The album cover image URL from Spotify's CDN.""" + large_image = self._assets.get('large_image', '') + if large_image[:8] != 'spotify:': + return '' + album_image_id = large_image[8:] + return 'https://i.scdn.co/image/' + album_image_id + + @property + def track_id(self): + """:class:`str`: The track ID used by Spotify to identify this song.""" + return self._sync_id + + @property + def start(self): + """:class:`datetime.datetime`: When the user started playing this song in UTC.""" + return datetime.datetime.utcfromtimestamp(self._timestamps['start'] / 1000) + + @property + def end(self): + """:class:`datetime.datetime`: When the user will stop playing this song in UTC.""" + return datetime.datetime.utcfromtimestamp(self._timestamps['end'] / 1000) + + @property + def duration(self): + """:class:`datetime.timedelta`: The duration of the song being played.""" + return self.end - self.start + + @property + def party_id(self): + """:class:`str`: The party ID of the listening party.""" + return self._party.get('id', '') + +class CustomActivity(BaseActivity): + """Represents a Custom activity from Discord. + + .. container:: operations + + .. describe:: x == y + + Checks if two activities are equal. + + .. describe:: x != y + + Checks if two activities are not equal. + + .. describe:: hash(x) + + Returns the activity's hash. + + .. describe:: str(x) + + Returns the custom status text. + + .. versionadded:: 1.3 + + Attributes + ----------- + name: Optional[:class:`str`] + The custom activity's name. + emoji: Optional[:class:`PartialEmoji`] + The emoji to pass to the activity, if any. + """ + + __slots__ = ('name', 'emoji', 'state') + + def __init__(self, name, *, emoji=None, **extra): + super().__init__(**extra) + self.name = name + self.state = extra.pop('state', None) + if self.name == 'Custom Status': + self.name = self.state + + if emoji is None: + self.emoji = emoji + elif isinstance(emoji, dict): + self.emoji = PartialEmoji.from_dict(emoji) + elif isinstance(emoji, str): + self.emoji = PartialEmoji(name=emoji) + elif isinstance(emoji, PartialEmoji): + self.emoji = emoji + else: + raise TypeError('Expected str, PartialEmoji, or None, received {0!r} instead.'.format(type(emoji))) + + @property + def type(self): + """:class:`ActivityType`: Returns the activity's type. This is for compatibility with :class:`Activity`. + + It always returns :attr:`ActivityType.custom`. + """ + return ActivityType.custom + + def to_dict(self): + if self.name == self.state: + o = { + 'type': ActivityType.custom.value, + 'state': self.name, + 'name': 'Custom Status', + } + else: + o = { + 'type': ActivityType.custom.value, + 'name': self.name, + } + + if self.emoji: + o['emoji'] = self.emoji.to_dict() + return o + + def __eq__(self, other): + return (isinstance(other, CustomActivity) and other.name == self.name and other.emoji == self.emoji) + + def __ne__(self, other): + return not self.__eq__(other) + + def __hash__(self): + return hash((self.name, str(self.emoji))) + + def __str__(self): + if self.emoji: + if self.name: + return '%s %s' % (self.emoji, self.name) + return str(self.emoji) + else: + return str(self.name) + + def __repr__(self): + return ''.format(self) + + +def create_activity(data): + if not data: + return None + + game_type = try_enum(ActivityType, data.get('type', -1)) + if game_type is ActivityType.playing: + if 'application_id' in data or 'session_id' in data: + return Activity(**data) + return Game(**data) + elif game_type is ActivityType.custom: + try: + name = data.pop('name') + except KeyError: + return Activity(**data) + else: + return CustomActivity(name=name, **data) + elif game_type is ActivityType.streaming: + if 'url' in data: + return Streaming(**data) + return Activity(**data) + elif game_type is ActivityType.listening and 'sync_id' in data and 'session_id' in data: + return Spotify(**data) + return Activity(**data) diff --git a/venv/lib64/python3.8/site-packages/discord/appinfo.py b/venv/lib64/python3.8/site-packages/discord/appinfo.py new file mode 100644 index 0000000..cbc0056 --- /dev/null +++ b/venv/lib64/python3.8/site-packages/discord/appinfo.py @@ -0,0 +1,217 @@ +# -*- coding: utf-8 -*- + +""" +The MIT License (MIT) + +Copyright (c) 2015-present Rapptz + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. +""" + +from . import utils +from .user import User +from .asset import Asset +from .team import Team + + +class AppInfo: + """Represents the application info for the bot provided by Discord. + + + Attributes + ------------- + id: :class:`int` + The application ID. + name: :class:`str` + The application name. + owner: :class:`User` + The application owner. + team: Optional[:class:`Team`] + The application's team. + + .. versionadded:: 1.3 + + icon: Optional[:class:`str`] + The icon hash, if it exists. + description: Optional[:class:`str`] + The application description. + bot_public: :class:`bool` + Whether the bot can be invited by anyone or if it is locked + to the application owner. + bot_require_code_grant: :class:`bool` + Whether the bot requires the completion of the full oauth2 code + grant flow to join. + rpc_origins: Optional[List[:class:`str`]] + A list of RPC origin URLs, if RPC is enabled. + summary: :class:`str` + If this application is a game sold on Discord, + this field will be the summary field for the store page of its primary SKU. + + .. versionadded:: 1.3 + + verify_key: :class:`str` + The hex encoded key for verification in interactions and the + GameSDK's `GetTicket `_. + + .. versionadded:: 1.3 + + guild_id: Optional[:class:`int`] + If this application is a game sold on Discord, + this field will be the guild to which it has been linked to. + + .. versionadded:: 1.3 + + primary_sku_id: Optional[:class:`int`] + If this application is a game sold on Discord, + this field will be the id of the "Game SKU" that is created, + if it exists. + + .. versionadded:: 1.3 + + slug: Optional[:class:`str`] + If this application is a game sold on Discord, + this field will be the URL slug that links to the store page. + + .. versionadded:: 1.3 + + cover_image: Optional[:class:`str`] + If this application is a game sold on Discord, + this field will be the hash of the image on store embeds + + .. versionadded:: 1.3 + """ + __slots__ = ('_state', 'description', 'id', 'name', 'rpc_origins', + 'bot_public', 'bot_require_code_grant', 'owner', 'icon', + 'summary', 'verify_key', 'team', 'guild_id', 'primary_sku_id', + 'slug', 'cover_image') + + def __init__(self, state, data): + self._state = state + + self.id = int(data['id']) + self.name = data['name'] + self.description = data['description'] + self.icon = data['icon'] + self.rpc_origins = data['rpc_origins'] + self.bot_public = data['bot_public'] + self.bot_require_code_grant = data['bot_require_code_grant'] + self.owner = User(state=self._state, data=data['owner']) + + team = data.get('team') + self.team = Team(state, team) if team else None + + self.summary = data['summary'] + self.verify_key = data['verify_key'] + + self.guild_id = utils._get_as_snowflake(data, 'guild_id') + + self.primary_sku_id = utils._get_as_snowflake(data, 'primary_sku_id') + self.slug = data.get('slug') + self.cover_image = data.get('cover_image') + + def __repr__(self): + return '<{0.__class__.__name__} id={0.id} name={0.name!r} description={0.description!r} public={0.bot_public} ' \ + 'owner={0.owner!r}>'.format(self) + + @property + def icon_url(self): + """:class:`.Asset`: Retrieves the application's icon asset. + + This is equivalent to calling :meth:`icon_url_as` with + the default parameters ('webp' format and a size of 1024). + + .. versionadded:: 1.3 + """ + return self.icon_url_as() + + def icon_url_as(self, *, format='webp', size=1024): + """Returns an :class:`Asset` for the icon the application has. + + The format must be one of 'webp', 'jpeg', 'jpg' or 'png'. + The size must be a power of 2 between 16 and 4096. + + .. versionadded:: 1.6 + + Parameters + ----------- + format: :class:`str` + The format to attempt to convert the icon to. Defaults to 'webp'. + size: :class:`int` + The size of the image to display. + + Raises + ------ + InvalidArgument + Bad image format passed to ``format`` or invalid ``size``. + + Returns + -------- + :class:`Asset` + The resulting CDN asset. + """ + return Asset._from_icon(self._state, self, 'app', format=format, size=size) + + + @property + def cover_image_url(self): + """:class:`.Asset`: Retrieves the cover image on a store embed. + + This is equivalent to calling :meth:`cover_image_url_as` with + the default parameters ('webp' format and a size of 1024). + + .. versionadded:: 1.3 + """ + return self.cover_image_url_as() + + def cover_image_url_as(self, *, format='webp', size=1024): + """Returns an :class:`Asset` for the image on store embeds + if this application is a game sold on Discord. + + The format must be one of 'webp', 'jpeg', 'jpg' or 'png'. + The size must be a power of 2 between 16 and 4096. + + .. versionadded:: 1.6 + + Parameters + ----------- + format: :class:`str` + The format to attempt to convert the image to. Defaults to 'webp'. + size: :class:`int` + The size of the image to display. + + Raises + ------ + InvalidArgument + Bad image format passed to ``format`` or invalid ``size``. + + Returns + -------- + :class:`Asset` + The resulting CDN asset. + """ + return Asset._from_cover_image(self._state, self, format=format, size=size) + + @property + def guild(self): + """Optional[:class:`Guild`]: If this application is a game sold on Discord, + this field will be the guild to which it has been linked + + .. versionadded:: 1.3 + """ + return self._state._get_guild(int(self.guild_id)) diff --git a/venv/lib64/python3.8/site-packages/discord/asset.py b/venv/lib64/python3.8/site-packages/discord/asset.py new file mode 100644 index 0000000..ea45729 --- /dev/null +++ b/venv/lib64/python3.8/site-packages/discord/asset.py @@ -0,0 +1,262 @@ +# -*- coding: utf-8 -*- + +""" +The MIT License (MIT) + +Copyright (c) 2015-present Rapptz + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. +""" + +import io +from .errors import DiscordException +from .errors import InvalidArgument +from . import utils + +VALID_STATIC_FORMATS = frozenset({"jpeg", "jpg", "webp", "png"}) +VALID_AVATAR_FORMATS = VALID_STATIC_FORMATS | {"gif"} + +class Asset: + """Represents a CDN asset on Discord. + + .. container:: operations + + .. describe:: str(x) + + Returns the URL of the CDN asset. + + .. describe:: len(x) + + Returns the length of the CDN asset's URL. + + .. describe:: bool(x) + + Checks if the Asset has a URL. + + .. describe:: x == y + + Checks if the asset is equal to another asset. + + .. describe:: x != y + + Checks if the asset is not equal to another asset. + + .. describe:: hash(x) + + Returns the hash of the asset. + """ + __slots__ = ('_state', '_url') + + BASE = 'https://cdn.discordapp.com' + + def __init__(self, state, url=None): + self._state = state + self._url = url + + @classmethod + def _from_avatar(cls, state, user, *, format=None, static_format='webp', size=1024): + if not utils.valid_icon_size(size): + raise InvalidArgument("size must be a power of 2 between 16 and 4096") + if format is not None and format not in VALID_AVATAR_FORMATS: + raise InvalidArgument("format must be None or one of {}".format(VALID_AVATAR_FORMATS)) + if format == "gif" and not user.is_avatar_animated(): + raise InvalidArgument("non animated avatars do not support gif format") + if static_format not in VALID_STATIC_FORMATS: + raise InvalidArgument("static_format must be one of {}".format(VALID_STATIC_FORMATS)) + + if user.avatar is None: + return user.default_avatar_url + + if format is None: + format = 'gif' if user.is_avatar_animated() else static_format + + return cls(state, '/avatars/{0.id}/{0.avatar}.{1}?size={2}'.format(user, format, size)) + + @classmethod + def _from_icon(cls, state, object, path, *, format='webp', size=1024): + if object.icon is None: + return cls(state) + + if not utils.valid_icon_size(size): + raise InvalidArgument("size must be a power of 2 between 16 and 4096") + if format not in VALID_STATIC_FORMATS: + raise InvalidArgument("format must be None or one of {}".format(VALID_STATIC_FORMATS)) + + url = '/{0}-icons/{1.id}/{1.icon}.{2}?size={3}'.format(path, object, format, size) + return cls(state, url) + + @classmethod + def _from_cover_image(cls, state, obj, *, format='webp', size=1024): + if obj.cover_image is None: + return cls(state) + + if not utils.valid_icon_size(size): + raise InvalidArgument("size must be a power of 2 between 16 and 4096") + if format not in VALID_STATIC_FORMATS: + raise InvalidArgument("format must be None or one of {}".format(VALID_STATIC_FORMATS)) + + url = '/app-assets/{0.id}/store/{0.cover_image}.{1}?size={2}'.format(obj, format, size) + return cls(state, url) + + @classmethod + def _from_guild_image(cls, state, id, hash, key, *, format='webp', size=1024): + if not utils.valid_icon_size(size): + raise InvalidArgument("size must be a power of 2 between 16 and 4096") + if format not in VALID_STATIC_FORMATS: + raise InvalidArgument("format must be one of {}".format(VALID_STATIC_FORMATS)) + + if hash is None: + return cls(state) + + url = '/{key}/{0}/{1}.{2}?size={3}' + return cls(state, url.format(id, hash, format, size, key=key)) + + @classmethod + def _from_guild_icon(cls, state, guild, *, format=None, static_format='webp', size=1024): + if not utils.valid_icon_size(size): + raise InvalidArgument("size must be a power of 2 between 16 and 4096") + if format is not None and format not in VALID_AVATAR_FORMATS: + raise InvalidArgument("format must be one of {}".format(VALID_AVATAR_FORMATS)) + if format == "gif" and not guild.is_icon_animated(): + raise InvalidArgument("non animated guild icons do not support gif format") + if static_format not in VALID_STATIC_FORMATS: + raise InvalidArgument("static_format must be one of {}".format(VALID_STATIC_FORMATS)) + + if guild.icon is None: + return cls(state) + + if format is None: + format = 'gif' if guild.is_icon_animated() else static_format + + return cls(state, '/icons/{0.id}/{0.icon}.{1}?size={2}'.format(guild, format, size)) + + @classmethod + def _from_sticker_url(cls, state, sticker, *, size=1024): + if not utils.valid_icon_size(size): + raise InvalidArgument("size must be a power of 2 between 16 and 4096") + + return cls(state, '/stickers/{0.id}/{0.image}.png?size={2}'.format(sticker, format, size)) + + @classmethod + def _from_emoji(cls, state, emoji, *, format=None, static_format='png'): + if format is not None and format not in VALID_AVATAR_FORMATS: + raise InvalidArgument("format must be None or one of {}".format(VALID_AVATAR_FORMATS)) + if format == "gif" and not emoji.animated: + raise InvalidArgument("non animated emoji's do not support gif format") + if static_format not in VALID_STATIC_FORMATS: + raise InvalidArgument("static_format must be one of {}".format(VALID_STATIC_FORMATS)) + if format is None: + format = 'gif' if emoji.animated else static_format + + return cls(state, '/emojis/{0.id}.{1}'.format(emoji, format)) + + def __str__(self): + return self.BASE + self._url if self._url is not None else '' + + def __len__(self): + if self._url: + return len(self.BASE + self._url) + return 0 + + def __bool__(self): + return self._url is not None + + def __repr__(self): + return ''.format(self) + + def __eq__(self, other): + return isinstance(other, Asset) and self._url == other._url + + def __ne__(self, other): + return not self.__eq__(other) + + def __hash__(self): + return hash(self._url) + + async def read(self): + """|coro| + + Retrieves the content of this asset as a :class:`bytes` object. + + .. warning:: + + :class:`PartialEmoji` won't have a connection state if user created, + and a URL won't be present if a custom image isn't associated with + the asset, e.g. a guild with no custom icon. + + .. versionadded:: 1.1 + + Raises + ------ + DiscordException + There was no valid URL or internal connection state. + HTTPException + Downloading the asset failed. + NotFound + The asset was deleted. + + Returns + ------- + :class:`bytes` + The content of the asset. + """ + if not self._url: + raise DiscordException('Invalid asset (no URL provided)') + + if self._state is None: + raise DiscordException('Invalid state (no ConnectionState provided)') + + return await self._state.http.get_from_cdn(self.BASE + self._url) + + async def save(self, fp, *, seek_begin=True): + """|coro| + + Saves this asset into a file-like object. + + Parameters + ---------- + fp: Union[BinaryIO, :class:`os.PathLike`] + Same as in :meth:`Attachment.save`. + seek_begin: :class:`bool` + Same as in :meth:`Attachment.save`. + + Raises + ------ + DiscordException + There was no valid URL or internal connection state. + HTTPException + Downloading the asset failed. + NotFound + The asset was deleted. + + Returns + -------- + :class:`int` + The number of bytes written. + """ + + data = await self.read() + if isinstance(fp, io.IOBase) and fp.writable(): + written = fp.write(data) + if seek_begin: + fp.seek(0) + return written + else: + with open(fp, 'wb') as f: + return f.write(data) diff --git a/venv/lib64/python3.8/site-packages/discord/audit_logs.py b/venv/lib64/python3.8/site-packages/discord/audit_logs.py new file mode 100644 index 0000000..7d70a93 --- /dev/null +++ b/venv/lib64/python3.8/site-packages/discord/audit_logs.py @@ -0,0 +1,382 @@ +# -*- coding: utf-8 -*- + +""" +The MIT License (MIT) + +Copyright (c) 2015-present Rapptz + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. +""" + +from . import utils, enums +from .object import Object +from .permissions import PermissionOverwrite, Permissions +from .colour import Colour +from .invite import Invite +from .mixins import Hashable + +def _transform_verification_level(entry, data): + return enums.try_enum(enums.VerificationLevel, data) + +def _transform_default_notifications(entry, data): + return enums.try_enum(enums.NotificationLevel, data) + +def _transform_explicit_content_filter(entry, data): + return enums.try_enum(enums.ContentFilter, data) + +def _transform_permissions(entry, data): + return Permissions(data) + +def _transform_color(entry, data): + return Colour(data) + +def _transform_snowflake(entry, data): + return int(data) + +def _transform_channel(entry, data): + if data is None: + return None + return entry.guild.get_channel(int(data)) or Object(id=data) + +def _transform_owner_id(entry, data): + if data is None: + return None + return entry._get_member(int(data)) + +def _transform_inviter_id(entry, data): + if data is None: + return None + return entry._get_member(int(data)) + +def _transform_overwrites(entry, data): + overwrites = [] + for elem in data: + allow = Permissions(elem['allow']) + deny = Permissions(elem['deny']) + ow = PermissionOverwrite.from_pair(allow, deny) + + ow_type = elem['type'] + ow_id = int(elem['id']) + if ow_type == 'role': + target = entry.guild.get_role(ow_id) + else: + target = entry._get_member(ow_id) + + if target is None: + target = Object(id=ow_id) + + overwrites.append((target, ow)) + + return overwrites + +class AuditLogDiff: + def __len__(self): + return len(self.__dict__) + + def __iter__(self): + return iter(self.__dict__.items()) + + def __repr__(self): + values = ' '.join('%s=%r' % item for item in self.__dict__.items()) + return '' % values + +class AuditLogChanges: + TRANSFORMERS = { + 'verification_level': (None, _transform_verification_level), + 'explicit_content_filter': (None, _transform_explicit_content_filter), + 'allow': (None, _transform_permissions), + 'deny': (None, _transform_permissions), + 'permissions': (None, _transform_permissions), + 'id': (None, _transform_snowflake), + 'color': ('colour', _transform_color), + 'owner_id': ('owner', _transform_owner_id), + 'inviter_id': ('inviter', _transform_inviter_id), + 'channel_id': ('channel', _transform_channel), + 'afk_channel_id': ('afk_channel', _transform_channel), + 'system_channel_id': ('system_channel', _transform_channel), + 'widget_channel_id': ('widget_channel', _transform_channel), + 'permission_overwrites': ('overwrites', _transform_overwrites), + 'splash_hash': ('splash', None), + 'icon_hash': ('icon', None), + 'avatar_hash': ('avatar', None), + 'rate_limit_per_user': ('slowmode_delay', None), + 'default_message_notifications': ('default_notifications', _transform_default_notifications), + } + + def __init__(self, entry, data): + self.before = AuditLogDiff() + self.after = AuditLogDiff() + + for elem in data: + attr = elem['key'] + + # special cases for role add/remove + if attr == '$add': + self._handle_role(self.before, self.after, entry, elem['new_value']) + continue + elif attr == '$remove': + self._handle_role(self.after, self.before, entry, elem['new_value']) + continue + + transformer = self.TRANSFORMERS.get(attr) + if transformer: + key, transformer = transformer + if key: + attr = key + + try: + before = elem['old_value'] + except KeyError: + before = None + else: + if transformer: + before = transformer(entry, before) + + setattr(self.before, attr, before) + + try: + after = elem['new_value'] + except KeyError: + after = None + else: + if transformer: + after = transformer(entry, after) + + setattr(self.after, attr, after) + + # add an alias + if hasattr(self.after, 'colour'): + self.after.color = self.after.colour + self.before.color = self.before.colour + + def __repr__(self): + return '' % (self.before, self.after) + + def _handle_role(self, first, second, entry, elem): + if not hasattr(first, 'roles'): + setattr(first, 'roles', []) + + data = [] + g = entry.guild + + for e in elem: + role_id = int(e['id']) + role = g.get_role(role_id) + + if role is None: + role = Object(id=role_id) + role.name = e['name'] + + data.append(role) + + setattr(second, 'roles', data) + +class AuditLogEntry(Hashable): + r"""Represents an Audit Log entry. + + You retrieve these via :meth:`Guild.audit_logs`. + + .. container:: operations + + .. describe:: x == y + + Checks if two entries are equal. + + .. describe:: x != y + + Checks if two entries are not equal. + + .. describe:: hash(x) + + Returns the entry's hash. + + .. versionchanged:: 1.7 + Audit log entries are now comparable and hashable. + + Attributes + ----------- + action: :class:`AuditLogAction` + The action that was done. + user: :class:`abc.User` + The user who initiated this action. Usually a :class:`Member`\, unless gone + then it's a :class:`User`. + id: :class:`int` + The entry ID. + target: Any + The target that got changed. The exact type of this depends on + the action being done. + reason: Optional[:class:`str`] + The reason this action was done. + extra: Any + Extra information that this entry has that might be useful. + For most actions, this is ``None``. However in some cases it + contains extra information. See :class:`AuditLogAction` for + which actions have this field filled out. + """ + + def __init__(self, *, users, data, guild): + self._state = guild._state + self.guild = guild + self._users = users + self._from_data(data) + + def _from_data(self, data): + self.action = enums.try_enum(enums.AuditLogAction, data['action_type']) + self.id = int(data['id']) + + # this key is technically not usually present + self.reason = data.get('reason') + self.extra = data.get('options') + + if isinstance(self.action, enums.AuditLogAction) and self.extra: + if self.action is enums.AuditLogAction.member_prune: + # member prune has two keys with useful information + self.extra = type('_AuditLogProxy', (), {k: int(v) for k, v in self.extra.items()})() + elif self.action is enums.AuditLogAction.member_move or self.action is enums.AuditLogAction.message_delete: + channel_id = int(self.extra['channel_id']) + elems = { + 'count': int(self.extra['count']), + 'channel': self.guild.get_channel(channel_id) or Object(id=channel_id) + } + self.extra = type('_AuditLogProxy', (), elems)() + elif self.action is enums.AuditLogAction.member_disconnect: + # The member disconnect action has a dict with some information + elems = { + 'count': int(self.extra['count']), + } + self.extra = type('_AuditLogProxy', (), elems)() + elif self.action.name.endswith('pin'): + # the pin actions have a dict with some information + channel_id = int(self.extra['channel_id']) + message_id = int(self.extra['message_id']) + elems = { + 'channel': self.guild.get_channel(channel_id) or Object(id=channel_id), + 'message_id': message_id + } + self.extra = type('_AuditLogProxy', (), elems)() + elif self.action.name.startswith('overwrite_'): + # the overwrite_ actions have a dict with some information + instance_id = int(self.extra['id']) + the_type = self.extra.get('type') + if the_type == 'member': + self.extra = self._get_member(instance_id) + else: + role = self.guild.get_role(instance_id) + if role is None: + role = Object(id=instance_id) + role.name = self.extra.get('role_name') + self.extra = role + + # this key is not present when the above is present, typically. + # It's a list of { new_value: a, old_value: b, key: c } + # where new_value and old_value are not guaranteed to be there depending + # on the action type, so let's just fetch it for now and only turn it + # into meaningful data when requested + self._changes = data.get('changes', []) + + self.user = self._get_member(utils._get_as_snowflake(data, 'user_id')) + self._target_id = utils._get_as_snowflake(data, 'target_id') + + def _get_member(self, user_id): + return self.guild.get_member(user_id) or self._users.get(user_id) + + def __repr__(self): + return ''.format(self) + + @utils.cached_property + def created_at(self): + """:class:`datetime.datetime`: Returns the entry's creation time in UTC.""" + return utils.snowflake_time(self.id) + + @utils.cached_property + def target(self): + try: + converter = getattr(self, '_convert_target_' + self.action.target_type) + except AttributeError: + return Object(id=self._target_id) + else: + return converter(self._target_id) + + @utils.cached_property + def category(self): + """Optional[:class:`AuditLogActionCategory`]: The category of the action, if applicable.""" + return self.action.category + + @utils.cached_property + def changes(self): + """:class:`AuditLogChanges`: The list of changes this entry has.""" + obj = AuditLogChanges(self, self._changes) + del self._changes + return obj + + @utils.cached_property + def before(self): + """:class:`AuditLogDiff`: The target's prior state.""" + return self.changes.before + + @utils.cached_property + def after(self): + """:class:`AuditLogDiff`: The target's subsequent state.""" + return self.changes.after + + def _convert_target_guild(self, target_id): + return self.guild + + def _convert_target_channel(self, target_id): + ch = self.guild.get_channel(target_id) + if ch is None: + return Object(id=target_id) + return ch + + def _convert_target_user(self, target_id): + return self._get_member(target_id) + + def _convert_target_role(self, target_id): + role = self.guild.get_role(target_id) + if role is None: + return Object(id=target_id) + return role + + def _convert_target_invite(self, target_id): + # invites have target_id set to null + # so figure out which change has the full invite data + changeset = self.before if self.action is enums.AuditLogAction.invite_delete else self.after + + fake_payload = { + 'max_age': changeset.max_age, + 'max_uses': changeset.max_uses, + 'code': changeset.code, + 'temporary': changeset.temporary, + 'channel': changeset.channel, + 'uses': changeset.uses, + 'guild': self.guild, + } + + obj = Invite(state=self._state, data=fake_payload) + try: + obj.inviter = changeset.inviter + except AttributeError: + pass + return obj + + def _convert_target_emoji(self, target_id): + return self._state.get_emoji(target_id) or Object(id=target_id) + + def _convert_target_message(self, target_id): + return self._get_member(target_id) diff --git a/venv/lib64/python3.8/site-packages/discord/backoff.py b/venv/lib64/python3.8/site-packages/discord/backoff.py new file mode 100644 index 0000000..0f49d15 --- /dev/null +++ b/venv/lib64/python3.8/site-packages/discord/backoff.py @@ -0,0 +1,85 @@ +# -*- coding: utf-8 -*- + +""" +The MIT License (MIT) + +Copyright (c) 2015-present Rapptz + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. +""" + +import time +import random + +class ExponentialBackoff: + """An implementation of the exponential backoff algorithm + + Provides a convenient interface to implement an exponential backoff + for reconnecting or retrying transmissions in a distributed network. + + Once instantiated, the delay method will return the next interval to + wait for when retrying a connection or transmission. The maximum + delay increases exponentially with each retry up to a maximum of + 2^10 * base, and is reset if no more attempts are needed in a period + of 2^11 * base seconds. + + Parameters + ---------- + base: :class:`int` + The base delay in seconds. The first retry-delay will be up to + this many seconds. + integral: :class:`bool` + Set to ``True`` if whole periods of base is desirable, otherwise any + number in between may be returned. + """ + + def __init__(self, base=1, *, integral=False): + self._base = base + + self._exp = 0 + self._max = 10 + self._reset_time = base * 2 ** 11 + self._last_invocation = time.monotonic() + + # Use our own random instance to avoid messing with global one + rand = random.Random() + rand.seed() + + self._randfunc = rand.randrange if integral else rand.uniform + + def delay(self): + """Compute the next delay + + Returns the next delay to wait according to the exponential + backoff algorithm. This is a value between 0 and base * 2^exp + where exponent starts off at 1 and is incremented at every + invocation of this method up to a maximum of 10. + + If a period of more than base * 2^11 has passed since the last + retry, the exponent is reset to 1. + """ + invocation = time.monotonic() + interval = invocation - self._last_invocation + self._last_invocation = invocation + + if interval > self._reset_time: + self._exp = 0 + + self._exp = min(self._exp + 1, self._max) + return self._randfunc(0, self._base * 2 ** self._exp) diff --git a/venv/lib64/python3.8/site-packages/discord/calls.py b/venv/lib64/python3.8/site-packages/discord/calls.py new file mode 100644 index 0000000..2006b30 --- /dev/null +++ b/venv/lib64/python3.8/site-packages/discord/calls.py @@ -0,0 +1,176 @@ +# -*- coding: utf-8 -*- + +""" +The MIT License (MIT) + +Copyright (c) 2015-present Rapptz + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. +""" + +import datetime + +from . import utils +from .enums import VoiceRegion, try_enum +from .member import VoiceState + +class CallMessage: + """Represents a group call message from Discord. + + This is only received in cases where the message type is equivalent to + :attr:`MessageType.call`. + + .. deprecated:: 1.7 + + Attributes + ----------- + ended_timestamp: Optional[:class:`datetime.datetime`] + A naive UTC datetime object that represents the time that the call has ended. + participants: List[:class:`User`] + The list of users that are participating in this call. + message: :class:`Message` + The message associated with this call message. + """ + + def __init__(self, message, **kwargs): + self.message = message + self.ended_timestamp = utils.parse_time(kwargs.get('ended_timestamp')) + self.participants = kwargs.get('participants') + + @property + def call_ended(self): + """:class:`bool`: Indicates if the call has ended. + + .. deprecated:: 1.7 + """ + return self.ended_timestamp is not None + + @property + def channel(self): + r""":class:`GroupChannel`\: The private channel associated with this message. + + .. deprecated:: 1.7 + """ + return self.message.channel + + @property + def duration(self): + """Queries the duration of the call. + + If the call has not ended then the current duration will + be returned. + + .. deprecated:: 1.7 + + Returns + --------- + :class:`datetime.timedelta` + The timedelta object representing the duration. + """ + if self.ended_timestamp is None: + return datetime.datetime.utcnow() - self.message.created_at + else: + return self.ended_timestamp - self.message.created_at + +class GroupCall: + """Represents the actual group call from Discord. + + This is accompanied with a :class:`CallMessage` denoting the information. + + .. deprecated:: 1.7 + + Attributes + ----------- + call: :class:`CallMessage` + The call message associated with this group call. + unavailable: :class:`bool` + Denotes if this group call is unavailable. + ringing: List[:class:`User`] + A list of users that are currently being rung to join the call. + region: :class:`VoiceRegion` + The guild region the group call is being hosted on. + """ + + def __init__(self, **kwargs): + self.call = kwargs.get('call') + self.unavailable = kwargs.get('unavailable') + self._voice_states = {} + + for state in kwargs.get('voice_states', []): + self._update_voice_state(state) + + self._update(**kwargs) + + def _update(self, **kwargs): + self.region = try_enum(VoiceRegion, kwargs.get('region')) + lookup = {u.id: u for u in self.call.channel.recipients} + me = self.call.channel.me + lookup[me.id] = me + self.ringing = list(filter(None, map(lookup.get, kwargs.get('ringing', [])))) + + def _update_voice_state(self, data): + user_id = int(data['user_id']) + # left the voice channel? + if data['channel_id'] is None: + self._voice_states.pop(user_id, None) + else: + self._voice_states[user_id] = VoiceState(data=data, channel=self.channel) + + @property + def connected(self): + """List[:class:`User`]: A property that returns all users that are currently in this call. + + .. deprecated:: 1.7 + """ + ret = [u for u in self.channel.recipients if self.voice_state_for(u) is not None] + me = self.channel.me + if self.voice_state_for(me) is not None: + ret.append(me) + + return ret + + @property + def channel(self): + r""":class:`GroupChannel`\: Returns the channel the group call is in. + + .. deprecated:: 1.7 + """ + return self.call.channel + + @utils.deprecated() + def voice_state_for(self, user): + """Retrieves the :class:`VoiceState` for a specified :class:`User`. + + If the :class:`User` has no voice state then this function returns + ``None``. + + .. deprecated:: 1.7 + + Parameters + ------------ + user: :class:`User` + The user to retrieve the voice state for. + + Returns + -------- + Optional[:class:`VoiceState`] + The voice state associated with this user. + """ + + return self._voice_states.get(user.id) diff --git a/venv/lib64/python3.8/site-packages/discord/channel.py b/venv/lib64/python3.8/site-packages/discord/channel.py new file mode 100644 index 0000000..3510b80 --- /dev/null +++ b/venv/lib64/python3.8/site-packages/discord/channel.py @@ -0,0 +1,1569 @@ +# -*- coding: utf-8 -*- + +""" +The MIT License (MIT) + +Copyright (c) 2015-present Rapptz + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. +""" + +import time +import asyncio + +import discord.abc +from .permissions import Permissions +from .enums import ChannelType, try_enum, VoiceRegion +from .mixins import Hashable +from . import utils +from .asset import Asset +from .errors import ClientException, NoMoreItems, InvalidArgument + +__all__ = ( + 'TextChannel', + 'VoiceChannel', + 'StageChannel', + 'DMChannel', + 'CategoryChannel', + 'StoreChannel', + 'GroupChannel', + '_channel_factory', +) + +async def _single_delete_strategy(messages): + for m in messages: + await m.delete() + +class TextChannel(discord.abc.Messageable, discord.abc.GuildChannel, Hashable): + """Represents a Discord guild text channel. + + .. container:: operations + + .. describe:: x == y + + Checks if two channels are equal. + + .. describe:: x != y + + Checks if two channels are not equal. + + .. describe:: hash(x) + + Returns the channel's hash. + + .. describe:: str(x) + + Returns the channel's name. + + Attributes + ----------- + name: :class:`str` + The channel name. + guild: :class:`Guild` + The guild the channel belongs to. + id: :class:`int` + The channel ID. + category_id: Optional[:class:`int`] + The category channel ID this channel belongs to, if applicable. + topic: Optional[:class:`str`] + The channel's topic. ``None`` if it doesn't exist. + position: :class:`int` + The position in the channel list. This is a number that starts at 0. e.g. the + top channel is position 0. + last_message_id: Optional[:class:`int`] + The last message ID of the message sent to this channel. It may + *not* point to an existing or valid message. + slowmode_delay: :class:`int` + The number of seconds a member must wait between sending messages + in this channel. A value of `0` denotes that it is disabled. + Bots and users with :attr:`~Permissions.manage_channels` or + :attr:`~Permissions.manage_messages` bypass slowmode. + """ + + __slots__ = ('name', 'id', 'guild', 'topic', '_state', 'nsfw', + 'category_id', 'position', 'slowmode_delay', '_overwrites', + '_type', 'last_message_id') + + def __init__(self, *, state, guild, data): + self._state = state + self.id = int(data['id']) + self._type = data['type'] + self._update(guild, data) + + def __repr__(self): + attrs = [ + ('id', self.id), + ('name', self.name), + ('position', self.position), + ('nsfw', self.nsfw), + ('news', self.is_news()), + ('category_id', self.category_id) + ] + return '<%s %s>' % (self.__class__.__name__, ' '.join('%s=%r' % t for t in attrs)) + + def _update(self, guild, data): + self.guild = guild + self.name = data['name'] + self.category_id = utils._get_as_snowflake(data, 'parent_id') + self.topic = data.get('topic') + self.position = data['position'] + self.nsfw = data.get('nsfw', False) + # Does this need coercion into `int`? No idea yet. + self.slowmode_delay = data.get('rate_limit_per_user', 0) + self._type = data.get('type', self._type) + self.last_message_id = utils._get_as_snowflake(data, 'last_message_id') + self._fill_overwrites(data) + + async def _get_channel(self): + return self + + @property + def type(self): + """:class:`ChannelType`: The channel's Discord type.""" + return try_enum(ChannelType, self._type) + + @property + def _sorting_bucket(self): + return ChannelType.text.value + + @utils.copy_doc(discord.abc.GuildChannel.permissions_for) + def permissions_for(self, member): + base = super().permissions_for(member) + + # text channels do not have voice related permissions + denied = Permissions.voice() + base.value &= ~denied.value + return base + + @property + def members(self): + """List[:class:`Member`]: Returns all members that can see this channel.""" + return [m for m in self.guild.members if self.permissions_for(m).read_messages] + + def is_nsfw(self): + """:class:`bool`: Checks if the channel is NSFW.""" + return self.nsfw + + def is_news(self): + """:class:`bool`: Checks if the channel is a news channel.""" + return self._type == ChannelType.news.value + + @property + def last_message(self): + """Fetches the last message from this channel in cache. + + The message might not be valid or point to an existing message. + + .. admonition:: Reliable Fetching + :class: helpful + + For a slightly more reliable method of fetching the + last message, consider using either :meth:`history` + or :meth:`fetch_message` with the :attr:`last_message_id` + attribute. + + Returns + --------- + Optional[:class:`Message`] + The last message in this channel or ``None`` if not found. + """ + return self._state._get_message(self.last_message_id) if self.last_message_id else None + + async def edit(self, *, reason=None, **options): + """|coro| + + Edits the channel. + + You must have the :attr:`~Permissions.manage_channels` permission to + use this. + + .. versionchanged:: 1.3 + The ``overwrites`` keyword-only parameter was added. + + .. versionchanged:: 1.4 + The ``type`` keyword-only parameter was added. + + Parameters + ---------- + name: :class:`str` + The new channel name. + topic: :class:`str` + The new channel's topic. + position: :class:`int` + The new channel's position. + nsfw: :class:`bool` + To mark the channel as NSFW or not. + sync_permissions: :class:`bool` + Whether to sync permissions with the channel's new or pre-existing + category. Defaults to ``False``. + category: Optional[:class:`CategoryChannel`] + The new category for this channel. Can be ``None`` to remove the + category. + slowmode_delay: :class:`int` + Specifies the slowmode rate limit for user in this channel, in seconds. + A value of `0` disables slowmode. The maximum value possible is `21600`. + type: :class:`ChannelType` + Change the type of this text channel. Currently, only conversion between + :attr:`ChannelType.text` and :attr:`ChannelType.news` is supported. This + is only available to guilds that contain ``NEWS`` in :attr:`Guild.features`. + reason: Optional[:class:`str`] + The reason for editing this channel. Shows up on the audit log. + overwrites: :class:`dict` + A :class:`dict` of target (either a role or a member) to + :class:`PermissionOverwrite` to apply to the channel. + + Raises + ------ + InvalidArgument + If position is less than 0 or greater than the number of channels, or if + the permission overwrite information is not in proper form. + Forbidden + You do not have permissions to edit the channel. + HTTPException + Editing the channel failed. + """ + await self._edit(options, reason=reason) + + @utils.copy_doc(discord.abc.GuildChannel.clone) + async def clone(self, *, name=None, reason=None): + return await self._clone_impl({ + 'topic': self.topic, + 'nsfw': self.nsfw, + 'rate_limit_per_user': self.slowmode_delay + }, name=name, reason=reason) + + async def delete_messages(self, messages): + """|coro| + + Deletes a list of messages. This is similar to :meth:`Message.delete` + except it bulk deletes multiple messages. + + As a special case, if the number of messages is 0, then nothing + is done. If the number of messages is 1 then single message + delete is done. If it's more than two, then bulk delete is used. + + You cannot bulk delete more than 100 messages or messages that + are older than 14 days old. + + You must have the :attr:`~Permissions.manage_messages` permission to + use this. + + Usable only by bot accounts. + + Parameters + ----------- + messages: Iterable[:class:`abc.Snowflake`] + An iterable of messages denoting which ones to bulk delete. + + Raises + ------ + ClientException + The number of messages to delete was more than 100. + Forbidden + You do not have proper permissions to delete the messages or + you're not using a bot account. + NotFound + If single delete, then the message was already deleted. + HTTPException + Deleting the messages failed. + """ + if not isinstance(messages, (list, tuple)): + messages = list(messages) + + if len(messages) == 0: + return # do nothing + + if len(messages) == 1: + message_id = messages[0].id + await self._state.http.delete_message(self.id, message_id) + return + + if len(messages) > 100: + raise ClientException('Can only bulk delete messages up to 100 messages') + + message_ids = [m.id for m in messages] + await self._state.http.delete_messages(self.id, message_ids) + + async def purge(self, *, limit=100, check=None, before=None, after=None, around=None, oldest_first=False, bulk=True): + """|coro| + + Purges a list of messages that meet the criteria given by the predicate + ``check``. If a ``check`` is not provided then all messages are deleted + without discrimination. + + You must have the :attr:`~Permissions.manage_messages` permission to + delete messages even if they are your own (unless you are a user + account). The :attr:`~Permissions.read_message_history` permission is + also needed to retrieve message history. + + Internally, this employs a different number of strategies depending + on the conditions met such as if a bulk delete is possible or if + the account is a user bot or not. + + Examples + --------- + + Deleting bot's messages :: + + def is_me(m): + return m.author == client.user + + deleted = await channel.purge(limit=100, check=is_me) + await channel.send('Deleted {} message(s)'.format(len(deleted))) + + Parameters + ----------- + limit: Optional[:class:`int`] + The number of messages to search through. This is not the number + of messages that will be deleted, though it can be. + check: Callable[[:class:`Message`], :class:`bool`] + The function used to check if a message should be deleted. + It must take a :class:`Message` as its sole parameter. + before: Optional[Union[:class:`abc.Snowflake`, :class:`datetime.datetime`]] + Same as ``before`` in :meth:`history`. + after: Optional[Union[:class:`abc.Snowflake`, :class:`datetime.datetime`]] + Same as ``after`` in :meth:`history`. + around: Optional[Union[:class:`abc.Snowflake`, :class:`datetime.datetime`]] + Same as ``around`` in :meth:`history`. + oldest_first: Optional[:class:`bool`] + Same as ``oldest_first`` in :meth:`history`. + bulk: :class:`bool` + If ``True``, use bulk delete. Setting this to ``False`` is useful for mass-deleting + a bot's own messages without :attr:`Permissions.manage_messages`. When ``True``, will + fall back to single delete if current account is a user bot (now deprecated), or if messages are + older than two weeks. + + Raises + ------- + Forbidden + You do not have proper permissions to do the actions required. + HTTPException + Purging the messages failed. + + Returns + -------- + List[:class:`.Message`] + The list of messages that were deleted. + """ + + if check is None: + check = lambda m: True + + iterator = self.history(limit=limit, before=before, after=after, oldest_first=oldest_first, around=around) + ret = [] + count = 0 + + minimum_time = int((time.time() - 14 * 24 * 60 * 60) * 1000.0 - 1420070400000) << 22 + strategy = self.delete_messages if self._state.is_bot and bulk else _single_delete_strategy + + while True: + try: + msg = await iterator.next() + except NoMoreItems: + # no more messages to poll + if count >= 2: + # more than 2 messages -> bulk delete + to_delete = ret[-count:] + await strategy(to_delete) + elif count == 1: + # delete a single message + await ret[-1].delete() + + return ret + else: + if count == 100: + # we've reached a full 'queue' + to_delete = ret[-100:] + await strategy(to_delete) + count = 0 + await asyncio.sleep(1) + + if check(msg): + if msg.id < minimum_time: + # older than 14 days old + if count == 1: + await ret[-1].delete() + elif count >= 2: + to_delete = ret[-count:] + await strategy(to_delete) + + count = 0 + strategy = _single_delete_strategy + + count += 1 + ret.append(msg) + + async def webhooks(self): + """|coro| + + Gets the list of webhooks from this channel. + + Requires :attr:`~.Permissions.manage_webhooks` permissions. + + Raises + ------- + Forbidden + You don't have permissions to get the webhooks. + + Returns + -------- + List[:class:`Webhook`] + The webhooks for this channel. + """ + + from .webhook import Webhook + data = await self._state.http.channel_webhooks(self.id) + return [Webhook.from_state(d, state=self._state) for d in data] + + async def create_webhook(self, *, name, avatar=None, reason=None): + """|coro| + + Creates a webhook for this channel. + + Requires :attr:`~.Permissions.manage_webhooks` permissions. + + .. versionchanged:: 1.1 + Added the ``reason`` keyword-only parameter. + + Parameters + ------------- + name: :class:`str` + The webhook's name. + avatar: Optional[:class:`bytes`] + A :term:`py:bytes-like object` representing the webhook's default avatar. + This operates similarly to :meth:`~ClientUser.edit`. + reason: Optional[:class:`str`] + The reason for creating this webhook. Shows up in the audit logs. + + Raises + ------- + HTTPException + Creating the webhook failed. + Forbidden + You do not have permissions to create a webhook. + + Returns + -------- + :class:`Webhook` + The created webhook. + """ + + from .webhook import Webhook + if avatar is not None: + avatar = utils._bytes_to_base64_data(avatar) + + data = await self._state.http.create_webhook(self.id, name=str(name), avatar=avatar, reason=reason) + return Webhook.from_state(data, state=self._state) + + async def follow(self, *, destination, reason=None): + """ + Follows a channel using a webhook. + + Only news channels can be followed. + + .. note:: + + The webhook returned will not provide a token to do webhook + actions, as Discord does not provide it. + + .. versionadded:: 1.3 + + Parameters + ----------- + destination: :class:`TextChannel` + The channel you would like to follow from. + reason: Optional[:class:`str`] + The reason for following the channel. Shows up on the destination guild's audit log. + + .. versionadded:: 1.4 + + Raises + ------- + HTTPException + Following the channel failed. + Forbidden + You do not have the permissions to create a webhook. + + Returns + -------- + :class:`Webhook` + The created webhook. + """ + + if not self.is_news(): + raise ClientException('The channel must be a news channel.') + + if not isinstance(destination, TextChannel): + raise InvalidArgument('Expected TextChannel received {0.__name__}'.format(type(destination))) + + from .webhook import Webhook + data = await self._state.http.follow_webhook(self.id, webhook_channel_id=destination.id, reason=reason) + return Webhook._as_follower(data, channel=destination, user=self._state.user) + + def get_partial_message(self, message_id): + """Creates a :class:`PartialMessage` from the message ID. + + This is useful if you want to work with a message and only have its ID without + doing an unnecessary API call. + + .. versionadded:: 1.6 + + Parameters + ------------ + message_id: :class:`int` + The message ID to create a partial message for. + + Returns + --------- + :class:`PartialMessage` + The partial message. + """ + + from .message import PartialMessage + return PartialMessage(channel=self, id=message_id) + +class VocalGuildChannel(discord.abc.Connectable, discord.abc.GuildChannel, Hashable): + __slots__ = ('name', 'id', 'guild', 'bitrate', 'user_limit', + '_state', 'position', '_overwrites', 'category_id', + 'rtc_region') + + def __init__(self, *, state, guild, data): + self._state = state + self.id = int(data['id']) + self._update(guild, data) + + def _get_voice_client_key(self): + return self.guild.id, 'guild_id' + + def _get_voice_state_pair(self): + return self.guild.id, self.id + + def _update(self, guild, data): + self.guild = guild + self.name = data['name'] + self.rtc_region = data.get('rtc_region') + if self.rtc_region: + self.rtc_region = try_enum(VoiceRegion, self.rtc_region) + self.category_id = utils._get_as_snowflake(data, 'parent_id') + self.position = data['position'] + self.bitrate = data.get('bitrate') + self.user_limit = data.get('user_limit') + self._fill_overwrites(data) + + @property + def _sorting_bucket(self): + return ChannelType.voice.value + + @property + def members(self): + """List[:class:`Member`]: Returns all members that are currently inside this voice channel.""" + ret = [] + for user_id, state in self.guild._voice_states.items(): + if state.channel and state.channel.id == self.id: + member = self.guild.get_member(user_id) + if member is not None: + ret.append(member) + return ret + + @property + def voice_states(self): + """Returns a mapping of member IDs who have voice states in this channel. + + .. versionadded:: 1.3 + + .. note:: + + This function is intentionally low level to replace :attr:`members` + when the member cache is unavailable. + + Returns + -------- + Mapping[:class:`int`, :class:`VoiceState`] + The mapping of member ID to a voice state. + """ + return {key: value for key, value in self.guild._voice_states.items() if value.channel.id == self.id} + + @utils.copy_doc(discord.abc.GuildChannel.permissions_for) + def permissions_for(self, member): + base = super().permissions_for(member) + + # voice channels cannot be edited by people who can't connect to them + # It also implicitly denies all other voice perms + if not base.connect: + denied = Permissions.voice() + denied.update(manage_channels=True, manage_roles=True) + base.value &= ~denied.value + return base + +class VoiceChannel(VocalGuildChannel): + """Represents a Discord guild voice channel. + + .. container:: operations + + .. describe:: x == y + + Checks if two channels are equal. + + .. describe:: x != y + + Checks if two channels are not equal. + + .. describe:: hash(x) + + Returns the channel's hash. + + .. describe:: str(x) + + Returns the channel's name. + + Attributes + ----------- + name: :class:`str` + The channel name. + guild: :class:`Guild` + The guild the channel belongs to. + id: :class:`int` + The channel ID. + category_id: Optional[:class:`int`] + The category channel ID this channel belongs to, if applicable. + position: :class:`int` + The position in the channel list. This is a number that starts at 0. e.g. the + top channel is position 0. + bitrate: :class:`int` + The channel's preferred audio bitrate in bits per second. + user_limit: :class:`int` + The channel's limit for number of members that can be in a voice channel. + rtc_region: Optional[:class:`VoiceRegion`] + The region for the voice channel's voice communication. + A value of ``None`` indicates automatic voice region detection. + + .. versionadded:: 1.7 + """ + + __slots__ = () + + def __repr__(self): + attrs = [ + ('id', self.id), + ('name', self.name), + ('rtc_region', self.rtc_region), + ('position', self.position), + ('bitrate', self.bitrate), + ('user_limit', self.user_limit), + ('category_id', self.category_id) + ] + return '<%s %s>' % (self.__class__.__name__, ' '.join('%s=%r' % t for t in attrs)) + + @property + def type(self): + """:class:`ChannelType`: The channel's Discord type.""" + return ChannelType.voice + + @utils.copy_doc(discord.abc.GuildChannel.clone) + async def clone(self, *, name=None, reason=None): + return await self._clone_impl({ + 'bitrate': self.bitrate, + 'user_limit': self.user_limit + }, name=name, reason=reason) + + async def edit(self, *, reason=None, **options): + """|coro| + + Edits the channel. + + You must have the :attr:`~Permissions.manage_channels` permission to + use this. + + .. versionchanged:: 1.3 + The ``overwrites`` keyword-only parameter was added. + + Parameters + ---------- + name: :class:`str` + The new channel's name. + bitrate: :class:`int` + The new channel's bitrate. + user_limit: :class:`int` + The new channel's user limit. + position: :class:`int` + The new channel's position. + sync_permissions: :class:`bool` + Whether to sync permissions with the channel's new or pre-existing + category. Defaults to ``False``. + category: Optional[:class:`CategoryChannel`] + The new category for this channel. Can be ``None`` to remove the + category. + reason: Optional[:class:`str`] + The reason for editing this channel. Shows up on the audit log. + overwrites: :class:`dict` + A :class:`dict` of target (either a role or a member) to + :class:`PermissionOverwrite` to apply to the channel. + rtc_region: Optional[:class:`VoiceRegion`] + The new region for the voice channel's voice communication. + A value of ``None`` indicates automatic voice region detection. + + .. versionadded:: 1.7 + + Raises + ------ + InvalidArgument + If the permission overwrite information is not in proper form. + Forbidden + You do not have permissions to edit the channel. + HTTPException + Editing the channel failed. + """ + + await self._edit(options, reason=reason) + +class StageChannel(VocalGuildChannel): + """Represents a Discord guild stage channel. + + .. versionadded:: 1.7 + + .. container:: operations + + .. describe:: x == y + + Checks if two channels are equal. + + .. describe:: x != y + + Checks if two channels are not equal. + + .. describe:: hash(x) + + Returns the channel's hash. + + .. describe:: str(x) + + Returns the channel's name. + + Attributes + ----------- + name: :class:`str` + The channel name. + guild: :class:`Guild` + The guild the channel belongs to. + id: :class:`int` + The channel ID. + topic: Optional[:class:`str`] + The channel's topic. ``None`` if it isn't set. + category_id: Optional[:class:`int`] + The category channel ID this channel belongs to, if applicable. + position: :class:`int` + The position in the channel list. This is a number that starts at 0. e.g. the + top channel is position 0. + bitrate: :class:`int` + The channel's preferred audio bitrate in bits per second. + user_limit: :class:`int` + The channel's limit for number of members that can be in a stage channel. + rtc_region: Optional[:class:`VoiceRegion`] + The region for the stage channel's voice communication. + A value of ``None`` indicates automatic voice region detection. + """ + __slots__ = ('topic',) + + def __repr__(self): + attrs = [ + ('id', self.id), + ('name', self.name), + ('topic', self.topic), + ('rtc_region', self.rtc_region), + ('position', self.position), + ('bitrate', self.bitrate), + ('user_limit', self.user_limit), + ('category_id', self.category_id) + ] + return '<%s %s>' % (self.__class__.__name__, ' '.join('%s=%r' % t for t in attrs)) + + def _update(self, guild, data): + super()._update(guild, data) + self.topic = data.get('topic') + + @property + def requesting_to_speak(self): + """List[:class:`Member`]: A list of members who are requesting to speak in the stage channel.""" + return [member for member in self.members if member.voice.requested_to_speak_at is not None] + + @property + def type(self): + """:class:`ChannelType`: The channel's Discord type.""" + return ChannelType.stage_voice + + @utils.copy_doc(discord.abc.GuildChannel.clone) + async def clone(self, *, name=None, reason=None): + return await self._clone_impl({ + 'topic': self.topic, + }, name=name, reason=reason) + + async def edit(self, *, reason=None, **options): + """|coro| + + Edits the channel. + + You must have the :attr:`~Permissions.manage_channels` permission to + use this. + + Parameters + ---------- + name: :class:`str` + The new channel's name. + topic: :class:`str` + The new channel's topic. + position: :class:`int` + The new channel's position. + sync_permissions: :class:`bool` + Whether to sync permissions with the channel's new or pre-existing + category. Defaults to ``False``. + category: Optional[:class:`CategoryChannel`] + The new category for this channel. Can be ``None`` to remove the + category. + reason: Optional[:class:`str`] + The reason for editing this channel. Shows up on the audit log. + overwrites: :class:`dict` + A :class:`dict` of target (either a role or a member) to + :class:`PermissionOverwrite` to apply to the channel. + rtc_region: Optional[:class:`VoiceRegion`] + The new region for the stage channel's voice communication. + A value of ``None`` indicates automatic voice region detection. + + Raises + ------ + InvalidArgument + If the permission overwrite information is not in proper form. + Forbidden + You do not have permissions to edit the channel. + HTTPException + Editing the channel failed. + """ + + await self._edit(options, reason=reason) + +class CategoryChannel(discord.abc.GuildChannel, Hashable): + """Represents a Discord channel category. + + These are useful to group channels to logical compartments. + + .. container:: operations + + .. describe:: x == y + + Checks if two channels are equal. + + .. describe:: x != y + + Checks if two channels are not equal. + + .. describe:: hash(x) + + Returns the category's hash. + + .. describe:: str(x) + + Returns the category's name. + + Attributes + ----------- + name: :class:`str` + The category name. + guild: :class:`Guild` + The guild the category belongs to. + id: :class:`int` + The category channel ID. + position: :class:`int` + The position in the category list. This is a number that starts at 0. e.g. the + top category is position 0. + """ + + __slots__ = ('name', 'id', 'guild', 'nsfw', '_state', 'position', '_overwrites', 'category_id') + + def __init__(self, *, state, guild, data): + self._state = state + self.id = int(data['id']) + self._update(guild, data) + + def __repr__(self): + return ''.format(self) + + def _update(self, guild, data): + self.guild = guild + self.name = data['name'] + self.category_id = utils._get_as_snowflake(data, 'parent_id') + self.nsfw = data.get('nsfw', False) + self.position = data['position'] + self._fill_overwrites(data) + + @property + def _sorting_bucket(self): + return ChannelType.category.value + + @property + def type(self): + """:class:`ChannelType`: The channel's Discord type.""" + return ChannelType.category + + def is_nsfw(self): + """:class:`bool`: Checks if the category is NSFW.""" + return self.nsfw + + @utils.copy_doc(discord.abc.GuildChannel.clone) + async def clone(self, *, name=None, reason=None): + return await self._clone_impl({ + 'nsfw': self.nsfw + }, name=name, reason=reason) + + async def edit(self, *, reason=None, **options): + """|coro| + + Edits the channel. + + You must have the :attr:`~Permissions.manage_channels` permission to + use this. + + .. versionchanged:: 1.3 + The ``overwrites`` keyword-only parameter was added. + + Parameters + ---------- + name: :class:`str` + The new category's name. + position: :class:`int` + The new category's position. + nsfw: :class:`bool` + To mark the category as NSFW or not. + reason: Optional[:class:`str`] + The reason for editing this category. Shows up on the audit log. + overwrites: :class:`dict` + A :class:`dict` of target (either a role or a member) to + :class:`PermissionOverwrite` to apply to the channel. + + Raises + ------ + InvalidArgument + If position is less than 0 or greater than the number of categories. + Forbidden + You do not have permissions to edit the category. + HTTPException + Editing the category failed. + """ + + await self._edit(options=options, reason=reason) + + @utils.copy_doc(discord.abc.GuildChannel.move) + async def move(self, **kwargs): + kwargs.pop('category', None) + await super().move(**kwargs) + + @property + def channels(self): + """List[:class:`abc.GuildChannel`]: Returns the channels that are under this category. + + These are sorted by the official Discord UI, which places voice channels below the text channels. + """ + def comparator(channel): + return (not isinstance(channel, TextChannel), channel.position) + + ret = [c for c in self.guild.channels if c.category_id == self.id] + ret.sort(key=comparator) + return ret + + @property + def text_channels(self): + """List[:class:`TextChannel`]: Returns the text channels that are under this category.""" + ret = [c for c in self.guild.channels + if c.category_id == self.id + and isinstance(c, TextChannel)] + ret.sort(key=lambda c: (c.position, c.id)) + return ret + + @property + def voice_channels(self): + """List[:class:`VoiceChannel`]: Returns the voice channels that are under this category.""" + ret = [c for c in self.guild.channels + if c.category_id == self.id + and isinstance(c, VoiceChannel)] + ret.sort(key=lambda c: (c.position, c.id)) + return ret + + @property + def stage_channels(self): + """List[:class:`StageChannel`]: Returns the voice channels that are under this category. + + .. versionadded:: 1.7 + """ + ret = [c for c in self.guild.channels + if c.category_id == self.id + and isinstance(c, StageChannel)] + ret.sort(key=lambda c: (c.position, c.id)) + return ret + + async def create_text_channel(self, name, *, overwrites=None, reason=None, **options): + """|coro| + + A shortcut method to :meth:`Guild.create_text_channel` to create a :class:`TextChannel` in the category. + + Returns + ------- + :class:`TextChannel` + The channel that was just created. + """ + return await self.guild.create_text_channel(name, overwrites=overwrites, category=self, reason=reason, **options) + + async def create_voice_channel(self, name, *, overwrites=None, reason=None, **options): + """|coro| + + A shortcut method to :meth:`Guild.create_voice_channel` to create a :class:`VoiceChannel` in the category. + + Returns + ------- + :class:`VoiceChannel` + The channel that was just created. + """ + return await self.guild.create_voice_channel(name, overwrites=overwrites, category=self, reason=reason, **options) + + async def create_stage_channel(self, name, *, overwrites=None, reason=None, **options): + """|coro| + + A shortcut method to :meth:`Guild.create_stage_channel` to create a :class:`StageChannel` in the category. + + .. versionadded:: 1.7 + + Returns + ------- + :class:`StageChannel` + The channel that was just created. + """ + return await self.guild.create_stage_channel(name, overwrites=overwrites, category=self, reason=reason, **options) + +class StoreChannel(discord.abc.GuildChannel, Hashable): + """Represents a Discord guild store channel. + + .. container:: operations + + .. describe:: x == y + + Checks if two channels are equal. + + .. describe:: x != y + + Checks if two channels are not equal. + + .. describe:: hash(x) + + Returns the channel's hash. + + .. describe:: str(x) + + Returns the channel's name. + + Attributes + ----------- + name: :class:`str` + The channel name. + guild: :class:`Guild` + The guild the channel belongs to. + id: :class:`int` + The channel ID. + category_id: :class:`int` + The category channel ID this channel belongs to. + position: :class:`int` + The position in the channel list. This is a number that starts at 0. e.g. the + top channel is position 0. + """ + __slots__ = ('name', 'id', 'guild', '_state', 'nsfw', + 'category_id', 'position', '_overwrites',) + + def __init__(self, *, state, guild, data): + self._state = state + self.id = int(data['id']) + self._update(guild, data) + + def __repr__(self): + return ''.format(self) + + def _update(self, guild, data): + self.guild = guild + self.name = data['name'] + self.category_id = utils._get_as_snowflake(data, 'parent_id') + self.position = data['position'] + self.nsfw = data.get('nsfw', False) + self._fill_overwrites(data) + + @property + def _sorting_bucket(self): + return ChannelType.text.value + + @property + def type(self): + """:class:`ChannelType`: The channel's Discord type.""" + return ChannelType.store + + @utils.copy_doc(discord.abc.GuildChannel.permissions_for) + def permissions_for(self, member): + base = super().permissions_for(member) + + # store channels do not have voice related permissions + denied = Permissions.voice() + base.value &= ~denied.value + return base + + def is_nsfw(self): + """:class:`bool`: Checks if the channel is NSFW.""" + return self.nsfw + + @utils.copy_doc(discord.abc.GuildChannel.clone) + async def clone(self, *, name=None, reason=None): + return await self._clone_impl({ + 'nsfw': self.nsfw + }, name=name, reason=reason) + + async def edit(self, *, reason=None, **options): + """|coro| + + Edits the channel. + + You must have the :attr:`~Permissions.manage_channels` permission to + use this. + + Parameters + ---------- + name: :class:`str` + The new channel name. + position: :class:`int` + The new channel's position. + nsfw: :class:`bool` + To mark the channel as NSFW or not. + sync_permissions: :class:`bool` + Whether to sync permissions with the channel's new or pre-existing + category. Defaults to ``False``. + category: Optional[:class:`CategoryChannel`] + The new category for this channel. Can be ``None`` to remove the + category. + reason: Optional[:class:`str`] + The reason for editing this channel. Shows up on the audit log. + overwrites: :class:`dict` + A :class:`dict` of target (either a role or a member) to + :class:`PermissionOverwrite` to apply to the channel. + + .. versionadded:: 1.3 + + Raises + ------ + InvalidArgument + If position is less than 0 or greater than the number of channels, or if + the permission overwrite information is not in proper form. + Forbidden + You do not have permissions to edit the channel. + HTTPException + Editing the channel failed. + """ + await self._edit(options, reason=reason) + +class DMChannel(discord.abc.Messageable, Hashable): + """Represents a Discord direct message channel. + + .. container:: operations + + .. describe:: x == y + + Checks if two channels are equal. + + .. describe:: x != y + + Checks if two channels are not equal. + + .. describe:: hash(x) + + Returns the channel's hash. + + .. describe:: str(x) + + Returns a string representation of the channel + + Attributes + ---------- + recipient: :class:`User` + The user you are participating with in the direct message channel. + me: :class:`ClientUser` + The user presenting yourself. + id: :class:`int` + The direct message channel ID. + """ + + __slots__ = ('id', 'recipient', 'me', '_state') + + def __init__(self, *, me, state, data): + self._state = state + self.recipient = state.store_user(data['recipients'][0]) + self.me = me + self.id = int(data['id']) + + async def _get_channel(self): + return self + + def __str__(self): + return 'Direct Message with %s' % self.recipient + + def __repr__(self): + return ''.format(self) + + @property + def type(self): + """:class:`ChannelType`: The channel's Discord type.""" + return ChannelType.private + + @property + def created_at(self): + """:class:`datetime.datetime`: Returns the direct message channel's creation time in UTC.""" + return utils.snowflake_time(self.id) + + def permissions_for(self, user=None): + """Handles permission resolution for a :class:`User`. + + This function is there for compatibility with other channel types. + + Actual direct messages do not really have the concept of permissions. + + This returns all the Text related permissions set to ``True`` except: + + - :attr:`~Permissions.send_tts_messages`: You cannot send TTS messages in a DM. + - :attr:`~Permissions.manage_messages`: You cannot delete others messages in a DM. + + Parameters + ----------- + user: :class:`User` + The user to check permissions for. This parameter is ignored + but kept for compatibility. + + Returns + -------- + :class:`Permissions` + The resolved permissions. + """ + + base = Permissions.text() + base.read_messages = True + base.send_tts_messages = False + base.manage_messages = False + return base + + def get_partial_message(self, message_id): + """Creates a :class:`PartialMessage` from the message ID. + + This is useful if you want to work with a message and only have its ID without + doing an unnecessary API call. + + .. versionadded:: 1.6 + + Parameters + ------------ + message_id: :class:`int` + The message ID to create a partial message for. + + Returns + --------- + :class:`PartialMessage` + The partial message. + """ + + from .message import PartialMessage + return PartialMessage(channel=self, id=message_id) + +class GroupChannel(discord.abc.Messageable, Hashable): + """Represents a Discord group channel. + + .. container:: operations + + .. describe:: x == y + + Checks if two channels are equal. + + .. describe:: x != y + + Checks if two channels are not equal. + + .. describe:: hash(x) + + Returns the channel's hash. + + .. describe:: str(x) + + Returns a string representation of the channel + + Attributes + ---------- + recipients: List[:class:`User`] + The users you are participating with in the group channel. + me: :class:`ClientUser` + The user presenting yourself. + id: :class:`int` + The group channel ID. + owner: :class:`User` + The user that owns the group channel. + icon: Optional[:class:`str`] + The group channel's icon hash if provided. + name: Optional[:class:`str`] + The group channel's name if provided. + """ + + __slots__ = ('id', 'recipients', 'owner', 'icon', 'name', 'me', '_state') + + def __init__(self, *, me, state, data): + self._state = state + self.id = int(data['id']) + self.me = me + self._update_group(data) + + def _update_group(self, data): + owner_id = utils._get_as_snowflake(data, 'owner_id') + self.icon = data.get('icon') + self.name = data.get('name') + + try: + self.recipients = [self._state.store_user(u) for u in data['recipients']] + except KeyError: + pass + + if owner_id == self.me.id: + self.owner = self.me + else: + self.owner = utils.find(lambda u: u.id == owner_id, self.recipients) + + async def _get_channel(self): + return self + + def __str__(self): + if self.name: + return self.name + + if len(self.recipients) == 0: + return 'Unnamed' + + return ', '.join(map(lambda x: x.name, self.recipients)) + + def __repr__(self): + return ''.format(self) + + @property + def type(self): + """:class:`ChannelType`: The channel's Discord type.""" + return ChannelType.group + + @property + def icon_url(self): + """:class:`Asset`: Returns the channel's icon asset if available. + + This is equivalent to calling :meth:`icon_url_as` with + the default parameters ('webp' format and a size of 1024). + """ + return self.icon_url_as() + + def icon_url_as(self, *, format='webp', size=1024): + """Returns an :class:`Asset` for the icon the channel has. + + The format must be one of 'webp', 'jpeg', 'jpg' or 'png'. + The size must be a power of 2 between 16 and 4096. + + .. versionadded:: 2.0 + + Parameters + ----------- + format: :class:`str` + The format to attempt to convert the icon to. Defaults to 'webp'. + size: :class:`int` + The size of the image to display. + + Raises + ------ + InvalidArgument + Bad image format passed to ``format`` or invalid ``size``. + + Returns + -------- + :class:`Asset` + The resulting CDN asset. + """ + return Asset._from_icon(self._state, self, 'channel', format=format, size=size) + + @property + def created_at(self): + """:class:`datetime.datetime`: Returns the channel's creation time in UTC.""" + return utils.snowflake_time(self.id) + + def permissions_for(self, user): + """Handles permission resolution for a :class:`User`. + + This function is there for compatibility with other channel types. + + Actual direct messages do not really have the concept of permissions. + + This returns all the Text related permissions set to ``True`` except: + + - :attr:`~Permissions.send_tts_messages`: You cannot send TTS messages in a DM. + - :attr:`~Permissions.manage_messages`: You cannot delete others messages in a DM. + + This also checks the kick_members permission if the user is the owner. + + Parameters + ----------- + user: :class:`User` + The user to check permissions for. + + Returns + -------- + :class:`Permissions` + The resolved permissions for the user. + """ + + base = Permissions.text() + base.read_messages = True + base.send_tts_messages = False + base.manage_messages = False + base.mention_everyone = True + + if user.id == self.owner.id: + base.kick_members = True + + return base + + @utils.deprecated() + async def add_recipients(self, *recipients): + r"""|coro| + + Adds recipients to this group. + + A group can only have a maximum of 10 members. + Attempting to add more ends up in an exception. To + add a recipient to the group, you must have a relationship + with the user of type :attr:`RelationshipType.friend`. + + .. deprecated:: 1.7 + + Parameters + ----------- + \*recipients: :class:`User` + An argument list of users to add to this group. + + Raises + ------- + HTTPException + Adding a recipient to this group failed. + """ + + # TODO: wait for the corresponding WS event + + req = self._state.http.add_group_recipient + for recipient in recipients: + await req(self.id, recipient.id) + + @utils.deprecated() + async def remove_recipients(self, *recipients): + r"""|coro| + + Removes recipients from this group. + + .. deprecated:: 1.7 + + Parameters + ----------- + \*recipients: :class:`User` + An argument list of users to remove from this group. + + Raises + ------- + HTTPException + Removing a recipient from this group failed. + """ + + # TODO: wait for the corresponding WS event + + req = self._state.http.remove_group_recipient + for recipient in recipients: + await req(self.id, recipient.id) + + @utils.deprecated() + async def edit(self, **fields): + """|coro| + + Edits the group. + + .. deprecated:: 1.7 + + Parameters + ----------- + name: Optional[:class:`str`] + The new name to change the group to. + Could be ``None`` to remove the name. + icon: Optional[:class:`bytes`] + A :term:`py:bytes-like object` representing the new icon. + Could be ``None`` to remove the icon. + + Raises + ------- + HTTPException + Editing the group failed. + """ + + try: + icon_bytes = fields['icon'] + except KeyError: + pass + else: + if icon_bytes is not None: + fields['icon'] = utils._bytes_to_base64_data(icon_bytes) + + data = await self._state.http.edit_group(self.id, **fields) + self._update_group(data) + + async def leave(self): + """|coro| + + Leave the group. + + If you are the only one in the group, this deletes it as well. + + Raises + ------- + HTTPException + Leaving the group failed. + """ + + await self._state.http.leave_group(self.id) + +def _channel_factory(channel_type): + value = try_enum(ChannelType, channel_type) + if value is ChannelType.text: + return TextChannel, value + elif value is ChannelType.voice: + return VoiceChannel, value + elif value is ChannelType.private: + return DMChannel, value + elif value is ChannelType.category: + return CategoryChannel, value + elif value is ChannelType.group: + return GroupChannel, value + elif value is ChannelType.news: + return TextChannel, value + elif value is ChannelType.store: + return StoreChannel, value + elif value is ChannelType.stage_voice: + return StageChannel, value + else: + return None, value diff --git a/venv/lib64/python3.8/site-packages/discord/client.py b/venv/lib64/python3.8/site-packages/discord/client.py new file mode 100644 index 0000000..1c35fdd --- /dev/null +++ b/venv/lib64/python3.8/site-packages/discord/client.py @@ -0,0 +1,1494 @@ +# -*- coding: utf-8 -*- + +""" +The MIT License (MIT) + +Copyright (c) 2015-present Rapptz + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. +""" + +import asyncio +import logging +import signal +import sys +import traceback + +import aiohttp + +from .user import User, Profile +from .invite import Invite +from .template import Template +from .widget import Widget +from .guild import Guild +from .channel import _channel_factory +from .enums import ChannelType +from .mentions import AllowedMentions +from .errors import * +from .enums import Status, VoiceRegion +from .gateway import * +from .activity import BaseActivity, create_activity +from .voice_client import VoiceClient +from .http import HTTPClient +from .state import ConnectionState +from . import utils +from .object import Object +from .backoff import ExponentialBackoff +from .webhook import Webhook +from .iterators import GuildIterator +from .appinfo import AppInfo + +log = logging.getLogger(__name__) + +def _cancel_tasks(loop): + try: + task_retriever = asyncio.Task.all_tasks + except AttributeError: + # future proofing for 3.9 I guess + task_retriever = asyncio.all_tasks + + tasks = {t for t in task_retriever(loop=loop) if not t.done()} + + if not tasks: + return + + log.info('Cleaning up after %d tasks.', len(tasks)) + for task in tasks: + task.cancel() + + loop.run_until_complete(asyncio.gather(*tasks, return_exceptions=True)) + log.info('All tasks finished cancelling.') + + for task in tasks: + if task.cancelled(): + continue + if task.exception() is not None: + loop.call_exception_handler({ + 'message': 'Unhandled exception during Client.run shutdown.', + 'exception': task.exception(), + 'task': task + }) + +def _cleanup_loop(loop): + try: + _cancel_tasks(loop) + if sys.version_info >= (3, 6): + loop.run_until_complete(loop.shutdown_asyncgens()) + finally: + log.info('Closing the event loop.') + loop.close() + +class _ClientEventTask(asyncio.Task): + def __init__(self, original_coro, event_name, coro, *, loop): + super().__init__(coro, loop=loop) + self.__event_name = event_name + self.__original_coro = original_coro + + def __repr__(self): + info = [ + ('state', self._state.lower()), + ('event', self.__event_name), + ('coro', repr(self.__original_coro)), + ] + if self._exception is not None: + info.append(('exception', repr(self._exception))) + return ''.format(' '.join('%s=%s' % t for t in info)) + +class Client: + r"""Represents a client connection that connects to Discord. + This class is used to interact with the Discord WebSocket and API. + + A number of options can be passed to the :class:`Client`. + + Parameters + ----------- + max_messages: Optional[:class:`int`] + The maximum number of messages to store in the internal message cache. + This defaults to ``1000``. Passing in ``None`` disables the message cache. + + .. versionchanged:: 1.3 + Allow disabling the message cache and change the default size to ``1000``. + loop: Optional[:class:`asyncio.AbstractEventLoop`] + The :class:`asyncio.AbstractEventLoop` to use for asynchronous operations. + Defaults to ``None``, in which case the default event loop is used via + :func:`asyncio.get_event_loop()`. + connector: :class:`aiohttp.BaseConnector` + The connector to use for connection pooling. + proxy: Optional[:class:`str`] + Proxy URL. + proxy_auth: Optional[:class:`aiohttp.BasicAuth`] + An object that represents proxy HTTP Basic Authorization. + shard_id: Optional[:class:`int`] + Integer starting at ``0`` and less than :attr:`.shard_count`. + shard_count: Optional[:class:`int`] + The total number of shards. + intents: :class:`Intents` + The intents that you want to enable for the session. This is a way of + disabling and enabling certain gateway events from triggering and being sent. + If not given, defaults to a regularly constructed :class:`Intents` class. + + .. versionadded:: 1.5 + member_cache_flags: :class:`MemberCacheFlags` + Allows for finer control over how the library caches members. + If not given, defaults to cache as much as possible with the + currently selected intents. + + .. versionadded:: 1.5 + fetch_offline_members: :class:`bool` + A deprecated alias of ``chunk_guilds_at_startup``. + chunk_guilds_at_startup: :class:`bool` + Indicates if :func:`.on_ready` should be delayed to chunk all guilds + at start-up if necessary. This operation is incredibly slow for large + amounts of guilds. The default is ``True`` if :attr:`Intents.members` + is ``True``. + + .. versionadded:: 1.5 + status: Optional[:class:`.Status`] + A status to start your presence with upon logging on to Discord. + activity: Optional[:class:`.BaseActivity`] + An activity to start your presence with upon logging on to Discord. + allowed_mentions: Optional[:class:`AllowedMentions`] + Control how the client handles mentions by default on every message sent. + + .. versionadded:: 1.4 + heartbeat_timeout: :class:`float` + The maximum numbers of seconds before timing out and restarting the + WebSocket in the case of not receiving a HEARTBEAT_ACK. Useful if + processing the initial packets take too long to the point of disconnecting + you. The default timeout is 60 seconds. + guild_ready_timeout: :class:`float` + The maximum number of seconds to wait for the GUILD_CREATE stream to end before + preparing the member cache and firing READY. The default timeout is 2 seconds. + + .. versionadded:: 1.4 + guild_subscriptions: :class:`bool` + Whether to dispatch presence or typing events. Defaults to ``True``. + + .. versionadded:: 1.3 + + .. warning:: + + If this is set to ``False`` then the following features will be disabled: + + - No user related updates (:func:`on_user_update` will not dispatch) + - All member related events will be disabled. + - :func:`on_member_update` + - :func:`on_member_join` + - :func:`on_member_remove` + + - Typing events will be disabled (:func:`on_typing`). + - If ``fetch_offline_members`` is set to ``False`` then the user cache will not exist. + This makes it difficult or impossible to do many things, for example: + + - Computing permissions + - Querying members in a voice channel via :attr:`VoiceChannel.members` will be empty. + - Most forms of receiving :class:`Member` will be + receiving :class:`User` instead, except for message events. + - :attr:`Guild.owner` will usually resolve to ``None``. + - :meth:`Guild.get_member` will usually be unavailable. + - Anything that involves using :class:`Member`. + - :attr:`users` will not be as populated. + - etc. + + In short, this makes it so the only member you can reliably query is the + message author. Useful for bots that do not require any state. + assume_unsync_clock: :class:`bool` + Whether to assume the system clock is unsynced. This applies to the ratelimit handling + code. If this is set to ``True``, the default, then the library uses the time to reset + a rate limit bucket given by Discord. If this is ``False`` then your system clock is + used to calculate how long to sleep for. If this is set to ``False`` it is recommended to + sync your system clock to Google's NTP server. + + .. versionadded:: 1.3 + + Attributes + ----------- + ws + The websocket gateway the client is currently connected to. Could be ``None``. + loop: :class:`asyncio.AbstractEventLoop` + The event loop that the client uses for HTTP requests and websocket operations. + """ + def __init__(self, *, loop=None, **options): + self.ws = None + self.loop = asyncio.get_event_loop() if loop is None else loop + self._listeners = {} + self.shard_id = options.get('shard_id') + self.shard_count = options.get('shard_count') + + connector = options.pop('connector', None) + proxy = options.pop('proxy', None) + proxy_auth = options.pop('proxy_auth', None) + unsync_clock = options.pop('assume_unsync_clock', True) + self.http = HTTPClient(connector, proxy=proxy, proxy_auth=proxy_auth, unsync_clock=unsync_clock, loop=self.loop) + + self._handlers = { + 'ready': self._handle_ready + } + + self._hooks = { + 'before_identify': self._call_before_identify_hook + } + + self._connection = self._get_state(**options) + self._connection.shard_count = self.shard_count + self._closed = False + self._ready = asyncio.Event() + self._connection._get_websocket = self._get_websocket + self._connection._get_client = lambda: self + + if VoiceClient.warn_nacl: + VoiceClient.warn_nacl = False + log.warning("PyNaCl is not installed, voice will NOT be supported") + + # internals + + def _get_websocket(self, guild_id=None, *, shard_id=None): + return self.ws + + def _get_state(self, **options): + return ConnectionState(dispatch=self.dispatch, handlers=self._handlers, + hooks=self._hooks, syncer=self._syncer, http=self.http, loop=self.loop, **options) + + async def _syncer(self, guilds): + await self.ws.request_sync(guilds) + + def _handle_ready(self): + self._ready.set() + + @property + def latency(self): + """:class:`float`: Measures latency between a HEARTBEAT and a HEARTBEAT_ACK in seconds. + + This could be referred to as the Discord WebSocket protocol latency. + """ + ws = self.ws + return float('nan') if not ws else ws.latency + + def is_ws_ratelimited(self): + """:class:`bool`: Whether the websocket is currently rate limited. + + This can be useful to know when deciding whether you should query members + using HTTP or via the gateway. + + .. versionadded:: 1.6 + """ + if self.ws: + return self.ws.is_ratelimited() + return False + + @property + def user(self): + """Optional[:class:`.ClientUser`]: Represents the connected client. ``None`` if not logged in.""" + return self._connection.user + + @property + def guilds(self): + """List[:class:`.Guild`]: The guilds that the connected client is a member of.""" + return self._connection.guilds + + @property + def emojis(self): + """List[:class:`.Emoji`]: The emojis that the connected client has.""" + return self._connection.emojis + + @property + def cached_messages(self): + """Sequence[:class:`.Message`]: Read-only list of messages the connected client has cached. + + .. versionadded:: 1.1 + """ + return utils.SequenceProxy(self._connection._messages or []) + + @property + def private_channels(self): + """List[:class:`.abc.PrivateChannel`]: The private channels that the connected client is participating on. + + .. note:: + + This returns only up to 128 most recent private channels due to an internal working + on how Discord deals with private channels. + """ + return self._connection.private_channels + + @property + def voice_clients(self): + """List[:class:`.VoiceProtocol`]: Represents a list of voice connections. + + These are usually :class:`.VoiceClient` instances. + """ + return self._connection.voice_clients + + def is_ready(self): + """:class:`bool`: Specifies if the client's internal cache is ready for use.""" + return self._ready.is_set() + + async def _run_event(self, coro, event_name, *args, **kwargs): + try: + await coro(*args, **kwargs) + except asyncio.CancelledError: + pass + except Exception: + try: + await self.on_error(event_name, *args, **kwargs) + except asyncio.CancelledError: + pass + + def _schedule_event(self, coro, event_name, *args, **kwargs): + wrapped = self._run_event(coro, event_name, *args, **kwargs) + # Schedules the task + return _ClientEventTask(original_coro=coro, event_name=event_name, coro=wrapped, loop=self.loop) + + def dispatch(self, event, *args, **kwargs): + log.debug('Dispatching event %s', event) + method = 'on_' + event + + listeners = self._listeners.get(event) + if listeners: + removed = [] + for i, (future, condition) in enumerate(listeners): + if future.cancelled(): + removed.append(i) + continue + + try: + result = condition(*args) + except Exception as exc: + future.set_exception(exc) + removed.append(i) + else: + if result: + if len(args) == 0: + future.set_result(None) + elif len(args) == 1: + future.set_result(args[0]) + else: + future.set_result(args) + removed.append(i) + + if len(removed) == len(listeners): + self._listeners.pop(event) + else: + for idx in reversed(removed): + del listeners[idx] + + try: + coro = getattr(self, method) + except AttributeError: + pass + else: + self._schedule_event(coro, method, *args, **kwargs) + + async def on_error(self, event_method, *args, **kwargs): + """|coro| + + The default error handler provided by the client. + + By default this prints to :data:`sys.stderr` however it could be + overridden to have a different implementation. + Check :func:`~discord.on_error` for more details. + """ + print('Ignoring exception in {}'.format(event_method), file=sys.stderr) + traceback.print_exc() + + @utils.deprecated('Guild.chunk') + async def request_offline_members(self, *guilds): + r"""|coro| + + Requests previously offline members from the guild to be filled up + into the :attr:`.Guild.members` cache. This function is usually not + called. It should only be used if you have the ``fetch_offline_members`` + parameter set to ``False``. + + When the client logs on and connects to the websocket, Discord does + not provide the library with offline members if the number of members + in the guild is larger than 250. You can check if a guild is large + if :attr:`.Guild.large` is ``True``. + + .. warning:: + + This method is deprecated. Use :meth:`Guild.chunk` instead. + + Parameters + ----------- + \*guilds: :class:`.Guild` + An argument list of guilds to request offline members for. + + Raises + ------- + :exc:`.InvalidArgument` + If any guild is unavailable in the collection. + """ + if any(g.unavailable for g in guilds): + raise InvalidArgument('An unavailable guild was passed.') + + for guild in guilds: + await self._connection.chunk_guild(guild) + + # hooks + + async def _call_before_identify_hook(self, shard_id, *, initial=False): + # This hook is an internal hook that actually calls the public one. + # It allows the library to have its own hook without stepping on the + # toes of those who need to override their own hook. + await self.before_identify_hook(shard_id, initial=initial) + + async def before_identify_hook(self, shard_id, *, initial=False): + """|coro| + + A hook that is called before IDENTIFYing a session. This is useful + if you wish to have more control over the synchronization of multiple + IDENTIFYing clients. + + The default implementation sleeps for 5 seconds. + + .. versionadded:: 1.4 + + Parameters + ------------ + shard_id: :class:`int` + The shard ID that requested being IDENTIFY'd + initial: :class:`bool` + Whether this IDENTIFY is the first initial IDENTIFY. + """ + + if not initial: + await asyncio.sleep(5.0) + + # login state management + + async def login(self, token, *, bot=True): + """|coro| + + Logs in the client with the specified credentials. + + This function can be used in two different ways. + + .. warning:: + + Logging on with a user token is against the Discord + `Terms of Service `_ + and doing so might potentially get your account banned. + Use this at your own risk. + + Parameters + ----------- + token: :class:`str` + The authentication token. Do not prefix this token with + anything as the library will do it for you. + bot: :class:`bool` + Keyword argument that specifies if the account logging on is a bot + token or not. + + .. deprecated:: 1.7 + + Raises + ------ + :exc:`.LoginFailure` + The wrong credentials are passed. + :exc:`.HTTPException` + An unknown HTTP related error occurred, + usually when it isn't 200 or the known incorrect credentials + passing status code. + """ + + log.info('logging in using static token') + await self.http.static_login(token.strip(), bot=bot) + self._connection.is_bot = bot + + @utils.deprecated('Client.close') + async def logout(self): + """|coro| + + Logs out of Discord and closes all connections. + + .. deprecated:: 1.7 + + .. note:: + + This is just an alias to :meth:`close`. If you want + to do extraneous cleanup when subclassing, it is suggested + to override :meth:`close` instead. + """ + await self.close() + + async def connect(self, *, reconnect=True): + """|coro| + + Creates a websocket connection and lets the websocket listen + to messages from Discord. This is a loop that runs the entire + event system and miscellaneous aspects of the library. Control + is not resumed until the WebSocket connection is terminated. + + Parameters + ----------- + reconnect: :class:`bool` + If we should attempt reconnecting, either due to internet + failure or a specific failure on Discord's part. Certain + disconnects that lead to bad state will not be handled (such as + invalid sharding payloads or bad tokens). + + Raises + ------- + :exc:`.GatewayNotFound` + If the gateway to connect to Discord is not found. Usually if this + is thrown then there is a Discord API outage. + :exc:`.ConnectionClosed` + The websocket connection has been terminated. + """ + + backoff = ExponentialBackoff() + ws_params = { + 'initial': True, + 'shard_id': self.shard_id, + } + while not self.is_closed(): + try: + coro = DiscordWebSocket.from_client(self, **ws_params) + self.ws = await asyncio.wait_for(coro, timeout=60.0) + ws_params['initial'] = False + while True: + await self.ws.poll_event() + except ReconnectWebSocket as e: + log.info('Got a request to %s the websocket.', e.op) + self.dispatch('disconnect') + ws_params.update(sequence=self.ws.sequence, resume=e.resume, session=self.ws.session_id) + continue + except (OSError, + HTTPException, + GatewayNotFound, + ConnectionClosed, + aiohttp.ClientError, + asyncio.TimeoutError) as exc: + + self.dispatch('disconnect') + if not reconnect: + await self.close() + if isinstance(exc, ConnectionClosed) and exc.code == 1000: + # clean close, don't re-raise this + return + raise + + if self.is_closed(): + return + + # If we get connection reset by peer then try to RESUME + if isinstance(exc, OSError) and exc.errno in (54, 10054): + ws_params.update(sequence=self.ws.sequence, initial=False, resume=True, session=self.ws.session_id) + continue + + # We should only get this when an unhandled close code happens, + # such as a clean disconnect (1000) or a bad state (bad token, no sharding, etc) + # sometimes, discord sends us 1000 for unknown reasons so we should reconnect + # regardless and rely on is_closed instead + if isinstance(exc, ConnectionClosed): + if exc.code == 4014: + raise PrivilegedIntentsRequired(exc.shard_id) from None + if exc.code != 1000: + await self.close() + raise + + retry = backoff.delay() + log.exception("Attempting a reconnect in %.2fs", retry) + await asyncio.sleep(retry) + # Always try to RESUME the connection + # If the connection is not RESUME-able then the gateway will invalidate the session. + # This is apparently what the official Discord client does. + ws_params.update(sequence=self.ws.sequence, resume=True, session=self.ws.session_id) + + async def close(self): + """|coro| + + Closes the connection to Discord. + """ + if self._closed: + return + + await self.http.close() + self._closed = True + + for voice in self.voice_clients: + try: + await voice.disconnect() + except Exception: + # if an error happens during disconnects, disregard it. + pass + + if self.ws is not None and self.ws.open: + await self.ws.close(code=1000) + + self._ready.clear() + + def clear(self): + """Clears the internal state of the bot. + + After this, the bot can be considered "re-opened", i.e. :meth:`is_closed` + and :meth:`is_ready` both return ``False`` along with the bot's internal + cache cleared. + """ + self._closed = False + self._ready.clear() + self._connection.clear() + self.http.recreate() + + async def start(self, *args, **kwargs): + """|coro| + + A shorthand coroutine for :meth:`login` + :meth:`connect`. + + Raises + ------- + TypeError + An unexpected keyword argument was received. + """ + bot = kwargs.pop('bot', True) + reconnect = kwargs.pop('reconnect', True) + + if kwargs: + raise TypeError("unexpected keyword argument(s) %s" % list(kwargs.keys())) + + await self.login(*args, bot=bot) + await self.connect(reconnect=reconnect) + + def run(self, *args, **kwargs): + """A blocking call that abstracts away the event loop + initialisation from you. + + If you want more control over the event loop then this + function should not be used. Use :meth:`start` coroutine + or :meth:`connect` + :meth:`login`. + + Roughly Equivalent to: :: + + try: + loop.run_until_complete(start(*args, **kwargs)) + except KeyboardInterrupt: + loop.run_until_complete(close()) + # cancel all tasks lingering + finally: + loop.close() + + .. warning:: + + This function must be the last function to call due to the fact that it + is blocking. That means that registration of events or anything being + called after this function call will not execute until it returns. + """ + loop = self.loop + + try: + loop.add_signal_handler(signal.SIGINT, lambda: loop.stop()) + loop.add_signal_handler(signal.SIGTERM, lambda: loop.stop()) + except NotImplementedError: + pass + + async def runner(): + try: + await self.start(*args, **kwargs) + finally: + if not self.is_closed(): + await self.close() + + def stop_loop_on_completion(f): + loop.stop() + + future = asyncio.ensure_future(runner(), loop=loop) + future.add_done_callback(stop_loop_on_completion) + try: + loop.run_forever() + except KeyboardInterrupt: + log.info('Received signal to terminate bot and event loop.') + finally: + future.remove_done_callback(stop_loop_on_completion) + log.info('Cleaning up tasks.') + _cleanup_loop(loop) + + if not future.cancelled(): + try: + return future.result() + except KeyboardInterrupt: + # I am unsure why this gets raised here but suppress it anyway + return None + + # properties + + def is_closed(self): + """:class:`bool`: Indicates if the websocket connection is closed.""" + return self._closed + + @property + def activity(self): + """Optional[:class:`.BaseActivity`]: The activity being used upon + logging in. + """ + return create_activity(self._connection._activity) + + @activity.setter + def activity(self, value): + if value is None: + self._connection._activity = None + elif isinstance(value, BaseActivity): + self._connection._activity = value.to_dict() + else: + raise TypeError('activity must derive from BaseActivity.') + + @property + def allowed_mentions(self): + """Optional[:class:`~discord.AllowedMentions`]: The allowed mention configuration. + + .. versionadded:: 1.4 + """ + return self._connection.allowed_mentions + + @allowed_mentions.setter + def allowed_mentions(self, value): + if value is None or isinstance(value, AllowedMentions): + self._connection.allowed_mentions = value + else: + raise TypeError('allowed_mentions must be AllowedMentions not {0.__class__!r}'.format(value)) + + @property + def intents(self): + """:class:`~discord.Intents`: The intents configured for this connection. + + .. versionadded:: 1.5 + """ + return self._connection.intents + + # helpers/getters + + @property + def users(self): + """List[:class:`~discord.User`]: Returns a list of all the users the bot can see.""" + return list(self._connection._users.values()) + + def get_channel(self, id): + """Returns a channel with the given ID. + + Parameters + ----------- + id: :class:`int` + The ID to search for. + + Returns + -------- + Optional[Union[:class:`.abc.GuildChannel`, :class:`.abc.PrivateChannel`]] + The returned channel or ``None`` if not found. + """ + return self._connection.get_channel(id) + + def get_guild(self, id): + """Returns a guild with the given ID. + + Parameters + ----------- + id: :class:`int` + The ID to search for. + + Returns + -------- + Optional[:class:`.Guild`] + The guild or ``None`` if not found. + """ + return self._connection._get_guild(id) + + def get_user(self, id): + """Returns a user with the given ID. + + Parameters + ----------- + id: :class:`int` + The ID to search for. + + Returns + -------- + Optional[:class:`~discord.User`] + The user or ``None`` if not found. + """ + return self._connection.get_user(id) + + def get_emoji(self, id): + """Returns an emoji with the given ID. + + Parameters + ----------- + id: :class:`int` + The ID to search for. + + Returns + -------- + Optional[:class:`.Emoji`] + The custom emoji or ``None`` if not found. + """ + return self._connection.get_emoji(id) + + def get_all_channels(self): + """A generator that retrieves every :class:`.abc.GuildChannel` the client can 'access'. + + This is equivalent to: :: + + for guild in client.guilds: + for channel in guild.channels: + yield channel + + .. note:: + + Just because you receive a :class:`.abc.GuildChannel` does not mean that + you can communicate in said channel. :meth:`.abc.GuildChannel.permissions_for` should + be used for that. + + Yields + ------ + :class:`.abc.GuildChannel` + A channel the client can 'access'. + """ + + for guild in self.guilds: + for channel in guild.channels: + yield channel + + def get_all_members(self): + """Returns a generator with every :class:`.Member` the client can see. + + This is equivalent to: :: + + for guild in client.guilds: + for member in guild.members: + yield member + + Yields + ------ + :class:`.Member` + A member the client can see. + """ + for guild in self.guilds: + for member in guild.members: + yield member + + # listeners/waiters + + async def wait_until_ready(self): + """|coro| + + Waits until the client's internal cache is all ready. + """ + await self._ready.wait() + + def wait_for(self, event, *, check=None, timeout=None): + """|coro| + + Waits for a WebSocket event to be dispatched. + + This could be used to wait for a user to reply to a message, + or to react to a message, or to edit a message in a self-contained + way. + + The ``timeout`` parameter is passed onto :func:`asyncio.wait_for`. By default, + it does not timeout. Note that this does propagate the + :exc:`asyncio.TimeoutError` for you in case of timeout and is provided for + ease of use. + + In case the event returns multiple arguments, a :class:`tuple` containing those + arguments is returned instead. Please check the + :ref:`documentation ` for a list of events and their + parameters. + + This function returns the **first event that meets the requirements**. + + Examples + --------- + + Waiting for a user reply: :: + + @client.event + async def on_message(message): + if message.content.startswith('$greet'): + channel = message.channel + await channel.send('Say hello!') + + def check(m): + return m.content == 'hello' and m.channel == channel + + msg = await client.wait_for('message', check=check) + await channel.send('Hello {.author}!'.format(msg)) + + Waiting for a thumbs up reaction from the message author: :: + + @client.event + async def on_message(message): + if message.content.startswith('$thumb'): + channel = message.channel + await channel.send('Send me that \N{THUMBS UP SIGN} reaction, mate') + + def check(reaction, user): + return user == message.author and str(reaction.emoji) == '\N{THUMBS UP SIGN}' + + try: + reaction, user = await client.wait_for('reaction_add', timeout=60.0, check=check) + except asyncio.TimeoutError: + await channel.send('\N{THUMBS DOWN SIGN}') + else: + await channel.send('\N{THUMBS UP SIGN}') + + + Parameters + ------------ + event: :class:`str` + The event name, similar to the :ref:`event reference `, + but without the ``on_`` prefix, to wait for. + check: Optional[Callable[..., :class:`bool`]] + A predicate to check what to wait for. The arguments must meet the + parameters of the event being waited for. + timeout: Optional[:class:`float`] + The number of seconds to wait before timing out and raising + :exc:`asyncio.TimeoutError`. + + Raises + ------- + asyncio.TimeoutError + If a timeout is provided and it was reached. + + Returns + -------- + Any + Returns no arguments, a single argument, or a :class:`tuple` of multiple + arguments that mirrors the parameters passed in the + :ref:`event reference `. + """ + + future = self.loop.create_future() + if check is None: + def _check(*args): + return True + check = _check + + ev = event.lower() + try: + listeners = self._listeners[ev] + except KeyError: + listeners = [] + self._listeners[ev] = listeners + + listeners.append((future, check)) + return asyncio.wait_for(future, timeout) + + # event registration + + def event(self, coro): + """A decorator that registers an event to listen to. + + You can find more info about the events on the :ref:`documentation below `. + + The events must be a :ref:`coroutine `, if not, :exc:`TypeError` is raised. + + Example + --------- + + .. code-block:: python3 + + @client.event + async def on_ready(): + print('Ready!') + + Raises + -------- + TypeError + The coroutine passed is not actually a coroutine. + """ + + if not asyncio.iscoroutinefunction(coro): + raise TypeError('event registered must be a coroutine function') + + setattr(self, coro.__name__, coro) + log.debug('%s has successfully been registered as an event', coro.__name__) + return coro + + async def change_presence(self, *, activity=None, status=None, afk=False): + """|coro| + + Changes the client's presence. + + Example + --------- + + .. code-block:: python3 + + game = discord.Game("with the API") + await client.change_presence(status=discord.Status.idle, activity=game) + + Parameters + ---------- + activity: Optional[:class:`.BaseActivity`] + The activity being done. ``None`` if no currently active activity is done. + status: Optional[:class:`.Status`] + Indicates what status to change to. If ``None``, then + :attr:`.Status.online` is used. + afk: Optional[:class:`bool`] + Indicates if you are going AFK. This allows the discord + client to know how to handle push notifications better + for you in case you are actually idle and not lying. + + Raises + ------ + :exc:`.InvalidArgument` + If the ``activity`` parameter is not the proper type. + """ + + if status is None: + status = 'online' + status_enum = Status.online + elif status is Status.offline: + status = 'invisible' + status_enum = Status.offline + else: + status_enum = status + status = str(status) + + await self.ws.change_presence(activity=activity, status=status, afk=afk) + + for guild in self._connection.guilds: + me = guild.me + if me is None: + continue + + if activity is not None: + me.activities = (activity,) + else: + me.activities = () + + me.status = status_enum + + # Guild stuff + + def fetch_guilds(self, *, limit=100, before=None, after=None): + """Retrieves an :class:`.AsyncIterator` that enables receiving your guilds. + + .. note:: + + Using this, you will only receive :attr:`.Guild.owner`, :attr:`.Guild.icon`, + :attr:`.Guild.id`, and :attr:`.Guild.name` per :class:`.Guild`. + + .. note:: + + This method is an API call. For general usage, consider :attr:`guilds` instead. + + Examples + --------- + + Usage :: + + async for guild in client.fetch_guilds(limit=150): + print(guild.name) + + Flattening into a list :: + + guilds = await client.fetch_guilds(limit=150).flatten() + # guilds is now a list of Guild... + + All parameters are optional. + + Parameters + ----------- + limit: Optional[:class:`int`] + The number of guilds to retrieve. + If ``None``, it retrieves every guild you have access to. Note, however, + that this would make it a slow operation. + Defaults to ``100``. + before: Union[:class:`.abc.Snowflake`, :class:`datetime.datetime`] + Retrieves guilds before this date or object. + If a date is provided it must be a timezone-naive datetime representing UTC time. + after: Union[:class:`.abc.Snowflake`, :class:`datetime.datetime`] + Retrieve guilds after this date or object. + If a date is provided it must be a timezone-naive datetime representing UTC time. + + Raises + ------ + :exc:`.HTTPException` + Getting the guilds failed. + + Yields + -------- + :class:`.Guild` + The guild with the guild data parsed. + """ + return GuildIterator(self, limit=limit, before=before, after=after) + + async def fetch_template(self, code): + """|coro| + + Gets a :class:`.Template` from a discord.new URL or code. + + Parameters + ----------- + code: Union[:class:`.Template`, :class:`str`] + The Discord Template Code or URL (must be a discord.new URL). + + Raises + ------- + :exc:`.NotFound` + The template is invalid. + :exc:`.HTTPException` + Getting the template failed. + + Returns + -------- + :class:`.Template` + The template from the URL/code. + """ + code = utils.resolve_template(code) + data = await self.http.get_template(code) + return Template(data=data, state=self._connection) + + async def fetch_guild(self, guild_id): + """|coro| + + Retrieves a :class:`.Guild` from an ID. + + .. note:: + + Using this, you will **not** receive :attr:`.Guild.channels`, :attr:`.Guild.members`, + :attr:`.Member.activity` and :attr:`.Member.voice` per :class:`.Member`. + + .. note:: + + This method is an API call. For general usage, consider :meth:`get_guild` instead. + + Parameters + ----------- + guild_id: :class:`int` + The guild's ID to fetch from. + + Raises + ------ + :exc:`.Forbidden` + You do not have access to the guild. + :exc:`.HTTPException` + Getting the guild failed. + + Returns + -------- + :class:`.Guild` + The guild from the ID. + """ + data = await self.http.get_guild(guild_id) + return Guild(data=data, state=self._connection) + + async def create_guild(self, name, region=None, icon=None, *, code=None): + """|coro| + + Creates a :class:`.Guild`. + + Bot accounts in more than 10 guilds are not allowed to create guilds. + + Parameters + ---------- + name: :class:`str` + The name of the guild. + region: :class:`.VoiceRegion` + The region for the voice communication server. + Defaults to :attr:`.VoiceRegion.us_west`. + icon: :class:`bytes` + The :term:`py:bytes-like object` representing the icon. See :meth:`.ClientUser.edit` + for more details on what is expected. + code: Optional[:class:`str`] + The code for a template to create the guild with. + + .. versionadded:: 1.4 + + Raises + ------ + :exc:`.HTTPException` + Guild creation failed. + :exc:`.InvalidArgument` + Invalid icon image format given. Must be PNG or JPG. + + Returns + ------- + :class:`.Guild` + The guild created. This is not the same guild that is + added to cache. + """ + if icon is not None: + icon = utils._bytes_to_base64_data(icon) + + region = region or VoiceRegion.us_west + region_value = region.value + + if code: + data = await self.http.create_from_template(code, name, region_value, icon) + else: + data = await self.http.create_guild(name, region_value, icon) + return Guild(data=data, state=self._connection) + + # Invite management + + async def fetch_invite(self, url, *, with_counts=True): + """|coro| + + Gets an :class:`.Invite` from a discord.gg URL or ID. + + .. note:: + + If the invite is for a guild you have not joined, the guild and channel + attributes of the returned :class:`.Invite` will be :class:`.PartialInviteGuild` and + :class:`.PartialInviteChannel` respectively. + + Parameters + ----------- + url: Union[:class:`.Invite`, :class:`str`] + The Discord invite ID or URL (must be a discord.gg URL). + with_counts: :class:`bool` + Whether to include count information in the invite. This fills the + :attr:`.Invite.approximate_member_count` and :attr:`.Invite.approximate_presence_count` + fields. + + Raises + ------- + :exc:`.NotFound` + The invite has expired or is invalid. + :exc:`.HTTPException` + Getting the invite failed. + + Returns + -------- + :class:`.Invite` + The invite from the URL/ID. + """ + + invite_id = utils.resolve_invite(url) + data = await self.http.get_invite(invite_id, with_counts=with_counts) + return Invite.from_incomplete(state=self._connection, data=data) + + async def delete_invite(self, invite): + """|coro| + + Revokes an :class:`.Invite`, URL, or ID to an invite. + + You must have the :attr:`~.Permissions.manage_channels` permission in + the associated guild to do this. + + Parameters + ---------- + invite: Union[:class:`.Invite`, :class:`str`] + The invite to revoke. + + Raises + ------- + :exc:`.Forbidden` + You do not have permissions to revoke invites. + :exc:`.NotFound` + The invite is invalid or expired. + :exc:`.HTTPException` + Revoking the invite failed. + """ + + invite_id = utils.resolve_invite(invite) + await self.http.delete_invite(invite_id) + + # Miscellaneous stuff + + async def fetch_widget(self, guild_id): + """|coro| + + Gets a :class:`.Widget` from a guild ID. + + .. note:: + + The guild must have the widget enabled to get this information. + + Parameters + ----------- + guild_id: :class:`int` + The ID of the guild. + + Raises + ------- + :exc:`.Forbidden` + The widget for this guild is disabled. + :exc:`.HTTPException` + Retrieving the widget failed. + + Returns + -------- + :class:`.Widget` + The guild's widget. + """ + data = await self.http.get_widget(guild_id) + + return Widget(state=self._connection, data=data) + + async def application_info(self): + """|coro| + + Retrieves the bot's application information. + + Raises + ------- + :exc:`.HTTPException` + Retrieving the information failed somehow. + + Returns + -------- + :class:`.AppInfo` + The bot's application information. + """ + data = await self.http.application_info() + if 'rpc_origins' not in data: + data['rpc_origins'] = None + return AppInfo(self._connection, data) + + async def fetch_user(self, user_id): + """|coro| + + Retrieves a :class:`~discord.User` based on their ID. This can only + be used by bot accounts. You do not have to share any guilds + with the user to get this information, however many operations + do require that you do. + + .. note:: + + This method is an API call. If you have :attr:`Intents.members` and member cache enabled, consider :meth:`get_user` instead. + + Parameters + ----------- + user_id: :class:`int` + The user's ID to fetch from. + + Raises + ------- + :exc:`.NotFound` + A user with this ID does not exist. + :exc:`.HTTPException` + Fetching the user failed. + + Returns + -------- + :class:`~discord.User` + The user you requested. + """ + data = await self.http.get_user(user_id) + return User(state=self._connection, data=data) + + @utils.deprecated() + async def fetch_user_profile(self, user_id): + """|coro| + + Gets an arbitrary user's profile. + + .. deprecated:: 1.7 + + .. note:: + + This can only be used by non-bot accounts. + + Parameters + ------------ + user_id: :class:`int` + The ID of the user to fetch their profile for. + + Raises + ------- + :exc:`.Forbidden` + Not allowed to fetch profiles. + :exc:`.HTTPException` + Fetching the profile failed. + + Returns + -------- + :class:`.Profile` + The profile of the user. + """ + + state = self._connection + data = await self.http.get_user_profile(user_id) + + def transform(d): + return state._get_guild(int(d['id'])) + + since = data.get('premium_since') + mutual_guilds = list(filter(None, map(transform, data.get('mutual_guilds', [])))) + user = data['user'] + return Profile(flags=user.get('flags', 0), + premium_since=utils.parse_time(since), + mutual_guilds=mutual_guilds, + user=User(data=user, state=state), + connected_accounts=data['connected_accounts']) + + async def fetch_channel(self, channel_id): + """|coro| + + Retrieves a :class:`.abc.GuildChannel` or :class:`.abc.PrivateChannel` with the specified ID. + + .. note:: + + This method is an API call. For general usage, consider :meth:`get_channel` instead. + + .. versionadded:: 1.2 + + Raises + ------- + :exc:`.InvalidData` + An unknown channel type was received from Discord. + :exc:`.HTTPException` + Retrieving the channel failed. + :exc:`.NotFound` + Invalid Channel ID. + :exc:`.Forbidden` + You do not have permission to fetch this channel. + + Returns + -------- + Union[:class:`.abc.GuildChannel`, :class:`.abc.PrivateChannel`] + The channel from the ID. + """ + data = await self.http.get_channel(channel_id) + + factory, ch_type = _channel_factory(data['type']) + if factory is None: + raise InvalidData('Unknown channel type {type} for channel ID {id}.'.format_map(data)) + + if ch_type in (ChannelType.group, ChannelType.private): + channel = factory(me=self.user, data=data, state=self._connection) + else: + guild_id = int(data['guild_id']) + guild = self.get_guild(guild_id) or Object(id=guild_id) + channel = factory(guild=guild, state=self._connection, data=data) + + return channel + + async def fetch_webhook(self, webhook_id): + """|coro| + + Retrieves a :class:`.Webhook` with the specified ID. + + Raises + -------- + :exc:`.HTTPException` + Retrieving the webhook failed. + :exc:`.NotFound` + Invalid webhook ID. + :exc:`.Forbidden` + You do not have permission to fetch this webhook. + + Returns + --------- + :class:`.Webhook` + The webhook you requested. + """ + data = await self.http.get_webhook(webhook_id) + return Webhook.from_state(data, state=self._connection) diff --git a/venv/lib64/python3.8/site-packages/discord/colour.py b/venv/lib64/python3.8/site-packages/discord/colour.py new file mode 100644 index 0000000..fbf9aae --- /dev/null +++ b/venv/lib64/python3.8/site-packages/discord/colour.py @@ -0,0 +1,269 @@ +# -*- coding: utf-8 -*- + +""" +The MIT License (MIT) + +Copyright (c) 2015-present Rapptz + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. +""" + +import colorsys +import random + +class Colour: + """Represents a Discord role colour. This class is similar + to a (red, green, blue) :class:`tuple`. + + There is an alias for this called Color. + + .. container:: operations + + .. describe:: x == y + + Checks if two colours are equal. + + .. describe:: x != y + + Checks if two colours are not equal. + + .. describe:: hash(x) + + Return the colour's hash. + + .. describe:: str(x) + + Returns the hex format for the colour. + + Attributes + ------------ + value: :class:`int` + The raw integer colour value. + """ + + __slots__ = ('value',) + + def __init__(self, value): + if not isinstance(value, int): + raise TypeError('Expected int parameter, received %s instead.' % value.__class__.__name__) + + self.value = value + + def _get_byte(self, byte): + return (self.value >> (8 * byte)) & 0xff + + def __eq__(self, other): + return isinstance(other, Colour) and self.value == other.value + + def __ne__(self, other): + return not self.__eq__(other) + + def __str__(self): + return '#{:0>6x}'.format(self.value) + + def __repr__(self): + return '' % self.value + + def __hash__(self): + return hash(self.value) + + @property + def r(self): + """:class:`int`: Returns the red component of the colour.""" + return self._get_byte(2) + + @property + def g(self): + """:class:`int`: Returns the green component of the colour.""" + return self._get_byte(1) + + @property + def b(self): + """:class:`int`: Returns the blue component of the colour.""" + return self._get_byte(0) + + def to_rgb(self): + """Tuple[:class:`int`, :class:`int`, :class:`int`]: Returns an (r, g, b) tuple representing the colour.""" + return (self.r, self.g, self.b) + + @classmethod + def from_rgb(cls, r, g, b): + """Constructs a :class:`Colour` from an RGB tuple.""" + return cls((r << 16) + (g << 8) + b) + + @classmethod + def from_hsv(cls, h, s, v): + """Constructs a :class:`Colour` from an HSV tuple.""" + rgb = colorsys.hsv_to_rgb(h, s, v) + return cls.from_rgb(*(int(x * 255) for x in rgb)) + + @classmethod + def default(cls): + """A factory method that returns a :class:`Colour` with a value of ``0``.""" + return cls(0) + + @classmethod + def random(cls, *, seed=None): + """A factory method that returns a :class:`Colour` with a random hue. + + .. note:: + + The random algorithm works by choosing a colour with a random hue but + with maxed out saturation and value. + + .. versionadded:: 1.6 + + Parameters + ------------ + seed: Optional[Union[:class:`int`, :class:`str`, :class:`float`, :class:`bytes`, :class:`bytearray`]] + The seed to initialize the RNG with. If ``None`` is passed the default RNG is used. + + .. versionadded:: 1.7 + """ + rand = random if seed is None else random.Random(seed) + return cls.from_hsv(rand.random(), 1, 1) + + @classmethod + def teal(cls): + """A factory method that returns a :class:`Colour` with a value of ``0x1abc9c``.""" + return cls(0x1abc9c) + + @classmethod + def dark_teal(cls): + """A factory method that returns a :class:`Colour` with a value of ``0x11806a``.""" + return cls(0x11806a) + + @classmethod + def green(cls): + """A factory method that returns a :class:`Colour` with a value of ``0x2ecc71``.""" + return cls(0x2ecc71) + + @classmethod + def dark_green(cls): + """A factory method that returns a :class:`Colour` with a value of ``0x1f8b4c``.""" + return cls(0x1f8b4c) + + @classmethod + def blue(cls): + """A factory method that returns a :class:`Colour` with a value of ``0x3498db``.""" + return cls(0x3498db) + + @classmethod + def dark_blue(cls): + """A factory method that returns a :class:`Colour` with a value of ``0x206694``.""" + return cls(0x206694) + + @classmethod + def purple(cls): + """A factory method that returns a :class:`Colour` with a value of ``0x9b59b6``.""" + return cls(0x9b59b6) + + @classmethod + def dark_purple(cls): + """A factory method that returns a :class:`Colour` with a value of ``0x71368a``.""" + return cls(0x71368a) + + @classmethod + def magenta(cls): + """A factory method that returns a :class:`Colour` with a value of ``0xe91e63``.""" + return cls(0xe91e63) + + @classmethod + def dark_magenta(cls): + """A factory method that returns a :class:`Colour` with a value of ``0xad1457``.""" + return cls(0xad1457) + + @classmethod + def gold(cls): + """A factory method that returns a :class:`Colour` with a value of ``0xf1c40f``.""" + return cls(0xf1c40f) + + @classmethod + def dark_gold(cls): + """A factory method that returns a :class:`Colour` with a value of ``0xc27c0e``.""" + return cls(0xc27c0e) + + @classmethod + def orange(cls): + """A factory method that returns a :class:`Colour` with a value of ``0xe67e22``.""" + return cls(0xe67e22) + + @classmethod + def dark_orange(cls): + """A factory method that returns a :class:`Colour` with a value of ``0xa84300``.""" + return cls(0xa84300) + + @classmethod + def red(cls): + """A factory method that returns a :class:`Colour` with a value of ``0xe74c3c``.""" + return cls(0xe74c3c) + + @classmethod + def dark_red(cls): + """A factory method that returns a :class:`Colour` with a value of ``0x992d22``.""" + return cls(0x992d22) + + @classmethod + def lighter_grey(cls): + """A factory method that returns a :class:`Colour` with a value of ``0x95a5a6``.""" + return cls(0x95a5a6) + + lighter_gray = lighter_grey + + @classmethod + def dark_grey(cls): + """A factory method that returns a :class:`Colour` with a value of ``0x607d8b``.""" + return cls(0x607d8b) + + dark_gray = dark_grey + + @classmethod + def light_grey(cls): + """A factory method that returns a :class:`Colour` with a value of ``0x979c9f``.""" + return cls(0x979c9f) + + light_gray = light_grey + + @classmethod + def darker_grey(cls): + """A factory method that returns a :class:`Colour` with a value of ``0x546e7a``.""" + return cls(0x546e7a) + + darker_gray = darker_grey + + @classmethod + def blurple(cls): + """A factory method that returns a :class:`Colour` with a value of ``0x7289da``.""" + return cls(0x7289da) + + @classmethod + def greyple(cls): + """A factory method that returns a :class:`Colour` with a value of ``0x99aab5``.""" + return cls(0x99aab5) + + @classmethod + def dark_theme(cls): + """A factory method that returns a :class:`Colour` with a value of ``0x36393F``. + This will appear transparent on Discord's dark theme. + + .. versionadded:: 1.5 + """ + return cls(0x36393F) + +Color = Colour diff --git a/venv/lib64/python3.8/site-packages/discord/context_managers.py b/venv/lib64/python3.8/site-packages/discord/context_managers.py new file mode 100644 index 0000000..e4fde6b --- /dev/null +++ b/venv/lib64/python3.8/site-packages/discord/context_managers.py @@ -0,0 +1,67 @@ +# -*- coding: utf-8 -*- + +""" +The MIT License (MIT) + +Copyright (c) 2015-present Rapptz + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. +""" + +import asyncio + +def _typing_done_callback(fut): + # just retrieve any exception and call it a day + try: + fut.exception() + except (asyncio.CancelledError, Exception): + pass + +class Typing: + def __init__(self, messageable): + self.loop = messageable._state.loop + self.messageable = messageable + + async def do_typing(self): + try: + channel = self._channel + except AttributeError: + channel = await self.messageable._get_channel() + + typing = channel._state.http.send_typing + + while True: + await typing(channel.id) + await asyncio.sleep(5) + + def __enter__(self): + self.task = asyncio.ensure_future(self.do_typing(), loop=self.loop) + self.task.add_done_callback(_typing_done_callback) + return self + + def __exit__(self, exc_type, exc, tb): + self.task.cancel() + + async def __aenter__(self): + self._channel = channel = await self.messageable._get_channel() + await channel._state.http.send_typing(channel.id) + return self.__enter__() + + async def __aexit__(self, exc_type, exc, tb): + self.task.cancel() diff --git a/venv/lib64/python3.8/site-packages/discord/embeds.py b/venv/lib64/python3.8/site-packages/discord/embeds.py new file mode 100644 index 0000000..cbe1146 --- /dev/null +++ b/venv/lib64/python3.8/site-packages/discord/embeds.py @@ -0,0 +1,618 @@ +# -*- coding: utf-8 -*- + +""" +The MIT License (MIT) + +Copyright (c) 2015-present Rapptz + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. +""" + +import datetime + +from . import utils +from .colour import Colour + +class _EmptyEmbed: + def __bool__(self): + return False + + def __repr__(self): + return 'Embed.Empty' + + def __len__(self): + return 0 + +EmptyEmbed = _EmptyEmbed() + +class EmbedProxy: + def __init__(self, layer): + self.__dict__.update(layer) + + def __len__(self): + return len(self.__dict__) + + def __repr__(self): + return 'EmbedProxy(%s)' % ', '.join(('%s=%r' % (k, v) for k, v in self.__dict__.items() if not k.startswith('_'))) + + def __getattr__(self, attr): + return EmptyEmbed + +class Embed: + """Represents a Discord embed. + + .. container:: operations + + .. describe:: len(x) + + Returns the total size of the embed. + Useful for checking if it's within the 6000 character limit. + + Certain properties return an ``EmbedProxy``, a type + that acts similar to a regular :class:`dict` except using dotted access, + e.g. ``embed.author.icon_url``. If the attribute + is invalid or empty, then a special sentinel value is returned, + :attr:`Embed.Empty`. + + For ease of use, all parameters that expect a :class:`str` are implicitly + casted to :class:`str` for you. + + Attributes + ----------- + title: :class:`str` + The title of the embed. + This can be set during initialisation. + type: :class:`str` + The type of embed. Usually "rich". + This can be set during initialisation. + Possible strings for embed types can be found on discord's + `api docs `_ + description: :class:`str` + The description of the embed. + This can be set during initialisation. + url: :class:`str` + The URL of the embed. + This can be set during initialisation. + timestamp: :class:`datetime.datetime` + The timestamp of the embed content. This could be a naive or aware datetime. + colour: Union[:class:`Colour`, :class:`int`] + The colour code of the embed. Aliased to ``color`` as well. + This can be set during initialisation. + Empty + A special sentinel value used by ``EmbedProxy`` and this class + to denote that the value or attribute is empty. + """ + + __slots__ = ('title', 'url', 'type', '_timestamp', '_colour', '_footer', + '_image', '_thumbnail', '_video', '_provider', '_author', + '_fields', 'description') + + Empty = EmptyEmbed + + def __init__(self, **kwargs): + # swap the colour/color aliases + try: + colour = kwargs['colour'] + except KeyError: + colour = kwargs.get('color', EmptyEmbed) + + self.colour = colour + self.title = kwargs.get('title', EmptyEmbed) + self.type = kwargs.get('type', 'rich') + self.url = kwargs.get('url', EmptyEmbed) + self.description = kwargs.get('description', EmptyEmbed) + + if self.title is not EmptyEmbed: + self.title = str(self.title) + + if self.description is not EmptyEmbed: + self.description = str(self.description) + + if self.url is not EmptyEmbed: + self.url = str(self.url) + + try: + timestamp = kwargs['timestamp'] + except KeyError: + pass + else: + self.timestamp = timestamp + + @classmethod + def from_dict(cls, data): + """Converts a :class:`dict` to a :class:`Embed` provided it is in the + format that Discord expects it to be in. + + You can find out about this format in the `official Discord documentation`__. + + .. _DiscordDocs: https://discord.com/developers/docs/resources/channel#embed-object + + __ DiscordDocs_ + + Parameters + ----------- + data: :class:`dict` + The dictionary to convert into an embed. + """ + # we are bypassing __init__ here since it doesn't apply here + self = cls.__new__(cls) + + # fill in the basic fields + + self.title = data.get('title', EmptyEmbed) + self.type = data.get('type', EmptyEmbed) + self.description = data.get('description', EmptyEmbed) + self.url = data.get('url', EmptyEmbed) + + if self.title is not EmptyEmbed: + self.title = str(self.title) + + if self.description is not EmptyEmbed: + self.description = str(self.description) + + if self.url is not EmptyEmbed: + self.url = str(self.url) + + # try to fill in the more rich fields + + try: + self._colour = Colour(value=data['color']) + except KeyError: + pass + + try: + self._timestamp = utils.parse_time(data['timestamp']) + except KeyError: + pass + + for attr in ('thumbnail', 'video', 'provider', 'author', 'fields', 'image', 'footer'): + try: + value = data[attr] + except KeyError: + continue + else: + setattr(self, '_' + attr, value) + + return self + + def copy(self): + """Returns a shallow copy of the embed.""" + return Embed.from_dict(self.to_dict()) + + def __len__(self): + total = len(self.title) + len(self.description) + for field in getattr(self, '_fields', []): + total += len(field['name']) + len(field['value']) + + try: + footer = self._footer + except AttributeError: + pass + else: + total += len(footer['text']) + + try: + author = self._author + except AttributeError: + pass + else: + total += len(author['name']) + + return total + + @property + def colour(self): + return getattr(self, '_colour', EmptyEmbed) + + @colour.setter + def colour(self, value): + if isinstance(value, (Colour, _EmptyEmbed)): + self._colour = value + elif isinstance(value, int): + self._colour = Colour(value=value) + else: + raise TypeError('Expected discord.Colour, int, or Embed.Empty but received %s instead.' % value.__class__.__name__) + + color = colour + + @property + def timestamp(self): + return getattr(self, '_timestamp', EmptyEmbed) + + @timestamp.setter + def timestamp(self, value): + if isinstance(value, (datetime.datetime, _EmptyEmbed)): + self._timestamp = value + else: + raise TypeError("Expected datetime.datetime or Embed.Empty received %s instead" % value.__class__.__name__) + + @property + def footer(self): + """Union[:class:`EmbedProxy`, :attr:`Empty`]: Returns an ``EmbedProxy`` denoting the footer contents. + + See :meth:`set_footer` for possible values you can access. + + If the attribute has no value then :attr:`Empty` is returned. + """ + return EmbedProxy(getattr(self, '_footer', {})) + + def set_footer(self, *, text=EmptyEmbed, icon_url=EmptyEmbed): + """Sets the footer for the embed content. + + This function returns the class instance to allow for fluent-style + chaining. + + Parameters + ----------- + text: :class:`str` + The footer text. + icon_url: :class:`str` + The URL of the footer icon. Only HTTP(S) is supported. + """ + + self._footer = {} + if text is not EmptyEmbed: + self._footer['text'] = str(text) + + if icon_url is not EmptyEmbed: + self._footer['icon_url'] = str(icon_url) + + return self + + @property + def image(self): + """Union[:class:`EmbedProxy`, :attr:`Empty`]: Returns an ``EmbedProxy`` denoting the image contents. + + Possible attributes you can access are: + + - ``url`` + - ``proxy_url`` + - ``width`` + - ``height`` + + If the attribute has no value then :attr:`Empty` is returned. + """ + return EmbedProxy(getattr(self, '_image', {})) + + def set_image(self, *, url): + """Sets the image for the embed content. + + This function returns the class instance to allow for fluent-style + chaining. + + .. versionchanged:: 1.4 + Passing :attr:`Empty` removes the image. + + Parameters + ----------- + url: :class:`str` + The source URL for the image. Only HTTP(S) is supported. + """ + + if url is EmptyEmbed: + try: + del self._image + except AttributeError: + pass + else: + self._image = { + 'url': str(url) + } + + return self + + @property + def thumbnail(self): + """Union[:class:`EmbedProxy`, :attr:`Empty`]: Returns an ``EmbedProxy`` denoting the thumbnail contents. + + Possible attributes you can access are: + + - ``url`` + - ``proxy_url`` + - ``width`` + - ``height`` + + If the attribute has no value then :attr:`Empty` is returned. + """ + return EmbedProxy(getattr(self, '_thumbnail', {})) + + def set_thumbnail(self, *, url): + """Sets the thumbnail for the embed content. + + This function returns the class instance to allow for fluent-style + chaining. + + .. versionchanged:: 1.4 + Passing :attr:`Empty` removes the thumbnail. + + Parameters + ----------- + url: :class:`str` + The source URL for the thumbnail. Only HTTP(S) is supported. + """ + + if url is EmptyEmbed: + try: + del self._thumbnail + except AttributeError: + pass + else: + self._thumbnail = { + 'url': str(url) + } + + return self + + @property + def video(self): + """Union[:class:`EmbedProxy`, :attr:`Empty`]: Returns an ``EmbedProxy`` denoting the video contents. + + Possible attributes include: + + - ``url`` for the video URL. + - ``height`` for the video height. + - ``width`` for the video width. + + If the attribute has no value then :attr:`Empty` is returned. + """ + return EmbedProxy(getattr(self, '_video', {})) + + @property + def provider(self): + """Union[:class:`EmbedProxy`, :attr:`Empty`]: Returns an ``EmbedProxy`` denoting the provider contents. + + The only attributes that might be accessed are ``name`` and ``url``. + + If the attribute has no value then :attr:`Empty` is returned. + """ + return EmbedProxy(getattr(self, '_provider', {})) + + @property + def author(self): + """Union[:class:`EmbedProxy`, :attr:`Empty`]: Returns an ``EmbedProxy`` denoting the author contents. + + See :meth:`set_author` for possible values you can access. + + If the attribute has no value then :attr:`Empty` is returned. + """ + return EmbedProxy(getattr(self, '_author', {})) + + def set_author(self, *, name, url=EmptyEmbed, icon_url=EmptyEmbed): + """Sets the author for the embed content. + + This function returns the class instance to allow for fluent-style + chaining. + + Parameters + ----------- + name: :class:`str` + The name of the author. + url: :class:`str` + The URL for the author. + icon_url: :class:`str` + The URL of the author icon. Only HTTP(S) is supported. + """ + + self._author = { + 'name': str(name) + } + + if url is not EmptyEmbed: + self._author['url'] = str(url) + + if icon_url is not EmptyEmbed: + self._author['icon_url'] = str(icon_url) + + return self + + def remove_author(self): + """Clears embed's author information. + + This function returns the class instance to allow for fluent-style + chaining. + + .. versionadded:: 1.4 + """ + try: + del self._author + except AttributeError: + pass + + return self + + @property + def fields(self): + """List[Union[``EmbedProxy``, :attr:`Empty`]]: Returns a :class:`list` of ``EmbedProxy`` denoting the field contents. + + See :meth:`add_field` for possible values you can access. + + If the attribute has no value then :attr:`Empty` is returned. + """ + return [EmbedProxy(d) for d in getattr(self, '_fields', [])] + + def add_field(self, *, name, value, inline=True): + """Adds a field to the embed object. + + This function returns the class instance to allow for fluent-style + chaining. + + Parameters + ----------- + name: :class:`str` + The name of the field. + value: :class:`str` + The value of the field. + inline: :class:`bool` + Whether the field should be displayed inline. + """ + + field = { + 'inline': inline, + 'name': str(name), + 'value': str(value) + } + + try: + self._fields.append(field) + except AttributeError: + self._fields = [field] + + return self + + def insert_field_at(self, index, *, name, value, inline=True): + """Inserts a field before a specified index to the embed. + + This function returns the class instance to allow for fluent-style + chaining. + + .. versionadded:: 1.2 + + Parameters + ----------- + index: :class:`int` + The index of where to insert the field. + name: :class:`str` + The name of the field. + value: :class:`str` + The value of the field. + inline: :class:`bool` + Whether the field should be displayed inline. + """ + + field = { + 'inline': inline, + 'name': str(name), + 'value': str(value) + } + + try: + self._fields.insert(index, field) + except AttributeError: + self._fields = [field] + + return self + + def clear_fields(self): + """Removes all fields from this embed.""" + try: + self._fields.clear() + except AttributeError: + self._fields = [] + + def remove_field(self, index): + """Removes a field at a specified index. + + If the index is invalid or out of bounds then the error is + silently swallowed. + + .. note:: + + When deleting a field by index, the index of the other fields + shift to fill the gap just like a regular list. + + Parameters + ----------- + index: :class:`int` + The index of the field to remove. + """ + try: + del self._fields[index] + except (AttributeError, IndexError): + pass + + def set_field_at(self, index, *, name, value, inline=True): + """Modifies a field to the embed object. + + The index must point to a valid pre-existing field. + + This function returns the class instance to allow for fluent-style + chaining. + + Parameters + ----------- + index: :class:`int` + The index of the field to modify. + name: :class:`str` + The name of the field. + value: :class:`str` + The value of the field. + inline: :class:`bool` + Whether the field should be displayed inline. + + Raises + ------- + IndexError + An invalid index was provided. + """ + + try: + field = self._fields[index] + except (TypeError, IndexError, AttributeError): + raise IndexError('field index out of range') + + field['name'] = str(name) + field['value'] = str(value) + field['inline'] = inline + return self + + def to_dict(self): + """Converts this embed object into a dict.""" + + # add in the raw data into the dict + result = { + key[1:]: getattr(self, key) + for key in self.__slots__ + if key[0] == '_' and hasattr(self, key) + } + + # deal with basic convenience wrappers + + try: + colour = result.pop('colour') + except KeyError: + pass + else: + if colour: + result['color'] = colour.value + + try: + timestamp = result.pop('timestamp') + except KeyError: + pass + else: + if timestamp: + if timestamp.tzinfo: + result['timestamp'] = timestamp.astimezone(tz=datetime.timezone.utc).isoformat() + else: + result['timestamp'] = timestamp.replace(tzinfo=datetime.timezone.utc).isoformat() + + # add in the non raw attribute ones + if self.type: + result['type'] = self.type + + if self.description: + result['description'] = self.description + + if self.url: + result['url'] = self.url + + if self.title: + result['title'] = self.title + + return result diff --git a/venv/lib64/python3.8/site-packages/discord/emoji.py b/venv/lib64/python3.8/site-packages/discord/emoji.py new file mode 100644 index 0000000..735d508 --- /dev/null +++ b/venv/lib64/python3.8/site-packages/discord/emoji.py @@ -0,0 +1,254 @@ +# -*- coding: utf-8 -*- + +""" +The MIT License (MIT) + +Copyright (c) 2015-present Rapptz + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. +""" + +from .asset import Asset +from . import utils +from .partial_emoji import _EmojiTag +from .user import User + +class Emoji(_EmojiTag): + """Represents a custom emoji. + + Depending on the way this object was created, some of the attributes can + have a value of ``None``. + + .. container:: operations + + .. describe:: x == y + + Checks if two emoji are the same. + + .. describe:: x != y + + Checks if two emoji are not the same. + + .. describe:: hash(x) + + Return the emoji's hash. + + .. describe:: iter(x) + + Returns an iterator of ``(field, value)`` pairs. This allows this class + to be used as an iterable in list/dict/etc constructions. + + .. describe:: str(x) + + Returns the emoji rendered for discord. + + Attributes + ----------- + name: :class:`str` + The name of the emoji. + id: :class:`int` + The emoji's ID. + require_colons: :class:`bool` + If colons are required to use this emoji in the client (:PJSalt: vs PJSalt). + animated: :class:`bool` + Whether an emoji is animated or not. + managed: :class:`bool` + If this emoji is managed by a Twitch integration. + guild_id: :class:`int` + The guild ID the emoji belongs to. + available: :class:`bool` + Whether the emoji is available for use. + user: Optional[:class:`User`] + The user that created the emoji. This can only be retrieved using :meth:`Guild.fetch_emoji` and + having the :attr:`~Permissions.manage_emojis` permission. + """ + __slots__ = ('require_colons', 'animated', 'managed', 'id', 'name', '_roles', 'guild_id', + '_state', 'user', 'available') + + def __init__(self, *, guild, state, data): + self.guild_id = guild.id + self._state = state + self._from_data(data) + + def _from_data(self, emoji): + self.require_colons = emoji['require_colons'] + self.managed = emoji['managed'] + self.id = int(emoji['id']) + self.name = emoji['name'] + self.animated = emoji.get('animated', False) + self.available = emoji.get('available', True) + self._roles = utils.SnowflakeList(map(int, emoji.get('roles', []))) + user = emoji.get('user') + self.user = User(state=self._state, data=user) if user else None + + def _iterator(self): + for attr in self.__slots__: + if attr[0] != '_': + value = getattr(self, attr, None) + if value is not None: + yield (attr, value) + + def __iter__(self): + return self._iterator() + + def __str__(self): + if self.animated: + return ''.format(self) + return "<:{0.name}:{0.id}>".format(self) + + def __repr__(self): + return ''.format(self) + + def __eq__(self, other): + return isinstance(other, _EmojiTag) and self.id == other.id + + def __ne__(self, other): + return not self.__eq__(other) + + def __hash__(self): + return self.id >> 22 + + @property + def created_at(self): + """:class:`datetime.datetime`: Returns the emoji's creation time in UTC.""" + return utils.snowflake_time(self.id) + + @property + def url(self): + """:class:`Asset`: Returns the asset of the emoji. + + This is equivalent to calling :meth:`url_as` with + the default parameters (i.e. png/gif detection). + """ + return self.url_as(format=None) + + @property + def roles(self): + """List[:class:`Role`]: A :class:`list` of roles that is allowed to use this emoji. + + If roles is empty, the emoji is unrestricted. + """ + guild = self.guild + if guild is None: + return [] + + return [role for role in guild.roles if self._roles.has(role.id)] + + @property + def guild(self): + """:class:`Guild`: The guild this emoji belongs to.""" + return self._state._get_guild(self.guild_id) + + + def url_as(self, *, format=None, static_format="png"): + """Returns an :class:`Asset` for the emoji's url. + + The format must be one of 'webp', 'jpeg', 'jpg', 'png' or 'gif'. + 'gif' is only valid for animated emojis. + + .. versionadded:: 1.6 + + Parameters + ----------- + format: Optional[:class:`str`] + The format to attempt to convert the emojis to. + If the format is ``None``, then it is automatically + detected as either 'gif' or static_format, depending on whether the + emoji is animated or not. + static_format: Optional[:class:`str`] + Format to attempt to convert only non-animated emoji's to. + Defaults to 'png' + + Raises + ------- + InvalidArgument + Bad image format passed to ``format`` or ``static_format``. + + Returns + -------- + :class:`Asset` + The resulting CDN asset. + """ + return Asset._from_emoji(self._state, self, format=format, static_format=static_format) + + + def is_usable(self): + """:class:`bool`: Whether the bot can use this emoji. + + .. versionadded:: 1.3 + """ + if not self.available: + return False + if not self._roles: + return True + emoji_roles, my_roles = self._roles, self.guild.me._roles + return any(my_roles.has(role_id) for role_id in emoji_roles) + + async def delete(self, *, reason=None): + """|coro| + + Deletes the custom emoji. + + You must have :attr:`~Permissions.manage_emojis` permission to + do this. + + Parameters + ----------- + reason: Optional[:class:`str`] + The reason for deleting this emoji. Shows up on the audit log. + + Raises + ------- + Forbidden + You are not allowed to delete emojis. + HTTPException + An error occurred deleting the emoji. + """ + + await self._state.http.delete_custom_emoji(self.guild.id, self.id, reason=reason) + + async def edit(self, *, name=None, roles=None, reason=None): + r"""|coro| + + Edits the custom emoji. + + You must have :attr:`~Permissions.manage_emojis` permission to + do this. + + Parameters + ----------- + name: :class:`str` + The new emoji name. + roles: Optional[list[:class:`Role`]] + A :class:`list` of :class:`Role`\s that can use this emoji. Leave empty to make it available to everyone. + reason: Optional[:class:`str`] + The reason for editing this emoji. Shows up on the audit log. + + Raises + ------- + Forbidden + You are not allowed to edit emojis. + HTTPException + An error occurred editing the emoji. + """ + + name = name or self.name + if roles: + roles = [role.id for role in roles] + await self._state.http.edit_custom_emoji(self.guild.id, self.id, name=name, roles=roles, reason=reason) diff --git a/venv/lib64/python3.8/site-packages/discord/enums.py b/venv/lib64/python3.8/site-packages/discord/enums.py new file mode 100644 index 0000000..91592a6 --- /dev/null +++ b/venv/lib64/python3.8/site-packages/discord/enums.py @@ -0,0 +1,471 @@ +# -*- coding: utf-8 -*- + +""" +The MIT License (MIT) + +Copyright (c) 2015-present Rapptz + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. +""" + +import types +from collections import namedtuple + +__all__ = ( + 'Enum', + 'ChannelType', + 'MessageType', + 'VoiceRegion', + 'SpeakingState', + 'VerificationLevel', + 'ContentFilter', + 'Status', + 'DefaultAvatar', + 'RelationshipType', + 'AuditLogAction', + 'AuditLogActionCategory', + 'UserFlags', + 'ActivityType', + 'HypeSquadHouse', + 'NotificationLevel', + 'PremiumType', + 'UserContentFilter', + 'FriendFlags', + 'TeamMembershipState', + 'Theme', + 'WebhookType', + 'ExpireBehaviour', + 'ExpireBehavior', + 'StickerType', +) + +def _create_value_cls(name): + cls = namedtuple('_EnumValue_' + name, 'name value') + cls.__repr__ = lambda self: '<%s.%s: %r>' % (name, self.name, self.value) + cls.__str__ = lambda self: '%s.%s' % (name, self.name) + return cls + +def _is_descriptor(obj): + return hasattr(obj, '__get__') or hasattr(obj, '__set__') or hasattr(obj, '__delete__') + +class EnumMeta(type): + def __new__(cls, name, bases, attrs): + value_mapping = {} + member_mapping = {} + member_names = [] + + value_cls = _create_value_cls(name) + for key, value in list(attrs.items()): + is_descriptor = _is_descriptor(value) + if key[0] == '_' and not is_descriptor: + continue + + # Special case classmethod to just pass through + if isinstance(value, classmethod): + continue + + if is_descriptor: + setattr(value_cls, key, value) + del attrs[key] + continue + + try: + new_value = value_mapping[value] + except KeyError: + new_value = value_cls(name=key, value=value) + value_mapping[value] = new_value + member_names.append(key) + + member_mapping[key] = new_value + attrs[key] = new_value + + attrs['_enum_value_map_'] = value_mapping + attrs['_enum_member_map_'] = member_mapping + attrs['_enum_member_names_'] = member_names + actual_cls = super().__new__(cls, name, bases, attrs) + value_cls._actual_enum_cls_ = actual_cls + return actual_cls + + def __iter__(cls): + return (cls._enum_member_map_[name] for name in cls._enum_member_names_) + + def __reversed__(cls): + return (cls._enum_member_map_[name] for name in reversed(cls._enum_member_names_)) + + def __len__(cls): + return len(cls._enum_member_names_) + + def __repr__(cls): + return '' % cls.__name__ + + @property + def __members__(cls): + return types.MappingProxyType(cls._enum_member_map_) + + def __call__(cls, value): + try: + return cls._enum_value_map_[value] + except (KeyError, TypeError): + raise ValueError("%r is not a valid %s" % (value, cls.__name__)) + + def __getitem__(cls, key): + return cls._enum_member_map_[key] + + def __setattr__(cls, name, value): + raise TypeError('Enums are immutable.') + + def __delattr__(cls, attr): + raise TypeError('Enums are immutable') + + def __instancecheck__(self, instance): + # isinstance(x, Y) + # -> __instancecheck__(Y, x) + try: + return instance._actual_enum_cls_ is self + except AttributeError: + return False + +class Enum(metaclass=EnumMeta): + @classmethod + def try_value(cls, value): + try: + return cls._enum_value_map_[value] + except (KeyError, TypeError): + return value + + +class ChannelType(Enum): + text = 0 + private = 1 + voice = 2 + group = 3 + category = 4 + news = 5 + store = 6 + stage_voice = 13 + + def __str__(self): + return self.name + +class MessageType(Enum): + default = 0 + recipient_add = 1 + recipient_remove = 2 + call = 3 + channel_name_change = 4 + channel_icon_change = 5 + pins_add = 6 + new_member = 7 + premium_guild_subscription = 8 + premium_guild_tier_1 = 9 + premium_guild_tier_2 = 10 + premium_guild_tier_3 = 11 + channel_follow_add = 12 + guild_stream = 13 + guild_discovery_disqualified = 14 + guild_discovery_requalified = 15 + guild_discovery_grace_period_initial_warning = 16 + guild_discovery_grace_period_final_warning = 17 + +class VoiceRegion(Enum): + us_west = 'us-west' + us_east = 'us-east' + us_south = 'us-south' + us_central = 'us-central' + eu_west = 'eu-west' + eu_central = 'eu-central' + singapore = 'singapore' + london = 'london' + sydney = 'sydney' + amsterdam = 'amsterdam' + frankfurt = 'frankfurt' + brazil = 'brazil' + hongkong = 'hongkong' + russia = 'russia' + japan = 'japan' + southafrica = 'southafrica' + south_korea = 'south-korea' + india = 'india' + europe = 'europe' + dubai = 'dubai' + vip_us_east = 'vip-us-east' + vip_us_west = 'vip-us-west' + vip_amsterdam = 'vip-amsterdam' + + def __str__(self): + return self.value + +class SpeakingState(Enum): + none = 0 + voice = 1 + soundshare = 2 + priority = 4 + + def __str__(self): + return self.name + + def __int__(self): + return self.value + +class VerificationLevel(Enum): + none = 0 + low = 1 + medium = 2 + high = 3 + table_flip = 3 + extreme = 4 + double_table_flip = 4 + very_high = 4 + + def __str__(self): + return self.name + +class ContentFilter(Enum): + disabled = 0 + no_role = 1 + all_members = 2 + + def __str__(self): + return self.name + +class UserContentFilter(Enum): + disabled = 0 + friends = 1 + all_messages = 2 + +class FriendFlags(Enum): + noone = 0 + mutual_guilds = 1 + mutual_friends = 2 + guild_and_friends = 3 + everyone = 4 + +class Theme(Enum): + light = 'light' + dark = 'dark' + +class Status(Enum): + online = 'online' + offline = 'offline' + idle = 'idle' + dnd = 'dnd' + do_not_disturb = 'dnd' + invisible = 'invisible' + + def __str__(self): + return self.value + +class DefaultAvatar(Enum): + blurple = 0 + grey = 1 + gray = 1 + green = 2 + orange = 3 + red = 4 + + def __str__(self): + return self.name + +class RelationshipType(Enum): + friend = 1 + blocked = 2 + incoming_request = 3 + outgoing_request = 4 + +class NotificationLevel(Enum): + all_messages = 0 + only_mentions = 1 + +class AuditLogActionCategory(Enum): + create = 1 + delete = 2 + update = 3 + +class AuditLogAction(Enum): + guild_update = 1 + channel_create = 10 + channel_update = 11 + channel_delete = 12 + overwrite_create = 13 + overwrite_update = 14 + overwrite_delete = 15 + kick = 20 + member_prune = 21 + ban = 22 + unban = 23 + member_update = 24 + member_role_update = 25 + member_move = 26 + member_disconnect = 27 + bot_add = 28 + role_create = 30 + role_update = 31 + role_delete = 32 + invite_create = 40 + invite_update = 41 + invite_delete = 42 + webhook_create = 50 + webhook_update = 51 + webhook_delete = 52 + emoji_create = 60 + emoji_update = 61 + emoji_delete = 62 + message_delete = 72 + message_bulk_delete = 73 + message_pin = 74 + message_unpin = 75 + integration_create = 80 + integration_update = 81 + integration_delete = 82 + + @property + def category(self): + lookup = { + AuditLogAction.guild_update: AuditLogActionCategory.update, + AuditLogAction.channel_create: AuditLogActionCategory.create, + AuditLogAction.channel_update: AuditLogActionCategory.update, + AuditLogAction.channel_delete: AuditLogActionCategory.delete, + AuditLogAction.overwrite_create: AuditLogActionCategory.create, + AuditLogAction.overwrite_update: AuditLogActionCategory.update, + AuditLogAction.overwrite_delete: AuditLogActionCategory.delete, + AuditLogAction.kick: None, + AuditLogAction.member_prune: None, + AuditLogAction.ban: None, + AuditLogAction.unban: None, + AuditLogAction.member_update: AuditLogActionCategory.update, + AuditLogAction.member_role_update: AuditLogActionCategory.update, + AuditLogAction.member_move: None, + AuditLogAction.member_disconnect: None, + AuditLogAction.bot_add: None, + AuditLogAction.role_create: AuditLogActionCategory.create, + AuditLogAction.role_update: AuditLogActionCategory.update, + AuditLogAction.role_delete: AuditLogActionCategory.delete, + AuditLogAction.invite_create: AuditLogActionCategory.create, + AuditLogAction.invite_update: AuditLogActionCategory.update, + AuditLogAction.invite_delete: AuditLogActionCategory.delete, + AuditLogAction.webhook_create: AuditLogActionCategory.create, + AuditLogAction.webhook_update: AuditLogActionCategory.update, + AuditLogAction.webhook_delete: AuditLogActionCategory.delete, + AuditLogAction.emoji_create: AuditLogActionCategory.create, + AuditLogAction.emoji_update: AuditLogActionCategory.update, + AuditLogAction.emoji_delete: AuditLogActionCategory.delete, + AuditLogAction.message_delete: AuditLogActionCategory.delete, + AuditLogAction.message_bulk_delete: AuditLogActionCategory.delete, + AuditLogAction.message_pin: None, + AuditLogAction.message_unpin: None, + AuditLogAction.integration_create: AuditLogActionCategory.create, + AuditLogAction.integration_update: AuditLogActionCategory.update, + AuditLogAction.integration_delete: AuditLogActionCategory.delete, + } + return lookup[self] + + @property + def target_type(self): + v = self.value + if v == -1: + return 'all' + elif v < 10: + return 'guild' + elif v < 20: + return 'channel' + elif v < 30: + return 'user' + elif v < 40: + return 'role' + elif v < 50: + return 'invite' + elif v < 60: + return 'webhook' + elif v < 70: + return 'emoji' + elif v == 73: + return 'channel' + elif v < 80: + return 'message' + elif v < 90: + return 'integration' + +class UserFlags(Enum): + staff = 1 + partner = 2 + hypesquad = 4 + bug_hunter = 8 + mfa_sms = 16 + premium_promo_dismissed = 32 + hypesquad_bravery = 64 + hypesquad_brilliance = 128 + hypesquad_balance = 256 + early_supporter = 512 + team_user = 1024 + system = 4096 + has_unread_urgent_messages = 8192 + bug_hunter_level_2 = 16384 + verified_bot = 65536 + verified_bot_developer = 131072 + +class ActivityType(Enum): + unknown = -1 + playing = 0 + streaming = 1 + listening = 2 + watching = 3 + custom = 4 + competing = 5 + + def __int__(self): + return self.value + +class HypeSquadHouse(Enum): + bravery = 1 + brilliance = 2 + balance = 3 + +class PremiumType(Enum): + nitro_classic = 1 + nitro = 2 + +class TeamMembershipState(Enum): + invited = 1 + accepted = 2 + +class WebhookType(Enum): + incoming = 1 + channel_follower = 2 + +class ExpireBehaviour(Enum): + remove_role = 0 + kick = 1 + +ExpireBehavior = ExpireBehaviour + +class StickerType(Enum): + png = 1 + apng = 2 + lottie = 3 + +def try_enum(cls, val): + """A function that tries to turn the value into enum ``cls``. + + If it fails it returns the value instead. + """ + + try: + return cls._enum_value_map_[val] + except (KeyError, TypeError, AttributeError): + return val diff --git a/venv/lib64/python3.8/site-packages/discord/errors.py b/venv/lib64/python3.8/site-packages/discord/errors.py new file mode 100644 index 0000000..7247051 --- /dev/null +++ b/venv/lib64/python3.8/site-packages/discord/errors.py @@ -0,0 +1,201 @@ +# -*- coding: utf-8 -*- + +""" +The MIT License (MIT) + +Copyright (c) 2015-present Rapptz + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. +""" + +class DiscordException(Exception): + """Base exception class for discord.py + + Ideally speaking, this could be caught to handle any exceptions thrown from this library. + """ + pass + +class ClientException(DiscordException): + """Exception that's thrown when an operation in the :class:`Client` fails. + + These are usually for exceptions that happened due to user input. + """ + pass + +class NoMoreItems(DiscordException): + """Exception that is thrown when an async iteration operation has no more + items.""" + pass + +class GatewayNotFound(DiscordException): + """An exception that is usually thrown when the gateway hub + for the :class:`Client` websocket is not found.""" + def __init__(self): + message = 'The gateway to connect to discord was not found.' + super(GatewayNotFound, self).__init__(message) + +def flatten_error_dict(d, key=''): + items = [] + for k, v in d.items(): + new_key = key + '.' + k if key else k + + if isinstance(v, dict): + try: + _errors = v['_errors'] + except KeyError: + items.extend(flatten_error_dict(v, new_key).items()) + else: + items.append((new_key, ' '.join(x.get('message', '') for x in _errors))) + else: + items.append((new_key, v)) + + return dict(items) + +class HTTPException(DiscordException): + """Exception that's thrown when an HTTP request operation fails. + + Attributes + ------------ + response: :class:`aiohttp.ClientResponse` + The response of the failed HTTP request. This is an + instance of :class:`aiohttp.ClientResponse`. In some cases + this could also be a :class:`requests.Response`. + + text: :class:`str` + The text of the error. Could be an empty string. + status: :class:`int` + The status code of the HTTP request. + code: :class:`int` + The Discord specific error code for the failure. + """ + + def __init__(self, response, message): + self.response = response + self.status = response.status + if isinstance(message, dict): + self.code = message.get('code', 0) + base = message.get('message', '') + errors = message.get('errors') + if errors: + errors = flatten_error_dict(errors) + helpful = '\n'.join('In %s: %s' % t for t in errors.items()) + self.text = base + '\n' + helpful + else: + self.text = base + else: + self.text = message + self.code = 0 + + fmt = '{0.status} {0.reason} (error code: {1})' + if len(self.text): + fmt += ': {2}' + + super().__init__(fmt.format(self.response, self.code, self.text)) + +class Forbidden(HTTPException): + """Exception that's thrown for when status code 403 occurs. + + Subclass of :exc:`HTTPException` + """ + pass + +class NotFound(HTTPException): + """Exception that's thrown for when status code 404 occurs. + + Subclass of :exc:`HTTPException` + """ + pass + +class DiscordServerError(HTTPException): + """Exception that's thrown for when a 500 range status code occurs. + + Subclass of :exc:`HTTPException`. + + .. versionadded:: 1.5 + """ + pass + +class InvalidData(ClientException): + """Exception that's raised when the library encounters unknown + or invalid data from Discord. + """ + pass + +class InvalidArgument(ClientException): + """Exception that's thrown when an argument to a function + is invalid some way (e.g. wrong value or wrong type). + + This could be considered the analogous of ``ValueError`` and + ``TypeError`` except inherited from :exc:`ClientException` and thus + :exc:`DiscordException`. + """ + pass + +class LoginFailure(ClientException): + """Exception that's thrown when the :meth:`Client.login` function + fails to log you in from improper credentials or some other misc. + failure. + """ + pass + +class ConnectionClosed(ClientException): + """Exception that's thrown when the gateway connection is + closed for reasons that could not be handled internally. + + Attributes + ----------- + code: :class:`int` + The close code of the websocket. + reason: :class:`str` + The reason provided for the closure. + shard_id: Optional[:class:`int`] + The shard ID that got closed if applicable. + """ + def __init__(self, socket, *, shard_id, code=None): + # This exception is just the same exception except + # reconfigured to subclass ClientException for users + self.code = code or socket.close_code + # aiohttp doesn't seem to consistently provide close reason + self.reason = '' + self.shard_id = shard_id + super().__init__('Shard ID %s WebSocket closed with %s' % (self.shard_id, self.code)) + +class PrivilegedIntentsRequired(ClientException): + """Exception that's thrown when the gateway is requesting privileged intents + but they're not ticked in the developer page yet. + + Go to https://discord.com/developers/applications/ and enable the intents + that are required. Currently these are as follows: + + - :attr:`Intents.members` + - :attr:`Intents.presences` + + Attributes + ----------- + shard_id: Optional[:class:`int`] + The shard ID that got closed if applicable. + """ + + def __init__(self, shard_id): + self.shard_id = shard_id + msg = 'Shard ID %s is requesting privileged intents that have not been explicitly enabled in the ' \ + 'developer portal. It is recommended to go to https://discord.com/developers/applications/ ' \ + 'and explicitly enable the privileged intents within your application\'s page. If this is not ' \ + 'possible, then consider disabling the privileged intents instead.' + super().__init__(msg % shard_id) diff --git a/venv/lib64/python3.8/site-packages/discord/ext/commands/__init__.py b/venv/lib64/python3.8/site-packages/discord/ext/commands/__init__.py new file mode 100644 index 0000000..6f356c5 --- /dev/null +++ b/venv/lib64/python3.8/site-packages/discord/ext/commands/__init__.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- + +""" +discord.ext.commands +~~~~~~~~~~~~~~~~~~~~~ + +An extension module to facilitate creation of bot commands. + +:copyright: (c) 2015-present Rapptz +:license: MIT, see LICENSE for more details. +""" + +from .bot import Bot, AutoShardedBot, when_mentioned, when_mentioned_or +from .context import Context +from .core import * +from .errors import * +from .help import * +from .converter import * +from .cooldowns import * +from .cog import * diff --git a/venv/lib64/python3.8/site-packages/discord/ext/commands/__pycache__/__init__.cpython-38.pyc b/venv/lib64/python3.8/site-packages/discord/ext/commands/__pycache__/__init__.cpython-38.pyc new file mode 100644 index 0000000..1ed152d Binary files /dev/null and b/venv/lib64/python3.8/site-packages/discord/ext/commands/__pycache__/__init__.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/discord/ext/commands/__pycache__/_types.cpython-38.pyc b/venv/lib64/python3.8/site-packages/discord/ext/commands/__pycache__/_types.cpython-38.pyc new file mode 100644 index 0000000..4e9fa62 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/discord/ext/commands/__pycache__/_types.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/discord/ext/commands/__pycache__/bot.cpython-38.pyc b/venv/lib64/python3.8/site-packages/discord/ext/commands/__pycache__/bot.cpython-38.pyc new file mode 100644 index 0000000..68935a6 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/discord/ext/commands/__pycache__/bot.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/discord/ext/commands/__pycache__/cog.cpython-38.pyc b/venv/lib64/python3.8/site-packages/discord/ext/commands/__pycache__/cog.cpython-38.pyc new file mode 100644 index 0000000..3e45740 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/discord/ext/commands/__pycache__/cog.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/discord/ext/commands/__pycache__/context.cpython-38.pyc b/venv/lib64/python3.8/site-packages/discord/ext/commands/__pycache__/context.cpython-38.pyc new file mode 100644 index 0000000..e37661a Binary files /dev/null and b/venv/lib64/python3.8/site-packages/discord/ext/commands/__pycache__/context.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/discord/ext/commands/__pycache__/converter.cpython-38.pyc b/venv/lib64/python3.8/site-packages/discord/ext/commands/__pycache__/converter.cpython-38.pyc new file mode 100644 index 0000000..f4db8c2 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/discord/ext/commands/__pycache__/converter.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/discord/ext/commands/__pycache__/cooldowns.cpython-38.pyc b/venv/lib64/python3.8/site-packages/discord/ext/commands/__pycache__/cooldowns.cpython-38.pyc new file mode 100644 index 0000000..0cd4fa1 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/discord/ext/commands/__pycache__/cooldowns.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/discord/ext/commands/__pycache__/core.cpython-38.pyc b/venv/lib64/python3.8/site-packages/discord/ext/commands/__pycache__/core.cpython-38.pyc new file mode 100644 index 0000000..c21afd6 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/discord/ext/commands/__pycache__/core.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/discord/ext/commands/__pycache__/errors.cpython-38.pyc b/venv/lib64/python3.8/site-packages/discord/ext/commands/__pycache__/errors.cpython-38.pyc new file mode 100644 index 0000000..6164790 Binary files /dev/null and b/venv/lib64/python3.8/site-packages/discord/ext/commands/__pycache__/errors.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/discord/ext/commands/__pycache__/help.cpython-38.pyc b/venv/lib64/python3.8/site-packages/discord/ext/commands/__pycache__/help.cpython-38.pyc new file mode 100644 index 0000000..466a56a Binary files /dev/null and b/venv/lib64/python3.8/site-packages/discord/ext/commands/__pycache__/help.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/discord/ext/commands/__pycache__/view.cpython-38.pyc b/venv/lib64/python3.8/site-packages/discord/ext/commands/__pycache__/view.cpython-38.pyc new file mode 100644 index 0000000..e1cd87b Binary files /dev/null and b/venv/lib64/python3.8/site-packages/discord/ext/commands/__pycache__/view.cpython-38.pyc differ diff --git a/venv/lib64/python3.8/site-packages/discord/ext/commands/_types.py b/venv/lib64/python3.8/site-packages/discord/ext/commands/_types.py new file mode 100644 index 0000000..36d0efc --- /dev/null +++ b/venv/lib64/python3.8/site-packages/discord/ext/commands/_types.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- + +""" +The MIT License (MIT) + +Copyright (c) 2015-present Rapptz + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. +""" + +# This is merely a tag type to avoid circular import issues. +# Yes, this is a terrible solution but ultimately it is the only solution. +class _BaseCommand: + __slots__ = () diff --git a/venv/lib64/python3.8/site-packages/discord/ext/commands/bot.py b/venv/lib64/python3.8/site-packages/discord/ext/commands/bot.py new file mode 100644 index 0000000..ee0308e --- /dev/null +++ b/venv/lib64/python3.8/site-packages/discord/ext/commands/bot.py @@ -0,0 +1,1061 @@ +# -*- coding: utf-8 -*- + +""" +The MIT License (MIT) + +Copyright (c) 2015-present Rapptz + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. +""" + +import asyncio +import collections +import inspect +import importlib.util +import sys +import traceback +import types + +import discord + +from .core import GroupMixin +from .view import StringView +from .context import Context +from . import errors +from .help import HelpCommand, DefaultHelpCommand +from .cog import Cog + +def when_mentioned(bot, msg): + """A callable that implements a command prefix equivalent to being mentioned. + + These are meant to be passed into the :attr:`.Bot.command_prefix` attribute. + """ + return [bot.user.mention + ' ', '<@!%s> ' % bot.user.id] + +def when_mentioned_or(*prefixes): + """A callable that implements when mentioned or other prefixes provided. + + These are meant to be passed into the :attr:`.Bot.command_prefix` attribute. + + Example + -------- + + .. code-block:: python3 + + bot = commands.Bot(command_prefix=commands.when_mentioned_or('!')) + + + .. note:: + + This callable returns another callable, so if this is done inside a custom + callable, you must call the returned callable, for example: + + .. code-block:: python3 + + async def get_prefix(bot, message): + extras = await prefixes_for(message.guild) # returns a list + return commands.when_mentioned_or(*extras)(bot, message) + + + See Also + ---------- + :func:`.when_mentioned` + """ + def inner(bot, msg): + r = list(prefixes) + r = when_mentioned(bot, msg) + r + return r + + return inner + +def _is_submodule(parent, child): + return parent == child or child.startswith(parent + ".") + +class _DefaultRepr: + def __repr__(self): + return '' + +_default = _DefaultRepr() + +class BotBase(GroupMixin): + def __init__(self, command_prefix, help_command=_default, description=None, **options): + super().__init__(**options) + self.command_prefix = command_prefix + self.extra_events = {} + self.__cogs = {} + self.__extensions = {} + self._checks = [] + self._check_once = [] + self._before_invoke = None + self._after_invoke = None + self._help_command = None + self.description = inspect.cleandoc(description) if description else '' + self.owner_id = options.get('owner_id') + self.owner_ids = options.get('owner_ids', set()) + self.strip_after_prefix = options.get('strip_after_prefix', False) + + if self.owner_id and self.owner_ids: + raise TypeError('Both owner_id and owner_ids are set.') + + if self.owner_ids and not isinstance(self.owner_ids, collections.abc.Collection): + raise TypeError('owner_ids must be a collection not {0.__class__!r}'.format(self.owner_ids)) + + if options.pop('self_bot', False): + self._skip_check = lambda x, y: x != y + else: + self._skip_check = lambda x, y: x == y + + if help_command is _default: + self.help_command = DefaultHelpCommand() + else: + self.help_command = help_command + + # internal helpers + + def dispatch(self, event_name, *args, **kwargs): + super().dispatch(event_name, *args, **kwargs) + ev = 'on_' + event_name + for event in self.extra_events.get(ev, []): + self._schedule_event(event, ev, *args, **kwargs) + + async def close(self): + for extension in tuple(self.__extensions): + try: + self.unload_extension(extension) + except Exception: + pass + + for cog in tuple(self.__cogs): + try: + self.remove_cog(cog) + except Exception: + pass + + await super().close() + + async def on_command_error(self, context, exception): + """|coro| + + The default command error handler provided by the bot. + + By default this prints to :data:`sys.stderr` however it could be + overridden to have a different implementation. + + This only fires if you do not specify any listeners for command error. + """ + if self.extra_events.get('on_command_error', None): + return + + if hasattr(context.command, 'on_error'): + return + + cog = context.cog + if cog and Cog._get_overridden_method(cog.cog_command_error) is not None: + return + + print('Ignoring exception in command {}:'.format(context.command), file=sys.stderr) + traceback.print_exception(type(exception), exception, exception.__traceback__, file=sys.stderr) + + # global check registration + + def check(self, func): + r"""A decorator that adds a global check to the bot. + + A global check is similar to a :func:`.check` that is applied + on a per command basis except it is run before any command checks + have been verified and applies to every command the bot has. + + .. note:: + + This function can either be a regular function or a coroutine. + + Similar to a command :func:`.check`\, this takes a single parameter + of type :class:`.Context` and can only raise exceptions inherited from + :exc:`.CommandError`. + + Example + --------- + + .. code-block:: python3 + + @bot.check + def check_commands(ctx): + return ctx.command.qualified_name in allowed_commands + + """ + self.add_check(func) + return func + + def add_check(self, func, *, call_once=False): + """Adds a global check to the bot. + + This is the non-decorator interface to :meth:`.check` + and :meth:`.check_once`. + + Parameters + ----------- + func + The function that was used as a global check. + call_once: :class:`bool` + If the function should only be called once per + :meth:`.Command.invoke` call. + """ + + if call_once: + self._check_once.append(func) + else: + self._checks.append(func) + + def remove_check(self, func, *, call_once=False): + """Removes a global check from the bot. + + This function is idempotent and will not raise an exception + if the function is not in the global checks. + + Parameters + ----------- + func + The function to remove from the global checks. + call_once: :class:`bool` + If the function was added with ``call_once=True`` in + the :meth:`.Bot.add_check` call or using :meth:`.check_once`. + """ + l = self._check_once if call_once else self._checks + + try: + l.remove(func) + except ValueError: + pass + + def check_once(self, func): + r"""A decorator that adds a "call once" global check to the bot. + + Unlike regular global checks, this one is called only once + per :meth:`.Command.invoke` call. + + Regular global checks are called whenever a command is called + or :meth:`.Command.can_run` is called. This type of check + bypasses that and ensures that it's called only once, even inside + the default help command. + + .. note:: + + When using this function the :class:`.Context` sent to a group subcommand + may only parse the parent command and not the subcommands due to it + being invoked once per :meth:`.Bot.invoke` call. + + .. note:: + + This function can either be a regular function or a coroutine. + + Similar to a command :func:`.check`\, this takes a single parameter + of type :class:`.Context` and can only raise exceptions inherited from + :exc:`.CommandError`. + + Example + --------- + + .. code-block:: python3 + + @bot.check_once + def whitelist(ctx): + return ctx.message.author.id in my_whitelist + + """ + self.add_check(func, call_once=True) + return func + + async def can_run(self, ctx, *, call_once=False): + data = self._check_once if call_once else self._checks + + if len(data) == 0: + return True + + return await discord.utils.async_all(f(ctx) for f in data) + + async def is_owner(self, user): + """|coro| + + Checks if a :class:`~discord.User` or :class:`~discord.Member` is the owner of + this bot. + + If an :attr:`owner_id` is not set, it is fetched automatically + through the use of :meth:`~.Bot.application_info`. + + .. versionchanged:: 1.3 + The function also checks if the application is team-owned if + :attr:`owner_ids` is not set. + + Parameters + ----------- + user: :class:`.abc.User` + The user to check for. + + Returns + -------- + :class:`bool` + Whether the user is the owner. + """ + + if self.owner_id: + return user.id == self.owner_id + elif self.owner_ids: + return user.id in self.owner_ids + else: + app = await self.application_info() + if app.team: + self.owner_ids = ids = {m.id for m in app.team.members} + return user.id in ids + else: + self.owner_id = owner_id = app.owner.id + return user.id == owner_id + + def before_invoke(self, coro): + """A decorator that registers a coroutine as a pre-invoke hook. + + A pre-invoke hook is called directly before the command is + called. This makes it a useful function to set up database + connections or any type of set up required. + + This pre-invoke hook takes a sole parameter, a :class:`.Context`. + + .. note:: + + The :meth:`~.Bot.before_invoke` and :meth:`~.Bot.after_invoke` hooks are + only called if all checks and argument parsing procedures pass + without error. If any check or argument parsing procedures fail + then the hooks are not called. + + Parameters + ----------- + coro: :ref:`coroutine ` + The coroutine to register as the pre-invoke hook. + + Raises + ------- + TypeError + The coroutine passed is not actually a coroutine. + """ + if not asyncio.iscoroutinefunction(coro): + raise TypeError('The pre-invoke hook must be a coroutine.') + + self._before_invoke = coro + return coro + + def after_invoke(self, coro): + r"""A decorator that registers a coroutine as a post-invoke hook. + + A post-invoke hook is called directly after the command is + called. This makes it a useful function to clean-up database + connections or any type of clean up required. + + This post-invoke hook takes a sole parameter, a :class:`.Context`. + + .. note:: + + Similar to :meth:`~.Bot.before_invoke`\, this is not called unless + checks and argument parsing procedures succeed. This hook is, + however, **always** called regardless of the internal command + callback raising an error (i.e. :exc:`.CommandInvokeError`\). + This makes it ideal for clean-up scenarios. + + Parameters + ----------- + coro: :ref:`coroutine ` + The coroutine to register as the post-invoke hook. + + Raises + ------- + TypeError + The coroutine passed is not actually a coroutine. + """ + if not asyncio.iscoroutinefunction(coro): + raise TypeError('The post-invoke hook must be a coroutine.') + + self._after_invoke = coro + return coro + + # listener registration + + def add_listener(self, func, name=None): + """The non decorator alternative to :meth:`.listen`. + + Parameters + ----------- + func: :ref:`coroutine ` + The function to call. + name: Optional[:class:`str`] + The name of the event to listen for. Defaults to ``func.__name__``. + + Example + -------- + + .. code-block:: python3 + + async def on_ready(): pass + async def my_message(message): pass + + bot.add_listener(on_ready) + bot.add_listener(my_message, 'on_message') + + """ + name = func.__name__ if name is None else name + + if not asyncio.iscoroutinefunction(func): + raise TypeError('Listeners must be coroutines') + + if name in self.extra_events: + self.extra_events[name].append(func) + else: + self.extra_events[name] = [func] + + def remove_listener(self, func, name=None): + """Removes a listener from the pool of listeners. + + Parameters + ----------- + func + The function that was used as a listener to remove. + name: :class:`str` + The name of the event we want to remove. Defaults to + ``func.__name__``. + """ + + name = func.__name__ if name is None else name + + if name in self.extra_events: + try: + self.extra_events[name].remove(func) + except ValueError: + pass + + def listen(self, name=None): + """A decorator that registers another function as an external + event listener. Basically this allows you to listen to multiple + events from different places e.g. such as :func:`.on_ready` + + The functions being listened to must be a :ref:`coroutine `. + + Example + -------- + + .. code-block:: python3 + + @bot.listen() + async def on_message(message): + print('one') + + # in some other file... + + @bot.listen('on_message') + async def my_message(message): + print('two') + + Would print one and two in an unspecified order. + + Raises + ------- + TypeError + The function being listened to is not a coroutine. + """ + + def decorator(func): + self.add_listener(func, name) + return func + + return decorator + + # cogs + + def add_cog(self, cog): + """Adds a "cog" to the bot. + + A cog is a class that has its own event listeners and commands. + + Parameters + ----------- + cog: :class:`.Cog` + The cog to register to the bot. + + Raises + ------- + TypeError + The cog does not inherit from :class:`.Cog`. + CommandError + An error happened during loading. + """ + + if not isinstance(cog, Cog): + raise TypeError('cogs must derive from Cog') + + cog = cog._inject(self) + self.__cogs[cog.__cog_name__] = cog + + def get_cog(self, name): + """Gets the cog instance requested. + + If the cog is not found, ``None`` is returned instead. + + Parameters + ----------- + name: :class:`str` + The name of the cog you are requesting. + This is equivalent to the name passed via keyword + argument in class creation or the class name if unspecified. + + Returns + -------- + Optional[:class:`Cog`] + The cog that was requested. If not found, returns ``None``. + """ + return self.__cogs.get(name) + + def remove_cog(self, name): + """Removes a cog from the bot. + + All registered commands and event listeners that the + cog has registered will be removed as well. + + If no cog is found then this method has no effect. + + Parameters + ----------- + name: :class:`str` + The name of the cog to remove. + """ + + cog = self.__cogs.pop(name, None) + if cog is None: + return + + help_command = self._help_command + if help_command and help_command.cog is cog: + help_command.cog = None + cog._eject(self) + + @property + def cogs(self): + """Mapping[:class:`str`, :class:`Cog`]: A read-only mapping of cog name to cog.""" + return types.MappingProxyType(self.__cogs) + + # extensions + + def _remove_module_references(self, name): + # find all references to the module + # remove the cogs registered from the module + for cogname, cog in self.__cogs.copy().items(): + if _is_submodule(name, cog.__module__): + self.remove_cog(cogname) + + # remove all the commands from the module + for cmd in self.all_commands.copy().values(): + if cmd.module is not None and _is_submodule(name, cmd.module): + if isinstance(cmd, GroupMixin): + cmd.recursively_remove_all_commands() + self.remove_command(cmd.name) + + # remove all the listeners from the module + for event_list in self.extra_events.copy().values(): + remove = [] + for index, event in enumerate(event_list): + if event.__module__ is not None and _is_submodule(name, event.__module__): + remove.append(index) + + for index in reversed(remove): + del event_list[index] + + def _call_module_finalizers(self, lib, key): + try: + func = getattr(lib, 'teardown') + except AttributeError: + pass + else: + try: + func(self) + except Exception: + pass + finally: + self.__extensions.pop(key, None) + sys.modules.pop(key, None) + name = lib.__name__ + for module in list(sys.modules.keys()): + if _is_submodule(name, module): + del sys.modules[module] + + def _load_from_module_spec(self, spec, key): + # precondition: key not in self.__extensions + lib = importlib.util.module_from_spec(spec) + sys.modules[key] = lib + try: + spec.loader.exec_module(lib) + except Exception as e: + del sys.modules[key] + raise errors.ExtensionFailed(key, e) from e + + try: + setup = getattr(lib, 'setup') + except AttributeError: + del sys.modules[key] + raise errors.NoEntryPointError(key) + + try: + setup(self) + except Exception as e: + del sys.modules[key] + self._remove_module_references(lib.__name__) + self._call_module_finalizers(lib, key) + raise errors.ExtensionFailed(key, e) from e + else: + self.__extensions[key] = lib + + def _resolve_name(self, name, package): + try: + return importlib.util.resolve_name(name, package) + except ImportError: + raise errors.ExtensionNotFound(name) + + def load_extension(self, name, *, package=None): + """Loads an extension. + + An extension is a python module that contains commands, cogs, or + listeners. + + An extension must have a global function, ``setup`` defined as + the entry point on what to do when the extension is loaded. This entry + point must have a single argument, the ``bot``. + + Parameters + ------------ + name: :class:`str` + The extension name to load. It must be dot separated like + regular Python imports if accessing a sub-module. e.g. + ``foo.test`` if you want to import ``foo/test.py``. + package: Optional[:class:`str`] + The package name to resolve relative imports with. + This is required when loading an extension using a relative path, e.g ``.foo.test``. + Defaults to ``None``. + + .. versionadded:: 1.7 + + Raises + -------- + ExtensionNotFound + The extension could not be imported. + This is also raised if the name of the extension could not + be resolved using the provided ``package`` parameter. + ExtensionAlreadyLoaded + The extension is already loaded. + NoEntryPointError + The extension does not have a setup function. + ExtensionFailed + The extension or its setup function had an execution error. + """ + + name = self._resolve_name(name, package) + if name in self.__extensions: + raise errors.ExtensionAlreadyLoaded(name) + + spec = importlib.util.find_spec(name) + if spec is None: + raise errors.ExtensionNotFound(name) + + self._load_from_module_spec(spec, name) + + def unload_extension(self, name, *, package=None): + """Unloads an extension. + + When the extension is unloaded, all commands, listeners, and cogs are + removed from the bot and the module is un-imported. + + The extension can provide an optional global function, ``teardown``, + to do miscellaneous clean-up if necessary. This function takes a single + parameter, the ``bot``, similar to ``setup`` from + :meth:`~.Bot.load_extension`. + + Parameters + ------------ + name: :class:`str` + The extension name to unload. It must be dot separated like + regular Python imports if accessing a sub-module. e.g. + ``foo.test`` if you want to import ``foo/test.py``. + package: Optional[:class:`str`] + The package name to resolve relative imports with. + This is required when unloading an extension using a relative path, e.g ``.foo.test``. + Defaults to ``None``. + + .. versionadded:: 1.7 + + Raises + ------- + ExtensionNotFound + The name of the extension could not + be resolved using the provided ``package`` parameter. + ExtensionNotLoaded + The extension was not loaded. + """ + + name = self._resolve_name(name, package) + lib = self.__extensions.get(name) + if lib is None: + raise errors.ExtensionNotLoaded(name) + + self._remove_module_references(lib.__name__) + self._call_module_finalizers(lib, name) + + def reload_extension(self, name, *, package=None): + """Atomically reloads an extension. + + This replaces the extension with the same extension, only refreshed. This is + equivalent to a :meth:`unload_extension` followed by a :meth:`load_extension` + except done in an atomic way. That is, if an operation fails mid-reload then + the bot will roll-back to the prior working state. + + Parameters + ------------ + name: :class:`str` + The extension name to reload. It must be dot separated like + regular Python imports if accessing a sub-module. e.g. + ``foo.test`` if you want to import ``foo/test.py``. + package: Optional[:class:`str`] + The package name to resolve relative imports with. + This is required when reloading an extension using a relative path, e.g ``.foo.test``. + Defaults to ``None``. + + .. versionadded:: 1.7 + + Raises + ------- + ExtensionNotLoaded + The extension was not loaded. + ExtensionNotFound + The extension could not be imported. + This is also raised if the name of the extension could not + be resolved using the provided ``package`` parameter. + NoEntryPointError + The extension does not have a setup function. + ExtensionFailed + The extension setup function had an execution error. + """ + + name = self._resolve_name(name, package) + lib = self.__extensions.get(name) + if lib is None: + raise errors.ExtensionNotLoaded(name) + + # get the previous module states from sys modules + modules = { + name: module + for name, module in sys.modules.items() + if _is_submodule(lib.__name__, name) + } + + try: + # Unload and then load the module... + self._remove_module_references(lib.__name__) + self._call_module_finalizers(lib, name) + self.load_extension(name) + except Exception: + # if the load failed, the remnants should have been + # cleaned from the load_extension function call + # so let's load it from our old compiled library. + lib.setup(self) + self.__extensions[name] = lib + + # revert sys.modules back to normal and raise back to caller + sys.modules.update(modules) + raise + + @property + def extensions(self): + """Mapping[:class:`str`, :class:`py:types.ModuleType`]: A read-only mapping of extension name to extension.""" + return types.MappingProxyType(self.__extensions) + + # help command stuff + + @property + def help_command(self): + return self._help_command + + @help_command.setter + def help_command(self, value): + if value is not None: + if not isinstance(value, HelpCommand): + raise TypeError('help_command must be a subclass of HelpCommand') + if self._help_command is not None: + self._help_command._remove_from_bot(self) + self._help_command = value + value._add_to_bot(self) + elif self._help_command is not None: + self._help_command._remove_from_bot(self) + self._help_command = None + else: + self._help_command = None + + # command processing + + async def get_prefix(self, message): + """|coro| + + Retrieves the prefix the bot is listening to + with the message as a context. + + Parameters + ----------- + message: :class:`discord.Message` + The message context to get the prefix of. + + Returns + -------- + Union[List[:class:`str`], :class:`str`] + A list of prefixes or a single prefix that the bot is + listening for. + """ + prefix = ret = self.command_prefix + if callable(prefix): + ret = await discord.utils.maybe_coroutine(prefix, self, message) + + if not isinstance(ret, str): + try: + ret = list(ret) + except TypeError: + # It's possible that a generator raised this exception. Don't + # replace it with our own error if that's the case. + if isinstance(ret, collections.abc.Iterable): + raise + + raise TypeError("command_prefix must be plain string, iterable of strings, or callable " + "returning either of these, not {}".format(ret.__class__.__name__)) + + if not ret: + raise ValueError("Iterable command_prefix must contain at least one prefix") + + return ret + + async def get_context(self, message, *, cls=Context): + r"""|coro| + + Returns the invocation context from the message. + + This is a more low-level counter-part for :meth:`.process_commands` + to allow users more fine grained control over the processing. + + The returned context is not guaranteed to be a valid invocation + context, :attr:`.Context.valid` must be checked to make sure it is. + If the context is not valid then it is not a valid candidate to be + invoked under :meth:`~.Bot.invoke`. + + Parameters + ----------- + message: :class:`discord.Message` + The message to get the invocation context from. + cls + The factory class that will be used to create the context. + By default, this is :class:`.Context`. Should a custom + class be provided, it must be similar enough to :class:`.Context`\'s + interface. + + Returns + -------- + :class:`.Context` + The invocation context. The type of this can change via the + ``cls`` parameter. + """ + + view = StringView(message.content) + ctx = cls(prefix=None, view=view, bot=self, message=message) + + if self._skip_check(message.author.id, self.user.id): + return ctx + + prefix = await self.get_prefix(message) + invoked_prefix = prefix + + if isinstance(prefix, str): + if not view.skip_string(prefix): + return ctx + else: + try: + # if the context class' __init__ consumes something from the view this + # will be wrong. That seems unreasonable though. + if message.content.startswith(tuple(prefix)): + invoked_prefix = discord.utils.find(view.skip_string, prefix) + else: + return ctx + + except TypeError: + if not isinstance(prefix, list): + raise TypeError("get_prefix must return either a string or a list of string, " + "not {}".format(prefix.__class__.__name__)) + + # It's possible a bad command_prefix got us here. + for value in prefix: + if not isinstance(value, str): + raise TypeError("Iterable command_prefix or list returned from get_prefix must " + "contain only strings, not {}".format(value.__class__.__name__)) + + # Getting here shouldn't happen + raise + + if self.strip_after_prefix: + view.skip_ws() + + invoker = view.get_word() + ctx.invoked_with = invoker + ctx.prefix = invoked_prefix + ctx.command = self.all_commands.get(invoker) + return ctx + + async def invoke(self, ctx): + """|coro| + + Invokes the command given under the invocation context and + handles all the internal event dispatch mechanisms. + + Parameters + ----------- + ctx: :class:`.Context` + The invocation context to invoke. + """ + if ctx.command is not None: + self.dispatch('command', ctx) + try: + if await self.can_run(ctx, call_once=True): + await ctx.command.invoke(ctx) + else: + raise errors.CheckFailure('The global check once functions failed.') + except errors.CommandError as exc: + await ctx.command.dispatch_error(ctx, exc) + else: + self.dispatch('command_completion', ctx) + elif ctx.invoked_with: + exc = errors.CommandNotFound('Command "{}" is not found'.format(ctx.invoked_with)) + self.dispatch('command_error', ctx, exc) + + async def process_commands(self, message): + """|coro| + + This function processes the commands that have been registered + to the bot and other groups. Without this coroutine, none of the + commands will be triggered. + + By default, this coroutine is called inside the :func:`.on_message` + event. If you choose to override the :func:`.on_message` event, then + you should invoke this coroutine as well. + + This is built using other low level tools, and is equivalent to a + call to :meth:`~.Bot.get_context` followed by a call to :meth:`~.Bot.invoke`. + + This also checks if the message's author is a bot and doesn't + call :meth:`~.Bot.get_context` or :meth:`~.Bot.invoke` if so. + + Parameters + ----------- + message: :class:`discord.Message` + The message to process commands for. + """ + if message.author.bot: + return + + ctx = await self.get_context(message) + await self.invoke(ctx) + + async def on_message(self, message): + await self.process_commands(message) + +class Bot(BotBase, discord.Client): + """Represents a discord bot. + + This class is a subclass of :class:`discord.Client` and as a result + anything that you can do with a :class:`discord.Client` you can do with + this bot. + + This class also subclasses :class:`.GroupMixin` to provide the functionality + to manage commands. + + Attributes + ----------- + command_prefix + The command prefix is what the message content must contain initially + to have a command invoked. This prefix could either be a string to + indicate what the prefix should be, or a callable that takes in the bot + as its first parameter and :class:`discord.Message` as its second + parameter and returns the prefix. This is to facilitate "dynamic" + command prefixes. This callable can be either a regular function or + a coroutine. + + An empty string as the prefix always matches, enabling prefix-less + command invocation. While this may be useful in DMs it should be avoided + in servers, as it's likely to cause performance issues and unintended + command invocations. + + The command prefix could also be an iterable of strings indicating that + multiple checks for the prefix should be used and the first one to + match will be the invocation prefix. You can get this prefix via + :attr:`.Context.prefix`. To avoid confusion empty iterables are not + allowed. + + .. note:: + + When passing multiple prefixes be careful to not pass a prefix + that matches a longer prefix occurring later in the sequence. For + example, if the command prefix is ``('!', '!?')`` the ``'!?'`` + prefix will never be matched to any message as the previous one + matches messages starting with ``!?``. This is especially important + when passing an empty string, it should always be last as no prefix + after it will be matched. + case_insensitive: :class:`bool` + Whether the commands should be case insensitive. Defaults to ``False``. This + attribute does not carry over to groups. You must set it to every group if + you require group commands to be case insensitive as well. + description: :class:`str` + The content prefixed into the default help message. + self_bot: :class:`bool` + If ``True``, the bot will only listen to commands invoked by itself rather + than ignoring itself. If ``False`` (the default) then the bot will ignore + itself. This cannot be changed once initialised. + help_command: Optional[:class:`.HelpCommand`] + The help command implementation to use. This can be dynamically + set at runtime. To remove the help command pass ``None``. For more + information on implementing a help command, see :ref:`ext_commands_help_command`. + owner_id: Optional[:class:`int`] + The user ID that owns the bot. If this is not set and is then queried via + :meth:`.is_owner` then it is fetched automatically using + :meth:`~.Bot.application_info`. + owner_ids: Optional[Collection[:class:`int`]] + The user IDs that owns the bot. This is similar to :attr:`owner_id`. + If this is not set and the application is team based, then it is + fetched automatically using :meth:`~.Bot.application_info`. + For performance reasons it is recommended to use a :class:`set` + for the collection. You cannot set both ``owner_id`` and ``owner_ids``. + + .. versionadded:: 1.3 + strip_after_prefix: :class:`bool` + Whether to strip whitespace characters after encountering the command + prefix. This allows for ``! hello`` and ``!hello`` to both work if + the ``command_prefix`` is set to ``!``. Defaults to ``False``. + + .. versionadded:: 1.7 + """ + pass + +class AutoShardedBot(BotBase, discord.AutoShardedClient): + """This is similar to :class:`.Bot` except that it is inherited from + :class:`discord.AutoShardedClient` instead. + """ + pass diff --git a/venv/lib64/python3.8/site-packages/discord/ext/commands/cog.py b/venv/lib64/python3.8/site-packages/discord/ext/commands/cog.py new file mode 100644 index 0000000..e12b239 --- /dev/null +++ b/venv/lib64/python3.8/site-packages/discord/ext/commands/cog.py @@ -0,0 +1,451 @@ +# -*- coding: utf-8 -*- + +""" +The MIT License (MIT) + +Copyright (c) 2015-present Rapptz + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. +""" + +import inspect +import copy +from ._types import _BaseCommand + +__all__ = ( + 'CogMeta', + 'Cog', +) + +class CogMeta(type): + """A metaclass for defining a cog. + + Note that you should probably not use this directly. It is exposed + purely for documentation purposes along with making custom metaclasses to intermix + with other metaclasses such as the :class:`abc.ABCMeta` metaclass. + + For example, to create an abstract cog mixin class, the following would be done. + + .. code-block:: python3 + + import abc + + class CogABCMeta(commands.CogMeta, abc.ABCMeta): + pass + + class SomeMixin(metaclass=abc.ABCMeta): + pass + + class SomeCogMixin(SomeMixin, commands.Cog, metaclass=CogABCMeta): + pass + + .. note:: + + When passing an attribute of a metaclass that is documented below, note + that you must pass it as a keyword-only argument to the class creation + like the following example: + + .. code-block:: python3 + + class MyCog(commands.Cog, name='My Cog'): + pass + + Attributes + ----------- + name: :class:`str` + The cog name. By default, it is the name of the class with no modification. + description: :class:`str` + The cog description. By default, it is the cleaned docstring of the class. + + .. versionadded:: 1.6 + + command_attrs: :class:`dict` + A list of attributes to apply to every command inside this cog. The dictionary + is passed into the :class:`Command` options at ``__init__``. + If you specify attributes inside the command attribute in the class, it will + override the one specified inside this attribute. For example: + + .. code-block:: python3 + + class MyCog(commands.Cog, command_attrs=dict(hidden=True)): + @commands.command() + async def foo(self, ctx): + pass # hidden -> True + + @commands.command(hidden=False) + async def bar(self, ctx): + pass # hidden -> False + """ + + def __new__(cls, *args, **kwargs): + name, bases, attrs = args + attrs['__cog_name__'] = kwargs.pop('name', name) + attrs['__cog_settings__'] = kwargs.pop('command_attrs', {}) + + description = kwargs.pop('description', None) + if description is None: + description = inspect.cleandoc(attrs.get('__doc__', '')) + attrs['__cog_description__'] = description + + commands = {} + listeners = {} + no_bot_cog = 'Commands or listeners must not start with cog_ or bot_ (in method {0.__name__}.{1})' + + new_cls = super().__new__(cls, name, bases, attrs, **kwargs) + for base in reversed(new_cls.__mro__): + for elem, value in base.__dict__.items(): + if elem in commands: + del commands[elem] + if elem in listeners: + del listeners[elem] + + is_static_method = isinstance(value, staticmethod) + if is_static_method: + value = value.__func__ + if isinstance(value, _BaseCommand): + if is_static_method: + raise TypeError('Command in method {0}.{1!r} must not be staticmethod.'.format(base, elem)) + if elem.startswith(('cog_', 'bot_')): + raise TypeError(no_bot_cog.format(base, elem)) + commands[elem] = value + elif inspect.iscoroutinefunction(value): + try: + getattr(value, '__cog_listener__') + except AttributeError: + continue + else: + if elem.startswith(('cog_', 'bot_')): + raise TypeError(no_bot_cog.format(base, elem)) + listeners[elem] = value + + new_cls.__cog_commands__ = list(commands.values()) # this will be copied in Cog.__new__ + + listeners_as_list = [] + for listener in listeners.values(): + for listener_name in listener.__cog_listener_names__: + # I use __name__ instead of just storing the value so I can inject + # the self attribute when the time comes to add them to the bot + listeners_as_list.append((listener_name, listener.__name__)) + + new_cls.__cog_listeners__ = listeners_as_list + return new_cls + + def __init__(self, *args, **kwargs): + super().__init__(*args) + + @classmethod + def qualified_name(cls): + return cls.__cog_name__ + +def _cog_special_method(func): + func.__cog_special_method__ = None + return func + +class Cog(metaclass=CogMeta): + """The base class that all cogs must inherit from. + + A cog is a collection of commands, listeners, and optional state to + help group commands together. More information on them can be found on + the :ref:`ext_commands_cogs` page. + + When inheriting from this class, the options shown in :class:`CogMeta` + are equally valid here. + """ + + def __new__(cls, *args, **kwargs): + # For issue 426, we need to store a copy of the command objects + # since we modify them to inject `self` to them. + # To do this, we need to interfere with the Cog creation process. + self = super().__new__(cls) + cmd_attrs = cls.__cog_settings__ + + # Either update the command with the cog provided defaults or copy it. + self.__cog_commands__ = tuple(c._update_copy(cmd_attrs) for c in cls.__cog_commands__) + + lookup = { + cmd.qualified_name: cmd + for cmd in self.__cog_commands__ + } + + # Update the Command instances dynamically as well + for command in self.__cog_commands__: + setattr(self, command.callback.__name__, command) + parent = command.parent + if parent is not None: + # Get the latest parent reference + parent = lookup[parent.qualified_name] + + # Update our parent's reference to our self + parent.remove_command(command.name) + parent.add_command(command) + + return self + + def get_commands(self): + r""" + Returns + -------- + List[:class:`.Command`] + A :class:`list` of :class:`.Command`\s that are + defined inside this cog. + + .. note:: + + This does not include subcommands. + """ + return [c for c in self.__cog_commands__ if c.parent is None] + + @property + def qualified_name(self): + """:class:`str`: Returns the cog's specified name, not the class name.""" + return self.__cog_name__ + + @property + def description(self): + """:class:`str`: Returns the cog's description, typically the cleaned docstring.""" + return self.__cog_description__ + + @description.setter + def description(self, description): + self.__cog_description__ = description + + def walk_commands(self): + """An iterator that recursively walks through this cog's commands and subcommands. + + Yields + ------ + Union[:class:`.Command`, :class:`.Group`] + A command or group from the cog. + """ + from .core import GroupMixin + for command in self.__cog_commands__: + if command.parent is None: + yield command + if isinstance(command, GroupMixin): + yield from command.walk_commands() + + def get_listeners(self): + """Returns a :class:`list` of (name, function) listener pairs that are defined in this cog. + + Returns + -------- + List[Tuple[:class:`str`, :ref:`coroutine `]] + The listeners defined in this cog. + """ + return [(name, getattr(self, method_name)) for name, method_name in self.__cog_listeners__] + + @classmethod + def _get_overridden_method(cls, method): + """Return None if the method is not overridden. Otherwise returns the overridden method.""" + return getattr(method.__func__, '__cog_special_method__', method) + + @classmethod + def listener(cls, name=None): + """A decorator that marks a function as a listener. + + This is the cog equivalent of :meth:`.Bot.listen`. + + Parameters + ------------ + name: :class:`str` + The name of the event being listened to. If not provided, it + defaults to the function's name. + + Raises + -------- + TypeError + The function is not a coroutine function or a string was not passed as + the name. + """ + + if name is not None and not isinstance(name, str): + raise TypeError('Cog.listener expected str but received {0.__class__.__name__!r} instead.'.format(name)) + + def decorator(func): + actual = func + if isinstance(actual, staticmethod): + actual = actual.__func__ + if not inspect.iscoroutinefunction(actual): + raise TypeError('Listener function must be a coroutine function.') + actual.__cog_listener__ = True + to_assign = name or actual.__name__ + try: + actual.__cog_listener_names__.append(to_assign) + except AttributeError: + actual.__cog_listener_names__ = [to_assign] + # we have to return `func` instead of `actual` because + # we need the type to be `staticmethod` for the metaclass + # to pick it up but the metaclass unfurls the function and + # thus the assignments need to be on the actual function + return func + return decorator + + def has_error_handler(self): + """:class:`bool`: Checks whether the cog has an error handler. + + .. versionadded:: 1.7 + """ + return not hasattr(self.cog_command_error.__func__, '__cog_special_method__') + + @_cog_special_method + def cog_unload(self): + """A special method that is called when the cog gets removed. + + This function **cannot** be a coroutine. It must be a regular + function. + + Subclasses must replace this if they want special unloading behaviour. + """ + pass + + @_cog_special_method + def bot_check_once(self, ctx): + """A special method that registers as a :meth:`.Bot.check_once` + check. + + This function **can** be a coroutine and must take a sole parameter, + ``ctx``, to represent the :class:`.Context`. + """ + return True + + @_cog_special_method + def bot_check(self, ctx): + """A special method that registers as a :meth:`.Bot.check` + check. + + This function **can** be a coroutine and must take a sole parameter, + ``ctx``, to represent the :class:`.Context`. + """ + return True + + @_cog_special_method + def cog_check(self, ctx): + """A special method that registers as a :func:`commands.check` + for every command and subcommand in this cog. + + This function **can** be a coroutine and must take a sole parameter, + ``ctx``, to represent the :class:`.Context`. + """ + return True + + @_cog_special_method + async def cog_command_error(self, ctx, error): + """A special method that is called whenever an error + is dispatched inside this cog. + + This is similar to :func:`.on_command_error` except only applying + to the commands inside this cog. + + This **must** be a coroutine. + + Parameters + ----------- + ctx: :class:`.Context` + The invocation context where the error happened. + error: :class:`CommandError` + The error that happened. + """ + pass + + @_cog_special_method + async def cog_before_invoke(self, ctx): + """A special method that acts as a cog local pre-invoke hook. + + This is similar to :meth:`.Command.before_invoke`. + + This **must** be a coroutine. + + Parameters + ----------- + ctx: :class:`.Context` + The invocation context. + """ + pass + + @_cog_special_method + async def cog_after_invoke(self, ctx): + """A special method that acts as a cog local post-invoke hook. + + This is similar to :meth:`.Command.after_invoke`. + + This **must** be a coroutine. + + Parameters + ----------- + ctx: :class:`.Context` + The invocation context. + """ + pass + + def _inject(self, bot): + cls = self.__class__ + + # realistically, the only thing that can cause loading errors + # is essentially just the command loading, which raises if there are + # duplicates. When this condition is met, we want to undo all what + # we've added so far for some form of atomic loading. + for index, command in enumerate(self.__cog_commands__): + command.cog = self + if command.parent is None: + try: + bot.add_command(command) + except Exception as e: + # undo our additions + for to_undo in self.__cog_commands__[:index]: + if to_undo.parent is None: + bot.remove_command(to_undo.name) + raise e + + # check if we're overriding the default + if cls.bot_check is not Cog.bot_check: + bot.add_check(self.bot_check) + + if cls.bot_check_once is not Cog.bot_check_once: + bot.add_check(self.bot_check_once, call_once=True) + + # while Bot.add_listener can raise if it's not a coroutine, + # this precondition is already met by the listener decorator + # already, thus this should never raise. + # Outside of, memory errors and the like... + for name, method_name in self.__cog_listeners__: + bot.add_listener(getattr(self, method_name), name) + + return self + + def _eject(self, bot): + cls = self.__class__ + + try: + for command in self.__cog_commands__: + if command.parent is None: + bot.remove_command(command.name) + + for _, method_name in self.__cog_listeners__: + bot.remove_listener(getattr(self, method_name)) + + if cls.bot_check is not Cog.bot_check: + bot.remove_check(self.bot_check) + + if cls.bot_check_once is not Cog.bot_check_once: + bot.remove_check(self.bot_check_once, call_once=True) + finally: + try: + self.cog_unload() + except Exception: + pass diff --git a/venv/lib64/python3.8/site-packages/discord/ext/commands/context.py b/venv/lib64/python3.8/site-packages/discord/ext/commands/context.py new file mode 100644 index 0000000..8df4f73 --- /dev/null +++ b/venv/lib64/python3.8/site-packages/discord/ext/commands/context.py @@ -0,0 +1,340 @@ +# -*- coding: utf-8 -*- + +""" +The MIT License (MIT) + +Copyright (c) 2015-present Rapptz + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. +""" + +import discord.abc +import discord.utils + +class Context(discord.abc.Messageable): + r"""Represents the context in which a command is being invoked under. + + This class contains a lot of meta data to help you understand more about + the invocation context. This class is not created manually and is instead + passed around to commands as the first parameter. + + This class implements the :class:`~discord.abc.Messageable` ABC. + + Attributes + ----------- + message: :class:`.Message` + The message that triggered the command being executed. + bot: :class:`.Bot` + The bot that contains the command being executed. + args: :class:`list` + The list of transformed arguments that were passed into the command. + If this is accessed during the :func:`on_command_error` event + then this list could be incomplete. + kwargs: :class:`dict` + A dictionary of transformed arguments that were passed into the command. + Similar to :attr:`args`\, if this is accessed in the + :func:`on_command_error` event then this dict could be incomplete. + prefix: :class:`str` + The prefix that was used to invoke the command. + command: :class:`Command` + The command that is being invoked currently. + invoked_with: :class:`str` + The command name that triggered this invocation. Useful for finding out + which alias called the command. + invoked_parents: List[:class:`str`] + The command names of the parents that triggered this invocation. Useful for + finding out which aliases called the command. + + For example in commands ``?a b c test``, the invoked parents are ``['a', 'b', 'c']``. + + .. versionadded:: 1.7 + + invoked_subcommand: :class:`Command` + The subcommand that was invoked. + If no valid subcommand was invoked then this is equal to ``None``. + subcommand_passed: Optional[:class:`str`] + The string that was attempted to call a subcommand. This does not have + to point to a valid registered subcommand and could just point to a + nonsense string. If nothing was passed to attempt a call to a + subcommand then this is set to ``None``. + command_failed: :class:`bool` + A boolean that indicates if the command failed to be parsed, checked, + or invoked. + """ + + def __init__(self, **attrs): + self.message = attrs.pop('message', None) + self.bot = attrs.pop('bot', None) + self.args = attrs.pop('args', []) + self.kwargs = attrs.pop('kwargs', {}) + self.prefix = attrs.pop('prefix') + self.command = attrs.pop('command', None) + self.view = attrs.pop('view', None) + self.invoked_with = attrs.pop('invoked_with', None) + self.invoked_parents = attrs.pop('invoked_parents', []) + self.invoked_subcommand = attrs.pop('invoked_subcommand', None) + self.subcommand_passed = attrs.pop('subcommand_passed', None) + self.command_failed = attrs.pop('command_failed', False) + self._state = self.message._state + + async def invoke(self, *args, **kwargs): + r"""|coro| + + Calls a command with the arguments given. + + This is useful if you want to just call the callback that a + :class:`.Command` holds internally. + + .. note:: + + This does not handle converters, checks, cooldowns, pre-invoke, + or after-invoke hooks in any matter. It calls the internal callback + directly as-if it was a regular function. + + You must take care in passing the proper arguments when + using this function. + + .. warning:: + + The first parameter passed **must** be the command being invoked. + + Parameters + ----------- + command: :class:`.Command` + The command that is going to be called. + \*args + The arguments to to use. + \*\*kwargs + The keyword arguments to use. + + Raises + ------- + TypeError + The command argument to invoke is missing. + """ + + try: + command = args[0] + except IndexError: + raise TypeError('Missing command to invoke.') from None + + arguments = [] + if command.cog is not None: + arguments.append(command.cog) + + arguments.append(self) + arguments.extend(args[1:]) + + ret = await command.callback(*arguments, **kwargs) + return ret + + async def reinvoke(self, *, call_hooks=False, restart=True): + """|coro| + + Calls the command again. + + This is similar to :meth:`~.Context.invoke` except that it bypasses + checks, cooldowns, and error handlers. + + .. note:: + + If you want to bypass :exc:`.UserInputError` derived exceptions, + it is recommended to use the regular :meth:`~.Context.invoke` + as it will work more naturally. After all, this will end up + using the old arguments the user has used and will thus just + fail again. + + Parameters + ------------ + call_hooks: :class:`bool` + Whether to call the before and after invoke hooks. + restart: :class:`bool` + Whether to start the call chain from the very beginning + or where we left off (i.e. the command that caused the error). + The default is to start where we left off. + + Raises + ------- + ValueError + The context to reinvoke is not valid. + """ + cmd = self.command + view = self.view + if cmd is None: + raise ValueError('This context is not valid.') + + # some state to revert to when we're done + index, previous = view.index, view.previous + invoked_with = self.invoked_with + invoked_subcommand = self.invoked_subcommand + invoked_parents = self.invoked_parents + subcommand_passed = self.subcommand_passed + + if restart: + to_call = cmd.root_parent or cmd + view.index = len(self.prefix) + view.previous = 0 + self.invoked_parents = [] + self.invoked_with = view.get_word() # advance to get the root command + else: + to_call = cmd + + try: + await to_call.reinvoke(self, call_hooks=call_hooks) + finally: + self.command = cmd + view.index = index + view.previous = previous + self.invoked_with = invoked_with + self.invoked_subcommand = invoked_subcommand + self.invoked_parents = invoked_parents + self.subcommand_passed = subcommand_passed + + @property + def valid(self): + """:class:`bool`: Checks if the invocation context is valid to be invoked with.""" + return self.prefix is not None and self.command is not None + + async def _get_channel(self): + return self.channel + + @property + def cog(self): + """Optional[:class:`.Cog`]: Returns the cog associated with this context's command. None if it does not exist.""" + + if self.command is None: + return None + return self.command.cog + + @discord.utils.cached_property + def guild(self): + """Optional[:class:`.Guild`]: Returns the guild associated with this context's command. None if not available.""" + return self.message.guild + + @discord.utils.cached_property + def channel(self): + """Union[:class:`.abc.Messageable`]: Returns the channel associated with this context's command. + Shorthand for :attr:`.Message.channel`. + """ + return self.message.channel + + @discord.utils.cached_property + def author(self): + """Union[:class:`~discord.User`, :class:`.Member`]: + Returns the author associated with this context's command. Shorthand for :attr:`.Message.author` + """ + return self.message.author + + @discord.utils.cached_property + def me(self): + """Union[:class:`.Member`, :class:`.ClientUser`]: + Similar to :attr:`.Guild.me` except it may return the :class:`.ClientUser` in private message contexts. + """ + return self.guild.me if self.guild is not None else self.bot.user + + @property + def voice_client(self): + r"""Optional[:class:`.VoiceProtocol`]: A shortcut to :attr:`.Guild.voice_client`\, if applicable.""" + g = self.guild + return g.voice_client if g else None + + async def send_help(self, *args): + """send_help(entity=) + + |coro| + + Shows the help command for the specified entity if given. + The entity can be a command or a cog. + + If no entity is given, then it'll show help for the + entire bot. + + If the entity is a string, then it looks up whether it's a + :class:`Cog` or a :class:`Command`. + + .. note:: + + Due to the way this function works, instead of returning + something similar to :meth:`~.commands.HelpCommand.command_not_found` + this returns :class:`None` on bad input or no help command. + + Parameters + ------------ + entity: Optional[Union[:class:`Command`, :class:`Cog`, :class:`str`]] + The entity to show help for. + + Returns + -------- + Any + The result of the help command, if any. + """ + from .core import Group, Command, wrap_callback + from .errors import CommandError + + bot = self.bot + cmd = bot.help_command + + if cmd is None: + return None + + cmd = cmd.copy() + cmd.context = self + if len(args) == 0: + await cmd.prepare_help_command(self, None) + mapping = cmd.get_bot_mapping() + injected = wrap_callback(cmd.send_bot_help) + try: + return await injected(mapping) + except CommandError as e: + await cmd.on_help_command_error(self, e) + return None + + entity = args[0] + if entity is None: + return None + + if isinstance(entity, str): + entity = bot.get_cog(entity) or bot.get_command(entity) + + try: + entity.qualified_name + except AttributeError: + # if we're here then it's not a cog, group, or command. + return None + + await cmd.prepare_help_command(self, entity.qualified_name) + + try: + if hasattr(entity, '__cog_commands__'): + injected = wrap_callback(cmd.send_cog_help) + return await injected(entity) + elif isinstance(entity, Group): + injected = wrap_callback(cmd.send_group_help) + return await injected(entity) + elif isinstance(entity, Command): + injected = wrap_callback(cmd.send_command_help) + return await injected(entity) + else: + return None + except CommandError as e: + await cmd.on_help_command_error(self, e) + + @discord.utils.copy_doc(discord.Message.reply) + async def reply(self, content=None, **kwargs): + return await self.message.reply(content, **kwargs) diff --git a/venv/lib64/python3.8/site-packages/discord/ext/commands/converter.py b/venv/lib64/python3.8/site-packages/discord/ext/commands/converter.py new file mode 100644 index 0000000..fdc7649 --- /dev/null +++ b/venv/lib64/python3.8/site-packages/discord/ext/commands/converter.py @@ -0,0 +1,852 @@ +# -*- coding: utf-8 -*- + +""" +The MIT License (MIT) + +Copyright (c) 2015-present Rapptz + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. +""" + +import re +import inspect +import typing + +import discord + +from .errors import * + +__all__ = ( + 'Converter', + 'MemberConverter', + 'UserConverter', + 'MessageConverter', + 'PartialMessageConverter', + 'TextChannelConverter', + 'InviteConverter', + 'GuildConverter', + 'RoleConverter', + 'GameConverter', + 'ColourConverter', + 'ColorConverter', + 'VoiceChannelConverter', + 'StageChannelConverter', + 'EmojiConverter', + 'PartialEmojiConverter', + 'CategoryChannelConverter', + 'IDConverter', + 'StoreChannelConverter', + 'clean_content', + 'Greedy', +) + +def _get_from_guilds(bot, getter, argument): + result = None + for guild in bot.guilds: + result = getattr(guild, getter)(argument) + if result: + return result + return result + +_utils_get = discord.utils.get + +class Converter: + """The base class of custom converters that require the :class:`.Context` + to be passed to be useful. + + This allows you to implement converters that function similar to the + special cased ``discord`` classes. + + Classes that derive from this should override the :meth:`~.Converter.convert` + method to do its conversion logic. This method must be a :ref:`coroutine `. + """ + + async def convert(self, ctx, argument): + """|coro| + + The method to override to do conversion logic. + + If an error is found while converting, it is recommended to + raise a :exc:`.CommandError` derived exception as it will + properly propagate to the error handlers. + + Parameters + ----------- + ctx: :class:`.Context` + The invocation context that the argument is being used in. + argument: :class:`str` + The argument that is being converted. + + Raises + ------- + :exc:`.CommandError` + A generic exception occurred when converting the argument. + :exc:`.BadArgument` + The converter failed to convert the argument. + """ + raise NotImplementedError('Derived classes need to implement this.') + +class IDConverter(Converter): + def __init__(self): + self._id_regex = re.compile(r'([0-9]{15,20})$') + super().__init__() + + def _get_id_match(self, argument): + return self._id_regex.match(argument) + +class MemberConverter(IDConverter): + """Converts to a :class:`~discord.Member`. + + All lookups are via the local guild. If in a DM context, then the lookup + is done by the global cache. + + The lookup strategy is as follows (in order): + + 1. Lookup by ID. + 2. Lookup by mention. + 3. Lookup by name#discrim + 4. Lookup by name + 5. Lookup by nickname + + .. versionchanged:: 1.5 + Raise :exc:`.MemberNotFound` instead of generic :exc:`.BadArgument` + + .. versionchanged:: 1.5.1 + This converter now lazily fetches members from the gateway and HTTP APIs, + optionally caching the result if :attr:`.MemberCacheFlags.joined` is enabled. + """ + + async def query_member_named(self, guild, argument): + cache = guild._state.member_cache_flags.joined + if len(argument) > 5 and argument[-5] == '#': + username, _, discriminator = argument.rpartition('#') + members = await guild.query_members(username, limit=100, cache=cache) + return discord.utils.get(members, name=username, discriminator=discriminator) + else: + members = await guild.query_members(argument, limit=100, cache=cache) + return discord.utils.find(lambda m: m.name == argument or m.nick == argument, members) + + async def query_member_by_id(self, bot, guild, user_id): + ws = bot._get_websocket(shard_id=guild.shard_id) + cache = guild._state.member_cache_flags.joined + if ws.is_ratelimited(): + # If we're being rate limited on the WS, then fall back to using the HTTP API + # So we don't have to wait ~60 seconds for the query to finish + try: + member = await guild.fetch_member(user_id) + except discord.HTTPException: + return None + + if cache: + guild._add_member(member) + return member + + # If we're not being rate limited then we can use the websocket to actually query + members = await guild.query_members(limit=1, user_ids=[user_id], cache=cache) + if not members: + return None + return members[0] + + async def convert(self, ctx, argument): + bot = ctx.bot + match = self._get_id_match(argument) or re.match(r'<@!?([0-9]+)>$', argument) + guild = ctx.guild + result = None + user_id = None + if match is None: + # not a mention... + if guild: + result = guild.get_member_named(argument) + else: + result = _get_from_guilds(bot, 'get_member_named', argument) + else: + user_id = int(match.group(1)) + if guild: + result = guild.get_member(user_id) or _utils_get(ctx.message.mentions, id=user_id) + else: + result = _get_from_guilds(bot, 'get_member', user_id) + + if result is None: + if guild is None: + raise MemberNotFound(argument) + + if user_id is not None: + result = await self.query_member_by_id(bot, guild, user_id) + else: + result = await self.query_member_named(guild, argument) + + if not result: + raise MemberNotFound(argument) + + return result + +class UserConverter(IDConverter): + """Converts to a :class:`~discord.User`. + + All lookups are via the global user cache. + + The lookup strategy is as follows (in order): + + 1. Lookup by ID. + 2. Lookup by mention. + 3. Lookup by name#discrim + 4. Lookup by name + + .. versionchanged:: 1.5 + Raise :exc:`.UserNotFound` instead of generic :exc:`.BadArgument` + + .. versionchanged:: 1.6 + This converter now lazily fetches users from the HTTP APIs if an ID is passed + and it's not available in cache. + """ + async def convert(self, ctx, argument): + match = self._get_id_match(argument) or re.match(r'<@!?([0-9]+)>$', argument) + result = None + state = ctx._state + + if match is not None: + user_id = int(match.group(1)) + result = ctx.bot.get_user(user_id) or _utils_get(ctx.message.mentions, id=user_id) + if result is None: + try: + result = await ctx.bot.fetch_user(user_id) + except discord.HTTPException: + raise UserNotFound(argument) from None + + return result + + arg = argument + + # Remove the '@' character if this is the first character from the argument + if arg[0] == '@': + # Remove first character + arg = arg[1:] + + # check for discriminator if it exists, + if len(arg) > 5 and arg[-5] == '#': + discrim = arg[-4:] + name = arg[:-5] + predicate = lambda u: u.name == name and u.discriminator == discrim + result = discord.utils.find(predicate, state._users.values()) + if result is not None: + return result + + predicate = lambda u: u.name == arg + result = discord.utils.find(predicate, state._users.values()) + + if result is None: + raise UserNotFound(argument) + + return result + +class PartialMessageConverter(Converter): + """Converts to a :class:`discord.PartialMessage`. + + .. versionadded:: 1.7 + + The creation strategy is as follows (in order): + + 1. By "{channel ID}-{message ID}" (retrieved by shift-clicking on "Copy ID") + 2. By message ID (The message is assumed to be in the context channel.) + 3. By message URL + """ + def _get_id_matches(self, argument): + id_regex = re.compile(r'(?:(?P[0-9]{15,20})-)?(?P[0-9]{15,20})$') + link_regex = re.compile( + r'https?://(?:(ptb|canary|www)\.)?discord(?:app)?\.com/channels/' + r'(?:[0-9]{15,20}|@me)' + r'/(?P[0-9]{15,20})/(?P[0-9]{15,20})/?$' + ) + match = id_regex.match(argument) or link_regex.match(argument) + if not match: + raise MessageNotFound(argument) + channel_id = match.group("channel_id") + return int(match.group("message_id")), int(channel_id) if channel_id else None + + async def convert(self, ctx, argument): + message_id, channel_id = self._get_id_matches(argument) + channel = ctx.bot.get_channel(channel_id) if channel_id else ctx.channel + if not channel: + raise ChannelNotFound(channel_id) + return discord.PartialMessage(channel=channel, id=message_id) + +class MessageConverter(PartialMessageConverter): + """Converts to a :class:`discord.Message`. + + .. versionadded:: 1.1 + + The lookup strategy is as follows (in order): + + 1. Lookup by "{channel ID}-{message ID}" (retrieved by shift-clicking on "Copy ID") + 2. Lookup by message ID (the message **must** be in the context channel) + 3. Lookup by message URL + + .. versionchanged:: 1.5 + Raise :exc:`.ChannelNotFound`, :exc:`.MessageNotFound` or :exc:`.ChannelNotReadable` instead of generic :exc:`.BadArgument` + """ + async def convert(self, ctx, argument): + message_id, channel_id = self._get_id_matches(argument) + message = ctx.bot._connection._get_message(message_id) + if message: + return message + channel = ctx.bot.get_channel(channel_id) if channel_id else ctx.channel + if not channel: + raise ChannelNotFound(channel_id) + try: + return await channel.fetch_message(message_id) + except discord.NotFound: + raise MessageNotFound(argument) + except discord.Forbidden: + raise ChannelNotReadable(channel) + +class TextChannelConverter(IDConverter): + """Converts to a :class:`~discord.TextChannel`. + + All lookups are via the local guild. If in a DM context, then the lookup + is done by the global cache. + + The lookup strategy is as follows (in order): + + 1. Lookup by ID. + 2. Lookup by mention. + 3. Lookup by name + + .. versionchanged:: 1.5 + Raise :exc:`.ChannelNotFound` instead of generic :exc:`.BadArgument` + """ + async def convert(self, ctx, argument): + bot = ctx.bot + + match = self._get_id_match(argument) or re.match(r'<#([0-9]+)>$', argument) + result = None + guild = ctx.guild + + if match is None: + # not a mention + if guild: + result = discord.utils.get(guild.text_channels, name=argument) + else: + def check(c): + return isinstance(c, discord.TextChannel) and c.name == argument + result = discord.utils.find(check, bot.get_all_channels()) + else: + channel_id = int(match.group(1)) + if guild: + result = guild.get_channel(channel_id) + else: + result = _get_from_guilds(bot, 'get_channel', channel_id) + + if not isinstance(result, discord.TextChannel): + raise ChannelNotFound(argument) + + return result + +class VoiceChannelConverter(IDConverter): + """Converts to a :class:`~discord.VoiceChannel`. + + All lookups are via the local guild. If in a DM context, then the lookup + is done by the global cache. + + The lookup strategy is as follows (in order): + + 1. Lookup by ID. + 2. Lookup by mention. + 3. Lookup by name + + .. versionchanged:: 1.5 + Raise :exc:`.ChannelNotFound` instead of generic :exc:`.BadArgument` + """ + async def convert(self, ctx, argument): + bot = ctx.bot + match = self._get_id_match(argument) or re.match(r'<#([0-9]+)>$', argument) + result = None + guild = ctx.guild + + if match is None: + # not a mention + if guild: + result = discord.utils.get(guild.voice_channels, name=argument) + else: + def check(c): + return isinstance(c, discord.VoiceChannel) and c.name == argument + result = discord.utils.find(check, bot.get_all_channels()) + else: + channel_id = int(match.group(1)) + if guild: + result = guild.get_channel(channel_id) + else: + result = _get_from_guilds(bot, 'get_channel', channel_id) + + if not isinstance(result, discord.VoiceChannel): + raise ChannelNotFound(argument) + + return result + +class StageChannelConverter(IDConverter): + """Converts to a :class:`~discord.StageChannel`. + + .. versionadded:: 1.7 + + All lookups are via the local guild. If in a DM context, then the lookup + is done by the global cache. + + The lookup strategy is as follows (in order): + + 1. Lookup by ID. + 2. Lookup by mention. + 3. Lookup by name + """ + async def convert(self, ctx, argument): + bot = ctx.bot + match = self._get_id_match(argument) or re.match(r'<#([0-9]+)>$', argument) + result = None + guild = ctx.guild + + if match is None: + # not a mention + if guild: + result = discord.utils.get(guild.stage_channels, name=argument) + else: + def check(c): + return isinstance(c, discord.StageChannel) and c.name == argument + result = discord.utils.find(check, bot.get_all_channels()) + else: + channel_id = int(match.group(1)) + if guild: + result = guild.get_channel(channel_id) + else: + result = _get_from_guilds(bot, 'get_channel', channel_id) + + if not isinstance(result, discord.StageChannel): + raise ChannelNotFound(argument) + + return result + +class CategoryChannelConverter(IDConverter): + """Converts to a :class:`~discord.CategoryChannel`. + + All lookups are via the local guild. If in a DM context, then the lookup + is done by the global cache. + + The lookup strategy is as follows (in order): + + 1. Lookup by ID. + 2. Lookup by mention. + 3. Lookup by name + + .. versionchanged:: 1.5 + Raise :exc:`.ChannelNotFound` instead of generic :exc:`.BadArgument` + """ + async def convert(self, ctx, argument): + bot = ctx.bot + + match = self._get_id_match(argument) or re.match(r'<#([0-9]+)>$', argument) + result = None + guild = ctx.guild + + if match is None: + # not a mention + if guild: + result = discord.utils.get(guild.categories, name=argument) + else: + def check(c): + return isinstance(c, discord.CategoryChannel) and c.name == argument + result = discord.utils.find(check, bot.get_all_channels()) + else: + channel_id = int(match.group(1)) + if guild: + result = guild.get_channel(channel_id) + else: + result = _get_from_guilds(bot, 'get_channel', channel_id) + + if not isinstance(result, discord.CategoryChannel): + raise ChannelNotFound(argument) + + return result + +class StoreChannelConverter(IDConverter): + """Converts to a :class:`~discord.StoreChannel`. + + All lookups are via the local guild. If in a DM context, then the lookup + is done by the global cache. + + The lookup strategy is as follows (in order): + + 1. Lookup by ID. + 2. Lookup by mention. + 3. Lookup by name. + + .. versionadded:: 1.7 + """ + + async def convert(self, ctx, argument): + bot = ctx.bot + match = self._get_id_match(argument) or re.match(r'<#([0-9]+)>$', argument) + result = None + guild = ctx.guild + + if match is None: + # not a mention + if guild: + result = discord.utils.get(guild.channels, name=argument) + else: + def check(c): + return isinstance(c, discord.StoreChannel) and c.name == argument + result = discord.utils.find(check, bot.get_all_channels()) + else: + channel_id = int(match.group(1)) + if guild: + result = guild.get_channel(channel_id) + else: + result = _get_from_guilds(bot, 'get_channel', channel_id) + + if not isinstance(result, discord.StoreChannel): + raise ChannelNotFound(argument) + + return result + +class ColourConverter(Converter): + """Converts to a :class:`~discord.Colour`. + + .. versionchanged:: 1.5 + Add an alias named ColorConverter + + The following formats are accepted: + + - ``0x`` + - ``#`` + - ``0x#`` + - ``rgb(, , )`` + - Any of the ``classmethod`` in :class:`Colour` + + - The ``_`` in the name can be optionally replaced with spaces. + + Like CSS, ```` can be either 0-255 or 0-100% and ```` can be + either a 6 digit hex number or a 3 digit hex shortcut (e.g. #fff). + + .. versionchanged:: 1.5 + Raise :exc:`.BadColourArgument` instead of generic :exc:`.BadArgument` + + .. versionchanged:: 1.7 + Added support for ``rgb`` function and 3-digit hex shortcuts + """ + + RGB_REGEX = re.compile(r'rgb\s*\((?P[0-9]{1,3}%?)\s*,\s*(?P[0-9]{1,3}%?)\s*,\s*(?P[0-9]{1,3}%?)\s*\)') + + def parse_hex_number(self, argument): + arg = ''.join(i * 2 for i in argument) if len(argument) == 3 else argument + try: + value = int(arg, base=16) + if not (0 <= value <= 0xFFFFFF): + raise BadColourArgument(argument) + except ValueError: + raise BadColourArgument(argument) + else: + return discord.Color(value=value) + + def parse_rgb_number(self, argument, number): + if number[-1] == '%': + value = int(number[:-1]) + if not (0 <= value <= 100): + raise BadColourArgument(argument) + return round(255 * (value / 100)) + + value = int(number) + if not (0 <= value <= 255): + raise BadColourArgument(argument) + return value + + def parse_rgb(self, argument, *, regex=RGB_REGEX): + match = regex.match(argument) + if match is None: + raise BadColourArgument(argument) + + red = self.parse_rgb_number(argument, match.group('r')) + green = self.parse_rgb_number(argument, match.group('g')) + blue = self.parse_rgb_number(argument, match.group('b')) + return discord.Color.from_rgb(red, green, blue) + + async def convert(self, ctx, argument): + if argument[0] == '#': + return self.parse_hex_number(argument[1:]) + + if argument[0:2] == '0x': + rest = argument[2:] + # Legacy backwards compatible syntax + if rest.startswith('#'): + return self.parse_hex_number(rest[1:]) + return self.parse_hex_number(rest) + + arg = argument.lower() + if arg[0:3] == 'rgb': + return self.parse_rgb(arg) + + arg = arg.replace(' ', '_') + method = getattr(discord.Colour, arg, None) + if arg.startswith('from_') or method is None or not inspect.ismethod(method): + raise BadColourArgument(arg) + return method() + +ColorConverter = ColourConverter + +class RoleConverter(IDConverter): + """Converts to a :class:`~discord.Role`. + + All lookups are via the local guild. If in a DM context, the converter raises + :exc:`.NoPrivateMessage` exception. + + The lookup strategy is as follows (in order): + + 1. Lookup by ID. + 2. Lookup by mention. + 3. Lookup by name + + .. versionchanged:: 1.5 + Raise :exc:`.RoleNotFound` instead of generic :exc:`.BadArgument` + """ + async def convert(self, ctx, argument): + guild = ctx.guild + if not guild: + raise NoPrivateMessage() + + match = self._get_id_match(argument) or re.match(r'<@&([0-9]+)>$', argument) + if match: + result = guild.get_role(int(match.group(1))) + else: + result = discord.utils.get(guild._roles.values(), name=argument) + + if result is None: + raise RoleNotFound(argument) + return result + +class GameConverter(Converter): + """Converts to :class:`~discord.Game`.""" + async def convert(self, ctx, argument): + return discord.Game(name=argument) + +class InviteConverter(Converter): + """Converts to a :class:`~discord.Invite`. + + This is done via an HTTP request using :meth:`.Bot.fetch_invite`. + + .. versionchanged:: 1.5 + Raise :exc:`.BadInviteArgument` instead of generic :exc:`.BadArgument` + """ + async def convert(self, ctx, argument): + try: + invite = await ctx.bot.fetch_invite(argument) + return invite + except Exception as exc: + raise BadInviteArgument() from exc + +class GuildConverter(IDConverter): + """Converts to a :class:`~discord.Guild`. + + The lookup strategy is as follows (in order): + + 1. Lookup by ID. + 2. Lookup by name. (There is no disambiguation for Guilds with multiple matching names). + + .. versionadded:: 1.7 + """ + + async def convert(self, ctx, argument): + match = self._get_id_match(argument) + result = None + + if match is not None: + guild_id = int(match.group(1)) + result = ctx.bot.get_guild(guild_id) + + if result is None: + result = discord.utils.get(ctx.bot.guilds, name=argument) + + if result is None: + raise GuildNotFound(argument) + return result + +class EmojiConverter(IDConverter): + """Converts to a :class:`~discord.Emoji`. + + All lookups are done for the local guild first, if available. If that lookup + fails, then it checks the client's global cache. + + The lookup strategy is as follows (in order): + + 1. Lookup by ID. + 2. Lookup by extracting ID from the emoji. + 3. Lookup by name + + .. versionchanged:: 1.5 + Raise :exc:`.EmojiNotFound` instead of generic :exc:`.BadArgument` + """ + async def convert(self, ctx, argument): + match = self._get_id_match(argument) or re.match(r'$', argument) + result = None + bot = ctx.bot + guild = ctx.guild + + if match is None: + # Try to get the emoji by name. Try local guild first. + if guild: + result = discord.utils.get(guild.emojis, name=argument) + + if result is None: + result = discord.utils.get(bot.emojis, name=argument) + else: + emoji_id = int(match.group(1)) + + # Try to look up emoji by id. + if guild: + result = discord.utils.get(guild.emojis, id=emoji_id) + + if result is None: + result = discord.utils.get(bot.emojis, id=emoji_id) + + if result is None: + raise EmojiNotFound(argument) + + return result + +class PartialEmojiConverter(Converter): + """Converts to a :class:`~discord.PartialEmoji`. + + This is done by extracting the animated flag, name and ID from the emoji. + + .. versionchanged:: 1.5 + Raise :exc:`.PartialEmojiConversionFailure` instead of generic :exc:`.BadArgument` + """ + async def convert(self, ctx, argument): + match = re.match(r'<(a?):([a-zA-Z0-9\_]+):([0-9]+)>$', argument) + + if match: + emoji_animated = bool(match.group(1)) + emoji_name = match.group(2) + emoji_id = int(match.group(3)) + + return discord.PartialEmoji.with_state(ctx.bot._connection, animated=emoji_animated, name=emoji_name, + id=emoji_id) + + raise PartialEmojiConversionFailure(argument) + +class clean_content(Converter): + """Converts the argument to mention scrubbed version of + said content. + + This behaves similarly to :attr:`~discord.Message.clean_content`. + + Attributes + ------------ + fix_channel_mentions: :class:`bool` + Whether to clean channel mentions. + use_nicknames: :class:`bool` + Whether to use nicknames when transforming mentions. + escape_markdown: :class:`bool` + Whether to also escape special markdown characters. + remove_markdown: :class:`bool` + Whether to also remove special markdown characters. This option is not supported with ``escape_markdown`` + + .. versionadded:: 1.7 + """ + def __init__(self, *, fix_channel_mentions=False, use_nicknames=True, escape_markdown=False, remove_markdown=False): + self.fix_channel_mentions = fix_channel_mentions + self.use_nicknames = use_nicknames + self.escape_markdown = escape_markdown + self.remove_markdown = remove_markdown + + async def convert(self, ctx, argument): + message = ctx.message + transformations = {} + + if self.fix_channel_mentions and ctx.guild: + def resolve_channel(id, *, _get=ctx.guild.get_channel): + ch = _get(id) + return ('<#%s>' % id), ('#' + ch.name if ch else '#deleted-channel') + + transformations.update(resolve_channel(channel) for channel in message.raw_channel_mentions) + + if self.use_nicknames and ctx.guild: + def resolve_member(id, *, _get=ctx.guild.get_member): + m = _get(id) + return '@' + m.display_name if m else '@deleted-user' + else: + def resolve_member(id, *, _get=ctx.bot.get_user): + m = _get(id) + return '@' + m.name if m else '@deleted-user' + + + transformations.update( + ('<@%s>' % member_id, resolve_member(member_id)) + for member_id in message.raw_mentions + ) + + transformations.update( + ('<@!%s>' % member_id, resolve_member(member_id)) + for member_id in message.raw_mentions + ) + + if ctx.guild: + def resolve_role(_id, *, _find=ctx.guild.get_role): + r = _find(_id) + return '@' + r.name if r else '@deleted-role' + + transformations.update( + ('<@&%s>' % role_id, resolve_role(role_id)) + for role_id in message.raw_role_mentions + ) + + def repl(obj): + return transformations.get(obj.group(0), '') + + pattern = re.compile('|'.join(transformations.keys())) + result = pattern.sub(repl, argument) + + if self.escape_markdown: + result = discord.utils.escape_markdown(result) + elif self.remove_markdown: + result = discord.utils.remove_markdown(result) + + # Completely ensure no mentions escape: + return discord.utils.escape_mentions(result) + +class _Greedy: + __slots__ = ('converter',) + + def __init__(self, *, converter=None): + self.converter = converter + + def __getitem__(self, params): + if not isinstance(params, tuple): + params = (params,) + if len(params) != 1: + raise TypeError('Greedy[...] only takes a single argument') + converter = params[0] + + if not (callable(converter) or isinstance(converter, Converter) or hasattr(converter, '__origin__')): + raise TypeError('Greedy[...] expects a type or a Converter instance.') + + if converter is str or converter is type(None) or converter is _Greedy: + raise TypeError('Greedy[%s] is invalid.' % converter.__name__) + + if getattr(converter, '__origin__', None) is typing.Union and type(None) in converter.__args__: + raise TypeError('Greedy[%r] is invalid.' % converter) + + return self.__class__(converter=converter) + +Greedy = _Greedy() diff --git a/venv/lib64/python3.8/site-packages/discord/ext/commands/cooldowns.py b/venv/lib64/python3.8/site-packages/discord/ext/commands/cooldowns.py new file mode 100644 index 0000000..54a5339 --- /dev/null +++ b/venv/lib64/python3.8/site-packages/discord/ext/commands/cooldowns.py @@ -0,0 +1,295 @@ +# -*- coding: utf-8 -*- + +""" +The MIT License (MIT) + +Copyright (c) 2015-present Rapptz + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. +""" + +from discord.enums import Enum +import time +import asyncio +from collections import deque + +from ...abc import PrivateChannel +from .errors import MaxConcurrencyReached + +__all__ = ( + 'BucketType', + 'Cooldown', + 'CooldownMapping', + 'MaxConcurrency', +) + +class BucketType(Enum): + default = 0 + user = 1 + guild = 2 + channel = 3 + member = 4 + category = 5 + role = 6 + + def get_key(self, msg): + if self is BucketType.user: + return msg.author.id + elif self is BucketType.guild: + return (msg.guild or msg.author).id + elif self is BucketType.channel: + return msg.channel.id + elif self is BucketType.member: + return ((msg.guild and msg.guild.id), msg.author.id) + elif self is BucketType.category: + return (msg.channel.category or msg.channel).id + elif self is BucketType.role: + # we return the channel id of a private-channel as there are only roles in guilds + # and that yields the same result as for a guild with only the @everyone role + # NOTE: PrivateChannel doesn't actually have an id attribute but we assume we are + # recieving a DMChannel or GroupChannel which inherit from PrivateChannel and do + return (msg.channel if isinstance(msg.channel, PrivateChannel) else msg.author.top_role).id + + def __call__(self, msg): + return self.get_key(msg) + + +class Cooldown: + __slots__ = ('rate', 'per', 'type', '_window', '_tokens', '_last') + + def __init__(self, rate, per, type): + self.rate = int(rate) + self.per = float(per) + self.type = type + self._window = 0.0 + self._tokens = self.rate + self._last = 0.0 + + if not callable(self.type): + raise TypeError('Cooldown type must be a BucketType or callable') + + def get_tokens(self, current=None): + if not current: + current = time.time() + + tokens = self._tokens + + if current > self._window + self.per: + tokens = self.rate + return tokens + + def get_retry_after(self, current=None): + current = current or time.time() + tokens = self.get_tokens(current) + + if tokens == 0: + return self.per - (current - self._window) + + return 0.0 + + def update_rate_limit(self, current=None): + current = current or time.time() + self._last = current + + self._tokens = self.get_tokens(current) + + # first token used means that we start a new rate limit window + if self._tokens == self.rate: + self._window = current + + # check if we are rate limited + if self._tokens == 0: + return self.per - (current - self._window) + + # we're not so decrement our tokens + self._tokens -= 1 + + # see if we got rate limited due to this token change, and if + # so update the window to point to our current time frame + if self._tokens == 0: + self._window = current + + def reset(self): + self._tokens = self.rate + self._last = 0.0 + + def copy(self): + return Cooldown(self.rate, self.per, self.type) + + def __repr__(self): + return ''.format(self) + +class CooldownMapping: + def __init__(self, original): + self._cache = {} + self._cooldown = original + + def copy(self): + ret = CooldownMapping(self._cooldown) + ret._cache = self._cache.copy() + return ret + + @property + def valid(self): + return self._cooldown is not None + + @classmethod + def from_cooldown(cls, rate, per, type): + return cls(Cooldown(rate, per, type)) + + def _bucket_key(self, msg): + return self._cooldown.type(msg) + + def _verify_cache_integrity(self, current=None): + # we want to delete all cache objects that haven't been used + # in a cooldown window. e.g. if we have a command that has a + # cooldown of 60s and it has not been used in 60s then that key should be deleted + current = current or time.time() + dead_keys = [k for k, v in self._cache.items() if current > v._last + v.per] + for k in dead_keys: + del self._cache[k] + + def get_bucket(self, message, current=None): + if self._cooldown.type is BucketType.default: + return self._cooldown + + self._verify_cache_integrity(current) + key = self._bucket_key(message) + if key not in self._cache: + bucket = self._cooldown.copy() + self._cache[key] = bucket + else: + bucket = self._cache[key] + + return bucket + + def update_rate_limit(self, message, current=None): + bucket = self.get_bucket(message, current) + return bucket.update_rate_limit(current) + +class _Semaphore: + """This class is a version of a semaphore. + + If you're wondering why asyncio.Semaphore isn't being used, + it's because it doesn't expose the internal value. This internal + value is necessary because I need to support both `wait=True` and + `wait=False`. + + An asyncio.Queue could have been used to do this as well -- but it is + not as inefficient since internally that uses two queues and is a bit + overkill for what is basically a counter. + """ + + __slots__ = ('value', 'loop', '_waiters') + + def __init__(self, number): + self.value = number + self.loop = asyncio.get_event_loop() + self._waiters = deque() + + def __repr__(self): + return '<_Semaphore value={0.value} waiters={1}>'.format(self, len(self._waiters)) + + def locked(self): + return self.value == 0 + + def is_active(self): + return len(self._waiters) > 0 + + def wake_up(self): + while self._waiters: + future = self._waiters.popleft() + if not future.done(): + future.set_result(None) + return + + async def acquire(self, *, wait=False): + if not wait and self.value <= 0: + # signal that we're not acquiring + return False + + while self.value <= 0: + future = self.loop.create_future() + self._waiters.append(future) + try: + await future + except: + future.cancel() + if self.value > 0 and not future.cancelled(): + self.wake_up() + raise + + self.value -= 1 + return True + + def release(self): + self.value += 1 + self.wake_up() + +class MaxConcurrency: + __slots__ = ('number', 'per', 'wait', '_mapping') + + def __init__(self, number, *, per, wait): + self._mapping = {} + self.per = per + self.number = number + self.wait = wait + + if number <= 0: + raise ValueError('max_concurrency \'number\' cannot be less than 1') + + if not isinstance(per, BucketType): + raise TypeError('max_concurrency \'per\' must be of type BucketType not %r' % type(per)) + + def copy(self): + return self.__class__(self.number, per=self.per, wait=self.wait) + + def __repr__(self): + return ''.format(self) + + def get_key(self, message): + return self.per.get_key(message) + + async def acquire(self, message): + key = self.get_key(message) + + try: + sem = self._mapping[key] + except KeyError: + self._mapping[key] = sem = _Semaphore(self.number) + + acquired = await sem.acquire(wait=self.wait) + if not acquired: + raise MaxConcurrencyReached(self.number, self.per) + + async def release(self, message): + # Technically there's no reason for this function to be async + # But it might be more useful in the future + key = self.get_key(message) + + try: + sem = self._mapping[key] + except KeyError: + # ...? peculiar + return + else: + sem.release() + + if sem.value >= self.number and not sem.is_active(): + del self._mapping[key] diff --git a/venv/lib64/python3.8/site-packages/discord/ext/commands/core.py b/venv/lib64/python3.8/site-packages/discord/ext/commands/core.py new file mode 100644 index 0000000..1c22ec0 --- /dev/null +++ b/venv/lib64/python3.8/site-packages/discord/ext/commands/core.py @@ -0,0 +1,2070 @@ +# -*- coding: utf-8 -*- + +""" +The MIT License (MIT) + +Copyright (c) 2015-present Rapptz + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. +""" + +import asyncio +import functools +import inspect +import typing +import datetime + +import discord + +from .errors import * +from .cooldowns import Cooldown, BucketType, CooldownMapping, MaxConcurrency +from . import converter as converters +from ._types import _BaseCommand +from .cog import Cog + +__all__ = ( + 'Command', + 'Group', + 'GroupMixin', + 'command', + 'group', + 'has_role', + 'has_permissions', + 'has_any_role', + 'check', + 'check_any', + 'before_invoke', + 'after_invoke', + 'bot_has_role', + 'bot_has_permissions', + 'bot_has_any_role', + 'cooldown', + 'max_concurrency', + 'dm_only', + 'guild_only', + 'is_owner', + 'is_nsfw', + 'has_guild_permissions', + 'bot_has_guild_permissions' +) + +def wrap_callback(coro): + @functools.wraps(coro) + async def wrapped(*args, **kwargs): + try: + ret = await coro(*args, **kwargs) + except CommandError: + raise + except asyncio.CancelledError: + return + except Exception as exc: + raise CommandInvokeError(exc) from exc + return ret + return wrapped + +def hooked_wrapped_callback(command, ctx, coro): + @functools.wraps(coro) + async def wrapped(*args, **kwargs): + try: + ret = await coro(*args, **kwargs) + except CommandError: + ctx.command_failed = True + raise + except asyncio.CancelledError: + ctx.command_failed = True + return + except Exception as exc: + ctx.command_failed = True + raise CommandInvokeError(exc) from exc + finally: + if command._max_concurrency is not None: + await command._max_concurrency.release(ctx) + + await command.call_after_hooks(ctx) + return ret + return wrapped + +def _convert_to_bool(argument): + lowered = argument.lower() + if lowered in ('yes', 'y', 'true', 't', '1', 'enable', 'on'): + return True + elif lowered in ('no', 'n', 'false', 'f', '0', 'disable', 'off'): + return False + else: + raise BadBoolArgument(lowered) + +class _CaseInsensitiveDict(dict): + def __contains__(self, k): + return super().__contains__(k.casefold()) + + def __delitem__(self, k): + return super().__delitem__(k.casefold()) + + def __getitem__(self, k): + return super().__getitem__(k.casefold()) + + def get(self, k, default=None): + return super().get(k.casefold(), default) + + def pop(self, k, default=None): + return super().pop(k.casefold(), default) + + def __setitem__(self, k, v): + super().__setitem__(k.casefold(), v) + +class Command(_BaseCommand): + r"""A class that implements the protocol for a bot text command. + + These are not created manually, instead they are created via the + decorator or functional interface. + + Attributes + ----------- + name: :class:`str` + The name of the command. + callback: :ref:`coroutine ` + The coroutine that is executed when the command is called. + help: :class:`str` + The long help text for the command. + brief: Optional[:class:`str`] + The short help text for the command. + usage: Optional[:class:`str`] + A replacement for arguments in the default help text. + aliases: Union[List[:class:`str`], Tuple[:class:`str`]] + The list of aliases the command can be invoked under. + enabled: :class:`bool` + A boolean that indicates if the command is currently enabled. + If the command is invoked while it is disabled, then + :exc:`.DisabledCommand` is raised to the :func:`.on_command_error` + event. Defaults to ``True``. + parent: Optional[:class:`Command`] + The parent command that this command belongs to. ``None`` if there + isn't one. + cog: Optional[:class:`Cog`] + The cog that this command belongs to. ``None`` if there isn't one. + checks: List[Callable[[:class:`.Context`], :class:`bool`]] + A list of predicates that verifies if the command could be executed + with the given :class:`.Context` as the sole parameter. If an exception + is necessary to be thrown to signal failure, then one inherited from + :exc:`.CommandError` should be used. Note that if the checks fail then + :exc:`.CheckFailure` exception is raised to the :func:`.on_command_error` + event. + description: :class:`str` + The message prefixed into the default help command. + hidden: :class:`bool` + If ``True``\, the default help command does not show this in the + help output. + rest_is_raw: :class:`bool` + If ``False`` and a keyword-only argument is provided then the keyword + only argument is stripped and handled as if it was a regular argument + that handles :exc:`.MissingRequiredArgument` and default values in a + regular matter rather than passing the rest completely raw. If ``True`` + then the keyword-only argument will pass in the rest of the arguments + in a completely raw matter. Defaults to ``False``. + invoked_subcommand: Optional[:class:`Command`] + The subcommand that was invoked, if any. + require_var_positional: :class:`bool` + If ``True`` and a variadic positional argument is specified, requires + the user to specify at least one argument. Defaults to ``False``. + + .. versionadded:: 1.5 + + ignore_extra: :class:`bool` + If ``True``\, ignores extraneous strings passed to a command if all its + requirements are met (e.g. ``?foo a b c`` when only expecting ``a`` + and ``b``). Otherwise :func:`.on_command_error` and local error handlers + are called with :exc:`.TooManyArguments`. Defaults to ``True``. + cooldown_after_parsing: :class:`bool` + If ``True``\, cooldown processing is done after argument parsing, + which calls converters. If ``False`` then cooldown processing is done + first and then the converters are called second. Defaults to ``False``. + """ + + def __new__(cls, *args, **kwargs): + # if you're wondering why this is done, it's because we need to ensure + # we have a complete original copy of **kwargs even for classes that + # mess with it by popping before delegating to the subclass __init__. + # In order to do this, we need to control the instance creation and + # inject the original kwargs through __new__ rather than doing it + # inside __init__. + self = super().__new__(cls) + + # we do a shallow copy because it's probably the most common use case. + # this could potentially break if someone modifies a list or something + # while it's in movement, but for now this is the cheapest and + # fastest way to do what we want. + self.__original_kwargs__ = kwargs.copy() + return self + + def __init__(self, func, **kwargs): + if not asyncio.iscoroutinefunction(func): + raise TypeError('Callback must be a coroutine.') + + self.name = name = kwargs.get('name') or func.__name__ + if not isinstance(name, str): + raise TypeError('Name of a command must be a string.') + + self.callback = func + self.enabled = kwargs.get('enabled', True) + + help_doc = kwargs.get('help') + if help_doc is not None: + help_doc = inspect.cleandoc(help_doc) + else: + help_doc = inspect.getdoc(func) + if isinstance(help_doc, bytes): + help_doc = help_doc.decode('utf-8') + + self.help = help_doc + + self.brief = kwargs.get('brief') + self.usage = kwargs.get('usage') + self.rest_is_raw = kwargs.get('rest_is_raw', False) + self.aliases = kwargs.get('aliases', []) + + if not isinstance(self.aliases, (list, tuple)): + raise TypeError("Aliases of a command must be a list or a tuple of strings.") + + self.description = inspect.cleandoc(kwargs.get('description', '')) + self.hidden = kwargs.get('hidden', False) + + try: + checks = func.__commands_checks__ + checks.reverse() + except AttributeError: + checks = kwargs.get('checks', []) + finally: + self.checks = checks + + try: + cooldown = func.__commands_cooldown__ + except AttributeError: + cooldown = kwargs.get('cooldown') + finally: + self._buckets = CooldownMapping(cooldown) + + try: + max_concurrency = func.__commands_max_concurrency__ + except AttributeError: + max_concurrency = kwargs.get('max_concurrency') + finally: + self._max_concurrency = max_concurrency + + self.require_var_positional = kwargs.get('require_var_positional', False) + self.ignore_extra = kwargs.get('ignore_extra', True) + self.cooldown_after_parsing = kwargs.get('cooldown_after_parsing', False) + self.cog = None + + # bandaid for the fact that sometimes parent can be the bot instance + parent = kwargs.get('parent') + self.parent = parent if isinstance(parent, _BaseCommand) else None + + try: + before_invoke = func.__before_invoke__ + except AttributeError: + self._before_invoke = None + else: + self.before_invoke(before_invoke) + + try: + after_invoke = func.__after_invoke__ + except AttributeError: + self._after_invoke = None + else: + self.after_invoke(after_invoke) + + @property + def callback(self): + return self._callback + + @callback.setter + def callback(self, function): + self._callback = function + self.module = function.__module__ + + signature = inspect.signature(function) + self.params = signature.parameters.copy() + + # PEP-563 allows postponing evaluation of annotations with a __future__ + # import. When postponed, Parameter.annotation will be a string and must + # be replaced with the real value for the converters to work later on + for key, value in self.params.items(): + if isinstance(value.annotation, str): + self.params[key] = value = value.replace(annotation=eval(value.annotation, function.__globals__)) + + # fail early for when someone passes an unparameterized Greedy type + if value.annotation is converters.Greedy: + raise TypeError('Unparameterized Greedy[...] is disallowed in signature.') + + def add_check(self, func): + """Adds a check to the command. + + This is the non-decorator interface to :func:`.check`. + + .. versionadded:: 1.3 + + Parameters + ----------- + func + The function that will be used as a check. + """ + + self.checks.append(func) + + def remove_check(self, func): + """Removes a check from the command. + + This function is idempotent and will not raise an exception + if the function is not in the command's checks. + + .. versionadded:: 1.3 + + Parameters + ----------- + func + The function to remove from the checks. + """ + + try: + self.checks.remove(func) + except ValueError: + pass + + def update(self, **kwargs): + """Updates :class:`Command` instance with updated attribute. + + This works similarly to the :func:`.command` decorator in terms + of parameters in that they are passed to the :class:`Command` or + subclass constructors, sans the name and callback. + """ + self.__init__(self.callback, **dict(self.__original_kwargs__, **kwargs)) + + async def __call__(self, *args, **kwargs): + """|coro| + + Calls the internal callback that the command holds. + + .. note:: + + This bypasses all mechanisms -- including checks, converters, + invoke hooks, cooldowns, etc. You must take care to pass + the proper arguments and types to this function. + + .. versionadded:: 1.3 + """ + if self.cog is not None: + return await self.callback(self.cog, *args, **kwargs) + else: + return await self.callback(*args, **kwargs) + + def _ensure_assignment_on_copy(self, other): + other._before_invoke = self._before_invoke + other._after_invoke = self._after_invoke + if self.checks != other.checks: + other.checks = self.checks.copy() + if self._buckets.valid and not other._buckets.valid: + other._buckets = self._buckets.copy() + if self._max_concurrency != other._max_concurrency: + other._max_concurrency = self._max_concurrency.copy() + + try: + other.on_error = self.on_error + except AttributeError: + pass + return other + + def copy(self): + """Creates a copy of this command. + + Returns + -------- + :class:`Command` + A new instance of this command. + """ + ret = self.__class__(self.callback, **self.__original_kwargs__) + return self._ensure_assignment_on_copy(ret) + + def _update_copy(self, kwargs): + if kwargs: + kw = kwargs.copy() + kw.update(self.__original_kwargs__) + copy = self.__class__(self.callback, **kw) + return self._ensure_assignment_on_copy(copy) + else: + return self.copy() + + async def dispatch_error(self, ctx, error): + ctx.command_failed = True + cog = self.cog + try: + coro = self.on_error + except AttributeError: + pass + else: + injected = wrap_callback(coro) + if cog is not None: + await injected(cog, ctx, error) + else: + await injected(ctx, error) + + try: + if cog is not None: + local = Cog._get_overridden_method(cog.cog_command_error) + if local is not None: + wrapped = wrap_callback(local) + await wrapped(ctx, error) + finally: + ctx.bot.dispatch('command_error', ctx, error) + + async def _actual_conversion(self, ctx, converter, argument, param): + if converter is bool: + return _convert_to_bool(argument) + + try: + module = converter.__module__ + except AttributeError: + pass + else: + if module is not None and (module.startswith('discord.') and not module.endswith('converter')): + converter = getattr(converters, converter.__name__ + 'Converter', converter) + + try: + if inspect.isclass(converter): + if issubclass(converter, converters.Converter): + instance = converter() + ret = await instance.convert(ctx, argument) + return ret + else: + method = getattr(converter, 'convert', None) + if method is not None and inspect.ismethod(method): + ret = await method(ctx, argument) + return ret + elif isinstance(converter, converters.Converter): + ret = await converter.convert(ctx, argument) + return ret + except CommandError: + raise + except Exception as exc: + raise ConversionError(converter, exc) from exc + + try: + return converter(argument) + except CommandError: + raise + except Exception as exc: + try: + name = converter.__name__ + except AttributeError: + name = converter.__class__.__name__ + + raise BadArgument('Converting to "{}" failed for parameter "{}".'.format(name, param.name)) from exc + + async def do_conversion(self, ctx, converter, argument, param): + try: + origin = converter.__origin__ + except AttributeError: + pass + else: + if origin is typing.Union: + errors = [] + _NoneType = type(None) + for conv in converter.__args__: + # if we got to this part in the code, then the previous conversions have failed + # so we should just undo the view, return the default, and allow parsing to continue + # with the other parameters + if conv is _NoneType and param.kind != param.VAR_POSITIONAL: + ctx.view.undo() + return None if param.default is param.empty else param.default + + try: + value = await self._actual_conversion(ctx, conv, argument, param) + except CommandError as exc: + errors.append(exc) + else: + return value + + # if we're here, then we failed all the converters + raise BadUnionArgument(param, converter.__args__, errors) + + return await self._actual_conversion(ctx, converter, argument, param) + + def _get_converter(self, param): + converter = param.annotation + if converter is param.empty: + if param.default is not param.empty: + converter = str if param.default is None else type(param.default) + else: + converter = str + return converter + + async def transform(self, ctx, param): + required = param.default is param.empty + converter = self._get_converter(param) + consume_rest_is_special = param.kind == param.KEYWORD_ONLY and not self.rest_is_raw + view = ctx.view + view.skip_ws() + + # The greedy converter is simple -- it keeps going until it fails in which case, + # it undos the view ready for the next parameter to use instead + if type(converter) is converters._Greedy: + if param.kind == param.POSITIONAL_OR_KEYWORD or param.kind == param.POSITIONAL_ONLY: + return await self._transform_greedy_pos(ctx, param, required, converter.converter) + elif param.kind == param.VAR_POSITIONAL: + return await self._transform_greedy_var_pos(ctx, param, converter.converter) + else: + # if we're here, then it's a KEYWORD_ONLY param type + # since this is mostly useless, we'll helpfully transform Greedy[X] + # into just X and do the parsing that way. + converter = converter.converter + + if view.eof: + if param.kind == param.VAR_POSITIONAL: + raise RuntimeError() # break the loop + if required: + if self._is_typing_optional(param.annotation): + return None + raise MissingRequiredArgument(param) + return param.default + + previous = view.index + if consume_rest_is_special: + argument = view.read_rest().strip() + else: + argument = view.get_quoted_word() + view.previous = previous + + return await self.do_conversion(ctx, converter, argument, param) + + async def _transform_greedy_pos(self, ctx, param, required, converter): + view = ctx.view + result = [] + while not view.eof: + # for use with a manual undo + previous = view.index + + view.skip_ws() + try: + argument = view.get_quoted_word() + value = await self.do_conversion(ctx, converter, argument, param) + except (CommandError, ArgumentParsingError): + view.index = previous + break + else: + result.append(value) + + if not result and not required: + return param.default + return result + + async def _transform_greedy_var_pos(self, ctx, param, converter): + view = ctx.view + previous = view.index + try: + argument = view.get_quoted_word() + value = await self.do_conversion(ctx, converter, argument, param) + except (CommandError, ArgumentParsingError): + view.index = previous + raise RuntimeError() from None # break loop + else: + return value + + @property + def clean_params(self): + """OrderedDict[:class:`str`, :class:`inspect.Parameter`]: + Retrieves the parameter OrderedDict without the context or self parameters. + + Useful for inspecting signature. + """ + result = self.params.copy() + if self.cog is not None: + # first parameter is self + result.popitem(last=False) + + try: + # first/second parameter is context + result.popitem(last=False) + except Exception: + raise ValueError('Missing context parameter') from None + + return result + + @property + def full_parent_name(self): + """:class:`str`: Retrieves the fully qualified parent command name. + + This the base command name required to execute it. For example, + in ``?one two three`` the parent name would be ``one two``. + """ + entries = [] + command = self + while command.parent is not None: + command = command.parent + entries.append(command.name) + + return ' '.join(reversed(entries)) + + @property + def parents(self): + """List[:class:`Command`]: Retrieves the parents of this command. + + If the command has no parents then it returns an empty :class:`list`. + + For example in commands ``?a b c test``, the parents are ``[c, b, a]``. + + .. versionadded:: 1.1 + """ + entries = [] + command = self + while command.parent is not None: + command = command.parent + entries.append(command) + + return entries + + @property + def root_parent(self): + """Optional[:class:`Command`]: Retrieves the root parent of this command. + + If the command has no parents then it returns ``None``. + + For example in commands ``?a b c test``, the root parent is ``a``. + """ + if not self.parent: + return None + return self.parents[-1] + + @property + def qualified_name(self): + """:class:`str`: Retrieves the fully qualified command name. + + This is the full parent name with the command name as well. + For example, in ``?one two three`` the qualified name would be + ``one two three``. + """ + + parent = self.full_parent_name + if parent: + return parent + ' ' + self.name + else: + return self.name + + def __str__(self): + return self.qualified_name + + async def _parse_arguments(self, ctx): + ctx.args = [ctx] if self.cog is None else [self.cog, ctx] + ctx.kwargs = {} + args = ctx.args + kwargs = ctx.kwargs + + view = ctx.view + iterator = iter(self.params.items()) + + if self.cog is not None: + # we have 'self' as the first parameter so just advance + # the iterator and resume parsing + try: + next(iterator) + except StopIteration: + fmt = 'Callback for {0.name} command is missing "self" parameter.' + raise discord.ClientException(fmt.format(self)) + + # next we have the 'ctx' as the next parameter + try: + next(iterator) + except StopIteration: + fmt = 'Callback for {0.name} command is missing "ctx" parameter.' + raise discord.ClientException(fmt.format(self)) + + for name, param in iterator: + if param.kind == param.POSITIONAL_OR_KEYWORD or param.kind == param.POSITIONAL_ONLY: + transformed = await self.transform(ctx, param) + args.append(transformed) + elif param.kind == param.KEYWORD_ONLY: + # kwarg only param denotes "consume rest" semantics + if self.rest_is_raw: + converter = self._get_converter(param) + argument = view.read_rest() + kwargs[name] = await self.do_conversion(ctx, converter, argument, param) + else: + kwargs[name] = await self.transform(ctx, param) + break + elif param.kind == param.VAR_POSITIONAL: + if view.eof and self.require_var_positional: + raise MissingRequiredArgument(param) + while not view.eof: + try: + transformed = await self.transform(ctx, param) + args.append(transformed) + except RuntimeError: + break + + if not self.ignore_extra and not view.eof: + raise TooManyArguments('Too many arguments passed to ' + self.qualified_name) + + async def call_before_hooks(self, ctx): + # now that we're done preparing we can call the pre-command hooks + # first, call the command local hook: + cog = self.cog + if self._before_invoke is not None: + # should be cog if @commands.before_invoke is used + instance = getattr(self._before_invoke, '__self__', cog) + # __self__ only exists for methods, not functions + # however, if @command.before_invoke is used, it will be a function + if instance: + await self._before_invoke(instance, ctx) + else: + await self._before_invoke(ctx) + + # call the cog local hook if applicable: + if cog is not None: + hook = Cog._get_overridden_method(cog.cog_before_invoke) + if hook is not None: + await hook(ctx) + + # call the bot global hook if necessary + hook = ctx.bot._before_invoke + if hook is not None: + await hook(ctx) + + async def call_after_hooks(self, ctx): + cog = self.cog + if self._after_invoke is not None: + instance = getattr(self._after_invoke, '__self__', cog) + if instance: + await self._after_invoke(instance, ctx) + else: + await self._after_invoke(ctx) + + # call the cog local hook if applicable: + if cog is not None: + hook = Cog._get_overridden_method(cog.cog_after_invoke) + if hook is not None: + await hook(ctx) + + hook = ctx.bot._after_invoke + if hook is not None: + await hook(ctx) + + def _prepare_cooldowns(self, ctx): + if self._buckets.valid: + dt = ctx.message.edited_at or ctx.message.created_at + current = dt.replace(tzinfo=datetime.timezone.utc).timestamp() + bucket = self._buckets.get_bucket(ctx.message, current) + retry_after = bucket.update_rate_limit(current) + if retry_after: + raise CommandOnCooldown(bucket, retry_after) + + async def prepare(self, ctx): + ctx.command = self + + if not await self.can_run(ctx): + raise CheckFailure('The check functions for command {0.qualified_name} failed.'.format(self)) + + if self._max_concurrency is not None: + await self._max_concurrency.acquire(ctx) + + try: + if self.cooldown_after_parsing: + await self._parse_arguments(ctx) + self._prepare_cooldowns(ctx) + else: + self._prepare_cooldowns(ctx) + await self._parse_arguments(ctx) + + await self.call_before_hooks(ctx) + except: + if self._max_concurrency is not None: + await self._max_concurrency.release(ctx) + raise + + def is_on_cooldown(self, ctx): + """Checks whether the command is currently on cooldown. + + Parameters + ----------- + ctx: :class:`.Context` + The invocation context to use when checking the commands cooldown status. + + Returns + -------- + :class:`bool` + A boolean indicating if the command is on cooldown. + """ + if not self._buckets.valid: + return False + + bucket = self._buckets.get_bucket(ctx.message) + dt = ctx.message.edited_at or ctx.message.created_at + current = dt.replace(tzinfo=datetime.timezone.utc).timestamp() + return bucket.get_tokens(current) == 0 + + def reset_cooldown(self, ctx): + """Resets the cooldown on this command. + + Parameters + ----------- + ctx: :class:`.Context` + The invocation context to reset the cooldown under. + """ + if self._buckets.valid: + bucket = self._buckets.get_bucket(ctx.message) + bucket.reset() + + def get_cooldown_retry_after(self, ctx): + """Retrieves the amount of seconds before this command can be tried again. + + .. versionadded:: 1.4 + + Parameters + ----------- + ctx: :class:`.Context` + The invocation context to retrieve the cooldown from. + + Returns + -------- + :class:`float` + The amount of time left on this command's cooldown in seconds. + If this is ``0.0`` then the command isn't on cooldown. + """ + if self._buckets.valid: + bucket = self._buckets.get_bucket(ctx.message) + dt = ctx.message.edited_at or ctx.message.created_at + current = dt.replace(tzinfo=datetime.timezone.utc).timestamp() + return bucket.get_retry_after(current) + + return 0.0 + + async def invoke(self, ctx): + await self.prepare(ctx) + + # terminate the invoked_subcommand chain. + # since we're in a regular command (and not a group) then + # the invoked subcommand is None. + ctx.invoked_subcommand = None + ctx.subcommand_passed = None + injected = hooked_wrapped_callback(self, ctx, self.callback) + await injected(*ctx.args, **ctx.kwargs) + + async def reinvoke(self, ctx, *, call_hooks=False): + ctx.command = self + await self._parse_arguments(ctx) + + if call_hooks: + await self.call_before_hooks(ctx) + + ctx.invoked_subcommand = None + try: + await self.callback(*ctx.args, **ctx.kwargs) + except: + ctx.command_failed = True + raise + finally: + if call_hooks: + await self.call_after_hooks(ctx) + + def error(self, coro): + """A decorator that registers a coroutine as a local error handler. + + A local error handler is an :func:`.on_command_error` event limited to + a single command. However, the :func:`.on_command_error` is still + invoked afterwards as the catch-all. + + Parameters + ----------- + coro: :ref:`coroutine ` + The coroutine to register as the local error handler. + + Raises + ------- + TypeError + The coroutine passed is not actually a coroutine. + """ + + if not asyncio.iscoroutinefunction(coro): + raise TypeError('The error handler must be a coroutine.') + + self.on_error = coro + return coro + + def has_error_handler(self): + """:class:`bool`: Checks whether the command has an error handler registered. + + .. versionadded:: 1.7 + """ + return hasattr(self, 'on_error') + + def before_invoke(self, coro): + """A decorator that registers a coroutine as a pre-invoke hook. + + A pre-invoke hook is called directly before the command is + called. This makes it a useful function to set up database + connections or any type of set up required. + + This pre-invoke hook takes a sole parameter, a :class:`.Context`. + + See :meth:`.Bot.before_invoke` for more info. + + Parameters + ----------- + coro: :ref:`coroutine ` + The coroutine to register as the pre-invoke hook. + + Raises + ------- + TypeError + The coroutine passed is not actually a coroutine. + """ + if not asyncio.iscoroutinefunction(coro): + raise TypeError('The pre-invoke hook must be a coroutine.') + + self._before_invoke = coro + return coro + + def after_invoke(self, coro): + """A decorator that registers a coroutine as a post-invoke hook. + + A post-invoke hook is called directly after the command is + called. This makes it a useful function to clean-up database + connections or any type of clean up required. + + This post-invoke hook takes a sole parameter, a :class:`.Context`. + + See :meth:`.Bot.after_invoke` for more info. + + Parameters + ----------- + coro: :ref:`coroutine ` + The coroutine to register as the post-invoke hook. + + Raises + ------- + TypeError + The coroutine passed is not actually a coroutine. + """ + if not asyncio.iscoroutinefunction(coro): + raise TypeError('The post-invoke hook must be a coroutine.') + + self._after_invoke = coro + return coro + + @property + def cog_name(self): + """Optional[:class:`str`]: The name of the cog this command belongs to, if any.""" + return type(self.cog).__cog_name__ if self.cog is not None else None + + @property + def short_doc(self): + """:class:`str`: Gets the "short" documentation of a command. + + By default, this is the :attr:`brief` attribute. + If that lookup leads to an empty string then the first line of the + :attr:`help` attribute is used instead. + """ + if self.brief is not None: + return self.brief + if self.help is not None: + return self.help.split('\n', 1)[0] + return '' + + def _is_typing_optional(self, annotation): + try: + origin = annotation.__origin__ + except AttributeError: + return False + + if origin is not typing.Union: + return False + + return annotation.__args__[-1] is type(None) + + @property + def signature(self): + """:class:`str`: Returns a POSIX-like signature useful for help command output.""" + if self.usage is not None: + return self.usage + + + params = self.clean_params + if not params: + return '' + + result = [] + for name, param in params.items(): + greedy = isinstance(param.annotation, converters._Greedy) + + if param.default is not param.empty: + # We don't want None or '' to trigger the [name=value] case and instead it should + # do [name] since [name=None] or [name=] are not exactly useful for the user. + should_print = param.default if isinstance(param.default, str) else param.default is not None + if should_print: + result.append('[%s=%s]' % (name, param.default) if not greedy else + '[%s=%s]...' % (name, param.default)) + continue + else: + result.append('[%s]' % name) + + elif param.kind == param.VAR_POSITIONAL: + if self.require_var_positional: + result.append('<%s...>' % name) + else: + result.append('[%s...]' % name) + elif greedy: + result.append('[%s]...' % name) + elif self._is_typing_optional(param.annotation): + result.append('[%s]' % name) + else: + result.append('<%s>' % name) + + return ' '.join(result) + + async def can_run(self, ctx): + """|coro| + + Checks if the command can be executed by checking all the predicates + inside the :attr:`checks` attribute. This also checks whether the + command is disabled. + + .. versionchanged:: 1.3 + Checks whether the command is disabled or not + + Parameters + ----------- + ctx: :class:`.Context` + The ctx of the command currently being invoked. + + Raises + ------- + :class:`CommandError` + Any command error that was raised during a check call will be propagated + by this function. + + Returns + -------- + :class:`bool` + A boolean indicating if the command can be invoked. + """ + + if not self.enabled: + raise DisabledCommand('{0.name} command is disabled'.format(self)) + + original = ctx.command + ctx.command = self + + try: + if not await ctx.bot.can_run(ctx): + raise CheckFailure('The global check functions for command {0.qualified_name} failed.'.format(self)) + + cog = self.cog + if cog is not None: + local_check = Cog._get_overridden_method(cog.cog_check) + if local_check is not None: + ret = await discord.utils.maybe_coroutine(local_check, ctx) + if not ret: + return False + + predicates = self.checks + if not predicates: + # since we have no checks, then we just return True. + return True + + return await discord.utils.async_all(predicate(ctx) for predicate in predicates) + finally: + ctx.command = original + +class GroupMixin: + """A mixin that implements common functionality for classes that behave + similar to :class:`.Group` and are allowed to register commands. + + Attributes + ----------- + all_commands: :class:`dict` + A mapping of command name to :class:`.Command` + objects. + case_insensitive: :class:`bool` + Whether the commands should be case insensitive. Defaults to ``False``. + """ + def __init__(self, *args, **kwargs): + case_insensitive = kwargs.get('case_insensitive', False) + self.all_commands = _CaseInsensitiveDict() if case_insensitive else {} + self.case_insensitive = case_insensitive + super().__init__(*args, **kwargs) + + @property + def commands(self): + """Set[:class:`.Command`]: A unique set of commands without aliases that are registered.""" + return set(self.all_commands.values()) + + def recursively_remove_all_commands(self): + for command in self.all_commands.copy().values(): + if isinstance(command, GroupMixin): + command.recursively_remove_all_commands() + self.remove_command(command.name) + + def add_command(self, command): + """Adds a :class:`.Command` into the internal list of commands. + + This is usually not called, instead the :meth:`~.GroupMixin.command` or + :meth:`~.GroupMixin.group` shortcut decorators are used instead. + + .. versionchanged:: 1.4 + Raise :exc:`.CommandRegistrationError` instead of generic :exc:`.ClientException` + + Parameters + ----------- + command: :class:`Command` + The command to add. + + Raises + ------- + :exc:`.CommandRegistrationError` + If the command or its alias is already registered by different command. + TypeError + If the command passed is not a subclass of :class:`.Command`. + """ + + if not isinstance(command, Command): + raise TypeError('The command passed must be a subclass of Command') + + if isinstance(self, Command): + command.parent = self + + if command.name in self.all_commands: + raise CommandRegistrationError(command.name) + + self.all_commands[command.name] = command + for alias in command.aliases: + if alias in self.all_commands: + self.remove_command(command.name) + raise CommandRegistrationError(alias, alias_conflict=True) + self.all_commands[alias] = command + + def remove_command(self, name): + """Remove a :class:`.Command` from the internal list + of commands. + + This could also be used as a way to remove aliases. + + Parameters + ----------- + name: :class:`str` + The name of the command to remove. + + Returns + -------- + Optional[:class:`.Command`] + The command that was removed. If the name is not valid then + ``None`` is returned instead. + """ + command = self.all_commands.pop(name, None) + + # does not exist + if command is None: + return None + + if name in command.aliases: + # we're removing an alias so we don't want to remove the rest + return command + + # we're not removing the alias so let's delete the rest of them. + for alias in command.aliases: + cmd = self.all_commands.pop(alias, None) + # in the case of a CommandRegistrationError, an alias might conflict + # with an already existing command. If this is the case, we want to + # make sure the pre-existing command is not removed. + if cmd not in (None, command): + self.all_commands[alias] = cmd + return command + + def walk_commands(self): + """An iterator that recursively walks through all commands and subcommands. + + .. versionchanged:: 1.4 + Duplicates due to aliases are no longer returned + + Yields + ------ + Union[:class:`.Command`, :class:`.Group`] + A command or group from the internal list of commands. + """ + for command in self.commands: + yield command + if isinstance(command, GroupMixin): + yield from command.walk_commands() + + def get_command(self, name): + """Get a :class:`.Command` from the internal list + of commands. + + This could also be used as a way to get aliases. + + The name could be fully qualified (e.g. ``'foo bar'``) will get + the subcommand ``bar`` of the group command ``foo``. If a + subcommand is not found then ``None`` is returned just as usual. + + Parameters + ----------- + name: :class:`str` + The name of the command to get. + + Returns + -------- + Optional[:class:`Command`] + The command that was requested. If not found, returns ``None``. + """ + + # fast path, no space in name. + if ' ' not in name: + return self.all_commands.get(name) + + names = name.split() + if not names: + return None + obj = self.all_commands.get(names[0]) + if not isinstance(obj, GroupMixin): + return obj + + for name in names[1:]: + try: + obj = obj.all_commands[name] + except (AttributeError, KeyError): + return None + + return obj + + def command(self, *args, **kwargs): + """A shortcut decorator that invokes :func:`.command` and adds it to + the internal command list via :meth:`~.GroupMixin.add_command`. + + Returns + -------- + Callable[..., :class:`Command`] + A decorator that converts the provided method into a Command, adds it to the bot, then returns it. + """ + def decorator(func): + kwargs.setdefault('parent', self) + result = command(*args, **kwargs)(func) + self.add_command(result) + return result + + return decorator + + def group(self, *args, **kwargs): + """A shortcut decorator that invokes :func:`.group` and adds it to + the internal command list via :meth:`~.GroupMixin.add_command`. + + Returns + -------- + Callable[..., :class:`Group`] + A decorator that converts the provided method into a Group, adds it to the bot, then returns it. + """ + def decorator(func): + kwargs.setdefault('parent', self) + result = group(*args, **kwargs)(func) + self.add_command(result) + return result + + return decorator + +class Group(GroupMixin, Command): + """A class that implements a grouping protocol for commands to be + executed as subcommands. + + This class is a subclass of :class:`.Command` and thus all options + valid in :class:`.Command` are valid in here as well. + + Attributes + ----------- + invoke_without_command: :class:`bool` + Indicates if the group callback should begin parsing and + invocation only if no subcommand was found. Useful for + making it an error handling function to tell the user that + no subcommand was found or to have different functionality + in case no subcommand was found. If this is ``False``, then + the group callback will always be invoked first. This means + that the checks and the parsing dictated by its parameters + will be executed. Defaults to ``False``. + case_insensitive: :class:`bool` + Indicates if the group's commands should be case insensitive. + Defaults to ``False``. + """ + def __init__(self, *args, **attrs): + self.invoke_without_command = attrs.pop('invoke_without_command', False) + super().__init__(*args, **attrs) + + def copy(self): + """Creates a copy of this :class:`Group`. + + Returns + -------- + :class:`Group` + A new instance of this group. + """ + ret = super().copy() + for cmd in self.commands: + ret.add_command(cmd.copy()) + return ret + + async def invoke(self, ctx): + ctx.invoked_subcommand = None + ctx.subcommand_passed = None + early_invoke = not self.invoke_without_command + if early_invoke: + await self.prepare(ctx) + + view = ctx.view + previous = view.index + view.skip_ws() + trigger = view.get_word() + + if trigger: + ctx.subcommand_passed = trigger + ctx.invoked_subcommand = self.all_commands.get(trigger, None) + + if early_invoke: + injected = hooked_wrapped_callback(self, ctx, self.callback) + await injected(*ctx.args, **ctx.kwargs) + + ctx.invoked_parents.append(ctx.invoked_with) + + if trigger and ctx.invoked_subcommand: + ctx.invoked_with = trigger + await ctx.invoked_subcommand.invoke(ctx) + elif not early_invoke: + # undo the trigger parsing + view.index = previous + view.previous = previous + await super().invoke(ctx) + + async def reinvoke(self, ctx, *, call_hooks=False): + ctx.invoked_subcommand = None + early_invoke = not self.invoke_without_command + if early_invoke: + ctx.command = self + await self._parse_arguments(ctx) + + if call_hooks: + await self.call_before_hooks(ctx) + + view = ctx.view + previous = view.index + view.skip_ws() + trigger = view.get_word() + + if trigger: + ctx.subcommand_passed = trigger + ctx.invoked_subcommand = self.all_commands.get(trigger, None) + + if early_invoke: + try: + await self.callback(*ctx.args, **ctx.kwargs) + except: + ctx.command_failed = True + raise + finally: + if call_hooks: + await self.call_after_hooks(ctx) + + ctx.invoked_parents.append(ctx.invoked_with) + + if trigger and ctx.invoked_subcommand: + ctx.invoked_with = trigger + await ctx.invoked_subcommand.reinvoke(ctx, call_hooks=call_hooks) + elif not early_invoke: + # undo the trigger parsing + view.index = previous + view.previous = previous + await super().reinvoke(ctx, call_hooks=call_hooks) + +# Decorators + +def command(name=None, cls=None, **attrs): + """A decorator that transforms a function into a :class:`.Command` + or if called with :func:`.group`, :class:`.Group`. + + By default the ``help`` attribute is received automatically from the + docstring of the function and is cleaned up with the use of + ``inspect.cleandoc``. If the docstring is ``bytes``, then it is decoded + into :class:`str` using utf-8 encoding. + + All checks added using the :func:`.check` & co. decorators are added into + the function. There is no way to supply your own checks through this + decorator. + + Parameters + ----------- + name: :class:`str` + The name to create the command with. By default this uses the + function name unchanged. + cls + The class to construct with. By default this is :class:`.Command`. + You usually do not change this. + attrs + Keyword arguments to pass into the construction of the class denoted + by ``cls``. + + Raises + ------- + TypeError + If the function is not a coroutine or is already a command. + """ + if cls is None: + cls = Command + + def decorator(func): + if isinstance(func, Command): + raise TypeError('Callback is already a command.') + return cls(func, name=name, **attrs) + + return decorator + +def group(name=None, **attrs): + """A decorator that transforms a function into a :class:`.Group`. + + This is similar to the :func:`.command` decorator but the ``cls`` + parameter is set to :class:`Group` by default. + + .. versionchanged:: 1.1 + The ``cls`` parameter can now be passed. + """ + + attrs.setdefault('cls', Group) + return command(name=name, **attrs) + +def check(predicate): + r"""A decorator that adds a check to the :class:`.Command` or its + subclasses. These checks could be accessed via :attr:`.Command.checks`. + + These checks should be predicates that take in a single parameter taking + a :class:`.Context`. If the check returns a ``False``\-like value then + during invocation a :exc:`.CheckFailure` exception is raised and sent to + the :func:`.on_command_error` event. + + If an exception should be thrown in the predicate then it should be a + subclass of :exc:`.CommandError`. Any exception not subclassed from it + will be propagated while those subclassed will be sent to + :func:`.on_command_error`. + + A special attribute named ``predicate`` is bound to the value + returned by this decorator to retrieve the predicate passed to the + decorator. This allows the following introspection and chaining to be done: + + .. code-block:: python3 + + def owner_or_permissions(**perms): + original = commands.has_permissions(**perms).predicate + async def extended_check(ctx): + if ctx.guild is None: + return False + return ctx.guild.owner_id == ctx.author.id or await original(ctx) + return commands.check(extended_check) + + .. note:: + + The function returned by ``predicate`` is **always** a coroutine, + even if the original function was not a coroutine. + + .. versionchanged:: 1.3 + The ``predicate`` attribute was added. + + Examples + --------- + + Creating a basic check to see if the command invoker is you. + + .. code-block:: python3 + + def check_if_it_is_me(ctx): + return ctx.message.author.id == 85309593344815104 + + @bot.command() + @commands.check(check_if_it_is_me) + async def only_for_me(ctx): + await ctx.send('I know you!') + + Transforming common checks into its own decorator: + + .. code-block:: python3 + + def is_me(): + def predicate(ctx): + return ctx.message.author.id == 85309593344815104 + return commands.check(predicate) + + @bot.command() + @is_me() + async def only_me(ctx): + await ctx.send('Only you!') + + Parameters + ----------- + predicate: Callable[[:class:`Context`], :class:`bool`] + The predicate to check if the command should be invoked. + """ + + def decorator(func): + if isinstance(func, Command): + func.checks.append(predicate) + else: + if not hasattr(func, '__commands_checks__'): + func.__commands_checks__ = [] + + func.__commands_checks__.append(predicate) + + return func + + if inspect.iscoroutinefunction(predicate): + decorator.predicate = predicate + else: + @functools.wraps(predicate) + async def wrapper(ctx): + return predicate(ctx) + decorator.predicate = wrapper + + return decorator + +def check_any(*checks): + r"""A :func:`check` that is added that checks if any of the checks passed + will pass, i.e. using logical OR. + + If all checks fail then :exc:`.CheckAnyFailure` is raised to signal the failure. + It inherits from :exc:`.CheckFailure`. + + .. note:: + + The ``predicate`` attribute for this function **is** a coroutine. + + .. versionadded:: 1.3 + + Parameters + ------------ + \*checks: Callable[[:class:`Context`], :class:`bool`] + An argument list of checks that have been decorated with + the :func:`check` decorator. + + Raises + ------- + TypeError + A check passed has not been decorated with the :func:`check` + decorator. + + Examples + --------- + + Creating a basic check to see if it's the bot owner or + the server owner: + + .. code-block:: python3 + + def is_guild_owner(): + def predicate(ctx): + return ctx.guild is not None and ctx.guild.owner_id == ctx.author.id + return commands.check(predicate) + + @bot.command() + @commands.check_any(commands.is_owner(), is_guild_owner()) + async def only_for_owners(ctx): + await ctx.send('Hello mister owner!') + """ + + unwrapped = [] + for wrapped in checks: + try: + pred = wrapped.predicate + except AttributeError: + raise TypeError('%r must be wrapped by commands.check decorator' % wrapped) from None + else: + unwrapped.append(pred) + + async def predicate(ctx): + errors = [] + for func in unwrapped: + try: + value = await func(ctx) + except CheckFailure as e: + errors.append(e) + else: + if value: + return True + # if we're here, all checks failed + raise CheckAnyFailure(unwrapped, errors) + + return check(predicate) + +def has_role(item): + """A :func:`.check` that is added that checks if the member invoking the + command has the role specified via the name or ID specified. + + If a string is specified, you must give the exact name of the role, including + caps and spelling. + + If an integer is specified, you must give the exact snowflake ID of the role. + + If the message is invoked in a private message context then the check will + return ``False``. + + This check raises one of two special exceptions, :exc:`.MissingRole` if the user + is missing a role, or :exc:`.NoPrivateMessage` if it is used in a private message. + Both inherit from :exc:`.CheckFailure`. + + .. versionchanged:: 1.1 + + Raise :exc:`.MissingRole` or :exc:`.NoPrivateMessage` + instead of generic :exc:`.CheckFailure` + + Parameters + ----------- + item: Union[:class:`int`, :class:`str`] + The name or ID of the role to check. + """ + + def predicate(ctx): + if not isinstance(ctx.channel, discord.abc.GuildChannel): + raise NoPrivateMessage() + + if isinstance(item, int): + role = discord.utils.get(ctx.author.roles, id=item) + else: + role = discord.utils.get(ctx.author.roles, name=item) + if role is None: + raise MissingRole(item) + return True + + return check(predicate) + +def has_any_role(*items): + r"""A :func:`.check` that is added that checks if the member invoking the + command has **any** of the roles specified. This means that if they have + one out of the three roles specified, then this check will return `True`. + + Similar to :func:`.has_role`\, the names or IDs passed in must be exact. + + This check raises one of two special exceptions, :exc:`.MissingAnyRole` if the user + is missing all roles, or :exc:`.NoPrivateMessage` if it is used in a private message. + Both inherit from :exc:`.CheckFailure`. + + .. versionchanged:: 1.1 + + Raise :exc:`.MissingAnyRole` or :exc:`.NoPrivateMessage` + instead of generic :exc:`.CheckFailure` + + Parameters + ----------- + items: List[Union[:class:`str`, :class:`int`]] + An argument list of names or IDs to check that the member has roles wise. + + Example + -------- + + .. code-block:: python3 + + @bot.command() + @commands.has_any_role('Library Devs', 'Moderators', 492212595072434186) + async def cool(ctx): + await ctx.send('You are cool indeed') + """ + def predicate(ctx): + if not isinstance(ctx.channel, discord.abc.GuildChannel): + raise NoPrivateMessage() + + getter = functools.partial(discord.utils.get, ctx.author.roles) + if any(getter(id=item) is not None if isinstance(item, int) else getter(name=item) is not None for item in items): + return True + raise MissingAnyRole(items) + + return check(predicate) + +def bot_has_role(item): + """Similar to :func:`.has_role` except checks if the bot itself has the + role. + + This check raises one of two special exceptions, :exc:`.BotMissingRole` if the bot + is missing the role, or :exc:`.NoPrivateMessage` if it is used in a private message. + Both inherit from :exc:`.CheckFailure`. + + .. versionchanged:: 1.1 + + Raise :exc:`.BotMissingRole` or :exc:`.NoPrivateMessage` + instead of generic :exc:`.CheckFailure` + """ + + def predicate(ctx): + ch = ctx.channel + if not isinstance(ch, discord.abc.GuildChannel): + raise NoPrivateMessage() + + me = ch.guild.me + if isinstance(item, int): + role = discord.utils.get(me.roles, id=item) + else: + role = discord.utils.get(me.roles, name=item) + if role is None: + raise BotMissingRole(item) + return True + return check(predicate) + +def bot_has_any_role(*items): + """Similar to :func:`.has_any_role` except checks if the bot itself has + any of the roles listed. + + This check raises one of two special exceptions, :exc:`.BotMissingAnyRole` if the bot + is missing all roles, or :exc:`.NoPrivateMessage` if it is used in a private message. + Both inherit from :exc:`.CheckFailure`. + + .. versionchanged:: 1.1 + + Raise :exc:`.BotMissingAnyRole` or :exc:`.NoPrivateMessage` + instead of generic checkfailure + """ + def predicate(ctx): + ch = ctx.channel + if not isinstance(ch, discord.abc.GuildChannel): + raise NoPrivateMessage() + + me = ch.guild.me + getter = functools.partial(discord.utils.get, me.roles) + if any(getter(id=item) is not None if isinstance(item, int) else getter(name=item) is not None for item in items): + return True + raise BotMissingAnyRole(items) + return check(predicate) + +def has_permissions(**perms): + """A :func:`.check` that is added that checks if the member has all of + the permissions necessary. + + Note that this check operates on the current channel permissions, not the + guild wide permissions. + + The permissions passed in must be exactly like the properties shown under + :class:`.discord.Permissions`. + + This check raises a special exception, :exc:`.MissingPermissions` + that is inherited from :exc:`.CheckFailure`. + + Parameters + ------------ + perms + An argument list of permissions to check for. + + Example + --------- + + .. code-block:: python3 + + @bot.command() + @commands.has_permissions(manage_messages=True) + async def test(ctx): + await ctx.send('You can manage messages.') + + """ + + invalid = set(perms) - set(discord.Permissions.VALID_FLAGS) + if invalid: + raise TypeError('Invalid permission(s): %s' % (', '.join(invalid))) + + def predicate(ctx): + ch = ctx.channel + permissions = ch.permissions_for(ctx.author) + + missing = [perm for perm, value in perms.items() if getattr(permissions, perm) != value] + + if not missing: + return True + + raise MissingPermissions(missing) + + return check(predicate) + +def bot_has_permissions(**perms): + """Similar to :func:`.has_permissions` except checks if the bot itself has + the permissions listed. + + This check raises a special exception, :exc:`.BotMissingPermissions` + that is inherited from :exc:`.CheckFailure`. + """ + + invalid = set(perms) - set(discord.Permissions.VALID_FLAGS) + if invalid: + raise TypeError('Invalid permission(s): %s' % (', '.join(invalid))) + + def predicate(ctx): + guild = ctx.guild + me = guild.me if guild is not None else ctx.bot.user + permissions = ctx.channel.permissions_for(me) + + missing = [perm for perm, value in perms.items() if getattr(permissions, perm) != value] + + if not missing: + return True + + raise BotMissingPermissions(missing) + + return check(predicate) + +def has_guild_permissions(**perms): + """Similar to :func:`.has_permissions`, but operates on guild wide + permissions instead of the current channel permissions. + + If this check is called in a DM context, it will raise an + exception, :exc:`.NoPrivateMessage`. + + .. versionadded:: 1.3 + """ + + invalid = set(perms) - set(discord.Permissions.VALID_FLAGS) + if invalid: + raise TypeError('Invalid permission(s): %s' % (', '.join(invalid))) + + def predicate(ctx): + if not ctx.guild: + raise NoPrivateMessage + + permissions = ctx.author.guild_permissions + missing = [perm for perm, value in perms.items() if getattr(permissions, perm) != value] + + if not missing: + return True + + raise MissingPermissions(missing) + + return check(predicate) + +def bot_has_guild_permissions(**perms): + """Similar to :func:`.has_guild_permissions`, but checks the bot + members guild permissions. + + .. versionadded:: 1.3 + """ + + invalid = set(perms) - set(discord.Permissions.VALID_FLAGS) + if invalid: + raise TypeError('Invalid permission(s): %s' % (', '.join(invalid))) + + def predicate(ctx): + if not ctx.guild: + raise NoPrivateMessage + + permissions = ctx.me.guild_permissions + missing = [perm for perm, value in perms.items() if getattr(permissions, perm) != value] + + if not missing: + return True + + raise BotMissingPermissions(missing) + + return check(predicate) + +def dm_only(): + """A :func:`.check` that indicates this command must only be used in a + DM context. Only private messages are allowed when + using the command. + + This check raises a special exception, :exc:`.PrivateMessageOnly` + that is inherited from :exc:`.CheckFailure`. + + .. versionadded:: 1.1 + """ + + def predicate(ctx): + if ctx.guild is not None: + raise PrivateMessageOnly() + return True + + return check(predicate) + +def guild_only(): + """A :func:`.check` that indicates this command must only be used in a + guild context only. Basically, no private messages are allowed when + using the command. + + This check raises a special exception, :exc:`.NoPrivateMessage` + that is inherited from :exc:`.CheckFailure`. + """ + + def predicate(ctx): + if ctx.guild is None: + raise NoPrivateMessage() + return True + + return check(predicate) + +def is_owner(): + """A :func:`.check` that checks if the person invoking this command is the + owner of the bot. + + This is powered by :meth:`.Bot.is_owner`. + + This check raises a special exception, :exc:`.NotOwner` that is derived + from :exc:`.CheckFailure`. + """ + + async def predicate(ctx): + if not await ctx.bot.is_owner(ctx.author): + raise NotOwner('You do not own this bot.') + return True + + return check(predicate) + +def is_nsfw(): + """A :func:`.check` that checks if the channel is a NSFW channel. + + This check raises a special exception, :exc:`.NSFWChannelRequired` + that is derived from :exc:`.CheckFailure`. + + .. versionchanged:: 1.1 + + Raise :exc:`.NSFWChannelRequired` instead of generic :exc:`.CheckFailure`. + DM channels will also now pass this check. + """ + def pred(ctx): + ch = ctx.channel + if ctx.guild is None or (isinstance(ch, discord.TextChannel) and ch.is_nsfw()): + return True + raise NSFWChannelRequired(ch) + return check(pred) + +def cooldown(rate, per, type=BucketType.default): + """A decorator that adds a cooldown to a :class:`.Command` + + A cooldown allows a command to only be used a specific amount + of times in a specific time frame. These cooldowns can be based + either on a per-guild, per-channel, per-user, per-role or global basis. + Denoted by the third argument of ``type`` which must be of enum + type :class:`.BucketType`. + + If a cooldown is triggered, then :exc:`.CommandOnCooldown` is triggered in + :func:`.on_command_error` and the local error handler. + + A command can only have a single cooldown. + + Parameters + ------------ + rate: :class:`int` + The number of times a command can be used before triggering a cooldown. + per: :class:`float` + The amount of seconds to wait for a cooldown when it's been triggered. + type: Union[:class:`.BucketType`, Callable[[:class:`.Message`], Any]] + The type of cooldown to have. If callable, should return a key for the mapping. + + .. versionchanged:: 1.7 + Callables are now supported for custom bucket types. + """ + + def decorator(func): + if isinstance(func, Command): + func._buckets = CooldownMapping(Cooldown(rate, per, type)) + else: + func.__commands_cooldown__ = Cooldown(rate, per, type) + return func + return decorator + +def max_concurrency(number, per=BucketType.default, *, wait=False): + """A decorator that adds a maximum concurrency to a :class:`.Command` or its subclasses. + + This enables you to only allow a certain number of command invocations at the same time, + for example if a command takes too long or if only one user can use it at a time. This + differs from a cooldown in that there is no set waiting period or token bucket -- only + a set number of people can run the command. + + .. versionadded:: 1.3 + + Parameters + ------------- + number: :class:`int` + The maximum number of invocations of this command that can be running at the same time. + per: :class:`.BucketType` + The bucket that this concurrency is based on, e.g. ``BucketType.guild`` would allow + it to be used up to ``number`` times per guild. + wait: :class:`bool` + Whether the command should wait for the queue to be over. If this is set to ``False`` + then instead of waiting until the command can run again, the command raises + :exc:`.MaxConcurrencyReached` to its error handler. If this is set to ``True`` + then the command waits until it can be executed. + """ + + def decorator(func): + value = MaxConcurrency(number, per=per, wait=wait) + if isinstance(func, Command): + func._max_concurrency = value + else: + func.__commands_max_concurrency__ = value + return func + return decorator + +def before_invoke(coro): + """A decorator that registers a coroutine as a pre-invoke hook. + + This allows you to refer to one before invoke hook for several commands that + do not have to be within the same cog. + + .. versionadded:: 1.4 + + Example + --------- + + .. code-block:: python3 + + async def record_usage(ctx): + print(ctx.author, 'used', ctx.command, 'at', ctx.message.created_at) + + @bot.command() + @commands.before_invoke(record_usage) + async def who(ctx): # Output: used who at