Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Clean up get_chapters code and expand tests #97

Merged
merged 1 commit into from
Jan 24, 2024
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
54 changes: 25 additions & 29 deletions machine/scripture/parse.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import re
from typing import Dict, List, Set, Union

from .canon import book_id_to_number
from .canon import book_id_to_number, book_number_to_id
from .constants import ORIGINAL_VERSIFICATION
from .verse_ref import Versification

COMMA_SEPARATED_BOOKS = re.compile(r"([A-Z\d]{3}|OT|NT)(, ?([A-Z\d]{3}|OT|NT))*")
BOOK_RANGE = re.compile(r"[A-Z\d]{3}-[A-Z\d]{3}")
CHAPTER_SELECTION = re.compile(r"[A-Z\d]{3} ?(\d+|\d+-\d+)(, ?(\d+|\d+-\d+))*")
BOOK_RANGE = re.compile(r"-?[A-Z\d]{3}-[A-Z\d]{3}")
CHAPTER_SELECTION = re.compile(r"-?[A-Z\d]{3} ?(\d+|\d+-\d+)(, ?(\d+|\d+-\d+))*")


def get_books(books: Union[str, List[str]]) -> Set[int]:
Expand Down Expand Up @@ -50,36 +50,28 @@ def get_chapters(
if isinstance(chapter_selections, str):
chapter_selections = chapter_selections.strip()

delimiter = ";"
if ";" in chapter_selections:
chapter_selections = chapter_selections.split(";")
delimiter = ";"
elif re.fullmatch(COMMA_SEPARATED_BOOKS, chapter_selections) is not None:
chapter_selections = chapter_selections.split(",")
elif chapter_selections.startswith("-"):
raise ValueError(f"Cannot subtract before adding sections: {chapter_selections}")
elif re.search(BOOK_RANGE, chapter_selections):
if len(chapter_selections) == 7:
chapter_selections = [chapter_selections]
else:
raise ValueError(
"Invalid syntax. If one of your selections is a range of books, \
selections must be seprated with semicolons."
)
elif re.fullmatch(CHAPTER_SELECTION, chapter_selections) is None:
delimiter = ","
elif (
re.fullmatch(BOOK_RANGE, chapter_selections) is None
and re.fullmatch(CHAPTER_SELECTION, chapter_selections) is None
):
raise ValueError(
"Invalid syntax. If one of your selections includes specific chapters or subtraction, \
selections must be separated with semicolons."
"Invalid syntax. If you are providing multiple selections, e.g. a range of books \
followed by a selection of chapters from a book, separate each selection with a semicolon."
)
else:
chapter_selections = [chapter_selections]

chapter_selections = chapter_selections.split(delimiter)

for section in chapter_selections:
section = section.strip()

if section.startswith("-"): # Subtraction
section = section[1:]
if any(
s.isdigit() and (i == len(section) - 1 or not section[i + 1].isalpha()) for i, s in enumerate(section)
): # Specific chapters from one book
if section[-1].isdigit(): # Specific chapters from one book
book = book_id_to_number(section[:3])
if book == 0:
raise ValueError(f"{section[:3]} is an invalid book ID.")
Expand Down Expand Up @@ -120,10 +112,13 @@ def get_chapters(
if len(ends) != 2 or book_id_to_number(ends[0]) == 0 or book_id_to_number(ends[1]) == 0:
raise ValueError(f"{section} is an invalid book range.")

if book_id_to_number(ends[0]) > book_id_to_number(ends[1]):
raise ValueError(f"{section} is an invalid book range. {ends[1]} precedes {ends[0]}.")

for i in range(book_id_to_number(ends[0]), book_id_to_number(ends[1]) + 1):
if i not in chapters:
raise ValueError(
f"{section[:3]} cannot be removed as it is not in the existing book selection."
f"{book_number_to_id(i)} cannot be removed as it is not in the existing book selection."
)

del chapters[i]
Expand All @@ -135,9 +130,7 @@ def get_chapters(
raise ValueError(f"{section[:3]} cannot be removed as it is not in the existing book selection.")

del chapters[book]
elif any(
s.isdigit() and (i == len(section) - 1 or not section[i + 1].isalpha()) for i, s in enumerate(section)
): # Specific chapters from one book
elif section[-1].isdigit(): # Specific chapters from one book
book = book_id_to_number(section[:3])
if book == 0:
raise ValueError(f"{section[:3]} is an invalid book ID.")
Expand All @@ -155,13 +148,13 @@ def get_chapters(
chapter_num = chapter_num.strip()
if "-" in chapter_num:
start, end = chapter_num.split("-")
if int(start) > last_chapter or int(end) > last_chapter:
if int(start) == 0 or int(start) > last_chapter or int(end) > last_chapter or int(start) > int(end):
raise ValueError(f"{chapter_num} is an invalid chapter range.")

for i in range(int(start), int(end) + 1):
book_chapters.add(i)
else:
if int(chapter_num) > last_chapter:
if int(chapter_num) == 0 or int(chapter_num) > last_chapter:
raise ValueError(f"{chapter_num} is an invalid chapter number.")

book_chapters.add(int(chapter_num))
Expand All @@ -175,6 +168,9 @@ def get_chapters(
if len(ends) != 2 or book_id_to_number(ends[0]) == 0 or book_id_to_number(ends[1]) == 0:
raise ValueError(f"{section} is an invalid book range.")

if book_id_to_number(ends[0]) > book_id_to_number(ends[1]):
raise ValueError(f"{section} is an invalid book range. {ends[1]} precedes {ends[0]}.")

for i in range(book_id_to_number(ends[0]), book_id_to_number(ends[1]) + 1):
chapters[i] = []
elif section == "OT":
Expand Down
24 changes: 24 additions & 0 deletions tests/scripture/test_parse.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,30 @@ def test_get_chapters() -> None:
assert get_chapters("NT;-MAT3-5,17;-REV21,22") == test_bible
assert get_chapters("MAT-JHN;-MAT-LUK") == {43: []}

with raises(ValueError):
# wrong order of chapters
print(get_chapters("MAT3-1"))

with raises(ValueError):
# wrong order of books
print(get_chapters("MRK-MAT"))

with raises(ValueError):
# wrong order of books in subtraction
print(get_chapters("-MRK-MAT"))

with raises(ValueError):
# chapter 0
print(get_chapters("MAT0-10"))

with raises(ValueError):
# invalid book/length of book name
get_chapters("MAT-FLUM")

with raises(ValueError):
# invalid book/length of book name in subtraction
get_chapters("-MAT-FLUM")

with raises(ValueError):
# empty string
get_chapters("")
Expand Down