process-bigraph 0.0.51__tar.gz → 1.0.0__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.
- {process_bigraph-0.0.51/process_bigraph.egg-info → process_bigraph-1.0.0}/PKG-INFO +1 -3
- process_bigraph-1.0.0/process_bigraph/__init__.py +36 -0
- {process_bigraph-0.0.51 → process_bigraph-1.0.0}/process_bigraph/composite.py +113 -69
- {process_bigraph-0.0.51 → process_bigraph-1.0.0}/process_bigraph/emitter.py +38 -116
- {process_bigraph-0.0.51 → process_bigraph-1.0.0}/process_bigraph/experiments/minimal_gillespie.py +1 -2
- process_bigraph-1.0.0/process_bigraph/processes/__init__.py +3 -0
- process_bigraph-1.0.0/process_bigraph/processes/examples.py +243 -0
- {process_bigraph-0.0.51 → process_bigraph-1.0.0}/process_bigraph/processes/growth_division.py +31 -14
- {process_bigraph-0.0.51 → process_bigraph-1.0.0}/process_bigraph/processes/parameter_scan.py +36 -35
- process_bigraph-1.0.0/process_bigraph/protocols/__init__.py +22 -0
- {process_bigraph-0.0.51 → process_bigraph-1.0.0}/process_bigraph/protocols/parallel.py +89 -30
- {process_bigraph-0.0.51 → process_bigraph-1.0.0}/process_bigraph/protocols/rest.py +57 -32
- {process_bigraph-0.0.51 → process_bigraph-1.0.0}/process_bigraph/run.py +3 -3
- {process_bigraph-0.0.51 → process_bigraph-1.0.0/process_bigraph.egg-info}/PKG-INFO +1 -3
- {process_bigraph-0.0.51 → process_bigraph-1.0.0}/process_bigraph.egg-info/SOURCES.txt +1 -8
- {process_bigraph-0.0.51 → process_bigraph-1.0.0}/process_bigraph.egg-info/requires.txt +0 -2
- {process_bigraph-0.0.51 → process_bigraph-1.0.0}/pyproject.toml +3 -6
- process_bigraph-0.0.51/process_bigraph/__init__.py +0 -58
- process_bigraph-0.0.51/process_bigraph/package/__init__.py +0 -0
- process_bigraph-0.0.51/process_bigraph/package/discover.py +0 -103
- process_bigraph-0.0.51/process_bigraph/process_types.py +0 -471
- process_bigraph-0.0.51/process_bigraph/processes/__init__.py +0 -26
- process_bigraph-0.0.51/process_bigraph/protocols/__init__.py +0 -17
- process_bigraph-0.0.51/process_bigraph/protocols/docker.py +0 -262
- process_bigraph-0.0.51/process_bigraph/protocols/local.py +0 -43
- process_bigraph-0.0.51/process_bigraph/protocols/protocol.py +0 -3
- process_bigraph-0.0.51/process_bigraph/tests.py +0 -1330
- process_bigraph-0.0.51/setup.py +0 -10
- {process_bigraph-0.0.51 → process_bigraph-1.0.0}/AUTHORS.md +0 -0
- {process_bigraph-0.0.51 → process_bigraph-1.0.0}/LICENSE +0 -0
- {process_bigraph-0.0.51 → process_bigraph-1.0.0}/README.md +0 -0
- {process_bigraph-0.0.51 → process_bigraph-1.0.0}/process_bigraph/experiments/__init__.py +0 -0
- {process_bigraph-0.0.51 → process_bigraph-1.0.0}/process_bigraph/protocols/socket.py +0 -0
- {process_bigraph-0.0.51 → process_bigraph-1.0.0}/process_bigraph/units.py +0 -0
- {process_bigraph-0.0.51 → process_bigraph-1.0.0}/process_bigraph.egg-info/dependency_links.txt +0 -0
- {process_bigraph-0.0.51 → process_bigraph-1.0.0}/process_bigraph.egg-info/top_level.txt +0 -0
- {process_bigraph-0.0.51 → process_bigraph-1.0.0}/setup.cfg +0 -0
|
@@ -1,17 +1,15 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: process-bigraph
|
|
3
|
-
Version: 0.0
|
|
3
|
+
Version: 1.0.0
|
|
4
4
|
Summary: protocol and execution for compositional systems biology
|
|
5
5
|
Requires-Python: >=3.11
|
|
6
6
|
Description-Content-Type: text/markdown
|
|
7
7
|
License-File: LICENSE
|
|
8
8
|
License-File: AUTHORS.md
|
|
9
9
|
Requires-Dist: bigraph-schema
|
|
10
|
-
Requires-Dist: docker>=7.1.0
|
|
11
10
|
Requires-Dist: ipdb>=0.13.13
|
|
12
11
|
Requires-Dist: matplotlib
|
|
13
12
|
Requires-Dist: pint>=0.24.4
|
|
14
|
-
Requires-Dist: pytest
|
|
15
13
|
Dynamic: license-file
|
|
16
14
|
|
|
17
15
|
# Process-Bigraph
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
from bigraph_schema import allocate_core
|
|
2
|
+
|
|
3
|
+
from process_bigraph.composite import Process, Step, Composite, interval_time_precision
|
|
4
|
+
from process_bigraph.emitter import Emitter, gather_emitter_results, generate_emitter_state
|
|
5
|
+
from process_bigraph.types import StepLink, ProcessLink, CompositeLink
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
import pprint
|
|
9
|
+
pretty = pprint.PrettyPrinter(indent=2)
|
|
10
|
+
|
|
11
|
+
def pp(x):
|
|
12
|
+
"""Print ``x`` in a pretty format."""
|
|
13
|
+
pretty.pprint(x)
|
|
14
|
+
|
|
15
|
+
def pf(x):
|
|
16
|
+
"""Format ``x`` for display."""
|
|
17
|
+
return pretty.pformat(x)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def register_types(core):
|
|
21
|
+
core.register_type('interval', {
|
|
22
|
+
'_inherit': 'float'})
|
|
23
|
+
|
|
24
|
+
core.register_type('default 1', {
|
|
25
|
+
'_inherit': 'float',
|
|
26
|
+
'_default': 1.0})
|
|
27
|
+
|
|
28
|
+
core.register_type('ode_config', {
|
|
29
|
+
'stoichiometry': {
|
|
30
|
+
'_type': 'array',
|
|
31
|
+
'_data': 'int64'},
|
|
32
|
+
'rates': 'map[float]',
|
|
33
|
+
'species': 'map[float]'})
|
|
34
|
+
|
|
35
|
+
return core
|
|
36
|
+
|
|
@@ -24,8 +24,8 @@ from typing import (
|
|
|
24
24
|
import collections
|
|
25
25
|
|
|
26
26
|
from bigraph_schema import (
|
|
27
|
-
Edge,
|
|
28
|
-
get_path, set_path, resolve_path, hierarchy_depth,
|
|
27
|
+
Edge,
|
|
28
|
+
get_path, set_path, resolve_path, hierarchy_depth,
|
|
29
29
|
is_schema_key, strip_schema_keys)
|
|
30
30
|
|
|
31
31
|
from bigraph_schema.protocols import local_lookup_module
|
|
@@ -120,6 +120,8 @@ def find_step_triggers(
|
|
|
120
120
|
|
|
121
121
|
for wire in wire_paths:
|
|
122
122
|
trigger_path = resolve_path(prefix + tuple(wire))
|
|
123
|
+
if isinstance(trigger_path, list):
|
|
124
|
+
import ipdb; ipdb.set_trace()
|
|
123
125
|
triggers.setdefault(trigger_path, []).append(path)
|
|
124
126
|
|
|
125
127
|
return triggers
|
|
@@ -404,7 +406,7 @@ class Open(Edge):
|
|
|
404
406
|
'initial_state', 'inputs', 'outputs', 'update')
|
|
405
407
|
|
|
406
408
|
ATTRIBUTE_READ_COMMANDS = (
|
|
407
|
-
'config', '
|
|
409
|
+
'config', 'schema', 'state')
|
|
408
410
|
|
|
409
411
|
|
|
410
412
|
def __init__(self, config=None, core=None):
|
|
@@ -678,7 +680,7 @@ def as_step(inputs, outputs, core=None):
|
|
|
678
680
|
FunctionStep.__name__ = step_name + 'Step'
|
|
679
681
|
|
|
680
682
|
if core is not None:
|
|
681
|
-
core.
|
|
683
|
+
core.register_link(step_name, FunctionStep)
|
|
682
684
|
|
|
683
685
|
return FunctionStep
|
|
684
686
|
|
|
@@ -710,7 +712,7 @@ def as_process(inputs, outputs, core=None):
|
|
|
710
712
|
FunctionProcess.__name__ = process_name + 'Process'
|
|
711
713
|
|
|
712
714
|
if core is not None:
|
|
713
|
-
core.
|
|
715
|
+
core.register_link(process_name, FunctionProcess)
|
|
714
716
|
|
|
715
717
|
return FunctionProcess
|
|
716
718
|
|
|
@@ -748,13 +750,13 @@ class ProcessEnsemble(Process):
|
|
|
748
750
|
inputs_func = getattr(self, attr_name)
|
|
749
751
|
if callable(inputs_func):
|
|
750
752
|
inputs = inputs_func()
|
|
751
|
-
union_inputs = self.core.
|
|
753
|
+
union_inputs = self.core.resolve(union_inputs, inputs)
|
|
752
754
|
|
|
753
755
|
if attr_name.startswith('outputs_'):
|
|
754
756
|
outputs_func = getattr(self, attr_name)
|
|
755
757
|
if callable(outputs_func):
|
|
756
758
|
outputs = outputs_func()
|
|
757
|
-
union_outputs = self.core.
|
|
759
|
+
union_outputs = self.core.resolve(union_outputs, outputs)
|
|
758
760
|
|
|
759
761
|
return {
|
|
760
762
|
'inputs': union_inputs,
|
|
@@ -836,8 +838,8 @@ class Composite(Process):
|
|
|
836
838
|
"""
|
|
837
839
|
|
|
838
840
|
config_schema = {
|
|
839
|
-
'
|
|
840
|
-
'state': 'tree[
|
|
841
|
+
'schema': 'schema',
|
|
842
|
+
'state': 'tree[node]',
|
|
841
843
|
'interface': {
|
|
842
844
|
'inputs': 'schema',
|
|
843
845
|
'outputs': 'schema'
|
|
@@ -860,7 +862,7 @@ class Composite(Process):
|
|
|
860
862
|
|
|
861
863
|
This method:
|
|
862
864
|
- Adds `global_time` to schema/state if missing
|
|
863
|
-
- Generates the full
|
|
865
|
+
- Generates the full schema/state tree
|
|
864
866
|
- Finds all step/process instances
|
|
865
867
|
- Resolves the schema bridge
|
|
866
868
|
- Prepares the step execution network
|
|
@@ -870,12 +872,12 @@ class Composite(Process):
|
|
|
870
872
|
config: Optional override configuration (usually not needed).
|
|
871
873
|
"""
|
|
872
874
|
|
|
873
|
-
# Get the initial
|
|
874
|
-
|
|
875
|
+
# Get the initial schema schema from config.
|
|
876
|
+
initial_schema = self.config.get('schema', {})
|
|
875
877
|
|
|
876
878
|
# Ensure 'global_time' is explicitly declared in the schema.
|
|
877
|
-
if 'global_time' not in
|
|
878
|
-
|
|
879
|
+
if 'global_time' not in initial_schema:
|
|
880
|
+
initial_schema['global_time'] = 'float'
|
|
879
881
|
|
|
880
882
|
# Get the initial state from config.
|
|
881
883
|
initial_state = self.config.get('state', {})
|
|
@@ -885,8 +887,9 @@ class Composite(Process):
|
|
|
885
887
|
initial_state['global_time'] = 0.0
|
|
886
888
|
|
|
887
889
|
# Generate internal schema and state structures using the core engine.
|
|
888
|
-
self.
|
|
889
|
-
|
|
890
|
+
# self.schema, self.state = self.core.generate(
|
|
891
|
+
self.schema, self.state = self.core.realize(
|
|
892
|
+
initial_schema,
|
|
890
893
|
initial_state)
|
|
891
894
|
|
|
892
895
|
# Load the bridge configuration, which defines how inputs/outputs connect to the world.
|
|
@@ -902,29 +905,39 @@ class Composite(Process):
|
|
|
902
905
|
self.edge_paths = {**self.process_paths, **self.step_paths}
|
|
903
906
|
|
|
904
907
|
# Initialize each process/step's state and accumulate it into a unified state tree.
|
|
905
|
-
|
|
908
|
+
edge_schema = {}
|
|
909
|
+
edge_state = {}
|
|
906
910
|
for path, edge in self.edge_paths.items():
|
|
907
911
|
# Generate the initial state for this specific edge (process or step).
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
path
|
|
911
|
-
edge)
|
|
912
|
+
initial_schema, initial_state = self.core.link_state(
|
|
913
|
+
edge,
|
|
914
|
+
path)
|
|
912
915
|
|
|
913
916
|
# Merge the new edge state with the global state tree, checking for conflicts.
|
|
914
917
|
try:
|
|
915
|
-
edge_state =
|
|
916
|
-
|
|
918
|
+
edge_schema, edge_state = self.core.combine(
|
|
919
|
+
edge_schema, edge_state,
|
|
920
|
+
initial_schema, initial_state)
|
|
921
|
+
|
|
922
|
+
except Exception as e:
|
|
917
923
|
raise Exception(
|
|
918
924
|
f'initial state from edge does not match initial state from other edges:\n'
|
|
919
925
|
f'{path}\n{edge}\n{edge_state}'
|
|
926
|
+
f'{e.message}'
|
|
920
927
|
)
|
|
921
928
|
|
|
922
929
|
# Apply the merged edge_state into the global state and update instance paths.
|
|
923
|
-
|
|
930
|
+
if edge_state:
|
|
931
|
+
self.schema, self.state = self.core.combine(
|
|
932
|
+
edge_schema, edge_state,
|
|
933
|
+
self.schema, self.state)
|
|
924
934
|
|
|
925
935
|
# Wire the input/output schema for the Composite from the bridge config.
|
|
926
936
|
self.process_schema = {
|
|
927
|
-
port: self.core.wire_schema(
|
|
937
|
+
port: self.core.wire_schema(
|
|
938
|
+
self.schema,
|
|
939
|
+
self.state,
|
|
940
|
+
self.bridge[port])
|
|
928
941
|
for port in ['inputs', 'outputs']
|
|
929
942
|
}
|
|
930
943
|
|
|
@@ -952,7 +965,7 @@ class Composite(Process):
|
|
|
952
965
|
Load a Composite from a saved JSON file.
|
|
953
966
|
|
|
954
967
|
Args:
|
|
955
|
-
path: Path to the saved
|
|
968
|
+
path: Path to the saved schema file.
|
|
956
969
|
core: Optional core context providing deserialization.
|
|
957
970
|
|
|
958
971
|
Returns:
|
|
@@ -960,8 +973,6 @@ class Composite(Process):
|
|
|
960
973
|
"""
|
|
961
974
|
with open(path) as data:
|
|
962
975
|
document = json.load(data)
|
|
963
|
-
composition = document['composition']
|
|
964
|
-
document['composition'] = core.deserialize('schema', composition)
|
|
965
976
|
return cls(document, core=core)
|
|
966
977
|
|
|
967
978
|
def clean_front(self, state):
|
|
@@ -976,7 +987,13 @@ class Composite(Process):
|
|
|
976
987
|
- self.step_paths
|
|
977
988
|
"""
|
|
978
989
|
self.process_paths = find_instance_paths(state, 'process_bigraph.composite.Process')
|
|
979
|
-
|
|
990
|
+
if hasattr(self, 'step_paths'):
|
|
991
|
+
previous_step_paths = self.step_paths.keys()
|
|
992
|
+
self.step_paths = find_instance_paths(state, 'process_bigraph.composite.Step')
|
|
993
|
+
if previous_step_paths != self.step_paths.keys():
|
|
994
|
+
self.build_step_network()
|
|
995
|
+
else:
|
|
996
|
+
self.step_paths = find_instance_paths(state, 'process_bigraph.composite.Step')
|
|
980
997
|
|
|
981
998
|
all_paths = set(
|
|
982
999
|
list(self.process_paths.keys()) +
|
|
@@ -999,12 +1016,13 @@ class Composite(Process):
|
|
|
999
1016
|
path: Path where merge should occur (default: root).
|
|
1000
1017
|
"""
|
|
1001
1018
|
path = path or []
|
|
1002
|
-
self.
|
|
1003
|
-
|
|
1019
|
+
# self.schema, self.state = self.core.merge(
|
|
1020
|
+
self.schema, self.state = self.core.combine(
|
|
1021
|
+
self.schema,
|
|
1004
1022
|
self.state,
|
|
1005
|
-
path,
|
|
1006
1023
|
schema,
|
|
1007
1024
|
state)
|
|
1025
|
+
|
|
1008
1026
|
self.find_instance_paths(self.state)
|
|
1009
1027
|
|
|
1010
1028
|
def merge_schema(
|
|
@@ -1025,10 +1043,10 @@ class Composite(Process):
|
|
|
1025
1043
|
scoped_schema = set_path({}, path, schema)
|
|
1026
1044
|
|
|
1027
1045
|
# Merge it into the existing schema
|
|
1028
|
-
self.
|
|
1046
|
+
self.schema = self.core.merge(self.schema, scoped_schema)
|
|
1029
1047
|
|
|
1030
1048
|
# Re-generate state based on the new schema structure
|
|
1031
|
-
self.
|
|
1049
|
+
self.schema, self.state = self.core.generate(self.schema, self.state)
|
|
1032
1050
|
|
|
1033
1051
|
# Re-scan the state tree for processes and steps
|
|
1034
1052
|
self.find_instance_paths(self.state)
|
|
@@ -1043,7 +1061,7 @@ class Composite(Process):
|
|
|
1043
1061
|
"""
|
|
1044
1062
|
path = path or []
|
|
1045
1063
|
scoped_update = set_path({}, path, update)
|
|
1046
|
-
self.state = self.core.apply(self.
|
|
1064
|
+
self.state = self.core.apply(self.schema, self.state, scoped_update)
|
|
1047
1065
|
self.find_instance_paths(self.state)
|
|
1048
1066
|
|
|
1049
1067
|
|
|
@@ -1058,16 +1076,17 @@ class Composite(Process):
|
|
|
1058
1076
|
Returns:
|
|
1059
1077
|
A serialized representation of the current state.
|
|
1060
1078
|
"""
|
|
1061
|
-
return self.core.serialize(self.
|
|
1079
|
+
return self.core.serialize(self.schema, self.state)
|
|
1062
1080
|
|
|
1063
1081
|
def serialize_schema(self) -> Dict[str, Any]:
|
|
1064
1082
|
"""
|
|
1065
|
-
Serialize the
|
|
1083
|
+
Serialize the schema (schema) using the core serializer.
|
|
1066
1084
|
|
|
1067
1085
|
Returns:
|
|
1068
1086
|
A serialized schema representation.
|
|
1069
1087
|
"""
|
|
1070
|
-
return self.core.
|
|
1088
|
+
return self.core.render(self.schema)
|
|
1089
|
+
# return self.core.serialize('schema', self.schema)
|
|
1071
1090
|
|
|
1072
1091
|
def save(
|
|
1073
1092
|
self,
|
|
@@ -1092,7 +1111,7 @@ class Composite(Process):
|
|
|
1092
1111
|
if state:
|
|
1093
1112
|
document['state'] = self.serialize_state()
|
|
1094
1113
|
if schema:
|
|
1095
|
-
document['
|
|
1114
|
+
document['schema'] = self.serialize_schema()
|
|
1096
1115
|
|
|
1097
1116
|
os.makedirs(outdir, exist_ok=True)
|
|
1098
1117
|
filepath = os.path.join(outdir, filename)
|
|
@@ -1128,13 +1147,15 @@ class Composite(Process):
|
|
|
1128
1147
|
"""
|
|
1129
1148
|
state = state or self.state
|
|
1130
1149
|
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1150
|
+
# if 'environment' in state and '_add' in state['environment']:
|
|
1151
|
+
# import ipdb; ipdb.set_trace()
|
|
1152
|
+
|
|
1153
|
+
bridge_view = self.core.view_ports(
|
|
1154
|
+
self.schema,
|
|
1155
|
+
state,
|
|
1134
1156
|
(),
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
)
|
|
1157
|
+
self.interface()['outputs'],
|
|
1158
|
+
self.bridge['outputs'])
|
|
1138
1159
|
|
|
1139
1160
|
return bridge_view
|
|
1140
1161
|
|
|
@@ -1268,14 +1289,13 @@ class Composite(Process):
|
|
|
1268
1289
|
|
|
1269
1290
|
for step_path in step_paths:
|
|
1270
1291
|
step = get_path(self.state, step_path)
|
|
1271
|
-
state = self.core.
|
|
1272
|
-
self.
|
|
1273
|
-
)
|
|
1292
|
+
state = self.core.view(
|
|
1293
|
+
self.schema, self.state, step_path, 'inputs')
|
|
1274
1294
|
|
|
1275
1295
|
# Steps are always invoked with interval = -1.0
|
|
1276
1296
|
step_update = self.process_update(
|
|
1277
|
-
step_path, step, state, -1.0, 'outputs'
|
|
1278
|
-
|
|
1297
|
+
step_path, step, state, -1.0, 'outputs')
|
|
1298
|
+
|
|
1279
1299
|
updates.append(step_update)
|
|
1280
1300
|
|
|
1281
1301
|
update_paths = self.apply_updates(updates)
|
|
@@ -1364,7 +1384,7 @@ class Composite(Process):
|
|
|
1364
1384
|
and captures its update as a deferred computation.
|
|
1365
1385
|
|
|
1366
1386
|
Args:
|
|
1367
|
-
path: The path to the process in the state/
|
|
1387
|
+
path: The path to the process in the state/schema tree.
|
|
1368
1388
|
process: The dictionary representing the process (must contain 'interval').
|
|
1369
1389
|
end_time: The simulation time to run up to.
|
|
1370
1390
|
full_step: The current smallest time step among all processes.
|
|
@@ -1387,7 +1407,10 @@ class Composite(Process):
|
|
|
1387
1407
|
state = future_front['state']
|
|
1388
1408
|
else:
|
|
1389
1409
|
# Otherwise, slice the current state for the process
|
|
1390
|
-
state = self.core.
|
|
1410
|
+
state = self.core.view(
|
|
1411
|
+
self.schema,
|
|
1412
|
+
self.state,
|
|
1413
|
+
path)
|
|
1391
1414
|
process_interval = process['interval']
|
|
1392
1415
|
|
|
1393
1416
|
# Determine the target time for the next update
|
|
@@ -1437,7 +1460,7 @@ class Composite(Process):
|
|
|
1437
1460
|
into absolute state terms until `.get()` is called on the returned `Defer` object.
|
|
1438
1461
|
|
|
1439
1462
|
Args:
|
|
1440
|
-
path: The path to the process in the state/
|
|
1463
|
+
path: The path to the process in the state/schema tree.
|
|
1441
1464
|
process: The dictionary representing the process instance (must include 'instance').
|
|
1442
1465
|
states: The current state values at the process’s ports.
|
|
1443
1466
|
interval: The time interval to simulate.
|
|
@@ -1451,14 +1474,22 @@ class Composite(Process):
|
|
|
1451
1474
|
|
|
1452
1475
|
# Invoke the process and retrieve a wrapped SyncUpdate object
|
|
1453
1476
|
update = process['instance'].invoke(clean_state, interval)
|
|
1454
|
-
|
|
1455
1477
|
# This nested function projects the update into the global state at the given path
|
|
1456
|
-
def defer_project(
|
|
1478
|
+
def defer_project(update_results: Any, args: Tuple[Any, Any, Union[str, Tuple[str, ...]]]) -> Any:
|
|
1457
1479
|
schema, state, process_path = args
|
|
1458
|
-
|
|
1480
|
+
|
|
1481
|
+
if not isinstance(update_results, list):
|
|
1482
|
+
update_results = [update_results]
|
|
1483
|
+
|
|
1484
|
+
return [self.core.project(
|
|
1485
|
+
schema,
|
|
1486
|
+
state,
|
|
1487
|
+
process_path,
|
|
1488
|
+
update_result,
|
|
1489
|
+
ports_key) for update_result in update_results]
|
|
1459
1490
|
|
|
1460
1491
|
# Return a deferred object that will project the update when requested
|
|
1461
|
-
return Defer(update, defer_project, (self.
|
|
1492
|
+
return Defer(update, defer_project, (self.schema, self.state, path))
|
|
1462
1493
|
|
|
1463
1494
|
def apply_updates(self, updates: List["Defer"]) -> List[Union[str, Tuple[str, ...]]]:
|
|
1464
1495
|
"""
|
|
@@ -1484,22 +1515,33 @@ class Composite(Process):
|
|
|
1484
1515
|
if not isinstance(series, list):
|
|
1485
1516
|
series = [series]
|
|
1486
1517
|
|
|
1487
|
-
for
|
|
1518
|
+
for update_schema, update_state in series:
|
|
1488
1519
|
# if update and isinstance(update, dict) and 'environment' in update and update['environment'] and isinstance(update['environment'], dict) and '_react' in update['environment']:
|
|
1489
1520
|
# import ipdb; ipdb.set_trace()
|
|
1490
1521
|
|
|
1491
1522
|
# Extract all hierarchical paths touched by this update
|
|
1492
|
-
paths = hierarchy_depth(
|
|
1523
|
+
paths = hierarchy_depth(update_state)
|
|
1493
1524
|
update_paths.extend(paths.keys())
|
|
1494
1525
|
|
|
1495
|
-
# Apply update directly to the internal state
|
|
1496
|
-
|
|
1526
|
+
# Apply update directly to the internal state,
|
|
1527
|
+
# using the schema from the link itself
|
|
1528
|
+
self.state, merges = self.core.apply(
|
|
1529
|
+
update_schema,
|
|
1530
|
+
self.state,
|
|
1531
|
+
update_state)
|
|
1532
|
+
|
|
1533
|
+
self.schema = self.core.resolve_merges(
|
|
1534
|
+
self.schema,
|
|
1535
|
+
merges)
|
|
1497
1536
|
|
|
1498
1537
|
# Read updated bridge outputs, if available
|
|
1499
|
-
bridge_update = self.read_bridge(
|
|
1538
|
+
bridge_update = self.read_bridge(update_state)
|
|
1500
1539
|
if bridge_update:
|
|
1501
1540
|
self.bridge_updates.append(bridge_update)
|
|
1502
1541
|
|
|
1542
|
+
self.schema, self.state = self.core.realize(self.schema, self.state)
|
|
1543
|
+
|
|
1544
|
+
# TODO: are we doing this twice?
|
|
1503
1545
|
# Refresh process and step instance paths
|
|
1504
1546
|
self.find_instance_paths(self.state)
|
|
1505
1547
|
|
|
@@ -1549,17 +1591,19 @@ class Composite(Process):
|
|
|
1549
1591
|
Returns:
|
|
1550
1592
|
A list of updates generated for the bridge outputs.
|
|
1551
1593
|
"""
|
|
1552
|
-
|
|
1594
|
+
project_schema, project_state = self.core.project_ports(
|
|
1553
1595
|
self.interface()['inputs'],
|
|
1554
1596
|
self.bridge['inputs'],
|
|
1555
1597
|
[],
|
|
1556
|
-
state
|
|
1557
|
-
)
|
|
1598
|
+
state)
|
|
1599
|
+
self.merge({}, project_state)
|
|
1558
1600
|
|
|
1559
|
-
self.
|
|
1560
|
-
self.
|
|
1601
|
+
# first_update = self.read_bridge(
|
|
1602
|
+
# self.state)
|
|
1603
|
+
# self.bridge_updates = [first_update]
|
|
1561
1604
|
|
|
1562
|
-
updates = self.bridge_updates
|
|
1563
1605
|
self.bridge_updates = []
|
|
1564
1606
|
|
|
1565
|
-
|
|
1607
|
+
self.run(interval)
|
|
1608
|
+
|
|
1609
|
+
return self.bridge_updates
|