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
21 changes: 19 additions & 2 deletions calendarium/tests/test_antiochian_readings.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import itertools
from datetime import date
from datetime import date, timedelta
from pathlib import Path

from django.test import TestCase
Expand Down Expand Up @@ -47,6 +47,20 @@ async def verse_set(reference):
displays = [r.pericope.sdisplay for r in await day.aget_readings()]
served = [(d, await verse_set(d)) for d in displays]

# The sources list the Lamentations (Matins of Holy Saturday, sung on
# Friday evening) under Holy Friday; orthocal carries them on Holy
# Saturday. Its Matins Epistle adds Gal 3:13-14, which the sources
# leave out, so containment is enough.
anticipated = []
if day.pdist == -2:
next_day = day_date + timedelta(days=1)
saturday = liturgics.Day(next_day.year, next_day.month, next_day.day,
tradition=Tradition.Greek)
await saturday.ainitialize()
anticipated = [await verse_set(r.pericope.sdisplay)
for r in await saturday.aget_readings()
if r.source.startswith('Matins')]

for _, title in group:
overlapping = '-'
try:
Expand All @@ -57,6 +71,8 @@ async def verse_set(reference):
status = 'unresolved'
elif any(found == wanted for _, found in served):
status = 'exact'
elif any(wanted <= found for found in anticipated):
status = 'exact'
elif overlaps := [d for d, found in served if found & wanted]:
status = 'boundary'
overlapping = ' | '.join(overlaps)
Expand Down Expand Up @@ -113,7 +129,8 @@ class TestExactGreekReadingBoundaries(TestCase):
(2, 9, 'Epistle', '1 John 2.18-29; 3.1-8'),
(2, 16, 'Epistle', '3 John 1.1-15'),
(3, 1, 'Epistle', 'Heb 11.24-26, 32-40'),
# 4/10, Holy Friday, is left alone; see load_exact_boundaries.py.
# Not 4/10: Holy Friday's listing is the Lamentations, which the app
# carries as Holy Saturday Matins; see load_exact_boundaries.py.
(4, 15, 'Epistle', 'Acts 2.22-38'),
(5, 7, 'Epistle', 'Acts 26.1, 12-20'),
(5, 8, 'Gospel', 'John 19.25-28, 21.24-25'),
Expand Down
5 changes: 5 additions & 0 deletions docs/greek-commons.md
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,11 @@ Of the 4:
- **Holy Friday**: `1 Cor 5:6-8` (Greek) vs. our existing Vespers Epistle
`1 Cor 1.18-2.2` (Slavic) — confirmed 2/2 years (2021, 2026). Added as a
`greek` override on the `Vespers`-desc Epistle slot (new Pericope).
**Reverted 2026-10-14**: this was a misreading. The sources list the
Lamentations (Matins of Holy Saturday, sung on Friday evening) under Friday;
`1 Cor 5:6-8` is that service's Epistle, which the app already carries on
Holy Saturday. Greek Vespers on Holy Friday reads `1 Cor 1:18-2:2` like
Slavic. See `docs/greek-lectionary.md`, "Accuracy, measured".
- **Holy Thursday's compound Gospel reading**: our version and
antiochian's differ by a few verses within an already-massive 6-part
compound citation (`Matt 26:2-20;...` vs `Matt 26:1-20;...`, etc.) —
Expand Down
44 changes: 26 additions & 18 deletions docs/greek-lectionary.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ investigation history, kept because it records *why* decisions were made and
which hypotheses are already dead; some of its early sections are superseded
and are marked as such.

Last measured 2026-10-14, by verse set against goarch.org: **6,626 of 6,696
Epistle and Gospel fields (99.0%) over 2018-2027**, and 670 of 672 in 2026.
Last measured 2026-10-14, by verse set against goarch.org: **6,636 of 6,696
Epistle and Gospel fields (99.1%) over 2018-2027**, and 671 of 672 in 2026.
An earlier "99.1%" compared only each citation's opening verse and is not
comparable; see "Accuracy, measured".

Expand Down Expand Up @@ -158,28 +158,36 @@ only if some app reading of the same kind covers exactly goarch.org's verses.

| year | Epistle/Gospel fields | exact |
|---|---|---|
| 2018 | 668 | 661 (99.0%) |
| 2019 | 668 | 659 (98.7%) |
| 2020 | 672 | 667 (99.3%) |
| 2021 | 668 | 661 (99.0%) |
| 2022 | 670 | 660 (98.5%) |
| 2023 | 670 | 659 (98.4%) |
| 2024 | 672 | 663 (98.7%) |
| 2025 | 668 | 665 (99.6%) |
| 2026 | 672 | 670 (99.7%) |
| 2027 | 668 | 661 (99.0%) |
| **all** | **6,696** | **6,626 (99.0%)** |
| 2018 | 668 | 662 (99.1%) |
| 2019 | 668 | 660 (98.8%) |
| 2020 | 672 | 668 (99.4%) |
| 2021 | 668 | 662 (99.1%) |
| 2022 | 670 | 661 (98.7%) |
| 2023 | 670 | 660 (98.5%) |
| 2024 | 672 | 664 (98.8%) |
| 2025 | 668 | 666 (99.7%) |
| 2026 | 672 | 671 (99.9%) |
| 2027 | 668 | 662 (99.1%) |
| **all** | **6,696** | **6,636 (99.1%)** |

Before the exact-boundary work (PR #252) the same measure gave 90.8%; after
it, 98.6%. Five more rows found with `--recurring` and corroborated by
antiochian.org brought it to 99.0%. Run the
antiochian.org brought it to 99.0%, and reading Holy Friday correctly (below)
to 99.1%.

**Holy Friday.** goarch.org lists `1 Corinthians 5:6-8` and `Matthew 27:62-66`
as Holy Friday's Epistle and Gospel. Those are the Lamentations readings --
Matins of Holy Saturday, sung on Friday evening -- which this app already
carries as Holy Saturday's Matins readings, exactly as oca.org does. Holy
Friday's own Vespers reads `1 Corinthians 1:18-2:2` and the composite Gospel in
the Greek tradition too (johnsanidopoulos.com's Holy Friday readings and Holy
Cross, Pittsburgh's service list both print them). The audit therefore also
accepts Holy Saturday's Matins readings on Holy Friday. A `greek` row added in
July from that Friday listing, putting `1 Cor 5:6-8` in the Vespers Epistle
slot, was removed. Run the
script with `--recurring` for the current list of differences; what remains is
mostly:

- **Holy Friday**, every year: both sources print `Matthew 27:62-66`, the
Lamentations Gospel (Matins of Holy Saturday, served on Friday evening), where
this slot carries the Vespers composite Gospel. Fixing it means modelling the
Lamentations as its own service, not swapping one Gospel for the other.
- **Apostles' feasts moved out of Holy or Bright Week** (`Luke 10:16-21` for
St Mark, `Acts 12:1-11` for St James, `Hebrews 13:7-16`): transfer logic,
not missing rows.
Expand Down
32 changes: 0 additions & 32 deletions fixtures/calendarium.json
Original file line number Diff line number Diff line change
Expand Up @@ -45865,21 +45865,6 @@
"tradition": "greek"
}
},
{
"model": "calendarium.reading",
"pk": 1794,
"fields": {
"month": 0,
"day": 0,
"pdist": -2,
"source": "Epistle",
"desc": "Vespers",
"pericope": 1012,
"ordering": 521,
"flag": 0,
"tradition": "greek"
}
},
{
"model": "calendarium.reading",
"pk": 1795,
Expand Down Expand Up @@ -63292,23 +63277,6 @@
"flag": 0
}
},
{
"model": "calendarium.pericope",
"pk": 1012,
"fields": {
"pericope": "308grk",
"book": "Apostol",
"display": "1 Corinthians 5.6-8",
"sdisplay": "1 Cor 5.6-8",
"desc": "Holy Friday Vespers (Greek)",
"preverse": "",
"prefix": "Brethren, your glorying",
"prefixb": "",
"verses": "1Cor_5006_5008",
"suffix": "",
"flag": 0
}
},
{
"model": "calendarium.pericope",
"pk": 1013,
Expand Down
19 changes: 17 additions & 2 deletions tools/greek/goa_verse_audit.py
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,16 @@ def verse_set(citation):
async def app_readings(date):
day = Day(date.year, date.month, date.day, tradition=Tradition.Greek)
await day.ainitialize()
return [(r.source, r.pericope.sdisplay) for r in await day.aget_readings()]
return day.pdist, [(r.source, r.pericope.sdisplay) for r in await day.aget_readings()]


# goarch.org lists the Lamentations -- Matins of Holy Saturday, sung on Friday
# evening -- as Holy Friday's Epistle and Gospel. This app keeps them where they
# belong liturgically, as Holy Saturday's Matins readings, so on Holy Friday
# those count too. goarch.org prints only 1 Cor 5:6-8 of the Matins Epistle,
# which also includes Gal 3:13-14, so containment is enough there.
HOLY_FRIDAY = -2
ANTICIPATED = {'Epistle': 'Matins Epistle', 'Gospel': 'Matins Gospel'}


async def audit(years):
Expand All @@ -142,7 +151,9 @@ async def audit(years):
continue
label, readings = value
date = datetime.date.fromisoformat(key)
ours = await app_readings(date)
pdist, ours = await app_readings(date)
if pdist == HOLY_FRIDAY:
_, saturday = await app_readings(date + datetime.timedelta(days=1))
for kind, citation in readings:
if kind not in SOURCES:
continue
Expand All @@ -153,6 +164,10 @@ async def audit(years):
result = 'unparsed'
elif want in got:
result = 'exact'
elif pdist == HOLY_FRIDAY and any(
want <= (verse_set(s) or frozenset())
for source, s in saturday if source == ANTICIPATED[SOURCES[kind]]):
result = 'exact'
elif any(g and g & want for g in got):
result = 'boundary'
else:
Expand Down
7 changes: 3 additions & 4 deletions tools/greek/load_exact_boundaries.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,9 @@
'goarch.org 2024, 2026; antiochian.org 2024, 2026'),
# Holy Friday is deliberately absent. Both sources print Matthew 27:62-66,
# but that is the Gospel of the Lamentations (Matins of Holy Saturday,
# served on Friday evening), not of Vespers, whose composite Gospel this
# slot carries. Replacing it would drop the Vespers Gospel and leave a
# Lamentations reading under a Vespers label; it needs the Lamentations
# modelled as its own service instead.
# sung on Friday evening), which the app already carries as Holy
# Saturday's Matins Gospel. This slot is Holy Friday Vespers, whose
# composite Gospel is the same in both traditions.
('Epistle', 3, 'Acts 2.22-36', 'Acts 2:22-38',
'goarch.org 2024, 2026; antiochian.org 2026'),
('Epistle', (5, 7), 'Acts 26.1-5, 12-20', 'Acts 26:1, 12-20',
Expand Down
Loading