Skip to content

Commit

Permalink
Setup Alembic
Browse files Browse the repository at this point in the history
  • Loading branch information
berrydenhartog committed May 6, 2024
1 parent 0844f5c commit 7ce67b2
Show file tree
Hide file tree
Showing 13 changed files with 66 additions and 85 deletions.
3 changes: 3 additions & 0 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
"POETRY_VIRTUALENVS_CREATE": "false"
},
"remoteUser": "root",
"features": {
"ghcr.io/devcontainers/features/docker-outside-of-docker:1": {}
},
"postCreateCommand": ".devcontainer/postCreateCommand.sh",
"customizations": {
"vscode": {
Expand Down
1 change: 1 addition & 0 deletions .env
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ PROJECT_NAME="TAD"
BACKEND_CORS_ORIGINS="http://localhost,https://localhost,http://127.0.0.1,https://127.0.0.1"
SECRET_KEY=changethisa

SQLALCHEMY_SCHEME="postgresql+psycopg"
POSTGRES_PORT=5432
POSTGRES_DB=app
POSTGRES_USER=postgres
Expand Down
4 changes: 2 additions & 2 deletions BUILD.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ poetry install
when poetry is done installing all dependencies you can start using the tool.

```shell
poetry run python -m tad
poetry run python -m uvicorn tad.main:app
```

## Building TAD with Containers
Expand Down Expand Up @@ -50,4 +50,4 @@ For testing, linting and other feature we use several tools. You can look up the

## Devcontainers

[VSCode](https://code.visualstudio.com/) has great support for devcontainers. If your editor had support for devcontainers you can also use them to start the devcontainer. Devcontaines offer great standardized environments for development.
[VSCode](https://code.visualstudio.com/) has great support for devcontainers. If your editor has support for devcontainers you can also use them to start the devcontainer. Devcontaines offer great standardized environments for development.
11 changes: 8 additions & 3 deletions compose.yml
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
services:
tad:
build: .
build:
context: .
dockerfile: tad/Dockerfile
image: ghcr.io/minbzk/tad:latest
restart: unless-stopped
depends_on:
- db
db:
condition: service_healthy
env_file:
- .env
ports:
- 8001:8000
- 8000:8000

db:
image: postgres:12
Expand All @@ -22,6 +25,8 @@ services:
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD?Variable not set}
- POSTGRES_USER=${POSTGRES_USER?Variable not set}
- POSTGRES_DB=${POSTGRES_DB?Variable not set}
healthcheck:
test: ["CMD-SHELL", "pg_isready", "-d", "tad"]

#TODO(berry): Traefik

Expand Down
10 changes: 4 additions & 6 deletions publiccode.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# metadata file that makes public software easily discoverable.
# More info at https://github.com/italia/publiccode.yml

publiccodeYmlVersion: '0.2'
publiccodeYmlVersion: "0.2"
categories:
- it-development
description:
Expand All @@ -14,9 +14,7 @@ description:
- Algorithm
genericName: tad
longDescription: |
TAD is a modern tool to apply technical and non-technical tests for an AI model.
TAD is a tool for Transparency Algorithm Decision making.
TAD is the acronym for Transparency of Algorithmic Decision making. The goal is to make algorithmic systems more transparant. It achieves this by generating standardized reports. These reports consist of both technical aspects as well as descriptive information about the system and regulatory assessments. For both the system and the model the lifecycle is important, so this is incorporated in both the tool as well as the reports. The definition for an algorithm is derived from the Algoritmeregister.
shortDescription: TAD is a tool for Transparency Algorithm Decision making
developmentStatus: concept
Expand All @@ -34,6 +32,6 @@ maintenance:
name: tad
platforms:
- web
releaseDate: '2024-04-25'
releaseDate: "2024-04-25"
softwareType: standalone/web
url: 'https://github.com/MinBZK/tad'
url: "https://github.com/MinBZK/tad"
3 changes: 0 additions & 3 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,6 @@ pyright = "^1.1.360"
cyclonedx-bom = "^4.4.2"
pip-licenses = "^4.4.0"

[tool.poetry.scripts]
tad = 'tad.__main__:main'

[tool.poetry.urls]
"Issue Tracker" = "https://github.com/MinBZK/tad/issues"

Expand Down
13 changes: 5 additions & 8 deletions Dockerfile → tad/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ ARG PYTHON_VERSION=3.11.7-slim
FROM --platform=$BUILDPLATFORM python:${PYTHON_VERSION} as project-base

LABEL [email protected] \
organization=MinBZK \
license=EUPL-1.2
organization=MinBZK \
license=EUPL-1.2

ENV PYTHONUNBUFFERED=1 \
PYTHONDONTWRITEBYTECODE=1 \
Expand All @@ -16,7 +16,7 @@ ENV PYTHONUNBUFFERED=1 \
POETRY_HOME='/usr/local'

RUN apt-get update && apt-get install -y --no-install-recommends \
curl \
curl libpq-dev \
&& rm -rf /var/lib/apt/lists/*

RUN curl -sSL https://install.python-poetry.org | python3 -
Expand Down Expand Up @@ -46,11 +46,8 @@ FROM project-base as production

COPY . /app/

EXPOSE 8000
RUN poetry install

ENV PYTHONPATH=/app/
WORKDIR /app/tad/
WORKDIR /app/

# change this to a usefull command
CMD ["python", "-m", "uvicorn", "main:app" ]
CMD ["python", "-m", "uvicorn", "--host", "0.0.0.0", "tad.main:app" ]
2 changes: 1 addition & 1 deletion alembic.ini → tad/alembic.ini
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

[alembic]
# path to migration scripts
script_location = tad/alembic
script_location = alembic

# template used to generate migration file names; The default value is %%(rev)s_%%(slug)s
# Uncomment the line below if you want the files to be prepended with date and time
Expand Down
29 changes: 6 additions & 23 deletions tad/alembic/env.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,36 +5,22 @@

from alembic import context

# this is the Alembic Config object, which provides
# access to the values within the .ini file in use.
config = context.config

# Interpret the config file for Python logging.
# This line sets up loggers basically.
if config.config_file_name is not None:
fileConfig(config.config_file_name)

# add your model's MetaData object here
# for 'autogenerate' support
# from myapp import mymodel
# target_metadata = mymodel.Base.metadata
from tad.models import SQLModel # noqa

target_metadata = SQLModel.metadata

# other values from the config, defined by the needs of env.py,
# can be acquired:
# my_important_option = config.get_main_option("my_important_option")
# ... etc.


def get_url():
scheme=os.getenv("SQLALCHEMY_SCHEME", "sqlite")
scheme = os.getenv("SQLALCHEMY_SCHEME", "sqlite")

if scheme == "sqlite":
file = os.getenv("SQLITE_FILE", "/tmp/database")
return f"{scheme}:///{file}"

file = os.getenv("SQLITE_FILE", "./database")
return f"{scheme}://{file}"

user = os.getenv("POSTGRES_USER", "postgres")
password = os.getenv("POSTGRES_PASSWORD", "")
Expand All @@ -43,6 +29,7 @@ def get_url():
db = os.getenv("POSTGRES_DB", "tad")
return f"{scheme}://{user}:{password}@{server}:{port}/{db}"


def run_migrations_offline():
"""Run migrations in 'offline' mode.
Expand All @@ -56,9 +43,7 @@ def run_migrations_offline():
"""
url = get_url()
context.configure(
url=url, target_metadata=target_metadata, literal_binds=True, compare_type=True
)
context.configure(url=url, target_metadata=target_metadata, literal_binds=True, compare_type=True)

with context.begin_transaction():
context.run_migrations()
Expand All @@ -80,9 +65,7 @@ def run_migrations_online():
)

with connectable.connect() as connection:
context.configure(
connection=connection, target_metadata=target_metadata, compare_type=True
)
context.configure(connection=connection, target_metadata=target_metadata, compare_type=True)

with context.begin_transaction():
context.run_migrations()
Expand Down
53 changes: 28 additions & 25 deletions tad/alembic/versions/99fb931b1324_.py
Original file line number Diff line number Diff line change
@@ -1,49 +1,52 @@
"""empty message
Revision ID: 99fb931b1324
Revises:
Revises:
Create Date: 2024-05-02 12:04:56.694709
"""
from typing import Sequence, Union

from alembic import op
from collections.abc import Sequence

import sqlalchemy as sa
import sqlmodel.sql.sqltypes

from alembic import op

# revision identifiers, used by Alembic.
revision: str = '99fb931b1324'
down_revision: Union[str, None] = None
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None
revision: str = "99fb931b1324"
down_revision: str | None = None
branch_labels: str | Sequence[str] | None = None
depends_on: str | Sequence[str] | None = None


def upgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.create_table('hero',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('name', sqlmodel.sql.sqltypes.AutoString(), nullable=False),
sa.Column('secret_name', sqlmodel.sql.sqltypes.AutoString(), nullable=False),
sa.Column('age', sa.Integer(), nullable=True),
sa.PrimaryKeyConstraint('id')
op.create_table(
"hero",
sa.Column("id", sa.Integer(), nullable=False),
sa.Column("name", sqlmodel.sql.sqltypes.AutoString(), nullable=False),
sa.Column("secret_name", sqlmodel.sql.sqltypes.AutoString(), nullable=False),
sa.Column("age", sa.Integer(), nullable=True),
sa.PrimaryKeyConstraint("id"),
)
op.create_table('user',
sa.Column('email', sqlmodel.sql.sqltypes.AutoString(), nullable=False),
sa.Column('is_active', sa.Boolean(), nullable=False),
sa.Column('is_superuser', sa.Boolean(), nullable=False),
sa.Column('full_name', sqlmodel.sql.sqltypes.AutoString(), nullable=True),
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('hashed_password', sqlmodel.sql.sqltypes.AutoString(), nullable=False),
sa.PrimaryKeyConstraint('id')
op.create_table(
"user",
sa.Column("email", sqlmodel.sql.sqltypes.AutoString(), nullable=False),
sa.Column("is_active", sa.Boolean(), nullable=False),
sa.Column("is_superuser", sa.Boolean(), nullable=False),
sa.Column("full_name", sqlmodel.sql.sqltypes.AutoString(), nullable=True),
sa.Column("id", sa.Integer(), nullable=False),
sa.Column("hashed_password", sqlmodel.sql.sqltypes.AutoString(), nullable=False),
sa.PrimaryKeyConstraint("id"),
)
op.create_index(op.f('ix_user_email'), 'user', ['email'], unique=True)
op.create_index(op.f("ix_user_email"), "user", ["email"], unique=True)
# ### end Alembic commands ###


def downgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.drop_index(op.f('ix_user_email'), table_name='user')
op.drop_table('user')
op.drop_table('hero')
op.drop_index(op.f("ix_user_email"), table_name="user")
op.drop_table("user")
op.drop_table("hero")
# ### end Alembic commands ###
9 changes: 5 additions & 4 deletions tad/core/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
from pydantic import (
AnyUrl,
BeforeValidator,
PostgresDsn,
computed_field,
model_validator,
)
Expand Down Expand Up @@ -41,16 +40,18 @@ def server_host(self) -> str:

PROJECT_NAME: str = "TAD"

# SQLALCHEMY_SCHEME: str = "postgresql+psycopg"
SQLALCHEMY_SCHEME: str = "sqlite"
if ENVIRONMENT == "local":
SQLALCHEMY_SCHEME: str = "sqlite"
else:
SQLALCHEMY_SCHEME: str = "postgresql+psycopg"

POSTGRES_SERVER: str = "db"
POSTGRES_PORT: int = 5432
POSTGRES_USER: str = "postgres"
POSTGRES_PASSWORD: str
POSTGRES_DB: str = "tad"

SQLITE_FILE: str = "/tmp/database"
SQLITE_FILE: str = "./database"

@computed_field # type: ignore[misc]
@property
Expand Down
9 changes: 0 additions & 9 deletions tad/main.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
import logging

from fastapi import FastAPI
from sqlmodel import Session, select
from starlette.middleware.cors import CORSMiddleware

from tad.core.config import settings
from tad.core.db import engine, init_db
from tad.models import Hero

logger = logging.getLogger(__name__)

Expand All @@ -24,10 +21,4 @@

@app.get("/")
async def root():
init_db()
# with Session(engine) as session:
# statement = select(UserBase).where(UserBase.full_name == "Spider-Boy")
# hero = session.exec(statement).first()
# print(hero)

return {"message": "Hello World"}
4 changes: 3 additions & 1 deletion tad/models.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from sqlmodel import Field, Relationship, SQLModel
from sqlmodel import Field, SQLModel


class Hero(SQLModel, table=True):
Expand All @@ -7,12 +7,14 @@ class Hero(SQLModel, table=True):
secret_name: str
age: int | None = None


class UserBase(SQLModel):
email: str = Field(unique=True, index=True)
is_active: bool = True
is_superuser: bool = False
full_name: str | None = None


# Database model, database table inferred from class name
class User(UserBase, table=True):
id: int | None = Field(default=None, primary_key=True)
Expand Down

0 comments on commit 7ce67b2

Please sign in to comment.