From 3c3cf80aaf0c06f8102838a94cbe1d7d4eae78a5 Mon Sep 17 00:00:00 2001 From: Alivecow Date: Fri, 21 Mar 2025 15:32:33 +0100 Subject: [PATCH 01/23] docs: Add docstrings for the haiku class Refs: OPS-68 --- senju/haiku.py | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/senju/haiku.py b/senju/haiku.py index e112215..734cbc4 100644 --- a/senju/haiku.py +++ b/senju/haiku.py @@ -19,15 +19,43 @@ def foobar(): @dataclass class Haiku: + """ + A class representing a haiku poem with three lines. + + Attributes: + lines (list[str]): A list containing the three lines of the haiku. + """ lines: list[str] def get_json(self): + """ + Converts the haiku lines to a JSON string. + + Returns: + str: A JSON string representation of the haiku lines. + """ return json.dumps(self.lines) @staticmethod def request_haiku(seed: str) -> Haiku: - """This function prompts the ai to generate - the hauku based on the user input""" + """ + Generates a haiku using an AI model based on the provided seed text. + + This function prompts the AI to generate a haiku based on the user input. + It validates that the response: + - Contains exactly 3 lines + + The function will retry until a valid haiku is generated. + + Args: + seed (str): The input text used to inspire the haiku generation. + + Returns: + Haiku: A new Haiku object containing the generated three lines. + + Raises: + Possible JSONDecodeError which is caught and handled with retries. + """ ai_gen_request = { "model": "haiku", From e6da82595ab1569f922eae6d5791ba89b8e79a3b Mon Sep 17 00:00:00 2001 From: Alivecow Date: Fri, 21 Mar 2025 16:22:12 +0100 Subject: [PATCH 02/23] docs: Add docstrings for the store manager and main Refs: OPS-68 --- docs/auto_docu.sh | 0 senju/haiku.py | 9 ++---- senju/main.py | 66 ++++++++++++++++++++++++++++++++++++++- senju/store_manager.py | 70 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 137 insertions(+), 8 deletions(-) mode change 100644 => 100755 docs/auto_docu.sh diff --git a/docs/auto_docu.sh b/docs/auto_docu.sh old mode 100644 new mode 100755 diff --git a/senju/haiku.py b/senju/haiku.py index 734cbc4..151647f 100644 --- a/senju/haiku.py +++ b/senju/haiku.py @@ -19,21 +19,16 @@ def foobar(): @dataclass class Haiku: - """ - A class representing a haiku poem with three lines. - - Attributes: - lines (list[str]): A list containing the three lines of the haiku. - """ lines: list[str] def get_json(self): - """ + """ Converts the haiku lines to a JSON string. Returns: str: A JSON string representation of the haiku lines. """ + return json.dumps(self.lines) @staticmethod diff --git a/senju/main.py b/senju/main.py index 663a7c5..575dc73 100644 --- a/senju/main.py +++ b/senju/main.py @@ -24,11 +24,28 @@ def foobar(): @app.route("/") def index_view(): + """ + Render the main index page of the application. + + Returns: + Text: The index.html template with title "Senju". + """ + return render_template("index.html", title="Senju") @app.route("/haiku/") def haiku_index_view(): + """ + Redirect to the most recently created haiku. + + Returns: + Response: Redirects to the haiku_view route with the latest haiku ID. + + Raises: + KeyError: If no haikus exist in the store yet. + """ + haiku_id: int | None = store.get_id_of_latest_haiku() if haiku_id is None: # TODO: add "empty haiku list" error page @@ -38,7 +55,23 @@ def haiku_index_view(): @app.route("/haiku/") def haiku_view(haiku_id): - """test""" + """ + Display a specific haiku by its ID. + + Loads the haiku with the given ID from the store and renders it using + the haiku.html template. If no haiku is found with the provided ID, + raises a KeyError. + + Args: + haiku_id (int): The ID of the haiku to display. + + Returns: + Text: The haiku.html template with the haiku data in context. + + Raises: + KeyError: If no haiku exists with the given ID. + """ + haiku: Haiku | None = store.load_haiku(haiku_id) if haiku is None: # TODO: add "haiku not found" page @@ -55,6 +88,13 @@ def haiku_view(haiku_id): @app.route("/prompt") def prompt_view(): + """ + Render the haiku generation prompt page. + + Returns: + Text: The prompt.html template with title "Haiku generation". + """ + return render_template( "prompt.html", title="Haiku generation" @@ -63,6 +103,12 @@ def prompt_view(): @app.route("/scan") def scan_view(): + """ + Render the image scanning page. + + Returns: + Text: The scan.html template with title "Image scanning". + """ return render_template( "scan.html", title="Image scanning" @@ -71,6 +117,17 @@ def scan_view(): @app.route("/api/v1/haiku", methods=['POST']) def generate_haiku(): + """ + API endpoint to generate a new haiku based on the provided prompt. + + Accepts POST requests with JSON data containing a 'prompt' field. + Generates a haiku using the prompt, saves it to the store, and returns the ID. + + Returns: + str: The ID of the newly created haiku if method is POST. + tuple: Error message and status code 405 if method is not POST. + """ + if request.method == 'POST': json_data = request.get_json() prompt = json_data["prompt"] @@ -83,6 +140,13 @@ def generate_haiku(): @app.route('/favicon.ico') def favicon(): + """ + Serve the favicon.ico file from the static directory. + + Returns: + Response: The favicon.ico file with the appropriate MIME type. + """ + return send_from_directory(os.path.join(app.root_path, 'static/img'), 'favicon.ico', mimetype='image/vnd.microsoft.icon') diff --git a/senju/store_manager.py b/senju/store_manager.py index 72a4561..8e418cd 100644 --- a/senju/store_manager.py +++ b/senju/store_manager.py @@ -25,13 +25,43 @@ class StoreManager: logger: Logger def __init__(self, path_to_db: Path = DEFAULT_DB_PATH) -> None: + """ + Initialize the StoreManager with a database path. + + Args: + path_to_db (Path, optional): Path to the TinyDB database file. + Defaults to DEFAULT_DB_PATH. + """ self._db = TinyDB(path_to_db) self.logger = Logger(__name__) def _query(self, query: QueryImpl) -> list[dict]: + """ + Execute a query against the database. + + Args: + query (QueryImpl): TinyDB query to execute. + + Returns: + list[dict]: List of documents matching the query. + """ + return self._db.search(query) def _load(self, id: int) -> Optional[dict]: + """ + Load a document by its ID. + + Args: + id (int): Document ID to load. + + Returns: + Optional[dict]: The document if found, None otherwise. + + Logs: + Warning if document with specified ID is not found. + """ + try: return self._db.get(doc_id=id) except IndexError as e: @@ -39,9 +69,29 @@ class StoreManager: return None def _save(self, data: dict) -> int: + """ + Save a document to the database. + + Args: + data (dict): Document data to save. + + Returns: + int: The document ID of the saved document. + """ + return self._db.insert(data) def load_haiku(self, key: int) -> Optional[Haiku]: + """ + Load a haiku by its ID. + + Args: + key (int): The ID of the haiku to load. + + Returns: + Optional[Haiku]: A Haiku object if found, None otherwise. + """ + raw_haiku: dict | None = self._load(key) if raw_haiku is None: return None @@ -49,9 +99,29 @@ class StoreManager: return h def save_haiku(self, data: Haiku) -> int: + """ + Save a haiku to the database. + + Args: + data (Haiku): The Haiku object to save. + + Returns: + int: The document ID of the saved haiku. + """ + return self._save(data.__dict__) def get_id_of_latest_haiku(self) -> Optional[int]: + """ + Get the ID of the most recently added haiku. + + Returns: + Optional[int]: The ID of the latest haiku if any exists, None otherwise. + + Logs: + Error if the database is empty. + """ + try: id = self._db.all()[-1].doc_id return id From ab47d13938626866a0906a231851006b13012f98 Mon Sep 17 00:00:00 2001 From: Alivecow Date: Fri, 21 Mar 2025 16:27:28 +0100 Subject: [PATCH 03/23] refactor: Apply precommit autochanges --- .coveragerc | 2 +- docs/source/conf.py | 3 +++ docs/source/index.rst | 2 +- senju/main.py | 10 ++++---- senju/templates/scan.html | 54 +++++++++++++++++++-------------------- 5 files changed, 37 insertions(+), 34 deletions(-) diff --git a/.coveragerc b/.coveragerc index 3dbfbb4..c712d25 100644 --- a/.coveragerc +++ b/.coveragerc @@ -1,2 +1,2 @@ [run] -omit = tests/* \ No newline at end of file +omit = tests/* diff --git a/docs/source/conf.py b/docs/source/conf.py index 3a1a6eb..f7adaa5 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -3,10 +3,13 @@ # For the full list of built-in configuration values, see the documentation: # https://www.sphinx-doc.org/en/master/usage/configuration.html +from __future__ import annotations + # -- Project information ----------------------------------------------------- # https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information import os import sys + sys.path.insert(0, os.path.abspath("../../senju")) project = 'senju' diff --git a/docs/source/index.rst b/docs/source/index.rst index aa7c231..d4ee233 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -16,4 +16,4 @@ documentation for details. :caption: Contents: usage - _modules/modules \ No newline at end of file + _modules/modules diff --git a/senju/main.py b/senju/main.py index 575dc73..a457e58 100644 --- a/senju/main.py +++ b/senju/main.py @@ -1,15 +1,14 @@ from __future__ import annotations +import os from pathlib import Path -from flask import (Flask, redirect, render_template, request, url_for, - send_from_directory) +from flask import (Flask, redirect, render_template, request, + send_from_directory, url_for) from senju.haiku import Haiku from senju.store_manager import StoreManager -import os - app = Flask(__name__) store = StoreManager(Path("/tmp/store.db")) @@ -121,7 +120,8 @@ def generate_haiku(): API endpoint to generate a new haiku based on the provided prompt. Accepts POST requests with JSON data containing a 'prompt' field. - Generates a haiku using the prompt, saves it to the store, and returns the ID. + Generates a haiku using the prompt, saves it to the store, + and returns the ID. Returns: str: The ID of the newly created haiku if method is POST. diff --git a/senju/templates/scan.html b/senju/templates/scan.html index b84a917..abe9564 100644 --- a/senju/templates/scan.html +++ b/senju/templates/scan.html @@ -12,7 +12,7 @@
- +

Upload your image

@@ -27,7 +27,7 @@
- + - + - + -
- +
+

AI recognized the following:

Waiting for input...

@@ -62,7 +62,7 @@
- +