dycw-utilities 0.109.27__py3-none-any.whl → 0.109.29__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.
- {dycw_utilities-0.109.27.dist-info → dycw_utilities-0.109.29.dist-info}/METADATA +1 -1
- {dycw_utilities-0.109.27.dist-info → dycw_utilities-0.109.29.dist-info}/RECORD +6 -6
- utilities/__init__.py +1 -1
- utilities/parse.py +375 -51
- {dycw_utilities-0.109.27.dist-info → dycw_utilities-0.109.29.dist-info}/WHEEL +0 -0
- {dycw_utilities-0.109.27.dist-info → dycw_utilities-0.109.29.dist-info}/licenses/LICENSE +0 -0
@@ -1,4 +1,4 @@
|
|
1
|
-
utilities/__init__.py,sha256=
|
1
|
+
utilities/__init__.py,sha256=AIZiPdrHMOKkgJqoeU29sMxSZXZMURdyCYzqvmBulyI,61
|
2
2
|
utilities/altair.py,sha256=Gpja-flOo-Db0PIPJLJsgzAlXWoKUjPU1qY-DQ829ek,9156
|
3
3
|
utilities/astor.py,sha256=xuDUkjq0-b6fhtwjhbnebzbqQZAjMSHR1IIS5uOodVg,777
|
4
4
|
utilities/asyncio.py,sha256=41oQUurWMvadFK5gFnaG21hMM0Vmfn2WS6OpC0R9mas,14757
|
@@ -41,7 +41,7 @@ utilities/operator.py,sha256=0M2yZJ0PODH47ogFEnkGMBe_cfxwZR02T_92LZVZvHo,3715
|
|
41
41
|
utilities/optuna.py,sha256=loyJGWTzljgdJaoLhP09PT8Jz6o_pwBOwehY33lHkhw,1923
|
42
42
|
utilities/orjson.py,sha256=Wj5pzG_VdgoAy14a7Luhem-BgYrRtRFvvl_POiszRd0,36930
|
43
43
|
utilities/os.py,sha256=D_FyyT-6TtqiN9KSS7c9g1fnUtgxmyMtzAjmYLkk46A,3587
|
44
|
-
utilities/parse.py,sha256=
|
44
|
+
utilities/parse.py,sha256=l8W5ik1CvmPEsas-dB7cS5gCKpeyr0hQDtjZqI-9azI,16283
|
45
45
|
utilities/pathlib.py,sha256=31WPMXdLIyXgYOMMl_HOI2wlo66MGSE-cgeelk-Lias,1410
|
46
46
|
utilities/period.py,sha256=ikHXsWtDLr553cfH6p9mMaiCnIAP69B7q84ckWV3HaA,10884
|
47
47
|
utilities/pickle.py,sha256=Bhvd7cZl-zQKQDFjUerqGuSKlHvnW1K2QXeU5UZibtg,657
|
@@ -87,7 +87,7 @@ utilities/warnings.py,sha256=yUgjnmkCRf6QhdyAXzl7u0qQFejhQG3PrjoSwxpbHrs,1819
|
|
87
87
|
utilities/whenever.py,sha256=TjoTAJ1R27-rKXiXzdE4GzPidmYqm0W58XydDXp-QZM,17786
|
88
88
|
utilities/zipfile.py,sha256=24lQc9ATcJxHXBPc_tBDiJk48pWyRrlxO2fIsFxU0A8,699
|
89
89
|
utilities/zoneinfo.py,sha256=-DQz5a0Ikw9jfSZtL0BEQkXOMC9yGn_xiJYNCLMiqEc,1989
|
90
|
-
dycw_utilities-0.109.
|
91
|
-
dycw_utilities-0.109.
|
92
|
-
dycw_utilities-0.109.
|
93
|
-
dycw_utilities-0.109.
|
90
|
+
dycw_utilities-0.109.29.dist-info/METADATA,sha256=wN-G6OupzEqFsIek2lE458u5MkSYceoapxbzRnWL8Z8,13005
|
91
|
+
dycw_utilities-0.109.29.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
92
|
+
dycw_utilities-0.109.29.dist-info/licenses/LICENSE,sha256=gppZp16M6nSVpBbUBrNL6JuYfvKwZiKgV7XoKKsHzqo,1066
|
93
|
+
dycw_utilities-0.109.29.dist-info/RECORD,,
|
utilities/__init__.py
CHANGED
utilities/parse.py
CHANGED
@@ -7,71 +7,138 @@ from enum import Enum
|
|
7
7
|
from pathlib import Path
|
8
8
|
from re import DOTALL
|
9
9
|
from types import NoneType
|
10
|
-
from typing import Any, override
|
10
|
+
from typing import TYPE_CHECKING, Any, override
|
11
11
|
|
12
|
-
from utilities.datetime import
|
12
|
+
from utilities.datetime import (
|
13
|
+
is_instance_date_not_datetime,
|
14
|
+
is_subclass_date_not_datetime,
|
15
|
+
)
|
13
16
|
from utilities.enum import ParseEnumError, parse_enum
|
14
17
|
from utilities.functions import is_subclass_int_not_bool
|
15
18
|
from utilities.iterables import OneEmptyError, OneNonUniqueError, one, one_str
|
16
19
|
from utilities.math import ParseNumberError, parse_number
|
17
20
|
from utilities.re import ExtractGroupError, extract_group
|
18
21
|
from utilities.sentinel import ParseSentinelError, Sentinel, parse_sentinel
|
19
|
-
from utilities.text import
|
22
|
+
from utilities.text import (
|
23
|
+
ParseBoolError,
|
24
|
+
ParseNoneError,
|
25
|
+
join_strs,
|
26
|
+
parse_bool,
|
27
|
+
parse_none,
|
28
|
+
split_key_value_pairs,
|
29
|
+
split_str,
|
30
|
+
)
|
20
31
|
from utilities.types import Duration, Number, ParseTextExtra
|
21
32
|
from utilities.typing import (
|
22
33
|
get_args,
|
34
|
+
is_dict_type,
|
35
|
+
is_frozenset_type,
|
36
|
+
is_list_type,
|
23
37
|
is_literal_type,
|
24
38
|
is_optional_type,
|
39
|
+
is_set_type,
|
25
40
|
is_tuple_type,
|
26
41
|
is_union_type,
|
27
42
|
)
|
28
43
|
from utilities.version import ParseVersionError, Version, parse_version
|
29
44
|
|
45
|
+
if TYPE_CHECKING:
|
46
|
+
from collections.abc import Mapping, Sequence
|
47
|
+
from collections.abc import Set as AbstractSet
|
48
|
+
|
30
49
|
|
31
50
|
def parse_text(
|
32
|
-
|
51
|
+
type_: Any,
|
33
52
|
text: str,
|
34
53
|
/,
|
35
54
|
*,
|
55
|
+
list_separator: str = ",",
|
56
|
+
pair_separator: str = "=",
|
36
57
|
head: bool = False,
|
37
58
|
case_sensitive: bool = False,
|
38
59
|
extra: ParseTextExtra | None = None,
|
39
60
|
) -> Any:
|
40
61
|
"""Parse text."""
|
41
|
-
if
|
62
|
+
if type_ is None:
|
42
63
|
try:
|
43
64
|
return parse_none(text)
|
44
65
|
except ParseNoneError:
|
45
|
-
raise _ParseTextParseError(
|
46
|
-
if isinstance(
|
47
|
-
return _parse_text_type(
|
48
|
-
if
|
49
|
-
return
|
50
|
-
|
66
|
+
raise _ParseTextParseError(type_=type_, text=text) from None
|
67
|
+
if isinstance(type_, type):
|
68
|
+
return _parse_text_type(type_, text, case_sensitive=case_sensitive, extra=extra)
|
69
|
+
if is_dict_type(type_):
|
70
|
+
return _parse_text_dict_type(
|
71
|
+
type_,
|
72
|
+
text,
|
73
|
+
list_separator=list_separator,
|
74
|
+
pair_separator=pair_separator,
|
75
|
+
head=head,
|
76
|
+
case_sensitive=case_sensitive,
|
77
|
+
extra=extra,
|
78
|
+
)
|
79
|
+
if is_frozenset_type(type_):
|
80
|
+
return frozenset(
|
81
|
+
_parse_text_set_type(
|
82
|
+
type_,
|
83
|
+
text,
|
84
|
+
list_separator=list_separator,
|
85
|
+
pair_separator=pair_separator,
|
86
|
+
head=head,
|
87
|
+
case_sensitive=case_sensitive,
|
88
|
+
extra=extra,
|
89
|
+
)
|
90
|
+
)
|
91
|
+
if is_list_type(type_):
|
92
|
+
return _parse_text_list_type(
|
93
|
+
type_,
|
94
|
+
text,
|
95
|
+
list_separator=list_separator,
|
96
|
+
pair_separator=pair_separator,
|
97
|
+
head=head,
|
98
|
+
case_sensitive=case_sensitive,
|
99
|
+
extra=extra,
|
100
|
+
)
|
101
|
+
if is_literal_type(type_):
|
102
|
+
return one_str(get_args(type_), text, head=head, case_sensitive=case_sensitive)
|
103
|
+
if is_optional_type(type_):
|
51
104
|
with suppress(ParseNoneError):
|
52
105
|
return parse_none(text)
|
53
|
-
inner = one(arg for arg in get_args(
|
106
|
+
inner = one(arg for arg in get_args(type_) if arg is not NoneType)
|
54
107
|
try:
|
55
108
|
return parse_text(
|
56
|
-
inner,
|
109
|
+
inner,
|
110
|
+
text,
|
111
|
+
list_separator=list_separator,
|
112
|
+
pair_separator=pair_separator,
|
113
|
+
head=head,
|
114
|
+
case_sensitive=case_sensitive,
|
115
|
+
extra=extra,
|
57
116
|
)
|
58
117
|
except _ParseTextParseError:
|
59
|
-
raise _ParseTextParseError(
|
60
|
-
if
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
parse_text(arg, text, head=head, case_sensitive=case_sensitive, extra=extra)
|
70
|
-
for arg, text in zip(args, texts, strict=True)
|
118
|
+
raise _ParseTextParseError(type_=type_, text=text) from None
|
119
|
+
if is_set_type(type_):
|
120
|
+
return _parse_text_set_type(
|
121
|
+
type_,
|
122
|
+
text,
|
123
|
+
list_separator=list_separator,
|
124
|
+
pair_separator=pair_separator,
|
125
|
+
head=head,
|
126
|
+
case_sensitive=case_sensitive,
|
127
|
+
extra=extra,
|
71
128
|
)
|
72
|
-
if
|
73
|
-
return
|
74
|
-
|
129
|
+
if is_tuple_type(type_):
|
130
|
+
return _parse_text_tuple_type(
|
131
|
+
type_,
|
132
|
+
text,
|
133
|
+
list_separator=list_separator,
|
134
|
+
pair_separator=pair_separator,
|
135
|
+
head=head,
|
136
|
+
case_sensitive=case_sensitive,
|
137
|
+
extra=extra,
|
138
|
+
)
|
139
|
+
if is_union_type(type_):
|
140
|
+
return _parse_text_union_type(type_, text, extra=extra)
|
141
|
+
raise _ParseTextParseError(type_=type_, text=text) from None
|
75
142
|
|
76
143
|
|
77
144
|
def _parse_text_type(
|
@@ -87,69 +154,69 @@ def _parse_text_type(
|
|
87
154
|
try:
|
88
155
|
return parse_none(text)
|
89
156
|
except ParseNoneError:
|
90
|
-
raise _ParseTextParseError(
|
157
|
+
raise _ParseTextParseError(type_=cls, text=text) from None
|
91
158
|
if issubclass(cls, str):
|
92
159
|
return text
|
93
160
|
if issubclass(cls, bool):
|
94
161
|
try:
|
95
162
|
return parse_bool(text)
|
96
163
|
except ParseBoolError:
|
97
|
-
raise _ParseTextParseError(
|
164
|
+
raise _ParseTextParseError(type_=cls, text=text) from None
|
98
165
|
if is_subclass_int_not_bool(cls):
|
99
166
|
try:
|
100
167
|
return int(text)
|
101
168
|
except ValueError:
|
102
|
-
raise _ParseTextParseError(
|
169
|
+
raise _ParseTextParseError(type_=cls, text=text) from None
|
103
170
|
if issubclass(cls, float):
|
104
171
|
try:
|
105
172
|
return float(text)
|
106
173
|
except ValueError:
|
107
|
-
raise _ParseTextParseError(
|
174
|
+
raise _ParseTextParseError(type_=cls, text=text) from None
|
108
175
|
if issubclass(cls, Enum):
|
109
176
|
try:
|
110
177
|
return parse_enum(text, cls, case_sensitive=case_sensitive)
|
111
178
|
except ParseEnumError:
|
112
|
-
raise _ParseTextParseError(
|
179
|
+
raise _ParseTextParseError(type_=cls, text=text) from None
|
113
180
|
if issubclass(cls, Path):
|
114
181
|
return Path(text).expanduser()
|
115
182
|
if issubclass(cls, Sentinel):
|
116
183
|
try:
|
117
184
|
return parse_sentinel(text)
|
118
185
|
except ParseSentinelError:
|
119
|
-
raise _ParseTextParseError(
|
186
|
+
raise _ParseTextParseError(type_=cls, text=text) from None
|
120
187
|
if issubclass(cls, Version):
|
121
188
|
try:
|
122
189
|
return parse_version(text)
|
123
190
|
except ParseVersionError:
|
124
|
-
raise _ParseTextParseError(
|
191
|
+
raise _ParseTextParseError(type_=cls, text=text) from None
|
125
192
|
if is_subclass_date_not_datetime(cls):
|
126
193
|
from utilities.whenever import ParseDateError, parse_date
|
127
194
|
|
128
195
|
try:
|
129
196
|
return parse_date(text)
|
130
197
|
except ParseDateError:
|
131
|
-
raise _ParseTextParseError(
|
198
|
+
raise _ParseTextParseError(type_=cls, text=text) from None
|
132
199
|
if issubclass(cls, dt.datetime):
|
133
200
|
from utilities.whenever import ParseDateTimeError, parse_datetime
|
134
201
|
|
135
202
|
try:
|
136
203
|
return parse_datetime(text)
|
137
204
|
except ParseDateTimeError:
|
138
|
-
raise _ParseTextParseError(
|
205
|
+
raise _ParseTextParseError(type_=cls, text=text) from None
|
139
206
|
if issubclass(cls, dt.time):
|
140
207
|
from utilities.whenever import ParseTimeError, parse_time
|
141
208
|
|
142
209
|
try:
|
143
210
|
return parse_time(text)
|
144
211
|
except ParseTimeError:
|
145
|
-
raise _ParseTextParseError(
|
212
|
+
raise _ParseTextParseError(type_=cls, text=text) from None
|
146
213
|
if issubclass(cls, dt.timedelta):
|
147
214
|
from utilities.whenever import ParseTimedeltaError, parse_timedelta
|
148
215
|
|
149
216
|
try:
|
150
217
|
return parse_timedelta(text)
|
151
218
|
except ParseTimedeltaError:
|
152
|
-
raise _ParseTextParseError(
|
219
|
+
raise _ParseTextParseError(type_=cls, text=text) from None
|
153
220
|
if extra is not None:
|
154
221
|
try:
|
155
222
|
parser = one(p for c, p in extra.items() if issubclass(cls, c))
|
@@ -157,41 +224,197 @@ def _parse_text_type(
|
|
157
224
|
pass
|
158
225
|
except OneNonUniqueError as error:
|
159
226
|
raise _ParseTextExtraNonUniqueError(
|
160
|
-
|
227
|
+
type_=cls, text=text, first=error.first, second=error.second
|
161
228
|
) from None
|
162
229
|
else:
|
163
230
|
return parser(text)
|
164
|
-
raise _ParseTextParseError(
|
231
|
+
raise _ParseTextParseError(type_=cls, text=text) from None
|
232
|
+
|
233
|
+
|
234
|
+
def _parse_text_dict_type(
|
235
|
+
type_: Any,
|
236
|
+
text: str,
|
237
|
+
/,
|
238
|
+
*,
|
239
|
+
list_separator: str = ",",
|
240
|
+
pair_separator: str = "=",
|
241
|
+
head: bool = False,
|
242
|
+
case_sensitive: bool = False,
|
243
|
+
extra: ParseTextExtra | None = None,
|
244
|
+
) -> dict[Any, Any]:
|
245
|
+
key_type, value_type = get_args(type_)
|
246
|
+
try:
|
247
|
+
inner_text = extract_group(r"^{(.*)}$", text, flags=DOTALL)
|
248
|
+
except ExtractGroupError:
|
249
|
+
raise _ParseTextParseError(type_=type_, text=text) from None
|
250
|
+
pairs = split_key_value_pairs(
|
251
|
+
inner_text,
|
252
|
+
list_separator=list_separator,
|
253
|
+
pair_separator=pair_separator,
|
254
|
+
mapping=True,
|
255
|
+
)
|
256
|
+
keys = (
|
257
|
+
parse_text(
|
258
|
+
key_type,
|
259
|
+
k,
|
260
|
+
list_separator=list_separator,
|
261
|
+
pair_separator=pair_separator,
|
262
|
+
head=head,
|
263
|
+
case_sensitive=case_sensitive,
|
264
|
+
extra=extra,
|
265
|
+
)
|
266
|
+
for k in pairs
|
267
|
+
)
|
268
|
+
values = (
|
269
|
+
parse_text(
|
270
|
+
value_type,
|
271
|
+
v,
|
272
|
+
list_separator=list_separator,
|
273
|
+
pair_separator=pair_separator,
|
274
|
+
head=head,
|
275
|
+
case_sensitive=case_sensitive,
|
276
|
+
extra=extra,
|
277
|
+
)
|
278
|
+
for v in pairs.values()
|
279
|
+
)
|
280
|
+
try:
|
281
|
+
return dict(zip(keys, values, strict=True))
|
282
|
+
except _ParseTextParseError:
|
283
|
+
raise _ParseTextParseError(type_=type_, text=text) from None
|
284
|
+
|
285
|
+
|
286
|
+
def _parse_text_list_type(
|
287
|
+
type_: Any,
|
288
|
+
text: str,
|
289
|
+
/,
|
290
|
+
*,
|
291
|
+
list_separator: str = ",",
|
292
|
+
pair_separator: str = "=",
|
293
|
+
head: bool = False,
|
294
|
+
case_sensitive: bool = False,
|
295
|
+
extra: ParseTextExtra | None = None,
|
296
|
+
) -> list[Any]:
|
297
|
+
inner_type = one(get_args(type_))
|
298
|
+
try:
|
299
|
+
inner_text = extract_group(r"^\[(.*)\]$", text, flags=DOTALL)
|
300
|
+
except ExtractGroupError:
|
301
|
+
raise _ParseTextParseError(type_=type_, text=text) from None
|
302
|
+
texts = split_str(inner_text, separator=list_separator)
|
303
|
+
try:
|
304
|
+
return [
|
305
|
+
parse_text(
|
306
|
+
inner_type,
|
307
|
+
t,
|
308
|
+
list_separator=list_separator,
|
309
|
+
pair_separator=pair_separator,
|
310
|
+
head=head,
|
311
|
+
case_sensitive=case_sensitive,
|
312
|
+
extra=extra,
|
313
|
+
)
|
314
|
+
for t in texts
|
315
|
+
]
|
316
|
+
except _ParseTextParseError:
|
317
|
+
raise _ParseTextParseError(type_=type_, text=text) from None
|
318
|
+
|
319
|
+
|
320
|
+
def _parse_text_set_type(
|
321
|
+
type_: Any,
|
322
|
+
text: str,
|
323
|
+
/,
|
324
|
+
*,
|
325
|
+
list_separator: str = ",",
|
326
|
+
pair_separator: str = "=",
|
327
|
+
head: bool = False,
|
328
|
+
case_sensitive: bool = False,
|
329
|
+
extra: ParseTextExtra | None = None,
|
330
|
+
) -> set[Any]:
|
331
|
+
inner_type = one(get_args(type_))
|
332
|
+
try:
|
333
|
+
inner_text = extract_group(r"^{(.*)}$", text, flags=DOTALL)
|
334
|
+
except ExtractGroupError:
|
335
|
+
raise _ParseTextParseError(type_=type_, text=text) from None
|
336
|
+
texts = split_str(inner_text, separator=list_separator)
|
337
|
+
try:
|
338
|
+
return {
|
339
|
+
parse_text(
|
340
|
+
inner_type,
|
341
|
+
t,
|
342
|
+
list_separator=list_separator,
|
343
|
+
pair_separator=pair_separator,
|
344
|
+
head=head,
|
345
|
+
case_sensitive=case_sensitive,
|
346
|
+
extra=extra,
|
347
|
+
)
|
348
|
+
for t in texts
|
349
|
+
}
|
350
|
+
except _ParseTextParseError:
|
351
|
+
raise _ParseTextParseError(type_=type_, text=text) from None
|
165
352
|
|
166
353
|
|
167
354
|
def _parse_text_union_type(
|
168
|
-
|
355
|
+
type_: Any, text: str, /, *, extra: ParseTextExtra | None = None
|
169
356
|
) -> Any:
|
170
|
-
if
|
357
|
+
if type_ is Number:
|
171
358
|
try:
|
172
359
|
return parse_number(text)
|
173
360
|
except ParseNumberError:
|
174
|
-
raise _ParseTextParseError(
|
175
|
-
if
|
361
|
+
raise _ParseTextParseError(type_=type_, text=text) from None
|
362
|
+
if type_ is Duration:
|
176
363
|
from utilities.whenever import ParseDurationError, parse_duration
|
177
364
|
|
178
365
|
try:
|
179
366
|
return parse_duration(text)
|
180
367
|
except ParseDurationError:
|
181
|
-
raise _ParseTextParseError(
|
368
|
+
raise _ParseTextParseError(type_=type_, text=text) from None
|
182
369
|
if extra is not None:
|
183
370
|
try:
|
184
|
-
parser = one(p for c, p in extra.items() if c is
|
371
|
+
parser = one(p for c, p in extra.items() if c is type_)
|
185
372
|
except OneEmptyError:
|
186
373
|
pass
|
187
374
|
else:
|
188
375
|
return parser(text)
|
189
|
-
raise _ParseTextParseError(
|
376
|
+
raise _ParseTextParseError(type_=type_, text=text) from None
|
377
|
+
|
378
|
+
|
379
|
+
def _parse_text_tuple_type(
|
380
|
+
type_: Any,
|
381
|
+
text: str,
|
382
|
+
/,
|
383
|
+
*,
|
384
|
+
list_separator: str = ",",
|
385
|
+
pair_separator: str = "=",
|
386
|
+
head: bool = False,
|
387
|
+
case_sensitive: bool = False,
|
388
|
+
extra: ParseTextExtra | None = None,
|
389
|
+
) -> tuple[Any, ...]:
|
390
|
+
args = get_args(type_)
|
391
|
+
try:
|
392
|
+
inner = extract_group(r"^\((.*)\)$", text, flags=DOTALL)
|
393
|
+
except ExtractGroupError:
|
394
|
+
raise _ParseTextParseError(type_=type_, text=text) from None
|
395
|
+
texts = inner.split(",")
|
396
|
+
if len(args) != len(texts):
|
397
|
+
raise _ParseTextParseError(type_=type_, text=text)
|
398
|
+
try:
|
399
|
+
return tuple(
|
400
|
+
parse_text(
|
401
|
+
arg,
|
402
|
+
text,
|
403
|
+
list_separator=list_separator,
|
404
|
+
pair_separator=pair_separator,
|
405
|
+
head=head,
|
406
|
+
case_sensitive=case_sensitive,
|
407
|
+
extra=extra,
|
408
|
+
)
|
409
|
+
for arg, text in zip(args, texts, strict=True)
|
410
|
+
)
|
411
|
+
except _ParseTextParseError:
|
412
|
+
raise _ParseTextParseError(type_=type_, text=text) from None
|
190
413
|
|
191
414
|
|
192
415
|
@dataclass
|
193
416
|
class ParseTextError(Exception):
|
194
|
-
|
417
|
+
type_: Any
|
195
418
|
text: str
|
196
419
|
|
197
420
|
|
@@ -199,7 +422,7 @@ class ParseTextError(Exception):
|
|
199
422
|
class _ParseTextParseError(ParseTextError):
|
200
423
|
@override
|
201
424
|
def __str__(self) -> str:
|
202
|
-
return f"Unable to parse {self.
|
425
|
+
return f"Unable to parse {self.type_!r}; got {self.text!r}"
|
203
426
|
|
204
427
|
|
205
428
|
@dataclass
|
@@ -209,4 +432,105 @@ class _ParseTextExtraNonUniqueError(ParseTextError):
|
|
209
432
|
|
210
433
|
@override
|
211
434
|
def __str__(self) -> str:
|
212
|
-
return f"Unable to parse {self.
|
435
|
+
return f"Unable to parse {self.type_!r} since `extra` must contain exactly one parent class; got {self.first!r}, {self.second!r} and perhaps more"
|
436
|
+
|
437
|
+
|
438
|
+
##
|
439
|
+
|
440
|
+
|
441
|
+
def to_text(
|
442
|
+
obj: Any, /, *, list_separator: str = ",", pair_separator: str = "="
|
443
|
+
) -> str:
|
444
|
+
"""Convert an object to text."""
|
445
|
+
if (obj is None) or isinstance(
|
446
|
+
obj, bool | int | float | str | Path | Sentinel | Version
|
447
|
+
):
|
448
|
+
return str(obj)
|
449
|
+
if is_instance_date_not_datetime(obj):
|
450
|
+
from utilities.whenever import serialize_date
|
451
|
+
|
452
|
+
return serialize_date(obj)
|
453
|
+
if isinstance(obj, dt.datetime):
|
454
|
+
from utilities.whenever import serialize_datetime
|
455
|
+
|
456
|
+
return serialize_datetime(obj)
|
457
|
+
if isinstance(obj, dt.time):
|
458
|
+
from utilities.whenever import serialize_time
|
459
|
+
|
460
|
+
return serialize_time(obj)
|
461
|
+
if isinstance(obj, dt.timedelta):
|
462
|
+
from utilities.whenever import serialize_timedelta
|
463
|
+
|
464
|
+
return serialize_timedelta(obj)
|
465
|
+
if isinstance(obj, Enum):
|
466
|
+
return obj.name
|
467
|
+
if isinstance(obj, dict):
|
468
|
+
return _to_text_dict(
|
469
|
+
obj, list_separator=list_separator, pair_separator=pair_separator
|
470
|
+
)
|
471
|
+
if isinstance(obj, list):
|
472
|
+
return _to_text_list(
|
473
|
+
obj, list_separator=list_separator, pair_separator=pair_separator
|
474
|
+
)
|
475
|
+
if isinstance(obj, tuple):
|
476
|
+
return _to_text_tuple(
|
477
|
+
obj, list_separator=list_separator, pair_separator=pair_separator
|
478
|
+
)
|
479
|
+
if isinstance(obj, set | frozenset):
|
480
|
+
return _to_text_set(
|
481
|
+
obj, list_separator=list_separator, pair_separator=pair_separator
|
482
|
+
)
|
483
|
+
raise NotImplementedError(obj)
|
484
|
+
|
485
|
+
|
486
|
+
def _to_text_dict(
|
487
|
+
obj: Mapping[Any, Any], /, *, list_separator: str = ",", pair_separator: str = "="
|
488
|
+
) -> str:
|
489
|
+
keys = (
|
490
|
+
to_text(k, list_separator=list_separator, pair_separator=pair_separator)
|
491
|
+
for k in obj
|
492
|
+
)
|
493
|
+
values = (
|
494
|
+
to_text(v, list_separator=list_separator, pair_separator=pair_separator)
|
495
|
+
for v in obj.values()
|
496
|
+
)
|
497
|
+
items = zip(keys, values, strict=True)
|
498
|
+
joined_items = (join_strs(item, separator=pair_separator) for item in items)
|
499
|
+
joined = join_strs(joined_items, separator=list_separator)
|
500
|
+
return f"{{{joined}}}"
|
501
|
+
|
502
|
+
|
503
|
+
def _to_text_list(
|
504
|
+
obj: Sequence[Any], /, *, list_separator: str = ",", pair_separator: str = "="
|
505
|
+
) -> str:
|
506
|
+
items = (
|
507
|
+
to_text(i, list_separator=list_separator, pair_separator=pair_separator)
|
508
|
+
for i in obj
|
509
|
+
)
|
510
|
+
joined = join_strs(items, separator=list_separator)
|
511
|
+
return f"[{joined}]"
|
512
|
+
|
513
|
+
|
514
|
+
def _to_text_set(
|
515
|
+
obj: AbstractSet[Any], /, *, list_separator: str = ",", pair_separator: str = "="
|
516
|
+
) -> str:
|
517
|
+
items = (
|
518
|
+
to_text(i, list_separator=list_separator, pair_separator=pair_separator)
|
519
|
+
for i in obj
|
520
|
+
)
|
521
|
+
joined = join_strs(items, sort=True, separator=list_separator)
|
522
|
+
return f"{{{joined}}}"
|
523
|
+
|
524
|
+
|
525
|
+
def _to_text_tuple(
|
526
|
+
obj: tuple[Any, ...], /, *, list_separator: str = ",", pair_separator: str = "="
|
527
|
+
) -> str:
|
528
|
+
items = (
|
529
|
+
to_text(i, list_separator=list_separator, pair_separator=pair_separator)
|
530
|
+
for i in obj
|
531
|
+
)
|
532
|
+
joined = join_strs(items, separator=list_separator)
|
533
|
+
return f"({joined})"
|
534
|
+
|
535
|
+
|
536
|
+
__all__ = ["parse_text"]
|
File without changes
|
File without changes
|