From e30c1cd1d518d0af3f24fee7cf522537f846e8dd Mon Sep 17 00:00:00 2001 From: Derek Gulbranson Date: Sun, 9 Aug 2026 14:59:37 -0700 Subject: [PATCH] Open the 2.2 cycle's version: 2.2.0dev The tree said 2.1.0 for the whole cycle, which had two costs. docs/conf.py reads __version__ directly and Read the Docs installs the default branch, so "latest" rendered 2.1.0 -- the release we shipped, not the one we are building. That is what prompted this. The second is the differential harness. Its version tell exists so a worker that silently resolved to the checkout cannot pass as the baseline, and with the tree and the 2.1.0 baseline wheel BOTH reporting 2.1.0 only the __file__ path told them apart -- the weak state test_tell_rejects_a_module_loaded_from_the_checkout documents in its own docstring, and the condition the worker_v1.py invocation trap exploited. A bare run now reads: tree: nameparser 2.2.0dev (.../nameparser/__init__.py) baseline: nameparser 2.1.0 (.../uv/environments-v2/...) Both halves discriminate again. PRE_RELEASE = 'dev' rather than a bare bump, because master must not claim to BE a release that does not exist. It normalizes to 2.2.0.dev0, which sorts above 2.1.0 and below 2.2.0, so an install from git can never masquerade as the release it precedes. The cost is on the tuple: VERSION is numeric by design, so it cannot carry the marker and `VERSION >= (2, 2, 0)` is already true here. It is public and its docstring invites that comparison, so the constant now says to use __version__ where the distinction matters. CITATION.cff deliberately stays at 2.1.0. It names the last citable released artifact, so it is the one version string that does not track the tree, and it lags on purpose until the next release. Nothing checks that -- no test, no CI -- so the checklist now says it outright rather than implying the two are kept equal. Release step 2 becomes "clear PRE_RELEASE" instead of "bump VERSION", and a new step 9 opens the next cycle's version alongside step 8's ledger. Both are cycle-open work; doing them together is what stops the tree and the docs drifting apart again. --- AGENTS.md | 24 ++++++++++++++++++++++-- nameparser/_version.py | 14 ++++++++++++-- 2 files changed, 34 insertions(+), 4 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 9df9b0b5..d49d4381 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -72,8 +72,15 @@ uv run sphinx-build -b html docs dist/docs # code with the pipe's, so a failing run reads as a passing one. The # classified summary it prints is the source for the release notes' behavior # claims, including the count of changed names that are Latin-only. -# 2. Bump VERSION in nameparser/_version.py (and the `version:` field in CITATION.cff to match) -# For a pre-release, set PRE_RELEASE = 'rc1' (etc.) — __version__ joins it without a dot ('2.0.0rc1'); '' means final +# 2. Clear PRE_RELEASE in nameparser/_version.py — it carries 'dev' through the +# cycle (see step 9), so releasing is setting it to ''. VERSION should already +# be the version you are shipping; bump it here only if step 9 was skipped. +# For an RC, set PRE_RELEASE = 'rc1' (etc.) instead — __version__ joins it +# without a dot ('2.0.0rc1'). +# Also set the `version:` field in CITATION.cff to this release. It is the ONE +# version string that does NOT track the tree: it names the last citable +# released artifact, so it lags on purpose for the whole cycle and catches up +# here. Nothing checks this — no test, no CI — so it is on you. # 3. Stamp "Unreleased" → "X.Y.Z - Month DD, YYYY" in docs/release_log.rst # 4. git commit + git tag -a vX.Y.Z -m "Release X.Y.Z" # 5. git push origin master && git push origin vX.Y.Z ← tag must be pushed separately before gh release create @@ -112,6 +119,19 @@ uv run sphinx-build -b html docs dist/docs # vocabulary (maiden markers, ambiguous acronyms). An alternation # matching no key fails as undeclared -- add it, or record it in # _NOT_A_VOCABULARY_COPY if it copies nothing. +# 9. Open the next cycle's VERSION: bump VERSION in nameparser/_version.py to +# the minor now being worked, and set PRE_RELEASE = 'dev'. The tree then says +# what it is building rather than what it last shipped -- docs/conf.py reads +# __version__ directly, so Read the Docs' "latest" is otherwise stuck on the +# previous release for the whole cycle. +# It also restores the differential harness's version tell: with the tree and +# the baseline wheel both reporting the same release, only the __file__ path +# distinguishes them, which is the weak state test_tell_rejects_a_module_ +# loaded_from_the_checkout documents. A dev tree differs on both halves. +# 'dev' normalizes to X.Y.0.dev0 -- above the last release, below the one it +# precedes -- so an install from master can never masquerade as the release. +# Leave CITATION.cff alone: it names the last RELEASED version and is meant +# to lag until step 2 of the next release. ``` Enable debug logging to see the parser's internal decisions: diff --git a/nameparser/_version.py b/nameparser/_version.py index 840df8a4..8ef1eef7 100644 --- a/nameparser/_version.py +++ b/nameparser/_version.py @@ -1,9 +1,19 @@ #: Release version parts (major, minor, micro). VERSION stays a pure #: numeric tuple so `nameparser.VERSION >= (2, 0, 0)` keeps working; the #: pre-release segment lives separately. -VERSION = (2, 1, 0) +#: +#: Bumped when a cycle OPENS, not when it ships, so the tree says what +#: it is building. Note the cost of the tuple being purely numeric: it +#: cannot carry the dev marker, so `VERSION >= (2, 2, 0)` is already +#: true here while 2.2.0 is unreleased. Compare `__version__` instead +#: where that distinction matters. +VERSION = (2, 2, 0) #: PEP 440 pre-release/dev segment appended to the numeric version, or #: "" for a final release. Joined WITHOUT a dot ("2.0.0rc1", not #: "2.0.0.rc1"); setuptools reads __version__ as the package version. -PRE_RELEASE = "" +#: +#: "dev" through the cycle, cleared at release. It normalizes to +#: 2.2.0.dev0, which sorts above 2.1.0 and BELOW 2.2.0, so an install +#: from master can never masquerade as the release it precedes. +PRE_RELEASE = "dev" __version__ = ".".join(map(str, VERSION)) + PRE_RELEASE