Exemplo n.º 1
0
def test_execute_should_show_operation_as_cancelled_on_subprocess_keyboard_interrupt(
        config: Config, pool: Pool, mocker: MockerFixture, io: BufferedIO,
        env: MockEnv):
    executor = Executor(env, pool, config, io)
    executor.verbose()

    # A return code of -2 means KeyboardInterrupt in the pip subprocess
    mocker.patch.object(executor, "_install", return_value=-2)

    assert executor.execute([Install(Package("clikit", "0.2.3"))]) == 1

    expected = """
Package operations: 1 install, 0 updates, 0 removals

  • Installing clikit (0.2.3)
  • Installing clikit (0.2.3): Cancelled
"""

    assert io.fetch_output() == expected
Exemplo n.º 2
0
def test_execute_shows_skipped_operations_if_verbose(config, pool, io,
                                                     config_cache_dir, env):
    config = Config()
    config.merge({"cache-dir": config_cache_dir.as_posix()})

    executor = Executor(env, pool, config, io)
    executor.verbose()

    assert 0 == executor.execute([
        Uninstall(Package("clikit", "0.2.3")).skip("Not currently installed")
    ])

    expected = """
Package operations: 0 installs, 0 updates, 0 removals, 1 skipped

  • Removing clikit (0.2.3): Skipped for the following reason: Not currently installed
"""
    assert expected == io.fetch_output()
    assert 0 == len(env.executed)
Exemplo n.º 3
0
def test_execute_should_show_errors(config, mocker, io, env):
    executor = Executor(env, pool, config, io)
    executor.verbose()

    mocker.patch.object(executor, "_install", side_effect=Exception("It failed!"))

    assert 1 == executor.execute([Install(Package("clikit", "0.2.3"))])

    expected = """
Package operations: 1 install, 0 updates, 0 removals

  • Installing clikit (0.2.3)

  Exception

  It failed!
"""

    assert expected in io.fetch_output()
Exemplo n.º 4
0
def test_executor_should_write_pep610_url_references_for_urls(
    tmp_venv: "VirtualEnv",
    pool: Pool,
    config: "Config",
    io: BufferedIO,
    mock_file_downloads: None,
):
    package = Package(
        "demo",
        "0.1.0",
        source_type="url",
        source_url="https://files.pythonhosted.org/demo-0.1.0-py2.py3-none-any.whl",
    )

    executor = Executor(tmp_venv, pool, config, io)
    executor.execute([Install(package)])
    verify_installed_distribution(
        tmp_venv, package, {"archive_info": {}, "url": package.source_url}
    )
Exemplo n.º 5
0
    def __init__(
        self,
        io: IO,
        env: Env,
        package: ProjectPackage,
        locker: Locker,
        pool: Pool,
        config: Config,
        installed: Repository | None = None,
        executor: Executor | None = None,
    ) -> None:
        self._io = io
        self._env = env
        self._package = package
        self._locker = locker
        self._pool = pool

        self._dry_run = False
        self._requires_synchronization = False
        self._update = False
        self._verbose = False
        self._write_lock = True
        self._groups: Iterable[str] | None = None

        self._execute_operations = True
        self._lock = False

        self._whitelist = []

        self._extras = []

        if executor is None:
            executor = Executor(self._env, self._pool, config, self._io)

        self._executor = executor
        self._use_executor = False

        self._installer = self._get_installer()
        if installed is None:
            installed = self._get_installed()

        self._installed_repository = installed
Exemplo n.º 6
0
def test_executor_should_write_pep610_url_references_for_editable_directories(
        tmp_venv, pool, config, io):
    url = Path(__file__).parent.parent.joinpath(
        "fixtures/simple_project").resolve()
    package = Package(
        "simple-project",
        "1.2.3",
        source_type="directory",
        source_url=url.as_posix(),
        develop=True,
    )

    executor = Executor(tmp_venv, pool, config, io)
    executor.execute([Install(package)])
    verify_installed_distribution(tmp_venv, package, {
        "dir_info": {
            "editable": True
        },
        "url": url.as_uri()
    })
Exemplo n.º 7
0
def test_executor_should_be_initialized_with_correct_workers(
    tmp_venv: VirtualEnv,
    pool: Pool,
    config: Config,
    io: BufferedIO,
    mocker: MockerFixture,
    max_workers: int | None,
    cpu_count: int | None,
    side_effect: Exception | None,
    expected_workers: int,
):
    config.merge({"installer": {"max-workers": max_workers}})

    mocker.patch("os.cpu_count",
                 return_value=cpu_count,
                 side_effect=side_effect)

    executor = Executor(tmp_venv, pool, config, io)

    assert executor._max_workers == expected_workers
Exemplo n.º 8
0
def test_execute_works_with_ansi_output(
    mocker: "MockerFixture",
    config: "Config",
    pool: Pool,
    io_decorated: BufferedIO,
    tmp_dir: str,
    mock_file_downloads: None,
    env: MockEnv,
):
    config.merge({"cache-dir": tmp_dir})

    executor = Executor(env, pool, config, io_decorated)

    install_output = (
        "some string that does not contain a keyb0ard !nterrupt or cance11ed by u$er"
    )
    mocker.patch.object(env, "_run", return_value=install_output)
    return_code = executor.execute(
        [
            Install(Package("pytest", "3.5.2")),
        ]
    )
    env._run.assert_called_once()

    # fmt: off
    expected = [
        "\x1b[39;1mPackage operations\x1b[39;22m: \x1b[34m1\x1b[39m install, \x1b[34m0\x1b[39m updates, \x1b[34m0\x1b[39m removals",  # noqa: E501
        "\x1b[34;1m•\x1b[39;22m \x1b[39mInstalling \x1b[39m\x1b[36mpytest\x1b[39m\x1b[39m (\x1b[39m\x1b[39;1m3.5.2\x1b[39;22m\x1b[39m)\x1b[39m: \x1b[34mPending...\x1b[39m",  # noqa: E501
        "\x1b[34;1m•\x1b[39;22m \x1b[39mInstalling \x1b[39m\x1b[36mpytest\x1b[39m\x1b[39m (\x1b[39m\x1b[39;1m3.5.2\x1b[39;22m\x1b[39m)\x1b[39m: \x1b[34mDownloading...\x1b[39m",  # noqa: E501
        "\x1b[34;1m•\x1b[39;22m \x1b[39mInstalling \x1b[39m\x1b[36mpytest\x1b[39m\x1b[39m (\x1b[39m\x1b[39;1m3.5.2\x1b[39;22m\x1b[39m)\x1b[39m: \x1b[34mInstalling...\x1b[39m",  # noqa: E501
        "\x1b[32;1m•\x1b[39;22m \x1b[39mInstalling \x1b[39m\x1b[36mpytest\x1b[39m\x1b[39m (\x1b[39m\x1b[32m3.5.2\x1b[39m\x1b[39m)\x1b[39m",  # finished  # noqa: E501
    ]
    # fmt: on

    output = io_decorated.fetch_output()
    # hint: use print(repr(output)) if you need to debug this

    for line in expected:
        assert line in output
    assert return_code == 0
Exemplo n.º 9
0
def test_executor_should_write_pep610_url_references_for_files(
        tmp_venv, pool, config, io):
    url = (Path(__file__).parent.parent.joinpath(
        "fixtures/distributions/demo-0.1.0-py2.py3-none-any.whl").resolve())
    package = Package("demo",
                      "0.1.0",
                      source_type="file",
                      source_url=url.as_posix())

    executor = Executor(tmp_venv, pool, config, io)
    executor.execute([Install(package)])

    dist_info = tmp_venv.site_packages.path.joinpath("demo-0.1.0.dist-info")
    assert dist_info.exists()

    direct_url_file = dist_info.joinpath("direct_url.json")

    assert direct_url_file.exists()

    url_reference = json.loads(direct_url_file.read_text(encoding="utf-8"))

    assert url_reference == {"archive_info": {}, "url": url.as_uri()}
Exemplo n.º 10
0
def test_execute_shows_skipped_operations_if_verbose(
    config: "Config", pool: Pool, io: BufferedIO, config_cache_dir: Path, env: MockEnv
):
    config.merge({"cache-dir": config_cache_dir.as_posix()})

    executor = Executor(env, pool, config, io)
    executor.verbose()

    assert (
        executor.execute(
            [Uninstall(Package("clikit", "0.2.3")).skip("Not currently installed")]
        )
        == 0
    )

    expected = """
Package operations: 0 installs, 0 updates, 0 removals, 1 skipped

  • Removing clikit (0.2.3): Skipped for the following reason: Not currently installed
"""
    assert io.fetch_output() == expected
    assert len(env.executed) == 0
Exemplo n.º 11
0
def test_executor_should_check_every_possible_hash_types_before_failing(
    config, io, pool, mocker, fixture_dir, tmp_dir
):
    mocker.patch.object(
        Chef, "get_cached_archive_for_link", side_effect=lambda link: link,
    )
    mocker.patch.object(
        Executor,
        "_download_archive",
        return_value=fixture_dir("distributions").joinpath(
            "demo-0.1.0-py2.py3-none-any.whl"
        ),
    )

    env = MockEnv(path=Path(tmp_dir))
    executor = Executor(env, pool, config, io)

    package = Package("demo", "0.1.0")
    package.files = [
        {"file": "demo-0.1.0-py2.py3-none-any.whl", "hash": "md5:123456"},
        {"file": "demo-0.1.0-py2.py3-none-any.whl", "hash": "sha256:123456"},
    ]

    expected_message = (
        "Invalid hashes "
        "("
        "md5:15507846fd4299596661d0197bfb4f90, "
        "sha256:70e704135718fffbcbf61ed1fc45933cfd86951a744b681000eaaa75da31f17a"
        ") "
        "for demo (0.1.0) using archive demo-0.1.0-py2.py3-none-any.whl. "
        "Expected one of md5:123456, sha256:123456."
    )

    with pytest.raises(RuntimeError, match=re.escape(expected_message)):
        executor._download_link(
            Install(package),
            Link("https://example.com/demo-0.1.0-py2.py3-none-any.whl"),
        )
Exemplo n.º 12
0
def test_executor_should_write_pep610_url_references_for_directories(
        tmp_venv, pool, config, io):
    url = Path(__file__).parent.parent.joinpath(
        "fixtures/simple_project").resolve()
    package = Package("simple-project",
                      "1.2.3",
                      source_type="directory",
                      source_url=url.as_posix())

    executor = Executor(tmp_venv, pool, config, io)
    executor.execute([Install(package)])

    dist_info = tmp_venv.site_packages.path.joinpath(
        "simple_project-1.2.3.dist-info")
    assert dist_info.exists()

    direct_url_file = dist_info.joinpath("direct_url.json")

    assert direct_url_file.exists()

    url_reference = json.loads(direct_url_file.read_text(encoding="utf-8"))

    assert url_reference == {"dir_info": {}, "url": url.as_uri()}
Exemplo n.º 13
0
def test_execute_should_gracefully_handle_io_error(config, mocker, io, env):
    executor = Executor(env, pool, config, io)
    executor.verbose()

    original_write_line = executor._io.write_line

    def write_line(string, **kwargs):
        # Simulate UnicodeEncodeError
        string.encode("ascii")
        original_write_line(string, **kwargs)

    mocker.patch.object(io, "write_line", side_effect=write_line)

    assert 1 == executor.execute([Install(Package("clikit", "0.2.3"))])

    expected = r"""
Package operations: 1 install, 0 updates, 0 removals


\s*Unicode\w+Error
"""

    assert re.match(expected, io.fetch_output())
Exemplo n.º 14
0
def test_execute_executes_a_batch_of_operations(mocker, config, pool, io,
                                                tmp_dir, mock_file_downloads,
                                                env):
    pip_editable_install = mocker.patch(
        "poetry.installation.executor.pip_editable_install", unsafe=not PY36)

    config = Config()
    config.merge({"cache-dir": tmp_dir})

    executor = Executor(env, pool, config, io)

    file_package = Package(
        "demo",
        "0.1.0",
        source_type="file",
        source_url=Path(__file__).parent.parent.joinpath(
            "fixtures/distributions/demo-0.1.0-py2.py3-none-any.whl").resolve(
            ).as_posix(),
    )

    directory_package = Package(
        "simple-project",
        "1.2.3",
        source_type="directory",
        source_url=Path(__file__).parent.parent.joinpath(
            "fixtures/simple_project").resolve().as_posix(),
    )

    git_package = Package(
        "demo",
        "0.1.0",
        source_type="git",
        source_reference="master",
        source_url="https://github.com/demo/demo.git",
        develop=True,
    )

    return_code = executor.execute([
        Install(Package("pytest", "3.5.2")),
        Uninstall(Package("attrs", "17.4.0")),
        Update(Package("requests", "2.18.3"), Package("requests", "2.18.4")),
        Uninstall(Package("clikit", "0.2.3")).skip("Not currently installed"),
        Install(file_package),
        Install(directory_package),
        Install(git_package),
    ])

    expected = """
Package operations: 4 installs, 1 update, 1 removal

  • Installing pytest (3.5.2)
  • Removing attrs (17.4.0)
  • Updating requests (2.18.3 -> 2.18.4)
  • Installing demo (0.1.0 {})
  • Installing simple-project (1.2.3 {})
  • Installing demo (0.1.0 master)
""".format(file_package.source_url, directory_package.source_url)

    expected = set(expected.splitlines())
    output = set(io.fetch_output().splitlines())
    assert expected == output
    assert 5 == len(env.executed)
    assert 0 == return_code
    pip_editable_install.assert_called_once()
Exemplo n.º 15
0
def test_execute_executes_a_batch_of_operations(
    mocker: MockerFixture,
    config: Config,
    pool: Pool,
    io: BufferedIO,
    tmp_dir: str,
    mock_file_downloads: None,
    env: MockEnv,
):
    pip_install = mocker.patch("poetry.installation.executor.pip_install")

    config.merge({"cache-dir": tmp_dir})

    executor = Executor(env, pool, config, io)

    file_package = Package(
        "demo",
        "0.1.0",
        source_type="file",
        source_url=Path(__file__).parent.parent.joinpath(
            "fixtures/distributions/demo-0.1.0-py2.py3-none-any.whl").resolve(
            ).as_posix(),
    )

    directory_package = Package(
        "simple-project",
        "1.2.3",
        source_type="directory",
        source_url=Path(__file__).parent.parent.joinpath(
            "fixtures/simple_project").resolve().as_posix(),
    )

    git_package = Package(
        "demo",
        "0.1.0",
        source_type="git",
        source_reference="master",
        source_url="https://github.com/demo/demo.git",
        develop=True,
    )

    return_code = executor.execute([
        Install(Package("pytest", "3.5.2")),
        Uninstall(Package("attrs", "17.4.0")),
        Update(Package("requests", "2.18.3"), Package("requests", "2.18.4")),
        Uninstall(Package("clikit", "0.2.3")).skip("Not currently installed"),
        Install(file_package),
        Install(directory_package),
        Install(git_package),
    ])

    expected = f"""
Package operations: 4 installs, 1 update, 1 removal

  • Installing pytest (3.5.2)
  • Removing attrs (17.4.0)
  • Updating requests (2.18.3 -> 2.18.4)
  • Installing demo (0.1.0 {file_package.source_url})
  • Installing simple-project (1.2.3 {directory_package.source_url})
  • Installing demo (0.1.0 master)
"""

    expected = set(expected.splitlines())
    output = set(io.fetch_output().splitlines())
    assert output == expected
    assert len(env.executed) == 1
    assert return_code == 0
    assert pip_install.call_count == 5
    assert pip_install.call_args.kwargs.get("upgrade", False)
    assert pip_install.call_args.kwargs.get("editable", False)