refspy.models.verse

Data object for a verse.

Attributes:
  • library: 1
  • book: 2
  • chapter: 3
  • verse: 4
 1"""Data object for a verse.
 2
 3Attributes:
 4    library: 1
 5    book: 2
 6    chapter: 3
 7    verse: 4
 8"""
 9
10from typing import Self
11
12from pydantic import BaseModel
13
14from refspy.types.index import Index
15from refspy.types.number import Number
16
17
18VerseTuple = tuple[Number, Number, Number, Number]
19
20
21class Verse(BaseModel):
22    """
23    Library, Book, Chapter, Verse
24    """
25
26    library: Number
27    book: Number
28    chapter: Number
29    verse: Number
30
31    def tuple(self) -> VerseTuple:
32        """A sortable tuple for comparison operations."""
33        return (self.library, self.book, self.chapter, self.verse)
34
35    def __hash__(self) -> int:
36        """Unique ID for key values."""
37        return hash(self.tuple())
38
39    def __eq__(self, other) -> bool:  # <-- Should be Self; TypeError requires object
40        return self.tuple() == other.tuple()
41
42    def __lt__(self, other: Self) -> bool:
43        """Compare verses by comparing tuples."""
44        return self.tuple() < other.tuple()
45
46    def __le__(self, other: Self) -> bool:
47        """Compare verses by comparing tuples."""
48        return self.tuple() <= other.tuple()
49
50    def __gt__(self, other: Self) -> bool:
51        """Compare verses by comparing tuples."""
52        return self.tuple() > other.tuple()
53
54    def __ge__(self, other: Self) -> bool:
55        """Compare verses by comparing tuples."""
56        return self.tuple() >= other.tuple()
57
58    @classmethod
59    def from_index(cls, index: Index) -> Self:
60        """
61        Convert a verse's index number to its tuple form.
62
63        Example:
64            ```
65            verse = Verse.from_index(1002003004)
66            ```
67        """
68        lbc, v = divmod(index, 1000)
69        lb, c = divmod(lbc, 1000)
70        l, b = divmod(lb, 1000)
71        return cls(library=l, book=b, chapter=c, verse=v)
72
73    def index(self) -> Index:
74        """Create a `refspy.index.Index` number representing this verse.
75
76        Example:
77            `verse(1, 2, 3, 4)` becomes `1002003004`
78        """
79        return (
80            (self.library * 1000 + self.book) * 1000 + self.chapter
81        ) * 1000 + self.verse
82
83
84def verse(library: Number, book: Number, chapter: Number, verse: Number) -> Verse:
85    """A shorthand constructor for verses."""
86    return Verse(library=library, book=book, chapter=chapter, verse=verse)
VerseTuple = tuple[typing.Annotated[int, Ge(ge=1), Le(le=999)], typing.Annotated[int, Ge(ge=1), Le(le=999)], typing.Annotated[int, Ge(ge=1), Le(le=999)], typing.Annotated[int, Ge(ge=1), Le(le=999)]]
class Verse(pydantic.main.BaseModel):
22class Verse(BaseModel):
23    """
24    Library, Book, Chapter, Verse
25    """
26
27    library: Number
28    book: Number
29    chapter: Number
30    verse: Number
31
32    def tuple(self) -> VerseTuple:
33        """A sortable tuple for comparison operations."""
34        return (self.library, self.book, self.chapter, self.verse)
35
36    def __hash__(self) -> int:
37        """Unique ID for key values."""
38        return hash(self.tuple())
39
40    def __eq__(self, other) -> bool:  # <-- Should be Self; TypeError requires object
41        return self.tuple() == other.tuple()
42
43    def __lt__(self, other: Self) -> bool:
44        """Compare verses by comparing tuples."""
45        return self.tuple() < other.tuple()
46
47    def __le__(self, other: Self) -> bool:
48        """Compare verses by comparing tuples."""
49        return self.tuple() <= other.tuple()
50
51    def __gt__(self, other: Self) -> bool:
52        """Compare verses by comparing tuples."""
53        return self.tuple() > other.tuple()
54
55    def __ge__(self, other: Self) -> bool:
56        """Compare verses by comparing tuples."""
57        return self.tuple() >= other.tuple()
58
59    @classmethod
60    def from_index(cls, index: Index) -> Self:
61        """
62        Convert a verse's index number to its tuple form.
63
64        Example:
65            ```
66            verse = Verse.from_index(1002003004)
67            ```
68        """
69        lbc, v = divmod(index, 1000)
70        lb, c = divmod(lbc, 1000)
71        l, b = divmod(lb, 1000)
72        return cls(library=l, book=b, chapter=c, verse=v)
73
74    def index(self) -> Index:
75        """Create a `refspy.index.Index` number representing this verse.
76
77        Example:
78            `verse(1, 2, 3, 4)` becomes `1002003004`
79        """
80        return (
81            (self.library * 1000 + self.book) * 1000 + self.chapter
82        ) * 1000 + self.verse

Library, Book, Chapter, Verse

library: Annotated[int, Ge(ge=1), Le(le=999)]
book: Annotated[int, Ge(ge=1), Le(le=999)]
chapter: Annotated[int, Ge(ge=1), Le(le=999)]
verse: Annotated[int, Ge(ge=1), Le(le=999)]
def tuple( self) -> tuple[typing.Annotated[int, Ge(ge=1), Le(le=999)], typing.Annotated[int, Ge(ge=1), Le(le=999)], typing.Annotated[int, Ge(ge=1), Le(le=999)], typing.Annotated[int, Ge(ge=1), Le(le=999)]]:
32    def tuple(self) -> VerseTuple:
33        """A sortable tuple for comparison operations."""
34        return (self.library, self.book, self.chapter, self.verse)

A sortable tuple for comparison operations.

@classmethod
def from_index( cls, index: Annotated[int, Ge(ge=1001001001), Le(le=999999999999)]) -> Self:
59    @classmethod
60    def from_index(cls, index: Index) -> Self:
61        """
62        Convert a verse's index number to its tuple form.
63
64        Example:
65            ```
66            verse = Verse.from_index(1002003004)
67            ```
68        """
69        lbc, v = divmod(index, 1000)
70        lb, c = divmod(lbc, 1000)
71        l, b = divmod(lb, 1000)
72        return cls(library=l, book=b, chapter=c, verse=v)

Convert a verse's index number to its tuple form.

Example:
verse = Verse.from_index(1002003004)
def index(self) -> Annotated[int, Ge(ge=1001001001), Le(le=999999999999)]:
74    def index(self) -> Index:
75        """Create a `refspy.index.Index` number representing this verse.
76
77        Example:
78            `verse(1, 2, 3, 4)` becomes `1002003004`
79        """
80        return (
81            (self.library * 1000 + self.book) * 1000 + self.chapter
82        ) * 1000 + self.verse

Create a refspy.index.Index number representing this verse.

Example:

verse(1, 2, 3, 4) becomes 1002003004

model_config: ClassVar[pydantic.config.ConfigDict] = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

def verse( library: Annotated[int, Ge(ge=1), Le(le=999)], book: Annotated[int, Ge(ge=1), Le(le=999)], chapter: Annotated[int, Ge(ge=1), Le(le=999)], verse: Annotated[int, Ge(ge=1), Le(le=999)]) -> Verse:
85def verse(library: Number, book: Number, chapter: Number, verse: Number) -> Verse:
86    """A shorthand constructor for verses."""
87    return Verse(library=library, book=book, chapter=chapter, verse=verse)

A shorthand constructor for verses.