Coverage for /builds/svesch/cikit/src/cikit/data/common.py: 100%

17 statements  

« prev     ^ index     » next       coverage.py v7.14.1, created at 2026-10-09 14:17 +0000

1# SPDX-License-Identifier: GPL-3.0-or-later 

2"""Common helpers for the cikit data package. 

3 

4This module provides small utility functions for working with local run data 

5files and resolving values from cached run data. 

6 

7Author: 

8 Sven Schlender 

9Date: 

10 2026-01-29 

11""" 

12 

13from pathlib import Path 

14from typing import Any 

15 

16from cikit.json_utils import load_json_file, save_json_file 

17 

18 

19def get_run_filename(directory: Path, run_name: str) -> Path: 

20 """Return the cache file path for a run. 

21 

22 Args: 

23 directory: Base cache directory. 

24 run_name: Logical run name. 

25 

26 Returns: 

27 Full path to the run JSON file. 

28 """ 

29 return directory / f"{run_name}.json" 

30 

31 

32def load_run_data(filepath: Path) -> Any: 

33 """Load JSON data from a file. 

34 

35 Missing files are treated as empty run data and return an empty dict. 

36 

37 Args: 

38 filepath: Path to the JSON file. 

39 

40 Returns: 

41 Parsed JSON content, or an empty dict if the file does not exist. 

42 

43 Raises: 

44 CiToolsError: If the file cannot be read or parsed as JSON. 

45 """ 

46 return load_json_file(filepath, description="run data") 

47 

48 

49def save_run_data(filepath: Path, data: Any) -> None: 

50 """Write JSON data to a file. 

51 

52 Parent directories are created automatically if needed. 

53 

54 Args: 

55 filepath: Path to the JSON file. 

56 data: JSON-serializable data to store. 

57 

58 Raises: 

59 CiToolsError: If the file cannot be written or the data cannot be 

60 serialized as JSON. 

61 """ 

62 save_json_file(filepath, data, description="run data") 

63 

64 

65def lookup_key(data: dict, dotted_key: str) -> Any: 

66 """Resolve a dotted key path inside a nested dictionary. 

67 

68 The key is split on dots and resolved step by step. If any path segment 

69 is missing, or if traversal reaches a non-dict value before the final 

70 segment, the function returns None. 

71 

72 Args: 

73 data: Nested dictionary to search in. 

74 dotted_key: Dot-separated key path, for example ``"a.b.c"``. 

75 

76 Returns: 

77 Resolved value, or None if the path cannot be resolved. 

78 """ 

79 parts = dotted_key.split(".") 

80 cur = data 

81 

82 for part in parts: 

83 if not isinstance(cur, dict) or part not in cur: 

84 return None 

85 cur = cur[part] 

86 

87 return cur