Exemplo n.º 1
0
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
Exemplo n.º 2
0
    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)
Exemplo n.º 3
0
def test_env_commands_with_spaces_in_their_arg_work_as_expected(
        tmp_dir: str, manager: EnvManager):
    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(f"pip {venv.pip_version} from ")
Exemplo n.º 4
0
def test_env_finds_the_correct_executables(tmp_dir: str, manager: EnvManager):
    venv_path = Path(tmp_dir) / "Virtual Env"
    manager.build_venv(str(venv_path), with_pip=True)
    venv = VirtualEnv(venv_path)

    default_executable = expected_executable = f"python{'.exe' if WINDOWS else ''}"
    default_pip_executable = expected_pip_executable = f"pip{'.exe' if WINDOWS else ''}"
    major_executable = f"python{sys.version_info[0]}{'.exe' if WINDOWS else ''}"
    major_pip_executable = f"pip{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])
Exemplo n.º 5
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))
Exemplo n.º 6
0
def test_virtualenvs_with_spaces_in_their_path_work_as_expected(
        tmp_dir: str, manager: EnvManager):
    venv_path = Path(tmp_dir) / "Virtual Env"

    manager.build_venv(str(venv_path))

    venv = VirtualEnv(venv_path)

    assert venv.run("python", "-V", shell=True).startswith("Python")
Exemplo n.º 7
0
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())
Exemplo n.º 8
0
def test_env_shell_commands_with_stdinput_in_their_arg_work_as_expected(
        tmp_dir: str, manager: EnvManager):
    venv_path = Path(tmp_dir) / "Virtual Env"
    manager.build_venv(str(venv_path))
    venv = VirtualEnv(venv_path)
    run_output_path = Path(
        venv.run("python", "-", input_=GET_BASE_PREFIX, shell=True).strip())
    venv_base_prefix_path = Path(str(venv.get_base_prefix()))
    assert run_output_path.resolve() == venv_base_prefix_path.resolve()
Exemplo n.º 9
0
def tmp_venv(tmp_dir: str, env_manager: EnvManager) -> VirtualEnv:
    venv_path = Path(tmp_dir) / "venv"

    env_manager.build_venv(str(venv_path))

    venv = VirtualEnv(venv_path)
    yield venv

    shutil.rmtree(str(venv.path))
Exemplo n.º 10
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)
Exemplo n.º 11
0
def test_env_finds_fallback_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))

    default_executable = f"python{'.exe' if WINDOWS else ''}"
    major_executable = f"python{sys.version_info[0]}{'.exe' if WINDOWS else ''}"
    minor_executable = (
        f"python{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 = f"pip{'.exe' if WINDOWS else ''}"
    major_pip_executable = f"pip{sys.version_info[0]}{'.exe' if WINDOWS else ''}"
    minor_pip_executable = (
        f"pip{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
Exemplo n.º 12
0
def test_venv_backup_exclusion(tmp_dir: str, manager: EnvManager):
    import xattr

    venv_path = Path(tmp_dir) / "Virtual Env"

    manager.build_venv(str(venv_path))

    value = (
        b"bplist00_\x10\x11com.apple.backupd"
        b"\x08\x00\x00\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00"
        b"\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1c"
    )
    assert (xattr.getxattr(
        str(venv_path),
        "com.apple.metadata:com_apple_backup_excludeItem") == value)
Exemplo n.º 13
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
Exemplo n.º 14
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")