Skip to content

Instantly share code, notes, and snippets.

@iilei
Created March 27, 2024 04:28
Show Gist options
  • Save iilei/a7fa95d3b5f5f545322e79b223870fd5 to your computer and use it in GitHub Desktop.
Save iilei/a7fa95d3b5f5f545322e79b223870fd5 to your computer and use it in GitHub Desktop.
Make dataclass props initializable
from dataclasses import field, dataclass
import datetime
from functools import wraps
def props_to_init(additional_kwargs):
def decorator(cls):
def modify_init(init):
@wraps(init)
def __init__(self, **kwargs):
kwargs_without_properties = {
k: v for k, v in kwargs.items() if k not in additional_kwargs.keys()
}
init(
self,
**kwargs_without_properties,
)
for k, v in additional_kwargs.items():
setattr(self, k, v() if callable(v) else v)
return __init__
cls.__init__ = modify_init(cls.__init__)
return cls
return decorator
@props_to_init({"date": datetime.datetime.now})
@dataclass
class Config:
secret: dict[str, str] = field(default_factory=lambda: {}, repr=False)
date_slice: str = field(init=False, repr=False, default="")
# `date` is added to the `init` fields, see decorators
# __date is to provide the source of truth for property getter / setter
__date: datetime.datetime = field(
init=False, repr=False, default_factory=datetime.datetime.now
)
def __post_init__(self):
self.__date = self.date
self.date_slice = self.__date.strftime("%Y%m%d")
@property
def date(self) -> datetime.datetime:
return self.__date
@date.setter
def date(self, date: datetime.datetime) -> None:
self.__date = date
self.date_slice = self.__date.strftime("%Y%m%d")
t = Config(date=datetime.datetime(2021, 1, 1), secret={"user": "xyz"})
print(t.date_slice)
t.date = datetime.datetime(2022, 1, 2)
print(t.date_slice)
print(t.secret)
print(t.date)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment