-
-
Notifications
You must be signed in to change notification settings - Fork 529
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
tox4: Support constraints.txt for package dependencies #1939
Comments
The project https://github.com/zopefoundation/RestrictedPython uses a constraints.txt with pytest < 5 Initially
This needs some more investigation...
|
@jugmac00 that RestrictedPython has an unnecessary constraint with pytest < 5 for Python 2.7 does not make any difference in the described problem. that is why I have made an abstract report without referencing a certain Repository. But yes it was RestrictedPython in the first place where I discovered the problem. |
So this is working as expected and works the same with tox 3. The issue is that deps and package dependencies are installed in two separate phases/invocation. What you specify for # this contains the constraint
install_deps> python -I -m pip install -c constraints.txt pytest-cov pytest-html
# this later does not
install_package_deps> python -I -m pip install pytest pytest-mock 'setuptools>=40.8.0' wheel Now as far as solutions for the issue, I think the best is to introduce a |
@loechel The original reported problem has been fixed on the rewrite branch already with #1991. This can be easily reproduced running tox4 alpha 6 and tox4 from the rewrite branch as e.g. tox4 from the rewrite branch (no isort)
tox4 alpha6 (isort got installed!)
While trying to verify this issue, I noticed, that your constraints file does not get used for the package dependency - that is what @gaborbernat and me are talking about. This now discovered issue is consistent between tox3 and tox4. So, what to do about it? First, yes, I was surprised that I finally got a Also, when I would want to reproduce the test environment without using
which would result in this here... ie with the "expected" pytest version.
On the other hand, except for my Zope app for which I use I pin my other app's dependencies with pip-compile and a requirements.txt, and I let my test dependencies float, which mostly is only When it is important to have consistent versioned test packages, you could either pin the version in So, as it seems I was the "first" one noticing the issue, and there are at least some other viable ways to pin the test dependencies, I do not think we have to implement a solution right now / at all. Though, I would suggest to document the behavior. P.S.: I restricted my view only on the test dependencies, as for the package itself it is a common pattern to use a requirements.txt anyway. |
I don't think either of these solutions is correct. The scope here is not to universally pin, but rather on the latest and test with a minimum version, which the constraint file expresses. I think solutions for this are two options:
|
How would that look like? Like this? cf #1929
Would then the |
[testenv:py39]
install_command = python -m pip install {opts} {packages} -c constraints.txt
extras = test |
Nice! I was not aware of this option. Looks great and works great. I just checked it with above mentioned project
|
Hi @jugmac00 and @gaborbernat Thanks for working on that issue. Maybe let me describe the background and idea behind the issue. I am also from the Zope/Plone Community and was used to the tooling that was provided by zc.buildout and other concepts in this context. Now I see two different approaches to a continuous development of projects in Python:
For the first use case I would always say, there is no need for a requirement / constraints file, you could and should if necessary pin or define ranges of dependency versions within the setup.py / setup.cfg with all specifics. So for RestrictedPython I would never use an install like > pip install .[test] -c constraints.txt but I would go for a simple: > pip install -U -e ".[test,develop] For the second use case, thats where the transition from zc.buildout to simple pip enabled virtualenvs is ongoing the old idea of known-good-versions files came up again. Zope and Plone most often use strict versions pins on a specific version and not ranges, which is perfect for a rock solid deployment, but not for development. In development Environments, I want to have most of the dependencies with floating versions, so that I could test against the latest version or subversion of a package without the need to lookup new versions or change the pins manual. For a project I would always have an own repository (like the buildout repos for a Zope / Plone deployment) with a requirement file that says explizit which Packages I would like / need to have. For Plone that could be something like: # Requirements for my Plone Project
Plone
collective.lineage
myproject.policy
myproject.theme A buildout constraints file in the Plone environment are managed by the release team (see for example: https://dist.plone.org/release/5.2-latest/versions.cfg), that could also include a known good set of versions for addons. The mayor difference between requirements.txt and constraints.txt and the install with pip is the key part here. pip will install all packages listed in a requirements file, but packages listed in a constraints file will only be installed if the package resolution finds the necessity that this package need to be installed to fulfil the dependencies, and it than will respect the specified version / version range. For me, constraints in a package using tox is more a management of constraints for the test / development packages defined and used in tox itself and not the package under test. Constraints files therefore should be loadable from remote http addresses, so that a managend constraint file could be included. So for me a [testenv]
extras =
tests
develop
deps =
-cconstraints.txt
pytest-html should always go into the dependency-install step and not the package-dependency-install step. And as @jugmac00 said correctly, if I install the package itself in a venv for testing without tox, than all test dependecies should be listed and if necessary pinned or described with a version range, excludes, ... within the setup definition of the package and not any requirements or constraints files within the repository. |
@gaborbernat thank you for pointing out that the deps packages are installed before the package itself. I was not aware of that. I see that some users, me included, sometimes don't specify the test dependencies anymore within the package but in the tox.ini. Especially in combination with lintings tools and pre-commit that makes a benefit and is superior of the zc.buildout behaviour that all steps normally are bind to the same python version. A lot of the tooling surrounding a package is most often better managed in separate files like tox.in or pre-commit configs than in the setup.py itself. But as we know not all developers specify the compatible versions within there setup.py it is sometimes necessary to have a constraints file. So I want that feature working correctly. |
The problem becomes when a package is both a package and a test dependency. The test requirement is installed first respecting the constraint file. However, if the package also pulls in that dependency and the constraint file is not specified, the package install would upgrade the test dependency. Though my |
Does not adding |
This is now documented under https://tox.readthedocs.io/en/rewrite/faq.html#using-constraint-files |
That documentation is quite good. The only remark here is that it omits one thing: constraints files are perfectly valid requirement files (the opposite is not true). They use a subset of what a reqs file can contain. This also means that nothing prevents people to just install constraint files if they want, they can use them as requirement files and some do, for valid reasons (pip performance is amazing with them). |
Isn't that only because of the pinned versions? |
Added with #2153 |
Yes. Using pinned versions bypassed most of pip resolver and in some cases it can make huge difference. No more round trips with pypa in order to find the right package version when you already know the only version that is allowed. |
Yeah, but in this case is less about constraint files, more about pinning. You can have requirements files pinned too, that are not constraints 😊 |
…m correctly using the minimum pytest version. The "deps" option does not specify the package dependencies, but a list of packages that should be installed before the package under test. However, it's possible ot use "install_command" to specify a constraints file. see tox-dev/tox#1939 (comment) Signed-off-by: Michael Seifert <[email protected]>
…m correctly using the minimum pytest version. The "deps" option does not specify the package dependencies, but a list of packages that should be installed before the package under test. However, it's possible ot use "install_command" to specify a constraints file. see tox-dev/tox#1939 (comment) Signed-off-by: Michael Seifert <[email protected]>
…m correctly using the minimum pytest version. The "deps" option does not specify the package dependencies, but a list of packages that should be installed before the package under test. However, it's possible ot use "install_command" to specify a constraints file. see tox-dev/tox#1939 (comment) Signed-off-by: Michael Seifert <[email protected]>
…m correctly using the minimum pytest version. The "deps" option does not specify the package dependencies, but a list of packages that should be installed before the package under test. However, it's possible ot use "install_command" to specify a constraints file. see tox-dev/tox#1939 (comment) Signed-off-by: Michael Seifert <[email protected]>
@gaborbernat With the recent issues I had with tox-dev/tox-uv#154 uv that does not support PIP_CONSTRAINTS, I realised that if we would have had an option like you mentioned, we would have being possible to implement it directly into tox-uv and avoid having to use lots of environment variables. WDYT? |
I do not follow what you had in mind exactly. |
If tox would have an option like At this moment there are several tox users that are using PIP_CONSTRAINTS variable to control what gets installed (some tox environment by not use it on purpose). That constraints file is usually updated by dependabot or other similar tool. That makes testing very easy to reproduce and also helps identifying when a dependency breaks your testing (the job that does not use a constraint). Same approach can also be used to have a lower-constraints file, that tests oldest supported dependencies, this one obviously being only manually updated. To rephrase for clarity: custom pip command or environment variable trick are not portable to uv (or other similar plugins), specific configuration options could allow that. If you agree, we could reopen or create new issue for adding a configurable option. Example of kind of change I now need to do in any project https://github.com/ansible/ansible-compat/pull/446/files -- just trying to find a way to avoid this. |
No, I don't want to deal with constraint files. The way the tox cache layer works it's not just "pass" through. It's needing to parse it, and I do not have appetiate to deal with that. |
if you have a python package to test with tox and using a constraints.txt to pin versions for specific dependencies tox4 will read the constraints.txt and add each line to the pip install command as a dependency.
Following https://tox.readthedocs.io/en/latest/example/basic.html#depending-on-requirements-txt-or-defining-constraints is misleading or wrong at that moment.
tox.ini
constraints.txt
results in an output line:
py36: 14582 W install_deps> python -I -m pip install pytest-cov pytest-html 'pytest>6' [tox/tox_env/api.py:288]
For
deps = -requirements.txt -cconstraints.txt pytest-cov pytest-html
suggested or expected command should be:
python -I -m pip install -U -r requirements.txt -c constraints.txt listeded-dependencies
or even better to read:
python -I -m pip install --upgrade --requirement requirements.txt --constraint constraints.txt listeded-dependencies
Background:
Constraints files may specify version pins or ranges for packages that might be used in this context. Those packages could be optional. In contrast to requirement files, where all declared packages are dependencies and must be met / installed with the specified pinned version.
Constraints files may be used as a definition of known good version set that works with a specific major release of a package.
Example:
The text was updated successfully, but these errors were encountered: