Esempio n. 1
0
    def __init__(
        self,
        candidates: Dict[str, Candidate],
        environment: Environment,
        clean: bool = False,
        dry_run: bool = False,
        retry_times: int = 1,
        install_self: bool = False,
        no_editable: bool = False,
    ) -> None:
        self.environment = environment
        self.clean = clean
        self.dry_run = dry_run
        self.retry_times = retry_times
        self.no_editable = no_editable
        self.install_self = install_self

        self.parallel = environment.project.config["parallel_install"]
        locked_repository = environment.project.locked_repository
        self.all_candidate_keys = list(locked_repository.all_candidates)
        self.working_set = environment.get_working_set()
        self.ui = environment.project.core.ui

        if self.no_editable:
            for candidate in candidates.values():
                candidate.req.editable = None  # type: ignore
        self.candidates = candidates
Esempio n. 2
0
 def __init__(
     self, candidates: Dict[str, Candidate], environment: Environment,
 ) -> None:
     self.candidates = candidates
     self.environment = environment
     self.parallel = environment.project.config["parallel_install"]
     self.working_set = environment.get_working_set()
Esempio n. 3
0
def ireq_as_line(ireq: InstallRequirement, environment: Environment) -> str:
    """Formats an `InstallRequirement` instance as a
    PEP 508 dependency string.

    Generic formatter for pretty printing InstallRequirements to the terminal
    in a less verbose way than using its `__str__` method.

    :param :class:`InstallRequirement` ireq: A pip **InstallRequirement** instance.
    :return: A formatted string for prettyprinting
    :rtype: str
    """
    if ireq.editable:
        line = "-e {}".format(ireq.link)
    else:
        if not ireq.req:
            ireq.req = parse_requirement("dummy @" + ireq.link.url)
            wheel = Wheel(environment.build(ireq))
            ireq.req.name = wheel.name

        line = _requirement_to_str_lowercase_name(ireq.req)

    if str(ireq.req.marker) != str(ireq.markers):
        if not ireq.req.marker:
            line = "{}; {}".format(line, ireq.markers)
        else:
            name, markers = line.split(";", 1)
            markers = Marker(markers) & ireq.markers
            line = "{}; {}".format(name, markers)

    return line
Esempio n. 4
0
def ireq_as_line(ireq: InstallRequirement, environment: Environment) -> str:
    """Formats an `InstallRequirement` instance as a
    PEP 508 dependency string.

    Generic formatter for pretty printing InstallRequirements to the terminal
    in a less verbose way than using its `__str__` method.

    :param :class:`InstallRequirement` ireq: A pip **InstallRequirement** instance.
    :return: A formatted string for prettyprinting
    :rtype: str
    """
    if ireq.editable:
        line = "-e {}".format(ireq.link)
    else:
        if not ireq.req:
            ireq.req = parse_requirement("dummy @" +
                                         ireq.link.url)  # type: ignore
            wheel = Wheel(environment.build(ireq))
            ireq.req.name = wheel.name  # type: ignore

        line = _requirement_to_str_lowercase_name(cast(PRequirement, ireq.req))
    assert ireq.req
    if not ireq.req.marker and ireq.markers:
        line = f"{line}; {ireq.markers}"

    return line
Esempio n. 5
0
File: core.py Progetto: pcskys/pdm
 def environment(self) -> Environment:
     if self.is_global:
         return GlobalEnvironment(self)
     if self.config["use_venv"] and "VIRTUAL_ENV" in os.environ:
         self.project_config["python.path"] = get_venv_python()
         return GlobalEnvironment(self)
     return Environment(self)
Esempio n. 6
0
def editables_candidate(environment: Environment) -> Candidate | None:
    """Return a candidate for `editables` package"""
    with environment.get_finder() as finder:
        best_match = finder.find_best_candidate("editables")
        if best_match.best_candidate is None:
            return None
        return Candidate.from_installation_candidate(
            best_match.best_candidate, parse_requirement("editables"),
            environment)
Esempio n. 7
0
 def get_environment(self) -> Environment:
     if self.is_global:
         env = GlobalEnvironment(self)
         # Rewrite global project's python requires to be
         # compatible with the exact version
         env.python_requires = PySpecSet(f"=={self.python.version}")
         return env
     if self.config["python.use_venv"]:
         if self.project_config.get("python.path") and not os.getenv(
                 "PDM_IGNORE_SAVED_PYTHON"):
             return (GlobalEnvironment(self) if is_venv_python(
                 self.python.executable) else Environment(self))
         if os.getenv("VIRTUAL_ENV"):
             venv = os.getenv("VIRTUAL_ENV")
             self.core.ui.echo(
                 f"Detected inside an active virtualenv {termui.green(venv)}, "
                 "reuse it.")
             # Temporary usage, do not save in .pdm.toml
             self._python = PythonInfo.from_path(get_venv_python(
                 Path(venv)))
             return GlobalEnvironment(self)
         existing_venv = next((venv for _, venv in iter_venvs(self)), None)
         if existing_venv:
             self.core.ui.echo(
                 f"Virtualenv {termui.green(str(existing_venv))} is reused.",
                 err=True,
             )
             path = existing_venv
         else:
             # Create a virtualenv using the selected Python interpreter
             self.core.ui.echo(
                 "python.use_venv is on, creating a virtualenv for this project...",
                 fg="yellow",
                 err=True,
             )
             backend: str = self.config["venv.backend"]
             venv_backend = BACKENDS[backend](self, None)
             path = venv_backend.create(None, (), False,
                                        self.config["venv.in_project"])
             self.core.ui.echo(f"Virtualenv {path} is created successfully")
         self.python = PythonInfo.from_path(get_venv_python(path))
         return GlobalEnvironment(self)
     else:
         return Environment(self)
Esempio n. 8
0
    def from_dist(cls: Type[_T], dist: Distribution,
                  environment: Environment) -> _T:
        """Create an instance from the distribution"""
        scheme = environment.get_paths()
        instance = cls(dist, environment)
        meta_location = os.path.normcase(dist._path.absolute())  # type: ignore
        dist_location = os.path.dirname(meta_location)
        if is_egg_link(dist):  # pragma: no cover
            egg_link_path = cast("Path | None",
                                 getattr(dist, "link_file", None))
            if not egg_link_path:
                termui.logger.warn(
                    "No egg link is found for editable distribution %s, do nothing.",
                    dist.metadata["Name"],
                )
            else:
                link_pointer = os.path.normcase(
                    egg_link_path.open("rb").readline().decode().strip())
                if link_pointer != dist_location:
                    raise UninstallError(
                        f"The link pointer in {egg_link_path} doesn't match "
                        f"the location of {dist.metadata['Name']}(at {dist_location}"
                    )
                instance.add_path(str(egg_link_path))
                instance.add_pth(link_pointer)
        elif dist.files:
            for file in dist.files:
                location = dist.locate_file(file)
                instance.add_path(str(location))
                bare_name, ext = os.path.splitext(location)
                if ext == ".py":
                    # .pyc files are added by add_path()
                    instance.add_path(bare_name + ".pyo")

        bin_dir = scheme["scripts"]

        if os.path.isdir(os.path.join(meta_location,
                                      "scripts")):  # pragma: no cover
            for script in os.listdir(os.path.join(meta_location, "scripts")):
                instance.add_path(os.path.join(bin_dir, script))
                if os.name == "nt":
                    instance.add_path(os.path.join(bin_dir, script) + ".bat")

        # find console_scripts
        _scripts_to_remove: list[str] = []
        for ep in dist.entry_points:
            if ep.group == "console_scripts":
                _scripts_to_remove.extend(_script_names(ep.name, False))
            elif ep.group == "gui_scripts":
                _scripts_to_remove.extend(_script_names(ep.name, True))

        for s in _scripts_to_remove:
            instance.add_path(os.path.join(bin_dir, s))
        return instance
Esempio n. 9
0
 def get_environment(self) -> Environment:
     """Get the environment selected by this project"""
     if self.is_global:
         env = GlobalEnvironment(self)
         # Rewrite global project's python requires to be
         # compatible with the exact version
         env.python_requires = PySpecSet(f"=={self.python.version}")
         return env
     if self.config["use_venv"] and is_venv_python(self.python.executable):
         # Only recognize venv created by python -m venv and virtualenv>20
         return GlobalEnvironment(self)
     return Environment(self)
Esempio n. 10
0
 def environment(self) -> Environment:
     if self.is_global:
         env = GlobalEnvironment(self)
         # Rewrite global project's python requires to be
         # compatible with the exact version
         env.python_requires = PySpecSet(
             "==" + get_python_version(self.python_executable, True)[0])
         return env
     if self.config["use_venv"] and is_venv_python(self.python_executable):
         # Only recognize venv created by python -m venv and virtualenv>20
         return GlobalEnvironment(self)
     return Environment(self)
Esempio n. 11
0
 def __init__(
     self,
     candidates: Dict[str, Candidate],
     environment: Environment,
     retry_times: int = 1,
 ) -> None:
     self.candidates = candidates
     self.environment = environment
     self.parallel = environment.project.config["parallel_install"]
     self.all_candidates = environment.project.get_locked_candidates(
         "__all__")
     self.working_set = environment.get_working_set()
     self.retry_times = retry_times
Esempio n. 12
0
 def environment(self) -> Environment:
     if self.is_global:
         env = GlobalEnvironment(self)
         # Rewrite global project's python requires to be
         # compatible with the exact version
         env.python_requires = PySpecSet(
             "==" + get_python_version(env.python_executable, True))
         return env
     if self.config["use_venv"]:
         venv_python = get_venv_python(self.root)
         if venv_python:
             self.project_config["python.path"] = venv_python
             return GlobalEnvironment(self)
     return Environment(self)
Esempio n. 13
0
def install_wheel(wheel: str,
                  environment: Environment,
                  direct_url: dict[str, Any] | None = None) -> None:
    """Install a normal wheel file into the environment."""
    additional_metadata = None
    if direct_url is not None:
        additional_metadata = {
            "direct_url.json": json.dumps(direct_url, indent=2).encode()
        }
    _install_wheel(
        wheel=wheel,
        interpreter=environment.interpreter.executable,
        script_kind=_get_kind(environment),
        scheme_dict=environment.get_paths(),
        additional_metadata=additional_metadata,
    )
Esempio n. 14
0
    def __init__(
        self,
        candidates: Dict[str, Candidate],
        environment: Environment,
        clean: bool = False,
        dry_run: bool = False,
        retry_times: int = 1,
        install_self: bool = False,
        no_editable: bool | Collection[str] = False,
        use_install_cache: bool = False,
        reinstall: bool = False,
    ) -> None:
        self.environment = environment
        self.clean = clean
        self.dry_run = dry_run
        self.retry_times = retry_times
        self.no_editable = no_editable
        self.install_self = install_self
        self.use_install_cache = use_install_cache
        self.reinstall = reinstall

        self.parallel = environment.project.config["install.parallel"]
        locked_repository = environment.project.locked_repository
        self.all_candidate_keys = list(locked_repository.all_candidates)
        self.working_set = environment.get_working_set()
        self.ui = environment.project.core.ui

        if isinstance(self.no_editable, Collection):
            keys = self.no_editable
        elif self.no_editable:
            keys = candidates.keys()
        else:
            keys = []
            if (self.install_self
                    and getattr(self.environment.project.meta,
                                "editable_backend", "path") == "editables"
                    and "editables" not in candidates):
                # Install `editables` as well as required by self project
                editables = editables_candidate(environment)
                if editables is not None:
                    candidates["editables"] = editables
        for key in keys:
            if key in candidates:
                candidates[key].req.editable = False
        self.candidates = candidates
        self._manager: InstallManager | None = None
Esempio n. 15
0
def install_wheel_with_cache(wheel: str,
                             environment: Environment,
                             direct_url: dict[str, Any] | None = None) -> None:
    """Only create .pth files referring to the cached package.
    If the cache doesn't exist, create one.
    """
    wheel_stem = Path(wheel).stem
    cache_path = environment.project.cache("packages") / wheel_stem
    package_cache = CachedPackage(cache_path)
    interpreter = environment.interpreter.executable
    script_kind = _get_kind(environment)
    if not cache_path.is_dir():
        logger.debug("Installing wheel into cached location %s", cache_path)
        cache_path.mkdir(exist_ok=True)
        _install_wheel(
            wheel=wheel,
            interpreter=interpreter,
            script_kind=script_kind,
            scheme_dict=package_cache.scheme(),
        )

    additional_metadata = {"REFER_TO": package_cache.path.as_posix().encode()}

    if direct_url is not None:
        additional_metadata["direct_url.json"] = json.dumps(direct_url,
                                                            indent=2).encode()

    def skip_files(scheme: Scheme, path: str) -> bool:
        return not (scheme == "scripts"
                    or path.split("/")[0].endswith(".dist-info")
                    or path.endswith(".pth"))

    filename = wheel_stem.split("-")[0] + ".pth"
    lib_path = package_cache.scheme()["purelib"]

    dist_info_dir = _install_wheel(
        wheel=wheel,
        interpreter=interpreter,
        script_kind=script_kind,
        scheme_dict=environment.get_paths(),
        excludes=skip_files,
        additional_files=[(None, filename,
                           io.BytesIO(f"{lib_path}\n".encode()))],
        additional_metadata=additional_metadata,
    )
    package_cache.add_referrer(dist_info_dir)
Esempio n. 16
0
 def environment(self) -> Environment:
     if self.is_global:
         env = GlobalEnvironment(self)
         # Rewrite global project's python requires to be
         # compatible with the exact version
         env.python_requires = PySpecSet(
             "==" + get_python_version(env.python_executable, True)[0])
         return env
     if not self.project_config.get(
             "python.path") and self.config["use_venv"]:
         venv_python = get_venv_python(self.root)
         if venv_python:
             self.project_config["python.path"] = venv_python
     if (self.config["use_venv"] and self.project_config.get("python.path")
             and Path(self.project_config.get("python.path")
                      ).parent.parent.joinpath("pyvenv.cfg").exists()):
         # Only recognize venv created by python -m venv and virtualenv>20
         return GlobalEnvironment(self)
     return Environment(self)
Esempio n. 17
0
def install_wheel_with_cache(wheel: str,
                             environment: Environment,
                             direct_url: dict[str, Any] | None = None) -> None:
    """Only create .pth files referring to the cached package.
    If the cache doesn't exist, create one.
    """
    wheel_stem = Path(wheel).stem
    cache_path = environment.project.cache("packages") / wheel_stem
    package_cache = CachedPackage(cache_path)
    interpreter = str(environment.interpreter.executable)
    script_kind = _get_kind(environment)
    supports_symlink = (environment.project.config["install.cache_method"]
                        == "symlink" and fs_supports_symlink())
    if not cache_path.is_dir():
        logger.debug("Installing wheel into cached location %s", cache_path)
        cache_path.mkdir(exist_ok=True)
        destination = InstallDestination(
            scheme_dict=package_cache.scheme(),
            interpreter=interpreter,
            script_kind=script_kind,
        )
        _install_wheel(wheel=wheel, destination=destination)

    additional_metadata = {"REFER_TO": package_cache.path.as_posix().encode()}

    if direct_url is not None:
        additional_metadata["direct_url.json"] = json.dumps(direct_url,
                                                            indent=2).encode()

    def skip_files(source: WheelFile, element: WheelContentElement) -> bool:
        root_scheme = _process_WHEEL_file(source)
        scheme, path = _determine_scheme(element[0][0], source, root_scheme)
        return not (
            scheme not in ("purelib", "platlib")
            or path.split("/")[0].endswith(".dist-info")
            # We need to skip the *-nspkg.pth files generated by setuptools'
            # namespace_packages merchanism. See issue#623 for details
            or not supports_symlink and path.endswith(".pth")
            and not path.endswith("-nspkg.pth"))

    additional_contents: list[WheelContentElement] = []
    lib_path = package_cache.scheme()["purelib"]
    if not supports_symlink:
        # HACK: Prefix with aaa_ to make it processed as early as possible
        filename = "aaa_" + wheel_stem.split("-")[0] + ".pth"
        stream = io.BytesIO(f"{lib_path}\n".encode())
        additional_contents.append(
            ((filename, "", str(len(stream.getvalue()))), stream, False))

    destination = InstallDestination(
        scheme_dict=environment.get_paths(),
        interpreter=interpreter,
        script_kind=script_kind,
        symlink_to=lib_path if supports_symlink else None,
    )

    dist_info_dir = _install_wheel(
        wheel=wheel,
        destination=destination,
        excludes=skip_files,
        additional_contents=additional_contents,
        additional_metadata=additional_metadata,
    )
    package_cache.add_referrer(dist_info_dir)
Esempio n. 18
0
 def environment(self) -> Environment:
     return Environment(self.python_requires, self.config)