bigraph-schema 0.0.38__tar.gz → 0.0.42__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.
Potentially problematic release.
This version of bigraph-schema might be problematic. Click here for more details.
- {bigraph-schema-0.0.38/bigraph_schema.egg-info → bigraph-schema-0.0.42}/PKG-INFO +1 -1
- {bigraph-schema-0.0.38 → bigraph-schema-0.0.42}/bigraph_schema/__init__.py +1 -1
- {bigraph-schema-0.0.38 → bigraph-schema-0.0.42}/bigraph_schema/parse.py +9 -2
- {bigraph-schema-0.0.38 → bigraph-schema-0.0.42}/bigraph_schema/registry.py +104 -29
- {bigraph-schema-0.0.38 → bigraph-schema-0.0.42}/bigraph_schema/type_system.py +366 -78
- {bigraph-schema-0.0.38 → bigraph-schema-0.0.42/bigraph_schema.egg-info}/PKG-INFO +1 -1
- {bigraph-schema-0.0.38 → bigraph-schema-0.0.42}/bigraph_schema.egg-info/SOURCES.txt +1 -15
- {bigraph-schema-0.0.38 → bigraph-schema-0.0.42}/setup.py +1 -1
- bigraph-schema-0.0.38/.github/workflows/notebook_to_html.yml +0 -48
- bigraph-schema-0.0.38/.github/workflows/pytest.yml +0 -29
- bigraph-schema-0.0.38/.gitignore +0 -14
- bigraph-schema-0.0.38/CLA.md +0 -113
- bigraph-schema-0.0.38/CODE_OF_CONDUCT.md +0 -137
- bigraph-schema-0.0.38/CONTRIBUTING.md +0 -44
- bigraph-schema-0.0.38/notebooks/core.ipynb +0 -1683
- bigraph-schema-0.0.38/notebooks/demo.ipynb +0 -1487
- bigraph-schema-0.0.38/notebooks/images/place-link.png +0 -0
- bigraph-schema-0.0.38/notebooks/images/reaction-after.png +0 -0
- bigraph-schema-0.0.38/notebooks/images/reaction-before.png +0 -0
- bigraph-schema-0.0.38/notebooks/images/redex-reactum.png +0 -0
- bigraph-schema-0.0.38/pytest.ini +0 -4
- bigraph-schema-0.0.38/release.sh +0 -43
- {bigraph-schema-0.0.38 → bigraph-schema-0.0.42}/AUTHORS.md +0 -0
- {bigraph-schema-0.0.38 → bigraph-schema-0.0.42}/LICENSE +0 -0
- {bigraph-schema-0.0.38 → bigraph-schema-0.0.42}/README.md +0 -0
- {bigraph-schema-0.0.38 → bigraph-schema-0.0.42}/bigraph_schema/data.py +0 -0
- {bigraph-schema-0.0.38 → bigraph-schema-0.0.42}/bigraph_schema/protocols.py +0 -0
- {bigraph-schema-0.0.38 → bigraph-schema-0.0.42}/bigraph_schema/react.py +0 -0
- {bigraph-schema-0.0.38 → bigraph-schema-0.0.42}/bigraph_schema/units.py +0 -0
- {bigraph-schema-0.0.38 → bigraph-schema-0.0.42}/bigraph_schema.egg-info/dependency_links.txt +0 -0
- {bigraph-schema-0.0.38 → bigraph-schema-0.0.42}/bigraph_schema.egg-info/requires.txt +0 -0
- {bigraph-schema-0.0.38 → bigraph-schema-0.0.42}/bigraph_schema.egg-info/top_level.txt +0 -0
- {bigraph-schema-0.0.38 → bigraph-schema-0.0.42}/setup.cfg +0 -0
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
from bigraph_schema.type_system import TypeSystem, Edge
|
|
2
|
-
from bigraph_schema.registry import get_path, establish_path, set_path, transform_path, deep_merge, validate_merge
|
|
2
|
+
from bigraph_schema.registry import get_path, establish_path, set_path, transform_path, deep_merge, validate_merge, default
|
|
@@ -20,6 +20,8 @@ parameter_examples = {
|
|
|
20
20
|
'typed_parameters': 'edge[a:int|b:(x:length|y:float),v[zz:float|xx:what]]',
|
|
21
21
|
'inputs_and_outputs': 'edge[input1:float|input2:int,output1:float|output2:int]',
|
|
22
22
|
'tuple': 'what[is,happening|(with:yellow|this:green)|this:now]',
|
|
23
|
+
'single': 'hello[(3),over]',
|
|
24
|
+
'double': 'hello[(3|4),over]',
|
|
23
25
|
'units_type': 'length^2*mass/time^1_5'}
|
|
24
26
|
|
|
25
27
|
|
|
@@ -98,10 +100,15 @@ class ParameterVisitor(NodeVisitor):
|
|
|
98
100
|
return visit[0]
|
|
99
101
|
|
|
100
102
|
def visit_group(self, node, visit):
|
|
101
|
-
return visit[1]
|
|
103
|
+
# return visit[1]
|
|
104
|
+
if isinstance(visit[1], (list, tuple, dict)):
|
|
105
|
+
return visit[1]
|
|
106
|
+
else:
|
|
107
|
+
return tuple([visit[1]])
|
|
102
108
|
|
|
103
109
|
def visit_nest(self, node, visit):
|
|
104
|
-
return {
|
|
110
|
+
return {
|
|
111
|
+
visit[0]: visit[2]}
|
|
105
112
|
|
|
106
113
|
def visit_type_name(self, node, visit):
|
|
107
114
|
type_name = visit[0]
|
|
@@ -9,7 +9,7 @@ import copy
|
|
|
9
9
|
import collections
|
|
10
10
|
import pytest
|
|
11
11
|
import traceback
|
|
12
|
-
|
|
12
|
+
import functools
|
|
13
13
|
import numpy as np
|
|
14
14
|
|
|
15
15
|
from pprint import pformat as pf
|
|
@@ -44,6 +44,8 @@ optional_schema_keys = set([
|
|
|
44
44
|
|
|
45
45
|
type_schema_keys = required_schema_keys | optional_schema_keys
|
|
46
46
|
|
|
47
|
+
SYMBOL_TYPES = ['enum']
|
|
48
|
+
|
|
47
49
|
TYPE_FUNCTION_KEYS = [
|
|
48
50
|
'_apply',
|
|
49
51
|
'_check',
|
|
@@ -90,7 +92,7 @@ def non_schema_keys(schema):
|
|
|
90
92
|
return [
|
|
91
93
|
element
|
|
92
94
|
for element in schema.keys()
|
|
93
|
-
if not element
|
|
95
|
+
if not is_schema_key(element)]
|
|
94
96
|
|
|
95
97
|
|
|
96
98
|
def type_merge(dct, merge_dct, path=tuple(), merge_supers=False):
|
|
@@ -295,6 +297,26 @@ def transform_path(tree, path, transform):
|
|
|
295
297
|
return set_path(tree, path, after)
|
|
296
298
|
|
|
297
299
|
|
|
300
|
+
def hierarchy_depth(hierarchy, path=()):
|
|
301
|
+
"""
|
|
302
|
+
Create a mapping of every path in the hierarchy to the node living at
|
|
303
|
+
that path in the hierarchy.
|
|
304
|
+
"""
|
|
305
|
+
|
|
306
|
+
base = {}
|
|
307
|
+
|
|
308
|
+
for key, inner in hierarchy.items():
|
|
309
|
+
down = tuple(path + (key,))
|
|
310
|
+
if is_schema_key(key):
|
|
311
|
+
base[path] = inner
|
|
312
|
+
elif isinstance(inner, dict) and 'instance' not in inner:
|
|
313
|
+
base.update(hierarchy_depth(inner, down))
|
|
314
|
+
else:
|
|
315
|
+
base[down] = inner
|
|
316
|
+
|
|
317
|
+
return base
|
|
318
|
+
|
|
319
|
+
|
|
298
320
|
def remove_omitted(before, after, tree):
|
|
299
321
|
"""
|
|
300
322
|
Removes anything in tree that was in before but not in after
|
|
@@ -336,6 +358,12 @@ def remove_path(tree, path):
|
|
|
336
358
|
return tree
|
|
337
359
|
|
|
338
360
|
|
|
361
|
+
def default(type, default):
|
|
362
|
+
return {
|
|
363
|
+
'_type': type,
|
|
364
|
+
'_default': default}
|
|
365
|
+
|
|
366
|
+
|
|
339
367
|
class Registry(object):
|
|
340
368
|
"""A Registry holds a collection of functions or objects"""
|
|
341
369
|
|
|
@@ -359,6 +387,7 @@ class Registry(object):
|
|
|
359
387
|
"""
|
|
360
388
|
|
|
361
389
|
# check that registered function have the required function keys
|
|
390
|
+
# TODO -- make this work to check the function keys
|
|
362
391
|
if callable(item) and self.function_keys:
|
|
363
392
|
sig = inspect.signature(item)
|
|
364
393
|
sig_keys = set(sig.parameters.keys())
|
|
@@ -375,11 +404,13 @@ class Registry(object):
|
|
|
375
404
|
raise Exception(
|
|
376
405
|
'registry already contains an entry for {}: {} --> {}'.format(
|
|
377
406
|
registry_key, self.registry[key], item))
|
|
378
|
-
|
|
379
|
-
else:
|
|
407
|
+
elif isinstance(item, dict):
|
|
380
408
|
self.registry[registry_key] = deep_merge(
|
|
381
409
|
self.registry[registry_key],
|
|
382
410
|
item)
|
|
411
|
+
else:
|
|
412
|
+
self.registry[registry_key] = item
|
|
413
|
+
|
|
383
414
|
else:
|
|
384
415
|
self.registry[registry_key] = item
|
|
385
416
|
self.main_keys.add(key)
|
|
@@ -388,7 +419,7 @@ class Registry(object):
|
|
|
388
419
|
def register_function(self, function):
|
|
389
420
|
if isinstance(function, str):
|
|
390
421
|
module_key = function
|
|
391
|
-
found = self.
|
|
422
|
+
found = self.find(module_key)
|
|
392
423
|
|
|
393
424
|
if found is None:
|
|
394
425
|
found = local_lookup_module(
|
|
@@ -396,7 +427,7 @@ class Registry(object):
|
|
|
396
427
|
|
|
397
428
|
if found is None:
|
|
398
429
|
raise Exception(
|
|
399
|
-
f'function "{
|
|
430
|
+
f'function "{module_key}" not found for type data')
|
|
400
431
|
|
|
401
432
|
elif inspect.isfunction(function):
|
|
402
433
|
found = function
|
|
@@ -413,12 +444,16 @@ class Registry(object):
|
|
|
413
444
|
for key, schema in schemas.items():
|
|
414
445
|
self.register(key, schema, force=force)
|
|
415
446
|
|
|
447
|
+
def find(self, key):
|
|
448
|
+
return self.registry.get(key)
|
|
449
|
+
|
|
450
|
+
|
|
416
451
|
def access(self, key):
|
|
417
452
|
"""
|
|
418
453
|
get an item by key from the registry.
|
|
419
454
|
"""
|
|
420
455
|
|
|
421
|
-
return self.
|
|
456
|
+
return self.find(key)
|
|
422
457
|
|
|
423
458
|
def list(self):
|
|
424
459
|
return list(self.main_keys)
|
|
@@ -582,7 +617,23 @@ def divide_any(schema, state, values, core):
|
|
|
582
617
|
for _ in range(divisions)]
|
|
583
618
|
|
|
584
619
|
|
|
585
|
-
def is_schema_key(
|
|
620
|
+
def is_schema_key(key):
|
|
621
|
+
return isinstance(key, str) and key.startswith('_')
|
|
622
|
+
|
|
623
|
+
def strip_schema_keys(state):
|
|
624
|
+
"""remove schema keys from a state dictionary, including nested dictionaries"""
|
|
625
|
+
if isinstance(state, dict):
|
|
626
|
+
output = {}
|
|
627
|
+
for key, value in state.items():
|
|
628
|
+
if not is_schema_key(key):
|
|
629
|
+
output[key] = strip_schema_keys(value)
|
|
630
|
+
else:
|
|
631
|
+
output = state
|
|
632
|
+
return output
|
|
633
|
+
|
|
634
|
+
|
|
635
|
+
|
|
636
|
+
def type_parameter_key(schema, key):
|
|
586
637
|
return key.strip('_') not in schema.get('_type_parameters', []) and key.startswith('_')
|
|
587
638
|
|
|
588
639
|
|
|
@@ -599,7 +650,7 @@ def resolve_any(schema, update, core):
|
|
|
599
650
|
else:
|
|
600
651
|
raise Exception(f'cannot resolve types when updating\ncurrent type: {schema}\nupdate type: {update}')
|
|
601
652
|
|
|
602
|
-
elif not key in outcome or
|
|
653
|
+
elif not key in outcome or type_parameter_key(update, key):
|
|
603
654
|
if subschema:
|
|
604
655
|
outcome[key] = subschema
|
|
605
656
|
else:
|
|
@@ -812,7 +863,7 @@ def deserialize_any(schema, state, core):
|
|
|
812
863
|
tree = {}
|
|
813
864
|
|
|
814
865
|
for key, value in state.items():
|
|
815
|
-
if key
|
|
866
|
+
if is_schema_key(key):
|
|
816
867
|
decoded = value
|
|
817
868
|
else:
|
|
818
869
|
decoded = core.deserialize(
|
|
@@ -848,27 +899,35 @@ def merge_any(schema, current_state, new_state, core):
|
|
|
848
899
|
# overwrites in place!
|
|
849
900
|
# TODO: this operation could update the schema (by merging a key not
|
|
850
901
|
# already in the schema) but that is not represented currently....
|
|
902
|
+
merge_state = None
|
|
903
|
+
|
|
851
904
|
if is_empty(current_state):
|
|
852
|
-
|
|
905
|
+
merge_state = new_state
|
|
853
906
|
|
|
854
907
|
elif is_empty(new_state):
|
|
855
|
-
|
|
908
|
+
merge_state = current_state
|
|
856
909
|
|
|
857
910
|
elif isinstance(new_state, dict):
|
|
858
911
|
if isinstance(current_state, dict):
|
|
859
912
|
for key, value in new_state.items():
|
|
860
|
-
if key
|
|
913
|
+
if is_schema_key(key):
|
|
861
914
|
current_state[key] = value
|
|
862
915
|
else:
|
|
863
916
|
current_state[key] = core.merge(
|
|
864
917
|
schema.get(key),
|
|
865
918
|
current_state.get(key),
|
|
866
919
|
value)
|
|
867
|
-
|
|
920
|
+
merge_state = current_state
|
|
868
921
|
else:
|
|
869
|
-
|
|
922
|
+
merge_state = new_state
|
|
870
923
|
else:
|
|
871
|
-
|
|
924
|
+
merge_state = new_state
|
|
925
|
+
|
|
926
|
+
return merge_state
|
|
927
|
+
|
|
928
|
+
# return core.deserialize(
|
|
929
|
+
# schema,
|
|
930
|
+
# merge_state)
|
|
872
931
|
|
|
873
932
|
|
|
874
933
|
def bind_any(schema, state, key, subschema, substate, core):
|
|
@@ -1193,7 +1252,7 @@ class TypeRegistry(Registry):
|
|
|
1193
1252
|
"""
|
|
1194
1253
|
|
|
1195
1254
|
if isinstance(schema, str):
|
|
1196
|
-
schema = self.
|
|
1255
|
+
schema = self.find(schema)
|
|
1197
1256
|
schema = copy.deepcopy(schema)
|
|
1198
1257
|
|
|
1199
1258
|
if '_type' not in schema:
|
|
@@ -1219,20 +1278,22 @@ class TypeRegistry(Registry):
|
|
|
1219
1278
|
for subkey, subschema in schema.items():
|
|
1220
1279
|
parameters = schema.get('_type_parameters', [])
|
|
1221
1280
|
if subkey in TYPE_FUNCTION_KEYS or is_method_key(subkey, parameters):
|
|
1222
|
-
registry = self.find_registry(
|
|
1223
|
-
subkey)
|
|
1281
|
+
registry = self.find_registry(subkey)
|
|
1224
1282
|
function_name, module_key = registry.register_function(subschema)
|
|
1225
1283
|
|
|
1226
1284
|
schema[subkey] = function_name
|
|
1227
1285
|
|
|
1228
1286
|
elif subkey not in type_schema_keys:
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
raise Exception(
|
|
1232
|
-
f'trying to register a new type ({key}), '
|
|
1233
|
-
f'but it depends on a type ({subkey}) which is not in the registry')
|
|
1287
|
+
if schema['_type'] in SYMBOL_TYPES:
|
|
1288
|
+
schema[subkey] = subschema
|
|
1234
1289
|
else:
|
|
1235
|
-
|
|
1290
|
+
lookup = self.find(subschema)
|
|
1291
|
+
if lookup is None:
|
|
1292
|
+
raise Exception(
|
|
1293
|
+
f'trying to register a new type ({key}), '
|
|
1294
|
+
f'but it depends on a type ({subkey}) which is not in the registry')
|
|
1295
|
+
else:
|
|
1296
|
+
schema[subkey] = lookup
|
|
1236
1297
|
else:
|
|
1237
1298
|
raise Exception(
|
|
1238
1299
|
f'all type definitions must be dicts '
|
|
@@ -1252,7 +1313,7 @@ class TypeRegistry(Registry):
|
|
|
1252
1313
|
for type_parameter in type_parameters}
|
|
1253
1314
|
|
|
1254
1315
|
|
|
1255
|
-
def
|
|
1316
|
+
def find(self, schema):
|
|
1256
1317
|
"""
|
|
1257
1318
|
expand the schema to its full type information from the type registry
|
|
1258
1319
|
"""
|
|
@@ -1290,7 +1351,10 @@ class TypeRegistry(Registry):
|
|
|
1290
1351
|
key: self.access(branch)
|
|
1291
1352
|
for key, branch in schema.items()}
|
|
1292
1353
|
|
|
1293
|
-
elif isinstance(schema, tuple):
|
|
1354
|
+
elif isinstance(schema, (tuple, int)):
|
|
1355
|
+
if isinstance(schema, int):
|
|
1356
|
+
schema = tuple([schema])
|
|
1357
|
+
|
|
1294
1358
|
tuple_schema = {
|
|
1295
1359
|
'_type': 'tuple',
|
|
1296
1360
|
'_type_parameters': []}
|
|
@@ -1336,17 +1400,28 @@ class TypeRegistry(Registry):
|
|
|
1336
1400
|
traceback.print_exc()
|
|
1337
1401
|
|
|
1338
1402
|
return found
|
|
1339
|
-
|
|
1403
|
+
|
|
1404
|
+
def access(self, schema):
|
|
1405
|
+
if isinstance(schema, str):
|
|
1406
|
+
return self.access_str(schema)
|
|
1407
|
+
else:
|
|
1408
|
+
return self.find(schema)
|
|
1409
|
+
|
|
1410
|
+
@functools.lru_cache(maxsize=None)
|
|
1411
|
+
def access_str(self, schema):
|
|
1412
|
+
return self.find(schema)
|
|
1413
|
+
|
|
1340
1414
|
def retrieve(self, schema):
|
|
1341
1415
|
"""
|
|
1342
1416
|
like access(schema) but raises an exception if nothing is found
|
|
1343
1417
|
"""
|
|
1344
1418
|
|
|
1345
|
-
found = self.
|
|
1419
|
+
found = self.find(schema)
|
|
1346
1420
|
if found is None:
|
|
1347
1421
|
raise Exception(f'schema not found for type: {schema}')
|
|
1348
1422
|
return found
|
|
1349
1423
|
|
|
1424
|
+
|
|
1350
1425
|
def lookup(self, type_key, attribute):
|
|
1351
1426
|
return self.access(type_key).get(attribute)
|
|
1352
1427
|
|