[Zope3-checkins] CVS: Zope3/lib/python/Zope/App/Forms - Exceptions.py:1.1 Converter.py:1.6 IConverter.py:1.2 IWidget.py:1.2 Widget.py:1.3
Jim Fulton
jim@zope.com
Sat, 7 Sep 2002 12:19:18 -0400
Update of /cvs-repository/Zope3/lib/python/Zope/App/Forms
In directory cvs.zope.org:/tmp/cvs-serv19433/lib/python/Zope/App/Forms
Modified Files:
Converter.py IConverter.py IWidget.py Widget.py
Added Files:
Exceptions.py
Log Message:
More cleanup/refactoring of Schemas and forms. There's more to come,
but I'm checkpointing here.
I:
- Added schema field properties. These are like standard Python
properies except that they are derived from Schema fields.
- Decomposed Str fields into Bytes fields and Text fields.
Bytes fields contain 8-bit data and are stored as python strings.
Text fields contain written human discourse, and are stored as
unicode. It is invalid to store Python strings in Text fields or
unicode in Bytes fields.
- Moved converters from schemas to forms, where they are used.
- Widgets are now responsible for:
- Getting raw data from the request
- Converting raw data to application data
- Validating converted data against schema fields
- Began defining an error framework for errors in forms.
- Simplified FormViews to reflect new widget responsibilities.
- Added Bytes, Int and Float widgets and changed some application and
test code to use them.
=== Added File Zope3/lib/python/Zope/App/Forms/Exceptions.py ===
##############################################################################
#
# 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.
#
##############################################################################
"""Validation Exceptions
$Id: Exceptions.py,v 1.1 2002/09/07 16:18:48 jim Exp $
"""
class WidgetInputError(Exception):
"""There were one or more user input errors
"""
def __init__(self, widget_name, widget_title, errors):
self.widget_name = widget_name
self.widget_title = widget_title
self.errors = errors
class ConversionError(WidgetInputError):
"""If some conversion fails, this exception is raised.
"""
def __init__(self, error_name, original_exception=None):
Exception.__init__(self)
self.error_name = error_name
self.original_exception = original_exception
=== Zope3/lib/python/Zope/App/Forms/Converter.py 1.5 => 1.6 ===
--- Zope3/lib/python/Zope/App/Forms/Converter.py:1.5 Thu Sep 5 14:55:01 2002
+++ Zope3/lib/python/Zope/App/Forms/Converter.py Sat Sep 7 12:18:48 2002
@@ -14,12 +14,72 @@
"""
$Id$
"""
-from types import TupleType, ListType
-ListTypes = (TupleType, ListType)
-from Zope.Schema.IConverter import IConverter
-from Zope.Schema.Converter import NullConverter
-from Zope.Schema.IField import IField
+from IConverter import IConverter
+from Exceptions import ConversionError
+
+class NullConverter(object):
+ """A converter that really doesn't do a thing.
+ """
+ __implements__ = IConverter
+
+ def convert(self, value):
+ return value
+
+class CombinedConverter(object):
+ """A converter that chains several converters to each other.
+ """
+ __implements__ = IConverter
+
+ def __init__(self, converters):
+ self._converters = converters
+
+ def convert(self, value):
+ for converter in self._converters:
+ value = converter.convert(value)
+ return value
+
+class FunctionConverter(object):
+ """Use a Python function to convert.
+ Turns *any* Python exception into a conversion error.
+ XXX Is this good/useful?
+ """
+ __implements__ = IConverter
+
+ def convert(self, value):
+ try:
+ return self._function(value)
+ except Exception, e:
+ raise ConversionError('Conversion error', e)
+
+def _functionConverterFactory(klass_name, function):
+ """Create a derived class of FunctionConvert which uses function.
+ """
+ klass = type(klass_name, (FunctionConverter,), {})
+ klass._function = function
+ return klass
+
+StrToIntConverter= _functionConverterFactory('StrToIntConverter', int)
+IntToStrConverter = _functionConverterFactory('IntToStrConverter', str)
+
+StrToFloatConverter = _functionConverterFactory('StrToFloatConverter', float)
+FloatToStrConverter = _functionConverterFactory('FloatToStrConverter', str)
+
+
+class FileToStrConverter(object):
+ __implements__ = IConverter
+
+ def convert(self, value):
+ try:
+ value = value.read()
+ except Exception, e:
+ raise ConversionError('Value is not a file object', e)
+ else:
+ if len(value):
+ return value
+ else:
+ return None
+
class RawToHomogeneousListConverter(NullConverter):
"""Converts a list of raw values to a list of values with a specific
@@ -35,19 +95,6 @@
return result
-class FieldToFieldConverter(NullConverter):
- """ """
- __convert_from__ = IField
- __convert_to__ = IField
-
- def convert(self, value):
- 'See Zope.App.Forms.IConverter.IConverter'
- assert isinstance(value, self.__convert_from__.type), 'Wrong Type'
- value = self.__convert_to__.type(value)
- assert isinstance(value, self.__convert_to__.type), 'Wrong Type'
- return value
-
-
class NoneToEmptyListConverter(NullConverter):
"""Converts None object to an empty list."""
@@ -57,12 +104,13 @@
else:
return value
-
class ValueToSingleItemListConverter(NullConverter):
"""Converts a single value to a list with the value being the only
element."""
- def convert(self, value):
+ def convert(self, value,
+ ListTypes = (tuple, list)
+ ):
if not isinstance(value, ListTypes):
return [value]
else:
=== Zope3/lib/python/Zope/App/Forms/IConverter.py 1.1 => 1.2 ===
--- Zope3/lib/python/Zope/App/Forms/IConverter.py:1.1 Sun Jul 14 09:32:53 2002
+++ Zope3/lib/python/Zope/App/Forms/IConverter.py Sat Sep 7 12:18:48 2002
@@ -14,18 +14,14 @@
"""
$Id$
"""
-
from Interface import Interface
-from Interface.Attribute import Attribute
-
class IConverter(Interface):
- """Converts from one type of Field type to another one. Most common will
- be to convert from String to another type, such as Integer."""
-
- __convert_to__ = Attribute('The field type this converter converts to.')
- __convert_from__ = Attribute('The field type this converter accepts '
- 'for conversion.')
+ """A converter can convert a value from one type to another."""
def convert(value):
- """This method converts from __convert_from__ to __convert_to__."""
+ """Call an IConverter with a value, and it will try to convert to
+ another value and return the result. If conversion cannot take
+ place, the convertor will raise a ConversionError.
+ """
+
=== Zope3/lib/python/Zope/App/Forms/IWidget.py 1.1 => 1.2 ===
--- Zope3/lib/python/Zope/App/Forms/IWidget.py:1.1 Sun Jul 14 09:32:53 2002
+++ Zope3/lib/python/Zope/App/Forms/IWidget.py Sat Sep 7 12:18:48 2002
@@ -14,10 +14,10 @@
"""
$Id$
"""
-from Zope.ComponentArchitecture.IContextDependent import IContextDependent
+from Zope.ComponentArchitecture.IView import IView
from Interface.Attribute import Attribute
-class IWidget(IContextDependent):
+class IWidget(IView):
"""Generically describes the behavior of a widget.
The widget defines a list of propertyNames, which describes
@@ -32,3 +32,23 @@
def getValue(name):
"""Look up a Widget setting (value) by name."""
+
+ def getData():
+ """Return converted and validated widget data.
+
+ A WidgetInputError is returned in the case of one or more
+ errors encountered, inputing, convrting, or validating the data.
+ """
+
+ def getName():
+ """Return the unique name for the widget.
+
+ This must be unique within a set of widgets.
+ """
+
+ def getTitle():
+ """Return the widget title.
+
+ This is the text that will be used to label the widget.
+ """
+
=== Zope3/lib/python/Zope/App/Forms/Widget.py 1.2 => 1.3 ===
--- Zope3/lib/python/Zope/App/Forms/Widget.py:1.2 Tue Jul 16 19:42:58 2002
+++ Zope3/lib/python/Zope/App/Forms/Widget.py Sat Sep 7 12:18:48 2002
@@ -15,12 +15,18 @@
$Id$
"""
from IWidget import IWidget
+from Zope.Schema.Exceptions import ValidationError
+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."""
__implements__ = IWidget
+ def __init__(self, context, request):
+ self.context = context
+ self.request = request
+
# See Zope.App.Forms.IWidget.IWidget
propertyNames = []
@@ -29,6 +35,21 @@
if name in self.propertyNames:
return getattr(self, name, None)
+ def getName(self):
+ return self.context.getName()
+
+ def getTitle(self):
+ return self.context.title
+
+ def getData(self):
+ raw = self._getRawData()
+ value = self._convert(raw)
+ try:
+ self.context.validate(value)
+ except ValidationError, v:
+ raise WidgetInputError(self.getName(), self.getTitle(), v)
+
+ return value
class CustomWidget(object):
"""Custom Widget."""
@@ -44,3 +65,13 @@
setattr(instance, item[0], item[1])
return instance
+class Customizer:
+ """Objects for making shorthands for creating CustomWidgets
+ """
+
+ def __init__(self, widget_class):
+ self.__widget_class = widget_class
+
+ def __call__(self, **kw):
+ # XXX should have error checking here!
+ return CustomWidgets(self.__widget_class, **kw)