encommon 0.17.2__py3-none-any.whl → 0.19.0__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
encommon/config/config.py CHANGED
@@ -21,6 +21,7 @@ from ..crypts import Crypts
21
21
  from ..types import DictStrAny
22
22
  from ..types import merge_dicts
23
23
  from ..types import setate
24
+ from ..types import sort_dict
24
25
 
25
26
  if TYPE_CHECKING:
26
27
  from ..utils.common import PATHABLE
@@ -43,7 +44,7 @@ class Config:
43
44
  -------
44
45
  >>> config = Config()
45
46
  >>> config.config
46
- {'enconfig': None, 'enlogger': None, 'encrypts': None}
47
+ {'enconfig': None, 'encrypts': None, 'enlogger': None}
47
48
 
48
49
  :param files: Complete or relative path to config files.
49
50
  :param paths: Complete or relative path to config paths.
@@ -275,7 +276,7 @@ class Config:
275
276
  :returns: Configuration dumped from the Pydantic model.
276
277
  """
277
278
 
278
- return self.params.endumped
279
+ return sort_dict(self.params.endumped)
279
280
 
280
281
 
281
282
  @property
@@ -0,0 +1,20 @@
1
+ """
2
+ Functions and routines associated with Enasis Network Common Library.
3
+
4
+ This file is part of Enasis Network software eco-system. Distribution
5
+ is permitted, for more information consult the project license file.
6
+ """
7
+
8
+
9
+
10
+ from .jinja2 import Jinja2
11
+ from .network import Network
12
+ from .network import insubnet_ip
13
+ from .network import isvalid_ip
14
+
15
+
16
+ __all__ = [
17
+ 'Jinja2',
18
+ 'Network',
19
+ 'insubnet_ip',
20
+ 'isvalid_ip']
@@ -0,0 +1,282 @@
1
+ """
2
+ Functions and routines associated with Enasis Network Common Library.
3
+
4
+ This file is part of Enasis Network software eco-system. Distribution
5
+ is permitted, for more information consult the project license file.
6
+ """
7
+
8
+
9
+
10
+ from ast import literal_eval as leval
11
+ from contextlib import suppress
12
+ from re import DOTALL
13
+ from re import findall as re_findall
14
+ from re import match as re_match
15
+ from typing import Any
16
+ from typing import Callable
17
+ from typing import Optional
18
+
19
+ from jinja2 import Environment
20
+ from jinja2 import StrictUndefined
21
+
22
+ from ..colors import Color
23
+ from ..crypts import Hashes
24
+ from ..times import Duration
25
+ from ..times import Time
26
+ from ..types import DictStrAny
27
+ from ..types import fuzzy_list
28
+ from ..utils import fuzz_match
29
+ from ..utils import rgxp_match
30
+
31
+
32
+
33
+ FILTER = Callable[..., Any]
34
+
35
+ JINJA2 = (
36
+ r'(\{\{.+?\}\})|'
37
+ r'(\{\%.+?\%\})')
38
+
39
+ LITERAL = (
40
+ r'^((\{([^\{%].+?)?\})|(\[(.+?|)\])'
41
+ '|True|False|None|'
42
+ r'(\-?([1-9]\d*|0)(\.\d+)?))$')
43
+
44
+ DEFAULT: dict[str, FILTER] = {
45
+ 'Duration': Duration,
46
+ 'Color': Color,
47
+ 'Hashes': Hashes,
48
+ 'Time': Time,
49
+ 'fuzz_match': fuzz_match,
50
+ 'fuzzy_list': fuzzy_list,
51
+ 'rgxp_match': rgxp_match}
52
+
53
+
54
+
55
+ class Jinja2:
56
+ """
57
+ Parse the provided input and intelligently return value.
58
+
59
+ Example
60
+ -------
61
+ >>> jinja2 = Jinja2()
62
+ >>> jinja2.parse('{{ 0 | Time}}')
63
+ '1970-01-01T00:00:00.000000+0000'
64
+
65
+ :param statics: Additional values available for parsing.
66
+ :param filters: Additional filter functions for parsing.
67
+ """
68
+
69
+ __statics: DictStrAny
70
+ __filters: dict[str, FILTER]
71
+
72
+ __jinjenv: Environment
73
+
74
+
75
+ def __init__(
76
+ self,
77
+ statics: Optional[DictStrAny] = None,
78
+ filters: Optional[dict[str, FILTER]] = None,
79
+ ) -> None:
80
+ """
81
+ Initialize instance for class using provided parameters.
82
+ """
83
+
84
+ statics = dict(statics or {})
85
+ filters = dict(filters or {})
86
+
87
+ items = DEFAULT.items()
88
+
89
+ for key, filter in items:
90
+ filters[key] = filter
91
+
92
+ self.__statics = statics
93
+ self.__filters = filters
94
+
95
+ jinjenv = Environment(
96
+ auto_reload=False,
97
+ autoescape=False,
98
+ cache_size=0,
99
+ extensions=[
100
+ 'jinja2.ext.i18n',
101
+ 'jinja2.ext.loopcontrols',
102
+ 'jinja2.ext.do'],
103
+ keep_trailing_newline=False,
104
+ lstrip_blocks=False,
105
+ newline_sequence='\n',
106
+ optimized=True,
107
+ trim_blocks=False,
108
+ undefined=StrictUndefined)
109
+
110
+ jinjenv.filters |= filters
111
+
112
+ self.__jinjenv = jinjenv
113
+
114
+
115
+ @property
116
+ def statics(
117
+ self,
118
+ ) -> DictStrAny:
119
+ """
120
+ Return the value for the attribute from class instance.
121
+
122
+ :returns: Value for the attribute from class instance.
123
+ """
124
+
125
+ return dict(self.__statics)
126
+
127
+
128
+ @property
129
+ def filters(
130
+ self,
131
+ ) -> dict[str, FILTER]:
132
+ """
133
+ Return the value for the attribute from class instance.
134
+
135
+ :returns: Value for the attribute from class instance.
136
+ """
137
+
138
+ return dict(self.__filters)
139
+
140
+
141
+ @property
142
+ def jinjenv(
143
+ self,
144
+ ) -> Environment:
145
+ """
146
+ Return the value for the attribute from class instance.
147
+
148
+ :returns: Value for the attribute from class instance.
149
+ """
150
+
151
+ return self.__jinjenv
152
+
153
+
154
+ def parser(
155
+ self,
156
+ value: str,
157
+ statics: Optional[DictStrAny] = None,
158
+ ) -> Any:
159
+ """
160
+ Return the provided input using the Jinja2 environment.
161
+
162
+ :param value: Input that will be processed and returned.
163
+ :param statics: Additional values available for parsing.
164
+ :returns: Provided input using the Jinja2 environment.
165
+ """
166
+
167
+ statics = statics or {}
168
+
169
+ parser = (
170
+ self.__jinjenv
171
+ .from_string)
172
+
173
+ rendered = (
174
+ parser(value)
175
+ .render(**statics))
176
+
177
+ return rendered
178
+
179
+
180
+ def parse( # noqa: CFQ004
181
+ self,
182
+ value: Any,
183
+ statics: Optional[DictStrAny] = None,
184
+ literal: bool = True,
185
+ ) -> Any:
186
+ """
187
+ Return the provided input using the Jinja2 environment.
188
+
189
+ :param value: Input that will be processed and returned.
190
+ :param statics: Additional values available for parsing.
191
+ :param literal: Determine if Python objects are evaled.
192
+ :returns: Provided input using the Jinja2 environment.
193
+ """
194
+
195
+
196
+ def _final( # noqa: CFQ004
197
+ value: Any,
198
+ ) -> Any:
199
+
200
+ if literal is False:
201
+ return value
202
+
203
+ match = re_match(
204
+ LITERAL, str(value))
205
+
206
+ if match is None:
207
+ return value
208
+
209
+ with suppress(Exception):
210
+ return leval(value)
211
+
212
+ return value
213
+
214
+
215
+ def _parse(
216
+ value: Any,
217
+ ) -> Any:
218
+
219
+ return self.parse(
220
+ value,
221
+ statics, literal)
222
+
223
+
224
+ def _parser(
225
+ value: Any,
226
+ ) -> Any:
227
+
228
+ parsed = self.parser(
229
+ value, statics)
230
+
231
+ return _final(parsed)
232
+
233
+
234
+ def _found(
235
+ value: Any,
236
+ ) -> list[Any]:
237
+
238
+ value = str(value)
239
+
240
+ return re_findall(
241
+ JINJA2, value, DOTALL)
242
+
243
+
244
+ if not len(_found(value)):
245
+ return _final(value)
246
+
247
+
248
+ with suppress(Exception):
249
+ value = _final(value)
250
+
251
+
252
+ if isinstance(value, dict):
253
+
254
+ value = dict(value)
255
+
256
+ items = value.items()
257
+
258
+ for key, _value in items:
259
+
260
+ _value = _parse(_value)
261
+
262
+ value[key] = _value
263
+
264
+
265
+ elif isinstance(value, list):
266
+
267
+ value = list(value)
268
+
269
+ values = enumerate(value)
270
+
271
+ for idx, _value in values:
272
+
273
+ _value = _parse(_value)
274
+
275
+ value[idx] = _value
276
+
277
+
278
+ elif value is not None:
279
+ value = _parser(value)
280
+
281
+
282
+ return value