Enforce + Autoclass: AttributeError: 'functools.partial' object has no attribute '__enforcer__'
smarie opened this issue · 1 comments
smarie commented
This works:
from autoclass import autoclass, setter_override
from numbers import Real
from enforce import runtime_validation, config
config(dict(mode='covariant')) # to accept subclasses in validation
@runtime_validation
@autoclass
class HouseConfiguration(object):
def __init__(self, surface: Real):
pass
# -- overriden setter for surface
@setter_override
def surface(self, surface):
print('Set surface to {}'.format(surface))
self._surface = surface
t = HouseConfiguration(12)
While this throws an exception AttributeError: 'functools.partial' object has no attribute '__enforcer__'
:
from autoclass import autoclass, setter_override
from numbers import Real
from enforce import runtime_validation, config
config(dict(mode='covariant')) # to accept subclasses in validation
@autoclass
@runtime_validation
class HouseConfiguration(object):
def __init__(self, surface: Real):
pass
# -- overriden setter for surface
@setter_override
def surface(self, surface):
print('Set surface to {}'.format(surface))
self._surface = surface
t = HouseConfiguration(12)
The only difference is the order of the annotations on class HouseConfiguration.
smarie commented
After investigation, the 'wrong' order should be forbidden, since otherwise this would lead to non-intuitive behaviours. For example if there is a second attribute:
from autoclass import autoclass, setter_override
from numbers import Real
from enforce import runtime_validation, config
config(dict(mode='covariant')) # to accept subclasses in validation
@autoclass
@runtime_validation
class HouseConfiguration(object):
def __init__(self, surface: Real, name: str):
pass
# -- overriden setter for surface
@setter_override
def surface(self, surface):
print('Set surface to {}'.format(surface))
self._surface = surface
t = HouseConfiguration(12)
Then the setter for surface
would by checked by enforce, but not the setter for name
. For this reason we will detect and prevent such usage by raising an exception when the @autoclass, @autodict or @autoprops annotations are used after enforce decorator, rather than before.