haiway 0.6.4__py3-none-any.whl → 0.7.1__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/state/structure.py CHANGED
@@ -1,4 +1,5 @@
1
- from collections.abc import Callable
1
+ import typing
2
+ from collections.abc import Mapping
2
3
  from copy import deepcopy
3
4
  from types import EllipsisType, GenericAlias
4
5
  from typing import (
@@ -10,13 +11,15 @@ from typing import (
10
11
  cast,
11
12
  dataclass_transform,
12
13
  final,
13
- get_origin,
14
14
  )
15
15
  from weakref import WeakValueDictionary
16
16
 
17
17
  from haiway.state.attributes import AttributeAnnotation, attribute_annotations
18
18
  from haiway.state.path import AttributePath
19
- from haiway.state.validation import attribute_validator
19
+ from haiway.state.validation import (
20
+ AttributeValidation,
21
+ AttributeValidator,
22
+ )
20
23
  from haiway.types import MISSING, Missing, not_missing
21
24
 
22
25
  __all__ = [
@@ -28,13 +31,15 @@ __all__ = [
28
31
  class StateAttribute[Value]:
29
32
  def __init__(
30
33
  self,
34
+ name: str,
31
35
  annotation: AttributeAnnotation,
32
36
  default: Value | Missing,
33
- validator: Callable[[Any], Value],
37
+ validator: AttributeValidation[Value],
34
38
  ) -> None:
39
+ self.name: str = name
35
40
  self.annotation: AttributeAnnotation = annotation
36
41
  self.default: Value | Missing = default
37
- self.validator: Callable[[Any], Value] = validator
42
+ self.validator: AttributeValidation[Value] = validator
38
43
 
39
44
  def validated(
40
45
  self,
@@ -69,28 +74,119 @@ class StateMeta(type):
69
74
 
70
75
  attributes: dict[str, StateAttribute[Any]] = {}
71
76
 
72
- if bases: # handle base class
73
- for key, annotation in attribute_annotations(
74
- state_type,
75
- type_parameters=type_parameters,
76
- ).items():
77
- # do not include ClassVars and dunder items
78
- if ((get_origin(annotation) or annotation) is ClassVar) or key.startswith("__"):
79
- continue
80
-
81
- attributes[key] = StateAttribute(
82
- annotation=annotation,
83
- default=getattr(state_type, key, MISSING),
84
- validator=attribute_validator(annotation),
85
- )
77
+ for key, annotation in attribute_annotations(
78
+ state_type,
79
+ type_parameters=type_parameters or {},
80
+ ).items():
81
+ default: Any = getattr(state_type, key, MISSING)
82
+ attributes[key] = StateAttribute(
83
+ name=key,
84
+ annotation=annotation.update_required(default is MISSING),
85
+ default=default,
86
+ validator=AttributeValidator.of(
87
+ annotation,
88
+ recursion_guard={
89
+ str(AttributeAnnotation(origin=state_type)): state_type.validator
90
+ },
91
+ ),
92
+ )
86
93
 
94
+ state_type.__PARAMETERS__ = type_parameters # pyright: ignore[reportAttributeAccessIssue]
87
95
  state_type.__ATTRIBUTES__ = attributes # pyright: ignore[reportAttributeAccessIssue]
88
96
  state_type.__slots__ = frozenset(attributes.keys()) # pyright: ignore[reportAttributeAccessIssue]
89
97
  state_type.__match_args__ = state_type.__slots__ # pyright: ignore[reportAttributeAccessIssue]
90
- state_type._ = AttributePath(state_type, attribute=state_type) # pyright: ignore[reportUnknownMemberType, reportAttributeAccessIssue]
98
+ state_type._ = AttributePath(state_type, attribute=state_type) # pyright: ignore[reportCallIssue, reportUnknownMemberType, reportAttributeAccessIssue]
91
99
 
92
100
  return state_type
93
101
 
102
+ def validator(
103
+ cls,
104
+ value: Any,
105
+ /,
106
+ ) -> Any: ...
107
+
108
+ def __instancecheck__(
109
+ self,
110
+ instance: Any,
111
+ ) -> bool:
112
+ # check for type match
113
+ if self.__subclasscheck__(type(instance)): # pyright: ignore[reportUnknownArgumentType]
114
+ return True
115
+
116
+ # otherwise check if we are dealing with unparametrized base
117
+ # against the parametrized one, our generic subtypes have base of unparametrized type
118
+ if type(instance) not in self.__bases__:
119
+ return False
120
+
121
+ try:
122
+ # validate instance to check unparametrized fields
123
+ _ = self(**vars(instance))
124
+
125
+ except Exception:
126
+ return False
127
+
128
+ else:
129
+ return True
130
+
131
+ def __subclasscheck__( # noqa: C901, PLR0911, PLR0912
132
+ self,
133
+ subclass: type[Any],
134
+ ) -> bool:
135
+ # check if we are the same class for early exit
136
+ if self == subclass:
137
+ return True
138
+
139
+ # then check if we are parametrized
140
+ checked_parameters: Mapping[str, Any] | None = getattr(
141
+ self,
142
+ "__PARAMETERS__",
143
+ None,
144
+ )
145
+ if checked_parameters is None:
146
+ # if we are not parametrized allow any subclass
147
+ return self in subclass.__bases__
148
+
149
+ # verify if we have common base next - our generic subtypes have the same base
150
+ if self.__bases__ == subclass.__bases__:
151
+ # if we have the same bases we have different generic subtypes
152
+ # we can verify all of the attributes to check if we have common base
153
+ available_parameters: Mapping[str, Any] | None = getattr(
154
+ subclass,
155
+ "__PARAMETERS__",
156
+ None,
157
+ )
158
+
159
+ if available_parameters is None:
160
+ # if we have no parameters at this stage this is a serious bug
161
+ raise RuntimeError("Invalid type parametrization for %s", subclass)
162
+
163
+ for key, param in checked_parameters.items():
164
+ match available_parameters.get(key):
165
+ case None: # if any parameter is missing we should not be there already
166
+ return False
167
+
168
+ case typing.Any:
169
+ continue # Any ignores type checks
170
+
171
+ case checked:
172
+ if param is Any:
173
+ continue # Any ignores type checks
174
+
175
+ elif issubclass(checked, param):
176
+ continue # if we have matching type we are fine
177
+
178
+ else:
179
+ return False # types are not matching
180
+
181
+ return True # when all parameters were matching we have matching subclass
182
+
183
+ elif subclass in self.__bases__: # our generic subtypes have base of unparametrized type
184
+ # if subclass parameters were not provided then we can be valid ony if all were Any
185
+ return all(param is Any for param in checked_parameters.values())
186
+
187
+ else:
188
+ return False # we have different base / comparing to not parametrized
189
+
94
190
 
95
191
  _types_cache: WeakValueDictionary[
96
192
  tuple[
@@ -108,13 +204,16 @@ class State(metaclass=StateMeta):
108
204
 
109
205
  _: ClassVar[Self]
110
206
  __IMMUTABLE__: ClassVar[EllipsisType] = ...
207
+ __PARAMETERS__: ClassVar[Mapping[str, Any] | None] = None
111
208
  __ATTRIBUTES__: ClassVar[dict[str, StateAttribute[Any]]]
112
209
 
210
+ @classmethod
113
211
  def __class_getitem__(
114
212
  cls,
115
213
  type_argument: tuple[type[Any], ...] | type[Any],
116
214
  ) -> type[Self]:
117
215
  assert Generic in cls.__bases__, "Can't specialize non generic type!" # nosec: B101
216
+ assert cls.__PARAMETERS__ is None, "Can't specialize already specialized type!" # nosec: B101
118
217
 
119
218
  type_arguments: tuple[type[Any], ...]
120
219
  match type_argument:
@@ -165,6 +264,22 @@ class State(metaclass=StateMeta):
165
264
  _types_cache[(cls, type_arguments)] = parametrized_type
166
265
  return parametrized_type
167
266
 
267
+ @classmethod
268
+ def validator(
269
+ cls,
270
+ value: Any,
271
+ /,
272
+ ) -> Self:
273
+ match value:
274
+ case validated if isinstance(validated, cls):
275
+ return validated
276
+
277
+ case {**values}:
278
+ return cls(**values)
279
+
280
+ case _:
281
+ raise TypeError(f"Expected '{cls.__name__}', received '{type(value).__name__}'")
282
+
168
283
  def __init__(
169
284
  self,
170
285
  **kwargs: Any,
@@ -1,10 +1,10 @@
1
- from collections.abc import Callable, Mapping, Sequence, Set
1
+ from collections.abc import Callable, Mapping, MutableMapping, Sequence, Set
2
2
  from datetime import date, datetime, time, timedelta, timezone
3
3
  from enum import Enum
4
4
  from pathlib import Path
5
5
  from re import Pattern
6
- from types import MappingProxyType, NoneType, UnionType
7
- from typing import Any, Literal, Protocol, Union
6
+ from types import EllipsisType, NoneType, UnionType
7
+ from typing import Any, Literal, Protocol, Self, Union, is_typeddict
8
8
  from typing import Mapping as MappingType # noqa: UP035
9
9
  from typing import Sequence as SequenceType # noqa: UP035
10
10
  from typing import Sequence as SetType # noqa: UP035
@@ -14,36 +14,90 @@ from haiway.state.attributes import AttributeAnnotation
14
14
  from haiway.types import MISSING, Missing
15
15
 
16
16
  __all__ = [
17
- "attribute_validator",
17
+ "AttributeValidation",
18
+ "AttributeValidationError",
19
+ "AttributeValidator",
18
20
  ]
19
21
 
20
22
 
21
- def attribute_validator(
22
- annotation: AttributeAnnotation,
23
- /,
24
- ) -> Callable[[Any], Any]:
25
- if validator := VALIDATORS.get(annotation.origin):
26
- return validator(annotation)
23
+ class AttributeValidation[Type](Protocol):
24
+ def __call__(
25
+ self,
26
+ value: Any,
27
+ /,
28
+ ) -> Type: ...
27
29
 
28
- elif hasattr(annotation.origin, "__IMMUTABLE__"):
29
- return _prepare_validator_of_type(annotation)
30
30
 
31
- elif issubclass(annotation.origin, Protocol):
32
- return _prepare_validator_of_type(annotation)
31
+ class AttributeValidationError(Exception):
32
+ pass
33
33
 
34
- elif issubclass(annotation.origin, Enum):
35
- return _prepare_validator_of_type(annotation)
36
34
 
37
- else:
38
- raise TypeError(f"Unsupported type annotation: {annotation}")
35
+ class AttributeValidator[Type]:
36
+ @classmethod
37
+ def of(
38
+ cls,
39
+ annotation: AttributeAnnotation,
40
+ /,
41
+ *,
42
+ recursion_guard: MutableMapping[str, AttributeValidation[Any]],
43
+ ) -> AttributeValidation[Any]:
44
+ if isinstance(annotation.origin, NotImplementedError | RuntimeError):
45
+ raise annotation.origin # raise an error if origin was not properly resolved
46
+
47
+ if recursive := recursion_guard.get(str(annotation)):
48
+ return recursive
49
+
50
+ validator: Self = cls(
51
+ annotation,
52
+ validation=MISSING,
53
+ )
54
+ recursion_guard[str(annotation)] = validator
55
+
56
+ if common := VALIDATORS.get(annotation.origin):
57
+ validator.validation = common(annotation, recursion_guard)
58
+
59
+ elif hasattr(annotation.origin, "__IMMUTABLE__"):
60
+ validator.validation = _prepare_validator_of_type(annotation, recursion_guard)
61
+
62
+ elif is_typeddict(annotation.origin):
63
+ validator.validation = _prepare_validator_of_typed_dict(annotation, recursion_guard)
64
+
65
+ elif issubclass(annotation.origin, Protocol):
66
+ validator.validation = _prepare_validator_of_type(annotation, recursion_guard)
67
+
68
+ elif issubclass(annotation.origin, Enum):
69
+ validator.validation = _prepare_validator_of_type(annotation, recursion_guard)
70
+
71
+ else:
72
+ raise TypeError(f"Unsupported type annotation: {annotation}")
73
+
74
+ return validator
75
+
76
+ def __init__(
77
+ self,
78
+ annotation: AttributeAnnotation,
79
+ validation: AttributeValidation[Type] | Missing,
80
+ ) -> None:
81
+ self.annotation: AttributeAnnotation = annotation
82
+ self.validation: AttributeValidation[Type] | Missing = validation
83
+
84
+ def __call__(
85
+ self,
86
+ value: Any,
87
+ /,
88
+ ) -> Any:
89
+ assert self.validation is not MISSING # nosec: B101
90
+ return self.validation(value) # pyright: ignore[reportCallIssue, reportUnknownVariableType]
39
91
 
40
92
 
41
93
  def _prepare_validator_of_any(
42
94
  annotation: AttributeAnnotation,
43
95
  /,
44
- ) -> Callable[[Any], Any]:
96
+ recursion_guard: MutableMapping[str, AttributeValidation[Any]],
97
+ ) -> AttributeValidation[Any]:
45
98
  def validator(
46
99
  value: Any,
100
+ /,
47
101
  ) -> Any:
48
102
  return value # any is always valid
49
103
 
@@ -53,9 +107,11 @@ def _prepare_validator_of_any(
53
107
  def _prepare_validator_of_none(
54
108
  annotation: AttributeAnnotation,
55
109
  /,
56
- ) -> Callable[[Any], Any]:
110
+ recursion_guard: MutableMapping[str, AttributeValidation[Any]],
111
+ ) -> AttributeValidation[Any]:
57
112
  def validator(
58
113
  value: Any,
114
+ /,
59
115
  ) -> Any:
60
116
  if value is None:
61
117
  return value
@@ -69,9 +125,11 @@ def _prepare_validator_of_none(
69
125
  def _prepare_validator_of_missing(
70
126
  annotation: AttributeAnnotation,
71
127
  /,
72
- ) -> Callable[[Any], Any]:
128
+ recursion_guard: MutableMapping[str, AttributeValidation[Any]],
129
+ ) -> AttributeValidation[Any]:
73
130
  def validator(
74
131
  value: Any,
132
+ /,
75
133
  ) -> Any:
76
134
  if value is MISSING:
77
135
  return value
@@ -85,12 +143,14 @@ def _prepare_validator_of_missing(
85
143
  def _prepare_validator_of_literal(
86
144
  annotation: AttributeAnnotation,
87
145
  /,
88
- ) -> Callable[[Any], Any]:
89
- elements: list[Any] = annotation.arguments
146
+ recursion_guard: MutableMapping[str, AttributeValidation[Any]],
147
+ ) -> AttributeValidation[Any]:
148
+ elements: Sequence[Any] = annotation.arguments
90
149
  formatted_type: str = str(annotation)
91
150
 
92
151
  def validator(
93
152
  value: Any,
153
+ /,
94
154
  ) -> Any:
95
155
  if value in elements:
96
156
  return value
@@ -104,12 +164,14 @@ def _prepare_validator_of_literal(
104
164
  def _prepare_validator_of_type(
105
165
  annotation: AttributeAnnotation,
106
166
  /,
107
- ) -> Callable[[Any], Any]:
167
+ recursion_guard: MutableMapping[str, AttributeValidation[Any]],
168
+ ) -> AttributeValidation[Any]:
108
169
  validated_type: type[Any] = annotation.origin
109
170
  formatted_type: str = str(annotation)
110
171
 
111
- def type_validator(
172
+ def validator(
112
173
  value: Any,
174
+ /,
113
175
  ) -> Any:
114
176
  match value:
115
177
  case value if isinstance(value, validated_type):
@@ -118,18 +180,23 @@ def _prepare_validator_of_type(
118
180
  case _:
119
181
  raise TypeError(f"'{value}' is not matching expected type of '{formatted_type}'")
120
182
 
121
- return type_validator
183
+ return validator
122
184
 
123
185
 
124
186
  def _prepare_validator_of_set(
125
187
  annotation: AttributeAnnotation,
126
188
  /,
127
- ) -> Callable[[Any], Any]:
128
- element_validator: Callable[[Any], Any] = attribute_validator(annotation.arguments[0])
189
+ recursion_guard: MutableMapping[str, AttributeValidation[Any]],
190
+ ) -> AttributeValidation[Any]:
191
+ element_validator: AttributeValidation[Any] = AttributeValidator.of(
192
+ annotation.arguments[0],
193
+ recursion_guard=recursion_guard,
194
+ )
129
195
  formatted_type: str = str(annotation)
130
196
 
131
197
  def validator(
132
198
  value: Any,
199
+ /,
133
200
  ) -> Any:
134
201
  if isinstance(value, set):
135
202
  return frozenset(element_validator(element) for element in value) # pyright: ignore[reportUnknownVariableType]
@@ -143,12 +210,17 @@ def _prepare_validator_of_set(
143
210
  def _prepare_validator_of_sequence(
144
211
  annotation: AttributeAnnotation,
145
212
  /,
146
- ) -> Callable[[Any], Any]:
147
- element_validator: Callable[[Any], Any] = attribute_validator(annotation.arguments[0])
213
+ recursion_guard: MutableMapping[str, AttributeValidation[Any]],
214
+ ) -> AttributeValidation[Any]:
215
+ element_validator: AttributeValidation[Any] = AttributeValidator.of(
216
+ annotation.arguments[0],
217
+ recursion_guard=recursion_guard,
218
+ )
148
219
  formatted_type: str = str(annotation)
149
220
 
150
221
  def validator(
151
222
  value: Any,
223
+ /,
152
224
  ) -> Any:
153
225
  match value:
154
226
  case [*elements]:
@@ -163,19 +235,29 @@ def _prepare_validator_of_sequence(
163
235
  def _prepare_validator_of_mapping(
164
236
  annotation: AttributeAnnotation,
165
237
  /,
166
- ) -> Callable[[Any], Any]:
167
- key_validator: Callable[[Any], Any] = attribute_validator(annotation.arguments[0])
168
- value_validator: Callable[[Any], Any] = attribute_validator(annotation.arguments[1])
238
+ recursion_guard: MutableMapping[str, AttributeValidation[Any]],
239
+ ) -> AttributeValidation[Any]:
240
+ key_validator: AttributeValidation[Any] = AttributeValidator.of(
241
+ annotation.arguments[0],
242
+ recursion_guard=recursion_guard,
243
+ )
244
+ value_validator: AttributeValidation[Any] = AttributeValidator.of(
245
+ annotation.arguments[1],
246
+ recursion_guard=recursion_guard,
247
+ )
169
248
  formatted_type: str = str(annotation)
170
249
 
171
250
  def validator(
172
251
  value: Any,
252
+ /,
173
253
  ) -> Any:
174
254
  match value:
175
255
  case {**elements}:
176
- return MappingProxyType(
177
- {key_validator(key): value_validator(value) for key, value in elements.items()}
178
- )
256
+ # TODO: make sure dict is not mutable with MappingProxyType?
257
+ return {
258
+ key_validator(key): value_validator(element)
259
+ for key, element in elements.items()
260
+ }
179
261
 
180
262
  case _:
181
263
  raise TypeError(f"'{value}' is not matching expected type of '{formatted_type}'")
@@ -186,13 +268,21 @@ def _prepare_validator_of_mapping(
186
268
  def _prepare_validator_of_tuple(
187
269
  annotation: AttributeAnnotation,
188
270
  /,
189
- ) -> Callable[[Any], Any]:
190
- if annotation.arguments[-1].origin == Ellipsis:
191
- element_validator: Callable[[Any], Any] = attribute_validator(annotation.arguments[0])
271
+ recursion_guard: MutableMapping[str, AttributeValidation[Any]],
272
+ ) -> AttributeValidation[Any]:
273
+ if (
274
+ annotation.arguments[-1].origin == Ellipsis
275
+ or annotation.arguments[-1].origin == EllipsisType
276
+ ):
277
+ element_validator: AttributeValidation[Any] = AttributeValidator.of(
278
+ annotation.arguments[0],
279
+ recursion_guard=recursion_guard,
280
+ )
192
281
  formatted_type: str = str(annotation)
193
282
 
194
283
  def validator(
195
284
  value: Any,
285
+ /,
196
286
  ) -> Any:
197
287
  match value:
198
288
  case [*elements]:
@@ -206,14 +296,16 @@ def _prepare_validator_of_tuple(
206
296
  return validator
207
297
 
208
298
  else:
209
- element_validators: list[Callable[[Any], Any]] = [
210
- attribute_validator(alternative) for alternative in annotation.arguments
299
+ element_validators: list[AttributeValidation[Any]] = [
300
+ AttributeValidator.of(alternative, recursion_guard=recursion_guard)
301
+ for alternative in annotation.arguments
211
302
  ]
212
303
  elements_count: int = len(element_validators)
213
304
  formatted_type: str = str(annotation)
214
305
 
215
306
  def validator(
216
307
  value: Any,
308
+ /,
217
309
  ) -> Any:
218
310
  match value:
219
311
  case [*elements]:
@@ -223,7 +315,7 @@ def _prepare_validator_of_tuple(
223
315
  )
224
316
 
225
317
  return tuple(
226
- element_validators[idx](value) for idx, value in enumerate(elements)
318
+ element_validators[idx](element) for idx, element in enumerate(elements)
227
319
  )
228
320
 
229
321
  case _:
@@ -237,14 +329,17 @@ def _prepare_validator_of_tuple(
237
329
  def _prepare_validator_of_union(
238
330
  annotation: AttributeAnnotation,
239
331
  /,
240
- ) -> Callable[[Any], Any]:
241
- validators: list[Callable[[Any], Any]] = [
242
- attribute_validator(alternative) for alternative in annotation.arguments
332
+ recursion_guard: MutableMapping[str, AttributeValidation[Any]],
333
+ ) -> AttributeValidation[Any]:
334
+ validators: list[AttributeValidation[Any]] = [
335
+ AttributeValidator.of(alternative, recursion_guard=recursion_guard)
336
+ for alternative in annotation.arguments
243
337
  ]
244
338
  formatted_type: str = str(annotation)
245
339
 
246
340
  def validator(
247
341
  value: Any,
342
+ /,
248
343
  ) -> Any:
249
344
  errors: list[Exception] = []
250
345
  for validator in validators:
@@ -265,13 +360,16 @@ def _prepare_validator_of_union(
265
360
  def _prepare_validator_of_callable(
266
361
  annotation: AttributeAnnotation,
267
362
  /,
268
- ) -> Callable[[Any], Any]:
363
+ recursion_guard: MutableMapping[str, AttributeValidation[Any]],
364
+ ) -> AttributeValidation[Any]:
269
365
  formatted_type: str = str(annotation)
270
366
 
271
367
  def validator(
272
368
  value: Any,
369
+ /,
273
370
  ) -> Any:
274
371
  if callable(value):
372
+ # TODO: we could verify callable signature here
275
373
  return value
276
374
 
277
375
  else:
@@ -280,7 +378,59 @@ def _prepare_validator_of_callable(
280
378
  return validator
281
379
 
282
380
 
283
- VALIDATORS: Mapping[Any, Callable[[AttributeAnnotation], Callable[[Any], Any]]] = {
381
+ def _prepare_validator_of_typed_dict(
382
+ annotation: AttributeAnnotation,
383
+ /,
384
+ recursion_guard: MutableMapping[str, AttributeValidation[Any]],
385
+ ) -> AttributeValidation[Any]:
386
+ def key_validator(
387
+ value: Any,
388
+ /,
389
+ ) -> Any:
390
+ match value:
391
+ case value if isinstance(value, str):
392
+ return value
393
+
394
+ case _:
395
+ raise TypeError(f"'{value}' is not matching expected type of 'str'")
396
+
397
+ values_validators: dict[str, AttributeValidation[Any]] = {
398
+ key: AttributeValidator.of(element, recursion_guard=recursion_guard)
399
+ for key, element in annotation.extra.items()
400
+ }
401
+ formatted_type: str = str(annotation)
402
+
403
+ def validator(
404
+ value: Any,
405
+ /,
406
+ ) -> Any:
407
+ match value:
408
+ case {**elements}:
409
+ validated: MutableMapping[str, Any] = {}
410
+ for key, validator in values_validators.items():
411
+ element: Any = elements.get(key, MISSING)
412
+ if element is not MISSING:
413
+ validated[key_validator(key)] = validator(element)
414
+
415
+ # TODO: make sure dict is not mutable with MappingProxyType?
416
+ return validated
417
+
418
+ case _:
419
+ raise TypeError(f"'{value}' is not matching expected type of '{formatted_type}'")
420
+
421
+ return validator
422
+
423
+
424
+ VALIDATORS: Mapping[
425
+ Any,
426
+ Callable[
427
+ [
428
+ AttributeAnnotation,
429
+ MutableMapping[str, AttributeValidation[Any]],
430
+ ],
431
+ AttributeValidation[Any],
432
+ ],
433
+ ] = {
284
434
  Any: _prepare_validator_of_any,
285
435
  NoneType: _prepare_validator_of_none,
286
436
  Missing: _prepare_validator_of_missing,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: haiway
3
- Version: 0.6.4
3
+ Version: 0.7.1
4
4
  Summary: Framework for dependency injection and state management within structured concurrency model.
5
5
  Maintainer-email: Kacper Kaliński <kacper.kalinski@miquido.com>
6
6
  License: MIT License
@@ -15,11 +15,11 @@ haiway/helpers/throttling.py,sha256=zo0OwFq64si5KUwhd58cFHLmGAmYwRbFRJMbv9suhPs,
15
15
  haiway/helpers/timeouted.py,sha256=1xU09hQnFdj6p48BwZl5xUvtIr3zC0ZUXehkdrduCjs,3074
16
16
  haiway/helpers/tracing.py,sha256=eQpkIoGSB51jRF8RcLaihvHX3VzJIRdyRxTx3I14Pzg,3346
17
17
  haiway/state/__init__.py,sha256=emTuwGFn7HyjyTJ_ass69J5jQIA7_WHO4teZz_dR05Y,355
18
- haiway/state/attributes.py,sha256=OVUHp0_OwDwqJa-4Rk_diQhIpBYg0PW9APU3p_UTjd0,13635
18
+ haiway/state/attributes.py,sha256=iQ7TJHnT3hlcYwKcxchXE56zU8WbOTJZhsVn_HocXBc,22903
19
19
  haiway/state/path.py,sha256=4vh-fYQv8_xRWjS0ErMQslKDWRI6-KVECAr8JhYk0UY,17503
20
20
  haiway/state/requirement.py,sha256=3iQqzp5Q7w6y5uClamJGH7S5Hib9pciuTAV27PP5lS8,6161
21
- haiway/state/structure.py,sha256=_1K_RSqA20ufcMay6i2CthMkgJeF1gZi7Hr4rUiCJs0,7869
22
- haiway/state/validation.py,sha256=l3NHHYVEr1M9F3HrV4hXA1gCibp7Uj5_nZWXMuy2tsU,9089
21
+ haiway/state/structure.py,sha256=dqLXUJPnaQqdRxbNwtGgUqGNCA8EDPj16M3Ob_sEz5U,11837
22
+ haiway/state/validation.py,sha256=n5cHcJTbv3Zf-qs05yzuLJIMBReV_4yYVwcH6IL58N0,13836
23
23
  haiway/types/__init__.py,sha256=00Ulp2BxcIWm9vWXKQPodpFEwE8hpqj6OYgrNxelp5s,252
24
24
  haiway/types/frozen.py,sha256=CZhFCXnWAKEhuWSfILxA8smfdpMd5Ku694ycfLh98R8,76
25
25
  haiway/types/missing.py,sha256=JiXo5xdi7H-PbIJr0fuK5wpOuQZhjrDYUkMlfIFcsaE,1705
@@ -31,8 +31,8 @@ haiway/utils/logs.py,sha256=oDsc1ZdqKDjlTlctLbDcp9iX98Acr-1tdw-Pyg3DElo,1577
31
31
  haiway/utils/mimic.py,sha256=BkVjTVP2TxxC8GChPGyDV6UXVwJmiRiSWeOYZNZFHxs,1828
32
32
  haiway/utils/noop.py,sha256=qgbZlOKWY6_23Zs43OLukK2HagIQKRyR04zrFVm5rWI,344
33
33
  haiway/utils/queue.py,sha256=oQ3GXCJ-PGNtMEr6EPdgqAvYZoj8lAa7Z2drBKBEoBM,2345
34
- haiway-0.6.4.dist-info/LICENSE,sha256=GehQEW_I1pkmxkkj3NEa7rCTQKYBn7vTPabpDYJlRuo,1063
35
- haiway-0.6.4.dist-info/METADATA,sha256=Vx_AwXB2HZvP8BIN3EdA9l4gk7YdeILRy72qZ3yPgf8,3898
36
- haiway-0.6.4.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
37
- haiway-0.6.4.dist-info/top_level.txt,sha256=_LdXVLzUzgkvAGQnQJj5kQfoFhpPW6EF4Kj9NapniLg,7
38
- haiway-0.6.4.dist-info/RECORD,,
34
+ haiway-0.7.1.dist-info/LICENSE,sha256=GehQEW_I1pkmxkkj3NEa7rCTQKYBn7vTPabpDYJlRuo,1063
35
+ haiway-0.7.1.dist-info/METADATA,sha256=XacjUXNqPQaTSoCxEcqcOcGgjAGr6uxBguhLwrEaIMM,3898
36
+ haiway-0.7.1.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
37
+ haiway-0.7.1.dist-info/top_level.txt,sha256=_LdXVLzUzgkvAGQnQJj5kQfoFhpPW6EF4Kj9NapniLg,7
38
+ haiway-0.7.1.dist-info/RECORD,,
File without changes