chore(release): 1.0.0b1 — the v1 target, staged as a beta
All seven v1 capabilities are landed (ROADMAP's v1 target is met), so this is the first release of the 1.x train. Staged as a beta rather than cut final on the operator's call: per the canonical policy `-beta.N` means feature-complete, external testing, no new features, focus is on bugs — which is exactly this state, with a cross-frontier bug-hunt panel outstanding on U7's diff. The repo learned this sequencing the hard way once: v0.2.0 was tagged and announced while a contract panel was in flight, the panel found three defects in the code just released, and v0.2.1 shipped within the hour. A beta is the designed answer to that, not a workaround for it. ALSO FIXES A SECOND COPY OF THE VERSION, found while cutting this one. `booth.__version__` was the literal `0.1.0` and had been wrong through six releases. It is now read from pyproject.toml — deliberately NOT from importlib.metadata, which describes a different artifact: this repo has no build step and no install step (booth.service runs uvicorn with WorkingDirectory set to the tree), and the venv was carrying a vestigial booth-0.3.0.dist-info with no package directory behind it. Installed metadata therefore reported 0.3.0 for a tree at 1.0.0b1 — confidently wrong and varying by environment, which is worse than a literal that at least fails the same way everywhere. booth/__init__.py is also, it turns out, effectively stdlib-only: scripts/booth imports booth.links / booth.marks / booth.manifest under the system python3 with no venv, and every one of those executes the package root first. Nothing asserted it. test_stdlib_only now covers __init__, and the no-venv import path is verified under python3.11 reporting 1.0.0b1. 642 tests green.
This commit is contained in:
+6
-3
@@ -1,9 +1,12 @@
|
||||
# The Booth — roadmap
|
||||
|
||||
Design: [`docs/design/information-architecture.md`](docs/design/information-architecture.md).
|
||||
Current version: `0.6.1` (**U1 through U7 landed — every v1 capability is in**;
|
||||
extracted from eshpfi 2026-09-21). **The 1.0 cut is now a decision, not a
|
||||
dependency**, and it is the operator's: a major bump needs his approval.
|
||||
Current version: `1.0.0b1` (**U1 through U7 landed — every v1 capability is
|
||||
in**; extracted from eshpfi 2026-09-21). **The v1 target is MET and staged as a
|
||||
beta** (operator, 2026-09-22): feature-complete, external testing, no new
|
||||
features — the remaining work is bugs. `1.0.0` final is cut when the beta
|
||||
survives; per the canonical policy an rc would be cut from the same commit,
|
||||
but a beta may still take fixes.
|
||||
|
||||
## v1 target
|
||||
|
||||
|
||||
+41
-2
@@ -1,3 +1,42 @@
|
||||
"""The Booth — ephemeral media drop board. See booth.app for the server."""
|
||||
"""The Booth — ephemeral media drop board. See booth.app for the server.
|
||||
|
||||
__version__ = "0.1.0"
|
||||
⚠ THIS FILE IS EFFECTIVELY STDLIB-ONLY and nothing used to say so. `scripts/booth`
|
||||
imports `booth.links` / `booth.marks` / `booth.manifest` under the SYSTEM python3
|
||||
with no venv, and importing any of them executes this module first — so a single
|
||||
third-party import here breaks `booth ask` on every fleet host exactly as one in
|
||||
those three would. `test_stdlib_only` now covers `__init__` for that reason.
|
||||
"""
|
||||
|
||||
import tomllib
|
||||
from pathlib import Path
|
||||
|
||||
_PYPROJECT = Path(__file__).resolve().parent.parent / "pyproject.toml"
|
||||
|
||||
|
||||
def _declared_version() -> str:
|
||||
"""The version of the code actually running, read from `pyproject.toml`.
|
||||
|
||||
⚠ NOT `importlib.metadata`, and the reason is this repo's own shape: there
|
||||
is no build step and no install step — `booth.service` runs uvicorn with
|
||||
WorkingDirectory set to the repo, so the running code IS this tree.
|
||||
Installed metadata describes a DIFFERENT artifact and was found saying
|
||||
`0.3.0` (a vestigial dist-info, three releases stale, with no package
|
||||
directory behind it) while the tree was at `1.0.0b1`. A confidently wrong
|
||||
number that varies by environment is worse than the hardcoded `0.1.0` this
|
||||
replaced, which at least failed the same way everywhere.
|
||||
|
||||
Falls back to installed metadata for the case this repo does not have but a
|
||||
consumer might: packaged as a wheel, where pyproject does not ship.
|
||||
"""
|
||||
try:
|
||||
return tomllib.loads(_PYPROJECT.read_text())["project"]["version"]
|
||||
except (OSError, KeyError, tomllib.TOMLDecodeError):
|
||||
try:
|
||||
from importlib.metadata import version
|
||||
|
||||
return version("booth")
|
||||
except Exception:
|
||||
return "0.0.0+unknown"
|
||||
|
||||
|
||||
__version__ = _declared_version()
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
[project]
|
||||
name = "booth"
|
||||
version = "0.6.1"
|
||||
version = "1.0.0b1"
|
||||
description = "The Booth — a dead-simple standing web server that scans a data dir of drop-folders and renders each as an ephemeral media 'booth' (image/webm/audio auto-gallery, or a folder's own index.html verbatim). Also accepts browser/curl uploads for pickup under a human-readable id. 24h TTL, then the folder is wiped. Fleet tool for CC sessions to surface A/B and smoke results to the operator."
|
||||
requires-python = ">=3.11"
|
||||
dependencies = [
|
||||
|
||||
+31
-1
@@ -7,6 +7,8 @@ See docs/contracts/u2_marks.contract.md.
|
||||
"""
|
||||
import ast
|
||||
import json
|
||||
import re
|
||||
import tomllib
|
||||
import pathlib
|
||||
import sys
|
||||
|
||||
@@ -276,7 +278,7 @@ def test_as_dict_round_trips_through_json(tmp_path):
|
||||
# ---- the stdlib-only invariant (INV-5) --------------------------------------
|
||||
|
||||
|
||||
@pytest.mark.parametrize("module", ["marks", "asks", "links", "manifest", "benches"])
|
||||
@pytest.mark.parametrize("module", ["marks", "asks", "links", "manifest", "benches", "__init__"])
|
||||
def test_stdlib_only(module):
|
||||
"""INV-5. scripts/booth imports these under the system python3 with NO venv,
|
||||
through a `python3 -c` heredoc that no AST extractor can see — so nothing
|
||||
@@ -1428,3 +1430,31 @@ def test_a_healthy_multi_answer_still_hydrates(tmp_path):
|
||||
by = {m.id: m for m in marks_for(tmp_path)}
|
||||
assert by["multi"].error is None, by["multi"].error
|
||||
assert by["single"].error is None, by["single"].error
|
||||
|
||||
|
||||
def test_the_package_version_carries_no_literal_of_its_own():
|
||||
"""`booth.__version__` said `0.1.0` through six releases while pyproject
|
||||
said `0.6.1` — a second copy of one fact, drifting silently, found only
|
||||
while cutting 1.0.
|
||||
|
||||
THE ASSERTION IS THE ABSENCE OF A LITERAL, not agreement with pyproject:
|
||||
`__version__` is now READ from pyproject, so comparing the two would be
|
||||
circular and would prove only that the read works. The defeating change is
|
||||
hardcoding a number back into this module, and that is what this catches.
|
||||
"""
|
||||
src = (pathlib.Path(__file__).parent.parent / "booth" / "__init__.py").read_text()
|
||||
literals = re.findall(r'__version__\s*=\s*["\']([^"\']+)["\']', src)
|
||||
assert not literals, f"booth/__init__.py hardcodes a version again: {literals}"
|
||||
|
||||
|
||||
def test_the_package_version_is_the_one_the_tree_declares():
|
||||
"""And it resolves, from the tree, to what pyproject says — NOT to whatever
|
||||
a stale dist-info in some venv happens to record. Found saying `0.3.0` from
|
||||
installed metadata while the tree was at `1.0.0b1`."""
|
||||
import booth
|
||||
|
||||
declared = tomllib.loads(
|
||||
(pathlib.Path(__file__).parent.parent / "pyproject.toml").read_text()
|
||||
)["project"]["version"]
|
||||
assert booth.__version__ == declared
|
||||
assert booth.__version__ != "0.0.0+unknown", "the pyproject read fell through"
|
||||
|
||||
Reference in New Issue
Block a user