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

Try using ensurepip instead of get-pip #665

Merged
merged 20 commits into from
May 18, 2021
Merged

Try using ensurepip instead of get-pip #665

merged 20 commits into from
May 18, 2021

Conversation

joerick
Copy link
Contributor

@joerick joerick commented May 8, 2021

Eliminating get-pip.py removes a vendored dependency.

@joerick joerick mentioned this pull request May 8, 2021
12 tasks
cibuildwheel/windows.py Outdated Show resolved Hide resolved
@joerick
Copy link
Contributor Author

joerick commented May 9, 2021

Hmm. It was working, but the 3.8.10 update broke it on mac! I wonder what changed...

@YannickJadoul
Copy link
Member

Cross-linking to #210. Great that it does now seem to be working! :-)

@joerick joerick marked this pull request as ready for review May 10, 2021 19:29
@joerick
Copy link
Contributor Author

joerick commented May 10, 2021

This is ready to go I think. To explain what's going on here, we need to ensure that pip is available on PATH as pip, because user options like BEFORE_BUILD will likely use that. But distributions differ in that respect, some have pip available, some only as pip3, some only have pip in site-packages for use as python -m pip.

So, to ensure that pip is available, you run python -m ensurepip --default-pip. But! If pip is installed, ensurepip does nothing, so it doesn't act on --default-pip. So the only way to get --default-pip to work is to make sure that ensurepip is actually installing pip! So that's the why behind the little dance we're doing here.

This seems okay, but alternative ideas welcome!

Comment on lines 237 to 242
try:
call(["python", "-m", "pip", "--version"], env=env, cwd="/tmp")
except subprocess.CalledProcessError:
pip_is_installed = False
else:
pip_is_installed = True
Copy link
Contributor

@henryiii henryiii May 11, 2021

Choose a reason for hiding this comment

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

This feels slightly overkill with an exception. How about adding check: bool=True to call, then passing check=check through to subprocess.run, and return the result? Then this could be:

pip_is_installed = call(["python", "-m", "pip", "--version"], env=env, cwd="/tmp", check=False).returncode == 0

Copy link
Contributor

Choose a reason for hiding this comment

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

(same thing for Windows)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

haha, yes that was my first instinct, too. You can see it here:
ef91635

However, I ended up (#665 (comment)) changing that to the exception form because

  • adding the check argument to call() is awkward, because it looks a lot like the env and cwd arguments, that passthrough to subprocess.run, but there's a subtle difference - a different default.
  • adding the return type CompletedProcess to call() is also awkward, because it's only useful when check=False.
  • it muddles call()'s purpose, it's no longer 'do this' it's now 'do this/try this and tell me what happened'

So I thought the exception was neater overall.

Copy link
Contributor

@henryiii henryiii May 13, 2021

Choose a reason for hiding this comment

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

Our entire wrapper is a bit bothersome - the important thing it does is add logging. It also happens to modify the interface just a tiny bit (different name, check=True). This is heavily because it was a shortcut for check_call, but we've standardized on run(check=True), which is the recommended method to use for 3.5+ code. So what about renaming the wrapper to utils.run, just passing **kwargs, and adding check=True for most of the uses? I'd rather make it look like something people are used to (subprocess.run), rather than save a few chars.

Now if it was dramatically better, ala plumbum, then it would be worth learning something new. But not for just a small interface change.

Could be updated later, of course, doesn't have to be in this PR.

Copy link
Contributor

Choose a reason for hiding this comment

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

Points 2 and 3 are just inherited from subprocess.run. The interface might not be ideal, but it's in the stdlib.

Copy link
Member

@mayeut mayeut May 13, 2021

Choose a reason for hiding this comment

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

Would using:

    call(["python", "-m", "ensurepip"], env=env, cwd="/tmp")
    call(
         ["python", "-m", "pip", "install", "--force-reinstall", "pip", *dependency_constraint_flags],
         env=env,
         cwd="/tmp",
     )

solve the issue of detecting if pip is installed in the first place ?

i.e. use --force-reinstall instead of --upgrade when installing the pinned version

Copy link
Contributor

Choose a reason for hiding this comment

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

Would that ensure the defaultpip script was there? I think so?

Copy link
Member

Choose a reason for hiding this comment

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

Given that an actual update would end-up in the place where we want to be and starts by removing the existing installation of pip, I would guess so. Let's try this. @joerick, I'll push a commit, please do revert it if you don't like what you're seeing :-)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I agree- if that works, I'm interested. Let's see.

Copy link
Contributor

@henryiii henryiii left a comment

Choose a reason for hiding this comment

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

I'm happy if we can get rid of this internal pip copy! :)

@joerick
Copy link
Contributor Author

joerick commented May 14, 2021

Cool, that worked! I just want to check out test suite timings though, it occurs to me that this might be reinstalling pip on every test now, which could be adding some time that we could do without...

@henryiii
Copy link
Contributor

Weren't we doing that before? The pinned pip was never the bundled pip.

@joerick
Copy link
Contributor Author

joerick commented May 15, 2021

Weren't we doing that before? The pinned pip was never the bundled pip.

True, but when running our integration tests, each test reuses the same environment, so once the pinned pip is installed, it doesn't get reinstalled on each test.

master a116c2e (uninstall) 7cde8fb (--force-reinstall)
GHA Linux 19m 24m 22m
GHA Mac 28m 20m 22m
GHA Windows 35m 36m 40m
Azure Mac 22m 18m 21m
Azure Windows 3.6 35m 37m 47m
Azure Windows 3.8 35m 47m 61m

There's quite a lot of variance in these figures, so I'm not totally sure, but it does look like an increase on windows... let me try adding back the check for installation_dir/bin/pip before doing the reinstall, maybe we'll see a decrease.

@joerick
Copy link
Contributor Author

joerick commented May 15, 2021

updated table with the last commit-

master a116c2e (uninstall) 7cde8fb (--force-reinstall) 39302c7 (--force-reinstall with existence check)
GHA Linux 19m 24m 22m 23m
GHA Mac 28m 20m 22m 22m
GHA Windows 35m 36m 40m 36m
Azure Mac 22m 18m 21m 14m
Azure Windows 3.6 35m 37m 47m 34m
Azure Windows 3.8 35m 47m 61m 36m

@joerick
Copy link
Contributor Author

joerick commented May 15, 2021

Looks like it's a bit faster with a check around the --force-reinstall step. @mayeut does this look okay to you still?

@mayeut
Copy link
Member

mayeut commented May 15, 2021

That looks promising this way.
I'd use the "if not installed" to set a flag variable to --force-reinstall with the default being --upgrade.
It would get rid of 1 call to pip install and avoid code duplication for all args but this one.
What do you think ?

@joerick
Copy link
Contributor Author

joerick commented May 16, 2021

Really nice idea 👍

Comment on lines 234 to 239
# ensure pip is installed
call(["python", "-m", "ensurepip"], env=env, cwd="/tmp")

# upgrade to the version matching our constraints
# if necessary, reinstall it to ensure that it's installed as 'pip'
requires_reinstall = not (installation_bin_path / "pip").exists()
Copy link
Member

Choose a reason for hiding this comment

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

maybe move python -m ensurepip below requires_reinstall to get rid of this call as well ?

requires_reinstall = not (installation_bin_path / "pip").exists()
if requires_reinstall:
    # ensure pip is installed
    call(["python", "-m", "ensurepip"], env=env, cwd="/tmp")

Copy link
Contributor Author

Choose a reason for hiding this comment

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

hmm. yeah, I guess it would be a little faster? I thought 'ensurepip' was a quick noop when it's installed, but it still takes around a second on my machine. I'll try your suggestion.

@joerick
Copy link
Contributor Author

joerick commented May 16, 2021

GHA having issues - https://www.githubstatus.com/

@mayeut
Copy link
Member

mayeut commented May 16, 2021

updated table with the last commit-

master a116c2e (uninstall) 7cde8fb (--force-reinstall) 39302c7 (--force-reinstall with existence check) fd94e77 (conditional ensurepip)
GHA Linux 19m 24m 22m 23m 24m
GHA Mac 28m 20m 22m 22m 21m
GHA Windows 35m 36m 40m 36m 32m
Azure Mac 22m 18m 21m 14m 14m
Azure Windows 3.6 35m 37m 47m 34m 41m
Azure Windows 3.8 35m 47m 61m 36m 34m

@joerick
Copy link
Contributor Author

joerick commented May 18, 2021

updated table with the last commits (no code changes)-

master a116c2e (uninstall) 7cde8fb (--force-reinstall) 39302c7 (--force-reinstall with existence check) fd94e77 (conditional ensurepip) 3a61a5a 9b48a41
GHA Linux 19m 24m 22m 23m 24m 20m 20m
GHA Mac 28m 20m 22m 22m 21m 17m 26m
GHA Windows 35m 36m 40m 36m 32m 30m 29m
Azure Mac 22m 18m 21m 14m 14m 14m 16m
Azure Windows 3.6 35m 37m 47m 34m 41m 37m 45m
Azure Windows 3.8 35m 47m 61m 36m 34m 29m 46m

In summary, there might be too much variance in the Azure Windows figures to conclude anything, but the GHA WIndows ones seem fairly stable. Conversely the Mac figures are more stable on Azure!

Either way, this seems good to go 👍

@joerick
Copy link
Contributor Author

joerick commented May 18, 2021

thanks for spotting that license note henry!

@joerick joerick merged commit a167567 into master May 18, 2021
@henryiii henryiii deleted the ensurepip-2 branch May 18, 2021 13:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants