-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathconfigs.py
More file actions
132 lines (115 loc) · 4.46 KB
/
configs.py
File metadata and controls
132 lines (115 loc) · 4.46 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
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
import configparser
import distutils.util
import collections
import os
import expandvars
import logging
LOGGER = logging.getLogger(__name__)
_UNSET = object()
class Config:
class ConfigInterpolation(configparser.BasicInterpolation):
def before_get(self, parser, section, option, value, defaults):
return expandvars.expandvars(value)
instances = list()
parser = configparser.ConfigParser(interpolation=ConfigInterpolation())
directory = None
file_names = None
def __init__(self, data_type, section, option=None, fallback=_UNSET):
self.__class__.instances.append(self)
self._data_type = data_type
self._is_none = False
self._section = section
self._option = option
self._fallback = fallback
self._gen_value = _UNSET
@staticmethod
def init(directory, *file_names, ignore_error=False):
# Set the directory of the configuration files to use
Config.directory = directory
# Load the configuration files
Config.load(*file_names, ignore_error=ignore_error)
@staticmethod
def path(target=""):
yield os.path.join(Config.directory, target)
@staticmethod
def dir(target=""):
return os.path.join(Config.directory, target)
@staticmethod
def load(*file_names, encoding=None, ignore_error=False):
# If configuration should only be reloaded
if not file_names: file_names = Config.file_names
# Set file names
Config.file_names = file_names
# Build the real path of each configuration file
config_file_paths = [os.path.join(Config.directory, file_name) for file_name in file_names]
# Check if the file exists
valid_file_paths = []
for config_file_path in config_file_paths:
if not os.path.isfile(config_file_path):
if not ignore_error:
raise FileNotFoundError
else:
valid_file_paths.append(config_file_path)
# Parse and read the configurations
Config.parser.read(valid_file_paths, encoding)
def get(self, option=None, **kwargs):
if self._is_none:
return None
option = self._option if option is None else option
if self._fallback is _UNSET:
value = Config.parser.get(self._section, option)
else:
value = Config.parser.get(self._section, option, fallback=self._fallback)
if value == '':
value = self._fallback
# Check the value
if value is None:
return None
if isinstance(value, collections.Generator):
if self._gen_value is _UNSET:
self._gen_value = next(value)
return self._gen_value
# Check data type
if isinstance(self._data_type, type):
if self._data_type == bool:
if isinstance(value, bool):
return value
elif isinstance(value, str):
return bool(distutils.util.strtobool(value))
elif self._data_type == str and kwargs:
value = str(value).format(**kwargs)
elif isinstance(self._data_type, tuple) and isinstance(value, str):
collection, data_type = self._data_type
if collection == list:
return [data_type(v) for v in value.split(",")]
# Return the casted value
return self._data_type(value)
def set(self, value):
if value is not None:
if not isinstance(value, self._data_type):
raise ValueError
self._is_none = False
value = self._data_type(value)
else:
self._is_none = True
return
if self._section not in Config.parser.sections():
Config.parser.add_section(self._section)
try:
Config.parser.set(self._section, self._option, str(value))
except Exception as e:
raise ValueError
@staticmethod
def update(data):
for section, data in data.items():
if section not in Config.parser.sections():
Config.parser.add_section(section)
for option, value in data:
Config.parser.set(section, option, value)
@staticmethod
def save(filename):
with open(Config.dir(filename), 'w') as f:
Config.parser.write(f)
@staticmethod
def data():
return {s: Config.parser.items(s) for s in Config.parser.sections()}