Skip to content

Commit

Permalink
Add miniver to simplify development branch descriptions
Browse files Browse the repository at this point in the history
```
In [1]: import pygfx

In [2]: pygfx.__version__
'0.1.18.post29+g9342016'

In [3]: from packaging.version import Version

In [4]: Version('0.1.18.post29+g9342016') > Version('0.1.18')
True

In [5]: assert Version('0.1.18.post29+g9342016') > Version('0.1.18')

In [6]: assert Version('0.1.18.post29+g9342016') < Version('0.1.19')
```

So I use this in my project and the github action that I use to upload
the package to pypi will make the static version correctly

see: https://github.com/ramonaoptics/python-teensytoany
  • Loading branch information
hmaarrfk committed Apr 13, 2024
1 parent 9342016 commit 20d06df
Show file tree
Hide file tree
Showing 7 changed files with 249 additions and 4 deletions.
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pygfx/_static_version.py export-subst
21 changes: 21 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ jobs:
fail-fast: false
steps:
- uses: actions/checkout@v3
with:
# https://github.com/actions/checkout#fetch-all-history-for-all-tags-and-branches
fetch-depth: 0
- name: Set up Python 3.9
uses: actions/setup-python@v4
with:
Expand All @@ -42,6 +45,9 @@ jobs:
fail-fast: false
steps:
- uses: actions/checkout@v3
with:
# https://github.com/actions/checkout#fetch-all-history-for-all-tags-and-branches
fetch-depth: 0
- name: Set up Python 3.9
uses: actions/setup-python@v4
with:
Expand Down Expand Up @@ -80,6 +86,9 @@ jobs:
pyversion: '3.11'
steps:
- uses: actions/checkout@v3
with:
# https://github.com/actions/checkout#fetch-all-history-for-all-tags-and-branches
fetch-depth: 0
- name: Set up Python ${{ matrix.pyversion }}
uses: actions/setup-python@v4
with:
Expand All @@ -103,6 +112,9 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
# https://github.com/actions/checkout#fetch-all-history-for-all-tags-and-branches
fetch-depth: 0
- name: Set up Python 3.9
uses: actions/setup-python@v4
with:
Expand All @@ -122,6 +134,9 @@ jobs:
fail-fast: false
steps:
- uses: actions/checkout@v3
with:
# https://github.com/actions/checkout#fetch-all-history-for-all-tags-and-branches
fetch-depth: 0
- name: Set up Python 3.9
uses: actions/setup-python@v4
with:
Expand Down Expand Up @@ -155,6 +170,9 @@ jobs:
fail-fast: false
steps:
- uses: actions/checkout@v3
with:
# https://github.com/actions/checkout#fetch-all-history-for-all-tags-and-branches
fetch-depth: 0
- name: Set up Python 3.9
uses: actions/setup-python@v4
with:
Expand Down Expand Up @@ -194,6 +212,9 @@ jobs:
if: success() && startsWith(github.ref, 'refs/tags/v')
steps:
- uses: actions/checkout@v3
with:
# https://github.com/actions/checkout#fetch-all-history-for-all-tags-and-branches
fetch-depth: 0
- name: Set up Python 3.9
uses: actions/setup-python@v4
with:
Expand Down
3 changes: 3 additions & 0 deletions .github/workflows/screenshots.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ jobs:
runs-on: 'ubuntu-latest'
steps:
- uses: actions/checkout@v3
with:
# https://github.com/actions/checkout#fetch-all-history-for-all-tags-and-branches
fetch-depth: 0
- name: Set up Python 3.9
uses: actions/setup-python@v4
with:
Expand Down
5 changes: 3 additions & 2 deletions pygfx/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,9 @@

del pylinalg

__version__ = "0.1.18"
version_info = tuple(map(int, __version__.split(".")))
from ._version import __version__

version_info = tuple(map(int, __version__.split(".")[:3]))

__wgpu_version_range__ = "0.14.1", "0.16.0"
__pylinalg_version_range__ = "0.4.1", "0.5.0"
Expand Down
12 changes: 12 additions & 0 deletions pygfx/_static_version.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# -*- coding: utf-8 -*-
# This file is part of 'miniver': https://github.com/jbweston/miniver
#
# This file will be overwritten by setup.py when a source or binary
# distribution is made. The magic value "__use_git__" is interpreted by
# _version.py.

version = "__use_git__"

# These values are only set if the distribution was created with 'git archive'
refnames = "$Format:%D$"
git_hash = "$Format:%h$"
191 changes: 191 additions & 0 deletions pygfx/_version.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,191 @@
# -*- coding: utf-8 -*-
# This file is part of 'miniver': https://github.com/jbweston/miniver
#
from collections import namedtuple
import os

Version = namedtuple("Version", ("release", "post", "labels"))

# No public API
__all__ = []

package_root = os.path.dirname(os.path.realpath(__file__))
package_name = os.path.basename(package_root)

STATIC_VERSION_FILE = "_static_version.py"


def get_version(version_file=STATIC_VERSION_FILE):
version_info = get_static_version_info(version_file)
version = version_info["version"]
if version == "__use_git__":
version = get_version_from_git()
if not version:
version = get_version_from_git_archive(version_info)
if not version:
version = Version("noget", None, None)
return pep440_format(version)
else:
return version


def get_static_version_info(version_file=STATIC_VERSION_FILE):
version_info = {}
with open(os.path.join(package_root, version_file), "rb") as f:
exec(f.read(), {}, version_info)
return version_info


def version_is_from_git(version_file=STATIC_VERSION_FILE):
return get_static_version_info(version_file)["version"] == "__use_git__"


def pep440_format(version_info):
release, post, labels = version_info

version_parts = [release]
if post:
if release.endswith("-post") or release.endswith(".post"):
version_parts.append(post)
else: # prefer PEP440 over strict adhesion to semver
version_parts.append(".post{}".format(post))

if labels:
version_parts.append("+")
version_parts.append(".".join(labels))

return "".join(version_parts)


def get_version_from_git():
import subprocess

# git describe --first-parent does not take into account tags from branches
# that were merged-in. The '--long' flag gets us the 'post' version and
# git hash, '--always' returns the git hash even if there are no tags.
for opts in [["--first-parent"], []]:
try:
p = subprocess.Popen(
["git", "describe", "--long", "--always", "--tags"] + opts,
cwd=package_root,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
)
except OSError:
return
if p.wait() == 0:
break
else:
return

description = (
p.communicate()[0]
.decode()
.strip("v") # Tags can have a leading 'v', but the version should not
.rstrip("\n")
.rsplit("-", 2) # Split the latest tag, commits since tag, and hash
)

try:
release, post, git = description
except ValueError: # No tags, only the git hash
# prepend 'g' to match with format returned by 'git describe'
git = "g{}".format(*description)
release = "nodescription"
post = None

labels = []
if post == "0":
post = None
else:
labels.append(git)

try:
p = subprocess.Popen(
["git", "describe", "--dirty"],
cwd=package_root,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
)
except OSError:
labels.append("confused") # This should never happen.
else:
dirty_output = p.communicate()[0].decode().strip("\n")
if dirty_output.endswith("dirty"):
labels.append("dirty")

return Version(release, post, labels)


# TODO: change this logic when there is a git pretty-format
# that gives the same output as 'git describe'.
# Currently we can only tell the tag the current commit is
# pointing to, or its hash (with no version info)
# if it is not tagged.
def get_version_from_git_archive(version_info):
try:
refnames = version_info["refnames"]
git_hash = version_info["git_hash"]
except KeyError:
# These fields are not present if we are running from an sdist.
# Execution should never reach here, though
return None

if git_hash.startswith("$Format") or refnames.startswith("$Format"):
# variables not expanded during 'git archive'
return None

vtag = "tag: v"
refs = set(r.strip() for r in refnames.split(","))
version_tags = set(r[len(vtag) :] for r in refs if r.startswith(vtag))
if version_tags:
release, *_ = sorted(version_tags) # prefer e.g. "2.0" over "2.0rc1"
return Version(release, post=None, labels=None)
else:
return Version("notag", post=None, labels=["g{}".format(git_hash)])


__version__ = get_version()


# The following section defines a 'get_cmdclass' function
# that can be used from setup.py. The '__version__' module
# global is used (but not modified).


def _write_version(fname):
# This could be a hard link, so try to delete it first. Is there any way
# to do this atomically together with opening?
try:
os.remove(fname)
except OSError:
pass
with open(fname, "w") as f:
f.write(
"# This file has been created by setup.py.\n"
"version = '{}'\n".format(__version__)
)


def get_cmdclass(pkg_source_path):
from setuptools.command.build_py import build_py as build_py_orig
from setuptools.command.sdist import sdist as sdist_orig

class _build_py(build_py_orig): # noqa
def run(self):
super().run()

src_marker = "".join(["src", os.path.sep])

if pkg_source_path.startswith(src_marker):
path = pkg_source_path[len(src_marker) :]
else:
path = pkg_source_path
_write_version(os.path.join(self.build_lib, path, STATIC_VERSION_FILE))

class _sdist(sdist_orig): # noqa
def make_release_tree(self, base_dir, files):
super().make_release_tree(base_dir, files)
_write_version(os.path.join(base_dir, pkg_source_path, STATIC_VERSION_FILE))

return dict(sdist=_sdist, build_py=_build_py)
20 changes: 18 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,24 @@
from setuptools import find_packages, setup


def get_version_and_cmdclass(pkg_path):
"""Load version.py module without importing the whole package.
Template code from miniver
"""
import os
from importlib.util import module_from_spec, spec_from_file_location

spec = spec_from_file_location("version", os.path.join(pkg_path, "_version.py"))
module = module_from_spec(spec)
spec.loader.exec_module(module)
return module.__version__, module.get_cmdclass(pkg_path)


version, cmdclass = get_version_and_cmdclass(r"pygfx")

with open("pygfx/__init__.py", "rb") as fh:
init_text = fh.read().decode()
VERSION = re.search(r"__version__ = \"(.*?)\"", init_text).group(1)
match = re.search(r"__wgpu_version_range__ = \"(.*?)\", \"(.*?)\"", init_text)
wgpu_min_ver, wgpu_max_ver = match.group(1), match.group(2)
match = re.search(r"__pylinalg_version_range__ = \"(.*?)\", \"(.*?)\"", init_text)
Expand Down Expand Up @@ -65,7 +80,8 @@

setup(
name="pygfx",
version=VERSION,
version=version,
cmdclass=cmdclass,
packages=find_packages(
exclude=["tests", "tests.*", "examples", "examples.*", "exp", "exp.*"]
),
Expand Down

0 comments on commit 20d06df

Please sign in to comment.