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
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
begin:vcard
fn:Dominik Huber
n:Huber;Dominik
email;internet:[EMAIL PROTECTED]
tel;work:++41 56 534 77 30
x-mozilla-html:FALSE
version:2.1
end:vcard

_______________________________________________
Zope3-dev mailing list
Zope3-dev@zope.org
Unsub: http://mail.zope.org/mailman/options/zope3-dev/archive%40mail-archive.com

Reply via email to