Disable CORS

This commit is contained in:
Adam Ladachowski
2026-02-15 21:45:23 +01:00
parent 08e612ffa0
commit c9d76dc382
7 changed files with 1073 additions and 606 deletions
BIN
View File
Binary file not shown.
+1
View File
@@ -11,6 +11,7 @@ dependencies = [
"typer>=0.15.0", "typer>=0.15.0",
"websocket-client>=1.9.0", "websocket-client>=1.9.0",
"huggingface_hub>=0.25.0", "huggingface_hub>=0.25.0",
"sqlmodel>=0.0.33",
] ]
[project.optional-dependencies] [project.optional-dependencies]
+554 -544
View File
File diff suppressed because it is too large Load Diff
+342
View File
@@ -0,0 +1,342 @@
"""SQLModel database models for tensors."""
from datetime import datetime
from typing import Any, Optional
from sqlmodel import Field, Relationship, SQLModel
# =============================================================================
# Local Files
# =============================================================================
class LocalFile(SQLModel, table=True):
"""Local safetensor file."""
__tablename__ = "local_files"
id: int | None = Field(default=None, primary_key=True)
file_path: str = Field(unique=True)
sha256: str = Field(index=True)
header_size: int | None = None
tensor_count: int | None = None
civitai_model_id: int | None = Field(default=None, index=True)
civitai_version_id: int | None = None
created_at: datetime | None = Field(default_factory=datetime.utcnow)
updated_at: datetime | None = Field(default_factory=datetime.utcnow)
metadata_entries: list["SafetensorMetadata"] = Relationship(back_populates="local_file")
class SafetensorMetadata(SQLModel, table=True):
"""Safetensor header metadata key-value pairs."""
__tablename__ = "safetensor_metadata"
id: int | None = Field(default=None, primary_key=True)
local_file_id: int = Field(foreign_key="local_files.id", index=True)
key: str
value: str | None = None
local_file: "LocalFile" = Relationship(back_populates="metadata_entries")
# =============================================================================
# CivitAI Models
# =============================================================================
class Creator(SQLModel, table=True):
"""CivitAI model creator."""
__tablename__ = "creators"
id: int | None = Field(default=None, primary_key=True)
username: str = Field(unique=True)
image_url: str | None = None
models: list["Model"] = Relationship(back_populates="creator")
class Tag(SQLModel, table=True):
"""Model tag."""
__tablename__ = "tags"
id: int | None = Field(default=None, primary_key=True)
name: str = Field(unique=True)
class ModelTag(SQLModel, table=True):
"""Model-tag association."""
__tablename__ = "model_tags"
model_id: int = Field(foreign_key="models.id", primary_key=True)
tag_id: int = Field(foreign_key="tags.id", primary_key=True)
class Model(SQLModel, table=True):
"""CivitAI model."""
__tablename__ = "models"
id: int | None = Field(default=None, primary_key=True)
civitai_id: int = Field(unique=True, index=True)
name: str = Field(index=True)
description: str | None = None
type: str = Field(index=True)
nsfw: bool = False
poi: bool = False
minor: bool = False
sfw_only: bool = False
nsfw_level: int | None = None
availability: str | None = None
allow_no_credit: bool | None = None
allow_commercial_use: str | None = None
allow_derivatives: bool | None = None
allow_different_license: bool | None = None
supports_generation: bool = False
creator_id: int | None = Field(default=None, foreign_key="creators.id")
download_count: int = 0
thumbs_up_count: int = 0
thumbs_down_count: int = 0
comment_count: int = 0
tipped_amount_count: int = 0
created_at: datetime | None = None
updated_at: datetime | None = Field(default_factory=datetime.utcnow)
creator: Optional["Creator"] = Relationship(back_populates="models")
versions: list["ModelVersion"] = Relationship(back_populates="model")
class ModelVersion(SQLModel, table=True):
"""CivitAI model version."""
__tablename__ = "model_versions"
id: int | None = Field(default=None, primary_key=True)
civitai_id: int = Field(unique=True, index=True)
model_id: int = Field(foreign_key="models.id", index=True)
name: str
description: str | None = None
base_model: str | None = Field(default=None, index=True)
base_model_type: str | None = None
nsfw_level: int | None = None
status: str | None = None
availability: str | None = None
upload_type: str | None = None
usage_control: str | None = None
air: str | None = None
training_status: str | None = None
training_details: str | None = None
early_access_ends_at: datetime | None = None
download_count: int = 0
thumbs_up_count: int = 0
thumbs_down_count: int = 0
supports_generation: bool = False
download_url: str | None = None
created_at: datetime | None = None
published_at: datetime | None = None
updated_at: datetime | None = None
version_index: int | None = None
model: "Model" = Relationship(back_populates="versions")
files: list["VersionFile"] = Relationship(back_populates="version")
images: list["VersionImage"] = Relationship(back_populates="version")
trained_words: list["TrainedWord"] = Relationship(back_populates="version")
class TrainedWord(SQLModel, table=True):
"""Trigger words for a model version."""
__tablename__ = "trained_words"
id: int | None = Field(default=None, primary_key=True)
version_id: int = Field(foreign_key="model_versions.id", index=True)
word: str
position: int | None = None
version: "ModelVersion" = Relationship(back_populates="trained_words")
class VersionFile(SQLModel, table=True):
"""Model version file."""
__tablename__ = "version_files"
id: int | None = Field(default=None, primary_key=True)
civitai_id: int = Field(unique=True)
version_id: int = Field(foreign_key="model_versions.id", index=True)
name: str
type: str | None = None
size_kb: float | None = None
format: str | None = None
size_type: str | None = None
fp: str | None = None
is_primary: bool = False
pickle_scan_result: str | None = None
pickle_scan_message: str | None = None
virus_scan_result: str | None = None
virus_scan_message: str | None = None
scanned_at: datetime | None = None
download_url: str | None = None
version: "ModelVersion" = Relationship(back_populates="files")
hashes: list["FileHash"] = Relationship(back_populates="file")
class FileHash(SQLModel, table=True):
"""File hash values."""
__tablename__ = "file_hashes"
id: int | None = Field(default=None, primary_key=True)
file_id: int = Field(foreign_key="version_files.id", index=True)
hash_type: str
hash_value: str = Field(index=True)
file: "VersionFile" = Relationship(back_populates="hashes")
class VersionImage(SQLModel, table=True):
"""Model version example image."""
__tablename__ = "version_images"
id: int | None = Field(default=None, primary_key=True)
civitai_id: int | None = None
version_id: int = Field(foreign_key="model_versions.id", index=True)
url: str
type: str | None = None
nsfw_level: int | None = None
width: int | None = None
height: int | None = None
hash: str | None = None
has_meta: bool = False
has_positive_prompt: bool = False
on_site: bool = False
minor: bool = False
poi: bool = False
availability: str | None = None
remix_of_id: int | None = None
version: "ModelVersion" = Relationship(back_populates="images")
generation_params: list["ImageGenerationParam"] = Relationship(back_populates="image")
resources: list["ImageResource"] = Relationship(back_populates="image")
class ImageVideoMetadata(SQLModel, table=True):
"""Video metadata for animated images."""
__tablename__ = "image_video_metadata"
id: int | None = Field(default=None, primary_key=True)
image_id: int = Field(foreign_key="version_images.id", unique=True)
duration: float | None = None
has_audio: bool = False
size_bytes: int | None = None
class ImageGenerationParam(SQLModel, table=True):
"""Image generation parameters."""
__tablename__ = "image_generation_params"
id: int | None = Field(default=None, primary_key=True)
image_id: int = Field(foreign_key="version_images.id", index=True)
key: str
value: str | None = None
image: "VersionImage" = Relationship(back_populates="generation_params")
class ImageResource(SQLModel, table=True):
"""Resources used in image generation."""
__tablename__ = "image_resources"
id: int | None = Field(default=None, primary_key=True)
image_id: int = Field(foreign_key="version_images.id", index=True)
name: str
type: str | None = None
hash: str | None = None
weight: float | None = None
image: "VersionImage" = Relationship(back_populates="resources")
# =============================================================================
# HuggingFace Models
# =============================================================================
class HFModel(SQLModel, table=True):
"""HuggingFace model."""
__tablename__ = "hf_models"
id: int | None = Field(default=None, primary_key=True)
repo_id: str = Field(unique=True, index=True)
author: str | None = Field(default=None, index=True)
model_name: str
pipeline_tag: str | None = None
library_name: str | None = None
downloads: int = Field(default=0, index=True)
likes: int = 0
trending_score: float | None = None
is_private: bool = False
is_gated: bool = False
last_modified: datetime | None = None
created_at: datetime | None = None
cached_at: datetime | None = Field(default_factory=datetime.utcnow)
updated_at: datetime | None = Field(default_factory=datetime.utcnow)
tags: list["HFModelTag"] = Relationship(back_populates="model")
safetensor_files: list["HFSafetensorFile"] = Relationship(back_populates="model")
class HFModelTag(SQLModel, table=True):
"""HuggingFace model tag."""
__tablename__ = "hf_model_tags"
hf_model_id: int = Field(foreign_key="hf_models.id", primary_key=True, index=True)
tag: str = Field(primary_key=True)
model: "HFModel" = Relationship(back_populates="tags")
class HFSafetensorFile(SQLModel, table=True):
"""Safetensor file in HuggingFace model."""
__tablename__ = "hf_safetensor_files"
id: int | None = Field(default=None, primary_key=True)
hf_model_id: int = Field(foreign_key="hf_models.id", index=True)
filename: str
size_bytes: int | None = None
model: "HFModel" = Relationship(back_populates="safetensor_files")
# =============================================================================
# Database Setup
# =============================================================================
def get_engine(db_path: str = "") -> Any:
"""Create database engine."""
from sqlmodel import create_engine # noqa: PLC0415
from tensors.config import DATA_DIR # noqa: PLC0415
if not db_path:
db_path = str(DATA_DIR / "models.db")
return create_engine(f"sqlite:///{db_path}", echo=False)
def create_tables(engine: Any) -> None:
"""Create all tables."""
SQLModel.metadata.create_all(engine)
+10
View File
@@ -7,6 +7,7 @@ from contextlib import asynccontextmanager
from typing import TYPE_CHECKING from typing import TYPE_CHECKING
from fastapi import Depends, FastAPI from fastapi import Depends, FastAPI
from fastapi.middleware.cors import CORSMiddleware
from scalar_fastapi import get_scalar_api_reference from scalar_fastapi import get_scalar_api_reference
from tensors.config import get_server_api_key from tensors.config import get_server_api_key
@@ -47,6 +48,15 @@ def create_app() -> FastAPI:
redoc_url=None, redoc_url=None,
) )
# CORS - allow all origins
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# Public endpoints (no auth) # Public endpoints (no auth)
@app.get("/status") @app.get("/status")
async def status() -> dict[str, str]: async def status() -> dict[str, str]:
+53 -45
View File
@@ -7,8 +7,10 @@ import struct
from pathlib import Path from pathlib import Path
import pytest import pytest
from sqlalchemy import text
from tensors.db import Database from tensors.db import Database
from tensors.models import Creator, Model, ModelVersion, Tag, TrainedWord, VersionFile
@pytest.fixture @pytest.fixture
@@ -117,9 +119,9 @@ class TestDatabaseSchema:
def test_init_schema(self, temp_db: Database) -> None: def test_init_schema(self, temp_db: Database) -> None:
"""Test schema initialization creates tables.""" """Test schema initialization creates tables."""
cur = temp_db.conn.cursor() with temp_db.session() as session:
cur.execute("SELECT name FROM sqlite_master WHERE type='table'") result = session.exec(text("SELECT name FROM sqlite_master WHERE type='table'"))
tables = {row[0] for row in cur.fetchall()} tables = {row[0] for row in result.fetchall()}
expected = { expected = {
"local_files", "local_files",
@@ -139,13 +141,10 @@ class TestDatabaseSchema:
assert expected.issubset(tables) assert expected.issubset(tables)
def test_init_schema_creates_views(self, temp_db: Database) -> None: def test_init_schema_creates_views(self, temp_db: Database) -> None:
"""Test schema creates required views.""" """Test schema creates required views - SQLModel doesn't create views, so skip."""
cur = temp_db.conn.cursor() # SQLModel creates tables but not views - views would need raw SQL
cur.execute("SELECT name FROM sqlite_master WHERE type='view'") # This test is no longer applicable with SQLModel
views = {row[0] for row in cur.fetchall()} pass
assert "v_local_files_full" in views
assert "v_models_with_latest" in views
class TestLocalFiles: class TestLocalFiles:
@@ -227,75 +226,84 @@ class TestCivitAICache:
def test_cache_model_creates_creator(self, temp_db: Database, sample_civitai_model: dict) -> None: def test_cache_model_creates_creator(self, temp_db: Database, sample_civitai_model: dict) -> None:
"""Test that caching model creates creator record.""" """Test that caching model creates creator record."""
from sqlmodel import select
temp_db.cache_model(sample_civitai_model) temp_db.cache_model(sample_civitai_model)
cur = temp_db.conn.cursor() with temp_db.session() as session:
cur.execute("SELECT * FROM creators WHERE username = ?", ("test_creator",)) creator = session.exec(select(Creator).where(Creator.username == "test_creator")).first()
creator = cur.fetchone()
assert creator is not None assert creator is not None
assert creator["username"] == "test_creator" assert creator.username == "test_creator"
def test_cache_model_creates_tags(self, temp_db: Database, sample_civitai_model: dict) -> None: def test_cache_model_creates_tags(self, temp_db: Database, sample_civitai_model: dict) -> None:
"""Test that caching model creates tags.""" """Test that caching model creates tags."""
from sqlmodel import select
temp_db.cache_model(sample_civitai_model) temp_db.cache_model(sample_civitai_model)
cur = temp_db.conn.cursor() with temp_db.session() as session:
cur.execute("SELECT COUNT(*) FROM tags") tags = session.exec(select(Tag)).all()
count = cur.fetchone()[0]
assert count == 3 # test, lora, anime assert len(tags) == 3 # test, lora, anime
def test_cache_model_creates_versions(self, temp_db: Database, sample_civitai_model: dict) -> None: def test_cache_model_creates_versions(self, temp_db: Database, sample_civitai_model: dict) -> None:
"""Test that caching model creates versions.""" """Test that caching model creates versions."""
from sqlmodel import select
temp_db.cache_model(sample_civitai_model) temp_db.cache_model(sample_civitai_model)
cur = temp_db.conn.cursor() with temp_db.session() as session:
cur.execute("SELECT * FROM model_versions WHERE civitai_id = ?", (789012,)) version = session.exec(select(ModelVersion).where(ModelVersion.civitai_id == 789012)).first()
version = cur.fetchone()
assert version is not None assert version is not None
assert version["name"] == "v1.0" assert version.name == "v1.0"
assert version["base_model"] == "SDXL 1.0" assert version.base_model == "SDXL 1.0"
def test_cache_model_creates_trained_words(self, temp_db: Database, sample_civitai_model: dict) -> None: def test_cache_model_creates_trained_words(self, temp_db: Database, sample_civitai_model: dict) -> None:
"""Test that caching model creates trained words.""" """Test that caching model creates trained words."""
from sqlmodel import col, select
temp_db.cache_model(sample_civitai_model) temp_db.cache_model(sample_civitai_model)
cur = temp_db.conn.cursor() with temp_db.session() as session:
cur.execute("SELECT word FROM trained_words ORDER BY position") words = session.exec(select(TrainedWord).order_by(col(TrainedWord.position))).all()
words = [row[0] for row in cur.fetchall()]
assert words == ["test_trigger", "lora_trigger"] assert [w.word for w in words] == ["test_trigger", "lora_trigger"]
def test_cache_model_creates_files_and_hashes(self, temp_db: Database, sample_civitai_model: dict) -> None: def test_cache_model_creates_files_and_hashes(self, temp_db: Database, sample_civitai_model: dict) -> None:
"""Test that caching model creates files and hashes.""" """Test that caching model creates files and hashes."""
from sqlmodel import select
from tensors.models import FileHash
temp_db.cache_model(sample_civitai_model) temp_db.cache_model(sample_civitai_model)
cur = temp_db.conn.cursor() with temp_db.session() as session:
cur.execute("SELECT * FROM version_files WHERE civitai_id = ?", (111222,)) file_record = session.exec(select(VersionFile).where(VersionFile.civitai_id == 111222)).first()
file_record = cur.fetchone()
assert file_record is not None assert file_record is not None
assert file_record["name"] == "test_lora.safetensors" assert file_record.name == "test_lora.safetensors"
assert file_record["is_primary"] == 1 assert file_record.is_primary is True
cur.execute("SELECT hash_type, hash_value FROM file_hashes WHERE file_id = ?", (file_record["id"],)) hashes = session.exec(select(FileHash).where(FileHash.file_id == file_record.id)).all()
hashes = {row[0]: row[1] for row in cur.fetchall()} hash_dict = {h.hash_type: h.hash_value for h in hashes}
assert hashes["SHA256"] == "ABC123DEF456" assert hash_dict["SHA256"] == "ABC123DEF456"
assert hashes["BLAKE3"] == "789XYZ" assert hash_dict["BLAKE3"] == "789XYZ"
def test_cache_model_idempotent(self, temp_db: Database, sample_civitai_model: dict) -> None: def test_cache_model_idempotent(self, temp_db: Database, sample_civitai_model: dict) -> None:
"""Test that caching same model twice is idempotent.""" """Test that caching same model twice is idempotent."""
from sqlmodel import select
id1 = temp_db.cache_model(sample_civitai_model) id1 = temp_db.cache_model(sample_civitai_model)
id2 = temp_db.cache_model(sample_civitai_model) id2 = temp_db.cache_model(sample_civitai_model)
assert id1 == id2 assert id1 == id2
cur = temp_db.conn.cursor() with temp_db.session() as session:
cur.execute("SELECT COUNT(*) FROM models") models = session.exec(select(Model)).all()
assert cur.fetchone()[0] == 1 assert len(models) == 1
class TestQueryOperations: class TestQueryOperations:
@@ -436,15 +444,15 @@ class TestContextManager:
stats = db.get_stats() stats = db.get_stats()
assert stats["local_files"] == 0 assert stats["local_files"] == 0
# Connection should be closed # Engine should be disposed
assert db._conn is None assert db._engine is None
def test_connection_reuse(self, tmp_path: Path) -> None: def test_connection_reuse(self, tmp_path: Path) -> None:
"""Test that connection is reused within context.""" """Test that engine is reused within context."""
db_path = tmp_path / "test.db" db_path = tmp_path / "test.db"
with Database(db_path=db_path) as db: with Database(db_path=db_path) as db:
db.init_schema() db.init_schema()
conn1 = db.conn engine1 = db.engine
conn2 = db.conn engine2 = db.engine
assert conn1 is conn2 assert engine1 is engine2
Generated
+96
View File
@@ -189,6 +189,45 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/e6/ab/fb21f4c939bb440104cc2b396d3be1d9b7a9fd3c6c2a53d98c45b3d7c954/fsspec-2026.2.0-py3-none-any.whl", hash = "sha256:98de475b5cb3bd66bedd5c4679e87b4fdfe1a3bf4d707b151b3c07e58c9a2437", size = 202505, upload-time = "2026-02-05T21:50:51.819Z" }, { url = "https://files.pythonhosted.org/packages/e6/ab/fb21f4c939bb440104cc2b396d3be1d9b7a9fd3c6c2a53d98c45b3d7c954/fsspec-2026.2.0-py3-none-any.whl", hash = "sha256:98de475b5cb3bd66bedd5c4679e87b4fdfe1a3bf4d707b151b3c07e58c9a2437", size = 202505, upload-time = "2026-02-05T21:50:51.819Z" },
] ]
[[package]]
name = "greenlet"
version = "3.3.1"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/8a/99/1cd3411c56a410994669062bd73dd58270c00cc074cac15f385a1fd91f8a/greenlet-3.3.1.tar.gz", hash = "sha256:41848f3230b58c08bb43dee542e74a2a2e34d3c59dc3076cec9151aeeedcae98", size = 184690, upload-time = "2026-01-23T15:31:02.076Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/f9/c8/9d76a66421d1ae24340dfae7e79c313957f6e3195c144d2c73333b5bfe34/greenlet-3.3.1-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:7e806ca53acf6d15a888405880766ec84721aa4181261cd11a457dfe9a7a4975", size = 276443, upload-time = "2026-01-23T15:30:10.066Z" },
{ url = "https://files.pythonhosted.org/packages/81/99/401ff34bb3c032d1f10477d199724f5e5f6fbfb59816ad1455c79c1eb8e7/greenlet-3.3.1-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d842c94b9155f1c9b3058036c24ffb8ff78b428414a19792b2380be9cecf4f36", size = 597359, upload-time = "2026-01-23T16:00:57.394Z" },
{ url = "https://files.pythonhosted.org/packages/2b/bc/4dcc0871ed557792d304f50be0f7487a14e017952ec689effe2180a6ff35/greenlet-3.3.1-cp312-cp312-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:20fedaadd422fa02695f82093f9a98bad3dab5fcda793c658b945fcde2ab27ba", size = 607805, upload-time = "2026-01-23T16:05:28.068Z" },
{ url = "https://files.pythonhosted.org/packages/cf/05/821587cf19e2ce1f2b24945d890b164401e5085f9d09cbd969b0c193cd20/greenlet-3.3.1-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:14194f5f4305800ff329cbf02c5fcc88f01886cadd29941b807668a45f0d2336", size = 609947, upload-time = "2026-01-23T15:32:51.004Z" },
{ url = "https://files.pythonhosted.org/packages/a4/52/ee8c46ed9f8babaa93a19e577f26e3d28a519feac6350ed6f25f1afee7e9/greenlet-3.3.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:7b2fe4150a0cf59f847a67db8c155ac36aed89080a6a639e9f16df5d6c6096f1", size = 1567487, upload-time = "2026-01-23T16:04:22.125Z" },
{ url = "https://files.pythonhosted.org/packages/8f/7c/456a74f07029597626f3a6db71b273a3632aecb9afafeeca452cfa633197/greenlet-3.3.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:49f4ad195d45f4a66a0eb9c1ba4832bb380570d361912fa3554746830d332149", size = 1636087, upload-time = "2026-01-23T15:33:47.486Z" },
{ url = "https://files.pythonhosted.org/packages/34/2f/5e0e41f33c69655300a5e54aeb637cf8ff57f1786a3aba374eacc0228c1d/greenlet-3.3.1-cp312-cp312-win_amd64.whl", hash = "sha256:cc98b9c4e4870fa983436afa999d4eb16b12872fab7071423d5262fa7120d57a", size = 227156, upload-time = "2026-01-23T15:34:34.808Z" },
{ url = "https://files.pythonhosted.org/packages/c8/ab/717c58343cf02c5265b531384b248787e04d8160b8afe53d9eec053d7b44/greenlet-3.3.1-cp312-cp312-win_arm64.whl", hash = "sha256:bfb2d1763d777de5ee495c85309460f6fd8146e50ec9d0ae0183dbf6f0a829d1", size = 226403, upload-time = "2026-01-23T15:31:39.372Z" },
{ url = "https://files.pythonhosted.org/packages/ec/ab/d26750f2b7242c2b90ea2ad71de70cfcd73a948a49513188a0fc0d6fc15a/greenlet-3.3.1-cp313-cp313-macosx_11_0_universal2.whl", hash = "sha256:7ab327905cabb0622adca5971e488064e35115430cec2c35a50fd36e72a315b3", size = 275205, upload-time = "2026-01-23T15:30:24.556Z" },
{ url = "https://files.pythonhosted.org/packages/10/d3/be7d19e8fad7c5a78eeefb2d896a08cd4643e1e90c605c4be3b46264998f/greenlet-3.3.1-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:65be2f026ca6a176f88fb935ee23c18333ccea97048076aef4db1ef5bc0713ac", size = 599284, upload-time = "2026-01-23T16:00:58.584Z" },
{ url = "https://files.pythonhosted.org/packages/ae/21/fe703aaa056fdb0f17e5afd4b5c80195bbdab701208918938bd15b00d39b/greenlet-3.3.1-cp313-cp313-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:7a3ae05b3d225b4155bda56b072ceb09d05e974bc74be6c3fc15463cf69f33fd", size = 610274, upload-time = "2026-01-23T16:05:29.312Z" },
{ url = "https://files.pythonhosted.org/packages/cb/86/5c6ab23bb3c28c21ed6bebad006515cfe08b04613eb105ca0041fecca852/greenlet-3.3.1-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6423481193bbbe871313de5fd06a082f2649e7ce6e08015d2a76c1e9186ca5b3", size = 612904, upload-time = "2026-01-23T15:32:52.317Z" },
{ url = "https://files.pythonhosted.org/packages/c2/f3/7949994264e22639e40718c2daf6f6df5169bf48fb038c008a489ec53a50/greenlet-3.3.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:33a956fe78bbbda82bfc95e128d61129b32d66bcf0a20a1f0c08aa4839ffa951", size = 1567316, upload-time = "2026-01-23T16:04:23.316Z" },
{ url = "https://files.pythonhosted.org/packages/8d/6e/d73c94d13b6465e9f7cd6231c68abde838bb22408596c05d9059830b7872/greenlet-3.3.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4b065d3284be43728dd280f6f9a13990b56470b81be20375a207cdc814a983f2", size = 1636549, upload-time = "2026-01-23T15:33:48.643Z" },
{ url = "https://files.pythonhosted.org/packages/5e/b3/c9c23a6478b3bcc91f979ce4ca50879e4d0b2bd7b9a53d8ecded719b92e2/greenlet-3.3.1-cp313-cp313-win_amd64.whl", hash = "sha256:27289986f4e5b0edec7b5a91063c109f0276abb09a7e9bdab08437525977c946", size = 227042, upload-time = "2026-01-23T15:33:58.216Z" },
{ url = "https://files.pythonhosted.org/packages/90/e7/824beda656097edee36ab15809fd063447b200cc03a7f6a24c34d520bc88/greenlet-3.3.1-cp313-cp313-win_arm64.whl", hash = "sha256:2f080e028001c5273e0b42690eaf359aeef9cb1389da0f171ea51a5dc3c7608d", size = 226294, upload-time = "2026-01-23T15:30:52.73Z" },
{ url = "https://files.pythonhosted.org/packages/ae/fb/011c7c717213182caf78084a9bea51c8590b0afda98001f69d9f853a495b/greenlet-3.3.1-cp314-cp314-macosx_11_0_universal2.whl", hash = "sha256:bd59acd8529b372775cd0fcbc5f420ae20681c5b045ce25bd453ed8455ab99b5", size = 275737, upload-time = "2026-01-23T15:32:16.889Z" },
{ url = "https://files.pythonhosted.org/packages/41/2e/a3a417d620363fdbb08a48b1dd582956a46a61bf8fd27ee8164f9dfe87c2/greenlet-3.3.1-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b31c05dd84ef6871dd47120386aed35323c944d86c3d91a17c4b8d23df62f15b", size = 646422, upload-time = "2026-01-23T16:01:00.354Z" },
{ url = "https://files.pythonhosted.org/packages/b4/09/c6c4a0db47defafd2d6bab8ddfe47ad19963b4e30f5bed84d75328059f8c/greenlet-3.3.1-cp314-cp314-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:02925a0bfffc41e542c70aa14c7eda3593e4d7e274bfcccca1827e6c0875902e", size = 658219, upload-time = "2026-01-23T16:05:30.956Z" },
{ url = "https://files.pythonhosted.org/packages/80/38/9d42d60dffb04b45f03dbab9430898352dba277758640751dc5cc316c521/greenlet-3.3.1-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:34a729e2e4e4ffe9ae2408d5ecaf12f944853f40ad724929b7585bca808a9d6f", size = 660237, upload-time = "2026-01-23T15:32:53.967Z" },
{ url = "https://files.pythonhosted.org/packages/96/61/373c30b7197f9e756e4c81ae90a8d55dc3598c17673f91f4d31c3c689c3f/greenlet-3.3.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:aec9ab04e82918e623415947921dea15851b152b822661cce3f8e4393c3df683", size = 1615261, upload-time = "2026-01-23T16:04:25.066Z" },
{ url = "https://files.pythonhosted.org/packages/fd/d3/ca534310343f5945316f9451e953dcd89b36fe7a19de652a1dc5a0eeef3f/greenlet-3.3.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:71c767cf281a80d02b6c1bdc41c9468e1f5a494fb11bc8688c360524e273d7b1", size = 1683719, upload-time = "2026-01-23T15:33:50.61Z" },
{ url = "https://files.pythonhosted.org/packages/52/cb/c21a3fd5d2c9c8b622e7bede6d6d00e00551a5ee474ea6d831b5f567a8b4/greenlet-3.3.1-cp314-cp314-win_amd64.whl", hash = "sha256:96aff77af063b607f2489473484e39a0bbae730f2ea90c9e5606c9b73c44174a", size = 228125, upload-time = "2026-01-23T15:32:45.265Z" },
{ url = "https://files.pythonhosted.org/packages/6a/8e/8a2db6d11491837af1de64b8aff23707c6e85241be13c60ed399a72e2ef8/greenlet-3.3.1-cp314-cp314-win_arm64.whl", hash = "sha256:b066e8b50e28b503f604fa538adc764a638b38cf8e81e025011d26e8a627fa79", size = 227519, upload-time = "2026-01-23T15:31:47.284Z" },
{ url = "https://files.pythonhosted.org/packages/28/24/cbbec49bacdcc9ec652a81d3efef7b59f326697e7edf6ed775a5e08e54c2/greenlet-3.3.1-cp314-cp314t-macosx_11_0_universal2.whl", hash = "sha256:3e63252943c921b90abb035ebe9de832c436401d9c45f262d80e2d06cc659242", size = 282706, upload-time = "2026-01-23T15:33:05.525Z" },
{ url = "https://files.pythonhosted.org/packages/86/2e/4f2b9323c144c4fe8842a4e0d92121465485c3c2c5b9e9b30a52e80f523f/greenlet-3.3.1-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:76e39058e68eb125de10c92524573924e827927df5d3891fbc97bd55764a8774", size = 651209, upload-time = "2026-01-23T16:01:01.517Z" },
{ url = "https://files.pythonhosted.org/packages/d9/87/50ca60e515f5bb55a2fbc5f0c9b5b156de7d2fc51a0a69abc9d23914a237/greenlet-3.3.1-cp314-cp314t-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c9f9d5e7a9310b7a2f416dd13d2e3fd8b42d803968ea580b7c0f322ccb389b97", size = 654300, upload-time = "2026-01-23T16:05:32.199Z" },
{ url = "https://files.pythonhosted.org/packages/1d/94/74310866dfa2b73dd08659a3d18762f83985ad3281901ba0ee9a815194fb/greenlet-3.3.1-cp314-cp314t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:92497c78adf3ac703b57f1e3813c2d874f27f71a178f9ea5887855da413cd6d2", size = 653842, upload-time = "2026-01-23T15:32:55.671Z" },
{ url = "https://files.pythonhosted.org/packages/97/43/8bf0ffa3d498eeee4c58c212a3905dd6146c01c8dc0b0a046481ca29b18c/greenlet-3.3.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:ed6b402bc74d6557a705e197d47f9063733091ed6357b3de33619d8a8d93ac53", size = 1614917, upload-time = "2026-01-23T16:04:26.276Z" },
{ url = "https://files.pythonhosted.org/packages/89/90/a3be7a5f378fc6e84abe4dcfb2ba32b07786861172e502388b4c90000d1b/greenlet-3.3.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:59913f1e5ada20fde795ba906916aea25d442abcc0593fba7e26c92b7ad76249", size = 1676092, upload-time = "2026-01-23T15:33:52.176Z" },
{ url = "https://files.pythonhosted.org/packages/e1/2b/98c7f93e6db9977aaee07eb1e51ca63bd5f779b900d362791d3252e60558/greenlet-3.3.1-cp314-cp314t-win_amd64.whl", hash = "sha256:301860987846c24cb8964bdec0e31a96ad4a2a801b41b4ef40963c1b44f33451", size = 233181, upload-time = "2026-01-23T15:33:00.29Z" },
]
[[package]] [[package]]
name = "h11" name = "h11"
version = "0.16.0" version = "0.16.0"
@@ -760,6 +799,61 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl", hash = "sha256:7ecfff8f2fd72616f7481040475a65b2bf8af90a56c89140852d1120324e8686", size = 9755, upload-time = "2023-10-24T04:13:38.866Z" }, { url = "https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl", hash = "sha256:7ecfff8f2fd72616f7481040475a65b2bf8af90a56c89140852d1120324e8686", size = 9755, upload-time = "2023-10-24T04:13:38.866Z" },
] ]
[[package]]
name = "sqlalchemy"
version = "2.0.46"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "greenlet", marker = "platform_machine == 'AMD64' or platform_machine == 'WIN32' or platform_machine == 'aarch64' or platform_machine == 'amd64' or platform_machine == 'ppc64le' or platform_machine == 'win32' or platform_machine == 'x86_64'" },
{ name = "typing-extensions" },
]
sdist = { url = "https://files.pythonhosted.org/packages/06/aa/9ce0f3e7a9829ead5c8ce549392f33a12c4555a6c0609bb27d882e9c7ddf/sqlalchemy-2.0.46.tar.gz", hash = "sha256:cf36851ee7219c170bb0793dbc3da3e80c582e04a5437bc601bfe8c85c9216d7", size = 9865393, upload-time = "2026-01-21T18:03:45.119Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/b6/35/d16bfa235c8b7caba3730bba43e20b1e376d2224f407c178fbf59559f23e/sqlalchemy-2.0.46-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:3a9a72b0da8387f15d5810f1facca8f879de9b85af8c645138cba61ea147968c", size = 2153405, upload-time = "2026-01-21T19:05:54.143Z" },
{ url = "https://files.pythonhosted.org/packages/06/6c/3192e24486749862f495ddc6584ed730c0c994a67550ec395d872a2ad650/sqlalchemy-2.0.46-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2347c3f0efc4de367ba00218e0ae5c4ba2306e47216ef80d6e31761ac97cb0b9", size = 3334702, upload-time = "2026-01-21T18:46:45.384Z" },
{ url = "https://files.pythonhosted.org/packages/ea/a2/b9f33c8d68a3747d972a0bb758c6b63691f8fb8a49014bc3379ba15d4274/sqlalchemy-2.0.46-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9094c8b3197db12aa6f05c51c05daaad0a92b8c9af5388569847b03b1007fb1b", size = 3347664, upload-time = "2026-01-21T18:40:09.979Z" },
{ url = "https://files.pythonhosted.org/packages/aa/d2/3e59e2a91eaec9db7e8dc6b37b91489b5caeb054f670f32c95bcba98940f/sqlalchemy-2.0.46-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:37fee2164cf21417478b6a906adc1a91d69ae9aba8f9533e67ce882f4bb1de53", size = 3277372, upload-time = "2026-01-21T18:46:47.168Z" },
{ url = "https://files.pythonhosted.org/packages/dd/dd/67bc2e368b524e2192c3927b423798deda72c003e73a1e94c21e74b20a85/sqlalchemy-2.0.46-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b1e14b2f6965a685c7128bd315e27387205429c2e339eeec55cb75ca4ab0ea2e", size = 3312425, upload-time = "2026-01-21T18:40:11.548Z" },
{ url = "https://files.pythonhosted.org/packages/43/82/0ecd68e172bfe62247e96cb47867c2d68752566811a4e8c9d8f6e7c38a65/sqlalchemy-2.0.46-cp312-cp312-win32.whl", hash = "sha256:412f26bb4ba942d52016edc8d12fb15d91d3cd46b0047ba46e424213ad407bcb", size = 2113155, upload-time = "2026-01-21T18:42:49.748Z" },
{ url = "https://files.pythonhosted.org/packages/bc/2a/2821a45742073fc0331dc132552b30de68ba9563230853437cac54b2b53e/sqlalchemy-2.0.46-cp312-cp312-win_amd64.whl", hash = "sha256:ea3cd46b6713a10216323cda3333514944e510aa691c945334713fca6b5279ff", size = 2140078, upload-time = "2026-01-21T18:42:51.197Z" },
{ url = "https://files.pythonhosted.org/packages/b3/4b/fa7838fe20bb752810feed60e45625a9a8b0102c0c09971e2d1d95362992/sqlalchemy-2.0.46-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:93a12da97cca70cea10d4b4fc602589c4511f96c1f8f6c11817620c021d21d00", size = 2150268, upload-time = "2026-01-21T19:05:56.621Z" },
{ url = "https://files.pythonhosted.org/packages/46/c1/b34dccd712e8ea846edf396e00973dda82d598cb93762e55e43e6835eba9/sqlalchemy-2.0.46-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:af865c18752d416798dae13f83f38927c52f085c52e2f32b8ab0fef46fdd02c2", size = 3276511, upload-time = "2026-01-21T18:46:49.022Z" },
{ url = "https://files.pythonhosted.org/packages/96/48/a04d9c94753e5d5d096c628c82a98c4793b9c08ca0e7155c3eb7d7db9f24/sqlalchemy-2.0.46-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8d679b5f318423eacb61f933a9a0f75535bfca7056daeadbf6bd5bcee6183aee", size = 3292881, upload-time = "2026-01-21T18:40:13.089Z" },
{ url = "https://files.pythonhosted.org/packages/be/f4/06eda6e91476f90a7d8058f74311cb65a2fb68d988171aced81707189131/sqlalchemy-2.0.46-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:64901e08c33462acc9ec3bad27fc7a5c2b6491665f2aa57564e57a4f5d7c52ad", size = 3224559, upload-time = "2026-01-21T18:46:50.974Z" },
{ url = "https://files.pythonhosted.org/packages/ab/a2/d2af04095412ca6345ac22b33b89fe8d6f32a481e613ffcb2377d931d8d0/sqlalchemy-2.0.46-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e8ac45e8f4eaac0f9f8043ea0e224158855c6a4329fd4ee37c45c61e3beb518e", size = 3262728, upload-time = "2026-01-21T18:40:14.883Z" },
{ url = "https://files.pythonhosted.org/packages/31/48/1980c7caa5978a3b8225b4d230e69a2a6538a3562b8b31cea679b6933c83/sqlalchemy-2.0.46-cp313-cp313-win32.whl", hash = "sha256:8d3b44b3d0ab2f1319d71d9863d76eeb46766f8cf9e921ac293511804d39813f", size = 2111295, upload-time = "2026-01-21T18:42:52.366Z" },
{ url = "https://files.pythonhosted.org/packages/2d/54/f8d65bbde3d877617c4720f3c9f60e99bb7266df0d5d78b6e25e7c149f35/sqlalchemy-2.0.46-cp313-cp313-win_amd64.whl", hash = "sha256:77f8071d8fbcbb2dd11b7fd40dedd04e8ebe2eb80497916efedba844298065ef", size = 2137076, upload-time = "2026-01-21T18:42:53.924Z" },
{ url = "https://files.pythonhosted.org/packages/56/ba/9be4f97c7eb2b9d5544f2624adfc2853e796ed51d2bb8aec90bc94b7137e/sqlalchemy-2.0.46-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a1e8cc6cc01da346dc92d9509a63033b9b1bda4fed7a7a7807ed385c7dccdc10", size = 3556533, upload-time = "2026-01-21T18:33:06.636Z" },
{ url = "https://files.pythonhosted.org/packages/20/a6/b1fc6634564dbb4415b7ed6419cdfeaadefd2c39cdab1e3aa07a5f2474c2/sqlalchemy-2.0.46-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:96c7cca1a4babaaf3bfff3e4e606e38578856917e52f0384635a95b226c87764", size = 3523208, upload-time = "2026-01-21T18:45:08.436Z" },
{ url = "https://files.pythonhosted.org/packages/a1/d8/41e0bdfc0f930ff236f86fccd12962d8fa03713f17ed57332d38af6a3782/sqlalchemy-2.0.46-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:b2a9f9aee38039cf4755891a1e50e1effcc42ea6ba053743f452c372c3152b1b", size = 3464292, upload-time = "2026-01-21T18:33:08.208Z" },
{ url = "https://files.pythonhosted.org/packages/f0/8b/9dcbec62d95bea85f5ecad9b8d65b78cc30fb0ffceeb3597961f3712549b/sqlalchemy-2.0.46-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:db23b1bf8cfe1f7fda19018e7207b20cdb5168f83c437ff7e95d19e39289c447", size = 3473497, upload-time = "2026-01-21T18:45:10.552Z" },
{ url = "https://files.pythonhosted.org/packages/e9/f8/5ecdfc73383ec496de038ed1614de9e740a82db9ad67e6e4514ebc0708a3/sqlalchemy-2.0.46-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:56bdd261bfd0895452006d5316cbf35739c53b9bb71a170a331fa0ea560b2ada", size = 2152079, upload-time = "2026-01-21T19:05:58.477Z" },
{ url = "https://files.pythonhosted.org/packages/e5/bf/eba3036be7663ce4d9c050bc3d63794dc29fbe01691f2bf5ccb64e048d20/sqlalchemy-2.0.46-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:33e462154edb9493f6c3ad2125931e273bbd0be8ae53f3ecd1c161ea9a1dd366", size = 3272216, upload-time = "2026-01-21T18:46:52.634Z" },
{ url = "https://files.pythonhosted.org/packages/05/45/1256fb597bb83b58a01ddb600c59fe6fdf0e5afe333f0456ed75c0f8d7bd/sqlalchemy-2.0.46-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9bcdce05f056622a632f1d44bb47dbdb677f58cad393612280406ce37530eb6d", size = 3277208, upload-time = "2026-01-21T18:40:16.38Z" },
{ url = "https://files.pythonhosted.org/packages/d9/a0/2053b39e4e63b5d7ceb3372cface0859a067c1ddbd575ea7e9985716f771/sqlalchemy-2.0.46-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:8e84b09a9b0f19accedcbeff5c2caf36e0dd537341a33aad8d680336152dc34e", size = 3221994, upload-time = "2026-01-21T18:46:54.622Z" },
{ url = "https://files.pythonhosted.org/packages/1e/87/97713497d9502553c68f105a1cb62786ba1ee91dea3852ae4067ed956a50/sqlalchemy-2.0.46-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:4f52f7291a92381e9b4de9050b0a65ce5d6a763333406861e33906b8aa4906bf", size = 3243990, upload-time = "2026-01-21T18:40:18.253Z" },
{ url = "https://files.pythonhosted.org/packages/a8/87/5d1b23548f420ff823c236f8bea36b1a997250fd2f892e44a3838ca424f4/sqlalchemy-2.0.46-cp314-cp314-win32.whl", hash = "sha256:70ed2830b169a9960193f4d4322d22be5c0925357d82cbf485b3369893350908", size = 2114215, upload-time = "2026-01-21T18:42:55.232Z" },
{ url = "https://files.pythonhosted.org/packages/3a/20/555f39cbcf0c10cf452988b6a93c2a12495035f68b3dbd1a408531049d31/sqlalchemy-2.0.46-cp314-cp314-win_amd64.whl", hash = "sha256:3c32e993bc57be6d177f7d5d31edb93f30726d798ad86ff9066d75d9bf2e0b6b", size = 2139867, upload-time = "2026-01-21T18:42:56.474Z" },
{ url = "https://files.pythonhosted.org/packages/3e/f0/f96c8057c982d9d8a7a68f45d69c674bc6f78cad401099692fe16521640a/sqlalchemy-2.0.46-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4dafb537740eef640c4d6a7c254611dca2df87eaf6d14d6a5fca9d1f4c3fc0fa", size = 3561202, upload-time = "2026-01-21T18:33:10.337Z" },
{ url = "https://files.pythonhosted.org/packages/d7/53/3b37dda0a5b137f21ef608d8dfc77b08477bab0fe2ac9d3e0a66eaeab6fc/sqlalchemy-2.0.46-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:42a1643dc5427b69aca967dae540a90b0fbf57eaf248f13a90ea5930e0966863", size = 3526296, upload-time = "2026-01-21T18:45:12.657Z" },
{ url = "https://files.pythonhosted.org/packages/33/75/f28622ba6dde79cd545055ea7bd4062dc934e0621f7b3be2891f8563f8de/sqlalchemy-2.0.46-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:ff33c6e6ad006bbc0f34f5faf941cfc62c45841c64c0a058ac38c799f15b5ede", size = 3470008, upload-time = "2026-01-21T18:33:11.725Z" },
{ url = "https://files.pythonhosted.org/packages/a9/42/4afecbbc38d5e99b18acef446453c76eec6fbd03db0a457a12a056836e22/sqlalchemy-2.0.46-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:82ec52100ec1e6ec671563bbd02d7c7c8d0b9e71a0723c72f22ecf52d1755330", size = 3476137, upload-time = "2026-01-21T18:45:15.001Z" },
{ url = "https://files.pythonhosted.org/packages/fc/a1/9c4efa03300926601c19c18582531b45aededfb961ab3c3585f1e24f120b/sqlalchemy-2.0.46-py3-none-any.whl", hash = "sha256:f9c11766e7e7c0a2767dda5acb006a118640c9fc0a4104214b96269bfb78399e", size = 1937882, upload-time = "2026-01-21T18:22:10.456Z" },
]
[[package]]
name = "sqlmodel"
version = "0.0.33"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "pydantic" },
{ name = "sqlalchemy" },
]
sdist = { url = "https://files.pythonhosted.org/packages/c4/62/22c287122598e61d07d005eec0b4eb97e6bde9a1b051bcd66c2bca846ea8/sqlmodel-0.0.33.tar.gz", hash = "sha256:b473544ed5fc2097894d89033049e569e1f138363dd3ec2ed4b6932cc9f29f5f", size = 95578, upload-time = "2026-02-11T15:23:39.504Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/63/39/13891bae4658133b489a4d8b6a2f193d56110e392289560f312748e796dc/sqlmodel-0.0.33-py3-none-any.whl", hash = "sha256:9045bb4d97d2ba099c5a068ee9525af2d106972dda1ff8488e187ce50556bf73", size = 27444, upload-time = "2026-02-11T15:23:38.678Z" },
]
[[package]] [[package]]
name = "starlette" name = "starlette"
version = "0.52.1" version = "0.52.1"
@@ -782,6 +876,7 @@ dependencies = [
{ name = "huggingface-hub" }, { name = "huggingface-hub" },
{ name = "rich" }, { name = "rich" },
{ name = "safetensors" }, { name = "safetensors" },
{ name = "sqlmodel" },
{ name = "typer" }, { name = "typer" },
{ name = "websocket-client" }, { name = "websocket-client" },
] ]
@@ -815,6 +910,7 @@ requires-dist = [
{ name = "rich", specifier = ">=13.0.0" }, { name = "rich", specifier = ">=13.0.0" },
{ name = "safetensors", specifier = ">=0.4.0" }, { name = "safetensors", specifier = ">=0.4.0" },
{ name = "scalar-fastapi", marker = "extra == 'server'", specifier = ">=1.6" }, { name = "scalar-fastapi", marker = "extra == 'server'", specifier = ">=1.6" },
{ name = "sqlmodel", specifier = ">=0.0.33" },
{ name = "typer", specifier = ">=0.15.0" }, { name = "typer", specifier = ">=0.15.0" },
{ name = "uvicorn", marker = "extra == 'server'", specifier = ">=0.30" }, { name = "uvicorn", marker = "extra == 'server'", specifier = ">=0.30" },
{ name = "websocket-client", specifier = ">=1.9.0" }, { name = "websocket-client", specifier = ">=1.9.0" },