From 615e427882799d2c42be0d34b986dfa0ed7f6e45 Mon Sep 17 00:00:00 2001 From: "alice.juan" Date: Thu, 2 Nov 2023 09:21:14 +0100 Subject: [PATCH 1/7] Better status codes for error handling in backend and add some error messages if Github settings were not added to help developers --- backend/editor/api.py | 12 ++++---- backend/editor/github_functions.py | 45 ++++++++++++++++++++---------- 2 files changed, 36 insertions(+), 21 deletions(-) diff --git a/backend/editor/api.py b/backend/editor/api.py index ae236e24..72ec7d43 100644 --- a/backend/editor/api.py +++ b/backend/editor/api.py @@ -101,7 +101,7 @@ def check_single(id): if len(id) == 0: raise HTTPException(status_code=404, detail="Entry not found") elif len(id) > 1: - raise HTTPException(status_code=500, detail="Multiple entries found") + raise HTTPException(status_code=409, detail="Multiple entries found") def file_cleanup(filepath): @@ -111,7 +111,7 @@ def file_cleanup(filepath): try: os.remove(filepath) except Exception as e: - raise HTTPException(status_code=500, detail="Taxonomy file not found for deletion") from e + raise HTTPException(status_code=404, detail="Taxonomy file not found for deletion") from e class StatusFilter(str, Enum): @@ -351,10 +351,10 @@ async def export_to_github( return url except GithubBranchExistsError: - raise HTTPException(status_code=500, detail="The Github branch already exists!") + raise HTTPException(status_code=409, detail="The Github branch already exists!") except GithubUploadError: - raise HTTPException(status_code=500, detail="Github upload error!") + raise HTTPException(status_code=400, detail="Github upload error!") # Post methods @@ -370,7 +370,7 @@ async def import_from_github(request: Request, branch: str, taxonomy_name: str): taxonomy = TaxonomyGraph(branch, taxonomy_name) if not taxonomy.is_valid_branch_name(): - raise HTTPException(status_code=400, detail="branch_name: Enter a valid branch name!") + raise HTTPException(status_code=422, detail="branch_name: Enter a valid branch name!") if await taxonomy.does_project_exist(): raise HTTPException(status_code=409, detail="Project already exists!") if not await taxonomy.is_branch_unique(): @@ -390,7 +390,7 @@ async def upload_taxonomy( # use the file name as the taxonomy name taxonomy = TaxonomyGraph(branch, taxonomy_name) if not taxonomy.is_valid_branch_name(): - raise HTTPException(status_code=400, detail="branch_name: Enter a valid branch name!") + raise HTTPException(status_code=422, detail="branch_name: Enter a valid branch name!") if await taxonomy.does_project_exist(): raise HTTPException(status_code=409, detail="Project already exists!") if not await taxonomy.is_branch_unique(): diff --git a/backend/editor/github_functions.py b/backend/editor/github_functions.py index 59bfcff9..4bafafe8 100644 --- a/backend/editor/github_functions.py +++ b/backend/editor/github_functions.py @@ -3,7 +3,7 @@ """ from textwrap import dedent -from github import Github +from github import Github, GithubException from . import settings @@ -21,8 +21,14 @@ def init_driver_and_repo(self): """ Initalize connection to Github with an access token """ - github_driver = Github(settings.access_token) - repo = github_driver.get_repo(settings.repo_uri) + access_token = settings.access_token + if not access_token: + raise Exception("Access token is not set. Please add your access token in .env") + repo_uri = settings.repo_uri + if not repo_uri: + raise Exception("repo_uri is not set. Please add your access token in .env") + github_driver = Github(access_token) + repo = github_driver.get_repo(repo_uri) return repo def list_all_branches(self): @@ -47,19 +53,28 @@ def update_file(self, filename): # Find taxonomy text file to be updated github_filepath = f"taxonomies/{self.taxonomy_name}.txt" commit_message = f"Update {self.taxonomy_name}.txt" + try: + current_file = self.repo.get_contents(github_filepath) + with open(filename, "r") as f: + new_file_contents = f.read() - current_file = self.repo.get_contents(github_filepath) - with open(filename, "r") as f: - new_file_contents = f.read() - - # Update the file - self.repo.update_file( - github_filepath, - commit_message, - new_file_contents, - current_file.sha, - branch=self.branch_name, - ) + # Update the file + self.repo.update_file( + github_filepath, + commit_message, + new_file_contents, + current_file.sha, + branch=self.branch_name, + ) + except GithubException as e: + # Handle GitHub API-related exceptions + raise Exception(f"GitHub API error: {e}") + except FileNotFoundError: + # Handle file not found error (e.g., when 'filename' does not exist) + raise Exception(f"File not found: {filename}") + except Exception as e: + # Handle any other unexpected exceptions + raise Exception(f"An error occurred: {e}") def create_pr(self, description): """ From 0d76858799f5ae9dc5f7ef3714cdd9c2ed220410 Mon Sep 17 00:00:00 2001 From: "alice.juan" Date: Thu, 2 Nov 2023 15:01:26 +0100 Subject: [PATCH 2/7] add a status code for the missing settings error --- backend/editor/github_functions.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/backend/editor/github_functions.py b/backend/editor/github_functions.py index 4bafafe8..550bcb2e 100644 --- a/backend/editor/github_functions.py +++ b/backend/editor/github_functions.py @@ -5,6 +5,10 @@ from github import Github, GithubException +from fastapi import ( + HTTPException, +) + from . import settings @@ -23,10 +27,10 @@ def init_driver_and_repo(self): """ access_token = settings.access_token if not access_token: - raise Exception("Access token is not set. Please add your access token in .env") + raise Exception(status_code=400, detail="Access token is not set. Please add your access token in .env") repo_uri = settings.repo_uri if not repo_uri: - raise Exception("repo_uri is not set. Please add your access token in .env") + raise Exception(status_code=400, detail="repo_uri is not set. Please add your access token in .env") github_driver = Github(access_token) repo = github_driver.get_repo(repo_uri) return repo From a9f8b7505d3bff0117e7a6de7736934bc72ce61d Mon Sep 17 00:00:00 2001 From: "alice.juan" Date: Thu, 2 Nov 2023 16:16:15 +0100 Subject: [PATCH 3/7] display in backend logs the detail prop of the exception --- backend/editor/api.py | 8 ++++++++ backend/editor/github_functions.py | 4 ++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/backend/editor/api.py b/backend/editor/api.py index 72ec7d43..f09a3691 100644 --- a/backend/editor/api.py +++ b/backend/editor/api.py @@ -138,6 +138,14 @@ async def validation_exception_handler(request: Request, exc: RequestValidationE content=jsonable_encoder({"detail": "Invalid request", "errors": reformatted_errors}), ) +@app.exception_handler(HTTPException) +async def http_exception_handler(request: Request, exc: HTTPException): + """ + Custom exception handler to log FastAPI exceptions. + """ + # Log the detail message + log.info(f" ERROR: {exc.detail}") + return JSONResponse(status_code=exc.status_code, content={"message": exc.detail}) # Get methods diff --git a/backend/editor/github_functions.py b/backend/editor/github_functions.py index 550bcb2e..937fabb0 100644 --- a/backend/editor/github_functions.py +++ b/backend/editor/github_functions.py @@ -27,10 +27,10 @@ def init_driver_and_repo(self): """ access_token = settings.access_token if not access_token: - raise Exception(status_code=400, detail="Access token is not set. Please add your access token in .env") + raise HTTPException(status_code=400, detail="Access token is not set. Please add your access token in .env") repo_uri = settings.repo_uri if not repo_uri: - raise Exception(status_code=400, detail="repo_uri is not set. Please add your access token in .env") + raise HTTPException(status_code=400, detail="repo_uri is not set. Please add your access token in .env") github_driver = Github(access_token) repo = github_driver.get_repo(repo_uri) return repo From 321399a4b3ef7a7eb55f9e662eb6d4979cbcbcf0 Mon Sep 17 00:00:00 2001 From: "alice.juan" Date: Thu, 2 Nov 2023 16:32:21 +0100 Subject: [PATCH 4/7] fix some quality issues --- backend/editor/api.py | 1 + backend/editor/github_functions.py | 10 ++++++++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/backend/editor/api.py b/backend/editor/api.py index f09a3691..4426f37a 100644 --- a/backend/editor/api.py +++ b/backend/editor/api.py @@ -138,6 +138,7 @@ async def validation_exception_handler(request: Request, exc: RequestValidationE content=jsonable_encoder({"detail": "Invalid request", "errors": reformatted_errors}), ) + @app.exception_handler(HTTPException) async def http_exception_handler(request: Request, exc: HTTPException): """ diff --git a/backend/editor/github_functions.py b/backend/editor/github_functions.py index 937fabb0..e63775e3 100644 --- a/backend/editor/github_functions.py +++ b/backend/editor/github_functions.py @@ -27,10 +27,16 @@ def init_driver_and_repo(self): """ access_token = settings.access_token if not access_token: - raise HTTPException(status_code=400, detail="Access token is not set. Please add your access token in .env") + raise HTTPException( + status_code=400, + detail="Access token is not set. Please add your access token in .env" + ) repo_uri = settings.repo_uri if not repo_uri: - raise HTTPException(status_code=400, detail="repo_uri is not set. Please add your access token in .env") + raise HTTPException( + status_code=400, + detail="repo_uri is not set. Please add your access token in .env" + ) github_driver = Github(access_token) repo = github_driver.get_repo(repo_uri) return repo From 9f863ae07401069f2a2116eb6cd2448bbed9b7a7 Mon Sep 17 00:00:00 2001 From: "alice.juan" Date: Thu, 2 Nov 2023 16:42:43 +0100 Subject: [PATCH 5/7] fix some backend issues according to isort and black --- backend/editor/api.py | 1 + backend/editor/github_functions.py | 10 +++------- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/backend/editor/api.py b/backend/editor/api.py index 4426f37a..7d8a2bb9 100644 --- a/backend/editor/api.py +++ b/backend/editor/api.py @@ -148,6 +148,7 @@ async def http_exception_handler(request: Request, exc: HTTPException): log.info(f" ERROR: {exc.detail}") return JSONResponse(status_code=exc.status_code, content={"message": exc.detail}) + # Get methods diff --git a/backend/editor/github_functions.py b/backend/editor/github_functions.py index e63775e3..4cb0e4da 100644 --- a/backend/editor/github_functions.py +++ b/backend/editor/github_functions.py @@ -3,12 +3,9 @@ """ from textwrap import dedent +from fastapi import HTTPException from github import Github, GithubException -from fastapi import ( - HTTPException, -) - from . import settings @@ -29,13 +26,12 @@ def init_driver_and_repo(self): if not access_token: raise HTTPException( status_code=400, - detail="Access token is not set. Please add your access token in .env" + detail="Access token is not set. Please add your access token in .env", ) repo_uri = settings.repo_uri if not repo_uri: raise HTTPException( - status_code=400, - detail="repo_uri is not set. Please add your access token in .env" + status_code=400, detail="repo_uri is not set. Please add your access token in .env" ) github_driver = Github(access_token) repo = github_driver.get_repo(repo_uri) From 6b27f19d7fafb6514e9863b0dc369e247f54e8bf Mon Sep 17 00:00:00 2001 From: "alice.juan" Date: Thu, 9 Nov 2023 08:45:58 +0100 Subject: [PATCH 6/7] fix some exception responses --- backend/editor/api.py | 7 ++++--- backend/editor/github_functions.py | 8 ++++---- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/backend/editor/api.py b/backend/editor/api.py index 7d8a2bb9..4500fa82 100644 --- a/backend/editor/api.py +++ b/backend/editor/api.py @@ -101,7 +101,7 @@ def check_single(id): if len(id) == 0: raise HTTPException(status_code=404, detail="Entry not found") elif len(id) > 1: - raise HTTPException(status_code=409, detail="Multiple entries found") + raise HTTPException(status_code=500, detail="Multiple entries found") def file_cleanup(filepath): @@ -110,8 +110,8 @@ def file_cleanup(filepath): """ try: os.remove(filepath) - except Exception as e: - raise HTTPException(status_code=404, detail="Taxonomy file not found for deletion") from e + except FileNotFoundError: + log.warn(f"Taxonomy file {filepath} not found for deletion") class StatusFilter(str, Enum): @@ -147,6 +147,7 @@ async def http_exception_handler(request: Request, exc: HTTPException): # Log the detail message log.info(f" ERROR: {exc.detail}") return JSONResponse(status_code=exc.status_code, content={"message": exc.detail}) + # return await http_exception_handler(request, exc) # Get methods diff --git a/backend/editor/github_functions.py b/backend/editor/github_functions.py index 4cb0e4da..4c0e683e 100644 --- a/backend/editor/github_functions.py +++ b/backend/editor/github_functions.py @@ -74,13 +74,13 @@ def update_file(self, filename): ) except GithubException as e: # Handle GitHub API-related exceptions - raise Exception(f"GitHub API error: {e}") - except FileNotFoundError: + raise Exception(f"GitHub API error: {e}") from e + except FileNotFoundError as e: # Handle file not found error (e.g., when 'filename' does not exist) - raise Exception(f"File not found: {filename}") + raise Exception(f"File not found: {filename}") from e except Exception as e: # Handle any other unexpected exceptions - raise Exception(f"An error occurred: {e}") + raise Exception(f"An error occurred: {e}") from e def create_pr(self, description): """ From fe1dca97b861259a4cb9a2058ee9ae4dd064f49e Mon Sep 17 00:00:00 2001 From: "alice.juan" Date: Thu, 9 Nov 2023 10:22:27 +0100 Subject: [PATCH 7/7] add custom http error handler --- backend/editor/api.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/backend/editor/api.py b/backend/editor/api.py index 4500fa82..ad1c6f92 100644 --- a/backend/editor/api.py +++ b/backend/editor/api.py @@ -24,6 +24,7 @@ status, ) from fastapi.encoders import jsonable_encoder +from fastapi.exception_handlers import http_exception_handler from fastapi.exceptions import RequestValidationError from fastapi.middleware.cors import CORSMiddleware from fastapi.responses import FileResponse, JSONResponse @@ -111,7 +112,7 @@ def file_cleanup(filepath): try: os.remove(filepath) except FileNotFoundError: - log.warn(f"Taxonomy file {filepath} not found for deletion") + log.warn(f"Taxonomy file {filepath} not found for deletion") class StatusFilter(str, Enum): @@ -140,14 +141,13 @@ async def validation_exception_handler(request: Request, exc: RequestValidationE @app.exception_handler(HTTPException) -async def http_exception_handler(request: Request, exc: HTTPException): +async def log_http_exception(request: Request, exc: HTTPException): """ Custom exception handler to log FastAPI exceptions. """ # Log the detail message log.info(f" ERROR: {exc.detail}") - return JSONResponse(status_code=exc.status_code, content={"message": exc.detail}) - # return await http_exception_handler(request, exc) + return await http_exception_handler(request, exc) # Get methods