示例#1
0
def _check_unit_consistency(actual_unit, wanted_unit, column):
    if actual_unit and wanted_unit is None:
        raise util.TableDefinitionError(
            f"Trying to convert from one unit to another, "
            f"but source unit not specified (in column {column.title})")
    elif wanted_unit != actual_unit:
        raise util.TableDefinitionError(
            f"Source value of different unit than specified source unit: "
            f"{actual_unit} and {wanted_unit} (in column {column.title})")
示例#2
0
def _check_unit_consistency(actual_unit, wanted_unit, column):
    if actual_unit and wanted_unit is None:
        raise util.TableDefinitionError(
            "Trying to convert from one unit to another, but source unit not specified"
            " (in column {})".format(column.title))
    elif wanted_unit != actual_unit:
        raise util.TableDefinitionError(
            "Source value of different unit than specified source unit: " +
            "{} and {}"
            " (in column {})".format(actual_unit, wanted_unit, column.title))
示例#3
0
    def __init__(self,
                 title,
                 pattern,
                 num_of_digits,
                 href,
                 col_type=None,
                 unit=None,
                 source_unit=None,
                 scale_factor=None,
                 relevant_for_diff=None,
                 display_title=None):

        # If scaling on the variables is performed, a display unit must be defined, explicitly
        if scale_factor is not None and scale_factor != 1 and unit is None:
            raise util.TableDefinitionError(
                "Scale factor is defined, but display unit is not (in column {})"
                .format(title))

        self.title = title
        self.pattern = pattern
        self.number_of_significant_digits = int(
            num_of_digits) if num_of_digits else None
        self.type = col_type
        self.unit = unit
        self.source_unit = source_unit
        self.scale_factor = float(
            scale_factor) if scale_factor else scale_factor
        self.href = href
        if relevant_for_diff is None:
            self.relevant_for_diff = False
        else:
            self.relevant_for_diff = True \
                if relevant_for_diff.lower() == "true" else False
        self.display_title = display_title
示例#4
0
def _get_scale_factor(unit, source_unit, column):
    if unit is None or unit == source_unit:
        return 1
    elif (source_unit in UNIT_CONVERSION.keys()
          and unit in UNIT_CONVERSION[source_unit].keys()):
        return UNIT_CONVERSION[source_unit][unit]
    else:
        # If the display unit is different from the source unit, a scale factor must be given explicitly
        raise util.TableDefinitionError(
            "Attribute displayUnit is different from sourceUnit," +
            f" but scaleFactor is not defined (in column {column.title})")
示例#5
0
    def __init__(
        self,
        title,
        pattern=None,
        num_of_digits=None,
        href=None,
        col_type=None,
        unit=None,
        source_unit=None,
        scale_factor=None,
        relevant_for_diff=None,
        display_title=None,
    ):

        # If scaling on the variables is performed, a display unit must be defined, explicitly
        if scale_factor is not None and scale_factor != 1 and unit is None:
            raise util.TableDefinitionError(
                f"Scale factor is defined, but display unit is not (in column {title})"
            )

        self.title = title
        self.pattern = pattern
        self.number_of_significant_digits = (int(num_of_digits)
                                             if num_of_digits else None)
        self.type = col_type
        self.unit = unit
        self.source_unit = source_unit
        self.scale_factor = Decimal(
            scale_factor) if scale_factor else scale_factor
        self.href = href
        if relevant_for_diff is None:
            self.relevant_for_diff = False
        else:
            self.relevant_for_diff = (True if relevant_for_diff.lower()
                                      == "true" else False)
        self.display_title = display_title

        # expected maximum width (in characters)
        self.max_width = None
示例#6
0
def _get_column_type_heur(column, column_values):
    if column.title == "status":
        return ColumnType.status

    column_type = column.type or None
    if column_type and column_type.type == ColumnType.measure:
        column_type = ColumnMeasureType(0)
    column_unit = column.unit  # May be None
    column_source_unit = column.source_unit  # May be None
    column_scale_factor = column.scale_factor  # May be None

    column_max_int_digits = 0
    column_max_dec_digits = 0
    column_has_numbers = False
    column_has_decimal_numbers = False

    if column_unit:
        explicit_unit_defined = True
    else:
        explicit_unit_defined = False

    if column_scale_factor is None:
        explicit_scale_defined = False
    else:
        explicit_scale_defined = True

    for value in column_values:

        if value is None or value == "":
            continue

        value_match = REGEX_MEASURE.match(str(value))

        # As soon as one row's value is no number, the column type is 'text'
        if value_match is None:
            return ColumnType.text
        else:
            column_has_numbers = True
            curr_column_unit = value_match.group(GROUP_UNIT)

            # If the units in two different rows of the same column differ,
            # 1. Raise an error if an explicit unit is defined by the displayUnit attribute
            #    and the unit in the column cell differs from the defined sourceUnit, or
            # 2. Handle the column as 'text' type, if no displayUnit was defined for the column's values.
            #    In that case, a unit different from the definition of sourceUnit does not lead to an error.
            if curr_column_unit:
                if column_source_unit is None and not explicit_scale_defined:
                    column_source_unit = curr_column_unit
                elif column_source_unit != curr_column_unit:
                    raise util.TableDefinitionError(
                        "Attribute sourceUnit different from real source unit: {} and {} (in column {})"
                        .format(column_source_unit, curr_column_unit,
                                column.title))
                if column_unit and curr_column_unit != column_unit:
                    if explicit_unit_defined:
                        _check_unit_consistency(curr_column_unit,
                                                column_source_unit, column)
                    else:
                        return ColumnType.text
                else:
                    column_unit = curr_column_unit

            if column_scale_factor is None:
                column_scale_factor = _get_scale_factor(
                    column_unit, column_source_unit, column)

            # Compute the number of decimal digits of the current value, considering the number of significant
            # digits for this column.
            # Use the column's scale factor for computing the decimal digits of the current value.
            # Otherwise, they might be different from output.
            scaled_value = float(util.remove_unit(
                str(value))) * column_scale_factor

            # Due to the scaling operation above, floats in the exponent notation may be created. Since this creates
            # special cases, immediately convert the value back to decimal notation.
            if value_match.group(GROUP_DEC_PART):
                # -1 since GROUP_DEC_PART includes the decimal point
                dec_digits_before_scale = len(
                    value_match.group(GROUP_DEC_PART)) - 1
            else:
                dec_digits_before_scale = 0
            max_number_of_dec_digits_after_scale = max(
                0, dec_digits_before_scale - ceil(log10(column_scale_factor)))

            scaled_value = "{0:.{1}f}".format(
                scaled_value, max_number_of_dec_digits_after_scale)
            scaled_value_match = REGEX_MEASURE.match(scaled_value)

            curr_dec_digits = _get_decimal_digits(
                scaled_value_match, column.number_of_significant_digits)
            column_max_dec_digits = max(column_max_dec_digits, curr_dec_digits)

            curr_int_digits = _get_int_digits(scaled_value_match)
            column_max_int_digits = max(column_max_int_digits, curr_int_digits)

            if (scaled_value_match.group(GROUP_DEC_PART) is not None
                    or value_match.group(GROUP_DEC_PART) is not None
                    or scaled_value_match.group(GROUP_SPECIAL_FLOATS_PART)
                    is not None):
                column_has_decimal_numbers = True

    if not column_has_numbers:
        # only empty values
        return ColumnType.text

    if (column_has_decimal_numbers or column_max_dec_digits
            or int(column_scale_factor) !=
            column_scale_factor  # non-int scaling factor
        ):
        column_type = ColumnMeasureType(column_max_dec_digits)
    else:
        column_type = ColumnType.count

    column_width = column_max_int_digits
    if column_max_dec_digits:
        column_width += column_max_dec_digits + 1

    return (
        column_type,
        column_unit,
        column_source_unit,
        column_scale_factor,
        column_width,
    )