def direct_url(self) -> dict[str, Any] | None: """PEP 610 direct_url.json data""" req = self.req if isinstance(req, VcsRequirement): if req.editable: assert self.ireq.source_dir return _filter_none({ "url": pip_shims.path_to_url(self.ireq.source_dir), "dir_info": { "editable": True }, "subdirectory": req.subdirectory, }) return _filter_none({ "url": url_without_fragments(req.repo), "vcs_info": _filter_none({ "vcs": req.vcs, "requested_revision": req.ref, "commit_id": self.revision, }), "subdirectory": req.subdirectory, }) elif isinstance(req, FileRequirement): if req.is_local_dir: return _filter_none({ "url": url_without_fragments(req.url), "dir_info": _filter_none({"editable": req.editable or None}), "subdirectory": req.subdirectory, }) url = expand_env_vars_in_auth( req.url.replace( "${PROJECT_ROOT}", self.environment.project.root.as_posix(). lstrip( # type: ignore "/"), )) with self.environment.get_finder() as finder: hash_cache = self.environment.project.make_hash_cache() hash_cache.session = finder.session # type: ignore return _filter_none({ "url": url_without_fragments(url), "archive_info": { "hash": hash_cache.get_hash(pip_shims.Link(url)).replace( ":", "=") }, "subdirectory": req.subdirectory, }) else: return None
def ireq(self) -> pip_shims.InstallRequirement: rv = self.req.as_ireq() if rv.link: rv.link = pip_shims.Link( expand_env_vars_in_auth( rv.link.url.replace( "${PROJECT_ROOT}", self.environment.project.root.as_posix().lstrip("/"), ) ) ) if rv.source_dir: rv.source_dir = os.path.normpath(os.path.abspath(rv.link.file_path)) if rv.local_file_path: rv.local_file_path = rv.link.file_path return rv
def get_ireq(self) -> pip_shims.InstallRequirement: rv, project = self.req.as_ireq(), self.environment.project if rv.link: rv.original_link = rv.link = pip_shims.Link( expand_env_vars_in_auth( rv.link.url.replace( "${PROJECT_ROOT}", project.root.as_posix().lstrip("/"), # type: ignore ))) if rv.source_dir: rv.source_dir = os.path.normpath( os.path.abspath(rv.link.file_path)) if rv.local_file_path: rv.local_file_path = rv.link.file_path elif self.candidate.link: rv.link = rv.original_link = self.candidate.link return rv
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)