There is a really annoying bug in zope that if you use @property then self losses its acquisition wrapper. Thats not easy to solve.
Where this bites you is if you want a custom getter or setter using z3cform or dexterity. The obvious way to do that is using @property. If your code doesn't require acquisition it will still work but if it does it fail fail in unexpected ways.
There is a work around. Support explicit or implicit getters and setters like Archetypes used to. Here is code I used to do this for my usecase.
Should something like this be inplace by default in dexterity?
I'm surprised this issue hasn't come up more often.
class GetterSetterAttributeField(z3c.form.datamanager.AttributeField):
"""Special datamanager to get around loss on acquisition when using @property"""
zope.component.adapts(
IPlominoForm, zope.schema.interfaces.IField)
def get(self):
"""See z3c.form.interfaces.IDataManager"""
getter = "get%s"%self.field.__name__.capitalize()
if hasattr(self.adapted_context, getter):
return getattr(self.adapted_context, getter)()
else:
return getattr(self.adapted_context, self.field.__name__)
def set(self, value):
"""See z3c.form.interfaces.IDataManager"""
if self.field.readonly:
raise TypeError("Can't set values on read-only fields "
"(name=%s, class=%s.%s)"
% (self.field.__name__,
self.context.__class__.__module__,
self.context.__class__.__name__))
setter = "set%s"%self.field.__name__.capitalize()
if hasattr(self.adapted_context, setter):
getattr(self.adapted_context, setter)(value)
else:
# get the right adapter or context
setattr(self.adapted_context, self.field.__name__, value)