From 9a4d057742515ad55689553c6cb0dffe322514fb Mon Sep 17 00:00:00 2001 From: Marco Edward Gorelli Date: Fri, 4 Oct 2024 14:29:33 +0100 Subject: [PATCH] feat: make typing available under narwhals.stable.v1 (#1130) * make typing available under narwhals.stable.v1 * coverage * py-shiny compat --- narwhals/stable/v1/_dtypes.py | 86 +++++++++++++++++++++++++++++++++ narwhals/stable/v1/dtypes.py | 83 ++++++++++---------------------- narwhals/stable/v1/typing.py | 91 +++++++++++++++++++++++++++++++++++ pyproject.toml | 1 + 4 files changed, 204 insertions(+), 57 deletions(-) create mode 100644 narwhals/stable/v1/_dtypes.py create mode 100644 narwhals/stable/v1/typing.py diff --git a/narwhals/stable/v1/_dtypes.py b/narwhals/stable/v1/_dtypes.py new file mode 100644 index 0000000000..13dd3237da --- /dev/null +++ b/narwhals/stable/v1/_dtypes.py @@ -0,0 +1,86 @@ +from narwhals.dtypes import Array +from narwhals.dtypes import Boolean +from narwhals.dtypes import Categorical +from narwhals.dtypes import Date +from narwhals.dtypes import Datetime as NwDatetime +from narwhals.dtypes import DType +from narwhals.dtypes import Duration as NwDuration +from narwhals.dtypes import Enum +from narwhals.dtypes import Float32 +from narwhals.dtypes import Float64 +from narwhals.dtypes import Int8 +from narwhals.dtypes import Int16 +from narwhals.dtypes import Int32 +from narwhals.dtypes import Int64 +from narwhals.dtypes import List +from narwhals.dtypes import NumericType +from narwhals.dtypes import Object +from narwhals.dtypes import String +from narwhals.dtypes import Struct +from narwhals.dtypes import UInt8 +from narwhals.dtypes import UInt16 +from narwhals.dtypes import UInt32 +from narwhals.dtypes import UInt64 +from narwhals.dtypes import Unknown + + +class Datetime(NwDatetime): + """ + Data type representing a calendar date and time of day. + + Arguments: + time_unit: Unit of time. Defaults to `'us'` (microseconds). + time_zone: Time zone string, as defined in zoneinfo (to see valid strings run + `import zoneinfo; zoneinfo.available_timezones()` for a full list). + + Notes: + Adapted from Polars implementation at: + https://github.com/pola-rs/polars/blob/py-1.7.1/py-polars/polars/datatypes/classes.py#L398-L457 + """ + + def __hash__(self) -> int: + return hash(self.__class__) + + +class Duration(NwDuration): + """ + Data type representing a time duration. + + Arguments: + time_unit: Unit of time. Defaults to `'us'` (microseconds). + + Notes: + Adapted from Polars implementation at: + https://github.com/pola-rs/polars/blob/py-1.7.1/py-polars/polars/datatypes/classes.py#L460-L502 + """ + + def __hash__(self) -> int: + return hash(self.__class__) + + +__all__ = [ + "Array", + "Boolean", + "Categorical", + "Date", + "Datetime", + "Duration", + "DType", + "Enum", + "Float32", + "Float64", + "Int8", + "Int16", + "Int32", + "Int64", + "List", + "NumericType", + "Object", + "String", + "Struct", + "UInt8", + "UInt16", + "UInt32", + "UInt64", + "Unknown", +] diff --git a/narwhals/stable/v1/dtypes.py b/narwhals/stable/v1/dtypes.py index 0d1e584688..f36da97259 100644 --- a/narwhals/stable/v1/dtypes.py +++ b/narwhals/stable/v1/dtypes.py @@ -1,60 +1,27 @@ -from narwhals.dtypes import Array -from narwhals.dtypes import Boolean -from narwhals.dtypes import Categorical -from narwhals.dtypes import Date -from narwhals.dtypes import Datetime as NwDatetime -from narwhals.dtypes import Duration as NwDuration -from narwhals.dtypes import Enum -from narwhals.dtypes import Float32 -from narwhals.dtypes import Float64 -from narwhals.dtypes import Int8 -from narwhals.dtypes import Int16 -from narwhals.dtypes import Int32 -from narwhals.dtypes import Int64 -from narwhals.dtypes import List -from narwhals.dtypes import Object -from narwhals.dtypes import String -from narwhals.dtypes import Struct -from narwhals.dtypes import UInt8 -from narwhals.dtypes import UInt16 -from narwhals.dtypes import UInt32 -from narwhals.dtypes import UInt64 -from narwhals.dtypes import Unknown - - -class Datetime(NwDatetime): - """ - Data type representing a calendar date and time of day. - - Arguments: - time_unit: Unit of time. Defaults to `'us'` (microseconds). - time_zone: Time zone string, as defined in zoneinfo (to see valid strings run - `import zoneinfo; zoneinfo.available_timezones()` for a full list). - - Notes: - Adapted from Polars implementation at: - https://github.com/pola-rs/polars/blob/py-1.7.1/py-polars/polars/datatypes/classes.py#L398-L457 - """ - - def __hash__(self) -> int: - return hash(self.__class__) - - -class Duration(NwDuration): - """ - Data type representing a time duration. - - Arguments: - time_unit: Unit of time. Defaults to `'us'` (microseconds). - - Notes: - Adapted from Polars implementation at: - https://github.com/pola-rs/polars/blob/py-1.7.1/py-polars/polars/datatypes/classes.py#L460-L502 - """ - - def __hash__(self) -> int: - return hash(self.__class__) - +from narwhals.stable.v1._dtypes import Array +from narwhals.stable.v1._dtypes import Boolean +from narwhals.stable.v1._dtypes import Categorical +from narwhals.stable.v1._dtypes import Date +from narwhals.stable.v1._dtypes import Datetime +from narwhals.stable.v1._dtypes import DType +from narwhals.stable.v1._dtypes import Duration +from narwhals.stable.v1._dtypes import Enum +from narwhals.stable.v1._dtypes import Float32 +from narwhals.stable.v1._dtypes import Float64 +from narwhals.stable.v1._dtypes import Int8 +from narwhals.stable.v1._dtypes import Int16 +from narwhals.stable.v1._dtypes import Int32 +from narwhals.stable.v1._dtypes import Int64 +from narwhals.stable.v1._dtypes import List +from narwhals.stable.v1._dtypes import NumericType +from narwhals.stable.v1._dtypes import Object +from narwhals.stable.v1._dtypes import String +from narwhals.stable.v1._dtypes import Struct +from narwhals.stable.v1._dtypes import UInt8 +from narwhals.stable.v1._dtypes import UInt16 +from narwhals.stable.v1._dtypes import UInt32 +from narwhals.stable.v1._dtypes import UInt64 +from narwhals.stable.v1._dtypes import Unknown __all__ = [ "Array", @@ -63,6 +30,7 @@ def __hash__(self) -> int: "Date", "Datetime", "Duration", + "DType", "Enum", "Float32", "Float64", @@ -71,6 +39,7 @@ def __hash__(self) -> int: "Int32", "Int64", "List", + "NumericType", "Object", "String", "Struct", diff --git a/narwhals/stable/v1/typing.py b/narwhals/stable/v1/typing.py new file mode 100644 index 0000000000..e8ab9e1ae7 --- /dev/null +++ b/narwhals/stable/v1/typing.py @@ -0,0 +1,91 @@ +from __future__ import annotations + +from typing import TYPE_CHECKING +from typing import Any +from typing import Protocol +from typing import TypeVar +from typing import Union + +if TYPE_CHECKING: + import sys + + if sys.version_info >= (3, 10): + from typing import TypeAlias + else: + from typing_extensions import TypeAlias + + from narwhals.stable.v1 import DataFrame + from narwhals.stable.v1 import Expr + from narwhals.stable.v1 import LazyFrame + from narwhals.stable.v1 import Series + from narwhals.stable.v1 import dtypes + + # All dataframes supported by Narwhals have a + # `columns` property. Their similarities don't extend + # _that_ much further unfortunately... + class NativeFrame(Protocol): + @property + def columns(self) -> Any: ... + + def join(self, *args: Any, **kwargs: Any) -> Any: ... + + class DataFrameLike(Protocol): + def __dataframe__(self, *args: Any, **kwargs: Any) -> Any: ... + + +IntoExpr: TypeAlias = Union["Expr", str, "Series"] +"""Anything which can be converted to an expression.""" + +IntoDataFrame: TypeAlias = Union["NativeFrame", "DataFrame[Any]", "DataFrameLike"] +"""Anything which can be converted to a Narwhals DataFrame.""" + +IntoFrame: TypeAlias = Union[ + "NativeFrame", "DataFrame[Any]", "LazyFrame[Any]", "DataFrameLike" +] +"""Anything which can be converted to a Narwhals DataFrame or LazyFrame.""" + +Frame: TypeAlias = Union["DataFrame[Any]", "LazyFrame[Any]"] +"""Narwhals DataFrame or Narwhals LazyFrame""" + +# TypeVars for some of the above +IntoFrameT = TypeVar("IntoFrameT", bound="IntoFrame") +IntoDataFrameT = TypeVar("IntoDataFrameT", bound="IntoDataFrame") +FrameT = TypeVar("FrameT", bound="Frame") +DataFrameT = TypeVar("DataFrameT", bound="DataFrame[Any]") + + +class DTypes: + Int64: type[dtypes.Int64] + Int32: type[dtypes.Int32] + Int16: type[dtypes.Int16] + Int8: type[dtypes.Int8] + UInt64: type[dtypes.UInt64] + UInt32: type[dtypes.UInt32] + UInt16: type[dtypes.UInt16] + UInt8: type[dtypes.UInt8] + Float64: type[dtypes.Float64] + Float32: type[dtypes.Float32] + String: type[dtypes.String] + Boolean: type[dtypes.Boolean] + Object: type[dtypes.Object] + Categorical: type[dtypes.Categorical] + Enum: type[dtypes.Enum] + Datetime: type[dtypes.Datetime] + Duration: type[dtypes.Duration] + Date: type[dtypes.Date] + Struct: type[dtypes.Struct] + List: type[dtypes.List] + Array: type[dtypes.Array] + Unknown: type[dtypes.Unknown] + + +__all__ = [ + "IntoExpr", + "IntoDataFrame", + "IntoDataFrameT", + "IntoFrame", + "IntoFrameT", + "Frame", + "FrameT", + "DataFrameT", +] diff --git a/pyproject.toml b/pyproject.toml index 3c2a009684..24020caa60 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -154,6 +154,7 @@ plugins = ["covdefaults"] [tool.coverage.report] omit = [ 'narwhals/typing.py', + 'narwhals/stable/v1/typing.py', # we can run this in every environment that we measure coverage on due to upper-bound constraits 'narwhals/_ibis/*', ]