I am looking at how Pants could support running te...
# general
f
I am looking at how Pants could support running tests against multiple Python versions. I have normally done it using
tox
before using Pants. Pants doesn’t mention
tox
in the docs and I didn’t find any related issues on GitHub. The
interpreter_constraints
option (docs) will resolve to a single Python interpreter version (so
interpreter_constraints = ["CPython==3.6.9", "CPython==3.8.5"]
wouldn’t make sense). My use case is as follows. I generate two PEX files — one for Python 3.6 and one for Python 3.8. It works out nicely since
pex_binary
provides interpreter_constraints parameter, so I have two declarations of
pex_binary
(in the root
BUILD
file) each having a distinct Python interpreter version constraint. When packaging, I do see that each PEX file (after unpacking for inspection) contains the wheels for the target Python version. I have managed to create a requirements file with pinned transitive 3rd party dependencies with the versions of Python packages that work for both 3.6 and 3.8. Having two target runtime environments of course implies that it’s required to run tests both against 3.6 and 3.8 interpreter. However, the
test
goal works only against a single interpreter version:
Copy code
[python-setup]
interpreter_constraints = ["CPython==3.8.5"]
Is there any way to run tests against multiple Python interpreters that I’ve missed being mentioned in the docs (without manually switching the Python versions in the
pants.toml
)?
w
hey @fresh-cat-90827: to do this, you can declare multiple
python_tests
targets, each with the different constraints
…which highlights another important point:
python_tests
targets can declare their own interpreter_constraints
if you find yourself frequently testing against multiple versions, you can write a macro that will declare all of them at once
h
Check out https://blog.pantsbuild.org/python-3-migrations/ if you haven't yet seen it!
👍 1
f
thanks @witty-crayon-22786 and @hundreds-father-404, this works for me. I have somehow thought that those Python 2/3 separations were not applicable to my case, sorry about that.
h
Ah yeah, that's something we could probably explain better - it's not just Py2 -> Py3 these features are useful for. Also Py37 -> Py39 for example
f
right, I got it! So say I want to make sure the whole monorepo is 3.6 compatible and 3.8 compatible — I’d basically need to use a macro
Copy code
# pants-plugins/macros.py
def python_tests_global(name, **kwargs):
    kwargs.pop("interpreter_constraints", None)

    python_tests(
        name=f"{name}_py369",
        interpreter_constraints=["==3.6.9"],
        **kwargs,
    )

    python_tests(
        name=f"{name}_py385",
        interpreter_constraints=["==3.8.5"],
        **kwargs,
    )
in all
BUILD
files which declare
python_tests
targets, right? I assume overriding built-in
python_tests
target is unsupported (or is a bad idea)?
h
Yeah, a macro or explicitly creating two targets each time. The macro is more convenient You technically could also create a new target type with the plugin API, but there's no practical benefit here over using the simpler macro feature
w
I assume overriding built-in 
python_tests
 target is unsupported (or is a bad idea)?
it’s not the best for clarity, no… introduces some magic
f
right, then given
Copy code
[python-setup]
interpreter_constraints = ["CPython==3.6.9", "CPython==3.8.5"]
it becomes important to make sure no-one is using the built-in
python_tests
target because Pants will pick either 3.6 or 3.8 when running tests whereas
python_tests_global
(from the macro above) would test for both versions. Would “banning”
python_tests
from being used be a good idea at all, if that’s possible? I am curious if there is any more effective way to make support the whole monorepo being tested against two versions, but perhaps there isn’t.
h
Unfortunately Pants does not have a way to ban using certain targets, nor to selectively unregister things that are builtin to
pants.backend.python
The best I can think of is to lint your BUILD files to not have
python_tests
, if that's the case every test must run w/ both interpreters. For example, you could use
./pants validate
to do this: you can define regex for Pants to check. https://www.pantsbuild.org/docs/reference-sourcefile-validation. (I'm not certain the error message would be super informative tho, as it wouldn't explain the remedy to instead use your macro's name)
f
that’s okay, @hundreds-father-404, Pants is extremely helpful, so this is just a minor detail really. Linting the
BUILD
files sounds like a fine idea to me, thank you! The
validate
goal, when it says
Validate sources against regexes.
does it refer to the BUILD files only (i.e. “sources of metadata for Pants”) or to any/some file(s) within the monorepo?
h
For validate, it can be any file, including files that Pants normally doesn't operate on like BUILD files and languages Pants doesn't (yet) understand like Rust. For example, we use this to validate our copyright https://github.com/pantsbuild/pants/blob/main/build-support/regexes/config.yaml
🙏 1
w
(…i once again wonder whether
validate
should move into
lint
)
h
It should, but technically, that would require a big rework: rn
lint
can only operate on files owned by targets. It's key that
validate
can run on any file and doesn't require targets
w
there are other reasons to fix that i think…
lint
should be able to operate on
BUILD
files, for example
(tangent, apologies)