diff --git a/narwhals/_arrow/dataframe.py b/narwhals/_arrow/dataframe.py index 034cf28759..bbca27f01e 100644 --- a/narwhals/_arrow/dataframe.py +++ b/narwhals/_arrow/dataframe.py @@ -47,8 +47,8 @@ from narwhals._typing import _EagerAllowedImpl, _LazyAllowedImpl from narwhals._utils import Version, _LimitedContext from narwhals.dtypes import DType + from narwhals.schema import Schema from narwhals.typing import ( - IntoSchema, JoinStrategy, SizedMultiIndexSelector, SizedMultiNameSelector, @@ -114,11 +114,9 @@ def from_dict( /, *, context: _LimitedContext, - schema: IntoSchema | None, + schema: Schema | None, ) -> Self: - from narwhals.schema import Schema - - pa_schema = Schema(schema).to_arrow() if schema is not None else schema + pa_schema = schema.to_arrow() if schema is not None else schema if pa_schema and not data: native = pa_schema.empty_table() else: @@ -132,11 +130,9 @@ def from_dicts( /, *, context: _LimitedContext, - schema: IntoSchema | None, + schema: Schema | None, ) -> Self: - from narwhals.schema import Schema - - pa_schema = Schema(schema).to_arrow() if schema is not None else schema + pa_schema = schema.to_arrow() if schema is not None else schema if pa_schema and not data: native = pa_schema.empty_table() else: @@ -158,13 +154,13 @@ def from_numpy( /, *, context: _LimitedContext, - schema: IntoSchema | Sequence[str] | None, + schema: Schema | Sequence[str] | None, ) -> Self: from narwhals.schema import Schema arrays = [pa.array(val) for val in data.T] - if isinstance(schema, (Mapping, Schema)): - native = pa.Table.from_arrays(arrays, schema=Schema(schema).to_arrow()) + if isinstance(schema, Schema): + native = pa.Table.from_arrays(arrays, schema=schema.to_arrow()) else: native = pa.Table.from_arrays(arrays, cls._numpy_column_names(data, schema)) return cls.from_native(native, context=context) diff --git a/narwhals/_compliant/dataframe.py b/narwhals/_compliant/dataframe.py index 03361545bf..bc938e8dfc 100644 --- a/narwhals/_compliant/dataframe.py +++ b/narwhals/_compliant/dataframe.py @@ -58,9 +58,9 @@ from narwhals.dataframe import DataFrame from narwhals.dtypes import DType from narwhals.exceptions import ColumnNotFoundError + from narwhals.schema import Schema from narwhals.typing import ( AsofJoinStrategy, - IntoSchema, JoinStrategy, MultiColSelector, MultiIndexSelector, @@ -190,7 +190,7 @@ def from_dict( /, *, context: _LimitedContext, - schema: IntoSchema | None, + schema: Schema | None, ) -> Self: ... @classmethod def from_dicts( @@ -199,7 +199,7 @@ def from_dicts( /, *, context: _LimitedContext, - schema: IntoSchema | None, + schema: Schema | None, ) -> Self: ... @classmethod def from_numpy( @@ -208,7 +208,7 @@ def from_numpy( /, *, context: _LimitedContext, - schema: IntoSchema | Sequence[str] | None, + schema: Schema | Sequence[str] | None, ) -> Self: ... def __array__(self, dtype: Any, *, copy: bool | None) -> _2DArray: ... def __getitem__( diff --git a/narwhals/_compliant/namespace.py b/narwhals/_compliant/namespace.py index 6f7062be35..63be4817b3 100644 --- a/narwhals/_compliant/namespace.py +++ b/narwhals/_compliant/namespace.py @@ -29,11 +29,11 @@ from narwhals._compliant.selectors import CompliantSelectorNamespace from narwhals._utils import Implementation, Version + from narwhals.schema import Schema from narwhals.typing import ( ConcatMethod, Into1DArray, IntoDType, - IntoSchema, NonNestedLiteral, _2DArray, ) @@ -206,14 +206,14 @@ def from_numpy(self, data: Into1DArray, /, schema: None = ...) -> EagerSeriesT_c @overload def from_numpy( - self, data: _2DArray, /, schema: IntoSchema | Sequence[str] | None + self, data: _2DArray, /, schema: Schema | Sequence[str] | None ) -> EagerDataFrameT: ... def from_numpy( self, data: Into1DArray | _2DArray, /, - schema: IntoSchema | Sequence[str] | None = None, + schema: Schema | Sequence[str] | None = None, ) -> EagerDataFrameT | EagerSeriesT_co: if is_numpy_array_2d(data): return self._dataframe.from_numpy(data, schema=schema, context=self) diff --git a/narwhals/_pandas_like/dataframe.py b/narwhals/_pandas_like/dataframe.py index 13e2351a2c..97e8cdb26f 100644 --- a/narwhals/_pandas_like/dataframe.py +++ b/narwhals/_pandas_like/dataframe.py @@ -1,6 +1,5 @@ from __future__ import annotations -from collections.abc import Iterable, Iterator, Mapping, Sequence from itertools import chain, product from typing import TYPE_CHECKING, Any, Callable, Literal, cast, overload @@ -33,8 +32,10 @@ ) from narwhals.dependencies import is_pandas_like_dataframe from narwhals.exceptions import InvalidOperationError, ShapeError +from narwhals.schema import Schema if TYPE_CHECKING: + from collections.abc import Iterable, Iterator, Mapping, Sequence from io import BytesIO from pathlib import Path from types import ModuleType @@ -55,7 +56,6 @@ from narwhals.typing import ( AsofJoinStrategy, DTypeBackend, - IntoSchema, JoinStrategy, PivotAgg, SizedMultiIndexSelector, @@ -147,10 +147,8 @@ def from_dict( /, *, context: _LimitedContext, - schema: IntoSchema | None, + schema: Schema | None, ) -> Self: - from narwhals.schema import Schema - implementation = context._implementation ns = implementation.to_native_namespace() Series = cast("type[pd.Series[Any]]", ns.Series) @@ -175,7 +173,7 @@ def from_dict( backend: Iterable[DTypeBackend] | None = None if aligned_data: backend = iter_dtype_backends(native.dtypes, implementation) - native = native.astype(Schema(schema).to_pandas(backend)) + native = native.astype(schema.to_pandas(backend)) return cls.from_native(native, context=context) @classmethod @@ -185,10 +183,8 @@ def from_dicts( /, *, context: _LimitedContext, - schema: IntoSchema | None, + schema: Schema | None, ) -> Self: - from narwhals.schema import Schema - implementation = context._implementation ns = implementation.to_native_namespace() DataFrame = cast("type[pd.DataFrame]", ns.DataFrame) @@ -200,7 +196,7 @@ def from_dicts( backend: Iterable[DTypeBackend] | None = None if data: backend = iter_dtype_backends(native.dtypes, implementation) - native = native.astype(Schema(schema).to_pandas(backend)) + native = native.astype(schema.to_pandas(backend)) return cls.from_native(native, context=context) @staticmethod @@ -223,20 +219,16 @@ def from_numpy( /, *, context: _LimitedContext, - schema: IntoSchema | Sequence[str] | None, + schema: Schema | Sequence[str] | None, ) -> Self: - from narwhals.schema import Schema - implementation = context._implementation DataFrame: Constructor = implementation.to_native_namespace().DataFrame - if isinstance(schema, (Mapping, Schema)): + if isinstance(schema, Schema): it: Iterable[DTypeBackend] = ( get_dtype_backend(native_type, implementation) for native_type in schema.values() ) - native = DataFrame(data, columns=schema.keys()).astype( - Schema(schema).to_pandas(it) - ) + native = DataFrame(data, columns=schema.keys()).astype(schema.to_pandas(it)) else: native = DataFrame(data, columns=cls._numpy_column_names(data, schema)) return cls.from_native(native, context=context) diff --git a/narwhals/_polars/dataframe.py b/narwhals/_polars/dataframe.py index 94984acb73..bfc4c29012 100644 --- a/narwhals/_polars/dataframe.py +++ b/narwhals/_polars/dataframe.py @@ -29,6 +29,7 @@ ) from narwhals.dependencies import is_numpy_array_1d from narwhals.exceptions import ColumnNotFoundError +from narwhals.schema import Schema if TYPE_CHECKING: from collections.abc import Iterable @@ -49,7 +50,6 @@ from narwhals.dataframe import DataFrame, LazyFrame from narwhals.dtypes import DType from narwhals.typing import ( - IntoSchema, JoinStrategy, MultiColSelector, MultiIndexSelector, @@ -316,11 +316,9 @@ def from_dict( /, *, context: _LimitedContext, - schema: IntoSchema | None, + schema: Schema | None, ) -> Self: - from narwhals.schema import Schema - - pl_schema = Schema(schema).to_polars() if schema is not None else schema + pl_schema = schema.to_polars() if schema is not None else schema return cls.from_native(pl.from_dict(data, pl_schema), context=context) @classmethod @@ -330,11 +328,9 @@ def from_dicts( /, *, context: _LimitedContext, - schema: IntoSchema | None, + schema: Schema | None, ) -> Self: - from narwhals.schema import Schema - - pl_schema = Schema(schema).to_polars() if schema is not None else schema + pl_schema = schema.to_polars() if schema is not None else schema if not data: native = pl.DataFrame(schema=pl_schema) elif FROM_DICTS_ACCEPTS_MAPPINGS or isinstance(data[0], dict): @@ -358,15 +354,9 @@ def from_numpy( /, *, context: _LimitedContext, # NOTE: Maybe only `Implementation`? - schema: IntoSchema | Sequence[str] | None, + schema: Schema | Sequence[str] | None, ) -> Self: - from narwhals.schema import Schema - - pl_schema = ( - Schema(schema).to_polars() - if isinstance(schema, (Mapping, Schema)) - else schema - ) + pl_schema = schema.to_polars() if isinstance(schema, Schema) else schema return cls.from_native(pl.from_numpy(data, pl_schema), context=context) def to_narwhals(self) -> DataFrame[pl.DataFrame]: diff --git a/narwhals/_polars/namespace.py b/narwhals/_polars/namespace.py index ac8da364be..be091c2b0f 100644 --- a/narwhals/_polars/namespace.py +++ b/narwhals/_polars/namespace.py @@ -22,7 +22,8 @@ from narwhals._polars.dataframe import Method, PolarsDataFrame, PolarsLazyFrame from narwhals._polars.typing import FrameT from narwhals._utils import Version, _LimitedContext - from narwhals.typing import Into1DArray, IntoDType, IntoSchema, TimeUnit, _2DArray + from narwhals.schema import Schema + from narwhals.typing import Into1DArray, IntoDType, TimeUnit, _2DArray class PolarsNamespace: @@ -97,14 +98,14 @@ def from_numpy(self, data: Into1DArray, /, schema: None = ...) -> PolarsSeries: @overload def from_numpy( - self, data: _2DArray, /, schema: IntoSchema | Sequence[str] | None + self, data: _2DArray, /, schema: Schema | Sequence[str] | None ) -> PolarsDataFrame: ... def from_numpy( self, data: Into1DArray | _2DArray, /, - schema: IntoSchema | Sequence[str] | None = None, + schema: Schema | Sequence[str] | None = None, ) -> PolarsDataFrame | PolarsSeries: if is_numpy_array_2d(data): return self._dataframe.from_numpy(data, schema=schema, context=self) diff --git a/narwhals/dataframe.py b/narwhals/dataframe.py index 74f1c68b03..9bab5512aa 100644 --- a/narwhals/dataframe.py +++ b/narwhals/dataframe.py @@ -39,6 +39,7 @@ is_lazy_allowed, is_list_of, is_sequence_like, + is_sequence_of, is_slice_none, predicates_contains_list_of_bool, qualified_type_name, @@ -603,7 +604,8 @@ def from_dict( implementation = Implementation.from_backend(backend) if is_eager_allowed(implementation): ns = cls._version.namespace.from_backend(implementation).compliant - compliant = ns._dataframe.from_dict(data, schema=schema, context=ns) + schema_ = Schema(schema) if schema is not None else None + compliant = ns._dataframe.from_dict(data, schema=schema_, context=ns) return cls(compliant, level="full") # NOTE: (#2786) needs resolving for extensions msg = ( @@ -673,7 +675,8 @@ def from_dicts( implementation = Implementation.from_backend(backend) if is_eager_allowed(implementation): ns = cls._version.namespace.from_backend(implementation).compliant - compliant = ns._dataframe.from_dicts(data, schema=schema, context=ns) + schema_ = Schema(schema) if schema is not None else None + compliant = ns._dataframe.from_dicts(data, schema=schema_, context=ns) return cls(compliant, level="full") # NOTE: (#2786) needs resolving for extensions msg = ( @@ -745,8 +748,13 @@ def from_numpy( raise TypeError(msg) implementation = Implementation.from_backend(backend) if is_eager_allowed(implementation): + schema_ = ( + schema + if schema is None or is_sequence_of(schema, str) + else Schema(schema) + ) ns = cls._version.namespace.from_backend(implementation).compliant - return cls(ns.from_numpy(data, schema), level="full") + return cls(ns.from_numpy(data, schema_), level="full") msg = ( f"{implementation} support in Narwhals is lazy-only, but `DataFrame.from_numpy` is an eager-only function.\n\n" "Hint: you may want to use an eager backend and then call `.lazy`, e.g.:\n\n" diff --git a/narwhals/functions.py b/narwhals/functions.py index 28ab30a641..c6d2b3ef71 100644 --- a/narwhals/functions.py +++ b/narwhals/functions.py @@ -17,14 +17,10 @@ supports_arrow_c_stream, validate_laziness, ) -from narwhals.dependencies import ( - is_narwhals_series, - is_numpy_array, - is_numpy_array_2d, - is_pyarrow_table, -) +from narwhals.dependencies import is_narwhals_series, is_numpy_array, is_pyarrow_table from narwhals.exceptions import InvalidOperationError from narwhals.expr import Expr +from narwhals.schema import Schema from narwhals.translate import from_native, to_native if TYPE_CHECKING: @@ -272,28 +268,7 @@ def from_dict( """ if backend is None: data, backend = _from_dict_no_backend(data) - implementation = Implementation.from_backend(backend) - if is_eager_allowed(implementation): - ns = Version.MAIN.namespace.from_backend(implementation).compliant - return ns._dataframe.from_dict(data, schema=schema, context=ns).to_narwhals() - if implementation is Implementation.UNKNOWN: # pragma: no cover - _native_namespace = implementation.to_native_namespace() - try: - # implementation is UNKNOWN, Narwhals extension using this feature should - # implement `from_dict` function in the top-level namespace. - native_frame: NativeDataFrame = _native_namespace.from_dict( - data, schema=schema - ) - except AttributeError as e: - msg = "Unknown namespace is expected to implement `from_dict` function." - raise AttributeError(msg) from e - return from_native(native_frame, eager_only=True) - msg = ( - f"{implementation} support in Narwhals is lazy-only, but `from_dict` is an eager-only function.\n\n" - "Hint: you may want to use an eager backend and then call `.lazy`, e.g.:\n\n" - f" nw.from_dict({{'a': [1, 2]}}, backend='pyarrow').lazy('{implementation}')" - ) - raise ValueError(msg) + return Version.MAIN.dataframe.from_dict(data, schema, backend=backend) def _from_dict_no_backend( @@ -415,43 +390,10 @@ def from_numpy( | e: [[1,3]] | └──────────────────┘ """ - if not is_numpy_array_2d(data): - msg = "`from_numpy` only accepts 2D numpy arrays" - raise ValueError(msg) - if not _is_into_schema(schema): - msg = ( - "`schema` is expected to be one of the following types: " - "IntoSchema | Sequence[str]. " - f"Got {type(schema)}." - ) - raise TypeError(msg) - implementation = Implementation.from_backend(backend) - if is_eager_allowed(implementation): - ns = Version.MAIN.namespace.from_backend(implementation).compliant - return ns.from_numpy(data, schema).to_narwhals() - if implementation is Implementation.UNKNOWN: # pragma: no cover - _native_namespace = implementation.to_native_namespace() - try: - # implementation is UNKNOWN, Narwhals extension using this feature should - # implement `from_numpy` function in the top-level namespace. - native_frame: NativeDataFrame = _native_namespace.from_numpy( - data, schema=schema - ) - except AttributeError as e: - msg = "Unknown namespace is expected to implement `from_numpy` function." - raise AttributeError(msg) from e - return from_native(native_frame, eager_only=True) - msg = ( - f"{implementation} support in Narwhals is lazy-only, but `from_numpy` is an eager-only function.\n\n" - "Hint: you may want to use an eager backend and then call `.lazy`, e.g.:\n\n" - f" nw.from_numpy(arr, backend='pyarrow').lazy('{implementation}')" - ) - raise ValueError(msg) + return Version.MAIN.dataframe.from_numpy(data, schema, backend=backend) def _is_into_schema(obj: Any) -> TypeIs[_IntoSchema]: - from narwhals.schema import Schema - return ( obj is None or isinstance(obj, (Mapping, Schema)) or is_sequence_but_not_str(obj) ) diff --git a/narwhals/schema.py b/narwhals/schema.py index b459be68fa..0b14c4f074 100644 --- a/narwhals/schema.py +++ b/narwhals/schema.py @@ -30,19 +30,20 @@ import pyarrow as pa from typing_extensions import Self - from narwhals.dtypes import DType from narwhals.typing import ( DTypeBackend, IntoArrowSchema, + IntoDType, IntoPandasSchema, IntoPolarsSchema, + IntoSchema, ) __all__ = ["Schema"] -class Schema(OrderedDict[str, "DType"]): +class Schema(OrderedDict[str, "IntoDType"]): """Ordered mapping of column names to their data type. Arguments: @@ -74,9 +75,7 @@ class Schema(OrderedDict[str, "DType"]): _version: ClassVar[Version] = Version.MAIN - def __init__( - self, schema: Mapping[str, DType] | Iterable[tuple[str, DType]] | None = None - ) -> None: + def __init__(self, schema: IntoSchema | None = None) -> None: schema = schema or {} super().__init__(schema) @@ -84,7 +83,7 @@ def names(self) -> list[str]: """Get the column names of the schema.""" return list(self.keys()) - def dtypes(self) -> list[DType]: + def dtypes(self) -> list[IntoDType]: """Get the data types of the schema.""" return list(self.values()) @@ -126,8 +125,10 @@ def from_arrow(cls, schema: IntoArrowSchema, /) -> Self: from narwhals._arrow.utils import native_to_narwhals_dtype return cls( - (field.name, native_to_narwhals_dtype(field.type, cls._version)) - for field in schema + tuple( + (field.name, native_to_narwhals_dtype(field.type, cls._version)) + for field in schema + ) ) @classmethod @@ -232,8 +233,10 @@ def from_polars(cls, schema: IntoPolarsSchema, /) -> Self: from narwhals._polars.utils import native_to_narwhals_dtype return cls( - (name, native_to_narwhals_dtype(dtype, cls._version)) - for name, dtype in schema.items() + tuple( + (name, native_to_narwhals_dtype(dtype, cls._version)) + for name, dtype in schema.items() + ) ) def to_arrow(self) -> pa.Schema: @@ -360,6 +363,13 @@ def _from_pandas_like( impl = implementation return cls( - (name, native_to_narwhals_dtype(dtype, cls._version, impl, allow_object=True)) - for name, dtype in schema.items() + tuple( + ( + name, + native_to_narwhals_dtype( + dtype, cls._version, impl, allow_object=True + ), + ) + for name, dtype in schema.items() + ) ) diff --git a/narwhals/stable/v1/__init__.py b/narwhals/stable/v1/__init__.py index 42d06ce928..7b47e3ed5e 100644 --- a/narwhals/stable/v1/__init__.py +++ b/narwhals/stable/v1/__init__.py @@ -80,7 +80,6 @@ Polars, ) from narwhals.dataframe import MultiColSelector, MultiIndexSelector - from narwhals.dtypes import DType from narwhals.typing import ( FileSource, IntoDType, @@ -128,7 +127,7 @@ def from_arrow( def from_dict( cls, data: Mapping[str, Any], - schema: Mapping[str, DType] | Schema | None = None, + schema: IntoSchema | None = None, *, backend: IntoBackend[EagerAllowed] | None = None, ) -> DataFrame[Any]: @@ -150,7 +149,7 @@ def from_dicts( def from_numpy( cls, data: _2DArray, - schema: Mapping[str, DType] | Schema | Sequence[str] | None = None, + schema: IntoSchema | Sequence[str] | None = None, *, backend: IntoBackend[EagerAllowed], ) -> DataFrame[Any]: @@ -453,9 +452,7 @@ class Schema(NwSchema): _version = Version.V1 @inherit_doc(NwSchema) - def __init__( - self, schema: Mapping[str, DType] | Iterable[tuple[str, DType]] | None = None - ) -> None: + def __init__(self, schema: IntoSchema | None = None) -> None: super().__init__(schema) @@ -1252,7 +1249,7 @@ def from_arrow( @deprecate_native_namespace() def from_dict( data: Mapping[str, Any], - schema: Mapping[str, DType] | Schema | None = None, + schema: IntoSchema | None = None, *, backend: IntoBackend[EagerAllowed] | None = None, native_namespace: ModuleType | None = None, # noqa: ARG001 @@ -1272,7 +1269,7 @@ def from_dict( @deprecate_native_namespace(required=True) def from_numpy( data: _2DArray, - schema: Mapping[str, DType] | Schema | Sequence[str] | None = None, + schema: IntoSchema | Sequence[str] | None = None, *, backend: IntoBackend[EagerAllowed] | None = None, native_namespace: ModuleType | None = None, # noqa: ARG001 diff --git a/narwhals/stable/v2/__init__.py b/narwhals/stable/v2/__init__.py index dde3c86aa4..97167d4409 100644 --- a/narwhals/stable/v2/__init__.py +++ b/narwhals/stable/v2/__init__.py @@ -74,7 +74,6 @@ Polars, ) from narwhals.dataframe import MultiColSelector, MultiIndexSelector - from narwhals.dtypes import DType from narwhals.typing import ( IntoDType, IntoExpr, @@ -120,7 +119,7 @@ def from_arrow( def from_dict( cls, data: Mapping[str, Any], - schema: Mapping[str, DType] | Schema | None = None, + schema: IntoSchema | None = None, *, backend: IntoBackend[EagerAllowed] | None = None, ) -> DataFrame[Any]: @@ -142,7 +141,7 @@ def from_dicts( def from_numpy( cls, data: _2DArray, - schema: Mapping[str, DType] | Schema | Sequence[str] | None = None, + schema: IntoSchema | Sequence[str] | None = None, *, backend: IntoBackend[EagerAllowed], ) -> DataFrame[Any]: @@ -311,9 +310,7 @@ class Schema(NwSchema): _version = Version.V2 @inherit_doc(NwSchema) - def __init__( - self, schema: Mapping[str, DType] | Iterable[tuple[str, DType]] | None = None - ) -> None: + def __init__(self, schema: IntoSchema | None = None) -> None: super().__init__(schema) @@ -1031,7 +1028,7 @@ def from_arrow( def from_dict( data: Mapping[str, Any], - schema: Mapping[str, DType] | Schema | None = None, + schema: IntoSchema | None = None, *, backend: IntoBackend[EagerAllowed] | None = None, ) -> DataFrame[Any]: @@ -1066,7 +1063,7 @@ def from_dict( def from_numpy( data: _2DArray, - schema: Mapping[str, DType] | Schema | Sequence[str] | None = None, + schema: IntoSchema | Sequence[str] | None = None, *, backend: IntoBackend[EagerAllowed], ) -> DataFrame[Any]: diff --git a/narwhals/typing.py b/narwhals/typing.py index 8c89b7745b..a6f7f31867 100644 --- a/narwhals/typing.py +++ b/narwhals/typing.py @@ -302,10 +302,9 @@ def Binary(self) -> type[dtypes.Binary]: ... └──────────────────┘ """ - -# TODO @dangotbanned: fix this? -# Constructor allows tuples, but we don't support that *everywhere* yet -IntoSchema: TypeAlias = "Mapping[str, dtypes.DType] | Schema" +IntoSchema: TypeAlias = ( + "Mapping[str, IntoDType] | Sequence[tuple[str, IntoDType]] | Schema" +) """Anything that can be converted into a Narwhals Schema. Defined by column names and their associated *instantiated* Narwhals DType. diff --git a/tests/testing/assert_series_equal_test.py b/tests/testing/assert_series_equal_test.py index d16e1065ce..9f757c0509 100644 --- a/tests/testing/assert_series_equal_test.py +++ b/tests/testing/assert_series_equal_test.py @@ -11,9 +11,11 @@ from tests.utils import PANDAS_VERSION, POLARS_VERSION, PYARROW_VERSION if TYPE_CHECKING: + from collections.abc import Mapping + from typing_extensions import TypeAlias - from narwhals.typing import IntoSchema, IntoSeriesT + from narwhals.typing import IntoDType, IntoSeriesT from tests.conftest import Data from tests.utils import ConstructorEager @@ -31,7 +33,9 @@ def series_from_native(native: IntoSeriesT) -> nw.Series[IntoSeriesT]: def test_self_equal( - constructor_eager: ConstructorEager, testing_data: Data, testing_schema: IntoSchema + constructor_eager: ConstructorEager, + testing_data: Data, + testing_schema: Mapping[str, IntoDType], ) -> None: """Test that a series is equal to itself, including nested dtypes with nulls.""" if "pandas" in str(constructor_eager): diff --git a/tests/testing/conftest.py b/tests/testing/conftest.py index ffb4fcc6fb..af83c78189 100644 --- a/tests/testing/conftest.py +++ b/tests/testing/conftest.py @@ -8,12 +8,14 @@ import narwhals as nw if TYPE_CHECKING: - from narwhals.typing import IntoSchema + from collections.abc import Mapping + + from narwhals.typing import IntoDType from tests.conftest import Data @pytest.fixture(scope="module") -def testing_schema() -> IntoSchema: +def testing_schema() -> Mapping[str, IntoDType]: return { "int": nw.Int32(), "float": nw.Float32(),