Esempio n. 1
0
 def test_closes_stdin(self) -> None:
     with pytest.raises(InstallationSubprocessError):
         call_subprocess(
             [sys.executable, "-c", "input()"],
             show_stdout=True,
             command_desc="stdin reader",
         )
Esempio n. 2
0
    def install_editable(
        self,
        install_options,  # type: List[str]
        global_options=(),  # type: Sequence[str]
        prefix=None  # type: Optional[str]
    ):
        # type: (...) -> None
        logger.info('Running setup.py develop for %s', self.name)

        if prefix:
            prefix_param = ['--prefix={}'.format(prefix)]
            install_options = list(install_options) + prefix_param
        base_cmd = make_setuptools_shim_args(
            self.setup_py_path,
            global_options=global_options,
            no_user_config=self.isolated
        )
        with indent_log():
            with self.build_env:
                call_subprocess(
                    base_cmd +
                    ['develop', '--no-deps'] +
                    list(install_options),
                    cwd=self.unpacked_source_directory,
                )

        self.install_succeeded = True
Esempio n. 3
0
    def test_spinner_finish(
        self,
        exit_status: int,
        show_stdout: bool,
        extra_ok_returncodes: Optional[Tuple[int, ...]],
        log_level: int,
        caplog: pytest.LogCaptureFixture,
        expected: Tuple[Optional[Type[Exception]], Optional[str], int],
    ) -> None:
        """
        Test that the spinner finishes correctly.
        """
        expected_exc_type = expected[0]
        expected_final_status = expected[1]
        expected_spin_count = expected[2]

        command = f'print("Hello"); print("world"); exit({exit_status})'
        args, spinner = self.prepare_call(caplog, log_level, command=command)
        exc_type: Optional[Type[Exception]]
        try:
            call_subprocess(
                args,
                show_stdout=show_stdout,
                extra_ok_returncodes=extra_ok_returncodes,
                spinner=spinner,
            )
        except Exception as exc:
            exc_type = type(exc)
        else:
            exc_type = None

        assert exc_type == expected_exc_type
        assert spinner.final_status == expected_final_status
        assert spinner.spin_count == expected_spin_count
Esempio n. 4
0
def generate_metadata(
    build_env: BuildEnvironment,
    setup_py_path: str,
    source_dir: str,
    isolated: bool,
    details: str,
) -> str:
    """Generate metadata using setup.py-based defacto mechanisms.

    Returns the generated metadata directory.
    """
    logger.debug(
        'Running setup.py (path:%s) egg_info for package %s',
        setup_py_path, details,
    )

    egg_info_dir = TempDirectory(
        kind="pip-egg-info", globally_managed=True
    ).path

    args = make_setuptools_egg_info_args(
        setup_py_path,
        egg_info_dir=egg_info_dir,
        no_user_config=isolated,
    )

    with build_env:
        call_subprocess(
            args,
            cwd=source_dir,
            command_desc='python setup.py egg_info',
        )

    # Return the .egg-info directory.
    return _find_egg_info(egg_info_dir)
Esempio n. 5
0
def install_editable(
    install_options: List[str],
    global_options: Sequence[str],
    prefix: Optional[str],
    home: Optional[str],
    use_user_site: bool,
    name: str,
    setup_py_path: str,
    isolated: bool,
    build_env: BuildEnvironment,
    unpacked_source_directory: str,
) -> 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,
                command_desc="python setup.py develop",
                cwd=unpacked_source_directory,
            )
Esempio n. 6
0
    def install_editable(
        self,
        install_options,  # type: List[str]
        global_options=(),  # type: Sequence[str]
        prefix=None  # type: Optional[str]
    ):
        # type: (...) -> None
        logger.info('Running setup.py develop for %s', self.name)

        args = make_setuptools_develop_args(
            self.setup_py_path,
            global_options=global_options,
            install_options=install_options,
            no_user_config=self.isolated,
            prefix=prefix,
        )

        with indent_log():
            with self.build_env:
                call_subprocess(
                    args,
                    cwd=self.unpacked_source_directory,
                )

        self.install_succeeded = True
Esempio n. 7
0
    def test_spinner_finish(
        self,
        exit_status,
        show_stdout,
        extra_ok_returncodes,
        log_level,
        caplog,
        expected,
    ):
        """
        Test that the spinner finishes correctly.
        """
        expected_exc_type = expected[0]
        expected_final_status = expected[1]
        expected_spin_count = expected[2]

        command = (f'print("Hello"); print("world"); exit({exit_status})')
        args, spinner = self.prepare_call(caplog, log_level, command=command)
        try:
            call_subprocess(
                args,
                show_stdout=show_stdout,
                extra_ok_returncodes=extra_ok_returncodes,
                spinner=spinner,
            )
        except Exception as exc:
            exc_type = type(exc)
        else:
            exc_type = None

        assert exc_type == expected_exc_type
        assert spinner.final_status == expected_final_status
        assert spinner.spin_count == expected_spin_count
Esempio n. 8
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,
            )
Esempio n. 9
0
    def test_info_logging__subprocess_error(self, capfd, caplog):
        """
        Test INFO logging of a subprocess with an error (and without passing
        show_stdout=True).
        """
        log_level = INFO
        command = 'print("Hello"); print("world"); exit("fail")'
        args, spinner = self.prepare_call(caplog, log_level, command=command)

        with pytest.raises(InstallationSubprocessError) as exc:
            call_subprocess(args, spinner=spinner)
        result = None
        exc_message = str(exc.value)
        assert exc_message.startswith(
            'Command errored out with exit status 1: ')
        assert exc_message.endswith('Check the logs for full command output.')

        expected = (None, [
            ('pip.subprocessor', ERROR, 'Complete output (3 lines):\n'),
        ])
        # The spinner should spin three times in this case since the
        # subprocess output isn't being written to the console.
        self.check_result(
            capfd,
            caplog,
            log_level,
            spinner,
            result,
            expected,
            expected_spinner=(3, 'error'),
        )

        # Do some further checking on the captured log records to confirm
        # that the subprocess output was logged.
        last_record = caplog.record_tuples[-1]
        last_message = last_record[2]
        lines = last_message.splitlines()

        # We have to sort before comparing the lines because we can't
        # guarantee the order in which stdout and stderr will appear.
        # For example, we observed the stderr lines coming before stdout
        # in CI for PyPy 2.7 even though stdout happens first chronologically.
        actual = sorted(lines)
        # Test the "command" line separately because we can't test an
        # exact match.
        command_line = actual.pop(1)
        assert actual == [
            '     cwd: None',
            '----------------------------------------',
            'Command errored out with exit status 1:',
            'Complete output (3 lines):',
            'Hello',
            'fail',
            'world',
        ], f'lines: {actual}'  # Show the full output on failure.

        assert command_line.startswith(' command: ')
        assert command_line.endswith('print("world"); exit("fail")\'')
Esempio n. 10
0
    def _install_requirements(
        pip_runnable: str,
        finder: "PackageFinder",
        requirements: Iterable[str],
        prefix: _Prefix,
        *,
        kind: str,
    ) -> None:
        args: List[str] = [
            sys.executable,
            pip_runnable,
            "install",
            "--ignore-installed",
            "--no-user",
            "--prefix",
            prefix.path,
            "--no-warn-script-location",
        ]
        if logger.getEffectiveLevel() <= logging.DEBUG:
            args.append("-v")
        for format_control in ("no_binary", "only_binary"):
            formats = getattr(finder.format_control, format_control)
            args.extend(
                (
                    "--" + format_control.replace("_", "-"),
                    ",".join(sorted(formats or {":none:"})),
                )
            )

        index_urls = finder.index_urls
        if index_urls:
            args.extend(["-i", index_urls[0]])
            for extra_index in index_urls[1:]:
                args.extend(["--extra-index-url", extra_index])
        else:
            args.append("--no-index")
        for link in finder.find_links:
            args.extend(["--find-links", link])

        for host in finder.trusted_hosts:
            args.extend(["--trusted-host", host])
        if finder.allow_all_prereleases:
            args.append("--pre")
        if finder.prefer_binary:
            args.append("--prefer-binary")
        args.append("--")
        args.extend(requirements)
        extra_environ = {"_PIP_STANDALONE_CERT": where()}
        with open_spinner(f"Installing {kind}") as spinner:
            call_subprocess(
                args,
                command_desc=f"pip subprocess to install {kind}",
                spinner=spinner,
                extra_environ=extra_environ,
            )
Esempio n. 11
0
    def _clean_one(self, req):
        base_args = self._base_setup_args(req)

        logger.info('Running setup.py clean for %s', req.name)
        clean_args = base_args + ['clean', '--all']
        try:
            call_subprocess(clean_args, cwd=req.source_dir)
            return True
        except Exception:
            logger.error('Failed cleaning build dir for %s', req.name)
            return False
Esempio n. 12
0
def _clean_one_legacy(req, global_options):
    # type: (InstallRequirement, List[str]) -> bool
    clean_args = make_setuptools_clean_args(req.setup_py_path,
                                            global_options=global_options)

    logger.info("Running setup.py clean for %s", req.name)
    try:
        call_subprocess(clean_args, cwd=req.source_dir)
        return True
    except Exception:
        logger.error("Failed cleaning build dir for %s", req.name)
        return False
Esempio n. 13
0
    def install_requirements(
            self,
            finder,  # type: PackageFinder
            requirements,  # type: Iterable[str]
            prefix_as_string,  # type: str
            message,  # type: str
    ):
        # type: (...) -> None
        prefix = self._prefixes[prefix_as_string]
        assert not prefix.setup
        prefix.setup = True
        if not requirements:
            return
        args = [
            sys.executable,
            os.path.dirname(pip_location),
            "install",
            "--ignore-installed",
            "--no-user",
            "--prefix",
            prefix.path,
            "--no-warn-script-location",
        ]  # type: List[str]
        if logger.getEffectiveLevel() <= logging.DEBUG:
            args.append("-v")
        for format_control in ("no_binary", "only_binary"):
            formats = getattr(finder.format_control, format_control)
            args.extend((
                "--" + format_control.replace("_", "-"),
                ",".join(sorted(formats or {":none:"})),
            ))

        index_urls = finder.index_urls
        if index_urls:
            args.extend(["-i", index_urls[0]])
            for extra_index in index_urls[1:]:
                args.extend(["--extra-index-url", extra_index])
        else:
            args.append("--no-index")
        for link in finder.find_links:
            args.extend(["--find-links", link])

        for host in finder.trusted_hosts:
            args.extend(["--trusted-host", host])
        if finder.allow_all_prereleases:
            args.append("--pre")
        if finder.prefer_binary:
            args.append("--prefer-binary")
        args.append("--")
        args.extend(requirements)
        with open_spinner(message) as spinner:
            call_subprocess(args, spinner=spinner)
Esempio n. 14
0
    def _clean_one(self, req):
        clean_args = make_setuptools_clean_args(
            req.setup_py_path,
            global_options=self.global_options,
        )

        logger.info('Running setup.py clean for %s', req.name)
        try:
            call_subprocess(clean_args, cwd=req.source_dir)
            return True
        except Exception:
            logger.error('Failed cleaning build dir for %s', req.name)
            return False
Esempio n. 15
0
    def install_requirements(
            self,
            finder,  # type: PackageFinder
            requirements,  # type: Iterable[str]
            prefix_as_string,  # type: str
            message  # type: str
    ):
        # type: (...) -> None
        prefix = self._prefixes[prefix_as_string]
        assert not prefix.setup
        prefix.setup = True
        if not requirements:
            return
        args = [
            sys.executable,
            os.path.dirname(pip_location),
            'install',
            '--ignore-installed',
            '--no-user',
            '--prefix',
            prefix.path,
            '--no-warn-script-location',
        ]  # type: List[str]
        if logger.getEffectiveLevel() <= logging.DEBUG:
            args.append('-v')
        for format_control in ('no_binary', 'only_binary'):
            formats = getattr(finder.format_control, format_control)
            args.extend(('--' + format_control.replace('_', '-'),
                         ','.join(sorted(formats or {':none:'}))))

        index_urls = finder.index_urls
        if index_urls:
            args.extend(['-i', index_urls[0]])
            for extra_index in index_urls[1:]:
                args.extend(['--extra-index-url', extra_index])
        else:
            args.append('--no-index')
        for link in finder.find_links:
            args.extend(['--find-links', link])

        for host in finder.trusted_hosts:
            args.extend(['--trusted-host', host])
        if finder.allow_all_prereleases:
            args.append('--pre')
        if finder.prefer_binary:
            args.append('--prefer-binary')
        args.append('--')
        args.extend(requirements)
        with open_spinner(message) as spinner:
            call_subprocess(args, spinner=spinner)
Esempio n. 16
0
def test_unicode_decode_error(caplog):
    if locale.getpreferredencoding() != "UTF-8":
        pytest.skip("locale.getpreferredencoding() is not UTF-8")
    caplog.set_level(INFO)
    call_subprocess([
        sys.executable,
        "-c",
        "import sys; sys.stdout.buffer.write(b'\\xff')",
    ],
                    show_stdout=True)

    assert len(caplog.records) == 2
    # First log record is "Running command ..."
    assert caplog.record_tuples[1] == ("pip.subprocessor", INFO, "\\xff")
Esempio n. 17
0
    def test_info_logging__subprocess_error(
            self, capfd: pytest.CaptureFixture[str],
            caplog: pytest.LogCaptureFixture) -> None:
        """
        Test INFO logging of a subprocess with an error (and without passing
        show_stdout=True).
        """
        log_level = INFO
        command = 'print("Hello"); print("world"); exit("fail")'
        args, spinner = self.prepare_call(caplog, log_level, command=command)

        with pytest.raises(InstallationSubprocessError) as exc:
            call_subprocess(
                args,
                command_desc="test info logging with subprocess error",
                spinner=spinner,
            )
        result = None
        exception = exc.value
        assert exception.reference == "subprocess-exited-with-error"
        assert "exit code: 1" in exception.message
        assert exception.note_stmt
        assert "not a problem with pip" in exception.note_stmt
        # Check that the process output is captured, and would be shown.
        assert exception.context
        assert "Hello\n" in exception.context
        assert "fail\n" in exception.context
        assert "world\n" in exception.context

        expected = (
            None,
            [
                # pytest's caplog overrides th formatter, which means that we
                # won't see the message formatted through our formatters.
                ("pip.subprocessor", ERROR, "[present-diagnostic]"),
            ],
        )
        # The spinner should spin three times in this case since the
        # subprocess output isn't being written to the console.
        self.check_result(
            capfd,
            caplog,
            log_level,
            spinner,
            result,
            expected,
            expected_spinner=(3, "error"),
        )
Esempio n. 18
0
    def test_info_logging(self, capfd: pytest.CaptureFixture[str],
                          caplog: pytest.LogCaptureFixture) -> None:
        """
        Test INFO logging (and without passing show_stdout=True).
        """
        log_level = INFO
        args, spinner = self.prepare_call(caplog, log_level)
        result = call_subprocess(
            args,
            command_desc="test info logging",
            spinner=spinner,
        )

        expected: Tuple[List[str], List[Tuple[str, int, str]]] = (
            ["Hello", "world"],
            [],
        )
        # The spinner should spin twice in this case since the subprocess
        # output isn't being written to the console.
        self.check_result(
            capfd,
            caplog,
            log_level,
            spinner,
            result,
            expected,
            expected_spinner=(2, "done"),
        )
Esempio n. 19
0
    def test_info_logging_with_show_stdout_true(
            self, capfd: pytest.CaptureFixture[str],
            caplog: pytest.LogCaptureFixture) -> None:
        """
        Test INFO logging with show_stdout=True.
        """
        log_level = INFO
        args, spinner = self.prepare_call(caplog, log_level)
        result = call_subprocess(args, spinner=spinner, show_stdout=True)

        expected = (
            ["Hello", "world"],
            [
                ("pip.subprocessor", INFO, "Running command "),
                ("pip.subprocessor", INFO, "Hello"),
                ("pip.subprocessor", INFO, "world"),
            ],
        )
        # The spinner shouldn't spin in this case since the subprocess
        # output is already being written to the console.
        self.check_result(
            capfd,
            caplog,
            log_level,
            spinner,
            result,
            expected,
            expected_spinner=(0, None),
        )
Esempio n. 20
0
    def test_debug_logging(self, capfd: pytest.CaptureFixture[str],
                           caplog: pytest.LogCaptureFixture) -> None:
        """
        Test DEBUG logging (and without passing show_stdout=True).
        """
        log_level = DEBUG
        args, spinner = self.prepare_call(caplog, log_level)
        result = call_subprocess(args, spinner=spinner)

        expected = (
            ["Hello", "world"],
            [
                ("pip.subprocessor", VERBOSE, "Running command "),
                ("pip.subprocessor", VERBOSE, "Hello"),
                ("pip.subprocessor", VERBOSE, "world"),
            ],
        )
        # The spinner shouldn't spin in this case since the subprocess
        # output is already being logged to the console.
        self.check_result(
            capfd,
            caplog,
            log_level,
            spinner,
            result,
            expected,
            expected_spinner=(0, None),
        )
Esempio n. 21
0
def test_call_subprocess_stdout_only(
    capfd: pytest.CaptureFixture[str],
    monkeypatch: pytest.MonkeyPatch,
    stdout_only: bool,
    expected: Tuple[str, ...],
) -> None:
    log = []
    monkeypatch.setattr(
        subprocess_logger,
        "log",
        lambda level, *args: log.append(args[0]),
    )
    out = call_subprocess(
        [
            sys.executable,
            "-c",
            "import sys; sys.stdout.write('out\\n'); sys.stderr.write('err\\n')",
        ],
        stdout_only=stdout_only,
    )
    assert out in expected
    captured = capfd.readouterr()
    assert captured.err == ""
    assert log == ["Running command %s", "out", "err"] or log == [
        "Running command %s",
        "err",
        "out",
    ]
Esempio n. 22
0
    def _build_one_legacy(self, req, tempd, python_tag=None):
        """Build one InstallRequirement using the "legacy" build process.

        Returns path to wheel if successfully built. Otherwise, returns None.
        """
        base_args = self._base_setup_args(req)

        spin_message = "Building wheel for %s (setup.py)" % (req.name,)
        with open_spinner(spin_message) as spinner:
            logger.debug("Destination directory: %s", tempd)
            wheel_args = base_args + ["bdist_wheel", "-d", tempd] + self.build_options

            if python_tag is not None:
                wheel_args += ["--python-tag", python_tag]

            try:
                output = call_subprocess(
                    wheel_args, cwd=req.unpacked_source_directory, spinner=spinner
                )
            except Exception:
                spinner.finish("error")
                logger.error("Failed building wheel for %s", req.name)
                return None

            names = os.listdir(tempd)
            wheel_path = get_legacy_build_wheel_path(
                names=names,
                temp_dir=tempd,
                req=req,
                command_args=wheel_args,
                command_output=output,
            )
            return wheel_path
Esempio n. 23
0
def generate_metadata(install_req):
    # type: (InstallRequirement) -> str
    """Generate metadata using setup.py-based defacto mechanisms.ArithmeticError

    Returns the generated metadata directory.
    """
    assert install_req.unpacked_source_directory

    req_details_str = install_req.name or "from {}".format(install_req.link)
    logger.debug(
        'Running setup.py (path:%s) egg_info for package %s',
        install_req.setup_py_path,
        req_details_str,
    )

    egg_info_dir = None  # type: Optional[str]
    # For non-editable installs, don't put the .egg-info files at the root,
    # to avoid confusion due to the source code being considered an installed
    # egg.
    if not install_req.editable:
        egg_info_dir = os.path.join(
            install_req.unpacked_source_directory,
            'pip-egg-info',
        )

        # setuptools complains if the target directory does not exist.
        ensure_dir(egg_info_dir)

    args = make_setuptools_egg_info_args(
        install_req.setup_py_path,
        egg_info_dir=egg_info_dir,
        no_user_config=install_req.isolated,
    )

    with install_req.build_env:
        call_subprocess(
            args,
            cwd=install_req.unpacked_source_directory,
            command_desc='python setup.py egg_info',
        )

    # Return the .egg-info directory.
    return _find_egg_info(
        install_req.unpacked_source_directory,
        install_req.editable,
    )
Esempio n. 24
0
    def _install_requirements(
        standalone_pip: str,
        finder: "PackageFinder",
        requirements: Iterable[str],
        prefix: _Prefix,
        message: str,
    ) -> None:
        args = [
            sys.executable,
            standalone_pip,
            'install',
            '--ignore-installed',
            '--no-user',
            '--prefix',
            prefix.path,
            '--no-warn-script-location',
        ]  # type: List[str]
        if logger.getEffectiveLevel() <= logging.DEBUG:
            args.append('-v')
        for format_control in ('no_binary', 'only_binary'):
            formats = getattr(finder.format_control, format_control)
            args.extend(('--' + format_control.replace('_', '-'),
                         ','.join(sorted(formats or {':none:'}))))

        index_urls = finder.index_urls
        if index_urls:
            args.extend(['-i', index_urls[0]])
            for extra_index in index_urls[1:]:
                args.extend(['--extra-index-url', extra_index])
        else:
            args.append('--no-index')
        for link in finder.find_links:
            args.extend(['--find-links', link])

        for host in finder.trusted_hosts:
            args.extend(['--trusted-host', host])
        if finder.allow_all_prereleases:
            args.append('--pre')
        if finder.prefer_binary:
            args.append('--prefer-binary')
        args.append('--')
        args.extend(requirements)
        extra_environ = {"_PIP_STANDALONE_CERT": where()}
        with open_spinner(message) as spinner:
            call_subprocess(args, spinner=spinner, extra_environ=extra_environ)
Esempio n. 25
0
def generate_metadata(
        build_env,  # type: BuildEnvironment
        setup_py_path,  # type: str
        source_dir,  # type: str
        editable,  # type: bool
        isolated,  # type: bool
        details,  # type: str
):
    # type: (...) -> str
    """Generate metadata using setup.py-based defacto mechanisms.

    Returns the generated metadata directory.
    """
    logger.debug(
        'Running setup.py (path:%s) egg_info for package %s',
        setup_py_path,
        details,
    )

    egg_info_dir = None  # type: Optional[str]
    # For non-editable installs, don't put the .egg-info files at the root,
    # to avoid confusion due to the source code being considered an installed
    # egg.
    if not editable:
        egg_info_dir = os.path.join(source_dir, 'pip-egg-info')
        # setuptools complains if the target directory does not exist.
        ensure_dir(egg_info_dir)

    args = make_setuptools_egg_info_args(
        setup_py_path,
        egg_info_dir=egg_info_dir,
        no_user_config=isolated,
    )

    with build_env:
        call_subprocess(
            args,
            cwd=source_dir,
            command_desc='python setup.py egg_info',
        )

    # Return the .egg-info directory.
    return _find_egg_info(source_dir, editable)
Esempio n. 26
0
def generate_metadata(
    build_env: BuildEnvironment,
    setup_py_path: str,
    source_dir: str,
    isolated: bool,
    details: str,
) -> str:
    """Generate metadata using setup.py-based defacto mechanisms.

    Returns the generated metadata directory.
    """
    logger.debug(
        "Running setup.py (path:%s) egg_info for package %s",
        setup_py_path,
        details,
    )

    egg_info_dir = TempDirectory(kind="pip-egg-info",
                                 globally_managed=True).path

    args = make_setuptools_egg_info_args(
        setup_py_path,
        egg_info_dir=egg_info_dir,
        no_user_config=isolated,
    )

    with build_env:
        with open_spinner("Preparing metadata (setup.py)") as spinner:
            try:
                call_subprocess(
                    args,
                    cwd=source_dir,
                    command_desc="python setup.py egg_info",
                    spinner=spinner,
                )
            except InstallationSubprocessError as error:
                raise MetadataGenerationFailed(
                    package_details=details) from error

    # Return the .egg-info directory.
    return _find_egg_info(egg_info_dir)
Esempio n. 27
0
 def run_command(
     cls,
     cmd,  # type: Union[List[str], CommandArgs]
     show_stdout=True,  # type: bool
     cwd=None,  # type: Optional[str]
     on_returncode="raise",  # type: Literal["raise", "warn", "ignore"]
     extra_ok_returncodes=None,  # type: Optional[Iterable[int]]
     command_desc=None,  # type: Optional[str]
     extra_environ=None,  # type: Optional[Mapping[str, Any]]
     spinner=None,  # type: Optional[SpinnerInterface]
     log_failed_cmd=True,  # type: bool
     stdout_only=False,  # type: bool
 ):
     # type: (...) -> str
     """
     Run a VCS subcommand
     This is simply a wrapper around call_subprocess that adds the VCS
     command name, and checks that the VCS is available
     """
     cmd = make_command(cls.name, *cmd)
     try:
         return call_subprocess(
             cmd,
             show_stdout,
             cwd,
             on_returncode=on_returncode,
             extra_ok_returncodes=extra_ok_returncodes,
             command_desc=command_desc,
             extra_environ=extra_environ,
             unset_environ=cls.unset_environ,
             spinner=spinner,
             log_failed_cmd=log_failed_cmd,
             stdout_only=stdout_only,
         )
     except FileNotFoundError:
         # errno.ENOENT = no such file or directory
         # In other words, the VCS executable isn't available
         raise BadCommand(
             f"Cannot find command {cls.name!r} - do you have "
             f"{cls.name!r} installed and in your PATH?"
         )
     except PermissionError:
         # errno.EACCES = Permission denied
         # This error occurs, for instance, when the command is installed
         # only for another user. So, the current user don't have
         # permission to call the other user command.
         raise BadCommand(
             f"No permission to execute {cls.name!r} - install it "
             f"locally, globally (ask admin), or check your PATH. "
             f"See possible solutions at "
             f"https://pip.pypa.io/en/latest/reference/pip_freeze/"
             f"#fixing-permission-denied."
         )
Esempio n. 28
0
def _generate_metadata_legacy(install_req):
    # type: (InstallRequirement) -> str
    req_details_str = install_req.name or "from {}".format(install_req.link)
    logger.debug(
        'Running setup.py (path:%s) egg_info for package %s',
        install_req.setup_py_path,
        req_details_str,
    )

    # Compose arguments for subprocess call
    base_cmd = make_setuptools_shim_args(install_req.setup_py_path)
    if install_req.isolated:
        base_cmd += ["--no-user-cfg"]

    # For non-editable installs, don't put the .egg-info files at the root,
    # to avoid confusion due to the source code being considered an installed
    # egg.
    egg_base_option = []  # type: List[str]
    if not install_req.editable:
        egg_info_dir = os.path.join(
            install_req.unpacked_source_directory,
            'pip-egg-info',
        )
        egg_base_option = ['--egg-base', egg_info_dir]

        # setuptools complains if the target directory does not exist.
        ensure_dir(egg_info_dir)

    with install_req.build_env:
        call_subprocess(
            base_cmd + ["egg_info"] + egg_base_option,
            cwd=install_req.unpacked_source_directory,
            command_desc='python setup.py egg_info',
        )

    # Return the .egg-info directory.
    return _find_egg_info(
        install_req.unpacked_source_directory,
        install_req.editable,
    )
Esempio n. 29
0
    def run_command(
            cls,
            cmd,  # type: Union[List[str], CommandArgs]
            show_stdout=True,  # type: bool
            cwd=None,  # type: Optional[str]
            on_returncode='raise',  # type: str
            extra_ok_returncodes=None,  # type: Optional[Iterable[int]]
            command_desc=None,  # type: Optional[str]
            extra_environ=None,  # type: Optional[Mapping[str, Any]]
            spinner=None,  # type: Optional[SpinnerInterface]
            log_failed_cmd=True,  # type: bool
            stdout_only=False,  # type: bool
    ):

        # type: (...) -> str
        """

        Run a VCS subcommand

        This is simply a wrapper around call_subprocess that adds the VCS

        command name, and checks that the VCS is available

        """

        cmd = make_command(cls.name, *cmd)

        try:

            return call_subprocess(cmd,
                                   show_stdout,
                                   cwd,
                                   on_returncode=on_returncode,
                                   extra_ok_returncodes=extra_ok_returncodes,
                                   command_desc=command_desc,
                                   extra_environ=extra_environ,
                                   unset_environ=cls.unset_environ,
                                   spinner=spinner,
                                   log_failed_cmd=log_failed_cmd,
                                   stdout_only=stdout_only)

        except FileNotFoundError:

            # errno.ENOENT = no such file or directory

            # In other words, the VCS executable isn't available

            raise BadCommand('Cannot find command {cls.name!r} - do you have '
                             '{cls.name!r} installed and in your '
                             'PATH?'.format(**locals()))
Esempio n. 30
0
    def test_info_logging(self, capfd, caplog):
        """
        Test INFO logging (and without passing show_stdout=True).
        """
        log_level = INFO
        args, spinner = self.prepare_call(caplog, log_level)
        result = call_subprocess(args, spinner=spinner)

        expected = (['Hello', 'world'], [])
        # The spinner should spin twice in this case since the subprocess
        # output isn't being written to the console.
        self.check_result(
            capfd, caplog, log_level, spinner, result, expected,
            expected_spinner=(2, 'done'),
        )