diff --git a/sefaria/model/linker/referenceable_book_node.py b/sefaria/model/linker/referenceable_book_node.py index 36106666e5..bb09aa0cff 100644 --- a/sefaria/model/linker/referenceable_book_node.py +++ b/sefaria/model/linker/referenceable_book_node.py @@ -9,10 +9,31 @@ def subref(ref: text.Ref, section: int): if ref.index_node.addressTypes[len(ref.sections)-1] == "Talmud": - d = ref._core_dict() - d['sections'][-1] += (section-1) - d['toSections'] = d['sections'][:] - return text.Ref(_obj=d) + return _talmud_subref(ref, section) + elif ref.index.categories == ['Tanakh', 'Torah']: + return _parsha_subref(ref, section) + else: + return ref.subref(section) + + +def _talmud_subref(ref: text.Ref, section: int): + d = ref._core_dict() + d['sections'][-1] += (section-1) + d['toSections'] = d['sections'][:] + return text.Ref(_obj=d) + + +def _parsha_subref(ref: text.Ref, section: int): + parsha_trefs = {n.wholeRef for n in ref.index.get_alt_struct_leaves()} + if ref.normal() in parsha_trefs: + book_subref = text.Ref(ref.index.title).subref(section) + if ref.contains(book_subref): + return book_subref + else: + # section doesn't fall within parsha + # Note, only validates that perek is in parsha range, doesn't check segment level. + # Edge case is Parshat Noach 6:3 + raise InputError else: return ref.subref(section) diff --git a/sefaria/model/linker/tests/linker_test.py b/sefaria/model/linker/tests/linker_test.py index 95a33bb2ee..863631d274 100644 --- a/sefaria/model/linker/tests/linker_test.py +++ b/sefaria/model/linker/tests/linker_test.py @@ -29,7 +29,6 @@ def test_resolved_raw_ref_clone(): @pytest.mark.parametrize(('resolver_data', 'expected_trefs'), [ - [crrd(["@Parshat Vayikra", "#2", "#3"], lang='en'), ('Leviticus 2:3',)], # Numbered JAs [crrd(["@Jerusalem", "@Talmud", "@Yoma", "#5a"], lang='en'), ("Jerusalem Talmud Yoma 1:1:20-25",)], [crrd(["@Babylonian", "@Talmud", "@Sukkah", "#49b"], lang='en'), ("Sukkah 49b",)], @@ -51,6 +50,11 @@ def test_resolved_raw_ref_clone(): [crrd(['@שבת', '#א', '#ב']), ["Mishnah Shabbat 1:2"]], # shouldn't match Shabbat 2a by reversing order of parts [crrd(['@שבת', '#ב', '#א']), ["Shabbat 2a", "Mishnah Shabbat 2:1"]], # ambiguous case + # Parsha -> sections + [crrd(["@Parshat Vayikra", "#2", "#3"], lang='en'), ('Leviticus 2:3',)], + [crrd(["@Parshat Tzav", "#2", "#3"], lang='en'), tuple()], # validate that sections fall within parsha + pytest.param(crrd(["@Parshat Noach", "#6", "#3"], lang='en'), tuple(), marks=pytest.mark.xfail(reason="currently dont check if pasuk/perek pair fall in parsha, only perek")), + # Aliases for perakim [crrd(["@משנה", "@ברכות", "#פרק קמא"]), ("Mishnah Berakhot 1",)], [crrd(["@משנה", "@ברכות", "#פרק בתרא"]), ("Mishnah Berakhot 9",)],