Added project structure and basic data models

This commit is contained in:
Donkie
2023-04-01 16:24:08 +02:00
commit c9b4705b28
18 changed files with 1031 additions and 0 deletions

0
spoolson/__init__.py Normal file
View File

0
spoolson/api/__init__.py Normal file
View File

View File

View File

@@ -0,0 +1,11 @@
"""Filament related endpoints."""
from typing import Union
from fastapi import APIRouter
from spoolson.api.v1.models import Filament
router = APIRouter(
prefix="/filament",
tags=["filament"],
)

44
spoolson/api/v1/models.py Normal file
View File

@@ -0,0 +1,44 @@
"""Pydantic data models for typing the FastAPI request/responses."""
from datetime import datetime
from typing import Optional
from pydantic import BaseModel, Field
class Vendor(BaseModel):
id: int = Field(description="Unique internal ID of this vendor.")
name: str = Field(max_length=64, description="Vendor name.")
comment: Optional[str] = Field(max_length=1024, description="Free text comment about this vendor.")
class Filament(BaseModel):
id: int = Field(description="Unique internal ID of this filament type.")
name: Optional[str] = Field(
max_length=64,
description=(
"Filament name, to distinguish this filament type among others from the same vendor."
"Should contain its color for example."
),
)
vendor: Optional[Vendor] = Field(description="The vendor of this filament type.")
material: Optional[str] = Field(max_length=64, description="The material of this filament, e.g. PLA.")
price: Optional[float] = Field(ge=0, description="The price of this filament in the system configured currency.")
density: float = Field(gt=0, description="The density of this filament in g/cm3.")
diameter: float = Field(gt=0, description="The diameter of this filament in mm.")
weight: Optional[float] = Field(gt=0, description="The weight of the filament in a full spool.")
spool_weight: Optional[float] = Field(gt=0, description="The empty spool weight.")
article_number: Optional[str] = Field(max_length=64, description="Vendor article number, e.g. EAN, QR code, etc.")
comment: Optional[str] = Field(max_length=1024, description="Free text comment about this filament type.")
class Spool(BaseModel):
id: int = Field(description="Unique internal ID of this spool of filament.")
registered: datetime = Field(description="When the spool was registered in the database.")
first_used: Optional[datetime] = Field(description="First logged occurence of spool usage.")
last_used: Optional[datetime] = Field(description="Last logged occurence of spool usage.")
filament: Filament = Field(description="The filament type of this spool.")
weight: float = Field(ge=0, description="Remaining weight of filament on the spool.")
location: Optional[str] = Field(max_length=64, description="Where this spool can be found.")
lot_nr: Optional[str] = Field(max_length=64, description="Vendor manufacturing lot/batch number of the spool.")
comment: Optional[str] = Field(max_length=1024, description="Free text comment about this specific spool.")

13
spoolson/api/v1/router.py Normal file
View File

@@ -0,0 +1,13 @@
"""Router setup for the v1 version of the API."""
from fastapi import APIRouter
from . import filament, spool, vendor
router = APIRouter(
prefix="/v1",
tags=["v1"],
)
router.include_router(filament.router)
router.include_router(spool.router)
router.include_router(vendor.router)

7
spoolson/api/v1/spool.py Normal file
View File

@@ -0,0 +1,7 @@
"""Spool related endpoints."""
from fastapi import APIRouter
router = APIRouter(
tags=["spool"],
)

View File

@@ -0,0 +1,7 @@
"""Vendor related endpoints."""
from fastapi import APIRouter
router = APIRouter(
tags=["vendor"],
)

View File

View File

@@ -0,0 +1,7 @@
from sqlalchemy.ext.asyncio import async_sessionmaker, create_async_engine
SQLALCHEMY_DATABASE_URL = "sqlite:///./sql_app.db"
# SQLALCHEMY_DATABASE_URL = "postgresql://user:password@postgresserver/db"
engine = create_async_engine(SQLALCHEMY_DATABASE_URL, connect_args={"check_same_thread": False})
SessionLocal = async_sessionmaker(engine, autocommit=False, autoflush=False)

View File

@@ -0,0 +1,51 @@
"""SQLAlchemy data models."""
from datetime import datetime
from typing import Optional
from sqlalchemy import Integer, String
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, relationship
class Base(DeclarativeBase):
pass
class Vendor(Base):
__tablename__ = "vendor"
id: Mapped[int] = mapped_column(Integer, primary_key=True, index=True)
name: Mapped[str] = mapped_column(String(64))
comment: Mapped[Optional[str]] = mapped_column(String(1024))
class Filament(Base):
__tablename__ = "material"
id: Mapped[int] = mapped_column(primary_key=True, index=True)
name: Mapped[Optional[str]] = mapped_column(String(64))
vendor: Mapped[Optional["Vendor"]] = relationship()
material: Mapped[Optional[str]] = mapped_column(String(64))
price: Mapped[Optional[float]] = mapped_column()
density: Mapped[float] = mapped_column()
diameter: Mapped[float] = mapped_column()
weight: Mapped[Optional[float]] = mapped_column()
spool_weight: Mapped[Optional[float]] = mapped_column()
article_number: Mapped[Optional[str]] = mapped_column(String(64))
comment: Mapped[Optional[str]] = mapped_column(String(1024))
# TODO: Print settings
# TODO: Color?
class Spool(Base):
__tablename__ = "spool"
id: Mapped[int] = mapped_column(primary_key=True, index=True)
registered: Mapped[datetime] = mapped_column()
first_used: Mapped[Optional[datetime]] = mapped_column()
last_used: Mapped[Optional[datetime]] = mapped_column()
filament: Mapped["Filament"] = mapped_column(index=True)
weight: Mapped[float] = mapped_column()
location: Mapped[Optional[str]] = mapped_column(String(64))
lot_nr: Mapped[Optional[str]] = mapped_column(String(64))
comment: Mapped[Optional[str]] = mapped_column(String(1024))

9
spoolson/main.py Normal file
View File

@@ -0,0 +1,9 @@
"""Main entrypoint to the server."""
from fastapi import FastAPI
import spoolson.api.v1.router
app = FastAPI()
app.include_router(spoolson.api.v1.router.router)