diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index f4331e1..681fb0e 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -41,6 +41,10 @@ jobs: TAG="$PUSHED_REF" fi + # The package version is derived from this tag by hatch-vcs + # at build time (see [tool.hatch.version] in pyproject.toml). + # We only need to validate the tag shape — there's no + # ``project.version`` field to cross-check anymore. case "$TAG" in renderers-v*) ;; *) @@ -49,21 +53,6 @@ jobs: ;; esac - VERSION="${TAG#renderers-v}" - FILE_VERSION=$(python - <<'PY' - import tomllib - from pathlib import Path - with Path('pyproject.toml').open('rb') as f: - data = tomllib.load(f) - print(data['project']['version']) - PY - ) - - if [ "$FILE_VERSION" != "$VERSION" ]; then - echo "Version mismatch: tag requests '$VERSION' but pyproject.toml defines '$FILE_VERSION'" >&2 - exit 1 - fi - echo "tag=$TAG" >> "$GITHUB_OUTPUT" - uses: astral-sh/setup-uv@v7 diff --git a/.gitignore b/.gitignore index 2f3dfb0..efbf202 100644 --- a/.gitignore +++ b/.gitignore @@ -14,6 +14,8 @@ __pycache__/ *.pyc *.pyo *.pyd +# generated by hatch-vcs at build time (see [tool.hatch.build.hooks.vcs]) +renderers/_version.py # tooling caches .pytest_cache/ diff --git a/pyproject.toml b/pyproject.toml index 3fc98c8..0b4a00c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,10 +1,14 @@ [build-system] -requires = ["hatchling"] +requires = ["hatchling", "hatch-vcs"] build-backend = "hatchling.build" [project] name = "renderers" -version = "0.1.7" +# Derived from git tags by hatch-vcs (see [tool.hatch.version] below). +# Untagged commits get PEP 440 dev versions like ``0.1.8.dev3+g4c877be4`` +# so any commit is uniquely installable; tagged commits get clean +# release versions like ``0.1.8``. +dynamic = ["version"] description = "Chat template renderers — deterministic message-to-token conversion for LLM training" readme = "README.md" requires-python = ">=3.10,<3.14" @@ -20,6 +24,25 @@ dependencies = [ "openai-harmony>=0.0.8", ] +[tool.hatch.version] +source = "vcs" +# Tags look like ``renderers-v0.1.8`` (prefix matches the publish.yml +# release contract); strip the prefix to get a PEP 440 version. The +# regex accepts any PEP 440-valid suffix after the prefix so we can +# tag pre-releases like ``renderers-v0.2.0rc1`` later if needed. +tag-pattern = '^renderers-v(?P.+)$' +# Used when building from a context without VCS metadata (e.g. an +# sdist consumed by a downstream that doesn't ship .git). Real +# builds from a checkout get the resolved version; this fallback +# only fires when the resolver has nothing to go on. +fallback-version = "0.0.0" + +[tool.hatch.build.hooks.vcs] +# Write the resolved version to a Python file so it can be inspected +# at runtime via ``renderers.__version__`` without re-parsing the +# wheel metadata. +version-file = "renderers/_version.py" + [tool.hatch.build.targets.wheel] packages = ["renderers"] diff --git a/renderers/__init__.py b/renderers/__init__.py index b28a485..24f076c 100644 --- a/renderers/__init__.py +++ b/renderers/__init__.py @@ -1,3 +1,11 @@ +try: + from renderers._version import __version__ +except ImportError: + # Source checkout without a built artifact (e.g. editable install + # before the first ``uv build`` populates ``_version.py``). Real + # installs always have it. + __version__ = "0+unknown" + from renderers.base import ( Content, ContentPart, @@ -73,6 +81,7 @@ "ToolCallFunction", "ToolSpec", "VideoPart", + "__version__", "build_training_sample", "build_trajectory_step", "create_renderer",