mirror of
https://github.com/Kludex/awesome-fastapi-projects.git
synced 2025-05-12 12:25:35 +00:00
Add a unique constraint for the repo url and source graph repo id
This commit is contained in:
parent
cca18fbd33
commit
102de55b12
@ -19,7 +19,7 @@ from collections.abc import AsyncGenerator
|
||||
from pathlib import PurePath
|
||||
from typing import Final
|
||||
|
||||
from sqlalchemy import BigInteger, ForeignKey, String, Text
|
||||
from sqlalchemy import BigInteger, ForeignKey, MetaData, String, Text, UniqueConstraint
|
||||
from sqlalchemy.ext.asyncio import (
|
||||
AsyncAttrs,
|
||||
AsyncEngine,
|
||||
@ -27,7 +27,12 @@ from sqlalchemy.ext.asyncio import (
|
||||
async_sessionmaker,
|
||||
create_async_engine,
|
||||
)
|
||||
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, relationship
|
||||
from sqlalchemy.orm import (
|
||||
Mapped,
|
||||
declarative_base,
|
||||
mapped_column,
|
||||
relationship,
|
||||
)
|
||||
|
||||
DB_PATH: Final[PurePath] = PurePath(__file__).parent.parent / "db.sqlite3"
|
||||
|
||||
@ -39,6 +44,16 @@ async_session_maker: Final[async_sessionmaker[AsyncSession]] = async_sessionmake
|
||||
engine, expire_on_commit=False, autoflush=False, autocommit=False
|
||||
)
|
||||
|
||||
metadata = MetaData(
|
||||
naming_convention={
|
||||
"ix": "ix_%(table_name)s_%(column_0_N_name)s ",
|
||||
"uq": "uq_%(table_name)s_%(column_0_N_name)s ",
|
||||
"ck": "ck_%(table_name)s_%(constraint_name)s ",
|
||||
"fk": "fk_%(table_name)s_%(column_0_N_name)s_%(referred_table_name)s",
|
||||
"pk": "pk_%(table_name)s",
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
async def get_async_session() -> AsyncGenerator[AsyncSession, None]:
|
||||
"""Get an async session."""
|
||||
@ -46,10 +61,7 @@ async def get_async_session() -> AsyncGenerator[AsyncSession, None]:
|
||||
yield session
|
||||
|
||||
|
||||
class Base(AsyncAttrs, DeclarativeBase):
|
||||
"""Declarative base for database models."""
|
||||
|
||||
pass
|
||||
Base = declarative_base(metadata=metadata, cls=AsyncAttrs)
|
||||
|
||||
|
||||
class Repo(Base):
|
||||
@ -66,6 +78,7 @@ class Repo(Base):
|
||||
dependencies: Mapped[list["Dependency"]] = relationship(
|
||||
"Dependency", secondary="repo_dependency", back_populates="repos"
|
||||
)
|
||||
__table_args__ = (UniqueConstraint("url", "source_graph_repo_id"),)
|
||||
|
||||
|
||||
class Dependency(Base):
|
||||
|
@ -21,7 +21,7 @@ async def create_or_update_repos_from_source_graph_repos_data(
|
||||
"""
|
||||
insert_statement = sqlalchemy.dialects.sqlite.insert(database.Repo)
|
||||
update_statement = insert_statement.on_conflict_do_update(
|
||||
index_elements=[database.Repo.url],
|
||||
index_elements=[database.Repo.url, database.Repo.source_graph_repo_id],
|
||||
set_={
|
||||
"url": insert_statement.excluded.url,
|
||||
"description": insert_statement.excluded.description,
|
||||
|
BIN
db.sqlite3
BIN
db.sqlite3
Binary file not shown.
@ -1,15 +1,15 @@
|
||||
"""Create Repo, Dependency and RepoDependency tables
|
||||
"""Set up the database
|
||||
|
||||
Revision ID: 0232d84a5aea
|
||||
Revision ID: 90eb9d1f9267
|
||||
Revises:
|
||||
Create Date: 2023-08-02 22:14:12.910175
|
||||
Create Date: 2023-08-15 14:13:30.562069
|
||||
|
||||
"""
|
||||
import sqlalchemy as sa
|
||||
from alembic import op
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = "0232d84a5aea"
|
||||
revision = "90eb9d1f9267"
|
||||
down_revision = None
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
@ -21,8 +21,8 @@ def upgrade() -> None:
|
||||
"dependency",
|
||||
sa.Column("id", sa.Integer(), nullable=False),
|
||||
sa.Column("name", sa.String(length=255), nullable=False),
|
||||
sa.PrimaryKeyConstraint("id"),
|
||||
sa.UniqueConstraint("name"),
|
||||
sa.PrimaryKeyConstraint("id", name=op.f("pk_dependency")),
|
||||
sa.UniqueConstraint("name", name=op.f("uq_dependency_name ")),
|
||||
)
|
||||
op.create_table(
|
||||
"repo",
|
||||
@ -31,19 +31,36 @@ def upgrade() -> None:
|
||||
sa.Column("description", sa.Text(), nullable=False),
|
||||
sa.Column("stars", sa.BigInteger(), nullable=False),
|
||||
sa.Column("source_graph_repo_id", sa.BigInteger(), nullable=True),
|
||||
sa.PrimaryKeyConstraint("id"),
|
||||
sa.UniqueConstraint("source_graph_repo_id"),
|
||||
sa.UniqueConstraint("url"),
|
||||
sa.PrimaryKeyConstraint("id", name=op.f("pk_repo")),
|
||||
sa.UniqueConstraint(
|
||||
"source_graph_repo_id", name=op.f("uq_repo_source_graph_repo_id ")
|
||||
),
|
||||
sa.UniqueConstraint(
|
||||
"url",
|
||||
"source_graph_repo_id",
|
||||
name=op.f("uq_repo_url_source_graph_repo_id "),
|
||||
),
|
||||
sa.UniqueConstraint("url", name=op.f("uq_repo_url ")),
|
||||
)
|
||||
op.create_table(
|
||||
"repo_dependency",
|
||||
sa.Column("repo_id", sa.Integer(), nullable=False),
|
||||
sa.Column("dependency_id", sa.Integer(), nullable=False),
|
||||
sa.ForeignKeyConstraint(
|
||||
["dependency_id"], ["dependency.id"], ondelete="CASCADE"
|
||||
["dependency_id"],
|
||||
["dependency.id"],
|
||||
name=op.f("fk_repo_dependency_dependency_id_dependency"),
|
||||
ondelete="CASCADE",
|
||||
),
|
||||
sa.ForeignKeyConstraint(
|
||||
["repo_id"],
|
||||
["repo.id"],
|
||||
name=op.f("fk_repo_dependency_repo_id_repo"),
|
||||
ondelete="CASCADE",
|
||||
),
|
||||
sa.PrimaryKeyConstraint(
|
||||
"repo_id", "dependency_id", name=op.f("pk_repo_dependency")
|
||||
),
|
||||
sa.ForeignKeyConstraint(["repo_id"], ["repo.id"], ondelete="CASCADE"),
|
||||
sa.PrimaryKeyConstraint("repo_id", "dependency_id"),
|
||||
)
|
||||
# ### end Alembic commands ###
|
||||
|
@ -16,7 +16,7 @@ dependencies = [
|
||||
"alembic",
|
||||
"fastapi[all]",
|
||||
"httpx-sse",
|
||||
"sqlalchemy[asyncio]",
|
||||
"sqlalchemy[asyncio,mypy]",
|
||||
"stamina",
|
||||
"third-party-imports",
|
||||
"typer[all]",
|
||||
@ -114,7 +114,8 @@ convention = "numpy"
|
||||
|
||||
[tool.mypy]
|
||||
plugins = [
|
||||
"pydantic.mypy"
|
||||
"pydantic.mypy",
|
||||
"sqlalchemy.ext.mypy.plugin",
|
||||
]
|
||||
strict = true
|
||||
exclude = [
|
||||
|
@ -66,6 +66,10 @@ markupsafe==2.1.3
|
||||
# mako
|
||||
mdurl==0.1.2
|
||||
# via markdown-it-py
|
||||
mypy==1.4.1
|
||||
# via sqlalchemy
|
||||
mypy-extensions==1.0.0
|
||||
# via mypy
|
||||
orjson==3.9.2
|
||||
# via fastapi
|
||||
pydantic==2.1.1
|
||||
@ -100,7 +104,7 @@ sniffio==1.3.0
|
||||
# anyio
|
||||
# httpcore
|
||||
# httpx
|
||||
sqlalchemy[asyncio]==2.0.19
|
||||
sqlalchemy[asyncio,mypy]==2.0.19
|
||||
# via
|
||||
# alembic
|
||||
# awesome-fastapi-projects (pyproject.toml)
|
||||
@ -118,6 +122,7 @@ typing-extensions==4.7.1
|
||||
# via
|
||||
# alembic
|
||||
# fastapi
|
||||
# mypy
|
||||
# pydantic
|
||||
# pydantic-core
|
||||
# sqlalchemy
|
||||
|
@ -95,7 +95,9 @@ matplotlib-inline==0.1.6
|
||||
mdurl==0.1.2
|
||||
# via markdown-it-py
|
||||
mypy==1.4.1
|
||||
# via awesome-fastapi-projects (pyproject.toml)
|
||||
# via
|
||||
# awesome-fastapi-projects (pyproject.toml)
|
||||
# sqlalchemy
|
||||
mypy-extensions==1.0.0
|
||||
# via
|
||||
# black
|
||||
@ -176,7 +178,7 @@ sniffio==1.3.0
|
||||
# anyio
|
||||
# httpcore
|
||||
# httpx
|
||||
sqlalchemy[asyncio]==2.0.19
|
||||
sqlalchemy[asyncio,mypy]==2.0.19
|
||||
# via
|
||||
# alembic
|
||||
# awesome-fastapi-projects (pyproject.toml)
|
||||
|
@ -75,6 +75,10 @@ markupsafe==2.1.3
|
||||
# mako
|
||||
mdurl==0.1.2
|
||||
# via markdown-it-py
|
||||
mypy==1.4.1
|
||||
# via sqlalchemy
|
||||
mypy-extensions==1.0.0
|
||||
# via mypy
|
||||
orjson==3.9.2
|
||||
# via fastapi
|
||||
packaging==23.1
|
||||
@ -133,7 +137,7 @@ sniffio==1.3.0
|
||||
# anyio
|
||||
# httpcore
|
||||
# httpx
|
||||
sqlalchemy[asyncio]==2.0.19
|
||||
sqlalchemy[asyncio,mypy]==2.0.19
|
||||
# via
|
||||
# alembic
|
||||
# awesome-fastapi-projects (pyproject.toml)
|
||||
@ -151,6 +155,7 @@ typing-extensions==4.7.1
|
||||
# via
|
||||
# alembic
|
||||
# fastapi
|
||||
# mypy
|
||||
# polyfactory
|
||||
# pydantic
|
||||
# pydantic-core
|
||||
|
Loading…
x
Reference in New Issue
Block a user