def test_normal_number_5(self): col_dp = ColumnDataProperty() col_dp.update_header(DataProperty("abc")) for value in [1.1, 2.2, 3.33]: col_dp.update_body(DataProperty(value)) assert col_dp.align == Align.RIGHT assert col_dp.decimal_places == 2 assert col_dp.typecode == Typecode.REAL_NUMBER assert col_dp.ascii_char_width == 4 assert col_dp.minmax_integer_digits.min_value == 1 assert col_dp.minmax_integer_digits.max_value == 1 assert col_dp.minmax_decimal_places.min_value == 1 assert col_dp.minmax_decimal_places.max_value == 2 assert col_dp.minmax_additional_format_len.min_value == 0 assert col_dp.minmax_additional_format_len.max_value == 0 assert text_type(col_dp) == ( "type=REAL_NUMBER, align=right, ascii_width=4, " "int_digits=1, decimal_places=(min=1, max=2)")
def test_normal_inf(self): col_dp = ColumnDataProperty() col_dp.update_header(DataProperty("inf")) for value in [inf, None, inf, "inf"]: col_dp.update_body(DataProperty(value)) assert col_dp.align == Align.LEFT assert col_dp.decimal_places is None assert col_dp.typecode == Typecode.INFINITY assert col_dp.ascii_char_width == 8 assert col_dp.minmax_integer_digits.min_value is None assert col_dp.minmax_integer_digits.max_value is None assert col_dp.minmax_decimal_places.min_value is None assert col_dp.minmax_decimal_places.max_value is None assert col_dp.minmax_additional_format_len.min_value == 0 assert col_dp.minmax_additional_format_len.max_value == 0 assert text_type(col_dp) == ( "type=INFINITY, align=left, ascii_width=8")
def test_normal_east_asian_ambiguous_width(self, ambiguous_width, ascii_char_width): col_dp = ColumnDataProperty(east_asian_ambiguous_width=ambiguous_width) col_dp.update_header(DataProperty("abc")) for value in ["ØØØ", "α", "ββ"]: col_dp.update_body( DataProperty(value, east_asian_ambiguous_width=ambiguous_width)) assert col_dp.align == Align.LEFT assert col_dp.decimal_places is None assert col_dp.typecode == Typecode.STRING assert col_dp.ascii_char_width == ascii_char_width assert col_dp.minmax_integer_digits.min_value is None assert col_dp.minmax_integer_digits.max_value is None assert col_dp.minmax_decimal_places.min_value is None assert col_dp.minmax_decimal_places.max_value is None assert col_dp.minmax_additional_format_len.min_value == 0 assert col_dp.minmax_additional_format_len.max_value == 0
def _validate_within_min_max(param_name, value, min_value, max_value, unit): if value is None: return if unit is None: unit = "" else: unit = "[{:s}]".format(unit) if value > max_value: raise InvalidParameterError("'{:s}' is too high".format(param_name), expected="<={:s}{:s}".format( DataProperty(max_value).to_str(), unit), value="{:s}{:s}".format( DataProperty(value).to_str(), unit)) if value < min_value: raise InvalidParameterError("'{:s}' is too low".format(param_name), expected=">={:s}{:s}".format( DataProperty(min_value).to_str(), unit), value="{:s}{:s}".format( DataProperty(value).to_str(), unit))
def test_normal_number_4(self): col_dp = ColumnDataProperty() col_dp.update_header(DataProperty("abc")) for value in [0.01, 1.0, 1.2]: col_dp.update_body(DataProperty(value)) assert col_dp.align == Align.RIGHT assert col_dp.decimal_places == 2 assert col_dp.typecode == Typecode.REAL_NUMBER assert col_dp.ascii_char_width == 4 assert col_dp.minmax_integer_digits.min_value == 1 assert col_dp.minmax_integer_digits.max_value == 1 assert col_dp.minmax_decimal_places.min_value == 0 assert col_dp.minmax_decimal_places.max_value == 2 assert col_dp.minmax_additional_format_len.min_value == 0 assert col_dp.minmax_additional_format_len.max_value == 0 assert str(col_dp) == ( "typename=REAL_NUMBER, align=right, ascii_char_width=4, " "integer_digits=(min=1, max=1), decimal_places=(min=0, max=2), " "additional_format_len=(min=0, max=0)")
def test_abnormal(self, value, expected): dp = DataProperty(value) Nan(dp.length).is_type()
def test_normal_eaaw(self, value, eaaw, expected_acs, expected_len): dp = DataProperty(value, east_asian_ambiguous_width=eaaw) assert dp.ascii_char_width == expected_acs assert dp.length == expected_len
def test_normal(self, value, expected_acs, expected_len): dp = DataProperty(value) assert dp.ascii_char_width == expected_acs assert dp.length == expected_len
def test_normal(self, value, expected): dp = DataProperty(value) assert dp.align == expected
def test_normal_tab(self, value, is_escape_html_tag, expected): dp = DataProperty(value, is_escape_html_tag=is_escape_html_tag) assert dp.data == expected
def test_smoke(self, value, strict_type_mapping, expected): dp = DataProperty(value, strict_type_mapping=strict_type_mapping) assert len(dp.__repr__()) > expected
def test_normal(self, lhs, rhs, expected): lhs = DataProperty(lhs) rhs = DataProperty(rhs) assert (lhs == rhs) == expected assert (lhs != rhs) == (not expected)
def test_abnormal(self, value): dp = DataProperty(value) Nan(dp.integer_digits).is_type()
def test_normal_east_asian_ambiguous_width(self, value, ascii_char_width, ambiguous_width, expected): dp = DataProperty(value, east_asian_ambiguous_width=ambiguous_width) assert dp.get_padding_len(ascii_char_width) == expected
def test_normal_ascii_escape_sequence(self, value, expected_acw, expected_len): dp = DataProperty(value) assert dp.ascii_char_width == expected_acw assert dp.length == expected_len
def test_normal(self, value, expected_acw): assert DataProperty(value).is_include_ansi_escape == expected_acw
def test_smoke(self, value, strict_level_map, expected): dp = DataProperty(value, strict_level_map=strict_level_map) assert len(dp.__repr__()) > expected
def test_exception_eaaw(self, value, eaaw, expected): with pytest.raises(expected): DataProperty(value, east_asian_ambiguous_width=eaaw)
def test_abnormal(self, value): dp = DataProperty(value) Nan(dp.decimal_places).is_type()
def test_normal(self, value, ascii_char_width, expected): dp = DataProperty(value) assert dp.get_padding_len(ascii_char_width) == expected
def test_normal(self, value, line_break_handling, expected): assert DataProperty( value, line_break_handling=line_break_handling).data == expected
def test_normal(self, value, expected): dp = DataProperty(value) assert dp.integer_digits == expected
class JavaScriptTableWriter(SourceCodeTableWriter): """ A table writer for class JavaScript format. :Example: :ref:`example-js-table-writer` .. py:attribute:: variable_declaration :type: str :value: "const" JavaScript variable declarations type. The value must be either ``"var"``, ``"let"`` or ``"const"``. .. py:method:: write_table |write_table| with JavaScript format. The tabular data are written as a nested list variable definition. :raises pytablewriter.EmptyTableNameError: If the |table_name| is empty. :Example: :ref:`example-js-table-writer` .. note:: Specific values in the tabular data are converted when writing: - |None|: written as ``null`` - |inf|: written as ``Infinity`` - |nan|: written as ``NaN`` - |datetime| instances determined by |is_datetime_instance_formatting| attribute: - |True|: written as `dateutil.parser <https://dateutil.readthedocs.io/en/stable/parser.html>`__ - |False|: written as |str| .. seealso:: :ref:`example-type-hint-js` """ FORMAT_NAME = "javascript" __VALID_VAR_DECLARATION = ("var", "let", "const") __NONE_VALUE_DP = DataProperty("null") @property def format_name(self) -> str: return self.FORMAT_NAME @property def support_split_write(self) -> bool: return True @property def variable_declaration(self) -> str: return self.__variable_declaration @variable_declaration.setter def variable_declaration(self, value: str): value = value.strip().casefold() if value not in self.__VALID_VAR_DECLARATION: raise ValueError("declaration must be either var, let or const") self.__variable_declaration = value def __init__(self, **kwargs) -> None: super().__init__(**kwargs) self.variable_declaration = "const" self._dp_extractor.type_value_map = { # Typecode.NONE: "null", Typecode.INFINITY: "Infinity", Typecode.NAN: "NaN", } self._dp_extractor.update_strict_level_map( {Typecode.BOOL: StrictLevel.MAX}) self.register_trans_func(bool_to_str) def get_variable_name(self, value: str) -> str: return sanitize_js_var_name(value, "_").casefold() def _write_table(self, **kwargs) -> None: if self.is_datetime_instance_formatting: self._dp_extractor.datetime_formatter = js_datetime_formatter else: self._dp_extractor.datetime_formatter = quote_datetime_formatter org_stream = self.stream self.stream = io.StringIO() self.inc_indent_level() super()._write_table(**kwargs) self.dec_indent_level() js_matrix_var_def_text = self.stream.getvalue().rstrip("\n") js_matrix_var_def_text = strip_quote(js_matrix_var_def_text, "true") js_matrix_var_def_text = strip_quote(js_matrix_var_def_text, "false") if self.is_write_closing_row: js_matrix_var_def_line_list = js_matrix_var_def_text.splitlines() js_matrix_var_def_line_list[-2] = js_matrix_var_def_line_list[ -2].rstrip(",") js_matrix_var_def_text = "\n".join(js_matrix_var_def_line_list) self.stream.close() self.stream = org_stream self.dec_indent_level() self._write_line(js_matrix_var_def_text) self.inc_indent_level() def _get_opening_row_items(self) -> List[str]: return [ "{:s} {:s} = [".format(self.variable_declaration, self.variable_name) ] def _get_closing_row_items(self) -> List[str]: return ["];"] def _to_row_item(self, row_idx: int, col_dp: ColumnDataProperty, value_dp: DataProperty) -> str: if value_dp.data is None: value_dp = self.__NONE_VALUE_DP return super()._to_row_item(row_idx, col_dp, value_dp)
def test_normal(self, value, expected): dp = DataProperty(value) assert dp.decimal_places == expected
class JavaScriptTableWriter(SourceCodeTableWriter): """ A table writer for class JavaScript format. .. py:attribute:: variable_declaration JavaScript variable declarations type. The value must be either ``"var"``, ``"let"`` or ``"const"``. Defaults to ``"const"``. .. py:method:: write_table |write_table| with JavaScript format. The tabular data are written as a nested list variable definition. :raises pytablewriter.EmptyTableNameError: If the |table_name| is empty. :raises pytablewriter.EmptyTableDataError: If the |header_list| and the |value_matrix| is empty. :Example: :ref:`example-js-table-writer` .. note:: Specific values in the tabular data are converted when writing: - |None|: written as ``null`` - |inf|: written as ``Infinity`` - |nan|: written as ``NaN`` - |datetime| instances determined by |is_datetime_instance_formatting| attribute: - |True|: written as `dateutil.parser <https://dateutil.readthedocs.io/en/stable/parser.html>`__ - |False|: written as |str| .. seealso:: :ref:`example-type-hint-js` """ __VALID_VAR_DECLARATION = ("var", "let", "const") __NONE_VALUE_DP = DataProperty("null") @property def format_name(self): return "javascript" @property def support_split_write(self): return True @property def variable_declaration(self): return self.__variable_declaration @variable_declaration.setter def variable_declaration(self, value): value = value.strip().lower() if value not in self.__VALID_VAR_DECLARATION: raise ValueError("declaration must be either var, let or const") self.__variable_declaration = value def __init__(self): super(JavaScriptTableWriter, self).__init__() self.variable_declaration = "const" self._dp_extractor.type_value_map = { # Typecode.NONE: "null", Typecode.INFINITY: "Infinity", Typecode.NAN: "NaN", } self._dp_extractor.const_value_map = {True: "true", False: "false"} def get_variable_name(self, value): import pathvalidate return pathvalidate.sanitize_js_var_name(value, "_").lower() def _write_table(self): if self.is_datetime_instance_formatting: self._dp_extractor.datetime_formatter = js_datetime_formatter else: self._dp_extractor.datetime_formatter = quote_datetime_formatter self._preprocess() org_stream = self.stream self.stream = six.StringIO() self.inc_indent_level() super(JavaScriptTableWriter, self)._write_table() self.dec_indent_level() js_matrix_var_def_text = self.stream.getvalue().rstrip("\n") if self.is_write_closing_row: js_matrix_var_def_line_list = js_matrix_var_def_text.splitlines() js_matrix_var_def_line_list[-2] = js_matrix_var_def_line_list[ -2].rstrip(",") js_matrix_var_def_text = "\n".join(js_matrix_var_def_line_list) self.stream.close() self.stream = org_stream self.dec_indent_level() self._write_line(js_matrix_var_def_text) self.inc_indent_level() def _get_opening_row_item_list(self): return [ "{:s} {:s} = [".format(self.variable_declaration, self.variable_name) ] def _get_closing_row_item_list(self): return ["];"] def _to_row_item(self, col_dp, value_dp): if value_dp.data is None: value_dp = self.__NONE_VALUE_DP return super(JavaScriptTableWriter, self)._to_row_item(col_dp, value_dp)
def test_normal(self, value, expected): dp = DataProperty(value) assert dp.additional_format_len == expected
def test_normal_tab(self, value, float_type, expected): dp = DataProperty(value, float_type=float_type) assert isinstance(dp.data, float_type) assert dp.data == expected
def test_normal(self, value, expected_data, expected_typecode): dp = DataProperty(value) assert dp == dp assert dp.data == expected_data assert dp.typecode == expected_typecode
def test_normal_format_str(self, value, format_flags, expected): dp = DataProperty(value, format_flags=format_flags) assert dp.to_str() == expected