Skip to content

Updating interface aware records with field node but without interface results in error #40

Description

@Nachtalb

Tested with Plone=5.1.6 with plone.app.registry=1.7.5 and plone.registry=1.1.5


Problem

In the release 1.1.0 and 1.1.1 ftw.datepicker added registry entries as
follows:

<record interface="ftw.datepicker.interfaces.IDatetimeRegistry" field="formats">
    <value purge="false">
        <element key="de">d.m.Y H:i</element>
        <element key="fr">d/m/Y H:i</element>
    </value>
</record>

Like this, the created record in the registry has a field knows about
the interface (due to the interface="..."). If a field knows about the
interface the record will provide IInterfaceAwareRecord on
initialization
.

In version 1.2.0 the record declaration was changed to:

<record name="ftw.datepicker.interfaces.IDatetimeRegistry.formats">
    <field type="plone.registry.field.Dict">
        <title>The formats per language</title>
        <key_type type="plone.registry.field.TextLine" />
        <value_type type="plone.registry.field.TextLine" />
    </field>
    <value purge="false">
        <element key="de">d.m.Y H:i</element>
        <element key="fr">d/m/Y H:i</element>
    </value>
</record>

In here we do not define the interface anymore but do define the field
itself.

Now when you have initially installed version 1.1.0 or 1.1.1 the field
knows the interface. When you reinstall the profile with version 1.2.0
and above plone.app.registry will get the existing record from the
registry. At that moment it sees that its field knows about the
interface and thus provides the IInterfaceAwareRecord interface. During
the registration of the entry, it finds that we declare the field
manually in the XML. Because of that, it creates a new field in case
something has changed. During this creation process of the field, it lets
the field know about the interface
. BUT because we didn't define an
interface this time in the record (interface="...") it sets None
instead of our actual interface.

Now during the rest of the installation process, the record provides
IInterfaceAwareRecord even though the field does not know about the
interface anymore.

Later on, in the record registration process, this will trigger the
redispatchInterfaceAwareRecordEvents subscriber from plone.registry.
At that moment it thinks, the record knows about the interface because it
still provides IInterfaceAwareRecord. This causes a failure when trying
to resolve that interface.


Expected behaviour

According to the plone.app.registrys docs<record name="ftw.datepicker.interfaces.IDatetimeRegistry.formats"> and <record interface="ftw.datepicker.interfaces.IDatetimeRegistry" field="formats"> are equivalent so it should fail when using one method once and the other another time.


Proposed Solution

Remove the interface by extending this if:

if field is not None and not IFieldRef.providedBy(field):
# Set interface name and fieldName, if applicable
field.interfaceName = interfaceName
field.fieldName = fieldName

like so:

if field is not None and not IFieldRef.providedBy(field):
    # Set interface name and fieldName, if applicable
    field.interfaceName = interfaceName
    field.fieldName = fieldName

    if interfaceName is None and existing_record:
        # Remove interface awareness in case the previous field was interface aware
        noLongerProvides(existing_record, IInterfaceAwareRecord)

Or we set the old interfaceName to the new field like so:

if field is not None and not IFieldRef.providedBy(field):
    # Set interface name and fieldName, if applicable
    field.interfaceName = existing_record.field.interfaceName if existing_record else interfaceName
    field.fieldName = fieldName

In the second solution, the fieldName could also be reused from the old field if possible.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions