1
1
"""Test serialization and deserialization of taurus objects."""
2
2
import json
3
+ from copy import deepcopy
4
+
3
5
import pytest
4
6
5
- from taurus .client .json_encoder import dumps , loads , copy , thin_dumps
7
+ from taurus .client .json_encoder import dumps , loads , copy , thin_dumps , _loado
8
+ from taurus .entity .attribute .property import Property
9
+ from taurus .entity .bounds .real_bounds import RealBounds
6
10
from taurus .entity .dict_serializable import DictSerializable
7
11
from taurus .entity .case_insensitive_dict import CaseInsensitiveDict
8
12
from taurus .entity .attribute .condition import Condition
11
15
from taurus .entity .object import MeasurementRun , MaterialRun , ProcessRun , MeasurementSpec
12
16
from taurus .entity .object .ingredient_run import IngredientRun
13
17
from taurus .entity .object .ingredient_spec import IngredientSpec
18
+ from taurus .entity .template .property_template import PropertyTemplate
14
19
from taurus .entity .value .nominal_integer import NominalInteger
15
20
from taurus .entity .value .nominal_real import NominalReal
16
21
from taurus .entity .value .normal_real import NormalReal
17
22
from taurus .enumeration .origin import Origin
23
+ from taurus .util import substitute_objects , substitute_links
18
24
19
25
20
26
def test_serialize ():
@@ -66,8 +72,24 @@ def test_enumeration_serde():
66
72
assert copy_condition .notes == Origin .get_value (condition .notes )
67
73
68
74
75
+ def test_attribute_serde ():
76
+ """An attribute with a link to an attribute template should be copy-able."""
77
+ prop_tmpl = PropertyTemplate (name = 'prop_tmpl' ,
78
+ bounds = RealBounds (0 , 2 , 'm' )
79
+ )
80
+ prop = Property (name = 'prop' ,
81
+ template = prop_tmpl ,
82
+ value = NominalReal (1 , 'm' )
83
+ )
84
+ meas_spec = MeasurementSpec ("a spec" )
85
+ meas = MeasurementRun ("a measurement" , spec = meas_spec , properties = [prop ])
86
+ assert loads (dumps (prop )) == prop
87
+ assert loads (dumps (meas )) == meas
88
+ assert isinstance (prop .template , PropertyTemplate )
89
+
90
+
69
91
def test_thin_dumps ():
70
- """Test that thin_dumps turns pointers into links and doesn't work on non-BaseEntity ."""
92
+ """Test that thin_dumps turns pointers into links."""
71
93
mat = MaterialRun ("The actual material" )
72
94
meas_spec = MeasurementSpec ("measurement" , uids = {'my_scope' : '324324' })
73
95
meas = MeasurementRun ("The measurement" , spec = meas_spec , material = mat )
@@ -78,8 +100,13 @@ def test_thin_dumps():
78
100
assert isinstance (thin_copy .spec , LinkByUID )
79
101
assert thin_copy .spec .id == meas_spec .uids ['my_scope' ]
80
102
103
+ # Check that LinkByUID objects are correctly converted their JSON equivalent
104
+ expected_json = '{"id": "my_id", "scope": "scope", "type": "link_by_uid"}'
105
+ assert thin_dumps (LinkByUID ('scope' , 'my_id' )) == expected_json
106
+
107
+ # Check that objects lacking .uid attributes will raise an exception when dumped
81
108
with pytest .raises (TypeError ):
82
- thin_dumps (LinkByUID ( 'scope' , 'id' ) )
109
+ thin_dumps ({{ 'key' : 'value' }} )
83
110
84
111
85
112
def test_uid_deser ():
@@ -126,6 +153,50 @@ def __init__(self, foo):
126
153
loads (serialized )
127
154
128
155
156
+ def test_pure_subsitutions ():
157
+ """Make sure substitute methods don't mutate inputs."""
158
+ json_str = '''
159
+ [
160
+ [
161
+ {
162
+ "uids": {
163
+ "id": "9118c2d3-1c38-47fe-a650-c2b92fdb6777"
164
+ },
165
+ "type": "material_run",
166
+ "name": "flour"
167
+ }
168
+ ],
169
+ {
170
+ "type": "ingredient_run",
171
+ "uids": {
172
+ "id": "8858805f-ec02-49e4-ba3b-d784e2aea3f8"
173
+ },
174
+ "material": {
175
+ "type": "link_by_uid",
176
+ "scope": "ID",
177
+ "id": "9118c2d3-1c38-47fe-a650-c2b92fdb6777"
178
+ },
179
+ "process": {
180
+ "type": "link_by_uid",
181
+ "scope": "ID",
182
+ "id": "9148c2d3-2c38-47fe-b650-c2b92fdb6777"
183
+ }
184
+ }
185
+ ]
186
+ '''
187
+ index = {}
188
+ original = json .loads (json_str , object_hook = lambda x : _loado (x , index ))
189
+ frozen = deepcopy (original )
190
+ loaded = substitute_objects (original , index )
191
+ assert original == frozen
192
+ frozen_loaded = deepcopy (loaded )
193
+ substitute_links (loaded )
194
+ assert loaded == frozen_loaded
195
+ for o in loaded :
196
+ substitute_links (o )
197
+ assert loaded == frozen_loaded
198
+
199
+
129
200
def test_case_insensitive_rehydration ():
130
201
"""
131
202
0 commit comments