def add_child_typeattr(parent_id, child_template_id, **kwargs): """ Add template and a type and typeattrs. """ #does this child already exist in this template? existing_child_typeattr = db.DBSession.query(TypeAttr).join( TemplateType).filter(TypeAttr.parent_id == parent_id).filter( TemplateType.template_id == child_template_id).first() if existing_child_typeattr is not None: return existing_child_typeattr parent_typeattr = db.DBSession.query(TypeAttr)\ .filter(TypeAttr.id == parent_id).one() child_type = add_child_templatetype(parent_typeattr.type_id, child_template_id) child_typeattr_i = TypeAttr() child_typeattr_i.attr_id = parent_typeattr.attr_id child_typeattr_i.type_id = child_type.id child_typeattr_i.parent_id = parent_id db.DBSession.add(child_typeattr_i) db.DBSession.flush() return child_typeattr_i
def _set_typeattr(typeattr, existing_ta=None, check_dimensions=True): """ Add or update a type attribute. If an existing type attribute is provided, then update. Checks are performed to ensure that the dimension provided on the type attr (not updateable) is the same as that on the referring attribute. The unit provided (stored on tattr) must conform to the dimension stored on the referring attribute (stored on tattr). This is done so that multiple templates can all use the same attribute, but specify different units. If no attr_id is provided, but an attr_name and dimension are provided, then a new attribute can be created (or retrieved) and used. I.e., no attribute ID must be specified if attr_name and dimension are specified. ***WARNING*** Setting ID to null means a new type attribute (and even a new attr) may be added, None are removed or replaced. To remove other type attrs, do it manually using delete_typeattr """ if existing_ta is None: #check for an existing TA check_existing_ta = None if typeattr.attr_id and typeattr.type_id: check_existing_ta = db.DBSession.query(TypeAttr)\ .filter(TypeAttr.attr_id == typeattr.attr_id, TypeAttr.type_id == typeattr.type_id).first() #There's already a TA with this attr_id in this type if check_existing_ta is not None: ta = check_existing_ta else: ta = TypeAttr(attr_id=typeattr.attr_id) ## default new type attrs to 'active'. ##This has replaced the database default because for child typeattrs, ##we need the status to be NULL so it can inherit from its parent ta.status = 'A' else: if typeattr.id is not None: ta = db.DBSession.query(TypeAttr).filter( TypeAttr.id == typeattr.id).one() else: ta = existing_ta ta.attr_id = typeattr.attr_id ta.unit_id = typeattr.unit_id ta.type_id = typeattr.type_id ta.data_type = typeattr.data_type ta.status = typeattr.status if typeattr.status is not None else 'A' if hasattr( typeattr, 'default_dataset_id') and typeattr.default_dataset_id is not None: ta.default_dataset_id = typeattr.default_dataset_id ta.description = typeattr.description ta.properties = typeattr.get_properties() #support legacy use of 'is_var' instead of 'attr_is_var' if hasattr(typeattr, 'is_var') and typeattr.is_var is not None: typeattr.attr_is_var = typeattr.is_var ta.attr_is_var = typeattr.attr_is_var if typeattr.attr_is_var is not None else 'N' ta.data_restriction = _parse_data_restriction(typeattr.data_restriction) if typeattr.unit_id is None or typeattr.unit_id == '': # All right. Check passed ta.unit_id = None pass else: unit = units.get_unit(typeattr.unit_id) dimension = units.get_dimension(unit.dimension_id) if typeattr.attr_id is not None and typeattr.attr_id > 0 and check_dimensions: # Getting the passed attribute, so we need to check consistency # between attr dimension id and typeattr dimension id attr = db.DBSession.query(Attr).filter( Attr.id == ta.attr_id).first() if attr is not None and attr.dimension_id is not None and\ attr.dimension_id != dimension.id or \ attr is not None and attr.dimension_id is None: attr_dimension = units.get_dimension(attr.dimension_id) # In this case there is an inconsistency between # attr.dimension_id and typeattr.unit_id raise HydraError( "Unit mismatch between type and attirbute." + f"Type attribute for {attr.name} specifies " + f"unit {unit.name}, dimension {dimension.name}." + f"The attribute specifies a dimension of {attr_dimension.name}" + "Cannot set a unit on a type attribute which " + "does not match its attribute.") elif typeattr.attr_id is None and typeattr.name is not None: # Getting/creating the attribute by typeattr dimension id and typeattr name # In this case the dimension_id "null"/"not null" status is ininfluent attr = get_attr_by_name_and_dimension(typeattr.name, dimension.id) ta.attr_id = attr.id ta.attr = attr if check_dimensions: check_dimension(ta) if existing_ta is None: log.debug("Adding ta to DB") db.DBSession.add(ta) if not hasattr(ta, 'attr'): attr = db.DBSession.query(Attr).filter(Attr.id == ta.attr_id).one() ta.attr = attr return ta
def parse_json_typeattr(type_i, typeattr_j, attribute_j, default_dataset_j, user_id=None): dimension_i = None if attribute_j.dimension_id is not None: # The dimension_id of the attribute is not None dimension_i = units.get_dimension(attribute_j.dimension_id) elif attribute_j.dimension is not None: # The dimension name of the attribute is not None dimension_name = attribute_j.dimension.strip() if dimension_name.lower() in ('dimensionless', ''): dimension_name = 'dimensionless' dimension_i = units.get_dimension_by_name(dimension_name.strip()) elif attribute_j.unit_id is not None: # The unit_id of the attribute is not None dimension_i = units.get_dimension_by_unit_id(attribute_j.unit_id) elif attribute_j.unit not in ('', None): # The unit of the attribute is not None attribute_unit_id = units.get_unit_by_abbreviation(attribute_j.unit).id attribute_j.unit_id = attribute_unit_id dimension_i = units.get_dimension_by_unit_id(attribute_j.unit_id) attribute_name = attribute_j.name.strip() if dimension_i is None: # In this case we must get the attr with dimension id not set attr_i = get_attr_by_name_and_dimension(attribute_name, None) else: attr_i = get_attr_by_name_and_dimension(attribute_name, dimension_i.id) #Get an ID for the attribute db.DBSession.flush() for ta in type_i.typeattrs: if ta.attr_id == attr_i.id: typeattr_i = ta break else: typeattr_i = TypeAttr() log.debug("Creating type attr: type_id=%s, attr_id=%s", type_i.id, attr_i.id) typeattr_i.type_id = type_i.id typeattr_i.attr_id = attr_i.id typeattr_i.attr_is_var = typeattr_j.attr_is_var typeattr_i.attr = attr_i typeattr_i.status = 'A' type_i.typeattrs.append(typeattr_i) db.DBSession.add(typeattr_i) unit_id = None if attribute_j.unit_id is not None: typeattr_i.unit_id = typeattr_j.unit_id check_dimension(typeattr_i) if typeattr_j.description is not None: typeattr_i.description = typeattr_j.description if typeattr_j.properties is not None: if isinstance(typeattr_j.properties, dict): typeattr_i.properties = json.dumps(typeattr_j.properties) else: typeattr_i.properties = typeattr_j.properties if typeattr_j.is_var is not None: typeattr_i.attr_is_var = typeattr_j.is_var if typeattr_j.data_type is not None: typeattr_i.data_type = typeattr_j.data_type if default_dataset_j is not None: default = default_dataset_j unit = default.unit unit_id = None if unit not in (None, ''): unit_id = units.get_unit_by_abbreviation(unit).id if unit_id is None and typeattr_i.unit_id is not None: unit_id = typeattr_i.unit_id if unit_id is not None: check_dimension(typeattr_i, unit_id) if unit_id is not None and typeattr_i.unit_id is not None: if unit_id != typeattr_i.unit_id: raise HydraError( "Default value has a unit of %s but the attribute" " says the unit should be: %s" % (typeattr_i.unit_id, unit_id)) val = default.value data_type = default.type name = default.name if default.name not in ( None, '') else "%s Default" % attr_i.name dataset_i = add_dataset(data_type, val, unit_id, name=name, user_id=user_id) typeattr_i.default_dataset_id = dataset_i.id if typeattr_j.restriction is not None or typeattr_j.data_restriction is not None: restriction = typeattr_j.restriction if typeattr_j.restriction is not None else typeattr_j.data_restriction if isinstance(restriction, dict): typeattr_i.data_restriction = json.dumps(restriction) else: typeattr_i.data_restriction = restriction else: typeattr_i.data_restriction = None return typeattr_i
def _parse_xml_typeattr(type_i, attribute, user_id=None): """ convert a typeattr etree element and turn it into a hydra type attr """ attr = _parse_xml_attribute(attribute) for ta in type_i.typeattrs: if ta.attr_id == attr.id: # Find the TypeAttr typeattr_i = ta break else: # Creating a new TypeAttr typeattr_i = TypeAttr() log.debug("Creating type attr: type_id=%s, attr_id=%s", type_i.id, attr.id) typeattr_i.type_id = type_i.id typeattr_i.attr_id = attr.id type_i.typeattrs.append(typeattr_i) db.DBSession.add(typeattr_i) typeattr_unit_id = None if attribute.find('unit') is not None: # Found the unit as child at first level unit = attribute.find('unit').text if unit not in ('', None): typeattr_unit_id = units.get_unit_by_abbreviation(unit).id if typeattr_unit_id is not None: typeattr_i.unit_id = typeattr_unit_id check_dimension(typeattr_i) if attribute.find('description') is not None: typeattr_i.description = attribute.find('description').text if attribute.find('properties') is not None: properties_string = get_etree_layout_as_dict( attribute.find('properties')) typeattr_i.properties = str(properties_string) if attribute.find('is_var') is not None: typeattr_i.attr_is_var = attribute.find('is_var').text if attribute.find('data_type') is not None: typeattr_i.data_type = attribute.find('data_type').text # Analyzing the "default" node if attribute.find('default') is not None: default = attribute.find('default') dataset_unit_id = None if default.find('unit') is not None: dataset_unit = default.find('unit').text if dataset_unit not in ('', None): dataset_unit_id = units.get_unit_by_abbreviation( dataset_unit).id if dataset_unit_id is None and typeattr_i.unit_id is not None: dataset_unit = typeattr_i.unit_id if dataset_unit_id is not None and typeattr_i.unit_id is not None: if dataset_unit_id != typeattr_i.unit_id: raise HydraError( f"Default value has a unit of {typeattr_i.unit_id}" + "but the attribute" + f" says the unit should be: {dataset_unit_id}") val = default.find('value').text try: Decimal(val) data_type = 'scalar' except: data_type = 'descriptor' dataset = add_dataset(data_type, val, dataset_unit_id, name="%s Default" % attr.name, user_id=user_id) typeattr_i.default_dataset_id = dataset.id if attribute.find('restrictions') is not None: restriction = str( dataset_util.get_restriction_as_dict( attribute.find('restrictions'))) typeattr_i.data_restriction = restriction else: typeattr_i.data_restriction = None return typeattr_i