Skip to content

Commit c90871e

Browse files
committed
chore: Use setuptools_scm to manage versioning
Summary ------- Pilots whether we can abandon versioneer in all projects, as setuptools_scm has minimal boilerplate. Changes ------- The setuptools_scm module is added to the pyproject.toml file, as recommended in the documentation. A tiny hack is added to the root ``__init__.py`` file, so that the version is read from ``nitransforms/_version.py`` when that file exists or it is interpolated via ``setuptools_scm.get_version``. To make the version traverse into container images, before building, ``python setup.py --version`` must be invoked first (and it will create the ``nitransforms/_version.py`` file. ``nitransforms/_version.py`` has been added to ``.gitignore`` to avoid adding it by mistake. Finally, the CircleCI workflow is also modified, so that the packaging is always tested and installed versions are checked both for python packages and docker distributions. Resolves: #82
1 parent f0c91b4 commit c90871e

File tree

6 files changed

+129
-3
lines changed

6 files changed

+129
-3
lines changed

.circleci/config.yml

+90-1
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,12 @@ jobs:
4141
docker push localhost:5000/ubuntu
4242
fi
4343
- checkout
44+
- run: pyenv local 3.7.0
4445
- run:
4546
name: Build Docker image & push to registry
4647
no_output_timeout: 60m
4748
command: |
49+
python3 setup.py --version
4850
e=1 && for i in {1..5}; do
4951
docker build --rm --cache-from=nitransforms:latest \
5052
-t nitransforms:latest \
@@ -63,6 +65,18 @@ jobs:
6365
key: build-v1-{{ .Branch }}-{{ epoch }}
6466
paths:
6567
- /tmp/docker
68+
- run:
69+
name: Check version packaged in Docker image
70+
command: |
71+
THISVERSION=$(python3 setup.py --version)
72+
THISVERSION=${CIRCLE_TAG:-$THISVERSION}
73+
INSTALLED_VERSION=$(\
74+
docker run -it --rm --entrypoint=python nitransforms \
75+
-c 'import nitransforms as nit; print(nit.__version__)')
76+
INSTALLED_VERSION=${INSTALLED_VERSION%$'\r'}
77+
echo "VERSION: \"$THISVERSION\""
78+
echo "INSTALLED: \"$INSTALLED_VERSION\""
79+
test "$INSTALLED_VERSION" = "$THISVERSION"
6680
- run:
6781
name: Store FreeSurfer license file
6882
command: |
@@ -74,6 +88,72 @@ jobs:
7488
paths:
7589
- fslicense
7690

91+
test_package:
92+
docker:
93+
- image: circleci/python:3.7.4
94+
working_directory: /tmp/src/nitransforms
95+
steps:
96+
- checkout
97+
- run:
98+
name: Setup Python environment with virtualenvs
99+
command: |
100+
python -m pip install --user --upgrade virtualenv pip
101+
- run:
102+
name: Prepare build environment
103+
command: |
104+
virtualenv --python=python3 /tmp/build
105+
source /tmp/build/bin/activate
106+
python3 -m pip install "setuptools ~= 42.0" "setuptools_scm[toml] >= 3.4" "pip>=10.0.1" \
107+
twine docutils
108+
- run:
109+
name: Prepare install environments
110+
command: |
111+
virtualenv --python=python3 /tmp/install_sdist
112+
source /tmp/install_sdist/bin/activate
113+
python3 -m pip install "setuptools ~= 42.0" "setuptools_scm[toml] >= 3.4" "pip>=10.0.1"
114+
deactivate
115+
virtualenv --python=python3 /tmp/install_wheel
116+
source /tmp/install_wheel/bin/activate
117+
python3 -m pip install "setuptools ~= 42.0" "setuptools_scm[toml] >= 3.4" "pip>=10.0.1"
118+
- run:
119+
name: Build NiTransforms in build environment
120+
command: |
121+
source /tmp/build/bin/activate
122+
python setup.py sdist bdist_wheel
123+
- store_artifacts:
124+
path: /tmp/src/nitransforms/dist
125+
- run:
126+
name: Check sdist package in build environment
127+
command: |
128+
source /tmp/build/bin/activate
129+
twine check dist/nitransforms*
130+
- run:
131+
name: Install sdist package into install environment and check version
132+
command: |
133+
source /tmp/install_sdist/bin/activate
134+
THISVERSION=$( python setup.py --version )
135+
THISVERSION=${CIRCLE_TAG:-$THISVERSION}
136+
pip install dist/nitransforms*.tar.gz
137+
which nitransforms | grep install_sdist\\/bin
138+
INSTALLED_VERSION=$(python -c 'import nitransforms as nit; print(nit.__version__)')
139+
INSTALLED_VERSION=${INSTALLED_VERSION%$'\r'}
140+
echo "VERSION: \"$THISVERSION\""
141+
echo "INSTALLED: \"$INSTALLED_VERSION\""
142+
test "$INSTALLED_VERSION" = "$THISVERSION"
143+
- run:
144+
name: Install wheel into install environment and check version
145+
command: |
146+
source /tmp/install_wheel/bin/activate
147+
THISVERSION=$( python setup.py --version )
148+
THISVERSION=${CIRCLE_TAG:-$THISVERSION}
149+
pip install dist/nitransforms*.whl
150+
which nitransforms | grep install_wheel\\/bin
151+
INSTALLED_VERSION=$(python -c 'import nitransforms as nit; print(nit.__version__)')
152+
INSTALLED_VERSION=${INSTALLED_VERSION%$'\r'}
153+
echo "VERSION: \"$THISVERSION\""
154+
echo "INSTALLED: \"$INSTALLED_VERSION\""
155+
test "$INSTALLED_VERSION" = "$THISVERSION"
156+
77157
test_pytest:
78158
machine:
79159
image: circleci/classic:201808-01
@@ -175,6 +255,14 @@ workflows:
175255
tags:
176256
only: /.*/
177257

258+
- test_package:
259+
filters:
260+
branches:
261+
ignore:
262+
- /docs?\/.*/
263+
tags:
264+
only: /.*/
265+
178266
- test_pytest:
179267
requires:
180268
- build
@@ -186,9 +274,10 @@ workflows:
186274
tags:
187275
only: /.*/
188276

189-
- test_packaging_and_deploy:
277+
- deploy_pypi:
190278
requires:
191279
- test_pytest
280+
- test_package
192281
filters:
193282
branches:
194283
ignore: /.*/

.gitignore

+3
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
# setuptools-scm
2+
nitransforms/_version.py
3+
14
# Byte-compiled / optimized / DLL files
25
__pycache__/
36
*.py[cod]

nitransforms/__init__.py

+16-2
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,21 @@
1818
"""
1919
from .linear import Affine
2020
from .nonlinear import DisplacementsFieldTransform
21-
from .io import afni, fsl, itk
2221

22+
try:
23+
from ._version import version as __version__
24+
except ModuleNotFoundError:
25+
from pkg_resources import get_distribution, DistributionNotFound
26+
try:
27+
__version__ = get_distribution('nitransforms').version
28+
except DistributionNotFound:
29+
__version__ = 'unknown'
30+
del get_distribution
31+
del DistributionNotFound
2332

24-
__all__ = ['afni', 'fsl', 'itk', 'Affine', 'DisplacementsFieldTransform']
33+
34+
__all__ = [
35+
'Affine',
36+
'DisplacementsFieldTransform',
37+
'__version__',
38+
]

pyproject.toml

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
[build-system]
2+
requires = ["setuptools ~= 42.0", "wheel", "setuptools_scm[toml] >= 3.4"]
3+
4+
[tool.setuptools_scm]
5+
write_to = "nitransforms/_version.py"
6+
write_to_template = """\
7+
\"\"\"Version file, automatically generated by setuptools_scm.\"\"\"
8+
__version__ = "{version}"
9+
"""
10+
fallback_version = "0.0"

setup.cfg

+3
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ test_requires =
1414
pytest-cov
1515
nose
1616
codecov
17+
setup_requires =
18+
setuptools_scm
19+
toml
1720
packages = find:
1821
include_package_data = True
1922

setup.py

+7
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
1+
"""Prepare package for distribution."""
2+
from pathlib import Path
13
from setuptools import setup
4+
from toml import loads
25

36
if __name__ == "__main__":
7+
scm_cfg = loads(
8+
(Path(__file__).parent / "pyproject.toml").read_text()
9+
)["tool"]["setuptools_scm"]
410
setup(
511
name="nitransforms",
12+
use_scm_version=scm_cfg,
613
)

0 commit comments

Comments
 (0)