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.

Files changed (33) hide show
  1. {bigraph-schema-0.0.38/bigraph_schema.egg-info → bigraph-schema-0.0.42}/PKG-INFO +1 -1
  2. {bigraph-schema-0.0.38 → bigraph-schema-0.0.42}/bigraph_schema/__init__.py +1 -1
  3. {bigraph-schema-0.0.38 → bigraph-schema-0.0.42}/bigraph_schema/parse.py +9 -2
  4. {bigraph-schema-0.0.38 → bigraph-schema-0.0.42}/bigraph_schema/registry.py +104 -29
  5. {bigraph-schema-0.0.38 → bigraph-schema-0.0.42}/bigraph_schema/type_system.py +366 -78
  6. {bigraph-schema-0.0.38 → bigraph-schema-0.0.42/bigraph_schema.egg-info}/PKG-INFO +1 -1
  7. {bigraph-schema-0.0.38 → bigraph-schema-0.0.42}/bigraph_schema.egg-info/SOURCES.txt +1 -15
  8. {bigraph-schema-0.0.38 → bigraph-schema-0.0.42}/setup.py +1 -1
  9. bigraph-schema-0.0.38/.github/workflows/notebook_to_html.yml +0 -48
  10. bigraph-schema-0.0.38/.github/workflows/pytest.yml +0 -29
  11. bigraph-schema-0.0.38/.gitignore +0 -14
  12. bigraph-schema-0.0.38/CLA.md +0 -113
  13. bigraph-schema-0.0.38/CODE_OF_CONDUCT.md +0 -137
  14. bigraph-schema-0.0.38/CONTRIBUTING.md +0 -44
  15. bigraph-schema-0.0.38/notebooks/core.ipynb +0 -1683
  16. bigraph-schema-0.0.38/notebooks/demo.ipynb +0 -1487
  17. bigraph-schema-0.0.38/notebooks/images/place-link.png +0 -0
  18. bigraph-schema-0.0.38/notebooks/images/reaction-after.png +0 -0
  19. bigraph-schema-0.0.38/notebooks/images/reaction-before.png +0 -0
  20. bigraph-schema-0.0.38/notebooks/images/redex-reactum.png +0 -0
  21. bigraph-schema-0.0.38/pytest.ini +0 -4
  22. bigraph-schema-0.0.38/release.sh +0 -43
  23. {bigraph-schema-0.0.38 → bigraph-schema-0.0.42}/AUTHORS.md +0 -0
  24. {bigraph-schema-0.0.38 → bigraph-schema-0.0.42}/LICENSE +0 -0
  25. {bigraph-schema-0.0.38 → bigraph-schema-0.0.42}/README.md +0 -0
  26. {bigraph-schema-0.0.38 → bigraph-schema-0.0.42}/bigraph_schema/data.py +0 -0
  27. {bigraph-schema-0.0.38 → bigraph-schema-0.0.42}/bigraph_schema/protocols.py +0 -0
  28. {bigraph-schema-0.0.38 → bigraph-schema-0.0.42}/bigraph_schema/react.py +0 -0
  29. {bigraph-schema-0.0.38 → bigraph-schema-0.0.42}/bigraph_schema/units.py +0 -0
  30. {bigraph-schema-0.0.38 → bigraph-schema-0.0.42}/bigraph_schema.egg-info/dependency_links.txt +0 -0
  31. {bigraph-schema-0.0.38 → bigraph-schema-0.0.42}/bigraph_schema.egg-info/requires.txt +0 -0
  32. {bigraph-schema-0.0.38 → bigraph-schema-0.0.42}/bigraph_schema.egg-info/top_level.txt +0 -0
  33. {bigraph-schema-0.0.38 → bigraph-schema-0.0.42}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: bigraph-schema
3
- Version: 0.0.38
3
+ Version: 0.0.42
4
4
  Summary: A serializable type schema for compositional systems biology
5
5
  Home-page: https://github.com/vivarium-collective/bigraph-schema
6
6
  Author: Eran Agmon, Ryan Spangler
@@ -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 {visit[0]: visit[2]}
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.startswith('_')]
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.access(module_key)
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 "{subschema}" not found for type data:\n {pf(schema)}')
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.registry.get(key)
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(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 is_schema_key(update, key):
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.startswith('_'):
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
- return new_state
905
+ merge_state = new_state
853
906
 
854
907
  elif is_empty(new_state):
855
- return current_state
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.startswith('_'):
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
- return current_state
920
+ merge_state = current_state
868
921
  else:
869
- return new_state
922
+ merge_state = new_state
870
923
  else:
871
- return new_state
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.access(schema)
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
- lookup = self.access(subschema)
1230
- if lookup is None:
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
- schema[subkey] = lookup
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 access(self, schema):
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.access(schema)
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