[Checkins] SVN: z3c.form/branches/fieldsandcontentproviders/src/z3c/form/ initial concept of contentprovider in a form

Jean-Francois Roche jfroche at jfroche.be
Fri Feb 12 07:26:27 EST 2010


Log message for revision 108950:
  initial concept of contentprovider in a form

Changed:
  A   z3c.form/branches/fieldsandcontentproviders/src/z3c/form/contentprovider.py
  A   z3c.form/branches/fieldsandcontentproviders/src/z3c/form/contentprovider.txt
  U   z3c.form/branches/fieldsandcontentproviders/src/z3c/form/interfaces.py
  U   z3c.form/branches/fieldsandcontentproviders/src/z3c/form/tests/test_doc.py

-=-
Added: z3c.form/branches/fieldsandcontentproviders/src/z3c/form/contentprovider.py
===================================================================
--- z3c.form/branches/fieldsandcontentproviders/src/z3c/form/contentprovider.py	                        (rev 0)
+++ z3c.form/branches/fieldsandcontentproviders/src/z3c/form/contentprovider.py	2010-02-12 12:26:27 UTC (rev 108950)
@@ -0,0 +1,76 @@
+import zope.component
+import zope.interface
+import zope.location
+import zope.schema.interfaces
+
+from z3c.form.field import FieldWidgets
+from z3c.form import interfaces, util
+from z3c.form.widget import AfterWidgetUpdateEvent
+
+
+class ContentProviders(dict):
+
+    def __getitem__(self, key):
+        factory = super(ContentProviders, self).__getitem__(key)
+        return ContentProviderFactory(name=key, factory=factory)
+
+
+class ContentProviderFactory(object):
+
+    def __init__(self, factory, *args, **kwargs):
+        self.factory = factory
+        self.args = args
+        self.kwargs = kwargs
+
+    def __call__(self, manager):
+        contentProvider = self.factory(manager.form, manager.request, manager.form)
+        return contentProvider
+
+
+class FieldWidgetsAndProviders(FieldWidgets):
+    zope.component.adapts(
+        interfaces.IWidgetsForm, interfaces.IFormLayer, zope.interface.Interface)
+    zope.interface.implementsOnly(interfaces.IWidgets)
+
+    def update(self):
+        super(FieldWidgetsAndProviders, self).update()
+        prefix = util.expandPrefix(self.form.prefix)
+        prefix += util.expandPrefix(self.prefix)
+
+        uniqueOrderedKeys = self._data_keys
+        for name in self.form.contentProviders:
+            factory = self.form.contentProviders[name]
+            contentProvider = factory(self)
+            newWidget = True
+            ignoreContext = True
+            # Step 1: Determine the mode of the contentProvider.
+            mode = self.mode
+            # Step 2: Get the widget for the given field.
+            shortName = name
+            #widget.name = prefix + shortName
+            contentProvider.id = (prefix + shortName).replace('.', '-')
+            # Step 4: Set the context
+            contentProvider.context = self.content
+            # Step 5: Set the form
+            contentProvider.form = self.form
+            # Optimization: Set both interfaces here, rather in step 4 and 5:
+            # ``alsoProvides`` is quite slow
+            zope.interface.alsoProvides(
+                contentProvider, interfaces.IContextAware, interfaces.IFormAware)
+            # Step 6: Set some variables
+            contentProvider.ignoreContext = ignoreContext
+            contentProvider.ignoreRequest = self.ignoreRequest
+            # Step 7: Set the mode of the widget
+            contentProvider.mode = mode
+            # Step 8: Update the widget
+            contentProvider.update()
+            zope.event.notify(AfterWidgetUpdateEvent(contentProvider))
+            # Step 9: Add the widget to the manager
+            uniqueOrderedKeys.append(shortName)
+            if newWidget:
+                self._data_values.append(contentProvider)
+                self._data[shortName] = contentProvider
+                zope.location.locate(contentProvider, self, shortName)
+            # allways ensure that we add all keys and keep the order given from
+            # button items
+            self._data_keys = uniqueOrderedKeys

Added: z3c.form/branches/fieldsandcontentproviders/src/z3c/form/contentprovider.txt
===================================================================
--- z3c.form/branches/fieldsandcontentproviders/src/z3c/form/contentprovider.txt	                        (rev 0)
+++ z3c.form/branches/fieldsandcontentproviders/src/z3c/form/contentprovider.txt	2010-02-12 12:26:27 UTC (rev 108950)
@@ -0,0 +1,71 @@
+ContentProviders
+----------------
+
+Before we can use a widget manager, we have to register the ``IFieldWidget`` adapter
+for the ``ITextLine`` field:
+
+  >>> import zope.component
+  >>> import zope.interface
+  >>> from z3c.form import interfaces, widget
+  >>> from z3c.form.testing import TestRequest
+
+  >>> @zope.component.adapter(zope.schema.TextLine, TestRequest)
+  ... @zope.interface.implementer(interfaces.IFieldWidget)
+  ... def TextFieldWidget(field, request):
+  ...     return widget.FieldWidget(field, widget.Widget(request))
+
+  >>> zope.component.provideAdapter(TextFieldWidget)
+
+  >>> from z3c.form import converter
+  >>> zope.component.provideAdapter(converter.FieldDataConverter)
+  >>> zope.component.provideAdapter(converter.FieldWidgetDataConverter)
+
+  >>> import zope.interface
+  >>> import zope.schema
+
+  >>> class IPerson(zope.interface.Interface):
+  ...     id = zope.schema.TextLine(
+  ...         title=u'ID',
+  ...         description=u"The person's ID.",
+  ...         readonly=True,
+  ...         required=True)
+  ...
+
+We want to mix fields and content providers::
+
+  >>> from z3c.form import field, form
+  >>> from z3c.form.interfaces import IWidgetsForm
+  >>> from z3c.form import widget
+  >>> from zope.contentprovider.provider import ContentProviderBase
+
+  >>> class ExtendedHelp(ContentProviderBase):
+  ...
+  ...   def update(self):
+  ...       pass
+  ...
+  ...   def render(self):
+  ...       """see `z3c.form.interfaces.IWidget`
+  ...       """
+  ...       return '<div class="extendedhelp">Some very long help text ...</div>'
+
+  >>> from z3c.form.contentprovider import ContentProviders
+  >>> class PersonForm(form.Form):
+  ...     zope.interface.implements(IWidgetsForm)
+  ...     prefix = 'form.'
+  ...     fields = field.Fields(IPerson)
+  ...     contentProviders = ContentProviders()
+  ...     contentProviders['longHelp'] = ExtendedHelp
+
+  >>> from z3c.form.testing import TestRequest
+  >>> request = TestRequest()
+  >>> context = object()
+  >>> personForm = PersonForm(context, request)
+
+  >>> from z3c.form.contentprovider import FieldWidgetsAndProviders
+  >>> manager = FieldWidgetsAndProviders(personForm, request, context)
+  >>> manager.ignoreContext = True
+  >>> manager.update()
+  >>> manager._data
+  {'longHelp': <ExtendedHelp object at ...>, 'id': <Widget 'form.widgets.id'>}
+  >>> manager.get('longHelp').render()
+  '<div class="extendedhelp">Some very long help text ...</div>'

Modified: z3c.form/branches/fieldsandcontentproviders/src/z3c/form/interfaces.py
===================================================================
--- z3c.form/branches/fieldsandcontentproviders/src/z3c/form/interfaces.py	2010-02-12 12:10:09 UTC (rev 108949)
+++ z3c.form/branches/fieldsandcontentproviders/src/z3c/form/interfaces.py	2010-02-12 12:26:27 UTC (rev 108950)
@@ -1007,7 +1007,15 @@
                       'the form.'),
         schema=IFields)
 
+class IWidgetsForm(IForm):
+    """A form that is based upon defined fields."""
 
+    widgetsItems = zope.schema.Object(
+        title=_('Widgets'),
+        description=_('A field manager describing the fields to be used for '
+                      'the form.'),
+        schema=IFields)
+
 class IButtonForm(IForm):
     """A form that is based upon defined buttons."""
 

Modified: z3c.form/branches/fieldsandcontentproviders/src/z3c/form/tests/test_doc.py
===================================================================
--- z3c.form/branches/fieldsandcontentproviders/src/z3c/form/tests/test_doc.py	2010-02-12 12:10:09 UTC (rev 108949)
+++ z3c.form/branches/fieldsandcontentproviders/src/z3c/form/tests/test_doc.py	2010-02-12 12:26:27 UTC (rev 108950)
@@ -56,6 +56,12 @@
             checker=checker,
             ),
         doctest.DocFileSuite(
+            '../contentprovider.txt',
+            setUp=setUp, tearDown=testing.tearDown,
+            optionflags=doctest.NORMALIZE_WHITESPACE|doctest.ELLIPSIS,
+            checker=checker,
+            ),
+        doctest.DocFileSuite(
             '../value.txt',
             setUp=placelesssetup.setUp, tearDown=placelesssetup.tearDown,
             optionflags=doctest.NORMALIZE_WHITESPACE|doctest.ELLIPSIS,



More information about the checkins mailing list