コード例 #1
0
ファイル: test_env.py プロジェクト: tony/poetry
def test_env_finds_the_correct_executables_for_generic_env(
    tmp_dir: str, manager: EnvManager
):
    venv_path = Path(tmp_dir) / "Virtual Env"
    child_venv_path = Path(tmp_dir) / "Child Virtual Env"
    manager.build_venv(str(venv_path), with_pip=True)
    parent_venv = VirtualEnv(venv_path)
    manager.build_venv(
        str(child_venv_path), executable=parent_venv.python, with_pip=True
    )
    venv = GenericEnv(parent_venv.path, child_env=VirtualEnv(child_venv_path))

    expected_executable = (
        f"python{sys.version_info[0]}.{sys.version_info[1]}{'.exe' if WINDOWS else ''}"
    )
    expected_pip_executable = (
        f"pip{sys.version_info[0]}.{sys.version_info[1]}{'.exe' if WINDOWS else ''}"
    )

    if WINDOWS:
        expected_executable = "python.exe"
        expected_pip_executable = "pip.exe"

    assert Path(venv.python).name == expected_executable
    assert Path(venv.pip).name == expected_pip_executable
コード例 #2
0
ファイル: test_env.py プロジェクト: jekinen/poetry
def test_env_commands_with_spaces_in_their_arg_work_as_expected(
        tmp_dir, manager):
    venv_path = Path(tmp_dir) / "Virtual Env"
    manager.build_venv(str(venv_path))
    venv = VirtualEnv(venv_path)
    assert venv.run("python", venv.pip, "--version", shell=True).startswith(
        "pip {} from ".format(venv.pip_version))
コード例 #3
0
def test_env_finds_the_correct_executables(tmp_dir, manager):
    venv_path = Path(tmp_dir) / "Virtual Env"
    manager.build_venv(str(venv_path), with_pip=True)
    venv = VirtualEnv(venv_path)

    default_executable = expected_executable = "python" + (".exe"
                                                           if WINDOWS else "")
    default_pip_executable = expected_pip_executable = "pip" + (
        ".exe" if WINDOWS else "")
    major_executable = "python{}{}".format(sys.version_info[0],
                                           ".exe" if WINDOWS else "")
    major_pip_executable = "pip{}{}".format(sys.version_info[0],
                                            ".exe" if WINDOWS else "")

    if (venv._bin_dir.joinpath(default_executable).exists()
            and venv._bin_dir.joinpath(major_executable).exists()):
        venv._bin_dir.joinpath(default_executable).unlink()
        expected_executable = major_executable

    if (venv._bin_dir.joinpath(default_pip_executable).exists()
            and venv._bin_dir.joinpath(major_pip_executable).exists()):
        venv._bin_dir.joinpath(default_pip_executable).unlink()
        expected_pip_executable = major_pip_executable

    venv = VirtualEnv(venv_path)

    assert Path(venv.python).name == expected_executable
    assert Path(venv.pip).name.startswith(
        expected_pip_executable.split(".")[0])
コード例 #4
0
ファイル: test_env.py プロジェクト: jekinen/poetry
def test_env_shell_commands_with_stdinput_in_their_arg_work_as_expected(
        tmp_dir, manager):
    venv_path = Path(tmp_dir) / "Virtual Env"
    manager.build_venv(str(venv_path))
    venv = VirtualEnv(venv_path)
    assert venv.run("python", "-", input_=GET_BASE_PREFIX,
                    shell=True).strip() == str(venv.get_base_prefix())
コード例 #5
0
ファイル: test_env.py プロジェクト: tony/poetry
def test_run_with_keyboard_interrupt(
    tmp_dir: str, tmp_venv: VirtualEnv, mocker: "MockerFixture"
):
    mocker.patch("subprocess.run", side_effect=KeyboardInterrupt())
    with pytest.raises(KeyboardInterrupt):
        tmp_venv.run("python", "-", input_=MINIMAL_SCRIPT)
    subprocess.run.assert_called_once()
コード例 #6
0
ファイル: test_env.py プロジェクト: timgates42/poetry
def test_run_with_called_process_error(tmp_dir: str, tmp_venv: VirtualEnv,
                                       mocker: MockerFixture):
    mocker.patch("subprocess.run",
                 side_effect=subprocess.CalledProcessError(42, "some_command"))
    with pytest.raises(EnvCommandError):
        tmp_venv.run("python", "-", input_=MINIMAL_SCRIPT)
    subprocess.run.assert_called_once()
コード例 #7
0
ファイル: test_env.py プロジェクト: tony/poetry
def test_run_with_input_non_zero_return(tmp_dir: str, tmp_venv: VirtualEnv):

    with pytest.raises(EnvCommandError) as process_error:
        # Test command that will return non-zero returncode.
        tmp_venv.run("python", "-", input_=ERRORING_SCRIPT)

    assert process_error.value.e.returncode == 1
コード例 #8
0
def test_virtualenvs_with_spaces_in_their_path_work_as_expected(tmp_dir):
    venv_path = Path(tmp_dir) / "Virtual Env"

    Env.build_venv(str(venv_path))

    venv = VirtualEnv(venv_path)

    assert venv.run("python", "-V", shell=True).startswith("Python")
コード例 #9
0
ファイル: test_env.py プロジェクト: tony/poetry
def test_call_no_input_with_keyboard_interrupt(
    tmp_dir: str, tmp_venv: VirtualEnv, mocker: "MockerFixture"
):
    mocker.patch("subprocess.call", side_effect=KeyboardInterrupt())
    kwargs = {"call": True}
    with pytest.raises(KeyboardInterrupt):
        tmp_venv.run("python", "-", **kwargs)
    subprocess.call.assert_called_once()
コード例 #10
0
ファイル: test_env.py プロジェクト: timgates42/poetry
def test_call_with_input_and_keyboard_interrupt(tmp_dir: str,
                                                tmp_venv: VirtualEnv,
                                                mocker: MockerFixture):
    mocker.patch("subprocess.run", side_effect=KeyboardInterrupt())
    kwargs = {"call": True}
    with pytest.raises(KeyboardInterrupt):
        tmp_venv.run("python", "-", input_=MINIMAL_SCRIPT, **kwargs)
    subprocess.run.assert_called_once()
コード例 #11
0
ファイル: test_env.py プロジェクト: timgates42/poetry
def test_env_get_supported_tags_matches_inside_virtualenv(
        tmp_dir: str, manager: EnvManager):
    venv_path = Path(tmp_dir) / "Virtual Env"
    manager.build_venv(str(venv_path))
    venv = VirtualEnv(venv_path)

    import packaging.tags

    assert venv.get_supported_tags() == list(packaging.tags.sys_tags())
コード例 #12
0
ファイル: test_env.py プロジェクト: timgates42/poetry
def test_call_no_input_with_called_process_error(tmp_dir: str,
                                                 tmp_venv: VirtualEnv,
                                                 mocker: MockerFixture):
    mocker.patch("subprocess.call",
                 side_effect=subprocess.CalledProcessError(42, "some_command"))
    kwargs = {"call": True}
    with pytest.raises(EnvCommandError):
        tmp_venv.run("python", "-", **kwargs)
    subprocess.call.assert_called_once()
コード例 #13
0
def test_env_finds_fallback_executables_for_generic_env(tmp_dir, manager):
    venv_path = Path(tmp_dir) / "Virtual Env"
    child_venv_path = Path(tmp_dir) / "Child Virtual Env"
    manager.build_venv(str(venv_path), with_pip=True)
    parent_venv = VirtualEnv(venv_path)
    manager.build_venv(str(child_venv_path),
                       executable=parent_venv.python,
                       with_pip=True)
    venv = GenericEnv(parent_venv.path, child_env=VirtualEnv(child_venv_path))

    default_executable = "python" + (".exe" if WINDOWS else "")
    major_executable = "python{}{}".format(sys.version_info[0],
                                           ".exe" if WINDOWS else "")
    minor_executable = "python{}.{}{}".format(sys.version_info[0],
                                              sys.version_info[1],
                                              ".exe" if WINDOWS else "")
    expected_executable = minor_executable
    if (venv._bin_dir.joinpath(expected_executable).exists()
            and venv._bin_dir.joinpath(major_executable).exists()):
        venv._bin_dir.joinpath(expected_executable).unlink()
        expected_executable = major_executable

    if (venv._bin_dir.joinpath(expected_executable).exists()
            and venv._bin_dir.joinpath(default_executable).exists()):
        venv._bin_dir.joinpath(expected_executable).unlink()
        expected_executable = default_executable

    default_pip_executable = "pip" + (".exe" if WINDOWS else "")
    major_pip_executable = "pip{}{}".format(sys.version_info[0],
                                            ".exe" if WINDOWS else "")
    minor_pip_executable = "pip{}.{}{}".format(sys.version_info[0],
                                               sys.version_info[1],
                                               ".exe" if WINDOWS else "")
    expected_pip_executable = minor_pip_executable
    if (venv._bin_dir.joinpath(expected_pip_executable).exists()
            and venv._bin_dir.joinpath(major_pip_executable).exists()):
        venv._bin_dir.joinpath(expected_pip_executable).unlink()
        expected_pip_executable = major_pip_executable

    if (venv._bin_dir.joinpath(expected_pip_executable).exists()
            and venv._bin_dir.joinpath(default_pip_executable).exists()):
        venv._bin_dir.joinpath(expected_pip_executable).unlink()
        expected_pip_executable = default_pip_executable

    if not venv._bin_dir.joinpath(expected_executable).exists():
        expected_executable = default_executable

    if not venv._bin_dir.joinpath(expected_pip_executable).exists():
        expected_pip_executable = default_pip_executable

    venv = GenericEnv(parent_venv.path, child_env=VirtualEnv(child_venv_path))

    assert Path(venv.python).name == expected_executable
    assert Path(venv.pip).name == expected_pip_executable
コード例 #14
0
def _sane_env(poetry, build_dir, io, clean=False):
    "Yield a sane virtual environment in build_dir."
    manager = EnvManager(poetry)
    if os.path.isdir(build_dir):
        env = VirtualEnv(build_dir)
        if clean or (not env.is_sane()):
            io.write_line(f"removing env {build_dir}")
            manager.remove_venv(build_dir)
    if not os.path.isdir(build_dir):
        io.write_line(f"building env {build_dir}")
        manager.build_venv(build_dir, executable=None)
    return VirtualEnv(build_dir)
コード例 #15
0
ファイル: info.py プロジェクト: yahkun/poetry
    def _pep517_metadata(cls, path):  # type (Path) -> PackageInfo
        """
        Helper method to use PEP-517 library to build and read package metadata.

        :param path: Path to package source to build and read metadata for.
        """
        info = None
        try:
            info = cls.from_setup_files(path)
            if info.requires_dist is not None:
                return info
        except PackageInfoError:
            pass

        with temporary_directory() as tmp_dir:
            # TODO: cache PEP 517 build environment corresponding to each project venv
            venv_dir = Path(tmp_dir) / ".venv"
            EnvManager.build_venv(venv_dir.as_posix())
            venv = VirtualEnv(venv_dir, venv_dir)

            dest_dir = Path(tmp_dir) / "dist"
            dest_dir.mkdir()

            try:
                venv.run("python", "-m", "pip", "install",
                         "--disable-pip-version-check", "--ignore-installed",
                         *PEP517_META_BUILD_DEPS)
                venv.run(
                    "python",
                    "-",
                    input_=PEP517_META_BUILD.format(source=path.as_posix(),
                                                    dest=dest_dir.as_posix()),
                )
                return cls.from_metadata(dest_dir)
            except EnvCommandError as e:
                # something went wrong while attempting pep517 metadata build
                # fallback to egg_info if setup.py available
                cls._log("PEP517 build failed: {}".format(e), level="debug")
                setup_py = path / "setup.py"
                if not setup_py.exists():
                    raise PackageInfoError(path)

                cwd = Path.cwd()
                os.chdir(path.as_posix())
                try:
                    venv.run("python", "setup.py", "egg_info")
                    return cls.from_metadata(path)
                except EnvCommandError:
                    raise PackageInfoError(path)
                finally:
                    os.chdir(cwd.as_posix())

        if info:
            cls._log(
                "Falling back to parsed setup.py file for {}".format(path),
                "debug")
            return info

        # if we reach here, everything has failed and all hope is lost
        raise PackageInfoError(path)
コード例 #16
0
ファイル: test_env.py プロジェクト: shutianxu/poetry
def test_env_site_packages_should_find_the_site_packages_directory_if_root(tmp_dir):
    site_packages = Path(tmp_dir).joinpath("site-packages")
    site_packages.mkdir(parents=True)

    env = VirtualEnv(Path(tmp_dir), Path(tmp_dir))

    assert site_packages == env.site_packages
コード例 #17
0
ファイル: test_env.py プロジェクト: mgasner/poetry
def tmp_venv(tmp_dir, config, request):
    venv_path = Path(tmp_dir) / "venv"

    EnvManager(config).build_venv(str(venv_path))

    venv = VirtualEnv(venv_path)
    yield venv

    shutil.rmtree(str(venv.path))
コード例 #18
0
def tmp_venv(tmp_dir: str) -> Iterator[VirtualEnv]:
    venv_path = Path(tmp_dir) / "venv"

    EnvManager.build_venv(str(venv_path))

    venv = VirtualEnv(venv_path)
    yield venv

    shutil.rmtree(str(venv.path))
コード例 #19
0
def tmp_venv(tmp_dir, env_manager):
    venv_path = Path(tmp_dir) / "venv"

    env_manager.build_venv(str(venv_path))

    venv = VirtualEnv(venv_path)
    yield venv

    shutil.rmtree(str(venv.path))
コード例 #20
0
def test_env_finds_the_correct_executables_for_generic_env(tmp_dir, manager):
    venv_path = Path(tmp_dir) / "Virtual Env"
    child_venv_path = Path(tmp_dir) / "Child Virtual Env"
    manager.build_venv(str(venv_path))
    parent_venv = VirtualEnv(venv_path)
    manager.build_venv(str(child_venv_path), executable=parent_venv.python)
    venv = GenericEnv(parent_venv.path, child_env=VirtualEnv(child_venv_path))

    expected_executable = "python{}.{}{}".format(sys.version_info[0],
                                                 sys.version_info[1],
                                                 ".exe" if WINDOWS else "")
    expected_pip_executable = "pip{}.{}{}".format(sys.version_info[0],
                                                  sys.version_info[1],
                                                  ".exe" if WINDOWS else "")

    if WINDOWS:
        expected_executable = "python.exe"
        expected_pip_executable = "pip.exe"

    assert Path(venv.python).name == expected_executable
    assert Path(venv.pip).name == expected_pip_executable
コード例 #21
0
ファイル: test_env.py プロジェクト: vsyakunin/poetry
def test_env_site_packages_should_find_the_site_packages_directory_if_standard(
        tmp_dir):
    if WINDOWS:
        site_packages = Path(tmp_dir).joinpath("Lib/site-packages")
    else:
        site_packages = Path(tmp_dir).joinpath(
            "lib/python{}/site-packages".format(".".join(
                str(v) for v in sys.version_info[:2])))

    site_packages.mkdir(parents=True)

    env = VirtualEnv(Path(tmp_dir), Path(tmp_dir))

    assert site_packages == env.site_packages
コード例 #22
0
ファイル: test_env.py プロジェクト: timgates42/poetry
def test_env_no_pip(tmp_path: Path, poetry: Poetry, flags: dict[str, bool],
                    packages: set[str]):
    venv_path = tmp_path / "venv"
    EnvManager(poetry).build_venv(path=venv_path, flags=flags)
    env = VirtualEnv(venv_path)
    installed_repository = InstalledRepository.load(env=env,
                                                    with_dependencies=True)
    installed_packages = {
        package.name
        for package in installed_repository.packages
        # workaround for BSD test environments
        if package.name != "sqlite3"
    }

    assert installed_packages == packages
コード例 #23
0
def test_env_has_symlinks_on_nix(tmp_dir):
    venv_path = Path(tmp_dir) / "Virtual Env"

    Env.build_venv(str(venv_path))

    venv = VirtualEnv(venv_path)

    venv_available = False
    try:
        from venv import EnvBuilder

        venv_available = True
    except ImportError:
        pass

    if os.name != "nt" and venv_available:
        assert os.path.islink(venv.python)
コード例 #24
0
    def activate(self, env: VirtualEnv) -> int | None:
        activate_script = self._get_activate_script()
        bin_dir = "Scripts" if WINDOWS else "bin"
        activate_path = env.path / bin_dir / activate_script

        # mypy requires using sys.platform instead of WINDOWS constant
        # in if statements to properly type check on Windows
        if sys.platform == "win32":
            if self._name in ("powershell", "pwsh"):
                args = ["-NoExit", "-File", str(activate_path)]
            else:
                # /K will execute the bat file and
                # keep the cmd process from terminating
                args = ["/K", str(activate_path)]
            completed_proc = subprocess.run([self.path, *args])
            return completed_proc.returncode

        import shlex

        terminal = Terminal()
        with env.temp_environ():
            c = pexpect.spawn(self._path, ["-i"],
                              dimensions=(terminal.height, terminal.width))

        if self._name == "zsh":
            c.setecho(False)

        c.sendline(
            f"{self._get_source_command()} {shlex.quote(str(activate_path))}")

        def resize(sig: Any, data: Any) -> None:
            terminal = Terminal()
            c.setwinsize(terminal.height, terminal.width)

        signal.signal(signal.SIGWINCH, resize)

        # Interact with the new shell.
        c.interact(escape_character=None)
        c.close()

        sys.exit(c.exitstatus)
コード例 #25
0
def test_uninstall_git_package_nspkg_pth_cleanup(
    mocker: MockerFixture, tmp_venv: VirtualEnv, pool: Pool
):
    # this test scenario requires a real installation using the pip installer
    installer = PipInstaller(tmp_venv, NullIO(), pool)

    # use a namepspace package
    package = Package(
        "namespace-package-one",
        "1.0.0",
        source_type="git",
        source_url="https://github.com/demo/namespace-package-one.git",
        source_reference="master",
    )

    # in order to reproduce the scenario where the git source is removed prior to proper
    # clean up of nspkg.pth file, we need to make sure the fixture is copied and not
    # symlinked into the git src directory
    def copy_only(source: Path, dest: Path) -> None:
        if dest.exists():
            dest.unlink()

        if source.is_dir():
            shutil.copytree(str(source), str(dest))
        else:
            shutil.copyfile(str(source), str(dest))

    mocker.patch("tests.helpers.copy_or_symlink", new=copy_only)

    # install package and then remove it
    installer.install(package)
    installer.remove(package)

    pth_file = f"{package.name}-nspkg.pth"
    assert not tmp_venv.site_packages.exists(pth_file)

    # any command in the virtual environment should trigger the error message
    output = tmp_venv.run("python", "-m", "site")
    assert not re.match(rf"Error processing line 1 of .*{pth_file}", output)
コード例 #26
0
 def _execute_setup(self):
     with temporary_directory() as tmp_dir:
         EnvManager.build_venv(tmp_dir)
         venv = VirtualEnv(Path(tmp_dir), Path(tmp_dir))
         venv.run("python", "setup.py", "egg_info")
コード例 #27
0
    def get_package_from_directory(
        cls, directory, name=None
    ):  # type: (Path, Optional[str]) -> Package
        supports_poetry = False
        pyproject = directory.joinpath("pyproject.toml")
        if pyproject.exists():
            pyproject = TomlFile(pyproject)
            pyproject_content = pyproject.read()
            supports_poetry = (
                "tool" in pyproject_content and "poetry" in pyproject_content["tool"]
            )

        if supports_poetry:
            poetry = Factory().create_poetry(directory)

            pkg = poetry.package
            package = Package(pkg.name, pkg.version)

            for dep in pkg.requires:
                if not dep.is_optional():
                    package.requires.append(dep)

            for extra, deps in pkg.extras.items():
                if extra not in package.extras:
                    package.extras[extra] = []

                for dep in deps:
                    package.extras[extra].append(dep)

            package.python_versions = pkg.python_versions
        else:
            # Execute egg_info
            current_dir = os.getcwd()
            os.chdir(str(directory))

            try:
                with temporary_directory() as tmp_dir:
                    EnvManager.build_venv(tmp_dir)
                    venv = VirtualEnv(Path(tmp_dir), Path(tmp_dir))
                    venv.run("python", "setup.py", "egg_info")
            except EnvCommandError:
                result = SetupReader.read_from_directory(directory)
                if not result["name"]:
                    # The name could not be determined
                    # We use the dependency name
                    result["name"] = name

                if not result["version"]:
                    # The version could not be determined
                    # so we raise an error since it is mandatory
                    raise RuntimeError(
                        "Unable to retrieve the package version for {}".format(
                            directory
                        )
                    )

                package_name = result["name"]
                package_version = result["version"]
                python_requires = result["python_requires"]
                if python_requires is None:
                    python_requires = "*"

                package_summary = ""

                requires = ""
                for dep in result["install_requires"]:
                    requires += dep + "\n"

                if result["extras_require"]:
                    requires += "\n"

                for extra_name, deps in result["extras_require"].items():
                    requires += "[{}]\n".format(extra_name)

                    for dep in deps:
                        requires += dep + "\n"

                    requires += "\n"

                reqs = parse_requires(requires)
            else:
                os.chdir(current_dir)
                # 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(directory), "**", "*.egg-info"),
                            recursive=True,
                        )
                    )
                else:
                    egg_info = next(directory.glob("**/*.egg-info"))

                meta = pkginfo.UnpackedSDist(str(egg_info))
                package_name = meta.name
                package_version = meta.version
                package_summary = meta.summary
                python_requires = meta.requires_python

                if meta.requires_dist:
                    reqs = list(meta.requires_dist)
                else:
                    reqs = []
                    requires = egg_info / "requires.txt"
                    if requires.exists():
                        with requires.open(encoding="utf-8") as f:
                            reqs = parse_requires(f.read())
            finally:
                os.chdir(current_dir)

            package = Package(package_name, package_version)
            package.description = package_summary

            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)

                if not dep.is_optional():
                    package.requires.append(dep)

            if python_requires:
                package.python_versions = python_requires

        if name and 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(
                    name, package.name
                )
            )

        package.source_type = "directory"
        package.source_url = directory.as_posix()

        return package
コード例 #28
0
ファイル: test_env.py プロジェクト: tony/poetry
def test_run_with_input(tmp_dir: str, tmp_venv: VirtualEnv):
    result = tmp_venv.run("python", "-", input_=MINIMAL_SCRIPT)

    assert result == "Minimal Output" + os.linesep