defl/defl/_dataclass_.py
2024-09-11 11:14:03 -04:00

73 lines
2.5 KiB
Python
Executable File

#!/usr/bin/env python
# https://github.com/FelixTheC/strongtyping/tree/main?tab=readme-ov-file
# git clone --depth 1 --recurse-submodules --shallow-submodules https://github.com/FelixTheC/strongtyping.git
import dataclasses
import inspect
import itertools
import typing
from functools import wraps
from inspect import signature
from types import *
from typing import *
from ._logger_ import log
from ._typeCheck_ import *
# TODO setattr verification
# == patch dataclass
def patchDataClassWithRunTimeValidator():
postInitStr = '__post_init__'
initStr = '__init__'
def _dataclassWrap(*args, **kargs):
ret = dataclasses._process_class_hidden(*args, **kargs)
def wrapOut(init):
def wrapIn(self, *args, **kargs):
__logIgnoreFrame__ = True
# log.info(type(self), args, kargs)
#| `init` is the class's __init__
#| `self` is the instantiated object
res = init(self, *args, **kargs) #| probably always None
myMod = inspect.getmodule(patchDataClassWithRunTimeValidator)
resMod = inspect.getmodule(self.__class__)
# log.info(self.__class__, myMod.__package__, resMod.__package__, resMod.__name__)
if (
myMod.__package__ != resMod.__package__ and # different package
resMod.__name__ != '__main__' # not defined in __main__
):
return res
#| validate args after __post_init__
checkObjectType(obj=self)
return res
return wrapIn
if (init := getattr(ret, initStr) if hasattr(ret, initStr) else None):
#| override signiture
try:
sig = signature(ret)
except ValueError as e:
e.add_note(str(ret))
e.add_note('make sure self is defined in function params.')
raise e
res = wrapOut(init)
res.__signature__ = sig
setattr(ret, initStr, res)
return ret
if not hasattr(dataclasses, '_process_class_hidden'):
dataclasses._process_class_hidden = dataclasses._process_class
dataclasses._process_class = _dataclassWrap
def unpatchDataClassWithRunTimeValidator():
if hasattr(dataclasses, '_process_class_hidden'):
dataclasses._process_class = dataclasses._process_class_hidden
del dataclasses._process_class_hidden