"""The CHANGELOG.md section of one version, the text of its release.""" from __future__ import annotations import re #: A version heading in CHANGELOG.md: "## [1.2.3] - 2026-10-01". _HEADING = re.compile(r"^## \[(?P[^\]]+)\]", re.MULTILINE) def changelog_section(text: str, version: str) -> str | None: """The body under ``## [version]`` up to the next version heading, or None.""" version = version.removeprefix("v") headings = list(_HEADING.finditer(text)) for i, heading in enumerate(headings): if heading.group("version") != version: continue line_end = text.find("\n", heading.end()) start = len(text) if line_end == -1 else line_end + 1 end = headings[i + 1].start() if i + 1 < len(headings) else len(text) body = text[start:end].strip() # Sections are sometimes closed by a horizontal rule; it is layout, not content. body = re.sub(r"\n*^---\s*\Z", "", body, flags=re.MULTILINE).strip() return body or None return None