Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions .github/workflows/test_tox.yml
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,16 @@ jobs:
posargs: 'PyPy'
pytest: false

test_supported_pythons:
uses: ./.github/workflows/tox.yml
with:
envs: |
- linux: pep8
- linux: py3
fill: true
fill_platforms: linux,macos
pytest: false

test_libraries:
uses: ./.github/workflows/tox.yml
with:
Expand Down
34 changes: 32 additions & 2 deletions .github/workflows/tox.yml

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -203,3 +203,6 @@ $RECYCLE.BIN/
### Pycharm
.idea
.history

# packaging
uv.lock
95 changes: 95 additions & 0 deletions tools/supported_pythons.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
# /// script
# requires-python = ">=3.12"
# dependencies = [
# "click==8.2.1",
# "peppyproject==1.0.2",
# "requests==2.32.5",
# "packaging==25.0",
# ]
# ///
import os
import warnings
from pathlib import Path

import click
import requests
from packaging.specifiers import SpecifierSet
from packaging.version import Version
from peppyproject import PyProjectConfiguration


@click.command()
@click.option("--source", default=None)
@click.option("--factors", default=None)
@click.option("--no-eoas", is_flag=True, default=False)
@click.option("--platforms", default=None)
def supported_python_envs_block(
source: Path = None,
factors: list[str] = None,
no_eoas: bool = False,
platforms: list[str] = None,
):
"""enumerate toxenvs Python from a package source"""

if platforms is None:
platforms = ["linux"]
elif isinstance(platforms, str):
platforms = platforms.split(",")

toxenvs = supported_python_toxenvs(source, factors, no_eoas)
envs_block = "\\n".join(
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

escaping the \n was necessary to get the multi-line block to correctly insert into a single line of GITHUB_OUTPUT, but it requires unpacking the \\ns later in tox_matrix.py which feels icky

f"- {platform}: {toxenv}" for platform in platforms for toxenv in toxenvs
)

print(envs_block)
with open(os.environ["GITHUB_OUTPUT"], "a") as f:
f.write(f"envs={envs_block}\n")


def supported_python_toxenvs(
source: Path = None,
factors: list[str] = None,
no_eoas: bool = False,
) -> list[str]:
if isinstance(factors, str):
factors = factors.split(",")

current_pythons = current_python_versions(no_eoas=no_eoas)

if source is None or source == "":
supported_pythons = current_pythons
else:
configuration = PyProjectConfiguration.from_directory(source)
try:
python_requirements = SpecifierSet(configuration["project"]["requires-python"])

supported_pythons = [
python for python in current_pythons if python in python_requirements
]
except (KeyError, TypeError):
warnings.warn(
"could not find `requires-python` in metadata; falling back to current Python versions..."
)
supported_pythons = current_pythons

return [
f"py{str(python).replace('.', '')}{'-' + '-'.join(factors) if factors is not None and len(factors) > 0 else ''}"
for python in supported_pythons
]


def current_python_versions(no_eoas: bool = False) -> list[Version]:
url = "https://endoflife.date/api/v1/products/python"
response = requests.get("https://endoflife.date/api/v1/products/python")
if response.status_code == 200:
return [
Version(python["name"])
for python in response.json()["result"]["releases"]
if not python["isEoas" if no_eoas else "isEol"]
]
else:
raise ValueError(f"request returned status code {response.status_code} [{url}]")


if __name__ == "__main__":
supported_python_envs_block()
2 changes: 1 addition & 1 deletion tools/tox_matrix.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ def load_tox_targets(envs, libraries, posargs, toxdeps, toxargs, pytest, pytest_
cache_restore_keys, artifact_path, runs_on, default_python, timeout_minutes):
"""Script to load tox targets for GitHub Actions workflow."""
# Load envs config
envs = yaml.load(envs, Loader=yaml.BaseLoader)
envs = yaml.load(envs.replace("\\n", "\n"), Loader=yaml.BaseLoader)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

here's where the aforementioned \\ns are unpacked

print(json.dumps(envs, indent=2))

# Load global libraries config
Expand Down
1 change: 1 addition & 0 deletions update_scripts_in_yml.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,4 @@ def base64_encode_into(script, yml_file, env_var):
base64_encode_into('set_env.py', 'tox.yml', 'SET_ENV_SCRIPT')
base64_encode_into('set_env.py', 'publish.yml', 'SET_ENV_SCRIPT')
base64_encode_into('set_env.py', 'publish_pure_python.yml', 'SET_ENV_SCRIPT')
base64_encode_into('supported_pythons.py', 'tox.yml', 'SUPPORTED_PYTHONS_SCRIPT')