mycorrhizal 0.1.0__py3-none-any.whl → 0.2.0__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.
- mycorrhizal/_version.py +1 -0
- mycorrhizal/common/__init__.py +15 -3
- mycorrhizal/common/cache.py +114 -0
- mycorrhizal/common/compilation.py +263 -0
- mycorrhizal/common/interface_detection.py +159 -0
- mycorrhizal/common/interfaces.py +3 -50
- mycorrhizal/common/mermaid.py +124 -0
- mycorrhizal/common/wrappers.py +1 -1
- mycorrhizal/hypha/core/builder.py +56 -8
- mycorrhizal/hypha/core/runtime.py +242 -107
- mycorrhizal/hypha/core/specs.py +19 -3
- mycorrhizal/mycelium/__init__.py +174 -0
- mycorrhizal/mycelium/core.py +619 -0
- mycorrhizal/mycelium/exceptions.py +30 -0
- mycorrhizal/mycelium/hypha_bridge.py +1143 -0
- mycorrhizal/mycelium/instance.py +440 -0
- mycorrhizal/mycelium/pn_context.py +276 -0
- mycorrhizal/mycelium/runner.py +165 -0
- mycorrhizal/mycelium/spores_integration.py +655 -0
- mycorrhizal/mycelium/tree_builder.py +102 -0
- mycorrhizal/mycelium/tree_spec.py +197 -0
- mycorrhizal/rhizomorph/README.md +82 -33
- mycorrhizal/rhizomorph/core.py +308 -82
- mycorrhizal/septum/TRANSITION_REFERENCE.md +385 -0
- mycorrhizal/{enoki → septum}/core.py +326 -100
- mycorrhizal/{enoki → septum}/testing_utils.py +7 -7
- mycorrhizal/{enoki → septum}/util.py +44 -21
- mycorrhizal/spores/__init__.py +72 -19
- mycorrhizal/spores/core.py +907 -75
- mycorrhizal/spores/dsl/__init__.py +8 -8
- mycorrhizal/spores/dsl/hypha.py +3 -15
- mycorrhizal/spores/dsl/rhizomorph.py +3 -11
- mycorrhizal/spores/dsl/{enoki.py → septum.py} +26 -77
- mycorrhizal/spores/encoder/json.py +21 -12
- mycorrhizal/spores/extraction.py +14 -11
- mycorrhizal/spores/models.py +75 -20
- mycorrhizal/spores/transport/__init__.py +9 -2
- mycorrhizal/spores/transport/base.py +36 -17
- mycorrhizal/spores/transport/file.py +126 -0
- mycorrhizal-0.2.0.dist-info/METADATA +335 -0
- mycorrhizal-0.2.0.dist-info/RECORD +54 -0
- mycorrhizal-0.1.0.dist-info/METADATA +0 -198
- mycorrhizal-0.1.0.dist-info/RECORD +0 -37
- /mycorrhizal/{enoki → septum}/__init__.py +0 -0
- {mycorrhizal-0.1.0.dist-info → mycorrhizal-0.2.0.dist-info}/WHEEL +0 -0
|
@@ -5,11 +5,11 @@ Spores DSL Adapters
|
|
|
5
5
|
DSL-specific adapters for integrating spores logging with:
|
|
6
6
|
- Hypha (Petri nets)
|
|
7
7
|
- Rhizomorph (Behavior trees)
|
|
8
|
-
-
|
|
8
|
+
- Septum (State machines)
|
|
9
9
|
|
|
10
10
|
Usage:
|
|
11
11
|
```python
|
|
12
|
-
from mycorrhizal.spores.dsl import HyphaAdapter, RhizomorphAdapter,
|
|
12
|
+
from mycorrhizal.spores.dsl import HyphaAdapter, RhizomorphAdapter, SeptumAdapter
|
|
13
13
|
|
|
14
14
|
# For Hypha (Petri nets)
|
|
15
15
|
hypha_adapter = HyphaAdapter()
|
|
@@ -27,11 +27,11 @@ Usage:
|
|
|
27
27
|
async def check(bb: Blackboard) -> Status:
|
|
28
28
|
return Status.SUCCESS
|
|
29
29
|
|
|
30
|
-
# For
|
|
31
|
-
|
|
30
|
+
# For Septum (State machines)
|
|
31
|
+
septum_adapter = SeptumAdapter()
|
|
32
32
|
|
|
33
|
-
@
|
|
34
|
-
@
|
|
33
|
+
@septum.on_state
|
|
34
|
+
@septum_adapter.log_state(event_type="state_execute")
|
|
35
35
|
async def on_state(ctx: SharedContext):
|
|
36
36
|
return Events.DONE
|
|
37
37
|
```
|
|
@@ -39,10 +39,10 @@ Usage:
|
|
|
39
39
|
|
|
40
40
|
from .hypha import HyphaAdapter
|
|
41
41
|
from .rhizomorph import RhizomorphAdapter
|
|
42
|
-
from .
|
|
42
|
+
from .septum import SeptumAdapter
|
|
43
43
|
|
|
44
44
|
__all__ = [
|
|
45
45
|
'HyphaAdapter',
|
|
46
46
|
'RhizomorphAdapter',
|
|
47
|
-
'
|
|
47
|
+
'SeptumAdapter',
|
|
48
48
|
]
|
mycorrhizal/spores/dsl/hypha.py
CHANGED
|
@@ -237,18 +237,10 @@ async def _log_transition_event(
|
|
|
237
237
|
event_attrs = {}
|
|
238
238
|
|
|
239
239
|
# Add token count
|
|
240
|
-
event_attrs["token_count"] =
|
|
241
|
-
name="token_count",
|
|
242
|
-
value=str(len(consumed)),
|
|
243
|
-
time=timestamp
|
|
244
|
-
)
|
|
240
|
+
event_attrs["token_count"] = attribute_value_from_python(len(consumed))
|
|
245
241
|
|
|
246
242
|
# Add transition name
|
|
247
|
-
event_attrs["transition_name"] =
|
|
248
|
-
name="transition_name",
|
|
249
|
-
value=func.__name__,
|
|
250
|
-
time=timestamp
|
|
251
|
-
)
|
|
243
|
+
event_attrs["transition_name"] = attribute_value_from_python(func.__name__)
|
|
252
244
|
|
|
253
245
|
# Extract from blackboard
|
|
254
246
|
bb_attrs = extract_attributes_from_blackboard(bb, timestamp)
|
|
@@ -358,11 +350,7 @@ async def _log_place_event(
|
|
|
358
350
|
|
|
359
351
|
# Build event attributes
|
|
360
352
|
event_attrs = {
|
|
361
|
-
"place_name":
|
|
362
|
-
name="place_name",
|
|
363
|
-
value=func.__name__,
|
|
364
|
-
time=timestamp
|
|
365
|
-
)
|
|
353
|
+
"place_name": attribute_value_from_python(func.__name__)
|
|
366
354
|
}
|
|
367
355
|
|
|
368
356
|
# Extract from blackboard
|
|
@@ -20,7 +20,7 @@ from ...spores import (
|
|
|
20
20
|
Event,
|
|
21
21
|
LogRecord,
|
|
22
22
|
Relationship,
|
|
23
|
-
|
|
23
|
+
attribute_value_from_python,
|
|
24
24
|
generate_event_id,
|
|
25
25
|
)
|
|
26
26
|
from ...spores.extraction import (
|
|
@@ -167,19 +167,11 @@ async def _log_node_event(
|
|
|
167
167
|
event_attrs = {}
|
|
168
168
|
|
|
169
169
|
# Add node name
|
|
170
|
-
event_attrs["node_name"] =
|
|
171
|
-
name="node_name",
|
|
172
|
-
value=func.__name__,
|
|
173
|
-
time=timestamp
|
|
174
|
-
)
|
|
170
|
+
event_attrs["node_name"] = attribute_value_from_python(func.__name__)
|
|
175
171
|
|
|
176
172
|
# Add status if requested and result is a Status
|
|
177
173
|
if log_status and isinstance(result, Status):
|
|
178
|
-
event_attrs["status"] =
|
|
179
|
-
name="status",
|
|
180
|
-
value=result.name,
|
|
181
|
-
time=timestamp
|
|
182
|
-
)
|
|
174
|
+
event_attrs["status"] = attribute_value_from_python(result.name)
|
|
183
175
|
|
|
184
176
|
# Extract from blackboard
|
|
185
177
|
bb_attrs = extract_attributes_from_blackboard(bb, timestamp)
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
2
|
"""
|
|
3
|
-
Spores Adapter for
|
|
3
|
+
Spores Adapter for Septum (State Machines)
|
|
4
4
|
|
|
5
|
-
Provides logging integration for
|
|
5
|
+
Provides logging integration for Septum state machines.
|
|
6
6
|
Extracts context information and automatically creates event/object logs.
|
|
7
7
|
"""
|
|
8
8
|
|
|
@@ -22,21 +22,22 @@ from ...spores import (
|
|
|
22
22
|
Relationship,
|
|
23
23
|
EventAttributeValue,
|
|
24
24
|
generate_event_id,
|
|
25
|
+
attribute_value_from_python,
|
|
25
26
|
)
|
|
26
27
|
from ...spores.extraction import (
|
|
27
28
|
extract_attributes_from_blackboard,
|
|
28
29
|
extract_objects_from_blackboard,
|
|
29
30
|
)
|
|
30
31
|
from ...spores.core import _send_log_record, get_object_cache
|
|
31
|
-
from ...
|
|
32
|
+
from ...septum.core import SharedContext, TransitionType
|
|
32
33
|
|
|
33
34
|
|
|
34
35
|
logger = logging.getLogger(__name__)
|
|
35
36
|
|
|
36
37
|
|
|
37
|
-
class
|
|
38
|
+
class SeptumAdapter:
|
|
38
39
|
"""
|
|
39
|
-
Adapter for
|
|
40
|
+
Adapter for Septum state machine logging.
|
|
40
41
|
|
|
41
42
|
Provides decorators and helpers for logging:
|
|
42
43
|
- State entry/exit/timeout events
|
|
@@ -46,13 +47,13 @@ class EnokiAdapter:
|
|
|
46
47
|
|
|
47
48
|
Usage:
|
|
48
49
|
```python
|
|
49
|
-
from mycorrhizal.spores.dsl import
|
|
50
|
+
from mycorrhizal.spores.dsl import SeptumAdapter
|
|
50
51
|
|
|
51
|
-
adapter =
|
|
52
|
+
adapter = SeptumAdapter()
|
|
52
53
|
|
|
53
|
-
@
|
|
54
|
+
@septum.state()
|
|
54
55
|
def MyState():
|
|
55
|
-
@
|
|
56
|
+
@septum.on_state
|
|
56
57
|
@adapter.log_state(event_type="state_execute")
|
|
57
58
|
async def on_state(ctx: SharedContext):
|
|
58
59
|
# Event automatically logged with:
|
|
@@ -61,7 +62,7 @@ class EnokiAdapter:
|
|
|
61
62
|
# - relationships to objects (with ObjectRef annotations)
|
|
62
63
|
return Events.DONE
|
|
63
64
|
|
|
64
|
-
@
|
|
65
|
+
@septum.on_enter
|
|
65
66
|
@adapter.log_state_lifecycle(event_type="state_enter")
|
|
66
67
|
async def on_enter(ctx: SharedContext):
|
|
67
68
|
pass
|
|
@@ -69,7 +70,7 @@ class EnokiAdapter:
|
|
|
69
70
|
"""
|
|
70
71
|
|
|
71
72
|
def __init__(self):
|
|
72
|
-
"""Initialize the
|
|
73
|
+
"""Initialize the Septum adapter."""
|
|
73
74
|
self._enabled = True
|
|
74
75
|
|
|
75
76
|
def enable(self):
|
|
@@ -88,7 +89,7 @@ class EnokiAdapter:
|
|
|
88
89
|
log_transition: bool = True,
|
|
89
90
|
) -> Callable:
|
|
90
91
|
"""
|
|
91
|
-
Decorator to log
|
|
92
|
+
Decorator to log Septum state execution.
|
|
92
93
|
|
|
93
94
|
Automatically captures:
|
|
94
95
|
- State name
|
|
@@ -214,19 +215,11 @@ async def _log_state_event(
|
|
|
214
215
|
if hasattr(ctx, 'current_state') and ctx.current_state:
|
|
215
216
|
state_name = getattr(ctx.current_state, 'name', state_name)
|
|
216
217
|
|
|
217
|
-
event_attrs["state_name"] =
|
|
218
|
-
name="state_name",
|
|
219
|
-
value=state_name,
|
|
220
|
-
time=timestamp
|
|
221
|
-
)
|
|
218
|
+
event_attrs["state_name"] = attribute_value_from_python(state_name)
|
|
222
219
|
|
|
223
220
|
# Add transition result if requested
|
|
224
221
|
if log_transition and isinstance(result, TransitionType):
|
|
225
|
-
event_attrs["transition"] =
|
|
226
|
-
name="transition",
|
|
227
|
-
value=result.name,
|
|
228
|
-
time=timestamp
|
|
229
|
-
)
|
|
222
|
+
event_attrs["transition"] = attribute_value_from_python(result.name)
|
|
230
223
|
|
|
231
224
|
# Extract from ctx.common (blackboard)
|
|
232
225
|
if hasattr(ctx, 'common') and ctx.common:
|
|
@@ -235,11 +228,7 @@ async def _log_state_event(
|
|
|
235
228
|
|
|
236
229
|
# Add message if present
|
|
237
230
|
if hasattr(ctx, 'msg') and ctx.msg is not None:
|
|
238
|
-
event_attrs["message_type"] =
|
|
239
|
-
name="message_type",
|
|
240
|
-
value=type(ctx.msg).__name__,
|
|
241
|
-
time=timestamp
|
|
242
|
-
)
|
|
231
|
+
event_attrs["message_type"] = attribute_value_from_python(type(ctx.msg).__name__)
|
|
243
232
|
|
|
244
233
|
# Extract objects from ctx.common
|
|
245
234
|
relationships = {}
|
|
@@ -293,16 +282,8 @@ async def _log_lifecycle_event(
|
|
|
293
282
|
|
|
294
283
|
# Build event attributes
|
|
295
284
|
event_attrs = {
|
|
296
|
-
"lifecycle_method":
|
|
297
|
-
|
|
298
|
-
value=func.__name__,
|
|
299
|
-
time=timestamp
|
|
300
|
-
),
|
|
301
|
-
"phase": EventAttributeValue(
|
|
302
|
-
name="phase",
|
|
303
|
-
value=phase,
|
|
304
|
-
time=timestamp
|
|
305
|
-
)
|
|
285
|
+
"lifecycle_method": attribute_value_from_python(func.__name__),
|
|
286
|
+
"phase": attribute_value_from_python(phase)
|
|
306
287
|
}
|
|
307
288
|
|
|
308
289
|
# Add state name
|
|
@@ -310,11 +291,7 @@ async def _log_lifecycle_event(
|
|
|
310
291
|
if hasattr(ctx, 'current_state') and ctx.current_state:
|
|
311
292
|
state_name = getattr(ctx.current_state, 'name', state_name)
|
|
312
293
|
|
|
313
|
-
event_attrs["state_name"] =
|
|
314
|
-
name="state_name",
|
|
315
|
-
value=state_name,
|
|
316
|
-
time=timestamp
|
|
317
|
-
)
|
|
294
|
+
event_attrs["state_name"] = attribute_value_from_python(state_name)
|
|
318
295
|
|
|
319
296
|
# Add static attributes
|
|
320
297
|
if attributes:
|
|
@@ -322,17 +299,9 @@ async def _log_lifecycle_event(
|
|
|
322
299
|
if callable(value):
|
|
323
300
|
if hasattr(ctx, 'common') and ctx.common:
|
|
324
301
|
result = value(ctx.common)
|
|
325
|
-
event_attrs[key] =
|
|
326
|
-
name=key,
|
|
327
|
-
value=str(result),
|
|
328
|
-
time=timestamp
|
|
329
|
-
)
|
|
302
|
+
event_attrs[key] = attribute_value_from_python(str(result))
|
|
330
303
|
else:
|
|
331
|
-
event_attrs[key] =
|
|
332
|
-
name=key,
|
|
333
|
-
value=str(value),
|
|
334
|
-
time=timestamp
|
|
335
|
-
)
|
|
304
|
+
event_attrs[key] = attribute_value_from_python(str(value))
|
|
336
305
|
|
|
337
306
|
# Extract from ctx.common
|
|
338
307
|
if hasattr(ctx, 'common') and ctx.common:
|
|
@@ -435,26 +404,14 @@ async def _log_message_event(
|
|
|
435
404
|
|
|
436
405
|
# Build event attributes
|
|
437
406
|
event_attrs = {
|
|
438
|
-
"message_type":
|
|
439
|
-
|
|
440
|
-
value=type(ctx.msg).__name__,
|
|
441
|
-
time=timestamp
|
|
442
|
-
),
|
|
443
|
-
"handler": EventAttributeValue(
|
|
444
|
-
name="handler",
|
|
445
|
-
value=func.__name__,
|
|
446
|
-
time=timestamp
|
|
447
|
-
)
|
|
407
|
+
"message_type": attribute_value_from_python(type(ctx.msg).__name__),
|
|
408
|
+
"handler": attribute_value_from_python(func.__name__)
|
|
448
409
|
}
|
|
449
410
|
|
|
450
411
|
# Add state name
|
|
451
412
|
if hasattr(ctx, 'current_state') and ctx.current_state:
|
|
452
413
|
state_name = getattr(ctx.current_state, 'name', 'unknown')
|
|
453
|
-
event_attrs["state_name"] =
|
|
454
|
-
name="state_name",
|
|
455
|
-
value=state_name,
|
|
456
|
-
time=timestamp
|
|
457
|
-
)
|
|
414
|
+
event_attrs["state_name"] = attribute_value_from_python(state_name)
|
|
458
415
|
|
|
459
416
|
# Add static attributes
|
|
460
417
|
if attributes:
|
|
@@ -462,17 +419,9 @@ async def _log_message_event(
|
|
|
462
419
|
if callable(value):
|
|
463
420
|
if hasattr(ctx, 'common') and ctx.common:
|
|
464
421
|
result = value(ctx.common)
|
|
465
|
-
event_attrs[key] =
|
|
466
|
-
name=key,
|
|
467
|
-
value=str(result),
|
|
468
|
-
time=timestamp
|
|
469
|
-
)
|
|
422
|
+
event_attrs[key] = attribute_value_from_python(str(result))
|
|
470
423
|
else:
|
|
471
|
-
event_attrs[key] =
|
|
472
|
-
name=key,
|
|
473
|
-
value=str(value),
|
|
474
|
-
time=timestamp
|
|
475
|
-
)
|
|
424
|
+
event_attrs[key] = attribute_value_from_python(str(value))
|
|
476
425
|
|
|
477
426
|
# Extract from ctx.common
|
|
478
427
|
if hasattr(ctx, 'common') and ctx.common:
|
|
@@ -27,23 +27,26 @@ class JSONEncoder(Encoder):
|
|
|
27
27
|
"event": {
|
|
28
28
|
"id": "evt-123",
|
|
29
29
|
"type": "process_item",
|
|
30
|
-
"
|
|
30
|
+
"activity": null,
|
|
31
|
+
"time": "2025-01-11T12:34:56.789000000Z",
|
|
31
32
|
"attributes": [
|
|
32
|
-
{"name": "priority", "value": "high", "
|
|
33
|
+
{"name": "priority", "value": "high", "type": "string", "time": null}
|
|
33
34
|
],
|
|
34
35
|
"relationships": [
|
|
35
36
|
{"objectId": "obj-456", "qualifier": "input"}
|
|
36
37
|
]
|
|
37
|
-
}
|
|
38
|
+
},
|
|
39
|
+
"object": null
|
|
38
40
|
}
|
|
39
41
|
|
|
40
42
|
Or for objects:
|
|
41
43
|
{
|
|
44
|
+
"event": null,
|
|
42
45
|
"object": {
|
|
43
46
|
"id": "obj-456",
|
|
44
47
|
"type": "WorkItem",
|
|
45
48
|
"attributes": [
|
|
46
|
-
{"name": "status", "value": "pending", "
|
|
49
|
+
{"name": "status", "value": "pending", "type": "string", "time": null}
|
|
47
50
|
],
|
|
48
51
|
"relationships": []
|
|
49
52
|
}
|
|
@@ -60,11 +63,11 @@ class JSONEncoder(Encoder):
|
|
|
60
63
|
Returns:
|
|
61
64
|
JSON-encoded bytes
|
|
62
65
|
"""
|
|
63
|
-
# Convert LogRecord to dict
|
|
66
|
+
# Convert LogRecord to dict with union structure (both fields, one null)
|
|
64
67
|
if record.event is not None:
|
|
65
|
-
data = {"event": self._event_to_dict(record.event)}
|
|
68
|
+
data = {"event": self._event_to_dict(record.event), "object": None}
|
|
66
69
|
else:
|
|
67
|
-
data = {"object": self._object_to_dict(record.object)}
|
|
70
|
+
data = {"event": None, "object": self._object_to_dict(record.object)}
|
|
68
71
|
|
|
69
72
|
# Encode to JSON
|
|
70
73
|
return json.dumps(data, separators=(',', ':')).encode('utf-8')
|
|
@@ -78,6 +81,7 @@ class JSONEncoder(Encoder):
|
|
|
78
81
|
return {
|
|
79
82
|
"id": event.id,
|
|
80
83
|
"type": event.type,
|
|
84
|
+
"activity": event.activity,
|
|
81
85
|
"time": self._format_datetime(event.time),
|
|
82
86
|
"attributes": [
|
|
83
87
|
self._event_attr_to_dict(name, attr)
|
|
@@ -104,21 +108,26 @@ class JSONEncoder(Encoder):
|
|
|
104
108
|
]
|
|
105
109
|
}
|
|
106
110
|
|
|
107
|
-
def _event_attr_to_dict(self, name: str, attr: EventAttributeValue) -> Dict[str,
|
|
111
|
+
def _event_attr_to_dict(self, name: str, attr: EventAttributeValue) -> Dict[str, Any]:
|
|
108
112
|
"""Convert EventAttributeValue to dict."""
|
|
109
113
|
return {
|
|
110
114
|
"name": attr.name or name,
|
|
111
115
|
"value": attr.value,
|
|
112
|
-
"
|
|
116
|
+
"type": attr.type
|
|
113
117
|
}
|
|
114
118
|
|
|
115
|
-
def _object_attr_to_dict(self, name: str, attr: ObjectAttributeValue) -> Dict[str,
|
|
119
|
+
def _object_attr_to_dict(self, name: str, attr: ObjectAttributeValue) -> Dict[str, Any]:
|
|
116
120
|
"""Convert ObjectAttributeValue to dict."""
|
|
117
|
-
|
|
121
|
+
result = {
|
|
118
122
|
"name": attr.name or name,
|
|
119
123
|
"value": attr.value,
|
|
120
|
-
"
|
|
124
|
+
"type": attr.type
|
|
121
125
|
}
|
|
126
|
+
if attr.time is not None:
|
|
127
|
+
result["time"] = self._format_datetime(attr.time)
|
|
128
|
+
else:
|
|
129
|
+
result["time"] = None
|
|
130
|
+
return result
|
|
122
131
|
|
|
123
132
|
def _relationship_to_dict(self, qualifier: str, rel: Relationship) -> Dict[str, str]:
|
|
124
133
|
"""Convert Relationship to dict."""
|
mycorrhizal/spores/extraction.py
CHANGED
|
@@ -41,7 +41,7 @@ def extract_attributes_from_params(
|
|
|
41
41
|
func: The decorated function
|
|
42
42
|
args: Positional arguments passed to function
|
|
43
43
|
kwargs: Keyword arguments passed to function
|
|
44
|
-
timestamp: Event timestamp for attribute
|
|
44
|
+
timestamp: Event timestamp (not used for attribute timestamps)
|
|
45
45
|
|
|
46
46
|
Returns:
|
|
47
47
|
Dictionary of attribute name -> EventAttributeValue
|
|
@@ -60,8 +60,8 @@ def extract_attributes_from_params(
|
|
|
60
60
|
if param_name in ('self', 'cls', 'bb', 'ctx', 'timebase', 'consumed'):
|
|
61
61
|
continue
|
|
62
62
|
|
|
63
|
-
# Extract attribute value
|
|
64
|
-
attr = attribute_value_from_python(param_value
|
|
63
|
+
# Extract attribute value (time=None for event attributes)
|
|
64
|
+
attr = attribute_value_from_python(param_value)
|
|
65
65
|
attributes[param_name] = attr
|
|
66
66
|
|
|
67
67
|
except Exception as e:
|
|
@@ -79,7 +79,7 @@ def extract_attributes_from_dict(
|
|
|
79
79
|
|
|
80
80
|
Args:
|
|
81
81
|
data: Dictionary with attribute values
|
|
82
|
-
timestamp: Event timestamp for attribute
|
|
82
|
+
timestamp: Event timestamp (not used for attribute timestamps)
|
|
83
83
|
|
|
84
84
|
Returns:
|
|
85
85
|
Dictionary of attribute name -> EventAttributeValue
|
|
@@ -87,7 +87,7 @@ def extract_attributes_from_dict(
|
|
|
87
87
|
attributes = {}
|
|
88
88
|
|
|
89
89
|
for key, value in data.items():
|
|
90
|
-
attr = attribute_value_from_python(value
|
|
90
|
+
attr = attribute_value_from_python(value)
|
|
91
91
|
attributes[key] = attr
|
|
92
92
|
|
|
93
93
|
return attributes
|
|
@@ -102,7 +102,7 @@ def extract_attributes_from_blackboard(
|
|
|
102
102
|
|
|
103
103
|
Args:
|
|
104
104
|
bb: Blackboard object
|
|
105
|
-
timestamp: Event timestamp for attribute
|
|
105
|
+
timestamp: Event timestamp (not used for attribute timestamps)
|
|
106
106
|
|
|
107
107
|
Returns:
|
|
108
108
|
Dictionary of attribute name -> EventAttributeValue
|
|
@@ -136,7 +136,7 @@ def extract_attributes_from_blackboard(
|
|
|
136
136
|
attr_name = metadata.name or field_name
|
|
137
137
|
else:
|
|
138
138
|
attr_name = field_name
|
|
139
|
-
attr = attribute_value_from_python(value
|
|
139
|
+
attr = attribute_value_from_python(value)
|
|
140
140
|
attributes[attr_name] = attr
|
|
141
141
|
|
|
142
142
|
except Exception as e:
|
|
@@ -168,13 +168,13 @@ def evaluate_computed_attributes(
|
|
|
168
168
|
# Call the function with blackboard
|
|
169
169
|
try:
|
|
170
170
|
result = value(bb)
|
|
171
|
-
attr = attribute_value_from_python(result
|
|
171
|
+
attr = attribute_value_from_python(result)
|
|
172
172
|
attributes[key] = attr
|
|
173
173
|
except Exception as e:
|
|
174
174
|
logger.error(f"Failed to compute attribute {key}: {e}")
|
|
175
175
|
else:
|
|
176
176
|
# Static value
|
|
177
|
-
attr = attribute_value_from_python(value
|
|
177
|
+
attr = attribute_value_from_python(value)
|
|
178
178
|
attributes[key] = attr
|
|
179
179
|
|
|
180
180
|
return attributes
|
|
@@ -289,6 +289,7 @@ def convert_to_ocel_object(
|
|
|
289
289
|
attr = attr.__class__(
|
|
290
290
|
name=key,
|
|
291
291
|
value=attr.value,
|
|
292
|
+
type=attr.type,
|
|
292
293
|
time=attr.time
|
|
293
294
|
)
|
|
294
295
|
attributes[key] = attr
|
|
@@ -302,6 +303,7 @@ def convert_to_ocel_object(
|
|
|
302
303
|
attr = attr.__class__(
|
|
303
304
|
name=key,
|
|
304
305
|
value=attr.value,
|
|
306
|
+
type=attr.type,
|
|
305
307
|
time=attr.time
|
|
306
308
|
)
|
|
307
309
|
attributes[key] = attr
|
|
@@ -359,6 +361,7 @@ def extract_objects_from_spec(
|
|
|
359
361
|
attr = attr.__class__(
|
|
360
362
|
name=key,
|
|
361
363
|
value=attr.value,
|
|
364
|
+
type=attr.type,
|
|
362
365
|
time=attr.time
|
|
363
366
|
)
|
|
364
367
|
attributes[key] = attr
|
|
@@ -447,12 +450,12 @@ def extract_from_rhizomorph_context(
|
|
|
447
450
|
return attributes, objects
|
|
448
451
|
|
|
449
452
|
|
|
450
|
-
def
|
|
453
|
+
def extract_from_septum_context(
|
|
451
454
|
ctx: Any,
|
|
452
455
|
timestamp: datetime
|
|
453
456
|
) -> tuple[Dict[str, EventAttributeValue], List[Object]]:
|
|
454
457
|
"""
|
|
455
|
-
Extract attributes and objects from
|
|
458
|
+
Extract attributes and objects from Septum state context.
|
|
456
459
|
|
|
457
460
|
Args:
|
|
458
461
|
ctx: SharedContext
|