| Index: bootstrap/virtualenv/virtualenv.py
|
| diff --git a/bootstrap/virtualenv/virtualenv.py b/bootstrap/virtualenv/virtualenv.py
|
| old mode 100755
|
| new mode 100644
|
| index 380a6013d42cd761107e28f289a9fab433704bc4..42cd1f4b01f297714e53c9b0a766dc1915151be7
|
| --- a/bootstrap/virtualenv/virtualenv.py
|
| +++ b/bootstrap/virtualenv/virtualenv.py
|
| @@ -1,34 +1,17 @@
|
| #!/usr/bin/env python
|
| -"""Create a "virtual" Python installation
|
| -"""
|
| +"""Create a "virtual" Python installation"""
|
|
|
| -__version__ = "12.0"
|
| -virtualenv_version = __version__ # legacy
|
| -
|
| -# NB: avoid placing additional imports here, before sys.path is fixed!
|
| -
|
| -import sys
|
| import os
|
| +import sys
|
|
|
| -#
|
| -# RATIONALE:
|
| -# This script is both it's own "host" and "guest". If it's running in "guest
|
| -# mode" (inside the virtualenv interpreter), it's essentially invoked via:
|
| -# /path/to/python /path/to/this/script.py
|
| -#
|
| -# Which, by the nature of Python, will put `/path/to/this` on the system path
|
| -# as the first argument. Now this can cause many subtle bugs, because the
|
| -# rest of the script is now looking to import from the "host" Python version
|
| -# first. This has been especially troublesome when trying to create a Python
|
| -# 3 "guest" env using a Python 2 "host", but even with minor Python
|
| -# differences, there may been some bleeding between environments that doesn't
|
| -# stand out as obviously.
|
| -#
|
| -# This removes the first argument off the system path, to avoid any accidental
|
| -# usage of the "host" library directories.
|
| -#
|
| +# If we are running in a new interpreter to create a virtualenv,
|
| +# we do NOT want paths from our existing location interfering with anything,
|
| +# So we remove this file's directory from sys.path - most likely to be
|
| +# the previous interpreter's site-packages. Solves #705, #763, #779
|
| if os.environ.get('VIRTUALENV_INTERPRETER_RUNNING'):
|
| - del sys.path[0]
|
| + for path in sys.path[:]:
|
| + if os.path.realpath(os.path.dirname(__file__)) == os.path.realpath(path):
|
| + sys.path.remove(path)
|
|
|
| import base64
|
| import codecs
|
| @@ -36,15 +19,25 @@ import optparse
|
| import re
|
| import shutil
|
| import logging
|
| -import tempfile
|
| import zlib
|
| import errno
|
| import glob
|
| import distutils.sysconfig
|
| -from distutils.util import strtobool
|
| import struct
|
| import subprocess
|
| -import tarfile
|
| +import pkgutil
|
| +import tempfile
|
| +import textwrap
|
| +from distutils.util import strtobool
|
| +from os.path import join
|
| +
|
| +try:
|
| + import ConfigParser
|
| +except ImportError:
|
| + import configparser as ConfigParser
|
| +
|
| +__version__ = "15.1.0"
|
| +virtualenv_version = __version__ # legacy
|
|
|
| if sys.version_info < (2, 6):
|
| print('ERROR: %s' % sys.exc_info()[1])
|
| @@ -56,12 +49,6 @@ try:
|
| except NameError:
|
| basestring = str
|
|
|
| -try:
|
| - import ConfigParser
|
| -except ImportError:
|
| - import configparser as ConfigParser
|
| -
|
| -join = os.path.join
|
| py_version = 'python%s.%s' % (sys.version_info[0], sys.version_info[1])
|
|
|
| is_jython = sys.platform.startswith('java')
|
| @@ -99,7 +86,7 @@ else:
|
| def get_installed_pythons():
|
| try:
|
| python_core = winreg.CreateKey(winreg.HKEY_LOCAL_MACHINE,
|
| - "Software\\Python\\PythonCore")
|
| + "Software\\Python\\PythonCore")
|
| except WindowsError:
|
| # No registered Python installations
|
| return {}
|
| @@ -146,168 +133,21 @@ if majver == 2:
|
| elif majver == 3:
|
| # Some extra modules are needed for Python 3, but different ones
|
| # for different versions.
|
| - REQUIRED_MODULES.extend(['_abcoll', 'warnings', 'linecache', 'abc', 'io',
|
| - '_weakrefset', 'copyreg', 'tempfile', 'random',
|
| - '__future__', 'collections', 'keyword', 'tarfile',
|
| - 'shutil', 'struct', 'copy', 'tokenize', 'token',
|
| - 'functools', 'heapq', 'bisect', 'weakref',
|
| - 'reprlib'])
|
| + REQUIRED_MODULES.extend([
|
| + '_abcoll', 'warnings', 'linecache', 'abc', 'io', '_weakrefset',
|
| + 'copyreg', 'tempfile', 'random', '__future__', 'collections',
|
| + 'keyword', 'tarfile', 'shutil', 'struct', 'copy', 'tokenize',
|
| + 'token', 'functools', 'heapq', 'bisect', 'weakref', 'reprlib'
|
| + ])
|
| if minver >= 2:
|
| REQUIRED_FILES[-1] = 'config-%s' % majver
|
| if minver >= 3:
|
| import sysconfig
|
| platdir = sysconfig.get_config_var('PLATDIR')
|
| REQUIRED_FILES.append(platdir)
|
| - # The whole list of 3.3 modules is reproduced below - the current
|
| - # uncommented ones are required for 3.3 as of now, but more may be
|
| - # added as 3.3 development continues.
|
| REQUIRED_MODULES.extend([
|
| - #"aifc",
|
| - #"antigravity",
|
| - #"argparse",
|
| - #"ast",
|
| - #"asynchat",
|
| - #"asyncore",
|
| - "base64",
|
| - #"bdb",
|
| - #"binhex",
|
| - #"bisect",
|
| - #"calendar",
|
| - #"cgi",
|
| - #"cgitb",
|
| - #"chunk",
|
| - #"cmd",
|
| - #"codeop",
|
| - #"code",
|
| - #"colorsys",
|
| - #"_compat_pickle",
|
| - #"compileall",
|
| - #"concurrent",
|
| - #"configparser",
|
| - #"contextlib",
|
| - #"cProfile",
|
| - #"crypt",
|
| - #"csv",
|
| - #"ctypes",
|
| - #"curses",
|
| - #"datetime",
|
| - #"dbm",
|
| - #"decimal",
|
| - #"difflib",
|
| - #"dis",
|
| - #"doctest",
|
| - #"dummy_threading",
|
| - "_dummy_thread",
|
| - #"email",
|
| - #"filecmp",
|
| - #"fileinput",
|
| - #"formatter",
|
| - #"fractions",
|
| - #"ftplib",
|
| - #"functools",
|
| - #"getopt",
|
| - #"getpass",
|
| - #"gettext",
|
| - #"glob",
|
| - #"gzip",
|
| - "hashlib",
|
| - #"heapq",
|
| - "hmac",
|
| - #"html",
|
| - #"http",
|
| - #"idlelib",
|
| - #"imaplib",
|
| - #"imghdr",
|
| - "imp",
|
| - "importlib",
|
| - #"inspect",
|
| - #"json",
|
| - #"lib2to3",
|
| - #"logging",
|
| - #"macpath",
|
| - #"macurl2path",
|
| - #"mailbox",
|
| - #"mailcap",
|
| - #"_markupbase",
|
| - #"mimetypes",
|
| - #"modulefinder",
|
| - #"multiprocessing",
|
| - #"netrc",
|
| - #"nntplib",
|
| - #"nturl2path",
|
| - #"numbers",
|
| - #"opcode",
|
| - #"optparse",
|
| - #"os2emxpath",
|
| - #"pdb",
|
| - #"pickle",
|
| - #"pickletools",
|
| - #"pipes",
|
| - #"pkgutil",
|
| - #"platform",
|
| - #"plat-linux2",
|
| - #"plistlib",
|
| - #"poplib",
|
| - #"pprint",
|
| - #"profile",
|
| - #"pstats",
|
| - #"pty",
|
| - #"pyclbr",
|
| - #"py_compile",
|
| - #"pydoc_data",
|
| - #"pydoc",
|
| - #"_pyio",
|
| - #"queue",
|
| - #"quopri",
|
| - #"reprlib",
|
| - "rlcompleter",
|
| - #"runpy",
|
| - #"sched",
|
| - #"shelve",
|
| - #"shlex",
|
| - #"smtpd",
|
| - #"smtplib",
|
| - #"sndhdr",
|
| - #"socket",
|
| - #"socketserver",
|
| - #"sqlite3",
|
| - #"ssl",
|
| - #"stringprep",
|
| - #"string",
|
| - #"_strptime",
|
| - #"subprocess",
|
| - #"sunau",
|
| - #"symbol",
|
| - #"symtable",
|
| - #"sysconfig",
|
| - #"tabnanny",
|
| - #"telnetlib",
|
| - #"test",
|
| - #"textwrap",
|
| - #"this",
|
| - #"_threading_local",
|
| - #"threading",
|
| - #"timeit",
|
| - #"tkinter",
|
| - #"tokenize",
|
| - #"token",
|
| - #"traceback",
|
| - #"trace",
|
| - #"tty",
|
| - #"turtledemo",
|
| - #"turtle",
|
| - #"unittest",
|
| - #"urllib",
|
| - #"uuid",
|
| - #"uu",
|
| - #"wave",
|
| - #"weakref",
|
| - #"webbrowser",
|
| - #"wsgiref",
|
| - #"xdrlib",
|
| - #"xml",
|
| - #"xmlrpc",
|
| - #"zipfile",
|
| + 'base64', '_dummy_thread', 'hashlib', 'hmac',
|
| + 'imp', 'importlib', 'rlcompleter'
|
| ])
|
| if minver >= 4:
|
| REQUIRED_MODULES.extend([
|
| @@ -315,12 +155,20 @@ elif majver == 3:
|
| '_collections_abc',
|
| '_bootlocale',
|
| ])
|
| + if minver >= 6:
|
| + REQUIRED_MODULES.extend(['enum'])
|
|
|
| if is_pypy:
|
| # these are needed to correctly display the exceptions that may happen
|
| # during the bootstrap
|
| REQUIRED_MODULES.extend(['traceback', 'linecache'])
|
|
|
| + if majver == 3:
|
| + # _functools is needed to import locale during stdio initialization and
|
| + # needs to be copied on PyPy because it's not built in
|
| + REQUIRED_MODULES.append('_functools')
|
| +
|
| +
|
| class Logger(object):
|
|
|
| """
|
| @@ -345,16 +193,22 @@ class Logger(object):
|
|
|
| def debug(self, msg, *args, **kw):
|
| self.log(self.DEBUG, msg, *args, **kw)
|
| +
|
| def info(self, msg, *args, **kw):
|
| self.log(self.INFO, msg, *args, **kw)
|
| +
|
| def notify(self, msg, *args, **kw):
|
| self.log(self.NOTIFY, msg, *args, **kw)
|
| +
|
| def warn(self, msg, *args, **kw):
|
| self.log(self.WARN, msg, *args, **kw)
|
| +
|
| def error(self, msg, *args, **kw):
|
| self.log(self.ERROR, msg, *args, **kw)
|
| +
|
| def fatal(self, msg, *args, **kw):
|
| self.log(self.FATAL, msg, *args, **kw)
|
| +
|
| def log(self, level, msg, *args, **kw):
|
| if args:
|
| if kw:
|
| @@ -450,7 +304,7 @@ class Logger(object):
|
| else:
|
| return level >= consumer_level
|
|
|
| - #@classmethod
|
| + @classmethod
|
| def level_for_integer(cls, level):
|
| levels = cls.LEVELS
|
| if level < 0:
|
| @@ -459,8 +313,6 @@ class Logger(object):
|
| return levels[-1]
|
| return levels[level]
|
|
|
| - level_for_integer = classmethod(level_for_integer)
|
| -
|
| # create a silent logger just to prevent this from being undefined
|
| # will be overridden with requested verbosity main() is called.
|
| logger = Logger([(Logger.LEVELS[-1], sys.stdout)])
|
| @@ -507,22 +359,19 @@ def copyfile(src, dest, symlink=True):
|
| def writefile(dest, content, overwrite=True):
|
| if not os.path.exists(dest):
|
| logger.info('Writing %s', dest)
|
| - f = open(dest, 'wb')
|
| - f.write(content.encode('utf-8'))
|
| - f.close()
|
| + with open(dest, 'wb') as f:
|
| + f.write(content.encode('utf-8'))
|
| return
|
| else:
|
| - f = open(dest, 'rb')
|
| - c = f.read()
|
| - f.close()
|
| + with open(dest, 'rb') as f:
|
| + c = f.read()
|
| if c != content.encode("utf-8"):
|
| if not overwrite:
|
| logger.notify('File %s exists with different content; not overwriting', dest)
|
| return
|
| logger.notify('Overwriting %s with new content', dest)
|
| - f = open(dest, 'wb')
|
| - f.write(content.encode('utf-8'))
|
| - f.close()
|
| + with open(dest, 'wb') as f:
|
| + f.write(content.encode('utf-8'))
|
| else:
|
| logger.info('Content %s already in place', dest)
|
|
|
| @@ -549,8 +398,7 @@ def _find_file(filename, dirs):
|
|
|
| def file_search_dirs():
|
| here = os.path.dirname(os.path.abspath(__file__))
|
| - dirs = ['.', here,
|
| - join(here, 'virtualenv_support')]
|
| + dirs = [here, join(here, 'virtualenv_support')]
|
| if os.path.splitext(os.path.dirname(__file__))[0] != 'virtualenv':
|
| # Probably some boot script; just in case virtualenv is installed...
|
| try:
|
| @@ -558,7 +406,8 @@ def file_search_dirs():
|
| except ImportError:
|
| pass
|
| else:
|
| - dirs.append(os.path.join(os.path.dirname(virtualenv.__file__), 'virtualenv_support'))
|
| + dirs.append(os.path.join(
|
| + os.path.dirname(virtualenv.__file__), 'virtualenv_support'))
|
| return [d for d in dirs if os.path.isdir(d)]
|
|
|
|
|
| @@ -737,7 +586,7 @@ def main():
|
| '--no-setuptools',
|
| dest='no_setuptools',
|
| action='store_true',
|
| - help='Do not install setuptools (or pip) in the new virtualenv.')
|
| + help='Do not install setuptools in the new virtualenv.')
|
|
|
| parser.add_option(
|
| '--no-pip',
|
| @@ -745,6 +594,12 @@ def main():
|
| action='store_true',
|
| help='Do not install pip in the new virtualenv.')
|
|
|
| + parser.add_option(
|
| + '--no-wheel',
|
| + dest='no_wheel',
|
| + action='store_true',
|
| + help='Do not install wheel in the new virtualenv.')
|
| +
|
| default_search_dirs = file_search_dirs()
|
| parser.add_option(
|
| '--extra-search-dir',
|
| @@ -756,12 +611,20 @@ def main():
|
| "This option can be used multiple times.")
|
|
|
| parser.add_option(
|
| - '--never-download',
|
| - dest="never_download",
|
| - action="store_true",
|
| + "--download",
|
| + dest="download",
|
| default=True,
|
| - help="DEPRECATED. Retained only for backward compatibility. This option has no effect. "
|
| - "Virtualenv never downloads pip or setuptools.")
|
| + action="store_true",
|
| + help="Download preinstalled packages from PyPI.",
|
| + )
|
| +
|
| + parser.add_option(
|
| + "--no-download",
|
| + '--never-download',
|
| + dest="download",
|
| + action="store_false",
|
| + help="Do not download preinstalled packages from PyPI.",
|
| + )
|
|
|
| parser.add_option(
|
| '--prompt',
|
| @@ -819,6 +682,11 @@ def main():
|
|
|
| home_dir = args[0]
|
|
|
| + if os.path.exists(home_dir) and os.path.isfile(home_dir):
|
| + logger.fatal('ERROR: File already exists and is not a directory.')
|
| + logger.fatal('Please provide a different path or delete the file.')
|
| + sys.exit(3)
|
| +
|
| if os.environ.get('WORKING_ENV'):
|
| logger.fatal('ERROR: you cannot run virtualenv while in a workingenv')
|
| logger.fatal('Please deactivate your workingenv, then re-run this script')
|
| @@ -832,19 +700,16 @@ def main():
|
| make_environment_relocatable(home_dir)
|
| return
|
|
|
| - if not options.never_download:
|
| - logger.warn('The --never-download option is for backward compatibility only.')
|
| - logger.warn('Setting it to false is no longer supported, and will be ignored.')
|
| -
|
| create_environment(home_dir,
|
| site_packages=options.system_site_packages,
|
| clear=options.clear,
|
| unzip_setuptools=options.unzip_setuptools,
|
| prompt=options.prompt,
|
| search_dirs=options.search_dirs,
|
| - never_download=True,
|
| + download=options.download,
|
| no_setuptools=options.no_setuptools,
|
| no_pip=options.no_pip,
|
| + no_wheel=options.no_wheel,
|
| symlink=options.symlink)
|
| if 'after_install' in globals():
|
| after_install(options, home_dir)
|
| @@ -852,7 +717,7 @@ def main():
|
| def call_subprocess(cmd, show_stdout=True,
|
| filter_stdout=None, cwd=None,
|
| raise_on_returncode=True, extra_env=None,
|
| - remove_from_env=None):
|
| + remove_from_env=None, stdin=None):
|
| cmd_parts = []
|
| for part in cmd:
|
| if len(part) > 45:
|
| @@ -882,7 +747,9 @@ def call_subprocess(cmd, show_stdout=True,
|
| env = None
|
| try:
|
| proc = subprocess.Popen(
|
| - cmd, stderr=subprocess.STDOUT, stdin=None, stdout=stdout,
|
| + cmd, stderr=subprocess.STDOUT,
|
| + stdin=None if stdin is None else subprocess.PIPE,
|
| + stdout=stdout,
|
| cwd=cwd, env=env)
|
| except Exception:
|
| e = sys.exc_info()[1]
|
| @@ -891,6 +758,10 @@ def call_subprocess(cmd, show_stdout=True,
|
| raise
|
| all_output = []
|
| if stdout is not None:
|
| + if stdin is not None:
|
| + proc.stdin.write(stdin)
|
| + proc.stdin.close()
|
| +
|
| stdout = proc.stdout
|
| encoding = sys.getdefaultencoding()
|
| fs_encoding = sys.getfilesystemencoding()
|
| @@ -914,7 +785,7 @@ def call_subprocess(cmd, show_stdout=True,
|
| else:
|
| logger.info(line)
|
| else:
|
| - proc.communicate()
|
| + proc.communicate(stdin)
|
| proc.wait()
|
| if proc.returncode:
|
| if raise_on_returncode:
|
| @@ -960,38 +831,84 @@ def find_wheels(projects, search_dirs):
|
|
|
| return wheels
|
|
|
| -def install_wheel(project_names, py_executable, search_dirs=None):
|
| +def install_wheel(project_names, py_executable, search_dirs=None,
|
| + download=False):
|
| if search_dirs is None:
|
| search_dirs = file_search_dirs()
|
|
|
| wheels = find_wheels(['setuptools', 'pip'], search_dirs)
|
| pythonpath = os.pathsep.join(wheels)
|
| - findlinks = ' '.join(search_dirs)
|
|
|
| - cmd = [
|
| - py_executable, '-c',
|
| - 'import sys, pip; sys.exit(pip.main(["install", "--ignore-installed"] + sys.argv[1:]))',
|
| - ] + project_names
|
| + # PIP_FIND_LINKS uses space as the path separator and thus cannot have paths
|
| + # with spaces in them. Convert any of those to local file:// URL form.
|
| + try:
|
| + from urlparse import urljoin
|
| + from urllib import pathname2url
|
| + except ImportError:
|
| + from urllib.parse import urljoin
|
| + from urllib.request import pathname2url
|
| + def space_path2url(p):
|
| + if ' ' not in p:
|
| + return p
|
| + return urljoin('file:', pathname2url(os.path.abspath(p)))
|
| + findlinks = ' '.join(space_path2url(d) for d in search_dirs)
|
| +
|
| + SCRIPT = textwrap.dedent("""
|
| + import sys
|
| + import pkgutil
|
| + import tempfile
|
| + import os
|
| +
|
| + import pip
|
| +
|
| + cert_data = pkgutil.get_data("pip._vendor.requests", "cacert.pem")
|
| + if cert_data is not None:
|
| + cert_file = tempfile.NamedTemporaryFile(delete=False)
|
| + cert_file.write(cert_data)
|
| + cert_file.close()
|
| + else:
|
| + cert_file = None
|
| +
|
| + try:
|
| + args = ["install", "--ignore-installed"]
|
| + if cert_file is not None:
|
| + args += ["--cert", cert_file.name]
|
| + args += sys.argv[1:]
|
| +
|
| + sys.exit(pip.main(args))
|
| + finally:
|
| + if cert_file is not None:
|
| + os.remove(cert_file.name)
|
| + """).encode("utf8")
|
| +
|
| + cmd = [py_executable, '-'] + project_names
|
| logger.start_progress('Installing %s...' % (', '.join(project_names)))
|
| logger.indent += 2
|
| +
|
| + env = {
|
| + "PYTHONPATH": pythonpath,
|
| + "JYTHONPATH": pythonpath, # for Jython < 3.x
|
| + "PIP_FIND_LINKS": findlinks,
|
| + "PIP_USE_WHEEL": "1",
|
| + "PIP_ONLY_BINARY": ":all:",
|
| + "PIP_USER": "0",
|
| + }
|
| +
|
| + if not download:
|
| + env["PIP_NO_INDEX"] = "1"
|
| +
|
| try:
|
| - call_subprocess(cmd, show_stdout=False,
|
| - extra_env = {
|
| - 'PYTHONPATH': pythonpath,
|
| - 'PIP_FIND_LINKS': findlinks,
|
| - 'PIP_USE_WHEEL': '1',
|
| - 'PIP_PRE': '1',
|
| - 'PIP_NO_INDEX': '1'
|
| - }
|
| - )
|
| + call_subprocess(cmd, show_stdout=False, extra_env=env, stdin=SCRIPT)
|
| finally:
|
| logger.indent -= 2
|
| logger.end_progress()
|
|
|
| +
|
| def create_environment(home_dir, site_packages=False, clear=False,
|
| unzip_setuptools=False,
|
| - prompt=None, search_dirs=None, never_download=False,
|
| - no_setuptools=False, no_pip=False, symlink=True):
|
| + prompt=None, search_dirs=None, download=False,
|
| + no_setuptools=False, no_pip=False, no_wheel=False,
|
| + symlink=True):
|
| """
|
| Creates a new environment in ``home_dir``.
|
|
|
| @@ -1009,20 +926,36 @@ def create_environment(home_dir, site_packages=False, clear=False,
|
|
|
| install_distutils(home_dir)
|
|
|
| + to_install = []
|
| +
|
| if not no_setuptools:
|
| - to_install = ['setuptools']
|
| - if not no_pip:
|
| - to_install.append('pip')
|
| - install_wheel(to_install, py_executable, search_dirs)
|
| + to_install.append('setuptools')
|
| +
|
| + if not no_pip:
|
| + to_install.append('pip')
|
| +
|
| + if not no_wheel:
|
| + to_install.append('wheel')
|
| +
|
| + if to_install:
|
| + install_wheel(
|
| + to_install,
|
| + py_executable,
|
| + search_dirs,
|
| + download=download,
|
| + )
|
|
|
| install_activate(home_dir, bin_dir, prompt)
|
|
|
| + install_python_config(home_dir, bin_dir, prompt)
|
| +
|
| def is_executable_file(fpath):
|
| return os.path.isfile(fpath) and os.access(fpath, os.X_OK)
|
|
|
| def path_locations(home_dir):
|
| """Return the path locations for the environment (where libraries are,
|
| where scripts go, etc)"""
|
| + home_dir = os.path.abspath(home_dir)
|
| # XXX: We'd use distutils.sysconfig.get_python_inc/lib but its
|
| # prefix arg is broken: http://bugs.python.org/issue3386
|
| if is_win:
|
| @@ -1059,17 +992,7 @@ def path_locations(home_dir):
|
| bin_dir = join(home_dir, 'bin')
|
| elif not is_win:
|
| lib_dir = join(home_dir, 'lib', py_version)
|
| - multiarch_exec = '/usr/bin/multiarch-platform'
|
| - if is_executable_file(multiarch_exec):
|
| - # In Mageia (2) and Mandriva distros the include dir must be like:
|
| - # virtualenv/include/multiarch-x86_64-linux/python2.7
|
| - # instead of being virtualenv/include/python2.7
|
| - p = subprocess.Popen(multiarch_exec, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
| - stdout, stderr = p.communicate()
|
| - # stdout.strip is needed to remove newline character
|
| - inc_dir = join(home_dir, 'include', stdout.strip(), py_version + abiflags)
|
| - else:
|
| - inc_dir = join(home_dir, 'include', py_version + abiflags)
|
| + inc_dir = join(home_dir, 'include', py_version + abiflags)
|
| bin_dir = join(home_dir, 'bin')
|
| return home_dir, lib_dir, inc_dir, bin_dir
|
|
|
| @@ -1096,6 +1019,12 @@ def change_prefix(filename, dst_prefix):
|
| # Check longer prefixes first so we don't split in the middle of a filename
|
| prefixes = sorted(prefixes, key=len, reverse=True)
|
| filename = os.path.abspath(filename)
|
| + # On Windows, make sure drive letter is uppercase
|
| + if is_win and filename[0] in 'abcdefghijklmnopqrstuvwxyz':
|
| + filename = filename[0].upper() + filename[1:]
|
| + for i, prefix in enumerate(prefixes):
|
| + if is_win and prefix[0] in 'abcdefghijklmnopqrstuvwxyz':
|
| + prefixes[i] = prefix[0].upper() + prefix[1:]
|
| for src_prefix in prefixes:
|
| if filename.startswith(src_prefix):
|
| _, relpath = filename.split(src_prefix, 1)
|
| @@ -1108,6 +1037,7 @@ def change_prefix(filename, dst_prefix):
|
|
|
| def copy_required_modules(dst_prefix, symlink):
|
| import imp
|
| +
|
| for modname in REQUIRED_MODULES:
|
| if modname in sys.builtin_module_names:
|
| logger.info("Ignoring built-in bootstrap module: %s" % modname)
|
| @@ -1136,6 +1066,16 @@ def copy_required_modules(dst_prefix, symlink):
|
| if os.path.exists(pyfile):
|
| copyfile(pyfile, dst_filename[:-1], symlink)
|
|
|
| +def copy_tcltk(src, dest, symlink):
|
| + """ copy tcl/tk libraries on Windows (issue #93) """
|
| + for libversion in '8.5', '8.6':
|
| + for libname in 'tcl', 'tk':
|
| + srcdir = join(src, 'tcl', libname + libversion)
|
| + destdir = join(dest, 'tcl', libname + libversion)
|
| + # Only copy the dirs from the above combinations that exist
|
| + if os.path.exists(srcdir) and not os.path.exists(destdir):
|
| + copyfileordir(srcdir, destdir, symlink)
|
| +
|
|
|
| def subst_path(prefix_path, prefix, home_dir):
|
| prefix_path = os.path.normpath(prefix_path)
|
| @@ -1192,10 +1132,13 @@ def install_python(home_dir, lib_dir, inc_dir, bin_dir, site_packages, clear, sy
|
| copy_required_modules(home_dir, symlink)
|
| finally:
|
| logger.indent -= 2
|
| + # ...copy tcl/tk
|
| + if is_win:
|
| + copy_tcltk(prefix, home_dir, symlink)
|
| mkdir(join(lib_dir, 'site-packages'))
|
| import site
|
| site_filename = site.__file__
|
| - if site_filename.endswith('.pyc'):
|
| + if site_filename.endswith('.pyc') or site_filename.endswith('.pyo'):
|
| site_filename = site_filename[:-1]
|
| elif site_filename.endswith('$py.class'):
|
| site_filename = site_filename.replace('$py.class', '.py')
|
| @@ -1428,12 +1371,6 @@ def install_python(home_dir, lib_dir, inc_dir, bin_dir, site_packages, clear, sy
|
| else:
|
| copyfile(py_executable, full_pth, symlink)
|
|
|
| - if is_win and ' ' in py_executable:
|
| - # There's a bug with subprocess on Windows when using a first
|
| - # argument that has a space in it. Instead we have to quote
|
| - # the value:
|
| - py_executable = '"%s"' % py_executable
|
| - # NOTE: keep this check as one line, cmd.exe doesn't cope with line breaks
|
| cmd = [py_executable, '-c', 'import sys;out=sys.stdout;'
|
| 'getattr(out, "buffer", out).write(sys.prefix.encode("utf-8"))']
|
| logger.info('Testing executable with %s %s "%s"' % tuple(cmd))
|
| @@ -1490,7 +1427,6 @@ def install_python(home_dir, lib_dir, inc_dir, bin_dir, site_packages, clear, sy
|
|
|
|
|
| def install_activate(home_dir, bin_dir, prompt=None):
|
| - home_dir = os.path.abspath(home_dir)
|
| if is_win or is_jython and os._name == 'nt':
|
| files = {
|
| 'activate.bat': ACTIVATE_BAT,
|
| @@ -1518,6 +1454,10 @@ def install_activate(home_dir, bin_dir, prompt=None):
|
| files['activate.csh'] = ACTIVATE_CSH
|
|
|
| files['activate_this.py'] = ACTIVATE_THIS
|
| +
|
| + install_files(home_dir, bin_dir, prompt, files)
|
| +
|
| +def install_files(home_dir, bin_dir, prompt, files):
|
| if hasattr(home_dir, 'decode'):
|
| home_dir = home_dir.decode(sys.getfilesystemencoding())
|
| vname = os.path.basename(home_dir)
|
| @@ -1529,6 +1469,15 @@ def install_activate(home_dir, bin_dir, prompt=None):
|
| content = content.replace('__BIN_NAME__', os.path.basename(bin_dir))
|
| writefile(os.path.join(bin_dir, name), content)
|
|
|
| +def install_python_config(home_dir, bin_dir, prompt=None):
|
| + if sys.platform == 'win32' or is_jython and os._name == 'nt':
|
| + files = {}
|
| + else:
|
| + files = {'python-config': PYTHON_CONFIG}
|
| + install_files(home_dir, bin_dir, prompt, files)
|
| + for name, content in files.items():
|
| + make_exe(os.path.join(bin_dir, name))
|
| +
|
| def install_distutils(home_dir):
|
| distutils_path = change_prefix(distutils.__path__[0], home_dir)
|
| mkdir(distutils_path)
|
| @@ -1566,30 +1515,32 @@ def fix_lib64(lib_dir, symlink=True):
|
| instead of lib/pythonX.Y. If this is such a platform we'll just create a
|
| symlink so lib64 points to lib
|
| """
|
| - if [p for p in distutils.sysconfig.get_config_vars().values()
|
| - if isinstance(p, basestring) and 'lib64' in p]:
|
| - # PyPy's library path scheme is not affected by this.
|
| - # Return early or we will die on the following assert.
|
| - if is_pypy:
|
| - logger.debug('PyPy detected, skipping lib64 symlinking')
|
| - return
|
| -
|
| - logger.debug('This system uses lib64; symlinking lib64 to lib')
|
| -
|
| - assert os.path.basename(lib_dir) == 'python%s' % sys.version[:3], (
|
| - "Unexpected python lib dir: %r" % lib_dir)
|
| - lib_parent = os.path.dirname(lib_dir)
|
| - top_level = os.path.dirname(lib_parent)
|
| - lib_dir = os.path.join(top_level, 'lib')
|
| - lib64_link = os.path.join(top_level, 'lib64')
|
| - assert os.path.basename(lib_parent) == 'lib', (
|
| - "Unexpected parent dir: %r" % lib_parent)
|
| - if os.path.lexists(lib64_link):
|
| - return
|
| - if symlink:
|
| - os.symlink('lib', lib64_link)
|
| - else:
|
| - copyfile('lib', lib64_link)
|
| + # PyPy's library path scheme is not affected by this.
|
| + # Return early or we will die on the following assert.
|
| + if is_pypy:
|
| + logger.debug('PyPy detected, skipping lib64 symlinking')
|
| + return
|
| + # Check we have a lib64 library path
|
| + if not [p for p in distutils.sysconfig.get_config_vars().values()
|
| + if isinstance(p, basestring) and 'lib64' in p]:
|
| + return
|
| +
|
| + logger.debug('This system uses lib64; symlinking lib64 to lib')
|
| +
|
| + assert os.path.basename(lib_dir) == 'python%s' % sys.version[:3], (
|
| + "Unexpected python lib dir: %r" % lib_dir)
|
| + lib_parent = os.path.dirname(lib_dir)
|
| + top_level = os.path.dirname(lib_parent)
|
| + lib_dir = os.path.join(top_level, 'lib')
|
| + lib64_link = os.path.join(top_level, 'lib64')
|
| + assert os.path.basename(lib_parent) == 'lib', (
|
| + "Unexpected parent dir: %r" % lib_parent)
|
| + if os.path.lexists(lib64_link):
|
| + return
|
| + if symlink:
|
| + os.symlink('lib', lib64_link)
|
| + else:
|
| + copyfile('lib', lib64_link)
|
|
|
| def resolve_interpreter(exe):
|
| """
|
| @@ -1597,6 +1548,7 @@ def resolve_interpreter(exe):
|
| """
|
| # If the "executable" is a version number, get the installed executable for
|
| # that version
|
| + orig_exe = exe
|
| python_versions = get_installed_pythons()
|
| if exe in python_versions:
|
| exe = python_versions[exe]
|
| @@ -1604,20 +1556,20 @@ def resolve_interpreter(exe):
|
| if os.path.abspath(exe) != exe:
|
| paths = os.environ.get('PATH', '').split(os.pathsep)
|
| for path in paths:
|
| - if os.path.exists(os.path.join(path, exe)):
|
| - exe = os.path.join(path, exe)
|
| + if os.path.exists(join(path, exe)):
|
| + exe = join(path, exe)
|
| break
|
| if not os.path.exists(exe):
|
| - logger.fatal('The executable %s (from --python=%s) does not exist' % (exe, exe))
|
| + logger.fatal('The path %s (from --python=%s) does not exist' % (exe, orig_exe))
|
| raise SystemExit(3)
|
| if not is_executable(exe):
|
| - logger.fatal('The executable %s (from --python=%s) is not executable' % (exe, exe))
|
| + logger.fatal('The path %s (from --python=%s) is not an executable file' % (exe, orig_exe))
|
| raise SystemExit(3)
|
| return exe
|
|
|
| def is_executable(exe):
|
| """Checks a file is executable"""
|
| - return os.access(exe, os.X_OK)
|
| + return os.path.isfile(exe) and os.access(exe, os.X_OK)
|
|
|
| ############################################################
|
| ## Relocating the environment:
|
| @@ -1660,16 +1612,14 @@ def fixup_scripts(home_dir, bin_dir):
|
| if not os.path.isfile(filename):
|
| # ignore subdirs, e.g. .svn ones.
|
| continue
|
| - f = open(filename, 'rb')
|
| - try:
|
| + lines = None
|
| + with open(filename, 'rb') as f:
|
| try:
|
| lines = f.read().decode('utf-8').splitlines()
|
| except UnicodeDecodeError:
|
| # This is probably a binary program instead
|
| # of a script, so just ignore it.
|
| continue
|
| - finally:
|
| - f.close()
|
| if not lines:
|
| logger.warn('Script %s is an empty file' % filename)
|
| continue
|
| @@ -1688,9 +1638,9 @@ def fixup_scripts(home_dir, bin_dir):
|
| continue
|
| logger.notify('Making script %s relative' % filename)
|
| script = relative_script([new_shebang] + lines[1:])
|
| - f = open(filename, 'wb')
|
| - f.write('\n'.join(script).encode('utf-8'))
|
| - f.close()
|
| + with open(filename, 'wb') as f:
|
| + f.write('\n'.join(script).encode('utf-8'))
|
| +
|
|
|
| def relative_script(lines):
|
| "Return a script that'll work in a relocatable environment."
|
| @@ -1737,9 +1687,8 @@ def fixup_pth_and_egg_link(home_dir, sys_path=None):
|
| def fixup_pth_file(filename):
|
| lines = []
|
| prev_lines = []
|
| - f = open(filename)
|
| - prev_lines = f.readlines()
|
| - f.close()
|
| + with open(filename) as f:
|
| + prev_lines = f.readlines()
|
| for line in prev_lines:
|
| line = line.strip()
|
| if (not line or line.startswith('#') or line.startswith('import ')
|
| @@ -1754,22 +1703,19 @@ def fixup_pth_file(filename):
|
| logger.info('No changes to .pth file %s' % filename)
|
| return
|
| logger.notify('Making paths in .pth file %s relative' % filename)
|
| - f = open(filename, 'w')
|
| - f.write('\n'.join(lines) + '\n')
|
| - f.close()
|
| + with open(filename, 'w') as f:
|
| + f.write('\n'.join(lines) + '\n')
|
|
|
| def fixup_egg_link(filename):
|
| - f = open(filename)
|
| - link = f.readline().strip()
|
| - f.close()
|
| + with open(filename) as f:
|
| + link = f.readline().strip()
|
| if os.path.abspath(link) != link:
|
| logger.debug('Link in %s already relative' % filename)
|
| return
|
| new_link = make_relative_path(filename, link)
|
| logger.notify('Rewriting link %s in %s as %s' % (link, filename, new_link))
|
| - f = open(filename, 'w')
|
| - f.write(new_link)
|
| - f.close()
|
| + with open(filename, 'w') as f:
|
| + f.write(new_link)
|
|
|
| def make_relative_path(source, dest, dest_is_directory=True):
|
| """
|
| @@ -1852,9 +1798,8 @@ def create_bootstrap_script(extra_text, python_version=''):
|
| filename = __file__
|
| if filename.endswith('.pyc'):
|
| filename = filename[:-1]
|
| - f = codecs.open(filename, 'r', encoding='utf-8')
|
| - content = f.read()
|
| - f.close()
|
| + with codecs.open(filename, 'r', encoding='utf-8') as f:
|
| + content = f.read()
|
| py_exe = 'python%s' % python_version
|
| content = (('#!/usr/bin/env %s\n' % py_exe)
|
| + '## WARNING: This file is generated\n'
|
| @@ -2014,71 +1959,70 @@ AVijEPwfucjncQ==
|
|
|
| ##file activate.sh
|
| ACTIVATE_SH = convert("""
|
| -eJytVVFvokAQfudXTLEPtTlLeo9tvMSmJpq02hSvl7u2wRUG2QR2DSxSe7n/frOACEVNLlceRHa+
|
| -nfl25pvZDswCnoDPQ4QoTRQsENIEPci4CsBMZBq7CAsuLOYqvmYKTTj3YxnBgiXBudGBjUzBZUJI
|
| -BXEqgCvweIyuCjeG4eF2F5x14bcB9KQiQQWrjSddI1/oQIx6SYYeoFjzWIoIhYI1izlbhJjkKO7D
|
| -M/QEmKfO9O7WeRo/zr4P7pyHwWxkwitcgwpQ5Ej96OX+PmiFwLeVjFUOrNYKaq1Nud3nR2n8nI2m
|
| -k9H0friPTGVsUdptaxGrTEfpNVFEskxpXtUkkCkl1UNF9cgLBkx48J4EXyALuBtAwNYIjF5kcmUU
|
| -abMKmMq1ULoiRbgsDEkTSsKSGFCJ6Z8vY/2xYiSacmtyAfCDdCNTVZoVF8vSTQOoEwSnOrngBkws
|
| -MYGMBMg8/bMBLSYKS7pYEXP0PqT+ZmBT0Xuy+Pplj5yn4aM9nk72JD8/Wi+Gr98sD9eWSMOwkapD
|
| -BbUv91XSvmyVkICt2tmXR4tWmrcUCsjWOpw87YidEC8i0gdTSOFhouJUNxR+4NYBG0MftoCTD9F7
|
| -2rTtxG3oPwY1b2HncYwhrlmj6Wq924xtGDWqfdNxap+OYxplEurnMVo9RWks+rH8qKEtx7kZT5zJ
|
| -4H7oOFclrN6uFe+d+nW2aIUsSgs/42EIPuOhXq+jEo3S6tX6w2ilNkDnIpHCWdEQhFgwj9pkk7FN
|
| -l/y5eQvRSIQ5+TrL05lewxWpt/Lbhes5cJF3mLET1MGhcKCF+40tNWnUulxrpojwDo2sObdje3Bz
|
| -N3QeHqf3D7OjEXMVV8LN3ZlvuzoWHqiUcNKHtwNd0IbvPGKYYM31nPKCgkUILw3KL+Y8l7aO1ArS
|
| -Ad37nIU0fCj5NE5gQCuC5sOSu+UdI2NeXg/lFkQIlFpdWVaWZRfvqGiirC9o6liJ9FXGYrSY9mI1
|
| -D/Ncozgn13vJvsznr7DnkJWXsyMH7e42ljdJ+aqNDF1bFnKWFLdj31xtaJYK6EXFgqmV/ymD/ROG
|
| -+n8O9H8f5vsGOWXsL1+1k3g=
|
| +eJytVd9v2kAMfs9fYQLq2m4MscdNVKMqEkgtVIQxbeuUHolpTgsXdHehpT/+9/mSEBJS2MOaB0ji
|
| +z77P9menDpOAK5jzEGERKw0zhFihD/dcB2CrKJYewoyLFvM0XzGNNpzOZbSAGVPBqVWHdRSDx4SI
|
| +NMhYANfgc4meDteW5ePGC45P4MkCumKhUENzDsu1H3lw1vJx1RJxGMKns6O2lWDqINGgotAHFCsu
|
| +I7FAoWHFJGezEFWGqsEvaD5C42naHb93X+A3+elYCgVaxgh8DmQAys9HL2SS0mIaWBgm7mTN/O3G
|
| +kzu6vHCng/HkW/fSve5O+hTOpnhfQAcoEry5jKVjNypoO0fgwzKSOgHm79KUK06Jfc7/RebHpD8a
|
| +9kdXvT2UcnuFWG6p0stNB0mWUUQ1q3uiGRVEMfXHR03dTuQATPjwqIIPcB9wL4CArRAY/ZHJixYL
|
| +Y9YBtcAoLQtFevOoI9QaHcEdMSAB0d08kuZhyUiSmav6CPCdVBnFOjNrLu6yMCWgKRA0TInBC5i4
|
| +QwX3JG/mm581GKnSsSSxJTFHf9MAKr8w5T/vOv1mUurn5/zlT6fvTntjZzAaNl9rQ5JkU5KIc0GX
|
| +inagwU57T2eddqWlTrvaS6d9sImZeUMkhWysveF0m37NcGub9Dpgi0j4qGiOzATjDr06OBjOYQOo
|
| +7RBoGtNm9Denv1i0LVI7lxJDXLHSSBeWRflsyyqw7diuW3h0XdvK6lBMyaoMG1UyHdTsoYBuue75
|
| +YOgOu1c91/2cwYpznPPeDoQpGL2xSm09NKp7BsvQ2hnT3aMs07lUnskpxewvBk73/LLnXo9HV9eT
|
| +ijB3hWBO2ygoiWg/bKuZxqCCQq0DD3vkWIVvI2KosIw+vqW1gIItEG5KJb+xb09g65ktwYKgTc51
|
| +uGJ/EFQs0ayEWLCQM5V9N4g+1+8UbXOJzF8bqhKtIqIwicWvzNFROZJlpfD8A7Vc044R0FxkcezG
|
| +VzsV75usvTdYef+57v5n1b225qhXfwEmxHEs
|
| """)
|
|
|
| ##file activate.fish
|
| ACTIVATE_FISH = convert("""
|
| -eJydVW2P2jgQ/s6vmAZQoVpA9/WkqqJaTou0u6x2uZVOVWWZZEKsS+yc7UDpr+84bziQbauLxEvs
|
| -eXnsZ56ZIWwTYSAWKUJWGAs7hMJgBEdhEwiMKnSIsBNywUMrDtziPBYmCeBDrFUG7v8HmCTW5n8u
|
| -Fu7NJJim81Bl08EQTqqAkEupLOhCgrAQCY2hTU+DQVxIiqgkRNiEBphFEKy+kd1BaFvwFOUBuIxA
|
| -oy20BKtAKp3xFMo0QNtCK5mhtMEA6BmSpUELKo38TThwLfguRVNaiRgs0llnEoIR29zfstf18/bv
|
| -5T17Wm7vAiiN3ONCzfbfwC3DtWXXDqHfAGX0q6z/bO82j3ebh1VwnbrduwTQbvwcRtesAfMGor/W
|
| -L3fs6Xnz8LRlm9fV8/P61sM0LDNwCZjl9gSpCokJRzpryGQ5t8kNGFUt51QjOZGu0Mj35FlYlXEr
|
| -yC09EVOp4lEXfF84Lz1qbhBsgl59vDedXI3rTV03xipduSgt9kLytI3XmBp3aV6MPoMQGNUU62T6
|
| -uQdeefTy1Hfj10zVHg2pq8fXDoHBiOv94csfXwN49xECqWREy7pwukKfvxdMY2j23vXDPuuxxeE+
|
| -JOdCOhxCE3N44B1ZeSLuZh8Mmkr2wEPAmPfKWHA2uxIRjEopdbQYjDz3BWOf14/scfmwoki1eQvX
|
| -ExBdF60Mqh+Y/QcX4uiH4Amwzx79KOVFtbL63sXJbtcvy8/3q5rupmO5CnE91wBviQAhjUUegYpL
|
| -vVEbpLt2/W+PklRgq5Ku6mp+rpMhhCo/lXthQTxJ2ysO4Ka0ad97S7VT/n6YXus6fzk3fLnBZW5C
|
| -KDC6gSO62QDqgFqLCCtPmjegjnLeAdArtSE8VYGbAJ/aLb+vnQutFhk768E9uRbSxhCMzdgEveYw
|
| -IZ5ZqFKl6+kz7UR4U+buqQZXu9SIujrAfD7f0FXpozB4Q0gwp31H9mVTZGGC4b871/wm7lvyDLu1
|
| -FUyvTj/yvD66k3UPTs08x1AQQaGziOl0S1qRkPG9COtBTSTWM9NzQ4R64B+Px/l3tDzCgxv5C6Ni
|
| -e+QaF9xFWrxx0V/G5uvYQOdiZzvYpQUVQSIsTr1TTghI33GnPbTA7/GCqcE3oE3GZurq4HeQXQD6
|
| -32XS1ITj/qLjN72ob0hc5C9bzw8MhfmL
|
| +eJyFVVFv2zYQftevuMoOnBS1gr0WGIZ08RADSRw4boBhGGhGOsUcKFIjKbUu9uN7lC2JsrXWDzZM
|
| +fnf38e6+uwlsdsJCLiRCUVkHrwiVxYy+hHqDbQKvQl3z1ImaO0xyYXdbeP9FuJ1QwMFUSnmcP4dL
|
| +2DlXfry+9v/sDqVMUl3AFVi0Vmj1PokmcKtBaecNQTjIhMHUyX0SRXmlKIpWkGEbDuYZzBZfCVcL
|
| +4youUdVQ6AyBqwwMusoocBrcDsmpKbgEQgijVYHKJbMI6DMhoEUHWmbhLdTcCP4q0TYokYNDev5c
|
| +QTxlq/tb9rJcbz7f3LOnm81d3GD8x3uav30FfwrnwCEOYRyAKot+FvXPzd3q8W71sBiJ3d2dMugu
|
| +fsxjCPsBmz+Wz3fsab16eNqw1ctivV7eBnwm8EzeuQIsSrcHqVMqwHbqq8/aarKSO+oYKhKXUn9p
|
| +SmWw0DVBdQ7bBlwaTR62bc+1tpaYb5PhUyScu48CRgvDLQbtMrMnMQ6dY5022JDRRrwJxWUfJwwP
|
| +ge0YIAVGfcUC1M8s8MxitFZjmR9W64hui7p4fBlWMZ5y81b/9cvfMbz7FWZKq4yOTeW1hbNBEWU+
|
| +b+/ejXMu95lOx696uXb8Go4T+Kw8R2EMSqx5KLkkCkQ+ZBZFbZsHL4OYseAvY3EPO5MYTBuhDZQa
|
| +TwPza8Y+LR/Z483Dgjwd4R3f7bTXx9Znkw6T6PAL83/hRD3jNAKFjuEx9NJkq5t+fabLvdvRwbw4
|
| +nEFTzwO6U+q34cvY7fL55tP94tg58XEA/q7LfdPsaUXFoEIMJdHF5iSW0+48CnDQ82G7n3XzAD6q
|
| +Bmo5XuOA0NQ67ir7AXJtQhtLKO7XhC0l39PGOBsHPvzBuHUSjoOnA0ldozGC9gZ5rek3+y3ALHO/
|
| +kT7AP379lQZLSnFDLtwWihfYxw4nZd+ZR7myfkI2ZTRCuRxmF/bCzkbhcElvYamW9PbDGrvqPKC0
|
| ++D/uLi/sFcxGjOHylYagZzzsjjhw206RQwrWIwOxS2dnk+40xOjX8bTPegz/gdWVSXuaowNuOLda
|
| +wYyNuRPSTcd/B48Ppeg=
|
| """)
|
|
|
| ##file activate.csh
|
| ACTIVATE_CSH = convert("""
|
| -eJx9VG1P2zAQ/u5fcYQKNgTNPtN1WxlIQ4KCUEGaxuQ6yYVYSuzKdhqVX7+zk3bpy5YPUXL3PPfc
|
| -ne98DLNCWshliVDV1kGCUFvMoJGugMjq2qQIiVSxSJ1cCofD1BYRnOVGV0CfZ0N2DD91DalQSjsw
|
| -tQLpIJMGU1euvPe7QeJlkKzgWixlhnAt4aoUVsLnLBiy5NtbJWQ5THX1ZciYKKWwkOFaE04dUm6D
|
| -r/zh7pq/3D7Nnid3/HEy+wFHY/gEJydg0aFaQrBFgz1c5DG1IhTs+UZgsBC2GMFBlaeH+8dZXwcW
|
| -VPvCjXdlAvCfQsE7al0+07XjZvrSCUevR5dnkVeKlFYZmUztG4BdzL2u9KyLVabTU0bdfg7a0hgs
|
| -cSmUg6UwUiQl2iHrcbcVGNvPCiLOe7+cRwG13z9qRGgx2z6DHjfm/Op2yqeT+xvOLzs0PTKHDz2V
|
| -tkckFHoQfQRXoGJAj9el0FyJCmEMhzgMS4sB7KPOE2ExoLcSieYwDvR+cP8cg11gKkVJc2wRcm1g
|
| -QhYFlXiTaTfO2ki0fQoiFM4tLuO4aZrhOzqR4dIPcWx17hphMBY+Srwh7RTyN83XOWkcSPh1Pg/k
|
| -TXX/jbJTbMtUmcxZ+/bbqOsy82suFQg/BhdSOTRhMNBHlUarCpU7JzBhmkKmRejKOQzayQe6MWoa
|
| -n1wqWmuh6LZAaHxcdeqIlVLhIBJdO9/kbl0It2oEXQj+eGjJOuvOIR/YGRqvFhttUB2XTvLXYN2H
|
| -37CBdbW2W7j2r2+VsCn0doVWcFG1/4y1VwBjfwAyoZhD
|
| +eJx1U2FP2zAQ/e5f8TAV3Soo+0zXbYUiDQkKQgVp2ibjJNfFUuIg22nVf885SVFLO3+I7Lt3fr6X
|
| +d8eY58ZjYQpCWfuAhFB7yrAyIYf0Ve1SQmLsuU6DWepAw9TnEoOFq0rwdjAUx/hV1Ui1tVWAqy1M
|
| +QGYcpaFYx+yVI67LkKwx1UuTEaYGl4X2Bl+zJpAlP/6V2hTDtCq/DYXQhdEeGW040Q/Eb+t9V/e3
|
| +U/V88zh/mtyqh8n8J47G+IKTE3gKZJdoYrK3h5MRU1tGYS83gqNc+3yEgyyP93cP820evHLvr2H8
|
| +kaYB/peoyY7aVHzpJnE9e+6I5Z+ji4GMTNJWNuOQq6MA1N25p8pW9HWdVWlfsNpPDbdxjgpaahuw
|
| +1M7opCA/FFu1uwxC7L8KUqmto1KyQe3rx0I0Eovdf7BVe67U5c1MzSZ310pddGheZoFPWyytRkzU
|
| +aCA/I+RkBXhFXr5aWV0SxjhUI6jwdAj8kmhPzX7nTfJFkM3MImp2VdVFFq1vLHSU5szYQK4Ri+Jd
|
| +xlW2JBtOGcyYVW7SnB3v6RS91g3gKapZ0oWxbHVteYIIq3iv7QeuSrUj6KSqQ+yqsxDj1ivNQxKF
|
| +YON10Q+NH/ARS95i5Tuqq2Vxfvc23f/FO6zrtXXmJr+ZtMY9/A15ZXFWtmch2rEQ4g1ryVHH
|
| """)
|
|
|
| ##file activate.bat
|
| ACTIVATE_BAT = convert("""
|
| -eJx9UdEKgjAUfW6wfxjiIH+hEDKUFHSKLCMI7kNOEkIf9P9pTJ3OLJ/03HPPPed4Es9XS9qqwqgT
|
| -PbGKKOdXL4aAFS7A4gvAwgijuiKlqOpGlATS2NeMLE+TjJM9RkQ+SmqAXLrBo1LLIeLdiWlD6jZt
|
| -r7VNubWkndkXaxg5GO3UaOOKS6drO3luDDiO5my3iA0YAKGzPRV1ack8cOdhysI0CYzIPzjSiH5X
|
| -0QcvC8Lfaj0emsVKYF2rhL5L3fCkVjV76kShi59NHwDniAHzkgDgqBcwOgTMx+gDQQqXCw==
|
| +eJx9Ul9LhEAQfxf8DoOclI/dYyFkaCmcq4gZQTBUrincuZFbff12T133TM+nnd35/Zvxlr7XDFhV
|
| +mUZHOVhFlOWP3g4DUriIWoVomYZpNBWUtGpaWgImO191pFkSpzlcmgaI70jVX7n2Qp8tuByg+46O
|
| +CMHbMq64T+nmlJt082D1T44muCDk2prgEHF4mdI9RaS/QwSt3zSyIAaftRccvqVTBziD1x/WlPD5
|
| +xd729NDBb8Nr4DU9QNMKsJeH9pkhPedhQsIkDuCDCa6A+NF9IevVFAohkqizdHetg/tkWvPoftWJ
|
| +MCqnOxv7/x7Np6yv9P2Ker5dmX8yNyCkkWnbZy3N5LarczlqL8htx2EM9rQ/2H5BvIsIEi8OEG8U
|
| ++g8CsNTr
|
| """)
|
|
|
| ##file deactivate.bat
|
| DEACTIVATE_BAT = convert("""
|
| -eJxzSE3OyFfIT0vj4ipOLVEI8wwKCXX0iXf1C7Pl4spMU0hJTcvMS01RiPf3cYmHyQYE+fsGhCho
|
| -cCkAAUibEkTEVhWLMlUlLk6QGixStlyaeCyJDPHw9/Pw93VFsQguim4ZXAJoIUw5DhX47XUM8UCx
|
| -EchHtwsohN1bILUgw61c/Vy4AJYPYm4=
|
| +eJyFkN0KgkAUhO8F32EQpHqFQEjQUPAPMaErqVxzId3IrV6/XST/UDx3c86c4WMO5FYysKJQFVVp
|
| +CEfqxsnJ9DI7SA25i20fFqs3HO+GYLsDZ7h8GM3xfLHrg1QNvpSX4CWpQGvokZk4uqrQAjXjyElB
|
| +a5IjCz0r+2dHcehHCe5MZNmB5R7TdqMqECMptHZh6DN/utb7Zs6Cej8OXYE5J04YOKFvD4GkHuJ0
|
| +pilSd1jG6n87tDZ+BUwUOepI6CGSkFMYWf0ihvT33Qj1A+tCkSI=
|
| """)
|
|
|
| ##file activate.ps1
|
| @@ -2220,6 +2164,25 @@ m8eg6WYWqR6SL5OjKMGfSrYt/6kxxQtOpeAgj1LXBNmpE2ElmCSIy5H0zFd8gJ924HWijWhb2hRC
|
| VF5PnJ+ts3a9/Mz38RpG/AUSzYUW
|
| """)
|
|
|
| +##file python-config
|
| +PYTHON_CONFIG = convert("""
|
| +eJyNVV1P2zAUfc+v8ODBiSABxlulTipbO6p1LWqBgVhlhcZpPYUkctzSivHfd6+dpGloGH2Ja/ue
|
| +e+65Hz78xNhtf3x90xmw7vCWsRPGLvpDNuz87MKfdKMWSWxZ4ilNpCLZJiuWc66SVFUOZkkcirll
|
| +rfxIBAzOMtImDzSVPBRrekwoX/OZu/0r4lm0DHiG60g86u8sjPw5rCyy86NRkB8QuuBRSqfAKESn
|
| +3orLTCQxE3GYkC9tYp8fk89OSwNsmXgizrhUtnumeSgeo5GbLUMk49Rv+2nK48Cm/qMwfp333J2/
|
| +dVcAGE0CIQHBsgIeEr4Wij0LtWDLzJ9ze5YEvH2WI6CHTAVcSu9ZCsXtgxu81CIvp6/k4eXsdfo7
|
| +PvDCRD75yi41QitfzlcPp1OI7i/1/iQitqnr0iMgQ+A6wa+IKwwdxyk9IiXNAzgquTFU8NIxAVjM
|
| +osm1Zz526e+shQ4hKRVci69nPC3Kw4NQEmkQ65E7OodxorSvxjvpBjQHDmWFIQ1mlmzlS5vedseT
|
| +/mgIEsMJ7Lxz2bLAF9M5xeLEhdbHxpWOw0GdkJApMVBRF1y+a0z3c9WZPAXGFcFrJgCIB+024uad
|
| +0CrzmEoRa3Ub4swNIHPGf7QDV+2uj2OiFWsChgCwjKqN6rp5izpbH6Wc1O1TclQTP/XVwi6anTr1
|
| +1sbubjZLI1+VptPSdCfwnFBrB1jvebrTA9uUhU2/9gad7xPqeFkaQcnnLbCViZK8d7R1kxzFrIJV
|
| +8EaLYmKYpvGVkig+3C5HCXbM1jGCGekiM2pRCVPyRyXYdPf6kcbWEQ36F5V4Gq9N7icNNw+JHwRE
|
| +LTgxRXACpvnQv/PuT0xCCAywY/K4hE6Now2qDwaSE5FB+1agsoUveYDepS83qFcF1NufvULD3fTl
|
| +g6Hgf7WBt6lzMeiyyWVn3P1WVbwaczHmTzE9A5SyItTVgFYyvs/L/fXlaNgbw8v3azT+0eikVlWD
|
| +/vBHbzQumP23uBCjsYdrL9OWARwxs/nuLOzeXbPJTa/Xv6sUmQir5pC1YRLz3eA+CD8Z0XpcW8v9
|
| +MZWF36ryyXXf3yBIz6nzqz8Muyz0m5Qj7OexfYo/Ph3LqvkHUg7AuA==
|
| +""")
|
| +
|
| MH_MAGIC = 0xfeedface
|
| MH_CIGAM = 0xcefaedfe
|
| MH_MAGIC_64 = 0xfeedfacf
|
| @@ -2356,12 +2319,14 @@ def mach_o_change(path, what, value):
|
| do_macho(file, 64, LITTLE_ENDIAN)
|
|
|
| assert(len(what) >= len(value))
|
| - do_file(open(path, 'r+b'))
|
| +
|
| + with open(path, 'r+b') as f:
|
| + do_file(f)
|
|
|
|
|
| if __name__ == '__main__':
|
| main()
|
|
|
| -## TODO:
|
| -## Copy python.exe.manifest
|
| -## Monkeypatch distutils.sysconfig
|
| +# TODO:
|
| +# Copy python.exe.manifest
|
| +# Monkeypatch distutils.sysconfig
|
|
|