diff --git a/src/safeds/data/tabular/containers/_column.py b/src/safeds/data/tabular/containers/_column.py index 7abb0a73f..963841049 100644 --- a/src/safeds/data/tabular/containers/_column.py +++ b/src/safeds/data/tabular/containers/_column.py @@ -530,6 +530,30 @@ def plot_histogram(self) -> Image: buffer.seek(0) return Image(buffer, ImageFormat.PNG) + # ------------------------------------------------------------------------------------------------------------------ + # Conversion + # ------------------------------------------------------------------------------------------------------------------ + + def to_html(self) -> str: + """ + Return an HTML representation of the column. + + Returns + ------- + output : str + The generated HTML. + + Examples + -------- + >>> from safeds.data.tabular.containers import Column + >>> column = Column("test", [1, 2, 3]) + >>> html = column.to_html() + """ + frame = self._data.to_frame() + frame.columns = [self.name] + + return frame.to_html(max_rows=self._data.size, max_cols=1) + # ------------------------------------------------------------------------------------------------------------------ # IPython integration # ------------------------------------------------------------------------------------------------------------------ diff --git a/src/safeds/data/tabular/containers/_row.py b/src/safeds/data/tabular/containers/_row.py index 91dd5e782..6278eb317 100644 --- a/src/safeds/data/tabular/containers/_row.py +++ b/src/safeds/data/tabular/containers/_row.py @@ -454,6 +454,23 @@ def to_dict(self) -> dict[str, Any]: """ return {column_name: self.get_value(column_name) for column_name in self.column_names} + def to_html(self) -> str: + """ + Return an HTML representation of the row. + + Returns + ------- + output : str + The generated HTML. + + Examples + -------- + >>> from safeds.data.tabular.containers import Row + >>> row = Row({"a": 1, "b": 2}) + >>> html = row.to_html() + """ + return self._data.to_html(max_rows=1, max_cols=self._data.shape[1]) + # ------------------------------------------------------------------------------------------------------------------ # IPython integration # ------------------------------------------------------------------------------------------------------------------ diff --git a/src/safeds/data/tabular/containers/_table.py b/src/safeds/data/tabular/containers/_table.py index 007ccbe1c..1f4cab0ee 100644 --- a/src/safeds/data/tabular/containers/_table.py +++ b/src/safeds/data/tabular/containers/_table.py @@ -1236,6 +1236,23 @@ def to_dict(self) -> dict[str, list[Any]]: """ return {column_name: list(self.get_column(column_name)) for column_name in self.column_names} + def to_html(self) -> str: + """ + Return an HTML representation of the table. + + Returns + ------- + output : str + The generated HTML. + + Examples + -------- + >>> from safeds.data.tabular.containers import Table + >>> table = Table.from_dict({"a": [1, 2, 3], "b": [4, 5, 6]}) + >>> html = table.to_html() + """ + return self._data.to_html(max_rows=self._data.shape[0], max_cols=self._data.shape[1]) + def to_columns(self) -> list[Column]: """ Return a list of the columns. diff --git a/tests/safeds/data/tabular/containers/test_column.py b/tests/safeds/data/tabular/containers/test_column.py index 2de1f7ccb..8e97c213d 100644 --- a/tests/safeds/data/tabular/containers/test_column.py +++ b/tests/safeds/data/tabular/containers/test_column.py @@ -3,6 +3,52 @@ from safeds.data.tabular.containers import Column +class TestToHtml: + @pytest.mark.parametrize( + "column", + [ + Column("a", []), + Column("a", [1, 2, 3]), + ], + ids=[ + "empty", + "non-empty", + ], + ) + def test_should_contain_table_element(self, column: Column) -> None: + pattern = r".*?" + assert re.search(pattern, column.to_html(), flags=re.S) is not None + + @pytest.mark.parametrize( + "column", + [ + Column("a", []), + Column("a", [1, 2, 3]), + ], + ids=[ + "empty", + "non-empty", + ], + ) + def test_should_contain_th_element_for_column_name(self, column: Column) -> None: + assert f"{column.name}" in column.to_html() + + @pytest.mark.parametrize( + "column", + [ + Column("a", []), + Column("a", [1, 2, 3]), + ], + ids=[ + "empty", + "non-empty", + ], + ) + def test_should_contain_td_element_for_each_value(self, column: Column) -> None: + for value in column: + assert f"{value}" in column.to_html() + + class TestReprHtml: @pytest.mark.parametrize( "column", diff --git a/tests/safeds/data/tabular/containers/test_row.py b/tests/safeds/data/tabular/containers/test_row.py index b1887b487..8486f5eff 100644 --- a/tests/safeds/data/tabular/containers/test_row.py +++ b/tests/safeds/data/tabular/containers/test_row.py @@ -402,6 +402,53 @@ def test_should_return_dict_for_table(self, row: Row, expected: dict[str, Any]) assert row.to_dict() == expected +class TestToHtml: + @pytest.mark.parametrize( + "row", + [ + Row(), + Row({"a": 1, "b": 2}), + ], + ids=[ + "empty", + "non-empty", + ], + ) + def test_should_contain_table_element(self, row: Row) -> None: + pattern = r".*?" + assert re.search(pattern, row.to_html(), flags=re.S) is not None + + @pytest.mark.parametrize( + "row", + [ + Row(), + Row({"a": 1, "b": 2}), + ], + ids=[ + "empty", + "non-empty", + ], + ) + def test_should_contain_th_element_for_each_column_name(self, row: Row) -> None: + for column_name in row.column_names: + assert f"{column_name}" in row.to_html() + + @pytest.mark.parametrize( + "row", + [ + Row(), + Row({"a": 1, "b": 2}), + ], + ids=[ + "empty", + "non-empty", + ], + ) + def test_should_contain_td_element_for_each_value(self, row: Row) -> None: + for value in row.values(): + assert f"{value}" in row.to_html() + + class TestReprHtml: @pytest.mark.parametrize( "row", diff --git a/tests/safeds/data/tabular/containers/test_table.py b/tests/safeds/data/tabular/containers/test_table.py index 5016b9d19..4285b1438 100644 --- a/tests/safeds/data/tabular/containers/test_table.py +++ b/tests/safeds/data/tabular/containers/test_table.py @@ -54,6 +54,54 @@ def test_should_return_dict_for_table(self, table: Table, expected: dict[str, li assert table.to_dict() == expected +class TestToHtml: + @pytest.mark.parametrize( + "table", + [ + Table.from_dict({}), + Table.from_dict({"a": [1, 2], "b": [3, 4]}), + ], + ids=[ + "empty", + "non-empty", + ], + ) + def test_should_contain_table_element(self, table: Table) -> None: + pattern = r".*?" + assert re.search(pattern, table.to_html(), flags=re.S) is not None + + @pytest.mark.parametrize( + "table", + [ + Table.from_dict({}), + Table.from_dict({"a": [1, 2], "b": [3, 4]}), + ], + ids=[ + "empty", + "non-empty", + ], + ) + def test_should_contain_th_element_for_each_column_name(self, table: Table) -> None: + for column_name in table.column_names: + assert f"{column_name}" in table.to_html() + + @pytest.mark.parametrize( + "table", + [ + Table.from_dict({}), + Table.from_dict({"a": [1, 2], "b": [3, 4]}), + ], + ids=[ + "empty", + "non-empty", + ], + ) + def test_should_contain_td_element_for_each_value(self, table: Table) -> None: + for column in table.to_columns(): + for value in column: + assert f"{value}" in table.to_html() + + class TestReprHtml: @pytest.mark.parametrize( "table",