Compare commits

..

2 Commits

Author SHA1 Message Date
2a8a44e80b [WIP] Exception handling 2026-02-15 17:39:21 +01:00
7c3593d066 [UPD] Delete Library 2026-02-15 16:34:43 +01:00
10 changed files with 123 additions and 22 deletions

View File

@@ -1,10 +1,13 @@
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 .exceptions import LibraryCreationException
import logging
logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger(__name__)
@@ -66,7 +69,16 @@ class LibraryController:
return False
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),
400
)
return self
def read(self, _id):
@@ -80,6 +92,6 @@ class LibraryController:
self.session.commit()
def delete(self):
delete(self.session, self)
delete(self.session, self.data)
del(self)

View File

@@ -0,0 +1,2 @@
from .base import LibraryExceptionBase
from .exc_01001X_create import LibraryCreationException

View File

@@ -0,0 +1,18 @@
class LibraryExceptionBase(Exception):
def __init__(self, code, error):
self.code = code
self.error = error
def to_dict(self):
return {
"status": "error",
"code": self.code,
"error": self.error,
"status_code": 400
}
def __str__(self):
return f"ERROR {self.code}: {self.error}"
def __repr__(self):
return f"LibraryExceptionBase(code={self.code!r}, error={self.error!r})"

View File

@@ -0,0 +1,26 @@
from .base import LibraryExceptionBase
#010010
class LibraryCreationException(LibraryExceptionBase):
def __init__(self, name, error, object, data, status_code=400):
self.code = "010010"
self.name = name
self.error = error
self.object = object
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 __repr__(self):
return f"LibraryCreationException(code={self.code!r}, error={self.error!r}), " \
f"object={self.object!r}, data={self.data!r}"

View File

@@ -1 +1,39 @@
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,
})
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

@@ -11,18 +11,10 @@ logger = logging.getLogger(__name__)
@api_library.route("/", methods=["POST"])
def create_library():
try:
data = request.json
except Exception as e:
logger.debug(f"{e}")
return { "status": "error", "error": "JSON Required" }, 415
with LibraryController() as controller:
try:
lib = Library(**data)
library = controller.create(lib)
except IntegrityError as e:
logger.debug(f"DB Error Creating {e}")
return { "status": "error", "error": f"{e.orig}" }, 400
else:
return { "status": "ok", "result": library.data.to_dict() }, 200

View File

@@ -1,4 +1,4 @@
__version__ = "0.2.0.dev"
from app import app
from app.config import config

BIN
test.db

Binary file not shown.

View File

@@ -1,7 +1,7 @@
import os
import unittest
from sqlalchemy.orm import sessionmaker
from sqlalchemy.exc import NoResultFound
from app.api.actions import install
from app.schema.library import Library, Tag, Book, BookTag, Path, Env
@@ -137,6 +137,11 @@ class TestDB(unittest.TestCase):
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(NoResultFound, LibraryController, 1, engine=self.engine)
if __name__ == "__main__":
unittest.main()

View File

@@ -2,11 +2,13 @@ import os
import unittest
from sqlalchemy.orm import sessionmaker
from sqlalchemy.exc import NoResultFound
from app.api.actions import install
from app.api.cruds.base 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
import logging
logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger(__name__)
@@ -137,6 +139,12 @@ class TestDB(unittest.TestCase):
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__":
unittest.main()