Created
March 18, 2022 20:32
-
-
Save rednafi/82e34135e6b6b5b4d83d63876bc5a3b9 to your computer and use it in GitHub Desktop.
Mutate the fields of a dataclass by applying ad-hoc mutation callables.
This file contains hidden or 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
from __future__ import annotations | |
import json | |
from collections.abc import Mapping | |
from dataclasses import dataclass | |
from typing import Callable | |
class Mutator: | |
def __init_subclass__( | |
cls, mutation: dict[str, Callable] | None = None | |
) -> None: | |
if not mutation: | |
return None | |
if not isinstance(mutation, Mapping): | |
raise TypeError( | |
"Mutation must be a Mapping between attribute name " | |
"and mutation callables.", | |
) | |
cls.__mutation__ = mutation | |
def __post_init__(self) -> None: | |
for attr, cb in self.__class__.__mutation__.items(): | |
if not isinstance(attr, str): | |
raise TypeError( | |
f"Mutation attribute '{attr}' is not a string." | |
) | |
if not callable(cb): | |
raise TypeError(f"Mutation callable '{cb}' is not a callable.") | |
setattr(self, attr, cb(getattr(self, attr))) | |
@dataclass | |
class Hello(Mutator, mutation={"a": lambda x: x ** 2, "b": json.dumps}): | |
a: int | |
b: dict | |
print(Hello(4, {"a": "b"})) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment