Repository: pypa/pip
File: src/pip/_internal/commands/cache.py (Python)

Code before:

        if not args:
            raise CommandError("Please provide a pattern")

        files = self._find_wheels(options, args[0])

        no_matching_msg = "No matching packages"
        if args[0] == "*":
            # Only fetch http files if no specific pattern given
            files += self._find_http_files(options)
        else:
            # Add the pattern to the log message
            no_matching_msg += f' for pattern "{args[0]}"'

        if not files:
            logger.warning(no_matching_msg)

        for filename in files:
            os.unlink(filename)
            logger.verbose("Removed %s", filename)

        http_dirs = filesystem.subdirs_with_no_files(self._cache_dir(options, "http"))
        wheel_dirs = filesystem.subdirs_with_no_files(
            self._cache_dir(options, "wheels")
        )
        dirs = list(http_dirs) + list(wheel_dirs)
        for dirname in dirs:
            try:
                os.rmdir(dirname)
            except FileNotFoundError:
                # If the file is already gone, that's fine.
                pass
            logger.verbose("Removed %s", dirname)

        # selfcheck.json is no longer used by pip.
        selfcheck_json = self._cache_dir(options, "selfcheck.json")
        if os.path.isfile(selfcheck_json):
            os.remove(selfcheck_json)
            logger.verbose("Removed legacy selfcheck.json file")

        logger.info("Files removed: %s", len(files))
        logger.info("Empty directories removed: %s", len(dirs))

    def purge_cache(self, options: Values, args: List[Any]) -> None:
        if args:
            raise CommandError("Too many arguments")

        return self.remove_cache_items(options, ["*"])

    def _cache_dir(self, options: Values, subdir: str) -> str:
        return os.path.join(options.cache_dir, subdir)

Review comment (suggestion):
```suggestion
        dirs = [*http_dirs, *wheel_dirs]
```

This should reduce memory usage a bit it avoids building the intermediate lists.

Code after:

    def remove_cache_items(self, options: Values, args: list[str]) -> None:
        if len(args) > 1:
            raise CommandError("Too many arguments")

        if not args:
            raise CommandError("Please provide a pattern")

        files = self._find_wheels(options, args[0])

        no_matching_msg = "No matching packages"
        if args[0] == "*":
            # Only fetch http files if no specific pattern given
            files += self._find_http_files(options)
        else:
            # Add the pattern to the log message
            no_matching_msg += f' for pattern "{args[0]}"'

        if not files:
            logger.warning(no_matching_msg)

        bytes_removed = 0
        for filename in files:
            bytes_removed += os.stat(filename).st_size
            os.unlink(filename)
            logger.verbose("Removed %s", filename)

        http_dirs = filesystem.subdirs_without_files(self._cache_dir(options, "http"))
        wheel_dirs = filesystem.subdirs_without_wheels(
            self._cache_dir(options, "wheels")
        )
        dirs = [*http_dirs, *wheel_dirs]

        for subdir in dirs:
            try:
                for file in subdir.iterdir():
                    file.unlink(missing_ok=True)
                subdir.rmdir()
            except FileNotFoundError:
                # If the directory is already gone, that's fine.
                pass
            logger.verbose("Removed %s", subdir)

        # selfcheck.json is no longer used by pip.
        selfcheck_json = self._cache_dir(options, "selfcheck.json")
        if os.path.isfile(selfcheck_json):
            os.remove(selfcheck_json)
            logger.verbose("Removed legacy selfcheck.json file")

        logger.info("Files removed: %s (%s)", len(files), format_size(bytes_removed))
        logger.info("Directories removed: %s", len(dirs))