From f56ceb324c6b373d59164d937138657596a0119d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20Gr=C3=A9us?= Date: Fri, 12 May 2023 16:00:43 +0200 Subject: [PATCH 01/14] refactor: Added and specified Errors in `Table` test: Added test for Errors in `Table` for to and from files feat: Added `WrongFileExtensionError` --- src/safeds/data/tabular/containers/_table.py | 118 ++++++++++++++---- src/safeds/data/tabular/typing/_schema.py | 2 +- src/safeds/exceptions/__init__.py | 2 + src/safeds/exceptions/_data.py | 14 ++- .../containers/_table/test_from_columns.py | 7 +- .../containers/_table/test_from_csv_file.py | 11 ++ .../containers/_table/test_from_excel_file.py | 11 ++ .../containers/_table/test_from_json_file.py | 11 ++ .../containers/_table/test_to_csv_file.py | 16 ++- .../containers/_table/test_to_excel_file.py | 12 ++ .../containers/_table/test_to_json_file.py | 16 ++- 11 files changed, 186 insertions(+), 34 deletions(-) diff --git a/src/safeds/data/tabular/containers/_table.py b/src/safeds/data/tabular/containers/_table.py index cf553eb33..f8026c6ad 100644 --- a/src/safeds/data/tabular/containers/_table.py +++ b/src/safeds/data/tabular/containers/_table.py @@ -25,6 +25,7 @@ NonNumericColumnError, SchemaMismatchError, UnknownColumnNameError, + WrongFileExtensionError, ) from ._column import Column @@ -92,9 +93,12 @@ def from_csv_file(path: str | Path) -> Table: ------ FileNotFoundError If the specified file does not exist. - ValueError - If the file could not be read. + WrongFileExtensionError + If the file is not a csv file. """ + path = Path(path) + if path.suffix != ".csv": + raise WrongFileExtensionError(path, ".csv") try: return Table._from_pandas_dataframe(pd.read_csv(path)) except FileNotFoundError as exception: @@ -104,6 +108,7 @@ def from_csv_file(path: str | Path) -> Table: def from_excel_file(path: str | Path) -> Table: """ Read data from an Excel file into a table. + Valid file extensions are `.xls`, '.xlsx', `.xlsm`, `.xlsb`, `.odf`, `.ods` and `.odt`. Parameters ---------- @@ -119,9 +124,13 @@ def from_excel_file(path: str | Path) -> Table: ------ FileNotFoundError If the specified file does not exist. - ValueError - If the file could not be read. + WrongFileExtensionError + If the file is not an Excel file. """ + path = Path(path) + excel_extensions = [".xls", ".xlsx", ".xlsm", ".xlsb", ".odf", ".ods", ".odt"] + if path.suffix not in excel_extensions: + raise WrongFileExtensionError(path, excel_extensions) try: return Table._from_pandas_dataframe( pd.read_excel(path, engine="openpyxl", usecols=lambda colname: "Unnamed" not in colname), @@ -148,9 +157,12 @@ def from_json_file(path: str | Path) -> Table: ------ FileNotFoundError If the specified file does not exist. - ValueError - If the file could not be read. + WrongFileExtensionError + If the file is not a JSON file. """ + path = Path(path) + if path.suffix != ".json": + raise WrongFileExtensionError(path, ".json") try: return Table._from_pandas_dataframe(pd.read_json(path)) except FileNotFoundError as exception: @@ -197,14 +209,20 @@ def from_columns(columns: list[Column]) -> Table: ------ ColumnLengthMismatchError If any of the column sizes does not match with the others. + DuplicateColumnNameError + If multiple columns have the same name. """ dataframe: DataFrame = pd.DataFrame() + column_names = list() for column in columns: if column._data.size != columns[0]._data.size: raise ColumnLengthMismatchError( "\n".join(f"{column.name}: {column._data.size}" for column in columns), ) + if column.name in column_names: + raise DuplicateColumnNameError(column.name) + column_names.append(column.name) dataframe[column.name] = column._data return Table._from_pandas_dataframe(dataframe) @@ -330,6 +348,8 @@ def __eq__(self, other: Any) -> bool: return True table1 = self.sort_columns() table2 = other.sort_columns() + if table1.number_of_rows == 0 and table2.number_of_rows == 0: + return table1._schema == table2._schema return table1._schema == table2._schema and table1._data.equals(table2._data) def __repr__(self) -> str: @@ -463,7 +483,7 @@ def get_column_type(self, column_name: str) -> ColumnType: Raises ------ - ColumnNameError + UnknownColumnNameError If the specified target column name does not exist. """ return self._schema.get_column_type(column_name) @@ -627,6 +647,10 @@ def add_row(self, row: Row) -> Table: table : Table A new table with the added row at the end. + Raises + ------ + SchemaMismatchError + If the schema of the row does not match the table schema. """ if self._schema != row.schema: raise SchemaMismatchError @@ -650,6 +674,11 @@ def add_rows(self, rows: list[Row] | Table) -> Table: ------- result : Table A new table which combines the original table and the given rows. + + Raises + ------ + SchemaMismatchError + If the schema of on of the row does not match the table schema. """ if isinstance(rows, Table): rows = rows.to_rows() @@ -705,7 +734,7 @@ def keep_only_columns(self, column_names: list[str]) -> Table: Raises ------ - ColumnNameError + UnknownColumnNameError If any of the given columns does not exist. """ invalid_columns = [] @@ -737,7 +766,7 @@ def remove_columns(self, column_names: list[str]) -> Table: Raises ------ - ColumnNameError + UnknownColumnNameError If any of the given columns does not exist. """ invalid_columns = [] @@ -851,7 +880,7 @@ def rename_column(self, old_name: str, new_name: str) -> Table: Raises ------ - ColumnNameError + UnknownColumnNameError If the specified old target column name does not exist. DuplicateColumnNameError If the specified new target column name already exists. @@ -960,7 +989,7 @@ def slice_rows( Raises ------ - ValueError + IndexOutOfBoundsError If the index is out of bounds. """ if start is None: @@ -969,8 +998,10 @@ def slice_rows( if end is None: end = self.number_of_rows - if start < 0 or end < 0 or start >= self.number_of_rows or end > self.number_of_rows or end < start: - raise ValueError("The given index is out of bounds") + if end < start: + raise IndexOutOfBoundsError(slice(start, end)) + if start < 0 or end < 0 or start >= self.number_of_rows or end > self.number_of_rows: + raise IndexOutOfBoundsError(start if start < 0 or start >= self.number_of_rows else end) new_df = self._data.iloc[start:end:step] new_df.columns = self._schema.column_names @@ -1053,10 +1084,13 @@ def split(self, percentage_in_first: float) -> tuple[Table, Table]: A tuple containing the two resulting tables. The first table has the specified size, the second table contains the rest of the data. - + Raises + ------ + ValueError: + if the 'percentage_in_first' is not between 0 and 1 """ - if percentage_in_first <= 0 or percentage_in_first >= 1: - raise ValueError("the given percentage is not in range") + if percentage_in_first < 0 or percentage_in_first > 1: + raise ValueError("The given percentage is not between 0 and 1") return ( self.slice_rows(0, round(percentage_in_first * self.number_of_rows)), self.slice_rows(round(percentage_in_first * self.number_of_rows)), @@ -1079,6 +1113,13 @@ def tag_columns(self, target_name: str, feature_names: list[str] | None = None) ------- tagged_table : TaggedTable A new tagged table with the given target and feature names. + + Raises + ------ + ValueError + If the target column is also a feature column. + ValueError + If no feature columns are specified. """ from ._tagged_table import TaggedTable @@ -1241,10 +1282,8 @@ def plot_lineplot(self, x_column_name: str, y_column_name: str) -> Image: UnknownColumnNameError If either of the columns do not exist. """ - if not self.has_column(x_column_name): - raise UnknownColumnNameError([x_column_name]) - if not self.has_column(y_column_name): - raise UnknownColumnNameError([y_column_name]) + if not self.has_column(x_column_name) or not self.has_column(y_column_name): + raise UnknownColumnNameError(([x_column_name] if not self.has_column(x_column_name) else []) + ([y_column_name] if not self.has_column(y_column_name) else [])) fig = plt.figure() ax = sns.lineplot( @@ -1288,10 +1327,8 @@ def plot_scatterplot(self, x_column_name: str, y_column_name: str) -> Image: UnknownColumnNameError If either of the columns do not exist. """ - if not self.has_column(x_column_name): - raise UnknownColumnNameError([x_column_name]) - if not self.has_column(y_column_name): - raise UnknownColumnNameError([y_column_name]) + if not self.has_column(x_column_name) or not self.has_column(y_column_name): + raise UnknownColumnNameError(([x_column_name] if not self.has_column(x_column_name) else []) + ([y_column_name] if not self.has_column(y_column_name) else [])) fig = plt.figure() ax = sns.scatterplot( @@ -1399,8 +1436,16 @@ def to_csv_file(self, path: str | Path) -> None: ---------- path : str | Path The path to the output file. + + Raises + ------ + WrongFileExtensionError + If the file is not a csv file. """ - Path(path).parent.mkdir(parents=True, exist_ok=True) + path = Path(path) + if path.suffix != ".csv": + raise WrongFileExtensionError(path, ".csv") + path.parent.mkdir(parents=True, exist_ok=True) data_to_csv = self._data.copy() data_to_csv.columns = self._schema.column_names data_to_csv.to_csv(path, index=False) @@ -1408,6 +1453,7 @@ def to_csv_file(self, path: str | Path) -> None: def to_excel_file(self, path: str | Path) -> None: """ Write the data from the table into an Excel file. + Valid file extensions are `.xls`, '.xlsx', `.xlsm`, `.xlsb`, `.odf`, `.ods` and `.odt`. If the file and/or the directories do not exist, they will be created. If the file already exists, it will be overwritten. @@ -1416,12 +1462,22 @@ def to_excel_file(self, path: str | Path) -> None: ---------- path : str | Path The path to the output file. + + Raises + ------ + WrongFileExtensionError + If the file is not an Excel file. """ + path = Path(path) + excel_extensions = [".xls", ".xlsx", ".xlsm", ".xlsb", ".odf", ".ods", ".odt"] + if path.suffix not in excel_extensions: + raise WrongFileExtensionError(path, excel_extensions) + # Create Excel metadata in the file tmp_table_file = openpyxl.Workbook() tmp_table_file.save(path) - Path(path).parent.mkdir(parents=True, exist_ok=True) + path.parent.mkdir(parents=True, exist_ok=True) data_to_excel = self._data.copy() data_to_excel.columns = self._schema.column_names data_to_excel.to_excel(path) @@ -1437,8 +1493,16 @@ def to_json_file(self, path: str | Path) -> None: ---------- path : str | Path The path to the output file. + + Raises + ------ + WrongFileExtensionError + If the file is not a JSON file. """ - Path(path).parent.mkdir(parents=True, exist_ok=True) + path = Path(path) + if path.suffix != ".json": + raise WrongFileExtensionError(path, ".json") + path.parent.mkdir(parents=True, exist_ok=True) data_to_json = self._data.copy() data_to_json.columns = self._schema.column_names data_to_json.to_json(path) diff --git a/src/safeds/data/tabular/typing/_schema.py b/src/safeds/data/tabular/typing/_schema.py index 13c0f521a..a75a87241 100644 --- a/src/safeds/data/tabular/typing/_schema.py +++ b/src/safeds/data/tabular/typing/_schema.py @@ -184,7 +184,7 @@ def get_column_type(self, column_name: str) -> ColumnType: Raises ------ - ColumnNameError + UnknownColumnNameError If the specified column name does not exist. Examples diff --git a/src/safeds/exceptions/__init__.py b/src/safeds/exceptions/__init__.py index d65119021..48af59135 100644 --- a/src/safeds/exceptions/__init__.py +++ b/src/safeds/exceptions/__init__.py @@ -10,6 +10,7 @@ TransformerNotFittedError, UnknownColumnNameError, ValueNotPresentWhenFittedError, + WrongFileExtensionError, ) from safeds.exceptions._ml import ( DatasetContainsTargetError, @@ -31,6 +32,7 @@ "TransformerNotFittedError", "UnknownColumnNameError", "ValueNotPresentWhenFittedError", + "WrongFileExtensionError", # ML exceptions "DatasetContainsTargetError", "DatasetMissesFeaturesError", diff --git a/src/safeds/exceptions/_data.py b/src/safeds/exceptions/_data.py index 8a551784b..dbdfe29e7 100644 --- a/src/safeds/exceptions/_data.py +++ b/src/safeds/exceptions/_data.py @@ -1,5 +1,7 @@ from __future__ import annotations +from pathlib import Path + class UnknownColumnNameError(KeyError): """ @@ -47,7 +49,10 @@ class IndexOutOfBoundsError(IndexError): """ def __init__(self, index: int | slice): - super().__init__(f"There is no element at index '{index}'.") + if isinstance(index, int): + super().__init__(f"There is no element at index '{index}'.") + else: + super().__init__(f"There is no element in the range [{index.start}, {index.stop}]") class ColumnSizeError(Exception): @@ -92,3 +97,10 @@ class ValueNotPresentWhenFittedError(Exception): def __init__(self, value: str, column: str) -> None: super().__init__(f"Value not present in the table the transformer was fitted on: \n{value} in column {column}.") + + +class WrongFileExtensionError(Exception): + """Exception raised when the file has the wrong file extension.""" + + def __init__(self, file: str | Path, file_extension: str | list[str]) -> None: + super().__init__(f"The file {file} has a wrong file extension. Please provide a file with the following extension(s): [{file_extension}]") diff --git a/tests/safeds/data/tabular/containers/_table/test_from_columns.py b/tests/safeds/data/tabular/containers/_table/test_from_columns.py index d56bd54af..6f283124c 100644 --- a/tests/safeds/data/tabular/containers/_table/test_from_columns.py +++ b/tests/safeds/data/tabular/containers/_table/test_from_columns.py @@ -1,6 +1,6 @@ import pytest from safeds.data.tabular.containers import Column, Table -from safeds.exceptions import ColumnLengthMismatchError +from safeds.exceptions import ColumnLengthMismatchError, DuplicateColumnNameError @pytest.mark.parametrize( @@ -29,3 +29,8 @@ def test_should_create_table_from_list_of_columns(columns: list[Column], expecte def test_should_raise_error_if_column_length_mismatch() -> None: with pytest.raises(ColumnLengthMismatchError): Table.from_columns([Column("col1", [5, 2, 3]), Column("col2", [5, 3, 4, 1])]) + + +def test_should_raise_error_if_duplicate_column_name() -> None: + with pytest.raises(DuplicateColumnNameError): + Table.from_columns([Column("col1", [5, 2, 3]), Column("col1", [5, 3, 4])]) diff --git a/tests/safeds/data/tabular/containers/_table/test_from_csv_file.py b/tests/safeds/data/tabular/containers/_table/test_from_csv_file.py index d437631b0..fa7da264b 100644 --- a/tests/safeds/data/tabular/containers/_table/test_from_csv_file.py +++ b/tests/safeds/data/tabular/containers/_table/test_from_csv_file.py @@ -2,6 +2,7 @@ import pytest from safeds.data.tabular.containers import Table +from safeds.exceptions import WrongFileExtensionError from tests.helpers import resolve_resource_path @@ -21,3 +22,13 @@ def test_should_create_table_from_csv_file(path: str | Path) -> None: def test_should_raise_error_if_file_not_found(path: str | Path) -> None: with pytest.raises(FileNotFoundError): Table.from_csv_file(resolve_resource_path(path)) + + +@pytest.mark.parametrize( + "path", + ["invalid_file_extension.file_extension", Path("invalid_file_extension.file_extension")], + ids=["by String", "by path"], +) +def test_should_raise_error_if_wrong_file_extension(path: str | Path) -> None: + with pytest.raises(WrongFileExtensionError): + Table.from_csv_file(resolve_resource_path(path)) diff --git a/tests/safeds/data/tabular/containers/_table/test_from_excel_file.py b/tests/safeds/data/tabular/containers/_table/test_from_excel_file.py index d44c60c9d..1a09bb81c 100644 --- a/tests/safeds/data/tabular/containers/_table/test_from_excel_file.py +++ b/tests/safeds/data/tabular/containers/_table/test_from_excel_file.py @@ -2,6 +2,7 @@ import pytest from safeds.data.tabular.containers import Table +from safeds.exceptions import WrongFileExtensionError from tests.helpers import resolve_resource_path @@ -38,3 +39,13 @@ def test_should_create_table_from_excel_file(path: str | Path, expected: Table) def test_should_raise_if_file_not_found() -> None: with pytest.raises(FileNotFoundError): Table.from_excel_file(resolve_resource_path("test_table_from_excel_file_invalid.xls")) + + +@pytest.mark.parametrize( + "path", + ["invalid_file_extension.file_extension", Path("invalid_file_extension.file_extension")], + ids=["by String", "by path"], +) +def test_should_raise_error_if_wrong_file_extension(path: str | Path) -> None: + with pytest.raises(WrongFileExtensionError): + Table.from_excel_file(resolve_resource_path(path)) diff --git a/tests/safeds/data/tabular/containers/_table/test_from_json_file.py b/tests/safeds/data/tabular/containers/_table/test_from_json_file.py index 34c591954..d986d571a 100644 --- a/tests/safeds/data/tabular/containers/_table/test_from_json_file.py +++ b/tests/safeds/data/tabular/containers/_table/test_from_json_file.py @@ -2,6 +2,7 @@ import pytest from safeds.data.tabular.containers import Table +from safeds.exceptions import WrongFileExtensionError from tests.helpers import resolve_resource_path @@ -21,3 +22,13 @@ def test_should_create_table_from_json_file(path: str | Path) -> None: def test_should_raise_error_if_file_not_found(path: str | Path) -> None: with pytest.raises(FileNotFoundError): Table.from_json_file(resolve_resource_path(path)) + + +@pytest.mark.parametrize( + "path", + ["invalid_file_extension.file_extension", Path("invalid_file_extension.file_extension")], + ids=["by String", "by path"], +) +def test_should_raise_error_if_wrong_file_extension(path: str | Path) -> None: + with pytest.raises(WrongFileExtensionError): + Table.from_json_file(resolve_resource_path(path)) diff --git a/tests/safeds/data/tabular/containers/_table/test_to_csv_file.py b/tests/safeds/data/tabular/containers/_table/test_to_csv_file.py index 60bea9acb..9fb60739a 100644 --- a/tests/safeds/data/tabular/containers/_table/test_to_csv_file.py +++ b/tests/safeds/data/tabular/containers/_table/test_to_csv_file.py @@ -1,12 +1,15 @@ from pathlib import Path from tempfile import NamedTemporaryFile +import pytest + from safeds.data.tabular.containers import Table +from safeds.exceptions import WrongFileExtensionError def test_should_create_csv_file_from_table_by_str() -> None: table = Table({"col1": ["col1_1"], "col2": ["col2_1"]}) - with NamedTemporaryFile() as tmp_table_file: + with NamedTemporaryFile(suffix=".csv") as tmp_table_file: tmp_table_file.close() with Path(tmp_table_file.name).open("w", encoding="utf-8") as tmp_file: table.to_csv_file(tmp_file.name) @@ -17,10 +20,19 @@ def test_should_create_csv_file_from_table_by_str() -> None: def test_should_create_csv_file_from_table_by_path() -> None: table = Table({"col1": ["col1_1"], "col2": ["col2_1"]}) - with NamedTemporaryFile() as tmp_table_file: + with NamedTemporaryFile(suffix=".csv") as tmp_table_file: tmp_table_file.close() with Path(tmp_table_file.name).open("w", encoding="utf-8") as tmp_file: table.to_csv_file(Path(tmp_file.name)) with Path(tmp_table_file.name).open("r", encoding="utf-8") as tmp_file: table_r = Table.from_csv_file(Path(tmp_file.name)) assert table == table_r + + +def test_should_raise_error_if_wrong_file_extension() -> None: + table = Table({"col1": ["col1_1"], "col2": ["col2_1"]}) + with NamedTemporaryFile(suffix=".invalid_file_extension") as tmp_table_file: + tmp_table_file.close() + with Path(tmp_table_file.name).open("w", encoding="utf-8") as tmp_file: + with pytest.raises(WrongFileExtensionError): + table.to_csv_file(Path(tmp_file.name)) diff --git a/tests/safeds/data/tabular/containers/_table/test_to_excel_file.py b/tests/safeds/data/tabular/containers/_table/test_to_excel_file.py index 96c2803ad..af61f286a 100644 --- a/tests/safeds/data/tabular/containers/_table/test_to_excel_file.py +++ b/tests/safeds/data/tabular/containers/_table/test_to_excel_file.py @@ -1,7 +1,10 @@ from pathlib import Path from tempfile import NamedTemporaryFile +import pytest + from safeds.data.tabular.containers import Table +from safeds.exceptions import WrongFileExtensionError def test_should_create_csv_file_from_table_by_str() -> None: @@ -24,3 +27,12 @@ def test_should_create_csv_file_from_table_by_path() -> None: with Path(tmp_table_file.name).open("r", encoding="utf-8") as tmp_file: table_r = Table.from_excel_file(Path(tmp_file.name)) assert table == table_r + + +def test_should_raise_error_if_wrong_file_extension() -> None: + table = Table({"col1": ["col1_1"], "col2": ["col2_1"]}) + with NamedTemporaryFile(suffix=".invalid_file_extension") as tmp_table_file: + tmp_table_file.close() + with Path(tmp_table_file.name).open("w", encoding="utf-8") as tmp_file: + with pytest.raises(WrongFileExtensionError): + table.to_excel_file(Path(tmp_file.name)) diff --git a/tests/safeds/data/tabular/containers/_table/test_to_json_file.py b/tests/safeds/data/tabular/containers/_table/test_to_json_file.py index 961b4f2a0..24efce050 100644 --- a/tests/safeds/data/tabular/containers/_table/test_to_json_file.py +++ b/tests/safeds/data/tabular/containers/_table/test_to_json_file.py @@ -1,12 +1,15 @@ from pathlib import Path from tempfile import NamedTemporaryFile +import pytest + from safeds.data.tabular.containers import Table +from safeds.exceptions import WrongFileExtensionError def test_should_create_json_file_from_table_by_str() -> None: table = Table({"col1": ["col1_1"], "col2": ["col2_1"]}) - with NamedTemporaryFile() as tmp_table_file: + with NamedTemporaryFile(suffix=".json") as tmp_table_file: tmp_table_file.close() with Path(tmp_table_file.name).open("w", encoding="utf-8") as tmp_file: table.to_json_file(tmp_file.name) @@ -17,10 +20,19 @@ def test_should_create_json_file_from_table_by_str() -> None: def test_should_create_json_file_from_table_by_path() -> None: table = Table({"col1": ["col1_1"], "col2": ["col2_1"]}) - with NamedTemporaryFile() as tmp_table_file: + with NamedTemporaryFile(suffix=".json") as tmp_table_file: tmp_table_file.close() with Path(tmp_table_file.name).open("w", encoding="utf-8") as tmp_file: table.to_json_file(Path(tmp_file.name)) with Path(tmp_table_file.name).open("r", encoding="utf-8") as tmp_file: table_r = Table.from_json_file(Path(tmp_file.name)) assert table == table_r + + +def test_should_raise_error_if_wrong_file_extension() -> None: + table = Table({"col1": ["col1_1"], "col2": ["col2_1"]}) + with NamedTemporaryFile(suffix=".invalid_file_extension") as tmp_table_file: + tmp_table_file.close() + with Path(tmp_table_file.name).open("w", encoding="utf-8") as tmp_file: + with pytest.raises(WrongFileExtensionError): + table.to_json_file(Path(tmp_file.name)) From 513770746ed035eda105e361bed067025c8e9c99 Mon Sep 17 00:00:00 2001 From: methr0 Date: Fri, 12 May 2023 16:16:24 +0200 Subject: [PATCH 02/14] split, remove cloumns --- src/safeds/data/tabular/containers/_table.py | 6 ++--- .../containers/_table/test_remove_columns.py | 13 ++++----- .../tabular/containers/_table/test_split.py | 27 ++++++++++++++----- 3 files changed, 30 insertions(+), 16 deletions(-) diff --git a/src/safeds/data/tabular/containers/_table.py b/src/safeds/data/tabular/containers/_table.py index f8026c6ad..03de9bacd 100644 --- a/src/safeds/data/tabular/containers/_table.py +++ b/src/safeds/data/tabular/containers/_table.py @@ -1000,12 +1000,12 @@ def slice_rows( if end < start: raise IndexOutOfBoundsError(slice(start, end)) - if start < 0 or end < 0 or start >= self.number_of_rows or end > self.number_of_rows: - raise IndexOutOfBoundsError(start if start < 0 or start >= self.number_of_rows else end) + if start < 0 or end < 0 or start > self.number_of_rows or end > self.number_of_rows: + raise IndexOutOfBoundsError(start if start < 0 or start > self.number_of_rows else end) new_df = self._data.iloc[start:end:step] new_df.columns = self._schema.column_names - return Table._from_pandas_dataframe(new_df) + return Table._from_pandas_dataframe(new_df, self._schema) def sort_columns( self, diff --git a/tests/safeds/data/tabular/containers/_table/test_remove_columns.py b/tests/safeds/data/tabular/containers/_table/test_remove_columns.py index f0a47fc18..73cd66088 100644 --- a/tests/safeds/data/tabular/containers/_table/test_remove_columns.py +++ b/tests/safeds/data/tabular/containers/_table/test_remove_columns.py @@ -4,15 +4,16 @@ @pytest.mark.parametrize( - ("table1", "expected"), + ("table1", "expected", "columns"), [ - (Table({"col1": [1, 2, 1], "col2": ["a", "b", "c"]}), Table({"col1": [1, 2, 1]})), - (Table({"col1": [1, 2, 1], "col2": [1, 2, 4]}), Table({"col1": [1, 2, 1]})), + (Table({"col1": [1, 2, 1], "col2": ["a", "b", "c"]}), Table({"col1": [1, 2, 1]}), ["col2"]), + (Table({"col1": [1, 2, 1], "col2": [1, 2, 4]}), Table({}), ["col1", "col2"]), + (Table({"col1": [1, 2, 1], "col2": [1, 2, 4]}), Table({"col1": [1, 2, 1], "col2": [1, 2, 4]}), []), ], - ids=["String", "Integer"], + ids=["one column", "multiple columns", "no columns"], ) -def test_should_remove_table_columns(table1: Table, expected: Table) -> None: - table1 = table1.remove_columns(["col2"]) +def test_should_remove_table_columns(table1: Table, expected: Table, columns: list[str]) -> None: + table1 = table1.remove_columns(columns) assert table1 == expected diff --git a/tests/safeds/data/tabular/containers/_table/test_split.py b/tests/safeds/data/tabular/containers/_table/test_split.py index 4c510299f..f9133381b 100644 --- a/tests/safeds/data/tabular/containers/_table/test_split.py +++ b/tests/safeds/data/tabular/containers/_table/test_split.py @@ -1,20 +1,35 @@ +import pandas as pd import pytest from safeds.data.tabular.containers import Table +from safeds.data.tabular.typing import Schema, Integer @pytest.mark.parametrize( - ("table", "result_train_table", "result_test_table"), + ("table", "result_train_table", "result_test_table", "percentage_in_first"), [ ( Table({"col1": [1, 2, 1], "col2": [1, 2, 4]}), Table({"col1": [1, 2], "col2": [1, 2]}), Table({"col1": [1], "col2": [4]}), + 2/3, + ), +( + Table({"col1": [1, 2, 1], "col2": [1, 2, 4]}), + Table._from_pandas_dataframe(pd.DataFrame(), Schema({"col1": Integer(), "col2": Integer()})), + Table({"col1": [1, 2, 1], "col2": [1, 2, 4]}), + 0, + ), +( + Table({"col1": [1, 2, 1], "col2": [1, 2, 4]}), + Table({"col1": [1, 2, 1], "col2": [1, 2, 4]}), + Table._from_pandas_dataframe(pd.DataFrame(), Schema({"col1": Integer(), "col2": Integer()})), + 1, ), ], - ids=["Table with three rows"], + ids=["2/3%", "0%", "100%"], ) -def test_should_split_table(table: Table, result_test_table: Table, result_train_table: Table) -> None: - train_table, test_table = table.split(2 / 3) +def test_should_split_table(table: Table, result_test_table: Table, result_train_table: Table, percentage_in_first: int) -> None: + train_table, test_table = table.split(percentage_in_first) assert result_test_table == test_table assert result_train_table == train_table @@ -22,12 +37,10 @@ def test_should_split_table(table: Table, result_test_table: Table, result_train @pytest.mark.parametrize( "percentage_in_first", [ - 0.0, - 1.0, -1.0, 2.0, ], - ids=["0.0%", "1.0%", "-1.0%", "2.0%"], + ids=["-100%", "200%"], ) def test_should_raise_if_value_not_in_range(percentage_in_first: float) -> None: table = Table({"col1": [1, 2, 1], "col2": [1, 2, 4]}) From 0c73682427687bd091aa756329eabc727681f7b2 Mon Sep 17 00:00:00 2001 From: methr0 Date: Fri, 12 May 2023 16:23:32 +0200 Subject: [PATCH 03/14] slice rows --- .../safeds/data/tabular/containers/_table/test_slice_rows.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/safeds/data/tabular/containers/_table/test_slice_rows.py b/tests/safeds/data/tabular/containers/_table/test_slice_rows.py index aabbc32af..17cf6c375 100644 --- a/tests/safeds/data/tabular/containers/_table/test_slice_rows.py +++ b/tests/safeds/data/tabular/containers/_table/test_slice_rows.py @@ -1,5 +1,8 @@ import pytest +from _pytest.python_api import raises + from safeds.data.tabular.containers import Table +from safeds.exceptions import IndexOutOfBoundsError @pytest.mark.parametrize( @@ -35,5 +38,5 @@ def test_should_slice_rows(table: Table, test_table: Table, second_test_table: T def test_should_raise_if_index_out_of_bounds(start: int, end: int, step: int) -> None: table = Table({"col1": [1, 2, 1], "col2": [1, 2, 4]}) - with pytest.raises(ValueError, match="The given index is out of bounds"): + with raises(IndexOutOfBoundsError): table.slice_rows(start, end, step) From b713c922b7827c485bfc643bb2bc6e40c77a145e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20Gr=C3=A9us?= Date: Fri, 12 May 2023 16:32:57 +0200 Subject: [PATCH 04/14] test: Added tests for Error in `Table.plot_lineplot` and `Table.plot_scatterplot` test: Corrected tests for `Table.split` --- src/safeds/data/tabular/containers/_table.py | 2 -- .../data/tabular/containers/_table/test_plot_lineplot.py | 4 ++-- .../data/tabular/containers/_table/test_plot_scatterplot.py | 3 ++- tests/safeds/data/tabular/containers/_table/test_split.py | 2 +- 4 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/safeds/data/tabular/containers/_table.py b/src/safeds/data/tabular/containers/_table.py index 03de9bacd..878ceb356 100644 --- a/src/safeds/data/tabular/containers/_table.py +++ b/src/safeds/data/tabular/containers/_table.py @@ -1121,8 +1121,6 @@ def tag_columns(self, target_name: str, feature_names: list[str] | None = None) ValueError If no feature columns are specified. """ - from ._tagged_table import TaggedTable - return TaggedTable._from_table(self, target_name, feature_names) def transform_column(self, name: str, transformer: Callable[[Row], Any]) -> Table: diff --git a/tests/safeds/data/tabular/containers/_table/test_plot_lineplot.py b/tests/safeds/data/tabular/containers/_table/test_plot_lineplot.py index 480d5b147..f8f1484aa 100644 --- a/tests/safeds/data/tabular/containers/_table/test_plot_lineplot.py +++ b/tests/safeds/data/tabular/containers/_table/test_plot_lineplot.py @@ -18,8 +18,8 @@ def test_should_match_snapshot() -> None: @pytest.mark.parametrize( ("x", "y"), - [("C", "A"), ("A", "C")], - ids=["x column", "y column"], + [("C", "A"), ("A", "C"), ("C", "D")], + ids=["x column", "y column", "x and y column"], ) def test_should_raise_if_column_does_not_exist(x: str, y: str) -> None: table = Table({"A": [1, 2, 3], "B": [2, 4, 7]}) diff --git a/tests/safeds/data/tabular/containers/_table/test_plot_scatterplot.py b/tests/safeds/data/tabular/containers/_table/test_plot_scatterplot.py index f23353517..4b5e61251 100644 --- a/tests/safeds/data/tabular/containers/_table/test_plot_scatterplot.py +++ b/tests/safeds/data/tabular/containers/_table/test_plot_scatterplot.py @@ -21,8 +21,9 @@ def test_should_match_snapshot() -> None: [ (Table({"A": [1, 2, 3], "B": [2, 4, 7]}), "C", "A"), (Table({"A": [1, 2, 3], "B": [2, 4, 7]}), "B", "C"), + (Table({"A": [1, 2, 3], "B": [2, 4, 7]}), "C", "D"), ], - ids=["First argument doesn't exist", "Second argument doesn't exist"], + ids=["First argument doesn't exist", "Second argument doesn't exist", "Both arguments do not exist"], ) def test_should_raise_if_column_does_not_exist(table: Table, col1: str, col2: str) -> None: with pytest.raises(UnknownColumnNameError): diff --git a/tests/safeds/data/tabular/containers/_table/test_split.py b/tests/safeds/data/tabular/containers/_table/test_split.py index f9133381b..214aed46b 100644 --- a/tests/safeds/data/tabular/containers/_table/test_split.py +++ b/tests/safeds/data/tabular/containers/_table/test_split.py @@ -45,5 +45,5 @@ def test_should_split_table(table: Table, result_test_table: Table, result_train def test_should_raise_if_value_not_in_range(percentage_in_first: float) -> None: table = Table({"col1": [1, 2, 1], "col2": [1, 2, 4]}) - with pytest.raises(ValueError, match="the given percentage is not in range"): + with pytest.raises(ValueError, match="The given percentage is not between 0 and 1"): table.split(percentage_in_first) From 005b3c8764ef8ad2213b36c0cd68ea1b36f773c1 Mon Sep 17 00:00:00 2001 From: methr0 Date: Fri, 19 May 2023 11:11:08 +0200 Subject: [PATCH 05/14] check error messages --- .../containers/_table/test_keep_only_columns.py | 2 +- .../containers/_table/test_plot_boxplots.py | 2 +- .../containers/_table/test_plot_lineplot.py | 8 ++++---- .../containers/_table/test_plot_scatterplot.py | 12 ++++++------ .../containers/_table/test_remove_columns.py | 2 +- .../tabular/containers/_table/test_rename.py | 4 ++-- .../containers/_table/test_replace_column.py | 11 ++++++----- .../tabular/containers/_table/test_slice_rows.py | 16 ++++++++-------- .../data/tabular/containers/_table/test_split.py | 2 +- .../containers/_table/test_transform_column.py | 2 +- .../containers/_table/test_transform_table.py | 4 ++-- 11 files changed, 33 insertions(+), 32 deletions(-) diff --git a/tests/safeds/data/tabular/containers/_table/test_keep_only_columns.py b/tests/safeds/data/tabular/containers/_table/test_keep_only_columns.py index a4a1ff723..a38cd6598 100644 --- a/tests/safeds/data/tabular/containers/_table/test_keep_only_columns.py +++ b/tests/safeds/data/tabular/containers/_table/test_keep_only_columns.py @@ -42,5 +42,5 @@ def test_should_keep_only_listed_columns(table: Table, column_names: list[str], def test_should_raise_error_if_column_name_unknown() -> None: table = Table({"A": [1], "B": [2]}) - with pytest.raises(UnknownColumnNameError): + with pytest.raises(UnknownColumnNameError, match=r"Could not find column\(s\) 'C'"): table.keep_only_columns(["C"]) diff --git a/tests/safeds/data/tabular/containers/_table/test_plot_boxplots.py b/tests/safeds/data/tabular/containers/_table/test_plot_boxplots.py index 6a8a31665..2e2cbc217 100644 --- a/tests/safeds/data/tabular/containers/_table/test_plot_boxplots.py +++ b/tests/safeds/data/tabular/containers/_table/test_plot_boxplots.py @@ -32,5 +32,5 @@ def test_should_match_snapshot(table: Table, path: str) -> None: def test_should_raise_if_column_contains_non_numerical_values() -> None: table = Table.from_dict({"A": ["1", "2", "3.5"], "B": ["0.2", "4", "77"]}) - with pytest.raises(NonNumericColumnError): + with pytest.raises(NonNumericColumnError, match=r"Tried to do a numerical operation on one or multiple non numerical Columns: \nThis table contains only non-numerical columns."): table.plot_boxplots() diff --git a/tests/safeds/data/tabular/containers/_table/test_plot_lineplot.py b/tests/safeds/data/tabular/containers/_table/test_plot_lineplot.py index f8f1484aa..e2bf6a952 100644 --- a/tests/safeds/data/tabular/containers/_table/test_plot_lineplot.py +++ b/tests/safeds/data/tabular/containers/_table/test_plot_lineplot.py @@ -17,11 +17,11 @@ def test_should_match_snapshot() -> None: @pytest.mark.parametrize( - ("x", "y"), - [("C", "A"), ("A", "C"), ("C", "D")], + ("x", "y", "error_message"), + [("C", "A", r"Could not find column\(s\) 'C'"), ("A", "C", r"Could not find column\(s\) 'C'"), ("C", "D", r"Could not find column\(s\) 'C, D'")], ids=["x column", "y column", "x and y column"], ) -def test_should_raise_if_column_does_not_exist(x: str, y: str) -> None: +def test_should_raise_if_column_does_not_exist(x: str, y: str, error_message: str) -> None: table = Table({"A": [1, 2, 3], "B": [2, 4, 7]}) - with pytest.raises(UnknownColumnNameError): + with pytest.raises(UnknownColumnNameError, match=error_message): table.plot_lineplot(x, y) diff --git a/tests/safeds/data/tabular/containers/_table/test_plot_scatterplot.py b/tests/safeds/data/tabular/containers/_table/test_plot_scatterplot.py index 4b5e61251..1158c0eab 100644 --- a/tests/safeds/data/tabular/containers/_table/test_plot_scatterplot.py +++ b/tests/safeds/data/tabular/containers/_table/test_plot_scatterplot.py @@ -17,14 +17,14 @@ def test_should_match_snapshot() -> None: @pytest.mark.parametrize( - ("table", "col1", "col2"), + ("table", "col1", "col2", "error_message"), [ - (Table({"A": [1, 2, 3], "B": [2, 4, 7]}), "C", "A"), - (Table({"A": [1, 2, 3], "B": [2, 4, 7]}), "B", "C"), - (Table({"A": [1, 2, 3], "B": [2, 4, 7]}), "C", "D"), + (Table({"A": [1, 2, 3], "B": [2, 4, 7]}), "C", "A", r"Could not find column\(s\) 'C'"), + (Table({"A": [1, 2, 3], "B": [2, 4, 7]}), "B", "C", r"Could not find column\(s\) 'C'"), + (Table({"A": [1, 2, 3], "B": [2, 4, 7]}), "C", "D", r"Could not find column\(s\) 'C, D'"), ], ids=["First argument doesn't exist", "Second argument doesn't exist", "Both arguments do not exist"], ) -def test_should_raise_if_column_does_not_exist(table: Table, col1: str, col2: str) -> None: - with pytest.raises(UnknownColumnNameError): +def test_should_raise_if_column_does_not_exist(table: Table, col1: str, col2: str, error_message: str) -> None: + with pytest.raises(UnknownColumnNameError, match=error_message): table.plot_scatterplot(col1, col2) diff --git a/tests/safeds/data/tabular/containers/_table/test_remove_columns.py b/tests/safeds/data/tabular/containers/_table/test_remove_columns.py index 73cd66088..2ed71334b 100644 --- a/tests/safeds/data/tabular/containers/_table/test_remove_columns.py +++ b/tests/safeds/data/tabular/containers/_table/test_remove_columns.py @@ -19,5 +19,5 @@ def test_should_remove_table_columns(table1: Table, expected: Table, columns: li def test_should_raise_if_column_not_found() -> None: table = Table({"A": [1], "B": [2]}) - with pytest.raises(UnknownColumnNameError): + with pytest.raises(UnknownColumnNameError, match=r"Could not find column\(s\) 'C'"): table.remove_columns(["C"]) diff --git a/tests/safeds/data/tabular/containers/_table/test_rename.py b/tests/safeds/data/tabular/containers/_table/test_rename.py index 97b9fc376..edb7d6d8c 100644 --- a/tests/safeds/data/tabular/containers/_table/test_rename.py +++ b/tests/safeds/data/tabular/containers/_table/test_rename.py @@ -18,11 +18,11 @@ def test_should_rename_column(name_from: str, name_to: str, column_one: str, col def test_should_raise_if_old_column_does_not_exist() -> None: table: Table = Table({"A": [1], "B": [2]}) - with pytest.raises(UnknownColumnNameError): + with pytest.raises(UnknownColumnNameError, match=r"Could not find column\(s\) 'C'"): table.rename_column("C", "D") def test_should_raise_if_new_column_exists_already() -> None: table: Table = Table({"A": [1], "B": [2]}) - with pytest.raises(DuplicateColumnNameError): + with pytest.raises(DuplicateColumnNameError, match=r"Column 'B' already exists."): table.rename_column("A", "B") diff --git a/tests/safeds/data/tabular/containers/_table/test_replace_column.py b/tests/safeds/data/tabular/containers/_table/test_replace_column.py index aeecb77e9..6dfead5dd 100644 --- a/tests/safeds/data/tabular/containers/_table/test_replace_column.py +++ b/tests/safeds/data/tabular/containers/_table/test_replace_column.py @@ -54,11 +54,11 @@ def test_should_replace_column(table: Table, column_name: str, column: Column, e @pytest.mark.parametrize( - ("old_column_name", "column_values", "column_name", "error"), + ("old_column_name", "column_values", "column_name", "error", "error_message"), [ - ("D", ["d", "e", "f"], "C", UnknownColumnNameError), - ("C", ["d", "e", "f"], "B", DuplicateColumnNameError), - ("C", ["d", "e"], "D", ColumnSizeError), + ("D", ["d", "e", "f"], "C", UnknownColumnNameError, r"Could not find column\(s\) 'D'"), + ("C", ["d", "e", "f"], "B", DuplicateColumnNameError, r"Column 'B' already exists."), + ("C", ["d", "e"], "D", ColumnSizeError, r"Expected a column of size 3 but got column of size 2."), ], ids=["UnknownColumnNameError", "DuplicateColumnNameError", "ColumnSizeError"], ) @@ -67,6 +67,7 @@ def test_should_raise_error( column_values: list[str], column_name: str, error: type[Exception], + error_message: str, ) -> None: input_table: Table = Table( { @@ -77,5 +78,5 @@ def test_should_raise_error( ) column = Column(column_name, column_values) - with pytest.raises(error): + with pytest.raises(error, match=error_message): input_table.replace_column(old_column_name, column) diff --git a/tests/safeds/data/tabular/containers/_table/test_slice_rows.py b/tests/safeds/data/tabular/containers/_table/test_slice_rows.py index 17cf6c375..23ce4ed5e 100644 --- a/tests/safeds/data/tabular/containers/_table/test_slice_rows.py +++ b/tests/safeds/data/tabular/containers/_table/test_slice_rows.py @@ -26,17 +26,17 @@ def test_should_slice_rows(table: Table, test_table: Table, second_test_table: T @pytest.mark.parametrize( - ("start", "end", "step"), + ("start", "end", "step", "error_message"), [ - (3, 2, 1), - (4, 0, 1), - (0, 4, 1), - (-4, 0, 1), - (0, -4, 1), + (3, 2, 1, r"There is no element in the range \[3, 2\]"), + (4, 0, 1, r"There is no element in the range \[4, 0\]"), + (0, 4, 1, r"There is no element at index '4'"), + (-4, 0, 1, r"There is no element at index '-4'"), + (0, -4, 1, r"There is no element in the range \[0, -4\]"), ], ) -def test_should_raise_if_index_out_of_bounds(start: int, end: int, step: int) -> None: +def test_should_raise_if_index_out_of_bounds(start: int, end: int, step: int, error_message: str) -> None: table = Table({"col1": [1, 2, 1], "col2": [1, 2, 4]}) - with raises(IndexOutOfBoundsError): + with raises(IndexOutOfBoundsError, match=error_message): table.slice_rows(start, end, step) diff --git a/tests/safeds/data/tabular/containers/_table/test_split.py b/tests/safeds/data/tabular/containers/_table/test_split.py index 214aed46b..281c891de 100644 --- a/tests/safeds/data/tabular/containers/_table/test_split.py +++ b/tests/safeds/data/tabular/containers/_table/test_split.py @@ -45,5 +45,5 @@ def test_should_split_table(table: Table, result_test_table: Table, result_train def test_should_raise_if_value_not_in_range(percentage_in_first: float) -> None: table = Table({"col1": [1, 2, 1], "col2": [1, 2, 4]}) - with pytest.raises(ValueError, match="The given percentage is not between 0 and 1"): + with pytest.raises(ValueError, match=r"The given percentage is not between 0 and 1"): table.split(percentage_in_first) diff --git a/tests/safeds/data/tabular/containers/_table/test_transform_column.py b/tests/safeds/data/tabular/containers/_table/test_transform_column.py index 0707dcae2..6219d9a6b 100644 --- a/tests/safeds/data/tabular/containers/_table/test_transform_column.py +++ b/tests/safeds/data/tabular/containers/_table/test_transform_column.py @@ -28,5 +28,5 @@ def test_should_raise_if_column_not_found() -> None: }, ) - with pytest.raises(UnknownColumnNameError): + with pytest.raises(UnknownColumnNameError, match=r"Could not find column\(s\) 'D'"): input_table.transform_column("D", lambda row: row.get_value("A") * 2) diff --git a/tests/safeds/data/tabular/containers/_table/test_transform_table.py b/tests/safeds/data/tabular/containers/_table/test_transform_table.py index 7d93e4b3d..ebd5687d3 100644 --- a/tests/safeds/data/tabular/containers/_table/test_transform_table.py +++ b/tests/safeds/data/tabular/containers/_table/test_transform_table.py @@ -98,7 +98,7 @@ def test_should_raise_if_column_not_found() -> None: }, ) - with pytest.raises(UnknownColumnNameError): + with pytest.raises(UnknownColumnNameError, match=r"Could not find column\(s\) 'col1'"): table_to_transform.transform_table(transformer) @@ -111,5 +111,5 @@ def test_should_raise_if_not_fitted() -> None: transformer = OneHotEncoder() - with pytest.raises(TransformerNotFittedError): + with pytest.raises(TransformerNotFittedError, match=r"The transformer has not been fitted yet."): table.transform_table(transformer) From 188a4032b103bae988298c3ec398b5c12fe5c053 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20Gr=C3=A9us?= Date: Fri, 19 May 2023 11:15:19 +0200 Subject: [PATCH 06/14] test: Tests from `Table` now assert the exact error messages --- src/safeds/data/tabular/containers/_table.py | 2 ++ src/safeds/exceptions/_data.py | 2 +- .../tabular/containers/_table/test_add_column.py | 4 ++-- .../containers/_table/test_add_columns.py | 14 ++++++++------ .../tabular/containers/_table/test_add_row.py | 2 +- .../tabular/containers/_table/test_add_rows.py | 2 +- .../tabular/containers/_table/test_dataframe.py | 2 +- .../containers/_table/test_filter_rows.py | 2 +- .../containers/_table/test_from_columns.py | 4 ++-- .../containers/_table/test_from_csv_file.py | 16 ++++++++-------- .../tabular/containers/_table/test_from_dict.py | 2 +- .../containers/_table/test_from_excel_file.py | 10 +++++----- .../containers/_table/test_from_json_file.py | 16 ++++++++-------- .../tabular/containers/_table/test_from_rows.py | 2 +- .../tabular/containers/_table/test_get_column.py | 2 +- .../tabular/containers/_table/test_get_row.py | 8 ++++---- .../data/tabular/containers/_table/test_init.py | 2 +- .../_table/test_inverse_transform_table.py | 2 +- .../containers/_table/test_to_csv_file.py | 2 +- .../containers/_table/test_to_excel_file.py | 2 +- .../containers/_table/test_to_json_file.py | 2 +- .../containers/_table/test_transform_table.py | 2 +- 22 files changed, 53 insertions(+), 49 deletions(-) diff --git a/src/safeds/data/tabular/containers/_table.py b/src/safeds/data/tabular/containers/_table.py index 878ceb356..03de9bacd 100644 --- a/src/safeds/data/tabular/containers/_table.py +++ b/src/safeds/data/tabular/containers/_table.py @@ -1121,6 +1121,8 @@ def tag_columns(self, target_name: str, feature_names: list[str] | None = None) ValueError If no feature columns are specified. """ + from ._tagged_table import TaggedTable + return TaggedTable._from_table(self, target_name, feature_names) def transform_column(self, name: str, transformer: Callable[[Row], Any]) -> Table: diff --git a/src/safeds/exceptions/_data.py b/src/safeds/exceptions/_data.py index dbdfe29e7..db62c62f5 100644 --- a/src/safeds/exceptions/_data.py +++ b/src/safeds/exceptions/_data.py @@ -103,4 +103,4 @@ class WrongFileExtensionError(Exception): """Exception raised when the file has the wrong file extension.""" def __init__(self, file: str | Path, file_extension: str | list[str]) -> None: - super().__init__(f"The file {file} has a wrong file extension. Please provide a file with the following extension(s): [{file_extension}]") + super().__init__(f"The file {file} has a wrong file extension. Please provide a file with the following extension(s): {file_extension}") diff --git a/tests/safeds/data/tabular/containers/_table/test_add_column.py b/tests/safeds/data/tabular/containers/_table/test_add_column.py index 111be80c6..26958e6a6 100644 --- a/tests/safeds/data/tabular/containers/_table/test_add_column.py +++ b/tests/safeds/data/tabular/containers/_table/test_add_column.py @@ -26,11 +26,11 @@ def test_should_add_column(table1: Table, column: Column, expected: Table) -> No def test_should_raise_error_if_column_name_exists() -> None: table1 = Table({"col1": [1, 2, 1], "col2": [1, 2, 4]}) - with pytest.raises(DuplicateColumnNameError): + with pytest.raises(DuplicateColumnNameError, match=r"Column 'col1' already exists."): table1.add_column(Column("col1", ["a", "b", "c"])) def test_should_raise_error_if_column_size_invalid() -> None: table1 = Table({"col1": [1, 2, 1], "col2": [1, 2, 4]}) - with pytest.raises(ColumnSizeError): + with pytest.raises(ColumnSizeError, match=r"Expected a column of size 3 but got column of size 4."): table1.add_column(Column("col3", ["a", "b", "c", "d"])) diff --git a/tests/safeds/data/tabular/containers/_table/test_add_columns.py b/tests/safeds/data/tabular/containers/_table/test_add_columns.py index 6647e6492..7a5d65676 100644 --- a/tests/safeds/data/tabular/containers/_table/test_add_columns.py +++ b/tests/safeds/data/tabular/containers/_table/test_add_columns.py @@ -36,30 +36,32 @@ def test_should_add_columns_from_table(table1: Table, table2: Table, expected: T @pytest.mark.parametrize( - ("table", "columns"), + ("table", "columns", "error_message_regex"), [ ( Table({"col1": [1, 2, 1], "col2": [1, 2, 4]}), [Column("col3", ["a", "b", "c", "d"]), Column("col4", ["e", "f", "g", "h"])], + r"Expected a column of size 3 but got column of size 4.", ), ], ids=["Two Columns with too many values"], ) -def test_should_raise_error_if_column_size_invalid(table: Table, columns: list[Column] | Table) -> None: - with pytest.raises(ColumnSizeError): +def test_should_raise_error_if_column_size_invalid(table: Table, columns: list[Column] | Table, error_message_regex: str) -> None: + with pytest.raises(ColumnSizeError, match=error_message_regex): table.add_columns(columns) @pytest.mark.parametrize( - ("table", "columns"), + ("table", "columns", "error_message_regex"), [ ( Table({"col1": [1, 2, 1], "col2": [1, 2, 4]}), [Column("col2", ["a", "b", "c"]), Column("col3", [2, 3, 4])], + r"Column 'col2' already exists.", ), ], ids=["Column already exists"], ) -def test_should_raise_error_if_column_name_in_result_column(table: Table, columns: list[Column] | Table) -> None: - with pytest.raises(DuplicateColumnNameError): +def test_should_raise_error_if_column_name_in_result_column(table: Table, columns: list[Column] | Table, error_message_regex: str) -> None: + with pytest.raises(DuplicateColumnNameError, match=error_message_regex): table.add_columns(columns) diff --git a/tests/safeds/data/tabular/containers/_table/test_add_row.py b/tests/safeds/data/tabular/containers/_table/test_add_row.py index a0a222995..e75e96ebb 100644 --- a/tests/safeds/data/tabular/containers/_table/test_add_row.py +++ b/tests/safeds/data/tabular/containers/_table/test_add_row.py @@ -21,5 +21,5 @@ def test_should_add_row(table: Table, row: Row) -> None: def test_should_raise_error_if_row_schema_invalid() -> None: table1 = Table({"col1": [1, 2, 1], "col2": [1, 2, 4]}) row = Row({"col1": 5, "col2": "Hallo"}) - with raises(SchemaMismatchError): + with raises(SchemaMismatchError, match=r"Failed because at least two schemas didn't match."): table1.add_row(row) diff --git a/tests/safeds/data/tabular/containers/_table/test_add_rows.py b/tests/safeds/data/tabular/containers/_table/test_add_rows.py index 01e918b03..88d427784 100644 --- a/tests/safeds/data/tabular/containers/_table/test_add_rows.py +++ b/tests/safeds/data/tabular/containers/_table/test_add_rows.py @@ -38,5 +38,5 @@ def test_should_add_rows_from_table(table1: Table, table2: Table, expected: Tabl def test_should_raise_error_if_row_schema_invalid() -> None: table1 = Table({"col1": [1, 2, 1], "col2": [1, 2, 4]}) row = [Row({"col1": 2, "col2": 4}), Row({"col1": 5, "col2": "Hallo"})] - with pytest.raises(SchemaMismatchError): + with pytest.raises(SchemaMismatchError, match=r"Failed because at least two schemas didn't match."): table1.add_rows(row) diff --git a/tests/safeds/data/tabular/containers/_table/test_dataframe.py b/tests/safeds/data/tabular/containers/_table/test_dataframe.py index 3eabb3237..e1776f757 100644 --- a/tests/safeds/data/tabular/containers/_table/test_dataframe.py +++ b/tests/safeds/data/tabular/containers/_table/test_dataframe.py @@ -23,5 +23,5 @@ def test_should_restore_table_from_exchange_object(table: Table) -> None: def test_should_raise_error_if_allow_copy_is_false() -> None: table = Table() - with pytest.raises(NotImplementedError, match="`allow_copy` must be True"): + with pytest.raises(NotImplementedError, match=r"For the moment we need to copy the data, so `allow_copy` must be True."): table.__dataframe__(allow_copy=False) diff --git a/tests/safeds/data/tabular/containers/_table/test_filter_rows.py b/tests/safeds/data/tabular/containers/_table/test_filter_rows.py index 2a777f2b3..5d4d40803 100644 --- a/tests/safeds/data/tabular/containers/_table/test_filter_rows.py +++ b/tests/safeds/data/tabular/containers/_table/test_filter_rows.py @@ -30,5 +30,5 @@ def test_should_filter_rows(table1: Table, filter_column: str, filter_value: Col # noinspection PyTypeChecker def test_should_raise_error_if_column_type_invalid() -> None: table = Table({"col1": [1, 2, 3], "col2": [1, 1, 4]}) - with pytest.raises(TypeError): + with pytest.raises(TypeError, match=r"'Series' object is not callable"): table.filter_rows(table.get_column("col1")._data > table.get_column("col2")._data) diff --git a/tests/safeds/data/tabular/containers/_table/test_from_columns.py b/tests/safeds/data/tabular/containers/_table/test_from_columns.py index 6f283124c..e2226aeed 100644 --- a/tests/safeds/data/tabular/containers/_table/test_from_columns.py +++ b/tests/safeds/data/tabular/containers/_table/test_from_columns.py @@ -27,10 +27,10 @@ def test_should_create_table_from_list_of_columns(columns: list[Column], expecte def test_should_raise_error_if_column_length_mismatch() -> None: - with pytest.raises(ColumnLengthMismatchError): + with pytest.raises(ColumnLengthMismatchError, match=r"The length of at least one column differs: \ncol1: 3\ncol2: 4"): Table.from_columns([Column("col1", [5, 2, 3]), Column("col2", [5, 3, 4, 1])]) def test_should_raise_error_if_duplicate_column_name() -> None: - with pytest.raises(DuplicateColumnNameError): + with pytest.raises(DuplicateColumnNameError, match=r"Column 'col1' already exists."): Table.from_columns([Column("col1", [5, 2, 3]), Column("col1", [5, 3, 4])]) diff --git a/tests/safeds/data/tabular/containers/_table/test_from_csv_file.py b/tests/safeds/data/tabular/containers/_table/test_from_csv_file.py index fa7da264b..7a16f5691 100644 --- a/tests/safeds/data/tabular/containers/_table/test_from_csv_file.py +++ b/tests/safeds/data/tabular/containers/_table/test_from_csv_file.py @@ -15,20 +15,20 @@ def test_should_create_table_from_csv_file(path: str | Path) -> None: @pytest.mark.parametrize( - "path", - ["test_table_from_csv_file_invalid.csv", Path("test_table_from_csv_file_invalid.csv")], + ("path", "expected_error_message"), + [("test_table_from_csv_file_invalid.csv", r"test_table_from_csv_file_invalid.csv\" does not exist"), (Path("test_table_from_csv_file_invalid.csv"), r"test_table_from_csv_file_invalid.csv\" does not exist")], ids=["by String", "by path"], ) -def test_should_raise_error_if_file_not_found(path: str | Path) -> None: - with pytest.raises(FileNotFoundError): +def test_should_raise_error_if_file_not_found(path: str | Path, expected_error_message: str) -> None: + with pytest.raises(FileNotFoundError, match=expected_error_message): Table.from_csv_file(resolve_resource_path(path)) @pytest.mark.parametrize( - "path", - ["invalid_file_extension.file_extension", Path("invalid_file_extension.file_extension")], + ("path", "expected_error_message"), + [("invalid_file_extension.file_extension", r"invalid_file_extension.file_extension has a wrong file extension. Please provide a file with the following extension\(s\): .csv"), (Path("invalid_file_extension.file_extension"), r"invalid_file_extension.file_extension has a wrong file extension. Please provide a file with the following extension\(s\): .csv")], ids=["by String", "by path"], ) -def test_should_raise_error_if_wrong_file_extension(path: str | Path) -> None: - with pytest.raises(WrongFileExtensionError): +def test_should_raise_error_if_wrong_file_extension(path: str | Path, expected_error_message: str) -> None: + with pytest.raises(WrongFileExtensionError, match=expected_error_message): Table.from_csv_file(resolve_resource_path(path)) diff --git a/tests/safeds/data/tabular/containers/_table/test_from_dict.py b/tests/safeds/data/tabular/containers/_table/test_from_dict.py index 724b4ad68..fc894e3ea 100644 --- a/tests/safeds/data/tabular/containers/_table/test_from_dict.py +++ b/tests/safeds/data/tabular/containers/_table/test_from_dict.py @@ -32,5 +32,5 @@ def test_should_create_table_from_dict(data: dict[str, list[Any]], expected: Tab def test_should_raise_error_if_columns_have_different_lengths() -> None: - with pytest.raises(ColumnLengthMismatchError): + with pytest.raises(ColumnLengthMismatchError, match=r"The length of at least one column differs: \na: 2\nb: 1"): Table.from_dict({"a": [1, 2], "b": [3]}) diff --git a/tests/safeds/data/tabular/containers/_table/test_from_excel_file.py b/tests/safeds/data/tabular/containers/_table/test_from_excel_file.py index 1a09bb81c..d6d205611 100644 --- a/tests/safeds/data/tabular/containers/_table/test_from_excel_file.py +++ b/tests/safeds/data/tabular/containers/_table/test_from_excel_file.py @@ -37,15 +37,15 @@ def test_should_create_table_from_excel_file(path: str | Path, expected: Table) def test_should_raise_if_file_not_found() -> None: - with pytest.raises(FileNotFoundError): + with pytest.raises(FileNotFoundError, match=r"test_table_from_excel_file_invalid.xls\" does not exist"): Table.from_excel_file(resolve_resource_path("test_table_from_excel_file_invalid.xls")) @pytest.mark.parametrize( - "path", - ["invalid_file_extension.file_extension", Path("invalid_file_extension.file_extension")], + ("path", "expected_error_message"), + [("invalid_file_extension.file_extension", r"invalid_file_extension.file_extension has a wrong file extension. Please provide a file with the following extension\(s\): \['.xls', '.xlsx', '.xlsm', '.xlsb', '.odf', '.ods', '.odt'\]"), (Path("invalid_file_extension.file_extension"), r"invalid_file_extension.file_extension has a wrong file extension. Please provide a file with the following extension\(s\): \['.xls', '.xlsx', '.xlsm', '.xlsb', '.odf', '.ods', '.odt'\]")], ids=["by String", "by path"], ) -def test_should_raise_error_if_wrong_file_extension(path: str | Path) -> None: - with pytest.raises(WrongFileExtensionError): +def test_should_raise_error_if_wrong_file_extension(path: str | Path, expected_error_message: str) -> None: + with pytest.raises(WrongFileExtensionError, match=expected_error_message): Table.from_excel_file(resolve_resource_path(path)) diff --git a/tests/safeds/data/tabular/containers/_table/test_from_json_file.py b/tests/safeds/data/tabular/containers/_table/test_from_json_file.py index d986d571a..755b2e8dc 100644 --- a/tests/safeds/data/tabular/containers/_table/test_from_json_file.py +++ b/tests/safeds/data/tabular/containers/_table/test_from_json_file.py @@ -15,20 +15,20 @@ def test_should_create_table_from_json_file(path: str | Path) -> None: @pytest.mark.parametrize( - "path", - ["test_table_from_json_file_invalid.json", Path("test_table_from_json_file_invalid.json")], + ("path", "expected_error_message"), + [("test_table_from_json_file_invalid.json", r"test_table_from_json_file_invalid.json\" does not exist"), (Path("test_table_from_json_file_invalid.json"), r"test_table_from_json_file_invalid.json\" does not exist")], ids=["by string", "by path"], ) -def test_should_raise_error_if_file_not_found(path: str | Path) -> None: - with pytest.raises(FileNotFoundError): +def test_should_raise_error_if_file_not_found(path: str | Path, expected_error_message: str) -> None: + with pytest.raises(FileNotFoundError, match=expected_error_message): Table.from_json_file(resolve_resource_path(path)) @pytest.mark.parametrize( - "path", - ["invalid_file_extension.file_extension", Path("invalid_file_extension.file_extension")], + ("path", "expected_error_message"), + [("invalid_file_extension.file_extension", r"invalid_file_extension.file_extension has a wrong file extension. Please provide a file with the following extension\(s\): .json"), (Path("invalid_file_extension.file_extension"), r"invalid_file_extension.file_extension has a wrong file extension. Please provide a file with the following extension\(s\): .json")], ids=["by String", "by path"], ) -def test_should_raise_error_if_wrong_file_extension(path: str | Path) -> None: - with pytest.raises(WrongFileExtensionError): +def test_should_raise_error_if_wrong_file_extension(path: str | Path, expected_error_message: str) -> None: + with pytest.raises(WrongFileExtensionError, match=expected_error_message): Table.from_json_file(resolve_resource_path(path)) diff --git a/tests/safeds/data/tabular/containers/_table/test_from_rows.py b/tests/safeds/data/tabular/containers/_table/test_from_rows.py index 0ae2d7d31..56c8a296a 100644 --- a/tests/safeds/data/tabular/containers/_table/test_from_rows.py +++ b/tests/safeds/data/tabular/containers/_table/test_from_rows.py @@ -33,5 +33,5 @@ def test_should_create_table_from_rows(rows: list[Row], expected: Table) -> None def test_should_raise_error_if_mismatching_schema() -> None: rows = [Row({"A": 1, "B": 2}), Row({"A": 2, "B": "a"})] - with pytest.raises(SchemaMismatchError): + with pytest.raises(SchemaMismatchError, match=r"Failed because at least two schemas didn't match."): Table.from_rows(rows) diff --git a/tests/safeds/data/tabular/containers/_table/test_get_column.py b/tests/safeds/data/tabular/containers/_table/test_get_column.py index 7dccc4adc..f5eccad42 100644 --- a/tests/safeds/data/tabular/containers/_table/test_get_column.py +++ b/tests/safeds/data/tabular/containers/_table/test_get_column.py @@ -16,5 +16,5 @@ def test_should_get_column(table1: Table, expected: Column) -> None: def test_should_raise_error_if_column_name_unknown() -> None: table = Table({"col1": ["col1_1"], "col2": ["col2_1"]}) - with pytest.raises(UnknownColumnNameError): + with pytest.raises(UnknownColumnNameError, match=r"Could not find column\(s\) 'col3'"): table.get_column("col3") diff --git a/tests/safeds/data/tabular/containers/_table/test_get_row.py b/tests/safeds/data/tabular/containers/_table/test_get_row.py index 2c5087785..2e1f85fa8 100644 --- a/tests/safeds/data/tabular/containers/_table/test_get_row.py +++ b/tests/safeds/data/tabular/containers/_table/test_get_row.py @@ -15,11 +15,11 @@ def test_should_get_row(table1: Table, expected: Row) -> None: @pytest.mark.parametrize( - "index", - [-1, 5], + ("index", "expected_error_message"), + [(-1, r"There is no element at index '-1'."), (5, r"There is no element at index '5'.")], ids=["<0", "too high"], ) -def test_should_raise_error_if_index_out_of_bounds(index: int) -> None: +def test_should_raise_error_if_index_out_of_bounds(index: int, expected_error_message: str) -> None: table = Table({"A": [1], "B": [2]}) - with pytest.raises(IndexOutOfBoundsError): + with pytest.raises(IndexOutOfBoundsError, match=expected_error_message): table.get_row(index) diff --git a/tests/safeds/data/tabular/containers/_table/test_init.py b/tests/safeds/data/tabular/containers/_table/test_init.py index aa5265869..0f7895715 100644 --- a/tests/safeds/data/tabular/containers/_table/test_init.py +++ b/tests/safeds/data/tabular/containers/_table/test_init.py @@ -22,5 +22,5 @@ def test_should_infer_the_schema(table: Table, expected: Schema) -> None: def test_should_raise_error_if_columns_have_different_lengths() -> None: - with pytest.raises(ColumnLengthMismatchError): + with pytest.raises(ColumnLengthMismatchError, match=r"The length of at least one column differs: \na: 2\nb: 1"): Table({"a": [1, 2], "b": [3]}) diff --git a/tests/safeds/data/tabular/containers/_table/test_inverse_transform_table.py b/tests/safeds/data/tabular/containers/_table/test_inverse_transform_table.py index bb0e151ad..cdcc98153 100644 --- a/tests/safeds/data/tabular/containers/_table/test_inverse_transform_table.py +++ b/tests/safeds/data/tabular/containers/_table/test_inverse_transform_table.py @@ -115,5 +115,5 @@ def test_should_raise_error_if_not_fitted() -> None: transformer = OneHotEncoder() - with pytest.raises(TransformerNotFittedError): + with pytest.raises(TransformerNotFittedError, match=r"The transformer has not been fitted yet."): table.inverse_transform_table(transformer) diff --git a/tests/safeds/data/tabular/containers/_table/test_to_csv_file.py b/tests/safeds/data/tabular/containers/_table/test_to_csv_file.py index 9fb60739a..4b2a590c2 100644 --- a/tests/safeds/data/tabular/containers/_table/test_to_csv_file.py +++ b/tests/safeds/data/tabular/containers/_table/test_to_csv_file.py @@ -34,5 +34,5 @@ def test_should_raise_error_if_wrong_file_extension() -> None: with NamedTemporaryFile(suffix=".invalid_file_extension") as tmp_table_file: tmp_table_file.close() with Path(tmp_table_file.name).open("w", encoding="utf-8") as tmp_file: - with pytest.raises(WrongFileExtensionError): + with pytest.raises(WrongFileExtensionError, match=r".invalid_file_extension has a wrong file extension. Please provide a file with the following extension\(s\): .csv"): table.to_csv_file(Path(tmp_file.name)) diff --git a/tests/safeds/data/tabular/containers/_table/test_to_excel_file.py b/tests/safeds/data/tabular/containers/_table/test_to_excel_file.py index af61f286a..71d626ceb 100644 --- a/tests/safeds/data/tabular/containers/_table/test_to_excel_file.py +++ b/tests/safeds/data/tabular/containers/_table/test_to_excel_file.py @@ -34,5 +34,5 @@ def test_should_raise_error_if_wrong_file_extension() -> None: with NamedTemporaryFile(suffix=".invalid_file_extension") as tmp_table_file: tmp_table_file.close() with Path(tmp_table_file.name).open("w", encoding="utf-8") as tmp_file: - with pytest.raises(WrongFileExtensionError): + with pytest.raises(WrongFileExtensionError, match=r".invalid_file_extension has a wrong file extension. Please provide a file with the following extension\(s\): \['.xls', '.xlsx', '.xlsm', '.xlsb', '.odf', '.ods', '.odt'\]"): table.to_excel_file(Path(tmp_file.name)) diff --git a/tests/safeds/data/tabular/containers/_table/test_to_json_file.py b/tests/safeds/data/tabular/containers/_table/test_to_json_file.py index 24efce050..62bb9c76d 100644 --- a/tests/safeds/data/tabular/containers/_table/test_to_json_file.py +++ b/tests/safeds/data/tabular/containers/_table/test_to_json_file.py @@ -34,5 +34,5 @@ def test_should_raise_error_if_wrong_file_extension() -> None: with NamedTemporaryFile(suffix=".invalid_file_extension") as tmp_table_file: tmp_table_file.close() with Path(tmp_table_file.name).open("w", encoding="utf-8") as tmp_file: - with pytest.raises(WrongFileExtensionError): + with pytest.raises(WrongFileExtensionError, match=r".invalid_file_extension has a wrong file extension. Please provide a file with the following extension\(s\): .json"): table.to_json_file(Path(tmp_file.name)) diff --git a/tests/safeds/data/tabular/containers/_table/test_transform_table.py b/tests/safeds/data/tabular/containers/_table/test_transform_table.py index 7d93e4b3d..5d704a740 100644 --- a/tests/safeds/data/tabular/containers/_table/test_transform_table.py +++ b/tests/safeds/data/tabular/containers/_table/test_transform_table.py @@ -98,7 +98,7 @@ def test_should_raise_if_column_not_found() -> None: }, ) - with pytest.raises(UnknownColumnNameError): + with pytest.raises(UnknownColumnNameError, match=r"Could not find column\(s\) 'col1'"): table_to_transform.transform_table(transformer) From ba2858adcad08e9aac9efdce864c8053a77c4ee5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20Gr=C3=A9us?= Date: Fri, 19 May 2023 11:25:37 +0200 Subject: [PATCH 07/14] refactor: Fixed RUFF Linter problems --- src/safeds/data/tabular/containers/_table.py | 3 ++- src/safeds/exceptions/_data.py | 5 ++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/safeds/data/tabular/containers/_table.py b/src/safeds/data/tabular/containers/_table.py index 03de9bacd..1df6b1ec4 100644 --- a/src/safeds/data/tabular/containers/_table.py +++ b/src/safeds/data/tabular/containers/_table.py @@ -108,6 +108,7 @@ def from_csv_file(path: str | Path) -> Table: def from_excel_file(path: str | Path) -> Table: """ Read data from an Excel file into a table. + Valid file extensions are `.xls`, '.xlsx', `.xlsm`, `.xlsb`, `.odf`, `.ods` and `.odt`. Parameters @@ -1453,8 +1454,8 @@ def to_csv_file(self, path: str | Path) -> None: def to_excel_file(self, path: str | Path) -> None: """ Write the data from the table into an Excel file. - Valid file extensions are `.xls`, '.xlsx', `.xlsm`, `.xlsb`, `.odf`, `.ods` and `.odt`. + Valid file extensions are `.xls`, '.xlsx', `.xlsm`, `.xlsb`, `.odf`, `.ods` and `.odt`. If the file and/or the directories do not exist, they will be created. If the file already exists, it will be overwritten. diff --git a/src/safeds/exceptions/_data.py b/src/safeds/exceptions/_data.py index db62c62f5..0a677046b 100644 --- a/src/safeds/exceptions/_data.py +++ b/src/safeds/exceptions/_data.py @@ -1,6 +1,9 @@ from __future__ import annotations -from pathlib import Path +from typing import TYPE_CHECKING + +if TYPE_CHECKING: + from pathlib import Path class UnknownColumnNameError(KeyError): From 150e41759e4cfed24b1911030795003fc7672fb9 Mon Sep 17 00:00:00 2001 From: megalinter-bot <129584137+megalinter-bot@users.noreply.github.com> Date: Fri, 19 May 2023 09:27:19 +0000 Subject: [PATCH 08/14] style: apply automated linter fixes --- src/safeds/data/tabular/containers/_table.py | 12 +++++++--- src/safeds/exceptions/_data.py | 5 ++++- .../containers/_table/test_add_columns.py | 8 +++++-- .../containers/_table/test_dataframe.py | 4 +++- .../containers/_table/test_from_columns.py | 4 +++- .../containers/_table/test_from_csv_file.py | 22 +++++++++++++++++-- .../containers/_table/test_from_excel_file.py | 17 +++++++++++++- .../containers/_table/test_from_json_file.py | 22 +++++++++++++++++-- .../containers/_table/test_plot_boxplots.py | 8 ++++++- .../containers/_table/test_plot_lineplot.py | 6 ++++- .../containers/_table/test_slice_rows.py | 1 - .../tabular/containers/_table/test_split.py | 12 +++++----- .../containers/_table/test_to_csv_file.py | 12 ++++++---- .../containers/_table/test_to_excel_file.py | 12 ++++++---- .../containers/_table/test_to_json_file.py | 12 ++++++---- 15 files changed, 124 insertions(+), 33 deletions(-) diff --git a/src/safeds/data/tabular/containers/_table.py b/src/safeds/data/tabular/containers/_table.py index 1df6b1ec4..10e77e2c1 100644 --- a/src/safeds/data/tabular/containers/_table.py +++ b/src/safeds/data/tabular/containers/_table.py @@ -214,7 +214,7 @@ def from_columns(columns: list[Column]) -> Table: If multiple columns have the same name. """ dataframe: DataFrame = pd.DataFrame() - column_names = list() + column_names = [] for column in columns: if column._data.size != columns[0]._data.size: @@ -1284,7 +1284,10 @@ def plot_lineplot(self, x_column_name: str, y_column_name: str) -> Image: If either of the columns do not exist. """ if not self.has_column(x_column_name) or not self.has_column(y_column_name): - raise UnknownColumnNameError(([x_column_name] if not self.has_column(x_column_name) else []) + ([y_column_name] if not self.has_column(y_column_name) else [])) + raise UnknownColumnNameError( + ([x_column_name] if not self.has_column(x_column_name) else []) + + ([y_column_name] if not self.has_column(y_column_name) else []), + ) fig = plt.figure() ax = sns.lineplot( @@ -1329,7 +1332,10 @@ def plot_scatterplot(self, x_column_name: str, y_column_name: str) -> Image: If either of the columns do not exist. """ if not self.has_column(x_column_name) or not self.has_column(y_column_name): - raise UnknownColumnNameError(([x_column_name] if not self.has_column(x_column_name) else []) + ([y_column_name] if not self.has_column(y_column_name) else [])) + raise UnknownColumnNameError( + ([x_column_name] if not self.has_column(x_column_name) else []) + + ([y_column_name] if not self.has_column(y_column_name) else []), + ) fig = plt.figure() ax = sns.scatterplot( diff --git a/src/safeds/exceptions/_data.py b/src/safeds/exceptions/_data.py index 0a677046b..19a68d3d2 100644 --- a/src/safeds/exceptions/_data.py +++ b/src/safeds/exceptions/_data.py @@ -106,4 +106,7 @@ class WrongFileExtensionError(Exception): """Exception raised when the file has the wrong file extension.""" def __init__(self, file: str | Path, file_extension: str | list[str]) -> None: - super().__init__(f"The file {file} has a wrong file extension. Please provide a file with the following extension(s): {file_extension}") + super().__init__( + f"The file {file} has a wrong file extension. Please provide a file with the following extension(s):" + f" {file_extension}", + ) diff --git a/tests/safeds/data/tabular/containers/_table/test_add_columns.py b/tests/safeds/data/tabular/containers/_table/test_add_columns.py index 7a5d65676..238a4fb03 100644 --- a/tests/safeds/data/tabular/containers/_table/test_add_columns.py +++ b/tests/safeds/data/tabular/containers/_table/test_add_columns.py @@ -46,7 +46,9 @@ def test_should_add_columns_from_table(table1: Table, table2: Table, expected: T ], ids=["Two Columns with too many values"], ) -def test_should_raise_error_if_column_size_invalid(table: Table, columns: list[Column] | Table, error_message_regex: str) -> None: +def test_should_raise_error_if_column_size_invalid( + table: Table, columns: list[Column] | Table, error_message_regex: str, +) -> None: with pytest.raises(ColumnSizeError, match=error_message_regex): table.add_columns(columns) @@ -62,6 +64,8 @@ def test_should_raise_error_if_column_size_invalid(table: Table, columns: list[C ], ids=["Column already exists"], ) -def test_should_raise_error_if_column_name_in_result_column(table: Table, columns: list[Column] | Table, error_message_regex: str) -> None: +def test_should_raise_error_if_column_name_in_result_column( + table: Table, columns: list[Column] | Table, error_message_regex: str, +) -> None: with pytest.raises(DuplicateColumnNameError, match=error_message_regex): table.add_columns(columns) diff --git a/tests/safeds/data/tabular/containers/_table/test_dataframe.py b/tests/safeds/data/tabular/containers/_table/test_dataframe.py index e1776f757..33522296f 100644 --- a/tests/safeds/data/tabular/containers/_table/test_dataframe.py +++ b/tests/safeds/data/tabular/containers/_table/test_dataframe.py @@ -23,5 +23,7 @@ def test_should_restore_table_from_exchange_object(table: Table) -> None: def test_should_raise_error_if_allow_copy_is_false() -> None: table = Table() - with pytest.raises(NotImplementedError, match=r"For the moment we need to copy the data, so `allow_copy` must be True."): + with pytest.raises( + NotImplementedError, match=r"For the moment we need to copy the data, so `allow_copy` must be True.", + ): table.__dataframe__(allow_copy=False) diff --git a/tests/safeds/data/tabular/containers/_table/test_from_columns.py b/tests/safeds/data/tabular/containers/_table/test_from_columns.py index e2226aeed..23bd12df8 100644 --- a/tests/safeds/data/tabular/containers/_table/test_from_columns.py +++ b/tests/safeds/data/tabular/containers/_table/test_from_columns.py @@ -27,7 +27,9 @@ def test_should_create_table_from_list_of_columns(columns: list[Column], expecte def test_should_raise_error_if_column_length_mismatch() -> None: - with pytest.raises(ColumnLengthMismatchError, match=r"The length of at least one column differs: \ncol1: 3\ncol2: 4"): + with pytest.raises( + ColumnLengthMismatchError, match=r"The length of at least one column differs: \ncol1: 3\ncol2: 4", + ): Table.from_columns([Column("col1", [5, 2, 3]), Column("col2", [5, 3, 4, 1])]) diff --git a/tests/safeds/data/tabular/containers/_table/test_from_csv_file.py b/tests/safeds/data/tabular/containers/_table/test_from_csv_file.py index 7a16f5691..e8878e969 100644 --- a/tests/safeds/data/tabular/containers/_table/test_from_csv_file.py +++ b/tests/safeds/data/tabular/containers/_table/test_from_csv_file.py @@ -16,7 +16,10 @@ def test_should_create_table_from_csv_file(path: str | Path) -> None: @pytest.mark.parametrize( ("path", "expected_error_message"), - [("test_table_from_csv_file_invalid.csv", r"test_table_from_csv_file_invalid.csv\" does not exist"), (Path("test_table_from_csv_file_invalid.csv"), r"test_table_from_csv_file_invalid.csv\" does not exist")], + [ + ("test_table_from_csv_file_invalid.csv", r"test_table_from_csv_file_invalid.csv\" does not exist"), + (Path("test_table_from_csv_file_invalid.csv"), r"test_table_from_csv_file_invalid.csv\" does not exist"), + ], ids=["by String", "by path"], ) def test_should_raise_error_if_file_not_found(path: str | Path, expected_error_message: str) -> None: @@ -26,7 +29,22 @@ def test_should_raise_error_if_file_not_found(path: str | Path, expected_error_m @pytest.mark.parametrize( ("path", "expected_error_message"), - [("invalid_file_extension.file_extension", r"invalid_file_extension.file_extension has a wrong file extension. Please provide a file with the following extension\(s\): .csv"), (Path("invalid_file_extension.file_extension"), r"invalid_file_extension.file_extension has a wrong file extension. Please provide a file with the following extension\(s\): .csv")], + [ + ( + "invalid_file_extension.file_extension", + ( + r"invalid_file_extension.file_extension has a wrong file extension. Please provide a file with the" + r" following extension\(s\): .csv" + ), + ), + ( + Path("invalid_file_extension.file_extension"), + ( + r"invalid_file_extension.file_extension has a wrong file extension. Please provide a file with the" + r" following extension\(s\): .csv" + ), + ), + ], ids=["by String", "by path"], ) def test_should_raise_error_if_wrong_file_extension(path: str | Path, expected_error_message: str) -> None: diff --git a/tests/safeds/data/tabular/containers/_table/test_from_excel_file.py b/tests/safeds/data/tabular/containers/_table/test_from_excel_file.py index d6d205611..f9c0b72f9 100644 --- a/tests/safeds/data/tabular/containers/_table/test_from_excel_file.py +++ b/tests/safeds/data/tabular/containers/_table/test_from_excel_file.py @@ -43,7 +43,22 @@ def test_should_raise_if_file_not_found() -> None: @pytest.mark.parametrize( ("path", "expected_error_message"), - [("invalid_file_extension.file_extension", r"invalid_file_extension.file_extension has a wrong file extension. Please provide a file with the following extension\(s\): \['.xls', '.xlsx', '.xlsm', '.xlsb', '.odf', '.ods', '.odt'\]"), (Path("invalid_file_extension.file_extension"), r"invalid_file_extension.file_extension has a wrong file extension. Please provide a file with the following extension\(s\): \['.xls', '.xlsx', '.xlsm', '.xlsb', '.odf', '.ods', '.odt'\]")], + [ + ( + "invalid_file_extension.file_extension", + ( + r"invalid_file_extension.file_extension has a wrong file extension. Please provide a file with the" + r" following extension\(s\): \['.xls', '.xlsx', '.xlsm', '.xlsb', '.odf', '.ods', '.odt'\]" + ), + ), + ( + Path("invalid_file_extension.file_extension"), + ( + r"invalid_file_extension.file_extension has a wrong file extension. Please provide a file with the" + r" following extension\(s\): \['.xls', '.xlsx', '.xlsm', '.xlsb', '.odf', '.ods', '.odt'\]" + ), + ), + ], ids=["by String", "by path"], ) def test_should_raise_error_if_wrong_file_extension(path: str | Path, expected_error_message: str) -> None: diff --git a/tests/safeds/data/tabular/containers/_table/test_from_json_file.py b/tests/safeds/data/tabular/containers/_table/test_from_json_file.py index 755b2e8dc..f2c53fd7f 100644 --- a/tests/safeds/data/tabular/containers/_table/test_from_json_file.py +++ b/tests/safeds/data/tabular/containers/_table/test_from_json_file.py @@ -16,7 +16,10 @@ def test_should_create_table_from_json_file(path: str | Path) -> None: @pytest.mark.parametrize( ("path", "expected_error_message"), - [("test_table_from_json_file_invalid.json", r"test_table_from_json_file_invalid.json\" does not exist"), (Path("test_table_from_json_file_invalid.json"), r"test_table_from_json_file_invalid.json\" does not exist")], + [ + ("test_table_from_json_file_invalid.json", r"test_table_from_json_file_invalid.json\" does not exist"), + (Path("test_table_from_json_file_invalid.json"), r"test_table_from_json_file_invalid.json\" does not exist"), + ], ids=["by string", "by path"], ) def test_should_raise_error_if_file_not_found(path: str | Path, expected_error_message: str) -> None: @@ -26,7 +29,22 @@ def test_should_raise_error_if_file_not_found(path: str | Path, expected_error_m @pytest.mark.parametrize( ("path", "expected_error_message"), - [("invalid_file_extension.file_extension", r"invalid_file_extension.file_extension has a wrong file extension. Please provide a file with the following extension\(s\): .json"), (Path("invalid_file_extension.file_extension"), r"invalid_file_extension.file_extension has a wrong file extension. Please provide a file with the following extension\(s\): .json")], + [ + ( + "invalid_file_extension.file_extension", + ( + r"invalid_file_extension.file_extension has a wrong file extension. Please provide a file with the" + r" following extension\(s\): .json" + ), + ), + ( + Path("invalid_file_extension.file_extension"), + ( + r"invalid_file_extension.file_extension has a wrong file extension. Please provide a file with the" + r" following extension\(s\): .json" + ), + ), + ], ids=["by String", "by path"], ) def test_should_raise_error_if_wrong_file_extension(path: str | Path, expected_error_message: str) -> None: diff --git a/tests/safeds/data/tabular/containers/_table/test_plot_boxplots.py b/tests/safeds/data/tabular/containers/_table/test_plot_boxplots.py index 2e2cbc217..2e9887db5 100644 --- a/tests/safeds/data/tabular/containers/_table/test_plot_boxplots.py +++ b/tests/safeds/data/tabular/containers/_table/test_plot_boxplots.py @@ -32,5 +32,11 @@ def test_should_match_snapshot(table: Table, path: str) -> None: def test_should_raise_if_column_contains_non_numerical_values() -> None: table = Table.from_dict({"A": ["1", "2", "3.5"], "B": ["0.2", "4", "77"]}) - with pytest.raises(NonNumericColumnError, match=r"Tried to do a numerical operation on one or multiple non numerical Columns: \nThis table contains only non-numerical columns."): + with pytest.raises( + NonNumericColumnError, + match=( + r"Tried to do a numerical operation on one or multiple non numerical Columns: \nThis table contains only" + r" non-numerical columns." + ), + ): table.plot_boxplots() diff --git a/tests/safeds/data/tabular/containers/_table/test_plot_lineplot.py b/tests/safeds/data/tabular/containers/_table/test_plot_lineplot.py index e2bf6a952..1eb5d101a 100644 --- a/tests/safeds/data/tabular/containers/_table/test_plot_lineplot.py +++ b/tests/safeds/data/tabular/containers/_table/test_plot_lineplot.py @@ -18,7 +18,11 @@ def test_should_match_snapshot() -> None: @pytest.mark.parametrize( ("x", "y", "error_message"), - [("C", "A", r"Could not find column\(s\) 'C'"), ("A", "C", r"Could not find column\(s\) 'C'"), ("C", "D", r"Could not find column\(s\) 'C, D'")], + [ + ("C", "A", r"Could not find column\(s\) 'C'"), + ("A", "C", r"Could not find column\(s\) 'C'"), + ("C", "D", r"Could not find column\(s\) 'C, D'"), + ], ids=["x column", "y column", "x and y column"], ) def test_should_raise_if_column_does_not_exist(x: str, y: str, error_message: str) -> None: diff --git a/tests/safeds/data/tabular/containers/_table/test_slice_rows.py b/tests/safeds/data/tabular/containers/_table/test_slice_rows.py index 23ce4ed5e..888143d21 100644 --- a/tests/safeds/data/tabular/containers/_table/test_slice_rows.py +++ b/tests/safeds/data/tabular/containers/_table/test_slice_rows.py @@ -1,6 +1,5 @@ import pytest from _pytest.python_api import raises - from safeds.data.tabular.containers import Table from safeds.exceptions import IndexOutOfBoundsError diff --git a/tests/safeds/data/tabular/containers/_table/test_split.py b/tests/safeds/data/tabular/containers/_table/test_split.py index 281c891de..ea00d714e 100644 --- a/tests/safeds/data/tabular/containers/_table/test_split.py +++ b/tests/safeds/data/tabular/containers/_table/test_split.py @@ -1,7 +1,7 @@ import pandas as pd import pytest from safeds.data.tabular.containers import Table -from safeds.data.tabular.typing import Schema, Integer +from safeds.data.tabular.typing import Integer, Schema @pytest.mark.parametrize( @@ -11,15 +11,15 @@ Table({"col1": [1, 2, 1], "col2": [1, 2, 4]}), Table({"col1": [1, 2], "col2": [1, 2]}), Table({"col1": [1], "col2": [4]}), - 2/3, + 2 / 3, ), -( + ( Table({"col1": [1, 2, 1], "col2": [1, 2, 4]}), Table._from_pandas_dataframe(pd.DataFrame(), Schema({"col1": Integer(), "col2": Integer()})), Table({"col1": [1, 2, 1], "col2": [1, 2, 4]}), 0, ), -( + ( Table({"col1": [1, 2, 1], "col2": [1, 2, 4]}), Table({"col1": [1, 2, 1], "col2": [1, 2, 4]}), Table._from_pandas_dataframe(pd.DataFrame(), Schema({"col1": Integer(), "col2": Integer()})), @@ -28,7 +28,9 @@ ], ids=["2/3%", "0%", "100%"], ) -def test_should_split_table(table: Table, result_test_table: Table, result_train_table: Table, percentage_in_first: int) -> None: +def test_should_split_table( + table: Table, result_test_table: Table, result_train_table: Table, percentage_in_first: int, +) -> None: train_table, test_table = table.split(percentage_in_first) assert result_test_table == test_table assert result_train_table == train_table diff --git a/tests/safeds/data/tabular/containers/_table/test_to_csv_file.py b/tests/safeds/data/tabular/containers/_table/test_to_csv_file.py index 4b2a590c2..cc2287d70 100644 --- a/tests/safeds/data/tabular/containers/_table/test_to_csv_file.py +++ b/tests/safeds/data/tabular/containers/_table/test_to_csv_file.py @@ -2,7 +2,6 @@ from tempfile import NamedTemporaryFile import pytest - from safeds.data.tabular.containers import Table from safeds.exceptions import WrongFileExtensionError @@ -33,6 +32,11 @@ def test_should_raise_error_if_wrong_file_extension() -> None: table = Table({"col1": ["col1_1"], "col2": ["col2_1"]}) with NamedTemporaryFile(suffix=".invalid_file_extension") as tmp_table_file: tmp_table_file.close() - with Path(tmp_table_file.name).open("w", encoding="utf-8") as tmp_file: - with pytest.raises(WrongFileExtensionError, match=r".invalid_file_extension has a wrong file extension. Please provide a file with the following extension\(s\): .csv"): - table.to_csv_file(Path(tmp_file.name)) + with Path(tmp_table_file.name).open("w", encoding="utf-8") as tmp_file, pytest.raises( + WrongFileExtensionError, + match=( + r".invalid_file_extension has a wrong file extension. Please provide a file with the following" + r" extension\(s\): .csv" + ), + ): + table.to_csv_file(Path(tmp_file.name)) diff --git a/tests/safeds/data/tabular/containers/_table/test_to_excel_file.py b/tests/safeds/data/tabular/containers/_table/test_to_excel_file.py index 71d626ceb..98a00ac62 100644 --- a/tests/safeds/data/tabular/containers/_table/test_to_excel_file.py +++ b/tests/safeds/data/tabular/containers/_table/test_to_excel_file.py @@ -2,7 +2,6 @@ from tempfile import NamedTemporaryFile import pytest - from safeds.data.tabular.containers import Table from safeds.exceptions import WrongFileExtensionError @@ -33,6 +32,11 @@ def test_should_raise_error_if_wrong_file_extension() -> None: table = Table({"col1": ["col1_1"], "col2": ["col2_1"]}) with NamedTemporaryFile(suffix=".invalid_file_extension") as tmp_table_file: tmp_table_file.close() - with Path(tmp_table_file.name).open("w", encoding="utf-8") as tmp_file: - with pytest.raises(WrongFileExtensionError, match=r".invalid_file_extension has a wrong file extension. Please provide a file with the following extension\(s\): \['.xls', '.xlsx', '.xlsm', '.xlsb', '.odf', '.ods', '.odt'\]"): - table.to_excel_file(Path(tmp_file.name)) + with Path(tmp_table_file.name).open("w", encoding="utf-8") as tmp_file, pytest.raises( + WrongFileExtensionError, + match=( + r".invalid_file_extension has a wrong file extension. Please provide a file with the following" + r" extension\(s\): \['.xls', '.xlsx', '.xlsm', '.xlsb', '.odf', '.ods', '.odt'\]" + ), + ): + table.to_excel_file(Path(tmp_file.name)) diff --git a/tests/safeds/data/tabular/containers/_table/test_to_json_file.py b/tests/safeds/data/tabular/containers/_table/test_to_json_file.py index 62bb9c76d..10b29ce04 100644 --- a/tests/safeds/data/tabular/containers/_table/test_to_json_file.py +++ b/tests/safeds/data/tabular/containers/_table/test_to_json_file.py @@ -2,7 +2,6 @@ from tempfile import NamedTemporaryFile import pytest - from safeds.data.tabular.containers import Table from safeds.exceptions import WrongFileExtensionError @@ -33,6 +32,11 @@ def test_should_raise_error_if_wrong_file_extension() -> None: table = Table({"col1": ["col1_1"], "col2": ["col2_1"]}) with NamedTemporaryFile(suffix=".invalid_file_extension") as tmp_table_file: tmp_table_file.close() - with Path(tmp_table_file.name).open("w", encoding="utf-8") as tmp_file: - with pytest.raises(WrongFileExtensionError, match=r".invalid_file_extension has a wrong file extension. Please provide a file with the following extension\(s\): .json"): - table.to_json_file(Path(tmp_file.name)) + with Path(tmp_table_file.name).open("w", encoding="utf-8") as tmp_file, pytest.raises( + WrongFileExtensionError, + match=( + r".invalid_file_extension has a wrong file extension. Please provide a file with the following" + r" extension\(s\): .json" + ), + ): + table.to_json_file(Path(tmp_file.name)) From 61964a1a5f75f9e537cec5ddd1f03991c2de8de9 Mon Sep 17 00:00:00 2001 From: megalinter-bot <129584137+megalinter-bot@users.noreply.github.com> Date: Fri, 19 May 2023 09:29:18 +0000 Subject: [PATCH 09/14] style: apply automated linter fixes --- src/safeds/exceptions/_data.py | 6 ++++-- .../data/tabular/containers/_table/test_add_columns.py | 8 ++++++-- .../data/tabular/containers/_table/test_dataframe.py | 3 ++- .../data/tabular/containers/_table/test_from_columns.py | 3 ++- tests/safeds/data/tabular/containers/_table/test_split.py | 5 ++++- 5 files changed, 18 insertions(+), 7 deletions(-) diff --git a/src/safeds/exceptions/_data.py b/src/safeds/exceptions/_data.py index 19a68d3d2..26e402c1c 100644 --- a/src/safeds/exceptions/_data.py +++ b/src/safeds/exceptions/_data.py @@ -107,6 +107,8 @@ class WrongFileExtensionError(Exception): def __init__(self, file: str | Path, file_extension: str | list[str]) -> None: super().__init__( - f"The file {file} has a wrong file extension. Please provide a file with the following extension(s):" - f" {file_extension}", + ( + f"The file {file} has a wrong file extension. Please provide a file with the following extension(s):" + f" {file_extension}" + ), ) diff --git a/tests/safeds/data/tabular/containers/_table/test_add_columns.py b/tests/safeds/data/tabular/containers/_table/test_add_columns.py index 238a4fb03..cc4d14fbb 100644 --- a/tests/safeds/data/tabular/containers/_table/test_add_columns.py +++ b/tests/safeds/data/tabular/containers/_table/test_add_columns.py @@ -47,7 +47,9 @@ def test_should_add_columns_from_table(table1: Table, table2: Table, expected: T ids=["Two Columns with too many values"], ) def test_should_raise_error_if_column_size_invalid( - table: Table, columns: list[Column] | Table, error_message_regex: str, + table: Table, + columns: list[Column] | Table, + error_message_regex: str, ) -> None: with pytest.raises(ColumnSizeError, match=error_message_regex): table.add_columns(columns) @@ -65,7 +67,9 @@ def test_should_raise_error_if_column_size_invalid( ids=["Column already exists"], ) def test_should_raise_error_if_column_name_in_result_column( - table: Table, columns: list[Column] | Table, error_message_regex: str, + table: Table, + columns: list[Column] | Table, + error_message_regex: str, ) -> None: with pytest.raises(DuplicateColumnNameError, match=error_message_regex): table.add_columns(columns) diff --git a/tests/safeds/data/tabular/containers/_table/test_dataframe.py b/tests/safeds/data/tabular/containers/_table/test_dataframe.py index 33522296f..32b06995e 100644 --- a/tests/safeds/data/tabular/containers/_table/test_dataframe.py +++ b/tests/safeds/data/tabular/containers/_table/test_dataframe.py @@ -24,6 +24,7 @@ def test_should_restore_table_from_exchange_object(table: Table) -> None: def test_should_raise_error_if_allow_copy_is_false() -> None: table = Table() with pytest.raises( - NotImplementedError, match=r"For the moment we need to copy the data, so `allow_copy` must be True.", + NotImplementedError, + match=r"For the moment we need to copy the data, so `allow_copy` must be True.", ): table.__dataframe__(allow_copy=False) diff --git a/tests/safeds/data/tabular/containers/_table/test_from_columns.py b/tests/safeds/data/tabular/containers/_table/test_from_columns.py index 23bd12df8..a0f1ea66b 100644 --- a/tests/safeds/data/tabular/containers/_table/test_from_columns.py +++ b/tests/safeds/data/tabular/containers/_table/test_from_columns.py @@ -28,7 +28,8 @@ def test_should_create_table_from_list_of_columns(columns: list[Column], expecte def test_should_raise_error_if_column_length_mismatch() -> None: with pytest.raises( - ColumnLengthMismatchError, match=r"The length of at least one column differs: \ncol1: 3\ncol2: 4", + ColumnLengthMismatchError, + match=r"The length of at least one column differs: \ncol1: 3\ncol2: 4", ): Table.from_columns([Column("col1", [5, 2, 3]), Column("col2", [5, 3, 4, 1])]) diff --git a/tests/safeds/data/tabular/containers/_table/test_split.py b/tests/safeds/data/tabular/containers/_table/test_split.py index ea00d714e..591a5c824 100644 --- a/tests/safeds/data/tabular/containers/_table/test_split.py +++ b/tests/safeds/data/tabular/containers/_table/test_split.py @@ -29,7 +29,10 @@ ids=["2/3%", "0%", "100%"], ) def test_should_split_table( - table: Table, result_test_table: Table, result_train_table: Table, percentage_in_first: int, + table: Table, + result_test_table: Table, + result_train_table: Table, + percentage_in_first: int, ) -> None: train_table, test_table = table.split(percentage_in_first) assert result_test_table == test_table From 0b1ba0c7fced986384c7a3c6422ec29b89c60aea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20Gr=C3=A9us?= Date: Fri, 19 May 2023 11:35:33 +0200 Subject: [PATCH 10/14] feat: Changed `Table.__eq__` to handle empty tables with no columns --- src/safeds/data/tabular/containers/_table.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/safeds/data/tabular/containers/_table.py b/src/safeds/data/tabular/containers/_table.py index 1df6b1ec4..bdbd0b3b3 100644 --- a/src/safeds/data/tabular/containers/_table.py +++ b/src/safeds/data/tabular/containers/_table.py @@ -351,6 +351,8 @@ def __eq__(self, other: Any) -> bool: table2 = other.sort_columns() if table1.number_of_rows == 0 and table2.number_of_rows == 0: return table1._schema == table2._schema + if table1.number_of_columns == 0 and table2.number_of_columns == 0: + return True return table1._schema == table2._schema and table1._data.equals(table2._data) def __repr__(self) -> str: From fe5a541fb8276636e32895bcb11add529a504839 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20Gr=C3=A9us?= Date: Fri, 19 May 2023 12:01:32 +0200 Subject: [PATCH 11/14] feat: Changed `Table.__eq__` to handle empty tables with no columns --- src/safeds/data/tabular/containers/_table.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/safeds/data/tabular/containers/_table.py b/src/safeds/data/tabular/containers/_table.py index 522f37911..10e77e2c1 100644 --- a/src/safeds/data/tabular/containers/_table.py +++ b/src/safeds/data/tabular/containers/_table.py @@ -351,8 +351,6 @@ def __eq__(self, other: Any) -> bool: table2 = other.sort_columns() if table1.number_of_rows == 0 and table2.number_of_rows == 0: return table1._schema == table2._schema - if table1.number_of_columns == 0 and table2.number_of_columns == 0: - return True return table1._schema == table2._schema and table1._data.equals(table2._data) def __repr__(self) -> str: From ef924285b01ad6139a5a962f1b690a6c33505f49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20Gr=C3=A9us?= Date: Fri, 19 May 2023 14:54:59 +0200 Subject: [PATCH 12/14] perf: Improved performance to not sort empty tables in the `Table.__eq__` method --- src/safeds/data/tabular/containers/_table.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/safeds/data/tabular/containers/_table.py b/src/safeds/data/tabular/containers/_table.py index 10e77e2c1..a5c8ba843 100644 --- a/src/safeds/data/tabular/containers/_table.py +++ b/src/safeds/data/tabular/containers/_table.py @@ -347,10 +347,10 @@ def __eq__(self, other: Any) -> bool: return NotImplemented if self is other: return True + if self.number_of_rows == 0 and other.number_of_rows == 0: + return self._schema == other._schema table1 = self.sort_columns() table2 = other.sort_columns() - if table1.number_of_rows == 0 and table2.number_of_rows == 0: - return table1._schema == table2._schema return table1._schema == table2._schema and table1._data.equals(table2._data) def __repr__(self) -> str: From fb4c3a4b99d380432ac54f316bf73a1f01c0200a Mon Sep 17 00:00:00 2001 From: Alexander <47296670+Marsmaennchen221@users.noreply.github.com> Date: Wed, 24 May 2023 18:20:31 +0200 Subject: [PATCH 13/14] Update src/safeds/data/tabular/containers/_table.py --- src/safeds/data/tabular/containers/_table.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/safeds/data/tabular/containers/_table.py b/src/safeds/data/tabular/containers/_table.py index a5c8ba843..7c6ca93b4 100644 --- a/src/safeds/data/tabular/containers/_table.py +++ b/src/safeds/data/tabular/containers/_table.py @@ -1006,7 +1006,7 @@ def slice_rows( new_df = self._data.iloc[start:end:step] new_df.columns = self._schema.column_names - return Table._from_pandas_dataframe(new_df, self._schema) + return Table._from_pandas_dataframe(new_df) def sort_columns( self, From 1da7952e36bd9008eb95157a0d169f8fd9ffcf2d Mon Sep 17 00:00:00 2001 From: Alexander <47296670+Marsmaennchen221@users.noreply.github.com> Date: Wed, 24 May 2023 18:31:39 +0200 Subject: [PATCH 14/14] Update src/safeds/data/tabular/containers/_table.py --- src/safeds/data/tabular/containers/_table.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/safeds/data/tabular/containers/_table.py b/src/safeds/data/tabular/containers/_table.py index 7c6ca93b4..99709faea 100644 --- a/src/safeds/data/tabular/containers/_table.py +++ b/src/safeds/data/tabular/containers/_table.py @@ -348,7 +348,7 @@ def __eq__(self, other: Any) -> bool: if self is other: return True if self.number_of_rows == 0 and other.number_of_rows == 0: - return self._schema == other._schema + return self.column_names == other.column_names table1 = self.sort_columns() table2 = other.sort_columns() return table1._schema == table2._schema and table1._data.equals(table2._data)