初始化奇妙小屏幕控制器项目

This commit is contained in:
2026-09-08 22:56:52 +08:00
commit 8d368de3b5
491 changed files with 67678 additions and 0 deletions
@@ -0,0 +1,95 @@
from __future__ import annotations
import os
import shutil
import threading
import time
from datetime import datetime, timezone
from pathlib import Path
from typing import Callable, Iterable
DEVICE_STORAGE_CACHE_SECONDS = 300.0
def _normalized_roots(paths: Iterable[Path]) -> list[Path]:
roots: list[Path] = []
for candidate in sorted(
{Path(path).resolve() for path in paths},
key=lambda path: len(path.parts),
):
if any(candidate == root or candidate.is_relative_to(root) for root in roots):
continue
roots.append(candidate)
return roots
def directory_bytes(paths: Iterable[Path]) -> int:
total = 0
pending = _normalized_roots(paths)
while pending:
path = pending.pop()
if not path.exists():
continue
if not path.is_dir():
total += path.stat(follow_symlinks=False).st_size
continue
with os.scandir(path) as entries:
for entry in entries:
if entry.is_dir(follow_symlinks=False):
pending.append(Path(entry.path))
else:
total += entry.stat(follow_symlinks=False).st_size
return total
class DeviceStorageMonitor:
def __init__(
self,
program_root: Path,
data_root: Path,
*,
cache_seconds: float = DEVICE_STORAGE_CACHE_SECONDS,
clock: Callable[[], float] = time.monotonic,
usage_reader: Callable[[Path], shutil._ntuple_diskusage] = shutil.disk_usage,
directory_reader: Callable[[Iterable[Path]], int] = directory_bytes,
) -> None:
self.program_root = Path(program_root).resolve()
self.data_root = Path(data_root).resolve()
self.cache_seconds = float(cache_seconds)
self._clock = clock
self._usage_reader = usage_reader
self._directory_reader = directory_reader
self._lock = threading.RLock()
self._snapshot: dict | None = None
self._sampled_monotonic = float("-inf")
def invalidate(self) -> None:
with self._lock:
self._snapshot = None
self._sampled_monotonic = float("-inf")
def get_status(self) -> dict:
with self._lock:
now = self._clock()
if (
self._snapshot is not None
and now - self._sampled_monotonic < self.cache_seconds
):
return dict(self._snapshot)
usage = self._usage_reader(self.program_root)
snapshot = {
"sampled_at": datetime.now(timezone.utc).isoformat().replace("+00:00", "Z"),
"device_total_bytes": usage.total,
"device_free_bytes": usage.free,
"software_bytes": self._directory_reader(
[self.program_root, self.data_root]
),
"templates_bytes": self._directory_reader(
[self.data_root / "templates", self.data_root / "animations"]
),
}
self._snapshot = snapshot
self._sampled_monotonic = now
return dict(snapshot)