encommon 0.7.6__py3-none-any.whl → 0.8.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/__init__.py +4 -0
- encommon/config/common.py +18 -14
- encommon/config/config.py +8 -5
- encommon/config/files.py +13 -7
- encommon/config/logger.py +94 -88
- encommon/config/params.py +1 -1
- encommon/config/paths.py +16 -8
- encommon/config/test/test_common.py +27 -4
- encommon/config/test/test_config.py +48 -82
- encommon/config/test/test_files.py +58 -43
- encommon/config/test/test_logger.py +129 -82
- encommon/config/test/test_paths.py +70 -30
- encommon/conftest.py +52 -12
- encommon/crypts/__init__.py +2 -0
- encommon/crypts/crypts.py +3 -1
- encommon/crypts/hashes.py +2 -2
- encommon/crypts/test/test_crypts.py +50 -28
- encommon/crypts/test/test_hashes.py +20 -18
- encommon/times/__init__.py +2 -0
- encommon/times/common.py +99 -15
- encommon/times/duration.py +50 -36
- encommon/times/parse.py +13 -25
- encommon/times/test/test_common.py +47 -16
- encommon/times/test/test_duration.py +104 -79
- encommon/times/test/test_parse.py +53 -63
- encommon/times/test/test_timers.py +90 -36
- encommon/times/test/test_times.py +21 -30
- encommon/times/test/test_window.py +73 -21
- encommon/times/timers.py +91 -58
- encommon/times/times.py +36 -34
- encommon/times/window.py +4 -4
- encommon/types/dicts.py +10 -4
- encommon/types/empty.py +7 -2
- encommon/types/strings.py +10 -0
- encommon/types/test/test_dicts.py +5 -5
- encommon/types/test/test_empty.py +4 -1
- encommon/types/test/test_strings.py +1 -1
- encommon/utils/__init__.py +4 -0
- encommon/utils/common.py +51 -6
- encommon/utils/match.py +1 -0
- encommon/utils/paths.py +42 -23
- encommon/utils/sample.py +31 -27
- encommon/utils/stdout.py +28 -17
- encommon/utils/test/test_common.py +35 -0
- encommon/utils/test/test_paths.py +3 -2
- encommon/utils/test/test_sample.py +28 -12
- encommon/version.txt +1 -1
- {encommon-0.7.6.dist-info → encommon-0.8.0.dist-info}/METADATA +1 -1
- encommon-0.8.0.dist-info/RECORD +63 -0
- encommon-0.7.6.dist-info/RECORD +0 -62
- {encommon-0.7.6.dist-info → encommon-0.8.0.dist-info}/LICENSE +0 -0
- {encommon-0.7.6.dist-info → encommon-0.8.0.dist-info}/WHEEL +0 -0
- {encommon-0.7.6.dist-info → encommon-0.8.0.dist-info}/top_level.txt +0 -0
encommon/utils/common.py
CHANGED
@@ -12,16 +12,61 @@ from typing import Union
|
|
12
12
|
|
13
13
|
|
14
14
|
|
15
|
-
JOINABLE = (
|
16
|
-
list # type: ignore
|
17
|
-
| tuple # type: ignore
|
18
|
-
| set) # type: ignore
|
15
|
+
JOINABLE = (list, tuple, set)
|
19
16
|
|
20
17
|
|
21
18
|
|
22
19
|
PATHABLE = Union[
|
23
|
-
str,
|
24
|
-
Path,
|
20
|
+
str, Path,
|
25
21
|
list[str | Path],
|
26
22
|
tuple[str | Path],
|
27
23
|
set[str]]
|
24
|
+
|
25
|
+
|
26
|
+
|
27
|
+
REPLACE = Union[
|
28
|
+
dict[str, str],
|
29
|
+
dict[str, str | Path],
|
30
|
+
dict[str, Path],
|
31
|
+
dict[str, str],
|
32
|
+
dict[str | Path, str],
|
33
|
+
dict[Path, str]]
|
34
|
+
|
35
|
+
|
36
|
+
|
37
|
+
def read_text(
|
38
|
+
path: str | Path,
|
39
|
+
) -> str:
|
40
|
+
"""
|
41
|
+
Read the text content from within the provided file path.
|
42
|
+
|
43
|
+
:param path: Complete or relative path to the text file.
|
44
|
+
:returns: Text content that was read from the file path.
|
45
|
+
"""
|
46
|
+
|
47
|
+
path = Path(path).resolve()
|
48
|
+
|
49
|
+
return path.read_text(
|
50
|
+
encoding='utf-8')
|
51
|
+
|
52
|
+
|
53
|
+
|
54
|
+
def save_text(
|
55
|
+
path: str | Path,
|
56
|
+
content: str,
|
57
|
+
) -> str:
|
58
|
+
"""
|
59
|
+
Save the provided text content to the provided file path.
|
60
|
+
|
61
|
+
:param path: Complete or relative path to the text file.
|
62
|
+
:param content: Content that will be written to the file.
|
63
|
+
:returns: Text content that was read from the file path.
|
64
|
+
"""
|
65
|
+
|
66
|
+
path = Path(path).resolve()
|
67
|
+
|
68
|
+
path.write_text(
|
69
|
+
data=content,
|
70
|
+
encoding='utf-8')
|
71
|
+
|
72
|
+
return read_text(path)
|
encommon/utils/match.py
CHANGED
encommon/utils/paths.py
CHANGED
@@ -10,22 +10,27 @@ is permitted, for more information consult the project license file.
|
|
10
10
|
from os import stat_result
|
11
11
|
from pathlib import Path
|
12
12
|
from typing import Optional
|
13
|
+
from typing import TYPE_CHECKING
|
13
14
|
|
14
|
-
from .common import PATHABLE
|
15
15
|
from .match import rgxp_match
|
16
|
+
from ..types import sort_dict
|
16
17
|
|
18
|
+
if TYPE_CHECKING:
|
19
|
+
from .common import PATHABLE
|
20
|
+
from .common import REPLACE
|
17
21
|
|
18
22
|
|
19
|
-
|
23
|
+
|
24
|
+
STATS_PATH = dict[str, stat_result]
|
20
25
|
|
21
26
|
|
22
27
|
|
23
28
|
def resolve_path(
|
24
29
|
path: str | Path,
|
25
|
-
replace: Optional[
|
30
|
+
replace: Optional['REPLACE'] = None,
|
26
31
|
) -> Path:
|
27
32
|
"""
|
28
|
-
Resolve the provided path
|
33
|
+
Resolve the provided path replacing the magic keywords.
|
29
34
|
|
30
35
|
Example
|
31
36
|
-------
|
@@ -33,14 +38,24 @@ def resolve_path(
|
|
33
38
|
PosixPath('/foo/bar')
|
34
39
|
|
35
40
|
:param path: Complete or relative path for processing.
|
36
|
-
:param replace: Optional
|
41
|
+
:param replace: Optional values to replace in the path.
|
37
42
|
:returns: New resolved filesystem path object instance.
|
38
43
|
"""
|
39
44
|
|
40
45
|
path = str(path).strip()
|
41
46
|
|
42
47
|
if replace is not None:
|
43
|
-
|
48
|
+
|
49
|
+
items = replace.items()
|
50
|
+
|
51
|
+
for old, new in items:
|
52
|
+
|
53
|
+
if isinstance(old, Path):
|
54
|
+
old = str(old)
|
55
|
+
|
56
|
+
if isinstance(new, Path):
|
57
|
+
new = str(new)
|
58
|
+
|
44
59
|
path = path.replace(old, new)
|
45
60
|
|
46
61
|
return Path(path).resolve()
|
@@ -48,11 +63,11 @@ def resolve_path(
|
|
48
63
|
|
49
64
|
|
50
65
|
def resolve_paths(
|
51
|
-
paths: PATHABLE,
|
52
|
-
replace: Optional[
|
66
|
+
paths: 'PATHABLE',
|
67
|
+
replace: Optional['REPLACE'] = None,
|
53
68
|
) -> tuple[Path, ...]:
|
54
69
|
"""
|
55
|
-
Resolve the provided paths
|
70
|
+
Resolve the provided paths replacing the magic keywords.
|
56
71
|
|
57
72
|
.. note::
|
58
73
|
This will remove duplicative paths from the returned.
|
@@ -63,7 +78,7 @@ def resolve_paths(
|
|
63
78
|
(PosixPath('/foo/bar'),)
|
64
79
|
|
65
80
|
:param paths: Complete or relative paths for processing.
|
66
|
-
:param replace: Optional
|
81
|
+
:param replace: Optional values to replace in the path.
|
67
82
|
:returns: New resolved filesystem path object instances.
|
68
83
|
"""
|
69
84
|
|
@@ -74,13 +89,13 @@ def resolve_paths(
|
|
74
89
|
|
75
90
|
for path in paths:
|
76
91
|
|
77
|
-
|
78
|
-
|
92
|
+
resolved = resolve_path(
|
93
|
+
path, replace)
|
79
94
|
|
80
|
-
if
|
95
|
+
if resolved in returned:
|
81
96
|
continue
|
82
97
|
|
83
|
-
returned.append(
|
98
|
+
returned.append(resolved)
|
84
99
|
|
85
100
|
return tuple(returned)
|
86
101
|
|
@@ -88,17 +103,18 @@ def resolve_paths(
|
|
88
103
|
|
89
104
|
def stats_path(
|
90
105
|
path: str | Path,
|
91
|
-
replace: Optional[
|
106
|
+
replace: Optional['REPLACE'] = None,
|
92
107
|
ignore: Optional[list[str]] = None,
|
93
|
-
) ->
|
108
|
+
) -> STATS_PATH:
|
94
109
|
"""
|
95
110
|
Collect stats object for the complete or relative path.
|
96
111
|
|
97
112
|
.. testsetup::
|
113
|
+
>>> from . import save_text
|
98
114
|
>>> path = Path(getfixture('tmpdir'))
|
99
115
|
>>> file = path.joinpath('hello.txt')
|
100
|
-
>>> file
|
101
|
-
|
116
|
+
>>> save_text(file, 'Hello world!')
|
117
|
+
'Hello world!'
|
102
118
|
|
103
119
|
Example
|
104
120
|
-------
|
@@ -108,18 +124,20 @@ def stats_path(
|
|
108
124
|
12
|
109
125
|
|
110
126
|
:param path: Complete or relative path for enumeration.
|
111
|
-
:param replace: Optional
|
127
|
+
:param replace: Optional values to replace in the path.
|
112
128
|
:param ignore: Paths matching these patterns are ignored.
|
113
129
|
:returns: Metadata for files recursively found in path.
|
114
130
|
"""
|
115
131
|
|
116
132
|
path = Path(path).resolve()
|
117
133
|
|
118
|
-
returned:
|
134
|
+
returned: STATS_PATH = {}
|
119
135
|
|
120
136
|
|
121
137
|
def _ignore() -> bool:
|
138
|
+
|
122
139
|
assert ignore is not None
|
140
|
+
|
123
141
|
return rgxp_match(
|
124
142
|
str(item), ignore)
|
125
143
|
|
@@ -141,8 +159,9 @@ def stats_path(
|
|
141
159
|
key = resolve_path(
|
142
160
|
item, replace)
|
143
161
|
|
144
|
-
|
145
|
-
|
162
|
+
stat = item.stat()
|
163
|
+
|
164
|
+
returned[str(key)] = stat
|
146
165
|
|
147
166
|
|
148
|
-
return
|
167
|
+
return sort_dict(returned)
|
encommon/utils/sample.py
CHANGED
@@ -13,17 +13,13 @@ from pathlib import Path
|
|
13
13
|
from typing import Any
|
14
14
|
from typing import Callable
|
15
15
|
from typing import Optional
|
16
|
-
from typing import
|
16
|
+
from typing import TYPE_CHECKING
|
17
17
|
|
18
|
-
from
|
19
|
-
from
|
18
|
+
from . import read_text
|
19
|
+
from . import save_text
|
20
20
|
|
21
|
-
|
22
|
-
|
23
|
-
_REPLACE = Union[
|
24
|
-
dict[str, str],
|
25
|
-
dict[str, str | Path],
|
26
|
-
dict[str, Path]]
|
21
|
+
if TYPE_CHECKING:
|
22
|
+
from .common import REPLACE
|
27
23
|
|
28
24
|
|
29
25
|
|
@@ -31,7 +27,7 @@ def prep_sample(
|
|
31
27
|
content: Any,
|
32
28
|
*,
|
33
29
|
default: Callable[[Any], str] = str,
|
34
|
-
replace: Optional[
|
30
|
+
replace: Optional['REPLACE'] = None,
|
35
31
|
) -> Any:
|
36
32
|
"""
|
37
33
|
Return the content after processing using JSON functions.
|
@@ -49,9 +45,9 @@ def prep_sample(
|
|
49
45
|
>>> prep_sample({'one': Empty})
|
50
46
|
{'one': 'Empty'}
|
51
47
|
|
52
|
-
:param content: Content
|
48
|
+
:param content: Content that will be processed as JSON.
|
53
49
|
:param default: Callable used when stringifying values.
|
54
|
-
:param replace: Optional
|
50
|
+
:param replace: Optional values to replace in the file.
|
55
51
|
:returns: Content after processing using JSON functions.
|
56
52
|
"""
|
57
53
|
|
@@ -60,13 +56,14 @@ def prep_sample(
|
|
60
56
|
|
61
57
|
prefix = 'encommon_sample'
|
62
58
|
|
63
|
-
replace =
|
59
|
+
replace = replace or {}
|
60
|
+
|
61
|
+
items = replace.items()
|
64
62
|
|
65
|
-
|
66
|
-
'PROJECT': PROJECT,
|
67
|
-
'WORKSPACE': WORKSPACE}
|
63
|
+
for old, new in items:
|
68
64
|
|
69
|
-
|
65
|
+
if isinstance(old, Path):
|
66
|
+
old = str(old)
|
70
67
|
|
71
68
|
if isinstance(new, Path):
|
72
69
|
new = str(new)
|
@@ -79,12 +76,12 @@ def prep_sample(
|
|
79
76
|
|
80
77
|
|
81
78
|
def load_sample(
|
82
|
-
path: Path,
|
79
|
+
path: str | Path,
|
83
80
|
content: Optional[Any] = None,
|
84
81
|
update: bool = False,
|
85
82
|
*,
|
86
83
|
default: Callable[[Any], str] = str,
|
87
|
-
replace: Optional[
|
84
|
+
replace: Optional['REPLACE'] = None,
|
88
85
|
) -> Any:
|
89
86
|
"""
|
90
87
|
Load the sample file and compare using provided content.
|
@@ -106,16 +103,19 @@ def load_sample(
|
|
106
103
|
>>> load_sample(sample)
|
107
104
|
{'one': 'two'}
|
108
105
|
|
109
|
-
:param path: Complete or relative path
|
106
|
+
:param path: Complete or relative path for the sample.
|
110
107
|
:param update: Determine whether the sample is updated.
|
111
|
-
:param content: Content
|
108
|
+
:param content: Content that will be processed as JSON.
|
112
109
|
:param default: Callable used when stringifying values.
|
113
|
-
:param replace: Optional
|
110
|
+
:param replace: Optional values to replace in the file.
|
114
111
|
:returns: Content after processing using JSON functions.
|
115
112
|
"""
|
116
113
|
|
114
|
+
path = Path(path).resolve()
|
115
|
+
|
117
116
|
loaded: Optional[Any] = None
|
118
117
|
|
118
|
+
|
119
119
|
content = prep_sample(
|
120
120
|
content=content,
|
121
121
|
default=default,
|
@@ -123,14 +123,18 @@ def load_sample(
|
|
123
123
|
|
124
124
|
|
125
125
|
def _save_sample() -> None:
|
126
|
-
|
127
|
-
|
126
|
+
|
127
|
+
dumped = dumps(
|
128
|
+
content, indent=2)
|
129
|
+
|
130
|
+
save_text(path, dumped)
|
128
131
|
|
129
132
|
|
130
133
|
def _load_sample() -> Any:
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
+
|
135
|
+
loaded = read_text(path)
|
136
|
+
|
137
|
+
return loads(loaded)
|
134
138
|
|
135
139
|
|
136
140
|
if path.exists():
|
encommon/utils/stdout.py
CHANGED
@@ -16,11 +16,13 @@ from typing import Literal
|
|
16
16
|
from typing import Optional
|
17
17
|
from typing import Union
|
18
18
|
|
19
|
-
from encommon.times import Duration
|
20
|
-
from encommon.times import Times
|
21
|
-
from encommon.types import Empty
|
22
|
-
|
23
19
|
from .common import JOINABLE
|
20
|
+
from ..times import Duration
|
21
|
+
from ..times import Times
|
22
|
+
from ..types import Empty
|
23
|
+
from ..types.strings import COMMAD
|
24
|
+
from ..types.strings import NEWLINE
|
25
|
+
from ..types.strings import SEMPTY
|
24
26
|
|
25
27
|
|
26
28
|
|
@@ -40,6 +42,10 @@ ANSIARRAY = Union[
|
|
40
42
|
|
41
43
|
|
42
44
|
|
45
|
+
_REPEAT = (list, tuple, dict)
|
46
|
+
|
47
|
+
|
48
|
+
|
43
49
|
@dataclass(frozen=True)
|
44
50
|
class ArrayColors:
|
45
51
|
"""
|
@@ -49,6 +55,9 @@ class ArrayColors:
|
|
49
55
|
label: int = 37
|
50
56
|
key: int = 97
|
51
57
|
|
58
|
+
colon: int = 37
|
59
|
+
hyphen: int = 37
|
60
|
+
|
52
61
|
bool: int = 93
|
53
62
|
none: int = 33
|
54
63
|
str: int = 92
|
@@ -58,13 +67,10 @@ class ArrayColors:
|
|
58
67
|
empty: int = 36
|
59
68
|
other: int = 91
|
60
69
|
|
61
|
-
colon: int = 37
|
62
|
-
hyphen: int = 37
|
63
|
-
|
64
70
|
|
65
71
|
|
66
72
|
def print_ansi(
|
67
|
-
string: str =
|
73
|
+
string: str = SEMPTY,
|
68
74
|
method: Literal['stdout', 'print'] = 'stdout',
|
69
75
|
output: bool = True,
|
70
76
|
) -> str:
|
@@ -133,8 +139,8 @@ def kvpair_ansi(
|
|
133
139
|
:returns: ANSI colorized string using inline directives.
|
134
140
|
""" # noqa: D301 LIT102
|
135
141
|
|
136
|
-
if isinstance(value, JOINABLE):
|
137
|
-
value =
|
142
|
+
if isinstance(value, JOINABLE):
|
143
|
+
value = COMMAD.join([
|
138
144
|
str(x) for x in value])
|
139
145
|
|
140
146
|
elif not isinstance(value, str):
|
@@ -161,7 +167,7 @@ def strip_ansi(
|
|
161
167
|
:returns: Provided string with the ANSI codes removed.
|
162
168
|
""" # noqa: D301 LIT102
|
163
169
|
|
164
|
-
return re_sub(ANSICODE,
|
170
|
+
return re_sub(ANSICODE, SEMPTY, string)
|
165
171
|
|
166
172
|
|
167
173
|
|
@@ -206,25 +212,28 @@ def array_ansi( # noqa: CFQ001, CFQ004
|
|
206
212
|
f'{prefix} {repeat}')
|
207
213
|
|
208
214
|
|
209
|
-
if isinstance(value,
|
215
|
+
if isinstance(value, _REPEAT):
|
210
216
|
refers.add(id(value))
|
211
217
|
|
212
218
|
|
213
|
-
|
219
|
+
typing = {
|
214
220
|
'list': list,
|
215
221
|
'tuple': tuple,
|
216
222
|
'dict': dict,
|
217
223
|
'frozenset': frozenset,
|
218
224
|
'set': set}
|
219
225
|
|
220
|
-
|
226
|
+
items = typing.items()
|
227
|
+
|
228
|
+
for name, _type in items:
|
221
229
|
|
222
230
|
if not isinstance(value, _type):
|
223
231
|
continue
|
224
232
|
|
225
233
|
output.append(
|
226
234
|
f'{prefix} '
|
227
|
-
f'<c{colors.label}>
|
235
|
+
f'<c{colors.label}>'
|
236
|
+
f'{name}<c0>')
|
228
237
|
|
229
238
|
return _process(
|
230
239
|
source=value,
|
@@ -281,7 +290,9 @@ def array_ansi( # noqa: CFQ001, CFQ004
|
|
281
290
|
|
282
291
|
assert isinstance(source, dict)
|
283
292
|
|
284
|
-
|
293
|
+
items = source.items()
|
294
|
+
|
295
|
+
for key, value in items:
|
285
296
|
|
286
297
|
prefix = (
|
287
298
|
f'{" " * indent}'
|
@@ -340,4 +351,4 @@ def array_ansi( # noqa: CFQ001, CFQ004
|
|
340
351
|
_output = [
|
341
352
|
make_ansi(x) for x in output]
|
342
353
|
|
343
|
-
return
|
354
|
+
return NEWLINE.join(_output)
|
@@ -0,0 +1,35 @@
|
|
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 pathlib import Path
|
11
|
+
|
12
|
+
from ..common import read_text
|
13
|
+
from ..common import save_text
|
14
|
+
|
15
|
+
|
16
|
+
|
17
|
+
def test_readsave_text(
|
18
|
+
tmp_path: Path,
|
19
|
+
) -> None:
|
20
|
+
"""
|
21
|
+
Perform various tests associated with relevant routines.
|
22
|
+
|
23
|
+
:param tmp_path: pytest object for temporal filesystem.
|
24
|
+
"""
|
25
|
+
|
26
|
+
content = 'pytest'
|
27
|
+
|
28
|
+
save_text(
|
29
|
+
f'{tmp_path}/test.txt',
|
30
|
+
content)
|
31
|
+
|
32
|
+
loaded = read_text(
|
33
|
+
f'{tmp_path}/test.txt')
|
34
|
+
|
35
|
+
assert loaded == content
|
@@ -13,7 +13,7 @@ from ..paths import resolve_path
|
|
13
13
|
from ..paths import resolve_paths
|
14
14
|
from ..paths import stats_path
|
15
15
|
from ... import PROJECT
|
16
|
-
from ...times
|
16
|
+
from ...times import Times
|
17
17
|
|
18
18
|
|
19
19
|
|
@@ -61,7 +61,7 @@ def test_stats_path() -> None:
|
|
61
61
|
|
62
62
|
stats = stats_path(
|
63
63
|
f'{PROJECT}/utils',
|
64
|
-
replace={
|
64
|
+
replace={PROJECT: '/'},
|
65
65
|
ignore=[r'\S+\.pyc'])
|
66
66
|
|
67
67
|
stat = stats['/utils/paths.py']
|
@@ -81,6 +81,7 @@ def test_stats_path() -> None:
|
|
81
81
|
'/utils/sample.py',
|
82
82
|
'/utils/stdout.py',
|
83
83
|
'/utils/test/__init__.py',
|
84
|
+
'/utils/test/test_common.py',
|
84
85
|
'/utils/test/test_match.py',
|
85
86
|
'/utils/test/test_paths.py',
|
86
87
|
'/utils/test/test_sample.py',
|
@@ -34,34 +34,50 @@ def test_load_sample(
|
|
34
34
|
:param tmp_path: pytest object for temporal filesystem.
|
35
35
|
"""
|
36
36
|
|
37
|
-
|
38
|
-
Path(tmp_path)
|
39
|
-
.joinpath('samples.json'))
|
37
|
+
prefix = 'encommon_sample'
|
40
38
|
|
41
39
|
source = {
|
42
40
|
'list': ['bar', 'baz'],
|
43
41
|
'tuple': (1, 2),
|
44
42
|
'project': PROJECT,
|
45
|
-
'other': '/
|
43
|
+
'other': '/pat/h',
|
44
|
+
'devnull': '/dev/null'}
|
46
45
|
|
47
46
|
expect = {
|
48
47
|
'list': ['bar', 'baz'],
|
49
48
|
'tuple': [1, 2],
|
50
|
-
'project': '_/
|
51
|
-
'other': '_/
|
49
|
+
'project': f'_/{prefix}/PROJECT/_',
|
50
|
+
'other': f'_/{prefix}/pytemp/_',
|
51
|
+
'devnull': '/dev/null'}
|
52
|
+
|
53
|
+
|
54
|
+
devnull = Path('/dev/null')
|
55
|
+
|
56
|
+
replaces = {
|
57
|
+
devnull: 'nothing here',
|
58
|
+
'PROJECT': str(PROJECT),
|
59
|
+
'pytemp': '/pat/h'}
|
60
|
+
|
61
|
+
|
62
|
+
sample_path = (
|
63
|
+
f'{tmp_path}/samples.json')
|
52
64
|
|
53
65
|
sample = load_sample(
|
54
|
-
path=
|
66
|
+
path=sample_path,
|
55
67
|
update=ENPYRWS,
|
56
68
|
content=source,
|
57
|
-
replace=
|
69
|
+
replace=replaces) # type: ignore
|
58
70
|
|
59
71
|
assert sample == expect
|
60
72
|
|
73
|
+
|
74
|
+
source |= {'list': [1, 3, 2]}
|
75
|
+
expect |= {'list': [1, 3, 2]}
|
76
|
+
|
61
77
|
sample = load_sample(
|
62
|
-
path=
|
63
|
-
content=source
|
78
|
+
path=sample_path,
|
79
|
+
content=source,
|
64
80
|
update=True,
|
65
|
-
replace=
|
81
|
+
replace=replaces) # type: ignore
|
66
82
|
|
67
|
-
assert sample == expect
|
83
|
+
assert sample == expect
|
encommon/version.txt
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.8.0
|
@@ -0,0 +1,63 @@
|
|
1
|
+
encommon/__init__.py,sha256=VoXUcphq-gcXCraaU47EtXBftF6UVuQPMGr0fuCTt9A,525
|
2
|
+
encommon/conftest.py,sha256=J2__qc7WP8oZkMLXRCw9qlBaaHSx1HhkIkKkGnHHCAU,1810
|
3
|
+
encommon/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
4
|
+
encommon/version.txt,sha256=pmeA2iMQO-rxJDK0GFCJZrMaKjp4f5RopbbNqoZnwe8,6
|
5
|
+
encommon/config/__init__.py,sha256=z5XduE2no0m1FUCkRyBnTU_1fFnpmn1ExV1ODpz-6Ak,816
|
6
|
+
encommon/config/common.py,sha256=QGrbA3OlQ0nta6cOyEu0dw8li9UlV_J7Yn3rhZLm7mw,2099
|
7
|
+
encommon/config/config.py,sha256=1_QFlMdYTB2VLhRtA_g6zhi-O2PFXCmZFBW6VIMPe4Y,4790
|
8
|
+
encommon/config/files.py,sha256=Mdb9MN4AKzue6Mdl4B2C8epiuPI6vnfVu55yiPUTiQ8,2388
|
9
|
+
encommon/config/logger.py,sha256=5X7Y72g-D4hJ2TCfqDxiAZpQcUT-Exgbf2t7kiIM0q0,13488
|
10
|
+
encommon/config/params.py,sha256=ZBcg2_gi-LWKMRUKrv3G4Eyr7hGAoxCVouVQLz3he1Y,1809
|
11
|
+
encommon/config/paths.py,sha256=eR0BQC_TaKHu1dQGrC8o69l6dEqDoI8JS9IHmPrsJ68,2535
|
12
|
+
encommon/config/test/__init__.py,sha256=i0JAeRcM-0YH2StGfwpaDbZV9dVribNSgFDcYcPPay8,313
|
13
|
+
encommon/config/test/test_common.py,sha256=K9KiAfbMBXaoYErW10X1AigFs8wNNNOxKG8QV6IYJdA,1069
|
14
|
+
encommon/config/test/test_config.py,sha256=j8RT1RaVNHcuoYDcatUktYPbZBDpCgZuxYnjhUuEpDQ,2329
|
15
|
+
encommon/config/test/test_files.py,sha256=kunksn9Y63YYwyjVL-21Vmh2PCCTVm8ZVzGfe9RjA0U,2230
|
16
|
+
encommon/config/test/test_logger.py,sha256=wjvCZKLD656SSEIlVbbnBEt9UJvQXzC8XINcnDKvNlg,5135
|
17
|
+
encommon/config/test/test_paths.py,sha256=vABtT3DH9P2HihAOeKVNFFBe9s2Y9yyIZ-qoytwcWnE,2568
|
18
|
+
encommon/crypts/__init__.py,sha256=UsGEitz8rWa7DQF3iAxEbTUAbdiEnE87LSuRs4OBeAQ,371
|
19
|
+
encommon/crypts/crypts.py,sha256=fCYEOlq5vp34L9yPT-oMhvI-8o6FRoPViM7aZShB1_Y,3540
|
20
|
+
encommon/crypts/hashes.py,sha256=bpQf2-Ma5SdMaEWP2nL1_9rtEQmTE0XTdDvSD-fQ9Mk,3075
|
21
|
+
encommon/crypts/params.py,sha256=7hh7a7VtsQNqcZHeSkQI_V4JLfoe0D-JyqrIvtoq86c,590
|
22
|
+
encommon/crypts/test/__init__.py,sha256=PjrnBYT0efyvbaGeNx94dm3tP3EVHUHSVs-VGeLEv5g,218
|
23
|
+
encommon/crypts/test/test_crypts.py,sha256=qAyWKehHNJVNpv085iRi6A7wNf5U9tSAir03dtNCJK0,2655
|
24
|
+
encommon/crypts/test/test_hashes.py,sha256=PBKafFK1ruDkgVdGuyjAdgr4xPNxXHVNW7bFeUDyUFc,1129
|
25
|
+
encommon/times/__init__.py,sha256=Gyi34zy6po35P2sNvbwnsOQg4kU6KOodfygLhRdCEgU,638
|
26
|
+
encommon/times/common.py,sha256=T-Bt8P1EBn-TOEF0Bd0kUJMr6qEFCnHOLiYqgJE9mqk,3635
|
27
|
+
encommon/times/duration.py,sha256=sLRk4D7lOHAC6wmI0uMEtIAt1j52OpAEP-vMJ0mam5E,10033
|
28
|
+
encommon/times/parse.py,sha256=FIWmho7gU-NjY8Si07VI_WVirEJgxQvdLXpIq0f3LCc,6153
|
29
|
+
encommon/times/timers.py,sha256=PWrxD9EZ-jZBDcuLTv-VAvE85X4EoCgY1IVaiFrpI2k,6663
|
30
|
+
encommon/times/times.py,sha256=xuPtFR2Gkr_AFPfspqGq3cU67rfZr0xvKcQvlw2Q-xQ,9696
|
31
|
+
encommon/times/window.py,sha256=CA9zIdi0ad-WiC03zG_T_WilWoEwATISVBOF1Jqtf4o,7975
|
32
|
+
encommon/times/test/__init__.py,sha256=PjrnBYT0efyvbaGeNx94dm3tP3EVHUHSVs-VGeLEv5g,218
|
33
|
+
encommon/times/test/test_common.py,sha256=r0vwJ-2SiwVOvSyEB0JkpWfsAeLvSCEhuLaYE1rk0VY,2059
|
34
|
+
encommon/times/test/test_duration.py,sha256=38BIpnK2dU0ZMhpxujNjc8WM0DAmPVi0IgQ9IzMW0Ss,4161
|
35
|
+
encommon/times/test/test_parse.py,sha256=iIKanoqqQMxpXVxo9HNwY7oscQB1HzXU9QId0puoGd4,4055
|
36
|
+
encommon/times/test/test_timers.py,sha256=VUlGg9Eu2Q2bMJt4355fMSWCShgIN2HLuFf2I8Rnqd0,3075
|
37
|
+
encommon/times/test/test_times.py,sha256=fDW3JroUM-tySqsvq25htbW2p1cYBNZr1W7E39sZUSE,1691
|
38
|
+
encommon/times/test/test_window.py,sha256=EBX6zYNBSgpZP5AvT4uCWvecQwv-2VRQHJ-etVjSfSw,5411
|
39
|
+
encommon/types/__init__.py,sha256=l2WKtDs6uC9I3dIGnrzJvz-4JLEETUJOfT509XyMQWs,420
|
40
|
+
encommon/types/dicts.py,sha256=lC2FmPzMEj9L73jUjf3o6OVQ-LqK_3gp5nBwYibdGfo,2265
|
41
|
+
encommon/types/empty.py,sha256=n5y5maXkcM3xNYNYGK6iqvk98ivQSeguaedwc0HoMv4,2739
|
42
|
+
encommon/types/strings.py,sha256=7HWZxTmQXIOxk1-hM4Ex4Jp2veZNZbj-8YmYXFOPFJ0,632
|
43
|
+
encommon/types/test/__init__.py,sha256=PjrnBYT0efyvbaGeNx94dm3tP3EVHUHSVs-VGeLEv5g,218
|
44
|
+
encommon/types/test/test_dicts.py,sha256=jOXE2NTfZg2dtmgR2Hv9uaAI90kKT-91bX6jWAu-5Xs,2678
|
45
|
+
encommon/types/test/test_empty.py,sha256=2VZReyiaQWslt7-JtPLhpqqhzMfXxQwfiaDHN1WAvXE,971
|
46
|
+
encommon/types/test/test_strings.py,sha256=gYq9B-ekRKw_j6pZiHJiQnkXHiH5fwK4CDdGnpqdtAs,406
|
47
|
+
encommon/utils/__init__.py,sha256=FJzSgfXddDXrxnencV6W4MArr3xQPEcfwrPVtMqwDHE,927
|
48
|
+
encommon/utils/common.py,sha256=N5CAo5rHIIvXzmOWwbO7R4xTYnGDqB9OYXGh0ignc_g,1355
|
49
|
+
encommon/utils/match.py,sha256=OG8lE78SpzE8hgbgVwIYC0yLYwchrdGA68twCUyglhA,2463
|
50
|
+
encommon/utils/paths.py,sha256=jdkXsP8y1jr-X-rqYC6Hexz3gRd9VbWtBalG-nffNyM,3545
|
51
|
+
encommon/utils/sample.py,sha256=jgamO4LTcIrcy7UNyoftLnTxDvAcz19o-zcja9WjaEQ,3230
|
52
|
+
encommon/utils/stdout.py,sha256=HAeN22KFd8nOYuH98bFPvJyAc1KGhdGydmITnf-DyG0,7531
|
53
|
+
encommon/utils/test/__init__.py,sha256=PjrnBYT0efyvbaGeNx94dm3tP3EVHUHSVs-VGeLEv5g,218
|
54
|
+
encommon/utils/test/test_common.py,sha256=BJtXkyzax1DmuHSRJvzaQ3bY7Iec06KMjDggUx2Gh_Y,681
|
55
|
+
encommon/utils/test/test_match.py,sha256=QagKpTFdRo23-Y55fSaJrSMpt5jIebScKbz0h8tivrI,1124
|
56
|
+
encommon/utils/test/test_paths.py,sha256=o7AF73jz09Mny21IsRG8vbB20mDH_oVmQFuxoSCLiOc,1919
|
57
|
+
encommon/utils/test/test_sample.py,sha256=sHAeWOL1mchTGYGQaFK_A3Z28tThuULumm9kQebnIdk,1710
|
58
|
+
encommon/utils/test/test_stdout.py,sha256=TA7xQuFoPZUYW2l00e04MGp4P9gHkkVxVflvPlhpQXg,4878
|
59
|
+
encommon-0.8.0.dist-info/LICENSE,sha256=otnXKCtMjPlbHs0wgZ_BWULrp3g_2dWQJ6icRk9nkgg,1071
|
60
|
+
encommon-0.8.0.dist-info/METADATA,sha256=Ne5b6fXbjvoO3QUm00_5zugq4ApFY5WnfjB9HoliCCs,2671
|
61
|
+
encommon-0.8.0.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
62
|
+
encommon-0.8.0.dist-info/top_level.txt,sha256=bP8q7-5tLDNm-3XPlqn_bDENfYNug5801H_xfz3BEAM,9
|
63
|
+
encommon-0.8.0.dist-info/RECORD,,
|