Mini Shell
"""Abstract parent class of guds modules"""
from abc import abstractmethod
import logging
from os import walk
from pathlib import Path
import shlex
import shutil
import subprocess
class ModuleBase:
def __init__(self, dry_run: bool, logger: logging.Logger):
self.dry_run = dry_run
self.logger = logger
@abstractmethod
def run_module(self, homedir: str) -> dict:
raise NotImplementedError
@classmethod
def calc_bytes(cls, size_check: Path) -> int:
if size_check.is_file():
return size_check.stat().st_size
total_size = 0
for root, _, files in walk(size_check):
for name in files:
filename = Path(root, name)
try:
total_size += filename.stat().st_size
except OSError:
pass
return total_size
@classmethod
def get_size(cls, size_check: Path) -> str:
"""Find the size of provided directory or file"""
total_size = cls.calc_bytes(size_check)
for suffix in ['B', 'KiB', 'MiB', 'GiB', 'TiB']:
if total_size < 1024.0:
return f"{total_size:3.1f} {suffix}"
total_size /= 1024.0
return f"{total_size:3.1f} PiB"
def find(
self,
homedir: str,
/,
*,
maxdepth=None,
regex=None,
prune_mail=True,
**kwargs,
) -> list[Path]:
"""returns each line of output from the command as an item in a list"""
cmd = ['find']
if regex is not None:
cmd.append('-O3')
cmd.append(homedir)
# ensure maxdepth is set first, if specified
if maxdepth is not None:
cmd.extend(['-maxdepth', str(maxdepth)])
elif prune_mail:
# optimization: prune and exclude ~/mail
cmd.extend(['-not', '(', '-path', f"{homedir}/mail", '-prune', ')'])
# regextype must be set before regex
if regex is not None:
cmd.extend(['-regextype', 'posix-extended', '-regex', regex])
for key, val in kwargs.items():
cmd.extend([f'-{key}', str(val)])
cmd.append('-print0')
self.logger.debug(shlex.join(cmd))
ret = subprocess.run(
cmd, stdout=subprocess.PIPE, encoding='utf-8', check=False
)
return [Path(x) for x in ret.stdout.split('\0') if x]
def delete_items(self, backuplist: list[Path]):
for backup in backuplist:
self.logger.info("Removing %s (%s)", backup, self.get_size(backup))
if self.dry_run:
continue
if backup.is_file():
backup.unlink()
elif backup.is_dir():
shutil.rmtree(str(backup))
Zerion Mini Shell 1.0