[Checkins] SVN: z3c.form/branches/fieldsandcontentproviders/src/z3c/form/ - Add content providers lookup by adaptation
Jean-Francois Roche
jfroche at jfroche.be
Fri Feb 12 12:47:27 EST 2010
Log message for revision 108957:
- Add content providers lookup by adaptation
- Rename form marker IWidgetsForm to IFieldsAndContentProviderForm
- Remove unneeded code in FieldWidgetsAndProviders.update
work in progress
Changed:
U z3c.form/branches/fieldsandcontentproviders/src/z3c/form/contentprovider.py
U z3c.form/branches/fieldsandcontentproviders/src/z3c/form/contentprovider.txt
U z3c.form/branches/fieldsandcontentproviders/src/z3c/form/field.py
U z3c.form/branches/fieldsandcontentproviders/src/z3c/form/interfaces.py
U z3c.form/branches/fieldsandcontentproviders/src/z3c/form/tests/test_doc.py
U z3c.form/branches/fieldsandcontentproviders/src/z3c/form/util.py
-=-
Modified: z3c.form/branches/fieldsandcontentproviders/src/z3c/form/contentprovider.py
===================================================================
--- z3c.form/branches/fieldsandcontentproviders/src/z3c/form/contentprovider.py 2010-02-12 16:35:25 UTC (rev 108956)
+++ z3c.form/branches/fieldsandcontentproviders/src/z3c/form/contentprovider.py 2010-02-12 17:47:27 UTC (rev 108957)
@@ -2,75 +2,68 @@
import zope.interface
import zope.location
import zope.schema.interfaces
+from zope.contentprovider.interfaces import IContentProvider
from z3c.form.field import FieldWidgets
-from z3c.form import interfaces, util
-from z3c.form.widget import AfterWidgetUpdateEvent
+from z3c.form import interfaces
+from z3c.form.interfaces import IContentProviders
+class BaseProvider(object):
+ __slots__ = ('position')
+
+lookup_ = BaseProvider()
+
+
class ContentProviders(dict):
+ zope.interface.implements(IContentProviders)
- def __getitem__(self, key):
- factory = super(ContentProviders, self).__getitem__(key)
- return ContentProviderFactory(name=key, factory=factory)
+ def __init__(self, names=None):
+ super(ContentProviders, self).__init__()
+ if names is not None:
+ for position, name in enumerate(names):
+ self[name] = lookup_
+ self[name].position = position
+ def __setitem__(self, key, value):
+ factory = ContentProviderFactory(factory=value, name=key)
+ super(ContentProviders, self).__setitem__(key, factory)
+
class ContentProviderFactory(object):
- def __init__(self, factory, *args, **kwargs):
+ def __init__(self, factory, name):
self.factory = factory
- self.args = args
- self.kwargs = kwargs
+ self.name = name
+ self.position = getattr(factory, 'position', None)
def __call__(self, manager):
- contentProvider = self.factory(manager.form, manager.request, manager.form)
+ if self.factory != lookup_:
+ contentProvider = self.factory(manager.content, manager.request, manager.form)
+ else:
+ contentProvider = zope.component.getMultiAdapter((manager.content, manager.request, manager.form),
+ IContentProvider, self.name)
return contentProvider
class FieldWidgetsAndProviders(FieldWidgets):
zope.component.adapts(
- interfaces.IWidgetsForm, interfaces.IFormLayer, zope.interface.Interface)
+ interfaces.IFieldsAndContentProviderForm, 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)
+ uniqueOrderedKeys.insert(factory.position, shortName)
+ self._data_values.insert(factory.position, 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
Modified: z3c.form/branches/fieldsandcontentproviders/src/z3c/form/contentprovider.txt
===================================================================
--- z3c.form/branches/fieldsandcontentproviders/src/z3c/form/contentprovider.txt 2010-02-12 16:35:25 UTC (rev 108956)
+++ z3c.form/branches/fieldsandcontentproviders/src/z3c/form/contentprovider.txt 2010-02-12 17:47:27 UTC (rev 108957)
@@ -20,45 +20,54 @@
>>> zope.component.provideAdapter(converter.FieldDataConverter)
>>> zope.component.provideAdapter(converter.FieldWidgetDataConverter)
+Now that everything we need is defined. We can define a simple schema with fields::
+
>>> 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::
+We want to mix fields and a content provider. We define a very simple
+content provider that will print extra help text after a widget::
>>> from z3c.form import field, form
- >>> from z3c.form.interfaces import IWidgetsForm
+ >>> from z3c.form.interfaces import IFieldsAndContentProviderForm
>>> from z3c.form import widget
>>> from zope.contentprovider.provider import ContentProviderBase
+ >>> from zope.interface import implements
>>> class ExtendedHelp(ContentProviderBase):
...
... def update(self):
- ... pass
+ ... self.person = self.context.id
...
... def render(self):
- ... """see `z3c.form.interfaces.IWidget`
- ... """
- ... return '<div class="extendedhelp">Some very long help text ...</div>'
+ ... return '<div class="extendedhelp">Some very long help text about person %s</div>' % self.person
>>> from z3c.form.contentprovider import ContentProviders
+ >>> from z3c.form.testing import setupFormDefaults
+ >>> setupFormDefaults()
+
>>> class PersonForm(form.Form):
- ... zope.interface.implements(IWidgetsForm)
+ ... implements(IFieldsAndContentProviderForm)
... prefix = 'form.'
... fields = field.Fields(IPerson)
+ ... ignoreContext = True
... contentProviders = ContentProviders()
... contentProviders['longHelp'] = ExtendedHelp
+ ... contentProviders['longHelp'].position = 2
>>> from z3c.form.testing import TestRequest
>>> request = TestRequest()
- >>> context = object()
+ >>> class Person(object):
+ ... id = 'james'
+ >>> context = Person()
>>> personForm = PersonForm(context, request)
>>> from z3c.form.contentprovider import FieldWidgetsAndProviders
@@ -68,4 +77,32 @@
>>> manager._data
{'longHelp': <ExtendedHelp object at ...>, 'id': <Widget 'form.widgets.id'>}
>>> manager.get('longHelp').render()
- '<div class="extendedhelp">Some very long help text ...</div>'
+ '<div class="extendedhelp">Some very long help text about person james</div>'
+
+We can also define content provider by adaptation::
+
+ >>> from zope.component import provideAdapter
+ >>> from zope.contentprovider.interfaces import IContentProvider
+ >>> from z3c.form.interfaces import IFormLayer
+ >>> provideAdapter(ExtendedHelp,
+ ... (zope.interface.Interface,
+ ... IFormLayer,
+ ... zope.interface.Interface),
+ ... provides=IContentProvider, name='longHelp')
+
+ >>> class PersonForm(form.Form):
+ ... implements(IFieldsAndContentProviderForm)
+ ... prefix = 'form.'
+ ... fields = field.Fields(IPerson)
+ ... ignoreContext = True
+ ... contentProviders = ContentProviders(['longHelp'])
+ ... contentProviders['longHelp'].position = 2
+
+ >>> 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 about person james</div>'
Modified: z3c.form/branches/fieldsandcontentproviders/src/z3c/form/field.py
===================================================================
--- z3c.form/branches/fieldsandcontentproviders/src/z3c/form/field.py 2010-02-12 16:35:25 UTC (rev 108956)
+++ z3c.form/branches/fieldsandcontentproviders/src/z3c/form/field.py 2010-02-12 17:47:27 UTC (rev 108957)
@@ -280,7 +280,7 @@
self.hasRequiredFields = True
uniqueOrderedKeys.append(shortName)
if newWidget:
- self._data_values.append(widget)
+ # self._data_values.append(widget)
self._data[shortName] = widget
zope.location.locate(widget, self, shortName)
# allways ensure that we add all keys and keep the order given from
Modified: z3c.form/branches/fieldsandcontentproviders/src/z3c/form/interfaces.py
===================================================================
--- z3c.form/branches/fieldsandcontentproviders/src/z3c/form/interfaces.py 2010-02-12 16:35:25 UTC (rev 108956)
+++ z3c.form/branches/fieldsandcontentproviders/src/z3c/form/interfaces.py 2010-02-12 17:47:27 UTC (rev 108957)
@@ -228,6 +228,11 @@
specification.
"""
+class IContentProviders(IManager):
+ """
+ A content provider manager
+ """
+
# ----[ Data Managers ]------------------------------------------------------
class IDataManager(zope.interface.Interface):
@@ -1007,14 +1012,14 @@
'the form.'),
schema=IFields)
-class IWidgetsForm(IForm):
- """A form that is based upon defined fields."""
+class IFieldsAndContentProviderForm(IForm):
+ """A form that is based upon defined fields and content providers"""
- widgetsItems = zope.schema.Object(
- title=_('Widgets'),
- description=_('A field manager describing the fields to be used for '
+ contentProviders = zope.schema.Object(
+ title=_('Content providers'),
+ description=_('A manager describing the content providers to be used for '
'the form.'),
- schema=IFields)
+ schema=IContentProviders)
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 16:35:25 UTC (rev 108956)
+++ z3c.form/branches/fieldsandcontentproviders/src/z3c/form/tests/test_doc.py 2010-02-12 17:47:27 UTC (rev 108957)
@@ -58,7 +58,7 @@
doctest.DocFileSuite(
'../contentprovider.txt',
setUp=setUp, tearDown=testing.tearDown,
- optionflags=doctest.NORMALIZE_WHITESPACE|doctest.ELLIPSIS,
+ optionflags=doctest.NORMALIZE_WHITESPACE|doctest.ELLIPSIS|doctest.REPORT_ONLY_FIRST_FAILURE,
checker=checker,
),
doctest.DocFileSuite(
Modified: z3c.form/branches/fieldsandcontentproviders/src/z3c/form/util.py
===================================================================
--- z3c.form/branches/fieldsandcontentproviders/src/z3c/form/util.py 2010-02-12 16:35:25 UTC (rev 108956)
+++ z3c.form/branches/fieldsandcontentproviders/src/z3c/form/util.py 2010-02-12 17:47:27 UTC (rev 108957)
@@ -138,7 +138,14 @@
raise ValueError(value)
self.data.append(value)
+ def insert(self, position, value):
+ if value in self.data:
+ raise ValueError(value)
+ self.data.insert(position, value)
+ #XXX TODO: Inherit from list
+
+
class Manager(object):
"""Non-persistent IManager implementation."""
zope.interface.implements(interfaces.IManager)
@@ -192,6 +199,10 @@
def __contains__(self, name):
return bool(self.get(name))
+ #XXX TODO:
+ # Add __setitem__ that will add key, value at the end of both lists as in PEP0372
+ # Add insertBefore(key)
+ # insertAfter(key)
class SelectionManager(Manager):
"""Non-persisents ISelectionManager implementation."""
More information about the checkins
mailing list