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
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
def _populate_source_dir(self, ireq: pip_shims.InstallRequirement) -> None: assert self.link if self.link.is_existing_dir(): ireq.source_dir = self.link.file_path elif self.req.editable: if self.environment.packages_path: src_dir = self.environment.packages_path / "src" elif os.getenv("VIRTUAL_ENV"): src_dir = Path(os.environ["VIRTUAL_ENV"]) / "src" else: src_dir = Path("src") if not src_dir.is_dir(): src_dir.mkdir() ireq.ensure_has_source_dir(str(src_dir)) elif not ireq.source_dir: ireq.source_dir = create_tracked_tempdir(prefix="pdm-build-")
def _get_source_dir(self, ireq: pip_shims.InstallRequirement) -> str: if ireq.source_dir: return ireq.source_dir if ireq.link and ireq.link.is_existing_dir(): ireq.source_dir = ireq.link.file_path return ireq.source_dir if self.packages_path: src_dir = self.packages_path / "src" elif os.getenv("VIRTUAL_ENV", None): src_dir = Path(os.environ["VIRTUAL_ENV"]) / "src" else: src_dir = Path("src") if not src_dir.is_dir(): src_dir.mkdir() ireq.ensure_has_source_dir(str(src_dir)) assert ireq.source_dir return ireq.source_dir
def populate_link( finder: PackageFinder, ireq: InstallRequirement, upgrade: bool = False, ): """Populate ireq's link attribute""" if not ireq.link: link = finder.find_requirement(ireq, upgrade) if not link: return link = getattr(link, "link", link) ireq.link = link
def populate_link( finder: PackageFinder, ireq: InstallRequirement, upgrade: bool = False, ) -> None: """Populate ireq's link attribute""" if not ireq.link: candidate = finder.find_requirement(ireq, upgrade) if not candidate: return link = getattr(candidate, "link", candidate) ireq.link = link
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: req = parse_requirement("dummy @" + ireq.link.url) # type: ignore req.name = Candidate(req).prepare(environment).metadata.metadata["Name"] ireq.req = req # type: ignore line = _requirement_to_str_lowercase_name(ireq) if ireq.markers: line = f"{line}; {ireq.markers}" return line
def build( self, ireq: pip_shims.InstallRequirement, hashes: Optional[Dict[str, str]] = None, allow_all: bool = True, ) -> str: """Build egg_info directory for editable candidates and a wheel for others. :param ireq: the InstallRequirment of the candidate. :param hashes: a dictionary of filename: hash_value to check against downloaded artifacts. :param allow_all: Allow building incompatible wheels. :returns: The full path of the built artifact. """ kwargs = self._make_building_args(ireq) wheel_cache = self.project.make_wheel_cache() with self.get_finder() as finder: with allow_all_wheels(allow_all): # temporarily allow all wheels to get a link. populate_link(finder, ireq, False) if hashes is None: cache_entry = wheel_cache.get_cache_entry( ireq.link, ireq.req.project_name, pip_shims.get_supported( version="".join( map( str, get_python_version(self.python_executable)[0][:2], ) ) ), ) if cache_entry is not None: stream.logger.debug( "Using cached wheel link: %s", cache_entry.link ) ireq.link = cache_entry.link if not ireq.editable and not ireq.req.name: ireq.source_dir = kwargs["build_dir"] else: ireq.ensure_has_source_dir(kwargs["build_dir"]) download_dir = kwargs["download_dir"] only_download = False if ireq.link.is_wheel: download_dir = kwargs["wheel_download_dir"] only_download = True if hashes: ireq.hash_options = convert_hashes(hashes) if not (ireq.editable and ireq.req.is_local_dir): downloader = pip_shims.Downloader(finder.session, "off") if ireq.link.is_vcs: ireq.link = pip_shims.Link(expand_env_vars_in_auth(ireq.link.url)) downloaded = pip_shims.unpack_url( ireq.link, ireq.source_dir, downloader, download_dir, ireq.hashes(False), ) # Preserve the downloaded file so that it won't be cleared. if downloaded and only_download: try: shutil.copy(downloaded.path, download_dir) except shutil.SameFileError: pass if ireq.link.is_wheel: # If the file is a wheel, should be already present under download dir. return (self.project.cache("wheels") / ireq.link.filename).as_posix() else: # Check the built wheel cache again after hashes are resolved. cache_entry = wheel_cache.get_cache_entry( ireq.link, ireq.req.project_name, pip_shims.get_supported( version="".join( map(str, get_python_version(self.python_executable)[0][:2]) ) ), ) if cache_entry is not None: stream.logger.debug("Using cached wheel link: %s", cache_entry.link) return cache_entry.link.file_path # Otherwise, now all source is prepared, build it. with EnvBuilder(ireq.unpacked_source_directory, self) as builder: if ireq.editable: ret = builder.build_egg_info(kwargs["build_dir"]) ireq.metadata_directory = ret else: should_cache = False if ireq.link.is_vcs: vcs = pip_shims.VcsSupport() vcs_backend = vcs.get_backend_for_scheme(ireq.link.scheme) if vcs_backend.is_immutable_rev_checkout( ireq.link.url, ireq.source_dir ): should_cache = True else: base, _ = ireq.link.splitext() if _egg_info_re.search(base) is not None: # Determine whether the string looks like an egg_info. should_cache = True output_dir = ( wheel_cache.get_path_for_link(ireq.link) if should_cache else kwargs["build_dir"] ) if not os.path.exists(output_dir): os.makedirs(output_dir, exist_ok=True) ret = builder.build_wheel(output_dir) return ret
def build( self, ireq: pip_shims.InstallRequirement, hashes: Optional[Dict[str, str]] = None, allow_all: bool = True, ) -> str: """Build egg_info directory for editable candidates and a wheel for others. :param ireq: the InstallRequirment of the candidate. :param hashes: a dictionary of filename: hash_value to check against downloaded artifacts. :param allow_all: Allow building incompatible wheels. :returns: The full path of the built artifact. """ build_dir = self._get_build_dir(ireq) wheel_cache = self.project.make_wheel_cache() supported_tags = pip_shims.get_supported("".join( map(str, get_python_version(self.python_executable, digits=2)[0]))) with self.get_finder(ignore_requires_python=True) as finder: with allow_all_wheels(allow_all): # temporarily allow all wheels to get a link. populate_link(finder, ireq, False) ireq.link = pip_shims.Link( expand_env_vars_in_auth( ireq.link.url.replace( "${PROJECT_ROOT}", self.project.root.as_posix().lstrip("/")))) if hashes is None and not ireq.editable: # If hashes are not given and cache is hit, replace the link with the # cached one. This can speed up by skipping the download and build. cache_entry = wheel_cache.get_cache_entry( ireq.link, ireq.req.project_name, supported_tags, ) if cache_entry is not None: termui.logger.debug("Using cached wheel link: %s", cache_entry.link) ireq.link = cache_entry.link if not ireq.editable and not ireq.req.name: ireq.source_dir = build_dir else: ireq.ensure_has_source_dir(build_dir) if hashes: ireq.hash_options = convert_hashes(hashes) if not (ireq.editable and ireq.req.is_local_dir): downloader = pip_shims.Downloader(finder.session, "off") downloaded = pip_shims.unpack_url( ireq.link, ireq.source_dir, downloader, hashes=ireq.hashes(False), ) if ireq.link.is_wheel: # If the file is a wheel, return the downloaded file directly. return downloaded.path # Check the built wheel cache again after hashes are resolved. if not ireq.editable: cache_entry = wheel_cache.get_cache_entry( ireq.link, ireq.req.project_name, supported_tags, ) if cache_entry is not None: termui.logger.debug("Using cached wheel link: %s", cache_entry.link) return cache_entry.link.file_path # Otherwise, as all source is already prepared, build it. with EnvBuilder(ireq.unpacked_source_directory, self) as builder: if ireq.editable: ret = builder.build_egg_info(build_dir) ireq.metadata_directory = ret return ret should_cache = False if ireq.link.is_vcs: vcs = pip_shims.VcsSupport() vcs_backend = vcs.get_backend_for_scheme(ireq.link.scheme) if vcs_backend.is_immutable_rev_checkout( ireq.link.url, ireq.source_dir): should_cache = True else: base, _ = ireq.link.splitext() if _egg_info_re.search(base) is not None: # Determine whether the string looks like an egg_info. should_cache = True output_dir = (wheel_cache.get_path_for_link(ireq.link) if should_cache else build_dir) if not os.path.exists(output_dir): os.makedirs(output_dir, exist_ok=True) return builder.build_wheel(output_dir)
def build( self, ireq: pip_shims.InstallRequirement, hashes: dict[str, str] | None = None, allow_all: bool = True, ) -> str: """Build egg_info directory for editable candidates and a wheel for others. :param ireq: the InstallRequirment of the candidate. :param hashes: a dictionary of filename: hash_value to check against downloaded artifacts. :param allow_all: Allow building incompatible wheels. :returns: The full path of the built artifact. """ from pdm.builders import EnvEggInfoBuilder, EnvWheelBuilder wheel_cache = self.project.make_wheel_cache() supported_tags = pip_shims.get_supported(self.interpreter.for_tag()) if hashes: ireq.hash_options = convert_hashes(hashes) with self.get_finder(ignore_requires_python=True) as finder: with allow_all_wheels(allow_all): # temporarily allow all wheels to get a link. populate_link(finder, ireq, False) assert ireq.link if hashes is None and not ireq.editable: # If hashes are not given and cache is hit, replace the link with the # cached one. This can speed up by skipping the download and build. cache_entry = wheel_cache.get_cache_entry( ireq.link, ireq.req.project_name, # type: ignore supported_tags, ) if cache_entry is not None: termui.logger.debug("Using cached wheel link: %s", cache_entry.link) ireq.link = cache_entry.link build_dir = self._get_build_dir(ireq) if not ireq.source_dir: ireq.source_dir = build_dir if not ireq.link.is_existing_dir(): downloader = pip_shims.Downloader(finder.session, "off") # type: ignore downloaded = pip_shims.unpack_url( ireq.link, ireq.source_dir, downloader, hashes=ireq.hashes(False), ) if ireq.link.is_wheel: # If the file is a wheel, return the downloaded file directly. assert downloaded return downloaded.path # Check the built wheel cache again after hashes are resolved. if not ireq.editable: cache_entry = wheel_cache.get_cache_entry( ireq.link, ireq.req.project_name, # type: ignore supported_tags, ) if cache_entry is not None: termui.logger.debug("Using cached wheel link: %s", cache_entry.link) return cache_entry.link.file_path # Otherwise, as all source is already prepared, build it. output_dir = os.path.join(build_dir, "dist") if not os.path.exists(output_dir): os.makedirs(output_dir, exist_ok=True) if ireq.editable: builder = EnvEggInfoBuilder(ireq.unpacked_source_directory, self) ret = ireq.metadata_directory = builder.build(output_dir) return ret should_cache = False if ireq.link.is_vcs: vcs = pip_shims.VcsSupport() vcs_backend = vcs.get_backend_for_scheme(ireq.link.scheme) if vcs_backend and vcs_backend.is_immutable_rev_checkout( ireq.link.url, ireq.source_dir): should_cache = True elif not ireq.link.is_existing_dir: base, _ = ireq.link.splitext() if _egg_info_re.search(base) is not None: # Determine whether the string looks like an egg_info. should_cache = True if should_cache: output_dir = wheel_cache.get_path_for_link(ireq.link) if not os.path.exists(output_dir): os.makedirs(output_dir, exist_ok=True) return EnvWheelBuilder(ireq.unpacked_source_directory, self).build(output_dir)