From b383a4530e66b03b3d811e384cc7fa8ef3ecc5b9 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Wed, 30 Sep 2020 07:53:25 +0200 Subject: [PATCH] better name, subclassing for easy extension to load --- python/damask/__init__.py | 29 ++++---- python/damask/_config.py | 66 +++++++++++++++++++ .../{_material.py => _configmaterial.py} | 51 +------------- .../material.yaml | 0 ...est_Material.py => test_MaterialConfig.py} | 24 +++---- 5 files changed, 95 insertions(+), 75 deletions(-) create mode 100644 python/damask/_config.py rename python/damask/{_material.py => _configmaterial.py} (80%) rename python/tests/reference/{Material => ConfigMaterial}/material.yaml (100%) rename python/tests/{test_Material.py => test_MaterialConfig.py} (68%) diff --git a/python/damask/__init__.py b/python/damask/__init__.py index e21ebd03d..955993607 100644 --- a/python/damask/__init__.py +++ b/python/damask/__init__.py @@ -10,20 +10,21 @@ with open(_Path(__file__).parent/_Path('VERSION')) as _f: # make classes directly accessible as damask.Class from ._environment import Environment as _ # noqa environment = _() -from ._table import Table # noqa -from ._vtk import VTK # noqa -from ._colormap import Colormap # noqa -from ._rotation import Rotation # noqa -from ._lattice import Symmetry, Lattice# noqa -from ._orientation import Orientation # noqa -from ._result import Result # noqa -from ._geom import Geom # noqa -from ._material import Material # noqa -from . import solver # noqa -from . import util # noqa -from . import seeds # noqa -from . import grid_filters # noqa -from . import mechanics # noqa +from ._table import Table # noqa +from ._vtk import VTK # noqa +from ._colormap import Colormap # noqa +from ._rotation import Rotation # noqa +from ._lattice import Symmetry, Lattice# noqa +from ._orientation import Orientation # noqa +from ._result import Result # noqa +from ._geom import Geom # noqa +from ._config import Config # noqa +from ._configmaterial import ConfigMaterial # noqa +from . import solver # noqa +from . import util # noqa +from . import seeds # noqa +from . import grid_filters # noqa +from . import mechanics # noqa diff --git a/python/damask/_config.py b/python/damask/_config.py new file mode 100644 index 000000000..0e21286aa --- /dev/null +++ b/python/damask/_config.py @@ -0,0 +1,66 @@ +from io import StringIO +import abc + +import yaml +import numpy as np + +class NiceDumper(yaml.SafeDumper): + """Make YAML readable for humans.""" + + def write_line_break(self, data=None): + super().write_line_break(data) + + if len(self.indents) == 1: + super().write_line_break() + + def increase_indent(self, flow=False, indentless=False): + return super().increase_indent(flow, False) + + +class Config(dict): + """YAML-based configuration.""" + + def __repr__(self): + """Show as in file.""" + output = StringIO() + self.save(output) + output.seek(0) + return ''.join(output.readlines()) + + @classmethod + def load(cls,fname): + """Load from yaml file.""" + try: + fhandle = open(fname) + except TypeError: + fhandle = fname + return cls(yaml.safe_load(fhandle)) + + def save(self,fname='material.yaml'): + """ + Save to yaml file. + + Parameters + ---------- + fname : file, str, or pathlib.Path + Filename or file for reading. + + """ + try: + fhandle = open(fname,'w') + except TypeError: + fhandle = fname + fhandle.write(yaml.dump(dict(self),width=256,default_flow_style=None,Dumper=NiceDumper)) + + + @property + @abc.abstractmethod + def is_complete(self): + """Check for completeness.""" + pass + + @property + @abc.abstractmethod + def is_valid(self): + """Check for valid file layout.""" + pass diff --git a/python/damask/_material.py b/python/damask/_configmaterial.py similarity index 80% rename from python/damask/_material.py rename to python/damask/_configmaterial.py index 106d1582e..861e41464 100644 --- a/python/damask/_material.py +++ b/python/damask/_configmaterial.py @@ -1,61 +1,14 @@ -from io import StringIO import copy -import yaml import numpy as np +from . import Config from . import Lattice from . import Rotation -class NiceDumper(yaml.SafeDumper): - """Make YAML readable for humans.""" - - def write_line_break(self, data=None): - super().write_line_break(data) - - if len(self.indents) == 1: - super().write_line_break() - - def increase_indent(self, flow=False, indentless=False): - return super().increase_indent(flow, False) - - -class Material(dict): +class ConfigMaterial(Config): """Material configuration.""" - def __repr__(self): - """Show as in file.""" - output = StringIO() - self.save(output) - output.seek(0) - return ''.join(output.readlines()) - - @staticmethod - def load(fname): - """Load from yaml file.""" - try: - fhandle = open(fname) - except TypeError: - fhandle = fname - return Material(yaml.safe_load(fhandle)) - - def save(self,fname='material.yaml'): - """ - Save to yaml file. - - Parameters - ---------- - fname : file, str, or pathlib.Path - Filename or file for reading. - - """ - try: - fhandle = open(fname,'w') - except TypeError: - fhandle = fname - fhandle.write(yaml.dump(dict(self),width=256,default_flow_style=None,Dumper=NiceDumper)) - - @property def is_complete(self): """Check for completeness.""" diff --git a/python/tests/reference/Material/material.yaml b/python/tests/reference/ConfigMaterial/material.yaml similarity index 100% rename from python/tests/reference/Material/material.yaml rename to python/tests/reference/ConfigMaterial/material.yaml diff --git a/python/tests/test_Material.py b/python/tests/test_MaterialConfig.py similarity index 68% rename from python/tests/test_Material.py rename to python/tests/test_MaterialConfig.py index 567dfe646..1be07fe58 100644 --- a/python/tests/test_Material.py +++ b/python/tests/test_MaterialConfig.py @@ -2,60 +2,60 @@ import os import pytest -from damask import Material +from damask import ConfigMaterial @pytest.fixture def reference_dir(reference_dir_base): """Directory containing reference results.""" - return reference_dir_base/'Material' + return reference_dir_base/'ConfigMaterial' class TestMaterial: @pytest.mark.parametrize('fname',[None,'test.yaml']) def test_load_save(self,reference_dir,tmp_path,fname): - reference = Material.load(reference_dir/'material.yaml') + reference = ConfigMaterial.load(reference_dir/'material.yaml') os.chdir(tmp_path) if fname is None: reference.save() - new = Material.load('material.yaml') + new = ConfigMaterial.load('material.yaml') else: reference.save(fname) - new = Material.load(fname) + new = ConfigMaterial.load(fname) assert reference == new def test_valid_complete(self,reference_dir): - material_config = Material.load(reference_dir/'material.yaml') + material_config = ConfigMaterial.load(reference_dir/'material.yaml') assert material_config.is_valid and material_config.is_complete def test_invalid_lattice(self,reference_dir): - material_config = Material.load(reference_dir/'material.yaml') + material_config = ConfigMaterial.load(reference_dir/'material.yaml') material_config['phase']['Aluminum']['lattice']='fxc' assert not material_config.is_valid def test_invalid_orientation(self,reference_dir): - material_config = Material.load(reference_dir/'material.yaml') + material_config = ConfigMaterial.load(reference_dir/'material.yaml') material_config['microstructure'][0]['constituents'][0]['orientation']=[0,0,0,0] assert not material_config.is_valid def test_invalid_fraction(self,reference_dir): - material_config = Material.load(reference_dir/'material.yaml') + material_config = ConfigMaterial.load(reference_dir/'material.yaml') material_config['microstructure'][0]['constituents'][0]['fraction']=.9 assert not material_config.is_valid @pytest.mark.parametrize('item',['homogenization','phase','microstructure']) def test_incomplete_missing(self,reference_dir,item): - material_config = Material.load(reference_dir/'material.yaml') + material_config = ConfigMaterial.load(reference_dir/'material.yaml') del material_config[item] assert not material_config.is_complete def test_incomplete_wrong_phase(self,reference_dir): - material_config = Material.load(reference_dir/'material.yaml') + material_config = ConfigMaterial.load(reference_dir/'material.yaml') new = material_config.microstructure_rename_phase({'Steel':'FeNbC'}) assert not new.is_complete def test_incomplete_wrong_homogenization(self,reference_dir): - material_config = Material.load(reference_dir/'material.yaml') + material_config = ConfigMaterial.load(reference_dir/'material.yaml') new = material_config.microstructure_rename_homogenization({'Taylor':'isostrain'}) assert not new.is_complete