Skip to content

Commit 82512b1

Browse files
authoredOct 25, 2024
Merge pull request #185 from casparvl/setuptools_scm_versioning
Add setuptools_scm for pyproject.toml, setup.cfg and setup.py
2 parents f321fc5 + cbefb7a commit 82512b1

File tree

7 files changed

+395
-4
lines changed

7 files changed

+395
-4
lines changed
 
+126
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
# documentation: https://help.github.com/en/articles/workflow-syntax-for-github-actions
2+
name: Test version for tarball without git metadata
3+
on: [push, pull_request, workflow_dispatch]
4+
permissions: read-all
5+
jobs:
6+
test_versioning_from_tarball:
7+
# ubuntu <= 20.04 is required for python 3.6
8+
runs-on: ubuntu-20.04
9+
strategy:
10+
fail-fast: false
11+
matrix:
12+
python-version: ['3.6', '3.7', '3.8', '3.9', '3.10', '3.11']
13+
steps:
14+
# - name: Check out repository
15+
# uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
16+
# with:
17+
# persist-credentials: false
18+
# fetch-depth: 0
19+
20+
- name: Set up Python
21+
uses: actions/setup-python@61a6322f88396a6271a6ee3565807d608ecaddd1 # v4.7.0
22+
with:
23+
python-version: ${{ matrix.python-version }}
24+
25+
- name: Install setuptools
26+
run: |
27+
if [[ "${{ matrix.python-version }}" == "3.6" ]]; then
28+
# system installed setuptools version in RHEL8 and CO7
29+
python -m pip install --user setuptools==39.2.0
30+
fi
31+
32+
- name: Install setuptools_scm
33+
run: |
34+
if [[ "${{ matrix.python-version }}" == "3.6" ]]; then
35+
python -m pip install --user 'setuptools_scm>=4.0.0,<=4.1.2'
36+
else
37+
python -m pip install --user setuptools_scm
38+
fi
39+
40+
- name: Check python and setuptools versions
41+
run: |
42+
python --version
43+
python -m pip --version
44+
python -c 'import setuptools; print("setuptools", setuptools.__version__)'
45+
python -m pip show setuptools_scm | grep Version
46+
47+
- name: Download and extract tarball for current commit
48+
run: |
49+
wget "$GITHUB_SERVER_URL/$GITHUB_REPOSITORY/archive/$GITHUB_SHA.tar.gz"
50+
tar -xzf "$GITHUB_SHA.tar.gz"
51+
# Check current directory contents
52+
find .
53+
54+
- name: Check version when running against uninstalled git clone
55+
run: |
56+
echo "importing eessi.testsuite from:"
57+
original_pythonpath=$PYTHONPATH
58+
export PYTHONPATH="$PWD/test-suite-$GITHUB_SHA:$PYTHONPATH"
59+
echo "PYTHONPATH: $PYTHONPATH"
60+
python3 -c "import eessi.testsuite; print(eessi.testsuite.__file__)"
61+
62+
uninstalled_version=$(python3 -c "import eessi.testsuite; print(eessi.testsuite.__version__)")
63+
echo "Version from uninstalled git clone: $uninstalled_version"
64+
fallback_version=$(grep -oP 'fallback_version\s*=\s*"\K[^"]+' "test-suite-$GITHUB_SHA/pyproject.toml")
65+
66+
echo "Testing if this version is the fallback version from pyproject.toml ..."
67+
if [[ "$uninstalled_version" != "$fallback_version" ]]; then
68+
echo "Version $uninstalled_version not equal to $fallback_version"
69+
exit 1
70+
else
71+
echo "... yes!"
72+
fi
73+
74+
export PYTHONPATH="$original_pythonpath"
75+
76+
- name: Install from extracted tarball
77+
run: |
78+
# Make sure we get the fallback version from the pyprject.toml before changing workdir
79+
fallback_version=$(grep -oP 'fallback_version\s*=\s*"\K[^"]+' "test-suite-$GITHUB_SHA/pyproject.toml")
80+
81+
# Make it easier to figure out CI issues in case of CI failures related to SCM versioning
82+
export SETUPTOOLS_SCM_DEBUG=1
83+
84+
# Change dir to the extracted tarball
85+
cd "test-suite-$GITHUB_SHA"
86+
87+
python -m pip install . --user
88+
89+
echo "Checking contents of .local"
90+
find $HOME/.local
91+
92+
# make sure we are not in the source directory
93+
cd $HOME
94+
95+
echo "Checking if file 'eessi/testsuite/_version.py' was generated by setuptools_scm":
96+
cat $HOME/.local/lib/python${{ matrix.python-version}}/site-packages/eessi/testsuite/_version.py
97+
98+
echo "Checking if version can be imported directly from the version file"
99+
if [[ "${{ matrix.python-version }}" == "3.6" ]]; then
100+
versionfile_version=$(python -c 'from eessi.testsuite._version import version; print(version)')
101+
else
102+
versionfile_version=$(python -c 'from eessi.testsuite._version import __version__; print(__version__)')
103+
fi
104+
echo "Version from version file: $versionfile_version"
105+
106+
echo "Checking if we can import the __version__ from eessi.testsuite"
107+
installed_version=$(python -c 'import eessi.testsuite; print(eessi.testsuite.__version__)')
108+
echo "Version from installed testsuite: $installed_version"
109+
110+
# Read the fallback version from the pyproject.toml
111+
echo "Testing if this is the fallback version from pyproject.toml ..."
112+
if [[ "$installed_version" != "$fallback_version" ]]; then
113+
echo "Version $installed_version not equal to $fallback_version"
114+
exit 1
115+
else
116+
echo "... yes!"
117+
fi
118+
119+
echo "Checking if the version imported from eessi.testsuite matches that from the version file ..."
120+
if [[ "$versionfile_version" != "$installed_version" ]]; then
121+
echo "Version $versionfile_version not equal to $installed_version"
122+
exit 1
123+
else
124+
echo "... yes!"
125+
fi
126+

‎.github/workflows/check_versions.yml

+47
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
# documentation: https://help.github.com/en/articles/workflow-syntax-for-github-actions
2+
name: Test fallback_version and version in run_reframe.sh against tags
3+
on: [push, pull_request, workflow_dispatch]
4+
permissions: read-all
5+
jobs:
6+
test_fallback_version_against_tags:
7+
# ubuntu <= 20.04 is required for python 3.6
8+
runs-on: ubuntu-20.04
9+
strategy:
10+
fail-fast: false
11+
steps:
12+
- name: Check out repository
13+
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
14+
with:
15+
persist-credentials: false
16+
fetch-depth: 0
17+
18+
- name: Check fallback version and version used in run_reframe.sh
19+
run: |
20+
# Get fallback version
21+
fallback_version=$(grep -oP 'fallback_version\s*=\s*"\K[^"]+' "pyproject.toml")
22+
# Prepend fallback version with 'v', as that is also the case for the other two version strings
23+
fallback_version="v$fallback_version"
24+
25+
# Get version from run_reframe.sh
26+
run_reframe_testsuite_version=$(grep -oP 'EESSI_TESTSUITE_BRANCH\s*=\s*[^v]*\K[^"\x27]*' "CI/run_reframe.sh")
27+
28+
# Grab the tag for the highest version, by sorting by (semantic) version, and then filtering on patterns
29+
# that match a pattern like v0.1.2. Finally, we grab the last to get the highest version
30+
most_recent_version=$(git tag --sort=version:refname | grep -P "v[0-9]+\.[0-9]+\.[0-9]+" | tail -n 1)
31+
32+
echo "Testing if fallback version and EESSI_TESTSUITE_BRANCH version in CI/run_reframe.sh are the same"
33+
if [[ "$fallback_version" != "$run_reframe_testsuite_version" ]]; then
34+
echo "Version $fallback_version not equal to $run_reframe_testsuite_version"
35+
exit 1
36+
else
37+
echo "... yes!"
38+
fi
39+
40+
echo "Testing if fallback version and most recent version tag are the same"
41+
if [[ "$fallback_version" != "$most_recent_version" ]]; then
42+
echo "Version $fallback_version not equal to $most_recent_version"
43+
exit 1
44+
else
45+
echo "... yes!"
46+
fi
47+

‎.github/workflows/pip_install.yml

+86
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ jobs:
1515
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
1616
with:
1717
persist-credentials: false
18+
fetch-depth: 0
1819

1920
- name: Set up Python
2021
uses: actions/setup-python@61a6322f88396a6271a6ee3565807d608ecaddd1 # v4.7.0
@@ -34,12 +35,18 @@ jobs:
3435
3536
- name: Install EESSI test suite with 'pip install'
3637
run: |
38+
# Make it easier to figure out CI issues in case of CI failures related to SCM versioning
39+
export SETUPTOOLS_SCM_DEBUG=1
3740
# install from source distribution tarball, to test release as published on PyPI
3841
rm -rf dist
42+
echo "Running python setup.py sdist"
3943
python setup.py sdist
4044
ls dist
4145
46+
echo "Running python -m pip install --user dist/eessi*.tar.gz"
4247
python -m pip install --user dist/eessi*.tar.gz
48+
49+
echo "Checking contents of .local"
4350
find $HOME/.local
4451
4552
# make sure we are not in the source directory
@@ -49,5 +56,84 @@ jobs:
4956
python -m pip --version
5057
python -c 'import setuptools; print("setuptools", setuptools.__version__)'
5158
59+
echo "Checking if file 'eessi/testsuite/_version.py' was generated by setuptools_scm":
60+
cat $HOME/.local/lib/python${{ matrix.python-version}}/site-packages/eessi/testsuite/_version.py
61+
62+
echo "Checking if version can be imported directly from the version file"
63+
if [[ "${{ matrix.python-version }}" == "3.6" ]]; then
64+
versionfile_version=$(python -c 'from eessi.testsuite._version import version; print(version)')
65+
else
66+
versionfile_version=$(python -c 'from eessi.testsuite._version import __version__; print(__version__)')
67+
fi
68+
echo "Version from version file: $versionfile_version"
69+
70+
echo "Checking if we can import the __version__ from eessi.testsuite"
71+
testsuite_version=$(python -c 'import eessi.testsuite; print(eessi.testsuite.__version__)')
72+
echo "Version imported from eessi.testsuite: $testsuite_version"
73+
74+
echo "Checking if the version imported from eessi.testsuite matches that from the version file ..."
75+
if [[ "$versionfile_version" != "$testsuite_version" ]]; then
76+
echo "Version $versionfile_version not equal to $testsuite_version"
77+
exit 1
78+
else
79+
echo "... yes!"
80+
fi
81+
82+
echo "Checking if we can import eessi.testsuite.utils"
83+
python -c 'import eessi.testsuite.utils'
84+
85+
echo "Checking if we can import eessi.testsuite.tests.apps"
86+
python -c 'import eessi.testsuite.tests.apps'
87+
88+
89+
- name: Install EESSI test suite with 'pip install git+https'
90+
run: |
91+
# Get version from the installation in the previous step
92+
testsuite_version=$(python -c 'import eessi.testsuite; print(eessi.testsuite.__version__)')
93+
94+
# Cleanup installation from previous step
95+
echo "Uninstalling testsuite for next step"
96+
python -m pip uninstall -y eessi-testsuite
97+
98+
pip install --user "git+$GITHUB_SERVER_URL/$GITHUB_REPOSITORY.git@$GITHUB_SHA"
99+
100+
echo "Checking contents of .local"
101+
find $HOME/.local
102+
103+
echo "Checking if file 'eessi/testsuite/_version.py' was generated by setuptools_scm":
104+
cat $HOME/.local/lib/python${{ matrix.python-version}}/site-packages/eessi/testsuite/_version.py
105+
106+
echo "Checking if version can be imported directly from the version file"
107+
if [[ "${{ matrix.python-version }}" == "3.6" ]]; then
108+
githttps_versionfile_version=$(python -c 'from eessi.testsuite._version import version; print(version)')
109+
else
110+
githttps_versionfile_version=$(python -c 'from eessi.testsuite._version import __version__; print(__version__)')
111+
fi
112+
echo "Version from version file: $githttps_versionfile_version"
113+
114+
echo "Checking if we can import the __version__ from eessi.testsuite"
115+
githttps_testsuite_version=$(python -c 'import eessi.testsuite; print(eessi.testsuite.__version__)')
116+
echo "Version imported from eessi.testsuite: $githttps_testsuite_version"
117+
118+
echo "Checking if the version imported from eessi.testsuite matches that from the version file ..."
119+
if [[ "$githttps_versionfile_version" != "$githttps_testsuite_version" ]]; then
120+
echo "Version $githttps_versionfile_version not equal to $githttps_testsuite_version"
121+
exit 1
122+
else
123+
echo "... yes!"
124+
fi
125+
126+
echo "Checking if the version import from a regular pip install and the git+https based install are the same ..."
127+
if [[ "$githttps_testsuite_version" != "$testsuite_version" ]]; then
128+
echo "Version $githttps_testsuite_version not equal to $testsuite_version"
129+
exit 1
130+
else
131+
echo "... yes!"
132+
fi
133+
134+
echo "Checking if we can import eessi.testsuite.utils"
52135
python -c 'import eessi.testsuite.utils'
136+
137+
echo "Checking if we can import eessi.testsuite.tests.apps"
53138
python -c 'import eessi.testsuite.tests.apps'
139+

‎eessi/testsuite/__init__.py

+83
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
# WARNING: this file is imported in setup.py
2+
# To make sure this works, we should avoid using imports other than from the Python standard library
3+
4+
try:
5+
# If this is an installed package, setuptools_scm will have written the _version.py file in the current directory
6+
from ._version import __version__
7+
except ImportError:
8+
try:
9+
# Setuptools_scm 4.1.2 (compatible with setuptools 39.2.0) write version instead of __version__
10+
# This can be removed once we no longer care about python 3.6 with setuptools 39.2.0
11+
from ._version import version
12+
__version__ = version
13+
except ImportError:
14+
# Fallback for when the package is not installed, but git cloned. Note that this requires setuptools_scm to be
15+
# available as a runtime dependency
16+
# The advantage here is that it will generate development versions if not on a tagged release version
17+
try:
18+
from setuptools_scm import get_version
19+
# Using a relative path for relative_to doesn't work, because it will be relative to the current working
20+
# directory (which could be anywhere)
21+
# __file__ is the location of this init file (a full path), and this gives us a predictable path to the root
22+
# (namely: two levels up). Note that if we ever move this __init__ file relative to the root of the git
23+
# tree, we'll need to adjust this
24+
__version__ = get_version(root='../..', relative_to=__file__)
25+
except (ImportError, LookupError):
26+
# If running from a tarball (e.g. release tarball) downloaded from github, we will not have the .git
27+
# folder available. Thus, setuptools_scm cannot determine the version in any way. Thus, use the
28+
# fallback_version from the pyproject.toml file (which doesn't exist when this is installed as a package,
29+
# but SHOULD exist when this is run from a downloaded tarball from git)
30+
31+
# Pyproject.toml should be two levels up from this file
32+
import os.path
33+
pyproject_toml = "%s/../../pyproject.toml" % os.path.dirname(__file__)
34+
35+
# Variables to track if we're in the right section and to store the fallback_version
36+
in_setuptools_scm_section = False
37+
fallback_version = None
38+
39+
file = None
40+
try:
41+
file = open(pyproject_toml, 'r')
42+
# Open the file and parse it manually
43+
fallback_version = None
44+
with file:
45+
for line in file:
46+
stripped_line = line.strip()
47+
48+
# Check if we're entering the [tool.setuptools_scm] section
49+
if stripped_line == "[tool.setuptools_scm]":
50+
in_setuptools_scm_section = True
51+
elif stripped_line.startswith("[") and in_setuptools_scm_section:
52+
# We've reached a new section, so stop searching
53+
break
54+
55+
# If we're in the right section, look for the fallback_version key
56+
if in_setuptools_scm_section and stripped_line.startswith("fallback_version"):
57+
# Extract the value after the '=' sign and strip any surrounding quotes or whitespace
58+
fallback_version = stripped_line.split('=', 1)[1].strip().strip('"').strip("'")
59+
break
60+
# Account for the possibility that we failed to extract the fallback_version field from pyproject.toml
61+
if fallback_version:
62+
__version__ = fallback_version
63+
else:
64+
msg = "fallback_version not found in file %s" % pyproject_toml
65+
msg += " when trying the get the EESSI test suite version. This should never happen."
66+
msg += " Please report an issue on Github, including information on how you installed"
67+
msg += " the EESSI test suite."
68+
print(msg)
69+
except FileNotFoundError:
70+
msg = "File %s not found when trying to extract the EESSI test suite version from" % pyproject_toml
71+
msg += " pyproject.toml. This should never happen. Please report an issue on GitHub,"
72+
msg += " including information on how you installed the EESSI test suite."
73+
print(msg)
74+
except Exception as e:
75+
print("When trying to open file %s, an exception was raised: %s." % (pyproject_toml, e))
76+
77+
# One of the above three methods to get __version__ defined SHOULD work in any situation.
78+
# It's considered a bug you reach this point without having a __version__ set
79+
if not __version__:
80+
msg = "__version__ should have been defined by now, but it is not."
81+
msg += " This is considered a bug, please report it in an issue on Github for the"
82+
msg += " EESSI test suite."
83+
raise ValueError(msg)

0 commit comments

Comments
 (0)
Failed to load comments.