-
Notifications
You must be signed in to change notification settings - Fork 62
Expand file tree
/
Copy pathyaml_utils.py
More file actions
56 lines (38 loc) · 1.78 KB
/
yaml_utils.py
File metadata and controls
56 lines (38 loc) · 1.78 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
import os
from collections.abc import Hashable
from typing import Any, TextIO
import yaml
from cycode.logger import get_logger
logger = get_logger('YAML Utils')
def _deep_update(source: dict[Hashable, Any], overrides: dict[Hashable, Any]) -> dict[Hashable, Any]:
for key, value in overrides.items():
if isinstance(value, dict) and value:
source[key] = _deep_update(source.get(key, {}), value)
else:
source[key] = overrides[key]
return source
def _yaml_object_safe_load(file: TextIO) -> dict[Hashable, Any]:
# loader.get_single_data could return None
loaded_file = yaml.safe_load(file)
if not isinstance(loaded_file, dict):
# forbid literals at the top level
logger.debug(
'YAML file does not contain a dictionary at the top level: %s',
{'filename': file.name, 'actual_type': type(loaded_file)},
)
return {}
return loaded_file
def read_yaml_file(filename: str) -> dict[Hashable, Any]:
if not os.access(filename, os.R_OK) or not os.path.exists(filename):
logger.debug('Config file is not accessible or does not exist: %s', {'filename': filename})
return {}
with open(filename, encoding='UTF-8') as file:
return _yaml_object_safe_load(file)
def write_yaml_file(filename: str, content: dict[Hashable, Any]) -> None:
if not os.access(filename, os.W_OK) and os.path.exists(filename):
logger.warning('No write permission for file. Cannot save config, %s', {'filename': filename})
return
with open(filename, 'w', encoding='UTF-8') as file:
yaml.safe_dump(content, file)
def update_yaml_file(filename: str, content: dict[Hashable, Any]) -> None:
write_yaml_file(filename, _deep_update(read_yaml_file(filename), content))