nox icon indicating copy to clipboard operation
nox copied to clipboard

Reading Python classifiers from pyproject.toml

Open henryiii opened this issue 1 year ago • 2 comments

How would this feature be useful?

We could convert python classifiers to a Python version list.

Describe the solution you'd like

Here's the current way to do it:

ALL_PYTHONS = [
    c.split()[-1]
    for c in nox.project.load_toml("pyproject.toml")["project"]["classifiers"]
    if c.startswith("Programming Language :: Python :: 3.")
]

Describe alternatives you've considered

No response

Anything else?

No response

henryiii avatar Oct 02 '24 19:10 henryiii

I just started utilizing nox and was looking for a way to get rid of the code duplication regarding the specified Python requirement from pyproject.toml and nox. For me, I was more looking into a way to use requires-python instead of the classifiers (since they are optional and requires-python is not). But this would work as well.

BTW: This could add great value to the documentation.

Keep up the great work!

o-moe avatar Oct 06 '24 18:10 o-moe

I think it would be fine to fall back to that if classifier are missing, but classifiers have an upper bound, while you should never put an upper cap for requires-Python.

henryiii avatar Oct 06 '24 18:10 henryiii

Here is my stupid implementation (with uv).

I make sure that the DEV python version is the lowest one. And also sort them using Version. Maybe this can help someone



from packaging.specifiers import SpecifierSet
from packaging.version import Version
CWD = Path(__file__).parent.resolve()
pyproject = nox.project.load_toml(CWD / "pyproject.toml")


# Parse our python versions
def check_python_versions() -> list[str]:
    """Parse and check the python versions

    It also check the ruff settings.

    Raises:
        RuntimeError: If we have a version mismatch
    """

    project = pyproject["project"]
    python_versions = [
        _.split("::")[-1].strip()
        for _ in project.get("classifiers", [])
        if re.match(
            r"Programming Language :: Python :: 3.\d+$",
            _,
        )
    ]
    python_versions = sorted(
        python_versions,
        key=Version,
        reverse=False,
    )
    requires_python = SpecifierSet(project["requires-python"])
    assert all(
        requires_python.contains(Version(version)) for version in python_versions
    ), "Please fix your python versions!"

    # Check ruff configuration
    if (CWD / "ruff.toml").is_file():
        ruff = nox.project.load_toml(CWD / "ruff.toml")
        ruff_version = ruff.get("target-version", "ruff_version")
        expected_ruff_version = re.sub(r"\.", "", f"py{python_versions[0]}")
        if ruff_version and expected_ruff_version != ruff_version:
            raise RuntimeError(f"Please fix your ruff version to {expected_ruff_version!r} instead of {ruff_version!r}")

    return python_versions

ews-ffarella avatar Oct 30 '24 22:10 ews-ffarella