From d28f27ff69d82ff33a3e6c7e56689ea611e36b71 Mon Sep 17 00:00:00 2001 From: Almar Klein Date: Thu, 17 Oct 2024 13:25:20 +0200 Subject: [PATCH] Add extra version info on dev installs (#623) * Add extra version info on dev installs * Allow build tool to find version --------- Co-authored-by: Korijn van Golen --- .github/workflows/cd.yml | 1 + .github/workflows/ci.yml | 6 ++- pyproject.toml | 2 +- wgpu/__init__.py | 6 +-- wgpu/_version.py | 113 +++++++++++++++++++++++++++++++++++++++ 5 files changed, 120 insertions(+), 8 deletions(-) create mode 100644 wgpu/_version.py diff --git a/.github/workflows/cd.yml b/.github/workflows/cd.yml index 1bb39c63..d92ad2cd 100644 --- a/.github/workflows/cd.yml +++ b/.github/workflows/cd.yml @@ -92,6 +92,7 @@ jobs: # Install sdist, but no test, because there is no wgpu-native lib now. filename=$(ls dist/*.tar.gz) pip install $filename + python -c "import wgpu; print(wgpu.__version__)" pip uninstall -y wgpu git reset --hard HEAD diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0c496358..2970ac47 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -143,12 +143,13 @@ jobs: - name: Install dependencies run: | python -m pip install --upgrade pip - pip install -U -e . + pip install -U . pip install -U pytest numpy psutil pyinstaller glfw - name: Test PyInstaller run: | + pushd $HOME pyinstaller --version - pytest -v wgpu/__pyinstaller + pytest -v --pyargs wgpu.__pyinstaller test-builds: name: ${{ matrix.name }} @@ -194,6 +195,7 @@ jobs: run: | python -m pip install --upgrade pip pip install -U -e .[tests] + python -c "import wgpu; print(wgpu.__version__)" - name: Unit tests run: | pytest -v tests diff --git a/pyproject.toml b/pyproject.toml index d672a910..18bc4fe9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -47,7 +47,7 @@ requires = ["requests", "hatchling"] build-backend = "hatchling.build" [tool.hatch.version] -path = "wgpu/__init__.py" +path = "wgpu/_version.py" [tool.hatch.build.targets.sdist] packages = ["wgpu"] diff --git a/wgpu/__init__.py b/wgpu/__init__.py index d9783205..df4857c1 100644 --- a/wgpu/__init__.py +++ b/wgpu/__init__.py @@ -5,6 +5,7 @@ # ruff: noqa: F401, F403 from ._coreutils import logger +from ._version import __version__, version_info from ._diagnostics import diagnostics, DiagnosticsBase from .flags import * from .enums import * @@ -14,10 +15,5 @@ from . import backends from . import resources - -__version__ = "0.18.1" -version_info = tuple(map(int, __version__.split("."))) - - # The API entrypoint, from wgpu.classes - gets replaced when a backend loads. gpu = GPU() # noqa: F405 diff --git a/wgpu/_version.py b/wgpu/_version.py new file mode 100644 index 00000000..c2421af4 --- /dev/null +++ b/wgpu/_version.py @@ -0,0 +1,113 @@ +""" +Versioning: we use a hard-coded version number, because it's simple and always +works. For dev installs we add extra version info from Git. +""" + +import logging +import subprocess +from pathlib import Path + + +# This is the reference version number, to be bumped before each release. +# The build system detects this definition when building a distribution. +__version__ = "0.18.1" + +# Allow using nearly the same code in different projects +project_name = "wgpu" + + +logger = logging.getLogger(project_name.lower()) + +# Get whether this is a repo. If so, repo_dir is the path, otherwise repo_dir is None. +repo_dir = Path(__file__).parents[1] +repo_dir = repo_dir if repo_dir.joinpath(".git").is_dir() else None + + +def get_version(): + """Get the version string.""" + if repo_dir: + return get_extended_version() + else: + return __version__ + + +def get_extended_version(): + """Get an extended version string with information from git.""" + + release, post, labels = get_version_info_from_git() + + # Sample first 3 parts of __version__ + base_release = ".".join(__version__.split(".")[:3]) + + # Check release + if not release: + release = base_release + elif release != base_release: + logger.warning( + f"{project_name} version from git ({release}) and __version__ ({base_release}) don't match." + ) + + # Build the total version + version = release + if post and post != "0": + version += f".post{post}" + if labels: + version += "+" + ".".join(labels) + + return version + + +def get_version_info_from_git(): + """Get (release, post, labels) from Git. + + With `release` the version number from the latest tag, `post` the + number of commits since that tag, and `labels` a tuple with the + git-hash and optionally a dirty flag. + """ + + # Call out to Git + command = [ + "git", + "describe", + "--long", + "--always", + "--tags", + "--dirty", + "--first-parent", + ] + try: + p = subprocess.run(command, cwd=repo_dir, capture_output=True) + except Exception as e: + logger.warning(f"Could not get {project_name} version: {e}") + p = None + + # Parse the result into parts + if p is None: + parts = (None, None, "unknown") + else: + output = p.stdout.decode(errors="ignore") + if p.returncode: + stderr = p.stderr.decode(errors="ignore") + logger.warning( + f"Could not get {project_name} version.\n\nstdout: " + + output + + "\n\nstderr: " + + stderr + ) + parts = (None, None, "unknown") + else: + parts = output.strip().lstrip("v").split("-") + if len(parts) <= 2: + # No tags (and thus also no post). Only git hash and maybe 'dirty' + parts = (None, None, *parts) + + # Return unpacked parts + release, post, *labels = parts + return release, post, labels + + +__version__ = get_version() + +version_info = tuple( + int(i) if i.isnumeric() else i for i in __version__.split("+")[0].split(".") +)