def test_passthrough_bounds(): """Test that unspecified Bounds are accepted and set to None.""" template = ProcessTemplate('foo', conditions=[ (LinkByUID('1', '2'), None), [LinkByUID('3', '4'), None], LinkByUID('5', '6'), ConditionTemplate('foo', bounds=IntegerBounds( 0, 10)), ]) assert len(template.conditions) == 4 for _, bounds in template.conditions: assert bounds is None copied = loads(dumps(template)) assert len(copied.conditions) == 4 for _, bounds in copied.conditions: assert bounds is None from_dict = ProcessTemplate.build({ 'type': 'process_template', 'name': 'foo', 'conditions': [[ { 'scope': 'foo', 'id': 'bar', 'type': 'link_by_uid', }, None, ]], }) assert len(from_dict.conditions) == 1
def test_dependencies(): """Test that dependency lists make sense.""" attribute_bounds = RealBounds(0, 100, '') cond_template = ConditionTemplate("a condition", bounds=attribute_bounds) proc_template = ProcessTemplate("a process template", conditions=[cond_template]) assert cond_template in proc_template.all_dependencies()
def __init__(self, name: str, *, uids: Optional[Dict[str, str]] = None, conditions: Optional[Sequence[ Union[ConditionTemplate, LinkByUID, Sequence[Union[ConditionTemplate, LinkByUID, Optional[BaseBounds]]]]]] = None, parameters: Optional[Sequence[ Union[ParameterTemplate, LinkByUID, Sequence[Union[ParameterTemplate, LinkByUID, Optional[BaseBounds]]]]]] = None, allowed_labels: Optional[List[str]] = None, allowed_names: Optional[List[str]] = None, description: Optional[str] = None, tags: Optional[List[str]] = None): if uids is None: uids = dict() DataConcepts.__init__(self, GEMDProcessTemplate.typ) GEMDProcessTemplate.__init__(self, name=name, uids=uids, conditions=conditions, parameters=parameters, tags=tags, description=description, allowed_labels=allowed_labels, allowed_names=allowed_names)
def test_bounds_mismatch(): """Test that a mismatch between the attribute and given bounds throws a ValueError.""" attribute_bounds = RealBounds(0, 100, '') object_bounds = RealBounds(200, 300, '') cond_template = ConditionTemplate("a condition", bounds=attribute_bounds) with pytest.raises(ValueError): ProcessTemplate("a process template", conditions=[[cond_template, object_bounds]])
def test_template_access(): """A process run's template should be equal to its spec's template.""" template = ProcessTemplate("process template", uids={'id': str(uuid4())}) spec = ProcessSpec("A spec", uids={'id': str(uuid4())}, template=template) proc = ProcessRun("A run", uids={'id': str(uuid4())}, spec=spec) assert proc.template == template proc.spec = LinkByUID.from_entity(spec) assert proc.template is None
def test_flatten_bounds(): """Test that flatten works when the objects contain other objects.""" bounds = CategoricalBounds(categories=["foo", "bar"]) template = ProcessTemplate( "spam", conditions=[(ConditionTemplate(name="eggs", bounds=bounds), bounds)] ) spec = ProcessSpec(name="spec", template=template) flat = flatten(spec, 'test-scope') assert len(flat) == 2, "Expected 2 flattened objects"
def test_invalid_assignment(): """Test that invalid assignments throw the appropriate errors.""" with pytest.raises(ValueError): Property(value=NominalReal(10, '')) with pytest.raises(TypeError): Property(name="property", value=10) with pytest.raises(TypeError): Property(name="property", template=ProcessTemplate("wrong kind of template")) with pytest.raises(ValueError): Property(name="property", origin=None)
def test_allowed_labels(): """ Test that allowed_labels can be assigned. Presently allowed_labels is not used for any validation, but this test can be expanded if it is used in the future. """ allowed_labels = ["solvent", "salt", "binder", "polymer"] proc_template = ProcessTemplate(name="test template", allowed_labels=allowed_labels) for label in allowed_labels: assert label in proc_template.allowed_labels
def test_allowed_names(): """ Test that allowed_names can be assigned. Presently allowed_names is not used for any validation, but this test can be expanded if it is used in the future. """ allowed_names = ["THF", "Carbon Disulfide", "Dimethyl Ether"] proc_template = ProcessTemplate(name="test template", allowed_names=allowed_names) for name in allowed_names: assert name in proc_template.allowed_names
def test_repeated_objects(): """Test that objects aren't double counted.""" ct = ConditionTemplate(name="color", bounds=CategoricalBounds(categories=["black", "white"])) pt = ProcessTemplate(name="painting", conditions=[ct]) ps = ProcessSpec(name='painting', template=pt, conditions=Condition(name='Paint color', value=NominalCategorical("black"), template=ct ) ) assert len(recursive_flatmap(ps, lambda x: [x])) == 3
def test_invalid_assignment(caplog): """Test that invalid assignments throw the appropriate errors.""" with pytest.raises(TypeError): Property(value=NominalReal(10, '')) with pytest.raises(TypeError): Property(name="property", value=10) with pytest.raises(TypeError): Property(name="property", template=ProcessTemplate("wrong kind of template")) with pytest.raises(ValueError): Property(name="property", origin=None) valid_prop = Property(name="property", value=NominalReal(10, ''), template=PropertyTemplate("template", bounds=RealBounds( 0, 100, ''))) good_val = valid_prop.value bad_val = NominalReal(-10.0, '') assert len(caplog.records ) == 0, "Warning caught before logging tests were reached." with validation_level(WarningLevel.IGNORE): valid_prop.value = bad_val assert len(caplog.records ) == 0, "Validation warned even though level is IGNORE." assert valid_prop.value == bad_val, "IGNORE allowed the bad value to be set." valid_prop.value = good_val assert len(caplog.records ) == 0, "Validation warned even though level is IGNORE." with validation_level(WarningLevel.WARNING): valid_prop.value = bad_val assert len(caplog.records ) == 1, "Validation didn't warn on out of bounds value." assert valid_prop.value == bad_val, "WARNING allowed the bad value to be set." valid_prop.value = good_val assert len( caplog.records) == 1, "Validation DID warn on a valid value." with validation_level(WarningLevel.FATAL): with pytest.raises(ValueError): valid_prop.value = bad_val assert valid_prop.value == good_val, "FATAL didn't allow the bad value to be set." with validation_level(WarningLevel.FATAL): with pytest.raises(ValueError): valid_prop.template = PropertyTemplate("template", bounds=RealBounds(0, 1, '')) assert valid_prop.value == good_val, "FATAL didn't allow the bad value to be set."
density_template = PropertyTemplate(name="Density", bounds=RealBounds(lower_bound=0, upper_bound=1.0e9, default_units='')) firing_temperature_template = ConditionTemplate(name="Firing Temperature", bounds=RealBounds( lower_bound=0, upper_bound=1.0e9, default_units='degC')) measurement_template = MeasurementTemplate("Density Measurement", properties=density_template) firing_template = ProcessTemplate(name="Firing in a kiln", conditions=(firing_temperature_template, RealBounds( lower_bound=500, upper_bound=1000, default_units='degC'))) material_template = MaterialTemplate(name="Some ceramic thing", properties=density_template) def make_data_island(density, bulk_modulus, firing_temperature, binders, powders, tag=None): """Helper function to create a relatively involved data island.""" binder_specs = keymap(lambda x: MaterialSpec(name=x), binders) powder_specs = keymap(lambda x: MaterialSpec(name=x), powders)