[Checkins] SVN: z3c.form/branches/adamg-objectwidget/src/z3c/form/ finish off the day,
Adam Groszer
agroszer at gmail.com
Tue Oct 7 14:32:13 EDT 2008
Log message for revision 91878:
finish off the day,
factory is solved
multi-error is in sight
code cleanup needed
Changed:
U z3c.form/branches/adamg-objectwidget/src/z3c/form/browser/object.py
U z3c.form/branches/adamg-objectwidget/src/z3c/form/browser/object.txt
U z3c.form/branches/adamg-objectwidget/src/z3c/form/configure.zcml
U z3c.form/branches/adamg-objectwidget/src/z3c/form/converter.py
U z3c.form/branches/adamg-objectwidget/src/z3c/form/dummy.py
U z3c.form/branches/adamg-objectwidget/src/z3c/form/error.py
U z3c.form/branches/adamg-objectwidget/src/z3c/form/interfaces.py
A z3c.form/branches/adamg-objectwidget/src/z3c/form/object.py
-=-
Modified: z3c.form/branches/adamg-objectwidget/src/z3c/form/browser/object.py
===================================================================
--- z3c.form/branches/adamg-objectwidget/src/z3c/form/browser/object.py 2008-10-07 17:37:12 UTC (rev 91877)
+++ z3c.form/branches/adamg-objectwidget/src/z3c/form/browser/object.py 2008-10-07 18:32:12 UTC (rev 91878)
@@ -3,66 +3,12 @@
import zope.interface
import zope.schema.interfaces
-from z3c.form import action, button, form, interfaces
-from z3c.form.i18n import MessageFactory as _
-from z3c.form import interfaces
+from z3c.form import form, interfaces
from z3c.form.widget import Widget, FieldWidget
-from z3c.form.field import FieldWidgets, Fields
from z3c.form.browser import widget
-from z3c.form.subform import EditSubForm
-class ObjectSubForm(form.BaseForm):
- zope.interface.implements(interfaces.ISubForm)
+from z3c.form.object import ObjectSubForm
- formErrorsMessage = _('There were some errors.')
- successMessage = _('Data successfully updated.')
- noChangesMessage = _('No changes were applied.')
-
- def __init__(self, context, parentWidget):
- self.context = context
- self.request = parentWidget.request
- self.parentWidget = parentWidget
- self.parentForm = self.__parent__ = parentWidget.form
-
- def _validate(self):
- for widget in self.widgets.values():
- try:
- # convert widget value to field value
- converter = interfaces.IDataConverter(widget)
- value = converter.toFieldValue(widget.value)
- # validate field value
- zope.component.getMultiAdapter(
- (self.context,
- self.request,
- self.parentWidget.form,
- getattr(widget, 'field', None),
- widget),
- interfaces.IValidator).validate(value)
- except (zope.schema.ValidationError, ValueError), error:
- # on exception, setup the widget error message
- view = zope.component.getMultiAdapter(
- (error, self.request, widget, widget.field,
- self.parentWidget.form, self.context),
- interfaces.IErrorViewSnippet)
- view.update()
- widget.error = view
-
- def update(self):
- self.fields = Fields(self.parentWidget.field.schema)
-
- self.mode = self.parentWidget.mode
- self.ignoreContext = self.parentWidget.ignoreContext
- self.ignoreRequest = self.parentWidget.ignoreRequest
- self.prefix = self.parentWidget.field.__name__
-
- if interfaces.IFormAware.providedBy(self.parentWidget):
- self.ignoreReadonly = self.parentWidget.form.ignoreReadonly
-
- super(ObjectSubForm, self).update()
-
- self._validate()
-
-
class ObjectWidget(widget.HTMLFormElement, Widget):
zope.interface.implementsOnly(interfaces.IObjectWidget)
Modified: z3c.form/branches/adamg-objectwidget/src/z3c/form/browser/object.txt
===================================================================
--- z3c.form/branches/adamg-objectwidget/src/z3c/form/browser/object.txt 2008-10-07 17:37:12 UTC (rev 91877)
+++ z3c.form/branches/adamg-objectwidget/src/z3c/form/browser/object.txt 2008-10-07 18:32:12 UTC (rev 91878)
@@ -18,6 +18,15 @@
+ >>> from z3c.form.dummy import MySubObjectFactory
+ >>> from z3c.form.dummy import MySecondFactory
+
+ >>> import zope.component
+
+ >>> zope.component.provideAdapter(MySubObjectFactory, name='IMySubObject')
+ >>> zope.component.provideAdapter(MySecondFactory, name='IMySecond')
+
+
As for all widgets, the objectwidget must provide the new ``IWidget``
interface:
@@ -184,8 +193,8 @@
We have to provide an adapter first:
>>> zope.component.provideAdapter(object.ObjectFieldWidget)
- >>> from z3c.form import converter
- >>> zope.component.provideAdapter(converter.ObjectConverter)
+ >>> import z3c.form.object
+ >>> zope.component.provideAdapter(z3c.form.object.ObjectConverter)
We define an interface containing a subobject, and an addform for it:
@@ -222,7 +231,7 @@
and which is already updated:
>>> myaddform.widgets['subobject'].subform
- <z3c.form.browser.object.ObjectSubForm object at ...>
+ <z3c.form.object.ObjectSubForm object at ...>
>>> myaddform.widgets['subobject'].subform.widgets.keys()
['foofield', 'barfield']
@@ -428,3 +437,61 @@
>>> root['first'].subobject.barfield
55
+
+
+
+ >>> request = TestRequest(form={'subobject.widgets.foofield':u'999999',
+ ... 'subobject.widgets.barfield':u'bad',
+ ... 'form.widgets.name':u'first',
+ ... 'form.widgets.subobject-empty-marker':u'1',
+ ... 'form.buttons.apply':'Apply'})
+
+ >>> editform.request = request
+
+#>>> from pub.dbgpclient import brk; brk('192.168.32.1')
+
+ >>> editform.update()
+ >>> print editform.render()
+ <html xmlns="http://www.w3.org/1999/xhtml">
+ <body>
+ <i>There were some errors.</i>
+ <ul>
+ <li>
+ my object:
+ <div class="error">The entered value is not a valid integer literal.</div>
+ </li>
+ </ul>
+ <form action=".">
+ <div class="row">
+ <b>
+ <div class="error">The entered value is not a valid integer literal.</div>
+ </b>
+ <label for="form-widgets-subobject">my object</label>
+ <fieldset class="object-widget required" id="form-widgets-subobject" name="form.widgets.subobject">
+ <legend>my object</legend>
+ <input class="text-widget required int-field" id="subobject-widgets-foofield" name="subobject.widgets.foofield" type="text" value="badder">
+ <br>
+ <div class="error">
+ <div class="error">The entered value is not a valid integer literal.</div>
+ </div>
+ <input class="text-widget required int-field" id="subobject-widgets-barfield" name="subobject.widgets.barfield" type="text" value="bad">
+ <br>
+ <input name="form.widgets.subobject-empty-marker" type="hidden" value="1">
+ </fieldset>
+ </div>
+ <div class="row">
+ <label for="form-widgets-name">name</label>
+ <input class="text-widget required textline-field" id="form-widgets-name" name="form.widgets.name" type="text" value="first">
+ </div>
+ <div class="action">
+ <input class="submit-widget button-field" id="form-buttons-apply" name="form.buttons.apply" type="submit" value="Apply">
+ </div>
+ </form>
+ </body>
+ </html>
+
+ >>> root['first'].subobject.foofield
+ 43
+
+ >>> root['first'].subobject.barfield
+ 55
Modified: z3c.form/branches/adamg-objectwidget/src/z3c/form/configure.zcml
===================================================================
--- z3c.form/branches/adamg-objectwidget/src/z3c/form/configure.zcml 2008-10-07 17:37:12 UTC (rev 91877)
+++ z3c.form/branches/adamg-objectwidget/src/z3c/form/configure.zcml 2008-10-07 18:32:12 UTC (rev 91878)
@@ -75,7 +75,7 @@
factory=".converter.MultiConverter"
/>
<adapter
- factory=".converter.ObjectConverter"
+ factory=".object.ObjectConverter"
/>
<!-- ITerms -->
Modified: z3c.form/branches/adamg-objectwidget/src/z3c/form/converter.py
===================================================================
--- z3c.form/branches/adamg-objectwidget/src/z3c/form/converter.py 2008-10-07 17:37:12 UTC (rev 91877)
+++ z3c.form/branches/adamg-objectwidget/src/z3c/form/converter.py 2008-10-07 18:32:12 UTC (rev 91878)
@@ -362,67 +362,7 @@
# convert the field values to a tuple or list
return collectionType(values)
-from z3c.form.dummy import MySubObject
-class ObjectConverter(BaseDataConverter):
- """Data converter for IObjectWidget."""
-
- zope.component.adapts(
- zope.schema.interfaces.IObject, interfaces.IObjectWidget)
-
- factory = MySubObject
- #factory = None
-
- def _fields(self):
- x = zope.schema.getFields(self.field.schema)
- return x
-
- def toWidgetValue(self, value):
- """Just dispatch it."""
- if value is self.field.missing_value:
- return None
-
- return value
-
- rv = {}
- for name, field in self._fields().items():
- #widget = zope.component.getMultiAdapter((field, self.widget.request),
- # interfaces.IFieldWidget)
- #converter = zope.component.getMultiAdapter((field, widget),
- # interfaces.IDataConverter)
-
- v = getattr(value, name, None)
- #rv[name] = converter.toWidgetValue(v)
- rv[name] = v
-
- return (rv, tuple())
-
- def toFieldValue(self, value):
- """See interfaces.IDataConverter"""
- #if self.factory is None:
- # adapter = zope.component.queryMultiAdapter(
- # (self.widget.context, self.widget.request, self.widget.form,
- # self.field.schema, self.widget),
- # interfaces.IValue, name='default')
- # if adapter:
- # obj = adapter.get()
- #else:
- # obj = self.factory()
-
- #this is creepy
- if value[1]:
- raise value[1][0].error
-
- obj = self.factory()
- for name, f in self._fields().items():
- try:
- setattr(obj, name, value[0][name])
- except KeyError:
- #smells like an input error?
- pass
- return obj
-
-
class BoolSingleCheckboxDataConverter(BaseDataConverter):
"A special converter between boolean fields and single checkbox widgets."
Modified: z3c.form/branches/adamg-objectwidget/src/z3c/form/dummy.py
===================================================================
--- z3c.form/branches/adamg-objectwidget/src/z3c/form/dummy.py 2008-10-07 17:37:12 UTC (rev 91877)
+++ z3c.form/branches/adamg-objectwidget/src/z3c/form/dummy.py 2008-10-07 18:32:12 UTC (rev 91878)
@@ -7,7 +7,8 @@
from zope.schema.fieldproperty import FieldProperty
class IMySubObject(zope.interface.Interface):
- foofield = zope.schema.Int(default=1111)
+ foofield = zope.schema.Int(default=1111,
+ max=9999)
barfield = zope.schema.Int(default=2222)
class MySubObject(object):
@@ -43,38 +44,59 @@
import zope.schema.interfaces
from z3c.form import interfaces
+from z3c.form.object import IObjectFactory
-
class FactoryAdapter(object):
""" """
- zope.interface.implements(interfaces.IValue)
+ zope.interface.implements(IObjectFactory)
zope.component.adapts(zope.interface.Interface, interfaces.IFormLayer,
- interfaces.IForm, zope.schema.interfaces.IField, interfaces.IWidget)
+ interfaces.IForm, interfaces.IWidget)
factory = None
- def __init__(self, context, request, form, field, widget):
+ def __init__(self, context, request, form, widget):
self.context = context
self.request = request
self.form = form
- self.field = field
self.widget = widget
- def get(self):
+ def get(self, value):
return self.factory()
def __repr__(self):
return '<%s %r>' % (self.__class__.__name__, self.__name__)
+#class MySubObjectFactory(FactoryAdapter):
+# zope.component.adapts(zope.interface.Interface, interfaces.IFormLayer,
+# interfaces.IForm, zope.interface.Interface, interfaces.IWidget)
+# #zope.component.adapts(zope.interface.Interface, interfaces.IFormLayer,
+# # interfaces.IForm, zope.schema.interfaces.IObject, interfaces.IWidget)
+#
+# factory = MySubObject
+#
+#class MySecondFactory(FactoryAdapter):
+# zope.component.adapts(zope.interface.Interface, interfaces.IFormLayer,
+# interfaces.IForm, zope.interface.Interface, interfaces.IWidget)
+# #zope.component.adapts(zope.interface.Interface, interfaces.IFormLayer,
+# # interfaces.IForm, zope.schema.interfaces.IObject, interfaces.IWidget)
+#
+# factory = MySecond
+
class MySubObjectFactory(FactoryAdapter):
- zope.component.adapts(zope.interface.Interface, interfaces.IFormLayer,
- interfaces.IForm, IMySubObject, interfaces.IWidget)
+ zope.component.adapts(
+ zope.interface.Interface, interfaces.IFormLayer,
+ interfaces.IForm, interfaces.IWidget)
+ #zope.component.adapts(zope.interface.Interface, interfaces.IFormLayer,
+ # interfaces.IForm, zope.schema.interfaces.IObject, interfaces.IWidget)
factory = MySubObject
class MySecondFactory(FactoryAdapter):
- zope.component.adapts(zope.interface.Interface, interfaces.IFormLayer,
- interfaces.IForm, IMySecond, interfaces.IWidget)
+ zope.component.adapts(
+ zope.interface.Interface, interfaces.IFormLayer,
+ interfaces.IForm, interfaces.IWidget)
+ #zope.component.adapts(zope.interface.Interface, interfaces.IFormLayer,
+ # interfaces.IForm, zope.schema.interfaces.IObject, interfaces.IWidget)
factory = MySecond
\ No newline at end of file
Modified: z3c.form/branches/adamg-objectwidget/src/z3c/form/error.py
===================================================================
--- z3c.form/branches/adamg-objectwidget/src/z3c/form/error.py 2008-10-07 17:37:12 UTC (rev 91877)
+++ z3c.form/branches/adamg-objectwidget/src/z3c/form/error.py 2008-10-07 18:32:12 UTC (rev 91878)
@@ -101,6 +101,23 @@
return self.error.args[0]
+class MultipleErrorViewSnippet(ErrorViewSnippet):
+ """Error view snippet for multiple errors."""
+ zope.component.adapts(
+ interfaces.IMultipleErrors, None, None, None, None, None)
+
+ def update(self):
+ output = ''
+ for error in self.error.errors:
+ view = zope.component.getMultiAdapter(
+ (error, self.request, widget, widget.field,
+ self.form, self.content), interfaces.IErrorViewSnippet)
+ output += view.render()
+ self.output = output
+
+ def render(self):
+ return self.output
+
class ErrorViewTemplateFactory(object):
"""Error view template factory."""
Modified: z3c.form/branches/adamg-objectwidget/src/z3c/form/interfaces.py
===================================================================
--- z3c.form/branches/adamg-objectwidget/src/z3c/form/interfaces.py 2008-10-07 17:37:12 UTC (rev 91877)
+++ z3c.form/branches/adamg-objectwidget/src/z3c/form/interfaces.py 2008-10-07 18:32:12 UTC (rev 91878)
@@ -154,6 +154,10 @@
def render():
"""Render view."""
+class IMultipleErrors(zope.interface.Interface):
+ """An error that contains many errors"""
+
+ errors = zope.interface.Attribute("List of errors")
# ----[ Fields ]--------------------------------------------------------------
@@ -509,7 +513,7 @@
"""Password widget."""
class IObjectWidget(IWidget):
- """Object widget."""
+ """Object widget."""
class IWidgets(IManager):
"""A widget manager"""
Added: z3c.form/branches/adamg-objectwidget/src/z3c/form/object.py
===================================================================
--- z3c.form/branches/adamg-objectwidget/src/z3c/form/object.py (rev 0)
+++ z3c.form/branches/adamg-objectwidget/src/z3c/form/object.py 2008-10-07 18:32:12 UTC (rev 91878)
@@ -0,0 +1,146 @@
+##############################################################################
+#
+# Copyright (c) 2007 Zope Foundation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Data Converters
+
+$Id$
+"""
+__docformat__ = "reStructuredText"
+import zope.i18n.format
+import zope.interface
+import zope.component
+import zope.schema
+
+from z3c.form.converter import BaseDataConverter
+
+from z3c.form.dummy import MySubObject
+from z3c.form import form, interfaces
+from z3c.form.field import Fields
+from z3c.form.i18n import MessageFactory as _
+
+class IObjectFactory(zope.interface.Interface):
+ """Factory that will instatiate our objects for ObjectWidget
+ """
+
+ def get(value):
+ """return a default object created to be populated
+ """
+
+class ObjectSubForm(form.BaseForm):
+ zope.interface.implements(interfaces.ISubForm)
+
+ formErrorsMessage = _('There were some errors.')
+ successMessage = _('Data successfully updated.')
+ noChangesMessage = _('No changes were applied.')
+
+ def __init__(self, context, parentWidget):
+ self.context = context
+ self.request = parentWidget.request
+ self.parentWidget = parentWidget
+ self.parentForm = self.__parent__ = parentWidget.form
+
+ def _validate(self):
+ for widget in self.widgets.values():
+ try:
+ # convert widget value to field value
+ converter = interfaces.IDataConverter(widget)
+ value = converter.toFieldValue(widget.value)
+ # validate field value
+ zope.component.getMultiAdapter(
+ (self.context,
+ self.request,
+ self.parentWidget.form,
+ getattr(widget, 'field', None),
+ widget),
+ interfaces.IValidator).validate(value)
+ except (zope.schema.ValidationError, ValueError), error:
+ # on exception, setup the widget error message
+ view = zope.component.getMultiAdapter(
+ (error, self.request, widget, widget.field,
+ self.parentWidget.form, self.context),
+ interfaces.IErrorViewSnippet)
+ view.update()
+ widget.error = view
+
+ def update(self):
+ self.fields = Fields(self.parentWidget.field.schema)
+
+ self.mode = self.parentWidget.mode
+ self.ignoreContext = self.parentWidget.ignoreContext
+ self.ignoreRequest = self.parentWidget.ignoreRequest
+ self.prefix = self.parentWidget.field.__name__
+
+ if interfaces.IFormAware.providedBy(self.parentWidget):
+ self.ignoreReadonly = self.parentWidget.form.ignoreReadonly
+
+ super(ObjectSubForm, self).update()
+
+ self._validate()
+
+
+class ObjectConverter(BaseDataConverter):
+ """Data converter for IObjectWidget."""
+
+ zope.component.adapts(
+ zope.schema.interfaces.IObject, interfaces.IObjectWidget)
+
+ #factory = MySubObject
+ factory = None
+
+ def _fields(self):
+ x = zope.schema.getFields(self.field.schema)
+ return x
+
+ def toWidgetValue(self, value):
+ """Just dispatch it."""
+ if value is self.field.missing_value:
+ return None
+
+ return value
+
+ def createObject(self, value):
+ #keep value passed, maybe some subclasses want it
+
+ if self.factory is None:
+ adapter = zope.component.queryMultiAdapter(
+ (self.widget.context, self.widget.request,
+ self.widget.form, self.widget),
+ IObjectFactory,
+ name=self.field.schema.__name__)
+ if adapter:
+ obj = adapter.get(value)
+ else:
+ #this is creepy, do we need this?
+ #there seems to be no way to dispatch???
+ obj = self.factory()
+
+ return obj
+
+ def toFieldValue(self, value):
+ """See interfaces.IDataConverter"""
+ if value[1]:
+ #lame, we must be able to show all errors
+ #if len(value[1])>1:
+ # from pub.dbgpclient import brk; brk('192.168.32.1')
+
+ raise value[1][0].error
+
+ obj = self.createObject(value)
+
+ for name, f in self._fields().items():
+ try:
+ setattr(obj, name, value[0][name])
+ except KeyError:
+ #smells like an input error?
+ pass
+ return obj
Property changes on: z3c.form/branches/adamg-objectwidget/src/z3c/form/object.py
___________________________________________________________________
Name: svn:keywords
+ Date Author Id Revision
Name: svn:eol-style
+ native
More information about the Checkins
mailing list