cctally 1.8.1 → 1.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,44 @@
1
+ """Public helper: read the latest stamped release header from CHANGELOG.md.
2
+
3
+ Read-only. Pure with respect to inputs (CHANGELOG.md contents). The
4
+ historical name ``_release_read_latest_release_version`` carried a
5
+ ``_release_`` prefix because the helper originated with the release-
6
+ automation work, but the function is not release-machinery: doctor,
7
+ the share kernel, and ``cctally --version`` all read it. Lives in a
8
+ public sibling so the maintainer-only release tooling can move to a
9
+ private artifact without dragging the version reader with it.
10
+ """
11
+
12
+ from __future__ import annotations
13
+
14
+ import sys
15
+
16
+
17
+ def _cctally():
18
+ """Call-time accessor for the ``cctally`` module (project memory
19
+ ``_cctally() accessor pattern``). Avoids module-top ``import cctally``
20
+ so monkeypatch-sensitive globals (``CHANGELOG_PATH`` and
21
+ ``RELEASE_HEADER_RE``) stay reachable for tests."""
22
+ return sys.modules["cctally"]
23
+
24
+
25
+ def _read_latest_changelog_version() -> tuple[str, str] | None:
26
+ """Read latest ``## [X.Y.Z] - YYYY-MM-DD`` header from
27
+ ``CHANGELOG_PATH``. Returns ``(version, date)`` or ``None`` if the
28
+ file is missing or has no stamped release header.
29
+
30
+ Body is byte-equivalent to the original
31
+ ``_release_read_latest_release_version`` definition in ``bin/cctally``
32
+ (the rename is the only intentional change); the regex
33
+ ``RELEASE_HEADER_RE`` is read from the ``cctally`` module so any
34
+ in-process update to the pattern remains the single source of truth.
35
+ """
36
+ c = _cctally()
37
+ try:
38
+ text = c.CHANGELOG_PATH.read_text(encoding="utf-8")
39
+ except FileNotFoundError:
40
+ return None
41
+ m = c.RELEASE_HEADER_RE.search(text)
42
+ if not m:
43
+ return None
44
+ return (m.group(1), m.group(2))
@@ -76,7 +76,7 @@ def _release_compute_next_version(
76
76
  return _release_format_semver(nxt_maj, nxt_min, nxt_pat, prerelease_id, 1)
77
77
 
78
78
  if is_prerelease:
79
- raise ValueError("current version is a prerelease; run 'cctally release finalize' first or use --bump in a prerelease bump")
79
+ raise ValueError("current version is a prerelease; run 'cctally-release finalize' first or use --bump in a prerelease bump")
80
80
 
81
81
  if kind == "patch":
82
82
  return _release_format_semver(cur_maj, cur_min, cur_pat + 1)
@@ -289,8 +289,10 @@ def _release_version() -> str:
289
289
  at `bin/cctally:86`). Falls back to `"dev"` when CHANGELOG is unreadable
290
290
  or has no stamped release entry yet (pre-release dev builds).
291
291
 
292
- Parallel to `_release_read_latest_release_version` in `bin/cctally` —
293
- intentionally duplicated so the template module stays free of any
292
+ Parallel to `_lib_changelog._read_latest_changelog_version`
293
+ (re-exported on `bin/cctally` under the historical
294
+ `_release_read_latest_release_version` name) — intentionally
295
+ duplicated so the template module stays free of any
294
296
  `bin/cctally` import. If CHANGELOG header format changes, update both.
295
297
  """
296
298
  from pathlib import Path