encommon 0.17.2__py3-none-any.whl → 0.19.0__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.
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