Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
DeaMariaLeon committed Oct 7, 2024
1 parent 3e0405d commit 8ea88cd
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 1 deletion.
74 changes: 73 additions & 1 deletion narwhals/dtypes.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
from __future__ import annotations

from collections import OrderedDict
from datetime import timezone
from typing import TYPE_CHECKING
from typing import Iterator
from typing import Literal
from typing import Mapping
from typing import Sequence

if TYPE_CHECKING:
from typing_extensions import Self
Expand Down Expand Up @@ -170,7 +174,75 @@ class Categorical(DType): ...
class Enum(DType): ...


class Struct(DType): ...
class Field:
"""
Definition of a single field within a `Struct` DataType.
Parameters
----------
name
The name of the field within its parent `Struct`.
dtype
The `DataType` of the field's values.
"""

name: str
dtype: DType

def __init__(self, name: str, dtype: DType) -> None:
self.name = name
self.dtype = dtype

def __eq__(self, other: Field) -> bool: # type: ignore[override]
return (self.name == other.name) & (self.dtype == other.dtype)

def __hash__(self) -> int:
return hash((self.name, self.dtype))

def __repr__(self) -> str:
class_name = self.__class__.__name__
return f"{class_name}({self.name!r}, {self.dtype})"


class Struct(DType):
fields: list[Field]

def __init__(self, fields: Sequence[Field] | Mapping[str, DType]) -> None:
if isinstance(fields, Mapping):
self.fields = [Field(name, dtype) for name, dtype in fields.items()]
else:
self.fields = list(fields)

def __eq__(self, other: DType | type[DType]) -> bool: # type: ignore[override]
# The comparison allows comparing objects to classes, and specific
# inner types to those without (eg: inner=None). if one of the
# arguments is not specific about its inner type we infer it
# as being equal. (See the List type for more info).
if type(other) and issubclass(other, self.__class__):
return True
elif isinstance(other, self.__class__):
return self.fields == other.fields
else:
return False

def __hash__(self) -> int:
return hash((self.__class__, tuple(self.fields)))

def __iter__(self) -> Iterator[tuple[str, DType]]:
for fld in self.fields:
yield fld.name, fld.dtype

def __reversed__(self) -> Iterator[tuple[str, DType]]:
for fld in reversed(self.fields):
yield fld.name, fld.dtype

def __repr__(self) -> str:
class_name = self.__class__.__name__
return f"{class_name}({dict(self)})"

def to_schema(self) -> OrderedDict[str, DType]:
"""Return Struct dtype as a schema dict."""
return OrderedDict(self)


class List(DType):
Expand Down
1 change: 1 addition & 0 deletions narwhals/stable/v1/typing.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ class DTypes:
Datetime: type[dtypes.Datetime]
Duration: type[dtypes.Duration]
Date: type[dtypes.Date]
Field: type[dtypes.Field]
Struct: type[dtypes.Struct]
List: type[dtypes.List]
Array: type[dtypes.Array]
Expand Down
1 change: 1 addition & 0 deletions narwhals/typing.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ class DTypes:
Datetime: type[dtypes.Datetime]
Duration: type[dtypes.Duration]
Date: type[dtypes.Date]
Field: type[dtypes.Field]
Struct: type[dtypes.Struct]
List: type[dtypes.List]
Array: type[dtypes.Array]
Expand Down

0 comments on commit 8ea88cd

Please sign in to comment.