DocTest fails when creating an object

99 Views Asked by At

I'm having a problem with a doctest because I'm trying to rename the IDs of a content type object in an IObjectAddedEvent handler. My requirement is to have IDs that are sequential and context specific eg CAM-001, CAM-002, BLK-001, BLK-002, etc

When I add a object manually in the browser the event handler renames the id correctly but when I try create it in a doctest it fails soon after it is added to it's container. plone.dexterity addContentToContainer calls _setObject with the original id, then the event handler kicks in and renames the id, and then when _getObject uses original id it obviously can't find the object so it bomb with an attribute error.

I created a product to illustrate this here https://github.com/mikejmets/wt.testrig.

I also tried using plone.api in the doctest but that also fails.

All ideas welcome.

1

There are 1 best solutions below

3
On BEST ANSWER

Since you are using dexterity, the best solution would be to write your own NameGenerator behavior.

I guess your DX content has the following behavior activated: <element value="plone.app.content.interfaces.INameFromTitle" />

This bahavior is responsible to rename the item after creation. You should remove this and add your own.

Example:

Register behavior with zcml.

<plone:behavior
    title="Special name(id) generator"
    description=""
    provides="dotted.name.to.your.INameGenerator"
    factory="dotted.name.to.your.name_generator.NameGenerator"
    for="dotted.name.to.content.interface"
    />

Corresponding python code.

from plone.app.content.interfaces import INameFromTitle
from zope.component import getUtility
from zope.interface import implements


class INameGenerator(INameFromTitle):
    """Behavior interface.
    """


class NameGenerator(object):
    """Customized name from title behavior."
    """

    implements(INameGenerator)


    def __init__(self, context):
        self.context = context

    @property
    def title(self):

        # YOUR IMPLEMENTATION
        title = ...

        return title

IMPORTANT: Inherit your interface from INameFromTitle

Now add <element value="dotted.name.to.your.INameGenerator" /> to your contents behaviors.

Probably removing the INameFromTitle behavior from your content type could be enough, but implement explicitly your own behavior would be better.