big upgrade UwU
This commit is contained in:
@@ -0,0 +1,118 @@
|
||||
"""Result objects describing what a download run did."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass, field
|
||||
from enum import Enum
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
class FileStatus(str, Enum):
|
||||
"""Outcome of a single file within a pack."""
|
||||
|
||||
DOWNLOADED = "downloaded"
|
||||
SKIPPED_EXISTING = "skipped_existing"
|
||||
FAILED = "failed"
|
||||
PLANNED = "planned" # --dry-run only
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class FileOutcome:
|
||||
"""What happened to one sticker file."""
|
||||
|
||||
path: Path
|
||||
status: FileStatus
|
||||
size: int = 0
|
||||
error: str | None = None
|
||||
|
||||
@property
|
||||
def name(self) -> str:
|
||||
return self.path.name
|
||||
|
||||
|
||||
@dataclass
|
||||
class PackResult:
|
||||
"""Aggregated outcome for one sticker pack."""
|
||||
|
||||
reference: str
|
||||
name: str | None = None
|
||||
title: str | None = None
|
||||
directory: Path | None = None
|
||||
total_stickers: int = 0
|
||||
outcomes: list[FileOutcome] = field(default_factory=list)
|
||||
error: str | None = None
|
||||
|
||||
@property
|
||||
def downloaded(self) -> int:
|
||||
return sum(1 for o in self.outcomes if o.status is FileStatus.DOWNLOADED)
|
||||
|
||||
@property
|
||||
def skipped(self) -> int:
|
||||
return sum(1 for o in self.outcomes if o.status is FileStatus.SKIPPED_EXISTING)
|
||||
|
||||
@property
|
||||
def planned(self) -> int:
|
||||
return sum(1 for o in self.outcomes if o.status is FileStatus.PLANNED)
|
||||
|
||||
@property
|
||||
def failed(self) -> int:
|
||||
return sum(1 for o in self.outcomes if o.status is FileStatus.FAILED)
|
||||
|
||||
@property
|
||||
def bytes_written(self) -> int:
|
||||
return sum(o.size for o in self.outcomes if o.status is FileStatus.DOWNLOADED)
|
||||
|
||||
@property
|
||||
def ok(self) -> bool:
|
||||
"""True when the pack was processed without a fatal or per-file error."""
|
||||
return self.error is None and self.failed == 0
|
||||
|
||||
def summary(self) -> str:
|
||||
if self.error is not None:
|
||||
return f"failed: {self.error}"
|
||||
parts = [f"{self.downloaded} downloaded"]
|
||||
if self.planned:
|
||||
parts.append(f"{self.planned} planned")
|
||||
if self.skipped:
|
||||
parts.append(f"{self.skipped} already present")
|
||||
if self.failed:
|
||||
parts.append(f"{self.failed} failed")
|
||||
return ", ".join(parts)
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class RunTotals:
|
||||
"""Totals across every pack in a run."""
|
||||
|
||||
packs: int
|
||||
packs_ok: int
|
||||
packs_failed: int
|
||||
downloaded: int
|
||||
skipped: int
|
||||
planned: int
|
||||
failed: int
|
||||
bytes_written: int
|
||||
|
||||
@classmethod
|
||||
def from_results(cls, results: list[PackResult]) -> RunTotals:
|
||||
return cls(
|
||||
packs=len(results),
|
||||
packs_ok=sum(1 for r in results if r.ok),
|
||||
packs_failed=sum(1 for r in results if not r.ok),
|
||||
downloaded=sum(r.downloaded for r in results),
|
||||
skipped=sum(r.skipped for r in results),
|
||||
planned=sum(r.planned for r in results),
|
||||
failed=sum(r.failed for r in results),
|
||||
bytes_written=sum(r.bytes_written for r in results),
|
||||
)
|
||||
|
||||
|
||||
def format_size(num_bytes: int) -> str:
|
||||
"""Human-readable byte count, e.g. ``1.4 MiB``."""
|
||||
size = float(num_bytes)
|
||||
for unit in ("B", "KiB", "MiB", "GiB"):
|
||||
if size < 1024 or unit == "GiB":
|
||||
precision = 0 if unit == "B" else 1
|
||||
return f"{size:.{precision}f} {unit}"
|
||||
size /= 1024
|
||||
raise AssertionError("unreachable") # pragma: no cover
|
||||
Reference in New Issue
Block a user