Coverage for /usr/local/lib/python3.12/site-packages/prefect/server/api/_ui_static.py: 33%
39 statements
« prev ^ index » next coverage.py v7.15.2, created at 2026-10-07 02:04 +0000
« prev ^ index » next coverage.py v7.15.2, created at 2026-10-07 02:04 +0000
1"""Private helpers for UI static-file management during server startup."""
3from __future__ import annotations
5import errno
6import logging
7import pathlib
8import shutil
9from dataclasses import dataclass
10from typing import Literal
12UIVersion = Literal["v1", "v2"]
15@dataclass(frozen=True)
16class UIBundle:
17 version: UIVersion
18 source_static_path: str
19 static_dir: str
20 base_url: str
21 cache_key: str
24def log_ui_static_copy_error(
25 bundle: UIBundle,
26 exc: OSError,
27 logger: logging.Logger,
28) -> None:
29 """Log an actionable error when copying a UI bundle's static files fails."""
30 if exc.errno == errno.ENOSPC:
31 try:
32 disk_path = pathlib.Path(bundle.static_dir)
33 while not disk_path.exists():
34 disk_path = disk_path.parent
35 usage = shutil.disk_usage(disk_path)
36 available_mb = usage.free / (1024 * 1024)
37 except OSError:
38 available_mb = None
39 try:
40 required_bytes = sum(
41 f.stat().st_size
42 for f in pathlib.Path(bundle.source_static_path).rglob("*")
43 if f.is_file()
44 )
45 required_mb = required_bytes / (1024 * 1024)
46 except OSError:
47 required_mb = None
49 space_detail = ""
50 if required_mb is not None and available_mb is not None:
51 space_detail = (
52 f" Required: {required_mb:.1f} MB, available: {available_mb:.1f} MB."
53 )
54 elif available_mb is not None:
55 space_detail = f" Available disk space: {available_mb:.1f} MB."
57 logger.error(
58 "Not enough disk space to unpack %s UI static"
59 " files at %s.%s To resolve this, increase the"
60 " size of the volume mounted at that path or set"
61 " PREFECT_UI_STATIC_DIRECTORY to a location with"
62 " sufficient space.",
63 bundle.version.upper(),
64 bundle.static_dir,
65 space_detail,
66 )
67 elif isinstance(exc, PermissionError):
68 logger.error(
69 "Failed to create %s UI static directory at %s:"
70 " %s. That UI will not be available. To resolve"
71 " this, set PREFECT_UI_STATIC_DIRECTORY to a"
72 " writable directory.",
73 bundle.version.upper(),
74 bundle.static_dir,
75 exc,
76 )
77 else:
78 logger.error(
79 "Failed to create %s UI static directory at %s:"
80 " %s. That UI will not be available.",
81 bundle.version.upper(),
82 bundle.static_dir,
83 exc,
84 )