evaluate sqlmodel

This commit is contained in:
2025-04-13 16:16:10 +02:00
parent a43e2c806c
commit b14a267b5b
107 changed files with 2517 additions and 6 deletions
+31
View File
@@ -0,0 +1,31 @@
.PHONY: clean virtualenv test docker dist dist-upload
clean:
find . -name '*.py[co]' -delete
virtualenv:
virtualenv --prompt '|> kontor <| ' env
env/bin/pip install -r requirements-dev.txt
env/bin/python setup.py develop
@echo
@echo "VirtualENV Setup Complete. Now run: source env/bin/activate"
@echo
test:
python -m pytest \
-v \
--cov=kontor \
--cov-report=term \
--cov-report=html:coverage-report \
tests/
docker: clean
docker build -t kontor-api:latest .
dist: clean
rm -rf dist/*
python setup.py sdist
python setup.py bdist_wheel
dist-upload:
twine upload dist/*
+59
View File
@@ -0,0 +1,59 @@
from argparse import ArgumentParser, ArgumentDefaultsHelpFormatter
from pathlib import Path
import logging.config
import yaml
from platformdirs import PlatformDirs
from sqlmodel import SQLModel, create_engine, Session, select
from model import Comic, Publisher
from model.media import MediaFile
parser = ArgumentParser(formatter_class=ArgumentDefaultsHelpFormatter)
parser.add_argument('--recreate-db', action='store_true')
parser.add_argument('--verbose', '-v', action='count', default=0)
parser.add_argument('--file', '-f', default='~/data.json')
parser.add_argument('--config', '-c', default='kontor')
args = parser.parse_args()
def get_logger(level: int, config: str):
dirs = PlatformDirs(config)
logging_config = Path(dirs.user_config_dir, 'logging-config.yaml')
with open(logging_config, 'rt') as f:
configDict = yaml.safe_load(f.read())
logging.config.dictConfig(configDict)
logger = logging.getLogger('development')
if level is not None:
match level:
case 0:
logger.setLevel(logging.INFO)
case 1:
logger.setLevel(logging.DEBUG)
case _:
logger.setLevel(logging.CRITICAL)
return logger
if __name__ == '__main__':
log = get_logger(args.verbose, args.config)
log.info('kontor started')
dirs = PlatformDirs(args.config)
database_config = Path(dirs.user_config_dir, 'database-config.yaml')
with open(database_config, 'rt') as f:
db_config = yaml.safe_load(f.read())
print(db_config)
connect_string = ('mariadb+mariadbconnector://{}:{}@{}:{}/{}'.format(
db_config['mariadb']['user'],
db_config['mariadb']['password'],
db_config['mariadb']['host'],
db_config['mariadb']['port'],
db_config['mariadb']['database']
))
engine = create_engine(connect_string, echo=True)
SQLModel.metadata.create_all(engine)
with Session(engine) as session:
files = session.exec(select(MediaFile)).all()
for file in files:
print("{} {}".format(file, file.actors))
log.info('kontor finished')
+1
View File
@@ -0,0 +1 @@
from .comic import Comic, Publisher, ComicWork, Artist, Worktype
+11
View File
@@ -0,0 +1,11 @@
import uuid
from datetime import datetime
from sqlmodel import SQLModel, Field
class AbstractEntity(SQLModel, table=False):
id: uuid.UUID = Field(default_factory=uuid.uuid4, primary_key=True)
created_date: datetime = Field(default_factory=datetime.now, nullable=False)
last_modified_date: datetime = Field(default_factory=datetime.now, nullable=False)
version: int = Field(default=0)
+58
View File
@@ -0,0 +1,58 @@
import uuid
from datetime import datetime
from sqlmodel import Field, Relationship, SQLModel
from model.base import AbstractEntity
class Publisher(AbstractEntity, table=True):
name: str = Field(index=True, unique=True)
comics: list["Comic"] = Relationship(back_populates="publisher")
def __repr__(self):
return f'Publisher({self.id} {self.name})'
def __str__(self):
return self.__repr__()
class Comic(AbstractEntity, table=True):
title: str = Field(index=True, unique=True)
publisher_id: uuid.UUID | None = Field(default=None, foreign_key="publisher.id")
publisher: Publisher | None = Relationship(back_populates="comics")
current_order: int = Field(default=False)
completed: int = Field(nullable=False)
#issues: list["Issue"] = Relationship(back_populates="comic")
#story_arcs: list["StoryArc"] = Relationship(back_populates="comic")
#trade_paperbacks: list["TradePaperback"] = Relationship(back_populates="comic")
#volumes: list["Volume"] = Relationship(back_populates="comic")
#comic_works: list["ComicWork"] = Relationship(back_populates="comic")
class Artist(AbstractEntity, table=True):
name: str = Field(nullable=False)
comic_works: list["ComicWork"] = Relationship(back_populates="artist")
class Worktype(AbstractEntity, table=True):
name: str = Field(nullable=False, unique=True)
#comic_works: list["ComicWork"] = Relationship(back_populates="worktype")
def __repr__(self):
return f'Worktype({self.id} {self.version} {self.name} {len(self.comic_works)})'
def __str__(self):
return f'{self.name}({self.id})'
class ComicWork(AbstractEntity, table=True):
__tablename__ = "comic_work"
comic_id: uuid.UUID | None = Field(nullable=False, foreign_key="comic.id")
#comic: Comic = Relationship(back_populates="comic_works")
artist_id: uuid.UUID | None = Field(nullable=False, foreign_key="artist.id")
artist: Artist = Relationship(back_populates="comic_works")
work_type_id: uuid.UUID | None = Field(nullable=False, foreign_key="worktype.id")
#worktype = Relationship(back_populates="comic_works")
+28
View File
@@ -0,0 +1,28 @@
from sqlmodel import Field, Relationship, table
from uuid import UUID
from .base import AbstractEntity
class MediaActorFile(AbstractEntity, table=True):
__tablename__ = "media_actor_file"
media_actor_id: UUID = Field(nullable=False, foreign_key="media_actor.id")
media_file_id: UUID = Field(nullable=False, foreign_key="media_file.id")
class MediaFile(AbstractEntity, table=True):
__tablename__ = "media_file"
cloud_link: str = Field(nullable=True, max_length=255)
file_name: str = Field(nullable=True, max_length=255)
path : str = Field(nullable=True, max_length=255)
title: str = Field(nullable=True, max_length=255)
url: str = Field(nullable=True, max_length=255)
actors : list["MediaActor"] = Relationship(back_populates="videos", link_model=MediaActorFile)
class MediaActor(AbstractEntity, table=True):
__tablename__ = "media_actor"
name: str = Field(nullable=True, max_length=255)
videos : list["MediaFile"] = Relationship(back_populates="actors", link_model=MediaActorFile)
+29
View File
@@ -0,0 +1,29 @@
[build-system]
requires = ["setuptools"]
[project]
name = "kontor-cli"
version = "0.1.0"
dependencies = [
"mariadb",
"sqlmodel",
"pathlib",
"platformdirs",
"pyyaml",
"beautifulsoup4",
]
requires-python = ">=3.10"
authors = [
{name = "Thomas Peetz", email = "thomas.peetz@thpeetz.de"}
]
maintainers = [
{name = "Thomas Peetz", email = "thomas.peetz@thpeetz.de"}
]
description = "CLI for Kontor application"
readme = "README.md"
classifiers = [
"Development Status :: 4 - Beta",
"Programming Language :: Python"
]
[project-scripts]
kontor = "kontor::main"
+8
View File
@@ -0,0 +1,8 @@
-r requirements.txt
pytest
pytest-cov
coverage
twine>=1.11.0
setuptools>=38.6.0
wheel>=0.31.0
+7
View File
@@ -0,0 +1,7 @@
mariadb
sqlalchemy
pathlib
platformdirs
pyyaml
beautifulsoup4
sqlmodel
View File