81 lines
3.2 KiB
Python
81 lines
3.2 KiB
Python
from __future__ import annotations
|
|
|
|
import re
|
|
import unicodedata
|
|
from pathlib import Path
|
|
from typing import Iterable
|
|
|
|
|
|
def sanitize_filename(name: str) -> str:
|
|
normalized = unicodedata.normalize("NFKD", name)
|
|
ascii_text = normalized.encode("ASCII", "ignore").decode()
|
|
ascii_text = ascii_text.lower()
|
|
ascii_text = ascii_text.replace(" ", "_")
|
|
ascii_text = re.sub(r"[^a-z0-9_\-\.]", "", ascii_text)
|
|
ascii_text = re.sub(r"_+", "_", ascii_text)
|
|
return ascii_text.strip("_") or "video"
|
|
|
|
|
|
def ensure_workspace(root: Path, folder_name: str) -> Path:
|
|
workspace = root / folder_name
|
|
workspace.mkdir(parents=True, exist_ok=True)
|
|
return workspace
|
|
|
|
|
|
def remove_paths(paths: Iterable[Path]) -> None:
|
|
import logging
|
|
import time
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
for path in paths:
|
|
if not path.exists():
|
|
continue
|
|
|
|
# Try to remove with retries and better error handling
|
|
max_retries = 3
|
|
for attempt in range(max_retries):
|
|
try:
|
|
if path.is_file() or path.is_symlink():
|
|
path.unlink(missing_ok=True)
|
|
else:
|
|
for child in sorted(path.rglob("*"), reverse=True):
|
|
if child.is_file() or child.is_symlink():
|
|
try:
|
|
child.unlink(missing_ok=True)
|
|
except PermissionError:
|
|
logger.warning(f"Não foi possível deletar {child}: sem permissão")
|
|
# Try to change permissions and retry
|
|
try:
|
|
child.chmod(0o777)
|
|
child.unlink(missing_ok=True)
|
|
except Exception as e:
|
|
logger.warning(f"Falha ao forçar deleção de {child}: {e}")
|
|
elif child.is_dir():
|
|
try:
|
|
child.rmdir()
|
|
except (PermissionError, OSError) as e:
|
|
logger.warning(f"Não foi possível remover diretório {child}: {e}")
|
|
|
|
try:
|
|
path.rmdir()
|
|
except (PermissionError, OSError) as e:
|
|
logger.warning(f"Não foi possível remover diretório {path}: {e}")
|
|
break # Success, exit retry loop
|
|
|
|
except PermissionError as e:
|
|
if attempt < max_retries - 1:
|
|
logger.warning(f"Tentativa {attempt + 1}/{max_retries} falhou ao deletar {path}: {e}. Tentando novamente...")
|
|
time.sleep(0.5) # Wait a bit before retry
|
|
# Try to change permissions
|
|
try:
|
|
path.chmod(0o777)
|
|
except Exception:
|
|
pass
|
|
else:
|
|
logger.error(f"Não foi possível deletar {path} após {max_retries} tentativas: {e}")
|
|
except Exception as e:
|
|
logger.error(f"Erro inesperado ao deletar {path}: {e}")
|
|
break # Don't retry on unexpected errors
|
|
|