a jurisdiction is not just a key any more

describe() in Python was answering a different fast than the same date on the
command line: xerophagy on a Wednesday of the Great Fast read as wine_oil. Not a
cosmetic difference in a tool whose whole job is to say what may be eaten.

The cause is that Jurisdiction grew a tradition and a discipline, and config
carries all three — main.rs reads the saved jurisdiction, then the saved
tradition, then whether the Typikon's full discipline was asked for, and builds
an overridden Jurisdiction from the lot. The bindings resolved the key and
stopped, so everything the other two decide was silently dropped.

They now take the same three steps, and tradition= and typikon= are arguments, so
the library can say what the command line can. Pascha does not take them: it
follows the paschalion alone and neither can move it.

The overrides are interned rather than leaked per call. main.rs leaks one per run
and exits; a library gets called in a loop, and a leak per call adds up. The
combinations are bounded by jurisdictions x traditions x discipline, so the map
cannot grow past that.

The parity test spread widens to seven dates across both fasts and both
calendars, and clippy now runs under the feature as well — the binding code only
exists there, so a bare clippy run had never looked at it.
This commit is contained in:
funkpower
2026-09-18 12:33:56 -04:00
parent 78c69e5979
commit 3e3b585b2a
4 changed files with 125 additions and 32 deletions
+26 -4
View File
@@ -27,10 +27,13 @@ BINARY = Path(__file__).resolve().parents[2] / "target" / "release" / "typikon"
# Pascha, Nativity, Theophany and an ordinary weekday: the movable cycle, the
# fixed calendar, the julian offset and the plain case.
DATES = [
datetime.date(2026, 4, 12),
datetime.date(2026, 12, 25),
datetime.date(2027, 1, 7),
datetime.date(2026, 3, 18),
datetime.date(2026, 4, 12), # Pascha
datetime.date(2026, 12, 25), # Nativity
datetime.date(2027, 1, 7), # Theophany on the old calendar
datetime.date(2026, 3, 18), # a Wednesday of the Great Fast
datetime.date(2026, 11, 20), # the Nativity Fast
datetime.date(2026, 8, 6), # Transfiguration, fish permitted
datetime.date(2026, 6, 10), # an ordinary weekday
]
@@ -71,6 +74,25 @@ def test_week_rejects_nonsense() -> None:
typikon.week(datetime.date(2026, 4, 10), 0)
def test_tradition_and_typikon_reach_the_answer() -> None:
# A Jurisdiction is not just a key: it carries a tradition and a discipline,
# and config supplies all three. The bindings resolved only the key once, and
# reported wine_oil where the CLI said xerophagy on a Lenten Wednesday — the
# tool's whole job, answered differently in the two front ends.
lent = datetime.date(2026, 3, 18)
assert typikon.describe(lent, tradition="greek").tradition == "greek"
assert typikon.describe(lent, tradition="slavic").tradition == "slavic"
# The Typikon's full discipline can only tighten a relaxed rule, never relax it.
strict = typikon.describe(lent, jurisdiction="ruthenian", typikon=True)
normal = typikon.describe(lent, jurisdiction="ruthenian", typikon=False)
assert (strict.fast, strict.fast_label) != (normal.fast, normal.fast_label)
def test_unknown_tradition_raises() -> None:
with pytest.raises(ValueError, match="unknown tradition"):
typikon.describe(datetime.date(2026, 4, 12), tradition="martian")
def test_unknown_jurisdiction_raises() -> None:
with pytest.raises(ValueError, match="unknown jurisdiction"):
typikon.describe(datetime.date(2026, 4, 12), jurisdiction="narnia")