get-pip icon indicating copy to clipboard operation
get-pip copied to clipboard

Provide get-pip.py versions for all python versions

Open xavfernandez opened this issue 3 years ago • 12 comments

Each time pip drops the support for some version of python, users need to update their script from https://bootstrap.pypa.io/get-pip.py to https://bootstrap.pypa.io/X.Y/get-pip.py.

I'm wondering if we shouldn't directly provide https://bootstrap.pypa.io/X.Y/get-pip.py for all existing (and recent) python versions.

That would currently mean to provide https://bootstrap.pypa.io/3.6/get-pip.py, https://bootstrap.pypa.io/3.7/get-pip.py, https://bootstrap.pypa.io/3.8/get-pip.py, https://bootstrap.pypa.io/3.9/get-pip.py & https://bootstrap.pypa.io/3.10/get-pip.py that would be copies of https://bootstrap.pypa.io/get-pip.py.

Users would then be able to directly use the get-pip.py script version matching their python version.

xavfernandez avatar Jan 26 '21 08:01 xavfernandez

As an alternative, get-pip.py could check the Python version, and if it's not a supported version, print a message directing the user to download the appropriate https://bootstrap.pypa.io/X.Y/get-pip.py script and use that, and then exit.

pfmoore avatar Jan 26 '21 17:01 pfmoore

Perhaps get-pip.py could redirect to the version that works for whichever version if Python is requesting it, that way users and build systems would not all need to code in the logic to select the correct URL for the correct Python version.

bsiegel avatar Jan 26 '21 19:01 bsiegel

We can't have redirects, since a common mechanism is using curl, which won't be happy with redirects.

pradyunsg avatar Jan 27 '21 04:01 pradyunsg

@pradyunsg curl -L can follow redirects just fine.

webknjaz avatar Jan 27 '21 09:01 webknjaz

But the suggestion was "redirect to the version that works for whichever version if Python is requesting it" and if you're requesting it with curl, the server has no way to know which version of Python is requesting it (because it's not being requested by Python!)

pfmoore avatar Jan 27 '21 09:01 pfmoore

Yep, sure - I should have been more clear, I don't think HTTP redirects specifically are the mechanism to achieve this. Just that in concept, if the initial script could function as a sort of stub, determine the Python version that is executing it, and then load the appropriate full version of the get-pip script, that would provide significant value. However, I realize even that may not be viable because the get-pip script is intentionally kept simple (e.g. it doesn't attempt to do any network operations for example, and adding such a mechanism would add new complexity, failure modes, etc).

An alternative that might provide similar value would be to provide versioned copies of the script not by their interpreter version, but by the version of pip they install (e.g. https://bootstrap.pypa.io/21.0/get-pip.py). Extending this idea, there is prior art we can look at from Javascript CDNs which allow the requester to include a version specifier in the URL. For example, this is how jsDelivr handles versioned URLs:

// load the specific version v3.2.1
https://cdn.jsdelivr.net/npm/[email protected]/dist/jquery.min.js

// load the latest v3.2.x version
https://cdn.jsdelivr.net/npm/[email protected]/dist/jquery.min.js

// load the latest v3.x version
https://cdn.jsdelivr.net/npm/jquery@3/dist/jquery.min.js

// omit the version completely to get the latest one
https://cdn.jsdelivr.net/npm/jquery/dist/jquery.min.js

This can be pretty easily managed by simply populating the appropriate directory structure with copies of the scripts, and publishing updates to the right places. It's only marginally more complex than the current approach, and the "deployment" could be done in a couple lines of shell script. But it would provide a lot of value for e.g. reproducible builds, CI maintainers, etc.

bsiegel avatar Jan 27 '21 20:01 bsiegel

I don't think jsDelivr's model works for us -- we don't follow SemVer and, realistically, "get me something for my Python version" is much easier to support than get-me-a-specific-version.


Now that the script for handling generation has been modernised in #85 and #100, this should be significantly easier to do. :)

pradyunsg avatar Feb 21 '21 10:02 pradyunsg

I think it’s a good idea to provide scripts for all versions, even if they are just duplicates to the main get-pip.py. Provision projects currently need to always refer to the versionless get-pip.py, which creates problems when the user provision with an old version of the tool after a Python version is dropped by pip, and the tool has no way to address this in a forward-compatible way.

If we provide scripts to all Python versions, tools can instead have something like

versioned_url = "https://bootstrap.pypa.io/{v.major}.{v.minor}/get-pip.py".format(v=sys.version_info)
script_path = _download_script(versioned_url)
subprocess.run([sys.executable, str(script_path)], check=True)

that’s guaranteed to work no matter in the future.

uranusjr avatar Mar 07 '21 18:03 uranusjr

Yup yup. That's why I've been making all the changes in this repository recently. ;)

pradyunsg avatar Mar 08 '21 19:03 pradyunsg

Alrighty, we can now do this. It's a matter of updating the following dictionary:

https://github.com/pypa/get-pip/blob/5a43acd2179f77d4e6385aa766cc7d7542d2eff7/scripts/generate.py#L20-L56

And updating the logic for how we determine the "minimum supported version" for the "default" get-pip.py script:

https://github.com/pypa/get-pip/blob/5a43acd2179f77d4e6385aa766cc7d7542d2eff7/scripts/generate.py#L159


The open question here is: how do we want to handle constraints for the versions of Python where we haven't dropped support yet? We do however need to care about the pip version, since that determines whether the script can run on the Python interpreter.

It's not a big deal for setuptools and wheel pins, since the newer versions of pip are Python-Requires aware -- so keeping them as empty strings is fine.

pradyunsg avatar Mar 14 '21 19:03 pradyunsg

Oh, I just realized... we do get the requires_python key in the JSON from PyPI -- we can use that information to populate the pip pin! We can probably remove the pip key from this mapping if we use this information!

Given that we don't need a setuptools/wheel pin anymore, that whole hard-coded-bits-of-information can be removed too, making this much easier to use as well.

pradyunsg avatar Mar 14 '21 19:03 pradyunsg

PRs to do this would be welcome!

pradyunsg avatar Jan 06 '22 09:01 pradyunsg