[Zope3-dev] RFC: CustomWidgetFactory and widgets having different __init__ signature

Dominik Huber dominik.huber at perse.ch
Tue Nov 15 09:56:37 EST 2005


Adam Groszer wrote:

>As I'm digging through zope.app.form.browser to fix the
>CustomWidgetFactory collector issue, I found the following:
>
>IWidget has no __init__ defined
>
>class Widget(object):
>    def __init__(self, context, request):
>
>class ItemsWidgetBase(TranslationHook, SimpleInputWidget):
>    def __init__(self, field, vocabulary, request):
>
>class ItemsEditWidgetBase(SingleDataHelper, ItemsWidgetBase):
>    def __init__(self, field, vocabulary, request):
>
>class ObjectWidget(BrowserWidget, InputWidget):
>    def __init__(self, context, request, factory, **kw):
>    
>class SequenceWidget(BrowserWidget, InputWidget):
>    def __init__(self, context, field, request, subwidget=None):
>
>class SequenceDisplayWidget(DisplayWidget):
>    def __init__(self, context, field, request, subwidget=None):
>
>class SourceDisplayWidget(zope.app.form.Widget):
>    def __init__(self, field, source, request):
>
>class SourceInputWidget(zope.app.form.InputWidget):
>    def __init__(self, field, source, request):
>
>class SourceSelectWidget(zope.app.form.browser.SelectWidget):
>    def __init__(self, field, source, request):
>
>CustomWidgetFactory fails on these different signatures. This affects
>the ZCML <browser:widget field="..." class="..."/>. Simple widgets
>will work, widgets with different signatures of course not.
>
>class CustomWidgetFactory(object):
>    implements(IViewFactory)
>    def __call__(self, context, request):
>class CustomSequenceWidgetFactory(object):
>    implements(IViewFactory)
>    def __call__(self, context, field, request):
>
>In fact, CustomSequenceWidgetFactory violates the IViewFactory
>interface with the different __call__ signature. That causes
>setUpWidget to fail. I'm wondering if this worked for anyone anytime.
>  
>
No, the widget stuff was broken long time ago. Phillip did some fixes 
within a branch, but this branch got deleted during the last repository 
cleaned up.

I'm not shure which change the widget-refactoring will bring, that was 
the reason why I never was digging deeper. 
(svn://svn.zope.org/repos/main/Zope3/branches/f12gsprint-widget).

>Now I'm stuck a little bit. How does a good solution look like?
>
>My half-baked solution was up to today for Itemswidgets (which caused
>the error for me) to mark it with a different interface and look for
>that in CustomWidgetFactory and pass different arguments.
>Now I'm not so sure that this is the right one.
>  
>
The current solution does not covers ObjectWidgets. My solutions are 
half-baked too, but maybe we can collect them to get an overview (see 
attached file).

The problem can be split in two parts:
1. __call__ with different signatures
2. creation/customization of widgets using the setattr(instance, name, 
value)

Regards,
Dominik
-------------- next part --------------
from zope.component.interfaces import IViewFactory
from zope.interface import implements
from zope.schema.interfaces import IChoice, ICollection



class CustomWidgetFactory(object):
    """Custom Widget Factory."""
    implements(IViewFactory)

    def __init__(self, widget_factory, *args, **kw):
        self._widget_factory = widget_factory
        self.args = args
        self.kw = kw

    def _create(self, args):
        instance = self._widget_factory(*args)
        for name, value in self.kw.items():
            setattr(instance, name, value)
        return instance

    def __call__(self, context, request):
        return self._create((context, request) + self.args)



class CustomSequenceWidgetFactory(CustomWidgetFactory):
    """Custom sequence widget factory."""

    def __call__(self, context, request):
        if not ICollection.providedBy(context):
            raise TypeError, "Provided field does not provide ICollection."
        args = (context, context.value_type, request) + self.args
        return self._create(args)



class CustomVocabularyWidgetFactory(CustomWidgetFactory):
    """Custom vocabulary widget factory."""

    def __call__(self, context, request):
        if not IChoice.providedBy(context):
            raise TypeError, "Provided field does not provide ICollection."
        args = (context, context.vocabulary, request) + self.args
        return self._create(args)



class TemplateWidgetFactory(CustomWidgetFactory):
    """The view kw attribute is called like a ViewPageTemplateFile."""

    def _create(self, args):
        instance = self._widget_factory(*args)
        for name, value in self.kw.items():
            if name is 'view':
                setattr(instance, name, value(instance, instance.request))
            else:
                setattr(instance, name, value)
        return instance



class TemplateSequenceWidgetFactory(CustomSequenceWidgetFactory):
    """The view kw attribute is called like a ViewPageTemplateFile."""

    def _create(self, args):
        instance = self._widget_factory(*args)
        for name, value in self.kw.items():
            if name is 'view':
                setattr(instance, name, value(instance, instance.request))
            else:
                setattr(instance, name, value)
        return instance
-------------- next part --------------
A non-text attachment was scrubbed...
Name: dominik.huber.vcf
Type: text/x-vcard
Size: 154 bytes
Desc: not available
Url : http://mail.zope.org/pipermail/zope3-dev/attachments/20051115/b60a2531/dominik.huber.vcf


More information about the Zope3-dev mailing list