mirror of
https://github.com/markbeep/AudioBookRequest.git
synced 2026-04-29 21:09:15 -05:00
test: switch from pyright to pyrefly for typing
perf: minimize HTML while templating
This commit is contained in:
@@ -13,7 +13,8 @@
|
||||
"tamasfe.even-better-toml",
|
||||
"bradlc.vscode-tailwindcss",
|
||||
"samuelcolvin.jinjahtml",
|
||||
"yzhang.markdown-all-in-one"
|
||||
"yzhang.markdown-all-in-one",
|
||||
"meta.pyrefly"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,11 +48,10 @@ jobs:
|
||||
|
||||
- run: uv sync --all-extras
|
||||
|
||||
- run: echo "$PWD/.venv/bin" >> $GITHUB_PATH
|
||||
- name: Run Type Checks
|
||||
run: uv run pyrefly check
|
||||
|
||||
- uses: jakebailey/pyright-action@v2
|
||||
with:
|
||||
extra-args: app # only check apps dir
|
||||
- run: echo "$PWD/.venv/bin" >> $GITHUB_PATH
|
||||
|
||||
- name: Check SQLite Alembic Migrations
|
||||
run: |
|
||||
|
||||
@@ -1,77 +0,0 @@
|
||||
name: Build Nix Docker Image
|
||||
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- "**.py"
|
||||
- "**.html"
|
||||
- "**.css"
|
||||
- "**.yaml"
|
||||
- "**.nix"
|
||||
branches:
|
||||
- main
|
||||
|
||||
env:
|
||||
DOCKER_TAG: ${{ secrets.DOCKER_HUB_USERNAME }}/audiobookrequest
|
||||
|
||||
jobs:
|
||||
website:
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- os: ubuntu-24.04
|
||||
arch: linux/amd64
|
||||
- os: ubuntu-24.04-arm
|
||||
arch: linux/arm64
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Install Nix
|
||||
uses: DeterminateSystems/nix-installer-action@main
|
||||
- name: Enable magic Nix cache
|
||||
uses: DeterminateSystems/flakehub-cache-action@main
|
||||
- name: Set version
|
||||
run: |
|
||||
# if [ "${{ github.event_name }}" == "release" ]; then
|
||||
# VERSION="${{ github.event.release.tag_name }}"
|
||||
# echo $VERSION > static/version
|
||||
# else
|
||||
github_sha_hash=${{ github.sha }}
|
||||
echo nix-test:${github_sha_hash:0:7} > static/version
|
||||
# fi
|
||||
- name: Build Docker image using Nix
|
||||
run: nix build ".#docker"
|
||||
|
||||
- name: Load image
|
||||
run: |
|
||||
export IMAGE_TAG=$(docker load < result | grep -Po 'Loaded image: \K.*')
|
||||
echo "Loaded image ${IMAGE_TAG}"
|
||||
echo "IMAGE_TAG=${IMAGE_TAG}" >> $GITHUB_ENV
|
||||
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_HUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}
|
||||
|
||||
- name: Push image
|
||||
run: |
|
||||
# if [ "${{ github.event_name }}" == "release" ]; then
|
||||
# VERSION="${{ github.event.release.tag_name }}"
|
||||
# MAJOR=$(echo $VERSION | cut -d. -f1)
|
||||
# MINOR=$(echo $VERSION | cut -d. -f2)
|
||||
# PATCH=$(echo $VERSION | cut -d. -f3)
|
||||
# docker tag $IMAGE_TAG "${DOCKER_TAG}:$VERSION"
|
||||
# docker tag $IMAGE_TAG "${DOCKER_TAG}:$MAJOR.$MINOR"
|
||||
# docker tag $IMAGE_TAG "${DOCKER_TAG}:$MAJOR"
|
||||
# docker tag $IMAGE_TAG "${DOCKER_TAG}:latest"
|
||||
# docker push "${DOCKER_TAG}:$VERSION"
|
||||
# docker push "${DOCKER_TAG}:$MAJOR.$MINOR"
|
||||
# docker push "${DOCKER_TAG}:$MAJOR"
|
||||
# docker push "${DOCKER_TAG}:latest"
|
||||
# else
|
||||
docker tag $IMAGE_TAG "${DOCKER_TAG}:nix-test"
|
||||
docker push "${DOCKER_TAG}:nix-test"
|
||||
# fi
|
||||
+1
-1
@@ -19,7 +19,7 @@ if config.config_file_name is not None:
|
||||
# for 'autogenerate' support
|
||||
# from myapp import mymodel
|
||||
# target_metadata = mymodel.Base.metadata
|
||||
target_metadata = models.BaseModel.metadata
|
||||
target_metadata = models.BaseSQLModel.metadata
|
||||
|
||||
# other values from the config, defined by the needs of env.py,
|
||||
# can be acquired:
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
from typing import cast
|
||||
import asyncio
|
||||
import time
|
||||
from datetime import datetime
|
||||
@@ -49,7 +50,7 @@ def clear_old_book_caches(session: Session):
|
||||
col(BookRequest.updated_at) < datetime.fromtimestamp(time.time() - REFETCH_TTL),
|
||||
col(BookRequest.user_username).is_(None),
|
||||
)
|
||||
result: CursorResult = session.execute(delete_query) # type: ignore[reportDeprecated]
|
||||
result = cast(CursorResult, session.execute(delete_query))
|
||||
session.commit()
|
||||
logger.debug("Cleared old book caches", rowcount=result.rowcount)
|
||||
|
||||
@@ -58,7 +59,7 @@ def get_region_from_settings() -> audible_region_type:
|
||||
region = Settings().app.default_region
|
||||
if region not in audible_regions:
|
||||
return "us"
|
||||
return region
|
||||
return cast(audible_region_type, region)
|
||||
|
||||
|
||||
async def _get_audnexus_book(
|
||||
|
||||
@@ -82,7 +82,7 @@ def create_valued_configuration(
|
||||
if not isinstance(_value, IndexerConfiguration):
|
||||
logger.debug("Skipping key", key=key)
|
||||
continue
|
||||
value: IndexerConfiguration[Any] = _value # pyright: ignore[reportUnknownVariableType]
|
||||
value: IndexerConfiguration[Any] = _value
|
||||
|
||||
config_value = indexer_configuration_cache.get(session, key)
|
||||
if config_value is None:
|
||||
|
||||
+13
-16
@@ -1,15 +1,14 @@
|
||||
# pyright: reportUnknownVariableType=false
|
||||
from pydantic import ConfigDict, BaseModel
|
||||
import json
|
||||
import uuid
|
||||
from datetime import datetime
|
||||
from enum import Enum
|
||||
from typing import Annotated, Literal, Optional, Union
|
||||
|
||||
import pydantic
|
||||
from sqlmodel import JSON, Column, DateTime, Field, SQLModel, UniqueConstraint, func
|
||||
|
||||
|
||||
class BaseModel(SQLModel):
|
||||
class BaseSQLModel(SQLModel):
|
||||
pass
|
||||
|
||||
|
||||
@@ -19,7 +18,7 @@ class GroupEnum(str, Enum):
|
||||
admin = "admin"
|
||||
|
||||
|
||||
class User(BaseModel, table=True):
|
||||
class User(BaseSQLModel, table=True):
|
||||
username: str = Field(primary_key=True)
|
||||
password: str
|
||||
group: GroupEnum = Field(
|
||||
@@ -60,7 +59,7 @@ class User(BaseModel, table=True):
|
||||
return self.username == username
|
||||
|
||||
|
||||
class BaseBook(BaseModel):
|
||||
class BaseBook(BaseSQLModel):
|
||||
asin: str
|
||||
title: str
|
||||
subtitle: Optional[str]
|
||||
@@ -114,11 +113,10 @@ class BookRequest(BaseBook, table=True):
|
||||
UniqueConstraint("asin", "user_username", name="unique_asin_user"),
|
||||
)
|
||||
|
||||
class Config: # pyright: ignore[reportIncompatibleVariableOverride]
|
||||
arbitrary_types_allowed = True
|
||||
model_config = ConfigDict(arbitrary_types_allowed=True)
|
||||
|
||||
|
||||
class ManualBookRequest(BaseModel, table=True):
|
||||
class ManualBookRequest(BaseSQLModel, table=True):
|
||||
id: uuid.UUID = Field(default_factory=uuid.uuid4, primary_key=True)
|
||||
user_username: str = Field(foreign_key="user.username", ondelete="CASCADE")
|
||||
title: str
|
||||
@@ -138,11 +136,10 @@ class ManualBookRequest(BaseModel, table=True):
|
||||
)
|
||||
downloaded: bool = False
|
||||
|
||||
class Config: # pyright: ignore[reportIncompatibleVariableOverride]
|
||||
arbitrary_types_allowed = True
|
||||
model_config = ConfigDict(arbitrary_types_allowed=True)
|
||||
|
||||
|
||||
class BookMetadata(BaseModel):
|
||||
class BookMetadata(BaseSQLModel):
|
||||
"""extra metadata that can be added to sources to better rank them"""
|
||||
|
||||
title: Optional[str] = None
|
||||
@@ -152,7 +149,7 @@ class BookMetadata(BaseModel):
|
||||
filetype: Optional[str] = None
|
||||
|
||||
|
||||
class BaseSource(BaseModel):
|
||||
class BaseSource(BaseSQLModel):
|
||||
guid: str
|
||||
indexer_id: int
|
||||
indexer: str
|
||||
@@ -187,14 +184,14 @@ ProwlarrSource = Annotated[
|
||||
]
|
||||
|
||||
|
||||
class Indexer(pydantic.BaseModel, frozen=True):
|
||||
class Indexer(BaseModel, frozen=True):
|
||||
id: int
|
||||
name: str
|
||||
enable: bool
|
||||
privacy: str
|
||||
|
||||
|
||||
class Config(BaseModel, table=True):
|
||||
class Config(BaseSQLModel, table=True):
|
||||
key: str = Field(primary_key=True)
|
||||
value: str
|
||||
|
||||
@@ -210,7 +207,7 @@ class NotificationBodyTypeEnum(str, Enum):
|
||||
json = "json"
|
||||
|
||||
|
||||
class Notification(BaseModel, table=True):
|
||||
class Notification(BaseSQLModel, table=True):
|
||||
id: uuid.UUID = Field(default_factory=uuid.uuid4, primary_key=True)
|
||||
name: str
|
||||
url: str
|
||||
@@ -225,7 +222,7 @@ class Notification(BaseModel, table=True):
|
||||
return json.dumps(self.headers)
|
||||
|
||||
|
||||
class APIKey(BaseModel, table=True):
|
||||
class APIKey(BaseSQLModel, table=True):
|
||||
id: uuid.UUID = Field(default_factory=uuid.uuid4, primary_key=True)
|
||||
user_username: str = Field(foreign_key="user.username", ondelete="CASCADE")
|
||||
name: str
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
import asyncio
|
||||
from types import CoroutineType
|
||||
from typing import Any
|
||||
|
||||
from app.internal.indexers.abstract import SessionContainer
|
||||
from app.internal.indexers.indexer_util import get_indexer_contexts
|
||||
@@ -24,7 +22,7 @@ async def edit_source_metadata(
|
||||
if exc:
|
||||
logger.error("Failed to setup indexer", error=str(exc))
|
||||
|
||||
coros: list[CoroutineType[Any, Any, None]] = []
|
||||
coros = []
|
||||
for source in sources:
|
||||
for context in contexts:
|
||||
if await context.indexer.is_matching_source(source, container):
|
||||
|
||||
@@ -81,7 +81,7 @@ class CompareSource:
|
||||
quality_range = quality_config.get_range(
|
||||
self.session, "quality_unknown_audio"
|
||||
)
|
||||
case "unknown":
|
||||
case "unknown" | _:
|
||||
quality_range = quality_config.get_range(
|
||||
self.session, "quality_unknown"
|
||||
)
|
||||
@@ -262,7 +262,7 @@ def fuzzy_author_narrator_match(
|
||||
return 0
|
||||
score = 0
|
||||
for book_person in book_people:
|
||||
best_match = 0
|
||||
best_match = 0.0
|
||||
for source_person in source_people:
|
||||
match_score = fuzz.token_set_ratio(
|
||||
book_person, source_person, processor=utils.default_process
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
# pyright: basic
|
||||
|
||||
import os
|
||||
from collections import defaultdict
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ from sqlmodel import Session
|
||||
from app.internal.auth.authentication import APIKeyAuth, DetailedUser
|
||||
from app.internal.indexers.abstract import SessionContainer
|
||||
from app.internal.indexers.indexer_util import get_indexer_contexts
|
||||
from app.internal.models import BaseModel, GroupEnum
|
||||
from app.internal.models import BaseSQLModel, GroupEnum
|
||||
from app.routers.settings.indexers import update_single_indexer
|
||||
from app.util.connection import get_connection
|
||||
from app.util.db import get_session
|
||||
@@ -48,7 +48,7 @@ async def update_indexer(
|
||||
return Response(status_code=204)
|
||||
|
||||
|
||||
class StringConfigurationResponse(BaseModel):
|
||||
class StringConfigurationResponse(BaseSQLModel):
|
||||
name: str
|
||||
description: Optional[str] = None
|
||||
default: Optional[str] = None
|
||||
|
||||
+2
-2
@@ -89,7 +89,7 @@ async def login(
|
||||
redirect_uri=auth_redirect_uri,
|
||||
)
|
||||
|
||||
state = jwt.encode( # pyright: ignore[reportUnknownMemberType]
|
||||
state = jwt.encode(
|
||||
{"redirect_uri": redirect_uri},
|
||||
auth_config.get_auth_secret(session),
|
||||
algorithm="HS256",
|
||||
@@ -247,7 +247,7 @@ async def login_oidc(
|
||||
request.session["exp"] = expires
|
||||
|
||||
if state:
|
||||
decoded = jwt.decode( # pyright: ignore[reportUnknownMemberType]
|
||||
decoded = jwt.decode(
|
||||
state,
|
||||
auth_config.get_auth_secret(session),
|
||||
algorithms=["HS256"],
|
||||
|
||||
+2
-1
@@ -34,7 +34,8 @@ etag_cache: dict[PathLike[str] | str, str] = {}
|
||||
def add_cache_headers(func: Callable[..., FileResponse]):
|
||||
def wrapper(v: str):
|
||||
file = func()
|
||||
if not (etag := etag_cache.get(file.path)) or Settings().app.debug:
|
||||
etag = etag_cache.get(file.path)
|
||||
if not etag or Settings().app.debug:
|
||||
with open(file.path, "rb") as f:
|
||||
etag = hashlib.sha1(f.read(), usedforsecurity=False).hexdigest()
|
||||
etag_cache[file.path] = etag
|
||||
|
||||
@@ -4,7 +4,7 @@ from contextlib import asynccontextmanager
|
||||
from typing import Annotated, Any, Literal, Mapping, Optional, cast
|
||||
|
||||
from aiohttp import ClientSession
|
||||
from apscheduler.schedulers.asyncio import AsyncIOScheduler # pyright: ignore[reportMissingTypeStubs]
|
||||
from apscheduler.schedulers.asyncio import AsyncIOScheduler
|
||||
from fastapi import APIRouter, Depends, FastAPI, Form, Request, Security
|
||||
from sqlmodel import Session
|
||||
|
||||
@@ -39,10 +39,10 @@ async def check_indexer_file_changes():
|
||||
@asynccontextmanager
|
||||
async def lifespan(app: FastAPI):
|
||||
scheduler = AsyncIOScheduler()
|
||||
scheduler.add_job(check_indexer_file_changes, "interval", seconds=15) # pyright: ignore[reportUnknownMemberType]
|
||||
scheduler.start() # pyright: ignore[reportUnknownMemberType]
|
||||
scheduler.add_job(check_indexer_file_changes, "interval", seconds=15)
|
||||
scheduler.start()
|
||||
yield
|
||||
scheduler.shutdown() # pyright: ignore[reportUnknownMemberType]
|
||||
scheduler.shutdown()
|
||||
|
||||
|
||||
router = APIRouter(prefix="/indexers", lifespan=lifespan)
|
||||
|
||||
+4
-8
@@ -39,12 +39,10 @@ class StringConfigCache[L: str](ABC):
|
||||
_cache: dict[L, str] = {}
|
||||
|
||||
@overload
|
||||
def get(self, session: Session, key: L) -> Optional[str]:
|
||||
pass
|
||||
def get(self, session: Session, key: L) -> Optional[str]: ...
|
||||
|
||||
@overload
|
||||
def get(self, session: Session, key: L, default: str) -> str:
|
||||
pass
|
||||
def get(self, session: Session, key: L, default: str) -> str: ...
|
||||
|
||||
def get(
|
||||
self, session: Session, key: L, default: Optional[str] = None
|
||||
@@ -75,12 +73,10 @@ class StringConfigCache[L: str](ABC):
|
||||
del self._cache[key]
|
||||
|
||||
@overload
|
||||
def get_int(self, session: Session, key: L) -> Optional[int]:
|
||||
pass
|
||||
def get_int(self, session: Session, key: L) -> Optional[int]: ...
|
||||
|
||||
@overload
|
||||
def get_int(self, session: Session, key: L, default: int) -> int:
|
||||
pass
|
||||
def get_int(self, session: Session, key: L, default: int) -> int: ...
|
||||
|
||||
def get_int(
|
||||
self, session: Session, key: L, default: Optional[int] = None
|
||||
|
||||
+2
-2
@@ -18,7 +18,7 @@ else:
|
||||
def get_session():
|
||||
with Session(engine) as session:
|
||||
if not Settings().db.use_postgres:
|
||||
session.execute(text("PRAGMA foreign_keys=ON")) # pyright: ignore[reportDeprecated]
|
||||
session.execute(text("PRAGMA foreign_keys=ON"))
|
||||
yield session
|
||||
|
||||
|
||||
@@ -27,5 +27,5 @@ def get_session():
|
||||
def open_session():
|
||||
with Session(engine) as session:
|
||||
if not Settings().db.use_postgres:
|
||||
session.execute(text("PRAGMA foreign_keys=ON")) # pyright: ignore[reportDeprecated]
|
||||
session.execute(text("PRAGMA foreign_keys=ON"))
|
||||
yield session
|
||||
|
||||
+23
-10
@@ -1,3 +1,5 @@
|
||||
from jinja2_htmlmin import minify_loader
|
||||
from jinja2 import Environment, FileSystemLoader
|
||||
from typing import Any, Mapping, overload
|
||||
|
||||
import markdown
|
||||
@@ -8,22 +10,33 @@ from starlette.background import BackgroundTask
|
||||
from app.internal.auth.authentication import DetailedUser
|
||||
from app.internal.env_settings import Settings
|
||||
|
||||
templates = Jinja2Blocks(directory="templates")
|
||||
templates.env.filters["zfill"] = lambda val, num: str(val).zfill(num) # pyright: ignore[reportUnknownLambdaType,reportUnknownMemberType,reportUnknownArgumentType]
|
||||
templates.env.filters["toJSstring"] = ( # pyright: ignore[reportUnknownLambdaType,reportUnknownMemberType,reportUnknownArgumentType]
|
||||
lambda val: f"'{str(val).replace("'", "\\'").replace('\n', '\\n')}'" # pyright: ignore[reportUnknownLambdaType,reportUnknownMemberType,reportUnknownArgumentType]
|
||||
templates = Jinja2Blocks(
|
||||
env=Environment(
|
||||
loader=minify_loader(
|
||||
FileSystemLoader("templates"),
|
||||
remove_comments=True, # pyrefly: ignore[bad-argument-type]
|
||||
remove_empty_space=True, # pyrefly: ignore[bad-argument-type]
|
||||
remove_all_empty_space=True, # pyrefly: ignore[bad-argument-type]
|
||||
reduce_boolean_attributes=True, # pyrefly: ignore[bad-argument-type]
|
||||
)
|
||||
)
|
||||
)
|
||||
templates.env.globals["vars"] = vars # pyright: ignore[reportUnknownMemberType]
|
||||
templates.env.globals["getattr"] = getattr # pyright: ignore[reportUnknownMemberType]
|
||||
templates.env.globals["version"] = Settings().app.version # pyright: ignore[reportUnknownMemberType]
|
||||
templates.env.globals["json_regexp"] = ( # pyright: ignore[reportUnknownMemberType]
|
||||
|
||||
templates.env.filters["zfill"] = lambda val, num: str(val).zfill(num)
|
||||
templates.env.filters["toJSstring"] = (
|
||||
lambda val: f"'{str(val).replace("'", "\\'").replace('\n', '\\n')}'"
|
||||
)
|
||||
templates.env.globals["vars"] = vars
|
||||
templates.env.globals["getattr"] = getattr
|
||||
templates.env.globals["version"] = Settings().app.version
|
||||
templates.env.globals["json_regexp"] = (
|
||||
r'^\{\s*(?:"[^"\\]*(?:\\.[^"\\]*)*"\s*:\s*"[^"\\]*(?:\\.[^"\\]*)*"\s*(?:,\s*"[^"\\]*(?:\\.[^"\\]*)*"\s*:\s*"[^"\\]*(?:\\.[^"\\]*)*"\s*)*)?\}$'
|
||||
)
|
||||
templates.env.globals["base_url"] = Settings().app.base_url.rstrip("/") # pyright: ignore[reportUnknownMemberType]
|
||||
templates.env.globals["base_url"] = Settings().app.base_url.rstrip("/")
|
||||
|
||||
with open("CHANGELOG.md", "r") as file:
|
||||
changelog_content = file.read()
|
||||
templates.env.globals["changelog"] = markdown.markdown(changelog_content) # pyright: ignore[reportUnknownMemberType]
|
||||
templates.env.globals["changelog"] = markdown.markdown(changelog_content)
|
||||
|
||||
|
||||
@overload
|
||||
|
||||
@@ -21,7 +21,7 @@ tailwind: node_modules
|
||||
tailwindcss -i static/tw.css -o static/globals.css --watch
|
||||
|
||||
types:
|
||||
uv run pyright app
|
||||
uv run pyrefly check
|
||||
uv run djlint templates
|
||||
uv run ruff format --check app
|
||||
uv run alembic check
|
||||
|
||||
+13
-10
@@ -30,6 +30,7 @@ dependencies = [
|
||||
"markdown>=3.8.2",
|
||||
"apscheduler>=3.11.0",
|
||||
"psycopg2-binary>=2.9.10",
|
||||
"jinja2-htmlmin>=1.0.1",
|
||||
]
|
||||
|
||||
# setuptools by default expects a "src" folder structure
|
||||
@@ -39,18 +40,20 @@ where = ["."]
|
||||
[tool.uv]
|
||||
package = false
|
||||
|
||||
[tool.pyright]
|
||||
include = ["**/*.py"]
|
||||
exclude = ["**/__pycache__", "**/.venv", "**/.direnv"]
|
||||
ignore = []
|
||||
|
||||
typeCheckingMode = "strict"
|
||||
reportUnknownParameterType = true
|
||||
reportMissingParameterType = true
|
||||
|
||||
[tool.djlint]
|
||||
profile = "jinja"
|
||||
ignore = "H021"
|
||||
|
||||
[tool.pyrefly]
|
||||
project-includes = ["app"]
|
||||
|
||||
[tool.pyrefly.errors]
|
||||
deprecated = false
|
||||
|
||||
[dependency-groups]
|
||||
dev = ["djlint", "pyright", "ruff"]
|
||||
dev = [
|
||||
"djlint",
|
||||
"pyrefly>=0.46.2",
|
||||
"ruff>=0.14.10",
|
||||
"ty>=0.0.8",
|
||||
]
|
||||
|
||||
@@ -223,6 +223,7 @@ dependencies = [
|
||||
{ name = "itsdangerous" },
|
||||
{ name = "jinja2" },
|
||||
{ name = "jinja2-fragments" },
|
||||
{ name = "jinja2-htmlmin" },
|
||||
{ name = "markdown" },
|
||||
{ name = "psycopg2-binary" },
|
||||
{ name = "pydantic" },
|
||||
@@ -244,8 +245,9 @@ dependencies = [
|
||||
[package.dev-dependencies]
|
||||
dev = [
|
||||
{ name = "djlint" },
|
||||
{ name = "pyright" },
|
||||
{ name = "pyrefly" },
|
||||
{ name = "ruff" },
|
||||
{ name = "ty" },
|
||||
]
|
||||
|
||||
[package.metadata]
|
||||
@@ -259,6 +261,7 @@ requires-dist = [
|
||||
{ name = "itsdangerous" },
|
||||
{ name = "jinja2" },
|
||||
{ name = "jinja2-fragments" },
|
||||
{ name = "jinja2-htmlmin", specifier = ">=1.0.1" },
|
||||
{ name = "markdown", specifier = ">=3.8.2" },
|
||||
{ name = "psycopg2-binary", specifier = ">=2.9.10" },
|
||||
{ name = "pydantic" },
|
||||
@@ -280,8 +283,9 @@ requires-dist = [
|
||||
[package.metadata.requires-dev]
|
||||
dev = [
|
||||
{ name = "djlint" },
|
||||
{ name = "pyright" },
|
||||
{ name = "ruff" },
|
||||
{ name = "pyrefly", specifier = ">=0.46.2" },
|
||||
{ name = "ruff", specifier = ">=0.14.10" },
|
||||
{ name = "ty", specifier = ">=0.0.8" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -638,6 +642,14 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/04/4b/29cac41a4d98d144bf5f6d33995617b185d14b22401f75ca86f384e87ff1/h11-0.16.0-py3-none-any.whl", hash = "sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86", size = 37515, upload-time = "2025-04-24T03:35:24.344Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "htmlmin2"
|
||||
version = "0.1.13"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/be/31/a76f4bfa885f93b8167cb4c85cf32b54d1f64384d0b897d45bc6d19b7b45/htmlmin2-0.1.13-py3-none-any.whl", hash = "sha256:75609f2a42e64f7ce57dbff28a39890363bde9e7e5885db633317efbdf8c79a2", size = 34486, upload-time = "2023-03-14T21:28:30.388Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "httpcore"
|
||||
version = "1.0.9"
|
||||
@@ -730,6 +742,19 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/e2/05/2a29edac68484f1e1171d257773f73b436a240bd2640ab66d27bfadb69ae/jinja2_fragments-1.9.0-py3-none-any.whl", hash = "sha256:69b91e7e2f325ea7e391e36a9abcc572db967e2bf3afd35f74fcb78fc9f8c6c5", size = 14433, upload-time = "2025-04-20T22:46:48.778Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "jinja2-htmlmin"
|
||||
version = "1.0.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "htmlmin2" },
|
||||
{ name = "jinja2" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/1a/ef/d642475f0cc66c89f3347924a23a173751dc160ba44269e76db48a89f2a7/jinja2_htmlmin-1.0.1.tar.gz", hash = "sha256:c53398ff12799a79ab75e471e9c26be9c837d1c10103da308280bd96c45588af", size = 21088, upload-time = "2025-07-29T17:08:43.698Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/13/6f/89b2029eb311bcab200d875599ab6594e186d865c181d08b686f60d3d26e/jinja2_htmlmin-1.0.1-py3-none-any.whl", hash = "sha256:b9c6c43e88443a238e3796054c4a54cd5bd755dfc3c65b775910813988a89da3", size = 4247, upload-time = "2025-07-29T17:08:42.595Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "jsbeautifier"
|
||||
version = "1.15.4"
|
||||
@@ -895,15 +920,6 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/fd/69/b547032297c7e63ba2af494edba695d781af8a0c6e89e4d06cf848b21d80/multidict-6.6.4-py3-none-any.whl", hash = "sha256:27d8f8e125c07cb954e54d75d04905a9bba8a439c1d84aca94949d4d03d8601c", size = 12313, upload-time = "2025-08-11T12:08:46.891Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nodeenv"
|
||||
version = "1.9.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/43/16/fc88b08840de0e0a72a2f9d8c6bae36be573e475a6326ae854bcc549fc45/nodeenv-1.9.1.tar.gz", hash = "sha256:6ec12890a2dab7946721edbfbcd91f3319c6ccc9aec47be7c7e6b7011ee6645f", size = 47437, upload-time = "2024-06-04T18:44:11.171Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/d2/1d/1b658dbd2b9fa9c4c9f32accbfc0205d532c8c6194dc0f2a4c0428e7128a/nodeenv-1.9.1-py2.py3-none-any.whl", hash = "sha256:ba11c9782d29c27c70ffbdda2d7415098754709be8a7056d79a737cd901155c9", size = 22314, upload-time = "2024-06-04T18:44:08.352Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pathspec"
|
||||
version = "0.12.1"
|
||||
@@ -1105,16 +1121,19 @@ wheels = [
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pyright"
|
||||
version = "1.1.403"
|
||||
name = "pyrefly"
|
||||
version = "0.46.2"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "nodeenv" },
|
||||
{ name = "typing-extensions" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/fe/f6/35f885264ff08c960b23d1542038d8da86971c5d8c955cfab195a4f672d7/pyright-1.1.403.tar.gz", hash = "sha256:3ab69b9f41c67fb5bbb4d7a36243256f0d549ed3608678d381d5f51863921104", size = 3913526, upload-time = "2025-07-09T07:15:52.882Z" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/a5/60/40ba98bed6cdc375d80d1be92b0980fb9425102993246dddd7a5cd9db9e2/pyrefly-0.46.2.tar.gz", hash = "sha256:d680c411948e41fcfc1d37f7c7a3d566c52e226d48eef0b1d4c922ddb0465abb", size = 4762179, upload-time = "2025-12-29T16:44:52.683Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/49/b6/b04e5c2f41a5ccad74a1a4759da41adb20b4bc9d59a5e08d29ba60084d07/pyright-1.1.403-py3-none-any.whl", hash = "sha256:c0eeca5aa76cbef3fcc271259bbd785753c7ad7bcac99a9162b4c4c7daed23b3", size = 5684504, upload-time = "2025-07-09T07:15:50.958Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/dc/05/5fa9cd08d9ed6f791158707cd7e860f283e6a44fddea1d5abb9dcb3a153c/pyrefly-0.46.2-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:94090428807796247b42f2c5840cff4d3262e1a64dcc23ba9d56cd0708e328b0", size = 11642476, upload-time = "2025-12-29T16:44:33.386Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/57/fd/d4c73518cbf8629c335e2ef6fe54d75d12782cb882d883c1fc964679f0c8/pyrefly-0.46.2-py3-none-macosx_11_0_arm64.whl", hash = "sha256:1dbe54b8ef0a3697614d3a622cd15eb642415bed4c72540372cbcbfb5ff0119a", size = 11262304, upload-time = "2025-12-29T16:44:35.823Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/01/ff/9f1056e2437b7067d950198312c3c26ead6c6bae57d14a2ba075bae82b90/pyrefly-0.46.2-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f225303ff76ad6b581abb566c160fbc64bcb9cf4260151c4897853485fab619b", size = 31476614, upload-time = "2025-12-29T16:44:38.4Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/8d/d4/302d853a3b34f8eec57ab6417c6b03d3f496fcb965fcf92893d5c6ff9179/pyrefly-0.46.2-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:81903be4bcdca9e1f24b7ad0a9768cd8094f74847c5f67ceec731bd2e933e3be", size = 33695293, upload-time = "2025-12-29T16:44:40.994Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/af/2c/458e271a63f5ddeb407b16277d1520425691f87627bce5cafac926339e3f/pyrefly-0.46.2-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a4bce05c26954fea7aa43ce51675ade8ea8770fe187443833e8751637864ebed", size = 34734729, upload-time = "2025-12-29T16:44:43.628Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/1d/e6/ac334eb16962f3da390859e70461be9bc8ebb1f7bdb6d11a99e846263d1e/pyrefly-0.46.2-py3-none-win32.whl", hash = "sha256:a95a95a53e453f381e4cf4da5cdc67b21852e9b13fafd71f97dcdc008e01b277", size = 10725298, upload-time = "2025-12-29T16:44:46.254Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c2/e0/96ca0587e76c08eb8c917b44369d953bf22e255f43568bf612811676ff69/pyrefly-0.46.2-py3-none-win_amd64.whl", hash = "sha256:e75d43f7149bc5d472edfa9071a95f51b2cd3024ff6d4808cddbcfbdfdd32d7a", size = 11417266, upload-time = "2025-12-29T16:44:48.212Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a1/ef/11687e55e5b3d92f9695c713d9f90af181c2a4376c032ec34650ea8a035d/pyrefly-0.46.2-py3-none-win_arm64.whl", hash = "sha256:1a467d24f33500d0bfc8fe8f8fe3d1da5d9e4ad9637fc49d4f83b3f2cef7d8d6", size = 10962676, upload-time = "2025-12-29T16:44:50.374Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1339,28 +1358,28 @@ wheels = [
|
||||
|
||||
[[package]]
|
||||
name = "ruff"
|
||||
version = "0.12.9"
|
||||
version = "0.14.10"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/4a/45/2e403fa7007816b5fbb324cb4f8ed3c7402a927a0a0cb2b6279879a8bfdc/ruff-0.12.9.tar.gz", hash = "sha256:fbd94b2e3c623f659962934e52c2bea6fc6da11f667a427a368adaf3af2c866a", size = 5254702, upload-time = "2025-08-14T16:08:55.2Z" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/57/08/52232a877978dd8f9cf2aeddce3e611b40a63287dfca29b6b8da791f5e8d/ruff-0.14.10.tar.gz", hash = "sha256:9a2e830f075d1a42cd28420d7809ace390832a490ed0966fe373ba288e77aaf4", size = 5859763, upload-time = "2025-12-18T19:28:57.98Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/ad/20/53bf098537adb7b6a97d98fcdebf6e916fcd11b2e21d15f8c171507909cc/ruff-0.12.9-py3-none-linux_armv6l.whl", hash = "sha256:fcebc6c79fcae3f220d05585229463621f5dbf24d79fdc4936d9302e177cfa3e", size = 11759705, upload-time = "2025-08-14T16:08:12.968Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/20/4d/c764ee423002aac1ec66b9d541285dd29d2c0640a8086c87de59ebbe80d5/ruff-0.12.9-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:aed9d15f8c5755c0e74467731a007fcad41f19bcce41cd75f768bbd687f8535f", size = 12527042, upload-time = "2025-08-14T16:08:16.54Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/8b/45/cfcdf6d3eb5fc78a5b419e7e616d6ccba0013dc5b180522920af2897e1be/ruff-0.12.9-py3-none-macosx_11_0_arm64.whl", hash = "sha256:5b15ea354c6ff0d7423814ba6d44be2807644d0c05e9ed60caca87e963e93f70", size = 11724457, upload-time = "2025-08-14T16:08:18.686Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/72/e6/44615c754b55662200c48bebb02196dbb14111b6e266ab071b7e7297b4ec/ruff-0.12.9-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d596c2d0393c2502eaabfef723bd74ca35348a8dac4267d18a94910087807c53", size = 11949446, upload-time = "2025-08-14T16:08:21.059Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/fd/d1/9b7d46625d617c7df520d40d5ac6cdcdf20cbccb88fad4b5ecd476a6bb8d/ruff-0.12.9-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:1b15599931a1a7a03c388b9c5df1bfa62be7ede6eb7ef753b272381f39c3d0ff", size = 11566350, upload-time = "2025-08-14T16:08:23.433Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/59/20/b73132f66f2856bc29d2d263c6ca457f8476b0bbbe064dac3ac3337a270f/ruff-0.12.9-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3d02faa2977fb6f3f32ddb7828e212b7dd499c59eb896ae6c03ea5c303575756", size = 13270430, upload-time = "2025-08-14T16:08:25.837Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a2/21/eaf3806f0a3d4c6be0a69d435646fba775b65f3f2097d54898b0fd4bb12e/ruff-0.12.9-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:17d5b6b0b3a25259b69ebcba87908496e6830e03acfb929ef9fd4c58675fa2ea", size = 14264717, upload-time = "2025-08-14T16:08:27.907Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d2/82/1d0c53bd37dcb582b2c521d352fbf4876b1e28bc0d8894344198f6c9950d/ruff-0.12.9-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:72db7521860e246adbb43f6ef464dd2a532ef2ef1f5dd0d470455b8d9f1773e0", size = 13684331, upload-time = "2025-08-14T16:08:30.352Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/3b/2f/1c5cf6d8f656306d42a686f1e207f71d7cebdcbe7b2aa18e4e8a0cb74da3/ruff-0.12.9-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a03242c1522b4e0885af63320ad754d53983c9599157ee33e77d748363c561ce", size = 12739151, upload-time = "2025-08-14T16:08:32.55Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/47/09/25033198bff89b24d734e6479e39b1968e4c992e82262d61cdccaf11afb9/ruff-0.12.9-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9fc83e4e9751e6c13b5046d7162f205d0a7bac5840183c5beebf824b08a27340", size = 12954992, upload-time = "2025-08-14T16:08:34.816Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/52/8e/d0dbf2f9dca66c2d7131feefc386523404014968cd6d22f057763935ab32/ruff-0.12.9-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:881465ed56ba4dd26a691954650de6ad389a2d1fdb130fe51ff18a25639fe4bb", size = 12899569, upload-time = "2025-08-14T16:08:36.852Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a0/bd/b614d7c08515b1428ed4d3f1d4e3d687deffb2479703b90237682586fa66/ruff-0.12.9-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:43f07a3ccfc62cdb4d3a3348bf0588358a66da756aa113e071b8ca8c3b9826af", size = 11751983, upload-time = "2025-08-14T16:08:39.314Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/58/d6/383e9f818a2441b1a0ed898d7875f11273f10882f997388b2b51cb2ae8b5/ruff-0.12.9-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:07adb221c54b6bba24387911e5734357f042e5669fa5718920ee728aba3cbadc", size = 11538635, upload-time = "2025-08-14T16:08:41.297Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/20/9c/56f869d314edaa9fc1f491706d1d8a47747b9d714130368fbd69ce9024e9/ruff-0.12.9-py3-none-musllinux_1_2_i686.whl", hash = "sha256:f5cd34fabfdea3933ab85d72359f118035882a01bff15bd1d2b15261d85d5f66", size = 12534346, upload-time = "2025-08-14T16:08:43.39Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/bd/4b/d8b95c6795a6c93b439bc913ee7a94fda42bb30a79285d47b80074003ee7/ruff-0.12.9-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:f6be1d2ca0686c54564da8e7ee9e25f93bdd6868263805f8c0b8fc6a449db6d7", size = 13017021, upload-time = "2025-08-14T16:08:45.889Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c7/c1/5f9a839a697ce1acd7af44836f7c2181cdae5accd17a5cb85fcbd694075e/ruff-0.12.9-py3-none-win32.whl", hash = "sha256:cc7a37bd2509974379d0115cc5608a1a4a6c4bff1b452ea69db83c8855d53f93", size = 11734785, upload-time = "2025-08-14T16:08:48.062Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/fa/66/cdddc2d1d9a9f677520b7cfc490d234336f523d4b429c1298de359a3be08/ruff-0.12.9-py3-none-win_amd64.whl", hash = "sha256:6fb15b1977309741d7d098c8a3cb7a30bc112760a00fb6efb7abc85f00ba5908", size = 12840654, upload-time = "2025-08-14T16:08:50.158Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ac/fd/669816bc6b5b93b9586f3c1d87cd6bc05028470b3ecfebb5938252c47a35/ruff-0.12.9-py3-none-win_arm64.whl", hash = "sha256:63c8c819739d86b96d500cce885956a1a48ab056bbcbc61b747ad494b2485089", size = 11949623, upload-time = "2025-08-14T16:08:52.233Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/60/01/933704d69f3f05ee16ef11406b78881733c186fe14b6a46b05cfcaf6d3b2/ruff-0.14.10-py3-none-linux_armv6l.whl", hash = "sha256:7a3ce585f2ade3e1f29ec1b92df13e3da262178df8c8bdf876f48fa0e8316c49", size = 13527080, upload-time = "2025-12-18T19:29:25.642Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/df/58/a0349197a7dfa603ffb7f5b0470391efa79ddc327c1e29c4851e85b09cc5/ruff-0.14.10-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:674f9be9372907f7257c51f1d4fc902cb7cf014b9980152b802794317941f08f", size = 13797320, upload-time = "2025-12-18T19:29:02.571Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/7b/82/36be59f00a6082e38c23536df4e71cdbc6af8d7c707eade97fcad5c98235/ruff-0.14.10-py3-none-macosx_11_0_arm64.whl", hash = "sha256:d85713d522348837ef9df8efca33ccb8bd6fcfc86a2cde3ccb4bc9d28a18003d", size = 12918434, upload-time = "2025-12-18T19:28:51.202Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a6/00/45c62a7f7e34da92a25804f813ebe05c88aa9e0c25e5cb5a7d23dd7450e3/ruff-0.14.10-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6987ebe0501ae4f4308d7d24e2d0fe3d7a98430f5adfd0f1fead050a740a3a77", size = 13371961, upload-time = "2025-12-18T19:29:04.991Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/40/31/a5906d60f0405f7e57045a70f2d57084a93ca7425f22e1d66904769d1628/ruff-0.14.10-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:16a01dfb7b9e4eee556fbfd5392806b1b8550c9b4a9f6acd3dbe6812b193c70a", size = 13275629, upload-time = "2025-12-18T19:29:21.381Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/3e/60/61c0087df21894cf9d928dc04bcd4fb10e8b2e8dca7b1a276ba2155b2002/ruff-0.14.10-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7165d31a925b7a294465fa81be8c12a0e9b60fb02bf177e79067c867e71f8b1f", size = 14029234, upload-time = "2025-12-18T19:29:00.132Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/44/84/77d911bee3b92348b6e5dab5a0c898d87084ea03ac5dc708f46d88407def/ruff-0.14.10-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:c561695675b972effb0c0a45db233f2c816ff3da8dcfbe7dfc7eed625f218935", size = 15449890, upload-time = "2025-12-18T19:28:53.573Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e9/36/480206eaefa24a7ec321582dda580443a8f0671fdbf6b1c80e9c3e93a16a/ruff-0.14.10-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4bb98fcbbc61725968893682fd4df8966a34611239c9fd07a1f6a07e7103d08e", size = 15123172, upload-time = "2025-12-18T19:29:23.453Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5c/38/68e414156015ba80cef5473d57919d27dfb62ec804b96180bafdeaf0e090/ruff-0.14.10-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f24b47993a9d8cb858429e97bdf8544c78029f09b520af615c1d261bf827001d", size = 14460260, upload-time = "2025-12-18T19:29:27.808Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b3/19/9e050c0dca8aba824d67cc0db69fb459c28d8cd3f6855b1405b3f29cc91d/ruff-0.14.10-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:59aabd2e2c4fd614d2862e7939c34a532c04f1084476d6833dddef4afab87e9f", size = 14229978, upload-time = "2025-12-18T19:29:11.32Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/51/eb/e8dd1dd6e05b9e695aa9dd420f4577debdd0f87a5ff2fedda33c09e9be8c/ruff-0.14.10-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:213db2b2e44be8625002dbea33bb9c60c66ea2c07c084a00d55732689d697a7f", size = 14338036, upload-time = "2025-12-18T19:29:09.184Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6a/12/f3e3a505db7c19303b70af370d137795fcfec136d670d5de5391e295c134/ruff-0.14.10-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:b914c40ab64865a17a9a5b67911d14df72346a634527240039eb3bd650e5979d", size = 13264051, upload-time = "2025-12-18T19:29:13.431Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/08/64/8c3a47eaccfef8ac20e0484e68e0772013eb85802f8a9f7603ca751eb166/ruff-0.14.10-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:1484983559f026788e3a5c07c81ef7d1e97c1c78ed03041a18f75df104c45405", size = 13283998, upload-time = "2025-12-18T19:29:06.994Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/12/84/534a5506f4074e5cc0529e5cd96cfc01bb480e460c7edf5af70d2bcae55e/ruff-0.14.10-py3-none-musllinux_1_2_i686.whl", hash = "sha256:c70427132db492d25f982fffc8d6c7535cc2fd2c83fc8888f05caaa248521e60", size = 13601891, upload-time = "2025-12-18T19:28:55.811Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/0d/1e/14c916087d8598917dbad9b2921d340f7884824ad6e9c55de948a93b106d/ruff-0.14.10-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:5bcf45b681e9f1ee6445d317ce1fa9d6cba9a6049542d1c3d5b5958986be8830", size = 14336660, upload-time = "2025-12-18T19:29:16.531Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f2/1c/d7b67ab43f30013b47c12b42d1acd354c195351a3f7a1d67f59e54227ede/ruff-0.14.10-py3-none-win32.whl", hash = "sha256:104c49fc7ab73f3f3a758039adea978869a918f31b73280db175b43a2d9b51d6", size = 13196187, upload-time = "2025-12-18T19:29:19.006Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/fb/9c/896c862e13886fae2af961bef3e6312db9ebc6adc2b156fe95e615dee8c1/ruff-0.14.10-py3-none-win_amd64.whl", hash = "sha256:466297bd73638c6bdf06485683e812db1c00c7ac96d4ddd0294a338c62fdc154", size = 14661283, upload-time = "2025-12-18T19:29:30.16Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/74/31/b0e29d572670dca3674eeee78e418f20bdf97fa8aa9ea71380885e175ca0/ruff-0.14.10-py3-none-win_arm64.whl", hash = "sha256:e51d046cf6dda98a4633b8a8a771451107413b0f07183b2bef03f075599e44e6", size = 13729839, upload-time = "2025-12-18T19:28:48.636Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1509,6 +1528,31 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/d0/30/dc54f88dd4a2b5dc8a0279bdd7270e735851848b762aeb1c1184ed1f6b14/tqdm-4.67.1-py3-none-any.whl", hash = "sha256:26445eca388f82e72884e0d580d5464cd801a3ea01e63e5601bdff9ba6a48de2", size = 78540, upload-time = "2024-11-24T20:12:19.698Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ty"
|
||||
version = "0.0.8"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/72/9d/59e955cc39206a0d58df5374808785c45ec2a8a2a230eb1638fbb4fe5c5d/ty-0.0.8.tar.gz", hash = "sha256:352ac93d6e0050763be57ad1e02087f454a842887e618ec14ac2103feac48676", size = 4828477, upload-time = "2025-12-29T13:50:07.193Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/69/2b/dd61f7e50a69c72f72c625d026e9ab64a0db62b2dd32e7426b520e2429c6/ty-0.0.8-py3-none-linux_armv6l.whl", hash = "sha256:a289d033c5576fa3b4a582b37d63395edf971cdbf70d2d2e6b8c95638d1a4fcd", size = 9853417, upload-time = "2025-12-29T13:50:08.979Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/90/72/3f1d3c64a049a388e199de4493689a51fc6aa5ff9884c03dea52b4966657/ty-0.0.8-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:788ea97dc8153a94e476c4d57b2551a9458f79c187c4aba48fcb81f05372924a", size = 9657890, upload-time = "2025-12-29T13:50:27.867Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/71/d1/08ac676bd536de3c2baba0deb60e67b3196683a2fabebfd35659d794b5e9/ty-0.0.8-py3-none-macosx_11_0_arm64.whl", hash = "sha256:1b5f1f3d3e230f35a29e520be7c3d90194a5229f755b721e9092879c00842d31", size = 9180129, upload-time = "2025-12-29T13:50:22.842Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/af/93/610000e2cfeea1875900f73a375ba917624b0a008d4b8a6c18c894c8dbbc/ty-0.0.8-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6da9ed377fbbcec0a3b60b2ca5fd30496e15068f47cef2344ba87923e78ba996", size = 9683517, upload-time = "2025-12-29T13:50:18.658Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/05/04/bef50ba7d8580b0140be597de5cc0ba9a63abe50d3f65560235f23658762/ty-0.0.8-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7d0a2bdce5e701d19eb8d46d9da0fe31340f079cecb7c438f5ac6897c73fc5ba", size = 9676279, upload-time = "2025-12-29T13:50:25.207Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/aa/b9/2aff1ef1f41b25898bc963173ae67fc8f04ca666ac9439a9c4e78d5cc0ff/ty-0.0.8-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ef9078799d26d3cc65366e02392e2b78f64f72911b599e80a8497d2ec3117ddb", size = 10073015, upload-time = "2025-12-29T13:50:35.422Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/df/0e/9feb6794b6ff0a157c3e6a8eb6365cbfa3adb9c0f7976e2abdc48615dd72/ty-0.0.8-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:54814ac39b4ab67cf111fc0a236818155cf49828976152378347a7678d30ee89", size = 10961649, upload-time = "2025-12-29T13:49:58.717Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f4/3b/faf7328b14f00408f4f65c9d01efe52e11b9bcc4a79e06187b370457b004/ty-0.0.8-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c4baf0a80398e8b6c68fa36ff85045a50ede1906cd4edb41fb4fab46d471f1d4", size = 10676190, upload-time = "2025-12-29T13:50:01.11Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/64/a5/cfeca780de7eeab7852c911c06a84615a174d23e9ae08aae42a645771094/ty-0.0.8-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ac8e23c3faefc579686799ef1649af8d158653169ad5c3a7df56b152781eeb67", size = 10438641, upload-time = "2025-12-29T13:50:29.664Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/0e/8d/8667c7e0ac9f13c461ded487c8d7350f440cd39ba866d0160a8e1b1efd6c/ty-0.0.8-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b558a647a073d0c25540aaa10f8947de826cb8757d034dd61ecf50ab8dbd77bf", size = 10214082, upload-time = "2025-12-29T13:50:31.531Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f8/11/e563229870e2c1d089e7e715c6c3b7605a34436dddf6f58e9205823020c2/ty-0.0.8-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:8c0104327bf480508bd81f320e22074477df159d9eff85207df39e9c62ad5e96", size = 9664364, upload-time = "2025-12-29T13:50:05.443Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b1/ad/05b79b778bf5237bcd7ee08763b226130aa8da872cbb151c8cfa2e886203/ty-0.0.8-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:496f1cb87261dd1a036a5609da80ee13de2e6ee4718a661bfa2afb91352fe528", size = 9679440, upload-time = "2025-12-29T13:50:11.289Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/12/b5/23ba887769c4a7b8abfd1b6395947dc3dcc87533fbf86379d3a57f87ae8f/ty-0.0.8-py3-none-musllinux_1_2_i686.whl", hash = "sha256:2c488031f92a075ae39d13ac6295fdce2141164ec38c5d47aa8dc24ee3afa37e", size = 9808201, upload-time = "2025-12-29T13:50:21.003Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f8/90/5a82ac0a0707db55376922aed80cd5fca6b2e6d6e9bcd8c286e6b43b4084/ty-0.0.8-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:90d6f08c5982fa3e802b8918a32e326153519077b827f91c66eea4913a86756a", size = 10313262, upload-time = "2025-12-29T13:50:03.306Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/14/f7/ff97f37f0a75db9495ddbc47738ec4339837867c4bfa145bdcfbd0d1eb2f/ty-0.0.8-py3-none-win32.whl", hash = "sha256:d7f460ad6fc9325e9cc8ea898949bbd88141b4609d1088d7ede02ce2ef06e776", size = 9254675, upload-time = "2025-12-29T13:50:33.35Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/af/51/eba5d83015e04630002209e3590c310a0ff1d26e1815af204a322617a42e/ty-0.0.8-py3-none-win_amd64.whl", hash = "sha256:1641fb8dedc3d2da43279d21c3c7c1f80d84eae5c264a1e8daa544458e433c19", size = 10131382, upload-time = "2025-12-29T13:50:13.719Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/38/1c/0d8454ff0f0f258737ecfe84f6e508729191d29663b404832f98fa5626b7/ty-0.0.8-py3-none-win_arm64.whl", hash = "sha256:ec74f022f315bede478ecae1277a01ab618e6500c1d68450d7883f5cd6ed554a", size = 9636374, upload-time = "2025-12-29T13:50:16.344Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "typer"
|
||||
version = "0.16.0"
|
||||
|
||||
Reference in New Issue
Block a user