Plone won't start when I try to get values from my registry

Hi all,

Plone won't start when I try to get values from my registry.
I would like to declare "categories" in my registry and use them to customize my form when I add a new page tutorial.

Here is my registry.xml

<?xml version="1.0"?>
<registry
    xmlns:i18n="http://xml.zope.org/namespaces/i18n"
    i18n:domain="tsfi.wiki">

<!-- -*- extra stuff goes here -*- -->
   <record name="tsfi.wiki.categories">
    <field type="plone.registry.field.Tuple">
      <title xmlns:ns0="http://xml.zope.org/namespaces/i18n" ns0:domain="tsfi.wiki">Categories</title>
      <value_type type="plone.registry.field.TextLine" />
    </field>
    <value>
      <element i18n:translate="" i18n:domain="tsfi.wiki">Category 1</element>
      <element i18n:translate="" i18n:domain="tsfi.wiki">Category 2</element>
    </value>
  </record>
</registry>

I have tried two methods to access to my registry from the interfaces.py :

== First method ==
from : develop/addons/schema-driven-forms/customising-form-behaviour/vocabularies.html

tutorial.py

from tsfi.wiki import _

from plone.app.textfield import RichText
from plone.supermodel import model

from zope import schema

from plone.autoform import directives
from plone.app.z3cform.widget import AjaxSelectFieldWidget

from .vocabularies import RegistrySource

class ITutorial(model.Schema):
    """Schema Tutorial content type."""

    introduction = RichText(title=_(u'Introduction'),
                            required=False,)

    tutorial_categories = schema.Set(title=_(u"Tutorial categories"),value_type=schema.Choice(source=RegistrySource('wikitsf.site.categories')))

vocabularies.py

from zope.interface import implementer

@implementer
class RegistrySource(object):

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

    def __call__(self, context):
        registry = queryUtility(IRegistry)
        terms = []

        if registry is not None:
            for value in registry.get(self.key, ()):
                terms.append(SimpleVocabulary.createTerm(value, value.encode('utf-8'), value))

        return SimpleVocabulary(terms)

When I start Plone :

  File "/home/plone/wiki/zinstance/src/tsfi.wiki/src/tsfi/wiki/tutorial.py", line 19, in <module>
    class ITutorial(model.Schema):
  File "/home/plone/wiki/zinstance/src/tsfi.wiki/src/tsfi/wiki/tutorial.py", line 26, in ITutorial
    tutorial_categories = schema.Set(title=_(u"Tutorial categories"),value_type=schema.Choice(source=RegistrySource('wikitsf.site.categories')))                                                                  
  File "/home/plone/wiki/buildout-cache/eggs/zope.interface-4.6.0-py3.7-linux-x86_64.egg/zope/interface/declarations.py", line 390, in __call__                                                                   
    spec = Implements.named(spec_name, *self.interfaces)
  File "/home/plone/wiki/buildout-cache/eggs/zope.interface-4.6.0-py3.7-linux-x86_64.egg/zope/interface/declarations.py", line 142, in named                                                                      
    inst.__init__(*interfaces)
  File "/home/plone/wiki/buildout-cache/eggs/zope.interface-4.6.0-py3.7-linux-x86_64.egg/zope/interface/declarations.py", line 64, in __init__                                                                    
    Specification.__init__(self, _normalizeargs(interfaces))
  File "/home/plone/wiki/buildout-cache/eggs/zope.interface-4.6.0-py3.7-linux-x86_64.egg/zope/interface/declarations.py", line 911, in _normalizeargs                                                             
    _normalizeargs(v, output)
  File "/home/plone/wiki/buildout-cache/eggs/zope.interface-4.6.0-py3.7-linux-x86_64.egg/zope/interface/declarations.py", line 910, in _normalizeargs                                                             
    for v in sequence:
zope.configuration.xmlconfig.ZopeXMLConfigurationError: File "/home/plone/wiki/zinstance/src/tsfi.wiki/src/tsfi/wiki/browser/configure.zcml", line 21.2-26.8                                                      
    File "/home/plone/wiki/zinstance/parts/instance/etc/site.zcml", line 16.2-16.23
    File "/home/plone/wiki/buildout-cache/eggs/Products.CMFPlone-5.2.0-py3.7.egg/Products/CMFPlone/configure.zcml", line 110.2-114.8                                                                              
    File "/home/plone/wiki/zinstance/src/tsfi.wiki/src/tsfi/wiki/configure.zcml", line 16.2-16.32
    TypeError: 'type' object is not iterable

== second method ==
tutorial.py

from tsfi.wiki import _

from plone.app.textfield import RichText
from plone.supermodel import model

from zope import schema

from plone.autoform import directives
from plone.app.z3cform.widget import AjaxSelectFieldWidget

from plone import api

class ITutorial(model.Schema):
    """Schema Tutorial content type."""

    introduction = RichText(title=_(u'Introduction'),
                            required=False,)

    tutorial_categories = schema.Set(title=_(u"Tutorial categories"),value_type=schema.Choice(values=api.portal.get_registry_record('tsfi.wiki.categories')))

When I start Plone :

  File "/home/plone/wiki/zinstance/src/tsfi.wiki/src/tsfi/wiki/tutorial.py", line 25, in ITutorial
    tutorial_categories = schema.Set(title=_(u"Tutorial categories"),value_type=schema.Choice(values=api.portal.get_registry_record('tsfi.wiki.categories')))
  File "</home/plone/wiki/buildout-cache/eggs/decorator-4.4.0-py3.7.egg/decorator.py:decorator-gen-6>", line 2, in get_registry_record
  File "/home/plone/wiki/buildout-cache/eggs/plone.api-1.10.0-py3.7.egg/plone/api/validation.py", line 77, in wrapped
    return function(*args, **kwargs)
  File "/home/plone/wiki/buildout-cache/eggs/plone.api-1.10.0-py3.7.egg/plone/api/portal.py", line 297, in get_registry_record
    registry = getUtility(IRegistry)
  File "/home/plone/wiki/buildout-cache/eggs/zope.component-4.5-py3.7.egg/zope/component/_api.py", line 154, in getUtility
    raise ComponentLookupError(interface, name)
zope.configuration.xmlconfig.ZopeXMLConfigurationError: File "/home/plone/wiki/zinstance/src/tsfi.wiki/src/tsfi/wiki/browser/configure.zcml", line 21.2-26.8
    File "/home/plone/wiki/zinstance/parts/instance/etc/site.zcml", line 16.2-16.23
    File "/home/plone/wiki/buildout-cache/eggs/Products.CMFPlone-5.2.0-py3.7.egg/Products/CMFPlone/configure.zcml", line 110.2-114.8
    File "/home/plone/wiki/zinstance/src/tsfi.wiki/src/tsfi/wiki/configure.zcml", line 16.2-16.32
    zope.interface.interfaces.ComponentLookupError: (<InterfaceClass plone.registry.interfaces.IRegistry>, '')

== Additional information ==
I have noticed that if I remove <browser:page /> from my browser/configure.zcml, I can access to my registry and use them in my form when I create my page tutorial.

Here is my configure.zcml

<configure
    xmlns="http://namespaces.zope.org/zope"
    xmlns:genericsetup="http://namespaces.zope.org/genericsetup"
    xmlns:i18n="http://namespaces.zope.org/i18n"
    xmlns:plone="http://namespaces.plone.org/plone"
    i18n_domain="tsfi.wiki">
  
  <i18n:registerTranslations directory="locales" />
  
  <!--
    Be careful if you use general includeDependencies, it can have sideffects!
    Better import explicite packages or configurations ;)
  -->
  <!--<includeDependencies package="." />-->
  
  <include package=".browser" />
      
  <include file="permissions.zcml" />
      
  <genericsetup:registerProfile
      name="default"
      title="tsfi.wiki"
      directory="profiles/default"
      description="Installs the tsfi.wiki add-on."
      provides="Products.GenericSetup.interfaces.EXTENSION"
      post_handler=".setuphandlers.post_install"
      />

  <genericsetup:registerProfile
      name="uninstall"
      title="tsfi.wiki (uninstall)"
      directory="profiles/uninstall"
      description="Uninstalls the tsfi.wiki add-on."
      provides="Products.GenericSetup.interfaces.EXTENSION"
      post_handler=".setuphandlers.uninstall"
      />

  <utility
      factory=".setuphandlers.HiddenProfiles"
      name="tsfi.wiki-hiddenprofiles"
      />

  <!-- -*- extra stuff goes here -*- -->

</configure>

browser/configure.zcml

<configure
    xmlns="http://namespaces.zope.org/zope"
    xmlns:browser="http://namespaces.zope.org/browser"
    xmlns:plone="http://namespaces.plone.org/plone"
    i18n_domain="tsfi.wiki">

  <!-- Set overrides folder for Just-a-Bunch-Of-Templates product --> 
  <include package="z3c.jbot" file="meta.zcml" />
  <browser:jbot
      directory="overrides"
      layer="tsfi.wiki.interfaces.ITsfiWikiLayer"
      />  

  <!-- Publish static files --> 
  <plone:static
      name="tsfi.wiki"
      type="plone"
      directory="static"
      />  

  <browser:page
      name="view"
      for="tsfi.wiki.tutorial.ITutorial"
      template="templates/tutorial.pt"
      permission="zope2.View"
      />  

</configure>

I have deployed my Plone with the installer and I have created my addon with mrbob.
Plone 5.2
Python 3.7

Thanks a lot for you help!

Slannes

What is the sense of this @implementer decorator without interface?

See also this with a working code example:

Thanks a lot for your quick reply.

To be honnest, I don't know. I was following the plone documentation : develop/addons/schema-driven-forms/customising-form-behaviour/vocabularies.html

It is my first time with Plone and I am not a Python guru.

Thanks to your link, I have adapted my class RegistrySource and it is working.

Here is my vocabularies.py

from zope.interface import implementer
from zope.schema.interfaces import IContextSourceBinder

from zope.component import queryUtility
from plone.registry.interfaces import IRegistry
from zope.schema.vocabulary import SimpleVocabulary


@implementer(IContextSourceBinder)
class RegistrySource(object):

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

    def __call__(self, context):
        registry = queryUtility(IRegistry)
        terms = []

        if registry is not None:
            for value in registry.get(self.key, ()):
                terms.append(SimpleVocabulary.createTerm(value, value.encode('utf-8'), value))

        return SimpleVocabulary(terms)

Thanks a lot Zopyx :slight_smile:

2 Likes