def get_dist_to_uninstall(self, candidate: Candidate) -> Optional[BaseDistribution]: # TODO: Are there more cases this needs to return True? Editable? dist = self._installed_dists.get(candidate.project_name) if dist is None: # Not installed, no uninstallation required. return None # Prevent uninstalling packages from /usr if dist_location(dist._dist) in ( get_scheme('', prefix=sys.base_prefix).purelib, get_scheme('', prefix=sys.base_prefix).platlib, ): return None # We're installing into global site. The current installation must # be uninstalled, no matter it's in global or user site, because the # user site installation has precedence over global. if not self._use_user_site: return dist # We're installing into user site. Remove the user site installation. if dist.in_usersite: return dist # We're installing into user site, but the installed incompatible # package is in global site. We can't uninstall that, and would let # the new user installation to "shadow" it. But shadowing won't work # in virtual environments, so we error out. if running_under_virtualenv() and dist.in_site_packages: message = ( f"Will not install to the user site because it will lack " f"sys.path precedence to {dist.raw_name} in {dist.location}" ) raise InstallationError(message) return None
def dist_in_install_path(dist): """ Return True if given Distribution is installed in path matching distutils_scheme layout. """ norm_path = normalize_path(dist_location(dist)) return norm_path.startswith(normalize_path( get_scheme("").purelib.split('python')[0]))
def _handle_target_dir( self, target_dir: str, target_temp_dir: TempDirectory, upgrade: bool ) -> None: ensure_dir(target_dir) # Checking both purelib and platlib directories for installed # packages to be moved to target directory lib_dir_list = [] # Checking both purelib and platlib directories for installed # packages to be moved to target directory scheme = get_scheme('', home=target_temp_dir.path) purelib_dir = scheme.purelib platlib_dir = scheme.platlib data_dir = scheme.data if os.path.exists(purelib_dir): lib_dir_list.append(purelib_dir) if os.path.exists(platlib_dir) and platlib_dir != purelib_dir: lib_dir_list.append(platlib_dir) if os.path.exists(data_dir): lib_dir_list.append(data_dir) for lib_dir in lib_dir_list: for item in os.listdir(lib_dir): if lib_dir == data_dir: ddir = os.path.join(data_dir, item) if any(s.startswith(ddir) for s in lib_dir_list[:-1]): continue target_item_dir = os.path.join(target_dir, item) if os.path.exists(target_item_dir): if not upgrade: logger.warning( 'Target directory %s already exists. Specify ' '--upgrade to force replacement.', target_item_dir ) continue if os.path.islink(target_item_dir): logger.warning( 'Target directory %s already exists and is ' 'a link. pip will not automatically replace ' 'links, please remove if replacement is ' 'desired.', target_item_dir ) continue if os.path.isdir(target_item_dir): shutil.rmtree(target_item_dir) else: os.remove(target_item_dir) shutil.move( os.path.join(lib_dir, item), target_item_dir )
def get_lib_location_guesses(user: bool = False, home: Optional[str] = None, root: Optional[str] = None, isolated: bool = False, prefix: Optional[str] = None) -> List[str]: scheme = get_scheme( '', user=user, home=home, root=root, isolated=isolated, prefix=prefix, ) return [scheme.purelib, scheme.platlib]
def _install_wheel(self, pkg): pkg._assert_paths(install=True) if pkg.package_path.endswith('.whl'): log.info( style_note("Found Python Wheel", os.path.basename(self.dist_info_dir))) else: log.info( style_note("Found dist-info", os.path.basename(self.dist_info_dir))) log.warning("Bare dist-info does not appear to be a wheel.") wheel_dir, dist_info_name = os.path.split(self.dist_info_dir) wheel_name = os.path.splitext(dist_info_name)[0] # Lets just take advantage of pip! # The only reason we're reading into pip like this is because we # would rather just do this part, rather than have it go through # the full process with the *.whl file. If this breaks, feel # free to do something like: # pip install --force-reinstall --prefix {pkg.install_path} --no-deps {pkg.package_path} # along with: # --no-warn-script-location # --disable-pip-version-check # We delay the import just in case the bootstrap is borked. from pip._internal.operations.install.wheel import install_wheel from pip._internal.locations import get_scheme # We may to trick pip into installing into another version's directories. scheme = get_scheme(self.name, prefix=pkg.install_path) version = get_default_python().version src_python = '{}python{}.{}{}'.format(os.path.sep, sys.version_info[0], sys.version_info[1], os.path.sep) dst_python = '{}python{}.{}{}'.format(os.path.sep, version[0], version[1], os.path.sep) if src_python != dst_python: for k in 'platlib', 'purelib', 'headers', 'scripts', 'data': setattr(scheme, k, getattr(scheme, k).replace(src_python, dst_python)) req = DummyPipRequirement() req.name = wheel_name install_wheel(pkg.name, pkg.package_path, scheme, '<VEE dummy request>')
def get_lib_location_guesses( user=False, # type: bool home=None, # type: Optional[str] root=None, # type: Optional[str] isolated=False, # type: bool prefix=None # type: Optional[str] ): # type:(...) -> List[str] scheme = get_scheme( '', user=user, home=home, root=root, isolated=isolated, prefix=prefix, ) return [scheme.purelib, scheme.platlib]
def install( self, install_options, # type: List[str] global_options=None, # type: Optional[Sequence[str]] root=None, # type: Optional[str] home=None, # type: Optional[str] prefix=None, # type: Optional[str] warn_script_location=True, # type: bool use_user_site=False, # type: bool pycompile=True # type: bool ): # type: (...) -> None scheme = get_scheme( self.name, user=use_user_site, home=home, root=root, isolated=self.isolated, prefix=prefix, )
def test_install_prefix(self, data, tmpdir): prefix = os.path.join(os.path.sep, 'some', 'path') self.prep(data, tmpdir) scheme = get_scheme( self.name, user=False, home=None, root=tmpdir, isolated=False, prefix=prefix, ) wheel.install_wheel( self.name, self.wheelpath, scheme=scheme, req_description=str(self.req), ) bin_dir = 'Scripts' if WINDOWS else 'bin' assert os.path.exists(os.path.join(tmpdir, 'some', 'path', bin_dir)) assert os.path.exists(os.path.join(tmpdir, 'some', 'path', 'my_data'))
def test_install_prefix(self, data: TestData, tmpdir: Path) -> None: prefix = os.path.join(os.path.sep, "some", "path") self.prep(data, tmpdir) scheme = get_scheme( self.name, user=False, home=None, root=str( tmpdir), # Casting needed for CPython 3.10+. See GH-10358. isolated=False, prefix=prefix, ) wheel.install_wheel( self.name, self.wheelpath, scheme=scheme, req_description=str(self.req), ) bin_dir = "Scripts" if WINDOWS else "bin" assert os.path.exists(os.path.join(tmpdir, "some", "path", bin_dir)) assert os.path.exists(os.path.join(tmpdir, "some", "path", "my_data"))
def install( self, install_options, # type: List[str] global_options=None, # type: Optional[Sequence[str]] root=None, # type: Optional[str] home=None, # type: Optional[str] prefix=None, # type: Optional[str] warn_script_location=True, # type: bool use_user_site=False, # type: bool pycompile=True # type: bool ): # type: (...) -> None scheme = get_scheme( self.name, user=use_user_site, home=home, root=root, isolated=self.isolated, prefix=prefix, ) global_options = global_options if global_options is not None else [] if self.editable: self.install_editable( install_options, global_options, prefix=prefix, home=home, use_user_site=use_user_site, ) return if self.is_wheel: self.move_wheel_files( self.source_dir, scheme=scheme, warn_script_location=warn_script_location, pycompile=pycompile, ) self.install_succeeded = True return # Extend the list of global and install options passed on to # the setup.py call with the ones from the requirements file. # Options specified in requirements file override those # specified on the command line, since the last option given # to setup.py is the one that is used. global_options = list(global_options) + \ self.options.get('global_options', []) install_options = list(install_options) + \ self.options.get('install_options', []) header_dir = scheme.headers with TempDirectory(kind="record") as temp_dir: record_filename = os.path.join(temp_dir.path, 'install-record.txt') install_args = make_setuptools_install_args( self.setup_py_path, global_options=global_options, install_options=install_options, record_filename=record_filename, root=root, prefix=prefix, header_dir=header_dir, home=home, use_user_site=use_user_site, no_user_config=self.isolated, pycompile=pycompile, ) runner = runner_with_spinner_message( "Running setup.py install for {}".format(self.name) ) with indent_log(), self.build_env: runner( cmd=install_args, cwd=self.unpacked_source_directory, ) if not os.path.exists(record_filename): logger.debug('Record file %s not found', record_filename) return self.install_succeeded = True def prepend_root(path): # type: (str) -> str if root is None or not os.path.isabs(path): return path else: return change_root(root, path) with open(record_filename) as f: for line in f: directory = os.path.dirname(line) if directory.endswith('.egg-info'): egg_info_dir = prepend_root(directory) break else: deprecated( reason=( "{} did not indicate that it installed an " ".egg-info directory. Only setup.py projects " "generating .egg-info directories are supported." ).format(self), replacement=( "for maintainers: updating the setup.py of {0}. " "For users: contact the maintainers of {0} to let " "them know to update their setup.py.".format( self.name ) ), gone_in="20.2", issue=6998, ) # FIXME: put the record somewhere return new_lines = [] with open(record_filename) as f: for line in f: filename = line.strip() if os.path.isdir(filename): filename += os.path.sep new_lines.append( os.path.relpath(prepend_root(filename), egg_info_dir) ) new_lines.sort() ensure_dir(egg_info_dir) inst_files_path = os.path.join(egg_info_dir, 'installed-files.txt') with open(inst_files_path, 'w') as f: f.write('\n'.join(new_lines) + '\n')
def install( self, install_options, # type: List[str] global_options=None, # type: Optional[Sequence[str]] root=None, # type: Optional[str] home=None, # type: Optional[str] prefix=None, # type: Optional[str] warn_script_location=True, # type: bool use_user_site=False, # type: bool pycompile=True # type: bool ): # type: (...) -> None scheme = get_scheme( self.name, user=use_user_site, home=home, root=root, isolated=self.isolated, prefix=prefix, ) global_options = global_options if global_options is not None else [] if self.editable: install_editable_legacy( install_options, global_options, prefix=prefix, home=home, use_user_site=use_user_site, name=self.name, setup_py_path=self.setup_py_path, isolated=self.isolated, build_env=self.build_env, unpacked_source_directory=self.unpacked_source_directory, ) self.install_succeeded = True return if self.is_wheel: assert self.local_file_path direct_url = None if self.original_link: direct_url = direct_url_from_link( self.original_link, self.source_dir, self.original_link_is_in_wheel_cache, ) install_wheel( self.name, self.local_file_path, scheme=scheme, req_description=str(self.req), pycompile=pycompile, warn_script_location=warn_script_location, direct_url=direct_url, ) self.install_succeeded = True return # TODO: Why don't we do this for editable installs? # Extend the list of global and install options passed on to # the setup.py call with the ones from the requirements file. # Options specified in requirements file override those # specified on the command line, since the last option given # to setup.py is the one that is used. global_options = list(global_options) + self.global_options install_options = list(install_options) + self.install_options try: success = install_legacy( install_options=install_options, global_options=global_options, root=root, home=home, prefix=prefix, use_user_site=use_user_site, pycompile=pycompile, scheme=scheme, setup_py_path=self.setup_py_path, isolated=self.isolated, req_name=self.name, build_env=self.build_env, unpacked_source_directory=self.unpacked_source_directory, req_description=str(self.req), ) except LegacyInstallFailure as exc: self.install_succeeded = False six.reraise(*exc.parent) except Exception: self.install_succeeded = True raise self.install_succeeded = success
def _get_scheme_dict(*args, **kwargs): scheme = get_scheme(*args, **kwargs) return {k: getattr(scheme, k) for k in SCHEME_KEYS}
def install( self, install_options, # type: List[str] global_options=None, # type: Optional[Sequence[str]] root=None, # type: Optional[str] home=None, # type: Optional[str] prefix=None, # type: Optional[str] warn_script_location=True, # type: bool use_user_site=False, # type: bool pycompile=True # type: bool ): # type: (...) -> None scheme = get_scheme( self.name, user=use_user_site, home=home, root=root, isolated=self.isolated, prefix=prefix, ) global_options = global_options if global_options is not None else [] if self.editable: install_editable_legacy( install_options, global_options, prefix=prefix, home=home, use_user_site=use_user_site, name=self.name, setup_py_path=self.setup_py_path, isolated=self.isolated, build_env=self.build_env, unpacked_source_directory=self.unpacked_source_directory, ) self.install_succeeded = True return if self.is_wheel: assert self.local_file_path install_wheel( self.name, self.local_file_path, scheme=scheme, req_description=str(self.req), pycompile=pycompile, warn_script_location=warn_script_location, ) self.install_succeeded = True return install_legacy( self, install_options=install_options, global_options=global_options, root=root, home=home, prefix=prefix, use_user_site=use_user_site, pycompile=pycompile, scheme=scheme, )
def install( self, install_options, # type: List[str] global_options=None, # type: Optional[Sequence[str]] root=None, # type: Optional[str] home=None, # type: Optional[str] prefix=None, # type: Optional[str] warn_script_location=True, # type: bool use_user_site=False, # type: bool pycompile=True # type: bool ): # type: (...) -> None scheme = get_scheme( name, user=use_user_site, home=home, root=root, isolated=isolated, prefix=prefix, ) global_options = global_options if global_options is not None else [] if editable: install_editable_legacy( install_options, global_options, prefix=prefix, home=home, use_user_site=use_user_site, name=name, setup_py_path=setup_py_path, isolated=isolated, build_env=build_env, unpacked_source_directory=unpacked_source_directory, ) install_succeeded = True return if is_wheel: assert local_file_path direct_url = None if original_link: direct_url = direct_url_from_link( original_link, source_dir, original_link_is_in_wheel_cache, ) install_wheel( name, local_file_path, scheme=scheme, req_description=str(req), pycompile=pycompile, warn_script_location=warn_script_location, direct_url=direct_url, requested=user_supplied, ) install_succeeded = True return # TODO: Why don't we do this for editable installs? # Extend the list of global and install options passed on to # the setup.py call with the ones from the requirements file. # Options specified in requirements file override those # specified on the command line, since the last option given # to setup.py is the one that is used. global_options = list(global_options) + global_options install_options = list(install_options) + install_options try: success = install_legacy( install_options=install_options, global_options=global_options, root=root, home=home, prefix=prefix, use_user_site=use_user_site, pycompile=pycompile, scheme=scheme, setup_py_path=setup_py_path, isolated=isolated, req_name=name, build_env=build_env, unpacked_source_directory=unpacked_source_directory, req_description=str(req), ) except LegacyInstallFailure as exc: install_succeeded = False six.reraise(*exc.parent) except Exception: install_succeeded = True raise install_succeeded = success if success and legacy_install_reason == 8368: deprecated( reason=( "{} was installed using the legacy 'setup.py install' " "method, because a wheel could not be built for it.". format(name) ), replacement="to fix the wheel build issue reported above", gone_in="21.0", issue=8368, )
def install( self, install_options: List[str], global_options: Optional[Sequence[str]] = None, root: Optional[str] = None, home: Optional[str] = None, prefix: Optional[str] = None, warn_script_location: bool = True, use_user_site: bool = False, pycompile: bool = True, ) -> None: scheme = get_scheme( self.name, user=use_user_site, home=home, root=root, isolated=self.isolated, prefix=prefix, ) global_options = global_options if global_options is not None else [] if self.editable and not self.is_wheel: install_editable_legacy( install_options, global_options, prefix=prefix, home=home, use_user_site=use_user_site, name=self.name, setup_py_path=self.setup_py_path, isolated=self.isolated, build_env=self.build_env, unpacked_source_directory=self.unpacked_source_directory, ) self.install_succeeded = True return if self.is_wheel: assert self.local_file_path direct_url = None # TODO this can be refactored to direct_url = self.download_info if self.editable: direct_url = direct_url_for_editable( self.unpacked_source_directory) elif self.original_link: direct_url = direct_url_from_link( self.original_link, self.source_dir, self.original_link_is_in_wheel_cache, ) install_wheel( self.name, self.local_file_path, scheme=scheme, req_description=str(self.req), pycompile=pycompile, warn_script_location=warn_script_location, direct_url=direct_url, requested=self.user_supplied, ) self.install_succeeded = True return # TODO: Why don't we do this for editable installs? # Extend the list of global and install options passed on to # the setup.py call with the ones from the requirements file. # Options specified in requirements file override those # specified on the command line, since the last option given # to setup.py is the one that is used. global_options = list(global_options) + self.global_options install_options = list(install_options) + self.install_options try: success = install_legacy( install_options=install_options, global_options=global_options, root=root, home=home, prefix=prefix, use_user_site=use_user_site, pycompile=pycompile, scheme=scheme, setup_py_path=self.setup_py_path, isolated=self.isolated, req_name=self.name, build_env=self.build_env, unpacked_source_directory=self.unpacked_source_directory, req_description=str(self.req), ) except LegacyInstallFailure as exc: self.install_succeeded = False raise exc except Exception: self.install_succeeded = True raise self.install_succeeded = success if success and self.legacy_install_reason == 8368: deprecated( reason=("{} was installed using the legacy 'setup.py install' " "method, because a wheel could not be built for it.". format(self.name)), replacement="to fix the wheel build issue reported above", gone_in=None, issue=8368, )
def __wheelInstall(self, name: str, filewhl: str) -> bool: """ Install .whl package Parameters ---------- name : str name of package filewhl : str path of package file Returns ------- bool whether the package is installed >>> __wheelInstall("package", "/tmp/packsX/package.whl") False >>> __wheelInstall("package", "/tmp/packsX/package.whl") True """ try: pack = pr.get_distribution(name) except Exception: scheme = get_scheme( name, user=False, home=None, root=None, prefix=None, ) install_wheel( name, filewhl, scheme=scheme, req_description=name, pycompile=True, ) return False if self.__u: removeDependency(f"{pack.key}=={pack.version}") scheme = get_scheme( name, user=False, home=None, root=None, prefix=None, ) install_wheel( name, filewhl, scheme=scheme, req_description=name, pycompile=True, ) return False return True
def _get_scheme_dict(*args: Any, **kwargs: Any) -> Dict[str, str]: scheme = get_scheme(*args, **kwargs) return {k: getattr(scheme, k) for k in SCHEME_KEYS}