From f0bfe1efb93e04e0e3b9a33b8b085fc09e86af36 Mon Sep 17 00:00:00 2001 From: Lukasz Kasprzak Date: Tue, 28 Jul 2026 10:54:28 +0200 Subject: fix(of): partial-proper memorials compose proper part + ferial (match USCCB) A memorial marked 'PROPER Gospel' (Guardian Angels, Mary Magdalene, Our Lady of Sorrows, Joseph the Worker, the Passion of John the Baptist, Sts Martha/Mary/ Lazarus) uses the FERIAL first reading + its proper gospel; one marked 'PROPER First Reading' (Barnabas) uses its proper first + the ferial gospel. Previously we imported catholic-resources' *suggested* first for the gospel-proper ones, which differs from what USCCB publishes. - readings.go: when the observed's inline Mass has only a proper gospel (or only a proper first), fill the missing reading/psalm from the day's ferial and sort into canonical order. A fully-proper feast is untouched. Factored out ofFerial(). - gen-of-sanctoral-readings.py: keep only the strictly-proper part per the CR source-note. Verified vs USCCB: Guardian Angels (2025-10-02) now = Nehemiah 8 / Ps 19 / Matt 18:1-5,10 exactly. Updates TestUniversalSanctoralReadings. --- scripts/gen-of-sanctoral-readings.py | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) (limited to 'scripts') diff --git a/scripts/gen-of-sanctoral-readings.py b/scripts/gen-of-sanctoral-readings.py index fd9c035..a37a0c1 100644 --- a/scripts/gen-of-sanctoral-readings.py +++ b/scripts/gen-of-sanctoral-readings.py @@ -85,18 +85,27 @@ def scrape(): continue mmdd = f"{MONS[m.group(1)]:02d}-{int(m.group(2)):02d}" rank, src = c[3], c[4] + su = src.upper() if rank.startswith("USA") or "Calif" in rank: continue # national additions not in the universal calendar - if not ("PROPER" in src.upper() or "Solemnity" in rank or "Feast" in rank): + if not ("PROPER" in su or "Solemnity" in rank or "Feast" in rank): continue # Common-based memorial -> keep the ferial - rows.append((mmdd, c[2], "vigil" in c[2].lower(), - {"first": clean_cite(c[5]), "psalm": clean_cite(c[6]), - "second": clean_cite(c[7]), "gospel": clean_cite(c[9])})) + parts = {"first": clean_cite(c[5]), "psalm": clean_cite(c[6]), + "second": clean_cite(c[7]), "gospel": clean_cite(c[9])} + # PARTIAL propers: the source-note marks which part is strictly proper; the + # OTHER reading is the ferial (the resolver fills it at runtime). A memorial + # with a "PROPER Gospel" keeps ONLY the gospel (Guardian Angels = ferial + # first + Matt 18); a "PROPER First Reading" keeps only the first (Barnabas). + if "PROPER" in su and "GOSPEL" in su and "FIRST" not in su: + parts = {"first": "", "psalm": "", "second": "", "gospel": parts["gospel"]} + elif "PROPER" in su and "FIRST" in su and "GOSPEL" not in su: + parts = {"first": parts["first"], "psalm": parts["psalm"], "second": "", "gospel": ""} + rows.append((mmdd, c[2], "vigil" in c[2].lower(), parts)) # one Mass per date: prefer the day Mass over a vigil; later row breaks ties best = {} for mmdd, name, isvig, parts in rows: - if not (parts["first"] and parts["gospel"]): - continue # need at least first + gospel + if not (parts["first"] or parts["gospel"]): + continue # need at least the proper part cur = best.get(mmdd) if cur is None or (cur[0] and not isvig): # replace a vigil with a day Mass best[mmdd] = (isvig, name, parts) -- cgit v1.3