Exemple #1
0
def test_parse_constraint_multi_wilcard(input):
    assert parse_constraint(input) == VersionUnion(
        VersionRange(
            Version.from_parts(2, 7, 0), Version.from_parts(3, 0, 0), True, False
        ),
        VersionRange(Version.from_parts(3, 2, 0), None, True, False),
    )
def test_parse_constraint_multi(input: str) -> None:
    assert parse_constraint(input) == VersionRange(
        Version.from_parts(2, 0, 0),
        Version.from_parts(3, 0, 0),
        include_min=False,
        include_max=True,
    )
Exemple #3
0
    def _get_lock_data(self) -> "TOMLDocument":
        if not self._lock.exists():
            raise RuntimeError(
                "No lockfile found. Unable to read locked packages")

        try:
            lock_data = self._lock.read()
        except TOMLKitError as e:
            raise RuntimeError(f"Unable to read the lock file ({e}).")

        lock_version = Version.parse(lock_data["metadata"].get(
            "lock-version", "1.0"))
        current_version = Version.parse(self._VERSION)
        # We expect the locker to be able to read lock files
        # from the same semantic versioning range
        accepted_versions = parse_constraint("^{}".format(
            Version.from_parts(current_version.major, 0)))
        lock_version_allowed = accepted_versions.allows(lock_version)
        if lock_version_allowed and current_version < lock_version:
            logger.warning(
                "The lock file might not be compatible with the current version of Poetry.\n"
                "Upgrade Poetry to ensure the lock file is read properly or, alternatively, "
                "regenerate the lock file with the `poetry lock` command.")
        elif not lock_version_allowed:
            raise RuntimeError(
                "The lock file is not compatible with the current version of Poetry.\n"
                "Upgrade Poetry to be able to read the lock file or, alternatively, "
                "regenerate the lock file with the `poetry lock` command.")

        return lock_data
Exemple #4
0
    def _setup_build(self) -> None:
        builder = SdistBuilder(self._poetry)
        setup = self._path / "setup.py"
        has_setup = setup.exists()

        if has_setup:
            self._io.write_error_line(
                "<warning>A setup.py file already exists. Using it.</warning>")
        else:
            with setup.open("w", encoding="utf-8") as f:
                f.write(decode(builder.build_setup()))

        try:
            if self._env.pip_version < Version.from_parts(19, 0):
                pip_install(self._path, self._env, upgrade=True, editable=True)
            else:
                # Temporarily rename pyproject.toml
                shutil.move(str(self._poetry.file),
                            str(self._poetry.file.with_suffix(".tmp")))
                try:
                    pip_install(self._path,
                                self._env,
                                upgrade=True,
                                editable=True)
                finally:
                    shutil.move(
                        str(self._poetry.file.with_suffix(".tmp")),
                        str(self._poetry.file),
                    )
        finally:
            if not has_setup:
                os.remove(str(setup))
Exemple #5
0
def mock_subprocess_calls(setup, current_python, mocker):
    mocker.patch(
        "subprocess.check_output",
        side_effect=check_output_wrapper(Version.from_parts(*current_python)),
    )
    mocker.patch(
        "subprocess.Popen.communicate",
        side_effect=[("/prefix", None), ("/prefix", None), ("/prefix", None)],
    )
Exemple #6
0
def mock_subprocess_calls(setup: None, current_python: tuple[int, int, int],
                          mocker: MockerFixture) -> None:
    mocker.patch(
        "subprocess.check_output",
        side_effect=check_output_wrapper(Version.from_parts(*current_python)),
    )
    mocker.patch(
        "subprocess.Popen.communicate",
        side_effect=[("/prefix", None), ("/prefix", None), ("/prefix", None)],
    )
Exemple #7
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
Exemple #8
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}",
    )
Exemple #9
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,
    )
import pytest

from poetry.core.semver.helpers import parse_constraint
from poetry.core.semver.version import Version
from poetry.core.semver.version_range import VersionRange
from poetry.core.semver.version_union import VersionUnion


@pytest.mark.parametrize(
    "constraint,version",
    [
        (
            "~=3.8",
            VersionRange(
                min=Version.from_parts(3, 8),
                max=Version.from_parts(4, 0),
                include_min=True,
            ),
        ),
        (
            "== 3.8.*",
            VersionRange(
                min=Version.from_parts(3, 8),
                max=Version.from_parts(3, 9, 0),
                include_min=True,
            ),
        ),
        (
            "~= 3.8",
            VersionRange(
                min=Version.from_parts(3, 8),
Exemple #11
0
def parse_single_constraint(constraint: str) -> VersionConstraint:
    from poetry.core.semver.patterns import BASIC_CONSTRAINT
    from poetry.core.semver.patterns import CARET_CONSTRAINT
    from poetry.core.semver.patterns import TILDE_CONSTRAINT
    from poetry.core.semver.patterns import TILDE_PEP440_CONSTRAINT
    from poetry.core.semver.patterns import X_CONSTRAINT
    from poetry.core.semver.version import Version
    from poetry.core.semver.version_range import VersionRange
    from poetry.core.semver.version_union import VersionUnion

    m = re.match(r"(?i)^v?[xX*](\.[xX*])*$", constraint)
    if m:
        return VersionRange()

    # Tilde range
    m = TILDE_CONSTRAINT.match(constraint)
    if m:
        version = Version.parse(m.group("version"))
        high = version.stable.next_minor()
        if version.release.precision == 1:
            high = version.stable.next_major()

        return VersionRange(version, high, include_min=True)

    # PEP 440 Tilde range (~=)
    m = TILDE_PEP440_CONSTRAINT.match(constraint)
    if m:
        version = Version.parse(m.group("version"))
        if version.release.precision == 2:
            high = version.stable.next_major()
        else:
            high = version.stable.next_minor()

        return VersionRange(version, high, include_min=True)

    # Caret range
    m = CARET_CONSTRAINT.match(constraint)
    if m:
        version = Version.parse(m.group("version"))

        return VersionRange(version, version.next_breaking(), include_min=True)

    # X Range
    m = X_CONSTRAINT.match(constraint)
    if m:
        op = m.group("op")
        major = int(m.group(2))
        minor = m.group(3)

        if minor is not None:
            version = Version.from_parts(major, int(minor), 0)
            result: VersionConstraint = VersionRange(version,
                                                     version.next_minor(),
                                                     include_min=True)
        else:
            if major == 0:
                result = VersionRange(max=Version.from_parts(1, 0, 0))
            else:
                version = Version.from_parts(major, 0, 0)

                result = VersionRange(version,
                                      version.next_major(),
                                      include_min=True)

        if op == "!=":
            result = VersionRange().difference(result)

        return result

    # Basic comparator
    m = BASIC_CONSTRAINT.match(constraint)
    if m:
        op = m.group("op")
        version_string = m.group("version")

        if version_string == "dev":
            version_string = "0.0-dev"

        try:
            version = Version.parse(version_string)
        except ValueError:
            raise ValueError(
                f"Could not parse version constraint: {constraint}")

        if op == "<":
            return VersionRange(max=version)
        if op == "<=":
            return VersionRange(max=version, include_max=True)
        if op == ">":
            return VersionRange(min=version)
        if op == ">=":
            return VersionRange(min=version, include_min=True)
        if op == "!=":
            return VersionUnion(VersionRange(max=version),
                                VersionRange(min=version))
        return version

    from poetry.core.semver.exceptions import ParseConstraintError

    raise ParseConstraintError(
        f"Could not parse version constraint: {constraint}")
Exemple #12
0
import pytest

from poetry.core.semver.helpers import parse_constraint
from poetry.core.semver.version import Version
from poetry.core.semver.version_range import VersionRange
from poetry.core.semver.version_union import VersionUnion
from poetry.core.version.pep440 import ReleaseTag


@pytest.mark.parametrize(
    "constraint,version",
    [
        (
            "~=3.8",
            VersionRange(
                min=Version.from_parts(3, 8),
                max=Version.from_parts(4, 0),
                include_min=True,
            ),
        ),
        (
            "== 3.8.*",
            VersionRange(
                min=Version.from_parts(3, 8),
                max=Version.from_parts(3, 9, 0),
                include_min=True,
            ),
        ),
        (
            "~= 3.8",
            VersionRange(
from poetry.core.semver.helpers import parse_constraint
from poetry.core.semver.version import Version
from poetry.core.semver.version_range import VersionRange
from poetry.core.semver.version_union import VersionUnion
from poetry.core.version.pep440 import ReleaseTag


@pytest.mark.parametrize(
    "input,constraint",
    [
        ("*", VersionRange()),
        ("*.*", VersionRange()),
        ("v*.*", VersionRange()),
        ("*.x.*", VersionRange()),
        ("x.X.x.*", VersionRange()),
        (">1.0.0", VersionRange(min=Version.from_parts(1, 0, 0))),
        ("<1.2.3", VersionRange(max=Version.from_parts(1, 2, 3))),
        ("<=1.2.3",
         VersionRange(max=Version.from_parts(1, 2, 3), include_max=True)),
        (">=1.2.3",
         VersionRange(min=Version.from_parts(1, 2, 3), include_min=True)),
        ("=1.2.3", Version.from_parts(1, 2, 3)),
        ("1.2.3", Version.from_parts(1, 2, 3)),
        ("1!2.3.4", Version.from_parts(2, 3, 4, epoch=1)),
        ("=1.0", Version.from_parts(1, 0, 0)),
        ("1.2.3b5", Version.from_parts(1, 2, 3, pre=ReleaseTag("beta", 5))),
        (">= 1.2.3",
         VersionRange(min=Version.from_parts(1, 2, 3), include_min=True)),
        (
            ">dev",
            VersionRange(min=Version.from_parts(0, 0, dev=ReleaseTag("dev"))),
from __future__ import annotations

import pytest

from poetry.core.semver.empty_constraint import EmptyConstraint
from poetry.core.semver.version import Version
from poetry.core.semver.version_range import VersionRange
from poetry.core.version.exceptions import InvalidVersion
from poetry.core.version.pep440 import ReleaseTag


@pytest.mark.parametrize(
    "text,version",
    [
        ("1.0.0", Version.from_parts(1, 0, 0)),
        ("1", Version.from_parts(1, 0, 0)),
        ("1.0", Version.from_parts(1, 0, 0)),
        ("1b1", Version.from_parts(1, 0, 0, pre=ReleaseTag("beta", 1))),
        ("1.0b1", Version.from_parts(1, 0, 0, pre=ReleaseTag("beta", 1))),
        ("1.0.0b1", Version.from_parts(1, 0, 0, pre=ReleaseTag("beta", 1))),
        ("1.0.0-b1", Version.from_parts(1, 0, 0, pre=ReleaseTag("beta", 1))),
        ("1.0.0-beta.1", Version.from_parts(1, 0, 0, pre=ReleaseTag("beta",
                                                                    1))),
        ("1.0.0+1", Version.from_parts(1, 0, 0, local=1)),
        ("1.0.0-1", Version.from_parts(1, 0, 0, post=ReleaseTag("post", 1))),
        ("1.0.0.0", Version.from_parts(1, 0, 0, extra=0)),
        ("1.0.0-post", Version.from_parts(1, 0, 0, post=ReleaseTag("post"))),
        ("1.0.0-post1", Version.from_parts(1, 0, 0, post=ReleaseTag("post",
                                                                    1))),
        ("0.6c", Version.from_parts(0, 6, 0, pre=ReleaseTag("rc", 0))),
        ("0.6pre", Version.from_parts(0, 6, 0, pre=ReleaseTag("preview", 0))),
Exemple #15
0
    def install_directory(self, package: Package) -> str | int:
        from cleo.io.null_io import NullIO

        from poetry.factory import Factory

        assert package.source_url is not None
        if package.root_dir:
            req = package.root_dir / package.source_url
        else:
            req = Path(package.source_url).resolve(strict=False)

        pyproject = PyProjectTOML(os.path.join(req, "pyproject.toml"))

        if pyproject.is_poetry_project():
            # Even if there is a build system specified
            # some versions of pip (< 19.0.0) don't understand it
            # so we need to check the version of pip to know
            # if we can rely on the build system
            legacy_pip = self._env.pip_version < Version.from_parts(19, 0, 0)
            package_poetry = Factory().create_poetry(
                pyproject.file.path.parent)

            builder: Builder
            if package.develop and not package_poetry.package.build_script:
                from poetry.masonry.builders.editable import EditableBuilder

                # This is a Poetry package in editable mode
                # we can use the EditableBuilder without going through pip
                # to install it, unless it has a build script.
                builder = EditableBuilder(package_poetry, self._env, NullIO())
                builder.build()

                return 0
            elif legacy_pip or package_poetry.package.build_script:
                from poetry.core.masonry.builders.sdist import SdistBuilder

                # We need to rely on creating a temporary setup.py
                # file since the version of pip does not support
                # build-systems
                # We also need it for non-PEP-517 packages
                builder = SdistBuilder(package_poetry)

                with builder.setup_py():
                    if package.develop:
                        return pip_install(
                            path=req,
                            environment=self._env,
                            upgrade=True,
                            editable=True,
                        )
                    return pip_install(path=req,
                                       environment=self._env,
                                       deps=False,
                                       upgrade=True)

        if package.develop:
            return pip_install(path=req,
                               environment=self._env,
                               upgrade=True,
                               editable=True)
        return pip_install(path=req,
                           environment=self._env,
                           deps=False,
                           upgrade=True)