Files
buzzer/buzzer_tool/core/commands/pull.py
2026-03-02 00:25:40 +01:00

63 lines
2.0 KiB
Python

import os
import posixpath
import time
def _resolve_local_target(remote_path: str, target: str | None) -> str:
if target:
return target
basename = posixpath.basename(remote_path.rstrip("/"))
if not basename:
raise ValueError("Kann keinen lokalen Dateinamen aus dem Remote-Pfad ableiten. Bitte Zielpfad angeben.")
return basename
def execute(conn, source: str, target: str | None = None):
local_path = _resolve_local_target(source, target)
os.makedirs(os.path.dirname(local_path) or ".", exist_ok=True)
last_print = 0.0
start_time = time.monotonic()
def _progress(_chunk_len: int, received: int, expected: int | None):
nonlocal last_print
now = time.monotonic()
if now - last_print < 0.2:
return
last_print = now
elapsed = max(now - start_time, 1e-6)
speed_kb_s = (received / 1024.0) / elapsed
if expected is not None and expected > 0:
percent = (received * 100.0) / expected
remaining = max(expected - received, 0)
eta_sec = (remaining / 1024.0) / speed_kb_s if speed_kb_s > 0 else 0.0
eta_str = f"{int(eta_sec // 60):02d}:{int(eta_sec % 60):02d}"
print(
f"\r⬇️ {received}/{expected} B ({percent:5.1f}%) | {speed_kb_s:6.1f} KB/s | ETA {eta_str}",
end="",
flush=True,
)
else:
print(f"\r⬇️ {received} B | {speed_kb_s:6.1f} KB/s", end="", flush=True)
data = conn.get_file_data(source, progress_callback=_progress)
if len(data) > 0:
print()
with open(local_path, "wb") as f:
f.write(data)
total_duration = max(time.monotonic() - start_time, 1e-6)
avg_speed_kb_s = (len(data) / 1024.0) / total_duration
print(f"✅ Heruntergeladen: '{source}' -> '{local_path}' ({len(data)} B, {avg_speed_kb_s:.1f} KB/s)")
return {
"source": source,
"target": local_path,
"size": len(data),
}