diff --git a/pyproject.toml b/pyproject.toml index 1d0d405..757372d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -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", ] diff --git a/src/dataclassish/__init__.py b/src/dataclassish/__init__.py index fcaf4b7..79c22eb 100644 --- a/src/dataclassish/__init__.py +++ b/src/dataclassish/__init__.py @@ -18,7 +18,6 @@ "field_values", "field_items", # Classes - "DataclassInstance", "F", ) @@ -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 diff --git a/src/dataclassish/_src/converters.py b/src/dataclassish/_src/converters.py index 4ab1386..36514a4 100644 --- a/src/dataclassish/_src/converters.py +++ b/src/dataclassish/_src/converters.py @@ -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] diff --git a/src/dataclassish/_src/register_dataclass.py b/src/dataclassish/_src/register_dataclass.py index a44b15d..43408be 100644 --- a/src/dataclassish/_src/register_dataclass.py +++ b/src/dataclassish/_src/register_dataclass.py @@ -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: @@ -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: @@ -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: @@ -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: @@ -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, @@ -184,7 +188,7 @@ def asdict( @dispatch def astuple( - obj: DataclassInstance, + obj: opt.dataclasses.HasDataclassFields, /, *, tuple_factory: Callable[[Any], tuple[Any, ...]] = tuple, diff --git a/src/dataclassish/_src/types.py b/src/dataclassish/_src/types.py index 9ac8674..751845c 100644 --- a/src/dataclassish/_src/types.py +++ b/src/dataclassish/_src/types.py @@ -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 V = TypeVar("V") diff --git a/uv.lock b/uv.lock index b1b5610..f1be8e3 100644 --- a/uv.lock +++ b/uv.lock @@ -310,7 +310,7 @@ test = [ [package.metadata] requires-dist = [ - { name = "optype", specifier = ">=0.16.0" }, + { name = "optype", specifier = ">=0.17.0" }, { name = "plum-dispatch", specifier = ">=2.5.1" }, { name = "typing-extensions", specifier = ">=4.12.2" }, ] @@ -672,14 +672,14 @@ wheels = [ [[package]] name = "optype" -version = "0.16.0" +version = "0.17.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "typing-extensions", marker = "python_full_version < '3.13'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/66/d3/c88bb4bd90867356275ca839499313851af4b36fce6919ebc5e1de26e7ca/optype-0.16.0.tar.gz", hash = "sha256:fa682fd629ef6b70ba656ebc9fdd6614ba06ce13f52e0416dd8014c7e691a2d1", size = 53498, upload-time = "2026-02-19T23:37:09.495Z" } +sdist = { url = "https://files.pythonhosted.org/packages/81/9f/3b13bab05debf685678b8af004e46b8c67c6f98ffa08eaf5d33bcf162c16/optype-0.17.0.tar.gz", hash = "sha256:31351a1e64d9eba7bf67e14deefb286e85c66458db63c67dd5e26dd72e4664e5", size = 53484, upload-time = "2026-03-08T23:03:12.594Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/91/a8/fe26515203cff140f1afc31236fb7f703d4bb4bd5679d28afcb3661c8d9f/optype-0.16.0-py3-none-any.whl", hash = "sha256:c28905713f55630b4bb8948f38e027ad13a541499ebcf957501f486da54b74d2", size = 65893, upload-time = "2026-02-19T23:37:08.217Z" }, + { url = "https://files.pythonhosted.org/packages/6b/44/dca78187415947d1bb90b2ee2a58e47d9573528331e8dc6196996b53612a/optype-0.17.0-py3-none-any.whl", hash = "sha256:8c2d88ff13149454bcf6eb47502f80d288bc542e7238fcc412ac4d222c439397", size = 65854, upload-time = "2026-03-08T23:03:11.425Z" }, ] [[package]]