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})")
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))
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
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})")
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
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, )