Skip to content

Commit

Permalink
Use setuptools_scm for versioning, fixes #1333 (#1334)
Browse files Browse the repository at this point in the history
* Use setuptools_scm for versioning

* Use astropys approach for setuptools_scm

* Require setuptools_scm at runtime for dev

* Fix file exclude in manifest
  • Loading branch information
maxnoe committed Nov 13, 2020
1 parent 83c96f9 commit 3689b52
Show file tree
Hide file tree
Showing 7 changed files with 35 additions and 189 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ __pycache__

# ignore version cache file (generated automatically when setup.py is run)
ctapipe/_version_cache.py
ctapipe/_version.py

# Ignore .c files by default to avoid including generated code. If you want to
# add a non-generated .c extension, use `git add -f filename.c`.
Expand Down
5 changes: 1 addition & 4 deletions MANIFEST.in
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,11 @@ include CHANGES.rst

include setup.cfg

recursive-include *.pyx *.c *.pxd
recursive-include docs *
recursive-include licenses *
recursive-include cextern *
recursive-include scripts *

prune build
prune docs/_build
prune docs/api
exclude ctapipe/_dev_version.py

global-exclude *.pyc *.o
5 changes: 2 additions & 3 deletions ctapipe/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
"""
ctapipe - CTA Python pipeline experimental version
"""
from .version import __version__

from . import version

__version__ = version.get_version(pep440=False)
__all__ = ['__version__']
9 changes: 9 additions & 0 deletions ctapipe/_dev_version.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Try to use setuptools_scm to get the current version; this is only used
# in development installations from the git repository.
# see ctapipe/version.py for details
try:
from setuptools_scm import get_version

version = get_version(root="..", relative_to=__file__)
except Exception as e:
raise ImportError(f"setuptools_scm broken or not installed: {e}")
187 changes: 18 additions & 169 deletions ctapipe/version.py
Original file line number Diff line number Diff line change
@@ -1,172 +1,21 @@
"""
Get version identification from git.
# this is adapted from https://github.com/astropy/astropy/blob/master/astropy/version.py
# see https://github.com/astropy/astropy/pull/10774 for a discussion on why this needed.

The update_release_version() function writes the current version to the
VERSION file. This function should be called before packaging a release version.
Use the get_version() function to get the version string, including the latest
commit, from git.
If git is not available the VERSION file will be read.
Heres an example of such a version string:
v0.2.0.post58+git57440dc
This code was taken from here:
https://github.com/aebrahim/python-git-version
Combining ideas from
http://blogs.nopcode.org/brainstorm/2013/05/20/pragmatic-python-versioning-via-setuptools-and-git-tags/
and Python Versioneer
https://github.com/warner/python-versioneer
but being much more lightwheight
"""
from subprocess import check_output, CalledProcessError
from os import path, name, devnull, environ, listdir

__all__ = ("get_version",)

CURRENT_DIRECTORY = path.dirname(path.abspath(__file__))
VERSION_FILE = path.join(CURRENT_DIRECTORY, "_version_cache.py")

GIT_COMMAND = "git"

if name == "nt":

def find_git_on_windows():
"""find the path to the git executable on windows"""
# first see if git is in the path
try:
check_output(["where", "/Q", "git"])
# if this command succeeded, git is in the path
return "git"
# catch the exception thrown if git was not found
except CalledProcessError:
pass
# There are several locations git.exe may be hiding
possible_locations = []
# look in program files for msysgit
if "PROGRAMFILES(X86)" in environ:
possible_locations.append(
"%s/Git/cmd/git.exe" % environ["PROGRAMFILES(X86)"]
)
if "PROGRAMFILES" in environ:
possible_locations.append("%s/Git/cmd/git.exe" % environ["PROGRAMFILES"])
# look for the github version of git
if "LOCALAPPDATA" in environ:
github_dir = "%s/GitHub" % environ["LOCALAPPDATA"]
if path.isdir(github_dir):
for subdir in listdir(github_dir):
if not subdir.startswith("PortableGit"):
continue
possible_locations.append(
"%s/%s/bin/git.exe" % (github_dir, subdir)
)
for possible_location in possible_locations:
if path.isfile(possible_location):
return possible_location
# git was not found
return "git"

GIT_COMMAND = find_git_on_windows()


def get_git_describe_version(abbrev=7):
"""return the string output of git desribe"""
try:
try:
with open(devnull, "w") as fnull:
arguments = [GIT_COMMAND, "describe", "--tags", "--abbrev=%d" % abbrev]
return (
check_output(arguments, cwd=CURRENT_DIRECTORY, stderr=fnull)
.decode("ascii")
.strip()
)
except (OSError, CalledProcessError):
return None


def format_git_describe(git_str, pep440=False):
"""format the result of calling 'git describe' as a python version"""

if "-" not in git_str: # currently at a tag
formatted_str = git_str
else:
# formatted as version-N-githash
# want to convert to version.postN-githash
git_str = git_str.replace("-", ".post", 1)
if pep440: # does not allow git hash afterwards
formatted_str = git_str.split("-")[0]
else:
formatted_str = git_str.replace("-g", "+git")

# need to remove the "v" to have a proper python version
if formatted_str.startswith("v"):
formatted_str = formatted_str[1:]

return formatted_str


def read_release_version():
"""Read version information from VERSION file"""
try:
from ._version_cache import version

if len(version) == 0:
version = None
return version
from ._dev_version import version
except ImportError:
return "unknown"


def update_release_version(pep440=False):
"""Release versions are stored in a file called VERSION.
This method updates the version stored in the file.
This function should be called when creating new releases.
It is called by setup.py when building a package.
pep440: bool
When True, this function returns a version string suitable for
a release as defined by PEP 440. When False, the githash (if
available) will be appended to the version string.
"""
version = get_version(pep440=pep440)
with open(VERSION_FILE, "w") as outfile:
outfile.write(f"version='{version}'")
outfile.write("\n")


def get_version(pep440=False):
"""Tracks the version number.
pep440: bool
When True, this function returns a version string suitable for
a release as defined by PEP 440. When False, the githash (if
available) will be appended to the version string.
The file VERSION holds the version information. If this is not a git
repository, then it is reasonable to assume that the version is not
being incremented and the version returned will be the release version as
read from the file.
However, if the script is located within an active git repository,
git-describe is used to get the version information.
The file VERSION will need to be changed manually.
"""

raw_git_version = get_git_describe_version()
if not raw_git_version: # not a git repository
return read_release_version()

git_version = format_git_describe(raw_git_version, pep440=pep440)

return git_version


if __name__ == "__main__":
print(get_version())
from ._version import version
except Exception:
import warnings

warnings.warn(
"Could not determine ctapipe version; this indicates a broken installation."
" Install ctapipe from PyPI, using conda or from a local git repository."
" Installing github's autogenerated source release tarballs "
" does not include version information and should be avoided."
)
del warnings
version = "0.0.0"

__version__ = version
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[build-system]
requires = ["setuptools >= 40.6.0", "wheel"]
requires = ["setuptools >= 40.6.0", "wheel", "setuptools_scm[toml]>=3.4"]
build-backend = "setuptools.build_meta"

[tool.black]
Expand Down
15 changes: 3 additions & 12 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,8 @@

# import ah_bootstrap
from setuptools import setup, find_packages

import sys
import os

# pep 517 builds do not have cwd in PATH by default
sys.path.insert(0, os.path.dirname(__file__))
# Get the long and version description from the package's docstring
import ctapipe # noqa


# Define entry points for command-line scripts
# TODO: this shuold be automated (e.g. look for main functions and
# rename _ to -, and prepend 'ctapipe'
Expand Down Expand Up @@ -49,11 +41,8 @@
"graphviz",
]

ctapipe.version.update_release_version()

setup(
packages=find_packages(),
version=ctapipe.version.get_version(pep440=True),
python_requires=">=3.7",
install_requires=[
"astropy>=3,<5",
Expand All @@ -72,6 +61,7 @@
"tqdm>=4.32",
"traitlets~=5.0,>=5.0.5",
"zstandard",
"setuptools_scm>=3.4",
# needed for astropy hdf5 io. Version 3 breaks copying those tables
# with pytables du to variable length strings.
"h5py~=2.0",
Expand All @@ -82,8 +72,9 @@
"tests": tests_require,
"docs": docs_require,
},
use_scm_version={"write_to": os.path.join("ctapipe", "_version.py")},
tests_require=tests_require,
setup_requires=["pytest_runner"],
setup_requires=["pytest_runner", "setuptools_scm"],
classifiers=[
"Intended Audience :: Science/Research",
"License :: OSI Approved :: BSD License",
Expand Down

0 comments on commit 3689b52

Please sign in to comment.