Esempio n. 1
0
    def __init__(self,
                 name: str,
                 *,
                 uids: Optional[Dict[str, str]] = None,
                 tags: Optional[List[str]] = None,
                 notes: Optional[str] = None,
                 material: Optional[GEMDMaterialSpec] = None,
                 process: Optional[GEMDProcessSpec] = None,
                 mass_fraction: Optional[ContinuousValue] = None,
                 volume_fraction: Optional[ContinuousValue] = None,
                 number_fraction: Optional[ContinuousValue] = None,
                 absolute_quantity: Optional[ContinuousValue] = None,
                 labels: Optional[List[str]] = None,
                 file_links: Optional[List[FileLink]] = None):
        if uids is None:
            uids = dict()

        DataConcepts.__init__(self, GEMDIngredientSpec.typ)
        GEMDIngredientSpec.__init__(self,
                                    uids=uids,
                                    tags=tags,
                                    notes=notes,
                                    material=material,
                                    process=process,
                                    mass_fraction=mass_fraction,
                                    volume_fraction=volume_fraction,
                                    number_fraction=number_fraction,
                                    absolute_quantity=absolute_quantity,
                                    labels=labels,
                                    name=name,
                                    file_links=file_links)
def test_invalid_assignment():
    """Invalid assignments to `process` or `material` throw a TypeError."""
    with pytest.raises(TypeError):
        IngredientSpec(name="name", material=NominalReal(3, ''))
    with pytest.raises(TypeError):
        IngredientSpec(name="name", process="process")
    with pytest.raises(TypeError):
        IngredientSpec()  # Name is required
def test_bad_has_template():
    """Make sure the non-implementation of HasTemplate behaves properly."""
    assert isinstance(None, IngredientSpec(name="name")._template_type()), \
        "Ingredients didn't have NoneType templates"
    assert IngredientSpec(name="name").template is None, \
        "An ingredient didn't have a null template."
    with pytest.raises(
            AttributeError):  # Note an AttributeError, not a TypeError
        IngredientSpec(name="name").template = 1
Esempio n. 4
0
def test_invalid_quantities(invalid_quantity):
    """Check that any non-continuous value for a quantity throws a TypeError."""
    with pytest.raises(TypeError):
        IngredientSpec(name="name", mass_fraction=invalid_quantity)
    with pytest.raises(TypeError):
        IngredientSpec(name="name", volume_fraction=invalid_quantity)
    with pytest.raises(TypeError):
        IngredientSpec(name="name", number_fraction=invalid_quantity)
    with pytest.raises(TypeError):
        IngredientSpec(name="name", absolute_quantity=invalid_quantity)
Esempio n. 5
0
def test_valid_quantities(valid_quantity):
    """
    Check that all quantities must be continuous values.

    There are no restrictions on the value or the units. Although a volume fraction of -5 kg
    does not make physical sense, it will not throw an error.
    """
    ingred = IngredientSpec(name="name", mass_fraction=valid_quantity)
    assert ingred.mass_fraction == valid_quantity
    ingred = IngredientSpec(name="name", volume_fraction=valid_quantity)
    assert ingred.volume_fraction == valid_quantity
    ingred = IngredientSpec(name="name", number_fraction=valid_quantity)
    assert ingred.number_fraction == valid_quantity
    ingred = IngredientSpec(name="name", absolute_quantity=valid_quantity)
    assert ingred.absolute_quantity == valid_quantity
Esempio n. 6
0
def test_scope_control():
    """Serializing a nested object should be identical to individually serializing each piece."""
    input_material = MaterialSpec()
    process = ProcessSpec()
    IngredientSpec(material=input_material, process=process)
    material = MaterialSpec(process=process)

    # Verify the default scope is there
    default_json = GEMDJson()
    default_text = default_json.dumps(material)
    assert "auto" in default_text
    assert "custom" not in default_text

    # Clear out ids
    input_material.uids = {}
    process.uids = {}
    process.ingredients[0].uids = {}
    input_material.uids = {}
    material.uids = {}

    # Verify the default scope is there
    custom_json = GEMDJson(scope='custom')
    custom_text = custom_json.dumps(material)
    assert "auto" not in custom_text
    assert "custom" in custom_text
Esempio n. 7
0
def test_circular_crawl():
    """Test that make_instance can handle a circular set of linked objects."""
    proc = ProcessSpec("process name")
    mat = MaterialSpec("material name", process=proc)
    IngredientSpec(name="ingredient name", material=mat, process=proc)
    mat_run = make_instance(mat)
    assert mat_run == mat_run.process.ingredients[0].material
def test_valid_quantities(valid_quantity, caplog):
    """
    Check that all quantities must be continuous values.

    There are no restrictions on the value or the units. Although a volume fraction of -5 kg
    does not make physical sense, it will not throw an error.
    """
    with validation_level(WarningLevel.IGNORE):
        ingred = IngredientSpec(name="name", mass_fraction=valid_quantity)
        assert ingred.mass_fraction == valid_quantity
        ingred = IngredientSpec(name="name", volume_fraction=valid_quantity)
        assert ingred.volume_fraction == valid_quantity
        ingred = IngredientSpec(name="name", number_fraction=valid_quantity)
        assert ingred.number_fraction == valid_quantity
        ingred = IngredientSpec(name="name", absolute_quantity=valid_quantity)
        assert ingred.absolute_quantity == valid_quantity
    assert len(caplog.records) == 0, "Warned when validation set to IGNORE."
Esempio n. 9
0
def test_ingredient_spec():
    """Tests that a process can house an ingredient, and that pairing survives serialization."""
    # Create a ProcessSpec
    proc_spec = ProcessSpec(name="a process spec", tags=["tag1", "tag2"])
    IngredientSpec(name='Input',
                   material=MaterialSpec(name='Raw'),
                   process=proc_spec)

    # Make copies of both specs
    proc_spec_copy = loads(dumps(proc_spec))

    assert proc_spec_copy == proc_spec, "Full structure wasn't preserved across serialization"
Esempio n. 10
0
def test_many_ingredients():
    """Test that ingredients remain connected to processes when round-robined through json."""
    proc = ProcessRun("foo", spec=ProcessSpec("sfoo"))
    expected = []
    for i in range(10):
        mat = MaterialRun(name=str(i), spec=MaterialSpec("s{}".format(i)))
        i_spec = IngredientSpec(name="i{}".format(i), material=mat.spec, process=proc.spec)
        IngredientRun(process=proc, material=mat, spec=i_spec)
        expected.append("i{}".format(i))

    reloaded = loads(dumps(proc))
    assert len(list(reloaded.ingredients)) == 10
    names = [x.name for x in reloaded.ingredients]
    assert sorted(names) == sorted(expected)
Esempio n. 11
0
def test_make_instance():
    """Build up several linked objects and test their properties."""
    msr_spec = MeasurementSpec()
    assert isinstance(make_instance(msr_spec), MeasurementRun)

    mat_spec = MaterialSpec(name='Mat name')
    mat_spec.process = ProcessSpec(name='Pro name')
    IngredientSpec(name='Ing label', process=mat_spec.process)
    mat_spec.process.ingredients[0].material = MaterialSpec(name='Baby mat name')

    mat_run = make_instance(mat_spec)
    assert isinstance(mat_run, MaterialRun)
    assert isinstance(mat_run.process, ProcessRun)
    assert isinstance(mat_run.process.ingredients[0], IngredientRun)
    assert isinstance(mat_run.process.ingredients[0].material, MaterialRun)

    assert mat_run.process.spec == mat_run.spec.process
    ingredient = mat_run.process.ingredients[0]
    assert ingredient.spec == mat_run.spec.process.ingredients[0]
    assert ingredient.material.spec == mat_run.spec.process.ingredients[0].material
def test_validation_control(caplog):
    """Verify that when validation is requested, limits are enforced."""
    with validation_level(WarningLevel.WARNING):
        IngredientSpec(name="name", mass_fraction=NominalReal(0.5, ''))
        assert len(caplog.records) == 0, "Warned on valid values with WARNING."
        IngredientSpec(name="name", mass_fraction=NominalReal(5, ''))
        assert len(
            caplog.records) == 1, "Didn't warn on invalid values with WARNING."
        IngredientSpec(name="name", mass_fraction=NominalReal(0.5, 'm'))
        assert len(
            caplog.records) == 2, "Didn't warn on invalid units with WARNING."
    with validation_level(WarningLevel.FATAL):
        # The following should not raise an exception
        IngredientSpec(name="name", mass_fraction=NominalReal(0.5, ''))
        with pytest.raises(ValueError):
            IngredientSpec(name="name", mass_fraction=NominalReal(5, ''))
        with pytest.raises(ValueError):
            IngredientSpec(name="name", mass_fraction=NominalReal(0.5, 'm'))
Esempio n. 13
0
def test_ingredient_reassignment():
    """Check that an ingredient spec can be re-assigned to a new process spec."""
    boiling = ProcessSpec("Boil potatoes")
    frying = ProcessSpec("Fry potatoes")
    oil = IngredientSpec(name="Oil", process=boiling)
    potatoes = IngredientSpec(name="Potatoes", process=boiling)
    assert oil.process == boiling
    assert set(boiling.ingredients) == {oil, potatoes}
    assert frying.ingredients == []

    oil.process = frying
    assert oil.process == frying
    assert boiling.ingredients == [potatoes]
    assert frying.ingredients == [oil]

    potatoes.process = frying
    assert potatoes.process == frying
    assert boiling.ingredients == []
    assert set(frying.ingredients) == {oil, potatoes}