From 5f7b4102bc9cc7c8750ce3804f6639a0903bf8cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20Ur=C3=ADa?= Date: Sat, 14 Feb 2026 18:37:48 +0100 Subject: [PATCH] [UPD] Added LibraryController --- app/api/actions/create_engine.py | 18 +++ app/api/cruds/{library => base}/__init__.py | 0 app/api/cruds/{library => base}/create.py | 4 +- app/api/cruds/base/delete.py | 7 + app/api/cruds/base/read.py | 8 ++ app/api/cruds/base/update.py | 6 + app/api/cruds/library/delete.py | 7 - app/api/cruds/library/read.py | 8 -- app/api/cruds/library/update.py | 6 - app/controller/__init__.py | 60 ++++++++ app/schema/library/library.py | 2 +- tests/test_controller.py | 143 ++++++++++++++++++++ tests/test_db.py | 24 ++-- 13 files changed, 257 insertions(+), 36 deletions(-) create mode 100644 app/api/actions/create_engine.py rename app/api/cruds/{library => base}/__init__.py (100%) rename app/api/cruds/{library => base}/create.py (76%) create mode 100644 app/api/cruds/base/delete.py create mode 100644 app/api/cruds/base/read.py create mode 100644 app/api/cruds/base/update.py delete mode 100644 app/api/cruds/library/delete.py delete mode 100644 app/api/cruds/library/read.py delete mode 100644 app/api/cruds/library/update.py create mode 100644 app/controller/__init__.py create mode 100644 tests/test_controller.py diff --git a/app/api/actions/create_engine.py b/app/api/actions/create_engine.py new file mode 100644 index 0000000..9d16afa --- /dev/null +++ b/app/api/actions/create_engine.py @@ -0,0 +1,18 @@ +from ...db.config.config import get_engine_configuration +from sqlalchemy import create_engine as sqlalchemy_create_engine +from functools import cache +from sqlalchemy.orm import sessionmaker + + +import logging +logger = logging.getLogger(__name__) + +@cache +def create_engine(*, engine_string=None, echo=None): + logger.debug(f"create_engine {engine_string}") + if engine_string is None: + engine_string, echo = get_engine_configuration() + engine = sqlalchemy_create_engine(engine_string, echo=echo=="true", future=True) # TODO + Session = sessionmaker(engine) + session = Session() + return engine, session \ No newline at end of file diff --git a/app/api/cruds/library/__init__.py b/app/api/cruds/base/__init__.py similarity index 100% rename from app/api/cruds/library/__init__.py rename to app/api/cruds/base/__init__.py diff --git a/app/api/cruds/library/create.py b/app/api/cruds/base/create.py similarity index 76% rename from app/api/cruds/library/create.py rename to app/api/cruds/base/create.py index 6d9eb36..baa0d29 100644 --- a/app/api/cruds/library/create.py +++ b/app/api/cruds/base/create.py @@ -1,10 +1,10 @@ from sqlalchemy.orm import Session -from ....schema.library.library import Library +from ....schema.library.base import Base import logging logger = logging.getLogger(__name__) -def create(session:Session, library:Library): +def create(session:Session, library:Base): logger.debug("Add Library") session.add(library) logger.debug("Added Library") diff --git a/app/api/cruds/base/delete.py b/app/api/cruds/base/delete.py new file mode 100644 index 0000000..eed48c8 --- /dev/null +++ b/app/api/cruds/base/delete.py @@ -0,0 +1,7 @@ +from sqlalchemy.orm import Session + +from ....schema.library.base import Base + +def delete(session:Session, library:Base): + session.delete(library) + session.commit() \ No newline at end of file diff --git a/app/api/cruds/base/read.py b/app/api/cruds/base/read.py new file mode 100644 index 0000000..8bb8645 --- /dev/null +++ b/app/api/cruds/base/read.py @@ -0,0 +1,8 @@ +from sqlalchemy.orm import Session +from sqlalchemy import select + +from ....schema.library.base import Base + +def read(session:Session, _id:int, obj:Base): + stmt = select(obj).where(obj.id == _id) + return session.scalars(stmt).one() \ No newline at end of file diff --git a/app/api/cruds/base/update.py b/app/api/cruds/base/update.py new file mode 100644 index 0000000..36526b4 --- /dev/null +++ b/app/api/cruds/base/update.py @@ -0,0 +1,6 @@ +from sqlalchemy.orm import Session + +from ....schema.library.base import Base + +def update(session:Session, library:Base): + session.commit() \ No newline at end of file diff --git a/app/api/cruds/library/delete.py b/app/api/cruds/library/delete.py deleted file mode 100644 index 001c9be..0000000 --- a/app/api/cruds/library/delete.py +++ /dev/null @@ -1,7 +0,0 @@ -from sqlalchemy.orm import Session - -from ....schema.library.library import Library - -def delete(session:Session, library:Library): - session.delete(library) - session.commit() \ No newline at end of file diff --git a/app/api/cruds/library/read.py b/app/api/cruds/library/read.py deleted file mode 100644 index 49cee27..0000000 --- a/app/api/cruds/library/read.py +++ /dev/null @@ -1,8 +0,0 @@ -from sqlalchemy.orm import Session -from sqlalchemy import select - -from ....schema.library.library import Library - -def read(session:Session, _id:int): - stmt = select(Library).where(Library.id == _id) - return session.scalars(stmt).one() \ No newline at end of file diff --git a/app/api/cruds/library/update.py b/app/api/cruds/library/update.py deleted file mode 100644 index a7a03c2..0000000 --- a/app/api/cruds/library/update.py +++ /dev/null @@ -1,6 +0,0 @@ -from sqlalchemy.orm import Session - -from ....schema.library.library import Library - -def update(session:Session, library:Library): - session.commit() \ No newline at end of file diff --git a/app/controller/__init__.py b/app/controller/__init__.py new file mode 100644 index 0000000..2d301e5 --- /dev/null +++ b/app/controller/__init__.py @@ -0,0 +1,60 @@ +from sqlalchemy import create_engine +from sqlalchemy.orm import sessionmaker + +from app.api.cruds.base import create, read, update, delete +from app.schema.library import Library +from ..db.config.config import get_engine_configuration + +import logging +logging.basicConfig(level=logging.DEBUG) +logger = logging.getLogger(__name__) + +class LibraryController: + def __init__(self, library_id=None, *, engine_string=None, echo=False, engine=None): + if engine_string is None: + engine_string, echo = get_engine_configuration() + if engine is None: + self._engine = create_engine(engine_string, echo=echo=="true", future=True) + else: + self._engine = engine + self._Session = sessionmaker(bind=self.engine) + self._library = None + if library_id is not None: + self.read(library_id) + + @property + def data(self): + return self._library + + @property + def engine(self): + return self._engine + + @property + def Session(self): + return self._Session + + @property + def session(self): + return self.Session() + + def create(self, library:Library): + with self.session as session: + self._library = create(session, library) + return self + + def read(self, _id): + with self.session as session: + self._library = read(session, _id, Library) + return self + + def update(self): + with self.session as session: + session.commit() + + def delete(self): + with self.session as session: + delete(session, self) + del(self) + + diff --git a/app/schema/library/library.py b/app/schema/library/library.py index 1c9b399..c80e010 100644 --- a/app/schema/library/library.py +++ b/app/schema/library/library.py @@ -30,4 +30,4 @@ class Library(Base): ) def __repr__(self) -> str: - return f"Library(id={self.id!r}, name={self.name!r}, notes={self.notes!r}" \ No newline at end of file + return f"Library(id={self.id!r}, name={self.name!r}, notes={self.notes!r})" \ No newline at end of file diff --git a/tests/test_controller.py b/tests/test_controller.py new file mode 100644 index 0000000..17bea4c --- /dev/null +++ b/tests/test_controller.py @@ -0,0 +1,143 @@ +import os +import unittest + +from sqlalchemy.orm import sessionmaker + +from app.api.actions import install +from app.schema.library import Library, Tag, Book, BookTag, Path, Env +from app.controller import LibraryController + +import logging +logging.basicConfig(level=logging.DEBUG) +logger = logging.getLogger(__name__) + +class TestDB(unittest.TestCase): + + def setUp(self): + os.environ["DEV_URIA_BIBLIOGAME_CONFIG_DB"] = "sqlite:///" + os.environ["DEV_URIA_BIBLIOGAME_DEBUG"] = "true" + self.engine = install() + + self.library = LibraryController(engine = self.engine) + + self.tags = [ + Tag( + name="Foo" + ), + Tag( + name="Bar" + ) + ] + self.library.create(Library( + name="Library Test", + notes="My duckling library test", + paths=[ + Path( + path="/home/ivan/Documentos/ttprpg" + ) + ], + envs=[ + Env( + key="ENVIRONMENT_VARIABLE", + value="Clearly an environment variable" + ) + ], + books=[ + Book( + name="Test book", + tags=[ + BookTag( + tag=self.tags[0] + ) + ] + ), + ], + tags=self.tags + )) + return super().setUp() + + def test_install(self): + library = LibraryController(1, engine = self.engine) + library_string = str(library.data) + self.assertEqual(library_string, str(self.library.data)) + """ + def test_read_name(self): + library = read(self.session, 1) + logger.debug(f"Name: {library.name}") + self.assertEqual(library.name, self.library.name) + self.assertEqual(library.name, "Library Test") + + def test_read_notes(self): + library = read(self.session, 1) + logger.debug(f"Notes: {library.notes}") + self.assertEqual(library.notes, self.library.notes) + self.assertEqual(library.notes, "My duckling library test") + + def test_read_path(self): + library = read(self.session, 1) + logger.debug(f"PATH: {library.paths[0].path}") + self.assertEqual(library.paths[0].path, self.library.paths[0].path) + self.assertEqual(library.paths[0].path, "/home/ivan/Documentos/ttprpg") + + def test_read_env(self): + library = read(self.session, 1) + logger.debug(f"ENV: {library.envs[0].key} - {library.envs[0].value}") + self.assertEqual(library.envs[0].key, self.library.envs[0].key) + self.assertEqual(library.envs[0].value, self.library.envs[0].value) + self.assertEqual(library.envs[0].key, "ENVIRONMENT_VARIABLE") + self.assertEqual(library.envs[0].value, "Clearly an environment variable") + + def test_read_book(self): + library = read(self.session, 1) + book = library.books[0] + logger.debug(f"BOOK: {book}") + self.assertEqual(book.name, self.library.books[0].name) + self.assertEqual(book.name, "Test book") + + def test_read_tags(self): + library = read(self.session, 1) + tags = library.tags + self.assertEqual(tags, self.library.tags) + self.assertEqual(tags, self.tags) + self.assertEqual(str(tags[0]), str(self.tags[0])) + self.assertEqual(tags[0].name, self.tags[0].name) + self.assertEqual(tags[0].name, "Foo") + self.assertEqual(str(tags[1]), str(self.tags[1])) + self.assertEqual(tags[1].name, self.tags[1].name) + self.assertEqual(tags[1].name, "Bar") + + def test_read_book_tags(self): + library = read(self.session, 1) + book = library.books[0] + tags = library.tags + logger.debug(f"BOOK TAGS: {book.tags}") + self.assertEqual(str(book.tags[0].tag), str(self.tags[0])) + self.assertEqual(str(book.tags[0].tag), str(tags[0])) + self.assertEqual(book.tags[0].tag.name, tags[0].name) + self.assertEqual(book.tags[0].tag.name, "Foo") + self.assertNotEqual(book.tags[0].tag.name, "Bar") + + def test_update_name(self): + library = read(self.session, 1) + library.name = "Another Library" + update(self.session, library) + library1 = read(self.session, 1) + self.assertEqual(library1.name, self.library.name) + self.assertNotEqual(library1.name, "Library Test") + self.assertEqual(library1.name, "Another Library") + + def test_update_name(self): + library = read(self.session, 1) + library.books[0].name = "Another Book on the shelf" + update(self.session, library) + + library1 = read(self.session, 1) + book = library1.books[0] + + self.assertEqual(book.name, self.library.books[0].name) + self.assertNotEqual(book.name, "Test book") + self.assertEqual(book.name, "Another Book on the shelf") + """ + +if __name__ == "__main__": + unittest.main() \ No newline at end of file diff --git a/tests/test_db.py b/tests/test_db.py index 1d91146..b19a7e3 100644 --- a/tests/test_db.py +++ b/tests/test_db.py @@ -4,7 +4,7 @@ import unittest from sqlalchemy.orm import sessionmaker from app.api.actions import install -from app.api.cruds.library import create, read, update +from app.api.cruds.base import create, read, update from app.schema.library import Library, Path, Env, Book, Tag, BookTag import logging @@ -57,29 +57,29 @@ class TestDB(unittest.TestCase): return super().setUp() def test_install(self): - library_string = str(read(self.session, 1)) + library_string = str(read(self.session, 1, Library)) self.assertEqual(library_string, str(self.library)) def test_read_name(self): - library = read(self.session, 1) + library = read(self.session, 1, Library) logger.debug(f"Name: {library.name}") self.assertEqual(library.name, self.library.name) self.assertEqual(library.name, "Library Test") def test_read_notes(self): - library = read(self.session, 1) + library = read(self.session, 1, Library) logger.debug(f"Notes: {library.notes}") self.assertEqual(library.notes, self.library.notes) self.assertEqual(library.notes, "My duckling library test") def test_read_path(self): - library = read(self.session, 1) + library = read(self.session, 1, Library) logger.debug(f"PATH: {library.paths[0].path}") self.assertEqual(library.paths[0].path, self.library.paths[0].path) self.assertEqual(library.paths[0].path, "/home/ivan/Documentos/ttprpg") def test_read_env(self): - library = read(self.session, 1) + library = read(self.session, 1, Library) logger.debug(f"ENV: {library.envs[0].key} - {library.envs[0].value}") self.assertEqual(library.envs[0].key, self.library.envs[0].key) self.assertEqual(library.envs[0].value, self.library.envs[0].value) @@ -87,14 +87,14 @@ class TestDB(unittest.TestCase): self.assertEqual(library.envs[0].value, "Clearly an environment variable") def test_read_book(self): - library = read(self.session, 1) + library = read(self.session, 1, Library) book = library.books[0] logger.debug(f"BOOK: {book}") self.assertEqual(book.name, self.library.books[0].name) self.assertEqual(book.name, "Test book") def test_read_tags(self): - library = read(self.session, 1) + library = read(self.session, 1, Library) tags = library.tags self.assertEqual(tags, self.library.tags) self.assertEqual(tags, self.tags) @@ -106,7 +106,7 @@ class TestDB(unittest.TestCase): self.assertEqual(tags[1].name, "Bar") def test_read_book_tags(self): - library = read(self.session, 1) + library = read(self.session, 1, Library) book = library.books[0] tags = library.tags logger.debug(f"BOOK TAGS: {book.tags}") @@ -117,7 +117,7 @@ class TestDB(unittest.TestCase): self.assertNotEqual(book.tags[0].tag.name, "Bar") def test_update_name(self): - library = read(self.session, 1) + library = read(self.session, 1, Library) library.name = "Another Library" update(self.session, library) library1 = read(self.session, 1) @@ -126,11 +126,11 @@ class TestDB(unittest.TestCase): self.assertEqual(library1.name, "Another Library") def test_update_name(self): - library = read(self.session, 1) + library = read(self.session, 1, Library) library.books[0].name = "Another Book on the shelf" update(self.session, library) - library1 = read(self.session, 1) + library1 = read(self.session, 1, Library) book = library1.books[0] self.assertEqual(book.name, self.library.books[0].name)