appier 1.34.7__py2.py3-none-any.whl → 1.34.8__py2.py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
appier/config.py CHANGED
@@ -1,401 +1,409 @@
1
- #!/usr/bin/python
2
- # -*- coding: utf-8 -*-
3
-
4
- # Hive Appier Framework
5
- # Copyright (c) 2008-2024 Hive Solutions Lda.
6
- #
7
- # This file is part of Hive Appier Framework.
8
- #
9
- # Hive Appier Framework is free software: you can redistribute it and/or modify
10
- # it under the terms of the Apache License as published by the Apache
11
- # Foundation, either version 2.0 of the License, or (at your option) any
12
- # later version.
13
- #
14
- # Hive Appier Framework is distributed in the hope that it will be useful,
15
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
16
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
- # Apache License for more details.
18
- #
19
- # You should have received a copy of the Apache License along with
20
- # Hive Appier Framework. If not, see <http://www.apache.org/licenses/>.
21
-
22
- __author__ = "João Magalhães <joamag@hive.pt>"
23
- """ The author(s) of the module """
24
-
25
- __copyright__ = "Copyright (c) 2008-2024 Hive Solutions Lda."
26
- """ The copyright for the module """
27
-
28
- __license__ = "Apache License, Version 2.0"
29
- """ The license for the module """
30
-
31
- import os
32
- import sys
33
- import json
34
-
35
- from . import legacy
36
-
37
- FILE_NAME = "appier.json"
38
- """ The default name of the file that is going to be
39
- used for the loading of configuration values from JSON """
40
-
41
- FILE_TEMPLATE = "appier.%s.json"
42
- """ The template to be used in the construction of the
43
- domain specific configuration file paths """
44
-
45
- HOME_FILE = "~/.home"
46
- """ The location of the file that may be used to "redirect"
47
- the home directory contents to a different directory """
48
-
49
- IMPORT_NAMES = ("$import", "$include", "$IMPORT", "$INCLUDE")
50
- """ The multiple possible definitions of the special configuration
51
- name that references a list of include files to be loaded """
52
-
53
- CASTS = {
54
- bool: lambda v: v if isinstance(v, bool) else v in ("1", "true", "True"),
55
- list: lambda v: v if isinstance(v, list) else v.split(";") if v else [],
56
- tuple: lambda v: v if isinstance(v, tuple) else tuple(v.split(";") if v else []),
57
- }
58
- """ The map containing the various cast method
59
- operation associated with the various data types,
60
- they provide a different type of casting strategy """
61
-
62
- ENV_ENCODINGS = ("utf-8", sys.getdefaultencoding(), sys.getfilesystemencoding())
63
- """ The sequence of encodings that are going to
64
- be used to try to decode possible byte based strings
65
- for the various environment variable values """
66
-
67
- CONFIGS = {}
68
- """ The map that contains the key value association
69
- for all the currently set global configurations """
70
-
71
- CONFIG_F = []
72
- """ The list of files that have been used for the loading
73
- of the configuration through this session, every time a
74
- loading of configuration from a file occurs the same path
75
- is added to this global list """
76
-
77
- HOMES = []
78
- """ Global reference to the paths to the directory considered
79
- to be the home on in terms of configuration, this value should
80
- be set on the initial loading of the ".home" file """
81
-
82
- if not isinstance(__builtins__, dict):
83
- __builtins__ = __builtins__.__dict__
84
-
85
-
86
- def conf(name, default=None, cast=None, ctx=None):
87
- """
88
- Retrieves the configuration value for the provided value
89
- defaulting to the provided default value in case no value
90
- is found for the provided name.
91
-
92
- An optional cast operation may be performed on the value
93
- in case it's requested.
94
-
95
- :type name: String
96
- :param name: The name of the configuration value to be
97
- retrieved.
98
- :type default: Object
99
- :param default: The default value to be retrieved in case
100
- no value was found for the provided name.
101
- :type cast: Type/String
102
- :param cast: The cast operation to be performed in the
103
- resolved value (optional).
104
- :type ctx: Dictionary
105
- :param ctx: The context dictionary to be used for situations
106
- where a more contextual configuration is meant to be used instead
107
- of the process wide global configuration.
108
- :rtype: Object
109
- :return: The value for the configuration with the requested
110
- name or the default value if no value was found.
111
- """
112
-
113
- configs = ctx["configs"] if ctx else CONFIGS
114
- cast = _cast_r(cast)
115
- value = configs.get(name, default)
116
- if cast and not value == None:
117
- value = cast(value)
118
- return value
119
-
120
-
121
- def conf_prefix(prefix, ctx=None):
122
- configs = ctx["configs"] if ctx else CONFIGS
123
- configs_prefix = dict()
124
- for name, value in configs.items():
125
- if not name.startswith(prefix):
126
- continue
127
- configs_prefix[name] = value
128
- return configs_prefix
129
-
130
-
131
- def conf_suffix(suffix, ctx=None):
132
- configs = ctx["configs"] if ctx else CONFIGS
133
- configs_suffix = dict()
134
- for name, value in configs.items():
135
- if not name.endswith(suffix):
136
- continue
137
- configs_suffix[name] = value
138
- return configs_suffix
139
-
140
-
141
- def conf_s(name, value, ctx=None):
142
- configs = ctx["configs"] if ctx else CONFIGS
143
- configs[name] = value
144
-
145
-
146
- def conf_r(name, ctx=None):
147
- configs = ctx["configs"] if ctx else CONFIGS
148
- if not name in configs:
149
- return
150
- del configs[name]
151
-
152
-
153
- def conf_d(ctx=None):
154
- configs = ctx["configs"] if ctx else CONFIGS
155
- return configs
156
-
157
-
158
- def conf_ctx():
159
- return dict(configs=dict(), config_f=dict())
160
-
161
-
162
- def load(names=(FILE_NAME,), path=None, encoding="utf-8", ctx=None):
163
- paths = []
164
- homes = get_homes()
165
- for home in homes:
166
- paths += [os.path.join(home), os.path.join(home, ".config")]
167
- paths += [sys.prefix]
168
- paths.append(path)
169
- for path in paths:
170
- for name in names:
171
- load_file(name=name, path=path, encoding=encoding, ctx=ctx)
172
- load_dot_env(ctx=ctx)
173
- load_env(ctx=ctx)
174
-
175
-
176
- def load_file(name=FILE_NAME, path=None, encoding="utf-8", ctx=None):
177
- configs = ctx["configs"] if ctx else CONFIGS
178
- config_f = ctx["config_f"] if ctx else CONFIG_F
179
-
180
- if path:
181
- path = os.path.normpath(path)
182
- if path:
183
- file_path = os.path.join(path, name)
184
- else:
185
- file_path = name
186
-
187
- file_path = os.path.abspath(file_path)
188
- file_path = os.path.normpath(file_path)
189
- base_path = os.path.dirname(file_path)
190
-
191
- exists = os.path.exists(file_path)
192
- if not exists:
193
- return
194
-
195
- exists = file_path in config_f
196
- if exists:
197
- config_f.remove(file_path)
198
- config_f.append(file_path)
199
-
200
- file = open(file_path, "rb")
201
- try:
202
- data = file.read()
203
- finally:
204
- file.close()
205
- if not data:
206
- return
207
-
208
- data = data.decode(encoding)
209
- data_j = json.loads(data)
210
-
211
- _load_includes(base_path, data_j, encoding=encoding)
212
-
213
- for key, value in data_j.items():
214
- if not _is_valid(key):
215
- continue
216
- configs[key] = value
217
-
218
-
219
- def load_dot_env(name=".env", encoding="utf-8", ctx=None):
220
- configs = ctx["configs"] if ctx else CONFIGS
221
- config_f = ctx["config_f"] if ctx else CONFIG_F
222
-
223
- file_path = os.path.abspath(name)
224
- file_path = os.path.normpath(file_path)
225
-
226
- exists = os.path.exists(file_path)
227
- if not exists:
228
- return
229
-
230
- exists = file_path in config_f
231
- if exists:
232
- config_f.remove(file_path)
233
- config_f.append(file_path)
234
-
235
- file = open(file_path, "rb")
236
- try:
237
- data = file.read()
238
- finally:
239
- file.close()
240
- if not data:
241
- return
242
-
243
- data = data.decode(encoding)
244
- data = data.strip()
245
- lines = data.splitlines()
246
- lines = [line.strip() for line in lines]
247
-
248
- for line in lines:
249
- line = line.strip()
250
- if not line:
251
- continue
252
- if line.startswith("#"):
253
- continue
254
- key, value = line.split("=", 1)
255
- key = key.strip()
256
- value = value.strip()
257
- if (
258
- value.startswith('"')
259
- and value.endswith('"')
260
- or value.startswith("'")
261
- and value.endswith("'")
262
- ):
263
- value = value[1:-1].replace('\\"', '"')
264
- configs[key] = value
265
-
266
-
267
- def load_env(ctx=None):
268
- configs = ctx["configs"] if ctx else CONFIGS
269
-
270
- config = dict(os.environ)
271
- homes = get_homes()
272
-
273
- for home in homes:
274
- _load_includes(home, config)
275
-
276
- for key, value in legacy.iteritems(config):
277
- if not _is_valid(key):
278
- continue
279
- configs[key] = value
280
- is_bytes = legacy.is_bytes(value)
281
- if not is_bytes:
282
- continue
283
- for encoding in ENV_ENCODINGS:
284
- try:
285
- value = value.decode(encoding)
286
- except UnicodeDecodeError:
287
- pass
288
- else:
289
- break
290
- configs[key] = value
291
-
292
-
293
- def get_homes(file_path=HOME_FILE, default="~", encoding="utf-8", force_default=False):
294
- global HOMES
295
- if HOMES:
296
- return HOMES
297
-
298
- HOMES = os.environ.get("HOMES", None)
299
- HOMES = HOMES.split(";") if HOMES else HOMES
300
- if not HOMES == None:
301
- return HOMES
302
-
303
- default = os.path.expanduser(default)
304
- default = os.path.abspath(default)
305
- default = os.path.normpath(default)
306
- HOMES = [default]
307
-
308
- file_path = os.path.expanduser(file_path)
309
- file_path = os.path.normpath(file_path)
310
- exists = os.path.exists(file_path)
311
- if not exists:
312
- return HOMES
313
-
314
- if not force_default:
315
- del HOMES[:]
316
-
317
- file = open(file_path, "rb")
318
- try:
319
- data = file.read()
320
- finally:
321
- file.close()
322
-
323
- data = data.decode("utf-8")
324
- data = data.strip()
325
- paths = data.splitlines()
326
- paths = [path.strip() for path in paths]
327
-
328
- for path in paths:
329
- path = path.strip()
330
- if not path:
331
- continue
332
- path = os.path.expanduser(path)
333
- path = os.path.abspath(path)
334
- path = os.path.normpath(path)
335
- HOMES.append(path)
336
-
337
- return HOMES
338
-
339
-
340
- def _cast_r(cast):
341
- is_string = type(cast) in legacy.STRINGS
342
- if is_string:
343
- cast = __builtins__.get(cast, None)
344
- if not cast:
345
- return None
346
- return CASTS.get(cast, cast)
347
-
348
-
349
- def _load_includes(base_path, config, encoding="utf-8"):
350
- includes = ()
351
-
352
- for alias in IMPORT_NAMES:
353
- includes = config.get(alias, includes)
354
-
355
- if legacy.is_string(includes):
356
- includes = includes.split(";")
357
-
358
- for include in includes:
359
- load_file(name=include, path=base_path, encoding=encoding)
360
-
361
-
362
- def _is_valid(key):
363
- if key in IMPORT_NAMES:
364
- return False
365
- return True
366
-
367
-
368
- def _is_devel():
369
- """
370
- Simple debug/development level detection mechanism to be
371
- used at load time to determine if the system is running
372
- under a development (debug) environment.
373
-
374
- This function should not be used at runtime as there are
375
- other (more powerful) mechanisms to archive the same
376
- type of results.
377
-
378
- :rtype: bool
379
- :return: If the current environment is running under a
380
- development type level of traceability.
381
- """
382
-
383
- return conf("LEVEL", "INFO") in ("DEBUG",)
384
-
385
-
386
- def _is_secure():
387
- """
388
- Simple secure variable that should be overriden only under
389
- very specific/critical operation that control if the current
390
- environment should hide information that would otherwise
391
- compromise some of the system's secrecy (eg: version, name, etc.)
392
-
393
- :rtype: bool
394
- :return: If the current environment is running under a
395
- secured type level of traceability.
396
- """
397
-
398
- return conf("SECURE", True, cast=bool)
399
-
400
-
401
- load()
1
+ #!/usr/bin/python
2
+ # -*- coding: utf-8 -*-
3
+
4
+ # Hive Appier Framework
5
+ # Copyright (c) 2008-2024 Hive Solutions Lda.
6
+ #
7
+ # This file is part of Hive Appier Framework.
8
+ #
9
+ # Hive Appier Framework is free software: you can redistribute it and/or modify
10
+ # it under the terms of the Apache License as published by the Apache
11
+ # Foundation, either version 2.0 of the License, or (at your option) any
12
+ # later version.
13
+ #
14
+ # Hive Appier Framework is distributed in the hope that it will be useful,
15
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
16
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
+ # Apache License for more details.
18
+ #
19
+ # You should have received a copy of the Apache License along with
20
+ # Hive Appier Framework. If not, see <http://www.apache.org/licenses/>.
21
+
22
+ """appier.config
23
+
24
+ Centralised configuration handling for environment variables,
25
+ command-line options and INI/JSON files. Exposes `conf` helper
26
+ to fetch typed values with defaults, automatic casting and caching.
27
+ Used throughout Appier for feature toggles and credentials.
28
+ """
29
+
30
+ __author__ = "João Magalhães <joamag@hive.pt>"
31
+ """ The author(s) of the module """
32
+
33
+ __copyright__ = "Copyright (c) 2008-2024 Hive Solutions Lda."
34
+ """ The copyright for the module """
35
+
36
+ __license__ = "Apache License, Version 2.0"
37
+ """ The license for the module """
38
+
39
+ import os
40
+ import sys
41
+ import json
42
+
43
+ from . import legacy
44
+
45
+ FILE_NAME = "appier.json"
46
+ """ The default name of the file that is going to be
47
+ used for the loading of configuration values from JSON """
48
+
49
+ FILE_TEMPLATE = "appier.%s.json"
50
+ """ The template to be used in the construction of the
51
+ domain specific configuration file paths """
52
+
53
+ HOME_FILE = "~/.home"
54
+ """ The location of the file that may be used to "redirect"
55
+ the home directory contents to a different directory """
56
+
57
+ IMPORT_NAMES = ("$import", "$include", "$IMPORT", "$INCLUDE")
58
+ """ The multiple possible definitions of the special configuration
59
+ name that references a list of include files to be loaded """
60
+
61
+ CASTS = {
62
+ bool: lambda v: v if isinstance(v, bool) else v in ("1", "true", "True"),
63
+ list: lambda v: v if isinstance(v, list) else v.split(";") if v else [],
64
+ tuple: lambda v: v if isinstance(v, tuple) else tuple(v.split(";") if v else []),
65
+ }
66
+ """ The map containing the various cast method
67
+ operation associated with the various data types,
68
+ they provide a different type of casting strategy """
69
+
70
+ ENV_ENCODINGS = ("utf-8", sys.getdefaultencoding(), sys.getfilesystemencoding())
71
+ """ The sequence of encodings that are going to
72
+ be used to try to decode possible byte based strings
73
+ for the various environment variable values """
74
+
75
+ CONFIGS = {}
76
+ """ The map that contains the key value association
77
+ for all the currently set global configurations """
78
+
79
+ CONFIG_F = []
80
+ """ The list of files that have been used for the loading
81
+ of the configuration through this session, every time a
82
+ loading of configuration from a file occurs the same path
83
+ is added to this global list """
84
+
85
+ HOMES = []
86
+ """ Global reference to the paths to the directory considered
87
+ to be the home on in terms of configuration, this value should
88
+ be set on the initial loading of the ".home" file """
89
+
90
+ if not isinstance(__builtins__, dict):
91
+ __builtins__ = __builtins__.__dict__
92
+
93
+
94
+ def conf(name, default=None, cast=None, ctx=None):
95
+ """
96
+ Retrieves the configuration value for the provided value
97
+ defaulting to the provided default value in case no value
98
+ is found for the provided name.
99
+
100
+ An optional cast operation may be performed on the value
101
+ in case it's requested.
102
+
103
+ :type name: String
104
+ :param name: The name of the configuration value to be
105
+ retrieved.
106
+ :type default: Object
107
+ :param default: The default value to be retrieved in case
108
+ no value was found for the provided name.
109
+ :type cast: Type/String
110
+ :param cast: The cast operation to be performed in the
111
+ resolved value (optional).
112
+ :type ctx: Dictionary
113
+ :param ctx: The context dictionary to be used for situations
114
+ where a more contextual configuration is meant to be used instead
115
+ of the process wide global configuration.
116
+ :rtype: Object
117
+ :return: The value for the configuration with the requested
118
+ name or the default value if no value was found.
119
+ """
120
+
121
+ configs = ctx["configs"] if ctx else CONFIGS
122
+ cast = _cast_r(cast)
123
+ value = configs.get(name, default)
124
+ if cast and not value == None:
125
+ value = cast(value)
126
+ return value
127
+
128
+
129
+ def conf_prefix(prefix, ctx=None):
130
+ configs = ctx["configs"] if ctx else CONFIGS
131
+ configs_prefix = dict()
132
+ for name, value in configs.items():
133
+ if not name.startswith(prefix):
134
+ continue
135
+ configs_prefix[name] = value
136
+ return configs_prefix
137
+
138
+
139
+ def conf_suffix(suffix, ctx=None):
140
+ configs = ctx["configs"] if ctx else CONFIGS
141
+ configs_suffix = dict()
142
+ for name, value in configs.items():
143
+ if not name.endswith(suffix):
144
+ continue
145
+ configs_suffix[name] = value
146
+ return configs_suffix
147
+
148
+
149
+ def conf_s(name, value, ctx=None):
150
+ configs = ctx["configs"] if ctx else CONFIGS
151
+ configs[name] = value
152
+
153
+
154
+ def conf_r(name, ctx=None):
155
+ configs = ctx["configs"] if ctx else CONFIGS
156
+ if not name in configs:
157
+ return
158
+ del configs[name]
159
+
160
+
161
+ def conf_d(ctx=None):
162
+ configs = ctx["configs"] if ctx else CONFIGS
163
+ return configs
164
+
165
+
166
+ def conf_ctx():
167
+ return dict(configs=dict(), config_f=dict())
168
+
169
+
170
+ def load(names=(FILE_NAME,), path=None, encoding="utf-8", ctx=None):
171
+ paths = []
172
+ homes = get_homes()
173
+ for home in homes:
174
+ paths += [os.path.join(home), os.path.join(home, ".config")]
175
+ paths += [sys.prefix]
176
+ paths.append(path)
177
+ for path in paths:
178
+ for name in names:
179
+ load_file(name=name, path=path, encoding=encoding, ctx=ctx)
180
+ load_dot_env(ctx=ctx)
181
+ load_env(ctx=ctx)
182
+
183
+
184
+ def load_file(name=FILE_NAME, path=None, encoding="utf-8", ctx=None):
185
+ configs = ctx["configs"] if ctx else CONFIGS
186
+ config_f = ctx["config_f"] if ctx else CONFIG_F
187
+
188
+ if path:
189
+ path = os.path.normpath(path)
190
+ if path:
191
+ file_path = os.path.join(path, name)
192
+ else:
193
+ file_path = name
194
+
195
+ file_path = os.path.abspath(file_path)
196
+ file_path = os.path.normpath(file_path)
197
+ base_path = os.path.dirname(file_path)
198
+
199
+ exists = os.path.exists(file_path)
200
+ if not exists:
201
+ return
202
+
203
+ exists = file_path in config_f
204
+ if exists:
205
+ config_f.remove(file_path)
206
+ config_f.append(file_path)
207
+
208
+ file = open(file_path, "rb")
209
+ try:
210
+ data = file.read()
211
+ finally:
212
+ file.close()
213
+ if not data:
214
+ return
215
+
216
+ data = data.decode(encoding)
217
+ data_j = json.loads(data)
218
+
219
+ _load_includes(base_path, data_j, encoding=encoding)
220
+
221
+ for key, value in data_j.items():
222
+ if not _is_valid(key):
223
+ continue
224
+ configs[key] = value
225
+
226
+
227
+ def load_dot_env(name=".env", encoding="utf-8", ctx=None):
228
+ configs = ctx["configs"] if ctx else CONFIGS
229
+ config_f = ctx["config_f"] if ctx else CONFIG_F
230
+
231
+ file_path = os.path.abspath(name)
232
+ file_path = os.path.normpath(file_path)
233
+
234
+ exists = os.path.exists(file_path)
235
+ if not exists:
236
+ return
237
+
238
+ exists = file_path in config_f
239
+ if exists:
240
+ config_f.remove(file_path)
241
+ config_f.append(file_path)
242
+
243
+ file = open(file_path, "rb")
244
+ try:
245
+ data = file.read()
246
+ finally:
247
+ file.close()
248
+ if not data:
249
+ return
250
+
251
+ data = data.decode(encoding)
252
+ data = data.strip()
253
+ lines = data.splitlines()
254
+ lines = [line.strip() for line in lines]
255
+
256
+ for line in lines:
257
+ line = line.strip()
258
+ if not line:
259
+ continue
260
+ if line.startswith("#"):
261
+ continue
262
+ key, value = line.split("=", 1)
263
+ key = key.strip()
264
+ value = value.strip()
265
+ if (
266
+ value.startswith('"')
267
+ and value.endswith('"')
268
+ or value.startswith("'")
269
+ and value.endswith("'")
270
+ ):
271
+ value = value[1:-1].replace('\\"', '"')
272
+ configs[key] = value
273
+
274
+
275
+ def load_env(ctx=None):
276
+ configs = ctx["configs"] if ctx else CONFIGS
277
+
278
+ config = dict(os.environ)
279
+ homes = get_homes()
280
+
281
+ for home in homes:
282
+ _load_includes(home, config)
283
+
284
+ for key, value in legacy.iteritems(config):
285
+ if not _is_valid(key):
286
+ continue
287
+ configs[key] = value
288
+ is_bytes = legacy.is_bytes(value)
289
+ if not is_bytes:
290
+ continue
291
+ for encoding in ENV_ENCODINGS:
292
+ try:
293
+ value = value.decode(encoding)
294
+ except UnicodeDecodeError:
295
+ pass
296
+ else:
297
+ break
298
+ configs[key] = value
299
+
300
+
301
+ def get_homes(file_path=HOME_FILE, default="~", encoding="utf-8", force_default=False):
302
+ global HOMES
303
+ if HOMES:
304
+ return HOMES
305
+
306
+ HOMES = os.environ.get("HOMES", None)
307
+ HOMES = HOMES.split(";") if HOMES else HOMES
308
+ if not HOMES == None:
309
+ return HOMES
310
+
311
+ default = os.path.expanduser(default)
312
+ default = os.path.abspath(default)
313
+ default = os.path.normpath(default)
314
+ HOMES = [default]
315
+
316
+ file_path = os.path.expanduser(file_path)
317
+ file_path = os.path.normpath(file_path)
318
+ exists = os.path.exists(file_path)
319
+ if not exists:
320
+ return HOMES
321
+
322
+ if not force_default:
323
+ del HOMES[:]
324
+
325
+ file = open(file_path, "rb")
326
+ try:
327
+ data = file.read()
328
+ finally:
329
+ file.close()
330
+
331
+ data = data.decode("utf-8")
332
+ data = data.strip()
333
+ paths = data.splitlines()
334
+ paths = [path.strip() for path in paths]
335
+
336
+ for path in paths:
337
+ path = path.strip()
338
+ if not path:
339
+ continue
340
+ path = os.path.expanduser(path)
341
+ path = os.path.abspath(path)
342
+ path = os.path.normpath(path)
343
+ HOMES.append(path)
344
+
345
+ return HOMES
346
+
347
+
348
+ def _cast_r(cast):
349
+ is_string = type(cast) in legacy.STRINGS
350
+ if is_string:
351
+ cast = __builtins__.get(cast, None)
352
+ if not cast:
353
+ return None
354
+ return CASTS.get(cast, cast)
355
+
356
+
357
+ def _load_includes(base_path, config, encoding="utf-8"):
358
+ includes = ()
359
+
360
+ for alias in IMPORT_NAMES:
361
+ includes = config.get(alias, includes)
362
+
363
+ if legacy.is_string(includes):
364
+ includes = includes.split(";")
365
+
366
+ for include in includes:
367
+ load_file(name=include, path=base_path, encoding=encoding)
368
+
369
+
370
+ def _is_valid(key):
371
+ if key in IMPORT_NAMES:
372
+ return False
373
+ return True
374
+
375
+
376
+ def _is_devel():
377
+ """
378
+ Simple debug/development level detection mechanism to be
379
+ used at load time to determine if the system is running
380
+ under a development (debug) environment.
381
+
382
+ This function should not be used at runtime as there are
383
+ other (more powerful) mechanisms to archive the same
384
+ type of results.
385
+
386
+ :rtype: bool
387
+ :return: If the current environment is running under a
388
+ development type level of traceability.
389
+ """
390
+
391
+ return conf("LEVEL", "INFO") in ("DEBUG",)
392
+
393
+
394
+ def _is_secure():
395
+ """
396
+ Simple secure variable that should be overriden only under
397
+ very specific/critical operation that control if the current
398
+ environment should hide information that would otherwise
399
+ compromise some of the system's secrecy (eg: version, name, etc.)
400
+
401
+ :rtype: bool
402
+ :return: If the current environment is running under a
403
+ secured type level of traceability.
404
+ """
405
+
406
+ return conf("SECURE", True, cast=bool)
407
+
408
+
409
+ load()