[Zope3-checkins] CVS: Zope3/src/zope/schema - __init__.py:1.12 _bootstrapfields.py:1.19 _field.py:1.18 interfaces.py:1.26

Richard Jones richard@commonground.com.au
Sun, 13 Jul 2003 02:47:33 -0400


Update of /cvs-repository/Zope3/src/zope/schema
In directory cvs.zope.org:/tmp/cvs-serv31581/src/zope/schema

Modified Files:
	__init__.py _bootstrapfields.py _field.py interfaces.py 
Log Message:
Implemented Object field types, and ObjectWidget to go with it.
Object fields have Fields on them, and when included in a form view, their
sub-fields fully participate in the form generate and editing. You'd use
this kinda thing for generating an Address field.

The change required the removal of the apply_update method on EditView. It is
replaced by the calling of applyChanges on each widget (facilitated by the 
applyWidgetsChanges function of zope.app.form.utility).

To make this sane, the ObjectWidget must be used via CustomWidget so we can
indicate which factory is to be called to generate the container for the
Object's fields. ObjectWidget and SequenceWidget also allow overriding of
the widgets used to render their sub-fields.

If this is all confusing, then see the new widgets.txt help file in the
zope/app/browser/form/ directory, and it may or may not help :)


=== Zope3/src/zope/schema/__init__.py 1.11 => 1.12 ===
--- Zope3/src/zope/schema/__init__.py:1.11	Thu Apr 24 16:51:58 2003
+++ Zope3/src/zope/schema/__init__.py	Sun Jul 13 02:47:28 2003
@@ -21,6 +21,7 @@
 from zope.schema._field import Bytes, BytesLine
 from zope.schema._field import Text, TextLine, Bool, Int, Float, Tuple, List
 from zope.schema._field import Password, Dict, Datetime, SourceText
+from zope.schema._field import Object
 from zope.schema._field import EnumeratedTextLine, EnumeratedInt
 from zope.schema._field import EnumeratedDatetime, EnumeratedFloat
 from zope.schema._field import InterfaceField


=== Zope3/src/zope/schema/_bootstrapfields.py 1.18 => 1.19 ===
--- Zope3/src/zope/schema/_bootstrapfields.py:1.18	Fri Jun 13 11:25:45 2003
+++ Zope3/src/zope/schema/_bootstrapfields.py	Sun Jul 13 02:47:28 2003
@@ -44,6 +44,10 @@
     _type = None
     context = None
 
+    # if input for this Field is missing, and that's ok, then this is the
+    # value to use
+    missing_value = None
+
     # Note that the "order" field has a dual existance:
     # 1. The class variable Field.order is used as a source for the
     #    monotonically increasing values used to provide...


=== Zope3/src/zope/schema/_field.py 1.17 => 1.18 ===
--- Zope3/src/zope/schema/_field.py:1.17	Fri Jul 11 22:47:22 2003
+++ Zope3/src/zope/schema/_field.py	Sun Jul 13 02:47:28 2003
@@ -30,7 +30,7 @@
 from zope.schema.interfaces import IInterfaceField
 from zope.schema.interfaces import IBool, IInt, IBytes, IBytesLine, IFloat
 from zope.schema.interfaces import IDatetime, ISequence, ITuple, IList, IDict
-from zope.schema.interfaces import IPassword
+from zope.schema.interfaces import IPassword, IObject
 from zope.schema.interfaces import IEnumeratedDatetime, IEnumeratedTextLine
 from zope.schema.interfaces import IEnumeratedInt, IEnumeratedFloat
 
@@ -171,12 +171,51 @@
     """A field representing a Tuple."""
     implements(ITuple)
     _type = tuple
+    missing_value = ()
 
 
 class List(Sequence):
     """A field representing a List."""
     implements(IList)
     _type = list
+    missing_value = []
+
+
+def _validate_fields(schema, value, errors=None):
+    if errors is None:
+        errors = []
+
+    for name, item in value.__dict__.items():
+        field = schema[name]
+        error = None
+        try:
+            field.validate(item)
+        except ValidationError, error:
+            pass
+        else:
+            # We validated, so clear error (if any) and done with
+            # this value
+            error = None
+            break
+
+        if error is not None:
+            errors.append(error)
+
+    return errors
+
+class Object(Field):
+    __doc__ = IObject.__doc__
+    implements(IObject)
+
+    def __init__(self, schema, **kw):
+        super(Object, self).__init__(**kw)
+        self.schema = schema
+
+    def _validate(self, value):
+        super(Object, self)._validate(value)
+        errors = _validate_fields(self.schema, value)
+        if errors:
+            raise ValidationError(WrongContainedType, errors)
 
 
 class Dict(MinMaxLen, Iterable, Field):


=== Zope3/src/zope/schema/interfaces.py 1.25 => 1.26 ===
--- Zope3/src/zope/schema/interfaces.py:1.25	Fri Jul 11 22:47:22 2003
+++ Zope3/src/zope/schema/interfaces.py	Sun Jul 13 02:47:28 2003
@@ -343,6 +343,12 @@
 class IList(ISequence):
     u"""Field containing a conventional list."""
 
+class IObject(IField):
+    u"""Field containing an Object value."""
+
+    schema = Attribute("schema",
+        _(u"The Interface that defines the Fields comprising the Object."))
+
 class IDict(IMinMaxLen, IIterable, IContainer):
     u"""Field containing a conventional dict.
 
@@ -359,7 +365,6 @@
         _(u"""Field values must conform to the given type, expressed
            via a Field.
         """))
-
 
 class IVocabularyQuery(Interface):
     """Query object for a vocabulary.