bigraph-schema 1.0.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.
- bigraph_schema/__init__.py +112 -0
- bigraph_schema/core.py +759 -0
- bigraph_schema/edge.py +138 -0
- bigraph_schema/methods/__init__.py +12 -0
- bigraph_schema/methods/apply.py +276 -0
- bigraph_schema/methods/check.py +213 -0
- bigraph_schema/methods/default.py +204 -0
- bigraph_schema/methods/generalize.py +309 -0
- bigraph_schema/methods/handle_parameters.py +182 -0
- bigraph_schema/methods/infer.py +217 -0
- bigraph_schema/methods/jump.py +432 -0
- bigraph_schema/methods/merge.py +405 -0
- bigraph_schema/methods/realize.py +527 -0
- bigraph_schema/methods/resolve.py +692 -0
- bigraph_schema/methods/serialize.py +491 -0
- bigraph_schema/methods/validate.py +249 -0
- bigraph_schema/package/__init__.py +1 -0
- bigraph_schema/package/discover.py +122 -0
- bigraph_schema/parse.py +183 -0
- bigraph_schema/protocols.py +57 -0
- bigraph_schema/schema.py +370 -0
- bigraph_schema/units.py +133 -0
- bigraph_schema-1.0.0.dist-info/METADATA +66 -0
- bigraph_schema-1.0.0.dist-info/RECORD +28 -0
- bigraph_schema-1.0.0.dist-info/WHEEL +5 -0
- bigraph_schema-1.0.0.dist-info/licenses/AUTHORS.md +6 -0
- bigraph_schema-1.0.0.dist-info/licenses/LICENSE +201 -0
- bigraph_schema-1.0.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,491 @@
|
|
|
1
|
+
from plum import dispatch
|
|
2
|
+
import numpy as np
|
|
3
|
+
from numpy.random.mtrand import RandomState
|
|
4
|
+
|
|
5
|
+
from bigraph_schema.schema import (
|
|
6
|
+
Node,
|
|
7
|
+
Atom,
|
|
8
|
+
Empty,
|
|
9
|
+
NONE_SYMBOL,
|
|
10
|
+
Union,
|
|
11
|
+
Tuple,
|
|
12
|
+
Boolean,
|
|
13
|
+
Number,
|
|
14
|
+
Integer,
|
|
15
|
+
Float,
|
|
16
|
+
Delta,
|
|
17
|
+
Nonnegative,
|
|
18
|
+
NPRandom,
|
|
19
|
+
String,
|
|
20
|
+
Enum,
|
|
21
|
+
Wrap,
|
|
22
|
+
Maybe,
|
|
23
|
+
Overwrite,
|
|
24
|
+
List,
|
|
25
|
+
Map,
|
|
26
|
+
Tree,
|
|
27
|
+
Array,
|
|
28
|
+
Key,
|
|
29
|
+
Path,
|
|
30
|
+
Wires,
|
|
31
|
+
Schema,
|
|
32
|
+
Link,
|
|
33
|
+
dtype_schema,
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
from bigraph_schema.methods.check import check
|
|
37
|
+
from bigraph_schema.methods.resolve import resolve
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def wrap_default(schema, result):
|
|
41
|
+
found = None
|
|
42
|
+
if isinstance(schema, Node) and schema._default:
|
|
43
|
+
found = schema._default
|
|
44
|
+
elif isinstance(schema, dict) and '_default' in schema:
|
|
45
|
+
found = schema['_default']
|
|
46
|
+
|
|
47
|
+
if found:
|
|
48
|
+
inner_default = found
|
|
49
|
+
if isinstance(result, str) and isinstance(inner_default, str):
|
|
50
|
+
result = result + '{' + inner_default + '}'
|
|
51
|
+
elif isinstance(result, dict) and '_type' in result:
|
|
52
|
+
result['_default'] = inner_default
|
|
53
|
+
else:
|
|
54
|
+
result = {
|
|
55
|
+
'_type': result,
|
|
56
|
+
'_default': inner_default}
|
|
57
|
+
|
|
58
|
+
return result
|
|
59
|
+
|
|
60
|
+
@dispatch
|
|
61
|
+
def render(schema: Empty, defaults=False):
|
|
62
|
+
return 'empty'
|
|
63
|
+
|
|
64
|
+
@dispatch
|
|
65
|
+
def render(schema: Maybe, defaults=False):
|
|
66
|
+
value = render(schema._value, defaults=defaults)
|
|
67
|
+
if isinstance(value, str):
|
|
68
|
+
result = f'maybe[{value}]'
|
|
69
|
+
else:
|
|
70
|
+
result = {
|
|
71
|
+
'_type': 'maybe',
|
|
72
|
+
'_value': value}
|
|
73
|
+
return wrap_default(schema, result) if defaults else result
|
|
74
|
+
|
|
75
|
+
@dispatch
|
|
76
|
+
def render(schema: Overwrite, defaults=False):
|
|
77
|
+
value = render(schema._value, defaults=defaults)
|
|
78
|
+
if isinstance(value, str):
|
|
79
|
+
result = f'overwrite[{value}]'
|
|
80
|
+
else:
|
|
81
|
+
result = {
|
|
82
|
+
'_type': 'overwrite',
|
|
83
|
+
'_value': value}
|
|
84
|
+
return wrap_default(schema, result) if defaults else result
|
|
85
|
+
|
|
86
|
+
@dispatch
|
|
87
|
+
def render(schema: Wrap, defaults=False):
|
|
88
|
+
value = render(schema._value, defaults=defaults)
|
|
89
|
+
if isinstance(value, str):
|
|
90
|
+
result = f'wrap[{value}]'
|
|
91
|
+
else:
|
|
92
|
+
result = {
|
|
93
|
+
'_type': 'wrap',
|
|
94
|
+
'_value': value}
|
|
95
|
+
return wrap_default(schema, result) if defaults else result
|
|
96
|
+
|
|
97
|
+
@dispatch
|
|
98
|
+
def render(schema: Union, defaults=False):
|
|
99
|
+
options = [
|
|
100
|
+
render(option, defaults=defaults)
|
|
101
|
+
for option in schema._options]
|
|
102
|
+
if all([isinstance(option,str) for option in options]):
|
|
103
|
+
result = '~'.join(options)
|
|
104
|
+
else:
|
|
105
|
+
result = {
|
|
106
|
+
'_type': 'union',
|
|
107
|
+
'_options': options}
|
|
108
|
+
return wrap_default(schema, result) if defaults else result
|
|
109
|
+
|
|
110
|
+
@dispatch
|
|
111
|
+
def render(schema: Tuple, defaults=False):
|
|
112
|
+
values = [
|
|
113
|
+
render(value, defaults=defaults)
|
|
114
|
+
for value in schema._values]
|
|
115
|
+
if all([isinstance(value, str) for value in values]):
|
|
116
|
+
join = ','.join(values)
|
|
117
|
+
result = f'tuple[{join}]'
|
|
118
|
+
else:
|
|
119
|
+
result = {
|
|
120
|
+
'_type': 'tuple',
|
|
121
|
+
'_values': values}
|
|
122
|
+
return wrap_default(schema, result) if defaults else result
|
|
123
|
+
|
|
124
|
+
@dispatch
|
|
125
|
+
def render(schema: Boolean, defaults=False):
|
|
126
|
+
result = 'boolean'
|
|
127
|
+
return wrap_default(schema, result) if defaults else result
|
|
128
|
+
|
|
129
|
+
@dispatch
|
|
130
|
+
def render(schema: Integer, defaults=False):
|
|
131
|
+
result = 'integer'
|
|
132
|
+
return wrap_default(schema, result) if defaults else result
|
|
133
|
+
|
|
134
|
+
@dispatch
|
|
135
|
+
def render(schema: Delta, defaults=False):
|
|
136
|
+
result = 'delta'
|
|
137
|
+
return wrap_default(schema, result) if defaults else result
|
|
138
|
+
|
|
139
|
+
@dispatch
|
|
140
|
+
def render(schema: Nonnegative, defaults=False):
|
|
141
|
+
result = 'nonnegative'
|
|
142
|
+
return wrap_default(schema, result) if defaults else result
|
|
143
|
+
|
|
144
|
+
@dispatch
|
|
145
|
+
def render(schema: Float, defaults=False):
|
|
146
|
+
result = 'float'
|
|
147
|
+
return wrap_default(schema, result) if defaults else result
|
|
148
|
+
|
|
149
|
+
@dispatch
|
|
150
|
+
def render(schema: Number, defaults=False):
|
|
151
|
+
result = 'number'
|
|
152
|
+
return wrap_default(schema, result) if defaults else result
|
|
153
|
+
|
|
154
|
+
@dispatch
|
|
155
|
+
def render(schema: String, defaults=False):
|
|
156
|
+
result = 'string'
|
|
157
|
+
return wrap_default(schema, result) if defaults else result
|
|
158
|
+
|
|
159
|
+
@dispatch
|
|
160
|
+
def render(schema: Enum, defaults=False):
|
|
161
|
+
values = ','.join(schema._values)
|
|
162
|
+
result = f'enum[{values}]'
|
|
163
|
+
return wrap_default(schema, result) if defaults else result
|
|
164
|
+
|
|
165
|
+
@dispatch
|
|
166
|
+
def render(schema: List, defaults=False):
|
|
167
|
+
element = render(schema._element, defaults=defaults)
|
|
168
|
+
if isinstance(element, str):
|
|
169
|
+
result = f'list[{element}]'
|
|
170
|
+
else:
|
|
171
|
+
result = {
|
|
172
|
+
'_type': 'list',
|
|
173
|
+
'_element': element}
|
|
174
|
+
|
|
175
|
+
return wrap_default(schema, result) if defaults else result
|
|
176
|
+
|
|
177
|
+
@dispatch
|
|
178
|
+
def render(schema: Map, defaults=False):
|
|
179
|
+
key = render(schema._key, defaults=defaults)
|
|
180
|
+
value = render(schema._value, defaults=defaults)
|
|
181
|
+
|
|
182
|
+
if isinstance(key, str) and isinstance(value,str):
|
|
183
|
+
if key == 'string':
|
|
184
|
+
result = f'map[{value}]'
|
|
185
|
+
else:
|
|
186
|
+
result = f'map[{key},{value}]'
|
|
187
|
+
else:
|
|
188
|
+
result = {
|
|
189
|
+
'_type': 'map',
|
|
190
|
+
'_key': key,
|
|
191
|
+
'_value': value}
|
|
192
|
+
|
|
193
|
+
return wrap_default(schema, result) if defaults else result
|
|
194
|
+
|
|
195
|
+
@dispatch
|
|
196
|
+
def render(schema: Tree, defaults=False):
|
|
197
|
+
leaf = render(schema._leaf, defaults=defaults)
|
|
198
|
+
if isinstance(leaf, str):
|
|
199
|
+
result = f'tree[{leaf}]'
|
|
200
|
+
else:
|
|
201
|
+
result = {'_type': 'tree', '_leaf': leaf}
|
|
202
|
+
|
|
203
|
+
return wrap_default(schema, result) if defaults else result
|
|
204
|
+
|
|
205
|
+
@dispatch
|
|
206
|
+
def render(schema: NPRandom, defaults=False):
|
|
207
|
+
result = {
|
|
208
|
+
'_type': 'random_state',
|
|
209
|
+
'state': render(schema.state, defaults=defaults)}
|
|
210
|
+
return wrap_default(schema, result) if defaults else result
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
@dispatch
|
|
214
|
+
def render(schema: np.dtype, defaults=False):
|
|
215
|
+
dtype = dtype_schema(schema)
|
|
216
|
+
return render(dtype, defaults=defaults)
|
|
217
|
+
|
|
218
|
+
@dispatch
|
|
219
|
+
def render(schema: Array, defaults=False):
|
|
220
|
+
shape = '|'.join([str(value) for value in schema._shape])
|
|
221
|
+
data_schema = dtype_schema(schema._data)
|
|
222
|
+
data = render(
|
|
223
|
+
data_schema,
|
|
224
|
+
defaults=defaults)
|
|
225
|
+
|
|
226
|
+
result = f'array[{shape},{data}]'
|
|
227
|
+
return wrap_default(schema, result) if defaults else result
|
|
228
|
+
|
|
229
|
+
@dispatch
|
|
230
|
+
def render(schema: Key, defaults=False):
|
|
231
|
+
result = 'key'
|
|
232
|
+
return wrap_default(schema, result) if defaults else result
|
|
233
|
+
|
|
234
|
+
@dispatch
|
|
235
|
+
def render(schema: Path, defaults=False):
|
|
236
|
+
result = 'path'
|
|
237
|
+
return wrap_default(schema, result) if defaults else result
|
|
238
|
+
|
|
239
|
+
@dispatch
|
|
240
|
+
def render(schema: Wires, defaults=False):
|
|
241
|
+
result = 'wires'
|
|
242
|
+
return wrap_default(schema, result) if defaults else result
|
|
243
|
+
|
|
244
|
+
@dispatch
|
|
245
|
+
def render(schema: Link, defaults=False):
|
|
246
|
+
intermediate = {
|
|
247
|
+
'_type': 'link',
|
|
248
|
+
'_inputs': render(schema._inputs, defaults=defaults),
|
|
249
|
+
'_outputs': render(schema._outputs, defaults=defaults),
|
|
250
|
+
'inputs': render(schema.inputs, defaults=defaults),
|
|
251
|
+
'outputs': render(schema.outputs, defaults=defaults)}
|
|
252
|
+
|
|
253
|
+
if isinstance(intermediate['_inputs'], str) and isinstance(intermediate['_outputs'], str):
|
|
254
|
+
result = f'link[{intermediate["_inputs"]},{intermediate["_outputs"]}]'
|
|
255
|
+
else:
|
|
256
|
+
result = intermediate
|
|
257
|
+
|
|
258
|
+
return wrap_default(schema, result) if defaults else result
|
|
259
|
+
|
|
260
|
+
@dispatch
|
|
261
|
+
def render(schema: dict, defaults=False):
|
|
262
|
+
if '_type' in schema:
|
|
263
|
+
return schema
|
|
264
|
+
else:
|
|
265
|
+
parts = {}
|
|
266
|
+
for key, value in schema.items():
|
|
267
|
+
subrender = render(value, defaults=defaults)
|
|
268
|
+
parts[key] = subrender
|
|
269
|
+
|
|
270
|
+
if not defaults:
|
|
271
|
+
parts = render_associated(parts)
|
|
272
|
+
|
|
273
|
+
return wrap_default(schema, parts) if defaults else parts
|
|
274
|
+
|
|
275
|
+
@dispatch
|
|
276
|
+
def render(schema: np.str_, defaults=False):
|
|
277
|
+
return str(schema)
|
|
278
|
+
|
|
279
|
+
@dispatch
|
|
280
|
+
def render(schema: Node, defaults=False):
|
|
281
|
+
subrender = {}
|
|
282
|
+
|
|
283
|
+
for key in schema.__dataclass_fields__:
|
|
284
|
+
value = getattr(schema,key)
|
|
285
|
+
if key == '_default':
|
|
286
|
+
subrender[key] = serialize(schema, value)
|
|
287
|
+
else:
|
|
288
|
+
subrender[key] = render(value, defaults=defaults)
|
|
289
|
+
|
|
290
|
+
if not defaults:
|
|
291
|
+
subrender = render_associated(subrender)
|
|
292
|
+
|
|
293
|
+
return wrap_default(schema, subrender) if defaults else subrender
|
|
294
|
+
|
|
295
|
+
@dispatch
|
|
296
|
+
def render(schema: str, defaults=False):
|
|
297
|
+
return schema
|
|
298
|
+
|
|
299
|
+
@dispatch
|
|
300
|
+
def render(schema, defaults=False):
|
|
301
|
+
return schema
|
|
302
|
+
|
|
303
|
+
def render_associated(assoc):
|
|
304
|
+
if all([isinstance(value, str) for value in assoc.values()]):
|
|
305
|
+
parts = [f'{key}:{value}' for key, value in assoc.items()]
|
|
306
|
+
assoc = '|'.join(parts)
|
|
307
|
+
return assoc
|
|
308
|
+
|
|
309
|
+
|
|
310
|
+
@dispatch
|
|
311
|
+
def serialize(schema: Empty, state):
|
|
312
|
+
return NONE_SYMBOL
|
|
313
|
+
|
|
314
|
+
@dispatch
|
|
315
|
+
def serialize(schema: Maybe, state):
|
|
316
|
+
if state is None:
|
|
317
|
+
return NONE_SYMBOL
|
|
318
|
+
else:
|
|
319
|
+
return serialize(
|
|
320
|
+
schema._value,
|
|
321
|
+
state)
|
|
322
|
+
|
|
323
|
+
@dispatch
|
|
324
|
+
def serialize(schema: Wrap, state):
|
|
325
|
+
return serialize(schema._value, state)
|
|
326
|
+
|
|
327
|
+
@dispatch
|
|
328
|
+
def serialize(schema: Union, state):
|
|
329
|
+
match = None
|
|
330
|
+
for option in schema._options:
|
|
331
|
+
if check(option, state):
|
|
332
|
+
match = serialize(option, state)
|
|
333
|
+
|
|
334
|
+
break
|
|
335
|
+
return match
|
|
336
|
+
|
|
337
|
+
@dispatch
|
|
338
|
+
def serialize(schema: Tuple, state):
|
|
339
|
+
return [
|
|
340
|
+
serialize(subschema, value)
|
|
341
|
+
for subschema, value in zip(schema._values, state)]
|
|
342
|
+
|
|
343
|
+
@dispatch
|
|
344
|
+
def serialize(schema: Boolean, state):
|
|
345
|
+
if state:
|
|
346
|
+
return 'true'
|
|
347
|
+
else:
|
|
348
|
+
return 'false'
|
|
349
|
+
|
|
350
|
+
@dispatch
|
|
351
|
+
def serialize(schema: NPRandom, state):
|
|
352
|
+
if isinstance(state, RandomState):
|
|
353
|
+
return serialize(
|
|
354
|
+
schema.state,
|
|
355
|
+
state.get_state())
|
|
356
|
+
elif isinstance(state, (list, tuple)):
|
|
357
|
+
return state
|
|
358
|
+
else:
|
|
359
|
+
import ipdb; ipdb.set_trace()
|
|
360
|
+
|
|
361
|
+
@dispatch
|
|
362
|
+
def serialize(schema: String, state):
|
|
363
|
+
return state
|
|
364
|
+
|
|
365
|
+
@dispatch
|
|
366
|
+
def serialize(schema: np.str_, state):
|
|
367
|
+
return str(state)
|
|
368
|
+
|
|
369
|
+
@dispatch
|
|
370
|
+
def serialize(schema: List, state):
|
|
371
|
+
return [
|
|
372
|
+
serialize(schema._element, element)
|
|
373
|
+
for element in state]
|
|
374
|
+
|
|
375
|
+
@dispatch
|
|
376
|
+
def serialize(schema: Map, state):
|
|
377
|
+
return {
|
|
378
|
+
key: serialize(schema._value, value)
|
|
379
|
+
for key, value in state.items()}
|
|
380
|
+
|
|
381
|
+
@dispatch
|
|
382
|
+
def serialize(schema: Tree, state):
|
|
383
|
+
if check(schema._leaf, state):
|
|
384
|
+
return serialize(schema._leaf, state)
|
|
385
|
+
else:
|
|
386
|
+
try:
|
|
387
|
+
return {
|
|
388
|
+
key: serialize(schema, branch)
|
|
389
|
+
for key, branch in state.items()}
|
|
390
|
+
except Exception as e:
|
|
391
|
+
import ipdb; ipdb.set_trace()
|
|
392
|
+
|
|
393
|
+
@dispatch
|
|
394
|
+
def serialize(schema: dict, state):
|
|
395
|
+
if not isinstance(state, dict):
|
|
396
|
+
return {}
|
|
397
|
+
|
|
398
|
+
result = {}
|
|
399
|
+
|
|
400
|
+
for key, subschema in schema.items():
|
|
401
|
+
if not key.startswith('_'):
|
|
402
|
+
result[key] = serialize(
|
|
403
|
+
subschema,
|
|
404
|
+
state.get(key))
|
|
405
|
+
|
|
406
|
+
return result
|
|
407
|
+
|
|
408
|
+
|
|
409
|
+
@dispatch
|
|
410
|
+
def serialize(schema: Number, state):
|
|
411
|
+
return state
|
|
412
|
+
|
|
413
|
+
|
|
414
|
+
@dispatch
|
|
415
|
+
def serialize(schema: Atom, state):
|
|
416
|
+
return str(state)
|
|
417
|
+
|
|
418
|
+
|
|
419
|
+
@dispatch
|
|
420
|
+
def serialize(schema: Array, state: np.ndarray):
|
|
421
|
+
return state.tolist()
|
|
422
|
+
|
|
423
|
+
@dispatch
|
|
424
|
+
def serialize(schema: Array, state: list):
|
|
425
|
+
return state
|
|
426
|
+
|
|
427
|
+
@dispatch
|
|
428
|
+
def serialize(schema: Array, state: dict):
|
|
429
|
+
return state
|
|
430
|
+
|
|
431
|
+
@dispatch
|
|
432
|
+
def serialize(schema: Array, state):
|
|
433
|
+
raise Exception(f'serializing array:\n {schema}\nbut state is not an array?\n {state}')
|
|
434
|
+
|
|
435
|
+
@dispatch
|
|
436
|
+
def serialize(schema: Schema, state):
|
|
437
|
+
return render(state)
|
|
438
|
+
|
|
439
|
+
@dispatch
|
|
440
|
+
def serialize(schema: Link, state):
|
|
441
|
+
address = serialize(schema.address, state.get('address'))
|
|
442
|
+
instance = state.get('instance')
|
|
443
|
+
unconfig = state.get('config')
|
|
444
|
+
|
|
445
|
+
if instance is None:
|
|
446
|
+
config_schema = {}
|
|
447
|
+
else:
|
|
448
|
+
config_schema = instance.core.access(instance.config_schema)
|
|
449
|
+
|
|
450
|
+
# config = serialize(config_schema, unconfig)
|
|
451
|
+
# inputs = serialize(schema.inputs, state.get('inputs'))
|
|
452
|
+
# outputs = serialize(schema.outputs, state.get('outputs'))
|
|
453
|
+
_inputs = resolve(schema._inputs, state.get('_inputs'))
|
|
454
|
+
_outputs = resolve(schema._outputs, state.get('_outputs'))
|
|
455
|
+
|
|
456
|
+
encode = {
|
|
457
|
+
'address': address,
|
|
458
|
+
'config': unconfig,
|
|
459
|
+
'_inputs': render(_inputs),
|
|
460
|
+
'_outputs': render(_outputs)}
|
|
461
|
+
|
|
462
|
+
if state.get('inputs'):
|
|
463
|
+
encode['inputs'] = state.get('inputs')
|
|
464
|
+
if state.get('outputs'):
|
|
465
|
+
encode['outputs'] = state.get('outputs')
|
|
466
|
+
|
|
467
|
+
return encode
|
|
468
|
+
|
|
469
|
+
|
|
470
|
+
@dispatch
|
|
471
|
+
def serialize(schema: None, state: None):
|
|
472
|
+
return None
|
|
473
|
+
|
|
474
|
+
@dispatch
|
|
475
|
+
def serialize(schema: Node, state):
|
|
476
|
+
if isinstance(state, dict):
|
|
477
|
+
result = {}
|
|
478
|
+
|
|
479
|
+
for key in schema.__dataclass_fields__:
|
|
480
|
+
if not key in ('_default',):
|
|
481
|
+
if key in state:
|
|
482
|
+
result[key] = serialize(
|
|
483
|
+
getattr(schema, key),
|
|
484
|
+
state[key])
|
|
485
|
+
|
|
486
|
+
return result
|
|
487
|
+
elif state is None:
|
|
488
|
+
return None
|
|
489
|
+
else:
|
|
490
|
+
return str(state)
|
|
491
|
+
|