Edit File by line
/home/barbar84/www/wp-conte.../plugins/sujqvwi/ShExBy/shex_roo.../lib/python3..../site-pac.../pip
File: wheel.py
"""
[0] Fix | Delete
Support for installing and building the "wheel" binary package format.
[1] Fix | Delete
"""
[2] Fix | Delete
from __future__ import absolute_import
[3] Fix | Delete
[4] Fix | Delete
import compileall
[5] Fix | Delete
import csv
[6] Fix | Delete
import errno
[7] Fix | Delete
import functools
[8] Fix | Delete
import hashlib
[9] Fix | Delete
import logging
[10] Fix | Delete
import os
[11] Fix | Delete
import os.path
[12] Fix | Delete
import re
[13] Fix | Delete
import shutil
[14] Fix | Delete
import stat
[15] Fix | Delete
import sys
[16] Fix | Delete
import tempfile
[17] Fix | Delete
import warnings
[18] Fix | Delete
[19] Fix | Delete
from base64 import urlsafe_b64encode
[20] Fix | Delete
from email.parser import Parser
[21] Fix | Delete
[22] Fix | Delete
from pip._vendor.six import StringIO
[23] Fix | Delete
[24] Fix | Delete
import pip
[25] Fix | Delete
from pip.compat import expanduser
[26] Fix | Delete
from pip.download import path_to_url, unpack_url
[27] Fix | Delete
from pip.exceptions import (
[28] Fix | Delete
InstallationError, InvalidWheelFilename, UnsupportedWheel)
[29] Fix | Delete
from pip.locations import distutils_scheme, PIP_DELETE_MARKER_FILENAME
[30] Fix | Delete
from pip import pep425tags
[31] Fix | Delete
from pip.utils import (
[32] Fix | Delete
call_subprocess, ensure_dir, captured_stdout, rmtree, read_chunks,
[33] Fix | Delete
)
[34] Fix | Delete
from pip.utils.ui import open_spinner
[35] Fix | Delete
from pip.utils.logging import indent_log
[36] Fix | Delete
from pip.utils.setuptools_build import SETUPTOOLS_SHIM
[37] Fix | Delete
from pip._vendor.distlib.scripts import ScriptMaker
[38] Fix | Delete
from pip._vendor import pkg_resources
[39] Fix | Delete
from pip._vendor.packaging.utils import canonicalize_name
[40] Fix | Delete
from pip._vendor.six.moves import configparser
[41] Fix | Delete
[42] Fix | Delete
[43] Fix | Delete
wheel_ext = '.whl'
[44] Fix | Delete
[45] Fix | Delete
VERSION_COMPATIBLE = (1, 0)
[46] Fix | Delete
[47] Fix | Delete
[48] Fix | Delete
logger = logging.getLogger(__name__)
[49] Fix | Delete
[50] Fix | Delete
[51] Fix | Delete
class WheelCache(object):
[52] Fix | Delete
"""A cache of wheels for future installs."""
[53] Fix | Delete
[54] Fix | Delete
def __init__(self, cache_dir, format_control):
[55] Fix | Delete
"""Create a wheel cache.
[56] Fix | Delete
[57] Fix | Delete
:param cache_dir: The root of the cache.
[58] Fix | Delete
:param format_control: A pip.index.FormatControl object to limit
[59] Fix | Delete
binaries being read from the cache.
[60] Fix | Delete
"""
[61] Fix | Delete
self._cache_dir = expanduser(cache_dir) if cache_dir else None
[62] Fix | Delete
self._format_control = format_control
[63] Fix | Delete
[64] Fix | Delete
def cached_wheel(self, link, package_name):
[65] Fix | Delete
return cached_wheel(
[66] Fix | Delete
self._cache_dir, link, self._format_control, package_name)
[67] Fix | Delete
[68] Fix | Delete
[69] Fix | Delete
def _cache_for_link(cache_dir, link):
[70] Fix | Delete
"""
[71] Fix | Delete
Return a directory to store cached wheels in for link.
[72] Fix | Delete
[73] Fix | Delete
Because there are M wheels for any one sdist, we provide a directory
[74] Fix | Delete
to cache them in, and then consult that directory when looking up
[75] Fix | Delete
cache hits.
[76] Fix | Delete
[77] Fix | Delete
We only insert things into the cache if they have plausible version
[78] Fix | Delete
numbers, so that we don't contaminate the cache with things that were not
[79] Fix | Delete
unique. E.g. ./package might have dozens of installs done for it and build
[80] Fix | Delete
a version of 0.0...and if we built and cached a wheel, we'd end up using
[81] Fix | Delete
the same wheel even if the source has been edited.
[82] Fix | Delete
[83] Fix | Delete
:param cache_dir: The cache_dir being used by pip.
[84] Fix | Delete
:param link: The link of the sdist for which this will cache wheels.
[85] Fix | Delete
"""
[86] Fix | Delete
[87] Fix | Delete
# We want to generate an url to use as our cache key, we don't want to just
[88] Fix | Delete
# re-use the URL because it might have other items in the fragment and we
[89] Fix | Delete
# don't care about those.
[90] Fix | Delete
key_parts = [link.url_without_fragment]
[91] Fix | Delete
if link.hash_name is not None and link.hash is not None:
[92] Fix | Delete
key_parts.append("=".join([link.hash_name, link.hash]))
[93] Fix | Delete
key_url = "#".join(key_parts)
[94] Fix | Delete
[95] Fix | Delete
# Encode our key url with sha224, we'll use this because it has similar
[96] Fix | Delete
# security properties to sha256, but with a shorter total output (and thus
[97] Fix | Delete
# less secure). However the differences don't make a lot of difference for
[98] Fix | Delete
# our use case here.
[99] Fix | Delete
hashed = hashlib.sha224(key_url.encode()).hexdigest()
[100] Fix | Delete
[101] Fix | Delete
# We want to nest the directories some to prevent having a ton of top level
[102] Fix | Delete
# directories where we might run out of sub directories on some FS.
[103] Fix | Delete
parts = [hashed[:2], hashed[2:4], hashed[4:6], hashed[6:]]
[104] Fix | Delete
[105] Fix | Delete
# Inside of the base location for cached wheels, expand our parts and join
[106] Fix | Delete
# them all together.
[107] Fix | Delete
return os.path.join(cache_dir, "wheels", *parts)
[108] Fix | Delete
[109] Fix | Delete
[110] Fix | Delete
def cached_wheel(cache_dir, link, format_control, package_name):
[111] Fix | Delete
if not cache_dir:
[112] Fix | Delete
return link
[113] Fix | Delete
if not link:
[114] Fix | Delete
return link
[115] Fix | Delete
if link.is_wheel:
[116] Fix | Delete
return link
[117] Fix | Delete
if not link.is_artifact:
[118] Fix | Delete
return link
[119] Fix | Delete
if not package_name:
[120] Fix | Delete
return link
[121] Fix | Delete
canonical_name = canonicalize_name(package_name)
[122] Fix | Delete
formats = pip.index.fmt_ctl_formats(format_control, canonical_name)
[123] Fix | Delete
if "binary" not in formats:
[124] Fix | Delete
return link
[125] Fix | Delete
root = _cache_for_link(cache_dir, link)
[126] Fix | Delete
try:
[127] Fix | Delete
wheel_names = os.listdir(root)
[128] Fix | Delete
except OSError as e:
[129] Fix | Delete
if e.errno in (errno.ENOENT, errno.ENOTDIR):
[130] Fix | Delete
return link
[131] Fix | Delete
raise
[132] Fix | Delete
candidates = []
[133] Fix | Delete
for wheel_name in wheel_names:
[134] Fix | Delete
try:
[135] Fix | Delete
wheel = Wheel(wheel_name)
[136] Fix | Delete
except InvalidWheelFilename:
[137] Fix | Delete
continue
[138] Fix | Delete
if not wheel.supported():
[139] Fix | Delete
# Built for a different python/arch/etc
[140] Fix | Delete
continue
[141] Fix | Delete
candidates.append((wheel.support_index_min(), wheel_name))
[142] Fix | Delete
if not candidates:
[143] Fix | Delete
return link
[144] Fix | Delete
candidates.sort()
[145] Fix | Delete
path = os.path.join(root, candidates[0][1])
[146] Fix | Delete
return pip.index.Link(path_to_url(path))
[147] Fix | Delete
[148] Fix | Delete
[149] Fix | Delete
def rehash(path, algo='sha256', blocksize=1 << 20):
[150] Fix | Delete
"""Return (hash, length) for path using hashlib.new(algo)"""
[151] Fix | Delete
h = hashlib.new(algo)
[152] Fix | Delete
length = 0
[153] Fix | Delete
with open(path, 'rb') as f:
[154] Fix | Delete
for block in read_chunks(f, size=blocksize):
[155] Fix | Delete
length += len(block)
[156] Fix | Delete
h.update(block)
[157] Fix | Delete
digest = 'sha256=' + urlsafe_b64encode(
[158] Fix | Delete
h.digest()
[159] Fix | Delete
).decode('latin1').rstrip('=')
[160] Fix | Delete
return (digest, length)
[161] Fix | Delete
[162] Fix | Delete
[163] Fix | Delete
def open_for_csv(name, mode):
[164] Fix | Delete
if sys.version_info[0] < 3:
[165] Fix | Delete
nl = {}
[166] Fix | Delete
bin = 'b'
[167] Fix | Delete
else:
[168] Fix | Delete
nl = {'newline': ''}
[169] Fix | Delete
bin = ''
[170] Fix | Delete
return open(name, mode + bin, **nl)
[171] Fix | Delete
[172] Fix | Delete
[173] Fix | Delete
def fix_script(path):
[174] Fix | Delete
"""Replace #!python with #!/path/to/python
[175] Fix | Delete
Return True if file was changed."""
[176] Fix | Delete
# XXX RECORD hashes will need to be updated
[177] Fix | Delete
if os.path.isfile(path):
[178] Fix | Delete
with open(path, 'rb') as script:
[179] Fix | Delete
firstline = script.readline()
[180] Fix | Delete
if not firstline.startswith(b'#!python'):
[181] Fix | Delete
return False
[182] Fix | Delete
exename = sys.executable.encode(sys.getfilesystemencoding())
[183] Fix | Delete
firstline = b'#!' + exename + os.linesep.encode("ascii")
[184] Fix | Delete
rest = script.read()
[185] Fix | Delete
with open(path, 'wb') as script:
[186] Fix | Delete
script.write(firstline)
[187] Fix | Delete
script.write(rest)
[188] Fix | Delete
return True
[189] Fix | Delete
[190] Fix | Delete
dist_info_re = re.compile(r"""^(?P<namever>(?P<name>.+?)(-(?P<ver>\d.+?))?)
[191] Fix | Delete
\.dist-info$""", re.VERBOSE)
[192] Fix | Delete
[193] Fix | Delete
[194] Fix | Delete
def root_is_purelib(name, wheeldir):
[195] Fix | Delete
"""
[196] Fix | Delete
Return True if the extracted wheel in wheeldir should go into purelib.
[197] Fix | Delete
"""
[198] Fix | Delete
name_folded = name.replace("-", "_")
[199] Fix | Delete
for item in os.listdir(wheeldir):
[200] Fix | Delete
match = dist_info_re.match(item)
[201] Fix | Delete
if match and match.group('name') == name_folded:
[202] Fix | Delete
with open(os.path.join(wheeldir, item, 'WHEEL')) as wheel:
[203] Fix | Delete
for line in wheel:
[204] Fix | Delete
line = line.lower().rstrip()
[205] Fix | Delete
if line == "root-is-purelib: true":
[206] Fix | Delete
return True
[207] Fix | Delete
return False
[208] Fix | Delete
[209] Fix | Delete
[210] Fix | Delete
def get_entrypoints(filename):
[211] Fix | Delete
if not os.path.exists(filename):
[212] Fix | Delete
return {}, {}
[213] Fix | Delete
[214] Fix | Delete
# This is done because you can pass a string to entry_points wrappers which
[215] Fix | Delete
# means that they may or may not be valid INI files. The attempt here is to
[216] Fix | Delete
# strip leading and trailing whitespace in order to make them valid INI
[217] Fix | Delete
# files.
[218] Fix | Delete
with open(filename) as fp:
[219] Fix | Delete
data = StringIO()
[220] Fix | Delete
for line in fp:
[221] Fix | Delete
data.write(line.strip())
[222] Fix | Delete
data.write("\n")
[223] Fix | Delete
data.seek(0)
[224] Fix | Delete
[225] Fix | Delete
cp = configparser.RawConfigParser()
[226] Fix | Delete
cp.optionxform = lambda option: option
[227] Fix | Delete
cp.readfp(data)
[228] Fix | Delete
[229] Fix | Delete
console = {}
[230] Fix | Delete
gui = {}
[231] Fix | Delete
if cp.has_section('console_scripts'):
[232] Fix | Delete
console = dict(cp.items('console_scripts'))
[233] Fix | Delete
if cp.has_section('gui_scripts'):
[234] Fix | Delete
gui = dict(cp.items('gui_scripts'))
[235] Fix | Delete
return console, gui
[236] Fix | Delete
[237] Fix | Delete
[238] Fix | Delete
def move_wheel_files(name, req, wheeldir, user=False, home=None, root=None,
[239] Fix | Delete
pycompile=True, scheme=None, isolated=False, prefix=None, strip_file_prefix=None):
[240] Fix | Delete
"""Install a wheel"""
[241] Fix | Delete
[242] Fix | Delete
if not scheme:
[243] Fix | Delete
scheme = distutils_scheme(
[244] Fix | Delete
name, user=user, home=home, root=root, isolated=isolated,
[245] Fix | Delete
prefix=prefix,
[246] Fix | Delete
)
[247] Fix | Delete
[248] Fix | Delete
if root_is_purelib(name, wheeldir):
[249] Fix | Delete
lib_dir = scheme['purelib']
[250] Fix | Delete
else:
[251] Fix | Delete
lib_dir = scheme['platlib']
[252] Fix | Delete
[253] Fix | Delete
info_dir = []
[254] Fix | Delete
data_dirs = []
[255] Fix | Delete
source = wheeldir.rstrip(os.path.sep) + os.path.sep
[256] Fix | Delete
[257] Fix | Delete
# Record details of the files moved
[258] Fix | Delete
# installed = files copied from the wheel to the destination
[259] Fix | Delete
# changed = files changed while installing (scripts #! line typically)
[260] Fix | Delete
# generated = files newly generated during the install (script wrappers)
[261] Fix | Delete
installed = {}
[262] Fix | Delete
changed = set()
[263] Fix | Delete
generated = []
[264] Fix | Delete
[265] Fix | Delete
# Compile all of the pyc files that we're going to be installing
[266] Fix | Delete
if pycompile:
[267] Fix | Delete
with captured_stdout() as stdout:
[268] Fix | Delete
with warnings.catch_warnings():
[269] Fix | Delete
warnings.filterwarnings('ignore')
[270] Fix | Delete
compileall.compile_dir(source, force=True, quiet=True)
[271] Fix | Delete
logger.debug(stdout.getvalue())
[272] Fix | Delete
[273] Fix | Delete
def normpath(src, p):
[274] Fix | Delete
return os.path.relpath(src, p).replace(os.path.sep, '/')
[275] Fix | Delete
[276] Fix | Delete
def record_installed(srcfile, destfile, modified=False):
[277] Fix | Delete
"""Map archive RECORD paths to installation RECORD paths."""
[278] Fix | Delete
oldpath = normpath(srcfile, wheeldir)
[279] Fix | Delete
newpath = normpath(destfile, lib_dir)
[280] Fix | Delete
installed[oldpath] = newpath
[281] Fix | Delete
if modified:
[282] Fix | Delete
changed.add(destfile)
[283] Fix | Delete
[284] Fix | Delete
def clobber(source, dest, is_base, fixer=None, filter=None):
[285] Fix | Delete
ensure_dir(dest) # common for the 'include' path
[286] Fix | Delete
[287] Fix | Delete
for dir, subdirs, files in os.walk(source):
[288] Fix | Delete
basedir = dir[len(source):].lstrip(os.path.sep)
[289] Fix | Delete
destdir = os.path.join(dest, basedir)
[290] Fix | Delete
if is_base and basedir.split(os.path.sep, 1)[0].endswith('.data'):
[291] Fix | Delete
continue
[292] Fix | Delete
for s in subdirs:
[293] Fix | Delete
destsubdir = os.path.join(dest, basedir, s)
[294] Fix | Delete
if is_base and basedir == '' and destsubdir.endswith('.data'):
[295] Fix | Delete
data_dirs.append(s)
[296] Fix | Delete
continue
[297] Fix | Delete
elif (is_base and
[298] Fix | Delete
s.endswith('.dist-info') and
[299] Fix | Delete
canonicalize_name(s).startswith(
[300] Fix | Delete
canonicalize_name(req.name))):
[301] Fix | Delete
assert not info_dir, ('Multiple .dist-info directories: ' +
[302] Fix | Delete
destsubdir + ', ' +
[303] Fix | Delete
', '.join(info_dir))
[304] Fix | Delete
info_dir.append(destsubdir)
[305] Fix | Delete
for f in files:
[306] Fix | Delete
# Skip unwanted files
[307] Fix | Delete
if filter and filter(f):
[308] Fix | Delete
continue
[309] Fix | Delete
srcfile = os.path.join(dir, f)
[310] Fix | Delete
destfile = os.path.join(dest, basedir, f)
[311] Fix | Delete
# directory creation is lazy and after the file filtering above
[312] Fix | Delete
# to ensure we don't install empty dirs; empty dirs can't be
[313] Fix | Delete
# uninstalled.
[314] Fix | Delete
ensure_dir(destdir)
[315] Fix | Delete
[316] Fix | Delete
# We use copyfile (not move, copy, or copy2) to be extra sure
[317] Fix | Delete
# that we are not moving directories over (copyfile fails for
[318] Fix | Delete
# directories) as well as to ensure that we are not copying
[319] Fix | Delete
# over any metadata because we want more control over what
[320] Fix | Delete
# metadata we actually copy over.
[321] Fix | Delete
shutil.copyfile(srcfile, destfile)
[322] Fix | Delete
[323] Fix | Delete
# Copy over the metadata for the file, currently this only
[324] Fix | Delete
# includes the atime and mtime.
[325] Fix | Delete
st = os.stat(srcfile)
[326] Fix | Delete
if hasattr(os, "utime"):
[327] Fix | Delete
os.utime(destfile, (st.st_atime, st.st_mtime))
[328] Fix | Delete
[329] Fix | Delete
# If our file is executable, then make our destination file
[330] Fix | Delete
# executable.
[331] Fix | Delete
if os.access(srcfile, os.X_OK):
[332] Fix | Delete
st = os.stat(srcfile)
[333] Fix | Delete
permissions = (
[334] Fix | Delete
st.st_mode | stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH
[335] Fix | Delete
)
[336] Fix | Delete
os.chmod(destfile, permissions)
[337] Fix | Delete
[338] Fix | Delete
changed = False
[339] Fix | Delete
if fixer:
[340] Fix | Delete
changed = fixer(destfile)
[341] Fix | Delete
record_installed(srcfile, destfile, changed)
[342] Fix | Delete
[343] Fix | Delete
clobber(source, lib_dir, True)
[344] Fix | Delete
[345] Fix | Delete
assert info_dir, "%s .dist-info directory not found" % req
[346] Fix | Delete
[347] Fix | Delete
# Get the defined entry points
[348] Fix | Delete
ep_file = os.path.join(info_dir[0], 'entry_points.txt')
[349] Fix | Delete
console, gui = get_entrypoints(ep_file)
[350] Fix | Delete
[351] Fix | Delete
def is_entrypoint_wrapper(name):
[352] Fix | Delete
# EP, EP.exe and EP-script.py are scripts generated for
[353] Fix | Delete
# entry point EP by setuptools
[354] Fix | Delete
if name.lower().endswith('.exe'):
[355] Fix | Delete
matchname = name[:-4]
[356] Fix | Delete
elif name.lower().endswith('-script.py'):
[357] Fix | Delete
matchname = name[:-10]
[358] Fix | Delete
elif name.lower().endswith(".pya"):
[359] Fix | Delete
matchname = name[:-4]
[360] Fix | Delete
else:
[361] Fix | Delete
matchname = name
[362] Fix | Delete
# Ignore setuptools-generated scripts
[363] Fix | Delete
return (matchname in console or matchname in gui)
[364] Fix | Delete
[365] Fix | Delete
for datadir in data_dirs:
[366] Fix | Delete
fixer = None
[367] Fix | Delete
filter = None
[368] Fix | Delete
for subdir in os.listdir(os.path.join(wheeldir, datadir)):
[369] Fix | Delete
fixer = None
[370] Fix | Delete
if subdir == 'scripts':
[371] Fix | Delete
fixer = fix_script
[372] Fix | Delete
filter = is_entrypoint_wrapper
[373] Fix | Delete
source = os.path.join(wheeldir, datadir, subdir)
[374] Fix | Delete
dest = scheme[subdir]
[375] Fix | Delete
clobber(source, dest, False, fixer=fixer, filter=filter)
[376] Fix | Delete
[377] Fix | Delete
maker = ScriptMaker(None, scheme['scripts'])
[378] Fix | Delete
[379] Fix | Delete
# Ensure old scripts are overwritten.
[380] Fix | Delete
# See https://github.com/pypa/pip/issues/1800
[381] Fix | Delete
maker.clobber = True
[382] Fix | Delete
[383] Fix | Delete
# Ensure we don't generate any variants for scripts because this is almost
[384] Fix | Delete
# never what somebody wants.
[385] Fix | Delete
# See https://bitbucket.org/pypa/distlib/issue/35/
[386] Fix | Delete
maker.variants = set(('', ))
[387] Fix | Delete
[388] Fix | Delete
# This is required because otherwise distlib creates scripts that are not
[389] Fix | Delete
# executable.
[390] Fix | Delete
# See https://bitbucket.org/pypa/distlib/issue/32/
[391] Fix | Delete
maker.set_mode = True
[392] Fix | Delete
[393] Fix | Delete
# Simplify the script and fix the fact that the default script swallows
[394] Fix | Delete
# every single stack trace.
[395] Fix | Delete
# See https://bitbucket.org/pypa/distlib/issue/34/
[396] Fix | Delete
# See https://bitbucket.org/pypa/distlib/issue/33/
[397] Fix | Delete
def _get_script_text(entry):
[398] Fix | Delete
if entry.suffix is None:
[399] Fix | Delete
raise InstallationError(
[400] Fix | Delete
"Invalid script entry point: %s for req: %s - A callable "
[401] Fix | Delete
"suffix is required. Cf https://packaging.python.org/en/"
[402] Fix | Delete
"latest/distributing.html#console-scripts for more "
[403] Fix | Delete
"information." % (entry, req)
[404] Fix | Delete
)
[405] Fix | Delete
return maker.script_template % {
[406] Fix | Delete
"module": entry.prefix,
[407] Fix | Delete
"import_name": entry.suffix.split(".")[0],
[408] Fix | Delete
"func": entry.suffix,
[409] Fix | Delete
}
[410] Fix | Delete
[411] Fix | Delete
maker._get_script_text = _get_script_text
[412] Fix | Delete
maker.script_template = """# -*- coding: utf-8 -*-
[413] Fix | Delete
import re
[414] Fix | Delete
import sys
[415] Fix | Delete
[416] Fix | Delete
from %(module)s import %(import_name)s
[417] Fix | Delete
[418] Fix | Delete
if __name__ == '__main__':
[419] Fix | Delete
sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
[420] Fix | Delete
sys.exit(%(func)s())
[421] Fix | Delete
"""
[422] Fix | Delete
[423] Fix | Delete
# Special case pip and setuptools to generate versioned wrappers
[424] Fix | Delete
#
[425] Fix | Delete
# The issue is that some projects (specifically, pip and setuptools) use
[426] Fix | Delete
# code in setup.py to create "versioned" entry points - pip2.7 on Python
[427] Fix | Delete
# 2.7, pip3.3 on Python 3.3, etc. But these entry points are baked into
[428] Fix | Delete
# the wheel metadata at build time, and so if the wheel is installed with
[429] Fix | Delete
# a *different* version of Python the entry points will be wrong. The
[430] Fix | Delete
# correct fix for this is to enhance the metadata to be able to describe
[431] Fix | Delete
# such versioned entry points, but that won't happen till Metadata 2.0 is
[432] Fix | Delete
# available.
[433] Fix | Delete
# In the meantime, projects using versioned entry points will either have
[434] Fix | Delete
# incorrect versioned entry points, or they will not be able to distribute
[435] Fix | Delete
# "universal" wheels (i.e., they will need a wheel per Python version).
[436] Fix | Delete
#
[437] Fix | Delete
# Because setuptools and pip are bundled with _ensurepip and virtualenv,
[438] Fix | Delete
# we need to use universal wheels. So, as a stopgap until Metadata 2.0, we
[439] Fix | Delete
# override the versioned entry points in the wheel and generate the
[440] Fix | Delete
# correct ones. This code is purely a short-term measure until Metadata 2.0
[441] Fix | Delete
# is available.
[442] Fix | Delete
#
[443] Fix | Delete
# To add the level of hack in this section of code, in order to support
[444] Fix | Delete
# ensurepip this code will look for an ``ENSUREPIP_OPTIONS`` environment
[445] Fix | Delete
# variable which will control which version scripts get installed.
[446] Fix | Delete
#
[447] Fix | Delete
# ENSUREPIP_OPTIONS=altinstall
[448] Fix | Delete
# - Only pipX.Y and easy_install-X.Y will be generated and installed
[449] Fix | Delete
# ENSUREPIP_OPTIONS=install
[450] Fix | Delete
# - pipX.Y, pipX, easy_install-X.Y will be generated and installed. Note
[451] Fix | Delete
# that this option is technically if ENSUREPIP_OPTIONS is set and is
[452] Fix | Delete
# not altinstall
[453] Fix | Delete
# DEFAULT
[454] Fix | Delete
# - The default behavior is to install pip, pipX, pipX.Y, easy_install
[455] Fix | Delete
# and easy_install-X.Y.
[456] Fix | Delete
pip_script = console.pop('pip', None)
[457] Fix | Delete
if pip_script:
[458] Fix | Delete
if "ENSUREPIP_OPTIONS" not in os.environ:
[459] Fix | Delete
spec = 'pip = ' + pip_script
[460] Fix | Delete
generated.extend(maker.make(spec))
[461] Fix | Delete
[462] Fix | Delete
if os.environ.get("ENSUREPIP_OPTIONS", "") != "altinstall":
[463] Fix | Delete
spec = 'pip%s = %s' % (sys.version[:1], pip_script)
[464] Fix | Delete
generated.extend(maker.make(spec))
[465] Fix | Delete
[466] Fix | Delete
spec = 'pip%s = %s' % (sys.version[:3], pip_script)
[467] Fix | Delete
generated.extend(maker.make(spec))
[468] Fix | Delete
# Delete any other versioned pip entry points
[469] Fix | Delete
pip_ep = [k for k in console if re.match(r'pip(\d(\.\d)?)?$', k)]
[470] Fix | Delete
for k in pip_ep:
[471] Fix | Delete
del console[k]
[472] Fix | Delete
easy_install_script = console.pop('easy_install', None)
[473] Fix | Delete
if easy_install_script:
[474] Fix | Delete
if "ENSUREPIP_OPTIONS" not in os.environ:
[475] Fix | Delete
spec = 'easy_install = ' + easy_install_script
[476] Fix | Delete
generated.extend(maker.make(spec))
[477] Fix | Delete
[478] Fix | Delete
spec = 'easy_install-%s = %s' % (sys.version[:3], easy_install_script)
[479] Fix | Delete
generated.extend(maker.make(spec))
[480] Fix | Delete
# Delete any other versioned easy_install entry points
[481] Fix | Delete
easy_install_ep = [
[482] Fix | Delete
k for k in console if re.match(r'easy_install(-\d\.\d)?$', k)
[483] Fix | Delete
]
[484] Fix | Delete
for k in easy_install_ep:
[485] Fix | Delete
del console[k]
[486] Fix | Delete
[487] Fix | Delete
# Generate the console and GUI entry points specified in the wheel
[488] Fix | Delete
if len(console) > 0:
[489] Fix | Delete
generated.extend(
[490] Fix | Delete
maker.make_multiple(['%s = %s' % kv for kv in console.items()])
[491] Fix | Delete
)
[492] Fix | Delete
if len(gui) > 0:
[493] Fix | Delete
generated.extend(
[494] Fix | Delete
maker.make_multiple(
[495] Fix | Delete
['%s = %s' % kv for kv in gui.items()],
[496] Fix | Delete
{'gui': True}
[497] Fix | Delete
)
[498] Fix | Delete
)
[499] Fix | Delete
12
It is recommended that you Edit text format, this type of Fix handles quite a lot in one request
Function