aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar ChrisJL <[email protected]>2023-08-11 15:55:20 +0100
committerGravatar GitHub <[email protected]>2023-08-11 15:55:20 +0100
commit14b01397684162f3e82dd3703c0bed531a77eb5a (patch)
tree2c21b0eeff30bf56816ec6f501e5e27f19ea6de4
parentMerge pull request #2710 from python-discord/dependabot/pip/ruff-0.0.283 (diff)
parentDon't use a BaseSettings instance for constants that don't need to be overwri... (diff)
Merge pull request #2695 from python-discord/pydantic-v2
Migrate to Pydantic v2
-rw-r--r--bot/constants.py536
-rw-r--r--bot/exts/filtering/_filter_lists/antispam.py2
-rw-r--r--bot/exts/filtering/_filters/filter.py4
-rw-r--r--bot/exts/filtering/_settings.py2
-rw-r--r--bot/exts/filtering/_settings_types/actions/infraction_and_notification.py16
-rw-r--r--bot/exts/filtering/_settings_types/actions/ping.py4
-rw-r--r--bot/exts/filtering/_settings_types/settings_entry.py2
-rw-r--r--bot/exts/filtering/_settings_types/validations/bypass_roles.py25
-rw-r--r--bot/exts/filtering/_settings_types/validations/channel_scope.py34
-rw-r--r--bot/exts/filtering/_ui/filter.py6
-rw-r--r--bot/exts/filtering/_ui/filter_list.py2
-rw-r--r--bot/exts/filtering/_utils.py13
-rw-r--r--bot/exts/filtering/filtering.py14
-rw-r--r--bot/exts/recruitment/talentpool/_api.py12
-rw-r--r--botstrap.py6
-rw-r--r--poetry.lock234
-rw-r--r--pyproject.toml3
-rw-r--r--tests/bot/exts/filtering/test_settings_entries.py4
18 files changed, 508 insertions, 411 deletions
diff --git a/bot/constants.py b/bot/constants.py
index fa72de19f..4e73fbe74 100644
--- a/bot/constants.py
+++ b/bot/constants.py
@@ -8,23 +8,23 @@ By default, the values defined in the classes are used, these can be overridden
import os
from enum import Enum
-from pydantic import BaseModel, BaseSettings, root_validator
+from pydantic import BaseModel
+from pydantic_settings import BaseSettings
-class EnvConfig(BaseSettings):
+class EnvConfig(
+ BaseSettings,
+ env_file=(".env.server", ".env"),
+ env_file_encoding = "utf-8",
+ env_nested_delimiter = "__",
+ extra="ignore",
+):
"""Our default configuration for models that should load from .env files."""
- class Config:
- """Specify what .env files to load, and how to load them."""
-
- env_file = ".env.server", ".env",
- env_file_encoding = "utf-8"
- env_nested_delimiter = "__"
-
class _Miscellaneous(EnvConfig):
- debug = True
- file_logs = False
+ debug: bool = True
+ file_logs: bool = False
Miscellaneous = _Miscellaneous()
@@ -34,192 +34,186 @@ FILE_LOGS = Miscellaneous.file_logs
DEBUG_MODE = Miscellaneous.debug
-class _Bot(EnvConfig):
- EnvConfig.Config.env_prefix = "bot_"
+class _Bot(EnvConfig, env_prefix="bot_"):
- prefix = "!"
- sentry_dsn = ""
- token = ""
- trace_loggers = "*"
+ prefix: str = "!"
+ sentry_dsn: str = ""
+ token: str
+ trace_loggers: str = "*"
Bot = _Bot()
-class _Channels(EnvConfig):
- EnvConfig.Config.env_prefix = "channels_"
+class _Channels(EnvConfig, env_prefix="channels_"):
- announcements = 354619224620138496
- changelog = 748238795236704388
- mailing_lists = 704372456592506880
- python_events = 729674110270963822
- python_news = 704372456592506880
- reddit = 458224812528238616
+ announcements: int = 354619224620138496
+ changelog: int = 748238795236704388
+ mailing_lists: int = 704372456592506880
+ python_events: int = 729674110270963822
+ python_news: int = 704372456592506880
+ reddit: int = 458224812528238616
- dev_contrib = 635950537262759947
- dev_core = 411200599653351425
- dev_log = 622895325144940554
+ dev_contrib: int = 635950537262759947
+ dev_core: int = 411200599653351425
+ dev_log: int = 622895325144940554
- meta = 429409067623251969
- python_general = 267624335836053506
+ meta: int = 429409067623251969
+ python_general: int = 267624335836053506
- python_help = 1035199133436354600
+ python_help: int = 1035199133436354600
- attachment_log = 649243850006855680
- filter_log = 1014943924185473094
- message_log = 467752170159079424
- mod_log = 282638479504965634
- nomination_voting_archive = 833371042046148738
- user_log = 528976905546760203
- voice_log = 640292421988646961
+ attachment_log: int = 649243850006855680
+ filter_log: int = 1014943924185473094
+ message_log: int = 467752170159079424
+ mod_log: int = 282638479504965634
+ nomination_voting_archive: int = 833371042046148738
+ user_log: int = 528976905546760203
+ voice_log: int = 640292421988646961
- off_topic_0 = 291284109232308226
- off_topic_1 = 463035241142026251
- off_topic_2 = 463035268514185226
+ off_topic_0: int = 291284109232308226
+ off_topic_1: int = 463035241142026251
+ off_topic_2: int = 463035268514185226
- bot_commands = 267659945086812160
- discord_bots = 343944376055103488
- esoteric = 470884583684964352
- voice_gate = 764802555427029012
- code_jam_planning = 490217981872177157
+ bot_commands: int = 267659945086812160
+ discord_bots: int = 343944376055103488
+ esoteric: int = 470884583684964352
+ voice_gate: int = 764802555427029012
+ code_jam_planning: int = 490217981872177157
# Staff
- admins = 365960823622991872
- admin_spam = 563594791770914816
- defcon = 464469101889454091
- helpers = 385474242440986624
- incidents = 714214212200562749
- incidents_archive = 720668923636351037
- mod_alerts = 473092532147060736
- mod_meta = 775412552795947058
- mods = 305126844661760000
- nominations = 822920136150745168
- nomination_discussion = 798959130634747914
- nomination_voting = 822853512709931008
- organisation = 551789653284356126
+ admins: int = 365960823622991872
+ admin_spam: int = 563594791770914816
+ defcon: int = 464469101889454091
+ helpers: int = 385474242440986624
+ incidents: int = 714214212200562749
+ incidents_archive: int = 720668923636351037
+ mod_alerts: int = 473092532147060736
+ mod_meta: int = 775412552795947058
+ mods: int = 305126844661760000
+ nominations: int = 822920136150745168
+ nomination_discussion: int = 798959130634747914
+ nomination_voting: int = 822853512709931008
+ organisation: int = 551789653284356126
# Staff announcement channels
- admin_announcements = 749736155569848370
- mod_announcements = 372115205867700225
- staff_announcements = 464033278631084042
- staff_info = 396684402404622347
- staff_lounge = 464905259261755392
+ admin_announcements: int = 749736155569848370
+ mod_announcements: int = 372115205867700225
+ staff_announcements: int = 464033278631084042
+ staff_info: int = 396684402404622347
+ staff_lounge: int = 464905259261755392
# Voice Channels
- admins_voice = 500734494840717332
- code_help_voice_0 = 751592231726481530
- code_help_voice_1 = 764232549840846858
- general_voice_0 = 751591688538947646
- general_voice_1 = 799641437645701151
- staff_voice = 412375055910043655
+ admins_voice: int = 500734494840717332
+ code_help_voice_0: int = 751592231726481530
+ code_help_voice_1: int = 764232549840846858
+ general_voice_0: int = 751591688538947646
+ general_voice_1: int = 799641437645701151
+ staff_voice: int = 412375055910043655
- black_formatter = 846434317021741086
+ black_formatter: int = 846434317021741086
# Voice Chat
- code_help_chat_0 = 755154969761677312
- code_help_chat_1 = 766330079135268884
- staff_voice_chat = 541638762007101470
- voice_chat_0 = 412357430186344448
- voice_chat_1 = 799647045886541885
+ code_help_chat_0: int = 755154969761677312
+ code_help_chat_1: int = 766330079135268884
+ staff_voice_chat: int = 541638762007101470
+ voice_chat_0: int = 412357430186344448
+ voice_chat_1: int = 799647045886541885
- big_brother = 468507907357409333
- duck_pond = 637820308341915648
- roles = 851270062434156586
+ big_brother: int = 468507907357409333
+ duck_pond: int = 637820308341915648
+ roles: int = 851270062434156586
- rules = 693837295685730335
+ rules: int = 693837295685730335
Channels = _Channels()
-class _Roles(EnvConfig):
-
- EnvConfig.Config.env_prefix = "roles_"
+class _Roles(EnvConfig, env_prefix="roles_"):
# Self-assignable roles, see the Subscribe cog
- advent_of_code = 518565788744024082
- announcements = 463658397560995840
- lovefest = 542431903886606399
- pyweek_announcements = 897568414044938310
- revival_of_code = 988801794668908655
- legacy_help_channels_access = 1074780483776417964
-
- contributors = 295488872404484098
- help_cooldown = 699189276025421825
- partners = 323426753857191936
- python_community = 458226413825294336
- voice_verified = 764802720779337729
+ advent_of_code: int = 518565788744024082
+ announcements: int = 463658397560995840
+ lovefest: int = 542431903886606399
+ pyweek_announcements: int = 897568414044938310
+ revival_of_code: int = 988801794668908655
+ legacy_help_channels_access: int = 1074780483776417964
+
+ contributors: int = 295488872404484098
+ help_cooldown: int = 699189276025421825
+ partners: int = 323426753857191936
+ python_community: int = 458226413825294336
+ voice_verified: int = 764802720779337729
# Streaming
- video = 764245844798079016
+ video: int = 764245844798079016
# Staff
- admins = 267628507062992896
- core_developers = 587606783669829632
- code_jam_event_team = 787816728474288181
- devops = 409416496733880320
- domain_leads = 807415650778742785
- events_lead = 778361735739998228
- helpers = 267630620367257601
- moderators = 831776746206265384
- mod_team = 267629731250176001
- owners = 267627879762755584
- project_leads = 815701647526330398
+ admins: int = 267628507062992896
+ core_developers: int = 587606783669829632
+ code_jam_event_team: int = 787816728474288181
+ devops: int = 409416496733880320
+ domain_leads: int = 807415650778742785
+ events_lead: int = 778361735739998228
+ helpers: int = 267630620367257601
+ moderators: int = 831776746206265384
+ mod_team: int = 267629731250176001
+ owners: int = 267627879762755584
+ project_leads: int = 815701647526330398
# Code Jam
- jammers = 737249140966162473
+ jammers: int = 737249140966162473
# Patreon
- patreon_tier_1 = 505040943800516611
- patreon_tier_2 = 743399725914390631
- patreon_tier_3 = 743400204367036520
+ patreon_tier_1: int = 505040943800516611
+ patreon_tier_2: int = 743399725914390631
+ patreon_tier_3: int = 743400204367036520
Roles = _Roles()
-class _Categories(EnvConfig):
- EnvConfig.Config.env_prefix = "categories_"
+class _Categories(EnvConfig, env_prefix="categories_"):
- logs = 468520609152892958
- moderators = 749736277464842262
- modmail = 714494672835444826
- appeals = 890331800025563216
- appeals_2 = 895417395261341766
- voice = 356013253765234688
+ logs: int = 468520609152892958
+ moderators: int = 749736277464842262
+ modmail: int = 714494672835444826
+ appeals: int = 890331800025563216
+ appeals_2: int = 895417395261341766
+ voice: int = 356013253765234688
# 2021 Summer Code Jam
- summer_code_jam = 861692638540857384
- python_help_system = 691405807388196926
+ summer_code_jam: int = 861692638540857384
+ python_help_system: int = 691405807388196926
Categories = _Categories()
-class _Guild(EnvConfig):
- EnvConfig.Config.env_prefix = "guild_"
+class _Guild(EnvConfig, env_prefix="guild_"):
- id = 267624335836053506
- invite = "https://discord.gg/python"
+ id: int = 267624335836053506
+ invite: str = "https://discord.gg/python"
- moderation_categories = [
+ moderation_categories: tuple[int, ...] = (
Categories.moderators,
Categories.modmail,
Categories.logs,
Categories.appeals,
Categories.appeals_2
- ]
- moderation_channels = [Channels.admins, Channels.admin_spam, Channels.mods]
- modlog_blacklist = [
+ )
+ moderation_channels: tuple[int, ...] = (Channels.admins, Channels.admin_spam, Channels.mods)
+ modlog_blacklist: tuple[int, ...] = (
Channels.attachment_log,
Channels.message_log,
Channels.mod_log,
Channels.staff_voice,
Channels.filter_log
- ]
- reminder_whitelist = [Channels.bot_commands, Channels.dev_contrib, Channels.black_formatter]
- moderation_roles = [Roles.admins, Roles.mod_team, Roles.moderators, Roles.owners]
- staff_roles = [Roles.admins, Roles.helpers, Roles.mod_team, Roles.owners]
+ )
+ reminder_whitelist: tuple[int, ...] = (Channels.bot_commands, Channels.dev_contrib, Channels.black_formatter)
+ moderation_roles: tuple[int, ...] = (Roles.admins, Roles.mod_team, Roles.moderators, Roles.owners)
+ staff_roles: tuple[int, ...] = (Roles.admins, Roles.helpers, Roles.mod_team, Roles.owners)
Guild = _Guild()
@@ -268,8 +262,7 @@ class Webhook(BaseModel):
channel: int
-class _Webhooks(EnvConfig):
- EnvConfig.Config.env_prefix = "webhooks_"
+class _Webhooks(EnvConfig, env_prefix="webhooks_"):
big_brother: Webhook = Webhook(id=569133704568373283, channel=Channels.big_brother)
dev_log: Webhook = Webhook(id=680501655111729222, channel=Channels.dev_log)
@@ -282,85 +275,55 @@ class _Webhooks(EnvConfig):
Webhooks = _Webhooks()
-class _BigBrother(EnvConfig):
- EnvConfig.Config.env_prefix = "big_brother_"
+class _BigBrother(EnvConfig, env_prefix="big_brother_"):
- header_message_limit = 15
- log_delay = 15
+ header_message_limit: int = 15
+ log_delay: int = 15
BigBrother = _BigBrother()
-class _CodeBlock(EnvConfig):
- EnvConfig.Config.env_prefix = "code_block_"
+class _CodeBlock(EnvConfig, env_prefix="code_block_"):
# The channels in which code blocks will be detected. They are not subject to a cooldown.
- channel_whitelist: list[int] = [Channels.bot_commands]
+ channel_whitelist: tuple[int, ...] = (Channels.bot_commands,)
# The channels which will be affected by a cooldown. These channels are also whitelisted.
- cooldown_channels: list[int] = [Channels.python_general]
+ cooldown_channels: tuple[int, ...] = (Channels.python_general,)
- cooldown_seconds = 300
- minimum_lines = 4
+ cooldown_seconds: int = 300
+ minimum_lines: int = 4
CodeBlock = _CodeBlock()
-class _Colours(EnvConfig):
- EnvConfig.Config.env_prefix = "colours_"
-
- blue = 0x3775a8
- bright_green = 0x01d277
- orange = 0xe67e22
- pink = 0xcf84e0
- purple = 0xb734eb
- soft_green = 0x68c290
- soft_orange = 0xf9cb54
- soft_red = 0xcd6d6d
- white = 0xfffffe
- yellow = 0xffd241
-
- @root_validator(pre=True)
- def parse_hex_values(cls, values: dict) -> dict: # noqa: N805
- """Convert hex strings to ints."""
- for key, value in values.items():
- values[key] = int(value, 16)
- return values
-
+class _HelpChannels(EnvConfig, env_prefix="help_channels_"):
-Colours = _Colours()
-
-
-class _HelpChannels(EnvConfig):
- EnvConfig.Config.env_prefix = "help_channels_"
-
- enable = True
- idle_minutes = 60
- deleted_idle_minutes = 5
+ enable: bool = True
+ idle_minutes: int = 60
+ deleted_idle_minutes: int = 5
# Roles which are allowed to use the command which makes channels dormant
- cmd_whitelist = Guild.moderation_roles
+ cmd_whitelist: tuple[int, ...] = Guild.moderation_roles
HelpChannels = _HelpChannels()
-class _RedirectOutput(EnvConfig):
- EnvConfig.Config.env_prefix = "redirect_output_"
+class _RedirectOutput(EnvConfig, env_prefix="redirect_output_"):
- delete_delay = 15
- delete_invocation = True
+ delete_delay: int = 15
+ delete_invocation: bool = True
RedirectOutput = _RedirectOutput()
-class _DuckPond(EnvConfig):
- EnvConfig.Config.env_prefix = "duck_pond_"
+class _DuckPond(EnvConfig, env_prefix="duck_pond_"):
- threshold = 7
+ threshold: int = 7
- channel_blacklist: list[int] = [
+ channel_blacklist: tuple[int, ...] = (
Channels.announcements,
Channels.python_news,
Channels.python_events,
@@ -371,126 +334,114 @@ class _DuckPond(EnvConfig):
Channels.staff_announcements,
Channels.mod_announcements,
Channels.admin_announcements,
- Channels.staff_info
- ]
+ Channels.staff_info,
+ )
DuckPond = _DuckPond()
-class _PythonNews(EnvConfig):
- EnvConfig.Config.env_prefix = "python_news_"
+class _PythonNews(EnvConfig, env_prefix="python_news_"):
channel: int = Webhooks.python_news.channel
webhook: int = Webhooks.python_news.id
- mail_lists = ["python-ideas", "python-announce-list", "pypi-announce", "python-dev"]
+ mail_lists: tuple[str, ...] = ("python-ideas", "python-announce-list", "pypi-announce", "python-dev")
PythonNews = _PythonNews()
-class _VoiceGate(EnvConfig):
- EnvConfig.Config.env_prefix = "voice_gate_"
+class _VoiceGate(EnvConfig, env_prefix="voice_gate_"):
- bot_message_delete_delay = 10
- minimum_activity_blocks = 3
- minimum_days_member = 3
- minimum_messages = 50
- voice_ping_delete_delay = 60
+ bot_message_delete_delay: int = 10
+ minimum_activity_blocks: int = 3
+ minimum_days_member: int = 3
+ minimum_messages: int = 50
+ voice_ping_delete_delay: int = 60
VoiceGate = _VoiceGate()
-class _Branding(EnvConfig):
- EnvConfig.Config.env_prefix = "branding_"
+class _Branding(EnvConfig, env_prefix="branding_"):
- cycle_frequency = 3
+ cycle_frequency: int = 3
Branding = _Branding()
-class _VideoPermission(EnvConfig):
- EnvConfig.Config.env_prefix = "video_permission_"
+class _VideoPermission(EnvConfig, env_prefix="video_permission_"):
- default_permission_duration = 5
+ default_permission_duration: int = 5
VideoPermission = _VideoPermission()
-class _Redis(EnvConfig):
- EnvConfig.Config.env_prefix = "redis_"
+class _Redis(EnvConfig, env_prefix="redis_"):
- host = "redis.default.svc.cluster.local"
- password = ""
- port = 6379
- use_fakeredis = False # If this is True, Bot will use fakeredis.aioredis
+ host: str = "redis.default.svc.cluster.local"
+ password: str = ""
+ port: int = 6379
+ use_fakeredis: bool = False # If this is True, Bot will use fakeredis.aioredis
Redis = _Redis()
-class _CleanMessages(EnvConfig):
- EnvConfig.Config.env_prefix = "clean_"
+class _CleanMessages(EnvConfig, env_prefix="clean_"):
- message_limit = 10_000
+ message_limit: int = 10_000
CleanMessages = _CleanMessages()
-class _Stats(EnvConfig):
- EnvConfig.Config.env_prefix = "stats_"
+class _Stats(EnvConfig, env_prefix="stats_"):
- presence_update_timeout = 30
- statsd_host = "graphite.default.svc.cluster.local"
+ presence_update_timeout: int = 30
+ statsd_host: str = "graphite.default.svc.cluster.local"
Stats = _Stats()
-class _Cooldowns(EnvConfig):
- EnvConfig.Config.env_prefix = "cooldowns_"
+class _Cooldowns(EnvConfig, env_prefix="cooldowns_"):
- tags = 60
+ tags: int = 60
Cooldowns = _Cooldowns()
-class _Metabase(EnvConfig):
- EnvConfig.Config.env_prefix = "metabase_"
+class _Metabase(EnvConfig, env_prefix="metabase_"):
- username = ""
- password = ""
- base_url = "http://metabase.default.svc.cluster.local"
- public_url = "https://metabase.pythondiscord.com"
- max_session_age = 20_160
+ username: str = ""
+ password: str = ""
+ base_url: str = "http://metabase.default.svc.cluster.local"
+ public_url: str = "https://metabase.pythondiscord.com"
+ max_session_age: int = 20_160
Metabase = _Metabase()
-class _BaseURLs(EnvConfig):
- EnvConfig.Config.env_prefix = "urls_"
+class _BaseURLs(EnvConfig, env_prefix="urls_"):
# Snekbox endpoints
- snekbox_eval_api = "http://snekbox.default.svc.cluster.local/eval"
+ snekbox_eval_api: str = "http://snekbox.default.svc.cluster.local/eval"
# Discord API
- discord_api = "https://discordapp.com/api/v7/"
+ discord_api: str = "https://discordapp.com/api/v7/"
# Misc endpoints
- bot_avatar = "https://raw.githubusercontent.com/python-discord/branding/main/logos/logo_circle/logo_circle.png"
-
- github_bot_repo = "https://github.com/python-discord/bot"
+ bot_avatar: str = "https://raw.githubusercontent.com/python-discord/branding/main/logos/logo_circle/logo_circle.png"
+ github_bot_repo: str = "https://github.com/python-discord/bot"
# Site
- site_api = "http://site.default.svc.cluster.local/api"
-
- paste_url = "https://paste.pythondiscord.com"
+ site_api: str = "http://site.default.svc.cluster.local/api"
+ paste_url: str = "https://paste.pythondiscord.com"
BaseURLs = _BaseURLs()
@@ -502,8 +453,8 @@ class _URLs(_BaseURLs):
discord_invite_api: str = "".join([BaseURLs.discord_api, "invites"])
# Base site vars
- connect_max_retries = 3
- connect_cooldown = 5
+ connect_max_retries: int = 3
+ connect_cooldown: int = 5
site_logs_view: str = "https://pythondiscord.com/staff/bot/logs"
@@ -511,59 +462,58 @@ class _URLs(_BaseURLs):
URLs = _URLs()
-class _Emojis(EnvConfig):
- EnvConfig.Config.env_prefix = "emojis_"
+class _Emojis(EnvConfig, env_prefix="emojis_"):
- badge_bug_hunter = "<:bug_hunter_lvl1:743882896372269137>"
- badge_bug_hunter_level_2 = "<:bug_hunter_lvl2:743882896611344505>"
- badge_early_supporter = "<:early_supporter:743882896909140058>"
- badge_hypesquad = "<:hypesquad_events:743882896892362873>"
- badge_hypesquad_balance = "<:hypesquad_balance:743882896460480625>"
- badge_hypesquad_bravery = "<:hypesquad_bravery:743882896745693335>"
- badge_hypesquad_brilliance = "<:hypesquad_brilliance:743882896938631248>"
- badge_partner = "<:partner:748666453242413136>"
- badge_staff = "<:discord_staff:743882896498098226>"
- badge_verified_bot_developer = "<:verified_bot_dev:743882897299210310>"
- badge_discord_certified_moderator = "<:discord_certified_moderator:1114130029547364434>"
- badge_bot_http_interactions = "<:bot_http_interactions:1114130379754975283>"
- badge_active_developer = "<:active_developer:1114130031036338176>"
- verified_bot = "<:verified_bot:811645219220750347>"
- bot = "<:bot:812712599464443914>"
+ badge_bug_hunter: str = "<:bug_hunter_lvl1:743882896372269137>"
+ badge_bug_hunter_level_2: str = "<:bug_hunter_lvl2:743882896611344505>"
+ badge_early_supporter: str = "<:early_supporter:743882896909140058>"
+ badge_hypesquad: str = "<:hypesquad_events:743882896892362873>"
+ badge_hypesquad_balance: str = "<:hypesquad_balance:743882896460480625>"
+ badge_hypesquad_bravery: str = "<:hypesquad_bravery:743882896745693335>"
+ badge_hypesquad_brilliance: str = "<:hypesquad_brilliance:743882896938631248>"
+ badge_partner: str = "<:partner:748666453242413136>"
+ badge_staff: str = "<:discord_staff:743882896498098226>"
+ badge_verified_bot_developer: str = "<:verified_bot_dev:743882897299210310>"
+ badge_discord_certified_moderator: str = "<:discord_certified_moderator:1114130029547364434>"
+ badge_bot_http_interactions: str = "<:bot_http_interactions:1114130379754975283>"
+ badge_active_developer: str = "<:active_developer:1114130031036338176>"
+ verified_bot: str = "<:verified_bot:811645219220750347>"
+ bot: str = "<:bot:812712599464443914>"
- defcon_shutdown = "<:defcondisabled:470326273952972810>"
- defcon_unshutdown = "<:defconenabled:470326274213150730>"
- defcon_update = "<:defconsettingsupdated:470326274082996224>"
+ defcon_shutdown: str = "<:defcondisabled:470326273952972810>"
+ defcon_unshutdown: str = "<:defconenabled:470326274213150730>"
+ defcon_update: str = "<:defconsettingsupdated:470326274082996224>"
- failmail = "<:failmail:633660039931887616>"
- failed_file = "<:failed_file:1073298441968562226>"
+ failmail: str = "<:failmail:633660039931887616>"
+ failed_file: str = "<:failed_file:1073298441968562226>"
- incident_actioned = "<:incident_actioned:714221559279255583>"
- incident_investigating = "<:incident_investigating:714224190928191551>"
- incident_unactioned = "<:incident_unactioned:714223099645526026>"
+ incident_actioned: str = "<:incident_actioned:714221559279255583>"
+ incident_investigating: str = "<:incident_investigating:714224190928191551>"
+ incident_unactioned: str = "<:incident_unactioned:714223099645526026>"
- status_dnd = "<:status_dnd:470326272082313216>"
- status_idle = "<:status_idle:470326266625785866>"
- status_offline = "<:status_offline:470326266537705472>"
- status_online = "<:status_online:470326272351010816>"
+ status_dnd: str = "<:status_dnd:470326272082313216>"
+ status_idle: str = "<:status_idle:470326266625785866>"
+ status_offline: str = "<:status_offline:470326266537705472>"
+ status_online: str = "<:status_online:470326272351010816>"
- ducky_dave = "<:ducky_dave:742058418692423772>"
+ ducky_dave: str = "<:ducky_dave:742058418692423772>"
- trashcan = "<:trashcan:637136429717389331>"
+ trashcan: str = "<:trashcan:637136429717389331>"
- bullet = "\u2022"
- check_mark = "\u2705"
- cross_mark = "\u274C"
- new = "\U0001F195"
- pencil = "\u270F"
+ bullet: str = "\u2022"
+ check_mark: str = "\u2705"
+ cross_mark: str = "\u274C"
+ new: str = "\U0001F195"
+ pencil: str = "\u270F"
- ok_hand = ":ok_hand:"
+ ok_hand: str = ":ok_hand:"
Emojis = _Emojis()
-class _Icons(EnvConfig):
- EnvConfig.Config.env_prefix = "icons_"
+class Icons:
+ """URLs to commonly used icons."""
crown_blurple = "https://cdn.discordapp.com/emojis/469964153289965568.png"
crown_green = "https://cdn.discordapp.com/emojis/469964154719961088.png"
@@ -617,15 +567,25 @@ class _Icons(EnvConfig):
voice_state_red = "https://cdn.discordapp.com/emojis/656899769905709076.png"
-Icons = _Icons()
+class Colours:
+ """Colour codes, mostly used to set discord.Embed colours."""
+ blue: int = 0x3775a8
+ bright_green: int = 0x01d277
+ orange: int = 0xe67e22
+ pink: int = 0xcf84e0
+ purple: int = 0xb734eb
+ soft_green: int = 0x68c290
+ soft_orange: int = 0xf9cb54
+ soft_red: int = 0xcd6d6d
+ white: int = 0xfffffe
+ yellow: int = 0xffd241
-class _Keys(EnvConfig):
- EnvConfig.Config.env_prefix = "api_keys_"
+class _Keys(EnvConfig, env_prefix="api_keys_"):
- github = ""
- site_api = ""
+ github: str = ""
+ site_api: str = ""
Keys = _Keys()
@@ -637,7 +597,7 @@ PROJECT_ROOT = os.path.abspath(os.path.join(BOT_DIR, os.pardir))
# Default role combinations
MODERATION_ROLES = Guild.moderation_roles
STAFF_ROLES = Guild.staff_roles
-STAFF_PARTNERS_COMMUNITY_ROLES = STAFF_ROLES + [Roles.partners, Roles.python_community]
+STAFF_PARTNERS_COMMUNITY_ROLES = STAFF_ROLES + (Roles.partners, Roles.python_community)
# Channel combinations
MODERATION_CHANNELS = Guild.moderation_channels
@@ -650,7 +610,7 @@ GIT_SHA = os.environ.get("GIT_SHA", "development")
# Bot replies
-NEGATIVE_REPLIES = [
+NEGATIVE_REPLIES = (
"Noooooo!!",
"Nope.",
"I'm sorry Dave, I'm afraid I can't do that.",
@@ -668,9 +628,9 @@ NEGATIVE_REPLIES = [
"NEGATORY.",
"Nuh-uh.",
"Not in my house!",
-]
+)
-POSITIVE_REPLIES = [
+POSITIVE_REPLIES = (
"Yep.",
"Absolutely!",
"Can do!",
@@ -688,9 +648,9 @@ POSITIVE_REPLIES = [
"Of course!",
"Aye aye, cap'n!",
"I'll allow it.",
-]
+)
-ERROR_REPLIES = [
+ERROR_REPLIES = (
"Please don't do that.",
"You have to stop.",
"Do you mind?",
@@ -701,4 +661,4 @@ ERROR_REPLIES = [
"Are you trying to kill me?",
"Noooooo!!",
"I can't believe you've done this",
-]
+)
diff --git a/bot/exts/filtering/_filter_lists/antispam.py b/bot/exts/filtering/_filter_lists/antispam.py
index 22f35f40e..f27412e1a 100644
--- a/bot/exts/filtering/_filter_lists/antispam.py
+++ b/bot/exts/filtering/_filter_lists/antispam.py
@@ -93,7 +93,7 @@ class AntispamList(UniquesListBase):
current_actions.pop("ping", None)
current_actions.pop("send_alert", None)
- new_infraction = current_actions[InfractionAndNotification.name].copy()
+ new_infraction = current_actions[InfractionAndNotification.name].model_copy()
# Smaller infraction value => higher in hierarchy.
if not current_infraction or new_infraction.infraction_type.value < current_infraction.value:
# Pick the first triggered filter for the reason, there's no good way to decide between them.
diff --git a/bot/exts/filtering/_filters/filter.py b/bot/exts/filtering/_filters/filter.py
index 6745e4f66..3f201cfde 100644
--- a/bot/exts/filtering/_filters/filter.py
+++ b/bot/exts/filtering/_filters/filter.py
@@ -31,7 +31,7 @@ class Filter(FieldRequiring):
self.updated_at = arrow.get(filter_data["updated_at"])
self.actions, self.validations = create_settings(filter_data["settings"], defaults=defaults)
if self.extra_fields_type:
- self.extra_fields = self.extra_fields_type.parse_obj(filter_data["additional_settings"])
+ self.extra_fields = self.extra_fields_type.model_validate(filter_data["additional_settings"])
else:
self.extra_fields = None
@@ -46,7 +46,7 @@ class Filter(FieldRequiring):
filter_settings = {}
if self.extra_fields:
- filter_settings = self.extra_fields.dict(exclude_unset=True)
+ filter_settings = self.extra_fields.model_dump(exclude_unset=True)
return settings, filter_settings
diff --git a/bot/exts/filtering/_settings.py b/bot/exts/filtering/_settings.py
index 766a5ea10..7005dd2d1 100644
--- a/bot/exts/filtering/_settings.py
+++ b/bot/exts/filtering/_settings.py
@@ -227,5 +227,5 @@ class Defaults(NamedTuple):
"""Return a dict representation of the stored fields across all entries."""
dict_ = {}
for settings in self:
- dict_ = reduce(operator.or_, (entry.dict() for entry in settings.values()), dict_)
+ dict_ = reduce(operator.or_, (entry.model_dump() for entry in settings.values()), dict_)
return dict_
diff --git a/bot/exts/filtering/_settings_types/actions/infraction_and_notification.py b/bot/exts/filtering/_settings_types/actions/infraction_and_notification.py
index f12538294..359aa7bc3 100644
--- a/bot/exts/filtering/_settings_types/actions/infraction_and_notification.py
+++ b/bot/exts/filtering/_settings_types/actions/infraction_and_notification.py
@@ -6,7 +6,7 @@ import discord.abc
from dateutil.relativedelta import relativedelta
from discord import Colour, Embed, Member, User
from discord.errors import Forbidden
-from pydantic import validator
+from pydantic import field_validator
from pydis_core.utils.logging import get_logger
from pydis_core.utils.members import get_or_fetch_member
@@ -151,7 +151,7 @@ class InfractionAndNotification(ActionEntry):
infraction_duration: InfractionDuration
infraction_channel: int
- @validator("infraction_type", pre=True)
+ @field_validator("infraction_type", mode="before")
@classmethod
def convert_infraction_name(cls, infr_type: str | Infraction) -> Infraction:
"""Convert the string to an Infraction by name."""
@@ -221,14 +221,14 @@ class InfractionAndNotification(ActionEntry):
"""
# Lower number -> higher in the hierarchy
if self.infraction_type is None:
- return other.copy()
+ return other.model_copy()
if other.infraction_type is None:
- return self.copy()
+ return self.model_copy()
if self.infraction_type.value < other.infraction_type.value:
- result = self.copy()
+ result = self.model_copy()
elif self.infraction_type.value > other.infraction_type.value:
- result = other.copy()
+ result = other.model_copy()
other = self
else:
now = arrow.utcnow().datetime
@@ -236,9 +236,9 @@ class InfractionAndNotification(ActionEntry):
other.infraction_duration is not None
and now + self.infraction_duration.value > now + other.infraction_duration.value
):
- result = self.copy()
+ result = self.model_copy()
else:
- result = other.copy()
+ result = other.model_copy()
other = self
# If the winner has no message but the loser does, copy the message to the winner.
diff --git a/bot/exts/filtering/_settings_types/actions/ping.py b/bot/exts/filtering/_settings_types/actions/ping.py
index fa3e2224f..4b38a19f3 100644
--- a/bot/exts/filtering/_settings_types/actions/ping.py
+++ b/bot/exts/filtering/_settings_types/actions/ping.py
@@ -1,6 +1,6 @@
from typing import ClassVar, Self
-from pydantic import validator
+from pydantic import field_validator
from bot.exts.filtering._filter_context import FilterContext
from bot.exts.filtering._settings_types.settings_entry import ActionEntry
@@ -25,7 +25,7 @@ class Ping(ActionEntry):
guild_pings: set[str]
dm_pings: set[str]
- @validator("*", pre=True)
+ @field_validator("*", mode="before")
@classmethod
def init_sequence_if_none(cls, pings: list[str] | None) -> list[str]:
"""Initialize an empty sequence if the value is None."""
diff --git a/bot/exts/filtering/_settings_types/settings_entry.py b/bot/exts/filtering/_settings_types/settings_entry.py
index a3a2cbe1a..1cb9d9f2a 100644
--- a/bot/exts/filtering/_settings_types/settings_entry.py
+++ b/bot/exts/filtering/_settings_types/settings_entry.py
@@ -28,7 +28,7 @@ class SettingsEntry(BaseModel, FieldRequiring):
def __init__(self, defaults: SettingsEntry | None = None, /, **data):
overrides = set()
if defaults:
- defaults_dict = defaults.dict()
+ defaults_dict = defaults.model_dump()
for field_name, field_value in list(data.items()):
if field_value is None:
data[field_name] = defaults_dict[field_name]
diff --git a/bot/exts/filtering/_settings_types/validations/bypass_roles.py b/bot/exts/filtering/_settings_types/validations/bypass_roles.py
index 50fb1e650..0ddb2fdb5 100644
--- a/bot/exts/filtering/_settings_types/validations/bypass_roles.py
+++ b/bot/exts/filtering/_settings_types/validations/bypass_roles.py
@@ -1,6 +1,8 @@
-from typing import ClassVar, Union
+from collections.abc import Sequence
+from typing import ClassVar
from discord import Member
+from pydantic import field_validator
from bot.exts.filtering._filter_context import FilterContext
from bot.exts.filtering._settings_types.settings_entry import ValidationEntry
@@ -12,7 +14,26 @@ class RoleBypass(ValidationEntry):
name: ClassVar[str] = "bypass_roles"
description: ClassVar[str] = "A list of role IDs or role names. Users with these roles will not trigger the filter."
- bypass_roles: set[Union[int, str]] # noqa: UP007
+ bypass_roles: set[int | str]
+
+ @field_validator("bypass_roles", mode="before")
+ @classmethod
+ def init_if_bypass_roles_none(cls, bypass_roles: Sequence[int | str] | None) -> Sequence[int | str]:
+ """
+ Initialize an empty sequence if the value is None.
+
+ This also coerces each element of bypass_roles to an int, if possible.
+ """
+ if bypass_roles is None:
+ return []
+
+ def _coerce_to_int(input: int | str) -> int | str:
+ try:
+ return int(input)
+ except ValueError:
+ return input
+
+ return map(_coerce_to_int, bypass_roles)
def triggers_on(self, ctx: FilterContext) -> bool:
"""Return whether the filter should be triggered on this user given their roles."""
diff --git a/bot/exts/filtering/_settings_types/validations/channel_scope.py b/bot/exts/filtering/_settings_types/validations/channel_scope.py
index 1880ae27e..3d31131af 100644
--- a/bot/exts/filtering/_settings_types/validations/channel_scope.py
+++ b/bot/exts/filtering/_settings_types/validations/channel_scope.py
@@ -1,6 +1,7 @@
-from typing import ClassVar, Union
+from collections.abc import Sequence
+from typing import ClassVar
-from pydantic import validator
+from pydantic import field_validator
from bot.exts.filtering._filter_context import FilterContext
from bot.exts.filtering._settings_types.settings_entry import ValidationEntry
@@ -29,20 +30,29 @@ class ChannelScope(ValidationEntry):
)
}
- # NOTE: Don't change this to use the new 3.10 union syntax unless you ensure Pydantic type validation and coercion
- # work properly. At the time of writing this code there's a difference.
- disabled_channels: set[Union[int, str]] # noqa: UP007
- disabled_categories: set[Union[int, str]] # noqa: UP007
- enabled_channels: set[Union[int, str]] # noqa: UP007
- enabled_categories: set[Union[int, str]] # noqa: UP007
+ disabled_channels: set[int | str]
+ disabled_categories: set[int | str]
+ enabled_channels: set[int | str]
+ enabled_categories: set[int | str]
- @validator("*", pre=True)
+ @field_validator("*", mode="before")
@classmethod
- def init_if_sequence_none(cls, sequence: list[str] | None) -> list[str]:
- """Initialize an empty sequence if the value is None."""
+ def init_if_sequence_none(cls, sequence: Sequence[int | str] | None) -> Sequence[int | str]:
+ """
+ Initialize an empty sequence if the value is None.
+
+ This also coerces each element of sequence to an int, if possible.
+ """
if sequence is None:
return []
- return sequence
+
+ def _coerce_to_int(input: int | str) -> int | str:
+ try:
+ return int(input)
+ except ValueError:
+ return input
+
+ return map(_coerce_to_int, sequence)
def triggers_on(self, ctx: FilterContext) -> bool:
"""
diff --git a/bot/exts/filtering/_ui/filter.py b/bot/exts/filtering/_ui/filter.py
index 4300de19c..6927a5d41 100644
--- a/bot/exts/filtering/_ui/filter.py
+++ b/bot/exts/filtering/_ui/filter.py
@@ -34,7 +34,7 @@ def build_filter_repr_dict(
default_setting_values = {}
for settings_group in filter_list[list_type].defaults:
for _, setting in settings_group.items():
- default_setting_values.update(to_serializable(setting.dict(), ui_repr=True))
+ default_setting_values.update(to_serializable(setting.model_dump(), ui_repr=True))
# Add overrides. It's done in this way to preserve field order, since the filter won't have all settings.
total_values = {}
@@ -47,7 +47,7 @@ def build_filter_repr_dict(
# Add the filter-specific settings.
if filter_type.extra_fields_type:
# This iterates over the default values of the extra fields model.
- for name, value in filter_type.extra_fields_type().dict().items():
+ for name, value in filter_type.extra_fields_type().model_dump().items():
if name not in extra_fields_overrides or repr_equals(extra_fields_overrides[name], value):
total_values[f"{filter_type.name}/{name}"] = value
else:
@@ -287,7 +287,7 @@ class FilterEditView(EditBaseView):
if "/" in setting_name:
filter_name, setting_name = setting_name.split("/", maxsplit=1)
dict_to_edit = self.filter_settings_overrides
- default_value = self.filter_type.extra_fields_type().dict()[setting_name]
+ default_value = self.filter_type.extra_fields_type().model_dump()[setting_name]
else:
dict_to_edit = self.settings_overrides
default_value = self.filter_list[self.list_type].default(setting_name)
diff --git a/bot/exts/filtering/_ui/filter_list.py b/bot/exts/filtering/_ui/filter_list.py
index 062975ad7..2858817e3 100644
--- a/bot/exts/filtering/_ui/filter_list.py
+++ b/bot/exts/filtering/_ui/filter_list.py
@@ -50,7 +50,7 @@ def build_filterlist_repr_dict(filter_list: FilterList, list_type: ListType, new
default_setting_values = {}
for settings_group in filter_list[list_type].defaults:
for _, setting in settings_group.items():
- default_setting_values.update(to_serializable(setting.dict(), ui_repr=True))
+ default_setting_values.update(to_serializable(setting.model_dump(), ui_repr=True))
# Add new values. It's done in this way to preserve field order, since the new_values won't have all settings.
total_values = {}
diff --git a/bot/exts/filtering/_utils.py b/bot/exts/filtering/_utils.py
index e109a47ee..944cf3837 100644
--- a/bot/exts/filtering/_utils.py
+++ b/bot/exts/filtering/_utils.py
@@ -7,7 +7,7 @@ import pkgutil
import types
from abc import ABC, abstractmethod
from collections import defaultdict
-from collections.abc import Iterable
+from collections.abc import Callable, Iterable
from dataclasses import dataclass
from functools import cache
from typing import Any, Self, TypeVar, Union, get_args, get_origin
@@ -15,6 +15,7 @@ from typing import Any, Self, TypeVar, Union, get_args, get_origin
import discord
import regex
from discord.ext.commands import Command
+from pydantic_core import core_schema
import bot
from bot.bot import Bot
@@ -252,12 +253,16 @@ class CustomIOField:
self.value = self.process_value(value)
@classmethod
- def __get_validators__(cls):
+ def __get_pydantic_core_schema__(
+ cls,
+ _source: type[Any],
+ _handler: Callable[[Any], core_schema.CoreSchema],
+ ) -> core_schema.CoreSchema:
"""Boilerplate for Pydantic."""
- yield cls.validate
+ return core_schema.general_plain_validator_function(cls.validate)
@classmethod
- def validate(cls, v: Any) -> Self:
+ def validate(cls, v: Any, _info: core_schema.ValidationInfo) -> Self:
"""Takes the given value and returns a class instance with that value."""
if isinstance(v, CustomIOField):
return cls(v.value)
diff --git a/bot/exts/filtering/filtering.py b/bot/exts/filtering/filtering.py
index 2b7ad2ff3..bedd9958f 100644
--- a/bot/exts/filtering/filtering.py
+++ b/bot/exts/filtering/filtering.py
@@ -181,7 +181,7 @@ class Filtering(Cog):
extra_fields_type,
type_hints[field_name]
)
- for field_name in extra_fields_type.__fields__
+ for field_name in extra_fields_type.model_fields
}
async def schedule_offending_messages_deletion(self) -> None:
@@ -754,7 +754,7 @@ class Filtering(Cog):
setting_values = {}
for settings_group in filter_list[list_type].defaults:
for _, setting in settings_group.items():
- setting_values.update(to_serializable(setting.dict(), ui_repr=True))
+ setting_values.update(to_serializable(setting.model_dump(), ui_repr=True))
embed = Embed(colour=Colour.blue())
populate_embed_from_dict(embed, setting_values)
@@ -1239,7 +1239,13 @@ class Filtering(Cog):
for current_settings in (filter_.actions, filter_.validations):
if current_settings:
for setting_entry in current_settings.values():
- settings.update({setting: None for setting in setting_entry.dict() if setting not in settings})
+ settings.update(
+ {
+ setting: None
+ for setting in setting_entry.model_dump()
+ if setting not in settings
+ }
+ )
# Even though the list ID remains unchanged, it still needs to be provided for correct serializer validation.
list_id = filter_list[list_type].id
@@ -1295,7 +1301,7 @@ class Filtering(Cog):
if not (differ_by_default <= override_matches): # The overrides didn't cover for the default mismatches.
return False
- filter_settings = filter_.extra_fields.dict() if filter_.extra_fields else {}
+ filter_settings = filter_.extra_fields.model_dump() if filter_.extra_fields else {}
# If the dict changes then some fields were not the same.
return (filter_settings | filter_settings_query) == filter_settings
diff --git a/bot/exts/recruitment/talentpool/_api.py b/bot/exts/recruitment/talentpool/_api.py
index e12111de5..f7b243209 100644
--- a/bot/exts/recruitment/talentpool/_api.py
+++ b/bot/exts/recruitment/talentpool/_api.py
@@ -1,6 +1,6 @@
from datetime import datetime
-from pydantic import BaseModel, Field, parse_obj_as
+from pydantic import BaseModel, Field, TypeAdapter
from pydis_core.site_api import APIClient
@@ -50,13 +50,13 @@ class NominationAPI:
params["user__id"] = str(user_id)
data = await self.site_api.get("bot/nominations", params=params)
- nominations = parse_obj_as(list[Nomination], data)
+ nominations = TypeAdapter(list[Nomination]).validate_python(data)
return nominations
async def get_nomination(self, nomination_id: int) -> Nomination:
"""Fetch a nomination by ID."""
data = await self.site_api.get(f"bot/nominations/{nomination_id}")
- nomination = Nomination.parse_obj(data)
+ nomination = Nomination.model_validate(data)
return nomination
async def edit_nomination(
@@ -84,7 +84,7 @@ class NominationAPI:
data["thread_id"] = thread_id
result = await self.site_api.patch(f"bot/nominations/{nomination_id}", json=data)
- return Nomination.parse_obj(result)
+ return Nomination.model_validate(result)
async def edit_nomination_entry(
self,
@@ -96,7 +96,7 @@ class NominationAPI:
"""Edit a nomination entry."""
data = {"actor": actor_id, "reason": reason}
result = await self.site_api.patch(f"bot/nominations/{nomination_id}", json=data)
- return Nomination.parse_obj(result)
+ return Nomination.model_validate(result)
async def post_nomination(
self,
@@ -111,7 +111,7 @@ class NominationAPI:
"user": user_id,
}
result = await self.site_api.post("bot/nominations", json=data)
- return Nomination.parse_obj(result)
+ return Nomination.model_validate(result)
async def get_activity(
self,
diff --git a/botstrap.py b/botstrap.py
index c57a254a3..7a9d94d8b 100644
--- a/botstrap.py
+++ b/botstrap.py
@@ -176,7 +176,7 @@ with DiscordClient(guild_id=GUILD_ID) as discord_client:
all_roles = discord_client.get_all_roles()
- for role_name in _Roles.__fields__:
+ for role_name in _Roles.model_fields:
role_id = all_roles.get(role_name, None)
if not role_id:
@@ -209,7 +209,7 @@ with DiscordClient(guild_id=GUILD_ID) as discord_client:
python_help_channel_id = discord_client.create_forum_channel(python_help_channel_name, python_help_category_id)
all_channels[PYTHON_HELP_CHANNEL_NAME] = python_help_channel_id
- for channel_name in _Channels.__fields__:
+ for channel_name in _Channels.model_fields:
channel_id = all_channels.get(channel_name, None)
if not channel_id:
log.warning(
@@ -222,7 +222,7 @@ with DiscordClient(guild_id=GUILD_ID) as discord_client:
config_str += "\n#Categories\n"
- for category_name in _Categories.__fields__:
+ for category_name in _Categories.model_fields:
category_id = all_categories.get(category_name, None)
if not category_id:
log.warning(
diff --git a/poetry.lock b/poetry.lock
index e45697329..b467300fe 100644
--- a/poetry.lock
+++ b/poetry.lock
@@ -137,6 +137,17 @@ files = [
frozenlist = ">=1.1.0"
[[package]]
+name = "annotated-types"
+version = "0.5.0"
+description = "Reusable constraint types to use with typing.Annotated"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "annotated_types-0.5.0-py3-none-any.whl", hash = "sha256:58da39888f92c276ad970249761ebea80ba544b77acddaa1a4d6cf78287d45fd"},
+ {file = "annotated_types-0.5.0.tar.gz", hash = "sha256:47cdc3490d9ac1506ce92c7aaa76c579dc3509ff11e098fc867e5130ab7be802"},
+]
+
+[[package]]
name = "anyio"
version = "3.7.1"
description = "High level compatibility layer for multiple asynchronous event loop implementations"
@@ -190,13 +201,13 @@ fakeredis = ["fakeredis[lua] (>=1.7.1)"]
[[package]]
name = "async-timeout"
-version = "4.0.2"
+version = "4.0.3"
description = "Timeout context manager for asyncio programs"
optional = false
-python-versions = ">=3.6"
+python-versions = ">=3.7"
files = [
- {file = "async-timeout-4.0.2.tar.gz", hash = "sha256:2163e1640ddb52b7a8c80d0a67a08587e5d245cc9c553a74a847056bc2976b15"},
- {file = "async_timeout-4.0.2-py3-none-any.whl", hash = "sha256:8ca1e4fcf50d07413d66d1a5e416e42cfdf5851c981d679a09851a6853383b3c"},
+ {file = "async-timeout-4.0.3.tar.gz", hash = "sha256:4640d96be84d82d02ed59ea2b7105a0f7b33abe8703703cd0ab0bf87c427522f"},
+ {file = "async_timeout-4.0.3-py3-none-any.whl", hash = "sha256:7405140ff1230c310e51dc27b3145b9092d659ce68ff733fb0cefe3ee42be028"},
]
[[package]]
@@ -931,13 +942,10 @@ files = [
{file = "lxml-4.9.3-cp27-cp27m-macosx_11_0_x86_64.whl", hash = "sha256:b0a545b46b526d418eb91754565ba5b63b1c0b12f9bd2f808c852d9b4b2f9b5c"},
{file = "lxml-4.9.3-cp27-cp27m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:075b731ddd9e7f68ad24c635374211376aa05a281673ede86cbe1d1b3455279d"},
{file = "lxml-4.9.3-cp27-cp27m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:1e224d5755dba2f4a9498e150c43792392ac9b5380aa1b845f98a1618c94eeef"},
- {file = "lxml-4.9.3-cp27-cp27m-win32.whl", hash = "sha256:2c74524e179f2ad6d2a4f7caf70e2d96639c0954c943ad601a9e146c76408ed7"},
- {file = "lxml-4.9.3-cp27-cp27m-win_amd64.whl", hash = "sha256:4f1026bc732b6a7f96369f7bfe1a4f2290fb34dce00d8644bc3036fb351a4ca1"},
{file = "lxml-4.9.3-cp27-cp27mu-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c0781a98ff5e6586926293e59480b64ddd46282953203c76ae15dbbbf302e8bb"},
{file = "lxml-4.9.3-cp27-cp27mu-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:cef2502e7e8a96fe5ad686d60b49e1ab03e438bd9123987994528febd569868e"},
{file = "lxml-4.9.3-cp310-cp310-macosx_11_0_x86_64.whl", hash = "sha256:b86164d2cff4d3aaa1f04a14685cbc072efd0b4f99ca5708b2ad1b9b5988a991"},
{file = "lxml-4.9.3-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:42871176e7896d5d45138f6d28751053c711ed4d48d8e30b498da155af39aebd"},
- {file = "lxml-4.9.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:ae8b9c6deb1e634ba4f1930eb67ef6e6bf6a44b6eb5ad605642b2d6d5ed9ce3c"},
{file = "lxml-4.9.3-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:411007c0d88188d9f621b11d252cce90c4a2d1a49db6c068e3c16422f306eab8"},
{file = "lxml-4.9.3-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:cd47b4a0d41d2afa3e58e5bf1f62069255aa2fd6ff5ee41604418ca925911d76"},
{file = "lxml-4.9.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:0e2cb47860da1f7e9a5256254b74ae331687b9672dfa780eed355c4c9c3dbd23"},
@@ -946,7 +954,6 @@ files = [
{file = "lxml-4.9.3-cp310-cp310-win_amd64.whl", hash = "sha256:97047f0d25cd4bcae81f9ec9dc290ca3e15927c192df17331b53bebe0e3ff96d"},
{file = "lxml-4.9.3-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:1f447ea5429b54f9582d4b955f5f1985f278ce5cf169f72eea8afd9502973dd5"},
{file = "lxml-4.9.3-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:57d6ba0ca2b0c462f339640d22882acc711de224d769edf29962b09f77129cbf"},
- {file = "lxml-4.9.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:9767e79108424fb6c3edf8f81e6730666a50feb01a328f4a016464a5893f835a"},
{file = "lxml-4.9.3-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:71c52db65e4b56b8ddc5bb89fb2e66c558ed9d1a74a45ceb7dcb20c191c3df2f"},
{file = "lxml-4.9.3-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:d73d8ecf8ecf10a3bd007f2192725a34bd62898e8da27eb9d32a58084f93962b"},
{file = "lxml-4.9.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:0a3d3487f07c1d7f150894c238299934a2a074ef590b583103a45002035be120"},
@@ -966,7 +973,6 @@ files = [
{file = "lxml-4.9.3-cp36-cp36m-macosx_11_0_x86_64.whl", hash = "sha256:64f479d719dc9f4c813ad9bb6b28f8390360660b73b2e4beb4cb0ae7104f1c12"},
{file = "lxml-4.9.3-cp36-cp36m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:dd708cf4ee4408cf46a48b108fb9427bfa00b9b85812a9262b5c668af2533ea5"},
{file = "lxml-4.9.3-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5c31c7462abdf8f2ac0577d9f05279727e698f97ecbb02f17939ea99ae8daa98"},
- {file = "lxml-4.9.3-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:e3cd95e10c2610c360154afdc2f1480aea394f4a4f1ea0a5eacce49640c9b190"},
{file = "lxml-4.9.3-cp36-cp36m-manylinux_2_28_x86_64.whl", hash = "sha256:4930be26af26ac545c3dffb662521d4e6268352866956672231887d18f0eaab2"},
{file = "lxml-4.9.3-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4aec80cde9197340bc353d2768e2a75f5f60bacda2bab72ab1dc499589b3878c"},
{file = "lxml-4.9.3-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:14e019fd83b831b2e61baed40cab76222139926b1fb5ed0e79225bc0cae14584"},
@@ -976,7 +982,6 @@ files = [
{file = "lxml-4.9.3-cp36-cp36m-win_amd64.whl", hash = "sha256:bef4e656f7d98aaa3486d2627e7d2df1157d7e88e7efd43a65aa5dd4714916cf"},
{file = "lxml-4.9.3-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:46f409a2d60f634fe550f7133ed30ad5321ae2e6630f13657fb9479506b00601"},
{file = "lxml-4.9.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:4c28a9144688aef80d6ea666c809b4b0e50010a2aca784c97f5e6bf143d9f129"},
- {file = "lxml-4.9.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:141f1d1a9b663c679dc524af3ea1773e618907e96075262726c7612c02b149a4"},
{file = "lxml-4.9.3-cp37-cp37m-manylinux_2_28_x86_64.whl", hash = "sha256:53ace1c1fd5a74ef662f844a0413446c0629d151055340e9893da958a374f70d"},
{file = "lxml-4.9.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:17a753023436a18e27dd7769e798ce302963c236bc4114ceee5b25c18c52c693"},
{file = "lxml-4.9.3-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:7d298a1bd60c067ea75d9f684f5f3992c9d6766fadbc0bcedd39750bf344c2f4"},
@@ -986,7 +991,6 @@ files = [
{file = "lxml-4.9.3-cp37-cp37m-win_amd64.whl", hash = "sha256:120fa9349a24c7043854c53cae8cec227e1f79195a7493e09e0c12e29f918e52"},
{file = "lxml-4.9.3-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:4d2d1edbca80b510443f51afd8496be95529db04a509bc8faee49c7b0fb6d2cc"},
{file = "lxml-4.9.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:8d7e43bd40f65f7d97ad8ef5c9b1778943d02f04febef12def25f7583d19baac"},
- {file = "lxml-4.9.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:71d66ee82e7417828af6ecd7db817913cb0cf9d4e61aa0ac1fde0583d84358db"},
{file = "lxml-4.9.3-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:6fc3c450eaa0b56f815c7b62f2b7fba7266c4779adcf1cece9e6deb1de7305ce"},
{file = "lxml-4.9.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:65299ea57d82fb91c7f019300d24050c4ddeb7c5a190e076b5f48a2b43d19c42"},
{file = "lxml-4.9.3-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:eadfbbbfb41b44034a4c757fd5d70baccd43296fb894dba0295606a7cf3124aa"},
@@ -996,7 +1000,6 @@ files = [
{file = "lxml-4.9.3-cp38-cp38-win_amd64.whl", hash = "sha256:92af161ecbdb2883c4593d5ed4815ea71b31fafd7fd05789b23100d081ecac96"},
{file = "lxml-4.9.3-cp39-cp39-macosx_11_0_x86_64.whl", hash = "sha256:9bb6ad405121241e99a86efff22d3ef469024ce22875a7ae045896ad23ba2340"},
{file = "lxml-4.9.3-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:8ed74706b26ad100433da4b9d807eae371efaa266ffc3e9191ea436087a9d6a7"},
- {file = "lxml-4.9.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:fbf521479bcac1e25a663df882c46a641a9bff6b56dc8b0fafaebd2f66fb231b"},
{file = "lxml-4.9.3-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:303bf1edce6ced16bf67a18a1cf8339d0db79577eec5d9a6d4a80f0fb10aa2da"},
{file = "lxml-4.9.3-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:5515edd2a6d1a5a70bfcdee23b42ec33425e405c5b351478ab7dc9347228f96e"},
{file = "lxml-4.9.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:690dafd0b187ed38583a648076865d8c229661ed20e48f2335d68e2cf7dc829d"},
@@ -1007,16 +1010,13 @@ files = [
{file = "lxml-4.9.3-cp39-cp39-win_amd64.whl", hash = "sha256:4dd9a263e845a72eacb60d12401e37c616438ea2e5442885f65082c276dfb2b2"},
{file = "lxml-4.9.3-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:6689a3d7fd13dc687e9102a27e98ef33730ac4fe37795d5036d18b4d527abd35"},
{file = "lxml-4.9.3-pp37-pypy37_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:f6bdac493b949141b733c5345b6ba8f87a226029cbabc7e9e121a413e49441e0"},
- {file = "lxml-4.9.3-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:05186a0f1346ae12553d66df1cfce6f251589fea3ad3da4f3ef4e34b2d58c6a3"},
{file = "lxml-4.9.3-pp37-pypy37_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:c2006f5c8d28dee289f7020f721354362fa304acbaaf9745751ac4006650254b"},
{file = "lxml-4.9.3-pp38-pypy38_pp73-macosx_11_0_x86_64.whl", hash = "sha256:5c245b783db29c4e4fbbbfc9c5a78be496c9fea25517f90606aa1f6b2b3d5f7b"},
{file = "lxml-4.9.3-pp38-pypy38_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:4fb960a632a49f2f089d522f70496640fdf1218f1243889da3822e0a9f5f3ba7"},
- {file = "lxml-4.9.3-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:50670615eaf97227d5dc60de2dc99fb134a7130d310d783314e7724bf163f75d"},
{file = "lxml-4.9.3-pp38-pypy38_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:9719fe17307a9e814580af1f5c6e05ca593b12fb7e44fe62450a5384dbf61b4b"},
{file = "lxml-4.9.3-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:3331bece23c9ee066e0fb3f96c61322b9e0f54d775fccefff4c38ca488de283a"},
{file = "lxml-4.9.3-pp39-pypy39_pp73-macosx_11_0_x86_64.whl", hash = "sha256:ed667f49b11360951e201453fc3967344d0d0263aa415e1619e85ae7fd17b4e0"},
{file = "lxml-4.9.3-pp39-pypy39_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:8b77946fd508cbf0fccd8e400a7f71d4ac0e1595812e66025bac475a8e811694"},
- {file = "lxml-4.9.3-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:e4da8ca0c0c0aea88fd46be8e44bd49716772358d648cce45fe387f7b92374a7"},
{file = "lxml-4.9.3-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:fe4bda6bd4340caa6e5cf95e73f8fea5c4bfc55763dd42f1b50a94c1b4a2fbd4"},
{file = "lxml-4.9.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:f3df3db1d336b9356dd3112eae5f5c2b8b377f3bc826848567f10bfddfee77e9"},
{file = "lxml-4.9.3.tar.gz", hash = "sha256:48628bd53a426c9eb9bc066a923acaa0878d1e86129fd5359aee99285f4eed9c"},
@@ -1206,18 +1206,18 @@ test = ["docutils", "mypy", "pytest-cov", "pytest-pycodestyle", "pytest-runner"]
[[package]]
name = "platformdirs"
-version = "3.9.1"
+version = "3.10.0"
description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"."
optional = false
python-versions = ">=3.7"
files = [
- {file = "platformdirs-3.9.1-py3-none-any.whl", hash = "sha256:ad8291ae0ae5072f66c16945166cb11c63394c7a3ad1b1bc9828ca3162da8c2f"},
- {file = "platformdirs-3.9.1.tar.gz", hash = "sha256:1b42b450ad933e981d56e59f1b97495428c9bd60698baab9f3eb3d00d5822421"},
+ {file = "platformdirs-3.10.0-py3-none-any.whl", hash = "sha256:d7c24979f292f916dc9cbf8648319032f551ea8c49a4c9bf2fb556a02070ec1d"},
+ {file = "platformdirs-3.10.0.tar.gz", hash = "sha256:b45696dab2d7cc691a3226759c0d3b00c47c8b6e293d96f6436f733303f77f6d"},
]
[package.extras]
-docs = ["furo (>=2023.5.20)", "proselint (>=0.13)", "sphinx (>=7.0.1)", "sphinx-autodoc-typehints (>=1.23,!=1.23.4)"]
-test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.3.1)", "pytest-cov (>=4.1)", "pytest-mock (>=3.10)"]
+docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.1)", "sphinx-autodoc-typehints (>=1.24)"]
+test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.4)", "pytest-cov (>=4.1)", "pytest-mock (>=3.11.1)"]
[[package]]
name = "pluggy"
@@ -1375,56 +1375,150 @@ files = [
[[package]]
name = "pydantic"
-version = "1.10.9"
-description = "Data validation and settings management using python type hints"
+version = "2.0.3"
+description = "Data validation using Python type hints"
optional = false
python-versions = ">=3.7"
files = [
- {file = "pydantic-1.10.9-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e692dec4a40bfb40ca530e07805b1208c1de071a18d26af4a2a0d79015b352ca"},
- {file = "pydantic-1.10.9-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:3c52eb595db83e189419bf337b59154bdcca642ee4b2a09e5d7797e41ace783f"},
- {file = "pydantic-1.10.9-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:939328fd539b8d0edf244327398a667b6b140afd3bf7e347cf9813c736211896"},
- {file = "pydantic-1.10.9-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b48d3d634bca23b172f47f2335c617d3fcb4b3ba18481c96b7943a4c634f5c8d"},
- {file = "pydantic-1.10.9-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:f0b7628fb8efe60fe66fd4adadd7ad2304014770cdc1f4934db41fe46cc8825f"},
- {file = "pydantic-1.10.9-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:e1aa5c2410769ca28aa9a7841b80d9d9a1c5f223928ca8bec7e7c9a34d26b1d4"},
- {file = "pydantic-1.10.9-cp310-cp310-win_amd64.whl", hash = "sha256:eec39224b2b2e861259d6f3c8b6290d4e0fbdce147adb797484a42278a1a486f"},
- {file = "pydantic-1.10.9-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d111a21bbbfd85c17248130deac02bbd9b5e20b303338e0dbe0faa78330e37e0"},
- {file = "pydantic-1.10.9-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2e9aec8627a1a6823fc62fb96480abe3eb10168fd0d859ee3d3b395105ae19a7"},
- {file = "pydantic-1.10.9-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:07293ab08e7b4d3c9d7de4949a0ea571f11e4557d19ea24dd3ae0c524c0c334d"},
- {file = "pydantic-1.10.9-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7ee829b86ce984261d99ff2fd6e88f2230068d96c2a582f29583ed602ef3fc2c"},
- {file = "pydantic-1.10.9-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:4b466a23009ff5cdd7076eb56aca537c745ca491293cc38e72bf1e0e00de5b91"},
- {file = "pydantic-1.10.9-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:7847ca62e581e6088d9000f3c497267868ca2fa89432714e21a4fb33a04d52e8"},
- {file = "pydantic-1.10.9-cp311-cp311-win_amd64.whl", hash = "sha256:7845b31959468bc5b78d7b95ec52fe5be32b55d0d09983a877cca6aedc51068f"},
- {file = "pydantic-1.10.9-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:517a681919bf880ce1dac7e5bc0c3af1e58ba118fd774da2ffcd93c5f96eaece"},
- {file = "pydantic-1.10.9-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:67195274fd27780f15c4c372f4ba9a5c02dad6d50647b917b6a92bf00b3d301a"},
- {file = "pydantic-1.10.9-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2196c06484da2b3fded1ab6dbe182bdabeb09f6318b7fdc412609ee2b564c49a"},
- {file = "pydantic-1.10.9-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:6257bb45ad78abacda13f15bde5886efd6bf549dd71085e64b8dcf9919c38b60"},
- {file = "pydantic-1.10.9-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:3283b574b01e8dbc982080d8287c968489d25329a463b29a90d4157de4f2baaf"},
- {file = "pydantic-1.10.9-cp37-cp37m-win_amd64.whl", hash = "sha256:5f8bbaf4013b9a50e8100333cc4e3fa2f81214033e05ac5aa44fa24a98670a29"},
- {file = "pydantic-1.10.9-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:b9cd67fb763248cbe38f0593cd8611bfe4b8ad82acb3bdf2b0898c23415a1f82"},
- {file = "pydantic-1.10.9-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:f50e1764ce9353be67267e7fd0da08349397c7db17a562ad036aa7c8f4adfdb6"},
- {file = "pydantic-1.10.9-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:73ef93e5e1d3c8e83f1ff2e7fdd026d9e063c7e089394869a6e2985696693766"},
- {file = "pydantic-1.10.9-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:128d9453d92e6e81e881dd7e2484e08d8b164da5507f62d06ceecf84bf2e21d3"},
- {file = "pydantic-1.10.9-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:ad428e92ab68798d9326bb3e5515bc927444a3d71a93b4a2ca02a8a5d795c572"},
- {file = "pydantic-1.10.9-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:fab81a92f42d6d525dd47ced310b0c3e10c416bbfae5d59523e63ea22f82b31e"},
- {file = "pydantic-1.10.9-cp38-cp38-win_amd64.whl", hash = "sha256:963671eda0b6ba6926d8fc759e3e10335e1dc1b71ff2a43ed2efd6996634dafb"},
- {file = "pydantic-1.10.9-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:970b1bdc6243ef663ba5c7e36ac9ab1f2bfecb8ad297c9824b542d41a750b298"},
- {file = "pydantic-1.10.9-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:7e1d5290044f620f80cf1c969c542a5468f3656de47b41aa78100c5baa2b8276"},
- {file = "pydantic-1.10.9-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:83fcff3c7df7adff880622a98022626f4f6dbce6639a88a15a3ce0f96466cb60"},
- {file = "pydantic-1.10.9-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0da48717dc9495d3a8f215e0d012599db6b8092db02acac5e0d58a65248ec5bc"},
- {file = "pydantic-1.10.9-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:0a2aabdc73c2a5960e87c3ffebca6ccde88665616d1fd6d3db3178ef427b267a"},
- {file = "pydantic-1.10.9-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:9863b9420d99dfa9c064042304868e8ba08e89081428a1c471858aa2af6f57c4"},
- {file = "pydantic-1.10.9-cp39-cp39-win_amd64.whl", hash = "sha256:e7c9900b43ac14110efa977be3da28931ffc74c27e96ee89fbcaaf0b0fe338e1"},
- {file = "pydantic-1.10.9-py3-none-any.whl", hash = "sha256:6cafde02f6699ce4ff643417d1a9223716ec25e228ddc3b436fe7e2d25a1f305"},
- {file = "pydantic-1.10.9.tar.gz", hash = "sha256:95c70da2cd3b6ddf3b9645ecaa8d98f3d80c606624b6d245558d202cd23ea3be"},
+ {file = "pydantic-2.0.3-py3-none-any.whl", hash = "sha256:614eb3321eb600c81899a88fa9858b008e3c79e0d4f1b49ab1f516b4b0c27cfb"},
+ {file = "pydantic-2.0.3.tar.gz", hash = "sha256:94f13e0dcf139a5125e88283fc999788d894e14ed90cf478bcc2ee50bd4fc630"},
]
[package.dependencies]
-python-dotenv = {version = ">=0.10.4", optional = true, markers = "extra == \"dotenv\""}
-typing-extensions = ">=4.2.0"
+annotated-types = ">=0.4.0"
+pydantic-core = "2.3.0"
+typing-extensions = ">=4.6.1"
[package.extras]
-dotenv = ["python-dotenv (>=0.10.4)"]
-email = ["email-validator (>=1.0.3)"]
+email = ["email-validator (>=2.0.0)"]
+
+[[package]]
+name = "pydantic-core"
+version = "2.3.0"
+description = ""
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "pydantic_core-2.3.0-cp310-cp310-macosx_10_7_x86_64.whl", hash = "sha256:4542c98b8364b976593703a2dda97377433b102f380b61bc3a2cbc2fbdae1d1f"},
+ {file = "pydantic_core-2.3.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9342de50824b40f55d2600f66c6f9a91a3a24851eca39145a749a3dc804ee599"},
+ {file = "pydantic_core-2.3.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:539432f911686cb80284c30b33eaf9f4fd9a11e1111fe0dc98fdbdce69b49821"},
+ {file = "pydantic_core-2.3.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:38a0e7ee65c8999394d92d9c724434cb629279d19844f2b69d9bbc46dc8b8b61"},
+ {file = "pydantic_core-2.3.0-cp310-cp310-manylinux_2_24_armv7l.whl", hash = "sha256:e3ed6834cc005798187a56c248a2240207cb8ffdda1c89e9afda4c3d526c2ea0"},
+ {file = "pydantic_core-2.3.0-cp310-cp310-manylinux_2_24_ppc64le.whl", hash = "sha256:e72ac299a6bf732a60852d052acf3999d234686755a02ba111e85e7ebf8155b1"},
+ {file = "pydantic_core-2.3.0-cp310-cp310-manylinux_2_24_s390x.whl", hash = "sha256:616b3451b05ca63b8f433c627f68046b39543faeaa4e50d8c6699a2a1e4b85a5"},
+ {file = "pydantic_core-2.3.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:adcb9c8848e15c613e483e0b99767ae325af27fe0dbd866df01fe5849d06e6e1"},
+ {file = "pydantic_core-2.3.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:464bf799b422be662e5e562e62beeffc9eaa907d381a9d63a2556615bbda286d"},
+ {file = "pydantic_core-2.3.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:4638ebc17de08c2f3acba557efeb6f195c88b7299d8c55c0bb4e20638bbd4d03"},
+ {file = "pydantic_core-2.3.0-cp310-none-win32.whl", hash = "sha256:9ff322c7e1030543d35d83bb521b69114d3d150750528d7757544f639def9ad6"},
+ {file = "pydantic_core-2.3.0-cp310-none-win_amd64.whl", hash = "sha256:4824eb018f0a4680b1e434697a9bf3f41c7799b80076d06530cbbd212e040ccc"},
+ {file = "pydantic_core-2.3.0-cp311-cp311-macosx_10_7_x86_64.whl", hash = "sha256:0aa429578e23885b3984c49d687cd05ab06f0b908ea1711a8bf7e503b7f97160"},
+ {file = "pydantic_core-2.3.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:20d710c1f79af930b8891bcebd84096798e4387ab64023ef41521d58f21277d3"},
+ {file = "pydantic_core-2.3.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:309f45d4d7481d6f09cb9e35c72caa0e50add4a30bb08c04c5fe5956a0158633"},
+ {file = "pydantic_core-2.3.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1bcfb7be905aa849bd882262e1df3f75b564e2f708b4b4c7ad2d3deaf5410562"},
+ {file = "pydantic_core-2.3.0-cp311-cp311-manylinux_2_24_armv7l.whl", hash = "sha256:85cd9c0af34e371390e3cb2f3a470b0b40cc07568c1e966c638c49062be6352d"},
+ {file = "pydantic_core-2.3.0-cp311-cp311-manylinux_2_24_ppc64le.whl", hash = "sha256:37c5028cebdf731298724070838fb3a71ef1fbd201d193d311ac2cbdbca25a23"},
+ {file = "pydantic_core-2.3.0-cp311-cp311-manylinux_2_24_s390x.whl", hash = "sha256:e4208f23f12d0ad206a07a489ef4cb15722c10b62774c4460ee4123250be938e"},
+ {file = "pydantic_core-2.3.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c24465dd11b65c8510f251b095fc788c7c91481c81840112fe3f76c30793a455"},
+ {file = "pydantic_core-2.3.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:3cd7ee8bbfab277ab56e272221886fd33a1b5943fbf45ae9195aa6a48715a8a0"},
+ {file = "pydantic_core-2.3.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:0fc7e0b056b66cc536e97ef60f48b3b289f6b3b62ac225afd4b22a42434617bf"},
+ {file = "pydantic_core-2.3.0-cp311-none-win32.whl", hash = "sha256:4788135db4bd83a5edc3522b11544b013be7d25b74b155e08dd3b20cd6663bbb"},
+ {file = "pydantic_core-2.3.0-cp311-none-win_amd64.whl", hash = "sha256:f93c867e5e85584a28c6a6feb6f2086d717266eb5d1210d096dd717b7f4dec04"},
+ {file = "pydantic_core-2.3.0-cp312-cp312-macosx_10_7_x86_64.whl", hash = "sha256:73f62bb7fd862d9bcd886e10612bade6fe042eda8b47e8c129892bcfb7b45e84"},
+ {file = "pydantic_core-2.3.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4d889d498fce64bfcd8adf1a78579a7f626f825cbeb2956a24a29b35f9a1df32"},
+ {file = "pydantic_core-2.3.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7d55e38a89ec2ae17b2fa7ffeda6b70f63afab1888bd0d57aaa7b7879760acb4"},
+ {file = "pydantic_core-2.3.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1aefebb506bc1fe355d91d25f12bcdea7f4d7c2d9f0f6716dd025543777c99a5"},
+ {file = "pydantic_core-2.3.0-cp312-cp312-manylinux_2_24_armv7l.whl", hash = "sha256:6441a29f42585f085db0c04cd0557d4cbbb46fa68a0972409b1cfe9f430280c1"},
+ {file = "pydantic_core-2.3.0-cp312-cp312-manylinux_2_24_ppc64le.whl", hash = "sha256:47e8f034be31390a8f525431eb5e803a78ce7e2e11b32abf5361a972e14e6b61"},
+ {file = "pydantic_core-2.3.0-cp312-cp312-manylinux_2_24_s390x.whl", hash = "sha256:ad814864aba263be9c83ada44a95f72d10caabbf91589321f95c29c902bdcff0"},
+ {file = "pydantic_core-2.3.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9eff3837d447fccf2ac38c259b14ab9cbde700df355a45a1f3ff244d5e78f8b6"},
+ {file = "pydantic_core-2.3.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:534f3f63c000f08050c6f7f4378bf2b52d7ba9214e9d35e3f60f7ad24a4d6425"},
+ {file = "pydantic_core-2.3.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:ef6a222d54f742c24f6b143aab088702db3a827b224e75b9dd28b38597c595fe"},
+ {file = "pydantic_core-2.3.0-cp312-none-win32.whl", hash = "sha256:4e26944e64ecc1d7b19db954c0f7b471f3b141ec8e1a9f57cfe27671525cd248"},
+ {file = "pydantic_core-2.3.0-cp312-none-win_amd64.whl", hash = "sha256:019c5c41941438570dfc7d3f0ae389b2425add1775a357ce1e83ed1434f943d6"},
+ {file = "pydantic_core-2.3.0-cp37-cp37m-macosx_10_7_x86_64.whl", hash = "sha256:27c1bbfb9d84a75cf33b7f19b53c29eb7ead99b235fce52aced5507174ab8f98"},
+ {file = "pydantic_core-2.3.0-cp37-cp37m-macosx_11_0_arm64.whl", hash = "sha256:7cb496e934b71f1ade844ab91d6ccac78a3520e5df02fdb2357f85a71e541e69"},
+ {file = "pydantic_core-2.3.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5af2d43b1978958d91351afbcc9b4d0cfe144c46c61740e82aaac8bb39ab1a4d"},
+ {file = "pydantic_core-2.3.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4d3097c39d7d4e8dba2ef86de171dcccad876c36d8379415ba18a5a4d0533510"},
+ {file = "pydantic_core-2.3.0-cp37-cp37m-manylinux_2_24_armv7l.whl", hash = "sha256:dd3b023f3317dbbbc775e43651ce1a31a9cea46216ad0b5be37afc18a2007699"},
+ {file = "pydantic_core-2.3.0-cp37-cp37m-manylinux_2_24_ppc64le.whl", hash = "sha256:27babb9879bf2c45ed655d02639f4c30e2b9ef1b71ce59c2305bbf7287910a18"},
+ {file = "pydantic_core-2.3.0-cp37-cp37m-manylinux_2_24_s390x.whl", hash = "sha256:2183a9e18cdc0de53bdaa1675f237259162abeb62d6ac9e527c359c1074dc55d"},
+ {file = "pydantic_core-2.3.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c089d8e7f1b4db08b2f8e4107304eec338df046275dad432635a9be9531e2fc8"},
+ {file = "pydantic_core-2.3.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:2f10aa5452b865818dd0137f568d443f5e93b60a27080a01aa4b7512c7ba13a3"},
+ {file = "pydantic_core-2.3.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:f642313d559f9d9a00c4de6820124059cc3342a0d0127b18301de2c680d5ea40"},
+ {file = "pydantic_core-2.3.0-cp37-none-win32.whl", hash = "sha256:45327fc57afbe3f2c3d7f54a335d5cecee8a9fdb3906a2fbed8af4092f4926df"},
+ {file = "pydantic_core-2.3.0-cp37-none-win_amd64.whl", hash = "sha256:e427b66596a6441a5607dfc0085b47d36073f88da7ac48afd284263b9b99e6ce"},
+ {file = "pydantic_core-2.3.0-cp38-cp38-macosx_10_7_x86_64.whl", hash = "sha256:0b3d781c71b8bfb621ef23b9c874933e2cd33237c1a65cc20eeb37437f8e7e18"},
+ {file = "pydantic_core-2.3.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:ad46027dbd5c1db87dc0b49becbe23093b143a20302028d387dae37ee5ef95f5"},
+ {file = "pydantic_core-2.3.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:39aa09ed7ce2a648c904f79032d16dda29e6913112af8465a7bf710eef23c7ca"},
+ {file = "pydantic_core-2.3.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:05b4bf8c58409586a7a04c858a86ab10f28c6c1a7c33da65e0326c59d5b0ab16"},
+ {file = "pydantic_core-2.3.0-cp38-cp38-manylinux_2_24_armv7l.whl", hash = "sha256:ba2b807d2b62c446120906b8580cddae1d76d3de4efbb95ccc87f5e35c75b4b2"},
+ {file = "pydantic_core-2.3.0-cp38-cp38-manylinux_2_24_ppc64le.whl", hash = "sha256:ea955e4ed21f4bbb9b83fea09fc6af0bed82e69ecf6b35ec89237a0a49633033"},
+ {file = "pydantic_core-2.3.0-cp38-cp38-manylinux_2_24_s390x.whl", hash = "sha256:06884c07956526ac9ebfef40fe21a11605569b8fc0e2054a375fb39c978bf48f"},
+ {file = "pydantic_core-2.3.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f868e731a18b403b88aa434d960489ceeed0ddeb44ebc02389540731a67705e0"},
+ {file = "pydantic_core-2.3.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:cb08fab0fc1db15c277b72e33ac74ad9c0c789413da8984a3eacb22a94b42ef4"},
+ {file = "pydantic_core-2.3.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6ca34c29fbd6592de5fd39e80c1993634d704c4e7e14ba54c87b2c7c53da68fe"},
+ {file = "pydantic_core-2.3.0-cp38-none-win32.whl", hash = "sha256:cd782807d35c8a41aaa7d30b5107784420eefd9fdc1c760d86007d43ae00b15d"},
+ {file = "pydantic_core-2.3.0-cp38-none-win_amd64.whl", hash = "sha256:01f56d5ee70b1d39c0fd08372cc5142274070ab7181d17c86035f130eebc05b8"},
+ {file = "pydantic_core-2.3.0-cp39-cp39-macosx_10_7_x86_64.whl", hash = "sha256:78b1ac0151271ce62bc2b33755f1043eda6a310373143a2f27e2bcd3d5fc8633"},
+ {file = "pydantic_core-2.3.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:64bfd2c35a2c350f73ac52dc134d8775f93359c4c969280a6fe5301b5b6e7431"},
+ {file = "pydantic_core-2.3.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:937c0fe9538f1212b62df6a68f8d78df3572fe3682d9a0dd8851eac8a4e46063"},
+ {file = "pydantic_core-2.3.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4d965c7c4b40d1cedec9188782e98bd576f9a04868835604200c3a6e817b824f"},
+ {file = "pydantic_core-2.3.0-cp39-cp39-manylinux_2_24_armv7l.whl", hash = "sha256:ad442b8585ed4a3c2d22e4bf7b465d9b7d281e055b09719a8aeb5b576422dc9b"},
+ {file = "pydantic_core-2.3.0-cp39-cp39-manylinux_2_24_ppc64le.whl", hash = "sha256:4bf20c9722821fce766e685718e739deeccc60d6bc7be5029281db41f999ee0c"},
+ {file = "pydantic_core-2.3.0-cp39-cp39-manylinux_2_24_s390x.whl", hash = "sha256:f3dd5333049b5b3faa739e0f40b77cc8b7a1aded2f2da0e28794c81586d7b08a"},
+ {file = "pydantic_core-2.3.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:0dc5f516b24d24bc9e8dd9305460899f38302b3c4f9752663b396ef9848557bf"},
+ {file = "pydantic_core-2.3.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:055f7ea6b1fbb37880d66d70eefd22dd319b09c79d2cb99b1dbfeb34b653b0b2"},
+ {file = "pydantic_core-2.3.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:af693a89db6d6ac97dd84dd7769b3f2bd9007b578127d0e7dda03053f4d3b34b"},
+ {file = "pydantic_core-2.3.0-cp39-none-win32.whl", hash = "sha256:f60e31e3e15e8c294bf70c60f8ae4d0c3caf3af8f26466e9aa8ea4c01302749b"},
+ {file = "pydantic_core-2.3.0-cp39-none-win_amd64.whl", hash = "sha256:2b79f3681481f4424d7845cc7a261d5a4baa810d656b631fa844dc9967b36a7b"},
+ {file = "pydantic_core-2.3.0-pp310-pypy310_pp73-macosx_10_7_x86_64.whl", hash = "sha256:a666134b41712e30a71afaa26deeb4da374179f769fa49784cdf0e7698880fab"},
+ {file = "pydantic_core-2.3.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1c119e9227487ad3d7c3c737d896afe548a6be554091f9745da1f4b489c40561"},
+ {file = "pydantic_core-2.3.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:73929a2fb600a2333fce2efd92596cff5e6bf8946e20e93c067b220760064862"},
+ {file = "pydantic_core-2.3.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:41bbc2678a5b6a19371b2cb51f30ccea71f0c14b26477d2d884fed761cea42c7"},
+ {file = "pydantic_core-2.3.0-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:dcbff997f47d45bf028bda4c3036bb3101e89a3df271281d392b6175f71c71d1"},
+ {file = "pydantic_core-2.3.0-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:afa8808159169368b66e4fbeafac6c6fd8f26246dc4d0dcc2caf94bd9cf1b828"},
+ {file = "pydantic_core-2.3.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:12be3b5f54f8111ca38e6b7277f26c23ba5cb3344fae06f879a0a93dfc8b479e"},
+ {file = "pydantic_core-2.3.0-pp37-pypy37_pp73-macosx_10_7_x86_64.whl", hash = "sha256:ed5babdcd3d052ba5cf8832561f18df20778c7ccf12587b2d82f7bf3bf259a0e"},
+ {file = "pydantic_core-2.3.0-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3d642e5c029e2acfacf6aa0a7a3e822086b3b777c70d364742561f9ca64c1ffc"},
+ {file = "pydantic_core-2.3.0-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8ba3073eb38a1294e8c7902989fb80a7a147a69db2396818722bd078476586a0"},
+ {file = "pydantic_core-2.3.0-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d5146a6749b1905e04e62e0ad4622f079e5582f8b3abef5fb64516c623127908"},
+ {file = "pydantic_core-2.3.0-pp37-pypy37_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:deeb64335f489c3c11949cbd1d1668b3f1fb2d1c6a5bf40e126ef7bf95f9fa40"},
+ {file = "pydantic_core-2.3.0-pp37-pypy37_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:31acc37288b8e69e4849f618c3d5cf13b58077c1a1ff9ade0b3065ba974cd385"},
+ {file = "pydantic_core-2.3.0-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:e09d9f6d722de9d4c1c5f122ea9bc6b25a05f975457805af4dcab7b0128aacbf"},
+ {file = "pydantic_core-2.3.0-pp38-pypy38_pp73-macosx_10_7_x86_64.whl", hash = "sha256:ba6a8cf089222a171b8f84e6ec2d10f7a9d14f26be3a347b14775a8741810676"},
+ {file = "pydantic_core-2.3.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ef1fd1b24e9bcddcb168437686677104e205c8e25b066e73ffdf331d3bb8792b"},
+ {file = "pydantic_core-2.3.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eda1a89c4526826c0a87d33596a4cd15b8f58e9250f503e39af1699ba9c878e8"},
+ {file = "pydantic_core-2.3.0-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a3e9a18401a28db4358da2e191508702dbf065f2664c710708cdf9552b9fa50c"},
+ {file = "pydantic_core-2.3.0-pp38-pypy38_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:a439fd0d45d51245bbde799726adda5bd18aed3fa2b01ab2e6a64d6d13776fa3"},
+ {file = "pydantic_core-2.3.0-pp38-pypy38_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:bf6a1d2c920cc9528e884850a4b2ee7629e3d362d5c44c66526d4097bbb07a1a"},
+ {file = "pydantic_core-2.3.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:e33fcbea3b63a339dd94de0fc442fefacfe681cc7027ce63f67af9f7ceec7422"},
+ {file = "pydantic_core-2.3.0-pp39-pypy39_pp73-macosx_10_7_x86_64.whl", hash = "sha256:bf3ed993bdf4754909f175ff348cf8f78d4451215b8aa338633f149ca3b1f37a"},
+ {file = "pydantic_core-2.3.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7584171eb3115acd4aba699bc836634783f5bd5aab131e88d8eeb8a3328a4a72"},
+ {file = "pydantic_core-2.3.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1624baa76d1740711b2048f302ae9a6d73d277c55a8c3e88b53b773ebf73a971"},
+ {file = "pydantic_core-2.3.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:06f33f695527f5a86e090f208978f9fd252c9cfc7e869d3b679bd71f7cb2c1fa"},
+ {file = "pydantic_core-2.3.0-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:7ecf0a67b212900e92f328181fed02840d74ed39553cdb38d27314e2b9c89dfa"},
+ {file = "pydantic_core-2.3.0-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:45fa1e8ad6f4367ad73674ca560da8e827cc890eaf371f3ee063d6d7366a207b"},
+ {file = "pydantic_core-2.3.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:8d0dbcc57839831ae79fd24b1b83d42bc9448d79feaf3ed3fb5cbf94ffbf3eb7"},
+ {file = "pydantic_core-2.3.0.tar.gz", hash = "sha256:5cfb5ac4e82c47d5dc25b209dd4c3989e284b80109f9e08b33c895080c424b4f"},
+]
+
+[package.dependencies]
+typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0"
+
+[[package]]
+name = "pydantic-settings"
+version = "2.0.2"
+description = "Settings management using Pydantic"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "pydantic_settings-2.0.2-py3-none-any.whl", hash = "sha256:6183a2abeab465d5a3ab69758e9a22d38b0cc2ba193f0b85f6971a252ea630f6"},
+ {file = "pydantic_settings-2.0.2.tar.gz", hash = "sha256:342337fff50b23585e807a86dec85037900972364435c55c2fc00d16ff080539"},
+]
+
+[package.dependencies]
+pydantic = ">=2.0.1"
+python-dotenv = ">=0.21.0"
[[package]]
name = "pydis-core"
@@ -2104,23 +2198,23 @@ zstd = ["zstandard (>=0.18.0)"]
[[package]]
name = "virtualenv"
-version = "20.24.1"
+version = "20.24.2"
description = "Virtual Python Environment builder"
optional = false
python-versions = ">=3.7"
files = [
- {file = "virtualenv-20.24.1-py3-none-any.whl", hash = "sha256:01aacf8decd346cf9a865ae85c0cdc7f64c8caa07ff0d8b1dfc1733d10677442"},
- {file = "virtualenv-20.24.1.tar.gz", hash = "sha256:2ef6a237c31629da6442b0bcaa3999748108c7166318d1f55cc9f8d7294e97bd"},
+ {file = "virtualenv-20.24.2-py3-none-any.whl", hash = "sha256:43a3052be36080548bdee0b42919c88072037d50d56c28bd3f853cbe92b953ff"},
+ {file = "virtualenv-20.24.2.tar.gz", hash = "sha256:fd8a78f46f6b99a67b7ec5cf73f92357891a7b3a40fd97637c27f854aae3b9e0"},
]
[package.dependencies]
-distlib = ">=0.3.6,<1"
-filelock = ">=3.12,<4"
-platformdirs = ">=3.5.1,<4"
+distlib = ">=0.3.7,<1"
+filelock = ">=3.12.2,<4"
+platformdirs = ">=3.9.1,<4"
[package.extras]
docs = ["furo (>=2023.5.20)", "proselint (>=0.13)", "sphinx (>=7.0.1)", "sphinx-argparse (>=0.4)", "sphinxcontrib-towncrier (>=0.2.1a0)", "towncrier (>=23.6)"]
-test = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "coverage-enable-subprocess (>=1)", "flaky (>=3.7)", "packaging (>=23.1)", "pytest (>=7.3.1)", "pytest-env (>=0.8.1)", "pytest-freezer (>=0.4.6)", "pytest-mock (>=3.10)", "pytest-randomly (>=3.12)", "pytest-timeout (>=2.1)", "setuptools (>=67.8)", "time-machine (>=2.9)"]
+test = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "coverage-enable-subprocess (>=1)", "flaky (>=3.7)", "packaging (>=23.1)", "pytest (>=7.4)", "pytest-env (>=0.8.2)", "pytest-freezer (>=0.4.8)", "pytest-mock (>=3.11.1)", "pytest-randomly (>=3.12)", "pytest-timeout (>=2.1)", "setuptools (>=68)", "time-machine (>=2.10)"]
[[package]]
name = "wcwidth"
@@ -2223,4 +2317,4 @@ multidict = ">=4.0"
[metadata]
lock-version = "2.0"
python-versions = "3.11.*"
-content-hash = "60353f299efeb38128df337aabef6ec53c5018c9a1fe14254737b5079f094f41"
+content-hash = "e7e58f19c35b45ba8b1ee279e852fbe5111ad70b1bb9f5f5de0941dd966bb6ed"
diff --git a/pyproject.toml b/pyproject.toml
index 68aa2685f..af17a1ed9 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -28,7 +28,8 @@ rapidfuzz = "3.2.0"
regex = "2023.8.8"
sentry-sdk = "1.29.2"
tldextract = "3.4.4"
-pydantic = { version = "1.10.9", extras = ["dotenv"]}
+pydantic = "2.0.3"
+pydantic-settings = "2.0.2"
[tool.poetry.dev-dependencies]
coverage = "7.2.7"
diff --git a/tests/bot/exts/filtering/test_settings_entries.py b/tests/bot/exts/filtering/test_settings_entries.py
index 3ae0b5ab5..988435022 100644
--- a/tests/bot/exts/filtering/test_settings_entries.py
+++ b/tests/bot/exts/filtering/test_settings_entries.py
@@ -173,7 +173,7 @@ class FilterTests(unittest.TestCase):
result = infraction1.union(infraction2)
self.assertDictEqual(
- result.dict(),
+ result.model_dump(),
{
"infraction_type": Infraction.TIMEOUT,
"infraction_reason": "there",
@@ -206,7 +206,7 @@ class FilterTests(unittest.TestCase):
result = infraction1.union(infraction2)
self.assertDictEqual(
- result.dict(),
+ result.model_dump(),
{
"infraction_type": Infraction.BAN,
"infraction_reason": "",