Пример #1
0
def install_given_reqs(
        requirements,  # type: List[InstallRequirement]
        install_options,  # type: List[str]
        global_options,  # type: Sequence[str]
        root,  # type: Optional[str]
        home,  # type: Optional[str]
        prefix,  # type: Optional[str]
        warn_script_location,  # type: bool
        use_user_site,  # type: bool
        pycompile,  # type: bool
):
    # type: (...) -> List[InstallationResult]
    """
    Install everything in the given list.

    (to be called after having downloaded and unpacked the packages)
    """
    to_install = collections.OrderedDict(_validate_requirements(requirements))

    if to_install:
        logger.info(
            'Installing collected packages: %s',
            ', '.join(to_install.keys()),
        )

    installed = []

    with indent_log():
        for req_name, requirement in to_install.items():
            if requirement.should_reinstall:
                logger.info('Attempting uninstall: %s', req_name)
                with indent_log():
                    uninstalled_pathset = requirement.uninstall(
                        auto_confirm=True)
            else:
                uninstalled_pathset = None

            try:
                requirement.install(
                    install_options,
                    global_options,
                    root=root,
                    home=home,
                    prefix=prefix,
                    warn_script_location=warn_script_location,
                    use_user_site=use_user_site,
                    pycompile=pycompile,
                )
            except Exception:
                # if install did not succeed, rollback previous uninstall
                if uninstalled_pathset and not requirement.install_succeeded:
                    uninstalled_pathset.rollback()
                raise
            else:
                if uninstalled_pathset and requirement.install_succeeded:
                    uninstalled_pathset.commit()

            installed.append(InstallationResult(req_name))

    return installed
Пример #2
0
    def prepare_editable_requirement(
            self,
            req,  # type: InstallRequirement
    ):
        # type: (...) -> Distribution
        """Prepare an editable requirement
        """
        assert req.editable, "cannot prepare a non-editable req as editable"

        logger.info('Obtaining %s', req)

        with indent_log():
            if self.require_hashes:
                raise InstallationError(
                    'The editable requirement {} cannot be installed when '
                    'requiring hashes, because there is no single file to '
                    'hash.'.format(req))
            req.ensure_has_source_dir(self.src_dir)
            req.update_editable(not self._download_should_save)

            dist = _get_prepared_distribution(
                req,
                self.req_tracker,
                self.finder,
                self.build_isolation,
            )

            if self._download_should_save:
                req.archive(self.download_dir)
            req.check_if_exists(self.use_user_site)

        return dist
Пример #3
0
def install_editable(
        install_options,  # type: List[str]
        global_options,  # type: Sequence[str]
        prefix,  # type: Optional[str]
        home,  # type: Optional[str]
        use_user_site,  # type: bool
        name,  # type: str
        setup_py_path,  # type: str
        isolated,  # type: bool
        build_env,  # type: BuildEnvironment
        unpacked_source_directory,  # type: str
):
    # type: (...) -> None
    """Install a package in editable mode. Most arguments are pass-through
    to setuptools.
    """
    logger.info('Running setup.py develop for %s', name)

    args = make_setuptools_develop_args(
        setup_py_path,
        global_options=global_options,
        install_options=install_options,
        no_user_config=isolated,
        prefix=prefix,
        home=home,
        use_user_site=use_user_site,
    )

    with indent_log():
        with build_env:
            call_subprocess(
                args,
                cwd=unpacked_source_directory,
            )
Пример #4
0
def show_tags(options):
    # type: (Values) -> None
    tag_limit = 10

    target_python = make_target_python(options)
    tags = target_python.get_tags()

    # Display the target options that were explicitly provided.
    formatted_target = target_python.format_given()
    suffix = ''
    if formatted_target:
        suffix = ' (target: {})'.format(formatted_target)

    msg = 'Compatible tags: {}{}'.format(len(tags), suffix)
    logger.info(msg)

    if options.verbose < 1 and len(tags) > tag_limit:
        tags_limited = True
        tags = tags[:tag_limit]
    else:
        tags_limited = False

    with indent_log():
        for tag in tags:
            logger.info(str(tag))

        if tags_limited:
            msg = (
                '...\n'
                '[First {tag_limit} tags shown. Pass --verbose to show all.]'
            ).format(tag_limit=tag_limit)
            logger.info(msg)
Пример #5
0
def show_vendor_versions():
    # type: () -> None
    logger.info('vendored library versions:')

    vendor_txt_versions = create_vendor_txt_map()
    with indent_log():
        show_actual_vendor_versions(vendor_txt_versions)
Пример #6
0
 def print_config_file_values(self, variant):
     # type: (Kind) -> None
     """Get key-value pairs from the file of a variant"""
     for name, value in self.configuration.\
             get_values_in_config(variant).items():
         with indent_log():
             write_output("%s: %s", name, value)
Пример #7
0
    def remove(self, auto_confirm=False, verbose=False):
        # type: (bool, bool) -> None
        """Remove paths in ``self.paths`` with confirmation (unless
        ``auto_confirm`` is True)."""

        if not self.paths:
            logger.info(
                "Can't uninstall '%s'. No files were found to uninstall.",
                self.dist.project_name,
            )
            return

        dist_name_version = (self.dist.project_name + "-" + self.dist.version)
        logger.info('Uninstalling %s:', dist_name_version)

        with indent_log():
            if auto_confirm or self._allowed_to_proceed(verbose):
                moved = self._moved_paths

                for_rename = compress_for_rename(self.paths)

                for path in sorted(compact(for_rename)):
                    moved.stash(path)
                    logger.debug('Removing file or directory %s', path)

                for pth in self.pth.values():
                    pth.remove()

                logger.info('Successfully uninstalled %s', dist_name_version)
Пример #8
0
 def print_env_var_values(self):
     # type: () -> None
     """Get key-values pairs present as environment variables"""
     write_output("%s:", 'env_var')
     with indent_log():
         for key, value in sorted(self.configuration.get_environ_vars()):
             env_var = 'PIP_{}'.format(key.upper())
             write_output("%s=%r", env_var, value)
Пример #9
0
        def _display(msg, paths):
            # type: (str, Iterable[str]) -> None
            if not paths:
                return

            logger.info(msg)
            with indent_log():
                for path in sorted(compact(paths)):
                    logger.info(path)
Пример #10
0
    def _prepare_linked_requirement(self, req, parallel_builds):
        # type: (InstallRequirement, bool) -> Distribution
        assert req.link
        link = req.link
        download_dir = self._get_download_dir(link)

        with indent_log():
            self._ensure_link_req_src_dir(req, download_dir, parallel_builds)
            hashes = self._get_linked_req_hashes(req)
            if link.url not in self._downloaded:
                try:
                    local_file = unpack_url(
                        link,
                        req.source_dir,
                        self._download,
                        download_dir,
                        hashes,
                    )
                except NetworkConnectionError as exc:
                    raise InstallationError(
                        'Could not install requirement {} because of HTTP '
                        'error {} for URL {}'.format(req, exc, link))
            else:
                file_path, content_type = self._downloaded[link.url]
                if hashes:
                    hashes.check_against_path(file_path)
                local_file = File(file_path, content_type)

            # For use in later processing, preserve the file path on the
            # requirement.
            if local_file:
                req.local_file_path = local_file.path

            dist = _get_prepared_distribution(
                req,
                self.req_tracker,
                self.finder,
                self.build_isolation,
            )

            if download_dir:
                if link.is_existing_dir():
                    logger.info('Link is a directory, ignoring download_dir')
                elif local_file:
                    download_location = os.path.join(download_dir,
                                                     link.filename)
                    if not os.path.exists(download_location):
                        shutil.copy(local_file.path, download_location)
                        download_path = display_path(download_location)
                        logger.info('Saved %s', download_path)

            if self._download_should_save:
                # Make a .zip of the source_dir we already created.
                if link.is_vcs:
                    req.archive(self.download_dir)
        return dist
Пример #11
0
def show_sys_implementation():
    # type: () -> None
    logger.info('sys.implementation:')
    if hasattr(sys, 'implementation'):
        implementation = sys.implementation  # type: ignore
        implementation_name = implementation.name
    else:
        implementation_name = ''

    with indent_log():
        show_value('name', implementation_name)
Пример #12
0
 def prepare_linked_requirement(self, req, parallel_builds=False):
     # type: (InstallRequirement, bool) -> Distribution
     """Prepare a requirement to be obtained from req.link."""
     assert req.link
     link = req.link
     self._log_preparing_link(req)
     with indent_log():
         wheel_dist = self._fetch_metadata_using_lazy_wheel(link)
     if wheel_dist is not None:
         req.needs_more_preparation = True
         return wheel_dist
     return self._prepare_linked_requirement(req, parallel_builds)
Пример #13
0
def build(
        requirements,  # type: Iterable[InstallRequirement]
        wheel_cache,  # type: WheelCache
        build_options,  # type: List[str]
        global_options,  # type: List[str]
):
    # type: (...) -> BuildResult
    """Build wheels.

    :return: The list of InstallRequirement that succeeded to build and
        the list of InstallRequirement that failed to build.
    """
    if not requirements:
        return [], []

    # Build the wheels.
    logger.info(
        'Building wheels for collected packages: %s',
        ', '.join(req.name for req in requirements),  # type: ignore
    )

    with indent_log():
        build_successes, build_failures = [], []
        for req in requirements:
            cache_dir = _get_cache_dir(req, wheel_cache)
            wheel_file = _build_one(req, cache_dir, build_options,
                                    global_options)
            if wheel_file:
                # Update the link for this.
                req.link = Link(path_to_url(wheel_file))
                req.local_file_path = req.link.file_path
                assert req.link.is_wheel
                build_successes.append(req)
            else:
                build_failures.append(req)

    # notify success/failure
    if build_successes:
        logger.info(
            'Successfully built %s',
            ' '.join([req.name for req in build_successes]),  # type: ignore
        )
    if build_failures:
        logger.info(
            'Failed to build %s',
            ' '.join([req.name for req in build_failures]),  # type: ignore
        )
    # Return a list of requirements that failed to build
    return build_successes, build_failures
Пример #14
0
    def list_config_values(self, options, args):
        # type: (Values, List[str]) -> None
        """List config key-value pairs across different config files"""
        self._get_n_args(args, "debug", n=0)

        self.print_env_var_values()
        # Iterate over config files and print if they exist, and the
        # key-value pairs present in them if they do
        for variant, files in sorted(self.configuration.iter_config_files()):
            write_output("%s:", variant)
            for fname in files:
                with indent_log():
                    file_exists = os.path.exists(fname)
                    write_output("%s, exists: %r", fname, file_exists)
                    if file_exists:
                        self.print_config_file_values(variant)
Пример #15
0
    def process_project_url(self, project_url, link_evaluator):
        # type: (Link, LinkEvaluator) -> List[InstallationCandidate]
        logger.debug(
            'Fetching project page and analyzing links: %s', project_url,
        )
        html_page = self._link_collector.fetch_page(project_url)
        if html_page is None:
            return []

        page_links = list(parse_links(html_page))

        with indent_log():
            package_links = self.evaluate_links(
                link_evaluator,
                links=page_links,
            )

        return package_links
Пример #16
0
    def prepare_metadata(self):
        # type: () -> None
        """Ensure that project metadata is available.

        Under PEP 517, call the backend hook to prepare the metadata.
        Under legacy processing, call setup.py egg-info.
        """
        assert self.source_dir

        with indent_log():
            self.metadata_directory = self._generate_metadata()

        # Act on the newly generated metadata, based on the name and version.
        if not self.name:
            self._set_requirement()
        else:
            self.warn_on_mismatching_name()

        self.assert_source_matches_version()
Пример #17
0
    def export(self, location, url):
        # type: (str, HiddenText) -> None
        """Export the svn repository at the url to the destination location"""
        url, rev_options = self.get_url_rev_options(url)

        logger.info('Exporting svn repository %s to %s', url, location)
        with indent_log():
            if os.path.exists(location):
                # Subversion doesn't like to check out over an existing
                # directory --force fixes this, but was only added in svn 1.5
                rmtree(location)
            cmd_args = make_command(
                'export',
                self.get_remote_call_options(),
                rev_options.to_args(),
                url,
                location,
            )
            self.run_command(cmd_args)
Пример #18
0
 def prepare_installed_requirement(
         self,
         req,  # type: InstallRequirement
         skip_reason  # type: str
 ):
     # type: (...) -> Distribution
     """Prepare an already-installed requirement
     """
     assert req.satisfied_by, "req should have been satisfied but isn't"
     assert skip_reason is not None, (
         "did not get skip reason skipped but req.satisfied_by "
         "is set to {}".format(req.satisfied_by))
     logger.info('Requirement %s: %s (%s)', skip_reason, req,
                 req.satisfied_by.version)
     with indent_log():
         if self.require_hashes:
             logger.debug(
                 'Since it is already installed, we are trusting this '
                 'package without checking its hash. To ensure a '
                 'completely repeatable environment, install into an '
                 'empty virtualenv.')
         return InstalledDistribution(req).get_pkg_resources_distribution()
Пример #19
0
def install(
        install_options,  # type: List[str]
        global_options,  # type: Sequence[str]
        root,  # type: Optional[str]
        home,  # type: Optional[str]
        prefix,  # type: Optional[str]
        use_user_site,  # type: bool
        pycompile,  # type: bool
        scheme,  # type: Scheme
        setup_py_path,  # type: str
        isolated,  # type: bool
        req_name,  # type: str
        build_env,  # type: BuildEnvironment
        unpacked_source_directory,  # type: str
        req_description,  # type: str
):
    # type: (...) -> bool

    header_dir = scheme.headers

    with TempDirectory(kind="record") as temp_dir:
        try:
            record_filename = os.path.join(temp_dir.path, 'install-record.txt')
            install_args = make_setuptools_install_args(
                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=isolated,
                pycompile=pycompile,
            )

            runner = runner_with_spinner_message(
                "Running setup.py install for {}".format(req_name))
            with indent_log(), build_env:
                runner(
                    cmd=install_args,
                    cwd=unpacked_source_directory,
                )

            if not os.path.exists(record_filename):
                logger.debug('Record file %s not found', record_filename)
                # Signal to the caller that we didn't install the new package
                return False

        except Exception:
            # Signal to the caller that we didn't install the new package
            raise LegacyInstallFailure

        # At this point, we have successfully installed the requirement.

        # We intentionally do not use any encoding to read the file because
        # setuptools writes the file using distutils.file_util.write_file,
        # which does not specify an encoding.
        with open(record_filename) as f:
            record_lines = f.read().splitlines()

    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)

    for line in record_lines:
        directory = os.path.dirname(line)
        if directory.endswith('.egg-info'):
            egg_info_dir = prepend_root(directory)
            break
    else:
        message = ("{} did not indicate that it installed an "
                   ".egg-info directory. Only setup.py projects "
                   "generating .egg-info directories are supported."
                   ).format(req_description)
        raise InstallationError(message)

    new_lines = []
    for line in record_lines:
        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')

    return True
Пример #20
0
    def _resolve_one(
            self,
            requirement_set,  # type: RequirementSet
            req_to_install,  # type: InstallRequirement
    ):
        # type: (...) -> List[InstallRequirement]
        """Prepare a single requirements file.

        :return: A list of additional InstallRequirements to also install.
        """
        # Tell user what we are doing for this requirement:
        # obtain (editable), skipping, processing (local url), collecting
        # (remote url or package name)
        if req_to_install.constraint or req_to_install.prepared:
            return []

        req_to_install.prepared = True

        # Parse and return dependencies
        dist = self._get_dist_for(req_to_install)
        # This will raise UnsupportedPythonVersion if the given Python
        # version isn't compatible with the distribution's Requires-Python.
        _check_dist_requires_python(
            dist,
            version_info=self._py_version_info,
            ignore_requires_python=self.ignore_requires_python,
        )

        more_reqs = []  # type: List[InstallRequirement]

        def add_req(subreq, extras_requested):
            sub_install_req = self._make_install_req(
                str(subreq),
                req_to_install,
            )
            parent_req_name = req_to_install.name
            to_scan_again, add_to_parent = requirement_set.add_requirement(
                sub_install_req,
                parent_req_name=parent_req_name,
                extras_requested=extras_requested,
            )
            if parent_req_name and add_to_parent:
                self._discovered_dependencies[parent_req_name].append(
                    add_to_parent)
            more_reqs.extend(to_scan_again)

        with indent_log():
            # We add req_to_install before its dependencies, so that we
            # can refer to it when adding dependencies.
            if not requirement_set.has_requirement(req_to_install.name):
                # 'unnamed' requirements will get added here
                # 'unnamed' requirements can only come from being directly
                # provided by the user.
                assert req_to_install.user_supplied
                requirement_set.add_requirement(
                    req_to_install,
                    parent_req_name=None,
                )

            if not self.ignore_dependencies:
                if req_to_install.extras:
                    logger.debug(
                        "Installing extra requirements: %r",
                        ','.join(req_to_install.extras),
                    )
                missing_requested = sorted(
                    set(req_to_install.extras) - set(dist.extras))
                for missing in missing_requested:
                    logger.warning("%s does not provide the extra '%s'", dist,
                                   missing)

                available_requested = sorted(
                    set(dist.extras) & set(req_to_install.extras))
                for subreq in dist.requires(available_requested):
                    add_req(subreq, extras_requested=available_requested)

        return more_reqs