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

1"""Private helpers for UI static-file management during server startup.""" 

2 

3from __future__ import annotations 

4 

5import errno 

6import logging 

7import pathlib 

8import shutil 

9from dataclasses import dataclass 

10from typing import Literal 

11 

12UIVersion = Literal["v1", "v2"] 

13 

14 

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 

22 

23 

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 

48 

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." 

56 

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 )