From 2a8a44e80b0f117f4980f4712f9e915b0105849a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20Ur=C3=ADa?= Date: Sun, 15 Feb 2026 17:39:21 +0100 Subject: [PATCH] [WIP] Exception handling --- app/controller/__init__.py | 14 +++++- app/controller/exceptions/__init__.py | 2 + app/controller/exceptions/base.py | 18 ++++++++ .../exceptions/exc_01001X_create.py | 26 ++++++++++++ app/routes/__init__.py | 40 +++++++++++++++++- app/routes/api/library/create.py | 18 +++----- test.db | Bin 32768 -> 32768 bytes 7 files changed, 103 insertions(+), 15 deletions(-) create mode 100644 app/controller/exceptions/__init__.py create mode 100644 app/controller/exceptions/base.py create mode 100644 app/controller/exceptions/exc_01001X_create.py diff --git a/app/controller/__init__.py b/app/controller/__init__.py index 80b3a81..aba76f2 100644 --- a/app/controller/__init__.py +++ b/app/controller/__init__.py @@ -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): - self._library = create(self.session, 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): diff --git a/app/controller/exceptions/__init__.py b/app/controller/exceptions/__init__.py new file mode 100644 index 0000000..578ba81 --- /dev/null +++ b/app/controller/exceptions/__init__.py @@ -0,0 +1,2 @@ +from .base import LibraryExceptionBase +from .exc_01001X_create import LibraryCreationException \ No newline at end of file diff --git a/app/controller/exceptions/base.py b/app/controller/exceptions/base.py new file mode 100644 index 0000000..8a1add8 --- /dev/null +++ b/app/controller/exceptions/base.py @@ -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})" \ No newline at end of file diff --git a/app/controller/exceptions/exc_01001X_create.py b/app/controller/exceptions/exc_01001X_create.py new file mode 100644 index 0000000..9101d38 --- /dev/null +++ b/app/controller/exceptions/exc_01001X_create.py @@ -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}" \ No newline at end of file diff --git a/app/routes/__init__.py b/app/routes/__init__.py index 565e321..765664e 100644 --- a/app/routes/__init__.py +++ b/app/routes/__init__.py @@ -1 +1,39 @@ -from .api import api \ No newline at end of file +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 + diff --git a/app/routes/api/library/create.py b/app/routes/api/library/create.py index 8064bfb..8b9d201 100644 --- a/app/routes/api/library/create.py +++ b/app/routes/api/library/create.py @@ -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 + + data = request.json 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 \ No newline at end of file + lib = Library(**data) + library = controller.create(lib) + return { "status": "ok", "result": library.data.to_dict() }, 200 \ No newline at end of file diff --git a/test.db b/test.db index cd897f14deaeae229c54d4e14b06e8763559aa14..7618a5b91925e1eecdbd514d83ecca3f23a928aa 100644 GIT binary patch delta 118 zcmZo@U}|V!njp={Gf~Ewk!NGV5`G>Q{uvDXGx*Q&f8~F*Sx}*afAS1@Z(S}1FyLfi zVGw8V$;?Ym