haiway 0.26.0__py3-none-any.whl → 0.27.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.
- haiway/__init__.py +10 -0
- haiway/context/__init__.py +2 -0
- haiway/context/access.py +4 -0
- haiway/context/observability.py +11 -1
- haiway/helpers/concurrent.py +8 -9
- haiway/helpers/files.py +4 -4
- haiway/helpers/observability.py +8 -2
- haiway/opentelemetry/observability.py +60 -14
- haiway/utils/__init__.py +12 -0
- haiway/utils/collections.py +31 -31
- haiway/utils/formatting.py +126 -36
- haiway/utils/metadata.py +480 -0
- {haiway-0.26.0.dist-info → haiway-0.27.0.dist-info}/METADATA +1 -1
- {haiway-0.26.0.dist-info → haiway-0.27.0.dist-info}/RECORD +16 -15
- {haiway-0.26.0.dist-info → haiway-0.27.0.dist-info}/WHEEL +0 -0
- {haiway-0.26.0.dist-info → haiway-0.27.0.dist-info}/licenses/LICENSE +0 -0
haiway/utils/metadata.py
ADDED
@@ -0,0 +1,480 @@
|
|
1
|
+
import json
|
2
|
+
from collections.abc import Collection, Iterator, Mapping
|
3
|
+
from datetime import datetime
|
4
|
+
from types import EllipsisType
|
5
|
+
from typing import Any, ClassVar, Final, Self, cast, final
|
6
|
+
from uuid import UUID
|
7
|
+
|
8
|
+
__all__ = (
|
9
|
+
"META_EMPTY",
|
10
|
+
"Meta",
|
11
|
+
"MetaTags",
|
12
|
+
"MetaValue",
|
13
|
+
"MetaValues",
|
14
|
+
)
|
15
|
+
|
16
|
+
type MetaValue = Mapping[str, MetaValue] | Collection[MetaValue] | str | float | int | bool | None
|
17
|
+
type MetaValues = Mapping[str, MetaValue]
|
18
|
+
type MetaTags = Collection[str]
|
19
|
+
|
20
|
+
|
21
|
+
@final
|
22
|
+
class Meta(Mapping[str, MetaValue]):
|
23
|
+
"""
|
24
|
+
Immutable metadata container with type-safe access to common fields.
|
25
|
+
|
26
|
+
Meta provides a structured way to store and access metadata as key-value pairs
|
27
|
+
with built-in support for common metadata fields like identifiers, names,
|
28
|
+
descriptions, tags, and timestamps. All values are validated to ensure they
|
29
|
+
conform to the MetaValue type constraints.
|
30
|
+
|
31
|
+
The class implements the Mapping protocol, allowing dict-like access while
|
32
|
+
maintaining immutability. It provides builder-style methods (with_*) for
|
33
|
+
creating modified copies and convenience properties for accessing standard
|
34
|
+
metadata fields.
|
35
|
+
|
36
|
+
Examples
|
37
|
+
--------
|
38
|
+
>>> meta = Meta.of({"kind": "user", "name": "John"})
|
39
|
+
>>> meta = meta.with_tags(["active", "verified"])
|
40
|
+
>>> print(meta.kind) # "user"
|
41
|
+
>>> print(meta.tags) # ("active", "verified")
|
42
|
+
"""
|
43
|
+
|
44
|
+
__IMMUTABLE__: ClassVar[EllipsisType] = ...
|
45
|
+
|
46
|
+
__slots__ = ("_values",)
|
47
|
+
|
48
|
+
def __init__(
|
49
|
+
self,
|
50
|
+
values: MetaValues,
|
51
|
+
/,
|
52
|
+
):
|
53
|
+
assert isinstance(values, Mapping) # nosec: B101
|
54
|
+
self._values: MetaValues
|
55
|
+
object.__setattr__(
|
56
|
+
self,
|
57
|
+
"_values",
|
58
|
+
values,
|
59
|
+
)
|
60
|
+
|
61
|
+
@classmethod
|
62
|
+
def of(
|
63
|
+
cls,
|
64
|
+
meta: Self | MetaValues | None,
|
65
|
+
) -> Self:
|
66
|
+
"""
|
67
|
+
Create a Meta instance from various input types.
|
68
|
+
|
69
|
+
This factory method provides a flexible way to create Meta instances,
|
70
|
+
handling None values, existing Meta instances, and raw mappings.
|
71
|
+
|
72
|
+
Parameters
|
73
|
+
----------
|
74
|
+
meta : Self | MetaValues | None
|
75
|
+
The metadata to wrap. Can be None (returns META_EMPTY),
|
76
|
+
an existing Meta instance (returns as-is), or a mapping
|
77
|
+
of values to validate and wrap.
|
78
|
+
|
79
|
+
Returns
|
80
|
+
-------
|
81
|
+
Self
|
82
|
+
A Meta instance containing the provided metadata.
|
83
|
+
"""
|
84
|
+
if meta is None:
|
85
|
+
return cast(Self, META_EMPTY)
|
86
|
+
|
87
|
+
elif isinstance(meta, Meta):
|
88
|
+
return cast(Self, meta)
|
89
|
+
|
90
|
+
else:
|
91
|
+
assert isinstance(meta, Mapping) # nosec: B101
|
92
|
+
return cls({key: _validated_meta_value(value) for key, value in meta.items()})
|
93
|
+
|
94
|
+
@classmethod
|
95
|
+
def from_mapping(
|
96
|
+
cls,
|
97
|
+
mapping: Mapping[str, Any],
|
98
|
+
/,
|
99
|
+
) -> Self:
|
100
|
+
return cls({key: _validated_meta_value(value) for key, value in mapping.items()})
|
101
|
+
|
102
|
+
@classmethod
|
103
|
+
def from_json(
|
104
|
+
cls,
|
105
|
+
value: str | bytes,
|
106
|
+
/,
|
107
|
+
) -> Self:
|
108
|
+
match json.loads(value):
|
109
|
+
case {**values}:
|
110
|
+
return cls({key: _validated_meta_value(val) for key, val in values.items()})
|
111
|
+
|
112
|
+
case other:
|
113
|
+
raise ValueError(f"Invalid json: {other}")
|
114
|
+
|
115
|
+
def to_str(self) -> str:
|
116
|
+
return self.__str__()
|
117
|
+
|
118
|
+
def to_mapping(
|
119
|
+
self,
|
120
|
+
) -> Mapping[str, Any]:
|
121
|
+
return self._values
|
122
|
+
|
123
|
+
def to_json(
|
124
|
+
self,
|
125
|
+
) -> str:
|
126
|
+
return json.dumps(self._values)
|
127
|
+
|
128
|
+
@property
|
129
|
+
def kind(self) -> str | None:
|
130
|
+
match self._values.get("kind"):
|
131
|
+
case str() as kind:
|
132
|
+
return kind
|
133
|
+
|
134
|
+
case _:
|
135
|
+
return None
|
136
|
+
|
137
|
+
def with_kind(
|
138
|
+
self,
|
139
|
+
kind: str,
|
140
|
+
/,
|
141
|
+
) -> Self:
|
142
|
+
return self.__class__(
|
143
|
+
{
|
144
|
+
**self._values,
|
145
|
+
"kind": kind,
|
146
|
+
}
|
147
|
+
)
|
148
|
+
|
149
|
+
def _get_uuid(
|
150
|
+
self,
|
151
|
+
key: str,
|
152
|
+
/,
|
153
|
+
) -> UUID | None:
|
154
|
+
match self._values.get(key):
|
155
|
+
case str() as identifier:
|
156
|
+
try:
|
157
|
+
return UUID(identifier)
|
158
|
+
except ValueError:
|
159
|
+
return None
|
160
|
+
case _:
|
161
|
+
return None
|
162
|
+
|
163
|
+
def _with_uuid(
|
164
|
+
self,
|
165
|
+
key: str,
|
166
|
+
/,
|
167
|
+
*,
|
168
|
+
value: UUID,
|
169
|
+
) -> Self:
|
170
|
+
return self.__class__(
|
171
|
+
{
|
172
|
+
**self._values,
|
173
|
+
key: str(value),
|
174
|
+
}
|
175
|
+
)
|
176
|
+
|
177
|
+
@property
|
178
|
+
def identifier(self) -> UUID | None:
|
179
|
+
return self._get_uuid("identifier")
|
180
|
+
|
181
|
+
def with_identifier(
|
182
|
+
self,
|
183
|
+
identifier: UUID,
|
184
|
+
/,
|
185
|
+
) -> Self:
|
186
|
+
return self._with_uuid(
|
187
|
+
"identifier",
|
188
|
+
value=identifier,
|
189
|
+
)
|
190
|
+
|
191
|
+
@property
|
192
|
+
def origin_identifier(self) -> UUID | None:
|
193
|
+
return self._get_uuid("origin_identifier")
|
194
|
+
|
195
|
+
def with_origin_identifier(
|
196
|
+
self,
|
197
|
+
identifier: UUID,
|
198
|
+
/,
|
199
|
+
) -> Self:
|
200
|
+
return self._with_uuid(
|
201
|
+
"origin_identifier",
|
202
|
+
value=identifier,
|
203
|
+
)
|
204
|
+
|
205
|
+
@property
|
206
|
+
def predecessor_identifier(self) -> UUID | None:
|
207
|
+
return self._get_uuid("predecessor_identifier")
|
208
|
+
|
209
|
+
def with_predecessor_identifier(
|
210
|
+
self,
|
211
|
+
identifier: UUID,
|
212
|
+
/,
|
213
|
+
) -> Self:
|
214
|
+
return self._with_uuid(
|
215
|
+
"predecessor_identifier",
|
216
|
+
value=identifier,
|
217
|
+
)
|
218
|
+
|
219
|
+
@property
|
220
|
+
def successor_identifier(self) -> UUID | None:
|
221
|
+
return self._get_uuid("successor_identifier")
|
222
|
+
|
223
|
+
def with_successor_identifier(
|
224
|
+
self,
|
225
|
+
identifier: UUID,
|
226
|
+
/,
|
227
|
+
) -> Self:
|
228
|
+
return self._with_uuid(
|
229
|
+
"successor_identifier",
|
230
|
+
value=identifier,
|
231
|
+
)
|
232
|
+
|
233
|
+
@property
|
234
|
+
def name(self) -> str | None:
|
235
|
+
match self._values.get("name"):
|
236
|
+
case str() as name:
|
237
|
+
return name
|
238
|
+
|
239
|
+
case _:
|
240
|
+
return None
|
241
|
+
|
242
|
+
def with_name(
|
243
|
+
self,
|
244
|
+
name: str,
|
245
|
+
/,
|
246
|
+
) -> Self:
|
247
|
+
return self.__class__(
|
248
|
+
{
|
249
|
+
**self._values,
|
250
|
+
"name": name,
|
251
|
+
}
|
252
|
+
)
|
253
|
+
|
254
|
+
@property
|
255
|
+
def description(self) -> str | None:
|
256
|
+
match self._values.get("description"):
|
257
|
+
case str() as description:
|
258
|
+
return description
|
259
|
+
|
260
|
+
case _:
|
261
|
+
return None
|
262
|
+
|
263
|
+
def with_description(
|
264
|
+
self,
|
265
|
+
description: str,
|
266
|
+
/,
|
267
|
+
) -> Self:
|
268
|
+
return self.__class__(
|
269
|
+
{
|
270
|
+
**self._values,
|
271
|
+
"description": description,
|
272
|
+
}
|
273
|
+
)
|
274
|
+
|
275
|
+
@property
|
276
|
+
def tags(self) -> MetaTags:
|
277
|
+
match self._values.get("tags"):
|
278
|
+
case [*tags]:
|
279
|
+
return tuple(tag for tag in tags if isinstance(tag, str))
|
280
|
+
|
281
|
+
case _:
|
282
|
+
return ()
|
283
|
+
|
284
|
+
def with_tags(
|
285
|
+
self,
|
286
|
+
tags: MetaTags,
|
287
|
+
/,
|
288
|
+
) -> Self:
|
289
|
+
match self._values.get("tags"):
|
290
|
+
case [*current_tags]:
|
291
|
+
return self.__class__(
|
292
|
+
{
|
293
|
+
**self._values,
|
294
|
+
"tags": (
|
295
|
+
*current_tags,
|
296
|
+
*(
|
297
|
+
_validated_meta_value(tag)
|
298
|
+
for tag in tags
|
299
|
+
if tag not in current_tags
|
300
|
+
),
|
301
|
+
),
|
302
|
+
}
|
303
|
+
)
|
304
|
+
|
305
|
+
case _:
|
306
|
+
return self.__class__({**self._values, "tags": tags})
|
307
|
+
|
308
|
+
def has_tags(
|
309
|
+
self,
|
310
|
+
tags: MetaTags,
|
311
|
+
/,
|
312
|
+
) -> bool:
|
313
|
+
match self._values.get("tags"):
|
314
|
+
case [*meta_tags]:
|
315
|
+
return all(tag in meta_tags for tag in tags)
|
316
|
+
|
317
|
+
case _:
|
318
|
+
return False
|
319
|
+
|
320
|
+
@property
|
321
|
+
def creation(self) -> datetime | None:
|
322
|
+
match self._values.get("creation"):
|
323
|
+
case str() as iso_value:
|
324
|
+
try:
|
325
|
+
return datetime.fromisoformat(iso_value)
|
326
|
+
|
327
|
+
except ValueError:
|
328
|
+
return None
|
329
|
+
|
330
|
+
case _:
|
331
|
+
return None
|
332
|
+
|
333
|
+
def with_creation(
|
334
|
+
self,
|
335
|
+
creation: datetime,
|
336
|
+
/,
|
337
|
+
) -> Self:
|
338
|
+
return self.__class__(
|
339
|
+
{
|
340
|
+
**self._values,
|
341
|
+
"creation": creation.isoformat(),
|
342
|
+
}
|
343
|
+
)
|
344
|
+
|
345
|
+
def merged_with(
|
346
|
+
self,
|
347
|
+
values: Self | MetaValues | None,
|
348
|
+
/,
|
349
|
+
) -> Self:
|
350
|
+
if not values:
|
351
|
+
return self # do not make a copy when nothing will be updated
|
352
|
+
|
353
|
+
return self.__class__(
|
354
|
+
{
|
355
|
+
**self._values, # already validated
|
356
|
+
**{key: _validated_meta_value(value) for key, value in values.items()},
|
357
|
+
}
|
358
|
+
)
|
359
|
+
|
360
|
+
def excluding(
|
361
|
+
self,
|
362
|
+
*excluded: str,
|
363
|
+
) -> Self:
|
364
|
+
if not excluded:
|
365
|
+
return self
|
366
|
+
|
367
|
+
excluded_set: set[str] = set(excluded)
|
368
|
+
return self.__class__(
|
369
|
+
{key: value for key, value in self._values.items() if key not in excluded_set}
|
370
|
+
)
|
371
|
+
|
372
|
+
def updated(
|
373
|
+
self,
|
374
|
+
**values: MetaValue,
|
375
|
+
) -> Self:
|
376
|
+
return self.__replace__(**values)
|
377
|
+
|
378
|
+
def __replace__(
|
379
|
+
self,
|
380
|
+
**values: Any,
|
381
|
+
) -> Self:
|
382
|
+
return self.merged_with(values)
|
383
|
+
|
384
|
+
def __bool__(self) -> bool:
|
385
|
+
return bool(self._values)
|
386
|
+
|
387
|
+
def __contains__(
|
388
|
+
self,
|
389
|
+
element: Any,
|
390
|
+
) -> bool:
|
391
|
+
return element in self._values
|
392
|
+
|
393
|
+
def __setattr__(
|
394
|
+
self,
|
395
|
+
name: str,
|
396
|
+
value: Any,
|
397
|
+
) -> Any:
|
398
|
+
raise AttributeError(
|
399
|
+
f"Can't modify immutable {self.__class__.__qualname__},"
|
400
|
+
f" attribute - '{name}' cannot be modified"
|
401
|
+
)
|
402
|
+
|
403
|
+
def __delattr__(
|
404
|
+
self,
|
405
|
+
name: str,
|
406
|
+
) -> None:
|
407
|
+
raise AttributeError(
|
408
|
+
f"Can't modify immutable {self.__class__.__qualname__},"
|
409
|
+
f" attribute - '{name}' cannot be deleted"
|
410
|
+
)
|
411
|
+
|
412
|
+
def __setitem__(
|
413
|
+
self,
|
414
|
+
key: str,
|
415
|
+
value: Any,
|
416
|
+
) -> MetaValue:
|
417
|
+
raise AttributeError(
|
418
|
+
f"Can't modify immutable {self.__class__.__qualname__},"
|
419
|
+
f" item - '{key}' cannot be modified"
|
420
|
+
)
|
421
|
+
|
422
|
+
def __delitem__(
|
423
|
+
self,
|
424
|
+
key: str,
|
425
|
+
) -> MetaValue:
|
426
|
+
raise AttributeError(
|
427
|
+
f"Can't modify immutable {self.__class__.__qualname__},"
|
428
|
+
f" item - '{key}' cannot be deleted"
|
429
|
+
)
|
430
|
+
|
431
|
+
def __getitem__(
|
432
|
+
self,
|
433
|
+
key: str,
|
434
|
+
) -> MetaValue:
|
435
|
+
return self._values[key]
|
436
|
+
|
437
|
+
def __iter__(self) -> Iterator[str]:
|
438
|
+
return iter(self._values)
|
439
|
+
|
440
|
+
def __len__(self) -> int:
|
441
|
+
return len(self._values)
|
442
|
+
|
443
|
+
def __copy__(self) -> Self:
|
444
|
+
return self # Metadata is immutable, no need to provide an actual copy
|
445
|
+
|
446
|
+
def __deepcopy__(
|
447
|
+
self,
|
448
|
+
memo: dict[int, Any] | None,
|
449
|
+
) -> Self:
|
450
|
+
return self # Metadata is immutable, no need to provide an actual copy
|
451
|
+
|
452
|
+
|
453
|
+
def _validated_meta_value(value: Any) -> MetaValue: # noqa: PLR0911
|
454
|
+
match value:
|
455
|
+
case None:
|
456
|
+
return value
|
457
|
+
|
458
|
+
case str():
|
459
|
+
return value
|
460
|
+
|
461
|
+
case int():
|
462
|
+
return value
|
463
|
+
|
464
|
+
case float():
|
465
|
+
return value
|
466
|
+
|
467
|
+
case bool():
|
468
|
+
return value
|
469
|
+
|
470
|
+
case [*values]:
|
471
|
+
return tuple(_validated_meta_value(value) for value in values)
|
472
|
+
|
473
|
+
case {**values}:
|
474
|
+
return {key: _validated_meta_value(value) for key, value in values.items()}
|
475
|
+
|
476
|
+
case other:
|
477
|
+
raise TypeError(f"Invalid Meta value: {type(other)}")
|
478
|
+
|
479
|
+
|
480
|
+
META_EMPTY: Final[Meta] = Meta({})
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: haiway
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.27.0
|
4
4
|
Summary: Framework for dependency injection and state management within structured concurrency model.
|
5
5
|
Project-URL: Homepage, https://miquido.com
|
6
6
|
Project-URL: Repository, https://github.com/miquido/haiway.git
|
@@ -1,10 +1,10 @@
|
|
1
|
-
haiway/__init__.py,sha256=
|
1
|
+
haiway/__init__.py,sha256=qzLQvEsgGKFNHp9A34sTg_MrBSvPUq4UtmQS172TfaI,2247
|
2
2
|
haiway/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
3
|
-
haiway/context/__init__.py,sha256=
|
4
|
-
haiway/context/access.py,sha256=
|
3
|
+
haiway/context/__init__.py,sha256=fjWNPXgBsW_nBsT8aR0SuiRehxDylRHHXA-nU2Rvy_Y,1356
|
4
|
+
haiway/context/access.py,sha256=Itpweo9sRFuf_Gu601v6_lWXmAJa4qYsmz2dQ7m7pYA,31527
|
5
5
|
haiway/context/disposables.py,sha256=7Jo-5qzS3UQvZUf4yOqUgfnueMg8I65jwHDp-4g6w54,7998
|
6
6
|
haiway/context/identifier.py,sha256=ps7YM1ZnUrj66SPVyxqMhTRMaYOMNSb82J3FfMRVHm4,4690
|
7
|
-
haiway/context/observability.py,sha256
|
7
|
+
haiway/context/observability.py,sha256=-Q-uzGdtYV1TYaSbhZLMQSTJEMRKBMKTiIv6RoyZXTM,20601
|
8
8
|
haiway/context/presets.py,sha256=NVRv-PzuzonxdzIEJmt8SRMRO0lUgKb-jR-2ixUtkzI,10760
|
9
9
|
haiway/context/state.py,sha256=1oeON23_vaX7IgyckPcA5jWMXije93TNuSh0l9dQqNE,9920
|
10
10
|
haiway/context/tasks.py,sha256=0LdoxkQW0op4-QhAA-IDQO0PQr6Q3Vp4mO5ssEFbclU,4930
|
@@ -12,14 +12,14 @@ haiway/context/types.py,sha256=LoW8238TTdbUgmxyHDi0LVc8M8ZwTHLWKkAPttTsTeg,746
|
|
12
12
|
haiway/helpers/__init__.py,sha256=gyKM1mWyuQwSx_2ajpI0UF1nA8l5D7wrzZOt9XUkWJA,780
|
13
13
|
haiway/helpers/asynchrony.py,sha256=Ddj8UdXhVczAbAC-rLpyhWa4RJ_W2Eolo45Veorq7_4,5362
|
14
14
|
haiway/helpers/caching.py,sha256=BqgcUGQSAmXsuLi5V8EwlZzuGyutHOn1V4k7BHsGKeg,14347
|
15
|
-
haiway/helpers/concurrent.py,sha256=
|
16
|
-
haiway/helpers/files.py,sha256=
|
17
|
-
haiway/helpers/observability.py,sha256=
|
15
|
+
haiway/helpers/concurrent.py,sha256=kTcm_wLAKqVQOKgTHIKwbkMX5hJ5GIXOAc5RRIUvbo4,13063
|
16
|
+
haiway/helpers/files.py,sha256=MzGR-GF8FpBzSihDeen7wdxmX2R-JjAT1MB9aMW-8-g,11626
|
17
|
+
haiway/helpers/observability.py,sha256=ylDilsseZwTsPBmLO6GSUrbiTV593fwNqi3nL8wk814,11043
|
18
18
|
haiway/helpers/retries.py,sha256=OH__I9e-PUFxcSwuQLIzJ9F1MwXgbz1Ur4jEjJiOmjQ,8974
|
19
19
|
haiway/helpers/throttling.py,sha256=KBWUSHdKVMC5_nRMmmoPNwfp-3AcerQ6OczJa9gNLM0,5796
|
20
20
|
haiway/helpers/timeouting.py,sha256=GQ8-btb36f0Jq7TnorAPYXyKScNmf0nxHXCYxqGl-o8,3949
|
21
21
|
haiway/opentelemetry/__init__.py,sha256=TV-1C14mDAtcHhFZ29ActFQdrGH6x5KuGV9w-JlKYJg,91
|
22
|
-
haiway/opentelemetry/observability.py,sha256=
|
22
|
+
haiway/opentelemetry/observability.py,sha256=7VugyXLxGA75VUTSS9fBoVx4SvqZebFpGkOVV70q4-s,29142
|
23
23
|
haiway/state/__init__.py,sha256=mtYgg2TojOBNjFsfoRjYkfZPDhKV5sPJXxDGFBvB8-0,417
|
24
24
|
haiway/state/attributes.py,sha256=sububiFP23aBB8RGk6OvTUp7BEY6S0kER_uHC09yins,26733
|
25
25
|
haiway/state/immutable.py,sha256=YStOo1RQs8JoyLuumOmFXp9IrwOMzIHExVvDmcqj4lE,3693
|
@@ -30,17 +30,18 @@ haiway/state/validation.py,sha256=8IKm9-rJDmP0xJhqRCPc1mm7J1nnjbZDdInmCHZxaeg,24
|
|
30
30
|
haiway/types/__init__.py,sha256=BQKjbPZQej4DQsD_y4linn4rQMWdfaahKW-t-gapSjs,285
|
31
31
|
haiway/types/default.py,sha256=59chcOaoGqI2to08RamCCLluimfYbJp5xbYl3fWaLrM,4153
|
32
32
|
haiway/types/missing.py,sha256=V9FWUgAWUsmFuSXc57MORQOVh2wO2vlF1qYopmcEA2A,5760
|
33
|
-
haiway/utils/__init__.py,sha256=
|
33
|
+
haiway/utils/__init__.py,sha256=ZmRloJ3IUqotOjN1_ejS3NYb4A30LKR78YTaY5b3nao,1133
|
34
34
|
haiway/utils/always.py,sha256=dd6jDQ1j4DpJjTKO1J2Tv5xS8X1LnMC4kQ0D7DtKUvw,1230
|
35
|
-
haiway/utils/collections.py,sha256=
|
35
|
+
haiway/utils/collections.py,sha256=LExyiwpJX7nc0FKhrK12Yim90IcHzHBWRXvnjLjJrz8,4653
|
36
36
|
haiway/utils/env.py,sha256=mCMveOWwOphgp8Ir5NEpZQFENyG7MBOoLlUeHzzIYEQ,11262
|
37
|
-
haiway/utils/formatting.py,sha256=
|
37
|
+
haiway/utils/formatting.py,sha256=cqZHlRc9E4ybNq0Uo826JPJ7WuOWOOY995mCe_2URQw,6499
|
38
38
|
haiway/utils/logs.py,sha256=-MVyxVGU892yJKFh0bkshW_NEg1aiJt9wv2cUY2w98o,1847
|
39
|
+
haiway/utils/metadata.py,sha256=I_e9D5rhHLm7fpHyZFjChm1FnNxPPkeTulD8uhDn_a4,11754
|
39
40
|
haiway/utils/mimic.py,sha256=xaZiUKp096QFfdSw7cNIKEWt2UIS7vf880KF54gny38,1831
|
40
41
|
haiway/utils/noop.py,sha256=U8ocfoCgt-pY0owJDPtrRrj53cabeIXH9qCKWMQnoRk,1336
|
41
42
|
haiway/utils/queue.py,sha256=6v2u3pA6A44IuCCTOjmCt3yLyOcm7PCRnrIGo25j-1o,6402
|
42
43
|
haiway/utils/stream.py,sha256=lXaeveTY0-AYG5xVzcQYaiC6SUD5fUtHoMXiQcrQAAM,5723
|
43
|
-
haiway-0.
|
44
|
-
haiway-0.
|
45
|
-
haiway-0.
|
46
|
-
haiway-0.
|
44
|
+
haiway-0.27.0.dist-info/METADATA,sha256=0dw_DzT7Ui0OY25vJ8Xem5Wo52jDepyfYIg45BnuroI,4919
|
45
|
+
haiway-0.27.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
46
|
+
haiway-0.27.0.dist-info/licenses/LICENSE,sha256=3phcpHVNBP8jsi77gOO0E7rgKeDeu99Pi7DSnK9YHoQ,1069
|
47
|
+
haiway-0.27.0.dist-info/RECORD,,
|
File without changes
|
File without changes
|