MinDalle_StableDiff/Python310/Lib/site-packages/cleanpy/_manipulator.py

88 lines
2.8 KiB
Python
Raw Permalink Normal View History

2022-09-17 15:26:13 +03:00
import os
import shutil
from collections import defaultdict
from logging import Logger
from os import DirEntry
from typing import Dict
from ._const import EntryType, RemoveTarget
class DirEntryManipulator:
def __init__(self, logger: Logger, interactive: bool, follow_symlinks: bool, dry_run: bool):
self.__logger = logger
self.__interactive = interactive
self.__follow_symlinks = follow_symlinks
self.__dry_run = dry_run
self.remove_count: Dict[str, int] = defaultdict(int)
self.error_count: Dict[str, int] = defaultdict(int)
logger.debug(f"follow_symlinks: {follow_symlinks}")
logger.debug(f"dry run: {dry_run}")
def is_dir(self, entry: DirEntry) -> bool:
return entry.is_dir(follow_symlinks=self.__follow_symlinks)
def is_file(self, entry: DirEntry) -> bool:
return entry.is_file(follow_symlinks=self.__follow_symlinks)
def get_entry_type(self, entry: DirEntry) -> EntryType:
if self.is_dir(entry):
return EntryType.DIR
if self.is_file(entry):
return EntryType.FILE
return EntryType.UNDELETABLE
def remove(self, entry: DirEntry, remove_target: RemoveTarget) -> None:
if not self.__prompt_remove(entry.path):
self.__logger.warning(f"skip removal of '{entry.path}'")
return
if self.is_dir(entry):
self.__logger.info(
f"remove directory [{remove_target.category} - {remove_target.name}]: {entry.path}"
)
try:
if not self.__dry_run:
shutil.rmtree(entry.path)
self.remove_count["directories"] += 1
except OSError as e:
self.__logger.error(f"failed to remove a directory '{entry.path}': {e}")
self.error_count["directories"] += 1
return
if self.is_file(entry):
self.__logger.info(
f"remove file [{remove_target.category} - {remove_target.name}]: {entry.path}"
)
try:
if not self.__dry_run:
os.remove(entry.path)
self.remove_count["files"] += 1
return
except OSError as e:
self.__logger.error(f"failed to remove a file '{entry.path}': {e}")
self.error_count["files"] += 1
return
self.__logger.error(f"unknown entry: {entry.path}")
def __prompt_remove(self, remove_path: str) -> bool:
if not self.__interactive:
return True
response = input(f"Remove '{remove_path}'? [y/N]: ")
response = response.strip().casefold()
if not response:
return False
if response[0] == "y":
return True
return False