We have a Dexterity-based content type that must inherit a field's default value from its parent. We use the following:
In the model:
<model xmlns="http://namespaces.plone.org/supermodel/schema"
xmlns:indexer="http://namespaces.plone.org/supermodel/indexer"
xmlns:form="http://namespaces.plone.org/supermodel/form">
<schema>
...
<field name="subjects" type="zope.schema.Tuple" indexer:searchable="true">
...
<defaultFactory>my.package.content.default_subjects</defaultFactory>
...
</field>
</schema>
</model>
The factory is declared like this:
from zope.schema.interfaces import IContextAwareDefaultFactory
...
@provider(IContextAwareDefaultFactory)
def default_subjects(context):
return getattr(context, 'subjects', ())
This works fine when running an instance:
(Pdb) context
<MyType at /Plone/folder>
(Pdb) type(context)
<type 'Acquisition.ImplicitAcquisitionWrapper'>
But fails when running tests as context is not wrapped:
(Pdb) context
<MyType at test>
(Pdb) type(context)
<class 'my.package.content.MyType'>
How can I solve this?
You are doing everything correctly. When in code you try to access subjects like that:
When
subjectshas never been set, the__getattr__implementation of Dexterity starts its work. This__getattr__magic for missing attributes is implemented by Python. It somehow looses the acquisition wrapper. After loosing the acquisition wrapper, neither aq_parent nor parent continue to work. In my tests, I was able to circumvent this by callingBut this is not satisfactory.
In view code you do not have this problem, because the view does not access the attribute via
object.subjectsat all, so the acquisition context never gets lost.I'll finish my analysis here, but I noted my findings in a bugreport for plone.dexterity. Maybe you want to provide a minimal test there: https://github.com/plone/plone.dexterity/issues/53