def do_build( project: Project, sdist: bool = True, wheel: bool = True, dest: str = "dist", clean: bool = True, ): """Build artifacts for distribution.""" if project.is_global: raise ProjectError("Not allowed to build based on the global project.") check_project_file(project) if not wheel and not sdist: stream.echo("All artifacts are disabled, nothing to do.", err=True) return if not os.path.isabs(dest): dest = project.root.joinpath(dest).as_posix() if clean: shutil.rmtree(dest, ignore_errors=True) with stream.logging("build"), EnvBuilder(project.root, project.environment) as builder: if sdist: stream.echo("Building sdist...") loc = builder.build_sdist(dest) stream.echo(f"Built sdist at {loc}") if wheel: stream.echo("Building wheel...") loc = builder.build_wheel(dest) stream.echo(f"Built wheel at {loc}")
def update_project_egg_info(self): if not self.environment.project.meta.name: return canonical_name = self.environment.project.meta.project_name.lower( ).replace("-", "_") egg_info_dir = self.environment.project.root / f"{canonical_name}.egg-info" if egg_info_dir.exists(): stream.echo("Updating the project's egg info...") with EnvBuilder(self.environment.project.root, self.environment) as builder: builder.build_egg_info(str(builder.src_dir))
def install_editable(self, ireq: pip_shims.InstallRequirement) -> None: setup_path = ireq.setup_py_path paths = self.environment.get_paths() install_script = importlib.import_module( "pdm.installers._editable_install" ).__file__.rstrip("co") install_args = [ self.environment.python_executable, "-u", install_script, setup_path, paths["prefix"], paths["purelib"], paths["scripts"], ] with EnvBuilder(ireq.unpacked_source_directory, self.environment) as builder: builder.install(["setuptools"]) extra_env = {"INJECT_SITE": "1"} if not self.environment.is_global else None builder.subprocess_runner( install_args, ireq.unpacked_source_directory, extra_env )
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)