-
+
Byte:
- {{ byte_status | default('Unknown') }}
+ {{ overall_status | default('Unknown') | upper }}
- .
-
Currently in
From da6ec7cad89b60b0f85c700398ac7facdcfdfa04 Mon Sep 17 00:00:00 2001
From: Jacob Coffee
Date: Sun, 3 Mar 2024 23:12:56 -0600
Subject: [PATCH 13/29] feat: enhance guild schema detail
---
src/server/domain/__init__.py | 2 +-
src/server/domain/db/models.py | 2 +-
src/server/domain/guilds/controllers.py | 86 +++++++++++++++---------
src/server/domain/guilds/dependencies.py | 22 +++++-
src/server/domain/guilds/schemas.py | 30 ++++++++-
src/server/domain/guilds/services.py | 41 ++++++++++-
6 files changed, 142 insertions(+), 41 deletions(-)
diff --git a/src/server/domain/__init__.py b/src/server/domain/__init__.py
index e770574..768c733 100644
--- a/src/server/domain/__init__.py
+++ b/src/server/domain/__init__.py
@@ -26,7 +26,7 @@
routes: list[ControllerRouterHandler] = [
system.controllers.system.SystemController,
web.controllers.web.WebController,
- guilds.controllers.GuildController,
+ guilds.controllers.GuildsController,
]
"""Routes for the application."""
diff --git a/src/server/domain/db/models.py b/src/server/domain/db/models.py
index 6ce111a..f57e256 100644
--- a/src/server/domain/db/models.py
+++ b/src/server/domain/db/models.py
@@ -8,7 +8,7 @@
from sqlalchemy.ext.associationproxy import AssociationProxy, association_proxy
from sqlalchemy.orm import Mapped, mapped_column, relationship
-__all__ = ("GitHubConfig", "Guild", "SOTagsConfig", "User")
+__all__ = ("GitHubConfig", "Guild", "SOTagsConfig", "User", "AllowedUsersConfig")
class Guild(UUIDAuditBase):
diff --git a/src/server/domain/guilds/controllers.py b/src/server/domain/guilds/controllers.py
index ccca0b6..21d53f4 100644
--- a/src/server/domain/guilds/controllers.py
+++ b/src/server/domain/guilds/controllers.py
@@ -7,7 +7,6 @@
from litestar.di import Provide
from litestar.params import Dependency, Parameter
-from server.domain.db.models import Guild
from server.domain.guilds import urls
from server.domain.guilds.dependencies import provides_guilds_service
from server.domain.guilds.schemas import GuildSchema, UpdateableGuildSetting
@@ -17,10 +16,10 @@
from advanced_alchemy import FilterTypes
from litestar.pagination import OffsetPagination
-__all__ = ("GuildController",)
+__all__ = ("GuildsController",)
-class GuildController(Controller):
+class GuildsController(Controller):
"""Controller for guild-based routes."""
tags = ["Guilds"]
@@ -33,9 +32,9 @@ class GuildController(Controller):
path=urls.GUILD_LIST,
)
async def list_guilds(
- self,
- guilds_service: GuildsService,
- filters: list[FilterTypes] = Dependency(skip_validation=True),
+ self,
+ guilds_service: GuildsService,
+ filters: list[FilterTypes] = Dependency(skip_validation=True),
) -> OffsetPagination[GuildSchema]:
"""List guilds.
@@ -56,16 +55,16 @@ async def list_guilds(
path=urls.GUILD_CREATE,
)
async def create_guild(
- self,
- guilds_service: GuildsService,
- guild_id: int = Parameter(
- title="Guild ID",
- description="The guild ID.",
- ),
- guild_name: str = Parameter(
- title="Guild Name",
- description="The guild name.",
- ),
+ self,
+ guilds_service: GuildsService,
+ guild_id: int = Parameter(
+ title="Guild ID",
+ description="The guild ID.",
+ ),
+ guild_name: str = Parameter(
+ title="Guild Name",
+ description="The guild name.",
+ ),
) -> str:
"""Create a guild.
@@ -88,20 +87,20 @@ async def create_guild(
path=urls.GUILD_UPDATE,
)
async def update_guild(
- self,
- guilds_service: GuildsService,
- guild_id: Guild.guild_id = Parameter(
- title="Guild ID",
- description="The guild ID.",
- ),
- setting: UpdateableGuildSetting = Parameter(
- title="Setting",
- description="The setting to update.",
- ),
- value: str | int = Parameter(
- title="Value",
- description="The new value for the setting.",
- ),
+ self,
+ guilds_service: GuildsService,
+ guild_id: int = Parameter(
+ title="Guild ID",
+ description="The guild ID.",
+ ),
+ setting: UpdateableGuildSetting = Parameter(
+ title="Setting",
+ description="The setting to update.",
+ ),
+ value: str | int = Parameter(
+ title="Value",
+ description="The new value for the setting.",
+ ),
) -> str:
"""Update a guild by ID.
@@ -114,5 +113,32 @@ async def update_guild(
Returns:
Guild: Updated guild object
"""
+ # todo: this is a placeholder, update
await guilds_service.update(guild_id, setting, {"some-config-thing": value})
return f"Guild {guild_id} updated."
+
+ @get(
+ operation_id="GuildDetail",
+ name="guilds:detail",
+ summary="Get guild details.",
+ path=urls.GUILD_DETAIL,
+ )
+ async def get_guild(
+ self,
+ guilds_service: GuildsService,
+ guild_id: int = Parameter(
+ title="Guild ID",
+ description="The guild ID.",
+ ),
+ ) -> GuildSchema:
+ """Get a guild by ID.
+
+ Args:
+ guilds_service (GuildsService): Guilds service
+ guild_id (int): Guild ID
+
+ Returns:
+ Guild: Guild object
+ """
+ result = await guilds_service.get(guild_id, id_attribute="guild_id")
+ return guilds_service.to_schema(GuildSchema, result)
diff --git a/src/server/domain/guilds/dependencies.py b/src/server/domain/guilds/dependencies.py
index 77cc803..b84c34d 100644
--- a/src/server/domain/guilds/dependencies.py
+++ b/src/server/domain/guilds/dependencies.py
@@ -4,8 +4,9 @@
from typing import TYPE_CHECKING
from sqlalchemy import select
+from sqlalchemy.orm import joinedload, noload, selectinload
-from server.domain.db.models import Guild
+from server.domain.db.models import AllowedUsersConfig, GitHubConfig, Guild, SOTagsConfig
from server.domain.guilds.services import GuildsService
from server.lib import log
@@ -20,7 +21,7 @@
async def provides_guilds_service(db_session: AsyncSession) -> AsyncGenerator[GuildsService, None]:
- """Construct GuildConfig-based repository and service objects for the request.
+ """Construct Guilds-based repository and service objects for the request.
Args:
db_session (AsyncSession): SQLAlchemy AsyncSession
@@ -28,7 +29,22 @@ async def provides_guilds_service(db_session: AsyncSession) -> AsyncGenerator[Gu
Yields:
GuildsService: GuildConfig-based service
"""
- async with GuildsService.new(session=db_session, statement=select(Guild).order_by(Guild.guild_id)) as service:
+ async with GuildsService.new(
+ session=db_session,
+ statement=select(Guild)
+ .order_by(Guild.guild_name)
+ .options(
+ selectinload(Guild.github_config).options(
+ joinedload(GitHubConfig.guild, innerjoin=True).options(noload("*")),
+ ),
+ selectinload(Guild.sotags_configs).options(
+ joinedload(SOTagsConfig.guild, innerjoin=True).options(noload("*")),
+ ),
+ selectinload(Guild.allowed_users).options(
+ joinedload(AllowedUsersConfig.guild, innerjoin=True).options(noload("*")),
+ ),
+ ),
+ ) as service:
try:
yield service
finally:
diff --git a/src/server/domain/guilds/schemas.py b/src/server/domain/guilds/schemas.py
index 0871b27..89a2158 100644
--- a/src/server/domain/guilds/schemas.py
+++ b/src/server/domain/guilds/schemas.py
@@ -10,6 +10,23 @@
__all__ = ("GuildCreate", "GuildSchema", "GuildUpdate", "UpdateableGuildSetting")
+class GitHubConfigSchema(CamelizedBaseModel):
+ guild_id: UUID
+ discussion_sync: bool
+ github_organization: str | None
+ github_repository: str | None
+
+
+class SOTagsConfigSchema(CamelizedBaseModel):
+ guild_id: UUID
+ tag_name: str
+
+
+class AllowedUsersConfigSchema(CamelizedBaseModel):
+ guild_id: int
+ user_id: UUID
+
+
class GuildSchema(CamelizedBaseModel):
"""Schema representing an existing guild."""
@@ -24,6 +41,15 @@ class GuildSchema(CamelizedBaseModel):
issue_linking: bool | None = Field(title="Issue Linking", description="Is issue linking enabled.")
comment_linking: bool | None = Field(title="Comment Linking", description="Is comment linking enabled.")
pep_linking: bool | None = Field(title="PEP Linking", description="Is PEP linking enabled.")
+ github_config: GitHubConfigSchema | None = Field(
+ title="GitHub Config", description="The GitHub configuration for the guild."
+ )
+ sotags_configs: list[SOTagsConfigSchema] = Field(
+ title="StackOverflow Tags Configs", description="The StackOverflow tags configuration for the guild."
+ )
+ allowed_users: list[AllowedUsersConfigSchema] = Field(
+ title="Allowed Users", description="The allowed users configuration for the guild."
+ )
class GuildCreate(CamelizedBaseModel):
@@ -56,9 +82,7 @@ class UpdateableGuildSetting(CamelizedBaseModel):
"""Guild Model Settings"""
prefix: str = Field(title="Prefix", description="The prefix for the guild.")
help_channel_id: int = Field(title="Help Channel ID", description="The channel ID for the help channel.")
- sync_label: str = Field(
- title="Sync Label", description="The forum label to use for GitHub discussion syncs."
- )
+ sync_label: str = Field(title="Sync Label", description="The forum label to use for GitHub discussion syncs.")
issue_linking: bool = Field(title="Issue Linking", description="Is issue linking enabled.")
comment_linking: bool = Field(title="Comment Linking", description="Is comment linking enabled.")
pep_linking: bool = Field(title="PEP Linking", description="Is PEP linking enabled.")
diff --git a/src/server/domain/guilds/services.py b/src/server/domain/guilds/services.py
index b21c90e..c207966 100644
--- a/src/server/domain/guilds/services.py
+++ b/src/server/domain/guilds/services.py
@@ -3,14 +3,13 @@
from typing import Any
-from server.domain.db.models import Guild
+from server.domain.db.models import AllowedUsersConfig, GitHubConfig, Guild, SOTagsConfig
from server.lib import log
-from server.lib.repository import SQLAlchemyAsyncSlugRepository
+from server.lib.repository import SQLAlchemyAsyncRepository, SQLAlchemyAsyncSlugRepository
from server.lib.service import SQLAlchemyAsyncRepositoryService
__all__ = ("GuildsRepository", "GuildsService")
-
logger = log.get_logger()
@@ -37,3 +36,39 @@ async def to_model(self, data: Guild | dict[str, Any], operation: str | None = N
Project: Converted model
"""
return await super().to_model(data, operation)
+
+
+class GitHubConfigRepository(SQLAlchemyAsyncRepository[GitHubConfig]):
+ """GitHubConfig SQLAlchemy Repository."""
+
+ model_type = GitHubConfig
+
+
+class GitHubConfigService(SQLAlchemyAsyncRepositoryService[GitHubConfig]):
+ """Handles basic operations for the guilds' GitHub config."""
+
+ repository_type = GitHubConfigRepository
+
+
+class SOTagsConfigRepository(SQLAlchemyAsyncRepository[SOTagsConfig]):
+ """SOTagsConfig SQLAlchemy Repository."""
+
+ model_type = SOTagsConfig
+
+
+class SOTagsConfigService(SQLAlchemyAsyncRepositoryService[SOTagsConfig]):
+ """Handles basic operations for the guilds' StackOverflow tags config."""
+
+ repository_type = SOTagsConfigRepository
+
+
+class AllowedUsersConfigRepository(SQLAlchemyAsyncRepository[AllowedUsersConfig]):
+ """AllowedUsersConfig SQLAlchemy Repository."""
+
+ model_type = AllowedUsersConfig
+
+
+class AllowedUsersConfigService(SQLAlchemyAsyncRepositoryService[AllowedUsersConfig]):
+ """Handles basic operations for the guilds' Allowed Users config."""
+
+ repository_type = AllowedUsersConfigRepository
From 79a7f89d0e776a17a97fe0e93514eebbe54052be Mon Sep 17 00:00:00 2001
From: Jacob Coffee
Date: Fri, 8 Mar 2024 22:35:32 -0600
Subject: [PATCH 14/29] feat: add predicate for guild admin check
---
src/byte/lib/utils.py | 25 +++++++++++++++++++++++++
1 file changed, 25 insertions(+)
diff --git a/src/byte/lib/utils.py b/src/byte/lib/utils.py
index 777664e..4f18d76 100644
--- a/src/byte/lib/utils.py
+++ b/src/byte/lib/utils.py
@@ -29,6 +29,10 @@
"RuffRule",
"FormattedRuffRule",
"PEP",
+ "PEPType",
+ "PEPStatus",
+ "PEPHistoryItem",
+ "is_guild_admin",
"is_byte_dev",
"linker",
"mention_user",
@@ -142,6 +146,27 @@ class PEP(TypedDict):
url: str
+def is_guild_admin() -> Check[Any]:
+ """Check if the user is a guild admin.
+
+ Returns:
+ A check function.
+ """
+
+ async def predicate(ctx: Context) -> bool:
+ """Check if the user is a guild admin.
+
+ Args:
+ ctx: Context object.
+
+ Returns:
+ True if the user is a guild admin, False otherwise.
+ """
+ return ctx.author.guild_permissions.administrator
+
+ return commands.check(predicate)
+
+
def is_byte_dev() -> Check[Any]:
"""Check if the user is a Byte developer.
From b036bb7090929a3f511918be6edbc3b5143eb94e Mon Sep 17 00:00:00 2001
From: Jacob Coffee
Date: Sun, 10 Mar 2024 17:14:48 -0500
Subject: [PATCH 15/29] feat: add guild configuration command (#78)
* feat: add guild configuration command
* feat: add litestar office hours command
* fix: centralize options for slashcmd and dropdown
* ci: apply pre-commit
* chore: dependecy updates
* chore: clean up utils
* fix: move moved import
* fix: attempt to fix broken modal submission
* feat: finalize working config selection and sub selections
* ci: for some reason pre-commit is stupid and changed every fucking file
---
.pre-commit-config.yaml | 5 +-
docs/conf.py | 1 +
pdm.lock | 26 +-
pyproject.toml | 4 +-
src/__init__.py | 1 +
src/__main__.py | 1 +
src/app.py | 1 +
src/byte/__init__.py | 1 +
src/byte/bot.py | 1 +
src/byte/lib/__init__.py | 3 +-
src/byte/lib/checks.py | 65 ++++
src/byte/lib/common/__init__.py | 46 ++-
src/byte/lib/common/assets.py | 1 +
src/byte/lib/common/colors.py | 1 +
src/byte/lib/common/guilds.py | 1 +
src/byte/lib/common/links.py | 1 +
src/byte/lib/common/mention.py | 129 ++++++++
src/byte/lib/log.py | 11 +
src/byte/lib/settings.py | 5 +
src/byte/lib/types/__init__.py | 5 +
src/byte/lib/types/astral.py | 32 ++
src/byte/lib/types/python.py | 77 +++++
src/byte/lib/utils.py | 312 ++----------------
src/byte/plugins/admin.py | 5 +-
src/byte/plugins/astral.py | 11 +-
src/byte/plugins/config.py | 69 ++++
src/byte/plugins/custom/litestar.py | 55 ++-
src/byte/plugins/events.py | 1 +
src/byte/plugins/general.py | 3 +-
src/byte/plugins/github.py | 1 +
src/byte/plugins/python.py | 1 +
src/byte/plugins/testing.py | 1 +
src/byte/views/abstract_views.py | 11 +-
src/byte/views/astral.py | 1 +
src/byte/views/config.py | 263 +++++++++++++++
src/byte/views/python.py | 1 +
src/cli.py | 1 +
src/server/__init__.py | 1 +
src/server/domain/__init__.py | 1 +
src/server/domain/db/__init__.py | 1 +
src/server/domain/db/models.py | 1 +
src/server/domain/github/helpers.py | 1 +
src/server/domain/guilds/controllers.py | 1 +
src/server/domain/guilds/dependencies.py | 1 +
src/server/domain/guilds/helpers.py | 1 +
src/server/domain/guilds/schemas.py | 1 +
src/server/domain/guilds/services.py | 1 +
src/server/domain/guilds/urls.py | 1 +
src/server/domain/system/__init__.py | 1 +
.../domain/system/controllers/__init__.py | 1 +
.../domain/system/controllers/system.py | 1 +
src/server/domain/system/dtos.py | 1 +
src/server/domain/system/helpers.py | 1 +
src/server/domain/urls.py | 1 +
src/server/domain/web/__init__.py | 1 +
src/server/domain/web/controllers/__init__.py | 1 +
src/server/domain/web/controllers/web.py | 1 +
src/server/lib/__init__.py | 1 +
src/server/lib/constants.py | 1 +
src/server/lib/cors.py | 1 +
src/server/lib/db/__init__.py | 1 +
src/server/lib/db/base.py | 1 +
src/server/lib/db/migrations/env.py | 1 +
.../versions/002_simplify_models.py | 1 +
.../lib/db/migrations/versions/initial.py | 1 +
src/server/lib/db/orm.py | 1 +
src/server/lib/dependencies.py | 1 +
src/server/lib/dto.py | 7 +-
src/server/lib/exceptions.py | 1 +
src/server/lib/log/controller.py | 1 +
src/server/lib/log/utils.py | 1 +
src/server/lib/openapi.py | 1 +
src/server/lib/repository.py | 1 +
src/server/lib/schema.py | 1 +
src/server/lib/serialization.py | 1 +
src/server/lib/service.py | 13 +-
src/server/lib/settings.py | 1 +
src/server/lib/static_files.py | 1 +
src/server/lib/template.py | 1 +
src/server/lib/types.py | 1 +
src/utils.py | 1 +
tools/build_docs.py | 1 +
82 files changed, 896 insertions(+), 321 deletions(-)
create mode 100644 src/byte/lib/checks.py
create mode 100644 src/byte/lib/common/mention.py
create mode 100644 src/byte/lib/types/__init__.py
create mode 100644 src/byte/lib/types/astral.py
create mode 100644 src/byte/lib/types/python.py
create mode 100644 src/byte/plugins/config.py
create mode 100644 src/byte/views/config.py
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index e48d07b..8cf5cb9 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -18,7 +18,7 @@ repos:
- id: mixed-line-ending
- id: trailing-whitespace
- repo: https://github.com/charliermarsh/ruff-pre-commit
- rev: "v0.2.2"
+ rev: "v0.3.2"
hooks:
- id: ruff
args: ["--fix"]
@@ -88,7 +88,7 @@ repos:
# discord-py,
# ]
- repo: https://github.com/RobertCraigie/pyright-python
- rev: v1.1.351
+ rev: v1.1.353
hooks:
- id: pyright
additional_dependencies:
@@ -142,6 +142,7 @@ repos:
asyncpg-stubs,
polyfactory,
discord-py,
+ types-python-dateutil,
]
- repo: https://github.com/sphinx-contrib/sphinx-lint
rev: "v0.9.1"
diff --git a/docs/conf.py b/docs/conf.py
index 5bc74c6..dcaed6c 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -1,4 +1,5 @@
"""Sphinx configuration."""
+
from __future__ import annotations
import importlib.metadata
diff --git a/pdm.lock b/pdm.lock
index 934b060..cd0e778 100644
--- a/pdm.lock
+++ b/pdm.lock
@@ -5,7 +5,7 @@
groups = ["default", "docs", "lint", "test"]
strategy = ["cross_platform", "inherit_metadata"]
lock_version = "4.4.1"
-content_hash = "sha256:7098b3193b937e135dd887069755130b9528dc064cdd068424cf78340e091281"
+content_hash = "sha256:85851593eb18cf99411fefc596f8644a2b15988a4e0b6467aaaa5a3b4c50aeb8"
[[package]]
name = "accessible-pygments"
@@ -655,7 +655,7 @@ files = [
name = "domdf-python-tools"
version = "3.8.0.post2"
requires_python = ">=3.6"
-summary = "Helpful functions for Python 🐍 🛠️"
+summary = "Helpful functions for Python‚ÄÇüêç‚ÄÇüõ†Ô∏è"
groups = ["docs"]
dependencies = [
"natsort>=7.0.1",
@@ -782,31 +782,35 @@ files = [
[[package]]
name = "githubkit"
-version = "0.11.1"
+version = "0.11.2"
requires_python = ">=3.8,<4.0"
-git = "https://github.com/yanyongyu/githubkit.git"
-revision = "5d88fdc2349496a696d000ea31fef30efcae5e55"
summary = "GitHub SDK for Python"
groups = ["default"]
dependencies = [
- "hishel<0.0.22,>=0.0.21",
+ "hishel<=0.0.24,>=0.0.21",
"httpx<1.0.0,>=0.23.0",
"pydantic!=2.5.0,!=2.5.1,<3.0.0,>=1.9.1",
"typing-extensions<5.0.0,>=4.3.0",
]
+files = [
+ {file = "githubkit-0.11.2-py3-none-any.whl", hash = "sha256:d6776c667e37e0a120c003fa0a4c4c9a03c99a87a8a1767d3b67a87e09567933"},
+ {file = "githubkit-0.11.2.tar.gz", hash = "sha256:2192cd30f32424d5ac8b104f3fc601c69ff1d4f63e2934eff3873953afca961b"},
+]
[[package]]
name = "githubkit"
-version = "0.11.1"
+version = "0.11.2"
extras = ["auth-app"]
requires_python = ">=3.8,<4.0"
-git = "https://github.com/yanyongyu/githubkit.git"
-revision = "5d88fdc2349496a696d000ea31fef30efcae5e55"
summary = "GitHub SDK for Python"
groups = ["default"]
dependencies = [
"PyJWT[crypto]<3.0.0,>=2.4.0",
- "githubkit @ git+https://github.com/yanyongyu/githubkit.git@5d88fdc2349496a696d000ea31fef30efcae5e55",
+ "githubkit==0.11.2",
+]
+files = [
+ {file = "githubkit-0.11.2-py3-none-any.whl", hash = "sha256:d6776c667e37e0a120c003fa0a4c4c9a03c99a87a8a1767d3b67a87e09567933"},
+ {file = "githubkit-0.11.2.tar.gz", hash = "sha256:2192cd30f32424d5ac8b104f3fc601c69ff1d4f63e2934eff3873953afca961b"},
]
[[package]]
@@ -2216,7 +2220,7 @@ files = [
name = "sphinx-toolbox"
version = "3.5.0"
requires_python = ">=3.7"
-summary = "Box of handy tools for Sphinx 🧰 📔"
+summary = "Box of handy tools for Sphinx 🧰 📔"
groups = ["docs"]
dependencies = [
"apeye>=0.4.0",
diff --git a/pyproject.toml b/pyproject.toml
index 29d5529..571004a 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -15,11 +15,11 @@ dependencies = [
"advanced-alchemy>=0.6.1",
"certifi>=2023.11.17",
"asyncpg>=0.29.0",
- "githubkit[auth-app] @ git+https://github.com/yanyongyu/githubkit.git",
"PyJWT>=2.8.0",
"alembic>=1.13.0",
"pre-commit>=3.6.2",
"ruff>=0.1.7",
+ "githubkit[auth-app]>=0.11.2",
]
requires-python = ">=3.11,<4.0"
readme = "README.md"
@@ -82,7 +82,7 @@ changelog = "git cliff -c pyproject.toml -o docs/changelog.rst"
# TODO: Move more from makefile here
ci = { composite = ["lint", "test"] }
-[tool.pdm.dev-dependencies]
+[project.optional-dependencies]
test = [
"pytest>=7.4.3",
"coverage>=7.3.2",
diff --git a/src/__init__.py b/src/__init__.py
index f9b6856..538e852 100644
--- a/src/__init__.py
+++ b/src/__init__.py
@@ -1,4 +1,5 @@
"""Byte Bot."""
+
from __future__ import annotations
from rich import get_console
diff --git a/src/__main__.py b/src/__main__.py
index 2a7da61..ab78994 100644
--- a/src/__main__.py
+++ b/src/__main__.py
@@ -1,4 +1,5 @@
"""Application Entrypoint."""
+
from __future__ import annotations
__all__ = ("run_cli",)
diff --git a/src/app.py b/src/app.py
index 0a9bd6a..0707eea 100644
--- a/src/app.py
+++ b/src/app.py
@@ -1,4 +1,5 @@
"""ASGI application factory."""
+
from __future__ import annotations
from typing import TYPE_CHECKING
diff --git a/src/byte/__init__.py b/src/byte/__init__.py
index e242444..44b0719 100644
--- a/src/byte/__init__.py
+++ b/src/byte/__init__.py
@@ -1,4 +1,5 @@
"""Byte Bot Bot."""
+
from __future__ import annotations
from byte import bot, lib, plugins, views
diff --git a/src/byte/bot.py b/src/byte/bot.py
index 456cd59..6d33e3d 100644
--- a/src/byte/bot.py
+++ b/src/byte/bot.py
@@ -1,4 +1,5 @@
"""Byte Bot."""
+
from __future__ import annotations
import contextlib
diff --git a/src/byte/lib/__init__.py b/src/byte/lib/__init__.py
index 28cfd13..412b7bf 100644
--- a/src/byte/lib/__init__.py
+++ b/src/byte/lib/__init__.py
@@ -1,10 +1,11 @@
"""Byte library module."""
-from byte.lib import common, log, settings, utils
+from byte.lib import common, log, settings, types, utils
__all__ = [
"settings",
"utils",
"log",
"common",
+ "types",
]
diff --git a/src/byte/lib/checks.py b/src/byte/lib/checks.py
new file mode 100644
index 0000000..e95a28d
--- /dev/null
+++ b/src/byte/lib/checks.py
@@ -0,0 +1,65 @@
+""":doc:`Checks ` for Byte."""
+
+from __future__ import annotations
+
+from typing import TYPE_CHECKING
+
+from discord.ext.commands import CheckFailure, Context, check
+
+from byte.lib import settings
+
+if TYPE_CHECKING:
+ from collections.abc import Callable
+
+ from discord.ext.commands._types import Check
+
+__all__ = ("is_byte_dev", "is_guild_admin")
+
+
+def is_guild_admin() -> Callable[[Context], Check]:
+ """Check if the user is a guild admin.
+
+ Returns:
+ A check function.
+ """
+
+ async def predicate(ctx: Context) -> bool:
+ """Check if the user is a guild admin.
+
+ Args:
+ ctx: Context object.
+
+ Returns:
+ True if the user is a guild admin, False otherwise.
+ """
+ if not (member := ctx.guild.get_member(ctx.author.id)):
+ msg = "Member not found in the guild."
+ raise CheckFailure(msg)
+ return member.guild_permissions.administrator
+
+ return check(predicate)
+
+
+def is_byte_dev() -> Callable[[Context], Check]:
+ """Determines if the user is a Byte developer or owner.
+
+ Returns:
+ A check function.
+ """
+
+ async def predicate(ctx: Context) -> bool:
+ """Check if the user is a Byte developer or owner.
+
+ Args:
+ ctx: Context object.
+
+ Returns:
+ True if the user is a Byte developer or owner, False otherwise.
+ """
+ return (
+ await ctx.bot.is_owner(ctx.author)
+ or ctx.author.id == settings.discord.DEV_USER_ID
+ or any(role.name == "byte-dev" for role in ctx.author.roles)
+ )
+
+ return check(predicate)
diff --git a/src/byte/lib/common/__init__.py b/src/byte/lib/common/__init__.py
index 5a7f255..4c23612 100644
--- a/src/byte/lib/common/__init__.py
+++ b/src/byte/lib/common/__init__.py
@@ -3,11 +3,55 @@
.. todo:: temporary, these are not multi-guild friendly.
"""
-from byte.lib.common import assets, colors, guilds, links
+from typing import Any
+
+from byte.lib.common import assets, colors, guilds, links, mention
__all__ = (
"assets",
"colors",
"guilds",
"links",
+ "config_options",
+ "mention",
)
+
+config_options: list[dict[str, Any]] = [
+ {
+ "label": "Server Settings",
+ "description": "Configure overall server settings",
+ "sub_settings": [
+ {"label": "Prefix", "field": "prefix", "data_type": "String"},
+ {"label": "Help Channel ID", "field": "help_channel_id", "data_type": "Integer"},
+ {"label": "Sync Label", "field": "sync_label", "data_type": "String"},
+ {"label": "Issue Linking", "field": "issue_linking", "data_type": "True/False"},
+ {"label": "Comment Linking", "field": "comment_linking", "data_type": "True/False"},
+ {"label": "PEP Linking", "field": "pep_linking", "data_type": "True/False"},
+ ],
+ },
+ {
+ "label": "GitHub Settings",
+ "description": "Configure GitHub settings",
+ "sub_settings": [
+ {"label": "Discussion Sync", "field": "discussion_sync", "data_type": "True/False"},
+ {"label": "GitHub Organization", "field": "github_organization", "data_type": "String"},
+ {"label": "GitHub Repository", "field": "github_repository", "data_type": "String"},
+ ],
+ },
+ {
+ "label": "StackOverflow Settings",
+ "description": "Configure StackOverflow settings",
+ "sub_settings": [
+ {"label": "Tag Name", "field": "tag_name", "data_type": "Comma-Separated String"},
+ ],
+ },
+ {
+ "label": "Allowed Users",
+ "description": "Configure allowed users",
+ "sub_settings": [
+ {"label": "User ID", "field": "user_id", "data_type": "Integer"},
+ ],
+ },
+ # Forum Settings: Configure help and showcase forum settings
+ # Byte Settings: Configure meta-level Byte features
+]
diff --git a/src/byte/lib/common/assets.py b/src/byte/lib/common/assets.py
index d478841..ea5e52d 100644
--- a/src/byte/lib/common/assets.py
+++ b/src/byte/lib/common/assets.py
@@ -2,6 +2,7 @@
.. todo:: temporary, these are not multi-guild friendly.
"""
+
from typing import Final
# --- Assets
diff --git a/src/byte/lib/common/colors.py b/src/byte/lib/common/colors.py
index cfa5795..622f0bb 100644
--- a/src/byte/lib/common/colors.py
+++ b/src/byte/lib/common/colors.py
@@ -2,6 +2,7 @@
.. todo:: temporary, these are not multi-guild friendly.
"""
+
from typing import Final
# --- Colors
diff --git a/src/byte/lib/common/guilds.py b/src/byte/lib/common/guilds.py
index cee58ae..6f05964 100644
--- a/src/byte/lib/common/guilds.py
+++ b/src/byte/lib/common/guilds.py
@@ -2,6 +2,7 @@
.. todo:: temporary, these are not multi-guild friendly.
"""
+
from typing import Final
# --- Channel IDs
diff --git a/src/byte/lib/common/links.py b/src/byte/lib/common/links.py
index a1f0d64..28eb128 100644
--- a/src/byte/lib/common/links.py
+++ b/src/byte/lib/common/links.py
@@ -2,6 +2,7 @@
.. todo:: temporary, these are not multi-guild friendly.
"""
+
from typing import Final
# --- Links
diff --git a/src/byte/lib/common/mention.py b/src/byte/lib/common/mention.py
new file mode 100644
index 0000000..f81c6ba
--- /dev/null
+++ b/src/byte/lib/common/mention.py
@@ -0,0 +1,129 @@
+"""Helper functions for mentioning users, roles, and channels."""
+
+from __future__ import annotations
+
+__all__ = (
+ "mention_channel",
+ "mention_custom_emoji",
+ "mention_custom_emoji_animated",
+ "mention_guild_navigation",
+ "mention_role",
+ "mention_slash_command",
+ "mention_timestamp",
+ "mention_user",
+ "mention_user_nickname",
+)
+
+
+def mention_user(user_id: int) -> str:
+ """Mention a user by ID.
+
+ Args:
+ user_id: The unique identifier for the user.
+
+ Returns:
+ A formatted string that mentions the user.
+ """
+ return f"<@{user_id}>"
+
+
+def mention_user_nickname(user_id: int) -> str:
+ """Mention a user by ID with a nickname.
+
+ Args:
+ user_id: The unique identifier for the user.
+
+ Returns:
+ A formatted string that mentions the user with a nickname.
+ """
+ return f"<@!{user_id}>"
+
+
+def mention_channel(channel_id: int) -> str:
+ """Mention a channel by ID.
+
+ Args:
+ channel_id: The unique identifier for the channel.
+
+ Returns:
+ A formatted string that mentions the channel.
+ """
+ return f"<#{channel_id}>"
+
+
+def mention_role(role_id: int) -> str:
+ """Mention a role by ID.
+
+ Args:
+ role_id: The unique identifier for the role.
+
+ Returns:
+ A formatted string that mentions the role.
+ """
+ return f"<@&{role_id}>"
+
+
+def mention_slash_command(name: str, command_id: int) -> str:
+ """Mention a slash command by name and ID.
+
+ Args:
+ name: The name of the slash command.
+ command_id: The unique identifier for the slash command.
+
+ Returns:
+ A formatted string that mentions the slash command.
+ """
+ return f"{name}:{command_id}>"
+
+
+def mention_custom_emoji(name: str, emoji_id: int) -> str:
+ """Mention a custom emoji by name and ID.
+
+ Args:
+ name: The name of the emoji.
+ emoji_id: The unique identifier for the emoji.
+
+ Returns:
+ A formatted string that mentions the custom emoji.
+ """
+ return f"<:{name}:{emoji_id}>"
+
+
+def mention_custom_emoji_animated(name: str, emoji_id: int) -> str:
+ """Mention an animated custom emoji by name and ID.
+
+ Args:
+ name: The name of the animated emoji.
+ emoji_id: The unique identifier for the animated emoji.
+
+ Returns:
+ A formatted string that mentions the animated custom emoji.
+ """
+ return f""
+
+
+def mention_timestamp(timestamp: int, style: str = "") -> str:
+ """Mention a timestamp, optionally with a style.
+
+ Args:
+ timestamp: The Unix timestamp to format.
+ style: An optional string representing the timestamp style.
+ (Default `` ``, valid styles: ``t``, ``T``, ``d``, ``D``, ``f``, ``F``, ``R``)
+
+ Returns:
+ A formatted string that represents the timestamp.
+ """
+ return f"" if style else f""
+
+
+def mention_guild_navigation(guild_nav_type: str, guild_element_id: int) -> str:
+ """Mention a guild navigation element by type and ID.
+
+ Args:
+ guild_nav_type: The type of the guild navigation element.
+ guild_element_id: The unique identifier for the element.
+
+ Returns:
+ A formatted string that mentions the guild navigation element.
+ """
+ return f"<{guild_element_id}:{guild_nav_type}>"
diff --git a/src/byte/lib/log.py b/src/byte/lib/log.py
index b42849e..c1373e3 100644
--- a/src/byte/lib/log.py
+++ b/src/byte/lib/log.py
@@ -1,4 +1,5 @@
"""Centralized logging configuration."""
+
import logging
import logging.config
import logging.handlers
@@ -72,6 +73,16 @@ def setup_logging() -> None:
"handlers": ["console", "file"],
"propagate": False,
},
+ "httpcore": {
+ "level": settings.log.HTTP_CORE_LEVEL,
+ "handlers": ["console", "file"],
+ "propagate": False,
+ },
+ "httpx": {
+ "level": settings.log.HTTPX_LEVEL,
+ "handlers": ["console", "file"],
+ "propagate": False,
+ },
"websockets": {
"level": settings.log.WEBSOCKETS_LEVEL,
"handlers": ["console", "file"],
diff --git a/src/byte/lib/settings.py b/src/byte/lib/settings.py
index e70cdbc..1dc0985 100644
--- a/src/byte/lib/settings.py
+++ b/src/byte/lib/settings.py
@@ -1,4 +1,5 @@
"""Project Settings."""
+
from __future__ import annotations
import os
@@ -106,6 +107,10 @@ class LogSettings(BaseSettings):
"""Sets the log level for the websockets library."""
ASYNCIO_LEVEL: int = 20
"""Sets the log level for the asyncio library."""
+ HTTP_CORE_LEVEL: int = 20
+ """Sets the log level for the httpcore library. (Used in cert. validation)"""
+ HTTPX_LEVEL: int = 30
+ """Sets the log level for the httpx library."""
FORMAT: str = "[[ %(asctime)s ]] - [[ %(name)s ]] - [[ %(levelname)s ]] - %(message)s"
"""Log format string."""
FILE: Path = BASE_DIR / "logs" / "byte.log"
diff --git a/src/byte/lib/types/__init__.py b/src/byte/lib/types/__init__.py
new file mode 100644
index 0000000..7e42cd8
--- /dev/null
+++ b/src/byte/lib/types/__init__.py
@@ -0,0 +1,5 @@
+"""Types and similar facilities used throughout library code."""
+
+from byte.lib.types import astral, python
+
+__all__ = ("astral", "python")
diff --git a/src/byte/lib/types/astral.py b/src/byte/lib/types/astral.py
new file mode 100644
index 0000000..cf0ee23
--- /dev/null
+++ b/src/byte/lib/types/astral.py
@@ -0,0 +1,32 @@
+"""Types for Astral views and plugins."""
+
+from __future__ import annotations
+
+from typing import TypedDict
+
+__all__ = ("BaseRuffRule", "FormattedRuffRule", "RuffRule")
+
+
+class BaseRuffRule(TypedDict):
+ """Base Ruff rule data."""
+
+ name: str
+ summary: str
+ fix: str
+ explanation: str
+
+
+class RuffRule(BaseRuffRule):
+ """Ruff rule data."""
+
+ code: str
+ linter: str
+ message_formats: list[str]
+ preview: bool
+
+
+class FormattedRuffRule(BaseRuffRule):
+ """Formatted Ruff rule data."""
+
+ rule_link: str
+ rule_anchor_link: str
diff --git a/src/byte/lib/types/python.py b/src/byte/lib/types/python.py
new file mode 100644
index 0000000..f9c3123
--- /dev/null
+++ b/src/byte/lib/types/python.py
@@ -0,0 +1,77 @@
+"""Types for Python related views and plugins."""
+
+from __future__ import annotations
+
+from enum import StrEnum
+from typing import TYPE_CHECKING, TypedDict
+
+if TYPE_CHECKING:
+ from datetime import datetime
+
+__all__ = ("PEP", "PEPHistoryItem", "PEPStatus", "PEPType")
+
+
+class PEPType(StrEnum):
+ """Type of PEP.
+
+ Based off of `PEP Types in PEP1 `_.
+ """
+
+ I = "Informational" # noqa: E741
+ P = "Process"
+ S = "Standards Track"
+
+
+class PEPStatus(StrEnum):
+ """Status of a PEP.
+
+ .. note:: ``Active`` and ``Accepted`` both traditionally use ``A``,
+ but are differentiated here for clarity.
+
+ Based off of `PEP Status in PEP1 `_.
+ """
+
+ A = "Active"
+ AA = "Accepted"
+ D = "Deferred"
+ __ = "Draft"
+ F = "Final"
+ P = "Provisional"
+ R = "Rejected"
+ S = "Superseded"
+ W = "Withdrawn"
+
+
+class PEPHistoryItem(TypedDict, total=False):
+ """PEP history item.
+
+ Sometimes these include a list of ``datetime`` objects,
+ other times they are a list of datetime and str
+ because they contain a date and an rST link.
+ """
+
+ date: str
+ link: str
+
+
+class PEP(TypedDict):
+ """PEP data.
+
+ Based off of the `PEPS API `_.
+ """
+
+ number: int
+ title: str
+ authors: list[str] | str
+ discussions_to: str
+ status: PEPStatus
+ type: PEPType
+ topic: str
+ created: datetime
+ python_version: list[float] | float
+ post_history: list[str]
+ resolution: str | None
+ requires: str | None
+ replaces: str | None
+ superseded_by: str | None
+ url: str
diff --git a/src/byte/lib/utils.py b/src/byte/lib/utils.py
index 4f18d76..8e60f75 100644
--- a/src/byte/lib/utils.py
+++ b/src/byte/lib/utils.py
@@ -1,196 +1,42 @@
"""Byte utilities."""
+
from __future__ import annotations
+import datetime as dt
import json
import re
import subprocess
from datetime import UTC, datetime
-from enum import StrEnum
from itertools import islice
-from typing import TYPE_CHECKING, TypedDict, TypeVar
+from typing import TYPE_CHECKING, TypeVar
import httpx
from anyio import run_process
-from discord.ext import commands
from ruff.__main__ import find_ruff_bin # type: ignore[import-untyped]
-from byte.lib import settings
from byte.lib.common.links import pastebin
+from byte.lib.types.python import PEP, PEPStatus, PEPType
if TYPE_CHECKING:
from collections.abc import Iterable
- from typing import Any
- from discord.ext.commands import Context
- from discord.ext.commands._types import Check
+ from byte.lib.types.astral import FormattedRuffRule, RuffRule
__all__ = (
- "BaseRuffRule",
- "RuffRule",
- "FormattedRuffRule",
- "PEP",
- "PEPType",
- "PEPStatus",
- "PEPHistoryItem",
- "is_guild_admin",
- "is_byte_dev",
- "linker",
- "mention_user",
- "mention_user_nickname",
- "mention_channel",
- "mention_role",
- "mention_slash_command",
- "mention_custom_emoji",
- "mention_custom_emoji_animated",
- "mention_timestamp",
- "mention_guild_navigation",
+ "chunk_sequence",
+ "format_resolution_link",
"format_ruff_rule",
- "query_all_ruff_rules",
- "run_ruff_format",
+ "get_next_friday",
+ "linker",
"paste",
- "chunk_sequence",
"query_all_peps",
+ "query_all_ruff_rules",
+ "run_ruff_format",
)
_T = TypeVar("_T")
-class BaseRuffRule(TypedDict):
- """Base Ruff rule data."""
-
- name: str
- summary: str
- fix: str
- explanation: str
-
-
-class RuffRule(BaseRuffRule):
- """Ruff rule data."""
-
- code: str
- linter: str
- message_formats: list[str]
- preview: bool
-
-
-class FormattedRuffRule(BaseRuffRule):
- """Formatted Ruff rule data."""
-
- rule_link: str
- rule_anchor_link: str
-
-
-class PEPType(StrEnum):
- """Type of PEP.
-
- Based off of `PEP Types in PEP1 `_.
- """
-
- I = "Informational" # noqa: E741
- P = "Process"
- S = "Standards Track"
-
-
-class PEPStatus(StrEnum):
- """Status of a PEP.
-
- .. note:: ``Active`` and ``Accepted`` both traditionally use ``A``,
- but are differentiated here for clarity.
-
- Based off of `PEP Status in PEP1 `_.
- """
-
- A = "Active"
- AA = "Accepted"
- D = "Deferred"
- __ = "Draft"
- F = "Final"
- P = "Provisional"
- R = "Rejected"
- S = "Superseded"
- W = "Withdrawn"
-
-
-class PEPHistoryItem(TypedDict, total=False):
- """PEP history item.
-
- Sometimes these include a list of ``datetime`` objects,
- other times they are a list of datetime and str
- because they contain a date and an rST link.
- """
-
- date: str
- link: str
-
-
-class PEP(TypedDict):
- """PEP data.
-
- Based off of the `PEPS API `_.
- """
-
- number: int
- title: str
- authors: list[str] | str
- discussions_to: str
- status: PEPStatus
- type: PEPType
- topic: str
- created: datetime
- python_version: list[float] | float
- post_history: list[str]
- resolution: str | None
- requires: str | None
- replaces: str | None
- superseded_by: str | None
- url: str
-
-
-def is_guild_admin() -> Check[Any]:
- """Check if the user is a guild admin.
-
- Returns:
- A check function.
- """
-
- async def predicate(ctx: Context) -> bool:
- """Check if the user is a guild admin.
-
- Args:
- ctx: Context object.
-
- Returns:
- True if the user is a guild admin, False otherwise.
- """
- return ctx.author.guild_permissions.administrator
-
- return commands.check(predicate)
-
-
-def is_byte_dev() -> Check[Any]:
- """Check if the user is a Byte developer.
-
- Returns:
- A check function.
- """
-
- async def predicate(ctx: Context) -> bool:
- """Check if the user is a Byte Dev or Owner.
-
- Args:
- ctx: Context object.
-
- Returns:
- True if the user is a Byte Dev or Owner, False otherwise.
- """
- if await ctx.bot.is_owner(ctx.author) or ctx.author.id == settings.discord.DEV_USER_ID:
- return True
-
- return any(role.name == "byte-dev" for role in ctx.author.roles) # type: ignore[reportAttributeAccessIssue]
-
- return commands.check(predicate)
-
-
def linker(title: str, link: str, show_embed: bool = False) -> str:
"""Create a Markdown link, optionally with an embed.
@@ -205,120 +51,6 @@ def linker(title: str, link: str, show_embed: bool = False) -> str:
return f"[{title}]({link})" if show_embed else f"[{title}](<{link}>)"
-def mention_user(user_id: int) -> str:
- """Mention a user by ID.
-
- Args:
- user_id: The unique identifier for the user.
-
- Returns:
- A formatted string that mentions the user.
- """
- return f"<@{user_id}>"
-
-
-def mention_user_nickname(user_id: int) -> str:
- """Mention a user by ID with a nickname.
-
- Args:
- user_id: The unique identifier for the user.
-
- Returns:
- A formatted string that mentions the user with a nickname.
- """
- return f"<@!{user_id}>"
-
-
-def mention_channel(channel_id: int) -> str:
- """Mention a channel by ID.
-
- Args:
- channel_id: The unique identifier for the channel.
-
- Returns:
- A formatted string that mentions the channel.
- """
- return f"<#{channel_id}>"
-
-
-def mention_role(role_id: int) -> str:
- """Mention a role by ID.
-
- Args:
- role_id: The unique identifier for the role.
-
- Returns:
- A formatted string that mentions the role.
- """
- return f"<@&{role_id}>"
-
-
-def mention_slash_command(name: str, command_id: int) -> str:
- """Mention a slash command by name and ID.
-
- Args:
- name: The name of the slash command.
- command_id: The unique identifier for the slash command.
-
- Returns:
- A formatted string that mentions the slash command.
- """
- return f"{name}:{command_id}>"
-
-
-def mention_custom_emoji(name: str, emoji_id: int) -> str:
- """Mention a custom emoji by name and ID.
-
- Args:
- name: The name of the emoji.
- emoji_id: The unique identifier for the emoji.
-
- Returns:
- A formatted string that mentions the custom emoji.
- """
- return f"<:{name}:{emoji_id}>"
-
-
-def mention_custom_emoji_animated(name: str, emoji_id: int) -> str:
- """Mention an animated custom emoji by name and ID.
-
- Args:
- name: The name of the animated emoji.
- emoji_id: The unique identifier for the animated emoji.
-
- Returns:
- A formatted string that mentions the animated custom emoji.
- """
- return f""
-
-
-def mention_timestamp(timestamp: int, style: str = "") -> str:
- """Mention a timestamp, optionally with a style.
-
- Args:
- timestamp: The Unix timestamp to format.
- style: An optional string representing the timestamp style.
- (Default `` ``, valid styles: ``t``, ``T``, ``d``, ``D``, ``f``, ``F``, ``R``)
-
- Returns:
- A formatted string that represents the timestamp.
- """
- return f"" if style else f""
-
-
-def mention_guild_navigation(guild_nav_type: str, guild_element_id: int) -> str:
- """Mention a guild navigation element by type and ID.
-
- Args:
- guild_nav_type: The type of the guild navigation element.
- guild_element_id: The unique identifier for the element.
-
- Returns:
- A formatted string that mentions the guild navigation element.
- """
- return f"<{guild_element_id}:{guild_nav_type}>"
-
-
def format_ruff_rule(rule_data: RuffRule) -> FormattedRuffRule:
"""Format ruff rule data for embed-friendly output and append rule link.
@@ -467,3 +199,25 @@ async def query_all_peps() -> list[PEP]:
}
for pep_info in data.values()
]
+
+
+def get_next_friday(now: datetime, delay: int | None = None) -> tuple[datetime, datetime]:
+ """Calculate the next Friday from ``now``.
+
+ If ``delay``, calculate the Friday for ``delay`` weeks from now.
+
+ Args:
+ now: The current date and time.
+ delay: The number of weeks to delay the calculation.
+
+ Returns:
+ datetime: The next Friday, optionally for the week after next.
+ """
+ days_ahead = 4 - now.weekday()
+ if days_ahead < 0:
+ days_ahead += 7
+ if delay:
+ days_ahead += 7 * delay
+ start_dt = (now + dt.timedelta(days=days_ahead)).replace(hour=11, minute=0, second=0, microsecond=0)
+ end_dt = start_dt + dt.timedelta(hours=1)
+ return start_dt, end_dt
diff --git a/src/byte/plugins/admin.py b/src/byte/plugins/admin.py
index ac80a6a..a84e3bc 100644
--- a/src/byte/plugins/admin.py
+++ b/src/byte/plugins/admin.py
@@ -2,15 +2,16 @@
.. todo:: add an unload cog command.
"""
+
from discord import Interaction
from discord.app_commands import command as app_command
from discord.ext import commands
from discord.ext.commands import Bot, Cog, Context, command, group, is_owner
-from byte.lib.utils import is_byte_dev
-
__all__ = ("AdminCommands", "setup")
+from byte.lib.checks import is_byte_dev
+
class AdminCommands(Cog):
"""Admin command cog."""
diff --git a/src/byte/plugins/astral.py b/src/byte/plugins/astral.py
index 5fb9f1e..89894f6 100644
--- a/src/byte/plugins/astral.py
+++ b/src/byte/plugins/astral.py
@@ -1,4 +1,5 @@
"""Plugins for Astral Inc. related software, including Ruff, uv, etc."""
+
from __future__ import annotations
from typing import TYPE_CHECKING
@@ -14,7 +15,7 @@
from byte.views.astral import RuffView
if TYPE_CHECKING:
- from byte.lib.utils import RuffRule
+ from byte.lib.types.astral import RuffRule
__all__ = ("Astral", "setup")
@@ -32,10 +33,10 @@ def __init__(self, bot: Bot, rules: list[RuffRule]) -> None:
async def _rule_autocomplete(self, _: Interaction, current_rule: str) -> list[Choice[str]]:
# TODO: this can and should be made faster, rn this is slow, slow like the maintainer
return [
- Choice(name=f'{code} - {rule["name"]}', value=code)
- for code, rule in self._rules.items()
- if current_rule.lower() in code.lower()
- ][:25]
+ Choice(name=f'{code} - {rule["name"]}', value=code)
+ for code, rule in self._rules.items()
+ if current_rule.lower() in code.lower()
+ ][:25]
@app_command(name="ruff")
@autocomplete(rule=_rule_autocomplete)
diff --git a/src/byte/plugins/config.py b/src/byte/plugins/config.py
new file mode 100644
index 0000000..5dfc7e3
--- /dev/null
+++ b/src/byte/plugins/config.py
@@ -0,0 +1,69 @@
+"""Plugins for guild admins to configure Byte and its features."""
+
+from __future__ import annotations
+
+from typing import TYPE_CHECKING
+
+from discord.app_commands import Choice, autocomplete
+from discord.app_commands import command as app_command
+from discord.ext.commands import Bot, Cog
+
+from byte.lib.common import config_options
+from byte.views.config import ConfigView
+
+if TYPE_CHECKING:
+ from discord import Interaction
+
+__all__ = ("Config", "setup")
+
+
+class Config(Cog):
+ """Config cog."""
+
+ def __init__(self, bot: Bot) -> None:
+ """Initialize cog."""
+ self.bot = bot
+ self.__cog_name__ = "Config Commands"
+ self.config_options = config_options
+
+ async def _config_autocomplete(self, interaction: Interaction, current: str) -> list[Choice[str]]: # noqa: ARG002
+ """Autocomplete config for the config dropdown (up?) slash command."""
+ return [
+ Choice(name=f"{option['label']} - {option['description']}", value=option["label"])
+ for option in config_options
+ if current.lower() in option["label"].lower()
+ ][:25]
+
+ @app_command(name="config")
+ @autocomplete(setting=_config_autocomplete)
+ async def config_rule(self, interaction: Interaction, setting: str | None = None) -> None:
+ """Slash command to configure Byte.
+
+ Args:
+ interaction: Interaction object.
+ setting: The setting to configure.
+ """
+ if setting:
+ if selected_option := next(
+ (option for option in config_options if option["label"] == setting),
+ None,
+ ):
+ view = ConfigView(preselected=selected_option["label"])
+ await interaction.response.send_message(
+ f"Configure {selected_option['label']}:",
+ view=view,
+ ephemeral=True,
+ )
+ else:
+ await interaction.response.send_message(
+ f"Invalid setting: {setting}. Please select a valid setting.",
+ ephemeral=True,
+ )
+ else:
+ view = ConfigView()
+ await interaction.response.send_message("Select a configuration option:", view=view, ephemeral=True)
+
+
+async def setup(bot: Bot) -> None:
+ """Set up the config cog."""
+ await bot.add_cog(Config(bot))
diff --git a/src/byte/plugins/custom/litestar.py b/src/byte/plugins/custom/litestar.py
index c205ab4..efe458c 100644
--- a/src/byte/plugins/custom/litestar.py
+++ b/src/byte/plugins/custom/litestar.py
@@ -1,11 +1,18 @@
"""Custom plugins for the Litestar Discord."""
+
from __future__ import annotations
-from discord import Embed
+import datetime
+
+from dateutil.zoneinfo import gettz
+from discord import Embed, EntityType, Interaction, Object, PrivacyLevel
+from discord.app_commands import command as app_command
from discord.ext.commands import Bot, Cog, Context, command, group, is_owner
+from byte.lib.checks import is_byte_dev
from byte.lib.common.colors import litestar_yellow
-from byte.lib.utils import is_byte_dev, mention_role, mention_user
+from byte.lib.common.mention import mention_role, mention_user
+from byte.lib.utils import get_next_friday
__all__ = ("LitestarCommands", "setup")
@@ -85,6 +92,50 @@ async def apply_role_embed(self, ctx: Context[Bot]) -> None:
await ctx.send(embed=embed)
+ @app_command(
+ name="schedule-office-hours",
+ description="Schedule Office Hours event for the upcoming or the week after next Friday.",
+ )
+ async def schedule_office_hours(self, interaction: Interaction, delay: int | None = None) -> None:
+ """Schedule Office Hours event for the upcoming or ``delay`` weeks after next Friday.
+
+ Args:
+ interaction: Interaction object.
+ delay: Optional. Number of weeks to delay the event.
+ """
+ now_cst = datetime.datetime.now(gettz("America/Chicago"))
+ start_dt, end_dt = get_next_friday(now_cst, delay)
+ existing_events = interaction.guild.scheduled_events
+
+ for event in existing_events:
+ if (
+ event.name == "Office Hours"
+ and event.start_time.astimezone(gettz("America/Chicago")).date() == start_dt.date()
+ ):
+ await interaction.response.send_message(
+ "An Office Hours event is already scheduled for that day.", ephemeral=True
+ )
+ return
+
+ await interaction.guild.create_scheduled_event(
+ name="Office Hours",
+ start_time=start_dt,
+ end_time=end_dt,
+ description="Join us for our weekly office hours!",
+ entity_type=EntityType.stage_instance,
+ privacy_level=PrivacyLevel.guild_only,
+ reason=f"Scheduled by {interaction.user} via /schedule-office-hours",
+ channel=Object(id=1215926860144443502),
+ )
+
+ formatted_date = f""
+ start_time_formatted = f""
+ end_time_formatted = f""
+
+ await interaction.response.send_message(
+ f"Office Hours event scheduled: {formatted_date} from {start_time_formatted} - {end_time_formatted}."
+ )
+
async def setup(bot: Bot) -> None:
"""Add cog to bot.
diff --git a/src/byte/plugins/events.py b/src/byte/plugins/events.py
index feec474..2a96621 100644
--- a/src/byte/plugins/events.py
+++ b/src/byte/plugins/events.py
@@ -1,4 +1,5 @@
"""Plugins for events."""
+
from threading import Thread
from typing import cast
diff --git a/src/byte/plugins/general.py b/src/byte/plugins/general.py
index c034d71..17b155e 100644
--- a/src/byte/plugins/general.py
+++ b/src/byte/plugins/general.py
@@ -1,4 +1,5 @@
"""General plugins to be used wherever."""
+
from __future__ import annotations
from discord import Embed, Interaction
@@ -36,7 +37,7 @@ async def show_paste(self, interaction: Interaction) -> None:
embed.add_field(
name="Syntax Highlighting",
value="You can also use backticks to format your code. Read about it in the "
- f"{linker('Discord Markdown Guide', markdown_guide)}.",
+ f"{linker('Discord Markdown Guide', markdown_guide)}.",
)
embed.set_thumbnail(url=litestar_logo_yellow)
diff --git a/src/byte/plugins/github.py b/src/byte/plugins/github.py
index 680018e..4033e03 100644
--- a/src/byte/plugins/github.py
+++ b/src/byte/plugins/github.py
@@ -1,4 +1,5 @@
"""Plugins for GitHub interactions."""
+
from __future__ import annotations
from typing import Self
diff --git a/src/byte/plugins/python.py b/src/byte/plugins/python.py
index 900da80..b9b97ea 100644
--- a/src/byte/plugins/python.py
+++ b/src/byte/plugins/python.py
@@ -1,4 +1,5 @@
"""Plugins for Python related things, including PyPI, PEPs, etc."""
+
from __future__ import annotations
from discord import Embed, Interaction
diff --git a/src/byte/plugins/testing.py b/src/byte/plugins/testing.py
index b258db8..81734e1 100644
--- a/src/byte/plugins/testing.py
+++ b/src/byte/plugins/testing.py
@@ -1,4 +1,5 @@
"""Plugins for testing purposes."""
+
from discord.ext.commands import Bot, Cog, Context, command, group
diff --git a/src/byte/views/abstract_views.py b/src/byte/views/abstract_views.py
index f51d4e2..333ae7a 100644
--- a/src/byte/views/abstract_views.py
+++ b/src/byte/views/abstract_views.py
@@ -1,25 +1,30 @@
"""Inheritable views that include extra functionality for base Views classes."""
+
from __future__ import annotations
from copy import deepcopy
-from typing import TYPE_CHECKING, Any, Literal, TypedDict
+from typing import TYPE_CHECKING, Any, Literal, ParamSpec, TypedDict
from discord import ButtonStyle, Colour, Embed, Interaction
from discord.ui import Button, View, button
if TYPE_CHECKING:
from datetime import datetime
- from typing import Self, NotRequired
+ from typing import NotRequired, Self
from discord.ext.commands import Bot
__all__ = ("ExtendedEmbed", "Field", "ButtonEmbedView")
+P = ParamSpec("P")
+
class ButtonEmbedView(View):
"""Base view including common buttons."""
- def __init__(self, author: int, bot: Bot, original_embed: Embed, minified_embed: Embed, *args, **kwargs) -> None:
+ def __init__(
+ self, author: int, bot: Bot, original_embed: Embed, minified_embed: Embed, *args: P.args, **kwargs: P.kwargs
+ ) -> None:
"""Initialize the view.
Args:
diff --git a/src/byte/views/astral.py b/src/byte/views/astral.py
index 2e77494..47dc3ca 100644
--- a/src/byte/views/astral.py
+++ b/src/byte/views/astral.py
@@ -1,4 +1,5 @@
"""Discord UI views used in Astral commands."""
+
from __future__ import annotations
from byte.lib.log import get_logger
diff --git a/src/byte/views/config.py b/src/byte/views/config.py
new file mode 100644
index 0000000..492dd27
--- /dev/null
+++ b/src/byte/views/config.py
@@ -0,0 +1,263 @@
+"""Discord UI views used in Byte config commands."""
+
+from __future__ import annotations
+
+from typing import Any
+
+from discord import ButtonStyle, Interaction, SelectOption, TextStyle
+from discord.ui import Button, Modal, Select, TextInput, View
+
+from byte.lib.common import config_options
+from byte.lib.log import get_logger
+
+__all__ = ("ConfigView",)
+
+logger = get_logger()
+
+
+class FinishButton(Button):
+ """Finish button."""
+
+ def __init__(self) -> None:
+ """Initialize button."""
+ super().__init__(style=ButtonStyle.success, label="Finished")
+
+ async def callback(self, interaction: Interaction) -> None:
+ """Callback for button.
+
+ Args:
+ interaction: Interaction object.
+ """
+ await interaction.response.send_message("Configuration complete!", ephemeral=True)
+ self.view.stop()
+
+
+class BackButton(Button):
+ """Back button."""
+
+ def __init__(self) -> None:
+ """Initialize button."""
+ super().__init__(style=ButtonStyle.secondary, label="Back")
+
+ async def callback(self, interaction: Interaction) -> None:
+ """Callback for button.
+
+ Args:
+ interaction: Interaction object.
+ """
+ view = ConfigView()
+ await interaction.response.edit_message(content="Select a configuration option:", view=view)
+
+
+class CancelButton(Button):
+ """Cancel button."""
+
+ def __init__(self) -> None:
+ """Initialize button."""
+ super().__init__(style=ButtonStyle.danger, label="Cancel")
+
+ async def callback(self, interaction: Interaction) -> None:
+ """Callback for button.
+
+ Args:
+ interaction: Interaction object.
+ """
+ await interaction.response.send_message("Configuration cancelled.", ephemeral=True)
+ self.view.stop()
+
+
+class ConfigSelect(Select):
+ """Configuration select dropdown menu."""
+
+ def __init__(self, preselected: str | None = None) -> None:
+ """Initialize select.
+
+ Args:
+ preselected: Preselected option, if given.
+ """
+ options = [SelectOption(label=option["label"], description=option["description"]) for option in config_options]
+ super().__init__(placeholder="Choose a setting...", min_values=1, max_values=1, options=options)
+
+ if preselected:
+ for option in options:
+ if option.label == preselected:
+ option.default = True
+ break
+
+ async def callback(self, interaction: Interaction) -> None:
+ """Callback for select.
+
+ Args:
+ interaction: Interaction object.
+ """
+ selected_option = next(option for option in config_options if option["label"] == self.values[0])
+ if "sub_settings" in selected_option:
+ view = ConfigKeyView(selected_option)
+ await interaction.response.edit_message(content=f"Select a key for {selected_option['label']}:", view=view)
+ else:
+ modal = ConfigModal(title=f"Configure {selected_option['label']}")
+ await interaction.response.send_modal(modal)
+
+
+class ConfigKeySelect(Select):
+ """Configuration key select dropdown menu."""
+
+ def __init__(self, option: dict[str, Any]) -> None:
+ """Initialize select.
+
+ Args:
+ option: The selected configuration option.
+ """
+ self.option = option
+ options = [
+ SelectOption(label=sub_setting["label"], description=sub_setting.get("description", ""))
+ for sub_setting in option["sub_settings"]
+ ]
+ super().__init__(placeholder="Choose a key...", min_values=1, max_values=1, options=options)
+
+ async def callback(self, interaction: Interaction) -> None:
+ """Callback for select.
+
+ Args:
+ interaction: Interaction object.
+ """
+ selected_sub_setting = self.values[0]
+ selected_sub_setting = next(
+ sub_setting for sub_setting in self.option["sub_settings"] if sub_setting["label"] == selected_sub_setting
+ )
+ modal = ConfigModal(
+ title=f"{self.option['label']} - {selected_sub_setting['label']}",
+ sub_setting=selected_sub_setting,
+ option=self.option,
+ )
+ await interaction.response.send_modal(modal)
+
+
+class ConfigView(View):
+ """Configuration view."""
+
+ def __init__(self, preselected: str | None = None) -> None:
+ """Initialize view.
+
+ Args:
+ preselected: Preselected option, if given.
+ """
+ super().__init__(timeout=None)
+ self.add_item(ConfigSelect(preselected))
+ self.add_item(FinishButton())
+ self.add_item(CancelButton())
+
+
+class ConfigKeyView(View):
+ """Configuration key view."""
+
+ def __init__(self, option: dict[str, Any]) -> None:
+ """Initialize view.
+
+ Args:
+ option: The selected configuration option.
+ """
+ super().__init__(timeout=None)
+ self.add_item(ConfigKeySelect(option))
+ self.add_item(BackButton())
+ self.add_item(CancelButton())
+
+
+class ConfigModal(Modal):
+ """Configuration modal."""
+
+ def __init__(
+ self,
+ title: str,
+ sub_setting: dict[str, str] | None = None,
+ sub_settings: list[dict[str, str]] | None = None,
+ option: dict[str, Any] | None = None,
+ ) -> None:
+ """Initialize modal.
+
+ Args:
+ title: Title of modal.
+ sub_setting: The selected sub-setting, if applicable.
+ sub_settings: List of sub-settings, if configuring all keys.
+ option: The selected configuration option, if applicable.
+ """
+ super().__init__(title=title + "\n\n")
+ self.option = option
+
+ if sub_settings:
+ for sub_setting in sub_settings:
+ self.add_item(
+ TextInput(
+ label=sub_setting["label"],
+ style=TextStyle.short,
+ custom_id=sub_setting["field"],
+ placeholder=f"Enter {sub_setting['label']} ({sub_setting['data_type']})",
+ required=True,
+ min_length=4 if sub_setting["data_type"] == "True/False" else 1,
+ max_length=5
+ if sub_setting["data_type"] == "True/False"
+ else 100
+ if sub_setting["data_type"] in ["String", "Integer"]
+ else 300
+ if sub_setting["data_type"] == "Comma-separated list"
+ else None,
+ )
+ )
+ elif sub_setting:
+ self.add_item(
+ TextInput(
+ label=sub_setting["label"],
+ style=TextStyle.short,
+ placeholder=f"Enter {sub_setting['label']} ({sub_setting['data_type']})",
+ required=True,
+ min_length=4 if sub_setting["data_type"] == "True/False" else 1,
+ max_length=5
+ if sub_setting["data_type"] == "True/False"
+ else 100
+ if sub_setting["data_type"] in ["String", "Integer"]
+ else 300
+ if sub_setting["data_type"] == "Comma-separated list"
+ else None,
+ )
+ )
+ else:
+ self.add_item(
+ TextInput(
+ label="Configuration Value",
+ style=TextStyle.short,
+ placeholder="Enter your configuration value...",
+ required=True,
+ )
+ )
+
+ async def on_submit(self, interaction: Interaction) -> None:
+ """Handle modal submission.
+
+ Args:
+ interaction: Interaction object.
+ """
+ config_values = {item.custom_id: item.value for item in self.children if hasattr(item, "custom_id")}
+ await interaction.response.send_message(f"Configuration values received: {config_values}", ephemeral=True)
+
+ if self.option:
+ view = ConfigKeyView(self.option)
+ await interaction.followup.send(
+ f"Select another key for {self.option['label']} or click 'Back' to return to the main menu.",
+ view=view,
+ ephemeral=True,
+ )
+ else:
+ view = ConfigView()
+ await interaction.followup.send(
+ "Select another setting or click 'Finished' when done.", view=view, ephemeral=True
+ )
+
+ async def on_error(self, interaction: Interaction, error: Exception) -> None:
+ """Handle modal submission error.
+
+ Args:
+ interaction: Interaction object.
+ error: Error object.
+ """
+ await interaction.response.send_message("Oops! Something went wrong.", ephemeral=True)
+ logger.exception("Error occurred while processing config modal submission", exc_info=error)
diff --git a/src/byte/views/python.py b/src/byte/views/python.py
index 795514c..00989d5 100644
--- a/src/byte/views/python.py
+++ b/src/byte/views/python.py
@@ -1,4 +1,5 @@
"""Discord UI views used in Python commands."""
+
from __future__ import annotations
from byte.lib.log import get_logger
diff --git a/src/cli.py b/src/cli.py
index 3792729..78534dc 100644
--- a/src/cli.py
+++ b/src/cli.py
@@ -1,4 +1,5 @@
"""Project CLI."""
+
from __future__ import annotations
import multiprocessing
diff --git a/src/server/__init__.py b/src/server/__init__.py
index e2374c1..f3a871a 100644
--- a/src/server/__init__.py
+++ b/src/server/__init__.py
@@ -1,4 +1,5 @@
"""Byte Bot Server."""
+
from __future__ import annotations
from server import domain, lib
diff --git a/src/server/domain/__init__.py b/src/server/domain/__init__.py
index 768c733..bea0a22 100644
--- a/src/server/domain/__init__.py
+++ b/src/server/domain/__init__.py
@@ -1,4 +1,5 @@
"""Application Modules."""
+
from __future__ import annotations
from typing import TYPE_CHECKING
diff --git a/src/server/domain/db/__init__.py b/src/server/domain/db/__init__.py
index ea8a50c..c8a8fea 100644
--- a/src/server/domain/db/__init__.py
+++ b/src/server/domain/db/__init__.py
@@ -1,4 +1,5 @@
"""Domain for database models."""
+
from server.domain.db import models
__all__ = ["models"]
diff --git a/src/server/domain/db/models.py b/src/server/domain/db/models.py
index f57e256..ecbe42f 100644
--- a/src/server/domain/db/models.py
+++ b/src/server/domain/db/models.py
@@ -1,4 +1,5 @@
"""Shared models."""
+
from __future__ import annotations
from uuid import UUID # noqa: TCH003
diff --git a/src/server/domain/github/helpers.py b/src/server/domain/github/helpers.py
index edf4bcc..fbab915 100644
--- a/src/server/domain/github/helpers.py
+++ b/src/server/domain/github/helpers.py
@@ -1,4 +1,5 @@
"""Helper functions for use within the GitHub domain."""
+
from __future__ import annotations
from githubkit import AppInstallationAuthStrategy, GitHub # type: ignore[reportMissingImports]
diff --git a/src/server/domain/guilds/controllers.py b/src/server/domain/guilds/controllers.py
index 21d53f4..fca75d3 100644
--- a/src/server/domain/guilds/controllers.py
+++ b/src/server/domain/guilds/controllers.py
@@ -1,4 +1,5 @@
"""Guild controller."""
+
from __future__ import annotations
from typing import TYPE_CHECKING
diff --git a/src/server/domain/guilds/dependencies.py b/src/server/domain/guilds/dependencies.py
index b84c34d..1d3ef92 100644
--- a/src/server/domain/guilds/dependencies.py
+++ b/src/server/domain/guilds/dependencies.py
@@ -1,4 +1,5 @@
"""Dependencies for guilds."""
+
from __future__ import annotations
from typing import TYPE_CHECKING
diff --git a/src/server/domain/guilds/helpers.py b/src/server/domain/guilds/helpers.py
index 6d0ec14..e1edd15 100644
--- a/src/server/domain/guilds/helpers.py
+++ b/src/server/domain/guilds/helpers.py
@@ -1,4 +1,5 @@
"""Helper functions to be used for interacting with Guild data."""
+
from __future__ import annotations
from server.domain.guilds.dependencies import provides_guilds_service
diff --git a/src/server/domain/guilds/schemas.py b/src/server/domain/guilds/schemas.py
index 89a2158..4110589 100644
--- a/src/server/domain/guilds/schemas.py
+++ b/src/server/domain/guilds/schemas.py
@@ -1,4 +1,5 @@
"""API Schemas for guild domain."""
+
from __future__ import annotations
from uuid import UUID # noqa: TCH003
diff --git a/src/server/domain/guilds/services.py b/src/server/domain/guilds/services.py
index c207966..96f1260 100644
--- a/src/server/domain/guilds/services.py
+++ b/src/server/domain/guilds/services.py
@@ -1,4 +1,5 @@
"""Guild services."""
+
from __future__ import annotations
from typing import Any
diff --git a/src/server/domain/guilds/urls.py b/src/server/domain/guilds/urls.py
index 0ec7c1c..42989d9 100644
--- a/src/server/domain/guilds/urls.py
+++ b/src/server/domain/guilds/urls.py
@@ -1,4 +1,5 @@
"""Guild URLs."""
+
from __future__ import annotations
from typing import Final
diff --git a/src/server/domain/system/__init__.py b/src/server/domain/system/__init__.py
index bde82a7..bf4e867 100644
--- a/src/server/domain/system/__init__.py
+++ b/src/server/domain/system/__init__.py
@@ -1,4 +1,5 @@
"""System domain."""
+
from __future__ import annotations
from server.domain.system import controllers, dtos, helpers
diff --git a/src/server/domain/system/controllers/__init__.py b/src/server/domain/system/controllers/__init__.py
index dc0d429..43c936a 100644
--- a/src/server/domain/system/controllers/__init__.py
+++ b/src/server/domain/system/controllers/__init__.py
@@ -1,4 +1,5 @@
"""System domain controllers."""
+
from __future__ import annotations
from server.domain.system.controllers import system
diff --git a/src/server/domain/system/controllers/system.py b/src/server/domain/system/controllers/system.py
index e411ee2..d4fd57d 100644
--- a/src/server/domain/system/controllers/system.py
+++ b/src/server/domain/system/controllers/system.py
@@ -1,4 +1,5 @@
"""System Controller."""
+
from __future__ import annotations
from typing import TYPE_CHECKING
diff --git a/src/server/domain/system/dtos.py b/src/server/domain/system/dtos.py
index 469fa80..77f2c20 100644
--- a/src/server/domain/system/dtos.py
+++ b/src/server/domain/system/dtos.py
@@ -1,4 +1,5 @@
"""System domain DTOS."""
+
from dataclasses import dataclass
from typing import Annotated, Literal
diff --git a/src/server/domain/system/helpers.py b/src/server/domain/system/helpers.py
index 2660dd9..abc93b8 100644
--- a/src/server/domain/system/helpers.py
+++ b/src/server/domain/system/helpers.py
@@ -1,4 +1,5 @@
"""System domain helper functions."""
+
from __future__ import annotations
from time import time
diff --git a/src/server/domain/urls.py b/src/server/domain/urls.py
index 4de204c..810f0ba 100644
--- a/src/server/domain/urls.py
+++ b/src/server/domain/urls.py
@@ -1,4 +1,5 @@
"""Domain URLs."""
+
from __future__ import annotations
from typing import Final
diff --git a/src/server/domain/web/__init__.py b/src/server/domain/web/__init__.py
index 7720fb5..772e8e6 100644
--- a/src/server/domain/web/__init__.py
+++ b/src/server/domain/web/__init__.py
@@ -1,4 +1,5 @@
"""Web domain."""
+
from __future__ import annotations
from server.domain.web import controllers
diff --git a/src/server/domain/web/controllers/__init__.py b/src/server/domain/web/controllers/__init__.py
index 378db02..ead8ddf 100644
--- a/src/server/domain/web/controllers/__init__.py
+++ b/src/server/domain/web/controllers/__init__.py
@@ -1,4 +1,5 @@
"""Web domain controllers."""
+
from __future__ import annotations
from server.domain.web.controllers import web
diff --git a/src/server/domain/web/controllers/web.py b/src/server/domain/web/controllers/web.py
index aa1a26a..80bd2b3 100644
--- a/src/server/domain/web/controllers/web.py
+++ b/src/server/domain/web/controllers/web.py
@@ -1,4 +1,5 @@
"""Web Controller."""
+
from __future__ import annotations
from typing import TYPE_CHECKING
diff --git a/src/server/lib/__init__.py b/src/server/lib/__init__.py
index 7e6ba14..01a75a5 100644
--- a/src/server/lib/__init__.py
+++ b/src/server/lib/__init__.py
@@ -1,4 +1,5 @@
"""Server Lib."""
+
from __future__ import annotations
from server.lib import (
diff --git a/src/server/lib/constants.py b/src/server/lib/constants.py
index 84f29a7..6457f20 100644
--- a/src/server/lib/constants.py
+++ b/src/server/lib/constants.py
@@ -1,4 +1,5 @@
"""Byte server constants."""
+
from __future__ import annotations
__all__ = [
diff --git a/src/server/lib/cors.py b/src/server/lib/cors.py
index 02441eb..e050d18 100644
--- a/src/server/lib/cors.py
+++ b/src/server/lib/cors.py
@@ -1,4 +1,5 @@
"""CORS config."""
+
from litestar.config.cors import CORSConfig
from server.lib import settings
diff --git a/src/server/lib/db/__init__.py b/src/server/lib/db/__init__.py
index 057fc56..2a6b238 100644
--- a/src/server/lib/db/__init__.py
+++ b/src/server/lib/db/__init__.py
@@ -1,4 +1,5 @@
"""Core DB Package."""
+
from __future__ import annotations
from server.lib.db import orm
diff --git a/src/server/lib/db/base.py b/src/server/lib/db/base.py
index 7b87265..719bfec 100644
--- a/src/server/lib/db/base.py
+++ b/src/server/lib/db/base.py
@@ -1,4 +1,5 @@
"""Database session and engine."""
+
from __future__ import annotations
from contextlib import asynccontextmanager
diff --git a/src/server/lib/db/migrations/env.py b/src/server/lib/db/migrations/env.py
index 06ecfdb..5e77ab9 100644
--- a/src/server/lib/db/migrations/env.py
+++ b/src/server/lib/db/migrations/env.py
@@ -1,4 +1,5 @@
"""Alembic environment for migrations."""
+
from __future__ import annotations
import asyncio
diff --git a/src/server/lib/db/migrations/versions/002_simplify_models.py b/src/server/lib/db/migrations/versions/002_simplify_models.py
index a181f12..a4809d8 100644
--- a/src/server/lib/db/migrations/versions/002_simplify_models.py
+++ b/src/server/lib/db/migrations/versions/002_simplify_models.py
@@ -6,6 +6,7 @@
Create Date: 2023-12-18 03:20:32.171148+00:00
"""
+
from __future__ import annotations
import warnings
diff --git a/src/server/lib/db/migrations/versions/initial.py b/src/server/lib/db/migrations/versions/initial.py
index b54c66b..7ffad26 100644
--- a/src/server/lib/db/migrations/versions/initial.py
+++ b/src/server/lib/db/migrations/versions/initial.py
@@ -4,6 +4,7 @@
Create Date: 2023-11-26 20:11:48.777676+00:00
"""
+
from __future__ import annotations
import warnings
diff --git a/src/server/lib/db/orm.py b/src/server/lib/db/orm.py
index ab21a6d..1615d81 100644
--- a/src/server/lib/db/orm.py
+++ b/src/server/lib/db/orm.py
@@ -1,4 +1,5 @@
"""Application ORM configuration."""
+
from __future__ import annotations
from typing import Any
diff --git a/src/server/lib/dependencies.py b/src/server/lib/dependencies.py
index af468c9..236f3d3 100644
--- a/src/server/lib/dependencies.py
+++ b/src/server/lib/dependencies.py
@@ -1,4 +1,5 @@
"""Application dependency providers."""
+
from __future__ import annotations
from datetime import datetime
diff --git a/src/server/lib/dto.py b/src/server/lib/dto.py
index 34084c4..13ce0c9 100644
--- a/src/server/lib/dto.py
+++ b/src/server/lib/dto.py
@@ -1,4 +1,5 @@
"""DTO Library layer module."""
+
from __future__ import annotations
from typing import TYPE_CHECKING, Literal, overload
@@ -23,8 +24,7 @@ def config(
rename_strategy: RenameStrategy | None = None,
max_nested_depth: int | None = None,
partial: bool | None = None,
-) -> SQLAlchemyDTOConfig:
- ...
+) -> SQLAlchemyDTOConfig: ...
@overload
@@ -35,8 +35,7 @@ def config(
rename_strategy: RenameStrategy | None = None,
max_nested_depth: int | None = None,
partial: bool | None = None,
-) -> DTOConfig:
- ...
+) -> DTOConfig: ...
# noinspection PyUnusedLocal
diff --git a/src/server/lib/exceptions.py b/src/server/lib/exceptions.py
index 8afb921..fa61ea2 100644
--- a/src/server/lib/exceptions.py
+++ b/src/server/lib/exceptions.py
@@ -3,6 +3,7 @@
Also, defines functions that translate service and repository exceptions
into HTTP exceptions.
"""
+
from __future__ import annotations
import sys
diff --git a/src/server/lib/log/controller.py b/src/server/lib/log/controller.py
index 6e64f50..59a7d12 100644
--- a/src/server/lib/log/controller.py
+++ b/src/server/lib/log/controller.py
@@ -4,6 +4,7 @@
Adds a filter for health check route logs.
"""
+
from __future__ import annotations
import logging
diff --git a/src/server/lib/log/utils.py b/src/server/lib/log/utils.py
index 7e9a4dc..e6f5b1f 100644
--- a/src/server/lib/log/utils.py
+++ b/src/server/lib/log/utils.py
@@ -7,6 +7,7 @@
:class:`EventFilter` - A structlog processor that removes keys from the log event if they exist.
"""
+
from __future__ import annotations
from typing import TYPE_CHECKING
diff --git a/src/server/lib/openapi.py b/src/server/lib/openapi.py
index 7f97d5d..1c65362 100644
--- a/src/server/lib/openapi.py
+++ b/src/server/lib/openapi.py
@@ -1,4 +1,5 @@
"""OpenAPI Config."""
+
from __future__ import annotations
from litestar.openapi.config import OpenAPIConfig
diff --git a/src/server/lib/repository.py b/src/server/lib/repository.py
index 308595e..d822436 100644
--- a/src/server/lib/repository.py
+++ b/src/server/lib/repository.py
@@ -1,4 +1,5 @@
"""Repository module."""
+
from __future__ import annotations
import random
diff --git a/src/server/lib/schema.py b/src/server/lib/schema.py
index 6855eb8..233608a 100644
--- a/src/server/lib/schema.py
+++ b/src/server/lib/schema.py
@@ -1,4 +1,5 @@
"""Schema."""
+
from __future__ import annotations
from pydantic import BaseModel as _BaseModel
diff --git a/src/server/lib/serialization.py b/src/server/lib/serialization.py
index fb3163c..820f553 100644
--- a/src/server/lib/serialization.py
+++ b/src/server/lib/serialization.py
@@ -1,4 +1,5 @@
"""Serialization Helpers."""
+
from __future__ import annotations
import datetime
diff --git a/src/server/lib/service.py b/src/server/lib/service.py
index bf9f5c6..882b0c9 100644
--- a/src/server/lib/service.py
+++ b/src/server/lib/service.py
@@ -3,6 +3,7 @@
RepositoryService object is generic on the domain model type, which
should be an SQLAlchemy model.
"""
+
from __future__ import annotations
import contextlib
@@ -41,8 +42,7 @@ class SQLAlchemyAsyncRepositoryService(_SQLAlchemyAsyncRepositoryService[ModelT]
"""
@overload
- def to_dto(self, data: ModelT) -> ModelT:
- ...
+ def to_dto(self, data: ModelT) -> ModelT: ...
@overload
def to_dto(
@@ -50,8 +50,7 @@ def to_dto(
data: Sequence[ModelT],
total: int | None = None,
*filters: FilterTypes | ColumnElement[bool],
- ) -> OffsetPagination[ModelT]:
- ...
+ ) -> OffsetPagination[ModelT]: ...
def to_dto(
self,
@@ -82,8 +81,7 @@ def to_dto(
)
@overload
- def to_schema(self, dto: type[ModelDTOT], data: ModelT) -> ModelDTOT:
- ...
+ def to_schema(self, dto: type[ModelDTOT], data: ModelT) -> ModelDTOT: ...
@overload
def to_schema(
@@ -92,8 +90,7 @@ def to_schema(
data: Sequence[ModelT],
total: int | None = None,
*filters: FilterTypes,
- ) -> OffsetPagination[ModelDTOT]:
- ...
+ ) -> OffsetPagination[ModelDTOT]: ...
def to_schema(
self,
diff --git a/src/server/lib/settings.py b/src/server/lib/settings.py
index c873408..d8828bf 100644
--- a/src/server/lib/settings.py
+++ b/src/server/lib/settings.py
@@ -1,4 +1,5 @@
"""Project Settings."""
+
from __future__ import annotations
import base64
diff --git a/src/server/lib/static_files.py b/src/server/lib/static_files.py
index 524bb4b..c0dd33f 100644
--- a/src/server/lib/static_files.py
+++ b/src/server/lib/static_files.py
@@ -1,4 +1,5 @@
"""Static files configuration."""
+
from __future__ import annotations
from pathlib import Path
diff --git a/src/server/lib/template.py b/src/server/lib/template.py
index f623233..2287430 100644
--- a/src/server/lib/template.py
+++ b/src/server/lib/template.py
@@ -2,6 +2,7 @@
See TemplateSettings for configuration.
"""
+
from __future__ import annotations
from litestar.template.config import TemplateConfig
diff --git a/src/server/lib/types.py b/src/server/lib/types.py
index 5850f5a..6fdfd07 100644
--- a/src/server/lib/types.py
+++ b/src/server/lib/types.py
@@ -1,4 +1,5 @@
"""Library module for type definitions to be used in the application."""
+
from __future__ import annotations
from typing import TYPE_CHECKING, Any, Literal, TypeAlias, TypeVar
diff --git a/src/utils.py b/src/utils.py
index 3159fa0..cab0a9a 100644
--- a/src/utils.py
+++ b/src/utils.py
@@ -1,4 +1,5 @@
"""General utility functions."""
+
from __future__ import annotations
import base64
diff --git a/tools/build_docs.py b/tools/build_docs.py
index f15122d..c274b51 100644
--- a/tools/build_docs.py
+++ b/tools/build_docs.py
@@ -1,4 +1,5 @@
"""Builds the documentation and copies it to the output directory."""
+
from __future__ import annotations
import argparse
From 03a160b607ac51cbfe4f84d054507e478cb47b81 Mon Sep 17 00:00:00 2001
From: Jacob Coffee
Date: Sun, 10 Mar 2024 17:33:08 -0500
Subject: [PATCH 16/29] feat: add model for forum configuration
---
pyproject.toml | 2 +-
src/server/domain/db/models.py | 67 ++++++++++-
.../migrations/versions/003_forum models.py | 109 ++++++++++++++++++
3 files changed, 176 insertions(+), 2 deletions(-)
create mode 100644 src/server/lib/db/migrations/versions/003_forum models.py
diff --git a/pyproject.toml b/pyproject.toml
index 571004a..1af0e21 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -254,7 +254,7 @@ known-first-party = ["src", "tests"]
]
"src/**/*.*" = ["PLR0913", "SLF001"]
"src/server/lib/db/base.py" = ["E501"]
-"src/server/lib/db/migrations/versions/*.*" = ["D", "INP", "PGH"]
+"src/server/lib/db/migrations/versions/*.*" = ["D", "INP", "PGH", "N999"]
"tests/**/*.*" = [
"S101",
"D",
diff --git a/src/server/domain/db/models.py b/src/server/domain/db/models.py
index ecbe42f..81368b8 100644
--- a/src/server/domain/db/models.py
+++ b/src/server/domain/db/models.py
@@ -9,7 +9,7 @@
from sqlalchemy.ext.associationproxy import AssociationProxy, association_proxy
from sqlalchemy.orm import Mapped, mapped_column, relationship
-__all__ = ("GitHubConfig", "Guild", "SOTagsConfig", "User", "AllowedUsersConfig")
+__all__ = ("GitHubConfig", "Guild", "SOTagsConfig", "User", "AllowedUsersConfig", "ForumConfig")
class Guild(UUIDAuditBase):
@@ -31,6 +31,7 @@ class Guild(UUIDAuditBase):
guild_name: Mapped[str] = mapped_column(String(100))
prefix: Mapped[str] = mapped_column(String(5), server_default="!", default="!")
help_channel_id: Mapped[int | None] = mapped_column(BigInteger)
+ showcase_channel_id: Mapped[int | None] = mapped_column(BigInteger)
sync_label: Mapped[str | None]
issue_linking: Mapped[bool] = mapped_column(default=False)
comment_linking: Mapped[bool] = mapped_column(default=False)
@@ -54,6 +55,11 @@ class Guild(UUIDAuditBase):
back_populates="guild",
cascade="save-update, merge, delete",
)
+ forum_config: Mapped[ForumConfig | None] = relationship(
+ lazy="noload",
+ back_populates="guild",
+ cascade="save-update, merge, delete",
+ )
class GitHubConfig(UUIDAuditBase):
@@ -174,3 +180,62 @@ class User(UUIDAuditBase):
lazy="noload",
cascade="save-update, merge, delete",
)
+
+
+class ForumConfig(UUIDAuditBase):
+ """Forum configuration.
+
+ A guild will be able to set whether they want help and/or showcase forums.
+ * If they already have them set up, they can configure the channel IDs for them.
+ * If they don't have them set up, they can configure the category and channel names for them
+ Byte will then create the channels for them.
+ * If they don't want them, they can disable them.
+
+ Help forum settings include:
+ * Respond with help embed, including a link to 'Open a GitHub Issue'
+ if the `GitHubConfig:github_organization` and `GitHubConfig:github_repository` are set.
+ Also includes `Solve` button to mark as solved and close the thread.
+ * Automatic thread closing after a certain period of inactivity.
+ * Uploading of threads into GitHub discussions.
+ * Pinging of defined roles when a thread has not received a response from someone with those roles
+ after a certain period of time.
+
+ Showcase forum settings include:
+ * Respond with showcase embed, including a link to 'Add to awesome-$repo'
+ if the `GitHubConfig:github_organization` and `GitHubConfig:github_awesome` are set.
+ * Automatic thread closing after a certain period of inactivity.
+ * Uploading of threads into GitHub discussions.
+ """
+
+ __tablename__ = "forum_config" # type: ignore[reportAssignmentType]
+ __table_args__ = {"comment": "Forum configuration for a guild."}
+
+ guild_id: Mapped[UUID] = mapped_column(ForeignKey("guild.id", ondelete="cascade"))
+
+ """Help forum settings."""
+ help_forum: Mapped[bool] = mapped_column(default=False)
+ help_forum_category: Mapped[str | None]
+ help_channel_id: Mapped[int | None] = association_proxy("guild", "help_channel_id")
+ help_thread_auto_close: Mapped[bool] = mapped_column(default=False)
+ help_thread_auto_close_days: Mapped[int | None]
+ help_thread_notify: Mapped[bool] = mapped_column(default=False)
+ help_thread_notify_roles: Mapped[str | None]
+ help_thread_notify_days: Mapped[int | None]
+ help_thread_sync: Mapped[bool] = association_proxy("guild", "github_config.discussion_sync")
+
+ """Showcase forum settings."""
+ showcase_forum: Mapped[bool] = mapped_column(default=False)
+ showcase_forum_category: Mapped[str | None]
+ showcase_channel_id: Mapped[int | None] = association_proxy("guild", "showcase_channel_Id")
+ showcase_thread_auto_close: Mapped[bool] = mapped_column(default=False)
+ showcase_thread_auto_close_days: Mapped[int | None]
+
+ # =================
+ # ORM Relationships
+ # =================
+ guild: Mapped[Guild] = relationship(
+ back_populates="forum_config",
+ innerjoin=True,
+ lazy="noload",
+ cascade="save-update, merge, delete",
+ )
diff --git a/src/server/lib/db/migrations/versions/003_forum models.py b/src/server/lib/db/migrations/versions/003_forum models.py
new file mode 100644
index 0000000..308c7e5
--- /dev/null
+++ b/src/server/lib/db/migrations/versions/003_forum models.py
@@ -0,0 +1,109 @@
+# type: ignore
+"""
+
+Revision ID: 73a26ceab2c4
+Revises: feebdacfdd91
+Create Date: 2024-03-10 22:30:54.150566+00:00
+
+"""
+
+from __future__ import annotations
+
+import warnings
+
+import sqlalchemy as sa
+from advanced_alchemy.types import GUID, ORA_JSONB, DateTimeUTC
+from alembic import op
+from sqlalchemy import Text # noqa: F401
+
+__all__ = ["downgrade", "upgrade", "schema_upgrades", "schema_downgrades", "data_upgrades", "data_downgrades"]
+
+sa.GUID = GUID
+sa.DateTimeUTC = DateTimeUTC
+sa.ORA_JSONB = ORA_JSONB
+
+# revision identifiers, used by Alembic.
+revision = "73a26ceab2c4"
+down_revision = "feebdacfdd91"
+branch_labels = None
+depends_on = None
+
+
+def upgrade() -> None:
+ with warnings.catch_warnings():
+ warnings.filterwarnings("ignore", category=UserWarning)
+ with op.get_context().autocommit_block():
+ schema_upgrades()
+ data_upgrades()
+
+
+def downgrade() -> None:
+ with warnings.catch_warnings():
+ warnings.filterwarnings("ignore", category=UserWarning)
+ with op.get_context().autocommit_block():
+ data_downgrades()
+ schema_downgrades()
+
+
+def schema_upgrades() -> None:
+ """schema upgrade migrations go here."""
+ # ### commands auto generated by Alembic - please adjust! ###
+ op.create_table(
+ "forum_config",
+ sa.Column("id", sa.GUID(length=16), nullable=False),
+ sa.Column("guild_id", sa.GUID(length=16), nullable=False),
+ sa.Column("help_forum", sa.Boolean(), nullable=False),
+ sa.Column("help_forum_category", sa.String(), nullable=True),
+ sa.Column("help_thread_auto_close", sa.Boolean(), nullable=False),
+ sa.Column("help_thread_auto_close_days", sa.Integer(), nullable=True),
+ sa.Column("help_thread_notify", sa.Boolean(), nullable=False),
+ sa.Column("help_thread_notify_roles", sa.String(), nullable=True),
+ sa.Column("help_thread_notify_days", sa.Integer(), nullable=True),
+ sa.Column("showcase_forum", sa.Boolean(), nullable=False),
+ sa.Column("showcase_forum_category", sa.String(), nullable=True),
+ sa.Column("showcase_thread_auto_close", sa.Boolean(), nullable=False),
+ sa.Column("showcase_thread_auto_close_days", sa.Integer(), nullable=True),
+ sa.Column("sa_orm_sentinel", sa.Integer(), nullable=True),
+ sa.Column("created_at", sa.DateTimeUTC(timezone=True), nullable=False),
+ sa.Column("updated_at", sa.DateTimeUTC(timezone=True), nullable=False),
+ sa.ForeignKeyConstraint(
+ ["guild_id"], ["guild.id"], name=op.f("fk_forum_config_guild_id_guild"), ondelete="cascade"
+ ),
+ sa.PrimaryKeyConstraint("id", name=op.f("pk_forum_config")),
+ )
+ with op.batch_alter_table("allowed_users", schema=None) as batch_op:
+ batch_op.create_table_comment("Configuration for allowed users in a Discord guild.", existing_comment=None)
+
+ with op.batch_alter_table("guild", schema=None) as batch_op:
+ batch_op.add_column(sa.Column("showcase_channel_id", sa.BigInteger(), nullable=True))
+ batch_op.create_table_comment("Configuration for a Discord guild.", existing_comment=None)
+
+ with op.batch_alter_table("so_tags", schema=None) as batch_op:
+ batch_op.create_table_comment("Configuration for a Discord guild's Stack Overflow tags.", existing_comment=None)
+
+ # ### end Alembic commands ###
+
+
+def schema_downgrades() -> None:
+ """schema downgrade migrations go here."""
+ # ### commands auto generated by Alembic - please adjust! ###
+ with op.batch_alter_table("so_tags", schema=None) as batch_op:
+ batch_op.drop_table_comment(existing_comment="Configuration for a Discord guild's Stack Overflow tags.")
+
+ with op.batch_alter_table("guild", schema=None) as batch_op:
+ batch_op.drop_table_comment(existing_comment="Configuration for a Discord guild.")
+ batch_op.drop_column("showcase_channel_id")
+
+ with op.batch_alter_table("allowed_users", schema=None) as batch_op:
+ batch_op.drop_table_comment(existing_comment="Configuration for allowed users in a Discord guild.")
+
+ op.drop_table("forum_config")
+ # ### end Alembic commands ###
+
+
+def data_upgrades() -> None:
+ """Add any optional data upgrade migrations here!"""
+
+
+def data_downgrades() -> None:
+ """Add any optional data downgrade migrations here!"""
From 187d1b0cd1605a67af743f40fd06db58175e4bac Mon Sep 17 00:00:00 2001
From: Jacob Coffee
Date: Sun, 10 Mar 2024 17:55:29 -0500
Subject: [PATCH 17/29] feat: update schema for updateable settings
---
src/server/domain/guilds/controllers.py | 10 +++---
src/server/domain/guilds/schemas.py | 42 +++++++++++++++++++++++--
2 files changed, 46 insertions(+), 6 deletions(-)
diff --git a/src/server/domain/guilds/controllers.py b/src/server/domain/guilds/controllers.py
index fca75d3..6ffb014 100644
--- a/src/server/domain/guilds/controllers.py
+++ b/src/server/domain/guilds/controllers.py
@@ -102,7 +102,7 @@ async def update_guild(
title="Value",
description="The new value for the setting.",
),
- ) -> str:
+ ) -> GuildSchema | OffsetPagination[GuildSchema]:
"""Update a guild by ID.
Args:
@@ -114,9 +114,11 @@ async def update_guild(
Returns:
Guild: Updated guild object
"""
- # todo: this is a placeholder, update
- await guilds_service.update(guild_id, setting, {"some-config-thing": value})
- return f"Guild {guild_id} updated."
+ _guild = guilds_service.get(guild_id, id_attribute="guild_id")
+ # todo: this is a placeholder, update to grab whichever setting is being update, and update the corresponding
+ # tables value
+ await guilds_service.update(_guild, setting, {"some-config-thing": value})
+ return guilds_service.to_schema(GuildSchema, _guild)
@get(
operation_id="GuildDetail",
diff --git a/src/server/domain/guilds/schemas.py b/src/server/domain/guilds/schemas.py
index 4110589..c363fcb 100644
--- a/src/server/domain/guilds/schemas.py
+++ b/src/server/domain/guilds/schemas.py
@@ -82,7 +82,8 @@ class UpdateableGuildSetting(CamelizedBaseModel):
"""Guild Model Settings"""
prefix: str = Field(title="Prefix", description="The prefix for the guild.")
- help_channel_id: int = Field(title="Help Channel ID", description="The channel ID for the help channel.")
+ help_channel_id: int = Field(title="Help Channel ID", description="The channel ID for the help forum.")
+ showcase_channel_id: int = Field(title="Showcase Channel ID", description="The channel ID for the showcase forum.")
sync_label: str = Field(title="Sync Label", description="The forum label to use for GitHub discussion syncs.")
issue_linking: bool = Field(title="Issue Linking", description="Is issue linking enabled.")
comment_linking: bool = Field(title="Comment Linking", description="Is comment linking enabled.")
@@ -94,7 +95,44 @@ class UpdateableGuildSetting(CamelizedBaseModel):
github_repository: str = Field(title="GitHub Repository", description="The GitHub repository to sync.")
"""StackOverflow Tags Config Settings"""
- tag_name: str = Field(title="StackOverflow Tag", description="The StackOverflow tag to sync.")
+ tag_name: list[str] = Field(
+ title="StackOverflow Tag(s)",
+ description="The StackOverflow tag(s) to sync.",
+ examples=["litestar", "byte", "python"],
+ )
"""Allowed Users Config Settings"""
user_id: int = Field(title="User ID", description="The user or role ID to allow.")
+
+ """Forum Config Settings"""
+ """Help Forum"""
+ help_forum: bool = Field(title="Help Forum", description="Is the help forum enabled.")
+ help_forum_category: str = Field(title="Help Forum Category", description="The help forum category.")
+ help_thread_auto_close: bool = Field(
+ title="Help Thread Auto Close", description="Is the help thread auto close enabled."
+ )
+ help_thread_auto_close_days: int = Field(
+ title="Help Thread Auto Close Days", description="The days to auto close help threads after inactivity."
+ )
+ help_thread_notify: bool = Field(
+ title="Help Thread Notify", description="Whether to notify roles for unresponded help threads."
+ )
+ help_thread_notify_roles: list[int] = Field(
+ title="Help Thread Notify Roles", description="The roles to notify for unresponded help threads."
+ )
+ help_thread_notify_days: int = Field(
+ title="Help Thread Notify Days", description="The days to notify `notify_roles` after not receiving a response."
+ )
+ help_thread_sync: bool = Field(
+ title="Help Thread Sync", description="Is the help thread GitHub discussions sync enabled."
+ )
+
+ """Showcase forum"""
+ showcase_forum: bool = Field(title="Showcase Forum", description="Is the showcase forum enabled.")
+ showcase_forum_category: str = Field(title="Showcase Forum Category", description="The showcase forum category.")
+ showcase_thread_auto_close: bool = Field(
+ title="Showcase Thread Auto Close", description="Is the showcase thread auto close enabled."
+ )
+ showcase_thread_auto_close_days: int = Field(
+ title="Showcase Thread Auto Close Days", description="The days to auto close showcase threads after inactivity."
+ )
From 67b756beaec3379656ba8ce6e888ad7ff55d1d30 Mon Sep 17 00:00:00 2001
From: Jacob Coffee
Date: Sun, 10 Mar 2024 22:17:57 -0500
Subject: [PATCH 18/29] ci: add helpers for container setup and teardown
---
Makefile | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
diff --git a/Makefile b/Makefile
index 3fbf73f..88a4334 100644
--- a/Makefile
+++ b/Makefile
@@ -51,6 +51,24 @@ install: ## Install all dependencies
@command -v $(PDM) > /dev/null || (echo "PDM not found. Installing..." && $(MAKE) install-pdm)
$(MAKE) install-pre-commit
+up-container: ## Start the Byte database container
+ @echo "=> Starting Byte database container"
+ @docker compose -f docker-compose.infra.yml up -d
+ @echo "=> Started Byte database container"
+
+clean-container: ## Stop, remove, and wipe the Byte database container and volume
+ @echo "=> Stopping and removing Byte database container"
+ @docker stop byte-db-1
+ @docker rm byte-db-1
+ @docker volume rm byte_db-data
+ @echo "=> Stopped and removed Byte database container"
+
+load-container: migrate ## Perform database migrations and load test data into the Byte database container
+ @echo "=> Loading database migrations and test data"
+ # load data, we already run migrate
+
+ @echo "=> Loaded database migrations and test data"
+
# =============================================================================
# Tests, Linting, Coverage
# =============================================================================
From aeee8bccd362aba439889a40438970c2de30f4df Mon Sep 17 00:00:00 2001
From: Jacob Coffee
Date: Sun, 10 Mar 2024 22:18:44 -0500
Subject: [PATCH 19/29] feat: update schemas and route for updating
---
src/server/domain/guilds/dependencies.py | 3 +++
src/server/domain/guilds/schemas.py | 33 +++++++++++++++++++++---
2 files changed, 33 insertions(+), 3 deletions(-)
diff --git a/src/server/domain/guilds/dependencies.py b/src/server/domain/guilds/dependencies.py
index 1d3ef92..1f80903 100644
--- a/src/server/domain/guilds/dependencies.py
+++ b/src/server/domain/guilds/dependencies.py
@@ -44,6 +44,9 @@ async def provides_guilds_service(db_session: AsyncSession) -> AsyncGenerator[Gu
selectinload(Guild.allowed_users).options(
joinedload(AllowedUsersConfig.guild, innerjoin=True).options(noload("*")),
),
+ selectinload(Guild.forum_config).options(
+ joinedload(Guild.forum_config, innerjoin=True).options(noload("*")),
+ ),
),
) as service:
try:
diff --git a/src/server/domain/guilds/schemas.py b/src/server/domain/guilds/schemas.py
index c363fcb..09d2205 100644
--- a/src/server/domain/guilds/schemas.py
+++ b/src/server/domain/guilds/schemas.py
@@ -8,10 +8,12 @@
from server.lib.schema import CamelizedBaseModel
-__all__ = ("GuildCreate", "GuildSchema", "GuildUpdate", "UpdateableGuildSetting")
+__all__ = ("AllowedUsersConfigSchema", "ForumConfigSchema", "GitHubConfigSchema", "GuildCreate", "GuildSchema", "GuildUpdate", "SOTagsConfigSchema", "UpdateableGuildSetting", )
class GitHubConfigSchema(CamelizedBaseModel):
+ """Schema for validating GitHub configuration."""
+
guild_id: UUID
discussion_sync: bool
github_organization: str | None
@@ -19,15 +21,37 @@ class GitHubConfigSchema(CamelizedBaseModel):
class SOTagsConfigSchema(CamelizedBaseModel):
+ """Schema for validating StackOverflow tags configuration."""
+
guild_id: UUID
tag_name: str
class AllowedUsersConfigSchema(CamelizedBaseModel):
- guild_id: int
+ """Schema for validating allowed users for certain admin actions within a guild."""
+
+ guild_id: UUID
user_id: UUID
+class ForumConfigSchema(CamelizedBaseModel):
+ """Schema for validating forum configuration."""
+
+ guild_id: UUID
+ help_forum: bool = Field(title="Help Forum", description="Is the help forum enabled.")
+ help_forum_category: str
+ help_thread_auto_close: bool
+ help_thread_auto_close_days: int
+ help_thread_notify: bool
+ help_thread_notify_roles: list[int]
+ help_thread_notify_days: int
+ help_thread_sync: bool
+ showcase_forum: bool
+ showcase_forum_category: str
+ showcase_thread_auto_close: bool
+ showcase_thread_auto_close_days: int
+
+
class GuildSchema(CamelizedBaseModel):
"""Schema representing an existing guild."""
@@ -51,6 +75,9 @@ class GuildSchema(CamelizedBaseModel):
allowed_users: list[AllowedUsersConfigSchema] = Field(
title="Allowed Users", description="The allowed users configuration for the guild."
)
+ forum_config: ForumConfigSchema | None = Field(
+ title="Forum Config", description="The forum configuration for the guild."
+ )
class GuildCreate(CamelizedBaseModel):
@@ -78,7 +105,7 @@ class GuildUpdate(CamelizedBaseModel):
class UpdateableGuildSetting(CamelizedBaseModel):
- """An allowed setting that admins can update for their guild."""
+ """Allowed settings that admins can update for their guild."""
"""Guild Model Settings"""
prefix: str = Field(title="Prefix", description="The prefix for the guild.")
From aa612ee3bfab518726c6dedd58c304aef71b82f6 Mon Sep 17 00:00:00 2001
From: Jacob Coffee
Date: Sun, 10 Mar 2024 22:35:59 -0500
Subject: [PATCH 20/29] fix: correctly load forum config
---
src/server/domain/guilds/dependencies.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/server/domain/guilds/dependencies.py b/src/server/domain/guilds/dependencies.py
index 1f80903..f557f5c 100644
--- a/src/server/domain/guilds/dependencies.py
+++ b/src/server/domain/guilds/dependencies.py
@@ -7,7 +7,7 @@
from sqlalchemy import select
from sqlalchemy.orm import joinedload, noload, selectinload
-from server.domain.db.models import AllowedUsersConfig, GitHubConfig, Guild, SOTagsConfig
+from server.domain.db.models import AllowedUsersConfig, ForumConfig, GitHubConfig, Guild, SOTagsConfig
from server.domain.guilds.services import GuildsService
from server.lib import log
@@ -45,7 +45,7 @@ async def provides_guilds_service(db_session: AsyncSession) -> AsyncGenerator[Gu
joinedload(AllowedUsersConfig.guild, innerjoin=True).options(noload("*")),
),
selectinload(Guild.forum_config).options(
- joinedload(Guild.forum_config, innerjoin=True).options(noload("*")),
+ joinedload(ForumConfig.guild, innerjoin=True).options(noload("*")),
),
),
) as service:
From 38af83407d8f2fd14d7cc95d020b4e86a1b2982b Mon Sep 17 00:00:00 2001
From: Jacob Coffee
Date: Sun, 10 Mar 2024 23:22:59 -0500
Subject: [PATCH 21/29] ci: update deps
---
Makefile | 8 ++
pdm.lock | 233 ++++++++++++++++++++++++++++---------------------------
2 files changed, 125 insertions(+), 116 deletions(-)
diff --git a/Makefile b/Makefile
index 88a4334..42ac73d 100644
--- a/Makefile
+++ b/Makefile
@@ -69,6 +69,14 @@ load-container: migrate ## Perform database migrations and load test data into t
@echo "=> Loaded database migrations and test data"
+.PHONY: refresh-lockfiles
+refresh-lockfiles: ## Sync lockfiles with requirements files.
+ $(PDM) update --update-reuse -G:all
+
+.PHONY: lock
+lock: ## Rebuild lockfiles from scratch, updating all dependencies
+ $(PDM) update --update-eager -G:all
+
# =============================================================================
# Tests, Linting, Coverage
# =============================================================================
diff --git a/pdm.lock b/pdm.lock
index cd0e778..56399ca 100644
--- a/pdm.lock
+++ b/pdm.lock
@@ -5,7 +5,7 @@
groups = ["default", "docs", "lint", "test"]
strategy = ["cross_platform", "inherit_metadata"]
lock_version = "4.4.1"
-content_hash = "sha256:85851593eb18cf99411fefc596f8644a2b15988a4e0b6467aaaa5a3b4c50aeb8"
+content_hash = "sha256:32b6a491dea5963afb177ae0726e8012dd21ebdd2067d7e68ed82dfa1a32df94"
[[package]]
name = "accessible-pygments"
@@ -691,7 +691,7 @@ files = [
[[package]]
name = "faker"
-version = "23.3.0"
+version = "24.1.0"
requires_python = ">=3.8"
summary = "Faker is a Python package that generates fake data for you."
groups = ["default"]
@@ -699,8 +699,8 @@ dependencies = [
"python-dateutil>=2.4",
]
files = [
- {file = "Faker-23.3.0-py3-none-any.whl", hash = "sha256:117ce1a2805c1bc5ca753b3dc6f9d567732893b2294b827d3164261ee8f20267"},
- {file = "Faker-23.3.0.tar.gz", hash = "sha256:458d93580de34403a8dec1e8d5e6be2fee96c4deca63b95d71df7a6a80a690de"},
+ {file = "Faker-24.1.0-py3-none-any.whl", hash = "sha256:89ae0932f4f269754790569828859eaa0ae2ce73d1f3eb1f30ae7c20d4daf5ce"},
+ {file = "Faker-24.1.0.tar.gz", hash = "sha256:4fb0c16c71ad35d278a5fa7a4106a5c26c2b2b5c5efc47c1d67635db90b6071e"},
]
[[package]]
@@ -855,16 +855,17 @@ files = [
[[package]]
name = "hishel"
-version = "0.0.21"
+version = "0.0.24"
requires_python = ">=3.8"
summary = "Persistent cache implementation for httpx and httpcore"
groups = ["default"]
dependencies = [
"httpx>=0.22.0",
+ "typing-extensions>=4.8.0",
]
files = [
- {file = "hishel-0.0.21-py3-none-any.whl", hash = "sha256:2347180fb2396700f0616cdfd4bb9d04ba0c543694d19f2d0156226dfa5a511d"},
- {file = "hishel-0.0.21.tar.gz", hash = "sha256:62de30930e7fc02551d17d0f653f6e79499eaeffe32be9e36664ea7e0c0b82bd"},
+ {file = "hishel-0.0.24-py3-none-any.whl", hash = "sha256:8b6e43481485e1938d78bd35c0bcb38646fe8f2e090fedb64b4dc1d6015ffe49"},
+ {file = "hishel-0.0.24.tar.gz", hash = "sha256:4ac494c6bfedc431e480ab85d3435d4710230b2ad6092766b6ccf82b1d7e4152"},
]
[[package]]
@@ -941,7 +942,7 @@ files = [
[[package]]
name = "hypothesis"
-version = "6.98.13"
+version = "6.99.2"
requires_python = ">=3.8"
summary = "A library for property-based testing"
groups = ["test"]
@@ -950,8 +951,8 @@ dependencies = [
"sortedcontainers<3.0.0,>=2.1.0",
]
files = [
- {file = "hypothesis-6.98.13-py3-none-any.whl", hash = "sha256:42ba2cc2d1fe04a65124fadfc6a305dbf62607aa9f8f94a10efadee9cfa1c4dd"},
- {file = "hypothesis-6.98.13.tar.gz", hash = "sha256:746b5316da2c7af4c3816c34af675909fcb1a6a0e5c7af5cfc36c450be2dca34"},
+ {file = "hypothesis-6.99.2-py3-none-any.whl", hash = "sha256:f277f6ccb074f39d51c7f32ba5a0ff640dba9b71ef69ea1e1e09b6f7c25302f5"},
+ {file = "hypothesis-6.99.2.tar.gz", hash = "sha256:24453b1a86151be83d26e81834e29022b3e3f0fc5d71275cc3d096649a13c53c"},
]
[[package]]
@@ -1041,7 +1042,7 @@ files = [
[[package]]
name = "litestar"
-version = "2.6.1"
+version = "2.7.0"
requires_python = "<4.0,>=3.8"
summary = "Litestar - A production-ready, highly performant, extensible ASGI API Framework"
groups = ["default"]
@@ -1058,13 +1059,13 @@ dependencies = [
"typing-extensions",
]
files = [
- {file = "litestar-2.6.1-py3-none-any.whl", hash = "sha256:33451b705f04f1f1ee991c28502afc2ce1b5ca5df25f0ae6ae8cf11063397e42"},
- {file = "litestar-2.6.1.tar.gz", hash = "sha256:3232190578d81180cce765840dfe72ef6b5d7ec2aead6fc37d664e61d8e2f647"},
+ {file = "litestar-2.7.0-py3-none-any.whl", hash = "sha256:62eabe89c08a1a5b66063bf9d8ec7677368bf7d3593c0579fb3605dd61b486a3"},
+ {file = "litestar-2.7.0.tar.gz", hash = "sha256:30f703b513d8c8a7f82e3b5cd583b071147f7e60b929650eeeeb00ff0ff65582"},
]
[[package]]
name = "litestar"
-version = "2.6.1"
+version = "2.7.0"
extras = ["jwt", "opentelemetry", "prometheus", "standard", "structlog"]
requires_python = "<4.0,>=3.8"
summary = "Litestar - A production-ready, highly performant, extensible ASGI API Framework"
@@ -1074,7 +1075,7 @@ dependencies = [
"fast-query-parsers>=1.0.2",
"jinja2",
"jsbeautifier",
- "litestar==2.6.1",
+ "litestar==2.7.0",
"opentelemetry-instrumentation-asgi",
"prometheus-client",
"python-jose",
@@ -1083,8 +1084,8 @@ dependencies = [
"uvloop>=0.18.0; sys_platform != \"win32\"",
]
files = [
- {file = "litestar-2.6.1-py3-none-any.whl", hash = "sha256:33451b705f04f1f1ee991c28502afc2ce1b5ca5df25f0ae6ae8cf11063397e42"},
- {file = "litestar-2.6.1.tar.gz", hash = "sha256:3232190578d81180cce765840dfe72ef6b5d7ec2aead6fc37d664e61d8e2f647"},
+ {file = "litestar-2.7.0-py3-none-any.whl", hash = "sha256:62eabe89c08a1a5b66063bf9d8ec7677368bf7d3593c0579fb3605dd61b486a3"},
+ {file = "litestar-2.7.0.tar.gz", hash = "sha256:30f703b513d8c8a7f82e3b5cd583b071147f7e60b929650eeeeb00ff0ff65582"},
]
[[package]]
@@ -1172,34 +1173,34 @@ files = [
[[package]]
name = "msgpack"
-version = "1.0.7"
+version = "1.0.8"
requires_python = ">=3.8"
summary = "MessagePack serializer"
groups = ["docs"]
files = [
- {file = "msgpack-1.0.7-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:576eb384292b139821c41995523654ad82d1916da6a60cff129c715a6223ea84"},
- {file = "msgpack-1.0.7-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:730076207cb816138cf1af7f7237b208340a2c5e749707457d70705715c93b93"},
- {file = "msgpack-1.0.7-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:85765fdf4b27eb5086f05ac0491090fc76f4f2b28e09d9350c31aac25a5aaff8"},
- {file = "msgpack-1.0.7-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3476fae43db72bd11f29a5147ae2f3cb22e2f1a91d575ef130d2bf49afd21c46"},
- {file = "msgpack-1.0.7-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6d4c80667de2e36970ebf74f42d1088cc9ee7ef5f4e8c35eee1b40eafd33ca5b"},
- {file = "msgpack-1.0.7-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5b0bf0effb196ed76b7ad883848143427a73c355ae8e569fa538365064188b8e"},
- {file = "msgpack-1.0.7-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:f9a7c509542db4eceed3dcf21ee5267ab565a83555c9b88a8109dcecc4709002"},
- {file = "msgpack-1.0.7-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:84b0daf226913133f899ea9b30618722d45feffa67e4fe867b0b5ae83a34060c"},
- {file = "msgpack-1.0.7-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:ec79ff6159dffcc30853b2ad612ed572af86c92b5168aa3fc01a67b0fa40665e"},
- {file = "msgpack-1.0.7-cp311-cp311-win32.whl", hash = "sha256:3e7bf4442b310ff154b7bb9d81eb2c016b7d597e364f97d72b1acc3817a0fdc1"},
- {file = "msgpack-1.0.7-cp311-cp311-win_amd64.whl", hash = "sha256:3f0c8c6dfa6605ab8ff0611995ee30d4f9fcff89966cf562733b4008a3d60d82"},
- {file = "msgpack-1.0.7-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:f0936e08e0003f66bfd97e74ee530427707297b0d0361247e9b4f59ab78ddc8b"},
- {file = "msgpack-1.0.7-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:98bbd754a422a0b123c66a4c341de0474cad4a5c10c164ceed6ea090f3563db4"},
- {file = "msgpack-1.0.7-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b291f0ee7961a597cbbcc77709374087fa2a9afe7bdb6a40dbbd9b127e79afee"},
- {file = "msgpack-1.0.7-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ebbbba226f0a108a7366bf4b59bf0f30a12fd5e75100c630267d94d7f0ad20e5"},
- {file = "msgpack-1.0.7-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1e2d69948e4132813b8d1131f29f9101bc2c915f26089a6d632001a5c1349672"},
- {file = "msgpack-1.0.7-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bdf38ba2d393c7911ae989c3bbba510ebbcdf4ecbdbfec36272abe350c454075"},
- {file = "msgpack-1.0.7-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:993584fc821c58d5993521bfdcd31a4adf025c7d745bbd4d12ccfecf695af5ba"},
- {file = "msgpack-1.0.7-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:52700dc63a4676669b341ba33520f4d6e43d3ca58d422e22ba66d1736b0a6e4c"},
- {file = "msgpack-1.0.7-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:e45ae4927759289c30ccba8d9fdce62bb414977ba158286b5ddaf8df2cddb5c5"},
- {file = "msgpack-1.0.7-cp312-cp312-win32.whl", hash = "sha256:27dcd6f46a21c18fa5e5deed92a43d4554e3df8d8ca5a47bf0615d6a5f39dbc9"},
- {file = "msgpack-1.0.7-cp312-cp312-win_amd64.whl", hash = "sha256:7687e22a31e976a0e7fc99c2f4d11ca45eff652a81eb8c8085e9609298916dcf"},
- {file = "msgpack-1.0.7.tar.gz", hash = "sha256:572efc93db7a4d27e404501975ca6d2d9775705c2d922390d878fcf768d92c87"},
+ {file = "msgpack-1.0.8-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9517004e21664f2b5a5fd6333b0731b9cf0817403a941b393d89a2f1dc2bd836"},
+ {file = "msgpack-1.0.8-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d16a786905034e7e34098634b184a7d81f91d4c3d246edc6bd7aefb2fd8ea6ad"},
+ {file = "msgpack-1.0.8-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e2872993e209f7ed04d963e4b4fbae72d034844ec66bc4ca403329db2074377b"},
+ {file = "msgpack-1.0.8-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5c330eace3dd100bdb54b5653b966de7f51c26ec4a7d4e87132d9b4f738220ba"},
+ {file = "msgpack-1.0.8-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:83b5c044f3eff2a6534768ccfd50425939e7a8b5cf9a7261c385de1e20dcfc85"},
+ {file = "msgpack-1.0.8-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1876b0b653a808fcd50123b953af170c535027bf1d053b59790eebb0aeb38950"},
+ {file = "msgpack-1.0.8-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:dfe1f0f0ed5785c187144c46a292b8c34c1295c01da12e10ccddfc16def4448a"},
+ {file = "msgpack-1.0.8-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:3528807cbbb7f315bb81959d5961855e7ba52aa60a3097151cb21956fbc7502b"},
+ {file = "msgpack-1.0.8-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e2f879ab92ce502a1e65fce390eab619774dda6a6ff719718069ac94084098ce"},
+ {file = "msgpack-1.0.8-cp311-cp311-win32.whl", hash = "sha256:26ee97a8261e6e35885c2ecd2fd4a6d38252246f94a2aec23665a4e66d066305"},
+ {file = "msgpack-1.0.8-cp311-cp311-win_amd64.whl", hash = "sha256:eadb9f826c138e6cf3c49d6f8de88225a3c0ab181a9b4ba792e006e5292d150e"},
+ {file = "msgpack-1.0.8-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:114be227f5213ef8b215c22dde19532f5da9652e56e8ce969bf0a26d7c419fee"},
+ {file = "msgpack-1.0.8-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:d661dc4785affa9d0edfdd1e59ec056a58b3dbb9f196fa43587f3ddac654ac7b"},
+ {file = "msgpack-1.0.8-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d56fd9f1f1cdc8227d7b7918f55091349741904d9520c65f0139a9755952c9e8"},
+ {file = "msgpack-1.0.8-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0726c282d188e204281ebd8de31724b7d749adebc086873a59efb8cf7ae27df3"},
+ {file = "msgpack-1.0.8-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8db8e423192303ed77cff4dce3a4b88dbfaf43979d280181558af5e2c3c71afc"},
+ {file = "msgpack-1.0.8-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:99881222f4a8c2f641f25703963a5cefb076adffd959e0558dc9f803a52d6a58"},
+ {file = "msgpack-1.0.8-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:b5505774ea2a73a86ea176e8a9a4a7c8bf5d521050f0f6f8426afe798689243f"},
+ {file = "msgpack-1.0.8-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:ef254a06bcea461e65ff0373d8a0dd1ed3aa004af48839f002a0c994a6f72d04"},
+ {file = "msgpack-1.0.8-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:e1dd7839443592d00e96db831eddb4111a2a81a46b028f0facd60a09ebbdd543"},
+ {file = "msgpack-1.0.8-cp312-cp312-win32.whl", hash = "sha256:64d0fcd436c5683fdd7c907eeae5e2cbb5eb872fafbc03a43609d7941840995c"},
+ {file = "msgpack-1.0.8-cp312-cp312-win_amd64.whl", hash = "sha256:74398a4cf19de42e1498368c36eed45d9528f5fd0155241e82c4082b7e16cffd"},
+ {file = "msgpack-1.0.8.tar.gz", hash = "sha256:95c02b0e27e706e48d0e5426d1710ca78e0f0628d6e89d5b5a5b91a5f12274f3"},
]
[[package]]
@@ -1269,7 +1270,7 @@ files = [
[[package]]
name = "mypy"
-version = "1.8.0"
+version = "1.9.0"
requires_python = ">=3.8"
summary = "Optional static typing for Python"
groups = ["lint"]
@@ -1278,18 +1279,18 @@ dependencies = [
"typing-extensions>=4.1.0",
]
files = [
- {file = "mypy-1.8.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:855fe27b80375e5c5878492f0729540db47b186509c98dae341254c8f45f42ae"},
- {file = "mypy-1.8.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4c886c6cce2d070bd7df4ec4a05a13ee20c0aa60cb587e8d1265b6c03cf91da3"},
- {file = "mypy-1.8.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d19c413b3c07cbecf1f991e2221746b0d2a9410b59cb3f4fb9557f0365a1a817"},
- {file = "mypy-1.8.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:9261ed810972061388918c83c3f5cd46079d875026ba97380f3e3978a72f503d"},
- {file = "mypy-1.8.0-cp311-cp311-win_amd64.whl", hash = "sha256:51720c776d148bad2372ca21ca29256ed483aa9a4cdefefcef49006dff2a6835"},
- {file = "mypy-1.8.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:52825b01f5c4c1c4eb0db253ec09c7aa17e1a7304d247c48b6f3599ef40db8bd"},
- {file = "mypy-1.8.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f5ac9a4eeb1ec0f1ccdc6f326bcdb464de5f80eb07fb38b5ddd7b0de6bc61e55"},
- {file = "mypy-1.8.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:afe3fe972c645b4632c563d3f3eff1cdca2fa058f730df2b93a35e3b0c538218"},
- {file = "mypy-1.8.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:42c6680d256ab35637ef88891c6bd02514ccb7e1122133ac96055ff458f93fc3"},
- {file = "mypy-1.8.0-cp312-cp312-win_amd64.whl", hash = "sha256:720a5ca70e136b675af3af63db533c1c8c9181314d207568bbe79051f122669e"},
- {file = "mypy-1.8.0-py3-none-any.whl", hash = "sha256:538fd81bb5e430cc1381a443971c0475582ff9f434c16cd46d2c66763ce85d9d"},
- {file = "mypy-1.8.0.tar.gz", hash = "sha256:6ff8b244d7085a0b425b56d327b480c3b29cafbd2eff27316a004f9a7391ae07"},
+ {file = "mypy-1.9.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:653265f9a2784db65bfca694d1edd23093ce49740b2244cde583aeb134c008f3"},
+ {file = "mypy-1.9.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3a3c007ff3ee90f69cf0a15cbcdf0995749569b86b6d2f327af01fd1b8aee9dc"},
+ {file = "mypy-1.9.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2418488264eb41f69cc64a69a745fad4a8f86649af4b1041a4c64ee61fc61129"},
+ {file = "mypy-1.9.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:68edad3dc7d70f2f17ae4c6c1b9471a56138ca22722487eebacfd1eb5321d612"},
+ {file = "mypy-1.9.0-cp311-cp311-win_amd64.whl", hash = "sha256:85ca5fcc24f0b4aeedc1d02f93707bccc04733f21d41c88334c5482219b1ccb3"},
+ {file = "mypy-1.9.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:aceb1db093b04db5cd390821464504111b8ec3e351eb85afd1433490163d60cd"},
+ {file = "mypy-1.9.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0235391f1c6f6ce487b23b9dbd1327b4ec33bb93934aa986efe8a9563d9349e6"},
+ {file = "mypy-1.9.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d4d5ddc13421ba3e2e082a6c2d74c2ddb3979c39b582dacd53dd5d9431237185"},
+ {file = "mypy-1.9.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:190da1ee69b427d7efa8aa0d5e5ccd67a4fb04038c380237a0d96829cb157913"},
+ {file = "mypy-1.9.0-cp312-cp312-win_amd64.whl", hash = "sha256:fe28657de3bfec596bbeef01cb219833ad9d38dd5393fc649f4b366840baefe6"},
+ {file = "mypy-1.9.0-py3-none-any.whl", hash = "sha256:a260627a570559181a9ea5de61ac6297aa5af202f06fd7ab093ce74e7181e43e"},
+ {file = "mypy-1.9.0.tar.gz", hash = "sha256:3cc5da0127e6a478cddd906068496a97a7618a21ce9b54bde5bf7e539c7af974"},
]
[[package]]
@@ -1401,13 +1402,13 @@ files = [
[[package]]
name = "packaging"
-version = "23.2"
+version = "24.0"
requires_python = ">=3.7"
summary = "Core utilities for Python packages"
groups = ["docs", "test"]
files = [
- {file = "packaging-23.2-py3-none-any.whl", hash = "sha256:8c491190033a9af7e1d931d0b5dacc2ef47509b34dd0de67ed209b5203fc88c7"},
- {file = "packaging-23.2.tar.gz", hash = "sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5"},
+ {file = "packaging-24.0-py3-none-any.whl", hash = "sha256:2ddfb553fdf02fb784c234c7ba6ccc288296ceabec964ad2eae3777778130bc5"},
+ {file = "packaging-24.0.tar.gz", hash = "sha256:eb82c5e3e56209074766e6885bb04b8c38a0c015d0a30036ebe7ece34c9989e9"},
]
[[package]]
@@ -1434,7 +1435,7 @@ files = [
[[package]]
name = "polyfactory"
-version = "2.14.1"
+version = "2.15.0"
requires_python = "<4.0,>=3.8"
summary = "Mock data generation factories"
groups = ["default"]
@@ -1443,8 +1444,8 @@ dependencies = [
"typing-extensions>=4.6.0",
]
files = [
- {file = "polyfactory-2.14.1-py3-none-any.whl", hash = "sha256:8aff3be75e046501ec5c411c78c23db284322c760fef50d560ee6ed683f217c8"},
- {file = "polyfactory-2.14.1.tar.gz", hash = "sha256:8c1d5f15dad1ebfd0845d65d4a55f9791cddfa6b3096ad9f9e2fd02a4804631b"},
+ {file = "polyfactory-2.15.0-py3-none-any.whl", hash = "sha256:ff5b6a8742cbd6fbde9f81310b9732d5421fbec31916d6ede5a977753110fbe9"},
+ {file = "polyfactory-2.15.0.tar.gz", hash = "sha256:a3ff5263756ad74acf4001f04c1b6aab7d1197cbaa070352df79573a8dcd85ec"},
]
[[package]]
@@ -1511,7 +1512,7 @@ files = [
[[package]]
name = "pydantic"
-version = "2.6.2"
+version = "2.6.3"
requires_python = ">=3.8"
summary = "Data validation using Python type hints"
groups = ["default", "docs"]
@@ -1521,8 +1522,8 @@ dependencies = [
"typing-extensions>=4.6.1",
]
files = [
- {file = "pydantic-2.6.2-py3-none-any.whl", hash = "sha256:37a5432e54b12fecaa1049c5195f3d860a10e01bdfd24f1840ef14bd0d3aeab3"},
- {file = "pydantic-2.6.2.tar.gz", hash = "sha256:a09be1c3d28f3abe37f8a78af58284b236a92ce520105ddc91a6d29ea1176ba7"},
+ {file = "pydantic-2.6.3-py3-none-any.whl", hash = "sha256:72c6034df47f46ccdf81869fddb81aade68056003900a8724a4f160700016a2a"},
+ {file = "pydantic-2.6.3.tar.gz", hash = "sha256:e07805c4c7f5c6826e33a1d4c9d47950d7eaf34868e2690f8594d2e30241f11f"},
]
[[package]]
@@ -1656,7 +1657,7 @@ files = [
[[package]]
name = "pyright"
-version = "1.1.351"
+version = "1.1.353"
requires_python = ">=3.7"
summary = "Command line wrapper for pyright"
groups = ["lint"]
@@ -1664,8 +1665,8 @@ dependencies = [
"nodeenv>=1.6.0",
]
files = [
- {file = "pyright-1.1.351-py3-none-any.whl", hash = "sha256:83b44b25396ae20661fc5f133c3fce30928ff1296d4f2e5ff0bca5fcf03eb89d"},
- {file = "pyright-1.1.351.tar.gz", hash = "sha256:01124099714eebd7f6525d8cbfa350626b56dfaf771cfcd55c03e69f0f1efbbd"},
+ {file = "pyright-1.1.353-py3-none-any.whl", hash = "sha256:8d7e6719d0be4fd9f4a37f010237c6a74d91ec1e7c81de634c2f3f9965f8ab43"},
+ {file = "pyright-1.1.353.tar.gz", hash = "sha256:24343bbc2a4f997563f966b6244a2e863473f1d85af6d24abcb366fcbb4abca9"},
]
[[package]]
@@ -1681,7 +1682,7 @@ files = [
[[package]]
name = "pytest"
-version = "8.0.2"
+version = "8.1.1"
requires_python = ">=3.8"
summary = "pytest: simple powerful testing with Python"
groups = ["test"]
@@ -1689,16 +1690,16 @@ dependencies = [
"colorama; sys_platform == \"win32\"",
"iniconfig",
"packaging",
- "pluggy<2.0,>=1.3.0",
+ "pluggy<2.0,>=1.4",
]
files = [
- {file = "pytest-8.0.2-py3-none-any.whl", hash = "sha256:edfaaef32ce5172d5466b5127b42e0d6d35ebbe4453f0e3505d96afd93f6b096"},
- {file = "pytest-8.0.2.tar.gz", hash = "sha256:d4051d623a2e0b7e51960ba963193b09ce6daeb9759a451844a21e4ddedfc1bd"},
+ {file = "pytest-8.1.1-py3-none-any.whl", hash = "sha256:2a8386cfc11fa9d2c50ee7b2a57e7d898ef90470a7a34c4b949ff59662bb78b7"},
+ {file = "pytest-8.1.1.tar.gz", hash = "sha256:ac978141a75948948817d360297b7aae0fcb9d6ff6bc9ec6d514b85d5a65c044"},
]
[[package]]
name = "pytest-asyncio"
-version = "0.23.5"
+version = "0.23.5.post1"
requires_python = ">=3.8"
summary = "Pytest support for asyncio"
groups = ["test"]
@@ -1706,8 +1707,8 @@ dependencies = [
"pytest<9,>=7.0.0",
]
files = [
- {file = "pytest-asyncio-0.23.5.tar.gz", hash = "sha256:3a048872a9c4ba14c3e90cc1aa20cbc2def7d01c7c8db3777ec281ba9c057675"},
- {file = "pytest_asyncio-0.23.5-py3-none-any.whl", hash = "sha256:4e7093259ba018d58ede7d5315131d21923a60f8a6e9ee266ce1589685c89eac"},
+ {file = "pytest-asyncio-0.23.5.post1.tar.gz", hash = "sha256:b9a8806bea78c21276bc34321bbf234ba1b2ea5b30d9f0ce0f2dea45e4685813"},
+ {file = "pytest_asyncio-0.23.5.post1-py3-none-any.whl", hash = "sha256:30f54d27774e79ac409778889880242b0403d09cabd65b727ce90fe92dd5d80e"},
]
[[package]]
@@ -1770,7 +1771,7 @@ files = [
[[package]]
name = "python-dateutil"
-version = "2.8.2"
+version = "2.9.0.post0"
requires_python = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7"
summary = "Extensions to the standard Python datetime module"
groups = ["default"]
@@ -1778,8 +1779,8 @@ dependencies = [
"six>=1.5",
]
files = [
- {file = "python-dateutil-2.8.2.tar.gz", hash = "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86"},
- {file = "python_dateutil-2.8.2-py2.py3-none-any.whl", hash = "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9"},
+ {file = "python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3"},
+ {file = "python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427"},
]
[[package]]
@@ -1852,7 +1853,7 @@ files = [
[[package]]
name = "rich"
-version = "13.7.0"
+version = "13.7.1"
requires_python = ">=3.7.0"
summary = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal"
groups = ["default"]
@@ -1861,8 +1862,8 @@ dependencies = [
"pygments<3.0.0,>=2.13.0",
]
files = [
- {file = "rich-13.7.0-py3-none-any.whl", hash = "sha256:6da14c108c4866ee9520bbffa71f6fe3962e193b7da68720583850cd4548e235"},
- {file = "rich-13.7.0.tar.gz", hash = "sha256:5cb5123b5cf9ee70584244246816e9114227e0b98ad9176eede6ad54bf5403fa"},
+ {file = "rich-13.7.1-py3-none-any.whl", hash = "sha256:4edbae314f59eb482f54e9e30bf00d33350aaa94f4bfcd4e9e3110e64d0d7222"},
+ {file = "rich-13.7.1.tar.gz", hash = "sha256:9be308cb1fe2f1f57d67ce99e95af38a1e2bc71ad9813b0e247cf7ffbcc3a432"},
]
[[package]]
@@ -1938,28 +1939,28 @@ files = [
[[package]]
name = "ruff"
-version = "0.2.2"
+version = "0.3.2"
requires_python = ">=3.7"
summary = "An extremely fast Python linter and code formatter, written in Rust."
groups = ["default"]
files = [
- {file = "ruff-0.2.2-py3-none-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:0a9efb032855ffb3c21f6405751d5e147b0c6b631e3ca3f6b20f917572b97eb6"},
- {file = "ruff-0.2.2-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:d450b7fbff85913f866a5384d8912710936e2b96da74541c82c1b458472ddb39"},
- {file = "ruff-0.2.2-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ecd46e3106850a5c26aee114e562c329f9a1fbe9e4821b008c4404f64ff9ce73"},
- {file = "ruff-0.2.2-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5e22676a5b875bd72acd3d11d5fa9075d3a5f53b877fe7b4793e4673499318ba"},
- {file = "ruff-0.2.2-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1695700d1e25a99d28f7a1636d85bafcc5030bba9d0578c0781ba1790dbcf51c"},
- {file = "ruff-0.2.2-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:b0c232af3d0bd8f521806223723456ffebf8e323bd1e4e82b0befb20ba18388e"},
- {file = "ruff-0.2.2-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f63d96494eeec2fc70d909393bcd76c69f35334cdbd9e20d089fb3f0640216ca"},
- {file = "ruff-0.2.2-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6a61ea0ff048e06de273b2e45bd72629f470f5da8f71daf09fe481278b175001"},
- {file = "ruff-0.2.2-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5e1439c8f407e4f356470e54cdecdca1bd5439a0673792dbe34a2b0a551a2fe3"},
- {file = "ruff-0.2.2-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:940de32dc8853eba0f67f7198b3e79bc6ba95c2edbfdfac2144c8235114d6726"},
- {file = "ruff-0.2.2-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:0c126da55c38dd917621552ab430213bdb3273bb10ddb67bc4b761989210eb6e"},
- {file = "ruff-0.2.2-py3-none-musllinux_1_2_i686.whl", hash = "sha256:3b65494f7e4bed2e74110dac1f0d17dc8e1f42faaa784e7c58a98e335ec83d7e"},
- {file = "ruff-0.2.2-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:1ec49be4fe6ddac0503833f3ed8930528e26d1e60ad35c2446da372d16651ce9"},
- {file = "ruff-0.2.2-py3-none-win32.whl", hash = "sha256:d920499b576f6c68295bc04e7b17b6544d9d05f196bb3aac4358792ef6f34325"},
- {file = "ruff-0.2.2-py3-none-win_amd64.whl", hash = "sha256:cc9a91ae137d687f43a44c900e5d95e9617cb37d4c989e462980ba27039d239d"},
- {file = "ruff-0.2.2-py3-none-win_arm64.whl", hash = "sha256:c9d15fc41e6054bfc7200478720570078f0b41c9ae4f010bcc16bd6f4d1aacdd"},
- {file = "ruff-0.2.2.tar.gz", hash = "sha256:e62ed7f36b3068a30ba39193a14274cd706bc486fad521276458022f7bccb31d"},
+ {file = "ruff-0.3.2-py3-none-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:77f2612752e25f730da7421ca5e3147b213dca4f9a0f7e0b534e9562c5441f01"},
+ {file = "ruff-0.3.2-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:9966b964b2dd1107797be9ca7195002b874424d1d5472097701ae8f43eadef5d"},
+ {file = "ruff-0.3.2-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b83d17ff166aa0659d1e1deaf9f2f14cbe387293a906de09bc4860717eb2e2da"},
+ {file = "ruff-0.3.2-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bb875c6cc87b3703aeda85f01c9aebdce3d217aeaca3c2e52e38077383f7268a"},
+ {file = "ruff-0.3.2-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:be75e468a6a86426430373d81c041b7605137a28f7014a72d2fc749e47f572aa"},
+ {file = "ruff-0.3.2-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:967978ac2d4506255e2f52afe70dda023fc602b283e97685c8447d036863a302"},
+ {file = "ruff-0.3.2-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1231eacd4510f73222940727ac927bc5d07667a86b0cbe822024dd00343e77e9"},
+ {file = "ruff-0.3.2-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2c6d613b19e9a8021be2ee1d0e27710208d1603b56f47203d0abbde906929a9b"},
+ {file = "ruff-0.3.2-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c8439338a6303585d27b66b4626cbde89bb3e50fa3cae86ce52c1db7449330a7"},
+ {file = "ruff-0.3.2-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:de8b480d8379620cbb5ea466a9e53bb467d2fb07c7eca54a4aa8576483c35d36"},
+ {file = "ruff-0.3.2-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:b74c3de9103bd35df2bb05d8b2899bf2dbe4efda6474ea9681280648ec4d237d"},
+ {file = "ruff-0.3.2-py3-none-musllinux_1_2_i686.whl", hash = "sha256:f380be9fc15a99765c9cf316b40b9da1f6ad2ab9639e551703e581a5e6da6745"},
+ {file = "ruff-0.3.2-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:0ac06a3759c3ab9ef86bbeca665d31ad3aa9a4b1c17684aadb7e61c10baa0df4"},
+ {file = "ruff-0.3.2-py3-none-win32.whl", hash = "sha256:9bd640a8f7dd07a0b6901fcebccedadeb1a705a50350fb86b4003b805c81385a"},
+ {file = "ruff-0.3.2-py3-none-win_amd64.whl", hash = "sha256:0c1bdd9920cab5707c26c8b3bf33a064a4ca7842d91a99ec0634fec68f9f4037"},
+ {file = "ruff-0.3.2-py3-none-win_arm64.whl", hash = "sha256:5f65103b1d76e0d600cabd577b04179ff592064eaa451a70a81085930e907d0b"},
+ {file = "ruff-0.3.2.tar.gz", hash = "sha256:fa78ec9418eb1ca3db392811df3376b46471ae93792a81af2d1cbb0e5dcb5142"},
]
[[package]]
@@ -2325,7 +2326,7 @@ files = [
[[package]]
name = "sqlalchemy"
-version = "2.0.27"
+version = "2.0.28"
requires_python = ">=3.7"
summary = "Database Abstraction Library"
groups = ["default", "docs"]
@@ -2334,24 +2335,24 @@ dependencies = [
"typing-extensions>=4.6.0",
]
files = [
- {file = "SQLAlchemy-2.0.27-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6c5bad7c60a392850d2f0fee8f355953abaec878c483dd7c3836e0089f046bf6"},
- {file = "SQLAlchemy-2.0.27-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a3012ab65ea42de1be81fff5fb28d6db893ef978950afc8130ba707179b4284a"},
- {file = "SQLAlchemy-2.0.27-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dbcd77c4d94b23e0753c5ed8deba8c69f331d4fd83f68bfc9db58bc8983f49cd"},
- {file = "SQLAlchemy-2.0.27-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d177b7e82f6dd5e1aebd24d9c3297c70ce09cd1d5d37b43e53f39514379c029c"},
- {file = "SQLAlchemy-2.0.27-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:680b9a36029b30cf063698755d277885d4a0eab70a2c7c6e71aab601323cba45"},
- {file = "SQLAlchemy-2.0.27-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:1306102f6d9e625cebaca3d4c9c8f10588735ef877f0360b5cdb4fdfd3fd7131"},
- {file = "SQLAlchemy-2.0.27-cp311-cp311-win32.whl", hash = "sha256:5b78aa9f4f68212248aaf8943d84c0ff0f74efc65a661c2fc68b82d498311fd5"},
- {file = "SQLAlchemy-2.0.27-cp311-cp311-win_amd64.whl", hash = "sha256:15e19a84b84528f52a68143439d0c7a3a69befcd4f50b8ef9b7b69d2628ae7c4"},
- {file = "SQLAlchemy-2.0.27-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:0de1263aac858f288a80b2071990f02082c51d88335a1db0d589237a3435fe71"},
- {file = "SQLAlchemy-2.0.27-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ce850db091bf7d2a1f2fdb615220b968aeff3849007b1204bf6e3e50a57b3d32"},
- {file = "SQLAlchemy-2.0.27-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8dfc936870507da96aebb43e664ae3a71a7b96278382bcfe84d277b88e379b18"},
- {file = "SQLAlchemy-2.0.27-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c4fbe6a766301f2e8a4519f4500fe74ef0a8509a59e07a4085458f26228cd7cc"},
- {file = "SQLAlchemy-2.0.27-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:4535c49d961fe9a77392e3a630a626af5baa967172d42732b7a43496c8b28876"},
- {file = "SQLAlchemy-2.0.27-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:0fb3bffc0ced37e5aa4ac2416f56d6d858f46d4da70c09bb731a246e70bff4d5"},
- {file = "SQLAlchemy-2.0.27-cp312-cp312-win32.whl", hash = "sha256:7f470327d06400a0aa7926b375b8e8c3c31d335e0884f509fe272b3c700a7254"},
- {file = "SQLAlchemy-2.0.27-cp312-cp312-win_amd64.whl", hash = "sha256:f9374e270e2553653d710ece397df67db9d19c60d2647bcd35bfc616f1622dcd"},
- {file = "SQLAlchemy-2.0.27-py3-none-any.whl", hash = "sha256:1ab4e0448018d01b142c916cc7119ca573803a4745cfe341b8f95657812700ac"},
- {file = "SQLAlchemy-2.0.27.tar.gz", hash = "sha256:86a6ed69a71fe6b88bf9331594fa390a2adda4a49b5c06f98e47bf0d392534f8"},
+ {file = "SQLAlchemy-2.0.28-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:46a3d4e7a472bfff2d28db838669fc437964e8af8df8ee1e4548e92710929adc"},
+ {file = "SQLAlchemy-2.0.28-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:0d3dd67b5d69794cfe82862c002512683b3db038b99002171f624712fa71aeaa"},
+ {file = "SQLAlchemy-2.0.28-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c61e2e41656a673b777e2f0cbbe545323dbe0d32312f590b1bc09da1de6c2a02"},
+ {file = "SQLAlchemy-2.0.28-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0315d9125a38026227f559488fe7f7cee1bd2fbc19f9fd637739dc50bb6380b2"},
+ {file = "SQLAlchemy-2.0.28-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:af8ce2d31679006e7b747d30a89cd3ac1ec304c3d4c20973f0f4ad58e2d1c4c9"},
+ {file = "SQLAlchemy-2.0.28-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:81ba314a08c7ab701e621b7ad079c0c933c58cdef88593c59b90b996e8b58fa5"},
+ {file = "SQLAlchemy-2.0.28-cp311-cp311-win32.whl", hash = "sha256:1ee8bd6d68578e517943f5ebff3afbd93fc65f7ef8f23becab9fa8fb315afb1d"},
+ {file = "SQLAlchemy-2.0.28-cp311-cp311-win_amd64.whl", hash = "sha256:ad7acbe95bac70e4e687a4dc9ae3f7a2f467aa6597049eeb6d4a662ecd990bb6"},
+ {file = "SQLAlchemy-2.0.28-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:d3499008ddec83127ab286c6f6ec82a34f39c9817f020f75eca96155f9765097"},
+ {file = "SQLAlchemy-2.0.28-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:9b66fcd38659cab5d29e8de5409cdf91e9986817703e1078b2fdaad731ea66f5"},
+ {file = "SQLAlchemy-2.0.28-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bea30da1e76cb1acc5b72e204a920a3a7678d9d52f688f087dc08e54e2754c67"},
+ {file = "SQLAlchemy-2.0.28-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:124202b4e0edea7f08a4db8c81cc7859012f90a0d14ba2bf07c099aff6e96462"},
+ {file = "SQLAlchemy-2.0.28-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:e23b88c69497a6322b5796c0781400692eca1ae5532821b39ce81a48c395aae9"},
+ {file = "SQLAlchemy-2.0.28-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4b6303bfd78fb3221847723104d152e5972c22367ff66edf09120fcde5ddc2e2"},
+ {file = "SQLAlchemy-2.0.28-cp312-cp312-win32.whl", hash = "sha256:a921002be69ac3ab2cf0c3017c4e6a3377f800f1fca7f254c13b5f1a2f10022c"},
+ {file = "SQLAlchemy-2.0.28-cp312-cp312-win_amd64.whl", hash = "sha256:b4a2cf92995635b64876dc141af0ef089c6eea7e05898d8d8865e71a326c0385"},
+ {file = "SQLAlchemy-2.0.28-py3-none-any.whl", hash = "sha256:78bb7e8da0183a8301352d569900d9d3594c48ac21dc1c2ec6b3121ed8b6c986"},
+ {file = "SQLAlchemy-2.0.28.tar.gz", hash = "sha256:dd53b6c4e6d960600fd6532b79ee28e2da489322fcf6648738134587faf767b6"},
]
[[package]]
From a73c315c49cbdb2131c042fc54a2df75bea03b60 Mon Sep 17 00:00:00 2001
From: Jacob Coffee
Date: Sun, 10 Mar 2024 23:23:59 -0500
Subject: [PATCH 22/29] feat: add routes to display sections on guild data
---
src/server/domain/guilds/controllers.py | 137 ++++++++++++++++++++++-
src/server/domain/guilds/dependencies.py | 110 +++++++++++++++++-
src/server/domain/guilds/schemas.py | 11 +-
src/server/domain/guilds/services.py | 81 +++++++++++++-
src/server/domain/guilds/urls.py | 8 ++
5 files changed, 338 insertions(+), 9 deletions(-)
diff --git a/src/server/domain/guilds/controllers.py b/src/server/domain/guilds/controllers.py
index 6ffb014..55af847 100644
--- a/src/server/domain/guilds/controllers.py
+++ b/src/server/domain/guilds/controllers.py
@@ -9,9 +9,28 @@
from litestar.params import Dependency, Parameter
from server.domain.guilds import urls
-from server.domain.guilds.dependencies import provides_guilds_service
-from server.domain.guilds.schemas import GuildSchema, UpdateableGuildSetting
-from server.domain.guilds.services import GuildsService # noqa: TCH001
+from server.domain.guilds.dependencies import (
+ provides_allowed_users_config_service,
+ provides_forum_config_service,
+ provides_github_config_service,
+ provides_guilds_service,
+ provides_sotags_config_service,
+)
+from server.domain.guilds.schemas import (
+ AllowedUsersConfigSchema,
+ ForumConfigSchema,
+ GitHubConfigSchema,
+ GuildSchema,
+ SOTagsConfigSchema,
+ UpdateableGuildSetting,
+)
+from server.domain.guilds.services import (
+ AllowedUsersConfigService, # noqa: TCH001
+ ForumConfigService, # noqa: TCH001
+ GitHubConfigService, # noqa: TCH001
+ GuildsService, # noqa: TCH001
+ SOTagsConfigService, # noqa: TCH001
+)
if TYPE_CHECKING:
from advanced_alchemy import FilterTypes
@@ -24,7 +43,13 @@ class GuildsController(Controller):
"""Controller for guild-based routes."""
tags = ["Guilds"]
- dependencies = {"guilds_service": Provide(provides_guilds_service)}
+ dependencies = {
+ "guilds_service": Provide(provides_guilds_service),
+ "github_service": Provide(provides_github_config_service),
+ "sotags_service": Provide(provides_sotags_config_service),
+ "allowed_users_service": Provide(provides_allowed_users_config_service),
+ "forum_service": Provide(provides_forum_config_service),
+ }
@get(
operation_id="Guilds",
@@ -145,3 +170,107 @@ async def get_guild(
"""
result = await guilds_service.get(guild_id, id_attribute="guild_id")
return guilds_service.to_schema(GuildSchema, result)
+
+ @get(
+ operation_id="GitHubDetail",
+ name="guilds:github-config",
+ summary="Get GitHub config for a guild.",
+ path=urls.GUILD_GITHUB_DETAIL,
+ )
+ async def get_guild_github_config(
+ self,
+ github_service: GitHubConfigService,
+ guild_id: int = Parameter(
+ title="Guild ID",
+ description="The guild ID.",
+ ),
+ ) -> GitHubConfigSchema | OffsetPagination[GitHubConfigSchema]:
+ """Get a guild's GitHub config by ID.
+
+ Args:
+ github_service (GitHubConfigService): GitHub config service
+ guild_id (int): Guild ID
+
+ Returns:
+ GitHubConfig: GitHub config object
+ """
+ result = await github_service.get(guild_id, id_attribute="guild_id")
+ return github_service.to_schema(GitHubConfigSchema, result)
+
+ @get(
+ operation_id="SOTagsDetail",
+ name="guilds:sotags-config",
+ summary="Get StackOverflow tags config for a guild.",
+ path=urls.GUILD_SOTAGS_DETAIL,
+ )
+ async def get_guild_sotags_config(
+ self,
+ sotags_service: SOTagsConfigService,
+ guild_id: int = Parameter(
+ title="Guild ID",
+ description="The guild ID.",
+ ),
+ ) -> SOTagsConfigSchema | OffsetPagination[SOTagsConfigSchema]:
+ """Get a guild's StackOverflow tags config by ID.
+
+ Args:
+ sotags_service (SOTagsConfigService): StackOverflow tags config service
+ guild_id (int): Guild ID
+
+ Returns:
+ SOTagsConfig: StackOverflow tags config object
+ """
+ result = await sotags_service.get(guild_id, id_attribute="guild_id")
+ return sotags_service.to_schema(SOTagsConfigSchema, result)
+
+ @get(
+ operation_id="AllowedUsersDetail",
+ name="guilds:allowed-users-config",
+ summary="Get allowed users config for a guild.",
+ path=urls.GUILD_ALLOWED_USERS_DETAIL,
+ )
+ async def get_guild_allowed_users_config(
+ self,
+ allowed_users_service: AllowedUsersConfigService,
+ guild_id: int = Parameter(
+ title="Guild ID",
+ description="The guild ID.",
+ ),
+ ) -> AllowedUsersConfigSchema | OffsetPagination[AllowedUsersConfigSchema]:
+ """Get a guild's allowed users config by ID.
+
+ Args:
+ allowed_users_service (AllowedUsersConfigService): Allowed users config service
+ guild_id (int): Guild ID
+
+ Returns:
+ AllowedUsersConfig: Allowed users config object
+ """
+ result = await allowed_users_service.get(guild_id, id_attribute="guild_id")
+ return allowed_users_service.to_schema(AllowedUsersConfigSchema, result)
+
+ @get(
+ operation_id="ForumDetail",
+ name="guilds:forum-config",
+ summary="Get forum config for a guild.",
+ path=urls.GUILD_FORUM_DETAIL,
+ )
+ async def get_guild_forum_config(
+ self,
+ forum_service: ForumConfigService,
+ guild_id: int = Parameter(
+ title="Guild ID",
+ description="The guild ID.",
+ ),
+ ) -> ForumConfigSchema | OffsetPagination[ForumConfigSchema]:
+ """Get a guild's forum config by ID.
+
+ Args:
+ forum_service (ForumConfigService): Forum config service
+ guild_id (int): Guild ID
+
+ Returns:
+ ForumConfig: Forum config object
+ """
+ result = await forum_service.get(guild_id, id_attribute="guild_id")
+ return forum_service.to_schema(ForumConfigSchema, result)
diff --git a/src/server/domain/guilds/dependencies.py b/src/server/domain/guilds/dependencies.py
index f557f5c..0425d8c 100644
--- a/src/server/domain/guilds/dependencies.py
+++ b/src/server/domain/guilds/dependencies.py
@@ -8,7 +8,13 @@
from sqlalchemy.orm import joinedload, noload, selectinload
from server.domain.db.models import AllowedUsersConfig, ForumConfig, GitHubConfig, Guild, SOTagsConfig
-from server.domain.guilds.services import GuildsService
+from server.domain.guilds.services import (
+ AllowedUsersConfigService,
+ ForumConfigService,
+ GitHubConfigService,
+ GuildsService,
+ SOTagsConfigService,
+)
from server.lib import log
if TYPE_CHECKING:
@@ -16,7 +22,13 @@
from sqlalchemy.ext.asyncio import AsyncSession
-__all__ = ("provides_guilds_service",)
+__all__ = (
+ "provides_allowed_users_config_service",
+ "provides_forum_config_service",
+ "provides_github_config_service",
+ "provides_guilds_service",
+ "provides_sotags_config_service",
+)
logger = log.get_logger()
@@ -53,3 +65,97 @@ async def provides_guilds_service(db_session: AsyncSession) -> AsyncGenerator[Gu
yield service
finally:
...
+
+
+async def provides_github_config_service(db_session: AsyncSession) -> AsyncGenerator[GitHubConfigService, None]:
+ """Construct GitHubConfig-based repository and service objects for the request.
+
+ Args:
+ db_session (AsyncSession): SQLAlchemy AsyncSession
+
+ Yields:
+ GitHubConfigService: GitHubConfig-based service
+ """
+ async with GitHubConfigService.new(
+ session=db_session,
+ statement=select(GitHubConfig)
+ .order_by(GitHubConfig.github_organization)
+ .options(
+ selectinload(GitHubConfig.guild).options(noload("*")),
+ ),
+ ) as service:
+ try:
+ yield service
+ finally:
+ ...
+
+
+async def provides_sotags_config_service(db_session: AsyncSession) -> AsyncGenerator[SOTagsConfigService, None]:
+ """Construct SOTagsConfig-based repository and service objects for the request.
+
+ Args:
+ db_session (AsyncSession): SQLAlchemy AsyncSession
+
+ Yields:
+ SOTagsConfigService: SOTagsConfig-based service
+ """
+ async with SOTagsConfigService.new(
+ session=db_session,
+ statement=select(SOTagsConfig)
+ .order_by(SOTagsConfig.tag_name)
+ .options(
+ selectinload(SOTagsConfig.guild).options(noload("*")),
+ ),
+ ) as service:
+ try:
+ yield service
+ finally:
+ ...
+
+
+async def provides_allowed_users_config_service(
+ db_session: AsyncSession,
+) -> AsyncGenerator[AllowedUsersConfigService, None]:
+ """Construct AllowedUsersConfig-based repository and service objects for the request.
+
+ Args:
+ db_session (AsyncSession): SQLAlchemy AsyncSession
+
+ Yields:
+ AllowedUsersConfigService: AllowedUsersConfig-based service
+ """
+ async with AllowedUsersConfigService.new(
+ session=db_session,
+ statement=select(AllowedUsersConfig)
+ .order_by(AllowedUsersConfig.user_id)
+ .options(
+ selectinload(AllowedUsersConfig.guild).options(noload("*")),
+ ),
+ ) as service:
+ try:
+ yield service
+ finally:
+ ...
+
+
+async def provides_forum_config_service(db_session: AsyncSession) -> AsyncGenerator[ForumConfigService, None]:
+ """Construct ForumConfig-based repository and service objects for the request.
+
+ Args:
+ db_session (AsyncSession): SQLAlchemy AsyncSession
+
+ Yields:
+ ForumConfigService: ForumConfig-based service
+ """
+ async with ForumConfigService.new(
+ session=db_session,
+ statement=select(ForumConfig)
+ .order_by(ForumConfig.help_forum)
+ .options(
+ selectinload(ForumConfig.guild).options(noload("*")),
+ ),
+ ) as service:
+ try:
+ yield service
+ finally:
+ ...
diff --git a/src/server/domain/guilds/schemas.py b/src/server/domain/guilds/schemas.py
index 09d2205..068f24b 100644
--- a/src/server/domain/guilds/schemas.py
+++ b/src/server/domain/guilds/schemas.py
@@ -8,7 +8,16 @@
from server.lib.schema import CamelizedBaseModel
-__all__ = ("AllowedUsersConfigSchema", "ForumConfigSchema", "GitHubConfigSchema", "GuildCreate", "GuildSchema", "GuildUpdate", "SOTagsConfigSchema", "UpdateableGuildSetting", )
+__all__ = (
+ "AllowedUsersConfigSchema",
+ "ForumConfigSchema",
+ "GitHubConfigSchema",
+ "GuildCreate",
+ "GuildSchema",
+ "GuildUpdate",
+ "SOTagsConfigSchema",
+ "UpdateableGuildSetting",
+)
class GitHubConfigSchema(CamelizedBaseModel):
diff --git a/src/server/domain/guilds/services.py b/src/server/domain/guilds/services.py
index 96f1260..d148d16 100644
--- a/src/server/domain/guilds/services.py
+++ b/src/server/domain/guilds/services.py
@@ -4,12 +4,23 @@
from typing import Any
-from server.domain.db.models import AllowedUsersConfig, GitHubConfig, Guild, SOTagsConfig
+from server.domain.db.models import AllowedUsersConfig, ForumConfig, GitHubConfig, Guild, SOTagsConfig
from server.lib import log
from server.lib.repository import SQLAlchemyAsyncRepository, SQLAlchemyAsyncSlugRepository
from server.lib.service import SQLAlchemyAsyncRepositoryService
-__all__ = ("GuildsRepository", "GuildsService")
+__all__ = (
+ "AllowedUsersConfigRepository",
+ "AllowedUsersConfigService",
+ "ForumConfigRepository",
+ "ForumConfigService",
+ "GitHubConfigRepository",
+ "GitHubConfigService",
+ "GuildsRepository",
+ "GuildsService",
+ "SOTagsConfigRepository",
+ "SOTagsConfigService",
+)
logger = log.get_logger()
@@ -49,6 +60,19 @@ class GitHubConfigService(SQLAlchemyAsyncRepositoryService[GitHubConfig]):
"""Handles basic operations for the guilds' GitHub config."""
repository_type = GitHubConfigRepository
+ match_fields = ["guild_id"]
+
+ async def to_model(self, data: GitHubConfig | dict[str, Any], operation: str | None = None) -> GitHubConfig:
+ """Convert data to a model.
+
+ Args:
+ data (GitHubConfig | dict[str, Any]): Data to convert to a model
+ operation (str | None): Operation to perform on the data
+
+ Returns:
+ Project: Converted model
+ """
+ return await super().to_model(data, operation)
class SOTagsConfigRepository(SQLAlchemyAsyncRepository[SOTagsConfig]):
@@ -61,6 +85,19 @@ class SOTagsConfigService(SQLAlchemyAsyncRepositoryService[SOTagsConfig]):
"""Handles basic operations for the guilds' StackOverflow tags config."""
repository_type = SOTagsConfigRepository
+ match_fields = ["guild_id"]
+
+ async def to_model(self, data: SOTagsConfig | dict[str, Any], operation: str | None = None) -> SOTagsConfig:
+ """Convert data to a model.
+
+ Args:
+ data (SOTagsConfig | dict[str, Any]): Data to convert to a model
+ operation (str | None): Operation to perform on the data
+
+ Returns:
+ Project: Converted model
+ """
+ return await super().to_model(data, operation)
class AllowedUsersConfigRepository(SQLAlchemyAsyncRepository[AllowedUsersConfig]):
@@ -73,3 +110,43 @@ class AllowedUsersConfigService(SQLAlchemyAsyncRepositoryService[AllowedUsersCon
"""Handles basic operations for the guilds' Allowed Users config."""
repository_type = AllowedUsersConfigRepository
+ match_fields = ["guild_id"]
+
+ async def to_model(
+ self, data: AllowedUsersConfig | dict[str, Any], operation: str | None = None
+ ) -> AllowedUsersConfig:
+ """Convert data to a model.
+
+ Args:
+ data (AllowedUsersConfig | dict[str, Any]): Data to convert to a model
+ operation (str | None): Operation to perform on the data
+
+ Returns:
+ Project: Converted model
+ """
+ return await super().to_model(data, operation)
+
+
+class ForumConfigRepository(SQLAlchemyAsyncRepository[ForumConfig]):
+ """ForumConfig SQLAlchemy Repository."""
+
+ model_type = ForumConfig
+
+
+class ForumConfigService(SQLAlchemyAsyncRepositoryService[ForumConfig]):
+ """Handles basic operations for the guilds' Forum config."""
+
+ repository_type = AllowedUsersConfigRepository
+ match_fields = ["guild_id"]
+
+ async def to_model(self, data: ForumConfig | dict[str, Any], operation: str | None = None) -> ForumConfig:
+ """Convert data to a model.
+
+ Args:
+ data (ForumConfig | dict[str, Any]): Data to convert to a model
+ operation (str | None): Operation to perform on the data
+
+ Returns:
+ Project: Converted model
+ """
+ return await super().to_model(data, operation)
diff --git a/src/server/domain/guilds/urls.py b/src/server/domain/guilds/urls.py
index 42989d9..d17e0fa 100644
--- a/src/server/domain/guilds/urls.py
+++ b/src/server/domain/guilds/urls.py
@@ -19,3 +19,11 @@
"""Update guild URL."""
GUILD_DETAIL: Final = f"{OPENAPI_SCHEMA}/guilds/{{guild_id:int}}/info"
"""Guild detail URL."""
+GUILD_GITHUB_DETAIL: Final = f"{OPENAPI_SCHEMA}/guilds/{{guild_id:int}}/github/info"
+"""Guild GitHub detail URL."""
+GUILD_SOTAGS_DETAIL: Final = f"{OPENAPI_SCHEMA}/guilds/{{guild_id:int}}/sotags/info"
+"""Guild StackOverflow tags detail URL."""
+GUILD_ALLOWED_USERS_DETAIL: Final = f"{OPENAPI_SCHEMA}/guilds/{{guild_id:int}}/allowed_users/info"
+"""Guild allowed users detail URL."""
+GUILD_FORUM_DETAIL: Final = f"{OPENAPI_SCHEMA}/guilds/{{guild_id:int}}/forum/info"
+"""Guild forum detail URL."""
From d5708fb124910802b038cd3aca4b6ab8701ce76f Mon Sep 17 00:00:00 2001
From: Jacob Coffee
Date: Mon, 11 Mar 2024 00:45:00 -0500
Subject: [PATCH 23/29] ci: add helper for full container refresh
---
Makefile | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/Makefile b/Makefile
index 42ac73d..de44e0a 100644
--- a/Makefile
+++ b/Makefile
@@ -65,10 +65,12 @@ clean-container: ## Stop, remove, and wipe the Byte database container and volum
load-container: migrate ## Perform database migrations and load test data into the Byte database container
@echo "=> Loading database migrations and test data"
- # load data, we already run migrate
-
+ @echo "not yet implemented"
@echo "=> Loaded database migrations and test data"
+refresh-container: clean-container up-container load-container ## Refresh the Byte database container
+
+
.PHONY: refresh-lockfiles
refresh-lockfiles: ## Sync lockfiles with requirements files.
$(PDM) update --update-reuse -G:all
From 47635b84ef56d8ce72a38cc42a245198b80ddd8c Mon Sep 17 00:00:00 2001
From: Jacob Coffee
Date: Mon, 11 Mar 2024 01:19:36 -0500
Subject: [PATCH 24/29] fix!: new migration for uuid issues
---
src/server/domain/db/models.py | 10 +-
.../versions/004_snowflake fixes.py | 178 ++++++++++++++++++
2 files changed, 183 insertions(+), 5 deletions(-)
create mode 100644 src/server/lib/db/migrations/versions/004_snowflake fixes.py
diff --git a/src/server/domain/db/models.py b/src/server/domain/db/models.py
index 81368b8..1390d4a 100644
--- a/src/server/domain/db/models.py
+++ b/src/server/domain/db/models.py
@@ -73,7 +73,7 @@ class GitHubConfig(UUIDAuditBase):
__tablename__ = "github_config" # type: ignore[reportAssignmentType]
__table_args__ = {"comment": "GitHub configuration for a guild."}
- guild_id: Mapped[UUID] = mapped_column(ForeignKey("guild.id", ondelete="cascade"))
+ guild_id: Mapped[int] = mapped_column(BigInteger, ForeignKey("guild.guild_id", ondelete="cascade"))
discussion_sync: Mapped[bool] = mapped_column(default=False)
github_organization: Mapped[str | None]
github_repository: Mapped[str | None]
@@ -92,13 +92,13 @@ class GitHubConfig(UUIDAuditBase):
class SOTagsConfig(UUIDAuditBase):
"""SQLAlchemy association model for a guild's Stack Overflow tags config."""
- __tablename__ = "so_tags" # type: ignore[reportAssignmentType]
+ __tablename__ = "so_tags_config" # type: ignore[reportAssignmentType]
__table_args__ = (
UniqueConstraint("guild_id", "tag_name"),
{"comment": "Configuration for a Discord guild's Stack Overflow tags."},
)
- guild_id: Mapped[UUID] = mapped_column(ForeignKey("guild.id", ondelete="cascade"))
+ guild_id: Mapped[int] = mapped_column(BigInteger, ForeignKey("guild.guild_id", ondelete="cascade"))
guild_name: AssociationProxy[str] = association_proxy("guild", "guild_name")
tag_name: Mapped[str] = mapped_column(String(50))
@@ -131,7 +131,7 @@ class AllowedUsersConfig(UUIDAuditBase):
{"comment": "Configuration for allowed users in a Discord guild."},
)
- guild_id: Mapped[int] = mapped_column(ForeignKey("guild.guild_id", ondelete="cascade"))
+ guild_id: Mapped[int] = mapped_column(BigInteger, ForeignKey("guild.guild_id", ondelete="cascade"))
user_id: Mapped[UUID] = mapped_column(ForeignKey("user.id", ondelete="cascade"))
guild_name: AssociationProxy[str] = association_proxy("guild", "guild_name")
@@ -210,7 +210,7 @@ class ForumConfig(UUIDAuditBase):
__tablename__ = "forum_config" # type: ignore[reportAssignmentType]
__table_args__ = {"comment": "Forum configuration for a guild."}
- guild_id: Mapped[UUID] = mapped_column(ForeignKey("guild.id", ondelete="cascade"))
+ guild_id: Mapped[int] = mapped_column(BigInteger, ForeignKey("guild.guild_id", ondelete="cascade"))
"""Help forum settings."""
help_forum: Mapped[bool] = mapped_column(default=False)
diff --git a/src/server/lib/db/migrations/versions/004_snowflake fixes.py b/src/server/lib/db/migrations/versions/004_snowflake fixes.py
new file mode 100644
index 0000000..6a672ad
--- /dev/null
+++ b/src/server/lib/db/migrations/versions/004_snowflake fixes.py
@@ -0,0 +1,178 @@
+# type: ignore
+"""
+
+Revision ID: f32ee278015d
+Revises: 73a26ceab2c4
+Create Date: 2024-03-11 05:17:53.372688+00:00
+
+"""
+
+from __future__ import annotations
+
+import warnings
+
+import sqlalchemy as sa
+from advanced_alchemy.types import GUID, ORA_JSONB, DateTimeUTC
+from alembic import op
+from sqlalchemy import Text # noqa: F401
+
+__all__ = ["downgrade", "upgrade", "schema_upgrades", "schema_downgrades", "data_upgrades", "data_downgrades"]
+
+sa.GUID = GUID
+sa.DateTimeUTC = DateTimeUTC
+sa.ORA_JSONB = ORA_JSONB
+
+# revision identifiers, used by Alembic.
+revision = "f32ee278015d"
+down_revision = "73a26ceab2c4"
+branch_labels = None
+depends_on = None
+
+
+def upgrade() -> None:
+ with warnings.catch_warnings():
+ warnings.filterwarnings("ignore", category=UserWarning)
+ with op.get_context().autocommit_block():
+ schema_upgrades()
+ data_upgrades()
+
+
+def downgrade() -> None:
+ with warnings.catch_warnings():
+ warnings.filterwarnings("ignore", category=UserWarning)
+ with op.get_context().autocommit_block():
+ data_downgrades()
+ schema_downgrades()
+
+
+def schema_upgrades() -> None:
+ """schema upgrade migrations go here."""
+ from sqlalchemy import inspect
+
+ inspector = inspect(op.get_bind())
+ if "forum_config" in inspector.get_table_names():
+ op.drop_table("forum_config")
+ if "github_config" in inspector.get_table_names():
+ op.drop_table("github_config")
+ if "so_tags" in inspector.get_table_names():
+ op.drop_table("so_tags")
+
+ # Recreate sub-tables with original schema
+ op.create_table(
+ "forum_config",
+ sa.Column("id", sa.BigInteger(), autoincrement=True, nullable=False),
+ sa.Column("guild_id", sa.BigInteger(), nullable=False),
+ sa.ForeignKeyConstraint(["guild_id"], ["guild.guild_id"], ondelete="CASCADE"),
+ sa.PrimaryKeyConstraint("id"),
+ )
+
+ op.create_table(
+ "github_config",
+ sa.Column("id", sa.BigInteger(), autoincrement=True, nullable=False),
+ sa.Column("guild_id", sa.BigInteger(), nullable=False),
+ sa.ForeignKeyConstraint(["guild_id"], ["guild.guild_id"], ondelete="CASCADE"),
+ sa.PrimaryKeyConstraint("id"),
+ )
+
+ op.create_table(
+ "so_tags_config",
+ sa.Column("id", sa.BigInteger(), autoincrement=True, nullable=False),
+ sa.Column("guild_id", sa.BigInteger(), nullable=False),
+ sa.ForeignKeyConstraint(["guild_id"], ["guild.guild_id"], ondelete="CASCADE"),
+ sa.PrimaryKeyConstraint("id"),
+ )
+
+ # ### commands auto generated by Alembic - please adjust! ###
+ with op.batch_alter_table("forum_config", schema=None) as batch_op:
+ batch_op.add_column(sa.Column("help_forum", sa.Boolean(), nullable=False))
+ batch_op.add_column(sa.Column("help_forum_category", sa.String(), nullable=True))
+ batch_op.add_column(sa.Column("help_thread_auto_close", sa.Boolean(), nullable=False))
+ batch_op.add_column(sa.Column("help_thread_auto_close_days", sa.Integer(), nullable=True))
+ batch_op.add_column(sa.Column("help_thread_notify", sa.Boolean(), nullable=False))
+ batch_op.add_column(sa.Column("help_thread_notify_roles", sa.String(), nullable=True))
+ batch_op.add_column(sa.Column("help_thread_notify_days", sa.Integer(), nullable=True))
+ batch_op.add_column(sa.Column("showcase_forum", sa.Boolean(), nullable=False))
+ batch_op.add_column(sa.Column("showcase_forum_category", sa.String(), nullable=True))
+ batch_op.add_column(sa.Column("showcase_thread_auto_close", sa.Boolean(), nullable=False))
+ batch_op.add_column(sa.Column("showcase_thread_auto_close_days", sa.Integer(), nullable=True))
+ batch_op.add_column(sa.Column("sa_orm_sentinel", sa.Integer(), nullable=True))
+ batch_op.add_column(sa.Column("created_at", sa.DateTimeUTC(timezone=True), nullable=False))
+ batch_op.add_column(sa.Column("updated_at", sa.DateTimeUTC(timezone=True), nullable=False))
+ batch_op.drop_constraint("fk_forum_config_guild_id_guild", type_="foreignkey")
+ batch_op.create_foreign_key(
+ batch_op.f("fk_forum_config_guild_id_guild"), "guild", ["guild_id"], ["guild_id"], ondelete="cascade"
+ )
+ batch_op.create_table_comment("Forum configuration for a guild.", existing_comment=None)
+
+ with op.batch_alter_table("github_config", schema=None) as batch_op:
+ batch_op.add_column(sa.Column("discussion_sync", sa.Boolean(), nullable=False))
+ batch_op.add_column(sa.Column("github_organization", sa.String(), nullable=True))
+ batch_op.add_column(sa.Column("github_repository", sa.String(), nullable=True))
+ batch_op.add_column(sa.Column("sa_orm_sentinel", sa.Integer(), nullable=True))
+ batch_op.add_column(sa.Column("created_at", sa.DateTimeUTC(timezone=True), nullable=False))
+ batch_op.add_column(sa.Column("updated_at", sa.DateTimeUTC(timezone=True), nullable=False))
+ batch_op.drop_constraint("fk_github_config_guild_id_guild", type_="foreignkey")
+ batch_op.create_foreign_key(
+ batch_op.f("fk_github_config_guild_id_guild"), "guild", ["guild_id"], ["guild_id"], ondelete="cascade"
+ )
+ batch_op.create_table_comment("GitHub configuration for a guild.", existing_comment=None)
+
+ with op.batch_alter_table("so_tags_config", schema=None) as batch_op:
+ batch_op.add_column(sa.Column("tag_name", sa.String(length=50), nullable=False))
+ batch_op.add_column(sa.Column("sa_orm_sentinel", sa.Integer(), nullable=True))
+ batch_op.add_column(sa.Column("created_at", sa.DateTimeUTC(timezone=True), nullable=False))
+ batch_op.add_column(sa.Column("updated_at", sa.DateTimeUTC(timezone=True), nullable=False))
+ batch_op.create_unique_constraint(batch_op.f("uq_so_tags_config_guild_id"), ["guild_id", "tag_name"])
+ batch_op.drop_constraint("fk_so_tags_config_guild_id_guild", type_="foreignkey")
+ batch_op.create_foreign_key(
+ batch_op.f("fk_so_tags_config_guild_id_guild"), "guild", ["guild_id"], ["guild_id"], ondelete="cascade"
+ )
+ batch_op.create_table_comment("Configuration for a Discord guild's Stack Overflow tags.", existing_comment=None)
+
+ # ### end Alembic commands ###
+
+
+def schema_downgrades() -> None:
+ """if we have to downgrade we're fucked."""
+ from sqlalchemy import inspect
+
+ inspector = inspect(op.get_bind())
+ if "forum_config" in inspector.get_table_names():
+ op.drop_table("forum_config")
+ if "github_config" in inspector.get_table_names():
+ op.drop_table("github_config")
+ if "so_tags_config" in inspector.get_table_names():
+ op.drop_table("so_tags_config")
+
+ # Recreate sub-tables with original schema
+ op.create_table(
+ "forum_config",
+ sa.Column("id", sa.UUID(), nullable=False),
+ sa.Column("guild_id", sa.UUID(), nullable=False),
+ sa.ForeignKeyConstraint(["guild_id"], ["guild.id"], ondelete="CASCADE"),
+ sa.PrimaryKeyConstraint("id"),
+ )
+
+ op.create_table(
+ "github_config",
+ sa.Column("id", sa.UUID(), nullable=False),
+ sa.Column("guild_id", sa.UUID(), nullable=False),
+ sa.ForeignKeyConstraint(["guild_id"], ["guild.id"], ondelete="CASCADE"),
+ sa.PrimaryKeyConstraint("id"),
+ )
+
+ op.create_table(
+ "so_tags",
+ sa.Column("id", sa.UUID(), nullable=False),
+ sa.Column("guild_id", sa.UUID(), nullable=False),
+ sa.ForeignKeyConstraint(["guild_id"], ["guild.id"], ondelete="CASCADE"),
+ sa.PrimaryKeyConstraint("id"),
+ )
+
+
+def data_upgrades() -> None:
+ """Add any optional data upgrade migrations here!"""
+
+
+def data_downgrades() -> None:
+ """Add any optional data downgrade migrations here!"""
From bd8ce861ab0f79e0690ff43652284e84d8397e24 Mon Sep 17 00:00:00 2001
From: Jacob Coffee
Date: Mon, 11 Mar 2024 02:17:07 -0500
Subject: [PATCH 25/29] fix: remove blanket check for delete button view
---
src/byte/views/abstract_views.py | 9 ++++++---
src/byte/views/forums.py | 2 +-
2 files changed, 7 insertions(+), 4 deletions(-)
diff --git a/src/byte/views/abstract_views.py b/src/byte/views/abstract_views.py
index 333ae7a..f25375a 100644
--- a/src/byte/views/abstract_views.py
+++ b/src/byte/views/abstract_views.py
@@ -41,8 +41,11 @@ def __init__(
self.original_embed = original_embed
self.minified_embed = minified_embed
- async def interaction_check(self, interaction: Interaction) -> bool:
- """Check if the user is the author or a guild admin.
+ async def delete_interaction_check(self, interaction: Interaction) -> bool:
+ """Check if the user is the author or a guild admin
+
+ .. note:: Only checks for the ``delete`` button, as we want to expose
+ the ``learn more`` button to anyone.
Args:
interaction: Interaction object.
@@ -63,7 +66,7 @@ async def delete_button_callback(self, interaction: Interaction) -> None:
Args:
interaction: Interaction object.
"""
- if await self.interaction_check(interaction):
+ if await self.delete_interaction_check(interaction):
await interaction.message.delete()
async def learn_more_button_callback(self, interaction: Interaction) -> None:
diff --git a/src/byte/views/forums.py b/src/byte/views/forums.py
index 6d4218b..59010ca 100644
--- a/src/byte/views/forums.py
+++ b/src/byte/views/forums.py
@@ -45,7 +45,7 @@ async def setup(self) -> None:
except Exception:
logger.exception("failed to setup view for guild %s", self.guild_id)
- async def interaction_check(self, interaction: Interaction) -> bool:
+ async def delete_interaction_check(self, interaction: Interaction) -> bool:
"""Check if the user is the author or an admin.
Args:
From 653fba1d2e78096cb454f18a1f22fd5c709ef283 Mon Sep 17 00:00:00 2001
From: Jacob Coffee
Date: Mon, 11 Mar 2024 02:17:58 -0500
Subject: [PATCH 26/29] fix: allow dropdown for config key
---
src/server/domain/guilds/controllers.py | 2 +-
src/server/domain/guilds/schemas.py | 17 ++++++++++++++++-
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/src/server/domain/guilds/controllers.py b/src/server/domain/guilds/controllers.py
index 55af847..3c0b87f 100644
--- a/src/server/domain/guilds/controllers.py
+++ b/src/server/domain/guilds/controllers.py
@@ -119,7 +119,7 @@ async def update_guild(
title="Guild ID",
description="The guild ID.",
),
- setting: UpdateableGuildSetting = Parameter(
+ setting: UpdateableGuildSetting.as_enum() = Parameter(
title="Setting",
description="The setting to update.",
),
diff --git a/src/server/domain/guilds/schemas.py b/src/server/domain/guilds/schemas.py
index 068f24b..f76c37b 100644
--- a/src/server/domain/guilds/schemas.py
+++ b/src/server/domain/guilds/schemas.py
@@ -2,6 +2,8 @@
from __future__ import annotations
+from enum import StrEnum, Enum
+from typing import Type
from uuid import UUID # noqa: TCH003
from pydantic import Field
@@ -19,6 +21,8 @@
"UpdateableGuildSetting",
)
+from server.lib.serialization import convert_camel_to_snake_case
+
class GitHubConfigSchema(CamelizedBaseModel):
"""Schema for validating GitHub configuration."""
@@ -138,7 +142,7 @@ class UpdateableGuildSetting(CamelizedBaseModel):
)
"""Allowed Users Config Settings"""
- user_id: int = Field(title="User ID", description="The user or role ID to allow.")
+ allowed_user_id: int = Field(title="User ID", description="The user or role ID to allow.")
"""Forum Config Settings"""
"""Help Forum"""
@@ -172,3 +176,14 @@ class UpdateableGuildSetting(CamelizedBaseModel):
showcase_thread_auto_close_days: int = Field(
title="Showcase Thread Auto Close Days", description="The days to auto close showcase threads after inactivity."
)
+
+ @classmethod
+ def as_enum(cls) -> type[Enum]:
+ """Helper to dynamically create an enum from the class fields."""
+ return StrEnum(
+ cls.__name__,
+ {
+ convert_camel_to_snake_case(field.alias): convert_camel_to_snake_case(field.alias)
+ for field in cls.__fields__.values()
+ },
+ )
From acc4bf1cba9f040e2e965961ac060a97ce899dd7 Mon Sep 17 00:00:00 2001
From: Jacob Coffee
Date: Fri, 10 May 2024 20:04:43 -0500
Subject: [PATCH 27/29] chore: updates
---
.pdm-python | 2 +-
.pre-commit-config.yaml | 2 +-
.tool-versions | 2 +-
pdm.lock | 817 ++++++++++++++--------------------------
pyproject.toml | 11 +-
5 files changed, 297 insertions(+), 537 deletions(-)
diff --git a/.pdm-python b/.pdm-python
index e2e784d..15f5b02 100644
--- a/.pdm-python
+++ b/.pdm-python
@@ -1 +1 @@
-.venv/bin/python
+/Users/jcoffee5/git/public/JacobCoffee/byte/.venv/bin/python
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 8cf5cb9..0526059 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -1,5 +1,5 @@
default_language_version:
- python: "3.11"
+ python: "3.12"
default_install_hook_types: [commit-msg, pre-commit]
repos:
- repo: https://github.com/compilerla/conventional-pre-commit
diff --git a/.tool-versions b/.tool-versions
index 504f142..f732415 100644
--- a/.tool-versions
+++ b/.tool-versions
@@ -1 +1 @@
-python 3.11
+python 3.12
diff --git a/pdm.lock b/pdm.lock
index 56399ca..7fce002 100644
--- a/pdm.lock
+++ b/pdm.lock
@@ -5,24 +5,25 @@
groups = ["default", "docs", "lint", "test"]
strategy = ["cross_platform", "inherit_metadata"]
lock_version = "4.4.1"
-content_hash = "sha256:32b6a491dea5963afb177ae0726e8012dd21ebdd2067d7e68ed82dfa1a32df94"
+content_hash = "sha256:56e9925849af7995247ba4070b4957ac69a8ed1f7c21b7112a671945ec5e0f54"
[[package]]
name = "accessible-pygments"
-version = "0.0.4"
+version = "0.0.5"
+requires_python = ">=3.9"
summary = "A collection of accessible pygments styles"
groups = ["docs"]
dependencies = [
"pygments>=1.5",
]
files = [
- {file = "accessible-pygments-0.0.4.tar.gz", hash = "sha256:e7b57a9b15958e9601c7e9eb07a440c813283545a20973f2574a5f453d0e953e"},
- {file = "accessible_pygments-0.0.4-py2.py3-none-any.whl", hash = "sha256:416c6d8c1ea1c5ad8701903a20fcedf953c6e720d64f33dc47bfb2d3f2fa4e8d"},
+ {file = "accessible_pygments-0.0.5-py3-none-any.whl", hash = "sha256:88ae3211e68a1d0b011504b2ffc1691feafce124b845bd072ab6f9f66f34d4b7"},
+ {file = "accessible_pygments-0.0.5.tar.gz", hash = "sha256:40918d3e6a2b619ad424cb91e556bd3bd8865443d9f22f1dcdf79e33c8046872"},
]
[[package]]
name = "advanced-alchemy"
-version = "0.7.4"
+version = "0.8.4"
requires_python = ">=3.8"
summary = "Ready-to-go SQLAlchemy concoctions."
groups = ["default"]
@@ -33,13 +34,13 @@ dependencies = [
"typing-extensions>=4.0.0",
]
files = [
- {file = "advanced_alchemy-0.7.4-py3-none-any.whl", hash = "sha256:52502d1131963dfcdca52c0edd6935e1c21ca3b5612677769ccf48f214383053"},
- {file = "advanced_alchemy-0.7.4.tar.gz", hash = "sha256:d4097fc337d6c971fc673695fdc3ff5f0d69282c7fea3f4754ef7c345051c4c3"},
+ {file = "advanced_alchemy-0.8.4-py3-none-any.whl", hash = "sha256:0ad4e2e33cfa6f8641ea7e9df50c8dbb18890000080b74d85305ba8821c2ce50"},
+ {file = "advanced_alchemy-0.8.4.tar.gz", hash = "sha256:6436ebad0e0b92ef5093bf425961f5469020035c65953ff7f619aef24a08fc71"},
]
[[package]]
name = "aiohttp"
-version = "3.9.3"
+version = "3.9.5"
requires_python = ">=3.8"
summary = "Async http client/server framework (asyncio)"
groups = ["default"]
@@ -51,37 +52,22 @@ dependencies = [
"yarl<2.0,>=1.0",
]
files = [
- {file = "aiohttp-3.9.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:6b88f9386ff1ad91ace19d2a1c0225896e28815ee09fc6a8932fded8cda97c3d"},
- {file = "aiohttp-3.9.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c46956ed82961e31557b6857a5ca153c67e5476972e5f7190015018760938da2"},
- {file = "aiohttp-3.9.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:07b837ef0d2f252f96009e9b8435ec1fef68ef8b1461933253d318748ec1acdc"},
- {file = "aiohttp-3.9.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dad46e6f620574b3b4801c68255492e0159d1712271cc99d8bdf35f2043ec266"},
- {file = "aiohttp-3.9.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5ed3e046ea7b14938112ccd53d91c1539af3e6679b222f9469981e3dac7ba1ce"},
- {file = "aiohttp-3.9.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:039df344b45ae0b34ac885ab5b53940b174530d4dd8a14ed8b0e2155b9dddccb"},
- {file = "aiohttp-3.9.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7943c414d3a8d9235f5f15c22ace69787c140c80b718dcd57caaade95f7cd93b"},
- {file = "aiohttp-3.9.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:84871a243359bb42c12728f04d181a389718710129b36b6aad0fc4655a7647d4"},
- {file = "aiohttp-3.9.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:5eafe2c065df5401ba06821b9a054d9cb2848867f3c59801b5d07a0be3a380ae"},
- {file = "aiohttp-3.9.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:9d3c9b50f19704552f23b4eaea1fc082fdd82c63429a6506446cbd8737823da3"},
- {file = "aiohttp-3.9.3-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:f033d80bc6283092613882dfe40419c6a6a1527e04fc69350e87a9df02bbc283"},
- {file = "aiohttp-3.9.3-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:2c895a656dd7e061b2fd6bb77d971cc38f2afc277229ce7dd3552de8313a483e"},
- {file = "aiohttp-3.9.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:1f5a71d25cd8106eab05f8704cd9167b6e5187bcdf8f090a66c6d88b634802b4"},
- {file = "aiohttp-3.9.3-cp311-cp311-win32.whl", hash = "sha256:50fca156d718f8ced687a373f9e140c1bb765ca16e3d6f4fe116e3df7c05b2c5"},
- {file = "aiohttp-3.9.3-cp311-cp311-win_amd64.whl", hash = "sha256:5fe9ce6c09668063b8447f85d43b8d1c4e5d3d7e92c63173e6180b2ac5d46dd8"},
- {file = "aiohttp-3.9.3-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:38a19bc3b686ad55804ae931012f78f7a534cce165d089a2059f658f6c91fa60"},
- {file = "aiohttp-3.9.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:770d015888c2a598b377bd2f663adfd947d78c0124cfe7b959e1ef39f5b13869"},
- {file = "aiohttp-3.9.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ee43080e75fc92bf36219926c8e6de497f9b247301bbf88c5c7593d931426679"},
- {file = "aiohttp-3.9.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:52df73f14ed99cee84865b95a3d9e044f226320a87af208f068ecc33e0c35b96"},
- {file = "aiohttp-3.9.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dc9b311743a78043b26ffaeeb9715dc360335e5517832f5a8e339f8a43581e4d"},
- {file = "aiohttp-3.9.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b955ed993491f1a5da7f92e98d5dad3c1e14dc175f74517c4e610b1f2456fb11"},
- {file = "aiohttp-3.9.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:504b6981675ace64c28bf4a05a508af5cde526e36492c98916127f5a02354d53"},
- {file = "aiohttp-3.9.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a6fe5571784af92b6bc2fda8d1925cccdf24642d49546d3144948a6a1ed58ca5"},
- {file = "aiohttp-3.9.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:ba39e9c8627edc56544c8628cc180d88605df3892beeb2b94c9bc857774848ca"},
- {file = "aiohttp-3.9.3-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:e5e46b578c0e9db71d04c4b506a2121c0cb371dd89af17a0586ff6769d4c58c1"},
- {file = "aiohttp-3.9.3-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:938a9653e1e0c592053f815f7028e41a3062e902095e5a7dc84617c87267ebd5"},
- {file = "aiohttp-3.9.3-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:c3452ea726c76e92f3b9fae4b34a151981a9ec0a4847a627c43d71a15ac32aa6"},
- {file = "aiohttp-3.9.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:ff30218887e62209942f91ac1be902cc80cddb86bf00fbc6783b7a43b2bea26f"},
- {file = "aiohttp-3.9.3-cp312-cp312-win32.whl", hash = "sha256:38f307b41e0bea3294a9a2a87833191e4bcf89bb0365e83a8be3a58b31fb7f38"},
- {file = "aiohttp-3.9.3-cp312-cp312-win_amd64.whl", hash = "sha256:b791a3143681a520c0a17e26ae7465f1b6f99461a28019d1a2f425236e6eedb5"},
- {file = "aiohttp-3.9.3.tar.gz", hash = "sha256:90842933e5d1ff760fae6caca4b2b3edba53ba8f4b71e95dacf2818a2aca06f7"},
+ {file = "aiohttp-3.9.5-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:c7a4b7a6cf5b6eb11e109a9755fd4fda7d57395f8c575e166d363b9fc3ec4678"},
+ {file = "aiohttp-3.9.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:0a158704edf0abcac8ac371fbb54044f3270bdbc93e254a82b6c82be1ef08f3c"},
+ {file = "aiohttp-3.9.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d153f652a687a8e95ad367a86a61e8d53d528b0530ef382ec5aaf533140ed00f"},
+ {file = "aiohttp-3.9.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:82a6a97d9771cb48ae16979c3a3a9a18b600a8505b1115cfe354dfb2054468b4"},
+ {file = "aiohttp-3.9.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:60cdbd56f4cad9f69c35eaac0fbbdf1f77b0ff9456cebd4902f3dd1cf096464c"},
+ {file = "aiohttp-3.9.5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8676e8fd73141ded15ea586de0b7cda1542960a7b9ad89b2b06428e97125d4fa"},
+ {file = "aiohttp-3.9.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:da00da442a0e31f1c69d26d224e1efd3a1ca5bcbf210978a2ca7426dfcae9f58"},
+ {file = "aiohttp-3.9.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:18f634d540dd099c262e9f887c8bbacc959847cfe5da7a0e2e1cf3f14dbf2daf"},
+ {file = "aiohttp-3.9.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:320e8618eda64e19d11bdb3bd04ccc0a816c17eaecb7e4945d01deee2a22f95f"},
+ {file = "aiohttp-3.9.5-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:2faa61a904b83142747fc6a6d7ad8fccff898c849123030f8e75d5d967fd4a81"},
+ {file = "aiohttp-3.9.5-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:8c64a6dc3fe5db7b1b4d2b5cb84c4f677768bdc340611eca673afb7cf416ef5a"},
+ {file = "aiohttp-3.9.5-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:393c7aba2b55559ef7ab791c94b44f7482a07bf7640d17b341b79081f5e5cd1a"},
+ {file = "aiohttp-3.9.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:c671dc117c2c21a1ca10c116cfcd6e3e44da7fcde37bf83b2be485ab377b25da"},
+ {file = "aiohttp-3.9.5-cp312-cp312-win32.whl", hash = "sha256:5a7ee16aab26e76add4afc45e8f8206c95d1d75540f1039b84a03c3b3800dd59"},
+ {file = "aiohttp-3.9.5-cp312-cp312-win_amd64.whl", hash = "sha256:5ca51eadbd67045396bc92a4345d1790b7301c14d1848feaac1d6a6c9289e888"},
+ {file = "aiohttp-3.9.5.tar.gz", hash = "sha256:edea7d15772ceeb29db4aff55e482d4bcfb6ae160ce144f2682de02f6d693551"},
]
[[package]]
@@ -141,7 +127,7 @@ name = "anyio"
version = "4.3.0"
requires_python = ">=3.8"
summary = "High level compatibility layer for multiple asynchronous event loop implementations"
-groups = ["default"]
+groups = ["default", "docs"]
dependencies = [
"idna>=2.8",
"sniffio>=1.1",
@@ -194,36 +180,13 @@ files = [
{file = "asgiref-3.7.2.tar.gz", hash = "sha256:9e0ce3aa93a819ba5b45120216b23878cf6e8525eb3848653452b4192b92afed"},
]
-[[package]]
-name = "async-timeout"
-version = "4.0.3"
-requires_python = ">=3.7"
-summary = "Timeout context manager for asyncio programs"
-groups = ["default"]
-marker = "python_version < \"3.12.0\""
-files = [
- {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]]
name = "asyncpg"
version = "0.29.0"
requires_python = ">=3.8.0"
summary = "An asyncio PostgreSQL driver"
groups = ["default"]
-dependencies = [
- "async-timeout>=4.0.3; python_version < \"3.12.0\"",
-]
files = [
- {file = "asyncpg-0.29.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d4900ee08e85af01adb207519bb4e14b1cae8fd21e0ccf80fac6aa60b6da37b4"},
- {file = "asyncpg-0.29.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a65c1dcd820d5aea7c7d82a3fdcb70e096f8f70d1a8bf93eb458e49bfad036ac"},
- {file = "asyncpg-0.29.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5b52e46f165585fd6af4863f268566668407c76b2c72d366bb8b522fa66f1870"},
- {file = "asyncpg-0.29.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dc600ee8ef3dd38b8d67421359779f8ccec30b463e7aec7ed481c8346decf99f"},
- {file = "asyncpg-0.29.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:039a261af4f38f949095e1e780bae84a25ffe3e370175193174eb08d3cecab23"},
- {file = "asyncpg-0.29.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:6feaf2d8f9138d190e5ec4390c1715c3e87b37715cd69b2c3dfca616134efd2b"},
- {file = "asyncpg-0.29.0-cp311-cp311-win32.whl", hash = "sha256:1e186427c88225ef730555f5fdda6c1812daa884064bfe6bc462fd3a71c4b675"},
- {file = "asyncpg-0.29.0-cp311-cp311-win_amd64.whl", hash = "sha256:cfe73ffae35f518cfd6e4e5f5abb2618ceb5ef02a2365ce64f132601000587d3"},
{file = "asyncpg-0.29.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:6011b0dc29886ab424dc042bf9eeb507670a3b40aece3439944006aafe023178"},
{file = "asyncpg-0.29.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b544ffc66b039d5ec5a7454667f855f7fec08e0dfaf5a5490dfafbb7abbd2cfb"},
{file = "asyncpg-0.29.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d84156d5fb530b06c493f9e7635aa18f518fa1d1395ef240d211cb563c4e2364"},
@@ -248,8 +211,8 @@ files = [
[[package]]
name = "autodoc-pydantic"
-version = "2.0.1"
-requires_python = ">=3.7.1,<4.0.0"
+version = "2.2.0"
+requires_python = "<4.0.0,>=3.8.1"
summary = "Seamlessly integrate pydantic models in your Sphinx documentation."
groups = ["docs"]
dependencies = [
@@ -258,8 +221,7 @@ dependencies = [
"pydantic<3.0.0,>=2.0",
]
files = [
- {file = "autodoc_pydantic-2.0.1-py3-none-any.whl", hash = "sha256:d3c302fdb6d37edb5b721f0f540252fa79cea7018bc1a9a85bf70f33a68b0ce4"},
- {file = "autodoc_pydantic-2.0.1.tar.gz", hash = "sha256:7a125a4ff18e4903e27be71e4ddb3269380860eacab4a584d6cc2e212fa96991"},
+ {file = "autodoc_pydantic-2.2.0-py3-none-any.whl", hash = "sha256:8c6a36fbf6ed2700ea9c6d21ea76ad541b621fbdf16b5a80ee04673548af4d95"},
]
[[package]]
@@ -278,13 +240,13 @@ files = [
[[package]]
name = "babel"
-version = "2.14.0"
-requires_python = ">=3.7"
+version = "2.15.0"
+requires_python = ">=3.8"
summary = "Internationalization utilities"
groups = ["docs"]
files = [
- {file = "Babel-2.14.0-py3-none-any.whl", hash = "sha256:efb1a25b7118e67ce3a259bed20545c29cb68be8ad2c784c83689981b7a57287"},
- {file = "Babel-2.14.0.tar.gz", hash = "sha256:6919867db036398ba21eb5c7a0f6b28ab8cbc3ae7a73a44ebe34ae74a4e7d363"},
+ {file = "Babel-2.15.0-py3-none-any.whl", hash = "sha256:08706bdad8d0a3413266ab61bd6c34d0c28d6e1e7badf40a2cebe67644e2e1fb"},
+ {file = "babel-2.15.0.tar.gz", hash = "sha256:8daf0e265d05768bc6c7a314cf1321e9a123afc328cc635c18622a2f30a04413"},
]
[[package]]
@@ -383,7 +345,7 @@ name = "cfgv"
version = "3.4.0"
requires_python = ">=3.8"
summary = "Validate configuration and produce human readable error messages."
-groups = ["default", "lint"]
+groups = ["lint"]
files = [
{file = "cfgv-3.4.0-py2.py3-none-any.whl", hash = "sha256:b7265b1f29fd3316bfcd2b330d63d024f2bfd8bcb8b0272f8e19a504856c48f9"},
{file = "cfgv-3.4.0.tar.gz", hash = "sha256:e52591d4c5f5dead8e0f673fb16db7949d2cfb3f7da4582893288f0ded8fe560"},
@@ -397,21 +359,6 @@ summary = "The Real First Universal Charset Detector. Open, modern and actively
groups = ["docs"]
files = [
{file = "charset-normalizer-3.3.2.tar.gz", hash = "sha256:f30c3cb33b24454a82faecaf01b19c18562b1e89558fb6c56de4d9118a032fd5"},
- {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"},
@@ -468,68 +415,48 @@ files = [
[[package]]
name = "coverage"
-version = "7.4.3"
+version = "7.5.1"
requires_python = ">=3.8"
summary = "Code coverage measurement for Python"
groups = ["test"]
files = [
- {file = "coverage-7.4.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:cbbe5e739d45a52f3200a771c6d2c7acf89eb2524890a4a3aa1a7fa0695d2a47"},
- {file = "coverage-7.4.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:489763b2d037b164846ebac0cbd368b8a4ca56385c4090807ff9fad817de4113"},
- {file = "coverage-7.4.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:451f433ad901b3bb00184d83fd83d135fb682d780b38af7944c9faeecb1e0bfe"},
- {file = "coverage-7.4.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fcc66e222cf4c719fe7722a403888b1f5e1682d1679bd780e2b26c18bb648cdc"},
- {file = "coverage-7.4.3-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b3ec74cfef2d985e145baae90d9b1b32f85e1741b04cd967aaf9cfa84c1334f3"},
- {file = "coverage-7.4.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:abbbd8093c5229c72d4c2926afaee0e6e3140de69d5dcd918b2921f2f0c8baba"},
- {file = "coverage-7.4.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:35eb581efdacf7b7422af677b92170da4ef34500467381e805944a3201df2079"},
- {file = "coverage-7.4.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:8249b1c7334be8f8c3abcaaa996e1e4927b0e5a23b65f5bf6cfe3180d8ca7840"},
- {file = "coverage-7.4.3-cp311-cp311-win32.whl", hash = "sha256:cf30900aa1ba595312ae41978b95e256e419d8a823af79ce670835409fc02ad3"},
- {file = "coverage-7.4.3-cp311-cp311-win_amd64.whl", hash = "sha256:18c7320695c949de11a351742ee001849912fd57e62a706d83dfc1581897fa2e"},
- {file = "coverage-7.4.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:b51bfc348925e92a9bd9b2e48dad13431b57011fd1038f08316e6bf1df107d10"},
- {file = "coverage-7.4.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d6cdecaedea1ea9e033d8adf6a0ab11107b49571bbb9737175444cea6eb72328"},
- {file = "coverage-7.4.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3b2eccb883368f9e972e216c7b4c7c06cabda925b5f06dde0650281cb7666a30"},
- {file = "coverage-7.4.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6c00cdc8fa4e50e1cc1f941a7f2e3e0f26cb2a1233c9696f26963ff58445bac7"},
- {file = "coverage-7.4.3-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b9a4a8dd3dcf4cbd3165737358e4d7dfbd9d59902ad11e3b15eebb6393b0446e"},
- {file = "coverage-7.4.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:062b0a75d9261e2f9c6d071753f7eef0fc9caf3a2c82d36d76667ba7b6470003"},
- {file = "coverage-7.4.3-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:ebe7c9e67a2d15fa97b77ea6571ce5e1e1f6b0db71d1d5e96f8d2bf134303c1d"},
- {file = "coverage-7.4.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:c0a120238dd71c68484f02562f6d446d736adcc6ca0993712289b102705a9a3a"},
- {file = "coverage-7.4.3-cp312-cp312-win32.whl", hash = "sha256:37389611ba54fd6d278fde86eb2c013c8e50232e38f5c68235d09d0a3f8aa352"},
- {file = "coverage-7.4.3-cp312-cp312-win_amd64.whl", hash = "sha256:d25b937a5d9ffa857d41be042b4238dd61db888533b53bc76dc082cb5a15e914"},
- {file = "coverage-7.4.3-pp38.pp39.pp310-none-any.whl", hash = "sha256:7cbde573904625509a3f37b6fecea974e363460b556a627c60dc2f47e2fffa51"},
- {file = "coverage-7.4.3.tar.gz", hash = "sha256:276f6077a5c61447a48d133ed13e759c09e62aff0dc84274a68dc18660104d52"},
+ {file = "coverage-7.5.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:b6cf3764c030e5338e7f61f95bd21147963cf6aa16e09d2f74f1fa52013c1206"},
+ {file = "coverage-7.5.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2ec92012fefebee89a6b9c79bc39051a6cb3891d562b9270ab10ecfdadbc0c34"},
+ {file = "coverage-7.5.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:16db7f26000a07efcf6aea00316f6ac57e7d9a96501e990a36f40c965ec7a95d"},
+ {file = "coverage-7.5.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:beccf7b8a10b09c4ae543582c1319c6df47d78fd732f854ac68d518ee1fb97fa"},
+ {file = "coverage-7.5.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8748731ad392d736cc9ccac03c9845b13bb07d020a33423fa5b3a36521ac6e4e"},
+ {file = "coverage-7.5.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:7352b9161b33fd0b643ccd1f21f3a3908daaddf414f1c6cb9d3a2fd618bf2572"},
+ {file = "coverage-7.5.1-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:7a588d39e0925f6a2bff87154752481273cdb1736270642aeb3635cb9b4cad07"},
+ {file = "coverage-7.5.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:68f962d9b72ce69ea8621f57551b2fa9c70509af757ee3b8105d4f51b92b41a7"},
+ {file = "coverage-7.5.1-cp312-cp312-win32.whl", hash = "sha256:f152cbf5b88aaeb836127d920dd0f5e7edff5a66f10c079157306c4343d86c19"},
+ {file = "coverage-7.5.1-cp312-cp312-win_amd64.whl", hash = "sha256:5a5740d1fb60ddf268a3811bcd353de34eb56dc24e8f52a7f05ee513b2d4f596"},
+ {file = "coverage-7.5.1-pp38.pp39.pp310-none-any.whl", hash = "sha256:6537e7c10cc47c595828b8a8be04c72144725c383c4702703ff4e42e44577312"},
+ {file = "coverage-7.5.1.tar.gz", hash = "sha256:54de9ef3a9da981f7af93eafde4ede199e0846cd819eb27c88e2b712aae9708c"},
]
[[package]]
name = "coverage"
-version = "7.4.3"
+version = "7.5.1"
extras = ["toml"]
requires_python = ">=3.8"
summary = "Code coverage measurement for Python"
groups = ["test"]
dependencies = [
- "coverage==7.4.3",
-]
-files = [
- {file = "coverage-7.4.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:cbbe5e739d45a52f3200a771c6d2c7acf89eb2524890a4a3aa1a7fa0695d2a47"},
- {file = "coverage-7.4.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:489763b2d037b164846ebac0cbd368b8a4ca56385c4090807ff9fad817de4113"},
- {file = "coverage-7.4.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:451f433ad901b3bb00184d83fd83d135fb682d780b38af7944c9faeecb1e0bfe"},
- {file = "coverage-7.4.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fcc66e222cf4c719fe7722a403888b1f5e1682d1679bd780e2b26c18bb648cdc"},
- {file = "coverage-7.4.3-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b3ec74cfef2d985e145baae90d9b1b32f85e1741b04cd967aaf9cfa84c1334f3"},
- {file = "coverage-7.4.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:abbbd8093c5229c72d4c2926afaee0e6e3140de69d5dcd918b2921f2f0c8baba"},
- {file = "coverage-7.4.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:35eb581efdacf7b7422af677b92170da4ef34500467381e805944a3201df2079"},
- {file = "coverage-7.4.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:8249b1c7334be8f8c3abcaaa996e1e4927b0e5a23b65f5bf6cfe3180d8ca7840"},
- {file = "coverage-7.4.3-cp311-cp311-win32.whl", hash = "sha256:cf30900aa1ba595312ae41978b95e256e419d8a823af79ce670835409fc02ad3"},
- {file = "coverage-7.4.3-cp311-cp311-win_amd64.whl", hash = "sha256:18c7320695c949de11a351742ee001849912fd57e62a706d83dfc1581897fa2e"},
- {file = "coverage-7.4.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:b51bfc348925e92a9bd9b2e48dad13431b57011fd1038f08316e6bf1df107d10"},
- {file = "coverage-7.4.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d6cdecaedea1ea9e033d8adf6a0ab11107b49571bbb9737175444cea6eb72328"},
- {file = "coverage-7.4.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3b2eccb883368f9e972e216c7b4c7c06cabda925b5f06dde0650281cb7666a30"},
- {file = "coverage-7.4.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6c00cdc8fa4e50e1cc1f941a7f2e3e0f26cb2a1233c9696f26963ff58445bac7"},
- {file = "coverage-7.4.3-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b9a4a8dd3dcf4cbd3165737358e4d7dfbd9d59902ad11e3b15eebb6393b0446e"},
- {file = "coverage-7.4.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:062b0a75d9261e2f9c6d071753f7eef0fc9caf3a2c82d36d76667ba7b6470003"},
- {file = "coverage-7.4.3-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:ebe7c9e67a2d15fa97b77ea6571ce5e1e1f6b0db71d1d5e96f8d2bf134303c1d"},
- {file = "coverage-7.4.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:c0a120238dd71c68484f02562f6d446d736adcc6ca0993712289b102705a9a3a"},
- {file = "coverage-7.4.3-cp312-cp312-win32.whl", hash = "sha256:37389611ba54fd6d278fde86eb2c013c8e50232e38f5c68235d09d0a3f8aa352"},
- {file = "coverage-7.4.3-cp312-cp312-win_amd64.whl", hash = "sha256:d25b937a5d9ffa857d41be042b4238dd61db888533b53bc76dc082cb5a15e914"},
- {file = "coverage-7.4.3-pp38.pp39.pp310-none-any.whl", hash = "sha256:7cbde573904625509a3f37b6fecea974e363460b556a627c60dc2f47e2fffa51"},
- {file = "coverage-7.4.3.tar.gz", hash = "sha256:276f6077a5c61447a48d133ed13e759c09e62aff0dc84274a68dc18660104d52"},
+ "coverage==7.5.1",
+]
+files = [
+ {file = "coverage-7.5.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:b6cf3764c030e5338e7f61f95bd21147963cf6aa16e09d2f74f1fa52013c1206"},
+ {file = "coverage-7.5.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2ec92012fefebee89a6b9c79bc39051a6cb3891d562b9270ab10ecfdadbc0c34"},
+ {file = "coverage-7.5.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:16db7f26000a07efcf6aea00316f6ac57e7d9a96501e990a36f40c965ec7a95d"},
+ {file = "coverage-7.5.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:beccf7b8a10b09c4ae543582c1319c6df47d78fd732f854ac68d518ee1fb97fa"},
+ {file = "coverage-7.5.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8748731ad392d736cc9ccac03c9845b13bb07d020a33423fa5b3a36521ac6e4e"},
+ {file = "coverage-7.5.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:7352b9161b33fd0b643ccd1f21f3a3908daaddf414f1c6cb9d3a2fd618bf2572"},
+ {file = "coverage-7.5.1-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:7a588d39e0925f6a2bff87154752481273cdb1736270642aeb3635cb9b4cad07"},
+ {file = "coverage-7.5.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:68f962d9b72ce69ea8621f57551b2fa9c70509af757ee3b8105d4f51b92b41a7"},
+ {file = "coverage-7.5.1-cp312-cp312-win32.whl", hash = "sha256:f152cbf5b88aaeb836127d920dd0f5e7edff5a66f10c079157306c4343d86c19"},
+ {file = "coverage-7.5.1-cp312-cp312-win_amd64.whl", hash = "sha256:5a5740d1fb60ddf268a3811bcd353de34eb56dc24e8f52a7f05ee513b2d4f596"},
+ {file = "coverage-7.5.1-pp38.pp39.pp310-none-any.whl", hash = "sha256:6537e7c10cc47c595828b8a8be04c72144725c383c4702703ff4e42e44577312"},
+ {file = "coverage-7.5.1.tar.gz", hash = "sha256:54de9ef3a9da981f7af93eafde4ede199e0846cd819eb27c88e2b712aae9708c"},
]
[[package]]
@@ -578,13 +505,13 @@ files = [
[[package]]
name = "cssutils"
-version = "2.9.0"
+version = "2.10.2"
requires_python = ">=3.8"
summary = "A CSS Cascading Style Sheets library for Python"
groups = ["docs"]
files = [
- {file = "cssutils-2.9.0-py3-none-any.whl", hash = "sha256:f8b013169e281c0c6083207366c5005f5dd4549055f7aba840384fb06a78745c"},
- {file = "cssutils-2.9.0.tar.gz", hash = "sha256:89477b3d17d790e97b9fb4def708767061055795aae6f7c82ae32e967c9be4cd"},
+ {file = "cssutils-2.10.2-py3-none-any.whl", hash = "sha256:4ad7d2f29270b22cf199f65a6b5e795f2c3130f3b9fb50c3d45e5054ef86e41a"},
+ {file = "cssutils-2.10.2.tar.gz", hash = "sha256:93cf92a350b1c123b17feff042e212f94d960975a3ed145743d84ebe8ccec7ab"},
]
[[package]]
@@ -634,7 +561,7 @@ files = [
name = "distlib"
version = "0.3.8"
summary = "Distribution utilities"
-groups = ["default", "lint"]
+groups = ["lint"]
files = [
{file = "distlib-0.3.8-py2.py3-none-any.whl", hash = "sha256:034db59a0b96f8ca18035f36290806a9a6e6bd9d1ff91e45a7f172eb17e51784"},
{file = "distlib-0.3.8.tar.gz", hash = "sha256:1530ea13e350031b6312d8580ddb6b27a104275a31106523b8f123787f494f64"},
@@ -642,20 +569,20 @@ files = [
[[package]]
name = "docutils"
-version = "0.20.1"
-requires_python = ">=3.7"
+version = "0.21.2"
+requires_python = ">=3.9"
summary = "Docutils -- Python Documentation Utilities"
groups = ["docs"]
files = [
- {file = "docutils-0.20.1-py3-none-any.whl", hash = "sha256:96f387a2c5562db4476f09f13bbab2192e764cac08ebbf3a34a95d9b1e4a59d6"},
- {file = "docutils-0.20.1.tar.gz", hash = "sha256:f08a4e276c3a1583a86dce3e34aba3fe04d02bba2dd51ed16106244e8a923e3b"},
+ {file = "docutils-0.21.2-py3-none-any.whl", hash = "sha256:dafca5b9e384f0e419294eb4d2ff9fa826435bf15f15b7bd45723e8ad76811b2"},
+ {file = "docutils-0.21.2.tar.gz", hash = "sha256:3a6b18732edf182daa3cd12775bbb338cf5691468f91eeeb109deff6ebfa986f"},
]
[[package]]
name = "domdf-python-tools"
version = "3.8.0.post2"
requires_python = ">=3.6"
-summary = "Helpful functions for Python‚ÄÇüêç‚ÄÇüõ†Ô∏è"
+summary = "Helpful functions for Python 🐍 🛠️"
groups = ["docs"]
dependencies = [
"natsort>=7.0.1",
@@ -691,7 +618,7 @@ files = [
[[package]]
name = "faker"
-version = "24.1.0"
+version = "25.1.0"
requires_python = ">=3.8"
summary = "Faker is a Python package that generates fake data for you."
groups = ["default"]
@@ -699,8 +626,8 @@ dependencies = [
"python-dateutil>=2.4",
]
files = [
- {file = "Faker-24.1.0-py3-none-any.whl", hash = "sha256:89ae0932f4f269754790569828859eaa0ae2ce73d1f3eb1f30ae7c20d4daf5ce"},
- {file = "Faker-24.1.0.tar.gz", hash = "sha256:4fb0c16c71ad35d278a5fa7a4106a5c26c2b2b5c5efc47c1d67635db90b6071e"},
+ {file = "Faker-25.1.0-py3-none-any.whl", hash = "sha256:24e28dce0b89683bb9e017e042b971c8c4909cff551b6d46f1e207674c7c2526"},
+ {file = "Faker-25.1.0.tar.gz", hash = "sha256:2107618cf306bb188dcfea3e5cfd94aa92d65c7293a2437c1e96a99c83274755"},
]
[[package]]
@@ -730,13 +657,13 @@ files = [
[[package]]
name = "filelock"
-version = "3.13.1"
+version = "3.14.0"
requires_python = ">=3.8"
summary = "A platform independent file lock."
-groups = ["default", "docs", "lint"]
+groups = ["docs", "lint"]
files = [
- {file = "filelock-3.13.1-py3-none-any.whl", hash = "sha256:57dbda9b35157b05fb3e58ee91448612eb674172fab98ee235ccb0b5bee19a1c"},
- {file = "filelock-3.13.1.tar.gz", hash = "sha256:521f5f56c50f8426f5e03ad3b281b490a87ef15bc6c526f168290f0c7148d44e"},
+ {file = "filelock-3.14.0-py3-none-any.whl", hash = "sha256:43339835842f110ca7ae60f1e1c160714c5a6afd15a2873419ab185334975c0f"},
+ {file = "filelock-3.14.0.tar.gz", hash = "sha256:6ea72da3be9b8c82afd3edcf99f2fffbb5076335a5ae4d03248bb5b6c3eae78a"},
]
[[package]]
@@ -746,21 +673,6 @@ requires_python = ">=3.8"
summary = "A list-like structure which implements collections.abc.MutableSequence"
groups = ["default"]
files = [
- {file = "frozenlist-1.4.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:a0cb6f11204443f27a1628b0e460f37fb30f624be6051d490fa7d7e26d4af3d0"},
- {file = "frozenlist-1.4.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b46c8ae3a8f1f41a0d2ef350c0b6e65822d80772fe46b653ab6b6274f61d4a49"},
- {file = "frozenlist-1.4.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:fde5bd59ab5357e3853313127f4d3565fc7dad314a74d7b5d43c22c6a5ed2ced"},
- {file = "frozenlist-1.4.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:722e1124aec435320ae01ee3ac7bec11a5d47f25d0ed6328f2273d287bc3abb0"},
- {file = "frozenlist-1.4.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2471c201b70d58a0f0c1f91261542a03d9a5e088ed3dc6c160d614c01649c106"},
- {file = "frozenlist-1.4.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c757a9dd70d72b076d6f68efdbb9bc943665ae954dad2801b874c8c69e185068"},
- {file = "frozenlist-1.4.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f146e0911cb2f1da549fc58fc7bcd2b836a44b79ef871980d605ec392ff6b0d2"},
- {file = "frozenlist-1.4.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4f9c515e7914626b2a2e1e311794b4c35720a0be87af52b79ff8e1429fc25f19"},
- {file = "frozenlist-1.4.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:c302220494f5c1ebeb0912ea782bcd5e2f8308037b3c7553fad0e48ebad6ad82"},
- {file = "frozenlist-1.4.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:442acde1e068288a4ba7acfe05f5f343e19fac87bfc96d89eb886b0363e977ec"},
- {file = "frozenlist-1.4.1-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:1b280e6507ea8a4fa0c0a7150b4e526a8d113989e28eaaef946cc77ffd7efc0a"},
- {file = "frozenlist-1.4.1-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:fe1a06da377e3a1062ae5fe0926e12b84eceb8a50b350ddca72dc85015873f74"},
- {file = "frozenlist-1.4.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:db9e724bebd621d9beca794f2a4ff1d26eed5965b004a97f1f1685a173b869c2"},
- {file = "frozenlist-1.4.1-cp311-cp311-win32.whl", hash = "sha256:e774d53b1a477a67838a904131c4b0eef6b3d8a651f8b138b04f748fccfefe17"},
- {file = "frozenlist-1.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:fb3c2db03683b5767dedb5769b8a40ebb47d6f7f45b1b3e3b4b51ec8ad9d9825"},
{file = "frozenlist-1.4.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:1979bc0aeb89b33b588c51c54ab0161791149f2461ea7c7c946d95d5f93b56ae"},
{file = "frozenlist-1.4.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:cc7b01b3754ea68a62bd77ce6020afaffb44a590c2289089289363472d13aedb"},
{file = "frozenlist-1.4.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c9c92be9fd329ac801cc420e08452b70e7aeab94ea4233a4804f0915c14eba9b"},
@@ -782,35 +694,35 @@ files = [
[[package]]
name = "githubkit"
-version = "0.11.2"
-requires_python = ">=3.8,<4.0"
+version = "0.11.4"
+requires_python = "<4.0,>=3.8"
summary = "GitHub SDK for Python"
groups = ["default"]
dependencies = [
- "hishel<=0.0.24,>=0.0.21",
+ "hishel<=0.0.26,>=0.0.21",
"httpx<1.0.0,>=0.23.0",
"pydantic!=2.5.0,!=2.5.1,<3.0.0,>=1.9.1",
"typing-extensions<5.0.0,>=4.3.0",
]
files = [
- {file = "githubkit-0.11.2-py3-none-any.whl", hash = "sha256:d6776c667e37e0a120c003fa0a4c4c9a03c99a87a8a1767d3b67a87e09567933"},
- {file = "githubkit-0.11.2.tar.gz", hash = "sha256:2192cd30f32424d5ac8b104f3fc601c69ff1d4f63e2934eff3873953afca961b"},
+ {file = "githubkit-0.11.4-py3-none-any.whl", hash = "sha256:281af76e9ec24a1f3dc1c99ed4e50785898220d47f84acb2f87be8d7a572769a"},
+ {file = "githubkit-0.11.4.tar.gz", hash = "sha256:e629d833f98157cb4b1c14b69fdb54f7f960fb0da6906f1fa30fca14c347c0d4"},
]
[[package]]
name = "githubkit"
-version = "0.11.2"
+version = "0.11.4"
extras = ["auth-app"]
-requires_python = ">=3.8,<4.0"
+requires_python = "<4.0,>=3.8"
summary = "GitHub SDK for Python"
groups = ["default"]
dependencies = [
"PyJWT[crypto]<3.0.0,>=2.4.0",
- "githubkit==0.11.2",
+ "githubkit==0.11.4",
]
files = [
- {file = "githubkit-0.11.2-py3-none-any.whl", hash = "sha256:d6776c667e37e0a120c003fa0a4c4c9a03c99a87a8a1767d3b67a87e09567933"},
- {file = "githubkit-0.11.2.tar.gz", hash = "sha256:2192cd30f32424d5ac8b104f3fc601c69ff1d4f63e2934eff3873953afca961b"},
+ {file = "githubkit-0.11.4-py3-none-any.whl", hash = "sha256:281af76e9ec24a1f3dc1c99ed4e50785898220d47f84acb2f87be8d7a572769a"},
+ {file = "githubkit-0.11.4.tar.gz", hash = "sha256:e629d833f98157cb4b1c14b69fdb54f7f960fb0da6906f1fa30fca14c347c0d4"},
]
[[package]]
@@ -821,15 +733,6 @@ summary = "Lightweight in-process concurrent programming"
groups = ["default", "docs"]
marker = "platform_machine == \"win32\" or platform_machine == \"WIN32\" or platform_machine == \"AMD64\" or platform_machine == \"amd64\" or platform_machine == \"x86_64\" or platform_machine == \"ppc64le\" or platform_machine == \"aarch64\" or sys_platform == \"darwin\""
files = [
- {file = "greenlet-3.0.3-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:b1b5667cced97081bf57b8fa1d6bfca67814b0afd38208d52538316e9422fc61"},
- {file = "greenlet-3.0.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:52f59dd9c96ad2fc0d5724107444f76eb20aaccb675bf825df6435acb7703559"},
- {file = "greenlet-3.0.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:afaff6cf5200befd5cec055b07d1c0a5a06c040fe5ad148abcd11ba6ab9b114e"},
- {file = "greenlet-3.0.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fe754d231288e1e64323cfad462fcee8f0288654c10bdf4f603a39ed923bef33"},
- {file = "greenlet-3.0.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2797aa5aedac23af156bbb5a6aa2cd3427ada2972c828244eb7d1b9255846379"},
- {file = "greenlet-3.0.3-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b7f009caad047246ed379e1c4dbcb8b020f0a390667ea74d2387be2998f58a22"},
- {file = "greenlet-3.0.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:c5e1536de2aad7bf62e27baf79225d0d64360d4168cf2e6becb91baf1ed074f3"},
- {file = "greenlet-3.0.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:894393ce10ceac937e56ec00bb71c4c2f8209ad516e96033e4b3b1de270e200d"},
- {file = "greenlet-3.0.3-cp311-cp311-win_amd64.whl", hash = "sha256:1ea188d4f49089fc6fb283845ab18a2518d279c7cd9da1065d7a84e991748728"},
{file = "greenlet-3.0.3-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:70fb482fdf2c707765ab5f0b6655e9cfcf3780d8d87355a063547b41177599be"},
{file = "greenlet-3.0.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d4d1ac74f5c0c0524e4a24335350edad7e5f03b9532da7ea4d3c54d527784f2e"},
{file = "greenlet-3.0.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:149e94a2dd82d19838fe4b2259f1b6b9957d5ba1b25640d2380bea9c5df37676"},
@@ -847,7 +750,7 @@ name = "h11"
version = "0.14.0"
requires_python = ">=3.7"
summary = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1"
-groups = ["default"]
+groups = ["default", "docs"]
files = [
{file = "h11-0.14.0-py3-none-any.whl", hash = "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761"},
{file = "h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d"},
@@ -855,7 +758,7 @@ files = [
[[package]]
name = "hishel"
-version = "0.0.24"
+version = "0.0.26"
requires_python = ">=3.8"
summary = "Persistent cache implementation for httpx and httpcore"
groups = ["default"]
@@ -864,8 +767,8 @@ dependencies = [
"typing-extensions>=4.8.0",
]
files = [
- {file = "hishel-0.0.24-py3-none-any.whl", hash = "sha256:8b6e43481485e1938d78bd35c0bcb38646fe8f2e090fedb64b4dc1d6015ffe49"},
- {file = "hishel-0.0.24.tar.gz", hash = "sha256:4ac494c6bfedc431e480ab85d3435d4710230b2ad6092766b6ccf82b1d7e4152"},
+ {file = "hishel-0.0.26-py3-none-any.whl", hash = "sha256:63cd3fee495124e0ed3461b374c43eab3e9deb2f01ba72eafe36d7df5fcf8b46"},
+ {file = "hishel-0.0.26.tar.gz", hash = "sha256:f0ae2766214499cb0253a5ec7694f0d6e3835c9a35634356f8926fb7a1cf379e"},
]
[[package]]
@@ -885,7 +788,7 @@ files = [
[[package]]
name = "httpcore"
-version = "1.0.4"
+version = "1.0.5"
requires_python = ">=3.8"
summary = "A minimal low-level HTTP client."
groups = ["default"]
@@ -894,8 +797,8 @@ dependencies = [
"h11<0.15,>=0.13",
]
files = [
- {file = "httpcore-1.0.4-py3-none-any.whl", hash = "sha256:ac418c1db41bade2ad53ae2f3834a3a0f5ae76b56cf5aa497d2d033384fc7d73"},
- {file = "httpcore-1.0.4.tar.gz", hash = "sha256:cb2839ccfcba0d2d3c1131d3c3e26dfc327326fbe7a5dc0dbfe9f6c9151bb022"},
+ {file = "httpcore-1.0.5-py3-none-any.whl", hash = "sha256:421f18bac248b25d310f3cacd198d55b8e6125c107797b609ff9b7a6ba7991b5"},
+ {file = "httpcore-1.0.5.tar.gz", hash = "sha256:34a38e2f9291467ee3b44e89dd52615370e152954ba21721378a87b2960f7a61"},
]
[[package]]
@@ -942,7 +845,7 @@ files = [
[[package]]
name = "hypothesis"
-version = "6.99.2"
+version = "6.100.6"
requires_python = ">=3.8"
summary = "A library for property-based testing"
groups = ["test"]
@@ -951,30 +854,30 @@ dependencies = [
"sortedcontainers<3.0.0,>=2.1.0",
]
files = [
- {file = "hypothesis-6.99.2-py3-none-any.whl", hash = "sha256:f277f6ccb074f39d51c7f32ba5a0ff640dba9b71ef69ea1e1e09b6f7c25302f5"},
- {file = "hypothesis-6.99.2.tar.gz", hash = "sha256:24453b1a86151be83d26e81834e29022b3e3f0fc5d71275cc3d096649a13c53c"},
+ {file = "hypothesis-6.100.6-py3-none-any.whl", hash = "sha256:416d2c2b248df6fe71e2ae94b4b475cbaaced4c949929039e0484463dfc30644"},
+ {file = "hypothesis-6.100.6.tar.gz", hash = "sha256:726663fe65c793cd0c092b82ce737940f7da7fa1297a81da898c3317e5a19026"},
]
[[package]]
name = "identify"
-version = "2.5.35"
+version = "2.5.36"
requires_python = ">=3.8"
summary = "File identification library for Python"
-groups = ["default", "lint"]
+groups = ["lint"]
files = [
- {file = "identify-2.5.35-py2.py3-none-any.whl", hash = "sha256:c4de0081837b211594f8e877a6b4fad7ca32bbfc1a9307fdd61c28bfe923f13e"},
- {file = "identify-2.5.35.tar.gz", hash = "sha256:10a7ca245cfcd756a554a7288159f72ff105ad233c7c4b9c6f0f4d108f5f6791"},
+ {file = "identify-2.5.36-py2.py3-none-any.whl", hash = "sha256:37d93f380f4de590500d9dba7db359d0d3da95ffe7f9de1753faa159e71e7dfa"},
+ {file = "identify-2.5.36.tar.gz", hash = "sha256:e5e00f54165f9047fbebeb4a560f9acfb8af4c88232be60a488e9b68d122745d"},
]
[[package]]
name = "idna"
-version = "3.6"
+version = "3.7"
requires_python = ">=3.5"
summary = "Internationalized Domain Names in Applications (IDNA)"
groups = ["default", "docs"]
files = [
- {file = "idna-3.6-py3-none-any.whl", hash = "sha256:c05567e9c24a6b9faaa835c4821bad0590fbb9d5779e7caa6e1cc4978e7eb24f"},
- {file = "idna-3.6.tar.gz", hash = "sha256:9ecdbbd083b06798ae1e86adcbfe8ab1479cf864e4ee30fe4e46a003d12491ca"},
+ {file = "idna-3.7-py3-none-any.whl", hash = "sha256:82fee1fc78add43492d3a1898bfa6d8a904cc97d8427f683ed8e798d07761aa0"},
+ {file = "idna-3.7.tar.gz", hash = "sha256:028ff3aadf0609c1fd278d8ea3089299412a7a8b9bd005dd08b9f8285bcb5cfc"},
]
[[package]]
@@ -1015,7 +918,7 @@ files = [
[[package]]
name = "jinja2"
-version = "3.1.3"
+version = "3.1.4"
requires_python = ">=3.7"
summary = "A very fast and expressive template engine."
groups = ["default", "docs"]
@@ -1023,8 +926,8 @@ dependencies = [
"MarkupSafe>=2.0",
]
files = [
- {file = "Jinja2-3.1.3-py3-none-any.whl", hash = "sha256:7d6d50dd97d52cbc355597bd845fabfbac3f551e1f99619e39a35ce8c370b5fa"},
- {file = "Jinja2-3.1.3.tar.gz", hash = "sha256:ac8bd6544d4bb2c9792bf3a159e80bba8fda7f07e81bc3aed565432d5925ba90"},
+ {file = "jinja2-3.1.4-py3-none-any.whl", hash = "sha256:bc5dd2abb727a5319567b7a813e6a2e7318c39f4f487cfe6c89c6f9c7d25197d"},
+ {file = "jinja2-3.1.4.tar.gz", hash = "sha256:4a3aee7acbbe7303aede8e9648d13b8bf88a429282aa6122a993f0ac800cb369"},
]
[[package]]
@@ -1042,7 +945,7 @@ files = [
[[package]]
name = "litestar"
-version = "2.7.0"
+version = "2.8.3"
requires_python = "<4.0,>=3.8"
summary = "Litestar - A production-ready, highly performant, extensible ASGI API Framework"
groups = ["default"]
@@ -1059,13 +962,13 @@ dependencies = [
"typing-extensions",
]
files = [
- {file = "litestar-2.7.0-py3-none-any.whl", hash = "sha256:62eabe89c08a1a5b66063bf9d8ec7677368bf7d3593c0579fb3605dd61b486a3"},
- {file = "litestar-2.7.0.tar.gz", hash = "sha256:30f703b513d8c8a7f82e3b5cd583b071147f7e60b929650eeeeb00ff0ff65582"},
+ {file = "litestar-2.8.3-py3-none-any.whl", hash = "sha256:bef5e8592b1afba24306f9a5834d84cef89826b12f58a97d3099cf49e2f3767d"},
+ {file = "litestar-2.8.3.tar.gz", hash = "sha256:3764eef3885b331bfb15c478a2b9e2bc1980741ff58bd5512d599436f669549c"},
]
[[package]]
name = "litestar"
-version = "2.7.0"
+version = "2.8.3"
extras = ["jwt", "opentelemetry", "prometheus", "standard", "structlog"]
requires_python = "<4.0,>=3.8"
summary = "Litestar - A production-ready, highly performant, extensible ASGI API Framework"
@@ -1075,7 +978,7 @@ dependencies = [
"fast-query-parsers>=1.0.2",
"jinja2",
"jsbeautifier",
- "litestar==2.7.0",
+ "litestar==2.8.3",
"opentelemetry-instrumentation-asgi",
"prometheus-client",
"python-jose",
@@ -1084,27 +987,13 @@ dependencies = [
"uvloop>=0.18.0; sys_platform != \"win32\"",
]
files = [
- {file = "litestar-2.7.0-py3-none-any.whl", hash = "sha256:62eabe89c08a1a5b66063bf9d8ec7677368bf7d3593c0579fb3605dd61b486a3"},
- {file = "litestar-2.7.0.tar.gz", hash = "sha256:30f703b513d8c8a7f82e3b5cd583b071147f7e60b929650eeeeb00ff0ff65582"},
-]
-
-[[package]]
-name = "livereload"
-version = "2.6.3"
-summary = "Python LiveReload is an awesome tool for web developers"
-groups = ["docs"]
-dependencies = [
- "six",
- "tornado; python_version > \"2.7\"",
-]
-files = [
- {file = "livereload-2.6.3-py2.py3-none-any.whl", hash = "sha256:ad4ac6f53b2d62bb6ce1a5e6e96f1f00976a32348afedcb4b6d68df2a1d346e4"},
- {file = "livereload-2.6.3.tar.gz", hash = "sha256:776f2f865e59fde56490a56bcc6773b6917366bce0c267c60ee8aaf1a0959869"},
+ {file = "litestar-2.8.3-py3-none-any.whl", hash = "sha256:bef5e8592b1afba24306f9a5834d84cef89826b12f58a97d3099cf49e2f3767d"},
+ {file = "litestar-2.8.3.tar.gz", hash = "sha256:3764eef3885b331bfb15c478a2b9e2bc1980741ff58bd5512d599436f669549c"},
]
[[package]]
name = "mako"
-version = "1.3.2"
+version = "1.3.3"
requires_python = ">=3.8"
summary = "A super-fast templating language that borrows the best ideas from the existing templating languages."
groups = ["default"]
@@ -1112,8 +1001,8 @@ dependencies = [
"MarkupSafe>=0.9.2",
]
files = [
- {file = "Mako-1.3.2-py3-none-any.whl", hash = "sha256:32a99d70754dfce237019d17ffe4a282d2d3351b9c476e90d8a60e63f133b80c"},
- {file = "Mako-1.3.2.tar.gz", hash = "sha256:2a0c8ad7f6274271b3bb7467dd37cf9cc6dab4bc19cb69a4ef10669402de698e"},
+ {file = "Mako-1.3.3-py3-none-any.whl", hash = "sha256:5324b88089a8978bf76d1629774fcc2f1c07b82acdf00f4c5dd8ceadfffc4b40"},
+ {file = "Mako-1.3.3.tar.gz", hash = "sha256:e16c01d9ab9c11f7290eef1cfefc093fb5a45ee4a3da09e2fec2e4d1bae54e73"},
]
[[package]]
@@ -1137,16 +1026,6 @@ requires_python = ">=3.7"
summary = "Safely add untrusted strings to HTML/XML markup."
groups = ["default", "docs"]
files = [
- {file = "MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:629ddd2ca402ae6dbedfceeba9c46d5f7b2a61d9749597d4307f943ef198fc1f"},
- {file = "MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:5b7b716f97b52c5a14bffdf688f971b2d5ef4029127f1ad7a513973cfd818df2"},
- {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6ec585f69cec0aa07d945b20805be741395e28ac1627333b1c5b0105962ffced"},
- {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b91c037585eba9095565a3556f611e3cbfaa42ca1e865f7b8015fe5c7336d5a5"},
- {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7502934a33b54030eaf1194c21c692a534196063db72176b0c4028e140f8f32c"},
- {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:0e397ac966fdf721b2c528cf028494e86172b4feba51d65f81ffd65c63798f3f"},
- {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:c061bb86a71b42465156a3ee7bd58c8c2ceacdbeb95d05a99893e08b8467359a"},
- {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:3a57fdd7ce31c7ff06cdfbf31dafa96cc533c21e443d57f5b1ecc6cdc668ec7f"},
- {file = "MarkupSafe-2.1.5-cp311-cp311-win32.whl", hash = "sha256:397081c1a0bfb5124355710fe79478cdbeb39626492b15d399526ae53422b906"},
- {file = "MarkupSafe-2.1.5-cp311-cp311-win_amd64.whl", hash = "sha256:2b7c57a4dfc4f16f7142221afe5ba4e093e09e728ca65c51f5620c9aaeb9a617"},
{file = "MarkupSafe-2.1.5-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:8dec4936e9c3100156f8a2dc89c4b88d5c435175ff03413b443469c7c8c5f4d1"},
{file = "MarkupSafe-2.1.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:3c6b973f22eb18a789b1460b4b91bf04ae3f0c4234a0a6aa6b0a92f6f7b951d4"},
{file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ac07bad82163452a6884fe8fa0963fb98c2346ba78d779ec06bd7a6262132aee"},
@@ -1178,17 +1057,6 @@ requires_python = ">=3.8"
summary = "MessagePack serializer"
groups = ["docs"]
files = [
- {file = "msgpack-1.0.8-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9517004e21664f2b5a5fd6333b0731b9cf0817403a941b393d89a2f1dc2bd836"},
- {file = "msgpack-1.0.8-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d16a786905034e7e34098634b184a7d81f91d4c3d246edc6bd7aefb2fd8ea6ad"},
- {file = "msgpack-1.0.8-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e2872993e209f7ed04d963e4b4fbae72d034844ec66bc4ca403329db2074377b"},
- {file = "msgpack-1.0.8-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5c330eace3dd100bdb54b5653b966de7f51c26ec4a7d4e87132d9b4f738220ba"},
- {file = "msgpack-1.0.8-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:83b5c044f3eff2a6534768ccfd50425939e7a8b5cf9a7261c385de1e20dcfc85"},
- {file = "msgpack-1.0.8-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1876b0b653a808fcd50123b953af170c535027bf1d053b59790eebb0aeb38950"},
- {file = "msgpack-1.0.8-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:dfe1f0f0ed5785c187144c46a292b8c34c1295c01da12e10ccddfc16def4448a"},
- {file = "msgpack-1.0.8-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:3528807cbbb7f315bb81959d5961855e7ba52aa60a3097151cb21956fbc7502b"},
- {file = "msgpack-1.0.8-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e2f879ab92ce502a1e65fce390eab619774dda6a6ff719718069ac94084098ce"},
- {file = "msgpack-1.0.8-cp311-cp311-win32.whl", hash = "sha256:26ee97a8261e6e35885c2ecd2fd4a6d38252246f94a2aec23665a4e66d066305"},
- {file = "msgpack-1.0.8-cp311-cp311-win_amd64.whl", hash = "sha256:eadb9f826c138e6cf3c49d6f8de88225a3c0ab181a9b4ba792e006e5292d150e"},
{file = "msgpack-1.0.8-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:114be227f5213ef8b215c22dde19532f5da9652e56e8ce969bf0a26d7c419fee"},
{file = "msgpack-1.0.8-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:d661dc4785affa9d0edfdd1e59ec056a58b3dbb9f196fa43587f3ddac654ac7b"},
{file = "msgpack-1.0.8-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d56fd9f1f1cdc8227d7b7918f55091349741904d9520c65f0139a9755952c9e8"},
@@ -1210,13 +1078,6 @@ requires_python = ">=3.8"
summary = "A fast serialization and validation library, with builtin support for JSON, MessagePack, YAML, and TOML."
groups = ["default"]
files = [
- {file = "msgspec-0.18.6-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:e77e56ffe2701e83a96e35770c6adb655ffc074d530018d1b584a8e635b4f36f"},
- {file = "msgspec-0.18.6-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d5351afb216b743df4b6b147691523697ff3a2fc5f3d54f771e91219f5c23aaa"},
- {file = "msgspec-0.18.6-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c3232fabacef86fe8323cecbe99abbc5c02f7698e3f5f2e248e3480b66a3596b"},
- {file = "msgspec-0.18.6-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e3b524df6ea9998bbc99ea6ee4d0276a101bcc1aa8d14887bb823914d9f60d07"},
- {file = "msgspec-0.18.6-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:37f67c1d81272131895bb20d388dd8d341390acd0e192a55ab02d4d6468b434c"},
- {file = "msgspec-0.18.6-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:d0feb7a03d971c1c0353de1a8fe30bb6579c2dc5ccf29b5f7c7ab01172010492"},
- {file = "msgspec-0.18.6-cp311-cp311-win_amd64.whl", hash = "sha256:41cf758d3f40428c235c0f27bc6f322d43063bc32da7b9643e3f805c21ed57b4"},
{file = "msgspec-0.18.6-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:d86f5071fe33e19500920333c11e2267a31942d18fed4d9de5bc2fbab267d28c"},
{file = "msgspec-0.18.6-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ce13981bfa06f5eb126a3a5a38b1976bddb49a36e4f46d8e6edecf33ccf11df1"},
{file = "msgspec-0.18.6-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e97dec6932ad5e3ee1e3c14718638ba333befc45e0661caa57033cd4cc489466"},
@@ -1234,21 +1095,6 @@ requires_python = ">=3.7"
summary = "multidict implementation"
groups = ["default"]
files = [
- {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"},
@@ -1270,7 +1116,7 @@ files = [
[[package]]
name = "mypy"
-version = "1.9.0"
+version = "1.10.0"
requires_python = ">=3.8"
summary = "Optional static typing for Python"
groups = ["lint"]
@@ -1279,18 +1125,13 @@ dependencies = [
"typing-extensions>=4.1.0",
]
files = [
- {file = "mypy-1.9.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:653265f9a2784db65bfca694d1edd23093ce49740b2244cde583aeb134c008f3"},
- {file = "mypy-1.9.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3a3c007ff3ee90f69cf0a15cbcdf0995749569b86b6d2f327af01fd1b8aee9dc"},
- {file = "mypy-1.9.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2418488264eb41f69cc64a69a745fad4a8f86649af4b1041a4c64ee61fc61129"},
- {file = "mypy-1.9.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:68edad3dc7d70f2f17ae4c6c1b9471a56138ca22722487eebacfd1eb5321d612"},
- {file = "mypy-1.9.0-cp311-cp311-win_amd64.whl", hash = "sha256:85ca5fcc24f0b4aeedc1d02f93707bccc04733f21d41c88334c5482219b1ccb3"},
- {file = "mypy-1.9.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:aceb1db093b04db5cd390821464504111b8ec3e351eb85afd1433490163d60cd"},
- {file = "mypy-1.9.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0235391f1c6f6ce487b23b9dbd1327b4ec33bb93934aa986efe8a9563d9349e6"},
- {file = "mypy-1.9.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d4d5ddc13421ba3e2e082a6c2d74c2ddb3979c39b582dacd53dd5d9431237185"},
- {file = "mypy-1.9.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:190da1ee69b427d7efa8aa0d5e5ccd67a4fb04038c380237a0d96829cb157913"},
- {file = "mypy-1.9.0-cp312-cp312-win_amd64.whl", hash = "sha256:fe28657de3bfec596bbeef01cb219833ad9d38dd5393fc649f4b366840baefe6"},
- {file = "mypy-1.9.0-py3-none-any.whl", hash = "sha256:a260627a570559181a9ea5de61ac6297aa5af202f06fd7ab093ce74e7181e43e"},
- {file = "mypy-1.9.0.tar.gz", hash = "sha256:3cc5da0127e6a478cddd906068496a97a7618a21ce9b54bde5bf7e539c7af974"},
+ {file = "mypy-1.10.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:a781f6ad4bab20eef8b65174a57e5203f4be627b46291f4589879bf4e257b97b"},
+ {file = "mypy-1.10.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b808e12113505b97d9023b0b5e0c0705a90571c6feefc6f215c1df9381256e30"},
+ {file = "mypy-1.10.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f55583b12156c399dce2df7d16f8a5095291354f1e839c252ec6c0611e86e2e"},
+ {file = "mypy-1.10.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4cf18f9d0efa1b16478c4c129eabec36148032575391095f73cae2e722fcf9d5"},
+ {file = "mypy-1.10.0-cp312-cp312-win_amd64.whl", hash = "sha256:bc6ac273b23c6b82da3bb25f4136c4fd42665f17f2cd850771cb600bdd2ebeda"},
+ {file = "mypy-1.10.0-py3-none-any.whl", hash = "sha256:f8c083976eb530019175aabadb60921e73b4f45736760826aa1689dda8208aee"},
+ {file = "mypy-1.10.0.tar.gz", hash = "sha256:3d087fcbec056c4ee34974da493a826ce316947485cef3901f511848e687c131"},
]
[[package]]
@@ -1320,7 +1161,7 @@ name = "nodeenv"
version = "1.8.0"
requires_python = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*"
summary = "Node.js virtual environment builder"
-groups = ["default", "lint"]
+groups = ["lint"]
dependencies = [
"setuptools",
]
@@ -1413,24 +1254,24 @@ files = [
[[package]]
name = "platformdirs"
-version = "4.2.0"
+version = "4.2.1"
requires_python = ">=3.8"
-summary = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"."
-groups = ["default", "docs", "lint"]
+summary = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`."
+groups = ["docs", "lint"]
files = [
- {file = "platformdirs-4.2.0-py3-none-any.whl", hash = "sha256:0614df2a2f37e1a662acbd8e2b25b92ccf8632929bc6d43467e17fe89c75e068"},
- {file = "platformdirs-4.2.0.tar.gz", hash = "sha256:ef0cc731df711022c174543cb70a9b5bd22e5a9337c8624ef2c2ceb8ddad8768"},
+ {file = "platformdirs-4.2.1-py3-none-any.whl", hash = "sha256:17d5a1161b3fd67b390023cb2d3b026bbd40abde6fdb052dfbd3a29c3ba22ee1"},
+ {file = "platformdirs-4.2.1.tar.gz", hash = "sha256:031cd18d4ec63ec53e82dceaac0417d218a6863f7745dfcc9efe7793b7039bdf"},
]
[[package]]
name = "pluggy"
-version = "1.4.0"
+version = "1.5.0"
requires_python = ">=3.8"
summary = "plugin and hook calling mechanisms for python"
groups = ["test"]
files = [
- {file = "pluggy-1.4.0-py3-none-any.whl", hash = "sha256:7db9f7b503d67d1c5b95f59773ebb58a8c1c288129a88665838012cfb07b8981"},
- {file = "pluggy-1.4.0.tar.gz", hash = "sha256:8c85c2876142a764e5b7548e7d9a0e0ddb46f5185161049a79b7e974454223be"},
+ {file = "pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669"},
+ {file = "pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1"},
]
[[package]]
@@ -1450,10 +1291,10 @@ files = [
[[package]]
name = "pre-commit"
-version = "3.6.2"
+version = "3.7.0"
requires_python = ">=3.9"
summary = "A framework for managing and maintaining multi-language pre-commit hooks."
-groups = ["default", "lint"]
+groups = ["lint"]
dependencies = [
"cfgv>=2.0.0",
"identify>=1.0.0",
@@ -1462,8 +1303,8 @@ dependencies = [
"virtualenv>=20.10.0",
]
files = [
- {file = "pre_commit-3.6.2-py2.py3-none-any.whl", hash = "sha256:ba637c2d7a670c10daedc059f5c49b5bd0aadbccfcd7ec15592cf9665117532c"},
- {file = "pre_commit-3.6.2.tar.gz", hash = "sha256:c3ef34f463045c88658c5b99f38c1e297abdcc0ff13f98d3370055fbbfabc67e"},
+ {file = "pre_commit-3.7.0-py2.py3-none-any.whl", hash = "sha256:5eae9e10c2b5ac51577c3452ec0a490455c45a0533f7960f993a0d01e59decab"},
+ {file = "pre_commit-3.7.0.tar.gz", hash = "sha256:e209d61b8acdcf742404408531f0c37d49d2c734fd7cff2d6076083d191cb060"},
]
[[package]]
@@ -1512,73 +1353,60 @@ files = [
[[package]]
name = "pydantic"
-version = "2.6.3"
+version = "2.7.1"
requires_python = ">=3.8"
summary = "Data validation using Python type hints"
groups = ["default", "docs"]
dependencies = [
"annotated-types>=0.4.0",
- "pydantic-core==2.16.3",
+ "pydantic-core==2.18.2",
"typing-extensions>=4.6.1",
]
files = [
- {file = "pydantic-2.6.3-py3-none-any.whl", hash = "sha256:72c6034df47f46ccdf81869fddb81aade68056003900a8724a4f160700016a2a"},
- {file = "pydantic-2.6.3.tar.gz", hash = "sha256:e07805c4c7f5c6826e33a1d4c9d47950d7eaf34868e2690f8594d2e30241f11f"},
+ {file = "pydantic-2.7.1-py3-none-any.whl", hash = "sha256:e029badca45266732a9a79898a15ae2e8b14840b1eabbb25844be28f0b33f3d5"},
+ {file = "pydantic-2.7.1.tar.gz", hash = "sha256:e9dbb5eada8abe4d9ae5f46b9939aead650cd2b68f249bb3a8139dbe125803cc"},
]
[[package]]
name = "pydantic-core"
-version = "2.16.3"
+version = "2.18.2"
requires_python = ">=3.8"
-summary = ""
+summary = "Core functionality for Pydantic validation and serialization"
groups = ["default", "docs"]
dependencies = [
"typing-extensions!=4.7.0,>=4.6.0",
]
files = [
- {file = "pydantic_core-2.16.3-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:519ae0312616026bf4cedc0fe459e982734f3ca82ee8c7246c19b650b60a5ee4"},
- {file = "pydantic_core-2.16.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b3992a322a5617ded0a9f23fd06dbc1e4bd7cf39bc4ccf344b10f80af58beacd"},
- {file = "pydantic_core-2.16.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8d62da299c6ecb04df729e4b5c52dc0d53f4f8430b4492b93aa8de1f541c4aac"},
- {file = "pydantic_core-2.16.3-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2acca2be4bb2f2147ada8cac612f8a98fc09f41c89f87add7256ad27332c2fda"},
- {file = "pydantic_core-2.16.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1b662180108c55dfbf1280d865b2d116633d436cfc0bba82323554873967b340"},
- {file = "pydantic_core-2.16.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e7c6ed0dc9d8e65f24f5824291550139fe6f37fac03788d4580da0d33bc00c97"},
- {file = "pydantic_core-2.16.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a6b1bb0827f56654b4437955555dc3aeeebeddc47c2d7ed575477f082622c49e"},
- {file = "pydantic_core-2.16.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e56f8186d6210ac7ece503193ec84104da7ceb98f68ce18c07282fcc2452e76f"},
- {file = "pydantic_core-2.16.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:936e5db01dd49476fa8f4383c259b8b1303d5dd5fb34c97de194560698cc2c5e"},
- {file = "pydantic_core-2.16.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:33809aebac276089b78db106ee692bdc9044710e26f24a9a2eaa35a0f9fa70ba"},
- {file = "pydantic_core-2.16.3-cp311-none-win32.whl", hash = "sha256:ded1c35f15c9dea16ead9bffcde9bb5c7c031bff076355dc58dcb1cb436c4721"},
- {file = "pydantic_core-2.16.3-cp311-none-win_amd64.whl", hash = "sha256:d89ca19cdd0dd5f31606a9329e309d4fcbb3df860960acec32630297d61820df"},
- {file = "pydantic_core-2.16.3-cp311-none-win_arm64.whl", hash = "sha256:6162f8d2dc27ba21027f261e4fa26f8bcb3cf9784b7f9499466a311ac284b5b9"},
- {file = "pydantic_core-2.16.3-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:0f56ae86b60ea987ae8bcd6654a887238fd53d1384f9b222ac457070b7ac4cff"},
- {file = "pydantic_core-2.16.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c9bd22a2a639e26171068f8ebb5400ce2c1bc7d17959f60a3b753ae13c632975"},
- {file = "pydantic_core-2.16.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4204e773b4b408062960e65468d5346bdfe139247ee5f1ca2a378983e11388a2"},
- {file = "pydantic_core-2.16.3-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f651dd19363c632f4abe3480a7c87a9773be27cfe1341aef06e8759599454120"},
- {file = "pydantic_core-2.16.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:aaf09e615a0bf98d406657e0008e4a8701b11481840be7d31755dc9f97c44053"},
- {file = "pydantic_core-2.16.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8e47755d8152c1ab5b55928ab422a76e2e7b22b5ed8e90a7d584268dd49e9c6b"},
- {file = "pydantic_core-2.16.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:500960cb3a0543a724a81ba859da816e8cf01b0e6aaeedf2c3775d12ee49cade"},
- {file = "pydantic_core-2.16.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:cf6204fe865da605285c34cf1172879d0314ff267b1c35ff59de7154f35fdc2e"},
- {file = "pydantic_core-2.16.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d33dd21f572545649f90c38c227cc8631268ba25c460b5569abebdd0ec5974ca"},
- {file = "pydantic_core-2.16.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:49d5d58abd4b83fb8ce763be7794d09b2f50f10aa65c0f0c1696c677edeb7cbf"},
- {file = "pydantic_core-2.16.3-cp312-none-win32.whl", hash = "sha256:f53aace168a2a10582e570b7736cc5bef12cae9cf21775e3eafac597e8551fbe"},
- {file = "pydantic_core-2.16.3-cp312-none-win_amd64.whl", hash = "sha256:0d32576b1de5a30d9a97f300cc6a3f4694c428d956adbc7e6e2f9cad279e45ed"},
- {file = "pydantic_core-2.16.3-cp312-none-win_arm64.whl", hash = "sha256:ec08be75bb268473677edb83ba71e7e74b43c008e4a7b1907c6d57e940bf34b6"},
- {file = "pydantic_core-2.16.3-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:36fa178aacbc277bc6b62a2c3da95226520da4f4e9e206fdf076484363895d2c"},
- {file = "pydantic_core-2.16.3-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:dcca5d2bf65c6fb591fff92da03f94cd4f315972f97c21975398bd4bd046854a"},
- {file = "pydantic_core-2.16.3-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2a72fb9963cba4cd5793854fd12f4cfee731e86df140f59ff52a49b3552db241"},
- {file = "pydantic_core-2.16.3-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b60cc1a081f80a2105a59385b92d82278b15d80ebb3adb200542ae165cd7d183"},
- {file = "pydantic_core-2.16.3-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:cbcc558401de90a746d02ef330c528f2e668c83350f045833543cd57ecead1ad"},
- {file = "pydantic_core-2.16.3-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:fee427241c2d9fb7192b658190f9f5fd6dfe41e02f3c1489d2ec1e6a5ab1e04a"},
- {file = "pydantic_core-2.16.3-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:f4cb85f693044e0f71f394ff76c98ddc1bc0953e48c061725e540396d5c8a2e1"},
- {file = "pydantic_core-2.16.3-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:b29eeb887aa931c2fcef5aa515d9d176d25006794610c264ddc114c053bf96fe"},
- {file = "pydantic_core-2.16.3-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:a425479ee40ff021f8216c9d07a6a3b54b31c8267c6e17aa88b70d7ebd0e5e5b"},
- {file = "pydantic_core-2.16.3-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:5c5cbc703168d1b7a838668998308018a2718c2130595e8e190220238addc96f"},
- {file = "pydantic_core-2.16.3-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:99b6add4c0b39a513d323d3b93bc173dac663c27b99860dd5bf491b240d26137"},
- {file = "pydantic_core-2.16.3-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75f76ee558751746d6a38f89d60b6228fa174e5172d143886af0f85aa306fd89"},
- {file = "pydantic_core-2.16.3-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:00ee1c97b5364b84cb0bd82e9bbf645d5e2871fb8c58059d158412fee2d33d8a"},
- {file = "pydantic_core-2.16.3-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:287073c66748f624be4cef893ef9174e3eb88fe0b8a78dc22e88eca4bc357ca6"},
- {file = "pydantic_core-2.16.3-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:ed25e1835c00a332cb10c683cd39da96a719ab1dfc08427d476bce41b92531fc"},
- {file = "pydantic_core-2.16.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:86b3d0033580bd6bbe07590152007275bd7af95f98eaa5bd36f3da219dcd93da"},
- {file = "pydantic_core-2.16.3.tar.gz", hash = "sha256:1cac689f80a3abab2d3c0048b29eea5751114054f032a941a32de4c852c59cad"},
+ {file = "pydantic_core-2.18.2-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:fb2bd7be70c0fe4dfd32c951bc813d9fe6ebcbfdd15a07527796c8204bd36242"},
+ {file = "pydantic_core-2.18.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6132dd3bd52838acddca05a72aafb6eab6536aa145e923bb50f45e78b7251043"},
+ {file = "pydantic_core-2.18.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d7d904828195733c183d20a54230c0df0eb46ec746ea1a666730787353e87182"},
+ {file = "pydantic_core-2.18.2-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c9bd70772c720142be1020eac55f8143a34ec9f82d75a8e7a07852023e46617f"},
+ {file = "pydantic_core-2.18.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2b8ed04b3582771764538f7ee7001b02e1170223cf9b75dff0bc698fadb00cf3"},
+ {file = "pydantic_core-2.18.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e6dac87ddb34aaec85f873d737e9d06a3555a1cc1a8e0c44b7f8d5daeb89d86f"},
+ {file = "pydantic_core-2.18.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7ca4ae5a27ad7a4ee5170aebce1574b375de390bc01284f87b18d43a3984df72"},
+ {file = "pydantic_core-2.18.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:886eec03591b7cf058467a70a87733b35f44707bd86cf64a615584fd72488b7c"},
+ {file = "pydantic_core-2.18.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:ca7b0c1f1c983e064caa85f3792dd2fe3526b3505378874afa84baf662e12241"},
+ {file = "pydantic_core-2.18.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4b4356d3538c3649337df4074e81b85f0616b79731fe22dd11b99499b2ebbdf3"},
+ {file = "pydantic_core-2.18.2-cp312-none-win32.whl", hash = "sha256:8b172601454f2d7701121bbec3425dd71efcb787a027edf49724c9cefc14c038"},
+ {file = "pydantic_core-2.18.2-cp312-none-win_amd64.whl", hash = "sha256:b1bd7e47b1558ea872bd16c8502c414f9e90dcf12f1395129d7bb42a09a95438"},
+ {file = "pydantic_core-2.18.2-cp312-none-win_arm64.whl", hash = "sha256:98758d627ff397e752bc339272c14c98199c613f922d4a384ddc07526c86a2ec"},
+ {file = "pydantic_core-2.18.2-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:a1874c6dd4113308bd0eb568418e6114b252afe44319ead2b4081e9b9521fe75"},
+ {file = "pydantic_core-2.18.2-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:ccdd111c03bfd3666bd2472b674c6899550e09e9f298954cfc896ab92b5b0e6d"},
+ {file = "pydantic_core-2.18.2-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e18609ceaa6eed63753037fc06ebb16041d17d28199ae5aba0052c51449650a9"},
+ {file = "pydantic_core-2.18.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6e5c584d357c4e2baf0ff7baf44f4994be121e16a2c88918a5817331fc7599d7"},
+ {file = "pydantic_core-2.18.2-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:43f0f463cf89ace478de71a318b1b4f05ebc456a9b9300d027b4b57c1a2064fb"},
+ {file = "pydantic_core-2.18.2-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:e1b395e58b10b73b07b7cf740d728dd4ff9365ac46c18751bf8b3d8cca8f625a"},
+ {file = "pydantic_core-2.18.2-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:0098300eebb1c837271d3d1a2cd2911e7c11b396eac9661655ee524a7f10587b"},
+ {file = "pydantic_core-2.18.2-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:36789b70d613fbac0a25bb07ab3d9dba4d2e38af609c020cf4d888d165ee0bf3"},
+ {file = "pydantic_core-2.18.2-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:3f9a801e7c8f1ef8718da265bba008fa121243dfe37c1cea17840b0944dfd72c"},
+ {file = "pydantic_core-2.18.2-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:3a6515ebc6e69d85502b4951d89131ca4e036078ea35533bb76327f8424531ce"},
+ {file = "pydantic_core-2.18.2-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:20aca1e2298c56ececfd8ed159ae4dde2df0781988c97ef77d5c16ff4bd5b400"},
+ {file = "pydantic_core-2.18.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:223ee893d77a310a0391dca6df00f70bbc2f36a71a895cecd9a0e762dc37b349"},
+ {file = "pydantic_core-2.18.2-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2334ce8c673ee93a1d6a65bd90327588387ba073c17e61bf19b4fd97d688d63c"},
+ {file = "pydantic_core-2.18.2-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:cbca948f2d14b09d20268cda7b0367723d79063f26c4ffc523af9042cad95592"},
+ {file = "pydantic_core-2.18.2-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:b3ef08e20ec49e02d5c6717a91bb5af9b20f1805583cb0adfe9ba2c6b505b5ae"},
+ {file = "pydantic_core-2.18.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:c6fdc8627910eed0c01aed6a390a252fe3ea6d472ee70fdde56273f198938374"},
+ {file = "pydantic_core-2.18.2.tar.gz", hash = "sha256:2e29d20810dfc3043ee13ac7d9e25105799817683348823f305ab3f349b9386e"},
]
[[package]]
@@ -1619,13 +1447,13 @@ files = [
[[package]]
name = "pygments"
-version = "2.17.2"
-requires_python = ">=3.7"
+version = "2.18.0"
+requires_python = ">=3.8"
summary = "Pygments is a syntax highlighting package written in Python."
groups = ["default", "docs"]
files = [
- {file = "pygments-2.17.2-py3-none-any.whl", hash = "sha256:b27c2826c47d0f3219f29554824c30c5e8945175d888647acd804ddd04af846c"},
- {file = "pygments-2.17.2.tar.gz", hash = "sha256:da46cec9fd2de5be3a8a784f434e4c4ab670b4ff54d605c4c2717e9d49c4c367"},
+ {file = "pygments-2.18.0-py3-none-any.whl", hash = "sha256:b8e6aca0523f3ab76fee51799c488e38782ac06eafcf95e7ba832985c8e7b13a"},
+ {file = "pygments-2.18.0.tar.gz", hash = "sha256:786ff802f32e91311bff3889f6e9a86e81505fe99f2735bb6d60ae0c5004f199"},
]
[[package]]
@@ -1657,7 +1485,7 @@ files = [
[[package]]
name = "pyright"
-version = "1.1.353"
+version = "1.1.362"
requires_python = ">=3.7"
summary = "Command line wrapper for pyright"
groups = ["lint"]
@@ -1665,8 +1493,8 @@ dependencies = [
"nodeenv>=1.6.0",
]
files = [
- {file = "pyright-1.1.353-py3-none-any.whl", hash = "sha256:8d7e6719d0be4fd9f4a37f010237c6a74d91ec1e7c81de634c2f3f9965f8ab43"},
- {file = "pyright-1.1.353.tar.gz", hash = "sha256:24343bbc2a4f997563f966b6244a2e863473f1d85af6d24abcb366fcbb4abca9"},
+ {file = "pyright-1.1.362-py3-none-any.whl", hash = "sha256:969957cff45154d8a45a4ab1dae5bdc8223d8bd3c64654fa608ab3194dfff319"},
+ {file = "pyright-1.1.362.tar.gz", hash = "sha256:6a477e448d4a07a6a0eab58b2a15a1bbed031eb3169fa809edee79cca168d83a"},
]
[[package]]
@@ -1682,7 +1510,7 @@ files = [
[[package]]
name = "pytest"
-version = "8.1.1"
+version = "8.2.0"
requires_python = ">=3.8"
summary = "pytest: simple powerful testing with Python"
groups = ["test"]
@@ -1690,16 +1518,16 @@ dependencies = [
"colorama; sys_platform == \"win32\"",
"iniconfig",
"packaging",
- "pluggy<2.0,>=1.4",
+ "pluggy<2.0,>=1.5",
]
files = [
- {file = "pytest-8.1.1-py3-none-any.whl", hash = "sha256:2a8386cfc11fa9d2c50ee7b2a57e7d898ef90470a7a34c4b949ff59662bb78b7"},
- {file = "pytest-8.1.1.tar.gz", hash = "sha256:ac978141a75948948817d360297b7aae0fcb9d6ff6bc9ec6d514b85d5a65c044"},
+ {file = "pytest-8.2.0-py3-none-any.whl", hash = "sha256:1733f0620f6cda4095bbf0d9ff8022486e91892245bb9e7d5542c018f612f233"},
+ {file = "pytest-8.2.0.tar.gz", hash = "sha256:d507d4482197eac0ba2bae2e9babf0672eb333017bcedaa5fb1a3d42c1174b3f"},
]
[[package]]
name = "pytest-asyncio"
-version = "0.23.5.post1"
+version = "0.23.6"
requires_python = ">=3.8"
summary = "Pytest support for asyncio"
groups = ["test"]
@@ -1707,8 +1535,8 @@ dependencies = [
"pytest<9,>=7.0.0",
]
files = [
- {file = "pytest-asyncio-0.23.5.post1.tar.gz", hash = "sha256:b9a8806bea78c21276bc34321bbf234ba1b2ea5b30d9f0ce0f2dea45e4685813"},
- {file = "pytest_asyncio-0.23.5.post1-py3-none-any.whl", hash = "sha256:30f54d27774e79ac409778889880242b0403d09cabd65b727ce90fe92dd5d80e"},
+ {file = "pytest-asyncio-0.23.6.tar.gz", hash = "sha256:ffe523a89c1c222598c76856e76852b787504ddb72dd5d9b6617ffa8aa2cde5f"},
+ {file = "pytest_asyncio-0.23.6-py3-none-any.whl", hash = "sha256:68516fdd1018ac57b846c9846b954f0393b26f094764a28c955eabb0536a4e8a"},
]
[[package]]
@@ -1728,8 +1556,8 @@ files = [
[[package]]
name = "pytest-cov"
-version = "4.1.0"
-requires_python = ">=3.7"
+version = "5.0.0"
+requires_python = ">=3.8"
summary = "Pytest plugin for measuring coverage."
groups = ["test"]
dependencies = [
@@ -1737,8 +1565,8 @@ dependencies = [
"pytest>=4.6",
]
files = [
- {file = "pytest-cov-4.1.0.tar.gz", hash = "sha256:3904b13dfbfec47f003b8e77fd5b589cd11904a21ddf1ab38a64f204d6a10ef6"},
- {file = "pytest_cov-4.1.0-py3-none-any.whl", hash = "sha256:6ba70b9e97e69fcc3fb45bfeab2d0a138fb65c4d0d6a41ef33983ad114be8c3a"},
+ {file = "pytest-cov-5.0.0.tar.gz", hash = "sha256:5837b58e9f6ebd335b0f8060eecce69b662415b16dc503883a02f45dfeb14857"},
+ {file = "pytest_cov-5.0.0-py3-none-any.whl", hash = "sha256:4f0764a1219df53214206bf1feea4633c3b558a2925c8b59f144f682861ce652"},
]
[[package]]
@@ -1757,16 +1585,16 @@ files = [
[[package]]
name = "pytest-mock"
-version = "3.12.0"
+version = "3.14.0"
requires_python = ">=3.8"
summary = "Thin-wrapper around the mock package for easier use with pytest"
groups = ["test"]
dependencies = [
- "pytest>=5.0",
+ "pytest>=6.2.5",
]
files = [
- {file = "pytest-mock-3.12.0.tar.gz", hash = "sha256:31a40f038c22cad32287bb43932054451ff5583ff094bca6f675df2f8bc1a6e9"},
- {file = "pytest_mock-3.12.0-py3-none-any.whl", hash = "sha256:0972719a7263072da3a21c7f4773069bcc7486027d7e8e1f81d98a47e701bc4f"},
+ {file = "pytest-mock-3.14.0.tar.gz", hash = "sha256:2719255a1efeceadbc056d6bf3df3d1c5015530fb40cf347c0f9afac88410bd0"},
+ {file = "pytest_mock-3.14.0-py3-none-any.whl", hash = "sha256:0b72c38033392a5f4621342fe11e9219ac11ec9d375f8e2a0c164539e0d70f6f"},
]
[[package]]
@@ -1816,14 +1644,6 @@ requires_python = ">=3.6"
summary = "YAML parser and emitter for Python"
groups = ["default", "lint"]
files = [
- {file = "PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007"},
- {file = "PyYAML-6.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab"},
- {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d"},
- {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc"},
- {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673"},
- {file = "PyYAML-6.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b"},
- {file = "PyYAML-6.0.1-cp311-cp311-win32.whl", hash = "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741"},
- {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"},
{file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"},
{file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"},
{file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef"},
@@ -1868,18 +1688,18 @@ files = [
[[package]]
name = "rich-click"
-version = "1.7.3"
+version = "1.8.1"
requires_python = ">=3.7"
summary = "Format click help output nicely with rich"
groups = ["default"]
dependencies = [
"click>=7",
- "rich>=10.7.0",
+ "rich>=10.7",
"typing-extensions",
]
files = [
- {file = "rich-click-1.7.3.tar.gz", hash = "sha256:bced1594c497dc007ab49508ff198bb437c576d01291c13a61658999066481f4"},
- {file = "rich_click-1.7.3-py3-none-any.whl", hash = "sha256:bc4163d4e2a3361e21c4d72d300eca6eb8896dfc978667923cb1d4937b8769a3"},
+ {file = "rich_click-1.8.1-py3-none-any.whl", hash = "sha256:0cf0bf84404e78379bd2722db88cb07ffd0535440e20a05943d5b02249d90f8a"},
+ {file = "rich_click-1.8.1.tar.gz", hash = "sha256:73c2ec88a66d7bf6b8c32783539d1c9c92c7c75847f14186092d27f83b206e8a"},
]
[[package]]
@@ -1918,14 +1738,6 @@ summary = "C version of reader, parser and emitter for ruamel.yaml derived from
groups = ["docs"]
marker = "platform_python_implementation == \"CPython\" and python_version < \"3.13\""
files = [
- {file = "ruamel.yaml.clib-0.2.8-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:bef08cd86169d9eafb3ccb0a39edb11d8e25f3dae2b28f5c52fd997521133069"},
- {file = "ruamel.yaml.clib-0.2.8-cp311-cp311-macosx_13_0_arm64.whl", hash = "sha256:b16420e621d26fdfa949a8b4b47ade8810c56002f5389970db4ddda51dbff248"},
- {file = "ruamel.yaml.clib-0.2.8-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:25c515e350e5b739842fc3228d662413ef28f295791af5e5110b543cf0b57d9b"},
- {file = "ruamel.yaml.clib-0.2.8-cp311-cp311-manylinux_2_24_aarch64.whl", hash = "sha256:1707814f0d9791df063f8c19bb51b0d1278b8e9a2353abbb676c2f685dee6afe"},
- {file = "ruamel.yaml.clib-0.2.8-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:46d378daaac94f454b3a0e3d8d78cafd78a026b1d71443f4966c696b48a6d899"},
- {file = "ruamel.yaml.clib-0.2.8-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:09b055c05697b38ecacb7ac50bdab2240bfca1a0c4872b0fd309bb07dc9aa3a9"},
- {file = "ruamel.yaml.clib-0.2.8-cp311-cp311-win32.whl", hash = "sha256:53a300ed9cea38cf5a2a9b069058137c2ca1ce658a874b79baceb8f892f915a7"},
- {file = "ruamel.yaml.clib-0.2.8-cp311-cp311-win_amd64.whl", hash = "sha256:c2a72e9109ea74e511e29032f3b670835f8a59bbdc9ce692c5b4ed91ccf1eedb"},
{file = "ruamel.yaml.clib-0.2.8-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:ebc06178e8821efc9692ea7544aa5644217358490145629914d8020042c24aa1"},
{file = "ruamel.yaml.clib-0.2.8-cp312-cp312-macosx_13_0_arm64.whl", hash = "sha256:edaef1c1200c4b4cb914583150dcaa3bc30e592e907c01117c08b13a07255ec2"},
{file = "ruamel.yaml.clib-0.2.8-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d176b57452ab5b7028ac47e7b3cf644bcfdc8cacfecf7e71759f7f51a59e5c92"},
@@ -1939,39 +1751,39 @@ files = [
[[package]]
name = "ruff"
-version = "0.3.2"
+version = "0.4.4"
requires_python = ">=3.7"
summary = "An extremely fast Python linter and code formatter, written in Rust."
groups = ["default"]
files = [
- {file = "ruff-0.3.2-py3-none-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:77f2612752e25f730da7421ca5e3147b213dca4f9a0f7e0b534e9562c5441f01"},
- {file = "ruff-0.3.2-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:9966b964b2dd1107797be9ca7195002b874424d1d5472097701ae8f43eadef5d"},
- {file = "ruff-0.3.2-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b83d17ff166aa0659d1e1deaf9f2f14cbe387293a906de09bc4860717eb2e2da"},
- {file = "ruff-0.3.2-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bb875c6cc87b3703aeda85f01c9aebdce3d217aeaca3c2e52e38077383f7268a"},
- {file = "ruff-0.3.2-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:be75e468a6a86426430373d81c041b7605137a28f7014a72d2fc749e47f572aa"},
- {file = "ruff-0.3.2-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:967978ac2d4506255e2f52afe70dda023fc602b283e97685c8447d036863a302"},
- {file = "ruff-0.3.2-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1231eacd4510f73222940727ac927bc5d07667a86b0cbe822024dd00343e77e9"},
- {file = "ruff-0.3.2-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2c6d613b19e9a8021be2ee1d0e27710208d1603b56f47203d0abbde906929a9b"},
- {file = "ruff-0.3.2-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c8439338a6303585d27b66b4626cbde89bb3e50fa3cae86ce52c1db7449330a7"},
- {file = "ruff-0.3.2-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:de8b480d8379620cbb5ea466a9e53bb467d2fb07c7eca54a4aa8576483c35d36"},
- {file = "ruff-0.3.2-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:b74c3de9103bd35df2bb05d8b2899bf2dbe4efda6474ea9681280648ec4d237d"},
- {file = "ruff-0.3.2-py3-none-musllinux_1_2_i686.whl", hash = "sha256:f380be9fc15a99765c9cf316b40b9da1f6ad2ab9639e551703e581a5e6da6745"},
- {file = "ruff-0.3.2-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:0ac06a3759c3ab9ef86bbeca665d31ad3aa9a4b1c17684aadb7e61c10baa0df4"},
- {file = "ruff-0.3.2-py3-none-win32.whl", hash = "sha256:9bd640a8f7dd07a0b6901fcebccedadeb1a705a50350fb86b4003b805c81385a"},
- {file = "ruff-0.3.2-py3-none-win_amd64.whl", hash = "sha256:0c1bdd9920cab5707c26c8b3bf33a064a4ca7842d91a99ec0634fec68f9f4037"},
- {file = "ruff-0.3.2-py3-none-win_arm64.whl", hash = "sha256:5f65103b1d76e0d600cabd577b04179ff592064eaa451a70a81085930e907d0b"},
- {file = "ruff-0.3.2.tar.gz", hash = "sha256:fa78ec9418eb1ca3db392811df3376b46471ae93792a81af2d1cbb0e5dcb5142"},
+ {file = "ruff-0.4.4-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:29d44ef5bb6a08e235c8249294fa8d431adc1426bfda99ed493119e6f9ea1bf6"},
+ {file = "ruff-0.4.4-py3-none-macosx_11_0_arm64.whl", hash = "sha256:c4efe62b5bbb24178c950732ddd40712b878a9b96b1d02b0ff0b08a090cbd891"},
+ {file = "ruff-0.4.4-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4c8e2f1e8fc12d07ab521a9005d68a969e167b589cbcaee354cb61e9d9de9c15"},
+ {file = "ruff-0.4.4-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:60ed88b636a463214905c002fa3eaab19795679ed55529f91e488db3fe8976ab"},
+ {file = "ruff-0.4.4-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b90fc5e170fc71c712cc4d9ab0e24ea505c6a9e4ebf346787a67e691dfb72e85"},
+ {file = "ruff-0.4.4-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:8e7e6ebc10ef16dcdc77fd5557ee60647512b400e4a60bdc4849468f076f6eef"},
+ {file = "ruff-0.4.4-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b9ddb2c494fb79fc208cd15ffe08f32b7682519e067413dbaf5f4b01a6087bcd"},
+ {file = "ruff-0.4.4-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c51c928a14f9f0a871082603e25a1588059b7e08a920f2f9fa7157b5bf08cfe9"},
+ {file = "ruff-0.4.4-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b5eb0a4bfd6400b7d07c09a7725e1a98c3b838be557fee229ac0f84d9aa49c36"},
+ {file = "ruff-0.4.4-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:b1867ee9bf3acc21778dcb293db504692eda5f7a11a6e6cc40890182a9f9e595"},
+ {file = "ruff-0.4.4-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:1aecced1269481ef2894cc495647392a34b0bf3e28ff53ed95a385b13aa45768"},
+ {file = "ruff-0.4.4-py3-none-musllinux_1_2_i686.whl", hash = "sha256:9da73eb616b3241a307b837f32756dc20a0b07e2bcb694fec73699c93d04a69e"},
+ {file = "ruff-0.4.4-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:958b4ea5589706a81065e2a776237de2ecc3e763342e5cc8e02a4a4d8a5e6f95"},
+ {file = "ruff-0.4.4-py3-none-win32.whl", hash = "sha256:cb53473849f011bca6e754f2cdf47cafc9c4f4ff4570003a0dad0b9b6890e876"},
+ {file = "ruff-0.4.4-py3-none-win_amd64.whl", hash = "sha256:424e5b72597482543b684c11def82669cc6b395aa8cc69acc1858b5ef3e5daae"},
+ {file = "ruff-0.4.4-py3-none-win_arm64.whl", hash = "sha256:39df0537b47d3b597293edbb95baf54ff5b49589eb7ff41926d8243caa995ea6"},
+ {file = "ruff-0.4.4.tar.gz", hash = "sha256:f87ea42d5cdebdc6a69761a9d0bc83ae9b3b30d0ad78952005ba6568d6c022af"},
]
[[package]]
name = "setuptools"
-version = "69.1.1"
+version = "69.5.1"
requires_python = ">=3.8"
summary = "Easily download, build, install, upgrade, and uninstall Python packages"
groups = ["default", "lint"]
files = [
- {file = "setuptools-69.1.1-py3-none-any.whl", hash = "sha256:02fa291a0471b3a18b2b2481ed902af520c69e8ae0919c13da936542754b4c56"},
- {file = "setuptools-69.1.1.tar.gz", hash = "sha256:5c0806c7d9af348e6dd3777b4f4dbb42c7ad85b190104837488eab9a7c945cf8"},
+ {file = "setuptools-69.5.1-py3-none-any.whl", hash = "sha256:c636ac361bc47580504644275c9ad802c50415c7522212252c033bd15f301f32"},
+ {file = "setuptools-69.5.1.tar.gz", hash = "sha256:6c1fccdac05a97e598fb0ae3bbed5904ccb317337a51139dcd51453611bbb987"},
]
[[package]]
@@ -2004,7 +1816,7 @@ name = "sniffio"
version = "1.3.1"
requires_python = ">=3.7"
summary = "Sniff out which async library your code is running under"
-groups = ["default"]
+groups = ["default", "docs"]
files = [
{file = "sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2"},
{file = "sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc"},
@@ -2043,28 +1855,28 @@ files = [
[[package]]
name = "sourcery"
-version = "1.15.0"
+version = "1.17.0"
summary = "Magically refactor Python"
groups = ["lint"]
files = [
- {file = "sourcery-1.15.0-py2.py3-none-macosx_10_9_universal2.whl", hash = "sha256:5d8ab8f61d0a55418b5debb999f76538d8e946a9a69a9e0be66593c1e17ff20f"},
- {file = "sourcery-1.15.0-py2.py3-none-manylinux1_x86_64.whl", hash = "sha256:5c2d7723b7c1bbd3a904fa2d85ef074b9ef1091c917a4e8c57a88b70bcda0699"},
- {file = "sourcery-1.15.0-py2.py3-none-win_amd64.whl", hash = "sha256:ab3438770f4f1535a2a4d872f5a84d12773eeb00825b96a5f2ed321ec3912b5e"},
+ {file = "sourcery-1.17.0-py2.py3-none-macosx_10_9_universal2.whl", hash = "sha256:1cd2fc122b63817f1e2337cace5c35f5012458dfa0f3db9c8840062bc2efbcd1"},
+ {file = "sourcery-1.17.0-py2.py3-none-manylinux1_x86_64.whl", hash = "sha256:5464d0b5f14e84373b9c7e39a406cd77acaaa3a0c0cf3262ddd4bf93b5fe74ea"},
+ {file = "sourcery-1.17.0-py2.py3-none-win_amd64.whl", hash = "sha256:0a07646e014c5b59fcfbcf142b1c283bbac2fa73f421850cb761d949f7a7bee6"},
]
[[package]]
name = "sphinx"
-version = "7.2.6"
+version = "7.3.7"
requires_python = ">=3.9"
summary = "Python documentation generator"
groups = ["docs"]
dependencies = [
"Jinja2>=3.0",
"Pygments>=2.14",
- "alabaster<0.8,>=0.7",
+ "alabaster~=0.7.14",
"babel>=2.9",
"colorama>=0.4.5; sys_platform == \"win32\"",
- "docutils<0.21,>=0.18.1",
+ "docutils<0.22,>=0.18.1",
"imagesize>=1.3",
"packaging>=21.0",
"requests>=2.25.0",
@@ -2077,38 +1889,41 @@ dependencies = [
"sphinxcontrib-serializinghtml>=1.1.9",
]
files = [
- {file = "sphinx-7.2.6-py3-none-any.whl", hash = "sha256:1e09160a40b956dc623c910118fa636da93bd3ca0b9876a7b3df90f07d691560"},
- {file = "sphinx-7.2.6.tar.gz", hash = "sha256:9a5160e1ea90688d5963ba09a2dcd8bdd526620edbb65c328728f1b2228d5ab5"},
+ {file = "sphinx-7.3.7-py3-none-any.whl", hash = "sha256:413f75440be4cacf328f580b4274ada4565fb2187d696a84970c23f77b64d8c3"},
+ {file = "sphinx-7.3.7.tar.gz", hash = "sha256:a4a7db75ed37531c05002d56ed6948d4c42f473a36f46e1382b0bd76ca9627bc"},
]
[[package]]
name = "sphinx-autobuild"
-version = "2024.2.4"
+version = "2024.4.16"
requires_python = ">=3.9"
-summary = "Rebuild Sphinx documentation on changes, with live-reload in the browser."
+summary = "Rebuild Sphinx documentation on changes, with hot reloading in the browser."
groups = ["docs"]
dependencies = [
"colorama",
- "livereload",
"sphinx",
+ "starlette>=0.35",
+ "uvicorn>=0.25",
+ "watchfiles>=0.20",
+ "websockets>=11",
]
files = [
- {file = "sphinx_autobuild-2024.2.4-py3-none-any.whl", hash = "sha256:63fd87ab7505872a89aef468ce6503f65e794a195f4ae62269db3b85b72d4854"},
- {file = "sphinx_autobuild-2024.2.4.tar.gz", hash = "sha256:cb9d2121a176d62d45471624872afc5fad7755ad662738abe400ecf4a7954303"},
+ {file = "sphinx_autobuild-2024.4.16-py3-none-any.whl", hash = "sha256:f2522779d30fcbf0253e09714f274ce8c608cb6ebcd67922b1c54de59faba702"},
+ {file = "sphinx_autobuild-2024.4.16.tar.gz", hash = "sha256:1c0ed37a1970eed197f9c5a66d65759e7c4e4cba7b5a5d77940752bf1a59f2c7"},
]
[[package]]
name = "sphinx-autodoc-typehints"
-version = "2.0.0"
-requires_python = ">=3.8"
+version = "2.1.0"
+requires_python = ">=3.9"
summary = "Type hints (PEP 484) support for the Sphinx autodoc extension"
groups = ["docs"]
dependencies = [
- "sphinx>=7.1.2",
+ "sphinx>=7.3.5",
]
files = [
- {file = "sphinx_autodoc_typehints-2.0.0-py3-none-any.whl", hash = "sha256:12c0e161f6fe191c2cdfd8fa3caea271f5387d9fbc67ebcd6f4f1f24ce880993"},
- {file = "sphinx_autodoc_typehints-2.0.0.tar.gz", hash = "sha256:7f2cdac2e70fd9787926b6e9e541cd4ded1e838d2b46fda2a1bb0a75ec5b7f3a"},
+ {file = "sphinx_autodoc_typehints-2.1.0-py3-none-any.whl", hash = "sha256:46f1a710b3ed35904f63a77c5e68334c5ee1c2e22828b75fdcd147f1c52c199b"},
+ {file = "sphinx_autodoc_typehints-2.1.0.tar.gz", hash = "sha256:51bf8dc77c4fba747e32f0735002a91500747d0553cae616863848e8f5e49fe8"},
]
[[package]]
@@ -2221,7 +2036,7 @@ files = [
name = "sphinx-toolbox"
version = "3.5.0"
requires_python = ">=3.7"
-summary = "Box of handy tools for Sphinx 🧰 📔"
+summary = "Box of handy tools for Sphinx 🧰 📔"
groups = ["docs"]
dependencies = [
"apeye>=0.4.0",
@@ -2326,7 +2141,7 @@ files = [
[[package]]
name = "sqlalchemy"
-version = "2.0.28"
+version = "2.0.30"
requires_python = ">=3.7"
summary = "Database Abstraction Library"
groups = ["default", "docs"]
@@ -2335,24 +2150,30 @@ dependencies = [
"typing-extensions>=4.6.0",
]
files = [
- {file = "SQLAlchemy-2.0.28-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:46a3d4e7a472bfff2d28db838669fc437964e8af8df8ee1e4548e92710929adc"},
- {file = "SQLAlchemy-2.0.28-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:0d3dd67b5d69794cfe82862c002512683b3db038b99002171f624712fa71aeaa"},
- {file = "SQLAlchemy-2.0.28-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c61e2e41656a673b777e2f0cbbe545323dbe0d32312f590b1bc09da1de6c2a02"},
- {file = "SQLAlchemy-2.0.28-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0315d9125a38026227f559488fe7f7cee1bd2fbc19f9fd637739dc50bb6380b2"},
- {file = "SQLAlchemy-2.0.28-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:af8ce2d31679006e7b747d30a89cd3ac1ec304c3d4c20973f0f4ad58e2d1c4c9"},
- {file = "SQLAlchemy-2.0.28-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:81ba314a08c7ab701e621b7ad079c0c933c58cdef88593c59b90b996e8b58fa5"},
- {file = "SQLAlchemy-2.0.28-cp311-cp311-win32.whl", hash = "sha256:1ee8bd6d68578e517943f5ebff3afbd93fc65f7ef8f23becab9fa8fb315afb1d"},
- {file = "SQLAlchemy-2.0.28-cp311-cp311-win_amd64.whl", hash = "sha256:ad7acbe95bac70e4e687a4dc9ae3f7a2f467aa6597049eeb6d4a662ecd990bb6"},
- {file = "SQLAlchemy-2.0.28-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:d3499008ddec83127ab286c6f6ec82a34f39c9817f020f75eca96155f9765097"},
- {file = "SQLAlchemy-2.0.28-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:9b66fcd38659cab5d29e8de5409cdf91e9986817703e1078b2fdaad731ea66f5"},
- {file = "SQLAlchemy-2.0.28-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bea30da1e76cb1acc5b72e204a920a3a7678d9d52f688f087dc08e54e2754c67"},
- {file = "SQLAlchemy-2.0.28-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:124202b4e0edea7f08a4db8c81cc7859012f90a0d14ba2bf07c099aff6e96462"},
- {file = "SQLAlchemy-2.0.28-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:e23b88c69497a6322b5796c0781400692eca1ae5532821b39ce81a48c395aae9"},
- {file = "SQLAlchemy-2.0.28-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4b6303bfd78fb3221847723104d152e5972c22367ff66edf09120fcde5ddc2e2"},
- {file = "SQLAlchemy-2.0.28-cp312-cp312-win32.whl", hash = "sha256:a921002be69ac3ab2cf0c3017c4e6a3377f800f1fca7f254c13b5f1a2f10022c"},
- {file = "SQLAlchemy-2.0.28-cp312-cp312-win_amd64.whl", hash = "sha256:b4a2cf92995635b64876dc141af0ef089c6eea7e05898d8d8865e71a326c0385"},
- {file = "SQLAlchemy-2.0.28-py3-none-any.whl", hash = "sha256:78bb7e8da0183a8301352d569900d9d3594c48ac21dc1c2ec6b3121ed8b6c986"},
- {file = "SQLAlchemy-2.0.28.tar.gz", hash = "sha256:dd53b6c4e6d960600fd6532b79ee28e2da489322fcf6648738134587faf767b6"},
+ {file = "SQLAlchemy-2.0.30-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:5a79d65395ac5e6b0c2890935bad892eabb911c4aa8e8015067ddb37eea3d56c"},
+ {file = "SQLAlchemy-2.0.30-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:9a5baf9267b752390252889f0c802ea13b52dfee5e369527da229189b8bd592e"},
+ {file = "SQLAlchemy-2.0.30-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3cb5a646930c5123f8461f6468901573f334c2c63c795b9af350063a736d0134"},
+ {file = "SQLAlchemy-2.0.30-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:296230899df0b77dec4eb799bcea6fbe39a43707ce7bb166519c97b583cfcab3"},
+ {file = "SQLAlchemy-2.0.30-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:c62d401223f468eb4da32627bffc0c78ed516b03bb8a34a58be54d618b74d472"},
+ {file = "SQLAlchemy-2.0.30-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:3b69e934f0f2b677ec111b4d83f92dc1a3210a779f69bf905273192cf4ed433e"},
+ {file = "SQLAlchemy-2.0.30-cp312-cp312-win32.whl", hash = "sha256:77d2edb1f54aff37e3318f611637171e8ec71472f1fdc7348b41dcb226f93d90"},
+ {file = "SQLAlchemy-2.0.30-cp312-cp312-win_amd64.whl", hash = "sha256:b6c7ec2b1f4969fc19b65b7059ed00497e25f54069407a8701091beb69e591a5"},
+ {file = "SQLAlchemy-2.0.30-py3-none-any.whl", hash = "sha256:7108d569d3990c71e26a42f60474b4c02c8586c4681af5fd67e51a044fdea86a"},
+ {file = "SQLAlchemy-2.0.30.tar.gz", hash = "sha256:2b1708916730f4830bc69d6f49d37f7698b5bd7530aca7f04f785f8849e95255"},
+]
+
+[[package]]
+name = "starlette"
+version = "0.37.2"
+requires_python = ">=3.8"
+summary = "The little ASGI library that shines."
+groups = ["docs"]
+dependencies = [
+ "anyio<5,>=3.4.0",
+]
+files = [
+ {file = "starlette-0.37.2-py3-none-any.whl", hash = "sha256:6fe59f29268538e5d0d182f2791a479a0c64638e6935d1c6989e63fb2699c6ee"},
+ {file = "starlette-0.37.2.tar.gz", hash = "sha256:9af890290133b79fc3db55474ade20f6220a364a0402e0b556e7cd5e1e093823"},
]
[[package]]
@@ -2377,36 +2198,15 @@ files = [
{file = "tabulate-0.9.0.tar.gz", hash = "sha256:0095b12bf5966de529c0feb1fa08671671b3368eec77d7ef7ab114be2c068b3c"},
]
-[[package]]
-name = "tornado"
-version = "6.4"
-requires_python = ">= 3.8"
-summary = "Tornado is a Python web framework and asynchronous networking library, originally developed at FriendFeed."
-groups = ["docs"]
-marker = "python_version > \"2.7\""
-files = [
- {file = "tornado-6.4-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:02ccefc7d8211e5a7f9e8bc3f9e5b0ad6262ba2fbb683a6443ecc804e5224ce0"},
- {file = "tornado-6.4-cp38-abi3-macosx_10_9_x86_64.whl", hash = "sha256:27787de946a9cffd63ce5814c33f734c627a87072ec7eed71f7fc4417bb16263"},
- {file = "tornado-6.4-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f7894c581ecdcf91666a0912f18ce5e757213999e183ebfc2c3fdbf4d5bd764e"},
- {file = "tornado-6.4-cp38-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e43bc2e5370a6a8e413e1e1cd0c91bedc5bd62a74a532371042a18ef19e10579"},
- {file = "tornado-6.4-cp38-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f0251554cdd50b4b44362f73ad5ba7126fc5b2c2895cc62b14a1c2d7ea32f212"},
- {file = "tornado-6.4-cp38-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:fd03192e287fbd0899dd8f81c6fb9cbbc69194d2074b38f384cb6fa72b80e9c2"},
- {file = "tornado-6.4-cp38-abi3-musllinux_1_1_i686.whl", hash = "sha256:88b84956273fbd73420e6d4b8d5ccbe913c65d31351b4c004ae362eba06e1f78"},
- {file = "tornado-6.4-cp38-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:71ddfc23a0e03ef2df1c1397d859868d158c8276a0603b96cf86892bff58149f"},
- {file = "tornado-6.4-cp38-abi3-win32.whl", hash = "sha256:6f8a6c77900f5ae93d8b4ae1196472d0ccc2775cc1dfdc9e7727889145c45052"},
- {file = "tornado-6.4-cp38-abi3-win_amd64.whl", hash = "sha256:10aeaa8006333433da48dec9fe417877f8bcc21f48dda8d661ae79da357b2a63"},
- {file = "tornado-6.4.tar.gz", hash = "sha256:72291fa6e6bc84e626589f1c29d90a5a6d593ef5ae68052ee2ef000dfd273dee"},
-]
-
[[package]]
name = "typing-extensions"
-version = "4.10.0"
+version = "4.11.0"
requires_python = ">=3.8"
summary = "Backported and Experimental Type Hints for Python 3.8+"
groups = ["default", "docs", "lint"]
files = [
- {file = "typing_extensions-4.10.0-py3-none-any.whl", hash = "sha256:69b1a937c3a517342112fb4c6df7e72fc39a38e7891a5730ed4985b5214b5475"},
- {file = "typing_extensions-4.10.0.tar.gz", hash = "sha256:b0abd7c89e8fb96f98db18d86106ff1d90ab692004eb746cf6eda2682f91b3cb"},
+ {file = "typing_extensions-4.11.0-py3-none-any.whl", hash = "sha256:c1f94d72897edaf4ce775bb7558d5b79d8126906a14ea5ed1635921406c0387a"},
+ {file = "typing_extensions-4.11.0.tar.gz", hash = "sha256:83f085bd5ca59c80295fc2a82ab5dac679cbe02b9f33f7d83af68e241bea51b0"},
]
[[package]]
@@ -2422,22 +2222,22 @@ files = [
[[package]]
name = "uvicorn"
-version = "0.27.1"
+version = "0.29.0"
requires_python = ">=3.8"
summary = "The lightning-fast ASGI server."
-groups = ["default"]
+groups = ["default", "docs"]
dependencies = [
"click>=7.0",
"h11>=0.8",
]
files = [
- {file = "uvicorn-0.27.1-py3-none-any.whl", hash = "sha256:5c89da2f3895767472a35556e539fd59f7edbe9b1e9c0e1c99eebeadc61838e4"},
- {file = "uvicorn-0.27.1.tar.gz", hash = "sha256:3d9a267296243532db80c83a959a3400502165ade2c1338dea4e67915fd4745a"},
+ {file = "uvicorn-0.29.0-py3-none-any.whl", hash = "sha256:2c2aac7ff4f4365c206fd773a39bf4ebd1047c238f8b8268ad996829323473de"},
+ {file = "uvicorn-0.29.0.tar.gz", hash = "sha256:6a69214c0b6a087462412670b3ef21224fa48cae0e452b5883e8e8bdfdd11dd0"},
]
[[package]]
name = "uvicorn"
-version = "0.27.1"
+version = "0.29.0"
extras = ["standard"]
requires_python = ">=3.8"
summary = "The lightning-fast ASGI server."
@@ -2447,14 +2247,14 @@ dependencies = [
"httptools>=0.5.0",
"python-dotenv>=0.13",
"pyyaml>=5.1",
- "uvicorn==0.27.1",
+ "uvicorn==0.29.0",
"uvloop!=0.15.0,!=0.15.1,>=0.14.0; (sys_platform != \"cygwin\" and sys_platform != \"win32\") and platform_python_implementation != \"PyPy\"",
"watchfiles>=0.13",
"websockets>=10.4",
]
files = [
- {file = "uvicorn-0.27.1-py3-none-any.whl", hash = "sha256:5c89da2f3895767472a35556e539fd59f7edbe9b1e9c0e1c99eebeadc61838e4"},
- {file = "uvicorn-0.27.1.tar.gz", hash = "sha256:3d9a267296243532db80c83a959a3400502165ade2c1338dea4e67915fd4745a"},
+ {file = "uvicorn-0.29.0-py3-none-any.whl", hash = "sha256:2c2aac7ff4f4365c206fd773a39bf4ebd1047c238f8b8268ad996829323473de"},
+ {file = "uvicorn-0.29.0.tar.gz", hash = "sha256:6a69214c0b6a087462412670b3ef21224fa48cae0e452b5883e8e8bdfdd11dd0"},
]
[[package]]
@@ -2482,18 +2282,18 @@ files = [
[[package]]
name = "virtualenv"
-version = "20.25.1"
+version = "20.26.1"
requires_python = ">=3.7"
summary = "Virtual Python Environment builder"
-groups = ["default", "lint"]
+groups = ["lint"]
dependencies = [
"distlib<1,>=0.3.7",
"filelock<4,>=3.12.2",
"platformdirs<5,>=3.9.1",
]
files = [
- {file = "virtualenv-20.25.1-py3-none-any.whl", hash = "sha256:961c026ac520bac5f69acb8ea063e8a4f071bcc9457b9c1f28f6b085c511583a"},
- {file = "virtualenv-20.25.1.tar.gz", hash = "sha256:e08e13ecdca7a0bd53798f356d5831434afa5b07b93f0abdf0797b7a06ffe197"},
+ {file = "virtualenv-20.26.1-py3-none-any.whl", hash = "sha256:7aa9982a728ae5892558bff6a2839c00b9ed145523ece2274fad6f414690ae75"},
+ {file = "virtualenv-20.26.1.tar.gz", hash = "sha256:604bfdceaeece392802e6ae48e69cec49168b9c5f4a44e483963f9242eb0e78b"},
]
[[package]]
@@ -2501,24 +2301,11 @@ name = "watchfiles"
version = "0.21.0"
requires_python = ">=3.8"
summary = "Simple, modern and high performance file watching and code reload in python."
-groups = ["default"]
+groups = ["default", "docs"]
dependencies = [
"anyio>=3.0.0",
]
files = [
- {file = "watchfiles-0.21.0-cp311-cp311-macosx_10_7_x86_64.whl", hash = "sha256:668c265d90de8ae914f860d3eeb164534ba2e836811f91fecc7050416ee70aa7"},
- {file = "watchfiles-0.21.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3a23092a992e61c3a6a70f350a56db7197242f3490da9c87b500f389b2d01eef"},
- {file = "watchfiles-0.21.0-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:e7941bbcfdded9c26b0bf720cb7e6fd803d95a55d2c14b4bd1f6a2772230c586"},
- {file = "watchfiles-0.21.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:11cd0c3100e2233e9c53106265da31d574355c288e15259c0d40a4405cbae317"},
- {file = "watchfiles-0.21.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d78f30cbe8b2ce770160d3c08cff01b2ae9306fe66ce899b73f0409dc1846c1b"},
- {file = "watchfiles-0.21.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6674b00b9756b0af620aa2a3346b01f8e2a3dc729d25617e1b89cf6af4a54eb1"},
- {file = "watchfiles-0.21.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fd7ac678b92b29ba630d8c842d8ad6c555abda1b9ef044d6cc092dacbfc9719d"},
- {file = "watchfiles-0.21.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9c873345680c1b87f1e09e0eaf8cf6c891b9851d8b4d3645e7efe2ec20a20cc7"},
- {file = "watchfiles-0.21.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:49f56e6ecc2503e7dbe233fa328b2be1a7797d31548e7a193237dcdf1ad0eee0"},
- {file = "watchfiles-0.21.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:02d91cbac553a3ad141db016e3350b03184deaafeba09b9d6439826ee594b365"},
- {file = "watchfiles-0.21.0-cp311-none-win32.whl", hash = "sha256:ebe684d7d26239e23d102a2bad2a358dedf18e462e8808778703427d1f584400"},
- {file = "watchfiles-0.21.0-cp311-none-win_amd64.whl", hash = "sha256:4566006aa44cb0d21b8ab53baf4b9c667a0ed23efe4aaad8c227bfba0bf15cbe"},
- {file = "watchfiles-0.21.0-cp311-none-win_arm64.whl", hash = "sha256:c550a56bf209a3d987d5a975cdf2063b3389a5d16caf29db4bdddeae49f22078"},
{file = "watchfiles-0.21.0-cp312-cp312-macosx_10_7_x86_64.whl", hash = "sha256:51ddac60b96a42c15d24fbdc7a4bfcd02b5a29c047b7f8bf63d3f6f5a860949a"},
{file = "watchfiles-0.21.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:511f0b034120cd1989932bf1e9081aa9fb00f1f949fbd2d9cab6264916ae89b1"},
{file = "watchfiles-0.21.0-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:cfb92d49dbb95ec7a07511bc9efb0faff8fe24ef3805662b8d6808ba8409a71a"},
@@ -2562,19 +2349,8 @@ name = "websockets"
version = "12.0"
requires_python = ">=3.8"
summary = "An implementation of the WebSocket Protocol (RFC 6455 & 7692)"
-groups = ["default"]
+groups = ["default", "docs"]
files = [
- {file = "websockets-12.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:5d873c7de42dea355d73f170be0f23788cf3fa9f7bed718fd2830eefedce01b4"},
- {file = "websockets-12.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3f61726cae9f65b872502ff3c1496abc93ffbe31b278455c418492016e2afc8f"},
- {file = "websockets-12.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ed2fcf7a07334c77fc8a230755c2209223a7cc44fc27597729b8ef5425aa61a3"},
- {file = "websockets-12.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8e332c210b14b57904869ca9f9bf4ca32f5427a03eeb625da9b616c85a3a506c"},
- {file = "websockets-12.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5693ef74233122f8ebab026817b1b37fe25c411ecfca084b29bc7d6efc548f45"},
- {file = "websockets-12.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6e9e7db18b4539a29cc5ad8c8b252738a30e2b13f033c2d6e9d0549b45841c04"},
- {file = "websockets-12.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:6e2df67b8014767d0f785baa98393725739287684b9f8d8a1001eb2839031447"},
- {file = "websockets-12.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:bea88d71630c5900690fcb03161ab18f8f244805c59e2e0dc4ffadae0a7ee0ca"},
- {file = "websockets-12.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:dff6cdf35e31d1315790149fee351f9e52978130cef6c87c4b6c9b3baf78bc53"},
- {file = "websockets-12.0-cp311-cp311-win32.whl", hash = "sha256:3e3aa8c468af01d70332a382350ee95f6986db479ce7af14d5e81ec52aa2b402"},
- {file = "websockets-12.0-cp311-cp311-win_amd64.whl", hash = "sha256:25eb766c8ad27da0f79420b2af4b85d29914ba0edf69f547cc4f06ca6f1d403b"},
{file = "websockets-12.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0e6e2711d5a8e6e482cacb927a49a3d432345dfe7dea8ace7b5790df5932e4df"},
{file = "websockets-12.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:dbcf72a37f0b3316e993e13ecf32f10c0e1259c28ffd0a85cee26e8549595fbc"},
{file = "websockets-12.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:12743ab88ab2af1d17dd4acb4645677cb7063ef4db93abffbf164218a5d54c6b"},
@@ -2647,21 +2423,6 @@ dependencies = [
"multidict>=4.0",
]
files = [
- {file = "yarl-1.9.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:35a2b9396879ce32754bd457d31a51ff0a9d426fd9e0e3c33394bf4b9036b099"},
- {file = "yarl-1.9.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4c7d56b293cc071e82532f70adcbd8b61909eec973ae9d2d1f9b233f3d943f2c"},
- {file = "yarl-1.9.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d8a1c6c0be645c745a081c192e747c5de06e944a0d21245f4cf7c05e457c36e0"},
- {file = "yarl-1.9.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4b3c1ffe10069f655ea2d731808e76e0f452fc6c749bea04781daf18e6039525"},
- {file = "yarl-1.9.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:549d19c84c55d11687ddbd47eeb348a89df9cb30e1993f1b128f4685cd0ebbf8"},
- {file = "yarl-1.9.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a7409f968456111140c1c95301cadf071bd30a81cbd7ab829169fb9e3d72eae9"},
- {file = "yarl-1.9.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e23a6d84d9d1738dbc6e38167776107e63307dfc8ad108e580548d1f2c587f42"},
- {file = "yarl-1.9.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d8b889777de69897406c9fb0b76cdf2fd0f31267861ae7501d93003d55f54fbe"},
- {file = "yarl-1.9.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:03caa9507d3d3c83bca08650678e25364e1843b484f19986a527630ca376ecce"},
- {file = "yarl-1.9.4-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:4e9035df8d0880b2f1c7f5031f33f69e071dfe72ee9310cfc76f7b605958ceb9"},
- {file = "yarl-1.9.4-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:c0ec0ed476f77db9fb29bca17f0a8fcc7bc97ad4c6c1d8959c507decb22e8572"},
- {file = "yarl-1.9.4-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:ee04010f26d5102399bd17f8df8bc38dc7ccd7701dc77f4a68c5b8d733406958"},
- {file = "yarl-1.9.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:49a180c2e0743d5d6e0b4d1a9e5f633c62eca3f8a86ba5dd3c471060e352ca98"},
- {file = "yarl-1.9.4-cp311-cp311-win32.whl", hash = "sha256:81eb57278deb6098a5b62e88ad8281b2ba09f2f1147c4767522353eaa6260b31"},
- {file = "yarl-1.9.4-cp311-cp311-win_amd64.whl", hash = "sha256:d1d2532b340b692880261c15aee4dc94dd22ca5d61b9db9a8a361953d36410b1"},
{file = "yarl-1.9.4-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0d2454f0aef65ea81037759be5ca9947539667eecebca092733b2eb43c965a81"},
{file = "yarl-1.9.4-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:44d8ffbb9c06e5a7f529f38f53eda23e50d1ed33c6c869e01481d3fafa6b8142"},
{file = "yarl-1.9.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:aaaea1e536f98754a6e5c56091baa1b6ce2f2700cc4a00b0d49eca8dea471074"},
diff --git a/pyproject.toml b/pyproject.toml
index 1af0e21..6cc5288 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -12,16 +12,15 @@ dependencies = [
"litestar[jwt,opentelemetry,prometheus,standard,structlog]>=2.4.3",
"pydantic-settings>=2.1.0",
"anyio>=4.1.0",
- "advanced-alchemy>=0.6.1",
+ "advanced-alchemy>=0.6.1, <0.9.0",
"certifi>=2023.11.17",
"asyncpg>=0.29.0",
"PyJWT>=2.8.0",
"alembic>=1.13.0",
- "pre-commit>=3.6.2",
"ruff>=0.1.7",
"githubkit[auth-app]>=0.11.2",
]
-requires-python = ">=3.11,<4.0"
+requires-python = ">=3.12,<4.0"
readme = "README.md"
license = { text = "MIT" }
classifiers = [
@@ -29,7 +28,7 @@ classifiers = [
'Programming Language :: Python',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3 :: Only',
- 'Programming Language :: Python :: 3.11',
+ 'Programming Language :: Python :: 3.12',
'Intended Audience :: Developers',
'Intended Audience :: Information Technology',
'Intended Audience :: System Administrators',
@@ -154,7 +153,7 @@ exclude = [
"tools",
"docs",
]
-pythonVersion = "3.11"
+pythonVersion = "3.12"
reportOptionalMemberAccess = false
reportUnknownMemberType = false
reportGeneralTypeIssues = true
@@ -236,7 +235,7 @@ classmethod-decorators = [
]
[tool.ruff.lint.isort]
-known-first-party = ["src", "tests"]
+known-first-party = ["src", "tests", "byte", "server", "app", "utils"]
[tool.ruff.lint.per-file-ignores]
# Tests can use magic values, assertions, and relative imports
From b24f92b2639a9edefbf63c37e4f6a93f49c1edda Mon Sep 17 00:00:00 2001
From: Jacob Coffee
Date: Fri, 10 May 2024 20:18:49 -0500
Subject: [PATCH 28/29] ci: 3.12
---
.github/workflows/ci.yml | 8 ++++----
.github/workflows/docs.yml | 4 ++--
2 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 57ae32d..790c510 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -14,7 +14,7 @@ jobs:
- uses: actions/setup-python@v4
with:
- python-version: "3.11"
+ python-version: "3.12"
- name: Install Pre-Commit
run: python -m pip install pre-commit && pre-commit install
@@ -34,7 +34,7 @@ jobs:
strategy:
fail-fast: true
matrix:
- python-version: ["3.11"]
+ python-version: ["3.12"]
timeout-minutes: 15
defaults:
run:
@@ -73,12 +73,12 @@ jobs:
- name: Set up Python
uses: actions/setup-python@v4
with:
- python-version: "3.11"
+ python-version: "3.12"
- uses: pdm-project/setup-pdm@v3
name: Set up PDM
with:
- python-version: "3.11"
+ python-version: "3.12"
allow-python-prereleases: true
cache: true
diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml
index d04856f..a5b3eb1 100644
--- a/.github/workflows/docs.yml
+++ b/.github/workflows/docs.yml
@@ -22,12 +22,12 @@ jobs:
- uses: actions/setup-python@v4
with:
- python-version: "3.11"
+ python-version: "3.12"
- uses: pdm-project/setup-pdm@v3
name: Set up PDM
with:
- python-version: "3.11"
+ python-version: "3.12"
allow-python-prereleases: true
cache: true
From b3a7c11df92338d8369ce1206ddce90f1a5c542f Mon Sep 17 00:00:00 2001
From: Jacob Coffee
Date: Fri, 10 May 2024 22:07:59 -0500
Subject: [PATCH 29/29] ci: 3.11 only in railway
---
.tool-versions | 1 +
pyproject.toml | 5 +++--
2 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/.tool-versions b/.tool-versions
index f732415..647c783 100644
--- a/.tool-versions
+++ b/.tool-versions
@@ -1 +1,2 @@
+python 3.11
python 3.12
diff --git a/pyproject.toml b/pyproject.toml
index 6cc5288..2b4ac7f 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -20,7 +20,7 @@ dependencies = [
"ruff>=0.1.7",
"githubkit[auth-app]>=0.11.2",
]
-requires-python = ">=3.12,<4.0"
+requires-python = ">=3.11,<4.0"
readme = "README.md"
license = { text = "MIT" }
classifiers = [
@@ -28,6 +28,7 @@ classifiers = [
'Programming Language :: Python',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3 :: Only',
+ 'Programming Language :: Python :: 3.11',
'Programming Language :: Python :: 3.12',
'Intended Audience :: Developers',
'Intended Audience :: Information Technology',
@@ -207,7 +208,7 @@ strict-imports = false
[tool.ruff]
line-length = 120
src = ["src", "tests"]
-target-version = "py311"
+target-version = "py312"
[tool.ruff.lint]
select = ["ALL"]