Source code for gemseo.core.grammars.simple_grammar

# -*- coding: utf-8 -*-
# Copyright 2021 IRT Saint Exupéry, https://www.irt-saintexupery.com
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License version 3 as published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.

"""Most basic grammar implementation."""

import logging

from gemseo.core.grammars.abstract_grammar import AbstractGrammar
from gemseo.core.grammars.errors import InvalidDataException

LOGGER = logging.getLogger(__name__)


[docs]class SimpleGrammar(AbstractGrammar): """Store the data named and types.""" def __init__(self, name): """Constructor. :param name : grammar name """ super(SimpleGrammar, self).__init__(name) # Data names list self.data_names = [] # Data types list in the same order as self.data_names self.data_types = []
[docs] def load_data(self, data, raise_exception=True): """Loads the data dictionary in the grammar and checks it against self properties. :param data: the input data :param raise_exception: if False, no exception is raised when data is invalid (Default value = True) """ self.check(data, raise_exception) return data
[docs] def check(self, data, raise_exception=True): """Checks local data against self properties. :param raise_exception: if False, no exception is raised when data is invalid (Default value = True) """ failed = False if not isinstance(data, dict): failed = True LOGGER.error("Grammar data is not a dict, in %s", self.name) if raise_exception: raise InvalidDataException("Invalid data in " + str(self.name)) for data_type in self.data_types: if data_type is not None and not isinstance(data_type, type): msg = "Invalid data type in grammar {} , {} is not a type".format( self.name, data_type ) raise TypeError(msg) for data_type, data_name in zip(self.data_types, self.data_names): if data_name not in data: failed = True LOGGER.error("Missing input: %s in %s", data_name, self.name) elif not isinstance(data[data_name], data_type): failed = True LOGGER.error( "Wrong input type for: %s in %s got %s instead of %s", data_name, self.name, type(data[data_name]), data_type, ) if failed and raise_exception: raise InvalidDataException("Invalid data in " + str(self.name))
[docs] def initialize_from_base_dict(self, typical_data_dict): """Initialize the grammar with types and names from a typical data entry. :param typical_data_dict: a data dictionary """ self.data_names = [] self.data_types = [] for key, value in typical_data_dict.items(): self.data_names.append(key) self.data_types.append(type(value))
[docs] def get_data_names(self): """Returns the list of data names. :returns: the data names alphabetically sorted """ return self.data_names
[docs] def is_all_data_names_existing(self, data_names): """Checks if data_names are present in grammar. :param data_names: the data names list :returns: True if all data are in grammar """ for data_name in data_names: if not self.is_data_name_existing(data_name): return False return True
def _update_field(self, data_name, data_type): """Updates self properties with a new property of data_name,data_type Adds it if self has no property named data_name Updates self.data_types otherwise. :param data_name: the name of the property :param data_type: the type of the property """ if data_name in self.data_names: indx = self.data_names.index(data_name) self.data_names[indx] = data_name self.data_types[indx] = data_type else: self.data_names.append(data_name) self.data_types.append(data_type)
[docs] def get_type_of_data_named(self, data_name): """Gets the associated type to the data named data_name. :param data_name: the name of the property :returns: data type associated to data_name """ if not self.is_data_name_existing(data_name): raise ValueError("Unknown data named :" + str(data_name)) indx = self.data_names.index(data_name) return self.data_types[indx]
[docs] def update_from(self, input_grammar): """Adds properties coming from another grammar. :param input_grammar: the grammar to take inputs from """ if not isinstance(input_grammar, AbstractGrammar): msg = self._get_update_error_msg(self, input_grammar) raise TypeError(msg) input_grammar = input_grammar.to_simple_grammar() for g_name, g_type in zip(input_grammar.data_names, input_grammar.data_types): self._update_field(g_name, g_type)
[docs] def update_from_if_not_in(self, input_grammar, exclude_grammar): """Adds properties coming from input_grammar if they are not in exclude_grammar. :param input_grammar: the grammar to take inputs from :param exclude_grammar: exclusion grammar """ if not isinstance(input_grammar, AbstractGrammar) or not isinstance( exclude_grammar, AbstractGrammar ): msg = self._get_update_error_msg(self, input_grammar, exclude_grammar) raise TypeError(msg) input_grammar = input_grammar.to_simple_grammar() exclude_grammar = exclude_grammar.to_simple_grammar() for g_name, g_type in zip(input_grammar.data_names, input_grammar.data_types): if exclude_grammar.is_data_name_existing(g_name): ex_data_type = exclude_grammar.get_type_of_data_named(g_name) if g_type != ex_data_type: raise ValueError( "Inconsistent grammar update " + str(g_type) + " !=" + str(ex_data_type) ) else: self._update_field(g_name, g_type)
[docs] def is_data_name_existing(self, data_name): """Checks if data_name is present in grammar. :param data_name: the data name :returns: True if data is in grammar """ return data_name in self.data_names
[docs] def clear(self): """Clears the data to produce an empty grammar.""" self.data_names = [] self.data_types = []
[docs] def to_simple_grammar(self): """Converts to the base SimpleGrammar type. :returns: a SimpleGrammar instance equivalent to self """ return self