Add LRU caching to Bible methods and improve API performance

Import lru_cache and add caching decorators to frequently called methods
including verse lookup, book/chapter enumeration, and text retrieval.
Replace iterator-based verse text lookup with direct cached method.
This commit is contained in:
2025-05-26 15:23:20 -04:00
parent 141c30d2a2
commit d4ede379c1
+107 -1
View File
@@ -150,7 +150,113 @@ class VerseReference(BaseModel):
return cls(book=book, chapter=int(chapter), verse=int(verse))
class @lru_cache(maxsize=256)
class Bible:
"""Represents a Bible."""
def __init__(self, fname=None):
if fname is None:
# Get the directory where this script is located
current_dir = Path(__file__).parent
# Look for verses file in the package static directory
self.fname = current_dir / "static" / "verses-1769.json"
else:
self.fname = Path(fname)
# Load the JSON data from the file.
with open(self.fname, "r") as f:
self.verses = json.load(f)
@lru_cache(maxsize=1024)
def __getitem__(self, verse):
"""Returns the text of the verse."""
# Check if the verse exists in the dictionary.
if verse not in self.verses:
raise KeyError(f"Verse {verse} not found in the Bible.")
return self.verses[verse]
def iter_verses(self):
"""Iterates over the verses in the Bible."""
for verse in self.verses:
verse_ref = VerseReference.from_string(verse)
# Remove the leading "# " and brackets from the text.
# This is a workaround for the JSON format.
# The text is stored as a string with leading "# " and brackets.
# Example: "# [In the beginning God created the heaven and the earth.]"
text = self.verses[verse]
text.replace("# ", "")
text.replace("[", "")
text.replace("]", "")
yield Verse(
book=verse_ref.book,
chapter=verse_ref.chapter,
verse=verse_ref.verse,
text=text,
)
@lru_cache(maxsize=1)
def get_books(self):
"""Returns a list of all books in the Bible."""
yielded = set()
books = []
for verse in self.verses:
verse_ref = VerseReference.from_string(verse)
if verse_ref.book in yielded:
continue
yielded.add(verse_ref.book)
books.append(verse_ref.book)
return books
def iter_books(self):
"""Iterates over the books in the Bible."""
for book in self.get_books():
yield book
@lru_cache(maxsize=1)
def get_chapters(self):
"""Returns a list of all chapters in the Bible."""
yielded = set()
chapters = []
for verse in self.verses:
verse_ref = VerseReference.from_string(verse)
if (verse_ref.book, verse_ref.chapter) in yielded:
continue
yielded.add((verse_ref.book, verse_ref.chapter))
chapters.append((verse_ref.book, verse_ref.chapter))
return chapters
def iter_chapters(self):
"""Iterates over the chapters in the Bible."""
for book, chapter in self.get_chapters():
yield book, chapter
def iter_chapters_by_book(self):
"""Iterates over the chapters in the Bible, grouped by book."""
yielded = set()
for verse in self.verses:
verse_ref = VerseReference.from_string(verse)
if (verse_ref.book, verse_ref.chapter) in yielded:
continue
yielded.add((verse_ref.book, verse_ref.chapter))
yield verse_ref.book, verse_ref.chapter
def iter_verse_references(self):
"""Iterates over the verse references in the Bible."""
for verse in self.verses:
yield VerseReference.from_string(verse)
@lru_cache(maxsize=256)
def get_verses_by_book_chapter(self, book, chapter):
"""Returns a list of verses for a specific book and chapter."""
verses = []