diff --git a/.circleci/config.yml b/.circleci/config.yml index b7db4924..7d3f0765 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -63,6 +63,19 @@ jobs: key: build-v1-{{ .Branch }}-{{ epoch }} paths: - /tmp/docker + - run: + name: Check version packaged in Docker image + command: | + THISVERSION=$(python3 setup.py --version) + THISVERSION=${CIRCLE_TAG:-$THISVERSION} + INSTALLED_VERSION=$(\ + docker run -it --rm --entrypoint=python nitransforms \ + -c 'import nitransforms as nit; print(nit.__version__)') + INSTALLED_VERSION=${INSTALLED_VERSION%$'\r'} + echo "VERSION: \"$THISVERSION\"" + echo "INSTALLED: \"$INSTALLED_VERSION\"" + test "$INSTALLED_VERSION" = "$THISVERSION" + - run: name: Store FreeSurfer license file command: | @@ -125,16 +138,81 @@ jobs: - store_test_results: path: /tmp/tests/summaries/ - test_packaging_and_deploy: - machine: - image: circleci/classic:201808-01 + test_package: + docker: + - image: circleci/python:3.7.4 + working_directory: /tmp/src/nitransforms + steps: + - checkout + - run: + name: Setup Python environment with virtualenvs + command: | + python -m pip install --user --upgrade virtualenv pip + - run: + name: Prepare build environment + command: | + virtualenv --python=python3 /tmp/build + source /tmp/build/bin/activate + python3 -m pip install "setuptools ~= 42.0" "setuptools_scm[toml] >= 3.4" "pip>=10.0.1" \ + twine docutils + - run: + name: Build NiTransforms in build environment + command: | + source /tmp/build/bin/activate + python setup.py sdist bdist_wheel + - run: + name: Check sdist package in build environment + command: | + source /tmp/build/bin/activate + twine check dist/nitransforms* + - store_artifacts: + path: /tmp/src/nitransforms/dist + - run: + name: Prepare sdist install environment + command: | + virtualenv --python=python3 /tmp/install_sdist + source /tmp/install_sdist/bin/activate + python3 -m pip install "setuptools ~= 42.0" "setuptools_scm[toml] >= 3.4" "pip>=10.0.1" + - run: + name: Install sdist package into install environment and check version + command: | + source /tmp/install_sdist/bin/activate + THISVERSION=$( python setup.py --version ) + THISVERSION=${CIRCLE_TAG:-$THISVERSION} + pip install dist/nitransforms*.tar.gz + INSTALLED_VERSION=$(python -c 'import nitransforms as nit; print(nit.__version__)') + INSTALLED_VERSION=${INSTALLED_VERSION%$'\r'} + echo "VERSION: \"$THISVERSION\"" + echo "INSTALLED: \"$INSTALLED_VERSION\"" + test "$INSTALLED_VERSION" = "$THISVERSION" + - run: + name: Prepare wheel install environment + command: | + virtualenv --python=python3 /tmp/install_wheel + source /tmp/install_wheel/bin/activate + python3 -m pip install "setuptools ~= 42.0" "setuptools_scm[toml] >= 3.4" "pip>=10.0.1" + - run: + name: Install wheel into install environment and check version + command: | + source /tmp/install_wheel/bin/activate + THISVERSION=$( python setup.py --version ) + THISVERSION=${CIRCLE_TAG:-$THISVERSION} + pip install dist/nitransforms*.whl + INSTALLED_VERSION=$(python -c 'import nitransforms as nit; print(nit.__version__)') + INSTALLED_VERSION=${INSTALLED_VERSION%$'\r'} + echo "VERSION: \"$THISVERSION\"" + echo "INSTALLED: \"$INSTALLED_VERSION\"" + test "$INSTALLED_VERSION" = "$THISVERSION" + + deploy_pypi: + docker: + - image: circleci/python:3.7.4 working_directory: /tmp/src/nitransforms steps: - checkout - - run: pyenv local 3.7.0 - run: name: Install build depends - command: python3 -m pip install "setuptools>=30.4.0" "pip>=10.0.1" "twine<2.0" docutils + command: python3 -m pip install "setuptools ~= 42.0" "setuptools_scm[toml] >= 3.4" "pip>=10.0.1" "twine<2.0" docutils - run: name: Build and check command: | @@ -144,7 +222,7 @@ jobs: - run: name: Validate version command: | - THISVERSION=$( python3 get_version.py ) + THISVERSION=$( python setup.py --version ) python3 -m pip install dist/*.tar.gz mkdir empty cd empty @@ -167,9 +245,18 @@ workflows: tags: only: /.*/ - - test_packaging_and_deploy: + - test_package: + filters: + branches: + ignore: + - /docs?\/.*/ + tags: + only: /.*/ + + - deploy_pypi: requires: - build_pytest + - test_package filters: branches: ignore: /.*/ diff --git a/.gitignore b/.gitignore index fccbf479..8681c41b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,6 @@ +# setuptools-scm +nitransforms/_version.py + # Byte-compiled / optimized / DLL files __pycache__/ *.py[cod] diff --git a/nitransforms/__init__.py b/nitransforms/__init__.py index 34868b55..c35b9a18 100644 --- a/nitransforms/__init__.py +++ b/nitransforms/__init__.py @@ -18,7 +18,21 @@ """ from .linear import Affine from .nonlinear import DisplacementsFieldTransform -from .io import afni, fsl, itk +try: + from ._version import __version__ +except ModuleNotFoundError: + from pkg_resources import get_distribution, DistributionNotFound + try: + __version__ = get_distribution('nitransforms').version + except DistributionNotFound: + __version__ = 'unknown' + del get_distribution + del DistributionNotFound -__all__ = ['afni', 'fsl', 'itk', 'Affine', 'DisplacementsFieldTransform'] + +__all__ = [ + 'Affine', + 'DisplacementsFieldTransform', + '__version__', +] diff --git a/nitransforms/tests/test_version.py b/nitransforms/tests/test_version.py new file mode 100644 index 00000000..0e2e7fd6 --- /dev/null +++ b/nitransforms/tests/test_version.py @@ -0,0 +1,41 @@ +"""Test _version.py.""" +import sys +from collections import namedtuple +from pkg_resources import DistributionNotFound +from importlib import reload +import nitransforms + + +def test_version_scm0(monkeypatch): + """Retrieve the version via setuptools_scm.""" + class _version: + __version__ = "10.0.0" + + monkeypatch.setitem(sys.modules, 'nitransforms._version', _version) + reload(nitransforms) + assert nitransforms.__version__ == "10.0.0" + + +def test_version_scm1(monkeypatch): + """Retrieve the version via pkg_resources.""" + monkeypatch.setitem(sys.modules, 'nitransforms._version', None) + + def _dist(name): + Distribution = namedtuple("Distribution", ["name", "version"]) + return Distribution(name, "success") + + monkeypatch.setattr('pkg_resources.get_distribution', _dist) + reload(nitransforms) + assert nitransforms.__version__ == "success" + + +def test_version_scm2(monkeypatch): + """Check version could not be interpolated.""" + monkeypatch.setitem(sys.modules, 'nitransforms._version', None) + + def _raise(name): + raise DistributionNotFound("No get_distribution mock") + + monkeypatch.setattr('pkg_resources.get_distribution', _raise) + reload(nitransforms) + assert nitransforms.__version__ == "unknown" diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 00000000..132dd49d --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,10 @@ +[build-system] +requires = ["setuptools ~= 42.0", "wheel", "setuptools_scm[toml] >= 3.4"] + +[tool.setuptools_scm] +write_to = "nitransforms/_version.py" +write_to_template = """\ +\"\"\"Version file, automatically generated by setuptools_scm.\"\"\" +__version__ = "{version}" +""" +fallback_version = "0.0" diff --git a/setup.cfg b/setup.cfg index 5d8b63a1..122eee65 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,6 +1,20 @@ [metadata] -provides = - nitransforms +author = The NiPreps developers +author_email = nipreps@gmail.com +classifiers = + Development Status :: 2 - Pre-Alpha + Intended Audience :: Science/Research + Topic :: Scientific/Engineering :: Image Recognition + License :: OSI Approved :: BSD License + Programming Language :: Python :: 3.6 + Programming Language :: Python :: 3.7 + Programming Language :: Python :: 3.8 +description = NiTransforms -- Neuroimaging spatial transforms in Python. +license = MIT +long_description = file:README.md +long_description_content_type = text/markdown; charset=UTF-8 +provides = nitransforms +url = https://github.com/poldracklab/nitransforms [options] python_requires = >= 3.6 @@ -14,6 +28,9 @@ test_requires = pytest-cov nose codecov +setup_requires = + setuptools_scm + toml packages = find: include_package_data = True diff --git a/setup.py b/setup.py index 8b25856b..5f2a1c89 100644 --- a/setup.py +++ b/setup.py @@ -1,6 +1,13 @@ +"""Prepare package for distribution.""" +from pathlib import Path from setuptools import setup +from toml import loads if __name__ == "__main__": + scm_cfg = loads( + (Path(__file__).parent / "pyproject.toml").read_text() + )["tool"]["setuptools_scm"] setup( name="nitransforms", + use_scm_version=scm_cfg, )