Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion machine/scripture/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
SEPTUAGINT_VERSIFICATION,
VULGATE_VERSIFICATION,
)
from .parse import get_books, get_chapters
from .parse import get_books, get_chapters, try_get_chapters
from .verse_ref import (
NULL_VERSIFICATION,
VERSE_RANGE_SEPARATOR,
Expand All @@ -44,6 +44,7 @@
"get_bbbcccvvv",
"get_books",
"get_chapters",
"try_get_chapters",
"is_book_id_valid",
"is_canonical",
"is_nt",
Expand Down
13 changes: 12 additions & 1 deletion machine/scripture/parse.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import re
from typing import Dict, List, Set, Union
from typing import Dict, List, Optional, Set, Union

from .canon import book_id_to_number, book_number_to_id
from .constants import ORIGINAL_VERSIFICATION
Expand Down Expand Up @@ -57,6 +57,8 @@ def _update_selection(book_set: Set[int], book_nums: Set[int], subtraction: bool

def parse_selection(selection: str, versification: Versification) -> Dict[int, List[int]]:
selection = selection.strip()
if len(selection) == 0:
raise ValueError("Empty book range.")
chapters = {}

if selection[-1].isdigit() and len(selection) > 3: # Specific chapters from one book
Expand Down Expand Up @@ -179,3 +181,12 @@ def get_chapters(
chapters[book] = selection_chapters[book]

return chapters


def try_get_chapters(
selections: Union[str, List[str]], versification: Versification = ORIGINAL_VERSIFICATION
) -> Optional[Dict[int, List[int]]]:
try:
return get_chapters(selections, versification)
except ValueError:
Comment thread
claude[bot] marked this conversation as resolved.
return None
29 changes: 28 additions & 1 deletion tests/scripture/test_parse.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from pytest import raises

from machine.scripture import get_books, get_chapters
from machine.scripture import get_books, get_chapters, try_get_chapters


def test_get_books() -> None:
Expand Down Expand Up @@ -177,3 +177,30 @@ def test_get_chapters() -> None:
get_chapters("OT,MAT1")
with raises(ValueError):
get_chapters("OT,MAT-LUK")

# empty segments

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FYI: F4. The empty-segment guard is tested only through string input with a doubled or lone ;. The list path (get_chapters(["MAT", ""]), ["-"], [""]) and a trailing delimiter ("MAT;") used to raise IndexError and now raise ValueError, which I confirmed by running them. No test pins this, so if it regresses, try_get_chapters raises again. Add one or two of these.

with raises(ValueError):
get_chapters("MAT;;MRK")
with raises(ValueError):
get_chapters(" ; ")
with raises(ValueError):
get_chapters(";")


def test_try_get_chapters() -> None:
assert try_get_chapters("MAT1-4,12,9") == {40: [1, 2, 3, 4, 9, 12]}
assert try_get_chapters("") == {}
assert try_get_chapters(["MAT", "-MAT 1"]) == {40: list(range(2, 29))}

# invalid syntax, book, chapter, and subtraction
assert try_get_chapters("OT,MAT1") is None
assert try_get_chapters("ABC") is None
assert try_get_chapters("MAT 500") is None
assert try_get_chapters("MAT3-1") is None
assert try_get_chapters("-MRK") is None
assert try_get_chapters("MRK 2-5;-MRK 6") is None

# empty segments
assert try_get_chapters("MAT;;MRK") is None
assert try_get_chapters(" ; ") is None
assert try_get_chapters(";") is None
Loading