From b1736dbb223e860062d00fd177112dec2faf2b6e Mon Sep 17 00:00:00 2001 From: Bas Nijholt Date: Sat, 29 Apr 2023 23:16:58 -0700 Subject: [PATCH] Use versioningit --- adaptive/__init__.py | 3 +- adaptive/_static_version.py | 11 -- adaptive/_version.py | 210 +----------------------------------- docs/environment.yml | 1 + pyproject.toml | 14 ++- setup.cfg | 5 + setup.py | 22 ---- 7 files changed, 24 insertions(+), 242 deletions(-) delete mode 100644 adaptive/_static_version.py create mode 100644 setup.cfg delete mode 100644 setup.py diff --git a/adaptive/__init__.py b/adaptive/__init__.py index dbf7c6b86..4f99d67e7 100644 --- a/adaptive/__init__.py +++ b/adaptive/__init__.py @@ -53,6 +53,5 @@ __all__.append("SKOptLearner") -# to avoid confusion with `notebook_extension` and `__version__` -del _version # type: ignore[name-defined] # noqa: F821 +# to avoid confusion with `notebook_extension` del notebook_integration # type: ignore[name-defined] # noqa: F821 diff --git a/adaptive/_static_version.py b/adaptive/_static_version.py deleted file mode 100644 index f7d3e6c9c..000000000 --- a/adaptive/_static_version.py +++ /dev/null @@ -1,11 +0,0 @@ -# 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$" diff --git a/adaptive/_version.py b/adaptive/_version.py index ce1351504..2eb743f4e 100644 --- a/adaptive/_version.py +++ b/adaptive/_version.py @@ -1,208 +1,6 @@ -# This file is part of 'miniver': https://github.com/jbweston/miniver -# -from __future__ import annotations +from pathlib import Path -import os -import subprocess -from collections import namedtuple +import versioningit -from setuptools.command.build_py import build_py as build_py_orig -from setuptools.command.sdist import sdist as sdist_orig - -Version = namedtuple("Version", ("release", "dev", "labels")) - -# No public API -__all__: list[str] = [] - -package_root = os.path.dirname(os.path.realpath(__file__)) -package_name = os.path.basename(package_root) -distr_root = os.path.dirname(package_root) -# If the package is inside a "src" directory the -# distribution root is 1 level up. -if os.path.split(distr_root)[1] == "src": - _package_root_inside_src = True - distr_root = os.path.dirname(distr_root) -else: - _package_root_inside_src = False - -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("unknown", 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, dev, labels = version_info - - version_parts = [release] - if dev: - if release.endswith("-dev") or release.endswith(".dev"): - version_parts.append(dev) - else: # prefer PEP440 over strict adhesion to semver - version_parts.append(f".dev{dev}") - - if labels: - version_parts.append("+") - version_parts.append(".".join(labels)) - - return "".join(version_parts) - - -def get_version_from_git(): - try: - p = subprocess.Popen( - ["git", "rev-parse", "--show-toplevel"], - cwd=distr_root, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - ) - except OSError: - return - if p.wait() != 0: - return - if not os.path.samefile(p.communicate()[0].decode().rstrip("\n"), distr_root): - # The top-level directory of the current Git repository is not the same - # as the root directory of the distribution: do not extract the - # version from Git. - return - - # git describe --first-parent does not take into account tags from branches - # that were merged-in. The '--long' flag gets us the 'dev' 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=distr_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, dev, 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 = "unknown" - dev = None - - labels = [] - if dev == "0": - dev = None - else: - labels.append(git) - - try: - p = subprocess.Popen(["git", "diff", "--quiet"], cwd=distr_root) - except OSError: - labels.append("confused") # This should never happen. - else: - if p.wait() == 1: - labels.append("dirty") - - return Version(release, dev, 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 = {r.strip() for r in refnames.split(",")} - version_tags = {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, dev=None, labels=None) - else: - return Version("unknown", dev=None, labels=[f"g{git_hash}"]) - - -__version__ = get_version() - - -# The following section defines a module global 'cmdclass', -# which can be used from setup.py. The 'package_name' and -# '__version__' module globals are 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__) - ) - - -class _build_py(build_py_orig): - def run(self): - super().run() - _write_version(os.path.join(self.build_lib, package_name, STATIC_VERSION_FILE)) - - -class _sdist(sdist_orig): - def make_release_tree(self, base_dir, files): - super().make_release_tree(base_dir, files) - if _package_root_inside_src: - p = os.path.join("src", package_name) - else: - p = package_name - _write_version(os.path.join(base_dir, p, STATIC_VERSION_FILE)) - - -cmdclass = {"sdist": _sdist, "build_py": _build_py} +REPO_ROOT = Path(__file__).parent.parent +__version__ = versioningit.get_version(project_dir=REPO_ROOT) diff --git a/docs/environment.yml b/docs/environment.yml index ade7f65ee..67298496c 100644 --- a/docs/environment.yml +++ b/docs/environment.yml @@ -25,3 +25,4 @@ dependencies: - myst-parser=0.18.1 - dask=2023.3.2 - emoji=2.2.0 + - versioningit=2.2.0 diff --git a/pyproject.toml b/pyproject.toml index 6a907965e..f0ea8eddf 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [build-system] build-backend = "setuptools.build_meta" -requires = ["setuptools ~= 65.0.0", "versioningit ~= 2.0.1", "wheel"] +requires = ["setuptools ~= 65.0.0", "versioningit ~= 2.2.0", "wheel"] [project] name = "adaptive" @@ -24,6 +24,7 @@ dependencies = [ "cloudpickle", "loky >= 2.9", "typing_extensions; python_version < '3.10'", + "versioningit", ] [project.optional-dependencies] @@ -115,3 +116,14 @@ ignore = [ [tool.ruff.mccabe] max-complexity = 18 + +[tool.versioningit] + +[tool.versioningit.vcs] +method = "git" +match = ["v*"] +default-tag = "0.0.0" + +[tool.versioningit.onbuild] +build-file = "adaptive/_version.py" +source-file = "adaptive/_version.py" diff --git a/setup.cfg b/setup.cfg new file mode 100644 index 000000000..f464225ad --- /dev/null +++ b/setup.cfg @@ -0,0 +1,5 @@ +# All other settings are in pyproject.toml +[options] +cmdclass = + sdist = versioningit.cmdclass.sdist + build_py = versioningit.cmdclass.build_py diff --git a/setup.py b/setup.py deleted file mode 100644 index 175f16062..000000000 --- a/setup.py +++ /dev/null @@ -1,22 +0,0 @@ -#!/usr/bin/env python3 - -from setuptools import setup - - -# Loads _version.py module without importing the whole package. -def get_version_and_cmdclass(package_name): - import os - from importlib.util import module_from_spec, spec_from_file_location - - spec = spec_from_file_location("version", os.path.join(package_name, "_version.py")) - module = module_from_spec(spec) - spec.loader.exec_module(module) - return module.__version__, module.cmdclass - - -version, cmdclass = get_version_and_cmdclass("adaptive") - - -setup( - cmdclass=cmdclass, -)