Allow opt out of venv recreation when requirements have changed#13048
Conversation
Can you explain a bit more for people like I who do not know the details of all this process? More specifically, does it mean that:
|
|
This is correct. |
|
@LeonarddeR I think we may be able to safely avoid recreating the venv at all if only requirements have changed, as long as we remove any old requirements no longer listed. |
|
I think this makes sense, however this does not remove dependencies of no longer needed packages. Could this be a problem? |
|
Oh you're right, I assumed it did. As we never removed indirect
dependencies this wouldn't be any worse I guess, though due to this, it
may not be worth the trouble unless it did remove everything properly.
In theory, we could:
1. fetch all installed packages that are not dependencies with: py -m
pip list --not-required --format=freeze >nonDeps.txt
2. Calculate non-dependencies that we don't require: remove all lines
from nonDeps.txt that appear in requirements.txt
3. Uninstall these remaining non-dependencies: py -m pip uninstall -r
nonDeps.txt
4. Go back to step 1 until nonDeps.txt after filtering is empty.
But we may run into trouble when filtering nonDeps.txt as the packages
listed in our requirements.txt may not be the exact most specific
version possible.
So, I'm not sure if this is all worth it. I really don't know why pip
has never supported better installed package dependency tracking.
If there are no other ideas then what is in this pr is suitable. I just
want to double check the wording one more time.
|
That's a true thing. Pip is lacking many of these features that are pretty important to have. I think PipEnv would fill that gap, but I recall that has other issues, mainly related to performance.
I think this pr offers the best of both worlds by giving the user choice about what to do. Usually they can safely choose to keep the venv, we can always urge to a venv removal on NVDA Devel if it is strictly necessary. |
An alternative approach would be not to use our requirements.txt as is but:
Agreed that this is a lot of work for a very questionable benefit.
In what cases venv should be removed even though only packages are changed? |
I must admit is this is a pretty hypothetical case. I'm not sure whether pip will handle cases properly where we downgrade a package in our requirements file that itself also specifies a downgrade of a dependant package. |
Also, there is of course the case where we specify a package upgrade that updates the package itself, but where the package doesn't specify strict version constraints for its dependencies. IN that case, at some point dependencies of dependencies won't be up to date and no longer equal to the versions used on appveyor. |
|
Thanks for your explanation @LeonarddeR. In that case I would personally prefer to":
Obviously it is possible that even with these improvements in place the version of requirements or some packages where we do not specify exacts version (such as flake8) would be different between local builds and AppVeyor, but I don't thing there is much we can do to fix this. |
|
Any comparison logic we come up with for this is not going to play well with configobj, as it is not coming from Pypy with a specific version, but rather a git commit url. Perhaps when configobj 5.1.0 is added to Pypy we might be able to, then all of our requirements will have exact versions. |
Well, I'd rather have logic that respects requirements not of the package==version form, including references to git commits, wheels, etc. There might be situations where we need them. |
|
The fact that we do not have a version specified for configObj in our requirements file is not really a problem in the design I have in mint since:
|
|
@lukaszgo1commented Do you think @michaelDCurran's code from #13048 (comment) should be preferred over current code? |
seanbudd
left a comment
There was a problem hiding this comment.
Generally LGTM, as @michaelDCurran said, this is suitable as this PR is the best option available.
| shutil.copy(requirements_path, venv_orig_requirements_path) | ||
|
|
||
|
|
||
| def createVenvAndPopulate(): |
There was a problem hiding this comment.
Might as well split these up for future modularity.
| def createVenvAndPopulate(): | |
| def createVenv(): |
See test results for failed build of commit a5701ff409 |
137dd01 to
ff0978b
Compare
Co-authored-by: Sean Budd <seanbudd123@gmail.com>
|
@seanbudd think we're ok now. I had to rebase on master because something went wrong, don't see exactly what or why. |
|
This breaks non-interactive (background) builds, this previously wasn't a common case because questions were only asked when the virtual env wasn't recognised as being created by NVDA, whereas updates to the requirements file are much more common. It would be good if this took the default action ( |
|
Out of intrest, why would one build non-interactively outside of appveyor? Appveyor builds are always fresh aren't they? |
|
I run the build in the background and output to a file. I typically do other things with the shell while it is building. I like having the build logs redirected to a file so that I can more easily inspect them after a build (if it encounters issues). It would be very unusual for me to want to avoid venv recreation. |
|
Another situation is integration with an IDE. Most IDE's let you specify a script to run to build / clean etc. |
|
Ugh, this is problematic indeed. I will have a closer look later today. Timeout seems to be problematic, I'd rather have a default applied per question when running non-interactively. Non-interactive mode should also be non-destructive, so answer usually should be no. |
I disagree here, I think the default should be the main use-case, ensuring the environment matches the requirements for this version of the source code. Wanting to skip updating the venv is the exception (special case). To take this path, you really need to know what you are doing as a developer, it is likely that the code depends on the updated requirement. Currently the justification in this PR description is:
I don't think I follow the problem. Could you expand on where this causes a problem? It would be good to capture the use-case in the description.
Yes, I'm ok with this, specifying some parameter along with |
|
One way to detect this situation is to use |
|
In that case, let's go with that. I'll try to come with a pr tomorrow or next week. |
|
Thanks for the quick solution @LeonarddeR. I did some tests yesterday to understand the initial motivation for this PR. I think it is worth summing up here and adding to the description. First I'd like to check if you agree with my understanding:
I was under the impression that pip caches the packages locally after the first install. Subsequent venv creations should be just a matter of copying the files again. I would have hoped there wasn't such a difference in the two approaches, however testing it locally it does appear to take significantly longer. |
Summary: #13048 introduced another prompt to address when dependencies in requirements.txt have changed. This blocks non-interactive use of the ensureVenv script, e.g. when running "scons source" non-interactively. Description: - Use defaults when running in non-interactive mode. - Output to stdout notification when running in non-interactive mode. To aid debugging if interactive mode is determined incorrectly. - Output questions and default answer to stdout when running in non-interactive mode To aid debugging if interactive mode is determined incorrectly. Note: that isatty is not always available on sys.stdout e.g. when it is set to the NVDA python console. Testing: Tested running scons source > d:\output and observed that the venv was dropped and recreated.
Link to issue number:
None
Summary of the issue:
When the requirements file changes, the ensureVenv script forcefully recreates the environment. In many cases, this behavior is slightly harsh.
Description of how this pull request fixes the issue:
Instead of always recreating the environment, ask the user what to do. If "No" is chosen, the requirements file is installed without recreating.
Testing strategy:
Tested both paths by changing a single line in the requirements file.
Known issues with pull request:
None
Change log entries:
Probably not relevant.
Code Review Checklist: