Пример #1
0
def check_dimension(typeattr, unit_id=None):
    """
        Check that the unit and dimension on a type attribute match.
        Alternatively, pass in a unit manually to check against the dimension
        of the type attribute
    """
    if unit_id is None:
        unit_id = typeattr.unit_id

    dimension_id = get_attr(typeattr.attr_id).dimension_id

    if unit_id is not None and dimension_id is None:
        # First error case
        unit_dimension_id = units.get_dimension_by_unit_id(unit_id).id
        unit = units.get_unit(unit_id)
        dimension = units.get_dimension(unit_dimension_id, do_accept_dimension_id_none=True)
        raise HydraError(f"Unit {unit_id} ({unit.abbreviation}) has dimension_id"+
                         f" {dimension.id}(name=dimension.name),"+
                         " but attribute has no dimension")
    elif unit_id is not None and dimension_id is not None:
        unit_dimension_id = units.get_dimension_by_unit_id(unit_id).id
        unit = units.get_unit(unit_id)
        dimension1 = units.get_dimension(unit_dimension_id, do_accept_dimension_id_none=True)
        dimension2 = units.get_dimension(unit_dimension_id, do_accept_dimension_id_none=True)
        if unit_dimension_id != dimension_id:
            # Only error case
            raise HydraError(f"Unit {unit_id} ({unit.abbreviation}) has dimension_id"+
                             f" {dimension1.id}(name=dimension1.name),"+
                             f" but attribute has id: {dimension2.id}({dimension2.name})")
Пример #2
0
def _make_attr_element(parent, attr_i):
    """
        create an attribute element from an attribute DB object
    """
    attr = etree.SubElement(parent, "attribute")

    attr_name = etree.SubElement(attr, 'name')
    attr_name.text = attr_i.name

    attr_desc = etree.SubElement(attr, 'description')
    attr_desc.text = attr_i.description

    attr_dimension = etree.SubElement(attr, 'dimension')
    attr_dimension.text = units.get_dimension(
        attr_i.dimension_id, do_accept_dimension_id_none=True).name

    return attr
Пример #3
0
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
Пример #4
0
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