| 
							 | 
						""" | 
					
					
						
						| 
							 | 
						Easy Install | 
					
					
						
						| 
							 | 
						------------ | 
					
					
						
						| 
							 | 
						 | 
					
					
						
						| 
							 | 
						A tool for doing automatic download/extract/build of distutils-based Python | 
					
					
						
						| 
							 | 
						packages.  For detailed documentation, see the accompanying EasyInstall.txt | 
					
					
						
						| 
							 | 
						file, or visit the `EasyInstall home page`__. | 
					
					
						
						| 
							 | 
						 | 
					
					
						
						| 
							 | 
						__ https://setuptools.pypa.io/en/latest/deprecated/easy_install.html | 
					
					
						
						| 
							 | 
						 | 
					
					
						
						| 
							 | 
						""" | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						from glob import glob | 
					
					
						
						| 
							 | 
						from distutils.util import get_platform | 
					
					
						
						| 
							 | 
						from distutils.util import convert_path, subst_vars | 
					
					
						
						| 
							 | 
						from distutils.errors import ( | 
					
					
						
						| 
							 | 
						    DistutilsArgError, DistutilsOptionError, | 
					
					
						
						| 
							 | 
						    DistutilsError, DistutilsPlatformError, | 
					
					
						
						| 
							 | 
						) | 
					
					
						
						| 
							 | 
						from distutils import log, dir_util | 
					
					
						
						| 
							 | 
						from distutils.command.build_scripts import first_line_re | 
					
					
						
						| 
							 | 
						from distutils.spawn import find_executable | 
					
					
						
						| 
							 | 
						from distutils.command import install | 
					
					
						
						| 
							 | 
						import sys | 
					
					
						
						| 
							 | 
						import os | 
					
					
						
						| 
							 | 
						import zipimport | 
					
					
						
						| 
							 | 
						import shutil | 
					
					
						
						| 
							 | 
						import tempfile | 
					
					
						
						| 
							 | 
						import zipfile | 
					
					
						
						| 
							 | 
						import re | 
					
					
						
						| 
							 | 
						import stat | 
					
					
						
						| 
							 | 
						import random | 
					
					
						
						| 
							 | 
						import textwrap | 
					
					
						
						| 
							 | 
						import warnings | 
					
					
						
						| 
							 | 
						import site | 
					
					
						
						| 
							 | 
						import struct | 
					
					
						
						| 
							 | 
						import contextlib | 
					
					
						
						| 
							 | 
						import subprocess | 
					
					
						
						| 
							 | 
						import shlex | 
					
					
						
						| 
							 | 
						import io | 
					
					
						
						| 
							 | 
						import configparser | 
					
					
						
						| 
							 | 
						import sysconfig | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						from sysconfig import get_path | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						from setuptools import SetuptoolsDeprecationWarning | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						from setuptools import Command | 
					
					
						
						| 
							 | 
						from setuptools.sandbox import run_setup | 
					
					
						
						| 
							 | 
						from setuptools.command import setopt | 
					
					
						
						| 
							 | 
						from setuptools.archive_util import unpack_archive | 
					
					
						
						| 
							 | 
						from setuptools.package_index import ( | 
					
					
						
						| 
							 | 
						    PackageIndex, parse_requirement_arg, URL_SCHEME, | 
					
					
						
						| 
							 | 
						) | 
					
					
						
						| 
							 | 
						from setuptools.command import bdist_egg, egg_info | 
					
					
						
						| 
							 | 
						from setuptools.wheel import Wheel | 
					
					
						
						| 
							 | 
						from pkg_resources import ( | 
					
					
						
						| 
							 | 
						    normalize_path, resource_string, | 
					
					
						
						| 
							 | 
						    get_distribution, find_distributions, Environment, Requirement, | 
					
					
						
						| 
							 | 
						    Distribution, PathMetadata, EggMetadata, WorkingSet, DistributionNotFound, | 
					
					
						
						| 
							 | 
						    VersionConflict, DEVELOP_DIST, | 
					
					
						
						| 
							 | 
						) | 
					
					
						
						| 
							 | 
						import pkg_resources | 
					
					
						
						| 
							 | 
						from .._path import ensure_directory | 
					
					
						
						| 
							 | 
						from ..extern.jaraco.text import yield_lines | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						 | 
					
					
						
						| 
							 | 
						warnings.filterwarnings("default", category=pkg_resources.PEP440Warning) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						__all__ = [ | 
					
					
						
						| 
							 | 
						    'easy_install', 'PthDistributions', 'extract_wininst_cfg', | 
					
					
						
						| 
							 | 
						    'get_exe_prefixes', | 
					
					
						
						| 
							 | 
						] | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						def is_64bit(): | 
					
					
						
						| 
							 | 
						    return struct.calcsize("P") == 8 | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						def _to_bytes(s): | 
					
					
						
						| 
							 | 
						    return s.encode('utf8') | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						def isascii(s): | 
					
					
						
						| 
							 | 
						    try: | 
					
					
						
						| 
							 | 
						        s.encode('ascii') | 
					
					
						
						| 
							 | 
						        return True | 
					
					
						
						| 
							 | 
						    except UnicodeError: | 
					
					
						
						| 
							 | 
						        return False | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						def _one_liner(text): | 
					
					
						
						| 
							 | 
						    return textwrap.dedent(text).strip().replace('\n', '; ') | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						class easy_install(Command): | 
					
					
						
						| 
							 | 
						    """Manage a download/build/install process""" | 
					
					
						
						| 
							 | 
						    description = "Find/get/install Python packages" | 
					
					
						
						| 
							 | 
						    command_consumes_arguments = True | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						    user_options = [ | 
					
					
						
						| 
							 | 
						        ('prefix=', None, "installation prefix"), | 
					
					
						
						| 
							 | 
						        ("zip-ok", "z", "install package as a zipfile"), | 
					
					
						
						| 
							 | 
						        ("multi-version", "m", "make apps have to require() a version"), | 
					
					
						
						| 
							 | 
						        ("upgrade", "U", "force upgrade (searches PyPI for latest versions)"), | 
					
					
						
						| 
							 | 
						        ("install-dir=", "d", "install package to DIR"), | 
					
					
						
						| 
							 | 
						        ("script-dir=", "s", "install scripts to DIR"), | 
					
					
						
						| 
							 | 
						        ("exclude-scripts", "x", "Don't install scripts"), | 
					
					
						
						| 
							 | 
						        ("always-copy", "a", "Copy all needed packages to install dir"), | 
					
					
						
						| 
							 | 
						        ("index-url=", "i", "base URL of Python Package Index"), | 
					
					
						
						| 
							 | 
						        ("find-links=", "f", "additional URL(s) to search for packages"), | 
					
					
						
						| 
							 | 
						        ("build-directory=", "b", | 
					
					
						
						| 
							 | 
						         "download/extract/build in DIR; keep the results"), | 
					
					
						
						| 
							 | 
						        ('optimize=', 'O', | 
					
					
						
						| 
							 | 
						         "also compile with optimization: -O1 for \"python -O\", " | 
					
					
						
						| 
							 | 
						         "-O2 for \"python -OO\", and -O0 to disable [default: -O0]"), | 
					
					
						
						| 
							 | 
						        ('record=', None, | 
					
					
						
						| 
							 | 
						         "filename in which to record list of installed files"), | 
					
					
						
						| 
							 | 
						        ('always-unzip', 'Z', "don't install as a zipfile, no matter what"), | 
					
					
						
						| 
							 | 
						        ('site-dirs=', 'S', "list of directories where .pth files work"), | 
					
					
						
						| 
							 | 
						        ('editable', 'e', "Install specified packages in editable form"), | 
					
					
						
						| 
							 | 
						        ('no-deps', 'N', "don't install dependencies"), | 
					
					
						
						| 
							 | 
						        ('allow-hosts=', 'H', "pattern(s) that hostnames must match"), | 
					
					
						
						| 
							 | 
						        ('local-snapshots-ok', 'l', | 
					
					
						
						| 
							 | 
						         "allow building eggs from local checkouts"), | 
					
					
						
						| 
							 | 
						        ('version', None, "print version information and exit"), | 
					
					
						
						| 
							 | 
						        ('no-find-links', None, | 
					
					
						
						| 
							 | 
						         "Don't load find-links defined in packages being installed"), | 
					
					
						
						| 
							 | 
						        ('user', None, "install in user site-package '%s'" % site.USER_SITE) | 
					
					
						
						| 
							 | 
						    ] | 
					
					
						
						| 
							 | 
						    boolean_options = [ | 
					
					
						
						| 
							 | 
						        'zip-ok', 'multi-version', 'exclude-scripts', 'upgrade', 'always-copy', | 
					
					
						
						| 
							 | 
						        'editable', | 
					
					
						
						| 
							 | 
						        'no-deps', 'local-snapshots-ok', 'version', | 
					
					
						
						| 
							 | 
						        'user' | 
					
					
						
						| 
							 | 
						    ] | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						    negative_opt = {'always-unzip': 'zip-ok'} | 
					
					
						
						| 
							 | 
						    create_index = PackageIndex | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						    def initialize_options(self): | 
					
					
						
						| 
							 | 
						        warnings.warn( | 
					
					
						
						| 
							 | 
						            "easy_install command is deprecated. " | 
					
					
						
						| 
							 | 
						            "Use build and pip and other standards-based tools.", | 
					
					
						
						| 
							 | 
						            EasyInstallDeprecationWarning, | 
					
					
						
						| 
							 | 
						        ) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						         | 
					
					
						
						| 
							 | 
						         | 
					
					
						
						| 
							 | 
						        self.user = 0 | 
					
					
						
						| 
							 | 
						        self.zip_ok = self.local_snapshots_ok = None | 
					
					
						
						| 
							 | 
						        self.install_dir = self.script_dir = self.exclude_scripts = None | 
					
					
						
						| 
							 | 
						        self.index_url = None | 
					
					
						
						| 
							 | 
						        self.find_links = None | 
					
					
						
						| 
							 | 
						        self.build_directory = None | 
					
					
						
						| 
							 | 
						        self.args = None | 
					
					
						
						| 
							 | 
						        self.optimize = self.record = None | 
					
					
						
						| 
							 | 
						        self.upgrade = self.always_copy = self.multi_version = None | 
					
					
						
						| 
							 | 
						        self.editable = self.no_deps = self.allow_hosts = None | 
					
					
						
						| 
							 | 
						        self.root = self.prefix = self.no_report = None | 
					
					
						
						| 
							 | 
						        self.version = None | 
					
					
						
						| 
							 | 
						        self.install_purelib = None   | 
					
					
						
						| 
							 | 
						        self.install_platlib = None   | 
					
					
						
						| 
							 | 
						        self.install_headers = None   | 
					
					
						
						| 
							 | 
						        self.install_lib = None   | 
					
					
						
						| 
							 | 
						        self.install_scripts = None | 
					
					
						
						| 
							 | 
						        self.install_data = None | 
					
					
						
						| 
							 | 
						        self.install_base = None | 
					
					
						
						| 
							 | 
						        self.install_platbase = None | 
					
					
						
						| 
							 | 
						        self.install_userbase = site.USER_BASE | 
					
					
						
						| 
							 | 
						        self.install_usersite = site.USER_SITE | 
					
					
						
						| 
							 | 
						        self.no_find_links = None | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						         | 
					
					
						
						| 
							 | 
						        self.package_index = None | 
					
					
						
						| 
							 | 
						        self.pth_file = self.always_copy_from = None | 
					
					
						
						| 
							 | 
						        self.site_dirs = None | 
					
					
						
						| 
							 | 
						        self.installed_projects = {} | 
					
					
						
						| 
							 | 
						         | 
					
					
						
						| 
							 | 
						         | 
					
					
						
						| 
							 | 
						         | 
					
					
						
						| 
							 | 
						         | 
					
					
						
						| 
							 | 
						         | 
					
					
						
						| 
							 | 
						        self._dry_run = None | 
					
					
						
						| 
							 | 
						        self.verbose = self.distribution.verbose | 
					
					
						
						| 
							 | 
						        self.distribution._set_command_options( | 
					
					
						
						| 
							 | 
						            self, self.distribution.get_option_dict('easy_install') | 
					
					
						
						| 
							 | 
						        ) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						    def delete_blockers(self, blockers): | 
					
					
						
						| 
							 | 
						        extant_blockers = ( | 
					
					
						
						| 
							 | 
						            filename for filename in blockers | 
					
					
						
						| 
							 | 
						            if os.path.exists(filename) or os.path.islink(filename) | 
					
					
						
						| 
							 | 
						        ) | 
					
					
						
						| 
							 | 
						        list(map(self._delete_path, extant_blockers)) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						    def _delete_path(self, path): | 
					
					
						
						| 
							 | 
						        log.info("Deleting %s", path) | 
					
					
						
						| 
							 | 
						        if self.dry_run: | 
					
					
						
						| 
							 | 
						            return | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						        is_tree = os.path.isdir(path) and not os.path.islink(path) | 
					
					
						
						| 
							 | 
						        remover = rmtree if is_tree else os.unlink | 
					
					
						
						| 
							 | 
						        remover(path) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						    @staticmethod | 
					
					
						
						| 
							 | 
						    def _render_version(): | 
					
					
						
						| 
							 | 
						        """ | 
					
					
						
						| 
							 | 
						        Render the Setuptools version and installation details, then exit. | 
					
					
						
						| 
							 | 
						        """ | 
					
					
						
						| 
							 | 
						        ver = '{}.{}'.format(*sys.version_info) | 
					
					
						
						| 
							 | 
						        dist = get_distribution('setuptools') | 
					
					
						
						| 
							 | 
						        tmpl = 'setuptools {dist.version} from {dist.location} (Python {ver})' | 
					
					
						
						| 
							 | 
						        print(tmpl.format(**locals())) | 
					
					
						
						| 
							 | 
						        raise SystemExit() | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						    def finalize_options(self):   | 
					
					
						
						| 
							 | 
						        self.version and self._render_version() | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						        py_version = sys.version.split()[0] | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						        self.config_vars = dict(sysconfig.get_config_vars()) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						        self.config_vars.update({ | 
					
					
						
						| 
							 | 
						            'dist_name': self.distribution.get_name(), | 
					
					
						
						| 
							 | 
						            'dist_version': self.distribution.get_version(), | 
					
					
						
						| 
							 | 
						            'dist_fullname': self.distribution.get_fullname(), | 
					
					
						
						| 
							 | 
						            'py_version': py_version, | 
					
					
						
						| 
							 | 
						            'py_version_short': f'{sys.version_info.major}.{sys.version_info.minor}', | 
					
					
						
						| 
							 | 
						            'py_version_nodot': f'{sys.version_info.major}{sys.version_info.minor}', | 
					
					
						
						| 
							 | 
						            'sys_prefix': self.config_vars['prefix'], | 
					
					
						
						| 
							 | 
						            'sys_exec_prefix': self.config_vars['exec_prefix'], | 
					
					
						
						| 
							 | 
						             | 
					
					
						
						| 
							 | 
						            'abiflags': getattr(sys, 'abiflags', ''), | 
					
					
						
						| 
							 | 
						            'platlibdir': getattr(sys, 'platlibdir', 'lib'), | 
					
					
						
						| 
							 | 
						        }) | 
					
					
						
						| 
							 | 
						        with contextlib.suppress(AttributeError): | 
					
					
						
						| 
							 | 
						             | 
					
					
						
						| 
							 | 
						            self.config_vars.update({ | 
					
					
						
						| 
							 | 
						                'implementation_lower': install._get_implementation().lower(), | 
					
					
						
						| 
							 | 
						                'implementation': install._get_implementation(), | 
					
					
						
						| 
							 | 
						            }) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						         | 
					
					
						
						| 
							 | 
						        self.config_vars.setdefault( | 
					
					
						
						| 
							 | 
						            'py_version_nodot_plat', | 
					
					
						
						| 
							 | 
						            getattr(sys, 'windir', '').replace('.', ''), | 
					
					
						
						| 
							 | 
						        ) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						        self.config_vars['userbase'] = self.install_userbase | 
					
					
						
						| 
							 | 
						        self.config_vars['usersite'] = self.install_usersite | 
					
					
						
						| 
							 | 
						        if self.user and not site.ENABLE_USER_SITE: | 
					
					
						
						| 
							 | 
						            log.warn("WARNING: The user site-packages directory is disabled.") | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						        self._fix_install_dir_for_user_site() | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						        self.expand_basedirs() | 
					
					
						
						| 
							 | 
						        self.expand_dirs() | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						        self._expand( | 
					
					
						
						| 
							 | 
						            'install_dir', 'script_dir', 'build_directory', | 
					
					
						
						| 
							 | 
						            'site_dirs', | 
					
					
						
						| 
							 | 
						        ) | 
					
					
						
						| 
							 | 
						         | 
					
					
						
						| 
							 | 
						         | 
					
					
						
						| 
							 | 
						        if self.script_dir is None: | 
					
					
						
						| 
							 | 
						            self.script_dir = self.install_dir | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						        if self.no_find_links is None: | 
					
					
						
						| 
							 | 
						            self.no_find_links = False | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						         | 
					
					
						
						| 
							 | 
						         | 
					
					
						
						| 
							 | 
						         | 
					
					
						
						| 
							 | 
						        self.set_undefined_options( | 
					
					
						
						| 
							 | 
						            'install_lib', ('install_dir', 'install_dir') | 
					
					
						
						| 
							 | 
						        ) | 
					
					
						
						| 
							 | 
						         | 
					
					
						
						| 
							 | 
						        self.set_undefined_options( | 
					
					
						
						| 
							 | 
						            'install_scripts', ('install_dir', 'script_dir') | 
					
					
						
						| 
							 | 
						        ) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						        if self.user and self.install_purelib: | 
					
					
						
						| 
							 | 
						            self.install_dir = self.install_purelib | 
					
					
						
						| 
							 | 
						            self.script_dir = self.install_scripts | 
					
					
						
						| 
							 | 
						         | 
					
					
						
						| 
							 | 
						        self.set_undefined_options('install', ('record', 'record')) | 
					
					
						
						| 
							 | 
						        self.all_site_dirs = get_site_dirs() | 
					
					
						
						| 
							 | 
						        self.all_site_dirs.extend(self._process_site_dirs(self.site_dirs)) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						        if not self.editable: | 
					
					
						
						| 
							 | 
						            self.check_site_dir() | 
					
					
						
						| 
							 | 
						        default_index = os.getenv("__EASYINSTALL_INDEX", "https://pypi.org/simple/") | 
					
					
						
						| 
							 | 
						         | 
					
					
						
						| 
							 | 
						        self.index_url = self.index_url or default_index | 
					
					
						
						| 
							 | 
						        self.shadow_path = self.all_site_dirs[:] | 
					
					
						
						| 
							 | 
						        for path_item in self.install_dir, normalize_path(self.script_dir): | 
					
					
						
						| 
							 | 
						            if path_item not in self.shadow_path: | 
					
					
						
						| 
							 | 
						                self.shadow_path.insert(0, path_item) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						        if self.allow_hosts is not None: | 
					
					
						
						| 
							 | 
						            hosts = [s.strip() for s in self.allow_hosts.split(',')] | 
					
					
						
						| 
							 | 
						        else: | 
					
					
						
						| 
							 | 
						            hosts = ['*'] | 
					
					
						
						| 
							 | 
						        if self.package_index is None: | 
					
					
						
						| 
							 | 
						            self.package_index = self.create_index( | 
					
					
						
						| 
							 | 
						                self.index_url, search_path=self.shadow_path, hosts=hosts, | 
					
					
						
						| 
							 | 
						            ) | 
					
					
						
						| 
							 | 
						        self.local_index = Environment(self.shadow_path + sys.path) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						        if self.find_links is not None: | 
					
					
						
						| 
							 | 
						            if isinstance(self.find_links, str): | 
					
					
						
						| 
							 | 
						                self.find_links = self.find_links.split() | 
					
					
						
						| 
							 | 
						        else: | 
					
					
						
						| 
							 | 
						            self.find_links = [] | 
					
					
						
						| 
							 | 
						        if self.local_snapshots_ok: | 
					
					
						
						| 
							 | 
						            self.package_index.scan_egg_links(self.shadow_path + sys.path) | 
					
					
						
						| 
							 | 
						        if not self.no_find_links: | 
					
					
						
						| 
							 | 
						            self.package_index.add_find_links(self.find_links) | 
					
					
						
						| 
							 | 
						        self.set_undefined_options('install_lib', ('optimize', 'optimize')) | 
					
					
						
						| 
							 | 
						        self.optimize = self._validate_optimize(self.optimize) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						        if self.editable and not self.build_directory: | 
					
					
						
						| 
							 | 
						            raise DistutilsArgError( | 
					
					
						
						| 
							 | 
						                "Must specify a build directory (-b) when using --editable" | 
					
					
						
						| 
							 | 
						            ) | 
					
					
						
						| 
							 | 
						        if not self.args: | 
					
					
						
						| 
							 | 
						            raise DistutilsArgError( | 
					
					
						
						| 
							 | 
						                "No urls, filenames, or requirements specified (see --help)") | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						        self.outputs = [] | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						    @staticmethod | 
					
					
						
						| 
							 | 
						    def _process_site_dirs(site_dirs): | 
					
					
						
						| 
							 | 
						        if site_dirs is None: | 
					
					
						
						| 
							 | 
						            return | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						        normpath = map(normalize_path, sys.path) | 
					
					
						
						| 
							 | 
						        site_dirs = [ | 
					
					
						
						| 
							 | 
						            os.path.expanduser(s.strip()) for s in | 
					
					
						
						| 
							 | 
						            site_dirs.split(',') | 
					
					
						
						| 
							 | 
						        ] | 
					
					
						
						| 
							 | 
						        for d in site_dirs: | 
					
					
						
						| 
							 | 
						            if not os.path.isdir(d): | 
					
					
						
						| 
							 | 
						                log.warn("%s (in --site-dirs) does not exist", d) | 
					
					
						
						| 
							 | 
						            elif normalize_path(d) not in normpath: | 
					
					
						
						| 
							 | 
						                raise DistutilsOptionError( | 
					
					
						
						| 
							 | 
						                    d + " (in --site-dirs) is not on sys.path" | 
					
					
						
						| 
							 | 
						                ) | 
					
					
						
						| 
							 | 
						            else: | 
					
					
						
						| 
							 | 
						                yield normalize_path(d) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						    @staticmethod | 
					
					
						
						| 
							 | 
						    def _validate_optimize(value): | 
					
					
						
						| 
							 | 
						        try: | 
					
					
						
						| 
							 | 
						            value = int(value) | 
					
					
						
						| 
							 | 
						            if value not in range(3): | 
					
					
						
						| 
							 | 
						                raise ValueError | 
					
					
						
						| 
							 | 
						        except ValueError as e: | 
					
					
						
						| 
							 | 
						            raise DistutilsOptionError( | 
					
					
						
						| 
							 | 
						                "--optimize must be 0, 1, or 2" | 
					
					
						
						| 
							 | 
						            ) from e | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						        return value | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						    def _fix_install_dir_for_user_site(self): | 
					
					
						
						| 
							 | 
						        """ | 
					
					
						
						| 
							 | 
						        Fix the install_dir if "--user" was used. | 
					
					
						
						| 
							 | 
						        """ | 
					
					
						
						| 
							 | 
						        if not self.user: | 
					
					
						
						| 
							 | 
						            return | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						        self.create_home_path() | 
					
					
						
						| 
							 | 
						        if self.install_userbase is None: | 
					
					
						
						| 
							 | 
						            msg = "User base directory is not specified" | 
					
					
						
						| 
							 | 
						            raise DistutilsPlatformError(msg) | 
					
					
						
						| 
							 | 
						        self.install_base = self.install_platbase = self.install_userbase | 
					
					
						
						| 
							 | 
						        scheme_name = f'{os.name}_user' | 
					
					
						
						| 
							 | 
						        self.select_scheme(scheme_name) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						    def _expand_attrs(self, attrs): | 
					
					
						
						| 
							 | 
						        for attr in attrs: | 
					
					
						
						| 
							 | 
						            val = getattr(self, attr) | 
					
					
						
						| 
							 | 
						            if val is not None: | 
					
					
						
						| 
							 | 
						                if os.name == 'posix' or os.name == 'nt': | 
					
					
						
						| 
							 | 
						                    val = os.path.expanduser(val) | 
					
					
						
						| 
							 | 
						                val = subst_vars(val, self.config_vars) | 
					
					
						
						| 
							 | 
						                setattr(self, attr, val) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						    def expand_basedirs(self): | 
					
					
						
						| 
							 | 
						        """Calls `os.path.expanduser` on install_base, install_platbase and | 
					
					
						
						| 
							 | 
						        root.""" | 
					
					
						
						| 
							 | 
						        self._expand_attrs(['install_base', 'install_platbase', 'root']) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						    def expand_dirs(self): | 
					
					
						
						| 
							 | 
						        """Calls `os.path.expanduser` on install dirs.""" | 
					
					
						
						| 
							 | 
						        dirs = [ | 
					
					
						
						| 
							 | 
						            'install_purelib', | 
					
					
						
						| 
							 | 
						            'install_platlib', | 
					
					
						
						| 
							 | 
						            'install_lib', | 
					
					
						
						| 
							 | 
						            'install_headers', | 
					
					
						
						| 
							 | 
						            'install_scripts', | 
					
					
						
						| 
							 | 
						            'install_data', | 
					
					
						
						| 
							 | 
						        ] | 
					
					
						
						| 
							 | 
						        self._expand_attrs(dirs) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						    def run(self, show_deprecation=True): | 
					
					
						
						| 
							 | 
						        if show_deprecation: | 
					
					
						
						| 
							 | 
						            self.announce( | 
					
					
						
						| 
							 | 
						                "WARNING: The easy_install command is deprecated " | 
					
					
						
						| 
							 | 
						                "and will be removed in a future version.", | 
					
					
						
						| 
							 | 
						                log.WARN, | 
					
					
						
						| 
							 | 
						            ) | 
					
					
						
						| 
							 | 
						        if self.verbose != self.distribution.verbose: | 
					
					
						
						| 
							 | 
						            log.set_verbosity(self.verbose) | 
					
					
						
						| 
							 | 
						        try: | 
					
					
						
						| 
							 | 
						            for spec in self.args: | 
					
					
						
						| 
							 | 
						                self.easy_install(spec, not self.no_deps) | 
					
					
						
						| 
							 | 
						            if self.record: | 
					
					
						
						| 
							 | 
						                outputs = self.outputs | 
					
					
						
						| 
							 | 
						                if self.root:   | 
					
					
						
						| 
							 | 
						                    root_len = len(self.root) | 
					
					
						
						| 
							 | 
						                    for counter in range(len(outputs)): | 
					
					
						
						| 
							 | 
						                        outputs[counter] = outputs[counter][root_len:] | 
					
					
						
						| 
							 | 
						                from distutils import file_util | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						                self.execute( | 
					
					
						
						| 
							 | 
						                    file_util.write_file, (self.record, outputs), | 
					
					
						
						| 
							 | 
						                    "writing list of installed files to '%s'" % | 
					
					
						
						| 
							 | 
						                    self.record | 
					
					
						
						| 
							 | 
						                ) | 
					
					
						
						| 
							 | 
						            self.warn_deprecated_options() | 
					
					
						
						| 
							 | 
						        finally: | 
					
					
						
						| 
							 | 
						            log.set_verbosity(self.distribution.verbose) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						    def pseudo_tempname(self): | 
					
					
						
						| 
							 | 
						        """Return a pseudo-tempname base in the install directory. | 
					
					
						
						| 
							 | 
						        This code is intentionally naive; if a malicious party can write to | 
					
					
						
						| 
							 | 
						        the target directory you're already in deep doodoo. | 
					
					
						
						| 
							 | 
						        """ | 
					
					
						
						| 
							 | 
						        try: | 
					
					
						
						| 
							 | 
						            pid = os.getpid() | 
					
					
						
						| 
							 | 
						        except Exception: | 
					
					
						
						| 
							 | 
						            pid = random.randint(0, sys.maxsize) | 
					
					
						
						| 
							 | 
						        return os.path.join(self.install_dir, "test-easy-install-%s" % pid) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						    def warn_deprecated_options(self): | 
					
					
						
						| 
							 | 
						        pass | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						    def check_site_dir(self):   | 
					
					
						
						| 
							 | 
						        """Verify that self.install_dir is .pth-capable dir, if needed""" | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						        instdir = normalize_path(self.install_dir) | 
					
					
						
						| 
							 | 
						        pth_file = os.path.join(instdir, 'easy-install.pth') | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						        if not os.path.exists(instdir): | 
					
					
						
						| 
							 | 
						            try: | 
					
					
						
						| 
							 | 
						                os.makedirs(instdir) | 
					
					
						
						| 
							 | 
						            except (OSError, IOError): | 
					
					
						
						| 
							 | 
						                self.cant_write_to_target() | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						         | 
					
					
						
						| 
							 | 
						        is_site_dir = instdir in self.all_site_dirs | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						        if not is_site_dir and not self.multi_version: | 
					
					
						
						| 
							 | 
						             | 
					
					
						
						| 
							 | 
						            is_site_dir = self.check_pth_processing() | 
					
					
						
						| 
							 | 
						        else: | 
					
					
						
						| 
							 | 
						             | 
					
					
						
						| 
							 | 
						            testfile = self.pseudo_tempname() + '.write-test' | 
					
					
						
						| 
							 | 
						            test_exists = os.path.exists(testfile) | 
					
					
						
						| 
							 | 
						            try: | 
					
					
						
						| 
							 | 
						                if test_exists: | 
					
					
						
						| 
							 | 
						                    os.unlink(testfile) | 
					
					
						
						| 
							 | 
						                open(testfile, 'w').close() | 
					
					
						
						| 
							 | 
						                os.unlink(testfile) | 
					
					
						
						| 
							 | 
						            except (OSError, IOError): | 
					
					
						
						| 
							 | 
						                self.cant_write_to_target() | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						        if not is_site_dir and not self.multi_version: | 
					
					
						
						| 
							 | 
						             | 
					
					
						
						| 
							 | 
						            pythonpath = os.environ.get('PYTHONPATH', '') | 
					
					
						
						| 
							 | 
						            log.warn(self.__no_default_msg, self.install_dir, pythonpath) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						        if is_site_dir: | 
					
					
						
						| 
							 | 
						            if self.pth_file is None: | 
					
					
						
						| 
							 | 
						                self.pth_file = PthDistributions(pth_file, self.all_site_dirs) | 
					
					
						
						| 
							 | 
						        else: | 
					
					
						
						| 
							 | 
						            self.pth_file = None | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						        if self.multi_version and not os.path.exists(pth_file): | 
					
					
						
						| 
							 | 
						            self.pth_file = None   | 
					
					
						
						| 
							 | 
						        self.install_dir = instdir | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						    __cant_write_msg = textwrap.dedent(""" | 
					
					
						
						| 
							 | 
						        can't create or remove files in install directory | 
					
					
						
						| 
							 | 
						 | 
					
					
						
						| 
							 | 
						        The following error occurred while trying to add or remove files in the | 
					
					
						
						| 
							 | 
						        installation directory: | 
					
					
						
						| 
							 | 
						 | 
					
					
						
						| 
							 | 
						            %s | 
					
					
						
						| 
							 | 
						 | 
					
					
						
						| 
							 | 
						        The installation directory you specified (via --install-dir, --prefix, or | 
					
					
						
						| 
							 | 
						        the distutils default setting) was: | 
					
					
						
						| 
							 | 
						 | 
					
					
						
						| 
							 | 
						            %s | 
					
					
						
						| 
							 | 
						        """).lstrip()   | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						    __not_exists_id = textwrap.dedent(""" | 
					
					
						
						| 
							 | 
						        This directory does not currently exist.  Please create it and try again, or | 
					
					
						
						| 
							 | 
						        choose a different installation directory (using the -d or --install-dir | 
					
					
						
						| 
							 | 
						        option). | 
					
					
						
						| 
							 | 
						        """).lstrip()   | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						    __access_msg = textwrap.dedent(""" | 
					
					
						
						| 
							 | 
						        Perhaps your account does not have write access to this directory?  If the | 
					
					
						
						| 
							 | 
						        installation directory is a system-owned directory, you may need to sign in | 
					
					
						
						| 
							 | 
						        as the administrator or "root" account.  If you do not have administrative | 
					
					
						
						| 
							 | 
						        access to this machine, you may wish to choose a different installation | 
					
					
						
						| 
							 | 
						        directory, preferably one that is listed in your PYTHONPATH environment | 
					
					
						
						| 
							 | 
						        variable. | 
					
					
						
						| 
							 | 
						 | 
					
					
						
						| 
							 | 
						        For information on other options, you may wish to consult the | 
					
					
						
						| 
							 | 
						        documentation at: | 
					
					
						
						| 
							 | 
						 | 
					
					
						
						| 
							 | 
						          https://setuptools.pypa.io/en/latest/deprecated/easy_install.html | 
					
					
						
						| 
							 | 
						 | 
					
					
						
						| 
							 | 
						        Please make the appropriate changes for your system and try again. | 
					
					
						
						| 
							 | 
						        """).lstrip()   | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						    def cant_write_to_target(self): | 
					
					
						
						| 
							 | 
						        msg = self.__cant_write_msg % (sys.exc_info()[1], self.install_dir,) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						        if not os.path.exists(self.install_dir): | 
					
					
						
						| 
							 | 
						            msg += '\n' + self.__not_exists_id | 
					
					
						
						| 
							 | 
						        else: | 
					
					
						
						| 
							 | 
						            msg += '\n' + self.__access_msg | 
					
					
						
						| 
							 | 
						        raise DistutilsError(msg) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						    def check_pth_processing(self): | 
					
					
						
						| 
							 | 
						        """Empirically verify whether .pth files are supported in inst. dir""" | 
					
					
						
						| 
							 | 
						        instdir = self.install_dir | 
					
					
						
						| 
							 | 
						        log.info("Checking .pth file support in %s", instdir) | 
					
					
						
						| 
							 | 
						        pth_file = self.pseudo_tempname() + ".pth" | 
					
					
						
						| 
							 | 
						        ok_file = pth_file + '.ok' | 
					
					
						
						| 
							 | 
						        ok_exists = os.path.exists(ok_file) | 
					
					
						
						| 
							 | 
						        tmpl = _one_liner(""" | 
					
					
						
						| 
							 | 
						            import os | 
					
					
						
						| 
							 | 
						            f = open({ok_file!r}, 'w') | 
					
					
						
						| 
							 | 
						            f.write('OK') | 
					
					
						
						| 
							 | 
						            f.close() | 
					
					
						
						| 
							 | 
						            """) + '\n' | 
					
					
						
						| 
							 | 
						        try: | 
					
					
						
						| 
							 | 
						            if ok_exists: | 
					
					
						
						| 
							 | 
						                os.unlink(ok_file) | 
					
					
						
						| 
							 | 
						            dirname = os.path.dirname(ok_file) | 
					
					
						
						| 
							 | 
						            os.makedirs(dirname, exist_ok=True) | 
					
					
						
						| 
							 | 
						            f = open(pth_file, 'w') | 
					
					
						
						| 
							 | 
						        except (OSError, IOError): | 
					
					
						
						| 
							 | 
						            self.cant_write_to_target() | 
					
					
						
						| 
							 | 
						        else: | 
					
					
						
						| 
							 | 
						            try: | 
					
					
						
						| 
							 | 
						                f.write(tmpl.format(**locals())) | 
					
					
						
						| 
							 | 
						                f.close() | 
					
					
						
						| 
							 | 
						                f = None | 
					
					
						
						| 
							 | 
						                executable = sys.executable | 
					
					
						
						| 
							 | 
						                if os.name == 'nt': | 
					
					
						
						| 
							 | 
						                    dirname, basename = os.path.split(executable) | 
					
					
						
						| 
							 | 
						                    alt = os.path.join(dirname, 'pythonw.exe') | 
					
					
						
						| 
							 | 
						                    use_alt = ( | 
					
					
						
						| 
							 | 
						                        basename.lower() == 'python.exe' and | 
					
					
						
						| 
							 | 
						                        os.path.exists(alt) | 
					
					
						
						| 
							 | 
						                    ) | 
					
					
						
						| 
							 | 
						                    if use_alt: | 
					
					
						
						| 
							 | 
						                         | 
					
					
						
						| 
							 | 
						                        executable = alt | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						                from distutils.spawn import spawn | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						                spawn([executable, '-E', '-c', 'pass'], 0) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						                if os.path.exists(ok_file): | 
					
					
						
						| 
							 | 
						                    log.info( | 
					
					
						
						| 
							 | 
						                        "TEST PASSED: %s appears to support .pth files", | 
					
					
						
						| 
							 | 
						                        instdir | 
					
					
						
						| 
							 | 
						                    ) | 
					
					
						
						| 
							 | 
						                    return True | 
					
					
						
						| 
							 | 
						            finally: | 
					
					
						
						| 
							 | 
						                if f: | 
					
					
						
						| 
							 | 
						                    f.close() | 
					
					
						
						| 
							 | 
						                if os.path.exists(ok_file): | 
					
					
						
						| 
							 | 
						                    os.unlink(ok_file) | 
					
					
						
						| 
							 | 
						                if os.path.exists(pth_file): | 
					
					
						
						| 
							 | 
						                    os.unlink(pth_file) | 
					
					
						
						| 
							 | 
						        if not self.multi_version: | 
					
					
						
						| 
							 | 
						            log.warn("TEST FAILED: %s does NOT support .pth files", instdir) | 
					
					
						
						| 
							 | 
						        return False | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						    def install_egg_scripts(self, dist): | 
					
					
						
						| 
							 | 
						        """Write all the scripts for `dist`, unless scripts are excluded""" | 
					
					
						
						| 
							 | 
						        if not self.exclude_scripts and dist.metadata_isdir('scripts'): | 
					
					
						
						| 
							 | 
						            for script_name in dist.metadata_listdir('scripts'): | 
					
					
						
						| 
							 | 
						                if dist.metadata_isdir('scripts/' + script_name): | 
					
					
						
						| 
							 | 
						                     | 
					
					
						
						| 
							 | 
						                     | 
					
					
						
						| 
							 | 
						                    continue | 
					
					
						
						| 
							 | 
						                self.install_script( | 
					
					
						
						| 
							 | 
						                    dist, script_name, | 
					
					
						
						| 
							 | 
						                    dist.get_metadata('scripts/' + script_name) | 
					
					
						
						| 
							 | 
						                ) | 
					
					
						
						| 
							 | 
						        self.install_wrapper_scripts(dist) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						    def add_output(self, path): | 
					
					
						
						| 
							 | 
						        if os.path.isdir(path): | 
					
					
						
						| 
							 | 
						            for base, dirs, files in os.walk(path): | 
					
					
						
						| 
							 | 
						                for filename in files: | 
					
					
						
						| 
							 | 
						                    self.outputs.append(os.path.join(base, filename)) | 
					
					
						
						| 
							 | 
						        else: | 
					
					
						
						| 
							 | 
						            self.outputs.append(path) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						    def not_editable(self, spec): | 
					
					
						
						| 
							 | 
						        if self.editable: | 
					
					
						
						| 
							 | 
						            raise DistutilsArgError( | 
					
					
						
						| 
							 | 
						                "Invalid argument %r: you can't use filenames or URLs " | 
					
					
						
						| 
							 | 
						                "with --editable (except via the --find-links option)." | 
					
					
						
						| 
							 | 
						                % (spec,) | 
					
					
						
						| 
							 | 
						            ) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						    def check_editable(self, spec): | 
					
					
						
						| 
							 | 
						        if not self.editable: | 
					
					
						
						| 
							 | 
						            return | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						        if os.path.exists(os.path.join(self.build_directory, spec.key)): | 
					
					
						
						| 
							 | 
						            raise DistutilsArgError( | 
					
					
						
						| 
							 | 
						                "%r already exists in %s; can't do a checkout there" % | 
					
					
						
						| 
							 | 
						                (spec.key, self.build_directory) | 
					
					
						
						| 
							 | 
						            ) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						    @contextlib.contextmanager | 
					
					
						
						| 
							 | 
						    def _tmpdir(self): | 
					
					
						
						| 
							 | 
						        tmpdir = tempfile.mkdtemp(prefix=u"easy_install-") | 
					
					
						
						| 
							 | 
						        try: | 
					
					
						
						| 
							 | 
						             | 
					
					
						
						| 
							 | 
						            yield str(tmpdir) | 
					
					
						
						| 
							 | 
						        finally: | 
					
					
						
						| 
							 | 
						            os.path.exists(tmpdir) and rmtree(tmpdir) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						    def easy_install(self, spec, deps=False): | 
					
					
						
						| 
							 | 
						        with self._tmpdir() as tmpdir: | 
					
					
						
						| 
							 | 
						            if not isinstance(spec, Requirement): | 
					
					
						
						| 
							 | 
						                if URL_SCHEME(spec): | 
					
					
						
						| 
							 | 
						                     | 
					
					
						
						| 
							 | 
						                    self.not_editable(spec) | 
					
					
						
						| 
							 | 
						                    dl = self.package_index.download(spec, tmpdir) | 
					
					
						
						| 
							 | 
						                    return self.install_item(None, dl, tmpdir, deps, True) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						                elif os.path.exists(spec): | 
					
					
						
						| 
							 | 
						                     | 
					
					
						
						| 
							 | 
						                    self.not_editable(spec) | 
					
					
						
						| 
							 | 
						                    return self.install_item(None, spec, tmpdir, deps, True) | 
					
					
						
						| 
							 | 
						                else: | 
					
					
						
						| 
							 | 
						                    spec = parse_requirement_arg(spec) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						            self.check_editable(spec) | 
					
					
						
						| 
							 | 
						            dist = self.package_index.fetch_distribution( | 
					
					
						
						| 
							 | 
						                spec, tmpdir, self.upgrade, self.editable, | 
					
					
						
						| 
							 | 
						                not self.always_copy, self.local_index | 
					
					
						
						| 
							 | 
						            ) | 
					
					
						
						| 
							 | 
						            if dist is None: | 
					
					
						
						| 
							 | 
						                msg = "Could not find suitable distribution for %r" % spec | 
					
					
						
						| 
							 | 
						                if self.always_copy: | 
					
					
						
						| 
							 | 
						                    msg += " (--always-copy skips system and development eggs)" | 
					
					
						
						| 
							 | 
						                raise DistutilsError(msg) | 
					
					
						
						| 
							 | 
						            elif dist.precedence == DEVELOP_DIST: | 
					
					
						
						| 
							 | 
						                 | 
					
					
						
						| 
							 | 
						                self.process_distribution(spec, dist, deps, "Using") | 
					
					
						
						| 
							 | 
						                return dist | 
					
					
						
						| 
							 | 
						            else: | 
					
					
						
						| 
							 | 
						                return self.install_item(spec, dist.location, tmpdir, deps) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						    def install_item(self, spec, download, tmpdir, deps, install_needed=False): | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						         | 
					
					
						
						| 
							 | 
						        install_needed = install_needed or self.always_copy | 
					
					
						
						| 
							 | 
						        install_needed = install_needed or os.path.dirname(download) == tmpdir | 
					
					
						
						| 
							 | 
						        install_needed = install_needed or not download.endswith('.egg') | 
					
					
						
						| 
							 | 
						        install_needed = install_needed or ( | 
					
					
						
						| 
							 | 
						            self.always_copy_from is not None and | 
					
					
						
						| 
							 | 
						            os.path.dirname(normalize_path(download)) == | 
					
					
						
						| 
							 | 
						            normalize_path(self.always_copy_from) | 
					
					
						
						| 
							 | 
						        ) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						        if spec and not install_needed: | 
					
					
						
						| 
							 | 
						             | 
					
					
						
						| 
							 | 
						             | 
					
					
						
						| 
							 | 
						            for dist in self.local_index[spec.project_name]: | 
					
					
						
						| 
							 | 
						                if dist.location == download: | 
					
					
						
						| 
							 | 
						                    break | 
					
					
						
						| 
							 | 
						            else: | 
					
					
						
						| 
							 | 
						                install_needed = True   | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						        log.info("Processing %s", os.path.basename(download)) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						        if install_needed: | 
					
					
						
						| 
							 | 
						            dists = self.install_eggs(spec, download, tmpdir) | 
					
					
						
						| 
							 | 
						            for dist in dists: | 
					
					
						
						| 
							 | 
						                self.process_distribution(spec, dist, deps) | 
					
					
						
						| 
							 | 
						        else: | 
					
					
						
						| 
							 | 
						            dists = [self.egg_distribution(download)] | 
					
					
						
						| 
							 | 
						            self.process_distribution(spec, dists[0], deps, "Using") | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						        if spec is not None: | 
					
					
						
						| 
							 | 
						            for dist in dists: | 
					
					
						
						| 
							 | 
						                if dist in spec: | 
					
					
						
						| 
							 | 
						                    return dist | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						    def select_scheme(self, name): | 
					
					
						
						| 
							 | 
						        try: | 
					
					
						
						| 
							 | 
						            install._select_scheme(self, name) | 
					
					
						
						| 
							 | 
						        except AttributeError: | 
					
					
						
						| 
							 | 
						             | 
					
					
						
						| 
							 | 
						            install.install.select_scheme(self, name.replace('posix', 'unix')) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						     | 
					
					
						
						| 
							 | 
						    def process_distribution(   | 
					
					
						
						| 
							 | 
						            self, requirement, dist, deps=True, *info, | 
					
					
						
						| 
							 | 
						    ): | 
					
					
						
						| 
							 | 
						        self.update_pth(dist) | 
					
					
						
						| 
							 | 
						        self.package_index.add(dist) | 
					
					
						
						| 
							 | 
						        if dist in self.local_index[dist.key]: | 
					
					
						
						| 
							 | 
						            self.local_index.remove(dist) | 
					
					
						
						| 
							 | 
						        self.local_index.add(dist) | 
					
					
						
						| 
							 | 
						        self.install_egg_scripts(dist) | 
					
					
						
						| 
							 | 
						        self.installed_projects[dist.key] = dist | 
					
					
						
						| 
							 | 
						        log.info(self.installation_report(requirement, dist, *info)) | 
					
					
						
						| 
							 | 
						        if (dist.has_metadata('dependency_links.txt') and | 
					
					
						
						| 
							 | 
						                not self.no_find_links): | 
					
					
						
						| 
							 | 
						            self.package_index.add_find_links( | 
					
					
						
						| 
							 | 
						                dist.get_metadata_lines('dependency_links.txt') | 
					
					
						
						| 
							 | 
						            ) | 
					
					
						
						| 
							 | 
						        if not deps and not self.always_copy: | 
					
					
						
						| 
							 | 
						            return | 
					
					
						
						| 
							 | 
						        elif requirement is not None and dist.key != requirement.key: | 
					
					
						
						| 
							 | 
						            log.warn("Skipping dependencies for %s", dist) | 
					
					
						
						| 
							 | 
						            return   | 
					
					
						
						| 
							 | 
						        elif requirement is None or dist not in requirement: | 
					
					
						
						| 
							 | 
						             | 
					
					
						
						| 
							 | 
						            distreq = dist.as_requirement() | 
					
					
						
						| 
							 | 
						            requirement = Requirement(str(distreq)) | 
					
					
						
						| 
							 | 
						        log.info("Processing dependencies for %s", requirement) | 
					
					
						
						| 
							 | 
						        try: | 
					
					
						
						| 
							 | 
						            distros = WorkingSet([]).resolve( | 
					
					
						
						| 
							 | 
						                [requirement], self.local_index, self.easy_install | 
					
					
						
						| 
							 | 
						            ) | 
					
					
						
						| 
							 | 
						        except DistributionNotFound as e: | 
					
					
						
						| 
							 | 
						            raise DistutilsError(str(e)) from e | 
					
					
						
						| 
							 | 
						        except VersionConflict as e: | 
					
					
						
						| 
							 | 
						            raise DistutilsError(e.report()) from e | 
					
					
						
						| 
							 | 
						        if self.always_copy or self.always_copy_from: | 
					
					
						
						| 
							 | 
						             | 
					
					
						
						| 
							 | 
						            for dist in distros: | 
					
					
						
						| 
							 | 
						                if dist.key not in self.installed_projects: | 
					
					
						
						| 
							 | 
						                    self.easy_install(dist.as_requirement()) | 
					
					
						
						| 
							 | 
						        log.info("Finished processing dependencies for %s", requirement) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						    def should_unzip(self, dist): | 
					
					
						
						| 
							 | 
						        if self.zip_ok is not None: | 
					
					
						
						| 
							 | 
						            return not self.zip_ok | 
					
					
						
						| 
							 | 
						        if dist.has_metadata('not-zip-safe'): | 
					
					
						
						| 
							 | 
						            return True | 
					
					
						
						| 
							 | 
						        if not dist.has_metadata('zip-safe'): | 
					
					
						
						| 
							 | 
						            return True | 
					
					
						
						| 
							 | 
						        return False | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						    def maybe_move(self, spec, dist_filename, setup_base): | 
					
					
						
						| 
							 | 
						        dst = os.path.join(self.build_directory, spec.key) | 
					
					
						
						| 
							 | 
						        if os.path.exists(dst): | 
					
					
						
						| 
							 | 
						            msg = ( | 
					
					
						
						| 
							 | 
						                "%r already exists in %s; build directory %s will not be kept" | 
					
					
						
						| 
							 | 
						            ) | 
					
					
						
						| 
							 | 
						            log.warn(msg, spec.key, self.build_directory, setup_base) | 
					
					
						
						| 
							 | 
						            return setup_base | 
					
					
						
						| 
							 | 
						        if os.path.isdir(dist_filename): | 
					
					
						
						| 
							 | 
						            setup_base = dist_filename | 
					
					
						
						| 
							 | 
						        else: | 
					
					
						
						| 
							 | 
						            if os.path.dirname(dist_filename) == setup_base: | 
					
					
						
						| 
							 | 
						                os.unlink(dist_filename)   | 
					
					
						
						| 
							 | 
						            contents = os.listdir(setup_base) | 
					
					
						
						| 
							 | 
						            if len(contents) == 1: | 
					
					
						
						| 
							 | 
						                dist_filename = os.path.join(setup_base, contents[0]) | 
					
					
						
						| 
							 | 
						                if os.path.isdir(dist_filename): | 
					
					
						
						| 
							 | 
						                     | 
					
					
						
						| 
							 | 
						                    setup_base = dist_filename | 
					
					
						
						| 
							 | 
						        ensure_directory(dst) | 
					
					
						
						| 
							 | 
						        shutil.move(setup_base, dst) | 
					
					
						
						| 
							 | 
						        return dst | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						    def install_wrapper_scripts(self, dist): | 
					
					
						
						| 
							 | 
						        if self.exclude_scripts: | 
					
					
						
						| 
							 | 
						            return | 
					
					
						
						| 
							 | 
						        for args in ScriptWriter.best().get_args(dist): | 
					
					
						
						| 
							 | 
						            self.write_script(*args) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						    def install_script(self, dist, script_name, script_text, dev_path=None): | 
					
					
						
						| 
							 | 
						        """Generate a legacy script wrapper and install it""" | 
					
					
						
						| 
							 | 
						        spec = str(dist.as_requirement()) | 
					
					
						
						| 
							 | 
						        is_script = is_python_script(script_text, script_name) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						        if is_script: | 
					
					
						
						| 
							 | 
						            body = self._load_template(dev_path) % locals() | 
					
					
						
						| 
							 | 
						            script_text = ScriptWriter.get_header(script_text) + body | 
					
					
						
						| 
							 | 
						        self.write_script(script_name, _to_bytes(script_text), 'b') | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						    @staticmethod | 
					
					
						
						| 
							 | 
						    def _load_template(dev_path): | 
					
					
						
						| 
							 | 
						        """ | 
					
					
						
						| 
							 | 
						        There are a couple of template scripts in the package. This | 
					
					
						
						| 
							 | 
						        function loads one of them and prepares it for use. | 
					
					
						
						| 
							 | 
						        """ | 
					
					
						
						| 
							 | 
						         | 
					
					
						
						| 
							 | 
						         | 
					
					
						
						| 
							 | 
						        name = 'script.tmpl' | 
					
					
						
						| 
							 | 
						        if dev_path: | 
					
					
						
						| 
							 | 
						            name = name.replace('.tmpl', ' (dev).tmpl') | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						        raw_bytes = resource_string('setuptools', name) | 
					
					
						
						| 
							 | 
						        return raw_bytes.decode('utf-8') | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						    def write_script(self, script_name, contents, mode="t", blockers=()): | 
					
					
						
						| 
							 | 
						        """Write an executable file to the scripts directory""" | 
					
					
						
						| 
							 | 
						        self.delete_blockers(   | 
					
					
						
						| 
							 | 
						            [os.path.join(self.script_dir, x) for x in blockers] | 
					
					
						
						| 
							 | 
						        ) | 
					
					
						
						| 
							 | 
						        log.info("Installing %s script to %s", script_name, self.script_dir) | 
					
					
						
						| 
							 | 
						        target = os.path.join(self.script_dir, script_name) | 
					
					
						
						| 
							 | 
						        self.add_output(target) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						        if self.dry_run: | 
					
					
						
						| 
							 | 
						            return | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						        mask = current_umask() | 
					
					
						
						| 
							 | 
						        ensure_directory(target) | 
					
					
						
						| 
							 | 
						        if os.path.exists(target): | 
					
					
						
						| 
							 | 
						            os.unlink(target) | 
					
					
						
						| 
							 | 
						        with open(target, "w" + mode) as f: | 
					
					
						
						| 
							 | 
						            f.write(contents) | 
					
					
						
						| 
							 | 
						        chmod(target, 0o777 - mask) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						    def install_eggs(self, spec, dist_filename, tmpdir): | 
					
					
						
						| 
							 | 
						         | 
					
					
						
						| 
							 | 
						        installer_map = { | 
					
					
						
						| 
							 | 
						            '.egg': self.install_egg, | 
					
					
						
						| 
							 | 
						            '.exe': self.install_exe, | 
					
					
						
						| 
							 | 
						            '.whl': self.install_wheel, | 
					
					
						
						| 
							 | 
						        } | 
					
					
						
						| 
							 | 
						        try: | 
					
					
						
						| 
							 | 
						            install_dist = installer_map[ | 
					
					
						
						| 
							 | 
						                dist_filename.lower()[-4:] | 
					
					
						
						| 
							 | 
						            ] | 
					
					
						
						| 
							 | 
						        except KeyError: | 
					
					
						
						| 
							 | 
						            pass | 
					
					
						
						| 
							 | 
						        else: | 
					
					
						
						| 
							 | 
						            return [install_dist(dist_filename, tmpdir)] | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						         | 
					
					
						
						| 
							 | 
						        setup_base = tmpdir | 
					
					
						
						| 
							 | 
						        if os.path.isfile(dist_filename) and not dist_filename.endswith('.py'): | 
					
					
						
						| 
							 | 
						            unpack_archive(dist_filename, tmpdir, self.unpack_progress) | 
					
					
						
						| 
							 | 
						        elif os.path.isdir(dist_filename): | 
					
					
						
						| 
							 | 
						            setup_base = os.path.abspath(dist_filename) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						        if (setup_base.startswith(tmpdir)   | 
					
					
						
						| 
							 | 
						                and self.build_directory and spec is not None): | 
					
					
						
						| 
							 | 
						            setup_base = self.maybe_move(spec, dist_filename, setup_base) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						         | 
					
					
						
						| 
							 | 
						        setup_script = os.path.join(setup_base, 'setup.py') | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						        if not os.path.exists(setup_script): | 
					
					
						
						| 
							 | 
						            setups = glob(os.path.join(setup_base, '*', 'setup.py')) | 
					
					
						
						| 
							 | 
						            if not setups: | 
					
					
						
						| 
							 | 
						                raise DistutilsError( | 
					
					
						
						| 
							 | 
						                    "Couldn't find a setup script in %s" % | 
					
					
						
						| 
							 | 
						                    os.path.abspath(dist_filename) | 
					
					
						
						| 
							 | 
						                ) | 
					
					
						
						| 
							 | 
						            if len(setups) > 1: | 
					
					
						
						| 
							 | 
						                raise DistutilsError( | 
					
					
						
						| 
							 | 
						                    "Multiple setup scripts in %s" % | 
					
					
						
						| 
							 | 
						                    os.path.abspath(dist_filename) | 
					
					
						
						| 
							 | 
						                ) | 
					
					
						
						| 
							 | 
						            setup_script = setups[0] | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						         | 
					
					
						
						| 
							 | 
						        if self.editable: | 
					
					
						
						| 
							 | 
						            log.info(self.report_editable(spec, setup_script)) | 
					
					
						
						| 
							 | 
						            return [] | 
					
					
						
						| 
							 | 
						        else: | 
					
					
						
						| 
							 | 
						            return self.build_and_install(setup_script, setup_base) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						    def egg_distribution(self, egg_path): | 
					
					
						
						| 
							 | 
						        if os.path.isdir(egg_path): | 
					
					
						
						| 
							 | 
						            metadata = PathMetadata(egg_path, os.path.join(egg_path, | 
					
					
						
						| 
							 | 
						                                                           'EGG-INFO')) | 
					
					
						
						| 
							 | 
						        else: | 
					
					
						
						| 
							 | 
						            metadata = EggMetadata(zipimport.zipimporter(egg_path)) | 
					
					
						
						| 
							 | 
						        return Distribution.from_filename(egg_path, metadata=metadata) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						     | 
					
					
						
						| 
							 | 
						    def install_egg(self, egg_path, tmpdir):   | 
					
					
						
						| 
							 | 
						        destination = os.path.join( | 
					
					
						
						| 
							 | 
						            self.install_dir, | 
					
					
						
						| 
							 | 
						            os.path.basename(egg_path), | 
					
					
						
						| 
							 | 
						        ) | 
					
					
						
						| 
							 | 
						        destination = os.path.abspath(destination) | 
					
					
						
						| 
							 | 
						        if not self.dry_run: | 
					
					
						
						| 
							 | 
						            ensure_directory(destination) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						        dist = self.egg_distribution(egg_path) | 
					
					
						
						| 
							 | 
						        if not ( | 
					
					
						
						| 
							 | 
						            os.path.exists(destination) and os.path.samefile(egg_path, destination) | 
					
					
						
						| 
							 | 
						        ): | 
					
					
						
						| 
							 | 
						            if os.path.isdir(destination) and not os.path.islink(destination): | 
					
					
						
						| 
							 | 
						                dir_util.remove_tree(destination, dry_run=self.dry_run) | 
					
					
						
						| 
							 | 
						            elif os.path.exists(destination): | 
					
					
						
						| 
							 | 
						                self.execute( | 
					
					
						
						| 
							 | 
						                    os.unlink, | 
					
					
						
						| 
							 | 
						                    (destination,), | 
					
					
						
						| 
							 | 
						                    "Removing " + destination, | 
					
					
						
						| 
							 | 
						                ) | 
					
					
						
						| 
							 | 
						            try: | 
					
					
						
						| 
							 | 
						                new_dist_is_zipped = False | 
					
					
						
						| 
							 | 
						                if os.path.isdir(egg_path): | 
					
					
						
						| 
							 | 
						                    if egg_path.startswith(tmpdir): | 
					
					
						
						| 
							 | 
						                        f, m = shutil.move, "Moving" | 
					
					
						
						| 
							 | 
						                    else: | 
					
					
						
						| 
							 | 
						                        f, m = shutil.copytree, "Copying" | 
					
					
						
						| 
							 | 
						                elif self.should_unzip(dist): | 
					
					
						
						| 
							 | 
						                    self.mkpath(destination) | 
					
					
						
						| 
							 | 
						                    f, m = self.unpack_and_compile, "Extracting" | 
					
					
						
						| 
							 | 
						                else: | 
					
					
						
						| 
							 | 
						                    new_dist_is_zipped = True | 
					
					
						
						| 
							 | 
						                    if egg_path.startswith(tmpdir): | 
					
					
						
						| 
							 | 
						                        f, m = shutil.move, "Moving" | 
					
					
						
						| 
							 | 
						                    else: | 
					
					
						
						| 
							 | 
						                        f, m = shutil.copy2, "Copying" | 
					
					
						
						| 
							 | 
						                self.execute( | 
					
					
						
						| 
							 | 
						                    f, | 
					
					
						
						| 
							 | 
						                    (egg_path, destination), | 
					
					
						
						| 
							 | 
						                    (m + " %s to %s") % ( | 
					
					
						
						| 
							 | 
						                        os.path.basename(egg_path), | 
					
					
						
						| 
							 | 
						                        os.path.dirname(destination) | 
					
					
						
						| 
							 | 
						                    ), | 
					
					
						
						| 
							 | 
						                ) | 
					
					
						
						| 
							 | 
						                update_dist_caches( | 
					
					
						
						| 
							 | 
						                    destination, | 
					
					
						
						| 
							 | 
						                    fix_zipimporter_caches=new_dist_is_zipped, | 
					
					
						
						| 
							 | 
						                ) | 
					
					
						
						| 
							 | 
						            except Exception: | 
					
					
						
						| 
							 | 
						                update_dist_caches(destination, fix_zipimporter_caches=False) | 
					
					
						
						| 
							 | 
						                raise | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						        self.add_output(destination) | 
					
					
						
						| 
							 | 
						        return self.egg_distribution(destination) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						    def install_exe(self, dist_filename, tmpdir): | 
					
					
						
						| 
							 | 
						         | 
					
					
						
						| 
							 | 
						        cfg = extract_wininst_cfg(dist_filename) | 
					
					
						
						| 
							 | 
						        if cfg is None: | 
					
					
						
						| 
							 | 
						            raise DistutilsError( | 
					
					
						
						| 
							 | 
						                "%s is not a valid distutils Windows .exe" % dist_filename | 
					
					
						
						| 
							 | 
						            ) | 
					
					
						
						| 
							 | 
						         | 
					
					
						
						| 
							 | 
						        dist = Distribution( | 
					
					
						
						| 
							 | 
						            None, | 
					
					
						
						| 
							 | 
						            project_name=cfg.get('metadata', 'name'), | 
					
					
						
						| 
							 | 
						            version=cfg.get('metadata', 'version'), platform=get_platform(), | 
					
					
						
						| 
							 | 
						        ) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						         | 
					
					
						
						| 
							 | 
						        egg_path = os.path.join(tmpdir, dist.egg_name() + '.egg') | 
					
					
						
						| 
							 | 
						        dist.location = egg_path | 
					
					
						
						| 
							 | 
						        egg_tmp = egg_path + '.tmp' | 
					
					
						
						| 
							 | 
						        _egg_info = os.path.join(egg_tmp, 'EGG-INFO') | 
					
					
						
						| 
							 | 
						        pkg_inf = os.path.join(_egg_info, 'PKG-INFO') | 
					
					
						
						| 
							 | 
						        ensure_directory(pkg_inf)   | 
					
					
						
						| 
							 | 
						        dist._provider = PathMetadata(egg_tmp, _egg_info)   | 
					
					
						
						| 
							 | 
						        self.exe_to_egg(dist_filename, egg_tmp) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						         | 
					
					
						
						| 
							 | 
						        if not os.path.exists(pkg_inf): | 
					
					
						
						| 
							 | 
						            f = open(pkg_inf, 'w') | 
					
					
						
						| 
							 | 
						            f.write('Metadata-Version: 1.0\n') | 
					
					
						
						| 
							 | 
						            for k, v in cfg.items('metadata'): | 
					
					
						
						| 
							 | 
						                if k != 'target_version': | 
					
					
						
						| 
							 | 
						                    f.write('%s: %s\n' % (k.replace('_', '-').title(), v)) | 
					
					
						
						| 
							 | 
						            f.close() | 
					
					
						
						| 
							 | 
						        script_dir = os.path.join(_egg_info, 'scripts') | 
					
					
						
						| 
							 | 
						         | 
					
					
						
						| 
							 | 
						        self.delete_blockers([ | 
					
					
						
						| 
							 | 
						            os.path.join(script_dir, args[0]) | 
					
					
						
						| 
							 | 
						            for args in ScriptWriter.get_args(dist) | 
					
					
						
						| 
							 | 
						        ]) | 
					
					
						
						| 
							 | 
						         | 
					
					
						
						| 
							 | 
						        bdist_egg.make_zipfile( | 
					
					
						
						| 
							 | 
						            egg_path, egg_tmp, verbose=self.verbose, dry_run=self.dry_run, | 
					
					
						
						| 
							 | 
						        ) | 
					
					
						
						| 
							 | 
						         | 
					
					
						
						| 
							 | 
						        return self.install_egg(egg_path, tmpdir) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						     | 
					
					
						
						| 
							 | 
						    def exe_to_egg(self, dist_filename, egg_tmp):   | 
					
					
						
						| 
							 | 
						        """Extract a bdist_wininst to the directories an egg would use""" | 
					
					
						
						| 
							 | 
						         | 
					
					
						
						| 
							 | 
						        prefixes = get_exe_prefixes(dist_filename) | 
					
					
						
						| 
							 | 
						        to_compile = [] | 
					
					
						
						| 
							 | 
						        native_libs = [] | 
					
					
						
						| 
							 | 
						        top_level = {} | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						        def process(src, dst): | 
					
					
						
						| 
							 | 
						            s = src.lower() | 
					
					
						
						| 
							 | 
						            for old, new in prefixes: | 
					
					
						
						| 
							 | 
						                if s.startswith(old): | 
					
					
						
						| 
							 | 
						                    src = new + src[len(old):] | 
					
					
						
						| 
							 | 
						                    parts = src.split('/') | 
					
					
						
						| 
							 | 
						                    dst = os.path.join(egg_tmp, *parts) | 
					
					
						
						| 
							 | 
						                    dl = dst.lower() | 
					
					
						
						| 
							 | 
						                    if dl.endswith('.pyd') or dl.endswith('.dll'): | 
					
					
						
						| 
							 | 
						                        parts[-1] = bdist_egg.strip_module(parts[-1]) | 
					
					
						
						| 
							 | 
						                        top_level[os.path.splitext(parts[0])[0]] = 1 | 
					
					
						
						| 
							 | 
						                        native_libs.append(src) | 
					
					
						
						| 
							 | 
						                    elif dl.endswith('.py') and old != 'SCRIPTS/': | 
					
					
						
						| 
							 | 
						                        top_level[os.path.splitext(parts[0])[0]] = 1 | 
					
					
						
						| 
							 | 
						                        to_compile.append(dst) | 
					
					
						
						| 
							 | 
						                    return dst | 
					
					
						
						| 
							 | 
						            if not src.endswith('.pth'): | 
					
					
						
						| 
							 | 
						                log.warn("WARNING: can't process %s", src) | 
					
					
						
						| 
							 | 
						            return None | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						         | 
					
					
						
						| 
							 | 
						        unpack_archive(dist_filename, egg_tmp, process) | 
					
					
						
						| 
							 | 
						        stubs = [] | 
					
					
						
						| 
							 | 
						        for res in native_libs: | 
					
					
						
						| 
							 | 
						            if res.lower().endswith('.pyd'):   | 
					
					
						
						| 
							 | 
						                parts = res.split('/') | 
					
					
						
						| 
							 | 
						                resource = parts[-1] | 
					
					
						
						| 
							 | 
						                parts[-1] = bdist_egg.strip_module(parts[-1]) + '.py' | 
					
					
						
						| 
							 | 
						                pyfile = os.path.join(egg_tmp, *parts) | 
					
					
						
						| 
							 | 
						                to_compile.append(pyfile) | 
					
					
						
						| 
							 | 
						                stubs.append(pyfile) | 
					
					
						
						| 
							 | 
						                bdist_egg.write_stub(resource, pyfile) | 
					
					
						
						| 
							 | 
						        self.byte_compile(to_compile)   | 
					
					
						
						| 
							 | 
						        bdist_egg.write_safety_flag( | 
					
					
						
						| 
							 | 
						            os.path.join(egg_tmp, 'EGG-INFO'), | 
					
					
						
						| 
							 | 
						            bdist_egg.analyze_egg(egg_tmp, stubs))   | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						        for name in 'top_level', 'native_libs': | 
					
					
						
						| 
							 | 
						            if locals()[name]: | 
					
					
						
						| 
							 | 
						                txt = os.path.join(egg_tmp, 'EGG-INFO', name + '.txt') | 
					
					
						
						| 
							 | 
						                if not os.path.exists(txt): | 
					
					
						
						| 
							 | 
						                    f = open(txt, 'w') | 
					
					
						
						| 
							 | 
						                    f.write('\n'.join(locals()[name]) + '\n') | 
					
					
						
						| 
							 | 
						                    f.close() | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						    def install_wheel(self, wheel_path, tmpdir): | 
					
					
						
						| 
							 | 
						        wheel = Wheel(wheel_path) | 
					
					
						
						| 
							 | 
						        assert wheel.is_compatible() | 
					
					
						
						| 
							 | 
						        destination = os.path.join(self.install_dir, wheel.egg_name()) | 
					
					
						
						| 
							 | 
						        destination = os.path.abspath(destination) | 
					
					
						
						| 
							 | 
						        if not self.dry_run: | 
					
					
						
						| 
							 | 
						            ensure_directory(destination) | 
					
					
						
						| 
							 | 
						        if os.path.isdir(destination) and not os.path.islink(destination): | 
					
					
						
						| 
							 | 
						            dir_util.remove_tree(destination, dry_run=self.dry_run) | 
					
					
						
						| 
							 | 
						        elif os.path.exists(destination): | 
					
					
						
						| 
							 | 
						            self.execute( | 
					
					
						
						| 
							 | 
						                os.unlink, | 
					
					
						
						| 
							 | 
						                (destination,), | 
					
					
						
						| 
							 | 
						                "Removing " + destination, | 
					
					
						
						| 
							 | 
						            ) | 
					
					
						
						| 
							 | 
						        try: | 
					
					
						
						| 
							 | 
						            self.execute( | 
					
					
						
						| 
							 | 
						                wheel.install_as_egg, | 
					
					
						
						| 
							 | 
						                (destination,), | 
					
					
						
						| 
							 | 
						                ("Installing %s to %s") % ( | 
					
					
						
						| 
							 | 
						                    os.path.basename(wheel_path), | 
					
					
						
						| 
							 | 
						                    os.path.dirname(destination) | 
					
					
						
						| 
							 | 
						                ), | 
					
					
						
						| 
							 | 
						            ) | 
					
					
						
						| 
							 | 
						        finally: | 
					
					
						
						| 
							 | 
						            update_dist_caches(destination, fix_zipimporter_caches=False) | 
					
					
						
						| 
							 | 
						        self.add_output(destination) | 
					
					
						
						| 
							 | 
						        return self.egg_distribution(destination) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						    __mv_warning = textwrap.dedent(""" | 
					
					
						
						| 
							 | 
						        Because this distribution was installed --multi-version, before you can | 
					
					
						
						| 
							 | 
						        import modules from this package in an application, you will need to | 
					
					
						
						| 
							 | 
						        'import pkg_resources' and then use a 'require()' call similar to one of | 
					
					
						
						| 
							 | 
						        these examples, in order to select the desired version: | 
					
					
						
						| 
							 | 
						 | 
					
					
						
						| 
							 | 
						            pkg_resources.require("%(name)s")  # latest installed version | 
					
					
						
						| 
							 | 
						            pkg_resources.require("%(name)s==%(version)s")  # this exact version | 
					
					
						
						| 
							 | 
						            pkg_resources.require("%(name)s>=%(version)s")  # this version or higher | 
					
					
						
						| 
							 | 
						        """).lstrip()   | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						    __id_warning = textwrap.dedent(""" | 
					
					
						
						| 
							 | 
						        Note also that the installation directory must be on sys.path at runtime for | 
					
					
						
						| 
							 | 
						        this to work.  (e.g. by being the application's script directory, by being on | 
					
					
						
						| 
							 | 
						        PYTHONPATH, or by being added to sys.path by your code.) | 
					
					
						
						| 
							 | 
						        """)   | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						    def installation_report(self, req, dist, what="Installed"): | 
					
					
						
						| 
							 | 
						        """Helpful installation message for display to package users""" | 
					
					
						
						| 
							 | 
						        msg = "\n%(what)s %(eggloc)s%(extras)s" | 
					
					
						
						| 
							 | 
						        if self.multi_version and not self.no_report: | 
					
					
						
						| 
							 | 
						            msg += '\n' + self.__mv_warning | 
					
					
						
						| 
							 | 
						            if self.install_dir not in map(normalize_path, sys.path): | 
					
					
						
						| 
							 | 
						                msg += '\n' + self.__id_warning | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						        eggloc = dist.location | 
					
					
						
						| 
							 | 
						        name = dist.project_name | 
					
					
						
						| 
							 | 
						        version = dist.version | 
					
					
						
						| 
							 | 
						        extras = ''   | 
					
					
						
						| 
							 | 
						        return msg % locals() | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						    __editable_msg = textwrap.dedent(""" | 
					
					
						
						| 
							 | 
						        Extracted editable version of %(spec)s to %(dirname)s | 
					
					
						
						| 
							 | 
						 | 
					
					
						
						| 
							 | 
						        If it uses setuptools in its setup script, you can activate it in | 
					
					
						
						| 
							 | 
						        "development" mode by going to that directory and running:: | 
					
					
						
						| 
							 | 
						 | 
					
					
						
						| 
							 | 
						            %(python)s setup.py develop | 
					
					
						
						| 
							 | 
						 | 
					
					
						
						| 
							 | 
						        See the setuptools documentation for the "develop" command for more info. | 
					
					
						
						| 
							 | 
						        """).lstrip()   | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						    def report_editable(self, spec, setup_script): | 
					
					
						
						| 
							 | 
						        dirname = os.path.dirname(setup_script) | 
					
					
						
						| 
							 | 
						        python = sys.executable | 
					
					
						
						| 
							 | 
						        return '\n' + self.__editable_msg % locals() | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						    def run_setup(self, setup_script, setup_base, args): | 
					
					
						
						| 
							 | 
						        sys.modules.setdefault('distutils.command.bdist_egg', bdist_egg) | 
					
					
						
						| 
							 | 
						        sys.modules.setdefault('distutils.command.egg_info', egg_info) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						        args = list(args) | 
					
					
						
						| 
							 | 
						        if self.verbose > 2: | 
					
					
						
						| 
							 | 
						            v = 'v' * (self.verbose - 1) | 
					
					
						
						| 
							 | 
						            args.insert(0, '-' + v) | 
					
					
						
						| 
							 | 
						        elif self.verbose < 2: | 
					
					
						
						| 
							 | 
						            args.insert(0, '-q') | 
					
					
						
						| 
							 | 
						        if self.dry_run: | 
					
					
						
						| 
							 | 
						            args.insert(0, '-n') | 
					
					
						
						| 
							 | 
						        log.info( | 
					
					
						
						| 
							 | 
						            "Running %s %s", setup_script[len(setup_base) + 1:], ' '.join(args) | 
					
					
						
						| 
							 | 
						        ) | 
					
					
						
						| 
							 | 
						        try: | 
					
					
						
						| 
							 | 
						            run_setup(setup_script, args) | 
					
					
						
						| 
							 | 
						        except SystemExit as v: | 
					
					
						
						| 
							 | 
						            raise DistutilsError( | 
					
					
						
						| 
							 | 
						                "Setup script exited with %s" % (v.args[0],) | 
					
					
						
						| 
							 | 
						            ) from v | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						    def build_and_install(self, setup_script, setup_base): | 
					
					
						
						| 
							 | 
						        args = ['bdist_egg', '--dist-dir'] | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						        dist_dir = tempfile.mkdtemp( | 
					
					
						
						| 
							 | 
						            prefix='egg-dist-tmp-', dir=os.path.dirname(setup_script) | 
					
					
						
						| 
							 | 
						        ) | 
					
					
						
						| 
							 | 
						        try: | 
					
					
						
						| 
							 | 
						            self._set_fetcher_options(os.path.dirname(setup_script)) | 
					
					
						
						| 
							 | 
						            args.append(dist_dir) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						            self.run_setup(setup_script, setup_base, args) | 
					
					
						
						| 
							 | 
						            all_eggs = Environment([dist_dir]) | 
					
					
						
						| 
							 | 
						            eggs = [] | 
					
					
						
						| 
							 | 
						            for key in all_eggs: | 
					
					
						
						| 
							 | 
						                for dist in all_eggs[key]: | 
					
					
						
						| 
							 | 
						                    eggs.append(self.install_egg(dist.location, setup_base)) | 
					
					
						
						| 
							 | 
						            if not eggs and not self.dry_run: | 
					
					
						
						| 
							 | 
						                log.warn("No eggs found in %s (setup script problem?)", | 
					
					
						
						| 
							 | 
						                         dist_dir) | 
					
					
						
						| 
							 | 
						            return eggs | 
					
					
						
						| 
							 | 
						        finally: | 
					
					
						
						| 
							 | 
						            rmtree(dist_dir) | 
					
					
						
						| 
							 | 
						            log.set_verbosity(self.verbose)   | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						    def _set_fetcher_options(self, base): | 
					
					
						
						| 
							 | 
						        """ | 
					
					
						
						| 
							 | 
						        When easy_install is about to run bdist_egg on a source dist, that | 
					
					
						
						| 
							 | 
						        source dist might have 'setup_requires' directives, requiring | 
					
					
						
						| 
							 | 
						        additional fetching. Ensure the fetcher options given to easy_install | 
					
					
						
						| 
							 | 
						        are available to that command as well. | 
					
					
						
						| 
							 | 
						        """ | 
					
					
						
						| 
							 | 
						         | 
					
					
						
						| 
							 | 
						         | 
					
					
						
						| 
							 | 
						        ei_opts = self.distribution.get_option_dict('easy_install').copy() | 
					
					
						
						| 
							 | 
						        fetch_directives = ( | 
					
					
						
						| 
							 | 
						            'find_links', 'site_dirs', 'index_url', 'optimize', 'allow_hosts', | 
					
					
						
						| 
							 | 
						        ) | 
					
					
						
						| 
							 | 
						        fetch_options = {} | 
					
					
						
						| 
							 | 
						        for key, val in ei_opts.items(): | 
					
					
						
						| 
							 | 
						            if key not in fetch_directives: | 
					
					
						
						| 
							 | 
						                continue | 
					
					
						
						| 
							 | 
						            fetch_options[key] = val[1] | 
					
					
						
						| 
							 | 
						         | 
					
					
						
						| 
							 | 
						        settings = dict(easy_install=fetch_options) | 
					
					
						
						| 
							 | 
						        cfg_filename = os.path.join(base, 'setup.cfg') | 
					
					
						
						| 
							 | 
						        setopt.edit_config(cfg_filename, settings) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						    def update_pth(self, dist):   | 
					
					
						
						| 
							 | 
						        if self.pth_file is None: | 
					
					
						
						| 
							 | 
						            return | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						        for d in self.pth_file[dist.key]:   | 
					
					
						
						| 
							 | 
						            if not self.multi_version and d.location == dist.location: | 
					
					
						
						| 
							 | 
						                continue | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						            log.info("Removing %s from easy-install.pth file", d) | 
					
					
						
						| 
							 | 
						            self.pth_file.remove(d) | 
					
					
						
						| 
							 | 
						            if d.location in self.shadow_path: | 
					
					
						
						| 
							 | 
						                self.shadow_path.remove(d.location) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						        if not self.multi_version: | 
					
					
						
						| 
							 | 
						            if dist.location in self.pth_file.paths: | 
					
					
						
						| 
							 | 
						                log.info( | 
					
					
						
						| 
							 | 
						                    "%s is already the active version in easy-install.pth", | 
					
					
						
						| 
							 | 
						                    dist, | 
					
					
						
						| 
							 | 
						                ) | 
					
					
						
						| 
							 | 
						            else: | 
					
					
						
						| 
							 | 
						                log.info("Adding %s to easy-install.pth file", dist) | 
					
					
						
						| 
							 | 
						                self.pth_file.add(dist)   | 
					
					
						
						| 
							 | 
						                if dist.location not in self.shadow_path: | 
					
					
						
						| 
							 | 
						                    self.shadow_path.append(dist.location) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						        if self.dry_run: | 
					
					
						
						| 
							 | 
						            return | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						        self.pth_file.save() | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						        if dist.key != 'setuptools': | 
					
					
						
						| 
							 | 
						            return | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						         | 
					
					
						
						| 
							 | 
						         | 
					
					
						
						| 
							 | 
						        filename = os.path.join(self.install_dir, 'setuptools.pth') | 
					
					
						
						| 
							 | 
						        if os.path.islink(filename): | 
					
					
						
						| 
							 | 
						            os.unlink(filename) | 
					
					
						
						| 
							 | 
						        with open(filename, 'wt') as f: | 
					
					
						
						| 
							 | 
						            f.write(self.pth_file.make_relative(dist.location) + '\n') | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						    def unpack_progress(self, src, dst): | 
					
					
						
						| 
							 | 
						         | 
					
					
						
						| 
							 | 
						        log.debug("Unpacking %s to %s", src, dst) | 
					
					
						
						| 
							 | 
						        return dst   | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						    def unpack_and_compile(self, egg_path, destination): | 
					
					
						
						| 
							 | 
						        to_compile = [] | 
					
					
						
						| 
							 | 
						        to_chmod = [] | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						        def pf(src, dst): | 
					
					
						
						| 
							 | 
						            if dst.endswith('.py') and not src.startswith('EGG-INFO/'): | 
					
					
						
						| 
							 | 
						                to_compile.append(dst) | 
					
					
						
						| 
							 | 
						            elif dst.endswith('.dll') or dst.endswith('.so'): | 
					
					
						
						| 
							 | 
						                to_chmod.append(dst) | 
					
					
						
						| 
							 | 
						            self.unpack_progress(src, dst) | 
					
					
						
						| 
							 | 
						            return not self.dry_run and dst or None | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						        unpack_archive(egg_path, destination, pf) | 
					
					
						
						| 
							 | 
						        self.byte_compile(to_compile) | 
					
					
						
						| 
							 | 
						        if not self.dry_run: | 
					
					
						
						| 
							 | 
						            for f in to_chmod: | 
					
					
						
						| 
							 | 
						                mode = ((os.stat(f)[stat.ST_MODE]) | 0o555) & 0o7755 | 
					
					
						
						| 
							 | 
						                chmod(f, mode) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						    def byte_compile(self, to_compile): | 
					
					
						
						| 
							 | 
						        if sys.dont_write_bytecode: | 
					
					
						
						| 
							 | 
						            return | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						        from distutils.util import byte_compile | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						        try: | 
					
					
						
						| 
							 | 
						             | 
					
					
						
						| 
							 | 
						            log.set_verbosity(self.verbose - 1) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						            byte_compile(to_compile, optimize=0, force=1, dry_run=self.dry_run) | 
					
					
						
						| 
							 | 
						            if self.optimize: | 
					
					
						
						| 
							 | 
						                byte_compile( | 
					
					
						
						| 
							 | 
						                    to_compile, optimize=self.optimize, force=1, | 
					
					
						
						| 
							 | 
						                    dry_run=self.dry_run, | 
					
					
						
						| 
							 | 
						                ) | 
					
					
						
						| 
							 | 
						        finally: | 
					
					
						
						| 
							 | 
						            log.set_verbosity(self.verbose)   | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						    __no_default_msg = textwrap.dedent(""" | 
					
					
						
						| 
							 | 
						        bad install directory or PYTHONPATH | 
					
					
						
						| 
							 | 
						 | 
					
					
						
						| 
							 | 
						        You are attempting to install a package to a directory that is not | 
					
					
						
						| 
							 | 
						        on PYTHONPATH and which Python does not read ".pth" files from.  The | 
					
					
						
						| 
							 | 
						        installation directory you specified (via --install-dir, --prefix, or | 
					
					
						
						| 
							 | 
						        the distutils default setting) was: | 
					
					
						
						| 
							 | 
						 | 
					
					
						
						| 
							 | 
						            %s | 
					
					
						
						| 
							 | 
						 | 
					
					
						
						| 
							 | 
						        and your PYTHONPATH environment variable currently contains: | 
					
					
						
						| 
							 | 
						 | 
					
					
						
						| 
							 | 
						            %r | 
					
					
						
						| 
							 | 
						 | 
					
					
						
						| 
							 | 
						        Here are some of your options for correcting the problem: | 
					
					
						
						| 
							 | 
						 | 
					
					
						
						| 
							 | 
						        * You can choose a different installation directory, i.e., one that is | 
					
					
						
						| 
							 | 
						          on PYTHONPATH or supports .pth files | 
					
					
						
						| 
							 | 
						 | 
					
					
						
						| 
							 | 
						        * You can add the installation directory to the PYTHONPATH environment | 
					
					
						
						| 
							 | 
						          variable.  (It must then also be on PYTHONPATH whenever you run | 
					
					
						
						| 
							 | 
						          Python and want to use the package(s) you are installing.) | 
					
					
						
						| 
							 | 
						 | 
					
					
						
						| 
							 | 
						        * You can set up the installation directory to support ".pth" files by | 
					
					
						
						| 
							 | 
						          using one of the approaches described here: | 
					
					
						
						| 
							 | 
						 | 
					
					
						
						| 
							 | 
						          https://setuptools.pypa.io/en/latest/deprecated/easy_install.html#custom-installation-locations | 
					
					
						
						| 
							 | 
						 | 
					
					
						
						| 
							 | 
						 | 
					
					
						
						| 
							 | 
						        Please make the appropriate changes for your system and try again. | 
					
					
						
						| 
							 | 
						        """).strip() | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						    def create_home_path(self): | 
					
					
						
						| 
							 | 
						        """Create directories under ~.""" | 
					
					
						
						| 
							 | 
						        if not self.user: | 
					
					
						
						| 
							 | 
						            return | 
					
					
						
						| 
							 | 
						        home = convert_path(os.path.expanduser("~")) | 
					
					
						
						| 
							 | 
						        for path in only_strs(self.config_vars.values()): | 
					
					
						
						| 
							 | 
						            if path.startswith(home) and not os.path.isdir(path): | 
					
					
						
						| 
							 | 
						                self.debug_print("os.makedirs('%s', 0o700)" % path) | 
					
					
						
						| 
							 | 
						                os.makedirs(path, 0o700) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						    INSTALL_SCHEMES = dict( | 
					
					
						
						| 
							 | 
						        posix=dict( | 
					
					
						
						| 
							 | 
						            install_dir='$base/lib/python$py_version_short/site-packages', | 
					
					
						
						| 
							 | 
						            script_dir='$base/bin', | 
					
					
						
						| 
							 | 
						        ), | 
					
					
						
						| 
							 | 
						    ) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						    DEFAULT_SCHEME = dict( | 
					
					
						
						| 
							 | 
						        install_dir='$base/Lib/site-packages', | 
					
					
						
						| 
							 | 
						        script_dir='$base/Scripts', | 
					
					
						
						| 
							 | 
						    ) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						    def _expand(self, *attrs): | 
					
					
						
						| 
							 | 
						        config_vars = self.get_finalized_command('install').config_vars | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						        if self.prefix: | 
					
					
						
						| 
							 | 
						             | 
					
					
						
						| 
							 | 
						            config_vars = dict(config_vars) | 
					
					
						
						| 
							 | 
						            config_vars['base'] = self.prefix | 
					
					
						
						| 
							 | 
						            scheme = self.INSTALL_SCHEMES.get(os.name, self.DEFAULT_SCHEME) | 
					
					
						
						| 
							 | 
						            for attr, val in scheme.items(): | 
					
					
						
						| 
							 | 
						                if getattr(self, attr, None) is None: | 
					
					
						
						| 
							 | 
						                    setattr(self, attr, val) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						        from distutils.util import subst_vars | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						        for attr in attrs: | 
					
					
						
						| 
							 | 
						            val = getattr(self, attr) | 
					
					
						
						| 
							 | 
						            if val is not None: | 
					
					
						
						| 
							 | 
						                val = subst_vars(val, config_vars) | 
					
					
						
						| 
							 | 
						                if os.name == 'posix': | 
					
					
						
						| 
							 | 
						                    val = os.path.expanduser(val) | 
					
					
						
						| 
							 | 
						                setattr(self, attr, val) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						def _pythonpath(): | 
					
					
						
						| 
							 | 
						    items = os.environ.get('PYTHONPATH', '').split(os.pathsep) | 
					
					
						
						| 
							 | 
						    return filter(None, items) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						def get_site_dirs(): | 
					
					
						
						| 
							 | 
						    """ | 
					
					
						
						| 
							 | 
						    Return a list of 'site' dirs | 
					
					
						
						| 
							 | 
						    """ | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						    sitedirs = [] | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						     | 
					
					
						
						| 
							 | 
						    sitedirs.extend(_pythonpath()) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						    prefixes = [sys.prefix] | 
					
					
						
						| 
							 | 
						    if sys.exec_prefix != sys.prefix: | 
					
					
						
						| 
							 | 
						        prefixes.append(sys.exec_prefix) | 
					
					
						
						| 
							 | 
						    for prefix in prefixes: | 
					
					
						
						| 
							 | 
						        if not prefix: | 
					
					
						
						| 
							 | 
						            continue | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						        if sys.platform in ('os2emx', 'riscos'): | 
					
					
						
						| 
							 | 
						            sitedirs.append(os.path.join(prefix, "Lib", "site-packages")) | 
					
					
						
						| 
							 | 
						        elif os.sep == '/': | 
					
					
						
						| 
							 | 
						            sitedirs.extend([ | 
					
					
						
						| 
							 | 
						                os.path.join( | 
					
					
						
						| 
							 | 
						                    prefix, | 
					
					
						
						| 
							 | 
						                    "lib", | 
					
					
						
						| 
							 | 
						                    "python{}.{}".format(*sys.version_info), | 
					
					
						
						| 
							 | 
						                    "site-packages", | 
					
					
						
						| 
							 | 
						                ), | 
					
					
						
						| 
							 | 
						                os.path.join(prefix, "lib", "site-python"), | 
					
					
						
						| 
							 | 
						            ]) | 
					
					
						
						| 
							 | 
						        else: | 
					
					
						
						| 
							 | 
						            sitedirs.extend([ | 
					
					
						
						| 
							 | 
						                prefix, | 
					
					
						
						| 
							 | 
						                os.path.join(prefix, "lib", "site-packages"), | 
					
					
						
						| 
							 | 
						            ]) | 
					
					
						
						| 
							 | 
						        if sys.platform != 'darwin': | 
					
					
						
						| 
							 | 
						            continue | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						         | 
					
					
						
						| 
							 | 
						         | 
					
					
						
						| 
							 | 
						         | 
					
					
						
						| 
							 | 
						        if 'Python.framework' not in prefix: | 
					
					
						
						| 
							 | 
						            continue | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						        home = os.environ.get('HOME') | 
					
					
						
						| 
							 | 
						        if not home: | 
					
					
						
						| 
							 | 
						            continue | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						        home_sp = os.path.join( | 
					
					
						
						| 
							 | 
						            home, | 
					
					
						
						| 
							 | 
						            'Library', | 
					
					
						
						| 
							 | 
						            'Python', | 
					
					
						
						| 
							 | 
						            '{}.{}'.format(*sys.version_info), | 
					
					
						
						| 
							 | 
						            'site-packages', | 
					
					
						
						| 
							 | 
						        ) | 
					
					
						
						| 
							 | 
						        sitedirs.append(home_sp) | 
					
					
						
						| 
							 | 
						    lib_paths = get_path('purelib'), get_path('platlib') | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						    sitedirs.extend(s for s in lib_paths if s not in sitedirs) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						    if site.ENABLE_USER_SITE: | 
					
					
						
						| 
							 | 
						        sitedirs.append(site.USER_SITE) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						    with contextlib.suppress(AttributeError): | 
					
					
						
						| 
							 | 
						        sitedirs.extend(site.getsitepackages()) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						    sitedirs = list(map(normalize_path, sitedirs)) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						    return sitedirs | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						def expand_paths(inputs):   | 
					
					
						
						| 
							 | 
						    """Yield sys.path directories that might contain "old-style" packages""" | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						    seen = {} | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						    for dirname in inputs: | 
					
					
						
						| 
							 | 
						        dirname = normalize_path(dirname) | 
					
					
						
						| 
							 | 
						        if dirname in seen: | 
					
					
						
						| 
							 | 
						            continue | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						        seen[dirname] = 1 | 
					
					
						
						| 
							 | 
						        if not os.path.isdir(dirname): | 
					
					
						
						| 
							 | 
						            continue | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						        files = os.listdir(dirname) | 
					
					
						
						| 
							 | 
						        yield dirname, files | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						        for name in files: | 
					
					
						
						| 
							 | 
						            if not name.endswith('.pth'): | 
					
					
						
						| 
							 | 
						                 | 
					
					
						
						| 
							 | 
						                continue | 
					
					
						
						| 
							 | 
						            if name in ('easy-install.pth', 'setuptools.pth'): | 
					
					
						
						| 
							 | 
						                 | 
					
					
						
						| 
							 | 
						                continue | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						             | 
					
					
						
						| 
							 | 
						            f = open(os.path.join(dirname, name)) | 
					
					
						
						| 
							 | 
						            lines = list(yield_lines(f)) | 
					
					
						
						| 
							 | 
						            f.close() | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						             | 
					
					
						
						| 
							 | 
						            for line in lines: | 
					
					
						
						| 
							 | 
						                if line.startswith("import"): | 
					
					
						
						| 
							 | 
						                    continue | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						                line = normalize_path(line.rstrip()) | 
					
					
						
						| 
							 | 
						                if line in seen: | 
					
					
						
						| 
							 | 
						                    continue | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						                seen[line] = 1 | 
					
					
						
						| 
							 | 
						                if not os.path.isdir(line): | 
					
					
						
						| 
							 | 
						                    continue | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						                yield line, os.listdir(line) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						def extract_wininst_cfg(dist_filename): | 
					
					
						
						| 
							 | 
						    """Extract configuration data from a bdist_wininst .exe | 
					
					
						
						| 
							 | 
						 | 
					
					
						
						| 
							 | 
						    Returns a configparser.RawConfigParser, or None | 
					
					
						
						| 
							 | 
						    """ | 
					
					
						
						| 
							 | 
						    f = open(dist_filename, 'rb') | 
					
					
						
						| 
							 | 
						    try: | 
					
					
						
						| 
							 | 
						        endrec = zipfile._EndRecData(f) | 
					
					
						
						| 
							 | 
						        if endrec is None: | 
					
					
						
						| 
							 | 
						            return None | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						        prepended = (endrec[9] - endrec[5]) - endrec[6] | 
					
					
						
						| 
							 | 
						        if prepended < 12:   | 
					
					
						
						| 
							 | 
						            return None | 
					
					
						
						| 
							 | 
						        f.seek(prepended - 12) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						        tag, cfglen, bmlen = struct.unpack("<iii", f.read(12)) | 
					
					
						
						| 
							 | 
						        if tag not in (0x1234567A, 0x1234567B): | 
					
					
						
						| 
							 | 
						            return None   | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						        f.seek(prepended - (12 + cfglen)) | 
					
					
						
						| 
							 | 
						        init = {'version': '', 'target_version': ''} | 
					
					
						
						| 
							 | 
						        cfg = configparser.RawConfigParser(init) | 
					
					
						
						| 
							 | 
						        try: | 
					
					
						
						| 
							 | 
						            part = f.read(cfglen) | 
					
					
						
						| 
							 | 
						             | 
					
					
						
						| 
							 | 
						            config = part.split(b'\0', 1)[0] | 
					
					
						
						| 
							 | 
						             | 
					
					
						
						| 
							 | 
						             | 
					
					
						
						| 
							 | 
						            config = config.decode(sys.getfilesystemencoding()) | 
					
					
						
						| 
							 | 
						            cfg.read_file(io.StringIO(config)) | 
					
					
						
						| 
							 | 
						        except configparser.Error: | 
					
					
						
						| 
							 | 
						            return None | 
					
					
						
						| 
							 | 
						        if not cfg.has_section('metadata') or not cfg.has_section('Setup'): | 
					
					
						
						| 
							 | 
						            return None | 
					
					
						
						| 
							 | 
						        return cfg | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						    finally: | 
					
					
						
						| 
							 | 
						        f.close() | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						def get_exe_prefixes(exe_filename): | 
					
					
						
						| 
							 | 
						    """Get exe->egg path translations for a given .exe file""" | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						    prefixes = [ | 
					
					
						
						| 
							 | 
						        ('PURELIB/', ''), | 
					
					
						
						| 
							 | 
						        ('PLATLIB/pywin32_system32', ''), | 
					
					
						
						| 
							 | 
						        ('PLATLIB/', ''), | 
					
					
						
						| 
							 | 
						        ('SCRIPTS/', 'EGG-INFO/scripts/'), | 
					
					
						
						| 
							 | 
						        ('DATA/lib/site-packages', ''), | 
					
					
						
						| 
							 | 
						    ] | 
					
					
						
						| 
							 | 
						    z = zipfile.ZipFile(exe_filename) | 
					
					
						
						| 
							 | 
						    try: | 
					
					
						
						| 
							 | 
						        for info in z.infolist(): | 
					
					
						
						| 
							 | 
						            name = info.filename | 
					
					
						
						| 
							 | 
						            parts = name.split('/') | 
					
					
						
						| 
							 | 
						            if len(parts) == 3 and parts[2] == 'PKG-INFO': | 
					
					
						
						| 
							 | 
						                if parts[1].endswith('.egg-info'): | 
					
					
						
						| 
							 | 
						                    prefixes.insert(0, ('/'.join(parts[:2]), 'EGG-INFO/')) | 
					
					
						
						| 
							 | 
						                    break | 
					
					
						
						| 
							 | 
						            if len(parts) != 2 or not name.endswith('.pth'): | 
					
					
						
						| 
							 | 
						                continue | 
					
					
						
						| 
							 | 
						            if name.endswith('-nspkg.pth'): | 
					
					
						
						| 
							 | 
						                continue | 
					
					
						
						| 
							 | 
						            if parts[0].upper() in ('PURELIB', 'PLATLIB'): | 
					
					
						
						| 
							 | 
						                contents = z.read(name).decode() | 
					
					
						
						| 
							 | 
						                for pth in yield_lines(contents): | 
					
					
						
						| 
							 | 
						                    pth = pth.strip().replace('\\', '/') | 
					
					
						
						| 
							 | 
						                    if not pth.startswith('import'): | 
					
					
						
						| 
							 | 
						                        prefixes.append((('%s/%s/' % (parts[0], pth)), '')) | 
					
					
						
						| 
							 | 
						    finally: | 
					
					
						
						| 
							 | 
						        z.close() | 
					
					
						
						| 
							 | 
						    prefixes = [(x.lower(), y) for x, y in prefixes] | 
					
					
						
						| 
							 | 
						    prefixes.sort() | 
					
					
						
						| 
							 | 
						    prefixes.reverse() | 
					
					
						
						| 
							 | 
						    return prefixes | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						class PthDistributions(Environment): | 
					
					
						
						| 
							 | 
						    """A .pth file with Distribution paths in it""" | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						    dirty = False | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						    def __init__(self, filename, sitedirs=()): | 
					
					
						
						| 
							 | 
						        self.filename = filename | 
					
					
						
						| 
							 | 
						        self.sitedirs = list(map(normalize_path, sitedirs)) | 
					
					
						
						| 
							 | 
						        self.basedir = normalize_path(os.path.dirname(self.filename)) | 
					
					
						
						| 
							 | 
						        self._load() | 
					
					
						
						| 
							 | 
						        super().__init__([], None, None) | 
					
					
						
						| 
							 | 
						        for path in yield_lines(self.paths): | 
					
					
						
						| 
							 | 
						            list(map(self.add, find_distributions(path, True))) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						    def _load(self): | 
					
					
						
						| 
							 | 
						        self.paths = [] | 
					
					
						
						| 
							 | 
						        saw_import = False | 
					
					
						
						| 
							 | 
						        seen = dict.fromkeys(self.sitedirs) | 
					
					
						
						| 
							 | 
						        if os.path.isfile(self.filename): | 
					
					
						
						| 
							 | 
						            f = open(self.filename, 'rt') | 
					
					
						
						| 
							 | 
						            for line in f: | 
					
					
						
						| 
							 | 
						                if line.startswith('import'): | 
					
					
						
						| 
							 | 
						                    saw_import = True | 
					
					
						
						| 
							 | 
						                    continue | 
					
					
						
						| 
							 | 
						                path = line.rstrip() | 
					
					
						
						| 
							 | 
						                self.paths.append(path) | 
					
					
						
						| 
							 | 
						                if not path.strip() or path.strip().startswith('#'): | 
					
					
						
						| 
							 | 
						                    continue | 
					
					
						
						| 
							 | 
						                 | 
					
					
						
						| 
							 | 
						                 | 
					
					
						
						| 
							 | 
						                path = self.paths[-1] = normalize_path( | 
					
					
						
						| 
							 | 
						                    os.path.join(self.basedir, path) | 
					
					
						
						| 
							 | 
						                ) | 
					
					
						
						| 
							 | 
						                if not os.path.exists(path) or path in seen: | 
					
					
						
						| 
							 | 
						                    self.paths.pop()   | 
					
					
						
						| 
							 | 
						                    self.dirty = True   | 
					
					
						
						| 
							 | 
						                    continue | 
					
					
						
						| 
							 | 
						                seen[path] = 1 | 
					
					
						
						| 
							 | 
						            f.close() | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						        if self.paths and not saw_import: | 
					
					
						
						| 
							 | 
						            self.dirty = True   | 
					
					
						
						| 
							 | 
						        while self.paths and not self.paths[-1].strip(): | 
					
					
						
						| 
							 | 
						            self.paths.pop() | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						    def save(self): | 
					
					
						
						| 
							 | 
						        """Write changed .pth file back to disk""" | 
					
					
						
						| 
							 | 
						        if not self.dirty: | 
					
					
						
						| 
							 | 
						            return | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						        rel_paths = list(map(self.make_relative, self.paths)) | 
					
					
						
						| 
							 | 
						        if rel_paths: | 
					
					
						
						| 
							 | 
						            log.debug("Saving %s", self.filename) | 
					
					
						
						| 
							 | 
						            lines = self._wrap_lines(rel_paths) | 
					
					
						
						| 
							 | 
						            data = '\n'.join(lines) + '\n' | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						            if os.path.islink(self.filename): | 
					
					
						
						| 
							 | 
						                os.unlink(self.filename) | 
					
					
						
						| 
							 | 
						            with open(self.filename, 'wt') as f: | 
					
					
						
						| 
							 | 
						                f.write(data) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						        elif os.path.exists(self.filename): | 
					
					
						
						| 
							 | 
						            log.debug("Deleting empty %s", self.filename) | 
					
					
						
						| 
							 | 
						            os.unlink(self.filename) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						        self.dirty = False | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						    @staticmethod | 
					
					
						
						| 
							 | 
						    def _wrap_lines(lines): | 
					
					
						
						| 
							 | 
						        return lines | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						    def add(self, dist): | 
					
					
						
						| 
							 | 
						        """Add `dist` to the distribution map""" | 
					
					
						
						| 
							 | 
						        new_path = ( | 
					
					
						
						| 
							 | 
						            dist.location not in self.paths and ( | 
					
					
						
						| 
							 | 
						                dist.location not in self.sitedirs or | 
					
					
						
						| 
							 | 
						                 | 
					
					
						
						| 
							 | 
						                dist.location == os.getcwd() | 
					
					
						
						| 
							 | 
						            ) | 
					
					
						
						| 
							 | 
						        ) | 
					
					
						
						| 
							 | 
						        if new_path: | 
					
					
						
						| 
							 | 
						            self.paths.append(dist.location) | 
					
					
						
						| 
							 | 
						            self.dirty = True | 
					
					
						
						| 
							 | 
						        super().add(dist) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						    def remove(self, dist): | 
					
					
						
						| 
							 | 
						        """Remove `dist` from the distribution map""" | 
					
					
						
						| 
							 | 
						        while dist.location in self.paths: | 
					
					
						
						| 
							 | 
						            self.paths.remove(dist.location) | 
					
					
						
						| 
							 | 
						            self.dirty = True | 
					
					
						
						| 
							 | 
						        super().remove(dist) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						    def make_relative(self, path): | 
					
					
						
						| 
							 | 
						        npath, last = os.path.split(normalize_path(path)) | 
					
					
						
						| 
							 | 
						        baselen = len(self.basedir) | 
					
					
						
						| 
							 | 
						        parts = [last] | 
					
					
						
						| 
							 | 
						        sep = os.altsep == '/' and '/' or os.sep | 
					
					
						
						| 
							 | 
						        while len(npath) >= baselen: | 
					
					
						
						| 
							 | 
						            if npath == self.basedir: | 
					
					
						
						| 
							 | 
						                parts.append(os.curdir) | 
					
					
						
						| 
							 | 
						                parts.reverse() | 
					
					
						
						| 
							 | 
						                return sep.join(parts) | 
					
					
						
						| 
							 | 
						            npath, last = os.path.split(npath) | 
					
					
						
						| 
							 | 
						            parts.append(last) | 
					
					
						
						| 
							 | 
						        else: | 
					
					
						
						| 
							 | 
						            return path | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						class RewritePthDistributions(PthDistributions): | 
					
					
						
						| 
							 | 
						    @classmethod | 
					
					
						
						| 
							 | 
						    def _wrap_lines(cls, lines): | 
					
					
						
						| 
							 | 
						        yield cls.prelude | 
					
					
						
						| 
							 | 
						        for line in lines: | 
					
					
						
						| 
							 | 
						            yield line | 
					
					
						
						| 
							 | 
						        yield cls.postlude | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						    prelude = _one_liner(""" | 
					
					
						
						| 
							 | 
						        import sys | 
					
					
						
						| 
							 | 
						        sys.__plen = len(sys.path) | 
					
					
						
						| 
							 | 
						        """) | 
					
					
						
						| 
							 | 
						    postlude = _one_liner(""" | 
					
					
						
						| 
							 | 
						        import sys | 
					
					
						
						| 
							 | 
						        new = sys.path[sys.__plen:] | 
					
					
						
						| 
							 | 
						        del sys.path[sys.__plen:] | 
					
					
						
						| 
							 | 
						        p = getattr(sys, '__egginsert', 0) | 
					
					
						
						| 
							 | 
						        sys.path[p:p] = new | 
					
					
						
						| 
							 | 
						        sys.__egginsert = p + len(new) | 
					
					
						
						| 
							 | 
						        """) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						if os.environ.get('SETUPTOOLS_SYS_PATH_TECHNIQUE', 'raw') == 'rewrite': | 
					
					
						
						| 
							 | 
						    PthDistributions = RewritePthDistributions | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						def _first_line_re(): | 
					
					
						
						| 
							 | 
						    """ | 
					
					
						
						| 
							 | 
						    Return a regular expression based on first_line_re suitable for matching | 
					
					
						
						| 
							 | 
						    strings. | 
					
					
						
						| 
							 | 
						    """ | 
					
					
						
						| 
							 | 
						    if isinstance(first_line_re.pattern, str): | 
					
					
						
						| 
							 | 
						        return first_line_re | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						     | 
					
					
						
						| 
							 | 
						    return re.compile(first_line_re.pattern.decode()) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						def auto_chmod(func, arg, exc): | 
					
					
						
						| 
							 | 
						    if func in [os.unlink, os.remove] and os.name == 'nt': | 
					
					
						
						| 
							 | 
						        chmod(arg, stat.S_IWRITE) | 
					
					
						
						| 
							 | 
						        return func(arg) | 
					
					
						
						| 
							 | 
						    et, ev, _ = sys.exc_info() | 
					
					
						
						| 
							 | 
						     | 
					
					
						
						| 
							 | 
						    raise (ev[0], ev[1] + (" %s %s" % (func, arg))) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						def update_dist_caches(dist_path, fix_zipimporter_caches): | 
					
					
						
						| 
							 | 
						    """ | 
					
					
						
						| 
							 | 
						    Fix any globally cached `dist_path` related data | 
					
					
						
						| 
							 | 
						 | 
					
					
						
						| 
							 | 
						    `dist_path` should be a path of a newly installed egg distribution (zipped | 
					
					
						
						| 
							 | 
						    or unzipped). | 
					
					
						
						| 
							 | 
						 | 
					
					
						
						| 
							 | 
						    sys.path_importer_cache contains finder objects that have been cached when | 
					
					
						
						| 
							 | 
						    importing data from the original distribution. Any such finders need to be | 
					
					
						
						| 
							 | 
						    cleared since the replacement distribution might be packaged differently, | 
					
					
						
						| 
							 | 
						    e.g. a zipped egg distribution might get replaced with an unzipped egg | 
					
					
						
						| 
							 | 
						    folder or vice versa. Having the old finders cached may then cause Python | 
					
					
						
						| 
							 | 
						    to attempt loading modules from the replacement distribution using an | 
					
					
						
						| 
							 | 
						    incorrect loader. | 
					
					
						
						| 
							 | 
						 | 
					
					
						
						| 
							 | 
						    zipimport.zipimporter objects are Python loaders charged with importing | 
					
					
						
						| 
							 | 
						    data packaged inside zip archives. If stale loaders referencing the | 
					
					
						
						| 
							 | 
						    original distribution, are left behind, they can fail to load modules from | 
					
					
						
						| 
							 | 
						    the replacement distribution. E.g. if an old zipimport.zipimporter instance | 
					
					
						
						| 
							 | 
						    is used to load data from a new zipped egg archive, it may cause the | 
					
					
						
						| 
							 | 
						    operation to attempt to locate the requested data in the wrong location - | 
					
					
						
						| 
							 | 
						    one indicated by the original distribution's zip archive directory | 
					
					
						
						| 
							 | 
						    information. Such an operation may then fail outright, e.g. report having | 
					
					
						
						| 
							 | 
						    read a 'bad local file header', or even worse, it may fail silently & | 
					
					
						
						| 
							 | 
						    return invalid data. | 
					
					
						
						| 
							 | 
						 | 
					
					
						
						| 
							 | 
						    zipimport._zip_directory_cache contains cached zip archive directory | 
					
					
						
						| 
							 | 
						    information for all existing zipimport.zipimporter instances and all such | 
					
					
						
						| 
							 | 
						    instances connected to the same archive share the same cached directory | 
					
					
						
						| 
							 | 
						    information. | 
					
					
						
						| 
							 | 
						 | 
					
					
						
						| 
							 | 
						    If asked, and the underlying Python implementation allows it, we can fix | 
					
					
						
						| 
							 | 
						    all existing zipimport.zipimporter instances instead of having to track | 
					
					
						
						| 
							 | 
						    them down and remove them one by one, by updating their shared cached zip | 
					
					
						
						| 
							 | 
						    archive directory information. This, of course, assumes that the | 
					
					
						
						| 
							 | 
						    replacement distribution is packaged as a zipped egg. | 
					
					
						
						| 
							 | 
						 | 
					
					
						
						| 
							 | 
						    If not asked to fix existing zipimport.zipimporter instances, we still do | 
					
					
						
						| 
							 | 
						    our best to clear any remaining zipimport.zipimporter related cached data | 
					
					
						
						| 
							 | 
						    that might somehow later get used when attempting to load data from the new | 
					
					
						
						| 
							 | 
						    distribution and thus cause such load operations to fail. Note that when | 
					
					
						
						| 
							 | 
						    tracking down such remaining stale data, we can not catch every conceivable | 
					
					
						
						| 
							 | 
						    usage from here, and we clear only those that we know of and have found to | 
					
					
						
						| 
							 | 
						    cause problems if left alive. Any remaining caches should be updated by | 
					
					
						
						| 
							 | 
						    whomever is in charge of maintaining them, i.e. they should be ready to | 
					
					
						
						| 
							 | 
						    handle us replacing their zip archives with new distributions at runtime. | 
					
					
						
						| 
							 | 
						 | 
					
					
						
						| 
							 | 
						    """ | 
					
					
						
						| 
							 | 
						     | 
					
					
						
						| 
							 | 
						     | 
					
					
						
						| 
							 | 
						     | 
					
					
						
						| 
							 | 
						     | 
					
					
						
						| 
							 | 
						     | 
					
					
						
						| 
							 | 
						     | 
					
					
						
						| 
							 | 
						     | 
					
					
						
						| 
							 | 
						     | 
					
					
						
						| 
							 | 
						     | 
					
					
						
						| 
							 | 
						     | 
					
					
						
						| 
							 | 
						     | 
					
					
						
						| 
							 | 
						     | 
					
					
						
						| 
							 | 
						    normalized_path = normalize_path(dist_path) | 
					
					
						
						| 
							 | 
						    _uncache(normalized_path, sys.path_importer_cache) | 
					
					
						
						| 
							 | 
						    if fix_zipimporter_caches: | 
					
					
						
						| 
							 | 
						        _replace_zip_directory_cache_data(normalized_path) | 
					
					
						
						| 
							 | 
						    else: | 
					
					
						
						| 
							 | 
						         | 
					
					
						
						| 
							 | 
						         | 
					
					
						
						| 
							 | 
						         | 
					
					
						
						| 
							 | 
						         | 
					
					
						
						| 
							 | 
						         | 
					
					
						
						| 
							 | 
						         | 
					
					
						
						| 
							 | 
						         | 
					
					
						
						| 
							 | 
						         | 
					
					
						
						| 
							 | 
						         | 
					
					
						
						| 
							 | 
						         | 
					
					
						
						| 
							 | 
						         | 
					
					
						
						| 
							 | 
						         | 
					
					
						
						| 
							 | 
						         | 
					
					
						
						| 
							 | 
						         | 
					
					
						
						| 
							 | 
						        _remove_and_clear_zip_directory_cache_data(normalized_path) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						def _collect_zipimporter_cache_entries(normalized_path, cache): | 
					
					
						
						| 
							 | 
						    """ | 
					
					
						
						| 
							 | 
						    Return zipimporter cache entry keys related to a given normalized path. | 
					
					
						
						| 
							 | 
						 | 
					
					
						
						| 
							 | 
						    Alternative path spellings (e.g. those using different character case or | 
					
					
						
						| 
							 | 
						    those using alternative path separators) related to the same path are | 
					
					
						
						| 
							 | 
						    included. Any sub-path entries are included as well, i.e. those | 
					
					
						
						| 
							 | 
						    corresponding to zip archives embedded in other zip archives. | 
					
					
						
						| 
							 | 
						 | 
					
					
						
						| 
							 | 
						    """ | 
					
					
						
						| 
							 | 
						    result = [] | 
					
					
						
						| 
							 | 
						    prefix_len = len(normalized_path) | 
					
					
						
						| 
							 | 
						    for p in cache: | 
					
					
						
						| 
							 | 
						        np = normalize_path(p) | 
					
					
						
						| 
							 | 
						        if (np.startswith(normalized_path) and | 
					
					
						
						| 
							 | 
						                np[prefix_len:prefix_len + 1] in (os.sep, '')): | 
					
					
						
						| 
							 | 
						            result.append(p) | 
					
					
						
						| 
							 | 
						    return result | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						def _update_zipimporter_cache(normalized_path, cache, updater=None): | 
					
					
						
						| 
							 | 
						    """ | 
					
					
						
						| 
							 | 
						    Update zipimporter cache data for a given normalized path. | 
					
					
						
						| 
							 | 
						 | 
					
					
						
						| 
							 | 
						    Any sub-path entries are processed as well, i.e. those corresponding to zip | 
					
					
						
						| 
							 | 
						    archives embedded in other zip archives. | 
					
					
						
						| 
							 | 
						 | 
					
					
						
						| 
							 | 
						    Given updater is a callable taking a cache entry key and the original entry | 
					
					
						
						| 
							 | 
						    (after already removing the entry from the cache), and expected to update | 
					
					
						
						| 
							 | 
						    the entry and possibly return a new one to be inserted in its place. | 
					
					
						
						| 
							 | 
						    Returning None indicates that the entry should not be replaced with a new | 
					
					
						
						| 
							 | 
						    one. If no updater is given, the cache entries are simply removed without | 
					
					
						
						| 
							 | 
						    any additional processing, the same as if the updater simply returned None. | 
					
					
						
						| 
							 | 
						 | 
					
					
						
						| 
							 | 
						    """ | 
					
					
						
						| 
							 | 
						    for p in _collect_zipimporter_cache_entries(normalized_path, cache): | 
					
					
						
						| 
							 | 
						         | 
					
					
						
						| 
							 | 
						         | 
					
					
						
						| 
							 | 
						         | 
					
					
						
						| 
							 | 
						         | 
					
					
						
						| 
							 | 
						         | 
					
					
						
						| 
							 | 
						         | 
					
					
						
						| 
							 | 
						         | 
					
					
						
						| 
							 | 
						         | 
					
					
						
						| 
							 | 
						         | 
					
					
						
						| 
							 | 
						        old_entry = cache[p] | 
					
					
						
						| 
							 | 
						        del cache[p] | 
					
					
						
						| 
							 | 
						        new_entry = updater and updater(p, old_entry) | 
					
					
						
						| 
							 | 
						        if new_entry is not None: | 
					
					
						
						| 
							 | 
						            cache[p] = new_entry | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						def _uncache(normalized_path, cache): | 
					
					
						
						| 
							 | 
						    _update_zipimporter_cache(normalized_path, cache) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						def _remove_and_clear_zip_directory_cache_data(normalized_path): | 
					
					
						
						| 
							 | 
						    def clear_and_remove_cached_zip_archive_directory_data(path, old_entry): | 
					
					
						
						| 
							 | 
						        old_entry.clear() | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						    _update_zipimporter_cache( | 
					
					
						
						| 
							 | 
						        normalized_path, zipimport._zip_directory_cache, | 
					
					
						
						| 
							 | 
						        updater=clear_and_remove_cached_zip_archive_directory_data) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						 | 
					
					
						
						| 
							 | 
						 | 
					
					
						
						| 
							 | 
						 | 
					
					
						
						| 
							 | 
						 | 
					
					
						
						| 
							 | 
						 | 
					
					
						
						| 
							 | 
						 | 
					
					
						
						| 
							 | 
						 | 
					
					
						
						| 
							 | 
						 | 
					
					
						
						| 
							 | 
						if '__pypy__' in sys.builtin_module_names: | 
					
					
						
						| 
							 | 
						    _replace_zip_directory_cache_data = \ | 
					
					
						
						| 
							 | 
						        _remove_and_clear_zip_directory_cache_data | 
					
					
						
						| 
							 | 
						else: | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						    def _replace_zip_directory_cache_data(normalized_path): | 
					
					
						
						| 
							 | 
						        def replace_cached_zip_archive_directory_data(path, old_entry): | 
					
					
						
						| 
							 | 
						             | 
					
					
						
						| 
							 | 
						             | 
					
					
						
						| 
							 | 
						             | 
					
					
						
						| 
							 | 
						             | 
					
					
						
						| 
							 | 
						             | 
					
					
						
						| 
							 | 
						             | 
					
					
						
						| 
							 | 
						             | 
					
					
						
						| 
							 | 
						            old_entry.clear() | 
					
					
						
						| 
							 | 
						            zipimport.zipimporter(path) | 
					
					
						
						| 
							 | 
						            old_entry.update(zipimport._zip_directory_cache[path]) | 
					
					
						
						| 
							 | 
						            return old_entry | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						        _update_zipimporter_cache( | 
					
					
						
						| 
							 | 
						            normalized_path, zipimport._zip_directory_cache, | 
					
					
						
						| 
							 | 
						            updater=replace_cached_zip_archive_directory_data) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						def is_python(text, filename='<string>'): | 
					
					
						
						| 
							 | 
						    "Is this string a valid Python script?" | 
					
					
						
						| 
							 | 
						    try: | 
					
					
						
						| 
							 | 
						        compile(text, filename, 'exec') | 
					
					
						
						| 
							 | 
						    except (SyntaxError, TypeError): | 
					
					
						
						| 
							 | 
						        return False | 
					
					
						
						| 
							 | 
						    else: | 
					
					
						
						| 
							 | 
						        return True | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						def is_sh(executable): | 
					
					
						
						| 
							 | 
						    """Determine if the specified executable is a .sh (contains a #! line)""" | 
					
					
						
						| 
							 | 
						    try: | 
					
					
						
						| 
							 | 
						        with io.open(executable, encoding='latin-1') as fp: | 
					
					
						
						| 
							 | 
						            magic = fp.read(2) | 
					
					
						
						| 
							 | 
						    except (OSError, IOError): | 
					
					
						
						| 
							 | 
						        return executable | 
					
					
						
						| 
							 | 
						    return magic == '#!' | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						def nt_quote_arg(arg): | 
					
					
						
						| 
							 | 
						    """Quote a command line argument according to Windows parsing rules""" | 
					
					
						
						| 
							 | 
						    return subprocess.list2cmdline([arg]) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						def is_python_script(script_text, filename): | 
					
					
						
						| 
							 | 
						    """Is this text, as a whole, a Python script? (as opposed to shell/bat/etc. | 
					
					
						
						| 
							 | 
						    """ | 
					
					
						
						| 
							 | 
						    if filename.endswith('.py') or filename.endswith('.pyw'): | 
					
					
						
						| 
							 | 
						        return True   | 
					
					
						
						| 
							 | 
						    if is_python(script_text, filename): | 
					
					
						
						| 
							 | 
						        return True   | 
					
					
						
						| 
							 | 
						    if script_text.startswith('#!'): | 
					
					
						
						| 
							 | 
						         | 
					
					
						
						| 
							 | 
						        return 'python' in script_text.splitlines()[0].lower() | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						    return False   | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						try: | 
					
					
						
						| 
							 | 
						    from os import chmod as _chmod | 
					
					
						
						| 
							 | 
						except ImportError: | 
					
					
						
						| 
							 | 
						     | 
					
					
						
						| 
							 | 
						    def _chmod(*args): | 
					
					
						
						| 
							 | 
						        pass | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						def chmod(path, mode): | 
					
					
						
						| 
							 | 
						    log.debug("changing mode of %s to %o", path, mode) | 
					
					
						
						| 
							 | 
						    try: | 
					
					
						
						| 
							 | 
						        _chmod(path, mode) | 
					
					
						
						| 
							 | 
						    except os.error as e: | 
					
					
						
						| 
							 | 
						        log.debug("chmod failed: %s", e) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						class CommandSpec(list): | 
					
					
						
						| 
							 | 
						    """ | 
					
					
						
						| 
							 | 
						    A command spec for a #! header, specified as a list of arguments akin to | 
					
					
						
						| 
							 | 
						    those passed to Popen. | 
					
					
						
						| 
							 | 
						    """ | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						    options = [] | 
					
					
						
						| 
							 | 
						    split_args = dict() | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						    @classmethod | 
					
					
						
						| 
							 | 
						    def best(cls): | 
					
					
						
						| 
							 | 
						        """ | 
					
					
						
						| 
							 | 
						        Choose the best CommandSpec class based on environmental conditions. | 
					
					
						
						| 
							 | 
						        """ | 
					
					
						
						| 
							 | 
						        return cls | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						    @classmethod | 
					
					
						
						| 
							 | 
						    def _sys_executable(cls): | 
					
					
						
						| 
							 | 
						        _default = os.path.normpath(sys.executable) | 
					
					
						
						| 
							 | 
						        return os.environ.get('__PYVENV_LAUNCHER__', _default) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						    @classmethod | 
					
					
						
						| 
							 | 
						    def from_param(cls, param): | 
					
					
						
						| 
							 | 
						        """ | 
					
					
						
						| 
							 | 
						        Construct a CommandSpec from a parameter to build_scripts, which may | 
					
					
						
						| 
							 | 
						        be None. | 
					
					
						
						| 
							 | 
						        """ | 
					
					
						
						| 
							 | 
						        if isinstance(param, cls): | 
					
					
						
						| 
							 | 
						            return param | 
					
					
						
						| 
							 | 
						        if isinstance(param, list): | 
					
					
						
						| 
							 | 
						            return cls(param) | 
					
					
						
						| 
							 | 
						        if param is None: | 
					
					
						
						| 
							 | 
						            return cls.from_environment() | 
					
					
						
						| 
							 | 
						         | 
					
					
						
						| 
							 | 
						        return cls.from_string(param) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						    @classmethod | 
					
					
						
						| 
							 | 
						    def from_environment(cls): | 
					
					
						
						| 
							 | 
						        return cls([cls._sys_executable()]) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						    @classmethod | 
					
					
						
						| 
							 | 
						    def from_string(cls, string): | 
					
					
						
						| 
							 | 
						        """ | 
					
					
						
						| 
							 | 
						        Construct a command spec from a simple string representing a command | 
					
					
						
						| 
							 | 
						        line parseable by shlex.split. | 
					
					
						
						| 
							 | 
						        """ | 
					
					
						
						| 
							 | 
						        items = shlex.split(string, **cls.split_args) | 
					
					
						
						| 
							 | 
						        return cls(items) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						    def install_options(self, script_text): | 
					
					
						
						| 
							 | 
						        self.options = shlex.split(self._extract_options(script_text)) | 
					
					
						
						| 
							 | 
						        cmdline = subprocess.list2cmdline(self) | 
					
					
						
						| 
							 | 
						        if not isascii(cmdline): | 
					
					
						
						| 
							 | 
						            self.options[:0] = ['-x'] | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						    @staticmethod | 
					
					
						
						| 
							 | 
						    def _extract_options(orig_script): | 
					
					
						
						| 
							 | 
						        """ | 
					
					
						
						| 
							 | 
						        Extract any options from the first line of the script. | 
					
					
						
						| 
							 | 
						        """ | 
					
					
						
						| 
							 | 
						        first = (orig_script + '\n').splitlines()[0] | 
					
					
						
						| 
							 | 
						        match = _first_line_re().match(first) | 
					
					
						
						| 
							 | 
						        options = match.group(1) or '' if match else '' | 
					
					
						
						| 
							 | 
						        return options.strip() | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						    def as_header(self): | 
					
					
						
						| 
							 | 
						        return self._render(self + list(self.options)) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						    @staticmethod | 
					
					
						
						| 
							 | 
						    def _strip_quotes(item): | 
					
					
						
						| 
							 | 
						        _QUOTES = '"\'' | 
					
					
						
						| 
							 | 
						        for q in _QUOTES: | 
					
					
						
						| 
							 | 
						            if item.startswith(q) and item.endswith(q): | 
					
					
						
						| 
							 | 
						                return item[1:-1] | 
					
					
						
						| 
							 | 
						        return item | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						    @staticmethod | 
					
					
						
						| 
							 | 
						    def _render(items): | 
					
					
						
						| 
							 | 
						        cmdline = subprocess.list2cmdline( | 
					
					
						
						| 
							 | 
						            CommandSpec._strip_quotes(item.strip()) for item in items) | 
					
					
						
						| 
							 | 
						        return '#!' + cmdline + '\n' | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						 | 
					
					
						
						| 
							 | 
						sys_executable = CommandSpec._sys_executable() | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						class WindowsCommandSpec(CommandSpec): | 
					
					
						
						| 
							 | 
						    split_args = dict(posix=False) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						class ScriptWriter: | 
					
					
						
						| 
							 | 
						    """ | 
					
					
						
						| 
							 | 
						    Encapsulates behavior around writing entry point scripts for console and | 
					
					
						
						| 
							 | 
						    gui apps. | 
					
					
						
						| 
							 | 
						    """ | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						    template = textwrap.dedent(r""" | 
					
					
						
						| 
							 | 
						        # EASY-INSTALL-ENTRY-SCRIPT: %(spec)r,%(group)r,%(name)r | 
					
					
						
						| 
							 | 
						        import re | 
					
					
						
						| 
							 | 
						        import sys | 
					
					
						
						| 
							 | 
						 | 
					
					
						
						| 
							 | 
						        # for compatibility with easy_install; see #2198 | 
					
					
						
						| 
							 | 
						        __requires__ = %(spec)r | 
					
					
						
						| 
							 | 
						 | 
					
					
						
						| 
							 | 
						        try: | 
					
					
						
						| 
							 | 
						            from importlib.metadata import distribution | 
					
					
						
						| 
							 | 
						        except ImportError: | 
					
					
						
						| 
							 | 
						            try: | 
					
					
						
						| 
							 | 
						                from importlib_metadata import distribution | 
					
					
						
						| 
							 | 
						            except ImportError: | 
					
					
						
						| 
							 | 
						                from pkg_resources import load_entry_point | 
					
					
						
						| 
							 | 
						 | 
					
					
						
						| 
							 | 
						 | 
					
					
						
						| 
							 | 
						        def importlib_load_entry_point(spec, group, name): | 
					
					
						
						| 
							 | 
						            dist_name, _, _ = spec.partition('==') | 
					
					
						
						| 
							 | 
						            matches = ( | 
					
					
						
						| 
							 | 
						                entry_point | 
					
					
						
						| 
							 | 
						                for entry_point in distribution(dist_name).entry_points | 
					
					
						
						| 
							 | 
						                if entry_point.group == group and entry_point.name == name | 
					
					
						
						| 
							 | 
						            ) | 
					
					
						
						| 
							 | 
						            return next(matches).load() | 
					
					
						
						| 
							 | 
						 | 
					
					
						
						| 
							 | 
						 | 
					
					
						
						| 
							 | 
						        globals().setdefault('load_entry_point', importlib_load_entry_point) | 
					
					
						
						| 
							 | 
						 | 
					
					
						
						| 
							 | 
						 | 
					
					
						
						| 
							 | 
						        if __name__ == '__main__': | 
					
					
						
						| 
							 | 
						            sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0]) | 
					
					
						
						| 
							 | 
						            sys.exit(load_entry_point(%(spec)r, %(group)r, %(name)r)()) | 
					
					
						
						| 
							 | 
						        """).lstrip() | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						    command_spec_class = CommandSpec | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						    @classmethod | 
					
					
						
						| 
							 | 
						    def get_script_args(cls, dist, executable=None, wininst=False): | 
					
					
						
						| 
							 | 
						         | 
					
					
						
						| 
							 | 
						        warnings.warn("Use get_args", EasyInstallDeprecationWarning) | 
					
					
						
						| 
							 | 
						        writer = (WindowsScriptWriter if wininst else ScriptWriter).best() | 
					
					
						
						| 
							 | 
						        header = cls.get_script_header("", executable, wininst) | 
					
					
						
						| 
							 | 
						        return writer.get_args(dist, header) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						    @classmethod | 
					
					
						
						| 
							 | 
						    def get_script_header(cls, script_text, executable=None, wininst=False): | 
					
					
						
						| 
							 | 
						         | 
					
					
						
						| 
							 | 
						        warnings.warn( | 
					
					
						
						| 
							 | 
						            "Use get_header", EasyInstallDeprecationWarning, stacklevel=2) | 
					
					
						
						| 
							 | 
						        if wininst: | 
					
					
						
						| 
							 | 
						            executable = "python.exe" | 
					
					
						
						| 
							 | 
						        return cls.get_header(script_text, executable) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						    @classmethod | 
					
					
						
						| 
							 | 
						    def get_args(cls, dist, header=None): | 
					
					
						
						| 
							 | 
						        """ | 
					
					
						
						| 
							 | 
						        Yield write_script() argument tuples for a distribution's | 
					
					
						
						| 
							 | 
						        console_scripts and gui_scripts entry points. | 
					
					
						
						| 
							 | 
						        """ | 
					
					
						
						| 
							 | 
						        if header is None: | 
					
					
						
						| 
							 | 
						            header = cls.get_header() | 
					
					
						
						| 
							 | 
						        spec = str(dist.as_requirement()) | 
					
					
						
						| 
							 | 
						        for type_ in 'console', 'gui': | 
					
					
						
						| 
							 | 
						            group = type_ + '_scripts' | 
					
					
						
						| 
							 | 
						            for name, ep in dist.get_entry_map(group).items(): | 
					
					
						
						| 
							 | 
						                cls._ensure_safe_name(name) | 
					
					
						
						| 
							 | 
						                script_text = cls.template % locals() | 
					
					
						
						| 
							 | 
						                args = cls._get_script_args(type_, name, header, script_text) | 
					
					
						
						| 
							 | 
						                for res in args: | 
					
					
						
						| 
							 | 
						                    yield res | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						    @staticmethod | 
					
					
						
						| 
							 | 
						    def _ensure_safe_name(name): | 
					
					
						
						| 
							 | 
						        """ | 
					
					
						
						| 
							 | 
						        Prevent paths in *_scripts entry point names. | 
					
					
						
						| 
							 | 
						        """ | 
					
					
						
						| 
							 | 
						        has_path_sep = re.search(r'[\\/]', name) | 
					
					
						
						| 
							 | 
						        if has_path_sep: | 
					
					
						
						| 
							 | 
						            raise ValueError("Path separators not allowed in script names") | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						    @classmethod | 
					
					
						
						| 
							 | 
						    def get_writer(cls, force_windows): | 
					
					
						
						| 
							 | 
						         | 
					
					
						
						| 
							 | 
						        warnings.warn("Use best", EasyInstallDeprecationWarning) | 
					
					
						
						| 
							 | 
						        return WindowsScriptWriter.best() if force_windows else cls.best() | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						    @classmethod | 
					
					
						
						| 
							 | 
						    def best(cls): | 
					
					
						
						| 
							 | 
						        """ | 
					
					
						
						| 
							 | 
						        Select the best ScriptWriter for this environment. | 
					
					
						
						| 
							 | 
						        """ | 
					
					
						
						| 
							 | 
						        if sys.platform == 'win32' or (os.name == 'java' and os._name == 'nt'): | 
					
					
						
						| 
							 | 
						            return WindowsScriptWriter.best() | 
					
					
						
						| 
							 | 
						        else: | 
					
					
						
						| 
							 | 
						            return cls | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						    @classmethod | 
					
					
						
						| 
							 | 
						    def _get_script_args(cls, type_, name, header, script_text): | 
					
					
						
						| 
							 | 
						         | 
					
					
						
						| 
							 | 
						        yield (name, header + script_text) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						    @classmethod | 
					
					
						
						| 
							 | 
						    def get_header(cls, script_text="", executable=None): | 
					
					
						
						| 
							 | 
						        """Create a #! line, getting options (if any) from script_text""" | 
					
					
						
						| 
							 | 
						        cmd = cls.command_spec_class.best().from_param(executable) | 
					
					
						
						| 
							 | 
						        cmd.install_options(script_text) | 
					
					
						
						| 
							 | 
						        return cmd.as_header() | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						class WindowsScriptWriter(ScriptWriter): | 
					
					
						
						| 
							 | 
						    command_spec_class = WindowsCommandSpec | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						    @classmethod | 
					
					
						
						| 
							 | 
						    def get_writer(cls): | 
					
					
						
						| 
							 | 
						         | 
					
					
						
						| 
							 | 
						        warnings.warn("Use best", EasyInstallDeprecationWarning) | 
					
					
						
						| 
							 | 
						        return cls.best() | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						    @classmethod | 
					
					
						
						| 
							 | 
						    def best(cls): | 
					
					
						
						| 
							 | 
						        """ | 
					
					
						
						| 
							 | 
						        Select the best ScriptWriter suitable for Windows | 
					
					
						
						| 
							 | 
						        """ | 
					
					
						
						| 
							 | 
						        writer_lookup = dict( | 
					
					
						
						| 
							 | 
						            executable=WindowsExecutableLauncherWriter, | 
					
					
						
						| 
							 | 
						            natural=cls, | 
					
					
						
						| 
							 | 
						        ) | 
					
					
						
						| 
							 | 
						         | 
					
					
						
						| 
							 | 
						        launcher = os.environ.get('SETUPTOOLS_LAUNCHER', 'executable') | 
					
					
						
						| 
							 | 
						        return writer_lookup[launcher] | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						    @classmethod | 
					
					
						
						| 
							 | 
						    def _get_script_args(cls, type_, name, header, script_text): | 
					
					
						
						| 
							 | 
						        "For Windows, add a .py extension" | 
					
					
						
						| 
							 | 
						        ext = dict(console='.pya', gui='.pyw')[type_] | 
					
					
						
						| 
							 | 
						        if ext not in os.environ['PATHEXT'].lower().split(';'): | 
					
					
						
						| 
							 | 
						            msg = ( | 
					
					
						
						| 
							 | 
						                "{ext} not listed in PATHEXT; scripts will not be " | 
					
					
						
						| 
							 | 
						                "recognized as executables." | 
					
					
						
						| 
							 | 
						            ).format(**locals()) | 
					
					
						
						| 
							 | 
						            warnings.warn(msg, UserWarning) | 
					
					
						
						| 
							 | 
						        old = ['.pya', '.py', '-script.py', '.pyc', '.pyo', '.pyw', '.exe'] | 
					
					
						
						| 
							 | 
						        old.remove(ext) | 
					
					
						
						| 
							 | 
						        header = cls._adjust_header(type_, header) | 
					
					
						
						| 
							 | 
						        blockers = [name + x for x in old] | 
					
					
						
						| 
							 | 
						        yield name + ext, header + script_text, 't', blockers | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						    @classmethod | 
					
					
						
						| 
							 | 
						    def _adjust_header(cls, type_, orig_header): | 
					
					
						
						| 
							 | 
						        """ | 
					
					
						
						| 
							 | 
						        Make sure 'pythonw' is used for gui and 'python' is used for | 
					
					
						
						| 
							 | 
						        console (regardless of what sys.executable is). | 
					
					
						
						| 
							 | 
						        """ | 
					
					
						
						| 
							 | 
						        pattern = 'pythonw.exe' | 
					
					
						
						| 
							 | 
						        repl = 'python.exe' | 
					
					
						
						| 
							 | 
						        if type_ == 'gui': | 
					
					
						
						| 
							 | 
						            pattern, repl = repl, pattern | 
					
					
						
						| 
							 | 
						        pattern_ob = re.compile(re.escape(pattern), re.IGNORECASE) | 
					
					
						
						| 
							 | 
						        new_header = pattern_ob.sub(string=orig_header, repl=repl) | 
					
					
						
						| 
							 | 
						        return new_header if cls._use_header(new_header) else orig_header | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						    @staticmethod | 
					
					
						
						| 
							 | 
						    def _use_header(new_header): | 
					
					
						
						| 
							 | 
						        """ | 
					
					
						
						| 
							 | 
						        Should _adjust_header use the replaced header? | 
					
					
						
						| 
							 | 
						 | 
					
					
						
						| 
							 | 
						        On non-windows systems, always use. On | 
					
					
						
						| 
							 | 
						        Windows systems, only use the replaced header if it resolves | 
					
					
						
						| 
							 | 
						        to an executable on the system. | 
					
					
						
						| 
							 | 
						        """ | 
					
					
						
						| 
							 | 
						        clean_header = new_header[2:-1].strip('"') | 
					
					
						
						| 
							 | 
						        return sys.platform != 'win32' or find_executable(clean_header) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						class WindowsExecutableLauncherWriter(WindowsScriptWriter): | 
					
					
						
						| 
							 | 
						    @classmethod | 
					
					
						
						| 
							 | 
						    def _get_script_args(cls, type_, name, header, script_text): | 
					
					
						
						| 
							 | 
						        """ | 
					
					
						
						| 
							 | 
						        For Windows, add a .py extension and an .exe launcher | 
					
					
						
						| 
							 | 
						        """ | 
					
					
						
						| 
							 | 
						        if type_ == 'gui': | 
					
					
						
						| 
							 | 
						            launcher_type = 'gui' | 
					
					
						
						| 
							 | 
						            ext = '-script.pyw' | 
					
					
						
						| 
							 | 
						            old = ['.pyw'] | 
					
					
						
						| 
							 | 
						        else: | 
					
					
						
						| 
							 | 
						            launcher_type = 'cli' | 
					
					
						
						| 
							 | 
						            ext = '-script.py' | 
					
					
						
						| 
							 | 
						            old = ['.py', '.pyc', '.pyo'] | 
					
					
						
						| 
							 | 
						        hdr = cls._adjust_header(type_, header) | 
					
					
						
						| 
							 | 
						        blockers = [name + x for x in old] | 
					
					
						
						| 
							 | 
						        yield (name + ext, hdr + script_text, 't', blockers) | 
					
					
						
						| 
							 | 
						        yield ( | 
					
					
						
						| 
							 | 
						            name + '.exe', get_win_launcher(launcher_type), | 
					
					
						
						| 
							 | 
						            'b'   | 
					
					
						
						| 
							 | 
						        ) | 
					
					
						
						| 
							 | 
						        if not is_64bit(): | 
					
					
						
						| 
							 | 
						             | 
					
					
						
						| 
							 | 
						             | 
					
					
						
						| 
							 | 
						             | 
					
					
						
						| 
							 | 
						             | 
					
					
						
						| 
							 | 
						             | 
					
					
						
						| 
							 | 
						            m_name = name + '.exe.manifest' | 
					
					
						
						| 
							 | 
						            yield (m_name, load_launcher_manifest(name), 't') | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						 | 
					
					
						
						| 
							 | 
						get_script_args = ScriptWriter.get_script_args | 
					
					
						
						| 
							 | 
						get_script_header = ScriptWriter.get_script_header | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						def get_win_launcher(type): | 
					
					
						
						| 
							 | 
						    """ | 
					
					
						
						| 
							 | 
						    Load the Windows launcher (executable) suitable for launching a script. | 
					
					
						
						| 
							 | 
						 | 
					
					
						
						| 
							 | 
						    `type` should be either 'cli' or 'gui' | 
					
					
						
						| 
							 | 
						 | 
					
					
						
						| 
							 | 
						    Returns the executable as a byte string. | 
					
					
						
						| 
							 | 
						    """ | 
					
					
						
						| 
							 | 
						    launcher_fn = '%s.exe' % type | 
					
					
						
						| 
							 | 
						    if is_64bit(): | 
					
					
						
						| 
							 | 
						        if get_platform() == "win-arm64": | 
					
					
						
						| 
							 | 
						            launcher_fn = launcher_fn.replace(".", "-arm64.") | 
					
					
						
						| 
							 | 
						        else: | 
					
					
						
						| 
							 | 
						            launcher_fn = launcher_fn.replace(".", "-64.") | 
					
					
						
						| 
							 | 
						    else: | 
					
					
						
						| 
							 | 
						        launcher_fn = launcher_fn.replace(".", "-32.") | 
					
					
						
						| 
							 | 
						    return resource_string('setuptools', launcher_fn) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						def load_launcher_manifest(name): | 
					
					
						
						| 
							 | 
						    manifest = pkg_resources.resource_string(__name__, 'launcher manifest.xml') | 
					
					
						
						| 
							 | 
						    return manifest.decode('utf-8') % vars() | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						def rmtree(path, ignore_errors=False, onerror=auto_chmod): | 
					
					
						
						| 
							 | 
						    return shutil.rmtree(path, ignore_errors, onerror) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						def current_umask(): | 
					
					
						
						| 
							 | 
						    tmp = os.umask(0o022) | 
					
					
						
						| 
							 | 
						    os.umask(tmp) | 
					
					
						
						| 
							 | 
						    return tmp | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						def only_strs(values): | 
					
					
						
						| 
							 | 
						    """ | 
					
					
						
						| 
							 | 
						    Exclude non-str values. Ref #3063. | 
					
					
						
						| 
							 | 
						    """ | 
					
					
						
						| 
							 | 
						    return filter(lambda val: isinstance(val, str), values) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						class EasyInstallDeprecationWarning(SetuptoolsDeprecationWarning): | 
					
					
						
						| 
							 | 
						    """ | 
					
					
						
						| 
							 | 
						    Warning for EasyInstall deprecations, bypassing suppression. | 
					
					
						
						| 
							 | 
						    """ | 
					
					
						
						| 
							 | 
						
 |