Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ classifiers = [
"Typing :: Typed",
]
dependencies = [
"optype>=0.16.0",
"optype>=0.17.0",
"plum-dispatch>=2.5.1",
"typing_extensions>=4.12.2",
]
Expand Down
3 changes: 1 addition & 2 deletions src/dataclassish/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
"field_values",
"field_items",
# Classes
"DataclassInstance",
"F",
)
Comment thread
nstarman marked this conversation as resolved.

Expand All @@ -33,7 +32,7 @@
get_field,
replace,
)
from ._src.types import DataclassInstance, F
from ._src.types import F
from ._version import version as __version__

# Register dispatches by importing the submodules
Expand Down
2 changes: 1 addition & 1 deletion src/dataclassish/_src/converters.py
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,7 @@ def field(


class DataclassWithConvertersInstance(Protocol):
"""DataclassInstance Protocol with additional ``__converter_init__``."""
"""Dataclass instance Protocol with additional ``__converter_init__``."""

__dataclass_fields__: ClassVar[dict[str, dataclasses.Field[Any]]]
__dataclass_init__: Callable[..., None]
Expand Down
18 changes: 11 additions & 7 deletions src/dataclassish/_src/register_dataclass.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,17 @@
)
from typing import Any

import optype as opt
from plum import dispatch

from .register_base import _recursive_replace_helper
from .types import DataclassInstance

# ===================================================================

if sys.version_info < (3, 13):

@dispatch
def get_field(obj: DataclassInstance, k: str, /) -> Any:
def get_field(obj: opt.dataclasses.HasDataclassFields, k: str, /) -> Any:
"""Get a field of a dataclass instance by name.

Examples:
Expand All @@ -49,7 +49,9 @@ def get_field(obj: DataclassInstance, k: str, /) -> Any:
if sys.version_info < (3, 13):

@dispatch
def replace(obj: DataclassInstance, /, **kwargs: Any) -> DataclassInstance:
def replace(
obj: opt.dataclasses.HasDataclassFields, /, **kwargs: Any
) -> opt.dataclasses.HasDataclassFields:
"""Replace the fields of a dataclass instance.

Examples:
Expand All @@ -72,7 +74,9 @@ def replace(obj: DataclassInstance, /, **kwargs: Any) -> DataclassInstance:
return _dataclass_replace(obj, **kwargs)

@dispatch # type: ignore[no-redef]
def replace(obj: DataclassInstance, fs: Mapping[str, Any], /) -> DataclassInstance:
def replace(
obj: opt.dataclasses.HasDataclassFields, fs: Mapping[str, Any], /
) -> opt.dataclasses.HasDataclassFields:
"""Replace the fields of a dataclass instance.

Examples:
Expand Down Expand Up @@ -127,7 +131,7 @@ def replace(obj: DataclassInstance, fs: Mapping[str, Any], /) -> DataclassInstan


@dispatch
def fields(obj: DataclassInstance, /) -> tuple[Field, ...]: # type: ignore[type-arg] # TODO: raise issue in beartype
def fields(obj: opt.dataclasses.HasDataclassFields, /) -> tuple[Field, ...]: # type: ignore[type-arg] # TODO: raise issue in beartype
"""Return the fields of a dataclass instance.

Examples:
Expand All @@ -154,7 +158,7 @@ def fields(obj: DataclassInstance, /) -> tuple[Field, ...]: # type: ignore[type

@dispatch
def asdict(
obj: DataclassInstance,
obj: opt.dataclasses.HasDataclassFields,
/,
*,
dict_factory: Callable[[list[tuple[str, Any]]], dict[str, Any]] = dict,
Expand Down Expand Up @@ -184,7 +188,7 @@ def asdict(

@dispatch
def astuple(
obj: DataclassInstance,
obj: opt.dataclasses.HasDataclassFields,
/,
*,
tuple_factory: Callable[[Any], tuple[Any, ...]] = tuple,
Expand Down
41 changes: 2 additions & 39 deletions src/dataclassish/_src/types.py
Original file line number Diff line number Diff line change
@@ -1,46 +1,9 @@
"""Data types for ``dataclassish``."""

__all__ = ("DataclassInstance", "F")
__all__ = ("F",)

from dataclasses import dataclass
from typing import Any, ClassVar, Generic, Protocol, TypeVar, runtime_checkable


@runtime_checkable
class DataclassInstance(Protocol):
"""Protocol for dataclass instances.

Examples
--------
>>> from dataclasses import dataclass
>>> from dataclassish import DataclassInstance

>>> @dataclass
... class Point:
... x: float
... y: float

>>> issubclass(Point, DataclassInstance)
True

>>> point = Point(1.0, 2.0)

>>> isinstance(point, DataclassInstance)
True

"""

__dataclass_fields__: ClassVar[dict[str, Any]]

# B/c of https://github.com/python/mypy/issues/3939 just having
# `__dataclass_fields__` is insufficient for `issubclass` checks.
@classmethod
def __subclasshook__(cls: type, c: type) -> bool:
"""Customize the subclass check."""
return hasattr(c, "__dataclass_fields__")


# ===================================================================
from typing import Generic, TypeVar
Comment thread
nstarman marked this conversation as resolved.

V = TypeVar("V")

Expand Down
8 changes: 4 additions & 4 deletions uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading