diff --git a/src/safeds/data/tabular/containers/_lazy_vectorized_row.py b/src/safeds/data/tabular/containers/_lazy_vectorized_row.py index 1a53da529..122af8317 100644 --- a/src/safeds/data/tabular/containers/_lazy_vectorized_row.py +++ b/src/safeds/data/tabular/containers/_lazy_vectorized_row.py @@ -21,7 +21,7 @@ class _LazyVectorizedRow(Row): up operations on the row. Moreover, accessing a column only builds an expression that will be evaluated when needed. This is useful when later - operations remove more rows or columns, so we don't do unnecessary work upfront. + operations remove rows or columns, so we don't do unnecessary work upfront. """ # ------------------------------------------------------------------------------------------------------------------ diff --git a/src/safeds/data/tabular/containers/_row.py b/src/safeds/data/tabular/containers/_row.py index 6d43fb570..f16ea898e 100644 --- a/src/safeds/data/tabular/containers/_row.py +++ b/src/safeds/data/tabular/containers/_row.py @@ -2,27 +2,29 @@ from abc import ABC, abstractmethod from collections.abc import Iterator, Mapping -from typing import TYPE_CHECKING, Any +from typing import TYPE_CHECKING + +from ._cell import Cell if TYPE_CHECKING: from safeds.data.tabular.typing import ColumnType, Schema - from ._cell import Cell - -class Row(ABC, Mapping[str, Any]): +class Row(ABC, Mapping[str, Cell]): """ A one-dimensional collection of named, heterogeneous values. - This class cannot be instantiated directly. It is only used for arguments of callbacks. + You only need to interact with this class in callbacks passed to higher-order functions. """ # ------------------------------------------------------------------------------------------------------------------ # Dunder methods # ------------------------------------------------------------------------------------------------------------------ - def __contains__(self, name: Any) -> bool: - return self.has_column(name) + def __contains__(self, key: object, /) -> bool: + if not isinstance(key, str): + return False + return self.has_column(key) @abstractmethod def __eq__(self, other: object) -> bool: ... @@ -33,7 +35,7 @@ def __getitem__(self, name: str) -> Cell: @abstractmethod def __hash__(self) -> int: ... - def __iter__(self) -> Iterator[Any]: + def __iter__(self) -> Iterator[str]: return iter(self.column_names) def __len__(self) -> int: @@ -48,18 +50,18 @@ def __sizeof__(self) -> int: ... @property @abstractmethod - def column_names(self) -> list[str]: - """The names of the columns in the row.""" + def column_count(self) -> int: + """The number of columns.""" @property @abstractmethod - def column_count(self) -> int: - """The number of columns in the row.""" + def column_names(self) -> list[str]: + """The names of the columns.""" @property @abstractmethod def schema(self) -> Schema: - """The schema of the row.""" + """The schema, which is a mapping from column names to their types.""" # ------------------------------------------------------------------------------------------------------------------ # Column operations @@ -98,7 +100,6 @@ def get_cell(self, name: str) -> Cell: | 2 | 4 | +------+------+ - >>> table.remove_rows(lambda row: row["col1"] == 1) +------+------+ | col1 | col2 | @@ -112,7 +113,7 @@ def get_cell(self, name: str) -> Cell: @abstractmethod def get_column_type(self, name: str) -> ColumnType: """ - Get the type of the specified column. + Get the type of a column. This is equivalent to using the `[]` operator (indexed access). Parameters ---------- @@ -127,13 +128,13 @@ def get_column_type(self, name: str) -> ColumnType: Raises ------ ColumnNotFoundError - If the column name does not exist. + If the column does not exist. """ @abstractmethod def has_column(self, name: str) -> bool: """ - Check if the row has a column with the specified name. + Check if the row has a column with a specific name. This is equivalent to using the `in` operator. Parameters ---------- diff --git a/src/safeds/data/tabular/containers/_table.py b/src/safeds/data/tabular/containers/_table.py index c39f96c6e..744d82d18 100644 --- a/src/safeds/data/tabular/containers/_table.py +++ b/src/safeds/data/tabular/containers/_table.py @@ -393,9 +393,9 @@ def _data_frame(self) -> pl.DataFrame: return self.__data_frame_cache @property - def column_names(self) -> list[str]: + def column_count(self) -> int: """ - The names of the columns in the table. + The number of columns. **Note:** This operation must compute the schema of the table, which can be expensive. @@ -403,15 +403,15 @@ def column_names(self) -> list[str]: -------- >>> from safeds.data.tabular.containers import Table >>> table = Table({"a": [1, 2, 3], "b": [4, 5, 6]}) - >>> table.column_names - ['a', 'b'] + >>> table.column_count + 2 """ - return self.schema.column_names + return len(self.column_names) @property - def column_count(self) -> int: + def column_names(self) -> list[str]: """ - The number of columns in the table. + The names of the columns in the table. **Note:** This operation must compute the schema of the table, which can be expensive. @@ -419,15 +419,15 @@ def column_count(self) -> int: -------- >>> from safeds.data.tabular.containers import Table >>> table = Table({"a": [1, 2, 3], "b": [4, 5, 6]}) - >>> table.column_count - 2 + >>> table.column_names + ['a', 'b'] """ - return len(self.column_names) + return self.schema.column_names @property def row_count(self) -> int: """ - The number of rows in the table. + The number of rows. **Note:** This operation must fully load the data into memory, which can be expensive. @@ -458,7 +458,7 @@ def plot(self) -> TablePlotter: @property def schema(self) -> Schema: """ - The schema of the table. + The schema, which is a mapping from column names to their types. Examples -------- diff --git a/src/safeds/data/tabular/typing/_schema.py b/src/safeds/data/tabular/typing/_schema.py index f1ce98698..27684fd92 100644 --- a/src/safeds/data/tabular/typing/_schema.py +++ b/src/safeds/data/tabular/typing/_schema.py @@ -1,22 +1,20 @@ from __future__ import annotations import sys +from collections.abc import Iterator, Mapping from typing import TYPE_CHECKING from safeds._utils import _structural_hash from safeds._validation import _check_columns_exist +from ._column_type import ColumnType from ._polars_column_type import _PolarsColumnType if TYPE_CHECKING: - from collections.abc import Mapping - import polars as pl - from ._column_type import ColumnType - -class Schema: +class Schema(Mapping[str, ColumnType]): """The schema of a row or table.""" # ------------------------------------------------------------------------------------------------------------------ @@ -41,6 +39,11 @@ def __init__(self, schema: Mapping[str, ColumnType]) -> None: check_dtypes=False, ) + def __contains__(self, key: object, /) -> bool: + if not isinstance(key, str): + return False + return self.has_column(key) + def __eq__(self, other: object) -> bool: if not isinstance(other, Schema): return NotImplemented @@ -48,9 +51,18 @@ def __eq__(self, other: object) -> bool: return True return self._schema == other._schema + def __getitem__(self, key: str, /) -> ColumnType: + return self.get_column_type(key) + def __hash__(self) -> int: return _structural_hash(tuple(self._schema.keys()), [str(type_) for type_ in self._schema.values()]) + def __iter__(self) -> Iterator[str]: + return iter(self._schema.keys()) + + def __len__(self) -> int: + return self.column_count + def __repr__(self) -> str: return f"Schema({self!s})" @@ -108,7 +120,7 @@ def column_names(self) -> list[str]: def get_column_type(self, name: str) -> ColumnType: """ - Get the type of a column. + Get the type of a column. This is equivalent to using the `[]` operator (indexed access). Parameters ---------- @@ -131,6 +143,9 @@ def get_column_type(self, name: str) -> ColumnType: >>> schema = Schema({"a": ColumnType.int64(), "b": ColumnType.float32()}) >>> schema.get_column_type("a") int64 + + >>> schema["b"] + float32 """ _check_columns_exist(self, name) @@ -138,7 +153,7 @@ def get_column_type(self, name: str) -> ColumnType: def has_column(self, name: str) -> bool: """ - Check if the table has a column with a specific name. + Check if the schema has a column with a specific name. This is equivalent to using the `in` operator. Parameters ---------- @@ -148,7 +163,7 @@ def has_column(self, name: str) -> bool: Returns ------- has_column: - Whether the table has a column with the specified name. + Whether the schema has a column with the specified name. Examples -------- @@ -157,7 +172,7 @@ def has_column(self, name: str) -> bool: >>> schema.has_column("a") True - >>> schema.has_column("c") + >>> "c" in schema False """ return name in self._schema diff --git a/tests/helpers/_assertions.py b/tests/helpers/_assertions.py index 76358b17e..0a0434ed5 100644 --- a/tests/helpers/_assertions.py +++ b/tests/helpers/_assertions.py @@ -4,7 +4,7 @@ from polars.testing import assert_frame_equal from safeds.data.labeled.containers import TabularDataset -from safeds.data.tabular.containers import Cell, Column, Table +from safeds.data.tabular.containers import Cell, Column, Row, Table def assert_tables_are_equal( @@ -62,44 +62,71 @@ def assert_that_tabular_datasets_are_equal(table1: TabularDataset, table2: Tabul def assert_cell_operation_works( - input_value: Any, + value: Any, transformer: Callable[[Cell], Cell], - expected_value: Any, + expected: Any, ) -> None: """ Assert that a cell operation works as expected. Parameters ---------- - input_value: + value: The value in the input cell. transformer: The transformer to apply to the cells. - expected_value: + expected: The expected value of the transformed cell. """ - column = Column("A", [input_value]) + column = Column("A", [value]) transformed_column = column.transform(transformer) - assert transformed_column == Column("A", [expected_value]), f"Expected: {expected_value}\nGot: {transformed_column}" + actual = transformed_column[0] + assert actual == expected def assert_row_operation_works( - input_value: Any, - transformer: Callable[[Table], Table], - expected_value: Any, + table: Table, + computer: Callable[[Row], Cell], + expected: list[Any], ) -> None: """ Assert that a row operation works as expected. Parameters ---------- - input_value: - The value in the input row. - transformer: - The transformer to apply to the rows. - expected_value: - The expected value of the transformed row. + table: + The input table. + computer: + The function that computes the new column. + expected: + The expected values of the computed column. + """ + column_name = _find_free_column_name(table, "computed") + + new_table = table.add_computed_column(column_name, computer) + actual = list(new_table.get_column(column_name)) + assert actual == expected + + +def _find_free_column_name(table: Table, prefix: str) -> str: """ - table = Table(input_value) - transformed_table = transformer(table) - assert transformed_table == Table(expected_value), f"Expected: {expected_value}\nGot: {transformed_table}" + Find a free column name in the table. + + Parameters + ---------- + table: + The table to search for a free column name. + prefix: + The prefix to use for the column name. + + Returns + ------- + free_name: + A free column name. + """ + column_name = prefix + + while column_name in table.column_names: + column_name += "_" + + return column_name diff --git a/tests/safeds/data/tabular/containers/_cell/__init__.py b/tests/safeds/data/tabular/containers/_lazy_cell/__init__.py similarity index 100% rename from tests/safeds/data/tabular/containers/_cell/__init__.py rename to tests/safeds/data/tabular/containers/_lazy_cell/__init__.py diff --git a/tests/safeds/data/tabular/containers/_cell/test_abs.py b/tests/safeds/data/tabular/containers/_lazy_cell/test_abs.py similarity index 100% rename from tests/safeds/data/tabular/containers/_cell/test_abs.py rename to tests/safeds/data/tabular/containers/_lazy_cell/test_abs.py diff --git a/tests/safeds/data/tabular/containers/_cell/test_add.py b/tests/safeds/data/tabular/containers/_lazy_cell/test_add.py similarity index 100% rename from tests/safeds/data/tabular/containers/_cell/test_add.py rename to tests/safeds/data/tabular/containers/_lazy_cell/test_add.py diff --git a/tests/safeds/data/tabular/containers/_cell/test_and.py b/tests/safeds/data/tabular/containers/_lazy_cell/test_and.py similarity index 100% rename from tests/safeds/data/tabular/containers/_cell/test_and.py rename to tests/safeds/data/tabular/containers/_lazy_cell/test_and.py diff --git a/tests/safeds/data/tabular/containers/_cell/test_ceil.py b/tests/safeds/data/tabular/containers/_lazy_cell/test_ceil.py similarity index 100% rename from tests/safeds/data/tabular/containers/_cell/test_ceil.py rename to tests/safeds/data/tabular/containers/_lazy_cell/test_ceil.py diff --git a/tests/safeds/data/tabular/containers/_cell/test_div.py b/tests/safeds/data/tabular/containers/_lazy_cell/test_div.py similarity index 100% rename from tests/safeds/data/tabular/containers/_cell/test_div.py rename to tests/safeds/data/tabular/containers/_lazy_cell/test_div.py diff --git a/tests/safeds/data/tabular/containers/_cell/test_eq.py b/tests/safeds/data/tabular/containers/_lazy_cell/test_eq.py similarity index 100% rename from tests/safeds/data/tabular/containers/_cell/test_eq.py rename to tests/safeds/data/tabular/containers/_lazy_cell/test_eq.py diff --git a/tests/safeds/data/tabular/containers/_cell/test_equals.py b/tests/safeds/data/tabular/containers/_lazy_cell/test_equals.py similarity index 100% rename from tests/safeds/data/tabular/containers/_cell/test_equals.py rename to tests/safeds/data/tabular/containers/_lazy_cell/test_equals.py diff --git a/tests/safeds/data/tabular/containers/_cell/test_first_not_none.py b/tests/safeds/data/tabular/containers/_lazy_cell/test_first_not_none.py similarity index 100% rename from tests/safeds/data/tabular/containers/_cell/test_first_not_none.py rename to tests/safeds/data/tabular/containers/_lazy_cell/test_first_not_none.py diff --git a/tests/safeds/data/tabular/containers/_cell/test_floor.py b/tests/safeds/data/tabular/containers/_lazy_cell/test_floor.py similarity index 100% rename from tests/safeds/data/tabular/containers/_cell/test_floor.py rename to tests/safeds/data/tabular/containers/_lazy_cell/test_floor.py diff --git a/tests/safeds/data/tabular/containers/_cell/test_floordiv.py b/tests/safeds/data/tabular/containers/_lazy_cell/test_floordiv.py similarity index 100% rename from tests/safeds/data/tabular/containers/_cell/test_floordiv.py rename to tests/safeds/data/tabular/containers/_lazy_cell/test_floordiv.py diff --git a/tests/safeds/data/tabular/containers/_cell/test_ge.py b/tests/safeds/data/tabular/containers/_lazy_cell/test_ge.py similarity index 100% rename from tests/safeds/data/tabular/containers/_cell/test_ge.py rename to tests/safeds/data/tabular/containers/_lazy_cell/test_ge.py diff --git a/tests/safeds/data/tabular/containers/_cell/test_gt.py b/tests/safeds/data/tabular/containers/_lazy_cell/test_gt.py similarity index 100% rename from tests/safeds/data/tabular/containers/_cell/test_gt.py rename to tests/safeds/data/tabular/containers/_lazy_cell/test_gt.py diff --git a/tests/safeds/data/tabular/containers/_cell/test_hash.py b/tests/safeds/data/tabular/containers/_lazy_cell/test_hash.py similarity index 100% rename from tests/safeds/data/tabular/containers/_cell/test_hash.py rename to tests/safeds/data/tabular/containers/_lazy_cell/test_hash.py diff --git a/tests/safeds/data/tabular/containers/_cell/test_le.py b/tests/safeds/data/tabular/containers/_lazy_cell/test_le.py similarity index 100% rename from tests/safeds/data/tabular/containers/_cell/test_le.py rename to tests/safeds/data/tabular/containers/_lazy_cell/test_le.py diff --git a/tests/safeds/data/tabular/containers/_cell/test_lt.py b/tests/safeds/data/tabular/containers/_lazy_cell/test_lt.py similarity index 100% rename from tests/safeds/data/tabular/containers/_cell/test_lt.py rename to tests/safeds/data/tabular/containers/_lazy_cell/test_lt.py diff --git a/tests/safeds/data/tabular/containers/_cell/test_mod.py b/tests/safeds/data/tabular/containers/_lazy_cell/test_mod.py similarity index 100% rename from tests/safeds/data/tabular/containers/_cell/test_mod.py rename to tests/safeds/data/tabular/containers/_lazy_cell/test_mod.py diff --git a/tests/safeds/data/tabular/containers/_cell/test_mul.py b/tests/safeds/data/tabular/containers/_lazy_cell/test_mul.py similarity index 100% rename from tests/safeds/data/tabular/containers/_cell/test_mul.py rename to tests/safeds/data/tabular/containers/_lazy_cell/test_mul.py diff --git a/tests/safeds/data/tabular/containers/_cell/test_ne.py b/tests/safeds/data/tabular/containers/_lazy_cell/test_ne.py similarity index 100% rename from tests/safeds/data/tabular/containers/_cell/test_ne.py rename to tests/safeds/data/tabular/containers/_lazy_cell/test_ne.py diff --git a/tests/safeds/data/tabular/containers/_cell/test_neg.py b/tests/safeds/data/tabular/containers/_lazy_cell/test_neg.py similarity index 100% rename from tests/safeds/data/tabular/containers/_cell/test_neg.py rename to tests/safeds/data/tabular/containers/_lazy_cell/test_neg.py diff --git a/tests/safeds/data/tabular/containers/_cell/test_not.py b/tests/safeds/data/tabular/containers/_lazy_cell/test_not.py similarity index 100% rename from tests/safeds/data/tabular/containers/_cell/test_not.py rename to tests/safeds/data/tabular/containers/_lazy_cell/test_not.py diff --git a/tests/safeds/data/tabular/containers/_cell/test_or.py b/tests/safeds/data/tabular/containers/_lazy_cell/test_or.py similarity index 100% rename from tests/safeds/data/tabular/containers/_cell/test_or.py rename to tests/safeds/data/tabular/containers/_lazy_cell/test_or.py diff --git a/tests/safeds/data/tabular/containers/_cell/test_pos.py b/tests/safeds/data/tabular/containers/_lazy_cell/test_pos.py similarity index 100% rename from tests/safeds/data/tabular/containers/_cell/test_pos.py rename to tests/safeds/data/tabular/containers/_lazy_cell/test_pos.py diff --git a/tests/safeds/data/tabular/containers/_cell/test_pow.py b/tests/safeds/data/tabular/containers/_lazy_cell/test_pow.py similarity index 100% rename from tests/safeds/data/tabular/containers/_cell/test_pow.py rename to tests/safeds/data/tabular/containers/_lazy_cell/test_pow.py diff --git a/tests/safeds/data/tabular/containers/_cell/test_sizeof.py b/tests/safeds/data/tabular/containers/_lazy_cell/test_sizeof.py similarity index 100% rename from tests/safeds/data/tabular/containers/_cell/test_sizeof.py rename to tests/safeds/data/tabular/containers/_lazy_cell/test_sizeof.py diff --git a/tests/safeds/data/tabular/containers/_cell/test_sub.py b/tests/safeds/data/tabular/containers/_lazy_cell/test_sub.py similarity index 100% rename from tests/safeds/data/tabular/containers/_cell/test_sub.py rename to tests/safeds/data/tabular/containers/_lazy_cell/test_sub.py diff --git a/tests/safeds/data/tabular/containers/_cell/test_xor.py b/tests/safeds/data/tabular/containers/_lazy_cell/test_xor.py similarity index 100% rename from tests/safeds/data/tabular/containers/_cell/test_xor.py rename to tests/safeds/data/tabular/containers/_lazy_cell/test_xor.py diff --git a/tests/safeds/data/tabular/containers/_row/__init__.py b/tests/safeds/data/tabular/containers/_lazy_string_cell/__init__.py similarity index 100% rename from tests/safeds/data/tabular/containers/_row/__init__.py rename to tests/safeds/data/tabular/containers/_lazy_string_cell/__init__.py diff --git a/tests/safeds/data/tabular/containers/_string_cell/test_contains.py b/tests/safeds/data/tabular/containers/_lazy_string_cell/test_contains.py similarity index 100% rename from tests/safeds/data/tabular/containers/_string_cell/test_contains.py rename to tests/safeds/data/tabular/containers/_lazy_string_cell/test_contains.py diff --git a/tests/safeds/data/tabular/containers/_string_cell/test_ends_with.py b/tests/safeds/data/tabular/containers/_lazy_string_cell/test_ends_with.py similarity index 100% rename from tests/safeds/data/tabular/containers/_string_cell/test_ends_with.py rename to tests/safeds/data/tabular/containers/_lazy_string_cell/test_ends_with.py diff --git a/tests/safeds/data/tabular/containers/_string_cell/test_equals.py b/tests/safeds/data/tabular/containers/_lazy_string_cell/test_equals.py similarity index 100% rename from tests/safeds/data/tabular/containers/_string_cell/test_equals.py rename to tests/safeds/data/tabular/containers/_lazy_string_cell/test_equals.py diff --git a/tests/safeds/data/tabular/containers/_string_cell/test_hash.py b/tests/safeds/data/tabular/containers/_lazy_string_cell/test_hash.py similarity index 100% rename from tests/safeds/data/tabular/containers/_string_cell/test_hash.py rename to tests/safeds/data/tabular/containers/_lazy_string_cell/test_hash.py diff --git a/tests/safeds/data/tabular/containers/_string_cell/test_index_of.py b/tests/safeds/data/tabular/containers/_lazy_string_cell/test_index_of.py similarity index 100% rename from tests/safeds/data/tabular/containers/_string_cell/test_index_of.py rename to tests/safeds/data/tabular/containers/_lazy_string_cell/test_index_of.py diff --git a/tests/safeds/data/tabular/containers/_string_cell/test_length.py b/tests/safeds/data/tabular/containers/_lazy_string_cell/test_length.py similarity index 100% rename from tests/safeds/data/tabular/containers/_string_cell/test_length.py rename to tests/safeds/data/tabular/containers/_lazy_string_cell/test_length.py diff --git a/tests/safeds/data/tabular/containers/_string_cell/test_replace.py b/tests/safeds/data/tabular/containers/_lazy_string_cell/test_replace.py similarity index 100% rename from tests/safeds/data/tabular/containers/_string_cell/test_replace.py rename to tests/safeds/data/tabular/containers/_lazy_string_cell/test_replace.py diff --git a/tests/safeds/data/tabular/containers/_string_cell/test_sizeof.py b/tests/safeds/data/tabular/containers/_lazy_string_cell/test_sizeof.py similarity index 100% rename from tests/safeds/data/tabular/containers/_string_cell/test_sizeof.py rename to tests/safeds/data/tabular/containers/_lazy_string_cell/test_sizeof.py diff --git a/tests/safeds/data/tabular/containers/_string_cell/test_starts_with.py b/tests/safeds/data/tabular/containers/_lazy_string_cell/test_starts_with.py similarity index 100% rename from tests/safeds/data/tabular/containers/_string_cell/test_starts_with.py rename to tests/safeds/data/tabular/containers/_lazy_string_cell/test_starts_with.py diff --git a/tests/safeds/data/tabular/containers/_string_cell/test_substring.py b/tests/safeds/data/tabular/containers/_lazy_string_cell/test_substring.py similarity index 100% rename from tests/safeds/data/tabular/containers/_string_cell/test_substring.py rename to tests/safeds/data/tabular/containers/_lazy_string_cell/test_substring.py diff --git a/tests/safeds/data/tabular/containers/_string_cell/test_to_date.py b/tests/safeds/data/tabular/containers/_lazy_string_cell/test_to_date.py similarity index 100% rename from tests/safeds/data/tabular/containers/_string_cell/test_to_date.py rename to tests/safeds/data/tabular/containers/_lazy_string_cell/test_to_date.py diff --git a/tests/safeds/data/tabular/containers/_string_cell/test_to_datetime.py b/tests/safeds/data/tabular/containers/_lazy_string_cell/test_to_datetime.py similarity index 100% rename from tests/safeds/data/tabular/containers/_string_cell/test_to_datetime.py rename to tests/safeds/data/tabular/containers/_lazy_string_cell/test_to_datetime.py diff --git a/tests/safeds/data/tabular/containers/_string_cell/test_to_float.py b/tests/safeds/data/tabular/containers/_lazy_string_cell/test_to_float.py similarity index 100% rename from tests/safeds/data/tabular/containers/_string_cell/test_to_float.py rename to tests/safeds/data/tabular/containers/_lazy_string_cell/test_to_float.py diff --git a/tests/safeds/data/tabular/containers/_string_cell/test_to_int.py b/tests/safeds/data/tabular/containers/_lazy_string_cell/test_to_int.py similarity index 100% rename from tests/safeds/data/tabular/containers/_string_cell/test_to_int.py rename to tests/safeds/data/tabular/containers/_lazy_string_cell/test_to_int.py diff --git a/tests/safeds/data/tabular/containers/_string_cell/test_to_lowercase.py b/tests/safeds/data/tabular/containers/_lazy_string_cell/test_to_lowercase.py similarity index 100% rename from tests/safeds/data/tabular/containers/_string_cell/test_to_lowercase.py rename to tests/safeds/data/tabular/containers/_lazy_string_cell/test_to_lowercase.py diff --git a/tests/safeds/data/tabular/containers/_string_cell/test_to_uppercase.py b/tests/safeds/data/tabular/containers/_lazy_string_cell/test_to_uppercase.py similarity index 100% rename from tests/safeds/data/tabular/containers/_string_cell/test_to_uppercase.py rename to tests/safeds/data/tabular/containers/_lazy_string_cell/test_to_uppercase.py diff --git a/tests/safeds/data/tabular/containers/_string_cell/test_trim.py b/tests/safeds/data/tabular/containers/_lazy_string_cell/test_trim.py similarity index 100% rename from tests/safeds/data/tabular/containers/_string_cell/test_trim.py rename to tests/safeds/data/tabular/containers/_lazy_string_cell/test_trim.py diff --git a/tests/safeds/data/tabular/containers/_string_cell/test_trim_end.py b/tests/safeds/data/tabular/containers/_lazy_string_cell/test_trim_end.py similarity index 100% rename from tests/safeds/data/tabular/containers/_string_cell/test_trim_end.py rename to tests/safeds/data/tabular/containers/_lazy_string_cell/test_trim_end.py diff --git a/tests/safeds/data/tabular/containers/_string_cell/test_trim_start.py b/tests/safeds/data/tabular/containers/_lazy_string_cell/test_trim_start.py similarity index 100% rename from tests/safeds/data/tabular/containers/_string_cell/test_trim_start.py rename to tests/safeds/data/tabular/containers/_lazy_string_cell/test_trim_start.py diff --git a/tests/safeds/data/tabular/containers/_string_cell/__init__.py b/tests/safeds/data/tabular/containers/_lazy_temporal_cell/__init__.py similarity index 100% rename from tests/safeds/data/tabular/containers/_string_cell/__init__.py rename to tests/safeds/data/tabular/containers/_lazy_temporal_cell/__init__.py diff --git a/tests/safeds/data/tabular/containers/_temporal_cell/test_century.py b/tests/safeds/data/tabular/containers/_lazy_temporal_cell/test_century.py similarity index 100% rename from tests/safeds/data/tabular/containers/_temporal_cell/test_century.py rename to tests/safeds/data/tabular/containers/_lazy_temporal_cell/test_century.py diff --git a/tests/safeds/data/tabular/containers/_temporal_cell/test_date_to_string.py b/tests/safeds/data/tabular/containers/_lazy_temporal_cell/test_date_to_string.py similarity index 100% rename from tests/safeds/data/tabular/containers/_temporal_cell/test_date_to_string.py rename to tests/safeds/data/tabular/containers/_lazy_temporal_cell/test_date_to_string.py diff --git a/tests/safeds/data/tabular/containers/_temporal_cell/test_datetime_to_string.py b/tests/safeds/data/tabular/containers/_lazy_temporal_cell/test_datetime_to_string.py similarity index 100% rename from tests/safeds/data/tabular/containers/_temporal_cell/test_datetime_to_string.py rename to tests/safeds/data/tabular/containers/_lazy_temporal_cell/test_datetime_to_string.py diff --git a/tests/safeds/data/tabular/containers/_temporal_cell/test_day.py b/tests/safeds/data/tabular/containers/_lazy_temporal_cell/test_day.py similarity index 100% rename from tests/safeds/data/tabular/containers/_temporal_cell/test_day.py rename to tests/safeds/data/tabular/containers/_lazy_temporal_cell/test_day.py diff --git a/tests/safeds/data/tabular/containers/_temporal_cell/test_equals.py b/tests/safeds/data/tabular/containers/_lazy_temporal_cell/test_equals.py similarity index 100% rename from tests/safeds/data/tabular/containers/_temporal_cell/test_equals.py rename to tests/safeds/data/tabular/containers/_lazy_temporal_cell/test_equals.py diff --git a/tests/safeds/data/tabular/containers/_temporal_cell/test_hash.py b/tests/safeds/data/tabular/containers/_lazy_temporal_cell/test_hash.py similarity index 100% rename from tests/safeds/data/tabular/containers/_temporal_cell/test_hash.py rename to tests/safeds/data/tabular/containers/_lazy_temporal_cell/test_hash.py diff --git a/tests/safeds/data/tabular/containers/_temporal_cell/test_month.py b/tests/safeds/data/tabular/containers/_lazy_temporal_cell/test_month.py similarity index 100% rename from tests/safeds/data/tabular/containers/_temporal_cell/test_month.py rename to tests/safeds/data/tabular/containers/_lazy_temporal_cell/test_month.py diff --git a/tests/safeds/data/tabular/containers/_temporal_cell/test_sizeof.py b/tests/safeds/data/tabular/containers/_lazy_temporal_cell/test_sizeof.py similarity index 100% rename from tests/safeds/data/tabular/containers/_temporal_cell/test_sizeof.py rename to tests/safeds/data/tabular/containers/_lazy_temporal_cell/test_sizeof.py diff --git a/tests/safeds/data/tabular/containers/_temporal_cell/test_week.py b/tests/safeds/data/tabular/containers/_lazy_temporal_cell/test_week.py similarity index 100% rename from tests/safeds/data/tabular/containers/_temporal_cell/test_week.py rename to tests/safeds/data/tabular/containers/_lazy_temporal_cell/test_week.py diff --git a/tests/safeds/data/tabular/containers/_temporal_cell/test_weekday.py b/tests/safeds/data/tabular/containers/_lazy_temporal_cell/test_weekday.py similarity index 100% rename from tests/safeds/data/tabular/containers/_temporal_cell/test_weekday.py rename to tests/safeds/data/tabular/containers/_lazy_temporal_cell/test_weekday.py diff --git a/tests/safeds/data/tabular/containers/_temporal_cell/test_year.py b/tests/safeds/data/tabular/containers/_lazy_temporal_cell/test_year.py similarity index 100% rename from tests/safeds/data/tabular/containers/_temporal_cell/test_year.py rename to tests/safeds/data/tabular/containers/_lazy_temporal_cell/test_year.py diff --git a/tests/safeds/data/tabular/containers/_temporal_cell/__init__.py b/tests/safeds/data/tabular/containers/_lazy_vectorized_row/__init__.py similarity index 100% rename from tests/safeds/data/tabular/containers/_temporal_cell/__init__.py rename to tests/safeds/data/tabular/containers/_lazy_vectorized_row/__init__.py diff --git a/tests/safeds/data/tabular/containers/_lazy_vectorized_row/__snapshots__/test_hash.ambr b/tests/safeds/data/tabular/containers/_lazy_vectorized_row/__snapshots__/test_hash.ambr new file mode 100644 index 000000000..f079fdc47 --- /dev/null +++ b/tests/safeds/data/tabular/containers/_lazy_vectorized_row/__snapshots__/test_hash.ambr @@ -0,0 +1,10 @@ +# serializer version: 1 +# name: TestContract.test_should_return_same_hash_in_different_processes[empty] + 1789859531466043636 +# --- +# name: TestContract.test_should_return_same_hash_in_different_processes[no rows] + 585695607399955642 +# --- +# name: TestContract.test_should_return_same_hash_in_different_processes[with data] + 909875695937937648 +# --- diff --git a/tests/safeds/data/tabular/containers/_row/test_column_count.py b/tests/safeds/data/tabular/containers/_lazy_vectorized_row/test_column_count.py similarity index 57% rename from tests/safeds/data/tabular/containers/_row/test_column_count.py rename to tests/safeds/data/tabular/containers/_lazy_vectorized_row/test_column_count.py index c7a65c9e0..73d7d8660 100644 --- a/tests/safeds/data/tabular/containers/_row/test_column_count.py +++ b/tests/safeds/data/tabular/containers/_lazy_vectorized_row/test_column_count.py @@ -8,13 +8,15 @@ ("table", "expected"), [ (Table({}), 0), - (Table({"A": [1, 2, 3]}), 1), + (Table({"col1": []}), 1), + (Table({"col1": [1], "col2": [1]}), 2), ], ids=[ "empty", - "non-empty", + "no rows", + "with data", ], ) -def test_should_return_the_number_of_columns(table: Table, expected: int) -> None: - row = _LazyVectorizedRow(table=table) +def test_should_return_number_of_columns(table: Table, expected: int) -> None: + row = _LazyVectorizedRow(table) assert row.column_count == expected diff --git a/tests/safeds/data/tabular/containers/_lazy_vectorized_row/test_column_names.py b/tests/safeds/data/tabular/containers/_lazy_vectorized_row/test_column_names.py new file mode 100644 index 000000000..dca260703 --- /dev/null +++ b/tests/safeds/data/tabular/containers/_lazy_vectorized_row/test_column_names.py @@ -0,0 +1,22 @@ +import pytest + +from safeds.data.tabular.containers import Table +from safeds.data.tabular.containers._lazy_vectorized_row import _LazyVectorizedRow + + +@pytest.mark.parametrize( + ("table", "expected"), + [ + (Table({}), []), + (Table({"col1": []}), ["col1"]), + (Table({"col1": [1], "col2": [1]}), ["col1", "col2"]), + ], + ids=[ + "empty", + "no rows", + "with data", + ], +) +def test_should_return_column_names(table: Table, expected: list[str]) -> None: + row = _LazyVectorizedRow(table) + assert row.column_names == expected diff --git a/tests/safeds/data/tabular/containers/_lazy_vectorized_row/test_contains.py b/tests/safeds/data/tabular/containers/_lazy_vectorized_row/test_contains.py new file mode 100644 index 000000000..31929b932 --- /dev/null +++ b/tests/safeds/data/tabular/containers/_lazy_vectorized_row/test_contains.py @@ -0,0 +1,24 @@ +import pytest + +from safeds.data.tabular.containers import Table +from safeds.data.tabular.containers._lazy_vectorized_row import _LazyVectorizedRow + + +@pytest.mark.parametrize( + ("table", "column", "expected"), + [ + (Table({}), "C", False), + (Table({"A": []}), "A", True), + (Table({"A": []}), "B", False), + (Table({"A": []}), 1, False), + ], + ids=[ + "empty", + "has column", + "doesn't have column", + "key is not string", + ], +) +def test_should_return_if_column_is_in_row(table: Table, column: str, expected: bool) -> None: + row = _LazyVectorizedRow(table) + assert (column in row) == expected diff --git a/tests/safeds/data/tabular/containers/_lazy_vectorized_row/test_eq.py b/tests/safeds/data/tabular/containers/_lazy_vectorized_row/test_eq.py new file mode 100644 index 000000000..f27c2180f --- /dev/null +++ b/tests/safeds/data/tabular/containers/_lazy_vectorized_row/test_eq.py @@ -0,0 +1,140 @@ +from typing import Any + +import pytest + +from safeds.data.tabular.containers import Column, Table +from safeds.data.tabular.containers._lazy_vectorized_row import _LazyVectorizedRow + + +@pytest.mark.parametrize( + ("table_1", "table_2", "expected"), + [ + # equal (empty) + ( + Table({}), + Table({}), + True, + ), + # equal (no rows) + ( + Table({"col1": []}), + Table({"col1": []}), + True, + ), + # equal (with data) + ( + Table({"col1": [1], "col2": [2]}), + Table({"col1": [1], "col2": [2]}), + True, + ), + # not equal (too few columns) + ( + Table({"col1": [1]}), + Table({}), + False, + ), + # not equal (too many columns) + ( + Table({}), + Table({"col1": [1]}), + False, + ), + # not equal (different column order) + ( + Table({"col1": [1], "col2": [2]}), + Table({"col2": [2], "col1": [1]}), + False, + ), + # not equal (different column names) + ( + Table({"col1": [1]}), + Table({"col2": [1]}), + False, + ), + # not equal (different types) + ( + Table({"col1": [1]}), + Table({"col1": ["1"]}), + False, + ), + # not equal (too few rows) + ( + Table({"col1": [1, 2]}), + Table({"col1": [1]}), # Needs at least one value, so the types match + False, + ), + # not equal (too many rows) + ( + Table({"col1": [1]}), # Needs at least one value, so the types match + Table({"col1": [1, 2]}), + False, + ), + # not equal (different row order) + ( + Table({"col1": [1, 2]}), + Table({"col1": [2, 1]}), + False, + ), + # not equal (different values) + ( + Table({"col1": [1, 2]}), + Table({"col1": [1, 3]}), + False, + ), + ], + ids=[ + # Equal + "equal (empty)", + "equal (no rows)", + "equal (with data)", + # Not equal because of columns + "not equal (too few columns)", + "not equal (too many columns)", + "not equal (different column order)", + "not equal (different column names)", + "not equal (different types)", + # Not equal because of rows + "not equal (too few rows)", + "not equal (too many rows)", + "not equal (different row order)", + "not equal (different values)", + ], +) +def test_should_return_whether_objects_are_equal(table_1: Table, table_2: Table, expected: bool) -> None: + row_1 = _LazyVectorizedRow(table_1) + row_2 = _LazyVectorizedRow(table_2) + assert (row_1.__eq__(row_2)) == expected + + +@pytest.mark.parametrize( + "table", + [ + Table({}), + Table({"col1": []}), + Table({"col1": [1]}), + ], + ids=[ + "empty", + "no rows", + "non-empty", + ], +) +def test_should_return_true_if_objects_are_identical(table: Table) -> None: + row = _LazyVectorizedRow(table) + assert (row.__eq__(row)) is True + + +@pytest.mark.parametrize( + ("table", "other"), + [ + (Table({}), None), + (Table({}), Column("col1", [])), + ], + ids=[ + "Row vs. None", + "Row vs. Column", + ], +) +def test_should_return_not_implemented_if_other_has_different_type(table: Table, other: Any) -> None: + row = _LazyVectorizedRow(table) + assert (row.__eq__(other)) is NotImplemented diff --git a/tests/safeds/data/tabular/containers/_lazy_vectorized_row/test_get_cell.py b/tests/safeds/data/tabular/containers/_lazy_vectorized_row/test_get_cell.py new file mode 100644 index 000000000..189f8d20e --- /dev/null +++ b/tests/safeds/data/tabular/containers/_lazy_vectorized_row/test_get_cell.py @@ -0,0 +1,59 @@ +from typing import Any + +import pytest + +from safeds.data.tabular.containers import Table +from safeds.data.tabular.containers._lazy_vectorized_row import _LazyVectorizedRow +from safeds.exceptions import ColumnNotFoundError +from tests.helpers import assert_row_operation_works + + +@pytest.mark.parametrize( + ("table", "name", "target", "expected"), + [ + ( + Table({"A": [1, 2]}), + "A", + 1, + [True, False], + ), + ( + Table({"A": [1, 2], "B": [3, 4]}), + "A", + 1, + [True, False], + ), + ], + ids=[ + "one column", + "two columns", + ], +) +def test_should_get_correct_item( + table: Table, + name: str, + target: int, + expected: list[Any], +) -> None: + assert_row_operation_works( + table, + lambda row: row.get_cell(name) == target, + expected, + ) + + +@pytest.mark.parametrize( + ("table", "name"), + [ + (Table({}), "A"), + (Table({"A": []}), "B"), + ], + ids=[ + "empty", + "non-empty", + ], +) +def test_should_raise_if_column_does_not_exist(table: Table, name: str) -> None: + row = _LazyVectorizedRow(table) + with pytest.raises(ColumnNotFoundError): + row.get_cell(name) diff --git a/tests/safeds/data/tabular/containers/_lazy_vectorized_row/test_get_column_type.py b/tests/safeds/data/tabular/containers/_lazy_vectorized_row/test_get_column_type.py new file mode 100644 index 000000000..0c658db8f --- /dev/null +++ b/tests/safeds/data/tabular/containers/_lazy_vectorized_row/test_get_column_type.py @@ -0,0 +1,33 @@ +import pytest + +from safeds.data.tabular.containers import Table +from safeds.data.tabular.containers._lazy_vectorized_row import _LazyVectorizedRow +from safeds.data.tabular.typing import ColumnType +from safeds.exceptions import ColumnNotFoundError + + +@pytest.mark.parametrize( + ("table", "name", "expected"), + [ + ( + Table({"col1": [1]}), + "col1", + ColumnType.int64(), + ), + ( + Table({"col1": ["a"]}), + "col1", + ColumnType.string(), + ), + ], + ids=["int column", "string column"], +) +def test_should_return_data_type_of_column(table: Table, name: str, expected: ColumnType) -> None: + row = _LazyVectorizedRow(table) + assert row.get_column_type(name) == expected + + +def test_should_raise_if_column_name_is_unknown() -> None: + row = _LazyVectorizedRow(Table({})) + with pytest.raises(ColumnNotFoundError): + row.get_column_type("col1") diff --git a/tests/safeds/data/tabular/containers/_lazy_vectorized_row/test_getitem.py b/tests/safeds/data/tabular/containers/_lazy_vectorized_row/test_getitem.py new file mode 100644 index 000000000..0f5ee9fb1 --- /dev/null +++ b/tests/safeds/data/tabular/containers/_lazy_vectorized_row/test_getitem.py @@ -0,0 +1,59 @@ +from typing import Any + +import pytest + +from safeds.data.tabular.containers import Table +from safeds.data.tabular.containers._lazy_vectorized_row import _LazyVectorizedRow +from safeds.exceptions import ColumnNotFoundError +from tests.helpers import assert_row_operation_works + + +@pytest.mark.parametrize( + ("table", "name", "target", "expected"), + [ + ( + Table({"A": [1, 2]}), + "A", + 1, + [True, False], + ), + ( + Table({"A": [1, 2], "B": [3, 4]}), + "A", + 1, + [True, False], + ), + ], + ids=[ + "one column", + "two columns", + ], +) +def test_should_get_correct_item( + table: Table, + name: str, + target: int, + expected: list[Any], +) -> None: + assert_row_operation_works( + table, + lambda row: row[name] == target, + expected, + ) + + +@pytest.mark.parametrize( + ("table", "name"), + [ + (Table({}), "A"), + (Table({"A": []}), "B"), + ], + ids=[ + "empty", + "non-empty", + ], +) +def test_should_raise_if_column_does_not_exist(table: Table, name: str) -> None: + row = _LazyVectorizedRow(table) + with pytest.raises(ColumnNotFoundError): + _ignored = row[name] diff --git a/tests/safeds/data/tabular/containers/_lazy_vectorized_row/test_has_column.py b/tests/safeds/data/tabular/containers/_lazy_vectorized_row/test_has_column.py new file mode 100644 index 000000000..cc8062773 --- /dev/null +++ b/tests/safeds/data/tabular/containers/_lazy_vectorized_row/test_has_column.py @@ -0,0 +1,18 @@ +import pytest + +from safeds.data.tabular.containers import Table +from safeds.data.tabular.containers._lazy_vectorized_row import _LazyVectorizedRow + + +@pytest.mark.parametrize( + ("table", "column", "expected"), + [ + (Table({}), "C", False), + (Table({"A": []}), "A", True), + (Table({"A": []}), "B", False), + ], + ids=["empty", "has column", "doesn't have column"], +) +def test_should_return_if_column_is_in_row(table: Table, column: str, expected: bool) -> None: + row = _LazyVectorizedRow(table) + assert row.has_column(column) == expected diff --git a/tests/safeds/data/tabular/containers/_lazy_vectorized_row/test_hash.py b/tests/safeds/data/tabular/containers/_lazy_vectorized_row/test_hash.py new file mode 100644 index 000000000..bbc5ac3e0 --- /dev/null +++ b/tests/safeds/data/tabular/containers/_lazy_vectorized_row/test_hash.py @@ -0,0 +1,90 @@ +from collections.abc import Callable + +import pytest +from syrupy import SnapshotAssertion + +from safeds.data.tabular.containers import Table +from safeds.data.tabular.containers._lazy_vectorized_row import _LazyVectorizedRow + + +@pytest.mark.parametrize( + "table_factory", + [ + lambda: Table({}), + lambda: Table({"col1": []}), + lambda: Table({"col1": [1, 2]}), + ], + ids=[ + "empty", + "no rows", + "with data", + ], +) +class TestContract: + def test_should_return_same_hash_for_equal_objects(self, table_factory: Callable[[], Table]) -> None: + row_1 = _LazyVectorizedRow(table_factory()) + row_2 = _LazyVectorizedRow(table_factory()) + assert hash(row_1) == hash(row_2) + + def test_should_return_same_hash_in_different_processes( + self, + table_factory: Callable[[], Table], + snapshot: SnapshotAssertion, + ) -> None: + row = _LazyVectorizedRow(table_factory()) + assert hash(row) == snapshot + + +@pytest.mark.parametrize( + ("table_1", "table_2"), + [ + # too few columns + ( + Table({"col1": [1]}), + Table({}), + ), + # too many columns + ( + Table({}), + Table({"col1": [1]}), + ), + # different column order + ( + Table({"col1": [1], "col2": [2]}), + Table({"col2": [2], "col1": [1]}), + ), + # different column names + ( + Table({"col1": [1]}), + Table({"col2": [1]}), + ), + # different types + ( + Table({"col1": [1]}), + Table({"col1": ["1"]}), + ), + # too few rows + ( + Table({"col1": [1, 2]}), + Table({"col1": [1]}), # Needs at least one value, so the types match + ), + # too many rows + ( + Table({"col1": [1]}), # Needs at least one value, so the types match + Table({"col1": [1, 2]}), + ), + ], + ids=[ + "too few columns", + "too many columns", + "different column order", + "different column names", + "different types", + "too few rows", + "too many rows", + ], +) +def test_should_be_good_hash(table_1: Table, table_2: Table) -> None: + row_1 = _LazyVectorizedRow(table_1) + row_2 = _LazyVectorizedRow(table_2) + assert hash(row_1) != hash(row_2) diff --git a/tests/safeds/data/tabular/containers/_lazy_vectorized_row/test_iter.py b/tests/safeds/data/tabular/containers/_lazy_vectorized_row/test_iter.py new file mode 100644 index 000000000..1eea612cd --- /dev/null +++ b/tests/safeds/data/tabular/containers/_lazy_vectorized_row/test_iter.py @@ -0,0 +1,22 @@ +import pytest + +from safeds.data.tabular.containers import Table +from safeds.data.tabular.containers._lazy_vectorized_row import _LazyVectorizedRow + + +@pytest.mark.parametrize( + ("table", "expected"), + [ + (Table({}), []), + (Table({"col1": []}), ["col1"]), + (Table({"col1": [], "col2": []}), ["col1", "col2"]), + ], + ids=[ + "empty", + "one column", + "two columns", + ], +) +def test_should_return_column_names(table: Table, expected: list[str]) -> None: + row = _LazyVectorizedRow(table) + assert list(row) == expected diff --git a/tests/safeds/data/tabular/containers/_row/test_len.py b/tests/safeds/data/tabular/containers/_lazy_vectorized_row/test_len.py similarity index 50% rename from tests/safeds/data/tabular/containers/_row/test_len.py rename to tests/safeds/data/tabular/containers/_lazy_vectorized_row/test_len.py index 577018476..bab49223d 100644 --- a/tests/safeds/data/tabular/containers/_row/test_len.py +++ b/tests/safeds/data/tabular/containers/_lazy_vectorized_row/test_len.py @@ -8,15 +8,15 @@ ("table", "expected"), [ (Table({}), 0), - (Table({"A": ["a", "aa", "aaa"]}), 1), - (Table({"A": ["a", "aa", "aaa"], "B": ["b", "bb", "bbb"]}), 2), + (Table({"col1": []}), 1), + (Table({"col1": [1], "col2": [1]}), 2), ], ids=[ "empty", - "one column", - "two columns", + "no rows", + "with data", ], ) -def test_should_have_same_length_as_number_of_columns(table: Table, expected: int) -> None: - row = _LazyVectorizedRow(table=table) +def test_should_return_number_of_columns(table: Table, expected: int) -> None: + row = _LazyVectorizedRow(table) assert len(row) == expected diff --git a/tests/safeds/data/tabular/containers/_lazy_vectorized_row/test_schema.py b/tests/safeds/data/tabular/containers/_lazy_vectorized_row/test_schema.py new file mode 100644 index 000000000..b4d0edf66 --- /dev/null +++ b/tests/safeds/data/tabular/containers/_lazy_vectorized_row/test_schema.py @@ -0,0 +1,32 @@ +import pytest + +from safeds.data.tabular.containers import Table +from safeds.data.tabular.containers._lazy_vectorized_row import _LazyVectorizedRow +from safeds.data.tabular.typing import ColumnType, Schema + + +@pytest.mark.parametrize( + ("table", "expected"), + [ + ( + Table({}), + Schema({}), + ), + ( + Table({"col1": []}), + Schema({"col1": ColumnType.null()}), + ), + ( + Table({"col1": [1], "col2": [1]}), + Schema({"col1": ColumnType.int64(), "col2": ColumnType.int64()}), + ), + ], + ids=[ + "empty", + "no rows", + "with data", + ], +) +def test_should_return_schema(table: Table, expected: Schema) -> None: + row = _LazyVectorizedRow(table) + assert row.schema == expected diff --git a/tests/safeds/data/tabular/containers/_lazy_vectorized_row/test_sizeof.py b/tests/safeds/data/tabular/containers/_lazy_vectorized_row/test_sizeof.py new file mode 100644 index 000000000..111ed5bc7 --- /dev/null +++ b/tests/safeds/data/tabular/containers/_lazy_vectorized_row/test_sizeof.py @@ -0,0 +1,24 @@ +import sys + +import pytest + +from safeds.data.tabular.containers import Table +from safeds.data.tabular.containers._lazy_vectorized_row import _LazyVectorizedRow + + +@pytest.mark.parametrize( + "table", + [ + Table({}), + Table({"col1": []}), + Table({"col1": [0, 1], "col2": ["a", "b"]}), + ], + ids=[ + "empty", + "no rows", + "with data", + ], +) +def test_should_size_be_greater_than_normal_object(table: Table) -> None: + row = _LazyVectorizedRow(table) + assert sys.getsizeof(row) > sys.getsizeof(object()) diff --git a/tests/safeds/data/tabular/containers/_row/test_column_names.py b/tests/safeds/data/tabular/containers/_row/test_column_names.py deleted file mode 100644 index 09b32bbf7..000000000 --- a/tests/safeds/data/tabular/containers/_row/test_column_names.py +++ /dev/null @@ -1,25 +0,0 @@ -import pytest - -from safeds.data.tabular.containers import Table -from safeds.data.tabular.containers._lazy_vectorized_row import _LazyVectorizedRow - - -@pytest.mark.parametrize( - ("table", "expected"), - [ - (Table({}), []), - (Table({"A": [1, 2, 3]}), ["A"]), - ( - Table({"A": [1, 2, 3], "B": ["A", "A", "Bla"], "C": [True, True, False], "D": [1.0, 2.1, 4.5]}), - ["A", "B", "C", "D"], - ), - ], - ids=[ - "empty", - "one-column", - "four-column", - ], -) -def test_should_return_the_column_names(table: Table, expected: list[str]) -> None: - row = _LazyVectorizedRow(table=table) - assert row.column_names == expected diff --git a/tests/safeds/data/tabular/containers/_row/test_contains.py b/tests/safeds/data/tabular/containers/_row/test_contains.py deleted file mode 100644 index fc9cda260..000000000 --- a/tests/safeds/data/tabular/containers/_row/test_contains.py +++ /dev/null @@ -1,24 +0,0 @@ -import pytest - -from safeds.data.tabular.containers import Table -from safeds.data.tabular.containers._lazy_vectorized_row import _LazyVectorizedRow - - -@pytest.mark.parametrize( - ("table", "column_name", "expected"), - [ - (Table({}), "A", False), - (Table({"A": [1, 2, 3]}), "A", True), - (Table({"A": [1, 2, 3], "B": ["A", "A", "Bla"]}), "C", False), - (Table({"col1": [1, 2, 3], "B": ["A", "A", "Bla"]}), 1, False), - ], - ids=[ - "empty row", - "column exists", - "column does not exist", - "not a string", - ], -) -def test_should_return_whether_the_row_has_the_column(table: Table, column_name: str, expected: bool) -> None: - row = _LazyVectorizedRow(table=table) - assert (column_name in row) == expected diff --git a/tests/safeds/data/tabular/containers/_row/test_eq.py b/tests/safeds/data/tabular/containers/_row/test_eq.py deleted file mode 100644 index 5e57cbc56..000000000 --- a/tests/safeds/data/tabular/containers/_row/test_eq.py +++ /dev/null @@ -1,59 +0,0 @@ -import pytest - -from safeds.data.tabular.containers import Table -from safeds.data.tabular.containers._lazy_vectorized_row import _LazyVectorizedRow - - -@pytest.mark.parametrize( - ("table1", "table2", "expected"), - [ - (Table({"col1": []}), Table({"col1": []}), True), - (Table({"col1": [1, 2]}), Table({"col1": [1, 2]}), True), - (Table({"col1": [1, 2]}), Table({"col1": [2, 3]}), False), - (Table({"col1": [1, 2]}), Table({"col2": [1, 2]}), False), - (Table({"col1": ["1", "2"]}), Table({"col1": [1, 2]}), False), - ], - ids=[ - "empty rows", - "equal rows", - "different values", - "different columns", - "different types", - ], -) -def test_should_return_whether_two_rows_are_equal(table1: Table, table2: Table, expected: bool) -> None: - row1 = _LazyVectorizedRow(table=table1) - row2 = _LazyVectorizedRow(table=table2) - assert (row1.__eq__(row2)) == expected - - -@pytest.mark.parametrize( - ("table", "expected"), - [ - (Table({"col1": []}), True), - (Table({"col1": [1, 2]}), True), - ], - ids=[ - "empty table", - "filled table", - ], -) -def test_should_return_true_if_rows_are_strict_equal(table: Table, expected: bool) -> None: - row1 = _LazyVectorizedRow(table=table) - assert (row1.__eq__(row1)) == expected - - -@pytest.mark.parametrize( - ("table1", "table2"), - [ - (Table({"col1": []}), Table({"col1": []})), - (Table({"col1": [1, 2]}), Table({"col1": [1, 2]})), - ], - ids=[ - "empty tables", - "filled tables", - ], -) -def test_should_return_false_if_object_is_other_type(table1: Table, table2: Table) -> None: - row1 = _LazyVectorizedRow(table=table1) - assert (row1.__eq__(table2)) == NotImplemented diff --git a/tests/safeds/data/tabular/containers/_row/test_get_cell.py b/tests/safeds/data/tabular/containers/_row/test_get_cell.py deleted file mode 100644 index aec1adf63..000000000 --- a/tests/safeds/data/tabular/containers/_row/test_get_cell.py +++ /dev/null @@ -1,46 +0,0 @@ -import re - -import pytest - -from safeds.data.tabular.containers import Table -from safeds.data.tabular.containers._lazy_vectorized_row import _LazyVectorizedRow -from safeds.exceptions import ColumnNotFoundError -from tests.helpers import assert_row_operation_works - - -@pytest.mark.parametrize( - ("table_data", "column_name", "target", "expected"), - [ - ({"A": [1, 2]}, "A", 1, {"A": [2]}), - ({"A": [1, 2, 3], "B": [4, 5, 2]}, "B", 2, {"A": [1, 2], "B": [4, 5]}), - ], - ids=[ - "one column", - "two columns", - ], -) -def test_should_get_correct_item(table_data: dict, column_name: str, target: int, expected: dict) -> None: - assert_row_operation_works( - table_data, - lambda table: table.remove_rows(lambda row: row.get_cell(column_name).eq(target)), - expected, - ) - - -@pytest.mark.parametrize( - ("table", "column_name"), - [ - (Table({}), "A"), - (Table({"A": ["a", "aa", "aaa"]}), "B"), - (Table({"A": ["b", "aa", "aaa"], "C": ["b", "aa", "aaa"]}), "B"), - ], - ids=[ - "empty table", - "table with one column", - "table with two columns", - ], -) -def test_should_raise_column_not_found_error(table: Table, column_name: str) -> None: - row = _LazyVectorizedRow(table=table) - with pytest.raises(ColumnNotFoundError, match=re.escape(f"Could not find column(s):\n - '{column_name}'")): - row.get_cell(column_name) diff --git a/tests/safeds/data/tabular/containers/_row/test_get_column_type.py b/tests/safeds/data/tabular/containers/_row/test_get_column_type.py deleted file mode 100644 index 2cf29bfab..000000000 --- a/tests/safeds/data/tabular/containers/_row/test_get_column_type.py +++ /dev/null @@ -1,21 +0,0 @@ -import pytest - -from safeds.data.tabular.containers import Table -from safeds.data.tabular.containers._lazy_vectorized_row import _LazyVectorizedRow -from safeds.data.tabular.typing import ColumnType - - -@pytest.mark.parametrize( - ("table", "column_name", "expected"), - [ - (Table({"col1": ["A"]}), "col1", ColumnType.string()), - (Table({"col1": ["a"], "col2": [1]}), "col2", ColumnType.int64()), - ], - ids=[ - "one column", - "two columns", - ], -) -def test_should_return_the_type_of_the_column(table: Table, column_name: str, expected: ColumnType) -> None: - row = _LazyVectorizedRow(table=table) - assert row.get_column_type(column_name) == expected diff --git a/tests/safeds/data/tabular/containers/_row/test_getitem.py b/tests/safeds/data/tabular/containers/_row/test_getitem.py deleted file mode 100644 index 2ca90d53c..000000000 --- a/tests/safeds/data/tabular/containers/_row/test_getitem.py +++ /dev/null @@ -1,46 +0,0 @@ -import re - -import pytest - -from safeds.data.tabular.containers import Table -from safeds.data.tabular.containers._lazy_vectorized_row import _LazyVectorizedRow -from safeds.exceptions import ColumnNotFoundError -from tests.helpers import assert_row_operation_works - - -@pytest.mark.parametrize( - ("table_data", "column_name", "target", "expected"), - [ - ({"A": [1, 2]}, "A", 1, {"A": [2]}), - ({"A": [1, 2, 3], "B": [4, 5, 2]}, "B", 2, {"A": [1, 2], "B": [4, 5]}), - ], - ids=[ - "table one column", - "table two columns", - ], -) -def test_should_get_correct_item(table_data: dict, column_name: str, target: int, expected: dict) -> None: - assert_row_operation_works( - table_data, - lambda table: table.remove_rows(lambda row: row[column_name].eq(target)), - expected, - ) - - -@pytest.mark.parametrize( - ("table", "column_name"), - [ - (Table({}), "A"), - (Table({"A": ["a", "aa", "aaa"]}), "B"), - (Table({"A": ["b", "aa", "aaa"], "C": ["b", "aa", "aaa"]}), "B"), - ], - ids=[ - "empty table", - "table with one column", - "table with two columns", - ], -) -def test_should_raise_column_not_found_error(table: Table, column_name: str) -> None: - row = _LazyVectorizedRow(table=table) - with pytest.raises(ColumnNotFoundError, match=re.escape(f"Could not find column(s):\n - '{column_name}'")): - row[column_name] diff --git a/tests/safeds/data/tabular/containers/_row/test_has_column.py b/tests/safeds/data/tabular/containers/_row/test_has_column.py deleted file mode 100644 index 2fad69b81..000000000 --- a/tests/safeds/data/tabular/containers/_row/test_has_column.py +++ /dev/null @@ -1,22 +0,0 @@ -import pytest - -from safeds.data.tabular.containers import Table -from safeds.data.tabular.containers._lazy_vectorized_row import _LazyVectorizedRow - - -@pytest.mark.parametrize( - ("table", "column_name", "expected"), - [ - (Table({}), "A", False), - (Table({"A": ["a", "aa", "aaa"]}), "A", True), - (Table({"A": ["a", "aa", "aaa"]}), "B", False), - ], - ids=[ - "empty table", - "table with existing column_name", - "table with non existing column_name", - ], -) -def test_should_have_column_name(table: Table, column_name: str, expected: bool) -> None: - row = _LazyVectorizedRow(table=table) - assert row.has_column(column_name) == expected diff --git a/tests/safeds/data/tabular/containers/_row/test_hash.py b/tests/safeds/data/tabular/containers/_row/test_hash.py deleted file mode 100644 index 7dacd8439..000000000 --- a/tests/safeds/data/tabular/containers/_row/test_hash.py +++ /dev/null @@ -1,25 +0,0 @@ -import pytest - -from safeds.data.tabular.containers import Table -from safeds.data.tabular.containers._lazy_vectorized_row import _LazyVectorizedRow - - -@pytest.mark.parametrize( - ("table1", "table2", "expected"), - [ - (Table({}), Table({"A": ["a", "aa", "aaa"]}), False), - (Table({}), Table({}), True), - (Table({"A": ["a", "aa", "aaa"]}), Table({"A": ["a", "aa", "aaa"]}), True), - (Table({"A": ["a", "aa", "aaa"]}), Table({"B": ["a", "aa", "aaa"]}), False), - ], - ids=[ - "empty and different table", - "same empty tables", - "same tables", - "different tables", - ], -) -def test_should_return_consistent_hashes(table1: Table, table2: Table, expected: bool) -> None: - row1 = _LazyVectorizedRow(table=table1) - row2 = _LazyVectorizedRow(table=table2) - assert (hash(row1) == hash(row2)) == expected diff --git a/tests/safeds/data/tabular/containers/_row/test_iter.py b/tests/safeds/data/tabular/containers/_row/test_iter.py deleted file mode 100644 index ea74f3703..000000000 --- a/tests/safeds/data/tabular/containers/_row/test_iter.py +++ /dev/null @@ -1,23 +0,0 @@ -import pytest - -from safeds.data.tabular.containers import Table -from safeds.data.tabular.containers._lazy_vectorized_row import _LazyVectorizedRow - - -@pytest.mark.parametrize( - ("table", "expected"), - [ - (Table({}), []), - (Table({"A": ["a", "aa", "aaa"]}), ["A"]), - (Table({"A": ["a", "aa", "aaa"], "B": ["b", "bb", "bbb"], "C": ["c", "cc", "ccc"]}), ["A", "B", "C"]), - ], - ids=[ - "empty", - "one column", - "three columns", - ], -) -def test_should_return_same_list_of_column_name_with_iter(table: Table, expected: list) -> None: - row = _LazyVectorizedRow(table=table) - iterable = iter(row) - assert list(iterable) == expected diff --git a/tests/safeds/data/tabular/containers/_row/test_schema.py b/tests/safeds/data/tabular/containers/_row/test_schema.py deleted file mode 100644 index 8e9412bce..000000000 --- a/tests/safeds/data/tabular/containers/_row/test_schema.py +++ /dev/null @@ -1,22 +0,0 @@ -import pytest - -from safeds.data.tabular.containers import Table -from safeds.data.tabular.containers._lazy_vectorized_row import _LazyVectorizedRow - - -@pytest.mark.parametrize( - ("table"), - [ - (Table({})), - (Table({"A": ["a", "aa", "aaa"]})), - (Table({"A": ["a", "aa", "aaa"], "B": ["b", "bb", "bbb"]})), - ], - ids=[ - "empty", - "one column", - "two columns", - ], -) -def test_should_return_same_schema(table: Table) -> None: - row = _LazyVectorizedRow(table=table) - assert table.schema == row.schema diff --git a/tests/safeds/data/tabular/containers/_row/test_sizeof.py b/tests/safeds/data/tabular/containers/_row/test_sizeof.py deleted file mode 100644 index 808e0882b..000000000 --- a/tests/safeds/data/tabular/containers/_row/test_sizeof.py +++ /dev/null @@ -1,10 +0,0 @@ -import sys - -import polars as pl - -from safeds.data.tabular.containers._lazy_vectorized_row import _LazyVectorizedRow - - -def test_should_return_size_greater_than_normal_object() -> None: - cell = _LazyVectorizedRow(pl.col("a")) - assert sys.getsizeof(cell) > sys.getsizeof(object()) diff --git a/tests/safeds/data/tabular/containers/_table/test_eq.py b/tests/safeds/data/tabular/containers/_table/test_eq.py index da61b8564..7ef114ece 100644 --- a/tests/safeds/data/tabular/containers/_table/test_eq.py +++ b/tests/safeds/data/tabular/containers/_table/test_eq.py @@ -99,7 +99,7 @@ "not equal (different values)", ], ) -def test_should_return_whether_tables_are_equal(table_1: Table, table_2: Table, expected: bool) -> None: +def test_should_return_whether_objects_are_equal(table_1: Table, table_2: Table, expected: bool) -> None: assert (table_1.__eq__(table_2)) == expected @@ -116,7 +116,7 @@ def test_should_return_whether_tables_are_equal(table_1: Table, table_2: Table, "non-empty", ], ) -def test_should_return_true_if_tables_are_identical(table: Table) -> None: +def test_should_return_true_if_objects_are_identical(table: Table) -> None: assert (table.__eq__(table)) is True @@ -131,5 +131,5 @@ def test_should_return_true_if_tables_are_identical(table: Table) -> None: "Table vs. Column", ], ) -def test_should_return_not_implemented_if_other_is_not_table(table: Table, other: Any) -> None: +def test_should_return_not_implemented_if_other_has_different_type(table: Table, other: Any) -> None: assert (table.__eq__(other)) is NotImplemented diff --git a/tests/safeds/data/tabular/containers/_table/test_schema.py b/tests/safeds/data/tabular/containers/_table/test_schema.py new file mode 100644 index 000000000..96a2b998c --- /dev/null +++ b/tests/safeds/data/tabular/containers/_table/test_schema.py @@ -0,0 +1,30 @@ +import pytest + +from safeds.data.tabular.containers import Table +from safeds.data.tabular.typing import ColumnType, Schema + + +@pytest.mark.parametrize( + ("table", "expected"), + [ + ( + Table({}), + Schema({}), + ), + ( + Table({"col1": []}), + Schema({"col1": ColumnType.null()}), + ), + ( + Table({"col1": [1], "col2": [1]}), + Schema({"col1": ColumnType.int64(), "col2": ColumnType.int64()}), + ), + ], + ids=[ + "empty", + "no rows", + "with data", + ], +) +def test_should_return_schema(table: Table, expected: Schema) -> None: + assert table.schema == expected diff --git a/tests/safeds/data/tabular/typing/_column_type/__init__.py b/tests/safeds/data/tabular/typing/_polars_column_type/__init__.py similarity index 100% rename from tests/safeds/data/tabular/typing/_column_type/__init__.py rename to tests/safeds/data/tabular/typing/_polars_column_type/__init__.py diff --git a/tests/safeds/data/tabular/typing/_column_type/__snapshots__/test_hash.ambr b/tests/safeds/data/tabular/typing/_polars_column_type/__snapshots__/test_hash.ambr similarity index 100% rename from tests/safeds/data/tabular/typing/_column_type/__snapshots__/test_hash.ambr rename to tests/safeds/data/tabular/typing/_polars_column_type/__snapshots__/test_hash.ambr diff --git a/tests/safeds/data/tabular/typing/_column_type/test_eq.py b/tests/safeds/data/tabular/typing/_polars_column_type/test_eq.py similarity index 88% rename from tests/safeds/data/tabular/typing/_column_type/test_eq.py rename to tests/safeds/data/tabular/typing/_polars_column_type/test_eq.py index 2edeba7a2..9a7250247 100644 --- a/tests/safeds/data/tabular/typing/_column_type/test_eq.py +++ b/tests/safeds/data/tabular/typing/_polars_column_type/test_eq.py @@ -23,7 +23,7 @@ "not equal (numeric vs. non-numeric)", ], ) -def test_should_return_whether_column_types_are_equal(type_1: Table, type_2: Table, expected: bool) -> None: +def test_should_return_whether_objects_are_equal(type_1: Table, type_2: Table, expected: bool) -> None: assert (type_1.__eq__(type_2)) == expected @@ -70,7 +70,7 @@ def test_should_return_whether_column_types_are_equal(type_1: Table, type_2: Tab "null", ], ) -def test_should_return_true_if_column_types_are_identical(type_: ColumnType) -> None: +def test_should_return_true_if_objects_are_identical(type_: ColumnType) -> None: assert (type_.__eq__(type_)) is True @@ -85,5 +85,5 @@ def test_should_return_true_if_column_types_are_identical(type_: ColumnType) -> "ColumnType vs. Column", ], ) -def test_should_return_not_implemented_if_other_is_not_column_type(type_: ColumnType, other: Any) -> None: +def test_should_return_not_implemented_if_other_has_different_type(type_: ColumnType, other: Any) -> None: assert (type_.__eq__(other)) is NotImplemented diff --git a/tests/safeds/data/tabular/typing/_column_type/test_hash.py b/tests/safeds/data/tabular/typing/_polars_column_type/test_hash.py similarity index 100% rename from tests/safeds/data/tabular/typing/_column_type/test_hash.py rename to tests/safeds/data/tabular/typing/_polars_column_type/test_hash.py diff --git a/tests/safeds/data/tabular/typing/_column_type/test_is_float.py b/tests/safeds/data/tabular/typing/_polars_column_type/test_is_float.py similarity index 100% rename from tests/safeds/data/tabular/typing/_column_type/test_is_float.py rename to tests/safeds/data/tabular/typing/_polars_column_type/test_is_float.py diff --git a/tests/safeds/data/tabular/typing/_column_type/test_is_int.py b/tests/safeds/data/tabular/typing/_polars_column_type/test_is_int.py similarity index 100% rename from tests/safeds/data/tabular/typing/_column_type/test_is_int.py rename to tests/safeds/data/tabular/typing/_polars_column_type/test_is_int.py diff --git a/tests/safeds/data/tabular/typing/_column_type/test_is_numeric.py b/tests/safeds/data/tabular/typing/_polars_column_type/test_is_numeric.py similarity index 100% rename from tests/safeds/data/tabular/typing/_column_type/test_is_numeric.py rename to tests/safeds/data/tabular/typing/_polars_column_type/test_is_numeric.py diff --git a/tests/safeds/data/tabular/typing/_column_type/test_is_signed_int.py b/tests/safeds/data/tabular/typing/_polars_column_type/test_is_signed_int.py similarity index 100% rename from tests/safeds/data/tabular/typing/_column_type/test_is_signed_int.py rename to tests/safeds/data/tabular/typing/_polars_column_type/test_is_signed_int.py diff --git a/tests/safeds/data/tabular/typing/_column_type/test_is_temporal.py b/tests/safeds/data/tabular/typing/_polars_column_type/test_is_temporal.py similarity index 100% rename from tests/safeds/data/tabular/typing/_column_type/test_is_temporal.py rename to tests/safeds/data/tabular/typing/_polars_column_type/test_is_temporal.py diff --git a/tests/safeds/data/tabular/typing/_column_type/test_is_unsigned_int.py b/tests/safeds/data/tabular/typing/_polars_column_type/test_is_unsigned_int.py similarity index 100% rename from tests/safeds/data/tabular/typing/_column_type/test_is_unsigned_int.py rename to tests/safeds/data/tabular/typing/_polars_column_type/test_is_unsigned_int.py diff --git a/tests/safeds/data/tabular/typing/_column_type/test_repr.py b/tests/safeds/data/tabular/typing/_polars_column_type/test_repr.py similarity index 100% rename from tests/safeds/data/tabular/typing/_column_type/test_repr.py rename to tests/safeds/data/tabular/typing/_polars_column_type/test_repr.py diff --git a/tests/safeds/data/tabular/typing/_column_type/test_sizeof.py b/tests/safeds/data/tabular/typing/_polars_column_type/test_sizeof.py similarity index 100% rename from tests/safeds/data/tabular/typing/_column_type/test_sizeof.py rename to tests/safeds/data/tabular/typing/_polars_column_type/test_sizeof.py diff --git a/tests/safeds/data/tabular/typing/_column_type/test_str.py b/tests/safeds/data/tabular/typing/_polars_column_type/test_str.py similarity index 100% rename from tests/safeds/data/tabular/typing/_column_type/test_str.py rename to tests/safeds/data/tabular/typing/_polars_column_type/test_str.py diff --git a/tests/safeds/data/tabular/typing/_schema/test_contains.py b/tests/safeds/data/tabular/typing/_schema/test_contains.py new file mode 100644 index 000000000..c30855ba0 --- /dev/null +++ b/tests/safeds/data/tabular/typing/_schema/test_contains.py @@ -0,0 +1,38 @@ +import pytest + +from safeds.data.tabular.typing import ColumnType, Schema + + +@pytest.mark.parametrize( + ("schema", "column", "expected"), + [ + ( + Schema({}), + "C", + False, + ), + ( + Schema({"A": ColumnType.null()}), + "A", + True, + ), + ( + Schema({"A": ColumnType.null()}), + "B", + False, + ), + ( + Schema({"A": ColumnType.null()}), + 1, + False, + ), + ], + ids=[ + "empty", + "has column", + "doesn't have column", + "key is not string", + ], +) +def test_should_check_if_column_is_in_schema(schema: Schema, column: str, expected: bool) -> None: + assert (column in schema) == expected diff --git a/tests/safeds/data/tabular/typing/_schema/test_eq.py b/tests/safeds/data/tabular/typing/_schema/test_eq.py index 668d029b4..a36565b10 100644 --- a/tests/safeds/data/tabular/typing/_schema/test_eq.py +++ b/tests/safeds/data/tabular/typing/_schema/test_eq.py @@ -71,7 +71,7 @@ "not equal (different types)", ], ) -def test_should_return_whether_schemas_are_equal(schema_1: Schema, schema_2: Schema, expected: bool) -> None: +def test_should_return_whether_objects_are_equal(schema_1: Schema, schema_2: Schema, expected: bool) -> None: assert (schema_1.__eq__(schema_2)) == expected @@ -88,7 +88,7 @@ def test_should_return_whether_schemas_are_equal(schema_1: Schema, schema_2: Sch "two columns", ], ) -def test_should_return_true_if_schemas_are_identical(schema: Schema) -> None: +def test_should_return_true_if_objects_are_identical(schema: Schema) -> None: assert (schema.__eq__(schema)) is True @@ -103,5 +103,5 @@ def test_should_return_true_if_schemas_are_identical(schema: Schema) -> None: "Schema vs. Column", ], ) -def test_should_return_not_implemented_if_other_is_not_schema(schema: Schema, other: Any) -> None: +def test_should_return_not_implemented_if_other_has_different_type(schema: Schema, other: Any) -> None: assert (schema.__eq__(other)) is NotImplemented diff --git a/tests/safeds/data/tabular/typing/_schema/test_get_item.py b/tests/safeds/data/tabular/typing/_schema/test_get_item.py new file mode 100644 index 000000000..ed1a37a1a --- /dev/null +++ b/tests/safeds/data/tabular/typing/_schema/test_get_item.py @@ -0,0 +1,29 @@ +import pytest + +from safeds.data.tabular.typing import ColumnType, Schema +from safeds.exceptions import ColumnNotFoundError + + +@pytest.mark.parametrize( + ("schema", "name", "expected"), + [ + ( + Schema({"col1": ColumnType.int64()}), + "col1", + ColumnType.int64(), + ), + ( + Schema({"col1": ColumnType.string()}), + "col1", + ColumnType.string(), + ), + ], + ids=["int column", "string column"], +) +def test_should_return_data_type_of_column(schema: Schema, name: str, expected: ColumnType) -> None: + assert schema[name] == expected + + +def test_should_raise_if_column_name_is_unknown() -> None: + with pytest.raises(ColumnNotFoundError): + _ignored = Schema({})["col1"] diff --git a/tests/safeds/data/tabular/typing/_schema/test_has_column.py b/tests/safeds/data/tabular/typing/_schema/test_has_column.py index 38a182ccd..c01ee801e 100644 --- a/tests/safeds/data/tabular/typing/_schema/test_has_column.py +++ b/tests/safeds/data/tabular/typing/_schema/test_has_column.py @@ -12,5 +12,5 @@ ], ids=["empty", "has column", "doesn't have column"], ) -def test_should_return_if_column_is_in_schema(schema: Schema, column: str, expected: bool) -> None: +def test_should_check_if_column_is_in_schema(schema: Schema, column: str, expected: bool) -> None: assert schema.has_column(column) == expected diff --git a/tests/safeds/data/tabular/typing/_schema/test_iter.py b/tests/safeds/data/tabular/typing/_schema/test_iter.py new file mode 100644 index 000000000..1f9156bb7 --- /dev/null +++ b/tests/safeds/data/tabular/typing/_schema/test_iter.py @@ -0,0 +1,20 @@ +import pytest + +from safeds.data.tabular.typing import ColumnType, Schema + + +@pytest.mark.parametrize( + ("schema", "expected"), + [ + (Schema({}), []), + (Schema({"col1": ColumnType.null()}), ["col1"]), + (Schema({"col1": ColumnType.null(), "col2": ColumnType.null()}), ["col1", "col2"]), + ], + ids=[ + "empty", + "one column", + "two columns", + ], +) +def test_should_return_column_names(schema: Schema, expected: list[str]) -> None: + assert list(schema) == expected diff --git a/tests/safeds/data/tabular/typing/_schema/test_len.py b/tests/safeds/data/tabular/typing/_schema/test_len.py new file mode 100644 index 000000000..de8d63fa4 --- /dev/null +++ b/tests/safeds/data/tabular/typing/_schema/test_len.py @@ -0,0 +1,20 @@ +import pytest + +from safeds.data.tabular.typing import ColumnType, Schema + + +@pytest.mark.parametrize( + ("schema", "expected"), + [ + (Schema({}), 0), + (Schema({"col1": ColumnType.null()}), 1), + (Schema({"col1": ColumnType.null(), "col2": ColumnType.null()}), 2), + ], + ids=[ + "empty", + "one column", + "two columns", + ], +) +def test_should_return_number_of_columns(schema: Schema, expected: int) -> None: + assert len(schema) == expected