python/adbc_driver_manager/adbc_driver_manager/_version.py (135 lines of code) (raw):

# -*- coding: utf-8 -*- # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # Generated by miniver (CC0). import os import re # This file is part of 'miniver': https://github.com/jbweston/miniver # from collections import namedtuple Version = namedtuple("Version", ("release", "dev", "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" TAG_RELEASE_FORMAT = re.compile( r"^apache-arrow-adbc-([0-9]+\.[0-9]+\.[0-9]+)(?:-rc[0-9]+)?$" ) def get_version(version_file=STATIC_VERSION_FILE): override = os.environ.get("SETUPTOOLS_SCM_PRETEND_VERSION") if override is not None and override != "": return override 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(".dev{}".format(dev)) 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 '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"] + 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, dev, git = description release = TAG_RELEASE_FORMAT.match(release).group(1) except (AttributeError, ValueError): # Invalid tag; or no tags, only the git hash # prepend 'g' to match with format returned by 'git describe' git = "g{}".format(*description) # XXX: assume version if not given release = "0.0.0" dev = None labels = [] if dev == "0": dev = None else: labels.append(git) try: p = subprocess.Popen(["git", "diff", "--quiet"], cwd=package_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: " 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" release = TAG_RELEASE_FORMAT.match(release).group(1) return Version(release, dev=None, labels=None) else: return Version("unknown", dev=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): 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): 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) if __name__ == "__main__": print("Version: ", get_version())