Compare commits

..

11 Commits

Author SHA1 Message Date
969333998c [UPD] Exception handling 2026-02-15 20:53:32 +01:00
2a8a44e80b [WIP] Exception handling 2026-02-15 17:39:21 +01:00
7c3593d066 [UPD] Delete Library 2026-02-15 16:34:43 +01:00
c701a4ab9b [WIP] Library REST API 2026-02-15 11:32:33 +01:00
c468f51672 [UPD] Added api to create Library 2026-02-15 10:36:37 +01:00
bb8324ad1d [UPD] Added config file 2026-02-15 08:55:57 +01:00
d84d62c79f [FEA] Added Conroller for sanity 2026-02-15 08:47:46 +01:00
f50a9d0916 [FEA] Added Conroller for sanity 2026-02-15 08:38:55 +01:00
5f7b4102bc [UPD] Added LibraryController 2026-02-14 18:37:48 +01:00
5fc1dc1b82 [REF] Even Less Files 2026-02-13 15:07:44 +01:00
368038bdb9 [REF] Less Files 2026-02-13 15:07:11 +01:00
56 changed files with 686 additions and 134 deletions

1
.python-version Normal file
View File

@@ -0,0 +1 @@
3.12.3

View File

@@ -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

View File

@@ -1,12 +1,17 @@
from sqlalchemy import create_engine from sqlalchemy import create_engine
from sqlalchemy.orm import Session
from ...schema.library.base import Base from ...schema.library.base import Base
from ...db.config.config import get_engine_configuration from ...db.config.config import get_engine_configuration
import logging
logger = logging.getLogger(__name__)
def install(): def install():
logger.info("Installing")
engine_string, echo = get_engine_configuration() engine_string, echo = get_engine_configuration()
logger.debug(f"engine_string: {engine_string}")
engine = create_engine(engine_string, echo=echo=="true", future=True) # TODO engine = create_engine(engine_string, echo=echo=="true", future=True) # TODO
metadata = Base.metadata metadata = Base.metadata
metadata.create_all(engine) metadata.create_all(engine)
logger.info("Installed")
return engine return engine

View File

@@ -0,0 +1,4 @@
from .create import create
from .read import read, read_all
from .update import update
from .delete import delete

View File

@@ -1,14 +1,15 @@
from sqlalchemy.orm import Session from sqlalchemy.orm import Session
from ....schema.library.library import Library from ....schema.library.base import Base
import logging import logging
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
def create(session:Session, library:Library): def create(session:Session, library:Base):
logger.debug("Add Library") logger.debug("Add Library")
session.add(library) session.add(library)
logger.debug("Added Library") logger.debug("Added Library")
session.commit() session.commit()
logger.debug("Committed Library") logger.debug("Committed Library")
session.refresh(library) session.refresh(library)
logger.debug("Rerfreshed Library") logger.debug("Refreshed Library")
return library

View File

@@ -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()

View File

@@ -0,0 +1,12 @@
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()
def read_all(session:Session, obj:Base):
stmt = select(obj)
return session.scalars(stmt).fetchall() #TODO: Pagination

View File

@@ -0,0 +1,6 @@
from sqlalchemy.orm import Session
from ....schema.library.base import Base
def update(session:Session, library:Base):
session.commit()

View File

@@ -1,6 +0,0 @@
from sqlalchemy.orm import Session
from ....schema.library.env import Env
def create(session:Session, env:Env):
session.add(env)
session.commit()

View File

@@ -1,7 +0,0 @@
from sqlalchemy.orm import Session
from ....schema.library.env import Env
def delete(session:Session, env:Env):
session.delete(env)
session.commit()

View File

@@ -1,9 +0,0 @@
from sqlalchemy.orm import Session
from sqlalchemy import select
from ....schema.library.env import Env
def read(session:Session, _id:int):
stmt = select(Env).where(Env.id == _id)
env:Env = session.scalars(stmt).one()
return env

View File

@@ -1,7 +0,0 @@
import os
from sqlalchemy.orm import Session
from ....schema.library.env import Env
def update(session:Session, env:Env):
session.commit()

View File

@@ -1,4 +0,0 @@
from .create import create
from .read import read
from .update import update
from .delete import delete

View File

@@ -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()

View File

@@ -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()

View File

@@ -1,6 +0,0 @@
from sqlalchemy.orm import Session
from ....schema.library.library import Library
def update(session:Session, library:Library):
session.commit()

View File

@@ -1,6 +0,0 @@
from sqlalchemy.orm import Session
from ....schema.library.path import Path
def create(session:Session, path:Path):
session.add(path)
session.commit()

View File

@@ -1,7 +0,0 @@
from sqlalchemy.orm import Session
from ....schema.library.path import Path
def delete(session:Session, path:Path):
session.delete(path)
session.commit()

View File

@@ -1,10 +0,0 @@
import os
from sqlalchemy.orm import Session
from sqlalchemy import select
from ....schema.library.path import Path
def read(session:Session, _id:int):
stmt = select(Path).where(Path.id == _id)
path:Path = session.scalars(stmt).one()
return path

View File

@@ -1,7 +0,0 @@
import os
from sqlalchemy.orm import Session
from ....schema.library.path import Path
def update(session:Session, path:Path):
session.commit()

View File

@@ -1,6 +0,0 @@
from sqlalchemy.orm import Session
from .....schema.library.book import Book
def create(session:Session, book:Book):
session.add(book)
session.commit()

View File

@@ -1,7 +0,0 @@
from sqlalchemy.orm import Session
from .....schema.library.book import Book
def delete(session:Session, book:Book):
session.delete(book)
session.commit()

View File

@@ -1,8 +0,0 @@
from sqlalchemy.orm import Session
from sqlalchemy import select
from .....schema.library.book import Book
def read(session:Session, _id:int):
stmt = select(Book).where(Book.id == _id)
return session.scalars(stmt).one()

View File

@@ -1,6 +0,0 @@
from sqlalchemy.orm import Session
from .....schema.library.book import Book
def update(session:Session, book:Book):
session.commit()

View File

@@ -1,3 +1,8 @@
__version__ = "0.2.0.dev"
from flask import Flask from flask import Flask
from .routes.api import api
app = Flask(__name__) app = Flask(__name__)
app.register_blueprint(api)

36
app/config/__init__.py Normal file
View File

@@ -0,0 +1,36 @@
import configparser
from .defaults import default_db_query
from .defaults import default_app_port, default_app_debug
import logging
logger = logging.getLogger(__name__)
config = configparser.ConfigParser()
config.read("config.ini")
logger.debug(f"config: {config.sections()}")
def save_config():
with open("config.ini", "w") as f:
config.write(f)
def check_config():
save = False
if not "DataBase" in config:
logger.debug("DataBase not found in Config")
config["DataBase"] = {
"query": default_db_query
}
save = True
if not "App" in config:
logger.debug("App not found in Config")
config["App"] = {
"port": default_app_port,
"debug": default_app_debug
}
save = True
if save: save_config()
check_config()

3
app/config/defaults.py Normal file
View File

@@ -0,0 +1,3 @@
default_db_query = "sqlite:///library.db"
default_app_port = 15012
default_app_debug = False

117
app/controller/__init__.py Normal file
View File

@@ -0,0 +1,117 @@
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from sqlalchemy.exc import IntegrityError
from app.api.cruds.base import create, read, update, delete, read_all
from app.schema.library import Library
from ..db.config.config import get_engine_configuration
from sqlalchemy.exc import NoResultFound
from .exceptions import LibraryCreationException
from .exceptions import LibraryReadException
from .exceptions import LibraryUpdateException
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._session = self._Session()
self._library = None
if library_id is not None:
self.read(library_id)
self._libraries = []
def __del__(self):
self.session.close()
def __enter__(self):
return self
def __exit__(self, *exc):
del(self)
return False
@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
@property
def libraries(self):
if self._library and len(self._libraries) == 0:
self._libraries = [self._library]
return self._libraries
def set_library(self, _id):
libraries = filter(lambda x: x.get("id") == _id, self.libraries)
if len(libraries) == 1:
self._library = libraries[0]
return True
return False
#CRUDS
def create(self, library:Library):
try:
self._library = create(self.session, library)
except IntegrityError as e:
raise LibraryCreationException(
"Cannot create library",
f"{e.orig}",
"library",
str(library)
)
return self
def read(self, _id):
try:
self._library = read(self.session, _id, Library)
except NoResultFound as e:
raise LibraryReadException(
f"Cannot read Library with id {_id}",
f"{e}",
"library",
_id
)
return self
def read_all(self):
self._libraries = read_all(self.session, Library)
def update(self):
try:
self.session.commit()
except IntegrityError as e:
raise LibraryUpdateException(
f"Cannot update Library",
f"{e}",
"library",
None
)
def delete(self):
delete(self.session, self.data)
del(self)

View File

@@ -0,0 +1,5 @@
from .base import LibraryExceptionBase
from .exc_01000X_data import LibraryDataExection
from .exc_01001X_create import LibraryCreationException
from .exc_01002X_read import LibraryReadException
from .exc_01003X_update import LibraryUpdateException

View File

@@ -0,0 +1,26 @@
class LibraryExceptionBase(Exception):
def __init__(self, name, error, object_name, data, *, status_code=400):
self.code = "000000"
self.name = name
self.error = error
self.object = object_name
self.data = data
self.status_code = status_code
def to_dict(self):
return {
"status": "error",
"name": self.name,
"code": self.code,
"error": self.error,
"object": self.object,
"data": self.data,
"status_code": self.status_code
}
def __str__(self):
return f"ERROR {self.code}: {self.error}"
def __repr__(self):
return f"{self.__class__}(code={self.code!r}, error={self.error!r}), " \
f"object={self.object!r}, data={self.data!r}, status_code={self._status_code})"

View File

@@ -0,0 +1,7 @@
from .base import LibraryExceptionBase
#010010
class LibraryDataExection(LibraryExceptionBase):
def __init__(self, name, error, object_name, data, *, status_code=400):
self.code = "010000"
super().__init__(name, error, object_name, data, status_code=status_code)

View File

@@ -0,0 +1,7 @@
from .base import LibraryExceptionBase
#010010
class LibraryCreationException(LibraryExceptionBase):
def __init__(self, name, error, object_name, data, *, status_code=400):
self.code = "010010"
super().__init__(name, error, object_name, data, status_code=status_code)

View File

@@ -0,0 +1,7 @@
from .base import LibraryExceptionBase
#010030
class LibraryReadException(LibraryExceptionBase):
def __init__(self, name, error, object_name, data, status_code=404):
super().__init__(name, error, object_name, data, status_code=status_code)
self.code = "010030"

View File

@@ -0,0 +1,7 @@
from .base import LibraryExceptionBase
#010020
class LibraryUpdateException(LibraryExceptionBase):
def __init__(self, name, error, object_name, data, status_code=404):
super().__init__(name, error, object_name, data, status_code=status_code)
self.code = "010020"

View File

@@ -0,0 +1 @@
from .update_item_key import update_item_key

View File

@@ -0,0 +1,21 @@
from ..exceptions import LibraryDataExection
from ...schema.library import Base
def update_item_key(obj:Base, key, value):
if key == "id":
raise LibraryDataExection(
"id is not updatable",
"The key ID is not Updatable",
obj.__class__,
{key: value}
)
try:
obj.__getattribute__(key)
except AttributeError:
raise LibraryDataExection(
f"{key} not in {obj.__class__}",
f"The key {key} is not in {obj.__class__}",
obj.__class__,
{key: value}
)
obj.__setattr__(key, value)

View File

@@ -1,10 +1,12 @@
import os import os
from ...config import config
import logging import logging
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
def get_engine_configuration(): def get_engine_configuration():
echo = os.getenv("DEV_URIA_BIBLIOGAME_DEBUG", "false") echo = os.getenv("DEV_URIA_BIBLIOGAME_DEBUG", "false")
engine_string = os.getenv("DEV_URIA_BIBLIOGAME_CONFIG_DB", "sqlite://") engine_string = os.getenv("DEV_URIA_BIBLIOGAME_CONFIG_DB", config["DataBase"].get("query", "sqlite:///"))
logger.debug(f"engine_string, {engine_string}") logger.debug(f"engine_string, {engine_string}")
return (engine_string, echo) return (engine_string, echo)

40
app/routes/__init__.py Normal file
View File

@@ -0,0 +1,40 @@
from flask import json, make_response
from werkzeug.exceptions import HTTPException
from .api import api
from ..controller.exceptions import LibraryExceptionBase
@api.errorhandler(LibraryExceptionBase)
def handle_exception(e):
"""Return JSON instead of HTML for HTTP errors."""
# start with the correct headers and status code from the error
response = make_response()
# replace the body with JSON
response.data = json.dumps({
"status": "error",
"code": e.code,
"status_code": e.status_code,
"name": e.name,
"error": e.error,
"data": e.data
})
response.content_type = "application/json"
response.status_code = e.status_code
return response
@api.errorhandler(HTTPException)
def handle_exception(e):
"""Return JSON instead of HTML for HTTP errors."""
# start with the correct headers and status code from the error
response = e.get_response()
# replace the body with JSON
response.data = json.dumps({
"status": "error",
"code": f"000{e.code}",
"status_code": e.code,
"name": e.name,
"error": e.description,
})
response.content_type = "application/json"
return response

View File

@@ -0,0 +1,6 @@
from .blueprint import api
from .install import post_install
from .library import api_library
api.register_blueprint(api_library)

View File

@@ -0,0 +1,3 @@
from flask import Blueprint
api = Blueprint("api", __name__, url_prefix="/api")

24
app/routes/api/install.py Normal file
View File

@@ -0,0 +1,24 @@
from flask import request
from ...config import config, save_config
from ...api.actions.install import install
import logging
logger = logging.getLogger(__name__)
from .blueprint import api
@api.route("/install", methods=["POST"])
def post_install():
try:
body = request.json
except:
logger.debug("Installing with config.ini params")
else:
if body.get("query_string"):
config["DataBase"]["query"] = body.get("query_string")
save_config()
finally:
install()
return { "status": "ok" }, 200

View File

@@ -0,0 +1,5 @@
from .blueprint import api_library
from .create import create_library
from .read import read_libraries, read_library
from .update import update_library
from .delete import delete_library

View File

@@ -0,0 +1,3 @@
from flask import Blueprint
api_library = Blueprint("api_library", __name__, url_prefix="/library")

View File

@@ -0,0 +1,19 @@
from flask import request
from .blueprint import api_library
from ....controller import LibraryController
from ....schema.library.library import Library
import logging
logger = logging.getLogger(__name__)
@api_library.route("/", methods=["POST"])
def create_library():
data = request.json
with LibraryController() as controller:
lib = Library(**data)
library = controller.create(lib)
return { "status": "ok", "result": library.data.to_dict() }, 200

View File

@@ -0,0 +1,19 @@
from flask import request
from sqlalchemy.exc import NoResultFound
from .blueprint import api_library
from ....controller import LibraryController
from ....schema.library.library import Library
import logging
logger = logging.getLogger(__name__)
@api_library.route("/<_id>", methods=["DELETE"])
def delete_library(_id):
controller = LibraryController(_id)
controller.delete()
return { "status": "ok" }, 201

View File

@@ -0,0 +1,21 @@
from flask import request
from sqlalchemy.exc import NoResultFound
from .blueprint import api_library
from ....controller import LibraryController
from ....schema.library.library import Library
import logging
logger = logging.getLogger(__name__)
@api_library.route("/", methods=["GET"])
def read_libraries():
library = LibraryController()
library.read_all()
return { "status": "ok", "results": [lib.to_dict() for lib in library.libraries] }, 200
@api_library.route("/<_id>", methods=["GET"])
def read_library(_id):
library = LibraryController(_id)
return { "status": "ok", "result": library.data.to_dict() }, 200

View File

@@ -0,0 +1,27 @@
from flask import request
from sqlalchemy.exc import IntegrityError, NoResultFound
from .blueprint import api_library
from ....controller import LibraryController
from ....controller.functions import update_item_key
from ....schema.library.library import Library
import logging
logger = logging.getLogger(__name__)
@api_library.route("/<_id>", methods=["PATCH"])
def update_library(_id):
data:dict = request.json
controller = LibraryController(_id)
library = controller.data
for key, value in data.items():
update_item_key(library, key, value)
controller.update()
return { "status": "ok", "result": controller.data.to_dict() }, 200

View File

@@ -10,8 +10,8 @@ from .base import Base
class Library(Base): class Library(Base):
__tablename__ = "library" __tablename__ = "library"
id: Mapped[int] = mapped_column(primary_key=True) id: Mapped[int] = mapped_column(primary_key=True)
name: Mapped[str] = mapped_column(String(255)) name: Mapped[str] = mapped_column(String(255), unique=True)
notes: Mapped[str] = mapped_column(String(65656)) notes: Mapped[Optional[str]] = mapped_column(String(65656))
envs: Mapped[List["Env"]] = relationship( envs: Mapped[List["Env"]] = relationship(
back_populates="library", cascade="all, delete-orphan" back_populates="library", cascade="all, delete-orphan"
@@ -29,5 +29,12 @@ class Library(Base):
back_populates="library", cascade="all, delete-orphan" back_populates="library", cascade="all, delete-orphan"
) )
def to_dict(self) -> dict:
return {
"id": self.id,
"name": self.name,
"notes": self.notes
}
def __repr__(self) -> str: def __repr__(self) -> str:
return f"Library(id={self.id!r}, name={self.name!r}, notes={self.notes!r}" return f"Library(id={self.id!r}, name={self.name!r}, notes={self.notes!r})"

7
config.ini Normal file
View File

@@ -0,0 +1,7 @@
[DataBase]
query = sqlite:///test.db
[App]
port = 15012
debug = True

14
main.py
View File

@@ -0,0 +1,14 @@
from app import app
from app.config import config
import logging
level = config["App"].get("debug", False) and logging.DEBUG or logging.INFO
logging.basicConfig(level=level)
logger = logging.getLogger(__name__)
logger.info(f"Logging level set to {level}")
if __name__ == "__main__":
app.run(port=config["App"]["port"], debug=config["App"]["debug"])

BIN
test.db Normal file

Binary file not shown.

149
tests/test_controller.py Normal file
View File

@@ -0,0 +1,149 @@
import os
import unittest
from sqlalchemy.exc import NoResultFound
from app.api.actions import install
from app.schema.library import Library, Tag, Book, BookTag, Path, Env
from app.controller import LibraryController
from app.controller.exceptions import LibraryReadException
import logging
logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger(__name__)
class TestController(unittest.TestCase):
def setUp(self):
os.environ["DEV_URIA_BIBLIOGAME_CONFIG_DB"] = "sqlite:///"
os.environ["DEV_URIA_BIBLIOGAME_DEBUG"] = "false"
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 = LibraryController(1, engine=self.engine)
logger.debug(f"Name: {library.data.name}")
self.assertEqual(library.data.name, self.library.data.name)
self.assertEqual(library.data.name, "Library Test")
def test_read_notes(self):
library = LibraryController(1, engine=self.engine)
logger.debug(f"Notes: {library.data.notes}")
self.assertEqual(library.data.notes, self.library.data.notes)
self.assertEqual(library.data.notes, "My duckling library test")
def test_read_path(self):
library = LibraryController(1, engine=self.engine)
logger.debug(f"PATH: {library.data.paths[0].path}")
self.assertEqual(library.data.paths[0].path, self.library.data.paths[0].path)
self.assertEqual(library.data.paths[0].path, "/home/ivan/Documentos/ttprpg")
def test_read_env(self):
library = LibraryController(1, engine=self.engine)
logger.debug(f"ENV: {library.data.envs[0].key} - {library.data.envs[0].value}")
self.assertEqual(library.data.envs[0].key, self.library.data.envs[0].key)
self.assertEqual(library.data.envs[0].value, self.library.data.envs[0].value)
self.assertEqual(library.data.envs[0].key, "ENVIRONMENT_VARIABLE")
self.assertEqual(library.data.envs[0].value, "Clearly an environment variable")
def test_read_book(self):
library = LibraryController(1, engine=self.engine)
book = library.data.books[0]
logger.debug(f"BOOK: {book}")
self.assertEqual(book.name, self.library.data.books[0].name)
self.assertEqual(book.name, "Test book")
def test_read_tags(self):
library = LibraryController(1, engine=self.engine)
tags = library.data.tags
self.assertEqual(str(tags), str(self.library.data.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 = LibraryController(1, engine=self.engine)
book = library.data.books[0]
tags = library.data.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 = LibraryController(1, engine=self.engine)
library.data.name = "Another Library"
library.update()
library1 = LibraryController(1, engine=self.engine)
self.assertEqual(library1.data.name, self.library.data.name)
self.assertNotEqual(library1.data.name, "Library Test")
self.assertEqual(library1.data.name, "Another Library")
def test_update_name(self):
library = LibraryController(1, engine=self.engine)
library.data.books[0].name = "Another Book on the shelf"
library.update()
library1 = LibraryController(1, engine=self.engine)
book = library1.data.books[0]
self.assertEqual(book.name, self.library.data.books[0].name)
self.assertNotEqual(book.name, "Test book")
self.assertEqual(book.name, "Another Book on the shelf")
def test_delete_library(self):
library = LibraryController(1, engine=self.engine)
library.delete()
self.assertRaises(LibraryReadException, LibraryController, 1, engine=self.engine)
if __name__ == "__main__":
unittest.main()

View File

@@ -2,11 +2,13 @@ import os
import unittest import unittest
from sqlalchemy.orm import sessionmaker from sqlalchemy.orm import sessionmaker
from sqlalchemy.exc import NoResultFound
from app.api.actions import install from app.api.actions import install
from app.api.cruds.library import create, read, update from app.api.cruds.base import create, read, update, delete
from app.schema.library import Library, Path, Env, Book, Tag, BookTag from app.schema.library import Library, Path, Env, Book, Tag, BookTag
import logging import logging
logging.basicConfig(level=logging.DEBUG) logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@@ -15,7 +17,7 @@ class TestDB(unittest.TestCase):
def setUp(self): def setUp(self):
os.environ["DEV_URIA_BIBLIOGAME_CONFIG_DB"] = "sqlite:///" os.environ["DEV_URIA_BIBLIOGAME_CONFIG_DB"] = "sqlite:///"
os.environ["DEV_URIA_BIBLIOGAME_DEBUG"] = "true" os.environ["DEV_URIA_BIBLIOGAME_DEBUG"] = "false"
self.engine = install() self.engine = install()
self.tags = [ self.tags = [
Tag( Tag(
@@ -57,29 +59,29 @@ class TestDB(unittest.TestCase):
return super().setUp() return super().setUp()
def test_install(self): 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)) self.assertEqual(library_string, str(self.library))
def test_read_name(self): def test_read_name(self):
library = read(self.session, 1) library = read(self.session, 1, Library)
logger.debug(f"Name: {library.name}") logger.debug(f"Name: {library.name}")
self.assertEqual(library.name, self.library.name) self.assertEqual(library.name, self.library.name)
self.assertEqual(library.name, "Library Test") self.assertEqual(library.name, "Library Test")
def test_read_notes(self): def test_read_notes(self):
library = read(self.session, 1) library = read(self.session, 1, Library)
logger.debug(f"Notes: {library.notes}") logger.debug(f"Notes: {library.notes}")
self.assertEqual(library.notes, self.library.notes) self.assertEqual(library.notes, self.library.notes)
self.assertEqual(library.notes, "My duckling library test") self.assertEqual(library.notes, "My duckling library test")
def test_read_path(self): def test_read_path(self):
library = read(self.session, 1) library = read(self.session, 1, Library)
logger.debug(f"PATH: {library.paths[0].path}") 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, self.library.paths[0].path)
self.assertEqual(library.paths[0].path, "/home/ivan/Documentos/ttprpg") self.assertEqual(library.paths[0].path, "/home/ivan/Documentos/ttprpg")
def test_read_env(self): 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}") 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].key, self.library.envs[0].key)
self.assertEqual(library.envs[0].value, self.library.envs[0].value) self.assertEqual(library.envs[0].value, self.library.envs[0].value)
@@ -87,14 +89,14 @@ class TestDB(unittest.TestCase):
self.assertEqual(library.envs[0].value, "Clearly an environment variable") self.assertEqual(library.envs[0].value, "Clearly an environment variable")
def test_read_book(self): def test_read_book(self):
library = read(self.session, 1) library = read(self.session, 1, Library)
book = library.books[0] book = library.books[0]
logger.debug(f"BOOK: {book}") logger.debug(f"BOOK: {book}")
self.assertEqual(book.name, self.library.books[0].name) self.assertEqual(book.name, self.library.books[0].name)
self.assertEqual(book.name, "Test book") self.assertEqual(book.name, "Test book")
def test_read_tags(self): def test_read_tags(self):
library = read(self.session, 1) library = read(self.session, 1, Library)
tags = library.tags tags = library.tags
self.assertEqual(tags, self.library.tags) self.assertEqual(tags, self.library.tags)
self.assertEqual(tags, self.tags) self.assertEqual(tags, self.tags)
@@ -106,7 +108,7 @@ class TestDB(unittest.TestCase):
self.assertEqual(tags[1].name, "Bar") self.assertEqual(tags[1].name, "Bar")
def test_read_book_tags(self): def test_read_book_tags(self):
library = read(self.session, 1) library = read(self.session, 1, Library)
book = library.books[0] book = library.books[0]
tags = library.tags tags = library.tags
logger.debug(f"BOOK TAGS: {book.tags}") logger.debug(f"BOOK TAGS: {book.tags}")
@@ -117,12 +119,31 @@ class TestDB(unittest.TestCase):
self.assertNotEqual(book.tags[0].tag.name, "Bar") self.assertNotEqual(book.tags[0].tag.name, "Bar")
def test_update_name(self): def test_update_name(self):
library = read(self.session, 1) library = read(self.session, 1, Library)
library.name = "Another Library" library.name = "Another Library"
update(self.session, library) update(self.session, library)
self.assertEqual(library.name, self.library.name) library1 = read(self.session, 1)
self.assertNotEqual(library.name, "Library Test") self.assertEqual(library1.name, self.library.name)
self.assertEqual(library.name, "Another Library") self.assertNotEqual(library1.name, "Library Test")
self.assertEqual(library1.name, "Another Library")
def test_update_name(self):
library = read(self.session, 1, Library)
library.books[0].name = "Another Book on the shelf"
update(self.session, library)
library1 = read(self.session, 1, Library)
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")
def test_delete_library(self):
library = read(self.session, 1, Library)
delete(self.session, library)
self.assertRaises(NoResultFound, read, self.session, 1, Library)
if __name__ == "__main__": if __name__ == "__main__":