[Zope3-checkins] CVS: Zope3/lib/python/Zope/App/Forms - Utility.py:1.2 Exceptions.py:1.3 IWidget.py:1.4 Widget.py:1.4
Jim Fulton
jim@zope.com
Mon, 28 Oct 2002 18:53:01 -0500
Update of /cvs-repository/Zope3/lib/python/Zope/App/Forms
In directory cvs.zope.org:/tmp/cvs-serv12652/lib/python/Zope/App/Forms
Modified Files:
Exceptions.py IWidget.py Widget.py
Added Files:
Utility.py
Log Message:
Merged the form (Zope.App.Forms) changes from the
Zope3-Banagalore-TTW-Branch branch.
See IWidget and IBrwoserWidget for important changes to those
interfaces.
See Utility.py for a number of functions for managing schema-driven
forms. These will ultimately replace FormViews, which will, I hope,
soon be deprecated.
=== Zope3/lib/python/Zope/App/Forms/Utility.py 1.1 => 1.2 ===
--- /dev/null Mon Oct 28 18:53:01 2002
+++ Zope3/lib/python/Zope/App/Forms/Utility.py Mon Oct 28 18:52:31 2002
@@ -0,0 +1,146 @@
+##############################################################################
+#
+# Copyright (c) 2002 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (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.
+#
+##############################################################################
+"""Form utility functions
+
+In Zope 2's formulator, forms provide a basic mechanism for
+organizating collections of fields and providing unsert interfaces for
+them, especially editing interfaces.
+
+In Zope 3, formulator's forms are replaced by Schema (See
+Zope.Schema). In addition, the Formulator fields have been replaced by
+schema filds and form widgets. Schema fields just express the sematics
+of data values. They contain no presentation logic or parameters.
+Widgets are views on fields that take care of presentation. The widget
+view names represent styles that can be selected by applications to
+customise the presentation. There can also be custom widgets with
+specific parameters.
+
+This module provides some utility functions that provide some of the
+functionality of formulator forms that isn't handled by schema,
+fields, or widgets.
+
+$Id$
+"""
+__metaclass__ = type
+
+from Zope.ComponentArchitecture import getView, getDefaultViewName
+from Zope.Schema.IField import IField
+from Zope.App.Forms.IWidget import IWidget
+from Zope.App.Forms.Exceptions import WidgetsError
+from Zope.Proxy.ContextWrapper import ContextWrapper
+
+
+def setUpWidget(view, name, field, value=None):
+ """Set up a single view widget
+
+ The widget will be an attribute of the view. If there is already
+ an attribute of the given name, it must be a widget and it will be
+ initialized with the given value if not None.
+
+ If there isn't already a view attribute of the given name, then a
+ widget will be created and assigned to the attribute.
+ """
+
+ # Has a (custom) widget already been defined?
+ widget = getattr(view, name, None)
+ if widget is None:
+ # There isn't already a widget, create one
+ field = ContextWrapper(field, view.context, name=name)
+ vname = getDefaultViewName(field, view.request)
+ widget = getView(field, vname, view.request)
+ setattr(view, name, widget)
+ else:
+ # We have an attribute of the right name, it it really a widget
+ if not IWidget.isImplementedBy(widget):
+ raise TypeError(
+ "The %s view attribute named, %s, should be a widget, "
+ "but isn't."
+ % (view.__class__.__name__, name))
+
+ if value is not None:
+ widget.setData(value)
+
+def setUpWidgets(view, schema, **kw):
+ """Set up widgets for the fields defined by a schema
+
+ Initial data is provided by keyword arguments.
+ """
+
+ for name in schema:
+ field = schema[name]
+ if IField.isImplementedBy(field):
+ # OK, we really got a field
+ setUpWidget(view, name, field, kw.get(name))
+
+def setUpEditWidgets(view, schema, content=None):
+ """Set up widgets for the fields defined by a schema
+
+ Initial data is provided by content object attributes.
+ No initial data is provided if the content lacks a named
+ attribute, or if the named attribute value is None.
+ """
+ if content is None:
+ content = view.context
+
+ for name in schema:
+ field = schema[name]
+ if IField.isImplementedBy(field):
+ # OK, we really got a field
+ setUpWidget(view, name, field, getattr(content, name, None))
+
+def getWidgetsData(view, schema):
+ """Collect the user-entered data defined by a schema
+
+ Data is collected from view widgets. For every field in the
+ schema, we look for a view of the same name and get it's data.
+
+ The data are returned in a mapping from field name to value.
+ """
+
+ result = {}
+ errors = []
+
+ for name in schema:
+ field = schema[name]
+ if IField.isImplementedBy(field):
+ # OK, we really got a field
+ try:
+ result[name] = getattr(view, name).getData()
+ except Exception, v:
+ errors.append(v)
+
+ if errors:
+ raise WidgetsError(*errors)
+
+ return result
+
+def getWidgetsDataForContent(view, schema, content=None):
+ """Collect the user-entered data defined by a schema
+
+ Data is collected from view widgets. For every field in the
+ schema, we look for a view of the same name and get it's data.
+
+ The data are assigned to the given content object.
+ """
+ data = getWidgetsData(view, schema)
+
+ if content is None:
+ content = view.context
+
+ for name in schema:
+ field = schema[name]
+ if IField.isImplementedBy(field):
+ # OK, we really got a field
+ setattr(content, name, getattr(view, name).getData())
+
=== Zope3/lib/python/Zope/App/Forms/Exceptions.py 1.2 => 1.3 ===
--- Zope3/lib/python/Zope/App/Forms/Exceptions.py:1.2 Wed Oct 9 09:53:54 2002
+++ Zope3/lib/python/Zope/App/Forms/Exceptions.py Mon Oct 28 18:52:31 2002
@@ -37,3 +37,28 @@
self.error_name = error_name
self.original_exception = original_exception
+
+class ErrorContainer(Exception):
+ """A base error class for collecting multiple errors
+ """
+
+ def append(self, error):
+ self.args += (error, )
+
+ def __len__(self):
+ return len(self.args)
+
+ def __iter__(self):
+ return iter(self.args)
+
+ def __getitem__(self, i):
+ return self.args[i]
+
+ def __str__(self):
+ return "\n".join(map(str, self.args))
+
+ __repr__ = __str__
+
+class WidgetsError(ErrorContainer):
+ """A collection of errors from widget processing.
+ """
=== Zope3/lib/python/Zope/App/Forms/IWidget.py 1.3 => 1.4 ===
--- Zope3/lib/python/Zope/App/Forms/IWidget.py:1.3 Wed Oct 9 09:26:06 2002
+++ Zope3/lib/python/Zope/App/Forms/IWidget.py Mon Oct 28 18:52:31 2002
@@ -51,4 +51,9 @@
This is the text that will be used to label the widget.
"""
+ def setData(value):
+ """Set the default data for the widget.
+ The given value should only be used if the user hasn't entered
+ any data and the data should be a valid data for the field.
+ """
=== Zope3/lib/python/Zope/App/Forms/Widget.py 1.3 => 1.4 ===
--- Zope3/lib/python/Zope/App/Forms/Widget.py:1.3 Sat Sep 7 12:18:48 2002
+++ Zope3/lib/python/Zope/App/Forms/Widget.py Mon Oct 28 18:52:31 2002
@@ -19,8 +19,10 @@
from Zope.App.Forms.Exceptions import WidgetInputError
class Widget(object):
- """I do not know what will be in this class, but it provides an extra
- layer."""
+ """Mix-in class providing some functionality common accross view types
+ """
+
+
__implements__ = IWidget
def __init__(self, context, request):