Skip to content

Commit

Permalink
SDK: Bump required Python version to >= 3.9, Add version CI check
Browse files Browse the repository at this point in the history
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).
  • Loading branch information
s-heppner committed Nov 14, 2024
1 parent 49d3bd0 commit 6a051f9
Show file tree
Hide file tree
Showing 5 changed files with 151 additions and 11 deletions.
52 changes: 42 additions & 10 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,47 @@ name: ci
on: [push, pull_request]

env:
X_PYTHON_VERSION: "3.12"
X_PYTHON_MIN_VERSION: "3.9"
X_PYTHON_MAX_VERSION: "3.13"

jobs:
check-python-versions:
# This job checks that the Python Versions we support match and are not End of Life
runs-on: ubuntu-latest
defaults:
run:
working-directory: ./etc/scripts
steps:
- uses: actions/checkout@v2
- name: Set up Python ${{ env.X_PYTHON_MIN_VERSION }}
uses: actions/setup-python@v2
with:
python-version: ${{ env.X_PYTHON_MIN_VERSION }}
- name: Install Python dependencies
run: |
python -m pip install --upgrade pip
pip install -r ./check_python_versions_requirements.txt
- name: Check Supported Python Versions
run: |
python check_python_versions_supported.py \
${{ env.X_PYTHON_MIN_VERSION }} \
${{ env.X_PYTHON_MAX_VERSION }}
- name: Check Python Versions coincide with the SDKs pyproject.toml
run: |
python check_python_versions_coincide.py \
../../sdk/pyproject.toml \
${{ env.X_PYTHON_MIN_VERSION }} \
${{ env.X_PYTHON_MAX_VERSION }}
# Todo: Check other pyproject.toml here as well, as we add them

sdk-test:
# This job runs the unittests on the python versions specified down at the matrix
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.8", "3.10", "3.12"]
python-version: [${{ env.X_PYTHON_MIN_VERSION }}, ${{ env.X_PYTHON_MAX_VERSION }}]
env:
COUCHDB_ADMIN_PASSWORD: "yo0Quai3"
# (2024-10-11, s-heppner)
Expand Down Expand Up @@ -65,10 +97,10 @@ jobs:
working-directory: ./sdk
steps:
- uses: actions/checkout@v2
- name: Set up Python ${{ env.X_PYTHON_VERSION }}
- name: Set up Python ${{ env.X_PYTHON_MIN_VERSION }}
uses: actions/setup-python@v2
with:
python-version: ${{ env.X_PYTHON_VERSION }}
python-version: ${{ env.X_PYTHON_MIN_VERSION }}
- name: Install Python dependencies
run: |
python -m pip install --upgrade pip
Expand All @@ -88,10 +120,10 @@ jobs:
working-directory: ./sdk
steps:
- uses: actions/checkout@v2
- name: Set up Python ${{ env.X_PYTHON_VERSION }}
- name: Set up Python ${{ env.X_PYTHON_MIN_VERSION }}
uses: actions/setup-python@v2
with:
python-version: ${{ env.X_PYTHON_VERSION }}
python-version: ${{ env.X_PYTHON_MIN_VERSION }}
- name: Install Python dependencies
run: |
python -m pip install --upgrade pip
Expand All @@ -114,10 +146,10 @@ jobs:
working-directory: ./sdk
steps:
- uses: actions/checkout@v2
- name: Set up Python ${{ env.X_PYTHON_VERSION }}
- name: Set up Python ${{ env.X_PYTHON_MIN_VERSION }}
uses: actions/setup-python@v2
with:
python-version: ${{ env.X_PYTHON_VERSION }}
python-version: ${{ env.X_PYTHON_MIN_VERSION }}
- name: Install Python dependencies
run: |
python -m pip install --upgrade pip
Expand All @@ -135,10 +167,10 @@ jobs:
working-directory: ./sdk
steps:
- uses: actions/checkout@v2
- name: Set up Python ${{ env.X_PYTHON_VERSION }}
- name: Set up Python ${{ env.X_PYTHON_MIN_VERSION }}
uses: actions/setup-python@v2
with:
python-version: ${{ env.X_PYTHON_VERSION }}
python-version: ${{ env.X_PYTHON_MIN_VERSION }}
- name: Install dependencies
run: |
python -m pip install --upgrade pip
Expand Down
46 changes: 46 additions & 0 deletions etc/scripts/check_python_versions_coincide.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
"""
This helper script checks if the Python versions defined in a `pyproject.toml` coincide with the given `min_version`
and `max_version` and returns an error if they don't.
"""
import re
import argparse
import sys
from packaging.version import Version, InvalidVersion

def main(pyproject_toml_path: str, min_version: str, max_version: str) -> None:
# Load and check `requires-python` version from `pyproject.toml`
try:
with open(pyproject_toml_path, "r") as f:
pyproject_content = f.read()

match = re.search(r'requires-python\s*=\s*">=([\d.]+)"', pyproject_content)
if not match:
print(f"Error: `requires-python` field not found or invalid format in `{pyproject_toml_path}`")
sys.exit(1)

pyproject_version = match.group(1)
if Version(pyproject_version) < Version(min_version):
print(f"Error: Python version in `{pyproject_toml_path}` `requires-python` ({pyproject_version}) "
f"is smaller than `min_version` ({min_version}).")
sys.exit(1)

except FileNotFoundError:
print(f"Error: File not found: `{pyproject_toml_path}`.")
sys.exit(1)

print(f"Success: Version in pyproject.toml `requires-python` (>={pyproject_version}) "
f"matches expected versions ([{min_version} to {max_version}]).")


if __name__ == "__main__":
parser = argparse.ArgumentParser(description="Check Python version support and alignment with pyproject.toml.")
parser.add_argument("pyproject_toml_path", help="Path to the `pyproject.toml` file to check.")
parser.add_argument("min_version", help="The minimum Python version.")
parser.add_argument("max_version", help="The maximum Python version.")
args = parser.parse_args()

try:
main(args.pyproject_toml_path, args.min_version, args.max_version)
except InvalidVersion:
print("Error: Invalid version format provided.")
sys.exit(1)
1 change: 1 addition & 0 deletions etc/scripts/check_python_versions_requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
requests>=2.23
61 changes: 61 additions & 0 deletions etc/scripts/check_python_versions_supported.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
"""
This helper script checks that the provided `min_version` and `max_version` are supported and released, respectively,
using the API from the great https://github.com/endoflife-date/endoflife.date project.
"""
import argparse
import sys
import requests
from packaging.version import InvalidVersion
from datetime import datetime

def main(min_version: str, max_version: str) -> None:
# Fetch supported Python versions and check min/max versions
try:
response = requests.get("https://endoflife.date/api/python.json")
response.raise_for_status()
eol_data = response.json()
eol_versions = {entry["cycle"]: {"eol": entry["eol"], "releaseDate": entry["releaseDate"]} for entry in eol_data}

# Get current date to compare with EoL and release dates
current_date = datetime.now().date()

# Check min_version EoL status
min_eol_date = eol_versions.get(min_version, {}).get("eol")
if min_eol_date and datetime.strptime(min_eol_date, "%Y-%m-%d").date() <= current_date:
print(f"Error: min_version {min_version} has reached End-of-Life.")
sys.exit(1)

# Check max_version EoL and release status
max_info = eol_versions.get(max_version)
if max_info:
max_eol_date = max_info["eol"]
max_release_date = max_info["releaseDate"]

# Check if max_version has a release date in the future
if max_release_date and datetime.strptime(max_release_date, "%Y-%m-%d").date() > current_date:
print(f"Error: max_version {max_version} has not been officially released yet.")
sys.exit(1)

# Check if max_version has reached EoL
if max_eol_date and datetime.strptime(max_eol_date, "%Y-%m-%d").date() <= current_date:
print(f"Error: max_version {max_version} has reached End-of-Life.")
sys.exit(1)

except requests.RequestException:
print("Error: Failed to fetch Python version support data.")
sys.exit(1)

print(f"Version check passed: min_version [{min_version}] is supported "
f"and max_version [{max_version}] is released.")

if __name__ == "__main__":
parser = argparse.ArgumentParser(description="Check Python version support and alignment with pyproject.toml.")
parser.add_argument("min_version", help="The minimum Python version.")
parser.add_argument("max_version", help="The maximum Python version.")
args = parser.parse_args()

try:
main(args.min_version, args.max_version)
except InvalidVersion:
print("Error: Invalid version format provided.")
sys.exit(1)
2 changes: 1 addition & 1 deletion sdk/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ classifiers = [
"Operating System :: OS Independent",
"Development Status :: 5 - Production/Stable"
]
requires-python = ">=3.8"
requires-python = ">=3.9"
dependencies = [
"jsonschema~=4.7",
"lxml>=4.2,<5",
Expand Down

0 comments on commit 6a051f9

Please sign in to comment.