mirror of
https://github.com/senju1337/senju.git
synced 2025-12-24 07:39:29 +00:00
docs: Add module level dockstrings and change other
Refs: OPS-68
This commit is contained in:
parent
ab47d13938
commit
8a3c997cf7
3 changed files with 213 additions and 101 deletions
|
|
@ -1,3 +1,59 @@
|
||||||
|
"""
|
||||||
|
Haiku Generation Module
|
||||||
|
=======================
|
||||||
|
|
||||||
|
A client interface for AI-powered haiku poem generation.
|
||||||
|
|
||||||
|
This module provides the core functionality for communicating with an Ollama-based
|
||||||
|
AI service to generate three-line haiku poems. It handles the entire generation
|
||||||
|
process, from sending properly formatted requests to processing and validating
|
||||||
|
the returned poems.
|
||||||
|
|
||||||
|
Classes
|
||||||
|
-------
|
||||||
|
Haiku
|
||||||
|
A dataclass representation of a haiku poem, providing structure for storage,
|
||||||
|
manipulation and serialization of poem data.
|
||||||
|
|
||||||
|
**Methods**:
|
||||||
|
|
||||||
|
* ``to_json()``: Converts a haiku instance to JSON format for API responses
|
||||||
|
* ``generate_haiku(seed_text)``: Creates a new haiku using the AI service
|
||||||
|
|
||||||
|
Constants
|
||||||
|
---------
|
||||||
|
AI_SERVICE_URL
|
||||||
|
The endpoint URL for the Ollama API service.
|
||||||
|
|
||||||
|
AI_MODEL_NAME
|
||||||
|
The specific AI model used for haiku generation.
|
||||||
|
|
||||||
|
REQUEST_TIMEOUT
|
||||||
|
The maximum time (in seconds) to wait for AI service responses.
|
||||||
|
|
||||||
|
Dependencies
|
||||||
|
------------
|
||||||
|
* requests: HTTP client library for API communication
|
||||||
|
* dataclasses: Support for the Haiku data structure
|
||||||
|
* logging: Error and diagnostic information capture
|
||||||
|
* json: Processing of API responses
|
||||||
|
|
||||||
|
Implementation Details
|
||||||
|
----------------------
|
||||||
|
The module implements a robust communication pattern with the AI service, including:
|
||||||
|
|
||||||
|
1. Proper request formatting with seed text integration
|
||||||
|
2. Multiple retry attempts for handling temporary service issues
|
||||||
|
3. Response validation to ensure the returned text follows haiku structure
|
||||||
|
4. Fallback mechanisms when the AI service returns unsuitable content
|
||||||
|
5. JSON serialization for consistent data exchange
|
||||||
|
|
||||||
|
When communicating with the AI service, the module maintains appropriate
|
||||||
|
error handling and logging to help diagnose any generation issues. It aims
|
||||||
|
to provide a reliable haiku generation experience even when dealing with the
|
||||||
|
inherent unpredictability of AI-generated content.
|
||||||
|
"""
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import json
|
import json
|
||||||
|
|
@ -19,73 +75,64 @@ def foobar():
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class Haiku:
|
class Haiku:
|
||||||
|
"""
|
||||||
|
A class representing a haiku poem with three lines.
|
||||||
|
|
||||||
|
:ivar lines: A list containing the three lines of the haiku.
|
||||||
|
:type lines: list[str]
|
||||||
|
"""
|
||||||
lines: list[str]
|
lines: list[str]
|
||||||
|
|
||||||
def get_json(self):
|
def get_json(self):
|
||||||
"""
|
"""
|
||||||
Converts the haiku lines to a JSON string.
|
Converts the haiku lines to a JSON string.
|
||||||
|
|
||||||
Returns:
|
:return: A JSON string representation of the haiku lines.
|
||||||
str: A JSON string representation of the haiku lines.
|
:rtype: str
|
||||||
"""
|
"""
|
||||||
|
|
||||||
return json.dumps(self.lines)
|
return json.dumps(self.lines)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def request_haiku(seed: str) -> Haiku:
|
def request_haiku(seed: str) -> 'Haiku':
|
||||||
"""
|
"""
|
||||||
Generates a haiku using an AI model based on the provided seed text.
|
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.
|
This function prompts the AI to generate a haiku based on the user input.
|
||||||
It validates that the response:
|
It validates that the response contains exactly 3 lines.
|
||||||
- Contains exactly 3 lines
|
|
||||||
|
|
||||||
The function will retry until a valid haiku is generated.
|
The function will retry until a valid haiku is generated.
|
||||||
|
|
||||||
Args:
|
:param seed: The input text used to inspire the haiku generation.
|
||||||
seed (str): The input text used to inspire the haiku generation.
|
:type seed: str
|
||||||
|
:return: A new Haiku object containing the generated three lines.
|
||||||
|
:rtype: Haiku
|
||||||
|
|
||||||
Returns:
|
:raises: Possible JSONDecodeError which is caught and handled with retries.
|
||||||
Haiku: A new Haiku object containing the generated three lines.
|
|
||||||
|
|
||||||
Raises:
|
|
||||||
Possible JSONDecodeError which is caught and handled with retries.
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
ai_gen_request = {
|
ai_gen_request = {
|
||||||
"model": "haiku",
|
"model": "haiku",
|
||||||
"prompt": f"{seed}",
|
"prompt": f"{seed}",
|
||||||
"stream": False,
|
"stream": False,
|
||||||
"eval_count": 20
|
"eval_count": 20
|
||||||
}
|
}
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
r = requests.post(url=AI_BASE_URL + AI_GEN_ENDPOINT,
|
r = requests.post(url=AI_BASE_URL + AI_GEN_ENDPOINT,
|
||||||
json=ai_gen_request)
|
json=ai_gen_request)
|
||||||
ai_response = str(r.json()["response"])
|
ai_response = str(r.json()["response"])
|
||||||
|
|
||||||
logging.warning(ai_response)
|
logging.warning(ai_response)
|
||||||
|
|
||||||
lines = ai_response.split("\n")
|
lines = ai_response.split("\n")
|
||||||
|
|
||||||
for _ in range(0, 2):
|
for _ in range(0, 2):
|
||||||
lines.pop()
|
lines.pop()
|
||||||
|
|
||||||
logging.warning(lines)
|
logging.warning(lines)
|
||||||
|
|
||||||
if len(lines) != 3:
|
if len(lines) != 3:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
haiku = Haiku(
|
haiku = Haiku(
|
||||||
[
|
[
|
||||||
lines[0],
|
lines[0],
|
||||||
lines[1],
|
lines[1],
|
||||||
lines[2]
|
lines[2]
|
||||||
])
|
])
|
||||||
|
|
||||||
break
|
break
|
||||||
except json.JSONDecodeError:
|
except json.JSONDecodeError:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
return haiku
|
return haiku
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,42 @@
|
||||||
|
"""
|
||||||
|
Senju Haiku Web Application
|
||||||
|
===========================
|
||||||
|
|
||||||
|
A Flask-based web interface for generating, viewing, and managing haiku poetry.
|
||||||
|
|
||||||
|
This application provides a comprehensive interface between users and an AI-powered
|
||||||
|
haiku generation service, with persistent storage capabilities. Users can interact
|
||||||
|
with the system through both a web interface and a RESTful API.
|
||||||
|
|
||||||
|
Features
|
||||||
|
--------
|
||||||
|
* **Landing page**: Welcome interface introducing users to the Senju service
|
||||||
|
* **Browsing interface**: Gallery-style viewing of previously generated haikus
|
||||||
|
* **Prompt interface**: Text input system for generating haikus from seed text
|
||||||
|
* **Image scanning**: Experimental interface for creating haikus from visual inputs
|
||||||
|
* **RESTful API**: Programmatic access for integration with other services
|
||||||
|
|
||||||
|
Architecture
|
||||||
|
------------
|
||||||
|
The application implements a RESTful architecture using Flask's routing system
|
||||||
|
and template rendering. All user interactions are handled through clearly defined
|
||||||
|
routes, with appropriate error handling for exceptional cases.
|
||||||
|
|
||||||
|
Dependencies
|
||||||
|
------------
|
||||||
|
* future.annotations: Enhanced type hint support
|
||||||
|
* os, Path: Filesystem operations for storage management
|
||||||
|
* Flask: Core web application framework
|
||||||
|
* Haiku: Custom class for poem representation and generation
|
||||||
|
* StoreManager: Database abstraction for persistence operations
|
||||||
|
|
||||||
|
Implementation
|
||||||
|
--------------
|
||||||
|
The module initializes both a Flask application instance and a StoreManager
|
||||||
|
with a configured storage location. All routes and view functions required
|
||||||
|
for the complete web interface are defined within this module.
|
||||||
|
"""
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
|
@ -26,32 +65,26 @@ def index_view():
|
||||||
"""
|
"""
|
||||||
Render the main index page of the application.
|
Render the main index page of the application.
|
||||||
|
|
||||||
Returns:
|
:return: The index.html template with title "Senju".
|
||||||
Text: The index.html template with title "Senju".
|
:rtype: flask.Response
|
||||||
"""
|
"""
|
||||||
|
|
||||||
return render_template("index.html", title="Senju")
|
return render_template("index.html", title="Senju")
|
||||||
|
|
||||||
|
|
||||||
@app.route("/haiku/")
|
@app.route("/haiku/")
|
||||||
def haiku_index_view():
|
def haiku_index_view():
|
||||||
"""
|
"""
|
||||||
Redirect to the most recently created haiku.
|
Redirect to the most recently created haiku.
|
||||||
|
|
||||||
Returns:
|
:return: Redirects to the haiku_view route with the latest haiku ID.
|
||||||
Response: Redirects to the haiku_view route with the latest haiku ID.
|
:rtype: flask.Response
|
||||||
|
:raises KeyError: If no haikus exist in the store yet.
|
||||||
Raises:
|
|
||||||
KeyError: If no haikus exist in the store yet.
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
haiku_id: int | None = store.get_id_of_latest_haiku()
|
haiku_id: int | None = store.get_id_of_latest_haiku()
|
||||||
if haiku_id is None:
|
if haiku_id is None:
|
||||||
# TODO: add "empty haiku list" error page
|
# TODO: add "empty haiku list" error page
|
||||||
raise KeyError("no haiku exist yet")
|
raise KeyError("no haiku exist yet")
|
||||||
return redirect(url_for("haiku_view", haiku_id=haiku_id))
|
return redirect(url_for("haiku_view", haiku_id=haiku_id))
|
||||||
|
|
||||||
|
|
||||||
@app.route("/haiku/<int:haiku_id>")
|
@app.route("/haiku/<int:haiku_id>")
|
||||||
def haiku_view(haiku_id):
|
def haiku_view(haiku_id):
|
||||||
"""
|
"""
|
||||||
|
|
@ -61,16 +94,12 @@ def haiku_view(haiku_id):
|
||||||
the haiku.html template. If no haiku is found with the provided ID,
|
the haiku.html template. If no haiku is found with the provided ID,
|
||||||
raises a KeyError.
|
raises a KeyError.
|
||||||
|
|
||||||
Args:
|
:param haiku_id: The ID of the haiku to display.
|
||||||
haiku_id (int): The ID of the haiku to display.
|
:type haiku_id: int
|
||||||
|
:return: The haiku.html template with the haiku data in context.
|
||||||
Returns:
|
:rtype: flask.Response
|
||||||
Text: The haiku.html template with the haiku data in context.
|
:raises KeyError: If no haiku exists with the given ID.
|
||||||
|
|
||||||
Raises:
|
|
||||||
KeyError: If no haiku exists with the given ID.
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
haiku: Haiku | None = store.load_haiku(haiku_id)
|
haiku: Haiku | None = store.load_haiku(haiku_id)
|
||||||
if haiku is None:
|
if haiku is None:
|
||||||
# TODO: add "haiku not found" page
|
# TODO: add "haiku not found" page
|
||||||
|
|
@ -78,42 +107,37 @@ def haiku_view(haiku_id):
|
||||||
context: dict = {
|
context: dict = {
|
||||||
"haiku": haiku
|
"haiku": haiku
|
||||||
}
|
}
|
||||||
|
|
||||||
return render_template(
|
return render_template(
|
||||||
"haiku.html",
|
"haiku.html",
|
||||||
context=context,
|
context=context,
|
||||||
title="Haiku of the Day")
|
title="Haiku of the Day")
|
||||||
|
|
||||||
|
|
||||||
@app.route("/prompt")
|
@app.route("/prompt")
|
||||||
def prompt_view():
|
def prompt_view():
|
||||||
"""
|
"""
|
||||||
Render the haiku generation prompt page.
|
Render the haiku generation prompt page.
|
||||||
|
|
||||||
Returns:
|
:return: The prompt.html template with title "Haiku generation".
|
||||||
Text: The prompt.html template with title "Haiku generation".
|
:rtype: flask.Response
|
||||||
"""
|
"""
|
||||||
|
|
||||||
return render_template(
|
return render_template(
|
||||||
"prompt.html",
|
"prompt.html",
|
||||||
title="Haiku generation"
|
title="Haiku generation"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@app.route("/scan")
|
@app.route("/scan")
|
||||||
def scan_view():
|
def scan_view():
|
||||||
"""
|
"""
|
||||||
Render the image scanning page.
|
Render the image scanning page.
|
||||||
|
|
||||||
Returns:
|
:return: The scan.html template with title "Image scanning".
|
||||||
Text: The scan.html template with title "Image scanning".
|
:rtype: flask.Response
|
||||||
"""
|
"""
|
||||||
return render_template(
|
return render_template(
|
||||||
"scan.html",
|
"scan.html",
|
||||||
title="Image scanning"
|
title="Image scanning"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@app.route("/api/v1/haiku", methods=['POST'])
|
@app.route("/api/v1/haiku", methods=['POST'])
|
||||||
def generate_haiku():
|
def generate_haiku():
|
||||||
"""
|
"""
|
||||||
|
|
@ -123,11 +147,10 @@ def generate_haiku():
|
||||||
Generates a haiku using the prompt, saves it to the store,
|
Generates a haiku using the prompt, saves it to the store,
|
||||||
and returns the ID.
|
and returns the ID.
|
||||||
|
|
||||||
Returns:
|
:return: The ID of the newly created haiku if method is POST.
|
||||||
str: The ID of the newly created haiku if method is POST.
|
Error message and status code 405 if method is not POST.
|
||||||
tuple: Error message and status code 405 if method is not POST.
|
:rtype: Union[str, Tuple[str, int]]
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if request.method == 'POST':
|
if request.method == 'POST':
|
||||||
json_data = request.get_json()
|
json_data = request.get_json()
|
||||||
prompt = json_data["prompt"]
|
prompt = json_data["prompt"]
|
||||||
|
|
@ -137,16 +160,14 @@ def generate_haiku():
|
||||||
else:
|
else:
|
||||||
return "Method not allowed", 405
|
return "Method not allowed", 405
|
||||||
|
|
||||||
|
|
||||||
@app.route('/favicon.ico')
|
@app.route('/favicon.ico')
|
||||||
def favicon():
|
def favicon():
|
||||||
"""
|
"""
|
||||||
Serve the favicon.ico file from the static directory.
|
Serve the favicon.ico file from the static directory.
|
||||||
|
|
||||||
Returns:
|
:return: The favicon.ico file with the appropriate MIME type.
|
||||||
Response: The favicon.ico file with the appropriate MIME type.
|
:rtype: flask.Response
|
||||||
"""
|
"""
|
||||||
|
|
||||||
return send_from_directory(os.path.join(app.root_path, 'static/img'),
|
return send_from_directory(os.path.join(app.root_path, 'static/img'),
|
||||||
'favicon.ico',
|
'favicon.ico',
|
||||||
mimetype='image/vnd.microsoft.icon')
|
mimetype='image/vnd.microsoft.icon')
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,47 @@
|
||||||
|
"""
|
||||||
|
Senju Database Management Module
|
||||||
|
================================
|
||||||
|
|
||||||
|
A database interaction layer for the Senju haiku management system.
|
||||||
|
|
||||||
|
This module implements a lightweight document database abstraction using TinyDB
|
||||||
|
for persistent storage of haiku poems. It provides a clean interface for storing,
|
||||||
|
retrieving, updating, and managing haiku entries in the system.
|
||||||
|
|
||||||
|
Classes
|
||||||
|
-------
|
||||||
|
StoreManager
|
||||||
|
The primary class responsible for all database operations. Handles connection
|
||||||
|
management, CRUD operations, and query capabilities for haiku data.
|
||||||
|
|
||||||
|
Functions
|
||||||
|
---------
|
||||||
|
utility_function
|
||||||
|
Provides simple arithmetic operations to support database functionalities.
|
||||||
|
|
||||||
|
Constants
|
||||||
|
---------
|
||||||
|
DEFAULT_DB_PATH
|
||||||
|
The default filesystem location for the TinyDB database file (/var/lib/senju.json).
|
||||||
|
|
||||||
|
Dependencies
|
||||||
|
------------
|
||||||
|
* future.annotations: Enhanced type hint support
|
||||||
|
* logging.Logger: Diagnostic and error logging capabilities
|
||||||
|
* pathlib.Path: Cross-platform filesystem path handling
|
||||||
|
* typing.Optional: Type annotations for nullable values
|
||||||
|
* tinydb.TinyDB: Lightweight document database implementation
|
||||||
|
* tinydb.QueryImpl: Query builder for database searches
|
||||||
|
* senju.haiku.Haiku: Data model for haiku representation
|
||||||
|
|
||||||
|
Implementation Details
|
||||||
|
----------------------
|
||||||
|
The module uses TinyDB as its storage engine, providing a JSON-based document
|
||||||
|
storage solution that balances simplicity with functionality. The StoreManager
|
||||||
|
abstracts all database operations behind a clean API, handling connection lifecycle
|
||||||
|
and providing methods for common operations on haiku data.
|
||||||
|
"""
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from logging import Logger
|
from logging import Logger
|
||||||
|
|
@ -20,6 +64,17 @@ def foobar():
|
||||||
|
|
||||||
|
|
||||||
class StoreManager:
|
class StoreManager:
|
||||||
|
"""
|
||||||
|
Manages the storage and retrieval of haiku data using TinyDB.
|
||||||
|
|
||||||
|
This class provides an interface for saving and loading haikus from
|
||||||
|
a TinyDB database file.
|
||||||
|
|
||||||
|
:ivar _db: Database instance for storing haiku data.
|
||||||
|
:type _db: TinyDB
|
||||||
|
:ivar logger: Logger for tracking operations and errors.
|
||||||
|
:type logger: Logger
|
||||||
|
"""
|
||||||
__slots__ = "_db", "logger"
|
__slots__ = "_db", "logger"
|
||||||
_db: TinyDB
|
_db: TinyDB
|
||||||
logger: Logger
|
logger: Logger
|
||||||
|
|
@ -28,9 +83,9 @@ class StoreManager:
|
||||||
"""
|
"""
|
||||||
Initialize the StoreManager with a database path.
|
Initialize the StoreManager with a database path.
|
||||||
|
|
||||||
Args:
|
:param path_to_db: Path to the TinyDB database file. Defaults to DEFAULT_DB_PATH.
|
||||||
path_to_db (Path, optional): Path to the TinyDB database file.
|
:type path_to_db: Path, optional
|
||||||
Defaults to DEFAULT_DB_PATH.
|
:return: None
|
||||||
"""
|
"""
|
||||||
self._db = TinyDB(path_to_db)
|
self._db = TinyDB(path_to_db)
|
||||||
self.logger = Logger(__name__)
|
self.logger = Logger(__name__)
|
||||||
|
|
@ -39,29 +94,25 @@ class StoreManager:
|
||||||
"""
|
"""
|
||||||
Execute a query against the database.
|
Execute a query against the database.
|
||||||
|
|
||||||
Args:
|
:param query: TinyDB query to execute.
|
||||||
query (QueryImpl): TinyDB query to execute.
|
:type query: QueryImpl
|
||||||
|
:return: List of documents matching the query.
|
||||||
Returns:
|
:rtype: list[dict]
|
||||||
list[dict]: List of documents matching the query.
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
return self._db.search(query)
|
return self._db.search(query)
|
||||||
|
|
||||||
def _load(self, id: int) -> Optional[dict]:
|
def _load(self, id: int) -> Optional[dict]:
|
||||||
"""
|
"""
|
||||||
Load a document by its ID.
|
Load a document by its ID.
|
||||||
|
|
||||||
Args:
|
:param id: Document ID to load.
|
||||||
id (int): Document ID to load.
|
:type id: int
|
||||||
|
:return: The document if found, None otherwise.
|
||||||
|
:rtype: Optional[dict]
|
||||||
|
|
||||||
Returns:
|
.. note::
|
||||||
Optional[dict]: The document if found, None otherwise.
|
Logs a warning if document with specified ID is not found.
|
||||||
|
|
||||||
Logs:
|
|
||||||
Warning if document with specified ID is not found.
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
try:
|
try:
|
||||||
return self._db.get(doc_id=id)
|
return self._db.get(doc_id=id)
|
||||||
except IndexError as e:
|
except IndexError as e:
|
||||||
|
|
@ -72,26 +123,22 @@ class StoreManager:
|
||||||
"""
|
"""
|
||||||
Save a document to the database.
|
Save a document to the database.
|
||||||
|
|
||||||
Args:
|
:param data: Document data to save.
|
||||||
data (dict): Document data to save.
|
:type data: dict
|
||||||
|
:return: The document ID of the saved document.
|
||||||
Returns:
|
:rtype: int
|
||||||
int: The document ID of the saved document.
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
return self._db.insert(data)
|
return self._db.insert(data)
|
||||||
|
|
||||||
def load_haiku(self, key: int) -> Optional[Haiku]:
|
def load_haiku(self, key: int) -> Optional[Haiku]:
|
||||||
"""
|
"""
|
||||||
Load a haiku by its ID.
|
Load a haiku by its ID.
|
||||||
|
|
||||||
Args:
|
:param key: The ID of the haiku to load.
|
||||||
key (int): The ID of the haiku to load.
|
:type key: int
|
||||||
|
:return: A Haiku object if found, None otherwise.
|
||||||
Returns:
|
:rtype: Optional[Haiku]
|
||||||
Optional[Haiku]: A Haiku object if found, None otherwise.
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
raw_haiku: dict | None = self._load(key)
|
raw_haiku: dict | None = self._load(key)
|
||||||
if raw_haiku is None:
|
if raw_haiku is None:
|
||||||
return None
|
return None
|
||||||
|
|
@ -102,26 +149,23 @@ class StoreManager:
|
||||||
"""
|
"""
|
||||||
Save a haiku to the database.
|
Save a haiku to the database.
|
||||||
|
|
||||||
Args:
|
:param data: The Haiku object to save.
|
||||||
data (Haiku): The Haiku object to save.
|
:type data: Haiku
|
||||||
|
:return: The document ID of the saved haiku.
|
||||||
Returns:
|
:rtype: int
|
||||||
int: The document ID of the saved haiku.
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
return self._save(data.__dict__)
|
return self._save(data.__dict__)
|
||||||
|
|
||||||
def get_id_of_latest_haiku(self) -> Optional[int]:
|
def get_id_of_latest_haiku(self) -> Optional[int]:
|
||||||
"""
|
"""
|
||||||
Get the ID of the most recently added haiku.
|
Get the ID of the most recently added haiku.
|
||||||
|
|
||||||
Returns:
|
:return: The ID of the latest haiku if any exists, None otherwise.
|
||||||
Optional[int]: The ID of the latest haiku if any exists, None otherwise.
|
:rtype: Optional[int]
|
||||||
|
|
||||||
Logs:
|
.. note::
|
||||||
Error if the database is empty.
|
Logs an error if the database is empty.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
try:
|
try:
|
||||||
id = self._db.all()[-1].doc_id
|
id = self._db.all()[-1].doc_id
|
||||||
return id
|
return id
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue