示例#1
0
def test_build_environment_not_called_without_build_script_specified(
        mocker: MockerFixture, poetry: Poetry, tmp_dir: str):
    project_env = MockEnv(path=Path(tmp_dir) / "project")
    ephemeral_env = MockEnv(path=Path(tmp_dir) / "ephemeral")

    mocker.patch("poetry.utils.env.ephemeral_environment"
                 ).return_value.__enter__.return_value = ephemeral_env

    with build_environment(poetry, project_env) as env:
        assert env == project_env
        assert not env.executed
示例#2
0
def test_tags_cpython37():
    assert (
        get_abi_tag(
            MockEnv(
                version_info=(3, 7, 3),
                python_implementation="CPython",
                config_vars={"Py_DEBUG": True, "WITH_PYMALLOC": True},
            )
        )
        == "cp37dm"
    )
    assert (
        get_abi_tag(
            MockEnv(
                version_info=(3, 7, 3),
                python_implementation="CPython",
                config_vars={"Py_DEBUG": True, "WITH_PYMALLOC": False},
            )
        )
        == "cp37d"
    )
    assert (
        get_abi_tag(
            MockEnv(
                version_info=(3, 7, 3),
                python_implementation="CPython",
                config_vars={"Py_DEBUG": False, "WITH_PYMALLOC": True},
            )
        )
        == "cp37m"
    )
    assert (
        get_abi_tag(
            MockEnv(
                version_info=(3, 7, 3),
                python_implementation="CPython",
                config_vars={"Py_DEBUG": False, "WITH_PYMALLOC": False},
            )
        )
        == "cp37"
    )
    with pytest.warns(RuntimeWarning):
        assert (
            get_abi_tag(
                MockEnv(
                    version_info=(3, 7, 3),
                    python_implementation="CPython",
                    config_vars={"Py_DEBUG": False},
                )
            )
            == "cp37m"
        )
示例#3
0
def test_installer_can_handle_old_lock_files(installer, locker, package, repo,
                                             installed, config):
    pool = Pool()
    pool.add_repository(MockRepository())

    package.add_dependency("pytest", "^3.5", category="dev")

    locker.locked()
    locker.mock_lock_data(fixture("old-lock"))

    installer = Installer(NullIO(),
                          MockEnv(),
                          package,
                          locker,
                          pool,
                          config,
                          installed=installed)

    installer.run()

    assert 6 == len(installer.installer.installs)

    installer = Installer(
        NullIO(),
        MockEnv(version_info=(2, 7, 18)),
        package,
        locker,
        pool,
        config,
        installed=installed,
    )

    installer.run()

    # funcsigs will be added
    assert 7 == len(installer.installer.installs)

    installer = Installer(
        NullIO(),
        MockEnv(version_info=(2, 7, 18), platform="win32"),
        package,
        locker,
        pool,
        config,
        installed=installed,
    )

    installer.run()

    # colorama will be added
    assert 8 == len(installer.installer.installs)
示例#4
0
def env():
    return MockEnv(
        supported_tags=[
            Tag("cp37", "cp37", "macosx_10_15_x86_64"),
            Tag("py3", "none", "any"),
        ]
    )
示例#5
0
def test_get_cached_archive_for_link(config: Config, mocker: MockerFixture,
                                     link: str, cached: str):
    chef = Chef(
        config,
        MockEnv(
            version_info=(3, 8, 3),
            marker_env={
                "interpreter_name": "cpython",
                "interpreter_version": "3.8.3"
            },
            supported_tags=[
                Tag("cp38", "cp38", "macosx_10_15_x86_64"),
                Tag("py3", "none", "any"),
            ],
        ),
    )

    mocker.patch.object(
        chef,
        "get_cached_archives_for_link",
        return_value=[
            Path("/cache/demo-0.1.0-py2.py3-none-any"),
            Path("/cache/demo-0.1.0.tar.gz"),
            Path("/cache/demo-0.1.0-cp38-cp38-macosx_10_15_x86_64.whl"),
            Path("/cache/demo-0.1.0-cp37-cp37-macosx_10_15_x86_64.whl"),
        ],
    )

    archive = chef.get_cached_archive_for_link(Link(link))

    assert Path(cached) == archive
示例#6
0
def setup(mocker):
    mocker.patch(
        "poetry.utils.env.EnvManager.get",
        return_value=MockEnv(path=Path("/prefix"),
                             base=Path("/base/prefix"),
                             is_venv=True),
    )
示例#7
0
def test_executor_should_use_cached_link_and_hash(
    config, io, pool, mocker, fixture_dir, tmp_dir
):
    # Produce a file:/// URI that is a valid link
    link_cached = Link(
        fixture_dir("distributions")
        .joinpath("demo-0.1.0-py2.py3-none-any.whl")
        .as_uri()
    )
    mocker.patch.object(
        Chef, "get_cached_archive_for_link", side_effect=lambda _: link_cached
    )

    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:15507846fd4299596661d0197bfb4f90",
        }
    ]

    archive = executor._download_link(
        Install(package), Link("https://example.com/demo-0.1.0-py2.py3-none-any.whl")
    )

    assert archive == link_cached
示例#8
0
def test_executor_should_check_every_possible_hash_types(
    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:15507846fd4299596661d0197bfb4f90",
        }
    ]

    archive = executor._download_link(
        Install(package), Link("https://example.com/demo-0.1.0-py2.py3-none-any.whl")
    )

    assert archive == fixture_dir("distributions").joinpath(
        "demo-0.1.0-py2.py3-none-any.whl"
    )
示例#9
0
def test_executor_should_delete_incomplete_downloads(config, io, tmp_dir,
                                                     mocker, pool,
                                                     mock_file_downloads):
    fixture = Path(__file__).parent.parent.joinpath(
        "fixtures/distributions/demo-0.1.0-py2.py3-none-any.whl")
    destination_fixture = Path(tmp_dir) / "tomlkit-0.5.3-py2.py3-none-any.whl"
    shutil.copyfile(str(fixture), str(destination_fixture))
    mocker.patch(
        "poetry.installation.executor.Executor._download_archive",
        side_effect=Exception("Download error"),
    )
    mocker.patch(
        "poetry.installation.chef.Chef.get_cached_archive_for_link",
        side_effect=lambda link: link,
    )
    mocker.patch(
        "poetry.installation.chef.Chef.get_cache_directory_for_link",
        return_value=Path(tmp_dir),
    )

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

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

    with pytest.raises(Exception, match="Download error"):
        executor._download(Install(Package("tomlkit", "0.5.3")))

    assert not destination_fixture.exists()
示例#10
0
def test_build_should_temporarily_remove_the_pyproject_file(tmp_dir, mocker):
    move = mocker.patch("shutil.move")
    tmp_dir = Path(tmp_dir)
    env = MockEnv(path=tmp_dir, pip_version="19.1", execute=False, sys_path=[])
    module_path = fixtures_dir / "extended"

    builder = EditableBuilder(Factory().create_poetry(module_path), env,
                              NullIO())
    builder.build()

    expected = [[
        sys.executable, "-m", "pip", "install", "-e",
        str(module_path)
    ]]
    assert expected == env.executed

    assert 2 == move.call_count

    expected_calls = [
        mocker.call(str(module_path / "pyproject.toml"),
                    str(module_path / "pyproject.tmp")),
        mocker.call(str(module_path / "pyproject.tmp"),
                    str(module_path / "pyproject.toml")),
    ]

    assert expected_calls == move.call_args_list
示例#11
0
文件: test_use.py 项目: yosmoc/poetry
def test_get_prefers_explicitly_activated_non_existing_virtualenvs_over_env_var(
    mocker, tester, current_python, venv_cache, venv_name, venvs_in_cache_config
):
    os.environ["VIRTUAL_ENV"] = "/environment/prefix"

    python_minor = ".".join(str(v) for v in current_python[:2])
    venv_dir = venv_cache / "{}-py{}".format(venv_name, python_minor)

    mocker.patch(
        "poetry.utils.env.EnvManager._env",
        new_callable=mocker.PropertyMock,
        return_value=MockEnv(
            path=Path("/environment/prefix"),
            base=Path("/base/prefix"),
            version_info=current_python,
            is_venv=True,
        ),
    )
    mocker.patch("poetry.utils.env.EnvManager.build_venv", side_effect=build_venv)

    tester.execute(python_minor)

    expected = """\
Creating virtualenv {} in {}
Using virtualenv: {}
""".format(
        venv_dir.name, venv_dir.parent, venv_dir,
    )

    assert expected == tester.io.fetch_output()
示例#12
0
def test_get_prefers_explicitly_activated_non_existing_virtualenvs_over_env_var(
    mocker: MockerFixture,
    tester: CommandTester,
    current_python: tuple[int, int, int],
    venv_cache: Path,
    venv_name: str,
    venvs_in_cache_config: None,
):
    os.environ["VIRTUAL_ENV"] = "/environment/prefix"

    python_minor = ".".join(str(v) for v in current_python[:2])
    venv_dir = venv_cache / f"{venv_name}-py{python_minor}"

    mocker.patch(
        "poetry.utils.env.EnvManager._env",
        new_callable=mocker.PropertyMock,
        return_value=MockEnv(
            path=Path("/environment/prefix"),
            base=Path("/base/prefix"),
            version_info=current_python,
            is_venv=True,
        ),
    )
    mocker.patch("poetry.utils.env.EnvManager.build_venv",
                 side_effect=build_venv)

    tester.execute(python_minor)

    expected = f"""\
Creating virtualenv {venv_dir.name} in {venv_dir.parent}
Using virtualenv: {venv_dir}
"""

    assert tester.io.fetch_output() == expected
示例#13
0
def setup(mocker, installer, installed):
    Env._env = MockEnv()

    # Set Installer's installer
    p = mocker.patch("poetry.installation.installer.Installer._get_installer")
    p.return_value = installer

    p = mocker.patch("poetry.installation.installer.Installer._get_installed")
    p.return_value = installed

    p = mocker.patch(
        "poetry.repositories.installed_repository.InstalledRepository.load")
    p.return_value = installed

    # Patch git module to not actually clone projects
    mocker.patch("poetry.vcs.git.Git.clone", new=mock_clone)
    mocker.patch("poetry.vcs.git.Git.checkout", new=lambda *_: None)
    p = mocker.patch("poetry.vcs.git.Git.rev_parse")
    p.return_value = "9cf87a285a2d3fbb0b9fa621997b3acc3631ed24"

    # Setting terminal width
    environ = dict(os.environ)
    os.environ["COLUMNS"] = "80"

    yield

    os.environ.clear()
    os.environ.update(environ)
    Env._env = None
示例#14
0
def test_get_cached_archives_for_link(config, mocker):
    chef = Chef(
        config,
        MockEnv(marker_env={
            "interpreter_name": "cpython",
            "interpreter_version": "3.8.3"
        }),
    )

    distributions = Path(__file__).parent.parent.joinpath(
        "fixtures/distributions")
    mocker.patch.object(
        chef,
        "get_cache_directory_for_link",
        return_value=distributions,
    )

    archives = chef.get_cached_archives_for_link(
        Link("https://files.python-poetry.org/demo-0.1.0.tar.gz"))

    assert archives
    assert set(archives) == {
        Link(path.as_uri())
        for path in distributions.glob("demo-0.1.0*")
    }
示例#15
0
def test_get_cached_archive_for_link(config, mocker):
    chef = Chef(
        config,
        MockEnv(
            version_info=(3, 8, 3),
            marker_env={
                "interpreter_name": "cpython",
                "interpreter_version": "3.8.3"
            },
            supported_tags=[
                Tag("cp38", "cp38", "macosx_10_15_x86_64"),
                Tag("py3", "none", "any"),
            ],
        ),
    )

    cwd = Path.cwd() / ".pypoetrycache"

    mocker.patch.object(
        chef,
        "get_cached_archives_for_link",
        return_value=[
            Link(f"file:///{cwd}demo-0.1.0-py2.py3-none-any"),
            Link(f"file:///{cwd}demo-0.1.0.tar.gz"),
            Link(f"file:///{cwd}demo-0.1.0-cp38-cp38-macosx_10_15_x86_64.whl"),
            Link(f"file:///{cwd}demo-0.1.0-cp37-cp37-macosx_10_15_x86_64.whl"),
        ],
    )

    archive = chef.get_cached_archive_for_link(
        Link("https://files.python-poetry.org/demo-0.1.0.tar.gz"))

    assert Link(f"file:///{cwd}demo-0.1.0-cp38-cp38-macosx_10_15_x86_64.whl"
                ) == archive
示例#16
0
def test_execute_executes_a_batch_of_operations(
    config, pool, io, tmp_dir, mock_file_downloads
):
    config = Config()
    config.merge({"cache-dir": tmp_dir})

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

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

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

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

    assert 0 == 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)
示例#17
0
def test_builder_should_execute_build_scripts(extended_without_setup_poetry):
    env = MockEnv(path=Path("/foo"))
    builder = EditableBuilder(extended_without_setup_poetry, env, NullIO())

    builder.build()

    assert [
        ["python", str(extended_without_setup_poetry.file.parent / "build.py")]
    ] == env.executed
示例#18
0
def test_tags_cpython38():
    assert (
        get_abi_tag(
            MockEnv(
                version_info=(3, 8, 0),
                python_implementation="CPython",
                config_vars={"Py_DEBUG": True},
            )
        )
        == "cp38d"
    )
    assert (
        get_abi_tag(
            MockEnv(
                version_info=(3, 8, 0), python_implementation="CPython", config_vars={},
            )
        )
        == "cp38"
    )
示例#19
0
def test_build_environment_called_build_script_specified(
        mocker: MockerFixture, extended_without_setup_poetry: Poetry,
        tmp_dir: str):
    project_env = MockEnv(path=Path(tmp_dir) / "project")
    ephemeral_env = MockEnv(path=Path(tmp_dir) / "ephemeral")

    mocker.patch("poetry.utils.env.ephemeral_environment"
                 ).return_value.__enter__.return_value = ephemeral_env

    with build_environment(extended_without_setup_poetry, project_env) as env:
        assert env == ephemeral_env
        assert env.executed == [[
            "python",
            env.pip_embedded,
            "install",
            "--disable-pip-version-check",
            "--ignore-installed",
            *extended_without_setup_poetry.pyproject.build_system.requires,
        ]]
示例#20
0
def test_run_passes_all_args(app, mocker):
    env = MockEnv(path=Path("/prefix"), base=Path("/base/prefix"), is_venv=True)
    mocker.patch("poetry.utils.env.EnvManager.get", return_value=env)

    command = app.find("run")
    tester = CommandTester(command)

    tester.execute("python -V")

    assert [["python", "-V"]] == env.executed
示例#21
0
def test_builder_falls_back_on_setup_and_pip_for_packages_with_build_scripts(
        mocker, extended_poetry, tmp_dir):
    pip_editable_install = mocker.patch(
        "poetry.masonry.builders.editable.pip_editable_install")
    env = MockEnv(path=Path(tmp_dir) / "foo")
    builder = EditableBuilder(extended_poetry, env, NullIO())

    builder.build()
    pip_editable_install.assert_called_once_with(
        extended_poetry.pyproject.file.path.parent, env)
    assert [] == env.executed
示例#22
0
def test_get_prefers_explicitly_activated_non_existing_virtualenvs_over_env_var(
        app, tmp_dir, config, mocker):
    app.poetry._config = config

    os.environ["VIRTUAL_ENV"] = "/environment/prefix"

    venv_name = EnvManager.generate_env_name("simple_project",
                                             str(app.poetry.file.parent))
    current_python = sys.version_info[:3]
    python_minor = ".".join(str(v) for v in current_python[:2])

    config.add_property("settings.virtualenvs.path", str(tmp_dir))

    mocker.patch(
        "poetry.utils.env.EnvManager._env",
        new_callable=mocker.PropertyMock,
        return_value=MockEnv(
            path=Path("/environment/prefix"),
            base=Path("/base/prefix"),
            version_info=current_python,
            is_venv=True,
        ),
    )

    mocker.patch(
        "poetry.utils._compat.subprocess.check_output",
        side_effect=check_output_wrapper(Version(*current_python)),
    )
    mocker.patch(
        "poetry.utils._compat.subprocess.Popen.communicate",
        side_effect=[("/prefix", None), ("/prefix", None), ("/prefix", None)],
    )
    mocker.patch("poetry.utils.env.EnvManager.build_venv",
                 side_effect=build_venv)

    command = app.find("env use")
    tester = CommandTester(command)
    tester.execute(python_minor)

    expected = """\
Creating virtualenv {} in {}
Using virtualenv: {}
""".format(
        "{}-py{}".format(venv_name, python_minor),
        tmp_dir,
        os.path.join(tmp_dir, "{}-py{}".format(venv_name, python_minor)),
    )

    assert expected == tester.io.fetch_output()
示例#23
0
def test_build_should_delegate_to_pip_for_non_pure_python_packages(
        tmp_dir, mocker):
    move = mocker.patch("shutil.move")
    tmp_dir = Path(tmp_dir)
    env = MockEnv(path=tmp_dir, pip_version="18.1", execute=False)
    env.site_packages.mkdir(parents=True)
    module_path = fixtures_dir / "extended"

    builder = EditableBuilder(Poetry.create(module_path), env, NullIO())
    builder.build()

    expected = [["python", "-m", "pip", "install", "-e", str(module_path)]]
    assert expected == env.executed

    assert 0 == move.call_count
示例#24
0
def test_builder_should_execute_build_scripts(
        mocker: MockerFixture, extended_without_setup_poetry: Poetry,
        tmp_dir: str):
    env = MockEnv(path=Path(tmp_dir) / "foo")
    mocker.patch("poetry.masonry.builders.editable.build_environment"
                 ).return_value.__enter__.return_value = env

    builder = EditableBuilder(extended_without_setup_poetry, env, NullIO())

    builder.build()

    assert [[
        "python",
        str(extended_without_setup_poetry.file.parent / "build.py")
    ]] == env.executed
示例#25
0
def test_get_cache_directory_for_link(config):
    chef = Chef(
        config,
        MockEnv(
            marker_env={"interpreter_name": "cpython", "interpreter_version": "3.8.3"}
        ),
    )

    directory = chef.get_cache_directory_for_link(
        Link("https://files.python-poetry.org/poetry-1.1.0.tar.gz")
    )
    expected = Path(
        "/foo/artifacts/ba/63/13/283a3b3b7f95f05e9e6f84182d276f7bb0951d5b0cc24422b33f7a4648"
    )

    assert expected == directory
示例#26
0
def test_builder_falls_back_on_setup_and_pip_for_packages_with_build_scripts(
        extended_poetry, tmp_dir):
    env = MockEnv(path=Path(tmp_dir) / "foo")
    builder = EditableBuilder(extended_poetry, env, NullIO())

    builder.build()

    assert [[
        "python",
        "-m",
        "pip",
        "install",
        "-e",
        str(extended_poetry.file.parent),
        "--no-deps",
    ]] == env.executed
示例#27
0
def test_chooser_chooses_system_specific_wheel_link_if_available(
    mock_pypi, mock_legacy, source_type, pool
):
    env = MockEnv(
        supported_tags=[Tag("cp37", "cp37m", "win32"), Tag("py3", "none", "any")]
    )
    chooser = Chooser(pool, env)

    package = Package("pyyaml", "3.13.0")
    if source_type == "legacy":
        package.source_type = "legacy"
        package.source_reference = "foo"
        package.source_url = "https://foo.bar/simple/"

    link = chooser.choose_for(package)

    assert "PyYAML-3.13-cp37-cp37m-win32.whl" == link.filename
示例#28
0
def test_execute_should_show_operation_as_cancelled_on_subprocess_keyboard_interrupt(
        config, mocker, io):
    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 1 == executor.execute([Install(Package("clikit", "0.2.3"))])

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

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

    assert expected == io.fetch_output()
示例#29
0
def test_execute_shows_skipped_operations_if_verbose(config, pool, io):
    config = Config()
    config.merge({"cache-dir": "/foo"})

    env = MockEnv()
    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)
示例#30
0
def test_execute_should_show_errors(config, mocker, io):
    env = MockEnv()
    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()