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.
Tested with
Plone=5.1.6withplone.app.registry=1.7.5andplone.registry=1.1.5Problem
In the release 1.1.0 and 1.1.1 ftw.datepicker added registry entries as
follows:
Like this, the created record in the registry has a field knows about
the interface (due to the
interface="..."). If a field knows about theinterfacethe record will provide IInterfaceAwareRecord oninitialization.
In version 1.2.0 the record declaration was changed to:
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.registrywill get the existing record from theregistry. At that moment it sees that its field knows about the
interface and thus provides the
IInterfaceAwareRecordinterface. Duringthe registration of the entry, it finds that we declare the
fieldmanually 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 setsNoneinstead 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
redispatchInterfaceAwareRecordEventssubscriber fromplone.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:
plone.app.registry/plone/app/registry/exportimport/handler.py
Lines 255 to 258 in 04e431b
like so:
Or we set the old
interfaceNameto the new field like so:In the second solution, the fieldName could also be reused from the old field if possible.