Skip to content

Use versioningit to work with pyproject.toml and remove setup.py #420

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions adaptive/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
11 changes: 0 additions & 11 deletions adaptive/_static_version.py

This file was deleted.

210 changes: 4 additions & 206 deletions adaptive/_version.py
Original file line number Diff line number Diff line change
@@ -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)
1 change: 1 addition & 0 deletions docs/environment.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,4 @@ dependencies:
- myst-parser=0.18.1
- dask=2023.3.2
- emoji=2.2.0
- versioningit=2.2.0
14 changes: 13 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -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"
Expand All @@ -24,6 +24,7 @@ dependencies = [
"cloudpickle",
"loky >= 2.9",
"typing_extensions; python_version < '3.10'",
"versioningit",
]

[project.optional-dependencies]
Expand Down Expand Up @@ -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"
5 changes: 5 additions & 0 deletions setup.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# All other settings are in pyproject.toml
[options]
cmdclass =
sdist = versioningit.cmdclass.sdist
build_py = versioningit.cmdclass.build_py
22 changes: 0 additions & 22 deletions setup.py

This file was deleted.