nox icon indicating copy to clipboard operation
nox copied to clipboard

Provide a way to read `requires_python` from a project's settings

Open brettcannon opened this issue 3 years ago • 2 comments

How would this feature be useful? Instead of having to specify what versions of Python are supported both in project metadata and in my noxfile.py , read it from the project metadata to infer what versions are supported.

This may require PEP 621 to gain traction before it's feasible.

Describe the solution you'd like Some way to say, "use requires_python to know what versions of Python are considered supported".

Describe alternatives you've considered

  • Script to generate my noxfile.py based on my requires_python metadata.
  • Module to provide a decorator for a session.

brettcannon avatar Feb 10 '21 19:02 brettcannon

I don't have an immediate solution, but I do have some thoughts on this.

The easy way (classifiers)

The way I address this for my own projects is with a very basic function that scrapes the PyPI trove classifiers, like:

def supported_pythons(classifiers_file=Path("setup.cfg")):
    """
    Parse all supported Python classifiers from setup.cfg
    """
    pattern = re.compile(r"Programming Language :: Python :: ([0-9]+\.[0-9.]+)")
    return pattern.findall(classifiers_file.read_text())

That covers only minor versions, of course, but it feeds nicely into @nox.session(python=supported_pythons())

It would probably be more correct way here to use setuptools/distutils to pull the classifiers? One could in the same manner pull requires_python...

The trickier way (requires_python)

However, requires_python can get a lot hairier -- e.g., Requires-Python: ">2.7,!=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -- allowing PEP 345 conditionals and then all the myriad PEP 440 version specs. I'm assuming there is some way in setuptools/distutils to parse those out and get a boolean for whether python executable X is valid under requires_python Y.

For nox, though, python= is implemented as more of a guess and check (see virtualenv.py). Call the appropriate version of the executable for that system; if that doesn't work, then skip that version and let the user know.

It seems to me that to properly handle requires_python nox would instead want to collate a list of all available system Pythons, then filter them based on that list.

vaneseltine avatar May 28 '21 18:05 vaneseltine

cibuildwheel does a similar thing which might be interesting here:

  • reads requires_python (either PEP 621, setup.cfg or setup.py): https://github.com/pypa/cibuildwheel/blob/main/cibuildwheel/projectfiles.py
  • uses this string to build a packaging.specifiers.SpecifierSet
  • use the SpecifierSet to check if a specific python version can be used for building a wheel: https://github.com/pypa/cibuildwheel/blob/99d6c378dbf9587555424f68c2c596750dea12c7/cibuildwheel/util.py#L254-L262

mayeut avatar May 08 '22 17:05 mayeut