mirror of
https://github.com/kuhyx/signal-bot.git
synced 2026-11-11 12:37:32 +01:00
"Wersja 0.1.7 «Callistus I»" told nobody whether Callistus was the fifteenth pope or the hundredth, and the changelog was the one place the ladder is actually read. pope_line() derives both facts from popes.json -- the ordinal, and the `reign` string exactly as the table spells it, so the one reigning pope keeps his single year instead of being padded into a range he never had. It appears in all four places a version is named: the group announcement (header and every block of a backlog), each section of DOCS-changelog.md, /healthz, and the !papiez caption, which now describes the release's pope in the same sentence it uses for every other one. The changelog's copy is checked rather than trusted, like the heading name already was: a test walks the raw file and compares each line against popes.json, so a hand-edited ordinal fails here instead of in a group. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017w1HZ3cZ7neL3rFdQ6VMBA
108 lines
3.3 KiB
Python
108 lines
3.3 KiB
Python
# Copyright (c) 2026 Krzysztof Rudnicki. MIT licence.
|
|
"""DOCS-changelog.md is the only copy, so the parser has to earn that."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import re
|
|
from pathlib import Path
|
|
|
|
from signal_bot.changelog import Release, load, parse, since
|
|
from signal_bot.versioning import (
|
|
__version__,
|
|
latin_name,
|
|
ordinal_for,
|
|
pope_for,
|
|
pope_line,
|
|
)
|
|
|
|
HEADING = re.compile(r"^##\s+(\d+\.\d+\.\d+)\s*—")
|
|
|
|
DOCUMENT = """\
|
|
# Changelog
|
|
|
|
Prose between releases is ignored.
|
|
|
|
- a bullet before any heading belongs to no release
|
|
|
|
## 0.0.1 — Linus
|
|
|
|
- druga zmiana
|
|
- trzecia zmiana
|
|
|
|
Some more prose.
|
|
|
|
## 0.0.0 — Święty Piotr Apostoł
|
|
|
|
- pierwsza zmiana
|
|
"""
|
|
|
|
|
|
def test_parse_reads_headings_and_their_bullets() -> None:
|
|
releases = parse(DOCUMENT)
|
|
assert [r.version for r in releases] == ["0.0.0", "0.0.1"]
|
|
assert releases[0].pope == "Święty Piotr Apostoł"
|
|
assert releases[1].lines == ("druga zmiana", "trzecia zmiana")
|
|
|
|
|
|
def test_a_bullet_above_every_heading_belongs_to_nobody() -> None:
|
|
"""Otherwise the file's own format documentation becomes a changelog entry."""
|
|
assert all("belongs to no release" not in line for r in parse(DOCUMENT) for line in r.lines)
|
|
|
|
|
|
def test_parse_of_nothing_is_nothing() -> None:
|
|
assert parse("# Changelog\n\njust prose\n") == ()
|
|
|
|
|
|
def test_releases_come_back_oldest_first_whatever_the_file_order() -> None:
|
|
assert [r.ordinal for r in parse(DOCUMENT)] == [1, 2]
|
|
|
|
|
|
def test_since_returns_only_what_the_group_has_not_seen() -> None:
|
|
releases = parse(DOCUMENT)
|
|
assert [r.version for r in since(releases, "0.0.0")] == ["0.0.1"]
|
|
assert since(releases, "0.0.1") == ()
|
|
|
|
|
|
def test_since_an_unknown_version_announces_nothing() -> None:
|
|
"""A hand-edited or downgraded record must not dump the whole backlog."""
|
|
assert since(parse(DOCUMENT), "9.9.9") == ()
|
|
|
|
|
|
def test_a_missing_changelog_costs_an_announcement_not_the_process() -> None:
|
|
assert load(Path("/nonexistent/DOCS-changelog.md")) == ()
|
|
|
|
|
|
def test_the_real_changelog_covers_the_running_version() -> None:
|
|
"""A release with no entry would announce a version and then say nothing."""
|
|
versions = [release.version for release in load()]
|
|
assert __version__ in versions
|
|
|
|
|
|
def test_release_knows_its_ordinal() -> None:
|
|
assert Release("2.13.7", "Jan Paweł II", ()).ordinal == 264
|
|
|
|
|
|
def test_every_heading_name_matches_the_derived_latin_one() -> None:
|
|
"""The doc is checked, not trusted: a typo here fails here, not in a group."""
|
|
for release in load():
|
|
assert release.pope == latin_name(release.pope_entry), release.version
|
|
|
|
|
|
def test_every_section_carries_its_derived_papacy_line() -> None:
|
|
"""The ordinal and the reign are data, so the document may not disagree.
|
|
|
|
Read off the raw file rather than the parsed releases: the parser ignores
|
|
anything that is not a heading or a bullet, which is what makes this line
|
|
free to add -- and what would let it rot unnoticed without this test.
|
|
"""
|
|
lines = Path("DOCS-changelog.md").read_text(encoding="utf-8").splitlines()
|
|
checked = 0
|
|
for index, line in enumerate(lines):
|
|
heading = HEADING.match(line)
|
|
if heading is None:
|
|
continue
|
|
pope = pope_for(ordinal_for(heading.group(1)))
|
|
assert lines[index + 2] == pope_line(pope), heading.group(1)
|
|
checked += 1
|
|
assert checked == len(load())
|