graphrefly 0.22.0__cp312-abi3-win_amd64.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.
graphrefly/__init__.py ADDED
@@ -0,0 +1,131 @@
1
+ """Python-owned facade for the GraphReFly native engine."""
2
+
3
+ from graphrefly._facade import (
4
+ _VERSION,
5
+ SENTINEL,
6
+ AsyncRunner,
7
+ ControlMessage,
8
+ Ctx,
9
+ DataMessage,
10
+ ErrorMessage,
11
+ Graph,
12
+ GraphCheckpoint,
13
+ GraphEvent,
14
+ GraphReentryQueue,
15
+ Message,
16
+ Node,
17
+ PullContext,
18
+ RestoreContext,
19
+ RestoreDescriptor,
20
+ RestoreRef,
21
+ RestoreRegistry,
22
+ Retain,
23
+ RewireNext,
24
+ Sentinel,
25
+ Subscription,
26
+ WireBridge,
27
+ WireBridgeAckDriver,
28
+ WireBridgeAckDriverIssue,
29
+ WireBridgeAckDriverStatus,
30
+ WireBridgeAckTimeout,
31
+ WireBridgeIssue,
32
+ WireBridgeProtobuf,
33
+ WireBridgeProtobufIssue,
34
+ WireBridgeProtobufStatus,
35
+ WireBridgeStatus,
36
+ WireEdgeGroup,
37
+ WireEdgeGroupIssue,
38
+ WireEdgeGroupStatus,
39
+ anyio_runner,
40
+ async_node,
41
+ asyncio_runner,
42
+ from_async_iter,
43
+ from_awaitable,
44
+ restore_graph,
45
+ restore_ref,
46
+ restore_registry,
47
+ trio_runner,
48
+ version,
49
+ wire_bridge,
50
+ wire_bridge_ack_driver,
51
+ wire_bridge_protobuf,
52
+ wire_edge_group,
53
+ )
54
+ from graphrefly.exceptions import (
55
+ CallbackError,
56
+ GraphCallbackError,
57
+ GraphReflyCheckpointError,
58
+ GraphReflyError,
59
+ GraphReflyNoDataError,
60
+ GraphReflyRestoreError,
61
+ GraphReflyRuntimeError,
62
+ GraphReflyValueError,
63
+ SubscriberCallbackError,
64
+ )
65
+ from graphrefly.issues import DataIssue
66
+
67
+ __all__ = [
68
+ "CallbackError",
69
+ "AsyncRunner",
70
+ "ControlMessage",
71
+ "Ctx",
72
+ "DataMessage",
73
+ "DataIssue",
74
+ "ErrorMessage",
75
+ "Graph",
76
+ "GraphCallbackError",
77
+ "GraphCheckpoint",
78
+ "GraphReflyCheckpointError",
79
+ "GraphEvent",
80
+ "GraphReentryQueue",
81
+ "GraphReflyError",
82
+ "GraphReflyNoDataError",
83
+ "GraphReflyRestoreError",
84
+ "GraphReflyRuntimeError",
85
+ "GraphReflyValueError",
86
+ "Message",
87
+ "Node",
88
+ "PullContext",
89
+ "Retain",
90
+ "RewireNext",
91
+ "RestoreContext",
92
+ "RestoreDescriptor",
93
+ "RestoreRef",
94
+ "RestoreRegistry",
95
+ "SENTINEL",
96
+ "Sentinel",
97
+ "Subscription",
98
+ "SubscriberCallbackError",
99
+ "WireBridge",
100
+ "WireBridgeAckDriver",
101
+ "WireBridgeAckDriverIssue",
102
+ "WireBridgeAckDriverStatus",
103
+ "WireBridgeAckTimeout",
104
+ "WireBridgeIssue",
105
+ "WireBridgeProtobuf",
106
+ "WireBridgeProtobufIssue",
107
+ "WireBridgeProtobufStatus",
108
+ "WireBridgeStatus",
109
+ "WireEdgeGroup",
110
+ "WireEdgeGroupIssue",
111
+ "WireEdgeGroupStatus",
112
+ "__version__",
113
+ "async_node",
114
+ "anyio_runner",
115
+ "asyncio_runner",
116
+ "from_async_iter",
117
+ "from_awaitable",
118
+ "restore_graph",
119
+ "restore_ref",
120
+ "restore_registry",
121
+ "trio_runner",
122
+ "version",
123
+ "wire_bridge",
124
+ "wire_bridge_ack_driver",
125
+ "wire_bridge_protobuf",
126
+ "wire_edge_group",
127
+ ]
128
+
129
+ __version__ = _VERSION
130
+
131
+ globals().pop("_native", None)
@@ -0,0 +1,449 @@
1
+ """Private fixed-stimulus harness for GraphReFly conformance tests.
2
+
3
+ D447 permits this module for approved scenario stimuli over private native
4
+ internals. It is deliberately not exported from ``graphrefly.__all__``.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ from collections.abc import Callable, Iterable
10
+ from sys import modules
11
+ from threading import get_ident
12
+ from typing import Any, Literal
13
+
14
+ import graphrefly._native as _native
15
+ from graphrefly._facade import (
16
+ Ctx,
17
+ Graph,
18
+ Node,
19
+ _poison_on_fatal,
20
+ _reject_async_callable,
21
+ _reject_awaitable,
22
+ _reject_sentinel_data,
23
+ )
24
+ from graphrefly.exceptions import GraphReflyRuntimeError, GraphReflyValueError
25
+
26
+ if hasattr(modules["graphrefly"], "_native"):
27
+ delattr(modules["graphrefly"], "_native")
28
+
29
+ PausableMode = Literal["true", "resumeAll", "false"]
30
+
31
+
32
+ class ConformanceAsyncHandle:
33
+ """Private scenario-fixed handle for a captured async-pool ctx."""
34
+
35
+ def __init__(self, native: Any, *, owner_thread: int, lifetime: Any) -> None:
36
+ self._native = native
37
+ self._owner_thread = owner_thread
38
+ self._lifetime = lifetime
39
+
40
+ def has_pending(self) -> bool:
41
+ self._check_thread()
42
+ try:
43
+ return bool(self._native.has_pending())
44
+ except RuntimeError as error:
45
+ raise GraphReflyRuntimeError(str(error)) from error
46
+ except BaseException as error:
47
+ _poison_on_fatal(self._lifetime, error)
48
+
49
+ def resolve(self, value: object) -> None:
50
+ self._check_thread()
51
+ _reject_sentinel_data(value)
52
+ _reject_awaitable(value)
53
+ try:
54
+ self._native.resolve(value)
55
+ except RuntimeError as error:
56
+ raise GraphReflyRuntimeError(str(error)) from error
57
+ except BaseException as error:
58
+ _poison_on_fatal(self._lifetime, error)
59
+
60
+ def invalidate_live_deps(self) -> None:
61
+ self._check_thread()
62
+ try:
63
+ self._native.invalidate_live_deps()
64
+ except RuntimeError as error:
65
+ raise GraphReflyRuntimeError(str(error)) from error
66
+ except BaseException as error:
67
+ _poison_on_fatal(self._lifetime, error)
68
+
69
+ def _check_thread(self) -> None:
70
+ if get_ident() != self._owner_thread:
71
+ msg = (
72
+ "GraphReFly Python conformance async handles are bound to "
73
+ "their creating thread in v0"
74
+ )
75
+ raise GraphReflyRuntimeError(msg)
76
+ if self._lifetime.closed:
77
+ raise GraphReflyRuntimeError(self._lifetime.closed_message)
78
+
79
+
80
+ class ConformanceStimulus:
81
+ """Scenario-named private stimuli; not a generic message sender."""
82
+
83
+ def __init__(self, graph: Graph) -> None:
84
+ self._graph = graph
85
+
86
+ def state_empty(self, name: str | None = None) -> Node[object]:
87
+ self._graph._check_thread()
88
+ try:
89
+ return Node(
90
+ self._graph._native.state_empty(name),
91
+ owner_thread=self._graph._owner_thread,
92
+ lifetime=self._graph._lifetime,
93
+ writable=True,
94
+ )
95
+ except ValueError as error:
96
+ raise GraphReflyValueError(str(error)) from error
97
+ except RuntimeError as error:
98
+ raise GraphReflyRuntimeError(str(error)) from error
99
+ except BaseException as error:
100
+ _poison_on_fatal(self._graph._lifetime, error)
101
+
102
+ def node(
103
+ self,
104
+ deps: Iterable[Node[Any]],
105
+ callback: Callable[[Ctx], object],
106
+ name: str | None = None,
107
+ *,
108
+ partial: bool = False,
109
+ complete_when_deps_complete: bool = True,
110
+ error_when_deps_error: bool = True,
111
+ terminal_as_real_input: bool = False,
112
+ pausable: PausableMode = "true",
113
+ pull_id: str | None = None,
114
+ ) -> Node[object]:
115
+ self._graph._check_thread()
116
+ deps = list(deps)
117
+ native_deps = self._graph._native_deps(deps)
118
+
119
+ def native_callback(native_ctx: _native.Ctx) -> None:
120
+ value = callback(
121
+ Ctx(
122
+ native_ctx,
123
+ owner_thread=self._graph._owner_thread,
124
+ lifetime=self._graph._lifetime,
125
+ )
126
+ )
127
+ _reject_awaitable(value)
128
+
129
+ try:
130
+ return Node(
131
+ self._graph._native._conformance_node(
132
+ native_deps,
133
+ native_callback,
134
+ name,
135
+ partial,
136
+ complete_when_deps_complete,
137
+ error_when_deps_error,
138
+ terminal_as_real_input,
139
+ pausable,
140
+ pull_id,
141
+ ),
142
+ owner_thread=self._graph._owner_thread,
143
+ lifetime=self._graph._lifetime,
144
+ )
145
+ except ValueError as error:
146
+ raise GraphReflyValueError(str(error)) from error
147
+ except RuntimeError as error:
148
+ raise GraphReflyRuntimeError(str(error)) from error
149
+ except BaseException as error:
150
+ _poison_on_fatal(self._graph._lifetime, error)
151
+
152
+ def c7_send_unheld_dirty_up(self, node: Node[Any]) -> None:
153
+ self._native_node(node)._up_dirty()
154
+
155
+ def c7_send_unheld_teardown_up(self, node: Node[Any]) -> None:
156
+ self._native_node(node)._up_teardown()
157
+
158
+ def c15_dep_goes_dirty(self, node: Node[Any]) -> None:
159
+ self._native_node(node)._down_dirty()
160
+
161
+ def c15_dirty_dep_completes_without_data(self, node: Node[Any]) -> None:
162
+ self._native_node(node)._down_complete()
163
+
164
+ def c15_dirty_dep_errors_without_data(self, node: Node[Any], diagnostic: str) -> None:
165
+ self._native_node(node)._down_error(diagnostic)
166
+
167
+ def c17_dep_errors(self, node: Node[Any], diagnostic: str) -> None:
168
+ self._native_node(node)._down_error(diagnostic)
169
+
170
+ def c17_dep_emits_data_then_completes(self, node: Node[Any], value: object) -> None:
171
+ _reject_sentinel_data(value)
172
+ self._native_node(node)._down_data_complete(value)
173
+
174
+ def c19_dep_invalidates_after_dirty(self, node: Node[Any]) -> None:
175
+ self._native_node(node)._down_invalidate()
176
+
177
+ def c20_dep_tears_down(self, node: Node[Any]) -> None:
178
+ self._native_node(node)._down_teardown()
179
+
180
+ def c23_dep_dirty_then_resolved(self, node: Node[Any]) -> None:
181
+ native = self._native_node(node)
182
+ native._up_dirty()
183
+ native._down_resolved()
184
+
185
+ def c23_dep_emits_data_data_invalidate(
186
+ self,
187
+ node: Node[Any],
188
+ first: object,
189
+ second: object,
190
+ ) -> None:
191
+ _reject_sentinel_data(first)
192
+ _reject_sentinel_data(second)
193
+ self._native_node(node)._down_data_data_invalidate(first, second)
194
+
195
+ def c12_dep_emits_data_resolved(self, node: Node[Any], value: object) -> None:
196
+ _reject_sentinel_data(value)
197
+ _reject_awaitable(value)
198
+ self._native_node(node)._conformance_c12_down_data_resolved(value)
199
+
200
+ def c23_dep_completes(self, node: Node[Any]) -> None:
201
+ self._native_node(node)._down_complete()
202
+
203
+ def c23_dep_errors(self, node: Node[Any], diagnostic: str) -> None:
204
+ self._native_node(node)._down_error(diagnostic)
205
+
206
+ def c16_pull(self, node: Node[Any], pull_id: str, params: object | None = None) -> None:
207
+ _reject_sentinel_data(params)
208
+ self._native_node(node)._conformance_up_pull(pull_id, params)
209
+
210
+ def c16_pull_toward(
211
+ self,
212
+ node: Node[Any],
213
+ toward_dep: int,
214
+ pull_id: str,
215
+ params: object | None = None,
216
+ ) -> None:
217
+ _reject_sentinel_data(params)
218
+ self._native_node(node)._conformance_up_pull_toward(toward_dep, pull_id, params)
219
+
220
+ def c26_send_forbidden_data_up(self, node: Node[Any], value: object) -> None:
221
+ _reject_sentinel_data(value)
222
+ self._native_node(node)._conformance_up_data_forbidden(value)
223
+
224
+ def c11_immediate_subscribe_dep(
225
+ self,
226
+ node: Node[Any],
227
+ dep: Node[Any],
228
+ callback: Callable[[Ctx], object],
229
+ ) -> None:
230
+ def native_callback(native_ctx: _native.Ctx) -> None:
231
+ value = callback(
232
+ Ctx(
233
+ native_ctx,
234
+ owner_thread=self._graph._owner_thread,
235
+ lifetime=self._graph._lifetime,
236
+ )
237
+ )
238
+ _reject_awaitable(value)
239
+
240
+ self._native_node(node)._conformance_immediate_subscribe_dep(
241
+ self._native_node(dep),
242
+ native_callback,
243
+ )
244
+
245
+ def c8_immediate_subscribe_dep(
246
+ self,
247
+ node: Node[Any],
248
+ dep: Node[Any],
249
+ callback: Callable[[Ctx], object],
250
+ ) -> None:
251
+ native_callback = self._native_callback(callback)
252
+ try:
253
+ self._native_node(node)._conformance_immediate_subscribe_dep(
254
+ self._native_node(dep),
255
+ native_callback,
256
+ )
257
+ except RuntimeError as error:
258
+ raise GraphReflyRuntimeError(str(error)) from error
259
+ except BaseException as error:
260
+ _poison_on_fatal(self._graph._lifetime, error)
261
+
262
+ def c8_immediate_unsubscribe_dep(
263
+ self,
264
+ node: Node[Any],
265
+ dep: Node[Any],
266
+ callback: Callable[[Ctx], object],
267
+ ) -> None:
268
+ native_callback = self._native_callback(callback)
269
+ try:
270
+ self._native_node(node)._conformance_immediate_unsubscribe_dep(
271
+ self._native_node(dep),
272
+ native_callback,
273
+ )
274
+ except RuntimeError as error:
275
+ raise GraphReflyRuntimeError(str(error)) from error
276
+ except BaseException as error:
277
+ _poison_on_fatal(self._graph._lifetime, error)
278
+
279
+ def c8_immediate_replace_deps(
280
+ self,
281
+ node: Node[Any],
282
+ deps: Iterable[Node[Any]],
283
+ callback: Callable[[Ctx], object],
284
+ ) -> None:
285
+ native_callback = self._native_callback(callback)
286
+ try:
287
+ self._native_node(node)._conformance_immediate_replace_deps(
288
+ [self._native_node(dep) for dep in deps],
289
+ native_callback,
290
+ )
291
+ except RuntimeError as error:
292
+ raise GraphReflyRuntimeError(str(error)) from error
293
+ except BaseException as error:
294
+ _poison_on_fatal(self._graph._lifetime, error)
295
+
296
+ def c22_old_shape_data(self, node: Node[Any], value: object) -> None:
297
+ _reject_sentinel_data(value)
298
+ _reject_awaitable(value)
299
+ try:
300
+ self._native_node(node)._conformance_c22_down_data(value)
301
+ except RuntimeError as error:
302
+ raise GraphReflyRuntimeError(str(error)) from error
303
+ except BaseException as error:
304
+ _poison_on_fatal(self._graph._lifetime, error)
305
+
306
+ def c2_async_result_node(
307
+ self,
308
+ dep: Node[Any],
309
+ name: str | None = None,
310
+ ) -> tuple[Node[object], ConformanceAsyncHandle]:
311
+ return self._async_node([dep], name=name, pausable="true")
312
+
313
+ def c4_async_diamond_leg(
314
+ self,
315
+ dep: Node[Any],
316
+ name: str | None = None,
317
+ ) -> tuple[Node[object], ConformanceAsyncHandle]:
318
+ return self._async_node([dep], name=name, pausable="true")
319
+
320
+ def c9_pausable_false_async_source(
321
+ self,
322
+ name: str | None = None,
323
+ ) -> tuple[Node[object], ConformanceAsyncHandle]:
324
+ return self._async_source(name=name, pausable="false")
325
+
326
+ def c10_true_mode_async_leaf_source(
327
+ self,
328
+ name: str | None = None,
329
+ ) -> tuple[Node[object], ConformanceAsyncHandle]:
330
+ return self._async_source(name=name, pausable="true")
331
+
332
+ def c21_live_edge_async_node(
333
+ self,
334
+ dep: Node[Any],
335
+ name: str | None = None,
336
+ ) -> tuple[Node[object], ConformanceAsyncHandle]:
337
+ return self._async_node([dep], name=name, pausable="true")
338
+
339
+ def c21_replace_with_live_dep(
340
+ self,
341
+ node: Node[Any],
342
+ dep: Node[Any],
343
+ pending: ConformanceAsyncHandle,
344
+ ) -> None:
345
+ if pending._lifetime is not self._graph._lifetime:
346
+ msg = "conformance async handle must belong to this GraphReFly graph"
347
+ raise GraphReflyRuntimeError(msg)
348
+ self._native_node(node)._conformance_c21_replace_with_live_dep(
349
+ self._native_node(dep),
350
+ pending._native,
351
+ )
352
+
353
+ def _native_node(self, node: Node[Any]) -> _native.Node:
354
+ if not isinstance(node, Node):
355
+ msg = "conformance stimulus nodes must be graphrefly.Node objects"
356
+ raise GraphReflyValueError(msg)
357
+ return self._graph._native_node(node)
358
+
359
+ def _native_callback(self, callback: Callable[[Ctx], object]) -> Callable[[_native.Ctx], None]:
360
+ if not callable(callback):
361
+ msg = "conformance rewire callback must be callable"
362
+ raise GraphReflyValueError(msg)
363
+ _reject_async_callable(callback)
364
+
365
+ def native_callback(native_ctx: _native.Ctx) -> None:
366
+ value = callback(
367
+ Ctx(
368
+ native_ctx,
369
+ owner_thread=self._graph._owner_thread,
370
+ lifetime=self._graph._lifetime,
371
+ )
372
+ )
373
+ _reject_awaitable(value)
374
+
375
+ return native_callback
376
+
377
+ def _async_node(
378
+ self,
379
+ deps: Iterable[Node[Any]],
380
+ *,
381
+ name: str | None,
382
+ pausable: PausableMode,
383
+ ) -> tuple[Node[object], ConformanceAsyncHandle]:
384
+ self._graph._check_thread()
385
+ native_deps = self._graph._native_deps(list(deps))
386
+ try:
387
+ native_node, native_handle = self._graph._native._conformance_async_node(
388
+ native_deps,
389
+ name,
390
+ pausable,
391
+ )
392
+ return (
393
+ Node(
394
+ native_node,
395
+ owner_thread=self._graph._owner_thread,
396
+ lifetime=self._graph._lifetime,
397
+ ),
398
+ ConformanceAsyncHandle(
399
+ native_handle,
400
+ owner_thread=self._graph._owner_thread,
401
+ lifetime=self._graph._lifetime,
402
+ ),
403
+ )
404
+ except ValueError as error:
405
+ raise GraphReflyValueError(str(error)) from error
406
+ except RuntimeError as error:
407
+ raise GraphReflyRuntimeError(str(error)) from error
408
+ except BaseException as error:
409
+ _poison_on_fatal(self._graph._lifetime, error)
410
+
411
+ def _async_source(
412
+ self,
413
+ *,
414
+ name: str | None,
415
+ pausable: PausableMode,
416
+ ) -> tuple[Node[object], ConformanceAsyncHandle]:
417
+ self._graph._check_thread()
418
+ try:
419
+ native_node, native_handle = self._graph._native._conformance_async_source(
420
+ name,
421
+ pausable,
422
+ )
423
+ return (
424
+ Node(
425
+ native_node,
426
+ owner_thread=self._graph._owner_thread,
427
+ lifetime=self._graph._lifetime,
428
+ ),
429
+ ConformanceAsyncHandle(
430
+ native_handle,
431
+ owner_thread=self._graph._owner_thread,
432
+ lifetime=self._graph._lifetime,
433
+ ),
434
+ )
435
+ except ValueError as error:
436
+ raise GraphReflyValueError(str(error)) from error
437
+ except RuntimeError as error:
438
+ raise GraphReflyRuntimeError(str(error)) from error
439
+ except BaseException as error:
440
+ _poison_on_fatal(self._graph._lifetime, error)
441
+
442
+
443
+ def up_data_forbidden(ctx: Ctx, value: object) -> None:
444
+ _reject_sentinel_data(value)
445
+ ctx._native._conformance_up_data(value)
446
+
447
+
448
+ def down_complete(ctx: Ctx) -> None:
449
+ ctx._native._conformance_down_complete()