How to test a content type with a IContextAwareDefaultFactory

182 Views Asked by At

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?

1

There are 1 best solutions below

1
On

You are doing everything correctly. When in code you try to access subjects like that:

>>> object.subjects

When subjects has 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 calling

>>> object.__getattr__('subjects')

But this is not satisfactory.

In view code you do not have this problem, because the view does not access the attribute via object.subjects at 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