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 +131 -0
- graphrefly/_conformance.py +449 -0
- graphrefly/_facade.py +3511 -0
- graphrefly/_native.pyd +0 -0
- graphrefly/_native.pyi +302 -0
- graphrefly/exceptions.py +47 -0
- graphrefly/issues.py +16 -0
- graphrefly/py.typed +1 -0
- graphrefly-0.22.0.dist-info/METADATA +219 -0
- graphrefly-0.22.0.dist-info/RECORD +13 -0
- graphrefly-0.22.0.dist-info/WHEEL +4 -0
- graphrefly-0.22.0.dist-info/licenses/LICENSE +21 -0
- graphrefly-0.22.0.dist-info/sboms/graphrefly-bindings-py.cyclonedx.json +1824 -0
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()
|