bigraph-schema 0.0.60__tar.gz → 0.0.62__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.60 → bigraph-schema-0.0.62}/.gitignore +4 -1
- {bigraph-schema-0.0.60/bigraph_schema.egg-info → bigraph-schema-0.0.62}/PKG-INFO +1 -1
- {bigraph-schema-0.0.60 → bigraph-schema-0.0.62}/bigraph_schema/__init__.py +2 -2
- {bigraph-schema-0.0.60 → bigraph-schema-0.0.62}/bigraph_schema/registry.py +43 -28
- {bigraph-schema-0.0.60 → bigraph-schema-0.0.62}/bigraph_schema/tests.py +160 -117
- {bigraph-schema-0.0.60 → bigraph-schema-0.0.62}/bigraph_schema/type_functions.py +625 -247
- {bigraph-schema-0.0.60 → bigraph-schema-0.0.62}/bigraph_schema/type_system.py +399 -757
- bigraph-schema-0.0.62/bigraph_schema/type_system_adjunct.py +502 -0
- {bigraph-schema-0.0.60 → bigraph-schema-0.0.62}/bigraph_schema/utilities.py +21 -0
- {bigraph-schema-0.0.60 → bigraph-schema-0.0.62/bigraph_schema.egg-info}/PKG-INFO +1 -1
- {bigraph-schema-0.0.60 → bigraph-schema-0.0.62}/bigraph_schema.egg-info/SOURCES.txt +2 -0
- {bigraph-schema-0.0.60 → bigraph-schema-0.0.62}/bigraph_schema.egg-info/requires.txt +4 -2
- bigraph-schema-0.0.62/pyproject.toml +19 -0
- {bigraph-schema-0.0.60 → bigraph-schema-0.0.62}/setup.py +1 -1
- {bigraph-schema-0.0.60 → bigraph-schema-0.0.62}/.github/workflows/notebook_to_html.yml +0 -0
- {bigraph-schema-0.0.60 → bigraph-schema-0.0.62}/.github/workflows/pytest.yml +0 -0
- {bigraph-schema-0.0.60 → bigraph-schema-0.0.62}/AUTHORS.md +0 -0
- {bigraph-schema-0.0.60 → bigraph-schema-0.0.62}/CLA.md +0 -0
- {bigraph-schema-0.0.60 → bigraph-schema-0.0.62}/CODE_OF_CONDUCT.md +0 -0
- {bigraph-schema-0.0.60 → bigraph-schema-0.0.62}/CONTRIBUTING.md +0 -0
- {bigraph-schema-0.0.60 → bigraph-schema-0.0.62}/LICENSE +0 -0
- {bigraph-schema-0.0.60 → bigraph-schema-0.0.62}/README.md +0 -0
- {bigraph-schema-0.0.60 → bigraph-schema-0.0.62}/bigraph_schema/edge.py +0 -0
- {bigraph-schema-0.0.60 → bigraph-schema-0.0.62}/bigraph_schema/parse.py +0 -0
- {bigraph-schema-0.0.60 → bigraph-schema-0.0.62}/bigraph_schema/protocols.py +0 -0
- {bigraph-schema-0.0.60 → bigraph-schema-0.0.62}/bigraph_schema/units.py +0 -0
- {bigraph-schema-0.0.60 → bigraph-schema-0.0.62}/bigraph_schema.egg-info/dependency_links.txt +0 -0
- {bigraph-schema-0.0.60 → bigraph-schema-0.0.62}/bigraph_schema.egg-info/top_level.txt +0 -0
- {bigraph-schema-0.0.60 → bigraph-schema-0.0.62}/notebooks/core.ipynb +0 -0
- {bigraph-schema-0.0.60 → bigraph-schema-0.0.62}/notebooks/demo.ipynb +0 -0
- {bigraph-schema-0.0.60 → bigraph-schema-0.0.62}/notebooks/images/place-link.png +0 -0
- {bigraph-schema-0.0.60 → bigraph-schema-0.0.62}/notebooks/images/reaction-after.png +0 -0
- {bigraph-schema-0.0.60 → bigraph-schema-0.0.62}/notebooks/images/reaction-before.png +0 -0
- {bigraph-schema-0.0.60 → bigraph-schema-0.0.62}/notebooks/images/redex-reactum.png +0 -0
- {bigraph-schema-0.0.60 → bigraph-schema-0.0.62}/pytest.ini +0 -0
- {bigraph-schema-0.0.60 → bigraph-schema-0.0.62}/release.sh +0 -0
- {bigraph-schema-0.0.60 → bigraph-schema-0.0.62}/setup.cfg +0 -0
|
@@ -3,6 +3,6 @@ from bigraph_schema.registry import (
|
|
|
3
3
|
strip_schema_keys, type_parameter_key, non_schema_keys, set_path, transform_path)
|
|
4
4
|
from bigraph_schema.utilities import get_path, visit_method
|
|
5
5
|
from bigraph_schema.edge import Edge
|
|
6
|
-
from bigraph_schema.type_system import TypeSystem
|
|
6
|
+
from bigraph_schema.type_system import TypeSystem
|
|
7
7
|
from bigraph_schema.protocols import local_lookup_module
|
|
8
|
-
from bigraph_schema.type_functions import FUNCTION_TYPE, METHOD_TYPE
|
|
8
|
+
from bigraph_schema.type_functions import FUNCTION_TYPE, METHOD_TYPE, type_schema_keys, resolve_path
|
|
@@ -23,10 +23,13 @@ def deep_merge_copy(dct, merge_dct):
|
|
|
23
23
|
|
|
24
24
|
|
|
25
25
|
def deep_merge(dct, merge_dct):
|
|
26
|
-
"""
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
26
|
+
"""
|
|
27
|
+
Recursive dict merge
|
|
28
|
+
|
|
29
|
+
This mutates dct - the contents of merge_dct are added to dct (which is
|
|
30
|
+
also returned).
|
|
31
|
+
|
|
32
|
+
If you want to keep dct you could use deep_merge_copy
|
|
30
33
|
"""
|
|
31
34
|
if dct is None:
|
|
32
35
|
dct = {}
|
|
@@ -45,10 +48,14 @@ def deep_merge(dct, merge_dct):
|
|
|
45
48
|
|
|
46
49
|
|
|
47
50
|
def validate_merge(state, dct, merge_dct):
|
|
48
|
-
"""
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
51
|
+
"""
|
|
52
|
+
Recursive dict merge
|
|
53
|
+
|
|
54
|
+
This mutates dct - the contents of merge_dct are added to dct (which is
|
|
55
|
+
also returned).
|
|
56
|
+
|
|
57
|
+
If you want to keep dct you could call it like
|
|
58
|
+
deep_merge(copy.deepcopy(dct), merge_dct)
|
|
52
59
|
"""
|
|
53
60
|
dct = dct or {}
|
|
54
61
|
merge_dct = merge_dct or {}
|
|
@@ -77,16 +84,16 @@ def validate_merge(state, dct, merge_dct):
|
|
|
77
84
|
|
|
78
85
|
def establish_path(tree, path, top=None, cursor=()):
|
|
79
86
|
"""
|
|
80
|
-
Given a tree and a path in the tree that may or may not yet exist,
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
87
|
+
Given a tree and a path in the tree that may or may not yet exist, add
|
|
88
|
+
nodes along the path and return the final node which is now at the given
|
|
89
|
+
path.
|
|
90
|
+
|
|
84
91
|
Args:
|
|
85
92
|
- tree: the tree we are establishing a path in
|
|
86
93
|
- path: where the new subtree will be located in the tree
|
|
87
94
|
- top: (None) a reference to the top of the tree
|
|
88
95
|
- cursor: (()) the current location we are visiting in the tree
|
|
89
|
-
|
|
96
|
+
|
|
90
97
|
Returns:
|
|
91
98
|
- node: the new node of the tree that exists at the given path
|
|
92
99
|
"""
|
|
@@ -127,14 +134,14 @@ def set_path(tree, path, value, top=None, cursor=None):
|
|
|
127
134
|
"""
|
|
128
135
|
Given a tree, a path, and a value, sets the location
|
|
129
136
|
in the tree corresponding to the path to the given value
|
|
130
|
-
|
|
137
|
+
|
|
131
138
|
Args:
|
|
132
139
|
- tree: the tree we are setting a value in
|
|
133
140
|
- path: where the new value will be located in the tree
|
|
134
141
|
- value: the value to set at the given path in the tree
|
|
135
142
|
- top: (None) a reference to the top of the tree
|
|
136
143
|
- cursor: (()) the current location we are visiting in the tree
|
|
137
|
-
|
|
144
|
+
|
|
138
145
|
Returns:
|
|
139
146
|
- node: the new node of the tree that exists at the given path
|
|
140
147
|
"""
|
|
@@ -199,14 +206,16 @@ def set_star_path(tree, path, value, top=None, cursor=()):
|
|
|
199
206
|
|
|
200
207
|
def transform_path(tree, path, transform):
|
|
201
208
|
"""
|
|
202
|
-
Given a tree, a path, and a transform (function), mutate the tree by
|
|
203
|
-
|
|
204
|
-
|
|
209
|
+
Given a tree, a path, and a transform (function), mutate the tree by
|
|
210
|
+
replacing the subtree at the path by whatever is returned from applying the
|
|
211
|
+
transform to the existing value.
|
|
212
|
+
|
|
205
213
|
Args:
|
|
206
214
|
- tree: the tree we are setting a value in
|
|
207
215
|
- path: where the new value will be located in the tree
|
|
208
|
-
- transform: the function to apply to whatever currently lives at the given
|
|
209
|
-
|
|
216
|
+
- transform: the function to apply to whatever currently lives at the given
|
|
217
|
+
path in the tree
|
|
218
|
+
|
|
210
219
|
Returns:
|
|
211
220
|
- node: the node of the tree that exists at the given path
|
|
212
221
|
"""
|
|
@@ -278,7 +287,9 @@ def non_schema_keys(schema):
|
|
|
278
287
|
|
|
279
288
|
|
|
280
289
|
def strip_schema_keys(state):
|
|
281
|
-
"""
|
|
290
|
+
"""
|
|
291
|
+
remove schema keys from a state dictionary, including nested dictionaries
|
|
292
|
+
"""
|
|
282
293
|
if isinstance(state, dict):
|
|
283
294
|
output = {}
|
|
284
295
|
for key, value in state.items():
|
|
@@ -300,7 +311,9 @@ def default(type, default):
|
|
|
300
311
|
|
|
301
312
|
|
|
302
313
|
class Registry(object):
|
|
303
|
-
"""
|
|
314
|
+
"""
|
|
315
|
+
A Registry holds a collection of functions or objects
|
|
316
|
+
"""
|
|
304
317
|
|
|
305
318
|
def __init__(self, function_keys=None):
|
|
306
319
|
function_keys = function_keys or []
|
|
@@ -315,10 +328,12 @@ class Registry(object):
|
|
|
315
328
|
Args:
|
|
316
329
|
- key: Item key.
|
|
317
330
|
- item: The item to add.
|
|
318
|
-
- alternate_keys: Additional keys under which to register the item.
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
331
|
+
- alternate_keys: Additional keys under which to register the item.
|
|
332
|
+
These keys will not be included in the list returned by
|
|
333
|
+
``Registry.list()``. This may be useful if you want to be able to
|
|
334
|
+
look up an item in the registry under multiple keys.
|
|
335
|
+
- strict (bool): Disallow re-registration, overriding existing keys.
|
|
336
|
+
False by default.
|
|
322
337
|
"""
|
|
323
338
|
|
|
324
339
|
# check that registered function have the required function keys
|
|
@@ -367,7 +382,7 @@ class Registry(object):
|
|
|
367
382
|
elif inspect.isfunction(function):
|
|
368
383
|
found = function
|
|
369
384
|
module_key = function_module(found)
|
|
370
|
-
|
|
385
|
+
|
|
371
386
|
function_name = module_key.split('.')[-1]
|
|
372
387
|
self.register(function_name, found)
|
|
373
388
|
self.register(module_key, found)
|
|
@@ -381,7 +396,7 @@ class Registry(object):
|
|
|
381
396
|
|
|
382
397
|
def find(self, key):
|
|
383
398
|
return self.registry.get(key)
|
|
384
|
-
|
|
399
|
+
|
|
385
400
|
|
|
386
401
|
def access(self, key):
|
|
387
402
|
"""
|
|
@@ -7,10 +7,11 @@ import pprint
|
|
|
7
7
|
import numpy as np
|
|
8
8
|
from dataclasses import asdict
|
|
9
9
|
|
|
10
|
-
from bigraph_schema import
|
|
10
|
+
from bigraph_schema import local_lookup_module, TypeSystem
|
|
11
11
|
from bigraph_schema.type_functions import (
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
accumulate, base_types, data_module, deserialize_integer,
|
|
13
|
+
divide_longest, to_string)
|
|
14
|
+
from bigraph_schema.utilities import compare_dicts, NONE_SYMBOL, state_instance
|
|
14
15
|
from bigraph_schema.units import units
|
|
15
16
|
from bigraph_schema.registry import establish_path, remove_omitted
|
|
16
17
|
|
|
@@ -21,7 +22,30 @@ def core():
|
|
|
21
22
|
return register_test_types(core)
|
|
22
23
|
|
|
23
24
|
|
|
25
|
+
def register_test_types(core):
|
|
26
|
+
"""
|
|
27
|
+
defines the test schemas
|
|
28
|
+
"""
|
|
29
|
+
register_cube(core)
|
|
30
|
+
|
|
31
|
+
core.register('compartment', {
|
|
32
|
+
'counts': 'tree[float]',
|
|
33
|
+
'inner': 'tree[compartment]'})
|
|
34
|
+
|
|
35
|
+
core.register('metaedge', {
|
|
36
|
+
'_inherit': 'edge',
|
|
37
|
+
'_inputs': {
|
|
38
|
+
'before': 'metaedge'},
|
|
39
|
+
'_outputs': {
|
|
40
|
+
'after': 'metaedge'}})
|
|
41
|
+
|
|
42
|
+
return core
|
|
43
|
+
|
|
44
|
+
|
|
24
45
|
def register_cube(core):
|
|
46
|
+
"""
|
|
47
|
+
adds an additional simple schema for the test fixture
|
|
48
|
+
"""
|
|
25
49
|
cube_schema = {
|
|
26
50
|
'shape': {
|
|
27
51
|
'_type': 'shape',
|
|
@@ -50,24 +74,24 @@ def register_cube(core):
|
|
|
50
74
|
return core
|
|
51
75
|
|
|
52
76
|
|
|
53
|
-
def
|
|
54
|
-
|
|
77
|
+
def test_basic_types(core):
|
|
78
|
+
assert core.find('integer')
|
|
79
|
+
assert core.find('cube')['depth']['_type'] == 'integer'
|
|
55
80
|
|
|
56
|
-
core.register('compartment', {
|
|
57
|
-
'counts': 'tree[float]',
|
|
58
|
-
'inner': 'tree[compartment]'})
|
|
59
|
-
|
|
60
|
-
core.register('metaedge', {
|
|
61
|
-
'_inherit': 'edge',
|
|
62
|
-
'_inputs': {
|
|
63
|
-
'before': 'metaedge'},
|
|
64
|
-
'_outputs': {
|
|
65
|
-
'after': 'metaedge'}})
|
|
66
81
|
|
|
67
|
-
|
|
82
|
+
def test_update_types(core):
|
|
83
|
+
core.update_types({'A': "payload"})
|
|
84
|
+
desc = "a placeholder type with no structure"
|
|
85
|
+
core.update_types({'A': {'_description':desc}})
|
|
86
|
+
assert core.access('A') == {'_type': 'payload', '_description': desc}
|
|
68
87
|
|
|
69
88
|
|
|
70
89
|
def test_reregister_type(core):
|
|
90
|
+
"""
|
|
91
|
+
register raises an exception if replacing a schema with strict
|
|
92
|
+
|
|
93
|
+
it replaces the schema if not strict
|
|
94
|
+
"""
|
|
71
95
|
core.register('A', {'_default': 'a'})
|
|
72
96
|
with pytest.raises(Exception) as e:
|
|
73
97
|
core.register(
|
|
@@ -79,6 +103,18 @@ def test_reregister_type(core):
|
|
|
79
103
|
assert core.access('A')['_default'] == 'b'
|
|
80
104
|
|
|
81
105
|
|
|
106
|
+
def test_merge_schemas(core):
|
|
107
|
+
a = {'foo': {'bar': [1],
|
|
108
|
+
'baz': [2]}}
|
|
109
|
+
b = {'foo': {'bar': 3},
|
|
110
|
+
'baz': 12}
|
|
111
|
+
|
|
112
|
+
assert core.merge_schemas(a, b) == \
|
|
113
|
+
{'foo': {'bar': 3,
|
|
114
|
+
'baz': [2]},
|
|
115
|
+
'baz': 12}
|
|
116
|
+
|
|
117
|
+
|
|
82
118
|
def test_generate_default(core):
|
|
83
119
|
int_default = core.default(
|
|
84
120
|
{'_type': 'integer'}
|
|
@@ -126,6 +162,15 @@ def test_apply_update(core):
|
|
|
126
162
|
|
|
127
163
|
|
|
128
164
|
def print_schema_validation(core, library, should_pass):
|
|
165
|
+
"""
|
|
166
|
+
validate_schema returns nothing for a valid schema declaration
|
|
167
|
+
|
|
168
|
+
this helper function makes clearer reports out of the test
|
|
169
|
+
failures
|
|
170
|
+
|
|
171
|
+
this is also why running the file outside pytest prints out
|
|
172
|
+
a huge wall of text
|
|
173
|
+
"""
|
|
129
174
|
for key, declaration in library.items():
|
|
130
175
|
report = core.validate_schema(declaration)
|
|
131
176
|
if len(report) == 0:
|
|
@@ -605,7 +650,8 @@ def test_link_place(core):
|
|
|
605
650
|
|
|
606
651
|
def test_units(core):
|
|
607
652
|
schema_length = {
|
|
608
|
-
'distance': {
|
|
653
|
+
'distance': {
|
|
654
|
+
'_type': 'length'}}
|
|
609
655
|
|
|
610
656
|
state = {'distance': 11 * units.meter}
|
|
611
657
|
update = {'distance': -5 * units.feet}
|
|
@@ -838,7 +884,7 @@ def test_inherits_from(core):
|
|
|
838
884
|
|
|
839
885
|
assert core.inherits_from(
|
|
840
886
|
'tree[path]',
|
|
841
|
-
'tree[list[
|
|
887
|
+
'tree[list[mark]]')
|
|
842
888
|
|
|
843
889
|
assert not core.inherits_from(
|
|
844
890
|
'tree[path]',
|
|
@@ -1368,106 +1414,108 @@ def test_maybe_type(core):
|
|
|
1368
1414
|
|
|
1369
1415
|
|
|
1370
1416
|
def test_tuple_type(core):
|
|
1371
|
-
|
|
1417
|
+
schemas = [{
|
|
1372
1418
|
'_type': 'tuple',
|
|
1373
1419
|
'_type_parameters': ['0', '1', '2'],
|
|
1374
1420
|
'_0': 'string',
|
|
1375
|
-
'_1': '
|
|
1376
|
-
'_2': 'map[maybe[float]]'}
|
|
1421
|
+
'_1': 'integer',
|
|
1422
|
+
'_2': 'map[maybe[float]]'},
|
|
1377
1423
|
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1424
|
+
('string', 'integer', 'map[maybe[float]]'),
|
|
1425
|
+
'tuple[string,integer,map[maybe[float]]]',
|
|
1426
|
+
'string|integer|map[maybe[float]]']
|
|
1381
1427
|
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1428
|
+
for schema in schemas:
|
|
1429
|
+
state = (
|
|
1430
|
+
'aaaaa',
|
|
1431
|
+
13, {
|
|
1432
|
+
'a': 1.1,
|
|
1433
|
+
'b': None})
|
|
1387
1434
|
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1435
|
+
update = (
|
|
1436
|
+
'bbbbbb',
|
|
1437
|
+
10, {
|
|
1438
|
+
'a': 33.33,
|
|
1439
|
+
'b': 4.44444})
|
|
1393
1440
|
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1441
|
+
assert core.check(schema, state)
|
|
1442
|
+
assert core.check(schema, update)
|
|
1443
|
+
assert not core.check(schema, 15)
|
|
1397
1444
|
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1445
|
+
result = core.apply(
|
|
1446
|
+
schema,
|
|
1447
|
+
state,
|
|
1448
|
+
update)
|
|
1402
1449
|
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1450
|
+
assert len(result) == 3
|
|
1451
|
+
assert result[0] == update[0]
|
|
1452
|
+
assert result[1] == 23
|
|
1453
|
+
assert result[2]['a'] == 34.43
|
|
1454
|
+
assert result[2]['b'] == update[2]['b']
|
|
1408
1455
|
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1456
|
+
encode = core.serialize(schema, state)
|
|
1457
|
+
assert encode[2]['b'] == NONE_SYMBOL
|
|
1458
|
+
assert encode[1] == '13'
|
|
1412
1459
|
|
|
1413
|
-
|
|
1414
|
-
|
|
1460
|
+
decode = core.deserialize(schema, encode)
|
|
1461
|
+
assert decode == state
|
|
1415
1462
|
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1463
|
+
tuple_type = core.access('(3|4|10)')
|
|
1464
|
+
assert '_2' in tuple_type
|
|
1465
|
+
assert tuple_type['_2'] == '10'
|
|
1419
1466
|
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1467
|
+
tuple_type = core.access('tuple[9,float,7]')
|
|
1468
|
+
assert '_2' in tuple_type
|
|
1469
|
+
assert tuple_type['_2'] == '7'
|
|
1423
1470
|
|
|
1424
1471
|
|
|
1425
1472
|
def test_union_type(core):
|
|
1426
|
-
|
|
1473
|
+
schemas = [{
|
|
1427
1474
|
'_type': 'union',
|
|
1428
1475
|
'_type_parameters': ['0', '1', '2'],
|
|
1429
1476
|
'_0': 'string',
|
|
1430
1477
|
'_1': 'integer',
|
|
1431
|
-
'_2': 'map[maybe[float]]'}
|
|
1478
|
+
'_2': 'map[maybe[float]]'},
|
|
1432
1479
|
|
|
1433
|
-
|
|
1480
|
+
'string~integer~map[maybe[float]]']
|
|
1434
1481
|
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1482
|
+
for schema in schemas:
|
|
1483
|
+
state = {
|
|
1484
|
+
'a': 1.1,
|
|
1485
|
+
'b': None}
|
|
1438
1486
|
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1487
|
+
update = {
|
|
1488
|
+
'a': 33.33,
|
|
1489
|
+
'b': 4.44444}
|
|
1442
1490
|
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1491
|
+
assert core.check(schema, state)
|
|
1492
|
+
assert core.check(schema, update)
|
|
1493
|
+
assert core.check(schema, 15)
|
|
1446
1494
|
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1495
|
+
wrong_state = {
|
|
1496
|
+
'a': 1.1,
|
|
1497
|
+
'b': None}
|
|
1450
1498
|
|
|
1451
|
-
|
|
1499
|
+
wrong_update = 'a different type'
|
|
1452
1500
|
|
|
1453
|
-
|
|
1454
|
-
|
|
1501
|
+
assert core.check(schema, wrong_state)
|
|
1502
|
+
assert core.check(schema, wrong_update)
|
|
1455
1503
|
|
|
1456
|
-
|
|
1504
|
+
# TODO: deal with union apply of different types
|
|
1457
1505
|
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1506
|
+
result = core.apply(
|
|
1507
|
+
schema,
|
|
1508
|
+
state,
|
|
1509
|
+
update)
|
|
1462
1510
|
|
|
1463
|
-
|
|
1464
|
-
|
|
1511
|
+
assert result['a'] == 34.43
|
|
1512
|
+
assert result['b'] == update['b']
|
|
1465
1513
|
|
|
1466
|
-
|
|
1467
|
-
|
|
1514
|
+
encode = core.serialize(schema, state)
|
|
1515
|
+
assert encode['b'] == NONE_SYMBOL
|
|
1468
1516
|
|
|
1469
|
-
|
|
1470
|
-
|
|
1517
|
+
decode = core.deserialize(schema, encode)
|
|
1518
|
+
assert decode == state
|
|
1471
1519
|
|
|
1472
1520
|
|
|
1473
1521
|
def test_union_values(core):
|
|
@@ -1992,27 +2040,6 @@ def test_set_slice(core):
|
|
|
1992
2040
|
1])[1] == 33
|
|
1993
2041
|
|
|
1994
2042
|
|
|
1995
|
-
def from_state(dataclass, state):
|
|
1996
|
-
if hasattr(dataclass, '__dataclass_fields__'):
|
|
1997
|
-
fields = dataclass.__dataclass_fields__
|
|
1998
|
-
state = state or {}
|
|
1999
|
-
|
|
2000
|
-
init = {}
|
|
2001
|
-
for key, field in fields.items():
|
|
2002
|
-
substate = from_state(
|
|
2003
|
-
field.type,
|
|
2004
|
-
state.get(key))
|
|
2005
|
-
init[key] = substate
|
|
2006
|
-
instance = dataclass(**init)
|
|
2007
|
-
# elif get_origin(dataclass) in [typing.Union, typing.Mapping]:
|
|
2008
|
-
# instance = state
|
|
2009
|
-
else:
|
|
2010
|
-
instance = state
|
|
2011
|
-
# instance = dataclass(state)
|
|
2012
|
-
|
|
2013
|
-
return instance
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
2043
|
def test_dataclass(core):
|
|
2017
2044
|
simple_schema = {
|
|
2018
2045
|
'a': 'float',
|
|
@@ -2023,7 +2050,7 @@ def test_dataclass(core):
|
|
|
2023
2050
|
# TODO: accept just a string instead of only a path
|
|
2024
2051
|
simple_dataclass = core.dataclass(
|
|
2025
2052
|
simple_schema,
|
|
2026
|
-
|
|
2053
|
+
'simple')
|
|
2027
2054
|
|
|
2028
2055
|
simple_state = {
|
|
2029
2056
|
'a': 88.888,
|
|
@@ -2037,10 +2064,14 @@ def test_dataclass(core):
|
|
|
2037
2064
|
c=True,
|
|
2038
2065
|
x='what')
|
|
2039
2066
|
|
|
2040
|
-
simple_from =
|
|
2067
|
+
simple_from = state_instance(
|
|
2041
2068
|
simple_dataclass,
|
|
2042
2069
|
simple_state)
|
|
2043
2070
|
|
|
2071
|
+
default_simple = core.default_instance(
|
|
2072
|
+
simple_schema,
|
|
2073
|
+
'simple_default')
|
|
2074
|
+
|
|
2044
2075
|
nested_schema = {
|
|
2045
2076
|
'a': {
|
|
2046
2077
|
'a': {
|
|
@@ -2050,7 +2081,7 @@ def test_dataclass(core):
|
|
|
2050
2081
|
|
|
2051
2082
|
nested_dataclass = core.dataclass(
|
|
2052
2083
|
nested_schema,
|
|
2053
|
-
|
|
2084
|
+
'nested')
|
|
2054
2085
|
|
|
2055
2086
|
nested_state = {
|
|
2056
2087
|
'a': {
|
|
@@ -2066,7 +2097,7 @@ def test_dataclass(core):
|
|
|
2066
2097
|
b=3.3333),
|
|
2067
2098
|
5555.55))
|
|
2068
2099
|
|
|
2069
|
-
nested_from =
|
|
2100
|
+
nested_from = state_instance(
|
|
2070
2101
|
nested_dataclass,
|
|
2071
2102
|
nested_state)
|
|
2072
2103
|
|
|
@@ -2079,7 +2110,7 @@ def test_dataclass(core):
|
|
|
2079
2110
|
|
|
2080
2111
|
complex_dataclass = core.dataclass(
|
|
2081
2112
|
complex_schema,
|
|
2082
|
-
|
|
2113
|
+
'complex')
|
|
2083
2114
|
|
|
2084
2115
|
complex_state = {
|
|
2085
2116
|
'a': {
|
|
@@ -2103,7 +2134,7 @@ def test_dataclass(core):
|
|
|
2103
2134
|
'OOO': ['..', '..', 'a', 'w']}}},
|
|
2104
2135
|
'e': np.zeros((3, 4, 10))}}
|
|
2105
2136
|
|
|
2106
|
-
complex_from =
|
|
2137
|
+
complex_from = state_instance(
|
|
2107
2138
|
complex_dataclass,
|
|
2108
2139
|
complex_state)
|
|
2109
2140
|
|
|
@@ -2121,6 +2152,7 @@ def test_enum_type(core):
|
|
|
2121
2152
|
'planet',
|
|
2122
2153
|
'enum[mercury,venus,earth,mars,jupiter,saturn,neptune]')
|
|
2123
2154
|
|
|
2155
|
+
# this is equivalent to the above (TODO: test this)
|
|
2124
2156
|
# core.register('planet', {
|
|
2125
2157
|
# '_type': 'enum',
|
|
2126
2158
|
# '_type_parameters': ['0', '1', '2', '3', '4', '5', '6'],
|
|
@@ -2247,8 +2279,8 @@ def test_generate(core):
|
|
|
2247
2279
|
'_type': 'enum[x,y,z]',
|
|
2248
2280
|
'_default': 'y'},
|
|
2249
2281
|
'units': {
|
|
2250
|
-
'
|
|
2251
|
-
'
|
|
2282
|
+
'meters': 11.1111,
|
|
2283
|
+
'seconds': 22.833333}}
|
|
2252
2284
|
|
|
2253
2285
|
generated_schema, generated_state = core.generate(
|
|
2254
2286
|
schema,
|
|
@@ -2257,8 +2289,8 @@ def test_generate(core):
|
|
|
2257
2289
|
assert generated_state['A'] == 0.0
|
|
2258
2290
|
assert generated_state['B'] == 'one'
|
|
2259
2291
|
assert generated_state['C'] == 'y'
|
|
2260
|
-
assert generated_state['units']['
|
|
2261
|
-
assert '
|
|
2292
|
+
assert generated_state['units']['seconds'] == 22.833333
|
|
2293
|
+
assert 'meters' not in generated_schema['units']
|
|
2262
2294
|
|
|
2263
2295
|
|
|
2264
2296
|
def test_edge_cycle(core):
|
|
@@ -2382,6 +2414,14 @@ def test_union_key_error(core):
|
|
|
2382
2414
|
result = generate_method(core, schema, state)
|
|
2383
2415
|
|
|
2384
2416
|
|
|
2417
|
+
def test_update_removed(core):
|
|
2418
|
+
schema = 'map[float]'
|
|
2419
|
+
state = {
|
|
2420
|
+
'a': 11.11,
|
|
2421
|
+
'b': 12.2222,
|
|
2422
|
+
'c': 13.33333333}
|
|
2423
|
+
|
|
2424
|
+
|
|
2385
2425
|
def fix_test_slice_edge(core):
|
|
2386
2426
|
initial_schema = {
|
|
2387
2427
|
'edge': {
|
|
@@ -2504,6 +2544,7 @@ if __name__ == '__main__':
|
|
|
2504
2544
|
core = TypeSystem()
|
|
2505
2545
|
core = register_test_types(core)
|
|
2506
2546
|
|
|
2547
|
+
test_basic_types(core)
|
|
2507
2548
|
test_reregister_type(core)
|
|
2508
2549
|
test_generate_default(core)
|
|
2509
2550
|
test_apply_update(core)
|
|
@@ -2554,6 +2595,8 @@ if __name__ == '__main__':
|
|
|
2554
2595
|
test_union_key_error(core)
|
|
2555
2596
|
test_tree_equivalence(core)
|
|
2556
2597
|
test_star_view_project(core)
|
|
2598
|
+
test_update_removed(core)
|
|
2599
|
+
test_merge_schemas(core)
|
|
2557
2600
|
|
|
2558
2601
|
# test_slice_edge(core)
|
|
2559
2602
|
# test_complex_wiring(core)
|