Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

p.a.registry, DictRow and custom validator #14

Open
naro opened this issue May 14, 2013 · 6 comments
Open

p.a.registry, DictRow and custom validator #14

naro opened this issue May 14, 2013 · 6 comments
Labels

Comments

@naro
Copy link
Member

naro commented May 14, 2013

My schema looks like:

from plone.directives import form
from collective.z3cform.datagridfield import DataGridFieldFactory
from collective.z3cform.datagridfield.registry import DictRow

class IPanelRowSchema(form.Schema):
    path = TextLine(title=u"Path", required=False)
    title = TextLine(title=u"Title", required=False)

class IPanelSchema(form.Schema):
    form.widget(paths=DataGridFieldFactory)
    paths = List(value_type=DictRow(title=u"tablerow", schema=IPanelRowSchema))

@form.validator(field=IPanelSchema['paths'])
def validatePaths(value):
    pass

and I'm using the schema as schema for controlpanel.RegistryEditForm (Plone 4.2). The control panel uses p.a.registry as a storage. When I try to apply p.a.registry GS profile, it fails on:

  File "/zope/eggs/plone.app.registry-1.1-py2.6.egg/plone/app/registry/exportimport/handler.py", line 80, in importDocument
    self.importRecords(node)
  File "/zope/eggs/plone.app.registry-1.1-py2.6.egg/plone/app/registry/exportimport/handler.py", line 253, in importRecords
    self.context.registerInterface(interface, omit=tuple(omit), prefix=prefix)
  File "/zope/eggs/plone.registry-1.0.1-py2.6.egg/plone/registry/registry.py", line 112, in registerInterface
    self.records[record_name] = Record(persistent_field, value, _validate=False)
  File "/zope/eggs/plone.registry-1.0.1-py2.6.egg/plone/registry/registry.py", line 164, in __setitem__
    self._setField(name, record.field)
  File "/zope/eggs/plone.registry-1.0.1-py2.6.egg/plone/registry/registry.py", line 257, in _setField
    raise ValueError("The record's field must be an IPersistentField.")
ValueError: The record's field must be an IPersistentField.

as soon as I remove the validator, p.a.registry GS step is applied without any problems. I have tried to register the validator as described in http://developer.plone.org/forms/z3c.form.html#form-widget-validators but the problem is the same.

@miohtama
Copy link
Contributor

I think this is not a problem with c.z.DGF but a general issue with plone.app.registry. The same problems apply fields using PersistentList (like Choice). I suggest you could try to file a support issue against p.a.registry (or their might already exist one). Then also, link the issue here so it does not get lost!

@davisagli
Copy link
Member

It's a design choice in plone.registry to only support primitive field types included in zope.schema. The reason is that the fields are stored persistently and we don't want the registry to break if you remove some package.

@miohtama
Copy link
Contributor

@naro : Just to check here - does c.z.dgf store DictRow objects or PersistentDicts? We could make it store the latter as PersistentDict is probably something we could allow by design decision. PersistentDicts and PersistentLists are probably not going away from Zope core (right?) and used by many fields. @davisagli what do you think?

@davisagli
Copy link
Member

Not sure, ask @optilude

@naro
Copy link
Member Author

naro commented May 17, 2013

If I check the underlying record in p.a.registry, it's class is a <type 'dict'>. Anyway, it works, but problem is if I register a validator which is strange. I don't understand why registerd validator should break a field persistence.

@jensens jensens added the bug label Jul 30, 2015
@frapell
Copy link
Member

frapell commented Jan 15, 2019

@naro I just hit this exact same issue. I found that when the registry.xml is imported, the registry field is created in
https://github.com/plone/plone.app.registry/blob/fd6e7f94061dd1bf39660588ab3e4f77eb704c16/plone/app/registry/exportimport/handler.py#L180

The adapter code is defined in https://github.com/plone/plone.registry/blob/4d03736d8cf41ffed2323ea6b6d40d2c4b6f7364/plone/registry/fieldfactory.py#L20

And at the very end, it will copy the properties from the zope.schema field to the new plone.registry field https://github.com/plone/plone.registry/blob/4d03736d8cf41ffed2323ea6b6d40d2c4b6f7364/plone/registry/fieldfactory.py#L60

What happens when you register a custom validator, is that the context_dict will have the __provides__ attribute (It will not have it if the field doesn't have a validator registered), and so, the newly created field will have its __provides__ overridden, causing the IPersistentField.providedBy(field) to fail in https://github.com/plone/plone.registry/blob/4d03736d8cf41ffed2323ea6b6d40d2c4b6f7364/plone/registry/registry.py#L286 and provoking this issue.

The way I found to solve this issue in my case, was to add __provides__ as an ignored property in my code's __init__.py with:

from plone.registry.field import DisallowedProperty
DisallowedProperty('__provides__')

I am not 100% but this might be a solution that needs to be added to plone.registry, like https://github.com/plone/plone.registry/blob/4d03736d8cf41ffed2323ea6b6d40d2c4b6f7364/plone/registry/field.py#L280

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

5 participants