encommon 0.20.5__tar.gz → 0.21.0__tar.gz

Sign up to get free protection for your applications and to get access to all the features.
Files changed (99) hide show
  1. {encommon-0.20.5/encommon.egg-info → encommon-0.21.0}/PKG-INFO +2 -2
  2. {encommon-0.20.5 → encommon-0.21.0}/encommon/types/__init__.py +4 -0
  3. {encommon-0.20.5 → encommon-0.21.0}/encommon/types/notate.py +179 -0
  4. {encommon-0.20.5 → encommon-0.21.0}/encommon/types/test/__init__.py +7 -0
  5. {encommon-0.20.5 → encommon-0.21.0}/encommon/types/test/test_dicts.py +1 -0
  6. encommon-0.21.0/encommon/types/test/test_notate.py +478 -0
  7. encommon-0.21.0/encommon/version.txt +1 -0
  8. {encommon-0.20.5 → encommon-0.21.0/encommon.egg-info}/PKG-INFO +2 -2
  9. encommon-0.20.5/encommon/types/test/test_notate.py +0 -217
  10. encommon-0.20.5/encommon/version.txt +0 -1
  11. {encommon-0.20.5 → encommon-0.21.0}/LICENSE +0 -0
  12. {encommon-0.20.5 → encommon-0.21.0}/MANIFEST.in +0 -0
  13. {encommon-0.20.5 → encommon-0.21.0}/README.md +0 -0
  14. {encommon-0.20.5 → encommon-0.21.0}/encommon/__init__.py +0 -0
  15. {encommon-0.20.5 → encommon-0.21.0}/encommon/colors/__init__.py +0 -0
  16. {encommon-0.20.5 → encommon-0.21.0}/encommon/colors/color.py +0 -0
  17. {encommon-0.20.5 → encommon-0.21.0}/encommon/colors/test/__init__.py +0 -0
  18. {encommon-0.20.5 → encommon-0.21.0}/encommon/colors/test/test_color.py +0 -0
  19. {encommon-0.20.5 → encommon-0.21.0}/encommon/config/__init__.py +0 -0
  20. {encommon-0.20.5 → encommon-0.21.0}/encommon/config/config.py +0 -0
  21. {encommon-0.20.5 → encommon-0.21.0}/encommon/config/files.py +0 -0
  22. {encommon-0.20.5 → encommon-0.21.0}/encommon/config/logger.py +0 -0
  23. {encommon-0.20.5 → encommon-0.21.0}/encommon/config/params.py +0 -0
  24. {encommon-0.20.5 → encommon-0.21.0}/encommon/config/paths.py +0 -0
  25. {encommon-0.20.5 → encommon-0.21.0}/encommon/config/test/__init__.py +0 -0
  26. {encommon-0.20.5 → encommon-0.21.0}/encommon/config/test/test_config.py +0 -0
  27. {encommon-0.20.5 → encommon-0.21.0}/encommon/config/test/test_files.py +0 -0
  28. {encommon-0.20.5 → encommon-0.21.0}/encommon/config/test/test_logger.py +0 -0
  29. {encommon-0.20.5 → encommon-0.21.0}/encommon/config/test/test_paths.py +0 -0
  30. {encommon-0.20.5 → encommon-0.21.0}/encommon/config/test/test_utils.py +0 -0
  31. {encommon-0.20.5 → encommon-0.21.0}/encommon/config/utils.py +0 -0
  32. {encommon-0.20.5 → encommon-0.21.0}/encommon/conftest.py +0 -0
  33. {encommon-0.20.5 → encommon-0.21.0}/encommon/crypts/__init__.py +0 -0
  34. {encommon-0.20.5 → encommon-0.21.0}/encommon/crypts/crypts.py +0 -0
  35. {encommon-0.20.5 → encommon-0.21.0}/encommon/crypts/hashes.py +0 -0
  36. {encommon-0.20.5 → encommon-0.21.0}/encommon/crypts/params.py +0 -0
  37. {encommon-0.20.5 → encommon-0.21.0}/encommon/crypts/test/__init__.py +0 -0
  38. {encommon-0.20.5 → encommon-0.21.0}/encommon/crypts/test/test_crypts.py +0 -0
  39. {encommon-0.20.5 → encommon-0.21.0}/encommon/crypts/test/test_hashes.py +0 -0
  40. {encommon-0.20.5 → encommon-0.21.0}/encommon/parse/__init__.py +0 -0
  41. {encommon-0.20.5 → encommon-0.21.0}/encommon/parse/jinja2.py +0 -0
  42. {encommon-0.20.5 → encommon-0.21.0}/encommon/parse/network.py +0 -0
  43. {encommon-0.20.5 → encommon-0.21.0}/encommon/parse/test/__init__.py +0 -0
  44. {encommon-0.20.5 → encommon-0.21.0}/encommon/parse/test/test_jinja2.py +0 -0
  45. {encommon-0.20.5 → encommon-0.21.0}/encommon/parse/test/test_network.py +0 -0
  46. {encommon-0.20.5 → encommon-0.21.0}/encommon/py.typed +0 -0
  47. {encommon-0.20.5 → encommon-0.21.0}/encommon/times/__init__.py +0 -0
  48. {encommon-0.20.5 → encommon-0.21.0}/encommon/times/common.py +0 -0
  49. {encommon-0.20.5 → encommon-0.21.0}/encommon/times/duration.py +0 -0
  50. {encommon-0.20.5 → encommon-0.21.0}/encommon/times/params.py +0 -0
  51. {encommon-0.20.5 → encommon-0.21.0}/encommon/times/parse.py +0 -0
  52. {encommon-0.20.5 → encommon-0.21.0}/encommon/times/test/__init__.py +0 -0
  53. {encommon-0.20.5 → encommon-0.21.0}/encommon/times/test/test_duration.py +0 -0
  54. {encommon-0.20.5 → encommon-0.21.0}/encommon/times/test/test_params.py +0 -0
  55. {encommon-0.20.5 → encommon-0.21.0}/encommon/times/test/test_parse.py +0 -0
  56. {encommon-0.20.5 → encommon-0.21.0}/encommon/times/test/test_time.py +0 -0
  57. {encommon-0.20.5 → encommon-0.21.0}/encommon/times/test/test_timer.py +0 -0
  58. {encommon-0.20.5 → encommon-0.21.0}/encommon/times/test/test_timers.py +0 -0
  59. {encommon-0.20.5 → encommon-0.21.0}/encommon/times/test/test_unitime.py +0 -0
  60. {encommon-0.20.5 → encommon-0.21.0}/encommon/times/test/test_utils.py +0 -0
  61. {encommon-0.20.5 → encommon-0.21.0}/encommon/times/test/test_window.py +0 -0
  62. {encommon-0.20.5 → encommon-0.21.0}/encommon/times/test/test_windows.py +0 -0
  63. {encommon-0.20.5 → encommon-0.21.0}/encommon/times/time.py +0 -0
  64. {encommon-0.20.5 → encommon-0.21.0}/encommon/times/timer.py +0 -0
  65. {encommon-0.20.5 → encommon-0.21.0}/encommon/times/timers.py +0 -0
  66. {encommon-0.20.5 → encommon-0.21.0}/encommon/times/unitime.py +0 -0
  67. {encommon-0.20.5 → encommon-0.21.0}/encommon/times/utils.py +0 -0
  68. {encommon-0.20.5 → encommon-0.21.0}/encommon/times/window.py +0 -0
  69. {encommon-0.20.5 → encommon-0.21.0}/encommon/times/windows.py +0 -0
  70. {encommon-0.20.5 → encommon-0.21.0}/encommon/types/classes.py +0 -0
  71. {encommon-0.20.5 → encommon-0.21.0}/encommon/types/dicts.py +0 -0
  72. {encommon-0.20.5 → encommon-0.21.0}/encommon/types/empty.py +0 -0
  73. {encommon-0.20.5 → encommon-0.21.0}/encommon/types/lists.py +0 -0
  74. {encommon-0.20.5 → encommon-0.21.0}/encommon/types/strings.py +0 -0
  75. {encommon-0.20.5 → encommon-0.21.0}/encommon/types/test/test_classes.py +0 -0
  76. {encommon-0.20.5 → encommon-0.21.0}/encommon/types/test/test_empty.py +0 -0
  77. {encommon-0.20.5 → encommon-0.21.0}/encommon/types/test/test_lists.py +0 -0
  78. {encommon-0.20.5 → encommon-0.21.0}/encommon/types/test/test_strings.py +0 -0
  79. {encommon-0.20.5 → encommon-0.21.0}/encommon/types/types.py +0 -0
  80. {encommon-0.20.5 → encommon-0.21.0}/encommon/utils/__init__.py +0 -0
  81. {encommon-0.20.5 → encommon-0.21.0}/encommon/utils/common.py +0 -0
  82. {encommon-0.20.5 → encommon-0.21.0}/encommon/utils/files.py +0 -0
  83. {encommon-0.20.5 → encommon-0.21.0}/encommon/utils/match.py +0 -0
  84. {encommon-0.20.5 → encommon-0.21.0}/encommon/utils/paths.py +0 -0
  85. {encommon-0.20.5 → encommon-0.21.0}/encommon/utils/sample.py +0 -0
  86. {encommon-0.20.5 → encommon-0.21.0}/encommon/utils/stdout.py +0 -0
  87. {encommon-0.20.5 → encommon-0.21.0}/encommon/utils/test/__init__.py +0 -0
  88. {encommon-0.20.5 → encommon-0.21.0}/encommon/utils/test/test_files.py +0 -0
  89. {encommon-0.20.5 → encommon-0.21.0}/encommon/utils/test/test_match.py +0 -0
  90. {encommon-0.20.5 → encommon-0.21.0}/encommon/utils/test/test_paths.py +0 -0
  91. {encommon-0.20.5 → encommon-0.21.0}/encommon/utils/test/test_sample.py +0 -0
  92. {encommon-0.20.5 → encommon-0.21.0}/encommon/utils/test/test_stdout.py +0 -0
  93. {encommon-0.20.5 → encommon-0.21.0}/encommon.egg-info/SOURCES.txt +0 -0
  94. {encommon-0.20.5 → encommon-0.21.0}/encommon.egg-info/dependency_links.txt +0 -0
  95. {encommon-0.20.5 → encommon-0.21.0}/encommon.egg-info/requires.txt +0 -0
  96. {encommon-0.20.5 → encommon-0.21.0}/encommon.egg-info/top_level.txt +0 -0
  97. {encommon-0.20.5 → encommon-0.21.0}/pyproject.toml +0 -0
  98. {encommon-0.20.5 → encommon-0.21.0}/require/install.txt +0 -0
  99. {encommon-0.20.5 → encommon-0.21.0}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.2
2
2
  Name: encommon
3
- Version: 0.20.5
3
+ Version: 0.21.0
4
4
  Summary: Enasis Network Common Library
5
5
  License: MIT
6
6
  Project-URL: Source, https://github.com/enasisnetwork/encommon
@@ -17,7 +17,9 @@ from .lists import dedup_list
17
17
  from .lists import fuzzy_list
18
18
  from .lists import inlist
19
19
  from .notate import delate
20
+ from .notate import expate
20
21
  from .notate import getate
22
+ from .notate import impate
21
23
  from .notate import setate
22
24
  from .strings import hasstr
23
25
  from .strings import inrepr
@@ -39,8 +41,10 @@ __all__ = [
39
41
  'delate',
40
42
  'DictStrAny',
41
43
  'Empty',
44
+ 'expate',
42
45
  'getate',
43
46
  'hasstr',
47
+ 'impate',
44
48
  'inlist',
45
49
  'inrepr',
46
50
  'instr',
@@ -193,6 +193,185 @@ def delate(
193
193
 
194
194
 
195
195
 
196
+ def impate( # noqa: CFQ001,CFQ004
197
+ source: DictStrAny | list[DictStrAny],
198
+ delim: str = '/',
199
+ parent: Optional[str] = None,
200
+ *,
201
+ implode_list: bool = True,
202
+ recurse_list: bool = True,
203
+ ) -> DictStrAny | list[DictStrAny]:
204
+ """
205
+ Implode the dictionary into a single depth of notation.
206
+
207
+ Example
208
+ -------
209
+ >>> impate({'foo': {'bar': 'baz'}})
210
+ {'foo/bar': 'baz'}
211
+
212
+ :param source: Dictionary object processed in notation.
213
+ :param delim: Override default delimiter between parts.
214
+ :param parent: Parent key prefix for downstream update.
215
+ :param implode_list: Determine whether list is imploded.
216
+ :param recurse_list: Determine whether flatten in list.
217
+ :returns: New dictionary that was recursively imploded.
218
+ It is also possible that a list of dictionary will
219
+ be returned when provided and implode_list is False.
220
+ """
221
+
222
+ _implode = implode_list
223
+ _recurse = recurse_list
224
+
225
+
226
+ def _proclist(
227
+ source: list[Any],
228
+ delim: str,
229
+ parent: Optional[str],
230
+ ) -> DictStrAny | list[Any]:
231
+
232
+
233
+ if _implode is False:
234
+
235
+ process = [
236
+ (impate(
237
+ item, delim,
238
+ implode_list=_implode,
239
+ recurse_list=_recurse)
240
+ if isinstance(item, dict | list)
241
+ and _recurse is True
242
+ else item)
243
+ for item in source]
244
+
245
+ return (
246
+ {parent: process}
247
+ if parent is not None
248
+ else process)
249
+
250
+
251
+ returned: DictStrAny = {}
252
+
253
+ for i, item in enumerate(source):
254
+
255
+ key = (
256
+ f'{parent}{delim}{i}'
257
+ if parent is not None
258
+ else str(i))
259
+
260
+ if (isinstance(item, dict | list)
261
+ and _recurse is True):
262
+
263
+ implode = impate(
264
+ item, delim, key,
265
+ implode_list=_implode,
266
+ recurse_list=_recurse)
267
+
268
+ assert isinstance(implode, dict)
269
+
270
+ returned.update(implode)
271
+
272
+ else:
273
+ returned[key] = item
274
+
275
+ return returned
276
+
277
+
278
+ def _procdict(
279
+ source: DictStrAny,
280
+ delim: str,
281
+ parent: Optional[str],
282
+ ) -> DictStrAny:
283
+
284
+ returned: DictStrAny = {}
285
+
286
+ for key, value in source.items():
287
+
288
+ key = (
289
+ f'{parent}{delim}{key}'
290
+ if parent is not None
291
+ else key)
292
+
293
+ if isinstance(value, dict):
294
+
295
+ implode = impate(
296
+ value, delim, key,
297
+ implode_list=_implode,
298
+ recurse_list=_recurse)
299
+
300
+ assert isinstance(implode, dict)
301
+
302
+ returned |= implode
303
+
304
+ elif isinstance(value, list):
305
+
306
+ process = _proclist(
307
+ value, delim, key)
308
+
309
+ returned |= (
310
+ {key: process}
311
+ if not isinstance(process, dict)
312
+ else process)
313
+
314
+ else:
315
+ returned[key] = value
316
+
317
+ return returned
318
+
319
+
320
+ if isinstance(source, dict):
321
+ return _procdict(
322
+ source, delim, parent)
323
+
324
+ if isinstance(source, list):
325
+ return _proclist(
326
+ source, delim, parent)
327
+
328
+ raise ValueError('source')
329
+
330
+
331
+
332
+ def expate(
333
+ source: DictStrAny,
334
+ delim: str = '/',
335
+ ) -> DictStrAny:
336
+ """
337
+ Explode the dictionary from a single depth of notation.
338
+
339
+ Example
340
+ -------
341
+ >>> expate({'foo/bar': 'baz'})
342
+ {'foo': {'bar': 'baz'}}
343
+
344
+ :param source: Dictionary object processed in notation.
345
+ :param delim: Override default delimiter between parts.
346
+ :returns: New dictionary that was recursively exploded.
347
+ """
348
+
349
+ returned: DictStrAny = {}
350
+
351
+
352
+ items = source.items()
353
+
354
+ for key, value in items:
355
+
356
+ if isinstance(value, list):
357
+ value = [
358
+ (expate(x, delim)
359
+ if isinstance(x, dict)
360
+ else x)
361
+ for x in value]
362
+
363
+ if isinstance(value, dict):
364
+ value = expate(value, delim)
365
+
366
+ setate(
367
+ returned, key,
368
+ value, delim)
369
+
370
+
371
+ return returned
372
+
373
+
374
+
196
375
  def _setpath(
197
376
  source: _SETABLE,
198
377
  path: str,
@@ -8,6 +8,13 @@ is permitted, for more information consult the project license file.
8
8
 
9
9
 
10
10
  from copy import deepcopy
11
+ from pathlib import Path
12
+
13
+
14
+
15
+ SAMPLES = (
16
+ Path(__file__).parent
17
+ / 'samples')
11
18
 
12
19
 
13
20
 
@@ -140,6 +140,7 @@ def test_merge_dicts() -> None: # noqa: CFQ001
140
140
  assert source is not _source
141
141
 
142
142
 
143
+
143
144
  def test_sort_dict() -> None:
144
145
  """
145
146
  Perform various tests associated with relevant routines.
@@ -0,0 +1,478 @@
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 copy import deepcopy
11
+ from pathlib import Path
12
+
13
+ from _pytest.python_api import RaisesContext
14
+
15
+ from pytest import fixture
16
+ from pytest import raises
17
+
18
+ from . import SAMPLES
19
+ from . import _DICT1R
20
+ from ..notate import delate
21
+ from ..notate import expate
22
+ from ..notate import getate
23
+ from ..notate import impate
24
+ from ..notate import setate
25
+ from ..types import DictStrAny
26
+ from ...utils import load_sample
27
+ from ...utils import prep_sample
28
+ from ...utils.sample import ENPYRWS
29
+
30
+
31
+
32
+ _SAMPLE = dict[str, DictStrAny]
33
+
34
+
35
+
36
+ @fixture
37
+ def sample_impate() -> _SAMPLE:
38
+ """
39
+ Construct the dictionary for use with downstream tests.
40
+
41
+ :returns: Newly constructed dictionary for use in tests.
42
+ """
43
+
44
+ recurse_implode = (
45
+ impate(
46
+ deepcopy(_DICT1R),
47
+ recurse_list=True,
48
+ implode_list=True))
49
+
50
+ assert isinstance(
51
+ recurse_implode, dict)
52
+
53
+ nocurse_noplode = (
54
+ impate(
55
+ deepcopy(_DICT1R),
56
+ recurse_list=False,
57
+ implode_list=False))
58
+
59
+ assert isinstance(
60
+ nocurse_noplode, dict)
61
+
62
+ recurse_noplode = (
63
+ impate(
64
+ deepcopy(_DICT1R),
65
+ recurse_list=True,
66
+ implode_list=False))
67
+
68
+ assert isinstance(
69
+ recurse_noplode, dict)
70
+
71
+ nocurse_implode = (
72
+ impate(
73
+ deepcopy(_DICT1R),
74
+ recurse_list=False,
75
+ implode_list=True))
76
+
77
+ assert isinstance(
78
+ nocurse_implode, dict)
79
+
80
+
81
+ return {
82
+ 'recurse_implode': recurse_implode,
83
+ 'nocurse_noplode': nocurse_noplode,
84
+ 'recurse_noplode': recurse_noplode,
85
+ 'nocurse_implode': nocurse_implode}
86
+
87
+
88
+
89
+ @fixture
90
+ def sample_expate(
91
+ sample_impate: _SAMPLE,
92
+ ) -> _SAMPLE:
93
+ """
94
+ Construct the dictionary for use with downstream tests.
95
+
96
+ :param sample_impate: Source dictionary for use in test.
97
+ :returns: Newly constructed dictionary for use in tests.
98
+ """
99
+
100
+ recurse_implode = (
101
+ sample_impate[
102
+ 'recurse_implode'])
103
+
104
+ assert isinstance(
105
+ recurse_implode, dict)
106
+
107
+ nocurse_noplode = (
108
+ sample_impate[
109
+ 'nocurse_noplode'])
110
+
111
+ assert isinstance(
112
+ nocurse_noplode, dict)
113
+
114
+ recurse_noplode = (
115
+ sample_impate[
116
+ 'recurse_noplode'])
117
+
118
+ assert isinstance(
119
+ recurse_noplode, dict)
120
+
121
+ nocurse_implode = (
122
+ sample_impate[
123
+ 'nocurse_implode'])
124
+
125
+ assert isinstance(
126
+ nocurse_implode, dict)
127
+
128
+ return {
129
+ 'recurse_implode': (
130
+ expate(recurse_implode)),
131
+ 'nocurse_noplode': (
132
+ expate(nocurse_noplode)),
133
+ 'recurse_noplode': (
134
+ expate(recurse_noplode)),
135
+ 'nocurse_implode': (
136
+ expate(nocurse_implode))}
137
+
138
+
139
+
140
+ def test_getate() -> None:
141
+ """
142
+ Perform various tests associated with relevant routines.
143
+ """
144
+
145
+ source = deepcopy(_DICT1R)
146
+
147
+
148
+ value = getate(['1', 2], '1')
149
+ assert value == 2
150
+
151
+ value = getate((1, 2), '1')
152
+ assert value == 2
153
+
154
+ value = getate({'1': 2}, '1')
155
+ assert value == 2
156
+
157
+
158
+ path = 'recurse/dict/key'
159
+ value = getate(source, path)
160
+
161
+ assert value == 'd1dict'
162
+
163
+
164
+ path = 'recurse/list/0'
165
+ value = getate(source, path)
166
+
167
+ assert value == 'd1list'
168
+
169
+
170
+
171
+ def test_getate_cover() -> None:
172
+ """
173
+ Perform various tests associated with relevant routines.
174
+ """
175
+
176
+ source = deepcopy(_DICT1R)
177
+
178
+
179
+ assert not getate({}, 'd/n/e')
180
+ assert not getate([], '0/n/e')
181
+
182
+
183
+ path = 'recurse/str/a'
184
+ value = getate(source, path)
185
+
186
+ assert value is None
187
+
188
+
189
+
190
+ def test_setate() -> None:
191
+ """
192
+ Perform various tests associated with relevant routines.
193
+ """
194
+
195
+ source = deepcopy(_DICT1R)
196
+
197
+
198
+ path = 'list/1'
199
+ before = getate(source, path)
200
+ setate(source, path, 1)
201
+ after = getate(source, path)
202
+ assert after == 1
203
+ assert before is None
204
+
205
+
206
+ path = 'recurse/dict/key'
207
+ before = getate(source, path)
208
+ setate(source, path, 1)
209
+ after = getate(source, path)
210
+ assert after == 1
211
+ assert before == 'd1dict'
212
+
213
+
214
+ path = 'nested/0/dict/key'
215
+ before = getate(source, path)
216
+ setate(source, path, 1)
217
+ after = getate(source, path)
218
+ assert after == 1
219
+ assert before == 'd1dict'
220
+
221
+
222
+ path = 'recurse/list/0'
223
+ before = getate(source, path)
224
+ setate(source, path, 1)
225
+ after = getate(source, path)
226
+ assert after == 1
227
+ assert before == 'd1list'
228
+
229
+
230
+
231
+ def test_setate_cover() -> None:
232
+ """
233
+ Perform various tests associated with relevant routines.
234
+ """
235
+
236
+ source = deepcopy(_DICT1R)
237
+
238
+
239
+ path = 'nested/1/dict/key'
240
+ before = getate(source, path)
241
+ setate(source, path, 1)
242
+ after = getate(source, path)
243
+ assert after == 1
244
+ assert before is None
245
+
246
+
247
+
248
+ def test_setate_raises() -> None:
249
+ """
250
+ Perform various tests associated with relevant routines.
251
+ """
252
+
253
+ _raises: RaisesContext[
254
+ ValueError | IndexError]
255
+
256
+
257
+ _raises = raises(ValueError)
258
+
259
+ with _raises as reason:
260
+ setate(1, '1', 1) # type: ignore
261
+
262
+ _reason = str(reason.value)
263
+
264
+ assert _reason == 'source'
265
+
266
+
267
+ _raises = raises(IndexError)
268
+
269
+ with _raises as reason:
270
+ setate([], '1', 1)
271
+
272
+ _reason = str(reason.value)
273
+
274
+ assert _reason == '1'
275
+
276
+
277
+
278
+ def test_delate() -> None:
279
+ """
280
+ Perform various tests associated with relevant routines.
281
+ """
282
+
283
+ source = deepcopy(_DICT1R)
284
+
285
+
286
+ path = 'recurse/dict/key'
287
+ before = getate(source, path)
288
+ delate(source, path)
289
+ after = getate(source, path)
290
+ assert after is None
291
+ assert before == 'd1dict'
292
+
293
+
294
+ path = 'nested/0/dict/key'
295
+ before = getate(source, path)
296
+ delate(source, path)
297
+ after = getate(source, path)
298
+ assert after is None
299
+ assert before == 'd1dict'
300
+
301
+
302
+ path = 'recurse/list/0'
303
+ before = getate(source, path)
304
+ delate(source, path)
305
+ after = getate(source, path)
306
+ assert after is None
307
+ assert before == 'd1list'
308
+
309
+
310
+
311
+ def test_delate_raises() -> None:
312
+ """
313
+ Perform various tests associated with relevant routines.
314
+ """
315
+
316
+
317
+ _raises = raises(ValueError)
318
+
319
+ with _raises as reason:
320
+ delate(1, '1') # type: ignore
321
+
322
+ _reason = str(reason.value)
323
+
324
+ assert _reason == 'source'
325
+
326
+
327
+ _raises = raises(ValueError)
328
+
329
+ with _raises as reason:
330
+ delate({'a': 1}, 'a/1/c')
331
+
332
+ _reason = str(reason.value)
333
+
334
+ assert _reason == 'source'
335
+
336
+
337
+
338
+ def test_impate(
339
+ tmp_path: Path,
340
+ sample_impate: _SAMPLE,
341
+ sample_expate: _SAMPLE,
342
+ ) -> None:
343
+ """
344
+ Perform various tests associated with relevant routines.
345
+
346
+ :param sample_impate: Source dictionary for use in test.
347
+ :param sample_expate: Source dictionary for use in test.
348
+ :param tmp_path: pytest object for temporal filesystem.
349
+ """
350
+
351
+ sample_path = (
352
+ SAMPLES / 'impate.json')
353
+
354
+ sample = load_sample(
355
+ path=sample_path,
356
+ update=ENPYRWS,
357
+ content=sample_impate)
358
+
359
+ expect = prep_sample(
360
+ content=sample_impate)
361
+
362
+ assert expect == sample
363
+
364
+
365
+
366
+ def test_impate_cover(
367
+ tmp_path: Path,
368
+ sample_impate: _SAMPLE,
369
+ sample_expate: _SAMPLE,
370
+ ) -> None:
371
+ """
372
+ Perform various tests associated with relevant routines.
373
+
374
+ :param sample_impate: Source dictionary for use in test.
375
+ :param sample_expate: Source dictionary for use in test.
376
+ :param tmp_path: pytest object for temporal filesystem.
377
+ """
378
+
379
+
380
+ default = sample_impate[
381
+ 'recurse_implode']
382
+
383
+ assert default == impate(default)
384
+
385
+
386
+ sample = 'recurse_noplode'
387
+
388
+ implode = impate(
389
+ [sample_expate[sample],
390
+ sample_expate[sample]],
391
+ implode_list=False,
392
+ recurse_list=True)
393
+
394
+ assert isinstance(implode, list)
395
+
396
+ assert implode[0] == (
397
+ sample_impate[sample])
398
+
399
+
400
+ source = {'foo': {'bar': 'baz'}}
401
+ expect = {'foo/bar': 'baz'}
402
+
403
+ assert impate(source) == expect
404
+
405
+
406
+
407
+ def test_impate_raises() -> None:
408
+ """
409
+ Perform various tests associated with relevant routines.
410
+ """
411
+
412
+ _raises: RaisesContext[ValueError]
413
+
414
+
415
+ _raises = raises(ValueError)
416
+
417
+ with _raises as reason:
418
+ impate('foo') # type: ignore
419
+
420
+ _reason = str(reason.value)
421
+
422
+ assert _reason == 'source'
423
+
424
+
425
+
426
+ def test_expate(
427
+ tmp_path: Path,
428
+ sample_impate: _SAMPLE,
429
+ sample_expate: _SAMPLE,
430
+ ) -> None:
431
+ """
432
+ Perform various tests associated with relevant routines.
433
+
434
+ :param sample_impate: Source dictionary for use in test.
435
+ :param sample_expate: Source dictionary for use in test.
436
+ :param tmp_path: pytest object for temporal filesystem.
437
+ """
438
+
439
+ sample_path = (
440
+ SAMPLES / 'expate.json')
441
+
442
+ sample = load_sample(
443
+ path=sample_path,
444
+ update=ENPYRWS,
445
+ content=sample_expate)
446
+
447
+ expect = prep_sample(
448
+ content=sample_expate)
449
+
450
+ assert expect == sample
451
+
452
+
453
+
454
+ def test_expate_cover(
455
+ tmp_path: Path,
456
+ sample_impate: _SAMPLE,
457
+ sample_expate: _SAMPLE,
458
+ ) -> None:
459
+ """
460
+ Perform various tests associated with relevant routines.
461
+
462
+ :param sample_impate: Source dictionary for use in test.
463
+ :param sample_expate: Source dictionary for use in test.
464
+ :param tmp_path: pytest object for temporal filesystem.
465
+ """
466
+
467
+
468
+ assert sample_expate == (
469
+ expate(sample_impate))
470
+
471
+
472
+ assert sample_expate == (
473
+ expate(sample_expate))
474
+
475
+
476
+ assert all(
477
+ x == _DICT1R for x in
478
+ sample_expate.values())
@@ -0,0 +1 @@
1
+ 0.21.0
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.2
2
2
  Name: encommon
3
- Version: 0.20.5
3
+ Version: 0.21.0
4
4
  Summary: Enasis Network Common Library
5
5
  License: MIT
6
6
  Project-URL: Source, https://github.com/enasisnetwork/encommon
@@ -1,217 +0,0 @@
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 copy import deepcopy
11
-
12
- from _pytest.python_api import RaisesContext
13
-
14
- from pytest import raises
15
-
16
- from . import _DICT1R
17
- from ..notate import delate
18
- from ..notate import getate
19
- from ..notate import setate
20
-
21
-
22
-
23
- def test_getate() -> None:
24
- """
25
- Perform various tests associated with relevant routines.
26
- """
27
-
28
- source = deepcopy(_DICT1R)
29
-
30
-
31
- value = getate(['1', 2], '1')
32
- assert value == 2
33
-
34
- value = getate((1, 2), '1')
35
- assert value == 2
36
-
37
- value = getate({'1': 2}, '1')
38
- assert value == 2
39
-
40
-
41
- path = 'recurse/dict/key'
42
- value = getate(source, path)
43
-
44
- assert value == 'd1dict'
45
-
46
-
47
- path = 'recurse/list/0'
48
- value = getate(source, path)
49
-
50
- assert value == 'd1list'
51
-
52
-
53
-
54
- def test_getate_cover() -> None:
55
- """
56
- Perform various tests associated with relevant routines.
57
- """
58
-
59
- source = deepcopy(_DICT1R)
60
-
61
-
62
- assert not getate({}, 'd/n/e')
63
- assert not getate([], '0/n/e')
64
-
65
-
66
- path = 'recurse/str/a'
67
- value = getate(source, path)
68
-
69
- assert value is None
70
-
71
-
72
-
73
- def test_setate() -> None:
74
- """
75
- Perform various tests associated with relevant routines.
76
- """
77
-
78
- source = deepcopy(_DICT1R)
79
-
80
-
81
- path = 'list/1'
82
- before = getate(source, path)
83
- setate(source, path, 1)
84
- after = getate(source, path)
85
- assert after == 1
86
- assert before is None
87
-
88
-
89
- path = 'recurse/dict/key'
90
- before = getate(source, path)
91
- setate(source, path, 1)
92
- after = getate(source, path)
93
- assert after == 1
94
- assert before == 'd1dict'
95
-
96
-
97
- path = 'nested/0/dict/key'
98
- before = getate(source, path)
99
- setate(source, path, 1)
100
- after = getate(source, path)
101
- assert after == 1
102
- assert before == 'd1dict'
103
-
104
-
105
- path = 'recurse/list/0'
106
- before = getate(source, path)
107
- setate(source, path, 1)
108
- after = getate(source, path)
109
- assert after == 1
110
- assert before == 'd1list'
111
-
112
-
113
-
114
- def test_setate_cover() -> None:
115
- """
116
- Perform various tests associated with relevant routines.
117
- """
118
-
119
- source = deepcopy(_DICT1R)
120
-
121
-
122
- path = 'nested/1/dict/key'
123
- before = getate(source, path)
124
- setate(source, path, 1)
125
- after = getate(source, path)
126
- assert after == 1
127
- assert before is None
128
-
129
-
130
-
131
- def test_setate_raises() -> None:
132
- """
133
- Perform various tests associated with relevant routines.
134
- """
135
-
136
- _raises: RaisesContext[
137
- ValueError | IndexError]
138
-
139
-
140
- _raises = raises(ValueError)
141
-
142
- with _raises as reason:
143
- setate(1, '1', 1) # type: ignore
144
-
145
- _reason = str(reason.value)
146
-
147
- assert _reason == 'source'
148
-
149
-
150
- _raises = raises(IndexError)
151
-
152
- with _raises as reason:
153
- setate([], '1', 1)
154
-
155
- _reason = str(reason.value)
156
-
157
- assert _reason == '1'
158
-
159
-
160
-
161
- def test_delate() -> None:
162
- """
163
- Perform various tests associated with relevant routines.
164
- """
165
-
166
- source = deepcopy(_DICT1R)
167
-
168
-
169
- path = 'recurse/dict/key'
170
- before = getate(source, path)
171
- delate(source, path)
172
- after = getate(source, path)
173
- assert after is None
174
- assert before == 'd1dict'
175
-
176
-
177
- path = 'nested/0/dict/key'
178
- before = getate(source, path)
179
- delate(source, path)
180
- after = getate(source, path)
181
- assert after is None
182
- assert before == 'd1dict'
183
-
184
-
185
- path = 'recurse/list/0'
186
- before = getate(source, path)
187
- delate(source, path)
188
- after = getate(source, path)
189
- assert after is None
190
- assert before == 'd1list'
191
-
192
-
193
-
194
- def test_delate_raises() -> None:
195
- """
196
- Perform various tests associated with relevant routines.
197
- """
198
-
199
-
200
- _raises = raises(ValueError)
201
-
202
- with _raises as reason:
203
- delate(1, '1') # type: ignore
204
-
205
- _reason = str(reason.value)
206
-
207
- assert _reason == 'source'
208
-
209
-
210
- _raises = raises(ValueError)
211
-
212
- with _raises as reason:
213
- delate({'a': 1}, 'a/1/c')
214
-
215
- _reason = str(reason.value)
216
-
217
- assert _reason == 'source'
@@ -1 +0,0 @@
1
- 0.20.5
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes