def test_inplace_v_not(): """Test that client can copy a dictionary in which keys are BaseEntity objects.""" spec = ProcessSpec("A process spec", uids={'id': str(uuid4()), 'auto': str(uuid4())}) run1 = ProcessRun("A process run", spec=spec, uids={'id': str(uuid4()), 'auto': str(uuid4())}) run2 = ProcessRun("Another process run", spec=spec, uids={'id': str(uuid4())}) process_dict = {spec: [run1, run2]} subbed = substitute_links(process_dict) assert subbed != process_dict # This is true because the hashes change, even if objects equal substitute_links(process_dict, inplace=True) assert subbed == process_dict
def test_scope_substitution(): """Test that the native id gets serialized, when specified.""" native_id = 'id1' # Create measurement and material with two ids mat = MaterialRun("A material", uids={ native_id: str(uuid4()), "an_id": str(uuid4()), "another_id": str(uuid4())}) meas = MeasurementRun("A measurement", material=mat, uids={ "some_id": str(uuid4()), native_id: str(uuid4()), "an_id": str(uuid4())}) # Turn the material pointer into a LinkByUID using native_id subbed = substitute_links(meas, scope=native_id) assert subbed.material == LinkByUID.from_entity(mat, scope=native_id) # Put the measurement into a list and convert that into a LinkByUID using native_id measurements_list = [meas] subbed = substitute_links(measurements_list, scope=native_id) assert subbed == [LinkByUID.from_entity(meas, scope=native_id)]
def test_object_key_substitution(): """Test that client can copy a dictionary in which keys are BaseEntity objects.""" spec = ProcessSpec("A process spec", uids={'id': str(uuid4()), 'auto': str(uuid4())}) run1 = ProcessRun("A process run", spec=spec, uids={'id': str(uuid4()), 'auto': str(uuid4())}) run2 = ProcessRun("Another process run", spec=spec, uids={'id': str(uuid4())}) process_dict = {spec: [run1, run2]} subbed = substitute_links(process_dict, scope='auto') for key, value in subbed.items(): assert key == LinkByUID.from_entity(spec, scope='auto') assert LinkByUID.from_entity(run1, scope='auto') in value assert LinkByUID.from_entity(run2) in value reverse_process_dict = {run2: spec} subbed = substitute_links(reverse_process_dict, scope='auto') for key, value in subbed.items(): assert key == LinkByUID.from_entity(run2) assert value == LinkByUID.from_entity(spec, scope='auto')
def test_signature(): """Exercise various permutations of the substitute_links sig.""" spec = ProcessSpec("A process spec", uids={'my': 'spec'}) with pytest.warns(DeprecationWarning): run1 = ProcessRun("First process run", uids={'my': 'run1'}, spec=spec) assert isinstance(substitute_links(run1, native_uid='my').spec, LinkByUID) run2 = ProcessRun("Second process run", uids={'my': 'run2'}, spec=spec) assert isinstance(substitute_links(run2, scope='my').spec, LinkByUID) run3 = ProcessRun("Third process run", uids={'my': 'run3'}, spec=spec) assert isinstance(substitute_links(run3, 'my').spec, LinkByUID) with pytest.raises(ValueError): # Test deprecated auto-population run4 = ProcessRun("Fourth process run", uids={'my': 'run4'}, spec=spec) assert isinstance(substitute_links(run4, 'other', allow_fallback=False).spec, LinkByUID) with pytest.warns(DeprecationWarning): with pytest.raises(ValueError): # Test deprecated auto-population run5 = ProcessRun("Fifth process run", uids={'my': 'run4'}, spec=spec) assert isinstance(substitute_links(run5, scope="my", native_uid="my").spec, LinkByUID)
def test_substitution_without_id(): """Test that trying to substitute links if uids haven't been assigned throws an error.""" mat = MaterialRun("A material with no id") meas = MeasurementRun("A measurement with no id", material=mat) with pytest.raises(ValueError): substitute_links(meas), "subbed = substitute_links should fail if objects don't have uids" with pytest.raises(ValueError): substitute_links([meas, mat]), \ "subbed = substitute_links should fail if objects don't have uids" with pytest.raises(ValueError): substitute_links(meas.as_dict()), \ "subbed = substitute_links should fail if objects don't have uids" # Create a dictionary in which either the key or value is missing a uid meas.add_uid('id', str(uuid4())) with pytest.raises(ValueError): substitute_links({mat: meas}), \ "subbed = substitute_links should fail if objects don't have uids" with pytest.raises(ValueError): substitute_links({meas: mat}), \ "subbed = substitute_links should fail if objects don't have uids"
def test_material_soft_link(): """Test that a measurement run can link to a material run, and that it survives serde.""" dye = MaterialRun("rhodamine", file_links=FileLink(filename='a.csv', url='/a/path')) assert dye.measurements == [], "default value of .measurements should be an empty list" # The .measurements member should not be settable with pytest.raises(AttributeError): dye.measurements = [MeasurementRun("Dummy")] absorbance = MeasurementRun(name="Absorbance", uids={'id': str(uuid4())}, properties=[ Property(name='Abs at 500 nm', value=NominalReal(0.1, '')) ]) assert absorbance.material is None, "Measurements should have None as the material by default" absorbance.material = dye assert absorbance.material == dye, "Material not set correctly for measurement" assert dye.measurements == [ absorbance ], "Soft-link from material to measurement not created" fluorescence = MeasurementRun(name="Fluorescence", uids={'id': str(uuid4())}, properties=[ Property(name='PL counts at 550 nm', value=NominalReal(30000, '')) ], material=dye) assert fluorescence.material == dye, "Material not set correctly for measurement" assert dye.measurements == [absorbance, fluorescence], \ "Soft-link from material to measurements not created" assert loads(dumps(absorbance)) == absorbance, \ "Measurement should remain unchanged when serialized" assert loads(dumps(fluorescence)) == fluorescence, \ "Measurement should remain unchanged when serialized" assert 'measurements' in repr(dye) assert 'material' in repr(fluorescence) assert 'material' in repr(absorbance) subbed = substitute_links(dye) assert 'measurements' in repr(subbed)
def body(obj: BaseEntity): copy = substitute_links(loads(dumps(obj))) result.append(json.loads(dumps(copy))["context"][0])