Skip to content
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

Make -U non-recursive by default, add --upgrade-recursive option #571

Closed
wants to merge 2 commits into from

Conversation

fdintino
Copy link

@fdintino fdintino commented Jun 8, 2012

I believe that this pull request fixes #304. I incorporated a suggestion from one of the comments in that issue and kept the current behavior with the command option --upgrade-recursive.

@travisbot
Copy link

This pull request passes (merged 8a38346 into 8d92fc2).

@kennethreitz
Copy link
Contributor

This would be fantastic.

@lepture
Copy link

lepture commented Jul 2, 2012

👍

@kennethreitz
Copy link
Contributor

I'd also consider --upgrade-all instead of --upgrade-recursive

@ejucovy
Copy link

ejucovy commented Jul 2, 2012

@kennethreitz, I think --upgrade-recursive is the better name; --upgrade-all might sound like it should upgrade all the currently installed packages. A google search for "pip upgrade all" turns up requests for that sort of feature, so calling this flag --upgrade-all would probably confuse people, and make it harder to give the intuitive name to a future "upgrade all" command.

@kennethreitz
Copy link
Contributor

Ah, good point.

@qwcode
Copy link
Contributor

qwcode commented Jul 2, 2012

travisbot passing all the tests (and seeing that the commit from #fdintino didn't add or alter any tests) would imply that there was no previous coverage on this feature.

tests/test_upgrade.py seems to be all about single distributions w/o dependencies.

this would certainly be the time to add some tests related to recursion.

@ejucovy
Copy link

ejucovy commented Jul 2, 2012

I've forked fdintino's branch to add tests: ejucovy/pip@fdintino:fix-recursive-upgrades...ejucovy:fix-recursive-upgrades

The first new test, test_upgrade_without_unneeded_recursive_upgrades, will run and fail on pip presently. It passes on fdintino's branch.

The second new test passes in both cases. The third new test tests the new --upgrade-recursive feature.

@ejucovy
Copy link

ejucovy commented Jul 2, 2012

Nice catch, @qwcode. You're right, the implementation in this pull request breaks pip install --upgrade reqs.txt. That command should upgrade all packages explicitly listed in reqs.txt, but with this patch it only upgrades the first package listed and ignores the subsequent lines.

I've added an additional test for this behavior on my fork of fdintino's branch: ejucovy@e192a41

The last assertion in my new test fails on the branch. The same assertion passes on develop, so this feature isn't ready to be merged.

@fdintino
Copy link
Author

fdintino commented Jul 2, 2012

Thanks for the unit tests! I was getting concerned by the lack of feedback. I'll be away from a computer until this evening (EDT) but I'll fix this when I get back home.

Would the pip maintainers prefer if I merge commits where possible (having two commits, one from me and one from ejucovy) or does that not matter? I know that some projects prefer to have pull requests with as few commits as possible.

Thanks.

@fdintino
Copy link
Author

fdintino commented Jul 3, 2012

I added an is_subrequirement property to InstallRequirement and a method is_upgradeable() to RequirementSet:

def is_upgradeable(self, requirement):
    if requirement.is_subrequirement and not requirement.is_extra:
        return self.upgrade_recursive
    else:
        return self.upgrade

InstallRequirement.is_subrequirement evaluates to True if InstallRequirement.comes_from is an instance of InstallRequirement. I assumed that we would want packages defined with the "extra" syntax (e.g. "packagefoo[packagebar]") to upgrade with the non-recursive command, so I added an is_extra attribute to InstallRequirement to keep track of whether a dependent requirement came from an extras definition.

@travisbot
Copy link

This pull request fails (merged daaff403 into 5562a6b).

@travisbot
Copy link

This pull request passes (merged ed95a70 into 5562a6b).

@fdintino
Copy link
Author

fdintino commented Jul 4, 2012

In case anyone is confused by the above travisbot messages, the first test failed because of a timeout on the travis server, so I force pushed with a different commit timestamp to initiate another travis build.

@fdintino
Copy link
Author

fdintino commented Jul 6, 2012

Let me know if there's anything else I can do to help get this pulled in.

@@ -1096,6 +1113,12 @@ def prepare_files(self, finder, force_root_egg_info=False, bundle=False):
finally:
logger.indent -= 2

def is_upgradeable(self, requirement):
if requirement.is_subrequirement and not requirement.is_extra:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are extras treated differently from other dependencies (always recursively upgraded)?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At the time it made sense... I think my reasoning was that if you're supplying the extra alongside the package when issuing the upgrade command, then the expected behavior would be for the same upgrade logic to apply to both the base package and the extra packages, otherwise you wouldn't have used the extra specifier; e.g. why would you issue this command:

pip install -U jinja2[i18n]

and not this:

pip install -U jinja2

On the other hand, I'm not sure the extras make much sense in this context, so I'm not particularly attached to this line of reasoning and wouldn't be opposed to taking it out.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a verdict on this? Keep it or not?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On further consideration, I think this is assuming too much. I'll take it out.

@fdintino
Copy link
Author

I integrated the above comments about the tests and is_upgradeable into the latest pull request.

@travisbot
Copy link

This pull request fails (merged 679641d5 into c6789f6).

@qwcode
Copy link
Contributor

qwcode commented Jul 13, 2012

@pnasrat , do you understand the scenario that leads to this kind of travis failure?

@travisbot
Copy link

This pull request passes (merged ba12e28 into c6789f6).

@fdintino
Copy link
Author

I think it was because I force-pushed while it was starting to check it out, and the commit no longer existed for the merge. I had a typo in @ejucovy's author info

@qwcode
Copy link
Contributor

qwcode commented Jul 13, 2012

btw, I was working on migrating tests last night for #598, and I'm pretty sure I found a bug that affects the current upgrade code pathway. I'll reconfirm and post a pull later this weekend, and reference this pull.

you're working hard on this. I'll look it over in detail over the weekend.

considering this is a compatibility breaking change, I think I might post something to the list requesting feedback.
I searched the list real quick and didn't see any recent conversation on that.
my sense is the most people would be in favor of this, but there may be people who argue strongly for keeping -U as it is, and adding something like --upgrade-nonrecursive

@qwcode
Copy link
Contributor

qwcode commented Jul 16, 2012

@fdintino , ended up using what free time I had to sort thru #604. I'll look tomorrow. If it's real, I'm inclined to think #604 should block this pull, just because it shakes my confidence in some of the core logic underlying the upgrade.

req_to_install.conflicts_with = req_to_install.satisfied_by
req_to_install.satisfied_by = None
else:
install_needed = False
if req_to_install.satisfied_by:
if self.upgrade and not self.upgrade_recursive:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't follow this logic?
it seems like all we need to notify is this:
'Requirement already satisfied (use --upgrade to upgrade): %s' % req_to_install)
and if so, you don't need to pass in in upgrade as a property of RequirementSet, just upgrade_recursive

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe this message displays after any installation where the requirement is currently satisfied, not just upgrades. So if you performed

pip install Django

and you had Django 1.2.3 installed, you would see:

Requirement already satisfied (use --upgrade to upgrade): Django in [...]

whereas if Django was a dependency in install_requires that was satisfied but would be force-upgraded with --upgrade-recursive, it would instead display:

Requirement already satisfied (use --upgrade-recursive to upgrade): Django>1.2 in [...]

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm, I take that message just as an FYI to the user about how to upgrade an individual package, that was satisfied during the current installation, not as a tip on how to redo the last installation command to get certain packages upgraded.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That makes sense. I suppose the reason I did it this way is that with the previous behavior a pip install --upgrade never presented this message, whereas now it can and it struck me as confusing that the user would be directed to perform a --upgrade during a --upgrade (the source of the confusion here being the ambiguity of the argument to pip install)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

An upside of presenting the (use --upgrade-recursive to upgrade) notice is that it might ease confusion for people expecting the previous pip install -U behavior.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, I see your pt of view. maybe a 3rd person can help decide what is more intuitive in this case.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it would be nice to see the tests confirm the exptected notifications

@fdintino
Copy link
Author

The pypy build failed on travis, but it doesn't look related to this commit. The message is a bit confusing, almost looks like a travis bug, but I'd need someone else to weigh in.

@qwcode
Copy link
Contributor

qwcode commented Nov 20, 2012

pretty sure it's not related. I've seen that error pop up from time to time on other pypy tests. wish I knew how to guard against it once and for all.

@qwcode
Copy link
Contributor

qwcode commented Nov 24, 2012

@pnasrat : any thoughts on this one? it's a merge candidate I think, but needs multiple maintainers giving it a go, since It changes the behavior of -U. Not something to take lightly.

@qwcode
Copy link
Contributor

qwcode commented Nov 24, 2012

btw, I sent an email to the list months ago, asking if anyone had concerns with this change, and got no replies.

@pnasrat
Copy link
Contributor

pnasrat commented Nov 24, 2012

I'd say lets hold off on behaviour changes until we manage to review the command rework. Then we should come give some thought to the user experience and the right commands and options to make that happen. Then that would go towards a 2.0

@fdintino
Copy link
Author

Just to make sure we're all on the same page, this isn't simply a reworking of the command, it fixes a long-standing bug with the behavior of recursive upgrades. The current behavior makes pip unworkable for certain workflows at The Atlantic, and judging from the ticket this is intended to fix we aren't alone in this regard.

@qwcode
Copy link
Contributor

qwcode commented Nov 24, 2012

@fdintino , as for pip being "unworkable for certain workflows", I wrote up a gist a while back for your scenario.
see this comment: #304 (comment)
I remember we went back and forth on this, but I don't think you ever responded to my last iteration on this.
imo, pip can handle this workflow as is, but involves 2 steps that aren't obvious.

@qwcode
Copy link
Contributor

qwcode commented Nov 24, 2012

@pnasrat , by "command rework", you're talking about #721? you think this should hinge/hold on that?

@fdintino
Copy link
Author

@qwcode: I hadn't seen that. It's counterintuitive, but that is helpful. As a rule, if we're using the unpatched pip, we always use --no-deps when calling --upgrade, otherwise we're liable to end up with Django 1.5 alpha (because something has install_requires=['Django>1.2']), and who knows what else. Occasionally a developer will forget to use --no-deps, they start having issues with their install, and time is wasted until the problem is diagnosed back to having run --upgrade without --no-deps. This is why we decided it was worth spending company time working on fixing this issue.

I know you were just speculating, but to me #721 seems unrelated, since that seems to concern the apis in pip/commands/*, whereas this ticket is a modification to the behavior in pip/req.py.

@fdintino
Copy link
Author

Updates?

@fdintino
Copy link
Author

Specifically, I notice that #721 was closed, and this still passes the tests.

@qwcode
Copy link
Contributor

qwcode commented Dec 13, 2012

@fdintino I appreciate your persistence on this. I think this pull is worthy, but it's going to need other maintainers giving it reviews and thumbs up, since it's a major change.

@qwcode
Copy link
Contributor

qwcode commented Dec 17, 2012

@fdintino here's a thought. take your understanding you've gained from working on this, and use it towards a new pip upgrade command (a la #59), and leave the old pip install -U as it is for now.

usage:

pip upgrade <options> <package> ...

--recursive    //upgrade <package> recursively
--all                //upgrade everything  (lot of people wanting this)

@qwcode
Copy link
Contributor

qwcode commented Dec 17, 2012

@fdintino note that "pip list" (#752) is soon to be merged, which has an option for showing you what's out of date.

@qwcode
Copy link
Contributor

qwcode commented Dec 17, 2012

@fdintino , fyi, I'm gonna work on "pip upgrade", and just try to get it done.

@fdintino
Copy link
Author

Okay, I'd be willing to take a stab at it if you would like.

@qwcode
Copy link
Contributor

qwcode commented Dec 18, 2012

ok, thanks, I'll see how my time goes. I'll include you for review on anything I do.

@qwcode
Copy link
Contributor

qwcode commented Dec 18, 2012

and btw, if "pip upgrade --recursive" makes it in under my pull , I'll give you and ejucovy mucho credit. : )

@qwcode
Copy link
Contributor

qwcode commented Feb 10, 2013

hey, @fdintino, sorry, the reality of trying to get v1.3 tested and ready (and the latest effort to get ssl cert checking into pip) has stalled me on this. if you want to start on the pip upgrade idea, feel free and let me know.

I'm closing this in its current form, because I'm pretty keen on adding this via pip upgrade, and leave pip install --upgrade as it is, with an eventual deprecation.

btw, see the new current cookbook entry on how to do a non-recursive install using what pip offers now:
http://www.pip-installer.org/en/latest/cookbook.html#non-recursive-upgrades
If that seems wrong or confusing, let me know.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
auto-locked Outdated issues that have been locked by automation
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

8 participants