Skip to content
Snippets Groups Projects
get-pip.py 2.46 MiB
Newer Older
#!/usr/bin/env python
#
# Hi There!
#
# You may be wondering what this giant blob of binary data here is, you might
# even be worried that we're up to something nefarious (good for you for being
# paranoid!). This is a base85 encoding of a zip file, this zip file contains
# an entire copy of pip (version 23.0).
#
# Pip is a thing that installs packages, pip itself is a package that someone
# might want to install, especially if they're looking to run this get-pip.py
# script. Pip has a lot of code to deal with the security of installing
# packages, various edge cases on various platforms, and other such sort of
# "tribal knowledge" that has been encoded in its code base. Because of this
# we basically include an entire copy of pip inside this blob. We do this
# because the alternatives are attempt to implement a "minipip" that probably
# doesn't do things correctly and has weird edge cases, or compress pip itself
# down into a single file.
#
# If you're wondering how this is created, it is generated using
# `scripts/generate.py` in https://github.com/pypa/get-pip.

import sys

this_python = sys.version_info[:2]
min_version = (3, 7)
if this_python < min_version:
    message_parts = [
        "This script does not work on Python {}.{}".format(*this_python),
        "The minimum supported Python version is {}.{}.".format(*min_version),
        "Please use https://bootstrap.pypa.io/pip/{}.{}/get-pip.py instead.".format(*this_python),
    ]
    print("ERROR: " + " ".join(message_parts))
    sys.exit(1)


import os.path
import pkgutil
import shutil
import tempfile
import argparse
import importlib
from base64 import b85decode


def include_setuptools(args):
    """
    Install setuptools only if absent and not excluded.
    """
    cli = not args.no_setuptools
    env = not os.environ.get("PIP_NO_SETUPTOOLS")
    absent = not importlib.util.find_spec("setuptools")
    return cli and env and absent


def include_wheel(args):
    """
    Install wheel only if absent and not excluded.
    """
    cli = not args.no_wheel
    env = not os.environ.get("PIP_NO_WHEEL")
    absent = not importlib.util.find_spec("wheel")
    return cli and env and absent


def determine_pip_install_arguments():
    pre_parser = argparse.ArgumentParser()
    pre_parser.add_argument("--no-setuptools", action="store_true")
    pre_parser.add_argument("--no-wheel", action="store_true")
    pre, args = pre_parser.parse_known_args()

    args.append("pip")

    if include_setuptools(pre):
        args.append("setuptools")

    if include_wheel(pre):
        args.append("wheel")

    return ["install", "--upgrade", "--force-reinstall"] + args


def monkeypatch_for_cert(tmpdir):
    """Patches `pip install` to provide default certificate with the lowest priority.

    This ensures that the bundled certificates are used unless the user specifies a
    custom cert via any of pip's option passing mechanisms (config, env-var, CLI).

    A monkeypatch is the easiest way to achieve this, without messing too much with
    the rest of pip's internals.
    """
    from pip._internal.commands.install import InstallCommand

    # We want to be using the internal certificates.
    cert_path = os.path.join(tmpdir, "cacert.pem")
    with open(cert_path, "wb") as cert:
        cert.write(pkgutil.get_data("pip._vendor.certifi", "cacert.pem"))

    install_parse_args = InstallCommand.parse_args

    def cert_parse_args(self, args):
        if not self.parser.get_default_values().cert:
            # There are no user provided cert -- force use of bundled cert
            self.parser.defaults["cert"] = cert_path  # calculated above
        return install_parse_args(self, args)

    InstallCommand.parse_args = cert_parse_args


def bootstrap(tmpdir):
    monkeypatch_for_cert(tmpdir)

    # Execute the included pip and use it to install the latest pip and
    # setuptools from PyPI
    from pip._internal.cli.main import main as pip_entry_point
    args = determine_pip_install_arguments()
    sys.exit(pip_entry_point(args))


def main():
    tmpdir = None
    try:
        # Create a temporary working directory
        tmpdir = tempfile.mkdtemp()

        # Unpack the zipfile into the temporary directory
        pip_zip = os.path.join(tmpdir, "pip.zip")
        with open(pip_zip, "wb") as fp:
            fp.write(b85decode(DATA.replace(b"\n", b"")))

        # Add the zipfile to sys.path so that we can import it
        sys.path.insert(0, pip_zip)

        # Run the bootstrap
        bootstrap(tmpdir=tmpdir)
    finally:
        # Clean up our temporary working directory
        if tmpdir:
            shutil.rmtree(tmpdir, ignore_errors=True)


DATA = b"""
P)h>@6aWAK2mngCK33$8H+}X1003hF000jF003}la4%n9X>MtBUtcb8c|B0UO2j}6z0X&KUUXrd5f#*
ef)_y$_26w;%50mqfp%s{QkVX{vt7C&5b}6=dAye62s$SU9nhE}D}0jZ7QT~G41O@Cs{W8AFI5FEP~6
?y+rk*rU<;$CaP7I1^1|Pp&Ud1`-)Ht$47h=tSD>J!fm}sV{PrY}+lLd3oUh>R=L2FGW*E^2g*Gxwf^
e82QMwX{#{hK<5(fmSnUab%i{N{v`lg}tduUKS4YCD6gkCjC>0C$JPX}Aa(WN<gmo*)UOepU0;rYp~&
X(DpBFPL}t?ulkS<+%qo>R=ItXWk@_9-EstuX4u;Q}tnY|KAUO9KQH0000807|(&RwEnZzik2l0Imc8
01p5F0B~t=FJE76VQFq(UoLQYT~onsoG=i*^A#g<SawB74(*{)w^F5Ea_J$eltWV?7ly@Ju#s(+Y`?y
54D2T1gzYzP-n^O7{a{@n>k~cy`Say>QqE{|@JVt*Pu$xR(`G};)Krbmu>r!mBM?+;$5pWIOpUWWg_f
z&&Iba>oe^#uAua|L+MIMlgJUlQ!IC;zUDN1=XXU-{AygY0^gxyEd!+VMwOk!@Bx3%@ATvIwuFI*@$S
2}_Yo{E6Q_BX=Cwt_Yl&9ewT5IUGk9=Pj!f%PbYWscvNAhK9n!}Rfz@eJzY`c9(2;Yh-20LW;Te0P_p
@~U3CN~-}Yc@bha)u~X*U^o5lxkNF#QtivCrG!GkC@S`1FtF}@pe~CZFeVPmm;sXBDyRGRUHvimbBkf
n$9Y3@X+W^Zo&VK=dLV!rA=8D!+F8ZZGzuM^-Pr{@xkfAOUpKI12#E%uB;fm0t5lt&BFD>e(ZvnAQeh
>DJv3#>}rD!p1WoV`W_up;jKC3t=L*A^lu(TWQq9rx|iO>Ml8CskLT5a?e=}+;3K<`-RF@A9gH?g$l~
Ez@5Re!OgQ>$M>98)owJS{iz<v2hUMnV=TAb&rk2tbX4?+z;OuL$ko>fPALucNCG2JJwd!U=<`o0D3y
8tH=Rmu^+*rrErFsAsqWOavxeT-r)QnZCRM422Rt->rnF_0ILHAe@V}p#R9A-u9Vi$AT^_V3~0!sD4K
mfJ?)O^4q?tfepJ<s@@dRvbj@6%#8Pa-Z~UWyYt4^$f2<_5&2fb62w1__PoimKCvc)d!E|0pUpAi1=S
Uv<dh9o8`U4^T@31QY-O00;m|xjt5Y2PKuz0ssJ{1pojQ0001RX>c!JUvOz~Epl~kZe?;`UoLQYeN@4
2+b|5h`ztv2FdJ~aq8%_GScU;biuKZDNqQK%LQrhF(Pm4oBxf;-{`*KfPTHWG4v8d_kB^Vf4#RM=#jN
oNxRseNTkvb;ATxCfrhr=23H(uXr$IuliUKWa52!cF8eP#o4T2@76skm^e=RG_K{`;LjtO`}(XO#b$k
O-lmB|~5&ZK_tVMS?GZLFuXjgo=XyE8a1J@z%iFbskd`0(y0bk#O!oidt;R<-nMrAp;n$kv$s28WsFX
I0}m^jYiIbUfb&mzXkA5Dax%$KaQyR>YyOrXmdA)M?!YvmeWE(;G3Le80V(PZltS=punnaS#MK76T9A
yp4AIcm!|)zO8Wt>OmWe0noC9Xf=dsnEo<KM_on?g|V;!l6S}^U{x@sbih`+Fn6Q#d-x1TY(_n@R1RU
$IudKLRX*x&d4;dE>gNf$L7I}Gwwt<ZzwY&UdWOj2W1}oR|1y4hj)^MKtK<trUN3uoi)Wm?3OV8&@3H
z_%+g=6=4<j67)^%jtO1SN&+Y;Wl%yY$p;isM2uULC<+h))#Y!qoKyS@@KWE!$vNa7yn@2f<$;Y$vpq
qC8yi}{Sk{Nj&Z98~yCjI(K=^X7_iN>W=WjzGv%Ch~BB7@oWOf06i^UKLX%%{^OnP?Xo4gW&$`y)im^
Uq4@9L!XG-NDY0qS({=p=Z*M{c9IiAvK(L7wpG^0)(qEiyW3k0!34nTp$7FIleKPwqDu?^xfefX5~dL
9J1lv7(((+IC^D-ouwHk*gxRn)Zjt4^uX!B=I&UN`+?TMAJiT4+ew)TM8^q--VPZ%LYzS|vNuT{DY*4
iX-13AlK%)BvHZKTLNK-vFs9yxV1Ee_CJ<gq&2JBxiDF2UQ`(VZgrLs_fA=KKUY~OO?mHI-o$*ro75z
=riJ34)S7rRNfGj<s5&7}bHq_i-P)h>@6aWAK2mngCK32`gz%{@C0015V000aC003}la4&FqE_8WtWn
?9eu};M>3`O^T#obt*`VR~YY;QnfHmzwbC3ciJh5S8E87&>(bBYv517WkANp~bsMyYmG$}2ukNeuDHN
G^#ptMd*~JcpmA56q`#0W5TpB>IYnZ>tlx>JJR-$h|q#9KFT3l$ThGovM`Z`h1@k{0zqrjTIlGh#re*
%w%#go%(3HWDhs}=jz2OtQ*5LjXNW#DIpx4DusYoy!{s5eCbN6)&t+MoumghxP_Ew!2Ru`@Lf_lF*R=
M@&`~$0|XQR000O8O1VB(mbGx9Q2_t|Jpup#82|tPaA|NaUukZ1WpZv|Y%gD5X>MtBUtcb8d3BL7PsA
_`h4=gl>sYQ5qze*o5{yhISlAFch1PA2(j?d}sQ(_fa3Cbe66?u%{_@;$9zo|qsRtTMW`#Y8p2B@m$|
*$WzT`s1A1EoZseV$5;wimgqX)reVpI-E)>b%ylwX7E7V|&e9VZ=P?wvaUN~BBO8^yMQaT0}RgeJs@t
yNuSgplS{0nPB$>wDC_mB`!5Y~BZI1{gvqm;{0z$K(#iY?fngr-<U+GRyxS>YQuQ`U0hG;9hpHJtpwD
1o9}#PfrzG!(C2T!P$*b>&}6l&1Um3ko`)aFbeXUQ5!Sl*g}(&<cJ^*Q&9mO3~UTDh$Ru1Z!&hsm>T0
)?MS^_i(9h@ZA+gR(4qzl?-T?P2Gt_Fy6#Db>Df1Vtjk<NZE4peGNIHL=U12h2)N$=?ZabIo=Z0MXE*
P>1j(N$w%v)-x41@BxeriF0|XQR000O8O1VB(|7DJuC=37q&?f)@8UO$QaA|NaUukZ1WpZv|Y%gMUX>
4R)Wo~vZaCy~Q-E-Tx5r5ZTfie$Awj?i?r;a9Sn>fnFQ`hz+&b2ol4UZ<Fm^DSR0BKw2@&Df41waBMr
Q|w&IX%P@uvqNJZ$ALU^SrlRQRZx2-4~*+cD!m?Cwb1cwP1y;%d{=(ishXssxM6Dg>2aku7IBl&+`_G
V%OB7Wo7;43y$fZwKU(Fw7o5h8}m~ZE$_eYd#aW{whtn07F$v8SXP%M&v0kSG{J?)x#0P`B5M^*yKi_
udnMA0-=x{y6^!=tD6%2=`Es3{d|03S{q+3Dke#+%q&FoG*%@dQvWo^cOUsab;_&mTYjBR3DQ->C#K}
Fc@>;|h7j3aE4C{wm5Nt}-fHWzZBo_QXT_HHywio#0Fm`O|Jr@$~uUGw~ehxC3i6q$;B~KETN*qqgIw
Qwfyo(BS1{LG1EMf_^seqYTUpKr;^x)hY!>?c9FBp8j@HSB(;d#Ob2qiZ~m7wFp<79vfB9jAM15_|<4
RnIjKrkoRj<;!^wyBW|SLA$~c4cet6w-t>FvqKFi&Dn2yJ<w7aoOvdrDd56!-to)eAgs-A$rik?|0zk
tgXd9WH=48$z4(95&~!IqH;+p&oBpa{-{C0!O`%u-{Mk@zNf*(0;3QnS0)@|Q2UI={3NN;9Y7>lEEZX
rf_llN;M?L+?F&W&6cts`CW$Y3xeY0DmrS-IV9{ULd0lZuiXWtikpT9>KkkI&ZP&oe`?QqYokC=wiB?
|+kB|QZ?s7y7ESJaD_o&hg77J7k$wgOH81@Mm*e9((JEaulvLAWNQig%V+8VS16T#n<UGCdkh(Z3yv#
wQH1IB?DYi~KrIw4@!avvdgOgZSi1u?z4EdWJQWmLT;rMMm76slBP$rfOS%iVNQ!7|*2k}ff|RE>@3^
jFrM$hdY07$LqSBU<SofLsI?yXSrY&O@=4oB+kDZZ(6rkZ58*7`**LY4T8aP%3WI2C@aNk@b!PDwKv=
a|K{fr^q?z`YVorMPqh~=1N<OXO>DZ<pY>7t<Xd?&vFWwav%4U0?;HXbd|3p43yM*yq57+<~*x&uIJh
J%uCS6<Pt8DByRSe0YZXEfYJlum|!*1fh83nApc*(P8$amikfN{GvrE!&$0uz?UmLzj}d2cRf+7TYuO
eEu|zSz(l1tK^MmiL#ODXUplQ1*y-$l0(MAk>U>t*4!KC2*7B&SKuuO17KfBpmqpx4R)CT%U29n@gu}
jP1SD=K*Wc3zp3I38Ueqh_%RHiN388ir)H`2wkAYmC0gK<uEU&Stm9AHDqlK(Y(^^(<4<Q@d^Aui3HJ
rode9c6Qyp~b{Dre#aplCeeJ>Oj1!>W2y=aaUk;-=Yyh@{YVka97{8Xk?0OK&QPUmHDwmfEh3uyWtQJ
5VD|3&io$ygQmeDyIng#2$_R~jScfBz&QqXjNU}yRCc56L5UdTwwXWod7e5vtHJA`eM0b&EUj|3ODj|
ezB7|l?M#C<(>Y3|A}AP*qy})ddd!rJzB;bl!suf?Tsg%te*5|K>|L@x{|PKo);AbpiIOm1U5U<QfW9
mw4V5x7snsd^Jr%_e7QoPyJ>S^#-*r*>MmQP@8Bzv8;4DW&<2V}H_f$-I5G07-GR6F2C@0eCq9>QsZc
Loading
Loading full blame...