haiway 0.9.1__tar.gz → 0.10.1__tar.gz
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-0.9.1/src/haiway.egg-info → haiway-0.10.1}/PKG-INFO +1 -1
- {haiway-0.9.1 → haiway-0.10.1}/pyproject.toml +1 -1
- {haiway-0.9.1 → haiway-0.10.1}/src/haiway/__init__.py +6 -0
- {haiway-0.9.1 → haiway-0.10.1}/src/haiway/state/attributes.py +4 -1
- {haiway-0.9.1 → haiway-0.10.1}/src/haiway/state/structure.py +44 -11
- {haiway-0.9.1 → haiway-0.10.1}/src/haiway/state/validation.py +13 -4
- {haiway-0.9.1 → haiway-0.10.1}/src/haiway/types/__init__.py +3 -0
- haiway-0.10.1/src/haiway/types/default.py +108 -0
- {haiway-0.9.1 → haiway-0.10.1}/src/haiway/types/missing.py +1 -0
- {haiway-0.9.1 → haiway-0.10.1}/src/haiway/utils/__init__.py +3 -3
- haiway-0.10.1/src/haiway/utils/collections.py +108 -0
- {haiway-0.9.1 → haiway-0.10.1/src/haiway.egg-info}/PKG-INFO +1 -1
- {haiway-0.9.1 → haiway-0.10.1}/src/haiway.egg-info/SOURCES.txt +3 -3
- haiway-0.10.1/src/haiway.egg-info/top_level.txt +1 -0
- {haiway-0.9.1 → haiway-0.10.1}/tests/test_state.py +5 -1
- haiway-0.9.1/src/haiway/utils/mappings.py +0 -30
- haiway-0.9.1/src/haiway/utils/sequences.py +0 -56
- haiway-0.9.1/src/haiway.egg-info/top_level.txt +0 -2
- {haiway-0.9.1 → haiway-0.10.1}/LICENSE +0 -0
- {haiway-0.9.1 → haiway-0.10.1}/README.md +0 -0
- {haiway-0.9.1 → haiway-0.10.1}/setup.cfg +0 -0
- {haiway-0.9.1 → haiway-0.10.1}/src/haiway/context/__init__.py +0 -0
- {haiway-0.9.1 → haiway-0.10.1}/src/haiway/context/access.py +0 -0
- {haiway-0.9.1 → haiway-0.10.1}/src/haiway/context/disposables.py +0 -0
- {haiway-0.9.1 → haiway-0.10.1}/src/haiway/context/identifier.py +0 -0
- {haiway-0.9.1 → haiway-0.10.1}/src/haiway/context/logging.py +0 -0
- {haiway-0.9.1 → haiway-0.10.1}/src/haiway/context/metrics.py +0 -0
- {haiway-0.9.1 → haiway-0.10.1}/src/haiway/context/state.py +0 -0
- {haiway-0.9.1 → haiway-0.10.1}/src/haiway/context/tasks.py +0 -0
- {haiway-0.9.1 → haiway-0.10.1}/src/haiway/context/types.py +0 -0
- {haiway-0.9.1 → haiway-0.10.1}/src/haiway/helpers/__init__.py +0 -0
- {haiway-0.9.1 → haiway-0.10.1}/src/haiway/helpers/asynchrony.py +0 -0
- {haiway-0.9.1 → haiway-0.10.1}/src/haiway/helpers/caching.py +0 -0
- {haiway-0.9.1 → haiway-0.10.1}/src/haiway/helpers/metrics.py +0 -0
- {haiway-0.9.1 → haiway-0.10.1}/src/haiway/helpers/retries.py +0 -0
- {haiway-0.9.1 → haiway-0.10.1}/src/haiway/helpers/throttling.py +0 -0
- {haiway-0.9.1 → haiway-0.10.1}/src/haiway/helpers/timeouted.py +0 -0
- {haiway-0.9.1 → haiway-0.10.1}/src/haiway/helpers/tracing.py +0 -0
- {haiway-0.9.1 → haiway-0.10.1}/src/haiway/py.typed +0 -0
- {haiway-0.9.1 → haiway-0.10.1}/src/haiway/state/__init__.py +0 -0
- {haiway-0.9.1 → haiway-0.10.1}/src/haiway/state/path.py +0 -0
- {haiway-0.9.1 → haiway-0.10.1}/src/haiway/state/requirement.py +0 -0
- {haiway-0.9.1 → haiway-0.10.1}/src/haiway/types/frozen.py +0 -0
- {haiway-0.9.1 → haiway-0.10.1}/src/haiway/utils/always.py +0 -0
- {haiway-0.9.1 → haiway-0.10.1}/src/haiway/utils/env.py +0 -0
- /haiway-0.9.1/src/haiway/utils/immutable.py → /haiway-0.10.1/src/haiway/utils/freezing.py +0 -0
- {haiway-0.9.1 → haiway-0.10.1}/src/haiway/utils/logs.py +0 -0
- {haiway-0.9.1 → haiway-0.10.1}/src/haiway/utils/mimic.py +0 -0
- {haiway-0.9.1 → haiway-0.10.1}/src/haiway/utils/noop.py +0 -0
- {haiway-0.9.1 → haiway-0.10.1}/src/haiway/utils/queue.py +0 -0
- {haiway-0.9.1 → haiway-0.10.1}/src/haiway.egg-info/dependency_links.txt +0 -0
- {haiway-0.9.1 → haiway-0.10.1}/src/haiway.egg-info/requires.txt +0 -0
- {haiway-0.9.1 → haiway-0.10.1}/tests/test_async_queue.py +0 -0
- {haiway-0.9.1 → haiway-0.10.1}/tests/test_attribute_path.py +0 -0
- {haiway-0.9.1 → haiway-0.10.1}/tests/test_auto_retry.py +0 -0
- {haiway-0.9.1 → haiway-0.10.1}/tests/test_cache.py +0 -0
- {haiway-0.9.1 → haiway-0.10.1}/tests/test_context.py +0 -0
- {haiway-0.9.1 → haiway-0.10.1}/tests/test_streaming.py +0 -0
- {haiway-0.9.1 → haiway-0.10.1}/tests/test_timeout.py +0 -0
@@ -5,7 +5,7 @@ build-backend = "setuptools.build_meta"
|
|
5
5
|
[project]
|
6
6
|
name = "haiway"
|
7
7
|
description = "Framework for dependency injection and state management within structured concurrency model."
|
8
|
-
version = "0.
|
8
|
+
version = "0.10.1"
|
9
9
|
readme = "README.md"
|
10
10
|
maintainers = [
|
11
11
|
{ name = "Kacper Kaliński", email = "kacper.kalinski@miquido.com" },
|
@@ -28,6 +28,8 @@ from haiway.helpers import (
|
|
28
28
|
from haiway.state import AttributePath, AttributeRequirement, State
|
29
29
|
from haiway.types import (
|
30
30
|
MISSING,
|
31
|
+
Default,
|
32
|
+
DefaultValue,
|
31
33
|
Missing,
|
32
34
|
frozenlist,
|
33
35
|
is_missing,
|
@@ -39,6 +41,7 @@ from haiway.utils import (
|
|
39
41
|
always,
|
40
42
|
as_dict,
|
41
43
|
as_list,
|
44
|
+
as_set,
|
42
45
|
as_tuple,
|
43
46
|
async_always,
|
44
47
|
async_noop,
|
@@ -59,6 +62,8 @@ __all__ = [
|
|
59
62
|
"AsyncQueue",
|
60
63
|
"AttributePath",
|
61
64
|
"AttributeRequirement",
|
65
|
+
"Default",
|
66
|
+
"DefaultValue",
|
62
67
|
"Disposable",
|
63
68
|
"Disposables",
|
64
69
|
"MetricsContext",
|
@@ -78,6 +83,7 @@ __all__ = [
|
|
78
83
|
"always",
|
79
84
|
"as_dict",
|
80
85
|
"as_list",
|
86
|
+
"as_set",
|
81
87
|
"as_tuple",
|
82
88
|
"async_always",
|
83
89
|
"async_noop",
|
@@ -509,7 +509,10 @@ def _resolve_type_typeddict(
|
|
509
509
|
self_annotation=resolved_attribute,
|
510
510
|
recursion_guard=recursion_guard,
|
511
511
|
).update_required(key in annotation.__required_keys__)
|
512
|
-
resolved_attribute.extra =
|
512
|
+
resolved_attribute.extra = {
|
513
|
+
"attributes": attributes,
|
514
|
+
"required": annotation.__required_keys__,
|
515
|
+
}
|
513
516
|
return resolved_attribute
|
514
517
|
|
515
518
|
|
@@ -1,5 +1,5 @@
|
|
1
1
|
import typing
|
2
|
-
from collections.abc import Mapping
|
2
|
+
from collections.abc import Callable, Mapping
|
3
3
|
from types import EllipsisType, GenericAlias
|
4
4
|
from typing import (
|
5
5
|
Any,
|
@@ -10,34 +10,55 @@ from typing import (
|
|
10
10
|
cast,
|
11
11
|
dataclass_transform,
|
12
12
|
final,
|
13
|
+
overload,
|
13
14
|
)
|
14
15
|
from weakref import WeakValueDictionary
|
15
16
|
|
16
17
|
from haiway.state.attributes import AttributeAnnotation, attribute_annotations
|
17
18
|
from haiway.state.path import AttributePath
|
18
|
-
from haiway.state.validation import
|
19
|
-
|
20
|
-
AttributeValidator,
|
21
|
-
)
|
22
|
-
from haiway.types import MISSING, Missing, not_missing
|
19
|
+
from haiway.state.validation import AttributeValidation, AttributeValidator
|
20
|
+
from haiway.types import MISSING, DefaultValue, Missing, not_missing
|
23
21
|
|
24
22
|
__all__ = [
|
25
23
|
"State",
|
26
24
|
]
|
27
25
|
|
28
26
|
|
27
|
+
@overload
|
28
|
+
def Default[Value](
|
29
|
+
value: Value,
|
30
|
+
/,
|
31
|
+
) -> Value: ...
|
32
|
+
|
33
|
+
|
34
|
+
@overload
|
35
|
+
def Default[Value](
|
36
|
+
*,
|
37
|
+
factory: Callable[[], Value],
|
38
|
+
) -> Value: ...
|
39
|
+
|
40
|
+
|
41
|
+
def Default[Value](
|
42
|
+
value: Value | Missing = MISSING,
|
43
|
+
/,
|
44
|
+
*,
|
45
|
+
factory: Callable[[], Value] | Missing = MISSING,
|
46
|
+
) -> Value: # it is actually a DefaultValue, but type checker has to be fooled
|
47
|
+
return cast(Value, DefaultValue(value, factory=factory))
|
48
|
+
|
49
|
+
|
29
50
|
@final
|
30
51
|
class StateAttribute[Value]:
|
31
52
|
def __init__(
|
32
53
|
self,
|
33
54
|
name: str,
|
34
55
|
annotation: AttributeAnnotation,
|
35
|
-
default: Value
|
56
|
+
default: DefaultValue[Value],
|
36
57
|
validator: AttributeValidation[Value],
|
37
58
|
) -> None:
|
38
59
|
self.name: str = name
|
39
60
|
self.annotation: AttributeAnnotation = annotation
|
40
|
-
self.default: Value
|
61
|
+
self.default: DefaultValue[Value] = default
|
41
62
|
self.validator: AttributeValidation[Value] = validator
|
42
63
|
|
43
64
|
def validated(
|
@@ -45,13 +66,13 @@ class StateAttribute[Value]:
|
|
45
66
|
value: Any | Missing,
|
46
67
|
/,
|
47
68
|
) -> Value:
|
48
|
-
return self.validator(self.default if value is MISSING else value)
|
69
|
+
return self.validator(self.default() if value is MISSING else value)
|
49
70
|
|
50
71
|
|
51
72
|
@dataclass_transform(
|
52
73
|
kw_only_default=True,
|
53
74
|
frozen_default=True,
|
54
|
-
field_specifiers=(),
|
75
|
+
field_specifiers=(DefaultValue,),
|
55
76
|
)
|
56
77
|
class StateMeta(type):
|
57
78
|
def __new__(
|
@@ -81,7 +102,7 @@ class StateMeta(type):
|
|
81
102
|
attributes[key] = StateAttribute(
|
82
103
|
name=key,
|
83
104
|
annotation=annotation.update_required(default is MISSING),
|
84
|
-
default=default,
|
105
|
+
default=_resolve_default(default),
|
85
106
|
validator=AttributeValidator.of(
|
86
107
|
annotation,
|
87
108
|
recursion_guard={
|
@@ -187,6 +208,18 @@ class StateMeta(type):
|
|
187
208
|
return False # we have different base / comparing to not parametrized
|
188
209
|
|
189
210
|
|
211
|
+
def _resolve_default[Value](
|
212
|
+
value: DefaultValue[Value] | Value | Missing,
|
213
|
+
) -> DefaultValue[Value]:
|
214
|
+
if isinstance(value, DefaultValue):
|
215
|
+
return cast(DefaultValue[Value], value)
|
216
|
+
|
217
|
+
return DefaultValue[Value](
|
218
|
+
value,
|
219
|
+
factory=MISSING,
|
220
|
+
)
|
221
|
+
|
222
|
+
|
190
223
|
_types_cache: WeakValueDictionary[
|
191
224
|
tuple[
|
192
225
|
Any,
|
@@ -86,6 +86,12 @@ class AttributeValidator[Type]:
|
|
86
86
|
assert self.validation is not MISSING # nosec: B101
|
87
87
|
return self.validation(value) # pyright: ignore[reportCallIssue, reportUnknownVariableType]
|
88
88
|
|
89
|
+
def __str__(self) -> str:
|
90
|
+
return f"Validator[{self.annotation}]"
|
91
|
+
|
92
|
+
def __repr__(self) -> str:
|
93
|
+
return f"Validator[{self.annotation}]"
|
94
|
+
|
89
95
|
|
90
96
|
def _prepare_validator_of_any(
|
91
97
|
annotation: AttributeAnnotation,
|
@@ -391,11 +397,12 @@ def _prepare_validator_of_typed_dict(
|
|
391
397
|
case _:
|
392
398
|
raise TypeError(f"'{value}' is not matching expected type of 'str'")
|
393
399
|
|
400
|
+
formatted_type: str = str(annotation)
|
394
401
|
values_validators: dict[str, AttributeValidation[Any]] = {
|
395
402
|
key: AttributeValidator.of(element, recursion_guard=recursion_guard)
|
396
|
-
for key, element in annotation.extra.items()
|
403
|
+
for key, element in annotation.extra["attributes"].items()
|
397
404
|
}
|
398
|
-
|
405
|
+
required_values: Set[str] = annotation.extra["required"]
|
399
406
|
|
400
407
|
def validator(
|
401
408
|
value: Any,
|
@@ -406,8 +413,10 @@ def _prepare_validator_of_typed_dict(
|
|
406
413
|
validated: MutableMapping[str, Any] = {}
|
407
414
|
for key, validator in values_validators.items():
|
408
415
|
element: Any = elements.get(key, MISSING)
|
409
|
-
if element is not
|
410
|
-
|
416
|
+
if element is MISSING and key not in required_values:
|
417
|
+
continue # skip missing and not required
|
418
|
+
|
419
|
+
validated[key_validator(key)] = validator(element)
|
411
420
|
|
412
421
|
# TODO: make sure dict is not mutable with MappingProxyType?
|
413
422
|
return validated
|
@@ -1,8 +1,11 @@
|
|
1
|
+
from haiway.types.default import Default, DefaultValue
|
1
2
|
from haiway.types.frozen import frozenlist
|
2
3
|
from haiway.types.missing import MISSING, Missing, is_missing, not_missing, when_missing
|
3
4
|
|
4
5
|
__all__ = [
|
5
6
|
"MISSING",
|
7
|
+
"Default",
|
8
|
+
"DefaultValue",
|
6
9
|
"Missing",
|
7
10
|
"frozenlist",
|
8
11
|
"is_missing",
|
@@ -0,0 +1,108 @@
|
|
1
|
+
from collections.abc import Callable
|
2
|
+
from typing import Any, cast, final, overload
|
3
|
+
|
4
|
+
from haiway.types.missing import MISSING, Missing, not_missing
|
5
|
+
from haiway.utils.always import always
|
6
|
+
|
7
|
+
__all__ = [
|
8
|
+
"Default",
|
9
|
+
"DefaultValue",
|
10
|
+
]
|
11
|
+
|
12
|
+
|
13
|
+
@final
|
14
|
+
class DefaultValue[Value]:
|
15
|
+
@overload
|
16
|
+
def __init__(
|
17
|
+
self,
|
18
|
+
value: Value,
|
19
|
+
/,
|
20
|
+
) -> None: ...
|
21
|
+
|
22
|
+
@overload
|
23
|
+
def __init__(
|
24
|
+
self,
|
25
|
+
/,
|
26
|
+
*,
|
27
|
+
factory: Callable[[], Value],
|
28
|
+
) -> None: ...
|
29
|
+
|
30
|
+
@overload
|
31
|
+
def __init__(
|
32
|
+
self,
|
33
|
+
value: Value | Missing,
|
34
|
+
/,
|
35
|
+
*,
|
36
|
+
factory: Callable[[], Value] | Missing,
|
37
|
+
) -> None: ...
|
38
|
+
|
39
|
+
def __init__(
|
40
|
+
self,
|
41
|
+
value: Value | Missing = MISSING,
|
42
|
+
/,
|
43
|
+
*,
|
44
|
+
factory: Callable[[], Value] | Missing = MISSING,
|
45
|
+
) -> None:
|
46
|
+
assert ( # nosec: B101
|
47
|
+
value is MISSING or factory is MISSING
|
48
|
+
), "Can't specify both default value and factory"
|
49
|
+
|
50
|
+
self._value: Callable[[], Value | Missing]
|
51
|
+
if not_missing(factory):
|
52
|
+
object.__setattr__(
|
53
|
+
self,
|
54
|
+
"_value",
|
55
|
+
factory,
|
56
|
+
)
|
57
|
+
|
58
|
+
else:
|
59
|
+
object.__setattr__(
|
60
|
+
self,
|
61
|
+
"_value",
|
62
|
+
always(value),
|
63
|
+
)
|
64
|
+
|
65
|
+
def __call__(self) -> Value | Missing:
|
66
|
+
return self._value()
|
67
|
+
|
68
|
+
def __setattr__(
|
69
|
+
self,
|
70
|
+
__name: str,
|
71
|
+
__value: Any,
|
72
|
+
) -> None:
|
73
|
+
raise AttributeError("Missing can't be modified")
|
74
|
+
|
75
|
+
def __delattr__(
|
76
|
+
self,
|
77
|
+
__name: str,
|
78
|
+
) -> None:
|
79
|
+
raise AttributeError("Missing can't be modified")
|
80
|
+
|
81
|
+
|
82
|
+
@overload
|
83
|
+
def Default[Value](
|
84
|
+
value: Value,
|
85
|
+
/,
|
86
|
+
) -> Value: ...
|
87
|
+
|
88
|
+
|
89
|
+
@overload
|
90
|
+
def Default[Value](
|
91
|
+
*,
|
92
|
+
factory: Callable[[], Value],
|
93
|
+
) -> Value: ...
|
94
|
+
|
95
|
+
|
96
|
+
def Default[Value](
|
97
|
+
value: Value | Missing = MISSING,
|
98
|
+
/,
|
99
|
+
*,
|
100
|
+
factory: Callable[[], Value] | Missing = MISSING,
|
101
|
+
) -> Value: # it is actually a DefaultValue, but type checker has to be fooled most some cases
|
102
|
+
return cast(
|
103
|
+
Value,
|
104
|
+
DefaultValue(
|
105
|
+
value,
|
106
|
+
factory=factory,
|
107
|
+
),
|
108
|
+
)
|
@@ -1,18 +1,18 @@
|
|
1
1
|
from haiway.utils.always import always, async_always
|
2
|
+
from haiway.utils.collections import as_dict, as_list, as_set, as_tuple
|
2
3
|
from haiway.utils.env import getenv_bool, getenv_float, getenv_int, getenv_str, load_env
|
3
|
-
from haiway.utils.
|
4
|
+
from haiway.utils.freezing import freeze
|
4
5
|
from haiway.utils.logs import setup_logging
|
5
|
-
from haiway.utils.mappings import as_dict
|
6
6
|
from haiway.utils.mimic import mimic_function
|
7
7
|
from haiway.utils.noop import async_noop, noop
|
8
8
|
from haiway.utils.queue import AsyncQueue
|
9
|
-
from haiway.utils.sequences import as_list, as_tuple
|
10
9
|
|
11
10
|
__all__ = [
|
12
11
|
"AsyncQueue",
|
13
12
|
"always",
|
14
13
|
"as_dict",
|
15
14
|
"as_list",
|
15
|
+
"as_set",
|
16
16
|
"as_tuple",
|
17
17
|
"async_always",
|
18
18
|
"async_noop",
|
@@ -0,0 +1,108 @@
|
|
1
|
+
from collections.abc import Mapping, Sequence, Set
|
2
|
+
|
3
|
+
__all__ = [
|
4
|
+
"as_dict",
|
5
|
+
"as_list",
|
6
|
+
"as_set",
|
7
|
+
"as_tuple",
|
8
|
+
]
|
9
|
+
|
10
|
+
|
11
|
+
def as_list[T](
|
12
|
+
collection: Sequence[T],
|
13
|
+
/,
|
14
|
+
) -> list[T]:
|
15
|
+
"""
|
16
|
+
Converts any given Sequence into a list.
|
17
|
+
|
18
|
+
Parameters
|
19
|
+
----------
|
20
|
+
collection : Sequence[T]
|
21
|
+
The input collection to be converted.
|
22
|
+
|
23
|
+
Returns
|
24
|
+
-------
|
25
|
+
list[T]
|
26
|
+
A new list containing all elements of the input collection,
|
27
|
+
or the original list if it was already one.
|
28
|
+
"""
|
29
|
+
if isinstance(collection, list):
|
30
|
+
return collection
|
31
|
+
|
32
|
+
else:
|
33
|
+
return list(collection)
|
34
|
+
|
35
|
+
|
36
|
+
def as_tuple[T](
|
37
|
+
collection: Sequence[T],
|
38
|
+
/,
|
39
|
+
) -> tuple[T, ...]:
|
40
|
+
"""
|
41
|
+
Converts any given Sequence into a tuple.
|
42
|
+
|
43
|
+
Parameters
|
44
|
+
----------
|
45
|
+
collection : Sequence[T]
|
46
|
+
The input collection to be converted.
|
47
|
+
|
48
|
+
Returns
|
49
|
+
-------
|
50
|
+
tuple[T]
|
51
|
+
A new tuple containing all elements of the input collection,
|
52
|
+
or the original tuple if it was already one.
|
53
|
+
"""
|
54
|
+
if isinstance(collection, tuple):
|
55
|
+
return collection
|
56
|
+
|
57
|
+
else:
|
58
|
+
return tuple(collection)
|
59
|
+
|
60
|
+
|
61
|
+
def as_set[T](
|
62
|
+
collection: Set[T],
|
63
|
+
/,
|
64
|
+
) -> set[T]:
|
65
|
+
"""
|
66
|
+
Converts any given Set into a set.
|
67
|
+
|
68
|
+
Parameters
|
69
|
+
----------
|
70
|
+
collection : Set[T]
|
71
|
+
The input collection to be converted.
|
72
|
+
|
73
|
+
Returns
|
74
|
+
-------
|
75
|
+
set[T]
|
76
|
+
A new set containing all elements of the input collection,
|
77
|
+
or the original set if it was already one.
|
78
|
+
"""
|
79
|
+
if isinstance(collection, set):
|
80
|
+
return collection
|
81
|
+
|
82
|
+
else:
|
83
|
+
return set(collection)
|
84
|
+
|
85
|
+
|
86
|
+
def as_dict[K, V](
|
87
|
+
collection: Mapping[K, V],
|
88
|
+
/,
|
89
|
+
) -> dict[K, V]:
|
90
|
+
"""
|
91
|
+
Converts any given Mapping into a dict.
|
92
|
+
|
93
|
+
Parameters
|
94
|
+
----------
|
95
|
+
collection : Mapping[K, V]
|
96
|
+
The input collection to be converted.
|
97
|
+
|
98
|
+
Returns
|
99
|
+
-------
|
100
|
+
dict[K, V]
|
101
|
+
A new dict containing all elements of the input collection,
|
102
|
+
or the original dict if it was already one.
|
103
|
+
"""
|
104
|
+
if isinstance(collection, dict):
|
105
|
+
return collection
|
106
|
+
|
107
|
+
else:
|
108
|
+
return dict(collection)
|
@@ -32,18 +32,18 @@ src/haiway/state/requirement.py
|
|
32
32
|
src/haiway/state/structure.py
|
33
33
|
src/haiway/state/validation.py
|
34
34
|
src/haiway/types/__init__.py
|
35
|
+
src/haiway/types/default.py
|
35
36
|
src/haiway/types/frozen.py
|
36
37
|
src/haiway/types/missing.py
|
37
38
|
src/haiway/utils/__init__.py
|
38
39
|
src/haiway/utils/always.py
|
40
|
+
src/haiway/utils/collections.py
|
39
41
|
src/haiway/utils/env.py
|
40
|
-
src/haiway/utils/
|
42
|
+
src/haiway/utils/freezing.py
|
41
43
|
src/haiway/utils/logs.py
|
42
|
-
src/haiway/utils/mappings.py
|
43
44
|
src/haiway/utils/mimic.py
|
44
45
|
src/haiway/utils/noop.py
|
45
46
|
src/haiway/utils/queue.py
|
46
|
-
src/haiway/utils/sequences.py
|
47
47
|
tests/test_async_queue.py
|
48
48
|
tests/test_attribute_path.py
|
49
49
|
tests/test_auto_retry.py
|
@@ -0,0 +1 @@
|
|
1
|
+
haiway
|
@@ -7,7 +7,7 @@ from uuid import UUID, uuid4
|
|
7
7
|
|
8
8
|
from pytest import raises
|
9
9
|
|
10
|
-
from haiway import MISSING, Missing, State, frozenlist
|
10
|
+
from haiway import MISSING, Default, Missing, State, frozenlist
|
11
11
|
|
12
12
|
|
13
13
|
def test_basic_initializes_with_arguments() -> None:
|
@@ -92,11 +92,15 @@ def test_basic_initializes_with_defaults() -> None:
|
|
92
92
|
string: str = ""
|
93
93
|
integer: int = 0
|
94
94
|
optional: str | None = None
|
95
|
+
unique: UUID = Default(factory=uuid4)
|
96
|
+
same: UUID = Default(uuid4())
|
95
97
|
|
96
98
|
basic = Basics()
|
97
99
|
assert basic.string == ""
|
98
100
|
assert basic.integer == 0
|
99
101
|
assert basic.optional is None
|
102
|
+
assert basic.unique is not Basics().unique
|
103
|
+
assert basic.same is Basics().same
|
100
104
|
|
101
105
|
|
102
106
|
def test_basic_equals_checks_properties() -> None:
|
@@ -1,30 +0,0 @@
|
|
1
|
-
from collections.abc import Mapping
|
2
|
-
|
3
|
-
__all__ = [
|
4
|
-
"as_dict",
|
5
|
-
]
|
6
|
-
|
7
|
-
|
8
|
-
def as_dict[K, V](
|
9
|
-
mapping: Mapping[K, V],
|
10
|
-
/,
|
11
|
-
) -> dict[K, V]:
|
12
|
-
"""
|
13
|
-
Converts any given mapping into a dict.
|
14
|
-
|
15
|
-
Parameters
|
16
|
-
----------
|
17
|
-
mapping : Mapping[K, V]
|
18
|
-
The input mapping to be converted.
|
19
|
-
|
20
|
-
Returns
|
21
|
-
-------
|
22
|
-
dict[K, V]
|
23
|
-
A new dict containing all elements of the input mapping,
|
24
|
-
or the original dict if it was already one.
|
25
|
-
"""
|
26
|
-
if isinstance(mapping, dict):
|
27
|
-
return mapping
|
28
|
-
|
29
|
-
else:
|
30
|
-
return dict(mapping)
|
@@ -1,56 +0,0 @@
|
|
1
|
-
from collections.abc import Sequence
|
2
|
-
|
3
|
-
__all__ = [
|
4
|
-
"as_list",
|
5
|
-
"as_tuple",
|
6
|
-
]
|
7
|
-
|
8
|
-
|
9
|
-
def as_list[T](
|
10
|
-
sequence: Sequence[T],
|
11
|
-
/,
|
12
|
-
) -> list[T]:
|
13
|
-
"""
|
14
|
-
Converts any given sequence into a list.
|
15
|
-
|
16
|
-
Parameters
|
17
|
-
----------
|
18
|
-
sequence : Sequence[T]
|
19
|
-
The input sequence to be converted.
|
20
|
-
|
21
|
-
Returns
|
22
|
-
-------
|
23
|
-
list[T]
|
24
|
-
A new list containing all elements of the input sequence,
|
25
|
-
or the original list if it was already one.
|
26
|
-
"""
|
27
|
-
if isinstance(sequence, list):
|
28
|
-
return sequence
|
29
|
-
|
30
|
-
else:
|
31
|
-
return list(sequence)
|
32
|
-
|
33
|
-
|
34
|
-
def as_tuple[T](
|
35
|
-
sequence: Sequence[T],
|
36
|
-
/,
|
37
|
-
) -> tuple[T, ...]:
|
38
|
-
"""
|
39
|
-
Converts any given sequence into a tuple.
|
40
|
-
|
41
|
-
Parameters
|
42
|
-
----------
|
43
|
-
sequence : Sequence[T]
|
44
|
-
The input sequence to be converted.
|
45
|
-
|
46
|
-
Returns
|
47
|
-
-------
|
48
|
-
tuple[T]
|
49
|
-
A new tuple containing all elements of the input sequence,
|
50
|
-
or the original tuple if it was already one.
|
51
|
-
"""
|
52
|
-
if isinstance(sequence, tuple):
|
53
|
-
return sequence
|
54
|
-
|
55
|
-
else:
|
56
|
-
return tuple(sequence)
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|