encommon 0.5.0__py3-none-any.whl → 0.7.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 +2 -2
- encommon/conftest.py +2 -1
- encommon/times/test/test_timers.py +46 -3
- encommon/times/timers.py +172 -29
- encommon/utils/__init__.py +2 -0
- encommon/utils/stdout.py +212 -0
- encommon/utils/test/test_stdout.py +151 -0
- encommon/version.txt +1 -1
- {encommon-0.5.0.dist-info → encommon-0.7.0.dist-info}/METADATA +1 -1
- {encommon-0.5.0.dist-info → encommon-0.7.0.dist-info}/RECORD +13 -13
- {encommon-0.5.0.dist-info → encommon-0.7.0.dist-info}/LICENSE +0 -0
- {encommon-0.5.0.dist-info → encommon-0.7.0.dist-info}/WHEEL +0 -0
- {encommon-0.5.0.dist-info → encommon-0.7.0.dist-info}/top_level.txt +0 -0
encommon/config/config.py
CHANGED
@@ -155,9 +155,9 @@ class Config:
|
|
155
155
|
self,
|
156
156
|
) -> Params:
|
157
157
|
"""
|
158
|
-
Return the
|
158
|
+
Return the Pydantic model containing the configuration.
|
159
159
|
|
160
|
-
:returns:
|
160
|
+
:returns: Pydantic model containing the configuration.
|
161
161
|
"""
|
162
162
|
|
163
163
|
if self.__params is not None:
|
encommon/conftest.py
CHANGED
@@ -21,6 +21,7 @@ def config_path(
|
|
21
21
|
Construct the directory and files needed for the tests.
|
22
22
|
|
23
23
|
:param tmp_path: pytest object for temporal filesystem.
|
24
|
+
:returns: New resolved filesystem path object instance.
|
24
25
|
"""
|
25
26
|
|
26
27
|
|
@@ -40,4 +41,4 @@ def config_path(
|
|
40
41
|
.write_text('name: Tony Stark'))
|
41
42
|
|
42
43
|
|
43
|
-
return tmp_path
|
44
|
+
return tmp_path.resolve()
|
@@ -7,6 +7,7 @@ is permitted, for more information consult the project license file.
|
|
7
7
|
|
8
8
|
|
9
9
|
|
10
|
+
from pathlib import Path
|
10
11
|
from time import sleep
|
11
12
|
|
12
13
|
from pytest import raises
|
@@ -25,8 +26,10 @@ def test_Timers() -> None:
|
|
25
26
|
attrs = list(timers.__dict__)
|
26
27
|
|
27
28
|
assert attrs == [
|
28
|
-
'
|
29
|
-
'
|
29
|
+
'_Timers__timers',
|
30
|
+
'_Timers__cache_file',
|
31
|
+
'_Timers__cache_name',
|
32
|
+
'_Timers__cache_dict']
|
30
33
|
|
31
34
|
|
32
35
|
assert repr(timers).startswith(
|
@@ -36,7 +39,11 @@ def test_Timers() -> None:
|
|
36
39
|
'<encommon.times.timers.Timers')
|
37
40
|
|
38
41
|
|
39
|
-
assert timers.
|
42
|
+
assert timers.timers == {'one': 1}
|
43
|
+
assert timers.cache_file is not None
|
44
|
+
assert len(timers.cache_dict) == 1
|
45
|
+
assert timers.cache_name is not None
|
46
|
+
|
40
47
|
|
41
48
|
assert not timers.ready('one')
|
42
49
|
sleep(1.1)
|
@@ -50,6 +57,42 @@ def test_Timers() -> None:
|
|
50
57
|
|
51
58
|
|
52
59
|
|
60
|
+
def test_Timers_cache(
|
61
|
+
tmp_path: Path,
|
62
|
+
) -> None:
|
63
|
+
"""
|
64
|
+
Perform various tests associated with relevant routines.
|
65
|
+
|
66
|
+
:param tmp_path: pytest object for temporal filesystem.
|
67
|
+
"""
|
68
|
+
|
69
|
+
cache_file = (
|
70
|
+
f'{tmp_path}/timers.db')
|
71
|
+
|
72
|
+
timers1 = Timers(
|
73
|
+
timers={'one': 1},
|
74
|
+
cache_file=cache_file)
|
75
|
+
|
76
|
+
assert not timers1.ready('one')
|
77
|
+
|
78
|
+
sleep(0.75)
|
79
|
+
|
80
|
+
timers2 = Timers(
|
81
|
+
timers={'one': 1},
|
82
|
+
cache_file=cache_file)
|
83
|
+
|
84
|
+
assert not timers1.ready('one')
|
85
|
+
assert not timers2.ready('one')
|
86
|
+
|
87
|
+
sleep(0.25)
|
88
|
+
|
89
|
+
timers2.load_cache()
|
90
|
+
|
91
|
+
assert timers1.ready('one')
|
92
|
+
assert timers2.ready('one')
|
93
|
+
|
94
|
+
|
95
|
+
|
53
96
|
def test_Timers_raises() -> None:
|
54
97
|
"""
|
55
98
|
Perform various tests associated with relevant routines.
|
encommon/times/timers.py
CHANGED
@@ -7,59 +7,155 @@ is permitted, for more information consult the project license file.
|
|
7
7
|
|
8
8
|
|
9
9
|
|
10
|
+
from sqlite3 import connect as SQLite
|
10
11
|
from typing import Optional
|
12
|
+
from typing import TYPE_CHECKING
|
11
13
|
|
12
14
|
from .common import NUMERIC
|
13
15
|
from .common import PARSABLE
|
14
16
|
from .times import Times
|
15
17
|
|
18
|
+
if TYPE_CHECKING:
|
19
|
+
from sqlite3 import Connection
|
20
|
+
|
21
|
+
|
22
|
+
TABLE = (
|
23
|
+
"""
|
24
|
+
create table
|
25
|
+
if not exists
|
26
|
+
{0} (
|
27
|
+
"unique" text not null,
|
28
|
+
"update" text not null,
|
29
|
+
primary key ("unique"));
|
30
|
+
""") # noqa: LIT003
|
31
|
+
|
16
32
|
|
17
33
|
|
18
34
|
class Timers:
|
19
35
|
"""
|
20
36
|
Track timers on unique key and determine when to proceed.
|
21
37
|
|
38
|
+
.. warning::
|
39
|
+
This class will use an in-memory database for cache,
|
40
|
+
unless a cache file is explicity defined.
|
41
|
+
|
22
42
|
.. testsetup::
|
23
43
|
>>> from time import sleep
|
24
44
|
|
25
45
|
Example
|
26
46
|
-------
|
27
|
-
>>>
|
28
|
-
>>> timers
|
29
|
-
>>> timers.ready('test')
|
47
|
+
>>> timers = Timers({'one': 1})
|
48
|
+
>>> timers.ready('one')
|
30
49
|
False
|
31
50
|
>>> sleep(1)
|
32
|
-
>>> timers.ready('
|
51
|
+
>>> timers.ready('one')
|
33
52
|
True
|
34
53
|
|
35
|
-
:param
|
54
|
+
:param timers: Seconds that are used for each of timers.
|
55
|
+
:param cache_file: Optional path to SQLite database for
|
56
|
+
cache. This will allow for use between executions.
|
57
|
+
:param cache_name: Optional override default table name.
|
36
58
|
"""
|
37
59
|
|
38
|
-
|
39
|
-
|
60
|
+
__timers: dict[str, float]
|
61
|
+
__cache_file: 'Connection'
|
62
|
+
__cache_name: str
|
63
|
+
__cache_dict: dict[str, Times]
|
40
64
|
|
41
65
|
|
42
66
|
def __init__(
|
43
67
|
self,
|
44
|
-
|
68
|
+
timers: Optional[dict[str, NUMERIC]] = None,
|
69
|
+
cache_file: str = ':memory:',
|
70
|
+
cache_name: str = 'encommon_timers',
|
45
71
|
) -> None:
|
46
72
|
"""
|
47
73
|
Initialize instance for class using provided parameters.
|
48
74
|
"""
|
49
75
|
|
50
|
-
|
76
|
+
timers = timers or {}
|
51
77
|
|
52
|
-
|
78
|
+
|
79
|
+
self.__timers = {
|
53
80
|
k: float(v)
|
54
|
-
for k, v in
|
81
|
+
for k, v in
|
82
|
+
timers.items()}
|
83
|
+
|
84
|
+
|
85
|
+
cached = SQLite(cache_file)
|
86
|
+
|
87
|
+
cached.execute(
|
88
|
+
TABLE.format(cache_name))
|
55
89
|
|
56
|
-
|
90
|
+
cached.commit()
|
91
|
+
|
92
|
+
self.__cache_file = cached
|
93
|
+
self.__cache_name = cache_name
|
94
|
+
|
95
|
+
|
96
|
+
self.__cache_dict = {
|
57
97
|
x: Times()
|
58
|
-
for x in
|
98
|
+
for x in
|
99
|
+
self.__timers}
|
100
|
+
|
101
|
+
|
102
|
+
self.load_cache()
|
103
|
+
self.save_cache()
|
104
|
+
|
105
|
+
|
106
|
+
def load_cache(
|
107
|
+
self,
|
108
|
+
) -> None:
|
109
|
+
"""
|
110
|
+
Load the timers cache from the database into attribute.
|
111
|
+
"""
|
112
|
+
|
113
|
+
cached = self.__cache_file
|
114
|
+
table = self.__cache_name
|
115
|
+
cachem = self.__cache_dict
|
116
|
+
|
117
|
+
cursor = cached.execute(
|
118
|
+
f'select * from {table}'
|
119
|
+
' order by "unique" asc')
|
120
|
+
|
121
|
+
records = cursor.fetchall()
|
122
|
+
|
123
|
+
for record in records:
|
124
|
+
|
125
|
+
unique = record[0]
|
126
|
+
update = record[1]
|
127
|
+
|
128
|
+
times = Times(update)
|
129
|
+
|
130
|
+
cachem[unique] = times
|
131
|
+
|
132
|
+
|
133
|
+
def save_cache(
|
134
|
+
self,
|
135
|
+
) -> None:
|
136
|
+
"""
|
137
|
+
Save the timers cache from the attribute into database.
|
138
|
+
"""
|
139
|
+
|
140
|
+
cached = self.__cache_file
|
141
|
+
table = self.__cache_name
|
142
|
+
cachem = self.__cache_dict
|
143
|
+
|
144
|
+
insert = [
|
145
|
+
(k, str(v)) for k, v
|
146
|
+
in cachem.items()]
|
147
|
+
|
148
|
+
cached.executemany(
|
149
|
+
(f'replace into {table}'
|
150
|
+
' ("unique", "update")'
|
151
|
+
' values (?, ?)'),
|
152
|
+
tuple(insert))
|
153
|
+
|
154
|
+
cached.commit()
|
59
155
|
|
60
156
|
|
61
157
|
@property
|
62
|
-
def
|
158
|
+
def timers(
|
63
159
|
self,
|
64
160
|
) -> dict[str, float]:
|
65
161
|
"""
|
@@ -68,7 +164,46 @@ class Timers:
|
|
68
164
|
:returns: Property for attribute from the class instance.
|
69
165
|
"""
|
70
166
|
|
71
|
-
return dict(self.
|
167
|
+
return dict(self.__timers)
|
168
|
+
|
169
|
+
|
170
|
+
@property
|
171
|
+
def cache_file(
|
172
|
+
self,
|
173
|
+
) -> 'Connection':
|
174
|
+
"""
|
175
|
+
Return the property for attribute from the class instance.
|
176
|
+
|
177
|
+
:returns: Property for attribute from the class instance.
|
178
|
+
"""
|
179
|
+
|
180
|
+
return self.__cache_file
|
181
|
+
|
182
|
+
|
183
|
+
@property
|
184
|
+
def cache_dict(
|
185
|
+
self,
|
186
|
+
) -> dict[str, Times]:
|
187
|
+
"""
|
188
|
+
Return the property for attribute from the class instance.
|
189
|
+
|
190
|
+
:returns: Property for attribute from the class instance.
|
191
|
+
"""
|
192
|
+
|
193
|
+
return dict(self.__cache_dict)
|
194
|
+
|
195
|
+
|
196
|
+
@property
|
197
|
+
def cache_name(
|
198
|
+
self,
|
199
|
+
) -> str:
|
200
|
+
"""
|
201
|
+
Return the property for attribute from the class instance.
|
202
|
+
|
203
|
+
:returns: Property for attribute from the class instance.
|
204
|
+
"""
|
205
|
+
|
206
|
+
return self.__cache_name
|
72
207
|
|
73
208
|
|
74
209
|
def ready(
|
@@ -79,20 +214,24 @@ class Timers:
|
|
79
214
|
"""
|
80
215
|
Determine whether or not the appropriate time has passed.
|
81
216
|
|
217
|
+
.. note::
|
218
|
+
For performance reasons, this method will not notice
|
219
|
+
changes within the database unless refreshed first.
|
220
|
+
|
82
221
|
:param unique: Unique identifier for the timer in mapping.
|
83
222
|
:param update: Determines whether or not time is updated.
|
84
223
|
"""
|
85
224
|
|
86
|
-
|
87
|
-
|
225
|
+
timers = self.__timers
|
226
|
+
caches = self.__cache_dict
|
88
227
|
|
89
|
-
if unique not in
|
228
|
+
if unique not in caches:
|
90
229
|
raise ValueError('unique')
|
91
230
|
|
92
|
-
|
93
|
-
|
231
|
+
cache = caches[unique]
|
232
|
+
timer = timers[unique]
|
94
233
|
|
95
|
-
ready =
|
234
|
+
ready = cache.elapsed >= timer
|
96
235
|
|
97
236
|
if ready and update:
|
98
237
|
self.update(unique)
|
@@ -112,12 +251,14 @@ class Timers:
|
|
112
251
|
:param started: Override the start time for timer value.
|
113
252
|
"""
|
114
253
|
|
115
|
-
|
254
|
+
caches = self.__cache_dict
|
116
255
|
|
117
|
-
if unique not in
|
256
|
+
if unique not in caches:
|
118
257
|
raise ValueError('unique')
|
119
258
|
|
120
|
-
|
259
|
+
caches[unique] = Times(started)
|
260
|
+
|
261
|
+
self.save_cache()
|
121
262
|
|
122
263
|
|
123
264
|
def create(
|
@@ -134,11 +275,13 @@ class Timers:
|
|
134
275
|
:param started: Determines when the time starts for timer.
|
135
276
|
"""
|
136
277
|
|
137
|
-
|
138
|
-
|
278
|
+
timers = self.__timers
|
279
|
+
caches = self.__cache_dict
|
139
280
|
|
140
|
-
if unique in
|
281
|
+
if unique in caches:
|
141
282
|
raise ValueError('unique')
|
142
283
|
|
143
|
-
|
144
|
-
|
284
|
+
timers[unique] = float(minimum)
|
285
|
+
caches[unique] = Times(started)
|
286
|
+
|
287
|
+
self.save_cache()
|
encommon/utils/__init__.py
CHANGED
@@ -14,6 +14,7 @@ from .paths import resolve_paths
|
|
14
14
|
from .paths import stats_path
|
15
15
|
from .sample import load_sample
|
16
16
|
from .sample import prep_sample
|
17
|
+
from .stdout import array_ansi
|
17
18
|
from .stdout import kvpair_ansi
|
18
19
|
from .stdout import make_ansi
|
19
20
|
from .stdout import print_ansi
|
@@ -22,6 +23,7 @@ from .stdout import strip_ansi
|
|
22
23
|
|
23
24
|
|
24
25
|
__all__ = [
|
26
|
+
'array_ansi',
|
25
27
|
'fuzz_match',
|
26
28
|
'kvpair_ansi',
|
27
29
|
'load_sample',
|
encommon/utils/stdout.py
CHANGED
@@ -7,11 +7,18 @@ is permitted, for more information consult the project license file.
|
|
7
7
|
|
8
8
|
|
9
9
|
|
10
|
+
from dataclasses import dataclass
|
10
11
|
from re import compile
|
11
12
|
from re import sub as re_sub
|
12
13
|
from sys import stdout
|
13
14
|
from typing import Any
|
14
15
|
from typing import Literal
|
16
|
+
from typing import Optional
|
17
|
+
from typing import Union
|
18
|
+
|
19
|
+
from encommon.times import Duration
|
20
|
+
from encommon.times import Times
|
21
|
+
from encommon.types import Empty
|
15
22
|
|
16
23
|
from .common import JOINABLE
|
17
24
|
|
@@ -20,6 +27,40 @@ from .common import JOINABLE
|
|
20
27
|
ANSICODE = compile(
|
21
28
|
r'\x1b\[[^A-Za-z]*[A-Za-z]')
|
22
29
|
|
30
|
+
ANSIARRAL = Union[
|
31
|
+
list[Any],
|
32
|
+
tuple[Any, ...],
|
33
|
+
set[Any]]
|
34
|
+
|
35
|
+
ANSIARRAD = dict[Any, Any]
|
36
|
+
|
37
|
+
ANSIARRAY = Union[
|
38
|
+
ANSIARRAL,
|
39
|
+
ANSIARRAD]
|
40
|
+
|
41
|
+
|
42
|
+
|
43
|
+
@dataclass(frozen=True)
|
44
|
+
class ArrayColors:
|
45
|
+
"""
|
46
|
+
Colors used to colorize the provided array like object.
|
47
|
+
"""
|
48
|
+
|
49
|
+
label: int = 37
|
50
|
+
key: int = 97
|
51
|
+
|
52
|
+
bool: int = 93
|
53
|
+
none: int = 33
|
54
|
+
str: int = 92
|
55
|
+
num: int = 93
|
56
|
+
|
57
|
+
times: int = 96
|
58
|
+
empty: int = 36
|
59
|
+
other: int = 91
|
60
|
+
|
61
|
+
colon: int = 37
|
62
|
+
hyphen: int = 37
|
63
|
+
|
23
64
|
|
24
65
|
|
25
66
|
def print_ansi(
|
@@ -121,3 +162,174 @@ def strip_ansi(
|
|
121
162
|
""" # noqa: D301 LIT102
|
122
163
|
|
123
164
|
return re_sub(ANSICODE, '', string)
|
165
|
+
|
166
|
+
|
167
|
+
|
168
|
+
def array_ansi( # noqa: CFQ001, CFQ004
|
169
|
+
source: ANSIARRAY,
|
170
|
+
*,
|
171
|
+
indent: int = 0,
|
172
|
+
colors: ArrayColors = ArrayColors(),
|
173
|
+
) -> str:
|
174
|
+
"""
|
175
|
+
Print the ANSI colorized iterable to the standard output.
|
176
|
+
|
177
|
+
.. note::
|
178
|
+
This massive function should be refactored, possibly
|
179
|
+
into a class with methods where there are functions.
|
180
|
+
|
181
|
+
:param source: Value in supported and iterable formats.
|
182
|
+
:param indent: How many levels for initial indentation.
|
183
|
+
:param colors: Determine colors used with different types.
|
184
|
+
:returns: ANSI colorized string using inline directives.
|
185
|
+
"""
|
186
|
+
|
187
|
+
output: list[str] = []
|
188
|
+
|
189
|
+
repeat = f'<c{colors.other}>REPEAT<c0>'
|
190
|
+
|
191
|
+
|
192
|
+
def _append(
|
193
|
+
prefix: str,
|
194
|
+
value: Any, # noqa: ANN401
|
195
|
+
indent: int,
|
196
|
+
refers: set[int],
|
197
|
+
) -> None:
|
198
|
+
|
199
|
+
if id(value) in refers:
|
200
|
+
return output.append(
|
201
|
+
f'{prefix} {repeat}')
|
202
|
+
|
203
|
+
refers.add(id(value))
|
204
|
+
|
205
|
+
|
206
|
+
types = {
|
207
|
+
'dict': dict,
|
208
|
+
'list': list,
|
209
|
+
'tuple': tuple,
|
210
|
+
'set': set}
|
211
|
+
|
212
|
+
for name, _type in types.items():
|
213
|
+
|
214
|
+
if not isinstance(value, _type):
|
215
|
+
continue
|
216
|
+
|
217
|
+
output.append(
|
218
|
+
f'{prefix} '
|
219
|
+
f'<c{colors.label}>{name}<c0>')
|
220
|
+
|
221
|
+
return _process(
|
222
|
+
source=value,
|
223
|
+
indent=indent + 2,
|
224
|
+
refers=refers)
|
225
|
+
|
226
|
+
|
227
|
+
value = _concrete(value)
|
228
|
+
|
229
|
+
output.append(
|
230
|
+
f'{prefix} {value}')
|
231
|
+
|
232
|
+
|
233
|
+
def _concrete(
|
234
|
+
source: Any, # noqa: ANN401
|
235
|
+
) -> str:
|
236
|
+
|
237
|
+
color = colors.other
|
238
|
+
|
239
|
+
if isinstance(source, bool):
|
240
|
+
color = colors.bool
|
241
|
+
|
242
|
+
if isinstance(source, int | float):
|
243
|
+
color = colors.num
|
244
|
+
|
245
|
+
elif isinstance(source, str):
|
246
|
+
color = colors.str
|
247
|
+
|
248
|
+
elif source is None:
|
249
|
+
color = colors.none
|
250
|
+
|
251
|
+
elif isinstance(source, Duration):
|
252
|
+
color = colors.times
|
253
|
+
|
254
|
+
elif isinstance(source, Times):
|
255
|
+
color = colors.times
|
256
|
+
|
257
|
+
elif source is Empty:
|
258
|
+
color = colors.empty
|
259
|
+
|
260
|
+
string = f'<c{color}>{source}<c0>'
|
261
|
+
|
262
|
+
if isinstance(source, str):
|
263
|
+
string = f"'{string}'"
|
264
|
+
|
265
|
+
return string
|
266
|
+
|
267
|
+
|
268
|
+
def _dict(
|
269
|
+
source: ANSIARRAD,
|
270
|
+
indent: int,
|
271
|
+
refers: Optional[set[int]] = None,
|
272
|
+
) -> None:
|
273
|
+
|
274
|
+
assert isinstance(source, dict)
|
275
|
+
|
276
|
+
for key, value in source.items():
|
277
|
+
|
278
|
+
prefix = (
|
279
|
+
f'{" " * indent}'
|
280
|
+
f'<c{colors.key}>{key}'
|
281
|
+
f'<c{colors.colon}>:<c0>')
|
282
|
+
|
283
|
+
_append(
|
284
|
+
prefix, value, indent,
|
285
|
+
refers=refers or set())
|
286
|
+
|
287
|
+
|
288
|
+
def _list(
|
289
|
+
source: ANSIARRAL,
|
290
|
+
indent: int,
|
291
|
+
refers: Optional[set[int]] = None,
|
292
|
+
) -> None:
|
293
|
+
|
294
|
+
assert isinstance(
|
295
|
+
source, (list, tuple, set))
|
296
|
+
|
297
|
+
for value in source:
|
298
|
+
|
299
|
+
prefix = (
|
300
|
+
f'{" " * indent}'
|
301
|
+
f'<c{colors.hyphen}>-<c0>')
|
302
|
+
|
303
|
+
_append(
|
304
|
+
prefix, value, indent,
|
305
|
+
refers=refers or set())
|
306
|
+
|
307
|
+
|
308
|
+
def _process(
|
309
|
+
source: ANSIARRAD | ANSIARRAL,
|
310
|
+
**kwargs: Any,
|
311
|
+
) -> None:
|
312
|
+
|
313
|
+
if isinstance(source, dict):
|
314
|
+
return _dict(source, **kwargs)
|
315
|
+
|
316
|
+
return _list(source, **kwargs)
|
317
|
+
|
318
|
+
|
319
|
+
if isinstance(source, dict):
|
320
|
+
_dict(source, indent)
|
321
|
+
|
322
|
+
elif isinstance(source, list):
|
323
|
+
_list(source, indent)
|
324
|
+
|
325
|
+
elif isinstance(source, tuple):
|
326
|
+
_list(source, indent)
|
327
|
+
|
328
|
+
elif isinstance(source, set):
|
329
|
+
_list(source, indent)
|
330
|
+
|
331
|
+
|
332
|
+
_output = [
|
333
|
+
make_ansi(x) for x in output]
|
334
|
+
|
335
|
+
return '\n'.join(_output)
|
@@ -9,10 +9,15 @@ is permitted, for more information consult the project license file.
|
|
9
9
|
|
10
10
|
from _pytest.capture import CaptureFixture
|
11
11
|
|
12
|
+
from ..stdout import array_ansi
|
12
13
|
from ..stdout import kvpair_ansi
|
13
14
|
from ..stdout import make_ansi
|
14
15
|
from ..stdout import print_ansi
|
15
16
|
from ..stdout import strip_ansi
|
17
|
+
from ...times import Duration
|
18
|
+
from ...times import Times
|
19
|
+
from ...times.common import UNIXMPOCH
|
20
|
+
from ...types import Empty
|
16
21
|
|
17
22
|
|
18
23
|
|
@@ -78,3 +83,149 @@ def test_strip_ansi() -> None:
|
|
78
83
|
output = '\x1b[0;31mtest\x1b[0;0m'
|
79
84
|
|
80
85
|
assert strip_ansi(output) == 'test'
|
86
|
+
|
87
|
+
|
88
|
+
|
89
|
+
def test_array_ansi() -> None: # noqa: CFQ001
|
90
|
+
"""
|
91
|
+
Perform various tests associated with relevant routines.
|
92
|
+
"""
|
93
|
+
|
94
|
+
simple = {
|
95
|
+
'str': 'value',
|
96
|
+
'list': [1, 2],
|
97
|
+
'bool': False}
|
98
|
+
|
99
|
+
repeat = {
|
100
|
+
'dict': simple | {
|
101
|
+
'dict': simple}}
|
102
|
+
|
103
|
+
source = {
|
104
|
+
'str': 'value',
|
105
|
+
'int': 1,
|
106
|
+
'float': 1.0,
|
107
|
+
'complex': complex(3, 1),
|
108
|
+
'list': [simple],
|
109
|
+
'tuple': (simple,),
|
110
|
+
'range': range(1, 3),
|
111
|
+
'dict1': simple,
|
112
|
+
'dict2': simple,
|
113
|
+
'dict3': simple,
|
114
|
+
'set': {1, 2, 3},
|
115
|
+
'frozenset': {1, 2, 3},
|
116
|
+
'bool': True,
|
117
|
+
'none': None,
|
118
|
+
'_private': None,
|
119
|
+
'repeat': repeat,
|
120
|
+
'Empty': Empty,
|
121
|
+
'Duration': Duration(190802),
|
122
|
+
'Times': Times(0)}
|
123
|
+
|
124
|
+
|
125
|
+
output = strip_ansi(
|
126
|
+
array_ansi(simple))
|
127
|
+
|
128
|
+
assert output == (
|
129
|
+
"str: 'value'\n"
|
130
|
+
'list: list\n'
|
131
|
+
' - 1\n'
|
132
|
+
' - 2\n'
|
133
|
+
'bool: False')
|
134
|
+
|
135
|
+
|
136
|
+
output = strip_ansi(
|
137
|
+
array_ansi([simple]))
|
138
|
+
|
139
|
+
assert output == (
|
140
|
+
'- dict\n'
|
141
|
+
" str: 'value'\n"
|
142
|
+
' list: list\n'
|
143
|
+
' - 1\n'
|
144
|
+
' - 2\n'
|
145
|
+
' bool: False')
|
146
|
+
|
147
|
+
|
148
|
+
output = strip_ansi(
|
149
|
+
array_ansi((1, 2, 3)))
|
150
|
+
|
151
|
+
assert output == (
|
152
|
+
'- 1\n'
|
153
|
+
'- 2\n'
|
154
|
+
'- 3')
|
155
|
+
|
156
|
+
|
157
|
+
output = strip_ansi(
|
158
|
+
array_ansi({1, 2, 3}))
|
159
|
+
|
160
|
+
assert output == (
|
161
|
+
'- 1\n'
|
162
|
+
'- 2\n'
|
163
|
+
'- 3')
|
164
|
+
|
165
|
+
|
166
|
+
output = strip_ansi(
|
167
|
+
array_ansi(source))
|
168
|
+
|
169
|
+
assert output == (
|
170
|
+
"str: 'value'\n"
|
171
|
+
'int: 1\n'
|
172
|
+
'float: 1.0\n'
|
173
|
+
'complex: (3+1j)\n'
|
174
|
+
'list: list\n'
|
175
|
+
' - dict\n'
|
176
|
+
" str: 'value'\n"
|
177
|
+
' list: list\n'
|
178
|
+
' - 1\n'
|
179
|
+
' - 2\n'
|
180
|
+
' bool: False\n'
|
181
|
+
'tuple: tuple\n'
|
182
|
+
' - dict\n'
|
183
|
+
" str: 'value'\n"
|
184
|
+
' list: list\n'
|
185
|
+
' - 1\n'
|
186
|
+
' - 2\n'
|
187
|
+
' bool: False\n'
|
188
|
+
'range: range(1, 3)\n'
|
189
|
+
'dict1: dict\n'
|
190
|
+
" str: 'value'\n"
|
191
|
+
' list: list\n'
|
192
|
+
' - 1\n'
|
193
|
+
' - 2\n'
|
194
|
+
' bool: False\n'
|
195
|
+
'dict2: dict\n'
|
196
|
+
" str: 'value'\n"
|
197
|
+
' list: list\n'
|
198
|
+
' - 1\n'
|
199
|
+
' - 2\n'
|
200
|
+
' bool: False\n'
|
201
|
+
'dict3: dict\n'
|
202
|
+
" str: 'value'\n"
|
203
|
+
' list: list\n'
|
204
|
+
' - 1\n'
|
205
|
+
' - 2\n'
|
206
|
+
' bool: False\n'
|
207
|
+
'set: set\n'
|
208
|
+
' - 1\n'
|
209
|
+
' - 2\n'
|
210
|
+
' - 3\n'
|
211
|
+
'frozenset: set\n'
|
212
|
+
' - 1\n'
|
213
|
+
' - 2\n'
|
214
|
+
' - 3\n'
|
215
|
+
'bool: True\n'
|
216
|
+
'none: None\n'
|
217
|
+
'_private: None\n'
|
218
|
+
'repeat: dict\n'
|
219
|
+
' dict: dict\n'
|
220
|
+
" str: 'value'\n"
|
221
|
+
' list: list\n'
|
222
|
+
' - 1\n'
|
223
|
+
' - 2\n'
|
224
|
+
' bool: False\n'
|
225
|
+
' dict: dict\n'
|
226
|
+
' str: REPEAT\n'
|
227
|
+
' list: REPEAT\n'
|
228
|
+
' bool: REPEAT\n'
|
229
|
+
'Empty: Empty\n'
|
230
|
+
'Duration: 2d5h\n'
|
231
|
+
f'Times: {UNIXMPOCH}')
|
encommon/version.txt
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.7.0
|
@@ -1,10 +1,10 @@
|
|
1
1
|
encommon/__init__.py,sha256=VoXUcphq-gcXCraaU47EtXBftF6UVuQPMGr0fuCTt9A,525
|
2
|
-
encommon/conftest.py,sha256=
|
2
|
+
encommon/conftest.py,sha256=z5BMi6KjNuactDRgbh8J8w81V08Ptf6QK2o_bJANRs4,880
|
3
3
|
encommon/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
4
|
-
encommon/version.txt,sha256=
|
4
|
+
encommon/version.txt,sha256=ln2a-xATRmZxZvLnboGRC8GQSI19QdUMoAcunZLwDjI,6
|
5
5
|
encommon/config/__init__.py,sha256=2ic7tK2lOQvqWmmQnMozqxCJcbyQ_sSEHmOUDUFan2U,710
|
6
6
|
encommon/config/common.py,sha256=gaKBgkF7b7UIAhd0ESio0KpG8JfdRpz5BxNgKRptd6A,2041
|
7
|
-
encommon/config/config.py,sha256
|
7
|
+
encommon/config/config.py,sha256=-wIkyA6YQGAly0WuXLaOYXENjZYRYgWk_VdUN8mMe8Q,4853
|
8
8
|
encommon/config/files.py,sha256=2DHz7GKOjF8FC26tY0V-E9svNMrlkSUshb2gfxqGgSo,2313
|
9
9
|
encommon/config/logger.py,sha256=2y-VFzgM2pZzEYq48XfvrDPrtUcxyP9QjbH5OG7fv5o,13449
|
10
10
|
encommon/config/params.py,sha256=IWQ-UzR8x6VxkcUddC3qhI612IFMfLW44jEjRePXK0c,1825
|
@@ -26,14 +26,14 @@ encommon/times/__init__.py,sha256=w6LeTybgdsi0oM1EL9ARbAqevX7Tn46JYhbXNAaWzB0,59
|
|
26
26
|
encommon/times/common.py,sha256=xLB_GLahYKT-YrVq90RUzmiodJQ4__1YihgZZTnadgg,2506
|
27
27
|
encommon/times/duration.py,sha256=8p-L9OItO80nnd35FYrAXbiUS8RJzavI21lXBrtLaH0,9872
|
28
28
|
encommon/times/parse.py,sha256=ZzranxftlB6bZJ1ivkoUxD53TUfXDDUdpq9jsSJN-88,6411
|
29
|
-
encommon/times/timers.py,sha256=
|
29
|
+
encommon/times/timers.py,sha256=yOVr6deGE5iatNWUwNQCzaXjMlLeYlolx4MmKT0MSHc,6312
|
30
30
|
encommon/times/times.py,sha256=Dfu6ztUsV4X4vHzOC7ds8jtYy0AVj4_R5xB6H-yzemE,9432
|
31
31
|
encommon/times/window.py,sha256=Fx_OJfU9B0IctCyaJ5XH_HxzhGlzeRATwuhI-HlsTPA,8023
|
32
32
|
encommon/times/test/__init__.py,sha256=PjrnBYT0efyvbaGeNx94dm3tP3EVHUHSVs-VGeLEv5g,218
|
33
33
|
encommon/times/test/test_common.py,sha256=nizxgB1scLDEm2o66waK1Ar_Dl5BBMTC-GRV7iDk0_U,1477
|
34
34
|
encommon/times/test/test_duration.py,sha256=rmAhW2otHzQDHF0mBSETHnnL2OSbeAFYEHpDlaUSRnI,3901
|
35
35
|
encommon/times/test/test_parse.py,sha256=TuZG_UbIEez4Ww35vdKIie_yaKp-PiUhsNmr1ZUoGvo,4308
|
36
|
-
encommon/times/test/test_timers.py,sha256=
|
36
|
+
encommon/times/test/test_timers.py,sha256=z-ONyKtkAZ1A7w8qgpgx07r-Vsl5jY-pe2oneSF7hyo,2314
|
37
37
|
encommon/times/test/test_times.py,sha256=DJBmRHCPkMLL9-bmc2DMhhf8zcr2rsTVAAQPavD_UmE,1986
|
38
38
|
encommon/times/test/test_window.py,sha256=EWjXR8XREYwKrH-221CBAUwLF9GpvHtuF_CSMdQtUXI,4735
|
39
39
|
encommon/types/__init__.py,sha256=l2WKtDs6uC9I3dIGnrzJvz-4JLEETUJOfT509XyMQWs,420
|
@@ -44,19 +44,19 @@ encommon/types/test/__init__.py,sha256=PjrnBYT0efyvbaGeNx94dm3tP3EVHUHSVs-VGeLEv
|
|
44
44
|
encommon/types/test/test_dicts.py,sha256=UHMvrWKnz-bPscq0Vp2uoLLFv4slvQQL2sobe5WUZ7U,2673
|
45
45
|
encommon/types/test/test_empty.py,sha256=YUn0ROFhrWLQ30uROVqroHW4BsnFbzUZjACs3aEvrrI,981
|
46
46
|
encommon/types/test/test_strings.py,sha256=WHXf1dnK6Qs2_0UyGYztJxpS29bnR8WKjKsvVO2WCi4,407
|
47
|
-
encommon/utils/__init__.py,sha256=
|
47
|
+
encommon/utils/__init__.py,sha256=bBiDsBz8j-fHJ-P-AM4rZKqfiLNv5Q8KID8GfcvpWLA,833
|
48
48
|
encommon/utils/common.py,sha256=UrowELh3PtDzpSS48nGhsAxTS_QUk96-KEJa4MlxiMA,466
|
49
49
|
encommon/utils/match.py,sha256=4L2d2Cvr7vp3odkRCdNQ10OIW8DkEP55_NbQ6bdsReo,2462
|
50
50
|
encommon/utils/paths.py,sha256=4EeaPsVwpv3pzoHeWmiSSGYZEud6hkD27kvbvgSpOPs,3236
|
51
51
|
encommon/utils/sample.py,sha256=hOhS6A2aB9a5kXfrst7gUSQkxuqEo2J1AFyBsJZQhHE,3169
|
52
|
-
encommon/utils/stdout.py,sha256=
|
52
|
+
encommon/utils/stdout.py,sha256=pPL68iE2oGk-hE3KGZjWE1vnOF6hflaarYPVZQnefHQ,7142
|
53
53
|
encommon/utils/test/__init__.py,sha256=PjrnBYT0efyvbaGeNx94dm3tP3EVHUHSVs-VGeLEv5g,218
|
54
54
|
encommon/utils/test/test_match.py,sha256=QagKpTFdRo23-Y55fSaJrSMpt5jIebScKbz0h8tivrI,1124
|
55
55
|
encommon/utils/test/test_paths.py,sha256=0ls9gWJ2B487Dr1fHDDFCZPA7gxtv56nFEYHrTkNX-U,1892
|
56
56
|
encommon/utils/test/test_sample.py,sha256=iNV9IxXmA5KJat3jKRiZH3iutHrT6bsibwti60AhICk,1464
|
57
|
-
encommon/utils/test/test_stdout.py,sha256=
|
58
|
-
encommon-0.
|
59
|
-
encommon-0.
|
60
|
-
encommon-0.
|
61
|
-
encommon-0.
|
62
|
-
encommon-0.
|
57
|
+
encommon/utils/test/test_stdout.py,sha256=U3YD8XIfVjjh_vNxN1UJqOWyp7_OFtJVl2K5oMziPu8,4878
|
58
|
+
encommon-0.7.0.dist-info/LICENSE,sha256=otnXKCtMjPlbHs0wgZ_BWULrp3g_2dWQJ6icRk9nkgg,1071
|
59
|
+
encommon-0.7.0.dist-info/METADATA,sha256=as7cVGwmjhknmAnTKkAOi6hrVIXU07tWU0t83L4Fn_4,2671
|
60
|
+
encommon-0.7.0.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
61
|
+
encommon-0.7.0.dist-info/top_level.txt,sha256=bP8q7-5tLDNm-3XPlqn_bDENfYNug5801H_xfz3BEAM,9
|
62
|
+
encommon-0.7.0.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|