From db2f54bf25c886313ae7852dcb668c4891137898 Mon Sep 17 00:00:00 2001 From: Remco de Boer <29308176+redeboer@users.noreply.github.com> Date: Tue, 11 Jul 2023 10:29:06 +0200 Subject: [PATCH] FIX: support `pyproject` in pytest job matrix (#30) --- create-pytest-matrix/action.yml | 2 ++ create-pytest-matrix/main.py | 60 ++++++++++++++++++++++++++------- 2 files changed, 50 insertions(+), 12 deletions(-) diff --git a/create-pytest-matrix/action.yml b/create-pytest-matrix/action.yml index fddba298..b8f888eb 100644 --- a/create-pytest-matrix/action.yml +++ b/create-pytest-matrix/action.yml @@ -35,6 +35,8 @@ runs: - uses: actions/setup-python@v4 with: python-version: "3.8" + - run: pip install toml + shell: bash - id: set-matrix name: Create run matrix in JSON form run: | diff --git a/create-pytest-matrix/main.py b/create-pytest-matrix/main.py index 6ec8c59e..b329f276 100644 --- a/create-pytest-matrix/main.py +++ b/create-pytest-matrix/main.py @@ -3,10 +3,13 @@ from __future__ import annotations import json +import os from argparse import ArgumentParser from configparser import ConfigParser from typing import Sequence +import toml + def main(argv: Sequence[str] | None = None) -> int: parser = ArgumentParser(__doc__) @@ -91,24 +94,57 @@ def create_job_matrix( return matrix +PYPROJECT_TOML = "pyproject.toml" +SETUP_CFG = "setup.cfg" +CLASSIFIERS_ERROR_MSG = ( + "This package does not have Python version classifiers, so cannot determine" + " intended Python versions. See https://pypi.org/classifiers." +) +VERSION_IDENTIFIER = "Programming Language :: Python :: 3." + + def get_supported_python_versions() -> list[str]: + classifiers = _get_classifiers() + return _determine_python_versions(classifiers) + + +def _get_classifiers() -> list[str]: + if os.path.exists(SETUP_CFG): + return __get_classifiers_from_cfg(SETUP_CFG) + if os.path.exists(PYPROJECT_TOML): + return __get_classifiers_from_toml(PYPROJECT_TOML) + msg = f"This project does not contain a {SETUP_CFG} or {PYPROJECT_TOML}" + raise FileNotFoundError(msg) + + +def __get_classifiers_from_cfg(path: str) -> list[str]: cfg = ConfigParser() - cfg.read("setup.cfg") + cfg.read(path) if not cfg.has_option("metadata", "classifiers"): + raise ValueError(CLASSIFIERS_ERROR_MSG) + raw = cfg.get("metadata", "classifiers") + return [s.strip() for s in raw.split("\n") if s.strip()] + + +def __get_classifiers_from_toml(path: str) -> list[str]: + with open(path) as f: + cfg = toml.load(f) + classifiers = cfg.get("project", {}).get("classifiers") + if classifiers is None: + raise ValueError(CLASSIFIERS_ERROR_MSG) + return classifiers + + +def _determine_python_versions(classifiers: list[str]) -> list[str]: + versions = [s for s in classifiers if s.startswith(VERSION_IDENTIFIER)] + if not versions: msg = ( - "This package does not have Python version classifiers. See" - " https://pypi.org/classifiers." + f"{SETUP_CFG} does not have any classifiers of the form" + f' "{VERSION_IDENTIFIER}*"' ) raise ValueError(msg) - raw = cfg.get("metadata", "classifiers") - lines = [s.strip() for s in raw.split("\n")] - identifier = "Programming Language :: Python :: 3." - classifiers = list(filter(lambda s: s.startswith(identifier), lines)) - if not classifiers: - msg = f'setup.cfg does not have any classifiers of the form "{identifier}*"' - raise ValueError(msg) - prefix = identifier[:-2] - return [s.replace(prefix, "") for s in classifiers] + prefix = VERSION_IDENTIFIER[:-2] + return [s.replace(prefix, "") for s in versions] if __name__ == "__main__":