haiway 0.8.0__tar.gz → 0.8.2__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.
Files changed (54) hide show
  1. {haiway-0.8.0/src/haiway.egg-info → haiway-0.8.2}/PKG-INFO +1 -1
  2. {haiway-0.8.0 → haiway-0.8.2}/pyproject.toml +1 -1
  3. {haiway-0.8.0 → haiway-0.8.2}/src/haiway/helpers/metrics.py +62 -53
  4. {haiway-0.8.0 → haiway-0.8.2/src/haiway.egg-info}/PKG-INFO +1 -1
  5. {haiway-0.8.0 → haiway-0.8.2}/tests/test_context.py +0 -1
  6. {haiway-0.8.0 → haiway-0.8.2}/LICENSE +0 -0
  7. {haiway-0.8.0 → haiway-0.8.2}/README.md +0 -0
  8. {haiway-0.8.0 → haiway-0.8.2}/setup.cfg +0 -0
  9. {haiway-0.8.0 → haiway-0.8.2}/src/haiway/__init__.py +0 -0
  10. {haiway-0.8.0 → haiway-0.8.2}/src/haiway/context/__init__.py +0 -0
  11. {haiway-0.8.0 → haiway-0.8.2}/src/haiway/context/access.py +0 -0
  12. {haiway-0.8.0 → haiway-0.8.2}/src/haiway/context/disposables.py +0 -0
  13. {haiway-0.8.0 → haiway-0.8.2}/src/haiway/context/identifier.py +0 -0
  14. {haiway-0.8.0 → haiway-0.8.2}/src/haiway/context/logging.py +0 -0
  15. {haiway-0.8.0 → haiway-0.8.2}/src/haiway/context/metrics.py +0 -0
  16. {haiway-0.8.0 → haiway-0.8.2}/src/haiway/context/state.py +0 -0
  17. {haiway-0.8.0 → haiway-0.8.2}/src/haiway/context/tasks.py +0 -0
  18. {haiway-0.8.0 → haiway-0.8.2}/src/haiway/context/types.py +0 -0
  19. {haiway-0.8.0 → haiway-0.8.2}/src/haiway/helpers/__init__.py +0 -0
  20. {haiway-0.8.0 → haiway-0.8.2}/src/haiway/helpers/asynchrony.py +0 -0
  21. {haiway-0.8.0 → haiway-0.8.2}/src/haiway/helpers/caching.py +0 -0
  22. {haiway-0.8.0 → haiway-0.8.2}/src/haiway/helpers/retries.py +0 -0
  23. {haiway-0.8.0 → haiway-0.8.2}/src/haiway/helpers/throttling.py +0 -0
  24. {haiway-0.8.0 → haiway-0.8.2}/src/haiway/helpers/timeouted.py +0 -0
  25. {haiway-0.8.0 → haiway-0.8.2}/src/haiway/helpers/tracing.py +0 -0
  26. {haiway-0.8.0 → haiway-0.8.2}/src/haiway/py.typed +0 -0
  27. {haiway-0.8.0 → haiway-0.8.2}/src/haiway/state/__init__.py +0 -0
  28. {haiway-0.8.0 → haiway-0.8.2}/src/haiway/state/attributes.py +0 -0
  29. {haiway-0.8.0 → haiway-0.8.2}/src/haiway/state/path.py +0 -0
  30. {haiway-0.8.0 → haiway-0.8.2}/src/haiway/state/requirement.py +0 -0
  31. {haiway-0.8.0 → haiway-0.8.2}/src/haiway/state/structure.py +0 -0
  32. {haiway-0.8.0 → haiway-0.8.2}/src/haiway/state/validation.py +0 -0
  33. {haiway-0.8.0 → haiway-0.8.2}/src/haiway/types/__init__.py +0 -0
  34. {haiway-0.8.0 → haiway-0.8.2}/src/haiway/types/frozen.py +0 -0
  35. {haiway-0.8.0 → haiway-0.8.2}/src/haiway/types/missing.py +0 -0
  36. {haiway-0.8.0 → haiway-0.8.2}/src/haiway/utils/__init__.py +0 -0
  37. {haiway-0.8.0 → haiway-0.8.2}/src/haiway/utils/always.py +0 -0
  38. {haiway-0.8.0 → haiway-0.8.2}/src/haiway/utils/env.py +0 -0
  39. {haiway-0.8.0 → haiway-0.8.2}/src/haiway/utils/immutable.py +0 -0
  40. {haiway-0.8.0 → haiway-0.8.2}/src/haiway/utils/logs.py +0 -0
  41. {haiway-0.8.0 → haiway-0.8.2}/src/haiway/utils/mimic.py +0 -0
  42. {haiway-0.8.0 → haiway-0.8.2}/src/haiway/utils/noop.py +0 -0
  43. {haiway-0.8.0 → haiway-0.8.2}/src/haiway/utils/queue.py +0 -0
  44. {haiway-0.8.0 → haiway-0.8.2}/src/haiway.egg-info/SOURCES.txt +0 -0
  45. {haiway-0.8.0 → haiway-0.8.2}/src/haiway.egg-info/dependency_links.txt +0 -0
  46. {haiway-0.8.0 → haiway-0.8.2}/src/haiway.egg-info/requires.txt +0 -0
  47. {haiway-0.8.0 → haiway-0.8.2}/src/haiway.egg-info/top_level.txt +0 -0
  48. {haiway-0.8.0 → haiway-0.8.2}/tests/test_async_queue.py +0 -0
  49. {haiway-0.8.0 → haiway-0.8.2}/tests/test_attribute_path.py +0 -0
  50. {haiway-0.8.0 → haiway-0.8.2}/tests/test_auto_retry.py +0 -0
  51. {haiway-0.8.0 → haiway-0.8.2}/tests/test_cache.py +0 -0
  52. {haiway-0.8.0 → haiway-0.8.2}/tests/test_state.py +0 -0
  53. {haiway-0.8.0 → haiway-0.8.2}/tests/test_streaming.py +0 -0
  54. {haiway-0.8.0 → haiway-0.8.2}/tests/test_timeout.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: haiway
3
- Version: 0.8.0
3
+ Version: 0.8.2
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
@@ -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.0"
8
+ version = "0.8.2"
9
9
  readme = "README.md"
10
10
  maintainers = [
11
11
  { name = "Kacper Kaliński", email = "kacper.kalinski@miquido.com" },
@@ -59,11 +59,11 @@ class MetricsLogger:
59
59
  def handler(
60
60
  cls,
61
61
  items_limit: int | None = None,
62
- item_character_limit: int | None = None,
62
+ redact_content: bool = False,
63
63
  ) -> MetricsHandler:
64
64
  logger_handler: Self = cls(
65
65
  items_limit=items_limit,
66
- item_character_limit=item_character_limit,
66
+ redact_content=redact_content,
67
67
  )
68
68
  return MetricsHandler(
69
69
  record=logger_handler.record,
@@ -73,11 +73,11 @@ class MetricsLogger:
73
73
 
74
74
  def __init__(
75
75
  self,
76
- items_limit: int | None = None,
77
- item_character_limit: int | None = None,
76
+ items_limit: int | None,
77
+ redact_content: bool,
78
78
  ) -> None:
79
79
  self.items_limit: int | None = items_limit
80
- self.item_character_limit: int | None = item_character_limit
80
+ self.redact_content: bool = redact_content
81
81
  self.scopes: dict[ScopeIdentifier, MetricsScopeStore] = {}
82
82
 
83
83
  def record(
@@ -93,13 +93,12 @@ class MetricsLogger:
93
93
  metrics[type(metric)] = current.__add__(metric) # pyright: ignore[reportUnknownMemberType, reportAttributeAccessIssue]
94
94
 
95
95
  metrics[type(metric)] = metric
96
- if __debug__:
97
- if log := _state_log(
98
- metric,
99
- list_items_limit=self.items_limit,
100
- item_character_limit=self.item_character_limit,
101
- ):
102
- ctx.log_info(f"Recorded:\n• {type(metric).__qualname__}:{log}")
96
+ if log := _state_log(
97
+ metric,
98
+ list_items_limit=self.items_limit,
99
+ redact_content=self.redact_content,
100
+ ):
101
+ ctx.log_debug(f"Recorded metric:\n⎡ {type(metric).__qualname__}:{log}\n⌊")
103
102
 
104
103
  def enter_scope[Metric: State](
105
104
  self,
@@ -107,7 +106,17 @@ class MetricsLogger:
107
106
  /,
108
107
  ) -> None:
109
108
  assert scope not in self.scopes # nosec: B101
110
- self.scopes[scope] = MetricsScopeStore(scope)
109
+ scope_metrics = MetricsScopeStore(scope)
110
+ self.scopes[scope] = scope_metrics
111
+ if not scope.is_root: # root scopes have no actual parent
112
+ for key in self.scopes.keys():
113
+ if key.scope_id == scope.parent_id:
114
+ self.scopes[key].nested.append(scope_metrics)
115
+ return
116
+
117
+ ctx.log_debug(
118
+ "Attempting to enter nested scope metrics without entering its parent first"
119
+ )
111
120
 
112
121
  def exit_scope[Metric: State](
113
122
  self,
@@ -117,22 +126,23 @@ class MetricsLogger:
117
126
  assert scope in self.scopes # nosec: B101
118
127
  self.scopes[scope].exited = monotonic()
119
128
 
120
- if __debug__:
121
- if scope.is_root and self.scopes[scope].finished:
122
- if log := _tree_log(
123
- self.scopes[scope],
124
- list_items_limit=self.items_limit,
125
- item_character_limit=self.item_character_limit,
126
- ):
127
- ctx.log_info(log)
129
+ if scope.is_root and self.scopes[scope].finished:
130
+ if log := _tree_log(
131
+ self.scopes[scope],
132
+ list_items_limit=self.items_limit,
133
+ redact_content=self.redact_content,
134
+ ):
135
+ ctx.log_debug(f"Metrics summary:\n{log}")
128
136
 
129
137
 
130
138
  def _tree_log(
131
139
  metrics: MetricsScopeStore,
132
140
  list_items_limit: int | None,
133
- item_character_limit: int | None,
141
+ redact_content: bool,
134
142
  ) -> str:
135
- log: str = f"@{metrics.identifier}({metrics.time:.2f}s):"
143
+ log: str = (
144
+ f"⎡ @{metrics.identifier.label} [{metrics.identifier.scope_id}]({metrics.time:.2f}s):"
145
+ )
136
146
 
137
147
  for metric in metrics.merged():
138
148
  metric_log: str = ""
@@ -140,52 +150,52 @@ def _tree_log(
140
150
  if value_log := _value_log(
141
151
  value,
142
152
  list_items_limit=list_items_limit,
143
- item_character_limit=item_character_limit,
153
+ redact_content=redact_content,
144
154
  ):
145
- metric_log += f"\n| + {key}: {value_log}"
155
+ metric_log += f"\n {key}: {value_log}"
146
156
 
147
157
  else:
148
- continue # skip missing values
158
+ continue # skip empty values
149
159
 
150
160
  if not metric_log:
151
161
  continue # skip empty logs
152
162
 
153
- log += f"\n• {type(metric).__qualname__}:{metric_log}"
163
+ log += f"\n•{type(metric).__qualname__}:{metric_log.replace("\n", "\n| ")}\n⌊"
154
164
 
155
165
  for nested in metrics.nested:
156
166
  nested_log: str = _tree_log(
157
167
  nested,
158
168
  list_items_limit=list_items_limit,
159
- item_character_limit=item_character_limit,
160
- ).replace("\n", "\n| ")
169
+ redact_content=redact_content,
170
+ )
161
171
 
162
- log += f"\n{nested_log}"
172
+ log += f"\n\n{nested_log}"
163
173
 
164
- return log.strip()
174
+ return log.strip().replace("\n", "\n| ") + "\n⌊"
165
175
 
166
176
 
167
177
  def _state_log(
168
178
  value: State,
169
179
  /,
170
180
  list_items_limit: int | None,
171
- item_character_limit: int | None,
181
+ redact_content: bool,
172
182
  ) -> str | None:
173
183
  state_log: str = ""
174
184
  for key, element in vars(value).items():
175
185
  element_log: str | None = _value_log(
176
186
  element,
177
187
  list_items_limit=list_items_limit,
178
- item_character_limit=item_character_limit,
188
+ redact_content=redact_content,
179
189
  )
180
190
 
181
191
  if element_log:
182
- state_log += f"\n| + {key}: {element_log}"
192
+ state_log += f"\n {key}: {element_log}"
183
193
 
184
194
  else:
185
195
  continue # skip empty logs
186
196
 
187
197
  if state_log:
188
- return state_log.replace("\n", "\n| ")
198
+ return state_log
189
199
 
190
200
  else:
191
201
  return None # skip empty logs
@@ -195,17 +205,17 @@ def _dict_log(
195
205
  value: dict[Any, Any],
196
206
  /,
197
207
  list_items_limit: int | None,
198
- item_character_limit: int | None,
208
+ redact_content: bool,
199
209
  ) -> str | None:
200
210
  dict_log: str = ""
201
211
  for key, element in value.items():
202
212
  element_log: str | None = _value_log(
203
213
  element,
204
214
  list_items_limit=list_items_limit,
205
- item_character_limit=item_character_limit,
215
+ redact_content=redact_content,
206
216
  )
207
217
  if element_log:
208
- dict_log += f"\n| + {key}: {element_log}"
218
+ dict_log += f"\n[{key}]: {element_log}"
209
219
 
210
220
  else:
211
221
  continue # skip empty logs
@@ -221,7 +231,7 @@ def _list_log(
221
231
  value: list[Any],
222
232
  /,
223
233
  list_items_limit: int | None,
224
- item_character_limit: int | None,
234
+ redact_content: bool,
225
235
  ) -> str | None:
226
236
  list_log: str = ""
227
237
  enumerated: list[tuple[int, Any]] = list(enumerate(value))
@@ -236,10 +246,10 @@ def _list_log(
236
246
  element_log: str | None = _value_log(
237
247
  element,
238
248
  list_items_limit=list_items_limit,
239
- item_character_limit=item_character_limit,
249
+ redact_content=redact_content,
240
250
  )
241
251
  if element_log:
242
- list_log += f"\n| [{idx}] {element_log}"
252
+ list_log += f"\n[{idx}] {element_log}"
243
253
 
244
254
  else:
245
255
  continue # skip empty logs
@@ -254,34 +264,33 @@ def _list_log(
254
264
  def _raw_value_log(
255
265
  value: Any,
256
266
  /,
257
- item_character_limit: int | None,
267
+ redact_content: bool,
258
268
  ) -> str | None:
259
269
  if value is MISSING:
260
270
  return None # skip missing
261
271
 
262
- value_log = str(value)
263
- if not value_log:
264
- return None # skip empty logs
272
+ if redact_content:
273
+ return "[redacted]"
265
274
 
266
- if (item_character_limit := item_character_limit) and len(value_log) > item_character_limit:
267
- return value_log.replace("\n", " ")[:item_character_limit] + "..."
275
+ elif isinstance(value, str):
276
+ return f'"{value}"'.replace("\n", "\n| ")
268
277
 
269
278
  else:
270
- return value_log.replace("\n", "\n| ")
279
+ return str(value).strip().replace("\n", "\n| ")
271
280
 
272
281
 
273
282
  def _value_log(
274
283
  value: Any,
275
284
  /,
276
285
  list_items_limit: int | None,
277
- item_character_limit: int | None,
286
+ redact_content: bool,
278
287
  ) -> str | None:
279
288
  # try unpack dicts
280
289
  if isinstance(value, dict):
281
290
  return _dict_log(
282
291
  cast(dict[Any, Any], value),
283
292
  list_items_limit=list_items_limit,
284
- item_character_limit=item_character_limit,
293
+ redact_content=redact_content,
285
294
  )
286
295
 
287
296
  # try unpack lists
@@ -289,7 +298,7 @@ def _value_log(
289
298
  return _list_log(
290
299
  cast(list[Any], value),
291
300
  list_items_limit=list_items_limit,
292
- item_character_limit=item_character_limit,
301
+ redact_content=redact_content,
293
302
  )
294
303
 
295
304
  # try unpack state
@@ -297,11 +306,11 @@ def _value_log(
297
306
  return _state_log(
298
307
  value,
299
308
  list_items_limit=list_items_limit,
300
- item_character_limit=item_character_limit,
309
+ redact_content=redact_content,
301
310
  )
302
311
 
303
312
  else:
304
313
  return _raw_value_log(
305
314
  value,
306
- item_character_limit=item_character_limit,
315
+ redact_content=redact_content,
307
316
  )
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: haiway
3
- Version: 0.8.0
3
+ Version: 0.8.2
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
@@ -1,4 +1,3 @@
1
-
2
1
  from pytest import mark, raises
3
2
 
4
3
  from haiway import MissingContext, State, ctx
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