-
Notifications
You must be signed in to change notification settings - Fork 3k
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
Add an upgrade-strategy option #3972
Changes from 5 commits
23e120b
61d8d6a
25d9866
09fe699
6550631
21c98ef
932ecd2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -140,10 +140,10 @@ def prep_for_dist(self): | |
class RequirementSet(object): | ||
|
||
def __init__(self, build_dir, src_dir, download_dir, upgrade=False, | ||
ignore_installed=False, as_egg=False, target_dir=None, | ||
ignore_dependencies=False, force_reinstall=False, | ||
use_user_site=False, session=None, pycompile=True, | ||
isolated=False, wheel_download_dir=None, | ||
upgrade_strategy=None, ignore_installed=False, as_egg=False, | ||
target_dir=None, ignore_dependencies=False, | ||
force_reinstall=False, use_user_site=False, session=None, | ||
pycompile=True, isolated=False, wheel_download_dir=None, | ||
wheel_cache=None, require_hashes=False): | ||
"""Create a RequirementSet. | ||
|
||
|
@@ -170,6 +170,7 @@ def __init__(self, build_dir, src_dir, download_dir, upgrade=False, | |
# the wheelhouse output by 'pip wheel'. | ||
self.download_dir = download_dir | ||
self.upgrade = upgrade | ||
self.upgrade_strategy = upgrade_strategy | ||
self.ignore_installed = ignore_installed | ||
self.force_reinstall = force_reinstall | ||
self.requirements = Requirements() | ||
|
@@ -241,6 +242,8 @@ def add_requirement(self, install_req, parent_req_name=None): | |
install_req.use_user_site = self.use_user_site | ||
install_req.target_dir = self.target_dir | ||
install_req.pycompile = self.pycompile | ||
install_req.is_direct = (parent_req_name is None) | ||
|
||
if not name: | ||
# url or path requirement w/o an egg fragment | ||
self.unnamed_requirements.append(install_req) | ||
|
@@ -375,6 +378,13 @@ def prepare_files(self, finder): | |
if hash_errors: | ||
raise hash_errors | ||
|
||
def _is_upgrade_allowed(self, req): | ||
return self.upgrade and ( | ||
self.upgrade_strategy == "eager" or ( | ||
self.upgrade_strategy == "non-eager" and req.is_direct | ||
) | ||
) | ||
|
||
def _check_skip_installed(self, req_to_install, finder): | ||
"""Check if req_to_install should be skipped. | ||
|
||
|
@@ -396,17 +406,20 @@ def _check_skip_installed(self, req_to_install, finder): | |
# Check whether to upgrade/reinstall this req or not. | ||
req_to_install.check_if_exists() | ||
if req_to_install.satisfied_by: | ||
skip_reason = 'satisfied (use --upgrade to upgrade)' | ||
if self.upgrade: | ||
best_installed = False | ||
upgrade_allowed = self._is_upgrade_allowed(req_to_install) | ||
|
||
# Is the best version is installed. | ||
best_installed = False | ||
|
||
if upgrade_allowed: | ||
# For link based requirements we have to pull the | ||
# tree down and inspect to assess the version #, so | ||
# its handled way down. | ||
if not (self.force_reinstall or req_to_install.link): | ||
try: | ||
finder.find_requirement(req_to_install, self.upgrade) | ||
finder.find_requirement( | ||
req_to_install, upgrade_allowed) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Won't There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I wondered the same initially. Then I decided to keep it as it was with upgrade. |
||
except BestVersionAlreadyInstalled: | ||
skip_reason = 'up-to-date' | ||
best_installed = True | ||
except DistributionNotFound: | ||
# No distribution found, so we squash the | ||
|
@@ -423,6 +436,15 @@ def _check_skip_installed(self, req_to_install, finder): | |
req_to_install.conflicts_with = \ | ||
req_to_install.satisfied_by | ||
req_to_install.satisfied_by = None | ||
|
||
# Figure out a nice message to say why we're skipping this. | ||
if best_installed: | ||
skip_reason = 'already up-to-date' | ||
elif self.upgrade_strategy == "non-eager": | ||
skip_reason = 'not upgraded as not directly required' | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This gets appended to "Requirement already" instead of to "Requirement". Now it looks a bit weird: There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. and same two lines above, gives There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I missed that line. 😅 I thought I had changed it... |
||
else: | ||
skip_reason = 'already satisfied' | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This can't happen - if the above two clauses are false, then the latest version is not installed and strategy is eager. Hence can't skip but need to upgrade. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Now that I think about it, yes. This is a need-to-upgrade. I don't know what reasoning I was applying earlier for this... There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah... I did that because of the assert on line 484. And because I could never hit that branch in any of my testing earlier, for the previous PR. |
||
|
||
return skip_reason | ||
else: | ||
return None | ||
|
@@ -520,7 +542,10 @@ def _prepare_file(self, | |
% (req_to_install, req_to_install.source_dir) | ||
) | ||
req_to_install.populate_link( | ||
finder, self.upgrade, require_hashes) | ||
finder, | ||
self._is_upgrade_allowed(req_to_install), | ||
require_hashes | ||
) | ||
# We can't hit this spot and have populate_link return None. | ||
# req_to_install.satisfied_by is None here (because we're | ||
# guarded) and upgrade has no impact except when satisfied_by | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You may want to consider whether "non-eager" is clear to a user. The original proposal of "only-if-needed" is not much longer. That's what the pip docs call it now: https://pip.pypa.io/en/latest/user_guide/#only-if-needed-recursive-upgrade
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Makes sense. I'll make the change.