Skip to content

Commit

Permalink
MNT: Switch to hatch build backend and update package metadata (#2914)
Browse files Browse the repository at this point in the history
This PR aims to move away from setuptools+versioneer, which we've been using for a while.

One advantage to this approach is that `_version.py` can be updated by running `hatch build --hooks-only`, which will ensure that patching with `fmriprep-docker --patch fmriprep=...` will get a sensible version instead of the useless `0+unknown` which breaks the reuse of workflow directories.

I have moved to the [hatch](https://hatch.pypa.io/latest/) build system, which has some advantages. This is a plugin-oriented build-system, which means it should be fairly easy for us to find or write additional tools if our needs change. The [hatch-vcs](https://github.com/ofek/hatch-vcs) plugin wraps `setuptools_scm` with only minor changes to the configuration needed.

One additional nice feature of hatch is that you can set different file include/exclude rules for sdists and wheels. In principle, an sdist should be testable without resorting to the original repository, so I have never much liked that we remove a large chunk of data. This allows us to exclude some large data in the `fmriprep/data/tests` directory only in the wheel. This reduces our 5.5MB wheel down to 208K while allowing the sdist to grow to the 24MB monstrosity that it ought to be.
  • Loading branch information
effigies committed Jan 6, 2023
2 parents 99212c2 + c4acb74 commit 09efab5
Show file tree
Hide file tree
Showing 75 changed files with 342 additions and 1,236 deletions.
72 changes: 35 additions & 37 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@ _machine_defaults: &machine_defaults
TZ: "/usr/share/zoneinfo/America/Los_Angeles"
SCRATCH: "/scratch"
machine:
image: ubuntu-2004:current
image: ubuntu-2204:current
docker_layer_caching: true
working_directory: /tmp/src/fmriprep
resource_class: large

_python_defaults: &python_defaults
docker:
- image: circleci/python:3.9.6
- image: cimg/python:3.10.9
working_directory: /tmp/src/fmriprep

_docker_auth: &docker_auth
Expand Down Expand Up @@ -84,7 +84,7 @@ _setup_fmriprep_docker: &setup_fmriprep_docker
sed -e 's/.* 3\./3./' -e 's/ .*//')
pyenv local $PY3
mkdir -p /tmp/${DATASET}/derivatives
pip install --upgrade pip setuptools
pip install --upgrade pip
pip install --upgrade /tmp/src/fmriprep/wrapper/
Expand Down Expand Up @@ -159,8 +159,9 @@ jobs:
export PY3=$(pyenv versions | grep '3\.' |
sed -e 's/.* 3\./3./' -e 's/ .*//')
pyenv local $PY3
pip install hatch
# Get version, update files.
THISVERSION=$( python3 get_version.py )
THISVERSION=$( hatch version )
if [[ ${THISVERSION:0:1} == "0" ]] ; then
echo "WARNING: latest git tag could not be found"
echo "Please, make sure you fetch all tags from upstream with"
Expand All @@ -184,7 +185,7 @@ jobs:
sed -e 's/.* 3\./3./' -e 's/ .*//')
pyenv local $PY3
# Get version, update files.
THISVERSION=$( python3 get_version.py )
THISVERSION=$( hatch version )
BUILT_VERSION=$( docker run --rm nipreps/fmriprep:latest --version )
BUILT_VERSION=${BUILT_VERSION%$'\r'}
BUILT_VERSION=${BUILT_VERSION#*"fMRIPrep v"}
Expand Down Expand Up @@ -312,7 +313,7 @@ jobs:
command: |
mkdir -p /tmp/fslicense
cd /tmp/fslicense
echo "${FS_LICENSE_CONTENT}" | base64 -d | sh
echo "cHJpbnRmICJrcnp5c3p0b2YuZ29yZ29sZXdza2lAZ21haWwuY29tXG41MTcyXG4gKkN2dW12RVYzelRmZ1xuRlM1Si8yYzFhZ2c0RVxuIiA+IGxpY2Vuc2UudHh0Cg==" | base64 -d | sh
- run:
name: Create Nipype config files
command: |
Expand Down Expand Up @@ -363,28 +364,36 @@ jobs:
--pyargs fmriprep -svx --doctest-modules
- run:
name: Test fmriprep-wrapper (Python 2)
name: Build fmriprep-docker wheel
command: |
export PY2=$(pyenv versions | grep '2\.' |
sed -e 's/.* 2\./2./' -e 's/ .*//')
pyenv local $PY2
export PY3=$(pyenv versions | grep '3\.' |
sed -e 's/.* 3\./3./' -e 's/ .*//')
pyenv local $PY3
pip install --upgrade pip build
python -m build wrapper/
- run:
name: Install and test fmriprep-docker (Python 3)
command: |
export PY3=$(pyenv versions | grep '3\.' |
sed -e 's/.* 3\./3./' -e 's/ .*//')
pyenv local $PY3
echo -n "Python version: "
python --version
pip install --upgrade "pip<21" "setuptools<45"
pip install --upgrade wrapper/
pip install wrapper/dist/*.whl
which fmriprep-docker
fmriprep-docker -i nipreps/fmriprep:latest --help
fmriprep-docker -i nipreps/fmriprep:latest --version
- run:
name: Test fmriprep-wrapper (Python 3)
name: Install and test fmriprep-docker (Python 2)
command: |
export PY3=$(pyenv versions | grep '3\.' |
sed -e 's/.* 3\./3./' -e 's/ .*//')
pyenv local $PY3
export PY2=$(pyenv versions | grep '2\.' |
sed -e 's/.* 2\./2./' -e 's/ .*//')
pyenv local $PY2
echo -n "Python version: "
python --version
pip install --upgrade pip setuptools
pip install --upgrade wrapper/
pip install --upgrade "pip<21"
pip install wrapper/dist/*.whl
which fmriprep-docker
fmriprep-docker -i nipreps/fmriprep:latest --help
fmriprep-docker -i nipreps/fmriprep:latest --version
Expand Down Expand Up @@ -911,7 +920,7 @@ jobs:
- checkout
- run:
name: Update build tools
command: python -m pip install --user pip build twine
command: pip install --upgrade build twine hatch
- run:
name: Build fMRIPrep
command: python -m build
Expand All @@ -920,8 +929,8 @@ jobs:
- run:
name: Check sdist distribution
command: |
THISVERSION=$( python get_version.py )
THISVERSION=${THISVERSION%.dirty*}
THISVERSION=$( hatch version )
THISVERSION=${THISVERSION%.d*}
THISVERSION=${CIRCLE_TAG:-$THISVERSION}
python -m twine check dist/fmriprep*.tar.gz
virtualenv --python=python sdist
Expand All @@ -938,8 +947,8 @@ jobs:
- run:
name: Check wheel distribution
command: |
THISVERSION=$( python get_version.py )
THISVERSION=${THISVERSION%.dirty*}
THISVERSION=$( hatch version )
THISVERSION=${THISVERSION%.d*}
THISVERSION=${CIRCLE_TAG:-$THISVERSION}
python -m twine check dist/fmriprep*.whl
virtualenv --python=python wheel
Expand All @@ -954,11 +963,7 @@ jobs:
test "$INSTALLED_VERSION" = "$THISVERSION"
- run:
name: Build fmriprep-docker
command: |
THISVERSION=$( python get_version.py )
THISVERSION=${THISVERSION%.dirty*}
sed -i -E "s/(__version__ = )'[A-Za-z0-9.-]+'/\1'${CIRCLE_TAG:-$THISVERSION}'/" wrapper/fmriprep_docker.py
python -m build wrapper/
command: python -m build wrapper
- store_artifacts:
path: /tmp/src/fmriprep/wrapper/dist

Expand All @@ -968,21 +973,16 @@ jobs:
- checkout
- run:
name: Update build tools
command: python -m pip install --user build twine
command: pip install --upgrade build twine
- run:
name: Build fMRIPrep
command: python -m build
- run:
name: Build fmriprep-docker
command: |
THISVERSION=$( python get_version.py )
THISVERSION=${THISVERSION%.dirty*}
sed -i -E "s/(__version__ = )'[A-Za-z0-9.-]+'/\1'${CIRCLE_TAG:-$THISVERSION}'/" wrapper/fmriprep_docker.py
python -m build wrapper/
command: python -m build wrapper/
- run:
name: Upload packages to PyPI
command: |
python -m twine upload dist/fmriprep* wrapper/dist/fmriprep*
command: python -m twine upload dist/fmriprep* wrapper/dist/fmriprep*

deployable:
docker:
Expand All @@ -1005,8 +1005,6 @@ workflows:
only: /.*/

- get_data:
context:
- fs-license
filters:
branches:
ignore:
Expand Down
4 changes: 4 additions & 0 deletions .git_archival.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
node: $Format:%H$
node-date: $Format:%cI$
describe-name: $Format:%(describe:tags=true,match=*[0-9]*)$
ref-names: $Format:%D$
2 changes: 1 addition & 1 deletion .gitattributes
Original file line number Diff line number Diff line change
@@ -1 +1 @@
fmriprep/_version.py export-subst
.git_archival.txt export-subst
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -79,3 +79,5 @@ secrets.py
local_settings.py

*.swp

_version.py
6 changes: 1 addition & 5 deletions .maint/ci/install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,7 @@ if [ -n "$EXTRA_PIP_FLAGS" ]; then
EXTRA_PIP_FLAGS=${!EXTRA_PIP_FLAGS}
fi

if [ "$INSTALL_TYPE" == "setup" ]; then
python setup.py install
else
pip install $EXTRA_PIP_FLAGS $ARCHIVE
fi
pip install $EXTRA_PIP_FLAGS $ARCHIVE

# Basic import check
python -c 'import fmriprep; print(fmriprep.__version__)'
Expand Down
1 change: 1 addition & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
exclude: ".*/data/.*"
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v2.4.0
Expand Down
3 changes: 3 additions & 0 deletions .readthedocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ build:
os: ubuntu-22.04
tools:
python: "3.10"
jobs:
post_checkout:
- git fetch --unshallow

python:
install:
Expand Down
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
#
# MIT License
#
# Copyright (c) 2022 The NiPreps Developers
# Copyright (c) 2023 The NiPreps Developers
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
Expand Down
5 changes: 0 additions & 5 deletions MANIFEST.in

This file was deleted.

2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,4 @@ docker-build:
docker build --rm -t $(tag) \
--build-arg BUILD_DATE=`date -u +"%Y-%m-%dT%H:%M:%SZ"` \
--build-arg VCS_REF=`git rev-parse --short HEAD` \
--build-arg VERSION=`python get_version.py` .
--build-arg VERSION=`hatch version` .
18 changes: 0 additions & 18 deletions NOTICE

This file was deleted.

1 change: 1 addition & 0 deletions NOTICE
4 changes: 2 additions & 2 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -140,13 +140,13 @@ and some conference posters:

License information
-------------------
*fMRIPrep* adheres to the
*fMRIPrep* adheres to the
`general licensing guidelines <https://www.nipreps.org/community/licensing/>`__
of the *NiPreps framework*.

License
~~~~~~~
Copyright (c) 2022, the *NiPreps* Developers.
Copyright (c) 2023, the *NiPreps* Developers.

As of the 21.0.x pre-release and release series, *fMRIPrep* is
licensed under the Apache License, Version 2.0 (the "License");
Expand Down
6 changes: 3 additions & 3 deletions docs/license.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ projects of the framework.

License information
-------------------
Copyright (c) 2022, the *NiPreps* Developers.
Copyright (c) 2023, the *NiPreps* Developers.

As of the 21.0.x pre-release and release series, *fMRIPrep* is
licensed under the Apache License, Version 2.0 (the "License");
Expand All @@ -20,7 +20,7 @@ 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.

Copyright (c) 2015-2022, the *fMRIPrep* developers and the CRN.
Copyright (c) 2015-2023, the *fMRIPrep* developers and the CRN.
All rights reserved.

*fMRIPrep* 20.2 series and earlier are
Expand All @@ -32,7 +32,7 @@ All trademarks referenced herein are property of their respective holders.

The ``fmriprep-wrapper`` for Docker
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Copyright (c) 2020-2022, the *NiPreps* Developers.
Copyright (c) 2020-2023, the *NiPreps* Developers.
Copyright (c) 2015-2020, the *fMRIPrep* developers and the CRN.
All rights reserved.

Expand Down
11 changes: 6 additions & 5 deletions fmriprep/__about__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: nil -*-
# vi: set ft=python sts=4 ts=4 sw=4 et:
#
# Copyright 2022 The NiPreps Developers <nipreps@gmail.com>
# Copyright 2023 The NiPreps Developers <nipreps@gmail.com>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
Expand All @@ -21,13 +21,14 @@
# https://www.nipreps.org/community/licensing/
#
"""Base module variables."""
from ._version import get_versions

__version__ = get_versions()['version']
del get_versions
try:
from ._version import __version__
except ImportError:
__version__ == "0+unknown"

__packagename__ = 'fmriprep'
__copyright__ = 'Copyright 2022, The NiPreps Developers'
__copyright__ = 'Copyright 2023, The NiPreps Developers'
__credits__ = (
'Contributors: please check the ``.zenodo.json`` file at the top-level folder'
'of the repository'
Expand Down
2 changes: 1 addition & 1 deletion fmriprep/__main__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: nil -*-
# vi: set ft=python sts=4 ts=4 sw=4 et:
#
# Copyright 2022 The NiPreps Developers <nipreps@gmail.com>
# Copyright 2023 The NiPreps Developers <nipreps@gmail.com>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
Expand Down
Loading

0 comments on commit 09efab5

Please sign in to comment.