Esempio n. 1
0
def test_remove_keeps_dir_if_not_deleteable(tmp_dir, manager, poetry, config,
                                            mocker):
    # Ensure we empty rather than delete folder if its is an active mount point.
    # See https://github.com/python-poetry/poetry/pull/2064
    config.merge({"virtualenvs": {"path": str(tmp_dir)}})

    venv_name = manager.generate_env_name("simple-project",
                                          str(poetry.file.parent))
    venv_path = Path(tmp_dir) / "{}-py3.6".format(venv_name)
    venv_path.mkdir()

    folder1_path = venv_path / "folder1"
    folder1_path.mkdir()

    file1_path = folder1_path / "file1"
    file1_path.touch(exist_ok=False)

    file2_path = venv_path / "file2"
    file2_path.touch(exist_ok=False)

    mocker.patch(
        "subprocess.check_output",
        side_effect=check_output_wrapper(Version.parse("3.6.6")),
    )

    original_rmtree = shutil.rmtree

    def err_on_rm_venv_only(path, *args, **kwargs):
        if path == str(venv_path):
            raise OSError(16,
                          "Test error")  # ERRNO 16: Device or resource busy
        else:
            original_rmtree(path)

    m = mocker.patch("shutil.rmtree", side_effect=err_on_rm_venv_only)

    venv = manager.remove("{}-py3.6".format(venv_name))

    m.assert_any_call(str(venv_path))

    assert venv_path == venv.path
    assert venv_path.exists()

    assert not folder1_path.exists()
    assert not file1_path.exists()
    assert not file2_path.exists()

    m.side_effect = original_rmtree  # Avoid teardown using `err_on_rm_venv_only`
Esempio n. 2
0
def test_activate_does_not_recreate_when_switching_minor(
    tmp_dir: str,
    manager: EnvManager,
    poetry: "Poetry",
    config: "Config",
    mocker: "MockerFixture",
):
    if "VIRTUAL_ENV" in os.environ:
        del os.environ["VIRTUAL_ENV"]

    venv_name = manager.generate_env_name("simple-project",
                                          str(poetry.file.parent))
    envs_file = TOMLFile(Path(tmp_dir) / "envs.toml")
    doc = tomlkit.document()
    doc[venv_name] = {"minor": "3.7", "patch": "3.7.0"}
    envs_file.write(doc)

    os.mkdir(os.path.join(tmp_dir, f"{venv_name}-py3.7"))
    os.mkdir(os.path.join(tmp_dir, f"{venv_name}-py3.6"))

    config.merge({"virtualenvs": {"path": str(tmp_dir)}})

    mocker.patch(
        "subprocess.check_output",
        side_effect=check_output_wrapper(Version.parse("3.6.6")),
    )
    mocker.patch(
        "subprocess.Popen.communicate",
        side_effect=[("/prefix", None), ("/prefix", None), ("/prefix", None)],
    )
    build_venv_m = mocker.patch("poetry.utils.env.EnvManager.build_venv",
                                side_effect=build_venv)
    remove_venv_m = mocker.patch("poetry.utils.env.EnvManager.remove_venv",
                                 side_effect=EnvManager.remove_venv)

    env = manager.activate("python3.6", NullIO())

    build_venv_m.assert_not_called()
    remove_venv_m.assert_not_called()

    assert envs_file.exists()
    envs = envs_file.read()
    assert envs[venv_name]["minor"] == "3.6"
    assert envs[venv_name]["patch"] == "3.6.6"

    assert env.path == Path(tmp_dir) / f"{venv_name}-py3.6"
    assert env.base == Path("/prefix")
    assert (Path(tmp_dir) / f"{venv_name}-py3.6").exists()
Esempio n. 3
0
def test_difference() -> None:
    v = Version.parse("1.2.3")

    assert v.difference(v).is_empty()
    assert v.difference(Version.parse("0.8.0")) == v
    assert v.difference(
        VersionRange(Version.parse("1.1.4"),
                     Version.parse("1.2.4"))).is_empty()
    assert (v.difference(
        VersionRange(Version.parse("1.4.0"), Version.parse("3.0.0"))) == v)
Esempio n. 4
0
    def all_classifiers(self) -> List[str]:
        from poetry.core.semver.version import Version  # noqa

        classifiers = copy.copy(self.classifiers)

        # Automatically set python classifiers
        if self.python_versions == "*":
            python_constraint = parse_constraint("~2.7 || ^3.4")
        else:
            python_constraint = self.python_constraint

        python_classifier_prefix = "Programming Language :: Python"
        python_classifiers = []

        # we sort python versions by sorting an int tuple of (major, minor) version
        # to ensure we sort 3.10 after 3.9
        for version in sorted(self.AVAILABLE_PYTHONS,
                              key=lambda x: tuple(map(int, x.split(".")))):
            if len(version) == 1:
                constraint = parse_constraint(version + ".*")
            else:
                constraint = Version.parse(version)

            if python_constraint.allows_any(constraint):
                classifier = "{} :: {}".format(python_classifier_prefix,
                                               version)
                if classifier not in python_classifiers:
                    python_classifiers.append(classifier)

        # Automatically set license classifiers
        if self.license:
            classifiers.append(self.license.classifier)

        # Sort classifiers and insert python classifiers at the right location. We do
        # it like this so that 3.10 is sorted after 3.9.
        sorted_classifiers = []
        python_classifiers_inserted = False
        for classifier in sorted(set(classifiers)):
            if (not python_classifiers_inserted
                    and classifier > python_classifier_prefix):
                sorted_classifiers.extend(python_classifiers)
                python_classifiers_inserted = True
            sorted_classifiers.append(classifier)

        if not python_classifiers_inserted:
            sorted_classifiers.extend(python_classifiers)

        return sorted_classifiers
Esempio n. 5
0
    def read_setup_cfg(
        self, filepath: Union[str, Path]
    ) -> Dict[str, Union[List, Dict]]:
        parser = ConfigParser()

        parser.read(str(filepath))

        name = None
        version = None
        if parser.has_option("metadata", "name"):
            name = parser.get("metadata", "name")

        if parser.has_option("metadata", "version"):
            version = Version.parse(parser.get("metadata", "version")).text

        install_requires = []
        extras_require = {}
        python_requires = None
        if parser.has_section("options"):
            if parser.has_option("options", "install_requires"):
                for dep in parser.get("options", "install_requires").split("\n"):
                    dep = dep.strip()
                    if not dep:
                        continue

                    install_requires.append(dep)

            if parser.has_option("options", "python_requires"):
                python_requires = parser.get("options", "python_requires")

        if parser.has_section("options.extras_require"):
            for group in parser.options("options.extras_require"):
                extras_require[group] = []
                deps = parser.get("options.extras_require", group)
                for dep in deps.split("\n"):
                    dep = dep.strip()
                    if not dep:
                        continue

                    extras_require[group].append(dep)

        return {
            "name": name,
            "version": version,
            "install_requires": install_requires,
            "extras_require": extras_require,
            "python_requires": python_requires,
        }
Esempio n. 6
0
def test_activate_activates_different_virtualenv_with_envs_file(
    tmp_dir: str,
    manager: EnvManager,
    poetry: "Poetry",
    config: "Config",
    mocker: "MockerFixture",
):
    if "VIRTUAL_ENV" in os.environ:
        del os.environ["VIRTUAL_ENV"]

    venv_name = manager.generate_env_name("simple-project", str(poetry.file.parent))
    envs_file = TOMLFile(Path(tmp_dir) / "envs.toml")
    doc = tomlkit.document()
    doc[venv_name] = {"minor": "3.7", "patch": "3.7.1"}
    envs_file.write(doc)

    os.mkdir(os.path.join(tmp_dir, f"{venv_name}-py3.7"))

    config.merge({"virtualenvs": {"path": str(tmp_dir)}})

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

    env = manager.activate("python3.6", NullIO())

    m.assert_called_with(
        Path(tmp_dir) / f"{venv_name}-py3.6",
        executable="/usr/bin/python3.6",
        flags={"always-copy": False, "system-site-packages": False},
        with_pip=True,
        with_setuptools=True,
        with_wheel=True,
    )

    assert envs_file.exists()
    envs = envs_file.read()
    assert envs[venv_name]["minor"] == "3.6"
    assert envs[venv_name]["patch"] == "3.6.6"

    assert env.path == Path(tmp_dir) / f"{venv_name}-py3.6"
    assert env.base == Path("/prefix")
Esempio n. 7
0
def test_remove_by_name(tmp_dir, manager, poetry, config, mocker):
    config.merge({"virtualenvs": {"path": str(tmp_dir)}})

    venv_name = manager.generate_env_name("simple-project", str(poetry.file.parent))
    (Path(tmp_dir) / "{}-py3.7".format(venv_name)).mkdir()
    (Path(tmp_dir) / "{}-py3.6".format(venv_name)).mkdir()

    mocker.patch(
        "subprocess.check_output",
        side_effect=check_output_wrapper(Version.parse("3.6.6")),
    )

    venv = manager.remove("{}-py3.6".format(venv_name))

    assert (Path(tmp_dir) / "{}-py3.6".format(venv_name)) == venv.path
    assert not (Path(tmp_dir) / "{}-py3.6".format(venv_name)).exists()
Esempio n. 8
0
    def _get_release_info(self, name: str, version: str) -> dict:
        page = self._get("/{}/".format(
            canonicalize_name(name).replace(".", "-")))
        if page is None:
            raise PackageNotFound('No package named "{}"'.format(name))

        data = PackageInfo(
            name=name,
            version=version,
            summary="",
            platform=None,
            requires_dist=[],
            requires_python=None,
            files=[],
            cache_version=str(self.CACHE_VERSION),
        )

        links = list(page.links_for_version(Version.parse(version)))
        if not links:
            raise PackageNotFound(
                'No valid distribution links found for package: "{}" version: "{}"'
                .format(name, version))
        urls = defaultdict(list)
        files = []
        for link in links:
            if link.is_wheel:
                urls["bdist_wheel"].append(link.url)
            elif link.filename.endswith(
                (".tar.gz", ".zip", ".bz2", ".xz", ".Z", ".tar")):
                urls["sdist"].append(link.url)

            h = link.hash
            if h:
                h = link.hash_name + ":" + link.hash
                files.append({"file": link.filename, "hash": h})

        data.files = files

        info = self._get_info_from_urls(urls)

        data.summary = info.summary
        data.requires_dist = info.requires_dist
        data.requires_python = info.requires_python

        return data.asdict()
Esempio n. 9
0
    def _transform_version(self, version: str, pretty_version: str) -> str:
        try:
            parsed = Version.parse(version)
            parts = [parsed.major, parsed.minor, parsed.patch]
        except ValueError:
            return pretty_version

        parts = parts[:parsed.precision]

        # check to see if we have a semver-looking version
        if len(parts) < 3:
            version = pretty_version
        else:
            version = ".".join(str(p) for p in parts)
            if parsed.is_unstable():
                version += "-{}".format(parsed.pre.to_string())

        return "^{}".format(version)
Esempio n. 10
0
    def link_version(self, link: Link) -> Optional[Version]:
        m = wheel_file_re.match(link.filename)
        if m:
            version = m.group("ver")
        else:
            info, ext = link.splitext()
            match = self.VERSION_REGEX.match(info)
            if not match:
                return None

            version = match.group(2)

        try:
            version = Version.parse(version)
        except ValueError:
            return None

        return version
Esempio n. 11
0
def test_intersect():
    v = Version.parse("1.2.3")

    assert v.intersect(v) == v
    assert v.intersect(Version.parse("1.1.4")).is_empty()
    assert (
        v.intersect(VersionRange(Version.parse("1.1.4"), Version.parse("1.2.4"))) == v
    )
    assert (
        Version.parse("1.1.4")
        .intersect(VersionRange(v, Version.parse("1.2.4")))
        .is_empty()
    )
Esempio n. 12
0
def test_deactivate_activated(
    tmp_dir: str,
    manager: EnvManager,
    poetry: Poetry,
    config: Config,
    mocker: MockerFixture,
):
    if "VIRTUAL_ENV" in os.environ:
        del os.environ["VIRTUAL_ENV"]

    venv_name = manager.generate_env_name("simple-project",
                                          str(poetry.file.parent))
    version = Version.from_parts(*sys.version_info[:3])
    other_version = Version.parse(
        "3.4") if version.major == 2 else version.next_minor()
    (Path(tmp_dir) / f"{venv_name}-py{version.major}.{version.minor}").mkdir()
    (Path(tmp_dir) /
     f"{venv_name}-py{other_version.major}.{other_version.minor}").mkdir()

    envs_file = TOMLFile(Path(tmp_dir) / "envs.toml")
    doc = tomlkit.document()
    doc[venv_name] = {
        "minor": f"{other_version.major}.{other_version.minor}",
        "patch": other_version.text,
    }
    envs_file.write(doc)

    config.merge({"virtualenvs": {"path": str(tmp_dir)}})

    mocker.patch(
        "subprocess.check_output",
        side_effect=check_output_wrapper(),
    )

    manager.deactivate(NullIO())
    env = manager.get()

    assert env.path == Path(
        tmp_dir) / f"{venv_name}-py{version.major}.{version.minor}"
    assert Path("/prefix")

    envs = envs_file.read()
    assert len(envs) == 0
Esempio n. 13
0
def test_remove_by_python_version(
    mocker: MockerFixture,
    tester: CommandTester,
    venvs_in_cache_dirs: list[str],
    venv_name: str,
    venv_cache: Path,
):
    check_output = mocker.patch(
        "subprocess.check_output",
        side_effect=check_output_wrapper(Version.parse("3.6.6")),
    )

    tester.execute("3.6")

    assert check_output.called
    assert not (venv_cache / f"{venv_name}-py3.6").exists()

    expected = f"Deleted virtualenv: {venv_cache / venv_name}-py3.6\n"
    assert tester.io.fetch_output() == expected
Esempio n. 14
0
    def _get_release_info(self, name: str, version: str) -> dict[str, Any]:
        page = self._get_page(f"/{canonicalize_name(name).replace('.', '-')}/")
        if page is None:
            raise PackageNotFound(f'No package named "{name}"')

        links = list(page.links_for_version(name, Version.parse(version)))

        return self._links_to_data(
            links,
            PackageInfo(
                name=name,
                version=version,
                summary="",
                platform=None,
                requires_dist=[],
                requires_python=None,
                files=[],
                cache_version=str(self.CACHE_VERSION),
            ),
        )
Esempio n. 15
0
def test_locker_should_neither_emit_warnings_nor_raise_error_for_lower_compatible_versions(
        locker, caplog):
    current_version = Version.parse(Locker._VERSION)
    older_version = ".".join(
        [str(current_version.major),
         str(current_version.minor - 1)])
    content = """\
[metadata]
content-hash = "c3d07fca33fba542ef2b2a4d75bf5b48d892d21a830e2ad9c952ba5123a52f77"
lock-version = "{version}"
python-versions = "~2.7 || ^3.4"

[metadata.files]
""".format(version=older_version)
    caplog.set_level(logging.WARNING, logger="poetry.packages.locker")

    locker.lock.write(tomlkit.parse(content))

    _ = locker.lock_data

    assert 0 == len(caplog.records)
Esempio n. 16
0
def test_create_venv_uses_patch_version_to_detect_compatibility(
    manager: EnvManager,
    poetry: Poetry,
    config: Config,
    mocker: MockerFixture,
    config_virtualenvs_path: Path,
):
    if "VIRTUAL_ENV" in os.environ:
        del os.environ["VIRTUAL_ENV"]

    version = Version.from_parts(*sys.version_info[:3])
    poetry.package.python_versions = "^" + ".".join(
        str(c) for c in sys.version_info[:3])
    venv_name = manager.generate_env_name("simple-project",
                                          str(poetry.file.parent))

    mocker.patch("sys.version_info",
                 (version.major, version.minor, version.patch + 1))
    check_output = mocker.patch(
        "subprocess.check_output",
        side_effect=check_output_wrapper(Version.parse("3.6.9")),
    )
    m = mocker.patch("poetry.utils.env.EnvManager.build_venv",
                     side_effect=lambda *args, **kwargs: "")

    manager.create_venv(NullIO())

    assert not check_output.called
    m.assert_called_with(
        config_virtualenvs_path /
        f"{venv_name}-py{version.major}.{version.minor}",
        executable=None,
        flags={
            "always-copy": False,
            "system-site-packages": False,
            "no-pip": False,
            "no-setuptools": False,
        },
        prompt=f"simple-project-py{version.major}.{version.minor}",
    )
Esempio n. 17
0
def test_remove_by_name(
    tmp_dir: str,
    manager: EnvManager,
    poetry: "Poetry",
    config: "Config",
    mocker: "MockerFixture",
):
    config.merge({"virtualenvs": {"path": str(tmp_dir)}})

    venv_name = manager.generate_env_name("simple-project", str(poetry.file.parent))
    (Path(tmp_dir) / f"{venv_name}-py3.7").mkdir()
    (Path(tmp_dir) / f"{venv_name}-py3.6").mkdir()

    mocker.patch(
        "subprocess.check_output",
        side_effect=check_output_wrapper(Version.parse("3.6.6")),
    )

    venv = manager.remove(f"{venv_name}-py3.6")

    assert (Path(tmp_dir) / f"{venv_name}-py3.6") == venv.path
    assert not (Path(tmp_dir) / f"{venv_name}-py3.6").exists()
Esempio n. 18
0
    def __init__(self,
                 version_info=(3, 7, 0),
                 python_implementation="CPython",
                 platform="darwin",
                 os_name="posix",
                 is_venv=False,
                 pip_version="19.1",
                 sys_path=None,
                 marker_env=None,
                 supported_tags=None,
                 **kwargs):
        super(MockEnv, self).__init__(**kwargs)

        self._version_info = version_info
        self._python_implementation = python_implementation
        self._platform = platform
        self._os_name = os_name
        self._is_venv = is_venv
        self._pip_version = Version.parse(pip_version)
        self._sys_path = sys_path
        self._mock_marker_env = marker_env
        self._supported_tags = supported_tags
Esempio n. 19
0
def test_create_venv_uses_patch_version_to_detect_compatibility_with_executable(
    manager: EnvManager,
    poetry: "Poetry",
    config: "Config",
    mocker: "MockerFixture",
    config_virtualenvs_path: Path,
):
    if "VIRTUAL_ENV" in os.environ:
        del os.environ["VIRTUAL_ENV"]

    version = Version.from_parts(*sys.version_info[:3])
    poetry.package.python_versions = f"~{version.major}.{version.minor-1}.0"
    venv_name = manager.generate_env_name("simple-project",
                                          str(poetry.file.parent))

    check_output = mocker.patch(
        "subprocess.check_output",
        side_effect=check_output_wrapper(
            Version.parse(f"{version.major}.{version.minor - 1}.0")),
    )
    m = mocker.patch("poetry.utils.env.EnvManager.build_venv",
                     side_effect=lambda *args, **kwargs: "")

    manager.create_venv(
        NullIO(), executable=f"python{version.major}.{version.minor - 1}")

    assert check_output.called
    m.assert_called_with(
        config_virtualenvs_path /
        f"{venv_name}-py{version.major}.{version.minor - 1}",
        executable=f"python{version.major}.{version.minor - 1}",
        flags={
            "always-copy": False,
            "system-site-packages": False
        },
        with_pip=True,
        with_setuptools=True,
        with_wheel=True,
    )
Esempio n. 20
0
def test_self_update_can_update_from_recommended_installation(
    tester: CommandTester,
    repo: TestRepository,
    installed: TestRepository,
):
    new_version = Version.parse(__version__).next_minor().text

    old_poetry = Package("poetry", __version__)
    old_poetry.add_dependency(Factory.create_dependency("cleo", "^0.8.2"))

    new_poetry = Package("poetry", new_version)
    new_poetry.add_dependency(Factory.create_dependency("cleo", "^1.0.0"))

    installed.add_package(old_poetry)
    installed.add_package(Package("cleo", "0.8.2"))

    repo.add_package(new_poetry)
    repo.add_package(Package("cleo", "1.0.0"))

    tester.execute()

    expected_output = f"""\
Updating Poetry version ...

Using version ^{new_version} for poetry

Updating dependencies
Resolving dependencies...

Writing lock file

Package operations: 0 installs, 2 updates, 0 removals

  • Updating cleo (0.8.2 -> 1.0.0)
  • Updating poetry ({__version__} -> {new_version})
"""

    assert tester.io.fetch_output() == expected_output
Esempio n. 21
0
def test_add_constraint_with_source_old_installer(
    app: "PoetryTestApplication",
    poetry: "Poetry",
    installer: "NoopInstaller",
    old_tester: "CommandTester",
):
    repo = LegacyRepository(name="my-index", url="https://my-index.fake")
    repo.add_package(get_package("cachy", "0.2.0"))
    repo._cache.store("matches").put("cachy:0.2.0", [Version.parse("0.2.0")],
                                     5)

    poetry.pool.add_repository(repo)

    old_tester.execute("cachy=0.2.0 --source my-index")

    expected = """\

Updating dependencies
Resolving dependencies...

Writing lock file

Package operations: 1 install, 0 updates, 0 removals

  - Installing cachy (0.2.0)
"""

    assert expected == old_tester.io.fetch_output()

    assert len(installer.installs) == 1

    content = app.poetry.file.read()["tool"]["poetry"]

    assert "cachy" in content["dependencies"]
    assert content["dependencies"]["cachy"] == {
        "version": "0.2.0",
        "source": "my-index",
    }
Esempio n. 22
0
def test_create_venv_fails_if_current_python_version_is_not_supported(
        manager: EnvManager, poetry: Poetry):
    if "VIRTUAL_ENV" in os.environ:
        del os.environ["VIRTUAL_ENV"]

    manager.create_venv(NullIO())

    current_version = Version.parse(".".join(
        str(c) for c in sys.version_info[:3]))
    next_version = ".".join(
        str(c) for c in (current_version.major, current_version.minor + 1, 0))
    package_version = "~" + next_version
    poetry.package.python_versions = package_version

    with pytest.raises(InvalidCurrentPythonVersionError) as e:
        manager.create_venv(NullIO())

    expected_message = (
        f"Current Python version ({current_version}) is not allowed by the project"
        f' ({package_version}).\nPlease change python executable via the "env use"'
        " command.")

    assert expected_message == str(e.value)
Esempio n. 23
0
    def __init__(
        self,
        version_info: Tuple[int, int, int] = (3, 7, 0),
        python_implementation: str = "CPython",
        platform: str = "darwin",
        os_name: str = "posix",
        is_venv: bool = False,
        pip_version: str = "19.1",
        sys_path: Optional[List[str]] = None,
        marker_env: Dict[str, Any] = None,
        supported_tags: List[Tag] = None,
        **kwargs: Any,
    ):
        super(MockEnv, self).__init__(**kwargs)

        self._version_info = version_info
        self._python_implementation = python_implementation
        self._platform = platform
        self._os_name = os_name
        self._is_venv = is_venv
        self._pip_version = Version.parse(pip_version)
        self._sys_path = sys_path
        self._mock_marker_env = marker_env
        self._supported_tags = supported_tags
Esempio n. 24
0
    def __init__(
            self,
            version_info=(3, 7, 0),  # type: Tuple[int, int, int]
            python_implementation="CPython",  # type: str
            platform="darwin",  # type: str
            os_name="posix",  # type: str
            is_venv=False,  # type: bool
            pip_version="19.1",  # type: str
            sys_path=None,  # type: Optional[List[str]]
            marker_env=None,  # type: Dict[str, Any]
            supported_tags=None,  # type: List[Tag]
            **kwargs,  # type: Any
    ):
        super(MockEnv, self).__init__(**kwargs)

        self._version_info = version_info
        self._python_implementation = python_implementation
        self._platform = platform
        self._os_name = os_name
        self._is_venv = is_venv
        self._pip_version = Version.parse(pip_version)
        self._sys_path = sys_path
        self._mock_marker_env = marker_env
        self._supported_tags = supported_tags
Esempio n. 25
0
def test_create_venv_tries_to_find_a_compatible_python_executable_using_generic_ones_first(
        manager, poetry, config, mocker, config_virtualenvs_path):
    if "VIRTUAL_ENV" in os.environ:
        del os.environ["VIRTUAL_ENV"]

    poetry.package.python_versions = "^3.6"
    venv_name = manager.generate_env_name("simple-project",
                                          str(poetry.file.parent))

    mocker.patch("sys.version_info", (2, 7, 16))
    mocker.patch(
        "subprocess.check_output",
        side_effect=check_output_wrapper(Version.parse("3.7.5")),
    )
    m = mocker.patch("poetry.utils.env.EnvManager.build_venv",
                     side_effect=lambda *args, **kwargs: "")

    manager.create_venv(NullIO())

    m.assert_called_with(
        config_virtualenvs_path / "{}-py3.7".format(venv_name),
        executable="python3",
        flags={"always-copy": False},
    )
Esempio n. 26
0
def test_remove_also_deactivates(tmp_dir, manager, poetry, config, mocker):
    config.merge({"virtualenvs": {"path": str(tmp_dir)}})

    venv_name = manager.generate_env_name("simple-project", str(poetry.file.parent))
    (Path(tmp_dir) / "{}-py3.7".format(venv_name)).mkdir()
    (Path(tmp_dir) / "{}-py3.6".format(venv_name)).mkdir()

    mocker.patch(
        "subprocess.check_output",
        side_effect=check_output_wrapper(Version.parse("3.6.6")),
    )

    envs_file = TOMLFile(Path(tmp_dir) / "envs.toml")
    doc = tomlkit.document()
    doc[venv_name] = {"minor": "3.6", "patch": "3.6.6"}
    envs_file.write(doc)

    venv = manager.remove("python3.6")

    assert (Path(tmp_dir) / "{}-py3.6".format(venv_name)) == venv.path
    assert not (Path(tmp_dir) / "{}-py3.6".format(venv_name)).exists()

    envs = envs_file.read()
    assert venv_name not in envs
Esempio n. 27
0
def test_remove_by_python_version(
    tmp_dir: str,
    manager: EnvManager,
    poetry: Poetry,
    config: Config,
    mocker: MockerFixture,
):
    config.merge({"virtualenvs": {"path": str(tmp_dir)}})

    venv_name = manager.generate_env_name("simple-project",
                                          str(poetry.file.parent))
    (Path(tmp_dir) / f"{venv_name}-py3.7").mkdir()
    (Path(tmp_dir) / f"{venv_name}-py3.6").mkdir()

    mocker.patch(
        "subprocess.check_output",
        side_effect=check_output_wrapper(Version.parse("3.6.6")),
    )

    venv = manager.remove("3.6")

    expected_venv_path = Path(tmp_dir) / f"{venv_name}-py3.6"
    assert venv.path == expected_venv_path
    assert not expected_venv_path.exists()
Esempio n. 28
0
from __future__ import annotations

from pathlib import Path
from typing import TYPE_CHECKING
from typing import Any
from typing import Callable

from poetry.core.semver.version import Version


if TYPE_CHECKING:
    from poetry.core.version.pep440.version import PEP440Version

VERSION_3_7_1 = Version.parse("3.7.1")


def build_venv(path: Path | str, **_: Any) -> None:
    Path(path).mkdir(parents=True, exist_ok=True)


def check_output_wrapper(
    version: PEP440Version = VERSION_3_7_1,
) -> Callable[[str, Any, Any], str]:
    def check_output(cmd: str, *_: Any, **__: Any) -> str:
        if "sys.version_info[:3]" in cmd:
            return version.text
        elif "sys.version_info[:2]" in cmd:
            return f"{version.major}.{version.minor}"
        elif '-c "import sys; print(sys.executable)"' in cmd:
            return f"/usr/bin/{cmd.split()[0]}"
        else:
Esempio n. 29
0
def get_python_constraint_from_marker(
    marker: BaseMarker, ) -> VersionConstraint:
    from poetry.core.semver.empty_constraint import EmptyConstraint
    from poetry.core.semver.helpers import parse_constraint
    from poetry.core.semver.version import Version
    from poetry.core.semver.version_range import VersionRange

    python_marker = marker.only("python_version", "python_full_version")
    if python_marker.is_any():
        return VersionRange()

    if python_marker.is_empty():
        return EmptyConstraint()

    markers = convert_markers(marker)
    if contains_group_without_marker(markers, "python_version"):
        # groups are in disjunctive normal form (DNF),
        # an empty group means that python_version does not appear in this group,
        # which means that python_version is arbitrary for this group
        return VersionRange()

    ors = []
    for or_ in markers["python_version"]:
        ands = []
        for op, version in or_:
            # Expand python version
            if op == "==":
                if "*" not in version:
                    version = "~" + version
                    op = ""
            elif op == "!=":
                if "*" not in version:
                    version += ".*"
            elif op in ("<=", ">"):
                parsed_version = Version.parse(version)
                if parsed_version.precision == 1:
                    if op == "<=":
                        op = "<"
                        version = parsed_version.next_major().text
                    elif op == ">":
                        op = ">="
                        version = parsed_version.next_major().text
                elif parsed_version.precision == 2:
                    if op == "<=":
                        op = "<"
                        version = parsed_version.next_minor().text
                    elif op == ">":
                        op = ">="
                        version = parsed_version.next_minor().text
            elif op in ("in", "not in"):
                versions = []
                for v in re.split("[ ,]+", version):
                    split = v.split(".")
                    if len(split) in [1, 2]:
                        split.append("*")
                        op_ = "" if op == "in" else "!="
                    else:
                        op_ = "==" if op == "in" else "!="

                    versions.append(op_ + ".".join(split))

                glue = " || " if op == "in" else ", "
                if versions:
                    ands.append(glue.join(versions))

                continue

            ands.append(f"{op}{version}")

        ors.append(" ".join(ands))

    return parse_constraint(" || ".join(ors))
Esempio n. 30
0
def test_links_for_version(
    version_string: str, filenames: Iterable[str], link_source: LinkSource
) -> None:
    version = Version.parse(version_string)
    expected = {Link(f"{link_source.url}/{name}") for name in filenames}
    assert set(link_source.links_for_version("demo", version)) == expected