| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798 |
- import shutil
- import xml.etree.ElementTree as ET
- from dataclasses import dataclass
- from datetime import datetime, timedelta
- from pathlib import Path
- @dataclass(frozen=True)
- class ArchiveLogsResult:
- checked_count: int
- archived_count: int
- skipped_count: int
- def find_xml_files(directory: Path) -> list[Path]:
- archive_directory = directory / "Archiv"
- return sorted(
- path
- for path in directory.rglob("*")
- if path.is_file()
- and path.suffix.lower() == ".xml"
- and not path.name.lower().startswith("sessions")
- and archive_directory not in path.parents
- )
- def get_archive_year(xml_path: Path, now: datetime | None = None) -> int | None:
- try:
- root = ET.parse(xml_path).getroot()
- except ET.ParseError:
- return None
- session = root.find("Session")
- if session is None:
- return None
- if session.get("Duration", "").strip():
- start_time = session.get("StartTime", "")
- try:
- return datetime.fromisoformat(start_time.replace("Z", "+00:00")).year
- except ValueError:
- return None
- created_at = datetime.fromtimestamp(xml_path.stat().st_birthtime)
- now = now or datetime.now()
- if now - created_at >= timedelta(days=30):
- return created_at.year
- return None
- def remove_empty_directories(directory: Path) -> int:
- archive_directory = directory / "Archiv"
- removed_count = 0
- subdirectories = sorted(
- (path for path in directory.rglob("*") if path.is_dir()),
- key=lambda path: len(path.parts),
- reverse=True,
- )
- for subdirectory in subdirectories:
- if subdirectory == archive_directory or archive_directory in subdirectory.parents:
- continue
- try:
- subdirectory.rmdir()
- except OSError:
- continue
- removed_count += 1
- return removed_count
- def run(directory: Path) -> ArchiveLogsResult:
- if not directory.is_dir():
- raise ValueError(f"Das Verzeichnis existiert nicht: {directory}")
- checked_count = 0
- archived_count = 0
- skipped_count = 0
- for xml_file in find_xml_files(directory):
- checked_count += 1
- year = get_archive_year(xml_file)
- if year is None:
- skipped_count += 1
- continue
- target_directory = directory / "Archiv" / str(year)
- target_directory.mkdir(parents=True, exist_ok=True)
- target = target_directory / xml_file.name
- if target.exists():
- skipped_count += 1
- continue
- shutil.move(str(xml_file), str(target))
- archived_count += 1
- remove_empty_directories(directory)
- return ArchiveLogsResult(
- checked_count=checked_count,
- archived_count=archived_count,
- skipped_count=skipped_count,
- )
|