Skip to content

Commit b91718f

Browse files
committed
SDK: Bump required Python version to >= 3.9, Add version CI check
This bumps the `requires-python` fiels in the `pyproject.toml` of the SDK from `">=3.8"` to `">=3.9"`, due to the fact that Python v3.8 reached EoL on 2024-10-07. Furthermore, to avoid future backward compatibility issues in native Python, as well as to ensure we're always supporting the currently supported Python versions, we add a CI check `check-python-versions` that uses two new scripts in `./etc/scripts` to check: a) our currently supported Python versions to an EoL database b) that our currently supported Python versions defined in the CI match the ones in the `pyproject.toml`. This should ensure that issues like #330 are avoided in the future. (Note that we still need to fix #330 though).
1 parent 49d3bd0 commit b91718f

File tree

5 files changed

+158
-11
lines changed

5 files changed

+158
-11
lines changed

.github/workflows/ci.yml

Lines changed: 48 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,47 @@ name: ci
33
on: [push, pull_request]
44

55
env:
6-
X_PYTHON_VERSION: "3.12"
6+
X_PYTHON_MIN_VERSION: "3.9"
7+
X_PYTHON_MAX_VERSION: "3.13"
78

89
jobs:
10+
check-python-versions:
11+
# This job checks that the Python Versions we support match and are not End of Life
12+
runs-on: ubuntu-latest
13+
defaults:
14+
run:
15+
working-directory: ./etc/scripts
16+
steps:
17+
- uses: actions/checkout@v2
18+
- name: Set up Python ${{ env.X_PYTHON_MIN_VERSION }}
19+
uses: actions/setup-python@v2
20+
with:
21+
python-version: ${{ env.X_PYTHON_MIN_VERSION }}
22+
- name: Install Python dependencies
23+
run: |
24+
python -m pip install --upgrade pip
25+
pip install -r ./check_python_versions_requirements.txt
26+
- name: Check Supported Python Versions
27+
run: |
28+
python check_python_versions_supported.py \
29+
${{ env.X_PYTHON_MIN_VERSION }} \
30+
${{ env.X_PYTHON_MAX_VERSION }}
31+
32+
- name: Check Python Versions coincide with the SDKs pyproject.toml
33+
run: |
34+
python check_python_versions_coincide.py \
35+
../../sdk/pyproject.toml \
36+
${{ env.X_PYTHON_MIN_VERSION }} \
37+
${{ env.X_PYTHON_MAX_VERSION }}
38+
39+
# Todo: Check other pyproject.toml here as well, as we add them
40+
941
sdk-test:
1042
# This job runs the unittests on the python versions specified down at the matrix
1143
runs-on: ubuntu-latest
1244
strategy:
1345
matrix:
14-
python-version: ["3.8", "3.10", "3.12"]
46+
python-version: ["3.9", "3.13"]
1547
env:
1648
COUCHDB_ADMIN_PASSWORD: "yo0Quai3"
1749
# (2024-10-11, s-heppner)
@@ -33,6 +65,12 @@ jobs:
3365
working-directory: ./sdk
3466
steps:
3567
- uses: actions/checkout@v2
68+
- name: Verify Matrix Version matches Global Version
69+
run: |
70+
if [ "${{ matrix.python-version }}" != "${{ env.X_PYTHON_MIN_VERSION }}" ] && [ "${{ matrix.python-version }}" != "${{ env.X_PYTHON_MAX_VERSION }}" ]; then
71+
echo "Error: Matrix version ${{ matrix.python-version }} does not match global version."
72+
exit 1
73+
fi
3674
- name: Set up Python ${{ matrix.python-version }}
3775
uses: actions/setup-python@v2
3876
with:
@@ -65,10 +103,10 @@ jobs:
65103
working-directory: ./sdk
66104
steps:
67105
- uses: actions/checkout@v2
68-
- name: Set up Python ${{ env.X_PYTHON_VERSION }}
106+
- name: Set up Python ${{ env.X_PYTHON_MIN_VERSION }}
69107
uses: actions/setup-python@v2
70108
with:
71-
python-version: ${{ env.X_PYTHON_VERSION }}
109+
python-version: ${{ env.X_PYTHON_MIN_VERSION }}
72110
- name: Install Python dependencies
73111
run: |
74112
python -m pip install --upgrade pip
@@ -88,10 +126,10 @@ jobs:
88126
working-directory: ./sdk
89127
steps:
90128
- uses: actions/checkout@v2
91-
- name: Set up Python ${{ env.X_PYTHON_VERSION }}
129+
- name: Set up Python ${{ env.X_PYTHON_MIN_VERSION }}
92130
uses: actions/setup-python@v2
93131
with:
94-
python-version: ${{ env.X_PYTHON_VERSION }}
132+
python-version: ${{ env.X_PYTHON_MIN_VERSION }}
95133
- name: Install Python dependencies
96134
run: |
97135
python -m pip install --upgrade pip
@@ -114,10 +152,10 @@ jobs:
114152
working-directory: ./sdk
115153
steps:
116154
- uses: actions/checkout@v2
117-
- name: Set up Python ${{ env.X_PYTHON_VERSION }}
155+
- name: Set up Python ${{ env.X_PYTHON_MIN_VERSION }}
118156
uses: actions/setup-python@v2
119157
with:
120-
python-version: ${{ env.X_PYTHON_VERSION }}
158+
python-version: ${{ env.X_PYTHON_MIN_VERSION }}
121159
- name: Install Python dependencies
122160
run: |
123161
python -m pip install --upgrade pip
@@ -135,10 +173,10 @@ jobs:
135173
working-directory: ./sdk
136174
steps:
137175
- uses: actions/checkout@v2
138-
- name: Set up Python ${{ env.X_PYTHON_VERSION }}
176+
- name: Set up Python ${{ env.X_PYTHON_MIN_VERSION }}
139177
uses: actions/setup-python@v2
140178
with:
141-
python-version: ${{ env.X_PYTHON_VERSION }}
179+
python-version: ${{ env.X_PYTHON_MIN_VERSION }}
142180
- name: Install dependencies
143181
run: |
144182
python -m pip install --upgrade pip
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
"""
2+
This helper script checks if the Python versions defined in a `pyproject.toml` coincide with the given `min_version`
3+
and `max_version` and returns an error if they don't.
4+
"""
5+
import re
6+
import argparse
7+
import sys
8+
from packaging.version import Version, InvalidVersion
9+
10+
def main(pyproject_toml_path: str, min_version: str, max_version: str) -> None:
11+
# Load and check `requires-python` version from `pyproject.toml`
12+
try:
13+
with open(pyproject_toml_path, "r") as f:
14+
pyproject_content = f.read()
15+
16+
match = re.search(r'requires-python\s*=\s*">=([\d.]+)"', pyproject_content)
17+
if not match:
18+
print(f"Error: `requires-python` field not found or invalid format in `{pyproject_toml_path}`")
19+
sys.exit(1)
20+
21+
pyproject_version = match.group(1)
22+
if Version(pyproject_version) < Version(min_version):
23+
print(f"Error: Python version in `{pyproject_toml_path}` `requires-python` ({pyproject_version}) "
24+
f"is smaller than `min_version` ({min_version}).")
25+
sys.exit(1)
26+
27+
except FileNotFoundError:
28+
print(f"Error: File not found: `{pyproject_toml_path}`.")
29+
sys.exit(1)
30+
31+
print(f"Success: Version in pyproject.toml `requires-python` (>={pyproject_version}) "
32+
f"matches expected versions ([{min_version} to {max_version}]).")
33+
34+
35+
if __name__ == "__main__":
36+
parser = argparse.ArgumentParser(description="Check Python version support and alignment with pyproject.toml.")
37+
parser.add_argument("pyproject_toml_path", help="Path to the `pyproject.toml` file to check.")
38+
parser.add_argument("min_version", help="The minimum Python version.")
39+
parser.add_argument("max_version", help="The maximum Python version.")
40+
args = parser.parse_args()
41+
42+
try:
43+
main(args.pyproject_toml_path, args.min_version, args.max_version)
44+
except InvalidVersion:
45+
print("Error: Invalid version format provided.")
46+
sys.exit(1)
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
requests>=2.23
2+
packaging>=24.2
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
"""
2+
This helper script checks that the provided `min_version` and `max_version` are supported and released, respectively,
3+
using the API from the great https://github.com/endoflife-date/endoflife.date project.
4+
"""
5+
import argparse
6+
import sys
7+
import requests
8+
from packaging.version import InvalidVersion
9+
from datetime import datetime
10+
11+
def main(min_version: str, max_version: str) -> None:
12+
# Fetch supported Python versions and check min/max versions
13+
try:
14+
response = requests.get("https://endoflife.date/api/python.json")
15+
response.raise_for_status()
16+
eol_data = response.json()
17+
eol_versions = {entry["cycle"]: {"eol": entry["eol"], "releaseDate": entry["releaseDate"]} for entry in eol_data}
18+
19+
# Get current date to compare with EoL and release dates
20+
current_date = datetime.now().date()
21+
22+
# Check min_version EoL status
23+
min_eol_date = eol_versions.get(min_version, {}).get("eol")
24+
if min_eol_date and datetime.strptime(min_eol_date, "%Y-%m-%d").date() <= current_date:
25+
print(f"Error: min_version {min_version} has reached End-of-Life.")
26+
sys.exit(1)
27+
28+
# Check max_version EoL and release status
29+
max_info = eol_versions.get(max_version)
30+
if max_info:
31+
max_eol_date = max_info["eol"]
32+
max_release_date = max_info["releaseDate"]
33+
34+
# Check if max_version has a release date in the future
35+
if max_release_date and datetime.strptime(max_release_date, "%Y-%m-%d").date() > current_date:
36+
print(f"Error: max_version {max_version} has not been officially released yet.")
37+
sys.exit(1)
38+
39+
# Check if max_version has reached EoL
40+
if max_eol_date and datetime.strptime(max_eol_date, "%Y-%m-%d").date() <= current_date:
41+
print(f"Error: max_version {max_version} has reached End-of-Life.")
42+
sys.exit(1)
43+
44+
except requests.RequestException:
45+
print("Error: Failed to fetch Python version support data.")
46+
sys.exit(1)
47+
48+
print(f"Version check passed: min_version [{min_version}] is supported "
49+
f"and max_version [{max_version}] is released.")
50+
51+
if __name__ == "__main__":
52+
parser = argparse.ArgumentParser(description="Check Python version support and alignment with pyproject.toml.")
53+
parser.add_argument("min_version", help="The minimum Python version.")
54+
parser.add_argument("max_version", help="The maximum Python version.")
55+
args = parser.parse_args()
56+
57+
try:
58+
main(args.min_version, args.max_version)
59+
except InvalidVersion:
60+
print("Error: Invalid version format provided.")
61+
sys.exit(1)

sdk/pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ classifiers = [
3434
"Operating System :: OS Independent",
3535
"Development Status :: 5 - Production/Stable"
3636
]
37-
requires-python = ">=3.8"
37+
requires-python = ">=3.9"
3838
dependencies = [
3939
"jsonschema~=4.7",
4040
"lxml>=4.2,<5",

0 commit comments

Comments
 (0)