-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* feat: 2nd commit * build: add typing_extensions * test: exclude pypy Signed-off-by: nstarman <nstarman@users.noreply.github.com>
- Loading branch information
Showing
10 changed files
with
146 additions
and
73 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,11 +1,21 @@ | ||
""" | ||
Copyright (c) 2024 Nathaniel Starkman. All rights reserved. | ||
"""Copyright (c) 2024 Nathaniel Starkman. All rights reserved. | ||
dataclasstools: dataclass tools, extended by multiple dispatch | ||
""" | ||
|
||
from __future__ import annotations | ||
|
||
from ._core import DataclassInstance, asdict, astuple, fields, replace | ||
from ._ext import field_items, field_values | ||
from ._version import version as __version__ | ||
|
||
__all__ = ["__version__"] | ||
__all__ = [ | ||
"__version__", | ||
# core | ||
"DataclassInstance", | ||
"replace", | ||
"fields", | ||
"asdict", | ||
"astuple", | ||
# ext | ||
"field_values", | ||
"field_items", | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
"""Core module for ``dataclasstools``.""" | ||
|
||
__all__ = ["DataclassInstance", "replace", "fields", "asdict", "astuple"] | ||
|
||
from collections.abc import Callable | ||
from dataclasses import Field as _dataclass_Field | ||
from dataclasses import asdict as _dataclass_asdict | ||
from dataclasses import astuple as _dataclass_astuple | ||
from dataclasses import fields as _dataclass_fields | ||
from dataclasses import replace as _dataclass_replace | ||
from typing import Any, ClassVar, Protocol, runtime_checkable | ||
|
||
from plum import dispatch | ||
|
||
|
||
@runtime_checkable | ||
class DataclassInstance(Protocol): | ||
"""Protocol for dataclass instances.""" | ||
|
||
__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__") | ||
|
||
|
||
@dispatch # type: ignore[misc] | ||
def replace(obj: DataclassInstance, /, **kwargs: Any) -> DataclassInstance: | ||
"""Replace the fields of a dataclass instance.""" | ||
return _dataclass_replace(obj, **kwargs) | ||
|
||
|
||
@dispatch # type: ignore[misc] | ||
def fields(obj: DataclassInstance) -> tuple[_dataclass_Field[Any], ...]: | ||
"""Return the fields of a dataclass instance.""" | ||
return _dataclass_fields(obj) | ||
|
||
|
||
@dispatch # type: ignore[misc] | ||
def asdict( | ||
obj: DataclassInstance, | ||
/, | ||
*, | ||
dict_factory: Callable[[list[tuple[str, Any]]], dict[str, Any]] = dict, | ||
) -> dict[str, Any]: | ||
"""Return the fields of a dataclass instance as a dictionary.""" | ||
return _dataclass_asdict(obj, dict_factory=dict_factory) | ||
|
||
|
||
@dispatch # type: ignore[misc] | ||
def astuple( | ||
obj: DataclassInstance, | ||
/, | ||
tuple_factory: Callable[[Any], tuple[Any, ...]] = tuple, | ||
) -> tuple[Any, ...]: | ||
"""Return the fields of a dataclass instance as a tuple.""" | ||
return _dataclass_astuple(obj, tuple_factory=tuple_factory) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
"""Extension functions for ``dataclasstools``.""" | ||
|
||
__all__ = ["field_values", "field_items"] | ||
|
||
from collections.abc import Iterator | ||
from typing import Any | ||
|
||
from plum import dispatch | ||
|
||
from ._core import DataclassInstance, fields | ||
|
||
|
||
@dispatch # type: ignore[misc] | ||
def field_values(obj: DataclassInstance) -> Iterator[Any]: | ||
"""Return the values of a dataclass instance.""" | ||
yield from (getattr(obj, f.name) for f in fields(obj)) | ||
|
||
|
||
@dispatch # type: ignore[misc] | ||
def field_items(obj: DataclassInstance) -> Iterator[tuple[str, Any]]: | ||
"""Return the field names and values of a dataclass instance.""" | ||
yield from ((f.name, getattr(obj, f.name)) for f in fields(obj)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,2 @@ | ||
from __future__ import annotations | ||
|
||
version: str | ||
version_tuple: tuple[int, int, int] | tuple[int, int, int, str, str] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
"""Tests.""" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,10 @@ | ||
from __future__ import annotations | ||
"""Test the package metadata.""" | ||
|
||
import importlib.metadata | ||
|
||
import dataclasstools as m | ||
|
||
|
||
def test_version(): | ||
"""Test that the package version matches the metadata.""" | ||
assert importlib.metadata.version("dataclasstools") == m.__version__ |