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.
@@ -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
+