-
-
Notifications
You must be signed in to change notification settings - Fork 35
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add miniver to simplify development branch descriptions
``` 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
Showing
7 changed files
with
249 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
pygfx/_static_version.py export-subst |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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$" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters