From eb70cd7c9125547ae311c33da2d382dd39606721 Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Fri, 2 Sep 2022 23:21:58 -0400 Subject: [PATCH 001/127] relocate all files into an actual overarching python module this facilitates packaging and relative imports also fixes some await issues and adds some type hints --- Main.py => canary/Main.py | 39 ++++--- {cogs => canary}/__init__.py | 0 bot.py => canary/bot.py | 12 +-- canary/cogs/__init__.py | 0 {cogs => canary/cogs}/banner.py | 35 +++--- {cogs => canary/cogs}/currency.py | 36 +++---- {cogs => canary/cogs}/customreactions.py | 14 +-- {cogs => canary/cogs}/games.py | 9 +- {cogs => canary/cogs}/helpers.py | 65 ++++++------ {cogs => canary/cogs}/images.py | 31 +++--- {cogs => canary/cogs}/info.py | 0 {cogs => canary/cogs}/memes.py | 9 +- {cogs => canary/cogs}/mod.py | 0 {cogs => canary/cogs}/music.py | 58 +++++----- {cogs => canary/cogs}/quotes.py | 100 +++++++++--------- {cogs => canary/cogs}/reminder.py | 19 ++-- {cogs => canary/cogs}/roles.py | 26 ++--- {cogs => canary/cogs}/score.py | 40 ++++--- {cogs => canary/cogs}/subscribers.py | 11 +- {cogs => canary/cogs}/utils/__init__.py | 0 {cogs => canary/cogs}/utils/arg_converter.py | 0 {cogs => canary/cogs}/utils/auto_incorrect.py | 0 {cogs => canary/cogs}/utils/checks.py | 0 {cogs => canary/cogs}/utils/clamp_default.py | 0 .../cogs}/utils/custom_requests.py | 0 {cogs => canary/cogs}/utils/dice_roll.py | 0 {cogs => canary/cogs}/utils/hangman.py | 0 {cogs => canary/cogs}/utils/image_helpers.py | 0 {cogs => canary/cogs}/utils/members.py | 0 {cogs => canary/cogs}/utils/mock_context.py | 0 {cogs => canary/cogs}/utils/music_helpers.py | 0 {cogs => canary/cogs}/utils/p_strings.py | 0 {cogs => canary/cogs}/utils/paginator.py | 0 .../cogs}/utils/role_restoration.py | 0 {cogs => canary/cogs}/utils/site_save.py | 0 {cogs => canary/cogs}/utils/subscribers.py | 0 pyproject.toml | 3 + 37 files changed, 266 insertions(+), 241 deletions(-) rename Main.py => canary/Main.py (90%) rename {cogs => canary}/__init__.py (100%) rename bot.py => canary/bot.py (93%) create mode 100644 canary/cogs/__init__.py rename {cogs => canary/cogs}/banner.py (97%) rename {cogs => canary/cogs}/currency.py (95%) rename {cogs => canary/cogs}/customreactions.py (99%) rename {cogs => canary/cogs}/games.py (98%) rename {cogs => canary/cogs}/helpers.py (95%) rename {cogs => canary/cogs}/images.py (75%) rename {cogs => canary/cogs}/info.py (100%) rename {cogs => canary/cogs}/memes.py (98%) rename {cogs => canary/cogs}/mod.py (100%) rename {cogs => canary/cogs}/music.py (93%) rename {cogs => canary/cogs}/quotes.py (84%) rename {cogs => canary/cogs}/reminder.py (96%) rename {cogs => canary/cogs}/roles.py (91%) rename {cogs => canary/cogs}/score.py (96%) rename {cogs => canary/cogs}/subscribers.py (96%) rename {cogs => canary/cogs}/utils/__init__.py (100%) rename {cogs => canary/cogs}/utils/arg_converter.py (100%) rename {cogs => canary/cogs}/utils/auto_incorrect.py (100%) rename {cogs => canary/cogs}/utils/checks.py (100%) rename {cogs => canary/cogs}/utils/clamp_default.py (100%) rename {cogs => canary/cogs}/utils/custom_requests.py (100%) rename {cogs => canary/cogs}/utils/dice_roll.py (100%) rename {cogs => canary/cogs}/utils/hangman.py (100%) rename {cogs => canary/cogs}/utils/image_helpers.py (100%) rename {cogs => canary/cogs}/utils/members.py (100%) rename {cogs => canary/cogs}/utils/mock_context.py (100%) rename {cogs => canary/cogs}/utils/music_helpers.py (100%) rename {cogs => canary/cogs}/utils/p_strings.py (100%) rename {cogs => canary/cogs}/utils/paginator.py (100%) rename {cogs => canary/cogs}/utils/role_restoration.py (100%) rename {cogs => canary/cogs}/utils/site_save.py (100%) rename {cogs => canary/cogs}/utils/subscribers.py (100%) diff --git a/Main.py b/canary/Main.py similarity index 90% rename from Main.py rename to canary/Main.py index fe932bb89..7df5ec543 100755 --- a/Main.py +++ b/canary/Main.py @@ -1,6 +1,6 @@ #! /usr/bin/env python3 # -# Copyright (C) idoneam (2016-2020) +# Copyright (C) idoneam (2016-2022) # # This file is part of Canary # @@ -23,31 +23,30 @@ # Other utilities import os import sys -import subprocess from datetime import datetime from pytz import timezone -from bot import bot +from canary.bot import bot import sqlite3 from cogs.utils.checks import is_developer, is_moderator -startup = [ - "cogs.banner", - "cogs.currency", - "cogs.customreactions", - "cogs.games", - "cogs.helpers", - "cogs.images", - "cogs.info", - "cogs.memes", - "cogs.mod", - "cogs.music", - "cogs.quotes", - "cogs.reminder", - "cogs.roles", - "cogs.score", - "cogs.subscribers", # Do not remove this terminating comma. -] +startup = [f"cogs.{c}" for c in ( + "banner", + "currency", + "customreactions", + "games", + "helpers", + "images", + "info", + "memes", + "mod", + "music", + "quotes", + "reminder", + "roles", + "score", + "subscribers", # Do not remove this terminating comma. +)] @bot.event diff --git a/cogs/__init__.py b/canary/__init__.py similarity index 100% rename from cogs/__init__.py rename to canary/__init__.py diff --git a/bot.py b/canary/bot.py similarity index 93% rename from bot.py rename to canary/bot.py index 535f089e7..e57ea63d3 100644 --- a/bot.py +++ b/canary/bot.py @@ -1,6 +1,3 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- -# # Copyright (C) idoneam (2016-2022) # # This file is part of Canary @@ -24,10 +21,9 @@ import logging import sqlite3 import traceback -import requests from discord import Webhook, RequestsWebhookAdapter, Intents -__all__ = ["bot", "developer_role", "moderator_role", "muted_role"] +__all__ = ["Canary", "bot", "developer_role", "moderator_role", "muted_role"] _parser = parser.Parser() command_prefix = _parser.command_prefix @@ -126,11 +122,11 @@ async def on_command_error(self, ctx, error): return elif isinstance(error, commands.DisabledCommand): - return await ctx.send("{} has been disabled.".format(ctx.command)) + return await ctx.send(f"{ctx.command} has been disabled.") elif isinstance(error, commands.NoPrivateMessage): try: - return await ctx.author.send("{} can not be used in Private Messages.".format(ctx.command)) + return await ctx.author.send(f"{ctx.command} can not be used in Private Messages.") except Exception: pass @@ -146,7 +142,7 @@ async def on_command_error(self, ctx, error): f"per {error.per.name}" ) - self.dev_logger.error("Ignoring exception in command {}:".format(ctx.command)) + self.dev_logger.error(f"Ignoring exception in command {ctx.command}:") self.log_traceback(error) diff --git a/canary/cogs/__init__.py b/canary/cogs/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/cogs/banner.py b/canary/cogs/banner.py similarity index 97% rename from cogs/banner.py rename to canary/cogs/banner.py index d1bbf0009..d2b3e766b 100644 --- a/cogs/banner.py +++ b/canary/cogs/banner.py @@ -21,31 +21,36 @@ from discord import utils # Other utilities -from io import BytesIO +import asyncio import datetime +import json import sqlite3 import requests +from io import BytesIO from PIL import Image, UnidentifiedImageError, ImageSequence -import json + +from ..bot import Canary from .utils.checks import is_moderator -import asyncio class Banner(commands.Cog): # Written by @le-potate - def __init__(self, bot): + def __init__(self, bot: Canary): self.bot = bot - self.guild = None - self.banner_reminders_role = None - self.banner_of_the_week_channel = None - self.banner_submissions_channel = None - self.banner_converted_channel = None - self.bots_channel = None - self.banner_winner_role = None - self.banner_vote_emoji = None - self.start_datetime = None - self.week_name = None - self.send_reminder = None + self.guild: discord.Guild | None = None + + self.banner_of_the_week_channel: discord.TextChannel | None = None + self.banner_submissions_channel: discord.TextChannel | None = None + self.banner_converted_channel: discord.TextChannel | None = None + self.bots_channel: discord.TextChannel | None = None + + self.banner_reminders_role: discord.Role | None = None + self.banner_winner_role: discord.Role | None = None + self.banner_vote_emoji: discord.Emoji | None = None + + self.start_datetime: datetime.datetime | None = None + self.week_name: str | None = None + self.send_reminder: str | None = None @commands.Cog.listener() async def on_ready(self): diff --git a/cogs/currency.py b/canary/cogs/currency.py similarity index 95% rename from cogs/currency.py rename to canary/cogs/currency.py index d2f9c05b6..ba66b07e8 100644 --- a/cogs/currency.py +++ b/canary/cogs/currency.py @@ -1,6 +1,4 @@ -# -*- coding: utf-8 -*- -# -# Copyright (C) idoneam (2016-2019) +# Copyright (C) idoneam (2016-2022) # # This file is part of Canary # @@ -22,7 +20,7 @@ from discord.ext import commands # For type hinting -from typing import Dict, List, Optional, Tuple +from ..bot import Canary # For DB functionality import sqlite3 @@ -69,12 +67,12 @@ class Currency(commands.Cog): - def __init__(self, bot): - self.bot = bot - self.currency = self.bot.config.currency - self.prec = self.currency["precision"] + def __init__(self, bot: Canary): + self.bot: Canary = bot + self.currency: dict = self.bot.config.currency + self.prec: int = self.currency["precision"] - async def fetch_all_balances(self) -> List[Tuple[str, str, Decimal]]: + async def fetch_all_balances(self) -> list[tuple[str, str, Decimal]]: conn = sqlite3.connect(self.bot.config.db_path) c = conn.cursor() c.execute( @@ -102,7 +100,7 @@ async def fetch_bank_balance(self, user: discord.Member) -> Decimal: return balance - async def create_bank_transaction(self, c, user: discord.Member, amount: Decimal, action: str, metadata: Dict): + async def create_bank_transaction(self, c, user: discord.Member, amount: Decimal, action: str, metadata: dict): # Don't create another connection in this function in order to properly # transaction-ify a series of bank "transactions". @@ -117,15 +115,16 @@ async def create_bank_transaction(self, c, user: discord.Member, amount: Decimal t = (user.id, self.currency_to_db(amount), action, json.dumps(metadata), now) c.execute("INSERT INTO BankTransactions(UserID, Amount, Action, " "Metadata, Date) VALUES(?, ?, ?, ?, ?)", t) - def parse_currency(self, amount: str, balance: Decimal): + @staticmethod + def parse_currency(amount: str, balance: Decimal): if amount.lower().strip() in CURRENCY_ALL: return balance - else: - try: - return Decimal(amount) - except InvalidOperation: - # Value error (invalid conversion) - return None + + try: + return Decimal(amount) + except InvalidOperation: + # Value error (invalid conversion) + return None def currency_to_db(self, amount: Decimal): return int(amount * Decimal(10 ** self.currency["precision"])) @@ -139,7 +138,8 @@ def format_currency(self, amount: Decimal): def format_symbol_currency(self, amount: Decimal): return self.currency["symbol"] + self.format_currency(amount) - def check_bet(self, balance: Decimal, bet: Decimal) -> Optional[str]: + @staticmethod + def check_bet(balance: Decimal, bet: Decimal) -> str | None: """ Checks universally invalid betting cases. """ diff --git a/cogs/customreactions.py b/canary/cogs/customreactions.py similarity index 99% rename from cogs/customreactions.py rename to canary/cogs/customreactions.py index c5470a499..520c37159 100644 --- a/cogs/customreactions.py +++ b/canary/cogs/customreactions.py @@ -1,4 +1,4 @@ -# Copyright (C) idoneam (2016-2021) +# Copyright (C) idoneam (2016-2022) # # This file is part of Canary # @@ -21,10 +21,9 @@ import asyncio # Other utilities -import random import sqlite3 +from ..bot import Canary from .utils.paginator import Pages -import time from .utils.p_strings import PStringEncodings EMOJI = { @@ -58,11 +57,11 @@ class CustomReactions(commands.Cog): # Written by @le-potate - def __init__(self, bot): - self.bot = bot + def __init__(self, bot: Canary): + self.bot: Canary = bot self.reaction_list = [] self.proposal_list = [] - self.p_strings = None + self.p_strings: PStringEncodings | None = None self.rebuild_lists() def rebuild_lists(self): @@ -95,6 +94,9 @@ async def on_message(self, message): if message.author == self.bot.user: return + if self.p_strings is None: + return + response = self.p_strings.parser( message.content.lower(), user=message.author.mention, channel=str(message.channel) ) diff --git a/cogs/games.py b/canary/cogs/games.py similarity index 98% rename from cogs/games.py rename to canary/cogs/games.py index 77a9cf49f..2a7048a95 100644 --- a/cogs/games.py +++ b/canary/cogs/games.py @@ -1,6 +1,4 @@ -# -*- coding: utf-8 -*- -# -# Copyright (C) idoneam (2016-2019) +# Copyright (C) idoneam (2016-2022) # # This file is part of Canary # @@ -31,6 +29,7 @@ import asyncio from typing import Optional from functools import partial +from ..bot import Canary from .utils.dice_roll import dice_roll from .utils.clamp_default import clamp_default from .utils.hangman import HangmanState @@ -47,8 +46,8 @@ class Games(commands.Cog): - def __init__(self, bot, hangman_tbl_name: str): - self.bot = bot + def __init__(self, bot: Canary, hangman_tbl_name: str): + self.bot: Canary = bot self.hm_cool_win: int = bot.config.games["hm_cool_win"] self.hm_norm_win: int = bot.config.games["hm_norm_win"] self.hm_timeout: int = bot.config.games["hm_timeout"] diff --git a/cogs/helpers.py b/canary/cogs/helpers.py similarity index 95% rename from cogs/helpers.py rename to canary/cogs/helpers.py index 1a42e6275..4cfe57b36 100644 --- a/cogs/helpers.py +++ b/canary/cogs/helpers.py @@ -29,20 +29,20 @@ import cv2 import numpy as np import googletrans -import os # Other utilities -import re -import math -import time import datetime +import math import random +import re +import sqlite3 +import time +from ..bot import Canary +from .utils.arg_converter import ArgConverter, StrConverter from .utils.paginator import Pages from .utils.custom_requests import fetch from .utils.site_save import site_save -from .utils.checks import is_moderator, is_developer -import sqlite3 -from .utils.arg_converter import ArgConverter, StrConverter +from .utils.checks import is_developer from discord.ext.commands import MessageConverter MCGILL_EXAM_URL = "https://www.mcgill.ca/exams/dates" @@ -71,8 +71,8 @@ class Helpers(commands.Cog): - def __init__(self, bot): - self.bot = bot + def __init__(self, bot: Canary): + self.bot: Canary = bot self.guild: discord.Guild | None = None @commands.Cog.listener() @@ -80,7 +80,7 @@ async def on_ready(self): self.guild = self.bot.get_guild(self.bot.config.server_id) @commands.command(aliases=["exams"]) - async def exam(self, ctx): + async def exam(self, ctx: commands.Context): """Retrieves the exam schedule link from McGill's Exam website.""" await ctx.trigger_typing() @@ -133,7 +133,7 @@ def _calculate_feels_like(temp: float, humidity: float, ws_kph: float) -> str: @commands.command() @site_save("http://weather.gc.ca/city/pages/qc-147_metric_e.html") - async def weather(self, ctx): + async def weather(self, ctx: commands.Context): """ Retrieves current weather conditions. Data taken from http://weather.gc.ca/city/pages/qc-147_metric_e.html @@ -216,19 +216,19 @@ def retrieve_string(label): await ctx.send(embed=weather_alert) @commands.command() - async def wttr(self, ctx): + async def wttr(self, ctx: commands.Context): """Retrieves Montreal's weather forecast from wttr.in""" await ctx.send(self.bot.config.wttr_in_tpl.format(round(time.time()))) @commands.command(aliases=["wttrmoon"]) - async def wttr_moon(self, ctx): + async def wttr_moon(self, ctx: commands.Context): """Retrieves the current moon phase from wttr.in/moon""" await ctx.send(WTTR_IN_MOON_URL) @commands.command() - async def course(self, ctx, *, query: str): + async def course(self, ctx: commands.Context, *, query: str): """Prints a summary of the queried course, taken from the course - calendar. ie. ?course comp 206 + calendar. i.e. ?course comp 206 Note: Bullet points without colons (':') are not parsed because I have yet to see one that actually has useful information. """ @@ -274,7 +274,7 @@ async def course(self, ctx, *, query: str): await ctx.send(embed=em) @commands.command() - async def keydates(self, ctx): + async def keydates(self, ctx: commands.Context): """Retrieves the important dates for the current term (Winter from January-April, Fall from May-December).""" @@ -334,7 +334,7 @@ async def keydates(self, ctx): await ctx.send(embed=em) @commands.command() - async def urban(self, ctx, *, query): + async def urban(self, ctx: commands.Context, *, query: str): """Fetches the top definitions from Urban Dictionary""" await ctx.trigger_typing() @@ -344,7 +344,7 @@ async def urban(self, ctx, *, query): definitions = definitions["list"][:5] if not definitions: - await ctx.send("No definition found for **%s**." % query) + await ctx.send(f"No definition found for **{query}**.") return markdown_url = f"[{definitions[0]['word']}]({url})" @@ -360,7 +360,7 @@ async def urban(self, ctx, *, query): p = Pages( ctx, item_list=definitions_list_text, - title="Definitions for '{}' from Urban Dictionary:".format(query), + title=f"Definitions for '{query}' from Urban Dictionary:", display_option=(3, 1), editable_content=False, ) @@ -413,7 +413,7 @@ async def tex(self, ctx, *, query: str): await ctx.send(file=discord.File(fp=img_bytes, filename=fn)) @commands.command() - async def search(self, ctx, *, query: str): + async def search(self, ctx: commands.Context, *, query: str): """Shows results for the queried keyword(s) in McGill courses""" keyword = query.replace(" ", "+") @@ -455,7 +455,7 @@ async def search(self, ctx, *, query: str): await p.paginate() @commands.command() - async def mose(self, ctx, dollar: float): + async def mose(self, ctx: commands.Context, dollar: float): """Currency conversion. Converts $$$ to the equivalent number of samosas, based on holy prices. Usage: `?mose ` @@ -468,23 +468,23 @@ async def mose(self, ctx, dollar: float): await ctx.send("${:.2f} is worth {} samosas.".format(dollar, total)) @commands.command() - async def tepid(self, ctx): + async def tepid(self, ctx: commands.Context): """Retrieves the CTF printers' statuses from tepid.science.mcgill.ca""" data = await fetch(self.bot.config.tepid_url, "json") for key, value in data.items(): await ctx.send(f"At least one printer in {key} is up!" if value else f"Both printers in {key} are down.") @commands.command() - async def modpow(self, ctx, a, b, m): + async def modpow(self, ctx: commands.Context, a, b, m): """Calculates a^b mod m, where a, b, c are big integers""" try: a, b, m = map(int, (a, b, m)) await ctx.send(pow(a, b, m)) except ValueError: - ctx.send("Input must be integers") + await ctx.send("Input must be integers") @commands.command(aliases=["foodspot", "fs", "food", "foodspotting", "food_spotting"]) - async def food_spot(self, ctx, *args): + async def food_spot(self, ctx: commands.Context, *args): # Written by @le-potate """Posts a food sale in #foodspotting. Use: `?foodspot Samosas in leacock` @@ -513,7 +513,7 @@ async def food_spot(self, ctx, *args): await channel.send(embed=embed) @commands.command() - async def choose(self, ctx, *, input_opts: str): + async def choose(self, ctx: commands.Context, *, input_opts: str): """ Randomly chooses one of the given options delimited by semicola or commas. @@ -525,7 +525,7 @@ async def choose(self, ctx, *, input_opts: str): await ctx.send(embed=embed) @commands.command(aliases=["color"]) - async def colour(self, ctx, *, arg: str): + async def colour(self, ctx: commands.Context, *, arg: str): """Shows a small image filled with the given hex colour. Usage: `?colour hex` """ @@ -551,7 +551,7 @@ async def colour(self, ctx, *, arg: str): await ctx.send(file=discord.File(fp=buffer, filename=fn)) @commands.command(aliases=["ui", "av", "avi", "userinfo"]) - async def user_info(self, ctx, user: discord.Member = None): + async def user_info(self, ctx: commands.Context, user: discord.Member | None = None): """ Show user info and avatar. Displays the information of the user @@ -576,7 +576,7 @@ async def user_info(self, ctx, user: discord.Member = None): await ctx.send(embed=ui_embed) @commands.command(aliases=["trans"]) - async def translate(self, ctx, command: str, *, inp_str: str = None): + async def translate(self, ctx: commands.Context, command: str, *, inp_str: str | None = None): """ Command used to translate some text from one language to another Takes two arguments: the source/target languages and the text to translate @@ -628,7 +628,6 @@ async def translate(self, ctx, command: str, *, inp_str: str = None): return source = codes[0].lower().strip() translator = googletrans.Translator() - detection = None if source == "": detection = translator.detect(inp_str) source = detection.lang @@ -652,7 +651,7 @@ async def translate(self, ctx, command: str, *, inp_str: str = None): @commands.max_concurrency(1, per=commands.BucketType.user, wait=False) @commands.command() @is_developer() - async def create_main_webhooks(self, ctx): + async def create_main_webhooks(self, ctx: commands.Context): """ Create the general-use webhooks for each channel. Ignores channels that already have them """ @@ -676,7 +675,7 @@ async def create_main_webhooks(self, ctx): await ctx.send(f"Ignored {ignored} channel{'s' if ignored == 1 else ''} without bot permissions") await ctx.send("Job completed.") - async def spoilerize_utility(self, ctx, message, reason: str = None, moderator: bool = False): + async def spoilerize_utility(self, ctx: commands.Context, message, reason: str = None, moderator: bool = False): if not moderator and ctx.author != message.author: return # get the webhook for this channel @@ -759,7 +758,7 @@ async def on_raw_reaction_add(self, payload): conn.close() @commands.command(alias=["spoiler"]) - async def spoilerize(self, ctx, *args): + async def spoilerize(self, ctx: commands.Context, *args): """ Spoilerize a message or a range of messages (max 30 messages) diff --git a/cogs/images.py b/canary/cogs/images.py similarity index 75% rename from cogs/images.py rename to canary/cogs/images.py index dda476967..a8f124619 100644 --- a/cogs/images.py +++ b/canary/cogs/images.py @@ -20,16 +20,17 @@ # misc imports import os +from ..bot import Canary from .utils import image_helpers as ih class Images(commands.Cog): - def __init__(self, bot): - self.bot = bot - self.max_size = self.bot.config.images["max_image_size"] - self.hist_lim = self.bot.config.images["image_history_limit"] - self.max_rad = self.bot.config.images["max_radius"] - self.max_itr = self.bot.config.images["max_iterations"] + def __init__(self, bot: Canary): + self.bot: Canary = bot + self.max_size: int = self.bot.config.images["max_image_size"] + self.hist_lim: int = self.bot.config.images["image_history_limit"] + self.max_rad: int = self.bot.config.images["max_radius"] + self.max_itr: int = self.bot.config.images["max_iterations"] @commands.Cog.listener() async def on_ready(self): @@ -37,63 +38,63 @@ async def on_ready(self): os.mkdir("./tmp/", mode=0o755) @commands.command() - async def polar(self, ctx): + async def polar(self, ctx: commands.Context): """ Transform Cartesian to polar coordinates. """ await ih.filter_image(self.bot.loop, ih.polar, ctx, self.hist_lim, self.max_size) @commands.command() - async def cart(self, ctx): + async def cart(self, ctx: commands.Context): """ Transform from polar to Cartesian coordinates. """ await ih.filter_image(self.bot.loop, ih.cart, ctx, self.hist_lim, self.max_size) @commands.command() - async def blur(self, ctx, iterations: int = 1): + async def blur(self, ctx: commands.Context, iterations: int = 1): """ Blur the image """ await ih.filter_image(self.bot.loop, ih.blur, ctx, self.hist_lim, self.max_size, iterations, self.max_itr) @commands.command(aliases=["left", "right"]) - async def hblur(self, ctx, radius: int = 10): + async def hblur(self, ctx: commands.Context, radius: int = 10): """ Blur the image horizontally """ await ih.filter_image(self.bot.loop, ih.hblur, ctx, self.hist_lim, self.max_size, radius, self.max_rad) @commands.command(aliases=["up", "down"]) - async def vblur(self, ctx, radius: int = 10): + async def vblur(self, ctx: commands.Context, radius: int = 10): """ Blur the image vertically """ await ih.filter_image(self.bot.loop, ih.vblur, ctx, self.hist_lim, self.max_size, radius, self.max_rad) @commands.command(aliases=["zoom", "radial"]) - async def rblur(self, ctx, radius: int = 10): + async def rblur(self, ctx: commands.Context, radius: int = 10): """ Radial blur """ await ih.filter_image(self.bot.loop, ih.rblur, ctx, self.hist_lim, self.max_size, radius, self.max_rad) @commands.command(aliases=["circle", "circular", "spin"]) - async def cblur(self, ctx, radius: int = 10): + async def cblur(self, ctx: commands.Context, radius: int = 10): """ Circular blur """ await ih.filter_image(self.bot.loop, ih.cblur, ctx, self.hist_lim, self.max_size, radius, self.max_rad) @commands.command(aliases=["df", "dfry", "fry"]) - async def deepfry(self, ctx, iterations: int = 1): + async def deepfry(self, ctx: commands.Context, iterations: int = 1): """ Deep fry an image, mhmm """ await ih.filter_image(self.bot.loop, ih.deepfry, ctx, self.hist_lim, self.max_size, iterations, self.max_itr) @commands.command() - async def noise(self, ctx, iterations: int = 1): + async def noise(self, ctx: commands.Context, iterations: int = 1): """ Add some noise to tha image!! """ diff --git a/cogs/info.py b/canary/cogs/info.py similarity index 100% rename from cogs/info.py rename to canary/cogs/info.py diff --git a/cogs/memes.py b/canary/cogs/memes.py similarity index 98% rename from cogs/memes.py rename to canary/cogs/memes.py index 8655bfe04..ee4a457a8 100644 --- a/cogs/memes.py +++ b/canary/cogs/memes.py @@ -1,4 +1,4 @@ -# Copyright (C) idoneam (2016-2021) +# Copyright (C) idoneam (2016-2022) # # This file is part of Canary # @@ -20,14 +20,15 @@ import discord # Other utilities -import random import aiohttp +import random +from ..bot import Canary from .utils.auto_incorrect import auto_incorrect class Memes(commands.Cog): - def __init__(self, bot): - self.bot = bot + def __init__(self, bot: Canary): + self.bot: Canary = bot @commands.command() async def bac(self, ctx, *, input_str: str = None): diff --git a/cogs/mod.py b/canary/cogs/mod.py similarity index 100% rename from cogs/mod.py rename to canary/cogs/mod.py diff --git a/cogs/music.py b/canary/cogs/music.py similarity index 93% rename from cogs/music.py rename to canary/cogs/music.py index 06ad1ee5a..b101695da 100644 --- a/cogs/music.py +++ b/canary/cogs/music.py @@ -28,6 +28,7 @@ import discord import yt_dlp from discord.ext import commands +from ..bot import Canary from .utils.music_helpers import ( FFMPEG_BEFORE_OPTS, FFMPEG_OPTS, @@ -47,8 +48,8 @@ class Music(commands.Cog): - def __init__(self, bot): - self.bot = bot + def __init__(self, bot: Canary): + self.bot: Canary = bot self.track_queue: deque = deque() self.track_history: deque = deque() self.looping_queue: bool = False @@ -124,43 +125,43 @@ def from_total(self, idx): def subc_decision(self, subc: str) -> tuple[Callable, Optional[Callable]]: match subc: case "play": - return (self.play, lambda x: x) + return self.play, lambda x: x case "playback_speed" | "playbackspeed" | "ps" | "speed": - return (self.playback_speed, conv_arg(float, True)) + return self.playback_speed, conv_arg(float, True) case "goto_time" | "gototime" | "gt": - return (self.goto_time, conv_arg(lambda x: x, True)) + return self.goto_time, conv_arg(lambda x: x, True) case "forward_time" | "forwardtime" | "ft": - return (self.forward_time, conv_arg(lambda x: x, True)) + return self.forward_time, conv_arg(lambda x: x, True) case "backward_time" | "backwardtime" | "bt" | "rewind": - return (self.backward_time, conv_arg(lambda x: "30" if x is None else x, False)) + return self.backward_time, conv_arg(lambda x: "30" if x is None else x, False) case "loop": - return (self.loop, conv_arg(lambda x: x, True)) + return self.loop, conv_arg(lambda x: x, True) case "print_queue" | "printqueue" | "pq": - return (self.print_queue, conv_arg(lambda x: 0 if x is None else int(x), False)) + return self.print_queue, conv_arg(lambda x: 0 if x is None else int(x), False) case "status" | "now_playing" | "nowplaying" | "np": - return (self.music_status, None) + return self.music_status, None case "remove" | "pop": - return (self.remove_track, conv_arg(int, True)) + return self.remove_track, conv_arg(int, True) case "insert": - return (self.insert_track, conv_arg(insert_converter, True)) + return self.insert_track, conv_arg(insert_converter, True) case "clear_queue" | "clearqueue" | "cq": - return (self.clear_queue, None) + return self.clear_queue, None case "clear_hist" | "clearhist" | "ch": - return (self.clear_hist, None) + return self.clear_hist, None case "queue" | "q": - return (self.queue_track, lambda x: x) + return self.queue_track, lambda x: x case "volume" | "vol" | "v": - return (self.volume, conv_arg(lambda x: float(x.strip("%")), True)) + return self.volume, conv_arg(lambda x: float(x.strip("%")), True) case "stop": - return (self.stop, None) + return self.stop, None case "skip" | "next": - return (self.skip, conv_arg(lambda x: 0 if x is None else int(x), False)) + return self.skip, conv_arg(lambda x: 0 if x is None else int(x), False) case "back" | "previous": - return (self.backtrack, conv_arg(lambda x: None if x is None else int(x), False)) + return self.backtrack, conv_arg(lambda x: None if x is None else int(x), False) case "pause": - return (self.pause, None) + return self.pause, None case "resume": - return (self.resume, None) + return self.resume, None case _: raise ValueError @@ -313,7 +314,8 @@ async def play(self, ctx, url: Optional[str] = None): skip_str, delta = self.skip_opts self.play_track(ctx, skip_str=skip_str, delta=delta) if self.pause_start is not None: - ctx.voice_client.pause() + if ctx.voice_client is not None: + await ctx.voice_client.pause() self.pause_start -= delta self.skip_opts = None @@ -604,13 +606,13 @@ async def volume(self, ctx, new_vol: float): arguments: (float) """ - self.volume_level = max(0, min(500, new_vol)) + self.volume_level = max(0., min(500., new_vol)) ctx.voice_client.source.volume = self.volume_level / 100 await ctx.send(f"changed volume to {self.volume_level}%.") @check_playing @check_banned - async def stop(self, ctx): + async def stop(self, ctx: commands.Context): """ stops and disconnects the bot from voice arguments: none @@ -622,7 +624,7 @@ async def stop(self, ctx): @check_playing @check_banned - async def skip(self, ctx, queue_amount: int): + async def skip(self, ctx: commands.Context, queue_amount: int): """ skips some amount of songs in the queue arguments: (optional: int [defaults to 0, going forward a single track]) @@ -644,7 +646,7 @@ async def skip(self, ctx, queue_amount: int): @check_playing @check_banned - async def backtrack(self, ctx, queue_amount: Optional[int]): + async def backtrack(self, ctx: commands.Context, queue_amount: Optional[int]): """ goes backwards in history by some amount of tracks arguments: (optional: int [defaults to 0 if track has been playing for more than 10 seconds, otherwise 1]) @@ -672,7 +674,7 @@ async def backtrack(self, ctx, queue_amount: Optional[int]): @check_playing @check_banned - async def pause(self, ctx): + async def pause(self, ctx: commands.Context): """ pauses currently playing track arguments: none @@ -682,7 +684,7 @@ async def pause(self, ctx): self.pause_start = time.perf_counter() await ctx.send("paused current track.") - async def resume(self, ctx): + async def resume(self, ctx: commands.Context): """ resumes currently paused track arguments: none diff --git a/cogs/quotes.py b/canary/cogs/quotes.py similarity index 84% rename from cogs/quotes.py rename to canary/cogs/quotes.py index f161ab6ce..220dade9b 100644 --- a/cogs/quotes.py +++ b/canary/cogs/quotes.py @@ -29,6 +29,7 @@ # Other utils import random +from ..bot import Canary from .utils.paginator import Pages GEN_SPACE_SYMBOLS = re.compile(r"[,“”\".?!]") @@ -40,9 +41,9 @@ class Quotes(commands.Cog): - def __init__(self, bot): - self.bot = bot - self.mc_table = {} + def __init__(self, bot: Canary): + self.bot: Canary = bot + self.mc_table: dict[str, dict] = {} self.rebuild_mc() def rebuild_mc(self): @@ -55,7 +56,7 @@ def rebuild_mc(self): c = conn.cursor() c.execute("SELECT Quote FROM Quotes") - lookup = {} + lookup: dict[str, dict] = {} for q in c.fetchall(): # Skip URL quotes @@ -99,7 +100,8 @@ def rebuild_mc(self): conn.close() @commands.command(aliases=["addq"]) - async def add_quotes(self, ctx, member: discord.Member = None, *, quote: str = None): + async def add_quotes( + self, ctx: commands.Context, member: discord.Member | None = None, *, quote: str | None = None): """ Add a quote to a user's quote database. """ @@ -239,7 +241,7 @@ def check(reaction, user): await ctx.send(embed=embed) @commands.command(aliases=["lq"]) - async def list_quotes(self, ctx, author: discord.Member = None): + async def list_quotes(self, ctx: commands.Context, author: discord.Member = None): """ List quotes """ @@ -309,7 +311,7 @@ def msg_check(msg): conn.close() @commands.command(aliases=["allq", "aq"]) - async def all_quotes(self, ctx, *, query): + async def all_quotes(self, ctx: commands.Context, *, query: str): """ List all quotes that contain the query string. Can optionally use regex by surrounding the the query with /.../. @@ -320,7 +322,7 @@ async def all_quotes(self, ctx, *, query): """ if not query: - ctx.send("You must provide a query") + await ctx.send("You must provide a query") return query_splitted = query.split() @@ -372,7 +374,7 @@ async def all_quotes(self, ctx, *, query): await p.paginate() @commands.command(aliases=["gen"]) - async def generate(self, ctx, seed: str = None, min_length: int = 1): + async def generate(self, ctx: commands.Context, seed: str = None, min_length: int = 1): """ Generates a random 'quote' using a Markov Chain. Optionally takes in a word to seed the Markov Chain with and (also optionally) a desired @@ -393,52 +395,54 @@ async def generate(self, ctx, seed: str = None, min_length: int = 1): if seed is None: await ctx.send("Markov chain table is empty.", delete_after=60) - elif seed not in self.mc_table.keys(): + return + if seed not in self.mc_table.keys(): await ctx.send("Could not generate anything with that seed.", delete_after=60) - else: - longest_sentence = [] - retries = 0 - - while len(longest_sentence) < min_length and retries < 200: - current_word = seed - sentence = [current_word] - - # Add words to the sentence until a termination condition is - # encountered. - while True: - choices = [(w, self.mc_table[current_word][w]) for w in self.mc_table[current_word]] - c_words, p_dist = zip(*choices) - - # Choose a random word and add it to the sentence using the - # probability distribution stored in the word entry. - old_word = current_word - current_word = np.random.choice(c_words, p=p_dist) + return - # Don't allow termination until the minimum length is met - # or we don't have any other option. - while ( - current_word == "TERM" - and len(sentence) < min_length - and len(self.mc_table[old_word].keys()) > 1 - ): - current_word = np.random.choice(c_words, p=p_dist) + longest_sentence = [] + retries = 0 + + while len(longest_sentence) < min_length and retries < 200: + current_word = seed + sentence = [current_word] + + # Add words to the sentence until a termination condition is + # encountered. + while True: + choices = [(w, self.mc_table[current_word][w]) for w in self.mc_table[current_word]] + c_words, p_dist = zip(*choices) + + # Choose a random word and add it to the sentence using the + # probability distribution stored in the word entry. + old_word = current_word + current_word = np.random.choice(c_words, p=p_dist) + + # Don't allow termination until the minimum length is met + # or we don't have any other option. + while ( + current_word == "TERM" + and len(sentence) < min_length + and len(self.mc_table[old_word].keys()) > 1 + ): + current_word = np.random.choice(c_words, p=p_dist) - # Don't allow repeat words too much - while len(sentence) >= 3 and (current_word == sentence[-1] == sentence[-2] == sentence[-3]): - current_word = np.random.choice(c_words, p=p_dist) + # Don't allow repeat words too much + while len(sentence) >= 3 and (current_word == sentence[-1] == sentence[-2] == sentence[-3]): + current_word = np.random.choice(c_words, p=p_dist) - # Cap sentence at 1000 words, just in case, and terminate - # if termination symbol is seen. - if current_word == "TERM" or len(sentence) >= 1000: - break - sentence.append(current_word) + # Cap sentence at 1000 words, just in case, and terminate + # if termination symbol is seen. + if current_word == "TERM" or len(sentence) >= 1000: + break + sentence.append(current_word) - if len(longest_sentence) < len(sentence) and len(" ".join(sentence)) <= 2000: - longest_sentence = sentence[:] + if len(longest_sentence) < len(sentence) and len(" ".join(sentence)) <= 2000: + longest_sentence = sentence[:] - retries += 1 + retries += 1 - await ctx.send(" ".join(longest_sentence)) + await ctx.send(" ".join(longest_sentence)) def setup(bot): diff --git a/cogs/reminder.py b/canary/cogs/reminder.py similarity index 96% rename from cogs/reminder.py rename to canary/cogs/reminder.py index dcf111c1a..3991f1b92 100644 --- a/cogs/reminder.py +++ b/canary/cogs/reminder.py @@ -25,6 +25,7 @@ import datetime # Other utilities +from ..bot import Canary from .utils.paginator import Pages # For remindme functionality @@ -90,8 +91,8 @@ class Reminder(commands.Cog): - def __init__(self, bot): - self.bot = bot + def __init__(self, bot: Canary): + self.bot: Canary = bot self.frequencies = {"daily": 1, "weekly": 7, "monthly": 30} async def check_reminders(self): @@ -145,7 +146,7 @@ async def check_reminders(self): await asyncio.sleep(60) # seconds @commands.command(aliases=["rm", "rem"]) - async def remindme(self, ctx, *, quote: str = ""): + async def remindme(self, ctx: commands.Context, *, quote: str = ""): """ Parses the reminder and adds a one-time reminder to the reminder database or calls remindme_repeating to deal with repetitive reminders @@ -193,7 +194,7 @@ async def remindme(self, ctx, *, quote: str = ""): """ if len(input_segments) > 0 and (input_segments[0] in ("daily", "weekly", "monthly")): - await self.__remindme_repeating(ctx, input_segments[0], quote=quote[len(input_segments[0]) + 1 :]) + await self.__remindme_repeating(ctx, input_segments[0], quote=quote[len(input_segments[0]) + 1:]) return for segment in input_segments: @@ -209,7 +210,7 @@ async def remindme(self, ctx, *, quote: str = ""): # They probably don't want their reminder nuked of punctuation, spaces # and formatting, so extract from original string. - reminder = quote[quote.index(first_reminder_segment) :] + reminder = quote[quote.index(first_reminder_segment):] # Date-based reminder triggered by "at" and "on" keywords if input_segments[0] in {"at", "on"}: @@ -235,10 +236,10 @@ async def remindme(self, ctx, *, quote: str = ""): # Strips "to" and dates from the reminder message time_input_end = time_result.span()[1] - if re.match("to", reminder[time_input_end : time_input_end + 4].strip(), re.IGNORECASE): - reminder = reminder[time_input_end + 3 :].strip() + if re.match("to", reminder[time_input_end:time_input_end + 4].strip(), re.IGNORECASE): + reminder = reminder[time_input_end + 3:].strip() else: - reminder = reminder[time_input_end + 1 :].strip() + reminder = reminder[time_input_end + 1:].strip() # Add message to database conn = sqlite3.connect(self.bot.config.db_path) @@ -436,7 +437,7 @@ def msg_check(msg): conn.commit() conn.close() - async def __remindme_repeating(self, ctx, freq: str = "", *, quote: str = ""): + async def __remindme_repeating(self, ctx: commands.Context, freq: str = "", *, quote: str = ""): """ Called by remindme to add a repeating reminder to the reminder database. diff --git a/cogs/roles.py b/canary/cogs/roles.py similarity index 91% rename from cogs/roles.py rename to canary/cogs/roles.py index 4115a5bc7..e9a769ea8 100644 --- a/cogs/roles.py +++ b/canary/cogs/roles.py @@ -16,13 +16,13 @@ # along with Canary. If not, see . import discord -import sqlite3 from discord import utils from discord.ext import commands from enum import Enum from typing import Optional, Tuple +from ..bot import Canary from .utils.checks import is_moderator from .utils.paginator import Pages from .utils.role_restoration import save_existing_roles, fetch_saved_roles, is_in_muted_table, role_restoring_page @@ -50,13 +50,13 @@ class Roles(commands.Cog): "generics": None, } - def __init__(self, bot): - self.bot = bot + def __init__(self, bot: Canary): + self.bot: Canary = bot self.roles = self.bot.config.roles self.mod_role = self.bot.config.moderator_role @staticmethod - async def paginate_roles(ctx, roles, title="All roles in server"): + async def paginate_roles(ctx: commands.Context, roles, title="All roles in server"): p = Pages(ctx, item_list=[r + "\n" for r in roles], title=title, display_option=(3, 20), editable_content=False) await p.paginate() @@ -148,7 +148,7 @@ async def add_role(self, ctx, requested_role: Optional[str], categories: Tuple[s return await self.toggle_role(ctx, RoleTransaction.ADD, requested_role, categories) @commands.command(aliases=["pronouns"]) - async def pronoun(self, ctx, *, pronoun: Optional[str] = None): + async def pronoun(self, ctx: commands.Context, *, pronoun: Optional[str] = None): """ Self-assign a pronoun role to a user. If no argument is given, returns a list of roles that can be used with this command. @@ -156,7 +156,7 @@ async def pronoun(self, ctx, *, pronoun: Optional[str] = None): await self.add_role(ctx, pronoun, ("pronouns",)) @commands.command(aliases=["fields", "program", "programs", "major", "majors"]) - async def field(self, ctx, *, field: Optional[str] = None): + async def field(self, ctx: commands.Context, *, field: Optional[str] = None): """ Self-assign a field of study role to a user. If no argument is given, returns a list of roles that can be used with this command. @@ -164,7 +164,7 @@ async def field(self, ctx, *, field: Optional[str] = None): await self.add_role(ctx, field, ("fields",)) @commands.command(aliases=["faculties"]) - async def faculty(self, ctx, *, faculty: Optional[str] = None): + async def faculty(self, ctx: commands.Context, *, faculty: Optional[str] = None): """ Self-assign a faculty of study role to a user. If no argument is given, returns a list of roles that can be used with this command. @@ -180,7 +180,7 @@ async def year(self, ctx, year: Optional[str] = None): await Roles.add_role(self, ctx, year, ("years",)) @commands.command(aliases=["iam", "generic", "generics"]) - async def i_am(self, ctx, *, role: Optional[str]): + async def i_am(self, ctx: commands.Context, *, role: Optional[str]): """ Self-assign a generic role to a user. If no argument is given, returns a list of roles that can be used with this command. @@ -188,7 +188,7 @@ async def i_am(self, ctx, *, role: Optional[str]): await self.add_role(ctx, role, Roles.ALL_CATEGORIES) @commands.command(aliases=["iamn"]) - async def i_am_not(self, ctx, *, role: Optional[str]): + async def i_am_not(self, ctx: commands.Context, *, role: Optional[str]): """ Self-unassign a generic role to a user. """ @@ -209,7 +209,7 @@ async def roles(self, ctx, user: discord.Member = None): ) @commands.command(aliases=["inrole"]) - async def in_role(self, ctx, *, query_role): + async def in_role(self, ctx: commands.Context, *, query_role): """Returns list of users in the specified role""" role = next((role for role in ctx.guild.roles if role.name.lower() == query_role.lower()), None) @@ -232,7 +232,7 @@ async def in_role(self, ctx, *, query_role): @commands.command(aliases=["cr", "createrole"]) @is_moderator() - async def create_role(self, ctx, *, role: Optional[str] = None): + async def create_role(self, ctx: commands.Context, *, role: Optional[str] = None): role = (role or "").strip() if not role: await ctx.send("Please specify a role name.") @@ -247,7 +247,7 @@ async def create_role(self, ctx, *, role: Optional[str] = None): await ctx.send("Role created successfully.") @commands.command(aliases=["inchannel"]) - async def in_channel(self, ctx): + async def in_channel(self, ctx: commands.Context): """Returns list of users in current channel""" channel = ctx.message.channel members = channel.members @@ -259,7 +259,7 @@ async def in_channel(self, ctx): await pages.paginate() @commands.command(aliases=["previousroles", "giverolesback", "rolesback", "givebackroles"]) - async def previous_roles(self, ctx, user: discord.Member): + async def previous_roles(self, ctx: commands.Context, user: discord.Member): """Show the list of roles that a user had before leaving, if possible. A moderator can click the OK react on the message to give these roles back """ diff --git a/cogs/score.py b/canary/cogs/score.py similarity index 96% rename from cogs/score.py rename to canary/cogs/score.py index b97b91413..84f328f18 100644 --- a/cogs/score.py +++ b/canary/cogs/score.py @@ -1,6 +1,4 @@ -# -*- coding: utf-8 -*- -# -# Copyright (C) idoneam (2016-2021) +# Copyright (C) idoneam (2016-2022) # # This file is part of Canary # @@ -23,6 +21,9 @@ import discord from discord.ext import commands +# For type hinting +from ..bot import Canary + # For DB functionality import sqlite3 import json @@ -145,11 +146,11 @@ async def convert(self, ctx, argument): class Score(commands.Cog): - def __init__(self, bot): - self.bot = bot - self.guild = None - self.UPMARTLET = None - self.DOWNMARTLET = None + def __init__(self, bot: Canary): + self.bot: Canary = bot + self.guild: discord.Guild | None = None + self.UPMARTLET: discord.Emoji | None = None + self.DOWNMARTLET: discord.Emoji | None = None @commands.Cog.listener() async def on_ready(self): @@ -332,16 +333,22 @@ async def _add_or_remove_reaction_from_db(self, payload, remove=False): @commands.Cog.listener() async def on_raw_reaction_add(self, payload): + if self.guild is None: + return + if payload.guild_id == self.guild.id: await self._add_or_remove_reaction_from_db(payload) @commands.Cog.listener() async def on_raw_reaction_remove(self, payload): + if self.guild is None: + return + if payload.guild_id == self.guild.id: await self._add_or_remove_reaction_from_db(payload, remove=True) @commands.command() - async def score(self, ctx, *args): + async def score(self, ctx: commands.Context, *args): """Display emoji score Basic examples: @@ -355,7 +362,8 @@ async def score(self, ctx, *args): -If @user or User, gives the score for this user. -If from and to flags, gives the score given from @userA to @userB. `from:all` and `to:all` can be used. -If nothing, gives your score - Note that it is possible to give usernames without mention. This is case sensitive. If a username contains a space, the username and flag must be included in quotes, e.g. "to:user name" + Note that it is possible to give usernames without mention. This is case sensitive. If a username contains a + space, the username and flag must be included in quotes, e.g. "to:user name" - Optional: `emoji` OR `emojitype:type` OR `emojiname:name` OR `:name:` -If emoji, gives the score for this emoji @@ -381,7 +389,7 @@ async def score(self, ctx, *args): try: args_dict = await self._get_converted_args_dict(ctx, args, from_xnor_to=True) except commands.BadArgument as err: - await ctx.send(err) + await ctx.send(str(err)) return # get the WHERE conditions and the values @@ -421,7 +429,8 @@ async def ranking(self, ctx, *args): -If from flag: gives the score received by every user from this user. `from:all` can be used. -If to flag: gives the score received by this user from every user. `to:all` can be used. -If nothing, gives the score of every user - Note that it is possible to give usernames without mention. This is case sensitive. If a username contains a space, the username and flag must be included in quotes, e.g. "to:user name" + Note that it is possible to give usernames without mention. This is case sensitive. If a username contains a + space, the username and flag must be included in quotes, e.g. "to:user name" - Optional: `emoji` OR `emojitype:type` OR `emojiname:name` OR `:name:` -If emoji, gives the score for this emoji @@ -515,7 +524,7 @@ async def ranking(self, ctx, *args): await p.paginate() @commands.command() - async def emojiranking(self, ctx, *args): + async def emojiranking(self, ctx: commands.Context, *args): """Ranking of how many times emojis were used Basic example: @@ -525,7 +534,8 @@ async def emojiranking(self, ctx, *args): - Optional: `from:@userA` AND `to:@userB` -If from and to flags, gives the score given from @userA to @userB. `from:all` and `to:all` can be used. - Note that it is possible to give usernames without mention. If a username contains a space, the username and flag must be included in quotes, e.g. "to:user name" + Note that it is possible to give usernames without mention. If a username contains a space, the username and + flag must be included in quotes, e.g. "to:user name" - Optional: `emojitype:type` -If emojitype flag, gives the score for this emojitype (see below for types) @@ -551,7 +561,7 @@ async def emojiranking(self, ctx, *args): try: args_dict = await self._get_converted_args_dict(ctx, args, from_xnor_to=True, member=False, emoji=False) except commands.BadArgument as err: - await ctx.send(err) + await ctx.send(str(err)) return if args_dict["emojitype"] == "score": diff --git a/cogs/subscribers.py b/canary/cogs/subscribers.py similarity index 96% rename from cogs/subscribers.py rename to canary/cogs/subscribers.py index 327993e19..e67ebc1e1 100644 --- a/cogs/subscribers.py +++ b/canary/cogs/subscribers.py @@ -31,6 +31,9 @@ import feedparser import requests +# Type hinting +from ..bot import Canary + # Subscriber decorator from .utils.subscribers import canary_subscriber @@ -59,8 +62,8 @@ class Subscribers(commands.Cog): - def __init__(self, bot): - self.bot = bot + def __init__(self, bot: Canary): + self.bot: Canary = bot # Compiled recall regular expression for filtering self._recall_filter = re.compile(self.bot.config.recall_filter, re.IGNORECASE) @@ -73,8 +76,8 @@ def __init__(self, bot): METRO_BLUE_LINE: METRO_NORMAL_SERVICE_MESSAGE, } - self._recall_channel = None - self._metro_status_channel = None + self._recall_channel: discord.TextChannel | None = None + self._metro_status_channel: discord.TextChannel | None = None @commands.Cog.listener() async def on_ready(self): diff --git a/cogs/utils/__init__.py b/canary/cogs/utils/__init__.py similarity index 100% rename from cogs/utils/__init__.py rename to canary/cogs/utils/__init__.py diff --git a/cogs/utils/arg_converter.py b/canary/cogs/utils/arg_converter.py similarity index 100% rename from cogs/utils/arg_converter.py rename to canary/cogs/utils/arg_converter.py diff --git a/cogs/utils/auto_incorrect.py b/canary/cogs/utils/auto_incorrect.py similarity index 100% rename from cogs/utils/auto_incorrect.py rename to canary/cogs/utils/auto_incorrect.py diff --git a/cogs/utils/checks.py b/canary/cogs/utils/checks.py similarity index 100% rename from cogs/utils/checks.py rename to canary/cogs/utils/checks.py diff --git a/cogs/utils/clamp_default.py b/canary/cogs/utils/clamp_default.py similarity index 100% rename from cogs/utils/clamp_default.py rename to canary/cogs/utils/clamp_default.py diff --git a/cogs/utils/custom_requests.py b/canary/cogs/utils/custom_requests.py similarity index 100% rename from cogs/utils/custom_requests.py rename to canary/cogs/utils/custom_requests.py diff --git a/cogs/utils/dice_roll.py b/canary/cogs/utils/dice_roll.py similarity index 100% rename from cogs/utils/dice_roll.py rename to canary/cogs/utils/dice_roll.py diff --git a/cogs/utils/hangman.py b/canary/cogs/utils/hangman.py similarity index 100% rename from cogs/utils/hangman.py rename to canary/cogs/utils/hangman.py diff --git a/cogs/utils/image_helpers.py b/canary/cogs/utils/image_helpers.py similarity index 100% rename from cogs/utils/image_helpers.py rename to canary/cogs/utils/image_helpers.py diff --git a/cogs/utils/members.py b/canary/cogs/utils/members.py similarity index 100% rename from cogs/utils/members.py rename to canary/cogs/utils/members.py diff --git a/cogs/utils/mock_context.py b/canary/cogs/utils/mock_context.py similarity index 100% rename from cogs/utils/mock_context.py rename to canary/cogs/utils/mock_context.py diff --git a/cogs/utils/music_helpers.py b/canary/cogs/utils/music_helpers.py similarity index 100% rename from cogs/utils/music_helpers.py rename to canary/cogs/utils/music_helpers.py diff --git a/cogs/utils/p_strings.py b/canary/cogs/utils/p_strings.py similarity index 100% rename from cogs/utils/p_strings.py rename to canary/cogs/utils/p_strings.py diff --git a/cogs/utils/paginator.py b/canary/cogs/utils/paginator.py similarity index 100% rename from cogs/utils/paginator.py rename to canary/cogs/utils/paginator.py diff --git a/cogs/utils/role_restoration.py b/canary/cogs/utils/role_restoration.py similarity index 100% rename from cogs/utils/role_restoration.py rename to canary/cogs/utils/role_restoration.py diff --git a/cogs/utils/site_save.py b/canary/cogs/utils/site_save.py similarity index 100% rename from cogs/utils/site_save.py rename to canary/cogs/utils/site_save.py diff --git a/cogs/utils/subscribers.py b/canary/cogs/utils/subscribers.py similarity index 100% rename from cogs/utils/subscribers.py rename to canary/cogs/utils/subscribers.py diff --git a/pyproject.toml b/pyproject.toml index da1ff8a3c..d26696831 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -6,6 +6,9 @@ license = "GPL-3.0-only" repository = "https://github.com/idoneam/Canary" readme = "README.md" authors = [] +packages = [ + { include = "canary" }, +] [tool.poetry.dependencies] python = "~3.10.0" From d58a14ff2370c79b2d14e18097b7704247b3a7f7 Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Fri, 2 Sep 2022 23:36:10 -0400 Subject: [PATCH 002/127] rename main and add some hints/format strings --- Dockerfile | 2 +- canary/Main.py | 23 +++++++++++------------ 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/Dockerfile b/Dockerfile index 8c647aa06..7d99a310e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -25,4 +25,4 @@ WORKDIR /canary # Users will have to mount their config.ini in by hand # Users should mount a read/writable volume for /canary/data/runtime -CMD ["python3.10", "Main.py"] +CMD ["python3.10", "-m", "canary.main"] diff --git a/canary/Main.py b/canary/Main.py index 7df5ec543..32d5921c7 100755 --- a/canary/Main.py +++ b/canary/Main.py @@ -17,18 +17,17 @@ # You should have received a copy of the GNU General Public License # along with Canary. If not, see . -# discord-py requirements import discord - -# Other utilities import os +import sqlite3 import sys + from datetime import datetime +from discord.ext.commands import Context from pytz import timezone -from canary.bot import bot -import sqlite3 -from cogs.utils.checks import is_developer, is_moderator +from canary.bot import bot +from canary.cogs.utils.checks import is_developer, is_moderator startup = [f"cogs.{c}" for c in ( "banner", @@ -77,22 +76,22 @@ async def load(ctx, extension_name: str): @bot.command() @is_moderator() -async def unload(ctx, extension_name: str): +async def unload(ctx: Context, extension_name: str): """ Unload a specific extension. Specify as cogs. """ try: bot.unload_extension(extension_name) except Exception as e: - await ctx.send("```{}: {}\n```".format(type(e).__name__, str(e))) + await ctx.send(f"```{type(e).__name__}: {str(e)}\n```") return - await ctx.send("{} unloaded.".format(extension_name)) + await ctx.send(f"{extension_name} unloaded.") @bot.command() @is_developer() -async def restart(ctx): +async def restart(ctx: Context): """ Restart the bot """ @@ -104,7 +103,7 @@ async def restart(ctx): @bot.command() @is_moderator() -async def sleep(ctx): +async def sleep(ctx: Context): """ Shut down the bot """ @@ -115,7 +114,7 @@ async def sleep(ctx): @bot.command() @is_moderator() -async def backup(ctx): +async def backup(ctx: Context): """ Send the current database file to the owner """ From 09d9bca40f27c343c3ec962fdafb7fa392d22293 Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Fri, 2 Sep 2022 23:36:37 -0400 Subject: [PATCH 003/127] linting and hinting --- canary/cogs/games.py | 9 ++++----- canary/cogs/quotes.py | 3 +-- canary/cogs/utils/__init__.py | 18 ------------------ canary/cogs/utils/auto_incorrect.py | 14 +++++++------- canary/cogs/utils/checks.py | 2 +- canary/cogs/utils/dice_roll.py | 6 ++---- canary/cogs/utils/music_helpers.py | 17 +++++++++++++++++ canary/cogs/utils/paginator.py | 2 -- canary/cogs/utils/role_restoration.py | 2 +- canary/cogs/utils/site_save.py | 1 - 10 files changed, 33 insertions(+), 41 deletions(-) diff --git a/canary/cogs/games.py b/canary/cogs/games.py index 2a7048a95..202709f1a 100644 --- a/canary/cogs/games.py +++ b/canary/cogs/games.py @@ -23,11 +23,10 @@ import re import os import sqlite3 -from time import time import pickle import random import asyncio -from typing import Optional +from time import time from functools import partial from ..bot import Canary from .utils.dice_roll import dice_roll @@ -53,7 +52,7 @@ def __init__(self, bot: Canary, hangman_tbl_name: str): self.hm_timeout: int = bot.config.games["hm_timeout"] self.hm_locks: dict[discord.TextChannel, asyncio.Lock] = dict() with open(f"{os.getcwd()}/data/premade/{hangman_tbl_name}.obj", "rb") as hangman_pkl: - self.hangman_dict: dict[str, tuple[list[tuple[str, Optional[str]]], str]] = pickle.load(hangman_pkl) + self.hangman_dict: dict[str, tuple[list[tuple[str, str | None]], str]] = pickle.load(hangman_pkl) def help_str(self): cat_list: str = ", ".join( @@ -74,7 +73,7 @@ def hm_msg_check(self, hm_channel: discord.TextChannel, lowered: str, msg: disco ) @commands.command(aliases=["hm"]) - async def hangman(self, ctx, command: Optional[str] = None): + async def hangman(self, ctx, command: str | None = None): """ play a nice game of hangman with internet strangers! guesses must be single letters (interpreted in a case insensitive manner) or the entire correct word. @@ -120,7 +119,7 @@ async def hangman(self, ctx, command: Optional[str] = None): game_state = HangmanState("[REDACTED]" if command is None else pretty_name, word_list) timeout_dict: dict[discord.Member, float] = {} - winner: Optional[discord.Member] = None + winner: discord.Member | None = None cool_win: bool = False msg_check = partial(self.hm_msg_check, ctx.message.channel, game_state.lword) diff --git a/canary/cogs/quotes.py b/canary/cogs/quotes.py index 220dade9b..bd31e4cdc 100644 --- a/canary/cogs/quotes.py +++ b/canary/cogs/quotes.py @@ -418,8 +418,7 @@ async def generate(self, ctx: commands.Context, seed: str = None, min_length: in old_word = current_word current_word = np.random.choice(c_words, p=p_dist) - # Don't allow termination until the minimum length is met - # or we don't have any other option. + # Don't allow termination until the minimum length is met, or we don't have any other option. while ( current_word == "TERM" and len(sentence) < min_length diff --git a/canary/cogs/utils/__init__.py b/canary/cogs/utils/__init__.py index b30f0b2c9..e69de29bb 100644 --- a/canary/cogs/utils/__init__.py +++ b/canary/cogs/utils/__init__.py @@ -1,18 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright (C) idoneam (2016-2019) -# -# This file is part of Canary -# -# Canary is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Canary is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Canary. If not, see . diff --git a/canary/cogs/utils/auto_incorrect.py b/canary/cogs/utils/auto_incorrect.py index 410f9f3bb..0262b4867 100644 --- a/canary/cogs/utils/auto_incorrect.py +++ b/canary/cogs/utils/auto_incorrect.py @@ -3,33 +3,33 @@ __all__ = ["auto_incorrect"] -def _swap(s, i): +def _swap(s: str, i: int): """ Given string s and index i, it swaps s[i] and s[i+1] and returns By @lazho """ si = s[i] sj = s[i + 1] - s = s[:i] + sj + si + s[i + 2 :] + s = s[:i] + sj + si + s[i + 2:] return s -def _repeat(s, i): +def _repeat(s: str, i: int): """ By @lazho """ return s[:i] + s[i] + s[i:] -def _omit(s, i): +def _omit(s: str, i: int): """ Given string s and index i, it omits the i-th character. By @lazho """ - return s[:i] + s[i + 1 :] + return s[:i] + s[i + 1:] -REPLACE_CASES = { +REPLACE_CASES: dict[str, str] = { "your": "you're", "you're": "your", "its": "it's", @@ -58,7 +58,7 @@ def _omit(s, i): } -def auto_incorrect(input_str): +def auto_incorrect(input_str: str): """ By @lazho """ diff --git a/canary/cogs/utils/checks.py b/canary/cogs/utils/checks.py index dabde3ffe..7deb62fba 100644 --- a/canary/cogs/utils/checks.py +++ b/canary/cogs/utils/checks.py @@ -21,7 +21,7 @@ import discord from discord.ext import commands -from bot import moderator_role, developer_role +from canary.bot import moderator_role, developer_role def is_moderator(): diff --git a/canary/cogs/utils/dice_roll.py b/canary/cogs/utils/dice_roll.py index 90720baa8..4d8e38c96 100644 --- a/canary/cogs/utils/dice_roll.py +++ b/canary/cogs/utils/dice_roll.py @@ -1,6 +1,4 @@ -# -*- coding: utf-8 -*- -# -# Copyright (C) idoneam (2016-2019) +# Copyright (C) idoneam (2016-2022) # # This file is part of Canary # @@ -20,7 +18,7 @@ from random import randint -def dice_roll(sides=20, n=1, modifier=0, mpr=False): +def dice_roll(sides: int = 20, n: int = 1, modifier: int = 0, mpr: bool = False): """ Rolls a die with given parameters Set mpr to True to mod each roll, otherwise, only the sum is modified diff --git a/canary/cogs/utils/music_helpers.py b/canary/cogs/utils/music_helpers.py index fb5e79a51..05f324d0b 100644 --- a/canary/cogs/utils/music_helpers.py +++ b/canary/cogs/utils/music_helpers.py @@ -1,3 +1,20 @@ +# Copyright (C) idoneam (2016-2022) +# +# This file is part of Canary +# +# Canary is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Canary is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Canary. If not, see . + import time from functools import wraps from typing import Iterable diff --git a/canary/cogs/utils/paginator.py b/canary/cogs/utils/paginator.py index ad316c8a9..0e90f1ed0 100644 --- a/canary/cogs/utils/paginator.py +++ b/canary/cogs/utils/paginator.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- -# # Copyright (C) idoneam (2016-2022) # # This file is part of Canary diff --git a/canary/cogs/utils/role_restoration.py b/canary/cogs/utils/role_restoration.py index 8cd4d0dea..1e03b1110 100644 --- a/canary/cogs/utils/role_restoration.py +++ b/canary/cogs/utils/role_restoration.py @@ -23,7 +23,7 @@ from .paginator import Pages from .mock_context import MockContext -from bot import muted_role as muted_role_name +from canary.bot import muted_role as muted_role_name import datetime diff --git a/canary/cogs/utils/site_save.py b/canary/cogs/utils/site_save.py index 8dfabeafb..e9196dd4d 100644 --- a/canary/cogs/utils/site_save.py +++ b/canary/cogs/utils/site_save.py @@ -1,6 +1,5 @@ import os from time import time -from typing import Optional import discord from .custom_requests import fetch from functools import wraps From 1e8201c34b1221d34215b5fd1d07f56d999a2a8b Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Fri, 2 Sep 2022 23:38:02 -0400 Subject: [PATCH 004/127] aaaaa --- canary/{Main.py => main.py} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename canary/{Main.py => main.py} (100%) diff --git a/canary/Main.py b/canary/main.py similarity index 100% rename from canary/Main.py rename to canary/main.py From 9ccd8e549db2eab4cc3c4549c85884c31ccbb361 Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Sat, 3 Sep 2022 09:36:09 -0400 Subject: [PATCH 005/127] lint --- canary/cogs/music.py | 2 +- canary/cogs/quotes.py | 9 +++---- canary/cogs/reminder.py | 10 ++++---- canary/cogs/utils/auto_incorrect.py | 4 ++-- canary/main.py | 37 ++++++++++++++++------------- 5 files changed, 31 insertions(+), 31 deletions(-) diff --git a/canary/cogs/music.py b/canary/cogs/music.py index b101695da..ec4d94306 100644 --- a/canary/cogs/music.py +++ b/canary/cogs/music.py @@ -606,7 +606,7 @@ async def volume(self, ctx, new_vol: float): arguments: (float) """ - self.volume_level = max(0., min(500., new_vol)) + self.volume_level = max(0.0, min(500.0, new_vol)) ctx.voice_client.source.volume = self.volume_level / 100 await ctx.send(f"changed volume to {self.volume_level}%.") diff --git a/canary/cogs/quotes.py b/canary/cogs/quotes.py index bd31e4cdc..f8cfc4c8e 100644 --- a/canary/cogs/quotes.py +++ b/canary/cogs/quotes.py @@ -101,7 +101,8 @@ def rebuild_mc(self): @commands.command(aliases=["addq"]) async def add_quotes( - self, ctx: commands.Context, member: discord.Member | None = None, *, quote: str | None = None): + self, ctx: commands.Context, member: discord.Member | None = None, *, quote: str | None = None + ): """ Add a quote to a user's quote database. """ @@ -419,11 +420,7 @@ async def generate(self, ctx: commands.Context, seed: str = None, min_length: in current_word = np.random.choice(c_words, p=p_dist) # Don't allow termination until the minimum length is met, or we don't have any other option. - while ( - current_word == "TERM" - and len(sentence) < min_length - and len(self.mc_table[old_word].keys()) > 1 - ): + while current_word == "TERM" and len(sentence) < min_length and len(self.mc_table[old_word].keys()) > 1: current_word = np.random.choice(c_words, p=p_dist) # Don't allow repeat words too much diff --git a/canary/cogs/reminder.py b/canary/cogs/reminder.py index 3991f1b92..a42770496 100644 --- a/canary/cogs/reminder.py +++ b/canary/cogs/reminder.py @@ -194,7 +194,7 @@ async def remindme(self, ctx: commands.Context, *, quote: str = ""): """ if len(input_segments) > 0 and (input_segments[0] in ("daily", "weekly", "monthly")): - await self.__remindme_repeating(ctx, input_segments[0], quote=quote[len(input_segments[0]) + 1:]) + await self.__remindme_repeating(ctx, input_segments[0], quote=quote[len(input_segments[0]) + 1 :]) return for segment in input_segments: @@ -210,7 +210,7 @@ async def remindme(self, ctx: commands.Context, *, quote: str = ""): # They probably don't want their reminder nuked of punctuation, spaces # and formatting, so extract from original string. - reminder = quote[quote.index(first_reminder_segment):] + reminder = quote[quote.index(first_reminder_segment) :] # Date-based reminder triggered by "at" and "on" keywords if input_segments[0] in {"at", "on"}: @@ -236,10 +236,10 @@ async def remindme(self, ctx: commands.Context, *, quote: str = ""): # Strips "to" and dates from the reminder message time_input_end = time_result.span()[1] - if re.match("to", reminder[time_input_end:time_input_end + 4].strip(), re.IGNORECASE): - reminder = reminder[time_input_end + 3:].strip() + if re.match("to", reminder[time_input_end : time_input_end + 4].strip(), re.IGNORECASE): + reminder = reminder[time_input_end + 3 :].strip() else: - reminder = reminder[time_input_end + 1:].strip() + reminder = reminder[time_input_end + 1 :].strip() # Add message to database conn = sqlite3.connect(self.bot.config.db_path) diff --git a/canary/cogs/utils/auto_incorrect.py b/canary/cogs/utils/auto_incorrect.py index 0262b4867..6b86f2a9b 100644 --- a/canary/cogs/utils/auto_incorrect.py +++ b/canary/cogs/utils/auto_incorrect.py @@ -10,7 +10,7 @@ def _swap(s: str, i: int): """ si = s[i] sj = s[i + 1] - s = s[:i] + sj + si + s[i + 2:] + s = s[:i] + sj + si + s[i + 2 :] return s @@ -26,7 +26,7 @@ def _omit(s: str, i: int): Given string s and index i, it omits the i-th character. By @lazho """ - return s[:i] + s[i + 1:] + return s[:i] + s[i + 1 :] REPLACE_CASES: dict[str, str] = { diff --git a/canary/main.py b/canary/main.py index 32d5921c7..32a3ffff2 100755 --- a/canary/main.py +++ b/canary/main.py @@ -29,23 +29,26 @@ from canary.bot import bot from canary.cogs.utils.checks import is_developer, is_moderator -startup = [f"cogs.{c}" for c in ( - "banner", - "currency", - "customreactions", - "games", - "helpers", - "images", - "info", - "memes", - "mod", - "music", - "quotes", - "reminder", - "roles", - "score", - "subscribers", # Do not remove this terminating comma. -)] +startup = [ + f"cogs.{c}" + for c in ( + "banner", + "currency", + "customreactions", + "games", + "helpers", + "images", + "info", + "memes", + "mod", + "music", + "quotes", + "reminder", + "roles", + "score", + "subscribers", # Do not remove this terminating comma. + ) +] @bot.event From 4ba48d31f57ef2ef8ec4986acb73d7fbc75ff425 Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Sat, 3 Sep 2022 09:46:50 -0400 Subject: [PATCH 006/127] docs: reformat readme and update a few things --- README.md | 104 +++++++++++++++++++++++++++++++++++------------------- 1 file changed, 67 insertions(+), 37 deletions(-) diff --git a/README.md b/README.md index 7f566a94b..4562581db 100644 --- a/README.md +++ b/README.md @@ -11,43 +11,53 @@ Canary is a Python3 bot designed for the McGill University Community Discord Ser ## Installation -1. If you wish to use the `update` command to update to the latest version of the bot, configure your github account in -your environment of choice and clone into the repository with: +1. If you wish to use the `update` command to update to the latest version of the bot, configure your GitHub account in + your environment of choice and clone into the repository with: -```bash -git clone https://github.com/idoneam/Canary -``` + ```bash + git clone https://github.com/idoneam/Canary + ``` 2. Dependencies are managed with poetry which can be installed via pip with: -```bash -python3 -m pip install poetry -``` + ```bash + python3 -m pip install poetry + ``` 3. Dependencies may be installed using poetry with the following command: -```bash -poetry install --no-dev -``` + ```bash + poetry install --no-dev + ``` -4. Use of the LaTeX equation functionality requires a working LaTeX installation (at the very minimum, `latex` and `dvipng` must be present). The easiest way to do this is to install TeX Live (usually possible through your distro's package manager, or through TeX Live's own facilities for the latest version). See the [TeX Live site](https://tug.org/texlive/) for more information. +4. Use of the LaTeX equation functionality requires a working LaTeX installation (at the very minimum, `latex` and + `dvipng` must be present). The easiest way to do this is to install TeX Live (usually possible through your distro's + package manager, or through TeX Live's own facilities for the latest version). See the + [TeX Live site](https://tug.org/texlive/) for more information. 5. Development dependencies (YAPF and `pytest`) can be installed alongside all other dependencies with: -```bash -poetry install -``` + ```bash + poetry install + ``` + +6. You may enter the virtual environment generated by the pipenv installation with: `poetry shell` or simply run the + bot with `poetry run canary` -6. You may enter the virtual environment generated by the pipenv installation with: `$ poetry shell` or simply run the bot with `$ poetry run python3 Main.py` +7. In order to run bots on Discord, you need to + [create a bot account](https://github.com/reactiflux/discord-irc/wiki/Creating-a-discord-bot-&-getting-a-token). -7. In order to run bots on Discord, you need to [create a bot account](https://github.com/reactiflux/discord-irc/wiki/Creating-a-discord-bot-&-getting-a-token). +8. In the Discord Developer Portal, you must enable the "Presence" and "Server Members" Privileged Gateway Intents (In + the Bot tab of your application) -8. In the Discord Developer Portal, you must enable the "Presence" and "Server Members" Privileged Gateway Intents (In the Bot tab of your application) +You must set certain values in the `config.ini` file, in particular your Discord bot token (which you get in the +previous link) and the values in the `[Server]` section. -You must set certain values in the `config.ini` file, in particular your Discord bot token (which you get in the previous link) and the values in the `[Server]` section.
Click here to see descriptions for a few of those values

-(For values that use Discord IDs, see [this](https://support.discordapp.com/hc/en-us/articles/206346498-Where-can-I-find-my-User-Server-Message-ID-) to know how to find them) +(For values that use Discord IDs, see +[this](https://support.discordapp.com/hc/en-us/articles/206346498-Where-can-I-find-my-User-Server-Message-ID-) to know +how to find them) * `[Discord]` * `Key`: Your Discord bot token. @@ -61,21 +71,26 @@ You must set certain values in the `config.ini` file, in particular your Discor * `BannerVoteEmoji`: The name of the emoji that is used to vote on Banner of the Week Contests. * `[Roles]` * `ModeratorRole`: The name of the role that your moderators have (for functions like DMing users). - * `DeveloperRole`: The name of the role that your developers have (for functions like restarting the bot). This could be the same role than moderator. + * `DeveloperRole`: The name of the role that your developers have (for functions like restarting the bot). This + could be the same role as moderator. * `McgillianRole`: The name of the role that verified McGillians have. * `HonoraryMcGillianRole`: The name of the role that Honorary McGillians (verified Non-McGillians) have. * `BannerRemindersRole`: The name of the role that is pinged when a Banner of the Week Contest starts. * `BannerWinnerRole`: The name of the role that is given to users that win a Banner of the Week Contest. * `TrashTierBannerRole`: The name of the role that is given to users that are banned from submitting in Banner of the Week Contests. * `NoFoodSpottingRole`: The name of the role assigned to abusers of the foodspotting command that will prevent them from using it. - * `MutedRole`: **(Optional)** The name of the role used to mute users and create an appeal channel for them. (The role presumably - also removes some permissions; exact role implementation is up to the server's administrators.) + * `MutedRole`: **(Optional)** The name of the role used to mute users and create an appeal channel for them. (The + role presumably also removes some permissions; exact role implementation is up to the server's administrators.) * `SecretCrabbo`: The name of the role for users that wish to be pinged for secret crabbo celebrations. * `[Channels]` - * `ReceptionChannel`: The name of the channel that will receive messages sent to the bot through the `answer` command (and where messages sent by mods to users with the `dm` command will be logged) - * `BannerOfTheWeekChannel`: The name of the channel where winning submissions for Banner of the Week Contests are sent. - * `BannerSubmissionsChannel`: The name of the channel where submissions for Banner of the Week Contests are sent. This is where users vote. - * `BannerConvertedChannel`: The name of the channel where the converted submissions for Banner of the Week Contests are sent. This is where the bot will fetch the winning banner. + * `ReceptionChannel`: The name of the channel that will receive messages sent to the bot through the `answer` + command (and where messages sent by mods to users with the `dm` command will be logged) + * `BannerOfTheWeekChannel`: The name of the channel where winning submissions for Banner of the Week Contests are + sent. + * `BannerSubmissionsChannel`: The name of the channel where submissions for Banner of the Week Contests are sent. + This is where users vote. + * `BannerConvertedChannel`: The name of the channel where the converted submissions for Banner of the Week Contests + are sent. This is where the bot will fetch the winning banner. * `FoodSpottingChannel`: The name of the channel where foodspotting posts are sent. * `MetroStatusChannel`: The name of the channel where metro status alerts are sent. * `BotsChannel`: The name of the channel for bot spamming. @@ -85,14 +100,22 @@ You must set certain values in the `config.ini` file, in particular your Discor * `[Meta]` * `Repository`: The HTTPS remote for this repository, used by the `update` command as the remote when pulling. * `[Logging]` - * `LogLevel`: [See this for a list of levels](https://docs.python.org/3/library/logging.html#levels). Logs from exceptions and commands like `mix` and `bac` are at the `info` level. Logging messages from the level selected *and* from more severe levels will be sent to your logging file. For example, setting the level to `info` also sends logs from `warning`, `error` and `critical`, but not from `debug`. - * `LogFile`: The file where the logging output will be sent (will be created there by the bot if it doesn't exist). Note that all logs are sent there, including those destined for devs and those destined for mods. - * `DevLogWebhookID`: Optional. If the ID of a webhook is input (and it's token below), logs destined for devs will also be sent to it. These values are contained in the discord webhook url: [discordapp.com/api/webhooks/WEBHOOK_ID/WEBHOOK_TOKEN](discordapp.com/api/webhooks/WEBHOOK_ID/WEBHOOK_TOKEN) + * `LogLevel`: [See this for a list of levels](https://docs.python.org/3/library/logging.html#levels). Logs from + exceptions and commands like `mix` and `bac` are at the `info` level. Logging messages from the level selected + *and* from more severe levels will be sent to your logging file. For example, setting the level to `info` also + sends logs from `warning`, `error` and `critical`, but not from `debug`. + * `LogFile`: The file where the logging output will be sent (will be created there by the bot if it doesn't exist). + Note that all logs are sent there, including those destined for devs and those destined for mods. + * `DevLogWebhookID`: Optional. If the ID of a webhook is input (and it's token below), logs destined for devs will + also be sent to it. These values are contained in the discord webhook url: + `discordapp.com/api/webhooks/WEBHOOK_ID/WEBHOOK_TOKEN` * `DevLogWebhookToken`: Optional. See above. - * `ModLogWebhookID`: Optional. If the ID of a webhook is input (and it's token below), logs destined for mods will also be sent to it. See the URL above to see how to find those values. + * `ModLogWebhookID`: Optional. If the ID of a webhook is input (and it's token below), logs destined for mods will + also be sent to it. See the URL above to see how to find those values. * `ModLogWebhookToken`: Optional. See above. * `[DB]` - * `Schema`: Location of the Schema file that creates tables in the database (This file already exists so you shouldn't have to change this unless you rename it or change its location). + * `Schema`: Location of the Schema file that creates tables in the database (This file already exists, so you + shouldn't have to change this unless you rename it or change its location). * `Path`: Your database file path (will be created there by the bot if it doesn't exist). * `[Helpers]` * `CourseTemplate`: McGill course schedule URL. **Changes every school year.** @@ -105,8 +128,10 @@ You must set certain values in the `config.ini` file, in particular your Discor * `FoodRecallChannel`: Channel where you want CFIA recall notices posted. * `FoodRecallLocationFilter`: Regions you want to receive CFIA recall notices for. * `FoodSpottingChannel`: Channel where you want foodspotting posts to be sent, ideally in a dedicated channel. - * `NoFoodSpottingRole`: Name of role assigned to abusers of the foodspotting command that will prevent them from using it. - * `MetroStatusChannel`: Channel where you want metro status alerts to be sent, ideally in a dedicated channel with opt-in read permissions for users. + * `NoFoodSpottingRole`: Name of role assigned to abusers of the foodspotting command that will prevent them from using + it. + * `MetroStatusChannel`: Channel where you want metro status alerts to be sent, ideally in a dedicated channel with + opt-in read permissions for users. * `[Currency]` * `Name`: The name of the bot currency. * `Symbol`: The currency's symbol (e.g. `$`). @@ -147,7 +172,8 @@ If you installed all dev dependencies, you can run tests with `poetry run pytest ## Running the bot -Run `poetry run python Main.py` in your shell. Ensure that your Discord token is set in the `config.ini` file within the `config` directory. +Run `poetry run canary` in your shell. Ensure that your Discord token is set in the `config.ini` file within the +`config` directory. ### Docker Container @@ -189,7 +215,9 @@ Optionally provide the `-d` flag to run the container in detached state. ## Code Linting -We format our code using PSF's [black](https://github.com/psf/black). Our builds will reject code that do not conform to the standards defined in [`pyproject.toml`](https://black.readthedocs.io/en/stable/pyproject_toml.html) . You may format your code using: +We format our code using PSF's [black](https://github.com/psf/black). Our builds will reject code that do not conform to +the standards defined in [`pyproject.toml`](https://black.readthedocs.io/en/stable/pyproject_toml.html) . You may format +your code using: ``` poetry run black . -t py310 --fast @@ -203,4 +231,6 @@ poetry run black --diff . -t py310 --fast ## Contributions -Contributions are welcome, feel free to fork our repository and open a pull request or open an issue. Please [review our contribution guidelines](https://github.com/idoneam/Canary/blob/dev/.github/contributing.md) before contributing. +Contributions are welcome, feel free to fork our repository and open a pull request or open an issue. +Please [review our contribution guidelines](https://github.com/idoneam/Canary/blob/dev/.github/contributing.md) +before contributing. From edf919b642d96e85780c2909f998c495faf61e8a Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Sat, 3 Sep 2022 09:47:15 -0400 Subject: [PATCH 007/127] add script for running the bot and install uvloop in actual main function --- canary/main.py | 9 +++++---- pyproject.toml | 3 +++ 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/canary/main.py b/canary/main.py index 32a3ffff2..f54cc2276 100755 --- a/canary/main.py +++ b/canary/main.py @@ -153,17 +153,18 @@ async def on_user_update(before, after): def main(): + if os.name == "posix": + import uvloop + uvloop.install() + for extension in startup: try: bot.load_extension(extension) except Exception as e: bot.dev_logger.warning(f"Failed to load extension {extension}\n" f"{type(e).__name__}: {e}") + bot.run(bot.config.discord_key) if __name__ == "__main__": - if os.name == "posix": - import uvloop - - uvloop.install() main() diff --git a/pyproject.toml b/pyproject.toml index d26696831..a0f375bc4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -10,6 +10,9 @@ packages = [ { include = "canary" }, ] +[tool.poetry.scripts] +canary = "canary.main:main" + [tool.poetry.dependencies] python = "~3.10.0" beautifulsoup4 = "==4.10.0" From a557ed665583228bf6b38a88c814e6c01fd7f622 Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Sat, 3 Sep 2022 10:43:28 -0400 Subject: [PATCH 008/127] fstrings --- canary/main.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/canary/main.py b/canary/main.py index f54cc2276..351284a03 100755 --- a/canary/main.py +++ b/canary/main.py @@ -71,10 +71,10 @@ async def load(ctx, extension_name: str): try: bot.load_extension(extension_name) except (AttributeError, ImportError) as e: - await ctx.send("```{}: {}\n```".format(type(e).__name__, str(e))) + await ctx.send(f"```{type(e).__name__}: {str(e)}\n```") return - await ctx.send("{} loaded.".format(extension_name)) + await ctx.send(f"{extension_name} loaded.") @bot.command() From 2a6f7498ebd9ac28bbdaf61481466e259842f326 Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Sat, 3 Sep 2022 10:43:54 -0400 Subject: [PATCH 009/127] typing/linting --- canary/cogs/banner.py | 12 ++++ canary/cogs/customreactions.py | 5 +- canary/cogs/helpers.py | 103 +++++++++++++++++++---------- canary/cogs/mod.py | 27 ++++++-- canary/cogs/music.py | 19 +++--- canary/cogs/quotes.py | 12 ++-- canary/cogs/reminder.py | 2 +- canary/cogs/utils/music_helpers.py | 4 +- 8 files changed, 125 insertions(+), 59 deletions(-) diff --git a/canary/cogs/banner.py b/canary/cogs/banner.py index d2b3e766b..e8a18cdfd 100644 --- a/canary/cogs/banner.py +++ b/canary/cogs/banner.py @@ -229,6 +229,18 @@ async def banner_winner(self, ctx, winner: discord.Member = None): You must be a moderator to use this command. """ + + if not self.guild: + return + + if not self.banner_submissions_channel: + await ctx.send("No banner submissions channel set.") + return + + if not self.banner_converted_channel: + await ctx.send("No converted banner channel set.") + return + if not self.start_datetime: await ctx.send("There is no banner contest right now.") return diff --git a/canary/cogs/customreactions.py b/canary/cogs/customreactions.py index 520c37159..76d67ca4a 100644 --- a/canary/cogs/customreactions.py +++ b/canary/cogs/customreactions.py @@ -59,9 +59,10 @@ class CustomReactions(commands.Cog): # Written by @le-potate def __init__(self, bot: Canary): self.bot: Canary = bot - self.reaction_list = [] - self.proposal_list = [] + self.reaction_list: list[str] = [] + self.proposal_list: list[str] = [] self.p_strings: PStringEncodings | None = None + self.rebuild_lists() def rebuild_lists(self): diff --git a/canary/cogs/helpers.py b/canary/cogs/helpers.py index 4cfe57b36..b93c87c60 100644 --- a/canary/cogs/helpers.py +++ b/canary/cogs/helpers.py @@ -87,7 +87,13 @@ async def exam(self, ctx: commands.Context): r = await fetch(MCGILL_EXAM_URL, "content") soup = BeautifulSoup(r, "html.parser") - link = soup.find("a", href=re.compile("exams/files/exams"))["href"] + + if (link_el := soup.find("a", href=re.compile(r"exams/files/exams"))) is None: + return await ctx.send("Error: could not find exam link on McGill's website") + + link = link_el["href"] + if isinstance(link, list): # Attribute access can return str or list[str] + link = link[0] if link[:2] == "//": link = "https:" + link @@ -155,13 +161,21 @@ def retrieve_string(label): tendency_string = retrieve_string("Tendency:") wind_string = retrieve_string("Wind:") humidity_string = retrieve_string("Humidity:") + + feels_like_values = { + "temp": re.search(r"-?\d+\.\d", temperature_string), + "humidity": re.search(r"\d+", humidity_string), + "ws_kph": re.search(r"\d+", wind_string), + } + feels_like_string = ( - Helpers._calculate_feels_like( - temp=float(re.search(r"-?\d+\.\d", temperature_string).group()), - humidity=float(re.search(r"\d+", humidity_string).group()), - ws_kph=float(re.search(r"\d+", wind_string).group()), - ) - if humidity_string and temperature_string and wind_string + Helpers._calculate_feels_like(**{k: float(v.group()) for k, v in feels_like_values.items()}) + if all(( + humidity_string, + temperature_string, + wind_string, + *feels_like_values.values(), + )) else "n/a" ) @@ -177,42 +191,55 @@ def retrieve_string(label): weather_now.add_field(name="Wind Speed", value=wind_string or "n/a", inline=True) weather_now.add_field(name="Feels like", value=feels_like_string, inline=True) + # Send weather first, then figure out alerts + await ctx.send(embed=weather_now) + # Weather alerts + def no_alerts_embed(title: str | None = None): + return discord.Embed(title=title, description="No alerts in effect.", colour=0xFF0000) + r_alert = await fetch(self.bot.config.gc_weather_alert_url, "content") alert_soup = BeautifulSoup(r_alert, "html.parser") alert_title = alert_soup.find("h1", string=ALERT_REGEX) + + if not alert_title: + return await ctx.send(embed=no_alerts_embed()) + alert_title_text = alert_title.get_text().strip() + no_alerts = no_alerts_embed(alert_title_text) # Only gets first

of warning. Subsequent paragraphs are ignored. - try: - alert_category = alert_title.find_next("h2") - alert_date = alert_category.find_next("span") - alert_heading = alert_date.find_next("strong") - # This is a string for some reason. - alert_location = alert_heading.find_next(string=MTL_REGEX) - # Only gets first

of warning. Subsequent paragraphs are ignored - alert_content = ". ".join(alert_location.find_next("p").get_text().strip().split(".")).rstrip() - - weather_alert = discord.Embed( - title=alert_title_text, - description="**{}** at {}".format(alert_category.get_text().strip(), alert_date.get_text().strip()), - colour=0xFF0000, - ) - weather_alert.add_field( - name=alert_heading.get_text().strip(), - value=f"**{alert_location.strip()}**\n{alert_content}", - inline=True, - ) - except AttributeError: - weather_alert = discord.Embed(title=alert_title_text, description="No alerts in effect.", colour=0xFF0000) - - # TODO Finish final message. Test on no-alert condition. + if (alert_category := alert_title.find_next("h2")) is None: + return await ctx.send(embed=no_alerts) + if (alert_date := alert_category.find_next("span")) is None: + return await ctx.send(embed=no_alerts) + if (alert_heading := alert_date.find_next("strong")) is None: + return await ctx.send(embed=no_alerts) + # This is a string for some reason. + if (alert_location := alert_heading.find_next(string=MTL_REGEX)) is None: + return await ctx.send(embed=no_alerts) + + # Only gets first

of warning. Subsequent paragraphs are ignored + if (alert_paragraph := alert_location.find_next("p")) is None: + return await ctx.send(embed=no_alerts) + + alert_content = ". ".join(alert_paragraph.get_text().strip().split(".")).rstrip() + + weather_alert = discord.Embed( + title=alert_title_text, + description=f"**{alert_category.get_text().strip()}** at {alert_date.get_text().strip()}", + colour=0xFF0000, + ) + weather_alert.add_field( + name=alert_heading.get_text().strip(), + value=f"**{alert_location.strip()}**\n{alert_content}", + inline=True, + ) # Sending final message - await ctx.send(embed=weather_now) await ctx.send(embed=weather_alert) @commands.command() @@ -368,13 +395,13 @@ async def urban(self, ctx: commands.Context, *, query: str): await p.paginate() @commands.command() - async def lmgtfy(self, ctx, *, query): + async def lmgtfy(self, ctx: commands.Context, *, query: str): """Generates a Let Me Google that For You link.""" url = LMGTFY_TEMPLATE.format(query.replace("+", "%2B").replace(" ", "+")) await ctx.send(url) @commands.command() - async def tex(self, ctx, *, query: str): + async def tex(self, ctx: commands.Context, *, query: str): """Parses and prints LaTeX equations.""" await ctx.trigger_typing() @@ -419,7 +446,7 @@ async def search(self, ctx: commands.Context, *, query: str): keyword = query.replace(" ", "+") pagelimit = 5 pagenum = 0 - courses = [] + courses: list = [] await ctx.trigger_typing() @@ -438,7 +465,7 @@ async def search(self, ctx: commands.Context, *, query: str): await ctx.send("No course found for: {}.".format(query)) return - course_list = {"names": [], "values": []} + course_list: dict[str, list[str]] = {"names": [], "values": []} for course in courses: # split results into titles + information title = course.find_all("h4")[0].get_text().split(" ") @@ -653,8 +680,11 @@ async def translate(self, ctx: commands.Context, command: str, *, inp_str: str | @is_developer() async def create_main_webhooks(self, ctx: commands.Context): """ - Create the general-use webhooks for each channel. Ignores channels that already have them + Create the general-use webhooks for each channel. The command ignores channels that already have webhooks. """ + if not self.guild: + return + ignored = 0 for channel in self.guild.text_channels: try: @@ -672,6 +702,7 @@ async def create_main_webhooks(self, ctx: commands.Context): await ctx.send(f"Created webhook for {channel.mention}") except discord.errors.Forbidden: ignored += 1 + await ctx.send(f"Ignored {ignored} channel{'s' if ignored == 1 else ''} without bot permissions") await ctx.send("Job completed.") diff --git a/canary/cogs/mod.py b/canary/cogs/mod.py index e25638194..129fb9fc4 100644 --- a/canary/cogs/mod.py +++ b/canary/cogs/mod.py @@ -49,6 +49,9 @@ def __init__(self, bot): async def on_ready(self): self.guild = self.bot.get_guild(self.bot.config.server_id) + if not self.guild: + return + await self.verification_purge_startup() conn = sqlite3.connect(self.bot.config.db_path) @@ -68,6 +71,7 @@ async def verification_purge_startup(self): self.verification_channel = utils.get(self.guild.text_channels, name=self.bot.config.verification_channel) if not self.verification_channel: return + # arbitrary min date because choosing dates that predate discord will cause an httpexception # when fetching message history after that date later on self.last_verification_purge_datetime = datetime(2018, 1, 1) @@ -114,7 +118,7 @@ async def check_verification_purge(self): conn.close() @commands.command() - async def answer(self, ctx, *args): + async def answer(self, ctx: commands.Context, *args): if isinstance(ctx.message.channel, discord.DMChannel): channel_to_send = utils.get( self.bot.get_guild(self.bot.config.server_id).text_channels, name=self.bot.config.reception_channel @@ -126,7 +130,7 @@ async def answer(self, ctx, *args): @commands.command(aliases=["dm"]) @is_moderator() - async def pm(self, ctx, user: discord.User, *, message): + async def pm(self, ctx: commands.Context, user: discord.User, *, message): """ PM a user on the server using the bot """ @@ -144,7 +148,7 @@ async def pm(self, ctx, user: discord.User, *, message): @commands.command() @is_moderator() - async def initiate_crabbo(self, ctx): + async def initiate_crabbo(self, ctx: commands.Context): """Initiates secret crabbo ceremony""" conn = sqlite3.connect(self.bot.config.db_path) @@ -167,7 +171,7 @@ async def initiate_crabbo(self, ctx): @commands.command() @is_moderator() - async def finalize_crabbo(self, ctx): + async def finalize_crabbo(self, ctx: commands.Context): """Sends crabbos their secret crabbo""" conn = sqlite3.connect(self.bot.config.db_path) @@ -197,6 +201,9 @@ async def finalize_crabbo(self, ctx): await ctx.message.delete() async def verification_purge_utility(self, after: datetime | discord.Message | None): + if not self.verification_channel: + return + # after can be None, a datetime or a discord message await self.verification_channel.send("Starting verification purge") channel = self.verification_channel @@ -227,27 +234,37 @@ async def verification_purge_utility(self, after: datetime | discord.Message | N @commands.command() @is_moderator() async def verification_purge(self, ctx, id: int = None): - """ " + """ Manually start the purge of pictures in the verification channel. If a message ID is provided, every pictures after that message will be removed. If no message ID is provided, this will be done for the whole channel (may take time). """ + + if not self.guild: + return + if not self.bot.config.verification_channel: await ctx.send("No verification channel set in config file") return + if not self.verification_channel: # if no verification_channel was found on startup, we try to see if it exists now self.verification_channel = utils.get(self.guild.text_channels, name=self.bot.config.verification_channel) if not self.verification_channel: await ctx.send(f"Cannot find verification channel named {self.bot.config.verification_channel}") return + message = None if id is not None: message = await self.verification_channel.fetch_message(id) + await self.verification_purge_utility(message) async def mute_utility(self, user: discord.Member, ctx=None): + if not self.guild: + return + # note that this is made such that if a user is already muted # we make sure the user still has the role, is still in the db, and still has a channel confirmation_channel = ctx.channel if ctx else self.appeals_log_channel diff --git a/canary/cogs/music.py b/canary/cogs/music.py index ec4d94306..c10e6d7d6 100644 --- a/canary/cogs/music.py +++ b/canary/cogs/music.py @@ -50,19 +50,19 @@ class Music(commands.Cog): def __init__(self, bot: Canary): self.bot: Canary = bot - self.track_queue: deque = deque() - self.track_history: deque = deque() + self.track_queue: deque[tuple[dict, str]] = deque() + self.track_history: deque[tuple[dict, str]] = deque() self.looping_queue: bool = False self.track_lock: asyncio.Lock = asyncio.Lock() - self.playing = None - self.looping_track = False + self.playing: tuple[dict, str] | None = None + self.looping_track: bool = False self.volume_level: float = self.bot.config.music["start_vol"] self.speed_flag: str = "atempo=1" self.speed_val: float = 1.0 self.skip_opts: Optional[tuple[str, int]] = None self.track_start_time: float = 0.0 - self.ban_role = self.bot.config.music["ban_role"] - self.pause_start: Optional[float] = None + self.ban_role: str = self.bot.config.music["ban_role"] + self.pause_start: float | None = None async def get_info(self, url: str): try: @@ -98,6 +98,9 @@ def total_len(self) -> int: return len(self.track_queue) + len(self.track_history) if self.looping_queue else len(self.track_queue) def play_track(self, ctx, *, skip_str: Optional[str] = None, delta: int = 0): + if self.playing is None: + return + ctx.voice_client.play( discord.PCMVolumeTransformer( discord.FFmpegPCMAudio( @@ -223,9 +226,9 @@ async def music(self, ctx, subcommand: Optional[str] = None, *, args: Optional[s await fn(ctx, converted) @check_banned - async def play(self, ctx, url: Optional[str] = None): + async def play(self, ctx: commands.Context, url: Optional[str] = None): """ - streams from a youtube url or track name, or if none is given, from the queue + streams from a YouTube url or track name, or if none is given, from the queue arguments: (optional: link or title of track) """ diff --git a/canary/cogs/quotes.py b/canary/cogs/quotes.py index f8cfc4c8e..09c0327f4 100644 --- a/canary/cogs/quotes.py +++ b/canary/cogs/quotes.py @@ -112,10 +112,13 @@ async def add_quotes( return member = member or ctx.message.reference.resolved.author quote = ctx.message.reference.resolved.content + + if member is None: + return + conn = sqlite3.connect(self.bot.config.db_path) c = conn.cursor() - t = (member.id, member.name, quote, str(ctx.message.created_at)) - c.execute("INSERT INTO Quotes VALUES (?,?,?,?)", t) + c.execute("INSERT INTO Quotes VALUES (?,?,?,?)", (member.id, member.name, quote, str(ctx.message.created_at))) msg = await ctx.send("Quote added.") conn.commit() @@ -145,8 +148,7 @@ def check(reaction, user): await msg.remove_reaction("🚮", self.bot.user) else: - t = (member.id, quote) - c.execute("DELETE FROM Quotes WHERE ID = ? AND Quote = ?", t) + c.execute("DELETE FROM Quotes WHERE ID = ? AND Quote = ?", (member.id, quote)) conn.commit() self.rebuild_mc() await msg.delete() @@ -401,7 +403,7 @@ async def generate(self, ctx: commands.Context, seed: str = None, min_length: in await ctx.send("Could not generate anything with that seed.", delete_after=60) return - longest_sentence = [] + longest_sentence: list[str] = [] retries = 0 while len(longest_sentence) < min_length and retries < 200: diff --git a/canary/cogs/reminder.py b/canary/cogs/reminder.py index a42770496..abf65c52d 100644 --- a/canary/cogs/reminder.py +++ b/canary/cogs/reminder.py @@ -47,7 +47,7 @@ ("no", "0"), ("none", "0"), ("zero", "0"), - *(zip(ONES_NAMES, range(1, 10))), + *zip(ONES_NAMES, range(1, 10)), ("ten", "10"), ("eleven", "11"), ("twelve", "12"), diff --git a/canary/cogs/utils/music_helpers.py b/canary/cogs/utils/music_helpers.py index 05f324d0b..6c925cb30 100644 --- a/canary/cogs/utils/music_helpers.py +++ b/canary/cogs/utils/music_helpers.py @@ -71,7 +71,7 @@ def insert_converter(arg: str): idx, url = arg.split(maxsplit=1) except ValueError as e: raise MusicArgConvertError(e) - return (int(idx), url) + return int(idx), url def check_playing(func): @@ -89,7 +89,7 @@ async def wrapper(self, ctx, *args, **kwargs): return wrapper -def mk_title_string(inf_dict) -> str: +def mk_title_string(inf_dict: dict) -> str: url = inf_dict.get("webpage_url") return ( inf_dict.get("title", "title not found") From d78586802907cc2a825f105f2f4b5c94f91969bd Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Sat, 3 Sep 2022 18:17:59 -0400 Subject: [PATCH 010/127] type hinting work --- canary/cogs/roles.py | 6 ++++- canary/cogs/utils/arg_converter.py | 4 +-- canary/cogs/utils/clamp_default.py | 8 +++--- canary/cogs/utils/mock_context.py | 37 +++++++++++++-------------- canary/cogs/utils/music_helpers.py | 7 ++--- canary/cogs/utils/p_strings.py | 16 ++++++++---- canary/cogs/utils/role_restoration.py | 6 +++-- 7 files changed, 48 insertions(+), 36 deletions(-) diff --git a/canary/cogs/roles.py b/canary/cogs/roles.py index e9a769ea8..37ee8f5dd 100644 --- a/canary/cogs/roles.py +++ b/canary/cogs/roles.py @@ -61,7 +61,11 @@ async def paginate_roles(ctx: commands.Context, roles, title="All roles in serve await p.paginate() async def toggle_role( - self, ctx, transaction: RoleTransaction, requested_role: Optional[str], categories: Tuple[str, ...] + self, + ctx: commands.Context, + transaction: RoleTransaction, + requested_role: Optional[str], + categories: Tuple[str, ...], ): """ Assigns a single role to a user with no checks from a category of roles diff --git a/canary/cogs/utils/arg_converter.py b/canary/cogs/utils/arg_converter.py index a002e5190..d0e432b73 100644 --- a/canary/cogs/utils/arg_converter.py +++ b/canary/cogs/utils/arg_converter.py @@ -149,7 +149,7 @@ async def convert(self, ctx, arguments): # Default converters class IntConverter(commands.Converter): @staticmethod - async def convert(ctx, argument): + async def convert(ctx, argument, **kwargs): try: return int(argument) except ValueError: @@ -158,7 +158,7 @@ async def convert(ctx, argument): class StrConverter(commands.Converter): @staticmethod - async def convert(ctx, argument): + async def convert(ctx, argument, **kwargs): try: return str(argument) except ValueError: diff --git a/canary/cogs/utils/clamp_default.py b/canary/cogs/utils/clamp_default.py index ae7d228a1..f1e14ba64 100644 --- a/canary/cogs/utils/clamp_default.py +++ b/canary/cogs/utils/clamp_default.py @@ -1,6 +1,4 @@ -# -*- coding: utf-8 -*- -# -# Copyright (C) idoneam (2016-2019) +# Copyright (C) idoneam (2016-2022) # # This file is part of Canary # @@ -17,8 +15,10 @@ # You should have received a copy of the GNU General Public License # along with Canary. If not, see . +from typing import Any + -def clamp_default(val, min_val, max_val, default): +def clamp_default(val: str | int | None, min_val: int, max_val: int, default: Any): """ Enforces a minimum and maximum (closed) bound on an integer. Returns a default value if val is not an integer or false-y. diff --git a/canary/cogs/utils/mock_context.py b/canary/cogs/utils/mock_context.py index d53f1aa4b..dba6a0c17 100644 --- a/canary/cogs/utils/mock_context.py +++ b/canary/cogs/utils/mock_context.py @@ -16,7 +16,6 @@ # along with Canary. If not, see . from dataclasses import dataclass -from typing import Union, Optional from discord import User, Member, Guild, ClientUser, Message, VoiceProtocol from discord.ext.commands import Bot, Cog, Command from discord.abc import Messageable @@ -26,21 +25,21 @@ class MockContext: """Class that can be used to mock a discord context""" - args: Optional[list] = None - author: Optional[Union[User, Member]] = None - bot: Optional[Bot] = None - channel: Optional[Union[Messageable]] = None - cog: Optional[Cog] = None - command: Optional[Command] = None - command_failed: Optional[bool] = None - guild: Optional[Guild] = None - invoked_parents: Optional[list[str]] = None - invoked_subcommand: Optional[Command] = None - invoked_with: Optional[str] = None - kwargs: Optional[dict] = None - me: Optional[Union[Member, ClientUser]] = None - message: Optional[Message] = None - prefix: Optional[str] = None - subcommand_passed: Optional[str] = None - valid: Optional[bool] = None - voice_client: Optional[VoiceProtocol] = None + args: list | None = None + author: User | Member | None = None + bot: Bot | None = None + channel: Messageable | None = None + cog: Cog | None = None + command: Command | None = None + command_failed: bool | None = None + guild: Guild | None = None + invoked_parents: list[str] | None = None + invoked_subcommand: Command | None = None + invoked_with: str | None = None + kwargs: dict | None = None + me: Member | ClientUser | None = None + message: Message | None = None + prefix: str | None = None + subcommand_passed: str | None = None + valid: bool | None = None + voice_client: VoiceProtocol | None = None diff --git a/canary/cogs/utils/music_helpers.py b/canary/cogs/utils/music_helpers.py index 6c925cb30..e5510f162 100644 --- a/canary/cogs/utils/music_helpers.py +++ b/canary/cogs/utils/music_helpers.py @@ -21,6 +21,7 @@ import yt_dlp import discord import random +from discord.ext.commands import Context class MusicArgConvertError(ValueError): @@ -76,7 +77,7 @@ def insert_converter(arg: str): def check_playing(func): @wraps(func) - async def wrapper(self, ctx, *args, **kwargs): + async def wrapper(self, ctx: Context, *args, **kwargs): if self.playing is None or ctx.voice_client is None or (not self.track_lock.locked()): await ctx.send("bot is not currently playing anything to a voice channel.") elif (ctx.author.voice is None or ctx.author.voice.channel != ctx.voice_client.channel) and len( @@ -128,7 +129,7 @@ def parse_time(time_str: str) -> int: def time_func(func): - async def wrapper(self, ctx, time_str: str): + async def wrapper(self, ctx: Context, time_str: str): try: parsed = parse_time(time_str) except ValueError: @@ -162,7 +163,7 @@ def mk_change_embed(data, track_list, title_str: str, footer_str: str) -> discor def check_banned(func): @wraps(func) - async def wrapper(self, ctx, *args, **kwargs): + async def wrapper(self, ctx: Context, *args, **kwargs): if discord.utils.get(ctx.author.roles, name=self.ban_role): return await ctx.send(f"you have the role `{self.ban_role}`, you are not allowed to do this.") return await func(self, ctx, *args, **kwargs) diff --git a/canary/cogs/utils/p_strings.py b/canary/cogs/utils/p_strings.py index 8de6aac44..289420cab 100644 --- a/canary/cogs/utils/p_strings.py +++ b/canary/cogs/utils/p_strings.py @@ -54,7 +54,7 @@ PLACEHOLDERS_PATTERNS = (re.compile(f"%{arg}%") for arg in PLACEHOLDERS_ARGS) -def _convert_choice_list(choice_list_string, to_pattern_str=False): +def _convert_choice_list(choice_list_string: str, to_pattern_str: bool = False): """ Takes a string with choice list placeholders and converts them to either a string where the choices are made (default) @@ -118,7 +118,7 @@ def _get_pattern_from_string(string, anywhere=False): class PString: - def __init__(self, string, user=None, channel=None, groups=[], additional_info=None): + def __init__(self, string, user=None, channel=None, groups: list | None = None, additional_info=None): """ A p-string is composed of a string with placeholders in it, and values for these placeholders. Printing a p-string will @@ -151,7 +151,7 @@ def __init__(self, string, user=None, channel=None, groups=[], additional_info=N self.string = string self.user = user self.channel = channel - self.groups = groups + self.groups: list = groups or [] self.additional_info = additional_info @property @@ -169,7 +169,13 @@ def __str__(self): class PStringEncodings: - def __init__(self, input_strings, output_strings, anywhere_values, additional_info_list=None): + def __init__( + self, + input_strings: list[str], + output_strings: list[str], + anywhere_values: bool | list[bool], + additional_info_list: list | None = None, + ): """ Used to encode a list of input strings with placeholders and a list of output strings with placeholders to @@ -233,7 +239,7 @@ def __init__(self, input_strings, output_strings, anywhere_values, additional_in for output_string, pattern, additional_info in zip(output_strings, self.patterns, additional_info_list) ] - def parser(self, content, user=None, channel=None): + def parser(self, content: str, user=None, channel=None): """ Return either None if the content matches no input pattern, or a random corresponding filled output p-string if it matches some diff --git a/canary/cogs/utils/role_restoration.py b/canary/cogs/utils/role_restoration.py index 1e03b1110..ac009df9a 100644 --- a/canary/cogs/utils/role_restoration.py +++ b/canary/cogs/utils/role_restoration.py @@ -23,11 +23,13 @@ from .paginator import Pages from .mock_context import MockContext -from canary.bot import muted_role as muted_role_name +from canary.bot import Canary, muted_role as muted_role_name import datetime -def save_existing_roles(bot, user: discord.Member, muted: bool = False, appeal_channel: discord.TextChannel = None): +async def save_existing_roles( + bot: Canary, user: discord.Member, muted: bool = False, appeal_channel: discord.TextChannel = None +): roles_id = [role.id for role in user.roles if role.name not in ("@everyone", muted_role_name)] if not roles_id and not muted: From 5b2f5d4b133eaf51dd3247c6c10c5aae25fc61d8 Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Sat, 3 Sep 2022 18:24:24 -0400 Subject: [PATCH 011/127] linting / code style / small fixes to strings --- canary/cogs/banner.py | 10 +- canary/cogs/currency.py | 4 +- canary/cogs/customreactions.py | 257 ++++++++++++++++----------------- canary/cogs/games.py | 8 +- canary/cogs/helpers.py | 24 +-- canary/cogs/info.py | 1 + canary/cogs/reminder.py | 11 +- canary/main.py | 14 +- 8 files changed, 164 insertions(+), 165 deletions(-) diff --git a/canary/cogs/banner.py b/canary/cogs/banner.py index e8a18cdfd..bdb50c9be 100644 --- a/canary/cogs/banner.py +++ b/canary/cogs/banner.py @@ -14,7 +14,6 @@ # # You should have received a copy of the GNU General Public License # along with Canary. If not, see . - # discord-py requirements import discord from discord.ext import commands, tasks @@ -175,7 +174,8 @@ def msg_check(msg): if date_str.lower() == "quit": await ctx.send("Command exited.") return - elif date_str.lower() == "now": + + if date_str.lower() == "now": timestamp = datetime.datetime.now().timestamp() else: try: @@ -308,6 +308,7 @@ def msg_check(msg): f"It might have been manually deleted. Exiting command." ) return + try: converted_message = await self.banner_converted_channel.fetch_message(converted_message_id) except discord.errors.NotFound: @@ -345,8 +346,7 @@ def msg_check(msg): await ctx.send("Command timed out.") return - confirmation_str = confirmation_msg.content - if confirmation_str.lower() != "yes": + if confirmation_msg.content.lower() != "yes": await ctx.send("Exiting without selecting winner.") return @@ -397,7 +397,7 @@ def msg_check(msg): await ctx.send("Successfully set banner and ended contest.") @commands.command(aliases=["submitbanner"]) - async def submit_banner(self, ctx, *args): + async def submit_banner(self, ctx: commands.Context, *args): """ Submit a picture for an Banner Picture of the Week contest diff --git a/canary/cogs/currency.py b/canary/cogs/currency.py index ba66b07e8..f7a7b1b34 100644 --- a/canary/cogs/currency.py +++ b/canary/cogs/currency.py @@ -396,11 +396,11 @@ async def give(self, ctx, user: discord.Member = None, amount: str = None): # Handle invalid cases if amount_dec is None: - await ctx.send("Invalid quantity: '{}'.".format(amount)) + await ctx.send(f"Invalid quantity: '{amount}'.") return if amount_dec <= 0: - await ctx.send("You cannot give {}!".format(self.format_symbol_currency(amount_dec))) + await ctx.send(f"You cannot give {self.format_symbol_currency(amount_dec)}!") return if amount_dec > balance: diff --git a/canary/cogs/customreactions.py b/canary/cogs/customreactions.py index 76d67ca4a..7b50e1a0c 100644 --- a/canary/cogs/customreactions.py +++ b/canary/cogs/customreactions.py @@ -91,7 +91,7 @@ def rebuild_proposal_list(self): conn.close() @commands.Cog.listener() - async def on_message(self, message): + async def on_message(self, message: discord.Message): if message.author == self.bot.user: return @@ -115,7 +115,7 @@ async def on_message(self, message): @commands.max_concurrency(1, per=commands.BucketType.user, wait=False) @commands.command(aliases=["customreaction", "customreacts", "customreact"]) - async def customreactions(self, ctx): + async def customreactions(self, ctx: commands.Context): current_options = [] main_user = ctx.message.author await ctx.message.delete() @@ -144,7 +144,7 @@ def msg_check(msg): # asyncio.create_task(ctx.send([...])) # (the get_event_loop() part isn't necessary) loop = asyncio.get_event_loop() - loop.create_task(ctx.send("Attachments cannot be used, " "but you may use URLs")) + loop.create_task(ctx.send("Attachments cannot be used, but you may use URLs")) else: return True @@ -163,7 +163,7 @@ def number_check(msg): return number_check - async def wait_for_reaction(message): + async def wait_for_reaction(message: discord.Message): try: reaction, user = await self.bot.wait_for( "reaction_add", check=get_reaction_check(reaction_user=main_user), timeout=60 @@ -174,7 +174,7 @@ async def wait_for_reaction(message): return return reaction, user - async def wait_for_message(message): + async def wait_for_message(message: discord.Message): try: msg = await self.bot.wait_for("message", check=get_msg_check(msg_user=main_user), timeout=60) except asyncio.TimeoutError: @@ -185,14 +185,14 @@ async def wait_for_message(message): await msg.delete() return content - async def add_multiple_reactions(message, reactions): + async def add_multiple_reactions(message: discord.Message, reactions): for reaction in reactions: await message.add_reaction(reaction) - async def add_yes_or_no_reactions(message): + async def add_yes_or_no_reactions(message: discord.Message): await add_multiple_reactions(message, (EMOJI["zero"], EMOJI["one"], EMOJI["stop_button"])) - async def add_control_reactions(message): + async def add_control_reactions(message: discord.Message): await add_multiple_reactions( message, ( @@ -205,7 +205,7 @@ async def add_control_reactions(message): ), ) - async def create_assistant(message, is_moderator): + async def create_assistant(message: discord.Message, is_moderator: bool): if is_moderator: description = ( f"{EMOJI['new']} Add a new custom reaction\n" @@ -265,15 +265,13 @@ async def create_assistant(message, is_moderator): await leave(message) return True - async def add_custom_react(message, is_moderator): + async def add_custom_react(message: discord.Message, is_moderator: bool): if is_moderator: title = "Add a custom reaction" footer = f"{main_user} is currently adding a custom reaction. \n" f"Write '{STOP_TEXT}' to cancel." else: title = "Propose a custom reaction" - footer = ( - f"{main_user} is currently proposing a custom " f"reaction. \n" f"Write '{STOP_TEXT}' to cancel." - ) + footer = f"{main_user} is currently proposing a custom reaction. \n" f"Write '{STOP_TEXT}' to cancel." description = "Write the prompt the bot will react to" await message.edit( embed=discord.Embed(title=title, description=description).set_footer( @@ -286,7 +284,7 @@ async def add_custom_react(message, is_moderator): if prompt_message.lower() == STOP_TEXT: await leave(message) return True - description = f"Prompt: {prompt_message}\nWrite the response " f"the bot will send" + description = f"Prompt: {prompt_message}\nWrite the response the bot will send" await message.edit( embed=discord.Embed(title=title, description=description).set_footer( text=footer, icon_url=main_user.avatar_url @@ -316,7 +314,7 @@ async def add_custom_react(message, is_moderator): if is_moderator: footer = f"{main_user} is currently adding a custom reaction." else: - footer = f"{main_user} is currently " f"proposing a custom reaction." + footer = f"{main_user} is currently proposing a custom reaction." current_options.extend((EMOJI["ok"], EMOJI["stop_button"])) await add_multiple_reactions(message, (*NUMBERS[1:4], EMOJI["ok"], EMOJI["stop_button"])) await message.edit( @@ -363,7 +361,7 @@ async def add_custom_react(message, is_moderator): title = f"Custom reaction proposal successfully submitted!" description = f"-Prompt: {prompt_message}\n" f"-Response: {response}" if delete: - description = f"{description}\n-Will delete the " f"message that calls the reaction" + description = f"{description}\n-Will delete the message that calls the reaction" if anywhere: description = ( f"{description}\n" @@ -391,14 +389,14 @@ async def add_custom_react(message, is_moderator): await leave(message) return True - async def list_custom_reacts(message, proposals): + async def list_custom_reacts(message: discord.Message, proposals): current_list = self.proposal_list if proposals else self.reaction_list if not current_list: if proposals: - title = "There are currently no custom reaction " "proposals in this server" + title = "There are currently no custom reaction proposals in this server" else: - title = "There are currently no custom reactions in " "this server" + title = "There are currently no custom reactions in this server" await message.edit(embed=discord.Embed(title=title), delete_after=60) return @@ -527,9 +525,9 @@ async def list_custom_reacts(message, proposals): if not current_list: if proposals: - title = "There are currently no custom " "reaction proposals in this server" + title = "There are currently no custom reaction proposals in this server" else: - title = "There are currently no custom " "reactions in this server" + title = "There are currently no custom reactions in this server" await message.edit(embed=discord.Embed(title=title), delete_after=60) return @@ -561,7 +559,7 @@ async def list_custom_reacts(message, proposals): user_modifying = await p.paginate() - async def information_on_react(message, current_list, number, proposals): + async def information_on_react(message: discord.Message, current_list, number, proposals): await message.edit(embed=LOADING_EMBED) custom_react = current_list[number - 1] @@ -574,13 +572,13 @@ async def information_on_react(message, current_list, number, proposals): if delete == 1: delete_str = "Deletes the message that calls the reaction" else: - delete_str = "Does not delete the message that " "calls the reaction" + delete_str = "Does not delete the message that calls the reaction" if anywhere == 1: - anywhere_str = "Activates the custom reaction if " "the prompt is anywhere in a message" + anywhere_str = "Activates the custom reaction if the prompt is anywhere in a message" else: - anywhere_str = "Only activates the custom reaction " "if the prompt is the full message" + anywhere_str = "Only activates the custom reaction if the prompt is the full message" if dm == 1: - dm_str = "Reacts in the DMs of the user who calls " "the reaction instead of the channel" + dm_str = "Reacts in the DMs of the user who calls the reaction instead of the channel" else: dm_str = "Reacts directly into the channel" @@ -651,7 +649,7 @@ async def information_on_react(message, current_list, number, proposals): current_options.clear() await message.clear_reactions() - async def edit_custom_react(message, reaction, user, custom_react, proposals): + async def edit_custom_react(message: discord.Message, reaction, user, custom_react, proposals): current_options.clear() await message.clear_reactions() custom_react_id = custom_react[0] @@ -672,9 +670,7 @@ async def edit_custom_react(message, reaction, user, custom_react, proposals): ) else: title = "Modify a custom reaction" - footer = ( - f"{user} is currently " f"modifying a custom reaction. " f"\nWrite '{STOP_TEXT}' to cancel." - ) + footer = f"{user} is currently modifying a custom reaction. \nWrite '{STOP_TEXT}' to cancel." description = "Please enter the new prompt" await message.edit( embed=discord.Embed(title=title, description=description).set_footer( @@ -710,13 +706,13 @@ async def edit_custom_react(message, reaction, user, custom_react, proposals): return True t = (prompt, custom_react_id) - c.execute("UPDATE CustomReactions SET Prompt = ? " "WHERE CustomReactionID = ?", t) + c.execute("UPDATE CustomReactions SET Prompt = ? WHERE CustomReactionID = ?", t) conn.commit() self.rebuild_lists() if proposals: - title = "Prompt successfully modified! " "Returning to list of reaction proposals..." + title = "Prompt successfully modified! Returning to list of reaction proposals..." else: - title = "Prompt successfully modified! " "Returning to list of current reactions..." + title = "Prompt successfully modified! Returning to list of current reactions..." await message.edit( embed=discord.Embed(title=title).set_footer(text=f"Modified by {user}.", icon_url=user.avatar_url) ) @@ -728,15 +724,12 @@ async def edit_custom_react(message, reaction, user, custom_react, proposals): if proposals: title = "Modify a custom reaction proposal" footer = ( - f"{user} is currently modifying a " - f"custom reaction proposal. \n" + f"{user} is currently modifying a custom reaction proposal. \n" f"Write '{STOP_TEXT}' to cancel." ) else: title = "Modify a custom reaction" - footer = ( - f"{user} is currently modifying a " f"custom reaction. " f"\nWrite '{STOP_TEXT}' to cancel." - ) + footer = f"{user} is currently modifying a custom reaction. \nWrite '{STOP_TEXT}' to cancel." description = "Please enter the new response" await message.edit( embed=discord.Embed(title=title, description=description).set_footer( @@ -750,14 +743,12 @@ async def edit_custom_react(message, reaction, user, custom_react, proposals): except asyncio.TimeoutError: if proposals: title = ( - "The modification of the custom reaction " - "proposal timed out. " + "The modification of the custom reaction proposal timed out. " "Returning to list of reaction proposals..." ) else: title = ( - "The modification of the custom reaction " - "timed out. " + "The modification of the custom reaction timed out. " "Returning to list of current reactions..." ) await message.edit(embed=discord.Embed(title=title)) @@ -772,14 +763,15 @@ async def edit_custom_react(message, reaction, user, custom_react, proposals): await leave(message) return True - t = (response, custom_react_id) - c.execute("UPDATE CustomReactions SET Response = ? " "WHERE CustomReactionID = ?", t) + c.execute( + "UPDATE CustomReactions SET Response = ? WHERE CustomReactionID = ?", (response, custom_react_id) + ) conn.commit() self.rebuild_lists() if proposals: - title = "Response successfully modified! " "Returning to list of reaction proposals..." + title = "Response successfully modified! Returning to list of reaction proposals..." else: - title = "Response successfully modified! " "Returning to list of current reactions..." + title = "Response successfully modified! Returning to list of current reactions..." await message.edit( embed=discord.Embed(title=title).set_footer(text=f"Modified by {user}.", icon_url=user.avatar_url) ) @@ -790,11 +782,11 @@ async def edit_custom_react(message, reaction, user, custom_react, proposals): if reaction.emoji == EMOJI["three"]: await message.edit(embed=LOADING_EMBED) if proposals: - title = "Modify a custom reaction proposal. " "React with the option you want" - footer = f"{user} is currently modifying a " f"custom reaction proposal. \n" + title = "Modify a custom reaction proposal. React with the option you want" + footer = f"{user} is currently modifying a custom reaction proposal. \n" else: - title = "Modify a custom reaction. React with the " "option you want" - footer = f"{user} is currently modifying a " f"custom reaction. \n" + title = "Modify a custom reaction. React with the option you want" + footer = f"{user} is currently modifying a custom reaction. \n" description = ( f"Should the message that calls the " f"reaction be deleted?\n" @@ -806,8 +798,10 @@ async def edit_custom_react(message, reaction, user, custom_react, proposals): current_options.extend((*NUMBERS[0:2], EMOJI["stop_button"])) await add_yes_or_no_reactions(message) await message.edit( - embed=discord.Embed(title=title, description=description).set_footer( - text=footer, icon_url=user.avatar_url + embed=( + discord.Embed(title=title, description=description).set_footer( + text=footer, icon_url=user.avatar_url + ) ) ) @@ -819,14 +813,12 @@ async def edit_custom_react(message, reaction, user, custom_react, proposals): except asyncio.TimeoutError: if proposals: title = ( - "The modification of the custom reaction " - "proposal timed out. " + "The modification of the custom reaction proposal timed out. " "Returning to list of reaction proposals..." ) else: title = ( - "The modification of the custom reaction " - "timed out. " + "The modification of the custom reaction timed out. " "Returning to list of current reactions..." ) await message.edit(embed=discord.Embed(title=title)) @@ -842,9 +834,9 @@ async def edit_custom_react(message, reaction, user, custom_react, proposals): if reaction.emoji == EMOJI["zero"]: if delete == 0: if proposals: - title = "Successfully kept current option! " "Returning to list of reaction " "proposals..." + title = "Successfully kept current option! Returning to list of reaction proposals..." else: - title = "Successfully kept current option! " "Returning to list of current " "reactions..." + title = "Successfully kept current option! Returning to list of current reactions..." await message.edit( embed=discord.Embed(title=title).set_footer( text=f"Modified by {user}.", icon_url=user.avatar_url @@ -854,15 +846,13 @@ async def edit_custom_react(message, reaction, user, custom_react, proposals): await asyncio.sleep(5) else: t = (0, custom_react_id) - c.execute("UPDATE CustomReactions SET DeletePrompt = ? " "WHERE CustomReactionID = ?", t) + c.execute("UPDATE CustomReactions SET DeletePrompt = ? WHERE CustomReactionID = ?", t) conn.commit() self.rebuild_lists() if proposals: - title = ( - "Option successfully modified! " "Returning to list of current " "reaction proposals..." - ) + title = "Option successfully modified! Returning to list of current reaction proposals..." else: - title = "Option successfully modified! " "Returning to list of current " "reactions..." + title = "Option successfully modified! Returning to list of current reactions..." await message.edit( embed=discord.Embed(title=title).set_footer( text=f"Modified by {user}.", icon_url=user.avatar_url @@ -875,9 +865,9 @@ async def edit_custom_react(message, reaction, user, custom_react, proposals): elif reaction.emoji == EMOJI["one"]: if delete == 1: if proposals: - title = "Successfully kept current option! " "Returning to list of " "reaction proposals..." + title = "Successfully kept current option! Returning to list of reaction proposals..." else: - title = "Successfully kept current option! " "Returning to list of " "current reactions..." + title = "Successfully kept current option! Returning to list of current reactions..." await message.edit( embed=discord.Embed(title=title).set_footer( text=f"Modified by {user}.", icon_url=user.avatar_url @@ -886,16 +876,16 @@ async def edit_custom_react(message, reaction, user, custom_react, proposals): conn.close() await asyncio.sleep(5) else: - t = (1, custom_react_id) - c.execute("UPDATE CustomReactions SET DeletePrompt = ? " "WHERE CustomReactionID = ?", t) + c.execute( + "UPDATE CustomReactions SET DeletePrompt = ? WHERE CustomReactionID = ?", + (1, custom_react_id), + ) conn.commit() self.rebuild_lists() if proposals: - title = ( - "Option successfully modified! " "Returning to list of current " "reaction proposals..." - ) + title = "Option successfully modified! Returning to list of current reaction proposals..." else: - title = "Option successfully modified! " "Returning to list of current " "reactions..." + title = "Option successfully modified! Returning to list of current reactions..." await message.edit( embed=discord.Embed(title=title).set_footer( text=f"Modified by {user}.", icon_url=user.avatar_url @@ -912,11 +902,11 @@ async def edit_custom_react(message, reaction, user, custom_react, proposals): if reaction.emoji == EMOJI["four"]: await message.edit(embed=LOADING_EMBED) if proposals: - title = "Modify a custom reaction proposal. " "React with the option you want" - footer = f"{user} is currently modifying a custom " f"reaction proposal. \n" + title = "Modify a custom reaction proposal. React with the option you want" + footer = f"{user} is currently modifying a custom reaction proposal. \n" else: - title = "Modify a custom reaction. " "React with the option you want" - footer = f"{user} is currently modifying a custom " f"reaction. \n" + title = "Modify a custom reaction. React with the option you want" + footer = f"{user} is currently modifying a custom reaction. \n" description = ( f"Should the custom reaction be activated " f"if the prompt is anywhere in a message?\n" @@ -940,14 +930,12 @@ async def edit_custom_react(message, reaction, user, custom_react, proposals): except asyncio.TimeoutError: if proposals: title = ( - "The modification of the custom reaction " - "proposal timed out. " + "The modification of the custom reaction proposal timed out. " "Returning to list of reaction proposals..." ) else: title = ( - "The modification of the custom reaction " - "timed out. " + "The modification of the custom reaction timed out. " "Returning to list of current reactions..." ) await message.edit(embed=discord.Embed(title=title)) @@ -963,9 +951,9 @@ async def edit_custom_react(message, reaction, user, custom_react, proposals): if reaction.emoji == EMOJI["zero"]: if anywhere == 0: if proposals: - title = "Successfully kept current option! " "Returning to list of " "reaction proposals..." + title = "Successfully kept current option! Returning to list of reaction proposals..." else: - title = "Successfully kept current option! " "Returning to list of " "current reactions..." + title = "Successfully kept current option! Returning to list of current reactions..." await message.edit( embed=discord.Embed(title=title).set_footer( text=f"Modified by {user}.", icon_url=user.avatar_url @@ -975,18 +963,18 @@ async def edit_custom_react(message, reaction, user, custom_react, proposals): await asyncio.sleep(5) else: t = (0, custom_react_id) - c.execute("UPDATE CustomReactions SET Anywhere = ? " "WHERE CustomReactionID = ?", t) + c.execute("UPDATE CustomReactions SET Anywhere = ? WHERE CustomReactionID = ?", t) conn.commit() self.rebuild_lists() if proposals: - title = ( - "Option successfully modified! " "Returning to list of current " "reaction proposals..." - ) + title = "Option successfully modified! Returning to list of current reaction proposals..." else: - title = "Option successfully modified! " "Returning to list of current " "reactions..." + title = "Option successfully modified! Returning to list of current reactions..." await message.edit( - embed=discord.Embed(title=title).set_footer( - text=f"Modified by {user}.", icon_url=user.avatar_url + embed=( + discord.Embed(title=title).set_footer( + text=f"Modified by {user}.", icon_url=user.avatar_url + ) ) ) conn.close() @@ -996,9 +984,9 @@ async def edit_custom_react(message, reaction, user, custom_react, proposals): elif reaction.emoji == EMOJI["one"]: if anywhere == 1: if proposals: - title = "Successfully kept current option! " "Returning to list of " "reaction proposals..." + title = "Successfully kept current option! Returning to list of reaction proposals..." else: - title = "Successfully kept current option! " "Returning to list of current " "reactions..." + title = "Successfully kept current option! Returning to list of current reactions..." await message.edit( embed=discord.Embed(title=title).set_footer( text=f"Modified by {user}.", icon_url=user.avatar_url @@ -1008,15 +996,13 @@ async def edit_custom_react(message, reaction, user, custom_react, proposals): await asyncio.sleep(5) else: t = (1, custom_react_id) - c.execute("UPDATE CustomReactions SET Anywhere = ? " "WHERE CustomReactionID = ?", t) + c.execute("UPDATE CustomReactions SET Anywhere = ? WHERE CustomReactionID = ?", t) conn.commit() self.rebuild_lists() if proposals: - title = ( - "Option successfully modified! " "Returning to list of current " "reaction proposals..." - ) + title = "Option successfully modified! Returning to list of current reaction proposals..." else: - title = "Option successfully modified! " "Returning to list of current " "reactions..." + title = "Option successfully modified! Returning to list of current reactions..." await message.edit( embed=discord.Embed(title=title).set_footer( text=f"Modified by {user}.", icon_url=user.avatar_url @@ -1033,14 +1019,13 @@ async def edit_custom_react(message, reaction, user, custom_react, proposals): if reaction.emoji == EMOJI["five"]: await message.edit(embed=LOADING_EMBED) if proposals: - title = "Modify a custom reaction proposal. " "React with the option you want" - footer = f"{user} is currently modifying a custom " f"reaction " f"proposal. \n" + title = "Modify a custom reaction proposal. React with the option you want" + footer = f"{user} is currently modifying a custom reaction proposal. \n" else: - title = "Modify a custom reaction. React with the " "option you want" - footer = f"{user} is currently modifying a " f"custom reaction. \n" + title = "Modify a custom reaction. React with the option you want" + footer = f"{user} is currently modifying a custom reaction. \n" description = ( - f"Should the reaction be sent in the DMs of " - f"the user who called the reaction " + f"Should the reaction be sent in the DMs of the user who called the reaction " f"instead of the channel?\n" f"{EMOJI['zero']} No\n" f"{EMOJI['one']} Yes" @@ -1050,8 +1035,10 @@ async def edit_custom_react(message, reaction, user, custom_react, proposals): current_options.extend((*NUMBERS[0:2], EMOJI["stop_button"])) await add_yes_or_no_reactions(message) await message.edit( - embed=discord.Embed(title=title, description=description).set_footer( - text=footer, icon_url=user.avatar_url + embed=( + discord.Embed(title=title, description=description).set_footer( + text=footer, icon_url=user.avatar_url + ) ) ) try: @@ -1062,14 +1049,12 @@ async def edit_custom_react(message, reaction, user, custom_react, proposals): except asyncio.TimeoutError: if proposals: title = ( - "The modification of the custom reaction " - "proposal timed out. " + "The modification of the custom reaction proposal timed out. " "Returning to list of reaction proposals..." ) else: title = ( - "The modification of the custom reaction " - "timed out. " + "The modification of the custom reaction timed out. " "Returning to list of current reactions..." ) await message.edit(embed=discord.Embed(title=title)) @@ -1085,30 +1070,31 @@ async def edit_custom_react(message, reaction, user, custom_react, proposals): if reaction.emoji == EMOJI["zero"]: if dm == 0: if proposals: - title = "Successfully kept current option! " "Returning to list of " "reaction proposals..." + title = "Successfully kept current option! Returning to list of reaction proposals..." else: - title = "Successfully kept current option! " "Returning to list of " "current reactions..." + title = "Successfully kept current option! Returning to list of current reactions..." await message.edit( - embed=discord.Embed(title=title).set_footer( - text=f"Modified by {user}.", icon_url=user.avatar_url + embed=( + discord.Embed(title=title).set_footer( + text=f"Modified by {user}.", icon_url=user.avatar_url + ) ) ) conn.close() await asyncio.sleep(5) else: - t = (0, custom_react_id) - c.execute("UPDATE CustomReactions SET DM = ? " "WHERE CustomReactionID = ?", t) + c.execute("UPDATE CustomReactions SET DM = ? WHERE CustomReactionID = ?", (0, custom_react_id)) conn.commit() self.rebuild_lists() if proposals: - title = ( - "Option successfully modified! " "Returning to list of current " "reaction proposals..." - ) + title = "Option successfully modified! Returning to list of current reaction proposals..." else: - title = "Option successfully modified! " "Returning to list of current " "reactions..." + title = "Option successfully modified! Returning to list of current reactions..." await message.edit( - embed=discord.Embed(title=title).set_footer( - text=f"Modified by {user}.", icon_url=user.avatar_url + embed=( + discord.Embed(title=title).set_footer( + text=f"Modified by {user}.", icon_url=user.avatar_url + ) ) ) conn.close() @@ -1117,30 +1103,32 @@ async def edit_custom_react(message, reaction, user, custom_react, proposals): elif reaction.emoji == EMOJI["one"]: if dm == 1: if proposals: - title = "Successfully kept current option! " "Returning to list of " "reaction proposals..." + title = "Successfully kept current option! Returning to list of reaction proposals..." else: - title = "Successfully kept current option! " "Returning to list of current " "reactions..." + title = "Successfully kept current option! Returning to list of current reactions..." await message.edit( - embed=discord.Embed(title=title).set_footer( - text=f"Modified by {user}.", icon_url=user.avatar_url + embed=( + discord.Embed(title=title).set_footer( + text=f"Modified by {user}.", icon_url=user.avatar_url + ) ) ) conn.close() await asyncio.sleep(5) else: t = (1, custom_react_id) - c.execute("UPDATE CustomReactions SET DM = ? " "WHERE CustomReactionID = ?", t) + c.execute("UPDATE CustomReactions SET DM = ? WHERE CustomReactionID = ?", t) conn.commit() self.rebuild_lists() if proposals: - title = ( - "Option successfully modified! " "Returning to list of current " "reaction proposals..." - ) + title = "Option successfully modified! Returning to list of current reaction proposals..." else: - title = "Option successfully modified! " "Returning to list of current " "reactions..." + title = "Option successfully modified! Returning to list of current reactions..." await message.edit( - embed=discord.Embed(title=title).set_footer( - text=f"Modified by {user}.", icon_url=user.avatar_url + embed=( + discord.Embed(title=title).set_footer( + text=f"Modified by {user}.", icon_url=user.avatar_url + ) ) ) conn.close() @@ -1153,7 +1141,7 @@ async def edit_custom_react(message, reaction, user, custom_react, proposals): # Approve a custom reaction proposal if reaction.emoji == EMOJI["white_check_mark"]: t = (0, custom_react_id) - c.execute("UPDATE CustomReactions SET Proposal = ? " "WHERE CustomReactionID = ?", t) + c.execute("UPDATE CustomReactions SET Proposal = ? WHERE CustomReactionID = ?", t) conn.commit() self.rebuild_lists() title = ( @@ -1172,13 +1160,12 @@ async def edit_custom_react(message, reaction, user, custom_react, proposals): conn.commit() if proposals: title = ( - "Custom reaction proposal successfully " - "rejected! Returning to list of current " + "Custom reaction proposal successfully rejected! Returning to list of current " "reaction proposals..." ) footer = f"Rejected by {user}." else: - title = "Custom reaction successfully deleted! " "Returning to list of current reactions..." + title = "Custom reaction successfully deleted! Returning to list of current reactions..." footer = f"Deleted by {user}." await message.edit(embed=discord.Embed(title=title).set_footer(text=footer, icon_url=user.avatar_url)) conn.close() @@ -1191,7 +1178,7 @@ async def edit_custom_react(message, reaction, user, custom_react, proposals): return True async def list_placeholders(message): - title = "The following placeholders can be used in " "prompts and responses:" + title = "The following placeholders can be used in prompts and responses:" description = ( "-%user%: the user who called " "the prompt (can only be used in a response)\n" diff --git a/canary/cogs/games.py b/canary/cogs/games.py index 202709f1a..eda043bd2 100644 --- a/canary/cogs/games.py +++ b/canary/cogs/games.py @@ -51,6 +51,7 @@ def __init__(self, bot: Canary, hangman_tbl_name: str): self.hm_norm_win: int = bot.config.games["hm_norm_win"] self.hm_timeout: int = bot.config.games["hm_timeout"] self.hm_locks: dict[discord.TextChannel, asyncio.Lock] = dict() + with open(f"{os.getcwd()}/data/premade/{hangman_tbl_name}.obj", "rb") as hangman_pkl: self.hangman_dict: dict[str, tuple[list[tuple[str, str | None]], str]] = pickle.load(hangman_pkl) @@ -67,7 +68,8 @@ def help_str(self): "resend this message by typing `?{hm|hangman} help`." ) - def hm_msg_check(self, hm_channel: discord.TextChannel, lowered: str, msg: discord.Message): + @staticmethod + def hm_msg_check(hm_channel: discord.TextChannel, lowered: str, msg: discord.Message): return msg.channel == hm_channel and ( (len(msg.content) == 1 and msg.content.isalpha()) or msg.content.lower() == lowered ) @@ -76,7 +78,7 @@ def hm_msg_check(self, hm_channel: discord.TextChannel, lowered: str, msg: disco async def hangman(self, ctx, command: str | None = None): """ play a nice game of hangman with internet strangers! - guesses must be single letters (interpreted in a case insensitive manner) or the entire correct word. + guesses must be single letters (interpreted in a case-insensitive manner) or the entire correct word. can either be called with "?{hm|hangman}" or "?{hm|hangman} x", where x is a valid category argument. see all categories by typing "?{hm|hangman} help". quit an ongoing game by typing "?{hm|hangman} quit". @@ -84,7 +86,7 @@ async def hangman(self, ctx, command: str | None = None): rules: - 5 wrong guesses allowed - for a guess to be registered, it must either be the full correct word or a single letter - - guesses are interpreted in a case insensitive manner + - guesses are interpreted in a case-insensitive manner """ await ctx.trigger_typing() diff --git a/canary/cogs/helpers.py b/canary/cogs/helpers.py index b93c87c60..c42cc65d6 100644 --- a/canary/cogs/helpers.py +++ b/canary/cogs/helpers.py @@ -170,12 +170,14 @@ def retrieve_string(label): feels_like_string = ( Helpers._calculate_feels_like(**{k: float(v.group()) for k, v in feels_like_values.items()}) - if all(( - humidity_string, - temperature_string, - wind_string, - *feels_like_values.values(), - )) + if all( + ( + humidity_string, + temperature_string, + wind_string, + *feels_like_values.values(), + ) + ) else "n/a" ) @@ -292,10 +294,12 @@ async def course(self, ctx: commands.Context, *, query: str): (a, b) = i.get_text().split(":", 1) tidbits.append((a.strip(), b.strip())) - em = discord.Embed(title=title, description=url, colour=0xDA291C) - em.add_field(name="Overview", value=overview, inline=False) - em.add_field(name="Terms", value=terms, inline=False) - em.add_field(name="Instructor(s)", value=instructors, inline=False) + em = ( + discord.Embed(title=title, description=url, colour=0xDA291C) + .add_field(name="Overview", value=overview, inline=False) + .add_field(name="Terms", value=terms, inline=False) + .add_field(name="Instructor(s)", value=instructors, inline=False) + ) for (a, b) in tidbits: em.add_field(name=a, value=b, inline=False) await ctx.send(embed=em) diff --git a/canary/cogs/info.py b/canary/cogs/info.py index d8aa32ff0..1c760aae0 100644 --- a/canary/cogs/info.py +++ b/canary/cogs/info.py @@ -27,6 +27,7 @@ def __init__(self, bot): @commands.command() async def version(self, ctx): + # TODO: use asyncio.create_subprocess_shell version = subprocess.check_output(("git", "describe", "--tags"), universal_newlines=True).strip() commit, authored = ( subprocess.check_output(("git", "log", "-1", "--pretty=format:%h %aI"), universal_newlines=True) diff --git a/canary/cogs/reminder.py b/canary/cogs/reminder.py index abf65c52d..5396e5354 100644 --- a/canary/cogs/reminder.py +++ b/canary/cogs/reminder.py @@ -89,6 +89,7 @@ # Regex for time HH:MM HM_REGEX = re.compile(r"\b([0-1]?[0-9]|2[0-4]):([0-5][0-9])") +FREQUENCIES = {"daily": 1, "weekly": 7, "monthly": 30} class Reminder(commands.Cog): def __init__(self, bot: Canary): @@ -104,11 +105,11 @@ async def check_reminders(self): await self.bot.wait_until_ready() while not self.bot.is_closed(): + if not (guild := self.guild): + return + conn = sqlite3.connect(self.bot.config.db_path) c = conn.cursor() - guild = self.bot.get_guild(self.bot.config.server_id) - if not guild: - return reminders = c.execute("SELECT * FROM Reminders").fetchall() for i in range(len(reminders)): member = discord.utils.get(guild.members, id=reminders[i][0]) @@ -132,7 +133,7 @@ async def check_reminders(self): else: last_date = datetime.datetime.strptime(reminders[i][5], "%Y-%m-%d %H:%M:%S.%f") - if datetime.datetime.now() - last_date > datetime.timedelta(days=self.frequencies[reminders[i][3]]): + if datetime.datetime.now() - last_date > datetime.timedelta(days=FREQUENCIES[reminders[i][3]]): await member.send(f"Reminding you to {reminders[i][2]}! [{i + 1:d}]") c.execute( @@ -448,7 +449,7 @@ async def __remindme_repeating(self, ctx: commands.Context, freq: str = "", *, q freq = freq.strip() quote = quote.strip() - if freq not in self.frequencies.keys(): + if freq not in FREQUENCIES.keys(): await ctx.send( "Please ensure you specify a frequency from the following " "list: `daily`, `weekly`, `monthly`, before your message!" diff --git a/canary/main.py b/canary/main.py index 351284a03..ef4216f15 100755 --- a/canary/main.py +++ b/canary/main.py @@ -53,10 +53,11 @@ @bot.event async def on_ready(): - if bot.config.dev_log_webhook_id and bot.config.dev_log_webhook_token: - webhook_string = " and to the log webhook" - else: - webhook_string = "" + webhook_string = ( + " and to the log webhook" + if bot.config.dev_log_webhook_id and bot.config.dev_log_webhook_token + else "" + ) sys.stdout.write(f"Bot is ready, program output will be written to a " f"log file{webhook_string}.\n") sys.stdout.flush() bot.dev_logger.info(f"Logged in as {bot.user.name} ({bot.user.id})") @@ -68,12 +69,13 @@ async def load(ctx, extension_name: str): """ Load a specific extension. Specify as cogs. """ + try: bot.load_extension(extension_name) except (AttributeError, ImportError) as e: await ctx.send(f"```{type(e).__name__}: {str(e)}\n```") - return + await ctx.send(f"{extension_name} loaded.") @@ -83,6 +85,7 @@ async def unload(ctx: Context, extension_name: str): """ Unload a specific extension. Specify as cogs. """ + try: bot.unload_extension(extension_name) except Exception as e: @@ -155,6 +158,7 @@ async def on_user_update(before, after): def main(): if os.name == "posix": import uvloop + uvloop.install() for extension in startup: From a85d8935eb3b39c05e278194d7c8b2db0f21d192 Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Sat, 3 Sep 2022 22:52:04 -0400 Subject: [PATCH 012/127] hinting --- canary/cogs/mod.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/canary/cogs/mod.py b/canary/cogs/mod.py index 129fb9fc4..07531763f 100644 --- a/canary/cogs/mod.py +++ b/canary/cogs/mod.py @@ -233,11 +233,11 @@ async def verification_purge_utility(self, after: datetime | discord.Message | N @commands.command() @is_moderator() - async def verification_purge(self, ctx, id: int = None): + async def verification_purge(self, ctx, id_: int = None): """ Manually start the purge of pictures in the verification channel. - If a message ID is provided, every pictures after that message will be removed. + If a message ID is provided, every picture after that message will be removed. If no message ID is provided, this will be done for the whole channel (may take time). """ @@ -256,8 +256,8 @@ async def verification_purge(self, ctx, id: int = None): return message = None - if id is not None: - message = await self.verification_channel.fetch_message(id) + if id_ is not None: + message = await self.verification_channel.fetch_message(id_) await self.verification_purge_utility(message) @@ -385,7 +385,7 @@ async def unmute_utility(self, user: discord.Member, ctx: discord.ext.commands.C @commands.command() @is_moderator() - async def mute(self, ctx, user: discord.Member): + async def mute(self, ctx: commands.Context, user: discord.Member): """ Mute a user and create an appeal channel (mod-only). The user's current roles are saved. @@ -395,7 +395,7 @@ async def mute(self, ctx, user: discord.Member): @commands.command() @is_moderator() - async def unmute(self, ctx, user: discord.Member): + async def unmute(self, ctx: commands.Context, user: discord.Member): """ Unmute a user and delete the appeal channel (mod-only). The user's previous roles are restored after confirmation. From d898859b1074726fb922da178f4ffd7be3b5c818 Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Sun, 4 Sep 2022 09:55:44 -0400 Subject: [PATCH 013/127] add aiosqlite and mypy typings for (optional) typechecking --- poetry.lock | 539 ++++++++++++++++++++++++++++++++++++++++++++----- pyproject.toml | 9 +- 2 files changed, 495 insertions(+), 53 deletions(-) diff --git a/poetry.lock b/poetry.lock index 7f981deb4..dd90714fe 100644 --- a/poetry.lock +++ b/poetry.lock @@ -17,6 +17,17 @@ yarl = ">=1.0,<2.0" [package.extras] speedups = ["aiodns", "brotlipy", "cchardet"] +[[package]] +name = "aiosqlite" +version = "0.17.0" +description = "asyncio bridge to the standard sqlite3 module" +category = "main" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +typing_extensions = ">=3.7.2" + [[package]] name = "async-timeout" version = "3.0.1" @@ -25,14 +36,6 @@ category = "main" optional = false python-versions = ">=3.5.3" -[[package]] -name = "atomicwrites" -version = "1.4.1" -description = "Atomic file writes." -category = "dev" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" - [[package]] name = "attrs" version = "22.1.0" @@ -72,7 +75,7 @@ python-versions = ">=3.7" [[package]] name = "black" -version = "22.6.0" +version = "22.8.0" description = "The uncompromising code formatter." category = "dev" optional = false @@ -216,7 +219,7 @@ python-versions = "*" [[package]] name = "hstspreload" -version = "2022.8.1" +version = "2022.9.1" description = "Chromium HSTS Preload list as a Python package" category = "main" optional = false @@ -304,6 +307,24 @@ category = "main" optional = false python-versions = ">=3.5, <4" +[[package]] +name = "mypy" +version = "0.971" +description = "Optional static typing for Python" +category = "dev" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +mypy-extensions = ">=0.4.3" +tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} +typing-extensions = ">=3.10" + +[package.extras] +dmypy = ["psutil (>=4.0)"] +python2 = ["typed-ast (>=1.4.0,<2)"] +reports = ["lxml"] + [[package]] name = "mypy-extensions" version = "0.4.3" @@ -349,14 +370,14 @@ pyparsing = ">=2.0.2,<3.0.5 || >3.0.5" [[package]] name = "pathspec" -version = "0.9.0" +version = "0.10.1" description = "Utility library for gitignore style pattern matching of file paths." category = "dev" optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" +python-versions = ">=3.7" [[package]] -name = "pillow" +name = "Pillow" version = "8.4.0" description = "Python Imaging Library (Fork)" category = "main" @@ -412,7 +433,7 @@ optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" [[package]] -name = "pynacl" +name = "PyNaCl" version = "1.4.0" description = "Python binding to the Networking and Cryptography (NaCl) library" category = "main" @@ -424,7 +445,7 @@ cffi = ">=1.4.1" six = "*" [package.extras] -docs = ["sphinx (>=1.6.5)", "sphinx-rtd-theme"] +docs = ["sphinx (>=1.6.5)", "sphinx_rtd_theme"] tests = ["hypothesis (>=3.27.0)", "pytest (>=3.2.1,!=3.3.0)"] [[package]] @@ -440,14 +461,13 @@ diagrams = ["jinja2", "railroad-diagrams"] [[package]] name = "pytest" -version = "7.1.2" +version = "7.1.3" description = "pytest: simple powerful testing with Python" category = "dev" optional = false python-versions = ">=3.7" [package.dependencies] -atomicwrites = {version = ">=1.0", markers = "sys_platform == \"win32\""} attrs = ">=19.2.0" colorama = {version = "*", markers = "sys_platform == \"win32\""} iniconfig = "*" @@ -522,11 +542,11 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" [[package]] name = "sniffio" -version = "1.2.0" +version = "1.3.0" description = "Sniff out which async library your code is running under" category = "main" optional = false -python-versions = ">=3.5" +python-versions = ">=3.7" [[package]] name = "soupsieve" @@ -538,7 +558,7 @@ python-versions = ">=3.6" [[package]] name = "sympy" -version = "1.11" +version = "1.11.1" description = "Computer algebra system (CAS) in Python" category = "main" optional = false @@ -566,6 +586,57 @@ category = "dev" optional = false python-versions = ">=3.7" +[[package]] +name = "types-beautifulsoup4" +version = "4.11.5" +description = "Typing stubs for beautifulsoup4" +category = "dev" +optional = false +python-versions = "*" + +[[package]] +name = "types-pytz" +version = "2022.2.1.0" +description = "Typing stubs for pytz" +category = "dev" +optional = false +python-versions = "*" + +[[package]] +name = "types-regex" +version = "2022.8.17.0" +description = "Typing stubs for regex" +category = "dev" +optional = false +python-versions = "*" + +[[package]] +name = "types-requests" +version = "2.28.9" +description = "Typing stubs for requests" +category = "dev" +optional = false +python-versions = "*" + +[package.dependencies] +types-urllib3 = "<1.27" + +[[package]] +name = "types-tabulate" +version = "0.8.11" +description = "Typing stubs for tabulate" +category = "dev" +optional = false +python-versions = "*" + +[[package]] +name = "types-urllib3" +version = "1.26.23" +description = "Typing stubs for urllib3" +category = "dev" +optional = false +python-versions = "*" + [[package]] name = "typing-extensions" version = "4.3.0" @@ -636,7 +707,7 @@ websockets = "*" [metadata] lock-version = "1.1" python-versions = "~3.10.0" -content-hash = "1b135d1cedf49f0d2c7a1e974881285a0a377e10a836289d95357053b5250c15" +content-hash = "4e91de797c0006cb53d197e5f0664631aadb1446ca1ce258c75f755baa14d515" [metadata.files] aiohttp = [ @@ -678,32 +749,145 @@ aiohttp = [ {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"}, ] +aiosqlite = [ + {file = "aiosqlite-0.17.0-py3-none-any.whl", hash = "sha256:6c49dc6d3405929b1d08eeccc72306d3677503cc5e5e43771efc1e00232e8231"}, + {file = "aiosqlite-0.17.0.tar.gz", hash = "sha256:f0e6acc24bc4864149267ac82fb46dfb3be4455f99fe21df82609cc6e6baee51"}, +] 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"}, ] -atomicwrites = [] -attrs = [] +attrs = [ + {file = "attrs-22.1.0-py2.py3-none-any.whl", hash = "sha256:86efa402f67bf2df34f51a335487cf46b1ec130d02b8d39fd248abfd30da551c"}, + {file = "attrs-22.1.0.tar.gz", hash = "sha256:29adc2665447e5191d0e7c568fde78b21f9672d344281d0c6e1ab085429b22b6"}, +] beautifulsoup4 = [ {file = "beautifulsoup4-4.10.0-py3-none-any.whl", hash = "sha256:9a315ce70049920ea4572a4055bc4bd700c940521d36fc858205ad4fcde149bf"}, {file = "beautifulsoup4-4.10.0.tar.gz", hash = "sha256:c23ad23c521d818955a4151a67d81580319d4bf548d3d49f4223ae041ff98891"}, ] -bidict = [] -black = [] -certifi = [] -cffi = [] +bidict = [ + {file = "bidict-0.22.0-py3-none-any.whl", hash = "sha256:415126d23a0c81e1a8c584a8fb1f6905ea090c772571803aeee0a2242e8e7ba0"}, + {file = "bidict-0.22.0.tar.gz", hash = "sha256:5c826b3e15e97cc6e615de295756847c282a79b79c5430d3bfc909b1ac9f5bd8"}, +] +black = [ + {file = "black-22.8.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:ce957f1d6b78a8a231b18e0dd2d94a33d2ba738cd88a7fe64f53f659eea49fdd"}, + {file = "black-22.8.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5107ea36b2b61917956d018bd25129baf9ad1125e39324a9b18248d362156a27"}, + {file = "black-22.8.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e8166b7bfe5dcb56d325385bd1d1e0f635f24aae14b3ae437102dedc0c186747"}, + {file = "black-22.8.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd82842bb272297503cbec1a2600b6bfb338dae017186f8f215c8958f8acf869"}, + {file = "black-22.8.0-cp310-cp310-win_amd64.whl", hash = "sha256:d839150f61d09e7217f52917259831fe2b689f5c8e5e32611736351b89bb2a90"}, + {file = "black-22.8.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:a05da0430bd5ced89176db098567973be52ce175a55677436a271102d7eaa3fe"}, + {file = "black-22.8.0-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4a098a69a02596e1f2a58a2a1c8d5a05d5a74461af552b371e82f9fa4ada8342"}, + {file = "black-22.8.0-cp36-cp36m-win_amd64.whl", hash = "sha256:5594efbdc35426e35a7defa1ea1a1cb97c7dbd34c0e49af7fb593a36bd45edab"}, + {file = "black-22.8.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:a983526af1bea1e4cf6768e649990f28ee4f4137266921c2c3cee8116ae42ec3"}, + {file = "black-22.8.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3b2c25f8dea5e8444bdc6788a2f543e1fb01494e144480bc17f806178378005e"}, + {file = "black-22.8.0-cp37-cp37m-win_amd64.whl", hash = "sha256:78dd85caaab7c3153054756b9fe8c611efa63d9e7aecfa33e533060cb14b6d16"}, + {file = "black-22.8.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:cea1b2542d4e2c02c332e83150e41e3ca80dc0fb8de20df3c5e98e242156222c"}, + {file = "black-22.8.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:5b879eb439094751185d1cfdca43023bc6786bd3c60372462b6f051efa6281a5"}, + {file = "black-22.8.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:0a12e4e1353819af41df998b02c6742643cfef58282915f781d0e4dd7a200411"}, + {file = "black-22.8.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c3a73f66b6d5ba7288cd5d6dad9b4c9b43f4e8a4b789a94bf5abfb878c663eb3"}, + {file = "black-22.8.0-cp38-cp38-win_amd64.whl", hash = "sha256:e981e20ec152dfb3e77418fb616077937378b322d7b26aa1ff87717fb18b4875"}, + {file = "black-22.8.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:8ce13ffed7e66dda0da3e0b2eb1bdfc83f5812f66e09aca2b0978593ed636b6c"}, + {file = "black-22.8.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:32a4b17f644fc288c6ee2bafdf5e3b045f4eff84693ac069d87b1a347d861497"}, + {file = "black-22.8.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0ad827325a3a634bae88ae7747db1a395d5ee02cf05d9aa7a9bd77dfb10e940c"}, + {file = "black-22.8.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:53198e28a1fb865e9fe97f88220da2e44df6da82b18833b588b1883b16bb5d41"}, + {file = "black-22.8.0-cp39-cp39-win_amd64.whl", hash = "sha256:bc4d4123830a2d190e9cc42a2e43570f82ace35c3aeb26a512a2102bce5af7ec"}, + {file = "black-22.8.0-py3-none-any.whl", hash = "sha256:d2c21d439b2baf7aa80d6dd4e3659259be64c6f49dfd0f32091063db0e006db4"}, + {file = "black-22.8.0.tar.gz", hash = "sha256:792f7eb540ba9a17e8656538701d3eb1afcb134e3b45b71f20b25c77a8db7e6e"}, +] +certifi = [ + {file = "certifi-2022.6.15-py3-none-any.whl", hash = "sha256:fe86415d55e84719d75f8b69414f6438ac3547d2078ab91b67e779ef69378412"}, + {file = "certifi-2022.6.15.tar.gz", hash = "sha256:84c85a9078b11105f04f3036a9482ae10e4621616db313fe045dd24743a0820d"}, +] +cffi = [ + {file = "cffi-1.15.1-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:a66d3508133af6e8548451b25058d5812812ec3798c886bf38ed24a98216fab2"}, + {file = "cffi-1.15.1-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:470c103ae716238bbe698d67ad020e1db9d9dba34fa5a899b5e21577e6d52ed2"}, + {file = "cffi-1.15.1-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:9ad5db27f9cabae298d151c85cf2bad1d359a1b9c686a275df03385758e2f914"}, + {file = "cffi-1.15.1-cp27-cp27m-win32.whl", hash = "sha256:b3bbeb01c2b273cca1e1e0c5df57f12dce9a4dd331b4fa1635b8bec26350bde3"}, + {file = "cffi-1.15.1-cp27-cp27m-win_amd64.whl", hash = "sha256:e00b098126fd45523dd056d2efba6c5a63b71ffe9f2bbe1a4fe1716e1d0c331e"}, + {file = "cffi-1.15.1-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:d61f4695e6c866a23a21acab0509af1cdfd2c013cf256bbf5b6b5e2695827162"}, + {file = "cffi-1.15.1-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:ed9cb427ba5504c1dc15ede7d516b84757c3e3d7868ccc85121d9310d27eed0b"}, + {file = "cffi-1.15.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:39d39875251ca8f612b6f33e6b1195af86d1b3e60086068be9cc053aa4376e21"}, + {file = "cffi-1.15.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:285d29981935eb726a4399badae8f0ffdff4f5050eaa6d0cfc3f64b857b77185"}, + {file = "cffi-1.15.1-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3eb6971dcff08619f8d91607cfc726518b6fa2a9eba42856be181c6d0d9515fd"}, + {file = "cffi-1.15.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:21157295583fe8943475029ed5abdcf71eb3911894724e360acff1d61c1d54bc"}, + {file = "cffi-1.15.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5635bd9cb9731e6d4a1132a498dd34f764034a8ce60cef4f5319c0541159392f"}, + {file = "cffi-1.15.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2012c72d854c2d03e45d06ae57f40d78e5770d252f195b93f581acf3ba44496e"}, + {file = "cffi-1.15.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd86c085fae2efd48ac91dd7ccffcfc0571387fe1193d33b6394db7ef31fe2a4"}, + {file = "cffi-1.15.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:fa6693661a4c91757f4412306191b6dc88c1703f780c8234035eac011922bc01"}, + {file = "cffi-1.15.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:59c0b02d0a6c384d453fece7566d1c7e6b7bae4fc5874ef2ef46d56776d61c9e"}, + {file = "cffi-1.15.1-cp310-cp310-win32.whl", hash = "sha256:cba9d6b9a7d64d4bd46167096fc9d2f835e25d7e4c121fb2ddfc6528fb0413b2"}, + {file = "cffi-1.15.1-cp310-cp310-win_amd64.whl", hash = "sha256:ce4bcc037df4fc5e3d184794f27bdaab018943698f4ca31630bc7f84a7b69c6d"}, + {file = "cffi-1.15.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3d08afd128ddaa624a48cf2b859afef385b720bb4b43df214f85616922e6a5ac"}, + {file = "cffi-1.15.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3799aecf2e17cf585d977b780ce79ff0dc9b78d799fc694221ce814c2c19db83"}, + {file = "cffi-1.15.1-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a591fe9e525846e4d154205572a029f653ada1a78b93697f3b5a8f1f2bc055b9"}, + {file = "cffi-1.15.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3548db281cd7d2561c9ad9984681c95f7b0e38881201e157833a2342c30d5e8c"}, + {file = "cffi-1.15.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:91fc98adde3d7881af9b59ed0294046f3806221863722ba7d8d120c575314325"}, + {file = "cffi-1.15.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:94411f22c3985acaec6f83c6df553f2dbe17b698cc7f8ae751ff2237d96b9e3c"}, + {file = "cffi-1.15.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:03425bdae262c76aad70202debd780501fabeaca237cdfddc008987c0e0f59ef"}, + {file = "cffi-1.15.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:cc4d65aeeaa04136a12677d3dd0b1c0c94dc43abac5860ab33cceb42b801c1e8"}, + {file = "cffi-1.15.1-cp311-cp311-win32.whl", hash = "sha256:a0f100c8912c114ff53e1202d0078b425bee3649ae34d7b070e9697f93c5d52d"}, + {file = "cffi-1.15.1-cp311-cp311-win_amd64.whl", hash = "sha256:04ed324bda3cda42b9b695d51bb7d54b680b9719cfab04227cdd1e04e5de3104"}, + {file = "cffi-1.15.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50a74364d85fd319352182ef59c5c790484a336f6db772c1a9231f1c3ed0cbd7"}, + {file = "cffi-1.15.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e263d77ee3dd201c3a142934a086a4450861778baaeeb45db4591ef65550b0a6"}, + {file = "cffi-1.15.1-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cec7d9412a9102bdc577382c3929b337320c4c4c4849f2c5cdd14d7368c5562d"}, + {file = "cffi-1.15.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4289fc34b2f5316fbb762d75362931e351941fa95fa18789191b33fc4cf9504a"}, + {file = "cffi-1.15.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:173379135477dc8cac4bc58f45db08ab45d228b3363adb7af79436135d028405"}, + {file = "cffi-1.15.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:6975a3fac6bc83c4a65c9f9fcab9e47019a11d3d2cf7f3c0d03431bf145a941e"}, + {file = "cffi-1.15.1-cp36-cp36m-win32.whl", hash = "sha256:2470043b93ff09bf8fb1d46d1cb756ce6132c54826661a32d4e4d132e1977adf"}, + {file = "cffi-1.15.1-cp36-cp36m-win_amd64.whl", hash = "sha256:30d78fbc8ebf9c92c9b7823ee18eb92f2e6ef79b45ac84db507f52fbe3ec4497"}, + {file = "cffi-1.15.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:198caafb44239b60e252492445da556afafc7d1e3ab7a1fb3f0584ef6d742375"}, + {file = "cffi-1.15.1-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5ef34d190326c3b1f822a5b7a45f6c4535e2f47ed06fec77d3d799c450b2651e"}, + {file = "cffi-1.15.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8102eaf27e1e448db915d08afa8b41d6c7ca7a04b7d73af6514df10a3e74bd82"}, + {file = "cffi-1.15.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5df2768244d19ab7f60546d0c7c63ce1581f7af8b5de3eb3004b9b6fc8a9f84b"}, + {file = "cffi-1.15.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a8c4917bd7ad33e8eb21e9a5bbba979b49d9a97acb3a803092cbc1133e20343c"}, + {file = "cffi-1.15.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0e2642fe3142e4cc4af0799748233ad6da94c62a8bec3a6648bf8ee68b1c7426"}, + {file = "cffi-1.15.1-cp37-cp37m-win32.whl", hash = "sha256:e229a521186c75c8ad9490854fd8bbdd9a0c9aa3a524326b55be83b54d4e0ad9"}, + {file = "cffi-1.15.1-cp37-cp37m-win_amd64.whl", hash = "sha256:a0b71b1b8fbf2b96e41c4d990244165e2c9be83d54962a9a1d118fd8657d2045"}, + {file = "cffi-1.15.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:320dab6e7cb2eacdf0e658569d2575c4dad258c0fcc794f46215e1e39f90f2c3"}, + {file = "cffi-1.15.1-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1e74c6b51a9ed6589199c787bf5f9875612ca4a8a0785fb2d4a84429badaf22a"}, + {file = "cffi-1.15.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a5c84c68147988265e60416b57fc83425a78058853509c1b0629c180094904a5"}, + {file = "cffi-1.15.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3b926aa83d1edb5aa5b427b4053dc420ec295a08e40911296b9eb1b6170f6cca"}, + {file = "cffi-1.15.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:87c450779d0914f2861b8526e035c5e6da0a3199d8f1add1a665e1cbc6fc6d02"}, + {file = "cffi-1.15.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4f2c9f67e9821cad2e5f480bc8d83b8742896f1242dba247911072d4fa94c192"}, + {file = "cffi-1.15.1-cp38-cp38-win32.whl", hash = "sha256:8b7ee99e510d7b66cdb6c593f21c043c248537a32e0bedf02e01e9553a172314"}, + {file = "cffi-1.15.1-cp38-cp38-win_amd64.whl", hash = "sha256:00a9ed42e88df81ffae7a8ab6d9356b371399b91dbdf0c3cb1e84c03a13aceb5"}, + {file = "cffi-1.15.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:54a2db7b78338edd780e7ef7f9f6c442500fb0d41a5a4ea24fff1c929d5af585"}, + {file = "cffi-1.15.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:fcd131dd944808b5bdb38e6f5b53013c5aa4f334c5cad0c72742f6eba4b73db0"}, + {file = "cffi-1.15.1-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7473e861101c9e72452f9bf8acb984947aa1661a7704553a9f6e4baa5ba64415"}, + {file = "cffi-1.15.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6c9a799e985904922a4d207a94eae35c78ebae90e128f0c4e521ce339396be9d"}, + {file = "cffi-1.15.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3bcde07039e586f91b45c88f8583ea7cf7a0770df3a1649627bf598332cb6984"}, + {file = "cffi-1.15.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:33ab79603146aace82c2427da5ca6e58f2b3f2fb5da893ceac0c42218a40be35"}, + {file = "cffi-1.15.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5d598b938678ebf3c67377cdd45e09d431369c3b1a5b331058c338e201f12b27"}, + {file = "cffi-1.15.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:db0fbb9c62743ce59a9ff687eb5f4afbe77e5e8403d6697f7446e5f609976f76"}, + {file = "cffi-1.15.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:98d85c6a2bef81588d9227dde12db8a7f47f639f4a17c9ae08e773aa9c697bf3"}, + {file = "cffi-1.15.1-cp39-cp39-win32.whl", hash = "sha256:40f4774f5a9d4f5e344f31a32b5096977b5d48560c5592e2f3d2c4374bd543ee"}, + {file = "cffi-1.15.1-cp39-cp39-win_amd64.whl", hash = "sha256:70df4e3b545a17496c9b3f41f5115e69a4f2e77e94e1d2a8e1070bc0c38c8a3c"}, + {file = "cffi-1.15.1.tar.gz", hash = "sha256:d400bfb9a37b1351253cb402671cea7e89bdecc294e8016a707f6d1d8ac934f9"}, +] chardet = [ {file = "chardet-3.0.4-py2.py3-none-any.whl", hash = "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691"}, {file = "chardet-3.0.4.tar.gz", hash = "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae"}, ] -charset-normalizer = [] -click = [] -colorama = [] +charset-normalizer = [ + {file = "charset-normalizer-2.1.1.tar.gz", hash = "sha256:5a3d016c7c547f69d6f81fb0db9449ce888b418b5b9952cc5e6e66843e9dd845"}, + {file = "charset_normalizer-2.1.1-py3-none-any.whl", hash = "sha256:83e9a75d1911279afd89352c68b45348559d1fc0506b054b346651b5e7fee29f"}, +] +click = [ + {file = "click-8.1.3-py3-none-any.whl", hash = "sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48"}, + {file = "click-8.1.3.tar.gz", hash = "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e"}, +] +colorama = [ + {file = "colorama-0.4.5-py2.py3-none-any.whl", hash = "sha256:854bf444933e37f5824ae7bfc1e98d5bce2ebe4160d46b5edf346a89358e99da"}, + {file = "colorama-0.4.5.tar.gz", hash = "sha256:e6c6b4334fc50988a639d9b98aa429a0b57da6e17b9a44f0451f930b6967b7a4"}, +] "discord.py" = [ {file = "discord.py-1.6.0-py3-none-any.whl", hash = "sha256:3df148daf6fbcc7ab5b11042368a3cd5f7b730b62f09fb5d3cbceff59bcfbb12"}, {file = "discord.py-1.6.0.tar.gz", hash = "sha256:ba8be99ff1b8c616f7b6dcb700460d0222b29d4c11048e74366954c465fdd05f"}, ] -feedparser = [] +feedparser = [ + {file = "feedparser-6.0.10-py3-none-any.whl", hash = "sha256:79c257d526d13b944e965f6095700587f27388e50ea16fd245babe4dfae7024f"}, + {file = "feedparser-6.0.10.tar.gz", hash = "sha256:27da485f4637ce7163cdeab13a80312b93b7d0c1b775bef4a47629a3110bca51"}, +] googletrans = [ {file = "googletrans-4.0.0rc1.tar.gz", hash = "sha256:74df47b092e2d566522019d149e3f1d75732570ad76eaf8e14aebeffc126c372"}, ] @@ -719,7 +903,10 @@ hpack = [ {file = "hpack-3.0.0-py2.py3-none-any.whl", hash = "sha256:0edd79eda27a53ba5be2dfabf3b15780928a0dff6eb0c60a3d6767720e970c89"}, {file = "hpack-3.0.0.tar.gz", hash = "sha256:8eec9c1f4bfae3408a3f30500261f7e6a65912dc138526ea054f9ad98892e9d2"}, ] -hstspreload = [] +hstspreload = [ + {file = "hstspreload-2022.9.1-py3-none-any.whl", hash = "sha256:22156f0f1335b46e999e3fd70223e86b33332e449e213e59e25f6a3618acae7d"}, + {file = "hstspreload-2022.9.1.tar.gz", hash = "sha256:890e89c1834ea83f39541fdd02be65b990092d256c5a5e1d74df5ab107ddfdaf"}, +] httpcore = [ {file = "httpcore-0.9.1-py3-none-any.whl", hash = "sha256:9850fe97a166a794d7e920590d5ec49a05488884c9fc8b5dba8561effab0c2a0"}, {file = "httpcore-0.9.1.tar.gz", hash = "sha256:ecc5949310d9dae4de64648a4ce529f86df1f232ce23dcfefe737c24d21dfbe9"}, @@ -809,11 +996,65 @@ mutagen = [ {file = "mutagen-1.45.1-py3-none-any.whl", hash = "sha256:9c9f243fcec7f410f138cb12c21c84c64fde4195481a30c9bfb05b5f003adfed"}, {file = "mutagen-1.45.1.tar.gz", hash = "sha256:6397602efb3c2d7baebd2166ed85731ae1c1d475abca22090b7141ff5034b3e1"}, ] +mypy = [ + {file = "mypy-0.971-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:f2899a3cbd394da157194f913a931edfd4be5f274a88041c9dc2d9cdcb1c315c"}, + {file = "mypy-0.971-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:98e02d56ebe93981c41211c05adb630d1d26c14195d04d95e49cd97dbc046dc5"}, + {file = "mypy-0.971-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:19830b7dba7d5356d3e26e2427a2ec91c994cd92d983142cbd025ebe81d69cf3"}, + {file = "mypy-0.971-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:02ef476f6dcb86e6f502ae39a16b93285fef97e7f1ff22932b657d1ef1f28655"}, + {file = "mypy-0.971-cp310-cp310-win_amd64.whl", hash = "sha256:25c5750ba5609a0c7550b73a33deb314ecfb559c350bb050b655505e8aed4103"}, + {file = "mypy-0.971-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:d3348e7eb2eea2472db611486846742d5d52d1290576de99d59edeb7cd4a42ca"}, + {file = "mypy-0.971-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:3fa7a477b9900be9b7dd4bab30a12759e5abe9586574ceb944bc29cddf8f0417"}, + {file = "mypy-0.971-cp36-cp36m-win_amd64.whl", hash = "sha256:2ad53cf9c3adc43cf3bea0a7d01a2f2e86db9fe7596dfecb4496a5dda63cbb09"}, + {file = "mypy-0.971-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:855048b6feb6dfe09d3353466004490b1872887150c5bb5caad7838b57328cc8"}, + {file = "mypy-0.971-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:23488a14a83bca6e54402c2e6435467a4138785df93ec85aeff64c6170077fb0"}, + {file = "mypy-0.971-cp37-cp37m-win_amd64.whl", hash = "sha256:4b21e5b1a70dfb972490035128f305c39bc4bc253f34e96a4adf9127cf943eb2"}, + {file = "mypy-0.971-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:9796a2ba7b4b538649caa5cecd398d873f4022ed2333ffde58eaf604c4d2cb27"}, + {file = "mypy-0.971-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:5a361d92635ad4ada1b1b2d3630fc2f53f2127d51cf2def9db83cba32e47c856"}, + {file = "mypy-0.971-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:b793b899f7cf563b1e7044a5c97361196b938e92f0a4343a5d27966a53d2ec71"}, + {file = "mypy-0.971-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:d1ea5d12c8e2d266b5fb8c7a5d2e9c0219fedfeb493b7ed60cd350322384ac27"}, + {file = "mypy-0.971-cp38-cp38-win_amd64.whl", hash = "sha256:23c7ff43fff4b0df93a186581885c8512bc50fc4d4910e0f838e35d6bb6b5e58"}, + {file = "mypy-0.971-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:1f7656b69974a6933e987ee8ffb951d836272d6c0f81d727f1d0e2696074d9e6"}, + {file = "mypy-0.971-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:d2022bfadb7a5c2ef410d6a7c9763188afdb7f3533f22a0a32be10d571ee4bbe"}, + {file = "mypy-0.971-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ef943c72a786b0f8d90fd76e9b39ce81fb7171172daf84bf43eaf937e9f220a9"}, + {file = "mypy-0.971-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:d744f72eb39f69312bc6c2abf8ff6656973120e2eb3f3ec4f758ed47e414a4bf"}, + {file = "mypy-0.971-cp39-cp39-win_amd64.whl", hash = "sha256:77a514ea15d3007d33a9e2157b0ba9c267496acf12a7f2b9b9f8446337aac5b0"}, + {file = "mypy-0.971-py3-none-any.whl", hash = "sha256:0d054ef16b071149917085f51f89555a576e2618d5d9dd70bd6eea6410af3ac9"}, + {file = "mypy-0.971.tar.gz", hash = "sha256:40b0f21484238269ae6a57200c807d80debc6459d444c0489a102d7c6a75fa56"}, +] mypy-extensions = [ {file = "mypy_extensions-0.4.3-py2.py3-none-any.whl", hash = "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d"}, {file = "mypy_extensions-0.4.3.tar.gz", hash = "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"}, ] -numpy = [] +numpy = [ + {file = "numpy-1.23.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e603ca1fb47b913942f3e660a15e55a9ebca906857edfea476ae5f0fe9b457d5"}, + {file = "numpy-1.23.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:633679a472934b1c20a12ed0c9a6c9eb167fbb4cb89031939bfd03dd9dbc62b8"}, + {file = "numpy-1.23.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:17e5226674f6ea79e14e3b91bfbc153fdf3ac13f5cc54ee7bc8fdbe820a32da0"}, + {file = "numpy-1.23.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bdc02c0235b261925102b1bd586579b7158e9d0d07ecb61148a1799214a4afd5"}, + {file = "numpy-1.23.2-cp310-cp310-win32.whl", hash = "sha256:df28dda02c9328e122661f399f7655cdcbcf22ea42daa3650a26bce08a187450"}, + {file = "numpy-1.23.2-cp310-cp310-win_amd64.whl", hash = "sha256:8ebf7e194b89bc66b78475bd3624d92980fca4e5bb86dda08d677d786fefc414"}, + {file = "numpy-1.23.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:dc76bca1ca98f4b122114435f83f1fcf3c0fe48e4e6f660e07996abf2f53903c"}, + {file = "numpy-1.23.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ecfdd68d334a6b97472ed032b5b37a30d8217c097acfff15e8452c710e775524"}, + {file = "numpy-1.23.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5593f67e66dea4e237f5af998d31a43e447786b2154ba1ad833676c788f37cde"}, + {file = "numpy-1.23.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ac987b35df8c2a2eab495ee206658117e9ce867acf3ccb376a19e83070e69418"}, + {file = "numpy-1.23.2-cp311-cp311-win32.whl", hash = "sha256:d98addfd3c8728ee8b2c49126f3c44c703e2b005d4a95998e2167af176a9e722"}, + {file = "numpy-1.23.2-cp311-cp311-win_amd64.whl", hash = "sha256:8ecb818231afe5f0f568c81f12ce50f2b828ff2b27487520d85eb44c71313b9e"}, + {file = "numpy-1.23.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:909c56c4d4341ec8315291a105169d8aae732cfb4c250fbc375a1efb7a844f8f"}, + {file = "numpy-1.23.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:8247f01c4721479e482cc2f9f7d973f3f47810cbc8c65e38fd1bbd3141cc9842"}, + {file = "numpy-1.23.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b8b97a8a87cadcd3f94659b4ef6ec056261fa1e1c3317f4193ac231d4df70215"}, + {file = "numpy-1.23.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bd5b7ccae24e3d8501ee5563e82febc1771e73bd268eef82a1e8d2b4d556ae66"}, + {file = "numpy-1.23.2-cp38-cp38-win32.whl", hash = "sha256:9b83d48e464f393d46e8dd8171687394d39bc5abfe2978896b77dc2604e8635d"}, + {file = "numpy-1.23.2-cp38-cp38-win_amd64.whl", hash = "sha256:dec198619b7dbd6db58603cd256e092bcadef22a796f778bf87f8592b468441d"}, + {file = "numpy-1.23.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:4f41f5bf20d9a521f8cab3a34557cd77b6f205ab2116651f12959714494268b0"}, + {file = "numpy-1.23.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:806cc25d5c43e240db709875e947076b2826f47c2c340a5a2f36da5bb10c58d6"}, + {file = "numpy-1.23.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8f9d84a24889ebb4c641a9b99e54adb8cab50972f0166a3abc14c3b93163f074"}, + {file = "numpy-1.23.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c403c81bb8ffb1c993d0165a11493fd4bf1353d258f6997b3ee288b0a48fce77"}, + {file = "numpy-1.23.2-cp39-cp39-win32.whl", hash = "sha256:cf8c6aed12a935abf2e290860af8e77b26a042eb7f2582ff83dc7ed5f963340c"}, + {file = "numpy-1.23.2-cp39-cp39-win_amd64.whl", hash = "sha256:5e28cd64624dc2354a349152599e55308eb6ca95a13ce6a7d5679ebff2962913"}, + {file = "numpy-1.23.2-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:806970e69106556d1dd200e26647e9bee5e2b3f1814f9da104a943e8d548ca38"}, + {file = "numpy-1.23.2-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2bd879d3ca4b6f39b7770829f73278b7c5e248c91d538aab1e506c628353e47f"}, + {file = "numpy-1.23.2-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:be6b350dfbc7f708d9d853663772a9310783ea58f6035eec649fb9c4371b5389"}, + {file = "numpy-1.23.2.tar.gz", hash = "sha256:b78d00e48261fbbd04aa0d7427cf78d18401ee0abd89c7559bbf422e5b1c7d01"}, +] opencv-python = [ {file = "opencv-python-4.6.0.66.tar.gz", hash = "sha256:c5bfae41ad4031e66bb10ec4a0a2ffd3e514d092652781e8b1ac98d1b59f1158"}, {file = "opencv_python-4.6.0.66-cp36-abi3-macosx_10_15_x86_64.whl", hash = "sha256:e6e448b62afc95c5b58f97e87ef84699e6607fe5c58730a03301c52496005cae"}, @@ -828,10 +1069,10 @@ packaging = [ {file = "packaging-21.3.tar.gz", hash = "sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb"}, ] pathspec = [ - {file = "pathspec-0.9.0-py2.py3-none-any.whl", hash = "sha256:7d15c4ddb0b5c802d161efc417ec1a2558ea2653c2e8ad9c19098201dc1c993a"}, - {file = "pathspec-0.9.0.tar.gz", hash = "sha256:e564499435a2673d586f6b2130bb5b95f04a3ba06f81b8f895b651a3c76aabb1"}, + {file = "pathspec-0.10.1-py3-none-any.whl", hash = "sha256:46846318467efc4556ccfd27816e004270a9eeeeb4d062ce5e6fc7a87c573f93"}, + {file = "pathspec-0.10.1.tar.gz", hash = "sha256:7ace6161b621d31e7902eb6b5ae148d12cfd23f4a249b9ffb6b9fee12084323d"}, ] -pillow = [ +Pillow = [ {file = "Pillow-8.4.0-cp310-cp310-macosx_10_10_universal2.whl", hash = "sha256:81f8d5c81e483a9442d72d182e1fb6dcb9723f289a57e8030811bac9ea3fef8d"}, {file = "Pillow-8.4.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:3f97cfb1e5a392d75dd8b9fd274d205404729923840ca94ca45a0af57e13dbe6"}, {file = "Pillow-8.4.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eb9fc393f3c61f9054e1ed26e6fe912c7321af2f41ff49d3f83d05bacf22cc78"}, @@ -874,7 +1115,10 @@ pillow = [ {file = "Pillow-8.4.0-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:244cf3b97802c34c41905d22810846802a3329ddcb93ccc432870243211c79fc"}, {file = "Pillow-8.4.0.tar.gz", hash = "sha256:b8e2f83c56e141920c39464b852de3719dfbfb6e3c99a2d8da0edf4fb33176ed"}, ] -platformdirs = [] +platformdirs = [ + {file = "platformdirs-2.5.2-py3-none-any.whl", hash = "sha256:027d8e83a2d7de06bbac4e5ef7e023c02b863d7ea5d079477e722bb41ab25788"}, + {file = "platformdirs-2.5.2.tar.gz", hash = "sha256:58c8abb07dcb441e6ee4b11d8df0ac856038f944ab98b7be6b27b2a3c7feef19"}, +] pluggy = [ {file = "pluggy-1.0.0-py2.py3-none-any.whl", hash = "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"}, {file = "pluggy-1.0.0.tar.gz", hash = "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159"}, @@ -887,8 +1131,39 @@ pycparser = [ {file = "pycparser-2.21-py2.py3-none-any.whl", hash = "sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9"}, {file = "pycparser-2.21.tar.gz", hash = "sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206"}, ] -pycryptodomex = [] -pynacl = [ +pycryptodomex = [ + {file = "pycryptodomex-3.15.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:6f5b6ba8aefd624834bc177a2ac292734996bb030f9d1b388e7504103b6fcddf"}, + {file = "pycryptodomex-3.15.0-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:4540904c09704b6f831059c0dfb38584acb82cb97b0125cd52688c1f1e3fffa6"}, + {file = "pycryptodomex-3.15.0-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:0fadb9f7fa3150577800eef35f62a8a24b9ddf1563ff060d9bd3af22d3952c8c"}, + {file = "pycryptodomex-3.15.0-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:fc9bc7a9b79fe5c750fc81a307052f8daabb709bdaabb0fb18fb136b66b653b5"}, + {file = "pycryptodomex-3.15.0-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:f8be976cec59b11f011f790b88aca67b4ea2bd286578d0bd3e31bcd19afcd3e4"}, + {file = "pycryptodomex-3.15.0-cp27-cp27m-manylinux2014_aarch64.whl", hash = "sha256:78d9621cf0ea35abf2d38fa2ca6d0634eab6c991a78373498ab149953787e5e5"}, + {file = "pycryptodomex-3.15.0-cp27-cp27m-win32.whl", hash = "sha256:b6306403228edde6e289f626a3908a2f7f67c344e712cf7c0a508bab3ad9e381"}, + {file = "pycryptodomex-3.15.0-cp27-cp27m-win_amd64.whl", hash = "sha256:48697790203909fab02a33226fda546604f4e2653f9d47bc5d3eb40879fa7c64"}, + {file = "pycryptodomex-3.15.0-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:18e2ab4813883ae63396c0ffe50b13554b32bb69ec56f0afaf052e7a7ae0d55b"}, + {file = "pycryptodomex-3.15.0-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:3709f13ca3852b0b07fc04a2c03b379189232b24007c466be0f605dd4723e9d4"}, + {file = "pycryptodomex-3.15.0-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:191e73bc84a8064ad1874dba0ebadedd7cce4dedee998549518f2c74a003b2e1"}, + {file = "pycryptodomex-3.15.0-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:e3164a18348bd53c69b4435ebfb4ac8a4076291ffa2a70b54f0c4b80c7834b1d"}, + {file = "pycryptodomex-3.15.0-cp27-cp27mu-manylinux2014_aarch64.whl", hash = "sha256:5676a132169a1c1a3712edf25250722ebc8c9102aa9abd814df063ca8362454f"}, + {file = "pycryptodomex-3.15.0-cp35-abi3-macosx_10_9_x86_64.whl", hash = "sha256:e2b12968522a0358b8917fc7b28865acac002f02f4c4c6020fcb264d76bfd06d"}, + {file = "pycryptodomex-3.15.0-cp35-abi3-manylinux1_i686.whl", hash = "sha256:e47bf8776a7e15576887f04314f5228c6527b99946e6638cf2f16da56d260cab"}, + {file = "pycryptodomex-3.15.0-cp35-abi3-manylinux1_x86_64.whl", hash = "sha256:996e1ba717077ce1e6d4849af7a1426f38b07b3d173b879e27d5e26d2e958beb"}, + {file = "pycryptodomex-3.15.0-cp35-abi3-manylinux2010_i686.whl", hash = "sha256:65204412d0c6a8e3c41e21e93a5e6054a74fea501afa03046a388cf042e3377a"}, + {file = "pycryptodomex-3.15.0-cp35-abi3-manylinux2010_x86_64.whl", hash = "sha256:dd452a5af7014e866206d41751886c9b4bf379a339fdf2dbfc7dd16c0fb4f8e0"}, + {file = "pycryptodomex-3.15.0-cp35-abi3-manylinux2014_aarch64.whl", hash = "sha256:b9279adc16e4b0f590ceff581f53a80179b02cba9056010d733eb4196134a870"}, + {file = "pycryptodomex-3.15.0-cp35-abi3-win32.whl", hash = "sha256:46b3f05f2f7ac7841053da4e0f69616929ca3c42f238c405f6c3df7759ad2780"}, + {file = "pycryptodomex-3.15.0-cp35-abi3-win_amd64.whl", hash = "sha256:8eecdf9cdc7343001d047f951b9cc805cd68cb6cd77b20ea46af5bffc5bd3dfb"}, + {file = "pycryptodomex-3.15.0-pp27-pypy_73-macosx_10_9_x86_64.whl", hash = "sha256:67e1e6a92151023ccdfcfbc0afb3314ad30080793b4c27956ea06ab1fb9bcd8a"}, + {file = "pycryptodomex-3.15.0-pp27-pypy_73-manylinux1_x86_64.whl", hash = "sha256:c4cb9cb492ea7dcdf222a8d19a1d09002798ea516aeae8877245206d27326d86"}, + {file = "pycryptodomex-3.15.0-pp27-pypy_73-manylinux2010_x86_64.whl", hash = "sha256:94c7b60e1f52e1a87715571327baea0733708ab4723346598beca4a3b6879794"}, + {file = "pycryptodomex-3.15.0-pp27-pypy_73-win32.whl", hash = "sha256:04cc393045a8f19dd110c975e30f38ed7ab3faf21ede415ea67afebd95a22380"}, + {file = "pycryptodomex-3.15.0-pp36-pypy36_pp73-macosx_10_9_x86_64.whl", hash = "sha256:0776bfaf2c48154ab54ea45392847c1283d2fcf64e232e85565f858baedfc1fa"}, + {file = "pycryptodomex-3.15.0-pp36-pypy36_pp73-manylinux1_x86_64.whl", hash = "sha256:463119d7d22d0fc04a0f9122e9d3e6121c6648bcb12a052b51bd1eed1b996aa2"}, + {file = "pycryptodomex-3.15.0-pp36-pypy36_pp73-manylinux2010_x86_64.whl", hash = "sha256:a07a64709e366c2041cd5cfbca592b43998bf4df88f7b0ca73dca37071ccf1bd"}, + {file = "pycryptodomex-3.15.0-pp36-pypy36_pp73-win32.whl", hash = "sha256:35a8f7afe1867118330e2e0e0bf759c409e28557fb1fc2fbb1c6c937297dbe9a"}, + {file = "pycryptodomex-3.15.0.tar.gz", hash = "sha256:7341f1bb2dadb0d1a0047f34c3a58208a92423cdbd3244d998e4b28df5eac0ed"}, +] +PyNaCl = [ {file = "PyNaCl-1.4.0-cp27-cp27m-macosx_10_10_x86_64.whl", hash = "sha256:ea6841bc3a76fa4942ce00f3bda7d436fda21e2d91602b9e21b7ca9ecab8f3ff"}, {file = "PyNaCl-1.4.0-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:d452a6746f0a7e11121e64625109bc4468fc3100452817001dbe018bb8b08514"}, {file = "PyNaCl-1.4.0-cp27-cp27m-win32.whl", hash = "sha256:2fe0fc5a2480361dcaf4e6e7cea00e078fcda07ba45f811b167e3f99e8cff574"}, @@ -908,9 +1183,18 @@ pynacl = [ {file = "PyNaCl-1.4.0-cp38-cp38-win_amd64.whl", hash = "sha256:7c6092102219f59ff29788860ccb021e80fffd953920c4a8653889c029b2d420"}, {file = "PyNaCl-1.4.0.tar.gz", hash = "sha256:54e9a2c849c742006516ad56a88f5c74bf2ce92c9f67435187c3c5953b346505"}, ] -pyparsing = [] -pytest = [] -pytz = [] +pyparsing = [ + {file = "pyparsing-3.0.9-py3-none-any.whl", hash = "sha256:5026bae9a10eeaefb61dab2f09052b9f4307d44aee4eda64b309723d8d206bbc"}, + {file = "pyparsing-3.0.9.tar.gz", hash = "sha256:2b020ecf7d21b687f219b71ecad3631f644a47f01403fa1d1036b0c6416d70fb"}, +] +pytest = [ + {file = "pytest-7.1.3-py3-none-any.whl", hash = "sha256:1377bda3466d70b55e3f5cecfa55bb7cfcf219c7964629b967c37cf0bda818b7"}, + {file = "pytest-7.1.3.tar.gz", hash = "sha256:4f365fec2dff9c1162f834d9f18af1ba13062db0c708bf7b946f8a5c76180c39"}, +] +pytz = [ + {file = "pytz-2022.2.1-py2.py3-none-any.whl", hash = "sha256:220f481bdafa09c3955dfbdddb7b57780e9a94f5127e35456a48589b9e0c0197"}, + {file = "pytz-2022.2.1.tar.gz", hash = "sha256:cea221417204f2d1a2aa03ddae3e867921971d0d76f14d87abb4414415bbdcf5"}, +] regex = [ {file = "regex-2021.11.10-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:9345b6f7ee578bad8e475129ed40123d265464c4cfead6c261fd60fc9de00bcf"}, {file = "regex-2021.11.10-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:416c5f1a188c91e3eb41e9c8787288e707f7d2ebe66e0a6563af280d9b68478f"}, @@ -987,7 +1271,10 @@ regex = [ {file = "regex-2021.11.10-cp39-cp39-win_amd64.whl", hash = "sha256:83ee89483672b11f8952b158640d0c0ff02dc43d9cb1b70c1564b49abe92ce29"}, {file = "regex-2021.11.10.tar.gz", hash = "sha256:f341ee2df0999bfdf7a95e448075effe0db212a59387de1a70690e4acb03d4c6"}, ] -requests = [] +requests = [ + {file = "requests-2.28.1-py3-none-any.whl", hash = "sha256:8fefa2a1a1365bf5520aac41836fbee479da67864514bdb821f31ce07ce65349"}, + {file = "requests-2.28.1.tar.gz", hash = "sha256:7c5599b102feddaa661c826c56ab4fee28bfd17f5abca1ebbe3e7f19d7c97983"}, +] rfc3986 = [ {file = "rfc3986-1.5.0-py2.py3-none-any.whl", hash = "sha256:a86d6e1f5b1dc238b218b012df0aa79409667bb209e58da56d0b94704e712a97"}, {file = "rfc3986-1.5.0.tar.gz", hash = "sha256:270aaf10d87d0d4e095063c65bf3ddbc6ee3d0b226328ce21e036f946e421835"}, @@ -1000,18 +1287,57 @@ six = [ {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, ] sniffio = [ - {file = "sniffio-1.2.0-py3-none-any.whl", hash = "sha256:471b71698eac1c2112a40ce2752bb2f4a4814c22a54a3eed3676bc0f5ca9f663"}, - {file = "sniffio-1.2.0.tar.gz", hash = "sha256:c4666eecec1d3f50960c6bdf61ab7bc350648da6c126e3cf6898d8cd4ddcd3de"}, + {file = "sniffio-1.3.0-py3-none-any.whl", hash = "sha256:eecefdce1e5bbfb7ad2eeaabf7c1eeb404d7757c379bd1f7e5cce9d8bf425384"}, + {file = "sniffio-1.3.0.tar.gz", hash = "sha256:e60305c5e5d314f5389259b7f22aaa33d8f7dee49763119234af3755c55b9101"}, +] +soupsieve = [ + {file = "soupsieve-2.3.2.post1-py3-none-any.whl", hash = "sha256:3b2503d3c7084a42b1ebd08116e5f81aadfaea95863628c80a3b774a11b7c759"}, + {file = "soupsieve-2.3.2.post1.tar.gz", hash = "sha256:fc53893b3da2c33de295667a0e19f078c14bf86544af307354de5fcf12a3f30d"}, +] +sympy = [ + {file = "sympy-1.11.1-py3-none-any.whl", hash = "sha256:938f984ee2b1e8eae8a07b884c8b7a1146010040fccddc6539c54f401c8f6fcf"}, + {file = "sympy-1.11.1.tar.gz", hash = "sha256:e32380dce63cb7c0108ed525570092fd45168bdae2faa17e528221ef72e88658"}, ] -soupsieve = [] -sympy = [] tabulate = [ {file = "tabulate-0.8.9-py3-none-any.whl", hash = "sha256:d7c013fe7abbc5e491394e10fa845f8f32fe54f8dc60c6622c6cf482d25d47e4"}, {file = "tabulate-0.8.9.tar.gz", hash = "sha256:eb1d13f25760052e8931f2ef80aaf6045a6cceb47514db8beab24cded16f13a7"}, ] -tomli = [] -typing-extensions = [] -urllib3 = [] +tomli = [ + {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, + {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, +] +types-beautifulsoup4 = [ + {file = "types-beautifulsoup4-4.11.5.tar.gz", hash = "sha256:645963117b0f03f4a44bda36cf3da50cc0e25001e4d19c044d1e323a37c69d73"}, + {file = "types_beautifulsoup4-4.11.5-py3-none-any.whl", hash = "sha256:4b97fce9049e5367ddf45333c8c7224e57d71a3f93162c714be52bf1aa538f0a"}, +] +types-pytz = [ + {file = "types-pytz-2022.2.1.0.tar.gz", hash = "sha256:47cfb19c52b9f75896440541db392fd312a35b279c6307a531db71152ea63e2b"}, + {file = "types_pytz-2022.2.1.0-py3-none-any.whl", hash = "sha256:50ead2254b524a3d4153bc65d00289b66898060d2938e586170dce918dbaf3b3"}, +] +types-regex = [ + {file = "types-regex-2022.8.17.0.tar.gz", hash = "sha256:6c3c2cac6486fba44dd3a8c6fbf780768b8e605455dd80364eea4f647179ec06"}, + {file = "types_regex-2022.8.17.0-py3-none-any.whl", hash = "sha256:73af11d8a146b1e9fbfd0f3eebfa5640ed1786f0d1b1fc8ff72e8882cf0f4133"}, +] +types-requests = [ + {file = "types-requests-2.28.9.tar.gz", hash = "sha256:feaf581bd580497a47fe845d506fa3b91b484cf706ff27774e87659837de9962"}, + {file = "types_requests-2.28.9-py3-none-any.whl", hash = "sha256:86cb66d3de2f53eac5c09adc42cf6547eefbd0c7e1210beca1ee751c35d96083"}, +] +types-tabulate = [ + {file = "types-tabulate-0.8.11.tar.gz", hash = "sha256:17a5fa3b5ca453815778fc9865e8ecd0118b07b2b9faff3e2b06fe448174dd5e"}, + {file = "types_tabulate-0.8.11-py3-none-any.whl", hash = "sha256:af811268241e8fb87b63c052c87d1e329898a93191309d5d42111372232b2e0e"}, +] +types-urllib3 = [ + {file = "types-urllib3-1.26.23.tar.gz", hash = "sha256:b78e819f0e350221d0689a5666162e467ba3910737bafda14b5c2c85e9bb1e56"}, + {file = "types_urllib3-1.26.23-py3-none-any.whl", hash = "sha256:333e675b188a1c1fd980b4b352f9e40572413a4c1ac689c23cd546e96310070a"}, +] +typing-extensions = [ + {file = "typing_extensions-4.3.0-py3-none-any.whl", hash = "sha256:25642c956049920a5aa49edcdd6ab1e06d7e5d467fc00e0506c44ac86fbfca02"}, + {file = "typing_extensions-4.3.0.tar.gz", hash = "sha256:e6d2677a32f47fc7eb2795db1dd15c1f34eff616bcaf2cfb5e997f854fa1c4a6"}, +] +urllib3 = [ + {file = "urllib3-1.26.12-py2.py3-none-any.whl", hash = "sha256:b930dd878d5a8afb066a637fbb35144fe7901e3b209d1cd4f524bd0e9deee997"}, + {file = "urllib3-1.26.12.tar.gz", hash = "sha256:3fa96cf423e6987997fc326ae8df396db2a8b7c667747d47ddd8ecba91f4a74e"}, +] uvloop = [ {file = "uvloop-0.16.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:6224f1401025b748ffecb7a6e2652b17768f30b1a6a3f7b44660e5b5b690b12d"}, {file = "uvloop-0.16.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:30ba9dcbd0965f5c812b7c2112a1ddf60cf904c1c160f398e7eed3a6b82dcd9c"}, @@ -1030,8 +1356,117 @@ uvloop = [ {file = "uvloop-0.16.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1e5f2e2ff51aefe6c19ee98af12b4ae61f5be456cd24396953244a30880ad861"}, {file = "uvloop-0.16.0.tar.gz", hash = "sha256:f74bc20c7b67d1c27c72601c78cf95be99d5c2cdd4514502b4f3eb0933ff1228"}, ] -websockets = [] -yarl = [] +websockets = [ + {file = "websockets-10.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:661f641b44ed315556a2fa630239adfd77bd1b11cb0b9d96ed8ad90b0b1e4978"}, + {file = "websockets-10.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b529fdfa881b69fe563dbd98acce84f3e5a67df13de415e143ef053ff006d500"}, + {file = "websockets-10.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f351c7d7d92f67c0609329ab2735eee0426a03022771b00102816a72715bb00b"}, + {file = "websockets-10.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:379e03422178436af4f3abe0aa8f401aa77ae2487843738542a75faf44a31f0c"}, + {file = "websockets-10.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:e904c0381c014b914136c492c8fa711ca4cced4e9b3d110e5e7d436d0fc289e8"}, + {file = "websockets-10.3-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:e7e6f2d6fd48422071cc8a6f8542016f350b79cc782752de531577d35e9bd677"}, + {file = "websockets-10.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:b9c77f0d1436ea4b4dc089ed8335fa141e6a251a92f75f675056dac4ab47a71e"}, + {file = "websockets-10.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e6fa05a680e35d0fcc1470cb070b10e6fe247af54768f488ed93542e71339d6f"}, + {file = "websockets-10.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:2f94fa3ae454a63ea3a19f73b95deeebc9f02ba2d5617ca16f0bbdae375cda47"}, + {file = "websockets-10.3-cp310-cp310-win32.whl", hash = "sha256:6ed1d6f791eabfd9808afea1e068f5e59418e55721db8b7f3bfc39dc831c42ae"}, + {file = "websockets-10.3-cp310-cp310-win_amd64.whl", hash = "sha256:347974105bbd4ea068106ec65e8e8ebd86f28c19e529d115d89bd8cc5cda3079"}, + {file = "websockets-10.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:fab7c640815812ed5f10fbee7abbf58788d602046b7bb3af9b1ac753a6d5e916"}, + {file = "websockets-10.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:994cdb1942a7a4c2e10098d9162948c9e7b235df755de91ca33f6e0481366fdb"}, + {file = "websockets-10.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:aad5e300ab32036eb3fdc350ad30877210e2f51bceaca83fb7fef4d2b6c72b79"}, + {file = "websockets-10.3-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:e49ea4c1a9543d2bd8a747ff24411509c29e4bdcde05b5b0895e2120cb1a761d"}, + {file = "websockets-10.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:6ea6b300a6bdd782e49922d690e11c3669828fe36fc2471408c58b93b5535a98"}, + {file = "websockets-10.3-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:ef5ce841e102278c1c2e98f043db99d6755b1c58bde475516aef3a008ed7f28e"}, + {file = "websockets-10.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d1655a6fc7aecd333b079d00fb3c8132d18988e47f19740c69303bf02e9883c6"}, + {file = "websockets-10.3-cp37-cp37m-win32.whl", hash = "sha256:83e5ca0d5b743cde3d29fda74ccab37bdd0911f25bd4cdf09ff8b51b7b4f2fa1"}, + {file = "websockets-10.3-cp37-cp37m-win_amd64.whl", hash = "sha256:da4377904a3379f0c1b75a965fff23b28315bcd516d27f99a803720dfebd94d4"}, + {file = "websockets-10.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:a1e15b230c3613e8ea82c9fc6941b2093e8eb939dd794c02754d33980ba81e36"}, + {file = "websockets-10.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:31564a67c3e4005f27815634343df688b25705cccb22bc1db621c781ddc64c69"}, + {file = "websockets-10.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:c8d1d14aa0f600b5be363077b621b1b4d1eb3fbf90af83f9281cda668e6ff7fd"}, + {file = "websockets-10.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8fbd7d77f8aba46d43245e86dd91a8970eac4fb74c473f8e30e9c07581f852b2"}, + {file = "websockets-10.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:210aad7fdd381c52e58777560860c7e6110b6174488ef1d4b681c08b68bf7f8c"}, + {file = "websockets-10.3-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:6075fd24df23133c1b078e08a9b04a3bc40b31a8def4ee0b9f2c8865acce913e"}, + {file = "websockets-10.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:7f6d96fdb0975044fdd7953b35d003b03f9e2bcf85f2d2cf86285ece53e9f991"}, + {file = "websockets-10.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:c7250848ce69559756ad0086a37b82c986cd33c2d344ab87fea596c5ac6d9442"}, + {file = "websockets-10.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:28dd20b938a57c3124028680dc1600c197294da5db4292c76a0b48efb3ed7f76"}, + {file = "websockets-10.3-cp38-cp38-win32.whl", hash = "sha256:54c000abeaff6d8771a4e2cef40900919908ea7b6b6a30eae72752607c6db559"}, + {file = "websockets-10.3-cp38-cp38-win_amd64.whl", hash = "sha256:7ab36e17af592eec5747c68ef2722a74c1a4a70f3772bc661079baf4ae30e40d"}, + {file = "websockets-10.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:a141de3d5a92188234afa61653ed0bbd2dde46ad47b15c3042ffb89548e77094"}, + {file = "websockets-10.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:97bc9d41e69a7521a358f9b8e44871f6cdeb42af31815c17aed36372d4eec667"}, + {file = "websockets-10.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:d6353ba89cfc657a3f5beabb3b69be226adbb5c6c7a66398e17809b0ce3c4731"}, + {file = "websockets-10.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ec2b0ab7edc8cd4b0eb428b38ed89079bdc20c6bdb5f889d353011038caac2f9"}, + {file = "websockets-10.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:85506b3328a9e083cc0a0fb3ba27e33c8db78341b3eb12eb72e8afd166c36680"}, + {file = "websockets-10.3-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:8af75085b4bc0b5c40c4a3c0e113fa95e84c60f4ed6786cbb675aeb1ee128247"}, + {file = "websockets-10.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:07cdc0a5b2549bcfbadb585ad8471ebdc7bdf91e32e34ae3889001c1c106a6af"}, + {file = "websockets-10.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:5b936bf552e4f6357f5727579072ff1e1324717902127ffe60c92d29b67b7be3"}, + {file = "websockets-10.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:e4e08305bfd76ba8edab08dcc6496f40674f44eb9d5e23153efa0a35750337e8"}, + {file = "websockets-10.3-cp39-cp39-win32.whl", hash = "sha256:bb621ec2dbbbe8df78a27dbd9dd7919f9b7d32a73fafcb4d9252fc4637343582"}, + {file = "websockets-10.3-cp39-cp39-win_amd64.whl", hash = "sha256:51695d3b199cd03098ae5b42833006a0f43dc5418d3102972addc593a783bc02"}, + {file = "websockets-10.3-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:907e8247480f287aa9bbc9391bd6de23c906d48af54c8c421df84655eef66af7"}, + {file = "websockets-10.3-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8b1359aba0ff810d5830d5ab8e2c4a02bebf98a60aa0124fb29aa78cfdb8031f"}, + {file = "websockets-10.3-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:93d5ea0b5da8d66d868b32c614d2b52d14304444e39e13a59566d4acb8d6e2e4"}, + {file = "websockets-10.3-pp37-pypy37_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:7934e055fd5cd9dee60f11d16c8d79c4567315824bacb1246d0208a47eca9755"}, + {file = "websockets-10.3-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:3eda1cb7e9da1b22588cefff09f0951771d6ee9fa8dbe66f5ae04cc5f26b2b55"}, + {file = "websockets-10.3.tar.gz", hash = "sha256:fc06cc8073c8e87072138ba1e431300e2d408f054b27047d047b549455066ff4"}, +] +yarl = [ + {file = "yarl-1.8.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:abc06b97407868ef38f3d172762f4069323de52f2b70d133d096a48d72215d28"}, + {file = "yarl-1.8.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:07b21e274de4c637f3e3b7104694e53260b5fc10d51fb3ec5fed1da8e0f754e3"}, + {file = "yarl-1.8.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9de955d98e02fab288c7718662afb33aab64212ecb368c5dc866d9a57bf48880"}, + {file = "yarl-1.8.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7ec362167e2c9fd178f82f252b6d97669d7245695dc057ee182118042026da40"}, + {file = "yarl-1.8.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:20df6ff4089bc86e4a66e3b1380460f864df3dd9dccaf88d6b3385d24405893b"}, + {file = "yarl-1.8.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5999c4662631cb798496535afbd837a102859568adc67d75d2045e31ec3ac497"}, + {file = "yarl-1.8.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ed19b74e81b10b592084a5ad1e70f845f0aacb57577018d31de064e71ffa267a"}, + {file = "yarl-1.8.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1e4808f996ca39a6463f45182e2af2fae55e2560be586d447ce8016f389f626f"}, + {file = "yarl-1.8.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:2d800b9c2eaf0684c08be5f50e52bfa2aa920e7163c2ea43f4f431e829b4f0fd"}, + {file = "yarl-1.8.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:6628d750041550c5d9da50bb40b5cf28a2e63b9388bac10fedd4f19236ef4957"}, + {file = "yarl-1.8.1-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:f5af52738e225fcc526ae64071b7e5342abe03f42e0e8918227b38c9aa711e28"}, + {file = "yarl-1.8.1-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:76577f13333b4fe345c3704811ac7509b31499132ff0181f25ee26619de2c843"}, + {file = "yarl-1.8.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:0c03f456522d1ec815893d85fccb5def01ffaa74c1b16ff30f8aaa03eb21e453"}, + {file = "yarl-1.8.1-cp310-cp310-win32.whl", hash = "sha256:ea30a42dc94d42f2ba4d0f7c0ffb4f4f9baa1b23045910c0c32df9c9902cb272"}, + {file = "yarl-1.8.1-cp310-cp310-win_amd64.whl", hash = "sha256:9130ddf1ae9978abe63808b6b60a897e41fccb834408cde79522feb37fb72fb0"}, + {file = "yarl-1.8.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:0ab5a138211c1c366404d912824bdcf5545ccba5b3ff52c42c4af4cbdc2c5035"}, + {file = "yarl-1.8.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0fb2cb4204ddb456a8e32381f9a90000429489a25f64e817e6ff94879d432fc"}, + {file = "yarl-1.8.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:85cba594433915d5c9a0d14b24cfba0339f57a2fff203a5d4fd070e593307d0b"}, + {file = "yarl-1.8.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1ca7e596c55bd675432b11320b4eacc62310c2145d6801a1f8e9ad160685a231"}, + {file = "yarl-1.8.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d0f77539733e0ec2475ddcd4e26777d08996f8cd55d2aef82ec4d3896687abda"}, + {file = "yarl-1.8.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:29e256649f42771829974e742061c3501cc50cf16e63f91ed8d1bf98242e5507"}, + {file = "yarl-1.8.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:7fce6cbc6c170ede0221cc8c91b285f7f3c8b9fe28283b51885ff621bbe0f8ee"}, + {file = "yarl-1.8.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:59ddd85a1214862ce7c7c66457f05543b6a275b70a65de366030d56159a979f0"}, + {file = "yarl-1.8.1-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:12768232751689c1a89b0376a96a32bc7633c08da45ad985d0c49ede691f5c0d"}, + {file = "yarl-1.8.1-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:b19255dde4b4f4c32e012038f2c169bb72e7f081552bea4641cab4d88bc409dd"}, + {file = "yarl-1.8.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:6c8148e0b52bf9535c40c48faebb00cb294ee577ca069d21bd5c48d302a83780"}, + {file = "yarl-1.8.1-cp37-cp37m-win32.whl", hash = "sha256:de839c3a1826a909fdbfe05f6fe2167c4ab033f1133757b5936efe2f84904c07"}, + {file = "yarl-1.8.1-cp37-cp37m-win_amd64.whl", hash = "sha256:dd032e8422a52e5a4860e062eb84ac94ea08861d334a4bcaf142a63ce8ad4802"}, + {file = "yarl-1.8.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:19cd801d6f983918a3f3a39f3a45b553c015c5aac92ccd1fac619bd74beece4a"}, + {file = "yarl-1.8.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6347f1a58e658b97b0a0d1ff7658a03cb79bdbda0331603bed24dd7054a6dea1"}, + {file = "yarl-1.8.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7c0da7e44d0c9108d8b98469338705e07f4bb7dab96dbd8fa4e91b337db42548"}, + {file = "yarl-1.8.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5587bba41399854703212b87071c6d8638fa6e61656385875f8c6dff92b2e461"}, + {file = "yarl-1.8.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:31a9a04ecccd6b03e2b0e12e82131f1488dea5555a13a4d32f064e22a6003cfe"}, + {file = "yarl-1.8.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:205904cffd69ae972a1707a1bd3ea7cded594b1d773a0ce66714edf17833cdae"}, + {file = "yarl-1.8.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ea513a25976d21733bff523e0ca836ef1679630ef4ad22d46987d04b372d57fc"}, + {file = "yarl-1.8.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d0b51530877d3ad7a8d47b2fff0c8df3b8f3b8deddf057379ba50b13df2a5eae"}, + {file = "yarl-1.8.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:d2b8f245dad9e331540c350285910b20dd913dc86d4ee410c11d48523c4fd546"}, + {file = "yarl-1.8.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:ab2a60d57ca88e1d4ca34a10e9fb4ab2ac5ad315543351de3a612bbb0560bead"}, + {file = "yarl-1.8.1-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:449c957ffc6bc2309e1fbe67ab7d2c1efca89d3f4912baeb8ead207bb3cc1cd4"}, + {file = "yarl-1.8.1-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:a165442348c211b5dea67c0206fc61366212d7082ba8118c8c5c1c853ea4d82e"}, + {file = "yarl-1.8.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:b3ded839a5c5608eec8b6f9ae9a62cb22cd037ea97c627f38ae0841a48f09eae"}, + {file = "yarl-1.8.1-cp38-cp38-win32.whl", hash = "sha256:c1445a0c562ed561d06d8cbc5c8916c6008a31c60bc3655cdd2de1d3bf5174a0"}, + {file = "yarl-1.8.1-cp38-cp38-win_amd64.whl", hash = "sha256:56c11efb0a89700987d05597b08a1efcd78d74c52febe530126785e1b1a285f4"}, + {file = "yarl-1.8.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:e80ed5a9939ceb6fda42811542f31c8602be336b1fb977bccb012e83da7e4936"}, + {file = "yarl-1.8.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6afb336e23a793cd3b6476c30f030a0d4c7539cd81649683b5e0c1b0ab0bf350"}, + {file = "yarl-1.8.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4c322cbaa4ed78a8aac89b2174a6df398faf50e5fc12c4c191c40c59d5e28357"}, + {file = "yarl-1.8.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fae37373155f5ef9b403ab48af5136ae9851151f7aacd9926251ab26b953118b"}, + {file = "yarl-1.8.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5395da939ffa959974577eff2cbfc24b004a2fb6c346918f39966a5786874e54"}, + {file = "yarl-1.8.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:076eede537ab978b605f41db79a56cad2e7efeea2aa6e0fa8f05a26c24a034fb"}, + {file = "yarl-1.8.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3d1a50e461615747dd93c099f297c1994d472b0f4d2db8a64e55b1edf704ec1c"}, + {file = "yarl-1.8.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7de89c8456525650ffa2bb56a3eee6af891e98f498babd43ae307bd42dca98f6"}, + {file = "yarl-1.8.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:4a88510731cd8d4befaba5fbd734a7dd914de5ab8132a5b3dde0bbd6c9476c64"}, + {file = "yarl-1.8.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:2d93a049d29df172f48bcb09acf9226318e712ce67374f893b460b42cc1380ae"}, + {file = "yarl-1.8.1-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:21ac44b763e0eec15746a3d440f5e09ad2ecc8b5f6dcd3ea8cb4773d6d4703e3"}, + {file = "yarl-1.8.1-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:d0272228fabe78ce00a3365ffffd6f643f57a91043e119c289aaba202f4095b0"}, + {file = "yarl-1.8.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:99449cd5366fe4608e7226c6cae80873296dfa0cde45d9b498fefa1de315a09e"}, + {file = "yarl-1.8.1-cp39-cp39-win32.whl", hash = "sha256:8b0af1cf36b93cee99a31a545fe91d08223e64390c5ecc5e94c39511832a4bb6"}, + {file = "yarl-1.8.1-cp39-cp39-win_amd64.whl", hash = "sha256:de49d77e968de6626ba7ef4472323f9d2e5a56c1d85b7c0e2a190b2173d3b9be"}, + {file = "yarl-1.8.1.tar.gz", hash = "sha256:af887845b8c2e060eb5605ff72b6f2dd2aab7a761379373fd89d314f4752abbf"}, +] yt-dlp = [ {file = "yt-dlp-2021.12.27.tar.gz", hash = "sha256:2244df3759751487e796b23b67216bee98e70832a3a43c2526b0b0e0bbfbcb5b"}, {file = "yt_dlp-2021.12.27-py2.py3-none-any.whl", hash = "sha256:bb46898a175d149c9c6bb2846056590d297aa4eafad8487c3e1315d2c6090896"}, diff --git a/pyproject.toml b/pyproject.toml index a0f375bc4..669240f99 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -32,10 +32,17 @@ yt-dlp = "^2021.12.27" Pillow = "^8.3.2" uvloop = {version="0.16.0", markers = "sys_platform == 'linux' or sys_platform == 'darwin'"} bidict = "^0.22.0" +aiosqlite = "^0.17.0" [tool.poetry.dev-dependencies] -pytest = "^7.0.1" +pytest = "^7.0.71" black = "^22.6" +mypy = ">=0.971,<0.972" +types-beautifulsoup4 = "^4.11.5" +types-regex = "^2022.8.17.0" +types-requests = "^2.28.9" +types-pytz = "^2022.2.1.0" +types-tabulate = "^0.8.11" [tool.black] line-length = 120 From 6a1a6eab86abbf35e44bdee8f0d785d7a55f38a8 Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Sun, 4 Sep 2022 09:57:32 -0400 Subject: [PATCH 014/127] relocate config & remove configurable schema location --- .dockerignore | 2 +- {config => canary/config}/__init__.py | 0 {config => canary/config}/config.ini | 1 - {config => canary/config}/parser.py | 12 ++++++------ 4 files changed, 7 insertions(+), 8 deletions(-) rename {config => canary/config}/__init__.py (100%) rename {config => canary/config}/config.ini (99%) rename {config => canary/config}/parser.py (97%) diff --git a/.dockerignore b/.dockerignore index 71de48aef..4c513943f 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,4 +1,4 @@ -config/config.ini +canary/config/config.ini env/ tests/ venv/ diff --git a/config/__init__.py b/canary/config/__init__.py similarity index 100% rename from config/__init__.py rename to canary/config/__init__.py diff --git a/config/config.ini b/canary/config/config.ini similarity index 99% rename from config/config.ini rename to canary/config/config.ini index 4923b4217..934a93ac2 100644 --- a/config/config.ini +++ b/canary/config/config.ini @@ -64,7 +64,6 @@ ModLogWebhookID = ModLogWebhookToken = [DB] -Schema = ./Martlet.schema Path = ./data/runtime/Martlet.db [Greetings] diff --git a/config/parser.py b/canary/config/parser.py similarity index 97% rename from config/parser.py rename to canary/config/parser.py index 58611bd1f..2c9785374 100644 --- a/config/parser.py +++ b/canary/config/parser.py @@ -17,9 +17,10 @@ import codecs import configparser - +import decimal import logging -import decimal # Currency + +from pathlib import Path LOG_LEVELS = { "critical": logging.CRITICAL, @@ -32,11 +33,11 @@ class Parser: - def __init__(self): - self.configfile = "./config/config.ini" + CONFIG_PATH = Path(__file__).parent / "config.ini" + def __init__(self): config = configparser.ConfigParser() - config.read_file(codecs.open(self.configfile, "r", "utf-8-sig")) + config.read_file(codecs.open(str(Parser.CONFIG_PATH), "r", "utf-8-sig")) # Discord token self.discord_key = config["Discord"]["Key"] @@ -101,7 +102,6 @@ def __init__(self): # DB configuration self.db_path = config["DB"]["Path"] - self.db_schema_path = config["DB"]["Schema"] # Helpers configuration self.course_tpl = config["Helpers"]["CourseTemplate"] From 745c20cf501ca8e754900f1fb97558e507012160 Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Sun, 4 Sep 2022 09:57:46 -0400 Subject: [PATCH 015/127] oop --- Martlet.schema | 104 ------------------------------------------------- 1 file changed, 104 deletions(-) delete mode 100644 Martlet.schema diff --git a/Martlet.schema b/Martlet.schema deleted file mode 100644 index 96c146a67..000000000 --- a/Martlet.schema +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright (C) idoneam (2016-2022) - * - * This file is part of Canary - * - * Canary is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Canary is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Canary. If not, see . - */ - - -CREATE TABLE IF NOT EXISTS "Quotes" ( - `ID` INTEGER, - `Name` TEXT, - `Quote` TEXT, - `Date` TEXT -); - -CREATE TABLE IF NOT EXISTS `Members` ( - `ID` INTEGER PRIMARY KEY, - `Name` TEXT -); - -CREATE TABLE IF NOT EXISTS 'Reminders' ( - 'ID' INTEGER, - 'Name' TEXT, - 'Reminder' TEXT, - 'Frequency' TEXT, - 'Date' TEXT, - 'LastReminder' TEXT -); - -CREATE TABLE IF NOT EXISTS `BankTransactions` ( - `TransactionID` INTEGER PRIMARY KEY, - `UserID` INTEGER, - `Amount` INTEGER, - `Action` TEXT, -- actions are separated from other metadata since they're mandatory - `Metadata` TEXT, - `Date` INTEGER, - - FOREIGN KEY(`UserID`) REFERENCES `Members`(`ID`) -); - -CREATE TABLE IF NOT EXISTS `Reactions` ( - `ReacterID` INTEGER, - `ReacteeID` INTEGER, - `ReactionName` TEXT, - `MessageID` INTEGER, - - FOREIGN KEY(`ReacterID`) REFERENCES `Members`(`ID`), - FOREIGN KEY(`ReacteeID`) REFERENCES `Members`(`ID`) -); -CREATE UNIQUE INDEX IF NOT EXISTS `unique_reaction` ON `Reactions` (`ReacterID`, `ReacteeID`, `ReactionName`, `MessageID`); - -CREATE TABLE IF NOT EXISTS `CustomReactions` ( - `CustomReactionID` INTEGER PRIMARY KEY, - `Prompt` TEXT, - `Response` TEXT, - `UserID` INTEGER, - `DeletePrompt` INTEGER, - `Anywhere` INTEGER, - `DM` INTEGER, - `Proposal` INTEGER -); - --- Used for when users leave/return -CREATE TABLE IF NOT EXISTS `PreviousRoles` ( - `ID` INTEGER UNIQUE, - `Roles` TEXT -- space-separated list of role IDs -); - --- Used for when users are muted; stores the ID of the Appeal Channel created for that user --- and stores old roles akin to the way PreviousRoles does it -CREATE TABLE IF NOT EXISTS `MutedUsers` ( - `UserID` INTEGER UNIQUE, - `AppealChannelID` INTEGER UNIQUE, - `Roles` TEXT, -- space-separated list of role IDs - `Date` INTEGER -); - -CREATE TABLE IF NOT EXISTS `Settings` ( - `Key` TEXT PRIMARY KEY, - `Value` TEXT -); - -CREATE TABLE IF NOT EXISTS `BannerSubmissions` ( - `UserID` INTEGER UNIQUE, - `PreviewMessageID` INTEGER, - `ConvertedMessageID` INTEGER -); - -CREATE TABLE IF NOT EXISTS `SpoilerizedMessages` ( - `MessageID` INTEGER UNIQUE, - `UserID` INTEGER -); From 2b1efccbbe4a2cd767bcceca91db6589d036d552 Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Sun, 4 Sep 2022 10:00:02 -0400 Subject: [PATCH 016/127] add new base cog which factors out some common functionality use it in basic cogs that dont need additional changes --- canary/cogs/base_cog.py | 50 +++++++++++++++++++++++++++++++++++++++++ canary/cogs/info.py | 8 ++----- canary/cogs/memes.py | 7 ++---- canary/cogs/roles.py | 6 +++-- 4 files changed, 58 insertions(+), 13 deletions(-) create mode 100644 canary/cogs/base_cog.py diff --git a/canary/cogs/base_cog.py b/canary/cogs/base_cog.py new file mode 100644 index 000000000..f857b94c2 --- /dev/null +++ b/canary/cogs/base_cog.py @@ -0,0 +1,50 @@ +import aiosqlite +import contextlib +import discord +import os + +from discord.ext import commands +from typing import Iterable + +from ..bot import Canary + +__all__ = [ + "CanaryCog", +] + + +class CanaryCog(commands.Cog): + def __init__(self, bot: Canary): + self.bot: Canary = bot + self.guild: discord.Guild | None = None + + @commands.Cog.listener() + async def on_ready(self): + self.guild = self.bot.get_guild(self.bot.config.server_id) + if not os.path.exists("./tmp/"): + os.mkdir("./tmp/", mode=0o755) + + @contextlib.asynccontextmanager + async def db(self) -> aiosqlite.Connection: + async with self.bot.db() as conn: + yield conn + + async def get_settings_key(self, key: str) -> str | None: + db: aiosqlite.Connection + async with self.db() as db: + c: aiosqlite.Cursor + async with db.execute("SELECT Value FROM Settings WHERE Key = ?", (key,)) as c: + fetched = await c.fetchone() + return fetched[0] if fetched is not None else None + + async def set_settings_key(self, key: str, value: str, pre_commit: Iterable | None = None) -> None: + db: aiosqlite.Connection + async with self.db() as db: + c: aiosqlite.Cursor + await db.execute("REPLACE INTO Settings VALUES (?, ?)", (key, value)) + + if pre_commit: + for s in pre_commit: + await db.execute(s) + + await db.commit() diff --git a/canary/cogs/info.py b/canary/cogs/info.py index 1c760aae0..798303c74 100644 --- a/canary/cogs/info.py +++ b/canary/cogs/info.py @@ -15,16 +15,12 @@ # You should have received a copy of the GNU General Public License # along with Canary. If not, see . -# discord-py requirements -import discord import subprocess from discord.ext import commands +from .base_cog import CanaryCog -class Info(commands.Cog): - def __init__(self, bot): - self.bot = bot - +class Info(CanaryCog): @commands.command() async def version(self, ctx): # TODO: use asyncio.create_subprocess_shell diff --git a/canary/cogs/memes.py b/canary/cogs/memes.py index ee4a457a8..e46d4ee9a 100644 --- a/canary/cogs/memes.py +++ b/canary/cogs/memes.py @@ -22,14 +22,11 @@ # Other utilities import aiohttp import random -from ..bot import Canary +from .base_cog import CanaryCog from .utils.auto_incorrect import auto_incorrect -class Memes(commands.Cog): - def __init__(self, bot: Canary): - self.bot: Canary = bot - +class Memes(CanaryCog): @commands.command() async def bac(self, ctx, *, input_str: str = None): """ diff --git a/canary/cogs/roles.py b/canary/cogs/roles.py index 37ee8f5dd..9692f6787 100644 --- a/canary/cogs/roles.py +++ b/canary/cogs/roles.py @@ -23,6 +23,7 @@ from typing import Optional, Tuple from ..bot import Canary +from .base_cog import CanaryCog from .utils.checks import is_moderator from .utils.paginator import Pages from .utils.role_restoration import save_existing_roles, fetch_saved_roles, is_in_muted_table, role_restoring_page @@ -33,7 +34,7 @@ class RoleTransaction(Enum): REMOVE = "remove" -class Roles(commands.Cog): +class Roles(CanaryCog): ALL_CATEGORIES = ( "pronouns", "fields", @@ -51,7 +52,8 @@ class Roles(commands.Cog): } def __init__(self, bot: Canary): - self.bot: Canary = bot + super().__init__(bot) + self.roles = self.bot.config.roles self.mod_role = self.bot.config.moderator_role From 74452c0fd8f82d8180f4cff83fa44e3d1db0a104 Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Sun, 4 Sep 2022 10:00:13 -0400 Subject: [PATCH 017/127] relocate schema --- canary/Martlet.schema | 104 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100644 canary/Martlet.schema diff --git a/canary/Martlet.schema b/canary/Martlet.schema new file mode 100644 index 000000000..96c146a67 --- /dev/null +++ b/canary/Martlet.schema @@ -0,0 +1,104 @@ +/* + * Copyright (C) idoneam (2016-2022) + * + * This file is part of Canary + * + * Canary is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Canary is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Canary. If not, see . + */ + + +CREATE TABLE IF NOT EXISTS "Quotes" ( + `ID` INTEGER, + `Name` TEXT, + `Quote` TEXT, + `Date` TEXT +); + +CREATE TABLE IF NOT EXISTS `Members` ( + `ID` INTEGER PRIMARY KEY, + `Name` TEXT +); + +CREATE TABLE IF NOT EXISTS 'Reminders' ( + 'ID' INTEGER, + 'Name' TEXT, + 'Reminder' TEXT, + 'Frequency' TEXT, + 'Date' TEXT, + 'LastReminder' TEXT +); + +CREATE TABLE IF NOT EXISTS `BankTransactions` ( + `TransactionID` INTEGER PRIMARY KEY, + `UserID` INTEGER, + `Amount` INTEGER, + `Action` TEXT, -- actions are separated from other metadata since they're mandatory + `Metadata` TEXT, + `Date` INTEGER, + + FOREIGN KEY(`UserID`) REFERENCES `Members`(`ID`) +); + +CREATE TABLE IF NOT EXISTS `Reactions` ( + `ReacterID` INTEGER, + `ReacteeID` INTEGER, + `ReactionName` TEXT, + `MessageID` INTEGER, + + FOREIGN KEY(`ReacterID`) REFERENCES `Members`(`ID`), + FOREIGN KEY(`ReacteeID`) REFERENCES `Members`(`ID`) +); +CREATE UNIQUE INDEX IF NOT EXISTS `unique_reaction` ON `Reactions` (`ReacterID`, `ReacteeID`, `ReactionName`, `MessageID`); + +CREATE TABLE IF NOT EXISTS `CustomReactions` ( + `CustomReactionID` INTEGER PRIMARY KEY, + `Prompt` TEXT, + `Response` TEXT, + `UserID` INTEGER, + `DeletePrompt` INTEGER, + `Anywhere` INTEGER, + `DM` INTEGER, + `Proposal` INTEGER +); + +-- Used for when users leave/return +CREATE TABLE IF NOT EXISTS `PreviousRoles` ( + `ID` INTEGER UNIQUE, + `Roles` TEXT -- space-separated list of role IDs +); + +-- Used for when users are muted; stores the ID of the Appeal Channel created for that user +-- and stores old roles akin to the way PreviousRoles does it +CREATE TABLE IF NOT EXISTS `MutedUsers` ( + `UserID` INTEGER UNIQUE, + `AppealChannelID` INTEGER UNIQUE, + `Roles` TEXT, -- space-separated list of role IDs + `Date` INTEGER +); + +CREATE TABLE IF NOT EXISTS `Settings` ( + `Key` TEXT PRIMARY KEY, + `Value` TEXT +); + +CREATE TABLE IF NOT EXISTS `BannerSubmissions` ( + `UserID` INTEGER UNIQUE, + `PreviewMessageID` INTEGER, + `ConvertedMessageID` INTEGER +); + +CREATE TABLE IF NOT EXISTS `SpoilerizedMessages` ( + `MessageID` INTEGER UNIQUE, + `UserID` INTEGER +); From 1baa45514ba93fe2f76f0be96c3e7999e029f589 Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Sun, 4 Sep 2022 10:00:22 -0400 Subject: [PATCH 018/127] add package manifest --- MANIFEST.in | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 MANIFEST.in diff --git a/MANIFEST.in b/MANIFEST.in new file mode 100644 index 000000000..fb991c226 --- /dev/null +++ b/MANIFEST.in @@ -0,0 +1,2 @@ +include canary/config/config.ini +include canary/Martlet.schema From fd957ed0343c6055e2f20586f5eaa2822d9a726a Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Sun, 4 Sep 2022 10:00:39 -0400 Subject: [PATCH 019/127] docs: update info on config --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 4562581db..843111945 100644 --- a/README.md +++ b/README.md @@ -173,7 +173,7 @@ If you installed all dev dependencies, you can run tests with `poetry run pytest ## Running the bot Run `poetry run canary` in your shell. Ensure that your Discord token is set in the `config.ini` file within the -`config` directory. +`canary/config` directory. ### Docker Container @@ -206,7 +206,7 @@ mkdir -f runtime-data # Run the container docker run -d \ - -v $(pwd)/config.ini:/canary/config/config.ini:ro \ + -v $(pwd)/config.ini:/canary/canary/config/config.ini:ro \ -v $(pwd)/runtime-data:/canary/data/runtime \ canary:latest ``` From 413491faf484f4caf3a34680ddec9613facf5d7f Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Sun, 4 Sep 2022 10:01:07 -0400 Subject: [PATCH 020/127] rewrite bot.py with async database + some code style changes --- canary/bot.py | 44 ++++++++++++++++++++++++++++---------------- 1 file changed, 28 insertions(+), 16 deletions(-) diff --git a/canary/bot.py b/canary/bot.py index e57ea63d3..1ead9a424 100644 --- a/canary/bot.py +++ b/canary/bot.py @@ -15,13 +15,15 @@ # You should have received a copy of the GNU General Public License # along with Canary. If not, see . -from discord.ext import commands - -from config import parser +import aiosqlite +import contextlib import logging -import sqlite3 import traceback + +from canary.config import parser from discord import Webhook, RequestsWebhookAdapter, Intents +from discord.ext import commands +from pathlib import Path __all__ = ["Canary", "bot", "developer_role", "moderator_role", "muted_role"] @@ -52,10 +54,7 @@ class _WebhookHandler(logging.Handler): def __init__(self, webhook_id, webhook_token, username=None): - if not username: - self.username = "Bot Logs" - else: - self.username = username + self.username = username or "Bot Logs" logging.Handler.__init__(self) self.webhook = Webhook.partial(webhook_id, webhook_token, adapter=RequestsWebhookAdapter()) @@ -82,26 +81,39 @@ def emit(self, record): class Canary(commands.Bot): + SCHEMA_PATH = Path(__file__).parent / "Martlet.schema" + def __init__(self, *args, **kwargs): super().__init__(command_prefix, *args, **kwargs) self.logger = _logger self.dev_logger = _dev_logger self.mod_logger = _mod_logger self.config = _parser - self._start_database() - def _start_database(self): + async def start(self, *args, **kwargs): # TODO: discordpy 2.0: use setup_hook for database setup + await self._start_database() + await super().start(*args, **kwargs) + + @contextlib.asynccontextmanager + async def db(self) -> aiosqlite.Connection: + conn: aiosqlite.Connection + async with aiosqlite.connect(self.config.db_path) as conn: + await conn.execute("PRAGMA foreign_keys = ON") + yield conn + + async def _start_database(self): if not self.config.db_path: self.dev_logger.warning("No path to database configuration file") return self.dev_logger.debug("Initializing SQLite database") - conn = sqlite3.connect(self.config.db_path) - c = conn.cursor() - with open(self.config.db_schema_path) as fp: - c.executescript(fp.read()) - conn.commit() - conn.close() + + db: aiosqlite.Connection + async with self.db() as db: + with open(Canary.SCHEMA_PATH) as fp: + await db.executescript(fp.read()) + await db.commit() + self.dev_logger.debug("Database is ready") def log_traceback(self, exception): From ac22e956e5ea1ebcf2e2183541a07d262c8d7d5f Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Sun, 4 Sep 2022 10:01:25 -0400 Subject: [PATCH 021/127] rewrite main.py with aiosqlite and code style changes --- canary/main.py | 29 +++++++++++++---------------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/canary/main.py b/canary/main.py index ef4216f15..d5758ba2e 100755 --- a/canary/main.py +++ b/canary/main.py @@ -16,10 +16,9 @@ # # You should have received a copy of the GNU General Public License # along with Canary. If not, see . - +import aiosqlite import discord import os -import sqlite3 import sys from datetime import datetime @@ -30,7 +29,7 @@ from canary.cogs.utils.checks import is_developer, is_moderator startup = [ - f"cogs.{c}" + f"canary.cogs.{c}" for c in ( "banner", "currency", @@ -54,9 +53,7 @@ @bot.event async def on_ready(): webhook_string = ( - " and to the log webhook" - if bot.config.dev_log_webhook_id and bot.config.dev_log_webhook_token - else "" + " and to the log webhook" if bot.config.dev_log_webhook_id and bot.config.dev_log_webhook_token else "" ) sys.stdout.write(f"Bot is ready, program output will be written to a " f"log file{webhook_string}.\n") sys.stdout.flush() @@ -134,11 +131,11 @@ async def backup(ctx: Context): async def on_member_join(member): member_id = member.id name = str(member) - conn = sqlite3.connect(bot.config.db_path) - c = conn.cursor() - c.execute("INSERT OR REPLACE INTO Members VALUES (?,?)", (member_id, name)) - conn.commit() - conn.close() + + db: aiosqlite.Connection + async with bot.db() as db: + await db.execute("INSERT OR REPLACE INTO Members VALUES (?,?)", (member_id, name)) + await db.commit() @bot.listen() @@ -148,11 +145,11 @@ async def on_user_update(before, after): user_id = after.id new_name = str(after) - conn = sqlite3.connect(bot.config.db_path) - c = conn.cursor() - c.execute("INSERT OR REPLACE INTO Members VALUES (?,?)", (user_id, new_name)) - conn.commit() - conn.close() + + db: aiosqlite.Connection + async with bot.db() as db: + await db.execute("INSERT OR REPLACE INTO Members VALUES (?,?)", (user_id, new_name)) + await db.commit() def main(): From e290cb062a34d611758b6976b02a1703f4894615 Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Sun, 4 Sep 2022 10:02:34 -0400 Subject: [PATCH 022/127] rewrite banner cog with aiosqlite and code style changes --- canary/cogs/banner.py | 143 +++++++++++++++++++----------------------- 1 file changed, 66 insertions(+), 77 deletions(-) diff --git a/canary/cogs/banner.py b/canary/cogs/banner.py index bdb50c9be..a3a6ffc29 100644 --- a/canary/cogs/banner.py +++ b/canary/cogs/banner.py @@ -20,23 +20,23 @@ from discord import utils # Other utilities +import aiosqlite import asyncio import datetime import json -import sqlite3 import requests from io import BytesIO from PIL import Image, UnidentifiedImageError, ImageSequence from ..bot import Canary +from .base_cog import CanaryCog from .utils.checks import is_moderator -class Banner(commands.Cog): +class Banner(CanaryCog): # Written by @le-potate def __init__(self, bot: Canary): - self.bot = bot - self.guild: discord.Guild | None = None + super().__init__(bot) self.banner_of_the_week_channel: discord.TextChannel | None = None self.banner_submissions_channel: discord.TextChannel | None = None @@ -51,9 +51,13 @@ def __init__(self, bot: Canary): self.week_name: str | None = None self.send_reminder: str | None = None - @commands.Cog.listener() + @CanaryCog.listener() async def on_ready(self): - self.guild = self.bot.get_guild(self.bot.config.server_id) + await super().on_ready() + + if not self.guild: + return + self.banner_of_the_week_channel = utils.get( self.guild.text_channels, name=self.bot.config.banner_of_the_week_channel ) @@ -68,18 +72,13 @@ async def on_ready(self): self.banner_winner_role = utils.get(self.guild.roles, name=self.bot.config.banner_winner_role) self.banner_vote_emoji = utils.get(self.guild.emojis, name=self.bot.config.banner_vote_emoji) - conn = sqlite3.connect(self.bot.config.db_path) - c = conn.cursor() - c.execute("SELECT Value FROM Settings WHERE Key = ?", ("BannerContestInfo",)) - fetched = c.fetchone() - if fetched: - banner_dict = json.loads(fetched[0]) + if (banner_contest_info := await self.get_settings_key("BannerContestInfo")) is not None: + banner_dict = json.loads(banner_contest_info) timestamp = banner_dict["timestamp"] if timestamp: self.start_datetime = datetime.datetime.fromtimestamp(timestamp) self.week_name = banner_dict["week_name"] self.send_reminder = banner_dict["send_reminder"] - conn.close() self.check_banner_contest_reminder.start() @@ -92,8 +91,6 @@ async def check_banner_contest_reminder(self): if datetime.datetime.now() < self.start_datetime or not self.send_reminder: return - conn = sqlite3.connect(self.bot.config.db_path) - c = conn.cursor() await self.banner_submissions_channel.send( f"{self.banner_reminders_role.mention} " f"Submissions are now open for the banner picture of the week! " @@ -101,15 +98,12 @@ async def check_banner_contest_reminder(self): f"The winner will be chosen in around 12 hours " f"(To get these reminders, type `.iam Banner Submissions` in {self.bots_channel.mention})" ) - c.execute("SELECT Value FROM Settings WHERE Key = ?", ("BannerContestInfo",)) - fetched = c.fetchone() - if fetched: + + if (banner_contest_info := await self.get_settings_key("BannerContestInfo")) is not None: self.send_reminder = False - banner_dict = json.loads(fetched[0]) + banner_dict = json.loads(banner_contest_info) banner_dict["send_reminder"] = False - c.execute("REPLACE INTO Settings VALUES (?, ?)", ("BannerContestInfo", json.dumps(banner_dict))) - conn.commit() - conn.close() + await self.set_settings_key("BannerContestInfo", json.dumps(banner_dict)) async def reset_banner_contest(self): self.start_datetime = None @@ -117,12 +111,7 @@ async def reset_banner_contest(self): self.send_reminder = None banner_dict = {"timestamp": None, "week_name": None, "send_reminder": None} - conn = sqlite3.connect(self.bot.config.db_path) - c = conn.cursor() - c.execute("REPLACE INTO Settings VALUES (?, ?)", ("BannerContestInfo", json.dumps(banner_dict))) - c.execute("DELETE FROM BannerSubmissions") - conn.commit() - conn.close() + await self.set_settings_key("BannerContestInfo", json.dumps(banner_dict)) @commands.command(aliases=["setbannercontest"]) @is_moderator() @@ -197,11 +186,9 @@ def msg_check(msg): week_name = week_msg.content banner_dict = {"timestamp": timestamp, "week_name": week_name, "send_reminder": True} - conn = sqlite3.connect(self.bot.config.db_path) - c = conn.cursor() - c.execute("REPLACE INTO Settings VALUES (?, ?)", ("BannerContestInfo", json.dumps(banner_dict))) - c.execute("DELETE FROM BannerSubmissions") - conn.commit() + await self.set_settings_key( + "BannerContestInfo", json.dumps(banner_dict), pre_commit=["DELETE FROM BannerSubmissions"] + ) self.start_datetime = datetime.datetime.fromtimestamp(timestamp) self.week_name = week_name @@ -211,7 +198,6 @@ def msg_check(msg): f"Start time for the banner contest of the week of `{week_name}` successfully set to " f"`{self.start_datetime.strftime('%Y-%m-%d %H:%M')}`." ) - conn.close() @commands.command(aliases=["bannerwinner", "setbannerwinner", "set_banner_winner"]) @is_moderator() @@ -287,11 +273,12 @@ def msg_check(msg): return winner_id = winner.id - conn = sqlite3.connect(self.bot.config.db_path) - c = conn.cursor() - c.execute("SELECT * FROM BannerSubmissions WHERE UserID = ?", (winner_id,)) - fetched = c.fetchone() - conn.close() + + db: aiosqlite.Connection + async with self.db() as db: + c: aiosqlite.Cursor + async with db.execute("SELECT * FROM BannerSubmissions WHERE UserID = ?", (winner_id,)) as c: + fetched = await c.fetchone() if not fetched: await ctx.send("No submission by this user in database. Exiting command.") @@ -364,28 +351,26 @@ def msg_check(msg): reason=f"Banner of the week winner submitted by {winner} " f"(Approved by {ctx.author})" ) except discord.errors.HTTPException as e: - if e.code == 30003: # Discord API code for full pins - pins = await self.banner_submissions_channel.pins() - await pins[-1].unpin(reason="#banner_submissions pins are full") - await preview_message.pin( - reason=f"Banner of the week winner submitted by {winner} " f"(Approved by {ctx.author})" - ) - else: + if e.code != 30003: # Discord API code for full pins raise e + pins = await self.banner_submissions_channel.pins() + await pins[-1].unpin(reason="#banner_submissions pins are full") + await preview_message.pin( + reason=f"Banner of the week winner submitted by {winner} " f"(Approved by {ctx.author})" + ) try: await converted_message.pin( reason=f"Banner of the week winner submitted by {winner} " f"(Approved by {ctx.author})" ) except discord.errors.HTTPException as e: - if e.code == 30003: - pins = await self.banner_converted_channel.pins() - await pins[-1].unpin(reason="#converted_banner_submissions pins are full") - await converted_message.pin( - reason=f"Banner of the week winner submitted by {winner} " f"(Approved by {ctx.author})" - ) - else: + if e.code != 30003: raise e + pins = await self.banner_converted_channel.pins() + await pins[-1].unpin(reason="#converted_banner_submissions pins are full") + await converted_message.pin( + reason=f"Banner of the week winner submitted by {winner} " f"(Approved by {ctx.author})" + ) await winner.add_roles(self.banner_winner_role, reason=f"Banner of the week winner (Approved by {ctx.author})") converted_read = await converted.read() @@ -408,8 +393,6 @@ async def submit_banner(self, ctx: commands.Context, *args): You must be a verified user to use this command. """ - conn = sqlite3.connect(self.bot.config.db_path) - c = conn.cursor() if not ( discord.utils.get(ctx.author.roles, name=self.bot.config.mcgillian_role) @@ -422,14 +405,12 @@ async def submit_banner(self, ctx: commands.Context, *args): await ctx.send("You cannot submit banners if you have the Trash Tier Banner Submissions role") return - c.execute("SELECT Value FROM Settings WHERE Key = ?", ("BannerContestInfo",)) - - fetched = c.fetchone() - if not fetched: + banner_contest_info = await self.get_settings_key("BannerContestInfo") + if not banner_contest_info: await ctx.send("No banner contest is currently set") return - banner_dict = json.loads(fetched[0]) + banner_dict = json.loads(banner_contest_info) timestamp = banner_dict["timestamp"] if not timestamp: @@ -542,18 +523,24 @@ async def submit_banner(self, ctx: commands.Context, *args): return replaced_message = False - c.execute("SELECT PreviewMessageID FROM BannerSubmissions WHERE UserID = ?", (ctx.author.id,)) - fetched = c.fetchone() - if fetched: - try: - message_to_replace = await self.banner_submissions_channel.fetch_message(fetched[0]) - await message_to_replace.delete() - except discord.errors.NotFound: - await ctx.send( - f"Could not delete previously posted submission from {self.banner_submissions_channel.mention}. " - f"It might have been manually deleted." - ) - replaced_message = True + + db: aiosqlite.Connection + async with self.db() as db: + c: aiosqlite.Cursor + async with db.execute( + "SELECT PreviewMessageID FROM BannerSubmissions WHERE UserID = ?", (ctx.author.id,) + ) as c: + fetched = await c.fetchone() + if fetched: + try: + message_to_replace = await self.banner_submissions_channel.fetch_message(fetched[0]) + await message_to_replace.delete() + except discord.errors.NotFound: + await ctx.send( + f"Could not delete previously posted submission from " + f"{self.banner_submissions_channel.mention}. It might have been manually deleted." + ) + replaced_message = True async def send_picture(frames, channel, filename): with BytesIO() as image_binary: @@ -580,11 +567,13 @@ async def send_picture(frames, channel, filename): ) await preview_message.add_reaction(self.banner_vote_emoji) - c.execute( - "REPLACE INTO BannerSubmissions VALUES (?, ?, ?)", (ctx.author.id, preview_message.id, converted_message.id) - ) - conn.commit() - conn.close() + async with self.db() as db: + await db.execute( + "REPLACE INTO BannerSubmissions VALUES (?, ?, ?)", + (ctx.author.id, preview_message.id, converted_message.id), + ) + await db.commit() + await ctx.send(f"Banner successfully {'resubmitted' if replaced_message else 'submitted'}!") From 7513cec3ca1a7bfc0bbcd494cc23721f9e804c27 Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Sun, 4 Sep 2022 10:02:57 -0400 Subject: [PATCH 023/127] rewrite currency cog with aiosqlite and code style changes --- canary/cogs/currency.py | 229 ++++++++++++++++++---------------------- 1 file changed, 100 insertions(+), 129 deletions(-) diff --git a/canary/cogs/currency.py b/canary/cogs/currency.py index f7a7b1b34..832bba823 100644 --- a/canary/cogs/currency.py +++ b/canary/cogs/currency.py @@ -15,30 +15,22 @@ # You should have received a copy of the GNU General Public License # along with Canary. If not, see . -# discord.py requirements +import datetime + +import aiosqlite import discord +import json +import random + +from decimal import Decimal, InvalidOperation from discord.ext import commands +from tabulate import tabulate -# For type hinting from ..bot import Canary - -# For DB functionality -import sqlite3 -import datetime +from .base_cog import CanaryCog from .utils.members import add_member_if_needed - -# For tables -from tabulate import tabulate from .utils.paginator import Pages -# For general currency shenanigans -from decimal import Decimal, InvalidOperation - -# For betting -import random - -# For other stuff -import json CLAIM_AMOUNT = Decimal(20) CLAIM_WAIT_TIME = datetime.timedelta(hours=1) @@ -66,41 +58,40 @@ ) -class Currency(commands.Cog): +class Currency(CanaryCog): def __init__(self, bot: Canary): - self.bot: Canary = bot + super().__init__(bot) self.currency: dict = self.bot.config.currency self.prec: int = self.currency["precision"] async def fetch_all_balances(self) -> list[tuple[str, str, Decimal]]: - conn = sqlite3.connect(self.bot.config.db_path) - c = conn.cursor() - c.execute( - "SELECT BT.UserID, M.Name, IFNULL(SUM(BT.Amount), 0) " - "FROM BankTransactions AS BT, Members as M " - "WHERE BT.UserID = M.ID GROUP BY UserID" - ) - - results = [(user_id, name, self.db_to_currency(balance)) for user_id, name, balance in c.fetchall()] - - conn.close() - - return results + db: aiosqlite.Connection + async with self.db() as db: + c: aiosqlite.Cursor + async with db.execute( + "SELECT BT.UserID, M.Name, IFNULL(SUM(BT.Amount), 0) " + "FROM BankTransactions AS BT, Members as M " + "WHERE BT.UserID = M.ID GROUP BY UserID" + ) as c: + return [ + (user_id, name, self.db_to_currency(balance)) for user_id, name, balance in (await c.fetchall()) + ] async def fetch_bank_balance(self, user: discord.Member) -> Decimal: - conn = sqlite3.connect(self.bot.config.db_path) - c = conn.cursor() - c.execute("SELECT IFNULL(SUM(Amount), 0) FROM BankTransactions WHERE " "UserID = ?", (user.id,)) - - balance = self.db_to_currency(c.fetchone()[0]) - if balance is None: - balance = Decimal(0) - - conn.close() - - return balance - - async def create_bank_transaction(self, c, user: discord.Member, amount: Decimal, action: str, metadata: dict): + db: aiosqlite.Connection + async with self.db() as db: + c: aiosqlite.Cursor + async with db.execute( + "SELECT IFNULL(SUM(Amount), 0) FROM BankTransactions WHERE " "UserID = ?", (user.id,) + ) as c: + balance = self.db_to_currency((await c.fetchone())[0]) + if balance is None: + balance = Decimal(0) + return balance + + async def create_bank_transaction( + self, db: aiosqlite.Connection, user: discord.Member, amount: Decimal, action: str, metadata: dict + ): # Don't create another connection in this function in order to properly # transaction-ify a series of bank "transactions". @@ -110,10 +101,12 @@ async def create_bank_transaction(self, c, user: discord.Member, amount: Decimal now = int(datetime.datetime.now().timestamp()) - c.execute("PRAGMA foreign_keys = ON") - await add_member_if_needed(self, c, user.id) - t = (user.id, self.currency_to_db(amount), action, json.dumps(metadata), now) - c.execute("INSERT INTO BankTransactions(UserID, Amount, Action, " "Metadata, Date) VALUES(?, ?, ?, ?, ?)", t) + await db.execute("PRAGMA foreign_keys = ON") + await add_member_if_needed(self, db, user.id) + await db.execute( + "INSERT INTO BankTransactions(UserID, Amount, Action, " "Metadata, Date) VALUES(?, ?, ?, ?, ?)", + (user.id, self.currency_to_db(amount), action, json.dumps(metadata), now), + ) @staticmethod def parse_currency(amount: str, balance: Decimal): @@ -172,38 +165,34 @@ async def initial_claim(self, ctx): # Start bot typing await ctx.trigger_typing() - conn = sqlite3.connect(self.bot.config.db_path) - c = conn.cursor() - - c.execute( - "SELECT IFNULL(MAX(Date), 0) FROM BankTransactions " "WHERE UserID = ? AND Action = ?", - (ctx.message.author.id, ACTION_INITIAL_CLAIM), - ) - - claim_time = c.fetchone()[0] - - author_name = ctx.message.author.display_name - - if claim_time > 0: - await ctx.send("{} has already claimed their initial " "currency.".format(author_name)) - return - - metadata = {"channel": ctx.message.channel.id} - - await self.create_bank_transaction( - c, ctx.message.author, self.currency["initial_amount"], ACTION_INITIAL_CLAIM, metadata - ) + db: aiosqlite.Connection + async with self.db() as db: + async with db.execute( + "SELECT IFNULL(MAX(Date), 0) FROM BankTransactions " "WHERE UserID = ? AND Action = ?", + (ctx.message.author.id, ACTION_INITIAL_CLAIM), + ) as c: + claim_time = (await c.fetchone())[0] + + author_name = ctx.message.author.display_name + + if claim_time > 0: + await ctx.send(f"{author_name} has already claimed their initial currency.") + return + + await self.create_bank_transaction( + db, + ctx.message.author, + self.currency["initial_amount"], + ACTION_INITIAL_CLAIM, + {"channel": ctx.message.channel.id}, + ) - conn.commit() + await db.commit() await ctx.send( - "{} claimed their initial {}!".format( - author_name, self.format_symbol_currency(self.currency["initial_amount"]) - ) + f"{author_name} claimed their initial {self.format_symbol_currency(self.currency['initial_amount'])}!" ) - conn.close() - @commands.command() async def claim(self, ctx): """ @@ -213,35 +202,28 @@ async def claim(self, ctx): # Start bot typing await ctx.trigger_typing() - conn = sqlite3.connect(self.bot.config.db_path) - c = conn.cursor() - - c.execute( - "SELECT IFNULL(MAX(Date), 0) FROM BankTransactions " "WHERE UserID = ? AND Action = ?", - (ctx.message.author.id, ACTION_CLAIM), - ) - - last_claimed = datetime.datetime.fromtimestamp(c.fetchone()[0]) threshold = datetime.datetime.now() - CLAIM_WAIT_TIME - if last_claimed < threshold: - author_name = ctx.message.author.display_name if ctx.message.author else ":b:roken bot" + db: aiosqlite.Connection + async with self.db() as db: + c: aiosqlite.Cursor + async with db.execute( + "SELECT IFNULL(MAX(Date), 0) FROM BankTransactions " "WHERE UserID = ? AND Action = ?", + (ctx.message.author.id, ACTION_CLAIM), + ) as c: + last_claimed = datetime.datetime.fromtimestamp((await c.fetchone())[0]) - metadata = {"channel": ctx.message.channel.id} + if last_claimed < threshold: + metadata = {"channel": ctx.message.channel.id} + await self.create_bank_transaction(db, ctx.message.author, CLAIM_AMOUNT, ACTION_CLAIM, metadata) + await db.commit() - await self.create_bank_transaction(c, ctx.message.author, CLAIM_AMOUNT, ACTION_CLAIM, metadata) + author_name = ctx.message.author.display_name if ctx.message.author else ":b:roken bot" + await ctx.send(f"{author_name} claimed {self.format_symbol_currency(CLAIM_AMOUNT)}!") + return - conn.commit() - - await ctx.send("{} claimed {}!".format(author_name, self.format_symbol_currency(CLAIM_AMOUNT))) - - else: - time_left = last_claimed - threshold - await ctx.send( - "Please wait {}h {}m to claim again!".format(time_left.seconds // 3600, time_left.seconds // 60 % 60) - ) - - conn.close() + time_left = last_claimed - threshold + await ctx.send(f"Please wait {time_left.seconds // 3600}h {time_left.seconds // 60 % 60}m to claim again!") @commands.command(aliases=["$", "bal"]) async def balance(self, ctx, user: discord.Member = None): @@ -257,7 +239,7 @@ async def balance(self, ctx, user: discord.Member = None): author = user if user else ctx.message.author amount = self.format_symbol_currency(await self.fetch_bank_balance(author)) - await ctx.send("{} has {} in their account.".format(author.display_name, amount)) + await ctx.send(f"{author.display_name} has {amount} in their account.") @commands.command(aliases=["bf"]) async def bet_flip(self, ctx, bet: str = None, face: str = None): @@ -290,16 +272,14 @@ async def bet_flip(self, ctx, bet: str = None, face: str = None): # If all cases pass, perform the gamble - conn = sqlite3.connect(self.bot.config.db_path) - c = conn.cursor() - result = random.choice(COIN_FLIP_CHOICES) - metadata = {"result": result, "channel": ctx.message.channel.id} - amount = bet_dec if choice == result else -bet_dec - await self.create_bank_transaction(c, ctx.message.author, amount, ACTION_BET_FLIP, metadata) - conn.commit() + + db: aiosqlite.Connection + async with self.db() as db: + await self.create_bank_transaction(db, ctx.message.author, amount, ACTION_BET_FLIP, metadata) + await db.commit() message = "Sorry! {} lost {} (result was **{}**)." if choice == result: @@ -309,8 +289,6 @@ async def bet_flip(self, ctx, bet: str = None, face: str = None): await ctx.send(message.format(author_name, self.format_symbol_currency(bet_dec), result)) - conn.close() - @commands.command(aliases=["br"]) async def bet_roll(self, ctx, bet: str = None): """ @@ -335,9 +313,6 @@ async def bet_roll(self, ctx, bet: str = None): # If all cases pass, perform the gamble - conn = sqlite3.connect(self.bot.config.db_path) - c = conn.cursor() - result = random.randrange(1, 101) amount_returned = Decimal(0) @@ -353,9 +328,12 @@ async def bet_roll(self, ctx, bet: str = None): "channel": ctx.message.channel.id, } - await self.create_bank_transaction(c, ctx.message.author, amount_returned - bet_dec, ACTION_BET_ROLL, metadata) - - conn.commit() + db: aiosqlite.Connection + async with self.db() as db: + await self.create_bank_transaction( + db, ctx.message.author, amount_returned - bet_dec, ACTION_BET_ROLL, metadata + ) + await db.commit() message = "Sorry! {un} lost {am} (result was **{re}**)." if amount_returned == bet_dec: @@ -370,8 +348,6 @@ async def bet_roll(self, ctx, bet: str = None): await ctx.send(message.format(un=author_name, am=bet_str, re=result)) - conn.close() - @commands.command() async def give(self, ctx, user: discord.Member = None, amount: str = None): """ @@ -420,18 +396,13 @@ async def give(self, ctx, user: discord.Member = None, amount: str = None): giftee_metadata = {"gifter": ctx.message.author.id, "channel": ctx.message.channel.id} - conn = sqlite3.connect(self.bot.config.db_path) - c = conn.cursor() - - await self.create_bank_transaction(c, ctx.message.author, -amount_dec, ACTION_GIFTER, gifter_metadata) - - await self.create_bank_transaction(c, user, amount_dec, ACTION_GIFTEE, giftee_metadata) - - conn.commit() - - await ctx.send("{} gave {} to {}!".format(grn, self.format_symbol_currency(amount_dec), gen)) + db: aiosqlite.Connection + async with self.db() as db: + await self.create_bank_transaction(db, ctx.message.author, -amount_dec, ACTION_GIFTER, gifter_metadata) + await self.create_bank_transaction(db, user, amount_dec, ACTION_GIFTEE, giftee_metadata) + await db.commit() - conn.close() + await ctx.send(f"{grn} gave {self.format_symbol_currency(amount_dec)} to {gen}!") @commands.command(aliases=["lb"]) async def leaderboard(self, ctx): From 0d20ab1d1d7889de71c729094f46b139b9847d28 Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Sun, 4 Sep 2022 10:03:10 -0400 Subject: [PATCH 024/127] rewrite customreactions cog with aiosqlite and refactoring --- canary/cogs/customreactions.py | 758 ++++++++++++--------------------- 1 file changed, 279 insertions(+), 479 deletions(-) diff --git a/canary/cogs/customreactions.py b/canary/cogs/customreactions.py index 7b50e1a0c..97ebb751a 100644 --- a/canary/cogs/customreactions.py +++ b/canary/cogs/customreactions.py @@ -15,14 +15,14 @@ # You should have received a copy of the GNU General Public License # along with Canary. If not, see . -# discord-py requirements +import asyncio +import aiosqlite import discord + from discord.ext import commands -import asyncio -# Other utilities -import sqlite3 from ..bot import Canary +from .base_cog import CanaryCog from .utils.paginator import Pages from .utils.p_strings import PStringEncodings @@ -50,30 +50,36 @@ NUMBERS = (EMOJI["zero"], EMOJI["one"], EMOJI["two"], EMOJI["three"], EMOJI["four"], EMOJI["five"]) -CUSTOM_REACTION_TIMEOUT = "Custom Reaction timed out. " "You may want to run the command again." +CUSTOM_REACTION_TIMEOUT = "Custom Reaction timed out. You may want to run the command again." STOP_TEXT = "stop" LOADING_EMBED = discord.Embed(title="Loading...") -class CustomReactions(commands.Cog): +class CustomReactions(CanaryCog): # Written by @le-potate def __init__(self, bot: Canary): - self.bot: Canary = bot - self.reaction_list: list[str] = [] - self.proposal_list: list[str] = [] + super().__init__(bot) + + self.reaction_list: list[tuple] = [] + self.proposal_list: list[tuple] = [] self.p_strings: PStringEncodings | None = None - self.rebuild_lists() + @CanaryCog.listener() + async def on_ready(self): + await super().on_ready() + await self.rebuild_lists() - def rebuild_lists(self): - self.rebuild_reaction_list() - self.rebuild_proposal_list() + async def rebuild_lists(self): + await self.rebuild_reaction_list() + await self.rebuild_proposal_list() + + async def rebuild_reaction_list(self): + db: aiosqlite.Connection + async with self.db() as db: + c: aiosqlite.Cursor + async with db.execute("SELECT * FROM CustomReactions WHERE Proposal = 0") as c: + self.reaction_list = [tuple(r) for r in (await c.fetchall())] - def rebuild_reaction_list(self): - conn = sqlite3.connect(self.bot.config.db_path) - c = conn.cursor() - c.execute("SELECT * FROM CustomReactions WHERE Proposal = 0") - self.reaction_list = c.fetchall() prompts = [row[1].lower() for row in self.reaction_list] responses = [row[2] for row in self.reaction_list] anywhere_values = [row[5] for row in self.reaction_list] @@ -81,14 +87,13 @@ def rebuild_reaction_list(self): self.p_strings = PStringEncodings( prompts, responses, anywhere_values, additional_info_list=additional_info_list ) - conn.close() - def rebuild_proposal_list(self): - conn = sqlite3.connect(self.bot.config.db_path) - c = conn.cursor() - c.execute("SELECT * FROM CustomReactions WHERE Proposal = 1") - self.proposal_list = c.fetchall() - conn.close() + async def rebuild_proposal_list(self): + db: aiosqlite.Connection + async with self.db() as db: + c: aiosqlite.Cursor + async with db.execute("SELECT * FROM CustomReactions WHERE Proposal = 1") as c: + self.proposal_list = [tuple(r) for r in (await c.fetchall())] @commands.Cog.listener() async def on_message(self, message: discord.Message): @@ -266,37 +271,44 @@ async def create_assistant(message: discord.Message, is_moderator: bool): return True async def add_custom_react(message: discord.Message, is_moderator: bool): - if is_moderator: - title = "Add a custom reaction" - footer = f"{main_user} is currently adding a custom reaction. \n" f"Write '{STOP_TEXT}' to cancel." - else: - title = "Propose a custom reaction" - footer = f"{main_user} is currently proposing a custom reaction. \n" f"Write '{STOP_TEXT}' to cancel." + status_msg = f"{main_user} is currently {'adding' if is_moderator else 'proposing'} a custom reaction." + + title = f"{'Add' if is_moderator else 'Propose'} a custom reaction" + footer = f"{status_msg}\nWrite '{STOP_TEXT}' to cancel." description = "Write the prompt the bot will react to" - await message.edit( - embed=discord.Embed(title=title, description=description).set_footer( - text=footer, icon_url=main_user.avatar_url + + async def _refresh_msg(): + await message.edit( + embed=discord.Embed(title=title, description=description).set_footer( + text=footer, icon_url=main_user.avatar_url + ) ) - ) + + await _refresh_msg() + prompt_message = await wait_for_message(message) + if prompt_message is None: return + if prompt_message.lower() == STOP_TEXT: await leave(message) return True + description = f"Prompt: {prompt_message}\nWrite the response the bot will send" - await message.edit( - embed=discord.Embed(title=title, description=description).set_footer( - text=footer, icon_url=main_user.avatar_url - ) - ) + await _refresh_msg() + response = await wait_for_message(message) + if response is None: return + if response.lower() == STOP_TEXT: await leave(message) return True + await message.edit(embed=LOADING_EMBED) + description = ( f"Prompt: {prompt_message}\nResponse: {response}\n" f"React with the options " @@ -311,17 +323,13 @@ async def add_custom_react(message: discord.Message, is_moderator: bool): f"the user who calls the " f"reaction instead of the channel\n" ) - if is_moderator: - footer = f"{main_user} is currently adding a custom reaction." - else: - footer = f"{main_user} is currently proposing a custom reaction." + + footer = f"{main_user} is currently {'adding' if is_moderator else 'proposing'} a custom reaction." + current_options.extend((EMOJI["ok"], EMOJI["stop_button"])) await add_multiple_reactions(message, (*NUMBERS[1:4], EMOJI["ok"], EMOJI["stop_button"])) - await message.edit( - embed=discord.Embed(title=title, description=description).set_footer( - text=footer, icon_url=main_user.avatar_url - ) - ) + await _refresh_msg() + try: reaction, user = await wait_for_reaction(message) except TypeError: @@ -342,45 +350,38 @@ async def add_custom_react(message: discord.Message, is_moderator: bool): current_options.clear() await message.clear_reactions() - conn = sqlite3.connect(self.bot.config.db_path) - c = conn.cursor() - t = (prompt_message, response, main_user.id, delete, anywhere, dm, not is_moderator) - c.execute( - "INSERT INTO CustomReactions(Prompt, Response, UserID, " - "DeletePrompt, Anywhere, DM, Proposal) " - "VALUES(?,?,?,?,?,?,?)", - t, - ) - conn.commit() - conn.close() - self.rebuild_lists() + + db: aiosqlite.Connection + async with self.db() as db: + await db.execute( + "INSERT INTO CustomReactions(Prompt, Response, UserID, " + "DeletePrompt, Anywhere, DM, Proposal) " + "VALUES(?, ?, ?, ?, ?, ?, ?)", + (prompt_message, response, main_user.id, delete, anywhere, dm, not is_moderator), + ) + await db.commit() + + await self.rebuild_lists() if is_moderator: - title = "Custom reaction successfully added!" + title = f"Custom reaction successfully added!" else: - title = f"Custom reaction proposal successfully submitted!" + title = "Custom reaction proposal successfully submitted!" description = f"-Prompt: {prompt_message}\n" f"-Response: {response}" if delete: description = f"{description}\n-Will delete the message that calls the reaction" if anywhere: description = ( f"{description}\n" - f"-Will activate the custom reaction " - "if the prompt is anywhere in a message" + f"-Will activate the custom reaction if the prompt is anywhere in a message" ) if dm: description = ( f"{description}\n" - f"-Will react in the DMs of the user " - f"who calls the reaction instead of the " - f"channel" + f"-Will react in the DMs of the user who calls the reaction instead of the channel" ) - await message.edit( - embed=discord.Embed(title=title, description=description).set_footer( - text=f"Added by {main_user}.", icon_url=main_user.avatar_url - ) - ) + await _refresh_msg() return @@ -392,11 +393,10 @@ async def add_custom_react(message: discord.Message, is_moderator: bool): async def list_custom_reacts(message: discord.Message, proposals): current_list = self.proposal_list if proposals else self.reaction_list + no_items_msg = f"There are currently no custom reaction{' proposal' if proposals else ''}s in this server" + if not current_list: - if proposals: - title = "There are currently no custom reaction proposals in this server" - else: - title = "There are currently no custom reactions in this server" + title = no_items_msg await message.edit(embed=discord.Embed(title=title), delete_after=60) return @@ -420,14 +420,12 @@ async def list_custom_reacts(message: discord.Message, proposals): if proposals: title = ( f"Current custom reaction proposals\n" - f"Click on {EMOJI['ok']} " - f"to approve, reject, edit, or see more " - f"information on one of them" + f"Click on {EMOJI['ok']} to approve, reject, edit, or see more information on one of them" ) else: title = ( - f"Current custom reactions\nClick on {EMOJI['ok']} " - f"to edit or see more information on one of them" + f"Current custom reactions\n" + f"Click on {EMOJI['ok']} to edit or see more information on one of them" ) p = Pages( @@ -446,17 +444,13 @@ async def list_custom_reacts(message: discord.Message, proposals): if proposals: title = ( f"Current custom reaction proposals\n" - f"{user_modifying}: Write the number of the " - f"custom reaction " - f"proposal you want to approve, reject, edit, or " - f"see more information on" + f"{user_modifying}: Write the number of the custom reaction proposal you want to " + f"approve, reject, edit, or see more information on" ) else: title = ( f"Current custom reactions\n" - f"{user_modifying}: Write the number of the " - f"custom reaction " - f"you want to edit or see more " + f"{user_modifying}: Write the number of the custom reaction you want to edit or see more " f"information on" ) message.embeds[0].title = title @@ -477,19 +471,14 @@ async def list_custom_reacts(message: discord.Message, proposals): if proposals: title = ( f"Current custom reaction proposals\n" - f"Click on {EMOJI['ok']} " - f"to approve, reject, edit, or " - f"see more information on one of them " - f"(Previous attempt received invalid input " - f"or timed out)" + f"Click on {EMOJI['ok']} to approve, reject, edit, or see more information on one of them " + f"(Previous attempt received invalid input or timed out)" ) else: title = ( f"Current custom reactions\n" - f"Click on {EMOJI['ok']} " - f"to edit or see more information on one of " - f"them (Previous attempt received invalid " - f"input or timed out)" + f"Click on {EMOJI['ok']} to edit or see more information on one of " + f"them (Previous attempt received invalid input or timed out)" ) p = Pages( ctx, @@ -500,6 +489,7 @@ async def list_custom_reacts(message: discord.Message, proposals): editable_content_emoji=EMOJI["ok"], return_user_on_edit=True, ) + else: left = await information_on_react(message, current_list, number, proposals) if left: @@ -524,21 +514,16 @@ async def list_custom_reacts(message: discord.Message, proposals): current_list = self.proposal_list if proposals else self.reaction_list if not current_list: - if proposals: - title = "There are currently no custom reaction proposals in this server" - else: - title = "There are currently no custom reactions in this server" + title = no_items_msg await message.edit(embed=discord.Embed(title=title), delete_after=60) return reaction_dict = { "names": [f"[{i + 1}]" for i in range(len(current_list))], "values": [ - f"Prompt: " - f"{reaction[1][:min(len(reaction[1]), 287)]}" + f"Prompt: {reaction[1][:min(len(reaction[1]), 287)]}" f'{"..." if len(reaction[1]) > 287 else ""}' - f"\nResponse: " - f"{reaction[2][:min(len(reaction[2]), 287)]}" + f"\nResponse: {reaction[2][:min(len(reaction[2]), 287)]}" f'{"..." if len(reaction[2]) > 287 else ""}' for reaction in current_list ], @@ -553,10 +538,9 @@ async def list_custom_reacts(message: discord.Message, proposals): editable_content_emoji=EMOJI["ok"], return_user_on_edit=True, ) - await message.edit(embed=LOADING_EMBED) + await message.edit(embed=LOADING_EMBED) await add_control_reactions(message) - user_modifying = await p.paginate() async def information_on_react(message: discord.Message, current_list, number, proposals): @@ -569,28 +553,31 @@ async def information_on_react(message: discord.Message, current_list, number, p delete = custom_react[4] anywhere = custom_react[5] dm = custom_react[6] - if delete == 1: - delete_str = "Deletes the message that calls the reaction" - else: - delete_str = "Does not delete the message that calls the reaction" + + delete_str = f"{'Deletes' if delete == 1 else 'Does not delete'} the message that calls the reaction" + if anywhere == 1: anywhere_str = "Activates the custom reaction if the prompt is anywhere in a message" else: anywhere_str = "Only activates the custom reaction if the prompt is the full message" + if dm == 1: dm_str = "Reacts in the DMs of the user who calls the reaction instead of the channel" else: dm_str = "Reacts directly into the channel" + base_desc = ( + f"{EMOJI['one']} Prompt: {prompt}\n" + f"{EMOJI['two']} Response: {response}\n" + f"{EMOJI['three']} {delete_str}\n" + f"{EMOJI['four']} {anywhere_str}\n" + f"{EMOJI['five']} {dm_str}\n" + ) + if proposals: description = ( - f"{EMOJI['one']} Prompt: {prompt}" - f"\n{EMOJI['two']} Response: {response}" - f"\n{EMOJI['three']} {delete_str}" - f"\n{EMOJI['four']} {anywhere_str}" - f"\n{EMOJI['five']} {dm_str}" - f"\n{EMOJI['white_check_mark']} " - f"Approve this proposal\n" + f"{base_desc}\n" + f"{EMOJI['white_check_mark']} Approve this proposal\n" f"{EMOJI['x']} Reject this proposal\n" f"Added by {user_who_added}" ) @@ -604,13 +591,8 @@ async def information_on_react(message: discord.Message, current_list, number, p ) else: description = ( - f"{EMOJI['one']} Prompt: {prompt}\n" - f"{EMOJI['two']} Response: {response}" - f"\n{EMOJI['three']} {delete_str}" - f"\n{EMOJI['four']} {anywhere_str}" - f"\n{EMOJI['five']} {dm_str}" - f"\n{EMOJI['put_litter_in_its_place']} " - f"Delete this custom reaction\n" + f"{base_desc}\n" + f"{EMOJI['put_litter_in_its_place']} Delete this custom reaction\n" f"Added by {user_who_added}" ) title = ( @@ -646,55 +628,51 @@ async def information_on_react(message: discord.Message, current_list, number, p return True except asyncio.TimeoutError: pass + current_options.clear() await message.clear_reactions() - async def edit_custom_react(message: discord.Message, reaction, user, custom_react, proposals): + async def edit_custom_react( + message: discord.Message, + reaction: discord.Reaction, + user, + custom_react, + proposals, + ): + db: aiosqlite.Connection + current_options.clear() await message.clear_reactions() custom_react_id = custom_react[0] delete = custom_react[4] anywhere = custom_react[5] dm = custom_react[6] - conn = sqlite3.connect(self.bot.config.db_path) - c = conn.cursor() + + noun = f"reaction{' proposal' if proposals else ''}" + noun_custom = f"custom {noun}" + + message_kept = f"Successfully kept current option! Returning to list of {noun}s..." + message_modified = f"Option successfully modified! Returning to list of {noun}s..." + message_time_out = f"The modification of the {noun_custom} timed out. Returning to list of {noun}s..." # Edit the prompt if reaction.emoji == EMOJI["one"]: - if proposals: - title = "Modify a custom reaction proposal" - footer = ( - f"{user} is currently modifying " - f"a custom reaction proposal. \n" - f"Write '{STOP_TEXT}' to cancel." - ) - else: - title = "Modify a custom reaction" - footer = f"{user} is currently modifying a custom reaction. \nWrite '{STOP_TEXT}' to cancel." - description = "Please enter the new prompt" await message.edit( - embed=discord.Embed(title=title, description=description).set_footer( - text=footer, icon_url=user.avatar_url + embed=( + discord.Embed( + title=f"Modify a {noun_custom}", + description="Please enter the new prompt" + ).set_footer( + text=f"{user} is currently modifying a {noun_custom}. \nWrite '{STOP_TEXT}' to cancel.", + icon_url=user.avatar_url + ) ) ) + try: msg = await self.bot.wait_for("message", check=get_msg_check(msg_user=user), timeout=60) - except asyncio.TimeoutError: - if proposals: - title = ( - "The modification of the custom reaction " - "proposal timed out. " - "Returning to list of reaction proposals..." - ) - else: - title = ( - "The modification of the custom reaction " - "timed out. " - "Returning to list of current reactions..." - ) - await message.edit(embed=discord.Embed(title=title)) - conn.close() + await message.edit(embed=discord.Embed(title=message_time_out)) await asyncio.sleep(5) return @@ -705,54 +683,38 @@ async def edit_custom_react(message: discord.Message, reaction, user, custom_rea await leave(message) return True - t = (prompt, custom_react_id) - c.execute("UPDATE CustomReactions SET Prompt = ? WHERE CustomReactionID = ?", t) - conn.commit() - self.rebuild_lists() - if proposals: - title = "Prompt successfully modified! Returning to list of reaction proposals..." - else: - title = "Prompt successfully modified! Returning to list of current reactions..." + async with self.db() as db: + await db.execute( + "UPDATE CustomReactions SET Prompt = ? WHERE CustomReactionID = ?", + (prompt, custom_react_id) + ) + await db.commit() + + await self.rebuild_lists() + await message.edit( - embed=discord.Embed(title=title).set_footer(text=f"Modified by {user}.", icon_url=user.avatar_url) + embed=discord.Embed( + title=f"Prompt successfully modified! Returning to list of {noun}s..." + ).set_footer(text=f"Modified by {user}.", icon_url=user.avatar_url) ) - conn.close() await asyncio.sleep(5) # Edit the response if reaction.emoji == EMOJI["two"]: - if proposals: - title = "Modify a custom reaction proposal" - footer = ( - f"{user} is currently modifying a custom reaction proposal. \n" - f"Write '{STOP_TEXT}' to cancel." - ) - else: - title = "Modify a custom reaction" - footer = f"{user} is currently modifying a custom reaction. \nWrite '{STOP_TEXT}' to cancel." - description = "Please enter the new response" await message.edit( - embed=discord.Embed(title=title, description=description).set_footer( - text=footer, icon_url=user.avatar_url + embed=discord.Embed( + title=f"Modify a {noun_custom}", + description="Please enter the new response" + ).set_footer( + text=f"{user} is currently modifying a {noun_custom}. \nWrite '{STOP_TEXT}' to cancel.", + icon_url=user.avatar_url ) ) try: msg = await self.bot.wait_for("message", check=get_msg_check(msg_user=user), timeout=60) - except asyncio.TimeoutError: - if proposals: - title = ( - "The modification of the custom reaction proposal timed out. " - "Returning to list of reaction proposals..." - ) - else: - title = ( - "The modification of the custom reaction timed out. " - "Returning to list of current reactions..." - ) - await message.edit(embed=discord.Embed(title=title)) - conn.close() + await message.edit(embed=discord.Embed(title=message_time_out)) await asyncio.sleep(5) return @@ -763,33 +725,25 @@ async def edit_custom_react(message: discord.Message, reaction, user, custom_rea await leave(message) return True - c.execute( - "UPDATE CustomReactions SET Response = ? WHERE CustomReactionID = ?", (response, custom_react_id) - ) - conn.commit() - self.rebuild_lists() - if proposals: - title = "Response successfully modified! Returning to list of reaction proposals..." - else: - title = "Response successfully modified! Returning to list of current reactions..." + async with self.db() as db: + await db.execute( + "UPDATE CustomReactions SET Response = ? WHERE CustomReactionID = ?", + (response, custom_react_id) + ) + await db.commit() + + await self.rebuild_lists() + title = f"Response successfully modified! Returning to list of {noun}s..." await message.edit( embed=discord.Embed(title=title).set_footer(text=f"Modified by {user}.", icon_url=user.avatar_url) ) - conn.close() await asyncio.sleep(5) # Edit the "delete" option if reaction.emoji == EMOJI["three"]: await message.edit(embed=LOADING_EMBED) - if proposals: - title = "Modify a custom reaction proposal. React with the option you want" - footer = f"{user} is currently modifying a custom reaction proposal. \n" - else: - title = "Modify a custom reaction. React with the option you want" - footer = f"{user} is currently modifying a custom reaction. \n" description = ( - f"Should the message that calls the " - f"reaction be deleted?\n" + f"Should the message that calls the reaction be deleted?\n" f"{EMOJI['zero']} No\n" f"{EMOJI['one']} Yes" ) @@ -799,8 +753,12 @@ async def edit_custom_react(message: discord.Message, reaction, user, custom_rea await add_yes_or_no_reactions(message) await message.edit( embed=( - discord.Embed(title=title, description=description).set_footer( - text=footer, icon_url=user.avatar_url + discord.Embed( + title=f"Modify a {noun_custom}. React with the option you want", + description=description, + ).set_footer( + text=f"{user} is currently modifying a {noun_custom}. \n", + icon_url=user.avatar_url, ) ) ) @@ -809,20 +767,8 @@ async def edit_custom_react(message: discord.Message, reaction, user, custom_rea reaction, reaction_user = await self.bot.wait_for( "reaction_add", check=get_reaction_check(reaction_user=user), timeout=60 ) - except asyncio.TimeoutError: - if proposals: - title = ( - "The modification of the custom reaction proposal timed out. " - "Returning to list of reaction proposals..." - ) - else: - title = ( - "The modification of the custom reaction timed out. " - "Returning to list of current reactions..." - ) - await message.edit(embed=discord.Embed(title=title)) - conn.close() + await message.edit(embed=discord.Embed(title=message_time_out)) await asyncio.sleep(5) current_options.clear() await message.clear_reactions() @@ -830,86 +776,43 @@ async def edit_custom_react(message: discord.Message, reaction, user, custom_rea current_options.clear() await message.clear_reactions() - # Deactivate the "delete" option - if reaction.emoji == EMOJI["zero"]: - if delete == 0: - if proposals: - title = "Successfully kept current option! Returning to list of reaction proposals..." - else: - title = "Successfully kept current option! Returning to list of current reactions..." - await message.edit( - embed=discord.Embed(title=title).set_footer( - text=f"Modified by {user}.", icon_url=user.avatar_url - ) - ) - conn.close() - await asyncio.sleep(5) - else: - t = (0, custom_react_id) - c.execute("UPDATE CustomReactions SET DeletePrompt = ? WHERE CustomReactionID = ?", t) - conn.commit() - self.rebuild_lists() - if proposals: - title = "Option successfully modified! Returning to list of current reaction proposals..." - else: - title = "Option successfully modified! Returning to list of current reactions..." - await message.edit( - embed=discord.Embed(title=title).set_footer( - text=f"Modified by {user}.", icon_url=user.avatar_url - ) - ) - conn.close() - await asyncio.sleep(5) - - # Activate the "delete" option - elif reaction.emoji == EMOJI["one"]: - if delete == 1: - if proposals: - title = "Successfully kept current option! Returning to list of reaction proposals..." - else: - title = "Successfully kept current option! Returning to list of current reactions..." - await message.edit( - embed=discord.Embed(title=title).set_footer( - text=f"Modified by {user}.", icon_url=user.avatar_url - ) - ) - conn.close() - await asyncio.sleep(5) + + if reaction.emoji == EMOJI["stop_button"]: + await leave(message) + return True + + if reaction.emoji in (EMOJI["zero"], EMOJI["one"]): + # 0: Deactivate the "delete" option + # 1: Activate the "delete" option + new_value = int(reaction.emoji == EMOJI["one"]) # 1 if one, 0 if zero; simple as that + + if delete == new_value: + title = message_kept else: - c.execute( - "UPDATE CustomReactions SET DeletePrompt = ? WHERE CustomReactionID = ?", - (1, custom_react_id), - ) - conn.commit() - self.rebuild_lists() - if proposals: - title = "Option successfully modified! Returning to list of current reaction proposals..." - else: - title = "Option successfully modified! Returning to list of current reactions..." - await message.edit( - embed=discord.Embed(title=title).set_footer( - text=f"Modified by {user}.", icon_url=user.avatar_url + async with self.db() as db: + await db.execute( + "UPDATE CustomReactions SET DeletePrompt = ? WHERE CustomReactionID = ?", + (new_value, custom_react_id) ) + await db.commit() + await self.rebuild_lists() + title = message_modified + + await message.edit( + embed=discord.Embed(title=title).set_footer( + text=f"Modified by {user}.", icon_url=user.avatar_url ) - conn.close() - await asyncio.sleep(5) - # Stop - elif reaction.emoji == EMOJI["stop_button"]: - await leave(message) - return True + ) + + await asyncio.sleep(5) # Edit the "anywhere" option if reaction.emoji == EMOJI["four"]: await message.edit(embed=LOADING_EMBED) - if proposals: - title = "Modify a custom reaction proposal. React with the option you want" - footer = f"{user} is currently modifying a custom reaction proposal. \n" - else: - title = "Modify a custom reaction. React with the option you want" - footer = f"{user} is currently modifying a custom reaction. \n" + title = f"Modify a {noun_custom}. React with the option you want" + footer = f"{user} is currently modifying a {noun_custom}. \n" description = ( - f"Should the custom reaction be activated " - f"if the prompt is anywhere in a message?\n" + f"Should the custom reaction be activated if the prompt is anywhere in a message?\n" f"{EMOJI['zero']} No\n" f"{EMOJI['one']} Yes" ) @@ -928,18 +831,11 @@ async def edit_custom_react(message: discord.Message, reaction, user, custom_rea ) except asyncio.TimeoutError: - if proposals: - title = ( - "The modification of the custom reaction proposal timed out. " - "Returning to list of reaction proposals..." - ) - else: - title = ( - "The modification of the custom reaction timed out. " - "Returning to list of current reactions..." - ) + title = ( + f"The modification of the {noun_custom} timed out. " + f"Returning to list of {noun}s..." + ) await message.edit(embed=discord.Embed(title=title)) - conn.close() await asyncio.sleep(5) current_options.clear() await message.clear_reactions() @@ -947,83 +843,41 @@ async def edit_custom_react(message: discord.Message, reaction, user, custom_rea current_options.clear() await message.clear_reactions() - # Deactivate "anywhere" option - if reaction.emoji == EMOJI["zero"]: - if anywhere == 0: - if proposals: - title = "Successfully kept current option! Returning to list of reaction proposals..." - else: - title = "Successfully kept current option! Returning to list of current reactions..." - await message.edit( - embed=discord.Embed(title=title).set_footer( - text=f"Modified by {user}.", icon_url=user.avatar_url - ) - ) - conn.close() - await asyncio.sleep(5) - else: - t = (0, custom_react_id) - c.execute("UPDATE CustomReactions SET Anywhere = ? WHERE CustomReactionID = ?", t) - conn.commit() - self.rebuild_lists() - if proposals: - title = "Option successfully modified! Returning to list of current reaction proposals..." - else: - title = "Option successfully modified! Returning to list of current reactions..." - await message.edit( - embed=( - discord.Embed(title=title).set_footer( - text=f"Modified by {user}.", icon_url=user.avatar_url - ) - ) - ) - conn.close() - await asyncio.sleep(5) - - # Activate "anywhere" option - elif reaction.emoji == EMOJI["one"]: - if anywhere == 1: - if proposals: - title = "Successfully kept current option! Returning to list of reaction proposals..." - else: - title = "Successfully kept current option! Returning to list of current reactions..." - await message.edit( - embed=discord.Embed(title=title).set_footer( - text=f"Modified by {user}.", icon_url=user.avatar_url - ) - ) - conn.close() - await asyncio.sleep(5) + + if reaction.emoji == EMOJI["stop_button"]: + await leave(message) + return True + + if reaction.emoji in (EMOJI["zero"], EMOJI["one"]): + # 0: Deactivate the "anywhere" option + # 1: Activate the "anywhere" option + new_value = int(reaction.emoji == EMOJI["one"]) # 1 if one, 0 if zero; simple as that + + if anywhere == new_value: + title = message_kept else: - t = (1, custom_react_id) - c.execute("UPDATE CustomReactions SET Anywhere = ? WHERE CustomReactionID = ?", t) - conn.commit() - self.rebuild_lists() - if proposals: - title = "Option successfully modified! Returning to list of current reaction proposals..." - else: - title = "Option successfully modified! Returning to list of current reactions..." - await message.edit( - embed=discord.Embed(title=title).set_footer( - text=f"Modified by {user}.", icon_url=user.avatar_url + async with self.db() as db: + await db.execute( + "UPDATE CustomReactions SET Anywhere = ? WHERE CustomReactionID = ?", + (new_value, custom_react_id) ) + await db.commit() + await self.rebuild_lists() + title = message_modified + + await message.edit( + embed=discord.Embed(title=title).set_footer( + text=f"Modified by {user}.", icon_url=user.avatar_url ) - conn.close() - await asyncio.sleep(5) - # Stop - elif reaction.emoji == EMOJI["stop_button"]: - await leave(message) - return True + ) + + await asyncio.sleep(5) # Edit "dm" option if reaction.emoji == EMOJI["five"]: await message.edit(embed=LOADING_EMBED) - if proposals: - title = "Modify a custom reaction proposal. React with the option you want" - footer = f"{user} is currently modifying a custom reaction proposal. \n" - else: - title = "Modify a custom reaction. React with the option you want" - footer = f"{user} is currently modifying a custom reaction. \n" + title = f"Modify a {noun_custom}. React with the option you want" + footer = f"{user} is currently modifying a {noun_custom}. \n" description = ( f"Should the reaction be sent in the DMs of the user who called the reaction " f"instead of the channel?\n" @@ -1047,18 +901,8 @@ async def edit_custom_react(message: discord.Message, reaction, user, custom_rea ) except asyncio.TimeoutError: - if proposals: - title = ( - "The modification of the custom reaction proposal timed out. " - "Returning to list of reaction proposals..." - ) - else: - title = ( - "The modification of the custom reaction timed out. " - "Returning to list of current reactions..." - ) + title = f"The modification of the {noun_custom} timed out. Returning to list of {noun}s..." await message.edit(embed=discord.Embed(title=title)) - conn.close() await asyncio.sleep(5) current_options.clear() await message.clear_reactions() @@ -1066,110 +910,66 @@ async def edit_custom_react(message: discord.Message, reaction, user, custom_rea current_options.clear() await message.clear_reactions() - # Deactivate "dm" option - if reaction.emoji == EMOJI["zero"]: - if dm == 0: - if proposals: - title = "Successfully kept current option! Returning to list of reaction proposals..." - else: - title = "Successfully kept current option! Returning to list of current reactions..." - await message.edit( - embed=( - discord.Embed(title=title).set_footer( - text=f"Modified by {user}.", icon_url=user.avatar_url - ) - ) - ) - conn.close() - await asyncio.sleep(5) - else: - c.execute("UPDATE CustomReactions SET DM = ? WHERE CustomReactionID = ?", (0, custom_react_id)) - conn.commit() - self.rebuild_lists() - if proposals: - title = "Option successfully modified! Returning to list of current reaction proposals..." - else: - title = "Option successfully modified! Returning to list of current reactions..." - await message.edit( - embed=( - discord.Embed(title=title).set_footer( - text=f"Modified by {user}.", icon_url=user.avatar_url - ) - ) - ) - conn.close() - await asyncio.sleep(5) - # Activate "dm" option - elif reaction.emoji == EMOJI["one"]: - if dm == 1: - if proposals: - title = "Successfully kept current option! Returning to list of reaction proposals..." - else: - title = "Successfully kept current option! Returning to list of current reactions..." - await message.edit( - embed=( - discord.Embed(title=title).set_footer( - text=f"Modified by {user}.", icon_url=user.avatar_url - ) - ) - ) - conn.close() - await asyncio.sleep(5) + + if reaction.emoji == EMOJI["stop_button"]: + await leave(message) + return True + + if reaction.emoji in (EMOJI["zero"], EMOJI["one"]): + # 0: Deactivate the "dm" option + # 1: Activate the "dm" option + new_value = int(reaction.emoji == EMOJI["one"]) # 1 if one, 0 if zero; simple as that + + if dm == new_value: + title = message_kept else: - t = (1, custom_react_id) - c.execute("UPDATE CustomReactions SET DM = ? WHERE CustomReactionID = ?", t) - conn.commit() - self.rebuild_lists() - if proposals: - title = "Option successfully modified! Returning to list of current reaction proposals..." - else: - title = "Option successfully modified! Returning to list of current reactions..." - await message.edit( - embed=( - discord.Embed(title=title).set_footer( - text=f"Modified by {user}.", icon_url=user.avatar_url - ) + async with self.db() as db: + await db.execute( + "UPDATE CustomReactions SET DM = ? WHERE CustomReactionID = ?", + (new_value, custom_react_id) ) + await db.commit() + await self.rebuild_lists() + title = message_modified + + await message.edit( + embed=discord.Embed(title=title).set_footer( + text=f"Modified by {user}.", icon_url=user.avatar_url ) - conn.close() - await asyncio.sleep(5) - # Stop - elif reaction.emoji == EMOJI["stop_button"]: - await leave(message) - return True + ) + + await asyncio.sleep(5) # Approve a custom reaction proposal if reaction.emoji == EMOJI["white_check_mark"]: - t = (0, custom_react_id) - c.execute("UPDATE CustomReactions SET Proposal = ? WHERE CustomReactionID = ?", t) - conn.commit() - self.rebuild_lists() - title = ( + async with self.db() as db: + await db.execute( + "UPDATE CustomReactions SET Proposal = ? WHERE CustomReactionID = ?", + (0, custom_react_id) + ) + await db.commit() + + await self.rebuild_lists() + + await message.edit(embed=discord.Embed(title=( "Custom reaction proposal successfully approved! " "Returning to list of current reaction proposals..." - ) - footer = f"Approved by {user}." - await message.edit(embed=discord.Embed(title=title).set_footer(text=footer, icon_url=user.avatar_url)) - conn.close() + )).set_footer(text=f"Approved by {user}.", icon_url=user.avatar_url)) + await asyncio.sleep(5) # Delete a custom reaction or proposal if reaction.emoji == EMOJI["put_litter_in_its_place"] or reaction.emoji == EMOJI["x"]: - t = (custom_react_id,) - c.execute("DELETE FROM CustomReactions WHERE CustomReactionID = ?", t) - conn.commit() - if proposals: - title = ( - "Custom reaction proposal successfully rejected! Returning to list of current " - "reaction proposals..." + async with self.db() as db: + await db.execute( + "DELETE FROM CustomReactions WHERE CustomReactionID = ?", + (custom_react_id,) ) - footer = f"Rejected by {user}." - else: - title = "Custom reaction successfully deleted! Returning to list of current reactions..." - footer = f"Deleted by {user}." + await db.commit() + title = f"Custom {noun} successfully rejected! Returning to list of {noun}s..." + footer = f"{'Rejected' if proposals else 'Deleted'} by {user}." await message.edit(embed=discord.Embed(title=title).set_footer(text=footer, icon_url=user.avatar_url)) - conn.close() - self.rebuild_lists() + await self.rebuild_lists() await asyncio.sleep(5) # Stop From 3223b0bbb38c5d24154b821bf1788c44538b0cc5 Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Sun, 4 Sep 2022 10:03:23 -0400 Subject: [PATCH 025/127] rewrite games cog with new base cog --- canary/cogs/games.py | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/canary/cogs/games.py b/canary/cogs/games.py index eda043bd2..543407ca3 100644 --- a/canary/cogs/games.py +++ b/canary/cogs/games.py @@ -15,20 +15,19 @@ # You should have received a copy of the GNU General Public License # along with Canary. If not, see . -# discord-py requirements +import asyncio import discord -from discord.ext import commands - -# Other utilities -import re import os -import sqlite3 import pickle import random -import asyncio +import re +import sqlite3 + +from discord.ext import commands from time import time from functools import partial -from ..bot import Canary + +from .base_cog import CanaryCog from .utils.dice_roll import dice_roll from .utils.clamp_default import clamp_default from .utils.hangman import HangmanState @@ -44,9 +43,10 @@ } -class Games(commands.Cog): - def __init__(self, bot: Canary, hangman_tbl_name: str): - self.bot: Canary = bot +class Games(CanaryCog): + def __init__(self, bot, hangman_tbl_name: str): + super().__init__(bot) + self.hm_cool_win: int = bot.config.games["hm_cool_win"] self.hm_norm_win: int = bot.config.games["hm_norm_win"] self.hm_timeout: int = bot.config.games["hm_timeout"] From fa3b42a22c01c17f3ff263f7f5e9d670d546e048 Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Sun, 4 Sep 2022 10:03:40 -0400 Subject: [PATCH 026/127] rewrite helpers cog and images cog with new base cog --- canary/cogs/helpers.py | 15 ++++----------- canary/cogs/images.py | 13 +++---------- 2 files changed, 7 insertions(+), 21 deletions(-) diff --git a/canary/cogs/helpers.py b/canary/cogs/helpers.py index c42cc65d6..4264bbc17 100644 --- a/canary/cogs/helpers.py +++ b/canary/cogs/helpers.py @@ -37,7 +37,8 @@ import re import sqlite3 import time -from ..bot import Canary + +from .base_cog import CanaryCog from .utils.arg_converter import ArgConverter, StrConverter from .utils.paginator import Pages from .utils.custom_requests import fetch @@ -70,15 +71,7 @@ MAIN_WEBHOOKS_PREFIX = "Main webhook for #" -class Helpers(commands.Cog): - def __init__(self, bot: Canary): - self.bot: Canary = bot - self.guild: discord.Guild | None = None - - @commands.Cog.listener() - async def on_ready(self): - self.guild = self.bot.get_guild(self.bot.config.server_id) - +class Helpers(CanaryCog): @commands.command(aliases=["exams"]) async def exam(self, ctx: commands.Context): """Retrieves the exam schedule link from McGill's Exam website.""" @@ -341,7 +334,7 @@ async def keydates(self, ctx: commands.Context): if node.name == "ul": sections.append(node.get_text()) previous = node.previous_sibling.previous_sibling - if previous.name == "p": + if previous and previous.name == "p": headers.append(previous.get_text()) else: # just in case the layout changes again, at least the whole thing won't break diff --git a/canary/cogs/images.py b/canary/cogs/images.py index a8f124619..39ebd0872 100644 --- a/canary/cogs/images.py +++ b/canary/cogs/images.py @@ -15,28 +15,21 @@ # You should have received a copy of the GNU General Public License # along with Canary. If not, see . -# imports for Discord from discord.ext import commands -# misc imports -import os from ..bot import Canary +from .base_cog import CanaryCog from .utils import image_helpers as ih -class Images(commands.Cog): +class Images(CanaryCog): def __init__(self, bot: Canary): - self.bot: Canary = bot + super().__init__(bot) self.max_size: int = self.bot.config.images["max_image_size"] self.hist_lim: int = self.bot.config.images["image_history_limit"] self.max_rad: int = self.bot.config.images["max_radius"] self.max_itr: int = self.bot.config.images["max_iterations"] - @commands.Cog.listener() - async def on_ready(self): - if not os.path.exists("./tmp/"): - os.mkdir("./tmp/", mode=0o755) - @commands.command() async def polar(self, ctx: commands.Context): """ From 79ca287bfbb447e4afab79b6913d886537d5b437 Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Sun, 4 Sep 2022 10:04:59 -0400 Subject: [PATCH 027/127] rewrite mod cog with aiosqlite and new base cog --- canary/cogs/mod.py | 36 +++++++++++++++++++----------------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/canary/cogs/mod.py b/canary/cogs/mod.py index 07531763f..1860841c2 100644 --- a/canary/cogs/mod.py +++ b/canary/cogs/mod.py @@ -14,7 +14,7 @@ # # You should have received a copy of the GNU General Public License # along with Canary. If not, see . - +import aiosqlite import discord import sqlite3 import random @@ -22,6 +22,7 @@ from discord import utils from discord.ext import commands, tasks +from .base_cog import CanaryCog from .utils.checks import is_moderator from datetime import datetime, timedelta from .utils.role_restoration import ( @@ -35,35 +36,36 @@ from .utils.mock_context import MockContext -class Mod(commands.Cog): +class Mod(CanaryCog): def __init__(self, bot): - self.bot = bot - self.guild: discord.Guild | None = None + super().__init__(bot) + self.verification_channel: discord.TextChannel | None = None self.last_verification_purge_datetime: datetime | None = None self.muted_users_to_appeal_channels: bidict = bidict() self.appeals_log_channel: discord.TextChannel | None = None self.muted_role: discord.Role | None = None - @commands.Cog.listener() + @CanaryCog.listener() async def on_ready(self): - self.guild = self.bot.get_guild(self.bot.config.server_id) + await super().on_ready() # TODO: needed? if not self.guild: return await self.verification_purge_startup() - conn = sqlite3.connect(self.bot.config.db_path) - c = conn.cursor() - c.execute("SELECT * FROM MutedUsers") - self.muted_users_to_appeal_channels = bidict( - [ - (self.bot.get_user(user_id), self.bot.get_channel(appeal_channel_id)) - for (user_id, appeal_channel_id, roles, date) in c.fetchall() - ] - ) - conn.close() + db: aiosqlite.Connection + async with self.db() as db: + c: aiosqlite.Cursor + async with db.execute("SELECT * FROM MutedUsers") as c: + self.muted_users_to_appeal_channels = bidict( + [ + (self.bot.get_user(user_id), self.bot.get_channel(appeal_channel_id)) + for (user_id, appeal_channel_id, roles, date) in (await c.fetchall()) + ] + ) + self.appeals_log_channel = utils.get(self.guild.text_channels, name=self.bot.config.appeals_log_channel) self.muted_role = utils.get(self.guild.roles, name=self.bot.config.muted_role) @@ -312,7 +314,7 @@ async def mute_utility(self, user: discord.Member, ctx=None): # save existing roles and add muted user to database (with the attached appeal channel) # note that this function is such that if the user was already in the db, only the appeal channel is updated # (i.e, the situation where a mod had manually deleted the appeal channel) - save_existing_roles(self.bot, user, muted=True, appeal_channel=channel) + await save_existing_roles(self.bot, user, muted=True, appeal_channel=channel) # Remove all roles failed_roles: list[str] = [] From e32f5ae9f7dbe1d2ef7d22b4b457b136552e2847 Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Sun, 4 Sep 2022 10:05:13 -0400 Subject: [PATCH 028/127] change music cog to use new base cog --- canary/cogs/music.py | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/canary/cogs/music.py b/canary/cogs/music.py index c10e6d7d6..5be467856 100644 --- a/canary/cogs/music.py +++ b/canary/cogs/music.py @@ -18,17 +18,19 @@ # TODO: determine and (if possible) fix source of lack of precision in relative time skips import asyncio +import discord import random import time +import yt_dlp + +from collections import deque +from discord.ext import commands +from functools import partial from itertools import chain from inspect import getdoc -from functools import partial -from collections import deque from typing import Callable, Optional, Iterable -import discord -import yt_dlp -from discord.ext import commands -from ..bot import Canary + +from .base_cog import CanaryCog from .utils.music_helpers import ( FFMPEG_BEFORE_OPTS, FFMPEG_OPTS, @@ -47,9 +49,10 @@ ) -class Music(commands.Cog): - def __init__(self, bot: Canary): - self.bot: Canary = bot +class Music(CanaryCog): + def __init__(self, bot): + super().__init__(bot) + self.track_queue: deque[tuple[dict, str]] = deque() self.track_history: deque[tuple[dict, str]] = deque() self.looping_queue: bool = False From bb068ab2e4fea52303989e5d1f90d24a2c8f8c86 Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Sun, 4 Sep 2022 10:05:28 -0400 Subject: [PATCH 029/127] change quote cog to use aiosqlite and new base cog --- canary/cogs/quotes.py | 341 ++++++++++++++++++++++-------------------- 1 file changed, 176 insertions(+), 165 deletions(-) diff --git a/canary/cogs/quotes.py b/canary/cogs/quotes.py index 09c0327f4..ead789ff4 100644 --- a/canary/cogs/quotes.py +++ b/canary/cogs/quotes.py @@ -15,21 +15,18 @@ # You should have received a copy of the GNU General Public License # along with Canary. If not, see . -# discord.py requirements -import discord -from discord.ext import commands +import aiosqlite import asyncio - -# For DB functionality -import sqlite3 - -# For Markov Chain +import discord import numpy as np +import random import re -# Other utils -import random +from discord.ext import commands +from typing import Iterable + from ..bot import Canary +from .base_cog import CanaryCog from .utils.paginator import Pages GEN_SPACE_SYMBOLS = re.compile(r"[,“”\".?!]") @@ -40,25 +37,31 @@ DEFAULT_AVATAR = "https://cdn.discordapp.com/embed/avatars/0.png" -class Quotes(commands.Cog): +class Quotes(CanaryCog): def __init__(self, bot: Canary): - self.bot: Canary = bot + super().__init__(bot) self.mc_table: dict[str, dict] = {} - self.rebuild_mc() - def rebuild_mc(self): + @CanaryCog.listener() + async def on_ready(self): + await super().on_ready() + await self.rebuild_mc() + + async def rebuild_mc(self): """ Rebuilds the Markov Chain lookup table for use with the ?generate command. Blame David for this code. """ - conn = sqlite3.connect(self.bot.config.db_path) - c = conn.cursor() - c.execute("SELECT Quote FROM Quotes") + + db: aiosqlite.Connection + async with self.db() as db: + async with db.execute("SELECT Quote FROM Quotes") as c: + all_quotes = await c.fetchall() lookup: dict[str, dict] = {} - for q in c.fetchall(): + for q in all_quotes: # Skip URL quotes if re.search(r"https?://", q[0]): continue @@ -97,7 +100,6 @@ def rebuild_mc(self): lookup[word][option] = lookup[word][option] / total self.mc_table = lookup - conn.close() @commands.command(aliases=["addq"]) async def add_quotes( @@ -116,112 +118,118 @@ async def add_quotes( if member is None: return - conn = sqlite3.connect(self.bot.config.db_path) - c = conn.cursor() - c.execute("INSERT INTO Quotes VALUES (?,?,?,?)", (member.id, member.name, quote, str(ctx.message.created_at))) - msg = await ctx.send("Quote added.") - - conn.commit() - - # Rebuild the Markov Chain lookup table to include new quote data. - self.rebuild_mc() - - await msg.add_reaction("🚮") - - def check(reaction, user): - # returns True if all the following is true: - # The user who reacted is either the quoter or the quoted person - # The user who reacted isn't the bot - # The react is the delete emoji - # The react is on the "Quote added." message - return ( - (user == ctx.message.author or user == member) - and user != self.bot.user - and str(reaction.emoji) == "🚮" - and reaction.message.id == msg.id + db: aiosqlite.Connection + async with self.db() as db: + await db.execute( + "INSERT INTO Quotes VALUES (?,?,?,?)", (member.id, member.name, quote, str(ctx.message.created_at)) ) - try: - await self.bot.wait_for("reaction_add", check=check, timeout=120) - - except asyncio.TimeoutError: - await msg.remove_reaction("🚮", self.bot.user) + msg = await ctx.send("Quote added.") - else: - c.execute("DELETE FROM Quotes WHERE ID = ? AND Quote = ?", (member.id, quote)) - conn.commit() - self.rebuild_mc() - await msg.delete() - await ctx.send("`Quote deleted.`", delete_after=60) + await db.commit() - conn.close() - - @commands.command(aliases=["q"]) - async def quotes(self, ctx, str1: str = None, *, str2: str = None): - """ - Retrieve a quote with a specified keyword / mention. Can optionally use - regex by surrounding the the query with /.../. - """ + # Rebuild the Markov Chain lookup table to include new quote data. + await self.rebuild_mc() - conn = sqlite3.connect(self.bot.config.db_path) - c = conn.cursor() - mentions = ctx.message.mentions - - if str1 is None: # No argument passed - quotes = c.execute("SELECT ID, Name, Quote FROM Quotes").fetchall() - - elif mentions and mentions[0].mention == str1: # Has args - u_id = mentions[0].id - # Query for either user and quote or user only (None) - c.execute( - "SELECT ID, Name, Quote FROM Quotes WHERE ID = ? AND Quote " "LIKE ?", - (u_id, f"%{str2 if str2 is not None else ''}%"), - ) - quotes = c.fetchall() - - else: # query for quote only - query = str1 if str2 is None else f"{str1} {str2}" - if query[0] == "/" and query[-1] == "/": - c.execute("SELECT ID, Name, Quote FROM Quotes") - quotes = c.fetchall() - try: - quotes = [q for q in quotes if re.search(query[1:-1], q[2])] - except re.error: - conn.close() - await ctx.send("Invalid regex syntax.") - return - else: - c.execute("SELECT ID, Name, Quote FROM Quotes WHERE Quote LIKE ?", (f"%{query}%",)) - quotes = c.fetchall() - - if not quotes: - msg = await ctx.send("Quote not found.\n") - await msg.add_reaction("🆗") + await msg.add_reaction("🚮") def check(reaction, user): # returns True if all the following is true: + # The user who reacted is either the quoter or the quoted person # The user who reacted isn't the bot - # The react is the ok emoji - # The react is on the "Quote not found." message - return (user == ctx.message.author and user != self.bot.user) and ( - str(reaction.emoji) == "🆗" and reaction.message.id == msg.id + # The react is the delete emoji + # The react is on the "Quote added." message + return ( + (user == ctx.message.author or user == member) + and user != self.bot.user + and str(reaction.emoji) == "🚮" + and reaction.message.id == msg.id ) try: await self.bot.wait_for("reaction_add", check=check, timeout=120) except asyncio.TimeoutError: - await msg.remove_reaction("🆗", self.bot.user) + await msg.remove_reaction("🚮", self.bot.user) else: - await ctx.message.delete() + await db.execute("DELETE FROM Quotes WHERE ID = ? AND Quote = ?", (member.id, quote)) + await db.commit() + await self.rebuild_mc() await msg.delete() + await ctx.send("`Quote deleted.`", delete_after=60) - conn.close() - return + @commands.command(aliases=["q"]) + async def quotes(self, ctx, str1: str = None, *, str2: str = None): + """ + Retrieve a quote with a specified keyword / mention. Can optionally use + regex by surrounding the the query with /.../. + """ - conn.close() - quote_tuple = random.choice(quotes) + quotes: Iterable[aiosqlite.Row] + + db: aiosqlite.Connection + async with self.db() as db: + c: aiosqlite.Cursor + + mentions = ctx.message.mentions + + if str1 is None: # No argument passed + async with db.execute("SELECT ID, Name, Quote FROM Quotes") as c: + quotes = await c.fetchall() + + elif mentions and mentions[0].mention == str1: # Has args + u_id = mentions[0].id + # Query for either user and quote or user only (None) + async with db.execute( + "SELECT ID, Name, Quote FROM Quotes WHERE ID = ? AND Quote " "LIKE ?", + (u_id, f"%{str2 if str2 is not None else ''}%"), + ) as c: + quotes = await c.fetchall() + + else: # query for quote only + query = str1 if str2 is None else f"{str1} {str2}" + if query[0] == "/" and query[-1] == "/": + async with db.execute("SELECT ID, Name, Quote FROM Quotes") as c: + quotes = await c.fetchall() + try: + quotes = [q for q in quotes if re.search(query[1:-1], q[2])] + except re.error: + await ctx.send("Invalid regex syntax.") + return + else: + async with db.execute( + "SELECT ID, Name, Quote FROM Quotes WHERE Quote LIKE ?", + (f"%{query}%",), + ) as c: + quotes = await c.fetchall() + + if not quotes: + msg = await ctx.send("Quote not found.\n") + await msg.add_reaction("🆗") + + def check(reaction, user): + # returns True if all the following is true: + # The user who reacted isn't the bot + # The react is the ok emoji + # The react is on the "Quote not found." message + return (user == ctx.message.author and user != self.bot.user) and ( + str(reaction.emoji) == "🆗" and reaction.message.id == msg.id + ) + + try: + await self.bot.wait_for("reaction_add", check=check, timeout=120) + + except asyncio.TimeoutError: + await msg.remove_reaction("🆗", self.bot.user) + + else: + await ctx.message.delete() + await msg.delete() + + return + + quote_tuple: tuple[int, str, str] = tuple(random.choice(list(quotes))) author_id = int(quote_tuple[0]) name = quote_tuple[1] quote = quote_tuple[2] @@ -251,67 +259,69 @@ async def list_quotes(self, ctx: commands.Context, author: discord.Member = None await ctx.trigger_typing() - conn = sqlite3.connect(self.bot.config.db_path) - c = conn.cursor() + db: aiosqlite.Connection + async with self.db() as db: + c: aiosqlite.Cursor - quote_author = author if author else ctx.message.author - author_id = quote_author.id - c.execute("SELECT * FROM Quotes WHERE ID = ?", (author_id,)) - quote_list = c.fetchall() + quote_author = author if author else ctx.message.author + author_id = quote_author.id - if not quote_list: - await ctx.send("No quote found.", delete_after=60) - return + async with db.execute("SELECT * FROM Quotes WHERE ID = ?", (author_id,)) as c: + quote_list: list[aiosqlite.Row] = list(await c.fetchall()) - quote_list_text = [f"[{i}] {quote[2]}" for i, quote in enumerate(quote_list, 1)] + if not quote_list: + await ctx.send("No quote found.", delete_after=60) + return - p = Pages(ctx, item_list=quote_list_text, title="Quotes from {}".format(quote_author.display_name)) + quote_list_text = [f"[{i}] {quote[2]}" for i, quote in enumerate(quote_list, 1)] - await p.paginate() + p = Pages(ctx, item_list=quote_list_text, title="Quotes from {}".format(quote_author.display_name)) - def msg_check(msg): - try: - return ( - 0 <= int(msg.content) <= len(quote_list) - and msg.author.id == author_id - and msg.channel == ctx.message.channel - ) - except ValueError: - return False + await p.paginate() - while p.edit_mode: - await ctx.send( - "Delete option selected. Enter a number to specify which " - "quote you want to delete, or enter 0 to return.", - delete_after=60, - ) + def msg_check(msg): + try: + return ( + 0 <= int(msg.content) <= len(quote_list) + and msg.author.id == author_id + and msg.channel == ctx.message.channel + ) + except ValueError: + return False + + while p.edit_mode: + await ctx.send( + "Delete option selected. Enter a number to specify which " + "quote you want to delete, or enter 0 to return.", + delete_after=60, + ) - try: - message = await self.bot.wait_for("message", check=msg_check, timeout=60) + try: + message = await self.bot.wait_for("message", check=msg_check, timeout=60) - except asyncio.TimeoutError: - await ctx.send("Command timeout. You may want to run the command again.", delete_after=60) - break + except asyncio.TimeoutError: + await ctx.send("Command timeout. You may want to run the command again.", delete_after=60) + break - else: - index = int(message.content) - 1 - if index == -1: - await ctx.send("Exit delq.", delete_after=60) else: - t = (quote_list[index][0], quote_list[index][2]) - del quote_list[index] - c.execute("DELETE FROM Quotes WHERE ID = ? AND Quote = ?", t) - conn.commit() + index = int(message.content) - 1 + if index == -1: + await ctx.send("Exit delq.", delete_after=60) + else: + del quote_list[index] - await ctx.send("Quote deleted", delete_after=60) - await message.delete() + await db.execute( + "DELETE FROM Quotes WHERE ID = ? AND Quote = ?", + (quote_list[index][0], quote_list[index][2]), + ) + await db.commit() - p.itemList = [f"[{i}] {quote[2]}" for i, quote in enumerate(quote_list, 1)] + await ctx.send("Quote deleted", delete_after=60) + await message.delete() - await p.paginate() + p.itemList = [f"[{i}] {quote[2]}" for i, quote in enumerate(quote_list, 1)] - conn.commit() - conn.close() + await p.paginate() @commands.command(aliases=["allq", "aq"]) async def all_quotes(self, ctx: commands.Context, *, query: str): @@ -344,21 +354,22 @@ async def all_quotes(self, ctx: commands.Context, *, query: str): query = " ".join(query_splitted) await ctx.trigger_typing() - conn = sqlite3.connect(self.bot.config.db_path) - c = conn.cursor() + db: aiosqlite.Connection + async with self.db() as db: + c: aiosqlite.Cursor - if query[0] == "/" and query[-1] == "/": - c.execute("SELECT * FROM Quotes") - quotes = c.fetchall() - try: - quote_list = [q for q in quotes if re.search(query[1:-1], q[2])] - except re.error: - conn.close() - await ctx.send("Invalid regex syntax.") - return - else: - c.execute("SELECT * FROM Quotes WHERE Quote LIKE ?", (f"%{query}%",)) - quote_list = c.fetchall() + if query[0] == "/" and query[-1] == "/": + async with db.execute("SELECT * FROM Quotes") as c: + quotes = list(await c.fetchall()) + + try: + quote_list = [q for q in quotes if re.search(query[1:-1], q[2])] + except re.error: + await ctx.send("Invalid regex syntax.") + return + else: + async with db.execute("SELECT * FROM Quotes WHERE Quote LIKE ?", (f"%{query}%",)) as c: + quote_list = list(await c.fetchall()) if not quote_list: await ctx.send("No quote found.", delete_after=60) From 2b357399c32d9b727ba07d88b1fd83b2878f2dc2 Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Sun, 4 Sep 2022 10:05:42 -0400 Subject: [PATCH 030/127] change reminder cog to use new base cog --- canary/cogs/reminder.py | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/canary/cogs/reminder.py b/canary/cogs/reminder.py index 5396e5354..dde657a5f 100644 --- a/canary/cogs/reminder.py +++ b/canary/cogs/reminder.py @@ -15,21 +15,17 @@ # You should have received a copy of the GNU General Public License # along with Canary. If not, see . -# discord-py requirements -import discord -from discord.ext import commands import asyncio - -# For DB Functionality -import sqlite3 import datetime +import discord +import re +import sqlite3 -# Other utilities -from ..bot import Canary +from discord.ext import commands + +from .base_cog import CanaryCog from .utils.paginator import Pages -# For remindme functionality -import re ONES_NAMES = ("one", "two", "three", "four", "five", "six", "seven", "eight", "nine") # Haha English start at 20 @@ -91,11 +87,8 @@ FREQUENCIES = {"daily": 1, "weekly": 7, "monthly": 30} -class Reminder(commands.Cog): - def __init__(self, bot: Canary): - self.bot: Canary = bot - self.frequencies = {"daily": 1, "weekly": 7, "monthly": 30} +class Reminder(CanaryCog): async def check_reminders(self): """ Co-routine that periodically checks if the bot must issue reminders to From b0785e1388c93fa0052f369f31f822e0ec055c6d Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Sun, 4 Sep 2022 10:05:58 -0400 Subject: [PATCH 031/127] make add_member_if_needed util async --- canary/cogs/roles.py | 2 +- canary/cogs/utils/members.py | 12 +++++++----- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/canary/cogs/roles.py b/canary/cogs/roles.py index 9692f6787..093b598a4 100644 --- a/canary/cogs/roles.py +++ b/canary/cogs/roles.py @@ -280,7 +280,7 @@ async def previous_roles(self, ctx: commands.Context, user: discord.Member): @commands.Cog.listener() async def on_member_remove(self, user: discord.Member): # If the user is muted, this saves all roles BUT the muted role into the PreviousRoles table - save_existing_roles(self.bot, user, muted=is_in_muted_table(self.bot, user)) + await save_existing_roles(self.bot, user, muted=is_in_muted_table(self.bot, user)) def setup(bot): diff --git a/canary/cogs/utils/members.py b/canary/cogs/utils/members.py index 67e2d9ab8..f9babbcc2 100644 --- a/canary/cogs/utils/members.py +++ b/canary/cogs/utils/members.py @@ -15,6 +15,7 @@ # You should have received a copy of the GNU General Public License # along with Canary. If not, see . +import aiosqlite import discord @@ -32,8 +33,9 @@ async def _get_name_from_id(self, user_id) -> str: return str(user_id) -async def add_member_if_needed(self, c, user_id) -> None: - c.execute("SELECT Name FROM Members WHERE ID = ?", (user_id,)) - if not c.fetchone(): - name = await _get_name_from_id(self, user_id) - c.execute("INSERT OR IGNORE INTO Members VALUES (?,?)", (user_id, name)) +async def add_member_if_needed(self, db: aiosqlite.Connection, user_id) -> None: + c: aiosqlite.Cursor + async with db.execute("SELECT Name FROM Members WHERE ID = ?", (user_id,)) as c: + if not (await c.fetchone()): + name = await _get_name_from_id(self, user_id) + await db.execute("INSERT OR IGNORE INTO Members VALUES (?,?)", (user_id, name)) From 80f2e5b916f3447e90b9ed9fd6ca8a4e37bd4c35 Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Sun, 4 Sep 2022 10:06:08 -0400 Subject: [PATCH 032/127] change score cog to new base cog + aiosqlite --- canary/cogs/score.py | 244 ++++++++++++++++++++++--------------------- 1 file changed, 123 insertions(+), 121 deletions(-) diff --git a/canary/cogs/score.py b/canary/cogs/score.py index 84f328f18..d2842bf47 100644 --- a/canary/cogs/score.py +++ b/canary/cogs/score.py @@ -14,7 +14,7 @@ # # You should have received a copy of the GNU General Public License # along with Canary. If not, see . - +import aiosqlite # Rewritten by @le-potate # discord.py requirements @@ -27,6 +27,7 @@ # For DB functionality import sqlite3 import json +from .base_cog import CanaryCog from .utils.members import add_member_if_needed # For argument parsing @@ -145,16 +146,17 @@ async def convert(self, ctx, argument): raise commands.BadArgument("`after` flag should take an " "integer as input") -class Score(commands.Cog): +class Score(CanaryCog): def __init__(self, bot: Canary): - self.bot: Canary = bot - self.guild: discord.Guild | None = None + super().__init__(bot) + self.UPMARTLET: discord.Emoji | None = None self.DOWNMARTLET: discord.Emoji | None = None @commands.Cog.listener() async def on_ready(self): - self.guild = self.bot.get_guild(self.bot.config.server_id) + await super().on_ready() + self.UPMARTLET = discord.utils.get(self.guild.emojis, name=self.bot.config.upvote_emoji) self.DOWNMARTLET = discord.utils.get(self.guild.emojis, name=self.bot.config.downvote_emoji) @@ -308,30 +310,29 @@ async def _add_or_remove_reaction_from_db(self, payload, remove=False): except discord.errors.NotFound: return - conn = sqlite3.connect(self.bot.config.db_path) - conn.execute("PRAGMA foreign_keys = ON") - c = conn.cursor() + db: aiosqlite.Connection + async with self.db() as db: + reacter_id = self.bot.get_user(payload.user_id).id + await add_member_if_needed(self, db, reacter_id) + reactee_id = message.author.id + await add_member_if_needed(self, db, reactee_id) - reacter_id = self.bot.get_user(payload.user_id).id - await add_member_if_needed(self, c, reacter_id) - reactee_id = message.author.id - await add_member_if_needed(self, c, reactee_id) + emoji = payload.emoji - emoji = payload.emoji + if remove: + await db.execute( + "DELETE FROM Reactions WHERE ReacterID = ? AND ReacteeID = ? AND ReactionName = ? " + "AND MessageID = ?", + (reacter_id, reactee_id, str(emoji), message_id), + ) + else: + await db.execute( + "INSERT OR IGNORE INTO Reactions VALUES (?,?,?,?)", (reacter_id, reactee_id, str(emoji), message_id) + ) - if remove: - c.execute( - "DELETE FROM Reactions WHERE ReacterID = ? AND ReacteeID = ? " "AND ReactionName = ? AND MessageID = ?", - (reacter_id, reactee_id, str(emoji), message_id), - ) - else: - c.execute( - "INSERT OR IGNORE INTO Reactions VALUES (?,?,?,?)", (reacter_id, reactee_id, str(emoji), message_id) - ) - conn.commit() - conn.close() + await db.commit() - @commands.Cog.listener() + @CanaryCog.listener() async def on_raw_reaction_add(self, payload): if self.guild is None: return @@ -339,7 +340,7 @@ async def on_raw_reaction_add(self, payload): if payload.guild_id == self.guild.id: await self._add_or_remove_reaction_from_db(payload) - @commands.Cog.listener() + @CanaryCog.listener() async def on_raw_reaction_remove(self, payload): if self.guild is None: return @@ -394,27 +395,28 @@ async def score(self, ctx: commands.Context, *args): # get the WHERE conditions and the values where_str, t = self._where_str_and_values_from_args_dict(args_dict) - conn = sqlite3.connect(self.bot.config.db_path) - c = conn.cursor() - if args_dict["emojitype"] != "score": - c.execute(f"SELECT count(ReacteeID) FROM Reactions " f"WHERE {where_str}", t) - react_count = c.fetchone()[0] - else: - c.execute( - ( - f"SELECT COUNT(IIF (ReactionName = ?1, 1, NULL)) - " - f"COUNT(IIF (ReactionName = ?2, 1, NULL)) " - f"FROM Reactions " - f"WHERE {where_str} " - f"AND (ReactionName = ?1 OR ReactionName=?2) " - ), - (str(self.UPMARTLET), str(self.DOWNMARTLET), *t), - ) - react_count = c.fetchone()[0] - await ctx.send(react_count) + db: aiosqlite.Connection + async with self.db() as db: + c: aiosqlite.Cursor + + if args_dict["emojitype"] != "score": + async with db.execute(f"SELECT count(ReacteeID) FROM Reactions " f"WHERE {where_str}", t) as c: + react_count = (await c.fetchone())[0] + else: + async with db.execute( + ( + f"SELECT COUNT(IIF (ReactionName = ?1, 1, NULL)) - " + f"COUNT(IIF (ReactionName = ?2, 1, NULL)) " + f"FROM Reactions " + f"WHERE {where_str} " + f"AND (ReactionName = ?1 OR ReactionName=?2) " + ), + (str(self.UPMARTLET), str(self.DOWNMARTLET), *t), + ) as c: + react_count = (await c.fetchone())[0] - conn.close() + await ctx.send(react_count) @commands.command() async def ranking(self, ctx, *args): @@ -453,8 +455,6 @@ async def ranking(self, ctx, *args): -"nothere" (All custom emoji not in the server), -"score" (The emojis used as upvotes and downvotes) """ - conn = sqlite3.connect(self.bot.config.db_path) - c = conn.cursor() try: args_dict = await self._get_converted_args_dict(ctx, args, from_nand_to=True, member=False) @@ -462,62 +462,63 @@ async def ranking(self, ctx, *args): await ctx.send(err) return - if not args_dict["to_member"]: - select_id = "ReacteeID" - else: - select_id = "ReacterID" - if args_dict["emojitype"] != "score": - # get the WHERE conditions and the values - where_str, t = self._where_str_and_values_from_args_dict(args_dict) - c.execute( - ( - f"SELECT printf('%d. %s', " - f"ROW_NUMBER() OVER (ORDER BY count(*) DESC), M.Name), " - f"printf('%d %s', count(*), " - f"IIF (count(*)!=1, 'times', 'time')) " - f"FROM Reactions AS R, Members as M " - f"WHERE {where_str} " - f"AND R.{select_id} = M.ID " - f"GROUP BY R.{select_id} " - f"ORDER BY count(*) DESC" - ), - t, - ) - - counts = list(zip(*c.fetchall())) - if not counts: - await ctx.send(embed=discord.Embed(title="This reaction was never used on this server.")) - return - names, values = counts + db: aiosqlite.Connection + async with self.db() as db: + c: aiosqlite.Cursor + + select_id = "ReacterID" if args_dict["to_member"] else "ReacteeID" + + if args_dict["emojitype"] != "score": + # get the WHERE conditions and the values + where_str, t = self._where_str_and_values_from_args_dict(args_dict) + async with db.execute( + ( + f"SELECT printf('%d. %s', " + f"ROW_NUMBER() OVER (ORDER BY count(*) DESC), M.Name), " + f"printf('%d %s', count(*), " + f"IIF (count(*)!=1, 'times', 'time')) " + f"FROM Reactions AS R, Members as M " + f"WHERE {where_str} " + f"AND R.{select_id} = M.ID " + f"GROUP BY R.{select_id} " + f"ORDER BY count(*) DESC" + ), + t, + ) as c: + counts = list(zip(*(await c.fetchall()))) + + if not counts: + await ctx.send(embed=discord.Embed(title="This reaction was never used on this server.")) + return + + else: + # get the WHERE conditions and the values + where_str, t = self._where_str_and_values_from_args_dict(args_dict, prefix="R") + async with db.execute( + ( + f"SELECT printf('%d. %s', " + f"ROW_NUMBER() OVER (ORDER BY TotalCount DESC), Name), " + f"TotalCount FROM " + f"(SELECT M.Name, " + f"COUNT(IIF (ReactionName = ?1, 1, NULL)) - " + f"COUNT(IIF (ReactionName = ?2, 1, NULL)) " + f"AS TotalCount " + f"FROM Reactions AS R, Members as M " + f"WHERE {where_str} " + f"AND (ReactionName = ?1 OR ReactionName=?2) " + f"AND R.{select_id} = M.ID " + f"GROUP BY R.{select_id})" + ), + (str(self.UPMARTLET), str(self.DOWNMARTLET), *t), + ) as c: + counts = list(zip(*(await c.fetchall()))) + + if not counts: + await ctx.send(embed=discord.Embed(title="No results found")) + return + + names, values = counts - else: - # get the WHERE conditions and the values - where_str, t = self._where_str_and_values_from_args_dict(args_dict, prefix="R") - c.execute( - ( - f"SELECT printf('%d. %s', " - f"ROW_NUMBER() OVER (ORDER BY TotalCount DESC), Name), " - f"TotalCount FROM " - f"(SELECT M.Name, " - f"COUNT(IIF (ReactionName = ?1, 1, NULL)) - " - f"COUNT(IIF (ReactionName = ?2, 1, NULL)) " - f"AS TotalCount " - f"FROM Reactions AS R, Members as M " - f"WHERE {where_str} " - f"AND (ReactionName = ?1 OR ReactionName=?2) " - f"AND R.{select_id} = M.ID " - f"GROUP BY R.{select_id})" - ), - (str(self.UPMARTLET), str(self.DOWNMARTLET), *t), - ) - counts = list(zip(*c.fetchall())) - if not counts: - await ctx.send(embed=discord.Embed(title="No results found")) - return - names = counts[0] - values = counts[1] - - conn.close() paginator_dict = {"names": names, "values": values} p = Pages(ctx, item_list=paginator_dict, title="Score ranking", display_option=(2, 9), editable_content=False) @@ -555,8 +556,6 @@ async def emojiranking(self, ctx: commands.Context, *args): -"here" (All custom emojis in the server), -"nothere" (All custom emoji not in the server) """ - conn = sqlite3.connect(self.bot.config.db_path) - c = conn.cursor() try: args_dict = await self._get_converted_args_dict(ctx, args, from_xnor_to=True, member=False, emoji=False) @@ -568,27 +567,30 @@ async def emojiranking(self, ctx: commands.Context, *args): await ctx.send("Invalid input: Emojitype flag cannot use " "type score for this function") # get the WHERE conditions and the values where_str, t = self._where_str_and_values_from_args_dict(args_dict) - c.execute( - ( - f"SELECT printf('%d. %s', " - f"ROW_NUMBER() OVER (ORDER BY count(*) DESC), " - f"ReactionName), printf('%d %s', count(*), " - f"IIF (count(*)!=1, 'times', 'time')) " - f"FROM Reactions " - f"WHERE {where_str} " - f"GROUP BY ReactionName " - ), - t, - ) - - counts = list(zip(*c.fetchall())) + + db: aiosqlite.Connection + async with self.db() as db: + c: aiosqlite.Cursor + async with db.execute( + ( + f"SELECT printf('%d. %s', " + f"ROW_NUMBER() OVER (ORDER BY count(*) DESC), " + f"ReactionName), printf('%d %s', count(*), " + f"IIF (count(*)!=1, 'times', 'time')) " + f"FROM Reactions " + f"WHERE {where_str} " + f"GROUP BY ReactionName " + ), + t, + ) as c: + counts = list(zip(*(await c.fetchall()))) + if not counts: await ctx.send(embed=discord.Embed(title="No results found")) return - names = counts[0] - values = counts[1] - conn.close() + names, values = counts + paginator_dict = {"names": names, "values": values} p = Pages(ctx, item_list=paginator_dict, title="Emoji ranking", display_option=(2, 9), editable_content=False) From 90e2e877c880f71cd2415a5ed38100764829100c Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Sun, 4 Sep 2022 10:06:13 -0400 Subject: [PATCH 033/127] comment --- canary/cogs/base_cog.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/canary/cogs/base_cog.py b/canary/cogs/base_cog.py index f857b94c2..c2fa192e4 100644 --- a/canary/cogs/base_cog.py +++ b/canary/cogs/base_cog.py @@ -21,6 +21,8 @@ def __init__(self, bot: Canary): @commands.Cog.listener() async def on_ready(self): self.guild = self.bot.get_guild(self.bot.config.server_id) + + # Make temporary directory, used mostly by images cog if not os.path.exists("./tmp/"): os.mkdir("./tmp/", mode=0o755) From 11e73c50d509b806bd1d560b3927858e324150a5 Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Sun, 4 Sep 2022 10:08:23 -0400 Subject: [PATCH 034/127] move Reminder.check_reminders to aiosqlite --- canary/cogs/reminder.py | 72 +++++++++++++++++++++-------------------- 1 file changed, 37 insertions(+), 35 deletions(-) diff --git a/canary/cogs/reminder.py b/canary/cogs/reminder.py index dde657a5f..e94c8aa54 100644 --- a/canary/cogs/reminder.py +++ b/canary/cogs/reminder.py @@ -17,6 +17,8 @@ import asyncio import datetime + +import aiosqlite import discord import re import sqlite3 @@ -101,42 +103,42 @@ async def check_reminders(self): if not (guild := self.guild): return - conn = sqlite3.connect(self.bot.config.db_path) - c = conn.cursor() - reminders = c.execute("SELECT * FROM Reminders").fetchall() - for i in range(len(reminders)): - member = discord.utils.get(guild.members, id=reminders[i][0]) - - # If non-repeating reminder is found - if reminders[i][3] == "once": - # Check date to remind user - reminder_activation_date = datetime.datetime.strptime(reminders[i][4], "%Y-%m-%d %H:%M:%S.%f") - # Compute future_date and current_date and if past, means - # time is due to remind user. - if reminder_activation_date <= datetime.datetime.now(): - await member.send("Reminding you to {}!".format(reminders[i][2])) - # Remove from from DB non-repeating reminder - c.execute( - ("DELETE FROM Reminders WHERE Reminder=? AND ID=?" + " AND DATE=?"), - (reminders[i][2], reminders[i][0], reminder_activation_date), - ) - conn.commit() - await asyncio.sleep(1) - - else: - last_date = datetime.datetime.strptime(reminders[i][5], "%Y-%m-%d %H:%M:%S.%f") - - if datetime.datetime.now() - last_date > datetime.timedelta(days=FREQUENCIES[reminders[i][3]]): - await member.send(f"Reminding you to {reminders[i][2]}! [{i + 1:d}]") - - c.execute( - ("UPDATE 'Reminders' SET LastReminder=? WHERE " + "Reminder=?"), - (datetime.datetime.now(), reminders[i][2]), - ) - conn.commit() - await asyncio.sleep(1) + db: aiosqlite.Connection + async with self.db() as db: + async with db.execute("SELECT * FROM Reminders") as c: + reminders = [tuple(r) for r in await c.fetchall()] + + for i in range(len(reminders)): + member = discord.utils.get(guild.members, id=reminders[i][0]) + + # If non-repeating reminder is found + if reminders[i][3] == "once": + # Check date to remind user + reminder_activation_date = datetime.datetime.strptime(reminders[i][4], "%Y-%m-%d %H:%M:%S.%f") + # Compute future_date and current_date and if past, means + # time is due to remind user. + if reminder_activation_date <= datetime.datetime.now(): + await member.send("Reminding you to {}!".format(reminders[i][2])) + # Remove from from DB non-repeating reminder + await db.execute( + ("DELETE FROM Reminders WHERE Reminder=? AND ID=?" + " AND DATE=?"), + (reminders[i][2], reminders[i][0], reminder_activation_date), + ) + await db.commit() + await asyncio.sleep(1) + + else: + last_date = datetime.datetime.strptime(reminders[i][5], "%Y-%m-%d %H:%M:%S.%f") + + if datetime.datetime.now() - last_date > datetime.timedelta(days=FREQUENCIES[reminders[i][3]]): + await member.send(f"Reminding you to {reminders[i][2]}! [{i + 1:d}]") + await db.execute( + ("UPDATE 'Reminders' SET LastReminder=? WHERE " + "Reminder=?"), + (datetime.datetime.now(), reminders[i][2]), + ) + await db.commit() + await asyncio.sleep(1) - conn.close() await asyncio.sleep(60) # seconds @commands.command(aliases=["rm", "rem"]) From b81a0265186dcb1b80d6441555459932de3f9d6a Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Sun, 4 Sep 2022 10:46:33 -0400 Subject: [PATCH 035/127] convert mod cog to use aiosqlite --- canary/cogs/mod.py | 76 ++++++++++++++++++---------------------------- 1 file changed, 30 insertions(+), 46 deletions(-) diff --git a/canary/cogs/mod.py b/canary/cogs/mod.py index 1860841c2..a053f329f 100644 --- a/canary/cogs/mod.py +++ b/canary/cogs/mod.py @@ -16,7 +16,6 @@ # along with Canary. If not, see . import aiosqlite import discord -import sqlite3 import random from bidict import bidict from discord import utils @@ -56,8 +55,8 @@ async def on_ready(self): await self.verification_purge_startup() db: aiosqlite.Connection + c: aiosqlite.Cursor async with self.db() as db: - c: aiosqlite.Cursor async with db.execute("SELECT * FROM MutedUsers") as c: self.muted_users_to_appeal_channels = bidict( [ @@ -77,22 +76,18 @@ async def verification_purge_startup(self): # arbitrary min date because choosing dates that predate discord will cause an httpexception # when fetching message history after that date later on self.last_verification_purge_datetime = datetime(2018, 1, 1) - conn = sqlite3.connect(self.bot.config.db_path) - c = conn.cursor() - c.execute("SELECT Value FROM Settings WHERE Key = ?", ("last_verification_purge_timestamp",)) - fetched = c.fetchone() + + fetched = await self.get_settings_key("last_verification_purge_timestamp") if fetched: - last_purge_timestamp = float(fetched[0]) + last_purge_timestamp = float(fetched) if last_purge_timestamp: self.last_verification_purge_datetime = datetime.fromtimestamp(last_purge_timestamp) else: # the verification purge info setting has not been added to db yet - c.execute( - "INSERT INTO Settings VALUES (?, ?)", - ("last_verification_purge_timestamp", self.last_verification_purge_datetime.timestamp()), + await self.set_settings_key( + "last_verification_purge_timestamp", + str(self.last_verification_purge_datetime.timestamp()) ) - conn.commit() - conn.close() self.check_verification_purge.start() @@ -105,19 +100,11 @@ async def check_verification_purge(self): if datetime.now() < self.last_verification_purge_datetime + timedelta(days=7): return - conn = sqlite3.connect(self.bot.config.db_path) - c = conn.cursor() # delete everything since the day of the last purge, including that day itself await self.verification_purge_utility(self.last_verification_purge_datetime - timedelta(days=1)) # update info - c.execute("SELECT Value FROM Settings WHERE Key = ?", ("last_verification_purge_timestamp",)) - fetched = c.fetchone() - if fetched: - c.execute( - "REPLACE INTO Settings VALUES (?, ?)", ("last_verification_purge_timestamp", datetime.now().timestamp()) - ) - conn.commit() - conn.close() + if (await self.get_settings_key("last_verification_purge_timestamp")) is not None: + await self.set_settings_key("last_verification_purge_timestamp", str(datetime.now().timestamp())) @commands.command() async def answer(self, ctx: commands.Context, *args): @@ -153,22 +140,18 @@ async def pm(self, ctx: commands.Context, user: discord.User, *, message): async def initiate_crabbo(self, ctx: commands.Context): """Initiates secret crabbo ceremony""" - conn = sqlite3.connect(self.bot.config.db_path) - c = conn.cursor() - c.execute("SELECT Value FROM Settings WHERE Key = ?", ("CrabboMsgID",)) - if c.fetchone(): + if (await self.get_settings_key("CrabboMsgID")) is not None: await ctx.send("secret crabbo has already been started.") - conn.close() return + crabbo_msg = await ctx.send( "🦀🦀🦀 crabbo time 🦀🦀🦀\n<@&" f"{discord.utils.get(ctx.guild.roles, name=self.bot.config.crabbo_role).id}" "> react to this message with 🦀 to enter the secret crabbo festival\n" "🦀🦀🦀 crabbo time 🦀🦀🦀" ) - c.execute("REPLACE INTO Settings VALUES (?, ?)", ("CrabboMsgID", crabbo_msg.id)) - conn.commit() - conn.close() + + await self.set_settings_key("CrabboMsgID", str(crabbo_msg.id)) await ctx.message.delete() @commands.command() @@ -176,24 +159,24 @@ async def initiate_crabbo(self, ctx: commands.Context): async def finalize_crabbo(self, ctx: commands.Context): """Sends crabbos their secret crabbo""" - conn = sqlite3.connect(self.bot.config.db_path) - c = conn.cursor() - c.execute("SELECT Value FROM Settings WHERE Key = ?", ("CrabboMsgID",)) - msg_id = c.fetchone() - c.execute("DELETE FROM Settings WHERE Key = ?", ("CrabboMsgID",)) - conn.commit() - conn.close() + msg_id = await self.get_settings_key("CrabboMsgId") + if not msg_id: await ctx.send("secret crabbo is not currently occurring.") return + + await self.del_settings_key("CrabboMsgId") + crabbos = None - for react in (await ctx.fetch_message(int(msg_id[0]))).reactions: + for react in (await ctx.fetch_message(int(msg_id))).reactions: if str(react) == "🦀": crabbos = await react.users().flatten() break + if crabbos is None or (num_crabbos := len(crabbos)) < 2: await ctx.send("not enough people participated in the secret crabbo festival.") return + random.shuffle(crabbos) for index, crabbo in enumerate(crabbos): await self.bot.get_user(crabbo.id).send( @@ -325,6 +308,7 @@ async def mute_utility(self, user: discord.Member, ctx=None): await user.remove_roles(role, reason=reason_message) except (discord.Forbidden, discord.HTTPException): failed_roles.append(str(role)) + # update dict self.muted_users_to_appeal_channels[user] = channel @@ -367,7 +351,7 @@ async def unmute_utility(self, user: discord.Member, ctx: discord.ext.commands.C ) # Remove entry from the database - remove_from_muted_table(self.bot, user) + await remove_from_muted_table(self.bot, user) # Delete appeal channel if user in self.muted_users_to_appeal_channels: @@ -406,7 +390,7 @@ async def unmute(self, ctx: commands.Context, user: discord.Member): """ await self.unmute_utility(user, ctx=ctx) - @commands.Cog.listener() + @CanaryCog.listener() async def on_member_update(self, before, after): muted_role_before = self.muted_role in before.roles muted_role_after = self.muted_role in after.roles @@ -416,7 +400,7 @@ async def on_member_update(self, before, after): not muted_role_before and muted_role_after and not ( - is_in_muted_table(self.bot, after) + (await is_in_muted_table(self.bot, after)) and has_muted_role(after) and after in self.muted_users_to_appeal_channels and self.muted_users_to_appeal_channels[after] in self.guild.text_channels @@ -429,7 +413,7 @@ async def on_member_update(self, before, after): muted_role_before and not muted_role_after and ( - is_in_muted_table(self.bot, after) + (await is_in_muted_table(self.bot, after)) or has_muted_role(after) or after in self.muted_users_to_appeal_channels ) @@ -437,7 +421,7 @@ async def on_member_update(self, before, after): await self.unmute_utility(after) # the next three functions are used for appeals logging - @commands.Cog.listener() + @CanaryCog.listener() async def on_message(self, message): if message.channel not in self.muted_users_to_appeal_channels.values(): return @@ -460,7 +444,7 @@ async def on_message(self, message): await self.appeals_log_channel.send(log_message) - @commands.Cog.listener() + @CanaryCog.listener() async def on_message_edit(self, before, after): if after.channel not in self.muted_users_to_appeal_channels.values(): return @@ -483,7 +467,7 @@ async def on_message_edit(self, before, after): await self.appeals_log_channel.send(log_message) - @commands.Cog.listener() + @CanaryCog.listener() async def on_message_delete(self, message): if message.channel not in self.muted_users_to_appeal_channels.values(): return @@ -503,7 +487,7 @@ async def on_message_delete(self, message): await self.appeals_log_channel.send(log_message) - @commands.Cog.listener() + @CanaryCog.listener() async def on_member_join(self, user: discord.Member): # If the user was already muted, restore the muted role if is_in_muted_table(self.bot, user): From 800612c4e8e38f83f104ddf6d0cb5a2127fa68ba Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Sun, 4 Sep 2022 10:46:44 -0400 Subject: [PATCH 036/127] convert reminder cog to use aiosqlite --- canary/cogs/reminder.py | 147 +++++++++++++++++++--------------------- 1 file changed, 68 insertions(+), 79 deletions(-) diff --git a/canary/cogs/reminder.py b/canary/cogs/reminder.py index e94c8aa54..e318cf064 100644 --- a/canary/cogs/reminder.py +++ b/canary/cogs/reminder.py @@ -21,7 +21,6 @@ import aiosqlite import discord import re -import sqlite3 from discord.ext import commands @@ -106,7 +105,7 @@ async def check_reminders(self): db: aiosqlite.Connection async with self.db() as db: async with db.execute("SELECT * FROM Reminders") as c: - reminders = [tuple(r) for r in await c.fetchall()] + reminders = [tuple(r) for r in (await c.fetchall())] for i in range(len(reminders)): member = discord.utils.get(guild.members, id=reminders[i][0]) @@ -129,7 +128,7 @@ async def check_reminders(self): else: last_date = datetime.datetime.strptime(reminders[i][5], "%Y-%m-%d %H:%M:%S.%f") - + if datetime.datetime.now() - last_date > datetime.timedelta(days=FREQUENCIES[reminders[i][3]]): await member.send(f"Reminding you to {reminders[i][2]}! [{i + 1:d}]") await db.execute( @@ -149,6 +148,9 @@ async def remindme(self, ctx: commands.Context, *, quote: str = ""): when keyword "daily", "weekly" or "monthly" is found. """ + db: aiosqlite.Connection + c: aiosqlite.Cursor + if quote == "": await ctx.send( "**Usage:** \n`?remindme in 1 hour and 20 minutes and 20 " @@ -238,34 +240,31 @@ async def remindme(self, ctx: commands.Context, *, quote: str = ""): reminder = reminder[time_input_end + 1 :].strip() # Add message to database - conn = sqlite3.connect(self.bot.config.db_path) - c = conn.cursor() - t = ( - ctx.message.author.id, - ctx.message.author.name, - reminder, - "once", - absolute_duedate, - datetime.datetime.now(), - ) - - c.execute("INSERT INTO Reminders VALUES (?, ?, ?, ?, ?, ?)", t) - - # Send user information and close database - reminders = c.execute("SELECT * FROM Reminders WHERE ID =?", (ctx.message.author.id,)).fetchall() - await ctx.author.send( - "Hi {}! \nI will remind you to {} on {} at {} unless you " - "send me a message to stop reminding you about it! " - "[{:d}]".format( - ctx.author.name, reminder, date_result.group(0), time_result.group(0), len(reminders) + 1 + async with self.db() as db: + t = ( + ctx.message.author.id, + ctx.message.author.name, + reminder, + "once", + absolute_duedate, + datetime.datetime.now(), + ) + await db.execute("INSERT INTO Reminders VALUES (?, ?, ?, ?, ?, ?)", t) + await db.commit() + + # Send user information and close database + async with db.execute("SELECT * FROM Reminders WHERE ID =?", (ctx.message.author.id,)) as c: + reminders = [tuple(r) for r in (await c.fetchall())] + + await ctx.author.send( + "Hi {}! \nI will remind you to {} on {} at {} unless you " + "send me a message to stop reminding you about it! " + "[{:d}]".format( + ctx.author.name, reminder, date_result.group(0), time_result.group(0), len(reminders) + 1 + ) ) - ) await ctx.send("Reminder added.") - - conn.commit() - conn.close() - return # Wrong input feedback depending on what is missing. @@ -311,13 +310,13 @@ async def remindme(self, ctx: commands.Context, *, quote: str = ""): # DB: Date will hold TDELTA (When reminder is due), LastReminder will # hold datetime.datetime.now() - conn = sqlite3.connect(self.bot.config.db_path) - c = conn.cursor() - t = (ctx.message.author.id, ctx.message.author.name, reminder, "once", reminder_time, time_now) - - reminders = c.execute("SELECT * FROM Reminders WHERE ID =?", (ctx.message.author.id,)).fetchall() + async with self.db() as db: + async with db.execute("SELECT * FROM Reminders WHERE ID =?", (ctx.message.author.id,)) as c: + reminders = [tuple(r) for r in (await c.fetchall())] - c.execute("INSERT INTO Reminders VALUES (?, ?, ?, ?, ?, ?)", t) + t = (ctx.message.author.id, ctx.message.author.name, reminder, "once", reminder_time, time_now) + await db.execute("INSERT INTO Reminders VALUES (?, ?, ?, ?, ?, ?)", t) + await db.commit() # Gets reminder date in YYYY-MM-DD format due_date = str(datetime.date(reminder_time.year, reminder_time.month, reminder_time.day)) @@ -332,9 +331,6 @@ async def remindme(self, ctx: commands.Context, *, quote: str = ""): ) await ctx.send("Reminder added.") - conn.commit() - conn.close() - @staticmethod def formatted_reminder_list(rem_list): return [ @@ -353,6 +349,9 @@ async def list_reminders(self, ctx): List reminders """ + db: aiosqlite.Connection + c: aiosqlite.Cursor + await ctx.trigger_typing() if not isinstance(ctx.message.channel, discord.DMChannel): @@ -362,24 +361,20 @@ async def list_reminders(self, ctx): ) return - conn = sqlite3.connect(self.bot.config.db_path) - c = conn.cursor() - rem_author = ctx.message.author - author_id = rem_author.id - c.execute("SELECT * FROM Reminders WHERE ID = ?", (author_id,)) - rem_list = c.fetchall() + async with self.db() as db: + async with db.execute("SELECT * FROM Reminders WHERE ID = ?", (rem_author.id,)) as c: + rem_list = [tuple(r) for r in (await c.fetchall())] + if not rem_list: await ctx.send("No reminder found.", delete_after=60) - conn.commit() - conn.close() return p = Pages( ctx, item_list=self.formatted_reminder_list(rem_list), - title="{}'s reminders".format(rem_author.display_name), + title=f"{rem_author.display_name}'s reminders", ) await p.paginate() @@ -388,7 +383,7 @@ def msg_check(msg): try: return ( 0 <= int(msg.content) <= len(rem_list) - and msg.author.id == author_id + and msg.author.id == rem_author.id and msg.channel == ctx.message.channel ) @@ -417,12 +412,15 @@ def msg_check(msg): await ctx.send("Exit delq.", delete_after=60) else: - t = (rem_list[index][0], rem_list[index][2]) # Remove deleted reminder from list: del rem_list[index] - c.execute("DELETE FROM Reminders WHERE ID = ? AND " "Reminder = ?", t) - conn.commit() + async with self.db() as db: + await db.execute( + "DELETE FROM Reminders WHERE ID = ? AND " "Reminder = ?", + (rem_list[index][0], rem_list[index][2]) + ) + await db.commit() await ctx.send("Reminder deleted", delete_after=60) @@ -430,15 +428,15 @@ def msg_check(msg): await p.paginate() - conn.commit() - conn.close() - async def __remindme_repeating(self, ctx: commands.Context, freq: str = "", *, quote: str = ""): """ Called by remindme to add a repeating reminder to the reminder database. """ + db: aiosqlite.Connection + c: aiosqlite.Cursor + bad_input = False freq = freq.strip() @@ -459,34 +457,28 @@ async def __remindme_repeating(self, ctx: commands.Context, freq: str = "", *, q if bad_input: return - conn = sqlite3.connect(self.bot.config.db_path) - c = conn.cursor() - - t = ( - ctx.message.author.id, - ctx.message.author.name, - quote, - freq, - datetime.datetime.now(), - datetime.datetime.now(), - ) + async with self.db() as db: + async with db.execute( + "SELECT * FROM Reminders WHERE Reminder = ? AND ID = ?", (quote, ctx.message.author.id) + ) as c: + existing_reminder = c.fetchone() - reminders = c.execute( - "SELECT * FROM Reminders WHERE Reminder = ? AND ID = ?", (quote, ctx.message.author.id) - ).fetchall() - - if len(reminders) > 0: + if existing_reminder is not None: await ctx.send( - "The reminder `{}` already exists in your database. Please " - "specify a unique reminder message!".format(quote) + f"The reminder `{quote}` already exists in your database. Please specify a unique reminder message!" ) - conn.commit() - conn.close() return - reminders = c.execute("SELECT * FROM Reminders WHERE ID = ?", (ctx.message.author.id,)).fetchall() + msg_author = ctx.message.author + async with self.db() as db: + async with db.execute("SELECT COUNT(*) FROM Reminders WHERE ID = ?", (msg_author.id,)) as c: + # noinspection PyRedundantParentheses + num_reminders = ((await c.fetchone()) or (0,))[0] - c.execute("INSERT INTO Reminders VALUES (?, ?, ?, ?, ?, ?)", t) + now = datetime.datetime.now() + t = (msg_author.id, msg_author.name, quote, freq, now, now) + await db.execute("INSERT INTO Reminders VALUES (?, ?, ?, ?, ?, ?)", t) + await db.commit() # Strips the string "to " from reminder messages if quote[:3].lower() == "to ": @@ -494,14 +486,11 @@ async def __remindme_repeating(self, ctx: commands.Context, freq: str = "", *, q await ctx.author.send( "Hi {}! \nI will remind you to {} {} until you send me a message " - "to stop reminding you about it! [{:d}]".format(ctx.author.name, quote, freq, len(reminders) + 1) + "to stop reminding you about it! [{:d}]".format(ctx.author.name, quote, freq, num_reminders + 1) ) await ctx.send("Reminder added.") - conn.commit() - conn.close() - def setup(bot): database = Reminder(bot) From 1fa6c879918c76b9b348cf51c371c0481419563b Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Sun, 4 Sep 2022 10:46:54 -0400 Subject: [PATCH 037/127] type hints for roles cog --- canary/cogs/roles.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/canary/cogs/roles.py b/canary/cogs/roles.py index 093b598a4..03c80a60d 100644 --- a/canary/cogs/roles.py +++ b/canary/cogs/roles.py @@ -215,7 +215,7 @@ async def roles(self, ctx, user: discord.Member = None): ) @commands.command(aliases=["inrole"]) - async def in_role(self, ctx: commands.Context, *, query_role): + async def in_role(self, ctx: commands.Context, *, query_role: str): """Returns list of users in the specified role""" role = next((role for role in ctx.guild.roles if role.name.lower() == query_role.lower()), None) @@ -238,7 +238,7 @@ async def in_role(self, ctx: commands.Context, *, query_role): @commands.command(aliases=["cr", "createrole"]) @is_moderator() - async def create_role(self, ctx: commands.Context, *, role: Optional[str] = None): + async def create_role(self, ctx: commands.Context, *, role: str | None = None): role = (role or "").strip() if not role: await ctx.send("Please specify a role name.") @@ -280,7 +280,7 @@ async def previous_roles(self, ctx: commands.Context, user: discord.Member): @commands.Cog.listener() async def on_member_remove(self, user: discord.Member): # If the user is muted, this saves all roles BUT the muted role into the PreviousRoles table - await save_existing_roles(self.bot, user, muted=is_in_muted_table(self.bot, user)) + await save_existing_roles(self.bot, user, muted=await is_in_muted_table(self.bot, user)) def setup(bot): From 9292a23e0b2bc44c7770b257f2cce4e9e1eda759 Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Sun, 4 Sep 2022 10:47:02 -0400 Subject: [PATCH 038/127] remove unused import in score cog --- canary/cogs/score.py | 1 - 1 file changed, 1 deletion(-) diff --git a/canary/cogs/score.py b/canary/cogs/score.py index d2842bf47..53b53f2de 100644 --- a/canary/cogs/score.py +++ b/canary/cogs/score.py @@ -25,7 +25,6 @@ from ..bot import Canary # For DB functionality -import sqlite3 import json from .base_cog import CanaryCog from .utils.members import add_member_if_needed From c21329d65d9d56334244ccaf00edb4e0b4f45c40 Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Sun, 4 Sep 2022 10:47:16 -0400 Subject: [PATCH 039/127] cleanup in role check utils --- canary/cogs/utils/checks.py | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/canary/cogs/utils/checks.py b/canary/cogs/utils/checks.py index 7deb62fba..5ebe942ae 100644 --- a/canary/cogs/utils/checks.py +++ b/canary/cogs/utils/checks.py @@ -1,7 +1,4 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- -# -# Copyright (C) idoneam (2016-2019) +# Copyright (C) idoneam (2016-2022) # # This file is part of Canary # @@ -27,9 +24,8 @@ def is_moderator(): """Returns True if user has a moderator role, raises an exception otherwise""" - def predicate(ctx): - role = discord.utils.get(ctx.author.roles, name=moderator_role) - if role is None: + def predicate(ctx: commands.Context): + if discord.utils.get(ctx.author.roles, name=moderator_role) is None: raise commands.MissingPermissions([moderator_role]) return True @@ -39,9 +35,8 @@ def predicate(ctx): def is_developer(): """Returns True if user is a bot developer, raises an exception otherwise""" - def predicate(ctx): - role = discord.utils.get(ctx.author.roles, name=developer_role) - if role is None: + def predicate(ctx: commands.Context): + if discord.utils.get(ctx.author.roles, name=developer_role) is None: raise commands.MissingPermissions([developer_role]) return True From d05f596eeb400d01f2e0c5bba004defd1289c4ce Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Sun, 4 Sep 2022 10:47:26 -0400 Subject: [PATCH 040/127] add settings key del function in base cog --- canary/cogs/base_cog.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/canary/cogs/base_cog.py b/canary/cogs/base_cog.py index c2fa192e4..e9f459626 100644 --- a/canary/cogs/base_cog.py +++ b/canary/cogs/base_cog.py @@ -50,3 +50,15 @@ async def set_settings_key(self, key: str, value: str, pre_commit: Iterable | No await db.execute(s) await db.commit() + + async def del_settings_key(self, key: str, pre_commit: Iterable | None = None) -> None: + db: aiosqlite.Connection + async with self.db() as db: + c: aiosqlite.Cursor + await db.execute("DELETE FROM Settings WHERE Key = ? LIMIT 1", (key,)) + + if pre_commit: + for s in pre_commit: + await db.execute(s) + + await db.commit() From 852d36b1535ece6756785a2ba798244dfc911327 Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Sun, 4 Sep 2022 10:47:35 -0400 Subject: [PATCH 041/127] convert games cog to aiosqlite --- canary/cogs/games.py | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/canary/cogs/games.py b/canary/cogs/games.py index 543407ca3..6598579fa 100644 --- a/canary/cogs/games.py +++ b/canary/cogs/games.py @@ -16,12 +16,13 @@ # along with Canary. If not, see . import asyncio + +import aiosqlite import discord import os import pickle import random import re -import sqlite3 from discord.ext import commands from time import time @@ -222,16 +223,16 @@ async def hangman(self, ctx, command: str | None = None): del self.hm_locks[ctx.message.channel] if winner is not None: - conn = sqlite3.connect(self.bot.config.db_path) - await self.bot.get_cog("Currency").create_bank_transaction( - conn.cursor(), - winner, - self.hm_cool_win if cool_win else self.hm_norm_win, - HANGMAN_REWARD, - {"cool": cool_win}, - ) - conn.commit() - conn.close() + db: aiosqlite.Connection + async with self.db() as db: + await self.bot.get_cog("Currency").create_bank_transaction( + db, + winner, + self.hm_cool_win if cool_win else self.hm_norm_win, + HANGMAN_REWARD, + {"cool": cool_win}, + ) + await db.commit() @commands.command() async def roll(self, ctx, arg: str = "", mpr: str = ""): From 06306c7b636de12b957552ae7e9a733ab5ecc22d Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Sun, 4 Sep 2022 10:47:45 -0400 Subject: [PATCH 042/127] convert helpers cog to aiosqlite --- canary/cogs/helpers.py | 35 +++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/canary/cogs/helpers.py b/canary/cogs/helpers.py index 4264bbc17..bb10bf2e1 100644 --- a/canary/cogs/helpers.py +++ b/canary/cogs/helpers.py @@ -14,7 +14,6 @@ # # You should have received a copy of the GNU General Public License # along with Canary. If not, see . - # discord-py requirements import discord from discord.ext import commands @@ -31,11 +30,11 @@ import googletrans # Other utilities +import aiosqlite import datetime import math import random import re -import sqlite3 import time from .base_cog import CanaryCog @@ -704,8 +703,11 @@ async def create_main_webhooks(self, ctx: commands.Context): await ctx.send("Job completed.") async def spoilerize_utility(self, ctx: commands.Context, message, reason: str = None, moderator: bool = False): + db: aiosqlite.Connection + if not moderator and ctx.author != message.author: return + # get the webhook for this channel webhook = discord.utils.find( lambda w: w.user == self.bot.user and w.name[: len(MAIN_WEBHOOKS_PREFIX)] == MAIN_WEBHOOKS_PREFIX, @@ -756,34 +758,35 @@ async def spoilerize_utility(self, ctx: commands.Context, message, reason: str = await webhook.send(files=files, username=author.display_name, avatar_url=author.avatar_url, wait=True) ) - conn = sqlite3.connect(self.bot.config.db_path) - c = conn.cursor() - for spoilerized_message in spoilerized_messages: - c.execute("REPLACE INTO SpoilerizedMessages VALUES (?, ?)", (spoilerized_message.id, author.id)) - conn.commit() - conn.close() + async with self.db() as db: + for spoilerized_message in spoilerized_messages: + await db.execute("REPLACE INTO SpoilerizedMessages VALUES (?, ?)", (spoilerized_message.id, author.id)) + await db.commit() # delete original message await message.delete() @commands.Cog.listener() async def on_raw_reaction_add(self, payload): + db: aiosqlite.Connection + if payload.guild_id != self.guild.id or str(payload.emoji) != "🚮": return + # if the put_litter_in_its_place react was used check if it was # on a spoilerized message by its original author, and if so delete it - conn = sqlite3.connect(self.bot.config.db_path) - c = conn.cursor() - c.execute( - "SELECT * From SpoilerizedMessages WHERE MessageID=? AND UserID=?", - (int(payload.message_id), int(payload.member.id)), - ) - found = c.fetchone() + + async with self.db() as db: + async with db.execute( + "SELECT * From SpoilerizedMessages WHERE MessageID=? AND UserID=?", + (int(payload.message_id), int(payload.member.id)), + ) as c: + found = await c.fetchone() + if found: channel = utils.get(self.guild.text_channels, id=payload.channel_id) message = await channel.fetch_message(payload.message_id) await message.delete() - conn.close() @commands.command(alias=["spoiler"]) async def spoilerize(self, ctx: commands.Context, *args): From fa93f1bab2aee8209466114949d6d71430a0d02e Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Sun, 4 Sep 2022 10:47:53 -0400 Subject: [PATCH 043/127] convert role restoration to aiosqlite --- canary/cogs/utils/role_restoration.py | 89 ++++++++++++--------------- 1 file changed, 40 insertions(+), 49 deletions(-) diff --git a/canary/cogs/utils/role_restoration.py b/canary/cogs/utils/role_restoration.py index ac009df9a..fdbb064c7 100644 --- a/canary/cogs/utils/role_restoration.py +++ b/canary/cogs/utils/role_restoration.py @@ -15,8 +15,8 @@ # You should have received a copy of the GNU General Public License # along with Canary. If not, see . +import aiosqlite import discord -import sqlite3 from discord import utils from discord.ext import commands @@ -35,48 +35,44 @@ async def save_existing_roles( if not roles_id and not muted: return - conn = sqlite3.connect(bot.config.db_path) - try: - c = conn.cursor() + db: aiosqlite.Connection + async with bot.db() as db: # store roles as a string of IDs separated by spaces if muted: now = datetime.datetime.now() - if is_in_muted_table(bot, user): + if await is_in_muted_table(bot, user): t = (appeal_channel.id, user.id) - c.execute(f"UPDATE MutedUsers SET AppealChannelID = ? WHERE UserID = ?", t) + await db.execute(f"UPDATE MutedUsers SET AppealChannelID = ? WHERE UserID = ?", t) else: t = (user.id, appeal_channel.id, " ".join(str(e) for e in roles_id), now) - c.execute(f"REPLACE INTO MutedUsers VALUES (?, ?, ?, ?)", t) + await db.execute(f"REPLACE INTO MutedUsers VALUES (?, ?, ?, ?)", t) else: t = (user.id, " ".join(str(e) for e in roles_id)) - c.execute(f"REPLACE INTO PreviousRoles VALUES (?, ?)", t) - conn.commit() - finally: - conn.close() + await db.execute(f"REPLACE INTO PreviousRoles VALUES (?, ?)", t) + await db.commit() -def fetch_saved_roles(bot, guild, user: discord.Member, muted: bool = False) -> list[discord.Role] | None: - conn = sqlite3.connect(bot.config.db_path) - try: - c = conn.cursor() - if muted: - fetched_roles = c.execute(f"SELECT Roles FROM MutedUsers WHERE UserID = ?", (user.id,)).fetchone() - else: - fetched_roles = c.execute(f"SELECT Roles FROM PreviousRoles WHERE ID = ?", (user.id,)).fetchone() - # the above returns a tuple with a string of IDs separated by spaces - - # Return list of all valid roles restored from the DB - # - filter(None, ...) strips false-y elements - return ( - list( - filter(None, (guild.get_role(int(role_id)) for role_id in fetched_roles[0].split(" ") if role_id != "")) - ) - if fetched_roles - else None - ) - finally: - conn.close() +def fetch_saved_roles(bot: Canary, guild, user: discord.Member, muted: bool = False) -> list[discord.Role] | None: + db: aiosqlite.Connection + c: aiosqlite.Cursor + + async with bot.db() as db: + q = "SELECT Roles FROM " + ("MutedUsers WHERE UserID = ?" if muted else "PreviousRoles WHERE ID = ?") + async with db.execute(q, (user.id,)) as c: + fetched_roles = await c.fetchone() + + # the above returns a tuple with a string of IDs separated by spaces + + # Return list of all valid roles restored from the DB + # - filter(None, ...) strips false-y elements + return ( + list( + filter(None, (guild.get_role(int(role_id)) for role_id in fetched_roles[0].split(" ") if role_id != "")) + ) + if fetched_roles + else None + ) def has_muted_role(user: discord.Member): @@ -84,28 +80,23 @@ def has_muted_role(user: discord.Member): return muted_role and next((r for r in user.roles if r == muted_role), None) is not None -def is_in_muted_table(bot, user: discord.Member): - conn = sqlite3.connect(bot.config.db_path) - try: - c = conn.cursor() - muted = c.execute("SELECT * FROM MutedUsers WHERE UserID = ?", (user.id,)).fetchone() - return muted is not None - finally: - conn.close() +async def is_in_muted_table(bot: Canary, user: discord.Member): + db: aiosqlite.Connection + c: aiosqlite.Cursor + async with bot.db() as db: + async with db.execute("SELECT * FROM MutedUsers WHERE UserID = ?", (user.id,)) as c: + return (await c.fetchone()) is not None -def remove_from_muted_table(bot, user: discord.Member): - conn = sqlite3.connect(bot.config.db_path) - try: - c = conn.cursor() - c.execute("DELETE FROM MutedUsers WHERE UserID = ?", (user.id,)) - conn.commit() - finally: - conn.close() +async def remove_from_muted_table(bot: Canary, user: discord.Member): + db: aiosqlite.Connection + async with bot.db() as db: + await db.execute("DELETE FROM MutedUsers WHERE UserID = ?", (user.id,)) + await db.commit() async def role_restoring_page( - bot, + bot: Canary, ctx: discord.ext.commands.Context | MockContext, user: discord.Member, roles: list[discord.Role] | None, From 91805c7885fd7f727aaddb7c4f2c08fbf3974537 Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Sun, 4 Sep 2022 10:58:22 -0400 Subject: [PATCH 044/127] fix fetch_saved_roles not being async --- canary/cogs/mod.py | 2 +- canary/cogs/roles.py | 2 +- canary/cogs/utils/role_restoration.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/canary/cogs/mod.py b/canary/cogs/mod.py index a053f329f..73346fbfd 100644 --- a/canary/cogs/mod.py +++ b/canary/cogs/mod.py @@ -337,7 +337,7 @@ async def unmute_utility(self, user: discord.Member, ctx: discord.ext.commands.C ) # Restore old roles from the database - valid_roles = fetch_saved_roles(self.bot, self.guild, user, muted=True) + valid_roles = await fetch_saved_roles(self.bot, self.guild, user, muted=True) # for the following, if ctx is provided then the optional bot, guild, channel and restored_by values are ignored # if there is no ctx, it means that the user was unmuted because a mod removed the role manually # to know which mod did it, we would have to go through the audit log and try the find the log entry. Instead, diff --git a/canary/cogs/roles.py b/canary/cogs/roles.py index 03c80a60d..30d9d7710 100644 --- a/canary/cogs/roles.py +++ b/canary/cogs/roles.py @@ -274,7 +274,7 @@ async def previous_roles(self, ctx: commands.Context, user: discord.Member): await ctx.send("Cannot restore roles to a muted user") return - valid_roles = fetch_saved_roles(self.bot, ctx.guild, user) + valid_roles = await fetch_saved_roles(self.bot, ctx.guild, user) await role_restoring_page(self.bot, ctx, user, valid_roles) @commands.Cog.listener() diff --git a/canary/cogs/utils/role_restoration.py b/canary/cogs/utils/role_restoration.py index fdbb064c7..c699ccb57 100644 --- a/canary/cogs/utils/role_restoration.py +++ b/canary/cogs/utils/role_restoration.py @@ -53,7 +53,7 @@ async def save_existing_roles( await db.commit() -def fetch_saved_roles(bot: Canary, guild, user: discord.Member, muted: bool = False) -> list[discord.Role] | None: +async def fetch_saved_roles(bot: Canary, guild, user: discord.Member, muted: bool = False) -> list[discord.Role] | None: db: aiosqlite.Connection c: aiosqlite.Cursor From cce5b95c2200b081bccd36dcbd3350075fbd21e5 Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Sun, 4 Sep 2022 10:58:37 -0400 Subject: [PATCH 045/127] respond with error msg if keydates encounters an http error --- canary/cogs/helpers.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/canary/cogs/helpers.py b/canary/cogs/helpers.py index bb10bf2e1..c40dec99a 100644 --- a/canary/cogs/helpers.py +++ b/canary/cogs/helpers.py @@ -15,6 +15,7 @@ # You should have received a copy of the GNU General Public License # along with Canary. If not, see . # discord-py requirements +import aiohttp import discord from discord.ext import commands from discord import utils @@ -303,7 +304,13 @@ async def keydates(self, ctx: commands.Context): await ctx.trigger_typing() - soup = BeautifulSoup(await fetch(MCGILL_KEY_DATES_URL, "content"), "html.parser") + try: + content = await fetch(MCGILL_KEY_DATES_URL, "content") + except Exception as e: + await ctx.send("Encountered an error while contacting the McGill server.") + raise e + + soup = BeautifulSoup(content, "html.parser") now = datetime.datetime.now() current_year, current_month = now.year, now.month From 889f2525da0e1be4f7bc49ca9e31c31a78b8e981 Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Sun, 4 Sep 2022 11:01:50 -0400 Subject: [PATCH 046/127] add error message if tex rendering fails --- canary/cogs/helpers.py | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/canary/cogs/helpers.py b/canary/cogs/helpers.py index c40dec99a..ac89905f3 100644 --- a/canary/cogs/helpers.py +++ b/canary/cogs/helpers.py @@ -424,15 +424,21 @@ async def tex(self, ctx: commands.Context, *, query: str): tex += "\\[" + sp[2 * i + 1] + "\\]" buf = BytesIO() - preview( - tex, - preamble=LATEX_PREAMBLE, - viewer="BytesIO", - outputbuffer=buf, - euler=False, - dvioptions=["-T", "tight", "-z", "9", "--truecolor", "-D", "600"], - ) - buf.seek(0) + + try: + preview( + tex, + preamble=LATEX_PREAMBLE, + viewer="BytesIO", + outputbuffer=buf, + euler=False, + dvioptions=["-T", "tight", "-z", "9", "--truecolor", "-D", "600"], + ) + buf.seek(0) + except RuntimeError as e: + await ctx.send("Encountered an error while trying to render TeX.") + raise e + img_bytes = np.asarray(bytearray(buf.read()), dtype=np.uint8) img = cv2.imdecode(img_bytes, cv2.IMREAD_UNCHANGED) img2 = cv2.copyMakeBorder(img, 115, 115, 115, 115, cv2.BORDER_CONSTANT, value=(255, 255, 255)) From f6518c8cb10b8b782bc3f78d19a8c56aff296644 Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Sun, 4 Sep 2022 11:12:31 -0400 Subject: [PATCH 047/127] linting and autoformatting fixes --- canary/cogs/banner.py | 10 +++--- canary/cogs/currency.py | 12 +++---- canary/cogs/customreactions.py | 51 ++++++++++++--------------- canary/cogs/games.py | 4 +-- canary/cogs/helpers.py | 10 +++--- canary/cogs/info.py | 2 +- canary/cogs/mod.py | 3 +- canary/cogs/quotes.py | 2 +- canary/cogs/reminder.py | 4 +-- canary/cogs/roles.py | 2 +- canary/cogs/score.py | 21 +++++------ canary/cogs/utils/arg_converter.py | 2 +- canary/cogs/utils/role_restoration.py | 6 ++-- canary/main.py | 4 +-- 14 files changed, 62 insertions(+), 71 deletions(-) diff --git a/canary/cogs/banner.py b/canary/cogs/banner.py index a3a6ffc29..5b9347cec 100644 --- a/canary/cogs/banner.py +++ b/canary/cogs/banner.py @@ -348,7 +348,7 @@ def msg_check(msg): try: await preview_message.pin( - reason=f"Banner of the week winner submitted by {winner} " f"(Approved by {ctx.author})" + reason=f"Banner of the week winner submitted by {winner} (Approved by {ctx.author})" ) except discord.errors.HTTPException as e: if e.code != 30003: # Discord API code for full pins @@ -356,12 +356,12 @@ def msg_check(msg): pins = await self.banner_submissions_channel.pins() await pins[-1].unpin(reason="#banner_submissions pins are full") await preview_message.pin( - reason=f"Banner of the week winner submitted by {winner} " f"(Approved by {ctx.author})" + reason=f"Banner of the week winner submitted by {winner} (Approved by {ctx.author})" ) try: await converted_message.pin( - reason=f"Banner of the week winner submitted by {winner} " f"(Approved by {ctx.author})" + reason=f"Banner of the week winner submitted by {winner} (Approved by {ctx.author})" ) except discord.errors.HTTPException as e: if e.code != 30003: @@ -369,14 +369,14 @@ def msg_check(msg): pins = await self.banner_converted_channel.pins() await pins[-1].unpin(reason="#converted_banner_submissions pins are full") await converted_message.pin( - reason=f"Banner of the week winner submitted by {winner} " f"(Approved by {ctx.author})" + reason=f"Banner of the week winner submitted by {winner} (Approved by {ctx.author})" ) await winner.add_roles(self.banner_winner_role, reason=f"Banner of the week winner (Approved by {ctx.author})") converted_read = await converted.read() await self.guild.edit( banner=converted_read, - reason=f"Banner of the week winner submitted by {winner} " f"(Approved by {ctx.author})", + reason=f"Banner of the week winner submitted by {winner} (Approved by {ctx.author})", ) await self.reset_banner_contest() await ctx.send("Successfully set banner and ended contest.") diff --git a/canary/cogs/currency.py b/canary/cogs/currency.py index 832bba823..707fc3ecc 100644 --- a/canary/cogs/currency.py +++ b/canary/cogs/currency.py @@ -82,7 +82,7 @@ async def fetch_bank_balance(self, user: discord.Member) -> Decimal: async with self.db() as db: c: aiosqlite.Cursor async with db.execute( - "SELECT IFNULL(SUM(Amount), 0) FROM BankTransactions WHERE " "UserID = ?", (user.id,) + "SELECT IFNULL(SUM(Amount), 0) FROM BankTransactions WHERE UserID = ?", (user.id,) ) as c: balance = self.db_to_currency((await c.fetchone())[0]) if balance is None: @@ -104,7 +104,7 @@ async def create_bank_transaction( await db.execute("PRAGMA foreign_keys = ON") await add_member_if_needed(self, db, user.id) await db.execute( - "INSERT INTO BankTransactions(UserID, Amount, Action, " "Metadata, Date) VALUES(?, ?, ?, ?, ?)", + "INSERT INTO BankTransactions(UserID, Amount, Action, Metadata, Date) VALUES(?, ?, ?, ?, ?)", (user.id, self.currency_to_db(amount), action, json.dumps(metadata), now), ) @@ -168,7 +168,7 @@ async def initial_claim(self, ctx): db: aiosqlite.Connection async with self.db() as db: async with db.execute( - "SELECT IFNULL(MAX(Date), 0) FROM BankTransactions " "WHERE UserID = ? AND Action = ?", + "SELECT IFNULL(MAX(Date), 0) FROM BankTransactions WHERE UserID = ? AND Action = ?", (ctx.message.author.id, ACTION_INITIAL_CLAIM), ) as c: claim_time = (await c.fetchone())[0] @@ -208,7 +208,7 @@ async def claim(self, ctx): async with self.db() as db: c: aiosqlite.Cursor async with db.execute( - "SELECT IFNULL(MAX(Date), 0) FROM BankTransactions " "WHERE UserID = ? AND Action = ?", + "SELECT IFNULL(MAX(Date), 0) FROM BankTransactions WHERE UserID = ? AND Action = ?", (ctx.message.author.id, ACTION_CLAIM), ) as c: last_claimed = datetime.datetime.fromtimestamp((await c.fetchone())[0]) @@ -339,7 +339,7 @@ async def bet_roll(self, ctx, bet: str = None): if amount_returned == bet_dec: message = "{un} broke even (result was **{re}**)." elif amount_returned > bet_dec: - message = "Congratulations! {un} won [net] {am} (result was " "**{re}**)." + message = "Congratulations! {un} won [net] {am} (result was **{re}**)." author_name = ctx.message.author.display_name @@ -415,7 +415,7 @@ async def leaderboard(self, ctx): balances = sorted(await self.fetch_all_balances(), reverse=True, key=lambda b: b[2]) if len(balances) == 0: - await ctx.send("Leaderboards are not yet available for this server, please " "collect some currency.") + await ctx.send("Leaderboards are not yet available for this server, please collect some currency.") return table = [] diff --git a/canary/cogs/customreactions.py b/canary/cogs/customreactions.py index 97ebb751a..5fe3a21e9 100644 --- a/canary/cogs/customreactions.py +++ b/canary/cogs/customreactions.py @@ -367,13 +367,12 @@ async def _refresh_msg(): title = f"Custom reaction successfully added!" else: title = "Custom reaction proposal successfully submitted!" - description = f"-Prompt: {prompt_message}\n" f"-Response: {response}" + description = f"-Prompt: {prompt_message}\n-Response: {response}" if delete: description = f"{description}\n-Will delete the message that calls the reaction" if anywhere: description = ( - f"{description}\n" - f"-Will activate the custom reaction if the prompt is anywhere in a message" + f"{description}\n-Will activate the custom reaction if the prompt is anywhere in a message" ) if dm: description = ( @@ -660,11 +659,10 @@ async def edit_custom_react( await message.edit( embed=( discord.Embed( - title=f"Modify a {noun_custom}", - description="Please enter the new prompt" + title=f"Modify a {noun_custom}", description="Please enter the new prompt" ).set_footer( text=f"{user} is currently modifying a {noun_custom}. \nWrite '{STOP_TEXT}' to cancel.", - icon_url=user.avatar_url + icon_url=user.avatar_url, ) ) ) @@ -685,8 +683,7 @@ async def edit_custom_react( async with self.db() as db: await db.execute( - "UPDATE CustomReactions SET Prompt = ? WHERE CustomReactionID = ?", - (prompt, custom_react_id) + "UPDATE CustomReactions SET Prompt = ? WHERE CustomReactionID = ?", (prompt, custom_react_id) ) await db.commit() @@ -703,11 +700,10 @@ async def edit_custom_react( if reaction.emoji == EMOJI["two"]: await message.edit( embed=discord.Embed( - title=f"Modify a {noun_custom}", - description="Please enter the new response" + title=f"Modify a {noun_custom}", description="Please enter the new response" ).set_footer( text=f"{user} is currently modifying a {noun_custom}. \nWrite '{STOP_TEXT}' to cancel.", - icon_url=user.avatar_url + icon_url=user.avatar_url, ) ) @@ -728,7 +724,7 @@ async def edit_custom_react( async with self.db() as db: await db.execute( "UPDATE CustomReactions SET Response = ? WHERE CustomReactionID = ?", - (response, custom_react_id) + (response, custom_react_id), ) await db.commit() @@ -792,7 +788,7 @@ async def edit_custom_react( async with self.db() as db: await db.execute( "UPDATE CustomReactions SET DeletePrompt = ? WHERE CustomReactionID = ?", - (new_value, custom_react_id) + (new_value, custom_react_id), ) await db.commit() await self.rebuild_lists() @@ -831,10 +827,7 @@ async def edit_custom_react( ) except asyncio.TimeoutError: - title = ( - f"The modification of the {noun_custom} timed out. " - f"Returning to list of {noun}s..." - ) + title = f"The modification of the {noun_custom} timed out. Returning to list of {noun}s..." await message.edit(embed=discord.Embed(title=title)) await asyncio.sleep(5) current_options.clear() @@ -859,7 +852,7 @@ async def edit_custom_react( async with self.db() as db: await db.execute( "UPDATE CustomReactions SET Anywhere = ? WHERE CustomReactionID = ?", - (new_value, custom_react_id) + (new_value, custom_react_id), ) await db.commit() await self.rebuild_lists() @@ -926,7 +919,7 @@ async def edit_custom_react( async with self.db() as db: await db.execute( "UPDATE CustomReactions SET DM = ? WHERE CustomReactionID = ?", - (new_value, custom_react_id) + (new_value, custom_react_id), ) await db.commit() await self.rebuild_lists() @@ -944,27 +937,27 @@ async def edit_custom_react( if reaction.emoji == EMOJI["white_check_mark"]: async with self.db() as db: await db.execute( - "UPDATE CustomReactions SET Proposal = ? WHERE CustomReactionID = ?", - (0, custom_react_id) + "UPDATE CustomReactions SET Proposal = ? WHERE CustomReactionID = ?", (0, custom_react_id) ) await db.commit() await self.rebuild_lists() - await message.edit(embed=discord.Embed(title=( - "Custom reaction proposal successfully approved! " - "Returning to list of current reaction proposals..." - )).set_footer(text=f"Approved by {user}.", icon_url=user.avatar_url)) + await message.edit( + embed=discord.Embed( + title=( + "Custom reaction proposal successfully approved! " + "Returning to list of current reaction proposals..." + ) + ).set_footer(text=f"Approved by {user}.", icon_url=user.avatar_url) + ) await asyncio.sleep(5) # Delete a custom reaction or proposal if reaction.emoji == EMOJI["put_litter_in_its_place"] or reaction.emoji == EMOJI["x"]: async with self.db() as db: - await db.execute( - "DELETE FROM CustomReactions WHERE CustomReactionID = ?", - (custom_react_id,) - ) + await db.execute("DELETE FROM CustomReactions WHERE CustomReactionID = ?", (custom_react_id,)) await db.commit() title = f"Custom {noun} successfully rejected! Returning to list of {noun}s..." footer = f"{'Rejected' if proposals else 'Deleted'} by {user}." diff --git a/canary/cogs/games.py b/canary/cogs/games.py index 6598579fa..5a687dd09 100644 --- a/canary/cogs/games.py +++ b/canary/cogs/games.py @@ -112,7 +112,7 @@ async def hangman(self, ctx, command: str | None = None): if ctx.message.channel in self.hm_locks: await ctx.send( - "command `hm|hangman` cannot " "be used to start a new game " "while one is already going on" + "command `hm|hangman` cannot be used to start a new game while one is already going on" ) return @@ -199,7 +199,7 @@ async def hangman(self, ctx, command: str | None = None): game_state.embed.set_image(url=game_state.img) await ctx.send(embed=game_state.embed) await ctx.send( - f"congratulations `{winner}`, you solved the hangman, " f"earning you {self.hm_norm_win} cheeps" + f"congratulations `{winner}`, you solved the hangman, earning you {self.hm_norm_win} cheeps" ) break else: diff --git a/canary/cogs/helpers.py b/canary/cogs/helpers.py index ac89905f3..9cb06b824 100644 --- a/canary/cogs/helpers.py +++ b/canary/cogs/helpers.py @@ -260,7 +260,7 @@ async def course(self, ctx: commands.Context, *, query: str): # cases. Courses across multiple semesters have a suffix like D1/D2. result = re.compile(r"([A-Za-z]{3}[A-Za-z0-9])\s*(\d{3}\s*(\w\d)?)", re.IGNORECASE | re.DOTALL).search(query) if not result: - await ctx.send(":warning: Incorrect format. The correct format is `?course " "`.") + await ctx.send(":warning: Incorrect format. The correct format is `?course `.") return search_term = re.sub(r"\s+", "", f"{result.group(1)}-{result.group(2)}") @@ -535,7 +535,7 @@ async def food_spot(self, ctx: commands.Context, *args): ) embed = discord.Embed(title="Food spotted", description=" ".join(args) if args else "\u200b") embed.set_footer( - text=("Added by {0} • Use '{1}foodspot' or '{1}fs' if you spot " "food (See '{1}help foodspot')").format( + text=("Added by {0} • Use '{1}foodspot' or '{1}fs' if you spot food (See '{1}help foodspot')").format( ctx.message.author, self.bot.config.command_prefix[0] ), icon_url=ctx.message.author.avatar_url, @@ -660,7 +660,7 @@ async def translate(self, ctx: commands.Context, command: str, *, inp_str: str | # Validation of language codes codes = command.replace("_", "-").split(">") if len(codes) != 2: - await ctx.send(f"Argument `{command}` is not properly formatted. " f"See `?translate help` to learn more.") + await ctx.send(f"Argument `{command}` is not properly formatted. See `?translate help` to learn more.") return source = codes[0].lower().strip() translator = googletrans.Translator() @@ -668,12 +668,12 @@ async def translate(self, ctx: commands.Context, command: str, *, inp_str: str | detection = translator.detect(inp_str) source = detection.lang elif source not in googletrans.LANGUAGES: - await ctx.send(f"`{source}` is not a valid language code. " f"See `?translate codes` for language codes.") + await ctx.send(f"`{source}` is not a valid language code. See `?translate codes` for language codes.") return destination = codes[1].lower().strip() if destination not in googletrans.LANGUAGES: await ctx.send( - f"`{destination}` is not a valid language code. " f"See `?translate codes` for language codes." + f"`{destination}` is not a valid language code. See `?translate codes` for language codes." ) return diff --git a/canary/cogs/info.py b/canary/cogs/info.py index 798303c74..71af932d3 100644 --- a/canary/cogs/info.py +++ b/canary/cogs/info.py @@ -30,7 +30,7 @@ async def version(self, ctx): .strip() .split(" ") ) - await ctx.send(f"Version: `{version}`\nCommit: `{commit}` " f"authored `{authored}`") + await ctx.send(f"Version: `{version}`\nCommit: `{commit}` authored `{authored}`") def setup(bot): diff --git a/canary/cogs/mod.py b/canary/cogs/mod.py index 73346fbfd..54387b333 100644 --- a/canary/cogs/mod.py +++ b/canary/cogs/mod.py @@ -85,8 +85,7 @@ async def verification_purge_startup(self): else: # the verification purge info setting has not been added to db yet await self.set_settings_key( - "last_verification_purge_timestamp", - str(self.last_verification_purge_datetime.timestamp()) + "last_verification_purge_timestamp", str(self.last_verification_purge_datetime.timestamp()) ) self.check_verification_purge.start() diff --git a/canary/cogs/quotes.py b/canary/cogs/quotes.py index ead789ff4..78a8f74f3 100644 --- a/canary/cogs/quotes.py +++ b/canary/cogs/quotes.py @@ -182,7 +182,7 @@ async def quotes(self, ctx, str1: str = None, *, str2: str = None): u_id = mentions[0].id # Query for either user and quote or user only (None) async with db.execute( - "SELECT ID, Name, Quote FROM Quotes WHERE ID = ? AND Quote " "LIKE ?", + "SELECT ID, Name, Quote FROM Quotes WHERE ID = ? AND Quote LIKE ?", (u_id, f"%{str2 if str2 is not None else ''}%"), ) as c: quotes = await c.fetchall() diff --git a/canary/cogs/reminder.py b/canary/cogs/reminder.py index e318cf064..92692e607 100644 --- a/canary/cogs/reminder.py +++ b/canary/cogs/reminder.py @@ -417,8 +417,8 @@ def msg_check(msg): async with self.db() as db: await db.execute( - "DELETE FROM Reminders WHERE ID = ? AND " "Reminder = ?", - (rem_list[index][0], rem_list[index][2]) + "DELETE FROM Reminders WHERE ID = ? AND Reminder = ?", + (rem_list[index][0], rem_list[index][2]), ) await db.commit() diff --git a/canary/cogs/roles.py b/canary/cogs/roles.py index 30d9d7710..5a7226b2e 100644 --- a/canary/cogs/roles.py +++ b/canary/cogs/roles.py @@ -130,7 +130,7 @@ async def toggle_role( elif limit and len(existing_roles) == limit: await ctx.send( - f"You have too many roles in category " f"`{category}` (limit is `{limit}`). " f"Please remove one." + f"You have too many roles in category `{category}` (limit is `{limit}`). Please remove one." ) return diff --git a/canary/cogs/score.py b/canary/cogs/score.py index 53b53f2de..d01b78eac 100644 --- a/canary/cogs/score.py +++ b/canary/cogs/score.py @@ -14,7 +14,7 @@ # # You should have received a copy of the GNU General Public License # along with Canary. If not, see . -import aiosqlite + # Rewritten by @le-potate # discord.py requirements @@ -25,6 +25,7 @@ from ..bot import Canary # For DB functionality +import aiosqlite import json from .base_cog import CanaryCog from .utils.members import add_member_if_needed @@ -47,7 +48,7 @@ async def convert(self, ctx, argument): except commands.BadArgument: if not any(argument in d.values() for d in EMOJI.values()): raise commands.BadArgument( - "Not in the current list of Discord Unicode Emojis " "and no Custom Emoji found" + "Not in the current list of Discord Unicode Emojis and no Custom Emoji found" ) return argument @@ -89,7 +90,7 @@ async def convert(self, ctx, argument): if "emojitype" not in argument.lower(): raise commands.BadArgument("No `emojitype` flag") if len(argument) < 11: - raise commands.BadArgument("No argument specified for " "`emojitype` flag") + raise commands.BadArgument("No argument specified for `emojitype` flag") result = argument[10:].lower() if result not in ("all", "unicode", "custom", "here", "nothere", "score"): raise commands.BadArgument("Unknown emoji type specified for `emojitype` flag") @@ -103,7 +104,7 @@ async def convert(self, ctx, argument): if "emojiname" not in argument.lower(): raise commands.BadArgument("No `emojiname` flag") if len(argument) < 11: - raise commands.BadArgument("No argument specified for " "`emojiname` flag") + raise commands.BadArgument("No argument specified for `emojiname` flag") return f":{argument[10:]}:" @@ -130,7 +131,7 @@ async def convert(self, ctx, argument): try: return int(argument[7:]) except ValueError: - raise commands.BadArgument("`before` flag should take an " "integer as input") + raise commands.BadArgument("`before` flag should take an integer as input") class AfterConverter(commands.Converter): @@ -142,7 +143,7 @@ async def convert(self, ctx, argument): try: return int(argument[6:]) except ValueError: - raise commands.BadArgument("`after` flag should take an " "integer as input") + raise commands.BadArgument("`after` flag should take an integer as input") class Score(CanaryCog): @@ -268,12 +269,12 @@ def _where_str_and_values_from_args_dict(self, args_dict, prefix=None): elif args_dict["emojitype"] == "custom": where_list.append("instr(ReactionName, '<') = 1") elif args_dict["emojitype"] == "here": - where_list.append(f"ReactionName IN " f"({','.join(['?']*len(guild_emojis))})") + where_list.append(f"ReactionName IN ({','.join(['?']*len(guild_emojis))})") values_list = values_list + guild_emojis elif args_dict["emojitype"] == "nothere": # must be a custom react where_list.append("instr(ReactionName, '<') = 1") - where_list.append(f"ReactionName NOT IN " f"({','.join(['?']*len(guild_emojis))})") + where_list.append(f"ReactionName NOT IN ({','.join(['?']*len(guild_emojis))})") values_list = values_list + guild_emojis # elif args_dict["emojitype"] == "all", there are no restrictions # elif args_dict["emojitype"] == "score", this must be dealt with @@ -400,7 +401,7 @@ async def score(self, ctx: commands.Context, *args): c: aiosqlite.Cursor if args_dict["emojitype"] != "score": - async with db.execute(f"SELECT count(ReacteeID) FROM Reactions " f"WHERE {where_str}", t) as c: + async with db.execute(f"SELECT count(ReacteeID) FROM Reactions WHERE {where_str}", t) as c: react_count = (await c.fetchone())[0] else: async with db.execute( @@ -563,7 +564,7 @@ async def emojiranking(self, ctx: commands.Context, *args): return if args_dict["emojitype"] == "score": - await ctx.send("Invalid input: Emojitype flag cannot use " "type score for this function") + await ctx.send("Invalid input: Emojitype flag cannot use type score for this function") # get the WHERE conditions and the values where_str, t = self._where_str_and_values_from_args_dict(args_dict) diff --git a/canary/cogs/utils/arg_converter.py b/canary/cogs/utils/arg_converter.py index d0e432b73..123b55e98 100644 --- a/canary/cogs/utils/arg_converter.py +++ b/canary/cogs/utils/arg_converter.py @@ -140,7 +140,7 @@ async def convert(self, ctx, arguments): # values or raise commands.BadArgument if they are required for key in remaining_vars: if len(self._converters_dict[key]) == 1: - raise commands.BadArgument(f"Invalid input: Missing required " f"argument {key}") + raise commands.BadArgument(f"Invalid input: Missing required argument {key}") else: converted_arguments_dict[key] = self._converters_dict[key][1] return converted_arguments_dict diff --git a/canary/cogs/utils/role_restoration.py b/canary/cogs/utils/role_restoration.py index c699ccb57..f9fcffb81 100644 --- a/canary/cogs/utils/role_restoration.py +++ b/canary/cogs/utils/role_restoration.py @@ -67,9 +67,7 @@ async def fetch_saved_roles(bot: Canary, guild, user: discord.Member, muted: boo # Return list of all valid roles restored from the DB # - filter(None, ...) strips false-y elements return ( - list( - filter(None, (guild.get_role(int(role_id)) for role_id in fetched_roles[0].split(" ") if role_id != "")) - ) + list(filter(None, (guild.get_role(int(role_id)) for role_id in fetched_roles[0].split(" ") if role_id != ""))) if fetched_roles else None ) @@ -161,7 +159,7 @@ async def role_restoring_page( ) embed = discord.Embed( - title=f"{user.display_name}'s previous roles were " f"successfully added back by {ok_user.display_name}" + title=f"{user.display_name}'s previous roles were successfully added back by {ok_user.display_name}" ) await message.edit(embed=embed) await message.clear_reaction("◀") diff --git a/canary/main.py b/canary/main.py index d5758ba2e..742d49e20 100755 --- a/canary/main.py +++ b/canary/main.py @@ -55,7 +55,7 @@ async def on_ready(): webhook_string = ( " and to the log webhook" if bot.config.dev_log_webhook_id and bot.config.dev_log_webhook_token else "" ) - sys.stdout.write(f"Bot is ready, program output will be written to a " f"log file{webhook_string}.\n") + sys.stdout.write(f"Bot is ready, program output will be written to a log file{webhook_string}.\n") sys.stdout.flush() bot.dev_logger.info(f"Logged in as {bot.user.name} ({bot.user.id})") @@ -162,7 +162,7 @@ def main(): try: bot.load_extension(extension) except Exception as e: - bot.dev_logger.warning(f"Failed to load extension {extension}\n" f"{type(e).__name__}: {e}") + bot.dev_logger.warning(f"Failed to load extension {extension}\n{type(e).__name__}: {e}") bot.run(bot.config.discord_key) From 21c6a7bf456d46ab48f68fbb11a85beaf716f0e6 Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Sun, 4 Sep 2022 11:36:21 -0400 Subject: [PATCH 048/127] type fixes --- canary/bot.py | 3 ++- canary/cogs/banner.py | 15 +++++++++++++-- canary/cogs/base_cog.py | 4 ++-- canary/cogs/currency.py | 3 ++- canary/cogs/mod.py | 3 +++ canary/cogs/quotes.py | 16 +++++++--------- canary/cogs/utils/role_restoration.py | 21 +++++++++++++-------- 7 files changed, 42 insertions(+), 23 deletions(-) diff --git a/canary/bot.py b/canary/bot.py index 1ead9a424..eeb269935 100644 --- a/canary/bot.py +++ b/canary/bot.py @@ -24,6 +24,7 @@ from discord import Webhook, RequestsWebhookAdapter, Intents from discord.ext import commands from pathlib import Path +from typing import AsyncGenerator __all__ = ["Canary", "bot", "developer_role", "moderator_role", "muted_role"] @@ -95,7 +96,7 @@ async def start(self, *args, **kwargs): # TODO: discordpy 2.0: use setup_hook f await super().start(*args, **kwargs) @contextlib.asynccontextmanager - async def db(self) -> aiosqlite.Connection: + async def db(self) -> AsyncGenerator[aiosqlite.Connection, None]: conn: aiosqlite.Connection async with aiosqlite.connect(self.config.db_path) as conn: await conn.execute("PRAGMA foreign_keys = ON") diff --git a/canary/cogs/banner.py b/canary/cogs/banner.py index 5b9347cec..362233a1b 100644 --- a/canary/cogs/banner.py +++ b/canary/cogs/banner.py @@ -219,6 +219,10 @@ async def banner_winner(self, ctx, winner: discord.Member = None): if not self.guild: return + if not self.banner_of_the_week_channel: + await ctx.send("No banner of the week channel set.") + return + if not self.banner_submissions_channel: await ctx.send("No banner submissions channel set.") return @@ -275,8 +279,8 @@ def msg_check(msg): winner_id = winner.id db: aiosqlite.Connection + c: aiosqlite.Cursor async with self.db() as db: - c: aiosqlite.Cursor async with db.execute("SELECT * FROM BannerSubmissions WHERE UserID = ?", (winner_id,)) as c: fetched = await c.fetchone() @@ -394,6 +398,10 @@ async def submit_banner(self, ctx: commands.Context, *args): You must be a verified user to use this command. """ + if not self.banner_submissions_channel: + await ctx.send("No banner submissions channel set.") + return + if not ( discord.utils.get(ctx.author.roles, name=self.bot.config.mcgillian_role) or discord.utils.get(ctx.author.roles, name=self.bot.config.honorary_mcgillian_role) @@ -430,7 +438,7 @@ async def submit_banner(self, ctx: commands.Context, *args): stretch = "-stretch" in args or "-stretched" in args - url = None + url: str | None = None if (stretch and len(args) == 1) or (not stretch and len(args) == 0): try: url = ctx.message.attachments[0].url @@ -450,6 +458,9 @@ async def submit_banner(self, ctx: commands.Context, *args): if arg != "-stretch" and arg != "-stretched": url = arg + if url is None: + return + user_image_file = BytesIO(requests.get(url).content) if user_image_file.getbuffer().nbytes >= 10000000: await ctx.send("Image must be less than 10 MB.") diff --git a/canary/cogs/base_cog.py b/canary/cogs/base_cog.py index e9f459626..1019fdf6b 100644 --- a/canary/cogs/base_cog.py +++ b/canary/cogs/base_cog.py @@ -4,7 +4,7 @@ import os from discord.ext import commands -from typing import Iterable +from typing import AsyncGenerator, Iterable from ..bot import Canary @@ -27,7 +27,7 @@ async def on_ready(self): os.mkdir("./tmp/", mode=0o755) @contextlib.asynccontextmanager - async def db(self) -> aiosqlite.Connection: + async def db(self) -> AsyncGenerator[aiosqlite.Connection, None]: async with self.bot.db() as conn: yield conn diff --git a/canary/cogs/currency.py b/canary/cogs/currency.py index 707fc3ecc..665dab342 100644 --- a/canary/cogs/currency.py +++ b/canary/cogs/currency.py @@ -84,7 +84,8 @@ async def fetch_bank_balance(self, user: discord.Member) -> Decimal: async with db.execute( "SELECT IFNULL(SUM(Amount), 0) FROM BankTransactions WHERE UserID = ?", (user.id,) ) as c: - balance = self.db_to_currency((await c.fetchone())[0]) + # noinspection PyRedundantParentheses + balance = self.db_to_currency(((await c.fetchone()) or (0,))[0]) if balance is None: balance = Decimal(0) return balance diff --git a/canary/cogs/mod.py b/canary/cogs/mod.py index 54387b333..02dd20357 100644 --- a/canary/cogs/mod.py +++ b/canary/cogs/mod.py @@ -249,6 +249,9 @@ async def mute_utility(self, user: discord.Member, ctx=None): if not self.guild: return + if not self.appeals_log_channel: + return + # note that this is made such that if a user is already muted # we make sure the user still has the role, is still in the db, and still has a channel confirmation_channel = ctx.channel if ctx else self.appeals_log_channel diff --git a/canary/cogs/quotes.py b/canary/cogs/quotes.py index 78a8f74f3..a3d554922 100644 --- a/canary/cogs/quotes.py +++ b/canary/cogs/quotes.py @@ -23,7 +23,6 @@ import re from discord.ext import commands -from typing import Iterable from ..bot import Canary from .base_cog import CanaryCog @@ -166,17 +165,16 @@ async def quotes(self, ctx, str1: str = None, *, str2: str = None): regex by surrounding the the query with /.../. """ - quotes: Iterable[aiosqlite.Row] + quotes: list[tuple[int, str, str]] db: aiosqlite.Connection + c: aiosqlite.Cursor async with self.db() as db: - c: aiosqlite.Cursor - mentions = ctx.message.mentions if str1 is None: # No argument passed async with db.execute("SELECT ID, Name, Quote FROM Quotes") as c: - quotes = await c.fetchall() + quotes = [tuple(r) for r in await c.fetchall()] elif mentions and mentions[0].mention == str1: # Has args u_id = mentions[0].id @@ -185,13 +183,13 @@ async def quotes(self, ctx, str1: str = None, *, str2: str = None): "SELECT ID, Name, Quote FROM Quotes WHERE ID = ? AND Quote LIKE ?", (u_id, f"%{str2 if str2 is not None else ''}%"), ) as c: - quotes = await c.fetchall() + quotes = [tuple(r) for r in await c.fetchall()] else: # query for quote only query = str1 if str2 is None else f"{str1} {str2}" if query[0] == "/" and query[-1] == "/": async with db.execute("SELECT ID, Name, Quote FROM Quotes") as c: - quotes = await c.fetchall() + quotes = [tuple(r) for r in await c.fetchall()] try: quotes = [q for q in quotes if re.search(query[1:-1], q[2])] except re.error: @@ -202,7 +200,7 @@ async def quotes(self, ctx, str1: str = None, *, str2: str = None): "SELECT ID, Name, Quote FROM Quotes WHERE Quote LIKE ?", (f"%{query}%",), ) as c: - quotes = await c.fetchall() + quotes = [tuple(r) for r in await c.fetchall()] if not quotes: msg = await ctx.send("Quote not found.\n") @@ -229,7 +227,7 @@ def check(reaction, user): return - quote_tuple: tuple[int, str, str] = tuple(random.choice(list(quotes))) + quote_tuple: tuple[int, str, str] = random.choice(quotes) author_id = int(quote_tuple[0]) name = quote_tuple[1] quote = quote_tuple[2] diff --git a/canary/cogs/utils/role_restoration.py b/canary/cogs/utils/role_restoration.py index f9fcffb81..fd489d316 100644 --- a/canary/cogs/utils/role_restoration.py +++ b/canary/cogs/utils/role_restoration.py @@ -28,7 +28,7 @@ async def save_existing_roles( - bot: Canary, user: discord.Member, muted: bool = False, appeal_channel: discord.TextChannel = None + bot: Canary, user: discord.Member, muted: bool = False, appeal_channel: discord.TextChannel | None = None ): roles_id = [role.id for role in user.roles if role.name not in ("@everyone", muted_role_name)] @@ -39,16 +39,21 @@ async def save_existing_roles( async with bot.db() as db: # store roles as a string of IDs separated by spaces if muted: - now = datetime.datetime.now() + if not appeal_channel: + return + if await is_in_muted_table(bot, user): - t = (appeal_channel.id, user.id) - await db.execute(f"UPDATE MutedUsers SET AppealChannelID = ? WHERE UserID = ?", t) + await db.execute( + f"UPDATE MutedUsers SET AppealChannelID = ? WHERE UserID = ?", (appeal_channel.id, user.id) + ) else: - t = (user.id, appeal_channel.id, " ".join(str(e) for e in roles_id), now) - await db.execute(f"REPLACE INTO MutedUsers VALUES (?, ?, ?, ?)", t) + await db.execute( + f"REPLACE INTO MutedUsers VALUES (?, ?, ?, ?)", + (user.id, appeal_channel.id, " ".join(str(e) for e in roles_id), datetime.datetime.now()), + ) + else: - t = (user.id, " ".join(str(e) for e in roles_id)) - await db.execute(f"REPLACE INTO PreviousRoles VALUES (?, ?)", t) + await db.execute(f"REPLACE INTO PreviousRoles VALUES (?, ?)", (user.id, " ".join(str(e) for e in roles_id))) await db.commit() From 76ca1361ff415959a2b0980fd16bdb985f4d80a3 Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Sun, 4 Sep 2022 11:36:55 -0400 Subject: [PATCH 049/127] lint --- canary/cogs/games.py | 4 +--- canary/cogs/helpers.py | 4 +--- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/canary/cogs/games.py b/canary/cogs/games.py index 5a687dd09..40fba4dc8 100644 --- a/canary/cogs/games.py +++ b/canary/cogs/games.py @@ -111,9 +111,7 @@ async def hangman(self, ctx, command: str | None = None): return if ctx.message.channel in self.hm_locks: - await ctx.send( - "command `hm|hangman` cannot be used to start a new game while one is already going on" - ) + await ctx.send("command `hm|hangman` cannot be used to start a new game while one is already going on") return channel_lock = asyncio.Lock() diff --git a/canary/cogs/helpers.py b/canary/cogs/helpers.py index 9cb06b824..74429dc59 100644 --- a/canary/cogs/helpers.py +++ b/canary/cogs/helpers.py @@ -672,9 +672,7 @@ async def translate(self, ctx: commands.Context, command: str, *, inp_str: str | return destination = codes[1].lower().strip() if destination not in googletrans.LANGUAGES: - await ctx.send( - f"`{destination}` is not a valid language code. See `?translate codes` for language codes." - ) + await ctx.send(f"`{destination}` is not a valid language code. See `?translate codes` for language codes.") return await ctx.send( From f30e0f2d127f6684fd2fcb3dfc93736f07cc53c6 Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Sun, 4 Sep 2022 12:54:13 -0400 Subject: [PATCH 050/127] fix some typing complaints --- canary/cogs/helpers.py | 2 +- canary/cogs/mod.py | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/canary/cogs/helpers.py b/canary/cogs/helpers.py index 74429dc59..a71ca2b7c 100644 --- a/canary/cogs/helpers.py +++ b/canary/cogs/helpers.py @@ -162,7 +162,7 @@ def retrieve_string(label): } feels_like_string = ( - Helpers._calculate_feels_like(**{k: float(v.group()) for k, v in feels_like_values.items()}) + Helpers._calculate_feels_like(**{k: float(v.group()) for k, v in feels_like_values.items() if v}) if all( ( humidity_string, diff --git a/canary/cogs/mod.py b/canary/cogs/mod.py index 02dd20357..217a14f76 100644 --- a/canary/cogs/mod.py +++ b/canary/cogs/mod.py @@ -332,6 +332,10 @@ async def mute_utility(self, user: discord.Member, ctx=None): async def unmute_utility(self, user: discord.Member, ctx: discord.ext.commands.Context | MockContext | None = None): confirmation_channel = ctx.channel if ctx else self.appeals_log_channel + + if not confirmation_channel: + return + reason_message = ( f"{ctx.author} used the unmute function on {user}" if ctx From 8b50a1a6417367d87aef44fefca076e61ee013a7 Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Sun, 4 Sep 2022 12:56:31 -0400 Subject: [PATCH 051/127] fix another typing complaint --- canary/cogs/utils/role_restoration.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/canary/cogs/utils/role_restoration.py b/canary/cogs/utils/role_restoration.py index fd489d316..0e38df500 100644 --- a/canary/cogs/utils/role_restoration.py +++ b/canary/cogs/utils/role_restoration.py @@ -105,7 +105,11 @@ async def role_restoring_page( roles: list[discord.Role] | None, muted: bool = False, ): - channel = ctx.channel + channel: discord.TextChannel | None = ctx.channel # Can be None from MockContext + + if channel is None: + return + if roles is None: # No row found in DB, as opposed to empty list if not muted: # don't say anything if this is while unmuting From 31c5c1e13d1b2e4d9b361ace1ee7ccb948a7a4d6 Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Sun, 4 Sep 2022 14:08:15 -0400 Subject: [PATCH 052/127] add bot health check function which checks if guild ID is set right --- canary/bot.py | 6 ++++++ canary/main.py | 1 + 2 files changed, 7 insertions(+) diff --git a/canary/bot.py b/canary/bot.py index eeb269935..9ae574105 100644 --- a/canary/bot.py +++ b/canary/bot.py @@ -94,6 +94,7 @@ def __init__(self, *args, **kwargs): async def start(self, *args, **kwargs): # TODO: discordpy 2.0: use setup_hook for database setup await self._start_database() await super().start(*args, **kwargs) + await self._health_check() @contextlib.asynccontextmanager async def db(self) -> AsyncGenerator[aiosqlite.Connection, None]: @@ -117,6 +118,11 @@ async def _start_database(self): self.dev_logger.debug("Database is ready") + async def health_check(self): + guild = self.get_guild(self.config.server_id) + if not guild: + self.dev_logger.error(f"Could not get guild for bot (specified server ID {self.config.server_id})") + def log_traceback(self, exception): self.dev_logger.error("".join(traceback.format_exception(type(exception), exception, exception.__traceback__))) diff --git a/canary/main.py b/canary/main.py index 742d49e20..accb54efa 100755 --- a/canary/main.py +++ b/canary/main.py @@ -58,6 +58,7 @@ async def on_ready(): sys.stdout.write(f"Bot is ready, program output will be written to a log file{webhook_string}.\n") sys.stdout.flush() bot.dev_logger.info(f"Logged in as {bot.user.name} ({bot.user.id})") + await bot.health_check() @bot.command() From ec3ac91f26033545142c18eb96cf68bd9e93a8dc Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Sun, 4 Sep 2022 14:11:37 -0400 Subject: [PATCH 053/127] switch subscribers cog to new base cog fix guild errors switch to async fetch for metro status --- canary/cogs/subscribers.py | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/canary/cogs/subscribers.py b/canary/cogs/subscribers.py index e67ebc1e1..aaec19730 100644 --- a/canary/cogs/subscribers.py +++ b/canary/cogs/subscribers.py @@ -29,12 +29,13 @@ import re import pickle import feedparser -import requests # Type hinting from ..bot import Canary +from .base_cog import CanaryCog # Subscriber decorator +from .utils.custom_requests import fetch from .utils.subscribers import canary_subscriber CFIA_FEED_URL = "http://inspection.gc.ca/eng/1388422350443/1388422374046.xml" @@ -61,9 +62,9 @@ os.makedirs("./data/runtime", exist_ok=True) -class Subscribers(commands.Cog): +class Subscribers(CanaryCog): def __init__(self, bot: Canary): - self.bot: Canary = bot + super().__init__(bot) # Compiled recall regular expression for filtering self._recall_filter = re.compile(self.bot.config.recall_filter, re.IGNORECASE) @@ -81,13 +82,13 @@ def __init__(self, bot: Canary): @commands.Cog.listener() async def on_ready(self): - self._recall_channel = utils.get( - self.bot.get_guild(self.bot.config.server_id).text_channels, name=self.bot.config.recall_channel - ) + await super().on_ready() - self._metro_status_channel = utils.get( - self.bot.get_guild(self.bot.config.server_id).text_channels, name=self.bot.config.metro_status_channel - ) + if not self.guild: + return + + self._recall_channel = utils.get(self.guild.text_channels, name=self.bot.config.recall_channel) + self._metro_status_channel = utils.get(self.guild.text_channels, name=self.bot.config.metro_status_channel) # Register all subscribers self.bot.loop.create_task(self.cfia_rss()) @@ -101,6 +102,9 @@ async def cfia_rss(self): feed for updates. """ + if not self._recall_channel: + return + newest_recalls = feedparser.parse(CFIA_FEED_URL)["entries"] try: @@ -158,9 +162,11 @@ async def metro_status(self): outages. """ + if not self._metro_status_channel: + return + try: - response = requests.get(METRO_STATUS_API) - response_data = response.json() + response_data = await fetch(METRO_STATUS_API, "json") except json.decoder.JSONDecodeError: # STM API sometimes returns non-JSON responses return From 2e4b886b9332bffba9e708971eeb13d3fb11ab3c Mon Sep 17 00:00:00 2001 From: namemcguffin <52169277+namemcguffin@users.noreply.github.com> Date: Sun, 4 Sep 2022 14:19:40 -0400 Subject: [PATCH 054/127] change: switched to using lxml parser instead of python html.parser when invoking using bs4. (#573) --- canary/cogs/helpers.py | 12 ++--- canary/cogs/subscribers.py | 2 +- canary/cogs/utils/hangman.py | 16 +++---- poetry.lock | 88 +++++++++++++++++++++++++++++++++++- pyproject.toml | 1 + 5 files changed, 103 insertions(+), 16 deletions(-) diff --git a/canary/cogs/helpers.py b/canary/cogs/helpers.py index a71ca2b7c..b0700a6c4 100644 --- a/canary/cogs/helpers.py +++ b/canary/cogs/helpers.py @@ -79,7 +79,7 @@ async def exam(self, ctx: commands.Context): r = await fetch(MCGILL_EXAM_URL, "content") - soup = BeautifulSoup(r, "html.parser") + soup = BeautifulSoup(r, "lxml") if (link_el := soup.find("a", href=re.compile(r"exams/files/exams"))) is None: return await ctx.send("Error: could not find exam link on McGill's website") @@ -140,7 +140,7 @@ async def weather(self, ctx: commands.Context): await ctx.trigger_typing() r = await fetch(self.bot.config.gc_weather_url, "content") - soup = BeautifulSoup(r, "html.parser") + soup = BeautifulSoup(r, "lxml") def retrieve_string(label): if elem := soup.find("dt", string=label).find_next_sibling(): @@ -195,7 +195,7 @@ def no_alerts_embed(title: str | None = None): return discord.Embed(title=title, description="No alerts in effect.", colour=0xFF0000) r_alert = await fetch(self.bot.config.gc_weather_alert_url, "content") - alert_soup = BeautifulSoup(r_alert, "html.parser") + alert_soup = BeautifulSoup(r_alert, "lxml") alert_title = alert_soup.find("h1", string=ALERT_REGEX) @@ -266,7 +266,7 @@ async def course(self, ctx: commands.Context, *, query: str): search_term = re.sub(r"\s+", "", f"{result.group(1)}-{result.group(2)}") url = self.bot.config.course_tpl.format(search_term) r = await fetch(url, "content") - soup = BeautifulSoup(r, "html.parser") + soup = BeautifulSoup(r, "lxml") # TODO: brute-force parsing at the moment title = soup.find_all("h1", {"id": "page-title"})[0].get_text().strip() @@ -310,7 +310,7 @@ async def keydates(self, ctx: commands.Context): await ctx.send("Encountered an error while contacting the McGill server.") raise e - soup = BeautifulSoup(content, "html.parser") + soup = BeautifulSoup(content, "lxml") now = datetime.datetime.now() current_year, current_month = now.year, now.month @@ -461,7 +461,7 @@ async def search(self, ctx: commands.Context, *, query: str): while pagenum < pagelimit: r = await fetch(self.bot.config.course_search_tpl.format(keyword, pagenum), "content") - soup = BeautifulSoup(r, "html.parser") + soup = BeautifulSoup(r, "lxml") found = soup.find_all("div", {"class": "views-row"}) if len(found) < 1: diff --git a/canary/cogs/subscribers.py b/canary/cogs/subscribers.py index aaec19730..a15718dde 100644 --- a/canary/cogs/subscribers.py +++ b/canary/cogs/subscribers.py @@ -124,7 +124,7 @@ async def cfia_rss(self): new_recalls = True recalls[recall_id] = "" recall_warning = discord.Embed(title=recall["title"], description=recall["link"]) - soup = BeautifulSoup(recall["summary"], "html.parser") + soup = BeautifulSoup(recall["summary"], "lxml") try: img_url = soup.img["src"] diff --git a/canary/cogs/utils/hangman.py b/canary/cogs/utils/hangman.py index d1223ca01..99889d4d5 100644 --- a/canary/cogs/utils/hangman.py +++ b/canary/cogs/utils/hangman.py @@ -77,7 +77,7 @@ def mk_animal_list() -> list[tuple[str, str]]: animal_list_soup = BeautifulSoup( - requests.get("https://en.wikipedia.org/wiki/List_of_animal_names").content, "html.parser" + requests.get("https://en.wikipedia.org/wiki/List_of_animal_names").content, "lxml" ).find_all("tr") animal_list: list[tuple[str, str]] = [] for i in range(16, len(animal_list_soup)): @@ -86,7 +86,7 @@ def mk_animal_list() -> list[tuple[str, str]]: continue animal_name = curr_entry.find("a") animal_soup = BeautifulSoup( - requests.get(f"https://en.wikipedia.org{animal_name['href']}").content, "html.parser" + requests.get(f"https://en.wikipedia.org{animal_name['href']}").content, "lxml" ) img_list = animal_soup.find_all("img") img_index = 0 @@ -98,7 +98,7 @@ def mk_animal_list() -> list[tuple[str, str]]: def mk_country_list() -> list[tuple[str, str]]: elem_list_soup = ( - BeautifulSoup(requests.get("https://en.wikipedia.org/wiki/List_of_sovereign_states").content, "html.parser") + BeautifulSoup(requests.get("https://en.wikipedia.org/wiki/List_of_sovereign_states").content, "lxml") .find("table", {"class": "sortable wikitable"}) .find_all("tr") ) @@ -117,7 +117,7 @@ def mk_country_list() -> list[tuple[str, str]]: country_name, "https:" + BeautifulSoup( - requests.get(f"https://en.wikipedia.org{country_name_entry['href']}").content, "html.parser" + requests.get(f"https://en.wikipedia.org{country_name_entry['href']}").content, "lxml" ) .find("table", {"class": "infobox"}) .find("a", {"class": "image"}) @@ -129,7 +129,7 @@ def mk_country_list() -> list[tuple[str, str]]: def mk_element_list() -> list[tuple[str, Optional[str]]]: elem_list_soup = BeautifulSoup( - requests.get("https://en.wikipedia.org/wiki/List_of_chemical_elements").content, "html.parser" + requests.get("https://en.wikipedia.org/wiki/List_of_chemical_elements").content, "lxml" ).find_all("tr") elem_list: list[tuple[str, Optional[str]]] = [] for i in range(4, 118): @@ -139,7 +139,7 @@ def mk_element_list() -> list[tuple[str, Optional[str]]]: elem_img: Optional[str] = ( "https:" + BeautifulSoup( - requests.get(f"https://en.wikipedia.org{elem_name_entry['href']}").content, "html.parser" + requests.get(f"https://en.wikipedia.org{elem_name_entry['href']}").content, "lxml" ) .find("table", {"class": "infobox"}) .find("a") @@ -153,7 +153,7 @@ def mk_element_list() -> list[tuple[str, Optional[str]]]: def mk_movie_list() -> list[tuple[str, str]]: kino_elem_soup = BeautifulSoup( - requests.get("https://en.wikipedia.org/wiki/List_of_years_in_film").content, "html.parser" + requests.get("https://en.wikipedia.org/wiki/List_of_years_in_film").content, "lxml" ).find_all("i") kino_list: list[tuple[str, str]] = [] for i in range(195, len(kino_elem_soup)): @@ -162,7 +162,7 @@ def mk_movie_list() -> list[tuple[str, str]]: try: kino_img = ( "https:" - + BeautifulSoup(requests.get(f"https://en.wikipedia.org{kino_elem['href']}").content, "html.parser") + + BeautifulSoup(requests.get(f"https://en.wikipedia.org{kino_elem['href']}").content, "lxml") .find("table", {"class": "infobox"}) .find("a", {"class": "image"}) .find("img")["src"] diff --git a/poetry.lock b/poetry.lock index dd90714fe..49a810018 100644 --- a/poetry.lock +++ b/poetry.lock @@ -279,6 +279,20 @@ category = "dev" optional = false python-versions = "*" +[[package]] +name = "lxml" +version = "4.9.1" +description = "Powerful and Pythonic XML processing library combining libxml2/libxslt with the ElementTree API." +category = "main" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, != 3.4.*" + +[package.extras] +cssselect = ["cssselect (>=0.7)"] +html5 = ["html5lib"] +htmlsoup = ["BeautifulSoup4"] +source = ["Cython (>=0.29.7)"] + [[package]] name = "mpmath" version = "1.2.1" @@ -707,7 +721,7 @@ websockets = "*" [metadata] lock-version = "1.1" python-versions = "~3.10.0" -content-hash = "4e91de797c0006cb53d197e5f0664631aadb1446ca1ce258c75f755baa14d515" +content-hash = "8f6b854b763818669b1eacc38df9860f8ab0267058d2931f7cae8e1ad6243deb" [metadata.files] aiohttp = [ @@ -927,6 +941,78 @@ iniconfig = [ {file = "iniconfig-1.1.1-py2.py3-none-any.whl", hash = "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3"}, {file = "iniconfig-1.1.1.tar.gz", hash = "sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32"}, ] +lxml = [ + {file = "lxml-4.9.1-cp27-cp27m-macosx_10_15_x86_64.whl", hash = "sha256:98cafc618614d72b02185ac583c6f7796202062c41d2eeecdf07820bad3295ed"}, + {file = "lxml-4.9.1-cp27-cp27m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c62e8dd9754b7debda0c5ba59d34509c4688f853588d75b53c3791983faa96fc"}, + {file = "lxml-4.9.1-cp27-cp27m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:21fb3d24ab430fc538a96e9fbb9b150029914805d551deeac7d7822f64631dfc"}, + {file = "lxml-4.9.1-cp27-cp27m-win32.whl", hash = "sha256:86e92728ef3fc842c50a5cb1d5ba2bc66db7da08a7af53fb3da79e202d1b2cd3"}, + {file = "lxml-4.9.1-cp27-cp27m-win_amd64.whl", hash = "sha256:4cfbe42c686f33944e12f45a27d25a492cc0e43e1dc1da5d6a87cbcaf2e95627"}, + {file = "lxml-4.9.1-cp27-cp27mu-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:dad7b164905d3e534883281c050180afcf1e230c3d4a54e8038aa5cfcf312b84"}, + {file = "lxml-4.9.1-cp27-cp27mu-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:a614e4afed58c14254e67862456d212c4dcceebab2eaa44d627c2ca04bf86837"}, + {file = "lxml-4.9.1-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:f9ced82717c7ec65a67667bb05865ffe38af0e835cdd78728f1209c8fffe0cad"}, + {file = "lxml-4.9.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:d9fc0bf3ff86c17348dfc5d322f627d78273eba545db865c3cd14b3f19e57fa5"}, + {file = "lxml-4.9.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:e5f66bdf0976ec667fc4594d2812a00b07ed14d1b44259d19a41ae3fff99f2b8"}, + {file = "lxml-4.9.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:fe17d10b97fdf58155f858606bddb4e037b805a60ae023c009f760d8361a4eb8"}, + {file = "lxml-4.9.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:8caf4d16b31961e964c62194ea3e26a0e9561cdf72eecb1781458b67ec83423d"}, + {file = "lxml-4.9.1-cp310-cp310-win32.whl", hash = "sha256:4780677767dd52b99f0af1f123bc2c22873d30b474aa0e2fc3fe5e02217687c7"}, + {file = "lxml-4.9.1-cp310-cp310-win_amd64.whl", hash = "sha256:b122a188cd292c4d2fcd78d04f863b789ef43aa129b233d7c9004de08693728b"}, + {file = "lxml-4.9.1-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:be9eb06489bc975c38706902cbc6888f39e946b81383abc2838d186f0e8b6a9d"}, + {file = "lxml-4.9.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:f1be258c4d3dc609e654a1dc59d37b17d7fef05df912c01fc2e15eb43a9735f3"}, + {file = "lxml-4.9.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:927a9dd016d6033bc12e0bf5dee1dde140235fc8d0d51099353c76081c03dc29"}, + {file = "lxml-4.9.1-cp35-cp35m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9232b09f5efee6a495a99ae6824881940d6447debe272ea400c02e3b68aad85d"}, + {file = "lxml-4.9.1-cp35-cp35m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:04da965dfebb5dac2619cb90fcf93efdb35b3c6994fea58a157a834f2f94b318"}, + {file = "lxml-4.9.1-cp35-cp35m-win32.whl", hash = "sha256:4d5bae0a37af799207140652a700f21a85946f107a199bcb06720b13a4f1f0b7"}, + {file = "lxml-4.9.1-cp35-cp35m-win_amd64.whl", hash = "sha256:4878e667ebabe9b65e785ac8da4d48886fe81193a84bbe49f12acff8f7a383a4"}, + {file = "lxml-4.9.1-cp36-cp36m-macosx_10_15_x86_64.whl", hash = "sha256:1355755b62c28950f9ce123c7a41460ed9743c699905cbe664a5bcc5c9c7c7fb"}, + {file = "lxml-4.9.1-cp36-cp36m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:bcaa1c495ce623966d9fc8a187da80082334236a2a1c7e141763ffaf7a405067"}, + {file = "lxml-4.9.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6eafc048ea3f1b3c136c71a86db393be36b5b3d9c87b1c25204e7d397cee9536"}, + {file = "lxml-4.9.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:13c90064b224e10c14dcdf8086688d3f0e612db53766e7478d7754703295c7c8"}, + {file = "lxml-4.9.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:206a51077773c6c5d2ce1991327cda719063a47adc02bd703c56a662cdb6c58b"}, + {file = "lxml-4.9.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:e8f0c9d65da595cfe91713bc1222af9ecabd37971762cb830dea2fc3b3bb2acf"}, + {file = "lxml-4.9.1-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:8f0a4d179c9a941eb80c3a63cdb495e539e064f8054230844dcf2fcb812b71d3"}, + {file = "lxml-4.9.1-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:830c88747dce8a3e7525defa68afd742b4580df6aa2fdd6f0855481e3994d391"}, + {file = "lxml-4.9.1-cp36-cp36m-win32.whl", hash = "sha256:1e1cf47774373777936c5aabad489fef7b1c087dcd1f426b621fda9dcc12994e"}, + {file = "lxml-4.9.1-cp36-cp36m-win_amd64.whl", hash = "sha256:5974895115737a74a00b321e339b9c3f45c20275d226398ae79ac008d908bff7"}, + {file = "lxml-4.9.1-cp37-cp37m-macosx_10_15_x86_64.whl", hash = "sha256:1423631e3d51008871299525b541413c9b6c6423593e89f9c4cfbe8460afc0a2"}, + {file = "lxml-4.9.1-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:2aaf6a0a6465d39b5ca69688fce82d20088c1838534982996ec46633dc7ad6cc"}, + {file = "lxml-4.9.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:9f36de4cd0c262dd9927886cc2305aa3f2210db437aa4fed3fb4940b8bf4592c"}, + {file = "lxml-4.9.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:ae06c1e4bc60ee076292e582a7512f304abdf6c70db59b56745cca1684f875a4"}, + {file = "lxml-4.9.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:57e4d637258703d14171b54203fd6822fda218c6c2658a7d30816b10995f29f3"}, + {file = "lxml-4.9.1-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:6d279033bf614953c3fc4a0aa9ac33a21e8044ca72d4fa8b9273fe75359d5cca"}, + {file = "lxml-4.9.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:a60f90bba4c37962cbf210f0188ecca87daafdf60271f4c6948606e4dabf8785"}, + {file = "lxml-4.9.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:6ca2264f341dd81e41f3fffecec6e446aa2121e0b8d026fb5130e02de1402785"}, + {file = "lxml-4.9.1-cp37-cp37m-win32.whl", hash = "sha256:27e590352c76156f50f538dbcebd1925317a0f70540f7dc8c97d2931c595783a"}, + {file = "lxml-4.9.1-cp37-cp37m-win_amd64.whl", hash = "sha256:eea5d6443b093e1545ad0210e6cf27f920482bfcf5c77cdc8596aec73523bb7e"}, + {file = "lxml-4.9.1-cp38-cp38-macosx_10_15_x86_64.whl", hash = "sha256:f05251bbc2145349b8d0b77c0d4e5f3b228418807b1ee27cefb11f69ed3d233b"}, + {file = "lxml-4.9.1-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:487c8e61d7acc50b8be82bda8c8d21d20e133c3cbf41bd8ad7eb1aaeb3f07c97"}, + {file = "lxml-4.9.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:8d1a92d8e90b286d491e5626af53afef2ba04da33e82e30744795c71880eaa21"}, + {file = "lxml-4.9.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:b570da8cd0012f4af9fa76a5635cd31f707473e65a5a335b186069d5c7121ff2"}, + {file = "lxml-4.9.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5ef87fca280fb15342726bd5f980f6faf8b84a5287fcc2d4962ea8af88b35130"}, + {file = "lxml-4.9.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:93e414e3206779ef41e5ff2448067213febf260ba747fc65389a3ddaa3fb8715"}, + {file = "lxml-4.9.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:6653071f4f9bac46fbc30f3c7838b0e9063ee335908c5d61fb7a4a86c8fd2036"}, + {file = "lxml-4.9.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:32a73c53783becdb7eaf75a2a1525ea8e49379fb7248c3eeefb9412123536387"}, + {file = "lxml-4.9.1-cp38-cp38-win32.whl", hash = "sha256:1a7c59c6ffd6ef5db362b798f350e24ab2cfa5700d53ac6681918f314a4d3b94"}, + {file = "lxml-4.9.1-cp38-cp38-win_amd64.whl", hash = "sha256:1436cf0063bba7888e43f1ba8d58824f085410ea2025befe81150aceb123e345"}, + {file = "lxml-4.9.1-cp39-cp39-macosx_10_15_x86_64.whl", hash = "sha256:4beea0f31491bc086991b97517b9683e5cfb369205dac0148ef685ac12a20a67"}, + {file = "lxml-4.9.1-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:41fb58868b816c202e8881fd0f179a4644ce6e7cbbb248ef0283a34b73ec73bb"}, + {file = "lxml-4.9.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:bd34f6d1810d9354dc7e35158aa6cc33456be7706df4420819af6ed966e85448"}, + {file = "lxml-4.9.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:edffbe3c510d8f4bf8640e02ca019e48a9b72357318383ca60e3330c23aaffc7"}, + {file = "lxml-4.9.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6d949f53ad4fc7cf02c44d6678e7ff05ec5f5552b235b9e136bd52e9bf730b91"}, + {file = "lxml-4.9.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:079b68f197c796e42aa80b1f739f058dcee796dc725cc9a1be0cdb08fc45b000"}, + {file = "lxml-4.9.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:9c3a88d20e4fe4a2a4a84bf439a5ac9c9aba400b85244c63a1ab7088f85d9d25"}, + {file = "lxml-4.9.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:4e285b5f2bf321fc0857b491b5028c5f276ec0c873b985d58d7748ece1d770dd"}, + {file = "lxml-4.9.1-cp39-cp39-win32.whl", hash = "sha256:ef72013e20dd5ba86a8ae1aed7f56f31d3374189aa8b433e7b12ad182c0d2dfb"}, + {file = "lxml-4.9.1-cp39-cp39-win_amd64.whl", hash = "sha256:10d2017f9150248563bb579cd0d07c61c58da85c922b780060dcc9a3aa9f432d"}, + {file = "lxml-4.9.1-pp37-pypy37_pp73-macosx_10_15_x86_64.whl", hash = "sha256:0538747a9d7827ce3e16a8fdd201a99e661c7dee3c96c885d8ecba3c35d1032c"}, + {file = "lxml-4.9.1-pp37-pypy37_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:0645e934e940107e2fdbe7c5b6fb8ec6232444260752598bc4d09511bd056c0b"}, + {file = "lxml-4.9.1-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:6daa662aba22ef3258934105be2dd9afa5bb45748f4f702a3b39a5bf53a1f4dc"}, + {file = "lxml-4.9.1-pp38-pypy38_pp73-macosx_10_15_x86_64.whl", hash = "sha256:603a464c2e67d8a546ddaa206d98e3246e5db05594b97db844c2f0a1af37cf5b"}, + {file = "lxml-4.9.1-pp38-pypy38_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:c4b2e0559b68455c085fb0f6178e9752c4be3bba104d6e881eb5573b399d1eb2"}, + {file = "lxml-4.9.1-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:0f3f0059891d3254c7b5fb935330d6db38d6519ecd238ca4fce93c234b4a0f73"}, + {file = "lxml-4.9.1-pp39-pypy39_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:c852b1530083a620cb0de5f3cd6826f19862bafeaf77586f1aef326e49d95f0c"}, + {file = "lxml-4.9.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:287605bede6bd36e930577c5925fcea17cb30453d96a7b4c63c14a257118dbb9"}, + {file = "lxml-4.9.1.tar.gz", hash = "sha256:fe749b052bb7233fe5d072fcb549221a8cb1a16725c47c37e42b0b9cb3ff2c3f"}, +] mpmath = [ {file = "mpmath-1.2.1-py3-none-any.whl", hash = "sha256:604bc21bd22d2322a177c73bdb573994ef76e62edd595d17e00aff24b0667e5c"}, {file = "mpmath-1.2.1.tar.gz", hash = "sha256:79ffb45cf9f4b101a807595bcb3e72e0396202e0b1d25d689134b48c4216a81a"}, diff --git a/pyproject.toml b/pyproject.toml index 669240f99..a709f7e3d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -33,6 +33,7 @@ Pillow = "^8.3.2" uvloop = {version="0.16.0", markers = "sys_platform == 'linux' or sys_platform == 'darwin'"} bidict = "^0.22.0" aiosqlite = "^0.17.0" +lxml = "^4.9.1" [tool.poetry.dev-dependencies] pytest = "^7.0.71" From f03a3dbdd2895ea8a1c50cc5efae97dda73f84a4 Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Sun, 4 Sep 2022 14:22:04 -0400 Subject: [PATCH 055/127] fix STM subscriber (?) by disabling content type checking in custom requests --- canary/cogs/utils/custom_requests.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/canary/cogs/utils/custom_requests.py b/canary/cogs/utils/custom_requests.py index 856268b56..ded2565c5 100644 --- a/canary/cogs/utils/custom_requests.py +++ b/canary/cogs/utils/custom_requests.py @@ -44,6 +44,7 @@ async def fetch(url, type="content"): if type.lower() == "content": return await response.text() elif type.lower() == "json": - return await response.json() + # Disable content type checking since STM sucks and returns json as text/html + return await response.json(content_type=None) else: raise InvalidTypeException From 227d2ab5cdbab1e5f98c604d8613051d93ae952c Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Sun, 4 Sep 2022 14:22:46 -0400 Subject: [PATCH 056/127] add hashbang to hangman --- canary/cogs/utils/hangman.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/canary/cogs/utils/hangman.py b/canary/cogs/utils/hangman.py index 99889d4d5..d58a082a5 100644 --- a/canary/cogs/utils/hangman.py +++ b/canary/cogs/utils/hangman.py @@ -1,4 +1,5 @@ -# Copyright (C) idoneam (2016-2021) +#!/usr/bin/env python3 +# Copyright (C) idoneam (2016-2022) # # This file is part of Canary # From df4aa31c74e7a4d003a839aa15d88efe79d3a4f2 Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Sun, 4 Sep 2022 16:03:41 -0400 Subject: [PATCH 057/127] mild refactor of customreactions cog --- canary/cogs/customreactions.py | 335 +++++++++++++-------------------- 1 file changed, 134 insertions(+), 201 deletions(-) diff --git a/canary/cogs/customreactions.py b/canary/cogs/customreactions.py index 5fe3a21e9..cd1caa1e2 100644 --- a/canary/cogs/customreactions.py +++ b/canary/cogs/customreactions.py @@ -190,6 +190,10 @@ async def wait_for_message(message: discord.Message): await msg.delete() return content + async def clear_options(message: discord.Message): + current_options.clear() + await message.clear_reactions() + async def add_multiple_reactions(message: discord.Message, reactions): for reaction in reactions: await message.add_reaction(reaction) @@ -210,31 +214,49 @@ async def add_control_reactions(message: discord.Message): ), ) - async def create_assistant(message: discord.Message, is_moderator: bool): - if is_moderator: - description = ( - f"{EMOJI['new']} Add a new custom reaction\n" - f"{EMOJI['mag']} See the list of current reactions " - f"and modify them\n" - f"{EMOJI['pencil']} See the list of proposed reactions " - f"({get_number_of_proposals()}) " - f"and approve or reject them\n" - f"{EMOJI['grey_question']} List of placeholders" - ) - else: - description = ( - f"{EMOJI['new']} Propose a new custom reaction\n" - f"{EMOJI['mag']} See the list of current reactions\n" - f"{EMOJI['pencil']} See the list of proposed reactions " - f"({get_number_of_proposals()})\n" - f"{EMOJI['grey_question']} List of placeholders" - ) - current_options.extend( - (EMOJI["new"], EMOJI["mag"], EMOJI["pencil"], EMOJI["grey_question"], EMOJI["stop_button"]) - ) - await add_multiple_reactions( - message, (EMOJI["new"], EMOJI["mag"], EMOJI["pencil"], EMOJI["grey_question"], EMOJI["stop_button"]) - ) + async def create_assistant(message: discord.Message, is_moderator: bool) -> bool | None: + actions = { + # Add/Propose a new custom reaction + EMOJI["new"]: { + "fn": add_custom_react, + "desc": f"{'Add' if is_moderator else 'Propose'} a new custom reaction", + "kwargs": dict(proposals=not is_moderator), + }, + # List custom reactions + EMOJI["mag"]: { + "fn": list_custom_reacts, + "desc": "See the list of current reactions" + (" and modify them" if is_moderator else ""), + "kwargs": dict(proposals=False), + }, + # List proposals + EMOJI["pencil"]: { + "fn": list_custom_reacts, + "desc": f"See the list of proposed reactions ({get_number_of_proposals()})" + ( + " and approve or reject them" if is_moderator else ""), + "kwargs": dict(proposals=True), + }, + # List placeholders + EMOJI["grey_question"]: { + "fn": list_placeholders, + "desc": "List of placeholders", + "kwargs": dict(), + }, + # Stop + EMOJI["stop_button"]: { + "fn": leave, + "desc": "", + "kwargs": dict(), + "hidden": True, + }, + } + + description = "\n".join(f"{k} {v['desc']}" for k, v in actions.items() if not v.get("hidden")) + + action_keys = tuple(actions.keys()) + + current_options.extend(action_keys) + await add_multiple_reactions(message, action_keys) + await message.edit( embed=discord.Embed(title="Custom Reactions", description=description).set_footer( text=f"{main_user}: Click on an emoji to choose an " @@ -243,37 +265,21 @@ async def create_assistant(message: discord.Message, is_moderator: bool): icon_url=main_user.avatar_url, ) ) + try: reaction, user = await wait_for_reaction(message) except TypeError: return - current_options.clear() - await message.clear_reactions() - # Add/Propose a new custom reaction - if reaction.emoji == EMOJI["new"]: - await add_custom_react(message, is_moderator) - return - # List custom reactions - if reaction.emoji == EMOJI["mag"]: - await list_custom_reacts(message, proposals=False) - return - # List proposals - if reaction.emoji == EMOJI["pencil"]: - await list_custom_reacts(message, proposals=True) - return - # List placeholders - if reaction.emoji == EMOJI["grey_question"]: - await list_placeholders(message) - return - # Stop - if reaction.emoji == EMOJI["stop_button"]: - await leave(message) - return True - async def add_custom_react(message: discord.Message, is_moderator: bool): - status_msg = f"{main_user} is currently {'adding' if is_moderator else 'proposing'} a custom reaction." + await clear_options(message) + + if (action := actions.get(reaction.emoji)) is not None: + return await action["fn"](message, **action["kwargs"]) - title = f"{'Add' if is_moderator else 'Propose'} a custom reaction" + async def add_custom_react(message: discord.Message, proposals: bool): + status_msg = f"{main_user} is currently {'proposing' if proposals else 'adding'} a custom reaction." + + title = f"{'Propose' if proposals else 'Add'} a custom reaction" footer = f"{status_msg}\nWrite '{STOP_TEXT}' to cancel." description = "Write the prompt the bot will react to" @@ -311,20 +317,13 @@ async def _refresh_msg(): description = ( f"Prompt: {prompt_message}\nResponse: {response}\n" - f"React with the options " - f"you want and click {EMOJI['ok']} " - f"when you are ready\n" - f"{EMOJI['one']} Delete the message " - f"that calls the reaction\n" - f"{EMOJI['two']} Activate the custom " - f"reaction if the prompt is " - f"anywhere in a message \n" - f"{EMOJI['three']} React in the DMs of " - f"the user who calls the " - f"reaction instead of the channel\n" + f"React with the options you want and click {EMOJI['ok']} when you are ready\n" + f"{EMOJI['one']} Delete the message that calls the reaction\n" + f"{EMOJI['two']} Activate the custom reaction if the prompt is anywhere in a message \n" + f"{EMOJI['three']} React in the DMs of the user who calls the reaction instead of the channel\n" ) - footer = f"{main_user} is currently {'adding' if is_moderator else 'proposing'} a custom reaction." + footer = f"{main_user} is currently {'proposing' if proposals else 'adding'} a custom reaction." current_options.extend((EMOJI["ok"], EMOJI["stop_button"])) await add_multiple_reactions(message, (*NUMBERS[1:4], EMOJI["ok"], EMOJI["stop_button"])) @@ -354,19 +353,18 @@ async def _refresh_msg(): db: aiosqlite.Connection async with self.db() as db: await db.execute( - "INSERT INTO CustomReactions(Prompt, Response, UserID, " - "DeletePrompt, Anywhere, DM, Proposal) " + "INSERT INTO CustomReactions(Prompt, Response, UserID, DeletePrompt, Anywhere, DM, Proposal) " "VALUES(?, ?, ?, ?, ?, ?, ?)", - (prompt_message, response, main_user.id, delete, anywhere, dm, not is_moderator), + (prompt_message, response, main_user.id, delete, anywhere, dm, proposals), ) await db.commit() await self.rebuild_lists() - if is_moderator: - title = f"Custom reaction successfully added!" - else: + if proposals: title = "Custom reaction proposal successfully submitted!" + else: + title = "Custom reaction successfully added!" description = f"-Prompt: {prompt_message}\n-Response: {response}" if delete: description = f"{description}\n-Will delete the message that calls the reaction" @@ -386,10 +384,9 @@ async def _refresh_msg(): # Stop if reaction.emoji == EMOJI["stop_button"]: - await leave(message) - return True + return await leave(message) - async def list_custom_reacts(message: discord.Message, proposals): + async def list_custom_reacts(message: discord.Message, proposals: bool) -> bool | None: current_list = self.proposal_list if proposals else self.reaction_list no_items_msg = f"There are currently no custom reaction{' proposal' if proposals else ''}s in this server" @@ -402,11 +399,9 @@ async def list_custom_reacts(message: discord.Message, proposals): reaction_dict = { "names": [f"[{i + 1}]" for i in range(len(current_list))], "values": [ - f"Prompt: " - f"{reaction[1][:min(len(reaction[1]), 287)]}" - f'{"..." if len(reaction[1]) > 287 else ""}' - f"\nResponse: " - f"{reaction[2][:min(len(reaction[2]), 287)]}" + f"Prompt: {reaction[1][:min(len(reaction[1]), 287)]}" + f'{"..." if len(reaction[1]) > 287 else ""}\n' + f"Response: {reaction[2][:min(len(reaction[2]), 287)]}" f'{"..." if len(reaction[2]) > 287 else ""}' for reaction in current_list ], @@ -490,22 +485,18 @@ async def list_custom_reacts(message: discord.Message, proposals): ) else: - left = await information_on_react(message, current_list, number, proposals) - if left: - return True + if left := await information_on_react(message, current_list, number, proposals): + return left + if proposals: title = ( f"Current custom reaction proposals\n" - f"Click on {EMOJI['ok']} " - f"to approve, reject, edit, or " - f"see more information on one of them" + f"Click on {EMOJI['ok']} to approve, reject, edit, or see more information on one of them" ) else: title = ( f"Current custom reactions\n" - f"Click on {EMOJI['ok']} " - f"to edit or see more information " - f"on one of them" + f"Click on {EMOJI['ok']} to edit or see more information on one of them" ) # update dictionary since a custom reaction might have been @@ -542,7 +533,7 @@ async def list_custom_reacts(message: discord.Message, proposals): await add_control_reactions(message) user_modifying = await p.paginate() - async def information_on_react(message: discord.Message, current_list, number, proposals): + async def information_on_react(message: discord.Message, current_list, number, proposals) -> bool | None: await message.edit(embed=LOADING_EMBED) custom_react = current_list[number - 1] @@ -602,8 +593,7 @@ async def information_on_react(message: discord.Message, current_list, number, p f"current reactions in 40 seconds otherwise)" ) - current_options.clear() - await message.clear_reactions() + await clear_options(message) if proposals: current_options.extend((*NUMBERS[1:6], EMOJI["white_check_mark"], EMOJI["x"], EMOJI["stop_button"])) else: @@ -622,14 +612,12 @@ async def information_on_react(message: discord.Message, current_list, number, p reaction, user = await self.bot.wait_for( "reaction_add", check=get_reaction_check(moderators=True), timeout=40 ) - left = await edit_custom_react(message, reaction, user, custom_react, proposals) - if left: - return True + if left := await edit_custom_react(message, reaction, user, custom_react, proposals): + return left except asyncio.TimeoutError: pass - current_options.clear() - await message.clear_reactions() + await clear_options(message) async def edit_custom_react( message: discord.Message, @@ -637,11 +625,11 @@ async def edit_custom_react( user, custom_react, proposals, - ): + ) -> bool | None: db: aiosqlite.Connection - current_options.clear() - await message.clear_reactions() + await clear_options(message) + custom_react_id = custom_react[0] delete = custom_react[4] anywhere = custom_react[5] @@ -654,16 +642,25 @@ async def edit_custom_react( message_modified = f"Option successfully modified! Returning to list of {noun}s..." message_time_out = f"The modification of the {noun_custom} timed out. Returning to list of {noun}s..." + footer_modifying_stop = f"{user} is currently modifying a {noun_custom}. \nWrite '{STOP_TEXT}' to cancel." + footer_modified = f"Modified by {user}." + + async def _edit_reaction_and_rebuild(react_id, key, value): + db_: aiosqlite.Connection + async with self.db() as db_: + await db_.execute( + f"UPDATE CustomReactions SET {key} = ? WHERE CustomReactionID = ?", (value, react_id) + ) + await db_.commit() + await self.rebuild_lists() + # Edit the prompt if reaction.emoji == EMOJI["one"]: await message.edit( embed=( discord.Embed( title=f"Modify a {noun_custom}", description="Please enter the new prompt" - ).set_footer( - text=f"{user} is currently modifying a {noun_custom}. \nWrite '{STOP_TEXT}' to cancel.", - icon_url=user.avatar_url, - ) + ).set_footer(text=footer_modifying_stop, icon_url=user.avatar_url) ) ) @@ -678,21 +675,14 @@ async def edit_custom_react( await msg.delete() if prompt.lower() == STOP_TEXT: - await leave(message) - return True + return await leave(message) - async with self.db() as db: - await db.execute( - "UPDATE CustomReactions SET Prompt = ? WHERE CustomReactionID = ?", (prompt, custom_react_id) - ) - await db.commit() - - await self.rebuild_lists() + await _edit_reaction_and_rebuild(custom_react_id, "Prompt", prompt) await message.edit( embed=discord.Embed( title=f"Prompt successfully modified! Returning to list of {noun}s..." - ).set_footer(text=f"Modified by {user}.", icon_url=user.avatar_url) + ).set_footer(text=footer_modified, icon_url=user.avatar_url) ) await asyncio.sleep(5) @@ -701,10 +691,7 @@ async def edit_custom_react( await message.edit( embed=discord.Embed( title=f"Modify a {noun_custom}", description="Please enter the new response" - ).set_footer( - text=f"{user} is currently modifying a {noun_custom}. \nWrite '{STOP_TEXT}' to cancel.", - icon_url=user.avatar_url, - ) + ).set_footer(text=footer_modifying_stop, icon_url=user.avatar_url) ) try: @@ -718,20 +705,13 @@ async def edit_custom_react( await msg.delete() if response.lower() == STOP_TEXT: - await leave(message) - return True + return await leave(message) - async with self.db() as db: - await db.execute( - "UPDATE CustomReactions SET Response = ? WHERE CustomReactionID = ?", - (response, custom_react_id), - ) - await db.commit() + await _edit_reaction_and_rebuild(custom_react_id, "Response", response) - await self.rebuild_lists() title = f"Response successfully modified! Returning to list of {noun}s..." await message.edit( - embed=discord.Embed(title=title).set_footer(text=f"Modified by {user}.", icon_url=user.avatar_url) + embed=discord.Embed(title=title).set_footer(text=footer_modified, icon_url=user.avatar_url) ) await asyncio.sleep(5) @@ -774,8 +754,7 @@ async def edit_custom_react( await message.clear_reactions() if reaction.emoji == EMOJI["stop_button"]: - await leave(message) - return True + return await leave(message) if reaction.emoji in (EMOJI["zero"], EMOJI["one"]): # 0: Deactivate the "delete" option @@ -785,19 +764,11 @@ async def edit_custom_react( if delete == new_value: title = message_kept else: - async with self.db() as db: - await db.execute( - "UPDATE CustomReactions SET DeletePrompt = ? WHERE CustomReactionID = ?", - (new_value, custom_react_id), - ) - await db.commit() - await self.rebuild_lists() title = message_modified + await _edit_reaction_and_rebuild(custom_react_id, "DeletePrompt", new_value) await message.edit( - embed=discord.Embed(title=title).set_footer( - text=f"Modified by {user}.", icon_url=user.avatar_url - ) + embed=discord.Embed(title=title).set_footer(text=footer_modified, icon_url=user.avatar_url) ) await asyncio.sleep(5) @@ -838,8 +809,7 @@ async def edit_custom_react( await message.clear_reactions() if reaction.emoji == EMOJI["stop_button"]: - await leave(message) - return True + return await leave(message) if reaction.emoji in (EMOJI["zero"], EMOJI["one"]): # 0: Deactivate the "anywhere" option @@ -849,19 +819,11 @@ async def edit_custom_react( if anywhere == new_value: title = message_kept else: - async with self.db() as db: - await db.execute( - "UPDATE CustomReactions SET Anywhere = ? WHERE CustomReactionID = ?", - (new_value, custom_react_id), - ) - await db.commit() - await self.rebuild_lists() title = message_modified + await _edit_reaction_and_rebuild(custom_react_id, "Anywhere", new_value) await message.edit( - embed=discord.Embed(title=title).set_footer( - text=f"Modified by {user}.", icon_url=user.avatar_url - ) + embed=discord.Embed(title=title).set_footer(text=footer_modified, icon_url=user.avatar_url) ) await asyncio.sleep(5) @@ -905,8 +867,7 @@ async def edit_custom_react( await message.clear_reactions() if reaction.emoji == EMOJI["stop_button"]: - await leave(message) - return True + return await leave(message) if reaction.emoji in (EMOJI["zero"], EMOJI["one"]): # 0: Deactivate the "dm" option @@ -916,32 +877,18 @@ async def edit_custom_react( if dm == new_value: title = message_kept else: - async with self.db() as db: - await db.execute( - "UPDATE CustomReactions SET DM = ? WHERE CustomReactionID = ?", - (new_value, custom_react_id), - ) - await db.commit() - await self.rebuild_lists() title = message_modified + await _edit_reaction_and_rebuild(custom_react_id, "DM", new_value) await message.edit( - embed=discord.Embed(title=title).set_footer( - text=f"Modified by {user}.", icon_url=user.avatar_url - ) + embed=discord.Embed(title=title).set_footer(text=footer_modified, icon_url=user.avatar_url) ) await asyncio.sleep(5) # Approve a custom reaction proposal if reaction.emoji == EMOJI["white_check_mark"]: - async with self.db() as db: - await db.execute( - "UPDATE CustomReactions SET Proposal = ? WHERE CustomReactionID = ?", (0, custom_react_id) - ) - await db.commit() - - await self.rebuild_lists() + await _edit_reaction_and_rebuild(custom_react_id, "Proposal", 0) await message.edit( embed=discord.Embed( @@ -967,51 +914,37 @@ async def edit_custom_react( # Stop if reaction.emoji == EMOJI["stop_button"]: - await leave(message) - return True + return await leave(message) - async def list_placeholders(message): + async def list_placeholders(message, **_kwargs): title = "The following placeholders can be used in prompts and responses:" description = ( - "-%user%: the user who called " - "the prompt (can only be used in a response)\n" - "-%channel%: the name of " - "the channel where the prompt was called " - "(can only be used in a response) \n" - "-%1%, %2%, etc. up to %9%: Groups. When a " - "prompt uses this, anything will match. For " - 'example, the prompt "i %1% apples" will work ' - 'for any message that starts with "i" and ends ' - 'with "apples", such as "i really like ' - 'apples". Then, the words that match to this ' - "group can be used in the response. For example, " - "keeping the same prompt and using the response " - '"i %1% pears" will send ' - '"i really like pears"\n' - "-%[]%: a comma-separated choice list. There are " - "two uses for this. The first is that when it is " - "used in a prompt, the prompt will accept either " - "of the choices. For example, the prompt " - '"%[hello, hi, hey]% world" will work if someone ' - 'writes "hello world", "hi world" or ' + "-%user%: the user who called the prompt (can only be used in a response)\n" + "-%channel%: the name of the channel where the prompt was called (can only be used in a response) \n" + "-%1%, %2%, etc. up to %9%: Groups. When a prompt uses this, anything will match. For " + 'example, the prompt "i %1% apples" will work for any message that starts with "i" and ends ' + 'with "apples", such as "i really like apples". Then, the words that match to this ' + "group can be used in the response. For example, keeping the same prompt and using the response " + '"i %1% pears" will send "i really like pears"\n' + "-%[]%: a comma-separated choice list. There are two uses for this. The first is that when it is " + "used in a prompt, the prompt will accept either of the choices. For example, the prompt " + '"%[hello, hi, hey]% world" will work if someone writes "hello world", "hi world" or ' '"hey world". The second use is that when it is ' - "used in a response, a random choice will be " - "chosen from the list. For example, the response " - '"i %[like, hate]% you" will either send "i ' - 'like you" or "i hate you". All placeholders ' - "can be used in choice lists (including choice " - "lists themselves). If a choice contains commas, " - 'it can be surrounded by "" to not be split into ' - "different choices" + "used in a response, a random choice will be chosen from the list. For example, the response " + '"i %[like, hate]% you" will either send "i like you" or "i hate you". All placeholders ' + "can be used in choice lists (including choice lists themselves). If a choice contains commas, " + 'it can be surrounded by "" to not be split into different choices' ) await message.edit(embed=discord.Embed(title=title, description=description)) - async def leave(message): + async def leave(message, **_kwargs) -> True: await message.delete() + return True initial_message = await ctx.send(embed=LOADING_EMBED) is_mod = discord.utils.get(main_user.roles, name=self.bot.config.moderator_role) is not None - await create_assistant(initial_message, is_mod) + + return await create_assistant(initial_message, is_mod) def setup(bot): From 9a948f3f1665606ba311d358e41c37a1f926ed23 Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Sun, 4 Sep 2022 18:00:22 -0400 Subject: [PATCH 058/127] feat: higher level abstraction for fetching lists --- canary/bot.py | 3 + canary/cogs/base_cog.py | 15 +++ canary/cogs/currency.py | 14 +- canary/cogs/customreactions.py | 12 +- canary/cogs/mod.py | 22 ++-- canary/cogs/quotes.py | 228 +++++++++++++++------------------ canary/cogs/reminder.py | 36 +++--- canary/cogs/score.py | 134 +++++++++---------- 8 files changed, 216 insertions(+), 248 deletions(-) diff --git a/canary/bot.py b/canary/bot.py index 9ae574105..e43c77b9b 100644 --- a/canary/bot.py +++ b/canary/bot.py @@ -103,6 +103,9 @@ async def db(self) -> AsyncGenerator[aiosqlite.Connection, None]: await conn.execute("PRAGMA foreign_keys = ON") yield conn + async def db_nocm(self) -> aiosqlite.Connection: + return await aiosqlite.connect(self.config.db_path) + async def _start_database(self): if not self.config.db_path: self.dev_logger.warning("No path to database configuration file") diff --git a/canary/cogs/base_cog.py b/canary/cogs/base_cog.py index 1019fdf6b..19a542873 100644 --- a/canary/cogs/base_cog.py +++ b/canary/cogs/base_cog.py @@ -31,6 +31,21 @@ async def db(self) -> AsyncGenerator[aiosqlite.Connection, None]: async with self.bot.db() as conn: yield conn + async def fetch_list( + self, + query: str, + params: tuple[str | int | float | bool, ...] = (), + db: aiosqlite.Connection | None = None, + ) -> list[tuple]: + if fresh_db := db is None: + db = await self.bot.db_nocm() + try: + async with db.execute(query, params) as c: + return [tuple(r) for r in await c.fetchall()] + finally: + if fresh_db: + await db.close() + async def get_settings_key(self, key: str) -> str | None: db: aiosqlite.Connection async with self.db() as db: diff --git a/canary/cogs/currency.py b/canary/cogs/currency.py index 665dab342..91ed08522 100644 --- a/canary/cogs/currency.py +++ b/canary/cogs/currency.py @@ -65,17 +65,15 @@ def __init__(self, bot: Canary): self.prec: int = self.currency["precision"] async def fetch_all_balances(self) -> list[tuple[str, str, Decimal]]: - db: aiosqlite.Connection - async with self.db() as db: - c: aiosqlite.Cursor - async with db.execute( + # after + return [ + (user_id, name, self.db_to_currency(balance)) + for user_id, name, balance in (await self.fetch_list( "SELECT BT.UserID, M.Name, IFNULL(SUM(BT.Amount), 0) " "FROM BankTransactions AS BT, Members as M " "WHERE BT.UserID = M.ID GROUP BY UserID" - ) as c: - return [ - (user_id, name, self.db_to_currency(balance)) for user_id, name, balance in (await c.fetchall()) - ] + )) + ] async def fetch_bank_balance(self, user: discord.Member) -> Decimal: db: aiosqlite.Connection diff --git a/canary/cogs/customreactions.py b/canary/cogs/customreactions.py index cd1caa1e2..bdc5cb5c3 100644 --- a/canary/cogs/customreactions.py +++ b/canary/cogs/customreactions.py @@ -74,11 +74,7 @@ async def rebuild_lists(self): await self.rebuild_proposal_list() async def rebuild_reaction_list(self): - db: aiosqlite.Connection - async with self.db() as db: - c: aiosqlite.Cursor - async with db.execute("SELECT * FROM CustomReactions WHERE Proposal = 0") as c: - self.reaction_list = [tuple(r) for r in (await c.fetchall())] + self.reaction_list = await self.fetch_list("SELECT * FROM CustomReactions WHERE Proposal = 0") prompts = [row[1].lower() for row in self.reaction_list] responses = [row[2] for row in self.reaction_list] @@ -89,11 +85,7 @@ async def rebuild_reaction_list(self): ) async def rebuild_proposal_list(self): - db: aiosqlite.Connection - async with self.db() as db: - c: aiosqlite.Cursor - async with db.execute("SELECT * FROM CustomReactions WHERE Proposal = 1") as c: - self.proposal_list = [tuple(r) for r in (await c.fetchall())] + self.proposal_list = await self.fetch_list("SELECT * FROM CustomReactions WHERE Proposal = 1") @commands.Cog.listener() async def on_message(self, message: discord.Message): diff --git a/canary/cogs/mod.py b/canary/cogs/mod.py index 217a14f76..b3ec9c8c7 100644 --- a/canary/cogs/mod.py +++ b/canary/cogs/mod.py @@ -14,7 +14,7 @@ # # You should have received a copy of the GNU General Public License # along with Canary. If not, see . -import aiosqlite + import discord import random from bidict import bidict @@ -54,16 +54,12 @@ async def on_ready(self): await self.verification_purge_startup() - db: aiosqlite.Connection - c: aiosqlite.Cursor - async with self.db() as db: - async with db.execute("SELECT * FROM MutedUsers") as c: - self.muted_users_to_appeal_channels = bidict( - [ - (self.bot.get_user(user_id), self.bot.get_channel(appeal_channel_id)) - for (user_id, appeal_channel_id, roles, date) in (await c.fetchall()) - ] - ) + self.muted_users_to_appeal_channels = bidict( + [ + (self.bot.get_user(user_id), self.bot.get_channel(appeal_channel_id)) + for (user_id, appeal_channel_id, roles, date) in (await self.fetch_list("SELECT * FROM MutedUsers")) + ] + ) self.appeals_log_channel = utils.get(self.guild.text_channels, name=self.bot.config.appeals_log_channel) self.muted_role = utils.get(self.guild.roles, name=self.bot.config.muted_role) @@ -73,7 +69,7 @@ async def verification_purge_startup(self): if not self.verification_channel: return - # arbitrary min date because choosing dates that predate discord will cause an httpexception + # arbitrary min date because choosing dates that predate discord will cause an HTTPException # when fetching message history after that date later on self.last_verification_purge_datetime = datetime(2018, 1, 1) @@ -451,7 +447,7 @@ async def on_message(self, message): await self.appeals_log_channel.send(log_message) @CanaryCog.listener() - async def on_message_edit(self, before, after): + async def on_message_edit(self, _before, after): if after.channel not in self.muted_users_to_appeal_channels.values(): return diff --git a/canary/cogs/quotes.py b/canary/cogs/quotes.py index a3d554922..aff5c36dd 100644 --- a/canary/cogs/quotes.py +++ b/canary/cogs/quotes.py @@ -53,11 +53,7 @@ async def rebuild_mc(self): Blame David for this code. """ - db: aiosqlite.Connection - async with self.db() as db: - async with db.execute("SELECT Quote FROM Quotes") as c: - all_quotes = await c.fetchall() - + all_quotes: list[tuple[str]] = await self.fetch_list("SELECT Quote FROM Quotes") lookup: dict[str, dict] = {} for q in all_quotes: @@ -136,8 +132,8 @@ def check(reaction, user): # returns True if all the following is true: # The user who reacted is either the quoter or the quoted person # The user who reacted isn't the bot - # The react is the delete emoji - # The react is on the "Quote added." message + # The reaction is the Delete emoji + # The reaction is on the "Quote added." message return ( (user == ctx.message.author or user == member) and user != self.bot.user @@ -167,65 +163,57 @@ async def quotes(self, ctx, str1: str = None, *, str2: str = None): quotes: list[tuple[int, str, str]] - db: aiosqlite.Connection - c: aiosqlite.Cursor - async with self.db() as db: - mentions = ctx.message.mentions - - if str1 is None: # No argument passed - async with db.execute("SELECT ID, Name, Quote FROM Quotes") as c: - quotes = [tuple(r) for r in await c.fetchall()] - - elif mentions and mentions[0].mention == str1: # Has args - u_id = mentions[0].id - # Query for either user and quote or user only (None) - async with db.execute( - "SELECT ID, Name, Quote FROM Quotes WHERE ID = ? AND Quote LIKE ?", - (u_id, f"%{str2 if str2 is not None else ''}%"), - ) as c: - quotes = [tuple(r) for r in await c.fetchall()] - - else: # query for quote only - query = str1 if str2 is None else f"{str1} {str2}" - if query[0] == "/" and query[-1] == "/": - async with db.execute("SELECT ID, Name, Quote FROM Quotes") as c: - quotes = [tuple(r) for r in await c.fetchall()] - try: - quotes = [q for q in quotes if re.search(query[1:-1], q[2])] - except re.error: - await ctx.send("Invalid regex syntax.") - return - else: - async with db.execute( - "SELECT ID, Name, Quote FROM Quotes WHERE Quote LIKE ?", - (f"%{query}%",), - ) as c: - quotes = [tuple(r) for r in await c.fetchall()] - - if not quotes: - msg = await ctx.send("Quote not found.\n") - await msg.add_reaction("🆗") - - def check(reaction, user): - # returns True if all the following is true: - # The user who reacted isn't the bot - # The react is the ok emoji - # The react is on the "Quote not found." message - return (user == ctx.message.author and user != self.bot.user) and ( - str(reaction.emoji) == "🆗" and reaction.message.id == msg.id - ) + mentions = ctx.message.mentions + if str1 is None: # No argument passed + quotes = await self.fetch_list("SELECT ID, Name, Quote FROM Quotes") + + elif mentions and mentions[0].mention == str1: # Has args + u_id = mentions[0].id + # Query for either user and quote or user only (None) + quotes = await self.fetch_list( + "SELECT ID, Name, Quote FROM Quotes WHERE ID = ? AND Quote LIKE ?", + (u_id, f"%{str2 if str2 is not None else ''}%"), + ) + + else: # query for quote only + query = str1 if str2 is None else f"{str1} {str2}" + if query[0] == "/" and query[-1] == "/": try: - await self.bot.wait_for("reaction_add", check=check, timeout=120) + quotes = [ + q for q in (await self.fetch_list("SELECT ID, Name, Quote FROM Quotes")) + if re.search(query[1:-1], q[2]) + ] + except re.error: + await ctx.send("Invalid regex syntax.") + return + else: + quotes = await self.fetch_list("SELECT ID, Name, Quote FROM Quotes WHERE Quote LIKE ?", (f"%{query}%",)) - except asyncio.TimeoutError: - await msg.remove_reaction("🆗", self.bot.user) + if not quotes: + msg = await ctx.send("Quote not found.\n") + await msg.add_reaction("🆗") - else: - await ctx.message.delete() - await msg.delete() + def check(reaction, user): + # returns True if all the following is true: + # The user who reacted isn't the bot + # The reaction is the ok emoji + # The reaction is on the "Quote not found." message + return (user == ctx.message.author and user != self.bot.user) and ( + str(reaction.emoji) == "🆗" and reaction.message.id == msg.id + ) - return + try: + await self.bot.wait_for("reaction_add", check=check, timeout=120) + + except asyncio.TimeoutError: + await msg.remove_reaction("🆗", self.bot.user) + + else: + await ctx.message.delete() + await msg.delete() + + return quote_tuple: tuple[int, str, str] = random.choice(quotes) author_id = int(quote_tuple[0]) @@ -255,71 +243,68 @@ async def list_quotes(self, ctx: commands.Context, author: discord.Member = None List quotes """ - await ctx.trigger_typing() - db: aiosqlite.Connection - async with self.db() as db: - c: aiosqlite.Cursor + c: aiosqlite.Cursor - quote_author = author if author else ctx.message.author - author_id = quote_author.id + await ctx.trigger_typing() - async with db.execute("SELECT * FROM Quotes WHERE ID = ?", (author_id,)) as c: - quote_list: list[aiosqlite.Row] = list(await c.fetchall()) + quote_author = author if author else ctx.message.author + author_id = quote_author.id - if not quote_list: - await ctx.send("No quote found.", delete_after=60) - return + quote_list: list[tuple] = await self.fetch_list("SELECT * FROM Quotes WHERE ID = ?", (author_id,)) + if not quote_list: + await ctx.send("No quote found.", delete_after=60) + return - quote_list_text = [f"[{i}] {quote[2]}" for i, quote in enumerate(quote_list, 1)] + quote_list_text = [f"[{i}] {quote[2]}" for i, quote in enumerate(quote_list, 1)] - p = Pages(ctx, item_list=quote_list_text, title="Quotes from {}".format(quote_author.display_name)) + p = Pages(ctx, item_list=quote_list_text, title="Quotes from {}".format(quote_author.display_name)) - await p.paginate() + await p.paginate() - def msg_check(msg): - try: - return ( - 0 <= int(msg.content) <= len(quote_list) - and msg.author.id == author_id - and msg.channel == ctx.message.channel - ) - except ValueError: - return False - - while p.edit_mode: - await ctx.send( - "Delete option selected. Enter a number to specify which " - "quote you want to delete, or enter 0 to return.", - delete_after=60, + def msg_check(msg): + try: + return ( + 0 <= int(msg.content) <= len(quote_list) + and msg.author.id == author_id + and msg.channel == ctx.message.channel ) + except ValueError: + return False - try: - message = await self.bot.wait_for("message", check=msg_check, timeout=60) + while p.edit_mode: + await ctx.send( + "Delete option selected. Enter a number to specify which " + "quote you want to delete, or enter 0 to return.", + delete_after=60, + ) - except asyncio.TimeoutError: - await ctx.send("Command timeout. You may want to run the command again.", delete_after=60) - break + try: + message = await self.bot.wait_for("message", check=msg_check, timeout=60) + + except asyncio.TimeoutError: + await ctx.send("Command timeout. You may want to run the command again.", delete_after=60) + break + else: + index = int(message.content) - 1 + if index == -1: + await ctx.send("Exit delq.", delete_after=60) else: - index = int(message.content) - 1 - if index == -1: - await ctx.send("Exit delq.", delete_after=60) - else: - del quote_list[index] + q = quote_list[index] - await db.execute( - "DELETE FROM Quotes WHERE ID = ? AND Quote = ?", - (quote_list[index][0], quote_list[index][2]), - ) + del quote_list[index] + + async with self.db() as db: + await db.execute("DELETE FROM Quotes WHERE ID = ? AND Quote = ?", (q[0], q[2])) await db.commit() - await ctx.send("Quote deleted", delete_after=60) - await message.delete() + await ctx.send("Quote deleted", delete_after=60) + await message.delete() - p.itemList = [f"[{i}] {quote[2]}" for i, quote in enumerate(quote_list, 1)] + p.itemList = [f"[{i}] {quote[2]}" for i, quote in enumerate(quote_list, 1)] - await p.paginate() + await p.paginate() @commands.command(aliases=["allq", "aq"]) async def all_quotes(self, ctx: commands.Context, *, query: str): @@ -352,22 +337,17 @@ async def all_quotes(self, ctx: commands.Context, *, query: str): query = " ".join(query_splitted) await ctx.trigger_typing() - db: aiosqlite.Connection - async with self.db() as db: - c: aiosqlite.Cursor - - if query[0] == "/" and query[-1] == "/": - async with db.execute("SELECT * FROM Quotes") as c: - quotes = list(await c.fetchall()) - - try: - quote_list = [q for q in quotes if re.search(query[1:-1], q[2])] - except re.error: - await ctx.send("Invalid regex syntax.") - return - else: - async with db.execute("SELECT * FROM Quotes WHERE Quote LIKE ?", (f"%{query}%",)) as c: - quote_list = list(await c.fetchall()) + if query[0] == "/" and query[-1] == "/": + try: + quote_list = [ + q for q in (await self.fetch_list("SELECT * FROM Quotes")) + if re.search(query[1:-1], q[2]) + ] + except re.error: + await ctx.send("Invalid regex syntax.") + return + else: + quote_list = await self.fetch_list("SELECT * FROM Quotes WHERE Quote LIKE ?", (f"%{query}%",)) if not quote_list: await ctx.send("No quote found.", delete_after=60) diff --git a/canary/cogs/reminder.py b/canary/cogs/reminder.py index 92692e607..149bf7fef 100644 --- a/canary/cogs/reminder.py +++ b/canary/cogs/reminder.py @@ -102,10 +102,8 @@ async def check_reminders(self): if not (guild := self.guild): return - db: aiosqlite.Connection async with self.db() as db: - async with db.execute("SELECT * FROM Reminders") as c: - reminders = [tuple(r) for r in (await c.fetchall())] + reminders = await self.fetch_list("SELECT * FROM Reminders", db=db) for i in range(len(reminders)): member = discord.utils.get(guild.members, id=reminders[i][0]) @@ -117,7 +115,7 @@ async def check_reminders(self): # Compute future_date and current_date and if past, means # time is due to remind user. if reminder_activation_date <= datetime.datetime.now(): - await member.send("Reminding you to {}!".format(reminders[i][2])) + await member.send(f"Reminding you to {reminders[i][2]}!") # Remove from from DB non-repeating reminder await db.execute( ("DELETE FROM Reminders WHERE Reminder=? AND ID=?" + " AND DATE=?"), @@ -252,15 +250,17 @@ async def remindme(self, ctx: commands.Context, *, quote: str = ""): await db.execute("INSERT INTO Reminders VALUES (?, ?, ?, ?, ?, ?)", t) await db.commit() - # Send user information and close database - async with db.execute("SELECT * FROM Reminders WHERE ID =?", (ctx.message.author.id,)) as c: - reminders = [tuple(r) for r in (await c.fetchall())] + # Send user information + + async with db.execute("SELECT COUNT(*) FROM Reminders WHERE ID = ?", (ctx.message.author.id,)) as c: + # noinspection PyRedundantParentheses + num_reminders = ((await c.fetchone()) or (0,))[0] await ctx.author.send( "Hi {}! \nI will remind you to {} on {} at {} unless you " "send me a message to stop reminding you about it! " "[{:d}]".format( - ctx.author.name, reminder, date_result.group(0), time_result.group(0), len(reminders) + 1 + ctx.author.name, reminder, date_result.group(0), time_result.group(0), num_reminders + 1 ) ) @@ -311,9 +311,7 @@ async def remindme(self, ctx: commands.Context, *, quote: str = ""): # DB: Date will hold TDELTA (When reminder is due), LastReminder will # hold datetime.datetime.now() async with self.db() as db: - async with db.execute("SELECT * FROM Reminders WHERE ID =?", (ctx.message.author.id,)) as c: - reminders = [tuple(r) for r in (await c.fetchall())] - + reminders = await self.fetch_list("SELECT * FROM Reminders WHERE ID =?", (ctx.message.author.id,), db=db) t = (ctx.message.author.id, ctx.message.author.name, reminder, "once", reminder_time, time_now) await db.execute("INSERT INTO Reminders VALUES (?, ?, ?, ?, ?, ?)", t) await db.commit() @@ -363,10 +361,7 @@ async def list_reminders(self, ctx): rem_author = ctx.message.author - async with self.db() as db: - async with db.execute("SELECT * FROM Reminders WHERE ID = ?", (rem_author.id,)) as c: - rem_list = [tuple(r) for r in (await c.fetchall())] - + rem_list = await self.fetch_list("SELECT * FROM Reminders WHERE ID = ?", (rem_author.id,)) if not rem_list: await ctx.send("No reminder found.", delete_after=60) return @@ -412,14 +407,13 @@ def msg_check(msg): await ctx.send("Exit delq.", delete_after=60) else: + r = rem_list[index] + # Remove deleted reminder from list: del rem_list[index] async with self.db() as db: - await db.execute( - "DELETE FROM Reminders WHERE ID = ? AND Reminder = ?", - (rem_list[index][0], rem_list[index][2]), - ) + await db.execute("DELETE FROM Reminders WHERE ID = ? AND Reminder = ?", (r[0], r[2])) await db.commit() await ctx.send("Reminder deleted", delete_after=60) @@ -485,8 +479,8 @@ async def __remindme_repeating(self, ctx: commands.Context, freq: str = "", *, q quote = quote[3:] await ctx.author.send( - "Hi {}! \nI will remind you to {} {} until you send me a message " - "to stop reminding you about it! [{:d}]".format(ctx.author.name, quote, freq, num_reminders + 1) + f"Hi {ctx.author.name}! \nI will remind you to {quote} {freq} until you send me a message " + f"to stop reminding you about it! [{num_reminders+1:d}]" ) await ctx.send("Reminder added.") diff --git a/canary/cogs/score.py b/canary/cogs/score.py index d01b78eac..7e0213f02 100644 --- a/canary/cogs/score.py +++ b/canary/cogs/score.py @@ -165,9 +165,9 @@ async def _get_converted_args_dict(ctx, args, from_xnor_to=False, from_nand_to=F # this will make an arg_converter with the possible values the # score, ranking, and emoji_ranking function can take, then do # additional checks to restrict it further - # If from_xnor_to, then if there is a from flag there must be a - # to flag and vice versa (used by score and emoji_ranking) - # If from_nand_to, there can either be a from or a to flag + # If from_xnor_to, then if there is a `from` flag there must be a + # `to` flag and vice versa (used by score and emoji_ranking) + # If from_nand_to, there can either be a `from` or a `to` flag # or nothing, not both (used by ranking) # If member, then a member can be input (will still look for # from/to flags but will raise an exception if both a member and @@ -278,7 +278,7 @@ def _where_str_and_values_from_args_dict(self, args_dict, prefix=None): values_list = values_list + guild_emojis # elif args_dict["emojitype"] == "all", there are no restrictions # elif args_dict["emojitype"] == "score", this must be dealt with - # outside of this function as this does not use a where close + # outside this function as this does not use a where close if not args_dict["self"]: where_list.append("ReacterID != ReacteeID") if args_dict["before"]: @@ -363,7 +363,7 @@ async def score(self, ctx: commands.Context, *args): -If @user or User, gives the score for this user. -If from and to flags, gives the score given from @userA to @userB. `from:all` and `to:all` can be used. -If nothing, gives your score - Note that it is possible to give usernames without mention. This is case sensitive. If a username contains a + Note that it is possible to give usernames without mention. This is case-sensitive. If a username contains a space, the username and flag must be included in quotes, e.g. "to:user name" - Optional: `emoji` OR `emojitype:type` OR `emojiname:name` OR `:name:` @@ -431,7 +431,7 @@ async def ranking(self, ctx, *args): -If from flag: gives the score received by every user from this user. `from:all` can be used. -If to flag: gives the score received by this user from every user. `to:all` can be used. -If nothing, gives the score of every user - Note that it is possible to give usernames without mention. This is case sensitive. If a username contains a + Note that it is possible to give usernames without mention. This is case-sensitive. If a username contains a space, the username and flag must be included in quotes, e.g. "to:user name" - Optional: `emoji` OR `emojitype:type` OR `emojiname:name` OR `:name:` @@ -462,60 +462,54 @@ async def ranking(self, ctx, *args): await ctx.send(err) return - db: aiosqlite.Connection - async with self.db() as db: - c: aiosqlite.Cursor + select_id = "ReacterID" if args_dict["to_member"] else "ReacteeID" - select_id = "ReacterID" if args_dict["to_member"] else "ReacteeID" - - if args_dict["emojitype"] != "score": - # get the WHERE conditions and the values - where_str, t = self._where_str_and_values_from_args_dict(args_dict) - async with db.execute( - ( - f"SELECT printf('%d. %s', " - f"ROW_NUMBER() OVER (ORDER BY count(*) DESC), M.Name), " - f"printf('%d %s', count(*), " - f"IIF (count(*)!=1, 'times', 'time')) " - f"FROM Reactions AS R, Members as M " - f"WHERE {where_str} " - f"AND R.{select_id} = M.ID " - f"GROUP BY R.{select_id} " - f"ORDER BY count(*) DESC" - ), - t, - ) as c: - counts = list(zip(*(await c.fetchall()))) + if args_dict["emojitype"] != "score": + # get the WHERE conditions and the values + where_str, t = self._where_str_and_values_from_args_dict(args_dict) + counts = list(zip(*(await self.fetch_list( + ( + f"SELECT printf('%d. %s', " + f"ROW_NUMBER() OVER (ORDER BY count(*) DESC), M.Name), " + f"printf('%d %s', count(*), " + f"IIF (count(*)!=1, 'times', 'time')) " + f"FROM Reactions AS R, Members as M " + f"WHERE {where_str} " + f"AND R.{select_id} = M.ID " + f"GROUP BY R.{select_id} " + f"ORDER BY count(*) DESC" + ), + t, + )))) - if not counts: - await ctx.send(embed=discord.Embed(title="This reaction was never used on this server.")) - return + if not counts: + await ctx.send(embed=discord.Embed(title="This reaction was never used on this server.")) + return - else: - # get the WHERE conditions and the values - where_str, t = self._where_str_and_values_from_args_dict(args_dict, prefix="R") - async with db.execute( - ( - f"SELECT printf('%d. %s', " - f"ROW_NUMBER() OVER (ORDER BY TotalCount DESC), Name), " - f"TotalCount FROM " - f"(SELECT M.Name, " - f"COUNT(IIF (ReactionName = ?1, 1, NULL)) - " - f"COUNT(IIF (ReactionName = ?2, 1, NULL)) " - f"AS TotalCount " - f"FROM Reactions AS R, Members as M " - f"WHERE {where_str} " - f"AND (ReactionName = ?1 OR ReactionName=?2) " - f"AND R.{select_id} = M.ID " - f"GROUP BY R.{select_id})" - ), - (str(self.UPMARTLET), str(self.DOWNMARTLET), *t), - ) as c: - counts = list(zip(*(await c.fetchall()))) + else: + # get the WHERE conditions and the values + where_str, t = self._where_str_and_values_from_args_dict(args_dict, prefix="R") + counts = list(zip(*(await self.fetch_list( + ( + f"SELECT printf('%d. %s', " + f"ROW_NUMBER() OVER (ORDER BY TotalCount DESC), Name), " + f"TotalCount FROM " + f"(SELECT M.Name, " + f"COUNT(IIF (ReactionName = ?1, 1, NULL)) - " + f"COUNT(IIF (ReactionName = ?2, 1, NULL)) " + f"AS TotalCount " + f"FROM Reactions AS R, Members as M " + f"WHERE {where_str} " + f"AND (ReactionName = ?1 OR ReactionName=?2) " + f"AND R.{select_id} = M.ID " + f"GROUP BY R.{select_id})" + ), + (str(self.UPMARTLET), str(self.DOWNMARTLET), *t), + )))) - if not counts: - await ctx.send(embed=discord.Embed(title="No results found")) - return + if not counts: + await ctx.send(embed=discord.Embed(title="No results found")) + return names, values = counts @@ -568,22 +562,18 @@ async def emojiranking(self, ctx: commands.Context, *args): # get the WHERE conditions and the values where_str, t = self._where_str_and_values_from_args_dict(args_dict) - db: aiosqlite.Connection - async with self.db() as db: - c: aiosqlite.Cursor - async with db.execute( - ( - f"SELECT printf('%d. %s', " - f"ROW_NUMBER() OVER (ORDER BY count(*) DESC), " - f"ReactionName), printf('%d %s', count(*), " - f"IIF (count(*)!=1, 'times', 'time')) " - f"FROM Reactions " - f"WHERE {where_str} " - f"GROUP BY ReactionName " - ), - t, - ) as c: - counts = list(zip(*(await c.fetchall()))) + counts = list(zip(*(await self.fetch_list( + ( + f"SELECT printf('%d. %s', " + f"ROW_NUMBER() OVER (ORDER BY count(*) DESC), " + f"ReactionName), printf('%d %s', count(*), " + f"IIF (count(*)!=1, 'times', 'time')) " + f"FROM Reactions " + f"WHERE {where_str} " + f"GROUP BY ReactionName " + ), + t, + )))) if not counts: await ctx.send(embed=discord.Embed(title="No results found")) From ad8d20fc17c224bc7e41a5ee351625637246d4a6 Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Sun, 4 Sep 2022 18:02:20 -0400 Subject: [PATCH 059/127] lint --- canary/cogs/currency.py | 12 ++-- canary/cogs/customreactions.py | 4 +- canary/cogs/quotes.py | 6 +- canary/cogs/score.py | 104 +++++++++++++++++++-------------- canary/cogs/utils/hangman.py | 12 +--- 5 files changed, 76 insertions(+), 62 deletions(-) diff --git a/canary/cogs/currency.py b/canary/cogs/currency.py index 91ed08522..ed00b175e 100644 --- a/canary/cogs/currency.py +++ b/canary/cogs/currency.py @@ -68,11 +68,13 @@ async def fetch_all_balances(self) -> list[tuple[str, str, Decimal]]: # after return [ (user_id, name, self.db_to_currency(balance)) - for user_id, name, balance in (await self.fetch_list( - "SELECT BT.UserID, M.Name, IFNULL(SUM(BT.Amount), 0) " - "FROM BankTransactions AS BT, Members as M " - "WHERE BT.UserID = M.ID GROUP BY UserID" - )) + for user_id, name, balance in ( + await self.fetch_list( + "SELECT BT.UserID, M.Name, IFNULL(SUM(BT.Amount), 0) " + "FROM BankTransactions AS BT, Members as M " + "WHERE BT.UserID = M.ID GROUP BY UserID" + ) + ) ] async def fetch_bank_balance(self, user: discord.Member) -> Decimal: diff --git a/canary/cogs/customreactions.py b/canary/cogs/customreactions.py index bdc5cb5c3..1e9e5476a 100644 --- a/canary/cogs/customreactions.py +++ b/canary/cogs/customreactions.py @@ -223,8 +223,8 @@ async def create_assistant(message: discord.Message, is_moderator: bool) -> bool # List proposals EMOJI["pencil"]: { "fn": list_custom_reacts, - "desc": f"See the list of proposed reactions ({get_number_of_proposals()})" + ( - " and approve or reject them" if is_moderator else ""), + "desc": f"See the list of proposed reactions ({get_number_of_proposals()})" + + (" and approve or reject them" if is_moderator else ""), "kwargs": dict(proposals=True), }, # List placeholders diff --git a/canary/cogs/quotes.py b/canary/cogs/quotes.py index aff5c36dd..12b22b13d 100644 --- a/canary/cogs/quotes.py +++ b/canary/cogs/quotes.py @@ -181,7 +181,8 @@ async def quotes(self, ctx, str1: str = None, *, str2: str = None): if query[0] == "/" and query[-1] == "/": try: quotes = [ - q for q in (await self.fetch_list("SELECT ID, Name, Quote FROM Quotes")) + q + for q in (await self.fetch_list("SELECT ID, Name, Quote FROM Quotes")) if re.search(query[1:-1], q[2]) ] except re.error: @@ -340,8 +341,7 @@ async def all_quotes(self, ctx: commands.Context, *, query: str): if query[0] == "/" and query[-1] == "/": try: quote_list = [ - q for q in (await self.fetch_list("SELECT * FROM Quotes")) - if re.search(query[1:-1], q[2]) + q for q in (await self.fetch_list("SELECT * FROM Quotes")) if re.search(query[1:-1], q[2]) ] except re.error: await ctx.send("Invalid regex syntax.") diff --git a/canary/cogs/score.py b/canary/cogs/score.py index 7e0213f02..9411acded 100644 --- a/canary/cogs/score.py +++ b/canary/cogs/score.py @@ -467,20 +467,26 @@ async def ranking(self, ctx, *args): if args_dict["emojitype"] != "score": # get the WHERE conditions and the values where_str, t = self._where_str_and_values_from_args_dict(args_dict) - counts = list(zip(*(await self.fetch_list( - ( - f"SELECT printf('%d. %s', " - f"ROW_NUMBER() OVER (ORDER BY count(*) DESC), M.Name), " - f"printf('%d %s', count(*), " - f"IIF (count(*)!=1, 'times', 'time')) " - f"FROM Reactions AS R, Members as M " - f"WHERE {where_str} " - f"AND R.{select_id} = M.ID " - f"GROUP BY R.{select_id} " - f"ORDER BY count(*) DESC" - ), - t, - )))) + counts = list( + zip( + *( + await self.fetch_list( + ( + f"SELECT printf('%d. %s', " + f"ROW_NUMBER() OVER (ORDER BY count(*) DESC), M.Name), " + f"printf('%d %s', count(*), " + f"IIF (count(*)!=1, 'times', 'time')) " + f"FROM Reactions AS R, Members as M " + f"WHERE {where_str} " + f"AND R.{select_id} = M.ID " + f"GROUP BY R.{select_id} " + f"ORDER BY count(*) DESC" + ), + t, + ) + ) + ) + ) if not counts: await ctx.send(embed=discord.Embed(title="This reaction was never used on this server.")) @@ -489,23 +495,29 @@ async def ranking(self, ctx, *args): else: # get the WHERE conditions and the values where_str, t = self._where_str_and_values_from_args_dict(args_dict, prefix="R") - counts = list(zip(*(await self.fetch_list( - ( - f"SELECT printf('%d. %s', " - f"ROW_NUMBER() OVER (ORDER BY TotalCount DESC), Name), " - f"TotalCount FROM " - f"(SELECT M.Name, " - f"COUNT(IIF (ReactionName = ?1, 1, NULL)) - " - f"COUNT(IIF (ReactionName = ?2, 1, NULL)) " - f"AS TotalCount " - f"FROM Reactions AS R, Members as M " - f"WHERE {where_str} " - f"AND (ReactionName = ?1 OR ReactionName=?2) " - f"AND R.{select_id} = M.ID " - f"GROUP BY R.{select_id})" - ), - (str(self.UPMARTLET), str(self.DOWNMARTLET), *t), - )))) + counts = list( + zip( + *( + await self.fetch_list( + ( + f"SELECT printf('%d. %s', " + f"ROW_NUMBER() OVER (ORDER BY TotalCount DESC), Name), " + f"TotalCount FROM " + f"(SELECT M.Name, " + f"COUNT(IIF (ReactionName = ?1, 1, NULL)) - " + f"COUNT(IIF (ReactionName = ?2, 1, NULL)) " + f"AS TotalCount " + f"FROM Reactions AS R, Members as M " + f"WHERE {where_str} " + f"AND (ReactionName = ?1 OR ReactionName=?2) " + f"AND R.{select_id} = M.ID " + f"GROUP BY R.{select_id})" + ), + (str(self.UPMARTLET), str(self.DOWNMARTLET), *t), + ) + ) + ) + ) if not counts: await ctx.send(embed=discord.Embed(title="No results found")) @@ -562,18 +574,24 @@ async def emojiranking(self, ctx: commands.Context, *args): # get the WHERE conditions and the values where_str, t = self._where_str_and_values_from_args_dict(args_dict) - counts = list(zip(*(await self.fetch_list( - ( - f"SELECT printf('%d. %s', " - f"ROW_NUMBER() OVER (ORDER BY count(*) DESC), " - f"ReactionName), printf('%d %s', count(*), " - f"IIF (count(*)!=1, 'times', 'time')) " - f"FROM Reactions " - f"WHERE {where_str} " - f"GROUP BY ReactionName " - ), - t, - )))) + counts = list( + zip( + *( + await self.fetch_list( + ( + f"SELECT printf('%d. %s', " + f"ROW_NUMBER() OVER (ORDER BY count(*) DESC), " + f"ReactionName), printf('%d %s', count(*), " + f"IIF (count(*)!=1, 'times', 'time')) " + f"FROM Reactions " + f"WHERE {where_str} " + f"GROUP BY ReactionName " + ), + t, + ) + ) + ) + ) if not counts: await ctx.send(embed=discord.Embed(title="No results found")) diff --git a/canary/cogs/utils/hangman.py b/canary/cogs/utils/hangman.py index d58a082a5..e4a732e82 100644 --- a/canary/cogs/utils/hangman.py +++ b/canary/cogs/utils/hangman.py @@ -86,9 +86,7 @@ def mk_animal_list() -> list[tuple[str, str]]: if curr_entry is None: continue animal_name = curr_entry.find("a") - animal_soup = BeautifulSoup( - requests.get(f"https://en.wikipedia.org{animal_name['href']}").content, "lxml" - ) + animal_soup = BeautifulSoup(requests.get(f"https://en.wikipedia.org{animal_name['href']}").content, "lxml") img_list = animal_soup.find_all("img") img_index = 0 while str(img_list[img_index]["src"]).endswith(".svg.png"): @@ -117,9 +115,7 @@ def mk_country_list() -> list[tuple[str, str]]: ( country_name, "https:" - + BeautifulSoup( - requests.get(f"https://en.wikipedia.org{country_name_entry['href']}").content, "lxml" - ) + + BeautifulSoup(requests.get(f"https://en.wikipedia.org{country_name_entry['href']}").content, "lxml") .find("table", {"class": "infobox"}) .find("a", {"class": "image"}) .find("img")["src"], @@ -139,9 +135,7 @@ def mk_element_list() -> list[tuple[str, Optional[str]]]: try: elem_img: Optional[str] = ( "https:" - + BeautifulSoup( - requests.get(f"https://en.wikipedia.org{elem_name_entry['href']}").content, "lxml" - ) + + BeautifulSoup(requests.get(f"https://en.wikipedia.org{elem_name_entry['href']}").content, "lxml") .find("table", {"class": "infobox"}) .find("a") .find("img")["src"] From 008460c103b5dec77782333d0b44aea2b7e064b2 Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Sun, 4 Sep 2022 18:08:34 -0400 Subject: [PATCH 060/127] score code style --- canary/cogs/score.py | 80 +++++++++++++++++--------------------------- 1 file changed, 30 insertions(+), 50 deletions(-) diff --git a/canary/cogs/score.py b/canary/cogs/score.py index 9411acded..67c0dc523 100644 --- a/canary/cogs/score.py +++ b/canary/cogs/score.py @@ -467,61 +467,41 @@ async def ranking(self, ctx, *args): if args_dict["emojitype"] != "score": # get the WHERE conditions and the values where_str, t = self._where_str_and_values_from_args_dict(args_dict) - counts = list( - zip( - *( - await self.fetch_list( - ( - f"SELECT printf('%d. %s', " - f"ROW_NUMBER() OVER (ORDER BY count(*) DESC), M.Name), " - f"printf('%d %s', count(*), " - f"IIF (count(*)!=1, 'times', 'time')) " - f"FROM Reactions AS R, Members as M " - f"WHERE {where_str} " - f"AND R.{select_id} = M.ID " - f"GROUP BY R.{select_id} " - f"ORDER BY count(*) DESC" - ), - t, - ) - ) - ) + q = ( + f"SELECT printf('%d. %s', ROW_NUMBER() OVER (ORDER BY count(*) DESC), M.Name), " + f"printf('%d %s', count(*), " + f"IIF (count(*)!=1, 'times', 'time')) " + f"FROM Reactions AS R, Members as M " + f"WHERE {where_str} " + f"AND R.{select_id} = M.ID " + f"GROUP BY R.{select_id} " + f"ORDER BY count(*) DESC" ) - - if not counts: - await ctx.send(embed=discord.Embed(title="This reaction was never used on this server.")) - return - + not_found_err = "This reaction was never used on this server." else: # get the WHERE conditions and the values - where_str, t = self._where_str_and_values_from_args_dict(args_dict, prefix="R") - counts = list( - zip( - *( - await self.fetch_list( - ( - f"SELECT printf('%d. %s', " - f"ROW_NUMBER() OVER (ORDER BY TotalCount DESC), Name), " - f"TotalCount FROM " - f"(SELECT M.Name, " - f"COUNT(IIF (ReactionName = ?1, 1, NULL)) - " - f"COUNT(IIF (ReactionName = ?2, 1, NULL)) " - f"AS TotalCount " - f"FROM Reactions AS R, Members as M " - f"WHERE {where_str} " - f"AND (ReactionName = ?1 OR ReactionName=?2) " - f"AND R.{select_id} = M.ID " - f"GROUP BY R.{select_id})" - ), - (str(self.UPMARTLET), str(self.DOWNMARTLET), *t), - ) - ) - ) + where_str, tp = self._where_str_and_values_from_args_dict(args_dict, prefix="R") + t = (str(self.UPMARTLET), str(self.DOWNMARTLET), *tp) + q = ( + f"SELECT printf('%d. %s', " + f"ROW_NUMBER() OVER (ORDER BY TotalCount DESC), Name), " + f"TotalCount FROM " + f"(SELECT M.Name, " + f"COUNT(IIF (ReactionName = ?1, 1, NULL)) - " + f"COUNT(IIF (ReactionName = ?2, 1, NULL)) " + f"AS TotalCount " + f"FROM Reactions AS R, Members as M " + f"WHERE {where_str} " + f"AND (ReactionName = ?1 OR ReactionName=?2) " + f"AND R.{select_id} = M.ID " + f"GROUP BY R.{select_id})" ) + not_found_err = "No results found" - if not counts: - await ctx.send(embed=discord.Embed(title="No results found")) - return + counts = list(zip(*(await self.fetch_list(q, t)))) + if not counts: + await ctx.send(embed=discord.Embed(title=not_found_err)) + return names, values = counts From 52d1f5591a62288169cfb5c486f88efc8f853519 Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Sun, 4 Sep 2022 20:36:27 -0400 Subject: [PATCH 061/127] score reformatting --- canary/cogs/score.py | 27 +++++++++------------------ 1 file changed, 9 insertions(+), 18 deletions(-) diff --git a/canary/cogs/score.py b/canary/cogs/score.py index 67c0dc523..b53ccf2e2 100644 --- a/canary/cogs/score.py +++ b/canary/cogs/score.py @@ -553,26 +553,17 @@ async def emojiranking(self, ctx: commands.Context, *args): await ctx.send("Invalid input: Emojitype flag cannot use type score for this function") # get the WHERE conditions and the values where_str, t = self._where_str_and_values_from_args_dict(args_dict) - - counts = list( - zip( - *( - await self.fetch_list( - ( - f"SELECT printf('%d. %s', " - f"ROW_NUMBER() OVER (ORDER BY count(*) DESC), " - f"ReactionName), printf('%d %s', count(*), " - f"IIF (count(*)!=1, 'times', 'time')) " - f"FROM Reactions " - f"WHERE {where_str} " - f"GROUP BY ReactionName " - ), - t, - ) - ) - ) + q = ( + f"SELECT printf('%d. %s', " + f"ROW_NUMBER() OVER (ORDER BY count(*) DESC), " + f"ReactionName), printf('%d %s', count(*), " + f"IIF (count(*)!=1, 'times', 'time')) " + f"FROM Reactions " + f"WHERE {where_str} " + f"GROUP BY ReactionName " ) + counts = list(zip(*(await self.fetch_list(q, t)))) if not counts: await ctx.send(embed=discord.Embed(title="No results found")) return From 0b714c9cac031efa4a33e73e0d02cf2fac70c21a Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Sun, 4 Sep 2022 22:54:42 -0400 Subject: [PATCH 062/127] fix some funky strings --- canary/cogs/reminder.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/canary/cogs/reminder.py b/canary/cogs/reminder.py index 149bf7fef..6508162cb 100644 --- a/canary/cogs/reminder.py +++ b/canary/cogs/reminder.py @@ -118,7 +118,7 @@ async def check_reminders(self): await member.send(f"Reminding you to {reminders[i][2]}!") # Remove from from DB non-repeating reminder await db.execute( - ("DELETE FROM Reminders WHERE Reminder=? AND ID=?" + " AND DATE=?"), + "DELETE FROM Reminders WHERE Reminder=? AND ID=? AND DATE=?", (reminders[i][2], reminders[i][0], reminder_activation_date), ) await db.commit() @@ -130,7 +130,7 @@ async def check_reminders(self): if datetime.datetime.now() - last_date > datetime.timedelta(days=FREQUENCIES[reminders[i][3]]): await member.send(f"Reminding you to {reminders[i][2]}! [{i + 1:d}]") await db.execute( - ("UPDATE 'Reminders' SET LastReminder=? WHERE " + "Reminder=?"), + "UPDATE 'Reminders' SET LastReminder=? WHERE Reminder=?", (datetime.datetime.now(), reminders[i][2]), ) await db.commit() From 8f88bc461be3f908a366a99953c382127a85814c Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Mon, 5 Sep 2022 09:33:47 -0400 Subject: [PATCH 063/127] add a fetch_one higher level fn to base cog do a bit of reminder refactoring --- canary/cogs/banner.py | 38 ++++++++++-------------- canary/cogs/base_cog.py | 15 ++++++++++ canary/cogs/currency.py | 65 +++++++++++++++++++++-------------------- canary/cogs/helpers.py | 11 +++---- canary/cogs/images.py | 2 +- canary/cogs/reminder.py | 56 ++++++++++++++++++----------------- canary/cogs/score.py | 34 +++++++++------------ 7 files changed, 112 insertions(+), 109 deletions(-) diff --git a/canary/cogs/banner.py b/canary/cogs/banner.py index 362233a1b..2e661d36c 100644 --- a/canary/cogs/banner.py +++ b/canary/cogs/banner.py @@ -278,11 +278,7 @@ def msg_check(msg): winner_id = winner.id - db: aiosqlite.Connection - c: aiosqlite.Cursor - async with self.db() as db: - async with db.execute("SELECT * FROM BannerSubmissions WHERE UserID = ?", (winner_id,)) as c: - fetched = await c.fetchone() + fetched = await self.fetch_one("SELECT * FROM BannerSubmissions WHERE UserID = ?", (winner_id,)) if not fetched: await ctx.send("No submission by this user in database. Exiting command.") @@ -535,23 +531,21 @@ async def submit_banner(self, ctx: commands.Context, *args): replaced_message = False - db: aiosqlite.Connection - async with self.db() as db: - c: aiosqlite.Cursor - async with db.execute( - "SELECT PreviewMessageID FROM BannerSubmissions WHERE UserID = ?", (ctx.author.id,) - ) as c: - fetched = await c.fetchone() - if fetched: - try: - message_to_replace = await self.banner_submissions_channel.fetch_message(fetched[0]) - await message_to_replace.delete() - except discord.errors.NotFound: - await ctx.send( - f"Could not delete previously posted submission from " - f"{self.banner_submissions_channel.mention}. It might have been manually deleted." - ) - replaced_message = True + fetched = await self.fetch_one( + "SELECT PreviewMessageID FROM BannerSubmissions WHERE UserID = ?", + (ctx.author.id,), + ) + + if fetched: + try: + message_to_replace = await self.banner_submissions_channel.fetch_message(fetched[0]) + await message_to_replace.delete() + except discord.errors.NotFound: + await ctx.send( + f"Could not delete previously posted submission from " + f"{self.banner_submissions_channel.mention}. It might have been manually deleted." + ) + replaced_message = True async def send_picture(frames, channel, filename): with BytesIO() as image_binary: diff --git a/canary/cogs/base_cog.py b/canary/cogs/base_cog.py index 19a542873..d82e551ea 100644 --- a/canary/cogs/base_cog.py +++ b/canary/cogs/base_cog.py @@ -46,6 +46,21 @@ async def fetch_list( if fresh_db: await db.close() + async def fetch_one( + self, + query: str, + params: tuple[str | int | float | bool, ...] = (), + db: aiosqlite.Connection | None = None, + ) -> tuple | None: + if fresh_db := db is None: + db = await self.bot.db_nocm() + try: + async with db.execute(query, params) as c: + return c.fetchone() + finally: + if fresh_db: + await db.close() + async def get_settings_key(self, key: str) -> str | None: db: aiosqlite.Connection async with self.db() as db: diff --git a/canary/cogs/currency.py b/canary/cogs/currency.py index ed00b175e..f98b91897 100644 --- a/canary/cogs/currency.py +++ b/canary/cogs/currency.py @@ -78,17 +78,11 @@ async def fetch_all_balances(self) -> list[tuple[str, str, Decimal]]: ] async def fetch_bank_balance(self, user: discord.Member) -> Decimal: - db: aiosqlite.Connection - async with self.db() as db: - c: aiosqlite.Cursor - async with db.execute( - "SELECT IFNULL(SUM(Amount), 0) FROM BankTransactions WHERE UserID = ?", (user.id,) - ) as c: - # noinspection PyRedundantParentheses - balance = self.db_to_currency(((await c.fetchone()) or (0,))[0]) - if balance is None: - balance = Decimal(0) - return balance + balance_t = await self.fetch_one( + "SELECT IFNULL(SUM(Amount), 0) FROM BankTransactions WHERE UserID = ?", + (user.id,) + ) + return self.db_to_currency(balance_t[0]) if balance_t is not None else Decimal(0) async def create_bank_transaction( self, db: aiosqlite.Connection, user: discord.Member, amount: Decimal, action: str, metadata: dict @@ -157,24 +151,31 @@ def check_bet(balance: Decimal, bet: Decimal) -> str | None: return "" + async def get_last_claim_time(self, db: aiosqlite.Connection, author: discord.Member | discord.User) -> int | None: + claim_time_t = await self.fetch_one( + "SELECT IFNULL(MAX(Date), 0) FROM BankTransactions WHERE UserID = ? AND Action = ?", + (author.id, ACTION_INITIAL_CLAIM), + db=db, + ) + return claim_time_t[0] if claim_time_t is not None else None + @commands.command() - async def initial_claim(self, ctx): + async def initial_claim(self, ctx: commands.Context): """ Claim's the user's start-up grant currency. """ - # Start bot typing await ctx.trigger_typing() + author = ctx.message.author + author_name = author.display_name + db: aiosqlite.Connection async with self.db() as db: - async with db.execute( - "SELECT IFNULL(MAX(Date), 0) FROM BankTransactions WHERE UserID = ? AND Action = ?", - (ctx.message.author.id, ACTION_INITIAL_CLAIM), - ) as c: - claim_time = (await c.fetchone())[0] + claim_time = await self.get_last_claim_time(db, author) - author_name = ctx.message.author.display_name + if claim_time is None: + return if claim_time > 0: await ctx.send(f"{author_name} has already claimed their initial currency.") @@ -182,12 +183,11 @@ async def initial_claim(self, ctx): await self.create_bank_transaction( db, - ctx.message.author, + author, self.currency["initial_amount"], ACTION_INITIAL_CLAIM, {"channel": ctx.message.channel.id}, ) - await db.commit() await ctx.send( @@ -195,7 +195,7 @@ async def initial_claim(self, ctx): ) @commands.command() - async def claim(self, ctx): + async def claim(self, ctx: commands.Context): """ Claim's the user's hourly currency. """ @@ -203,23 +203,24 @@ async def claim(self, ctx): # Start bot typing await ctx.trigger_typing() + author = ctx.message.author threshold = datetime.datetime.now() - CLAIM_WAIT_TIME db: aiosqlite.Connection async with self.db() as db: - c: aiosqlite.Cursor - async with db.execute( - "SELECT IFNULL(MAX(Date), 0) FROM BankTransactions WHERE UserID = ? AND Action = ?", - (ctx.message.author.id, ACTION_CLAIM), - ) as c: - last_claimed = datetime.datetime.fromtimestamp((await c.fetchone())[0]) + claim_time = await self.get_last_claim_time(db, author) + + if claim_time is None: + return + + last_claimed = datetime.datetime.fromtimestamp(claim_time) if last_claimed < threshold: metadata = {"channel": ctx.message.channel.id} - await self.create_bank_transaction(db, ctx.message.author, CLAIM_AMOUNT, ACTION_CLAIM, metadata) + await self.create_bank_transaction(db, author, CLAIM_AMOUNT, ACTION_CLAIM, metadata) await db.commit() - author_name = ctx.message.author.display_name if ctx.message.author else ":b:roken bot" + author_name = author.display_name if author else ":b:roken bot" await ctx.send(f"{author_name} claimed {self.format_symbol_currency(CLAIM_AMOUNT)}!") return @@ -303,7 +304,7 @@ async def bet_roll(self, ctx, bet: str = None): # Start bot typing await ctx.trigger_typing() - balance = await self.fetch_bank_balance(ctx.message.author) + balance: Decimal = await self.fetch_bank_balance(ctx.message.author) bet_dec = self.parse_currency(bet, balance) # Handle invalid cases @@ -362,7 +363,7 @@ async def give(self, ctx, user: discord.Member = None, amount: str = None): await ctx.send("Usage: ?give [user] [amount]") return - balance = await self.fetch_bank_balance(ctx.message.author) + balance: Decimal = await self.fetch_bank_balance(ctx.message.author) if balance <= 0: await ctx.send("You're too broke to give anyone anything!") diff --git a/canary/cogs/helpers.py b/canary/cogs/helpers.py index b0700a6c4..a8d5cd89a 100644 --- a/canary/cogs/helpers.py +++ b/canary/cogs/helpers.py @@ -15,7 +15,6 @@ # You should have received a copy of the GNU General Public License # along with Canary. If not, see . # discord-py requirements -import aiohttp import discord from discord.ext import commands from discord import utils @@ -787,12 +786,10 @@ async def on_raw_reaction_add(self, payload): # if the put_litter_in_its_place react was used check if it was # on a spoilerized message by its original author, and if so delete it - async with self.db() as db: - async with db.execute( - "SELECT * From SpoilerizedMessages WHERE MessageID=? AND UserID=?", - (int(payload.message_id), int(payload.member.id)), - ) as c: - found = await c.fetchone() + found = await self.fetch_one( + "SELECT * From SpoilerizedMessages WHERE MessageID=? AND UserID=?", + (int(payload.message_id), int(payload.member.id)), + ) if found: channel = utils.get(self.guild.text_channels, id=payload.channel_id) diff --git a/canary/cogs/images.py b/canary/cogs/images.py index 39ebd0872..64580f8f2 100644 --- a/canary/cogs/images.py +++ b/canary/cogs/images.py @@ -82,7 +82,7 @@ async def cblur(self, ctx: commands.Context, radius: int = 10): @commands.command(aliases=["df", "dfry", "fry"]) async def deepfry(self, ctx: commands.Context, iterations: int = 1): """ - Deep fry an image, mhmm + Deep-fry an image, mhmm """ await ih.filter_image(self.bot.loop, ih.deepfry, ctx, self.hist_lim, self.max_size, iterations, self.max_itr) diff --git a/canary/cogs/reminder.py b/canary/cogs/reminder.py index 6508162cb..186784e49 100644 --- a/canary/cogs/reminder.py +++ b/canary/cogs/reminder.py @@ -237,11 +237,13 @@ async def remindme(self, ctx: commands.Context, *, quote: str = ""): else: reminder = reminder[time_input_end + 1 :].strip() + message_author = ctx.message.author + # Add message to database async with self.db() as db: t = ( - ctx.message.author.id, - ctx.message.author.name, + message_author.id, + message_author.name, reminder, "once", absolute_duedate, @@ -252,17 +254,13 @@ async def remindme(self, ctx: commands.Context, *, quote: str = ""): # Send user information - async with db.execute("SELECT COUNT(*) FROM Reminders WHERE ID = ?", (ctx.message.author.id,)) as c: - # noinspection PyRedundantParentheses - num_reminders = ((await c.fetchone()) or (0,))[0] + num_reminders = await self.get_num_reminders(db, message_author) - await ctx.author.send( - "Hi {}! \nI will remind you to {} on {} at {} unless you " - "send me a message to stop reminding you about it! " - "[{:d}]".format( - ctx.author.name, reminder, date_result.group(0), time_result.group(0), num_reminders + 1 - ) - ) + await ctx.author.send( + f"Hi {ctx.author.name}! \nI will remind you to {reminder} on {date_result.group(0)} at " + f"{time_result.group(0)} unless you send me a message to stop reminding you about it! " + f"[{num_reminders + 1:d}]" + ) await ctx.send("Reminder added.") return @@ -311,7 +309,7 @@ async def remindme(self, ctx: commands.Context, *, quote: str = ""): # DB: Date will hold TDELTA (When reminder is due), LastReminder will # hold datetime.datetime.now() async with self.db() as db: - reminders = await self.fetch_list("SELECT * FROM Reminders WHERE ID =?", (ctx.message.author.id,), db=db) + num_reminders = await self.get_num_reminders(db, ctx.message.author) t = (ctx.message.author.id, ctx.message.author.name, reminder, "once", reminder_time, time_now) await db.execute("INSERT INTO Reminders VALUES (?, ?, ?, ?, ?, ?)", t) await db.commit() @@ -325,7 +323,7 @@ async def remindme(self, ctx: commands.Context, *, quote: str = ""): await ctx.author.send( f"Hi {ctx.author.name}! \nI will remind you to {reminder} on " f"{due_date} at {due_time} unless you send me a message to stop " - f"reminding you about it! [{len(reminders)+1}]" + f"reminding you about it! [{num_reminders+1:d}]" ) await ctx.send("Reminder added.") @@ -451,27 +449,23 @@ async def __remindme_repeating(self, ctx: commands.Context, freq: str = "", *, q if bad_input: return - async with self.db() as db: - async with db.execute( - "SELECT * FROM Reminders WHERE Reminder = ? AND ID = ?", (quote, ctx.message.author.id) - ) as c: - existing_reminder = c.fetchone() - + existing_reminder = await self.fetch_one( + "SELECT * FROM Reminders WHERE Reminder = ? AND ID = ?", (quote, ctx.message.author.id) + ) if existing_reminder is not None: await ctx.send( f"The reminder `{quote}` already exists in your database. Please specify a unique reminder message!" ) return + now = datetime.datetime.now() msg_author = ctx.message.author async with self.db() as db: - async with db.execute("SELECT COUNT(*) FROM Reminders WHERE ID = ?", (msg_author.id,)) as c: - # noinspection PyRedundantParentheses - num_reminders = ((await c.fetchone()) or (0,))[0] - - now = datetime.datetime.now() - t = (msg_author.id, msg_author.name, quote, freq, now, now) - await db.execute("INSERT INTO Reminders VALUES (?, ?, ?, ?, ?, ?)", t) + num_reminders = await self.get_num_reminders(db, msg_author) + await db.execute( + "INSERT INTO Reminders VALUES (?, ?, ?, ?, ?, ?)", + (msg_author.id, msg_author.name, quote, freq, now, now) + ) await db.commit() # Strips the string "to " from reminder messages @@ -485,6 +479,14 @@ async def __remindme_repeating(self, ctx: commands.Context, freq: str = "", *, q await ctx.send("Reminder added.") + async def get_num_reminders(self, db: aiosqlite.Connection, author: discord.Member | discord.User) -> int: + num_reminders_t = await self.fetch_one( + "SELECT COUNT(*) FROM Reminders WHERE ID = ?", + (author.id,), + db=db, + ) + return num_reminders_t[0] if num_reminders_t is not None else 0 + def setup(bot): database = Reminder(bot) diff --git a/canary/cogs/score.py b/canary/cogs/score.py index b53ccf2e2..ddf7dc296 100644 --- a/canary/cogs/score.py +++ b/canary/cogs/score.py @@ -396,27 +396,21 @@ async def score(self, ctx: commands.Context, *args): # get the WHERE conditions and the values where_str, t = self._where_str_and_values_from_args_dict(args_dict) - db: aiosqlite.Connection - async with self.db() as db: - c: aiosqlite.Cursor + if args_dict["emojitype"] != "score": + react_count_t = await self.fetch_one(f"SELECT count(ReacteeID) FROM Reactions WHERE {where_str}", t) + else: + react_count_t = await self.fetch_one( + ( + f"SELECT COUNT(IIF (ReactionName = ?1, 1, NULL)) - COUNT(IIF (ReactionName = ?2, 1, NULL)) " + f"FROM Reactions WHERE {where_str} AND (ReactionName = ?1 OR ReactionName=?2) " + ), + (str(self.UPMARTLET), str(self.DOWNMARTLET), *t), + ) - if args_dict["emojitype"] != "score": - async with db.execute(f"SELECT count(ReacteeID) FROM Reactions WHERE {where_str}", t) as c: - react_count = (await c.fetchone())[0] - else: - async with db.execute( - ( - f"SELECT COUNT(IIF (ReactionName = ?1, 1, NULL)) - " - f"COUNT(IIF (ReactionName = ?2, 1, NULL)) " - f"FROM Reactions " - f"WHERE {where_str} " - f"AND (ReactionName = ?1 OR ReactionName=?2) " - ), - (str(self.UPMARTLET), str(self.DOWNMARTLET), *t), - ) as c: - react_count = (await c.fetchone())[0] - - await ctx.send(react_count) + if react_count_t is None: + return + + await ctx.send(react_count_t[0]) @commands.command() async def ranking(self, ctx, *args): From d5916d825e11b1cdc3475638fd1eaedb4ac1defb Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Mon, 5 Sep 2022 09:35:03 -0400 Subject: [PATCH 064/127] clarifying parens --- canary/cogs/base_cog.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/canary/cogs/base_cog.py b/canary/cogs/base_cog.py index d82e551ea..6e44335ad 100644 --- a/canary/cogs/base_cog.py +++ b/canary/cogs/base_cog.py @@ -37,7 +37,7 @@ async def fetch_list( params: tuple[str | int | float | bool, ...] = (), db: aiosqlite.Connection | None = None, ) -> list[tuple]: - if fresh_db := db is None: + if fresh_db := (db is None): db = await self.bot.db_nocm() try: async with db.execute(query, params) as c: @@ -52,7 +52,7 @@ async def fetch_one( params: tuple[str | int | float | bool, ...] = (), db: aiosqlite.Connection | None = None, ) -> tuple | None: - if fresh_db := db is None: + if fresh_db := (db is None): db = await self.bot.db_nocm() try: async with db.execute(query, params) as c: From d29f534b299c7d58732df3cc4108220c96fd1e84 Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Mon, 5 Sep 2022 10:44:51 -0400 Subject: [PATCH 065/127] more reminders refactoring + lint --- canary/cogs/currency.py | 3 +- canary/cogs/reminder.py | 193 +++++++++++++++++++--------------------- 2 files changed, 92 insertions(+), 104 deletions(-) diff --git a/canary/cogs/currency.py b/canary/cogs/currency.py index f98b91897..9fa8ee2e1 100644 --- a/canary/cogs/currency.py +++ b/canary/cogs/currency.py @@ -79,8 +79,7 @@ async def fetch_all_balances(self) -> list[tuple[str, str, Decimal]]: async def fetch_bank_balance(self, user: discord.Member) -> Decimal: balance_t = await self.fetch_one( - "SELECT IFNULL(SUM(Amount), 0) FROM BankTransactions WHERE UserID = ?", - (user.id,) + "SELECT IFNULL(SUM(Amount), 0) FROM BankTransactions WHERE UserID = ?", (user.id,) ) return self.db_to_currency(balance_t[0]) if balance_t is not None else Decimal(0) diff --git a/canary/cogs/reminder.py b/canary/cogs/reminder.py index 186784e49..56a68e42b 100644 --- a/canary/cogs/reminder.py +++ b/canary/cogs/reminder.py @@ -15,13 +15,12 @@ # You should have received a copy of the GNU General Public License # along with Canary. If not, see . -import asyncio -import datetime - import aiosqlite +import asyncio import discord import re +from datetime import datetime, timedelta from discord.ext import commands from .base_cog import CanaryCog @@ -105,34 +104,32 @@ async def check_reminders(self): async with self.db() as db: reminders = await self.fetch_list("SELECT * FROM Reminders", db=db) - for i in range(len(reminders)): - member = discord.utils.get(guild.members, id=reminders[i][0]) + for i, reminder in enumerate(reminders): + member = discord.utils.get(guild.members, id=reminder[0]) + now = datetime.now() # If non-repeating reminder is found - if reminders[i][3] == "once": + if reminder[3] == "once": # Check date to remind user - reminder_activation_date = datetime.datetime.strptime(reminders[i][4], "%Y-%m-%d %H:%M:%S.%f") + reminder_activation_date = datetime.strptime(reminder[4], "%Y-%m-%d %H:%M:%S.%f") # Compute future_date and current_date and if past, means # time is due to remind user. - if reminder_activation_date <= datetime.datetime.now(): - await member.send(f"Reminding you to {reminders[i][2]}!") + if reminder_activation_date <= now: + await member.send(f"Reminding you to {reminder[2]}!") # Remove from from DB non-repeating reminder await db.execute( "DELETE FROM Reminders WHERE Reminder=? AND ID=? AND DATE=?", - (reminders[i][2], reminders[i][0], reminder_activation_date), + (reminder[2], reminder[0], reminder_activation_date), ) await db.commit() await asyncio.sleep(1) else: - last_date = datetime.datetime.strptime(reminders[i][5], "%Y-%m-%d %H:%M:%S.%f") + last_date = datetime.strptime(reminder[5], "%Y-%m-%d %H:%M:%S.%f") - if datetime.datetime.now() - last_date > datetime.timedelta(days=FREQUENCIES[reminders[i][3]]): - await member.send(f"Reminding you to {reminders[i][2]}! [{i + 1:d}]") - await db.execute( - "UPDATE 'Reminders' SET LastReminder=? WHERE Reminder=?", - (datetime.datetime.now(), reminders[i][2]), - ) + if now - last_date > timedelta(days=FREQUENCIES[reminders[i][3]]): + await member.send(f"Reminding you to {reminder[2]}! [{i + 1:d}]") + await db.execute("UPDATE Reminders SET LastReminder=? WHERE Reminder=?", (now, reminder[2])) await db.commit() await asyncio.sleep(1) @@ -151,9 +148,10 @@ async def remindme(self, ctx: commands.Context, *, quote: str = ""): if quote == "": await ctx.send( - "**Usage:** \n`?remindme in 1 hour and 20 minutes and 20 " - "seconds to eat` **or** \n `?remindme at 2020-04-30 11:30 to " - "graduate` **or** \n`?remindme daily to sleep`" + "**Usage:** \n" + "`?remindme in 1 hour and 20 minutes and 20 seconds to eat` **or** \n" + "`?remindme at 2020-04-30 11:30 to graduate` **or** \n" + "`?remindme daily to sleep`" ) return @@ -196,9 +194,9 @@ async def remindme(self, ctx: commands.Context, *, quote: str = ""): for segment in input_segments: if re.match(TIME_SEPARATOR_REGEX, segment): continue - if re.match(f"^{NUMBER_REGEX}$", segment): + if re.match(rf"^{NUMBER_REGEX}$", segment): last_number = segment - elif re.match(f"^{UNIT_REGEX}$", segment): + elif re.match(rf"^{UNIT_REGEX}$", segment): time_segments.append(f"{last_number} {segment}") else: first_reminder_segment = segment @@ -208,6 +206,8 @@ async def remindme(self, ctx: commands.Context, *, quote: str = ""): # and formatting, so extract from original string. reminder = quote[quote.index(first_reminder_segment) :] + msg_author = ctx.message.author + # Date-based reminder triggered by "at" and "on" keywords if input_segments[0] in {"at", "on"}: # Gets YYYY-mm-dd @@ -215,82 +215,81 @@ async def remindme(self, ctx: commands.Context, *, quote: str = ""): # Gets HH:MM time_result = re.search(HM_REGEX, original_input_copy) - # If both a date and a time is found, continue - if date_result and time_result: - # Compute datetime.Object - absolute_duedate = datetime.datetime.strptime( - "{Y}-{m}-{d}-{H}-{M}-{S}".format( - Y=date_result.group(1), - m=date_result.group(2), - d=date_result.group(4), - H=time_result.group(1), - M=time_result.group(2), - S=0.1, - ), - "%Y-%m-%d-%H-%M-%S.%f", - ) + if date_result is None or time_result is None: + # Wrong input feedback depending on what is missing. + await ctx.send("Check your private messages for info on correct syntax!") + await ctx.author.send("Please double check the following: ") + if not date_result: + await ctx.author.send("Make sure you have specified a date in the format: `YYYY-mm-dd`") + if not time_result: + await ctx.author.send("Make sure you have specified a time in the 24H format: `HH:MM`") + await ctx.author.send("E.g.: `?remindme on 2020-12-05 at 21:44 to feed Marty`") + return - # Strips "to" and dates from the reminder message - time_input_end = time_result.span()[1] - if re.match("to", reminder[time_input_end : time_input_end + 4].strip(), re.IGNORECASE): - reminder = reminder[time_input_end + 3 :].strip() - else: - reminder = reminder[time_input_end + 1 :].strip() - - message_author = ctx.message.author - - # Add message to database - async with self.db() as db: - t = ( - message_author.id, - message_author.name, - reminder, - "once", - absolute_duedate, - datetime.datetime.now(), - ) - await db.execute("INSERT INTO Reminders VALUES (?, ?, ?, ?, ?, ?)", t) - await db.commit() - - # Send user information - - num_reminders = await self.get_num_reminders(db, message_author) - - await ctx.author.send( - f"Hi {ctx.author.name}! \nI will remind you to {reminder} on {date_result.group(0)} at " - f"{time_result.group(0)} unless you send me a message to stop reminding you about it! " - f"[{num_reminders + 1:d}]" + # Otherwise, both a date and a time are found, so continue + + # Compute datetime.Object + absolute_duedate = datetime.strptime( + "{Y}-{m}-{d}-{H}-{M}-{S}".format( + Y=date_result.group(1), + m=date_result.group(2), + d=date_result.group(4), + H=time_result.group(1), + M=time_result.group(2), + S=0.1, + ), + "%Y-%m-%d-%H-%M-%S.%f", + ) + + # Strips "to" and dates from the reminder message + time_input_end = time_result.span()[1] + if re.match("to", reminder[time_input_end : time_input_end + 4].strip(), re.IGNORECASE): + reminder = reminder[time_input_end + 3 :].strip() + else: + reminder = reminder[time_input_end + 1 :].strip() + + # Add message to database + async with self.db() as db: + t = ( + msg_author.id, + msg_author.name, + reminder, + "once", + absolute_duedate, + datetime.now(), ) + await db.execute("INSERT INTO Reminders VALUES (?, ?, ?, ?, ?, ?)", t) + await db.commit() - await ctx.send("Reminder added.") - return + # Send user information - # Wrong input feedback depending on what is missing. - await ctx.send("Check your private messages for info on correct syntax!") - await ctx.author.send("Please double check the following: ") - if not date_result: - await ctx.author.send(("Make sure you have specified a date in the format: " + "`YYYY-mm-dd`")) - if not time_result: - await ctx.author.send(("Make sure you have specified a time in the 24H format: " + "`HH:MM`")) - await ctx.author.send("E.g.: `?remindme on 2020-12-05 at 21:44 to feed Marty`") + num_reminders = await self.get_num_reminders(db, msg_author) + + await ctx.author.send( + f"Hi {ctx.author.name}! \nI will remind you to {reminder} on {date_result.group(0)} at " + f"{time_result.group(0)} unless you send me a message to stop reminding you about it! " + f"[{num_reminders + 1:d}]" + ) + + await ctx.send("Reminder added.") return # Regex for the number and time units and store in "match" for segment in time_segments: - match = re.match(r"^({})\s+{}$".format(NUMBER_REGEX, UNIT_REGEX), segment) + match = re.match(rf"^({NUMBER_REGEX})\s+{UNIT_REGEX}$", segment) number = float(match.group(1)) # Regex potentially misspelled time units and match to proper # spelling. for regex in REMINDER_UNITS: - if re.match("^{}$".format(REMINDER_UNITS[regex]), match.group(3)): + if re.match(f"^{REMINDER_UNITS[regex]}$", match.group(3)): time_offset[regex] += number # Convert years to a unit that datetime will understand time_offset["days"] = time_offset["days"] + time_offset["years"] * 365 - time_now = datetime.datetime.now() # Current time - reminder_time = time_now + datetime.timedelta( + time_now = datetime.now() # Current time + reminder_time = time_now + timedelta( days=time_offset["days"], hours=time_offset["hours"], seconds=time_offset["seconds"], @@ -299,7 +298,7 @@ async def remindme(self, ctx: commands.Context, *, quote: str = ""): ) # Time to be reminded on if time_now == reminder_time: # No time in argument, or it's zero. - await ctx.send("Please specify a time! E.g.: `?remindme in 1 hour {}`".format(reminder)) + await ctx.send(f"Please specify a time! E.g.: `?remindme in 1 hour {reminder}`") return # Strips the string "to " from reminder messages @@ -309,20 +308,14 @@ async def remindme(self, ctx: commands.Context, *, quote: str = ""): # DB: Date will hold TDELTA (When reminder is due), LastReminder will # hold datetime.datetime.now() async with self.db() as db: - num_reminders = await self.get_num_reminders(db, ctx.message.author) - t = (ctx.message.author.id, ctx.message.author.name, reminder, "once", reminder_time, time_now) + num_reminders = await self.get_num_reminders(db, msg_author) + t = (msg_author.id, msg_author.name, reminder, "once", reminder_time, time_now) await db.execute("INSERT INTO Reminders VALUES (?, ?, ?, ?, ?, ?)", t) await db.commit() - # Gets reminder date in YYYY-MM-DD format - due_date = str(datetime.date(reminder_time.year, reminder_time.month, reminder_time.day)) - - # Gets reminder time in HH:MM - due_time = str(reminder_time).split()[1].split(":")[0] + ":" + str(reminder_time).split()[1].split(":")[1] - await ctx.author.send( f"Hi {ctx.author.name}! \nI will remind you to {reminder} on " - f"{due_date} at {due_time} unless you send me a message to stop " + f"{reminder_time.strftime('%Y-%m-%d at %H:%M')} unless you send me a message to stop " f"reminding you about it! [{num_reminders+1:d}]" ) await ctx.send("Reminder added.") @@ -427,7 +420,6 @@ async def __remindme_repeating(self, ctx: commands.Context, freq: str = "", *, q """ db: aiosqlite.Connection - c: aiosqlite.Cursor bad_input = False @@ -436,8 +428,8 @@ async def __remindme_repeating(self, ctx: commands.Context, freq: str = "", *, q if freq not in FREQUENCIES.keys(): await ctx.send( - "Please ensure you specify a frequency from the following " - "list: `daily`, `weekly`, `monthly`, before your message!" + "Please ensure you specify a frequency from the following list: " + "`daily`, `weekly`, `monthly`, before your message!" ) bad_input = True @@ -449,8 +441,10 @@ async def __remindme_repeating(self, ctx: commands.Context, freq: str = "", *, q if bad_input: return + msg_author = ctx.message.author + existing_reminder = await self.fetch_one( - "SELECT * FROM Reminders WHERE Reminder = ? AND ID = ?", (quote, ctx.message.author.id) + "SELECT * FROM Reminders WHERE Reminder = ? AND ID = ?", (quote, msg_author.id) ) if existing_reminder is not None: await ctx.send( @@ -458,13 +452,12 @@ async def __remindme_repeating(self, ctx: commands.Context, freq: str = "", *, q ) return - now = datetime.datetime.now() - msg_author = ctx.message.author + now = datetime.now() async with self.db() as db: num_reminders = await self.get_num_reminders(db, msg_author) await db.execute( "INSERT INTO Reminders VALUES (?, ?, ?, ?, ?, ?)", - (msg_author.id, msg_author.name, quote, freq, now, now) + (msg_author.id, msg_author.name, quote, freq, now, now), ) await db.commit() @@ -480,11 +473,7 @@ async def __remindme_repeating(self, ctx: commands.Context, freq: str = "", *, q await ctx.send("Reminder added.") async def get_num_reminders(self, db: aiosqlite.Connection, author: discord.Member | discord.User) -> int: - num_reminders_t = await self.fetch_one( - "SELECT COUNT(*) FROM Reminders WHERE ID = ?", - (author.id,), - db=db, - ) + num_reminders_t = await self.fetch_one("SELECT COUNT(*) FROM Reminders WHERE ID = ?", (author.id,), db=db) return num_reminders_t[0] if num_reminders_t is not None else 0 From 2f1a864c894db64dac488b9d2e0add69693c4764 Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Mon, 5 Sep 2022 12:43:47 -0400 Subject: [PATCH 066/127] add (de)serialization to settings key methods; some related refactoring --- canary/cogs/banner.py | 53 +++++++++++++++++++---------------------- canary/cogs/base_cog.py | 16 +++++++++---- canary/cogs/mod.py | 28 ++++++++++++---------- 3 files changed, 51 insertions(+), 46 deletions(-) diff --git a/canary/cogs/banner.py b/canary/cogs/banner.py index 2e661d36c..b24edab74 100644 --- a/canary/cogs/banner.py +++ b/canary/cogs/banner.py @@ -72,16 +72,25 @@ async def on_ready(self): self.banner_winner_role = utils.get(self.guild.roles, name=self.bot.config.banner_winner_role) self.banner_vote_emoji = utils.get(self.guild.emojis, name=self.bot.config.banner_vote_emoji) - if (banner_contest_info := await self.get_settings_key("BannerContestInfo")) is not None: - banner_dict = json.loads(banner_contest_info) - timestamp = banner_dict["timestamp"] - if timestamp: + banner_dict: dict | None + if (banner_dict := await self.get_banner_contest_info()) is not None: + if timestamp := banner_dict["timestamp"]: self.start_datetime = datetime.datetime.fromtimestamp(timestamp) self.week_name = banner_dict["week_name"] self.send_reminder = banner_dict["send_reminder"] self.check_banner_contest_reminder.start() + async def get_banner_contest_info(self): + return await self.get_settings_key("BannerContestInfo", deserialize=json.loads) + + async def set_banner_contest_info(self, banner_dict: dict, pre_commit: list[str] | None = None): + timestamp = banner_dict.get("timestamp") + self.start_datetime = datetime.datetime.fromtimestamp(timestamp) if timestamp is not None else None + self.week_name = banner_dict.get("week_name") + self.send_reminder = banner_dict.get("send_reminder") + await self.set_settings_key("BannerContestInfo", banner_dict, serialize=json.dumps, pre_commit=pre_commit) + @tasks.loop(minutes=1.0) async def check_banner_contest_reminder(self): # todo: make general scheduled events db instead @@ -99,19 +108,12 @@ async def check_banner_contest_reminder(self): f"(To get these reminders, type `.iam Banner Submissions` in {self.bots_channel.mention})" ) - if (banner_contest_info := await self.get_settings_key("BannerContestInfo")) is not None: - self.send_reminder = False - banner_dict = json.loads(banner_contest_info) - banner_dict["send_reminder"] = False - await self.set_settings_key("BannerContestInfo", json.dumps(banner_dict)) + banner_dict: dict | None + if (banner_dict := await self.get_banner_contest_info()) is not None: + await self.set_banner_contest_info({**banner_dict, "send_reminder": False}) async def reset_banner_contest(self): - self.start_datetime = None - self.week_name = None - self.send_reminder = None - - banner_dict = {"timestamp": None, "week_name": None, "send_reminder": None} - await self.set_settings_key("BannerContestInfo", json.dumps(banner_dict)) + await self.set_banner_contest_info({"timestamp": None, "week_name": None, "send_reminder": None}) @commands.command(aliases=["setbannercontest"]) @is_moderator() @@ -183,17 +185,14 @@ def msg_check(msg): except asyncio.TimeoutError: await ctx.send("Command timed out.") return + week_name = week_msg.content - banner_dict = {"timestamp": timestamp, "week_name": week_name, "send_reminder": True} - await self.set_settings_key( - "BannerContestInfo", json.dumps(banner_dict), pre_commit=["DELETE FROM BannerSubmissions"] + await self.set_banner_contest_info( + {"timestamp": timestamp, "week_name": week_name, "send_reminder": True}, + pre_commit=["DELETE FROM BannerSubmissions"], ) - self.start_datetime = datetime.datetime.fromtimestamp(timestamp) - self.week_name = week_name - self.send_reminder = True - await ctx.send( f"Start time for the banner contest of the week of `{week_name}` successfully set to " f"`{self.start_datetime.strftime('%Y-%m-%d %H:%M')}`." @@ -246,8 +245,7 @@ def msg_check(msg): if not winner: await ctx.send( - "Please enter the username of the winner " - "or `None` to end the contest without any winner.\n" + "Please enter the username of the winner or `None` to end the contest without any winner.\n" "Type `quit` to leave." ) @@ -409,13 +407,11 @@ async def submit_banner(self, ctx: commands.Context, *args): await ctx.send("You cannot submit banners if you have the Trash Tier Banner Submissions role") return - banner_contest_info = await self.get_settings_key("BannerContestInfo") - if not banner_contest_info: + banner_dict: dict | None = await self.get_banner_contest_info() + if banner_dict is None: await ctx.send("No banner contest is currently set") return - banner_dict = json.loads(banner_contest_info) - timestamp = banner_dict["timestamp"] if not timestamp: await ctx.send("No banner contest is currently set") @@ -525,6 +521,7 @@ async def submit_banner(self, ctx: commands.Context, *args): ) preview_user_image.paste(rgba_frame.resize(preview_user_size), preview_mask_user_image_start) preview_frames.append(Image.alpha_composite(preview_user_image, preview_mask)) + except UnidentifiedImageError or requests.exceptions.MissingSchema: await ctx.send(f"Image couldn't be opened.") return diff --git a/canary/cogs/base_cog.py b/canary/cogs/base_cog.py index 6e44335ad..786d2535f 100644 --- a/canary/cogs/base_cog.py +++ b/canary/cogs/base_cog.py @@ -4,7 +4,7 @@ import os from discord.ext import commands -from typing import AsyncGenerator, Iterable +from typing import Any, AsyncGenerator, Callable, Iterable from ..bot import Canary @@ -61,19 +61,25 @@ async def fetch_one( if fresh_db: await db.close() - async def get_settings_key(self, key: str) -> str | None: + async def get_settings_key(self, key: str, deserialize: Callable[[str], Any] = str) -> Any | None: db: aiosqlite.Connection async with self.db() as db: c: aiosqlite.Cursor async with db.execute("SELECT Value FROM Settings WHERE Key = ?", (key,)) as c: fetched = await c.fetchone() - return fetched[0] if fetched is not None else None + return deserialize(fetched[0]) if fetched is not None else None - async def set_settings_key(self, key: str, value: str, pre_commit: Iterable | None = None) -> None: + async def set_settings_key( + self, + key: str, + value: Any, + serialize: Callable[[Any], str] = str, + pre_commit: Iterable | None = None, + ) -> None: db: aiosqlite.Connection async with self.db() as db: c: aiosqlite.Cursor - await db.execute("REPLACE INTO Settings VALUES (?, ?)", (key, value)) + await db.execute("REPLACE INTO Settings VALUES (?, ?)", (key, serialize(value))) if pre_commit: for s in pre_commit: diff --git a/canary/cogs/mod.py b/canary/cogs/mod.py index b3ec9c8c7..a715669e4 100644 --- a/canary/cogs/mod.py +++ b/canary/cogs/mod.py @@ -73,15 +73,14 @@ async def verification_purge_startup(self): # when fetching message history after that date later on self.last_verification_purge_datetime = datetime(2018, 1, 1) - fetched = await self.get_settings_key("last_verification_purge_timestamp") - if fetched: - last_purge_timestamp = float(fetched) - if last_purge_timestamp: + last_purge_timestamp = await self.get_settings_key("last_verification_purge_timestamp", deserialize=float) + if last_purge_timestamp is not None: + if last_purge_timestamp: # Not 0 self.last_verification_purge_datetime = datetime.fromtimestamp(last_purge_timestamp) else: # the verification purge info setting has not been added to db yet await self.set_settings_key( - "last_verification_purge_timestamp", str(self.last_verification_purge_datetime.timestamp()) + "last_verification_purge_timestamp", self.last_verification_purge_datetime.timestamp() ) self.check_verification_purge.start() @@ -99,7 +98,7 @@ async def check_verification_purge(self): await self.verification_purge_utility(self.last_verification_purge_datetime - timedelta(days=1)) # update info if (await self.get_settings_key("last_verification_purge_timestamp")) is not None: - await self.set_settings_key("last_verification_purge_timestamp", str(datetime.now().timestamp())) + await self.set_settings_key("last_verification_purge_timestamp", datetime.now().timestamp()) @commands.command() async def answer(self, ctx: commands.Context, *args): @@ -146,7 +145,7 @@ async def initiate_crabbo(self, ctx: commands.Context): "🦀🦀🦀 crabbo time 🦀🦀🦀" ) - await self.set_settings_key("CrabboMsgID", str(crabbo_msg.id)) + await self.set_settings_key("CrabboMsgID", crabbo_msg.id) await ctx.message.delete() @commands.command() @@ -154,21 +153,21 @@ async def initiate_crabbo(self, ctx: commands.Context): async def finalize_crabbo(self, ctx: commands.Context): """Sends crabbos their secret crabbo""" - msg_id = await self.get_settings_key("CrabboMsgId") + msg_id = await self.get_settings_key("CrabboMsgId", deserialize=int) - if not msg_id: + if msg_id is None: await ctx.send("secret crabbo is not currently occurring.") return await self.del_settings_key("CrabboMsgId") - crabbos = None - for react in (await ctx.fetch_message(int(msg_id))).reactions: + crabbos = [] + for react in (await ctx.fetch_message(msg_id)).reactions: if str(react) == "🦀": crabbos = await react.users().flatten() break - if crabbos is None or (num_crabbos := len(crabbos)) < 2: + if (num_crabbos := len(crabbos)) < 2: await ctx.send("not enough people participated in the secret crabbo festival.") return @@ -184,13 +183,14 @@ async def verification_purge_utility(self, after: datetime | discord.Message | N if not self.verification_channel: return - # after can be None, a datetime or a discord message await self.verification_channel.send("Starting verification purge") + channel = self.verification_channel deleted = 0 async for message in channel.history(oldest_first=True, limit=None, after=after): if message.attachments or message.embeds: content = message.content + if message.embeds: thumbnail_found = False for embed in message.embeds: @@ -199,11 +199,13 @@ async def verification_purge_utility(self, after: datetime | discord.Message | N content = content.replace(embed.thumbnail.url, "") if not thumbnail_found: continue + if content: await channel.send( f"{message.author} sent the following purged message on " f"{message.created_at.strftime('%Y/%m/%d, %H:%M:%S')}: {content}" ) + await message.delete() deleted += 1 From 05ec215affc6f6924199a6fd4541c556c80b2a5b Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Mon, 5 Sep 2022 12:47:10 -0400 Subject: [PATCH 067/127] f string --- canary/cogs/utils/role_restoration.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/canary/cogs/utils/role_restoration.py b/canary/cogs/utils/role_restoration.py index 0e38df500..ab6279693 100644 --- a/canary/cogs/utils/role_restoration.py +++ b/canary/cogs/utils/role_restoration.py @@ -63,7 +63,7 @@ async def fetch_saved_roles(bot: Canary, guild, user: discord.Member, muted: boo c: aiosqlite.Cursor async with bot.db() as db: - q = "SELECT Roles FROM " + ("MutedUsers WHERE UserID = ?" if muted else "PreviousRoles WHERE ID = ?") + q = f"SELECT Roles FROM {'MutedUsers WHERE UserID' if muted else 'PreviousRoles WHERE ID'} = ?" async with db.execute(q, (user.id,)) as c: fetched_roles = await c.fetchone() From ebf5dd70391645f3b7737018b416c5db724355cb Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Sat, 12 Nov 2022 10:50:43 -0500 Subject: [PATCH 068/127] chore: more typing --- canary/cogs/currency.py | 8 +-- canary/cogs/customreactions.py | 83 +++++++++++++++++------------ canary/cogs/games.py | 10 ++-- canary/cogs/helpers.py | 12 ++++- canary/cogs/memes.py | 6 +-- canary/cogs/mod.py | 9 ++-- canary/cogs/music.py | 5 +- canary/cogs/quotes.py | 10 ++-- canary/cogs/utils/auto_incorrect.py | 4 +- 9 files changed, 88 insertions(+), 59 deletions(-) diff --git a/canary/cogs/currency.py b/canary/cogs/currency.py index 9fa8ee2e1..f5c22e638 100644 --- a/canary/cogs/currency.py +++ b/canary/cogs/currency.py @@ -227,7 +227,7 @@ async def claim(self, ctx: commands.Context): await ctx.send(f"Please wait {time_left.seconds // 3600}h {time_left.seconds // 60 % 60}m to claim again!") @commands.command(aliases=["$", "bal"]) - async def balance(self, ctx, user: discord.Member = None): + async def balance(self, ctx: commands.Context, user: discord.Member = None): """ Return the user's account balance. """ @@ -243,7 +243,7 @@ async def balance(self, ctx, user: discord.Member = None): await ctx.send(f"{author.display_name} has {amount} in their account.") @commands.command(aliases=["bf"]) - async def bet_flip(self, ctx, bet: str = None, face: str = None): + async def bet_flip(self, ctx: commands.Context, bet: str | None = None, face: str | None = None): """ Bets an amount of money on a coin flip. Usage: ?bet_flip h 10 or ?bet_flip t 5 @@ -291,7 +291,7 @@ async def bet_flip(self, ctx, bet: str = None, face: str = None): await ctx.send(message.format(author_name, self.format_symbol_currency(bet_dec), result)) @commands.command(aliases=["br"]) - async def bet_roll(self, ctx, bet: str = None): + async def bet_roll(self, ctx: commands.Context, bet: str | None = None): """ Bets an amount of currency on a D100 roll. Usage: ?bet_roll 100 or ?br all @@ -350,7 +350,7 @@ async def bet_roll(self, ctx, bet: str = None): await ctx.send(message.format(un=author_name, am=bet_str, re=result)) @commands.command() - async def give(self, ctx, user: discord.Member = None, amount: str = None): + async def give(self, ctx: commands.Context, user: discord.Member | None = None, amount: str | None = None): """ Gives some amount of currency to another user. """ diff --git a/canary/cogs/customreactions.py b/canary/cogs/customreactions.py index 1e9e5476a..15a9d5a50 100644 --- a/canary/cogs/customreactions.py +++ b/canary/cogs/customreactions.py @@ -20,12 +20,21 @@ import discord from discord.ext import commands +from typing import Callable, Coroutine, Literal, TypedDict from ..bot import Canary from .base_cog import CanaryCog from .utils.paginator import Pages from .utils.p_strings import PStringEncodings + +class AssistantAction(TypedDict, total=False): + fn: Callable[[discord.Message, bool, ...], Coroutine[None, None, bool]] + desc: str + kwargs: dict + hidden: bool + + EMOJI = { "new": "🆕", "mag": "🔍", @@ -69,11 +78,11 @@ async def on_ready(self): await super().on_ready() await self.rebuild_lists() - async def rebuild_lists(self): + async def rebuild_lists(self) -> None: await self.rebuild_reaction_list() await self.rebuild_proposal_list() - async def rebuild_reaction_list(self): + async def rebuild_reaction_list(self) -> None: self.reaction_list = await self.fetch_list("SELECT * FROM CustomReactions WHERE Proposal = 0") prompts = [row[1].lower() for row in self.reaction_list] @@ -84,11 +93,11 @@ async def rebuild_reaction_list(self): prompts, responses, anywhere_values, additional_info_list=additional_info_list ) - async def rebuild_proposal_list(self): + async def rebuild_proposal_list(self) -> None: self.proposal_list = await self.fetch_list("SELECT * FROM CustomReactions WHERE Proposal = 1") @commands.Cog.listener() - async def on_message(self, message: discord.Message): + async def on_message(self, message: discord.Message) -> None: if message.author == self.bot.user: return @@ -117,10 +126,10 @@ async def customreactions(self, ctx: commands.Context): main_user = ctx.message.author await ctx.message.delete() - def get_number_of_proposals(): + def get_number_of_proposals() -> int: return len(self.proposal_list) - def get_reaction_check(moderators=False, reaction_user=None): + def get_reaction_check(moderators=False, reaction_user=None) -> Callable: def reaction_check(reaction, user): return all( ( @@ -133,7 +142,7 @@ def reaction_check(reaction, user): return reaction_check - def get_msg_check(msg_user=None): + def get_msg_check(msg_user=None) -> Callable: def msg_check(msg): if all((not msg_user or msg.author == msg_user, msg.channel == ctx.channel)): if msg.attachments: @@ -147,7 +156,7 @@ def msg_check(msg): return msg_check - def get_number_check(msg_user=None, number_range=None): + def get_number_check(msg_user=None, number_range=None) -> Callable: def number_check(msg): if msg.content.isdigit(): return all( @@ -171,7 +180,7 @@ async def wait_for_reaction(message: discord.Message): return return reaction, user - async def wait_for_message(message: discord.Message): + async def wait_for_message(message: discord.Message) -> str | None: try: msg = await self.bot.wait_for("message", check=get_msg_check(msg_user=main_user), timeout=60) except asyncio.TimeoutError: @@ -182,18 +191,18 @@ async def wait_for_message(message: discord.Message): await msg.delete() return content - async def clear_options(message: discord.Message): + async def clear_options(message: discord.Message) -> None: current_options.clear() await message.clear_reactions() - async def add_multiple_reactions(message: discord.Message, reactions): + async def add_multiple_reactions(message: discord.Message, reactions) -> None: for reaction in reactions: await message.add_reaction(reaction) - async def add_yes_or_no_reactions(message: discord.Message): + async def add_yes_or_no_reactions(message: discord.Message) -> None: await add_multiple_reactions(message, (EMOJI["zero"], EMOJI["one"], EMOJI["stop_button"])) - async def add_control_reactions(message: discord.Message): + async def add_control_reactions(message: discord.Message) -> None: await add_multiple_reactions( message, ( @@ -206,8 +215,8 @@ async def add_control_reactions(message: discord.Message): ), ) - async def create_assistant(message: discord.Message, is_moderator: bool) -> bool | None: - actions = { + async def create_assistant(message: discord.Message, is_moderator: bool) -> bool: + actions: dict[str, AssistantAction] = { # Add/Propose a new custom reaction EMOJI["new"]: { "fn": add_custom_react, @@ -261,14 +270,14 @@ async def create_assistant(message: discord.Message, is_moderator: bool) -> bool try: reaction, user = await wait_for_reaction(message) except TypeError: - return + return False await clear_options(message) if (action := actions.get(reaction.emoji)) is not None: return await action["fn"](message, **action["kwargs"]) - async def add_custom_react(message: discord.Message, proposals: bool): + async def add_custom_react(message: discord.Message, proposals: bool) -> bool: status_msg = f"{main_user} is currently {'proposing' if proposals else 'adding'} a custom reaction." title = f"{'Propose' if proposals else 'Add'} a custom reaction" @@ -287,7 +296,7 @@ async def _refresh_msg(): prompt_message = await wait_for_message(message) if prompt_message is None: - return + return False if prompt_message.lower() == STOP_TEXT: await leave(message) @@ -299,7 +308,7 @@ async def _refresh_msg(): response = await wait_for_message(message) if response is None: - return + return False if response.lower() == STOP_TEXT: await leave(message) @@ -324,7 +333,7 @@ async def _refresh_msg(): try: reaction, user = await wait_for_reaction(message) except TypeError: - return + return False # If the user clicked OK, check if delete/anywhere/dm are checked if reaction.emoji == EMOJI["ok"]: @@ -372,13 +381,15 @@ async def _refresh_msg(): await _refresh_msg() - return + return False # Stop if reaction.emoji == EMOJI["stop_button"]: return await leave(message) - async def list_custom_reacts(message: discord.Message, proposals: bool) -> bool | None: + return False + + async def list_custom_reacts(message: discord.Message, proposals: bool) -> bool: current_list = self.proposal_list if proposals else self.reaction_list no_items_msg = f"There are currently no custom reaction{' proposal' if proposals else ''}s in this server" @@ -386,7 +397,7 @@ async def list_custom_reacts(message: discord.Message, proposals: bool) -> bool if not current_list: title = no_items_msg await message.edit(embed=discord.Embed(title=title), delete_after=60) - return + return False reaction_dict = { "names": [f"[{i + 1}]" for i in range(len(current_list))], @@ -498,7 +509,7 @@ async def list_custom_reacts(message: discord.Message, proposals: bool) -> bool if not current_list: title = no_items_msg await message.edit(embed=discord.Embed(title=title), delete_after=60) - return + return False reaction_dict = { "names": [f"[{i + 1}]" for i in range(len(current_list))], @@ -525,7 +536,9 @@ async def list_custom_reacts(message: discord.Message, proposals: bool) -> bool await add_control_reactions(message) user_modifying = await p.paginate() - async def information_on_react(message: discord.Message, current_list, number, proposals) -> bool | None: + return False + + async def information_on_react(message: discord.Message, current_list, number, proposals) -> bool: await message.edit(embed=LOADING_EMBED) custom_react = current_list[number - 1] @@ -610,6 +623,7 @@ async def information_on_react(message: discord.Message, current_list, number, p pass await clear_options(message) + return False async def edit_custom_react( message: discord.Message, @@ -617,7 +631,7 @@ async def edit_custom_react( user, custom_react, proposals, - ) -> bool | None: + ) -> bool: # Returns whether to leave the wizard db: aiosqlite.Connection await clear_options(message) @@ -661,7 +675,7 @@ async def _edit_reaction_and_rebuild(react_id, key, value): except asyncio.TimeoutError: await message.edit(embed=discord.Embed(title=message_time_out)) await asyncio.sleep(5) - return + return False prompt = msg.content await msg.delete() @@ -691,7 +705,7 @@ async def _edit_reaction_and_rebuild(react_id, key, value): except asyncio.TimeoutError: await message.edit(embed=discord.Embed(title=message_time_out)) await asyncio.sleep(5) - return + return False response = msg.content await msg.delete() @@ -740,7 +754,7 @@ async def _edit_reaction_and_rebuild(react_id, key, value): await asyncio.sleep(5) current_options.clear() await message.clear_reactions() - return + return False current_options.clear() await message.clear_reactions() @@ -795,7 +809,7 @@ async def _edit_reaction_and_rebuild(react_id, key, value): await asyncio.sleep(5) current_options.clear() await message.clear_reactions() - return + return False current_options.clear() await message.clear_reactions() @@ -853,7 +867,7 @@ async def _edit_reaction_and_rebuild(react_id, key, value): await asyncio.sleep(5) current_options.clear() await message.clear_reactions() - return + return False current_options.clear() await message.clear_reactions() @@ -908,7 +922,9 @@ async def _edit_reaction_and_rebuild(react_id, key, value): if reaction.emoji == EMOJI["stop_button"]: return await leave(message) - async def list_placeholders(message, **_kwargs): + return False + + async def list_placeholders(message, **_kwargs) -> Literal[False]: title = "The following placeholders can be used in prompts and responses:" description = ( "-%user%: the user who called the prompt (can only be used in a response)\n" @@ -928,8 +944,9 @@ async def list_placeholders(message, **_kwargs): 'it can be surrounded by "" to not be split into different choices' ) await message.edit(embed=discord.Embed(title=title, description=description)) + return False - async def leave(message, **_kwargs) -> True: + async def leave(message, **_kwargs) -> Literal[True]: await message.delete() return True diff --git a/canary/cogs/games.py b/canary/cogs/games.py index 40fba4dc8..ab57157fb 100644 --- a/canary/cogs/games.py +++ b/canary/cogs/games.py @@ -28,6 +28,7 @@ from time import time from functools import partial +from ..bot import Canary from .base_cog import CanaryCog from .utils.dice_roll import dice_roll from .utils.clamp_default import clamp_default @@ -35,7 +36,7 @@ from .currency import HANGMAN_REWARD ROLL_PATTERN = re.compile(r"^(\d*)d(\d*)([+-]?\d*)$") -CATEGORY_SYNONYMS = { +CATEGORY_SYNONYMS: dict[str, str] = { "movies": "movie", "kino": "movie", "elements": "element", @@ -45,7 +46,7 @@ class Games(CanaryCog): - def __init__(self, bot, hangman_tbl_name: str): + def __init__(self, bot: Canary, hangman_tbl_name: str) -> None: super().__init__(bot) self.hm_cool_win: int = bot.config.games["hm_cool_win"] @@ -56,7 +57,7 @@ def __init__(self, bot, hangman_tbl_name: str): with open(f"{os.getcwd()}/data/premade/{hangman_tbl_name}.obj", "rb") as hangman_pkl: self.hangman_dict: dict[str, tuple[list[tuple[str, str | None]], str]] = pickle.load(hangman_pkl) - def help_str(self): + def help_str(self) -> str: cat_list: str = ", ".join( f"`{hm_cat}` (length: {len(self.hangman_dict[hm_cat][0])})" for hm_cat in sorted(self.hangman_dict.keys()) ) @@ -103,7 +104,8 @@ async def hangman(self, ctx, command: str | None = None): await ctx.send("no game is currently being played in this channel") return - category: str = CATEGORY_SYNONYMS.get(command, command) or random.choice(list(self.hangman_dict.keys())) + command_str: str = command or "" + category: str = CATEGORY_SYNONYMS.get(command_str, command_str) or random.choice(list(self.hangman_dict.keys())) try: word_list, pretty_name = self.hangman_dict[category] except KeyError: diff --git a/canary/cogs/helpers.py b/canary/cogs/helpers.py index a8d5cd89a..029410540 100644 --- a/canary/cogs/helpers.py +++ b/canary/cogs/helpers.py @@ -712,7 +712,12 @@ async def create_main_webhooks(self, ctx: commands.Context): await ctx.send(f"Ignored {ignored} channel{'s' if ignored == 1 else ''} without bot permissions") await ctx.send("Job completed.") - async def spoilerize_utility(self, ctx: commands.Context, message, reason: str = None, moderator: bool = False): + async def spoilerize_utility( + self, ctx: commands.Context, + message: discord.Message, + reason: str | None = None, + moderator: bool = False + ) -> None: db: aiosqlite.Connection if not moderator and ctx.author != message.author: @@ -777,9 +782,12 @@ async def spoilerize_utility(self, ctx: commands.Context, message, reason: str = await message.delete() @commands.Cog.listener() - async def on_raw_reaction_add(self, payload): + async def on_raw_reaction_add(self, payload) -> None: db: aiosqlite.Connection + if not self.guild: + return + if payload.guild_id != self.guild.id or str(payload.emoji) != "🚮": return diff --git a/canary/cogs/memes.py b/canary/cogs/memes.py index e46d4ee9a..5ceba23de 100644 --- a/canary/cogs/memes.py +++ b/canary/cogs/memes.py @@ -28,7 +28,7 @@ class Memes(CanaryCog): @commands.command() - async def bac(self, ctx, *, input_str: str = None): + async def bac(self, ctx: commands.Context, *, input_str: str | None = None): """ Purposefully auto-incorrects inputted sentences Inputted text is either the content of the message to @@ -98,7 +98,7 @@ async def cheep(self, ctx): await ctx.send("CHEEP CHEEP") @commands.command() - async def mix(self, ctx, *, input_str: str = None): + async def mix(self, ctx, *, input_str: str | None = None): """Alternates upper/lower case for input string. Inputted text is either the content of the message to after the command or the content of the message to which @@ -147,7 +147,7 @@ def pyramidy(n, m): await ctx.send(f"**\n{msg}**") @commands.command() - async def xkcd(self, ctx, command: str = None): + async def xkcd(self, ctx, command: str | None = None): """ Enjoy a nice xkcd comic with some strangers on the internet! If no issue number is passed, returns a random xkcd. diff --git a/canary/cogs/mod.py b/canary/cogs/mod.py index a715669e4..79213eee1 100644 --- a/canary/cogs/mod.py +++ b/canary/cogs/mod.py @@ -21,6 +21,7 @@ from discord import utils from discord.ext import commands, tasks +from ..bot import Canary from .base_cog import CanaryCog from .utils.checks import is_moderator from datetime import datetime, timedelta @@ -36,7 +37,7 @@ class Mod(CanaryCog): - def __init__(self, bot): + def __init__(self, bot: Canary) -> None: super().__init__(bot) self.verification_channel: discord.TextChannel | None = None @@ -215,7 +216,7 @@ async def verification_purge_utility(self, after: datetime | discord.Message | N @commands.command() @is_moderator() - async def verification_purge(self, ctx, id_: int = None): + async def verification_purge(self, ctx: commands.Context, id_: int | None = None): """ Manually start the purge of pictures in the verification channel. @@ -243,7 +244,7 @@ async def verification_purge(self, ctx, id_: int = None): await self.verification_purge_utility(message) - async def mute_utility(self, user: discord.Member, ctx=None): + async def mute_utility(self, user: discord.Member, ctx: commands.Context | MockContext | None = None): if not self.guild: return @@ -252,7 +253,7 @@ async def mute_utility(self, user: discord.Member, ctx=None): # note that this is made such that if a user is already muted # we make sure the user still has the role, is still in the db, and still has a channel - confirmation_channel = ctx.channel if ctx else self.appeals_log_channel + confirmation_channel: discord.TextChannel = ctx.channel if ctx else self.appeals_log_channel appeals_category = utils.get(self.guild.categories, name=self.bot.config.appeals_category) moderator_role = utils.get(self.guild.roles, name=self.bot.config.moderator_role) reason_message = ( diff --git a/canary/cogs/music.py b/canary/cogs/music.py index 5be467856..fdfa7714f 100644 --- a/canary/cogs/music.py +++ b/canary/cogs/music.py @@ -30,6 +30,7 @@ from inspect import getdoc from typing import Callable, Optional, Iterable +from ..bot import Canary from .base_cog import CanaryCog from .utils.music_helpers import ( FFMPEG_BEFORE_OPTS, @@ -50,7 +51,7 @@ class Music(CanaryCog): - def __init__(self, bot): + def __init__(self, bot: Canary): super().__init__(bot) self.track_queue: deque[tuple[dict, str]] = deque() @@ -117,7 +118,7 @@ def play_track(self, ctx, *, skip_str: Optional[str] = None, delta: int = 0): ) self.track_start_time = time.perf_counter() - delta - def from_total(self, idx): + def from_total(self, idx: int) -> tuple[deque[tuple[dict, str]], int] | None: q_len: int = self.total_len() if idx >= q_len or idx < -q_len: return None diff --git a/canary/cogs/quotes.py b/canary/cogs/quotes.py index 12b22b13d..a1678e8fc 100644 --- a/canary/cogs/quotes.py +++ b/canary/cogs/quotes.py @@ -155,7 +155,7 @@ def check(reaction, user): await ctx.send("`Quote deleted.`", delete_after=60) @commands.command(aliases=["q"]) - async def quotes(self, ctx, str1: str = None, *, str2: str = None): + async def quotes(self, ctx, str1: str | None = None, *, str2: str | None = None): """ Retrieve a quote with a specified keyword / mention. Can optionally use regex by surrounding the the query with /.../. @@ -366,7 +366,7 @@ async def all_quotes(self, ctx: commands.Context, *, query: str): await p.paginate() @commands.command(aliases=["gen"]) - async def generate(self, ctx: commands.Context, seed: str = None, min_length: int = 1): + async def generate(self, ctx: commands.Context, seed: str | None = None, min_length: int = 1): """ Generates a random 'quote' using a Markov Chain. Optionally takes in a word to seed the Markov Chain with and (also optionally) a desired @@ -396,8 +396,8 @@ async def generate(self, ctx: commands.Context, seed: str = None, min_length: in retries = 0 while len(longest_sentence) < min_length and retries < 200: - current_word = seed - sentence = [current_word] + current_word: str = seed + sentence: list[str] = [current_word] # Add words to the sentence until a termination condition is # encountered. @@ -407,7 +407,7 @@ async def generate(self, ctx: commands.Context, seed: str = None, min_length: in # Choose a random word and add it to the sentence using the # probability distribution stored in the word entry. - old_word = current_word + old_word: str = current_word current_word = np.random.choice(c_words, p=p_dist) # Don't allow termination until the minimum length is met, or we don't have any other option. diff --git a/canary/cogs/utils/auto_incorrect.py b/canary/cogs/utils/auto_incorrect.py index 6b86f2a9b..ba9862c2e 100644 --- a/canary/cogs/utils/auto_incorrect.py +++ b/canary/cogs/utils/auto_incorrect.py @@ -63,11 +63,11 @@ def auto_incorrect(input_str: str): By @lazho """ chance = 99 - input_str = input_str.split() + input_split: list[str] = input_str.split() output_str = "" - for w in input_str: + for w in input_split: output_str += " " # Idiots don't use shift or capslock From 5f680b9c7472b8102a348abe26b125ed376621b4 Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Sat, 19 Nov 2022 18:34:41 -0500 Subject: [PATCH 069/127] chore: update dev dependencies & lockfile --- poetry.lock | 428 ++++++++++++++++++++++++++----------------------- pyproject.toml | 6 +- 2 files changed, 232 insertions(+), 202 deletions(-) diff --git a/poetry.lock b/poetry.lock index 49a810018..3f11d167d 100644 --- a/poetry.lock +++ b/poetry.lock @@ -48,7 +48,7 @@ python-versions = ">=3.5" dev = ["cloudpickle", "coverage[toml] (>=5.0.2)", "furo", "hypothesis", "mypy (>=0.900,!=0.940)", "pre-commit", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "sphinx", "sphinx-notfound-page", "zope.interface"] docs = ["furo", "sphinx", "sphinx-notfound-page", "zope.interface"] tests = ["cloudpickle", "coverage[toml] (>=5.0.2)", "hypothesis", "mypy (>=0.900,!=0.940)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "zope.interface"] -tests_no_zope = ["cloudpickle", "coverage[toml] (>=5.0.2)", "hypothesis", "mypy (>=0.900,!=0.940)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins"] +tests-no-zope = ["cloudpickle", "coverage[toml] (>=5.0.2)", "hypothesis", "mypy (>=0.900,!=0.940)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins"] [[package]] name = "beautifulsoup4" @@ -75,11 +75,11 @@ python-versions = ">=3.7" [[package]] name = "black" -version = "22.8.0" +version = "22.10.0" description = "The uncompromising code formatter." category = "dev" optional = false -python-versions = ">=3.6.2" +python-versions = ">=3.7" [package.dependencies] click = ">=8.0.0" @@ -96,7 +96,7 @@ uvloop = ["uvloop (>=0.15.2)"] [[package]] name = "certifi" -version = "2022.6.15" +version = "2022.9.24" description = "Python package for providing Mozilla's CA Bundle." category = "main" optional = false @@ -130,7 +130,7 @@ optional = false python-versions = ">=3.6.0" [package.extras] -unicode_backport = ["unicodedata2"] +unicode-backport = ["unicodedata2"] [[package]] name = "click" @@ -145,14 +145,14 @@ colorama = {version = "*", markers = "platform_system == \"Windows\""} [[package]] name = "colorama" -version = "0.4.5" +version = "0.4.6" description = "Cross-platform colored terminal text." category = "dev" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" [[package]] -name = "discord.py" +name = "discord-py" version = "1.6.0" description = "A Python wrapper for the Discord API" category = "main" @@ -167,6 +167,17 @@ PyNaCl = {version = ">=1.3.0,<1.5", optional = true, markers = "extra == \"voice docs = ["sphinx (==3.0.3)", "sphinxcontrib-trio (==1.1.2)", "sphinxcontrib-websupport"] voice = ["PyNaCl (>=1.3.0,<1.5)"] +[[package]] +name = "exceptiongroup" +version = "1.0.4" +description = "Backport of PEP 654 (exception groups)" +category = "dev" +optional = false +python-versions = ">=3.7" + +[package.extras] +test = ["pytest (>=6)"] + [[package]] name = "feedparser" version = "6.0.10" @@ -219,7 +230,7 @@ python-versions = "*" [[package]] name = "hstspreload" -version = "2022.9.1" +version = "2022.11.1" description = "Chromium HSTS Preload list as a Python package" category = "main" optional = false @@ -315,19 +326,19 @@ python-versions = ">=3.7" [[package]] name = "mutagen" -version = "1.45.1" +version = "1.46.0" description = "read and write audio tags for many formats" category = "main" optional = false -python-versions = ">=3.5, <4" +python-versions = ">=3.7" [[package]] name = "mypy" -version = "0.971" +version = "0.990" description = "Optional static typing for Python" category = "dev" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" [package.dependencies] mypy-extensions = ">=0.4.3" @@ -336,6 +347,7 @@ typing-extensions = ">=3.10" [package.extras] dmypy = ["psutil (>=4.0)"] +install-types = ["pip"] python2 = ["typed-ast (>=1.4.0,<2)"] reports = ["lxml"] @@ -349,7 +361,7 @@ python-versions = "*" [[package]] name = "numpy" -version = "1.23.2" +version = "1.23.4" description = "NumPy is the fundamental package for array computing with Python." category = "main" optional = false @@ -384,14 +396,14 @@ pyparsing = ">=2.0.2,<3.0.5 || >3.0.5" [[package]] name = "pathspec" -version = "0.10.1" +version = "0.10.2" description = "Utility library for gitignore style pattern matching of file paths." category = "dev" optional = false python-versions = ">=3.7" [[package]] -name = "Pillow" +name = "pillow" version = "8.4.0" description = "Python Imaging Library (Fork)" category = "main" @@ -400,15 +412,15 @@ python-versions = ">=3.6" [[package]] name = "platformdirs" -version = "2.5.2" -description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." +version = "2.5.4" +description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." category = "dev" optional = false python-versions = ">=3.7" [package.extras] -docs = ["furo (>=2021.7.5b38)", "proselint (>=0.10.2)", "sphinx (>=4)", "sphinx-autodoc-typehints (>=1.12)"] -test = ["appdirs (==1.4.4)", "pytest (>=6)", "pytest-cov (>=2.7)", "pytest-mock (>=3.6)"] +docs = ["furo (>=2022.9.29)", "proselint (>=0.13)", "sphinx (>=5.3)", "sphinx-autodoc-typehints (>=1.19.4)"] +test = ["appdirs (==1.4.4)", "pytest (>=7.2)", "pytest-cov (>=4)", "pytest-mock (>=3.10)"] [[package]] name = "pluggy" @@ -422,14 +434,6 @@ python-versions = ">=3.6" dev = ["pre-commit", "tox"] testing = ["pytest", "pytest-benchmark"] -[[package]] -name = "py" -version = "1.11.0" -description = "library with cross-python path, ini-parsing, io, code, log facilities" -category = "dev" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" - [[package]] name = "pycparser" version = "2.21" @@ -447,7 +451,7 @@ optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" [[package]] -name = "PyNaCl" +name = "pynacl" version = "1.4.0" description = "Python binding to the Networking and Cryptography (NaCl) library" category = "main" @@ -475,7 +479,7 @@ diagrams = ["jinja2", "railroad-diagrams"] [[package]] name = "pytest" -version = "7.1.3" +version = "7.2.0" description = "pytest: simple powerful testing with Python" category = "dev" optional = false @@ -484,18 +488,18 @@ python-versions = ">=3.7" [package.dependencies] attrs = ">=19.2.0" colorama = {version = "*", markers = "sys_platform == \"win32\""} +exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""} iniconfig = "*" packaging = "*" pluggy = ">=0.12,<2.0" -py = ">=1.8.2" -tomli = ">=1.0.0" +tomli = {version = ">=1.0.0", markers = "python_version < \"3.11\""} [package.extras] testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "xmlschema"] [[package]] name = "pytz" -version = "2022.2.1" +version = "2022.6" description = "World timezone definitions, modern and historical" category = "main" optional = false @@ -525,7 +529,7 @@ urllib3 = ">=1.21.1,<1.27" [package.extras] socks = ["PySocks (>=1.5.6,!=1.5.7)"] -use_chardet_on_py3 = ["chardet (>=3.0.2,<6)"] +use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] [[package]] name = "rfc3986" @@ -602,7 +606,7 @@ python-versions = ">=3.7" [[package]] name = "types-beautifulsoup4" -version = "4.11.5" +version = "4.11.6.1" description = "Typing stubs for beautifulsoup4" category = "dev" optional = false @@ -610,7 +614,7 @@ python-versions = "*" [[package]] name = "types-pytz" -version = "2022.2.1.0" +version = "2022.6.0.1" description = "Typing stubs for pytz" category = "dev" optional = false @@ -618,7 +622,7 @@ python-versions = "*" [[package]] name = "types-regex" -version = "2022.8.17.0" +version = "2022.10.31.0" description = "Typing stubs for regex" category = "dev" optional = false @@ -626,7 +630,7 @@ python-versions = "*" [[package]] name = "types-requests" -version = "2.28.9" +version = "2.28.11.5" description = "Typing stubs for requests" category = "dev" optional = false @@ -645,7 +649,7 @@ python-versions = "*" [[package]] name = "types-urllib3" -version = "1.26.23" +version = "1.26.25.4" description = "Typing stubs for urllib3" category = "dev" optional = false @@ -653,7 +657,7 @@ python-versions = "*" [[package]] name = "typing-extensions" -version = "4.3.0" +version = "4.4.0" description = "Backported and Experimental Type Hints for Python 3.7+" category = "main" optional = false @@ -687,7 +691,7 @@ test = ["aiohttp", "flake8 (>=3.9.2,<3.10.0)", "mypy (>=0.800)", "psutil", "pyOp [[package]] name = "websockets" -version = "10.3" +version = "10.4" description = "An implementation of the WebSocket Protocol (RFC 6455 & 7692)" category = "main" optional = false @@ -721,7 +725,7 @@ websockets = "*" [metadata] lock-version = "1.1" python-versions = "~3.10.0" -content-hash = "8f6b854b763818669b1eacc38df9860f8ab0267058d2931f7cae8e1ad6243deb" +content-hash = "9a9885637d1c56e793e349491971c5b7d66a560a48b388a57fbf496b39f22f3b" [metadata.files] aiohttp = [ @@ -784,33 +788,31 @@ bidict = [ {file = "bidict-0.22.0.tar.gz", hash = "sha256:5c826b3e15e97cc6e615de295756847c282a79b79c5430d3bfc909b1ac9f5bd8"}, ] black = [ - {file = "black-22.8.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:ce957f1d6b78a8a231b18e0dd2d94a33d2ba738cd88a7fe64f53f659eea49fdd"}, - {file = "black-22.8.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5107ea36b2b61917956d018bd25129baf9ad1125e39324a9b18248d362156a27"}, - {file = "black-22.8.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e8166b7bfe5dcb56d325385bd1d1e0f635f24aae14b3ae437102dedc0c186747"}, - {file = "black-22.8.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd82842bb272297503cbec1a2600b6bfb338dae017186f8f215c8958f8acf869"}, - {file = "black-22.8.0-cp310-cp310-win_amd64.whl", hash = "sha256:d839150f61d09e7217f52917259831fe2b689f5c8e5e32611736351b89bb2a90"}, - {file = "black-22.8.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:a05da0430bd5ced89176db098567973be52ce175a55677436a271102d7eaa3fe"}, - {file = "black-22.8.0-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4a098a69a02596e1f2a58a2a1c8d5a05d5a74461af552b371e82f9fa4ada8342"}, - {file = "black-22.8.0-cp36-cp36m-win_amd64.whl", hash = "sha256:5594efbdc35426e35a7defa1ea1a1cb97c7dbd34c0e49af7fb593a36bd45edab"}, - {file = "black-22.8.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:a983526af1bea1e4cf6768e649990f28ee4f4137266921c2c3cee8116ae42ec3"}, - {file = "black-22.8.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3b2c25f8dea5e8444bdc6788a2f543e1fb01494e144480bc17f806178378005e"}, - {file = "black-22.8.0-cp37-cp37m-win_amd64.whl", hash = "sha256:78dd85caaab7c3153054756b9fe8c611efa63d9e7aecfa33e533060cb14b6d16"}, - {file = "black-22.8.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:cea1b2542d4e2c02c332e83150e41e3ca80dc0fb8de20df3c5e98e242156222c"}, - {file = "black-22.8.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:5b879eb439094751185d1cfdca43023bc6786bd3c60372462b6f051efa6281a5"}, - {file = "black-22.8.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:0a12e4e1353819af41df998b02c6742643cfef58282915f781d0e4dd7a200411"}, - {file = "black-22.8.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c3a73f66b6d5ba7288cd5d6dad9b4c9b43f4e8a4b789a94bf5abfb878c663eb3"}, - {file = "black-22.8.0-cp38-cp38-win_amd64.whl", hash = "sha256:e981e20ec152dfb3e77418fb616077937378b322d7b26aa1ff87717fb18b4875"}, - {file = "black-22.8.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:8ce13ffed7e66dda0da3e0b2eb1bdfc83f5812f66e09aca2b0978593ed636b6c"}, - {file = "black-22.8.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:32a4b17f644fc288c6ee2bafdf5e3b045f4eff84693ac069d87b1a347d861497"}, - {file = "black-22.8.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0ad827325a3a634bae88ae7747db1a395d5ee02cf05d9aa7a9bd77dfb10e940c"}, - {file = "black-22.8.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:53198e28a1fb865e9fe97f88220da2e44df6da82b18833b588b1883b16bb5d41"}, - {file = "black-22.8.0-cp39-cp39-win_amd64.whl", hash = "sha256:bc4d4123830a2d190e9cc42a2e43570f82ace35c3aeb26a512a2102bce5af7ec"}, - {file = "black-22.8.0-py3-none-any.whl", hash = "sha256:d2c21d439b2baf7aa80d6dd4e3659259be64c6f49dfd0f32091063db0e006db4"}, - {file = "black-22.8.0.tar.gz", hash = "sha256:792f7eb540ba9a17e8656538701d3eb1afcb134e3b45b71f20b25c77a8db7e6e"}, + {file = "black-22.10.0-1fixedarch-cp310-cp310-macosx_11_0_x86_64.whl", hash = "sha256:5cc42ca67989e9c3cf859e84c2bf014f6633db63d1cbdf8fdb666dcd9e77e3fa"}, + {file = "black-22.10.0-1fixedarch-cp311-cp311-macosx_11_0_x86_64.whl", hash = "sha256:5d8f74030e67087b219b032aa33a919fae8806d49c867846bfacde57f43972ef"}, + {file = "black-22.10.0-1fixedarch-cp37-cp37m-macosx_10_16_x86_64.whl", hash = "sha256:197df8509263b0b8614e1df1756b1dd41be6738eed2ba9e9769f3880c2b9d7b6"}, + {file = "black-22.10.0-1fixedarch-cp38-cp38-macosx_10_16_x86_64.whl", hash = "sha256:2644b5d63633702bc2c5f3754b1b475378fbbfb481f62319388235d0cd104c2d"}, + {file = "black-22.10.0-1fixedarch-cp39-cp39-macosx_11_0_x86_64.whl", hash = "sha256:e41a86c6c650bcecc6633ee3180d80a025db041a8e2398dcc059b3afa8382cd4"}, + {file = "black-22.10.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2039230db3c6c639bd84efe3292ec7b06e9214a2992cd9beb293d639c6402edb"}, + {file = "black-22.10.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:14ff67aec0a47c424bc99b71005202045dc09270da44a27848d534600ac64fc7"}, + {file = "black-22.10.0-cp310-cp310-win_amd64.whl", hash = "sha256:819dc789f4498ecc91438a7de64427c73b45035e2e3680c92e18795a839ebb66"}, + {file = "black-22.10.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5b9b29da4f564ba8787c119f37d174f2b69cdfdf9015b7d8c5c16121ddc054ae"}, + {file = "black-22.10.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b8b49776299fece66bffaafe357d929ca9451450f5466e997a7285ab0fe28e3b"}, + {file = "black-22.10.0-cp311-cp311-win_amd64.whl", hash = "sha256:21199526696b8f09c3997e2b4db8d0b108d801a348414264d2eb8eb2532e540d"}, + {file = "black-22.10.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1e464456d24e23d11fced2bc8c47ef66d471f845c7b7a42f3bd77bf3d1789650"}, + {file = "black-22.10.0-cp37-cp37m-win_amd64.whl", hash = "sha256:9311e99228ae10023300ecac05be5a296f60d2fd10fff31cf5c1fa4ca4b1988d"}, + {file = "black-22.10.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:fba8a281e570adafb79f7755ac8721b6cf1bbf691186a287e990c7929c7692ff"}, + {file = "black-22.10.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:915ace4ff03fdfff953962fa672d44be269deb2eaf88499a0f8805221bc68c87"}, + {file = "black-22.10.0-cp38-cp38-win_amd64.whl", hash = "sha256:444ebfb4e441254e87bad00c661fe32df9969b2bf224373a448d8aca2132b395"}, + {file = "black-22.10.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:974308c58d057a651d182208a484ce80a26dac0caef2895836a92dd6ebd725e0"}, + {file = "black-22.10.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:72ef3925f30e12a184889aac03d77d031056860ccae8a1e519f6cbb742736383"}, + {file = "black-22.10.0-cp39-cp39-win_amd64.whl", hash = "sha256:432247333090c8c5366e69627ccb363bc58514ae3e63f7fc75c54b1ea80fa7de"}, + {file = "black-22.10.0-py3-none-any.whl", hash = "sha256:c957b2b4ea88587b46cf49d1dc17681c1e672864fd7af32fc1e9664d572b3458"}, + {file = "black-22.10.0.tar.gz", hash = "sha256:f513588da599943e0cde4e32cc9879e825d58720d6557062d1098c5ad80080e1"}, ] certifi = [ - {file = "certifi-2022.6.15-py3-none-any.whl", hash = "sha256:fe86415d55e84719d75f8b69414f6438ac3547d2078ab91b67e779ef69378412"}, - {file = "certifi-2022.6.15.tar.gz", hash = "sha256:84c85a9078b11105f04f3036a9482ae10e4621616db313fe045dd24743a0820d"}, + {file = "certifi-2022.9.24-py3-none-any.whl", hash = "sha256:90c1a32f1d68f940488354e36370f6cca89f0f106db09518524c88d6ed83f382"}, + {file = "certifi-2022.9.24.tar.gz", hash = "sha256:0d9c601124e5a6ba9712dbc60d9c53c21e34f5f641fe83002317394311bdce14"}, ] cffi = [ {file = "cffi-1.15.1-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:a66d3508133af6e8548451b25058d5812812ec3798c886bf38ed24a98216fab2"}, @@ -891,13 +893,17 @@ click = [ {file = "click-8.1.3.tar.gz", hash = "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e"}, ] colorama = [ - {file = "colorama-0.4.5-py2.py3-none-any.whl", hash = "sha256:854bf444933e37f5824ae7bfc1e98d5bce2ebe4160d46b5edf346a89358e99da"}, - {file = "colorama-0.4.5.tar.gz", hash = "sha256:e6c6b4334fc50988a639d9b98aa429a0b57da6e17b9a44f0451f930b6967b7a4"}, + {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, + {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, ] -"discord.py" = [ +discord-py = [ {file = "discord.py-1.6.0-py3-none-any.whl", hash = "sha256:3df148daf6fbcc7ab5b11042368a3cd5f7b730b62f09fb5d3cbceff59bcfbb12"}, {file = "discord.py-1.6.0.tar.gz", hash = "sha256:ba8be99ff1b8c616f7b6dcb700460d0222b29d4c11048e74366954c465fdd05f"}, ] +exceptiongroup = [ + {file = "exceptiongroup-1.0.4-py3-none-any.whl", hash = "sha256:542adf9dea4055530d6e1279602fa5cb11dab2395fa650b8674eaec35fc4a828"}, + {file = "exceptiongroup-1.0.4.tar.gz", hash = "sha256:bd14967b79cd9bdb54d97323216f8fdf533e278df937aa2a90089e7d6e06e5ec"}, +] feedparser = [ {file = "feedparser-6.0.10-py3-none-any.whl", hash = "sha256:79c257d526d13b944e965f6095700587f27388e50ea16fd245babe4dfae7024f"}, {file = "feedparser-6.0.10.tar.gz", hash = "sha256:27da485f4637ce7163cdeab13a80312b93b7d0c1b775bef4a47629a3110bca51"}, @@ -918,8 +924,8 @@ hpack = [ {file = "hpack-3.0.0.tar.gz", hash = "sha256:8eec9c1f4bfae3408a3f30500261f7e6a65912dc138526ea054f9ad98892e9d2"}, ] hstspreload = [ - {file = "hstspreload-2022.9.1-py3-none-any.whl", hash = "sha256:22156f0f1335b46e999e3fd70223e86b33332e449e213e59e25f6a3618acae7d"}, - {file = "hstspreload-2022.9.1.tar.gz", hash = "sha256:890e89c1834ea83f39541fdd02be65b990092d256c5a5e1d74df5ab107ddfdaf"}, + {file = "hstspreload-2022.11.1-py3-none-any.whl", hash = "sha256:ddd7c0e3b34711c1a370e1ec251c1238080af85c04c06ec2392b49a9977564e9"}, + {file = "hstspreload-2022.11.1.tar.gz", hash = "sha256:f259fc5726a52b7c626af5ad060f4b8739c109f375d386339883b88c6e03c01b"}, ] httpcore = [ {file = "httpcore-0.9.1-py3-none-any.whl", hash = "sha256:9850fe97a166a794d7e920590d5ec49a05488884c9fc8b5dba8561effab0c2a0"}, @@ -1079,67 +1085,74 @@ multidict = [ {file = "multidict-6.0.2.tar.gz", hash = "sha256:5ff3bd75f38e4c43f1f470f2df7a4d430b821c4ce22be384e1459cb57d6bb013"}, ] mutagen = [ - {file = "mutagen-1.45.1-py3-none-any.whl", hash = "sha256:9c9f243fcec7f410f138cb12c21c84c64fde4195481a30c9bfb05b5f003adfed"}, - {file = "mutagen-1.45.1.tar.gz", hash = "sha256:6397602efb3c2d7baebd2166ed85731ae1c1d475abca22090b7141ff5034b3e1"}, + {file = "mutagen-1.46.0-py3-none-any.whl", hash = "sha256:8af0728aa2d5c3ee5a727e28d0627966641fddfe804c23eabb5926a4d770aed5"}, + {file = "mutagen-1.46.0.tar.gz", hash = "sha256:6e5f8ba84836b99fe60be5fb27f84be4ad919bbb6b49caa6ae81e70584b55e58"}, ] mypy = [ - {file = "mypy-0.971-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:f2899a3cbd394da157194f913a931edfd4be5f274a88041c9dc2d9cdcb1c315c"}, - {file = "mypy-0.971-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:98e02d56ebe93981c41211c05adb630d1d26c14195d04d95e49cd97dbc046dc5"}, - {file = "mypy-0.971-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:19830b7dba7d5356d3e26e2427a2ec91c994cd92d983142cbd025ebe81d69cf3"}, - {file = "mypy-0.971-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:02ef476f6dcb86e6f502ae39a16b93285fef97e7f1ff22932b657d1ef1f28655"}, - {file = "mypy-0.971-cp310-cp310-win_amd64.whl", hash = "sha256:25c5750ba5609a0c7550b73a33deb314ecfb559c350bb050b655505e8aed4103"}, - {file = "mypy-0.971-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:d3348e7eb2eea2472db611486846742d5d52d1290576de99d59edeb7cd4a42ca"}, - {file = "mypy-0.971-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:3fa7a477b9900be9b7dd4bab30a12759e5abe9586574ceb944bc29cddf8f0417"}, - {file = "mypy-0.971-cp36-cp36m-win_amd64.whl", hash = "sha256:2ad53cf9c3adc43cf3bea0a7d01a2f2e86db9fe7596dfecb4496a5dda63cbb09"}, - {file = "mypy-0.971-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:855048b6feb6dfe09d3353466004490b1872887150c5bb5caad7838b57328cc8"}, - {file = "mypy-0.971-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:23488a14a83bca6e54402c2e6435467a4138785df93ec85aeff64c6170077fb0"}, - {file = "mypy-0.971-cp37-cp37m-win_amd64.whl", hash = "sha256:4b21e5b1a70dfb972490035128f305c39bc4bc253f34e96a4adf9127cf943eb2"}, - {file = "mypy-0.971-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:9796a2ba7b4b538649caa5cecd398d873f4022ed2333ffde58eaf604c4d2cb27"}, - {file = "mypy-0.971-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:5a361d92635ad4ada1b1b2d3630fc2f53f2127d51cf2def9db83cba32e47c856"}, - {file = "mypy-0.971-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:b793b899f7cf563b1e7044a5c97361196b938e92f0a4343a5d27966a53d2ec71"}, - {file = "mypy-0.971-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:d1ea5d12c8e2d266b5fb8c7a5d2e9c0219fedfeb493b7ed60cd350322384ac27"}, - {file = "mypy-0.971-cp38-cp38-win_amd64.whl", hash = "sha256:23c7ff43fff4b0df93a186581885c8512bc50fc4d4910e0f838e35d6bb6b5e58"}, - {file = "mypy-0.971-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:1f7656b69974a6933e987ee8ffb951d836272d6c0f81d727f1d0e2696074d9e6"}, - {file = "mypy-0.971-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:d2022bfadb7a5c2ef410d6a7c9763188afdb7f3533f22a0a32be10d571ee4bbe"}, - {file = "mypy-0.971-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ef943c72a786b0f8d90fd76e9b39ce81fb7171172daf84bf43eaf937e9f220a9"}, - {file = "mypy-0.971-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:d744f72eb39f69312bc6c2abf8ff6656973120e2eb3f3ec4f758ed47e414a4bf"}, - {file = "mypy-0.971-cp39-cp39-win_amd64.whl", hash = "sha256:77a514ea15d3007d33a9e2157b0ba9c267496acf12a7f2b9b9f8446337aac5b0"}, - {file = "mypy-0.971-py3-none-any.whl", hash = "sha256:0d054ef16b071149917085f51f89555a576e2618d5d9dd70bd6eea6410af3ac9"}, - {file = "mypy-0.971.tar.gz", hash = "sha256:40b0f21484238269ae6a57200c807d80debc6459d444c0489a102d7c6a75fa56"}, + {file = "mypy-0.990-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:aaf1be63e0207d7d17be942dcf9a6b641745581fe6c64df9a38deb562a7dbafa"}, + {file = "mypy-0.990-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d555aa7f44cecb7ea3c0ac69d58b1a5afb92caa017285a8e9c4efbf0518b61b4"}, + {file = "mypy-0.990-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8f694d6d09a460b117dccb6857dda269188e3437c880d7b60fa0014fa872d1e9"}, + {file = "mypy-0.990-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:269f0dfb6463b8780333310ff4b5134425157ef0d2b1d614015adaf6d6a7eabd"}, + {file = "mypy-0.990-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:8798c8ed83aa809f053abff08664bdca056038f5a02af3660de00b7290b64c47"}, + {file = "mypy-0.990-cp310-cp310-win_amd64.whl", hash = "sha256:47a9955214615108c3480a500cfda8513a0b1cd3c09a1ed42764ca0dd7b931dd"}, + {file = "mypy-0.990-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:4a8a6c10f4c63fbf6ad6c03eba22c9331b3946a4cec97f008e9ffb4d3b31e8e2"}, + {file = "mypy-0.990-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:cd2dd3730ba894ec2a2082cc703fbf3e95a08479f7be84912e3131fc68809d46"}, + {file = "mypy-0.990-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7da0005e47975287a92b43276e460ac1831af3d23032c34e67d003388a0ce8d0"}, + {file = "mypy-0.990-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:262c543ef24deb10470a3c1c254bb986714e2b6b1a67d66daf836a548a9f316c"}, + {file = "mypy-0.990-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:3ff201a0c6d3ea029d73b1648943387d75aa052491365b101f6edd5570d018ea"}, + {file = "mypy-0.990-cp311-cp311-win_amd64.whl", hash = "sha256:1767830da2d1afa4e62b684647af0ff79b401f004d7fa08bc5b0ce2d45bcd5ec"}, + {file = "mypy-0.990-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:6826d9c4d85bbf6d68cb279b561de6a4d8d778ca8e9ab2d00ee768ab501a9852"}, + {file = "mypy-0.990-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:46897755f944176fbc504178422a5a2875bbf3f7436727374724842c0987b5af"}, + {file = "mypy-0.990-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:0680389c34284287fe00e82fc8bccdea9aff318f7e7d55b90d967a13a9606013"}, + {file = "mypy-0.990-cp37-cp37m-win_amd64.whl", hash = "sha256:b08541a06eed35b543ae1a6b301590eb61826a1eb099417676ddc5a42aa151c5"}, + {file = "mypy-0.990-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:be88d665e76b452c26fb2bdc3d54555c01226fba062b004ede780b190a50f9db"}, + {file = "mypy-0.990-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:9b8f4a8213b1fd4b751e26b59ae0e0c12896568d7e805861035c7a15ed6dc9eb"}, + {file = "mypy-0.990-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:2b6f85c2ad378e3224e017904a051b26660087b3b76490d533b7344f1546d3ff"}, + {file = "mypy-0.990-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1ee5f99817ee70254e7eb5cf97c1b11dda29c6893d846c8b07bce449184e9466"}, + {file = "mypy-0.990-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:49082382f571c3186ce9ea0bd627cb1345d4da8d44a8377870f4442401f0a706"}, + {file = "mypy-0.990-cp38-cp38-win_amd64.whl", hash = "sha256:aba38e3dd66bdbafbbfe9c6e79637841928ea4c79b32e334099463c17b0d90ef"}, + {file = "mypy-0.990-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:9d851c09b981a65d9d283a8ccb5b1d0b698e580493416a10942ef1a04b19fd37"}, + {file = "mypy-0.990-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:d847dd23540e2912d9667602271e5ebf25e5788e7da46da5ffd98e7872616e8e"}, + {file = "mypy-0.990-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:cc6019808580565040cd2a561b593d7c3c646badd7e580e07d875eb1bf35c695"}, + {file = "mypy-0.990-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2a3150d409609a775c8cb65dbe305c4edd7fe576c22ea79d77d1454acd9aeda8"}, + {file = "mypy-0.990-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:3227f14fe943524f5794679156488f18bf8d34bfecd4623cf76bc55958d229c5"}, + {file = "mypy-0.990-cp39-cp39-win_amd64.whl", hash = "sha256:c76c769c46a1e6062a84837badcb2a7b0cdb153d68601a61f60739c37d41cc74"}, + {file = "mypy-0.990-py3-none-any.whl", hash = "sha256:8f1940325a8ed460ba03d19ab83742260fa9534804c317224e5d4e5aa588e2d6"}, + {file = "mypy-0.990.tar.gz", hash = "sha256:72382cb609142dba3f04140d016c94b4092bc7b4d98ca718740dc989e5271b8d"}, ] mypy-extensions = [ {file = "mypy_extensions-0.4.3-py2.py3-none-any.whl", hash = "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d"}, {file = "mypy_extensions-0.4.3.tar.gz", hash = "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"}, ] numpy = [ - {file = "numpy-1.23.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e603ca1fb47b913942f3e660a15e55a9ebca906857edfea476ae5f0fe9b457d5"}, - {file = "numpy-1.23.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:633679a472934b1c20a12ed0c9a6c9eb167fbb4cb89031939bfd03dd9dbc62b8"}, - {file = "numpy-1.23.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:17e5226674f6ea79e14e3b91bfbc153fdf3ac13f5cc54ee7bc8fdbe820a32da0"}, - {file = "numpy-1.23.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bdc02c0235b261925102b1bd586579b7158e9d0d07ecb61148a1799214a4afd5"}, - {file = "numpy-1.23.2-cp310-cp310-win32.whl", hash = "sha256:df28dda02c9328e122661f399f7655cdcbcf22ea42daa3650a26bce08a187450"}, - {file = "numpy-1.23.2-cp310-cp310-win_amd64.whl", hash = "sha256:8ebf7e194b89bc66b78475bd3624d92980fca4e5bb86dda08d677d786fefc414"}, - {file = "numpy-1.23.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:dc76bca1ca98f4b122114435f83f1fcf3c0fe48e4e6f660e07996abf2f53903c"}, - {file = "numpy-1.23.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ecfdd68d334a6b97472ed032b5b37a30d8217c097acfff15e8452c710e775524"}, - {file = "numpy-1.23.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5593f67e66dea4e237f5af998d31a43e447786b2154ba1ad833676c788f37cde"}, - {file = "numpy-1.23.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ac987b35df8c2a2eab495ee206658117e9ce867acf3ccb376a19e83070e69418"}, - {file = "numpy-1.23.2-cp311-cp311-win32.whl", hash = "sha256:d98addfd3c8728ee8b2c49126f3c44c703e2b005d4a95998e2167af176a9e722"}, - {file = "numpy-1.23.2-cp311-cp311-win_amd64.whl", hash = "sha256:8ecb818231afe5f0f568c81f12ce50f2b828ff2b27487520d85eb44c71313b9e"}, - {file = "numpy-1.23.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:909c56c4d4341ec8315291a105169d8aae732cfb4c250fbc375a1efb7a844f8f"}, - {file = "numpy-1.23.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:8247f01c4721479e482cc2f9f7d973f3f47810cbc8c65e38fd1bbd3141cc9842"}, - {file = "numpy-1.23.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b8b97a8a87cadcd3f94659b4ef6ec056261fa1e1c3317f4193ac231d4df70215"}, - {file = "numpy-1.23.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bd5b7ccae24e3d8501ee5563e82febc1771e73bd268eef82a1e8d2b4d556ae66"}, - {file = "numpy-1.23.2-cp38-cp38-win32.whl", hash = "sha256:9b83d48e464f393d46e8dd8171687394d39bc5abfe2978896b77dc2604e8635d"}, - {file = "numpy-1.23.2-cp38-cp38-win_amd64.whl", hash = "sha256:dec198619b7dbd6db58603cd256e092bcadef22a796f778bf87f8592b468441d"}, - {file = "numpy-1.23.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:4f41f5bf20d9a521f8cab3a34557cd77b6f205ab2116651f12959714494268b0"}, - {file = "numpy-1.23.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:806cc25d5c43e240db709875e947076b2826f47c2c340a5a2f36da5bb10c58d6"}, - {file = "numpy-1.23.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8f9d84a24889ebb4c641a9b99e54adb8cab50972f0166a3abc14c3b93163f074"}, - {file = "numpy-1.23.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c403c81bb8ffb1c993d0165a11493fd4bf1353d258f6997b3ee288b0a48fce77"}, - {file = "numpy-1.23.2-cp39-cp39-win32.whl", hash = "sha256:cf8c6aed12a935abf2e290860af8e77b26a042eb7f2582ff83dc7ed5f963340c"}, - {file = "numpy-1.23.2-cp39-cp39-win_amd64.whl", hash = "sha256:5e28cd64624dc2354a349152599e55308eb6ca95a13ce6a7d5679ebff2962913"}, - {file = "numpy-1.23.2-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:806970e69106556d1dd200e26647e9bee5e2b3f1814f9da104a943e8d548ca38"}, - {file = "numpy-1.23.2-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2bd879d3ca4b6f39b7770829f73278b7c5e248c91d538aab1e506c628353e47f"}, - {file = "numpy-1.23.2-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:be6b350dfbc7f708d9d853663772a9310783ea58f6035eec649fb9c4371b5389"}, - {file = "numpy-1.23.2.tar.gz", hash = "sha256:b78d00e48261fbbd04aa0d7427cf78d18401ee0abd89c7559bbf422e5b1c7d01"}, + {file = "numpy-1.23.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:95d79ada05005f6f4f337d3bb9de8a7774f259341c70bc88047a1f7b96a4bcb2"}, + {file = "numpy-1.23.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:926db372bc4ac1edf81cfb6c59e2a881606b409ddc0d0920b988174b2e2a767f"}, + {file = "numpy-1.23.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c237129f0e732885c9a6076a537e974160482eab8f10db6292e92154d4c67d71"}, + {file = "numpy-1.23.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a8365b942f9c1a7d0f0dc974747d99dd0a0cdfc5949a33119caf05cb314682d3"}, + {file = "numpy-1.23.4-cp310-cp310-win32.whl", hash = "sha256:2341f4ab6dba0834b685cce16dad5f9b6606ea8a00e6da154f5dbded70fdc4dd"}, + {file = "numpy-1.23.4-cp310-cp310-win_amd64.whl", hash = "sha256:d331afac87c92373826af83d2b2b435f57b17a5c74e6268b79355b970626e329"}, + {file = "numpy-1.23.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:488a66cb667359534bc70028d653ba1cf307bae88eab5929cd707c761ff037db"}, + {file = "numpy-1.23.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ce03305dd694c4873b9429274fd41fc7eb4e0e4dea07e0af97a933b079a5814f"}, + {file = "numpy-1.23.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8981d9b5619569899666170c7c9748920f4a5005bf79c72c07d08c8a035757b0"}, + {file = "numpy-1.23.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7a70a7d3ce4c0e9284e92285cba91a4a3f5214d87ee0e95928f3614a256a1488"}, + {file = "numpy-1.23.4-cp311-cp311-win32.whl", hash = "sha256:5e13030f8793e9ee42f9c7d5777465a560eb78fa7e11b1c053427f2ccab90c79"}, + {file = "numpy-1.23.4-cp311-cp311-win_amd64.whl", hash = "sha256:7607b598217745cc40f751da38ffd03512d33ec06f3523fb0b5f82e09f6f676d"}, + {file = "numpy-1.23.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:7ab46e4e7ec63c8a5e6dbf5c1b9e1c92ba23a7ebecc86c336cb7bf3bd2fb10e5"}, + {file = "numpy-1.23.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:a8aae2fb3180940011b4862b2dd3756616841c53db9734b27bb93813cd79fce6"}, + {file = "numpy-1.23.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8c053d7557a8f022ec823196d242464b6955a7e7e5015b719e76003f63f82d0f"}, + {file = "numpy-1.23.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a0882323e0ca4245eb0a3d0a74f88ce581cc33aedcfa396e415e5bba7bf05f68"}, + {file = "numpy-1.23.4-cp38-cp38-win32.whl", hash = "sha256:dada341ebb79619fe00a291185bba370c9803b1e1d7051610e01ed809ef3a4ba"}, + {file = "numpy-1.23.4-cp38-cp38-win_amd64.whl", hash = "sha256:0fe563fc8ed9dc4474cbf70742673fc4391d70f4363f917599a7fa99f042d5a8"}, + {file = "numpy-1.23.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c67b833dbccefe97cdd3f52798d430b9d3430396af7cdb2a0c32954c3ef73894"}, + {file = "numpy-1.23.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f76025acc8e2114bb664294a07ede0727aa75d63a06d2fae96bf29a81747e4a7"}, + {file = "numpy-1.23.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:12ac457b63ec8ded85d85c1e17d85efd3c2b0967ca39560b307a35a6703a4735"}, + {file = "numpy-1.23.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:95de7dc7dc47a312f6feddd3da2500826defdccbc41608d0031276a24181a2c0"}, + {file = "numpy-1.23.4-cp39-cp39-win32.whl", hash = "sha256:f2f390aa4da44454db40a1f0201401f9036e8d578a25f01a6e237cea238337ef"}, + {file = "numpy-1.23.4-cp39-cp39-win_amd64.whl", hash = "sha256:f260da502d7441a45695199b4e7fd8ca87db659ba1c78f2bbf31f934fe76ae0e"}, + {file = "numpy-1.23.4-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:61be02e3bf810b60ab74e81d6d0d36246dbfb644a462458bb53b595791251911"}, + {file = "numpy-1.23.4-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:296d17aed51161dbad3c67ed6d164e51fcd18dbcd5dd4f9d0a9c6055dce30810"}, + {file = "numpy-1.23.4-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:4d52914c88b4930dafb6c48ba5115a96cbab40f45740239d9f4159c4ba779962"}, + {file = "numpy-1.23.4.tar.gz", hash = "sha256:ed2cc92af0efad20198638c69bb0fc2870a58dabfba6eb722c933b48556c686c"}, ] opencv-python = [ {file = "opencv-python-4.6.0.66.tar.gz", hash = "sha256:c5bfae41ad4031e66bb10ec4a0a2ffd3e514d092652781e8b1ac98d1b59f1158"}, @@ -1155,10 +1168,10 @@ packaging = [ {file = "packaging-21.3.tar.gz", hash = "sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb"}, ] pathspec = [ - {file = "pathspec-0.10.1-py3-none-any.whl", hash = "sha256:46846318467efc4556ccfd27816e004270a9eeeeb4d062ce5e6fc7a87c573f93"}, - {file = "pathspec-0.10.1.tar.gz", hash = "sha256:7ace6161b621d31e7902eb6b5ae148d12cfd23f4a249b9ffb6b9fee12084323d"}, + {file = "pathspec-0.10.2-py3-none-any.whl", hash = "sha256:88c2606f2c1e818b978540f73ecc908e13999c6c3a383daf3705652ae79807a5"}, + {file = "pathspec-0.10.2.tar.gz", hash = "sha256:8f6bf73e5758fd365ef5d58ce09ac7c27d2833a8d7da51712eac6e27e35141b0"}, ] -Pillow = [ +pillow = [ {file = "Pillow-8.4.0-cp310-cp310-macosx_10_10_universal2.whl", hash = "sha256:81f8d5c81e483a9442d72d182e1fb6dcb9723f289a57e8030811bac9ea3fef8d"}, {file = "Pillow-8.4.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:3f97cfb1e5a392d75dd8b9fd274d205404729923840ca94ca45a0af57e13dbe6"}, {file = "Pillow-8.4.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eb9fc393f3c61f9054e1ed26e6fe912c7321af2f41ff49d3f83d05bacf22cc78"}, @@ -1202,17 +1215,13 @@ Pillow = [ {file = "Pillow-8.4.0.tar.gz", hash = "sha256:b8e2f83c56e141920c39464b852de3719dfbfb6e3c99a2d8da0edf4fb33176ed"}, ] platformdirs = [ - {file = "platformdirs-2.5.2-py3-none-any.whl", hash = "sha256:027d8e83a2d7de06bbac4e5ef7e023c02b863d7ea5d079477e722bb41ab25788"}, - {file = "platformdirs-2.5.2.tar.gz", hash = "sha256:58c8abb07dcb441e6ee4b11d8df0ac856038f944ab98b7be6b27b2a3c7feef19"}, + {file = "platformdirs-2.5.4-py3-none-any.whl", hash = "sha256:af0276409f9a02373d540bf8480021a048711d572745aef4b7842dad245eba10"}, + {file = "platformdirs-2.5.4.tar.gz", hash = "sha256:1006647646d80f16130f052404c6b901e80ee4ed6bef6792e1f238a8969106f7"}, ] pluggy = [ {file = "pluggy-1.0.0-py2.py3-none-any.whl", hash = "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"}, {file = "pluggy-1.0.0.tar.gz", hash = "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159"}, ] -py = [ - {file = "py-1.11.0-py2.py3-none-any.whl", hash = "sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378"}, - {file = "py-1.11.0.tar.gz", hash = "sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719"}, -] pycparser = [ {file = "pycparser-2.21-py2.py3-none-any.whl", hash = "sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9"}, {file = "pycparser-2.21.tar.gz", hash = "sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206"}, @@ -1249,7 +1258,7 @@ pycryptodomex = [ {file = "pycryptodomex-3.15.0-pp36-pypy36_pp73-win32.whl", hash = "sha256:35a8f7afe1867118330e2e0e0bf759c409e28557fb1fc2fbb1c6c937297dbe9a"}, {file = "pycryptodomex-3.15.0.tar.gz", hash = "sha256:7341f1bb2dadb0d1a0047f34c3a58208a92423cdbd3244d998e4b28df5eac0ed"}, ] -PyNaCl = [ +pynacl = [ {file = "PyNaCl-1.4.0-cp27-cp27m-macosx_10_10_x86_64.whl", hash = "sha256:ea6841bc3a76fa4942ce00f3bda7d436fda21e2d91602b9e21b7ca9ecab8f3ff"}, {file = "PyNaCl-1.4.0-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:d452a6746f0a7e11121e64625109bc4468fc3100452817001dbe018bb8b08514"}, {file = "PyNaCl-1.4.0-cp27-cp27m-win32.whl", hash = "sha256:2fe0fc5a2480361dcaf4e6e7cea00e078fcda07ba45f811b167e3f99e8cff574"}, @@ -1274,12 +1283,12 @@ pyparsing = [ {file = "pyparsing-3.0.9.tar.gz", hash = "sha256:2b020ecf7d21b687f219b71ecad3631f644a47f01403fa1d1036b0c6416d70fb"}, ] pytest = [ - {file = "pytest-7.1.3-py3-none-any.whl", hash = "sha256:1377bda3466d70b55e3f5cecfa55bb7cfcf219c7964629b967c37cf0bda818b7"}, - {file = "pytest-7.1.3.tar.gz", hash = "sha256:4f365fec2dff9c1162f834d9f18af1ba13062db0c708bf7b946f8a5c76180c39"}, + {file = "pytest-7.2.0-py3-none-any.whl", hash = "sha256:892f933d339f068883b6fd5a459f03d85bfcb355e4981e146d2c7616c21fef71"}, + {file = "pytest-7.2.0.tar.gz", hash = "sha256:c4014eb40e10f11f355ad4e3c2fb2c6c6d1919c73f3b5a433de4708202cade59"}, ] pytz = [ - {file = "pytz-2022.2.1-py2.py3-none-any.whl", hash = "sha256:220f481bdafa09c3955dfbdddb7b57780e9a94f5127e35456a48589b9e0c0197"}, - {file = "pytz-2022.2.1.tar.gz", hash = "sha256:cea221417204f2d1a2aa03ddae3e867921971d0d76f14d87abb4414415bbdcf5"}, + {file = "pytz-2022.6-py2.py3-none-any.whl", hash = "sha256:222439474e9c98fced559f1709d89e6c9cbf8d79c794ff3eb9f8800064291427"}, + {file = "pytz-2022.6.tar.gz", hash = "sha256:e89512406b793ca39f5971bc999cc538ce125c0e51c27941bef4568b460095e2"}, ] regex = [ {file = "regex-2021.11.10-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:9345b6f7ee578bad8e475129ed40123d265464c4cfead6c261fd60fc9de00bcf"}, @@ -1393,32 +1402,32 @@ tomli = [ {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, ] types-beautifulsoup4 = [ - {file = "types-beautifulsoup4-4.11.5.tar.gz", hash = "sha256:645963117b0f03f4a44bda36cf3da50cc0e25001e4d19c044d1e323a37c69d73"}, - {file = "types_beautifulsoup4-4.11.5-py3-none-any.whl", hash = "sha256:4b97fce9049e5367ddf45333c8c7224e57d71a3f93162c714be52bf1aa538f0a"}, + {file = "types-beautifulsoup4-4.11.6.1.tar.gz", hash = "sha256:d46be8f409ddccb6daaa9d118484185e70bcf552085c39c6d05b157cd1462e04"}, + {file = "types_beautifulsoup4-4.11.6.1-py3-none-any.whl", hash = "sha256:c1f803367a2b07ad4fdac40ddbea557010dc4ddd1ee92d801f317eb02e2e3c72"}, ] types-pytz = [ - {file = "types-pytz-2022.2.1.0.tar.gz", hash = "sha256:47cfb19c52b9f75896440541db392fd312a35b279c6307a531db71152ea63e2b"}, - {file = "types_pytz-2022.2.1.0-py3-none-any.whl", hash = "sha256:50ead2254b524a3d4153bc65d00289b66898060d2938e586170dce918dbaf3b3"}, + {file = "types-pytz-2022.6.0.1.tar.gz", hash = "sha256:d078196374d1277e9f9984d49373ea043cf2c64d5d5c491fbc86c258557bd46f"}, + {file = "types_pytz-2022.6.0.1-py3-none-any.whl", hash = "sha256:bea605ce5d5a5d52a8e1afd7656c9b42476e18a0f888de6be91587355313ddf4"}, ] types-regex = [ - {file = "types-regex-2022.8.17.0.tar.gz", hash = "sha256:6c3c2cac6486fba44dd3a8c6fbf780768b8e605455dd80364eea4f647179ec06"}, - {file = "types_regex-2022.8.17.0-py3-none-any.whl", hash = "sha256:73af11d8a146b1e9fbfd0f3eebfa5640ed1786f0d1b1fc8ff72e8882cf0f4133"}, + {file = "types-regex-2022.10.31.0.tar.gz", hash = "sha256:4e5827f49d65da579d6042cf1e5972437d9ae6b59b4b275030a6d983e361b211"}, + {file = "types_regex-2022.10.31.0-py3-none-any.whl", hash = "sha256:1f81ec831cf7aca7ec697f9e895b0421cc634f9df98a7dccba0488681a80b9c7"}, ] types-requests = [ - {file = "types-requests-2.28.9.tar.gz", hash = "sha256:feaf581bd580497a47fe845d506fa3b91b484cf706ff27774e87659837de9962"}, - {file = "types_requests-2.28.9-py3-none-any.whl", hash = "sha256:86cb66d3de2f53eac5c09adc42cf6547eefbd0c7e1210beca1ee751c35d96083"}, + {file = "types-requests-2.28.11.5.tar.gz", hash = "sha256:a7df37cc6fb6187a84097da951f8e21d335448aa2501a6b0a39cbd1d7ca9ee2a"}, + {file = "types_requests-2.28.11.5-py3-none-any.whl", hash = "sha256:091d4a5a33c1b4f20d8b1b952aa8fa27a6e767c44c3cf65e56580df0b05fd8a9"}, ] types-tabulate = [ {file = "types-tabulate-0.8.11.tar.gz", hash = "sha256:17a5fa3b5ca453815778fc9865e8ecd0118b07b2b9faff3e2b06fe448174dd5e"}, {file = "types_tabulate-0.8.11-py3-none-any.whl", hash = "sha256:af811268241e8fb87b63c052c87d1e329898a93191309d5d42111372232b2e0e"}, ] types-urllib3 = [ - {file = "types-urllib3-1.26.23.tar.gz", hash = "sha256:b78e819f0e350221d0689a5666162e467ba3910737bafda14b5c2c85e9bb1e56"}, - {file = "types_urllib3-1.26.23-py3-none-any.whl", hash = "sha256:333e675b188a1c1fd980b4b352f9e40572413a4c1ac689c23cd546e96310070a"}, + {file = "types-urllib3-1.26.25.4.tar.gz", hash = "sha256:eec5556428eec862b1ac578fb69aab3877995a99ffec9e5a12cf7fbd0cc9daee"}, + {file = "types_urllib3-1.26.25.4-py3-none-any.whl", hash = "sha256:ed6b9e8a8be488796f72306889a06a3fc3cb1aa99af02ab8afb50144d7317e49"}, ] typing-extensions = [ - {file = "typing_extensions-4.3.0-py3-none-any.whl", hash = "sha256:25642c956049920a5aa49edcdd6ab1e06d7e5d467fc00e0506c44ac86fbfca02"}, - {file = "typing_extensions-4.3.0.tar.gz", hash = "sha256:e6d2677a32f47fc7eb2795db1dd15c1f34eff616bcaf2cfb5e997f854fa1c4a6"}, + {file = "typing_extensions-4.4.0-py3-none-any.whl", hash = "sha256:16fa4864408f655d35ec496218b85f79b3437c829e93320c7c9215ccfd92489e"}, + {file = "typing_extensions-4.4.0.tar.gz", hash = "sha256:1511434bb92bf8dd198c12b1cc812e800d4181cfcb867674e0f8279cc93087aa"}, ] urllib3 = [ {file = "urllib3-1.26.12-py2.py3-none-any.whl", hash = "sha256:b930dd878d5a8afb066a637fbb35144fe7901e3b209d1cd4f524bd0e9deee997"}, @@ -1443,54 +1452,75 @@ uvloop = [ {file = "uvloop-0.16.0.tar.gz", hash = "sha256:f74bc20c7b67d1c27c72601c78cf95be99d5c2cdd4514502b4f3eb0933ff1228"}, ] websockets = [ - {file = "websockets-10.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:661f641b44ed315556a2fa630239adfd77bd1b11cb0b9d96ed8ad90b0b1e4978"}, - {file = "websockets-10.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b529fdfa881b69fe563dbd98acce84f3e5a67df13de415e143ef053ff006d500"}, - {file = "websockets-10.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f351c7d7d92f67c0609329ab2735eee0426a03022771b00102816a72715bb00b"}, - {file = "websockets-10.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:379e03422178436af4f3abe0aa8f401aa77ae2487843738542a75faf44a31f0c"}, - {file = "websockets-10.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:e904c0381c014b914136c492c8fa711ca4cced4e9b3d110e5e7d436d0fc289e8"}, - {file = "websockets-10.3-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:e7e6f2d6fd48422071cc8a6f8542016f350b79cc782752de531577d35e9bd677"}, - {file = "websockets-10.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:b9c77f0d1436ea4b4dc089ed8335fa141e6a251a92f75f675056dac4ab47a71e"}, - {file = "websockets-10.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e6fa05a680e35d0fcc1470cb070b10e6fe247af54768f488ed93542e71339d6f"}, - {file = "websockets-10.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:2f94fa3ae454a63ea3a19f73b95deeebc9f02ba2d5617ca16f0bbdae375cda47"}, - {file = "websockets-10.3-cp310-cp310-win32.whl", hash = "sha256:6ed1d6f791eabfd9808afea1e068f5e59418e55721db8b7f3bfc39dc831c42ae"}, - {file = "websockets-10.3-cp310-cp310-win_amd64.whl", hash = "sha256:347974105bbd4ea068106ec65e8e8ebd86f28c19e529d115d89bd8cc5cda3079"}, - {file = "websockets-10.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:fab7c640815812ed5f10fbee7abbf58788d602046b7bb3af9b1ac753a6d5e916"}, - {file = "websockets-10.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:994cdb1942a7a4c2e10098d9162948c9e7b235df755de91ca33f6e0481366fdb"}, - {file = "websockets-10.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:aad5e300ab32036eb3fdc350ad30877210e2f51bceaca83fb7fef4d2b6c72b79"}, - {file = "websockets-10.3-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:e49ea4c1a9543d2bd8a747ff24411509c29e4bdcde05b5b0895e2120cb1a761d"}, - {file = "websockets-10.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:6ea6b300a6bdd782e49922d690e11c3669828fe36fc2471408c58b93b5535a98"}, - {file = "websockets-10.3-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:ef5ce841e102278c1c2e98f043db99d6755b1c58bde475516aef3a008ed7f28e"}, - {file = "websockets-10.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d1655a6fc7aecd333b079d00fb3c8132d18988e47f19740c69303bf02e9883c6"}, - {file = "websockets-10.3-cp37-cp37m-win32.whl", hash = "sha256:83e5ca0d5b743cde3d29fda74ccab37bdd0911f25bd4cdf09ff8b51b7b4f2fa1"}, - {file = "websockets-10.3-cp37-cp37m-win_amd64.whl", hash = "sha256:da4377904a3379f0c1b75a965fff23b28315bcd516d27f99a803720dfebd94d4"}, - {file = "websockets-10.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:a1e15b230c3613e8ea82c9fc6941b2093e8eb939dd794c02754d33980ba81e36"}, - {file = "websockets-10.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:31564a67c3e4005f27815634343df688b25705cccb22bc1db621c781ddc64c69"}, - {file = "websockets-10.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:c8d1d14aa0f600b5be363077b621b1b4d1eb3fbf90af83f9281cda668e6ff7fd"}, - {file = "websockets-10.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8fbd7d77f8aba46d43245e86dd91a8970eac4fb74c473f8e30e9c07581f852b2"}, - {file = "websockets-10.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:210aad7fdd381c52e58777560860c7e6110b6174488ef1d4b681c08b68bf7f8c"}, - {file = "websockets-10.3-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:6075fd24df23133c1b078e08a9b04a3bc40b31a8def4ee0b9f2c8865acce913e"}, - {file = "websockets-10.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:7f6d96fdb0975044fdd7953b35d003b03f9e2bcf85f2d2cf86285ece53e9f991"}, - {file = "websockets-10.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:c7250848ce69559756ad0086a37b82c986cd33c2d344ab87fea596c5ac6d9442"}, - {file = "websockets-10.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:28dd20b938a57c3124028680dc1600c197294da5db4292c76a0b48efb3ed7f76"}, - {file = "websockets-10.3-cp38-cp38-win32.whl", hash = "sha256:54c000abeaff6d8771a4e2cef40900919908ea7b6b6a30eae72752607c6db559"}, - {file = "websockets-10.3-cp38-cp38-win_amd64.whl", hash = "sha256:7ab36e17af592eec5747c68ef2722a74c1a4a70f3772bc661079baf4ae30e40d"}, - {file = "websockets-10.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:a141de3d5a92188234afa61653ed0bbd2dde46ad47b15c3042ffb89548e77094"}, - {file = "websockets-10.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:97bc9d41e69a7521a358f9b8e44871f6cdeb42af31815c17aed36372d4eec667"}, - {file = "websockets-10.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:d6353ba89cfc657a3f5beabb3b69be226adbb5c6c7a66398e17809b0ce3c4731"}, - {file = "websockets-10.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ec2b0ab7edc8cd4b0eb428b38ed89079bdc20c6bdb5f889d353011038caac2f9"}, - {file = "websockets-10.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:85506b3328a9e083cc0a0fb3ba27e33c8db78341b3eb12eb72e8afd166c36680"}, - {file = "websockets-10.3-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:8af75085b4bc0b5c40c4a3c0e113fa95e84c60f4ed6786cbb675aeb1ee128247"}, - {file = "websockets-10.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:07cdc0a5b2549bcfbadb585ad8471ebdc7bdf91e32e34ae3889001c1c106a6af"}, - {file = "websockets-10.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:5b936bf552e4f6357f5727579072ff1e1324717902127ffe60c92d29b67b7be3"}, - {file = "websockets-10.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:e4e08305bfd76ba8edab08dcc6496f40674f44eb9d5e23153efa0a35750337e8"}, - {file = "websockets-10.3-cp39-cp39-win32.whl", hash = "sha256:bb621ec2dbbbe8df78a27dbd9dd7919f9b7d32a73fafcb4d9252fc4637343582"}, - {file = "websockets-10.3-cp39-cp39-win_amd64.whl", hash = "sha256:51695d3b199cd03098ae5b42833006a0f43dc5418d3102972addc593a783bc02"}, - {file = "websockets-10.3-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:907e8247480f287aa9bbc9391bd6de23c906d48af54c8c421df84655eef66af7"}, - {file = "websockets-10.3-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8b1359aba0ff810d5830d5ab8e2c4a02bebf98a60aa0124fb29aa78cfdb8031f"}, - {file = "websockets-10.3-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:93d5ea0b5da8d66d868b32c614d2b52d14304444e39e13a59566d4acb8d6e2e4"}, - {file = "websockets-10.3-pp37-pypy37_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:7934e055fd5cd9dee60f11d16c8d79c4567315824bacb1246d0208a47eca9755"}, - {file = "websockets-10.3-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:3eda1cb7e9da1b22588cefff09f0951771d6ee9fa8dbe66f5ae04cc5f26b2b55"}, - {file = "websockets-10.3.tar.gz", hash = "sha256:fc06cc8073c8e87072138ba1e431300e2d408f054b27047d047b549455066ff4"}, + {file = "websockets-10.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d58804e996d7d2307173d56c297cf7bc132c52df27a3efaac5e8d43e36c21c48"}, + {file = "websockets-10.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:bc0b82d728fe21a0d03e65f81980abbbcb13b5387f733a1a870672c5be26edab"}, + {file = "websockets-10.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ba089c499e1f4155d2a3c2a05d2878a3428cf321c848f2b5a45ce55f0d7d310c"}, + {file = "websockets-10.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:33d69ca7612f0ddff3316b0c7b33ca180d464ecac2d115805c044bf0a3b0d032"}, + {file = "websockets-10.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:62e627f6b6d4aed919a2052efc408da7a545c606268d5ab5bfab4432734b82b4"}, + {file = "websockets-10.4-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:38ea7b82bfcae927eeffc55d2ffa31665dc7fec7b8dc654506b8e5a518eb4d50"}, + {file = "websockets-10.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:e0cb5cc6ece6ffa75baccfd5c02cffe776f3f5c8bf486811f9d3ea3453676ce8"}, + {file = "websockets-10.4-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:ae5e95cfb53ab1da62185e23b3130e11d64431179debac6dc3c6acf08760e9b1"}, + {file = "websockets-10.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:7c584f366f46ba667cfa66020344886cf47088e79c9b9d39c84ce9ea98aaa331"}, + {file = "websockets-10.4-cp310-cp310-win32.whl", hash = "sha256:b029fb2032ae4724d8ae8d4f6b363f2cc39e4c7b12454df8df7f0f563ed3e61a"}, + {file = "websockets-10.4-cp310-cp310-win_amd64.whl", hash = "sha256:8dc96f64ae43dde92530775e9cb169979f414dcf5cff670455d81a6823b42089"}, + {file = "websockets-10.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:47a2964021f2110116cc1125b3e6d87ab5ad16dea161949e7244ec583b905bb4"}, + {file = "websockets-10.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:e789376b52c295c4946403bd0efecf27ab98f05319df4583d3c48e43c7342c2f"}, + {file = "websockets-10.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7d3f0b61c45c3fa9a349cf484962c559a8a1d80dae6977276df8fd1fa5e3cb8c"}, + {file = "websockets-10.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f55b5905705725af31ccef50e55391621532cd64fbf0bc6f4bac935f0fccec46"}, + {file = "websockets-10.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:00c870522cdb69cd625b93f002961ffb0c095394f06ba8c48f17eef7c1541f96"}, + {file = "websockets-10.4-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f38706e0b15d3c20ef6259fd4bc1700cd133b06c3c1bb108ffe3f8947be15fa"}, + {file = "websockets-10.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:f2c38d588887a609191d30e902df2a32711f708abfd85d318ca9b367258cfd0c"}, + {file = "websockets-10.4-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:fe10ddc59b304cb19a1bdf5bd0a7719cbbc9fbdd57ac80ed436b709fcf889106"}, + {file = "websockets-10.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:90fcf8929836d4a0e964d799a58823547df5a5e9afa83081761630553be731f9"}, + {file = "websockets-10.4-cp311-cp311-win32.whl", hash = "sha256:b9968694c5f467bf67ef97ae7ad4d56d14be2751000c1207d31bf3bb8860bae8"}, + {file = "websockets-10.4-cp311-cp311-win_amd64.whl", hash = "sha256:a7a240d7a74bf8d5cb3bfe6be7f21697a28ec4b1a437607bae08ac7acf5b4882"}, + {file = "websockets-10.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:74de2b894b47f1d21cbd0b37a5e2b2392ad95d17ae983e64727e18eb281fe7cb"}, + {file = "websockets-10.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e3a686ecb4aa0d64ae60c9c9f1a7d5d46cab9bfb5d91a2d303d00e2cd4c4c5cc"}, + {file = "websockets-10.4-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b0d15c968ea7a65211e084f523151dbf8ae44634de03c801b8bd070b74e85033"}, + {file = "websockets-10.4-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:00213676a2e46b6ebf6045bc11d0f529d9120baa6f58d122b4021ad92adabd41"}, + {file = "websockets-10.4-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:e23173580d740bf8822fd0379e4bf30aa1d5a92a4f252d34e893070c081050df"}, + {file = "websockets-10.4-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:dd500e0a5e11969cdd3320935ca2ff1e936f2358f9c2e61f100a1660933320ea"}, + {file = "websockets-10.4-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:4239b6027e3d66a89446908ff3027d2737afc1a375f8fd3eea630a4842ec9a0c"}, + {file = "websockets-10.4-cp37-cp37m-win32.whl", hash = "sha256:8a5cc00546e0a701da4639aa0bbcb0ae2bb678c87f46da01ac2d789e1f2d2038"}, + {file = "websockets-10.4-cp37-cp37m-win_amd64.whl", hash = "sha256:a9f9a735deaf9a0cadc2d8c50d1a5bcdbae8b6e539c6e08237bc4082d7c13f28"}, + {file = "websockets-10.4-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5c1289596042fad2cdceb05e1ebf7aadf9995c928e0da2b7a4e99494953b1b94"}, + {file = "websockets-10.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0cff816f51fb33c26d6e2b16b5c7d48eaa31dae5488ace6aae468b361f422b63"}, + {file = "websockets-10.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:dd9becd5fe29773d140d68d607d66a38f60e31b86df75332703757ee645b6faf"}, + {file = "websockets-10.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45ec8e75b7dbc9539cbfafa570742fe4f676eb8b0d3694b67dabe2f2ceed8aa6"}, + {file = "websockets-10.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4f72e5cd0f18f262f5da20efa9e241699e0cf3a766317a17392550c9ad7b37d8"}, + {file = "websockets-10.4-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:185929b4808b36a79c65b7865783b87b6841e852ef5407a2fb0c03381092fa3b"}, + {file = "websockets-10.4-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:7d27a7e34c313b3a7f91adcd05134315002aaf8540d7b4f90336beafaea6217c"}, + {file = "websockets-10.4-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:884be66c76a444c59f801ac13f40c76f176f1bfa815ef5b8ed44321e74f1600b"}, + {file = "websockets-10.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:931c039af54fc195fe6ad536fde4b0de04da9d5916e78e55405436348cfb0e56"}, + {file = "websockets-10.4-cp38-cp38-win32.whl", hash = "sha256:db3c336f9eda2532ec0fd8ea49fef7a8df8f6c804cdf4f39e5c5c0d4a4ad9a7a"}, + {file = "websockets-10.4-cp38-cp38-win_amd64.whl", hash = "sha256:48c08473563323f9c9debac781ecf66f94ad5a3680a38fe84dee5388cf5acaf6"}, + {file = "websockets-10.4-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:40e826de3085721dabc7cf9bfd41682dadc02286d8cf149b3ad05bff89311e4f"}, + {file = "websockets-10.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:56029457f219ade1f2fc12a6504ea61e14ee227a815531f9738e41203a429112"}, + {file = "websockets-10.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f5fc088b7a32f244c519a048c170f14cf2251b849ef0e20cbbb0fdf0fdaf556f"}, + {file = "websockets-10.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2fc8709c00704194213d45e455adc106ff9e87658297f72d544220e32029cd3d"}, + {file = "websockets-10.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0154f7691e4fe6c2b2bc275b5701e8b158dae92a1ab229e2b940efe11905dff4"}, + {file = "websockets-10.4-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4c6d2264f485f0b53adf22697ac11e261ce84805c232ed5dbe6b1bcb84b00ff0"}, + {file = "websockets-10.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:9bc42e8402dc5e9905fb8b9649f57efcb2056693b7e88faa8fb029256ba9c68c"}, + {file = "websockets-10.4-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:edc344de4dac1d89300a053ac973299e82d3db56330f3494905643bb68801269"}, + {file = "websockets-10.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:84bc2a7d075f32f6ed98652db3a680a17a4edb21ca7f80fe42e38753a58ee02b"}, + {file = "websockets-10.4-cp39-cp39-win32.whl", hash = "sha256:c94ae4faf2d09f7c81847c63843f84fe47bf6253c9d60b20f25edfd30fb12588"}, + {file = "websockets-10.4-cp39-cp39-win_amd64.whl", hash = "sha256:bbccd847aa0c3a69b5f691a84d2341a4f8a629c6922558f2a70611305f902d74"}, + {file = "websockets-10.4-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:82ff5e1cae4e855147fd57a2863376ed7454134c2bf49ec604dfe71e446e2193"}, + {file = "websockets-10.4-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d210abe51b5da0ffdbf7b43eed0cfdff8a55a1ab17abbec4301c9ff077dd0342"}, + {file = "websockets-10.4-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:942de28af58f352a6f588bc72490ae0f4ccd6dfc2bd3de5945b882a078e4e179"}, + {file = "websockets-10.4-pp37-pypy37_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c9b27d6c1c6cd53dc93614967e9ce00ae7f864a2d9f99fe5ed86706e1ecbf485"}, + {file = "websockets-10.4-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:3d3cac3e32b2c8414f4f87c1b2ab686fa6284a980ba283617404377cd448f631"}, + {file = "websockets-10.4-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:da39dd03d130162deb63da51f6e66ed73032ae62e74aaccc4236e30edccddbb0"}, + {file = "websockets-10.4-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:389f8dbb5c489e305fb113ca1b6bdcdaa130923f77485db5b189de343a179393"}, + {file = "websockets-10.4-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:09a1814bb15eff7069e51fed0826df0bc0702652b5cb8f87697d469d79c23576"}, + {file = "websockets-10.4-pp38-pypy38_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ff64a1d38d156d429404aaa84b27305e957fd10c30e5880d1765c9480bea490f"}, + {file = "websockets-10.4-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:b343f521b047493dc4022dd338fc6db9d9282658862756b4f6fd0e996c1380e1"}, + {file = "websockets-10.4-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:932af322458da7e4e35df32f050389e13d3d96b09d274b22a7aa1808f292fee4"}, + {file = "websockets-10.4-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d6a4162139374a49eb18ef5b2f4da1dd95c994588f5033d64e0bbfda4b6b6fcf"}, + {file = "websockets-10.4-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c57e4c1349fbe0e446c9fa7b19ed2f8a4417233b6984277cce392819123142d3"}, + {file = "websockets-10.4-pp39-pypy39_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b627c266f295de9dea86bd1112ed3d5fafb69a348af30a2422e16590a8ecba13"}, + {file = "websockets-10.4-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:05a7233089f8bd355e8cbe127c2e8ca0b4ea55467861906b80d2ebc7db4d6b72"}, + {file = "websockets-10.4.tar.gz", hash = "sha256:eef610b23933c54d5d921c92578ae5f89813438fded840c2e9809d378dc765d3"}, ] yarl = [ {file = "yarl-1.8.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:abc06b97407868ef38f3d172762f4069323de52f2b70d133d096a48d72215d28"}, diff --git a/pyproject.toml b/pyproject.toml index a709f7e3d..fa02a4196 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -36,9 +36,9 @@ aiosqlite = "^0.17.0" lxml = "^4.9.1" [tool.poetry.dev-dependencies] -pytest = "^7.0.71" -black = "^22.6" -mypy = ">=0.971,<0.972" +pytest = "^7.1.0" +black = "^22.6.0" +mypy = ">=0.990,<0.991" types-beautifulsoup4 = "^4.11.5" types-regex = "^2022.8.17.0" types-requests = "^2.28.9" From 57d2d2bbda9db568a456917cfd92d8f16c446bbc Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Sat, 19 Nov 2022 18:34:48 -0500 Subject: [PATCH 070/127] lint --- canary/cogs/helpers.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/canary/cogs/helpers.py b/canary/cogs/helpers.py index 029410540..db1075119 100644 --- a/canary/cogs/helpers.py +++ b/canary/cogs/helpers.py @@ -713,10 +713,7 @@ async def create_main_webhooks(self, ctx: commands.Context): await ctx.send("Job completed.") async def spoilerize_utility( - self, ctx: commands.Context, - message: discord.Message, - reason: str | None = None, - moderator: bool = False + self, ctx: commands.Context, message: discord.Message, reason: str | None = None, moderator: bool = False ) -> None: db: aiosqlite.Connection From 605cccbd5e2dbd94cab40822b1dd9b8e21120965 Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Sat, 19 Nov 2022 18:38:10 -0500 Subject: [PATCH 071/127] lint&hint --- canary/cogs/banner.py | 19 ++++++++++--------- canary/cogs/memes.py | 14 +++++++------- 2 files changed, 17 insertions(+), 16 deletions(-) diff --git a/canary/cogs/banner.py b/canary/cogs/banner.py index b24edab74..25d937946 100644 --- a/canary/cogs/banner.py +++ b/canary/cogs/banner.py @@ -20,7 +20,6 @@ from discord import utils # Other utilities -import aiosqlite import asyncio import datetime import json @@ -200,13 +199,13 @@ def msg_check(msg): @commands.command(aliases=["bannerwinner", "setbannerwinner", "set_banner_winner"]) @is_moderator() - async def banner_winner(self, ctx, winner: discord.Member = None): + async def banner_winner(self, ctx: commands.Context, winner: discord.Member = None): """ Select the winner for an ongoing Banner Picture of the Week contest - The winning picture is then set as the server's Banner and the submission is published on the Banner of the week channel. - The winning user receives the Banner of the Week Winner role, and the submission previews are pinned in the - Banner Submissions and Converted Banner Submissions channels. + The winning picture is then set as the server's Banner and the submission is published on the Banner of the week + channel. The winning user receives the Banner of the Week Winner role, and the submission previews are pinned in + the Banner Submissions and Converted Banner Submissions channels. This command can be used with a user as argument. Otherwise, a prompt will ask for the user. The user must have submitted a banner using the submitbanner command during the contest. @@ -382,11 +381,13 @@ def msg_check(msg): @commands.command(aliases=["submitbanner"]) async def submit_banner(self, ctx: commands.Context, *args): """ - Submit a picture for an Banner Picture of the Week contest + Submit a picture for a Banner Picture of the Week contest - There must be an ongoing Banner contest to use this command; check the Banner of the Week channel for more information. - This command can be used in a picture caption or with a url as argument. - The image will be scaled to maximum fit and centered; you can add -stretch to the command for the image to be stretched instead. + There must be an ongoing Banner contest to use this command; check the Banner of the Week channel for more + information. + This command can be used in a picture caption or with a URL as an argument. + The image will be scaled to maximum fit and centered; you can add -stretch to the command for the image to be + stretched instead. For better results, your picture must be at least 960x540 pixels in a 16:9 aspect ratio. You must be a verified user to use this command. diff --git a/canary/cogs/memes.py b/canary/cogs/memes.py index 5ceba23de..bb5443c4a 100644 --- a/canary/cogs/memes.py +++ b/canary/cogs/memes.py @@ -59,7 +59,7 @@ async def bac(self, ctx: commands.Context, *, input_str: str | None = None): await ctx.message.delete() @commands.command() - async def lenny(self, ctx): + async def lenny(self, ctx: commands.Context): """ Lenny face """ @@ -67,7 +67,7 @@ async def lenny(self, ctx): await ctx.message.delete() @commands.command() - async def license(self, ctx): + async def license(self, ctx: commands.Context): """ License """ @@ -93,12 +93,12 @@ async def license(self, ctx): await ctx.message.delete() @commands.command() - async def cheep(self, ctx): + async def cheep(self, ctx: commands.Context): """:^)""" await ctx.send("CHEEP CHEEP") @commands.command() - async def mix(self, ctx, *, input_str: str | None = None): + async def mix(self, ctx: commands.Context, *, input_str: str | None = None): """Alternates upper/lower case for input string. Inputted text is either the content of the message to after the command or the content of the message to which @@ -128,14 +128,14 @@ async def mix(self, ctx, *, input_str: str | None = None): await ctx.message.delete() @commands.command(aliases=["boot"]) - async def pyramid(self, ctx, num: int = 2, emoji: str = "👢"): + async def pyramid(self, ctx: commands.Context, num: int = 2, emoji: str = "👢"): """ Draws a pyramid of boots, default is 2 unless user specifies an integer number of levels of boots between -8 and 8. Also accepts any other emoji, word or multiword (in quotes) string. """ - def pyramidy(n, m): + def pyramidy(n: int, m: int) -> str: # Limit emoji/string to 8 characters or Discord/potate mald return f"{' ' * ((m - n) * 3)}{(emoji[:8] + ' ') * n}" @@ -147,7 +147,7 @@ def pyramidy(n, m): await ctx.send(f"**\n{msg}**") @commands.command() - async def xkcd(self, ctx, command: str | None = None): + async def xkcd(self, ctx: commands.Context, command: str | None = None): """ Enjoy a nice xkcd comic with some strangers on the internet! If no issue number is passed, returns a random xkcd. From eb2817acc7447c6c0c949295cdceb5370ee4692d Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Sat, 19 Nov 2022 18:55:45 -0500 Subject: [PATCH 072/127] banner cog cleanup --- canary/cogs/banner.py | 143 +++++++++++++++++++++++------------------- 1 file changed, 77 insertions(+), 66 deletions(-) diff --git a/canary/cogs/banner.py b/canary/cogs/banner.py index 25d937946..b4024d627 100644 --- a/canary/cogs/banner.py +++ b/canary/cogs/banner.py @@ -33,6 +33,13 @@ class Banner(CanaryCog): + CONVERTER_FILE = "./data/premade/banner_converter.png" + PREVIEW_FILE = "./data/premade/banner_preview.png" + + PREVIEW_MASK_USER_CANVAS_SIZE = (240, 135) + PREVIEW_MASK_USER_BOX_START = (5, 5) + TRANSPARENT = (0, 0, 0, 0) + # Written by @le-potate def __init__(self, bot: Canary): super().__init__(bot) @@ -255,19 +262,20 @@ def msg_check(msg): return winner_str = winner_msg.content - if winner_str.lower() == "none": - await self.reset_banner_contest() - await ctx.send("Successfully ended banner contest.") - return - elif winner_str.lower() == "quit": - await ctx.send("Command exited.") - return - else: - try: - winner = await commands.MemberConverter().convert(ctx, winner_str) - except commands.BadArgument: - await ctx.send("Could not find user.") + match winner_str.lower(): + case "none": + await self.reset_banner_contest() + await ctx.send("Successfully ended banner contest.") + return + case "quit": + await ctx.send("Command exited.") return + case _: + try: + winner = await commands.MemberConverter().convert(ctx, winner_str) + except commands.BadArgument: + await ctx.send("Could not find user.") + return if "BANNER" not in self.guild.features: await ctx.send("This server cannot upload and use a banner") @@ -378,6 +386,10 @@ def msg_check(msg): await self.reset_banner_contest() await ctx.send("Successfully set banner and ended contest.") + @staticmethod + def calc_ratio_max(canvas_dims: tuple[int, int], frame: Image) -> float: + return max(canvas_dims[0] / frame.size[0], canvas_dims[1] / frame.size[1]) + @commands.command(aliases=["submitbanner"]) async def submit_banner(self, ctx: commands.Context, *args): """ @@ -417,9 +429,8 @@ async def submit_banner(self, ctx: commands.Context, *args): if not timestamp: await ctx.send("No banner contest is currently set") return - start_datetime = datetime.datetime.fromtimestamp(timestamp) - if datetime.datetime.now() < start_datetime: + if datetime.datetime.now() < (start_datetime := datetime.datetime.fromtimestamp(timestamp)): await ctx.send(f"You must wait for {start_datetime.strftime('%Y-%m-%d %H:%M')} to submit!") return @@ -429,7 +440,7 @@ async def submit_banner(self, ctx: commands.Context, *args): ) return - stretch = "-stretch" in args or "-stretched" in args + stretch: bool = "-stretch" in args or "-stretched" in args url: str | None = None if (stretch and len(args) == 1) or (not stretch and len(args) == 0): @@ -446,10 +457,11 @@ async def submit_banner(self, ctx: commands.Context, *args): if stretch and len(args) > 2 or not stretch and len(args) > 1: await ctx.send("Too many arguments or misspelled flag") return - else: - for arg in args: - if arg != "-stretch" and arg != "-stretched": - url = arg + + # If the arguments look good: pull the URL out (a non-flag argument) + for arg in args: + if arg != "-stretch" and arg != "-stretched": + url = arg if url is None: return @@ -460,68 +472,67 @@ async def submit_banner(self, ctx: commands.Context, *args): return try: - with Image.open("./data/premade/banner_converter.png") as overlay_mask, Image.open( - "./data/premade/banner_preview.png" - ) as preview_mask, Image.open(user_image_file) as user_image: + with Image.open(Banner.CONVERTER_FILE) as overlay_mask, Image.open( + Banner.PREVIEW_FILE) as preview_mask, Image.open(user_image_file) as user_image: animated = user_image.is_animated overlay_mask_user_canvas_size = overlay_mask.size - preview_mask_user_canvas_size = (240, 135) - preview_mask_user_box_start = (5, 5) - overlay_frames = [] - preview_frames = [] + overlay_frames: list[Image] = [] + preview_frames: list[Image] = [] + durations: list[float] = [] + if animated: - durations = [] await ctx.send("Converting animated banner, this may take some time...") for frame in ImageSequence.Iterator(user_image): if animated: durations.append(frame.info["duration"]) + frame = frame.copy() rgba_frame = frame.convert("RGBA") + + # If we're stretching the banner, things are a bit easier for us, as we don't have to find a + # good 'fit' for the image. if stretch: overlay_frames.append( Image.alpha_composite(rgba_frame.resize(overlay_mask_user_canvas_size), overlay_mask) ) - preview_user_image = Image.new("RGBA", preview_mask.size, (0, 0, 0, 0)) + preview_user_image = Image.new("RGBA", preview_mask.size, Banner.TRANSPARENT) preview_user_image.paste( - rgba_frame.resize(preview_mask_user_canvas_size), preview_mask_user_box_start + rgba_frame.resize(Banner.PREVIEW_MASK_USER_CANVAS_SIZE), + Banner.PREVIEW_MASK_USER_BOX_START ) preview_frames.append(Image.alpha_composite(preview_user_image, preview_mask)) - else: - overlay_ratio = max( - overlay_mask_user_canvas_size[0] / rgba_frame.size[0], - overlay_mask_user_canvas_size[1] / rgba_frame.size[1], - ) - overlay_user_image = Image.new("RGBA", overlay_mask_user_canvas_size, (0, 0, 0, 0)) - overlay_user_size = ( - int(rgba_frame.size[0] * overlay_ratio), - int(rgba_frame.size[1] * overlay_ratio), - ) - overlay_mask_user_image_start = ( - int(overlay_mask_user_canvas_size[0] / 2 - overlay_user_size[0] / 2), - int(overlay_mask_user_canvas_size[1] / 2 - overlay_user_size[1] / 2), - ) - overlay_user_image.paste(rgba_frame.resize(overlay_user_size), overlay_mask_user_image_start) - overlay_frames.append(Image.alpha_composite(overlay_user_image, overlay_mask)) - - preview_ratio = max( - preview_mask_user_canvas_size[0] / rgba_frame.size[0], - preview_mask_user_canvas_size[1] / rgba_frame.size[1], - ) - preview_user_image = Image.new("RGBA", preview_mask.size, (0, 0, 0, 0)) - preview_user_size = ( - int(rgba_frame.size[0] * preview_ratio), - int(rgba_frame.size[1] * preview_ratio), - ) - preview_mask_user_image_start = ( - 5 + int(preview_mask_user_canvas_size[0] / 2 - preview_user_size[0] / 2), - 5 + int(preview_mask_user_canvas_size[1] / 2 - preview_user_size[1] / 2), - ) - preview_user_image.paste(rgba_frame.resize(preview_user_size), preview_mask_user_image_start) - preview_frames.append(Image.alpha_composite(preview_user_image, preview_mask)) + continue + + # Otherwise, we have to fit the image nicely into the frame + overlay_ratio: float = Banner.calc_ratio_max(overlay_mask_user_canvas_size, rgba_frame) + overlay_user_image: Image = Image.new("RGBA", overlay_mask_user_canvas_size, Banner.TRANSPARENT) + overlay_user_size: tuple[int, int] = ( + int(rgba_frame.size[0] * overlay_ratio), + int(rgba_frame.size[1] * overlay_ratio), + ) + overlay_mask_user_image_start: tuple[int, int] = ( + int(overlay_mask_user_canvas_size[0] / 2 - overlay_user_size[0] / 2), + int(overlay_mask_user_canvas_size[1] / 2 - overlay_user_size[1] / 2), + ) + overlay_user_image.paste(rgba_frame.resize(overlay_user_size), overlay_mask_user_image_start) + overlay_frames.append(Image.alpha_composite(overlay_user_image, overlay_mask)) + + preview_ratio: float = Banner.calc_ratio_max(Banner.PREVIEW_MASK_USER_CANVAS_SIZE, rgba_frame) + preview_user_image: Image = Image.new("RGBA", preview_mask.size, Banner.TRANSPARENT) + preview_user_size: tuple[int, int] = ( + int(rgba_frame.size[0] * preview_ratio), + int(rgba_frame.size[1] * preview_ratio), + ) + preview_mask_user_image_start: tuple[int, int] = ( + 5 + int(Banner.PREVIEW_MASK_USER_CANVAS_SIZE[0] / 2 - preview_user_size[0] / 2), + 5 + int(Banner.PREVIEW_MASK_USER_CANVAS_SIZE[1] / 2 - preview_user_size[1] / 2), + ) + preview_user_image.paste(rgba_frame.resize(preview_user_size), preview_mask_user_image_start) + preview_frames.append(Image.alpha_composite(preview_user_image, preview_mask)) except UnidentifiedImageError or requests.exceptions.MissingSchema: await ctx.send(f"Image couldn't be opened.") @@ -529,7 +540,7 @@ async def submit_banner(self, ctx: commands.Context, *args): replaced_message = False - fetched = await self.fetch_one( + fetched: tuple[int] | None = await self.fetch_one( "SELECT PreviewMessageID FROM BannerSubmissions WHERE UserID = ?", (ctx.author.id,), ) @@ -545,7 +556,7 @@ async def submit_banner(self, ctx: commands.Context, *args): ) replaced_message = True - async def send_picture(frames, channel, filename): + async def send_picture(frames: list, channel: discord.TextChannel, filename: str) -> discord.Message: with BytesIO() as image_binary: if animated: frames[0].save( @@ -561,11 +572,11 @@ async def send_picture(frames, channel, filename): ) return message - filetype = "gif" if animated else "png" - converted_message = await send_picture( + filetype: str = "gif" if animated else "png" + converted_message: discord.Message = await send_picture( overlay_frames, self.banner_converted_channel, f"converted_banner.{filetype}" ) - preview_message = await send_picture( + preview_message: discord.Message = await send_picture( preview_frames, self.banner_submissions_channel, f"banner_preview.{filetype}" ) await preview_message.add_reaction(self.banner_vote_emoji) From 205fc29617ec27d027334531e214abcca501d24a Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Sat, 19 Nov 2022 19:00:05 -0500 Subject: [PATCH 073/127] more banner cleanup --- canary/cogs/banner.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/canary/cogs/banner.py b/canary/cogs/banner.py index b4024d627..dd1aa289c 100644 --- a/canary/cogs/banner.py +++ b/canary/cogs/banner.py @@ -134,11 +134,13 @@ async def set_banner_contest(self, ctx): You must be a moderator to use this command. """ + if "BANNER" not in self.guild.features: await ctx.send( "Warning: This server cannot currently upload and use a banner. " "You may still set the next banner contest." ) + if self.start_datetime: if datetime.datetime.now() < self.start_datetime: await ctx.send( @@ -166,13 +168,14 @@ def msg_check(msg): except asyncio.TimeoutError: await ctx.send("Command timed out.") return - date_str = date_msg.content - if date_str.lower() == "quit": + date_str = date_msg.content.lower() + + if date_str == "quit": await ctx.send("Command exited.") return - if date_str.lower() == "now": + if date_str == "now": timestamp = datetime.datetime.now().timestamp() else: try: @@ -409,9 +412,10 @@ async def submit_banner(self, ctx: commands.Context, *args): await ctx.send("No banner submissions channel set.") return + # TODO: this is not portable to other server setups if not ( - discord.utils.get(ctx.author.roles, name=self.bot.config.mcgillian_role) - or discord.utils.get(ctx.author.roles, name=self.bot.config.honorary_mcgillian_role) + discord.utils.get(ctx.author.roles, name=self.bot.config.mcgillian_role) or + discord.utils.get(ctx.author.roles, name=self.bot.config.honorary_mcgillian_role) ): await ctx.send("You must be a verified user.") return From b976113c850e1c5d02898d38c0dd24cc00a1d58d Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Sat, 19 Nov 2022 19:05:43 -0500 Subject: [PATCH 074/127] currency cleanup --- canary/cogs/banner.py | 1 - canary/cogs/currency.py | 30 +++++++++++++----------------- 2 files changed, 13 insertions(+), 18 deletions(-) diff --git a/canary/cogs/banner.py b/canary/cogs/banner.py index dd1aa289c..bd7cf6e99 100644 --- a/canary/cogs/banner.py +++ b/canary/cogs/banner.py @@ -433,7 +433,6 @@ async def submit_banner(self, ctx: commands.Context, *args): if not timestamp: await ctx.send("No banner contest is currently set") return - if datetime.datetime.now() < (start_datetime := datetime.datetime.fromtimestamp(timestamp)): await ctx.send(f"You must wait for {start_datetime.strftime('%Y-%m-%d %H:%M')} to submit!") return diff --git a/canary/cogs/currency.py b/canary/cogs/currency.py index f5c22e638..8619a5868 100644 --- a/canary/cogs/currency.py +++ b/canary/cogs/currency.py @@ -85,7 +85,7 @@ async def fetch_bank_balance(self, user: discord.Member) -> Decimal: async def create_bank_transaction( self, db: aiosqlite.Connection, user: discord.Member, amount: Decimal, action: str, metadata: dict - ): + ) -> None: # Don't create another connection in this function in order to properly # transaction-ify a series of bank "transactions". @@ -103,7 +103,7 @@ async def create_bank_transaction( ) @staticmethod - def parse_currency(amount: str, balance: Decimal): + def parse_currency(amount: str, balance: Decimal) -> Decimal | None: if amount.lower().strip() in CURRENCY_ALL: return balance @@ -113,16 +113,16 @@ def parse_currency(amount: str, balance: Decimal): # Value error (invalid conversion) return None - def currency_to_db(self, amount: Decimal): + def currency_to_db(self, amount: Decimal) -> int: return int(amount * Decimal(10 ** self.currency["precision"])) - def db_to_currency(self, amount: int): + def db_to_currency(self, amount: int) -> Decimal: return Decimal(amount) / Decimal(10 ** self.currency["precision"]) - def format_currency(self, amount: Decimal): + def format_currency(self, amount: Decimal) -> str: return ("{:." + str(self.prec) + "f}").format(amount) - def format_symbol_currency(self, amount: Decimal): + def format_symbol_currency(self, amount: Decimal) -> str: return self.currency["symbol"] + self.format_currency(amount) @staticmethod @@ -148,8 +148,6 @@ def check_bet(balance: Decimal, bet: Decimal) -> str | None: if bet > balance: return "You're too broke to bet that much!" - return "" - async def get_last_claim_time(self, db: aiosqlite.Connection, author: discord.Member | discord.User) -> int | None: claim_time_t = await self.fetch_one( "SELECT IFNULL(MAX(Date), 0) FROM BankTransactions WHERE UserID = ? AND Action = ?", @@ -261,8 +259,7 @@ async def bet_flip(self, ctx: commands.Context, bet: str | None = None, face: st # Handle invalid cases - error = self.check_bet(balance, bet_dec) - if error != "": + if (error := self.check_bet(balance, bet_dec)) is not None: await ctx.send(error) return @@ -307,8 +304,7 @@ async def bet_roll(self, ctx: commands.Context, bet: str | None = None): bet_dec = self.parse_currency(bet, balance) # Handle invalid cases - error = self.check_bet(balance, bet_dec) - if error != "": + if (error := self.check_bet(balance, bet_dec)) != "": await ctx.send(error) return @@ -336,18 +332,19 @@ async def bet_roll(self, ctx: commands.Context, bet: str | None = None): ) await db.commit() - message = "Sorry! {un} lost {am} (result was **{re}**)." if amount_returned == bet_dec: - message = "{un} broke even (result was **{re}**)." + message_tpl = "{un} broke even (result was **{re}**)." elif amount_returned > bet_dec: - message = "Congratulations! {un} won [net] {am} (result was **{re}**)." + message_tpl = "Congratulations! {un} won [net] {am} (result was **{re}**)." + else: + message_tpl = "Sorry! {un} lost {am} (result was **{re}**)." author_name = ctx.message.author.display_name amount_msg_multiplier = -1 if amount_returned < bet_dec else 1 bet_str = self.format_symbol_currency(amount_msg_multiplier * (amount_returned - bet_dec)) - await ctx.send(message.format(un=author_name, am=bet_str, re=result)) + await ctx.send(message_tpl.format(un=author_name, am=bet_str, re=result)) @commands.command() async def give(self, ctx: commands.Context, user: discord.Member | None = None, amount: str | None = None): @@ -394,7 +391,6 @@ async def give(self, ctx: commands.Context, user: discord.Member | None = None, gen = user.display_name gifter_metadata = {"giftee": user.id, "channel": ctx.message.channel.id} - giftee_metadata = {"gifter": ctx.message.author.id, "channel": ctx.message.channel.id} db: aiosqlite.Connection From f1fd108899ed05e27c44c66aa88142b95fcb30e3 Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Sat, 19 Nov 2022 19:10:33 -0500 Subject: [PATCH 075/127] a bit of spacing --- canary/cogs/memes.py | 29 ++++++++++++----------------- 1 file changed, 12 insertions(+), 17 deletions(-) diff --git a/canary/cogs/memes.py b/canary/cogs/memes.py index bb5443c4a..2b146e9c7 100644 --- a/canary/cogs/memes.py +++ b/canary/cogs/memes.py @@ -72,23 +72,14 @@ async def license(self, ctx: commands.Context): License """ await ctx.send( - "This bot is free software: you can redistribute" - " it and/or modify it under the terms of the GNU" - " General Public License as published by the " - "Free Software Foundation, either version 3 of " - "the License, or (at your option) any later " - "version. **This bot is distributed in the hope " - "that it will be useful**, but WITHOUT ANY " - "WARRANTY; without even the implied warranty of " - "MERCHANTABILITY or **FITNESS FOR A PARTICULAR " - "PURPOSE**. See the GNU General Public License " - "for more details. This bot is developed " - "primarily by student volunteers with better " - "things to do. A copy of the GNU General Public " - "License is provided in the LICENSE.txt file " - "along with this bot. The GNU General Public " - "License can also be found at " - "." + "This bot is free software: you can redistribute it and/or modify it under the terms of the GNU" + " General Public License as published by the Free Software Foundation, either version 3 of " + "the License, or (at your option) any later version. **This bot is distributed in the hope " + "that it will be useful**, but WITHOUT ANY WARRANTY; without even the implied warranty of " + "MERCHANTABILITY or **FITNESS FOR A PARTICULAR PURPOSE**. See the GNU General Public License " + "for more details. This bot is developed primarily by student volunteers with better " + "things to do. A copy of the GNU General Public License is provided in the LICENSE.txt file " + "along with this bot. The GNU General Public License can also be found at ." ) await ctx.message.delete() @@ -106,12 +97,15 @@ async def mix(self, ctx: commands.Context, *, input_str: str | None = None): is replying a message, the bot will reply to that message as well. Invoking message will be deleted. """ + replying: bool = ctx.message.reference and ctx.message.reference.resolved if input_str is None: if not replying: return input_str = ctx.message.reference.resolved.content + msg = "".join((c.upper() if random.randint(0, 1) else c.lower()) for c in input_str) + self.bot.mod_logger.info( f"?mix invoked: Author: '{ctx.message.author}', " f"Message: '{ctx.message.content}'" @@ -124,6 +118,7 @@ async def mix(self, ctx: commands.Context, *, input_str: str | None = None): else "" ) ) + await ctx.send(msg, reference=ctx.message.reference, mention_author=False) await ctx.message.delete() From 81e1b110d2324f161aee5da17fa2ef76777f5105 Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Sat, 19 Nov 2022 19:19:58 -0500 Subject: [PATCH 076/127] lint --- canary/cogs/banner.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/canary/cogs/banner.py b/canary/cogs/banner.py index bd7cf6e99..692a35e4f 100644 --- a/canary/cogs/banner.py +++ b/canary/cogs/banner.py @@ -414,8 +414,8 @@ async def submit_banner(self, ctx: commands.Context, *args): # TODO: this is not portable to other server setups if not ( - discord.utils.get(ctx.author.roles, name=self.bot.config.mcgillian_role) or - discord.utils.get(ctx.author.roles, name=self.bot.config.honorary_mcgillian_role) + discord.utils.get(ctx.author.roles, name=self.bot.config.mcgillian_role) + or discord.utils.get(ctx.author.roles, name=self.bot.config.honorary_mcgillian_role) ): await ctx.send("You must be a verified user.") return @@ -476,7 +476,8 @@ async def submit_banner(self, ctx: commands.Context, *args): try: with Image.open(Banner.CONVERTER_FILE) as overlay_mask, Image.open( - Banner.PREVIEW_FILE) as preview_mask, Image.open(user_image_file) as user_image: + Banner.PREVIEW_FILE + ) as preview_mask, Image.open(user_image_file) as user_image: animated = user_image.is_animated @@ -504,8 +505,7 @@ async def submit_banner(self, ctx: commands.Context, *args): ) preview_user_image = Image.new("RGBA", preview_mask.size, Banner.TRANSPARENT) preview_user_image.paste( - rgba_frame.resize(Banner.PREVIEW_MASK_USER_CANVAS_SIZE), - Banner.PREVIEW_MASK_USER_BOX_START + rgba_frame.resize(Banner.PREVIEW_MASK_USER_CANVAS_SIZE), Banner.PREVIEW_MASK_USER_BOX_START ) preview_frames.append(Image.alpha_composite(preview_user_image, preview_mask)) continue From 9ffaf8ff570740e71ca2ef38ffc93bfb7d5fe1fc Mon Sep 17 00:00:00 2001 From: Mathieu B <47489943+le-potate@users.noreply.github.com> Date: Fri, 12 May 2023 15:03:53 -0400 Subject: [PATCH 077/127] update bot.py year --- canary/bot.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/canary/bot.py b/canary/bot.py index e43c77b9b..bf6859aef 100644 --- a/canary/bot.py +++ b/canary/bot.py @@ -1,4 +1,4 @@ -# Copyright (C) idoneam (2016-2022) +# Copyright (C) idoneam (2016-2023) # # This file is part of Canary # From 6a307d7b8d287e1c610848af870af1a52eb058d2 Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Sat, 13 May 2023 13:38:41 -0400 Subject: [PATCH 078/127] redo config class --- canary/bot.py | 58 ++++++------- canary/config/__init__.py | 5 ++ canary/config/{parser.py => config.py} | 111 ++++++++++++++++++++++++- poetry.lock | 70 +++++++++++++++- pyproject.toml | 4 +- 5 files changed, 213 insertions(+), 35 deletions(-) rename canary/config/{parser.py => config.py} (68%) diff --git a/canary/bot.py b/canary/bot.py index bf6859aef..784bcae15 100644 --- a/canary/bot.py +++ b/canary/bot.py @@ -20,7 +20,7 @@ import logging import traceback -from canary.config import parser +from canary.config import Config from discord import Webhook, RequestsWebhookAdapter, Intents from discord.ext import commands from pathlib import Path @@ -28,29 +28,29 @@ __all__ = ["Canary", "bot", "developer_role", "moderator_role", "muted_role"] -_parser = parser.Parser() -command_prefix = _parser.command_prefix +config = Config() +command_prefix = config.command_prefix # Create parent logger, which will send all logs from the "sub-loggers" # to the specified log file -_logger = logging.getLogger("Canary") -_logger.setLevel(_parser.log_level) -_file_handler = logging.FileHandler(filename=_parser.log_file, encoding="utf-8", mode="a") -_file_handler.setFormatter(logging.Formatter("[%(levelname)s] %(asctime)s: %(message)s")) -_logger.addHandler(_file_handler) +logger = logging.getLogger("Canary") +logger.setLevel(config.log_level) +file_handler = logging.FileHandler(filename=config.log_file, encoding="utf-8", mode="a") +file_handler.setFormatter(logging.Formatter("[%(levelname)s] %(asctime)s: %(message)s")) +logger.addHandler(file_handler) # Create dev (sub-)logger, which is where errors and messages are logged # If a dev webhook is specified, logs sent to the dev logger will be # sent to the webhook -_dev_logger = logging.getLogger("Canary.Dev") -_dev_logger.setLevel(_parser.log_level) +dev_logger = logging.getLogger("Canary.Dev") +dev_logger.setLevel(config.log_level) # Create mod (sub-)logger, where info for mods will be logged # If a mod webhook is specified, logs sent to the mod logger will be # sent to the webhook. This is always set to the INFO level, since this is # where info for mods is logged -_mod_logger = logging.getLogger("Canary.Mod") -_mod_logger.setLevel(logging.INFO) +mod_logger = logging.getLogger("Canary.Mod") +mod_logger.setLevel(logging.INFO) class _WebhookHandler(logging.Handler): @@ -64,21 +64,21 @@ def emit(self, record): self.webhook.send(f"```\n{msg}```", username=self.username) -if _parser.dev_log_webhook_id and _parser.dev_log_webhook_token: - _dev_webhook_username = f"{_parser.bot_name} Dev Logs" - _dev_webhook_handler = _WebhookHandler( - _parser.dev_log_webhook_id, _parser.dev_log_webhook_token, username=_dev_webhook_username +if config.dev_log_webhook_id and config.dev_log_webhook_token: + dev_webhook_username = f"{config.bot_name} Dev Logs" + dev_webhook_handler = _WebhookHandler( + config.dev_log_webhook_id, config.dev_log_webhook_token, username=dev_webhook_username ) - _dev_webhook_handler.setFormatter(logging.Formatter("[%(levelname)s] %(asctime)s:\n%(message)s")) - _dev_logger.addHandler(_dev_webhook_handler) + dev_webhook_handler.setFormatter(logging.Formatter("[%(levelname)s] %(asctime)s:\n%(message)s")) + dev_logger.addHandler(dev_webhook_handler) -if _parser.mod_log_webhook_id and _parser.mod_log_webhook_token: - _mod_webhook_username = f"{_parser.bot_name} Mod Logs" - _mod_webhook_handler = _WebhookHandler( - _parser.mod_log_webhook_id, _parser.mod_log_webhook_token, username=_mod_webhook_username +if config.mod_log_webhook_id and config.mod_log_webhook_token: + mod_webhook_username = f"{config.bot_name} Mod Logs" + mod_webhook_handler = _WebhookHandler( + config.mod_log_webhook_id, config.mod_log_webhook_token, username=mod_webhook_username ) - _mod_webhook_handler.setFormatter(logging.Formatter("[%(levelname)s] %(asctime)s:\n%(message)s")) - _mod_logger.addHandler(_mod_webhook_handler) + mod_webhook_handler.setFormatter(logging.Formatter("[%(levelname)s] %(asctime)s:\n%(message)s")) + mod_logger.addHandler(mod_webhook_handler) class Canary(commands.Bot): @@ -86,15 +86,15 @@ class Canary(commands.Bot): def __init__(self, *args, **kwargs): super().__init__(command_prefix, *args, **kwargs) - self.logger = _logger - self.dev_logger = _dev_logger - self.mod_logger = _mod_logger - self.config = _parser + self.logger = logger + self.dev_logger = dev_logger + self.mod_logger = mod_logger + self.config = config async def start(self, *args, **kwargs): # TODO: discordpy 2.0: use setup_hook for database setup await self._start_database() await super().start(*args, **kwargs) - await self._health_check() + await self.health_check() @contextlib.asynccontextmanager async def db(self) -> AsyncGenerator[aiosqlite.Connection, None]: diff --git a/canary/config/__init__.py b/canary/config/__init__.py index e69de29bb..9e6f2f6c8 100644 --- a/canary/config/__init__.py +++ b/canary/config/__init__.py @@ -0,0 +1,5 @@ +__all__ = [ + "Config", +] + +from .config import Config diff --git a/canary/config/parser.py b/canary/config/config.py similarity index 68% rename from canary/config/parser.py rename to canary/config/config.py index 2c9785374..2d7ffb65a 100644 --- a/canary/config/parser.py +++ b/canary/config/config.py @@ -19,8 +19,10 @@ import configparser import decimal import logging +import os from pathlib import Path +from pydantic import BaseModel, BaseSettings LOG_LEVELS = { "critical": logging.CRITICAL, @@ -32,18 +34,119 @@ } -class Parser: +class CurrencyModel(BaseModel): + name: str = "cheeps" + symbol: str = "ʧ" + precision: int = 2 + initial: int = 1000 + + # TODO: Finish + + +class MusicModel(BaseModel): + ban_role: str = "tone deaf" + start_vol: float = "100.0" + + +class Settings(BaseSettings): + # Discord token + discord_key: str + + # Server configs + server_id: int + command_prefix: str = "?" + bot_name: str = "Marty" + + # Emoji + upvote_emoji: str = "upmartlet" + downvote_emoji: str = "downmartlet" + banner_vote_emoji: str = "redchiken" + + # Roles + moderator_role: str = "Discord Moderator" + developer_role: str = "idoneam" + mcgillian_role: str = "McGillian" + honorary_mcgillian_role: str = "Honorary McGillian" + banner_reminders_role: str = "Banner Submissions" + banner_winner_role: str = "Banner of the Week Winner" + trash_tier_banner_role: str = "Trash Tier Banner Submissions" + no_food_spotting_role: str = "Trash Tier Foodspotting" + muted_role: str = "Muted" + crabbo_role: str = "Secret Crabbo" + + # Channels + reception_channel: str = "martys_dm" + banner_of_the_week_channel: str = "banner_of_the_week" + banner_submissions_channel: str = "banner_submissions" + banner_converted_channel: str = "converted_banner_submissions" + food_spotting_channel: str = "foodspotting" + metro_status_channel: str = "stm_alerts" + bots_channel: str = "bots" + verification_channel: str = "verification_log" + appeals_log_channel: str = "appeals_log" + appeals_category: str = "appeals" + + # Meta + repository: str = "https://github.com/idoneam/Canary.git" + + # Logging + dev_log_webhook_id: int | None = None + dev_log_webhook_token: str | None = None + mod_log_webhook_id: int | None = None + mod_log_webhook_token: str | None = None + + # Welcome + Farewell messages + # NOT PORTED FROM OLD CONFIG SETUP. + + # DB configuration + db_path: str = "./data/runtime/Martlet.db" + + # Helpers configuration + course_tpl: str = "http://www.mcgill.ca/study/2022-2023/courses/{}" + course_search_tpl: str = ( + "http://www.mcgill.ca/study/2022-2023/courses/search?search_api_views_fulltext={}&sort_by=field_subject_code" + "&page={}" + ) + gc_weather_url: str = "http://weather.gc.ca/city/pages/qc-147_metric_e.html" + gc_weather_alert_url: str = "https://weather.gc.ca/warnings/report_e.html?qc67" + wttr_in_tpl: str = "http://wttr.in/Montreal_2mpq_lang=en.png?_m" + tepid_url: str = "https://tepid.science.mcgill.ca:8443/tepid/screensaver/queues/status" + + # Subscription configuration + recall_channel: str = "food" + recall_filter: str = "Quebec|National" + + # Currency configuration + currency: CurrencyModel + + # Music configuration + music: MusicModel + + # Assignable Roles + # TODO + + class Config: + env_file = ".env" + env_prefix = "CANARY_" + env_nested_delimiter = "__" + + +class Config: CONFIG_PATH = Path(__file__).parent / "config.ini" def __init__(self): config = configparser.ConfigParser() - config.read_file(codecs.open(str(Parser.CONFIG_PATH), "r", "utf-8-sig")) + config.read_file(codecs.open(str(Config.CONFIG_PATH), "r", "utf-8-sig")) # Discord token - self.discord_key = config["Discord"]["Key"] + # Try to get from environment; if not found, then + self.discord_key = os.environ.get("CANARY_DISCORD_KEY", config["Discord"].get("Key")) + + if self.discord_key is None: + raise Exception("Missing discord key; please specify with CANARY_DISCORD_KEY environment variable.") # Server configs - self.server_id = int(config["Server"]["ServerID"]) + self.server_id = int(os.environ.get("CANARY_SERVER_ID", config["Server"].get("ServerID"))) self.command_prefix = [s for s in config["Server"]["CommandPrefix"].strip().split(",")] self.bot_name = config["Server"]["BotName"] diff --git a/poetry.lock b/poetry.lock index 3f11d167d..1c4416e62 100644 --- a/poetry.lock +++ b/poetry.lock @@ -450,6 +450,21 @@ category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +[[package]] +name = "pydantic" +version = "1.10.2" +description = "Data validation and settings management using python type hints" +category = "main" +optional = false +python-versions = ">=3.7" + +[package.dependencies] +typing-extensions = ">=4.1.0" + +[package.extras] +dotenv = ["python-dotenv (>=0.10.4)"] +email = ["email-validator (>=1.0.3)"] + [[package]] name = "pynacl" version = "1.4.0" @@ -497,6 +512,17 @@ tomli = {version = ">=1.0.0", markers = "python_version < \"3.11\""} [package.extras] testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "xmlschema"] +[[package]] +name = "python-dotenv" +version = "0.21.0" +description = "Read key-value pairs from a .env file and set them as environment variables" +category = "main" +optional = false +python-versions = ">=3.7" + +[package.extras] +cli = ["click (>=5.0)"] + [[package]] name = "pytz" version = "2022.6" @@ -725,7 +751,7 @@ websockets = "*" [metadata] lock-version = "1.1" python-versions = "~3.10.0" -content-hash = "9a9885637d1c56e793e349491971c5b7d66a560a48b388a57fbf496b39f22f3b" +content-hash = "f9cc4fc29fb495b269d95370d38ceaaaad31e021702c50ddf8756e307fceb3a1" [metadata.files] aiohttp = [ @@ -1258,6 +1284,44 @@ pycryptodomex = [ {file = "pycryptodomex-3.15.0-pp36-pypy36_pp73-win32.whl", hash = "sha256:35a8f7afe1867118330e2e0e0bf759c409e28557fb1fc2fbb1c6c937297dbe9a"}, {file = "pycryptodomex-3.15.0.tar.gz", hash = "sha256:7341f1bb2dadb0d1a0047f34c3a58208a92423cdbd3244d998e4b28df5eac0ed"}, ] +pydantic = [ + {file = "pydantic-1.10.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:bb6ad4489af1bac6955d38ebcb95079a836af31e4c4f74aba1ca05bb9f6027bd"}, + {file = "pydantic-1.10.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a1f5a63a6dfe19d719b1b6e6106561869d2efaca6167f84f5ab9347887d78b98"}, + {file = "pydantic-1.10.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:352aedb1d71b8b0736c6d56ad2bd34c6982720644b0624462059ab29bd6e5912"}, + {file = "pydantic-1.10.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:19b3b9ccf97af2b7519c42032441a891a5e05c68368f40865a90eb88833c2559"}, + {file = "pydantic-1.10.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e9069e1b01525a96e6ff49e25876d90d5a563bc31c658289a8772ae186552236"}, + {file = "pydantic-1.10.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:355639d9afc76bcb9b0c3000ddcd08472ae75318a6eb67a15866b87e2efa168c"}, + {file = "pydantic-1.10.2-cp310-cp310-win_amd64.whl", hash = "sha256:ae544c47bec47a86bc7d350f965d8b15540e27e5aa4f55170ac6a75e5f73b644"}, + {file = "pydantic-1.10.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a4c805731c33a8db4b6ace45ce440c4ef5336e712508b4d9e1aafa617dc9907f"}, + {file = "pydantic-1.10.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d49f3db871575e0426b12e2f32fdb25e579dea16486a26e5a0474af87cb1ab0a"}, + {file = "pydantic-1.10.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:37c90345ec7dd2f1bcef82ce49b6235b40f282b94d3eec47e801baf864d15525"}, + {file = "pydantic-1.10.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7b5ba54d026c2bd2cb769d3468885f23f43710f651688e91f5fb1edcf0ee9283"}, + {file = "pydantic-1.10.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:05e00dbebbe810b33c7a7362f231893183bcc4251f3f2ff991c31d5c08240c42"}, + {file = "pydantic-1.10.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:2d0567e60eb01bccda3a4df01df677adf6b437958d35c12a3ac3e0f078b0ee52"}, + {file = "pydantic-1.10.2-cp311-cp311-win_amd64.whl", hash = "sha256:c6f981882aea41e021f72779ce2a4e87267458cc4d39ea990729e21ef18f0f8c"}, + {file = "pydantic-1.10.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:c4aac8e7103bf598373208f6299fa9a5cfd1fc571f2d40bf1dd1955a63d6eeb5"}, + {file = "pydantic-1.10.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:81a7b66c3f499108b448f3f004801fcd7d7165fb4200acb03f1c2402da73ce4c"}, + {file = "pydantic-1.10.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bedf309630209e78582ffacda64a21f96f3ed2e51fbf3962d4d488e503420254"}, + {file = "pydantic-1.10.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:9300fcbebf85f6339a02c6994b2eb3ff1b9c8c14f502058b5bf349d42447dcf5"}, + {file = "pydantic-1.10.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:216f3bcbf19c726b1cc22b099dd409aa371f55c08800bcea4c44c8f74b73478d"}, + {file = "pydantic-1.10.2-cp37-cp37m-win_amd64.whl", hash = "sha256:dd3f9a40c16daf323cf913593083698caee97df2804aa36c4b3175d5ac1b92a2"}, + {file = "pydantic-1.10.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:b97890e56a694486f772d36efd2ba31612739bc6f3caeee50e9e7e3ebd2fdd13"}, + {file = "pydantic-1.10.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:9cabf4a7f05a776e7793e72793cd92cc865ea0e83a819f9ae4ecccb1b8aa6116"}, + {file = "pydantic-1.10.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:06094d18dd5e6f2bbf93efa54991c3240964bb663b87729ac340eb5014310624"}, + {file = "pydantic-1.10.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cc78cc83110d2f275ec1970e7a831f4e371ee92405332ebfe9860a715f8336e1"}, + {file = "pydantic-1.10.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:1ee433e274268a4b0c8fde7ad9d58ecba12b069a033ecc4645bb6303c062d2e9"}, + {file = "pydantic-1.10.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:7c2abc4393dea97a4ccbb4ec7d8658d4e22c4765b7b9b9445588f16c71ad9965"}, + {file = "pydantic-1.10.2-cp38-cp38-win_amd64.whl", hash = "sha256:0b959f4d8211fc964772b595ebb25f7652da3f22322c007b6fed26846a40685e"}, + {file = "pydantic-1.10.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c33602f93bfb67779f9c507e4d69451664524389546bacfe1bee13cae6dc7488"}, + {file = "pydantic-1.10.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:5760e164b807a48a8f25f8aa1a6d857e6ce62e7ec83ea5d5c5a802eac81bad41"}, + {file = "pydantic-1.10.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6eb843dcc411b6a2237a694f5e1d649fc66c6064d02b204a7e9d194dff81eb4b"}, + {file = "pydantic-1.10.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4b8795290deaae348c4eba0cebb196e1c6b98bdbe7f50b2d0d9a4a99716342fe"}, + {file = "pydantic-1.10.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:e0bedafe4bc165ad0a56ac0bd7695df25c50f76961da29c050712596cf092d6d"}, + {file = "pydantic-1.10.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:2e05aed07fa02231dbf03d0adb1be1d79cabb09025dd45aa094aa8b4e7b9dcda"}, + {file = "pydantic-1.10.2-cp39-cp39-win_amd64.whl", hash = "sha256:c1ba1afb396148bbc70e9eaa8c06c1716fdddabaf86e7027c5988bae2a829ab6"}, + {file = "pydantic-1.10.2-py3-none-any.whl", hash = "sha256:1b6ee725bd6e83ec78b1aa32c5b1fa67a3a65badddde3976bca5fe4568f27709"}, + {file = "pydantic-1.10.2.tar.gz", hash = "sha256:91b8e218852ef6007c2b98cd861601c6a09f1aa32bbbb74fab5b1c33d4a1e410"}, +] pynacl = [ {file = "PyNaCl-1.4.0-cp27-cp27m-macosx_10_10_x86_64.whl", hash = "sha256:ea6841bc3a76fa4942ce00f3bda7d436fda21e2d91602b9e21b7ca9ecab8f3ff"}, {file = "PyNaCl-1.4.0-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:d452a6746f0a7e11121e64625109bc4468fc3100452817001dbe018bb8b08514"}, @@ -1286,6 +1350,10 @@ pytest = [ {file = "pytest-7.2.0-py3-none-any.whl", hash = "sha256:892f933d339f068883b6fd5a459f03d85bfcb355e4981e146d2c7616c21fef71"}, {file = "pytest-7.2.0.tar.gz", hash = "sha256:c4014eb40e10f11f355ad4e3c2fb2c6c6d1919c73f3b5a433de4708202cade59"}, ] +python-dotenv = [ + {file = "python-dotenv-0.21.0.tar.gz", hash = "sha256:b77d08274639e3d34145dfa6c7008e66df0f04b7be7a75fd0d5292c191d79045"}, + {file = "python_dotenv-0.21.0-py3-none-any.whl", hash = "sha256:1684eb44636dd462b66c3ee016599815514527ad99965de77f43e0944634a7e5"}, +] pytz = [ {file = "pytz-2022.6-py2.py3-none-any.whl", hash = "sha256:222439474e9c98fced559f1709d89e6c9cbf8d79c794ff3eb9f8800064291427"}, {file = "pytz-2022.6.tar.gz", hash = "sha256:e89512406b793ca39f5971bc999cc538ce125c0e51c27941bef4568b460095e2"}, diff --git a/pyproject.toml b/pyproject.toml index fa02a4196..8d6592774 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "Canary" -version = "3.3.0" +version = "4.0.0" description = "" license = "GPL-3.0-only" repository = "https://github.com/idoneam/Canary" @@ -34,6 +34,8 @@ uvloop = {version="0.16.0", markers = "sys_platform == 'linux' or sys_platform = bidict = "^0.22.0" aiosqlite = "^0.17.0" lxml = "^4.9.1" +python-dotenv = "^0.21.0" +pydantic = "^1.10.2" [tool.poetry.dev-dependencies] pytest = "^7.1.0" From 0856545849dab9e09d160ff33fe18f43fbf4a932 Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Sat, 13 May 2023 13:38:53 -0400 Subject: [PATCH 079/127] type hint context in main.load fn --- canary/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/canary/main.py b/canary/main.py index accb54efa..a0f6f7b88 100755 --- a/canary/main.py +++ b/canary/main.py @@ -63,7 +63,7 @@ async def on_ready(): @bot.command() @is_moderator() -async def load(ctx, extension_name: str): +async def load(ctx: Context, extension_name: str): """ Load a specific extension. Specify as cogs. """ From fd4cc9d759f85cb1e07b38b205b238505ee88321 Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Sat, 13 May 2023 13:59:43 -0400 Subject: [PATCH 080/127] update dependencies, require poetry 1.4+ --- README.md | 5 +- poetry.lock | 2121 +++++++++++++++++++++++++----------------------- pyproject.toml | 14 +- 3 files changed, 1136 insertions(+), 1004 deletions(-) diff --git a/README.md b/README.md index 843111945..050b478f4 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,8 @@ [![Discord](https://img.shields.io/discord/236668784948019202.svg)](https://discord.gg/HDHvv58) [![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black) -Canary is a Python3 bot designed for the McGill University Community Discord Server. The bot provides helper functions to users, as well as fun functions, a quote database and custom greeting messages. +Canary is a Python3 bot designed for the McGill University Community Discord Server. The bot provides helper functions +to users, as well as fun functions, a quote database and custom greeting messages. ## Build Statuses @@ -18,7 +19,7 @@ Canary is a Python3 bot designed for the McGill University Community Discord Ser git clone https://github.com/idoneam/Canary ``` -2. Dependencies are managed with poetry which can be installed via pip with: +2. Dependencies are managed with `poetry` (1.4+), which can be installed via `pip` with: ```bash python3 -m pip install poetry diff --git a/poetry.lock b/poetry.lock index 1c4416e62..d94686432 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,3 +1,5 @@ +# This file is automatically @generated by Poetry 1.4.2 and should not be changed by hand. + [[package]] name = "aiohttp" version = "3.7.4.post0" @@ -5,6 +7,45 @@ description = "Async http client/server framework (asyncio)" category = "main" optional = false python-versions = ">=3.6" +files = [ + {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"}, +] [package.dependencies] async-timeout = ">=3.0,<4.0" @@ -24,6 +65,10 @@ description = "asyncio bridge to the standard sqlite3 module" category = "main" optional = false python-versions = ">=3.6" +files = [ + {file = "aiosqlite-0.17.0-py3-none-any.whl", hash = "sha256:6c49dc6d3405929b1d08eeccc72306d3677503cc5e5e43771efc1e00232e8231"}, + {file = "aiosqlite-0.17.0.tar.gz", hash = "sha256:f0e6acc24bc4864149267ac82fb46dfb3be4455f99fe21df82609cc6e6baee51"}, +] [package.dependencies] typing_extensions = ">=3.7.2" @@ -35,28 +80,41 @@ description = "Timeout context manager for asyncio programs" category = "main" optional = false python-versions = ">=3.5.3" +files = [ + {file = "async-timeout-3.0.1.tar.gz", hash = "sha256:0c3c816a028d47f659d6ff5c745cb2acf1f966da1fe5c19c77a70282b25f4c5f"}, + {file = "async_timeout-3.0.1-py3-none-any.whl", hash = "sha256:4291ca197d287d274d0b6cb5d6f8f8f82d434ed288f962539ff18cc9012f9ea3"}, +] [[package]] name = "attrs" -version = "22.1.0" +version = "23.1.0" description = "Classes Without Boilerplate" category = "main" optional = false -python-versions = ">=3.5" +python-versions = ">=3.7" +files = [ + {file = "attrs-23.1.0-py3-none-any.whl", hash = "sha256:1f28b4522cdc2fb4256ac1a020c78acf9cba2c6b461ccd2c126f3aa8e8335d04"}, + {file = "attrs-23.1.0.tar.gz", hash = "sha256:6279836d581513a26f1bf235f9acd333bc9115683f14f7e8fae46c98fc50e015"}, +] [package.extras] -dev = ["cloudpickle", "coverage[toml] (>=5.0.2)", "furo", "hypothesis", "mypy (>=0.900,!=0.940)", "pre-commit", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "sphinx", "sphinx-notfound-page", "zope.interface"] -docs = ["furo", "sphinx", "sphinx-notfound-page", "zope.interface"] -tests = ["cloudpickle", "coverage[toml] (>=5.0.2)", "hypothesis", "mypy (>=0.900,!=0.940)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "zope.interface"] -tests-no-zope = ["cloudpickle", "coverage[toml] (>=5.0.2)", "hypothesis", "mypy (>=0.900,!=0.940)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins"] +cov = ["attrs[tests]", "coverage[toml] (>=5.3)"] +dev = ["attrs[docs,tests]", "pre-commit"] +docs = ["furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier", "zope-interface"] +tests = ["attrs[tests-no-zope]", "zope-interface"] +tests-no-zope = ["cloudpickle", "hypothesis", "mypy (>=1.1.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] [[package]] name = "beautifulsoup4" -version = "4.10.0" +version = "4.12.2" description = "Screen-scraping library" category = "main" optional = false -python-versions = ">3.0.0" +python-versions = ">=3.6.0" +files = [ + {file = "beautifulsoup4-4.12.2-py3-none-any.whl", hash = "sha256:bd2520ca0d9d7d12694a53d44ac482d181b4ec1888909b035a3dbf40d0f57d4a"}, + {file = "beautifulsoup4-4.12.2.tar.gz", hash = "sha256:492bbc69dca35d12daac71c4db1bfff0c876c00ef4a2ffacce226d4638eb72da"}, +] [package.dependencies] soupsieve = ">1.2" @@ -67,26 +125,63 @@ lxml = ["lxml"] [[package]] name = "bidict" -version = "0.22.0" +version = "0.22.1" description = "The bidirectional mapping library for Python." category = "main" optional = false python-versions = ">=3.7" +files = [ + {file = "bidict-0.22.1-py3-none-any.whl", hash = "sha256:6ef212238eb884b664f28da76f33f1d28b260f665fc737b413b287d5487d1e7b"}, + {file = "bidict-0.22.1.tar.gz", hash = "sha256:1e0f7f74e4860e6d0943a05d4134c63a2fad86f3d4732fb265bd79e4e856d81d"}, +] + +[package.extras] +docs = ["furo", "sphinx", "sphinx-copybutton"] +lint = ["pre-commit"] +test = ["hypothesis", "pytest", "pytest-benchmark[histogram]", "pytest-cov", "pytest-xdist", "sortedcollections", "sortedcontainers", "sphinx"] [[package]] name = "black" -version = "22.10.0" +version = "23.3.0" description = "The uncompromising code formatter." category = "dev" optional = false python-versions = ">=3.7" +files = [ + {file = "black-23.3.0-cp310-cp310-macosx_10_16_arm64.whl", hash = "sha256:0945e13506be58bf7db93ee5853243eb368ace1c08a24c65ce108986eac65915"}, + {file = "black-23.3.0-cp310-cp310-macosx_10_16_universal2.whl", hash = "sha256:67de8d0c209eb5b330cce2469503de11bca4085880d62f1628bd9972cc3366b9"}, + {file = "black-23.3.0-cp310-cp310-macosx_10_16_x86_64.whl", hash = "sha256:7c3eb7cea23904399866c55826b31c1f55bbcd3890ce22ff70466b907b6775c2"}, + {file = "black-23.3.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:32daa9783106c28815d05b724238e30718f34155653d4d6e125dc7daec8e260c"}, + {file = "black-23.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:35d1381d7a22cc5b2be2f72c7dfdae4072a3336060635718cc7e1ede24221d6c"}, + {file = "black-23.3.0-cp311-cp311-macosx_10_16_arm64.whl", hash = "sha256:a8a968125d0a6a404842fa1bf0b349a568634f856aa08ffaff40ae0dfa52e7c6"}, + {file = "black-23.3.0-cp311-cp311-macosx_10_16_universal2.whl", hash = "sha256:c7ab5790333c448903c4b721b59c0d80b11fe5e9803d8703e84dcb8da56fec1b"}, + {file = "black-23.3.0-cp311-cp311-macosx_10_16_x86_64.whl", hash = "sha256:a6f6886c9869d4daae2d1715ce34a19bbc4b95006d20ed785ca00fa03cba312d"}, + {file = "black-23.3.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6f3c333ea1dd6771b2d3777482429864f8e258899f6ff05826c3a4fcc5ce3f70"}, + {file = "black-23.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:11c410f71b876f961d1de77b9699ad19f939094c3a677323f43d7a29855fe326"}, + {file = "black-23.3.0-cp37-cp37m-macosx_10_16_x86_64.whl", hash = "sha256:1d06691f1eb8de91cd1b322f21e3bfc9efe0c7ca1f0e1eb1db44ea367dff656b"}, + {file = "black-23.3.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:50cb33cac881766a5cd9913e10ff75b1e8eb71babf4c7104f2e9c52da1fb7de2"}, + {file = "black-23.3.0-cp37-cp37m-win_amd64.whl", hash = "sha256:e114420bf26b90d4b9daa597351337762b63039752bdf72bf361364c1aa05925"}, + {file = "black-23.3.0-cp38-cp38-macosx_10_16_arm64.whl", hash = "sha256:48f9d345675bb7fbc3dd85821b12487e1b9a75242028adad0333ce36ed2a6d27"}, + {file = "black-23.3.0-cp38-cp38-macosx_10_16_universal2.whl", hash = "sha256:714290490c18fb0126baa0fca0a54ee795f7502b44177e1ce7624ba1c00f2331"}, + {file = "black-23.3.0-cp38-cp38-macosx_10_16_x86_64.whl", hash = "sha256:064101748afa12ad2291c2b91c960be28b817c0c7eaa35bec09cc63aa56493c5"}, + {file = "black-23.3.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:562bd3a70495facf56814293149e51aa1be9931567474993c7942ff7d3533961"}, + {file = "black-23.3.0-cp38-cp38-win_amd64.whl", hash = "sha256:e198cf27888ad6f4ff331ca1c48ffc038848ea9f031a3b40ba36aced7e22f2c8"}, + {file = "black-23.3.0-cp39-cp39-macosx_10_16_arm64.whl", hash = "sha256:3238f2aacf827d18d26db07524e44741233ae09a584273aa059066d644ca7b30"}, + {file = "black-23.3.0-cp39-cp39-macosx_10_16_universal2.whl", hash = "sha256:f0bd2f4a58d6666500542b26354978218a9babcdc972722f4bf90779524515f3"}, + {file = "black-23.3.0-cp39-cp39-macosx_10_16_x86_64.whl", hash = "sha256:92c543f6854c28a3c7f39f4d9b7694f9a6eb9d3c5e2ece488c327b6e7ea9b266"}, + {file = "black-23.3.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3a150542a204124ed00683f0db1f5cf1c2aaaa9cc3495b7a3b5976fb136090ab"}, + {file = "black-23.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:6b39abdfb402002b8a7d030ccc85cf5afff64ee90fa4c5aebc531e3ad0175ddb"}, + {file = "black-23.3.0-py3-none-any.whl", hash = "sha256:ec751418022185b0c1bb7d7736e6933d40bbb14c14a0abcf9123d1b159f98dd4"}, + {file = "black-23.3.0.tar.gz", hash = "sha256:1c7b8d606e728a41ea1ccbd7264677e494e87cf630e399262ced92d4a8dac940"}, +] [package.dependencies] click = ">=8.0.0" mypy-extensions = ">=0.4.3" +packaging = ">=22.0" pathspec = ">=0.9.0" platformdirs = ">=2" -tomli = {version = ">=1.1.0", markers = "python_full_version < \"3.11.0a7\""} +tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} [package.extras] colorama = ["colorama (>=0.4.3)"] @@ -96,11 +191,15 @@ uvloop = ["uvloop (>=0.15.2)"] [[package]] name = "certifi" -version = "2022.9.24" +version = "2023.5.7" description = "Python package for providing Mozilla's CA Bundle." category = "main" optional = false python-versions = ">=3.6" +files = [ + {file = "certifi-2023.5.7-py3-none-any.whl", hash = "sha256:c6c2e98f5c7869efca1f8916fed228dd91539f9f1b444c314c06eef02980c716"}, + {file = "certifi-2023.5.7.tar.gz", hash = "sha256:0f0d56dc5a6ad56fd4ba36484d6cc34451e1c6548c61daad8c320169f91eddc7"}, +] [[package]] name = "cffi" @@ -109,6 +208,72 @@ description = "Foreign Function Interface for Python calling C code." category = "main" optional = false python-versions = "*" +files = [ + {file = "cffi-1.15.1-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:a66d3508133af6e8548451b25058d5812812ec3798c886bf38ed24a98216fab2"}, + {file = "cffi-1.15.1-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:470c103ae716238bbe698d67ad020e1db9d9dba34fa5a899b5e21577e6d52ed2"}, + {file = "cffi-1.15.1-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:9ad5db27f9cabae298d151c85cf2bad1d359a1b9c686a275df03385758e2f914"}, + {file = "cffi-1.15.1-cp27-cp27m-win32.whl", hash = "sha256:b3bbeb01c2b273cca1e1e0c5df57f12dce9a4dd331b4fa1635b8bec26350bde3"}, + {file = "cffi-1.15.1-cp27-cp27m-win_amd64.whl", hash = "sha256:e00b098126fd45523dd056d2efba6c5a63b71ffe9f2bbe1a4fe1716e1d0c331e"}, + {file = "cffi-1.15.1-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:d61f4695e6c866a23a21acab0509af1cdfd2c013cf256bbf5b6b5e2695827162"}, + {file = "cffi-1.15.1-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:ed9cb427ba5504c1dc15ede7d516b84757c3e3d7868ccc85121d9310d27eed0b"}, + {file = "cffi-1.15.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:39d39875251ca8f612b6f33e6b1195af86d1b3e60086068be9cc053aa4376e21"}, + {file = "cffi-1.15.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:285d29981935eb726a4399badae8f0ffdff4f5050eaa6d0cfc3f64b857b77185"}, + {file = "cffi-1.15.1-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3eb6971dcff08619f8d91607cfc726518b6fa2a9eba42856be181c6d0d9515fd"}, + {file = "cffi-1.15.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:21157295583fe8943475029ed5abdcf71eb3911894724e360acff1d61c1d54bc"}, + {file = "cffi-1.15.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5635bd9cb9731e6d4a1132a498dd34f764034a8ce60cef4f5319c0541159392f"}, + {file = "cffi-1.15.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2012c72d854c2d03e45d06ae57f40d78e5770d252f195b93f581acf3ba44496e"}, + {file = "cffi-1.15.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd86c085fae2efd48ac91dd7ccffcfc0571387fe1193d33b6394db7ef31fe2a4"}, + {file = "cffi-1.15.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:fa6693661a4c91757f4412306191b6dc88c1703f780c8234035eac011922bc01"}, + {file = "cffi-1.15.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:59c0b02d0a6c384d453fece7566d1c7e6b7bae4fc5874ef2ef46d56776d61c9e"}, + {file = "cffi-1.15.1-cp310-cp310-win32.whl", hash = "sha256:cba9d6b9a7d64d4bd46167096fc9d2f835e25d7e4c121fb2ddfc6528fb0413b2"}, + {file = "cffi-1.15.1-cp310-cp310-win_amd64.whl", hash = "sha256:ce4bcc037df4fc5e3d184794f27bdaab018943698f4ca31630bc7f84a7b69c6d"}, + {file = "cffi-1.15.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3d08afd128ddaa624a48cf2b859afef385b720bb4b43df214f85616922e6a5ac"}, + {file = "cffi-1.15.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3799aecf2e17cf585d977b780ce79ff0dc9b78d799fc694221ce814c2c19db83"}, + {file = "cffi-1.15.1-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a591fe9e525846e4d154205572a029f653ada1a78b93697f3b5a8f1f2bc055b9"}, + {file = "cffi-1.15.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3548db281cd7d2561c9ad9984681c95f7b0e38881201e157833a2342c30d5e8c"}, + {file = "cffi-1.15.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:91fc98adde3d7881af9b59ed0294046f3806221863722ba7d8d120c575314325"}, + {file = "cffi-1.15.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:94411f22c3985acaec6f83c6df553f2dbe17b698cc7f8ae751ff2237d96b9e3c"}, + {file = "cffi-1.15.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:03425bdae262c76aad70202debd780501fabeaca237cdfddc008987c0e0f59ef"}, + {file = "cffi-1.15.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:cc4d65aeeaa04136a12677d3dd0b1c0c94dc43abac5860ab33cceb42b801c1e8"}, + {file = "cffi-1.15.1-cp311-cp311-win32.whl", hash = "sha256:a0f100c8912c114ff53e1202d0078b425bee3649ae34d7b070e9697f93c5d52d"}, + {file = "cffi-1.15.1-cp311-cp311-win_amd64.whl", hash = "sha256:04ed324bda3cda42b9b695d51bb7d54b680b9719cfab04227cdd1e04e5de3104"}, + {file = "cffi-1.15.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50a74364d85fd319352182ef59c5c790484a336f6db772c1a9231f1c3ed0cbd7"}, + {file = "cffi-1.15.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e263d77ee3dd201c3a142934a086a4450861778baaeeb45db4591ef65550b0a6"}, + {file = "cffi-1.15.1-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cec7d9412a9102bdc577382c3929b337320c4c4c4849f2c5cdd14d7368c5562d"}, + {file = "cffi-1.15.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4289fc34b2f5316fbb762d75362931e351941fa95fa18789191b33fc4cf9504a"}, + {file = "cffi-1.15.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:173379135477dc8cac4bc58f45db08ab45d228b3363adb7af79436135d028405"}, + {file = "cffi-1.15.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:6975a3fac6bc83c4a65c9f9fcab9e47019a11d3d2cf7f3c0d03431bf145a941e"}, + {file = "cffi-1.15.1-cp36-cp36m-win32.whl", hash = "sha256:2470043b93ff09bf8fb1d46d1cb756ce6132c54826661a32d4e4d132e1977adf"}, + {file = "cffi-1.15.1-cp36-cp36m-win_amd64.whl", hash = "sha256:30d78fbc8ebf9c92c9b7823ee18eb92f2e6ef79b45ac84db507f52fbe3ec4497"}, + {file = "cffi-1.15.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:198caafb44239b60e252492445da556afafc7d1e3ab7a1fb3f0584ef6d742375"}, + {file = "cffi-1.15.1-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5ef34d190326c3b1f822a5b7a45f6c4535e2f47ed06fec77d3d799c450b2651e"}, + {file = "cffi-1.15.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8102eaf27e1e448db915d08afa8b41d6c7ca7a04b7d73af6514df10a3e74bd82"}, + {file = "cffi-1.15.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5df2768244d19ab7f60546d0c7c63ce1581f7af8b5de3eb3004b9b6fc8a9f84b"}, + {file = "cffi-1.15.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a8c4917bd7ad33e8eb21e9a5bbba979b49d9a97acb3a803092cbc1133e20343c"}, + {file = "cffi-1.15.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0e2642fe3142e4cc4af0799748233ad6da94c62a8bec3a6648bf8ee68b1c7426"}, + {file = "cffi-1.15.1-cp37-cp37m-win32.whl", hash = "sha256:e229a521186c75c8ad9490854fd8bbdd9a0c9aa3a524326b55be83b54d4e0ad9"}, + {file = "cffi-1.15.1-cp37-cp37m-win_amd64.whl", hash = "sha256:a0b71b1b8fbf2b96e41c4d990244165e2c9be83d54962a9a1d118fd8657d2045"}, + {file = "cffi-1.15.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:320dab6e7cb2eacdf0e658569d2575c4dad258c0fcc794f46215e1e39f90f2c3"}, + {file = "cffi-1.15.1-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1e74c6b51a9ed6589199c787bf5f9875612ca4a8a0785fb2d4a84429badaf22a"}, + {file = "cffi-1.15.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a5c84c68147988265e60416b57fc83425a78058853509c1b0629c180094904a5"}, + {file = "cffi-1.15.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3b926aa83d1edb5aa5b427b4053dc420ec295a08e40911296b9eb1b6170f6cca"}, + {file = "cffi-1.15.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:87c450779d0914f2861b8526e035c5e6da0a3199d8f1add1a665e1cbc6fc6d02"}, + {file = "cffi-1.15.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4f2c9f67e9821cad2e5f480bc8d83b8742896f1242dba247911072d4fa94c192"}, + {file = "cffi-1.15.1-cp38-cp38-win32.whl", hash = "sha256:8b7ee99e510d7b66cdb6c593f21c043c248537a32e0bedf02e01e9553a172314"}, + {file = "cffi-1.15.1-cp38-cp38-win_amd64.whl", hash = "sha256:00a9ed42e88df81ffae7a8ab6d9356b371399b91dbdf0c3cb1e84c03a13aceb5"}, + {file = "cffi-1.15.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:54a2db7b78338edd780e7ef7f9f6c442500fb0d41a5a4ea24fff1c929d5af585"}, + {file = "cffi-1.15.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:fcd131dd944808b5bdb38e6f5b53013c5aa4f334c5cad0c72742f6eba4b73db0"}, + {file = "cffi-1.15.1-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7473e861101c9e72452f9bf8acb984947aa1661a7704553a9f6e4baa5ba64415"}, + {file = "cffi-1.15.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6c9a799e985904922a4d207a94eae35c78ebae90e128f0c4e521ce339396be9d"}, + {file = "cffi-1.15.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3bcde07039e586f91b45c88f8583ea7cf7a0770df3a1649627bf598332cb6984"}, + {file = "cffi-1.15.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:33ab79603146aace82c2427da5ca6e58f2b3f2fb5da893ceac0c42218a40be35"}, + {file = "cffi-1.15.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5d598b938678ebf3c67377cdd45e09d431369c3b1a5b331058c338e201f12b27"}, + {file = "cffi-1.15.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:db0fbb9c62743ce59a9ff687eb5f4afbe77e5e8403d6697f7446e5f609976f76"}, + {file = "cffi-1.15.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:98d85c6a2bef81588d9227dde12db8a7f47f639f4a17c9ae08e773aa9c697bf3"}, + {file = "cffi-1.15.1-cp39-cp39-win32.whl", hash = "sha256:40f4774f5a9d4f5e344f31a32b5096977b5d48560c5592e2f3d2c4374bd543ee"}, + {file = "cffi-1.15.1-cp39-cp39-win_amd64.whl", hash = "sha256:70df4e3b545a17496c9b3f41f5115e69a4f2e77e94e1d2a8e1070bc0c38c8a3c"}, + {file = "cffi-1.15.1.tar.gz", hash = "sha256:d400bfb9a37b1351253cb402671cea7e89bdecc294e8016a707f6d1d8ac934f9"}, +] [package.dependencies] pycparser = "*" @@ -120,17 +285,95 @@ description = "Universal encoding detector for Python 2 and 3" category = "main" optional = false python-versions = "*" +files = [ + {file = "chardet-3.0.4-py2.py3-none-any.whl", hash = "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691"}, + {file = "chardet-3.0.4.tar.gz", hash = "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae"}, +] [[package]] name = "charset-normalizer" -version = "2.1.1" +version = "3.1.0" description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." category = "main" optional = false -python-versions = ">=3.6.0" - -[package.extras] -unicode-backport = ["unicodedata2"] +python-versions = ">=3.7.0" +files = [ + {file = "charset-normalizer-3.1.0.tar.gz", hash = "sha256:34e0a2f9c370eb95597aae63bf85eb5e96826d81e3dcf88b8886012906f509b5"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:e0ac8959c929593fee38da1c2b64ee9778733cdf03c482c9ff1d508b6b593b2b"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d7fc3fca01da18fbabe4625d64bb612b533533ed10045a2ac3dd194bfa656b60"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:04eefcee095f58eaabe6dc3cc2262f3bcd776d2c67005880894f447b3f2cb9c1"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:20064ead0717cf9a73a6d1e779b23d149b53daf971169289ed2ed43a71e8d3b0"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1435ae15108b1cb6fffbcea2af3d468683b7afed0169ad718451f8db5d1aff6f"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c84132a54c750fda57729d1e2599bb598f5fa0344085dbde5003ba429a4798c0"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75f2568b4189dda1c567339b48cba4ac7384accb9c2a7ed655cd86b04055c795"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:11d3bcb7be35e7b1bba2c23beedac81ee893ac9871d0ba79effc7fc01167db6c"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:891cf9b48776b5c61c700b55a598621fdb7b1e301a550365571e9624f270c203"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:5f008525e02908b20e04707a4f704cd286d94718f48bb33edddc7d7b584dddc1"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:b06f0d3bf045158d2fb8837c5785fe9ff9b8c93358be64461a1089f5da983137"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:49919f8400b5e49e961f320c735388ee686a62327e773fa5b3ce6721f7e785ce"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:22908891a380d50738e1f978667536f6c6b526a2064156203d418f4856d6e86a"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-win32.whl", hash = "sha256:12d1a39aa6b8c6f6248bb54550efcc1c38ce0d8096a146638fd4738e42284448"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:65ed923f84a6844de5fd29726b888e58c62820e0769b76565480e1fdc3d062f8"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9a3267620866c9d17b959a84dd0bd2d45719b817245e49371ead79ed4f710d19"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6734e606355834f13445b6adc38b53c0fd45f1a56a9ba06c2058f86893ae8017"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f8303414c7b03f794347ad062c0516cee0e15f7a612abd0ce1e25caf6ceb47df"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aaf53a6cebad0eae578f062c7d462155eada9c172bd8c4d250b8c1d8eb7f916a"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3dc5b6a8ecfdc5748a7e429782598e4f17ef378e3e272eeb1340ea57c9109f41"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e1b25e3ad6c909f398df8921780d6a3d120d8c09466720226fc621605b6f92b1"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0ca564606d2caafb0abe6d1b5311c2649e8071eb241b2d64e75a0d0065107e62"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b82fab78e0b1329e183a65260581de4375f619167478dddab510c6c6fb04d9b6"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:bd7163182133c0c7701b25e604cf1611c0d87712e56e88e7ee5d72deab3e76b5"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:11d117e6c63e8f495412d37e7dc2e2fff09c34b2d09dbe2bee3c6229577818be"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:cf6511efa4801b9b38dc5546d7547d5b5c6ef4b081c60b23e4d941d0eba9cbeb"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:abc1185d79f47c0a7aaf7e2412a0eb2c03b724581139193d2d82b3ad8cbb00ac"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:cb7b2ab0188829593b9de646545175547a70d9a6e2b63bf2cd87a0a391599324"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-win32.whl", hash = "sha256:c36bcbc0d5174a80d6cccf43a0ecaca44e81d25be4b7f90f0ed7bcfbb5a00909"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:cca4def576f47a09a943666b8f829606bcb17e2bc2d5911a46c8f8da45f56755"}, + {file = "charset_normalizer-3.1.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:0c95f12b74681e9ae127728f7e5409cbbef9cd914d5896ef238cc779b8152373"}, + {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fca62a8301b605b954ad2e9c3666f9d97f63872aa4efcae5492baca2056b74ab"}, + {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ac0aa6cd53ab9a31d397f8303f92c42f534693528fafbdb997c82bae6e477ad9"}, + {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c3af8e0f07399d3176b179f2e2634c3ce9c1301379a6b8c9c9aeecd481da494f"}, + {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3a5fc78f9e3f501a1614a98f7c54d3969f3ad9bba8ba3d9b438c3bc5d047dd28"}, + {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:628c985afb2c7d27a4800bfb609e03985aaecb42f955049957814e0491d4006d"}, + {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:74db0052d985cf37fa111828d0dd230776ac99c740e1a758ad99094be4f1803d"}, + {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:1e8fcdd8f672a1c4fc8d0bd3a2b576b152d2a349782d1eb0f6b8e52e9954731d"}, + {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:04afa6387e2b282cf78ff3dbce20f0cc071c12dc8f685bd40960cc68644cfea6"}, + {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:dd5653e67b149503c68c4018bf07e42eeed6b4e956b24c00ccdf93ac79cdff84"}, + {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d2686f91611f9e17f4548dbf050e75b079bbc2a82be565832bc8ea9047b61c8c"}, + {file = "charset_normalizer-3.1.0-cp37-cp37m-win32.whl", hash = "sha256:4155b51ae05ed47199dc5b2a4e62abccb274cee6b01da5b895099b61b1982974"}, + {file = "charset_normalizer-3.1.0-cp37-cp37m-win_amd64.whl", hash = "sha256:322102cdf1ab682ecc7d9b1c5eed4ec59657a65e1c146a0da342b78f4112db23"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:e633940f28c1e913615fd624fcdd72fdba807bf53ea6925d6a588e84e1151531"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:3a06f32c9634a8705f4ca9946d667609f52cf130d5548881401f1eb2c39b1e2c"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7381c66e0561c5757ffe616af869b916c8b4e42b367ab29fedc98481d1e74e14"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3573d376454d956553c356df45bb824262c397c6e26ce43e8203c4c540ee0acb"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e89df2958e5159b811af9ff0f92614dabf4ff617c03a4c1c6ff53bf1c399e0e1"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:78cacd03e79d009d95635e7d6ff12c21eb89b894c354bd2b2ed0b4763373693b"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:de5695a6f1d8340b12a5d6d4484290ee74d61e467c39ff03b39e30df62cf83a0"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1c60b9c202d00052183c9be85e5eaf18a4ada0a47d188a83c8f5c5b23252f649"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:f645caaf0008bacf349875a974220f1f1da349c5dbe7c4ec93048cdc785a3326"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:ea9f9c6034ea2d93d9147818f17c2a0860d41b71c38b9ce4d55f21b6f9165a11"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:80d1543d58bd3d6c271b66abf454d437a438dff01c3e62fdbcd68f2a11310d4b"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:73dc03a6a7e30b7edc5b01b601e53e7fc924b04e1835e8e407c12c037e81adbd"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6f5c2e7bc8a4bf7c426599765b1bd33217ec84023033672c1e9a8b35eaeaaaf8"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-win32.whl", hash = "sha256:12a2b561af122e3d94cdb97fe6fb2bb2b82cef0cdca131646fdb940a1eda04f0"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:3160a0fd9754aab7d47f95a6b63ab355388d890163eb03b2d2b87ab0a30cfa59"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:38e812a197bf8e71a59fe55b757a84c1f946d0ac114acafaafaf21667a7e169e"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6baf0baf0d5d265fa7944feb9f7451cc316bfe30e8df1a61b1bb08577c554f31"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:8f25e17ab3039b05f762b0a55ae0b3632b2e073d9c8fc88e89aca31a6198e88f"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3747443b6a904001473370d7810aa19c3a180ccd52a7157aacc264a5ac79265e"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b116502087ce8a6b7a5f1814568ccbd0e9f6cfd99948aa59b0e241dc57cf739f"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d16fd5252f883eb074ca55cb622bc0bee49b979ae4e8639fff6ca3ff44f9f854"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21fa558996782fc226b529fdd2ed7866c2c6ec91cee82735c98a197fae39f706"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6f6c7a8a57e9405cad7485f4c9d3172ae486cfef1344b5ddd8e5239582d7355e"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ac3775e3311661d4adace3697a52ac0bab17edd166087d493b52d4f4f553f9f0"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:10c93628d7497c81686e8e5e557aafa78f230cd9e77dd0c40032ef90c18f2230"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:6f4f4668e1831850ebcc2fd0b1cd11721947b6dc7c00bf1c6bd3c929ae14f2c7"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:0be65ccf618c1e7ac9b849c315cc2e8a8751d9cfdaa43027d4f6624bd587ab7e"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:53d0a3fa5f8af98a1e261de6a3943ca631c526635eb5817a87a59d9a57ebf48f"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-win32.whl", hash = "sha256:a04f86f41a8916fe45ac5024ec477f41f886b3c435da2d4e3d2709b22ab02af1"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:830d2948a5ec37c386d3170c483063798d7879037492540f10a475e3fd6f244b"}, + {file = "charset_normalizer-3.1.0-py3-none-any.whl", hash = "sha256:3d9098b479e78c85080c98e1e35ff40b4a31d8953102bb0fd7d1b6f8a2111a3d"}, +] [[package]] name = "click" @@ -139,6 +382,10 @@ description = "Composable command line interface toolkit" category = "dev" optional = false python-versions = ">=3.7" +files = [ + {file = "click-8.1.3-py3-none-any.whl", hash = "sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48"}, + {file = "click-8.1.3.tar.gz", hash = "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e"}, +] [package.dependencies] colorama = {version = "*", markers = "platform_system == \"Windows\""} @@ -150,6 +397,10 @@ description = "Cross-platform colored terminal text." category = "dev" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" +files = [ + {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, + {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, +] [[package]] name = "discord-py" @@ -158,6 +409,10 @@ description = "A Python wrapper for the Discord API" category = "main" optional = false python-versions = ">=3.5.3" +files = [ + {file = "discord.py-1.6.0-py3-none-any.whl", hash = "sha256:3df148daf6fbcc7ab5b11042368a3cd5f7b730b62f09fb5d3cbceff59bcfbb12"}, + {file = "discord.py-1.6.0.tar.gz", hash = "sha256:ba8be99ff1b8c616f7b6dcb700460d0222b29d4c11048e74366954c465fdd05f"}, +] [package.dependencies] aiohttp = ">=3.6.0,<3.8.0" @@ -169,11 +424,15 @@ voice = ["PyNaCl (>=1.3.0,<1.5)"] [[package]] name = "exceptiongroup" -version = "1.0.4" +version = "1.1.1" description = "Backport of PEP 654 (exception groups)" category = "dev" optional = false python-versions = ">=3.7" +files = [ + {file = "exceptiongroup-1.1.1-py3-none-any.whl", hash = "sha256:232c37c63e4f682982c8b6459f33a8981039e5fb8756b2074364e5055c498c9e"}, + {file = "exceptiongroup-1.1.1.tar.gz", hash = "sha256:d484c3090ba2889ae2928419117447a14daf3c1231d5e30d0aae34f354f01785"}, +] [package.extras] test = ["pytest (>=6)"] @@ -185,6 +444,10 @@ description = "Universal feed parser, handles RSS 0.9x, RSS 1.0, RSS 2.0, CDF, A category = "main" optional = false python-versions = ">=3.6" +files = [ + {file = "feedparser-6.0.10-py3-none-any.whl", hash = "sha256:79c257d526d13b944e965f6095700587f27388e50ea16fd245babe4dfae7024f"}, + {file = "feedparser-6.0.10.tar.gz", hash = "sha256:27da485f4637ce7163cdeab13a80312b93b7d0c1b775bef4a47629a3110bca51"}, +] [package.dependencies] sgmllib3k = "*" @@ -196,6 +459,9 @@ description = "Free Google Translate API for Python. Translates totally free of category = "main" optional = false python-versions = ">=3.6" +files = [ + {file = "googletrans-4.0.0rc1.tar.gz", hash = "sha256:74df47b092e2d566522019d149e3f1d75732570ad76eaf8e14aebeffc126c372"}, +] [package.dependencies] httpx = "0.13.3" @@ -207,6 +473,10 @@ description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" category = "main" optional = false python-versions = "*" +files = [ + {file = "h11-0.9.0-py2.py3-none-any.whl", hash = "sha256:4bc6d6a1238b7615b266ada57e0618568066f57dd6fa967d1290ec9309b2f2f1"}, + {file = "h11-0.9.0.tar.gz", hash = "sha256:33d4bca7be0fa039f4e84d50ab00531047e53d6ee8ffbc83501ea602c169cae1"}, +] [[package]] name = "h2" @@ -215,6 +485,10 @@ description = "HTTP/2 State-Machine based protocol implementation" category = "main" optional = false python-versions = "*" +files = [ + {file = "h2-3.2.0-py2.py3-none-any.whl", hash = "sha256:61e0f6601fa709f35cdb730863b4e5ec7ad449792add80d1410d4174ed139af5"}, + {file = "h2-3.2.0.tar.gz", hash = "sha256:875f41ebd6f2c44781259005b157faed1a5031df3ae5aa7bcb4628a6c0782f14"}, +] [package.dependencies] hpack = ">=3.0,<4" @@ -227,14 +501,22 @@ description = "Pure-Python HPACK header compression" category = "main" optional = false python-versions = "*" +files = [ + {file = "hpack-3.0.0-py2.py3-none-any.whl", hash = "sha256:0edd79eda27a53ba5be2dfabf3b15780928a0dff6eb0c60a3d6767720e970c89"}, + {file = "hpack-3.0.0.tar.gz", hash = "sha256:8eec9c1f4bfae3408a3f30500261f7e6a65912dc138526ea054f9ad98892e9d2"}, +] [[package]] name = "hstspreload" -version = "2022.11.1" +version = "2023.1.1" description = "Chromium HSTS Preload list as a Python package" category = "main" optional = false python-versions = ">=3.6" +files = [ + {file = "hstspreload-2023.1.1-py3-none-any.whl", hash = "sha256:ac8a56dd603b4bf55292fc7a157e0deea18ee5e2e5c114d131da8949cc7a54bb"}, + {file = "hstspreload-2023.1.1.tar.gz", hash = "sha256:b2330a88b3fe3344c9eb431257e1ff3ae06c3bc2ff87ca686a5f253e2881a6c1"}, +] [[package]] name = "httpcore" @@ -243,6 +525,10 @@ description = "A minimal low-level HTTP client." category = "main" optional = false python-versions = ">=3.6" +files = [ + {file = "httpcore-0.9.1-py3-none-any.whl", hash = "sha256:9850fe97a166a794d7e920590d5ec49a05488884c9fc8b5dba8561effab0c2a0"}, + {file = "httpcore-0.9.1.tar.gz", hash = "sha256:ecc5949310d9dae4de64648a4ce529f86df1f232ce23dcfefe737c24d21dfbe9"}, +] [package.dependencies] h11 = ">=0.8,<0.10" @@ -256,6 +542,10 @@ description = "The next generation HTTP client." category = "main" optional = false python-versions = ">=3.6" +files = [ + {file = "httpx-0.13.3-py3-none-any.whl", hash = "sha256:32d930858eab677bc29a742aaa4f096de259f1c78c68a90ad11f5c3c04f08335"}, + {file = "httpx-0.13.3.tar.gz", hash = "sha256:3642bd13e90b80ba8a243a730275eb10a4c26ec96f5fc16b87e458d4ab21efae"}, +] [package.dependencies] certifi = "*" @@ -273,6 +563,10 @@ description = "HTTP/2 framing layer for Python" category = "main" optional = false python-versions = "*" +files = [ + {file = "hyperframe-5.2.0-py2.py3-none-any.whl", hash = "sha256:5187962cb16dcc078f23cb5a4b110098d546c3f41ff2d4038a9896893bbd0b40"}, + {file = "hyperframe-5.2.0.tar.gz", hash = "sha256:a9f5c17f2cc3c719b917c4f33ed1c61bd1f8dfac4b1bd23b7c80b3400971b41f"}, +] [[package]] name = "idna" @@ -281,22 +575,109 @@ description = "Internationalized Domain Names in Applications (IDNA)" category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +files = [ + {file = "idna-2.10-py2.py3-none-any.whl", hash = "sha256:b97d804b1e9b523befed77c48dacec60e6dcb0b5391d57af6a65a312a90648c0"}, + {file = "idna-2.10.tar.gz", hash = "sha256:b307872f855b18632ce0c21c5e45be78c0ea7ae4c15c828c20788b26921eb3f6"}, +] [[package]] name = "iniconfig" -version = "1.1.1" -description = "iniconfig: brain-dead simple config-ini parsing" +version = "2.0.0" +description = "brain-dead simple config-ini parsing" category = "dev" optional = false -python-versions = "*" +python-versions = ">=3.7" +files = [ + {file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"}, + {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, +] [[package]] name = "lxml" -version = "4.9.1" +version = "4.9.2" description = "Powerful and Pythonic XML processing library combining libxml2/libxslt with the ElementTree API." category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, != 3.4.*" +files = [ + {file = "lxml-4.9.2-cp27-cp27m-macosx_10_15_x86_64.whl", hash = "sha256:76cf573e5a365e790396a5cc2b909812633409306c6531a6877c59061e42c4f2"}, + {file = "lxml-4.9.2-cp27-cp27m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b1f42b6921d0e81b1bcb5e395bc091a70f41c4d4e55ba99c6da2b31626c44892"}, + {file = "lxml-4.9.2-cp27-cp27m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:9f102706d0ca011de571de32c3247c6476b55bb6bc65a20f682f000b07a4852a"}, + {file = "lxml-4.9.2-cp27-cp27m-win32.whl", hash = "sha256:8d0b4612b66ff5d62d03bcaa043bb018f74dfea51184e53f067e6fdcba4bd8de"}, + {file = "lxml-4.9.2-cp27-cp27m-win_amd64.whl", hash = "sha256:4c8f293f14abc8fd3e8e01c5bd86e6ed0b6ef71936ded5bf10fe7a5efefbaca3"}, + {file = "lxml-4.9.2-cp27-cp27mu-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2899456259589aa38bfb018c364d6ae7b53c5c22d8e27d0ec7609c2a1ff78b50"}, + {file = "lxml-4.9.2-cp27-cp27mu-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:6749649eecd6a9871cae297bffa4ee76f90b4504a2a2ab528d9ebe912b101975"}, + {file = "lxml-4.9.2-cp310-cp310-macosx_10_15_x86_64.whl", hash = "sha256:a08cff61517ee26cb56f1e949cca38caabe9ea9fbb4b1e10a805dc39844b7d5c"}, + {file = "lxml-4.9.2-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:85cabf64adec449132e55616e7ca3e1000ab449d1d0f9d7f83146ed5bdcb6d8a"}, + {file = "lxml-4.9.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:8340225bd5e7a701c0fa98284c849c9b9fc9238abf53a0ebd90900f25d39a4e4"}, + {file = "lxml-4.9.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:1ab8f1f932e8f82355e75dda5413a57612c6ea448069d4fb2e217e9a4bed13d4"}, + {file = "lxml-4.9.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:699a9af7dffaf67deeae27b2112aa06b41c370d5e7633e0ee0aea2e0b6c211f7"}, + {file = "lxml-4.9.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:b9cc34af337a97d470040f99ba4282f6e6bac88407d021688a5d585e44a23184"}, + {file = "lxml-4.9.2-cp310-cp310-win32.whl", hash = "sha256:d02a5399126a53492415d4906ab0ad0375a5456cc05c3fc0fc4ca11771745cda"}, + {file = "lxml-4.9.2-cp310-cp310-win_amd64.whl", hash = "sha256:a38486985ca49cfa574a507e7a2215c0c780fd1778bb6290c21193b7211702ab"}, + {file = "lxml-4.9.2-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:c83203addf554215463b59f6399835201999b5e48019dc17f182ed5ad87205c9"}, + {file = "lxml-4.9.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:2a87fa548561d2f4643c99cd13131acb607ddabb70682dcf1dff5f71f781a4bf"}, + {file = "lxml-4.9.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:d6b430a9938a5a5d85fc107d852262ddcd48602c120e3dbb02137c83d212b380"}, + {file = "lxml-4.9.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:3efea981d956a6f7173b4659849f55081867cf897e719f57383698af6f618a92"}, + {file = "lxml-4.9.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:df0623dcf9668ad0445e0558a21211d4e9a149ea8f5666917c8eeec515f0a6d1"}, + {file = "lxml-4.9.2-cp311-cp311-win32.whl", hash = "sha256:da248f93f0418a9e9d94b0080d7ebc407a9a5e6d0b57bb30db9b5cc28de1ad33"}, + {file = "lxml-4.9.2-cp311-cp311-win_amd64.whl", hash = "sha256:3818b8e2c4b5148567e1b09ce739006acfaa44ce3156f8cbbc11062994b8e8dd"}, + {file = "lxml-4.9.2-cp35-cp35m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ca989b91cf3a3ba28930a9fc1e9aeafc2a395448641df1f387a2d394638943b0"}, + {file = "lxml-4.9.2-cp35-cp35m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:822068f85e12a6e292803e112ab876bc03ed1f03dddb80154c395f891ca6b31e"}, + {file = "lxml-4.9.2-cp35-cp35m-win32.whl", hash = "sha256:be7292c55101e22f2a3d4d8913944cbea71eea90792bf914add27454a13905df"}, + {file = "lxml-4.9.2-cp35-cp35m-win_amd64.whl", hash = "sha256:998c7c41910666d2976928c38ea96a70d1aa43be6fe502f21a651e17483a43c5"}, + {file = "lxml-4.9.2-cp36-cp36m-macosx_10_15_x86_64.whl", hash = "sha256:b26a29f0b7fc6f0897f043ca366142d2b609dc60756ee6e4e90b5f762c6adc53"}, + {file = "lxml-4.9.2-cp36-cp36m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:ab323679b8b3030000f2be63e22cdeea5b47ee0abd2d6a1dc0c8103ddaa56cd7"}, + {file = "lxml-4.9.2-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:689bb688a1db722485e4610a503e3e9210dcc20c520b45ac8f7533c837be76fe"}, + {file = "lxml-4.9.2-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:f49e52d174375a7def9915c9f06ec4e569d235ad428f70751765f48d5926678c"}, + {file = "lxml-4.9.2-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:36c3c175d34652a35475a73762b545f4527aec044910a651d2bf50de9c3352b1"}, + {file = "lxml-4.9.2-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:a35f8b7fa99f90dd2f5dc5a9fa12332642f087a7641289ca6c40d6e1a2637d8e"}, + {file = "lxml-4.9.2-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:58bfa3aa19ca4c0f28c5dde0ff56c520fbac6f0daf4fac66ed4c8d2fb7f22e74"}, + {file = "lxml-4.9.2-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:bc718cd47b765e790eecb74d044cc8d37d58562f6c314ee9484df26276d36a38"}, + {file = "lxml-4.9.2-cp36-cp36m-win32.whl", hash = "sha256:d5bf6545cd27aaa8a13033ce56354ed9e25ab0e4ac3b5392b763d8d04b08e0c5"}, + {file = "lxml-4.9.2-cp36-cp36m-win_amd64.whl", hash = "sha256:3ab9fa9d6dc2a7f29d7affdf3edebf6ece6fb28a6d80b14c3b2fb9d39b9322c3"}, + {file = "lxml-4.9.2-cp37-cp37m-macosx_10_15_x86_64.whl", hash = "sha256:05ca3f6abf5cf78fe053da9b1166e062ade3fa5d4f92b4ed688127ea7d7b1d03"}, + {file = "lxml-4.9.2-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:a5da296eb617d18e497bcf0a5c528f5d3b18dadb3619fbdadf4ed2356ef8d941"}, + {file = "lxml-4.9.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:04876580c050a8c5341d706dd464ff04fd597095cc8c023252566a8826505726"}, + {file = "lxml-4.9.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:c9ec3eaf616d67db0764b3bb983962b4f385a1f08304fd30c7283954e6a7869b"}, + {file = "lxml-4.9.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2a29ba94d065945944016b6b74e538bdb1751a1db6ffb80c9d3c2e40d6fa9894"}, + {file = "lxml-4.9.2-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:a82d05da00a58b8e4c0008edbc8a4b6ec5a4bc1e2ee0fb6ed157cf634ed7fa45"}, + {file = "lxml-4.9.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:223f4232855ade399bd409331e6ca70fb5578efef22cf4069a6090acc0f53c0e"}, + {file = "lxml-4.9.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d17bc7c2ccf49c478c5bdd447594e82692c74222698cfc9b5daae7ae7e90743b"}, + {file = "lxml-4.9.2-cp37-cp37m-win32.whl", hash = "sha256:b64d891da92e232c36976c80ed7ebb383e3f148489796d8d31a5b6a677825efe"}, + {file = "lxml-4.9.2-cp37-cp37m-win_amd64.whl", hash = "sha256:a0a336d6d3e8b234a3aae3c674873d8f0e720b76bc1d9416866c41cd9500ffb9"}, + {file = "lxml-4.9.2-cp38-cp38-macosx_10_15_x86_64.whl", hash = "sha256:da4dd7c9c50c059aba52b3524f84d7de956f7fef88f0bafcf4ad7dde94a064e8"}, + {file = "lxml-4.9.2-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:821b7f59b99551c69c85a6039c65b75f5683bdc63270fec660f75da67469ca24"}, + {file = "lxml-4.9.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:e5168986b90a8d1f2f9dc1b841467c74221bd752537b99761a93d2d981e04889"}, + {file = "lxml-4.9.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:8e20cb5a47247e383cf4ff523205060991021233ebd6f924bca927fcf25cf86f"}, + {file = "lxml-4.9.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:13598ecfbd2e86ea7ae45ec28a2a54fb87ee9b9fdb0f6d343297d8e548392c03"}, + {file = "lxml-4.9.2-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:880bbbcbe2fca64e2f4d8e04db47bcdf504936fa2b33933efd945e1b429bea8c"}, + {file = "lxml-4.9.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:7d2278d59425777cfcb19735018d897ca8303abe67cc735f9f97177ceff8027f"}, + {file = "lxml-4.9.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:5344a43228767f53a9df6e5b253f8cdca7dfc7b7aeae52551958192f56d98457"}, + {file = "lxml-4.9.2-cp38-cp38-win32.whl", hash = "sha256:925073b2fe14ab9b87e73f9a5fde6ce6392da430f3004d8b72cc86f746f5163b"}, + {file = "lxml-4.9.2-cp38-cp38-win_amd64.whl", hash = "sha256:9b22c5c66f67ae00c0199f6055705bc3eb3fcb08d03d2ec4059a2b1b25ed48d7"}, + {file = "lxml-4.9.2-cp39-cp39-macosx_10_15_x86_64.whl", hash = "sha256:5f50a1c177e2fa3ee0667a5ab79fdc6b23086bc8b589d90b93b4bd17eb0e64d1"}, + {file = "lxml-4.9.2-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:090c6543d3696cbe15b4ac6e175e576bcc3f1ccfbba970061b7300b0c15a2140"}, + {file = "lxml-4.9.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:63da2ccc0857c311d764e7d3d90f429c252e83b52d1f8f1d1fe55be26827d1f4"}, + {file = "lxml-4.9.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:5b4545b8a40478183ac06c073e81a5ce4cf01bf1734962577cf2bb569a5b3bbf"}, + {file = "lxml-4.9.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2e430cd2824f05f2d4f687701144556646bae8f249fd60aa1e4c768ba7018947"}, + {file = "lxml-4.9.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:6804daeb7ef69e7b36f76caddb85cccd63d0c56dedb47555d2fc969e2af6a1a5"}, + {file = "lxml-4.9.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:a6e441a86553c310258aca15d1c05903aaf4965b23f3bc2d55f200804e005ee5"}, + {file = "lxml-4.9.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ca34efc80a29351897e18888c71c6aca4a359247c87e0b1c7ada14f0ab0c0fb2"}, + {file = "lxml-4.9.2-cp39-cp39-win32.whl", hash = "sha256:6b418afe5df18233fc6b6093deb82a32895b6bb0b1155c2cdb05203f583053f1"}, + {file = "lxml-4.9.2-cp39-cp39-win_amd64.whl", hash = "sha256:f1496ea22ca2c830cbcbd473de8f114a320da308438ae65abad6bab7867fe38f"}, + {file = "lxml-4.9.2-pp37-pypy37_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:b264171e3143d842ded311b7dccd46ff9ef34247129ff5bf5066123c55c2431c"}, + {file = "lxml-4.9.2-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:0dc313ef231edf866912e9d8f5a042ddab56c752619e92dfd3a2c277e6a7299a"}, + {file = "lxml-4.9.2-pp38-pypy38_pp73-macosx_10_15_x86_64.whl", hash = "sha256:16efd54337136e8cd72fb9485c368d91d77a47ee2d42b057564aae201257d419"}, + {file = "lxml-4.9.2-pp38-pypy38_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:0f2b1e0d79180f344ff9f321327b005ca043a50ece8713de61d1cb383fb8ac05"}, + {file = "lxml-4.9.2-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:7b770ed79542ed52c519119473898198761d78beb24b107acf3ad65deae61f1f"}, + {file = "lxml-4.9.2-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:efa29c2fe6b4fdd32e8ef81c1528506895eca86e1d8c4657fda04c9b3786ddf9"}, + {file = "lxml-4.9.2-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:7e91ee82f4199af8c43d8158024cbdff3d931df350252288f0d4ce656df7f3b5"}, + {file = "lxml-4.9.2-pp39-pypy39_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:b23e19989c355ca854276178a0463951a653309fb8e57ce674497f2d9f208746"}, + {file = "lxml-4.9.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:01d36c05f4afb8f7c20fd9ed5badca32a2029b93b1750f571ccc0b142531caf7"}, + {file = "lxml-4.9.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:7b515674acfdcadb0eb5d00d8a709868173acece5cb0be3dd165950cbfdf5409"}, + {file = "lxml-4.9.2.tar.gz", hash = "sha256:2455cfaeb7ac70338b3257f41e21f0724f4b5b0c0e7702da67ee6c3640835b67"}, +] [package.extras] cssselect = ["cssselect (>=0.7)"] @@ -306,23 +687,105 @@ source = ["Cython (>=0.29.7)"] [[package]] name = "mpmath" -version = "1.2.1" +version = "1.3.0" description = "Python library for arbitrary-precision floating-point arithmetic" category = "main" optional = false python-versions = "*" +files = [ + {file = "mpmath-1.3.0-py3-none-any.whl", hash = "sha256:a0b2b9fe80bbcd81a6647ff13108738cfb482d481d826cc0e02f5b35e5c88d2c"}, + {file = "mpmath-1.3.0.tar.gz", hash = "sha256:7a28eb2a9774d00c7bc92411c19a89209d5da7c4c9a9e227be8330a23a25b91f"}, +] [package.extras] develop = ["codecov", "pycodestyle", "pytest (>=4.6)", "pytest-cov", "wheel"] +docs = ["sphinx"] +gmpy = ["gmpy2 (>=2.1.0a4)"] tests = ["pytest (>=4.6)"] [[package]] name = "multidict" -version = "6.0.2" +version = "6.0.4" description = "multidict implementation" category = "main" optional = false python-versions = ">=3.7" +files = [ + {file = "multidict-6.0.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:0b1a97283e0c85772d613878028fec909f003993e1007eafa715b24b377cb9b8"}, + {file = "multidict-6.0.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:eeb6dcc05e911516ae3d1f207d4b0520d07f54484c49dfc294d6e7d63b734171"}, + {file = "multidict-6.0.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d6d635d5209b82a3492508cf5b365f3446afb65ae7ebd755e70e18f287b0adf7"}, + {file = "multidict-6.0.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c048099e4c9e9d615545e2001d3d8a4380bd403e1a0578734e0d31703d1b0c0b"}, + {file = "multidict-6.0.4-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ea20853c6dbbb53ed34cb4d080382169b6f4554d394015f1bef35e881bf83547"}, + {file = "multidict-6.0.4-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:16d232d4e5396c2efbbf4f6d4df89bfa905eb0d4dc5b3549d872ab898451f569"}, + {file = "multidict-6.0.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:36c63aaa167f6c6b04ef2c85704e93af16c11d20de1d133e39de6a0e84582a93"}, + {file = "multidict-6.0.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:64bdf1086b6043bf519869678f5f2757f473dee970d7abf6da91ec00acb9cb98"}, + {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:43644e38f42e3af682690876cff722d301ac585c5b9e1eacc013b7a3f7b696a0"}, + {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:7582a1d1030e15422262de9f58711774e02fa80df0d1578995c76214f6954988"}, + {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:ddff9c4e225a63a5afab9dd15590432c22e8057e1a9a13d28ed128ecf047bbdc"}, + {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:ee2a1ece51b9b9e7752e742cfb661d2a29e7bcdba2d27e66e28a99f1890e4fa0"}, + {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a2e4369eb3d47d2034032a26c7a80fcb21a2cb22e1173d761a162f11e562caa5"}, + {file = "multidict-6.0.4-cp310-cp310-win32.whl", hash = "sha256:574b7eae1ab267e5f8285f0fe881f17efe4b98c39a40858247720935b893bba8"}, + {file = "multidict-6.0.4-cp310-cp310-win_amd64.whl", hash = "sha256:4dcbb0906e38440fa3e325df2359ac6cb043df8e58c965bb45f4e406ecb162cc"}, + {file = "multidict-6.0.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:0dfad7a5a1e39c53ed00d2dd0c2e36aed4650936dc18fd9a1826a5ae1cad6f03"}, + {file = "multidict-6.0.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:64da238a09d6039e3bd39bb3aee9c21a5e34f28bfa5aa22518581f910ff94af3"}, + {file = "multidict-6.0.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ff959bee35038c4624250473988b24f846cbeb2c6639de3602c073f10410ceba"}, + {file = "multidict-6.0.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:01a3a55bd90018c9c080fbb0b9f4891db37d148a0a18722b42f94694f8b6d4c9"}, + {file = "multidict-6.0.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c5cb09abb18c1ea940fb99360ea0396f34d46566f157122c92dfa069d3e0e982"}, + {file = "multidict-6.0.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:666daae833559deb2d609afa4490b85830ab0dfca811a98b70a205621a6109fe"}, + {file = "multidict-6.0.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:11bdf3f5e1518b24530b8241529d2050014c884cf18b6fc69c0c2b30ca248710"}, + {file = "multidict-6.0.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7d18748f2d30f94f498e852c67d61261c643b349b9d2a581131725595c45ec6c"}, + {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:458f37be2d9e4c95e2d8866a851663cbc76e865b78395090786f6cd9b3bbf4f4"}, + {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:b1a2eeedcead3a41694130495593a559a668f382eee0727352b9a41e1c45759a"}, + {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:7d6ae9d593ef8641544d6263c7fa6408cc90370c8cb2bbb65f8d43e5b0351d9c"}, + {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:5979b5632c3e3534e42ca6ff856bb24b2e3071b37861c2c727ce220d80eee9ed"}, + {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:dcfe792765fab89c365123c81046ad4103fcabbc4f56d1c1997e6715e8015461"}, + {file = "multidict-6.0.4-cp311-cp311-win32.whl", hash = "sha256:3601a3cece3819534b11d4efc1eb76047488fddd0c85a3948099d5da4d504636"}, + {file = "multidict-6.0.4-cp311-cp311-win_amd64.whl", hash = "sha256:81a4f0b34bd92df3da93315c6a59034df95866014ac08535fc819f043bfd51f0"}, + {file = "multidict-6.0.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:67040058f37a2a51ed8ea8f6b0e6ee5bd78ca67f169ce6122f3e2ec80dfe9b78"}, + {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:853888594621e6604c978ce2a0444a1e6e70c8d253ab65ba11657659dcc9100f"}, + {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:39ff62e7d0f26c248b15e364517a72932a611a9b75f35b45be078d81bdb86603"}, + {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:af048912e045a2dc732847d33821a9d84ba553f5c5f028adbd364dd4765092ac"}, + {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b1e8b901e607795ec06c9e42530788c45ac21ef3aaa11dbd0c69de543bfb79a9"}, + {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:62501642008a8b9871ddfccbf83e4222cf8ac0d5aeedf73da36153ef2ec222d2"}, + {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:99b76c052e9f1bc0721f7541e5e8c05db3941eb9ebe7b8553c625ef88d6eefde"}, + {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:509eac6cf09c794aa27bcacfd4d62c885cce62bef7b2c3e8b2e49d365b5003fe"}, + {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:21a12c4eb6ddc9952c415f24eef97e3e55ba3af61f67c7bc388dcdec1404a067"}, + {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:5cad9430ab3e2e4fa4a2ef4450f548768400a2ac635841bc2a56a2052cdbeb87"}, + {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:ab55edc2e84460694295f401215f4a58597f8f7c9466faec545093045476327d"}, + {file = "multidict-6.0.4-cp37-cp37m-win32.whl", hash = "sha256:5a4dcf02b908c3b8b17a45fb0f15b695bf117a67b76b7ad18b73cf8e92608775"}, + {file = "multidict-6.0.4-cp37-cp37m-win_amd64.whl", hash = "sha256:6ed5f161328b7df384d71b07317f4d8656434e34591f20552c7bcef27b0ab88e"}, + {file = "multidict-6.0.4-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5fc1b16f586f049820c5c5b17bb4ee7583092fa0d1c4e28b5239181ff9532e0c"}, + {file = "multidict-6.0.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1502e24330eb681bdaa3eb70d6358e818e8e8f908a22a1851dfd4e15bc2f8161"}, + {file = "multidict-6.0.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:b692f419760c0e65d060959df05f2a531945af31fda0c8a3b3195d4efd06de11"}, + {file = "multidict-6.0.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45e1ecb0379bfaab5eef059f50115b54571acfbe422a14f668fc8c27ba410e7e"}, + {file = "multidict-6.0.4-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ddd3915998d93fbcd2566ddf9cf62cdb35c9e093075f862935573d265cf8f65d"}, + {file = "multidict-6.0.4-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:59d43b61c59d82f2effb39a93c48b845efe23a3852d201ed2d24ba830d0b4cf2"}, + {file = "multidict-6.0.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cc8e1d0c705233c5dd0c5e6460fbad7827d5d36f310a0fadfd45cc3029762258"}, + {file = "multidict-6.0.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d6aa0418fcc838522256761b3415822626f866758ee0bc6632c9486b179d0b52"}, + {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:6748717bb10339c4760c1e63da040f5f29f5ed6e59d76daee30305894069a660"}, + {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:4d1a3d7ef5e96b1c9e92f973e43aa5e5b96c659c9bc3124acbbd81b0b9c8a951"}, + {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:4372381634485bec7e46718edc71528024fcdc6f835baefe517b34a33c731d60"}, + {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:fc35cb4676846ef752816d5be2193a1e8367b4c1397b74a565a9d0389c433a1d"}, + {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:4b9d9e4e2b37daddb5c23ea33a3417901fa7c7b3dee2d855f63ee67a0b21e5b1"}, + {file = "multidict-6.0.4-cp38-cp38-win32.whl", hash = "sha256:e41b7e2b59679edfa309e8db64fdf22399eec4b0b24694e1b2104fb789207779"}, + {file = "multidict-6.0.4-cp38-cp38-win_amd64.whl", hash = "sha256:d6c254ba6e45d8e72739281ebc46ea5eb5f101234f3ce171f0e9f5cc86991480"}, + {file = "multidict-6.0.4-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:16ab77bbeb596e14212e7bab8429f24c1579234a3a462105cda4a66904998664"}, + {file = "multidict-6.0.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:bc779e9e6f7fda81b3f9aa58e3a6091d49ad528b11ed19f6621408806204ad35"}, + {file = "multidict-6.0.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4ceef517eca3e03c1cceb22030a3e39cb399ac86bff4e426d4fc6ae49052cc60"}, + {file = "multidict-6.0.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:281af09f488903fde97923c7744bb001a9b23b039a909460d0f14edc7bf59706"}, + {file = "multidict-6.0.4-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:52f2dffc8acaba9a2f27174c41c9e57f60b907bb9f096b36b1a1f3be71c6284d"}, + {file = "multidict-6.0.4-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b41156839806aecb3641f3208c0dafd3ac7775b9c4c422d82ee2a45c34ba81ca"}, + {file = "multidict-6.0.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d5e3fc56f88cc98ef8139255cf8cd63eb2c586531e43310ff859d6bb3a6b51f1"}, + {file = "multidict-6.0.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8316a77808c501004802f9beebde51c9f857054a0c871bd6da8280e718444449"}, + {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:f70b98cd94886b49d91170ef23ec5c0e8ebb6f242d734ed7ed677b24d50c82cf"}, + {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:bf6774e60d67a9efe02b3616fee22441d86fab4c6d335f9d2051d19d90a40063"}, + {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:e69924bfcdda39b722ef4d9aa762b2dd38e4632b3641b1d9a57ca9cd18f2f83a"}, + {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:6b181d8c23da913d4ff585afd1155a0e1194c0b50c54fcfe286f70cdaf2b7176"}, + {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:52509b5be062d9eafc8170e53026fbc54cf3b32759a23d07fd935fb04fc22d95"}, + {file = "multidict-6.0.4-cp39-cp39-win32.whl", hash = "sha256:27c523fbfbdfd19c6867af7346332b62b586eed663887392cff78d614f9ec313"}, + {file = "multidict-6.0.4-cp39-cp39-win_amd64.whl", hash = "sha256:33029f5734336aa0d4c0384525da0387ef89148dc7191aae00ca5fb23d7aafc2"}, + {file = "multidict-6.0.4.tar.gz", hash = "sha256:3666906492efb76453c0e7b97f2cf459b0682e7402c0489a95484965dbc1da49"}, +] [[package]] name = "mutagen" @@ -331,17 +794,49 @@ description = "read and write audio tags for many formats" category = "main" optional = false python-versions = ">=3.7" +files = [ + {file = "mutagen-1.46.0-py3-none-any.whl", hash = "sha256:8af0728aa2d5c3ee5a727e28d0627966641fddfe804c23eabb5926a4d770aed5"}, + {file = "mutagen-1.46.0.tar.gz", hash = "sha256:6e5f8ba84836b99fe60be5fb27f84be4ad919bbb6b49caa6ae81e70584b55e58"}, +] [[package]] name = "mypy" -version = "0.990" +version = "1.2.0" description = "Optional static typing for Python" category = "dev" optional = false python-versions = ">=3.7" +files = [ + {file = "mypy-1.2.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:701189408b460a2ff42b984e6bd45c3f41f0ac9f5f58b8873bbedc511900086d"}, + {file = "mypy-1.2.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fe91be1c51c90e2afe6827601ca14353bbf3953f343c2129fa1e247d55fd95ba"}, + {file = "mypy-1.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8d26b513225ffd3eacece727f4387bdce6469192ef029ca9dd469940158bc89e"}, + {file = "mypy-1.2.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:3a2d219775a120581a0ae8ca392b31f238d452729adbcb6892fa89688cb8306a"}, + {file = "mypy-1.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:2e93a8a553e0394b26c4ca683923b85a69f7ccdc0139e6acd1354cc884fe0128"}, + {file = "mypy-1.2.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3efde4af6f2d3ccf58ae825495dbb8d74abd6d176ee686ce2ab19bd025273f41"}, + {file = "mypy-1.2.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:695c45cea7e8abb6f088a34a6034b1d273122e5530aeebb9c09626cea6dca4cb"}, + {file = "mypy-1.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d0e9464a0af6715852267bf29c9553e4555b61f5904a4fc538547a4d67617937"}, + {file = "mypy-1.2.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:8293a216e902ac12779eb7a08f2bc39ec6c878d7c6025aa59464e0c4c16f7eb9"}, + {file = "mypy-1.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:f46af8d162f3d470d8ffc997aaf7a269996d205f9d746124a179d3abe05ac602"}, + {file = "mypy-1.2.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:031fc69c9a7e12bcc5660b74122ed84b3f1c505e762cc4296884096c6d8ee140"}, + {file = "mypy-1.2.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:390bc685ec209ada4e9d35068ac6988c60160b2b703072d2850457b62499e336"}, + {file = "mypy-1.2.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:4b41412df69ec06ab141808d12e0bf2823717b1c363bd77b4c0820feaa37249e"}, + {file = "mypy-1.2.0-cp37-cp37m-win_amd64.whl", hash = "sha256:4e4a682b3f2489d218751981639cffc4e281d548f9d517addfd5a2917ac78119"}, + {file = "mypy-1.2.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:a197ad3a774f8e74f21e428f0de7f60ad26a8d23437b69638aac2764d1e06a6a"}, + {file = "mypy-1.2.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:c9a084bce1061e55cdc0493a2ad890375af359c766b8ac311ac8120d3a472950"}, + {file = "mypy-1.2.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eaeaa0888b7f3ccb7bcd40b50497ca30923dba14f385bde4af78fac713d6d6f6"}, + {file = "mypy-1.2.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:bea55fc25b96c53affab852ad94bf111a3083bc1d8b0c76a61dd101d8a388cf5"}, + {file = "mypy-1.2.0-cp38-cp38-win_amd64.whl", hash = "sha256:4c8d8c6b80aa4a1689f2a179d31d86ae1367ea4a12855cc13aa3ba24bb36b2d8"}, + {file = "mypy-1.2.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:70894c5345bea98321a2fe84df35f43ee7bb0feec117a71420c60459fc3e1eed"}, + {file = "mypy-1.2.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4a99fe1768925e4a139aace8f3fb66db3576ee1c30b9c0f70f744ead7e329c9f"}, + {file = "mypy-1.2.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:023fe9e618182ca6317ae89833ba422c411469156b690fde6a315ad10695a521"}, + {file = "mypy-1.2.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:4d19f1a239d59f10fdc31263d48b7937c585810288376671eaf75380b074f238"}, + {file = "mypy-1.2.0-cp39-cp39-win_amd64.whl", hash = "sha256:2de7babe398cb7a85ac7f1fd5c42f396c215ab3eff731b4d761d68d0f6a80f48"}, + {file = "mypy-1.2.0-py3-none-any.whl", hash = "sha256:d8e9187bfcd5ffedbe87403195e1fc340189a68463903c39e2b63307c9fa0394"}, + {file = "mypy-1.2.0.tar.gz", hash = "sha256:f70a40410d774ae23fcb4afbbeca652905a04de7948eaf0b1789c8d1426b72d1"}, +] [package.dependencies] -mypy-extensions = ">=0.4.3" +mypy-extensions = ">=1.0.0" tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} typing-extensions = ">=3.10" @@ -353,19 +848,53 @@ reports = ["lxml"] [[package]] name = "mypy-extensions" -version = "0.4.3" -description = "Experimental type system extensions for programs checked with the mypy typechecker." +version = "1.0.0" +description = "Type system extensions for programs checked with the mypy type checker." category = "dev" optional = false -python-versions = "*" +python-versions = ">=3.5" +files = [ + {file = "mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"}, + {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"}, +] [[package]] name = "numpy" -version = "1.23.4" -description = "NumPy is the fundamental package for array computing with Python." +version = "1.24.3" +description = "Fundamental package for array computing in Python" category = "main" optional = false python-versions = ">=3.8" +files = [ + {file = "numpy-1.24.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:3c1104d3c036fb81ab923f507536daedc718d0ad5a8707c6061cdfd6d184e570"}, + {file = "numpy-1.24.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:202de8f38fc4a45a3eea4b63e2f376e5f2dc64ef0fa692838e31a808520efaf7"}, + {file = "numpy-1.24.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8535303847b89aa6b0f00aa1dc62867b5a32923e4d1681a35b5eef2d9591a463"}, + {file = "numpy-1.24.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2d926b52ba1367f9acb76b0df6ed21f0b16a1ad87c6720a1121674e5cf63e2b6"}, + {file = "numpy-1.24.3-cp310-cp310-win32.whl", hash = "sha256:f21c442fdd2805e91799fbe044a7b999b8571bb0ab0f7850d0cb9641a687092b"}, + {file = "numpy-1.24.3-cp310-cp310-win_amd64.whl", hash = "sha256:ab5f23af8c16022663a652d3b25dcdc272ac3f83c3af4c02eb8b824e6b3ab9d7"}, + {file = "numpy-1.24.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:9a7721ec204d3a237225db3e194c25268faf92e19338a35f3a224469cb6039a3"}, + {file = "numpy-1.24.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d6cc757de514c00b24ae8cf5c876af2a7c3df189028d68c0cb4eaa9cd5afc2bf"}, + {file = "numpy-1.24.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:76e3f4e85fc5d4fd311f6e9b794d0c00e7002ec122be271f2019d63376f1d385"}, + {file = "numpy-1.24.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a1d3c026f57ceaad42f8231305d4653d5f05dc6332a730ae5c0bea3513de0950"}, + {file = "numpy-1.24.3-cp311-cp311-win32.whl", hash = "sha256:c91c4afd8abc3908e00a44b2672718905b8611503f7ff87390cc0ac3423fb096"}, + {file = "numpy-1.24.3-cp311-cp311-win_amd64.whl", hash = "sha256:5342cf6aad47943286afa6f1609cad9b4266a05e7f2ec408e2cf7aea7ff69d80"}, + {file = "numpy-1.24.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:7776ea65423ca6a15255ba1872d82d207bd1e09f6d0894ee4a64678dd2204078"}, + {file = "numpy-1.24.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:ae8d0be48d1b6ed82588934aaaa179875e7dc4f3d84da18d7eae6eb3f06c242c"}, + {file = "numpy-1.24.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ecde0f8adef7dfdec993fd54b0f78183051b6580f606111a6d789cd14c61ea0c"}, + {file = "numpy-1.24.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4749e053a29364d3452c034827102ee100986903263e89884922ef01a0a6fd2f"}, + {file = "numpy-1.24.3-cp38-cp38-win32.whl", hash = "sha256:d933fabd8f6a319e8530d0de4fcc2e6a61917e0b0c271fded460032db42a0fe4"}, + {file = "numpy-1.24.3-cp38-cp38-win_amd64.whl", hash = "sha256:56e48aec79ae238f6e4395886b5eaed058abb7231fb3361ddd7bfdf4eed54289"}, + {file = "numpy-1.24.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:4719d5aefb5189f50887773699eaf94e7d1e02bf36c1a9d353d9f46703758ca4"}, + {file = "numpy-1.24.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0ec87a7084caa559c36e0a2309e4ecb1baa03b687201d0a847c8b0ed476a7187"}, + {file = "numpy-1.24.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ea8282b9bcfe2b5e7d491d0bf7f3e2da29700cec05b49e64d6246923329f2b02"}, + {file = "numpy-1.24.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:210461d87fb02a84ef243cac5e814aad2b7f4be953b32cb53327bb49fd77fbb4"}, + {file = "numpy-1.24.3-cp39-cp39-win32.whl", hash = "sha256:784c6da1a07818491b0ffd63c6bbe5a33deaa0e25a20e1b3ea20cf0e43f8046c"}, + {file = "numpy-1.24.3-cp39-cp39-win_amd64.whl", hash = "sha256:d5036197ecae68d7f491fcdb4df90082b0d4960ca6599ba2659957aafced7c17"}, + {file = "numpy-1.24.3-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:352ee00c7f8387b44d19f4cada524586f07379c0d49270f87233983bc5087ca0"}, + {file = "numpy-1.24.3-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1a7d6acc2e7524c9955e5c903160aa4ea083736fde7e91276b0e5d98e6332812"}, + {file = "numpy-1.24.3-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:35400e6a8d102fd07c71ed7dcadd9eb62ee9a6e84ec159bd48c28235bbb0f8e4"}, + {file = "numpy-1.24.3.tar.gz", hash = "sha256:ab344f1bf21f140adab8e47fdbc7c35a477dc01408791f8ba00d018dd0bc5155"}, +] [[package]] name = "opencv-python" @@ -374,6 +903,15 @@ description = "Wrapper package for OpenCV python bindings." category = "main" optional = false python-versions = ">=3.6" +files = [ + {file = "opencv-python-4.6.0.66.tar.gz", hash = "sha256:c5bfae41ad4031e66bb10ec4a0a2ffd3e514d092652781e8b1ac98d1b59f1158"}, + {file = "opencv_python-4.6.0.66-cp36-abi3-macosx_10_15_x86_64.whl", hash = "sha256:e6e448b62afc95c5b58f97e87ef84699e6607fe5c58730a03301c52496005cae"}, + {file = "opencv_python-4.6.0.66-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5af8ba35a4fcb8913ffb86e92403e9a656a4bff4a645d196987468f0f8947875"}, + {file = "opencv_python-4.6.0.66-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dbdc84a9b4ea2cbae33861652d25093944b9959279200b7ae0badd32439f74de"}, + {file = "opencv_python-4.6.0.66-cp36-abi3-win32.whl", hash = "sha256:f482e78de6e7b0b060ff994ffd859bddc3f7f382bb2019ef157b0ea8ca8712f5"}, + {file = "opencv_python-4.6.0.66-cp36-abi3-win_amd64.whl", hash = "sha256:0dc82a3d8630c099d2f3ac1b1aabee164e8188db54a786abb7a4e27eba309440"}, + {file = "opencv_python-4.6.0.66-cp37-abi3-macosx_11_0_arm64.whl", hash = "sha256:6e32af22e3202748bd233ed8f538741876191863882eba44e332d1a34993165b"}, +] [package.dependencies] numpy = [ @@ -385,22 +923,27 @@ numpy = [ [[package]] name = "packaging" -version = "21.3" +version = "23.1" description = "Core utilities for Python packages" category = "dev" optional = false -python-versions = ">=3.6" - -[package.dependencies] -pyparsing = ">=2.0.2,<3.0.5 || >3.0.5" +python-versions = ">=3.7" +files = [ + {file = "packaging-23.1-py3-none-any.whl", hash = "sha256:994793af429502c4ea2ebf6bf664629d07c1a9fe974af92966e4b8d2df7edc61"}, + {file = "packaging-23.1.tar.gz", hash = "sha256:a392980d2b6cffa644431898be54b0045151319d1e7ec34f0cfed48767dd334f"}, +] [[package]] name = "pathspec" -version = "0.10.2" +version = "0.11.1" description = "Utility library for gitignore style pattern matching of file paths." category = "dev" optional = false python-versions = ">=3.7" +files = [ + {file = "pathspec-0.11.1-py3-none-any.whl", hash = "sha256:d8af70af76652554bd134c22b3e8a1cc46ed7d91edcdd721ef1a0c51a84a5293"}, + {file = "pathspec-0.11.1.tar.gz", hash = "sha256:2798de800fa92780e33acca925945e9a19a133b715067cf165b8866c15a31687"}, +] [[package]] name = "pillow" @@ -409,18 +952,65 @@ description = "Python Imaging Library (Fork)" category = "main" optional = false python-versions = ">=3.6" +files = [ + {file = "Pillow-8.4.0-cp310-cp310-macosx_10_10_universal2.whl", hash = "sha256:81f8d5c81e483a9442d72d182e1fb6dcb9723f289a57e8030811bac9ea3fef8d"}, + {file = "Pillow-8.4.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:3f97cfb1e5a392d75dd8b9fd274d205404729923840ca94ca45a0af57e13dbe6"}, + {file = "Pillow-8.4.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eb9fc393f3c61f9054e1ed26e6fe912c7321af2f41ff49d3f83d05bacf22cc78"}, + {file = "Pillow-8.4.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d82cdb63100ef5eedb8391732375e6d05993b765f72cb34311fab92103314649"}, + {file = "Pillow-8.4.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:62cc1afda735a8d109007164714e73771b499768b9bb5afcbbee9d0ff374b43f"}, + {file = "Pillow-8.4.0-cp310-cp310-win32.whl", hash = "sha256:e3dacecfbeec9a33e932f00c6cd7996e62f53ad46fbe677577394aaa90ee419a"}, + {file = "Pillow-8.4.0-cp310-cp310-win_amd64.whl", hash = "sha256:620582db2a85b2df5f8a82ddeb52116560d7e5e6b055095f04ad828d1b0baa39"}, + {file = "Pillow-8.4.0-cp36-cp36m-macosx_10_10_x86_64.whl", hash = "sha256:1bc723b434fbc4ab50bb68e11e93ce5fb69866ad621e3c2c9bdb0cd70e345f55"}, + {file = "Pillow-8.4.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:72cbcfd54df6caf85cc35264c77ede902452d6df41166010262374155947460c"}, + {file = "Pillow-8.4.0-cp36-cp36m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:70ad9e5c6cb9b8487280a02c0ad8a51581dcbbe8484ce058477692a27c151c0a"}, + {file = "Pillow-8.4.0-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:25a49dc2e2f74e65efaa32b153527fc5ac98508d502fa46e74fa4fd678ed6645"}, + {file = "Pillow-8.4.0-cp36-cp36m-win32.whl", hash = "sha256:93ce9e955cc95959df98505e4608ad98281fff037350d8c2671c9aa86bcf10a9"}, + {file = "Pillow-8.4.0-cp36-cp36m-win_amd64.whl", hash = "sha256:2e4440b8f00f504ee4b53fe30f4e381aae30b0568193be305256b1462216feff"}, + {file = "Pillow-8.4.0-cp37-cp37m-macosx_10_10_x86_64.whl", hash = "sha256:8c803ac3c28bbc53763e6825746f05cc407b20e4a69d0122e526a582e3b5e153"}, + {file = "Pillow-8.4.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c8a17b5d948f4ceeceb66384727dde11b240736fddeda54ca740b9b8b1556b29"}, + {file = "Pillow-8.4.0-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1394a6ad5abc838c5cd8a92c5a07535648cdf6d09e8e2d6df916dfa9ea86ead8"}, + {file = "Pillow-8.4.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:792e5c12376594bfcb986ebf3855aa4b7c225754e9a9521298e460e92fb4a488"}, + {file = "Pillow-8.4.0-cp37-cp37m-win32.whl", hash = "sha256:d99ec152570e4196772e7a8e4ba5320d2d27bf22fdf11743dd882936ed64305b"}, + {file = "Pillow-8.4.0-cp37-cp37m-win_amd64.whl", hash = "sha256:7b7017b61bbcdd7f6363aeceb881e23c46583739cb69a3ab39cb384f6ec82e5b"}, + {file = "Pillow-8.4.0-cp38-cp38-macosx_10_10_x86_64.whl", hash = "sha256:d89363f02658e253dbd171f7c3716a5d340a24ee82d38aab9183f7fdf0cdca49"}, + {file = "Pillow-8.4.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:0a0956fdc5defc34462bb1c765ee88d933239f9a94bc37d132004775241a7585"}, + {file = "Pillow-8.4.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5b7bb9de00197fb4261825c15551adf7605cf14a80badf1761d61e59da347779"}, + {file = "Pillow-8.4.0-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:72b9e656e340447f827885b8d7a15fc8c4e68d410dc2297ef6787eec0f0ea409"}, + {file = "Pillow-8.4.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a5a4532a12314149d8b4e4ad8ff09dde7427731fcfa5917ff16d0291f13609df"}, + {file = "Pillow-8.4.0-cp38-cp38-win32.whl", hash = "sha256:82aafa8d5eb68c8463b6e9baeb4f19043bb31fefc03eb7b216b51e6a9981ae09"}, + {file = "Pillow-8.4.0-cp38-cp38-win_amd64.whl", hash = "sha256:066f3999cb3b070a95c3652712cffa1a748cd02d60ad7b4e485c3748a04d9d76"}, + {file = "Pillow-8.4.0-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:5503c86916d27c2e101b7f71c2ae2cddba01a2cf55b8395b0255fd33fa4d1f1a"}, + {file = "Pillow-8.4.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4acc0985ddf39d1bc969a9220b51d94ed51695d455c228d8ac29fcdb25810e6e"}, + {file = "Pillow-8.4.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0b052a619a8bfcf26bd8b3f48f45283f9e977890263e4571f2393ed8898d331b"}, + {file = "Pillow-8.4.0-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:493cb4e415f44cd601fcec11c99836f707bb714ab03f5ed46ac25713baf0ff20"}, + {file = "Pillow-8.4.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b8831cb7332eda5dc89b21a7bce7ef6ad305548820595033a4b03cf3091235ed"}, + {file = "Pillow-8.4.0-cp39-cp39-win32.whl", hash = "sha256:5e9ac5f66616b87d4da618a20ab0a38324dbe88d8a39b55be8964eb520021e02"}, + {file = "Pillow-8.4.0-cp39-cp39-win_amd64.whl", hash = "sha256:3eb1ce5f65908556c2d8685a8f0a6e989d887ec4057326f6c22b24e8a172c66b"}, + {file = "Pillow-8.4.0-pp36-pypy36_pp73-macosx_10_10_x86_64.whl", hash = "sha256:ddc4d832a0f0b4c52fff973a0d44b6c99839a9d016fe4e6a1cb8f3eea96479c2"}, + {file = "Pillow-8.4.0-pp36-pypy36_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9a3e5ddc44c14042f0844b8cf7d2cd455f6cc80fd7f5eefbe657292cf601d9ad"}, + {file = "Pillow-8.4.0-pp36-pypy36_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c70e94281588ef053ae8998039610dbd71bc509e4acbc77ab59d7d2937b10698"}, + {file = "Pillow-8.4.0-pp37-pypy37_pp73-macosx_10_10_x86_64.whl", hash = "sha256:3862b7256046fcd950618ed22d1d60b842e3a40a48236a5498746f21189afbbc"}, + {file = "Pillow-8.4.0-pp37-pypy37_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a4901622493f88b1a29bd30ec1a2f683782e57c3c16a2dbc7f2595ba01f639df"}, + {file = "Pillow-8.4.0-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:84c471a734240653a0ec91dec0996696eea227eafe72a33bd06c92697728046b"}, + {file = "Pillow-8.4.0-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:244cf3b97802c34c41905d22810846802a3329ddcb93ccc432870243211c79fc"}, + {file = "Pillow-8.4.0.tar.gz", hash = "sha256:b8e2f83c56e141920c39464b852de3719dfbfb6e3c99a2d8da0edf4fb33176ed"}, +] [[package]] name = "platformdirs" -version = "2.5.4" +version = "3.5.1" description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." category = "dev" optional = false python-versions = ">=3.7" +files = [ + {file = "platformdirs-3.5.1-py3-none-any.whl", hash = "sha256:e2378146f1964972c03c085bb5662ae80b2b8c06226c54b2ff4aa9483e8a13a5"}, + {file = "platformdirs-3.5.1.tar.gz", hash = "sha256:412dae91f52a6f84830f39a8078cecd0e866cb72294a5c66808e74d5e88d251f"}, +] [package.extras] -docs = ["furo (>=2022.9.29)", "proselint (>=0.13)", "sphinx (>=5.3)", "sphinx-autodoc-typehints (>=1.19.4)"] -test = ["appdirs (==1.4.4)", "pytest (>=7.2)", "pytest-cov (>=4)", "pytest-mock (>=3.10)"] +docs = ["furo (>=2023.3.27)", "proselint (>=0.13)", "sphinx (>=6.2.1)", "sphinx-autodoc-typehints (>=1.23,!=1.23.4)"] +test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.3.1)", "pytest-cov (>=4)", "pytest-mock (>=3.10)"] [[package]] name = "pluggy" @@ -429,6 +1019,10 @@ description = "plugin and hook calling mechanisms for python" category = "dev" optional = false python-versions = ">=3.6" +files = [ + {file = "pluggy-1.0.0-py2.py3-none-any.whl", hash = "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"}, + {file = "pluggy-1.0.0.tar.gz", hash = "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159"}, +] [package.extras] dev = ["pre-commit", "tox"] @@ -441,25 +1035,102 @@ description = "C parser in Python" category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +files = [ + {file = "pycparser-2.21-py2.py3-none-any.whl", hash = "sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9"}, + {file = "pycparser-2.21.tar.gz", hash = "sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206"}, +] [[package]] name = "pycryptodomex" -version = "3.15.0" +version = "3.17" description = "Cryptographic library for Python" category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +files = [ + {file = "pycryptodomex-3.17-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:12056c38e49d972f9c553a3d598425f8a1c1d35b2e4330f89d5ff1ffb70de041"}, + {file = "pycryptodomex-3.17-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:ab33c2d9f275e05e235dbca1063753b5346af4a5cac34a51fa0da0d4edfb21d7"}, + {file = "pycryptodomex-3.17-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:caa937ff29d07a665dfcfd7a84f0d4207b2ebf483362fa9054041d67fdfacc20"}, + {file = "pycryptodomex-3.17-cp27-cp27m-manylinux2014_aarch64.whl", hash = "sha256:db23d7341e21b273d2440ec6faf6c8b1ca95c8894da612e165be0b89a8688340"}, + {file = "pycryptodomex-3.17-cp27-cp27m-musllinux_1_1_aarch64.whl", hash = "sha256:f854c8476512cebe6a8681cc4789e4fcff6019c17baa0fd72b459155dc605ab4"}, + {file = "pycryptodomex-3.17-cp27-cp27m-win32.whl", hash = "sha256:a57e3257bacd719769110f1f70dd901c5b6955e9596ad403af11a3e6e7e3311c"}, + {file = "pycryptodomex-3.17-cp27-cp27m-win_amd64.whl", hash = "sha256:d38ab9e53b1c09608ba2d9b8b888f1e75d6f66e2787e437adb1fecbffec6b112"}, + {file = "pycryptodomex-3.17-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:3c2516b42437ae6c7a29ef3ddc73c8d4714e7b6df995b76be4695bbe4b3b5cd2"}, + {file = "pycryptodomex-3.17-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:5c23482860302d0d9883404eaaa54b0615eefa5274f70529703e2c43cc571827"}, + {file = "pycryptodomex-3.17-cp27-cp27mu-manylinux2014_aarch64.whl", hash = "sha256:7a8dc3ee7a99aae202a4db52de5a08aa4d01831eb403c4d21da04ec2f79810db"}, + {file = "pycryptodomex-3.17-cp27-cp27mu-musllinux_1_1_aarch64.whl", hash = "sha256:7cc28dd33f1f3662d6da28ead4f9891035f63f49d30267d3b41194c8778997c8"}, + {file = "pycryptodomex-3.17-cp35-abi3-macosx_10_9_universal2.whl", hash = "sha256:2d4d395f109faba34067a08de36304e846c791808524614c731431ee048fe70a"}, + {file = "pycryptodomex-3.17-cp35-abi3-macosx_10_9_x86_64.whl", hash = "sha256:55eed98b4150a744920597c81b3965b632038781bab8a08a12ea1d004213c600"}, + {file = "pycryptodomex-3.17-cp35-abi3-manylinux2014_aarch64.whl", hash = "sha256:7fa0b52df90343fafe319257b31d909be1d2e8852277fb0376ba89d26d2921db"}, + {file = "pycryptodomex-3.17-cp35-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:78f0ddd4adc64baa39b416f3637aaf99f45acb0bcdc16706f0cc7ebfc6f10109"}, + {file = "pycryptodomex-3.17-cp35-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a4fa037078e92c7cc49f6789a8bac3de06856740bb2038d05f2d9a2e4b165d59"}, + {file = "pycryptodomex-3.17-cp35-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:88b0d5bb87eaf2a31e8a759302b89cf30c97f2f8ca7d83b8c9208abe8acb447a"}, + {file = "pycryptodomex-3.17-cp35-abi3-musllinux_1_1_i686.whl", hash = "sha256:6feedf4b0e36b395329b4186a805f60f900129cdf0170e120ecabbfcb763995d"}, + {file = "pycryptodomex-3.17-cp35-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:7a6651a07f67c28b6e978d63aa3a3fccea0feefed9a8453af3f7421a758461b7"}, + {file = "pycryptodomex-3.17-cp35-abi3-win32.whl", hash = "sha256:32e764322e902bbfac49ca1446604d2839381bbbdd5a57920c9daaf2e0b778df"}, + {file = "pycryptodomex-3.17-cp35-abi3-win_amd64.whl", hash = "sha256:4b51e826f0a04d832eda0790bbd0665d9bfe73e5a4d8ea93b6a9b38beeebe935"}, + {file = "pycryptodomex-3.17-pp27-pypy_73-macosx_10_9_x86_64.whl", hash = "sha256:d4cf0128da167562c49b0e034f09e9cedd733997354f2314837c2fa461c87bb1"}, + {file = "pycryptodomex-3.17-pp27-pypy_73-manylinux2010_x86_64.whl", hash = "sha256:c92537b596bd5bffb82f8964cabb9fef1bca8a28a9e0a69ffd3ec92a4a7ad41b"}, + {file = "pycryptodomex-3.17-pp27-pypy_73-win32.whl", hash = "sha256:599bb4ae4bbd614ca05f49bd4e672b7a250b80b13ae1238f05fd0f09d87ed80a"}, + {file = "pycryptodomex-3.17-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:4c4674f4b040321055c596aac926d12f7f6859dfe98cd12f4d9453b43ab6adc8"}, + {file = "pycryptodomex-3.17-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:67a3648025e4ddb72d43addab764336ba2e670c8377dba5dd752e42285440d31"}, + {file = "pycryptodomex-3.17-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:40e8a11f578bd0851b02719c862d55d3ee18d906c8b68a9c09f8c564d6bb5b92"}, + {file = "pycryptodomex-3.17-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:23d83b610bd97704f0cd3acc48d99b76a15c8c1540d8665c94d514a49905bad7"}, + {file = "pycryptodomex-3.17-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:fd29d35ac80755e5c0a99d96b44fb9abbd7e871849581ea6a4cb826d24267537"}, + {file = "pycryptodomex-3.17-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:64b876d57cb894b31056ad8dd6a6ae1099b117ae07a3d39707221133490e5715"}, + {file = "pycryptodomex-3.17-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ee8bf4fdcad7d66beb744957db8717afc12d176e3fd9c5d106835133881a049b"}, + {file = "pycryptodomex-3.17-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:c84689c73358dfc23f9fdcff2cb9e7856e65e2ce3b5ed8ff630d4c9bdeb1867b"}, + {file = "pycryptodomex-3.17.tar.gz", hash = "sha256:0af93aad8d62e810247beedef0261c148790c52f3cd33643791cc6396dd217c1"}, +] [[package]] name = "pydantic" -version = "1.10.2" +version = "1.10.7" description = "Data validation and settings management using python type hints" category = "main" optional = false python-versions = ">=3.7" +files = [ + {file = "pydantic-1.10.7-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e79e999e539872e903767c417c897e729e015872040e56b96e67968c3b918b2d"}, + {file = "pydantic-1.10.7-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:01aea3a42c13f2602b7ecbbea484a98169fb568ebd9e247593ea05f01b884b2e"}, + {file = "pydantic-1.10.7-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:516f1ed9bc2406a0467dd777afc636c7091d71f214d5e413d64fef45174cfc7a"}, + {file = "pydantic-1.10.7-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ae150a63564929c675d7f2303008d88426a0add46efd76c3fc797cd71cb1b46f"}, + {file = "pydantic-1.10.7-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:ecbbc51391248116c0a055899e6c3e7ffbb11fb5e2a4cd6f2d0b93272118a209"}, + {file = "pydantic-1.10.7-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:f4a2b50e2b03d5776e7f21af73e2070e1b5c0d0df255a827e7c632962f8315af"}, + {file = "pydantic-1.10.7-cp310-cp310-win_amd64.whl", hash = "sha256:a7cd2251439988b413cb0a985c4ed82b6c6aac382dbaff53ae03c4b23a70e80a"}, + {file = "pydantic-1.10.7-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:68792151e174a4aa9e9fc1b4e653e65a354a2fa0fed169f7b3d09902ad2cb6f1"}, + {file = "pydantic-1.10.7-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:dfe2507b8ef209da71b6fb5f4e597b50c5a34b78d7e857c4f8f3115effaef5fe"}, + {file = "pydantic-1.10.7-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:10a86d8c8db68086f1e30a530f7d5f83eb0685e632e411dbbcf2d5c0150e8dcd"}, + {file = "pydantic-1.10.7-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d75ae19d2a3dbb146b6f324031c24f8a3f52ff5d6a9f22f0683694b3afcb16fb"}, + {file = "pydantic-1.10.7-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:464855a7ff7f2cc2cf537ecc421291b9132aa9c79aef44e917ad711b4a93163b"}, + {file = "pydantic-1.10.7-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:193924c563fae6ddcb71d3f06fa153866423ac1b793a47936656e806b64e24ca"}, + {file = "pydantic-1.10.7-cp311-cp311-win_amd64.whl", hash = "sha256:b4a849d10f211389502059c33332e91327bc154acc1845f375a99eca3afa802d"}, + {file = "pydantic-1.10.7-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:cc1dde4e50a5fc1336ee0581c1612215bc64ed6d28d2c7c6f25d2fe3e7c3e918"}, + {file = "pydantic-1.10.7-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e0cfe895a504c060e5d36b287ee696e2fdad02d89e0d895f83037245218a87fe"}, + {file = "pydantic-1.10.7-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:670bb4683ad1e48b0ecb06f0cfe2178dcf74ff27921cdf1606e527d2617a81ee"}, + {file = "pydantic-1.10.7-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:950ce33857841f9a337ce07ddf46bc84e1c4946d2a3bba18f8280297157a3fd1"}, + {file = "pydantic-1.10.7-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:c15582f9055fbc1bfe50266a19771bbbef33dd28c45e78afbe1996fd70966c2a"}, + {file = "pydantic-1.10.7-cp37-cp37m-win_amd64.whl", hash = "sha256:82dffb306dd20bd5268fd6379bc4bfe75242a9c2b79fec58e1041fbbdb1f7914"}, + {file = "pydantic-1.10.7-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:8c7f51861d73e8b9ddcb9916ae7ac39fb52761d9ea0df41128e81e2ba42886cd"}, + {file = "pydantic-1.10.7-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:6434b49c0b03a51021ade5c4daa7d70c98f7a79e95b551201fff682fc1661245"}, + {file = "pydantic-1.10.7-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:64d34ab766fa056df49013bb6e79921a0265204c071984e75a09cbceacbbdd5d"}, + {file = "pydantic-1.10.7-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:701daea9ffe9d26f97b52f1d157e0d4121644f0fcf80b443248434958fd03dc3"}, + {file = "pydantic-1.10.7-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:cf135c46099ff3f919d2150a948ce94b9ce545598ef2c6c7bf55dca98a304b52"}, + {file = "pydantic-1.10.7-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:b0f85904f73161817b80781cc150f8b906d521fa11e3cdabae19a581c3606209"}, + {file = "pydantic-1.10.7-cp38-cp38-win_amd64.whl", hash = "sha256:9f6f0fd68d73257ad6685419478c5aece46432f4bdd8d32c7345f1986496171e"}, + {file = "pydantic-1.10.7-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c230c0d8a322276d6e7b88c3f7ce885f9ed16e0910354510e0bae84d54991143"}, + {file = "pydantic-1.10.7-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:976cae77ba6a49d80f461fd8bba183ff7ba79f44aa5cfa82f1346b5626542f8e"}, + {file = "pydantic-1.10.7-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7d45fc99d64af9aaf7e308054a0067fdcd87ffe974f2442312372dfa66e1001d"}, + {file = "pydantic-1.10.7-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d2a5ebb48958754d386195fe9e9c5106f11275867051bf017a8059410e9abf1f"}, + {file = "pydantic-1.10.7-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:abfb7d4a7cd5cc4e1d1887c43503a7c5dd608eadf8bc615413fc498d3e4645cd"}, + {file = "pydantic-1.10.7-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:80b1fab4deb08a8292d15e43a6edccdffa5377a36a4597bb545b93e79c5ff0a5"}, + {file = "pydantic-1.10.7-cp39-cp39-win_amd64.whl", hash = "sha256:d71e69699498b020ea198468e2480a2f1e7433e32a3a99760058c6520e2bea7e"}, + {file = "pydantic-1.10.7-py3-none-any.whl", hash = "sha256:0cd181f1d0b1d00e2b705f1bf1ac7799a2d938cce3376b8007df62b29be3c2c6"}, + {file = "pydantic-1.10.7.tar.gz", hash = "sha256:cfc83c0678b6ba51b0532bea66860617c4cd4251ecf76e9846fa5a9f3454e97e"}, +] [package.dependencies] -typing-extensions = ">=4.1.0" +typing-extensions = ">=4.2.0" [package.extras] dotenv = ["python-dotenv (>=0.10.4)"] @@ -472,36 +1143,48 @@ description = "Python binding to the Networking and Cryptography (NaCl) library" category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +files = [ + {file = "PyNaCl-1.4.0-cp27-cp27m-macosx_10_10_x86_64.whl", hash = "sha256:ea6841bc3a76fa4942ce00f3bda7d436fda21e2d91602b9e21b7ca9ecab8f3ff"}, + {file = "PyNaCl-1.4.0-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:d452a6746f0a7e11121e64625109bc4468fc3100452817001dbe018bb8b08514"}, + {file = "PyNaCl-1.4.0-cp27-cp27m-win32.whl", hash = "sha256:2fe0fc5a2480361dcaf4e6e7cea00e078fcda07ba45f811b167e3f99e8cff574"}, + {file = "PyNaCl-1.4.0-cp27-cp27m-win_amd64.whl", hash = "sha256:f8851ab9041756003119368c1e6cd0b9c631f46d686b3904b18c0139f4419f80"}, + {file = "PyNaCl-1.4.0-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:7757ae33dae81c300487591c68790dfb5145c7d03324000433d9a2c141f82af7"}, + {file = "PyNaCl-1.4.0-cp35-abi3-macosx_10_10_x86_64.whl", hash = "sha256:757250ddb3bff1eecd7e41e65f7f833a8405fede0194319f87899690624f2122"}, + {file = "PyNaCl-1.4.0-cp35-abi3-manylinux1_x86_64.whl", hash = "sha256:30f9b96db44e09b3304f9ea95079b1b7316b2b4f3744fe3aaecccd95d547063d"}, + {file = "PyNaCl-1.4.0-cp35-abi3-win32.whl", hash = "sha256:4e10569f8cbed81cb7526ae137049759d2a8d57726d52c1a000a3ce366779634"}, + {file = "PyNaCl-1.4.0-cp35-abi3-win_amd64.whl", hash = "sha256:c914f78da4953b33d4685e3cdc7ce63401247a21425c16a39760e282075ac4a6"}, + {file = "PyNaCl-1.4.0-cp35-cp35m-win32.whl", hash = "sha256:06cbb4d9b2c4bd3c8dc0d267416aaed79906e7b33f114ddbf0911969794b1cc4"}, + {file = "PyNaCl-1.4.0-cp35-cp35m-win_amd64.whl", hash = "sha256:511d269ee845037b95c9781aa702f90ccc36036f95d0f31373a6a79bd8242e25"}, + {file = "PyNaCl-1.4.0-cp36-cp36m-win32.whl", hash = "sha256:11335f09060af52c97137d4ac54285bcb7df0cef29014a1a4efe64ac065434c4"}, + {file = "PyNaCl-1.4.0-cp36-cp36m-win_amd64.whl", hash = "sha256:cd401ccbc2a249a47a3a1724c2918fcd04be1f7b54eb2a5a71ff915db0ac51c6"}, + {file = "PyNaCl-1.4.0-cp37-cp37m-win32.whl", hash = "sha256:8122ba5f2a2169ca5da936b2e5a511740ffb73979381b4229d9188f6dcb22f1f"}, + {file = "PyNaCl-1.4.0-cp37-cp37m-win_amd64.whl", hash = "sha256:537a7ccbea22905a0ab36ea58577b39d1fa9b1884869d173b5cf111f006f689f"}, + {file = "PyNaCl-1.4.0-cp38-cp38-win32.whl", hash = "sha256:9c4a7ea4fb81536c1b1f5cc44d54a296f96ae78c1ebd2311bd0b60be45a48d96"}, + {file = "PyNaCl-1.4.0-cp38-cp38-win_amd64.whl", hash = "sha256:7c6092102219f59ff29788860ccb021e80fffd953920c4a8653889c029b2d420"}, + {file = "PyNaCl-1.4.0.tar.gz", hash = "sha256:54e9a2c849c742006516ad56a88f5c74bf2ce92c9f67435187c3c5953b346505"}, +] -[package.dependencies] -cffi = ">=1.4.1" -six = "*" - -[package.extras] -docs = ["sphinx (>=1.6.5)", "sphinx_rtd_theme"] -tests = ["hypothesis (>=3.27.0)", "pytest (>=3.2.1,!=3.3.0)"] - -[[package]] -name = "pyparsing" -version = "3.0.9" -description = "pyparsing module - Classes and methods to define and execute parsing grammars" -category = "dev" -optional = false -python-versions = ">=3.6.8" +[package.dependencies] +cffi = ">=1.4.1" +six = "*" [package.extras] -diagrams = ["jinja2", "railroad-diagrams"] +docs = ["sphinx (>=1.6.5)", "sphinx-rtd-theme"] +tests = ["hypothesis (>=3.27.0)", "pytest (>=3.2.1,!=3.3.0)"] [[package]] name = "pytest" -version = "7.2.0" +version = "7.3.1" description = "pytest: simple powerful testing with Python" category = "dev" optional = false python-versions = ">=3.7" +files = [ + {file = "pytest-7.3.1-py3-none-any.whl", hash = "sha256:3799fa815351fea3a5e96ac7e503a96fa51cc9942c3753cda7651b93c1cfa362"}, + {file = "pytest-7.3.1.tar.gz", hash = "sha256:434afafd78b1d78ed0addf160ad2b77a30d35d4bdf8af234fe621919d9ed15e3"}, +] [package.dependencies] -attrs = ">=19.2.0" colorama = {version = "*", markers = "sys_platform == \"win32\""} exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""} iniconfig = "*" @@ -510,48 +1193,150 @@ pluggy = ">=0.12,<2.0" tomli = {version = ">=1.0.0", markers = "python_version < \"3.11\""} [package.extras] -testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "xmlschema"] +testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "xmlschema"] [[package]] name = "python-dotenv" -version = "0.21.0" +version = "0.21.1" description = "Read key-value pairs from a .env file and set them as environment variables" category = "main" optional = false python-versions = ">=3.7" +files = [ + {file = "python-dotenv-0.21.1.tar.gz", hash = "sha256:1c93de8f636cde3ce377292818d0e440b6e45a82f215c3744979151fa8151c49"}, + {file = "python_dotenv-0.21.1-py3-none-any.whl", hash = "sha256:41e12e0318bebc859fcc4d97d4db8d20ad21721a6aa5047dd59f090391cb549a"}, +] [package.extras] cli = ["click (>=5.0)"] [[package]] name = "pytz" -version = "2022.6" +version = "2023.3" description = "World timezone definitions, modern and historical" category = "main" optional = false python-versions = "*" +files = [ + {file = "pytz-2023.3-py2.py3-none-any.whl", hash = "sha256:a151b3abb88eda1d4e34a9814df37de2a80e301e68ba0fd856fb9b46bfbbbffb"}, + {file = "pytz-2023.3.tar.gz", hash = "sha256:1d8ce29db189191fb55338ee6d0387d82ab59f3d00eac103412d64e0ebd0c588"}, +] [[package]] name = "regex" -version = "2021.11.10" +version = "2023.5.5" description = "Alternative regular expression module, to replace re." category = "main" optional = false -python-versions = "*" +python-versions = ">=3.6" +files = [ + {file = "regex-2023.5.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:48c9ec56579d4ba1c88f42302194b8ae2350265cb60c64b7b9a88dcb7fbde309"}, + {file = "regex-2023.5.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:02f4541550459c08fdd6f97aa4e24c6f1932eec780d58a2faa2068253df7d6ff"}, + {file = "regex-2023.5.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:53e22e4460f0245b468ee645156a4f84d0fc35a12d9ba79bd7d79bdcd2f9629d"}, + {file = "regex-2023.5.5-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4b870b6f632fc74941cadc2a0f3064ed8409e6f8ee226cdfd2a85ae50473aa94"}, + {file = "regex-2023.5.5-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:171c52e320fe29260da550d81c6b99f6f8402450dc7777ef5ced2e848f3b6f8f"}, + {file = "regex-2023.5.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aad5524c2aedaf9aa14ef1bc9327f8abd915699dea457d339bebbe2f0d218f86"}, + {file = "regex-2023.5.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5a0f874ee8c0bc820e649c900243c6d1e6dc435b81da1492046716f14f1a2a96"}, + {file = "regex-2023.5.5-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:e645c757183ee0e13f0bbe56508598e2d9cd42b8abc6c0599d53b0d0b8dd1479"}, + {file = "regex-2023.5.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:a4c5da39bca4f7979eefcbb36efea04471cd68db2d38fcbb4ee2c6d440699833"}, + {file = "regex-2023.5.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:5e3f4468b8c6fd2fd33c218bbd0a1559e6a6fcf185af8bb0cc43f3b5bfb7d636"}, + {file = "regex-2023.5.5-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:59e4b729eae1a0919f9e4c0fc635fbcc9db59c74ad98d684f4877be3d2607dd6"}, + {file = "regex-2023.5.5-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:ba73a14e9c8f9ac409863543cde3290dba39098fc261f717dc337ea72d3ebad2"}, + {file = "regex-2023.5.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:0bbd5dcb19603ab8d2781fac60114fb89aee8494f4505ae7ad141a3314abb1f9"}, + {file = "regex-2023.5.5-cp310-cp310-win32.whl", hash = "sha256:40005cbd383438aecf715a7b47fe1e3dcbc889a36461ed416bdec07e0ef1db66"}, + {file = "regex-2023.5.5-cp310-cp310-win_amd64.whl", hash = "sha256:59597cd6315d3439ed4b074febe84a439c33928dd34396941b4d377692eca810"}, + {file = "regex-2023.5.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:8f08276466fedb9e36e5193a96cb944928301152879ec20c2d723d1031cd4ddd"}, + {file = "regex-2023.5.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:cd46f30e758629c3ee91713529cfbe107ac50d27110fdcc326a42ce2acf4dafc"}, + {file = "regex-2023.5.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f2910502f718828cecc8beff004917dcf577fc5f8f5dd40ffb1ea7612124547b"}, + {file = "regex-2023.5.5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:445d6f4fc3bd9fc2bf0416164454f90acab8858cd5a041403d7a11e3356980e8"}, + {file = "regex-2023.5.5-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:18196c16a584619c7c1d843497c069955d7629ad4a3fdee240eb347f4a2c9dbe"}, + {file = "regex-2023.5.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:33d430a23b661629661f1fe8395be2004006bc792bb9fc7c53911d661b69dd7e"}, + {file = "regex-2023.5.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:72a28979cc667e5f82ef433db009184e7ac277844eea0f7f4d254b789517941d"}, + {file = "regex-2023.5.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:f764e4dfafa288e2eba21231f455d209f4709436baeebb05bdecfb5d8ddc3d35"}, + {file = "regex-2023.5.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:23d86ad2121b3c4fc78c58f95e19173790e22ac05996df69b84e12da5816cb17"}, + {file = "regex-2023.5.5-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:690a17db524ee6ac4a27efc5406530dd90e7a7a69d8360235323d0e5dafb8f5b"}, + {file = "regex-2023.5.5-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:1ecf3dcff71f0c0fe3e555201cbe749fa66aae8d18f80d2cc4de8e66df37390a"}, + {file = "regex-2023.5.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:811040d7f3dd9c55eb0d8b00b5dcb7fd9ae1761c454f444fd9f37fe5ec57143a"}, + {file = "regex-2023.5.5-cp311-cp311-win32.whl", hash = "sha256:c8c143a65ce3ca42e54d8e6fcaf465b6b672ed1c6c90022794a802fb93105d22"}, + {file = "regex-2023.5.5-cp311-cp311-win_amd64.whl", hash = "sha256:586a011f77f8a2da4b888774174cd266e69e917a67ba072c7fc0e91878178a80"}, + {file = "regex-2023.5.5-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:b6365703e8cf1644b82104cdd05270d1a9f043119a168d66c55684b1b557d008"}, + {file = "regex-2023.5.5-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a56c18f21ac98209da9c54ae3ebb3b6f6e772038681d6cb43b8d53da3b09ee81"}, + {file = "regex-2023.5.5-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b8b942d8b3ce765dbc3b1dad0a944712a89b5de290ce8f72681e22b3c55f3cc8"}, + {file = "regex-2023.5.5-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:844671c9c1150fcdac46d43198364034b961bd520f2c4fdaabfc7c7d7138a2dd"}, + {file = "regex-2023.5.5-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c2ce65bdeaf0a386bb3b533a28de3994e8e13b464ac15e1e67e4603dd88787fa"}, + {file = "regex-2023.5.5-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fee0016cc35a8a91e8cc9312ab26a6fe638d484131a7afa79e1ce6165328a135"}, + {file = "regex-2023.5.5-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:18f05d14f14a812fe9723f13afafefe6b74ca042d99f8884e62dbd34dcccf3e2"}, + {file = "regex-2023.5.5-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:941b3f1b2392f0bcd6abf1bc7a322787d6db4e7457be6d1ffd3a693426a755f2"}, + {file = "regex-2023.5.5-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:921473a93bcea4d00295799ab929522fc650e85c6b9f27ae1e6bb32a790ea7d3"}, + {file = "regex-2023.5.5-cp36-cp36m-musllinux_1_1_ppc64le.whl", hash = "sha256:e2205a81f815b5bb17e46e74cc946c575b484e5f0acfcb805fb252d67e22938d"}, + {file = "regex-2023.5.5-cp36-cp36m-musllinux_1_1_s390x.whl", hash = "sha256:385992d5ecf1a93cb85adff2f73e0402dd9ac29b71b7006d342cc920816e6f32"}, + {file = "regex-2023.5.5-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:890a09cb0a62198bff92eda98b2b507305dd3abf974778bae3287f98b48907d3"}, + {file = "regex-2023.5.5-cp36-cp36m-win32.whl", hash = "sha256:821a88b878b6589c5068f4cc2cfeb2c64e343a196bc9d7ac68ea8c2a776acd46"}, + {file = "regex-2023.5.5-cp36-cp36m-win_amd64.whl", hash = "sha256:7918a1b83dd70dc04ab5ed24c78ae833ae8ea228cef84e08597c408286edc926"}, + {file = "regex-2023.5.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:338994d3d4ca4cf12f09822e025731a5bdd3a37aaa571fa52659e85ca793fb67"}, + {file = "regex-2023.5.5-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0a69cf0c00c4d4a929c6c7717fd918414cab0d6132a49a6d8fc3ded1988ed2ea"}, + {file = "regex-2023.5.5-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8f5e06df94fff8c4c85f98c6487f6636848e1dc85ce17ab7d1931df4a081f657"}, + {file = "regex-2023.5.5-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a8906669b03c63266b6a7693d1f487b02647beb12adea20f8840c1a087e2dfb5"}, + {file = "regex-2023.5.5-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9fda3e50abad8d0f48df621cf75adc73c63f7243cbe0e3b2171392b445401550"}, + {file = "regex-2023.5.5-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5ac2b7d341dc1bd102be849d6dd33b09701223a851105b2754339e390be0627a"}, + {file = "regex-2023.5.5-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:fb2b495dd94b02de8215625948132cc2ea360ae84fe6634cd19b6567709c8ae2"}, + {file = "regex-2023.5.5-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:aa7d032c1d84726aa9edeb6accf079b4caa87151ca9fabacef31fa028186c66d"}, + {file = "regex-2023.5.5-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:3d45864693351c15531f7e76f545ec35000d50848daa833cead96edae1665559"}, + {file = "regex-2023.5.5-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:21e90a288e6ba4bf44c25c6a946cb9b0f00b73044d74308b5e0afd190338297c"}, + {file = "regex-2023.5.5-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:10250a093741ec7bf74bcd2039e697f519b028518f605ff2aa7ac1e9c9f97423"}, + {file = "regex-2023.5.5-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:6b8d0c153f07a953636b9cdb3011b733cadd4178123ef728ccc4d5969e67f3c2"}, + {file = "regex-2023.5.5-cp37-cp37m-win32.whl", hash = "sha256:10374c84ee58c44575b667310d5bbfa89fb2e64e52349720a0182c0017512f6c"}, + {file = "regex-2023.5.5-cp37-cp37m-win_amd64.whl", hash = "sha256:9b320677521aabf666cdd6e99baee4fb5ac3996349c3b7f8e7c4eee1c00dfe3a"}, + {file = "regex-2023.5.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:afb1c70ec1e594a547f38ad6bf5e3d60304ce7539e677c1429eebab115bce56e"}, + {file = "regex-2023.5.5-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:cf123225945aa58b3057d0fba67e8061c62d14cc8a4202630f8057df70189051"}, + {file = "regex-2023.5.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a99757ad7fe5c8a2bb44829fc57ced11253e10f462233c1255fe03888e06bc19"}, + {file = "regex-2023.5.5-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a623564d810e7a953ff1357f7799c14bc9beeab699aacc8b7ab7822da1e952b8"}, + {file = "regex-2023.5.5-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ced02e3bd55e16e89c08bbc8128cff0884d96e7f7a5633d3dc366b6d95fcd1d6"}, + {file = "regex-2023.5.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d1cbe6b5be3b9b698d8cc4ee4dee7e017ad655e83361cd0ea8e653d65e469468"}, + {file = "regex-2023.5.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4a6e4b0e0531223f53bad07ddf733af490ba2b8367f62342b92b39b29f72735a"}, + {file = "regex-2023.5.5-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:2e9c4f778514a560a9c9aa8e5538bee759b55f6c1dcd35613ad72523fd9175b8"}, + {file = "regex-2023.5.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:256f7f4c6ba145f62f7a441a003c94b8b1af78cee2cccacfc1e835f93bc09426"}, + {file = "regex-2023.5.5-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:bd7b68fd2e79d59d86dcbc1ccd6e2ca09c505343445daaa4e07f43c8a9cc34da"}, + {file = "regex-2023.5.5-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:4a5059bd585e9e9504ef9c07e4bc15b0a621ba20504388875d66b8b30a5c4d18"}, + {file = "regex-2023.5.5-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:6893544e06bae009916a5658ce7207e26ed17385149f35a3125f5259951f1bbe"}, + {file = "regex-2023.5.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:c64d5abe91a3dfe5ff250c6bb267ef00dbc01501518225b45a5f9def458f31fb"}, + {file = "regex-2023.5.5-cp38-cp38-win32.whl", hash = "sha256:7923470d6056a9590247ff729c05e8e0f06bbd4efa6569c916943cb2d9b68b91"}, + {file = "regex-2023.5.5-cp38-cp38-win_amd64.whl", hash = "sha256:4035d6945cb961c90c3e1c1ca2feb526175bcfed44dfb1cc77db4fdced060d3e"}, + {file = "regex-2023.5.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:50fd2d9b36938d4dcecbd684777dd12a407add4f9f934f235c66372e630772b0"}, + {file = "regex-2023.5.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:d19e57f888b00cd04fc38f5e18d0efbd91ccba2d45039453ab2236e6eec48d4d"}, + {file = "regex-2023.5.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bd966475e963122ee0a7118ec9024388c602d12ac72860f6eea119a3928be053"}, + {file = "regex-2023.5.5-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:db09e6c18977a33fea26fe67b7a842f706c67cf8bda1450974d0ae0dd63570df"}, + {file = "regex-2023.5.5-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6164d4e2a82f9ebd7752a06bd6c504791bedc6418c0196cd0a23afb7f3e12b2d"}, + {file = "regex-2023.5.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:84397d3f750d153ebd7f958efaa92b45fea170200e2df5e0e1fd4d85b7e3f58a"}, + {file = "regex-2023.5.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9c3efee9bb53cbe7b285760c81f28ac80dc15fa48b5fe7e58b52752e642553f1"}, + {file = "regex-2023.5.5-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:144b5b017646b5a9392a5554a1e5db0000ae637be4971c9747566775fc96e1b2"}, + {file = "regex-2023.5.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:1189fbbb21e2c117fda5303653b61905aeeeea23de4a94d400b0487eb16d2d60"}, + {file = "regex-2023.5.5-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:f83fe9e10f9d0b6cf580564d4d23845b9d692e4c91bd8be57733958e4c602956"}, + {file = "regex-2023.5.5-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:72aa4746993a28c841e05889f3f1b1e5d14df8d3daa157d6001a34c98102b393"}, + {file = "regex-2023.5.5-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:de2f780c3242ea114dd01f84848655356af4dd561501896c751d7b885ea6d3a1"}, + {file = "regex-2023.5.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:290fd35219486dfbc00b0de72f455ecdd63e59b528991a6aec9fdfc0ce85672e"}, + {file = "regex-2023.5.5-cp39-cp39-win32.whl", hash = "sha256:732176f5427e72fa2325b05c58ad0b45af341c459910d766f814b0584ac1f9ac"}, + {file = "regex-2023.5.5-cp39-cp39-win_amd64.whl", hash = "sha256:1307aa4daa1cbb23823d8238e1f61292fd07e4e5d8d38a6efff00b67a7cdb764"}, + {file = "regex-2023.5.5.tar.gz", hash = "sha256:7d76a8a1fc9da08296462a18f16620ba73bcbf5909e42383b253ef34d9d5141e"}, +] [[package]] name = "requests" -version = "2.28.1" +version = "2.30.0" description = "Python HTTP for Humans." category = "main" optional = false -python-versions = ">=3.7, <4" +python-versions = ">=3.7" +files = [ + {file = "requests-2.30.0-py3-none-any.whl", hash = "sha256:10e94cc4f3121ee6da529d358cdaeaff2f1c409cd377dbc72b825852f2f7e294"}, + {file = "requests-2.30.0.tar.gz", hash = "sha256:239d7d4458afcb28a692cdd298d87542235f4ca8d36d03a15bfc128a6559a2f4"}, +] [package.dependencies] certifi = ">=2017.4.17" -charset-normalizer = ">=2,<3" +charset-normalizer = ">=2,<4" idna = ">=2.5,<4" -urllib3 = ">=1.21.1,<1.27" +urllib3 = ">=1.21.1,<3" [package.extras] socks = ["PySocks (>=1.5.6,!=1.5.7)"] @@ -564,6 +1349,10 @@ description = "Validating URI References per RFC 3986" category = "main" optional = false python-versions = "*" +files = [ + {file = "rfc3986-1.5.0-py2.py3-none-any.whl", hash = "sha256:a86d6e1f5b1dc238b218b012df0aa79409667bb209e58da56d0b94704e712a97"}, + {file = "rfc3986-1.5.0.tar.gz", hash = "sha256:270aaf10d87d0d4e095063c65bf3ddbc6ee3d0b226328ce21e036f946e421835"}, +] [package.extras] idna2008 = ["idna"] @@ -575,6 +1364,9 @@ description = "Py3k port of sgmllib." category = "main" optional = false python-versions = "*" +files = [ + {file = "sgmllib3k-1.0.0.tar.gz", hash = "sha256:7868fb1c8bfa764c1ac563d3cf369c381d1325d36124933a726f29fcdaa812e9"}, +] [[package]] name = "six" @@ -583,6 +1375,10 @@ description = "Python 2 and 3 compatibility utilities" category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" +files = [ + {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, + {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, +] [[package]] name = "sniffio" @@ -591,33 +1387,49 @@ description = "Sniff out which async library your code is running under" category = "main" optional = false python-versions = ">=3.7" +files = [ + {file = "sniffio-1.3.0-py3-none-any.whl", hash = "sha256:eecefdce1e5bbfb7ad2eeaabf7c1eeb404d7757c379bd1f7e5cce9d8bf425384"}, + {file = "sniffio-1.3.0.tar.gz", hash = "sha256:e60305c5e5d314f5389259b7f22aaa33d8f7dee49763119234af3755c55b9101"}, +] [[package]] name = "soupsieve" -version = "2.3.2.post1" +version = "2.4.1" description = "A modern CSS selector implementation for Beautiful Soup." category = "main" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" +files = [ + {file = "soupsieve-2.4.1-py3-none-any.whl", hash = "sha256:1c1bfee6819544a3447586c889157365a27e10d88cde3ad3da0cf0ddf646feb8"}, + {file = "soupsieve-2.4.1.tar.gz", hash = "sha256:89d12b2d5dfcd2c9e8c22326da9d9aa9cb3dfab0a83a024f05704076ee8d35ea"}, +] [[package]] name = "sympy" -version = "1.11.1" +version = "1.12" description = "Computer algebra system (CAS) in Python" category = "main" optional = false python-versions = ">=3.8" +files = [ + {file = "sympy-1.12-py3-none-any.whl", hash = "sha256:c3588cd4295d0c0f603d0f2ae780587e64e2efeedb3521e46b9bb1d08d184fa5"}, + {file = "sympy-1.12.tar.gz", hash = "sha256:ebf595c8dac3e0fdc4152c51878b498396ec7f30e7a914d6071e674d49420fb8"}, +] [package.dependencies] mpmath = ">=0.19" [[package]] name = "tabulate" -version = "0.8.9" +version = "0.8.10" description = "Pretty-print tabular data" category = "main" optional = false -python-versions = "*" +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +files = [ + {file = "tabulate-0.8.10-py3-none-any.whl", hash = "sha256:0ba055423dbaa164b9e456abe7920c5e8ed33fcc16f6d1b2f2d152c8e1e8b4fc"}, + {file = "tabulate-0.8.10.tar.gz", hash = "sha256:6c57f3f3dd7ac2782770155f3adb2db0b1a269637e42f27599925e64b114f519"}, +] [package.extras] widechars = ["wcwidth"] @@ -629,41 +1441,76 @@ description = "A lil' TOML parser" category = "dev" optional = false python-versions = ">=3.7" +files = [ + {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, + {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, +] [[package]] name = "types-beautifulsoup4" -version = "4.11.6.1" +version = "4.12.0.5" description = "Typing stubs for beautifulsoup4" category = "dev" optional = false python-versions = "*" +files = [ + {file = "types-beautifulsoup4-4.12.0.5.tar.gz", hash = "sha256:d9be456416a62a5b9740559592e1063a69d4b0a1b83911d878558c8ae8e07074"}, + {file = "types_beautifulsoup4-4.12.0.5-py3-none-any.whl", hash = "sha256:718364c8e6787884501c700b1d22b6c0a8711bf9d6c9bf96e1fba81495bc46a8"}, +] + +[package.dependencies] +types-html5lib = "*" + +[[package]] +name = "types-html5lib" +version = "1.1.11.14" +description = "Typing stubs for html5lib" +category = "dev" +optional = false +python-versions = "*" +files = [ + {file = "types-html5lib-1.1.11.14.tar.gz", hash = "sha256:091e9e74e0ee37c93fd789a164e99b2af80ecf5a314280450c6a763d027ea209"}, + {file = "types_html5lib-1.1.11.14-py3-none-any.whl", hash = "sha256:758c1a27f3b63363a346f3646be9f8b1f25df4fc1f96f88af6d1d831f24ad675"}, +] [[package]] name = "types-pytz" -version = "2022.6.0.1" +version = "2022.7.1.2" description = "Typing stubs for pytz" category = "dev" optional = false python-versions = "*" +files = [ + {file = "types-pytz-2022.7.1.2.tar.gz", hash = "sha256:487d3e8e9f4071eec8081746d53fa982bbc05812e719dcbf2ebf3d55a1a4cd28"}, + {file = "types_pytz-2022.7.1.2-py3-none-any.whl", hash = "sha256:40ca448a928d566f7d44ddfde0066e384f7ffbd4da2778e42a4570eaca572446"}, +] [[package]] name = "types-regex" -version = "2022.10.31.0" +version = "2022.10.31.6" description = "Typing stubs for regex" category = "dev" optional = false python-versions = "*" +files = [ + {file = "types-regex-2022.10.31.6.tar.gz", hash = "sha256:4b552e26afb01597d0a53a3bf4fe5892736c7178ae6e3d9d9b919168e58a6875"}, + {file = "types_regex-2022.10.31.6-py3-none-any.whl", hash = "sha256:0e5917db2ed629b7a658091576cc758fedf48397eae1aa9b085ae3ccfae225f2"}, +] [[package]] name = "types-requests" -version = "2.28.11.5" +version = "2.30.0.0" description = "Typing stubs for requests" category = "dev" optional = false python-versions = "*" +files = [ + {file = "types-requests-2.30.0.0.tar.gz", hash = "sha256:dec781054324a70ba64430ae9e62e7e9c8e4618c185a5cb3f87a6738251b5a31"}, + {file = "types_requests-2.30.0.0-py3-none-any.whl", hash = "sha256:c6cf08e120ca9f0dc4fa4e32c3f953c3fba222bcc1db6b97695bce8da1ba9864"}, +] [package.dependencies] -types-urllib3 = "<1.27" +types-urllib3 = "*" [[package]] name = "types-tabulate" @@ -672,35 +1519,52 @@ description = "Typing stubs for tabulate" category = "dev" optional = false python-versions = "*" +files = [ + {file = "types-tabulate-0.8.11.tar.gz", hash = "sha256:17a5fa3b5ca453815778fc9865e8ecd0118b07b2b9faff3e2b06fe448174dd5e"}, + {file = "types_tabulate-0.8.11-py3-none-any.whl", hash = "sha256:af811268241e8fb87b63c052c87d1e329898a93191309d5d42111372232b2e0e"}, +] [[package]] name = "types-urllib3" -version = "1.26.25.4" +version = "1.26.25.13" description = "Typing stubs for urllib3" category = "dev" optional = false python-versions = "*" +files = [ + {file = "types-urllib3-1.26.25.13.tar.gz", hash = "sha256:3300538c9dc11dad32eae4827ac313f5d986b8b21494801f1bf97a1ac6c03ae5"}, + {file = "types_urllib3-1.26.25.13-py3-none-any.whl", hash = "sha256:5dbd1d2bef14efee43f5318b5d36d805a489f6600252bb53626d4bfafd95e27c"}, +] [[package]] name = "typing-extensions" -version = "4.4.0" +version = "4.5.0" description = "Backported and Experimental Type Hints for Python 3.7+" category = "main" optional = false python-versions = ">=3.7" +files = [ + {file = "typing_extensions-4.5.0-py3-none-any.whl", hash = "sha256:fb33085c39dd998ac16d1431ebc293a8b3eedd00fd4a32de0ff79002c19511b4"}, + {file = "typing_extensions-4.5.0.tar.gz", hash = "sha256:5cb5f4a79139d699607b3ef622a1dedafa84e115ab0024e0d9c044a9479ca7cb"}, +] [[package]] name = "urllib3" -version = "1.26.12" +version = "2.0.2" 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.*, !=3.5.*, <4" +python-versions = ">=3.7" +files = [ + {file = "urllib3-2.0.2-py3-none-any.whl", hash = "sha256:d055c2f9d38dc53c808f6fdc8eab7360b6fdbbde02340ed25cfbcd817c62469e"}, + {file = "urllib3-2.0.2.tar.gz", hash = "sha256:61717a1095d7e155cdb737ac7bb2f4324a858a1e2e6466f6d03ff630ca68d3cc"}, +] [package.extras] -brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)", "brotlipy (>=0.6.0)"] -secure = ["certifi", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "ipaddress", "pyOpenSSL (>=0.14)", "urllib3-secure-extra"] -socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] +brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"] +secure = ["certifi", "cryptography (>=1.9)", "idna (>=2.0.0)", "pyopenssl (>=17.1.0)", "urllib3-secure-extra"] +socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] +zstd = ["zstandard (>=0.18.0)"] [[package]] name = "uvloop" @@ -709,6 +1573,24 @@ description = "Fast implementation of asyncio event loop on top of libuv" category = "main" optional = false python-versions = ">=3.7" +files = [ + {file = "uvloop-0.16.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:6224f1401025b748ffecb7a6e2652b17768f30b1a6a3f7b44660e5b5b690b12d"}, + {file = "uvloop-0.16.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:30ba9dcbd0965f5c812b7c2112a1ddf60cf904c1c160f398e7eed3a6b82dcd9c"}, + {file = "uvloop-0.16.0-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:bd53f7f5db562f37cd64a3af5012df8cac2c464c97e732ed556800129505bd64"}, + {file = "uvloop-0.16.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:772206116b9b57cd625c8a88f2413df2fcfd0b496eb188b82a43bed7af2c2ec9"}, + {file = "uvloop-0.16.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b572256409f194521a9895aef274cea88731d14732343da3ecdb175228881638"}, + {file = "uvloop-0.16.0-cp37-cp37m-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:04ff57aa137230d8cc968f03481176041ae789308b4d5079118331ab01112450"}, + {file = "uvloop-0.16.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3a19828c4f15687675ea912cc28bbcb48e9bb907c801873bd1519b96b04fb805"}, + {file = "uvloop-0.16.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:e814ac2c6f9daf4c36eb8e85266859f42174a4ff0d71b99405ed559257750382"}, + {file = "uvloop-0.16.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:bd8f42ea1ea8f4e84d265769089964ddda95eb2bb38b5cbe26712b0616c3edee"}, + {file = "uvloop-0.16.0-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:647e481940379eebd314c00440314c81ea547aa636056f554d491e40503c8464"}, + {file = "uvloop-0.16.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8e0d26fa5875d43ddbb0d9d79a447d2ace4180d9e3239788208527c4784f7cab"}, + {file = "uvloop-0.16.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:6ccd57ae8db17d677e9e06192e9c9ec4bd2066b77790f9aa7dede2cc4008ee8f"}, + {file = "uvloop-0.16.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:089b4834fd299d82d83a25e3335372f12117a7d38525217c2258e9b9f4578897"}, + {file = "uvloop-0.16.0-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:98d117332cc9e5ea8dfdc2b28b0a23f60370d02e1395f88f40d1effd2cb86c4f"}, + {file = "uvloop-0.16.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1e5f2e2ff51aefe6c19ee98af12b4ae61f5be456cd24396953244a30880ad861"}, + {file = "uvloop-0.16.0.tar.gz", hash = "sha256:f74bc20c7b67d1c27c72601c78cf95be99d5c2cdd4514502b4f3eb0933ff1228"}, +] [package.extras] dev = ["Cython (>=0.29.24,<0.30.0)", "Sphinx (>=4.1.2,<4.2.0)", "aiohttp", "flake8 (>=3.9.2,<3.10.0)", "mypy (>=0.800)", "psutil", "pyOpenSSL (>=19.0.0,<19.1.0)", "pycodestyle (>=2.7.0,<2.8.0)", "pytest (>=3.6.0)", "sphinx-rtd-theme (>=0.5.2,<0.6.0)", "sphinxcontrib-asyncio (>=0.3.0,<0.4.0)"] @@ -717,19 +1599,167 @@ test = ["aiohttp", "flake8 (>=3.9.2,<3.10.0)", "mypy (>=0.800)", "psutil", "pyOp [[package]] name = "websockets" -version = "10.4" +version = "11.0.3" description = "An implementation of the WebSocket Protocol (RFC 6455 & 7692)" category = "main" optional = false python-versions = ">=3.7" +files = [ + {file = "websockets-11.0.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:3ccc8a0c387629aec40f2fc9fdcb4b9d5431954f934da3eaf16cdc94f67dbfac"}, + {file = "websockets-11.0.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d67ac60a307f760c6e65dad586f556dde58e683fab03323221a4e530ead6f74d"}, + {file = "websockets-11.0.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:84d27a4832cc1a0ee07cdcf2b0629a8a72db73f4cf6de6f0904f6661227f256f"}, + {file = "websockets-11.0.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ffd7dcaf744f25f82190856bc26ed81721508fc5cbf2a330751e135ff1283564"}, + {file = "websockets-11.0.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7622a89d696fc87af8e8d280d9b421db5133ef5b29d3f7a1ce9f1a7bf7fcfa11"}, + {file = "websockets-11.0.3-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bceab846bac555aff6427d060f2fcfff71042dba6f5fca7dc4f75cac815e57ca"}, + {file = "websockets-11.0.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:54c6e5b3d3a8936a4ab6870d46bdd6ec500ad62bde9e44462c32d18f1e9a8e54"}, + {file = "websockets-11.0.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:41f696ba95cd92dc047e46b41b26dd24518384749ed0d99bea0a941ca87404c4"}, + {file = "websockets-11.0.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:86d2a77fd490ae3ff6fae1c6ceaecad063d3cc2320b44377efdde79880e11526"}, + {file = "websockets-11.0.3-cp310-cp310-win32.whl", hash = "sha256:2d903ad4419f5b472de90cd2d40384573b25da71e33519a67797de17ef849b69"}, + {file = "websockets-11.0.3-cp310-cp310-win_amd64.whl", hash = "sha256:1d2256283fa4b7f4c7d7d3e84dc2ece74d341bce57d5b9bf385df109c2a1a82f"}, + {file = "websockets-11.0.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:e848f46a58b9fcf3d06061d17be388caf70ea5b8cc3466251963c8345e13f7eb"}, + {file = "websockets-11.0.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:aa5003845cdd21ac0dc6c9bf661c5beddd01116f6eb9eb3c8e272353d45b3288"}, + {file = "websockets-11.0.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b58cbf0697721120866820b89f93659abc31c1e876bf20d0b3d03cef14faf84d"}, + {file = "websockets-11.0.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:660e2d9068d2bedc0912af508f30bbeb505bbbf9774d98def45f68278cea20d3"}, + {file = "websockets-11.0.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c1f0524f203e3bd35149f12157438f406eff2e4fb30f71221c8a5eceb3617b6b"}, + {file = "websockets-11.0.3-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:def07915168ac8f7853812cc593c71185a16216e9e4fa886358a17ed0fd9fcf6"}, + {file = "websockets-11.0.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:b30c6590146e53149f04e85a6e4fcae068df4289e31e4aee1fdf56a0dead8f97"}, + {file = "websockets-11.0.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:619d9f06372b3a42bc29d0cd0354c9bb9fb39c2cbc1a9c5025b4538738dbffaf"}, + {file = "websockets-11.0.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:01f5567d9cf6f502d655151645d4e8b72b453413d3819d2b6f1185abc23e82dd"}, + {file = "websockets-11.0.3-cp311-cp311-win32.whl", hash = "sha256:e1459677e5d12be8bbc7584c35b992eea142911a6236a3278b9b5ce3326f282c"}, + {file = "websockets-11.0.3-cp311-cp311-win_amd64.whl", hash = "sha256:e7837cb169eca3b3ae94cc5787c4fed99eef74c0ab9506756eea335e0d6f3ed8"}, + {file = "websockets-11.0.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:9f59a3c656fef341a99e3d63189852be7084c0e54b75734cde571182c087b152"}, + {file = "websockets-11.0.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2529338a6ff0eb0b50c7be33dc3d0e456381157a31eefc561771ee431134a97f"}, + {file = "websockets-11.0.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:34fd59a4ac42dff6d4681d8843217137f6bc85ed29722f2f7222bd619d15e95b"}, + {file = "websockets-11.0.3-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:332d126167ddddec94597c2365537baf9ff62dfcc9db4266f263d455f2f031cb"}, + {file = "websockets-11.0.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:6505c1b31274723ccaf5f515c1824a4ad2f0d191cec942666b3d0f3aa4cb4007"}, + {file = "websockets-11.0.3-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:f467ba0050b7de85016b43f5a22b46383ef004c4f672148a8abf32bc999a87f0"}, + {file = "websockets-11.0.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:9d9acd80072abcc98bd2c86c3c9cd4ac2347b5a5a0cae7ed5c0ee5675f86d9af"}, + {file = "websockets-11.0.3-cp37-cp37m-win32.whl", hash = "sha256:e590228200fcfc7e9109509e4d9125eace2042fd52b595dd22bbc34bb282307f"}, + {file = "websockets-11.0.3-cp37-cp37m-win_amd64.whl", hash = "sha256:b16fff62b45eccb9c7abb18e60e7e446998093cdcb50fed33134b9b6878836de"}, + {file = "websockets-11.0.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:fb06eea71a00a7af0ae6aefbb932fb8a7df3cb390cc217d51a9ad7343de1b8d0"}, + {file = "websockets-11.0.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:8a34e13a62a59c871064dfd8ffb150867e54291e46d4a7cf11d02c94a5275bae"}, + {file = "websockets-11.0.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:4841ed00f1026dfbced6fca7d963c4e7043aa832648671b5138008dc5a8f6d99"}, + {file = "websockets-11.0.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1a073fc9ab1c8aff37c99f11f1641e16da517770e31a37265d2755282a5d28aa"}, + {file = "websockets-11.0.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:68b977f21ce443d6d378dbd5ca38621755f2063d6fdb3335bda981d552cfff86"}, + {file = "websockets-11.0.3-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e1a99a7a71631f0efe727c10edfba09ea6bee4166a6f9c19aafb6c0b5917d09c"}, + {file = "websockets-11.0.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:bee9fcb41db2a23bed96c6b6ead6489702c12334ea20a297aa095ce6d31370d0"}, + {file = "websockets-11.0.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:4b253869ea05a5a073ebfdcb5cb3b0266a57c3764cf6fe114e4cd90f4bfa5f5e"}, + {file = "websockets-11.0.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:1553cb82942b2a74dd9b15a018dce645d4e68674de2ca31ff13ebc2d9f283788"}, + {file = "websockets-11.0.3-cp38-cp38-win32.whl", hash = "sha256:f61bdb1df43dc9c131791fbc2355535f9024b9a04398d3bd0684fc16ab07df74"}, + {file = "websockets-11.0.3-cp38-cp38-win_amd64.whl", hash = "sha256:03aae4edc0b1c68498f41a6772d80ac7c1e33c06c6ffa2ac1c27a07653e79d6f"}, + {file = "websockets-11.0.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:777354ee16f02f643a4c7f2b3eff8027a33c9861edc691a2003531f5da4f6bc8"}, + {file = "websockets-11.0.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8c82f11964f010053e13daafdc7154ce7385ecc538989a354ccc7067fd7028fd"}, + {file = "websockets-11.0.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3580dd9c1ad0701169e4d6fc41e878ffe05e6bdcaf3c412f9d559389d0c9e016"}, + {file = "websockets-11.0.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6f1a3f10f836fab6ca6efa97bb952300b20ae56b409414ca85bff2ad241d2a61"}, + {file = "websockets-11.0.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:df41b9bc27c2c25b486bae7cf42fccdc52ff181c8c387bfd026624a491c2671b"}, + {file = "websockets-11.0.3-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:279e5de4671e79a9ac877427f4ac4ce93751b8823f276b681d04b2156713b9dd"}, + {file = "websockets-11.0.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:1fdf26fa8a6a592f8f9235285b8affa72748dc12e964a5518c6c5e8f916716f7"}, + {file = "websockets-11.0.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:69269f3a0b472e91125b503d3c0b3566bda26da0a3261c49f0027eb6075086d1"}, + {file = "websockets-11.0.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:97b52894d948d2f6ea480171a27122d77af14ced35f62e5c892ca2fae9344311"}, + {file = "websockets-11.0.3-cp39-cp39-win32.whl", hash = "sha256:c7f3cb904cce8e1be667c7e6fef4516b98d1a6a0635a58a57528d577ac18a128"}, + {file = "websockets-11.0.3-cp39-cp39-win_amd64.whl", hash = "sha256:c792ea4eabc0159535608fc5658a74d1a81020eb35195dd63214dcf07556f67e"}, + {file = "websockets-11.0.3-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:f2e58f2c36cc52d41f2659e4c0cbf7353e28c8c9e63e30d8c6d3494dc9fdedcf"}, + {file = "websockets-11.0.3-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:de36fe9c02995c7e6ae6efe2e205816f5f00c22fd1fbf343d4d18c3d5ceac2f5"}, + {file = "websockets-11.0.3-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0ac56b661e60edd453585f4bd68eb6a29ae25b5184fd5ba51e97652580458998"}, + {file = "websockets-11.0.3-pp37-pypy37_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e052b8467dd07d4943936009f46ae5ce7b908ddcac3fda581656b1b19c083d9b"}, + {file = "websockets-11.0.3-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:42cc5452a54a8e46a032521d7365da775823e21bfba2895fb7b77633cce031bb"}, + {file = "websockets-11.0.3-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:e6316827e3e79b7b8e7d8e3b08f4e331af91a48e794d5d8b099928b6f0b85f20"}, + {file = "websockets-11.0.3-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8531fdcad636d82c517b26a448dcfe62f720e1922b33c81ce695d0edb91eb931"}, + {file = "websockets-11.0.3-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c114e8da9b475739dde229fd3bc6b05a6537a88a578358bc8eb29b4030fac9c9"}, + {file = "websockets-11.0.3-pp38-pypy38_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e063b1865974611313a3849d43f2c3f5368093691349cf3c7c8f8f75ad7cb280"}, + {file = "websockets-11.0.3-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:92b2065d642bf8c0a82d59e59053dd2fdde64d4ed44efe4870fa816c1232647b"}, + {file = "websockets-11.0.3-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:0ee68fe502f9031f19d495dae2c268830df2760c0524cbac5d759921ba8c8e82"}, + {file = "websockets-11.0.3-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dcacf2c7a6c3a84e720d1bb2b543c675bf6c40e460300b628bab1b1efc7c034c"}, + {file = "websockets-11.0.3-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b67c6f5e5a401fc56394f191f00f9b3811fe843ee93f4a70df3c389d1adf857d"}, + {file = "websockets-11.0.3-pp39-pypy39_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1d5023a4b6a5b183dc838808087033ec5df77580485fc533e7dab2567851b0a4"}, + {file = "websockets-11.0.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:ed058398f55163a79bb9f06a90ef9ccc063b204bb346c4de78efc5d15abfe602"}, + {file = "websockets-11.0.3-py3-none-any.whl", hash = "sha256:6681ba9e7f8f3b19440921e99efbb40fc89f26cd71bf539e45d8c8a25c976dc6"}, + {file = "websockets-11.0.3.tar.gz", hash = "sha256:88fc51d9a26b10fc331be344f1781224a375b78488fc343620184e95a4b27016"}, +] [[package]] name = "yarl" -version = "1.8.1" +version = "1.9.2" description = "Yet another URL library" category = "main" optional = false python-versions = ">=3.7" +files = [ + {file = "yarl-1.9.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:8c2ad583743d16ddbdf6bb14b5cd76bf43b0d0006e918809d5d4ddf7bde8dd82"}, + {file = "yarl-1.9.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:82aa6264b36c50acfb2424ad5ca537a2060ab6de158a5bd2a72a032cc75b9eb8"}, + {file = "yarl-1.9.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c0c77533b5ed4bcc38e943178ccae29b9bcf48ffd1063f5821192f23a1bd27b9"}, + {file = "yarl-1.9.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ee4afac41415d52d53a9833ebae7e32b344be72835bbb589018c9e938045a560"}, + {file = "yarl-1.9.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9bf345c3a4f5ba7f766430f97f9cc1320786f19584acc7086491f45524a551ac"}, + {file = "yarl-1.9.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2a96c19c52ff442a808c105901d0bdfd2e28575b3d5f82e2f5fd67e20dc5f4ea"}, + {file = "yarl-1.9.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:891c0e3ec5ec881541f6c5113d8df0315ce5440e244a716b95f2525b7b9f3608"}, + {file = "yarl-1.9.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c3a53ba34a636a256d767c086ceb111358876e1fb6b50dfc4d3f4951d40133d5"}, + {file = "yarl-1.9.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:566185e8ebc0898b11f8026447eacd02e46226716229cea8db37496c8cdd26e0"}, + {file = "yarl-1.9.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:2b0738fb871812722a0ac2154be1f049c6223b9f6f22eec352996b69775b36d4"}, + {file = "yarl-1.9.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:32f1d071b3f362c80f1a7d322bfd7b2d11e33d2adf395cc1dd4df36c9c243095"}, + {file = "yarl-1.9.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:e9fdc7ac0d42bc3ea78818557fab03af6181e076a2944f43c38684b4b6bed8e3"}, + {file = "yarl-1.9.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:56ff08ab5df8429901ebdc5d15941b59f6253393cb5da07b4170beefcf1b2528"}, + {file = "yarl-1.9.2-cp310-cp310-win32.whl", hash = "sha256:8ea48e0a2f931064469bdabca50c2f578b565fc446f302a79ba6cc0ee7f384d3"}, + {file = "yarl-1.9.2-cp310-cp310-win_amd64.whl", hash = "sha256:50f33040f3836e912ed16d212f6cc1efb3231a8a60526a407aeb66c1c1956dde"}, + {file = "yarl-1.9.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:646d663eb2232d7909e6601f1a9107e66f9791f290a1b3dc7057818fe44fc2b6"}, + {file = "yarl-1.9.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:aff634b15beff8902d1f918012fc2a42e0dbae6f469fce134c8a0dc51ca423bb"}, + {file = "yarl-1.9.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a83503934c6273806aed765035716216cc9ab4e0364f7f066227e1aaea90b8d0"}, + {file = "yarl-1.9.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b25322201585c69abc7b0e89e72790469f7dad90d26754717f3310bfe30331c2"}, + {file = "yarl-1.9.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:22a94666751778629f1ec4280b08eb11815783c63f52092a5953faf73be24191"}, + {file = "yarl-1.9.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8ec53a0ea2a80c5cd1ab397925f94bff59222aa3cf9c6da938ce05c9ec20428d"}, + {file = "yarl-1.9.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:159d81f22d7a43e6eabc36d7194cb53f2f15f498dbbfa8edc8a3239350f59fe7"}, + {file = "yarl-1.9.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:832b7e711027c114d79dffb92576acd1bd2decc467dec60e1cac96912602d0e6"}, + {file = "yarl-1.9.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:95d2ecefbcf4e744ea952d073c6922e72ee650ffc79028eb1e320e732898d7e8"}, + {file = "yarl-1.9.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:d4e2c6d555e77b37288eaf45b8f60f0737c9efa3452c6c44626a5455aeb250b9"}, + {file = "yarl-1.9.2-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:783185c75c12a017cc345015ea359cc801c3b29a2966c2655cd12b233bf5a2be"}, + {file = "yarl-1.9.2-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:b8cc1863402472f16c600e3e93d542b7e7542a540f95c30afd472e8e549fc3f7"}, + {file = "yarl-1.9.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:822b30a0f22e588b32d3120f6d41e4ed021806418b4c9f0bc3048b8c8cb3f92a"}, + {file = "yarl-1.9.2-cp311-cp311-win32.whl", hash = "sha256:a60347f234c2212a9f0361955007fcf4033a75bf600a33c88a0a8e91af77c0e8"}, + {file = "yarl-1.9.2-cp311-cp311-win_amd64.whl", hash = "sha256:be6b3fdec5c62f2a67cb3f8c6dbf56bbf3f61c0f046f84645cd1ca73532ea051"}, + {file = "yarl-1.9.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:38a3928ae37558bc1b559f67410df446d1fbfa87318b124bf5032c31e3447b74"}, + {file = "yarl-1.9.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ac9bb4c5ce3975aeac288cfcb5061ce60e0d14d92209e780c93954076c7c4367"}, + {file = "yarl-1.9.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3da8a678ca8b96c8606bbb8bfacd99a12ad5dd288bc6f7979baddd62f71c63ef"}, + {file = "yarl-1.9.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:13414591ff516e04fcdee8dc051c13fd3db13b673c7a4cb1350e6b2ad9639ad3"}, + {file = "yarl-1.9.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bf74d08542c3a9ea97bb8f343d4fcbd4d8f91bba5ec9d5d7f792dbe727f88938"}, + {file = "yarl-1.9.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6e7221580dc1db478464cfeef9b03b95c5852cc22894e418562997df0d074ccc"}, + {file = "yarl-1.9.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:494053246b119b041960ddcd20fd76224149cfea8ed8777b687358727911dd33"}, + {file = "yarl-1.9.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:52a25809fcbecfc63ac9ba0c0fb586f90837f5425edfd1ec9f3372b119585e45"}, + {file = "yarl-1.9.2-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:e65610c5792870d45d7b68c677681376fcf9cc1c289f23e8e8b39c1485384185"}, + {file = "yarl-1.9.2-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:1b1bba902cba32cdec51fca038fd53f8beee88b77efc373968d1ed021024cc04"}, + {file = "yarl-1.9.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:662e6016409828ee910f5d9602a2729a8a57d74b163c89a837de3fea050c7582"}, + {file = "yarl-1.9.2-cp37-cp37m-win32.whl", hash = "sha256:f364d3480bffd3aa566e886587eaca7c8c04d74f6e8933f3f2c996b7f09bee1b"}, + {file = "yarl-1.9.2-cp37-cp37m-win_amd64.whl", hash = "sha256:6a5883464143ab3ae9ba68daae8e7c5c95b969462bbe42e2464d60e7e2698368"}, + {file = "yarl-1.9.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5610f80cf43b6202e2c33ba3ec2ee0a2884f8f423c8f4f62906731d876ef4fac"}, + {file = "yarl-1.9.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:b9a4e67ad7b646cd6f0938c7ebfd60e481b7410f574c560e455e938d2da8e0f4"}, + {file = "yarl-1.9.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:83fcc480d7549ccebe9415d96d9263e2d4226798c37ebd18c930fce43dfb9574"}, + {file = "yarl-1.9.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5fcd436ea16fee7d4207c045b1e340020e58a2597301cfbcfdbe5abd2356c2fb"}, + {file = "yarl-1.9.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:84e0b1599334b1e1478db01b756e55937d4614f8654311eb26012091be109d59"}, + {file = "yarl-1.9.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3458a24e4ea3fd8930e934c129b676c27452e4ebda80fbe47b56d8c6c7a63a9e"}, + {file = "yarl-1.9.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:838162460b3a08987546e881a2bfa573960bb559dfa739e7800ceeec92e64417"}, + {file = "yarl-1.9.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f4e2d08f07a3d7d3e12549052eb5ad3eab1c349c53ac51c209a0e5991bbada78"}, + {file = "yarl-1.9.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:de119f56f3c5f0e2fb4dee508531a32b069a5f2c6e827b272d1e0ff5ac040333"}, + {file = "yarl-1.9.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:149ddea5abf329752ea5051b61bd6c1d979e13fbf122d3a1f9f0c8be6cb6f63c"}, + {file = "yarl-1.9.2-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:674ca19cbee4a82c9f54e0d1eee28116e63bc6fd1e96c43031d11cbab8b2afd5"}, + {file = "yarl-1.9.2-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:9b3152f2f5677b997ae6c804b73da05a39daa6a9e85a512e0e6823d81cdad7cc"}, + {file = "yarl-1.9.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:5415d5a4b080dc9612b1b63cba008db84e908b95848369aa1da3686ae27b6d2b"}, + {file = "yarl-1.9.2-cp38-cp38-win32.whl", hash = "sha256:f7a3d8146575e08c29ed1cd287068e6d02f1c7bdff8970db96683b9591b86ee7"}, + {file = "yarl-1.9.2-cp38-cp38-win_amd64.whl", hash = "sha256:63c48f6cef34e6319a74c727376e95626f84ea091f92c0250a98e53e62c77c72"}, + {file = "yarl-1.9.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:75df5ef94c3fdc393c6b19d80e6ef1ecc9ae2f4263c09cacb178d871c02a5ba9"}, + {file = "yarl-1.9.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c027a6e96ef77d401d8d5a5c8d6bc478e8042f1e448272e8d9752cb0aff8b5c8"}, + {file = "yarl-1.9.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f3b078dbe227f79be488ffcfc7a9edb3409d018e0952cf13f15fd6512847f3f7"}, + {file = "yarl-1.9.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:59723a029760079b7d991a401386390c4be5bfec1e7dd83e25a6a0881859e716"}, + {file = "yarl-1.9.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b03917871bf859a81ccb180c9a2e6c1e04d2f6a51d953e6a5cdd70c93d4e5a2a"}, + {file = "yarl-1.9.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c1012fa63eb6c032f3ce5d2171c267992ae0c00b9e164efe4d73db818465fac3"}, + {file = "yarl-1.9.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a74dcbfe780e62f4b5a062714576f16c2f3493a0394e555ab141bf0d746bb955"}, + {file = "yarl-1.9.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8c56986609b057b4839968ba901944af91b8e92f1725d1a2d77cbac6972b9ed1"}, + {file = "yarl-1.9.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:2c315df3293cd521033533d242d15eab26583360b58f7ee5d9565f15fee1bef4"}, + {file = "yarl-1.9.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:b7232f8dfbd225d57340e441d8caf8652a6acd06b389ea2d3222b8bc89cbfca6"}, + {file = "yarl-1.9.2-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:53338749febd28935d55b41bf0bcc79d634881195a39f6b2f767870b72514caf"}, + {file = "yarl-1.9.2-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:066c163aec9d3d073dc9ffe5dd3ad05069bcb03fcaab8d221290ba99f9f69ee3"}, + {file = "yarl-1.9.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8288d7cd28f8119b07dd49b7230d6b4562f9b61ee9a4ab02221060d21136be80"}, + {file = "yarl-1.9.2-cp39-cp39-win32.whl", hash = "sha256:b124e2a6d223b65ba8768d5706d103280914d61f5cae3afbc50fc3dfcc016623"}, + {file = "yarl-1.9.2-cp39-cp39-win_amd64.whl", hash = "sha256:61016e7d582bc46a5378ffdd02cd0314fb8ba52f40f9cf4d9a5e7dbef88dee18"}, + {file = "yarl-1.9.2.tar.gz", hash = "sha256:04ab9d4b9f587c06d801c2abfe9317b77cdf996c65a90d5e84ecc45010823571"}, +] [package.dependencies] idna = ">=2.0" @@ -742,6 +1772,10 @@ description = "A youtube-dl fork with additional features and patches" category = "main" optional = false python-versions = ">=3.6" +files = [ + {file = "yt-dlp-2021.12.27.tar.gz", hash = "sha256:2244df3759751487e796b23b67216bee98e70832a3a43c2526b0b0e0bbfbcb5b"}, + {file = "yt_dlp-2021.12.27-py2.py3-none-any.whl", hash = "sha256:bb46898a175d149c9c6bb2846056590d297aa4eafad8487c3e1315d2c6090896"}, +] [package.dependencies] mutagen = "*" @@ -749,909 +1783,6 @@ pycryptodomex = "*" websockets = "*" [metadata] -lock-version = "1.1" +lock-version = "2.0" python-versions = "~3.10.0" -content-hash = "f9cc4fc29fb495b269d95370d38ceaaaad31e021702c50ddf8756e307fceb3a1" - -[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"}, -] -aiosqlite = [ - {file = "aiosqlite-0.17.0-py3-none-any.whl", hash = "sha256:6c49dc6d3405929b1d08eeccc72306d3677503cc5e5e43771efc1e00232e8231"}, - {file = "aiosqlite-0.17.0.tar.gz", hash = "sha256:f0e6acc24bc4864149267ac82fb46dfb3be4455f99fe21df82609cc6e6baee51"}, -] -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-22.1.0-py2.py3-none-any.whl", hash = "sha256:86efa402f67bf2df34f51a335487cf46b1ec130d02b8d39fd248abfd30da551c"}, - {file = "attrs-22.1.0.tar.gz", hash = "sha256:29adc2665447e5191d0e7c568fde78b21f9672d344281d0c6e1ab085429b22b6"}, -] -beautifulsoup4 = [ - {file = "beautifulsoup4-4.10.0-py3-none-any.whl", hash = "sha256:9a315ce70049920ea4572a4055bc4bd700c940521d36fc858205ad4fcde149bf"}, - {file = "beautifulsoup4-4.10.0.tar.gz", hash = "sha256:c23ad23c521d818955a4151a67d81580319d4bf548d3d49f4223ae041ff98891"}, -] -bidict = [ - {file = "bidict-0.22.0-py3-none-any.whl", hash = "sha256:415126d23a0c81e1a8c584a8fb1f6905ea090c772571803aeee0a2242e8e7ba0"}, - {file = "bidict-0.22.0.tar.gz", hash = "sha256:5c826b3e15e97cc6e615de295756847c282a79b79c5430d3bfc909b1ac9f5bd8"}, -] -black = [ - {file = "black-22.10.0-1fixedarch-cp310-cp310-macosx_11_0_x86_64.whl", hash = "sha256:5cc42ca67989e9c3cf859e84c2bf014f6633db63d1cbdf8fdb666dcd9e77e3fa"}, - {file = "black-22.10.0-1fixedarch-cp311-cp311-macosx_11_0_x86_64.whl", hash = "sha256:5d8f74030e67087b219b032aa33a919fae8806d49c867846bfacde57f43972ef"}, - {file = "black-22.10.0-1fixedarch-cp37-cp37m-macosx_10_16_x86_64.whl", hash = "sha256:197df8509263b0b8614e1df1756b1dd41be6738eed2ba9e9769f3880c2b9d7b6"}, - {file = "black-22.10.0-1fixedarch-cp38-cp38-macosx_10_16_x86_64.whl", hash = "sha256:2644b5d63633702bc2c5f3754b1b475378fbbfb481f62319388235d0cd104c2d"}, - {file = "black-22.10.0-1fixedarch-cp39-cp39-macosx_11_0_x86_64.whl", hash = "sha256:e41a86c6c650bcecc6633ee3180d80a025db041a8e2398dcc059b3afa8382cd4"}, - {file = "black-22.10.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2039230db3c6c639bd84efe3292ec7b06e9214a2992cd9beb293d639c6402edb"}, - {file = "black-22.10.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:14ff67aec0a47c424bc99b71005202045dc09270da44a27848d534600ac64fc7"}, - {file = "black-22.10.0-cp310-cp310-win_amd64.whl", hash = "sha256:819dc789f4498ecc91438a7de64427c73b45035e2e3680c92e18795a839ebb66"}, - {file = "black-22.10.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5b9b29da4f564ba8787c119f37d174f2b69cdfdf9015b7d8c5c16121ddc054ae"}, - {file = "black-22.10.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b8b49776299fece66bffaafe357d929ca9451450f5466e997a7285ab0fe28e3b"}, - {file = "black-22.10.0-cp311-cp311-win_amd64.whl", hash = "sha256:21199526696b8f09c3997e2b4db8d0b108d801a348414264d2eb8eb2532e540d"}, - {file = "black-22.10.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1e464456d24e23d11fced2bc8c47ef66d471f845c7b7a42f3bd77bf3d1789650"}, - {file = "black-22.10.0-cp37-cp37m-win_amd64.whl", hash = "sha256:9311e99228ae10023300ecac05be5a296f60d2fd10fff31cf5c1fa4ca4b1988d"}, - {file = "black-22.10.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:fba8a281e570adafb79f7755ac8721b6cf1bbf691186a287e990c7929c7692ff"}, - {file = "black-22.10.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:915ace4ff03fdfff953962fa672d44be269deb2eaf88499a0f8805221bc68c87"}, - {file = "black-22.10.0-cp38-cp38-win_amd64.whl", hash = "sha256:444ebfb4e441254e87bad00c661fe32df9969b2bf224373a448d8aca2132b395"}, - {file = "black-22.10.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:974308c58d057a651d182208a484ce80a26dac0caef2895836a92dd6ebd725e0"}, - {file = "black-22.10.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:72ef3925f30e12a184889aac03d77d031056860ccae8a1e519f6cbb742736383"}, - {file = "black-22.10.0-cp39-cp39-win_amd64.whl", hash = "sha256:432247333090c8c5366e69627ccb363bc58514ae3e63f7fc75c54b1ea80fa7de"}, - {file = "black-22.10.0-py3-none-any.whl", hash = "sha256:c957b2b4ea88587b46cf49d1dc17681c1e672864fd7af32fc1e9664d572b3458"}, - {file = "black-22.10.0.tar.gz", hash = "sha256:f513588da599943e0cde4e32cc9879e825d58720d6557062d1098c5ad80080e1"}, -] -certifi = [ - {file = "certifi-2022.9.24-py3-none-any.whl", hash = "sha256:90c1a32f1d68f940488354e36370f6cca89f0f106db09518524c88d6ed83f382"}, - {file = "certifi-2022.9.24.tar.gz", hash = "sha256:0d9c601124e5a6ba9712dbc60d9c53c21e34f5f641fe83002317394311bdce14"}, -] -cffi = [ - {file = "cffi-1.15.1-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:a66d3508133af6e8548451b25058d5812812ec3798c886bf38ed24a98216fab2"}, - {file = "cffi-1.15.1-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:470c103ae716238bbe698d67ad020e1db9d9dba34fa5a899b5e21577e6d52ed2"}, - {file = "cffi-1.15.1-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:9ad5db27f9cabae298d151c85cf2bad1d359a1b9c686a275df03385758e2f914"}, - {file = "cffi-1.15.1-cp27-cp27m-win32.whl", hash = "sha256:b3bbeb01c2b273cca1e1e0c5df57f12dce9a4dd331b4fa1635b8bec26350bde3"}, - {file = "cffi-1.15.1-cp27-cp27m-win_amd64.whl", hash = "sha256:e00b098126fd45523dd056d2efba6c5a63b71ffe9f2bbe1a4fe1716e1d0c331e"}, - {file = "cffi-1.15.1-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:d61f4695e6c866a23a21acab0509af1cdfd2c013cf256bbf5b6b5e2695827162"}, - {file = "cffi-1.15.1-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:ed9cb427ba5504c1dc15ede7d516b84757c3e3d7868ccc85121d9310d27eed0b"}, - {file = "cffi-1.15.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:39d39875251ca8f612b6f33e6b1195af86d1b3e60086068be9cc053aa4376e21"}, - {file = "cffi-1.15.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:285d29981935eb726a4399badae8f0ffdff4f5050eaa6d0cfc3f64b857b77185"}, - {file = "cffi-1.15.1-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3eb6971dcff08619f8d91607cfc726518b6fa2a9eba42856be181c6d0d9515fd"}, - {file = "cffi-1.15.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:21157295583fe8943475029ed5abdcf71eb3911894724e360acff1d61c1d54bc"}, - {file = "cffi-1.15.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5635bd9cb9731e6d4a1132a498dd34f764034a8ce60cef4f5319c0541159392f"}, - {file = "cffi-1.15.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2012c72d854c2d03e45d06ae57f40d78e5770d252f195b93f581acf3ba44496e"}, - {file = "cffi-1.15.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd86c085fae2efd48ac91dd7ccffcfc0571387fe1193d33b6394db7ef31fe2a4"}, - {file = "cffi-1.15.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:fa6693661a4c91757f4412306191b6dc88c1703f780c8234035eac011922bc01"}, - {file = "cffi-1.15.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:59c0b02d0a6c384d453fece7566d1c7e6b7bae4fc5874ef2ef46d56776d61c9e"}, - {file = "cffi-1.15.1-cp310-cp310-win32.whl", hash = "sha256:cba9d6b9a7d64d4bd46167096fc9d2f835e25d7e4c121fb2ddfc6528fb0413b2"}, - {file = "cffi-1.15.1-cp310-cp310-win_amd64.whl", hash = "sha256:ce4bcc037df4fc5e3d184794f27bdaab018943698f4ca31630bc7f84a7b69c6d"}, - {file = "cffi-1.15.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3d08afd128ddaa624a48cf2b859afef385b720bb4b43df214f85616922e6a5ac"}, - {file = "cffi-1.15.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3799aecf2e17cf585d977b780ce79ff0dc9b78d799fc694221ce814c2c19db83"}, - {file = "cffi-1.15.1-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a591fe9e525846e4d154205572a029f653ada1a78b93697f3b5a8f1f2bc055b9"}, - {file = "cffi-1.15.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3548db281cd7d2561c9ad9984681c95f7b0e38881201e157833a2342c30d5e8c"}, - {file = "cffi-1.15.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:91fc98adde3d7881af9b59ed0294046f3806221863722ba7d8d120c575314325"}, - {file = "cffi-1.15.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:94411f22c3985acaec6f83c6df553f2dbe17b698cc7f8ae751ff2237d96b9e3c"}, - {file = "cffi-1.15.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:03425bdae262c76aad70202debd780501fabeaca237cdfddc008987c0e0f59ef"}, - {file = "cffi-1.15.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:cc4d65aeeaa04136a12677d3dd0b1c0c94dc43abac5860ab33cceb42b801c1e8"}, - {file = "cffi-1.15.1-cp311-cp311-win32.whl", hash = "sha256:a0f100c8912c114ff53e1202d0078b425bee3649ae34d7b070e9697f93c5d52d"}, - {file = "cffi-1.15.1-cp311-cp311-win_amd64.whl", hash = "sha256:04ed324bda3cda42b9b695d51bb7d54b680b9719cfab04227cdd1e04e5de3104"}, - {file = "cffi-1.15.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50a74364d85fd319352182ef59c5c790484a336f6db772c1a9231f1c3ed0cbd7"}, - {file = "cffi-1.15.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e263d77ee3dd201c3a142934a086a4450861778baaeeb45db4591ef65550b0a6"}, - {file = "cffi-1.15.1-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cec7d9412a9102bdc577382c3929b337320c4c4c4849f2c5cdd14d7368c5562d"}, - {file = "cffi-1.15.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4289fc34b2f5316fbb762d75362931e351941fa95fa18789191b33fc4cf9504a"}, - {file = "cffi-1.15.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:173379135477dc8cac4bc58f45db08ab45d228b3363adb7af79436135d028405"}, - {file = "cffi-1.15.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:6975a3fac6bc83c4a65c9f9fcab9e47019a11d3d2cf7f3c0d03431bf145a941e"}, - {file = "cffi-1.15.1-cp36-cp36m-win32.whl", hash = "sha256:2470043b93ff09bf8fb1d46d1cb756ce6132c54826661a32d4e4d132e1977adf"}, - {file = "cffi-1.15.1-cp36-cp36m-win_amd64.whl", hash = "sha256:30d78fbc8ebf9c92c9b7823ee18eb92f2e6ef79b45ac84db507f52fbe3ec4497"}, - {file = "cffi-1.15.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:198caafb44239b60e252492445da556afafc7d1e3ab7a1fb3f0584ef6d742375"}, - {file = "cffi-1.15.1-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5ef34d190326c3b1f822a5b7a45f6c4535e2f47ed06fec77d3d799c450b2651e"}, - {file = "cffi-1.15.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8102eaf27e1e448db915d08afa8b41d6c7ca7a04b7d73af6514df10a3e74bd82"}, - {file = "cffi-1.15.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5df2768244d19ab7f60546d0c7c63ce1581f7af8b5de3eb3004b9b6fc8a9f84b"}, - {file = "cffi-1.15.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a8c4917bd7ad33e8eb21e9a5bbba979b49d9a97acb3a803092cbc1133e20343c"}, - {file = "cffi-1.15.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0e2642fe3142e4cc4af0799748233ad6da94c62a8bec3a6648bf8ee68b1c7426"}, - {file = "cffi-1.15.1-cp37-cp37m-win32.whl", hash = "sha256:e229a521186c75c8ad9490854fd8bbdd9a0c9aa3a524326b55be83b54d4e0ad9"}, - {file = "cffi-1.15.1-cp37-cp37m-win_amd64.whl", hash = "sha256:a0b71b1b8fbf2b96e41c4d990244165e2c9be83d54962a9a1d118fd8657d2045"}, - {file = "cffi-1.15.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:320dab6e7cb2eacdf0e658569d2575c4dad258c0fcc794f46215e1e39f90f2c3"}, - {file = "cffi-1.15.1-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1e74c6b51a9ed6589199c787bf5f9875612ca4a8a0785fb2d4a84429badaf22a"}, - {file = "cffi-1.15.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a5c84c68147988265e60416b57fc83425a78058853509c1b0629c180094904a5"}, - {file = "cffi-1.15.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3b926aa83d1edb5aa5b427b4053dc420ec295a08e40911296b9eb1b6170f6cca"}, - {file = "cffi-1.15.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:87c450779d0914f2861b8526e035c5e6da0a3199d8f1add1a665e1cbc6fc6d02"}, - {file = "cffi-1.15.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4f2c9f67e9821cad2e5f480bc8d83b8742896f1242dba247911072d4fa94c192"}, - {file = "cffi-1.15.1-cp38-cp38-win32.whl", hash = "sha256:8b7ee99e510d7b66cdb6c593f21c043c248537a32e0bedf02e01e9553a172314"}, - {file = "cffi-1.15.1-cp38-cp38-win_amd64.whl", hash = "sha256:00a9ed42e88df81ffae7a8ab6d9356b371399b91dbdf0c3cb1e84c03a13aceb5"}, - {file = "cffi-1.15.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:54a2db7b78338edd780e7ef7f9f6c442500fb0d41a5a4ea24fff1c929d5af585"}, - {file = "cffi-1.15.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:fcd131dd944808b5bdb38e6f5b53013c5aa4f334c5cad0c72742f6eba4b73db0"}, - {file = "cffi-1.15.1-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7473e861101c9e72452f9bf8acb984947aa1661a7704553a9f6e4baa5ba64415"}, - {file = "cffi-1.15.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6c9a799e985904922a4d207a94eae35c78ebae90e128f0c4e521ce339396be9d"}, - {file = "cffi-1.15.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3bcde07039e586f91b45c88f8583ea7cf7a0770df3a1649627bf598332cb6984"}, - {file = "cffi-1.15.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:33ab79603146aace82c2427da5ca6e58f2b3f2fb5da893ceac0c42218a40be35"}, - {file = "cffi-1.15.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5d598b938678ebf3c67377cdd45e09d431369c3b1a5b331058c338e201f12b27"}, - {file = "cffi-1.15.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:db0fbb9c62743ce59a9ff687eb5f4afbe77e5e8403d6697f7446e5f609976f76"}, - {file = "cffi-1.15.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:98d85c6a2bef81588d9227dde12db8a7f47f639f4a17c9ae08e773aa9c697bf3"}, - {file = "cffi-1.15.1-cp39-cp39-win32.whl", hash = "sha256:40f4774f5a9d4f5e344f31a32b5096977b5d48560c5592e2f3d2c4374bd543ee"}, - {file = "cffi-1.15.1-cp39-cp39-win_amd64.whl", hash = "sha256:70df4e3b545a17496c9b3f41f5115e69a4f2e77e94e1d2a8e1070bc0c38c8a3c"}, - {file = "cffi-1.15.1.tar.gz", hash = "sha256:d400bfb9a37b1351253cb402671cea7e89bdecc294e8016a707f6d1d8ac934f9"}, -] -chardet = [ - {file = "chardet-3.0.4-py2.py3-none-any.whl", hash = "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691"}, - {file = "chardet-3.0.4.tar.gz", hash = "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae"}, -] -charset-normalizer = [ - {file = "charset-normalizer-2.1.1.tar.gz", hash = "sha256:5a3d016c7c547f69d6f81fb0db9449ce888b418b5b9952cc5e6e66843e9dd845"}, - {file = "charset_normalizer-2.1.1-py3-none-any.whl", hash = "sha256:83e9a75d1911279afd89352c68b45348559d1fc0506b054b346651b5e7fee29f"}, -] -click = [ - {file = "click-8.1.3-py3-none-any.whl", hash = "sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48"}, - {file = "click-8.1.3.tar.gz", hash = "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e"}, -] -colorama = [ - {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, - {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, -] -discord-py = [ - {file = "discord.py-1.6.0-py3-none-any.whl", hash = "sha256:3df148daf6fbcc7ab5b11042368a3cd5f7b730b62f09fb5d3cbceff59bcfbb12"}, - {file = "discord.py-1.6.0.tar.gz", hash = "sha256:ba8be99ff1b8c616f7b6dcb700460d0222b29d4c11048e74366954c465fdd05f"}, -] -exceptiongroup = [ - {file = "exceptiongroup-1.0.4-py3-none-any.whl", hash = "sha256:542adf9dea4055530d6e1279602fa5cb11dab2395fa650b8674eaec35fc4a828"}, - {file = "exceptiongroup-1.0.4.tar.gz", hash = "sha256:bd14967b79cd9bdb54d97323216f8fdf533e278df937aa2a90089e7d6e06e5ec"}, -] -feedparser = [ - {file = "feedparser-6.0.10-py3-none-any.whl", hash = "sha256:79c257d526d13b944e965f6095700587f27388e50ea16fd245babe4dfae7024f"}, - {file = "feedparser-6.0.10.tar.gz", hash = "sha256:27da485f4637ce7163cdeab13a80312b93b7d0c1b775bef4a47629a3110bca51"}, -] -googletrans = [ - {file = "googletrans-4.0.0rc1.tar.gz", hash = "sha256:74df47b092e2d566522019d149e3f1d75732570ad76eaf8e14aebeffc126c372"}, -] -h11 = [ - {file = "h11-0.9.0-py2.py3-none-any.whl", hash = "sha256:4bc6d6a1238b7615b266ada57e0618568066f57dd6fa967d1290ec9309b2f2f1"}, - {file = "h11-0.9.0.tar.gz", hash = "sha256:33d4bca7be0fa039f4e84d50ab00531047e53d6ee8ffbc83501ea602c169cae1"}, -] -h2 = [ - {file = "h2-3.2.0-py2.py3-none-any.whl", hash = "sha256:61e0f6601fa709f35cdb730863b4e5ec7ad449792add80d1410d4174ed139af5"}, - {file = "h2-3.2.0.tar.gz", hash = "sha256:875f41ebd6f2c44781259005b157faed1a5031df3ae5aa7bcb4628a6c0782f14"}, -] -hpack = [ - {file = "hpack-3.0.0-py2.py3-none-any.whl", hash = "sha256:0edd79eda27a53ba5be2dfabf3b15780928a0dff6eb0c60a3d6767720e970c89"}, - {file = "hpack-3.0.0.tar.gz", hash = "sha256:8eec9c1f4bfae3408a3f30500261f7e6a65912dc138526ea054f9ad98892e9d2"}, -] -hstspreload = [ - {file = "hstspreload-2022.11.1-py3-none-any.whl", hash = "sha256:ddd7c0e3b34711c1a370e1ec251c1238080af85c04c06ec2392b49a9977564e9"}, - {file = "hstspreload-2022.11.1.tar.gz", hash = "sha256:f259fc5726a52b7c626af5ad060f4b8739c109f375d386339883b88c6e03c01b"}, -] -httpcore = [ - {file = "httpcore-0.9.1-py3-none-any.whl", hash = "sha256:9850fe97a166a794d7e920590d5ec49a05488884c9fc8b5dba8561effab0c2a0"}, - {file = "httpcore-0.9.1.tar.gz", hash = "sha256:ecc5949310d9dae4de64648a4ce529f86df1f232ce23dcfefe737c24d21dfbe9"}, -] -httpx = [ - {file = "httpx-0.13.3-py3-none-any.whl", hash = "sha256:32d930858eab677bc29a742aaa4f096de259f1c78c68a90ad11f5c3c04f08335"}, - {file = "httpx-0.13.3.tar.gz", hash = "sha256:3642bd13e90b80ba8a243a730275eb10a4c26ec96f5fc16b87e458d4ab21efae"}, -] -hyperframe = [ - {file = "hyperframe-5.2.0-py2.py3-none-any.whl", hash = "sha256:5187962cb16dcc078f23cb5a4b110098d546c3f41ff2d4038a9896893bbd0b40"}, - {file = "hyperframe-5.2.0.tar.gz", hash = "sha256:a9f5c17f2cc3c719b917c4f33ed1c61bd1f8dfac4b1bd23b7c80b3400971b41f"}, -] -idna = [ - {file = "idna-2.10-py2.py3-none-any.whl", hash = "sha256:b97d804b1e9b523befed77c48dacec60e6dcb0b5391d57af6a65a312a90648c0"}, - {file = "idna-2.10.tar.gz", hash = "sha256:b307872f855b18632ce0c21c5e45be78c0ea7ae4c15c828c20788b26921eb3f6"}, -] -iniconfig = [ - {file = "iniconfig-1.1.1-py2.py3-none-any.whl", hash = "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3"}, - {file = "iniconfig-1.1.1.tar.gz", hash = "sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32"}, -] -lxml = [ - {file = "lxml-4.9.1-cp27-cp27m-macosx_10_15_x86_64.whl", hash = "sha256:98cafc618614d72b02185ac583c6f7796202062c41d2eeecdf07820bad3295ed"}, - {file = "lxml-4.9.1-cp27-cp27m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c62e8dd9754b7debda0c5ba59d34509c4688f853588d75b53c3791983faa96fc"}, - {file = "lxml-4.9.1-cp27-cp27m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:21fb3d24ab430fc538a96e9fbb9b150029914805d551deeac7d7822f64631dfc"}, - {file = "lxml-4.9.1-cp27-cp27m-win32.whl", hash = "sha256:86e92728ef3fc842c50a5cb1d5ba2bc66db7da08a7af53fb3da79e202d1b2cd3"}, - {file = "lxml-4.9.1-cp27-cp27m-win_amd64.whl", hash = "sha256:4cfbe42c686f33944e12f45a27d25a492cc0e43e1dc1da5d6a87cbcaf2e95627"}, - {file = "lxml-4.9.1-cp27-cp27mu-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:dad7b164905d3e534883281c050180afcf1e230c3d4a54e8038aa5cfcf312b84"}, - {file = "lxml-4.9.1-cp27-cp27mu-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:a614e4afed58c14254e67862456d212c4dcceebab2eaa44d627c2ca04bf86837"}, - {file = "lxml-4.9.1-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:f9ced82717c7ec65a67667bb05865ffe38af0e835cdd78728f1209c8fffe0cad"}, - {file = "lxml-4.9.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:d9fc0bf3ff86c17348dfc5d322f627d78273eba545db865c3cd14b3f19e57fa5"}, - {file = "lxml-4.9.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:e5f66bdf0976ec667fc4594d2812a00b07ed14d1b44259d19a41ae3fff99f2b8"}, - {file = "lxml-4.9.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:fe17d10b97fdf58155f858606bddb4e037b805a60ae023c009f760d8361a4eb8"}, - {file = "lxml-4.9.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:8caf4d16b31961e964c62194ea3e26a0e9561cdf72eecb1781458b67ec83423d"}, - {file = "lxml-4.9.1-cp310-cp310-win32.whl", hash = "sha256:4780677767dd52b99f0af1f123bc2c22873d30b474aa0e2fc3fe5e02217687c7"}, - {file = "lxml-4.9.1-cp310-cp310-win_amd64.whl", hash = "sha256:b122a188cd292c4d2fcd78d04f863b789ef43aa129b233d7c9004de08693728b"}, - {file = "lxml-4.9.1-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:be9eb06489bc975c38706902cbc6888f39e946b81383abc2838d186f0e8b6a9d"}, - {file = "lxml-4.9.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:f1be258c4d3dc609e654a1dc59d37b17d7fef05df912c01fc2e15eb43a9735f3"}, - {file = "lxml-4.9.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:927a9dd016d6033bc12e0bf5dee1dde140235fc8d0d51099353c76081c03dc29"}, - {file = "lxml-4.9.1-cp35-cp35m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9232b09f5efee6a495a99ae6824881940d6447debe272ea400c02e3b68aad85d"}, - {file = "lxml-4.9.1-cp35-cp35m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:04da965dfebb5dac2619cb90fcf93efdb35b3c6994fea58a157a834f2f94b318"}, - {file = "lxml-4.9.1-cp35-cp35m-win32.whl", hash = "sha256:4d5bae0a37af799207140652a700f21a85946f107a199bcb06720b13a4f1f0b7"}, - {file = "lxml-4.9.1-cp35-cp35m-win_amd64.whl", hash = "sha256:4878e667ebabe9b65e785ac8da4d48886fe81193a84bbe49f12acff8f7a383a4"}, - {file = "lxml-4.9.1-cp36-cp36m-macosx_10_15_x86_64.whl", hash = "sha256:1355755b62c28950f9ce123c7a41460ed9743c699905cbe664a5bcc5c9c7c7fb"}, - {file = "lxml-4.9.1-cp36-cp36m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:bcaa1c495ce623966d9fc8a187da80082334236a2a1c7e141763ffaf7a405067"}, - {file = "lxml-4.9.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6eafc048ea3f1b3c136c71a86db393be36b5b3d9c87b1c25204e7d397cee9536"}, - {file = "lxml-4.9.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:13c90064b224e10c14dcdf8086688d3f0e612db53766e7478d7754703295c7c8"}, - {file = "lxml-4.9.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:206a51077773c6c5d2ce1991327cda719063a47adc02bd703c56a662cdb6c58b"}, - {file = "lxml-4.9.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:e8f0c9d65da595cfe91713bc1222af9ecabd37971762cb830dea2fc3b3bb2acf"}, - {file = "lxml-4.9.1-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:8f0a4d179c9a941eb80c3a63cdb495e539e064f8054230844dcf2fcb812b71d3"}, - {file = "lxml-4.9.1-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:830c88747dce8a3e7525defa68afd742b4580df6aa2fdd6f0855481e3994d391"}, - {file = "lxml-4.9.1-cp36-cp36m-win32.whl", hash = "sha256:1e1cf47774373777936c5aabad489fef7b1c087dcd1f426b621fda9dcc12994e"}, - {file = "lxml-4.9.1-cp36-cp36m-win_amd64.whl", hash = "sha256:5974895115737a74a00b321e339b9c3f45c20275d226398ae79ac008d908bff7"}, - {file = "lxml-4.9.1-cp37-cp37m-macosx_10_15_x86_64.whl", hash = "sha256:1423631e3d51008871299525b541413c9b6c6423593e89f9c4cfbe8460afc0a2"}, - {file = "lxml-4.9.1-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:2aaf6a0a6465d39b5ca69688fce82d20088c1838534982996ec46633dc7ad6cc"}, - {file = "lxml-4.9.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:9f36de4cd0c262dd9927886cc2305aa3f2210db437aa4fed3fb4940b8bf4592c"}, - {file = "lxml-4.9.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:ae06c1e4bc60ee076292e582a7512f304abdf6c70db59b56745cca1684f875a4"}, - {file = "lxml-4.9.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:57e4d637258703d14171b54203fd6822fda218c6c2658a7d30816b10995f29f3"}, - {file = "lxml-4.9.1-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:6d279033bf614953c3fc4a0aa9ac33a21e8044ca72d4fa8b9273fe75359d5cca"}, - {file = "lxml-4.9.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:a60f90bba4c37962cbf210f0188ecca87daafdf60271f4c6948606e4dabf8785"}, - {file = "lxml-4.9.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:6ca2264f341dd81e41f3fffecec6e446aa2121e0b8d026fb5130e02de1402785"}, - {file = "lxml-4.9.1-cp37-cp37m-win32.whl", hash = "sha256:27e590352c76156f50f538dbcebd1925317a0f70540f7dc8c97d2931c595783a"}, - {file = "lxml-4.9.1-cp37-cp37m-win_amd64.whl", hash = "sha256:eea5d6443b093e1545ad0210e6cf27f920482bfcf5c77cdc8596aec73523bb7e"}, - {file = "lxml-4.9.1-cp38-cp38-macosx_10_15_x86_64.whl", hash = "sha256:f05251bbc2145349b8d0b77c0d4e5f3b228418807b1ee27cefb11f69ed3d233b"}, - {file = "lxml-4.9.1-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:487c8e61d7acc50b8be82bda8c8d21d20e133c3cbf41bd8ad7eb1aaeb3f07c97"}, - {file = "lxml-4.9.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:8d1a92d8e90b286d491e5626af53afef2ba04da33e82e30744795c71880eaa21"}, - {file = "lxml-4.9.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:b570da8cd0012f4af9fa76a5635cd31f707473e65a5a335b186069d5c7121ff2"}, - {file = "lxml-4.9.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5ef87fca280fb15342726bd5f980f6faf8b84a5287fcc2d4962ea8af88b35130"}, - {file = "lxml-4.9.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:93e414e3206779ef41e5ff2448067213febf260ba747fc65389a3ddaa3fb8715"}, - {file = "lxml-4.9.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:6653071f4f9bac46fbc30f3c7838b0e9063ee335908c5d61fb7a4a86c8fd2036"}, - {file = "lxml-4.9.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:32a73c53783becdb7eaf75a2a1525ea8e49379fb7248c3eeefb9412123536387"}, - {file = "lxml-4.9.1-cp38-cp38-win32.whl", hash = "sha256:1a7c59c6ffd6ef5db362b798f350e24ab2cfa5700d53ac6681918f314a4d3b94"}, - {file = "lxml-4.9.1-cp38-cp38-win_amd64.whl", hash = "sha256:1436cf0063bba7888e43f1ba8d58824f085410ea2025befe81150aceb123e345"}, - {file = "lxml-4.9.1-cp39-cp39-macosx_10_15_x86_64.whl", hash = "sha256:4beea0f31491bc086991b97517b9683e5cfb369205dac0148ef685ac12a20a67"}, - {file = "lxml-4.9.1-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:41fb58868b816c202e8881fd0f179a4644ce6e7cbbb248ef0283a34b73ec73bb"}, - {file = "lxml-4.9.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:bd34f6d1810d9354dc7e35158aa6cc33456be7706df4420819af6ed966e85448"}, - {file = "lxml-4.9.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:edffbe3c510d8f4bf8640e02ca019e48a9b72357318383ca60e3330c23aaffc7"}, - {file = "lxml-4.9.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6d949f53ad4fc7cf02c44d6678e7ff05ec5f5552b235b9e136bd52e9bf730b91"}, - {file = "lxml-4.9.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:079b68f197c796e42aa80b1f739f058dcee796dc725cc9a1be0cdb08fc45b000"}, - {file = "lxml-4.9.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:9c3a88d20e4fe4a2a4a84bf439a5ac9c9aba400b85244c63a1ab7088f85d9d25"}, - {file = "lxml-4.9.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:4e285b5f2bf321fc0857b491b5028c5f276ec0c873b985d58d7748ece1d770dd"}, - {file = "lxml-4.9.1-cp39-cp39-win32.whl", hash = "sha256:ef72013e20dd5ba86a8ae1aed7f56f31d3374189aa8b433e7b12ad182c0d2dfb"}, - {file = "lxml-4.9.1-cp39-cp39-win_amd64.whl", hash = "sha256:10d2017f9150248563bb579cd0d07c61c58da85c922b780060dcc9a3aa9f432d"}, - {file = "lxml-4.9.1-pp37-pypy37_pp73-macosx_10_15_x86_64.whl", hash = "sha256:0538747a9d7827ce3e16a8fdd201a99e661c7dee3c96c885d8ecba3c35d1032c"}, - {file = "lxml-4.9.1-pp37-pypy37_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:0645e934e940107e2fdbe7c5b6fb8ec6232444260752598bc4d09511bd056c0b"}, - {file = "lxml-4.9.1-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:6daa662aba22ef3258934105be2dd9afa5bb45748f4f702a3b39a5bf53a1f4dc"}, - {file = "lxml-4.9.1-pp38-pypy38_pp73-macosx_10_15_x86_64.whl", hash = "sha256:603a464c2e67d8a546ddaa206d98e3246e5db05594b97db844c2f0a1af37cf5b"}, - {file = "lxml-4.9.1-pp38-pypy38_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:c4b2e0559b68455c085fb0f6178e9752c4be3bba104d6e881eb5573b399d1eb2"}, - {file = "lxml-4.9.1-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:0f3f0059891d3254c7b5fb935330d6db38d6519ecd238ca4fce93c234b4a0f73"}, - {file = "lxml-4.9.1-pp39-pypy39_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:c852b1530083a620cb0de5f3cd6826f19862bafeaf77586f1aef326e49d95f0c"}, - {file = "lxml-4.9.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:287605bede6bd36e930577c5925fcea17cb30453d96a7b4c63c14a257118dbb9"}, - {file = "lxml-4.9.1.tar.gz", hash = "sha256:fe749b052bb7233fe5d072fcb549221a8cb1a16725c47c37e42b0b9cb3ff2c3f"}, -] -mpmath = [ - {file = "mpmath-1.2.1-py3-none-any.whl", hash = "sha256:604bc21bd22d2322a177c73bdb573994ef76e62edd595d17e00aff24b0667e5c"}, - {file = "mpmath-1.2.1.tar.gz", hash = "sha256:79ffb45cf9f4b101a807595bcb3e72e0396202e0b1d25d689134b48c4216a81a"}, -] -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"}, -] -mutagen = [ - {file = "mutagen-1.46.0-py3-none-any.whl", hash = "sha256:8af0728aa2d5c3ee5a727e28d0627966641fddfe804c23eabb5926a4d770aed5"}, - {file = "mutagen-1.46.0.tar.gz", hash = "sha256:6e5f8ba84836b99fe60be5fb27f84be4ad919bbb6b49caa6ae81e70584b55e58"}, -] -mypy = [ - {file = "mypy-0.990-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:aaf1be63e0207d7d17be942dcf9a6b641745581fe6c64df9a38deb562a7dbafa"}, - {file = "mypy-0.990-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d555aa7f44cecb7ea3c0ac69d58b1a5afb92caa017285a8e9c4efbf0518b61b4"}, - {file = "mypy-0.990-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8f694d6d09a460b117dccb6857dda269188e3437c880d7b60fa0014fa872d1e9"}, - {file = "mypy-0.990-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:269f0dfb6463b8780333310ff4b5134425157ef0d2b1d614015adaf6d6a7eabd"}, - {file = "mypy-0.990-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:8798c8ed83aa809f053abff08664bdca056038f5a02af3660de00b7290b64c47"}, - {file = "mypy-0.990-cp310-cp310-win_amd64.whl", hash = "sha256:47a9955214615108c3480a500cfda8513a0b1cd3c09a1ed42764ca0dd7b931dd"}, - {file = "mypy-0.990-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:4a8a6c10f4c63fbf6ad6c03eba22c9331b3946a4cec97f008e9ffb4d3b31e8e2"}, - {file = "mypy-0.990-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:cd2dd3730ba894ec2a2082cc703fbf3e95a08479f7be84912e3131fc68809d46"}, - {file = "mypy-0.990-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7da0005e47975287a92b43276e460ac1831af3d23032c34e67d003388a0ce8d0"}, - {file = "mypy-0.990-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:262c543ef24deb10470a3c1c254bb986714e2b6b1a67d66daf836a548a9f316c"}, - {file = "mypy-0.990-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:3ff201a0c6d3ea029d73b1648943387d75aa052491365b101f6edd5570d018ea"}, - {file = "mypy-0.990-cp311-cp311-win_amd64.whl", hash = "sha256:1767830da2d1afa4e62b684647af0ff79b401f004d7fa08bc5b0ce2d45bcd5ec"}, - {file = "mypy-0.990-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:6826d9c4d85bbf6d68cb279b561de6a4d8d778ca8e9ab2d00ee768ab501a9852"}, - {file = "mypy-0.990-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:46897755f944176fbc504178422a5a2875bbf3f7436727374724842c0987b5af"}, - {file = "mypy-0.990-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:0680389c34284287fe00e82fc8bccdea9aff318f7e7d55b90d967a13a9606013"}, - {file = "mypy-0.990-cp37-cp37m-win_amd64.whl", hash = "sha256:b08541a06eed35b543ae1a6b301590eb61826a1eb099417676ddc5a42aa151c5"}, - {file = "mypy-0.990-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:be88d665e76b452c26fb2bdc3d54555c01226fba062b004ede780b190a50f9db"}, - {file = "mypy-0.990-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:9b8f4a8213b1fd4b751e26b59ae0e0c12896568d7e805861035c7a15ed6dc9eb"}, - {file = "mypy-0.990-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:2b6f85c2ad378e3224e017904a051b26660087b3b76490d533b7344f1546d3ff"}, - {file = "mypy-0.990-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1ee5f99817ee70254e7eb5cf97c1b11dda29c6893d846c8b07bce449184e9466"}, - {file = "mypy-0.990-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:49082382f571c3186ce9ea0bd627cb1345d4da8d44a8377870f4442401f0a706"}, - {file = "mypy-0.990-cp38-cp38-win_amd64.whl", hash = "sha256:aba38e3dd66bdbafbbfe9c6e79637841928ea4c79b32e334099463c17b0d90ef"}, - {file = "mypy-0.990-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:9d851c09b981a65d9d283a8ccb5b1d0b698e580493416a10942ef1a04b19fd37"}, - {file = "mypy-0.990-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:d847dd23540e2912d9667602271e5ebf25e5788e7da46da5ffd98e7872616e8e"}, - {file = "mypy-0.990-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:cc6019808580565040cd2a561b593d7c3c646badd7e580e07d875eb1bf35c695"}, - {file = "mypy-0.990-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2a3150d409609a775c8cb65dbe305c4edd7fe576c22ea79d77d1454acd9aeda8"}, - {file = "mypy-0.990-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:3227f14fe943524f5794679156488f18bf8d34bfecd4623cf76bc55958d229c5"}, - {file = "mypy-0.990-cp39-cp39-win_amd64.whl", hash = "sha256:c76c769c46a1e6062a84837badcb2a7b0cdb153d68601a61f60739c37d41cc74"}, - {file = "mypy-0.990-py3-none-any.whl", hash = "sha256:8f1940325a8ed460ba03d19ab83742260fa9534804c317224e5d4e5aa588e2d6"}, - {file = "mypy-0.990.tar.gz", hash = "sha256:72382cb609142dba3f04140d016c94b4092bc7b4d98ca718740dc989e5271b8d"}, -] -mypy-extensions = [ - {file = "mypy_extensions-0.4.3-py2.py3-none-any.whl", hash = "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d"}, - {file = "mypy_extensions-0.4.3.tar.gz", hash = "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"}, -] -numpy = [ - {file = "numpy-1.23.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:95d79ada05005f6f4f337d3bb9de8a7774f259341c70bc88047a1f7b96a4bcb2"}, - {file = "numpy-1.23.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:926db372bc4ac1edf81cfb6c59e2a881606b409ddc0d0920b988174b2e2a767f"}, - {file = "numpy-1.23.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c237129f0e732885c9a6076a537e974160482eab8f10db6292e92154d4c67d71"}, - {file = "numpy-1.23.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a8365b942f9c1a7d0f0dc974747d99dd0a0cdfc5949a33119caf05cb314682d3"}, - {file = "numpy-1.23.4-cp310-cp310-win32.whl", hash = "sha256:2341f4ab6dba0834b685cce16dad5f9b6606ea8a00e6da154f5dbded70fdc4dd"}, - {file = "numpy-1.23.4-cp310-cp310-win_amd64.whl", hash = "sha256:d331afac87c92373826af83d2b2b435f57b17a5c74e6268b79355b970626e329"}, - {file = "numpy-1.23.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:488a66cb667359534bc70028d653ba1cf307bae88eab5929cd707c761ff037db"}, - {file = "numpy-1.23.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ce03305dd694c4873b9429274fd41fc7eb4e0e4dea07e0af97a933b079a5814f"}, - {file = "numpy-1.23.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8981d9b5619569899666170c7c9748920f4a5005bf79c72c07d08c8a035757b0"}, - {file = "numpy-1.23.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7a70a7d3ce4c0e9284e92285cba91a4a3f5214d87ee0e95928f3614a256a1488"}, - {file = "numpy-1.23.4-cp311-cp311-win32.whl", hash = "sha256:5e13030f8793e9ee42f9c7d5777465a560eb78fa7e11b1c053427f2ccab90c79"}, - {file = "numpy-1.23.4-cp311-cp311-win_amd64.whl", hash = "sha256:7607b598217745cc40f751da38ffd03512d33ec06f3523fb0b5f82e09f6f676d"}, - {file = "numpy-1.23.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:7ab46e4e7ec63c8a5e6dbf5c1b9e1c92ba23a7ebecc86c336cb7bf3bd2fb10e5"}, - {file = "numpy-1.23.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:a8aae2fb3180940011b4862b2dd3756616841c53db9734b27bb93813cd79fce6"}, - {file = "numpy-1.23.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8c053d7557a8f022ec823196d242464b6955a7e7e5015b719e76003f63f82d0f"}, - {file = "numpy-1.23.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a0882323e0ca4245eb0a3d0a74f88ce581cc33aedcfa396e415e5bba7bf05f68"}, - {file = "numpy-1.23.4-cp38-cp38-win32.whl", hash = "sha256:dada341ebb79619fe00a291185bba370c9803b1e1d7051610e01ed809ef3a4ba"}, - {file = "numpy-1.23.4-cp38-cp38-win_amd64.whl", hash = "sha256:0fe563fc8ed9dc4474cbf70742673fc4391d70f4363f917599a7fa99f042d5a8"}, - {file = "numpy-1.23.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c67b833dbccefe97cdd3f52798d430b9d3430396af7cdb2a0c32954c3ef73894"}, - {file = "numpy-1.23.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f76025acc8e2114bb664294a07ede0727aa75d63a06d2fae96bf29a81747e4a7"}, - {file = "numpy-1.23.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:12ac457b63ec8ded85d85c1e17d85efd3c2b0967ca39560b307a35a6703a4735"}, - {file = "numpy-1.23.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:95de7dc7dc47a312f6feddd3da2500826defdccbc41608d0031276a24181a2c0"}, - {file = "numpy-1.23.4-cp39-cp39-win32.whl", hash = "sha256:f2f390aa4da44454db40a1f0201401f9036e8d578a25f01a6e237cea238337ef"}, - {file = "numpy-1.23.4-cp39-cp39-win_amd64.whl", hash = "sha256:f260da502d7441a45695199b4e7fd8ca87db659ba1c78f2bbf31f934fe76ae0e"}, - {file = "numpy-1.23.4-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:61be02e3bf810b60ab74e81d6d0d36246dbfb644a462458bb53b595791251911"}, - {file = "numpy-1.23.4-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:296d17aed51161dbad3c67ed6d164e51fcd18dbcd5dd4f9d0a9c6055dce30810"}, - {file = "numpy-1.23.4-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:4d52914c88b4930dafb6c48ba5115a96cbab40f45740239d9f4159c4ba779962"}, - {file = "numpy-1.23.4.tar.gz", hash = "sha256:ed2cc92af0efad20198638c69bb0fc2870a58dabfba6eb722c933b48556c686c"}, -] -opencv-python = [ - {file = "opencv-python-4.6.0.66.tar.gz", hash = "sha256:c5bfae41ad4031e66bb10ec4a0a2ffd3e514d092652781e8b1ac98d1b59f1158"}, - {file = "opencv_python-4.6.0.66-cp36-abi3-macosx_10_15_x86_64.whl", hash = "sha256:e6e448b62afc95c5b58f97e87ef84699e6607fe5c58730a03301c52496005cae"}, - {file = "opencv_python-4.6.0.66-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5af8ba35a4fcb8913ffb86e92403e9a656a4bff4a645d196987468f0f8947875"}, - {file = "opencv_python-4.6.0.66-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dbdc84a9b4ea2cbae33861652d25093944b9959279200b7ae0badd32439f74de"}, - {file = "opencv_python-4.6.0.66-cp36-abi3-win32.whl", hash = "sha256:f482e78de6e7b0b060ff994ffd859bddc3f7f382bb2019ef157b0ea8ca8712f5"}, - {file = "opencv_python-4.6.0.66-cp36-abi3-win_amd64.whl", hash = "sha256:0dc82a3d8630c099d2f3ac1b1aabee164e8188db54a786abb7a4e27eba309440"}, - {file = "opencv_python-4.6.0.66-cp37-abi3-macosx_11_0_arm64.whl", hash = "sha256:6e32af22e3202748bd233ed8f538741876191863882eba44e332d1a34993165b"}, -] -packaging = [ - {file = "packaging-21.3-py3-none-any.whl", hash = "sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522"}, - {file = "packaging-21.3.tar.gz", hash = "sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb"}, -] -pathspec = [ - {file = "pathspec-0.10.2-py3-none-any.whl", hash = "sha256:88c2606f2c1e818b978540f73ecc908e13999c6c3a383daf3705652ae79807a5"}, - {file = "pathspec-0.10.2.tar.gz", hash = "sha256:8f6bf73e5758fd365ef5d58ce09ac7c27d2833a8d7da51712eac6e27e35141b0"}, -] -pillow = [ - {file = "Pillow-8.4.0-cp310-cp310-macosx_10_10_universal2.whl", hash = "sha256:81f8d5c81e483a9442d72d182e1fb6dcb9723f289a57e8030811bac9ea3fef8d"}, - {file = "Pillow-8.4.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:3f97cfb1e5a392d75dd8b9fd274d205404729923840ca94ca45a0af57e13dbe6"}, - {file = "Pillow-8.4.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eb9fc393f3c61f9054e1ed26e6fe912c7321af2f41ff49d3f83d05bacf22cc78"}, - {file = "Pillow-8.4.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d82cdb63100ef5eedb8391732375e6d05993b765f72cb34311fab92103314649"}, - {file = "Pillow-8.4.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:62cc1afda735a8d109007164714e73771b499768b9bb5afcbbee9d0ff374b43f"}, - {file = "Pillow-8.4.0-cp310-cp310-win32.whl", hash = "sha256:e3dacecfbeec9a33e932f00c6cd7996e62f53ad46fbe677577394aaa90ee419a"}, - {file = "Pillow-8.4.0-cp310-cp310-win_amd64.whl", hash = "sha256:620582db2a85b2df5f8a82ddeb52116560d7e5e6b055095f04ad828d1b0baa39"}, - {file = "Pillow-8.4.0-cp36-cp36m-macosx_10_10_x86_64.whl", hash = "sha256:1bc723b434fbc4ab50bb68e11e93ce5fb69866ad621e3c2c9bdb0cd70e345f55"}, - {file = "Pillow-8.4.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:72cbcfd54df6caf85cc35264c77ede902452d6df41166010262374155947460c"}, - {file = "Pillow-8.4.0-cp36-cp36m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:70ad9e5c6cb9b8487280a02c0ad8a51581dcbbe8484ce058477692a27c151c0a"}, - {file = "Pillow-8.4.0-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:25a49dc2e2f74e65efaa32b153527fc5ac98508d502fa46e74fa4fd678ed6645"}, - {file = "Pillow-8.4.0-cp36-cp36m-win32.whl", hash = "sha256:93ce9e955cc95959df98505e4608ad98281fff037350d8c2671c9aa86bcf10a9"}, - {file = "Pillow-8.4.0-cp36-cp36m-win_amd64.whl", hash = "sha256:2e4440b8f00f504ee4b53fe30f4e381aae30b0568193be305256b1462216feff"}, - {file = "Pillow-8.4.0-cp37-cp37m-macosx_10_10_x86_64.whl", hash = "sha256:8c803ac3c28bbc53763e6825746f05cc407b20e4a69d0122e526a582e3b5e153"}, - {file = "Pillow-8.4.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c8a17b5d948f4ceeceb66384727dde11b240736fddeda54ca740b9b8b1556b29"}, - {file = "Pillow-8.4.0-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1394a6ad5abc838c5cd8a92c5a07535648cdf6d09e8e2d6df916dfa9ea86ead8"}, - {file = "Pillow-8.4.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:792e5c12376594bfcb986ebf3855aa4b7c225754e9a9521298e460e92fb4a488"}, - {file = "Pillow-8.4.0-cp37-cp37m-win32.whl", hash = "sha256:d99ec152570e4196772e7a8e4ba5320d2d27bf22fdf11743dd882936ed64305b"}, - {file = "Pillow-8.4.0-cp37-cp37m-win_amd64.whl", hash = "sha256:7b7017b61bbcdd7f6363aeceb881e23c46583739cb69a3ab39cb384f6ec82e5b"}, - {file = "Pillow-8.4.0-cp38-cp38-macosx_10_10_x86_64.whl", hash = "sha256:d89363f02658e253dbd171f7c3716a5d340a24ee82d38aab9183f7fdf0cdca49"}, - {file = "Pillow-8.4.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:0a0956fdc5defc34462bb1c765ee88d933239f9a94bc37d132004775241a7585"}, - {file = "Pillow-8.4.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5b7bb9de00197fb4261825c15551adf7605cf14a80badf1761d61e59da347779"}, - {file = "Pillow-8.4.0-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:72b9e656e340447f827885b8d7a15fc8c4e68d410dc2297ef6787eec0f0ea409"}, - {file = "Pillow-8.4.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a5a4532a12314149d8b4e4ad8ff09dde7427731fcfa5917ff16d0291f13609df"}, - {file = "Pillow-8.4.0-cp38-cp38-win32.whl", hash = "sha256:82aafa8d5eb68c8463b6e9baeb4f19043bb31fefc03eb7b216b51e6a9981ae09"}, - {file = "Pillow-8.4.0-cp38-cp38-win_amd64.whl", hash = "sha256:066f3999cb3b070a95c3652712cffa1a748cd02d60ad7b4e485c3748a04d9d76"}, - {file = "Pillow-8.4.0-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:5503c86916d27c2e101b7f71c2ae2cddba01a2cf55b8395b0255fd33fa4d1f1a"}, - {file = "Pillow-8.4.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4acc0985ddf39d1bc969a9220b51d94ed51695d455c228d8ac29fcdb25810e6e"}, - {file = "Pillow-8.4.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0b052a619a8bfcf26bd8b3f48f45283f9e977890263e4571f2393ed8898d331b"}, - {file = "Pillow-8.4.0-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:493cb4e415f44cd601fcec11c99836f707bb714ab03f5ed46ac25713baf0ff20"}, - {file = "Pillow-8.4.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b8831cb7332eda5dc89b21a7bce7ef6ad305548820595033a4b03cf3091235ed"}, - {file = "Pillow-8.4.0-cp39-cp39-win32.whl", hash = "sha256:5e9ac5f66616b87d4da618a20ab0a38324dbe88d8a39b55be8964eb520021e02"}, - {file = "Pillow-8.4.0-cp39-cp39-win_amd64.whl", hash = "sha256:3eb1ce5f65908556c2d8685a8f0a6e989d887ec4057326f6c22b24e8a172c66b"}, - {file = "Pillow-8.4.0-pp36-pypy36_pp73-macosx_10_10_x86_64.whl", hash = "sha256:ddc4d832a0f0b4c52fff973a0d44b6c99839a9d016fe4e6a1cb8f3eea96479c2"}, - {file = "Pillow-8.4.0-pp36-pypy36_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9a3e5ddc44c14042f0844b8cf7d2cd455f6cc80fd7f5eefbe657292cf601d9ad"}, - {file = "Pillow-8.4.0-pp36-pypy36_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c70e94281588ef053ae8998039610dbd71bc509e4acbc77ab59d7d2937b10698"}, - {file = "Pillow-8.4.0-pp37-pypy37_pp73-macosx_10_10_x86_64.whl", hash = "sha256:3862b7256046fcd950618ed22d1d60b842e3a40a48236a5498746f21189afbbc"}, - {file = "Pillow-8.4.0-pp37-pypy37_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a4901622493f88b1a29bd30ec1a2f683782e57c3c16a2dbc7f2595ba01f639df"}, - {file = "Pillow-8.4.0-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:84c471a734240653a0ec91dec0996696eea227eafe72a33bd06c92697728046b"}, - {file = "Pillow-8.4.0-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:244cf3b97802c34c41905d22810846802a3329ddcb93ccc432870243211c79fc"}, - {file = "Pillow-8.4.0.tar.gz", hash = "sha256:b8e2f83c56e141920c39464b852de3719dfbfb6e3c99a2d8da0edf4fb33176ed"}, -] -platformdirs = [ - {file = "platformdirs-2.5.4-py3-none-any.whl", hash = "sha256:af0276409f9a02373d540bf8480021a048711d572745aef4b7842dad245eba10"}, - {file = "platformdirs-2.5.4.tar.gz", hash = "sha256:1006647646d80f16130f052404c6b901e80ee4ed6bef6792e1f238a8969106f7"}, -] -pluggy = [ - {file = "pluggy-1.0.0-py2.py3-none-any.whl", hash = "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"}, - {file = "pluggy-1.0.0.tar.gz", hash = "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159"}, -] -pycparser = [ - {file = "pycparser-2.21-py2.py3-none-any.whl", hash = "sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9"}, - {file = "pycparser-2.21.tar.gz", hash = "sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206"}, -] -pycryptodomex = [ - {file = "pycryptodomex-3.15.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:6f5b6ba8aefd624834bc177a2ac292734996bb030f9d1b388e7504103b6fcddf"}, - {file = "pycryptodomex-3.15.0-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:4540904c09704b6f831059c0dfb38584acb82cb97b0125cd52688c1f1e3fffa6"}, - {file = "pycryptodomex-3.15.0-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:0fadb9f7fa3150577800eef35f62a8a24b9ddf1563ff060d9bd3af22d3952c8c"}, - {file = "pycryptodomex-3.15.0-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:fc9bc7a9b79fe5c750fc81a307052f8daabb709bdaabb0fb18fb136b66b653b5"}, - {file = "pycryptodomex-3.15.0-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:f8be976cec59b11f011f790b88aca67b4ea2bd286578d0bd3e31bcd19afcd3e4"}, - {file = "pycryptodomex-3.15.0-cp27-cp27m-manylinux2014_aarch64.whl", hash = "sha256:78d9621cf0ea35abf2d38fa2ca6d0634eab6c991a78373498ab149953787e5e5"}, - {file = "pycryptodomex-3.15.0-cp27-cp27m-win32.whl", hash = "sha256:b6306403228edde6e289f626a3908a2f7f67c344e712cf7c0a508bab3ad9e381"}, - {file = "pycryptodomex-3.15.0-cp27-cp27m-win_amd64.whl", hash = "sha256:48697790203909fab02a33226fda546604f4e2653f9d47bc5d3eb40879fa7c64"}, - {file = "pycryptodomex-3.15.0-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:18e2ab4813883ae63396c0ffe50b13554b32bb69ec56f0afaf052e7a7ae0d55b"}, - {file = "pycryptodomex-3.15.0-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:3709f13ca3852b0b07fc04a2c03b379189232b24007c466be0f605dd4723e9d4"}, - {file = "pycryptodomex-3.15.0-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:191e73bc84a8064ad1874dba0ebadedd7cce4dedee998549518f2c74a003b2e1"}, - {file = "pycryptodomex-3.15.0-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:e3164a18348bd53c69b4435ebfb4ac8a4076291ffa2a70b54f0c4b80c7834b1d"}, - {file = "pycryptodomex-3.15.0-cp27-cp27mu-manylinux2014_aarch64.whl", hash = "sha256:5676a132169a1c1a3712edf25250722ebc8c9102aa9abd814df063ca8362454f"}, - {file = "pycryptodomex-3.15.0-cp35-abi3-macosx_10_9_x86_64.whl", hash = "sha256:e2b12968522a0358b8917fc7b28865acac002f02f4c4c6020fcb264d76bfd06d"}, - {file = "pycryptodomex-3.15.0-cp35-abi3-manylinux1_i686.whl", hash = "sha256:e47bf8776a7e15576887f04314f5228c6527b99946e6638cf2f16da56d260cab"}, - {file = "pycryptodomex-3.15.0-cp35-abi3-manylinux1_x86_64.whl", hash = "sha256:996e1ba717077ce1e6d4849af7a1426f38b07b3d173b879e27d5e26d2e958beb"}, - {file = "pycryptodomex-3.15.0-cp35-abi3-manylinux2010_i686.whl", hash = "sha256:65204412d0c6a8e3c41e21e93a5e6054a74fea501afa03046a388cf042e3377a"}, - {file = "pycryptodomex-3.15.0-cp35-abi3-manylinux2010_x86_64.whl", hash = "sha256:dd452a5af7014e866206d41751886c9b4bf379a339fdf2dbfc7dd16c0fb4f8e0"}, - {file = "pycryptodomex-3.15.0-cp35-abi3-manylinux2014_aarch64.whl", hash = "sha256:b9279adc16e4b0f590ceff581f53a80179b02cba9056010d733eb4196134a870"}, - {file = "pycryptodomex-3.15.0-cp35-abi3-win32.whl", hash = "sha256:46b3f05f2f7ac7841053da4e0f69616929ca3c42f238c405f6c3df7759ad2780"}, - {file = "pycryptodomex-3.15.0-cp35-abi3-win_amd64.whl", hash = "sha256:8eecdf9cdc7343001d047f951b9cc805cd68cb6cd77b20ea46af5bffc5bd3dfb"}, - {file = "pycryptodomex-3.15.0-pp27-pypy_73-macosx_10_9_x86_64.whl", hash = "sha256:67e1e6a92151023ccdfcfbc0afb3314ad30080793b4c27956ea06ab1fb9bcd8a"}, - {file = "pycryptodomex-3.15.0-pp27-pypy_73-manylinux1_x86_64.whl", hash = "sha256:c4cb9cb492ea7dcdf222a8d19a1d09002798ea516aeae8877245206d27326d86"}, - {file = "pycryptodomex-3.15.0-pp27-pypy_73-manylinux2010_x86_64.whl", hash = "sha256:94c7b60e1f52e1a87715571327baea0733708ab4723346598beca4a3b6879794"}, - {file = "pycryptodomex-3.15.0-pp27-pypy_73-win32.whl", hash = "sha256:04cc393045a8f19dd110c975e30f38ed7ab3faf21ede415ea67afebd95a22380"}, - {file = "pycryptodomex-3.15.0-pp36-pypy36_pp73-macosx_10_9_x86_64.whl", hash = "sha256:0776bfaf2c48154ab54ea45392847c1283d2fcf64e232e85565f858baedfc1fa"}, - {file = "pycryptodomex-3.15.0-pp36-pypy36_pp73-manylinux1_x86_64.whl", hash = "sha256:463119d7d22d0fc04a0f9122e9d3e6121c6648bcb12a052b51bd1eed1b996aa2"}, - {file = "pycryptodomex-3.15.0-pp36-pypy36_pp73-manylinux2010_x86_64.whl", hash = "sha256:a07a64709e366c2041cd5cfbca592b43998bf4df88f7b0ca73dca37071ccf1bd"}, - {file = "pycryptodomex-3.15.0-pp36-pypy36_pp73-win32.whl", hash = "sha256:35a8f7afe1867118330e2e0e0bf759c409e28557fb1fc2fbb1c6c937297dbe9a"}, - {file = "pycryptodomex-3.15.0.tar.gz", hash = "sha256:7341f1bb2dadb0d1a0047f34c3a58208a92423cdbd3244d998e4b28df5eac0ed"}, -] -pydantic = [ - {file = "pydantic-1.10.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:bb6ad4489af1bac6955d38ebcb95079a836af31e4c4f74aba1ca05bb9f6027bd"}, - {file = "pydantic-1.10.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a1f5a63a6dfe19d719b1b6e6106561869d2efaca6167f84f5ab9347887d78b98"}, - {file = "pydantic-1.10.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:352aedb1d71b8b0736c6d56ad2bd34c6982720644b0624462059ab29bd6e5912"}, - {file = "pydantic-1.10.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:19b3b9ccf97af2b7519c42032441a891a5e05c68368f40865a90eb88833c2559"}, - {file = "pydantic-1.10.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e9069e1b01525a96e6ff49e25876d90d5a563bc31c658289a8772ae186552236"}, - {file = "pydantic-1.10.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:355639d9afc76bcb9b0c3000ddcd08472ae75318a6eb67a15866b87e2efa168c"}, - {file = "pydantic-1.10.2-cp310-cp310-win_amd64.whl", hash = "sha256:ae544c47bec47a86bc7d350f965d8b15540e27e5aa4f55170ac6a75e5f73b644"}, - {file = "pydantic-1.10.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a4c805731c33a8db4b6ace45ce440c4ef5336e712508b4d9e1aafa617dc9907f"}, - {file = "pydantic-1.10.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d49f3db871575e0426b12e2f32fdb25e579dea16486a26e5a0474af87cb1ab0a"}, - {file = "pydantic-1.10.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:37c90345ec7dd2f1bcef82ce49b6235b40f282b94d3eec47e801baf864d15525"}, - {file = "pydantic-1.10.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7b5ba54d026c2bd2cb769d3468885f23f43710f651688e91f5fb1edcf0ee9283"}, - {file = "pydantic-1.10.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:05e00dbebbe810b33c7a7362f231893183bcc4251f3f2ff991c31d5c08240c42"}, - {file = "pydantic-1.10.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:2d0567e60eb01bccda3a4df01df677adf6b437958d35c12a3ac3e0f078b0ee52"}, - {file = "pydantic-1.10.2-cp311-cp311-win_amd64.whl", hash = "sha256:c6f981882aea41e021f72779ce2a4e87267458cc4d39ea990729e21ef18f0f8c"}, - {file = "pydantic-1.10.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:c4aac8e7103bf598373208f6299fa9a5cfd1fc571f2d40bf1dd1955a63d6eeb5"}, - {file = "pydantic-1.10.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:81a7b66c3f499108b448f3f004801fcd7d7165fb4200acb03f1c2402da73ce4c"}, - {file = "pydantic-1.10.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bedf309630209e78582ffacda64a21f96f3ed2e51fbf3962d4d488e503420254"}, - {file = "pydantic-1.10.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:9300fcbebf85f6339a02c6994b2eb3ff1b9c8c14f502058b5bf349d42447dcf5"}, - {file = "pydantic-1.10.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:216f3bcbf19c726b1cc22b099dd409aa371f55c08800bcea4c44c8f74b73478d"}, - {file = "pydantic-1.10.2-cp37-cp37m-win_amd64.whl", hash = "sha256:dd3f9a40c16daf323cf913593083698caee97df2804aa36c4b3175d5ac1b92a2"}, - {file = "pydantic-1.10.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:b97890e56a694486f772d36efd2ba31612739bc6f3caeee50e9e7e3ebd2fdd13"}, - {file = "pydantic-1.10.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:9cabf4a7f05a776e7793e72793cd92cc865ea0e83a819f9ae4ecccb1b8aa6116"}, - {file = "pydantic-1.10.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:06094d18dd5e6f2bbf93efa54991c3240964bb663b87729ac340eb5014310624"}, - {file = "pydantic-1.10.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cc78cc83110d2f275ec1970e7a831f4e371ee92405332ebfe9860a715f8336e1"}, - {file = "pydantic-1.10.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:1ee433e274268a4b0c8fde7ad9d58ecba12b069a033ecc4645bb6303c062d2e9"}, - {file = "pydantic-1.10.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:7c2abc4393dea97a4ccbb4ec7d8658d4e22c4765b7b9b9445588f16c71ad9965"}, - {file = "pydantic-1.10.2-cp38-cp38-win_amd64.whl", hash = "sha256:0b959f4d8211fc964772b595ebb25f7652da3f22322c007b6fed26846a40685e"}, - {file = "pydantic-1.10.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c33602f93bfb67779f9c507e4d69451664524389546bacfe1bee13cae6dc7488"}, - {file = "pydantic-1.10.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:5760e164b807a48a8f25f8aa1a6d857e6ce62e7ec83ea5d5c5a802eac81bad41"}, - {file = "pydantic-1.10.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6eb843dcc411b6a2237a694f5e1d649fc66c6064d02b204a7e9d194dff81eb4b"}, - {file = "pydantic-1.10.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4b8795290deaae348c4eba0cebb196e1c6b98bdbe7f50b2d0d9a4a99716342fe"}, - {file = "pydantic-1.10.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:e0bedafe4bc165ad0a56ac0bd7695df25c50f76961da29c050712596cf092d6d"}, - {file = "pydantic-1.10.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:2e05aed07fa02231dbf03d0adb1be1d79cabb09025dd45aa094aa8b4e7b9dcda"}, - {file = "pydantic-1.10.2-cp39-cp39-win_amd64.whl", hash = "sha256:c1ba1afb396148bbc70e9eaa8c06c1716fdddabaf86e7027c5988bae2a829ab6"}, - {file = "pydantic-1.10.2-py3-none-any.whl", hash = "sha256:1b6ee725bd6e83ec78b1aa32c5b1fa67a3a65badddde3976bca5fe4568f27709"}, - {file = "pydantic-1.10.2.tar.gz", hash = "sha256:91b8e218852ef6007c2b98cd861601c6a09f1aa32bbbb74fab5b1c33d4a1e410"}, -] -pynacl = [ - {file = "PyNaCl-1.4.0-cp27-cp27m-macosx_10_10_x86_64.whl", hash = "sha256:ea6841bc3a76fa4942ce00f3bda7d436fda21e2d91602b9e21b7ca9ecab8f3ff"}, - {file = "PyNaCl-1.4.0-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:d452a6746f0a7e11121e64625109bc4468fc3100452817001dbe018bb8b08514"}, - {file = "PyNaCl-1.4.0-cp27-cp27m-win32.whl", hash = "sha256:2fe0fc5a2480361dcaf4e6e7cea00e078fcda07ba45f811b167e3f99e8cff574"}, - {file = "PyNaCl-1.4.0-cp27-cp27m-win_amd64.whl", hash = "sha256:f8851ab9041756003119368c1e6cd0b9c631f46d686b3904b18c0139f4419f80"}, - {file = "PyNaCl-1.4.0-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:7757ae33dae81c300487591c68790dfb5145c7d03324000433d9a2c141f82af7"}, - {file = "PyNaCl-1.4.0-cp35-abi3-macosx_10_10_x86_64.whl", hash = "sha256:757250ddb3bff1eecd7e41e65f7f833a8405fede0194319f87899690624f2122"}, - {file = "PyNaCl-1.4.0-cp35-abi3-manylinux1_x86_64.whl", hash = "sha256:30f9b96db44e09b3304f9ea95079b1b7316b2b4f3744fe3aaecccd95d547063d"}, - {file = "PyNaCl-1.4.0-cp35-abi3-win32.whl", hash = "sha256:4e10569f8cbed81cb7526ae137049759d2a8d57726d52c1a000a3ce366779634"}, - {file = "PyNaCl-1.4.0-cp35-abi3-win_amd64.whl", hash = "sha256:c914f78da4953b33d4685e3cdc7ce63401247a21425c16a39760e282075ac4a6"}, - {file = "PyNaCl-1.4.0-cp35-cp35m-win32.whl", hash = "sha256:06cbb4d9b2c4bd3c8dc0d267416aaed79906e7b33f114ddbf0911969794b1cc4"}, - {file = "PyNaCl-1.4.0-cp35-cp35m-win_amd64.whl", hash = "sha256:511d269ee845037b95c9781aa702f90ccc36036f95d0f31373a6a79bd8242e25"}, - {file = "PyNaCl-1.4.0-cp36-cp36m-win32.whl", hash = "sha256:11335f09060af52c97137d4ac54285bcb7df0cef29014a1a4efe64ac065434c4"}, - {file = "PyNaCl-1.4.0-cp36-cp36m-win_amd64.whl", hash = "sha256:cd401ccbc2a249a47a3a1724c2918fcd04be1f7b54eb2a5a71ff915db0ac51c6"}, - {file = "PyNaCl-1.4.0-cp37-cp37m-win32.whl", hash = "sha256:8122ba5f2a2169ca5da936b2e5a511740ffb73979381b4229d9188f6dcb22f1f"}, - {file = "PyNaCl-1.4.0-cp37-cp37m-win_amd64.whl", hash = "sha256:537a7ccbea22905a0ab36ea58577b39d1fa9b1884869d173b5cf111f006f689f"}, - {file = "PyNaCl-1.4.0-cp38-cp38-win32.whl", hash = "sha256:9c4a7ea4fb81536c1b1f5cc44d54a296f96ae78c1ebd2311bd0b60be45a48d96"}, - {file = "PyNaCl-1.4.0-cp38-cp38-win_amd64.whl", hash = "sha256:7c6092102219f59ff29788860ccb021e80fffd953920c4a8653889c029b2d420"}, - {file = "PyNaCl-1.4.0.tar.gz", hash = "sha256:54e9a2c849c742006516ad56a88f5c74bf2ce92c9f67435187c3c5953b346505"}, -] -pyparsing = [ - {file = "pyparsing-3.0.9-py3-none-any.whl", hash = "sha256:5026bae9a10eeaefb61dab2f09052b9f4307d44aee4eda64b309723d8d206bbc"}, - {file = "pyparsing-3.0.9.tar.gz", hash = "sha256:2b020ecf7d21b687f219b71ecad3631f644a47f01403fa1d1036b0c6416d70fb"}, -] -pytest = [ - {file = "pytest-7.2.0-py3-none-any.whl", hash = "sha256:892f933d339f068883b6fd5a459f03d85bfcb355e4981e146d2c7616c21fef71"}, - {file = "pytest-7.2.0.tar.gz", hash = "sha256:c4014eb40e10f11f355ad4e3c2fb2c6c6d1919c73f3b5a433de4708202cade59"}, -] -python-dotenv = [ - {file = "python-dotenv-0.21.0.tar.gz", hash = "sha256:b77d08274639e3d34145dfa6c7008e66df0f04b7be7a75fd0d5292c191d79045"}, - {file = "python_dotenv-0.21.0-py3-none-any.whl", hash = "sha256:1684eb44636dd462b66c3ee016599815514527ad99965de77f43e0944634a7e5"}, -] -pytz = [ - {file = "pytz-2022.6-py2.py3-none-any.whl", hash = "sha256:222439474e9c98fced559f1709d89e6c9cbf8d79c794ff3eb9f8800064291427"}, - {file = "pytz-2022.6.tar.gz", hash = "sha256:e89512406b793ca39f5971bc999cc538ce125c0e51c27941bef4568b460095e2"}, -] -regex = [ - {file = "regex-2021.11.10-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:9345b6f7ee578bad8e475129ed40123d265464c4cfead6c261fd60fc9de00bcf"}, - {file = "regex-2021.11.10-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:416c5f1a188c91e3eb41e9c8787288e707f7d2ebe66e0a6563af280d9b68478f"}, - {file = "regex-2021.11.10-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e0538c43565ee6e703d3a7c3bdfe4037a5209250e8502c98f20fea6f5fdf2965"}, - {file = "regex-2021.11.10-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7ee1227cf08b6716c85504aebc49ac827eb88fcc6e51564f010f11a406c0a667"}, - {file = "regex-2021.11.10-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6650f16365f1924d6014d2ea770bde8555b4a39dc9576abb95e3cd1ff0263b36"}, - {file = "regex-2021.11.10-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:30ab804ea73972049b7a2a5c62d97687d69b5a60a67adca07eb73a0ddbc9e29f"}, - {file = "regex-2021.11.10-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:68a067c11463de2a37157930d8b153005085e42bcb7ad9ca562d77ba7d1404e0"}, - {file = "regex-2021.11.10-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:162abfd74e88001d20cb73ceaffbfe601469923e875caf9118333b1a4aaafdc4"}, - {file = "regex-2021.11.10-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:b9ed0b1e5e0759d6b7f8e2f143894b2a7f3edd313f38cf44e1e15d360e11749b"}, - {file = "regex-2021.11.10-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:473e67837f786404570eae33c3b64a4b9635ae9f00145250851a1292f484c063"}, - {file = "regex-2021.11.10-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:2fee3ed82a011184807d2127f1733b4f6b2ff6ec7151d83ef3477f3b96a13d03"}, - {file = "regex-2021.11.10-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:d5fd67df77bab0d3f4ea1d7afca9ef15c2ee35dfb348c7b57ffb9782a6e4db6e"}, - {file = "regex-2021.11.10-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:5d408a642a5484b9b4d11dea15a489ea0928c7e410c7525cd892f4d04f2f617b"}, - {file = "regex-2021.11.10-cp310-cp310-win32.whl", hash = "sha256:98ba568e8ae26beb726aeea2273053c717641933836568c2a0278a84987b2a1a"}, - {file = "regex-2021.11.10-cp310-cp310-win_amd64.whl", hash = "sha256:780b48456a0f0ba4d390e8b5f7c661fdd218934388cde1a974010a965e200e12"}, - {file = "regex-2021.11.10-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:dba70f30fd81f8ce6d32ddeef37d91c8948e5d5a4c63242d16a2b2df8143aafc"}, - {file = "regex-2021.11.10-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e1f54b9b4b6c53369f40028d2dd07a8c374583417ee6ec0ea304e710a20f80a0"}, - {file = "regex-2021.11.10-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fbb9dc00e39f3e6c0ef48edee202f9520dafb233e8b51b06b8428cfcb92abd30"}, - {file = "regex-2021.11.10-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:666abff54e474d28ff42756d94544cdfd42e2ee97065857413b72e8a2d6a6345"}, - {file = "regex-2021.11.10-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5537f71b6d646f7f5f340562ec4c77b6e1c915f8baae822ea0b7e46c1f09b733"}, - {file = "regex-2021.11.10-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ed2e07c6a26ed4bea91b897ee2b0835c21716d9a469a96c3e878dc5f8c55bb23"}, - {file = "regex-2021.11.10-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:ca5f18a75e1256ce07494e245cdb146f5a9267d3c702ebf9b65c7f8bd843431e"}, - {file = "regex-2021.11.10-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:74cbeac0451f27d4f50e6e8a8f3a52ca074b5e2da9f7b505c4201a57a8ed6286"}, - {file = "regex-2021.11.10-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:3598893bde43091ee5ca0a6ad20f08a0435e93a69255eeb5f81b85e81e329264"}, - {file = "regex-2021.11.10-cp36-cp36m-musllinux_1_1_ppc64le.whl", hash = "sha256:50a7ddf3d131dc5633dccdb51417e2d1910d25cbcf842115a3a5893509140a3a"}, - {file = "regex-2021.11.10-cp36-cp36m-musllinux_1_1_s390x.whl", hash = "sha256:61600a7ca4bcf78a96a68a27c2ae9389763b5b94b63943d5158f2a377e09d29a"}, - {file = "regex-2021.11.10-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:563d5f9354e15e048465061509403f68424fef37d5add3064038c2511c8f5e00"}, - {file = "regex-2021.11.10-cp36-cp36m-win32.whl", hash = "sha256:93a5051fcf5fad72de73b96f07d30bc29665697fb8ecdfbc474f3452c78adcf4"}, - {file = "regex-2021.11.10-cp36-cp36m-win_amd64.whl", hash = "sha256:b483c9d00a565633c87abd0aaf27eb5016de23fed952e054ecc19ce32f6a9e7e"}, - {file = "regex-2021.11.10-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:fff55f3ce50a3ff63ec8e2a8d3dd924f1941b250b0aac3d3d42b687eeff07a8e"}, - {file = "regex-2021.11.10-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e32d2a2b02ccbef10145df9135751abea1f9f076e67a4e261b05f24b94219e36"}, - {file = "regex-2021.11.10-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:53db2c6be8a2710b359bfd3d3aa17ba38f8aa72a82309a12ae99d3c0c3dcd74d"}, - {file = "regex-2021.11.10-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2207ae4f64ad3af399e2d30dde66f0b36ae5c3129b52885f1bffc2f05ec505c8"}, - {file = "regex-2021.11.10-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d5ca078bb666c4a9d1287a379fe617a6dccd18c3e8a7e6c7e1eb8974330c626a"}, - {file = "regex-2021.11.10-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dd33eb9bdcfbabab3459c9ee651d94c842bc8a05fabc95edf4ee0c15a072495e"}, - {file = "regex-2021.11.10-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:05b7d6d7e64efe309972adab77fc2af8907bb93217ec60aa9fe12a0dad35874f"}, - {file = "regex-2021.11.10-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:42b50fa6666b0d50c30a990527127334d6b96dd969011e843e726a64011485da"}, - {file = "regex-2021.11.10-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:6e1d2cc79e8dae442b3fa4a26c5794428b98f81389af90623ffcc650ce9f6732"}, - {file = "regex-2021.11.10-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:0416f7399e918c4b0e074a0f66e5191077ee2ca32a0f99d4c187a62beb47aa05"}, - {file = "regex-2021.11.10-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:ce298e3d0c65bd03fa65ffcc6db0e2b578e8f626d468db64fdf8457731052942"}, - {file = "regex-2021.11.10-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:dc07f021ee80510f3cd3af2cad5b6a3b3a10b057521d9e6aaeb621730d320c5a"}, - {file = "regex-2021.11.10-cp37-cp37m-win32.whl", hash = "sha256:e71255ba42567d34a13c03968736c5d39bb4a97ce98188fafb27ce981115beec"}, - {file = "regex-2021.11.10-cp37-cp37m-win_amd64.whl", hash = "sha256:07856afef5ffcc052e7eccf3213317fbb94e4a5cd8177a2caa69c980657b3cb4"}, - {file = "regex-2021.11.10-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:ba05430e819e58544e840a68b03b28b6d328aff2e41579037e8bab7653b37d83"}, - {file = "regex-2021.11.10-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7f301b11b9d214f83ddaf689181051e7f48905568b0c7017c04c06dfd065e244"}, - {file = "regex-2021.11.10-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4aaa4e0705ef2b73dd8e36eeb4c868f80f8393f5f4d855e94025ce7ad8525f50"}, - {file = "regex-2021.11.10-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:788aef3549f1924d5c38263104dae7395bf020a42776d5ec5ea2b0d3d85d6646"}, - {file = "regex-2021.11.10-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f8af619e3be812a2059b212064ea7a640aff0568d972cd1b9e920837469eb3cb"}, - {file = "regex-2021.11.10-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:85bfa6a5413be0ee6c5c4a663668a2cad2cbecdee367630d097d7823041bdeec"}, - {file = "regex-2021.11.10-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f23222527b307970e383433daec128d769ff778d9b29343fb3496472dc20dabe"}, - {file = "regex-2021.11.10-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:da1a90c1ddb7531b1d5ff1e171b4ee61f6345119be7351104b67ff413843fe94"}, - {file = "regex-2021.11.10-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:f5be7805e53dafe94d295399cfbe5227f39995a997f4fd8539bf3cbdc8f47ca8"}, - {file = "regex-2021.11.10-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a955b747d620a50408b7fdf948e04359d6e762ff8a85f5775d907ceced715129"}, - {file = "regex-2021.11.10-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:139a23d1f5d30db2cc6c7fd9c6d6497872a672db22c4ae1910be22d4f4b2068a"}, - {file = "regex-2021.11.10-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:ca49e1ab99593438b204e00f3970e7a5f70d045267051dfa6b5f4304fcfa1dbf"}, - {file = "regex-2021.11.10-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:96fc32c16ea6d60d3ca7f63397bff5c75c5a562f7db6dec7d412f7c4d2e78ec0"}, - {file = "regex-2021.11.10-cp38-cp38-win32.whl", hash = "sha256:0617383e2fe465732af4509e61648b77cbe3aee68b6ac8c0b6fe934db90be5cc"}, - {file = "regex-2021.11.10-cp38-cp38-win_amd64.whl", hash = "sha256:a3feefd5e95871872673b08636f96b61ebef62971eab044f5124fb4dea39919d"}, - {file = "regex-2021.11.10-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f7f325be2804246a75a4f45c72d4ce80d2443ab815063cdf70ee8fb2ca59ee1b"}, - {file = "regex-2021.11.10-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:537ca6a3586931b16a85ac38c08cc48f10fc870a5b25e51794c74df843e9966d"}, - {file = "regex-2021.11.10-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eef2afb0fd1747f33f1ee3e209bce1ed582d1896b240ccc5e2697e3275f037c7"}, - {file = "regex-2021.11.10-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:432bd15d40ed835a51617521d60d0125867f7b88acf653e4ed994a1f8e4995dc"}, - {file = "regex-2021.11.10-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b43c2b8a330a490daaef5a47ab114935002b13b3f9dc5da56d5322ff218eeadb"}, - {file = "regex-2021.11.10-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:962b9a917dd7ceacbe5cd424556914cb0d636001e393b43dc886ba31d2a1e449"}, - {file = "regex-2021.11.10-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fa8c626d6441e2d04b6ee703ef2d1e17608ad44c7cb75258c09dd42bacdfc64b"}, - {file = "regex-2021.11.10-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:3c5fb32cc6077abad3bbf0323067636d93307c9fa93e072771cf9a64d1c0f3ef"}, - {file = "regex-2021.11.10-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:cd410a1cbb2d297c67d8521759ab2ee3f1d66206d2e4328502a487589a2cb21b"}, - {file = "regex-2021.11.10-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:e6096b0688e6e14af6a1b10eaad86b4ff17935c49aa774eac7c95a57a4e8c296"}, - {file = "regex-2021.11.10-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:529801a0d58809b60b3531ee804d3e3be4b412c94b5d267daa3de7fadef00f49"}, - {file = "regex-2021.11.10-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:0f594b96fe2e0821d026365f72ac7b4f0b487487fb3d4aaf10dd9d97d88a9737"}, - {file = "regex-2021.11.10-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:2409b5c9cef7054dde93a9803156b411b677affc84fca69e908b1cb2c540025d"}, - {file = "regex-2021.11.10-cp39-cp39-win32.whl", hash = "sha256:3b5df18db1fccd66de15aa59c41e4f853b5df7550723d26aa6cb7f40e5d9da5a"}, - {file = "regex-2021.11.10-cp39-cp39-win_amd64.whl", hash = "sha256:83ee89483672b11f8952b158640d0c0ff02dc43d9cb1b70c1564b49abe92ce29"}, - {file = "regex-2021.11.10.tar.gz", hash = "sha256:f341ee2df0999bfdf7a95e448075effe0db212a59387de1a70690e4acb03d4c6"}, -] -requests = [ - {file = "requests-2.28.1-py3-none-any.whl", hash = "sha256:8fefa2a1a1365bf5520aac41836fbee479da67864514bdb821f31ce07ce65349"}, - {file = "requests-2.28.1.tar.gz", hash = "sha256:7c5599b102feddaa661c826c56ab4fee28bfd17f5abca1ebbe3e7f19d7c97983"}, -] -rfc3986 = [ - {file = "rfc3986-1.5.0-py2.py3-none-any.whl", hash = "sha256:a86d6e1f5b1dc238b218b012df0aa79409667bb209e58da56d0b94704e712a97"}, - {file = "rfc3986-1.5.0.tar.gz", hash = "sha256:270aaf10d87d0d4e095063c65bf3ddbc6ee3d0b226328ce21e036f946e421835"}, -] -sgmllib3k = [ - {file = "sgmllib3k-1.0.0.tar.gz", hash = "sha256:7868fb1c8bfa764c1ac563d3cf369c381d1325d36124933a726f29fcdaa812e9"}, -] -six = [ - {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, - {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, -] -sniffio = [ - {file = "sniffio-1.3.0-py3-none-any.whl", hash = "sha256:eecefdce1e5bbfb7ad2eeaabf7c1eeb404d7757c379bd1f7e5cce9d8bf425384"}, - {file = "sniffio-1.3.0.tar.gz", hash = "sha256:e60305c5e5d314f5389259b7f22aaa33d8f7dee49763119234af3755c55b9101"}, -] -soupsieve = [ - {file = "soupsieve-2.3.2.post1-py3-none-any.whl", hash = "sha256:3b2503d3c7084a42b1ebd08116e5f81aadfaea95863628c80a3b774a11b7c759"}, - {file = "soupsieve-2.3.2.post1.tar.gz", hash = "sha256:fc53893b3da2c33de295667a0e19f078c14bf86544af307354de5fcf12a3f30d"}, -] -sympy = [ - {file = "sympy-1.11.1-py3-none-any.whl", hash = "sha256:938f984ee2b1e8eae8a07b884c8b7a1146010040fccddc6539c54f401c8f6fcf"}, - {file = "sympy-1.11.1.tar.gz", hash = "sha256:e32380dce63cb7c0108ed525570092fd45168bdae2faa17e528221ef72e88658"}, -] -tabulate = [ - {file = "tabulate-0.8.9-py3-none-any.whl", hash = "sha256:d7c013fe7abbc5e491394e10fa845f8f32fe54f8dc60c6622c6cf482d25d47e4"}, - {file = "tabulate-0.8.9.tar.gz", hash = "sha256:eb1d13f25760052e8931f2ef80aaf6045a6cceb47514db8beab24cded16f13a7"}, -] -tomli = [ - {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, - {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, -] -types-beautifulsoup4 = [ - {file = "types-beautifulsoup4-4.11.6.1.tar.gz", hash = "sha256:d46be8f409ddccb6daaa9d118484185e70bcf552085c39c6d05b157cd1462e04"}, - {file = "types_beautifulsoup4-4.11.6.1-py3-none-any.whl", hash = "sha256:c1f803367a2b07ad4fdac40ddbea557010dc4ddd1ee92d801f317eb02e2e3c72"}, -] -types-pytz = [ - {file = "types-pytz-2022.6.0.1.tar.gz", hash = "sha256:d078196374d1277e9f9984d49373ea043cf2c64d5d5c491fbc86c258557bd46f"}, - {file = "types_pytz-2022.6.0.1-py3-none-any.whl", hash = "sha256:bea605ce5d5a5d52a8e1afd7656c9b42476e18a0f888de6be91587355313ddf4"}, -] -types-regex = [ - {file = "types-regex-2022.10.31.0.tar.gz", hash = "sha256:4e5827f49d65da579d6042cf1e5972437d9ae6b59b4b275030a6d983e361b211"}, - {file = "types_regex-2022.10.31.0-py3-none-any.whl", hash = "sha256:1f81ec831cf7aca7ec697f9e895b0421cc634f9df98a7dccba0488681a80b9c7"}, -] -types-requests = [ - {file = "types-requests-2.28.11.5.tar.gz", hash = "sha256:a7df37cc6fb6187a84097da951f8e21d335448aa2501a6b0a39cbd1d7ca9ee2a"}, - {file = "types_requests-2.28.11.5-py3-none-any.whl", hash = "sha256:091d4a5a33c1b4f20d8b1b952aa8fa27a6e767c44c3cf65e56580df0b05fd8a9"}, -] -types-tabulate = [ - {file = "types-tabulate-0.8.11.tar.gz", hash = "sha256:17a5fa3b5ca453815778fc9865e8ecd0118b07b2b9faff3e2b06fe448174dd5e"}, - {file = "types_tabulate-0.8.11-py3-none-any.whl", hash = "sha256:af811268241e8fb87b63c052c87d1e329898a93191309d5d42111372232b2e0e"}, -] -types-urllib3 = [ - {file = "types-urllib3-1.26.25.4.tar.gz", hash = "sha256:eec5556428eec862b1ac578fb69aab3877995a99ffec9e5a12cf7fbd0cc9daee"}, - {file = "types_urllib3-1.26.25.4-py3-none-any.whl", hash = "sha256:ed6b9e8a8be488796f72306889a06a3fc3cb1aa99af02ab8afb50144d7317e49"}, -] -typing-extensions = [ - {file = "typing_extensions-4.4.0-py3-none-any.whl", hash = "sha256:16fa4864408f655d35ec496218b85f79b3437c829e93320c7c9215ccfd92489e"}, - {file = "typing_extensions-4.4.0.tar.gz", hash = "sha256:1511434bb92bf8dd198c12b1cc812e800d4181cfcb867674e0f8279cc93087aa"}, -] -urllib3 = [ - {file = "urllib3-1.26.12-py2.py3-none-any.whl", hash = "sha256:b930dd878d5a8afb066a637fbb35144fe7901e3b209d1cd4f524bd0e9deee997"}, - {file = "urllib3-1.26.12.tar.gz", hash = "sha256:3fa96cf423e6987997fc326ae8df396db2a8b7c667747d47ddd8ecba91f4a74e"}, -] -uvloop = [ - {file = "uvloop-0.16.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:6224f1401025b748ffecb7a6e2652b17768f30b1a6a3f7b44660e5b5b690b12d"}, - {file = "uvloop-0.16.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:30ba9dcbd0965f5c812b7c2112a1ddf60cf904c1c160f398e7eed3a6b82dcd9c"}, - {file = "uvloop-0.16.0-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:bd53f7f5db562f37cd64a3af5012df8cac2c464c97e732ed556800129505bd64"}, - {file = "uvloop-0.16.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:772206116b9b57cd625c8a88f2413df2fcfd0b496eb188b82a43bed7af2c2ec9"}, - {file = "uvloop-0.16.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b572256409f194521a9895aef274cea88731d14732343da3ecdb175228881638"}, - {file = "uvloop-0.16.0-cp37-cp37m-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:04ff57aa137230d8cc968f03481176041ae789308b4d5079118331ab01112450"}, - {file = "uvloop-0.16.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3a19828c4f15687675ea912cc28bbcb48e9bb907c801873bd1519b96b04fb805"}, - {file = "uvloop-0.16.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:e814ac2c6f9daf4c36eb8e85266859f42174a4ff0d71b99405ed559257750382"}, - {file = "uvloop-0.16.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:bd8f42ea1ea8f4e84d265769089964ddda95eb2bb38b5cbe26712b0616c3edee"}, - {file = "uvloop-0.16.0-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:647e481940379eebd314c00440314c81ea547aa636056f554d491e40503c8464"}, - {file = "uvloop-0.16.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8e0d26fa5875d43ddbb0d9d79a447d2ace4180d9e3239788208527c4784f7cab"}, - {file = "uvloop-0.16.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:6ccd57ae8db17d677e9e06192e9c9ec4bd2066b77790f9aa7dede2cc4008ee8f"}, - {file = "uvloop-0.16.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:089b4834fd299d82d83a25e3335372f12117a7d38525217c2258e9b9f4578897"}, - {file = "uvloop-0.16.0-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:98d117332cc9e5ea8dfdc2b28b0a23f60370d02e1395f88f40d1effd2cb86c4f"}, - {file = "uvloop-0.16.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1e5f2e2ff51aefe6c19ee98af12b4ae61f5be456cd24396953244a30880ad861"}, - {file = "uvloop-0.16.0.tar.gz", hash = "sha256:f74bc20c7b67d1c27c72601c78cf95be99d5c2cdd4514502b4f3eb0933ff1228"}, -] -websockets = [ - {file = "websockets-10.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d58804e996d7d2307173d56c297cf7bc132c52df27a3efaac5e8d43e36c21c48"}, - {file = "websockets-10.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:bc0b82d728fe21a0d03e65f81980abbbcb13b5387f733a1a870672c5be26edab"}, - {file = "websockets-10.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ba089c499e1f4155d2a3c2a05d2878a3428cf321c848f2b5a45ce55f0d7d310c"}, - {file = "websockets-10.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:33d69ca7612f0ddff3316b0c7b33ca180d464ecac2d115805c044bf0a3b0d032"}, - {file = "websockets-10.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:62e627f6b6d4aed919a2052efc408da7a545c606268d5ab5bfab4432734b82b4"}, - {file = "websockets-10.4-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:38ea7b82bfcae927eeffc55d2ffa31665dc7fec7b8dc654506b8e5a518eb4d50"}, - {file = "websockets-10.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:e0cb5cc6ece6ffa75baccfd5c02cffe776f3f5c8bf486811f9d3ea3453676ce8"}, - {file = "websockets-10.4-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:ae5e95cfb53ab1da62185e23b3130e11d64431179debac6dc3c6acf08760e9b1"}, - {file = "websockets-10.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:7c584f366f46ba667cfa66020344886cf47088e79c9b9d39c84ce9ea98aaa331"}, - {file = "websockets-10.4-cp310-cp310-win32.whl", hash = "sha256:b029fb2032ae4724d8ae8d4f6b363f2cc39e4c7b12454df8df7f0f563ed3e61a"}, - {file = "websockets-10.4-cp310-cp310-win_amd64.whl", hash = "sha256:8dc96f64ae43dde92530775e9cb169979f414dcf5cff670455d81a6823b42089"}, - {file = "websockets-10.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:47a2964021f2110116cc1125b3e6d87ab5ad16dea161949e7244ec583b905bb4"}, - {file = "websockets-10.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:e789376b52c295c4946403bd0efecf27ab98f05319df4583d3c48e43c7342c2f"}, - {file = "websockets-10.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7d3f0b61c45c3fa9a349cf484962c559a8a1d80dae6977276df8fd1fa5e3cb8c"}, - {file = "websockets-10.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f55b5905705725af31ccef50e55391621532cd64fbf0bc6f4bac935f0fccec46"}, - {file = "websockets-10.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:00c870522cdb69cd625b93f002961ffb0c095394f06ba8c48f17eef7c1541f96"}, - {file = "websockets-10.4-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f38706e0b15d3c20ef6259fd4bc1700cd133b06c3c1bb108ffe3f8947be15fa"}, - {file = "websockets-10.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:f2c38d588887a609191d30e902df2a32711f708abfd85d318ca9b367258cfd0c"}, - {file = "websockets-10.4-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:fe10ddc59b304cb19a1bdf5bd0a7719cbbc9fbdd57ac80ed436b709fcf889106"}, - {file = "websockets-10.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:90fcf8929836d4a0e964d799a58823547df5a5e9afa83081761630553be731f9"}, - {file = "websockets-10.4-cp311-cp311-win32.whl", hash = "sha256:b9968694c5f467bf67ef97ae7ad4d56d14be2751000c1207d31bf3bb8860bae8"}, - {file = "websockets-10.4-cp311-cp311-win_amd64.whl", hash = "sha256:a7a240d7a74bf8d5cb3bfe6be7f21697a28ec4b1a437607bae08ac7acf5b4882"}, - {file = "websockets-10.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:74de2b894b47f1d21cbd0b37a5e2b2392ad95d17ae983e64727e18eb281fe7cb"}, - {file = "websockets-10.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e3a686ecb4aa0d64ae60c9c9f1a7d5d46cab9bfb5d91a2d303d00e2cd4c4c5cc"}, - {file = "websockets-10.4-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b0d15c968ea7a65211e084f523151dbf8ae44634de03c801b8bd070b74e85033"}, - {file = "websockets-10.4-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:00213676a2e46b6ebf6045bc11d0f529d9120baa6f58d122b4021ad92adabd41"}, - {file = "websockets-10.4-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:e23173580d740bf8822fd0379e4bf30aa1d5a92a4f252d34e893070c081050df"}, - {file = "websockets-10.4-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:dd500e0a5e11969cdd3320935ca2ff1e936f2358f9c2e61f100a1660933320ea"}, - {file = "websockets-10.4-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:4239b6027e3d66a89446908ff3027d2737afc1a375f8fd3eea630a4842ec9a0c"}, - {file = "websockets-10.4-cp37-cp37m-win32.whl", hash = "sha256:8a5cc00546e0a701da4639aa0bbcb0ae2bb678c87f46da01ac2d789e1f2d2038"}, - {file = "websockets-10.4-cp37-cp37m-win_amd64.whl", hash = "sha256:a9f9a735deaf9a0cadc2d8c50d1a5bcdbae8b6e539c6e08237bc4082d7c13f28"}, - {file = "websockets-10.4-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5c1289596042fad2cdceb05e1ebf7aadf9995c928e0da2b7a4e99494953b1b94"}, - {file = "websockets-10.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0cff816f51fb33c26d6e2b16b5c7d48eaa31dae5488ace6aae468b361f422b63"}, - {file = "websockets-10.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:dd9becd5fe29773d140d68d607d66a38f60e31b86df75332703757ee645b6faf"}, - {file = "websockets-10.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45ec8e75b7dbc9539cbfafa570742fe4f676eb8b0d3694b67dabe2f2ceed8aa6"}, - {file = "websockets-10.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4f72e5cd0f18f262f5da20efa9e241699e0cf3a766317a17392550c9ad7b37d8"}, - {file = "websockets-10.4-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:185929b4808b36a79c65b7865783b87b6841e852ef5407a2fb0c03381092fa3b"}, - {file = "websockets-10.4-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:7d27a7e34c313b3a7f91adcd05134315002aaf8540d7b4f90336beafaea6217c"}, - {file = "websockets-10.4-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:884be66c76a444c59f801ac13f40c76f176f1bfa815ef5b8ed44321e74f1600b"}, - {file = "websockets-10.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:931c039af54fc195fe6ad536fde4b0de04da9d5916e78e55405436348cfb0e56"}, - {file = "websockets-10.4-cp38-cp38-win32.whl", hash = "sha256:db3c336f9eda2532ec0fd8ea49fef7a8df8f6c804cdf4f39e5c5c0d4a4ad9a7a"}, - {file = "websockets-10.4-cp38-cp38-win_amd64.whl", hash = "sha256:48c08473563323f9c9debac781ecf66f94ad5a3680a38fe84dee5388cf5acaf6"}, - {file = "websockets-10.4-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:40e826de3085721dabc7cf9bfd41682dadc02286d8cf149b3ad05bff89311e4f"}, - {file = "websockets-10.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:56029457f219ade1f2fc12a6504ea61e14ee227a815531f9738e41203a429112"}, - {file = "websockets-10.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f5fc088b7a32f244c519a048c170f14cf2251b849ef0e20cbbb0fdf0fdaf556f"}, - {file = "websockets-10.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2fc8709c00704194213d45e455adc106ff9e87658297f72d544220e32029cd3d"}, - {file = "websockets-10.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0154f7691e4fe6c2b2bc275b5701e8b158dae92a1ab229e2b940efe11905dff4"}, - {file = "websockets-10.4-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4c6d2264f485f0b53adf22697ac11e261ce84805c232ed5dbe6b1bcb84b00ff0"}, - {file = "websockets-10.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:9bc42e8402dc5e9905fb8b9649f57efcb2056693b7e88faa8fb029256ba9c68c"}, - {file = "websockets-10.4-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:edc344de4dac1d89300a053ac973299e82d3db56330f3494905643bb68801269"}, - {file = "websockets-10.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:84bc2a7d075f32f6ed98652db3a680a17a4edb21ca7f80fe42e38753a58ee02b"}, - {file = "websockets-10.4-cp39-cp39-win32.whl", hash = "sha256:c94ae4faf2d09f7c81847c63843f84fe47bf6253c9d60b20f25edfd30fb12588"}, - {file = "websockets-10.4-cp39-cp39-win_amd64.whl", hash = "sha256:bbccd847aa0c3a69b5f691a84d2341a4f8a629c6922558f2a70611305f902d74"}, - {file = "websockets-10.4-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:82ff5e1cae4e855147fd57a2863376ed7454134c2bf49ec604dfe71e446e2193"}, - {file = "websockets-10.4-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d210abe51b5da0ffdbf7b43eed0cfdff8a55a1ab17abbec4301c9ff077dd0342"}, - {file = "websockets-10.4-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:942de28af58f352a6f588bc72490ae0f4ccd6dfc2bd3de5945b882a078e4e179"}, - {file = "websockets-10.4-pp37-pypy37_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c9b27d6c1c6cd53dc93614967e9ce00ae7f864a2d9f99fe5ed86706e1ecbf485"}, - {file = "websockets-10.4-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:3d3cac3e32b2c8414f4f87c1b2ab686fa6284a980ba283617404377cd448f631"}, - {file = "websockets-10.4-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:da39dd03d130162deb63da51f6e66ed73032ae62e74aaccc4236e30edccddbb0"}, - {file = "websockets-10.4-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:389f8dbb5c489e305fb113ca1b6bdcdaa130923f77485db5b189de343a179393"}, - {file = "websockets-10.4-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:09a1814bb15eff7069e51fed0826df0bc0702652b5cb8f87697d469d79c23576"}, - {file = "websockets-10.4-pp38-pypy38_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ff64a1d38d156d429404aaa84b27305e957fd10c30e5880d1765c9480bea490f"}, - {file = "websockets-10.4-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:b343f521b047493dc4022dd338fc6db9d9282658862756b4f6fd0e996c1380e1"}, - {file = "websockets-10.4-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:932af322458da7e4e35df32f050389e13d3d96b09d274b22a7aa1808f292fee4"}, - {file = "websockets-10.4-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d6a4162139374a49eb18ef5b2f4da1dd95c994588f5033d64e0bbfda4b6b6fcf"}, - {file = "websockets-10.4-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c57e4c1349fbe0e446c9fa7b19ed2f8a4417233b6984277cce392819123142d3"}, - {file = "websockets-10.4-pp39-pypy39_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b627c266f295de9dea86bd1112ed3d5fafb69a348af30a2422e16590a8ecba13"}, - {file = "websockets-10.4-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:05a7233089f8bd355e8cbe127c2e8ca0b4ea55467861906b80d2ebc7db4d6b72"}, - {file = "websockets-10.4.tar.gz", hash = "sha256:eef610b23933c54d5d921c92578ae5f89813438fded840c2e9809d378dc765d3"}, -] -yarl = [ - {file = "yarl-1.8.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:abc06b97407868ef38f3d172762f4069323de52f2b70d133d096a48d72215d28"}, - {file = "yarl-1.8.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:07b21e274de4c637f3e3b7104694e53260b5fc10d51fb3ec5fed1da8e0f754e3"}, - {file = "yarl-1.8.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9de955d98e02fab288c7718662afb33aab64212ecb368c5dc866d9a57bf48880"}, - {file = "yarl-1.8.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7ec362167e2c9fd178f82f252b6d97669d7245695dc057ee182118042026da40"}, - {file = "yarl-1.8.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:20df6ff4089bc86e4a66e3b1380460f864df3dd9dccaf88d6b3385d24405893b"}, - {file = "yarl-1.8.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5999c4662631cb798496535afbd837a102859568adc67d75d2045e31ec3ac497"}, - {file = "yarl-1.8.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ed19b74e81b10b592084a5ad1e70f845f0aacb57577018d31de064e71ffa267a"}, - {file = "yarl-1.8.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1e4808f996ca39a6463f45182e2af2fae55e2560be586d447ce8016f389f626f"}, - {file = "yarl-1.8.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:2d800b9c2eaf0684c08be5f50e52bfa2aa920e7163c2ea43f4f431e829b4f0fd"}, - {file = "yarl-1.8.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:6628d750041550c5d9da50bb40b5cf28a2e63b9388bac10fedd4f19236ef4957"}, - {file = "yarl-1.8.1-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:f5af52738e225fcc526ae64071b7e5342abe03f42e0e8918227b38c9aa711e28"}, - {file = "yarl-1.8.1-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:76577f13333b4fe345c3704811ac7509b31499132ff0181f25ee26619de2c843"}, - {file = "yarl-1.8.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:0c03f456522d1ec815893d85fccb5def01ffaa74c1b16ff30f8aaa03eb21e453"}, - {file = "yarl-1.8.1-cp310-cp310-win32.whl", hash = "sha256:ea30a42dc94d42f2ba4d0f7c0ffb4f4f9baa1b23045910c0c32df9c9902cb272"}, - {file = "yarl-1.8.1-cp310-cp310-win_amd64.whl", hash = "sha256:9130ddf1ae9978abe63808b6b60a897e41fccb834408cde79522feb37fb72fb0"}, - {file = "yarl-1.8.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:0ab5a138211c1c366404d912824bdcf5545ccba5b3ff52c42c4af4cbdc2c5035"}, - {file = "yarl-1.8.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0fb2cb4204ddb456a8e32381f9a90000429489a25f64e817e6ff94879d432fc"}, - {file = "yarl-1.8.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:85cba594433915d5c9a0d14b24cfba0339f57a2fff203a5d4fd070e593307d0b"}, - {file = "yarl-1.8.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1ca7e596c55bd675432b11320b4eacc62310c2145d6801a1f8e9ad160685a231"}, - {file = "yarl-1.8.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d0f77539733e0ec2475ddcd4e26777d08996f8cd55d2aef82ec4d3896687abda"}, - {file = "yarl-1.8.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:29e256649f42771829974e742061c3501cc50cf16e63f91ed8d1bf98242e5507"}, - {file = "yarl-1.8.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:7fce6cbc6c170ede0221cc8c91b285f7f3c8b9fe28283b51885ff621bbe0f8ee"}, - {file = "yarl-1.8.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:59ddd85a1214862ce7c7c66457f05543b6a275b70a65de366030d56159a979f0"}, - {file = "yarl-1.8.1-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:12768232751689c1a89b0376a96a32bc7633c08da45ad985d0c49ede691f5c0d"}, - {file = "yarl-1.8.1-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:b19255dde4b4f4c32e012038f2c169bb72e7f081552bea4641cab4d88bc409dd"}, - {file = "yarl-1.8.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:6c8148e0b52bf9535c40c48faebb00cb294ee577ca069d21bd5c48d302a83780"}, - {file = "yarl-1.8.1-cp37-cp37m-win32.whl", hash = "sha256:de839c3a1826a909fdbfe05f6fe2167c4ab033f1133757b5936efe2f84904c07"}, - {file = "yarl-1.8.1-cp37-cp37m-win_amd64.whl", hash = "sha256:dd032e8422a52e5a4860e062eb84ac94ea08861d334a4bcaf142a63ce8ad4802"}, - {file = "yarl-1.8.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:19cd801d6f983918a3f3a39f3a45b553c015c5aac92ccd1fac619bd74beece4a"}, - {file = "yarl-1.8.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6347f1a58e658b97b0a0d1ff7658a03cb79bdbda0331603bed24dd7054a6dea1"}, - {file = "yarl-1.8.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7c0da7e44d0c9108d8b98469338705e07f4bb7dab96dbd8fa4e91b337db42548"}, - {file = "yarl-1.8.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5587bba41399854703212b87071c6d8638fa6e61656385875f8c6dff92b2e461"}, - {file = "yarl-1.8.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:31a9a04ecccd6b03e2b0e12e82131f1488dea5555a13a4d32f064e22a6003cfe"}, - {file = "yarl-1.8.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:205904cffd69ae972a1707a1bd3ea7cded594b1d773a0ce66714edf17833cdae"}, - {file = "yarl-1.8.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ea513a25976d21733bff523e0ca836ef1679630ef4ad22d46987d04b372d57fc"}, - {file = "yarl-1.8.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d0b51530877d3ad7a8d47b2fff0c8df3b8f3b8deddf057379ba50b13df2a5eae"}, - {file = "yarl-1.8.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:d2b8f245dad9e331540c350285910b20dd913dc86d4ee410c11d48523c4fd546"}, - {file = "yarl-1.8.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:ab2a60d57ca88e1d4ca34a10e9fb4ab2ac5ad315543351de3a612bbb0560bead"}, - {file = "yarl-1.8.1-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:449c957ffc6bc2309e1fbe67ab7d2c1efca89d3f4912baeb8ead207bb3cc1cd4"}, - {file = "yarl-1.8.1-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:a165442348c211b5dea67c0206fc61366212d7082ba8118c8c5c1c853ea4d82e"}, - {file = "yarl-1.8.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:b3ded839a5c5608eec8b6f9ae9a62cb22cd037ea97c627f38ae0841a48f09eae"}, - {file = "yarl-1.8.1-cp38-cp38-win32.whl", hash = "sha256:c1445a0c562ed561d06d8cbc5c8916c6008a31c60bc3655cdd2de1d3bf5174a0"}, - {file = "yarl-1.8.1-cp38-cp38-win_amd64.whl", hash = "sha256:56c11efb0a89700987d05597b08a1efcd78d74c52febe530126785e1b1a285f4"}, - {file = "yarl-1.8.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:e80ed5a9939ceb6fda42811542f31c8602be336b1fb977bccb012e83da7e4936"}, - {file = "yarl-1.8.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6afb336e23a793cd3b6476c30f030a0d4c7539cd81649683b5e0c1b0ab0bf350"}, - {file = "yarl-1.8.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4c322cbaa4ed78a8aac89b2174a6df398faf50e5fc12c4c191c40c59d5e28357"}, - {file = "yarl-1.8.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fae37373155f5ef9b403ab48af5136ae9851151f7aacd9926251ab26b953118b"}, - {file = "yarl-1.8.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5395da939ffa959974577eff2cbfc24b004a2fb6c346918f39966a5786874e54"}, - {file = "yarl-1.8.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:076eede537ab978b605f41db79a56cad2e7efeea2aa6e0fa8f05a26c24a034fb"}, - {file = "yarl-1.8.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3d1a50e461615747dd93c099f297c1994d472b0f4d2db8a64e55b1edf704ec1c"}, - {file = "yarl-1.8.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7de89c8456525650ffa2bb56a3eee6af891e98f498babd43ae307bd42dca98f6"}, - {file = "yarl-1.8.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:4a88510731cd8d4befaba5fbd734a7dd914de5ab8132a5b3dde0bbd6c9476c64"}, - {file = "yarl-1.8.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:2d93a049d29df172f48bcb09acf9226318e712ce67374f893b460b42cc1380ae"}, - {file = "yarl-1.8.1-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:21ac44b763e0eec15746a3d440f5e09ad2ecc8b5f6dcd3ea8cb4773d6d4703e3"}, - {file = "yarl-1.8.1-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:d0272228fabe78ce00a3365ffffd6f643f57a91043e119c289aaba202f4095b0"}, - {file = "yarl-1.8.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:99449cd5366fe4608e7226c6cae80873296dfa0cde45d9b498fefa1de315a09e"}, - {file = "yarl-1.8.1-cp39-cp39-win32.whl", hash = "sha256:8b0af1cf36b93cee99a31a545fe91d08223e64390c5ecc5e94c39511832a4bb6"}, - {file = "yarl-1.8.1-cp39-cp39-win_amd64.whl", hash = "sha256:de49d77e968de6626ba7ef4472323f9d2e5a56c1d85b7c0e2a190b2173d3b9be"}, - {file = "yarl-1.8.1.tar.gz", hash = "sha256:af887845b8c2e060eb5605ff72b6f2dd2aab7a761379373fd89d314f4752abbf"}, -] -yt-dlp = [ - {file = "yt-dlp-2021.12.27.tar.gz", hash = "sha256:2244df3759751487e796b23b67216bee98e70832a3a43c2526b0b0e0bbfbcb5b"}, - {file = "yt_dlp-2021.12.27-py2.py3-none-any.whl", hash = "sha256:bb46898a175d149c9c6bb2846056590d297aa4eafad8487c3e1315d2c6090896"}, -] +content-hash = "7d05f16c0318f87b781ad5a1552b41d35d5792cff2ba5b0bed35e74acb597867" diff --git a/pyproject.toml b/pyproject.toml index 8d6592774..b5e8c132b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -15,10 +15,10 @@ canary = "canary.main:main" [tool.poetry.dependencies] python = "~3.10.0" -beautifulsoup4 = "==4.10.0" +beautifulsoup4 = "^4.12.2" sympy = "^1.9" -requests = ">=2.20.0" -tabulate = "==0.8.9" +requests = ">=2.30.0,<3" +tabulate = "~0.8.9" "discord.py" = {extras = ["voice"], version = "~1.6.0"} opencv-python = "==4.6.0.66" pytz = ">=2020.5" @@ -26,7 +26,7 @@ numpy = "^1.21.1" aiohttp = "~3.7.4" urllib3 = ">=1.25.3" feedparser = "^6.0.8" -regex = "^2021.11.10" +regex = "^2023.5.5" googletrans = "==4.0.0rc1" yt-dlp = "^2021.12.27" Pillow = "^8.3.2" @@ -38,9 +38,9 @@ python-dotenv = "^0.21.0" pydantic = "^1.10.2" [tool.poetry.dev-dependencies] -pytest = "^7.1.0" -black = "^22.6.0" -mypy = ">=0.990,<0.991" +pytest = "^7.3.1" +black = "^23.3.0" +mypy = "~1.2.0" types-beautifulsoup4 = "^4.11.5" types-regex = "^2022.8.17.0" types-requests = "^2.28.9" From 07c16b56dcc29473d62405b614f6f186ba816820 Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Sat, 13 May 2023 14:00:00 -0400 Subject: [PATCH 081/127] update python & actions ver --- .github/workflows/formatting_check.yml | 6 +++--- .github/workflows/poetry-dev.yml | 6 +++--- .github/workflows/poetry-prod.yml | 6 +++--- .github/workflows/publish-docker.yml | 6 +++--- Dockerfile | 4 ++-- 5 files changed, 14 insertions(+), 14 deletions(-) diff --git a/.github/workflows/formatting_check.yml b/.github/workflows/formatting_check.yml index 67f8e0d65..655f91fa9 100644 --- a/.github/workflows/formatting_check.yml +++ b/.github/workflows/formatting_check.yml @@ -9,9 +9,9 @@ jobs: lint: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - uses: actions/setup-python@v2 + - uses: actions/checkout@v3 + - uses: actions/setup-python@v4 - uses: psf/black@stable with: - options: "--diff --check -t py310 --fast" + options: "--diff --check -t py311 --fast" diff --git a/.github/workflows/poetry-dev.yml b/.github/workflows/poetry-dev.yml index 540d528fb..9d050072d 100644 --- a/.github/workflows/poetry-dev.yml +++ b/.github/workflows/poetry-dev.yml @@ -30,12 +30,12 @@ jobs: - 'macos-11.0' - 'windows-2019' python-version: - - '3.10' + - '3.11' steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Set up Python - uses: actions/setup-python@v2 + uses: actions/setup-python@v4 with: python-version: ${{ matrix.python-version }} diff --git a/.github/workflows/poetry-prod.yml b/.github/workflows/poetry-prod.yml index 8cae68b13..954b65654 100644 --- a/.github/workflows/poetry-prod.yml +++ b/.github/workflows/poetry-prod.yml @@ -20,12 +20,12 @@ jobs: - 'ubuntu-20.04' - 'ubuntu-18.04' python-version: - - '3.10' + - '3.11' steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Set up Python - uses: actions/setup-python@v2 + uses: actions/setup-python@v4 with: python-version: ${{ matrix.python-version }} diff --git a/.github/workflows/publish-docker.yml b/.github/workflows/publish-docker.yml index d4b956d3c..85809de3d 100644 --- a/.github/workflows/publish-docker.yml +++ b/.github/workflows/publish-docker.yml @@ -11,10 +11,10 @@ jobs: packages: write contents: read steps: - - uses: actions/checkout@v2 - - uses: actions/setup-python@v2 + - uses: actions/checkout@v3 + - uses: actions/setup-python@v4 with: - python-version: '3.10' + python-version: '3.11' - run: pip install poetry && poetry update && poetry export -f requirements.txt > requirements.txt - uses: docker/metadata-action@v3 id: meta diff --git a/Dockerfile b/Dockerfile index 7d99a310e..bc0ad3b2e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM python:3.10-slim-bullseye +FROM python:3.11-slim-bullseye # Install base apt dependencies RUN apt-get update && apt-get install -y git sqlite3 @@ -25,4 +25,4 @@ WORKDIR /canary # Users will have to mount their config.ini in by hand # Users should mount a read/writable volume for /canary/data/runtime -CMD ["python3.10", "-m", "canary.main"] +CMD ["python3.11", "-m", "canary.main"] From a9cf62f50ee17e994bd719c8f6adfc97f51482e4 Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Sat, 13 May 2023 14:00:43 -0400 Subject: [PATCH 082/127] new config integration work --- canary/bot.py | 22 +++++++++++++--------- canary/cogs/currency.py | 18 +++++++++++------- canary/config/config.py | 32 +++++++++++++++++--------------- 3 files changed, 41 insertions(+), 31 deletions(-) diff --git a/canary/bot.py b/canary/bot.py index 784bcae15..52bbeb9e4 100644 --- a/canary/bot.py +++ b/canary/bot.py @@ -26,15 +26,23 @@ from pathlib import Path from typing import AsyncGenerator -__all__ = ["Canary", "bot", "developer_role", "moderator_role", "muted_role"] +__all__ = ["Canary", "bot"] -config = Config() -command_prefix = config.command_prefix +LOG_LEVELS = { + "critical": logging.CRITICAL, + "error": logging.ERROR, + "warning": logging.WARNING, + "info": logging.INFO, + "debug": logging.DEBUG, + "notset": logging.NOTSET, +} + +config: Config = Config() # Create parent logger, which will send all logs from the "sub-loggers" # to the specified log file logger = logging.getLogger("Canary") -logger.setLevel(config.log_level) +logger.setLevel(LOG_LEVELS[config.log_level]) file_handler = logging.FileHandler(filename=config.log_file, encoding="utf-8", mode="a") file_handler.setFormatter(logging.Formatter("[%(levelname)s] %(asctime)s: %(message)s")) logger.addHandler(file_handler) @@ -85,7 +93,7 @@ class Canary(commands.Bot): SCHEMA_PATH = Path(__file__).parent / "Martlet.schema" def __init__(self, *args, **kwargs): - super().__init__(command_prefix, *args, **kwargs) + super().__init__(config.command_prefix, *args, **kwargs) self.logger = logger self.dev_logger = dev_logger self.mod_logger = mod_logger @@ -168,11 +176,7 @@ async def on_command_error(self, ctx, error): self.log_traceback(error) -# predefined variables to be imported intents = Intents.default() intents.members = True intents.presences = True bot = Canary(case_insensitive=True, intents=intents) -moderator_role = bot.config.moderator_role -developer_role = bot.config.developer_role -muted_role = bot.config.muted_role diff --git a/canary/cogs/currency.py b/canary/cogs/currency.py index 8619a5868..e4ede33d9 100644 --- a/canary/cogs/currency.py +++ b/canary/cogs/currency.py @@ -27,6 +27,7 @@ from tabulate import tabulate from ..bot import Canary +from ..config.config import CurrencyModel from .base_cog import CanaryCog from .utils.members import add_member_if_needed from .utils.paginator import Pages @@ -61,8 +62,11 @@ class Currency(CanaryCog): def __init__(self, bot: Canary): super().__init__(bot) - self.currency: dict = self.bot.config.currency - self.prec: int = self.currency["precision"] + self.currency: CurrencyModel = self.bot.config.currency + + self.symbol: str = self.currency.symbol + self.prec: int = self.currency.precision + self.initial: Decimal = Decimal(self.currency.initial) async def fetch_all_balances(self) -> list[tuple[str, str, Decimal]]: # after @@ -114,16 +118,16 @@ def parse_currency(amount: str, balance: Decimal) -> Decimal | None: return None def currency_to_db(self, amount: Decimal) -> int: - return int(amount * Decimal(10 ** self.currency["precision"])) + return int(amount * Decimal(10 ** self.prec)) def db_to_currency(self, amount: int) -> Decimal: - return Decimal(amount) / Decimal(10 ** self.currency["precision"]) + return Decimal(amount) / Decimal(10 ** self.prec) def format_currency(self, amount: Decimal) -> str: return ("{:." + str(self.prec) + "f}").format(amount) def format_symbol_currency(self, amount: Decimal) -> str: - return self.currency["symbol"] + self.format_currency(amount) + return self.symbol + self.format_currency(amount) @staticmethod def check_bet(balance: Decimal, bet: Decimal) -> str | None: @@ -181,14 +185,14 @@ async def initial_claim(self, ctx: commands.Context): await self.create_bank_transaction( db, author, - self.currency["initial_amount"], + self.initial, ACTION_INITIAL_CLAIM, {"channel": ctx.message.channel.id}, ) await db.commit() await ctx.send( - f"{author_name} claimed their initial {self.format_symbol_currency(self.currency['initial_amount'])}!" + f"{author_name} claimed their initial {self.format_symbol_currency(self.initial)}!" ) @commands.command() diff --git a/canary/config/config.py b/canary/config/config.py index 2d7ffb65a..b55afc13b 100644 --- a/canary/config/config.py +++ b/canary/config/config.py @@ -18,20 +18,18 @@ import codecs import configparser import decimal -import logging import os from pathlib import Path from pydantic import BaseModel, BaseSettings -LOG_LEVELS = { - "critical": logging.CRITICAL, - "error": logging.ERROR, - "warning": logging.WARNING, - "info": logging.INFO, - "debug": logging.DEBUG, - "notset": logging.NOTSET, -} +from typing import Literal + +__all__ = [ + "CurrencyModel", + "MusicModel", + "Config", +] class CurrencyModel(BaseModel): @@ -48,7 +46,11 @@ class MusicModel(BaseModel): start_vol: float = "100.0" -class Settings(BaseSettings): +class Config(BaseSettings): + # Logging + log_level: Literal["critical", "error", "warning", "info", "debug", "notset"] = "info" + log_file: Path = Path.cwd() / "canary.log" + # Discord token discord_key: str @@ -125,18 +127,18 @@ class Settings(BaseSettings): # Assignable Roles # TODO - class Config: + class Config: # Pydantic config for our own Config class env_file = ".env" env_prefix = "CANARY_" env_nested_delimiter = "__" -class Config: +class ConfigOld: CONFIG_PATH = Path(__file__).parent / "config.ini" def __init__(self): config = configparser.ConfigParser() - config.read_file(codecs.open(str(Config.CONFIG_PATH), "r", "utf-8-sig")) + config.read_file(codecs.open(str(ConfigOld.CONFIG_PATH), "r", "utf-8-sig")) # Discord token # Try to get from environment; if not found, then @@ -184,8 +186,8 @@ def __init__(self): # Logging self.log_file = config["Logging"]["LogFile"] - loglevel = config["Logging"]["LogLevel"].lower() - self.log_level = LOG_LEVELS.get(loglevel, logging.WARNING) + # loglevel = config["Logging"]["LogLevel"].lower() + # self.log_level = LOG_LEVELS.get(loglevel, logging.WARNING) if config["Logging"]["DevLogWebhookID"] and config["Logging"]["DevLogWebhookToken"]: self.dev_log_webhook_id = int(config["Logging"]["DevLogWebhookID"]) self.dev_log_webhook_token = config["Logging"]["DevLogWebhookToken"] From 19d873b0281e1dab1d1a3259f81bbc71d4070893 Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Sat, 13 May 2023 14:01:49 -0400 Subject: [PATCH 083/127] single year range var for course url templates --- canary/cogs/helpers.py | 15 +++++++++------ canary/config/config.py | 6 ++++-- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/canary/cogs/helpers.py b/canary/cogs/helpers.py index db1075119..b14370ebf 100644 --- a/canary/cogs/helpers.py +++ b/canary/cogs/helpers.py @@ -263,7 +263,7 @@ async def course(self, ctx: commands.Context, *, query: str): return search_term = re.sub(r"\s+", "", f"{result.group(1)}-{result.group(2)}") - url = self.bot.config.course_tpl.format(search_term) + url = self.bot.config.course_tpl.format(self.bot.config.course_year_range, search_term) r = await fetch(url, "content") soup = BeautifulSoup(r, "lxml") @@ -459,15 +459,18 @@ async def search(self, ctx: commands.Context, *, query: str): await ctx.trigger_typing() while pagenum < pagelimit: - r = await fetch(self.bot.config.course_search_tpl.format(keyword, pagenum), "content") + r = await fetch( + self.bot.config.course_search_tpl.format(self.bot.config.course_year_range, keyword, pagenum), + "content" + ) soup = BeautifulSoup(r, "lxml") found = soup.find_all("div", {"class": "views-row"}) if len(found) < 1: break - else: - courses = courses + found - pagenum += 1 + + courses = courses + found + pagenum += 1 if len(courses) < 1: await ctx.send("No course found for: {}.".format(query)) @@ -483,7 +486,7 @@ async def search(self, ctx: commands.Context, *, query: str): p = Pages( ctx, item_list=course_list, - title="Courses found for {}".format(query), + title=f"Courses found for {query}", display_option=(2, 10), editable_content=False, ) diff --git a/canary/config/config.py b/canary/config/config.py index b55afc13b..8b1675be8 100644 --- a/canary/config/config.py +++ b/canary/config/config.py @@ -104,9 +104,11 @@ class Config(BaseSettings): db_path: str = "./data/runtime/Martlet.db" # Helpers configuration - course_tpl: str = "http://www.mcgill.ca/study/2022-2023/courses/{}" + course_year_range: str = "2023-2024" + course_tpl: str = "http://www.mcgill.ca/study/{course_year_range}/courses/{}" course_search_tpl: str = ( - "http://www.mcgill.ca/study/2022-2023/courses/search?search_api_views_fulltext={}&sort_by=field_subject_code" + "http://www.mcgill.ca/study/{course_year_range}/courses/search?search_api_views_fulltext={}" + "&sort_by=field_subject_code" "&page={}" ) gc_weather_url: str = "http://weather.gc.ca/city/pages/qc-147_metric_e.html" From d1604a6da83d6b6e3da2bc8cb62591d37ddb53f6 Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Sat, 13 May 2023 14:03:54 -0400 Subject: [PATCH 084/127] new config: impl bet roll --- canary/cogs/currency.py | 2 +- canary/config/config.py | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/canary/cogs/currency.py b/canary/cogs/currency.py index e4ede33d9..ca622c05d 100644 --- a/canary/cogs/currency.py +++ b/canary/cogs/currency.py @@ -317,7 +317,7 @@ async def bet_roll(self, ctx: commands.Context, bet: str | None = None): result = random.randrange(1, 101) amount_returned = Decimal(0) - for case, amount in self.currency["bet_roll_cases"]: + for case, amount in zip(self.currency.bet_roll_cases, self.currency.bet_roll_returns): if result <= case: amount_returned = bet_dec * amount break diff --git a/canary/config/config.py b/canary/config/config.py index 8b1675be8..3e48a17fa 100644 --- a/canary/config/config.py +++ b/canary/config/config.py @@ -38,6 +38,9 @@ class CurrencyModel(BaseModel): precision: int = 2 initial: int = 1000 + bet_roll_cases: tuple[int, ...] = (66, 90, 99, 100) # d100 roll threshold + bet_roll_returns: tuple[int, ...] = (0, 2, 4, 10) # multiplication factorys + # TODO: Finish From 39162eacb19bd59a86eb273f2a972459aebd5d0c Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Sat, 13 May 2023 14:05:58 -0400 Subject: [PATCH 085/127] ignore poetry toml --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 7538d8ee0..d0b3cff07 100644 --- a/.gitignore +++ b/.gitignore @@ -103,6 +103,7 @@ ENV/ # configuration files **/*.ini +poetry.toml # other *~ From 1cfd552f57780a19876da5d9552695f8edaa8aeb Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Sat, 13 May 2023 14:06:06 -0400 Subject: [PATCH 086/127] add example env file --- example.env | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 example.env diff --git a/example.env b/example.env new file mode 100644 index 000000000..8b67e6add --- /dev/null +++ b/example.env @@ -0,0 +1,4 @@ +# Change this to .env and enter your customizations! +CANARY_DISCORD_TOKEN=my_token_here +CANARY_SERVER_ID=test-server-id +CANARY_COMMAND_PREFIX=! From 22c7e0613dcb8ea7850dda077dd27bacd9599e6c Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Sat, 13 May 2023 14:07:25 -0400 Subject: [PATCH 087/127] fix supported python ver --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index b5e8c132b..780deb81c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -14,7 +14,7 @@ packages = [ canary = "canary.main:main" [tool.poetry.dependencies] -python = "~3.10.0" +python = ">=3.10.0,<3.12" beautifulsoup4 = "^4.12.2" sympy = "^1.9" requests = ">=2.30.0,<3" From 87f780e7656aa38cfc8a8145d2b3696f1c8c49fb Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Sat, 13 May 2023 14:08:11 -0400 Subject: [PATCH 088/127] ci: remove old ubuntus from matrix --- .github/workflows/poetry-dev.yml | 2 -- .github/workflows/poetry-prod.yml | 1 - 2 files changed, 3 deletions(-) diff --git a/.github/workflows/poetry-dev.yml b/.github/workflows/poetry-dev.yml index 9d050072d..53a4e0876 100644 --- a/.github/workflows/poetry-dev.yml +++ b/.github/workflows/poetry-dev.yml @@ -25,8 +25,6 @@ jobs: matrix: os: - 'ubuntu-20.04' - - 'ubuntu-18.04' - # - 'macos-10.15' - 'macos-11.0' - 'windows-2019' python-version: diff --git a/.github/workflows/poetry-prod.yml b/.github/workflows/poetry-prod.yml index 954b65654..d2d00a57e 100644 --- a/.github/workflows/poetry-prod.yml +++ b/.github/workflows/poetry-prod.yml @@ -18,7 +18,6 @@ jobs: matrix: os: - 'ubuntu-20.04' - - 'ubuntu-18.04' python-version: - '3.11' steps: From f09795900db0c4e3c959e67e029c9b091bbea5ed Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Sat, 13 May 2023 14:09:43 -0400 Subject: [PATCH 089/127] chore [noci]: update copyright --- canary/Martlet.schema | 2 +- canary/cogs/currency.py | 2 +- canary/cogs/customreactions.py | 2 +- canary/cogs/games.py | 2 +- canary/cogs/helpers.py | 2 +- canary/cogs/memes.py | 2 +- canary/cogs/mod.py | 2 +- canary/cogs/roles.py | 2 +- canary/cogs/score.py | 2 +- canary/cogs/utils/arg_converter.py | 2 +- canary/cogs/utils/checks.py | 2 +- canary/cogs/utils/clamp_default.py | 2 +- canary/cogs/utils/dice_roll.py | 2 +- canary/cogs/utils/hangman.py | 2 +- canary/cogs/utils/mock_context.py | 2 +- canary/cogs/utils/music_helpers.py | 2 +- canary/cogs/utils/paginator.py | 2 +- canary/cogs/utils/role_restoration.py | 2 +- canary/config/config.py | 2 +- canary/main.py | 2 +- 20 files changed, 20 insertions(+), 20 deletions(-) diff --git a/canary/Martlet.schema b/canary/Martlet.schema index 96c146a67..0f0786fda 100644 --- a/canary/Martlet.schema +++ b/canary/Martlet.schema @@ -1,5 +1,5 @@ /* - * Copyright (C) idoneam (2016-2022) + * Copyright (C) idoneam (2016-2023) * * This file is part of Canary * diff --git a/canary/cogs/currency.py b/canary/cogs/currency.py index ca622c05d..15af39af6 100644 --- a/canary/cogs/currency.py +++ b/canary/cogs/currency.py @@ -1,4 +1,4 @@ -# Copyright (C) idoneam (2016-2022) +# Copyright (C) idoneam (2016-2023) # # This file is part of Canary # diff --git a/canary/cogs/customreactions.py b/canary/cogs/customreactions.py index 15a9d5a50..7d18ebfad 100644 --- a/canary/cogs/customreactions.py +++ b/canary/cogs/customreactions.py @@ -1,4 +1,4 @@ -# Copyright (C) idoneam (2016-2022) +# Copyright (C) idoneam (2016-2023) # # This file is part of Canary # diff --git a/canary/cogs/games.py b/canary/cogs/games.py index ab57157fb..b9d0b1d61 100644 --- a/canary/cogs/games.py +++ b/canary/cogs/games.py @@ -1,4 +1,4 @@ -# Copyright (C) idoneam (2016-2022) +# Copyright (C) idoneam (2016-2023) # # This file is part of Canary # diff --git a/canary/cogs/helpers.py b/canary/cogs/helpers.py index b14370ebf..059a4028a 100644 --- a/canary/cogs/helpers.py +++ b/canary/cogs/helpers.py @@ -1,4 +1,4 @@ -# Copyright (C) idoneam (2016-2022) +# Copyright (C) idoneam (2016-2023) # # This file is part of Canary # diff --git a/canary/cogs/memes.py b/canary/cogs/memes.py index 2b146e9c7..a18cb9583 100644 --- a/canary/cogs/memes.py +++ b/canary/cogs/memes.py @@ -1,4 +1,4 @@ -# Copyright (C) idoneam (2016-2022) +# Copyright (C) idoneam (2016-2023) # # This file is part of Canary # diff --git a/canary/cogs/mod.py b/canary/cogs/mod.py index 79213eee1..b81a8c4e0 100644 --- a/canary/cogs/mod.py +++ b/canary/cogs/mod.py @@ -1,4 +1,4 @@ -# Copyright (C) idoneam (2016-2022) +# Copyright (C) idoneam (2016-2023) # # This file is part of Canary # diff --git a/canary/cogs/roles.py b/canary/cogs/roles.py index 5a7226b2e..d003b0fa4 100644 --- a/canary/cogs/roles.py +++ b/canary/cogs/roles.py @@ -1,4 +1,4 @@ -# Copyright (C) idoneam (2016-2022) +# Copyright (C) idoneam (2016-2023) # # This file is part of Canary # diff --git a/canary/cogs/score.py b/canary/cogs/score.py index ddf7dc296..116475cbf 100644 --- a/canary/cogs/score.py +++ b/canary/cogs/score.py @@ -1,4 +1,4 @@ -# Copyright (C) idoneam (2016-2022) +# Copyright (C) idoneam (2016-2023) # # This file is part of Canary # diff --git a/canary/cogs/utils/arg_converter.py b/canary/cogs/utils/arg_converter.py index 123b55e98..f94d83db1 100644 --- a/canary/cogs/utils/arg_converter.py +++ b/canary/cogs/utils/arg_converter.py @@ -1,4 +1,4 @@ -# Copyright (C) idoneam (2016-2022) +# Copyright (C) idoneam (2016-2023) # # This file is part of Canary # diff --git a/canary/cogs/utils/checks.py b/canary/cogs/utils/checks.py index 5ebe942ae..5e034746e 100644 --- a/canary/cogs/utils/checks.py +++ b/canary/cogs/utils/checks.py @@ -1,4 +1,4 @@ -# Copyright (C) idoneam (2016-2022) +# Copyright (C) idoneam (2016-2023) # # This file is part of Canary # diff --git a/canary/cogs/utils/clamp_default.py b/canary/cogs/utils/clamp_default.py index f1e14ba64..8bbfeae19 100644 --- a/canary/cogs/utils/clamp_default.py +++ b/canary/cogs/utils/clamp_default.py @@ -1,4 +1,4 @@ -# Copyright (C) idoneam (2016-2022) +# Copyright (C) idoneam (2016-2023) # # This file is part of Canary # diff --git a/canary/cogs/utils/dice_roll.py b/canary/cogs/utils/dice_roll.py index 4d8e38c96..5afd5ac49 100644 --- a/canary/cogs/utils/dice_roll.py +++ b/canary/cogs/utils/dice_roll.py @@ -1,4 +1,4 @@ -# Copyright (C) idoneam (2016-2022) +# Copyright (C) idoneam (2016-2023) # # This file is part of Canary # diff --git a/canary/cogs/utils/hangman.py b/canary/cogs/utils/hangman.py index e4a732e82..621b6a6ae 100644 --- a/canary/cogs/utils/hangman.py +++ b/canary/cogs/utils/hangman.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (C) idoneam (2016-2022) +# Copyright (C) idoneam (2016-2023) # # This file is part of Canary # diff --git a/canary/cogs/utils/mock_context.py b/canary/cogs/utils/mock_context.py index dba6a0c17..0dbc16f78 100644 --- a/canary/cogs/utils/mock_context.py +++ b/canary/cogs/utils/mock_context.py @@ -1,4 +1,4 @@ -# Copyright (C) idoneam (2016-2022) +# Copyright (C) idoneam (2016-2023) # # This file is part of Canary # diff --git a/canary/cogs/utils/music_helpers.py b/canary/cogs/utils/music_helpers.py index e5510f162..f3fa86d4f 100644 --- a/canary/cogs/utils/music_helpers.py +++ b/canary/cogs/utils/music_helpers.py @@ -1,4 +1,4 @@ -# Copyright (C) idoneam (2016-2022) +# Copyright (C) idoneam (2016-2023) # # This file is part of Canary # diff --git a/canary/cogs/utils/paginator.py b/canary/cogs/utils/paginator.py index 0e90f1ed0..5947d944d 100644 --- a/canary/cogs/utils/paginator.py +++ b/canary/cogs/utils/paginator.py @@ -1,4 +1,4 @@ -# Copyright (C) idoneam (2016-2022) +# Copyright (C) idoneam (2016-2023) # # This file is part of Canary # diff --git a/canary/cogs/utils/role_restoration.py b/canary/cogs/utils/role_restoration.py index ab6279693..5957d30db 100644 --- a/canary/cogs/utils/role_restoration.py +++ b/canary/cogs/utils/role_restoration.py @@ -1,4 +1,4 @@ -# Copyright (C) idoneam (2016-2022) +# Copyright (C) idoneam (2016-2023) # # This file is part of Canary # diff --git a/canary/config/config.py b/canary/config/config.py index 3e48a17fa..bcddb70ea 100644 --- a/canary/config/config.py +++ b/canary/config/config.py @@ -1,4 +1,4 @@ -# Copyright (C) idoneam (2016-2022) +# Copyright (C) idoneam (2016-2023) # # This file is part of Canary # diff --git a/canary/main.py b/canary/main.py index a0f6f7b88..358cd7d8a 100755 --- a/canary/main.py +++ b/canary/main.py @@ -1,6 +1,6 @@ #! /usr/bin/env python3 # -# Copyright (C) idoneam (2016-2022) +# Copyright (C) idoneam (2016-2023) # # This file is part of Canary # From 5b4781603908d7998cde11ab59372a0d2d05dabc Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Sat, 13 May 2023 14:13:10 -0400 Subject: [PATCH 090/127] chore: update more deps --- poetry.lock | 125 +++++++++++++++++++++++++++---------------------- pyproject.toml | 6 +-- 2 files changed, 73 insertions(+), 58 deletions(-) diff --git a/poetry.lock b/poetry.lock index d94686432..45b4de73c 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.4.2 and should not be changed by hand. +# This file is automatically @generated by Poetry and should not be changed by hand. [[package]] name = "aiohttp" @@ -60,18 +60,19 @@ speedups = ["aiodns", "brotlipy", "cchardet"] [[package]] name = "aiosqlite" -version = "0.17.0" +version = "0.19.0" description = "asyncio bridge to the standard sqlite3 module" category = "main" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" files = [ - {file = "aiosqlite-0.17.0-py3-none-any.whl", hash = "sha256:6c49dc6d3405929b1d08eeccc72306d3677503cc5e5e43771efc1e00232e8231"}, - {file = "aiosqlite-0.17.0.tar.gz", hash = "sha256:f0e6acc24bc4864149267ac82fb46dfb3be4455f99fe21df82609cc6e6baee51"}, + {file = "aiosqlite-0.19.0-py3-none-any.whl", hash = "sha256:edba222e03453e094a3ce605db1b970c4b3376264e56f32e2a4959f948d66a96"}, + {file = "aiosqlite-0.19.0.tar.gz", hash = "sha256:95ee77b91c8d2808bd08a59fbebf66270e9090c3d92ffbf260dc0db0b979577d"}, ] -[package.dependencies] -typing_extensions = ">=3.7.2" +[package.extras] +dev = ["aiounittest (==1.4.1)", "attribution (==1.6.2)", "black (==23.3.0)", "coverage[toml] (==7.2.3)", "flake8 (==5.0.4)", "flake8-bugbear (==23.3.12)", "flit (==3.7.1)", "mypy (==1.2.0)", "ufmt (==2.1.0)", "usort (==1.0.6)"] +docs = ["sphinx (==6.1.3)", "sphinx-mdinclude (==0.5.3)"] [[package]] name = "async-timeout" @@ -801,38 +802,38 @@ files = [ [[package]] name = "mypy" -version = "1.2.0" +version = "1.3.0" description = "Optional static typing for Python" category = "dev" optional = false python-versions = ">=3.7" files = [ - {file = "mypy-1.2.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:701189408b460a2ff42b984e6bd45c3f41f0ac9f5f58b8873bbedc511900086d"}, - {file = "mypy-1.2.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fe91be1c51c90e2afe6827601ca14353bbf3953f343c2129fa1e247d55fd95ba"}, - {file = "mypy-1.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8d26b513225ffd3eacece727f4387bdce6469192ef029ca9dd469940158bc89e"}, - {file = "mypy-1.2.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:3a2d219775a120581a0ae8ca392b31f238d452729adbcb6892fa89688cb8306a"}, - {file = "mypy-1.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:2e93a8a553e0394b26c4ca683923b85a69f7ccdc0139e6acd1354cc884fe0128"}, - {file = "mypy-1.2.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3efde4af6f2d3ccf58ae825495dbb8d74abd6d176ee686ce2ab19bd025273f41"}, - {file = "mypy-1.2.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:695c45cea7e8abb6f088a34a6034b1d273122e5530aeebb9c09626cea6dca4cb"}, - {file = "mypy-1.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d0e9464a0af6715852267bf29c9553e4555b61f5904a4fc538547a4d67617937"}, - {file = "mypy-1.2.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:8293a216e902ac12779eb7a08f2bc39ec6c878d7c6025aa59464e0c4c16f7eb9"}, - {file = "mypy-1.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:f46af8d162f3d470d8ffc997aaf7a269996d205f9d746124a179d3abe05ac602"}, - {file = "mypy-1.2.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:031fc69c9a7e12bcc5660b74122ed84b3f1c505e762cc4296884096c6d8ee140"}, - {file = "mypy-1.2.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:390bc685ec209ada4e9d35068ac6988c60160b2b703072d2850457b62499e336"}, - {file = "mypy-1.2.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:4b41412df69ec06ab141808d12e0bf2823717b1c363bd77b4c0820feaa37249e"}, - {file = "mypy-1.2.0-cp37-cp37m-win_amd64.whl", hash = "sha256:4e4a682b3f2489d218751981639cffc4e281d548f9d517addfd5a2917ac78119"}, - {file = "mypy-1.2.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:a197ad3a774f8e74f21e428f0de7f60ad26a8d23437b69638aac2764d1e06a6a"}, - {file = "mypy-1.2.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:c9a084bce1061e55cdc0493a2ad890375af359c766b8ac311ac8120d3a472950"}, - {file = "mypy-1.2.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eaeaa0888b7f3ccb7bcd40b50497ca30923dba14f385bde4af78fac713d6d6f6"}, - {file = "mypy-1.2.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:bea55fc25b96c53affab852ad94bf111a3083bc1d8b0c76a61dd101d8a388cf5"}, - {file = "mypy-1.2.0-cp38-cp38-win_amd64.whl", hash = "sha256:4c8d8c6b80aa4a1689f2a179d31d86ae1367ea4a12855cc13aa3ba24bb36b2d8"}, - {file = "mypy-1.2.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:70894c5345bea98321a2fe84df35f43ee7bb0feec117a71420c60459fc3e1eed"}, - {file = "mypy-1.2.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4a99fe1768925e4a139aace8f3fb66db3576ee1c30b9c0f70f744ead7e329c9f"}, - {file = "mypy-1.2.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:023fe9e618182ca6317ae89833ba422c411469156b690fde6a315ad10695a521"}, - {file = "mypy-1.2.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:4d19f1a239d59f10fdc31263d48b7937c585810288376671eaf75380b074f238"}, - {file = "mypy-1.2.0-cp39-cp39-win_amd64.whl", hash = "sha256:2de7babe398cb7a85ac7f1fd5c42f396c215ab3eff731b4d761d68d0f6a80f48"}, - {file = "mypy-1.2.0-py3-none-any.whl", hash = "sha256:d8e9187bfcd5ffedbe87403195e1fc340189a68463903c39e2b63307c9fa0394"}, - {file = "mypy-1.2.0.tar.gz", hash = "sha256:f70a40410d774ae23fcb4afbbeca652905a04de7948eaf0b1789c8d1426b72d1"}, + {file = "mypy-1.3.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c1eb485cea53f4f5284e5baf92902cd0088b24984f4209e25981cc359d64448d"}, + {file = "mypy-1.3.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:4c99c3ecf223cf2952638da9cd82793d8f3c0c5fa8b6ae2b2d9ed1e1ff51ba85"}, + {file = "mypy-1.3.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:550a8b3a19bb6589679a7c3c31f64312e7ff482a816c96e0cecec9ad3a7564dd"}, + {file = "mypy-1.3.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:cbc07246253b9e3d7d74c9ff948cd0fd7a71afcc2b77c7f0a59c26e9395cb152"}, + {file = "mypy-1.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:a22435632710a4fcf8acf86cbd0d69f68ac389a3892cb23fbad176d1cddaf228"}, + {file = "mypy-1.3.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6e33bb8b2613614a33dff70565f4c803f889ebd2f859466e42b46e1df76018dd"}, + {file = "mypy-1.3.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7d23370d2a6b7a71dc65d1266f9a34e4cde9e8e21511322415db4b26f46f6b8c"}, + {file = "mypy-1.3.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:658fe7b674769a0770d4b26cb4d6f005e88a442fe82446f020be8e5f5efb2fae"}, + {file = "mypy-1.3.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:6e42d29e324cdda61daaec2336c42512e59c7c375340bd202efa1fe0f7b8f8ca"}, + {file = "mypy-1.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:d0b6c62206e04061e27009481cb0ec966f7d6172b5b936f3ead3d74f29fe3dcf"}, + {file = "mypy-1.3.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:76ec771e2342f1b558c36d49900dfe81d140361dd0d2df6cd71b3db1be155409"}, + {file = "mypy-1.3.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ebc95f8386314272bbc817026f8ce8f4f0d2ef7ae44f947c4664efac9adec929"}, + {file = "mypy-1.3.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:faff86aa10c1aa4a10e1a301de160f3d8fc8703b88c7e98de46b531ff1276a9a"}, + {file = "mypy-1.3.0-cp37-cp37m-win_amd64.whl", hash = "sha256:8c5979d0deb27e0f4479bee18ea0f83732a893e81b78e62e2dda3e7e518c92ee"}, + {file = "mypy-1.3.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:c5d2cc54175bab47011b09688b418db71403aefad07cbcd62d44010543fc143f"}, + {file = "mypy-1.3.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:87df44954c31d86df96c8bd6e80dfcd773473e877ac6176a8e29898bfb3501cb"}, + {file = "mypy-1.3.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:473117e310febe632ddf10e745a355714e771ffe534f06db40702775056614c4"}, + {file = "mypy-1.3.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:74bc9b6e0e79808bf8678d7678b2ae3736ea72d56eede3820bd3849823e7f305"}, + {file = "mypy-1.3.0-cp38-cp38-win_amd64.whl", hash = "sha256:44797d031a41516fcf5cbfa652265bb994e53e51994c1bd649ffcd0c3a7eccbf"}, + {file = "mypy-1.3.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:ddae0f39ca146972ff6bb4399f3b2943884a774b8771ea0a8f50e971f5ea5ba8"}, + {file = "mypy-1.3.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1c4c42c60a8103ead4c1c060ac3cdd3ff01e18fddce6f1016e08939647a0e703"}, + {file = "mypy-1.3.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e86c2c6852f62f8f2b24cb7a613ebe8e0c7dc1402c61d36a609174f63e0ff017"}, + {file = "mypy-1.3.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:f9dca1e257d4cc129517779226753dbefb4f2266c4eaad610fc15c6a7e14283e"}, + {file = "mypy-1.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:95d8d31a7713510685b05fbb18d6ac287a56c8f6554d88c19e73f724a445448a"}, + {file = "mypy-1.3.0-py3-none-any.whl", hash = "sha256:a8763e72d5d9574d45ce5881962bc8e9046bf7b375b0abf031f3e6811732a897"}, + {file = "mypy-1.3.0.tar.gz", hash = "sha256:e1f4d16e296f5135624b34e8fb741eb0eadedca90862405b1f1fde2040b9bd11"}, ] [package.dependencies] @@ -1568,34 +1569,48 @@ zstd = ["zstandard (>=0.18.0)"] [[package]] name = "uvloop" -version = "0.16.0" +version = "0.17.0" description = "Fast implementation of asyncio event loop on top of libuv" category = "main" optional = false python-versions = ">=3.7" files = [ - {file = "uvloop-0.16.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:6224f1401025b748ffecb7a6e2652b17768f30b1a6a3f7b44660e5b5b690b12d"}, - {file = "uvloop-0.16.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:30ba9dcbd0965f5c812b7c2112a1ddf60cf904c1c160f398e7eed3a6b82dcd9c"}, - {file = "uvloop-0.16.0-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:bd53f7f5db562f37cd64a3af5012df8cac2c464c97e732ed556800129505bd64"}, - {file = "uvloop-0.16.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:772206116b9b57cd625c8a88f2413df2fcfd0b496eb188b82a43bed7af2c2ec9"}, - {file = "uvloop-0.16.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b572256409f194521a9895aef274cea88731d14732343da3ecdb175228881638"}, - {file = "uvloop-0.16.0-cp37-cp37m-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:04ff57aa137230d8cc968f03481176041ae789308b4d5079118331ab01112450"}, - {file = "uvloop-0.16.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3a19828c4f15687675ea912cc28bbcb48e9bb907c801873bd1519b96b04fb805"}, - {file = "uvloop-0.16.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:e814ac2c6f9daf4c36eb8e85266859f42174a4ff0d71b99405ed559257750382"}, - {file = "uvloop-0.16.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:bd8f42ea1ea8f4e84d265769089964ddda95eb2bb38b5cbe26712b0616c3edee"}, - {file = "uvloop-0.16.0-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:647e481940379eebd314c00440314c81ea547aa636056f554d491e40503c8464"}, - {file = "uvloop-0.16.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8e0d26fa5875d43ddbb0d9d79a447d2ace4180d9e3239788208527c4784f7cab"}, - {file = "uvloop-0.16.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:6ccd57ae8db17d677e9e06192e9c9ec4bd2066b77790f9aa7dede2cc4008ee8f"}, - {file = "uvloop-0.16.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:089b4834fd299d82d83a25e3335372f12117a7d38525217c2258e9b9f4578897"}, - {file = "uvloop-0.16.0-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:98d117332cc9e5ea8dfdc2b28b0a23f60370d02e1395f88f40d1effd2cb86c4f"}, - {file = "uvloop-0.16.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1e5f2e2ff51aefe6c19ee98af12b4ae61f5be456cd24396953244a30880ad861"}, - {file = "uvloop-0.16.0.tar.gz", hash = "sha256:f74bc20c7b67d1c27c72601c78cf95be99d5c2cdd4514502b4f3eb0933ff1228"}, + {file = "uvloop-0.17.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:ce9f61938d7155f79d3cb2ffa663147d4a76d16e08f65e2c66b77bd41b356718"}, + {file = "uvloop-0.17.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:68532f4349fd3900b839f588972b3392ee56042e440dd5873dfbbcd2cc67617c"}, + {file = "uvloop-0.17.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0949caf774b9fcefc7c5756bacbbbd3fc4c05a6b7eebc7c7ad6f825b23998d6d"}, + {file = "uvloop-0.17.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ff3d00b70ce95adce264462c930fbaecb29718ba6563db354608f37e49e09024"}, + {file = "uvloop-0.17.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:a5abddb3558d3f0a78949c750644a67be31e47936042d4f6c888dd6f3c95f4aa"}, + {file = "uvloop-0.17.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:8efcadc5a0003d3a6e887ccc1fb44dec25594f117a94e3127954c05cf144d811"}, + {file = "uvloop-0.17.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:3378eb62c63bf336ae2070599e49089005771cc651c8769aaad72d1bd9385a7c"}, + {file = "uvloop-0.17.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6aafa5a78b9e62493539456f8b646f85abc7093dd997f4976bb105537cf2635e"}, + {file = "uvloop-0.17.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c686a47d57ca910a2572fddfe9912819880b8765e2f01dc0dd12a9bf8573e539"}, + {file = "uvloop-0.17.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:864e1197139d651a76c81757db5eb199db8866e13acb0dfe96e6fc5d1cf45fc4"}, + {file = "uvloop-0.17.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:2a6149e1defac0faf505406259561bc14b034cdf1d4711a3ddcdfbaa8d825a05"}, + {file = "uvloop-0.17.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:6708f30db9117f115eadc4f125c2a10c1a50d711461699a0cbfaa45b9a78e376"}, + {file = "uvloop-0.17.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:23609ca361a7fc587031429fa25ad2ed7242941adec948f9d10c045bfecab06b"}, + {file = "uvloop-0.17.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2deae0b0fb00a6af41fe60a675cec079615b01d68beb4cc7b722424406b126a8"}, + {file = "uvloop-0.17.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:45cea33b208971e87a31c17622e4b440cac231766ec11e5d22c76fab3bf9df62"}, + {file = "uvloop-0.17.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:9b09e0f0ac29eee0451d71798878eae5a4e6a91aa275e114037b27f7db72702d"}, + {file = "uvloop-0.17.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:dbbaf9da2ee98ee2531e0c780455f2841e4675ff580ecf93fe5c48fe733b5667"}, + {file = "uvloop-0.17.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:a4aee22ece20958888eedbad20e4dbb03c37533e010fb824161b4f05e641f738"}, + {file = "uvloop-0.17.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:307958f9fc5c8bb01fad752d1345168c0abc5d62c1b72a4a8c6c06f042b45b20"}, + {file = "uvloop-0.17.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3ebeeec6a6641d0adb2ea71dcfb76017602ee2bfd8213e3fcc18d8f699c5104f"}, + {file = "uvloop-0.17.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1436c8673c1563422213ac6907789ecb2b070f5939b9cbff9ef7113f2b531595"}, + {file = "uvloop-0.17.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:8887d675a64cfc59f4ecd34382e5b4f0ef4ae1da37ed665adba0c2badf0d6578"}, + {file = "uvloop-0.17.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:3db8de10ed684995a7f34a001f15b374c230f7655ae840964d51496e2f8a8474"}, + {file = "uvloop-0.17.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:7d37dccc7ae63e61f7b96ee2e19c40f153ba6ce730d8ba4d3b4e9738c1dccc1b"}, + {file = "uvloop-0.17.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:cbbe908fda687e39afd6ea2a2f14c2c3e43f2ca88e3a11964b297822358d0e6c"}, + {file = "uvloop-0.17.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3d97672dc709fa4447ab83276f344a165075fd9f366a97b712bdd3fee05efae8"}, + {file = "uvloop-0.17.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f1e507c9ee39c61bfddd79714e4f85900656db1aec4d40c6de55648e85c2799c"}, + {file = "uvloop-0.17.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:c092a2c1e736086d59ac8e41f9c98f26bbf9b9222a76f21af9dfe949b99b2eb9"}, + {file = "uvloop-0.17.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:30babd84706115626ea78ea5dbc7dd8d0d01a2e9f9b306d24ca4ed5796c66ded"}, + {file = "uvloop-0.17.0.tar.gz", hash = "sha256:0ddf6baf9cf11a1a22c71487f39f15b2cf78eb5bde7e5b45fbb99e8a9d91b9e1"}, ] [package.extras] -dev = ["Cython (>=0.29.24,<0.30.0)", "Sphinx (>=4.1.2,<4.2.0)", "aiohttp", "flake8 (>=3.9.2,<3.10.0)", "mypy (>=0.800)", "psutil", "pyOpenSSL (>=19.0.0,<19.1.0)", "pycodestyle (>=2.7.0,<2.8.0)", "pytest (>=3.6.0)", "sphinx-rtd-theme (>=0.5.2,<0.6.0)", "sphinxcontrib-asyncio (>=0.3.0,<0.4.0)"] +dev = ["Cython (>=0.29.32,<0.30.0)", "Sphinx (>=4.1.2,<4.2.0)", "aiohttp", "flake8 (>=3.9.2,<3.10.0)", "mypy (>=0.800)", "psutil", "pyOpenSSL (>=22.0.0,<22.1.0)", "pycodestyle (>=2.7.0,<2.8.0)", "pytest (>=3.6.0)", "sphinx-rtd-theme (>=0.5.2,<0.6.0)", "sphinxcontrib-asyncio (>=0.3.0,<0.4.0)"] docs = ["Sphinx (>=4.1.2,<4.2.0)", "sphinx-rtd-theme (>=0.5.2,<0.6.0)", "sphinxcontrib-asyncio (>=0.3.0,<0.4.0)"] -test = ["aiohttp", "flake8 (>=3.9.2,<3.10.0)", "mypy (>=0.800)", "psutil", "pyOpenSSL (>=19.0.0,<19.1.0)", "pycodestyle (>=2.7.0,<2.8.0)"] +test = ["Cython (>=0.29.32,<0.30.0)", "aiohttp", "flake8 (>=3.9.2,<3.10.0)", "mypy (>=0.800)", "psutil", "pyOpenSSL (>=22.0.0,<22.1.0)", "pycodestyle (>=2.7.0,<2.8.0)"] [[package]] name = "websockets" @@ -1784,5 +1799,5 @@ websockets = "*" [metadata] lock-version = "2.0" -python-versions = "~3.10.0" -content-hash = "7d05f16c0318f87b781ad5a1552b41d35d5792cff2ba5b0bed35e74acb597867" +python-versions = ">=3.10.0,<3.12" +content-hash = "4e6a5461b0843f16c1f74a1acf596fa8af6dc81dd9dcbb2aa3ba7e96ba8c821f" diff --git a/pyproject.toml b/pyproject.toml index 780deb81c..1ee6b4c2f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -30,9 +30,9 @@ regex = "^2023.5.5" googletrans = "==4.0.0rc1" yt-dlp = "^2021.12.27" Pillow = "^8.3.2" -uvloop = {version="0.16.0", markers = "sys_platform == 'linux' or sys_platform == 'darwin'"} +uvloop = {version="~0.17.0", markers = "sys_platform == 'linux' or sys_platform == 'darwin'"} bidict = "^0.22.0" -aiosqlite = "^0.17.0" +aiosqlite = "^0.19.0" lxml = "^4.9.1" python-dotenv = "^0.21.0" pydantic = "^1.10.2" @@ -40,7 +40,7 @@ pydantic = "^1.10.2" [tool.poetry.dev-dependencies] pytest = "^7.3.1" black = "^23.3.0" -mypy = "~1.2.0" +mypy = "~1.3.0" types-beautifulsoup4 = "^4.11.5" types-regex = "^2022.8.17.0" types-requests = "^2.28.9" From a2da07fcdd5ffdc84ead6f6e937c306151bf8721 Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Sat, 13 May 2023 14:22:54 -0400 Subject: [PATCH 091/127] chore: update pillow --- poetry.lock | 117 ++++++++++++++++++++++++++++++------------------- pyproject.toml | 2 +- 2 files changed, 74 insertions(+), 45 deletions(-) diff --git a/poetry.lock b/poetry.lock index 45b4de73c..731ba298f 100644 --- a/poetry.lock +++ b/poetry.lock @@ -948,55 +948,84 @@ files = [ [[package]] name = "pillow" -version = "8.4.0" +version = "9.5.0" description = "Python Imaging Library (Fork)" category = "main" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" files = [ - {file = "Pillow-8.4.0-cp310-cp310-macosx_10_10_universal2.whl", hash = "sha256:81f8d5c81e483a9442d72d182e1fb6dcb9723f289a57e8030811bac9ea3fef8d"}, - {file = "Pillow-8.4.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:3f97cfb1e5a392d75dd8b9fd274d205404729923840ca94ca45a0af57e13dbe6"}, - {file = "Pillow-8.4.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eb9fc393f3c61f9054e1ed26e6fe912c7321af2f41ff49d3f83d05bacf22cc78"}, - {file = "Pillow-8.4.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d82cdb63100ef5eedb8391732375e6d05993b765f72cb34311fab92103314649"}, - {file = "Pillow-8.4.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:62cc1afda735a8d109007164714e73771b499768b9bb5afcbbee9d0ff374b43f"}, - {file = "Pillow-8.4.0-cp310-cp310-win32.whl", hash = "sha256:e3dacecfbeec9a33e932f00c6cd7996e62f53ad46fbe677577394aaa90ee419a"}, - {file = "Pillow-8.4.0-cp310-cp310-win_amd64.whl", hash = "sha256:620582db2a85b2df5f8a82ddeb52116560d7e5e6b055095f04ad828d1b0baa39"}, - {file = "Pillow-8.4.0-cp36-cp36m-macosx_10_10_x86_64.whl", hash = "sha256:1bc723b434fbc4ab50bb68e11e93ce5fb69866ad621e3c2c9bdb0cd70e345f55"}, - {file = "Pillow-8.4.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:72cbcfd54df6caf85cc35264c77ede902452d6df41166010262374155947460c"}, - {file = "Pillow-8.4.0-cp36-cp36m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:70ad9e5c6cb9b8487280a02c0ad8a51581dcbbe8484ce058477692a27c151c0a"}, - {file = "Pillow-8.4.0-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:25a49dc2e2f74e65efaa32b153527fc5ac98508d502fa46e74fa4fd678ed6645"}, - {file = "Pillow-8.4.0-cp36-cp36m-win32.whl", hash = "sha256:93ce9e955cc95959df98505e4608ad98281fff037350d8c2671c9aa86bcf10a9"}, - {file = "Pillow-8.4.0-cp36-cp36m-win_amd64.whl", hash = "sha256:2e4440b8f00f504ee4b53fe30f4e381aae30b0568193be305256b1462216feff"}, - {file = "Pillow-8.4.0-cp37-cp37m-macosx_10_10_x86_64.whl", hash = "sha256:8c803ac3c28bbc53763e6825746f05cc407b20e4a69d0122e526a582e3b5e153"}, - {file = "Pillow-8.4.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c8a17b5d948f4ceeceb66384727dde11b240736fddeda54ca740b9b8b1556b29"}, - {file = "Pillow-8.4.0-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1394a6ad5abc838c5cd8a92c5a07535648cdf6d09e8e2d6df916dfa9ea86ead8"}, - {file = "Pillow-8.4.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:792e5c12376594bfcb986ebf3855aa4b7c225754e9a9521298e460e92fb4a488"}, - {file = "Pillow-8.4.0-cp37-cp37m-win32.whl", hash = "sha256:d99ec152570e4196772e7a8e4ba5320d2d27bf22fdf11743dd882936ed64305b"}, - {file = "Pillow-8.4.0-cp37-cp37m-win_amd64.whl", hash = "sha256:7b7017b61bbcdd7f6363aeceb881e23c46583739cb69a3ab39cb384f6ec82e5b"}, - {file = "Pillow-8.4.0-cp38-cp38-macosx_10_10_x86_64.whl", hash = "sha256:d89363f02658e253dbd171f7c3716a5d340a24ee82d38aab9183f7fdf0cdca49"}, - {file = "Pillow-8.4.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:0a0956fdc5defc34462bb1c765ee88d933239f9a94bc37d132004775241a7585"}, - {file = "Pillow-8.4.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5b7bb9de00197fb4261825c15551adf7605cf14a80badf1761d61e59da347779"}, - {file = "Pillow-8.4.0-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:72b9e656e340447f827885b8d7a15fc8c4e68d410dc2297ef6787eec0f0ea409"}, - {file = "Pillow-8.4.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a5a4532a12314149d8b4e4ad8ff09dde7427731fcfa5917ff16d0291f13609df"}, - {file = "Pillow-8.4.0-cp38-cp38-win32.whl", hash = "sha256:82aafa8d5eb68c8463b6e9baeb4f19043bb31fefc03eb7b216b51e6a9981ae09"}, - {file = "Pillow-8.4.0-cp38-cp38-win_amd64.whl", hash = "sha256:066f3999cb3b070a95c3652712cffa1a748cd02d60ad7b4e485c3748a04d9d76"}, - {file = "Pillow-8.4.0-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:5503c86916d27c2e101b7f71c2ae2cddba01a2cf55b8395b0255fd33fa4d1f1a"}, - {file = "Pillow-8.4.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4acc0985ddf39d1bc969a9220b51d94ed51695d455c228d8ac29fcdb25810e6e"}, - {file = "Pillow-8.4.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0b052a619a8bfcf26bd8b3f48f45283f9e977890263e4571f2393ed8898d331b"}, - {file = "Pillow-8.4.0-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:493cb4e415f44cd601fcec11c99836f707bb714ab03f5ed46ac25713baf0ff20"}, - {file = "Pillow-8.4.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b8831cb7332eda5dc89b21a7bce7ef6ad305548820595033a4b03cf3091235ed"}, - {file = "Pillow-8.4.0-cp39-cp39-win32.whl", hash = "sha256:5e9ac5f66616b87d4da618a20ab0a38324dbe88d8a39b55be8964eb520021e02"}, - {file = "Pillow-8.4.0-cp39-cp39-win_amd64.whl", hash = "sha256:3eb1ce5f65908556c2d8685a8f0a6e989d887ec4057326f6c22b24e8a172c66b"}, - {file = "Pillow-8.4.0-pp36-pypy36_pp73-macosx_10_10_x86_64.whl", hash = "sha256:ddc4d832a0f0b4c52fff973a0d44b6c99839a9d016fe4e6a1cb8f3eea96479c2"}, - {file = "Pillow-8.4.0-pp36-pypy36_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9a3e5ddc44c14042f0844b8cf7d2cd455f6cc80fd7f5eefbe657292cf601d9ad"}, - {file = "Pillow-8.4.0-pp36-pypy36_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c70e94281588ef053ae8998039610dbd71bc509e4acbc77ab59d7d2937b10698"}, - {file = "Pillow-8.4.0-pp37-pypy37_pp73-macosx_10_10_x86_64.whl", hash = "sha256:3862b7256046fcd950618ed22d1d60b842e3a40a48236a5498746f21189afbbc"}, - {file = "Pillow-8.4.0-pp37-pypy37_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a4901622493f88b1a29bd30ec1a2f683782e57c3c16a2dbc7f2595ba01f639df"}, - {file = "Pillow-8.4.0-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:84c471a734240653a0ec91dec0996696eea227eafe72a33bd06c92697728046b"}, - {file = "Pillow-8.4.0-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:244cf3b97802c34c41905d22810846802a3329ddcb93ccc432870243211c79fc"}, - {file = "Pillow-8.4.0.tar.gz", hash = "sha256:b8e2f83c56e141920c39464b852de3719dfbfb6e3c99a2d8da0edf4fb33176ed"}, + {file = "Pillow-9.5.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:ace6ca218308447b9077c14ea4ef381ba0b67ee78d64046b3f19cf4e1139ad16"}, + {file = "Pillow-9.5.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d3d403753c9d5adc04d4694d35cf0391f0f3d57c8e0030aac09d7678fa8030aa"}, + {file = "Pillow-9.5.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5ba1b81ee69573fe7124881762bb4cd2e4b6ed9dd28c9c60a632902fe8db8b38"}, + {file = "Pillow-9.5.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fe7e1c262d3392afcf5071df9afa574544f28eac825284596ac6db56e6d11062"}, + {file = "Pillow-9.5.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f36397bf3f7d7c6a3abdea815ecf6fd14e7fcd4418ab24bae01008d8d8ca15e"}, + {file = "Pillow-9.5.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:252a03f1bdddce077eff2354c3861bf437c892fb1832f75ce813ee94347aa9b5"}, + {file = "Pillow-9.5.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:85ec677246533e27770b0de5cf0f9d6e4ec0c212a1f89dfc941b64b21226009d"}, + {file = "Pillow-9.5.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:b416f03d37d27290cb93597335a2f85ed446731200705b22bb927405320de903"}, + {file = "Pillow-9.5.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:1781a624c229cb35a2ac31cc4a77e28cafc8900733a864870c49bfeedacd106a"}, + {file = "Pillow-9.5.0-cp310-cp310-win32.whl", hash = "sha256:8507eda3cd0608a1f94f58c64817e83ec12fa93a9436938b191b80d9e4c0fc44"}, + {file = "Pillow-9.5.0-cp310-cp310-win_amd64.whl", hash = "sha256:d3c6b54e304c60c4181da1c9dadf83e4a54fd266a99c70ba646a9baa626819eb"}, + {file = "Pillow-9.5.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:7ec6f6ce99dab90b52da21cf0dc519e21095e332ff3b399a357c187b1a5eee32"}, + {file = "Pillow-9.5.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:560737e70cb9c6255d6dcba3de6578a9e2ec4b573659943a5e7e4af13f298f5c"}, + {file = "Pillow-9.5.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:96e88745a55b88a7c64fa49bceff363a1a27d9a64e04019c2281049444a571e3"}, + {file = "Pillow-9.5.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d9c206c29b46cfd343ea7cdfe1232443072bbb270d6a46f59c259460db76779a"}, + {file = "Pillow-9.5.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cfcc2c53c06f2ccb8976fb5c71d448bdd0a07d26d8e07e321c103416444c7ad1"}, + {file = "Pillow-9.5.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:a0f9bb6c80e6efcde93ffc51256d5cfb2155ff8f78292f074f60f9e70b942d99"}, + {file = "Pillow-9.5.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:8d935f924bbab8f0a9a28404422da8af4904e36d5c33fc6f677e4c4485515625"}, + {file = "Pillow-9.5.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:fed1e1cf6a42577953abbe8e6cf2fe2f566daebde7c34724ec8803c4c0cda579"}, + {file = "Pillow-9.5.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:c1170d6b195555644f0616fd6ed929dfcf6333b8675fcca044ae5ab110ded296"}, + {file = "Pillow-9.5.0-cp311-cp311-win32.whl", hash = "sha256:54f7102ad31a3de5666827526e248c3530b3a33539dbda27c6843d19d72644ec"}, + {file = "Pillow-9.5.0-cp311-cp311-win_amd64.whl", hash = "sha256:cfa4561277f677ecf651e2b22dc43e8f5368b74a25a8f7d1d4a3a243e573f2d4"}, + {file = "Pillow-9.5.0-cp311-cp311-win_arm64.whl", hash = "sha256:965e4a05ef364e7b973dd17fc765f42233415974d773e82144c9bbaaaea5d089"}, + {file = "Pillow-9.5.0-cp312-cp312-win32.whl", hash = "sha256:22baf0c3cf0c7f26e82d6e1adf118027afb325e703922c8dfc1d5d0156bb2eeb"}, + {file = "Pillow-9.5.0-cp312-cp312-win_amd64.whl", hash = "sha256:432b975c009cf649420615388561c0ce7cc31ce9b2e374db659ee4f7d57a1f8b"}, + {file = "Pillow-9.5.0-cp37-cp37m-macosx_10_10_x86_64.whl", hash = "sha256:5d4ebf8e1db4441a55c509c4baa7a0587a0210f7cd25fcfe74dbbce7a4bd1906"}, + {file = "Pillow-9.5.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:375f6e5ee9620a271acb6820b3d1e94ffa8e741c0601db4c0c4d3cb0a9c224bf"}, + {file = "Pillow-9.5.0-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:99eb6cafb6ba90e436684e08dad8be1637efb71c4f2180ee6b8f940739406e78"}, + {file = "Pillow-9.5.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2dfaaf10b6172697b9bceb9a3bd7b951819d1ca339a5ef294d1f1ac6d7f63270"}, + {file = "Pillow-9.5.0-cp37-cp37m-manylinux_2_28_aarch64.whl", hash = "sha256:763782b2e03e45e2c77d7779875f4432e25121ef002a41829d8868700d119392"}, + {file = "Pillow-9.5.0-cp37-cp37m-manylinux_2_28_x86_64.whl", hash = "sha256:35f6e77122a0c0762268216315bf239cf52b88865bba522999dc38f1c52b9b47"}, + {file = "Pillow-9.5.0-cp37-cp37m-win32.whl", hash = "sha256:aca1c196f407ec7cf04dcbb15d19a43c507a81f7ffc45b690899d6a76ac9fda7"}, + {file = "Pillow-9.5.0-cp37-cp37m-win_amd64.whl", hash = "sha256:322724c0032af6692456cd6ed554bb85f8149214d97398bb80613b04e33769f6"}, + {file = "Pillow-9.5.0-cp38-cp38-macosx_10_10_x86_64.whl", hash = "sha256:a0aa9417994d91301056f3d0038af1199eb7adc86e646a36b9e050b06f526597"}, + {file = "Pillow-9.5.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:f8286396b351785801a976b1e85ea88e937712ee2c3ac653710a4a57a8da5d9c"}, + {file = "Pillow-9.5.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c830a02caeb789633863b466b9de10c015bded434deb3ec87c768e53752ad22a"}, + {file = "Pillow-9.5.0-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fbd359831c1657d69bb81f0db962905ee05e5e9451913b18b831febfe0519082"}, + {file = "Pillow-9.5.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f8fc330c3370a81bbf3f88557097d1ea26cd8b019d6433aa59f71195f5ddebbf"}, + {file = "Pillow-9.5.0-cp38-cp38-manylinux_2_28_aarch64.whl", hash = "sha256:7002d0797a3e4193c7cdee3198d7c14f92c0836d6b4a3f3046a64bd1ce8df2bf"}, + {file = "Pillow-9.5.0-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:229e2c79c00e85989a34b5981a2b67aa079fd08c903f0aaead522a1d68d79e51"}, + {file = "Pillow-9.5.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:9adf58f5d64e474bed00d69bcd86ec4bcaa4123bfa70a65ce72e424bfb88ed96"}, + {file = "Pillow-9.5.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:662da1f3f89a302cc22faa9f14a262c2e3951f9dbc9617609a47521c69dd9f8f"}, + {file = "Pillow-9.5.0-cp38-cp38-win32.whl", hash = "sha256:6608ff3bf781eee0cd14d0901a2b9cc3d3834516532e3bd673a0a204dc8615fc"}, + {file = "Pillow-9.5.0-cp38-cp38-win_amd64.whl", hash = "sha256:e49eb4e95ff6fd7c0c402508894b1ef0e01b99a44320ba7d8ecbabefddcc5569"}, + {file = "Pillow-9.5.0-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:482877592e927fd263028c105b36272398e3e1be3269efda09f6ba21fd83ec66"}, + {file = "Pillow-9.5.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3ded42b9ad70e5f1754fb7c2e2d6465a9c842e41d178f262e08b8c85ed8a1d8e"}, + {file = "Pillow-9.5.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c446d2245ba29820d405315083d55299a796695d747efceb5717a8b450324115"}, + {file = "Pillow-9.5.0-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8aca1152d93dcc27dc55395604dcfc55bed5f25ef4c98716a928bacba90d33a3"}, + {file = "Pillow-9.5.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:608488bdcbdb4ba7837461442b90ea6f3079397ddc968c31265c1e056964f1ef"}, + {file = "Pillow-9.5.0-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:60037a8db8750e474af7ffc9faa9b5859e6c6d0a50e55c45576bf28be7419705"}, + {file = "Pillow-9.5.0-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:07999f5834bdc404c442146942a2ecadd1cb6292f5229f4ed3b31e0a108746b1"}, + {file = "Pillow-9.5.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:a127ae76092974abfbfa38ca2d12cbeddcdeac0fb71f9627cc1135bedaf9d51a"}, + {file = "Pillow-9.5.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:489f8389261e5ed43ac8ff7b453162af39c3e8abd730af8363587ba64bb2e865"}, + {file = "Pillow-9.5.0-cp39-cp39-win32.whl", hash = "sha256:9b1af95c3a967bf1da94f253e56b6286b50af23392a886720f563c547e48e964"}, + {file = "Pillow-9.5.0-cp39-cp39-win_amd64.whl", hash = "sha256:77165c4a5e7d5a284f10a6efaa39a0ae8ba839da344f20b111d62cc932fa4e5d"}, + {file = "Pillow-9.5.0-pp38-pypy38_pp73-macosx_10_10_x86_64.whl", hash = "sha256:833b86a98e0ede388fa29363159c9b1a294b0905b5128baf01db683672f230f5"}, + {file = "Pillow-9.5.0-pp38-pypy38_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:aaf305d6d40bd9632198c766fb64f0c1a83ca5b667f16c1e79e1661ab5060140"}, + {file = "Pillow-9.5.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0852ddb76d85f127c135b6dd1f0bb88dbb9ee990d2cd9aa9e28526c93e794fba"}, + {file = "Pillow-9.5.0-pp38-pypy38_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:91ec6fe47b5eb5a9968c79ad9ed78c342b1f97a091677ba0e012701add857829"}, + {file = "Pillow-9.5.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:cb841572862f629b99725ebaec3287fc6d275be9b14443ea746c1dd325053cbd"}, + {file = "Pillow-9.5.0-pp39-pypy39_pp73-macosx_10_10_x86_64.whl", hash = "sha256:c380b27d041209b849ed246b111b7c166ba36d7933ec6e41175fd15ab9eb1572"}, + {file = "Pillow-9.5.0-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7c9af5a3b406a50e313467e3565fc99929717f780164fe6fbb7704edba0cebbe"}, + {file = "Pillow-9.5.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5671583eab84af046a397d6d0ba25343c00cd50bce03787948e0fff01d4fd9b1"}, + {file = "Pillow-9.5.0-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:84a6f19ce086c1bf894644b43cd129702f781ba5751ca8572f08aa40ef0ab7b7"}, + {file = "Pillow-9.5.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:1e7723bd90ef94eda669a3c2c19d549874dd5badaeefabefd26053304abe5799"}, + {file = "Pillow-9.5.0.tar.gz", hash = "sha256:bf548479d336726d7a0eceb6e767e179fbde37833ae42794602631a070d630f1"}, ] +[package.extras] +docs = ["furo", "olefile", "sphinx (>=2.4)", "sphinx-copybutton", "sphinx-inline-tabs", "sphinx-removed-in", "sphinxext-opengraph"] +tests = ["check-manifest", "coverage", "defusedxml", "markdown2", "olefile", "packaging", "pyroma", "pytest", "pytest-cov", "pytest-timeout"] + [[package]] name = "platformdirs" version = "3.5.1" @@ -1800,4 +1829,4 @@ websockets = "*" [metadata] lock-version = "2.0" python-versions = ">=3.10.0,<3.12" -content-hash = "4e6a5461b0843f16c1f74a1acf596fa8af6dc81dd9dcbb2aa3ba7e96ba8c821f" +content-hash = "502a94f21c3c3a4d81942488c5aa9fe26a305bb0bba55155e2b5a0af83ac736a" diff --git a/pyproject.toml b/pyproject.toml index 1ee6b4c2f..32b47ae83 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -29,7 +29,7 @@ feedparser = "^6.0.8" regex = "^2023.5.5" googletrans = "==4.0.0rc1" yt-dlp = "^2021.12.27" -Pillow = "^8.3.2" +Pillow = "^9.5.0" uvloop = {version="~0.17.0", markers = "sys_platform == 'linux' or sys_platform == 'darwin'"} bidict = "^0.22.0" aiosqlite = "^0.19.0" From 272049986f94eedb9e775f5adc85d6649e468a5e Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Sat, 13 May 2023 14:25:36 -0400 Subject: [PATCH 092/127] lint --- canary/cogs/helpers.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/canary/cogs/helpers.py b/canary/cogs/helpers.py index 059a4028a..2ae52d362 100644 --- a/canary/cogs/helpers.py +++ b/canary/cogs/helpers.py @@ -878,13 +878,15 @@ async def spoilerize(self, ctx: commands.Context, *args): if limit_reached: await ctx.send( - "Could not spoilerize all messages: Max 30 at the same time (this message will be deleted in 15 seconds).", + "Could not spoilerize all messages: Max 30 at the same time (this message will be deleted in 15 " + "seconds).", delete_after=15, ) else: if moderator: await ctx.send( - f"Completed spoilerization of {len(messages)} messages (this message will be deleted in 15 seconds).", + f"Completed spoilerization of {len(messages)} messages (this message will be deleted in 15 " + f"seconds).", delete_after=15, ) else: From 0f1213839aed7f65bdac8945e136a708579d3180 Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Sat, 13 May 2023 14:27:52 -0400 Subject: [PATCH 093/127] lint --- .github/workflows/formatting_check.yml | 3 +-- canary/cogs/banner.py | 1 - canary/cogs/currency.py | 10 ++++------ canary/cogs/games.py | 1 - canary/cogs/helpers.py | 5 ++--- canary/cogs/music.py | 1 - canary/cogs/utils/image_helpers.py | 1 - canary/cogs/utils/paginator.py | 4 ++-- pyproject.toml | 1 - 9 files changed, 9 insertions(+), 18 deletions(-) diff --git a/.github/workflows/formatting_check.yml b/.github/workflows/formatting_check.yml index 655f91fa9..d2e7f9855 100644 --- a/.github/workflows/formatting_check.yml +++ b/.github/workflows/formatting_check.yml @@ -13,5 +13,4 @@ jobs: - uses: actions/setup-python@v4 - uses: psf/black@stable with: - options: "--diff --check -t py311 --fast" - + options: "--diff --check -t py311" diff --git a/canary/cogs/banner.py b/canary/cogs/banner.py index 692a35e4f..7e37cf288 100644 --- a/canary/cogs/banner.py +++ b/canary/cogs/banner.py @@ -478,7 +478,6 @@ async def submit_banner(self, ctx: commands.Context, *args): with Image.open(Banner.CONVERTER_FILE) as overlay_mask, Image.open( Banner.PREVIEW_FILE ) as preview_mask, Image.open(user_image_file) as user_image: - animated = user_image.is_animated overlay_mask_user_canvas_size = overlay_mask.size diff --git a/canary/cogs/currency.py b/canary/cogs/currency.py index 15af39af6..977a5bc42 100644 --- a/canary/cogs/currency.py +++ b/canary/cogs/currency.py @@ -118,10 +118,10 @@ def parse_currency(amount: str, balance: Decimal) -> Decimal | None: return None def currency_to_db(self, amount: Decimal) -> int: - return int(amount * Decimal(10 ** self.prec)) + return int(amount * Decimal(10**self.prec)) def db_to_currency(self, amount: int) -> Decimal: - return Decimal(amount) / Decimal(10 ** self.prec) + return Decimal(amount) / Decimal(10**self.prec) def format_currency(self, amount: Decimal) -> str: return ("{:." + str(self.prec) + "f}").format(amount) @@ -191,9 +191,7 @@ async def initial_claim(self, ctx: commands.Context): ) await db.commit() - await ctx.send( - f"{author_name} claimed their initial {self.format_symbol_currency(self.initial)}!" - ) + await ctx.send(f"{author_name} claimed their initial {self.format_symbol_currency(self.initial)}!") @commands.command() async def claim(self, ctx: commands.Context): @@ -423,7 +421,7 @@ async def leaderboard(self, ctx): table_list = [] counter = 1 - for (_user_id, name, balance) in balances: + for _user_id, name, balance in balances: table.append((counter, name, self.format_symbol_currency(balance))) if counter % 7 == 0 or counter == len(balances): table_list.append(tabulate(table[:counter], headers=["Rank", "Name", "Balance"], tablefmt="fancy_grid")) diff --git a/canary/cogs/games.py b/canary/cogs/games.py index b9d0b1d61..7691d80bc 100644 --- a/canary/cogs/games.py +++ b/canary/cogs/games.py @@ -130,7 +130,6 @@ async def hangman(self, ctx, command: str | None = None): await ctx.send(embed=game_state.embed) while True: - msg_task = asyncio.create_task(self.bot.wait_for("message", check=msg_check, timeout=self.hm_timeout)) quit_task = asyncio.create_task(channel_lock.acquire()) done, _ = await asyncio.wait([msg_task, quit_task], return_when=asyncio.FIRST_COMPLETED) diff --git a/canary/cogs/helpers.py b/canary/cogs/helpers.py index 2ae52d362..888ab522e 100644 --- a/canary/cogs/helpers.py +++ b/canary/cogs/helpers.py @@ -292,7 +292,7 @@ async def course(self, ctx: commands.Context, *, query: str): .add_field(name="Terms", value=terms, inline=False) .add_field(name="Instructor(s)", value=instructors, inline=False) ) - for (a, b) in tidbits: + for a, b in tidbits: em.add_field(name=a, value=b, inline=False) await ctx.send(embed=em) @@ -460,8 +460,7 @@ async def search(self, ctx: commands.Context, *, query: str): while pagenum < pagelimit: r = await fetch( - self.bot.config.course_search_tpl.format(self.bot.config.course_year_range, keyword, pagenum), - "content" + self.bot.config.course_search_tpl.format(self.bot.config.course_year_range, keyword, pagenum), "content" ) soup = BeautifulSoup(r, "lxml") found = soup.find_all("div", {"class": "views-row"}) diff --git a/canary/cogs/music.py b/canary/cogs/music.py index fdfa7714f..f41e77604 100644 --- a/canary/cogs/music.py +++ b/canary/cogs/music.py @@ -288,7 +288,6 @@ async def play(self, ctx: commands.Context, url: Optional[str] = None): break if self.skip_opts is None: - if ctx.voice_client is None: break diff --git a/canary/cogs/utils/image_helpers.py b/canary/cogs/utils/image_helpers.py index c04c2f7bf..e2040e4f3 100644 --- a/canary/cogs/utils/image_helpers.py +++ b/canary/cogs/utils/image_helpers.py @@ -29,7 +29,6 @@ def apply_transform(transform, buffer, size, max_size, ext, is_png, *args): async def filter_image(loop, transform, ctx, history_limit, max_size, *args): - att = await get_attachment(ctx, history_limit) if att is None: await ctx.send( diff --git a/canary/cogs/utils/paginator.py b/canary/cogs/utils/paginator.py index 5947d944d..7ae09690c 100644 --- a/canary/cogs/utils/paginator.py +++ b/canary/cogs/utils/paginator.py @@ -234,7 +234,7 @@ async def _show_page(self, page): self.message = await self.channel.send( embed=self.pagesToSend[self.currentPage], delete_after=self.timeout ) - for (emoji, _) in self.actions: + for emoji, _ in self.actions: await self.message.add_reaction(emoji) return @@ -262,7 +262,7 @@ def _react_check(self, reaction, user): return False if reaction.message.id != self.message.id: return False - for (emoji, action) in self.actions: + for emoji, action in self.actions: if reaction.emoji != emoji: continue self.user = user diff --git a/pyproject.toml b/pyproject.toml index 32b47ae83..44e8255a0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -49,4 +49,3 @@ types-tabulate = "^0.8.11" [tool.black] line-length = 120 - From a23ce83b6a0cc144bf4bbec1cccf3800b99ef75e Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Sat, 3 Jun 2023 09:08:54 -0400 Subject: [PATCH 094/127] fix: defaults for currency and music nested settings --- canary/config/config.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/canary/config/config.py b/canary/config/config.py index bcddb70ea..d3ccb9ec5 100644 --- a/canary/config/config.py +++ b/canary/config/config.py @@ -124,10 +124,10 @@ class Config(BaseSettings): recall_filter: str = "Quebec|National" # Currency configuration - currency: CurrencyModel + currency: CurrencyModel = CurrencyModel() # Music configuration - music: MusicModel + music: MusicModel = MusicModel() # Assignable Roles # TODO From 2bc742d91e4d8131b9e47deb2a662451343ce7d1 Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Sat, 3 Jun 2023 09:13:09 -0400 Subject: [PATCH 095/127] fix: setting log levels with new config --- canary/bot.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/canary/bot.py b/canary/bot.py index 52bbeb9e4..c30fc3803 100644 --- a/canary/bot.py +++ b/canary/bot.py @@ -38,11 +38,12 @@ } config: Config = Config() +log_level = LOG_LEVELS[config.log_level] # Create parent logger, which will send all logs from the "sub-loggers" # to the specified log file logger = logging.getLogger("Canary") -logger.setLevel(LOG_LEVELS[config.log_level]) +logger.setLevel(log_level) file_handler = logging.FileHandler(filename=config.log_file, encoding="utf-8", mode="a") file_handler.setFormatter(logging.Formatter("[%(levelname)s] %(asctime)s: %(message)s")) logger.addHandler(file_handler) @@ -51,7 +52,7 @@ # If a dev webhook is specified, logs sent to the dev logger will be # sent to the webhook dev_logger = logging.getLogger("Canary.Dev") -dev_logger.setLevel(config.log_level) +dev_logger.setLevel(log_level) # Create mod (sub-)logger, where info for mods will be logged # If a mod webhook is specified, logs sent to the mod logger will be From 59832b5e4a128221c5681b77235993ae486d6303 Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Sat, 3 Jun 2023 09:13:20 -0400 Subject: [PATCH 096/127] fix: developer/moderator role checks --- canary/bot.py | 7 ++++++- canary/cogs/utils/checks.py | 10 +++++----- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/canary/bot.py b/canary/bot.py index c30fc3803..d1822ce19 100644 --- a/canary/bot.py +++ b/canary/bot.py @@ -26,7 +26,12 @@ from pathlib import Path from typing import AsyncGenerator -__all__ = ["Canary", "bot"] +__all__ = [ + "config", # Some functions/mixins use global config instead of some form of DI + + "Canary", + "bot", +] LOG_LEVELS = { "critical": logging.CRITICAL, diff --git a/canary/cogs/utils/checks.py b/canary/cogs/utils/checks.py index 5e034746e..563fb5b19 100644 --- a/canary/cogs/utils/checks.py +++ b/canary/cogs/utils/checks.py @@ -18,15 +18,15 @@ import discord from discord.ext import commands -from canary.bot import moderator_role, developer_role +from canary.bot import config def is_moderator(): """Returns True if user has a moderator role, raises an exception otherwise""" def predicate(ctx: commands.Context): - if discord.utils.get(ctx.author.roles, name=moderator_role) is None: - raise commands.MissingPermissions([moderator_role]) + if discord.utils.get(ctx.author.roles, name=config.moderator_role) is None: + raise commands.MissingPermissions([config.moderator_role]) return True return commands.check(predicate) @@ -36,8 +36,8 @@ def is_developer(): """Returns True if user is a bot developer, raises an exception otherwise""" def predicate(ctx: commands.Context): - if discord.utils.get(ctx.author.roles, name=developer_role) is None: - raise commands.MissingPermissions([developer_role]) + if discord.utils.get(ctx.author.roles, name=config.developer_role) is None: + raise commands.MissingPermissions([config.developer_role]) return True return commands.check(predicate) From ac93f3a1b1a9ca31fc24ae85983f191f6d5bff85 Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Sat, 3 Jun 2023 09:26:32 -0400 Subject: [PATCH 097/127] chore: port image config to new config object --- canary/cogs/images.py | 8 ++++---- canary/config/config.py | 10 ++++++++++ 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/canary/cogs/images.py b/canary/cogs/images.py index 64580f8f2..037cf6806 100644 --- a/canary/cogs/images.py +++ b/canary/cogs/images.py @@ -25,10 +25,10 @@ class Images(CanaryCog): def __init__(self, bot: Canary): super().__init__(bot) - self.max_size: int = self.bot.config.images["max_image_size"] - self.hist_lim: int = self.bot.config.images["image_history_limit"] - self.max_rad: int = self.bot.config.images["max_radius"] - self.max_itr: int = self.bot.config.images["max_iterations"] + self.max_size: int = self.bot.config.images.max_image_size + self.hist_lim: int = self.bot.config.images.image_history_limit + self.max_rad: int = self.bot.config.images.max_radius + self.max_itr: int = self.bot.config.images.max_iterations @commands.command() async def polar(self, ctx: commands.Context): diff --git a/canary/config/config.py b/canary/config/config.py index d3ccb9ec5..d9667da5f 100644 --- a/canary/config/config.py +++ b/canary/config/config.py @@ -49,6 +49,13 @@ class MusicModel(BaseModel): start_vol: float = "100.0" +class ImagesModel(BaseModel): + max_image_size: int = 8000000 + image_history_limit: int = 50 + max_radius: int = 500 + max_iterations: int = 20 + + class Config(BaseSettings): # Logging log_level: Literal["critical", "error", "warning", "info", "debug", "notset"] = "info" @@ -129,6 +136,9 @@ class Config(BaseSettings): # Music configuration music: MusicModel = MusicModel() + # Images configuration + images: ImagesModel = ImagesModel() + # Assignable Roles # TODO From 5bab9d466d723e5f5365758803c980bb307f359d Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Sat, 3 Jun 2023 09:26:46 -0400 Subject: [PATCH 098/127] fix: missing await for db fetchone --- canary/cogs/base_cog.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/canary/cogs/base_cog.py b/canary/cogs/base_cog.py index 786d2535f..a20a8aafd 100644 --- a/canary/cogs/base_cog.py +++ b/canary/cogs/base_cog.py @@ -56,7 +56,7 @@ async def fetch_one( db = await self.bot.db_nocm() try: async with db.execute(query, params) as c: - return c.fetchone() + return await c.fetchone() finally: if fresh_db: await db.close() From f012de63c6a0057b9b555567884b7458fad886b3 Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Sat, 3 Jun 2023 09:27:22 -0400 Subject: [PATCH 099/127] chore: port games config to new config model --- canary/cogs/games.py | 6 +++--- canary/config/config.py | 9 +++++++++ 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/canary/cogs/games.py b/canary/cogs/games.py index 7691d80bc..20fcb1cd0 100644 --- a/canary/cogs/games.py +++ b/canary/cogs/games.py @@ -49,9 +49,9 @@ class Games(CanaryCog): def __init__(self, bot: Canary, hangman_tbl_name: str) -> None: super().__init__(bot) - self.hm_cool_win: int = bot.config.games["hm_cool_win"] - self.hm_norm_win: int = bot.config.games["hm_norm_win"] - self.hm_timeout: int = bot.config.games["hm_timeout"] + self.hm_cool_win: int = bot.config.games.hm_cool_win + self.hm_norm_win: int = bot.config.games.hm_norm_win + self.hm_timeout: int = bot.config.games.hm_timeout self.hm_locks: dict[discord.TextChannel, asyncio.Lock] = dict() with open(f"{os.getcwd()}/data/premade/{hangman_tbl_name}.obj", "rb") as hangman_pkl: diff --git a/canary/config/config.py b/canary/config/config.py index d9667da5f..c15658234 100644 --- a/canary/config/config.py +++ b/canary/config/config.py @@ -56,6 +56,12 @@ class ImagesModel(BaseModel): max_iterations: int = 20 +class GamesModel(BaseModel): + hm_norm_win: int = 10 + hm_cool_win: int = 20 + hm_timeout: int = 600 + + class Config(BaseSettings): # Logging log_level: Literal["critical", "error", "warning", "info", "debug", "notset"] = "info" @@ -139,6 +145,9 @@ class Config(BaseSettings): # Images configuration images: ImagesModel = ImagesModel() + # Games configuration + games: GamesModel = GamesModel() + # Assignable Roles # TODO From 0c5d87b2989473fe52ad5c4f2666dbf9df455e9a Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Sat, 3 Jun 2023 09:30:02 -0400 Subject: [PATCH 100/127] fix: muted role checks --- canary/cogs/mod.py | 4 ++-- canary/cogs/utils/role_restoration.py | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/canary/cogs/mod.py b/canary/cogs/mod.py index b81a8c4e0..dfd0a0125 100644 --- a/canary/cogs/mod.py +++ b/canary/cogs/mod.py @@ -406,7 +406,7 @@ async def on_member_update(self, before, after): and muted_role_after and not ( (await is_in_muted_table(self.bot, after)) - and has_muted_role(after) + and has_muted_role(self.bot, after) and after in self.muted_users_to_appeal_channels and self.muted_users_to_appeal_channels[after] in self.guild.text_channels ) @@ -419,7 +419,7 @@ async def on_member_update(self, before, after): and not muted_role_after and ( (await is_in_muted_table(self.bot, after)) - or has_muted_role(after) + or has_muted_role(self.bot, after) or after in self.muted_users_to_appeal_channels ) ): diff --git a/canary/cogs/utils/role_restoration.py b/canary/cogs/utils/role_restoration.py index 5957d30db..edc5f5c44 100644 --- a/canary/cogs/utils/role_restoration.py +++ b/canary/cogs/utils/role_restoration.py @@ -23,14 +23,14 @@ from .paginator import Pages from .mock_context import MockContext -from canary.bot import Canary, muted_role as muted_role_name +from canary.bot import Canary import datetime async def save_existing_roles( bot: Canary, user: discord.Member, muted: bool = False, appeal_channel: discord.TextChannel | None = None ): - roles_id = [role.id for role in user.roles if role.name not in ("@everyone", muted_role_name)] + roles_id = [role.id for role in user.roles if role.name not in ("@everyone", bot.config.muted_role)] if not roles_id and not muted: return @@ -78,8 +78,8 @@ async def fetch_saved_roles(bot: Canary, guild, user: discord.Member, muted: boo ) -def has_muted_role(user: discord.Member): - muted_role = utils.get(user.guild.roles, name=muted_role_name) +def has_muted_role(bot: Canary, user: discord.Member): + muted_role = utils.get(user.guild.roles, name=bot.config.muted_role) return muted_role and next((r for r in user.roles if r == muted_role), None) is not None From 178a8a1ccbaa4c14462135d01033c206c2e2e69a Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Sat, 3 Jun 2023 09:39:32 -0400 Subject: [PATCH 101/127] fix: music config model default start vol value --- canary/config/config.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/canary/config/config.py b/canary/config/config.py index c15658234..a3c1a5b43 100644 --- a/canary/config/config.py +++ b/canary/config/config.py @@ -46,7 +46,7 @@ class CurrencyModel(BaseModel): class MusicModel(BaseModel): ban_role: str = "tone deaf" - start_vol: float = "100.0" + start_vol: float = 100.0 class ImagesModel(BaseModel): From 8792524cf9cac026b9736cb584fa0b7289116363 Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Sat, 3 Jun 2023 09:41:39 -0400 Subject: [PATCH 102/127] chore: port legacy assignable roles config to new config model --- canary/bot.py | 1 - canary/cogs/roles.py | 8 ++-- canary/config/config.py | 95 ++++++++++++++++++++++++++++++++++++++++- 3 files changed, 99 insertions(+), 5 deletions(-) diff --git a/canary/bot.py b/canary/bot.py index d1822ce19..9a0a028fd 100644 --- a/canary/bot.py +++ b/canary/bot.py @@ -28,7 +28,6 @@ __all__ = [ "config", # Some functions/mixins use global config instead of some form of DI - "Canary", "bot", ] diff --git a/canary/cogs/roles.py b/canary/cogs/roles.py index d003b0fa4..2058f3b5d 100644 --- a/canary/cogs/roles.py +++ b/canary/cogs/roles.py @@ -77,7 +77,7 @@ async def toggle_role( if not requested_role: roles = [] for c in categories: - roles += self.roles[c] # All roles in the category + roles += getattr(self.roles, c) # All roles in the category # If no role is specified, list what is available in all possible # categories for the command. @@ -87,12 +87,14 @@ async def toggle_role( # If a role is specified, narrow the category down to the one with the # role in it to impose a proper limit. try: - category = next((c for c in categories if requested_role.lower() in {r.lower() for r in self.roles[c]})) + category = next( + (c for c in categories if requested_role.lower() in {r.lower() for r in getattr(self.roles, c)}) + ) except StopIteration: await ctx.send(f"Invalid role for {fcategory} `{', '.join(categories)}`.") return - roles = self.roles[category] + roles = getattr(self.roles, category) roles_lower = [r.lower() for r in roles] requested_role = roles[roles_lower.index(requested_role.lower())] diff --git a/canary/config/config.py b/canary/config/config.py index a3c1a5b43..4e2f74519 100644 --- a/canary/config/config.py +++ b/canary/config/config.py @@ -62,6 +62,99 @@ class GamesModel(BaseModel): hm_timeout: int = 600 +class RolesModel(BaseModel): + pronouns: tuple[str, ...] = ("She/Her", "He/Him", "They/Them") + fields: tuple[str, ...] = ( + "Accounting", + "Agriculture", + "Anatomy and Cell Biology", + "Anthropology", + "Architecture", + "Biochemistry", + "Bioengineering", + "Biology", + "Bioresource Engineering", + "Chemical Engineering", + "Chemistry", + "Civil Engineering", + "Classics", + "cogito", + "Commerce", + "Computer Engineering", + "Computer Science", + "Computer Science/Biology", + "Cultural Studies", + "Desautels", + "Economics", + "Electrical Engineering", + "English", + "Experimental Medicine", + "Finance", + "Geography", + "History", + "Human Genetics", + "Indigenous Studies", + "International Development Studies", + "Jewish Studies", + "linguini", + "mac kid", + "Materials Engineering", + "Math", + "MBA", + "Mechanical Engineering", + "Medicine", + "Microbiology and Immunology", + "Neuroscience", + "Nursing", + "Pharmacology", + "Philosophy", + "Physical Therapy", + "Physics", + "Physiology", + "Political Science", + "Psychiatry", + "Psychology", + "Public Health", + "Social Work", + "Sociology", + "Software Engineering", + "Statistics", + "Theology", + "Urban Systems", + ) + faculties: tuple[str, ...] = ( + "Science", + "Engineering", + "Management", + "art you glad you're not in arts", + "ArtSci", + "Agriculture and Environment", + "Continuing Studies", + "Law", + "Education", + "Dentistry", + "Music", + ) + years: tuple[str, ...] = ("U0", "U1", "U2", "U3", "U4", "grad student", "workhere", "wenthere") + generics: tuple[str, ...] = ( + "weeb", + "weeb stomper", + "crosswords", + "stm_alertee", + "Stardew", + "R6", + "CS:GO Popflash", + "CS:GO Comp", + "Minecraft", + "Among Us", + "Pokemon Go", + "Secret Crabbo", + "Warzone", + "Monster Hunter", + "undersad", + ) + + class Config(BaseSettings): # Logging log_level: Literal["critical", "error", "warning", "info", "debug", "notset"] = "info" @@ -149,7 +242,7 @@ class Config(BaseSettings): games: GamesModel = GamesModel() # Assignable Roles - # TODO + roles: RolesModel = RolesModel() class Config: # Pydantic config for our own Config class env_file = ".env" From 253f5047d4946824e214dbd4ac68eba93ba2dca4 Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Sat, 3 Jun 2023 09:43:20 -0400 Subject: [PATCH 103/127] ci: tweak formatting check --- .github/workflows/formatting_check.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/formatting_check.yml b/.github/workflows/formatting_check.yml index d2e7f9855..36cfe528d 100644 --- a/.github/workflows/formatting_check.yml +++ b/.github/workflows/formatting_check.yml @@ -3,7 +3,7 @@ name: formatting check on: push: paths: - "**.py" + - "**.py" jobs: lint: @@ -13,4 +13,4 @@ jobs: - uses: actions/setup-python@v4 - uses: psf/black@stable with: - options: "--diff --check -t py311" + options: "--diff --check -t py311 canary" From 1e16edd54e5cfa0867cfd20a8f1a7e90d7e7bfc2 Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Sat, 3 Jun 2023 09:44:33 -0400 Subject: [PATCH 104/127] fix: music config access --- canary/cogs/music.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/canary/cogs/music.py b/canary/cogs/music.py index f41e77604..29b632287 100644 --- a/canary/cogs/music.py +++ b/canary/cogs/music.py @@ -60,12 +60,12 @@ def __init__(self, bot: Canary): self.track_lock: asyncio.Lock = asyncio.Lock() self.playing: tuple[dict, str] | None = None self.looping_track: bool = False - self.volume_level: float = self.bot.config.music["start_vol"] + self.volume_level: float = self.bot.config.music.start_vol self.speed_flag: str = "atempo=1" self.speed_val: float = 1.0 self.skip_opts: Optional[tuple[str, int]] = None self.track_start_time: float = 0.0 - self.ban_role: str = self.bot.config.music["ban_role"] + self.ban_role: str = self.bot.config.music.ban_role self.pause_start: float | None = None async def get_info(self, url: str): @@ -337,7 +337,7 @@ async def play(self, ctx: commands.Context, url: Optional[str] = None): self.playing = None self.track_lock.release() - self.volume_level = self.bot.config.music["start_vol"] + self.volume_level: float = self.bot.config.music.start_vol self.speed_flag = "atempo=1" @check_playing From 3254f5c490e9ef4b7610ef2c9a3f3f31d0d5cf24 Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Sat, 3 Jun 2023 10:25:26 -0400 Subject: [PATCH 105/127] chore: update discordpy to 1.7.3 --- poetry.lock | 8 ++++---- pyproject.toml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/poetry.lock b/poetry.lock index 731ba298f..6ca4f9d75 100644 --- a/poetry.lock +++ b/poetry.lock @@ -405,14 +405,14 @@ files = [ [[package]] name = "discord-py" -version = "1.6.0" +version = "1.7.3" description = "A Python wrapper for the Discord API" category = "main" optional = false python-versions = ">=3.5.3" files = [ - {file = "discord.py-1.6.0-py3-none-any.whl", hash = "sha256:3df148daf6fbcc7ab5b11042368a3cd5f7b730b62f09fb5d3cbceff59bcfbb12"}, - {file = "discord.py-1.6.0.tar.gz", hash = "sha256:ba8be99ff1b8c616f7b6dcb700460d0222b29d4c11048e74366954c465fdd05f"}, + {file = "discord.py-1.7.3-py3-none-any.whl", hash = "sha256:c6f64db136de0e18e090f6752ea68bdd4ab0a61b82dfe7acecefa22d6477bb0c"}, + {file = "discord.py-1.7.3.tar.gz", hash = "sha256:462cd0fe307aef8b29cbfa8dd613e548ae4b2cb581d46da9ac0d46fb6ea19408"}, ] [package.dependencies] @@ -1829,4 +1829,4 @@ websockets = "*" [metadata] lock-version = "2.0" python-versions = ">=3.10.0,<3.12" -content-hash = "502a94f21c3c3a4d81942488c5aa9fe26a305bb0bba55155e2b5a0af83ac736a" +content-hash = "a42a099e7fbbc4b83adac406f383e2da31e37caf650ce271d1fa4c7456b9dcb1" diff --git a/pyproject.toml b/pyproject.toml index 44e8255a0..1a5944121 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -19,7 +19,7 @@ beautifulsoup4 = "^4.12.2" sympy = "^1.9" requests = ">=2.30.0,<3" tabulate = "~0.8.9" -"discord.py" = {extras = ["voice"], version = "~1.6.0"} +"discord.py" = {version = "~1.7.3", extras = ["voice"]} opencv-python = "==4.6.0.66" pytz = ">=2020.5" numpy = "^1.21.1" From 0d4a71575b4c424a6229048c8aa1076c9acf7b18 Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Sat, 3 Jun 2023 10:40:32 -0400 Subject: [PATCH 106/127] fix: type hints causing bad conversions in currency cog --- canary/cogs/currency.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/canary/cogs/currency.py b/canary/cogs/currency.py index 977a5bc42..e89fe8a63 100644 --- a/canary/cogs/currency.py +++ b/canary/cogs/currency.py @@ -227,7 +227,7 @@ async def claim(self, ctx: commands.Context): await ctx.send(f"Please wait {time_left.seconds // 3600}h {time_left.seconds // 60 % 60}m to claim again!") @commands.command(aliases=["$", "bal"]) - async def balance(self, ctx: commands.Context, user: discord.Member = None): + async def balance(self, ctx: commands.Context, user: discord.Member | None = None): """ Return the user's account balance. """ @@ -243,13 +243,13 @@ async def balance(self, ctx: commands.Context, user: discord.Member = None): await ctx.send(f"{author.display_name} has {amount} in their account.") @commands.command(aliases=["bf"]) - async def bet_flip(self, ctx: commands.Context, bet: str | None = None, face: str | None = None): + async def bet_flip(self, ctx: commands.Context, bet: str = "", face: str = ""): """ Bets an amount of money on a coin flip. - Usage: ?bet_flip h 10 or ?bet_flip t 5 + Usage: ?bet_flip 10 h or ?bet_flip 5 t """ - if face is None or bet is None: + if bet == "" or face == "": return # Start bot typing @@ -290,13 +290,13 @@ async def bet_flip(self, ctx: commands.Context, bet: str | None = None, face: st await ctx.send(message.format(author_name, self.format_symbol_currency(bet_dec), result)) @commands.command(aliases=["br"]) - async def bet_roll(self, ctx: commands.Context, bet: str | None = None): + async def bet_roll(self, ctx: commands.Context, bet: str = ""): """ Bets an amount of currency on a D100 roll. Usage: ?bet_roll 100 or ?br all """ - if bet is None: + if bet == "": return # Start bot typing @@ -306,7 +306,7 @@ async def bet_roll(self, ctx: commands.Context, bet: str | None = None): bet_dec = self.parse_currency(bet, balance) # Handle invalid cases - if (error := self.check_bet(balance, bet_dec)) != "": + if (error := self.check_bet(balance, bet_dec)) is not None: await ctx.send(error) return @@ -349,7 +349,7 @@ async def bet_roll(self, ctx: commands.Context, bet: str | None = None): await ctx.send(message_tpl.format(un=author_name, am=bet_str, re=result)) @commands.command() - async def give(self, ctx: commands.Context, user: discord.Member | None = None, amount: str | None = None): + async def give(self, ctx: commands.Context, user: discord.Member, amount: str = ""): """ Gives some amount of currency to another user. """ @@ -357,7 +357,7 @@ async def give(self, ctx: commands.Context, user: discord.Member | None = None, # Start bot typing await ctx.trigger_typing() - if not user or amount is None: + if amount == "": await ctx.send("Usage: ?give [user] [amount]") return @@ -404,7 +404,7 @@ async def give(self, ctx: commands.Context, user: discord.Member | None = None, await ctx.send(f"{grn} gave {self.format_symbol_currency(amount_dec)} to {gen}!") @commands.command(aliases=["lb"]) - async def leaderboard(self, ctx): + async def leaderboard(self, ctx: commands.Context): """ Currency rankings """ From d3ee5b4261724a51876a570079382a0ba19ce6fb Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Sat, 3 Jun 2023 10:40:50 -0400 Subject: [PATCH 107/127] fix: type hints causing bad conversions in memes and roles cogs --- canary/cogs/memes.py | 12 ++++++------ canary/cogs/roles.py | 20 ++++++++++---------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/canary/cogs/memes.py b/canary/cogs/memes.py index a18cb9583..8a9cc70f5 100644 --- a/canary/cogs/memes.py +++ b/canary/cogs/memes.py @@ -28,7 +28,7 @@ class Memes(CanaryCog): @commands.command() - async def bac(self, ctx: commands.Context, *, input_str: str | None = None): + async def bac(self, ctx: commands.Context, *, input_str: str = ""): """ Purposefully auto-incorrects inputted sentences Inputted text is either the content of the message to @@ -38,7 +38,7 @@ async def bac(self, ctx: commands.Context, *, input_str: str | None = None): well. Invoking message will be deleted. """ replying: bool = ctx.message.reference and ctx.message.reference.resolved - if input_str is None: + if input_str == "": if not replying: return input_str = ctx.message.reference.resolved.content @@ -89,7 +89,7 @@ async def cheep(self, ctx: commands.Context): await ctx.send("CHEEP CHEEP") @commands.command() - async def mix(self, ctx: commands.Context, *, input_str: str | None = None): + async def mix(self, ctx: commands.Context, *, input_str: str = ""): """Alternates upper/lower case for input string. Inputted text is either the content of the message to after the command or the content of the message to which @@ -99,7 +99,7 @@ async def mix(self, ctx: commands.Context, *, input_str: str | None = None): """ replying: bool = ctx.message.reference and ctx.message.reference.resolved - if input_str is None: + if input_str == "": if not replying: return input_str = ctx.message.reference.resolved.content @@ -142,7 +142,7 @@ def pyramidy(n: int, m: int) -> str: await ctx.send(f"**\n{msg}**") @commands.command() - async def xkcd(self, ctx: commands.Context, command: str | None = None): + async def xkcd(self, ctx: commands.Context, command: str = ""): """ Enjoy a nice xkcd comic with some strangers on the internet! If no issue number is passed, returns a random xkcd. @@ -153,7 +153,7 @@ async def xkcd(self, ctx: commands.Context, command: str | None = None): await ctx.trigger_typing() async with aiohttp.ClientSession() as session: - if command is None: + if command == "": async with session.get("https://c.xkcd.com/comic/random") as r: if r.status != 200: await ctx.send(f"failure: random xkcd request returned `{r.status}`") diff --git a/canary/cogs/roles.py b/canary/cogs/roles.py index 2058f3b5d..595b9e81d 100644 --- a/canary/cogs/roles.py +++ b/canary/cogs/roles.py @@ -66,7 +66,7 @@ async def toggle_role( self, ctx: commands.Context, transaction: RoleTransaction, - requested_role: Optional[str], + requested_role: str, categories: Tuple[str, ...], ): """ @@ -156,7 +156,7 @@ async def add_role(self, ctx, requested_role: Optional[str], categories: Tuple[s return await self.toggle_role(ctx, RoleTransaction.ADD, requested_role, categories) @commands.command(aliases=["pronouns"]) - async def pronoun(self, ctx: commands.Context, *, pronoun: Optional[str] = None): + async def pronoun(self, ctx: commands.Context, *, pronoun: str = ""): """ Self-assign a pronoun role to a user. If no argument is given, returns a list of roles that can be used with this command. @@ -164,7 +164,7 @@ async def pronoun(self, ctx: commands.Context, *, pronoun: Optional[str] = None) await self.add_role(ctx, pronoun, ("pronouns",)) @commands.command(aliases=["fields", "program", "programs", "major", "majors"]) - async def field(self, ctx: commands.Context, *, field: Optional[str] = None): + async def field(self, ctx: commands.Context, *, field: str = ""): """ Self-assign a field of study role to a user. If no argument is given, returns a list of roles that can be used with this command. @@ -172,7 +172,7 @@ async def field(self, ctx: commands.Context, *, field: Optional[str] = None): await self.add_role(ctx, field, ("fields",)) @commands.command(aliases=["faculties"]) - async def faculty(self, ctx: commands.Context, *, faculty: Optional[str] = None): + async def faculty(self, ctx: commands.Context, *, faculty: str = ""): """ Self-assign a faculty of study role to a user. If no argument is given, returns a list of roles that can be used with this command. @@ -180,7 +180,7 @@ async def faculty(self, ctx: commands.Context, *, faculty: Optional[str] = None) await self.add_role(ctx, faculty, ("faculties",)) @commands.command(aliases=["years"]) - async def year(self, ctx, year: Optional[str] = None): + async def year(self, ctx, year: str = ""): """ Self-assign a year of study role to a user. If no argument is given, returns a list of roles that can be used with this command. @@ -188,7 +188,7 @@ async def year(self, ctx, year: Optional[str] = None): await Roles.add_role(self, ctx, year, ("years",)) @commands.command(aliases=["iam", "generic", "generics"]) - async def i_am(self, ctx: commands.Context, *, role: Optional[str]): + async def i_am(self, ctx: commands.Context, *, role: str = ""): """ Self-assign a generic role to a user. If no argument is given, returns a list of roles that can be used with this command. @@ -196,14 +196,14 @@ async def i_am(self, ctx: commands.Context, *, role: Optional[str]): await self.add_role(ctx, role, Roles.ALL_CATEGORIES) @commands.command(aliases=["iamn"]) - async def i_am_not(self, ctx: commands.Context, *, role: Optional[str]): + async def i_am_not(self, ctx: commands.Context, *, role: str = ""): """ Self-unassign a generic role to a user. """ await self.toggle_role(ctx, RoleTransaction.REMOVE, role, Roles.ALL_CATEGORIES) @commands.command() - async def roles(self, ctx, user: discord.Member = None): + async def roles(self, ctx, user: discord.Member): """Returns list of all roles in server or the list of a specific user's roles""" role_names = [ @@ -240,8 +240,8 @@ async def in_role(self, ctx: commands.Context, *, query_role: str): @commands.command(aliases=["cr", "createrole"]) @is_moderator() - async def create_role(self, ctx: commands.Context, *, role: str | None = None): - role = (role or "").strip() + async def create_role(self, ctx: commands.Context, *, role: str = ""): + role = role.strip() if not role: await ctx.send("Please specify a role name.") return From f4f5c2b13c6fc1414a6dc1bd00496764ca88e0ac Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Sat, 3 Jun 2023 10:41:04 -0400 Subject: [PATCH 108/127] chore: add log webhook env vars to example env --- canary/config/config.py | 11 +++++------ example.env | 4 ++++ 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/canary/config/config.py b/canary/config/config.py index 4e2f74519..07aa31a64 100644 --- a/canary/config/config.py +++ b/canary/config/config.py @@ -160,6 +160,11 @@ class Config(BaseSettings): log_level: Literal["critical", "error", "warning", "info", "debug", "notset"] = "info" log_file: Path = Path.cwd() / "canary.log" + dev_log_webhook_id: int | None = None + dev_log_webhook_token: str | None = None + mod_log_webhook_id: int | None = None + mod_log_webhook_token: str | None = None + # Discord token discord_key: str @@ -200,12 +205,6 @@ class Config(BaseSettings): # Meta repository: str = "https://github.com/idoneam/Canary.git" - # Logging - dev_log_webhook_id: int | None = None - dev_log_webhook_token: str | None = None - mod_log_webhook_id: int | None = None - mod_log_webhook_token: str | None = None - # Welcome + Farewell messages # NOT PORTED FROM OLD CONFIG SETUP. diff --git a/example.env b/example.env index 8b67e6add..b1dc74645 100644 --- a/example.env +++ b/example.env @@ -2,3 +2,7 @@ CANARY_DISCORD_TOKEN=my_token_here CANARY_SERVER_ID=test-server-id CANARY_COMMAND_PREFIX=! +CANARY_DEV_LOG_WEBHOOK_ID= +CANARY_DEV_LOG_WEBHOOK_TOKEN= +CANARY_MOD_LOG_WEBHOOK_ID= +CANARY_MOD_LOG_WEBHOOK_TOKEN= From 7624fb2a5ace56670d3d79c0893d0103a5a8490b Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Sat, 3 Jun 2023 10:58:15 -0400 Subject: [PATCH 109/127] chore: remove old config class --- canary/config/config.py | 162 ++-------------------------------------- 1 file changed, 8 insertions(+), 154 deletions(-) diff --git a/canary/config/config.py b/canary/config/config.py index 07aa31a64..21756ddae 100644 --- a/canary/config/config.py +++ b/canary/config/config.py @@ -15,11 +15,6 @@ # You should have received a copy of the GNU General Public License # along with Canary. If not, see . -import codecs -import configparser -import decimal -import os - from pathlib import Path from pydantic import BaseModel, BaseSettings @@ -41,7 +36,12 @@ class CurrencyModel(BaseModel): bet_roll_cases: tuple[int, ...] = (66, 90, 99, 100) # d100 roll threshold bet_roll_returns: tuple[int, ...] = (0, 2, 4, 10) # multiplication factorys - # TODO: Finish + # Unused old ideas laid to rest below + # "salary_base": decimal.Decimal(config["Currency"]["SalaryBase"]), + # "inflation": decimal.Decimal(config["Currency"]["Inflation"]), + # "income_tax": {decimal.Decimal(b): float(a) for b, a in income_tb}, + # "asset_tax": {decimal.Decimal(b): float(a) for b, a in asset_tb}, + # "transaction_tax": float(config["OtherTax"]["TransactionTax"]), class MusicModel(BaseModel): @@ -207,6 +207,8 @@ class Config(BaseSettings): # Welcome + Farewell messages # NOT PORTED FROM OLD CONFIG SETUP. + # self.welcome = config["Greetings"]["Welcome"].split("\n") + # self.goodbye = config["Greetings"]["Goodbye"].split("\n") # DB configuration db_path: str = "./data/runtime/Martlet.db" @@ -247,151 +249,3 @@ class Config: # Pydantic config for our own Config class env_file = ".env" env_prefix = "CANARY_" env_nested_delimiter = "__" - - -class ConfigOld: - CONFIG_PATH = Path(__file__).parent / "config.ini" - - def __init__(self): - config = configparser.ConfigParser() - config.read_file(codecs.open(str(ConfigOld.CONFIG_PATH), "r", "utf-8-sig")) - - # Discord token - # Try to get from environment; if not found, then - self.discord_key = os.environ.get("CANARY_DISCORD_KEY", config["Discord"].get("Key")) - - if self.discord_key is None: - raise Exception("Missing discord key; please specify with CANARY_DISCORD_KEY environment variable.") - - # Server configs - self.server_id = int(os.environ.get("CANARY_SERVER_ID", config["Server"].get("ServerID"))) - self.command_prefix = [s for s in config["Server"]["CommandPrefix"].strip().split(",")] - self.bot_name = config["Server"]["BotName"] - - # Emoji - self.upvote_emoji = config["Emoji"]["UpvoteEmoji"] - self.downvote_emoji = config["Emoji"]["DownvoteEmoji"] - self.banner_vote_emoji = config["Emoji"]["BannerVoteEmoji"] - - # Roles - self.moderator_role = config["Roles"]["ModeratorRole"] - self.developer_role = config["Roles"]["DeveloperRole"] - self.mcgillian_role = config["Roles"]["McGillianRole"] - self.honorary_mcgillian_role = config["Roles"]["HonoraryMcGillianRole"] - self.banner_reminders_role = config["Roles"]["BannerRemindersRole"] - self.banner_winner_role = config["Roles"]["BannerWinnerRole"] - self.trash_tier_banner_role = config["Roles"]["TrashTierBannerRole"] - self.no_food_spotting_role = config["Roles"]["NoFoodSpottingRole"] - self.muted_role = config["Roles"]["MutedRole"] - self.crabbo_role = config["Roles"]["CrabboRole"] - - # Channels - self.reception_channel = config["Channels"]["ReceptionChannel"] - self.banner_of_the_week_channel = config["Channels"]["BannerOfTheWeekChannel"] - self.banner_submissions_channel = config["Channels"]["BannerSubmissionsChannel"] - self.banner_converted_channel = config["Channels"]["BannerConvertedChannel"] - self.food_spotting_channel = config["Channels"]["FoodSpottingChannel"] - self.metro_status_channel = config["Channels"]["MetroStatusChannel"] - self.bots_channel = config["Channels"]["BotsChannel"] - self.verification_channel = config["Channels"]["VerificationChannel"] - self.appeals_log_channel = config["Channels"]["AppealsLogChannel"] - self.appeals_category = config["Channels"]["AppealsCategory"] - - # Meta - self.repository = config["Meta"]["Repository"] - - # Logging - self.log_file = config["Logging"]["LogFile"] - # loglevel = config["Logging"]["LogLevel"].lower() - # self.log_level = LOG_LEVELS.get(loglevel, logging.WARNING) - if config["Logging"]["DevLogWebhookID"] and config["Logging"]["DevLogWebhookToken"]: - self.dev_log_webhook_id = int(config["Logging"]["DevLogWebhookID"]) - self.dev_log_webhook_token = config["Logging"]["DevLogWebhookToken"] - else: - self.dev_log_webhook_id = None - self.dev_log_webhook_token = None - if config["Logging"]["ModLogWebhookID"] and config["Logging"]["ModLogWebhookToken"]: - self.mod_log_webhook_id = int(config["Logging"]["ModLogWebhookID"]) - self.mod_log_webhook_token = config["Logging"]["ModLogWebhookToken"] - else: - self.mod_log_webhook_id = None - self.mod_log_webhook_token = None - - # Welcome + Farewell messages - self.welcome = config["Greetings"]["Welcome"].split("\n") - self.goodbye = config["Greetings"]["Goodbye"].split("\n") - - # DB configuration - self.db_path = config["DB"]["Path"] - - # Helpers configuration - self.course_tpl = config["Helpers"]["CourseTemplate"] - self.course_search_tpl = config["Helpers"]["CourseSearchTemplate"] - self.gc_weather_url = config["Helpers"]["GCWeatherURL"] - self.gc_weather_alert_url = config["Helpers"]["GCWeatherAlertURL"] - self.wttr_in_tpl = config["Helpers"]["WttrINTemplate"] - self.tepid_url = config["Helpers"]["TepidURL"] - - # Subscription configuration - self.recall_channel = config["Subscribers"]["FoodRecallChannel"] - self.recall_filter = config["Subscribers"]["FoodRecallLocationFilter"] - - # Below lies currency configuration - currency_precision = int(config["Currency"]["Precision"]) - - income_tb = zip( - [x.strip() for x in config["IncomeTax"]["Brackets"].split(",")], - [x.strip() for x in config["IncomeTax"]["Amounts"].split(",")], - ) - - asset_tb = zip( - [x.strip() for x in config["AssetTax"]["Brackets"].split(",")], - [x.strip() for x in config["AssetTax"]["Amounts"].split(",")], - ) - - br_cases = zip( - [x.strip() for x in config["Betting"]["RollCases"].split(",")], - [x.strip() for x in config["Betting"]["RollReturns"].split(",")], - ) - - self.currency = { - "name": config["Currency"]["Name"], - "symbol": config["Currency"]["Symbol"], - "precision": currency_precision, - "initial_amount": decimal.Decimal(config["Currency"]["Initial"]), - "salary_base": decimal.Decimal(config["Currency"]["SalaryBase"]), - "inflation": decimal.Decimal(config["Currency"]["Inflation"]), - "income_tax": {decimal.Decimal(b): float(a) for b, a in income_tb}, - "asset_tax": {decimal.Decimal(b): float(a) for b, a in asset_tb}, - "transaction_tax": float(config["OtherTax"]["TransactionTax"]), - "bet_roll_cases": sorted([(int(c), decimal.Decimal(a)) for c, a in br_cases], key=lambda c: c[0]), - } - - self.images = { - "max_image_size": int(config["Images"]["MaxImageSize"]), - "image_history_limit": int(config["Images"]["ImageHistoryLimit"]), - "max_radius": int(config["Images"]["MaxRadius"]), - "max_iterations": int(config["Images"]["MaxIterations"]), - } - - self.games = { - "hm_norm_win": int(config["Games"]["HangmanNormalWin"]), - "hm_cool_win": int(config["Games"]["HangmanCoolWin"]), - "hm_timeout": int(config["Games"]["HangmanTimeOut"]), - } - - # Assignable Roles - roles = { - "pronouns": config["AssignableRoles"]["Pronouns"], - "fields": config["AssignableRoles"]["Fields"], - "faculties": config["AssignableRoles"]["Faculties"], - "years": config["AssignableRoles"]["Years"], - "generics": config["AssignableRoles"]["Generics"], - } - - self.music = {"ban_role": config["Music"]["BanRole"], "start_vol": float(config["Music"]["StartVol"])} - - for rc in roles: - roles[rc] = [r.strip() for r in roles[rc].split(",")] - - self.roles = roles From df41accf437d49b28c86eb0fe697d88f9732411a Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Sat, 3 Jun 2023 11:04:12 -0400 Subject: [PATCH 110/127] fix: listing all roles not working --- canary/cogs/roles.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/canary/cogs/roles.py b/canary/cogs/roles.py index 595b9e81d..2989225dc 100644 --- a/canary/cogs/roles.py +++ b/canary/cogs/roles.py @@ -203,7 +203,7 @@ async def i_am_not(self, ctx: commands.Context, *, role: str = ""): await self.toggle_role(ctx, RoleTransaction.REMOVE, role, Roles.ALL_CATEGORIES) @commands.command() - async def roles(self, ctx, user: discord.Member): + async def roles(self, ctx, user: discord.Member = None): # bad type hinting, but needed for discord.py conversion """Returns list of all roles in server or the list of a specific user's roles""" role_names = [ From 7cf6dda237cf6879adede0d9759871b5a4ff2f02 Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Sat, 3 Jun 2023 11:23:08 -0400 Subject: [PATCH 111/127] example env wording --- example.env | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/example.env b/example.env index b1dc74645..fdd0fdfef 100644 --- a/example.env +++ b/example.env @@ -1,4 +1,4 @@ -# Change this to .env and enter your customizations! +# Copy this to .env and enter your customizations! CANARY_DISCORD_TOKEN=my_token_here CANARY_SERVER_ID=test-server-id CANARY_COMMAND_PREFIX=! From 6bc59f7da422e465a786957d9d1b598cce9e6f56 Mon Sep 17 00:00:00 2001 From: "namemcguffin@rhizome" <52169277+namemcguffin@users.noreply.github.com> Date: Thu, 29 Jun 2023 13:27:42 -0400 Subject: [PATCH 112/127] [fix]: fixed field name in example.env --- example.env | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/example.env b/example.env index fdd0fdfef..b315c6bd4 100644 --- a/example.env +++ b/example.env @@ -1,5 +1,5 @@ # Copy this to .env and enter your customizations! -CANARY_DISCORD_TOKEN=my_token_here +CANARY_DISCORD_KEY=my_token_here CANARY_SERVER_ID=test-server-id CANARY_COMMAND_PREFIX=! CANARY_DEV_LOG_WEBHOOK_ID= From 69cda94df58ca1ffa8ce3eec1bba3ca83129ef8a Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Wed, 4 Sep 2024 19:02:07 -0400 Subject: [PATCH 113/127] update course year range to 24-25 --- canary/config/config.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/canary/config/config.py b/canary/config/config.py index 21756ddae..5e09dd4df 100644 --- a/canary/config/config.py +++ b/canary/config/config.py @@ -214,7 +214,7 @@ class Config(BaseSettings): db_path: str = "./data/runtime/Martlet.db" # Helpers configuration - course_year_range: str = "2023-2024" + course_year_range: str = "2024-2025" course_tpl: str = "http://www.mcgill.ca/study/{course_year_range}/courses/{}" course_search_tpl: str = ( "http://www.mcgill.ca/study/{course_year_range}/courses/search?search_api_views_fulltext={}" From 059465617d3c672c4feee78206a5a65f4240944a Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Wed, 4 Sep 2024 19:37:58 -0400 Subject: [PATCH 114/127] steal https://github.com/idoneam/Canary/pull/519 --- canary/cogs/helpers.py | 55 ++++++++++++++++++++++------------------- canary/config/config.py | 3 +-- 2 files changed, 31 insertions(+), 27 deletions(-) diff --git a/canary/cogs/helpers.py b/canary/cogs/helpers.py index 888ab522e..692fd418b 100644 --- a/canary/cogs/helpers.py +++ b/canary/cogs/helpers.py @@ -51,8 +51,6 @@ MCGILL_KEY_DATES_URL = "https://www.mcgill.ca/importantdates/key-dates" -WTTR_IN_MOON_URL = "http://wttr.in/moon.png" - URBAN_DICT_TEMPLATE = "http://api.urbandictionary.com/v0/define?term={}" LMGTFY_TEMPLATE = "https://letmegooglethat.com/?q={}" @@ -130,29 +128,46 @@ def _calculate_feels_like(temp: float, humidity: float, ws_kph: float) -> str: return f"{round(feels_like, 1)}°C" @commands.command() - @site_save("http://weather.gc.ca/city/pages/qc-147_metric_e.html") + @site_save("https://dd.weather.gc.ca/citypage_weather/xml/QC/s0000635_e.xml") async def weather(self, ctx: commands.Context): """ Retrieves current weather conditions. - Data taken from http://weather.gc.ca/city/pages/qc-147_metric_e.html + Data taken from https://dd.weather.gc.ca/citypage_weather/xml/QC/s0000635_e.xml """ await ctx.trigger_typing() r = await fetch(self.bot.config.gc_weather_url, "content") - soup = BeautifulSoup(r, "lxml") + soup = BeautifulSoup(r, features="xml") + + # We only care about the current conditions, rest can be discarded + soup = soup.currentConditions - def retrieve_string(label): - if elem := soup.find("dt", string=label).find_next_sibling(): + # Getting the wind specifically, because otherwise it starts being ugly very quickly + wind = soup.find("wind") + + def retrieve_string(label, search=None, search_soup=soup): + if elem := search_soup.find(label, string=search): return elem.get_text().strip() return None - observed_string = retrieve_string("Date: ") - temperature_string = retrieve_string("Temperature:") - condition_string = retrieve_string("Condition:") - pressure_string = retrieve_string("Pressure:") - tendency_string = retrieve_string("Tendency:") - wind_string = retrieve_string("Wind:") - humidity_string = retrieve_string("Humidity:") + def retrieve_attribute(label, key, search_soup=soup): + if attr := search_soup.find(label)[key]: + return attr.strip() + return None + + observed_string = retrieve_string("textSummary", re.compile("(EST|EDT)")) + temperature_string = retrieve_string("temperature") + "°C" + condition_string = retrieve_string("condition") + pressure_string = retrieve_string("pressure") + " kPa" + tendency_string = retrieve_attribute("pressure", "tendency") + wind_string = ( + retrieve_string("direction", search_soup=wind) + + " " + + retrieve_string("speed", search_soup=wind) + + " " + + retrieve_attribute("speed", "units", wind) + ) + humidity_string = retrieve_string("relativeHumidity") feels_like_values = { "temp": re.search(r"-?\d+\.\d", temperature_string), @@ -175,7 +190,7 @@ def retrieve_string(label): weather_now = discord.Embed( title="Current Weather", - description=f"Conditions observed at {observed_string or '[REDACTED]'}", + description=f"Conditions observed on {observed_string or '[REDACTED]'}", colour=0x7EC0EE, ) weather_now.add_field(name="Temperature", value=temperature_string or "n/a", inline=True) @@ -236,16 +251,6 @@ def no_alerts_embed(title: str | None = None): # Sending final message await ctx.send(embed=weather_alert) - @commands.command() - async def wttr(self, ctx: commands.Context): - """Retrieves Montreal's weather forecast from wttr.in""" - await ctx.send(self.bot.config.wttr_in_tpl.format(round(time.time()))) - - @commands.command(aliases=["wttrmoon"]) - async def wttr_moon(self, ctx: commands.Context): - """Retrieves the current moon phase from wttr.in/moon""" - await ctx.send(WTTR_IN_MOON_URL) - @commands.command() async def course(self, ctx: commands.Context, *, query: str): """Prints a summary of the queried course, taken from the course diff --git a/canary/config/config.py b/canary/config/config.py index 5e09dd4df..57d241ba7 100644 --- a/canary/config/config.py +++ b/canary/config/config.py @@ -221,9 +221,8 @@ class Config(BaseSettings): "&sort_by=field_subject_code" "&page={}" ) - gc_weather_url: str = "http://weather.gc.ca/city/pages/qc-147_metric_e.html" + gc_weather_url: str = "https://dd.weather.gc.ca/citypage_weather/xml/QC/s0000635_e.xml" gc_weather_alert_url: str = "https://weather.gc.ca/warnings/report_e.html?qc67" - wttr_in_tpl: str = "http://wttr.in/Montreal_2mpq_lang=en.png?_m" tepid_url: str = "https://tepid.science.mcgill.ca:8443/tepid/screensaver/queues/status" # Subscription configuration From 55a261a0b76d5aef76797de6f3b571daa6b940b1 Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Wed, 4 Sep 2024 19:39:09 -0400 Subject: [PATCH 115/127] update dependencies --- poetry.lock | 1979 ++++++++++++++++++++++++++---------------------- pyproject.toml | 30 +- 2 files changed, 1092 insertions(+), 917 deletions(-) diff --git a/poetry.lock b/poetry.lock index 6ca4f9d75..eceaeec9d 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,10 +1,9 @@ -# This file is automatically @generated by Poetry and should not be changed by hand. +# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand. [[package]] name = "aiohttp" version = "3.7.4.post0" description = "Async http client/server framework (asyncio)" -category = "main" optional = false python-versions = ">=3.6" files = [ @@ -62,7 +61,6 @@ speedups = ["aiodns", "brotlipy", "cchardet"] name = "aiosqlite" version = "0.19.0" description = "asyncio bridge to the standard sqlite3 module" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -78,7 +76,6 @@ docs = ["sphinx (==6.1.3)", "sphinx-mdinclude (==0.5.3)"] name = "async-timeout" version = "3.0.1" description = "Timeout context manager for asyncio programs" -category = "main" optional = false python-versions = ">=3.5.3" files = [ @@ -88,39 +85,41 @@ files = [ [[package]] name = "attrs" -version = "23.1.0" +version = "24.2.0" description = "Classes Without Boilerplate" -category = "main" optional = false python-versions = ">=3.7" files = [ - {file = "attrs-23.1.0-py3-none-any.whl", hash = "sha256:1f28b4522cdc2fb4256ac1a020c78acf9cba2c6b461ccd2c126f3aa8e8335d04"}, - {file = "attrs-23.1.0.tar.gz", hash = "sha256:6279836d581513a26f1bf235f9acd333bc9115683f14f7e8fae46c98fc50e015"}, + {file = "attrs-24.2.0-py3-none-any.whl", hash = "sha256:81921eb96de3191c8258c199618104dd27ac608d9366f5e35d011eae1867ede2"}, + {file = "attrs-24.2.0.tar.gz", hash = "sha256:5cfb1b9148b5b086569baec03f20d7b6bf3bcacc9a42bebf87ffaaca362f6346"}, ] [package.extras] -cov = ["attrs[tests]", "coverage[toml] (>=5.3)"] -dev = ["attrs[docs,tests]", "pre-commit"] -docs = ["furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier", "zope-interface"] -tests = ["attrs[tests-no-zope]", "zope-interface"] -tests-no-zope = ["cloudpickle", "hypothesis", "mypy (>=1.1.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] +benchmark = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-codspeed", "pytest-mypy-plugins", "pytest-xdist[psutil]"] +cov = ["cloudpickle", "coverage[toml] (>=5.3)", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] +dev = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pre-commit", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] +docs = ["cogapp", "furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier (<24.7)"] +tests = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] +tests-mypy = ["mypy (>=1.11.1)", "pytest-mypy-plugins"] [[package]] name = "beautifulsoup4" -version = "4.12.2" +version = "4.12.3" description = "Screen-scraping library" -category = "main" optional = false python-versions = ">=3.6.0" files = [ - {file = "beautifulsoup4-4.12.2-py3-none-any.whl", hash = "sha256:bd2520ca0d9d7d12694a53d44ac482d181b4ec1888909b035a3dbf40d0f57d4a"}, - {file = "beautifulsoup4-4.12.2.tar.gz", hash = "sha256:492bbc69dca35d12daac71c4db1bfff0c876c00ef4a2ffacce226d4638eb72da"}, + {file = "beautifulsoup4-4.12.3-py3-none-any.whl", hash = "sha256:b80878c9f40111313e55da8ba20bdba06d8fa3969fc68304167741bbf9e082ed"}, + {file = "beautifulsoup4-4.12.3.tar.gz", hash = "sha256:74e3d1928edc070d21748185c46e3fb33490f22f52a3addee9aee0f4f7781051"}, ] [package.dependencies] soupsieve = ">1.2" [package.extras] +cchardet = ["cchardet"] +chardet = ["chardet"] +charset-normalizer = ["charset-normalizer"] html5lib = ["html5lib"] lxml = ["lxml"] @@ -128,7 +127,6 @@ lxml = ["lxml"] name = "bidict" version = "0.22.1" description = "The bidirectional mapping library for Python." -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -143,37 +141,33 @@ test = ["hypothesis", "pytest", "pytest-benchmark[histogram]", "pytest-cov", "py [[package]] name = "black" -version = "23.3.0" +version = "24.8.0" description = "The uncompromising code formatter." -category = "dev" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "black-23.3.0-cp310-cp310-macosx_10_16_arm64.whl", hash = "sha256:0945e13506be58bf7db93ee5853243eb368ace1c08a24c65ce108986eac65915"}, - {file = "black-23.3.0-cp310-cp310-macosx_10_16_universal2.whl", hash = "sha256:67de8d0c209eb5b330cce2469503de11bca4085880d62f1628bd9972cc3366b9"}, - {file = "black-23.3.0-cp310-cp310-macosx_10_16_x86_64.whl", hash = "sha256:7c3eb7cea23904399866c55826b31c1f55bbcd3890ce22ff70466b907b6775c2"}, - {file = "black-23.3.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:32daa9783106c28815d05b724238e30718f34155653d4d6e125dc7daec8e260c"}, - {file = "black-23.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:35d1381d7a22cc5b2be2f72c7dfdae4072a3336060635718cc7e1ede24221d6c"}, - {file = "black-23.3.0-cp311-cp311-macosx_10_16_arm64.whl", hash = "sha256:a8a968125d0a6a404842fa1bf0b349a568634f856aa08ffaff40ae0dfa52e7c6"}, - {file = "black-23.3.0-cp311-cp311-macosx_10_16_universal2.whl", hash = "sha256:c7ab5790333c448903c4b721b59c0d80b11fe5e9803d8703e84dcb8da56fec1b"}, - {file = "black-23.3.0-cp311-cp311-macosx_10_16_x86_64.whl", hash = "sha256:a6f6886c9869d4daae2d1715ce34a19bbc4b95006d20ed785ca00fa03cba312d"}, - {file = "black-23.3.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6f3c333ea1dd6771b2d3777482429864f8e258899f6ff05826c3a4fcc5ce3f70"}, - {file = "black-23.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:11c410f71b876f961d1de77b9699ad19f939094c3a677323f43d7a29855fe326"}, - {file = "black-23.3.0-cp37-cp37m-macosx_10_16_x86_64.whl", hash = "sha256:1d06691f1eb8de91cd1b322f21e3bfc9efe0c7ca1f0e1eb1db44ea367dff656b"}, - {file = "black-23.3.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:50cb33cac881766a5cd9913e10ff75b1e8eb71babf4c7104f2e9c52da1fb7de2"}, - {file = "black-23.3.0-cp37-cp37m-win_amd64.whl", hash = "sha256:e114420bf26b90d4b9daa597351337762b63039752bdf72bf361364c1aa05925"}, - {file = "black-23.3.0-cp38-cp38-macosx_10_16_arm64.whl", hash = "sha256:48f9d345675bb7fbc3dd85821b12487e1b9a75242028adad0333ce36ed2a6d27"}, - {file = "black-23.3.0-cp38-cp38-macosx_10_16_universal2.whl", hash = "sha256:714290490c18fb0126baa0fca0a54ee795f7502b44177e1ce7624ba1c00f2331"}, - {file = "black-23.3.0-cp38-cp38-macosx_10_16_x86_64.whl", hash = "sha256:064101748afa12ad2291c2b91c960be28b817c0c7eaa35bec09cc63aa56493c5"}, - {file = "black-23.3.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:562bd3a70495facf56814293149e51aa1be9931567474993c7942ff7d3533961"}, - {file = "black-23.3.0-cp38-cp38-win_amd64.whl", hash = "sha256:e198cf27888ad6f4ff331ca1c48ffc038848ea9f031a3b40ba36aced7e22f2c8"}, - {file = "black-23.3.0-cp39-cp39-macosx_10_16_arm64.whl", hash = "sha256:3238f2aacf827d18d26db07524e44741233ae09a584273aa059066d644ca7b30"}, - {file = "black-23.3.0-cp39-cp39-macosx_10_16_universal2.whl", hash = "sha256:f0bd2f4a58d6666500542b26354978218a9babcdc972722f4bf90779524515f3"}, - {file = "black-23.3.0-cp39-cp39-macosx_10_16_x86_64.whl", hash = "sha256:92c543f6854c28a3c7f39f4d9b7694f9a6eb9d3c5e2ece488c327b6e7ea9b266"}, - {file = "black-23.3.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3a150542a204124ed00683f0db1f5cf1c2aaaa9cc3495b7a3b5976fb136090ab"}, - {file = "black-23.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:6b39abdfb402002b8a7d030ccc85cf5afff64ee90fa4c5aebc531e3ad0175ddb"}, - {file = "black-23.3.0-py3-none-any.whl", hash = "sha256:ec751418022185b0c1bb7d7736e6933d40bbb14c14a0abcf9123d1b159f98dd4"}, - {file = "black-23.3.0.tar.gz", hash = "sha256:1c7b8d606e728a41ea1ccbd7264677e494e87cf630e399262ced92d4a8dac940"}, + {file = "black-24.8.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:09cdeb74d494ec023ded657f7092ba518e8cf78fa8386155e4a03fdcc44679e6"}, + {file = "black-24.8.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:81c6742da39f33b08e791da38410f32e27d632260e599df7245cccee2064afeb"}, + {file = "black-24.8.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:707a1ca89221bc8a1a64fb5e15ef39cd755633daa672a9db7498d1c19de66a42"}, + {file = "black-24.8.0-cp310-cp310-win_amd64.whl", hash = "sha256:d6417535d99c37cee4091a2f24eb2b6d5ec42b144d50f1f2e436d9fe1916fe1a"}, + {file = "black-24.8.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:fb6e2c0b86bbd43dee042e48059c9ad7830abd5c94b0bc518c0eeec57c3eddc1"}, + {file = "black-24.8.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:837fd281f1908d0076844bc2b801ad2d369c78c45cf800cad7b61686051041af"}, + {file = "black-24.8.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:62e8730977f0b77998029da7971fa896ceefa2c4c4933fcd593fa599ecbf97a4"}, + {file = "black-24.8.0-cp311-cp311-win_amd64.whl", hash = "sha256:72901b4913cbac8972ad911dc4098d5753704d1f3c56e44ae8dce99eecb0e3af"}, + {file = "black-24.8.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:7c046c1d1eeb7aea9335da62472481d3bbf3fd986e093cffd35f4385c94ae368"}, + {file = "black-24.8.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:649f6d84ccbae73ab767e206772cc2d7a393a001070a4c814a546afd0d423aed"}, + {file = "black-24.8.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2b59b250fdba5f9a9cd9d0ece6e6d993d91ce877d121d161e4698af3eb9c1018"}, + {file = "black-24.8.0-cp312-cp312-win_amd64.whl", hash = "sha256:6e55d30d44bed36593c3163b9bc63bf58b3b30e4611e4d88a0c3c239930ed5b2"}, + {file = "black-24.8.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:505289f17ceda596658ae81b61ebbe2d9b25aa78067035184ed0a9d855d18afd"}, + {file = "black-24.8.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:b19c9ad992c7883ad84c9b22aaa73562a16b819c1d8db7a1a1a49fb7ec13c7d2"}, + {file = "black-24.8.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1f13f7f386f86f8121d76599114bb8c17b69d962137fc70efe56137727c7047e"}, + {file = "black-24.8.0-cp38-cp38-win_amd64.whl", hash = "sha256:f490dbd59680d809ca31efdae20e634f3fae27fba3ce0ba3208333b713bc3920"}, + {file = "black-24.8.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:eab4dd44ce80dea27dc69db40dab62d4ca96112f87996bca68cd75639aeb2e4c"}, + {file = "black-24.8.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3c4285573d4897a7610054af5a890bde7c65cb466040c5f0c8b732812d7f0e5e"}, + {file = "black-24.8.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9e84e33b37be070ba135176c123ae52a51f82306def9f7d063ee302ecab2cf47"}, + {file = "black-24.8.0-cp39-cp39-win_amd64.whl", hash = "sha256:73bbf84ed136e45d451a260c6b73ed674652f90a2b3211d6a35e78054563a9bb"}, + {file = "black-24.8.0-py3-none-any.whl", hash = "sha256:972085c618ee94f402da1af548a4f218c754ea7e5dc70acb168bfaca4c2542ed"}, + {file = "black-24.8.0.tar.gz", hash = "sha256:2500945420b6784c38b9ee885af039f5e7471ef284ab03fa35ecdde4688cd83f"}, ] [package.dependencies] @@ -183,97 +177,230 @@ packaging = ">=22.0" pathspec = ">=0.9.0" platformdirs = ">=2" tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} +typing-extensions = {version = ">=4.0.1", markers = "python_version < \"3.11\""} [package.extras] colorama = ["colorama (>=0.4.3)"] -d = ["aiohttp (>=3.7.4)"] +d = ["aiohttp (>=3.7.4)", "aiohttp (>=3.7.4,!=3.9.0)"] jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"] uvloop = ["uvloop (>=0.15.2)"] +[[package]] +name = "brotli" +version = "1.1.0" +description = "Python bindings for the Brotli compression library" +optional = false +python-versions = "*" +files = [ + {file = "Brotli-1.1.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:e1140c64812cb9b06c922e77f1c26a75ec5e3f0fb2bf92cc8c58720dec276752"}, + {file = "Brotli-1.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c8fd5270e906eef71d4a8d19b7c6a43760c6abcfcc10c9101d14eb2357418de9"}, + {file = "Brotli-1.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1ae56aca0402a0f9a3431cddda62ad71666ca9d4dc3a10a142b9dce2e3c0cda3"}, + {file = "Brotli-1.1.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:43ce1b9935bfa1ede40028054d7f48b5469cd02733a365eec8a329ffd342915d"}, + {file = "Brotli-1.1.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:7c4855522edb2e6ae7fdb58e07c3ba9111e7621a8956f481c68d5d979c93032e"}, + {file = "Brotli-1.1.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:38025d9f30cf4634f8309c6874ef871b841eb3c347e90b0851f63d1ded5212da"}, + {file = "Brotli-1.1.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:e6a904cb26bfefc2f0a6f240bdf5233be78cd2488900a2f846f3c3ac8489ab80"}, + {file = "Brotli-1.1.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:a37b8f0391212d29b3a91a799c8e4a2855e0576911cdfb2515487e30e322253d"}, + {file = "Brotli-1.1.0-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:e84799f09591700a4154154cab9787452925578841a94321d5ee8fb9a9a328f0"}, + {file = "Brotli-1.1.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:f66b5337fa213f1da0d9000bc8dc0cb5b896b726eefd9c6046f699b169c41b9e"}, + {file = "Brotli-1.1.0-cp310-cp310-win32.whl", hash = "sha256:be36e3d172dc816333f33520154d708a2657ea63762ec16b62ece02ab5e4daf2"}, + {file = "Brotli-1.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:0c6244521dda65ea562d5a69b9a26120769b7a9fb3db2fe9545935ed6735b128"}, + {file = "Brotli-1.1.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:a3daabb76a78f829cafc365531c972016e4aa8d5b4bf60660ad8ecee19df7ccc"}, + {file = "Brotli-1.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c8146669223164fc87a7e3de9f81e9423c67a79d6b3447994dfb9c95da16e2d6"}, + {file = "Brotli-1.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:30924eb4c57903d5a7526b08ef4a584acc22ab1ffa085faceb521521d2de32dd"}, + {file = "Brotli-1.1.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ceb64bbc6eac5a140ca649003756940f8d6a7c444a68af170b3187623b43bebf"}, + {file = "Brotli-1.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a469274ad18dc0e4d316eefa616d1d0c2ff9da369af19fa6f3daa4f09671fd61"}, + {file = "Brotli-1.1.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:524f35912131cc2cabb00edfd8d573b07f2d9f21fa824bd3fb19725a9cf06327"}, + {file = "Brotli-1.1.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:5b3cc074004d968722f51e550b41a27be656ec48f8afaeeb45ebf65b561481dd"}, + {file = "Brotli-1.1.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:19c116e796420b0cee3da1ccec3b764ed2952ccfcc298b55a10e5610ad7885f9"}, + {file = "Brotli-1.1.0-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:510b5b1bfbe20e1a7b3baf5fed9e9451873559a976c1a78eebaa3b86c57b4265"}, + {file = "Brotli-1.1.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:a1fd8a29719ccce974d523580987b7f8229aeace506952fa9ce1d53a033873c8"}, + {file = "Brotli-1.1.0-cp311-cp311-win32.whl", hash = "sha256:39da8adedf6942d76dc3e46653e52df937a3c4d6d18fdc94a7c29d263b1f5b50"}, + {file = "Brotli-1.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:aac0411d20e345dc0920bdec5548e438e999ff68d77564d5e9463a7ca9d3e7b1"}, + {file = "Brotli-1.1.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:316cc9b17edf613ac76b1f1f305d2a748f1b976b033b049a6ecdfd5612c70409"}, + {file = "Brotli-1.1.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:caf9ee9a5775f3111642d33b86237b05808dafcd6268faa492250e9b78046eb2"}, + {file = "Brotli-1.1.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:70051525001750221daa10907c77830bc889cb6d865cc0b813d9db7fefc21451"}, + {file = "Brotli-1.1.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7f4bf76817c14aa98cc6697ac02f3972cb8c3da93e9ef16b9c66573a68014f91"}, + {file = "Brotli-1.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d0c5516f0aed654134a2fc936325cc2e642f8a0e096d075209672eb321cff408"}, + {file = "Brotli-1.1.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6c3020404e0b5eefd7c9485ccf8393cfb75ec38ce75586e046573c9dc29967a0"}, + {file = "Brotli-1.1.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:4ed11165dd45ce798d99a136808a794a748d5dc38511303239d4e2363c0695dc"}, + {file = "Brotli-1.1.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:4093c631e96fdd49e0377a9c167bfd75b6d0bad2ace734c6eb20b348bc3ea180"}, + {file = "Brotli-1.1.0-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:7e4c4629ddad63006efa0ef968c8e4751c5868ff0b1c5c40f76524e894c50248"}, + {file = "Brotli-1.1.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:861bf317735688269936f755fa136a99d1ed526883859f86e41a5d43c61d8966"}, + {file = "Brotli-1.1.0-cp312-cp312-win32.whl", hash = "sha256:5f4d5ea15c9382135076d2fb28dde923352fe02951e66935a9efaac8f10e81b0"}, + {file = "Brotli-1.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:906bc3a79de8c4ae5b86d3d75a8b77e44404b0f4261714306e3ad248d8ab0951"}, + {file = "Brotli-1.1.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:a090ca607cbb6a34b0391776f0cb48062081f5f60ddcce5d11838e67a01928d1"}, + {file = "Brotli-1.1.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2de9d02f5bda03d27ede52e8cfe7b865b066fa49258cbab568720aa5be80a47d"}, + {file = "Brotli-1.1.0-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2333e30a5e00fe0fe55903c8832e08ee9c3b1382aacf4db26664a16528d51b4b"}, + {file = "Brotli-1.1.0-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4d4a848d1837973bf0f4b5e54e3bec977d99be36a7895c61abb659301b02c112"}, + {file = "Brotli-1.1.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:fdc3ff3bfccdc6b9cc7c342c03aa2400683f0cb891d46e94b64a197910dc4064"}, + {file = "Brotli-1.1.0-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:5eeb539606f18a0b232d4ba45adccde4125592f3f636a6182b4a8a436548b914"}, + {file = "Brotli-1.1.0-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:fd5f17ff8f14003595ab414e45fce13d073e0762394f957182e69035c9f3d7c2"}, + {file = "Brotli-1.1.0-cp36-cp36m-musllinux_1_1_ppc64le.whl", hash = "sha256:069a121ac97412d1fe506da790b3e69f52254b9df4eb665cd42460c837193354"}, + {file = "Brotli-1.1.0-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:e93dfc1a1165e385cc8239fab7c036fb2cd8093728cbd85097b284d7b99249a2"}, + {file = "Brotli-1.1.0-cp36-cp36m-win32.whl", hash = "sha256:a599669fd7c47233438a56936988a2478685e74854088ef5293802123b5b2460"}, + {file = "Brotli-1.1.0-cp36-cp36m-win_amd64.whl", hash = "sha256:d143fd47fad1db3d7c27a1b1d66162e855b5d50a89666af46e1679c496e8e579"}, + {file = "Brotli-1.1.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:11d00ed0a83fa22d29bc6b64ef636c4552ebafcef57154b4ddd132f5638fbd1c"}, + {file = "Brotli-1.1.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f733d788519c7e3e71f0855c96618720f5d3d60c3cb829d8bbb722dddce37985"}, + {file = "Brotli-1.1.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:929811df5462e182b13920da56c6e0284af407d1de637d8e536c5cd00a7daf60"}, + {file = "Brotli-1.1.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:0b63b949ff929fbc2d6d3ce0e924c9b93c9785d877a21a1b678877ffbbc4423a"}, + {file = "Brotli-1.1.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:d192f0f30804e55db0d0e0a35d83a9fead0e9a359a9ed0285dbacea60cc10a84"}, + {file = "Brotli-1.1.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:f296c40e23065d0d6650c4aefe7470d2a25fffda489bcc3eb66083f3ac9f6643"}, + {file = "Brotli-1.1.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:919e32f147ae93a09fe064d77d5ebf4e35502a8df75c29fb05788528e330fe74"}, + {file = "Brotli-1.1.0-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:23032ae55523cc7bccb4f6a0bf368cd25ad9bcdcc1990b64a647e7bbcce9cb5b"}, + {file = "Brotli-1.1.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:224e57f6eac61cc449f498cc5f0e1725ba2071a3d4f48d5d9dffba42db196438"}, + {file = "Brotli-1.1.0-cp37-cp37m-win32.whl", hash = "sha256:587ca6d3cef6e4e868102672d3bd9dc9698c309ba56d41c2b9c85bbb903cdb95"}, + {file = "Brotli-1.1.0-cp37-cp37m-win_amd64.whl", hash = "sha256:2954c1c23f81c2eaf0b0717d9380bd348578a94161a65b3a2afc62c86467dd68"}, + {file = "Brotli-1.1.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:efa8b278894b14d6da122a72fefcebc28445f2d3f880ac59d46c90f4c13be9a3"}, + {file = "Brotli-1.1.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:03d20af184290887bdea3f0f78c4f737d126c74dc2f3ccadf07e54ceca3bf208"}, + {file = "Brotli-1.1.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6172447e1b368dcbc458925e5ddaf9113477b0ed542df258d84fa28fc45ceea7"}, + {file = "Brotli-1.1.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a743e5a28af5f70f9c080380a5f908d4d21d40e8f0e0c8901604d15cfa9ba751"}, + {file = "Brotli-1.1.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:0541e747cce78e24ea12d69176f6a7ddb690e62c425e01d31cc065e69ce55b48"}, + {file = "Brotli-1.1.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:cdbc1fc1bc0bff1cef838eafe581b55bfbffaed4ed0318b724d0b71d4d377619"}, + {file = "Brotli-1.1.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:890b5a14ce214389b2cc36ce82f3093f96f4cc730c1cffdbefff77a7c71f2a97"}, + {file = "Brotli-1.1.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:1ab4fbee0b2d9098c74f3057b2bc055a8bd92ccf02f65944a241b4349229185a"}, + {file = "Brotli-1.1.0-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:141bd4d93984070e097521ed07e2575b46f817d08f9fa42b16b9b5f27b5ac088"}, + {file = "Brotli-1.1.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:fce1473f3ccc4187f75b4690cfc922628aed4d3dd013d047f95a9b3919a86596"}, + {file = "Brotli-1.1.0-cp38-cp38-win32.whl", hash = "sha256:db85ecf4e609a48f4b29055f1e144231b90edc90af7481aa731ba2d059226b1b"}, + {file = "Brotli-1.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:3d7954194c36e304e1523f55d7042c59dc53ec20dd4e9ea9d151f1b62b4415c0"}, + {file = "Brotli-1.1.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:5fb2ce4b8045c78ebbc7b8f3c15062e435d47e7393cc57c25115cfd49883747a"}, + {file = "Brotli-1.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:7905193081db9bfa73b1219140b3d315831cbff0d8941f22da695832f0dd188f"}, + {file = "Brotli-1.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a77def80806c421b4b0af06f45d65a136e7ac0bdca3c09d9e2ea4e515367c7e9"}, + {file = "Brotli-1.1.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8dadd1314583ec0bf2d1379f7008ad627cd6336625d6679cf2f8e67081b83acf"}, + {file = "Brotli-1.1.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:901032ff242d479a0efa956d853d16875d42157f98951c0230f69e69f9c09bac"}, + {file = "Brotli-1.1.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:22fc2a8549ffe699bfba2256ab2ed0421a7b8fadff114a3d201794e45a9ff578"}, + {file = "Brotli-1.1.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ae15b066e5ad21366600ebec29a7ccbc86812ed267e4b28e860b8ca16a2bc474"}, + {file = "Brotli-1.1.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:949f3b7c29912693cee0afcf09acd6ebc04c57af949d9bf77d6101ebb61e388c"}, + {file = "Brotli-1.1.0-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:89f4988c7203739d48c6f806f1e87a1d96e0806d44f0fba61dba81392c9e474d"}, + {file = "Brotli-1.1.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:de6551e370ef19f8de1807d0a9aa2cdfdce2e85ce88b122fe9f6b2b076837e59"}, + {file = "Brotli-1.1.0-cp39-cp39-win32.whl", hash = "sha256:f0d8a7a6b5983c2496e364b969f0e526647a06b075d034f3297dc66f3b360c64"}, + {file = "Brotli-1.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:cdad5b9014d83ca68c25d2e9444e28e967ef16e80f6b436918c700c117a85467"}, + {file = "Brotli-1.1.0.tar.gz", hash = "sha256:81de08ac11bcb85841e440c13611c00b67d3bf82698314928d0b676362546724"}, +] + +[[package]] +name = "brotlicffi" +version = "1.1.0.0" +description = "Python CFFI bindings to the Brotli library" +optional = false +python-versions = ">=3.7" +files = [ + {file = "brotlicffi-1.1.0.0-cp37-abi3-macosx_10_9_x86_64.whl", hash = "sha256:9b7ae6bd1a3f0df532b6d67ff674099a96d22bc0948955cb338488c31bfb8851"}, + {file = "brotlicffi-1.1.0.0-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:19ffc919fa4fc6ace69286e0a23b3789b4219058313cf9b45625016bf7ff996b"}, + {file = "brotlicffi-1.1.0.0-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9feb210d932ffe7798ee62e6145d3a757eb6233aa9a4e7db78dd3690d7755814"}, + {file = "brotlicffi-1.1.0.0-cp37-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:84763dbdef5dd5c24b75597a77e1b30c66604725707565188ba54bab4f114820"}, + {file = "brotlicffi-1.1.0.0-cp37-abi3-win32.whl", hash = "sha256:1b12b50e07c3911e1efa3a8971543e7648100713d4e0971b13631cce22c587eb"}, + {file = "brotlicffi-1.1.0.0-cp37-abi3-win_amd64.whl", hash = "sha256:994a4f0681bb6c6c3b0925530a1926b7a189d878e6e5e38fae8efa47c5d9c613"}, + {file = "brotlicffi-1.1.0.0-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:2e4aeb0bd2540cb91b069dbdd54d458da8c4334ceaf2d25df2f4af576d6766ca"}, + {file = "brotlicffi-1.1.0.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4b7b0033b0d37bb33009fb2fef73310e432e76f688af76c156b3594389d81391"}, + {file = "brotlicffi-1.1.0.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:54a07bb2374a1eba8ebb52b6fafffa2afd3c4df85ddd38fcc0511f2bb387c2a8"}, + {file = "brotlicffi-1.1.0.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7901a7dc4b88f1c1475de59ae9be59799db1007b7d059817948d8e4f12e24e35"}, + {file = "brotlicffi-1.1.0.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:ce01c7316aebc7fce59da734286148b1d1b9455f89cf2c8a4dfce7d41db55c2d"}, + {file = "brotlicffi-1.1.0.0-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:246f1d1a90279bb6069de3de8d75a8856e073b8ff0b09dcca18ccc14cec85979"}, + {file = "brotlicffi-1.1.0.0-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cc4bc5d82bc56ebd8b514fb8350cfac4627d6b0743382e46d033976a5f80fab6"}, + {file = "brotlicffi-1.1.0.0-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:37c26ecb14386a44b118ce36e546ce307f4810bc9598a6e6cb4f7fca725ae7e6"}, + {file = "brotlicffi-1.1.0.0-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ca72968ae4eaf6470498d5c2887073f7efe3b1e7d7ec8be11a06a79cc810e990"}, + {file = "brotlicffi-1.1.0.0-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:add0de5b9ad9e9aa293c3aa4e9deb2b61e99ad6c1634e01d01d98c03e6a354cc"}, + {file = "brotlicffi-1.1.0.0-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:9b6068e0f3769992d6b622a1cd2e7835eae3cf8d9da123d7f51ca9c1e9c333e5"}, + {file = "brotlicffi-1.1.0.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8557a8559509b61e65083f8782329188a250102372576093c88930c875a69838"}, + {file = "brotlicffi-1.1.0.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2a7ae37e5d79c5bdfb5b4b99f2715a6035e6c5bf538c3746abc8e26694f92f33"}, + {file = "brotlicffi-1.1.0.0-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:391151ec86bb1c683835980f4816272a87eaddc46bb91cbf44f62228b84d8cca"}, + {file = "brotlicffi-1.1.0.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:2f3711be9290f0453de8eed5275d93d286abe26b08ab4a35d7452caa1fef532f"}, + {file = "brotlicffi-1.1.0.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:1a807d760763e398bbf2c6394ae9da5815901aa93ee0a37bca5efe78d4ee3171"}, + {file = "brotlicffi-1.1.0.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fa8ca0623b26c94fccc3a1fdd895be1743b838f3917300506d04aa3346fd2a14"}, + {file = "brotlicffi-1.1.0.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3de0cf28a53a3238b252aca9fed1593e9d36c1d116748013339f0949bfc84112"}, + {file = "brotlicffi-1.1.0.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6be5ec0e88a4925c91f3dea2bb0013b3a2accda6f77238f76a34a1ea532a1cb0"}, + {file = "brotlicffi-1.1.0.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:d9eb71bb1085d996244439154387266fd23d6ad37161f6f52f1cd41dd95a3808"}, + {file = "brotlicffi-1.1.0.0.tar.gz", hash = "sha256:b77827a689905143f87915310b93b273ab17888fd43ef350d4832c4a71083c13"}, +] + +[package.dependencies] +cffi = ">=1.0.0" + [[package]] name = "certifi" -version = "2023.5.7" +version = "2024.8.30" description = "Python package for providing Mozilla's CA Bundle." -category = "main" optional = false python-versions = ">=3.6" files = [ - {file = "certifi-2023.5.7-py3-none-any.whl", hash = "sha256:c6c2e98f5c7869efca1f8916fed228dd91539f9f1b444c314c06eef02980c716"}, - {file = "certifi-2023.5.7.tar.gz", hash = "sha256:0f0d56dc5a6ad56fd4ba36484d6cc34451e1c6548c61daad8c320169f91eddc7"}, + {file = "certifi-2024.8.30-py3-none-any.whl", hash = "sha256:922820b53db7a7257ffbda3f597266d435245903d80737e34f8a45ff3e3230d8"}, + {file = "certifi-2024.8.30.tar.gz", hash = "sha256:bec941d2aa8195e248a60b31ff9f0558284cf01a52591ceda73ea9afffd69fd9"}, ] [[package]] name = "cffi" -version = "1.15.1" +version = "1.17.1" description = "Foreign Function Interface for Python calling C code." -category = "main" optional = false -python-versions = "*" +python-versions = ">=3.8" files = [ - {file = "cffi-1.15.1-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:a66d3508133af6e8548451b25058d5812812ec3798c886bf38ed24a98216fab2"}, - {file = "cffi-1.15.1-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:470c103ae716238bbe698d67ad020e1db9d9dba34fa5a899b5e21577e6d52ed2"}, - {file = "cffi-1.15.1-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:9ad5db27f9cabae298d151c85cf2bad1d359a1b9c686a275df03385758e2f914"}, - {file = "cffi-1.15.1-cp27-cp27m-win32.whl", hash = "sha256:b3bbeb01c2b273cca1e1e0c5df57f12dce9a4dd331b4fa1635b8bec26350bde3"}, - {file = "cffi-1.15.1-cp27-cp27m-win_amd64.whl", hash = "sha256:e00b098126fd45523dd056d2efba6c5a63b71ffe9f2bbe1a4fe1716e1d0c331e"}, - {file = "cffi-1.15.1-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:d61f4695e6c866a23a21acab0509af1cdfd2c013cf256bbf5b6b5e2695827162"}, - {file = "cffi-1.15.1-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:ed9cb427ba5504c1dc15ede7d516b84757c3e3d7868ccc85121d9310d27eed0b"}, - {file = "cffi-1.15.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:39d39875251ca8f612b6f33e6b1195af86d1b3e60086068be9cc053aa4376e21"}, - {file = "cffi-1.15.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:285d29981935eb726a4399badae8f0ffdff4f5050eaa6d0cfc3f64b857b77185"}, - {file = "cffi-1.15.1-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3eb6971dcff08619f8d91607cfc726518b6fa2a9eba42856be181c6d0d9515fd"}, - {file = "cffi-1.15.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:21157295583fe8943475029ed5abdcf71eb3911894724e360acff1d61c1d54bc"}, - {file = "cffi-1.15.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5635bd9cb9731e6d4a1132a498dd34f764034a8ce60cef4f5319c0541159392f"}, - {file = "cffi-1.15.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2012c72d854c2d03e45d06ae57f40d78e5770d252f195b93f581acf3ba44496e"}, - {file = "cffi-1.15.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd86c085fae2efd48ac91dd7ccffcfc0571387fe1193d33b6394db7ef31fe2a4"}, - {file = "cffi-1.15.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:fa6693661a4c91757f4412306191b6dc88c1703f780c8234035eac011922bc01"}, - {file = "cffi-1.15.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:59c0b02d0a6c384d453fece7566d1c7e6b7bae4fc5874ef2ef46d56776d61c9e"}, - {file = "cffi-1.15.1-cp310-cp310-win32.whl", hash = "sha256:cba9d6b9a7d64d4bd46167096fc9d2f835e25d7e4c121fb2ddfc6528fb0413b2"}, - {file = "cffi-1.15.1-cp310-cp310-win_amd64.whl", hash = "sha256:ce4bcc037df4fc5e3d184794f27bdaab018943698f4ca31630bc7f84a7b69c6d"}, - {file = "cffi-1.15.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3d08afd128ddaa624a48cf2b859afef385b720bb4b43df214f85616922e6a5ac"}, - {file = "cffi-1.15.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3799aecf2e17cf585d977b780ce79ff0dc9b78d799fc694221ce814c2c19db83"}, - {file = "cffi-1.15.1-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a591fe9e525846e4d154205572a029f653ada1a78b93697f3b5a8f1f2bc055b9"}, - {file = "cffi-1.15.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3548db281cd7d2561c9ad9984681c95f7b0e38881201e157833a2342c30d5e8c"}, - {file = "cffi-1.15.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:91fc98adde3d7881af9b59ed0294046f3806221863722ba7d8d120c575314325"}, - {file = "cffi-1.15.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:94411f22c3985acaec6f83c6df553f2dbe17b698cc7f8ae751ff2237d96b9e3c"}, - {file = "cffi-1.15.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:03425bdae262c76aad70202debd780501fabeaca237cdfddc008987c0e0f59ef"}, - {file = "cffi-1.15.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:cc4d65aeeaa04136a12677d3dd0b1c0c94dc43abac5860ab33cceb42b801c1e8"}, - {file = "cffi-1.15.1-cp311-cp311-win32.whl", hash = "sha256:a0f100c8912c114ff53e1202d0078b425bee3649ae34d7b070e9697f93c5d52d"}, - {file = "cffi-1.15.1-cp311-cp311-win_amd64.whl", hash = "sha256:04ed324bda3cda42b9b695d51bb7d54b680b9719cfab04227cdd1e04e5de3104"}, - {file = "cffi-1.15.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50a74364d85fd319352182ef59c5c790484a336f6db772c1a9231f1c3ed0cbd7"}, - {file = "cffi-1.15.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e263d77ee3dd201c3a142934a086a4450861778baaeeb45db4591ef65550b0a6"}, - {file = "cffi-1.15.1-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cec7d9412a9102bdc577382c3929b337320c4c4c4849f2c5cdd14d7368c5562d"}, - {file = "cffi-1.15.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4289fc34b2f5316fbb762d75362931e351941fa95fa18789191b33fc4cf9504a"}, - {file = "cffi-1.15.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:173379135477dc8cac4bc58f45db08ab45d228b3363adb7af79436135d028405"}, - {file = "cffi-1.15.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:6975a3fac6bc83c4a65c9f9fcab9e47019a11d3d2cf7f3c0d03431bf145a941e"}, - {file = "cffi-1.15.1-cp36-cp36m-win32.whl", hash = "sha256:2470043b93ff09bf8fb1d46d1cb756ce6132c54826661a32d4e4d132e1977adf"}, - {file = "cffi-1.15.1-cp36-cp36m-win_amd64.whl", hash = "sha256:30d78fbc8ebf9c92c9b7823ee18eb92f2e6ef79b45ac84db507f52fbe3ec4497"}, - {file = "cffi-1.15.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:198caafb44239b60e252492445da556afafc7d1e3ab7a1fb3f0584ef6d742375"}, - {file = "cffi-1.15.1-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5ef34d190326c3b1f822a5b7a45f6c4535e2f47ed06fec77d3d799c450b2651e"}, - {file = "cffi-1.15.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8102eaf27e1e448db915d08afa8b41d6c7ca7a04b7d73af6514df10a3e74bd82"}, - {file = "cffi-1.15.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5df2768244d19ab7f60546d0c7c63ce1581f7af8b5de3eb3004b9b6fc8a9f84b"}, - {file = "cffi-1.15.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a8c4917bd7ad33e8eb21e9a5bbba979b49d9a97acb3a803092cbc1133e20343c"}, - {file = "cffi-1.15.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0e2642fe3142e4cc4af0799748233ad6da94c62a8bec3a6648bf8ee68b1c7426"}, - {file = "cffi-1.15.1-cp37-cp37m-win32.whl", hash = "sha256:e229a521186c75c8ad9490854fd8bbdd9a0c9aa3a524326b55be83b54d4e0ad9"}, - {file = "cffi-1.15.1-cp37-cp37m-win_amd64.whl", hash = "sha256:a0b71b1b8fbf2b96e41c4d990244165e2c9be83d54962a9a1d118fd8657d2045"}, - {file = "cffi-1.15.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:320dab6e7cb2eacdf0e658569d2575c4dad258c0fcc794f46215e1e39f90f2c3"}, - {file = "cffi-1.15.1-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1e74c6b51a9ed6589199c787bf5f9875612ca4a8a0785fb2d4a84429badaf22a"}, - {file = "cffi-1.15.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a5c84c68147988265e60416b57fc83425a78058853509c1b0629c180094904a5"}, - {file = "cffi-1.15.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3b926aa83d1edb5aa5b427b4053dc420ec295a08e40911296b9eb1b6170f6cca"}, - {file = "cffi-1.15.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:87c450779d0914f2861b8526e035c5e6da0a3199d8f1add1a665e1cbc6fc6d02"}, - {file = "cffi-1.15.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4f2c9f67e9821cad2e5f480bc8d83b8742896f1242dba247911072d4fa94c192"}, - {file = "cffi-1.15.1-cp38-cp38-win32.whl", hash = "sha256:8b7ee99e510d7b66cdb6c593f21c043c248537a32e0bedf02e01e9553a172314"}, - {file = "cffi-1.15.1-cp38-cp38-win_amd64.whl", hash = "sha256:00a9ed42e88df81ffae7a8ab6d9356b371399b91dbdf0c3cb1e84c03a13aceb5"}, - {file = "cffi-1.15.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:54a2db7b78338edd780e7ef7f9f6c442500fb0d41a5a4ea24fff1c929d5af585"}, - {file = "cffi-1.15.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:fcd131dd944808b5bdb38e6f5b53013c5aa4f334c5cad0c72742f6eba4b73db0"}, - {file = "cffi-1.15.1-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7473e861101c9e72452f9bf8acb984947aa1661a7704553a9f6e4baa5ba64415"}, - {file = "cffi-1.15.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6c9a799e985904922a4d207a94eae35c78ebae90e128f0c4e521ce339396be9d"}, - {file = "cffi-1.15.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3bcde07039e586f91b45c88f8583ea7cf7a0770df3a1649627bf598332cb6984"}, - {file = "cffi-1.15.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:33ab79603146aace82c2427da5ca6e58f2b3f2fb5da893ceac0c42218a40be35"}, - {file = "cffi-1.15.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5d598b938678ebf3c67377cdd45e09d431369c3b1a5b331058c338e201f12b27"}, - {file = "cffi-1.15.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:db0fbb9c62743ce59a9ff687eb5f4afbe77e5e8403d6697f7446e5f609976f76"}, - {file = "cffi-1.15.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:98d85c6a2bef81588d9227dde12db8a7f47f639f4a17c9ae08e773aa9c697bf3"}, - {file = "cffi-1.15.1-cp39-cp39-win32.whl", hash = "sha256:40f4774f5a9d4f5e344f31a32b5096977b5d48560c5592e2f3d2c4374bd543ee"}, - {file = "cffi-1.15.1-cp39-cp39-win_amd64.whl", hash = "sha256:70df4e3b545a17496c9b3f41f5115e69a4f2e77e94e1d2a8e1070bc0c38c8a3c"}, - {file = "cffi-1.15.1.tar.gz", hash = "sha256:d400bfb9a37b1351253cb402671cea7e89bdecc294e8016a707f6d1d8ac934f9"}, + {file = "cffi-1.17.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:df8b1c11f177bc2313ec4b2d46baec87a5f3e71fc8b45dab2ee7cae86d9aba14"}, + {file = "cffi-1.17.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8f2cdc858323644ab277e9bb925ad72ae0e67f69e804f4898c070998d50b1a67"}, + {file = "cffi-1.17.1-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:edae79245293e15384b51f88b00613ba9f7198016a5948b5dddf4917d4d26382"}, + {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45398b671ac6d70e67da8e4224a065cec6a93541bb7aebe1b198a61b58c7b702"}, + {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ad9413ccdeda48c5afdae7e4fa2192157e991ff761e7ab8fdd8926f40b160cc3"}, + {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5da5719280082ac6bd9aa7becb3938dc9f9cbd57fac7d2871717b1feb0902ab6"}, + {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2bb1a08b8008b281856e5971307cc386a8e9c5b625ac297e853d36da6efe9c17"}, + {file = "cffi-1.17.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:045d61c734659cc045141be4bae381a41d89b741f795af1dd018bfb532fd0df8"}, + {file = "cffi-1.17.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:6883e737d7d9e4899a8a695e00ec36bd4e5e4f18fabe0aca0efe0a4b44cdb13e"}, + {file = "cffi-1.17.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:6b8b4a92e1c65048ff98cfe1f735ef8f1ceb72e3d5f0c25fdb12087a23da22be"}, + {file = "cffi-1.17.1-cp310-cp310-win32.whl", hash = "sha256:c9c3d058ebabb74db66e431095118094d06abf53284d9c81f27300d0e0d8bc7c"}, + {file = "cffi-1.17.1-cp310-cp310-win_amd64.whl", hash = "sha256:0f048dcf80db46f0098ccac01132761580d28e28bc0f78ae0d58048063317e15"}, + {file = "cffi-1.17.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a45e3c6913c5b87b3ff120dcdc03f6131fa0065027d0ed7ee6190736a74cd401"}, + {file = "cffi-1.17.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:30c5e0cb5ae493c04c8b42916e52ca38079f1b235c2f8ae5f4527b963c401caf"}, + {file = "cffi-1.17.1-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f75c7ab1f9e4aca5414ed4d8e5c0e303a34f4421f8a0d47a4d019ceff0ab6af4"}, + {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a1ed2dd2972641495a3ec98445e09766f077aee98a1c896dcb4ad0d303628e41"}, + {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:46bf43160c1a35f7ec506d254e5c890f3c03648a4dbac12d624e4490a7046cd1"}, + {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a24ed04c8ffd54b0729c07cee15a81d964e6fee0e3d4d342a27b020d22959dc6"}, + {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:610faea79c43e44c71e1ec53a554553fa22321b65fae24889706c0a84d4ad86d"}, + {file = "cffi-1.17.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:a9b15d491f3ad5d692e11f6b71f7857e7835eb677955c00cc0aefcd0669adaf6"}, + {file = "cffi-1.17.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:de2ea4b5833625383e464549fec1bc395c1bdeeb5f25c4a3a82b5a8c756ec22f"}, + {file = "cffi-1.17.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:fc48c783f9c87e60831201f2cce7f3b2e4846bf4d8728eabe54d60700b318a0b"}, + {file = "cffi-1.17.1-cp311-cp311-win32.whl", hash = "sha256:85a950a4ac9c359340d5963966e3e0a94a676bd6245a4b55bc43949eee26a655"}, + {file = "cffi-1.17.1-cp311-cp311-win_amd64.whl", hash = "sha256:caaf0640ef5f5517f49bc275eca1406b0ffa6aa184892812030f04c2abf589a0"}, + {file = "cffi-1.17.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:805b4371bf7197c329fcb3ead37e710d1bca9da5d583f5073b799d5c5bd1eee4"}, + {file = "cffi-1.17.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:733e99bc2df47476e3848417c5a4540522f234dfd4ef3ab7fafdf555b082ec0c"}, + {file = "cffi-1.17.1-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1257bdabf294dceb59f5e70c64a3e2f462c30c7ad68092d01bbbfb1c16b1ba36"}, + {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da95af8214998d77a98cc14e3a3bd00aa191526343078b530ceb0bd710fb48a5"}, + {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d63afe322132c194cf832bfec0dc69a99fb9bb6bbd550f161a49e9e855cc78ff"}, + {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f79fc4fc25f1c8698ff97788206bb3c2598949bfe0fef03d299eb1b5356ada99"}, + {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b62ce867176a75d03a665bad002af8e6d54644fad99a3c70905c543130e39d93"}, + {file = "cffi-1.17.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:386c8bf53c502fff58903061338ce4f4950cbdcb23e2902d86c0f722b786bbe3"}, + {file = "cffi-1.17.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4ceb10419a9adf4460ea14cfd6bc43d08701f0835e979bf821052f1805850fe8"}, + {file = "cffi-1.17.1-cp312-cp312-win32.whl", hash = "sha256:a08d7e755f8ed21095a310a693525137cfe756ce62d066e53f502a83dc550f65"}, + {file = "cffi-1.17.1-cp312-cp312-win_amd64.whl", hash = "sha256:51392eae71afec0d0c8fb1a53b204dbb3bcabcb3c9b807eedf3e1e6ccf2de903"}, + {file = "cffi-1.17.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f3a2b4222ce6b60e2e8b337bb9596923045681d71e5a082783484d845390938e"}, + {file = "cffi-1.17.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0984a4925a435b1da406122d4d7968dd861c1385afe3b45ba82b750f229811e2"}, + {file = "cffi-1.17.1-cp313-cp313-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d01b12eeeb4427d3110de311e1774046ad344f5b1a7403101878976ecd7a10f3"}, + {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:706510fe141c86a69c8ddc029c7910003a17353970cff3b904ff0686a5927683"}, + {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:de55b766c7aa2e2a3092c51e0483d700341182f08e67c63630d5b6f200bb28e5"}, + {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c59d6e989d07460165cc5ad3c61f9fd8f1b4796eacbd81cee78957842b834af4"}, + {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd398dbc6773384a17fe0d3e7eeb8d1a21c2200473ee6806bb5e6a8e62bb73dd"}, + {file = "cffi-1.17.1-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:3edc8d958eb099c634dace3c7e16560ae474aa3803a5df240542b305d14e14ed"}, + {file = "cffi-1.17.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:72e72408cad3d5419375fc87d289076ee319835bdfa2caad331e377589aebba9"}, + {file = "cffi-1.17.1-cp313-cp313-win32.whl", hash = "sha256:e03eab0a8677fa80d646b5ddece1cbeaf556c313dcfac435ba11f107ba117b5d"}, + {file = "cffi-1.17.1-cp313-cp313-win_amd64.whl", hash = "sha256:f6a16c31041f09ead72d69f583767292f750d24913dadacf5756b966aacb3f1a"}, + {file = "cffi-1.17.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:636062ea65bd0195bc012fea9321aca499c0504409f413dc88af450b57ffd03b"}, + {file = "cffi-1.17.1-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c7eac2ef9b63c79431bc4b25f1cd649d7f061a28808cbc6c47b534bd789ef964"}, + {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e221cf152cff04059d011ee126477f0d9588303eb57e88923578ace7baad17f9"}, + {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:31000ec67d4221a71bd3f67df918b1f88f676f1c3b535a7eb473255fdc0b83fc"}, + {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6f17be4345073b0a7b8ea599688f692ac3ef23ce28e5df79c04de519dbc4912c"}, + {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0e2b1fac190ae3ebfe37b979cc1ce69c81f4e4fe5746bb401dca63a9062cdaf1"}, + {file = "cffi-1.17.1-cp38-cp38-win32.whl", hash = "sha256:7596d6620d3fa590f677e9ee430df2958d2d6d6de2feeae5b20e82c00b76fbf8"}, + {file = "cffi-1.17.1-cp38-cp38-win_amd64.whl", hash = "sha256:78122be759c3f8a014ce010908ae03364d00a1f81ab5c7f4a7a5120607ea56e1"}, + {file = "cffi-1.17.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b2ab587605f4ba0bf81dc0cb08a41bd1c0a5906bd59243d56bad7668a6fc6c16"}, + {file = "cffi-1.17.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:28b16024becceed8c6dfbc75629e27788d8a3f9030691a1dbf9821a128b22c36"}, + {file = "cffi-1.17.1-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1d599671f396c4723d016dbddb72fe8e0397082b0a77a4fab8028923bec050e8"}, + {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ca74b8dbe6e8e8263c0ffd60277de77dcee6c837a3d0881d8c1ead7268c9e576"}, + {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f7f5baafcc48261359e14bcd6d9bff6d4b28d9103847c9e136694cb0501aef87"}, + {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:98e3969bcff97cae1b2def8ba499ea3d6f31ddfdb7635374834cf89a1a08ecf0"}, + {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cdf5ce3acdfd1661132f2a9c19cac174758dc2352bfe37d98aa7512c6b7178b3"}, + {file = "cffi-1.17.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:9755e4345d1ec879e3849e62222a18c7174d65a6a92d5b346b1863912168b595"}, + {file = "cffi-1.17.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:f1e22e8c4419538cb197e4dd60acc919d7696e5ef98ee4da4e01d3f8cfa4cc5a"}, + {file = "cffi-1.17.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:c03e868a0b3bc35839ba98e74211ed2b05d2119be4e8a0f224fba9384f1fe02e"}, + {file = "cffi-1.17.1-cp39-cp39-win32.whl", hash = "sha256:e31ae45bc2e29f6b2abd0de1cc3b9d5205aa847cafaecb8af1476a609a2f6eb7"}, + {file = "cffi-1.17.1-cp39-cp39-win_amd64.whl", hash = "sha256:d016c76bdd850f3c626af19b0542c9677ba156e4ee4fccfdd7848803533ef662"}, + {file = "cffi-1.17.1.tar.gz", hash = "sha256:1c39c6016c32bc48dd54561950ebd6836e1670f2ae46128f67cf49e789c52824"}, ] [package.dependencies] @@ -283,7 +410,6 @@ pycparser = "*" name = "chardet" version = "3.0.4" description = "Universal encoding detector for Python 2 and 3" -category = "main" optional = false python-versions = "*" files = [ @@ -293,99 +419,112 @@ files = [ [[package]] name = "charset-normalizer" -version = "3.1.0" +version = "3.3.2" description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." -category = "main" optional = false python-versions = ">=3.7.0" files = [ - {file = "charset-normalizer-3.1.0.tar.gz", hash = "sha256:34e0a2f9c370eb95597aae63bf85eb5e96826d81e3dcf88b8886012906f509b5"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:e0ac8959c929593fee38da1c2b64ee9778733cdf03c482c9ff1d508b6b593b2b"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d7fc3fca01da18fbabe4625d64bb612b533533ed10045a2ac3dd194bfa656b60"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:04eefcee095f58eaabe6dc3cc2262f3bcd776d2c67005880894f447b3f2cb9c1"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:20064ead0717cf9a73a6d1e779b23d149b53daf971169289ed2ed43a71e8d3b0"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1435ae15108b1cb6fffbcea2af3d468683b7afed0169ad718451f8db5d1aff6f"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c84132a54c750fda57729d1e2599bb598f5fa0344085dbde5003ba429a4798c0"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75f2568b4189dda1c567339b48cba4ac7384accb9c2a7ed655cd86b04055c795"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:11d3bcb7be35e7b1bba2c23beedac81ee893ac9871d0ba79effc7fc01167db6c"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:891cf9b48776b5c61c700b55a598621fdb7b1e301a550365571e9624f270c203"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:5f008525e02908b20e04707a4f704cd286d94718f48bb33edddc7d7b584dddc1"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:b06f0d3bf045158d2fb8837c5785fe9ff9b8c93358be64461a1089f5da983137"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:49919f8400b5e49e961f320c735388ee686a62327e773fa5b3ce6721f7e785ce"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:22908891a380d50738e1f978667536f6c6b526a2064156203d418f4856d6e86a"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-win32.whl", hash = "sha256:12d1a39aa6b8c6f6248bb54550efcc1c38ce0d8096a146638fd4738e42284448"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:65ed923f84a6844de5fd29726b888e58c62820e0769b76565480e1fdc3d062f8"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9a3267620866c9d17b959a84dd0bd2d45719b817245e49371ead79ed4f710d19"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6734e606355834f13445b6adc38b53c0fd45f1a56a9ba06c2058f86893ae8017"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f8303414c7b03f794347ad062c0516cee0e15f7a612abd0ce1e25caf6ceb47df"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aaf53a6cebad0eae578f062c7d462155eada9c172bd8c4d250b8c1d8eb7f916a"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3dc5b6a8ecfdc5748a7e429782598e4f17ef378e3e272eeb1340ea57c9109f41"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e1b25e3ad6c909f398df8921780d6a3d120d8c09466720226fc621605b6f92b1"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0ca564606d2caafb0abe6d1b5311c2649e8071eb241b2d64e75a0d0065107e62"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b82fab78e0b1329e183a65260581de4375f619167478dddab510c6c6fb04d9b6"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:bd7163182133c0c7701b25e604cf1611c0d87712e56e88e7ee5d72deab3e76b5"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:11d117e6c63e8f495412d37e7dc2e2fff09c34b2d09dbe2bee3c6229577818be"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:cf6511efa4801b9b38dc5546d7547d5b5c6ef4b081c60b23e4d941d0eba9cbeb"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:abc1185d79f47c0a7aaf7e2412a0eb2c03b724581139193d2d82b3ad8cbb00ac"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:cb7b2ab0188829593b9de646545175547a70d9a6e2b63bf2cd87a0a391599324"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-win32.whl", hash = "sha256:c36bcbc0d5174a80d6cccf43a0ecaca44e81d25be4b7f90f0ed7bcfbb5a00909"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:cca4def576f47a09a943666b8f829606bcb17e2bc2d5911a46c8f8da45f56755"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:0c95f12b74681e9ae127728f7e5409cbbef9cd914d5896ef238cc779b8152373"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fca62a8301b605b954ad2e9c3666f9d97f63872aa4efcae5492baca2056b74ab"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ac0aa6cd53ab9a31d397f8303f92c42f534693528fafbdb997c82bae6e477ad9"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c3af8e0f07399d3176b179f2e2634c3ce9c1301379a6b8c9c9aeecd481da494f"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3a5fc78f9e3f501a1614a98f7c54d3969f3ad9bba8ba3d9b438c3bc5d047dd28"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:628c985afb2c7d27a4800bfb609e03985aaecb42f955049957814e0491d4006d"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:74db0052d985cf37fa111828d0dd230776ac99c740e1a758ad99094be4f1803d"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:1e8fcdd8f672a1c4fc8d0bd3a2b576b152d2a349782d1eb0f6b8e52e9954731d"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:04afa6387e2b282cf78ff3dbce20f0cc071c12dc8f685bd40960cc68644cfea6"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:dd5653e67b149503c68c4018bf07e42eeed6b4e956b24c00ccdf93ac79cdff84"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d2686f91611f9e17f4548dbf050e75b079bbc2a82be565832bc8ea9047b61c8c"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-win32.whl", hash = "sha256:4155b51ae05ed47199dc5b2a4e62abccb274cee6b01da5b895099b61b1982974"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-win_amd64.whl", hash = "sha256:322102cdf1ab682ecc7d9b1c5eed4ec59657a65e1c146a0da342b78f4112db23"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:e633940f28c1e913615fd624fcdd72fdba807bf53ea6925d6a588e84e1151531"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:3a06f32c9634a8705f4ca9946d667609f52cf130d5548881401f1eb2c39b1e2c"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7381c66e0561c5757ffe616af869b916c8b4e42b367ab29fedc98481d1e74e14"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3573d376454d956553c356df45bb824262c397c6e26ce43e8203c4c540ee0acb"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e89df2958e5159b811af9ff0f92614dabf4ff617c03a4c1c6ff53bf1c399e0e1"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:78cacd03e79d009d95635e7d6ff12c21eb89b894c354bd2b2ed0b4763373693b"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:de5695a6f1d8340b12a5d6d4484290ee74d61e467c39ff03b39e30df62cf83a0"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1c60b9c202d00052183c9be85e5eaf18a4ada0a47d188a83c8f5c5b23252f649"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:f645caaf0008bacf349875a974220f1f1da349c5dbe7c4ec93048cdc785a3326"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:ea9f9c6034ea2d93d9147818f17c2a0860d41b71c38b9ce4d55f21b6f9165a11"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:80d1543d58bd3d6c271b66abf454d437a438dff01c3e62fdbcd68f2a11310d4b"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:73dc03a6a7e30b7edc5b01b601e53e7fc924b04e1835e8e407c12c037e81adbd"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6f5c2e7bc8a4bf7c426599765b1bd33217ec84023033672c1e9a8b35eaeaaaf8"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-win32.whl", hash = "sha256:12a2b561af122e3d94cdb97fe6fb2bb2b82cef0cdca131646fdb940a1eda04f0"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:3160a0fd9754aab7d47f95a6b63ab355388d890163eb03b2d2b87ab0a30cfa59"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:38e812a197bf8e71a59fe55b757a84c1f946d0ac114acafaafaf21667a7e169e"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6baf0baf0d5d265fa7944feb9f7451cc316bfe30e8df1a61b1bb08577c554f31"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:8f25e17ab3039b05f762b0a55ae0b3632b2e073d9c8fc88e89aca31a6198e88f"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3747443b6a904001473370d7810aa19c3a180ccd52a7157aacc264a5ac79265e"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b116502087ce8a6b7a5f1814568ccbd0e9f6cfd99948aa59b0e241dc57cf739f"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d16fd5252f883eb074ca55cb622bc0bee49b979ae4e8639fff6ca3ff44f9f854"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21fa558996782fc226b529fdd2ed7866c2c6ec91cee82735c98a197fae39f706"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6f6c7a8a57e9405cad7485f4c9d3172ae486cfef1344b5ddd8e5239582d7355e"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ac3775e3311661d4adace3697a52ac0bab17edd166087d493b52d4f4f553f9f0"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:10c93628d7497c81686e8e5e557aafa78f230cd9e77dd0c40032ef90c18f2230"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:6f4f4668e1831850ebcc2fd0b1cd11721947b6dc7c00bf1c6bd3c929ae14f2c7"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:0be65ccf618c1e7ac9b849c315cc2e8a8751d9cfdaa43027d4f6624bd587ab7e"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:53d0a3fa5f8af98a1e261de6a3943ca631c526635eb5817a87a59d9a57ebf48f"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-win32.whl", hash = "sha256:a04f86f41a8916fe45ac5024ec477f41f886b3c435da2d4e3d2709b22ab02af1"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:830d2948a5ec37c386d3170c483063798d7879037492540f10a475e3fd6f244b"}, - {file = "charset_normalizer-3.1.0-py3-none-any.whl", hash = "sha256:3d9098b479e78c85080c98e1e35ff40b4a31d8953102bb0fd7d1b6f8a2111a3d"}, + {file = "charset-normalizer-3.3.2.tar.gz", hash = "sha256:f30c3cb33b24454a82faecaf01b19c18562b1e89558fb6c56de4d9118a032fd5"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:25baf083bf6f6b341f4121c2f3c548875ee6f5339300e08be3f2b2ba1721cdd3"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:06435b539f889b1f6f4ac1758871aae42dc3a8c0e24ac9e60c2384973ad73027"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9063e24fdb1e498ab71cb7419e24622516c4a04476b17a2dab57e8baa30d6e03"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6897af51655e3691ff853668779c7bad41579facacf5fd7253b0133308cf000d"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1d3193f4a680c64b4b6a9115943538edb896edc190f0b222e73761716519268e"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cd70574b12bb8a4d2aaa0094515df2463cb429d8536cfb6c7ce983246983e5a6"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8465322196c8b4d7ab6d1e049e4c5cb460d0394da4a27d23cc242fbf0034b6b5"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a9a8e9031d613fd2009c182b69c7b2c1ef8239a0efb1df3f7c8da66d5dd3d537"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:beb58fe5cdb101e3a055192ac291b7a21e3b7ef4f67fa1d74e331a7f2124341c"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e06ed3eb3218bc64786f7db41917d4e686cc4856944f53d5bdf83a6884432e12"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:2e81c7b9c8979ce92ed306c249d46894776a909505d8f5a4ba55b14206e3222f"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:572c3763a264ba47b3cf708a44ce965d98555f618ca42c926a9c1616d8f34269"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fd1abc0d89e30cc4e02e4064dc67fcc51bd941eb395c502aac3ec19fab46b519"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-win32.whl", hash = "sha256:3d47fa203a7bd9c5b6cee4736ee84ca03b8ef23193c0d1ca99b5089f72645c73"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:10955842570876604d404661fbccbc9c7e684caf432c09c715ec38fbae45ae09"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:802fe99cca7457642125a8a88a084cef28ff0cf9407060f7b93dca5aa25480db"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ceae2f17a9c33cb48e3263960dc5fc8005351ee19db217e9b1bb15d28c02574"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:65f6f63034100ead094b8744b3b97965785388f308a64cf8d7c34f2f2e5be0c4"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4a78b2b446bd7c934f5dcedc588903fb2f5eec172f3d29e52a9096a43722adfc"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e537484df0d8f426ce2afb2d0f8e1c3d0b114b83f8850e5f2fbea0e797bd82ae"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:eb6904c354526e758fda7167b33005998fb68c46fbc10e013ca97f21ca5c8887"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:deb6be0ac38ece9ba87dea880e438f25ca3eddfac8b002a2ec3d9183a454e8ae"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:4ab2fe47fae9e0f9dee8c04187ce5d09f48eabe611be8259444906793ab7cbce"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:80402cd6ee291dcb72644d6eac93785fe2c8b9cb30893c1af5b8fdd753b9d40f"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-win32.whl", hash = "sha256:7cd13a2e3ddeed6913a65e66e94b51d80a041145a026c27e6bb76c31a853c6ab"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0b2b64d2bb6d3fb9112bafa732def486049e63de9618b5843bcdd081d8144cd8"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:ddbb2551d7e0102e7252db79ba445cdab71b26640817ab1e3e3648dad515003b"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:55086ee1064215781fff39a1af09518bc9255b50d6333f2e4c74ca09fac6a8f6"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8f4a014bc36d3c57402e2977dada34f9c12300af536839dc38c0beab8878f38a"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a10af20b82360ab00827f916a6058451b723b4e65030c5a18577c8b2de5b3389"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8d756e44e94489e49571086ef83b2bb8ce311e730092d2c34ca8f7d925cb20aa"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:90d558489962fd4918143277a773316e56c72da56ec7aa3dc3dbbe20fdfed15b"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6ac7ffc7ad6d040517be39eb591cac5ff87416c2537df6ba3cba3bae290c0fed"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:7ed9e526742851e8d5cc9e6cf41427dfc6068d4f5a3bb03659444b4cabf6bc26"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:8bdb58ff7ba23002a4c5808d608e4e6c687175724f54a5dade5fa8c67b604e4d"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:6b3251890fff30ee142c44144871185dbe13b11bab478a88887a639655be1068"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:b4a23f61ce87adf89be746c8a8974fe1c823c891d8f86eb218bb957c924bb143"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:efcb3f6676480691518c177e3b465bcddf57cea040302f9f4e6e191af91174d4"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-win32.whl", hash = "sha256:d965bba47ddeec8cd560687584e88cf699fd28f192ceb452d1d7ee807c5597b7"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:96b02a3dc4381e5494fad39be677abcb5e6634bf7b4fa83a6dd3112607547001"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:95f2a5796329323b8f0512e09dbb7a1860c46a39da62ecb2324f116fa8fdc85c"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c002b4ffc0be611f0d9da932eb0f704fe2602a9a949d1f738e4c34c75b0863d5"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a981a536974bbc7a512cf44ed14938cf01030a99e9b3a06dd59578882f06f985"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3287761bc4ee9e33561a7e058c72ac0938c4f57fe49a09eae428fd88aafe7bb6"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:42cb296636fcc8b0644486d15c12376cb9fa75443e00fb25de0b8602e64c1714"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0a55554a2fa0d408816b3b5cedf0045f4b8e1a6065aec45849de2d6f3f8e9786"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:c083af607d2515612056a31f0a8d9e0fcb5876b7bfc0abad3ecd275bc4ebc2d5"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:87d1351268731db79e0f8e745d92493ee2841c974128ef629dc518b937d9194c"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:bd8f7df7d12c2db9fab40bdd87a7c09b1530128315d047a086fa3ae3435cb3a8"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:c180f51afb394e165eafe4ac2936a14bee3eb10debc9d9e4db8958fe36afe711"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:8c622a5fe39a48f78944a87d4fb8a53ee07344641b0562c540d840748571b811"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-win32.whl", hash = "sha256:db364eca23f876da6f9e16c9da0df51aa4f104a972735574842618b8c6d999d4"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-win_amd64.whl", hash = "sha256:86216b5cee4b06df986d214f664305142d9c76df9b6512be2738aa72a2048f99"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:6463effa3186ea09411d50efc7d85360b38d5f09b870c48e4600f63af490e56a"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6c4caeef8fa63d06bd437cd4bdcf3ffefe6738fb1b25951440d80dc7df8c03ac"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:37e55c8e51c236f95b033f6fb391d7d7970ba5fe7ff453dad675e88cf303377a"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb69256e180cb6c8a894fee62b3afebae785babc1ee98b81cdf68bbca1987f33"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ae5f4161f18c61806f411a13b0310bea87f987c7d2ecdbdaad0e94eb2e404238"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b2b0a0c0517616b6869869f8c581d4eb2dd83a4d79e0ebcb7d373ef9956aeb0a"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:45485e01ff4d3630ec0d9617310448a8702f70e9c01906b0d0118bdf9d124cf2"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eb00ed941194665c332bf8e078baf037d6c35d7c4f3102ea2d4f16ca94a26dc8"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:2127566c664442652f024c837091890cb1942c30937add288223dc895793f898"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a50aebfa173e157099939b17f18600f72f84eed3049e743b68ad15bd69b6bf99"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:4d0d1650369165a14e14e1e47b372cfcb31d6ab44e6e33cb2d4e57265290044d"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:923c0c831b7cfcb071580d3f46c4baf50f174be571576556269530f4bbd79d04"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:06a81e93cd441c56a9b65d8e1d043daeb97a3d0856d177d5c90ba85acb3db087"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-win32.whl", hash = "sha256:6ef1d82a3af9d3eecdba2321dc1b3c238245d890843e040e41e470ffa64c3e25"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-win_amd64.whl", hash = "sha256:eb8821e09e916165e160797a6c17edda0679379a4be5c716c260e836e122f54b"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c235ebd9baae02f1b77bcea61bce332cb4331dc3617d254df3323aa01ab47bd4"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5b4c145409bef602a690e7cfad0a15a55c13320ff7a3ad7ca59c13bb8ba4d45d"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:68d1f8a9e9e37c1223b656399be5d6b448dea850bed7d0f87a8311f1ff3dabb0"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22afcb9f253dac0696b5a4be4a1c0f8762f8239e21b99680099abd9b2b1b2269"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e27ad930a842b4c5eb8ac0016b0a54f5aebbe679340c26101df33424142c143c"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1f79682fbe303db92bc2b1136016a38a42e835d932bab5b3b1bfcfbf0640e519"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b261ccdec7821281dade748d088bb6e9b69e6d15b30652b74cbbac25e280b796"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:122c7fa62b130ed55f8f285bfd56d5f4b4a5b503609d181f9ad85e55c89f4185"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:d0eccceffcb53201b5bfebb52600a5fb483a20b61da9dbc885f8b103cbe7598c"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9f96df6923e21816da7e0ad3fd47dd8f94b2a5ce594e00677c0013018b813458"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:7f04c839ed0b6b98b1a7501a002144b76c18fb1c1850c8b98d458ac269e26ed2"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:34d1c8da1e78d2e001f363791c98a272bb734000fcef47a491c1e3b0505657a8"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ff8fa367d09b717b2a17a052544193ad76cd49979c805768879cb63d9ca50561"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-win32.whl", hash = "sha256:aed38f6e4fb3f5d6bf81bfa990a07806be9d83cf7bacef998ab1a9bd660a581f"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-win_amd64.whl", hash = "sha256:b01b88d45a6fcb69667cd6d2f7a9aeb4bf53760d7fc536bf679ec94fe9f3ff3d"}, + {file = "charset_normalizer-3.3.2-py3-none-any.whl", hash = "sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc"}, ] [[package]] name = "click" -version = "8.1.3" +version = "8.1.7" description = "Composable command line interface toolkit" -category = "dev" optional = false python-versions = ">=3.7" files = [ - {file = "click-8.1.3-py3-none-any.whl", hash = "sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48"}, - {file = "click-8.1.3.tar.gz", hash = "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e"}, + {file = "click-8.1.7-py3-none-any.whl", hash = "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28"}, + {file = "click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de"}, ] [package.dependencies] @@ -395,7 +534,6 @@ colorama = {version = "*", markers = "platform_system == \"Windows\""} name = "colorama" version = "0.4.6" description = "Cross-platform colored terminal text." -category = "dev" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" files = [ @@ -407,7 +545,6 @@ files = [ name = "discord-py" version = "1.7.3" description = "A Python wrapper for the Discord API" -category = "main" optional = false python-versions = ">=3.5.3" files = [ @@ -425,14 +562,13 @@ voice = ["PyNaCl (>=1.3.0,<1.5)"] [[package]] name = "exceptiongroup" -version = "1.1.1" +version = "1.2.2" description = "Backport of PEP 654 (exception groups)" -category = "dev" optional = false python-versions = ">=3.7" files = [ - {file = "exceptiongroup-1.1.1-py3-none-any.whl", hash = "sha256:232c37c63e4f682982c8b6459f33a8981039e5fb8756b2074364e5055c498c9e"}, - {file = "exceptiongroup-1.1.1.tar.gz", hash = "sha256:d484c3090ba2889ae2928419117447a14daf3c1231d5e30d0aae34f354f01785"}, + {file = "exceptiongroup-1.2.2-py3-none-any.whl", hash = "sha256:3111b9d131c238bec2f8f516e123e14ba243563fb135d3fe885990585aa7795b"}, + {file = "exceptiongroup-1.2.2.tar.gz", hash = "sha256:47c2edf7c6738fafb49fd34290706d1a1a2f4d1c6df275526b62cbb4aa5393cc"}, ] [package.extras] @@ -440,14 +576,13 @@ test = ["pytest (>=6)"] [[package]] name = "feedparser" -version = "6.0.10" +version = "6.0.11" description = "Universal feed parser, handles RSS 0.9x, RSS 1.0, RSS 2.0, CDF, Atom 0.3, and Atom 1.0 feeds" -category = "main" optional = false python-versions = ">=3.6" files = [ - {file = "feedparser-6.0.10-py3-none-any.whl", hash = "sha256:79c257d526d13b944e965f6095700587f27388e50ea16fd245babe4dfae7024f"}, - {file = "feedparser-6.0.10.tar.gz", hash = "sha256:27da485f4637ce7163cdeab13a80312b93b7d0c1b775bef4a47629a3110bca51"}, + {file = "feedparser-6.0.11-py3-none-any.whl", hash = "sha256:0be7ee7b395572b19ebeb1d6aafb0028dee11169f1c934e0ed67d54992f4ad45"}, + {file = "feedparser-6.0.11.tar.gz", hash = "sha256:c9d0407b64c6f2a065d0ebb292c2b35c01050cc0dc33757461aaabdc4c4184d5"}, ] [package.dependencies] @@ -457,7 +592,6 @@ sgmllib3k = "*" name = "googletrans" version = "4.0.0rc1" description = "Free Google Translate API for Python. Translates totally free of charge." -category = "main" optional = false python-versions = ">=3.6" files = [ @@ -471,7 +605,6 @@ httpx = "0.13.3" name = "h11" version = "0.9.0" description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" -category = "main" optional = false python-versions = "*" files = [ @@ -483,7 +616,6 @@ files = [ name = "h2" version = "3.2.0" description = "HTTP/2 State-Machine based protocol implementation" -category = "main" optional = false python-versions = "*" files = [ @@ -499,7 +631,6 @@ hyperframe = ">=5.2.0,<6" name = "hpack" version = "3.0.0" description = "Pure-Python HPACK header compression" -category = "main" optional = false python-versions = "*" files = [ @@ -509,21 +640,19 @@ files = [ [[package]] name = "hstspreload" -version = "2023.1.1" +version = "2024.9.1" description = "Chromium HSTS Preload list as a Python package" -category = "main" optional = false python-versions = ">=3.6" files = [ - {file = "hstspreload-2023.1.1-py3-none-any.whl", hash = "sha256:ac8a56dd603b4bf55292fc7a157e0deea18ee5e2e5c114d131da8949cc7a54bb"}, - {file = "hstspreload-2023.1.1.tar.gz", hash = "sha256:b2330a88b3fe3344c9eb431257e1ff3ae06c3bc2ff87ca686a5f253e2881a6c1"}, + {file = "hstspreload-2024.9.1-py3-none-any.whl", hash = "sha256:9c1b2d0313899d3ff9dac03ab39d53fed95c32eef9862e7eabee8dc07dfd589c"}, + {file = "hstspreload-2024.9.1.tar.gz", hash = "sha256:2ab4518495a132c4ae430c474afffd12938852c6eec68ce1368c8f7858dc3076"}, ] [[package]] name = "httpcore" version = "0.9.1" description = "A minimal low-level HTTP client." -category = "main" optional = false python-versions = ">=3.6" files = [ @@ -533,14 +662,13 @@ files = [ [package.dependencies] h11 = ">=0.8,<0.10" -h2 = ">=3.0.0,<4.0.0" -sniffio = ">=1.0.0,<2.0.0" +h2 = "==3.*" +sniffio = "==1.*" [[package]] name = "httpx" version = "0.13.3" description = "The next generation HTTP client." -category = "main" optional = false python-versions = ">=3.6" files = [ @@ -550,10 +678,10 @@ files = [ [package.dependencies] certifi = "*" -chardet = ">=3.0.0,<4.0.0" +chardet = "==3.*" hstspreload = "*" -httpcore = ">=0.9.0,<0.10.0" -idna = ">=2.0.0,<3.0.0" +httpcore = "==0.9.*" +idna = "==2.*" rfc3986 = ">=1.3,<2" sniffio = "*" @@ -561,7 +689,6 @@ sniffio = "*" name = "hyperframe" version = "5.2.0" description = "HTTP/2 framing layer for Python" -category = "main" optional = false python-versions = "*" files = [ @@ -573,7 +700,6 @@ files = [ name = "idna" version = "2.10" description = "Internationalized Domain Names in Applications (IDNA)" -category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" files = [ @@ -585,7 +711,6 @@ files = [ name = "iniconfig" version = "2.0.0" description = "brain-dead simple config-ini parsing" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -595,102 +720,116 @@ files = [ [[package]] name = "lxml" -version = "4.9.2" +version = "4.9.4" description = "Powerful and Pythonic XML processing library combining libxml2/libxslt with the ElementTree API." -category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, != 3.4.*" files = [ - {file = "lxml-4.9.2-cp27-cp27m-macosx_10_15_x86_64.whl", hash = "sha256:76cf573e5a365e790396a5cc2b909812633409306c6531a6877c59061e42c4f2"}, - {file = "lxml-4.9.2-cp27-cp27m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b1f42b6921d0e81b1bcb5e395bc091a70f41c4d4e55ba99c6da2b31626c44892"}, - {file = "lxml-4.9.2-cp27-cp27m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:9f102706d0ca011de571de32c3247c6476b55bb6bc65a20f682f000b07a4852a"}, - {file = "lxml-4.9.2-cp27-cp27m-win32.whl", hash = "sha256:8d0b4612b66ff5d62d03bcaa043bb018f74dfea51184e53f067e6fdcba4bd8de"}, - {file = "lxml-4.9.2-cp27-cp27m-win_amd64.whl", hash = "sha256:4c8f293f14abc8fd3e8e01c5bd86e6ed0b6ef71936ded5bf10fe7a5efefbaca3"}, - {file = "lxml-4.9.2-cp27-cp27mu-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2899456259589aa38bfb018c364d6ae7b53c5c22d8e27d0ec7609c2a1ff78b50"}, - {file = "lxml-4.9.2-cp27-cp27mu-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:6749649eecd6a9871cae297bffa4ee76f90b4504a2a2ab528d9ebe912b101975"}, - {file = "lxml-4.9.2-cp310-cp310-macosx_10_15_x86_64.whl", hash = "sha256:a08cff61517ee26cb56f1e949cca38caabe9ea9fbb4b1e10a805dc39844b7d5c"}, - {file = "lxml-4.9.2-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:85cabf64adec449132e55616e7ca3e1000ab449d1d0f9d7f83146ed5bdcb6d8a"}, - {file = "lxml-4.9.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:8340225bd5e7a701c0fa98284c849c9b9fc9238abf53a0ebd90900f25d39a4e4"}, - {file = "lxml-4.9.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:1ab8f1f932e8f82355e75dda5413a57612c6ea448069d4fb2e217e9a4bed13d4"}, - {file = "lxml-4.9.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:699a9af7dffaf67deeae27b2112aa06b41c370d5e7633e0ee0aea2e0b6c211f7"}, - {file = "lxml-4.9.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:b9cc34af337a97d470040f99ba4282f6e6bac88407d021688a5d585e44a23184"}, - {file = "lxml-4.9.2-cp310-cp310-win32.whl", hash = "sha256:d02a5399126a53492415d4906ab0ad0375a5456cc05c3fc0fc4ca11771745cda"}, - {file = "lxml-4.9.2-cp310-cp310-win_amd64.whl", hash = "sha256:a38486985ca49cfa574a507e7a2215c0c780fd1778bb6290c21193b7211702ab"}, - {file = "lxml-4.9.2-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:c83203addf554215463b59f6399835201999b5e48019dc17f182ed5ad87205c9"}, - {file = "lxml-4.9.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:2a87fa548561d2f4643c99cd13131acb607ddabb70682dcf1dff5f71f781a4bf"}, - {file = "lxml-4.9.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:d6b430a9938a5a5d85fc107d852262ddcd48602c120e3dbb02137c83d212b380"}, - {file = "lxml-4.9.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:3efea981d956a6f7173b4659849f55081867cf897e719f57383698af6f618a92"}, - {file = "lxml-4.9.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:df0623dcf9668ad0445e0558a21211d4e9a149ea8f5666917c8eeec515f0a6d1"}, - {file = "lxml-4.9.2-cp311-cp311-win32.whl", hash = "sha256:da248f93f0418a9e9d94b0080d7ebc407a9a5e6d0b57bb30db9b5cc28de1ad33"}, - {file = "lxml-4.9.2-cp311-cp311-win_amd64.whl", hash = "sha256:3818b8e2c4b5148567e1b09ce739006acfaa44ce3156f8cbbc11062994b8e8dd"}, - {file = "lxml-4.9.2-cp35-cp35m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ca989b91cf3a3ba28930a9fc1e9aeafc2a395448641df1f387a2d394638943b0"}, - {file = "lxml-4.9.2-cp35-cp35m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:822068f85e12a6e292803e112ab876bc03ed1f03dddb80154c395f891ca6b31e"}, - {file = "lxml-4.9.2-cp35-cp35m-win32.whl", hash = "sha256:be7292c55101e22f2a3d4d8913944cbea71eea90792bf914add27454a13905df"}, - {file = "lxml-4.9.2-cp35-cp35m-win_amd64.whl", hash = "sha256:998c7c41910666d2976928c38ea96a70d1aa43be6fe502f21a651e17483a43c5"}, - {file = "lxml-4.9.2-cp36-cp36m-macosx_10_15_x86_64.whl", hash = "sha256:b26a29f0b7fc6f0897f043ca366142d2b609dc60756ee6e4e90b5f762c6adc53"}, - {file = "lxml-4.9.2-cp36-cp36m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:ab323679b8b3030000f2be63e22cdeea5b47ee0abd2d6a1dc0c8103ddaa56cd7"}, - {file = "lxml-4.9.2-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:689bb688a1db722485e4610a503e3e9210dcc20c520b45ac8f7533c837be76fe"}, - {file = "lxml-4.9.2-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:f49e52d174375a7def9915c9f06ec4e569d235ad428f70751765f48d5926678c"}, - {file = "lxml-4.9.2-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:36c3c175d34652a35475a73762b545f4527aec044910a651d2bf50de9c3352b1"}, - {file = "lxml-4.9.2-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:a35f8b7fa99f90dd2f5dc5a9fa12332642f087a7641289ca6c40d6e1a2637d8e"}, - {file = "lxml-4.9.2-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:58bfa3aa19ca4c0f28c5dde0ff56c520fbac6f0daf4fac66ed4c8d2fb7f22e74"}, - {file = "lxml-4.9.2-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:bc718cd47b765e790eecb74d044cc8d37d58562f6c314ee9484df26276d36a38"}, - {file = "lxml-4.9.2-cp36-cp36m-win32.whl", hash = "sha256:d5bf6545cd27aaa8a13033ce56354ed9e25ab0e4ac3b5392b763d8d04b08e0c5"}, - {file = "lxml-4.9.2-cp36-cp36m-win_amd64.whl", hash = "sha256:3ab9fa9d6dc2a7f29d7affdf3edebf6ece6fb28a6d80b14c3b2fb9d39b9322c3"}, - {file = "lxml-4.9.2-cp37-cp37m-macosx_10_15_x86_64.whl", hash = "sha256:05ca3f6abf5cf78fe053da9b1166e062ade3fa5d4f92b4ed688127ea7d7b1d03"}, - {file = "lxml-4.9.2-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:a5da296eb617d18e497bcf0a5c528f5d3b18dadb3619fbdadf4ed2356ef8d941"}, - {file = "lxml-4.9.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:04876580c050a8c5341d706dd464ff04fd597095cc8c023252566a8826505726"}, - {file = "lxml-4.9.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:c9ec3eaf616d67db0764b3bb983962b4f385a1f08304fd30c7283954e6a7869b"}, - {file = "lxml-4.9.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2a29ba94d065945944016b6b74e538bdb1751a1db6ffb80c9d3c2e40d6fa9894"}, - {file = "lxml-4.9.2-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:a82d05da00a58b8e4c0008edbc8a4b6ec5a4bc1e2ee0fb6ed157cf634ed7fa45"}, - {file = "lxml-4.9.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:223f4232855ade399bd409331e6ca70fb5578efef22cf4069a6090acc0f53c0e"}, - {file = "lxml-4.9.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d17bc7c2ccf49c478c5bdd447594e82692c74222698cfc9b5daae7ae7e90743b"}, - {file = "lxml-4.9.2-cp37-cp37m-win32.whl", hash = "sha256:b64d891da92e232c36976c80ed7ebb383e3f148489796d8d31a5b6a677825efe"}, - {file = "lxml-4.9.2-cp37-cp37m-win_amd64.whl", hash = "sha256:a0a336d6d3e8b234a3aae3c674873d8f0e720b76bc1d9416866c41cd9500ffb9"}, - {file = "lxml-4.9.2-cp38-cp38-macosx_10_15_x86_64.whl", hash = "sha256:da4dd7c9c50c059aba52b3524f84d7de956f7fef88f0bafcf4ad7dde94a064e8"}, - {file = "lxml-4.9.2-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:821b7f59b99551c69c85a6039c65b75f5683bdc63270fec660f75da67469ca24"}, - {file = "lxml-4.9.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:e5168986b90a8d1f2f9dc1b841467c74221bd752537b99761a93d2d981e04889"}, - {file = "lxml-4.9.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:8e20cb5a47247e383cf4ff523205060991021233ebd6f924bca927fcf25cf86f"}, - {file = "lxml-4.9.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:13598ecfbd2e86ea7ae45ec28a2a54fb87ee9b9fdb0f6d343297d8e548392c03"}, - {file = "lxml-4.9.2-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:880bbbcbe2fca64e2f4d8e04db47bcdf504936fa2b33933efd945e1b429bea8c"}, - {file = "lxml-4.9.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:7d2278d59425777cfcb19735018d897ca8303abe67cc735f9f97177ceff8027f"}, - {file = "lxml-4.9.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:5344a43228767f53a9df6e5b253f8cdca7dfc7b7aeae52551958192f56d98457"}, - {file = "lxml-4.9.2-cp38-cp38-win32.whl", hash = "sha256:925073b2fe14ab9b87e73f9a5fde6ce6392da430f3004d8b72cc86f746f5163b"}, - {file = "lxml-4.9.2-cp38-cp38-win_amd64.whl", hash = "sha256:9b22c5c66f67ae00c0199f6055705bc3eb3fcb08d03d2ec4059a2b1b25ed48d7"}, - {file = "lxml-4.9.2-cp39-cp39-macosx_10_15_x86_64.whl", hash = "sha256:5f50a1c177e2fa3ee0667a5ab79fdc6b23086bc8b589d90b93b4bd17eb0e64d1"}, - {file = "lxml-4.9.2-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:090c6543d3696cbe15b4ac6e175e576bcc3f1ccfbba970061b7300b0c15a2140"}, - {file = "lxml-4.9.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:63da2ccc0857c311d764e7d3d90f429c252e83b52d1f8f1d1fe55be26827d1f4"}, - {file = "lxml-4.9.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:5b4545b8a40478183ac06c073e81a5ce4cf01bf1734962577cf2bb569a5b3bbf"}, - {file = "lxml-4.9.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2e430cd2824f05f2d4f687701144556646bae8f249fd60aa1e4c768ba7018947"}, - {file = "lxml-4.9.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:6804daeb7ef69e7b36f76caddb85cccd63d0c56dedb47555d2fc969e2af6a1a5"}, - {file = "lxml-4.9.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:a6e441a86553c310258aca15d1c05903aaf4965b23f3bc2d55f200804e005ee5"}, - {file = "lxml-4.9.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ca34efc80a29351897e18888c71c6aca4a359247c87e0b1c7ada14f0ab0c0fb2"}, - {file = "lxml-4.9.2-cp39-cp39-win32.whl", hash = "sha256:6b418afe5df18233fc6b6093deb82a32895b6bb0b1155c2cdb05203f583053f1"}, - {file = "lxml-4.9.2-cp39-cp39-win_amd64.whl", hash = "sha256:f1496ea22ca2c830cbcbd473de8f114a320da308438ae65abad6bab7867fe38f"}, - {file = "lxml-4.9.2-pp37-pypy37_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:b264171e3143d842ded311b7dccd46ff9ef34247129ff5bf5066123c55c2431c"}, - {file = "lxml-4.9.2-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:0dc313ef231edf866912e9d8f5a042ddab56c752619e92dfd3a2c277e6a7299a"}, - {file = "lxml-4.9.2-pp38-pypy38_pp73-macosx_10_15_x86_64.whl", hash = "sha256:16efd54337136e8cd72fb9485c368d91d77a47ee2d42b057564aae201257d419"}, - {file = "lxml-4.9.2-pp38-pypy38_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:0f2b1e0d79180f344ff9f321327b005ca043a50ece8713de61d1cb383fb8ac05"}, - {file = "lxml-4.9.2-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:7b770ed79542ed52c519119473898198761d78beb24b107acf3ad65deae61f1f"}, - {file = "lxml-4.9.2-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:efa29c2fe6b4fdd32e8ef81c1528506895eca86e1d8c4657fda04c9b3786ddf9"}, - {file = "lxml-4.9.2-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:7e91ee82f4199af8c43d8158024cbdff3d931df350252288f0d4ce656df7f3b5"}, - {file = "lxml-4.9.2-pp39-pypy39_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:b23e19989c355ca854276178a0463951a653309fb8e57ce674497f2d9f208746"}, - {file = "lxml-4.9.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:01d36c05f4afb8f7c20fd9ed5badca32a2029b93b1750f571ccc0b142531caf7"}, - {file = "lxml-4.9.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:7b515674acfdcadb0eb5d00d8a709868173acece5cb0be3dd165950cbfdf5409"}, - {file = "lxml-4.9.2.tar.gz", hash = "sha256:2455cfaeb7ac70338b3257f41e21f0724f4b5b0c0e7702da67ee6c3640835b67"}, + {file = "lxml-4.9.4-cp27-cp27m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e214025e23db238805a600f1f37bf9f9a15413c7bf5f9d6ae194f84980c78722"}, + {file = "lxml-4.9.4-cp27-cp27m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:ec53a09aee61d45e7dbe7e91252ff0491b6b5fee3d85b2d45b173d8ab453efc1"}, + {file = "lxml-4.9.4-cp27-cp27m-win32.whl", hash = "sha256:7d1d6c9e74c70ddf524e3c09d9dc0522aba9370708c2cb58680ea40174800013"}, + {file = "lxml-4.9.4-cp27-cp27m-win_amd64.whl", hash = "sha256:cb53669442895763e61df5c995f0e8361b61662f26c1b04ee82899c2789c8f69"}, + {file = "lxml-4.9.4-cp27-cp27mu-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:647bfe88b1997d7ae8d45dabc7c868d8cb0c8412a6e730a7651050b8c7289cf2"}, + {file = "lxml-4.9.4-cp27-cp27mu-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:4d973729ce04784906a19108054e1fd476bc85279a403ea1a72fdb051c76fa48"}, + {file = "lxml-4.9.4-cp310-cp310-macosx_11_0_x86_64.whl", hash = "sha256:056a17eaaf3da87a05523472ae84246f87ac2f29a53306466c22e60282e54ff8"}, + {file = "lxml-4.9.4-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:aaa5c173a26960fe67daa69aa93d6d6a1cd714a6eb13802d4e4bd1d24a530644"}, + {file = "lxml-4.9.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:647459b23594f370c1c01768edaa0ba0959afc39caeeb793b43158bb9bb6a663"}, + {file = "lxml-4.9.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:bdd9abccd0927673cffe601d2c6cdad1c9321bf3437a2f507d6b037ef91ea307"}, + {file = "lxml-4.9.4-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:00e91573183ad273e242db5585b52670eddf92bacad095ce25c1e682da14ed91"}, + {file = "lxml-4.9.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:a602ed9bd2c7d85bd58592c28e101bd9ff9c718fbde06545a70945ffd5d11868"}, + {file = "lxml-4.9.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:de362ac8bc962408ad8fae28f3967ce1a262b5d63ab8cefb42662566737f1dc7"}, + {file = "lxml-4.9.4-cp310-cp310-win32.whl", hash = "sha256:33714fcf5af4ff7e70a49731a7cc8fd9ce910b9ac194f66eaa18c3cc0a4c02be"}, + {file = "lxml-4.9.4-cp310-cp310-win_amd64.whl", hash = "sha256:d3caa09e613ece43ac292fbed513a4bce170681a447d25ffcbc1b647d45a39c5"}, + {file = "lxml-4.9.4-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:359a8b09d712df27849e0bcb62c6a3404e780b274b0b7e4c39a88826d1926c28"}, + {file = "lxml-4.9.4-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:43498ea734ccdfb92e1886dfedaebeb81178a241d39a79d5351ba2b671bff2b2"}, + {file = "lxml-4.9.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:4855161013dfb2b762e02b3f4d4a21cc7c6aec13c69e3bffbf5022b3e708dd97"}, + {file = "lxml-4.9.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:c71b5b860c5215fdbaa56f715bc218e45a98477f816b46cfde4a84d25b13274e"}, + {file = "lxml-4.9.4-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:9a2b5915c333e4364367140443b59f09feae42184459b913f0f41b9fed55794a"}, + {file = "lxml-4.9.4-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:d82411dbf4d3127b6cde7da0f9373e37ad3a43e89ef374965465928f01c2b979"}, + {file = "lxml-4.9.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:273473d34462ae6e97c0f4e517bd1bf9588aa67a1d47d93f760a1282640e24ac"}, + {file = "lxml-4.9.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:389d2b2e543b27962990ab529ac6720c3dded588cc6d0f6557eec153305a3622"}, + {file = "lxml-4.9.4-cp311-cp311-win32.whl", hash = "sha256:8aecb5a7f6f7f8fe9cac0bcadd39efaca8bbf8d1bf242e9f175cbe4c925116c3"}, + {file = "lxml-4.9.4-cp311-cp311-win_amd64.whl", hash = "sha256:c7721a3ef41591341388bb2265395ce522aba52f969d33dacd822da8f018aff8"}, + {file = "lxml-4.9.4-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:dbcb2dc07308453db428a95a4d03259bd8caea97d7f0776842299f2d00c72fc8"}, + {file = "lxml-4.9.4-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:01bf1df1db327e748dcb152d17389cf6d0a8c5d533ef9bab781e9d5037619229"}, + {file = "lxml-4.9.4-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:e8f9f93a23634cfafbad6e46ad7d09e0f4a25a2400e4a64b1b7b7c0fbaa06d9d"}, + {file = "lxml-4.9.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:3f3f00a9061605725df1816f5713d10cd94636347ed651abdbc75828df302b20"}, + {file = "lxml-4.9.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:953dd5481bd6252bd480d6ec431f61d7d87fdcbbb71b0d2bdcfc6ae00bb6fb10"}, + {file = "lxml-4.9.4-cp312-cp312-win32.whl", hash = "sha256:266f655d1baff9c47b52f529b5f6bec33f66042f65f7c56adde3fcf2ed62ae8b"}, + {file = "lxml-4.9.4-cp312-cp312-win_amd64.whl", hash = "sha256:f1faee2a831fe249e1bae9cbc68d3cd8a30f7e37851deee4d7962b17c410dd56"}, + {file = "lxml-4.9.4-cp35-cp35m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:23d891e5bdc12e2e506e7d225d6aa929e0a0368c9916c1fddefab88166e98b20"}, + {file = "lxml-4.9.4-cp35-cp35m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:e96a1788f24d03e8d61679f9881a883ecdf9c445a38f9ae3f3f193ab6c591c66"}, + {file = "lxml-4.9.4-cp36-cp36m-macosx_11_0_x86_64.whl", hash = "sha256:5557461f83bb7cc718bc9ee1f7156d50e31747e5b38d79cf40f79ab1447afd2d"}, + {file = "lxml-4.9.4-cp36-cp36m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:fdb325b7fba1e2c40b9b1db407f85642e32404131c08480dd652110fc908561b"}, + {file = "lxml-4.9.4-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3d74d4a3c4b8f7a1f676cedf8e84bcc57705a6d7925e6daef7a1e54ae543a197"}, + {file = "lxml-4.9.4-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:ac7674d1638df129d9cb4503d20ffc3922bd463c865ef3cb412f2c926108e9a4"}, + {file = "lxml-4.9.4-cp36-cp36m-manylinux_2_28_x86_64.whl", hash = "sha256:ddd92e18b783aeb86ad2132d84a4b795fc5ec612e3545c1b687e7747e66e2b53"}, + {file = "lxml-4.9.4-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2bd9ac6e44f2db368ef8986f3989a4cad3de4cd55dbdda536e253000c801bcc7"}, + {file = "lxml-4.9.4-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:bc354b1393dce46026ab13075f77b30e40b61b1a53e852e99d3cc5dd1af4bc85"}, + {file = "lxml-4.9.4-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:f836f39678cb47c9541f04d8ed4545719dc31ad850bf1832d6b4171e30d65d23"}, + {file = "lxml-4.9.4-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:9c131447768ed7bc05a02553d939e7f0e807e533441901dd504e217b76307745"}, + {file = "lxml-4.9.4-cp36-cp36m-win32.whl", hash = "sha256:bafa65e3acae612a7799ada439bd202403414ebe23f52e5b17f6ffc2eb98c2be"}, + {file = "lxml-4.9.4-cp36-cp36m-win_amd64.whl", hash = "sha256:6197c3f3c0b960ad033b9b7d611db11285bb461fc6b802c1dd50d04ad715c225"}, + {file = "lxml-4.9.4-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:7b378847a09d6bd46047f5f3599cdc64fcb4cc5a5a2dd0a2af610361fbe77b16"}, + {file = "lxml-4.9.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:1343df4e2e6e51182aad12162b23b0a4b3fd77f17527a78c53f0f23573663545"}, + {file = "lxml-4.9.4-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:6dbdacf5752fbd78ccdb434698230c4f0f95df7dd956d5f205b5ed6911a1367c"}, + {file = "lxml-4.9.4-cp37-cp37m-manylinux_2_28_x86_64.whl", hash = "sha256:506becdf2ecaebaf7f7995f776394fcc8bd8a78022772de66677c84fb02dd33d"}, + {file = "lxml-4.9.4-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ca8e44b5ba3edb682ea4e6185b49661fc22b230cf811b9c13963c9f982d1d964"}, + {file = "lxml-4.9.4-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:9d9d5726474cbbef279fd709008f91a49c4f758bec9c062dfbba88eab00e3ff9"}, + {file = "lxml-4.9.4-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:bbdd69e20fe2943b51e2841fc1e6a3c1de460d630f65bde12452d8c97209464d"}, + {file = "lxml-4.9.4-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:8671622256a0859f5089cbe0ce4693c2af407bc053dcc99aadff7f5310b4aa02"}, + {file = "lxml-4.9.4-cp37-cp37m-win32.whl", hash = "sha256:dd4fda67f5faaef4f9ee5383435048ee3e11ad996901225ad7615bc92245bc8e"}, + {file = "lxml-4.9.4-cp37-cp37m-win_amd64.whl", hash = "sha256:6bee9c2e501d835f91460b2c904bc359f8433e96799f5c2ff20feebd9bb1e590"}, + {file = "lxml-4.9.4-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:1f10f250430a4caf84115b1e0f23f3615566ca2369d1962f82bef40dd99cd81a"}, + {file = "lxml-4.9.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:3b505f2bbff50d261176e67be24e8909e54b5d9d08b12d4946344066d66b3e43"}, + {file = "lxml-4.9.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:1449f9451cd53e0fd0a7ec2ff5ede4686add13ac7a7bfa6988ff6d75cff3ebe2"}, + {file = "lxml-4.9.4-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:4ece9cca4cd1c8ba889bfa67eae7f21d0d1a2e715b4d5045395113361e8c533d"}, + {file = "lxml-4.9.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:59bb5979f9941c61e907ee571732219fa4774d5a18f3fa5ff2df963f5dfaa6bc"}, + {file = "lxml-4.9.4-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:b1980dbcaad634fe78e710c8587383e6e3f61dbe146bcbfd13a9c8ab2d7b1192"}, + {file = "lxml-4.9.4-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:9ae6c3363261021144121427b1552b29e7b59de9d6a75bf51e03bc072efb3c37"}, + {file = "lxml-4.9.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:bcee502c649fa6351b44bb014b98c09cb00982a475a1912a9881ca28ab4f9cd9"}, + {file = "lxml-4.9.4-cp38-cp38-win32.whl", hash = "sha256:a8edae5253efa75c2fc79a90068fe540b197d1c7ab5803b800fccfe240eed33c"}, + {file = "lxml-4.9.4-cp38-cp38-win_amd64.whl", hash = "sha256:701847a7aaefef121c5c0d855b2affa5f9bd45196ef00266724a80e439220e46"}, + {file = "lxml-4.9.4-cp39-cp39-macosx_11_0_x86_64.whl", hash = "sha256:f610d980e3fccf4394ab3806de6065682982f3d27c12d4ce3ee46a8183d64a6a"}, + {file = "lxml-4.9.4-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:aa9b5abd07f71b081a33115d9758ef6077924082055005808f68feccb27616bd"}, + {file = "lxml-4.9.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:365005e8b0718ea6d64b374423e870648ab47c3a905356ab6e5a5ff03962b9a9"}, + {file = "lxml-4.9.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:16b9ec51cc2feab009e800f2c6327338d6ee4e752c76e95a35c4465e80390ccd"}, + {file = "lxml-4.9.4-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:a905affe76f1802edcac554e3ccf68188bea16546071d7583fb1b693f9cf756b"}, + {file = "lxml-4.9.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:fd814847901df6e8de13ce69b84c31fc9b3fb591224d6762d0b256d510cbf382"}, + {file = "lxml-4.9.4-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:91bbf398ac8bb7d65a5a52127407c05f75a18d7015a270fdd94bbcb04e65d573"}, + {file = "lxml-4.9.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:f99768232f036b4776ce419d3244a04fe83784bce871b16d2c2e984c7fcea847"}, + {file = "lxml-4.9.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:bb5bd6212eb0edfd1e8f254585290ea1dadc3687dd8fd5e2fd9a87c31915cdab"}, + {file = "lxml-4.9.4-cp39-cp39-win32.whl", hash = "sha256:88f7c383071981c74ec1998ba9b437659e4fd02a3c4a4d3efc16774eb108d0ec"}, + {file = "lxml-4.9.4-cp39-cp39-win_amd64.whl", hash = "sha256:936e8880cc00f839aa4173f94466a8406a96ddce814651075f95837316369899"}, + {file = "lxml-4.9.4-pp310-pypy310_pp73-macosx_11_0_x86_64.whl", hash = "sha256:f6c35b2f87c004270fa2e703b872fcc984d714d430b305145c39d53074e1ffe0"}, + {file = "lxml-4.9.4-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:606d445feeb0856c2b424405236a01c71af7c97e5fe42fbc778634faef2b47e4"}, + {file = "lxml-4.9.4-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:a1bdcbebd4e13446a14de4dd1825f1e778e099f17f79718b4aeaf2403624b0f7"}, + {file = "lxml-4.9.4-pp37-pypy37_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:0a08c89b23117049ba171bf51d2f9c5f3abf507d65d016d6e0fa2f37e18c0fc5"}, + {file = "lxml-4.9.4-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:232fd30903d3123be4c435fb5159938c6225ee8607b635a4d3fca847003134ba"}, + {file = "lxml-4.9.4-pp37-pypy37_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:231142459d32779b209aa4b4d460b175cadd604fed856f25c1571a9d78114771"}, + {file = "lxml-4.9.4-pp38-pypy38_pp73-macosx_11_0_x86_64.whl", hash = "sha256:520486f27f1d4ce9654154b4494cf9307b495527f3a2908ad4cb48e4f7ed7ef7"}, + {file = "lxml-4.9.4-pp38-pypy38_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:562778586949be7e0d7435fcb24aca4810913771f845d99145a6cee64d5b67ca"}, + {file = "lxml-4.9.4-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:a9e7c6d89c77bb2770c9491d988f26a4b161d05c8ca58f63fb1f1b6b9a74be45"}, + {file = "lxml-4.9.4-pp38-pypy38_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:786d6b57026e7e04d184313c1359ac3d68002c33e4b1042ca58c362f1d09ff58"}, + {file = "lxml-4.9.4-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:95ae6c5a196e2f239150aa4a479967351df7f44800c93e5a975ec726fef005e2"}, + {file = "lxml-4.9.4-pp39-pypy39_pp73-macosx_11_0_x86_64.whl", hash = "sha256:9b556596c49fa1232b0fff4b0e69b9d4083a502e60e404b44341e2f8fb7187f5"}, + {file = "lxml-4.9.4-pp39-pypy39_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:cc02c06e9e320869d7d1bd323df6dd4281e78ac2e7f8526835d3d48c69060683"}, + {file = "lxml-4.9.4-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:857d6565f9aa3464764c2cb6a2e3c2e75e1970e877c188f4aeae45954a314e0c"}, + {file = "lxml-4.9.4-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:c42ae7e010d7d6bc51875d768110c10e8a59494855c3d4c348b068f5fb81fdcd"}, + {file = "lxml-4.9.4-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:f10250bb190fb0742e3e1958dd5c100524c2cc5096c67c8da51233f7448dc137"}, + {file = "lxml-4.9.4.tar.gz", hash = "sha256:b1541e50b78e15fa06a2670157a1962ef06591d4c998b998047fff5e3236880e"}, ] [package.extras] cssselect = ["cssselect (>=0.7)"] html5 = ["html5lib"] htmlsoup = ["BeautifulSoup4"] -source = ["Cython (>=0.29.7)"] +source = ["Cython (==0.29.37)"] [[package]] name = "mpmath" version = "1.3.0" description = "Python library for arbitrary-precision floating-point arithmetic" -category = "main" optional = false python-versions = "*" files = [ @@ -706,152 +845,165 @@ tests = ["pytest (>=4.6)"] [[package]] name = "multidict" -version = "6.0.4" +version = "6.0.5" description = "multidict implementation" -category = "main" optional = false python-versions = ">=3.7" files = [ - {file = "multidict-6.0.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:0b1a97283e0c85772d613878028fec909f003993e1007eafa715b24b377cb9b8"}, - {file = "multidict-6.0.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:eeb6dcc05e911516ae3d1f207d4b0520d07f54484c49dfc294d6e7d63b734171"}, - {file = "multidict-6.0.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d6d635d5209b82a3492508cf5b365f3446afb65ae7ebd755e70e18f287b0adf7"}, - {file = "multidict-6.0.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c048099e4c9e9d615545e2001d3d8a4380bd403e1a0578734e0d31703d1b0c0b"}, - {file = "multidict-6.0.4-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ea20853c6dbbb53ed34cb4d080382169b6f4554d394015f1bef35e881bf83547"}, - {file = "multidict-6.0.4-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:16d232d4e5396c2efbbf4f6d4df89bfa905eb0d4dc5b3549d872ab898451f569"}, - {file = "multidict-6.0.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:36c63aaa167f6c6b04ef2c85704e93af16c11d20de1d133e39de6a0e84582a93"}, - {file = "multidict-6.0.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:64bdf1086b6043bf519869678f5f2757f473dee970d7abf6da91ec00acb9cb98"}, - {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:43644e38f42e3af682690876cff722d301ac585c5b9e1eacc013b7a3f7b696a0"}, - {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:7582a1d1030e15422262de9f58711774e02fa80df0d1578995c76214f6954988"}, - {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:ddff9c4e225a63a5afab9dd15590432c22e8057e1a9a13d28ed128ecf047bbdc"}, - {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:ee2a1ece51b9b9e7752e742cfb661d2a29e7bcdba2d27e66e28a99f1890e4fa0"}, - {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a2e4369eb3d47d2034032a26c7a80fcb21a2cb22e1173d761a162f11e562caa5"}, - {file = "multidict-6.0.4-cp310-cp310-win32.whl", hash = "sha256:574b7eae1ab267e5f8285f0fe881f17efe4b98c39a40858247720935b893bba8"}, - {file = "multidict-6.0.4-cp310-cp310-win_amd64.whl", hash = "sha256:4dcbb0906e38440fa3e325df2359ac6cb043df8e58c965bb45f4e406ecb162cc"}, - {file = "multidict-6.0.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:0dfad7a5a1e39c53ed00d2dd0c2e36aed4650936dc18fd9a1826a5ae1cad6f03"}, - {file = "multidict-6.0.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:64da238a09d6039e3bd39bb3aee9c21a5e34f28bfa5aa22518581f910ff94af3"}, - {file = "multidict-6.0.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ff959bee35038c4624250473988b24f846cbeb2c6639de3602c073f10410ceba"}, - {file = "multidict-6.0.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:01a3a55bd90018c9c080fbb0b9f4891db37d148a0a18722b42f94694f8b6d4c9"}, - {file = "multidict-6.0.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c5cb09abb18c1ea940fb99360ea0396f34d46566f157122c92dfa069d3e0e982"}, - {file = "multidict-6.0.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:666daae833559deb2d609afa4490b85830ab0dfca811a98b70a205621a6109fe"}, - {file = "multidict-6.0.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:11bdf3f5e1518b24530b8241529d2050014c884cf18b6fc69c0c2b30ca248710"}, - {file = "multidict-6.0.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7d18748f2d30f94f498e852c67d61261c643b349b9d2a581131725595c45ec6c"}, - {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:458f37be2d9e4c95e2d8866a851663cbc76e865b78395090786f6cd9b3bbf4f4"}, - {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:b1a2eeedcead3a41694130495593a559a668f382eee0727352b9a41e1c45759a"}, - {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:7d6ae9d593ef8641544d6263c7fa6408cc90370c8cb2bbb65f8d43e5b0351d9c"}, - {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:5979b5632c3e3534e42ca6ff856bb24b2e3071b37861c2c727ce220d80eee9ed"}, - {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:dcfe792765fab89c365123c81046ad4103fcabbc4f56d1c1997e6715e8015461"}, - {file = "multidict-6.0.4-cp311-cp311-win32.whl", hash = "sha256:3601a3cece3819534b11d4efc1eb76047488fddd0c85a3948099d5da4d504636"}, - {file = "multidict-6.0.4-cp311-cp311-win_amd64.whl", hash = "sha256:81a4f0b34bd92df3da93315c6a59034df95866014ac08535fc819f043bfd51f0"}, - {file = "multidict-6.0.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:67040058f37a2a51ed8ea8f6b0e6ee5bd78ca67f169ce6122f3e2ec80dfe9b78"}, - {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:853888594621e6604c978ce2a0444a1e6e70c8d253ab65ba11657659dcc9100f"}, - {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:39ff62e7d0f26c248b15e364517a72932a611a9b75f35b45be078d81bdb86603"}, - {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:af048912e045a2dc732847d33821a9d84ba553f5c5f028adbd364dd4765092ac"}, - {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b1e8b901e607795ec06c9e42530788c45ac21ef3aaa11dbd0c69de543bfb79a9"}, - {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:62501642008a8b9871ddfccbf83e4222cf8ac0d5aeedf73da36153ef2ec222d2"}, - {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:99b76c052e9f1bc0721f7541e5e8c05db3941eb9ebe7b8553c625ef88d6eefde"}, - {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:509eac6cf09c794aa27bcacfd4d62c885cce62bef7b2c3e8b2e49d365b5003fe"}, - {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:21a12c4eb6ddc9952c415f24eef97e3e55ba3af61f67c7bc388dcdec1404a067"}, - {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:5cad9430ab3e2e4fa4a2ef4450f548768400a2ac635841bc2a56a2052cdbeb87"}, - {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:ab55edc2e84460694295f401215f4a58597f8f7c9466faec545093045476327d"}, - {file = "multidict-6.0.4-cp37-cp37m-win32.whl", hash = "sha256:5a4dcf02b908c3b8b17a45fb0f15b695bf117a67b76b7ad18b73cf8e92608775"}, - {file = "multidict-6.0.4-cp37-cp37m-win_amd64.whl", hash = "sha256:6ed5f161328b7df384d71b07317f4d8656434e34591f20552c7bcef27b0ab88e"}, - {file = "multidict-6.0.4-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5fc1b16f586f049820c5c5b17bb4ee7583092fa0d1c4e28b5239181ff9532e0c"}, - {file = "multidict-6.0.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1502e24330eb681bdaa3eb70d6358e818e8e8f908a22a1851dfd4e15bc2f8161"}, - {file = "multidict-6.0.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:b692f419760c0e65d060959df05f2a531945af31fda0c8a3b3195d4efd06de11"}, - {file = "multidict-6.0.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45e1ecb0379bfaab5eef059f50115b54571acfbe422a14f668fc8c27ba410e7e"}, - {file = "multidict-6.0.4-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ddd3915998d93fbcd2566ddf9cf62cdb35c9e093075f862935573d265cf8f65d"}, - {file = "multidict-6.0.4-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:59d43b61c59d82f2effb39a93c48b845efe23a3852d201ed2d24ba830d0b4cf2"}, - {file = "multidict-6.0.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cc8e1d0c705233c5dd0c5e6460fbad7827d5d36f310a0fadfd45cc3029762258"}, - {file = "multidict-6.0.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d6aa0418fcc838522256761b3415822626f866758ee0bc6632c9486b179d0b52"}, - {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:6748717bb10339c4760c1e63da040f5f29f5ed6e59d76daee30305894069a660"}, - {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:4d1a3d7ef5e96b1c9e92f973e43aa5e5b96c659c9bc3124acbbd81b0b9c8a951"}, - {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:4372381634485bec7e46718edc71528024fcdc6f835baefe517b34a33c731d60"}, - {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:fc35cb4676846ef752816d5be2193a1e8367b4c1397b74a565a9d0389c433a1d"}, - {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:4b9d9e4e2b37daddb5c23ea33a3417901fa7c7b3dee2d855f63ee67a0b21e5b1"}, - {file = "multidict-6.0.4-cp38-cp38-win32.whl", hash = "sha256:e41b7e2b59679edfa309e8db64fdf22399eec4b0b24694e1b2104fb789207779"}, - {file = "multidict-6.0.4-cp38-cp38-win_amd64.whl", hash = "sha256:d6c254ba6e45d8e72739281ebc46ea5eb5f101234f3ce171f0e9f5cc86991480"}, - {file = "multidict-6.0.4-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:16ab77bbeb596e14212e7bab8429f24c1579234a3a462105cda4a66904998664"}, - {file = "multidict-6.0.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:bc779e9e6f7fda81b3f9aa58e3a6091d49ad528b11ed19f6621408806204ad35"}, - {file = "multidict-6.0.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4ceef517eca3e03c1cceb22030a3e39cb399ac86bff4e426d4fc6ae49052cc60"}, - {file = "multidict-6.0.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:281af09f488903fde97923c7744bb001a9b23b039a909460d0f14edc7bf59706"}, - {file = "multidict-6.0.4-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:52f2dffc8acaba9a2f27174c41c9e57f60b907bb9f096b36b1a1f3be71c6284d"}, - {file = "multidict-6.0.4-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b41156839806aecb3641f3208c0dafd3ac7775b9c4c422d82ee2a45c34ba81ca"}, - {file = "multidict-6.0.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d5e3fc56f88cc98ef8139255cf8cd63eb2c586531e43310ff859d6bb3a6b51f1"}, - {file = "multidict-6.0.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8316a77808c501004802f9beebde51c9f857054a0c871bd6da8280e718444449"}, - {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:f70b98cd94886b49d91170ef23ec5c0e8ebb6f242d734ed7ed677b24d50c82cf"}, - {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:bf6774e60d67a9efe02b3616fee22441d86fab4c6d335f9d2051d19d90a40063"}, - {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:e69924bfcdda39b722ef4d9aa762b2dd38e4632b3641b1d9a57ca9cd18f2f83a"}, - {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:6b181d8c23da913d4ff585afd1155a0e1194c0b50c54fcfe286f70cdaf2b7176"}, - {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:52509b5be062d9eafc8170e53026fbc54cf3b32759a23d07fd935fb04fc22d95"}, - {file = "multidict-6.0.4-cp39-cp39-win32.whl", hash = "sha256:27c523fbfbdfd19c6867af7346332b62b586eed663887392cff78d614f9ec313"}, - {file = "multidict-6.0.4-cp39-cp39-win_amd64.whl", hash = "sha256:33029f5734336aa0d4c0384525da0387ef89148dc7191aae00ca5fb23d7aafc2"}, - {file = "multidict-6.0.4.tar.gz", hash = "sha256:3666906492efb76453c0e7b97f2cf459b0682e7402c0489a95484965dbc1da49"}, + {file = "multidict-6.0.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:228b644ae063c10e7f324ab1ab6b548bdf6f8b47f3ec234fef1093bc2735e5f9"}, + {file = "multidict-6.0.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:896ebdcf62683551312c30e20614305f53125750803b614e9e6ce74a96232604"}, + {file = "multidict-6.0.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:411bf8515f3be9813d06004cac41ccf7d1cd46dfe233705933dd163b60e37600"}, + {file = "multidict-6.0.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1d147090048129ce3c453f0292e7697d333db95e52616b3793922945804a433c"}, + {file = "multidict-6.0.5-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:215ed703caf15f578dca76ee6f6b21b7603791ae090fbf1ef9d865571039ade5"}, + {file = "multidict-6.0.5-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7c6390cf87ff6234643428991b7359b5f59cc15155695deb4eda5c777d2b880f"}, + {file = "multidict-6.0.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21fd81c4ebdb4f214161be351eb5bcf385426bf023041da2fd9e60681f3cebae"}, + {file = "multidict-6.0.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3cc2ad10255f903656017363cd59436f2111443a76f996584d1077e43ee51182"}, + {file = "multidict-6.0.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:6939c95381e003f54cd4c5516740faba40cf5ad3eeff460c3ad1d3e0ea2549bf"}, + {file = "multidict-6.0.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:220dd781e3f7af2c2c1053da9fa96d9cf3072ca58f057f4c5adaaa1cab8fc442"}, + {file = "multidict-6.0.5-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:766c8f7511df26d9f11cd3a8be623e59cca73d44643abab3f8c8c07620524e4a"}, + {file = "multidict-6.0.5-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:fe5d7785250541f7f5019ab9cba2c71169dc7d74d0f45253f8313f436458a4ef"}, + {file = "multidict-6.0.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c1c1496e73051918fcd4f58ff2e0f2f3066d1c76a0c6aeffd9b45d53243702cc"}, + {file = "multidict-6.0.5-cp310-cp310-win32.whl", hash = "sha256:7afcdd1fc07befad18ec4523a782cde4e93e0a2bf71239894b8d61ee578c1319"}, + {file = "multidict-6.0.5-cp310-cp310-win_amd64.whl", hash = "sha256:99f60d34c048c5c2fabc766108c103612344c46e35d4ed9ae0673d33c8fb26e8"}, + {file = "multidict-6.0.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:f285e862d2f153a70586579c15c44656f888806ed0e5b56b64489afe4a2dbfba"}, + {file = "multidict-6.0.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:53689bb4e102200a4fafa9de9c7c3c212ab40a7ab2c8e474491914d2305f187e"}, + {file = "multidict-6.0.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:612d1156111ae11d14afaf3a0669ebf6c170dbb735e510a7438ffe2369a847fd"}, + {file = "multidict-6.0.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7be7047bd08accdb7487737631d25735c9a04327911de89ff1b26b81745bd4e3"}, + {file = "multidict-6.0.5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:de170c7b4fe6859beb8926e84f7d7d6c693dfe8e27372ce3b76f01c46e489fcf"}, + {file = "multidict-6.0.5-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:04bde7a7b3de05732a4eb39c94574db1ec99abb56162d6c520ad26f83267de29"}, + {file = "multidict-6.0.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:85f67aed7bb647f93e7520633d8f51d3cbc6ab96957c71272b286b2f30dc70ed"}, + {file = "multidict-6.0.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:425bf820055005bfc8aa9a0b99ccb52cc2f4070153e34b701acc98d201693733"}, + {file = "multidict-6.0.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:d3eb1ceec286eba8220c26f3b0096cf189aea7057b6e7b7a2e60ed36b373b77f"}, + {file = "multidict-6.0.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:7901c05ead4b3fb75113fb1dd33eb1253c6d3ee37ce93305acd9d38e0b5f21a4"}, + {file = "multidict-6.0.5-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:e0e79d91e71b9867c73323a3444724d496c037e578a0e1755ae159ba14f4f3d1"}, + {file = "multidict-6.0.5-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:29bfeb0dff5cb5fdab2023a7a9947b3b4af63e9c47cae2a10ad58394b517fddc"}, + {file = "multidict-6.0.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e030047e85cbcedbfc073f71836d62dd5dadfbe7531cae27789ff66bc551bd5e"}, + {file = "multidict-6.0.5-cp311-cp311-win32.whl", hash = "sha256:2f4848aa3baa109e6ab81fe2006c77ed4d3cd1e0ac2c1fbddb7b1277c168788c"}, + {file = "multidict-6.0.5-cp311-cp311-win_amd64.whl", hash = "sha256:2faa5ae9376faba05f630d7e5e6be05be22913782b927b19d12b8145968a85ea"}, + {file = "multidict-6.0.5-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:51d035609b86722963404f711db441cf7134f1889107fb171a970c9701f92e1e"}, + {file = "multidict-6.0.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:cbebcd5bcaf1eaf302617c114aa67569dd3f090dd0ce8ba9e35e9985b41ac35b"}, + {file = "multidict-6.0.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2ffc42c922dbfddb4a4c3b438eb056828719f07608af27d163191cb3e3aa6cc5"}, + {file = "multidict-6.0.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ceb3b7e6a0135e092de86110c5a74e46bda4bd4fbfeeb3a3bcec79c0f861e450"}, + {file = "multidict-6.0.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:79660376075cfd4b2c80f295528aa6beb2058fd289f4c9252f986751a4cd0496"}, + {file = "multidict-6.0.5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e4428b29611e989719874670fd152b6625500ad6c686d464e99f5aaeeaca175a"}, + {file = "multidict-6.0.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d84a5c3a5f7ce6db1f999fb9438f686bc2e09d38143f2d93d8406ed2dd6b9226"}, + {file = "multidict-6.0.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:76c0de87358b192de7ea9649beb392f107dcad9ad27276324c24c91774ca5271"}, + {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:79a6d2ba910adb2cbafc95dad936f8b9386e77c84c35bc0add315b856d7c3abb"}, + {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:92d16a3e275e38293623ebf639c471d3e03bb20b8ebb845237e0d3664914caef"}, + {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:fb616be3538599e797a2017cccca78e354c767165e8858ab5116813146041a24"}, + {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:14c2976aa9038c2629efa2c148022ed5eb4cb939e15ec7aace7ca932f48f9ba6"}, + {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:435a0984199d81ca178b9ae2c26ec3d49692d20ee29bc4c11a2a8d4514c67eda"}, + {file = "multidict-6.0.5-cp312-cp312-win32.whl", hash = "sha256:9fe7b0653ba3d9d65cbe7698cca585bf0f8c83dbbcc710db9c90f478e175f2d5"}, + {file = "multidict-6.0.5-cp312-cp312-win_amd64.whl", hash = "sha256:01265f5e40f5a17f8241d52656ed27192be03bfa8764d88e8220141d1e4b3556"}, + {file = "multidict-6.0.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:19fe01cea168585ba0f678cad6f58133db2aa14eccaf22f88e4a6dccadfad8b3"}, + {file = "multidict-6.0.5-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6bf7a982604375a8d49b6cc1b781c1747f243d91b81035a9b43a2126c04766f5"}, + {file = "multidict-6.0.5-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:107c0cdefe028703fb5dafe640a409cb146d44a6ae201e55b35a4af8e95457dd"}, + {file = "multidict-6.0.5-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:403c0911cd5d5791605808b942c88a8155c2592e05332d2bf78f18697a5fa15e"}, + {file = "multidict-6.0.5-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aeaf541ddbad8311a87dd695ed9642401131ea39ad7bc8cf3ef3967fd093b626"}, + {file = "multidict-6.0.5-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e4972624066095e52b569e02b5ca97dbd7a7ddd4294bf4e7247d52635630dd83"}, + {file = "multidict-6.0.5-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:d946b0a9eb8aaa590df1fe082cee553ceab173e6cb5b03239716338629c50c7a"}, + {file = "multidict-6.0.5-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:b55358304d7a73d7bdf5de62494aaf70bd33015831ffd98bc498b433dfe5b10c"}, + {file = "multidict-6.0.5-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:a3145cb08d8625b2d3fee1b2d596a8766352979c9bffe5d7833e0503d0f0b5e5"}, + {file = "multidict-6.0.5-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:d65f25da8e248202bd47445cec78e0025c0fe7582b23ec69c3b27a640dd7a8e3"}, + {file = "multidict-6.0.5-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:c9bf56195c6bbd293340ea82eafd0071cb3d450c703d2c93afb89f93b8386ccc"}, + {file = "multidict-6.0.5-cp37-cp37m-win32.whl", hash = "sha256:69db76c09796b313331bb7048229e3bee7928eb62bab5e071e9f7fcc4879caee"}, + {file = "multidict-6.0.5-cp37-cp37m-win_amd64.whl", hash = "sha256:fce28b3c8a81b6b36dfac9feb1de115bab619b3c13905b419ec71d03a3fc1423"}, + {file = "multidict-6.0.5-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:76f067f5121dcecf0d63a67f29080b26c43c71a98b10c701b0677e4a065fbd54"}, + {file = "multidict-6.0.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:b82cc8ace10ab5bd93235dfaab2021c70637005e1ac787031f4d1da63d493c1d"}, + {file = "multidict-6.0.5-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:5cb241881eefd96b46f89b1a056187ea8e9ba14ab88ba632e68d7a2ecb7aadf7"}, + {file = "multidict-6.0.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e8e94e6912639a02ce173341ff62cc1201232ab86b8a8fcc05572741a5dc7d93"}, + {file = "multidict-6.0.5-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:09a892e4a9fb47331da06948690ae38eaa2426de97b4ccbfafbdcbe5c8f37ff8"}, + {file = "multidict-6.0.5-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:55205d03e8a598cfc688c71ca8ea5f66447164efff8869517f175ea632c7cb7b"}, + {file = "multidict-6.0.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:37b15024f864916b4951adb95d3a80c9431299080341ab9544ed148091b53f50"}, + {file = "multidict-6.0.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f2a1dee728b52b33eebff5072817176c172050d44d67befd681609b4746e1c2e"}, + {file = "multidict-6.0.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:edd08e6f2f1a390bf137080507e44ccc086353c8e98c657e666c017718561b89"}, + {file = "multidict-6.0.5-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:60d698e8179a42ec85172d12f50b1668254628425a6bd611aba022257cac1386"}, + {file = "multidict-6.0.5-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:3d25f19500588cbc47dc19081d78131c32637c25804df8414463ec908631e453"}, + {file = "multidict-6.0.5-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:4cc0ef8b962ac7a5e62b9e826bd0cd5040e7d401bc45a6835910ed699037a461"}, + {file = "multidict-6.0.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:eca2e9d0cc5a889850e9bbd68e98314ada174ff6ccd1129500103df7a94a7a44"}, + {file = "multidict-6.0.5-cp38-cp38-win32.whl", hash = "sha256:4a6a4f196f08c58c59e0b8ef8ec441d12aee4125a7d4f4fef000ccb22f8d7241"}, + {file = "multidict-6.0.5-cp38-cp38-win_amd64.whl", hash = "sha256:0275e35209c27a3f7951e1ce7aaf93ce0d163b28948444bec61dd7badc6d3f8c"}, + {file = "multidict-6.0.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:e7be68734bd8c9a513f2b0cfd508802d6609da068f40dc57d4e3494cefc92929"}, + {file = "multidict-6.0.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:1d9ea7a7e779d7a3561aade7d596649fbecfa5c08a7674b11b423783217933f9"}, + {file = "multidict-6.0.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ea1456df2a27c73ce51120fa2f519f1bea2f4a03a917f4a43c8707cf4cbbae1a"}, + {file = "multidict-6.0.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cf590b134eb70629e350691ecca88eac3e3b8b3c86992042fb82e3cb1830d5e1"}, + {file = "multidict-6.0.5-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5c0631926c4f58e9a5ccce555ad7747d9a9f8b10619621f22f9635f069f6233e"}, + {file = "multidict-6.0.5-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dce1c6912ab9ff5f179eaf6efe7365c1f425ed690b03341911bf4939ef2f3046"}, + {file = "multidict-6.0.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0868d64af83169e4d4152ec612637a543f7a336e4a307b119e98042e852ad9c"}, + {file = "multidict-6.0.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:141b43360bfd3bdd75f15ed811850763555a251e38b2405967f8e25fb43f7d40"}, + {file = "multidict-6.0.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:7df704ca8cf4a073334e0427ae2345323613e4df18cc224f647f251e5e75a527"}, + {file = "multidict-6.0.5-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:6214c5a5571802c33f80e6c84713b2c79e024995b9c5897f794b43e714daeec9"}, + {file = "multidict-6.0.5-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:cd6c8fca38178e12c00418de737aef1261576bd1b6e8c6134d3e729a4e858b38"}, + {file = "multidict-6.0.5-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:e02021f87a5b6932fa6ce916ca004c4d441509d33bbdbeca70d05dff5e9d2479"}, + {file = "multidict-6.0.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ebd8d160f91a764652d3e51ce0d2956b38efe37c9231cd82cfc0bed2e40b581c"}, + {file = "multidict-6.0.5-cp39-cp39-win32.whl", hash = "sha256:04da1bb8c8dbadf2a18a452639771951c662c5ad03aefe4884775454be322c9b"}, + {file = "multidict-6.0.5-cp39-cp39-win_amd64.whl", hash = "sha256:d6f6d4f185481c9669b9447bf9d9cf3b95a0e9df9d169bbc17e363b7d5487755"}, + {file = "multidict-6.0.5-py3-none-any.whl", hash = "sha256:0d63c74e3d7ab26de115c49bffc92cc77ed23395303d496eae515d4204a625e7"}, + {file = "multidict-6.0.5.tar.gz", hash = "sha256:f7e301075edaf50500f0b341543c41194d8df3ae5caf4702f2095f3ca73dd8da"}, ] [[package]] name = "mutagen" -version = "1.46.0" +version = "1.47.0" description = "read and write audio tags for many formats" -category = "main" optional = false python-versions = ">=3.7" files = [ - {file = "mutagen-1.46.0-py3-none-any.whl", hash = "sha256:8af0728aa2d5c3ee5a727e28d0627966641fddfe804c23eabb5926a4d770aed5"}, - {file = "mutagen-1.46.0.tar.gz", hash = "sha256:6e5f8ba84836b99fe60be5fb27f84be4ad919bbb6b49caa6ae81e70584b55e58"}, + {file = "mutagen-1.47.0-py3-none-any.whl", hash = "sha256:edd96f50c5907a9539d8e5bba7245f62c9f520aef333d13392a79a4f70aca719"}, + {file = "mutagen-1.47.0.tar.gz", hash = "sha256:719fadef0a978c31b4cf3c956261b3c58b6948b32023078a2117b1de09f0fc99"}, ] [[package]] name = "mypy" -version = "1.3.0" +version = "1.11.2" description = "Optional static typing for Python" -category = "dev" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "mypy-1.3.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c1eb485cea53f4f5284e5baf92902cd0088b24984f4209e25981cc359d64448d"}, - {file = "mypy-1.3.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:4c99c3ecf223cf2952638da9cd82793d8f3c0c5fa8b6ae2b2d9ed1e1ff51ba85"}, - {file = "mypy-1.3.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:550a8b3a19bb6589679a7c3c31f64312e7ff482a816c96e0cecec9ad3a7564dd"}, - {file = "mypy-1.3.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:cbc07246253b9e3d7d74c9ff948cd0fd7a71afcc2b77c7f0a59c26e9395cb152"}, - {file = "mypy-1.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:a22435632710a4fcf8acf86cbd0d69f68ac389a3892cb23fbad176d1cddaf228"}, - {file = "mypy-1.3.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6e33bb8b2613614a33dff70565f4c803f889ebd2f859466e42b46e1df76018dd"}, - {file = "mypy-1.3.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7d23370d2a6b7a71dc65d1266f9a34e4cde9e8e21511322415db4b26f46f6b8c"}, - {file = "mypy-1.3.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:658fe7b674769a0770d4b26cb4d6f005e88a442fe82446f020be8e5f5efb2fae"}, - {file = "mypy-1.3.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:6e42d29e324cdda61daaec2336c42512e59c7c375340bd202efa1fe0f7b8f8ca"}, - {file = "mypy-1.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:d0b6c62206e04061e27009481cb0ec966f7d6172b5b936f3ead3d74f29fe3dcf"}, - {file = "mypy-1.3.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:76ec771e2342f1b558c36d49900dfe81d140361dd0d2df6cd71b3db1be155409"}, - {file = "mypy-1.3.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ebc95f8386314272bbc817026f8ce8f4f0d2ef7ae44f947c4664efac9adec929"}, - {file = "mypy-1.3.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:faff86aa10c1aa4a10e1a301de160f3d8fc8703b88c7e98de46b531ff1276a9a"}, - {file = "mypy-1.3.0-cp37-cp37m-win_amd64.whl", hash = "sha256:8c5979d0deb27e0f4479bee18ea0f83732a893e81b78e62e2dda3e7e518c92ee"}, - {file = "mypy-1.3.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:c5d2cc54175bab47011b09688b418db71403aefad07cbcd62d44010543fc143f"}, - {file = "mypy-1.3.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:87df44954c31d86df96c8bd6e80dfcd773473e877ac6176a8e29898bfb3501cb"}, - {file = "mypy-1.3.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:473117e310febe632ddf10e745a355714e771ffe534f06db40702775056614c4"}, - {file = "mypy-1.3.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:74bc9b6e0e79808bf8678d7678b2ae3736ea72d56eede3820bd3849823e7f305"}, - {file = "mypy-1.3.0-cp38-cp38-win_amd64.whl", hash = "sha256:44797d031a41516fcf5cbfa652265bb994e53e51994c1bd649ffcd0c3a7eccbf"}, - {file = "mypy-1.3.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:ddae0f39ca146972ff6bb4399f3b2943884a774b8771ea0a8f50e971f5ea5ba8"}, - {file = "mypy-1.3.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1c4c42c60a8103ead4c1c060ac3cdd3ff01e18fddce6f1016e08939647a0e703"}, - {file = "mypy-1.3.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e86c2c6852f62f8f2b24cb7a613ebe8e0c7dc1402c61d36a609174f63e0ff017"}, - {file = "mypy-1.3.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:f9dca1e257d4cc129517779226753dbefb4f2266c4eaad610fc15c6a7e14283e"}, - {file = "mypy-1.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:95d8d31a7713510685b05fbb18d6ac287a56c8f6554d88c19e73f724a445448a"}, - {file = "mypy-1.3.0-py3-none-any.whl", hash = "sha256:a8763e72d5d9574d45ce5881962bc8e9046bf7b375b0abf031f3e6811732a897"}, - {file = "mypy-1.3.0.tar.gz", hash = "sha256:e1f4d16e296f5135624b34e8fb741eb0eadedca90862405b1f1fde2040b9bd11"}, + {file = "mypy-1.11.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d42a6dd818ffce7be66cce644f1dff482f1d97c53ca70908dff0b9ddc120b77a"}, + {file = "mypy-1.11.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:801780c56d1cdb896eacd5619a83e427ce436d86a3bdf9112527f24a66618fef"}, + {file = "mypy-1.11.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:41ea707d036a5307ac674ea172875f40c9d55c5394f888b168033177fce47383"}, + {file = "mypy-1.11.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:6e658bd2d20565ea86da7d91331b0eed6d2eee22dc031579e6297f3e12c758c8"}, + {file = "mypy-1.11.2-cp310-cp310-win_amd64.whl", hash = "sha256:478db5f5036817fe45adb7332d927daa62417159d49783041338921dcf646fc7"}, + {file = "mypy-1.11.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:75746e06d5fa1e91bfd5432448d00d34593b52e7e91a187d981d08d1f33d4385"}, + {file = "mypy-1.11.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a976775ab2256aadc6add633d44f100a2517d2388906ec4f13231fafbb0eccca"}, + {file = "mypy-1.11.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:cd953f221ac1379050a8a646585a29574488974f79d8082cedef62744f0a0104"}, + {file = "mypy-1.11.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:57555a7715c0a34421013144a33d280e73c08df70f3a18a552938587ce9274f4"}, + {file = "mypy-1.11.2-cp311-cp311-win_amd64.whl", hash = "sha256:36383a4fcbad95f2657642a07ba22ff797de26277158f1cc7bd234821468b1b6"}, + {file = "mypy-1.11.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:e8960dbbbf36906c5c0b7f4fbf2f0c7ffb20f4898e6a879fcf56a41a08b0d318"}, + {file = "mypy-1.11.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:06d26c277962f3fb50e13044674aa10553981ae514288cb7d0a738f495550b36"}, + {file = "mypy-1.11.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6e7184632d89d677973a14d00ae4d03214c8bc301ceefcdaf5c474866814c987"}, + {file = "mypy-1.11.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:3a66169b92452f72117e2da3a576087025449018afc2d8e9bfe5ffab865709ca"}, + {file = "mypy-1.11.2-cp312-cp312-win_amd64.whl", hash = "sha256:969ea3ef09617aff826885a22ece0ddef69d95852cdad2f60c8bb06bf1f71f70"}, + {file = "mypy-1.11.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:37c7fa6121c1cdfcaac97ce3d3b5588e847aa79b580c1e922bb5d5d2902df19b"}, + {file = "mypy-1.11.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:4a8a53bc3ffbd161b5b2a4fff2f0f1e23a33b0168f1c0778ec70e1a3d66deb86"}, + {file = "mypy-1.11.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2ff93107f01968ed834f4256bc1fc4475e2fecf6c661260066a985b52741ddce"}, + {file = "mypy-1.11.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:edb91dded4df17eae4537668b23f0ff6baf3707683734b6a818d5b9d0c0c31a1"}, + {file = "mypy-1.11.2-cp38-cp38-win_amd64.whl", hash = "sha256:ee23de8530d99b6db0573c4ef4bd8f39a2a6f9b60655bf7a1357e585a3486f2b"}, + {file = "mypy-1.11.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:801ca29f43d5acce85f8e999b1e431fb479cb02d0e11deb7d2abb56bdaf24fd6"}, + {file = "mypy-1.11.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:af8d155170fcf87a2afb55b35dc1a0ac21df4431e7d96717621962e4b9192e70"}, + {file = "mypy-1.11.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f7821776e5c4286b6a13138cc935e2e9b6fde05e081bdebf5cdb2bb97c9df81d"}, + {file = "mypy-1.11.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:539c570477a96a4e6fb718b8d5c3e0c0eba1f485df13f86d2970c91f0673148d"}, + {file = "mypy-1.11.2-cp39-cp39-win_amd64.whl", hash = "sha256:3f14cd3d386ac4d05c5a39a51b84387403dadbd936e17cb35882134d4f8f0d24"}, + {file = "mypy-1.11.2-py3-none-any.whl", hash = "sha256:b499bc07dbdcd3de92b0a8b29fdf592c111276f6a12fe29c30f6c417dd546d12"}, + {file = "mypy-1.11.2.tar.gz", hash = "sha256:7f9993ad3e0ffdc95c2a14b66dee63729f021968bff8ad911867579c65d13a79"}, ] [package.dependencies] mypy-extensions = ">=1.0.0" tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} -typing-extensions = ">=3.10" +typing-extensions = ">=4.6.0" [package.extras] dmypy = ["psutil (>=4.0)"] install-types = ["pip"] -python2 = ["typed-ast (>=1.4.0,<2)"] +mypyc = ["setuptools (>=50)"] reports = ["lxml"] [[package]] name = "mypy-extensions" version = "1.0.0" description = "Type system extensions for programs checked with the mypy type checker." -category = "dev" optional = false python-versions = ">=3.5" files = [ @@ -861,96 +1013,98 @@ files = [ [[package]] name = "numpy" -version = "1.24.3" +version = "1.26.4" description = "Fundamental package for array computing in Python" -category = "main" optional = false -python-versions = ">=3.8" -files = [ - {file = "numpy-1.24.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:3c1104d3c036fb81ab923f507536daedc718d0ad5a8707c6061cdfd6d184e570"}, - {file = "numpy-1.24.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:202de8f38fc4a45a3eea4b63e2f376e5f2dc64ef0fa692838e31a808520efaf7"}, - {file = "numpy-1.24.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8535303847b89aa6b0f00aa1dc62867b5a32923e4d1681a35b5eef2d9591a463"}, - {file = "numpy-1.24.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2d926b52ba1367f9acb76b0df6ed21f0b16a1ad87c6720a1121674e5cf63e2b6"}, - {file = "numpy-1.24.3-cp310-cp310-win32.whl", hash = "sha256:f21c442fdd2805e91799fbe044a7b999b8571bb0ab0f7850d0cb9641a687092b"}, - {file = "numpy-1.24.3-cp310-cp310-win_amd64.whl", hash = "sha256:ab5f23af8c16022663a652d3b25dcdc272ac3f83c3af4c02eb8b824e6b3ab9d7"}, - {file = "numpy-1.24.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:9a7721ec204d3a237225db3e194c25268faf92e19338a35f3a224469cb6039a3"}, - {file = "numpy-1.24.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d6cc757de514c00b24ae8cf5c876af2a7c3df189028d68c0cb4eaa9cd5afc2bf"}, - {file = "numpy-1.24.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:76e3f4e85fc5d4fd311f6e9b794d0c00e7002ec122be271f2019d63376f1d385"}, - {file = "numpy-1.24.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a1d3c026f57ceaad42f8231305d4653d5f05dc6332a730ae5c0bea3513de0950"}, - {file = "numpy-1.24.3-cp311-cp311-win32.whl", hash = "sha256:c91c4afd8abc3908e00a44b2672718905b8611503f7ff87390cc0ac3423fb096"}, - {file = "numpy-1.24.3-cp311-cp311-win_amd64.whl", hash = "sha256:5342cf6aad47943286afa6f1609cad9b4266a05e7f2ec408e2cf7aea7ff69d80"}, - {file = "numpy-1.24.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:7776ea65423ca6a15255ba1872d82d207bd1e09f6d0894ee4a64678dd2204078"}, - {file = "numpy-1.24.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:ae8d0be48d1b6ed82588934aaaa179875e7dc4f3d84da18d7eae6eb3f06c242c"}, - {file = "numpy-1.24.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ecde0f8adef7dfdec993fd54b0f78183051b6580f606111a6d789cd14c61ea0c"}, - {file = "numpy-1.24.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4749e053a29364d3452c034827102ee100986903263e89884922ef01a0a6fd2f"}, - {file = "numpy-1.24.3-cp38-cp38-win32.whl", hash = "sha256:d933fabd8f6a319e8530d0de4fcc2e6a61917e0b0c271fded460032db42a0fe4"}, - {file = "numpy-1.24.3-cp38-cp38-win_amd64.whl", hash = "sha256:56e48aec79ae238f6e4395886b5eaed058abb7231fb3361ddd7bfdf4eed54289"}, - {file = "numpy-1.24.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:4719d5aefb5189f50887773699eaf94e7d1e02bf36c1a9d353d9f46703758ca4"}, - {file = "numpy-1.24.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0ec87a7084caa559c36e0a2309e4ecb1baa03b687201d0a847c8b0ed476a7187"}, - {file = "numpy-1.24.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ea8282b9bcfe2b5e7d491d0bf7f3e2da29700cec05b49e64d6246923329f2b02"}, - {file = "numpy-1.24.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:210461d87fb02a84ef243cac5e814aad2b7f4be953b32cb53327bb49fd77fbb4"}, - {file = "numpy-1.24.3-cp39-cp39-win32.whl", hash = "sha256:784c6da1a07818491b0ffd63c6bbe5a33deaa0e25a20e1b3ea20cf0e43f8046c"}, - {file = "numpy-1.24.3-cp39-cp39-win_amd64.whl", hash = "sha256:d5036197ecae68d7f491fcdb4df90082b0d4960ca6599ba2659957aafced7c17"}, - {file = "numpy-1.24.3-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:352ee00c7f8387b44d19f4cada524586f07379c0d49270f87233983bc5087ca0"}, - {file = "numpy-1.24.3-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1a7d6acc2e7524c9955e5c903160aa4ea083736fde7e91276b0e5d98e6332812"}, - {file = "numpy-1.24.3-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:35400e6a8d102fd07c71ed7dcadd9eb62ee9a6e84ec159bd48c28235bbb0f8e4"}, - {file = "numpy-1.24.3.tar.gz", hash = "sha256:ab344f1bf21f140adab8e47fdbc7c35a477dc01408791f8ba00d018dd0bc5155"}, +python-versions = ">=3.9" +files = [ + {file = "numpy-1.26.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:9ff0f4f29c51e2803569d7a51c2304de5554655a60c5d776e35b4a41413830d0"}, + {file = "numpy-1.26.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2e4ee3380d6de9c9ec04745830fd9e2eccb3e6cf790d39d7b98ffd19b0dd754a"}, + {file = "numpy-1.26.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d209d8969599b27ad20994c8e41936ee0964e6da07478d6c35016bc386b66ad4"}, + {file = "numpy-1.26.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ffa75af20b44f8dba823498024771d5ac50620e6915abac414251bd971b4529f"}, + {file = "numpy-1.26.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:62b8e4b1e28009ef2846b4c7852046736bab361f7aeadeb6a5b89ebec3c7055a"}, + {file = "numpy-1.26.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a4abb4f9001ad2858e7ac189089c42178fcce737e4169dc61321660f1a96c7d2"}, + {file = "numpy-1.26.4-cp310-cp310-win32.whl", hash = "sha256:bfe25acf8b437eb2a8b2d49d443800a5f18508cd811fea3181723922a8a82b07"}, + {file = "numpy-1.26.4-cp310-cp310-win_amd64.whl", hash = "sha256:b97fe8060236edf3662adfc2c633f56a08ae30560c56310562cb4f95500022d5"}, + {file = "numpy-1.26.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4c66707fabe114439db9068ee468c26bbdf909cac0fb58686a42a24de1760c71"}, + {file = "numpy-1.26.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:edd8b5fe47dab091176d21bb6de568acdd906d1887a4584a15a9a96a1dca06ef"}, + {file = "numpy-1.26.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7ab55401287bfec946ced39700c053796e7cc0e3acbef09993a9ad2adba6ca6e"}, + {file = "numpy-1.26.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:666dbfb6ec68962c033a450943ded891bed2d54e6755e35e5835d63f4f6931d5"}, + {file = "numpy-1.26.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:96ff0b2ad353d8f990b63294c8986f1ec3cb19d749234014f4e7eb0112ceba5a"}, + {file = "numpy-1.26.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:60dedbb91afcbfdc9bc0b1f3f402804070deed7392c23eb7a7f07fa857868e8a"}, + {file = "numpy-1.26.4-cp311-cp311-win32.whl", hash = "sha256:1af303d6b2210eb850fcf03064d364652b7120803a0b872f5211f5234b399f20"}, + {file = "numpy-1.26.4-cp311-cp311-win_amd64.whl", hash = "sha256:cd25bcecc4974d09257ffcd1f098ee778f7834c3ad767fe5db785be9a4aa9cb2"}, + {file = "numpy-1.26.4-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:b3ce300f3644fb06443ee2222c2201dd3a89ea6040541412b8fa189341847218"}, + {file = "numpy-1.26.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:03a8c78d01d9781b28a6989f6fa1bb2c4f2d51201cf99d3dd875df6fbd96b23b"}, + {file = "numpy-1.26.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9fad7dcb1aac3c7f0584a5a8133e3a43eeb2fe127f47e3632d43d677c66c102b"}, + {file = "numpy-1.26.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:675d61ffbfa78604709862923189bad94014bef562cc35cf61d3a07bba02a7ed"}, + {file = "numpy-1.26.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:ab47dbe5cc8210f55aa58e4805fe224dac469cde56b9f731a4c098b91917159a"}, + {file = "numpy-1.26.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:1dda2e7b4ec9dd512f84935c5f126c8bd8b9f2fc001e9f54af255e8c5f16b0e0"}, + {file = "numpy-1.26.4-cp312-cp312-win32.whl", hash = "sha256:50193e430acfc1346175fcbdaa28ffec49947a06918b7b92130744e81e640110"}, + {file = "numpy-1.26.4-cp312-cp312-win_amd64.whl", hash = "sha256:08beddf13648eb95f8d867350f6a018a4be2e5ad54c8d8caed89ebca558b2818"}, + {file = "numpy-1.26.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:7349ab0fa0c429c82442a27a9673fc802ffdb7c7775fad780226cb234965e53c"}, + {file = "numpy-1.26.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:52b8b60467cd7dd1e9ed082188b4e6bb35aa5cdd01777621a1658910745b90be"}, + {file = "numpy-1.26.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d5241e0a80d808d70546c697135da2c613f30e28251ff8307eb72ba696945764"}, + {file = "numpy-1.26.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f870204a840a60da0b12273ef34f7051e98c3b5961b61b0c2c1be6dfd64fbcd3"}, + {file = "numpy-1.26.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:679b0076f67ecc0138fd2ede3a8fd196dddc2ad3254069bcb9faf9a79b1cebcd"}, + {file = "numpy-1.26.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:47711010ad8555514b434df65f7d7b076bb8261df1ca9bb78f53d3b2db02e95c"}, + {file = "numpy-1.26.4-cp39-cp39-win32.whl", hash = "sha256:a354325ee03388678242a4d7ebcd08b5c727033fcff3b2f536aea978e15ee9e6"}, + {file = "numpy-1.26.4-cp39-cp39-win_amd64.whl", hash = "sha256:3373d5d70a5fe74a2c1bb6d2cfd9609ecf686d47a2d7b1d37a8f3b6bf6003aea"}, + {file = "numpy-1.26.4-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:afedb719a9dcfc7eaf2287b839d8198e06dcd4cb5d276a3df279231138e83d30"}, + {file = "numpy-1.26.4-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:95a7476c59002f2f6c590b9b7b998306fba6a5aa646b1e22ddfeaf8f78c3a29c"}, + {file = "numpy-1.26.4-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:7e50d0a0cc3189f9cb0aeb3a6a6af18c16f59f004b866cd2be1c14b36134a4a0"}, + {file = "numpy-1.26.4.tar.gz", hash = "sha256:2a02aba9ed12e4ac4eb3ea9421c420301a0c6460d9830d74a9df87efa4912010"}, ] [[package]] name = "opencv-python" -version = "4.6.0.66" +version = "4.10.0.84" description = "Wrapper package for OpenCV python bindings." -category = "main" optional = false python-versions = ">=3.6" files = [ - {file = "opencv-python-4.6.0.66.tar.gz", hash = "sha256:c5bfae41ad4031e66bb10ec4a0a2ffd3e514d092652781e8b1ac98d1b59f1158"}, - {file = "opencv_python-4.6.0.66-cp36-abi3-macosx_10_15_x86_64.whl", hash = "sha256:e6e448b62afc95c5b58f97e87ef84699e6607fe5c58730a03301c52496005cae"}, - {file = "opencv_python-4.6.0.66-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5af8ba35a4fcb8913ffb86e92403e9a656a4bff4a645d196987468f0f8947875"}, - {file = "opencv_python-4.6.0.66-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dbdc84a9b4ea2cbae33861652d25093944b9959279200b7ae0badd32439f74de"}, - {file = "opencv_python-4.6.0.66-cp36-abi3-win32.whl", hash = "sha256:f482e78de6e7b0b060ff994ffd859bddc3f7f382bb2019ef157b0ea8ca8712f5"}, - {file = "opencv_python-4.6.0.66-cp36-abi3-win_amd64.whl", hash = "sha256:0dc82a3d8630c099d2f3ac1b1aabee164e8188db54a786abb7a4e27eba309440"}, - {file = "opencv_python-4.6.0.66-cp37-abi3-macosx_11_0_arm64.whl", hash = "sha256:6e32af22e3202748bd233ed8f538741876191863882eba44e332d1a34993165b"}, + {file = "opencv-python-4.10.0.84.tar.gz", hash = "sha256:72d234e4582e9658ffea8e9cae5b63d488ad06994ef12d81dc303b17472f3526"}, + {file = "opencv_python-4.10.0.84-cp37-abi3-macosx_11_0_arm64.whl", hash = "sha256:fc182f8f4cda51b45f01c64e4cbedfc2f00aff799debebc305d8d0210c43f251"}, + {file = "opencv_python-4.10.0.84-cp37-abi3-macosx_12_0_x86_64.whl", hash = "sha256:71e575744f1d23f79741450254660442785f45a0797212852ee5199ef12eed98"}, + {file = "opencv_python-4.10.0.84-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:09a332b50488e2dda866a6c5573ee192fe3583239fb26ff2f7f9ceb0bc119ea6"}, + {file = "opencv_python-4.10.0.84-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9ace140fc6d647fbe1c692bcb2abce768973491222c067c131d80957c595b71f"}, + {file = "opencv_python-4.10.0.84-cp37-abi3-win32.whl", hash = "sha256:2db02bb7e50b703f0a2d50c50ced72e95c574e1e5a0bb35a8a86d0b35c98c236"}, + {file = "opencv_python-4.10.0.84-cp37-abi3-win_amd64.whl", hash = "sha256:32dbbd94c26f611dc5cc6979e6b7aa1f55a64d6b463cc1dcd3c95505a63e48fe"}, ] [package.dependencies] numpy = [ - {version = ">=1.21.2", markers = "python_version >= \"3.10\" or python_version >= \"3.6\" and platform_system == \"Darwin\" and platform_machine == \"arm64\""}, - {version = ">=1.19.3", markers = "python_version >= \"3.6\" and platform_system == \"Linux\" and platform_machine == \"aarch64\" or python_version >= \"3.9\""}, - {version = ">=1.14.5", markers = "python_version >= \"3.7\""}, - {version = ">=1.17.3", markers = "python_version >= \"3.8\""}, + {version = ">=1.23.5", markers = "python_version >= \"3.11\""}, + {version = ">=1.21.4", markers = "python_version >= \"3.10\" and platform_system == \"Darwin\" and python_version < \"3.11\""}, + {version = ">=1.21.2", markers = "platform_system != \"Darwin\" and python_version >= \"3.10\" and python_version < \"3.11\""}, ] [[package]] name = "packaging" -version = "23.1" +version = "24.1" description = "Core utilities for Python packages" -category = "dev" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "packaging-23.1-py3-none-any.whl", hash = "sha256:994793af429502c4ea2ebf6bf664629d07c1a9fe974af92966e4b8d2df7edc61"}, - {file = "packaging-23.1.tar.gz", hash = "sha256:a392980d2b6cffa644431898be54b0045151319d1e7ec34f0cfed48767dd334f"}, + {file = "packaging-24.1-py3-none-any.whl", hash = "sha256:5b8f2217dbdbd2f7f384c41c628544e6d52f2d0f53c6d0c3ea61aa5d1d7ff124"}, + {file = "packaging-24.1.tar.gz", hash = "sha256:026ed72c8ed3fcce5bf8950572258698927fd1dbda10a5e981cdf0ac37f4f002"}, ] [[package]] name = "pathspec" -version = "0.11.1" +version = "0.12.1" description = "Utility library for gitignore style pattern matching of file paths." -category = "dev" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "pathspec-0.11.1-py3-none-any.whl", hash = "sha256:d8af70af76652554bd134c22b3e8a1cc46ed7d91edcdd721ef1a0c51a84a5293"}, - {file = "pathspec-0.11.1.tar.gz", hash = "sha256:2798de800fa92780e33acca925945e9a19a133b715067cf165b8866c15a31687"}, + {file = "pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08"}, + {file = "pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712"}, ] [[package]] name = "pillow" version = "9.5.0" description = "Python Imaging Library (Fork)" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1028,30 +1182,29 @@ tests = ["check-manifest", "coverage", "defusedxml", "markdown2", "olefile", "pa [[package]] name = "platformdirs" -version = "3.5.1" -description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." -category = "dev" +version = "4.2.2" +description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`." optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "platformdirs-3.5.1-py3-none-any.whl", hash = "sha256:e2378146f1964972c03c085bb5662ae80b2b8c06226c54b2ff4aa9483e8a13a5"}, - {file = "platformdirs-3.5.1.tar.gz", hash = "sha256:412dae91f52a6f84830f39a8078cecd0e866cb72294a5c66808e74d5e88d251f"}, + {file = "platformdirs-4.2.2-py3-none-any.whl", hash = "sha256:2d7a1657e36a80ea911db832a8a6ece5ee53d8de21edd5cc5879af6530b1bfee"}, + {file = "platformdirs-4.2.2.tar.gz", hash = "sha256:38b7b51f512eed9e84a22788b4bce1de17c0adb134d6becb09836e37d8654cd3"}, ] [package.extras] -docs = ["furo (>=2023.3.27)", "proselint (>=0.13)", "sphinx (>=6.2.1)", "sphinx-autodoc-typehints (>=1.23,!=1.23.4)"] -test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.3.1)", "pytest-cov (>=4)", "pytest-mock (>=3.10)"] +docs = ["furo (>=2023.9.10)", "proselint (>=0.13)", "sphinx (>=7.2.6)", "sphinx-autodoc-typehints (>=1.25.2)"] +test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.4.3)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)"] +type = ["mypy (>=1.8)"] [[package]] name = "pluggy" -version = "1.0.0" +version = "1.5.0" description = "plugin and hook calling mechanisms for python" -category = "dev" optional = false -python-versions = ">=3.6" +python-versions = ">=3.8" files = [ - {file = "pluggy-1.0.0-py2.py3-none-any.whl", hash = "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"}, - {file = "pluggy-1.0.0.tar.gz", hash = "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159"}, + {file = "pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669"}, + {file = "pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1"}, ] [package.extras] @@ -1060,103 +1213,106 @@ testing = ["pytest", "pytest-benchmark"] [[package]] name = "pycparser" -version = "2.21" +version = "2.22" description = "C parser in Python" -category = "main" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +python-versions = ">=3.8" files = [ - {file = "pycparser-2.21-py2.py3-none-any.whl", hash = "sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9"}, - {file = "pycparser-2.21.tar.gz", hash = "sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206"}, + {file = "pycparser-2.22-py3-none-any.whl", hash = "sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc"}, + {file = "pycparser-2.22.tar.gz", hash = "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6"}, ] [[package]] name = "pycryptodomex" -version = "3.17" +version = "3.20.0" description = "Cryptographic library for Python" -category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" files = [ - {file = "pycryptodomex-3.17-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:12056c38e49d972f9c553a3d598425f8a1c1d35b2e4330f89d5ff1ffb70de041"}, - {file = "pycryptodomex-3.17-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:ab33c2d9f275e05e235dbca1063753b5346af4a5cac34a51fa0da0d4edfb21d7"}, - {file = "pycryptodomex-3.17-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:caa937ff29d07a665dfcfd7a84f0d4207b2ebf483362fa9054041d67fdfacc20"}, - {file = "pycryptodomex-3.17-cp27-cp27m-manylinux2014_aarch64.whl", hash = "sha256:db23d7341e21b273d2440ec6faf6c8b1ca95c8894da612e165be0b89a8688340"}, - {file = "pycryptodomex-3.17-cp27-cp27m-musllinux_1_1_aarch64.whl", hash = "sha256:f854c8476512cebe6a8681cc4789e4fcff6019c17baa0fd72b459155dc605ab4"}, - {file = "pycryptodomex-3.17-cp27-cp27m-win32.whl", hash = "sha256:a57e3257bacd719769110f1f70dd901c5b6955e9596ad403af11a3e6e7e3311c"}, - {file = "pycryptodomex-3.17-cp27-cp27m-win_amd64.whl", hash = "sha256:d38ab9e53b1c09608ba2d9b8b888f1e75d6f66e2787e437adb1fecbffec6b112"}, - {file = "pycryptodomex-3.17-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:3c2516b42437ae6c7a29ef3ddc73c8d4714e7b6df995b76be4695bbe4b3b5cd2"}, - {file = "pycryptodomex-3.17-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:5c23482860302d0d9883404eaaa54b0615eefa5274f70529703e2c43cc571827"}, - {file = "pycryptodomex-3.17-cp27-cp27mu-manylinux2014_aarch64.whl", hash = "sha256:7a8dc3ee7a99aae202a4db52de5a08aa4d01831eb403c4d21da04ec2f79810db"}, - {file = "pycryptodomex-3.17-cp27-cp27mu-musllinux_1_1_aarch64.whl", hash = "sha256:7cc28dd33f1f3662d6da28ead4f9891035f63f49d30267d3b41194c8778997c8"}, - {file = "pycryptodomex-3.17-cp35-abi3-macosx_10_9_universal2.whl", hash = "sha256:2d4d395f109faba34067a08de36304e846c791808524614c731431ee048fe70a"}, - {file = "pycryptodomex-3.17-cp35-abi3-macosx_10_9_x86_64.whl", hash = "sha256:55eed98b4150a744920597c81b3965b632038781bab8a08a12ea1d004213c600"}, - {file = "pycryptodomex-3.17-cp35-abi3-manylinux2014_aarch64.whl", hash = "sha256:7fa0b52df90343fafe319257b31d909be1d2e8852277fb0376ba89d26d2921db"}, - {file = "pycryptodomex-3.17-cp35-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:78f0ddd4adc64baa39b416f3637aaf99f45acb0bcdc16706f0cc7ebfc6f10109"}, - {file = "pycryptodomex-3.17-cp35-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a4fa037078e92c7cc49f6789a8bac3de06856740bb2038d05f2d9a2e4b165d59"}, - {file = "pycryptodomex-3.17-cp35-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:88b0d5bb87eaf2a31e8a759302b89cf30c97f2f8ca7d83b8c9208abe8acb447a"}, - {file = "pycryptodomex-3.17-cp35-abi3-musllinux_1_1_i686.whl", hash = "sha256:6feedf4b0e36b395329b4186a805f60f900129cdf0170e120ecabbfcb763995d"}, - {file = "pycryptodomex-3.17-cp35-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:7a6651a07f67c28b6e978d63aa3a3fccea0feefed9a8453af3f7421a758461b7"}, - {file = "pycryptodomex-3.17-cp35-abi3-win32.whl", hash = "sha256:32e764322e902bbfac49ca1446604d2839381bbbdd5a57920c9daaf2e0b778df"}, - {file = "pycryptodomex-3.17-cp35-abi3-win_amd64.whl", hash = "sha256:4b51e826f0a04d832eda0790bbd0665d9bfe73e5a4d8ea93b6a9b38beeebe935"}, - {file = "pycryptodomex-3.17-pp27-pypy_73-macosx_10_9_x86_64.whl", hash = "sha256:d4cf0128da167562c49b0e034f09e9cedd733997354f2314837c2fa461c87bb1"}, - {file = "pycryptodomex-3.17-pp27-pypy_73-manylinux2010_x86_64.whl", hash = "sha256:c92537b596bd5bffb82f8964cabb9fef1bca8a28a9e0a69ffd3ec92a4a7ad41b"}, - {file = "pycryptodomex-3.17-pp27-pypy_73-win32.whl", hash = "sha256:599bb4ae4bbd614ca05f49bd4e672b7a250b80b13ae1238f05fd0f09d87ed80a"}, - {file = "pycryptodomex-3.17-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:4c4674f4b040321055c596aac926d12f7f6859dfe98cd12f4d9453b43ab6adc8"}, - {file = "pycryptodomex-3.17-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:67a3648025e4ddb72d43addab764336ba2e670c8377dba5dd752e42285440d31"}, - {file = "pycryptodomex-3.17-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:40e8a11f578bd0851b02719c862d55d3ee18d906c8b68a9c09f8c564d6bb5b92"}, - {file = "pycryptodomex-3.17-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:23d83b610bd97704f0cd3acc48d99b76a15c8c1540d8665c94d514a49905bad7"}, - {file = "pycryptodomex-3.17-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:fd29d35ac80755e5c0a99d96b44fb9abbd7e871849581ea6a4cb826d24267537"}, - {file = "pycryptodomex-3.17-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:64b876d57cb894b31056ad8dd6a6ae1099b117ae07a3d39707221133490e5715"}, - {file = "pycryptodomex-3.17-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ee8bf4fdcad7d66beb744957db8717afc12d176e3fd9c5d106835133881a049b"}, - {file = "pycryptodomex-3.17-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:c84689c73358dfc23f9fdcff2cb9e7856e65e2ce3b5ed8ff630d4c9bdeb1867b"}, - {file = "pycryptodomex-3.17.tar.gz", hash = "sha256:0af93aad8d62e810247beedef0261c148790c52f3cd33643791cc6396dd217c1"}, + {file = "pycryptodomex-3.20.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:645bd4ca6f543685d643dadf6a856cc382b654cc923460e3a10a49c1b3832aeb"}, + {file = "pycryptodomex-3.20.0-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:ff5c9a67f8a4fba4aed887216e32cbc48f2a6fb2673bb10a99e43be463e15913"}, + {file = "pycryptodomex-3.20.0-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:8ee606964553c1a0bc74057dd8782a37d1c2bc0f01b83193b6f8bb14523b877b"}, + {file = "pycryptodomex-3.20.0-cp27-cp27m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7805830e0c56d88f4d491fa5ac640dfc894c5ec570d1ece6ed1546e9df2e98d6"}, + {file = "pycryptodomex-3.20.0-cp27-cp27m-musllinux_1_1_aarch64.whl", hash = "sha256:bc3ee1b4d97081260d92ae813a83de4d2653206967c4a0a017580f8b9548ddbc"}, + {file = "pycryptodomex-3.20.0-cp27-cp27m-win32.whl", hash = "sha256:8af1a451ff9e123d0d8bd5d5e60f8e3315c3a64f3cdd6bc853e26090e195cdc8"}, + {file = "pycryptodomex-3.20.0-cp27-cp27m-win_amd64.whl", hash = "sha256:cbe71b6712429650e3883dc81286edb94c328ffcd24849accac0a4dbcc76958a"}, + {file = "pycryptodomex-3.20.0-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:76bd15bb65c14900d98835fcd10f59e5e0435077431d3a394b60b15864fddd64"}, + {file = "pycryptodomex-3.20.0-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:653b29b0819605fe0898829c8ad6400a6ccde096146730c2da54eede9b7b8baa"}, + {file = "pycryptodomex-3.20.0-cp27-cp27mu-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:62a5ec91388984909bb5398ea49ee61b68ecb579123694bffa172c3b0a107079"}, + {file = "pycryptodomex-3.20.0-cp27-cp27mu-musllinux_1_1_aarch64.whl", hash = "sha256:108e5f1c1cd70ffce0b68739c75734437c919d2eaec8e85bffc2c8b4d2794305"}, + {file = "pycryptodomex-3.20.0-cp35-abi3-macosx_10_9_universal2.whl", hash = "sha256:59af01efb011b0e8b686ba7758d59cf4a8263f9ad35911bfe3f416cee4f5c08c"}, + {file = "pycryptodomex-3.20.0-cp35-abi3-macosx_10_9_x86_64.whl", hash = "sha256:82ee7696ed8eb9a82c7037f32ba9b7c59e51dda6f105b39f043b6ef293989cb3"}, + {file = "pycryptodomex-3.20.0-cp35-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:91852d4480a4537d169c29a9d104dda44094c78f1f5b67bca76c29a91042b623"}, + {file = "pycryptodomex-3.20.0-cp35-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bca649483d5ed251d06daf25957f802e44e6bb6df2e8f218ae71968ff8f8edc4"}, + {file = "pycryptodomex-3.20.0-cp35-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6e186342cfcc3aafaad565cbd496060e5a614b441cacc3995ef0091115c1f6c5"}, + {file = "pycryptodomex-3.20.0-cp35-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:25cd61e846aaab76d5791d006497134602a9e451e954833018161befc3b5b9ed"}, + {file = "pycryptodomex-3.20.0-cp35-abi3-musllinux_1_1_i686.whl", hash = "sha256:9c682436c359b5ada67e882fec34689726a09c461efd75b6ea77b2403d5665b7"}, + {file = "pycryptodomex-3.20.0-cp35-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:7a7a8f33a1f1fb762ede6cc9cbab8f2a9ba13b196bfaf7bc6f0b39d2ba315a43"}, + {file = "pycryptodomex-3.20.0-cp35-abi3-win32.whl", hash = "sha256:c39778fd0548d78917b61f03c1fa8bfda6cfcf98c767decf360945fe6f97461e"}, + {file = "pycryptodomex-3.20.0-cp35-abi3-win_amd64.whl", hash = "sha256:2a47bcc478741b71273b917232f521fd5704ab4b25d301669879e7273d3586cc"}, + {file = "pycryptodomex-3.20.0-pp27-pypy_73-manylinux2010_x86_64.whl", hash = "sha256:1be97461c439a6af4fe1cf8bf6ca5936d3db252737d2f379cc6b2e394e12a458"}, + {file = "pycryptodomex-3.20.0-pp27-pypy_73-win32.whl", hash = "sha256:19764605feea0df966445d46533729b645033f134baeb3ea26ad518c9fdf212c"}, + {file = "pycryptodomex-3.20.0-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:f2e497413560e03421484189a6b65e33fe800d3bd75590e6d78d4dfdb7accf3b"}, + {file = "pycryptodomex-3.20.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e48217c7901edd95f9f097feaa0388da215ed14ce2ece803d3f300b4e694abea"}, + {file = "pycryptodomex-3.20.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d00fe8596e1cc46b44bf3907354e9377aa030ec4cd04afbbf6e899fc1e2a7781"}, + {file = "pycryptodomex-3.20.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:88afd7a3af7ddddd42c2deda43d53d3dfc016c11327d0915f90ca34ebda91499"}, + {file = "pycryptodomex-3.20.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:d3584623e68a5064a04748fb6d76117a21a7cb5eaba20608a41c7d0c61721794"}, + {file = "pycryptodomex-3.20.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0daad007b685db36d977f9de73f61f8da2a7104e20aca3effd30752fd56f73e1"}, + {file = "pycryptodomex-3.20.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5dcac11031a71348faaed1f403a0debd56bf5404232284cf8c761ff918886ebc"}, + {file = "pycryptodomex-3.20.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:69138068268127cd605e03438312d8f271135a33140e2742b417d027a0539427"}, + {file = "pycryptodomex-3.20.0.tar.gz", hash = "sha256:7a710b79baddd65b806402e14766c721aee8fb83381769c27920f26476276c1e"}, ] [[package]] name = "pydantic" -version = "1.10.7" +version = "1.10.18" description = "Data validation and settings management using python type hints" -category = "main" optional = false python-versions = ">=3.7" files = [ - {file = "pydantic-1.10.7-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e79e999e539872e903767c417c897e729e015872040e56b96e67968c3b918b2d"}, - {file = "pydantic-1.10.7-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:01aea3a42c13f2602b7ecbbea484a98169fb568ebd9e247593ea05f01b884b2e"}, - {file = "pydantic-1.10.7-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:516f1ed9bc2406a0467dd777afc636c7091d71f214d5e413d64fef45174cfc7a"}, - {file = "pydantic-1.10.7-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ae150a63564929c675d7f2303008d88426a0add46efd76c3fc797cd71cb1b46f"}, - {file = "pydantic-1.10.7-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:ecbbc51391248116c0a055899e6c3e7ffbb11fb5e2a4cd6f2d0b93272118a209"}, - {file = "pydantic-1.10.7-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:f4a2b50e2b03d5776e7f21af73e2070e1b5c0d0df255a827e7c632962f8315af"}, - {file = "pydantic-1.10.7-cp310-cp310-win_amd64.whl", hash = "sha256:a7cd2251439988b413cb0a985c4ed82b6c6aac382dbaff53ae03c4b23a70e80a"}, - {file = "pydantic-1.10.7-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:68792151e174a4aa9e9fc1b4e653e65a354a2fa0fed169f7b3d09902ad2cb6f1"}, - {file = "pydantic-1.10.7-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:dfe2507b8ef209da71b6fb5f4e597b50c5a34b78d7e857c4f8f3115effaef5fe"}, - {file = "pydantic-1.10.7-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:10a86d8c8db68086f1e30a530f7d5f83eb0685e632e411dbbcf2d5c0150e8dcd"}, - {file = "pydantic-1.10.7-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d75ae19d2a3dbb146b6f324031c24f8a3f52ff5d6a9f22f0683694b3afcb16fb"}, - {file = "pydantic-1.10.7-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:464855a7ff7f2cc2cf537ecc421291b9132aa9c79aef44e917ad711b4a93163b"}, - {file = "pydantic-1.10.7-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:193924c563fae6ddcb71d3f06fa153866423ac1b793a47936656e806b64e24ca"}, - {file = "pydantic-1.10.7-cp311-cp311-win_amd64.whl", hash = "sha256:b4a849d10f211389502059c33332e91327bc154acc1845f375a99eca3afa802d"}, - {file = "pydantic-1.10.7-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:cc1dde4e50a5fc1336ee0581c1612215bc64ed6d28d2c7c6f25d2fe3e7c3e918"}, - {file = "pydantic-1.10.7-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e0cfe895a504c060e5d36b287ee696e2fdad02d89e0d895f83037245218a87fe"}, - {file = "pydantic-1.10.7-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:670bb4683ad1e48b0ecb06f0cfe2178dcf74ff27921cdf1606e527d2617a81ee"}, - {file = "pydantic-1.10.7-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:950ce33857841f9a337ce07ddf46bc84e1c4946d2a3bba18f8280297157a3fd1"}, - {file = "pydantic-1.10.7-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:c15582f9055fbc1bfe50266a19771bbbef33dd28c45e78afbe1996fd70966c2a"}, - {file = "pydantic-1.10.7-cp37-cp37m-win_amd64.whl", hash = "sha256:82dffb306dd20bd5268fd6379bc4bfe75242a9c2b79fec58e1041fbbdb1f7914"}, - {file = "pydantic-1.10.7-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:8c7f51861d73e8b9ddcb9916ae7ac39fb52761d9ea0df41128e81e2ba42886cd"}, - {file = "pydantic-1.10.7-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:6434b49c0b03a51021ade5c4daa7d70c98f7a79e95b551201fff682fc1661245"}, - {file = "pydantic-1.10.7-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:64d34ab766fa056df49013bb6e79921a0265204c071984e75a09cbceacbbdd5d"}, - {file = "pydantic-1.10.7-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:701daea9ffe9d26f97b52f1d157e0d4121644f0fcf80b443248434958fd03dc3"}, - {file = "pydantic-1.10.7-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:cf135c46099ff3f919d2150a948ce94b9ce545598ef2c6c7bf55dca98a304b52"}, - {file = "pydantic-1.10.7-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:b0f85904f73161817b80781cc150f8b906d521fa11e3cdabae19a581c3606209"}, - {file = "pydantic-1.10.7-cp38-cp38-win_amd64.whl", hash = "sha256:9f6f0fd68d73257ad6685419478c5aece46432f4bdd8d32c7345f1986496171e"}, - {file = "pydantic-1.10.7-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c230c0d8a322276d6e7b88c3f7ce885f9ed16e0910354510e0bae84d54991143"}, - {file = "pydantic-1.10.7-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:976cae77ba6a49d80f461fd8bba183ff7ba79f44aa5cfa82f1346b5626542f8e"}, - {file = "pydantic-1.10.7-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7d45fc99d64af9aaf7e308054a0067fdcd87ffe974f2442312372dfa66e1001d"}, - {file = "pydantic-1.10.7-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d2a5ebb48958754d386195fe9e9c5106f11275867051bf017a8059410e9abf1f"}, - {file = "pydantic-1.10.7-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:abfb7d4a7cd5cc4e1d1887c43503a7c5dd608eadf8bc615413fc498d3e4645cd"}, - {file = "pydantic-1.10.7-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:80b1fab4deb08a8292d15e43a6edccdffa5377a36a4597bb545b93e79c5ff0a5"}, - {file = "pydantic-1.10.7-cp39-cp39-win_amd64.whl", hash = "sha256:d71e69699498b020ea198468e2480a2f1e7433e32a3a99760058c6520e2bea7e"}, - {file = "pydantic-1.10.7-py3-none-any.whl", hash = "sha256:0cd181f1d0b1d00e2b705f1bf1ac7799a2d938cce3376b8007df62b29be3c2c6"}, - {file = "pydantic-1.10.7.tar.gz", hash = "sha256:cfc83c0678b6ba51b0532bea66860617c4cd4251ecf76e9846fa5a9f3454e97e"}, + {file = "pydantic-1.10.18-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e405ffcc1254d76bb0e760db101ee8916b620893e6edfbfee563b3c6f7a67c02"}, + {file = "pydantic-1.10.18-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e306e280ebebc65040034bff1a0a81fd86b2f4f05daac0131f29541cafd80b80"}, + {file = "pydantic-1.10.18-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:11d9d9b87b50338b1b7de4ebf34fd29fdb0d219dc07ade29effc74d3d2609c62"}, + {file = "pydantic-1.10.18-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b661ce52c7b5e5f600c0c3c5839e71918346af2ef20062705ae76b5c16914cab"}, + {file = "pydantic-1.10.18-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:c20f682defc9ef81cd7eaa485879ab29a86a0ba58acf669a78ed868e72bb89e0"}, + {file = "pydantic-1.10.18-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c5ae6b7c8483b1e0bf59e5f1843e4fd8fd405e11df7de217ee65b98eb5462861"}, + {file = "pydantic-1.10.18-cp310-cp310-win_amd64.whl", hash = "sha256:74fe19dda960b193b0eb82c1f4d2c8e5e26918d9cda858cbf3f41dd28549cb70"}, + {file = "pydantic-1.10.18-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:72fa46abace0a7743cc697dbb830a41ee84c9db8456e8d77a46d79b537efd7ec"}, + {file = "pydantic-1.10.18-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ef0fe7ad7cbdb5f372463d42e6ed4ca9c443a52ce544472d8842a0576d830da5"}, + {file = "pydantic-1.10.18-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a00e63104346145389b8e8f500bc6a241e729feaf0559b88b8aa513dd2065481"}, + {file = "pydantic-1.10.18-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ae6fa2008e1443c46b7b3a5eb03800121868d5ab6bc7cda20b5df3e133cde8b3"}, + {file = "pydantic-1.10.18-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:9f463abafdc92635da4b38807f5b9972276be7c8c5121989768549fceb8d2588"}, + {file = "pydantic-1.10.18-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:3445426da503c7e40baccefb2b2989a0c5ce6b163679dd75f55493b460f05a8f"}, + {file = "pydantic-1.10.18-cp311-cp311-win_amd64.whl", hash = "sha256:467a14ee2183bc9c902579bb2f04c3d3dac00eff52e252850509a562255b2a33"}, + {file = "pydantic-1.10.18-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:efbc8a7f9cb5fe26122acba1852d8dcd1e125e723727c59dcd244da7bdaa54f2"}, + {file = "pydantic-1.10.18-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:24a4a159d0f7a8e26bf6463b0d3d60871d6a52eac5bb6a07a7df85c806f4c048"}, + {file = "pydantic-1.10.18-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b74be007703547dc52e3c37344d130a7bfacca7df112a9e5ceeb840a9ce195c7"}, + {file = "pydantic-1.10.18-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fcb20d4cb355195c75000a49bb4a31d75e4295200df620f454bbc6bdf60ca890"}, + {file = "pydantic-1.10.18-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:46f379b8cb8a3585e3f61bf9ae7d606c70d133943f339d38b76e041ec234953f"}, + {file = "pydantic-1.10.18-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:cbfbca662ed3729204090c4d09ee4beeecc1a7ecba5a159a94b5a4eb24e3759a"}, + {file = "pydantic-1.10.18-cp312-cp312-win_amd64.whl", hash = "sha256:c6d0a9f9eccaf7f438671a64acf654ef0d045466e63f9f68a579e2383b63f357"}, + {file = "pydantic-1.10.18-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:3d5492dbf953d7d849751917e3b2433fb26010d977aa7a0765c37425a4026ff1"}, + {file = "pydantic-1.10.18-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fe734914977eed33033b70bfc097e1baaffb589517863955430bf2e0846ac30f"}, + {file = "pydantic-1.10.18-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:15fdbe568beaca9aacfccd5ceadfb5f1a235087a127e8af5e48df9d8a45ae85c"}, + {file = "pydantic-1.10.18-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:c3e742f62198c9eb9201781fbebe64533a3bbf6a76a91b8d438d62b813079dbc"}, + {file = "pydantic-1.10.18-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:19a3bd00b9dafc2cd7250d94d5b578edf7a0bd7daf102617153ff9a8fa37871c"}, + {file = "pydantic-1.10.18-cp37-cp37m-win_amd64.whl", hash = "sha256:2ce3fcf75b2bae99aa31bd4968de0474ebe8c8258a0110903478bd83dfee4e3b"}, + {file = "pydantic-1.10.18-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:335a32d72c51a313b33fa3a9b0fe283503272ef6467910338e123f90925f0f03"}, + {file = "pydantic-1.10.18-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:34a3613c7edb8c6fa578e58e9abe3c0f5e7430e0fc34a65a415a1683b9c32d9a"}, + {file = "pydantic-1.10.18-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e9ee4e6ca1d9616797fa2e9c0bfb8815912c7d67aca96f77428e316741082a1b"}, + {file = "pydantic-1.10.18-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:23e8ec1ce4e57b4f441fc91e3c12adba023fedd06868445a5b5f1d48f0ab3682"}, + {file = "pydantic-1.10.18-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:44ae8a3e35a54d2e8fa88ed65e1b08967a9ef8c320819a969bfa09ce5528fafe"}, + {file = "pydantic-1.10.18-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:d5389eb3b48a72da28c6e061a247ab224381435256eb541e175798483368fdd3"}, + {file = "pydantic-1.10.18-cp38-cp38-win_amd64.whl", hash = "sha256:069b9c9fc645474d5ea3653788b544a9e0ccd3dca3ad8c900c4c6eac844b4620"}, + {file = "pydantic-1.10.18-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:80b982d42515632eb51f60fa1d217dfe0729f008e81a82d1544cc392e0a50ddf"}, + {file = "pydantic-1.10.18-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:aad8771ec8dbf9139b01b56f66386537c6fe4e76c8f7a47c10261b69ad25c2c9"}, + {file = "pydantic-1.10.18-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:941a2eb0a1509bd7f31e355912eb33b698eb0051730b2eaf9e70e2e1589cae1d"}, + {file = "pydantic-1.10.18-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:65f7361a09b07915a98efd17fdec23103307a54db2000bb92095457ca758d485"}, + {file = "pydantic-1.10.18-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:6951f3f47cb5ca4da536ab161ac0163cab31417d20c54c6de5ddcab8bc813c3f"}, + {file = "pydantic-1.10.18-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:7a4c5eec138a9b52c67f664c7d51d4c7234c5ad65dd8aacd919fb47445a62c86"}, + {file = "pydantic-1.10.18-cp39-cp39-win_amd64.whl", hash = "sha256:49e26c51ca854286bffc22b69787a8d4063a62bf7d83dc21d44d2ff426108518"}, + {file = "pydantic-1.10.18-py3-none-any.whl", hash = "sha256:06a189b81ffc52746ec9c8c007f16e5167c8b0a696e1a726369327e3db7b2a82"}, + {file = "pydantic-1.10.18.tar.gz", hash = "sha256:baebdff1907d1d96a139c25136a9bb7d17e118f133a76a2ef3b845e831e3403a"}, ] [package.dependencies] @@ -1170,7 +1326,6 @@ email = ["email-validator (>=1.0.3)"] name = "pynacl" version = "1.4.0" description = "Python binding to the Networking and Cryptography (NaCl) library" -category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" files = [ @@ -1204,14 +1359,13 @@ tests = ["hypothesis (>=3.27.0)", "pytest (>=3.2.1,!=3.3.0)"] [[package]] name = "pytest" -version = "7.3.1" +version = "7.4.4" description = "pytest: simple powerful testing with Python" -category = "dev" optional = false python-versions = ">=3.7" files = [ - {file = "pytest-7.3.1-py3-none-any.whl", hash = "sha256:3799fa815351fea3a5e96ac7e503a96fa51cc9942c3753cda7651b93c1cfa362"}, - {file = "pytest-7.3.1.tar.gz", hash = "sha256:434afafd78b1d78ed0addf160ad2b77a30d35d4bdf8af234fe621919d9ed15e3"}, + {file = "pytest-7.4.4-py3-none-any.whl", hash = "sha256:b090cdf5ed60bf4c45261be03239c2c1c22df034fbffe691abe93cd80cea01d8"}, + {file = "pytest-7.4.4.tar.gz", hash = "sha256:2cf0005922c6ace4a3e2ec8b4080eb0d9753fdc93107415332f50ce9e7994280"}, ] [package.dependencies] @@ -1223,13 +1377,12 @@ pluggy = ">=0.12,<2.0" tomli = {version = ">=1.0.0", markers = "python_version < \"3.11\""} [package.extras] -testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "xmlschema"] +testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"] [[package]] name = "python-dotenv" version = "0.21.1" description = "Read key-value pairs from a .env file and set them as environment variables" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1242,124 +1395,126 @@ cli = ["click (>=5.0)"] [[package]] name = "pytz" -version = "2023.3" +version = "2024.1" description = "World timezone definitions, modern and historical" -category = "main" optional = false python-versions = "*" files = [ - {file = "pytz-2023.3-py2.py3-none-any.whl", hash = "sha256:a151b3abb88eda1d4e34a9814df37de2a80e301e68ba0fd856fb9b46bfbbbffb"}, - {file = "pytz-2023.3.tar.gz", hash = "sha256:1d8ce29db189191fb55338ee6d0387d82ab59f3d00eac103412d64e0ebd0c588"}, + {file = "pytz-2024.1-py2.py3-none-any.whl", hash = "sha256:328171f4e3623139da4983451950b28e95ac706e13f3f2630a879749e7a8b319"}, + {file = "pytz-2024.1.tar.gz", hash = "sha256:2a29735ea9c18baf14b448846bde5a48030ed267578472d8955cd0e7443a9812"}, ] [[package]] name = "regex" -version = "2023.5.5" +version = "2023.12.25" description = "Alternative regular expression module, to replace re." -category = "main" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" files = [ - {file = "regex-2023.5.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:48c9ec56579d4ba1c88f42302194b8ae2350265cb60c64b7b9a88dcb7fbde309"}, - {file = "regex-2023.5.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:02f4541550459c08fdd6f97aa4e24c6f1932eec780d58a2faa2068253df7d6ff"}, - {file = "regex-2023.5.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:53e22e4460f0245b468ee645156a4f84d0fc35a12d9ba79bd7d79bdcd2f9629d"}, - {file = "regex-2023.5.5-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4b870b6f632fc74941cadc2a0f3064ed8409e6f8ee226cdfd2a85ae50473aa94"}, - {file = "regex-2023.5.5-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:171c52e320fe29260da550d81c6b99f6f8402450dc7777ef5ced2e848f3b6f8f"}, - {file = "regex-2023.5.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aad5524c2aedaf9aa14ef1bc9327f8abd915699dea457d339bebbe2f0d218f86"}, - {file = "regex-2023.5.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5a0f874ee8c0bc820e649c900243c6d1e6dc435b81da1492046716f14f1a2a96"}, - {file = "regex-2023.5.5-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:e645c757183ee0e13f0bbe56508598e2d9cd42b8abc6c0599d53b0d0b8dd1479"}, - {file = "regex-2023.5.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:a4c5da39bca4f7979eefcbb36efea04471cd68db2d38fcbb4ee2c6d440699833"}, - {file = "regex-2023.5.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:5e3f4468b8c6fd2fd33c218bbd0a1559e6a6fcf185af8bb0cc43f3b5bfb7d636"}, - {file = "regex-2023.5.5-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:59e4b729eae1a0919f9e4c0fc635fbcc9db59c74ad98d684f4877be3d2607dd6"}, - {file = "regex-2023.5.5-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:ba73a14e9c8f9ac409863543cde3290dba39098fc261f717dc337ea72d3ebad2"}, - {file = "regex-2023.5.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:0bbd5dcb19603ab8d2781fac60114fb89aee8494f4505ae7ad141a3314abb1f9"}, - {file = "regex-2023.5.5-cp310-cp310-win32.whl", hash = "sha256:40005cbd383438aecf715a7b47fe1e3dcbc889a36461ed416bdec07e0ef1db66"}, - {file = "regex-2023.5.5-cp310-cp310-win_amd64.whl", hash = "sha256:59597cd6315d3439ed4b074febe84a439c33928dd34396941b4d377692eca810"}, - {file = "regex-2023.5.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:8f08276466fedb9e36e5193a96cb944928301152879ec20c2d723d1031cd4ddd"}, - {file = "regex-2023.5.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:cd46f30e758629c3ee91713529cfbe107ac50d27110fdcc326a42ce2acf4dafc"}, - {file = "regex-2023.5.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f2910502f718828cecc8beff004917dcf577fc5f8f5dd40ffb1ea7612124547b"}, - {file = "regex-2023.5.5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:445d6f4fc3bd9fc2bf0416164454f90acab8858cd5a041403d7a11e3356980e8"}, - {file = "regex-2023.5.5-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:18196c16a584619c7c1d843497c069955d7629ad4a3fdee240eb347f4a2c9dbe"}, - {file = "regex-2023.5.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:33d430a23b661629661f1fe8395be2004006bc792bb9fc7c53911d661b69dd7e"}, - {file = "regex-2023.5.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:72a28979cc667e5f82ef433db009184e7ac277844eea0f7f4d254b789517941d"}, - {file = "regex-2023.5.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:f764e4dfafa288e2eba21231f455d209f4709436baeebb05bdecfb5d8ddc3d35"}, - {file = "regex-2023.5.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:23d86ad2121b3c4fc78c58f95e19173790e22ac05996df69b84e12da5816cb17"}, - {file = "regex-2023.5.5-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:690a17db524ee6ac4a27efc5406530dd90e7a7a69d8360235323d0e5dafb8f5b"}, - {file = "regex-2023.5.5-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:1ecf3dcff71f0c0fe3e555201cbe749fa66aae8d18f80d2cc4de8e66df37390a"}, - {file = "regex-2023.5.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:811040d7f3dd9c55eb0d8b00b5dcb7fd9ae1761c454f444fd9f37fe5ec57143a"}, - {file = "regex-2023.5.5-cp311-cp311-win32.whl", hash = "sha256:c8c143a65ce3ca42e54d8e6fcaf465b6b672ed1c6c90022794a802fb93105d22"}, - {file = "regex-2023.5.5-cp311-cp311-win_amd64.whl", hash = "sha256:586a011f77f8a2da4b888774174cd266e69e917a67ba072c7fc0e91878178a80"}, - {file = "regex-2023.5.5-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:b6365703e8cf1644b82104cdd05270d1a9f043119a168d66c55684b1b557d008"}, - {file = "regex-2023.5.5-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a56c18f21ac98209da9c54ae3ebb3b6f6e772038681d6cb43b8d53da3b09ee81"}, - {file = "regex-2023.5.5-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b8b942d8b3ce765dbc3b1dad0a944712a89b5de290ce8f72681e22b3c55f3cc8"}, - {file = "regex-2023.5.5-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:844671c9c1150fcdac46d43198364034b961bd520f2c4fdaabfc7c7d7138a2dd"}, - {file = "regex-2023.5.5-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c2ce65bdeaf0a386bb3b533a28de3994e8e13b464ac15e1e67e4603dd88787fa"}, - {file = "regex-2023.5.5-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fee0016cc35a8a91e8cc9312ab26a6fe638d484131a7afa79e1ce6165328a135"}, - {file = "regex-2023.5.5-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:18f05d14f14a812fe9723f13afafefe6b74ca042d99f8884e62dbd34dcccf3e2"}, - {file = "regex-2023.5.5-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:941b3f1b2392f0bcd6abf1bc7a322787d6db4e7457be6d1ffd3a693426a755f2"}, - {file = "regex-2023.5.5-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:921473a93bcea4d00295799ab929522fc650e85c6b9f27ae1e6bb32a790ea7d3"}, - {file = "regex-2023.5.5-cp36-cp36m-musllinux_1_1_ppc64le.whl", hash = "sha256:e2205a81f815b5bb17e46e74cc946c575b484e5f0acfcb805fb252d67e22938d"}, - {file = "regex-2023.5.5-cp36-cp36m-musllinux_1_1_s390x.whl", hash = "sha256:385992d5ecf1a93cb85adff2f73e0402dd9ac29b71b7006d342cc920816e6f32"}, - {file = "regex-2023.5.5-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:890a09cb0a62198bff92eda98b2b507305dd3abf974778bae3287f98b48907d3"}, - {file = "regex-2023.5.5-cp36-cp36m-win32.whl", hash = "sha256:821a88b878b6589c5068f4cc2cfeb2c64e343a196bc9d7ac68ea8c2a776acd46"}, - {file = "regex-2023.5.5-cp36-cp36m-win_amd64.whl", hash = "sha256:7918a1b83dd70dc04ab5ed24c78ae833ae8ea228cef84e08597c408286edc926"}, - {file = "regex-2023.5.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:338994d3d4ca4cf12f09822e025731a5bdd3a37aaa571fa52659e85ca793fb67"}, - {file = "regex-2023.5.5-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0a69cf0c00c4d4a929c6c7717fd918414cab0d6132a49a6d8fc3ded1988ed2ea"}, - {file = "regex-2023.5.5-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8f5e06df94fff8c4c85f98c6487f6636848e1dc85ce17ab7d1931df4a081f657"}, - {file = "regex-2023.5.5-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a8906669b03c63266b6a7693d1f487b02647beb12adea20f8840c1a087e2dfb5"}, - {file = "regex-2023.5.5-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9fda3e50abad8d0f48df621cf75adc73c63f7243cbe0e3b2171392b445401550"}, - {file = "regex-2023.5.5-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5ac2b7d341dc1bd102be849d6dd33b09701223a851105b2754339e390be0627a"}, - {file = "regex-2023.5.5-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:fb2b495dd94b02de8215625948132cc2ea360ae84fe6634cd19b6567709c8ae2"}, - {file = "regex-2023.5.5-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:aa7d032c1d84726aa9edeb6accf079b4caa87151ca9fabacef31fa028186c66d"}, - {file = "regex-2023.5.5-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:3d45864693351c15531f7e76f545ec35000d50848daa833cead96edae1665559"}, - {file = "regex-2023.5.5-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:21e90a288e6ba4bf44c25c6a946cb9b0f00b73044d74308b5e0afd190338297c"}, - {file = "regex-2023.5.5-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:10250a093741ec7bf74bcd2039e697f519b028518f605ff2aa7ac1e9c9f97423"}, - {file = "regex-2023.5.5-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:6b8d0c153f07a953636b9cdb3011b733cadd4178123ef728ccc4d5969e67f3c2"}, - {file = "regex-2023.5.5-cp37-cp37m-win32.whl", hash = "sha256:10374c84ee58c44575b667310d5bbfa89fb2e64e52349720a0182c0017512f6c"}, - {file = "regex-2023.5.5-cp37-cp37m-win_amd64.whl", hash = "sha256:9b320677521aabf666cdd6e99baee4fb5ac3996349c3b7f8e7c4eee1c00dfe3a"}, - {file = "regex-2023.5.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:afb1c70ec1e594a547f38ad6bf5e3d60304ce7539e677c1429eebab115bce56e"}, - {file = "regex-2023.5.5-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:cf123225945aa58b3057d0fba67e8061c62d14cc8a4202630f8057df70189051"}, - {file = "regex-2023.5.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a99757ad7fe5c8a2bb44829fc57ced11253e10f462233c1255fe03888e06bc19"}, - {file = "regex-2023.5.5-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a623564d810e7a953ff1357f7799c14bc9beeab699aacc8b7ab7822da1e952b8"}, - {file = "regex-2023.5.5-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ced02e3bd55e16e89c08bbc8128cff0884d96e7f7a5633d3dc366b6d95fcd1d6"}, - {file = "regex-2023.5.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d1cbe6b5be3b9b698d8cc4ee4dee7e017ad655e83361cd0ea8e653d65e469468"}, - {file = "regex-2023.5.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4a6e4b0e0531223f53bad07ddf733af490ba2b8367f62342b92b39b29f72735a"}, - {file = "regex-2023.5.5-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:2e9c4f778514a560a9c9aa8e5538bee759b55f6c1dcd35613ad72523fd9175b8"}, - {file = "regex-2023.5.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:256f7f4c6ba145f62f7a441a003c94b8b1af78cee2cccacfc1e835f93bc09426"}, - {file = "regex-2023.5.5-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:bd7b68fd2e79d59d86dcbc1ccd6e2ca09c505343445daaa4e07f43c8a9cc34da"}, - {file = "regex-2023.5.5-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:4a5059bd585e9e9504ef9c07e4bc15b0a621ba20504388875d66b8b30a5c4d18"}, - {file = "regex-2023.5.5-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:6893544e06bae009916a5658ce7207e26ed17385149f35a3125f5259951f1bbe"}, - {file = "regex-2023.5.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:c64d5abe91a3dfe5ff250c6bb267ef00dbc01501518225b45a5f9def458f31fb"}, - {file = "regex-2023.5.5-cp38-cp38-win32.whl", hash = "sha256:7923470d6056a9590247ff729c05e8e0f06bbd4efa6569c916943cb2d9b68b91"}, - {file = "regex-2023.5.5-cp38-cp38-win_amd64.whl", hash = "sha256:4035d6945cb961c90c3e1c1ca2feb526175bcfed44dfb1cc77db4fdced060d3e"}, - {file = "regex-2023.5.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:50fd2d9b36938d4dcecbd684777dd12a407add4f9f934f235c66372e630772b0"}, - {file = "regex-2023.5.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:d19e57f888b00cd04fc38f5e18d0efbd91ccba2d45039453ab2236e6eec48d4d"}, - {file = "regex-2023.5.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bd966475e963122ee0a7118ec9024388c602d12ac72860f6eea119a3928be053"}, - {file = "regex-2023.5.5-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:db09e6c18977a33fea26fe67b7a842f706c67cf8bda1450974d0ae0dd63570df"}, - {file = "regex-2023.5.5-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6164d4e2a82f9ebd7752a06bd6c504791bedc6418c0196cd0a23afb7f3e12b2d"}, - {file = "regex-2023.5.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:84397d3f750d153ebd7f958efaa92b45fea170200e2df5e0e1fd4d85b7e3f58a"}, - {file = "regex-2023.5.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9c3efee9bb53cbe7b285760c81f28ac80dc15fa48b5fe7e58b52752e642553f1"}, - {file = "regex-2023.5.5-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:144b5b017646b5a9392a5554a1e5db0000ae637be4971c9747566775fc96e1b2"}, - {file = "regex-2023.5.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:1189fbbb21e2c117fda5303653b61905aeeeea23de4a94d400b0487eb16d2d60"}, - {file = "regex-2023.5.5-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:f83fe9e10f9d0b6cf580564d4d23845b9d692e4c91bd8be57733958e4c602956"}, - {file = "regex-2023.5.5-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:72aa4746993a28c841e05889f3f1b1e5d14df8d3daa157d6001a34c98102b393"}, - {file = "regex-2023.5.5-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:de2f780c3242ea114dd01f84848655356af4dd561501896c751d7b885ea6d3a1"}, - {file = "regex-2023.5.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:290fd35219486dfbc00b0de72f455ecdd63e59b528991a6aec9fdfc0ce85672e"}, - {file = "regex-2023.5.5-cp39-cp39-win32.whl", hash = "sha256:732176f5427e72fa2325b05c58ad0b45af341c459910d766f814b0584ac1f9ac"}, - {file = "regex-2023.5.5-cp39-cp39-win_amd64.whl", hash = "sha256:1307aa4daa1cbb23823d8238e1f61292fd07e4e5d8d38a6efff00b67a7cdb764"}, - {file = "regex-2023.5.5.tar.gz", hash = "sha256:7d76a8a1fc9da08296462a18f16620ba73bcbf5909e42383b253ef34d9d5141e"}, + {file = "regex-2023.12.25-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:0694219a1d54336fd0445ea382d49d36882415c0134ee1e8332afd1529f0baa5"}, + {file = "regex-2023.12.25-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b014333bd0217ad3d54c143de9d4b9a3ca1c5a29a6d0d554952ea071cff0f1f8"}, + {file = "regex-2023.12.25-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d865984b3f71f6d0af64d0d88f5733521698f6c16f445bb09ce746c92c97c586"}, + {file = "regex-2023.12.25-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1e0eabac536b4cc7f57a5f3d095bfa557860ab912f25965e08fe1545e2ed8b4c"}, + {file = "regex-2023.12.25-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c25a8ad70e716f96e13a637802813f65d8a6760ef48672aa3502f4c24ea8b400"}, + {file = "regex-2023.12.25-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a9b6d73353f777630626f403b0652055ebfe8ff142a44ec2cf18ae470395766e"}, + {file = "regex-2023.12.25-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a9cc99d6946d750eb75827cb53c4371b8b0fe89c733a94b1573c9dd16ea6c9e4"}, + {file = "regex-2023.12.25-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:88d1f7bef20c721359d8675f7d9f8e414ec5003d8f642fdfd8087777ff7f94b5"}, + {file = "regex-2023.12.25-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:cb3fe77aec8f1995611f966d0c656fdce398317f850d0e6e7aebdfe61f40e1cd"}, + {file = "regex-2023.12.25-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:7aa47c2e9ea33a4a2a05f40fcd3ea36d73853a2aae7b4feab6fc85f8bf2c9704"}, + {file = "regex-2023.12.25-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:df26481f0c7a3f8739fecb3e81bc9da3fcfae34d6c094563b9d4670b047312e1"}, + {file = "regex-2023.12.25-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:c40281f7d70baf6e0db0c2f7472b31609f5bc2748fe7275ea65a0b4601d9b392"}, + {file = "regex-2023.12.25-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:d94a1db462d5690ebf6ae86d11c5e420042b9898af5dcf278bd97d6bda065423"}, + {file = "regex-2023.12.25-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:ba1b30765a55acf15dce3f364e4928b80858fa8f979ad41f862358939bdd1f2f"}, + {file = "regex-2023.12.25-cp310-cp310-win32.whl", hash = "sha256:150c39f5b964e4d7dba46a7962a088fbc91f06e606f023ce57bb347a3b2d4630"}, + {file = "regex-2023.12.25-cp310-cp310-win_amd64.whl", hash = "sha256:09da66917262d9481c719599116c7dc0c321ffcec4b1f510c4f8a066f8768105"}, + {file = "regex-2023.12.25-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:1b9d811f72210fa9306aeb88385b8f8bcef0dfbf3873410413c00aa94c56c2b6"}, + {file = "regex-2023.12.25-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d902a43085a308cef32c0d3aea962524b725403fd9373dea18110904003bac97"}, + {file = "regex-2023.12.25-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d166eafc19f4718df38887b2bbe1467a4f74a9830e8605089ea7a30dd4da8887"}, + {file = "regex-2023.12.25-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c7ad32824b7f02bb3c9f80306d405a1d9b7bb89362d68b3c5a9be53836caebdb"}, + {file = "regex-2023.12.25-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:636ba0a77de609d6510235b7f0e77ec494d2657108f777e8765efc060094c98c"}, + {file = "regex-2023.12.25-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0fda75704357805eb953a3ee15a2b240694a9a514548cd49b3c5124b4e2ad01b"}, + {file = "regex-2023.12.25-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f72cbae7f6b01591f90814250e636065850c5926751af02bb48da94dfced7baa"}, + {file = "regex-2023.12.25-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:db2a0b1857f18b11e3b0e54ddfefc96af46b0896fb678c85f63fb8c37518b3e7"}, + {file = "regex-2023.12.25-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:7502534e55c7c36c0978c91ba6f61703faf7ce733715ca48f499d3dbbd7657e0"}, + {file = "regex-2023.12.25-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:e8c7e08bb566de4faaf11984af13f6bcf6a08f327b13631d41d62592681d24fe"}, + {file = "regex-2023.12.25-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:283fc8eed679758de38fe493b7d7d84a198b558942b03f017b1f94dda8efae80"}, + {file = "regex-2023.12.25-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:f44dd4d68697559d007462b0a3a1d9acd61d97072b71f6d1968daef26bc744bd"}, + {file = "regex-2023.12.25-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:67d3ccfc590e5e7197750fcb3a2915b416a53e2de847a728cfa60141054123d4"}, + {file = "regex-2023.12.25-cp311-cp311-win32.whl", hash = "sha256:68191f80a9bad283432385961d9efe09d783bcd36ed35a60fb1ff3f1ec2efe87"}, + {file = "regex-2023.12.25-cp311-cp311-win_amd64.whl", hash = "sha256:7d2af3f6b8419661a0c421584cfe8aaec1c0e435ce7e47ee2a97e344b98f794f"}, + {file = "regex-2023.12.25-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:8a0ccf52bb37d1a700375a6b395bff5dd15c50acb745f7db30415bae3c2b0715"}, + {file = "regex-2023.12.25-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:c3c4a78615b7762740531c27cf46e2f388d8d727d0c0c739e72048beb26c8a9d"}, + {file = "regex-2023.12.25-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ad83e7545b4ab69216cef4cc47e344d19622e28aabec61574b20257c65466d6a"}, + {file = "regex-2023.12.25-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b7a635871143661feccce3979e1727c4e094f2bdfd3ec4b90dfd4f16f571a87a"}, + {file = "regex-2023.12.25-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d498eea3f581fbe1b34b59c697512a8baef88212f92e4c7830fcc1499f5b45a5"}, + {file = "regex-2023.12.25-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:43f7cd5754d02a56ae4ebb91b33461dc67be8e3e0153f593c509e21d219c5060"}, + {file = "regex-2023.12.25-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:51f4b32f793812714fd5307222a7f77e739b9bc566dc94a18126aba3b92b98a3"}, + {file = "regex-2023.12.25-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ba99d8077424501b9616b43a2d208095746fb1284fc5ba490139651f971d39d9"}, + {file = "regex-2023.12.25-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:4bfc2b16e3ba8850e0e262467275dd4d62f0d045e0e9eda2bc65078c0110a11f"}, + {file = "regex-2023.12.25-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:8c2c19dae8a3eb0ea45a8448356ed561be843b13cbc34b840922ddf565498c1c"}, + {file = "regex-2023.12.25-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:60080bb3d8617d96f0fb7e19796384cc2467447ef1c491694850ebd3670bc457"}, + {file = "regex-2023.12.25-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:b77e27b79448e34c2c51c09836033056a0547aa360c45eeeb67803da7b0eedaf"}, + {file = "regex-2023.12.25-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:518440c991f514331f4850a63560321f833979d145d7d81186dbe2f19e27ae3d"}, + {file = "regex-2023.12.25-cp312-cp312-win32.whl", hash = "sha256:e2610e9406d3b0073636a3a2e80db05a02f0c3169b5632022b4e81c0364bcda5"}, + {file = "regex-2023.12.25-cp312-cp312-win_amd64.whl", hash = "sha256:cc37b9aeebab425f11f27e5e9e6cf580be7206c6582a64467a14dda211abc232"}, + {file = "regex-2023.12.25-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:da695d75ac97cb1cd725adac136d25ca687da4536154cdc2815f576e4da11c69"}, + {file = "regex-2023.12.25-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d126361607b33c4eb7b36debc173bf25d7805847346dd4d99b5499e1fef52bc7"}, + {file = "regex-2023.12.25-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4719bb05094d7d8563a450cf8738d2e1061420f79cfcc1fa7f0a44744c4d8f73"}, + {file = "regex-2023.12.25-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5dd58946bce44b53b06d94aa95560d0b243eb2fe64227cba50017a8d8b3cd3e2"}, + {file = "regex-2023.12.25-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:22a86d9fff2009302c440b9d799ef2fe322416d2d58fc124b926aa89365ec482"}, + {file = "regex-2023.12.25-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2aae8101919e8aa05ecfe6322b278f41ce2994c4a430303c4cd163fef746e04f"}, + {file = "regex-2023.12.25-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:e692296c4cc2873967771345a876bcfc1c547e8dd695c6b89342488b0ea55cd8"}, + {file = "regex-2023.12.25-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:263ef5cc10979837f243950637fffb06e8daed7f1ac1e39d5910fd29929e489a"}, + {file = "regex-2023.12.25-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:d6f7e255e5fa94642a0724e35406e6cb7001c09d476ab5fce002f652b36d0c39"}, + {file = "regex-2023.12.25-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:88ad44e220e22b63b0f8f81f007e8abbb92874d8ced66f32571ef8beb0643b2b"}, + {file = "regex-2023.12.25-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:3a17d3ede18f9cedcbe23d2daa8a2cd6f59fe2bf082c567e43083bba3fb00347"}, + {file = "regex-2023.12.25-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d15b274f9e15b1a0b7a45d2ac86d1f634d983ca40d6b886721626c47a400bf39"}, + {file = "regex-2023.12.25-cp37-cp37m-win32.whl", hash = "sha256:ed19b3a05ae0c97dd8f75a5d8f21f7723a8c33bbc555da6bbe1f96c470139d3c"}, + {file = "regex-2023.12.25-cp37-cp37m-win_amd64.whl", hash = "sha256:a6d1047952c0b8104a1d371f88f4ab62e6275567d4458c1e26e9627ad489b445"}, + {file = "regex-2023.12.25-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:b43523d7bc2abd757119dbfb38af91b5735eea45537ec6ec3a5ec3f9562a1c53"}, + {file = "regex-2023.12.25-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:efb2d82f33b2212898f1659fb1c2e9ac30493ac41e4d53123da374c3b5541e64"}, + {file = "regex-2023.12.25-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:b7fca9205b59c1a3d5031f7e64ed627a1074730a51c2a80e97653e3e9fa0d415"}, + {file = "regex-2023.12.25-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:086dd15e9435b393ae06f96ab69ab2d333f5d65cbe65ca5a3ef0ec9564dfe770"}, + {file = "regex-2023.12.25-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e81469f7d01efed9b53740aedd26085f20d49da65f9c1f41e822a33992cb1590"}, + {file = "regex-2023.12.25-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:34e4af5b27232f68042aa40a91c3b9bb4da0eeb31b7632e0091afc4310afe6cb"}, + {file = "regex-2023.12.25-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9852b76ab558e45b20bf1893b59af64a28bd3820b0c2efc80e0a70a4a3ea51c1"}, + {file = "regex-2023.12.25-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ff100b203092af77d1a5a7abe085b3506b7eaaf9abf65b73b7d6905b6cb76988"}, + {file = "regex-2023.12.25-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:cc038b2d8b1470364b1888a98fd22d616fba2b6309c5b5f181ad4483e0017861"}, + {file = "regex-2023.12.25-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:094ba386bb5c01e54e14434d4caabf6583334090865b23ef58e0424a6286d3dc"}, + {file = "regex-2023.12.25-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:5cd05d0f57846d8ba4b71d9c00f6f37d6b97d5e5ef8b3c3840426a475c8f70f4"}, + {file = "regex-2023.12.25-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:9aa1a67bbf0f957bbe096375887b2505f5d8ae16bf04488e8b0f334c36e31360"}, + {file = "regex-2023.12.25-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:98a2636994f943b871786c9e82bfe7883ecdaba2ef5df54e1450fa9869d1f756"}, + {file = "regex-2023.12.25-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:37f8e93a81fc5e5bd8db7e10e62dc64261bcd88f8d7e6640aaebe9bc180d9ce2"}, + {file = "regex-2023.12.25-cp38-cp38-win32.whl", hash = "sha256:d78bd484930c1da2b9679290a41cdb25cc127d783768a0369d6b449e72f88beb"}, + {file = "regex-2023.12.25-cp38-cp38-win_amd64.whl", hash = "sha256:b521dcecebc5b978b447f0f69b5b7f3840eac454862270406a39837ffae4e697"}, + {file = "regex-2023.12.25-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:f7bc09bc9c29ebead055bcba136a67378f03d66bf359e87d0f7c759d6d4ffa31"}, + {file = "regex-2023.12.25-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:e14b73607d6231f3cc4622809c196b540a6a44e903bcfad940779c80dffa7be7"}, + {file = "regex-2023.12.25-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:9eda5f7a50141291beda3edd00abc2d4a5b16c29c92daf8d5bd76934150f3edc"}, + {file = "regex-2023.12.25-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cc6bb9aa69aacf0f6032c307da718f61a40cf970849e471254e0e91c56ffca95"}, + {file = "regex-2023.12.25-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:298dc6354d414bc921581be85695d18912bea163a8b23cac9a2562bbcd5088b1"}, + {file = "regex-2023.12.25-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2f4e475a80ecbd15896a976aa0b386c5525d0ed34d5c600b6d3ebac0a67c7ddf"}, + {file = "regex-2023.12.25-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:531ac6cf22b53e0696f8e1d56ce2396311254eb806111ddd3922c9d937151dae"}, + {file = "regex-2023.12.25-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:22f3470f7524b6da61e2020672df2f3063676aff444db1daa283c2ea4ed259d6"}, + {file = "regex-2023.12.25-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:89723d2112697feaa320c9d351e5f5e7b841e83f8b143dba8e2d2b5f04e10923"}, + {file = "regex-2023.12.25-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0ecf44ddf9171cd7566ef1768047f6e66975788258b1c6c6ca78098b95cf9a3d"}, + {file = "regex-2023.12.25-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:905466ad1702ed4acfd67a902af50b8db1feeb9781436372261808df7a2a7bca"}, + {file = "regex-2023.12.25-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:4558410b7a5607a645e9804a3e9dd509af12fb72b9825b13791a37cd417d73a5"}, + {file = "regex-2023.12.25-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:7e316026cc1095f2a3e8cc012822c99f413b702eaa2ca5408a513609488cb62f"}, + {file = "regex-2023.12.25-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:3b1de218d5375cd6ac4b5493e0b9f3df2be331e86520f23382f216c137913d20"}, + {file = "regex-2023.12.25-cp39-cp39-win32.whl", hash = "sha256:11a963f8e25ab5c61348d090bf1b07f1953929c13bd2309a0662e9ff680763c9"}, + {file = "regex-2023.12.25-cp39-cp39-win_amd64.whl", hash = "sha256:e693e233ac92ba83a87024e1d32b5f9ab15ca55ddd916d878146f4e3406b5c91"}, + {file = "regex-2023.12.25.tar.gz", hash = "sha256:29171aa128da69afdf4bde412d5bedc335f2ca8fcfe4489038577d05f16181e5"}, ] [[package]] name = "requests" -version = "2.30.0" +version = "2.32.3" description = "Python HTTP for Humans." -category = "main" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "requests-2.30.0-py3-none-any.whl", hash = "sha256:10e94cc4f3121ee6da529d358cdaeaff2f1c409cd377dbc72b825852f2f7e294"}, - {file = "requests-2.30.0.tar.gz", hash = "sha256:239d7d4458afcb28a692cdd298d87542235f4ca8d36d03a15bfc128a6559a2f4"}, + {file = "requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6"}, + {file = "requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760"}, ] [package.dependencies] @@ -1376,7 +1531,6 @@ use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] name = "rfc3986" version = "1.5.0" description = "Validating URI References per RFC 3986" -category = "main" optional = false python-versions = "*" files = [ @@ -1391,7 +1545,6 @@ idna2008 = ["idna"] name = "sgmllib3k" version = "1.0.0" description = "Py3k port of sgmllib." -category = "main" optional = false python-versions = "*" files = [ @@ -1402,7 +1555,6 @@ files = [ name = "six" version = "1.16.0" description = "Python 2 and 3 compatibility utilities" -category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" files = [ @@ -1412,48 +1564,47 @@ files = [ [[package]] name = "sniffio" -version = "1.3.0" +version = "1.3.1" description = "Sniff out which async library your code is running under" -category = "main" optional = false python-versions = ">=3.7" files = [ - {file = "sniffio-1.3.0-py3-none-any.whl", hash = "sha256:eecefdce1e5bbfb7ad2eeaabf7c1eeb404d7757c379bd1f7e5cce9d8bf425384"}, - {file = "sniffio-1.3.0.tar.gz", hash = "sha256:e60305c5e5d314f5389259b7f22aaa33d8f7dee49763119234af3755c55b9101"}, + {file = "sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2"}, + {file = "sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc"}, ] [[package]] name = "soupsieve" -version = "2.4.1" +version = "2.6" description = "A modern CSS selector implementation for Beautiful Soup." -category = "main" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "soupsieve-2.4.1-py3-none-any.whl", hash = "sha256:1c1bfee6819544a3447586c889157365a27e10d88cde3ad3da0cf0ddf646feb8"}, - {file = "soupsieve-2.4.1.tar.gz", hash = "sha256:89d12b2d5dfcd2c9e8c22326da9d9aa9cb3dfab0a83a024f05704076ee8d35ea"}, + {file = "soupsieve-2.6-py3-none-any.whl", hash = "sha256:e72c4ff06e4fb6e4b5a9f0f55fe6e81514581fca1515028625d0f299c602ccc9"}, + {file = "soupsieve-2.6.tar.gz", hash = "sha256:e2e68417777af359ec65daac1057404a3c8a5455bb8abc36f1a9866ab1a51abb"}, ] [[package]] name = "sympy" -version = "1.12" +version = "1.13.2" description = "Computer algebra system (CAS) in Python" -category = "main" optional = false python-versions = ">=3.8" files = [ - {file = "sympy-1.12-py3-none-any.whl", hash = "sha256:c3588cd4295d0c0f603d0f2ae780587e64e2efeedb3521e46b9bb1d08d184fa5"}, - {file = "sympy-1.12.tar.gz", hash = "sha256:ebf595c8dac3e0fdc4152c51878b498396ec7f30e7a914d6071e674d49420fb8"}, + {file = "sympy-1.13.2-py3-none-any.whl", hash = "sha256:c51d75517712f1aed280d4ce58506a4a88d635d6b5dd48b39102a7ae1f3fcfe9"}, + {file = "sympy-1.13.2.tar.gz", hash = "sha256:401449d84d07be9d0c7a46a64bd54fe097667d5e7181bfe67ec777be9e01cb13"}, ] [package.dependencies] -mpmath = ">=0.19" +mpmath = ">=1.1.0,<1.4" + +[package.extras] +dev = ["hypothesis (>=6.70.0)", "pytest (>=7.1.0)"] [[package]] name = "tabulate" version = "0.8.10" description = "Pretty-print tabular data" -category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" files = [ @@ -1468,7 +1619,6 @@ widechars = ["wcwidth"] name = "tomli" version = "2.0.1" description = "A lil' TOML parser" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1478,14 +1628,13 @@ files = [ [[package]] name = "types-beautifulsoup4" -version = "4.12.0.5" +version = "4.12.0.20240511" description = "Typing stubs for beautifulsoup4" -category = "dev" optional = false -python-versions = "*" +python-versions = ">=3.8" files = [ - {file = "types-beautifulsoup4-4.12.0.5.tar.gz", hash = "sha256:d9be456416a62a5b9740559592e1063a69d4b0a1b83911d878558c8ae8e07074"}, - {file = "types_beautifulsoup4-4.12.0.5-py3-none-any.whl", hash = "sha256:718364c8e6787884501c700b1d22b6c0a8711bf9d6c9bf96e1fba81495bc46a8"}, + {file = "types-beautifulsoup4-4.12.0.20240511.tar.gz", hash = "sha256:004f6096fdd83b19cdbf6cb10e4eae57b10205eccc365d0a69d77da836012e28"}, + {file = "types_beautifulsoup4-4.12.0.20240511-py3-none-any.whl", hash = "sha256:7ceda66a93ba28d759d5046d7fec9f4cad2f563a77b3a789efc90bcadafeefd1"}, ] [package.dependencies] @@ -1493,60 +1642,55 @@ types-html5lib = "*" [[package]] name = "types-html5lib" -version = "1.1.11.14" +version = "1.1.11.20240806" description = "Typing stubs for html5lib" -category = "dev" optional = false -python-versions = "*" +python-versions = ">=3.8" files = [ - {file = "types-html5lib-1.1.11.14.tar.gz", hash = "sha256:091e9e74e0ee37c93fd789a164e99b2af80ecf5a314280450c6a763d027ea209"}, - {file = "types_html5lib-1.1.11.14-py3-none-any.whl", hash = "sha256:758c1a27f3b63363a346f3646be9f8b1f25df4fc1f96f88af6d1d831f24ad675"}, + {file = "types-html5lib-1.1.11.20240806.tar.gz", hash = "sha256:8060dc98baf63d6796a765bbbc809fff9f7a383f6e3a9add526f814c086545ef"}, + {file = "types_html5lib-1.1.11.20240806-py3-none-any.whl", hash = "sha256:575c4fd84ba8eeeaa8520c7e4c7042b7791f5ec3e9c0a5d5c418124c42d9e7e4"}, ] [[package]] name = "types-pytz" -version = "2022.7.1.2" +version = "2024.1.0.20240417" description = "Typing stubs for pytz" -category = "dev" optional = false -python-versions = "*" +python-versions = ">=3.8" files = [ - {file = "types-pytz-2022.7.1.2.tar.gz", hash = "sha256:487d3e8e9f4071eec8081746d53fa982bbc05812e719dcbf2ebf3d55a1a4cd28"}, - {file = "types_pytz-2022.7.1.2-py3-none-any.whl", hash = "sha256:40ca448a928d566f7d44ddfde0066e384f7ffbd4da2778e42a4570eaca572446"}, + {file = "types-pytz-2024.1.0.20240417.tar.gz", hash = "sha256:6810c8a1f68f21fdf0f4f374a432487c77645a0ac0b31de4bf4690cf21ad3981"}, + {file = "types_pytz-2024.1.0.20240417-py3-none-any.whl", hash = "sha256:8335d443310e2db7b74e007414e74c4f53b67452c0cb0d228ca359ccfba59659"}, ] [[package]] name = "types-regex" -version = "2022.10.31.6" +version = "2024.7.24.20240726" description = "Typing stubs for regex" -category = "dev" optional = false -python-versions = "*" +python-versions = ">=3.8" files = [ - {file = "types-regex-2022.10.31.6.tar.gz", hash = "sha256:4b552e26afb01597d0a53a3bf4fe5892736c7178ae6e3d9d9b919168e58a6875"}, - {file = "types_regex-2022.10.31.6-py3-none-any.whl", hash = "sha256:0e5917db2ed629b7a658091576cc758fedf48397eae1aa9b085ae3ccfae225f2"}, + {file = "types-regex-2024.7.24.20240726.tar.gz", hash = "sha256:f9cbebe607f53860bf5979de1e2a80cc04faf4849ee324461f982a3d46276d76"}, + {file = "types_regex-2024.7.24.20240726-py3-none-any.whl", hash = "sha256:c436d7eace8e6c33cec31630135c804c15cd4ef110baf9cdd370ac6e376ff661"}, ] [[package]] name = "types-requests" -version = "2.30.0.0" +version = "2.32.0.20240712" description = "Typing stubs for requests" -category = "dev" optional = false -python-versions = "*" +python-versions = ">=3.8" files = [ - {file = "types-requests-2.30.0.0.tar.gz", hash = "sha256:dec781054324a70ba64430ae9e62e7e9c8e4618c185a5cb3f87a6738251b5a31"}, - {file = "types_requests-2.30.0.0-py3-none-any.whl", hash = "sha256:c6cf08e120ca9f0dc4fa4e32c3f953c3fba222bcc1db6b97695bce8da1ba9864"}, + {file = "types-requests-2.32.0.20240712.tar.gz", hash = "sha256:90c079ff05e549f6bf50e02e910210b98b8ff1ebdd18e19c873cd237737c1358"}, + {file = "types_requests-2.32.0.20240712-py3-none-any.whl", hash = "sha256:f754283e152c752e46e70942fa2a146b5bc70393522257bb85bd1ef7e019dcc3"}, ] [package.dependencies] -types-urllib3 = "*" +urllib3 = ">=2" [[package]] name = "types-tabulate" version = "0.8.11" description = "Typing stubs for tabulate" -category = "dev" optional = false python-versions = "*" files = [ @@ -1554,40 +1698,26 @@ files = [ {file = "types_tabulate-0.8.11-py3-none-any.whl", hash = "sha256:af811268241e8fb87b63c052c87d1e329898a93191309d5d42111372232b2e0e"}, ] -[[package]] -name = "types-urllib3" -version = "1.26.25.13" -description = "Typing stubs for urllib3" -category = "dev" -optional = false -python-versions = "*" -files = [ - {file = "types-urllib3-1.26.25.13.tar.gz", hash = "sha256:3300538c9dc11dad32eae4827ac313f5d986b8b21494801f1bf97a1ac6c03ae5"}, - {file = "types_urllib3-1.26.25.13-py3-none-any.whl", hash = "sha256:5dbd1d2bef14efee43f5318b5d36d805a489f6600252bb53626d4bfafd95e27c"}, -] - [[package]] name = "typing-extensions" -version = "4.5.0" -description = "Backported and Experimental Type Hints for Python 3.7+" -category = "main" +version = "4.12.2" +description = "Backported and Experimental Type Hints for Python 3.8+" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "typing_extensions-4.5.0-py3-none-any.whl", hash = "sha256:fb33085c39dd998ac16d1431ebc293a8b3eedd00fd4a32de0ff79002c19511b4"}, - {file = "typing_extensions-4.5.0.tar.gz", hash = "sha256:5cb5f4a79139d699607b3ef622a1dedafa84e115ab0024e0d9c044a9479ca7cb"}, + {file = "typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d"}, + {file = "typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8"}, ] [[package]] name = "urllib3" -version = "2.0.2" +version = "2.0.7" description = "HTTP library with thread-safe connection pooling, file post, and more." -category = "main" optional = false python-versions = ">=3.7" files = [ - {file = "urllib3-2.0.2-py3-none-any.whl", hash = "sha256:d055c2f9d38dc53c808f6fdc8eab7360b6fdbbde02340ed25cfbcd817c62469e"}, - {file = "urllib3-2.0.2.tar.gz", hash = "sha256:61717a1095d7e155cdb737ac7bb2f4324a858a1e2e6466f6d03ff630ca68d3cc"}, + {file = "urllib3-2.0.7-py3-none-any.whl", hash = "sha256:fdb6d215c776278489906c2f8916e6e7d4f5a9b602ccbcfdf7f016fc8da0596e"}, + {file = "urllib3-2.0.7.tar.gz", hash = "sha256:c97dfde1f7bd43a71c8d2a58e369e9b2bf692d1334ea9f9cae55add7d0dd0f84"}, ] [package.extras] @@ -1600,7 +1730,6 @@ zstd = ["zstandard (>=0.18.0)"] name = "uvloop" version = "0.17.0" description = "Fast implementation of asyncio event loop on top of libuv" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1643,166 +1772,198 @@ test = ["Cython (>=0.29.32,<0.30.0)", "aiohttp", "flake8 (>=3.9.2,<3.10.0)", "my [[package]] name = "websockets" -version = "11.0.3" +version = "13.0.1" description = "An implementation of the WebSocket Protocol (RFC 6455 & 7692)" -category = "main" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "websockets-11.0.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:3ccc8a0c387629aec40f2fc9fdcb4b9d5431954f934da3eaf16cdc94f67dbfac"}, - {file = "websockets-11.0.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d67ac60a307f760c6e65dad586f556dde58e683fab03323221a4e530ead6f74d"}, - {file = "websockets-11.0.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:84d27a4832cc1a0ee07cdcf2b0629a8a72db73f4cf6de6f0904f6661227f256f"}, - {file = "websockets-11.0.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ffd7dcaf744f25f82190856bc26ed81721508fc5cbf2a330751e135ff1283564"}, - {file = "websockets-11.0.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7622a89d696fc87af8e8d280d9b421db5133ef5b29d3f7a1ce9f1a7bf7fcfa11"}, - {file = "websockets-11.0.3-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bceab846bac555aff6427d060f2fcfff71042dba6f5fca7dc4f75cac815e57ca"}, - {file = "websockets-11.0.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:54c6e5b3d3a8936a4ab6870d46bdd6ec500ad62bde9e44462c32d18f1e9a8e54"}, - {file = "websockets-11.0.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:41f696ba95cd92dc047e46b41b26dd24518384749ed0d99bea0a941ca87404c4"}, - {file = "websockets-11.0.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:86d2a77fd490ae3ff6fae1c6ceaecad063d3cc2320b44377efdde79880e11526"}, - {file = "websockets-11.0.3-cp310-cp310-win32.whl", hash = "sha256:2d903ad4419f5b472de90cd2d40384573b25da71e33519a67797de17ef849b69"}, - {file = "websockets-11.0.3-cp310-cp310-win_amd64.whl", hash = "sha256:1d2256283fa4b7f4c7d7d3e84dc2ece74d341bce57d5b9bf385df109c2a1a82f"}, - {file = "websockets-11.0.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:e848f46a58b9fcf3d06061d17be388caf70ea5b8cc3466251963c8345e13f7eb"}, - {file = "websockets-11.0.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:aa5003845cdd21ac0dc6c9bf661c5beddd01116f6eb9eb3c8e272353d45b3288"}, - {file = "websockets-11.0.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b58cbf0697721120866820b89f93659abc31c1e876bf20d0b3d03cef14faf84d"}, - {file = "websockets-11.0.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:660e2d9068d2bedc0912af508f30bbeb505bbbf9774d98def45f68278cea20d3"}, - {file = "websockets-11.0.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c1f0524f203e3bd35149f12157438f406eff2e4fb30f71221c8a5eceb3617b6b"}, - {file = "websockets-11.0.3-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:def07915168ac8f7853812cc593c71185a16216e9e4fa886358a17ed0fd9fcf6"}, - {file = "websockets-11.0.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:b30c6590146e53149f04e85a6e4fcae068df4289e31e4aee1fdf56a0dead8f97"}, - {file = "websockets-11.0.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:619d9f06372b3a42bc29d0cd0354c9bb9fb39c2cbc1a9c5025b4538738dbffaf"}, - {file = "websockets-11.0.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:01f5567d9cf6f502d655151645d4e8b72b453413d3819d2b6f1185abc23e82dd"}, - {file = "websockets-11.0.3-cp311-cp311-win32.whl", hash = "sha256:e1459677e5d12be8bbc7584c35b992eea142911a6236a3278b9b5ce3326f282c"}, - {file = "websockets-11.0.3-cp311-cp311-win_amd64.whl", hash = "sha256:e7837cb169eca3b3ae94cc5787c4fed99eef74c0ab9506756eea335e0d6f3ed8"}, - {file = "websockets-11.0.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:9f59a3c656fef341a99e3d63189852be7084c0e54b75734cde571182c087b152"}, - {file = "websockets-11.0.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2529338a6ff0eb0b50c7be33dc3d0e456381157a31eefc561771ee431134a97f"}, - {file = "websockets-11.0.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:34fd59a4ac42dff6d4681d8843217137f6bc85ed29722f2f7222bd619d15e95b"}, - {file = "websockets-11.0.3-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:332d126167ddddec94597c2365537baf9ff62dfcc9db4266f263d455f2f031cb"}, - {file = "websockets-11.0.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:6505c1b31274723ccaf5f515c1824a4ad2f0d191cec942666b3d0f3aa4cb4007"}, - {file = "websockets-11.0.3-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:f467ba0050b7de85016b43f5a22b46383ef004c4f672148a8abf32bc999a87f0"}, - {file = "websockets-11.0.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:9d9acd80072abcc98bd2c86c3c9cd4ac2347b5a5a0cae7ed5c0ee5675f86d9af"}, - {file = "websockets-11.0.3-cp37-cp37m-win32.whl", hash = "sha256:e590228200fcfc7e9109509e4d9125eace2042fd52b595dd22bbc34bb282307f"}, - {file = "websockets-11.0.3-cp37-cp37m-win_amd64.whl", hash = "sha256:b16fff62b45eccb9c7abb18e60e7e446998093cdcb50fed33134b9b6878836de"}, - {file = "websockets-11.0.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:fb06eea71a00a7af0ae6aefbb932fb8a7df3cb390cc217d51a9ad7343de1b8d0"}, - {file = "websockets-11.0.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:8a34e13a62a59c871064dfd8ffb150867e54291e46d4a7cf11d02c94a5275bae"}, - {file = "websockets-11.0.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:4841ed00f1026dfbced6fca7d963c4e7043aa832648671b5138008dc5a8f6d99"}, - {file = "websockets-11.0.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1a073fc9ab1c8aff37c99f11f1641e16da517770e31a37265d2755282a5d28aa"}, - {file = "websockets-11.0.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:68b977f21ce443d6d378dbd5ca38621755f2063d6fdb3335bda981d552cfff86"}, - {file = "websockets-11.0.3-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e1a99a7a71631f0efe727c10edfba09ea6bee4166a6f9c19aafb6c0b5917d09c"}, - {file = "websockets-11.0.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:bee9fcb41db2a23bed96c6b6ead6489702c12334ea20a297aa095ce6d31370d0"}, - {file = "websockets-11.0.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:4b253869ea05a5a073ebfdcb5cb3b0266a57c3764cf6fe114e4cd90f4bfa5f5e"}, - {file = "websockets-11.0.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:1553cb82942b2a74dd9b15a018dce645d4e68674de2ca31ff13ebc2d9f283788"}, - {file = "websockets-11.0.3-cp38-cp38-win32.whl", hash = "sha256:f61bdb1df43dc9c131791fbc2355535f9024b9a04398d3bd0684fc16ab07df74"}, - {file = "websockets-11.0.3-cp38-cp38-win_amd64.whl", hash = "sha256:03aae4edc0b1c68498f41a6772d80ac7c1e33c06c6ffa2ac1c27a07653e79d6f"}, - {file = "websockets-11.0.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:777354ee16f02f643a4c7f2b3eff8027a33c9861edc691a2003531f5da4f6bc8"}, - {file = "websockets-11.0.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8c82f11964f010053e13daafdc7154ce7385ecc538989a354ccc7067fd7028fd"}, - {file = "websockets-11.0.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3580dd9c1ad0701169e4d6fc41e878ffe05e6bdcaf3c412f9d559389d0c9e016"}, - {file = "websockets-11.0.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6f1a3f10f836fab6ca6efa97bb952300b20ae56b409414ca85bff2ad241d2a61"}, - {file = "websockets-11.0.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:df41b9bc27c2c25b486bae7cf42fccdc52ff181c8c387bfd026624a491c2671b"}, - {file = "websockets-11.0.3-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:279e5de4671e79a9ac877427f4ac4ce93751b8823f276b681d04b2156713b9dd"}, - {file = "websockets-11.0.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:1fdf26fa8a6a592f8f9235285b8affa72748dc12e964a5518c6c5e8f916716f7"}, - {file = "websockets-11.0.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:69269f3a0b472e91125b503d3c0b3566bda26da0a3261c49f0027eb6075086d1"}, - {file = "websockets-11.0.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:97b52894d948d2f6ea480171a27122d77af14ced35f62e5c892ca2fae9344311"}, - {file = "websockets-11.0.3-cp39-cp39-win32.whl", hash = "sha256:c7f3cb904cce8e1be667c7e6fef4516b98d1a6a0635a58a57528d577ac18a128"}, - {file = "websockets-11.0.3-cp39-cp39-win_amd64.whl", hash = "sha256:c792ea4eabc0159535608fc5658a74d1a81020eb35195dd63214dcf07556f67e"}, - {file = "websockets-11.0.3-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:f2e58f2c36cc52d41f2659e4c0cbf7353e28c8c9e63e30d8c6d3494dc9fdedcf"}, - {file = "websockets-11.0.3-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:de36fe9c02995c7e6ae6efe2e205816f5f00c22fd1fbf343d4d18c3d5ceac2f5"}, - {file = "websockets-11.0.3-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0ac56b661e60edd453585f4bd68eb6a29ae25b5184fd5ba51e97652580458998"}, - {file = "websockets-11.0.3-pp37-pypy37_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e052b8467dd07d4943936009f46ae5ce7b908ddcac3fda581656b1b19c083d9b"}, - {file = "websockets-11.0.3-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:42cc5452a54a8e46a032521d7365da775823e21bfba2895fb7b77633cce031bb"}, - {file = "websockets-11.0.3-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:e6316827e3e79b7b8e7d8e3b08f4e331af91a48e794d5d8b099928b6f0b85f20"}, - {file = "websockets-11.0.3-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8531fdcad636d82c517b26a448dcfe62f720e1922b33c81ce695d0edb91eb931"}, - {file = "websockets-11.0.3-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c114e8da9b475739dde229fd3bc6b05a6537a88a578358bc8eb29b4030fac9c9"}, - {file = "websockets-11.0.3-pp38-pypy38_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e063b1865974611313a3849d43f2c3f5368093691349cf3c7c8f8f75ad7cb280"}, - {file = "websockets-11.0.3-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:92b2065d642bf8c0a82d59e59053dd2fdde64d4ed44efe4870fa816c1232647b"}, - {file = "websockets-11.0.3-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:0ee68fe502f9031f19d495dae2c268830df2760c0524cbac5d759921ba8c8e82"}, - {file = "websockets-11.0.3-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dcacf2c7a6c3a84e720d1bb2b543c675bf6c40e460300b628bab1b1efc7c034c"}, - {file = "websockets-11.0.3-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b67c6f5e5a401fc56394f191f00f9b3811fe843ee93f4a70df3c389d1adf857d"}, - {file = "websockets-11.0.3-pp39-pypy39_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1d5023a4b6a5b183dc838808087033ec5df77580485fc533e7dab2567851b0a4"}, - {file = "websockets-11.0.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:ed058398f55163a79bb9f06a90ef9ccc063b204bb346c4de78efc5d15abfe602"}, - {file = "websockets-11.0.3-py3-none-any.whl", hash = "sha256:6681ba9e7f8f3b19440921e99efbb40fc89f26cd71bf539e45d8c8a25c976dc6"}, - {file = "websockets-11.0.3.tar.gz", hash = "sha256:88fc51d9a26b10fc331be344f1781224a375b78488fc343620184e95a4b27016"}, + {file = "websockets-13.0.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:1841c9082a3ba4a05ea824cf6d99570a6a2d8849ef0db16e9c826acb28089e8f"}, + {file = "websockets-13.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c5870b4a11b77e4caa3937142b650fbbc0914a3e07a0cf3131f35c0587489c1c"}, + {file = "websockets-13.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f1d3d1f2eb79fe7b0fb02e599b2bf76a7619c79300fc55f0b5e2d382881d4f7f"}, + {file = "websockets-13.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:15c7d62ee071fa94a2fc52c2b472fed4af258d43f9030479d9c4a2de885fd543"}, + {file = "websockets-13.0.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6724b554b70d6195ba19650fef5759ef11346f946c07dbbe390e039bcaa7cc3d"}, + {file = "websockets-13.0.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:56a952fa2ae57a42ba7951e6b2605e08a24801a4931b5644dfc68939e041bc7f"}, + {file = "websockets-13.0.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:17118647c0ea14796364299e942c330d72acc4b248e07e639d34b75067b3cdd8"}, + {file = "websockets-13.0.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:64a11aae1de4c178fa653b07d90f2fb1a2ed31919a5ea2361a38760192e1858b"}, + {file = "websockets-13.0.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:0617fd0b1d14309c7eab6ba5deae8a7179959861846cbc5cb528a7531c249448"}, + {file = "websockets-13.0.1-cp310-cp310-win32.whl", hash = "sha256:11f9976ecbc530248cf162e359a92f37b7b282de88d1d194f2167b5e7ad80ce3"}, + {file = "websockets-13.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:c3c493d0e5141ec055a7d6809a28ac2b88d5b878bb22df8c621ebe79a61123d0"}, + {file = "websockets-13.0.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:699ba9dd6a926f82a277063603fc8d586b89f4cb128efc353b749b641fcddda7"}, + {file = "websockets-13.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:cf2fae6d85e5dc384bf846f8243ddaa9197f3a1a70044f59399af001fd1f51d4"}, + {file = "websockets-13.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:52aed6ef21a0f1a2a5e310fb5c42d7555e9c5855476bbd7173c3aa3d8a0302f2"}, + {file = "websockets-13.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8eb2b9a318542153674c6e377eb8cb9ca0fc011c04475110d3477862f15d29f0"}, + {file = "websockets-13.0.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5df891c86fe68b2c38da55b7aea7095beca105933c697d719f3f45f4220a5e0e"}, + {file = "websockets-13.0.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fac2d146ff30d9dd2fcf917e5d147db037a5c573f0446c564f16f1f94cf87462"}, + {file = "websockets-13.0.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:b8ac5b46fd798bbbf2ac6620e0437c36a202b08e1f827832c4bf050da081b501"}, + {file = "websockets-13.0.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:46af561eba6f9b0848b2c9d2427086cabadf14e0abdd9fde9d72d447df268418"}, + {file = "websockets-13.0.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:b5a06d7f60bc2fc378a333978470dfc4e1415ee52f5f0fce4f7853eb10c1e9df"}, + {file = "websockets-13.0.1-cp311-cp311-win32.whl", hash = "sha256:556e70e4f69be1082e6ef26dcb70efcd08d1850f5d6c5f4f2bcb4e397e68f01f"}, + {file = "websockets-13.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:67494e95d6565bf395476e9d040037ff69c8b3fa356a886b21d8422ad86ae075"}, + {file = "websockets-13.0.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:f9c9e258e3d5efe199ec23903f5da0eeaad58cf6fccb3547b74fd4750e5ac47a"}, + {file = "websockets-13.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:6b41a1b3b561f1cba8321fb32987552a024a8f67f0d05f06fcf29f0090a1b956"}, + {file = "websockets-13.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f73e676a46b0fe9426612ce8caeca54c9073191a77c3e9d5c94697aef99296af"}, + {file = "websockets-13.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f613289f4a94142f914aafad6c6c87903de78eae1e140fa769a7385fb232fdf"}, + {file = "websockets-13.0.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0f52504023b1480d458adf496dc1c9e9811df4ba4752f0bc1f89ae92f4f07d0c"}, + {file = "websockets-13.0.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:139add0f98206cb74109faf3611b7783ceafc928529c62b389917a037d4cfdf4"}, + {file = "websockets-13.0.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:47236c13be337ef36546004ce8c5580f4b1150d9538b27bf8a5ad8edf23ccfab"}, + {file = "websockets-13.0.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:c44ca9ade59b2e376612df34e837013e2b273e6c92d7ed6636d0556b6f4db93d"}, + {file = "websockets-13.0.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:9bbc525f4be3e51b89b2a700f5746c2a6907d2e2ef4513a8daafc98198b92237"}, + {file = "websockets-13.0.1-cp312-cp312-win32.whl", hash = "sha256:3624fd8664f2577cf8de996db3250662e259bfbc870dd8ebdcf5d7c6ac0b5185"}, + {file = "websockets-13.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:0513c727fb8adffa6d9bf4a4463b2bade0186cbd8c3604ae5540fae18a90cb99"}, + {file = "websockets-13.0.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:1ee4cc030a4bdab482a37462dbf3ffb7e09334d01dd37d1063be1136a0d825fa"}, + {file = "websockets-13.0.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:dbb0b697cc0655719522406c059eae233abaa3243821cfdfab1215d02ac10231"}, + {file = "websockets-13.0.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:acbebec8cb3d4df6e2488fbf34702cbc37fc39ac7abf9449392cefb3305562e9"}, + {file = "websockets-13.0.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:63848cdb6fcc0bf09d4a155464c46c64ffdb5807ede4fb251da2c2692559ce75"}, + {file = "websockets-13.0.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:872afa52a9f4c414d6955c365b6588bc4401272c629ff8321a55f44e3f62b553"}, + {file = "websockets-13.0.1-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:05e70fec7c54aad4d71eae8e8cab50525e899791fc389ec6f77b95312e4e9920"}, + {file = "websockets-13.0.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:e82db3756ccb66266504f5a3de05ac6b32f287faacff72462612120074103329"}, + {file = "websockets-13.0.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:4e85f46ce287f5c52438bb3703d86162263afccf034a5ef13dbe4318e98d86e7"}, + {file = "websockets-13.0.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:f3fea72e4e6edb983908f0db373ae0732b275628901d909c382aae3b592589f2"}, + {file = "websockets-13.0.1-cp313-cp313-win32.whl", hash = "sha256:254ecf35572fca01a9f789a1d0f543898e222f7b69ecd7d5381d8d8047627bdb"}, + {file = "websockets-13.0.1-cp313-cp313-win_amd64.whl", hash = "sha256:ca48914cdd9f2ccd94deab5bcb5ac98025a5ddce98881e5cce762854a5de330b"}, + {file = "websockets-13.0.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:b74593e9acf18ea5469c3edaa6b27fa7ecf97b30e9dabd5a94c4c940637ab96e"}, + {file = "websockets-13.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:132511bfd42e77d152c919147078460c88a795af16b50e42a0bd14f0ad71ddd2"}, + {file = "websockets-13.0.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:165bedf13556f985a2aa064309baa01462aa79bf6112fbd068ae38993a0e1f1b"}, + {file = "websockets-13.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e801ca2f448850685417d723ec70298feff3ce4ff687c6f20922c7474b4746ae"}, + {file = "websockets-13.0.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:30d3a1f041360f029765d8704eae606781e673e8918e6b2c792e0775de51352f"}, + {file = "websockets-13.0.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:67648f5e50231b5a7f6d83b32f9c525e319f0ddc841be0de64f24928cd75a603"}, + {file = "websockets-13.0.1-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:4f0426d51c8f0926a4879390f53c7f5a855e42d68df95fff6032c82c888b5f36"}, + {file = "websockets-13.0.1-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:ef48e4137e8799998a343706531e656fdec6797b80efd029117edacb74b0a10a"}, + {file = "websockets-13.0.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:249aab278810bee585cd0d4de2f08cfd67eed4fc75bde623be163798ed4db2eb"}, + {file = "websockets-13.0.1-cp38-cp38-win32.whl", hash = "sha256:06c0a667e466fcb56a0886d924b5f29a7f0886199102f0a0e1c60a02a3751cb4"}, + {file = "websockets-13.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:1f3cf6d6ec1142412d4535adabc6bd72a63f5f148c43fe559f06298bc21953c9"}, + {file = "websockets-13.0.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:1fa082ea38d5de51dd409434edc27c0dcbd5fed2b09b9be982deb6f0508d25bc"}, + {file = "websockets-13.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:4a365bcb7be554e6e1f9f3ed64016e67e2fa03d7b027a33e436aecf194febb63"}, + {file = "websockets-13.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:10a0dc7242215d794fb1918f69c6bb235f1f627aaf19e77f05336d147fce7c37"}, + {file = "websockets-13.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:59197afd478545b1f73367620407b0083303569c5f2d043afe5363676f2697c9"}, + {file = "websockets-13.0.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7d20516990d8ad557b5abeb48127b8b779b0b7e6771a265fa3e91767596d7d97"}, + {file = "websockets-13.0.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a1a2e272d067030048e1fe41aa1ec8cfbbaabce733b3d634304fa2b19e5c897f"}, + {file = "websockets-13.0.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:ad327ac80ba7ee61da85383ca8822ff808ab5ada0e4a030d66703cc025b021c4"}, + {file = "websockets-13.0.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:518f90e6dd089d34eaade01101fd8a990921c3ba18ebbe9b0165b46ebff947f0"}, + {file = "websockets-13.0.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:68264802399aed6fe9652e89761031acc734fc4c653137a5911c2bfa995d6d6d"}, + {file = "websockets-13.0.1-cp39-cp39-win32.whl", hash = "sha256:a5dc0c42ded1557cc7c3f0240b24129aefbad88af4f09346164349391dea8e58"}, + {file = "websockets-13.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:b448a0690ef43db5ef31b3a0d9aea79043882b4632cfc3eaab20105edecf6097"}, + {file = "websockets-13.0.1-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:faef9ec6354fe4f9a2c0bbb52fb1ff852effc897e2a4501e25eb3a47cb0a4f89"}, + {file = "websockets-13.0.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:03d3f9ba172e0a53e37fa4e636b86cc60c3ab2cfee4935e66ed1d7acaa4625ad"}, + {file = "websockets-13.0.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d450f5a7a35662a9b91a64aefa852f0c0308ee256122f5218a42f1d13577d71e"}, + {file = "websockets-13.0.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3f55b36d17ac50aa8a171b771e15fbe1561217510c8768af3d546f56c7576cdc"}, + {file = "websockets-13.0.1-pp310-pypy310_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:14b9c006cac63772b31abbcd3e3abb6228233eec966bf062e89e7fa7ae0b7333"}, + {file = "websockets-13.0.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:b79915a1179a91f6c5f04ece1e592e2e8a6bd245a0e45d12fd56b2b59e559a32"}, + {file = "websockets-13.0.1-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:f40de079779acbcdbb6ed4c65af9f018f8b77c5ec4e17a4b737c05c2db554491"}, + {file = "websockets-13.0.1-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:80e4ba642fc87fa532bac07e5ed7e19d56940b6af6a8c61d4429be48718a380f"}, + {file = "websockets-13.0.1-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2a02b0161c43cc9e0232711eff846569fad6ec836a7acab16b3cf97b2344c060"}, + {file = "websockets-13.0.1-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6aa74a45d4cdc028561a7d6ab3272c8b3018e23723100b12e58be9dfa5a24491"}, + {file = "websockets-13.0.1-pp38-pypy38_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:00fd961943b6c10ee6f0b1130753e50ac5dcd906130dcd77b0003c3ab797d026"}, + {file = "websockets-13.0.1-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:d93572720d781331fb10d3da9ca1067817d84ad1e7c31466e9f5e59965618096"}, + {file = "websockets-13.0.1-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:71e6e5a3a3728886caee9ab8752e8113670936a193284be9d6ad2176a137f376"}, + {file = "websockets-13.0.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:c4a6343e3b0714e80da0b0893543bf9a5b5fa71b846ae640e56e9abc6fbc4c83"}, + {file = "websockets-13.0.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1a678532018e435396e37422a95e3ab87f75028ac79570ad11f5bf23cd2a7d8c"}, + {file = "websockets-13.0.1-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d6716c087e4aa0b9260c4e579bb82e068f84faddb9bfba9906cb87726fa2e870"}, + {file = "websockets-13.0.1-pp39-pypy39_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e33505534f3f673270dd67f81e73550b11de5b538c56fe04435d63c02c3f26b5"}, + {file = "websockets-13.0.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:acab3539a027a85d568c2573291e864333ec9d912675107d6efceb7e2be5d980"}, + {file = "websockets-13.0.1-py3-none-any.whl", hash = "sha256:b80f0c51681c517604152eb6a572f5a9378f877763231fddb883ba2f968e8817"}, + {file = "websockets-13.0.1.tar.gz", hash = "sha256:4d6ece65099411cfd9a48d13701d7438d9c34f479046b34c50ff60bb8834e43e"}, ] [[package]] name = "yarl" -version = "1.9.2" +version = "1.9.9" description = "Yet another URL library" -category = "main" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "yarl-1.9.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:8c2ad583743d16ddbdf6bb14b5cd76bf43b0d0006e918809d5d4ddf7bde8dd82"}, - {file = "yarl-1.9.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:82aa6264b36c50acfb2424ad5ca537a2060ab6de158a5bd2a72a032cc75b9eb8"}, - {file = "yarl-1.9.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c0c77533b5ed4bcc38e943178ccae29b9bcf48ffd1063f5821192f23a1bd27b9"}, - {file = "yarl-1.9.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ee4afac41415d52d53a9833ebae7e32b344be72835bbb589018c9e938045a560"}, - {file = "yarl-1.9.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9bf345c3a4f5ba7f766430f97f9cc1320786f19584acc7086491f45524a551ac"}, - {file = "yarl-1.9.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2a96c19c52ff442a808c105901d0bdfd2e28575b3d5f82e2f5fd67e20dc5f4ea"}, - {file = "yarl-1.9.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:891c0e3ec5ec881541f6c5113d8df0315ce5440e244a716b95f2525b7b9f3608"}, - {file = "yarl-1.9.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c3a53ba34a636a256d767c086ceb111358876e1fb6b50dfc4d3f4951d40133d5"}, - {file = "yarl-1.9.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:566185e8ebc0898b11f8026447eacd02e46226716229cea8db37496c8cdd26e0"}, - {file = "yarl-1.9.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:2b0738fb871812722a0ac2154be1f049c6223b9f6f22eec352996b69775b36d4"}, - {file = "yarl-1.9.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:32f1d071b3f362c80f1a7d322bfd7b2d11e33d2adf395cc1dd4df36c9c243095"}, - {file = "yarl-1.9.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:e9fdc7ac0d42bc3ea78818557fab03af6181e076a2944f43c38684b4b6bed8e3"}, - {file = "yarl-1.9.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:56ff08ab5df8429901ebdc5d15941b59f6253393cb5da07b4170beefcf1b2528"}, - {file = "yarl-1.9.2-cp310-cp310-win32.whl", hash = "sha256:8ea48e0a2f931064469bdabca50c2f578b565fc446f302a79ba6cc0ee7f384d3"}, - {file = "yarl-1.9.2-cp310-cp310-win_amd64.whl", hash = "sha256:50f33040f3836e912ed16d212f6cc1efb3231a8a60526a407aeb66c1c1956dde"}, - {file = "yarl-1.9.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:646d663eb2232d7909e6601f1a9107e66f9791f290a1b3dc7057818fe44fc2b6"}, - {file = "yarl-1.9.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:aff634b15beff8902d1f918012fc2a42e0dbae6f469fce134c8a0dc51ca423bb"}, - {file = "yarl-1.9.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a83503934c6273806aed765035716216cc9ab4e0364f7f066227e1aaea90b8d0"}, - {file = "yarl-1.9.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b25322201585c69abc7b0e89e72790469f7dad90d26754717f3310bfe30331c2"}, - {file = "yarl-1.9.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:22a94666751778629f1ec4280b08eb11815783c63f52092a5953faf73be24191"}, - {file = "yarl-1.9.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8ec53a0ea2a80c5cd1ab397925f94bff59222aa3cf9c6da938ce05c9ec20428d"}, - {file = "yarl-1.9.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:159d81f22d7a43e6eabc36d7194cb53f2f15f498dbbfa8edc8a3239350f59fe7"}, - {file = "yarl-1.9.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:832b7e711027c114d79dffb92576acd1bd2decc467dec60e1cac96912602d0e6"}, - {file = "yarl-1.9.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:95d2ecefbcf4e744ea952d073c6922e72ee650ffc79028eb1e320e732898d7e8"}, - {file = "yarl-1.9.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:d4e2c6d555e77b37288eaf45b8f60f0737c9efa3452c6c44626a5455aeb250b9"}, - {file = "yarl-1.9.2-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:783185c75c12a017cc345015ea359cc801c3b29a2966c2655cd12b233bf5a2be"}, - {file = "yarl-1.9.2-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:b8cc1863402472f16c600e3e93d542b7e7542a540f95c30afd472e8e549fc3f7"}, - {file = "yarl-1.9.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:822b30a0f22e588b32d3120f6d41e4ed021806418b4c9f0bc3048b8c8cb3f92a"}, - {file = "yarl-1.9.2-cp311-cp311-win32.whl", hash = "sha256:a60347f234c2212a9f0361955007fcf4033a75bf600a33c88a0a8e91af77c0e8"}, - {file = "yarl-1.9.2-cp311-cp311-win_amd64.whl", hash = "sha256:be6b3fdec5c62f2a67cb3f8c6dbf56bbf3f61c0f046f84645cd1ca73532ea051"}, - {file = "yarl-1.9.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:38a3928ae37558bc1b559f67410df446d1fbfa87318b124bf5032c31e3447b74"}, - {file = "yarl-1.9.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ac9bb4c5ce3975aeac288cfcb5061ce60e0d14d92209e780c93954076c7c4367"}, - {file = "yarl-1.9.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3da8a678ca8b96c8606bbb8bfacd99a12ad5dd288bc6f7979baddd62f71c63ef"}, - {file = "yarl-1.9.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:13414591ff516e04fcdee8dc051c13fd3db13b673c7a4cb1350e6b2ad9639ad3"}, - {file = "yarl-1.9.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bf74d08542c3a9ea97bb8f343d4fcbd4d8f91bba5ec9d5d7f792dbe727f88938"}, - {file = "yarl-1.9.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6e7221580dc1db478464cfeef9b03b95c5852cc22894e418562997df0d074ccc"}, - {file = "yarl-1.9.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:494053246b119b041960ddcd20fd76224149cfea8ed8777b687358727911dd33"}, - {file = "yarl-1.9.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:52a25809fcbecfc63ac9ba0c0fb586f90837f5425edfd1ec9f3372b119585e45"}, - {file = "yarl-1.9.2-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:e65610c5792870d45d7b68c677681376fcf9cc1c289f23e8e8b39c1485384185"}, - {file = "yarl-1.9.2-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:1b1bba902cba32cdec51fca038fd53f8beee88b77efc373968d1ed021024cc04"}, - {file = "yarl-1.9.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:662e6016409828ee910f5d9602a2729a8a57d74b163c89a837de3fea050c7582"}, - {file = "yarl-1.9.2-cp37-cp37m-win32.whl", hash = "sha256:f364d3480bffd3aa566e886587eaca7c8c04d74f6e8933f3f2c996b7f09bee1b"}, - {file = "yarl-1.9.2-cp37-cp37m-win_amd64.whl", hash = "sha256:6a5883464143ab3ae9ba68daae8e7c5c95b969462bbe42e2464d60e7e2698368"}, - {file = "yarl-1.9.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5610f80cf43b6202e2c33ba3ec2ee0a2884f8f423c8f4f62906731d876ef4fac"}, - {file = "yarl-1.9.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:b9a4e67ad7b646cd6f0938c7ebfd60e481b7410f574c560e455e938d2da8e0f4"}, - {file = "yarl-1.9.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:83fcc480d7549ccebe9415d96d9263e2d4226798c37ebd18c930fce43dfb9574"}, - {file = "yarl-1.9.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5fcd436ea16fee7d4207c045b1e340020e58a2597301cfbcfdbe5abd2356c2fb"}, - {file = "yarl-1.9.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:84e0b1599334b1e1478db01b756e55937d4614f8654311eb26012091be109d59"}, - {file = "yarl-1.9.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3458a24e4ea3fd8930e934c129b676c27452e4ebda80fbe47b56d8c6c7a63a9e"}, - {file = "yarl-1.9.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:838162460b3a08987546e881a2bfa573960bb559dfa739e7800ceeec92e64417"}, - {file = "yarl-1.9.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f4e2d08f07a3d7d3e12549052eb5ad3eab1c349c53ac51c209a0e5991bbada78"}, - {file = "yarl-1.9.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:de119f56f3c5f0e2fb4dee508531a32b069a5f2c6e827b272d1e0ff5ac040333"}, - {file = "yarl-1.9.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:149ddea5abf329752ea5051b61bd6c1d979e13fbf122d3a1f9f0c8be6cb6f63c"}, - {file = "yarl-1.9.2-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:674ca19cbee4a82c9f54e0d1eee28116e63bc6fd1e96c43031d11cbab8b2afd5"}, - {file = "yarl-1.9.2-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:9b3152f2f5677b997ae6c804b73da05a39daa6a9e85a512e0e6823d81cdad7cc"}, - {file = "yarl-1.9.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:5415d5a4b080dc9612b1b63cba008db84e908b95848369aa1da3686ae27b6d2b"}, - {file = "yarl-1.9.2-cp38-cp38-win32.whl", hash = "sha256:f7a3d8146575e08c29ed1cd287068e6d02f1c7bdff8970db96683b9591b86ee7"}, - {file = "yarl-1.9.2-cp38-cp38-win_amd64.whl", hash = "sha256:63c48f6cef34e6319a74c727376e95626f84ea091f92c0250a98e53e62c77c72"}, - {file = "yarl-1.9.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:75df5ef94c3fdc393c6b19d80e6ef1ecc9ae2f4263c09cacb178d871c02a5ba9"}, - {file = "yarl-1.9.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c027a6e96ef77d401d8d5a5c8d6bc478e8042f1e448272e8d9752cb0aff8b5c8"}, - {file = "yarl-1.9.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f3b078dbe227f79be488ffcfc7a9edb3409d018e0952cf13f15fd6512847f3f7"}, - {file = "yarl-1.9.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:59723a029760079b7d991a401386390c4be5bfec1e7dd83e25a6a0881859e716"}, - {file = "yarl-1.9.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b03917871bf859a81ccb180c9a2e6c1e04d2f6a51d953e6a5cdd70c93d4e5a2a"}, - {file = "yarl-1.9.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c1012fa63eb6c032f3ce5d2171c267992ae0c00b9e164efe4d73db818465fac3"}, - {file = "yarl-1.9.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a74dcbfe780e62f4b5a062714576f16c2f3493a0394e555ab141bf0d746bb955"}, - {file = "yarl-1.9.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8c56986609b057b4839968ba901944af91b8e92f1725d1a2d77cbac6972b9ed1"}, - {file = "yarl-1.9.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:2c315df3293cd521033533d242d15eab26583360b58f7ee5d9565f15fee1bef4"}, - {file = "yarl-1.9.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:b7232f8dfbd225d57340e441d8caf8652a6acd06b389ea2d3222b8bc89cbfca6"}, - {file = "yarl-1.9.2-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:53338749febd28935d55b41bf0bcc79d634881195a39f6b2f767870b72514caf"}, - {file = "yarl-1.9.2-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:066c163aec9d3d073dc9ffe5dd3ad05069bcb03fcaab8d221290ba99f9f69ee3"}, - {file = "yarl-1.9.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8288d7cd28f8119b07dd49b7230d6b4562f9b61ee9a4ab02221060d21136be80"}, - {file = "yarl-1.9.2-cp39-cp39-win32.whl", hash = "sha256:b124e2a6d223b65ba8768d5706d103280914d61f5cae3afbc50fc3dfcc016623"}, - {file = "yarl-1.9.2-cp39-cp39-win_amd64.whl", hash = "sha256:61016e7d582bc46a5378ffdd02cd0314fb8ba52f40f9cf4d9a5e7dbef88dee18"}, - {file = "yarl-1.9.2.tar.gz", hash = "sha256:04ab9d4b9f587c06d801c2abfe9317b77cdf996c65a90d5e84ecc45010823571"}, + {file = "yarl-1.9.9-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:133b755d23181d2cf580e50710deae62fd6cb8ecb57884d5d22cc1a80939cdd8"}, + {file = "yarl-1.9.9-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:3bbf66d0f0179762d1a2c06e80d2c114cef8432c2874b1446bdae314608e8fbf"}, + {file = "yarl-1.9.9-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:26ca7fb99d852370e270c88728e2e3edeebf67733b734af3835f87e8be700b88"}, + {file = "yarl-1.9.9-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ef6961a23410832cd4174a21e6af9581e43ee3934396875402c6c9b033aa8dc9"}, + {file = "yarl-1.9.9-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e4c1344979375c3fa4385583b2f6d633745b35c03fd9be0932fc57d367e1c6f4"}, + {file = "yarl-1.9.9-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:759fe2045c03e6bf4a0224335626348a0e474d6499778b4483d0830e6450469c"}, + {file = "yarl-1.9.9-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7c37b94f821cfaa62c78f27235bc6854cc42513209365c0aeb01348135e8d339"}, + {file = "yarl-1.9.9-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1fac0e265c7b6ad795dabb59a66b954238cc42e4698fcc23d6b8e0a8bbaf9e99"}, + {file = "yarl-1.9.9-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:5cc4a506a27e24158505767ee4a0ccb011afd0fc26fdc00b6cf1ad568b402ed8"}, + {file = "yarl-1.9.9-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:c0a5f76bbb15a03dbe23a6ba5e7a4c3129611351fed24144397db65612aa77c3"}, + {file = "yarl-1.9.9-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:fd5c078f5df104869e16e5d48b30190839f55b2cf6fee0bc5a0aa8ae9012250f"}, + {file = "yarl-1.9.9-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:7f01cc7aa0de27dd75a9e07467b5e55fcceb7e6982d10e823d1846ea5b68069c"}, + {file = "yarl-1.9.9-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:9f03ae9b83cafe414b6d36a02767e1d311e524fec7ed3afadfd1ed22d05a5cfd"}, + {file = "yarl-1.9.9-cp310-cp310-win32.whl", hash = "sha256:2843c48fc52da7536bf43480ed04de4a15381ed689417179d14c10f75c6f814e"}, + {file = "yarl-1.9.9-cp310-cp310-win_amd64.whl", hash = "sha256:ca3e332a01f9bca2ad3a7f51e4d86c97967cc92df7247ad806d88b62a52bf594"}, + {file = "yarl-1.9.9-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:a4990a054911d92be8e8370e399df6cd7d8e6f9c005a3752e35da36825cc114a"}, + {file = "yarl-1.9.9-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6e3cb4420b07a9f5d96d14b20fea67596a96ca4983bb55337f8587f83981e8ad"}, + {file = "yarl-1.9.9-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:cb9b53b33cd653fef934e6567c5d23ca5eefb1e412a6aa8be180586001609087"}, + {file = "yarl-1.9.9-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f6cf7f3eadcd6604d64eed954e7334187b97e19ccfb885d2f511093757dc5623"}, + {file = "yarl-1.9.9-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1d1982613016380b32e54ddec0ab937cdfc799d3f6c1c06c37144033219277ef"}, + {file = "yarl-1.9.9-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5f7e260c6e025a0c74f1ad77b1840d1c0ee784b9e8dfbeb72c696f333eab565a"}, + {file = "yarl-1.9.9-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:03ef72a7ac3833c8b17ba007b61eb569082c2c29ce84d18ddf4b360b76ca6412"}, + {file = "yarl-1.9.9-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3e6dbc044f5d98160bf9adb89b88cfe8bca410d1a7c40033e2e7a82b66a71276"}, + {file = "yarl-1.9.9-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:9f806c990da324686d2ea037f61079692f099876362654b88facf56022b41452"}, + {file = "yarl-1.9.9-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:5991b36f2028190c8c3f1a4e8e9890ee371ec61662facd16d935cd9c1bf96040"}, + {file = "yarl-1.9.9-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:e12e4972c710c591271d092e6565e6fb668dd957eedec244001ef5d3e6ac394d"}, + {file = "yarl-1.9.9-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:28ba2f36cace7e89c70a330bd0e40618e58fd72c71183221b50e7a58ea95d50a"}, + {file = "yarl-1.9.9-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:47d31e691ec9a909538b4ebbae8b1170ccccee68cc223803b0322c6807ebb169"}, + {file = "yarl-1.9.9-cp311-cp311-win32.whl", hash = "sha256:943001da123754a510b8118a46d57c73fe00ac63099ba0cd63ff580002704dd8"}, + {file = "yarl-1.9.9-cp311-cp311-win_amd64.whl", hash = "sha256:ec7ff70bff03dfb1a9abdf47c050d57c2fc13e6218d67ea09fa15abfb87ba26f"}, + {file = "yarl-1.9.9-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:af4d94a2c2ee22f72bb936e210cedfa05096cb54ded3d1123efb90e2e2290f4e"}, + {file = "yarl-1.9.9-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:d03619326737a50e495cd60e04bc43110e4a34f55f65e3953813dc078c6fe561"}, + {file = "yarl-1.9.9-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5ce6d710df44165fa78c56ee2665b927e6f9d11f3e7dd79befb1c41579890ef8"}, + {file = "yarl-1.9.9-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5ed54f985bf3fd9dd282dcdd1ab4026e6b9bd4cbbcdd95cef5aa7f588bbf558b"}, + {file = "yarl-1.9.9-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bd82d4553f67b22d149fe1f20185c6a2a8927d9727d0cac47e317f1190c5d96b"}, + {file = "yarl-1.9.9-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d9654036bb0c1b65aecbb352f556d29662ae91753acfeac5d63e3ac034bfd084"}, + {file = "yarl-1.9.9-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:161e19878551954b44852d4ba437ef9d74445e72a9fd5aef44897d0d8d3b316d"}, + {file = "yarl-1.9.9-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7387809ddc87819c6e8c5168f1fe1249684e62aea1f253e34282348e3b52af9c"}, + {file = "yarl-1.9.9-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:98ce91e549e23aa548c497e2c49af6a6534d35eab5029e262b6658191c3e5ec2"}, + {file = "yarl-1.9.9-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:70f1048e64993142a4d6e7546b0930f399f9c4ccc381b6622b1cb2eba06a848b"}, + {file = "yarl-1.9.9-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:d61b203da3141c6e3504e361588c7921ccb5f2ee2978db1e1b627411a629b339"}, + {file = "yarl-1.9.9-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:573981f4b16ccfef83847b1409588c1d7533767321452c310d9b12289965c062"}, + {file = "yarl-1.9.9-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:995c7d7b9c802a27c5c0e24bb2c5e4811c6d14b21644b8f02ffc613d7b7b8297"}, + {file = "yarl-1.9.9-cp312-cp312-win32.whl", hash = "sha256:249e1abdb978eb29b40c5956c4c4e9fd5bf6f594cee7b937122462722fdfd661"}, + {file = "yarl-1.9.9-cp312-cp312-win_amd64.whl", hash = "sha256:99139694b62e499e547540462efc66d62355620ef23e3f1b003f3473c6726f72"}, + {file = "yarl-1.9.9-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:dea263b77d6a7ec70a24cd684cf92337359ab2fd83ce99b9911935162573a5b6"}, + {file = "yarl-1.9.9-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:3ae01f51e3ff817b2f18eea194f3e57dd2d70fbaccea41f72bbe66769584aefe"}, + {file = "yarl-1.9.9-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:b727ab129e6d516c4743f28cbca0ebf7445ec4164a903370b59bc37fd0e2b87c"}, + {file = "yarl-1.9.9-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4b6dfd1f25a5ef1e6d074be97a87f3b0e3b6e2ecd18b7d8ae658e0008b44b6f5"}, + {file = "yarl-1.9.9-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9d84d43d03a0714f4d7eff664eed4a353549c1b393fcc1316f553092a761bd90"}, + {file = "yarl-1.9.9-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:392c8e83d5028697c14762bce46d544dc01cbcf20ded20872045aae3a195c636"}, + {file = "yarl-1.9.9-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:827ab00f66fbdafd2a6f9a45ec3c4a8fe9ce54d60b327aa68aef7af5f3edf35e"}, + {file = "yarl-1.9.9-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ac9f79aac6d7044b90bf9f01bb133be96f21cef5369cdf68456b49adb00a838e"}, + {file = "yarl-1.9.9-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:3fe175c07ba7a5afcc26d484541440649c3b72d688b6c07b03f0bcacbd2cf3b5"}, + {file = "yarl-1.9.9-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:d7eb3fd1854f87555fc4f44c59c375b4775e088ddc50870c02f633ff03105be9"}, + {file = "yarl-1.9.9-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:1384e4dcb659abc5adbb2f9d0fe9aa6a059fdfa5b87f46106ad54be98a272530"}, + {file = "yarl-1.9.9-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:fbc505f9ad1c2d60b1ced4fb8f75ff95afbfa671b276a1f1ca0a56d3d06cf32e"}, + {file = "yarl-1.9.9-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:604c18c279f3b1959ff94bcda60ab52eb4ec825df5e1388f589930ba61506420"}, + {file = "yarl-1.9.9-cp313-cp313-win32.whl", hash = "sha256:0ad6085a23808109318c2fde9538bce88850a44c42e7e1ca421ec2c3e5d15ffa"}, + {file = "yarl-1.9.9-cp313-cp313-win_amd64.whl", hash = "sha256:e476b86f9eff02f09193fd2deda16089725d3aeba609158000e0d2b8d5fec3be"}, + {file = "yarl-1.9.9-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:aefb612d7543fb9857134fc43b4cfda4a923bfcca9b06d1c6e74606f184f2a4c"}, + {file = "yarl-1.9.9-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:bf840a2b20d2215bd5de6af24f41c9532731db0e9a4a311105e066815a6fddd2"}, + {file = "yarl-1.9.9-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:0295083cd8cd2084c9be79f71be3bd957794aeca0beae2c73207d3d588a0cc16"}, + {file = "yarl-1.9.9-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3d00068b634194e754c6782478d3f882db66be5ecb6a75141c49f1515d317f94"}, + {file = "yarl-1.9.9-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ad1d40f2fff7214ba352f915a10c3bfc07f4b69693be35e3a00271160a487d1b"}, + {file = "yarl-1.9.9-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b8ad1ba32966ccec8781f22ef612d4a8e807e8e9c140a792e7d224a41ee30813"}, + {file = "yarl-1.9.9-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9686f8a0185a20e67d8d80df558d479d1fe93a79807f6275a7a9b3c33c4ae38e"}, + {file = "yarl-1.9.9-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:835a0a3c8f883501e93a60144ba8e228c420ef5afc196d73583699ee475e0cfa"}, + {file = "yarl-1.9.9-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:305386e05778c71ff67226788dd1d174c4f5b4b8f0886508d743eec56d2b7980"}, + {file = "yarl-1.9.9-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:76814a708dedddd09cfb2ea3aa750b10cc2dcd67ef342d6125ff145241e29e52"}, + {file = "yarl-1.9.9-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:cafcdb8580e570091086af9c8166fd8bafcc0f8eb88df0c86ee40f74e8b47b9a"}, + {file = "yarl-1.9.9-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:5ccbc555cc577ebe4520d3c803ebc6ffd7cba29e306e05c3f6768d1bd14a59ba"}, + {file = "yarl-1.9.9-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:19c4ca114cf6b4ff261e43cae7358a57673e1c6aceceeee488b922ee9d8c66e8"}, + {file = "yarl-1.9.9-cp38-cp38-win32.whl", hash = "sha256:7815dec325ce59320e2331dec2506859e8148de880c2350bab4955567d6fe569"}, + {file = "yarl-1.9.9-cp38-cp38-win_amd64.whl", hash = "sha256:93a33f4d0bfb4d64ae462af5962d5f6442f0bf973a8b7af77cfb89db59a59abe"}, + {file = "yarl-1.9.9-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:ea9bd8bb9ad6e340e052b6f5af9ce3d6e50416e304b0a4b6ed8378b304acf401"}, + {file = "yarl-1.9.9-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:2010da427b6dc6383e953ecc6c5002e51ce3a8f33ba8cd26f9ebc0541c1323be"}, + {file = "yarl-1.9.9-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:41b1645a5695b6802c545b6696a736738f6935167bc7fe8a886a4aeb4bc57004"}, + {file = "yarl-1.9.9-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0bc7076693614e2ece788a64c2fad3e5f874ace2ac4f871bcc35709fe552ec1"}, + {file = "yarl-1.9.9-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:785450c11aceda6a3b5be8022dccf17dfb03b20b4ee5489b1d0ddbac862ab404"}, + {file = "yarl-1.9.9-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e319c258048e1d1e68f2e5054f4c5043f59605f2b9bbb36452be879dfe4bf3ae"}, + {file = "yarl-1.9.9-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a9ae5ca05a0201bc3db217042664f349b3e81db45e774f10924d09b60cfea3de"}, + {file = "yarl-1.9.9-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8766bbda365a5e33d395ceaa7e94b82ccf844f401309f7106c13c20248bb7f42"}, + {file = "yarl-1.9.9-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:01feeab5fece9eceffab2796da37b51d0832e80258cccb32a5be4a05385278df"}, + {file = "yarl-1.9.9-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:24178f95ccd0bb6c740b90d980c4a48535a2fd4912c2dda93e252b8b2d9f7877"}, + {file = "yarl-1.9.9-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:f398b3f1cb58ab1fb96af1e767fb85f0a56d50e455496175bf008276fba273d2"}, + {file = "yarl-1.9.9-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:018dd5f6a8371dd4abf553bd996e673f5173d9f8a71566897edeaf279346f55e"}, + {file = "yarl-1.9.9-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:5cf8b89b2a29a4fe98469f98c8c597bb1a308f1c9392fce0930cfc282b8142b9"}, + {file = "yarl-1.9.9-cp39-cp39-win32.whl", hash = "sha256:98efdcdbaf954ae8e084be1345ffd038a27c8f7c842fb7642b58d160752b4823"}, + {file = "yarl-1.9.9-cp39-cp39-win_amd64.whl", hash = "sha256:6f83424adbf4c5bda78f7963f01253b756c2b2d6a0949ca838a838840dea2437"}, + {file = "yarl-1.9.9-py3-none-any.whl", hash = "sha256:4384fc34c0b1f6d71ddac126652285d4aaf8c6172eb3734c7e1bdc634635b7d9"}, + {file = "yarl-1.9.9.tar.gz", hash = "sha256:d58a26cbc785a0fb6ad2e733422631c7f45c364a40dbd0cabb9f0dfcdbb4940b"}, ] [package.dependencies] @@ -1811,22 +1972,36 @@ multidict = ">=4.0" [[package]] name = "yt-dlp" -version = "2021.12.27" -description = "A youtube-dl fork with additional features and patches" -category = "main" +version = "2024.8.6" +description = "A feature-rich command-line audio/video downloader" optional = false -python-versions = ">=3.6" +python-versions = ">=3.8" files = [ - {file = "yt-dlp-2021.12.27.tar.gz", hash = "sha256:2244df3759751487e796b23b67216bee98e70832a3a43c2526b0b0e0bbfbcb5b"}, - {file = "yt_dlp-2021.12.27-py2.py3-none-any.whl", hash = "sha256:bb46898a175d149c9c6bb2846056590d297aa4eafad8487c3e1315d2c6090896"}, + {file = "yt_dlp-2024.8.6-py3-none-any.whl", hash = "sha256:ab507ff600bd9269ad4d654e309646976778f0e243eaa2f6c3c3214278bb2922"}, + {file = "yt_dlp-2024.8.6.tar.gz", hash = "sha256:e8551f26bc8bf67b99c12373cc87ed2073436c3437e53290878d0f4b4bb1f663"}, ] [package.dependencies] +brotli = {version = "*", markers = "implementation_name == \"cpython\""} +brotlicffi = {version = "*", markers = "implementation_name != \"cpython\""} +certifi = "*" mutagen = "*" pycryptodomex = "*" -websockets = "*" +requests = ">=2.32.2,<3" +urllib3 = ">=1.26.17,<3" +websockets = ">=12.0" + +[package.extras] +build = ["build", "hatchling", "pip", "setuptools (>=71.0.2)", "wheel"] +curl-cffi = ["curl-cffi (==0.5.10)", "curl-cffi (>=0.5.10,<0.6.dev0 || ==0.7.*)"] +dev = ["autopep8 (>=2.0,<3.0)", "pre-commit", "pytest (>=8.1,<9.0)", "ruff (>=0.5.0,<0.6.0)"] +py2exe = ["py2exe (>=0.12)"] +pyinstaller = ["pyinstaller (>=6.7.0)"] +secretstorage = ["cffi", "secretstorage"] +static-analysis = ["autopep8 (>=2.0,<3.0)", "ruff (>=0.5.0,<0.6.0)"] +test = ["pytest (>=8.1,<9.0)"] [metadata] lock-version = "2.0" python-versions = ">=3.10.0,<3.12" -content-hash = "a42a099e7fbbc4b83adac406f383e2da31e37caf650ce271d1fa4c7456b9dcb1" +content-hash = "c6ece7aa719f09e1f5e0d8d715298670b5df29cc8dbce5b64ee6da2343e6f3c8" diff --git a/pyproject.toml b/pyproject.toml index 1a5944121..a1dec3c78 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -15,20 +15,20 @@ canary = "canary.main:main" [tool.poetry.dependencies] python = ">=3.10.0,<3.12" -beautifulsoup4 = "^4.12.2" -sympy = "^1.9" -requests = ">=2.30.0,<3" +beautifulsoup4 = "^4.12.3" +sympy = "^1.13.2" +requests = ">=2.32.3,<3" tabulate = "~0.8.9" "discord.py" = {version = "~1.7.3", extras = ["voice"]} -opencv-python = "==4.6.0.66" -pytz = ">=2020.5" -numpy = "^1.21.1" -aiohttp = "~3.7.4" -urllib3 = ">=1.25.3" +opencv-python = "==4.10.0.84" +pytz = ">=2024.1" +numpy = "^1.26.4" +aiohttp = "~3.7.4.post0" +urllib3 = "~2.0.7" feedparser = "^6.0.8" regex = "^2023.5.5" googletrans = "==4.0.0rc1" -yt-dlp = "^2021.12.27" +yt-dlp = "^2024.4.9" Pillow = "^9.5.0" uvloop = {version="~0.17.0", markers = "sys_platform == 'linux' or sys_platform == 'darwin'"} bidict = "^0.22.0" @@ -39,12 +39,12 @@ pydantic = "^1.10.2" [tool.poetry.dev-dependencies] pytest = "^7.3.1" -black = "^23.3.0" -mypy = "~1.3.0" -types-beautifulsoup4 = "^4.11.5" -types-regex = "^2022.8.17.0" -types-requests = "^2.28.9" -types-pytz = "^2022.2.1.0" +black = "^24.8.0" +mypy = "~1.11.2" +types-beautifulsoup4 = "^4.12.0.20240511" +types-regex = "^2024.7.24.20240726" +types-requests = "^2.32.0.20240712" +types-pytz = "^2024.1.0.20240417" types-tabulate = "^0.8.11" [tool.black] From 4efd41cedb9575cd30303fa8ab797655f33474a3 Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Wed, 4 Sep 2024 19:43:53 -0400 Subject: [PATCH 116/127] dockerfile work --- Dockerfile | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/Dockerfile b/Dockerfile index bc0ad3b2e..a6b543270 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM python:3.11-slim-bullseye +FROM python:3.11-slim-bookworm # Install base apt dependencies RUN apt-get update && apt-get install -y git sqlite3 @@ -13,16 +13,25 @@ RUN apt-get install -y \ ffmpeg \ gcc -# Install requirements with pip to use Docker cache independent of project metadata -COPY requirements.txt / -RUN pip install -r /requirements.txt +# Update pip, install poetry +RUN pip install --no-cache-dir -U pip; \ + pip install --no-cache-dir poetry==1.8.3 -# Copy code to the `canary` directory in the image and run the bot from there -COPY . /canary -WORKDIR /canary +COPY pyproject.toml . +COPY poetry.lock . +RUN poetry config virtualenvs.create false && \ + poetry --no-cache install --no-root --without dev + +# Copy code and pre-made data to the /app directory, where the bot will be run from +WORKDIR /app +COPY canary canary +COPY data data + +RUN pip install -e . # Notes: -# Users will have to mount their config.ini in by hand -# Users should mount a read/writable volume for /canary/data/runtime +# Users will have to configure their instance using environment variables, described by the Pydantic settings object +# in /app/canary/config/config.py +# Users should mount a read/writable volume for /app/data/runtime -CMD ["python3.11", "-m", "canary.main"] +CMD ["canary"] From 4c15035cfddfc543c9913e36b2645e3a43c76f1f Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Wed, 4 Sep 2024 19:55:39 -0400 Subject: [PATCH 117/127] some paginator type hinting --- canary/cogs/utils/paginator.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/canary/cogs/utils/paginator.py b/canary/cogs/utils/paginator.py index 7ae09690c..46dc42e44 100644 --- a/canary/cogs/utils/paginator.py +++ b/canary/cogs/utils/paginator.py @@ -24,15 +24,15 @@ class Pages: def __init__( self, ctx, - current_page=1, - msg=None, + current_page: int = 1, + msg: discord.Message | None = None, item_list=[], - title="Paginator", + title: str = "Paginator", display_option=(1, 0), - editable_content=True, - editable_content_emoji="🚮", - return_user_on_edit=False, - timeout=300, + editable_content: bool = True, + editable_content_emoji: str = "🚮", + return_user_on_edit: bool = False, + timeout: int = 300, ): """Creates a paginator. @@ -96,7 +96,7 @@ def __init__( self.guild = ctx.guild self.channel = ctx.channel self.user = ctx.author - self.message = msg + self.message: discord.Message | None = msg self.itemList = item_list self.title = title self.displayOption = display_option @@ -111,7 +111,7 @@ def __init__( if editable_content: self.actions.append((editable_content_emoji, self._edit)) self.currentPage = current_page - self.edit_mode = False + self.edit_mode: bool = False self.return_user_on_edit = return_user_on_edit self.timeout = timeout @@ -211,7 +211,7 @@ def _organize_embeds_list_embeds(self, pages_to_send): async def _show_page(self, page): self.currentPage = max(0, min(page, self.lastPage)) - if self.message: + if self.message is not None: if self.currentPage == 0: try: await self.message.delete() From 768188220ee3762a2b15dccdfbc47acba8f732b5 Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Wed, 4 Sep 2024 19:55:47 -0400 Subject: [PATCH 118/127] fix add_quote full name --- canary/cogs/quotes.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/canary/cogs/quotes.py b/canary/cogs/quotes.py index a1678e8fc..53ac526e5 100644 --- a/canary/cogs/quotes.py +++ b/canary/cogs/quotes.py @@ -97,7 +97,7 @@ async def rebuild_mc(self): self.mc_table = lookup @commands.command(aliases=["addq"]) - async def add_quotes( + async def add_quote( self, ctx: commands.Context, member: discord.Member | None = None, *, quote: str | None = None ): """ From a1a59e0606cc6a00388d0ab7b8d56564ac4efc6c Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Wed, 4 Sep 2024 20:02:28 -0400 Subject: [PATCH 119/127] fix some member converters in currency/quotes --- canary/cogs/currency.py | 3 ++- canary/cogs/quotes.py | 7 +++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/canary/cogs/currency.py b/canary/cogs/currency.py index e89fe8a63..d964b176a 100644 --- a/canary/cogs/currency.py +++ b/canary/cogs/currency.py @@ -25,6 +25,7 @@ from decimal import Decimal, InvalidOperation from discord.ext import commands from tabulate import tabulate +from typing import Optional from ..bot import Canary from ..config.config import CurrencyModel @@ -227,7 +228,7 @@ async def claim(self, ctx: commands.Context): await ctx.send(f"Please wait {time_left.seconds // 3600}h {time_left.seconds // 60 % 60}m to claim again!") @commands.command(aliases=["$", "bal"]) - async def balance(self, ctx: commands.Context, user: discord.Member | None = None): + async def balance(self, ctx: commands.Context, user: Optional[discord.Member] = None): """ Return the user's account balance. """ diff --git a/canary/cogs/quotes.py b/canary/cogs/quotes.py index 53ac526e5..4119c8287 100644 --- a/canary/cogs/quotes.py +++ b/canary/cogs/quotes.py @@ -23,6 +23,7 @@ import re from discord.ext import commands +from typing import Optional from ..bot import Canary from .base_cog import CanaryCog @@ -98,12 +99,14 @@ async def rebuild_mc(self): @commands.command(aliases=["addq"]) async def add_quote( - self, ctx: commands.Context, member: discord.Member | None = None, *, quote: str | None = None + self, ctx: commands.Context, member: Optional[discord.Member] = None, *, quote: Optional[str] ): """ Add a quote to a user's quote database. """ + replying: bool = ctx.message.reference and ctx.message.reference.resolved + if quote is None: if not replying: return @@ -239,7 +242,7 @@ def check(reaction, user): await ctx.send(embed=embed) @commands.command(aliases=["lq"]) - async def list_quotes(self, ctx: commands.Context, author: discord.Member = None): + async def list_quotes(self, ctx: commands.Context, author: Optional[discord.Member] = None): """ List quotes """ From a07addda6843c20a7e9990b0f81b9bf864ed80b3 Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Wed, 4 Sep 2024 20:02:59 -0400 Subject: [PATCH 120/127] custom reactions elifs --- canary/cogs/customreactions.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/canary/cogs/customreactions.py b/canary/cogs/customreactions.py index 7d18ebfad..754c602d2 100644 --- a/canary/cogs/customreactions.py +++ b/canary/cogs/customreactions.py @@ -693,7 +693,7 @@ async def _edit_reaction_and_rebuild(react_id, key, value): await asyncio.sleep(5) # Edit the response - if reaction.emoji == EMOJI["two"]: + elif reaction.emoji == EMOJI["two"]: await message.edit( embed=discord.Embed( title=f"Modify a {noun_custom}", description="Please enter the new response" @@ -722,7 +722,7 @@ async def _edit_reaction_and_rebuild(react_id, key, value): await asyncio.sleep(5) # Edit the "delete" option - if reaction.emoji == EMOJI["three"]: + elif reaction.emoji == EMOJI["three"]: await message.edit(embed=LOADING_EMBED) description = ( f"Should the message that calls the reaction be deleted?\n" @@ -780,7 +780,7 @@ async def _edit_reaction_and_rebuild(react_id, key, value): await asyncio.sleep(5) # Edit the "anywhere" option - if reaction.emoji == EMOJI["four"]: + elif reaction.emoji == EMOJI["four"]: await message.edit(embed=LOADING_EMBED) title = f"Modify a {noun_custom}. React with the option you want" footer = f"{user} is currently modifying a {noun_custom}. \n" @@ -835,7 +835,7 @@ async def _edit_reaction_and_rebuild(react_id, key, value): await asyncio.sleep(5) # Edit "dm" option - if reaction.emoji == EMOJI["five"]: + elif reaction.emoji == EMOJI["five"]: await message.edit(embed=LOADING_EMBED) title = f"Modify a {noun_custom}. React with the option you want" footer = f"{user} is currently modifying a {noun_custom}. \n" @@ -893,7 +893,7 @@ async def _edit_reaction_and_rebuild(react_id, key, value): await asyncio.sleep(5) # Approve a custom reaction proposal - if reaction.emoji == EMOJI["white_check_mark"]: + elif reaction.emoji == EMOJI["white_check_mark"]: await _edit_reaction_and_rebuild(custom_react_id, "Proposal", 0) await message.edit( @@ -908,7 +908,7 @@ async def _edit_reaction_and_rebuild(react_id, key, value): await asyncio.sleep(5) # Delete a custom reaction or proposal - if reaction.emoji == EMOJI["put_litter_in_its_place"] or reaction.emoji == EMOJI["x"]: + elif reaction.emoji == EMOJI["put_litter_in_its_place"] or reaction.emoji == EMOJI["x"]: async with self.db() as db: await db.execute("DELETE FROM CustomReactions WHERE CustomReactionID = ?", (custom_react_id,)) await db.commit() @@ -919,7 +919,7 @@ async def _edit_reaction_and_rebuild(react_id, key, value): await asyncio.sleep(5) # Stop - if reaction.emoji == EMOJI["stop_button"]: + elif reaction.emoji == EMOJI["stop_button"]: return await leave(message) return False From 63bca210d82f0e0a126428ee26c47c6c279ff31d Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Wed, 4 Sep 2024 20:05:10 -0400 Subject: [PATCH 121/127] lint: run black --- canary/cogs/banner.py | 8 +++++--- canary/cogs/quotes.py | 6 ++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/canary/cogs/banner.py b/canary/cogs/banner.py index 7e37cf288..3d5d2098c 100644 --- a/canary/cogs/banner.py +++ b/canary/cogs/banner.py @@ -475,9 +475,11 @@ async def submit_banner(self, ctx: commands.Context, *args): return try: - with Image.open(Banner.CONVERTER_FILE) as overlay_mask, Image.open( - Banner.PREVIEW_FILE - ) as preview_mask, Image.open(user_image_file) as user_image: + with ( + Image.open(Banner.CONVERTER_FILE) as overlay_mask, + Image.open(Banner.PREVIEW_FILE) as preview_mask, + Image.open(user_image_file) as user_image, + ): animated = user_image.is_animated overlay_mask_user_canvas_size = overlay_mask.size diff --git a/canary/cogs/quotes.py b/canary/cogs/quotes.py index 4119c8287..a459c5551 100644 --- a/canary/cogs/quotes.py +++ b/canary/cogs/quotes.py @@ -98,13 +98,11 @@ async def rebuild_mc(self): self.mc_table = lookup @commands.command(aliases=["addq"]) - async def add_quote( - self, ctx: commands.Context, member: Optional[discord.Member] = None, *, quote: Optional[str] - ): + async def add_quote(self, ctx: commands.Context, member: Optional[discord.Member] = None, *, quote: Optional[str]): """ Add a quote to a user's quote database. """ - + replying: bool = ctx.message.reference and ctx.message.reference.resolved if quote is None: From 7c3382217a1e9a3c183416b9690a32fa645597d8 Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Wed, 4 Sep 2024 20:10:32 -0400 Subject: [PATCH 122/127] remove old config.ini --- .dockerignore | 2 + MANIFEST.in | 1 - canary/config/config.ini | 128 --------------------------------------- 3 files changed, 2 insertions(+), 129 deletions(-) delete mode 100644 canary/config/config.ini diff --git a/.dockerignore b/.dockerignore index 4c513943f..57592148e 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,4 +1,6 @@ canary/config/config.ini +data/runtime/*.db +data/runtime/*.obj env/ tests/ venv/ diff --git a/MANIFEST.in b/MANIFEST.in index fb991c226..bae6f261e 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,2 +1 @@ -include canary/config/config.ini include canary/Martlet.schema diff --git a/canary/config/config.ini b/canary/config/config.ini deleted file mode 100644 index 934a93ac2..000000000 --- a/canary/config/config.ini +++ /dev/null @@ -1,128 +0,0 @@ -# Copyright (C) idoneam (2016-2022) -# -# This file is part of Canary -# -# Canary is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Canary is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Canary. If not, see . - -[Discord] -Key = KEY - -[Server] -ServerID = 236668784948019202 -CommandPrefix = ? -BotName = Marty - -[Emoji] -UpvoteEmoji = upmartlet -DownvoteEmoji = downmartlet -BannerVoteEmoji = redchiken - -[Roles] -ModeratorRole = Discord Moderator -DeveloperRole = idoneam -McGillianRole = McGillian -HonoraryMcGillianRole = Honorary McGillian -BannerRemindersRole = Banner Submissions -BannerWinnerRole = Banner of the Week Winner -TrashTierBannerRole = Trash Tier Banner Submissions -NoFoodSpottingRole = Trash Tier Foodspotting -MutedRole = Muted -CrabboRole = Secret Crabbo - -[Channels] -ReceptionChannel = martys_dm -BannerOfTheWeekChannel = banner_of_the_week -BannerSubmissionsChannel = banner_submissions -BannerConvertedChannel = converted_banner_submissions -FoodSpottingChannel = foodspotting -MetroStatusChannel = stm_alerts -BotsChannel = bots -VerificationChannel = verification_log -AppealsLogChannel = appeals_log -AppealsCategory = appeals - -[Meta] -Repository = https://github.com/idoneam/Canary.git - -[Logging] -LogLevel = info -LogFile = ./canary.log -DevLogWebhookID = -DevLogWebhookToken = -ModLogWebhookID = -ModLogWebhookToken = - -[DB] -Path = ./data/runtime/Martlet.db - -[Greetings] -Welcome = -Goodbye = - -[Helpers] -CourseTemplate = http://www.mcgill.ca/study/2020-2021/courses/{} -CourseSearchTemplate = http://www.mcgill.ca/study/2020-2021/courses/search?search_api_views_fulltext={}&sort_by=field_subject_code&page={} -GCWeatherURL = http://weather.gc.ca/city/pages/qc-147_metric_e.html -GCWeatherAlertURL = https://weather.gc.ca/warnings/report_e.html?qc67 -WttrINTemplate = http://wttr.in/Montreal_2mpq_lang=en.png?_m -TepidURL = https://tepid.science.mcgill.ca:8443/tepid/screensaver/queues/status - -[Subscribers] -FoodRecallChannel = food -FoodRecallLocationFilter = Quebec|National - -[Currency] -Name = cheeps -Symbol = ʧ -Precision = 2 -Initial = 1000 -SalaryBase = 200 -Inflation = 0.005 - -[IncomeTax] -Brackets = 100, 300, 1000, Infinity -Amounts = 0, 0.15, 0.30, 0.50 - -[AssetTax] -Brackets = 5000, 10000, Infinity -Amounts = 0, 0.20, 0.50 - -[OtherTax] -TransactionTax = 0.15 - -[Betting] -RollCases = 66, 90, 99, 100 -RollReturns = 0, 2, 4, 10 - -[Music] -BanRole = tone deaf -StartVol = 100 - -[Images] -MaxImageSize = 8000000 -ImageHistoryLimit = 50 -MaxRadius = 500 -MaxIterations = 20 - -[Games] -HangmanNormalWin = 10 -HangmanCoolWin = 20 -HangmanTimeOut = 600 - -[AssignableRoles] -Pronouns = She/Her, He/Him, They/Them -Fields = Accounting, Agriculture, Anatomy and Cell Biology, Anthropology, Architecture, Biochemistry, Bioengineering, Biology, Bioresource Engineering, Chemical Engineering, Chemistry, Civil Engineering, Classics, cogito, Commerce, Computer Engineering, Computer Science, Computer Science/Biology, Cultural Studies, Desautels, Economics, Electrical Engineering, English, Experimental Medicine, Finance, Geography, History, Human Genetics, Indigenous Studies, International Development Studies, Jewish Studies, linguini, mac kid, Materials Engineering, Math, MBA, Mechanical Engineering, Medicine, Microbiology and Immunology, Neuroscience, Nursing, Pharmacology, Philosophy, Physical Therapy, Physics, Physiology, Political Science, Psychiatry, Psychology, Public Health, Social Work, Sociology, Software Engineering, Statistics, Theology, Urban Systems -Faculties = Science, Engineering, Management, art you glad you're not in arts, ArtSci, Agriculture and Environment, Continuing Studies, Law, Education, Dentistry, Music -Years = U0, U1, U2, U3, U4, grad student, workhere, wenthere -Generics = weeb, weeb stomper, crosswords, stm_alertee, Stardew, R6, CS:GO, Minecraft, Among Us, Pokemon Go, Secret Crabbo, Warzone, Monster Hunter, undersad From 9d62e54978a5ff39a53bcf7bce8cc768d28f47ea Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Wed, 4 Sep 2024 20:10:52 -0400 Subject: [PATCH 123/127] docs: update config / deployment details --- README.md | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 050b478f4..a7e62c9f5 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ to users, as well as fun functions, a quote database and custom greeting message git clone https://github.com/idoneam/Canary ``` -2. Dependencies are managed with `poetry` (1.4+), which can be installed via `pip` with: +2. Dependencies are managed with `poetry` (1.8.3+), which can be installed via `pip` with: ```bash python3 -m pip install poetry @@ -42,7 +42,7 @@ to users, as well as fun functions, a quote database and custom greeting message poetry install ``` -6. You may enter the virtual environment generated by the pipenv installation with: `poetry shell` or simply run the +6. You may enter the virtual environment generated by the Poetry installation with: `poetry shell` or simply run the bot with `poetry run canary` 7. In order to run bots on Discord, you need to @@ -196,8 +196,12 @@ docker build -t canary:latest . #### Running the Container -You will need to download and modify Canary's [config.ini](config/config.ini) to your -liking, so it can be mounted inside the container. +You will need to set environment variables according to the values configured in the Pydantic +configuration object described in [config.py](canary/config/config.py). These environment variables +correspond to the properties of the object, uppercased, underscore-spaced, and prefixed with `CANARY_.` + +A bare minimum set of environment variables to set can be found in [example.env](./example.env). +These variables must be set inside the container in order for the bot to function. From within the root of the repository: @@ -207,8 +211,8 @@ mkdir -f runtime-data # Run the container docker run -d \ - -v $(pwd)/config.ini:/canary/canary/config/config.ini:ro \ - -v $(pwd)/runtime-data:/canary/data/runtime \ + --env-file my.env \ + -v $(pwd)/runtime-data:/app/data/runtime \ canary:latest ``` @@ -221,13 +225,13 @@ the standards defined in [`pyproject.toml`](https://black.readthedocs.io/en/stab your code using: ``` -poetry run black . -t py310 --fast +poetry run black . -t py310 ``` and ensure your code conforms to our linting with : ``` -poetry run black --diff . -t py310 --fast +poetry run black --diff . -t py310 ``` ## Contributions From bb156fc193953df95ffc2fea366b471f1d9fee77 Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Sat, 7 Sep 2024 14:49:53 -0400 Subject: [PATCH 124/127] ci: update actions --- .github/workflows/formatting_check.yml | 4 ++-- .github/workflows/poetry-dev.yml | 7 +++---- .github/workflows/poetry-prod.yml | 3 +-- .github/workflows/publish-docker.yml | 16 ++++++++-------- 4 files changed, 14 insertions(+), 16 deletions(-) diff --git a/.github/workflows/formatting_check.yml b/.github/workflows/formatting_check.yml index 36cfe528d..f28865409 100644 --- a/.github/workflows/formatting_check.yml +++ b/.github/workflows/formatting_check.yml @@ -9,8 +9,8 @@ jobs: lint: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 - - uses: actions/setup-python@v4 + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 - uses: psf/black@stable with: options: "--diff --check -t py311 canary" diff --git a/.github/workflows/poetry-dev.yml b/.github/workflows/poetry-dev.yml index 53a4e0876..3dbb01e3f 100644 --- a/.github/workflows/poetry-dev.yml +++ b/.github/workflows/poetry-dev.yml @@ -24,9 +24,9 @@ jobs: strategy: matrix: os: - - 'ubuntu-20.04' - - 'macos-11.0' - - 'windows-2019' + - 'ubuntu-24.04' + - 'macos-14.0' + - 'windows-2022' python-version: - '3.11' steps: @@ -48,4 +48,3 @@ jobs: - name: install canary development dependencies run: poetry install --no-interaction - diff --git a/.github/workflows/poetry-prod.yml b/.github/workflows/poetry-prod.yml index d2d00a57e..b0adcfe97 100644 --- a/.github/workflows/poetry-prod.yml +++ b/.github/workflows/poetry-prod.yml @@ -17,7 +17,7 @@ jobs: strategy: matrix: os: - - 'ubuntu-20.04' + - 'ubuntu-24.04' python-version: - '3.11' steps: @@ -39,4 +39,3 @@ jobs: - name: install canary production dependencies run: poetry install --no-dev --no-interaction - diff --git a/.github/workflows/publish-docker.yml b/.github/workflows/publish-docker.yml index 85809de3d..f42252d2b 100644 --- a/.github/workflows/publish-docker.yml +++ b/.github/workflows/publish-docker.yml @@ -11,12 +11,12 @@ jobs: packages: write contents: read steps: - - uses: actions/checkout@v3 - - uses: actions/setup-python@v4 + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 with: python-version: '3.11' - run: pip install poetry && poetry update && poetry export -f requirements.txt > requirements.txt - - uses: docker/metadata-action@v3 + - uses: docker/metadata-action@v5 id: meta with: images: ghcr.io/idoneam/Canary @@ -24,13 +24,13 @@ jobs: type=semver,pattern={{major}} type=semver,pattern={{major}}.{{minor}} type=semver,pattern={{version}} - - uses: docker/setup-buildx-action@v1 - - uses: docker/login-action@v1 + - uses: docker/setup-buildx-action@v3 + - uses: docker/login-action@v3 with: registry: ghcr.io - username: ${{ github.repository_owner }} - password: ${{ github.token }} - - uses: docker/build-push-action@v2 + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + - uses: docker/build-push-action@v6 with: context: . push: true From a222928f9d1bea1688ee2027671266320ce10ad8 Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Sat, 7 Sep 2024 14:55:07 -0400 Subject: [PATCH 125/127] chore: clear apt lists + combine apt RUN statements --- Dockerfile | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/Dockerfile b/Dockerfile index a6b543270..43e110ff2 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,17 +1,18 @@ FROM python:3.11-slim-bookworm -# Install base apt dependencies -RUN apt-get update && apt-get install -y git sqlite3 - -# Install auxiliary dependencies (for GL, Tex, etc.) -RUN apt-get install -y \ - libgl1-mesa-glx \ - texlive-latex-extra \ - texlive-fonts-extra \ - texlive-lang-greek \ - dvipng \ - ffmpeg \ - gcc +# Install base apt dependencies + auxiliary dependencies (for GL, Tex, etc.) +RUN apt-get update && \ + apt-get install -y \ + git \ + sqlite3 \ + libgl1-mesa-glx \ + texlive-latex-extra \ + texlive-fonts-extra \ + texlive-lang-greek \ + dvipng \ + ffmpeg \ + gcc && \ + rm -rf /var/lib/apt/lists/* # Update pip, install poetry RUN pip install --no-cache-dir -U pip; \ From 5839f8868edb3ff71d6b960a5456e957cd4d5254 Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Sat, 7 Sep 2024 15:03:34 -0400 Subject: [PATCH 126/127] chore(deps): update uvloop --- poetry.lock | 276 ++++++++++++++++++++++++------------------------- pyproject.toml | 2 +- 2 files changed, 139 insertions(+), 139 deletions(-) diff --git a/poetry.lock b/poetry.lock index eceaeec9d..62e64a995 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1182,13 +1182,13 @@ tests = ["check-manifest", "coverage", "defusedxml", "markdown2", "olefile", "pa [[package]] name = "platformdirs" -version = "4.2.2" +version = "4.3.1" description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`." optional = false python-versions = ">=3.8" files = [ - {file = "platformdirs-4.2.2-py3-none-any.whl", hash = "sha256:2d7a1657e36a80ea911db832a8a6ece5ee53d8de21edd5cc5879af6530b1bfee"}, - {file = "platformdirs-4.2.2.tar.gz", hash = "sha256:38b7b51f512eed9e84a22788b4bce1de17c0adb134d6becb09836e37d8654cd3"}, + {file = "platformdirs-4.3.1-py3-none-any.whl", hash = "sha256:facaa5a3c57aa1e053e3da7b49e0cc31fe0113ca42a4659d5c2e98e545624afe"}, + {file = "platformdirs-4.3.1.tar.gz", hash = "sha256:63b79589009fa8159973601dd4563143396b35c5f93a58b36f9049ff046949b1"}, ] [package.extras] @@ -1628,13 +1628,13 @@ files = [ [[package]] name = "types-beautifulsoup4" -version = "4.12.0.20240511" +version = "4.12.0.20240907" description = "Typing stubs for beautifulsoup4" optional = false python-versions = ">=3.8" files = [ - {file = "types-beautifulsoup4-4.12.0.20240511.tar.gz", hash = "sha256:004f6096fdd83b19cdbf6cb10e4eae57b10205eccc365d0a69d77da836012e28"}, - {file = "types_beautifulsoup4-4.12.0.20240511-py3-none-any.whl", hash = "sha256:7ceda66a93ba28d759d5046d7fec9f4cad2f563a77b3a789efc90bcadafeefd1"}, + {file = "types-beautifulsoup4-4.12.0.20240907.tar.gz", hash = "sha256:8d023b86530922070417a1d4c4d91678ab0ff2439b3b2b2cffa3b628b49ebab1"}, + {file = "types_beautifulsoup4-4.12.0.20240907-py3-none-any.whl", hash = "sha256:32f5ac48514b488f15241afdd7d2f73f0baf3c54e874e23b66708503dd288489"}, ] [package.dependencies] @@ -1675,13 +1675,13 @@ files = [ [[package]] name = "types-requests" -version = "2.32.0.20240712" +version = "2.32.0.20240907" description = "Typing stubs for requests" optional = false python-versions = ">=3.8" files = [ - {file = "types-requests-2.32.0.20240712.tar.gz", hash = "sha256:90c079ff05e549f6bf50e02e910210b98b8ff1ebdd18e19c873cd237737c1358"}, - {file = "types_requests-2.32.0.20240712-py3-none-any.whl", hash = "sha256:f754283e152c752e46e70942fa2a146b5bc70393522257bb85bd1ef7e019dcc3"}, + {file = "types-requests-2.32.0.20240907.tar.gz", hash = "sha256:ff33935f061b5e81ec87997e91050f7b4af4f82027a7a7a9d9aaea04a963fdf8"}, + {file = "types_requests-2.32.0.20240907-py3-none-any.whl", hash = "sha256:1d1e79faeaf9d42def77f3c304893dea17a97cae98168ac69f3cb465516ee8da"}, ] [package.dependencies] @@ -1728,47 +1728,47 @@ zstd = ["zstandard (>=0.18.0)"] [[package]] name = "uvloop" -version = "0.17.0" +version = "0.20.0" description = "Fast implementation of asyncio event loop on top of libuv" optional = false -python-versions = ">=3.7" -files = [ - {file = "uvloop-0.17.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:ce9f61938d7155f79d3cb2ffa663147d4a76d16e08f65e2c66b77bd41b356718"}, - {file = "uvloop-0.17.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:68532f4349fd3900b839f588972b3392ee56042e440dd5873dfbbcd2cc67617c"}, - {file = "uvloop-0.17.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0949caf774b9fcefc7c5756bacbbbd3fc4c05a6b7eebc7c7ad6f825b23998d6d"}, - {file = "uvloop-0.17.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ff3d00b70ce95adce264462c930fbaecb29718ba6563db354608f37e49e09024"}, - {file = "uvloop-0.17.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:a5abddb3558d3f0a78949c750644a67be31e47936042d4f6c888dd6f3c95f4aa"}, - {file = "uvloop-0.17.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:8efcadc5a0003d3a6e887ccc1fb44dec25594f117a94e3127954c05cf144d811"}, - {file = "uvloop-0.17.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:3378eb62c63bf336ae2070599e49089005771cc651c8769aaad72d1bd9385a7c"}, - {file = "uvloop-0.17.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6aafa5a78b9e62493539456f8b646f85abc7093dd997f4976bb105537cf2635e"}, - {file = "uvloop-0.17.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c686a47d57ca910a2572fddfe9912819880b8765e2f01dc0dd12a9bf8573e539"}, - {file = "uvloop-0.17.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:864e1197139d651a76c81757db5eb199db8866e13acb0dfe96e6fc5d1cf45fc4"}, - {file = "uvloop-0.17.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:2a6149e1defac0faf505406259561bc14b034cdf1d4711a3ddcdfbaa8d825a05"}, - {file = "uvloop-0.17.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:6708f30db9117f115eadc4f125c2a10c1a50d711461699a0cbfaa45b9a78e376"}, - {file = "uvloop-0.17.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:23609ca361a7fc587031429fa25ad2ed7242941adec948f9d10c045bfecab06b"}, - {file = "uvloop-0.17.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2deae0b0fb00a6af41fe60a675cec079615b01d68beb4cc7b722424406b126a8"}, - {file = "uvloop-0.17.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:45cea33b208971e87a31c17622e4b440cac231766ec11e5d22c76fab3bf9df62"}, - {file = "uvloop-0.17.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:9b09e0f0ac29eee0451d71798878eae5a4e6a91aa275e114037b27f7db72702d"}, - {file = "uvloop-0.17.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:dbbaf9da2ee98ee2531e0c780455f2841e4675ff580ecf93fe5c48fe733b5667"}, - {file = "uvloop-0.17.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:a4aee22ece20958888eedbad20e4dbb03c37533e010fb824161b4f05e641f738"}, - {file = "uvloop-0.17.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:307958f9fc5c8bb01fad752d1345168c0abc5d62c1b72a4a8c6c06f042b45b20"}, - {file = "uvloop-0.17.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3ebeeec6a6641d0adb2ea71dcfb76017602ee2bfd8213e3fcc18d8f699c5104f"}, - {file = "uvloop-0.17.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1436c8673c1563422213ac6907789ecb2b070f5939b9cbff9ef7113f2b531595"}, - {file = "uvloop-0.17.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:8887d675a64cfc59f4ecd34382e5b4f0ef4ae1da37ed665adba0c2badf0d6578"}, - {file = "uvloop-0.17.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:3db8de10ed684995a7f34a001f15b374c230f7655ae840964d51496e2f8a8474"}, - {file = "uvloop-0.17.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:7d37dccc7ae63e61f7b96ee2e19c40f153ba6ce730d8ba4d3b4e9738c1dccc1b"}, - {file = "uvloop-0.17.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:cbbe908fda687e39afd6ea2a2f14c2c3e43f2ca88e3a11964b297822358d0e6c"}, - {file = "uvloop-0.17.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3d97672dc709fa4447ab83276f344a165075fd9f366a97b712bdd3fee05efae8"}, - {file = "uvloop-0.17.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f1e507c9ee39c61bfddd79714e4f85900656db1aec4d40c6de55648e85c2799c"}, - {file = "uvloop-0.17.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:c092a2c1e736086d59ac8e41f9c98f26bbf9b9222a76f21af9dfe949b99b2eb9"}, - {file = "uvloop-0.17.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:30babd84706115626ea78ea5dbc7dd8d0d01a2e9f9b306d24ca4ed5796c66ded"}, - {file = "uvloop-0.17.0.tar.gz", hash = "sha256:0ddf6baf9cf11a1a22c71487f39f15b2cf78eb5bde7e5b45fbb99e8a9d91b9e1"}, +python-versions = ">=3.8.0" +files = [ + {file = "uvloop-0.20.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:9ebafa0b96c62881d5cafa02d9da2e44c23f9f0cd829f3a32a6aff771449c996"}, + {file = "uvloop-0.20.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:35968fc697b0527a06e134999eef859b4034b37aebca537daeb598b9d45a137b"}, + {file = "uvloop-0.20.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b16696f10e59d7580979b420eedf6650010a4a9c3bd8113f24a103dfdb770b10"}, + {file = "uvloop-0.20.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9b04d96188d365151d1af41fa2d23257b674e7ead68cfd61c725a422764062ae"}, + {file = "uvloop-0.20.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:94707205efbe809dfa3a0d09c08bef1352f5d3d6612a506f10a319933757c006"}, + {file = "uvloop-0.20.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:89e8d33bb88d7263f74dc57d69f0063e06b5a5ce50bb9a6b32f5fcbe655f9e73"}, + {file = "uvloop-0.20.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:e50289c101495e0d1bb0bfcb4a60adde56e32f4449a67216a1ab2750aa84f037"}, + {file = "uvloop-0.20.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:e237f9c1e8a00e7d9ddaa288e535dc337a39bcbf679f290aee9d26df9e72bce9"}, + {file = "uvloop-0.20.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:746242cd703dc2b37f9d8b9f173749c15e9a918ddb021575a0205ec29a38d31e"}, + {file = "uvloop-0.20.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:82edbfd3df39fb3d108fc079ebc461330f7c2e33dbd002d146bf7c445ba6e756"}, + {file = "uvloop-0.20.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:80dc1b139516be2077b3e57ce1cb65bfed09149e1d175e0478e7a987863b68f0"}, + {file = "uvloop-0.20.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:4f44af67bf39af25db4c1ac27e82e9665717f9c26af2369c404be865c8818dcf"}, + {file = "uvloop-0.20.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:4b75f2950ddb6feed85336412b9a0c310a2edbcf4cf931aa5cfe29034829676d"}, + {file = "uvloop-0.20.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:77fbc69c287596880ecec2d4c7a62346bef08b6209749bf6ce8c22bbaca0239e"}, + {file = "uvloop-0.20.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6462c95f48e2d8d4c993a2950cd3d31ab061864d1c226bbf0ee2f1a8f36674b9"}, + {file = "uvloop-0.20.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:649c33034979273fa71aa25d0fe120ad1777c551d8c4cd2c0c9851d88fcb13ab"}, + {file = "uvloop-0.20.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:3a609780e942d43a275a617c0839d85f95c334bad29c4c0918252085113285b5"}, + {file = "uvloop-0.20.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:aea15c78e0d9ad6555ed201344ae36db5c63d428818b4b2a42842b3870127c00"}, + {file = "uvloop-0.20.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:f0e94b221295b5e69de57a1bd4aeb0b3a29f61be6e1b478bb8a69a73377db7ba"}, + {file = "uvloop-0.20.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:fee6044b64c965c425b65a4e17719953b96e065c5b7e09b599ff332bb2744bdf"}, + {file = "uvloop-0.20.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:265a99a2ff41a0fd56c19c3838b29bf54d1d177964c300dad388b27e84fd7847"}, + {file = "uvloop-0.20.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b10c2956efcecb981bf9cfb8184d27d5d64b9033f917115a960b83f11bfa0d6b"}, + {file = "uvloop-0.20.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:e7d61fe8e8d9335fac1bf8d5d82820b4808dd7a43020c149b63a1ada953d48a6"}, + {file = "uvloop-0.20.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:2beee18efd33fa6fdb0976e18475a4042cd31c7433c866e8a09ab604c7c22ff2"}, + {file = "uvloop-0.20.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:d8c36fdf3e02cec92aed2d44f63565ad1522a499c654f07935c8f9d04db69e95"}, + {file = "uvloop-0.20.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a0fac7be202596c7126146660725157d4813aa29a4cc990fe51346f75ff8fde7"}, + {file = "uvloop-0.20.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9d0fba61846f294bce41eb44d60d58136090ea2b5b99efd21cbdf4e21927c56a"}, + {file = "uvloop-0.20.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:95720bae002ac357202e0d866128eb1ac82545bcf0b549b9abe91b5178d9b541"}, + {file = "uvloop-0.20.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:36c530d8fa03bfa7085af54a48f2ca16ab74df3ec7108a46ba82fd8b411a2315"}, + {file = "uvloop-0.20.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:e97152983442b499d7a71e44f29baa75b3b02e65d9c44ba53b10338e98dedb66"}, + {file = "uvloop-0.20.0.tar.gz", hash = "sha256:4603ca714a754fc8d9b197e325db25b2ea045385e8a3ad05d3463de725fdf469"}, ] [package.extras] -dev = ["Cython (>=0.29.32,<0.30.0)", "Sphinx (>=4.1.2,<4.2.0)", "aiohttp", "flake8 (>=3.9.2,<3.10.0)", "mypy (>=0.800)", "psutil", "pyOpenSSL (>=22.0.0,<22.1.0)", "pycodestyle (>=2.7.0,<2.8.0)", "pytest (>=3.6.0)", "sphinx-rtd-theme (>=0.5.2,<0.6.0)", "sphinxcontrib-asyncio (>=0.3.0,<0.4.0)"] docs = ["Sphinx (>=4.1.2,<4.2.0)", "sphinx-rtd-theme (>=0.5.2,<0.6.0)", "sphinxcontrib-asyncio (>=0.3.0,<0.4.0)"] -test = ["Cython (>=0.29.32,<0.30.0)", "aiohttp", "flake8 (>=3.9.2,<3.10.0)", "mypy (>=0.800)", "psutil", "pyOpenSSL (>=22.0.0,<22.1.0)", "pycodestyle (>=2.7.0,<2.8.0)"] +test = ["Cython (>=0.29.36,<0.30.0)", "aiohttp (==3.9.0b0)", "aiohttp (>=3.8.1)", "flake8 (>=5.0,<6.0)", "mypy (>=0.800)", "psutil", "pyOpenSSL (>=23.0.0,<23.1.0)", "pycodestyle (>=2.9.0,<2.10.0)"] [[package]] name = "websockets" @@ -1867,103 +1867,103 @@ files = [ [[package]] name = "yarl" -version = "1.9.9" +version = "1.10.0" description = "Yet another URL library" optional = false python-versions = ">=3.8" files = [ - {file = "yarl-1.9.9-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:133b755d23181d2cf580e50710deae62fd6cb8ecb57884d5d22cc1a80939cdd8"}, - {file = "yarl-1.9.9-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:3bbf66d0f0179762d1a2c06e80d2c114cef8432c2874b1446bdae314608e8fbf"}, - {file = "yarl-1.9.9-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:26ca7fb99d852370e270c88728e2e3edeebf67733b734af3835f87e8be700b88"}, - {file = "yarl-1.9.9-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ef6961a23410832cd4174a21e6af9581e43ee3934396875402c6c9b033aa8dc9"}, - {file = "yarl-1.9.9-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e4c1344979375c3fa4385583b2f6d633745b35c03fd9be0932fc57d367e1c6f4"}, - {file = "yarl-1.9.9-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:759fe2045c03e6bf4a0224335626348a0e474d6499778b4483d0830e6450469c"}, - {file = "yarl-1.9.9-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7c37b94f821cfaa62c78f27235bc6854cc42513209365c0aeb01348135e8d339"}, - {file = "yarl-1.9.9-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1fac0e265c7b6ad795dabb59a66b954238cc42e4698fcc23d6b8e0a8bbaf9e99"}, - {file = "yarl-1.9.9-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:5cc4a506a27e24158505767ee4a0ccb011afd0fc26fdc00b6cf1ad568b402ed8"}, - {file = "yarl-1.9.9-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:c0a5f76bbb15a03dbe23a6ba5e7a4c3129611351fed24144397db65612aa77c3"}, - {file = "yarl-1.9.9-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:fd5c078f5df104869e16e5d48b30190839f55b2cf6fee0bc5a0aa8ae9012250f"}, - {file = "yarl-1.9.9-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:7f01cc7aa0de27dd75a9e07467b5e55fcceb7e6982d10e823d1846ea5b68069c"}, - {file = "yarl-1.9.9-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:9f03ae9b83cafe414b6d36a02767e1d311e524fec7ed3afadfd1ed22d05a5cfd"}, - {file = "yarl-1.9.9-cp310-cp310-win32.whl", hash = "sha256:2843c48fc52da7536bf43480ed04de4a15381ed689417179d14c10f75c6f814e"}, - {file = "yarl-1.9.9-cp310-cp310-win_amd64.whl", hash = "sha256:ca3e332a01f9bca2ad3a7f51e4d86c97967cc92df7247ad806d88b62a52bf594"}, - {file = "yarl-1.9.9-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:a4990a054911d92be8e8370e399df6cd7d8e6f9c005a3752e35da36825cc114a"}, - {file = "yarl-1.9.9-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6e3cb4420b07a9f5d96d14b20fea67596a96ca4983bb55337f8587f83981e8ad"}, - {file = "yarl-1.9.9-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:cb9b53b33cd653fef934e6567c5d23ca5eefb1e412a6aa8be180586001609087"}, - {file = "yarl-1.9.9-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f6cf7f3eadcd6604d64eed954e7334187b97e19ccfb885d2f511093757dc5623"}, - {file = "yarl-1.9.9-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1d1982613016380b32e54ddec0ab937cdfc799d3f6c1c06c37144033219277ef"}, - {file = "yarl-1.9.9-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5f7e260c6e025a0c74f1ad77b1840d1c0ee784b9e8dfbeb72c696f333eab565a"}, - {file = "yarl-1.9.9-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:03ef72a7ac3833c8b17ba007b61eb569082c2c29ce84d18ddf4b360b76ca6412"}, - {file = "yarl-1.9.9-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3e6dbc044f5d98160bf9adb89b88cfe8bca410d1a7c40033e2e7a82b66a71276"}, - {file = "yarl-1.9.9-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:9f806c990da324686d2ea037f61079692f099876362654b88facf56022b41452"}, - {file = "yarl-1.9.9-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:5991b36f2028190c8c3f1a4e8e9890ee371ec61662facd16d935cd9c1bf96040"}, - {file = "yarl-1.9.9-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:e12e4972c710c591271d092e6565e6fb668dd957eedec244001ef5d3e6ac394d"}, - {file = "yarl-1.9.9-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:28ba2f36cace7e89c70a330bd0e40618e58fd72c71183221b50e7a58ea95d50a"}, - {file = "yarl-1.9.9-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:47d31e691ec9a909538b4ebbae8b1170ccccee68cc223803b0322c6807ebb169"}, - {file = "yarl-1.9.9-cp311-cp311-win32.whl", hash = "sha256:943001da123754a510b8118a46d57c73fe00ac63099ba0cd63ff580002704dd8"}, - {file = "yarl-1.9.9-cp311-cp311-win_amd64.whl", hash = "sha256:ec7ff70bff03dfb1a9abdf47c050d57c2fc13e6218d67ea09fa15abfb87ba26f"}, - {file = "yarl-1.9.9-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:af4d94a2c2ee22f72bb936e210cedfa05096cb54ded3d1123efb90e2e2290f4e"}, - {file = "yarl-1.9.9-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:d03619326737a50e495cd60e04bc43110e4a34f55f65e3953813dc078c6fe561"}, - {file = "yarl-1.9.9-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5ce6d710df44165fa78c56ee2665b927e6f9d11f3e7dd79befb1c41579890ef8"}, - {file = "yarl-1.9.9-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5ed54f985bf3fd9dd282dcdd1ab4026e6b9bd4cbbcdd95cef5aa7f588bbf558b"}, - {file = "yarl-1.9.9-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bd82d4553f67b22d149fe1f20185c6a2a8927d9727d0cac47e317f1190c5d96b"}, - {file = "yarl-1.9.9-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d9654036bb0c1b65aecbb352f556d29662ae91753acfeac5d63e3ac034bfd084"}, - {file = "yarl-1.9.9-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:161e19878551954b44852d4ba437ef9d74445e72a9fd5aef44897d0d8d3b316d"}, - {file = "yarl-1.9.9-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7387809ddc87819c6e8c5168f1fe1249684e62aea1f253e34282348e3b52af9c"}, - {file = "yarl-1.9.9-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:98ce91e549e23aa548c497e2c49af6a6534d35eab5029e262b6658191c3e5ec2"}, - {file = "yarl-1.9.9-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:70f1048e64993142a4d6e7546b0930f399f9c4ccc381b6622b1cb2eba06a848b"}, - {file = "yarl-1.9.9-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:d61b203da3141c6e3504e361588c7921ccb5f2ee2978db1e1b627411a629b339"}, - {file = "yarl-1.9.9-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:573981f4b16ccfef83847b1409588c1d7533767321452c310d9b12289965c062"}, - {file = "yarl-1.9.9-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:995c7d7b9c802a27c5c0e24bb2c5e4811c6d14b21644b8f02ffc613d7b7b8297"}, - {file = "yarl-1.9.9-cp312-cp312-win32.whl", hash = "sha256:249e1abdb978eb29b40c5956c4c4e9fd5bf6f594cee7b937122462722fdfd661"}, - {file = "yarl-1.9.9-cp312-cp312-win_amd64.whl", hash = "sha256:99139694b62e499e547540462efc66d62355620ef23e3f1b003f3473c6726f72"}, - {file = "yarl-1.9.9-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:dea263b77d6a7ec70a24cd684cf92337359ab2fd83ce99b9911935162573a5b6"}, - {file = "yarl-1.9.9-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:3ae01f51e3ff817b2f18eea194f3e57dd2d70fbaccea41f72bbe66769584aefe"}, - {file = "yarl-1.9.9-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:b727ab129e6d516c4743f28cbca0ebf7445ec4164a903370b59bc37fd0e2b87c"}, - {file = "yarl-1.9.9-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4b6dfd1f25a5ef1e6d074be97a87f3b0e3b6e2ecd18b7d8ae658e0008b44b6f5"}, - {file = "yarl-1.9.9-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9d84d43d03a0714f4d7eff664eed4a353549c1b393fcc1316f553092a761bd90"}, - {file = "yarl-1.9.9-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:392c8e83d5028697c14762bce46d544dc01cbcf20ded20872045aae3a195c636"}, - {file = "yarl-1.9.9-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:827ab00f66fbdafd2a6f9a45ec3c4a8fe9ce54d60b327aa68aef7af5f3edf35e"}, - {file = "yarl-1.9.9-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ac9f79aac6d7044b90bf9f01bb133be96f21cef5369cdf68456b49adb00a838e"}, - {file = "yarl-1.9.9-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:3fe175c07ba7a5afcc26d484541440649c3b72d688b6c07b03f0bcacbd2cf3b5"}, - {file = "yarl-1.9.9-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:d7eb3fd1854f87555fc4f44c59c375b4775e088ddc50870c02f633ff03105be9"}, - {file = "yarl-1.9.9-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:1384e4dcb659abc5adbb2f9d0fe9aa6a059fdfa5b87f46106ad54be98a272530"}, - {file = "yarl-1.9.9-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:fbc505f9ad1c2d60b1ced4fb8f75ff95afbfa671b276a1f1ca0a56d3d06cf32e"}, - {file = "yarl-1.9.9-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:604c18c279f3b1959ff94bcda60ab52eb4ec825df5e1388f589930ba61506420"}, - {file = "yarl-1.9.9-cp313-cp313-win32.whl", hash = "sha256:0ad6085a23808109318c2fde9538bce88850a44c42e7e1ca421ec2c3e5d15ffa"}, - {file = "yarl-1.9.9-cp313-cp313-win_amd64.whl", hash = "sha256:e476b86f9eff02f09193fd2deda16089725d3aeba609158000e0d2b8d5fec3be"}, - {file = "yarl-1.9.9-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:aefb612d7543fb9857134fc43b4cfda4a923bfcca9b06d1c6e74606f184f2a4c"}, - {file = "yarl-1.9.9-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:bf840a2b20d2215bd5de6af24f41c9532731db0e9a4a311105e066815a6fddd2"}, - {file = "yarl-1.9.9-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:0295083cd8cd2084c9be79f71be3bd957794aeca0beae2c73207d3d588a0cc16"}, - {file = "yarl-1.9.9-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3d00068b634194e754c6782478d3f882db66be5ecb6a75141c49f1515d317f94"}, - {file = "yarl-1.9.9-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ad1d40f2fff7214ba352f915a10c3bfc07f4b69693be35e3a00271160a487d1b"}, - {file = "yarl-1.9.9-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b8ad1ba32966ccec8781f22ef612d4a8e807e8e9c140a792e7d224a41ee30813"}, - {file = "yarl-1.9.9-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9686f8a0185a20e67d8d80df558d479d1fe93a79807f6275a7a9b3c33c4ae38e"}, - {file = "yarl-1.9.9-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:835a0a3c8f883501e93a60144ba8e228c420ef5afc196d73583699ee475e0cfa"}, - {file = "yarl-1.9.9-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:305386e05778c71ff67226788dd1d174c4f5b4b8f0886508d743eec56d2b7980"}, - {file = "yarl-1.9.9-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:76814a708dedddd09cfb2ea3aa750b10cc2dcd67ef342d6125ff145241e29e52"}, - {file = "yarl-1.9.9-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:cafcdb8580e570091086af9c8166fd8bafcc0f8eb88df0c86ee40f74e8b47b9a"}, - {file = "yarl-1.9.9-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:5ccbc555cc577ebe4520d3c803ebc6ffd7cba29e306e05c3f6768d1bd14a59ba"}, - {file = "yarl-1.9.9-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:19c4ca114cf6b4ff261e43cae7358a57673e1c6aceceeee488b922ee9d8c66e8"}, - {file = "yarl-1.9.9-cp38-cp38-win32.whl", hash = "sha256:7815dec325ce59320e2331dec2506859e8148de880c2350bab4955567d6fe569"}, - {file = "yarl-1.9.9-cp38-cp38-win_amd64.whl", hash = "sha256:93a33f4d0bfb4d64ae462af5962d5f6442f0bf973a8b7af77cfb89db59a59abe"}, - {file = "yarl-1.9.9-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:ea9bd8bb9ad6e340e052b6f5af9ce3d6e50416e304b0a4b6ed8378b304acf401"}, - {file = "yarl-1.9.9-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:2010da427b6dc6383e953ecc6c5002e51ce3a8f33ba8cd26f9ebc0541c1323be"}, - {file = "yarl-1.9.9-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:41b1645a5695b6802c545b6696a736738f6935167bc7fe8a886a4aeb4bc57004"}, - {file = "yarl-1.9.9-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0bc7076693614e2ece788a64c2fad3e5f874ace2ac4f871bcc35709fe552ec1"}, - {file = "yarl-1.9.9-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:785450c11aceda6a3b5be8022dccf17dfb03b20b4ee5489b1d0ddbac862ab404"}, - {file = "yarl-1.9.9-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e319c258048e1d1e68f2e5054f4c5043f59605f2b9bbb36452be879dfe4bf3ae"}, - {file = "yarl-1.9.9-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a9ae5ca05a0201bc3db217042664f349b3e81db45e774f10924d09b60cfea3de"}, - {file = "yarl-1.9.9-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8766bbda365a5e33d395ceaa7e94b82ccf844f401309f7106c13c20248bb7f42"}, - {file = "yarl-1.9.9-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:01feeab5fece9eceffab2796da37b51d0832e80258cccb32a5be4a05385278df"}, - {file = "yarl-1.9.9-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:24178f95ccd0bb6c740b90d980c4a48535a2fd4912c2dda93e252b8b2d9f7877"}, - {file = "yarl-1.9.9-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:f398b3f1cb58ab1fb96af1e767fb85f0a56d50e455496175bf008276fba273d2"}, - {file = "yarl-1.9.9-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:018dd5f6a8371dd4abf553bd996e673f5173d9f8a71566897edeaf279346f55e"}, - {file = "yarl-1.9.9-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:5cf8b89b2a29a4fe98469f98c8c597bb1a308f1c9392fce0930cfc282b8142b9"}, - {file = "yarl-1.9.9-cp39-cp39-win32.whl", hash = "sha256:98efdcdbaf954ae8e084be1345ffd038a27c8f7c842fb7642b58d160752b4823"}, - {file = "yarl-1.9.9-cp39-cp39-win_amd64.whl", hash = "sha256:6f83424adbf4c5bda78f7963f01253b756c2b2d6a0949ca838a838840dea2437"}, - {file = "yarl-1.9.9-py3-none-any.whl", hash = "sha256:4384fc34c0b1f6d71ddac126652285d4aaf8c6172eb3734c7e1bdc634635b7d9"}, - {file = "yarl-1.9.9.tar.gz", hash = "sha256:d58a26cbc785a0fb6ad2e733422631c7f45c364a40dbd0cabb9f0dfcdbb4940b"}, + {file = "yarl-1.10.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:1718c0bca5a61edac7a57dcc11856cb01bde13a9360a3cb6baf384b89cfc0b40"}, + {file = "yarl-1.10.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e4657fd290d556a5f3018d07c7b7deadcb622760c0125277d10a11471c340054"}, + {file = "yarl-1.10.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:044b76d069e69c6b0246f071ebac0576f89c772f806d66ef51e662bd015d03c7"}, + {file = "yarl-1.10.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c5527d32506c11150ca87f33820057dc284e2a01a87f0238555cada247a8b278"}, + {file = "yarl-1.10.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:36d12d78b8b0d46099d413c8689b5510ad9ce5e443363d1c37b6ac5b3d7cbdfb"}, + {file = "yarl-1.10.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:11f7f8a72b3e26c533fa7ffa7a8068f4e3aad7b67c5cf7b17ea8c79fc81d9830"}, + {file = "yarl-1.10.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:88173836a25b7e5dce989eeee3b92d8ef5cdf512830d4155c6212de98e616f70"}, + {file = "yarl-1.10.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c382e189af10070bcb39caa9406b9cc47b26c1d2257979f11fe03a38be09fea9"}, + {file = "yarl-1.10.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:534b8bc181dca1691cf491c263e084af678a8fb6b6181687c788027d8c317026"}, + {file = "yarl-1.10.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:5f3372f9ae1d1f001826b77d0b29d4220e84f6c5f53915e71a825cdd02600065"}, + {file = "yarl-1.10.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:4cca9ba00be4bb8a051c4007b60fc91d6c9728c8b70c86cee4c24be9d641002f"}, + {file = "yarl-1.10.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:a9d8c4be5658834dc688072239d220631ad4b71ff79a5f3d17fb653f16d10759"}, + {file = "yarl-1.10.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:ff45a655ca51e1cb778abbb586083fddb7d896332f47bb3b03bc75e30c25649f"}, + {file = "yarl-1.10.0-cp310-cp310-win32.whl", hash = "sha256:9ef7ce61958b3c7b2e2e0927c52d35cf367c5ee410e06e1337ecc83a90c23b95"}, + {file = "yarl-1.10.0-cp310-cp310-win_amd64.whl", hash = "sha256:48a48261f8d610b0e15fed033e74798763bc2f8f2c0d769a2a0732511af71f1e"}, + {file = "yarl-1.10.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:308d1cce071b5b500e3d95636bbf15dfdb8e87ed081b893555658a7f9869a156"}, + {file = "yarl-1.10.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:bc66927f6362ed613a483c22618f88f014994ccbd0b7a25ec1ebc8c472d4b40a"}, + {file = "yarl-1.10.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c4d13071c5b99974cfe2f94c749ecc4baf882f7c4b6e4c40ca3d15d1b7e81f24"}, + {file = "yarl-1.10.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:348ad53acd41caa489df7db352d620c982ab069855d9635dda73d685bbbc3636"}, + {file = "yarl-1.10.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:293f7c2b30d015de3f1441c4ee764963b86636fde881b4d6093498d1e8711f69"}, + {file = "yarl-1.10.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:315e8853d0ea46aabdce01f1f248fff7b9743de89b555c5f0487f54ac84beae8"}, + {file = "yarl-1.10.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:012c506b2c23be4500fb97509aa7e6a575996fb317b80667fa26899d456e2aaf"}, + {file = "yarl-1.10.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5f769c2708c31227c5349c3e4c668c8b4b2e25af3e7263723f2ef33e8e3906a0"}, + {file = "yarl-1.10.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:4f6ac063a4e9bbd4f6cc88cc621516a44d6aec66862ea8399ba063374e4b12c7"}, + {file = "yarl-1.10.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:18b7ce6d8c35da8e16dcc8de124a80e250fc8c73f8c02663acf2485c874f1972"}, + {file = "yarl-1.10.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:b80246bdee036381636e73ef0f19b032912064622b0e5ee44f6960fd11df12aa"}, + {file = "yarl-1.10.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:183dd37bb5471e8017ab8a998c1ea070b4a0b08a97a7c4e20e0c7ccbe8ebb999"}, + {file = "yarl-1.10.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:9b6d0d7522b514f054b359409817af4c5ed76fa4fe42d8bd1ed12956804cf595"}, + {file = "yarl-1.10.0-cp311-cp311-win32.whl", hash = "sha256:6026a6ef14d038a38ca9d81422db4b6bb7d5da94f9d08f21e0ad9ebd9c4bc3bb"}, + {file = "yarl-1.10.0-cp311-cp311-win_amd64.whl", hash = "sha256:190e70d2f9f16f1c9d666c103d635c9ed4bf8de7803e9fa0495eec405a3e96a8"}, + {file = "yarl-1.10.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:6bc602c7413e1b5223bc988947125998cb54d6184de45a871985daacc23e6c8c"}, + {file = "yarl-1.10.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:bf733c835ebbd52bd78a52b919205e0f06d8571f71976a0259e5bcc20d0a2f44"}, + {file = "yarl-1.10.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6e91ed5f6818e1e3806eaeb7b14d9e17b90340f23089451ea59a89a29499d760"}, + {file = "yarl-1.10.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:23057a004bc9735008eb2a04b6ce94c6c06219cdf2b193997fd3ae6039eb3196"}, + {file = "yarl-1.10.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2b922c32a1cff62bc43d408d1a8745abeed0a705793f2253c622bf3521922198"}, + {file = "yarl-1.10.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:be199fed28861d72df917e355287ad6835555d8210e7f8203060561f24d7d842"}, + {file = "yarl-1.10.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5cece693380c1c4a606cdcaa0c54eda8f72cfe1ba83f5149b9023bb955e8fa8e"}, + {file = "yarl-1.10.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ff8e803d8ca170e632fb3b4df1bfd29ba29be8edc3e9306c5ffa5fadea234a4f"}, + {file = "yarl-1.10.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:30dde3a8b88c80a4f049eb4dd240d2a02e89174da6be2525541f949bf9fa38ab"}, + {file = "yarl-1.10.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:dff84623e7098cf9bfbb5187f9883051af652b0ce08b9f7084cc8630b87b6457"}, + {file = "yarl-1.10.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:8e69b55965a47dd6c79e578abd7d85637b1bb4a7565436630826bdb28aa9b7ad"}, + {file = "yarl-1.10.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:5d0c9e1dcc92d46ca89608fe4763fc2362f1e81c19a922c67dbc0f20951466e4"}, + {file = "yarl-1.10.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:32e79d5ae975f7c2cc29f7104691fc9be5ee3724f24e1a7254d72f6219672108"}, + {file = "yarl-1.10.0-cp312-cp312-win32.whl", hash = "sha256:762a196612c2aba4197cd271da65fe08308f7ddf130dc63842c7a76d774b6a2c"}, + {file = "yarl-1.10.0-cp312-cp312-win_amd64.whl", hash = "sha256:8c6214071f653d21bb7b43f7ee519afcbf7084263bb43408f4939d14558290db"}, + {file = "yarl-1.10.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:0e0aea8319fdc1ac340236e58b0b7dc763621bce6ce98124a9d58104cafd0aaa"}, + {file = "yarl-1.10.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:0b3bf343b4ef9ec600d75363eb9b48ab3bd53b53d4e1c5a9fbf0cfe7ba73a47f"}, + {file = "yarl-1.10.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:05b07e6e0f715eaae9d927a302d9220724392f3c0b4e7f8dfa174bf2e1b8433e"}, + {file = "yarl-1.10.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8d7bd531d7eec4aa7ef8a99fef91962eeea5158a53af0ec507c476ddf8ebc29c"}, + {file = "yarl-1.10.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:183136dc5d5411872e7529c924189a2e26fac5a7f9769cf13ef854d1d653ad36"}, + {file = "yarl-1.10.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c77a3c10af4aaf8891578fe492ef0990c65cf7005dd371f5ea8007b420958bf6"}, + {file = "yarl-1.10.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:030d41d48217b180c5a176e59c49d212d54d89f6f53640fa4c1a1766492aec27"}, + {file = "yarl-1.10.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6f4f43ba30d604ba391bc7fe2dd104d6b87b62b0de4bbde79e362524b8a1eb75"}, + {file = "yarl-1.10.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:637dd0f55d1781d4634c23994101c509e455b5ab61af9086b5763b7eca9359aa"}, + {file = "yarl-1.10.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:99e7459ee86a3b81e57777afd3825b8b1acaac8a99f9c0bd02415d80eb3c371b"}, + {file = "yarl-1.10.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:a80cdb3c15c15b33ecdb080546dcb022789b0084ca66ad41ffa0fe09857fca11"}, + {file = "yarl-1.10.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:1824bfb932d8100e5c94f4f98c078f23ebc6f6fa93acc3d95408762089c54a06"}, + {file = "yarl-1.10.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:90fd64ce00f594db02f603efa502521c440fa1afcf6266be82eb31f19d2d9561"}, + {file = "yarl-1.10.0-cp313-cp313-win32.whl", hash = "sha256:687131ee4d045f3d58128ca28f5047ec902f7760545c39bbe003cc737c5a02b5"}, + {file = "yarl-1.10.0-cp313-cp313-win_amd64.whl", hash = "sha256:493ad061ee025c5ed3a60893cd70204eead1b3f60ccc90682e752f95b845bd46"}, + {file = "yarl-1.10.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:cd65588273d19f8483bc8f32a6fcf602e94a9a7ba287a1725977bd9527cd6c0c"}, + {file = "yarl-1.10.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6f64f8681671624f539eea5564518bc924524c25eb90ab24a7eddc2d872e668e"}, + {file = "yarl-1.10.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:3576ed2c51f8525d4ff5c3279247aacff9540bb43b292c4a37a8e6c6e1691adb"}, + {file = "yarl-1.10.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ca42a9281807fdf8fba86e671d8fdd76f92e9302a6d332957f2bae51c774f8a7"}, + {file = "yarl-1.10.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:54a4b5e6a060d46cad6a3cf340f4cb268e6fbc89c589d82a2da58f7db47c47c8"}, + {file = "yarl-1.10.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6eec21d8c3aa932c5a89480b58fa877e9c48092ab838ccc76788cbc917ceec0d"}, + {file = "yarl-1.10.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:273baee8a8af5989d5aab51c740e65bc2b1fc6619b9dd192cd16a3fae51100be"}, + {file = "yarl-1.10.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c1bf63ba496cd4f12d30e916d9a52daa6c91433fedd9cd0d99fef3e13232836f"}, + {file = "yarl-1.10.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:f8e24b9a4afdffab399191a9f0b0e80eabc7b7fdb9f2dbccdeb8e4d28e5c57bb"}, + {file = "yarl-1.10.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:4c46454fafa31f7241083a0dd21814f63e0fcb4ae49662dc7e286fd6a5160ea1"}, + {file = "yarl-1.10.0-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:beda87b63c08fb4df8cc5353eeefe68efe12aa4f5284958bd1466b14c85e508e"}, + {file = "yarl-1.10.0-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:9a8d6a0e2b5617b5c15c59db25f20ba429f1fea810f2c09fbf93067cb21ab085"}, + {file = "yarl-1.10.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:b453b3dbc1ed4c2907632d05b378123f3fb411cad05d8d96de7d95104ef11c70"}, + {file = "yarl-1.10.0-cp38-cp38-win32.whl", hash = "sha256:1ea30675fbf0ad6795c100da677ef6a8960a7db05ac5293f02a23c2230203c89"}, + {file = "yarl-1.10.0-cp38-cp38-win_amd64.whl", hash = "sha256:347011ad09a8f9be3d41fe2d7d611c3a4de4d49aa77bcb9a8c03c7a82fc45248"}, + {file = "yarl-1.10.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:18bc4600eed1907762c1816bb16ac63bc52912e53b5e9a353eb0935a78e95496"}, + {file = "yarl-1.10.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:eeb6a40c5ae2616fd38c1e039c6dd50031bbfbc2acacfd7b70a5d64fafc70901"}, + {file = "yarl-1.10.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:bc544248b5263e1c0f61332ccf35e37404b54213f77ed17457f857f40af51452"}, + {file = "yarl-1.10.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3352c69dc235850d6bf8ddad915931f00dcab208ac4248b9af46175204c2f5f9"}, + {file = "yarl-1.10.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:af5b52bfbbd5eb208cf1afe23c5ada443929e9b9d79e9fbc66cacc07e4e39748"}, + {file = "yarl-1.10.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1eafa7317063de4bc310716cdd9026c13f00b1629e649079a6908c3aafdf5046"}, + {file = "yarl-1.10.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a162cf04fd1e8d81025ec651d14cac4f6e0ca73a3c0a9482de8691b944e3098a"}, + {file = "yarl-1.10.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:179b1df5e9cd99234ea65e63d5bfc6dd524b2c3b6cf68a14b94ccbe01ab37ddd"}, + {file = "yarl-1.10.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:32d2e46848dea122484317485129f080220aa84aeb6a9572ad9015107cebeb07"}, + {file = "yarl-1.10.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:aa1aeb99408be0ca774c5126977eb085fedda6dd7d9198ce4ceb2d06a44325c7"}, + {file = "yarl-1.10.0-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:d2366e2f987f69752f0588d2035321aaf24272693d75f7f6bb7e8a0f48f7ccdd"}, + {file = "yarl-1.10.0-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:e8da33665ecc64cd3e593098adb449f9c65b4e3bc6338e75ad592da15453d898"}, + {file = "yarl-1.10.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:5b46c603bee1f2dd407b8358c2afc9b0472a22ccca528f114e1f4cd30dfecd22"}, + {file = "yarl-1.10.0-cp39-cp39-win32.whl", hash = "sha256:96422a3322b4d954f4c52403a2fc129ad118c151ee60a717847fb46a8480d1e1"}, + {file = "yarl-1.10.0-cp39-cp39-win_amd64.whl", hash = "sha256:52d1ae09b0764017e330bb5bf9af760c0168c564225085bb806f687bccffda8a"}, + {file = "yarl-1.10.0-py3-none-any.whl", hash = "sha256:99eaa7d53f509ba1c2fea8fdfec15ba3cd36caca31d57ec6665073b148b5f260"}, + {file = "yarl-1.10.0.tar.gz", hash = "sha256:3bf10a395adac62177ba8ea738617e8de6cbb1cea6aa5d5dd2accde704fc8195"}, ] [package.dependencies] @@ -2004,4 +2004,4 @@ test = ["pytest (>=8.1,<9.0)"] [metadata] lock-version = "2.0" python-versions = ">=3.10.0,<3.12" -content-hash = "c6ece7aa719f09e1f5e0d8d715298670b5df29cc8dbce5b64ee6da2343e6f3c8" +content-hash = "74095f0b2be462abf5edf0397ec3c7349c9bd8c846d4afb4a7b93d59e4b4a5b7" diff --git a/pyproject.toml b/pyproject.toml index a1dec3c78..8827235ff 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -30,7 +30,7 @@ regex = "^2023.5.5" googletrans = "==4.0.0rc1" yt-dlp = "^2024.4.9" Pillow = "^9.5.0" -uvloop = {version="~0.17.0", markers = "sys_platform == 'linux' or sys_platform == 'darwin'"} +uvloop = {version="~0.20.0", markers = "sys_platform == 'linux' or sys_platform == 'darwin'"} bidict = "^0.22.0" aiosqlite = "^0.19.0" lxml = "^4.9.1" From bceb4b5fabe9b02756b6638bcd4474ef619de5fd Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Sat, 7 Sep 2024 15:08:56 -0400 Subject: [PATCH 127/127] ci: build an edge (master-branch) image too --- .github/workflows/publish-docker.yml | 42 ++++++++++++++++++++++++---- 1 file changed, 36 insertions(+), 6 deletions(-) diff --git a/.github/workflows/publish-docker.yml b/.github/workflows/publish-docker.yml index f42252d2b..a97a2c287 100644 --- a/.github/workflows/publish-docker.yml +++ b/.github/workflows/publish-docker.yml @@ -4,6 +4,10 @@ on: release: types: [published] + push: + branches: + - master + jobs: publish: runs-on: ubuntu-latest @@ -12,26 +16,52 @@ jobs: contents: read steps: - uses: actions/checkout@v4 - - uses: actions/setup-python@v5 + + - name: Set up master (edge) image metadata + id: meta-master + uses: docker/metadata-action@v5 + if: ${{ github.event_name != 'release' }} with: - python-version: '3.11' - - run: pip install poetry && poetry update && poetry export -f requirements.txt > requirements.txt - - uses: docker/metadata-action@v5 - id: meta + images: | + ${{ inputs.image-name }} + flavor: | + latest=false + tags: | + type=raw,value=master,enable={{is_default_branch}} + type=sha,prefix=sha- + + - name: Set up release image metadata + id: meta-release + uses: docker/metadata-action@v5 + if: ${{ github.event_name == 'release' }} with: images: ghcr.io/idoneam/Canary + flavor: | + latest=true tags: | type=semver,pattern={{major}} type=semver,pattern={{major}}.{{minor}} type=semver,pattern={{version}} + - uses: docker/setup-buildx-action@v3 + - uses: docker/login-action@v3 with: registry: ghcr.io username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} + + - name: Build and push master (edge) image + uses: docker/build-push-action@v6 + if: ${{ github.event_name != 'release' }} + with: + context: . + push: true + tags: ${{ steps.meta-master.outputs.tags }} + - uses: docker/build-push-action@v6 + if: ${{ github.event_name == 'release' }} with: context: . push: true - tags: ${{ steps.meta.outputs.tags }} + tags: ${{ steps.meta-release.outputs.tags }}