From a8a193033abf5f713b422dd937131dfc3fbed908 Mon Sep 17 00:00:00 2001 From: tuopuu Date: Thu, 13 Oct 2016 14:59:53 +0300 Subject: [PATCH 01/14] Serialise CUDS model with a Yaml script. --- simphony/io/serialisation.py | 291 ++++++++++++++++++++++++ simphony/io/tests/test_serialisation.py | 153 +++++++++++++ 2 files changed, 444 insertions(+) create mode 100644 simphony/io/serialisation.py create mode 100644 simphony/io/tests/test_serialisation.py diff --git a/simphony/io/serialisation.py b/simphony/io/serialisation.py new file mode 100644 index 00000000..e0634d6d --- /dev/null +++ b/simphony/io/serialisation.py @@ -0,0 +1,291 @@ +import yaml +import numpy + +from simphony.cuds.model import * +from simphony.core.data_container import DataContainer +from simphony.cuds.meta.cuds_component import CUDSComponent +from simphony.core.keywords import KEYWORDS +from simphony.cuds.meta import * +from simphony.core.cuba import CUBA +from collections import OrderedDict +from importlib import import_module +from simphony.cuds.meta.validation import to_camel_case + +_CUDSREFMAP = OrderedDict() + + +def save_CUDS(handle, model): + """ Save CUDS model to a Yaml file + + Parameters + ---------- + handle: file handle + Yaml file where CUDS model is saved. File will be cleared. + model: CUDS model + + """ + + handle.seek(0) + handle.truncate() + + handle.write('- NAME:') + if model.name: + handle.write(' "'+model.name+'"') + else: + handle.write(' Null') + handle.write('\n\n') + handle.write('- DESCRIPTION:') + if model.description: + handle.write(' "'+model.description+'"') + else: + handle.write(' Null') + handle.write('\n') + #handle.write('# COMPONENTS') + + # Construct a map of referenced objects + global _CUDSREFMAP + _CUDSREFMAP.clear() + for comp in model.iter(CUDSComponent): + # Add component to dictionary if it's not there already + if comp.uid not in _CUDSREFMAP.keys(): + _CUDSREFMAP[comp.uid] = [] + # Check if the component has CUDSComponents in data + for data in comp._data.values(): + # either directly, or + if isinstance(data, CUDSComponent): + if data.uid not in _CUDSREFMAP.keys(): + _CUDSREFMAP[data.uid] = [] + _CUDSREFMAP[data.uid] += [comp.uid] + # as an element of a list + if type(data) == list: + for elem in data: + if isinstance(elem, CUDSComponent): + if elem.uid not in _CUDSREFMAP.keys(): + _CUDSREFMAP[elem.uid] = [] + _CUDSREFMAP[elem.uid] += [comp.uid] + + # Save CUDSComponents + for comp in model.iter(CUDSComponent): + if _CUDSREFMAP[comp.uid] is not 'saved': + stream = '' + stream = _CUDSComponent_to_yaml(comp, stream) + handle.write(stream) + _CUDSREFMAP[comp.uid] = 'saved' + + +def load_CUDS(handle): + """ Load CUDS model from a Yaml file + + Parameters + ---------- + handle: file handle + yaml file containing CUDSComponents + + Raises + ------ + FileError + if yaml file contains errors + + Returns + ------- + model: CUDS + computational model + + """ + + comp_dict = {} + name = None + desc = None + for data in yaml.safe_load_all(handle): + # Go through the dictionaries constructed from the Yaml script + for dict_cuds in data: + cubatype = dict_cuds.keys()[0] + if cubatype == 'NAME': + name = dict_cuds['NAME'] + elif cubatype == 'DESCRIPTION': + desc = dict_cuds['DESCRIPTION'] + else: + _dict_to_CUDSComponent(cubatype, dict_cuds[cubatype], comp_dict) + + model = CUDS(name = name, description = desc) + for compid in comp_dict.keys(): + model.add(comp_dict[compid]) + + return model + + +def _CUDSComponent_to_yaml(comp, stream): + """ Convert CUDSComponent containing data to Yaml script + + Parameters + ---------- + comp: CUDSComponent + CUDSComponent that will be converted to Yaml + stream: str + A string to which new Yaml script is added + + Returns + ------- + str + A string containing Yaml script of the added CUDSComponent and it's + sub-components + + """ + + # Use global (at module level) dictionary for bookkeeping of the + # references and of the saved components + global _CUDSREFMAP + yaml_comp = '\n' + yaml_comp += '- ' + str(comp.cuba_key).replace('CUBA.', '') + ':' + + # Check if 'comp' is referenced by some other CUDSComponent in the model + # and create an alias if needed + if _CUDSREFMAP[comp.uid]: + refnum = _CUDSREFMAP.keys().index(comp.uid) + 1 + yaml_comp += ' &' + str(refnum) + yaml_comp += '\n' + + # Go through the keys in the component + cdata = comp._data + for key in cdata.keys(): + # Check if the data is a list or numpy types or CUDSComponents + if type(cdata[key]) == list: + # List of simple types? + if KEYWORDS[key._name_].dtype in [numpy.float64, + numpy.int32, bool]: + items = [] + for item in cdata[key]: + items.append(item.tolist()) + value = str(items) + + # List of CUDSComponents + else: + value = '[' + for item in cdata[key]: + if isinstance(item, CUDSComponent): + if len(value) > 1: + value += ', ' + # CUDSComponent will be referenced by a small int + # number in the Yaml script + refnum = _CUDSREFMAP.keys().index(item.uid) + 1 + value += '*' + str(refnum) + + # Check from _CUDSREFMAP dictionary if the object + # referenced is not already saved + if _CUDSREFMAP[item.uid] is not 'saved' or []: + _CUDSREFMAP[item.uid] = 'saved' + # Generate Yaml script for this component + stream = _CUDSComponent_to_yaml(item, stream) + value += ']' + + # Only one CUDSComponent? + elif isinstance(cdata[key], CUDSComponent): + refnum = _CUDSREFMAP.keys().index(cdata[key].uid) + 1 + value = '*' + str(refnum) + + # Use _CUDSREFMAP dictionary to mark already saved + # referenced objects + if _CUDSREFMAP[cdata[key].uid] is not 'saved' or []: + _CUDSREFMAP[cdata[key].uid] = 'saved' + # Generate Yaml script for this component + stream = _CUDSComponent_to_yaml(cdata[key], stream) + + # Any of the simple data types? + elif type(cdata[key]) == str: + value = '"' + str(cdata[key]) + '"' + elif type(cdata[key]) == numpy.ndarray: + value = str(cdata[key].tolist()) + elif cdata[key] is None: + value = None + else: + value = str(cdata[key]) + + # Write only key-value pairs where value is not None + if value: + yaml_comp += ' ' + str(key).replace('CUBA.', '') + \ + ': ' + value + '\n' + stream = stream + yaml_comp + return stream + + +def _dict_to_CUDSComponent(cubatype, comp, comp_dict = {}): + """ Generate a CUDSComponent on the basis of a dictionary + provided by PyYaml library. + + Parameters + ---------- + cubatype: str + CUBA key (name) of the CUDSComponent in the format use in Yaml file + comp: dict + Dictionary object containing the parameters of the component. + comp_dict: dict + Dictionary where constructed CUDSComponents are added + with a Python id as reference: key-value pairs are of the format + id(CUDSComponent): CUDSComponent + + """ + + # Check that comp does not refer to one of the components that + # have been already constructed + if id(comp) in comp_dict.keys(): + return + + if cubatype in KEYWORDS.keys(): + # Find corresponding module and instantiate the class + mod = import_module('simphony.cuds.meta.%s' % cubatype.lower()) + comp_class = getattr(mod, to_camel_case(cubatype)) + + # Must use (at least) two None parameters here, because currently + # there is no (easy) way to read required parameters for + # a class that is dynamically instantiated. A solution would be + # to define default values, e.g. 'None', for all parameters that + # do not have it defined yet. + comp_inst = comp_class(None, None) + + # Go through the keys and values in comp dictionary and + # add supported ones to data_dict + data_dict = {} + supp_params = [str(e).replace('CUBA.','') + for e in comp_inst.supported_parameters()] + for key in comp.keys(): + # Check if it is safe to eval the key + if key in supp_params: + cubakey = eval('CUBA.' + key) + + # Check if value contains other CUDSComponents or data + value = comp[key] + if type(value) is list: + tmp = [] + for subcomp in value: + if type(subcomp) is dict: + # Construct the subcomponent before it can be + # added to the host component + _dict_to_CUDSComponent(key, subcomp, comp_dict) + tmp.append(comp_dict[id(subcomp)]) + else: + #validation.validate_cuba_keyword(subcomp, key) + tmp.append(subcomp) + data_dict[cubakey] = tmp + elif type(value) is dict: + _dict_to_CUDSComponent(key, value, comp_dict) + else: + #validation.validate_cuba_keyword(value, key) + data_dict[cubakey] = value + else: + message = 'Unknown CUDSComponent "{}" as a subcomponent' + raise ValueError(message.format(key)) + + # CUDSComponent data setter overwrites + # existing data attribute with the contents of data_dict, + # and removes CUBA.NAME key if it doesn't exist in data_dict + if CUBA.NAME not in data_dict.keys(): + data_dict[CUBA.NAME] = None + # Add data to the constructed CUDSComponent + comp_inst.data = data_dict + else: + message = 'Unknown CUDSComponent "{}"' + raise ValueError(message.format(cubatype)) + + # Store component under the key representing it's memory location + # so that correct object references from the yaml file are preserved + comp_dict[id(comp)] = comp_inst diff --git a/simphony/io/tests/test_serialisation.py b/simphony/io/tests/test_serialisation.py new file mode 100644 index 00000000..e428459f --- /dev/null +++ b/simphony/io/tests/test_serialisation.py @@ -0,0 +1,153 @@ +""" + Testing module for CUDS serialization functions. +""" +import unittest +import os +from contextlib import closing +import tempfile +from numpy.testing import assert_array_equal + +from simphony.cuds.model import * +from simphony.core.data_container import DataContainer + +from simphony.cuds.meta.cuds_component import CUDSComponent + +import numpy +import string +import random +from simphony.core.keywords import KEYWORDS +from simphony.cuds.meta import * +from simphony.core.cuba import CUBA +from uuid import UUID +from simphony.io.serialization import * +from collections import OrderedDict +from importlib import import_module +from simphony.cuds.meta.validation import to_camel_case + + + +class TestSerialization(unittest.TestCase): + """Tests for CUDS Yaml serialization functions.""" + def setUp(self): + self.temp_dir = tempfile.mkdtemp() + + def tearDown(self): + shutil.rmtree(self.temp_dir) + + def test_save_CUDS_name(self): + name = 'somename' + filename = os.path.join(self.temp_dir, 'test_named.yml') + C = CUDS(name = name) + with closing(open(filename,'w')) as handle: + save_CUDS(handle, C) + + CC = None + with closing(open(filename,'r')) as handle: + CC = load_CUDS(handle) + + self.assertEqual(CC.name, name) + + def test_save_CUDS_description(self): + description = 'some very long description' + filename = os.path.join(self.temp_dir, 'test_description.yml') + C = CUDS(description = description) + with closing(open(filename,'w')) as handle: + save_CUDS(handle, C) + + with closing(open(filename,'r')) as handle: + CC = load_CUDS(handle) + + self.assertEqual(CC.description, description) + + def test_save_CUDS_empty(self): + filename = os.path.join(self.temp_dir, 'test_empty.yml') + C = CUDS(name = 'empty', description = 'just an empty model') + with closing(open(filename,'w')) as handle: + save_CUDS(handle, C) + + CC = None + with closing(open(filename,'r')) as handle: + CC = load_CUDS(handle) + + self.assertEqual(CC.name, C.name) + self.assertEqual(CC.description, C.description) + + for item in CC.iter(): + self.assertEqual(item, None) + + + def test_save_CUDS_full(self): + filename = os.path.join(self.temp_dir, 'test_full.yml') + C = CUDS(name = 'full', description = 'fully randomized model') + + for key in KEYWORDS.keys(): + if key not in ['VERSION']: + comp = self._create_random_CUDSComponent(key) + if comp: + C.add(comp) + + with closing(open(filename,'w')) as handle: + save_CUDS(handle, C) + + CC = None + with closing(open(filename,'r')) as handle: + CC = load_CUDS(handle) + + self.assertEqual(CC.name, C.name) + self.assertEqual(CC.description, C.description) + + for CCitem in CC.iter(): + Citem = C.get(CCitem.name) + self.assertEqual(Citem.name, CCitem.name) + + def _ran(self, dtype, shape): + if dtype == numpy.int32: + if shape == []: + shape = [1] + return numpy.random.randint(-9999999,9999999,size = shape) + elif dtype == numpy.float64: + if shape == [] or shape == None: + return numpy.random.rand(3) + elif len(shape) == 2: + return numpy.random.rand(shape[0],shape[1]) + elif len(shape) == 1: + if shape[0] == 1: + return numpy.random.rand(1)[0] + else: + return numpy.random.rand(shape[0]) + elif dtype == str: + return ''.join(random.choice(string.ascii_uppercase + + string.digits) for _ in range(shape[0])) + elif dtype == bool: + return random.choice([True, False]) + + def _create_random_CUDSComponent(self, key): + api = import_module('simphony.cuds.meta.api') + if to_camel_case(key) in dir(api): + mod = import_module('simphony.cuds.meta.%s' % key.lower()) + comp_class = getattr(mod, to_camel_case(key)) + + if issubclass(comp_class, CUDSComponent): + comp_inst = comp_class(None, None) + data_dict = {} + for prm in comp_inst.supported_parameters(): + if prm is not CUBA.UUID: + name = str(prm).replace('CUBA.','') + if to_camel_case(name) in dir(api): + # Create one or two subcomponents if supported + if numpy.random.randint(2): + subcomp1 = + self._create_random_CUDSComponent(name) + data_dict[prm] = subcomp1 + else: + subcomp1 = random_component(name) + subcomp2 = random_component(name) + data_dict[prm] = [subcomp1, subcomp2] + else: + dtype = KEYWORDS[name].dtype + shape = KEYWORDS[name].shape + val = self._ran(dtype, shape) + data_dict[prm] = val + comp_inst.data = data_dict + return comp_inst + return None From 899b67c81db5de5e48bb6f28191006ccb5b023c5 Mon Sep 17 00:00:00 2001 From: tuopuu Date: Thu, 13 Oct 2016 15:11:44 +0300 Subject: [PATCH 02/14] Pep8 fix. --- simphony/io/tests/test_serialisation.py | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/simphony/io/tests/test_serialisation.py b/simphony/io/tests/test_serialisation.py index e428459f..1a38026e 100644 --- a/simphony/io/tests/test_serialisation.py +++ b/simphony/io/tests/test_serialisation.py @@ -37,7 +37,7 @@ def tearDown(self): def test_save_CUDS_name(self): name = 'somename' filename = os.path.join(self.temp_dir, 'test_named.yml') - C = CUDS(name = name) + C = CUDS(name=name) with closing(open(filename,'w')) as handle: save_CUDS(handle, C) @@ -50,7 +50,7 @@ def test_save_CUDS_name(self): def test_save_CUDS_description(self): description = 'some very long description' filename = os.path.join(self.temp_dir, 'test_description.yml') - C = CUDS(description = description) + C = CUDS(description=description) with closing(open(filename,'w')) as handle: save_CUDS(handle, C) @@ -61,7 +61,7 @@ def test_save_CUDS_description(self): def test_save_CUDS_empty(self): filename = os.path.join(self.temp_dir, 'test_empty.yml') - C = CUDS(name = 'empty', description = 'just an empty model') + C = CUDS(name='empty', description='just an empty model') with closing(open(filename,'w')) as handle: save_CUDS(handle, C) @@ -78,7 +78,7 @@ def test_save_CUDS_empty(self): def test_save_CUDS_full(self): filename = os.path.join(self.temp_dir, 'test_full.yml') - C = CUDS(name = 'full', description = 'fully randomized model') + C = CUDS(name='full', description='fully randomized model') for key in KEYWORDS.keys(): if key not in ['VERSION']: @@ -86,11 +86,11 @@ def test_save_CUDS_full(self): if comp: C.add(comp) - with closing(open(filename,'w')) as handle: + with closing(open(filename, 'w')) as handle: save_CUDS(handle, C) CC = None - with closing(open(filename,'r')) as handle: + with closing(open(filename, 'r')) as handle: CC = load_CUDS(handle) self.assertEqual(CC.name, C.name) @@ -104,12 +104,12 @@ def _ran(self, dtype, shape): if dtype == numpy.int32: if shape == []: shape = [1] - return numpy.random.randint(-9999999,9999999,size = shape) + return numpy.random.randint(-9999999, 9999999, size=shape) elif dtype == numpy.float64: if shape == [] or shape == None: return numpy.random.rand(3) elif len(shape) == 2: - return numpy.random.rand(shape[0],shape[1]) + return numpy.random.rand(shape[0], shape[1]) elif len(shape) == 1: if shape[0] == 1: return numpy.random.rand(1)[0] @@ -117,7 +117,7 @@ def _ran(self, dtype, shape): return numpy.random.rand(shape[0]) elif dtype == str: return ''.join(random.choice(string.ascii_uppercase + - string.digits) for _ in range(shape[0])) + string.digits) for _ in range(shape[0])) elif dtype == bool: return random.choice([True, False]) @@ -132,12 +132,12 @@ def _create_random_CUDSComponent(self, key): data_dict = {} for prm in comp_inst.supported_parameters(): if prm is not CUBA.UUID: - name = str(prm).replace('CUBA.','') + name = str(prm).replace('CUBA.', '') if to_camel_case(name) in dir(api): # Create one or two subcomponents if supported if numpy.random.randint(2): - subcomp1 = - self._create_random_CUDSComponent(name) + subcomp1 + = self._create_random_CUDSComponent(name) data_dict[prm] = subcomp1 else: subcomp1 = random_component(name) From bd7d6db1cb26dc5cb623a1bce7845658bdff2df5 Mon Sep 17 00:00:00 2001 From: tuopuu Date: Thu, 13 Oct 2016 15:20:10 +0300 Subject: [PATCH 03/14] Pep8 fix. --- simphony/io/serialisation.py | 8 ++++---- simphony/io/tests/test_serialisation.py | 14 ++++---------- 2 files changed, 8 insertions(+), 14 deletions(-) diff --git a/simphony/io/serialisation.py b/simphony/io/serialisation.py index e0634d6d..3f9631e3 100644 --- a/simphony/io/serialisation.py +++ b/simphony/io/serialisation.py @@ -40,7 +40,6 @@ def save_CUDS(handle, model): else: handle.write(' Null') handle.write('\n') - #handle.write('# COMPONENTS') # Construct a map of referenced objects global _CUDSREFMAP @@ -105,7 +104,8 @@ def load_CUDS(handle): elif cubatype == 'DESCRIPTION': desc = dict_cuds['DESCRIPTION'] else: - _dict_to_CUDSComponent(cubatype, dict_cuds[cubatype], comp_dict) + _dict_to_CUDSComponent(cubatype, dict_cuds[cubatype], + comp_dict) model = CUDS(name = name, description = desc) for compid in comp_dict.keys(): @@ -263,13 +263,13 @@ def _dict_to_CUDSComponent(cubatype, comp, comp_dict = {}): _dict_to_CUDSComponent(key, subcomp, comp_dict) tmp.append(comp_dict[id(subcomp)]) else: - #validation.validate_cuba_keyword(subcomp, key) + # validation.validate_cuba_keyword(subcomp, key) tmp.append(subcomp) data_dict[cubakey] = tmp elif type(value) is dict: _dict_to_CUDSComponent(key, value, comp_dict) else: - #validation.validate_cuba_keyword(value, key) + # validation.validate_cuba_keyword(value, key) data_dict[cubakey] = value else: message = 'Unknown CUDSComponent "{}" as a subcomponent' diff --git a/simphony/io/tests/test_serialisation.py b/simphony/io/tests/test_serialisation.py index 1a38026e..524359aa 100644 --- a/simphony/io/tests/test_serialisation.py +++ b/simphony/io/tests/test_serialisation.py @@ -7,16 +7,12 @@ import tempfile from numpy.testing import assert_array_equal -from simphony.cuds.model import * -from simphony.core.data_container import DataContainer - from simphony.cuds.meta.cuds_component import CUDSComponent import numpy import string import random from simphony.core.keywords import KEYWORDS -from simphony.cuds.meta import * from simphony.core.cuba import CUBA from uuid import UUID from simphony.io.serialization import * @@ -25,7 +21,6 @@ from simphony.cuds.meta.validation import to_camel_case - class TestSerialization(unittest.TestCase): """Tests for CUDS Yaml serialization functions.""" def setUp(self): @@ -82,7 +77,7 @@ def test_save_CUDS_full(self): for key in KEYWORDS.keys(): if key not in ['VERSION']: - comp = self._create_random_CUDSComponent(key) + comp = self._create_random_comp(key) if comp: C.add(comp) @@ -106,7 +101,7 @@ def _ran(self, dtype, shape): shape = [1] return numpy.random.randint(-9999999, 9999999, size=shape) elif dtype == numpy.float64: - if shape == [] or shape == None: + if shape == [] or shape is None: return numpy.random.rand(3) elif len(shape) == 2: return numpy.random.rand(shape[0], shape[1]) @@ -121,7 +116,7 @@ def _ran(self, dtype, shape): elif dtype == bool: return random.choice([True, False]) - def _create_random_CUDSComponent(self, key): + def _create_random_comp(self, key): api = import_module('simphony.cuds.meta.api') if to_camel_case(key) in dir(api): mod = import_module('simphony.cuds.meta.%s' % key.lower()) @@ -136,8 +131,7 @@ def _create_random_CUDSComponent(self, key): if to_camel_case(name) in dir(api): # Create one or two subcomponents if supported if numpy.random.randint(2): - subcomp1 - = self._create_random_CUDSComponent(name) + subcomp1 = self._create_random_comp(name) data_dict[prm] = subcomp1 else: subcomp1 = random_component(name) From 6869677b6b322630c5a1113999aa040ed47db718 Mon Sep 17 00:00:00 2001 From: tuopuu Date: Thu, 13 Oct 2016 15:36:58 +0300 Subject: [PATCH 04/14] Pep8 fix. --- simphony/io/serialisation.py | 15 +++++------ simphony/io/tests/test_serialisation.py | 36 ++++++++++++------------- 2 files changed, 24 insertions(+), 27 deletions(-) diff --git a/simphony/io/serialisation.py b/simphony/io/serialisation.py index 3f9631e3..e6e06801 100644 --- a/simphony/io/serialisation.py +++ b/simphony/io/serialisation.py @@ -1,11 +1,10 @@ import yaml import numpy -from simphony.cuds.model import * -from simphony.core.data_container import DataContainer +from simphony.cuds.model import CUDS from simphony.cuds.meta.cuds_component import CUDSComponent from simphony.core.keywords import KEYWORDS -from simphony.cuds.meta import * +# from simphony.cuds.meta import * from simphony.core.cuba import CUBA from collections import OrderedDict from importlib import import_module @@ -107,7 +106,7 @@ def load_CUDS(handle): _dict_to_CUDSComponent(cubatype, dict_cuds[cubatype], comp_dict) - model = CUDS(name = name, description = desc) + model = CUDS(name=name, description=desc) for compid in comp_dict.keys(): model.add(comp_dict[compid]) @@ -152,7 +151,7 @@ def _CUDSComponent_to_yaml(comp, stream): if type(cdata[key]) == list: # List of simple types? if KEYWORDS[key._name_].dtype in [numpy.float64, - numpy.int32, bool]: + numpy.int32, bool]: items = [] for item in cdata[key]: items.append(item.tolist()) @@ -208,7 +207,7 @@ def _CUDSComponent_to_yaml(comp, stream): return stream -def _dict_to_CUDSComponent(cubatype, comp, comp_dict = {}): +def _dict_to_CUDSComponent(cubatype, comp, comp_dict={}): """ Generate a CUDSComponent on the basis of a dictionary provided by PyYaml library. @@ -245,8 +244,8 @@ def _dict_to_CUDSComponent(cubatype, comp, comp_dict = {}): # Go through the keys and values in comp dictionary and # add supported ones to data_dict data_dict = {} - supp_params = [str(e).replace('CUBA.','') - for e in comp_inst.supported_parameters()] + supp_params = [str(e).replace('CUBA.', '') + for e in comp_inst.supported_parameters()] for key in comp.keys(): # Check if it is safe to eval the key if key in supp_params: diff --git a/simphony/io/tests/test_serialisation.py b/simphony/io/tests/test_serialisation.py index 524359aa..a8d9bcbe 100644 --- a/simphony/io/tests/test_serialisation.py +++ b/simphony/io/tests/test_serialisation.py @@ -3,21 +3,19 @@ """ import unittest import os +import shutil from contextlib import closing import tempfile -from numpy.testing import assert_array_equal - -from simphony.cuds.meta.cuds_component import CUDSComponent - import numpy import string import random +from importlib import import_module + +from simphony.cuds.meta.cuds_component import CUDSComponent +from simphony.cuds.model import CUDS from simphony.core.keywords import KEYWORDS from simphony.core.cuba import CUBA -from uuid import UUID -from simphony.io.serialization import * -from collections import OrderedDict -from importlib import import_module +from simphony.io.serialisation import save_CUDS, load_CUDS from simphony.cuds.meta.validation import to_camel_case @@ -33,11 +31,11 @@ def test_save_CUDS_name(self): name = 'somename' filename = os.path.join(self.temp_dir, 'test_named.yml') C = CUDS(name=name) - with closing(open(filename,'w')) as handle: + with closing(open(filename, 'w')) as handle: save_CUDS(handle, C) CC = None - with closing(open(filename,'r')) as handle: + with closing(open(filename, 'r')) as handle: CC = load_CUDS(handle) self.assertEqual(CC.name, name) @@ -46,10 +44,10 @@ def test_save_CUDS_description(self): description = 'some very long description' filename = os.path.join(self.temp_dir, 'test_description.yml') C = CUDS(description=description) - with closing(open(filename,'w')) as handle: + with closing(open(filename, 'w')) as handle: save_CUDS(handle, C) - with closing(open(filename,'r')) as handle: + with closing(open(filename, 'r')) as handle: CC = load_CUDS(handle) self.assertEqual(CC.description, description) @@ -57,11 +55,11 @@ def test_save_CUDS_description(self): def test_save_CUDS_empty(self): filename = os.path.join(self.temp_dir, 'test_empty.yml') C = CUDS(name='empty', description='just an empty model') - with closing(open(filename,'w')) as handle: + with closing(open(filename, 'w')) as handle: save_CUDS(handle, C) CC = None - with closing(open(filename,'r')) as handle: + with closing(open(filename, 'r')) as handle: CC = load_CUDS(handle) self.assertEqual(CC.name, C.name) @@ -70,7 +68,6 @@ def test_save_CUDS_empty(self): for item in CC.iter(): self.assertEqual(item, None) - def test_save_CUDS_full(self): filename = os.path.join(self.temp_dir, 'test_full.yml') C = CUDS(name='full', description='fully randomized model') @@ -111,8 +108,9 @@ def _ran(self, dtype, shape): else: return numpy.random.rand(shape[0]) elif dtype == str: - return ''.join(random.choice(string.ascii_uppercase + - string.digits) for _ in range(shape[0])) + randstr = ''.join(random.choice(string.ascii_uppercase) + for _ in range(shape[0])) + return randstr elif dtype == bool: return random.choice([True, False]) @@ -134,8 +132,8 @@ def _create_random_comp(self, key): subcomp1 = self._create_random_comp(name) data_dict[prm] = subcomp1 else: - subcomp1 = random_component(name) - subcomp2 = random_component(name) + subcomp1 = self._create_random_comp(name) + subcomp2 = self._create_random_comp(name) data_dict[prm] = [subcomp1, subcomp2] else: dtype = KEYWORDS[name].dtype From 424c8e04f1612836ef3e5709df6153e7ee942f9f Mon Sep 17 00:00:00 2001 From: tuopuu Date: Fri, 14 Oct 2016 12:48:33 +0300 Subject: [PATCH 05/14] Fix faulty iteration syntax. --- simphony/io/tests/test_serialisation.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/simphony/io/tests/test_serialisation.py b/simphony/io/tests/test_serialisation.py index a8d9bcbe..39295f96 100644 --- a/simphony/io/tests/test_serialisation.py +++ b/simphony/io/tests/test_serialisation.py @@ -65,7 +65,7 @@ def test_save_CUDS_empty(self): self.assertEqual(CC.name, C.name) self.assertEqual(CC.description, C.description) - for item in CC.iter(): + for item in CC.iter(CUDSComponent): self.assertEqual(item, None) def test_save_CUDS_full(self): @@ -88,7 +88,7 @@ def test_save_CUDS_full(self): self.assertEqual(CC.name, C.name) self.assertEqual(CC.description, C.description) - for CCitem in CC.iter(): + for CCitem in CC.iter(CUDSComponent): Citem = C.get(CCitem.name) self.assertEqual(Citem.name, CCitem.name) From 13d64f35a34ac1bf525d11ffc1fb060c64837fbe Mon Sep 17 00:00:00 2001 From: tuopuu Date: Mon, 17 Oct 2016 10:07:28 +0300 Subject: [PATCH 06/14] Partial fix to saved/loaded CUDS comparison. --- simphony/io/tests/test_serialisation.py | 48 +++++++++++++------------ 1 file changed, 25 insertions(+), 23 deletions(-) diff --git a/simphony/io/tests/test_serialisation.py b/simphony/io/tests/test_serialisation.py index 39295f96..c98835f8 100644 --- a/simphony/io/tests/test_serialisation.py +++ b/simphony/io/tests/test_serialisation.py @@ -19,8 +19,8 @@ from simphony.cuds.meta.validation import to_camel_case -class TestSerialization(unittest.TestCase): - """Tests for CUDS Yaml serialization functions.""" +class TestSerialisation(unittest.TestCase): + """Tests for CUDS Yaml serialisation functions.""" def setUp(self): self.temp_dir = tempfile.mkdtemp() @@ -34,10 +34,8 @@ def test_save_CUDS_name(self): with closing(open(filename, 'w')) as handle: save_CUDS(handle, C) - CC = None with closing(open(filename, 'r')) as handle: CC = load_CUDS(handle) - self.assertEqual(CC.name, name) def test_save_CUDS_description(self): @@ -49,7 +47,6 @@ def test_save_CUDS_description(self): with closing(open(filename, 'r')) as handle: CC = load_CUDS(handle) - self.assertEqual(CC.description, description) def test_save_CUDS_empty(self): @@ -58,7 +55,6 @@ def test_save_CUDS_empty(self): with closing(open(filename, 'w')) as handle: save_CUDS(handle, C) - CC = None with closing(open(filename, 'r')) as handle: CC = load_CUDS(handle) @@ -81,16 +77,21 @@ def test_save_CUDS_full(self): with closing(open(filename, 'w')) as handle: save_CUDS(handle, C) - CC = None with closing(open(filename, 'r')) as handle: CC = load_CUDS(handle) self.assertEqual(CC.name, C.name) self.assertEqual(CC.description, C.description) - for CCitem in CC.iter(CUDSComponent): - Citem = C.get(CCitem.name) - self.assertEqual(Citem.name, CCitem.name) + # Iterate over components in the original model and check + # that they are present in the loaded model + for Citem in C.iter(CUDSComponent): + # Check items that have name parameter defined + if hasattr(CCitem, 'name'): + Citem = C.get(CCitem.name) + self.assertEqual(Citem.name, CCitem.name) + for key in CCitem.data: + self.assertEqual(Citem.data[key], CCitem.data[key]) def _ran(self, dtype, shape): if dtype == numpy.int32: @@ -126,20 +127,21 @@ def _create_random_comp(self, key): for prm in comp_inst.supported_parameters(): if prm is not CUBA.UUID: name = str(prm).replace('CUBA.', '') - if to_camel_case(name) in dir(api): - # Create one or two subcomponents if supported - if numpy.random.randint(2): - subcomp1 = self._create_random_comp(name) - data_dict[prm] = subcomp1 + if numpy.random.randint(2): + if to_camel_case(name) in dir(api): + # Create one or two subcomponents if supported + if numpy.random.randint(2): + subcomp1 = self._create_random_comp(name) + data_dict[prm] = subcomp1 + else: + subcomp1 = self._create_random_comp(name) + subcomp2 = self._create_random_comp(name) + data_dict[prm] = [subcomp1, subcomp2] else: - subcomp1 = self._create_random_comp(name) - subcomp2 = self._create_random_comp(name) - data_dict[prm] = [subcomp1, subcomp2] - else: - dtype = KEYWORDS[name].dtype - shape = KEYWORDS[name].shape - val = self._ran(dtype, shape) - data_dict[prm] = val + dtype = KEYWORDS[name].dtype + shape = KEYWORDS[name].shape + val = self._ran(dtype, shape) + data_dict[prm] = val comp_inst.data = data_dict return comp_inst return None From 1ef4a5aa51a2f7181e81cfbd24b1d9537b0ef9f5 Mon Sep 17 00:00:00 2001 From: tuopuu Date: Mon, 17 Oct 2016 10:13:30 +0300 Subject: [PATCH 07/14] Typo fix. --- simphony/io/tests/test_serialisation.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/simphony/io/tests/test_serialisation.py b/simphony/io/tests/test_serialisation.py index c98835f8..21f44557 100644 --- a/simphony/io/tests/test_serialisation.py +++ b/simphony/io/tests/test_serialisation.py @@ -87,10 +87,10 @@ def test_save_CUDS_full(self): # that they are present in the loaded model for Citem in C.iter(CUDSComponent): # Check items that have name parameter defined - if hasattr(CCitem, 'name'): - Citem = C.get(CCitem.name) - self.assertEqual(Citem.name, CCitem.name) - for key in CCitem.data: + if hasattr(Citem, 'name'): + CCitem = CC.get(Citem.name) + self.assertEqual(CCitem.name, Citem.name) + for key in Citem.data: self.assertEqual(Citem.data[key], CCitem.data[key]) def _ran(self, dtype, shape): From 8496be3c8e0278c8647d6fc80c788ebc2ab8781b Mon Sep 17 00:00:00 2001 From: tuopuu Date: Mon, 17 Oct 2016 11:26:01 +0300 Subject: [PATCH 08/14] Test fix. --- simphony/io/tests/test_serialisation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/simphony/io/tests/test_serialisation.py b/simphony/io/tests/test_serialisation.py index 21f44557..0395b7cc 100644 --- a/simphony/io/tests/test_serialisation.py +++ b/simphony/io/tests/test_serialisation.py @@ -87,7 +87,7 @@ def test_save_CUDS_full(self): # that they are present in the loaded model for Citem in C.iter(CUDSComponent): # Check items that have name parameter defined - if hasattr(Citem, 'name'): + if Citem.name is not None: CCitem = CC.get(Citem.name) self.assertEqual(CCitem.name, Citem.name) for key in Citem.data: From 60a787b6a3f56f3f6602406aed0602dca2e4fe7c Mon Sep 17 00:00:00 2001 From: tuopuu Date: Fri, 4 Nov 2016 16:44:28 +0200 Subject: [PATCH 09/14] Class initialisation change, and removed randomized model creation in the tests. --- simphony/io/serialisation.py | 51 ++++++++------- simphony/io/tests/test_serialisation.py | 83 ++++++------------------- 2 files changed, 50 insertions(+), 84 deletions(-) diff --git a/simphony/io/serialisation.py b/simphony/io/serialisation.py index e6e06801..686c8fcc 100644 --- a/simphony/io/serialisation.py +++ b/simphony/io/serialisation.py @@ -233,24 +233,20 @@ def _dict_to_CUDSComponent(cubatype, comp, comp_dict={}): # Find corresponding module and instantiate the class mod = import_module('simphony.cuds.meta.%s' % cubatype.lower()) comp_class = getattr(mod, to_camel_case(cubatype)) - - # Must use (at least) two None parameters here, because currently - # there is no (easy) way to read required parameters for - # a class that is dynamically instantiated. A solution would be - # to define default values, e.g. 'None', for all parameters that - # do not have it defined yet. - comp_inst = comp_class(None, None) + # Get parameter names for __init__ method + init_params = comp_class.__init__.func_code.co_varnames # Go through the keys and values in comp dictionary and # add supported ones to data_dict - data_dict = {} + init_kwargs = {} + system_managed_keys = {} supp_params = [str(e).replace('CUBA.', '') - for e in comp_inst.supported_parameters()] + for e in comp_class.supported_parameters()] + # Don't accept UUID entry from the yaml file + supp_params.remove('UUID') for key in comp.keys(): - # Check if it is safe to eval the key + # Check if the key is supported if key in supp_params: - cubakey = eval('CUBA.' + key) - # Check if value contains other CUDSComponents or data value = comp[key] if type(value) is list: @@ -264,23 +260,36 @@ def _dict_to_CUDSComponent(cubatype, comp, comp_dict={}): else: # validation.validate_cuba_keyword(subcomp, key) tmp.append(subcomp) - data_dict[cubakey] = tmp + if key.lower() in init_params: + init_kwargs[key.lower()] = tmp + else: + cubaname = eval('CUBA.' + key) + system_managed_keys[cubaname] = tmp elif type(value) is dict: _dict_to_CUDSComponent(key, value, comp_dict) + tmp = value else: # validation.validate_cuba_keyword(value, key) - data_dict[cubakey] = value + tmp = value + + if key.lower() in init_params: + init_kwargs[key.lower()] = tmp + else: + cubaname = eval('CUBA.' + key) + system_managed_keys[cubaname] = tmp + else: message = 'Unknown CUDSComponent "{}" as a subcomponent' raise ValueError(message.format(key)) - # CUDSComponent data setter overwrites - # existing data attribute with the contents of data_dict, - # and removes CUBA.NAME key if it doesn't exist in data_dict - if CUBA.NAME not in data_dict.keys(): - data_dict[CUBA.NAME] = None - # Add data to the constructed CUDSComponent - comp_inst.data = data_dict + #if 'name' not in init_kwargs.keys(): + # init_kwargs['name'] = None + # Instantiate component with its subcomponents + comp_inst = comp_class(**init_kwargs) + # Add system managed components by updating the DataContainer + data = comp_inst.data + data.update(system_managed_keys) + comp_inst.data = data else: message = 'Unknown CUDSComponent "{}"' raise ValueError(message.format(cubatype)) diff --git a/simphony/io/tests/test_serialisation.py b/simphony/io/tests/test_serialisation.py index 0395b7cc..d93301ef 100644 --- a/simphony/io/tests/test_serialisation.py +++ b/simphony/io/tests/test_serialisation.py @@ -17,7 +17,7 @@ from simphony.core.cuba import CUBA from simphony.io.serialisation import save_CUDS, load_CUDS from simphony.cuds.meta.validation import to_camel_case - +from simphony.cuds.meta import api class TestSerialisation(unittest.TestCase): """Tests for CUDS Yaml serialisation functions.""" @@ -64,15 +64,24 @@ def test_save_CUDS_empty(self): for item in CC.iter(CUDSComponent): self.assertEqual(item, None) - def test_save_CUDS_full(self): + def test_save_CUDS_complicated_data(self): filename = os.path.join(self.temp_dir, 'test_full.yml') - C = CUDS(name='full', description='fully randomized model') - - for key in KEYWORDS.keys(): - if key not in ['VERSION']: - comp = self._create_random_comp(key) - if comp: - C.add(comp) + C = CUDS(name='full', + description='model with crossreferenced components') + + M1 = Material(name = 'steel', + description = 'FCC steel sphere structure') + M2 = Material(name = 'epoxy', description = '') + M3 = Material(name = 'iron', description = 'sheet metal container') + MR1 = MaterialRelation(name = 'steel spheres in epoxy', + material = [M1,M2]) + MR2 = MaterialRelation(name = 'epoxy in sheet metal container', + material = [M2,M3]) + # M1 is not added + C.add(M2) + C.add(M3) + C.add(MR1) + C.add(MR2) with closing(open(filename, 'w')) as handle: save_CUDS(handle, C) @@ -84,7 +93,8 @@ def test_save_CUDS_full(self): self.assertEqual(CC.description, C.description) # Iterate over components in the original model and check - # that they are present in the loaded model + # that they are present in the loaded model. Loaded model + # has additionally material 'M1' included. for Citem in C.iter(CUDSComponent): # Check items that have name parameter defined if Citem.name is not None: @@ -92,56 +102,3 @@ def test_save_CUDS_full(self): self.assertEqual(CCitem.name, Citem.name) for key in Citem.data: self.assertEqual(Citem.data[key], CCitem.data[key]) - - def _ran(self, dtype, shape): - if dtype == numpy.int32: - if shape == []: - shape = [1] - return numpy.random.randint(-9999999, 9999999, size=shape) - elif dtype == numpy.float64: - if shape == [] or shape is None: - return numpy.random.rand(3) - elif len(shape) == 2: - return numpy.random.rand(shape[0], shape[1]) - elif len(shape) == 1: - if shape[0] == 1: - return numpy.random.rand(1)[0] - else: - return numpy.random.rand(shape[0]) - elif dtype == str: - randstr = ''.join(random.choice(string.ascii_uppercase) - for _ in range(shape[0])) - return randstr - elif dtype == bool: - return random.choice([True, False]) - - def _create_random_comp(self, key): - api = import_module('simphony.cuds.meta.api') - if to_camel_case(key) in dir(api): - mod = import_module('simphony.cuds.meta.%s' % key.lower()) - comp_class = getattr(mod, to_camel_case(key)) - - if issubclass(comp_class, CUDSComponent): - comp_inst = comp_class(None, None) - data_dict = {} - for prm in comp_inst.supported_parameters(): - if prm is not CUBA.UUID: - name = str(prm).replace('CUBA.', '') - if numpy.random.randint(2): - if to_camel_case(name) in dir(api): - # Create one or two subcomponents if supported - if numpy.random.randint(2): - subcomp1 = self._create_random_comp(name) - data_dict[prm] = subcomp1 - else: - subcomp1 = self._create_random_comp(name) - subcomp2 = self._create_random_comp(name) - data_dict[prm] = [subcomp1, subcomp2] - else: - dtype = KEYWORDS[name].dtype - shape = KEYWORDS[name].shape - val = self._ran(dtype, shape) - data_dict[prm] = val - comp_inst.data = data_dict - return comp_inst - return None From b3443dbc753755d8a5a0951280c2961572c9e595 Mon Sep 17 00:00:00 2001 From: tuopuu Date: Fri, 4 Nov 2016 16:55:03 +0200 Subject: [PATCH 10/14] Flakes fix. --- simphony/io/serialisation.py | 6 ++---- simphony/io/tests/test_serialisation.py | 24 ++++++++++-------------- 2 files changed, 12 insertions(+), 18 deletions(-) diff --git a/simphony/io/serialisation.py b/simphony/io/serialisation.py index 686c8fcc..c18be6e3 100644 --- a/simphony/io/serialisation.py +++ b/simphony/io/serialisation.py @@ -263,7 +263,7 @@ def _dict_to_CUDSComponent(cubatype, comp, comp_dict={}): if key.lower() in init_params: init_kwargs[key.lower()] = tmp else: - cubaname = eval('CUBA.' + key) + cubaname = CUBA[key] system_managed_keys[cubaname] = tmp elif type(value) is dict: _dict_to_CUDSComponent(key, value, comp_dict) @@ -275,15 +275,13 @@ def _dict_to_CUDSComponent(cubatype, comp, comp_dict={}): if key.lower() in init_params: init_kwargs[key.lower()] = tmp else: - cubaname = eval('CUBA.' + key) + cubaname = CUBA[key] system_managed_keys[cubaname] = tmp else: message = 'Unknown CUDSComponent "{}" as a subcomponent' raise ValueError(message.format(key)) - #if 'name' not in init_kwargs.keys(): - # init_kwargs['name'] = None # Instantiate component with its subcomponents comp_inst = comp_class(**init_kwargs) # Add system managed components by updating the DataContainer diff --git a/simphony/io/tests/test_serialisation.py b/simphony/io/tests/test_serialisation.py index d93301ef..9b426a39 100644 --- a/simphony/io/tests/test_serialisation.py +++ b/simphony/io/tests/test_serialisation.py @@ -6,18 +6,14 @@ import shutil from contextlib import closing import tempfile -import numpy -import string -import random -from importlib import import_module from simphony.cuds.meta.cuds_component import CUDSComponent +from simphony.cuds.meta.material import Material +from simphony.cuds.meta.material_relation import MaterialRelation from simphony.cuds.model import CUDS from simphony.core.keywords import KEYWORDS from simphony.core.cuba import CUBA from simphony.io.serialisation import save_CUDS, load_CUDS -from simphony.cuds.meta.validation import to_camel_case -from simphony.cuds.meta import api class TestSerialisation(unittest.TestCase): """Tests for CUDS Yaml serialisation functions.""" @@ -69,14 +65,14 @@ def test_save_CUDS_complicated_data(self): C = CUDS(name='full', description='model with crossreferenced components') - M1 = Material(name = 'steel', - description = 'FCC steel sphere structure') - M2 = Material(name = 'epoxy', description = '') - M3 = Material(name = 'iron', description = 'sheet metal container') - MR1 = MaterialRelation(name = 'steel spheres in epoxy', - material = [M1,M2]) - MR2 = MaterialRelation(name = 'epoxy in sheet metal container', - material = [M2,M3]) + M1 = Material(name='steel', + description='FCC steel sphere structure') + M2 = Material(name='epoxy', description='') + M3 = Material(name='iron', description='sheet metal container') + MR1 = MaterialRelation(name='steel spheres in epoxy', + material=[M1, M2]) + MR2 = MaterialRelation(name='epoxy in sheet metal container', + material=[M2, M3]) # M1 is not added C.add(M2) C.add(M3) From bb0f2cc1255a1bce47e3b71d4294f49c00fade7b Mon Sep 17 00:00:00 2001 From: tuopuu Date: Fri, 4 Nov 2016 16:58:47 +0200 Subject: [PATCH 11/14] Pep8 fix. --- simphony/io/tests/test_serialisation.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/simphony/io/tests/test_serialisation.py b/simphony/io/tests/test_serialisation.py index 9b426a39..f09682dc 100644 --- a/simphony/io/tests/test_serialisation.py +++ b/simphony/io/tests/test_serialisation.py @@ -11,10 +11,9 @@ from simphony.cuds.meta.material import Material from simphony.cuds.meta.material_relation import MaterialRelation from simphony.cuds.model import CUDS -from simphony.core.keywords import KEYWORDS -from simphony.core.cuba import CUBA from simphony.io.serialisation import save_CUDS, load_CUDS + class TestSerialisation(unittest.TestCase): """Tests for CUDS Yaml serialisation functions.""" def setUp(self): From f81b3ded70abd601ef153d9921598c4742c5153f Mon Sep 17 00:00:00 2001 From: tuopuu Date: Sat, 5 Nov 2016 13:13:39 +0200 Subject: [PATCH 12/14] Add compare components to test_serialisation.py --- simphony/io/tests/test_serialisation.py | 28 ++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/simphony/io/tests/test_serialisation.py b/simphony/io/tests/test_serialisation.py index f09682dc..daa6087e 100644 --- a/simphony/io/tests/test_serialisation.py +++ b/simphony/io/tests/test_serialisation.py @@ -94,6 +94,28 @@ def test_save_CUDS_complicated_data(self): # Check items that have name parameter defined if Citem.name is not None: CCitem = CC.get(Citem.name) - self.assertEqual(CCitem.name, Citem.name) - for key in Citem.data: - self.assertEqual(Citem.data[key], CCitem.data[key]) + for key in Citem.data.keys(): + Ci = Citem.data[key] + CCi = CCitem.data[key] + _compare_components(Ci, CCi, testcase=self) + +def _compare_components(comp1, comp2, testcase): + self = testcase + if type(comp1) == list: + for i in xrange(len(comp1)): + if isinstance(comp1[i], CUDSComponent) + _compare_components(comp1[i], comp2[i], self) + else: + self.assertEqual(comp1[i], comp2[i]) + elif isinstance(comp1, CUDSComponent): + for key, value in comp1.data: + if type(value) == list: + for i in xrange(len(value)): + if isinstance(value[i], CUDSComponent) + _compare_components(value[i], comp2.data[key][i], + self) + else: + self.assertEqual(value[i], comp2.data[key][i]) + self.assertEqual(value, comp2.data[key]) + else: + self.assertEqual(comp1, comp2) From a575ba5a51b4b481e2d2b7d566307ba57cf22165 Mon Sep 17 00:00:00 2001 From: tuopuu Date: Sat, 5 Nov 2016 13:16:08 +0200 Subject: [PATCH 13/14] Fix syntax. --- simphony/io/tests/test_serialisation.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/simphony/io/tests/test_serialisation.py b/simphony/io/tests/test_serialisation.py index daa6087e..d9fdf318 100644 --- a/simphony/io/tests/test_serialisation.py +++ b/simphony/io/tests/test_serialisation.py @@ -99,11 +99,12 @@ def test_save_CUDS_complicated_data(self): CCi = CCitem.data[key] _compare_components(Ci, CCi, testcase=self) + def _compare_components(comp1, comp2, testcase): self = testcase if type(comp1) == list: for i in xrange(len(comp1)): - if isinstance(comp1[i], CUDSComponent) + if isinstance(comp1[i], CUDSComponent): _compare_components(comp1[i], comp2[i], self) else: self.assertEqual(comp1[i], comp2[i]) @@ -111,7 +112,7 @@ def _compare_components(comp1, comp2, testcase): for key, value in comp1.data: if type(value) == list: for i in xrange(len(value)): - if isinstance(value[i], CUDSComponent) + if isinstance(value[i], CUDSComponent): _compare_components(value[i], comp2.data[key][i], self) else: From aacbaa718b77bc4b2407ff1c6ad9ea1bf44b10dd Mon Sep 17 00:00:00 2001 From: tuopuu Date: Mon, 7 Nov 2016 10:45:50 +0200 Subject: [PATCH 14/14] Iteration fix. --- simphony/io/tests/test_serialisation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/simphony/io/tests/test_serialisation.py b/simphony/io/tests/test_serialisation.py index d9fdf318..e880da25 100644 --- a/simphony/io/tests/test_serialisation.py +++ b/simphony/io/tests/test_serialisation.py @@ -109,7 +109,7 @@ def _compare_components(comp1, comp2, testcase): else: self.assertEqual(comp1[i], comp2[i]) elif isinstance(comp1, CUDSComponent): - for key, value in comp1.data: + for key, value in comp1.data.iteritems(): if type(value) == list: for i in xrange(len(value)): if isinstance(value[i], CUDSComponent):