コード例 #1
0
ファイル: test_env.py プロジェクト: vsyakunin/poetry
def test_activate_activates_existing_virtualenv_no_envs_file(
        tmp_dir, manager, poetry, config, mocker):
    if "VIRTUAL_ENV" in os.environ:
        del os.environ["VIRTUAL_ENV"]

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

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

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

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

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

    m.assert_not_called()

    envs_file = TomlFile(Path(tmp_dir) / "envs.toml")
    assert envs_file.exists()
    envs = envs_file.read()
    assert envs[venv_name]["minor"] == "3.7"
    assert envs[venv_name]["patch"] == "3.7.1"

    assert env.path == Path(tmp_dir) / "{}-py3.7".format(venv_name)
    assert env.base == Path("/prefix")
コード例 #2
0
def test_activated(app, tmp_dir, config):
    app.poetry._config = config

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

    venv_name = EnvManager.generate_env_name("simple_project",
                                             str(app.poetry.file.parent))
    (Path(tmp_dir) / "{}-py3.7".format(venv_name)).mkdir()
    (Path(tmp_dir) / "{}-py3.6".format(venv_name)).mkdir()

    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)

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

    expected = """\
{}-py3.6
{}-py3.7 (Activated)
""".format(venv_name, venv_name)

    assert expected == tester.io.fetch_output()
コード例 #3
0
ファイル: test_env.py プロジェクト: vsyakunin/poetry
def test_get_prefers_explicitly_activated_virtualenvs_over_env_var(
        tmp_dir, manager, poetry, config, mocker):
    os.environ["VIRTUAL_ENV"] = "/environment/prefix"

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

    config.merge({"virtualenvs": {"path": str(tmp_dir)}})
    (Path(tmp_dir) / "{}-py3.7".format(venv_name)).mkdir()

    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)

    mocker.patch(
        "poetry.utils._compat.subprocess.check_output",
        side_effect=check_output_wrapper(),
    )
    mocker.patch(
        "poetry.utils._compat.subprocess.Popen.communicate",
        side_effect=[("/prefix", None)],
    )

    env = manager.get()

    assert env.path == Path(tmp_dir) / "{}-py3.7".format(venv_name)
    assert env.base == Path("/prefix")
コード例 #4
0
ファイル: test_env.py プロジェクト: vsyakunin/poetry
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(
        "poetry.utils._compat.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
コード例 #5
0
def test_pyproject_parsing(fixture):
    f = TomlFile(fixture.with_name('pyproject.toml'))

    content = f.read()

    assert 'dependencies' in content['tool']['poetry']
    assert content['tool']['poetry']['dependencies']['python'] == '^3.6'
コード例 #6
0
ファイル: test_toml_file.py プロジェクト: yunstanford/poetry
def test_pyproject_parsing(fixture):
    f = TomlFile(fixture.with_name("pyproject.toml"))

    content = f.read()

    assert "dependencies" in content["tool"]["poetry"]
    assert content["tool"]["poetry"]["dependencies"]["python"] == "^3.6"
コード例 #7
0
def test_activate_activates_non_existing_virtualenv_no_envs_file(
        mocker, tester, venv_cache, venv_name, venvs_in_cache_config):
    mocker.patch(
        "poetry.utils._compat.subprocess.check_output",
        side_effect=check_output_wrapper(),
    )

    mock_build_env = mocker.patch("poetry.utils.env.EnvManager.build_venv",
                                  side_effect=build_venv)

    tester.execute("3.7")

    venv_py37 = venv_cache / "{}-py3.7".format(venv_name)
    mock_build_env.assert_called_with(venv_py37, executable="python3.7")

    envs_file = TomlFile(venv_cache / "envs.toml")
    assert envs_file.exists()
    envs = envs_file.read()
    assert envs[venv_name]["minor"] == "3.7"
    assert envs[venv_name]["patch"] == "3.7.1"

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

    assert expected == tester.io.fetch_output()
コード例 #8
0
ファイル: test_env.py プロジェクト: vsyakunin/poetry
def test_activate_with_in_project_setting_does_not_fail_if_no_venvs_dir(
        manager, poetry, config, tmp_dir, mocker):
    if "VIRTUAL_ENV" in os.environ:
        del os.environ["VIRTUAL_ENV"]

    config.merge({
        "virtualenvs": {
            "path": str(Path(tmp_dir) / "virtualenvs"),
            "in-project": True,
        }
    })

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

    manager.activate("python3.7", NullIO())

    m.assert_called_with(os.path.join(str(poetry.file.parent), ".venv"),
                         executable="python3.7")

    envs_file = TomlFile(Path(tmp_dir) / "virtualenvs" / "envs.toml")
    assert not envs_file.exists()
コード例 #9
0
    def get(self, cwd, reload=False):  # type: (Path, bool) -> Env
        if self._env is not None and not reload:
            return self._env

        python_minor = ".".join([str(v) for v in sys.version_info[:2]])

        venv_path = self._config.get("virtualenvs.path")
        if venv_path is None:
            venv_path = Path(CACHE_DIR) / "virtualenvs"
        else:
            venv_path = Path(venv_path)

        envs_file = TomlFile(venv_path / self.ENVS_FILE)
        env = None
        base_env_name = self.generate_env_name(cwd.name, str(cwd))
        if envs_file.exists():
            envs = envs_file.read()
            env = envs.get(base_env_name)
            if env:
                python_minor = env["minor"]

        # Check if we are inside a virtualenv or not
        in_venv = os.environ.get("VIRTUAL_ENV") is not None

        if not in_venv or env is not None:
            # Checking if a local virtualenv exists
            if (cwd / ".venv").exists() and (cwd / ".venv").is_dir():
                venv = cwd / ".venv"

                return VirtualEnv(venv)

            create_venv = self._config.get("virtualenvs.create", True)

            if not create_venv:
                return SystemEnv(Path(sys.prefix))

            venv_path = self._config.get("virtualenvs.path")
            if venv_path is None:
                venv_path = Path(CACHE_DIR) / "virtualenvs"
            else:
                venv_path = Path(venv_path)

            name = "{}-py{}".format(base_env_name, python_minor.strip())

            venv = venv_path / name

            if not venv.exists():
                return SystemEnv(Path(sys.prefix))

            return VirtualEnv(venv)

        if os.environ.get("VIRTUAL_ENV") is not None:
            prefix = Path(os.environ["VIRTUAL_ENV"])
            base_prefix = None
        else:
            prefix = Path(sys.prefix)
            base_prefix = self.get_base_prefix()

        return VirtualEnv(prefix, base_prefix)
コード例 #10
0
    def install_directory(self, package):
        from poetry.io import NullIO
        from poetry.masonry.builder import SdistBuilder
        from poetry.poetry import Poetry
        from poetry.utils._compat import decode
        from poetry.utils.env import NullEnv
        from poetry.utils.toml_file import TomlFile

        if package.root_dir:
            req = os.path.join(package.root_dir, package.source_url)
        else:
            req = os.path.realpath(package.source_url)

        args = ["install", "--no-deps", "-U"]

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

        has_poetry = False
        has_build_system = False
        if pyproject.exists():
            pyproject_content = pyproject.read()
            has_poetry = ("tool" in pyproject_content
                          and "poetry" in pyproject_content["tool"])
            # Even if there is a build system specified
            # pip as of right now does not support it fully
            # TODO: Check for pip version when proper PEP-517 support lands
            # has_build_system = ("build-system" in pyproject_content)

        setup = os.path.join(req, "setup.py")
        has_setup = os.path.exists(setup)
        if not has_setup and has_poetry and (package.develop
                                             or not has_build_system):
            # We actually need to rely on creating a temporary setup.py
            # file since pip, as of this comment, does not support
            # build-system for editable packages
            # We also need it for non-PEP-517 packages
            builder = SdistBuilder(Poetry.create(pyproject.parent), NullEnv(),
                                   NullIO())

            with open(setup, "w", encoding="utf-8") as f:
                f.write(decode(builder.build_setup()))

        if package.develop:
            args.append("-e")

        args.append(req)

        if self._vendor_path:
            args += ["-t", self._vendor_path]

        try:
            return self.run(*args)
        finally:
            if not has_setup and os.path.exists(setup):
                os.remove(setup)
コード例 #11
0
ファイル: publisher.py プロジェクト: zymergen-luke/poetry
    def publish(self, repository_name, username, password):
        if repository_name:
            self._io.writeln(
                "Publishing <info>{}</info> (<comment>{}</comment>) "
                "to <fg=cyan>{}</>".format(
                    self._package.pretty_name,
                    self._package.pretty_version,
                    repository_name,
                ))
        else:
            self._io.writeln(
                "Publishing <info>{}</info> (<comment>{}</comment>) "
                "to <fg=cyan>PyPI</>".format(self._package.pretty_name,
                                             self._package.pretty_version))

        if not repository_name:
            url = "https://upload.pypi.org/legacy/"
            repository_name = "pypi"
        else:
            # Retrieving config information
            config_file = TomlFile(Path(CONFIG_DIR) / "config.toml")

            if not config_file.exists():
                raise RuntimeError("Config file does not exist. "
                                   "Unable to get repository information")

            config = config_file.read()

            if ("repositories" not in config
                    or repository_name not in config["repositories"]):
                raise RuntimeError(
                    "Repository {} is not defined".format(repository_name))

            url = config["repositories"][repository_name]["url"]

        if not (username and password):
            auth = get_http_basic_auth(self._poetry.auth_config,
                                       repository_name)
            if auth:
                username = auth[0]
                password = auth[1]

        # Requesting missing credentials
        if not username:
            username = self._io.ask("Username:"******"Password:")

        # TODO: handle certificates

        self._uploader.auth(username, password)

        return self._uploader.upload(url)
コード例 #12
0
    def install_directory(self, package):
        from poetry.factory import Factory
        from poetry.utils.toml_file import TomlFile

        if package.root_dir:
            req = (package.root_dir / package.source_url).as_posix()
        else:
            req = os.path.realpath(package.source_url)

        args = ["install", "--no-deps", "-U"]

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

        has_poetry = False
        has_build_system = False
        if pyproject.exists():
            pyproject_content = pyproject.read()
            has_poetry = (
                "tool" in pyproject_content and "poetry" in pyproject_content["tool"]
            )
            # Even if there is a build system specified
            # pip as of right now does not support it fully
            # TODO: Check for pip version when proper PEP-517 support lands
            # has_build_system = ("build-system" in pyproject_content)

        setup = os.path.join(req, "setup.py")
        has_setup = os.path.exists(setup)
        if has_poetry and (package.develop or not has_build_system):
            # We actually need to rely on creating a temporary setup.py
            # file since pip, as of this comment, does not support
            # build-system for editable packages
            # We also need it for non-PEP-517 packages
            from poetry.masonry.builders.editable import EditableBuilder

            builder = EditableBuilder(
                Factory().create_poetry(pyproject.parent), self._env, NullIO()
            )

            builder.build()

            return

        if package.develop:
            args.append("-e")

        args.append(req)

        try:
            return self.run(*args)
        finally:
            if not has_setup and os.path.exists(setup):
                os.remove(setup)
コード例 #13
0
ファイル: test_factory.py プロジェクト: trevenen/poetry
def test_validate_fails():
    complete = TomlFile(fixtures_dir / "complete.toml")
    content = complete.read()["tool"]["poetry"]
    content["this key is not in the schema"] = ""

    if PY2:
        expected = ("Additional properties are not allowed "
                    "(u'this key is not in the schema' was unexpected)")
    else:
        expected = ("Additional properties are not allowed "
                    "('this key is not in the schema' was unexpected)")

    assert Factory.validate(content) == {"errors": [expected], "warnings": []}
コード例 #14
0
ファイル: info.py プロジェクト: yahkun/poetry
 def _get_poetry_package(path):  # type: (Path) -> Optional[ProjectPackage]
     pyproject = path.joinpath("pyproject.toml")
     try:
         # Note: we ignore any setup.py file at this step
         if pyproject.exists():
             # TODO: add support for handling non-poetry PEP-517 builds
             pyproject = TomlFile(pyproject)
             pyproject_content = pyproject.read()
             supports_poetry = ("tool" in pyproject_content
                                and "poetry" in pyproject_content["tool"])
             if supports_poetry:
                 return Factory().create_poetry(path).package
     except RuntimeError:
         pass
コード例 #15
0
    def install_directory(self, package, update=False):
        from poetry.io import NullIO
        from poetry.masonry.builder import SdistBuilder
        from poetry.poetry import Poetry
        from poetry.utils._compat import decode
        from poetry.utils.env import NullEnv
        from poetry.utils.toml_file import TomlFile

        if package.root_dir:
            req = os.path.join(package.root_dir, package.source_url)
        else:
            req = os.path.realpath(package.source_url)

        args = ["install", "--no-deps", "-U"]

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

        has_poetry = False
        if pyproject.exists():
            pyproject_content = pyproject.read()
            has_poetry = ("tool" in pyproject_content
                          and "poetry" in pyproject_content["tool"])
            has_build_system = "build-system" in pyproject_content

        setup = os.path.join(req, "setup.py")
        has_setup = os.path.exists(setup)
        if not has_setup and has_poetry and (package.develop
                                             or not has_build_system):
            # We actually need to rely on creating a temporary setup.py
            # file since pip, as of this comment, does not support
            # build-system for editable packages
            # We also need it for non-PEP-517 packages
            builder = SdistBuilder(Poetry.create(pyproject.parent), NullEnv(),
                                   NullIO())

            with open(setup, "w") as f:
                f.write(decode(builder.build_setup()))

        if package.develop:
            args.append("-e")

        args.append(req)

        try:
            return self.run(*args)
        finally:
            if not has_setup and os.path.exists(setup):
                os.remove(setup)
コード例 #16
0
 def __init__(self, lock, local_config):
     self._lock = TomlFile(lock)
     self._local_config = local_config
     self._lock_data = None
     self._content_hash = self._get_content_hash()
     self._locked = False
     self._lock_data = None
コード例 #17
0
    def create(cls, pac_file: Path, modified=False):

        local_config = TomlFile(pac_file.as_posix()).read()
        if "package" not in local_config:
            raise RuntimeError("[package] section not found in {}".format(
                pac_file.name))
        # Checking validity
        cls.check(local_config)

        name = str(pac_file.parent).replace("/", ".")
        version = local_config["package"]["version"]

        if not modified:
            package = Package(name, version)
        else:
            old_version = _get_old_version(pac_file)
            package = ModifiedPackage(name, version, old_version)

        package.root_dir = pac_file.parent

        if "dependencies" in local_config:
            for name, constraint in local_config["dependencies"].items():
                package.add_dependency(name, constraint)

        if "dev-dependencies" in local_config:
            for name, constraint in local_config["dev-dependencies"].items():
                package.add_dependency(name, constraint, category="dev")

        return cls(pac_file, local_config, package)
コード例 #18
0
def test_activate_activates_non_existing_virtualenv_no_envs_file(
        app, tmp_dir, config, mocker):
    app.poetry._config = config

    if "VIRTUAL_ENV" in os.environ:
        del os.environ["VIRTUAL_ENV"]

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

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

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

    venv_name = EnvManager.generate_env_name("simple_project",
                                             str(app.poetry.file.parent))

    m.assert_called_with(os.path.join(tmp_dir, "{}-py3.7".format(venv_name)),
                         executable="python3.7")

    envs_file = TomlFile(Path(tmp_dir) / "envs.toml")
    assert envs_file.exists()
    envs = envs_file.read()
    assert envs[venv_name]["minor"] == "3.7"
    assert envs[venv_name]["patch"] == "3.7.1"

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

    assert expected == tester.io.fetch_output()
コード例 #19
0
def search_package(name):
    all_paths = set(Path(".").rglob("pac.toml"))
    found = None
    for path in all_paths:
        local_config = TomlFile(path.as_posix()).read()
        if local_config["package"]["name"] == name:
            found = Pac.create(path)
    return found
コード例 #20
0
    def __init__(self, file, local_config, package, locker, config):
        self._file = TomlFile(file)
        self._package = package
        self._local_config = local_config
        self._locker = Locker(locker.lock.path, locker._local_config)
        self._config = config

        # Configure sources
        self._pool = Pool()
コード例 #21
0
    def __init__(
            self,
            name,
            path,  # type: Path
            category="main",  # type: str
            optional=False,  # type: bool
            base=None,  # type: Path
            develop=True,  # type: bool
    ):
        self._path = path
        self._base = base
        self._full_path = path
        self._develop = develop
        self._supports_poetry = False

        if self._base and not self._path.is_absolute():
            self._full_path = self._base / self._path

        if not self._full_path.exists():
            raise ValueError("Directory {} does not exist".format(self._path))

        if self._full_path.is_file():
            raise ValueError("{} is a file, expected a directory".format(
                self._path))

        # Checking content to determine actions
        setup = self._full_path / "setup.py"
        pyproject = TomlFile(self._full_path / "pyproject.toml")
        if pyproject.exists():
            pyproject_content = pyproject.read()
            self._supports_poetry = ("tool" in pyproject_content
                                     and "poetry" in pyproject_content["tool"])

        if not setup.exists() and not self._supports_poetry:
            raise ValueError(
                "Directory {} does not seem to be a Python package".format(
                    self._full_path))

        super(DirectoryDependency, self).__init__(name,
                                                  "*",
                                                  category=category,
                                                  optional=optional,
                                                  allows_prereleases=True)
コード例 #22
0
    def __init__(self, file, local_config, package, locker):
        self._file = TomlFile(file)
        self._package = package
        self._local_config = local_config
        self._locker = Locker(locker.lock.path, locker._local_config)
        self._config = Config.create("config.toml")
        self._auth_config = Config.create("auth.toml")

        # Configure sources
        self._pool = Pool()
コード例 #23
0
ファイル: test_use.py プロジェクト: xantocoder/poetry-1
def test_get_prefers_explicitly_activated_virtualenvs_over_env_var(
    app, tmp_dir, mocker
):
    mocker.stopall()
    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])
    python_patch = ".".join(str(v) for v in current_python)

    app.poetry.config.merge({"virtualenvs": {"path": str(tmp_dir)}})
    (Path(tmp_dir) / "{}-py{}".format(venv_name, python_minor)).mkdir()

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

    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)],
    )

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

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

    assert expected == tester.io.fetch_output()
コード例 #24
0
def test_get_prefers_explicitly_activated_virtualenvs_over_env_var(
        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])
    python_patch = ".".join(str(v) for v in current_python[:3])
    venv_dir = venv_cache / "{}-py{}".format(venv_name, python_minor)
    venv_dir.mkdir(parents=True, exist_ok=True)

    envs_file = TomlFile(venv_cache / "envs.toml")
    doc = tomlkit.document()
    doc[venv_name] = {"minor": python_minor, "patch": python_patch}
    envs_file.write(doc)

    tester.execute(python_minor)

    expected = """\
Using virtualenv: {}
""".format(venv_dir)

    assert expected == tester.io.fetch_output()
コード例 #25
0
ファイル: test_env.py プロジェクト: yahkun/poetry
def test_deactivate_activated(tmp_dir, manager, poetry, config, mocker):
    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.parse(".".join(str(c) for c in sys.version_info[:3]))
    other_version = Version.parse("3.4") if version.major == 2 else version.next_minor
    (
        Path(tmp_dir) / "{}-py{}.{}".format(venv_name, version.major, version.minor)
    ).mkdir()
    (
        Path(tmp_dir)
        / "{}-py{}.{}".format(venv_name, other_version.major, other_version.minor)
    ).mkdir()

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

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

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

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

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

    envs = envs_file.read()
    assert len(envs) == 0
コード例 #26
0
ファイル: test_toml_file.py プロジェクト: yunstanford/poetry
def test_toml_file(fixture):
    f = TomlFile(fixture)

    content = f.read()

    assert content[""]["title"] == "TOML Example"

    assert content["owner"]["name"] == "Tom Preston-Werner"
    assert isinstance(content["owner"], dict)

    assert isinstance(content["database"]["ports"], list)
    assert content["database"]["ports"] == [8001, 8001, 8002]
    assert content["database"]["connection_max"] == 5000
    assert content["database"]["enabled"]

    servers = content["servers"]
    assert len(servers) == 2
    alpha = servers["alpha"]
    assert len(alpha) == 2
    assert alpha["ip"] == "10.0.0.1"
    assert alpha["dc"] == "eqdc10"
    beta = servers["beta"]
    assert len(beta) == 2
    assert beta["ip"] == "10.0.0.2"
    assert beta["dc"] == "eqdc10"

    clients = content["clients"]
    assert len(clients["data"]) == 2
    assert clients["data"] == [["gamma", "delta"], [1, 2]]
    assert clients["hosts"] == ["alpha", "omega"]
    assert clients["str_multiline"] == "Roses are red\nViolets are blue"

    fruits = content["fruit"]
    assert len(fruits) == 2
    apple = fruits[0]
    assert len(apple) == 3
    banana = fruits[1]
    assert len(banana["variety"][0]["points"]) == 3
コード例 #27
0
def test_toml_file(fixture):
    f = TomlFile(fixture)

    content = f.read()

    assert content['']['title'] == 'TOML Example'

    assert content['owner']['name'] == 'Tom Preston-Werner'
    assert isinstance(content['owner'], dict)

    assert isinstance(content['database']['ports'], list)
    assert content['database']['ports'] == [8001, 8001, 8002]
    assert content['database']['connection_max'] == 5000
    assert content['database']['enabled']

    servers = content['servers']
    assert len(servers) == 2
    alpha = servers['alpha']
    assert len(alpha) == 2
    assert alpha['ip'] == '10.0.0.1'
    assert alpha['dc'] == 'eqdc10'
    beta = servers['beta']
    assert len(beta) == 2
    assert beta['ip'] == '10.0.0.2'
    assert beta['dc'] == 'eqdc10'

    clients = content['clients']
    assert len(clients['data']) == 2
    assert clients['data'] == [['gamma', 'delta'], [1, 2]]
    assert clients['hosts'] == ['alpha', 'omega']
    assert clients['str_multiline'] == 'Roses are red\nViolets are blue'

    fruits = content['fruit']
    assert len(fruits) == 2
    apple = fruits[0]
    assert len(apple) == 3
    banana = fruits[1]
    assert len(banana['variety'][0]['points']) == 3
コード例 #28
0
def test_activate_activates_recreates_for_different_patch(
    tmp_dir, manager, poetry, config, mocker
):
    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, "{}-py3.7".format(venv_name)))

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

    mocker.patch(
        "poetry.utils._compat.subprocess.check_output",
        side_effect=check_output_wrapper(),
    )
    mocker.patch(
        "poetry.utils._compat.subprocess.Popen.communicate",
        side_effect=[
            ("/prefix", None),
            ('{"version_info": [3, 7, 0]}', None),
            ("/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=remove_venv
    )

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

    build_venv_m.assert_called_with(
        os.path.join(tmp_dir, "{}-py3.7".format(venv_name)), executable="python3.7"
    )
    remove_venv_m.assert_called_with(
        os.path.join(tmp_dir, "{}-py3.7".format(venv_name))
    )

    assert envs_file.exists()
    envs = envs_file.read()
    assert envs[venv_name]["minor"] == "3.7"
    assert envs[venv_name]["patch"] == "3.7.1"

    assert env.path == Path(tmp_dir) / "{}-py3.7".format(venv_name)
    assert env.base == Path("/prefix")
    assert (Path(tmp_dir) / "{}-py3.7".format(venv_name)).exists()
コード例 #29
0
    def handle(self):
        # Load poetry config and display errors, if any
        poetry_file = Poetry.locate(Path.cwd())
        config = TomlFile(str(poetry_file)).read()["tool"]["poetry"]
        check_result = Poetry.check(config, strict=True)
        if not check_result["errors"] and not check_result["warnings"]:
            self.info("All set!")

            return 0

        for error in check_result["errors"]:
            self.line("<error>Error: {}</error>".format(error))

        for error in check_result["warnings"]:
            self.line("<warning>Warning: {}</warning>".format(error))

        return 1
コード例 #30
0
ファイル: test_env.py プロジェクト: yudai-nkt/poetry
def test_activate_does_not_recreate_when_switching_minor(tmp_dir, config, mocker):
    if "VIRTUAL_ENV" in os.environ:
        del os.environ["VIRTUAL_ENV"]

    venv_name = EnvManager.generate_env_name("simple_project", str(CWD))
    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, "{}-py3.7".format(venv_name)))
    os.mkdir(os.path.join(tmp_dir, "{}-py3.6".format(venv_name)))

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

    mocker.patch(
        "poetry.utils._compat.subprocess.check_output",
        side_effect=check_output_wrapper(Version.parse("3.6.6")),
    )
    mocker.patch(
        "poetry.utils._compat.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=remove_venv
    )

    env = EnvManager(config).activate("python3.6", CWD, 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) / "{}-py3.6".format(venv_name)
    assert env.base == Path("/prefix")
    assert (Path(tmp_dir) / "{}-py3.6".format(venv_name)).exists()
コード例 #31
0
ファイル: locker.py プロジェクト: singulared/poetry
 def __init__(self, lock, local_config):  # type: (Path, dict) -> None
     self._lock = TomlFile(lock)
     self._local_config = local_config
     self._lock_data = None
     self._content_hash = self._get_content_hash()
コード例 #32
0
ファイル: locker.py プロジェクト: singulared/poetry
class Locker:

    _relevant_keys = ["dependencies", "dev-dependencies", "source", "extras"]

    def __init__(self, lock, local_config):  # type: (Path, dict) -> None
        self._lock = TomlFile(lock)
        self._local_config = local_config
        self._lock_data = None
        self._content_hash = self._get_content_hash()

    @property
    def lock(self):  # type: () -> TomlFile
        return self._lock

    @property
    def lock_data(self):
        if self._lock_data is None:
            self._lock_data = self._get_lock_data()

        return self._lock_data

    def is_locked(self):  # type: () -> bool
        """
        Checks whether the locker has been locked (lockfile found).
        """
        if not self._lock.exists():
            return False

        return "package" in self.lock_data

    def is_fresh(self):  # type: () -> bool
        """
        Checks whether the lock file is still up to date with the current hash.
        """
        lock = self._lock.read()
        metadata = lock.get("metadata", {})

        if "content-hash" in metadata:
            return self._content_hash == lock["metadata"]["content-hash"]

        return False

    def locked_repository(
        self, with_dev_reqs=False
    ):  # type: (bool) -> poetry.repositories.Repository
        """
        Searches and returns a repository of locked packages.
        """
        if not self.is_locked():
            return poetry.repositories.Repository()

        lock_data = self.lock_data
        packages = poetry.repositories.Repository()

        if with_dev_reqs:
            locked_packages = lock_data["package"]
        else:
            locked_packages = [
                p for p in lock_data["package"] if p["category"] == "main"
            ]

        if not locked_packages:
            return packages

        for info in locked_packages:
            package = poetry.packages.Package(
                info["name"], info["version"], info["version"]
            )
            package.description = info.get("description", "")
            package.category = info["category"]
            package.optional = info["optional"]
            package.hashes = lock_data["metadata"]["hashes"][info["name"]]
            package.python_versions = info["python-versions"]

            for dep_name, constraint in info.get("dependencies", {}).items():
                if isinstance(constraint, list):
                    for c in constraint:
                        package.add_dependency(dep_name, c)

                    continue

                package.add_dependency(dep_name, constraint)

            if "requirements" in info:
                package.requirements = info["requirements"]

            if "source" in info:
                package.source_type = info["source"]["type"]
                package.source_url = info["source"]["url"]
                package.source_reference = info["source"]["reference"]

            packages.add_package(package)

        return packages

    def set_lock_data(self, root, packages):  # type: () -> bool
        hashes = {}
        packages = self._lock_packages(packages)
        # Retrieving hashes
        for package in packages:
            if package["name"] not in hashes:
                hashes[package["name"]] = []

            hashes[package["name"]] += package["hashes"]
            del package["hashes"]

        lock = document()
        lock["package"] = packages

        if root.extras:
            lock["extras"] = {
                extra: [dep.pretty_name for dep in deps]
                for extra, deps in root.extras.items()
            }

        lock["metadata"] = {
            "python-versions": root.python_versions,
            "platform": root.platform,
            "content-hash": self._content_hash,
            "hashes": hashes,
        }

        if not self.is_locked() or lock != self.lock_data:
            self._write_lock_data(lock)

            return True

        return False

    def _write_lock_data(self, data):
        self.lock.write(data)

        # Checking lock file data consistency
        if data != self.lock.read():
            raise RuntimeError("Inconsistent lock file data.")

        self._lock_data = None

    def _get_content_hash(self):  # type: () -> str
        """
        Returns the sha256 hash of the sorted content of the composer file.
        """
        content = self._local_config

        relevant_content = {}
        for key in self._relevant_keys:
            relevant_content[key] = content.get(key)

        content_hash = sha256(
            json.dumps(relevant_content, sort_keys=True).encode()
        ).hexdigest()

        return content_hash

    def _get_lock_data(self):  # type: () -> dict
        if not self._lock.exists():
            raise RuntimeError("No lockfile found. Unable to read locked packages")

        return self._lock.read()

    def _lock_packages(
        self, packages
    ):  # type: (List['poetry.packages.Package']) -> list
        locked = []

        for package in sorted(packages, key=lambda x: x.name):
            spec = self._dump_package(package)

            locked.append(spec)

        return locked

    def _dump_package(self, package):  # type: (poetry.packages.Package) -> dict
        dependencies = {}
        for dependency in sorted(package.requires, key=lambda d: d.name):
            if dependency.is_optional() and not dependency.is_activated():
                continue

            if dependency.pretty_name not in dependencies:
                dependencies[dependency.pretty_name] = []

            constraint = {"version": str(dependency.pretty_constraint)}

            if not dependency.python_constraint.is_any():
                constraint["python"] = str(dependency.python_constraint)

            if dependency.platform != "*":
                constraint["platform"] = dependency.platform

            if len(constraint) == 1:
                dependencies[dependency.pretty_name].append(constraint["version"])
            else:
                dependencies[dependency.pretty_name].append(constraint)

        for name, constraints in dependencies.items():
            if len(constraints) == 1:
                dependencies[name] = constraints[0]

        data = {
            "name": package.pretty_name,
            "version": package.pretty_version,
            "description": package.description,
            "category": package.category,
            "optional": package.optional,
            "python-versions": package.python_versions,
            "platform": package.platform,
            "hashes": sorted(package.hashes),
        }

        if dependencies:
            for k, constraints in dependencies.items():
                if len(constraints) == 1:
                    dependencies[k] = constraints[0]

            data["dependencies"] = dependencies

        if package.source_type:
            data["source"] = {
                "type": package.source_type,
                "url": package.source_url,
                "reference": package.source_reference,
            }

        if package.requirements:
            data["requirements"] = package.requirements

        return data
コード例 #33
0
ファイル: test_poetry.py プロジェクト: shawegit/poetry
def test_check():
    complete = TomlFile(fixtures_dir / "complete.toml")
    content = complete.read(raw=True)["tool"]["poetry"]

    assert Poetry.check(content)
コード例 #34
0
ファイル: publisher.py プロジェクト: singulared/poetry
    def publish(self, repository_name, username, password):
        if repository_name:
            self._io.writeln(
                "Publishing <info>{}</info> (<comment>{}</comment>) "
                "to <fg=cyan>{}</>".format(
                    self._package.pretty_name,
                    self._package.pretty_version,
                    repository_name,
                )
            )
        else:
            self._io.writeln(
                "Publishing <info>{}</info> (<comment>{}</comment>) "
                "to <fg=cyan>PyPI</>".format(
                    self._package.pretty_name, self._package.pretty_version
                )
            )

        if not repository_name:
            url = "https://upload.pypi.org/legacy/"
            repository_name = "pypi"
        else:
            # Retrieving config information
            config_file = TomlFile(Path(CONFIG_DIR) / "config.toml")

            if not config_file.exists():
                raise RuntimeError(
                    "Config file does not exist. "
                    "Unable to get repository information"
                )

            config = config_file.read()

            if (
                "repositories" not in config
                or repository_name not in config["repositories"]
            ):
                raise RuntimeError(
                    "Repository {} is not defined".format(repository_name)
                )

            url = config["repositories"][repository_name]["url"]

        if not (username and password):
            auth = get_http_basic_auth(repository_name)
            if auth:
                username = auth[0]
                password = auth[1]

        # Requesting missing credentials
        if not username:
            username = self._io.ask("Username:"******"Password:")

        # TODO: handle certificates

        self._uploader.auth(username, password)

        return self._uploader.upload(url)
コード例 #35
0
ファイル: provider.py プロジェクト: singulared/poetry
    def search_for_vcs(self, dependency):  # type: (VCSDependency) -> List[Package]
        """
        Search for the specifications that match the given VCS dependency.

        Basically, we clone the repository in a temporary directory
        and get the information we need by checking out the specified reference.
        """
        if dependency.vcs != "git":
            raise ValueError("Unsupported VCS dependency {}".format(dependency.vcs))

        tmp_dir = Path(mkdtemp(prefix="pypoetry-git-{}".format(dependency.name)))

        try:
            git = Git()
            git.clone(dependency.source, tmp_dir)
            git.checkout(dependency.reference, tmp_dir)
            revision = git.rev_parse(dependency.reference, tmp_dir).strip()

            if dependency.tag or dependency.rev:
                revision = dependency.reference

            pyproject = TomlFile(tmp_dir / "pyproject.toml")
            pyproject_content = None
            has_poetry = False
            if pyproject.exists():
                pyproject_content = pyproject.read()
                has_poetry = (
                    "tool" in pyproject_content
                    and "poetry" in pyproject_content["tool"]
                )

            if pyproject_content and has_poetry:
                # If a pyproject.toml file exists
                # We use it to get the information we need
                info = pyproject_content["tool"]["poetry"]

                name = info["name"]
                version = info["version"]
                package = Package(name, version, version)
                package.source_type = dependency.vcs
                package.source_url = dependency.source
                package.source_reference = dependency.reference
                for req_name, req_constraint in info["dependencies"].items():
                    if req_name == "python":
                        package.python_versions = req_constraint
                        continue

                    package.add_dependency(req_name, req_constraint)
            else:
                # We need to use setup.py here
                # to figure the information we need
                # We need to place ourselves in the proper
                # folder for it to work
                venv = Venv.create(self._io)

                current_dir = os.getcwd()
                os.chdir(tmp_dir.as_posix())

                try:
                    venv.run("python", "setup.py", "egg_info")

                    # Sometimes pathlib will fail on recursive
                    # symbolic links, so we need to workaround it
                    # and use the glob module instead.
                    # Note that this does not happen with pathlib2
                    # so it's safe to use it for Python < 3.4.
                    if PY35:
                        egg_info = next(
                            Path(p)
                            for p in glob.glob(
                                os.path.join(str(tmp_dir), "**", "*.egg-info"),
                                recursive=True,
                            )
                        )
                    else:
                        egg_info = next(tmp_dir.glob("**/*.egg-info"))

                    meta = pkginfo.UnpackedSDist(str(egg_info))

                    if meta.requires_dist:
                        reqs = list(meta.requires_dist)
                    else:
                        reqs = []
                        requires = egg_info / "requires.txt"
                        if requires.exists():
                            with requires.open() as f:
                                reqs = parse_requires(f.read())

                    package = Package(meta.name, meta.version)

                    for req in reqs:
                        dep = dependency_from_pep_508(req)
                        if dep.in_extras:
                            for extra in dep.in_extras:
                                if extra not in package.extras:
                                    package.extras[extra] = []

                                package.extras[extra].append(dep)

                        package.requires.append(dep)
                except Exception:
                    raise
                finally:
                    os.chdir(current_dir)

            package.source_type = "git"
            package.source_url = dependency.source
            package.source_reference = revision
        except Exception:
            raise
        finally:
            shutil.rmtree(tmp_dir.as_posix())

        if dependency.name != package.name:
            # For now, the dependency's name must match the actual package's name
            raise RuntimeError(
                "The dependency name for {} does not match the actual package's name: {}".format(
                    dependency.name, package.name
                )
            )

        if dependency.extras:
            for extra in dependency.extras:
                if extra in package.extras:
                    for dep in package.extras[extra]:
                        dep.activate()

        return [package]
コード例 #36
0
ファイル: test_installer.py プロジェクト: singulared/poetry
def fixture(name):
    file = TomlFile(Path(__file__).parent / "fixtures" / "{}.test".format(name))

    return file.read()
コード例 #37
0
    def __init__(
        self,
        path,  # type: Path
        category="main",  # type: str
        optional=False,  # type: bool
        base=None,  # type: Path
        develop=False,  # type: bool
    ):
        from . import dependency_from_pep_508
        from .package import Package

        self._path = path
        self._base = base
        self._full_path = path
        self._develop = develop

        if self._base and not self._path.is_absolute():
            self._full_path = self._base / self._path

        if not self._full_path.exists():
            raise ValueError("Directory {} does not exist".format(self._path))

        if self._full_path.is_file():
            raise ValueError("{} is a file, expected a directory".format(self._path))

        # Checking content to dertermine actions
        setup = self._full_path / "setup.py"
        pyproject = TomlFile(self._full_path / "pyproject.toml")
        has_poetry = False
        if pyproject.exists():
            pyproject_content = pyproject.read(True)
            has_poetry = (
                "tool" in pyproject_content and "poetry" in pyproject_content["tool"]
            )

        if not setup.exists() and not has_poetry:
            raise ValueError(
                "Directory {} does not seem to be a Python package".format(
                    self._full_path
                )
            )

        if has_poetry:
            from poetry.masonry.builders import SdistBuilder
            from poetry.poetry import Poetry

            poetry = Poetry.create(self._full_path)
            builder = SdistBuilder(poetry, NullVenv(), NullIO())

            with setup.open("w") as f:
                f.write(decode(builder.build_setup()))

            package = poetry.package
            self._package = Package(package.pretty_name, package.version)
            self._package.requires += package.requires
            self._package.dev_requires += package.dev_requires
            self._package.python_versions = package.python_versions
            self._package.platform = package.platform
        else:
            # Execute egg_info
            current_dir = os.getcwd()
            os.chdir(str(self._full_path))

            try:
                cwd = base
                venv = Venv.create(NullIO(), cwd=cwd)
                venv.run("python", "setup.py", "egg_info")
            finally:
                os.chdir(current_dir)

            egg_info = list(self._full_path.glob("*.egg-info"))[0]

            meta = pkginfo.UnpackedSDist(str(egg_info))

            if meta.requires_dist:
                reqs = list(meta.requires_dist)
            else:
                reqs = []
                requires = egg_info / "requires.txt"
                if requires.exists():
                    with requires.open() as f:
                        reqs = parse_requires(f.read())

            package = Package(meta.name, meta.version)
            package.description = meta.summary

            for req in reqs:
                package.requires.append(dependency_from_pep_508(req))

            if meta.requires_python:
                package.python_versions = meta.requires_python

            if meta.platforms:
                platforms = [p for p in meta.platforms if p.lower() != "unknown"]
                if platforms:
                    package.platform = " || ".join(platforms)

            self._package = package

        self._package.source_type = "directory"
        self._package.source_url = self._path.as_posix()

        super(DirectoryDependency, self).__init__(
            self._package.name,
            self._package.version,
            category=category,
            optional=optional,
            allows_prereleases=True,
        )
コード例 #38
0
ファイル: test_poetry.py プロジェクト: singulared/poetry
def test_check_fails():
    complete = TomlFile(fixtures_dir / "complete.toml")
    content = complete.read()["tool"]["poetry"]
    content["this key is not in the schema"] = ""
    with pytest.raises(InvalidProjectFile):
        Poetry.check(content)