def handle(self, project: Project, options: argparse.Namespace) -> None: if not options.type: types: Iterable[str] = self.CACHE_TYPES elif options.type not in self.CACHE_TYPES: raise PdmUsageError( f"Invalid cache type {options.type}, should one of {self.CACHE_TYPES}" ) else: types = (str(options.type), ) packages = files = 0 with project.core.ui.open_spinner( f"Clearing {options.type or 'all'} caches...") as spinner: for type_ in types: if type_ == "packages": packages += self._clear_packages(project.cache(type_)) else: files += self._clear_files(project.cache(type_)) message = [] if packages: message.append( f"{packages} package{'s' if packages > 1 else ''}") if files: message.append(f"{files} file{'s' if files > 1 else ''}") if not message: # pragma: no cover text = "No files need to be removed" else: text = f"{' and '.join(message)} are removed" spinner.succeed(text)
def handle(self, project: Project, options: argparse.Namespace) -> None: if not options.type: cache_parent = project.cache_dir elif options.type not in self.CACHE_TYPES: raise PdmUsageError( f"Invalid cache type {options.type}, should one of {self.CACHE_TYPES}" ) else: cache_parent = project.cache(options.type) with project.core.ui.open_spinner( f"Clearing {options.type or 'all'} caches...") as spinner: files = list(find_files(cache_parent, "*")) for file in files: os.unlink(file) spinner.succeed( f"{len(files)} file{'s' if len(files) > 1 else ''} removed")
def remove_cache_files(project: Project, pattern: str) -> None: if not pattern: raise PdmUsageError("Please provide a pattern") if pattern == "*": files = list(find_files(project.cache_dir, pattern)) else: # Only remove wheel files which specific pattern is given files = list(find_files(project.cache("wheels"), pattern)) if not files: raise PdmUsageError("No matching files found") for file in files: os.unlink(file) project.core.ui.echo(f"Removed {file}", verbosity=termui.DETAIL) project.core.ui.echo(f"{len(files)} file{'s' if len(files) > 1 else ''} removed")
def handle(self, project: Project, options: argparse.Namespace) -> None: with project.core.ui.open_spinner("Calculating cache files"): output = [ f"{termui.cyan('Cache Root')}: {project.cache_dir}, " f"Total size: {format_size(directory_size(project.cache_dir))}" ] for name, description in [ ("hashes", "File Hashe Cache"), ("http", "HTTP Cache"), ("wheels", "Wheels Cache"), ("metadata", "Metadata Cache"), ]: cache_location = project.cache(name) files = list(find_files(cache_location, "*")) size = directory_size(cache_location) output.append(f" {termui.cyan(description)}: {cache_location}") output.append(f" Files: {len(files)}, Size: {format_size(size)}") project.core.ui.echo("\n".join(output))
def get_latest_version(project: Project) -> str | None: """Get the latest version of PDM from PyPI, cache for 7 days""" from pdm.utils import get_finder cache_key = hashlib.sha224(sys.executable.encode()).hexdigest() cache_file = project.cache("self-check") / cache_key if cache_file.exists(): state = json.loads(cache_file.read_text()) else: state = {} current_time = datetime.datetime.utcnow().timestamp() if ( state.get("last-check") and current_time - state["last-check"] < 60 * 60 * 24 * 7 ): return cast(str, state["latest-version"]) candidate = get_finder([], project.cache_dir.as_posix()).find_best_candidate("pdm") if not candidate.best_candidate: return None latest_version = str(candidate.best_candidate.version) state.update({"latest-version": latest_version, "last-check": current_time}) cache_file.write_text(json.dumps(state)) return latest_version
def handle(self, project: Project, options: argparse.Namespace) -> None: rows = [] for file in find_files(project.cache("wheels"), options.pattern): rows.append((format_size(file_size(file)), os.path.basename(file))) project.core.ui.display_columns(rows, [">Size", "Filename"])