[Zope3-checkins] CVS: Zope3/lib/python/Zope/Schema - _bootstrapFields.py:1.1 ErrorNames.py:1.2 Exceptions.py:1.3 FieldProperty.py:1.3 IField.py:1.3 _Field.py:1.3 _Schema.py:1.3 IValidator.py:NONE Validator.py:NONE

Jim Fulton jim@zope.com
Wed, 11 Sep 2002 18:06:42 -0400


Update of /cvs-repository/Zope3/lib/python/Zope/Schema
In directory cvs.zope.org:/tmp/cvs-serv7363

Modified Files:
	ErrorNames.py Exceptions.py FieldProperty.py IField.py 
	_Field.py _Schema.py 
Added Files:
	_bootstrapFields.py 
Removed Files:
	IValidator.py Validator.py 
Log Message:
Major refactoring of schemas:

  - Ripped out the validation framework. Fields now coordinate
    validation through inheritence with the help of super. I'm a big
    fan of super.

  - Field constructors no longer accept and set arbitrary field
    parameters. Fields only accepr keyword settings for settable
    attributes. 

  - Almost all field attributes are implemented with property-like
    objects that validate field attribute values. 

  - Field titles and descriptions are now unicode.

  - Field __name__ and __doc__ attributes can now ne provided with
    constructor keyword arguments.  The __name__ attribute is normally
    provided automatically by the interface initialization machinery.
    It might be useful to provide a __name__ attribute explicitly when
    a field is used outside of an interface.  If no __doc__ value is
    provided in the constructor, one will be computed from the title
    and description.

  - Fields can now be given an atribtrary constraint, which is just a
    callable object that returns a true value if the constraint is
    satisfied and false otherwise. It could also raise a
    ValidationError to provide an error message.

  - Fields keep track of the order in which they are defined. This is
    helpful for automatic form generation to get the form fields in
    the same order as the schema fields.

  - The sequence and dictionary fields (is anyone using these?) now
    restrict contents using fields, rather than types.

  - Float fields no longer accept ints.

  - Int fields now accept longs.

  - Handling of field attributes like default, min, max, and
    allowed_values are now defined recursively and validated with
    specialized properties. This allowed the definition of field
    interfaces and bootstrapping to be simplified.

  - Got rid of Float.decimals. YAGNI.

  - Boolean fields no longer have an allowable_values attribute. ;)

  - A number of new abstract field interfaces and implementations were
    added.




=== Added File Zope3/lib/python/Zope/Schema/_bootstrapFields.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.
# 
##############################################################################
"""
$Id: _bootstrapFields.py,v 1.1 2002/09/11 22:06:41 jim Exp $
"""
__metaclass__ = type

from Interface.Attribute import Attribute
from Exceptions import StopValidation, ValidationError
import ErrorNames

class ValidatedProperty:

    def __init__(self, name, check = None):
        self.__info  = name, check

    def __set__(self, inst, value):
        name, check = self.__info
        if value is not None:
            if check is not None:
                check(inst, value)
            else:
                inst.validate(value)
        inst.__dict__[name] = value
        
class Field(Attribute):

    # Type restrictions, if any
    _type = None
    order = 0l

    constraint = None
    default = ValidatedProperty('default')
    
    def __init__(self, __name__='', __doc__='',
                 title=u'', description=u'',
                 required=0, readonly=0, constraint=None, default=None,
                 ):
        """Pass in field values as keyword parameters."""


        if not __doc__:
            if title:
                if description:
                    __doc__ =  "%s\n\n%s" % (title, description)
                else:
                    __doc__ = title
            elif description:
                __doc__ = description

        super(Field, self).__init__(__name__, __doc__)
        self.title = title
        self.description = description
        self.required = required
        self.readonly = readonly
        self.constraint = constraint
        self.default = default

        # Keep track of the order of field definition
        Field.order += 1
        self.order = Field.order

        
    def validate(self, value):
        if value is None:
            if self.required:
                raise ValidationError(ErrorNames.RequiredMissing)
        else:
            try:
                self._validate(value)
            except StopValidation:
                pass
        
    def _validate(self, value):

        if self._type is not None and not isinstance(value, self._type):
            raise ValidationError(ErrorNames.WrongType, value, self._type)

        if self.constraint is not None and not self.constraint(value):
            raise ValidationError(ErrorNames.ConstraintNotSatisfied, value)


class Container(Field):

    def _validate(self, value):
        super(Container, self)._validate(value)

        if not hasattr(value, '__contains__'):
            try:
                iter(value)
            except:
                raise ValidationError(ErrorNames.NotAContainer, value)
                
                
class Iteratable(Container):

    def _validate(self, value):
        super(Iteratable, self)._validate(value)

        # See if we can get an iterator for it
        try:
            iter(value)
        except:
            raise ValidationError(ErrorNames.NotAnIterator, value)


class Orderable(Field):
    """Values of ordered fields can be sorted

    They can be restricted to a range of values.
    """

    min = ValidatedProperty('min')
    max = ValidatedProperty('max')

    def __init__(self, min=None, max=None, default=None, **kw):

        # Set min and max to None so that we can validate if
        # one of the super methods invoke validation.
        self.min = None
        self.max = None

        super(Orderable, self).__init__(**kw)

        # Now really set min and max
        self.min = min
        self.max = max

        # We've taken over setting default so it can be limited by min
        # and max.
        self.default = default
        

    def _validate(self, value):
        super(Orderable, self)._validate(value)
        
        if self.min is not None and value < self.min:
            raise ValidationError(ErrorNames.TooSmall, value, self.min)

        if self.max is not None and value > self.max:
            raise ValidationError(ErrorNames.TooBig, value, self.max)

_int_types = int, long
class Sized(Field):
    min_length = 0
    max_length = None

    def __init__(self, min_length=0, max_length=None, **kw):
        self.min_length = min_length
        self.max_length = max_length
        super(Sized, self).__init__(**kw)

    def _validate(self, value):
        super(Sized, self)._validate(value)

        if self.min_length is not None and len(value) < self.min_length:
            raise ValidationError(ErrorNames.TooShort, value, self.min_length)

        if self.max_length is not None and len(value) > self.max_length:
            raise ValidationError(ErrorNames.TooLong, value, self.max_length)
        

class Enumeratable(Field):

    def allowed_values(self, values):
        # Reset current value so it doesn't hose validation
        if not values:
            return
        
        old_allowed = getattr(self, 'allowed_values', None)
        self.allowed_values = None

        for value in values:
            
            try:
                self.validate(value)
            except:
                # restore the old value 
                self.allowed_values = old_allowed
                raise

    allowed_values = ValidatedProperty('allowed_values', allowed_values)

    def __init__(self, allowed_values=None, default=None, **kw):

        # Set allowed_values to None so that we can validate if
        # one of the super methods invoke validation.
        self.allowed_values = None
        super(Enumeratable, self).__init__(**kw)
        self.allowed_values = allowed_values

        # We've taken over setting default so it can be limited by min
        # and max.
        self.default = default

    def _validate(self, value):
        super(Enumeratable, self)._validate(value)

        if self.allowed_values:
            if not value in self.allowed_values:
                raise ValidationError(ErrorNames.InvalidValue)


class Text(Sized, Enumeratable):
    """A field representing a Str."""
    _type = unicode

class Bool(Field):
    """A field representing a Bool."""

    try:
        if type(True) is int:
            # If we have True and it's an int, then pretend we're 2.2.0.
            raise NameError("True") 
    except NameError:
        # Pre booleans
        _type = int
    else:
        _type = bool

class Int(Enumeratable, Orderable):
    """A field representing a Integer."""
    _type = int, long


=== Zope3/lib/python/Zope/Schema/ErrorNames.py 1.1 => 1.2 ===
--- Zope3/lib/python/Zope/Schema/ErrorNames.py:1.1	Thu Sep  5 14:55:03 2002
+++ Zope3/lib/python/Zope/Schema/ErrorNames.py	Wed Sep 11 18:06:41 2002
@@ -15,26 +15,28 @@
 
 $Id$
 """
-WrongType = "WrongType"
+WrongType = u"WrongType"
 
-RequiredMissing ='RequiredMissing'
+RequiredMissing = u'RequiredMissing'
 
-RequiredEmptyStr = 'RequiredEmptyString'
+RequiredEmptyStr = u'RequiredEmptyString'
 
-TooBig = 'TooBig'
+TooBig = u'TooBig'
 
-TooSmall = 'TooSmall'
+TooSmall = u'TooSmall'
 
-TooLong = 'TooLong'
+TooLong = u'TooLong'
 
-TooShort = 'TooShort'
+TooShort = u'TooShort'
 
-InvalidValue = 'InvalidValue'
+InvalidValue = u'InvalidValue'
 
-TooManyDecimals = 'TooManyDecimals'
+TooManyDecimals = u'TooManyDecimals'
 
-WrongContainedType = "WrongContainedType"
+WrongContainedType = u"WrongContainedType"
 
-NotEnoughElements = 'NotEnoughElements'
+ConstraintNotSatisfied = u'ConstraintNotSatisfied'
 
-TooManyElements = 'TooManyElements'
+NotAContainer = u'NotAContainer'
+
+NotAnIterator = u'NotAnIterator'


=== Zope3/lib/python/Zope/Schema/Exceptions.py 1.2 => 1.3 ===
--- Zope3/lib/python/Zope/Schema/Exceptions.py:1.2	Sat Sep  7 12:18:51 2002
+++ Zope3/lib/python/Zope/Schema/Exceptions.py	Wed Sep 11 18:06:41 2002
@@ -27,13 +27,11 @@
     """If some check during the Validation process fails, this exception is
     raised."""
 
-    def __init__(self, error_name):
-        Exception.__init__(self)
-        self.error_name = error_name
-
     def __cmp__(self, other):
-        return cmp(self.error_name, other.error_name)
+        return cmp(self.args, other.args)
 
+    def __repr__(self):
+        return ' '.join(map(str, self.args))
 
 # XXX YAGNI, this is doomed. ;)
 


=== Zope3/lib/python/Zope/Schema/FieldProperty.py 1.2 => 1.3 ===
--- Zope3/lib/python/Zope/Schema/FieldProperty.py:1.2	Sun Sep  8 09:52:13 2002
+++ Zope3/lib/python/Zope/Schema/FieldProperty.py	Wed Sep 11 18:06:41 2002
@@ -52,7 +52,9 @@
     def __set__(self, inst, value):
         self.__field.validate(value)
         inst.__dict__[self.__name] = value
-            
+
+    def __getattr__(self, name):
+        return getattr(self.__field, name)
 
 __doc__ = FieldProperty.__doc__ + __doc__
 


=== Zope3/lib/python/Zope/Schema/IField.py 1.2 => 1.3 ===
--- Zope3/lib/python/Zope/Schema/IField.py:1.2	Sat Sep  7 12:18:51 2002
+++ Zope3/lib/python/Zope/Schema/IField.py	Wed Sep 11 18:06:41 2002
@@ -16,231 +16,210 @@
 $Id$
 """
 from Interface import Interface
-import _Field as Field
+
+from _bootstrapFields import Field, Text, Bool, Int, Container, Iteratable
 
 class IField(Interface):
-    """All fields conform to this schema. Note that the interpretation
-    of 'required' is up to each field by itself. For some fields, such as
-    IBool, requiredness settings may make no difference.
+    u"""Fields
+
+    Fields are attribute specifications.
     """
 
-    title = Field.Text(
-        title="Title",
-        description="Title.",
-        default=""
+    title = Text(
+        title=u"Title",
+        description=u"A short summary or label",
+        default=u"",
+        required=0,
         )
     
-    description = Field.Text(
-        title="Description",
-        description="Description.",
-        default="",
-        required=0)
+    description = Text(
+        title=u"Description",
+        description=u"A description of the field",
+        default=u"",
+        required=0,)
+    
+    required = Bool(
+        title=u"Required",
+        description=(
+        u"An indication of whether the field value must be provided"),
+        default=1)
 
-    readonly = Field.Bool(
-        title="Read Only",
-        description="Read-only.",
+    readonly = Bool(
+        title="uRead Only",
+        description=u"Read-only.", # XXX what is this?
         default=0)
-    
-    required = Field.Bool(
-        title="Required",
-        description="Required.",
-        default=1)
+
+    default = Field(
+        title=u"The default field value",
+        description=u"""The field default value may be None or a legal
+                        field value"""
+        )
+
+    def constraint(value):
+        u"""Optional vaue constraint
+
+        Returns true is the value is legal, and false otherwise.
+
+        This is typically specified as a constructor argument.
+        """
 
     def validate(value):
-        """Validate that the given value is a valid field entry.
+        u"""Validate that the given value is a valid field entry.
 
         Returns nothing but raises an error if the value is invalid.
         """
+    order = Int(
+        title=u"Field Order",
+        description=u"""\
+        The order attribute can be used to determine the order in
+        which fields in a schema were defined. If one field is created
+        after another (in the same thread), it's order will be
+        greater.
+
+        (Fields in separate threads could have the same order.)
+        """,
+        required=1,
+        readonly=1,
+        )
 
-class ISingleValueField(IField):
-    """This field consists always only of one value and it not a homogeneous
-    container, like a list. Note that structures and instances of classes
-    might or might not be ISingleValueFields."""
-    
-    allowed_values = Field.Tuple(
-        title="Allowed Values",
-        description="Only values specified here can be values of this field. "
-                    "If the list is empty, then there are no further "
-                    "restictions.",
-        required=0,
-        default=())
-        
-
-    
-class IBool(ISingleValueField):
-    """Describes the footprint of a Bool variable."""
+class IContainer(IField):
+    u"""Fields with values that allow containment checks using the in operator
 
-    default = Field.Bool(
-        title="Default",
-        description="Default.",
-        default=0)
+    Values include squences, iteratorable objects, and any objects
+    that implement __contains__.
+    """
 
+class IIteratable(IContainer):
+    u"""Fields with value that can be iterated over
+    """
 
-class IBytes(ISingleValueField):
-    """Describes the footprint of a Bytes variable."""
+class IOrderable(IField):
+    u"""Orderable values
 
-    default = Field.Bytes(
-        title="Default",
-        description="Default.",
-        default="")
-    
-    min_length = Field.Int(
-        title="Minimum length",
-        description=("Value after whitespace processing cannot have less than "
-                     "min_length characters. If min_length is None, there is "
-                     "no minimum."),
-        required=0,
-        min=0, # needs to be a positive number
-        default=0)
+    They can be restricted to a range of values by specifying a
+    minimum and maximum value.
+    """
 
-    max_length = Field.Int(
-        title="Maximum length",
-        description=("Value after whitespace processing cannot have greater "
-                     "or equal than max_length characters. If max_length is "
-                     "None, there is no maximum."),
-        required=0,
-        min=0, # needs to be a positive number
-        default=None)
+    min = Field(
+        title=u"The minimum allowable value",
+        description=u"""\
+        If this value is not None, then it must be a legal field value
+        and all field values must be less than this valie.        
+        """
+        )
 
-class IText(ISingleValueField):
-    """Describes the footprint of a Str variable."""
+    max = Field(
+        title=u"The maximum allowable value",
+        description=u"""\
+        If this value is not None, then it must be a legal field value
+        and all field values must be greater than this valie.        
+        """
+        )
 
-    default = Field.Text(
-        title="Default",
-        description="Default.",
-        default=u"")
+class ISized(IField):
+    u"""Sized objects may have a minimum and maximum length
+    """
     
-    min_length = Field.Int(
-        title="Minimum length",
-        description=("Value after whitespace processing cannot have less than "
-                     "min_length characters. If min_length is None, there is "
-                     "no minimum."),
+    min_length = Int(
+        title=u"Minimum length",
+        description=u"""\
+        Value after whitespace processing cannot have less than 
+        min_length characters. If min_length is None, there is 
+        no minimum.
+        """,
         required=0,
         min=0, # needs to be a positive number
         default=0)
 
-    max_length = Field.Int(
-        title="Maximum length",
-        description=("Value after whitespace processing cannot have greater "
-                     "or equal than max_length characters. If max_length is "
-                     "None, there is no maximum."),
+    max_length = Int(
+        title=u"Maximum length",
+        description=u"""\
+        Value after whitespace processing cannot have greater
+        or equal than max_length characters. If max_length is
+        None, there is no maximum.""",
         required=0,
         min=0, # needs to be a positive number
         default=None)
 
-    
-class IInt(ISingleValueField):
-    """Describes the footprint of an Int variable."""
 
-    default = Field.Int(
-        title="Default",
-        description="Default.",
-        default=0)
+class IEnumeratable(IField):
+    u"""Fields with values that may be constrained to a set of values
+    """
     
-    min = Field.Int(
-        title="Minimum",
-        description="The minimal numerical value accepted. If min is None, "
-                    "there is no minimum.",
-        required=0,
-        default=0)
+    allowed_values = Container(
+        title=u"Allowed Values",
+        description=u"""\
+        Only values specified here can be values of this field.
+        If the list is empty, then there are no further
+        restictions.""",
+        required=0)
+            
+class IBool(IField):
+    u"""Describes the footprint of a Bool variable."""
 
-    max = Field.Int(
-        title="Maximum",
-        description="The masximal numerical value accepted. If min is None, "
-                    "there is no minimum.",
-        required=0,
-        default=None)
-    
-    
-class IFloat(ISingleValueField):
-    """Describes the footprint of a Float variable."""
+class IBytes(ISized, IEnumeratable, IIteratable):
+    u"""Describes the footprint of a Bytes variable."""
 
-    default = Field.Float(
-        title="Default",
-        description="Default.",
-        default=0)
+class IText(ISized, IEnumeratable, IIteratable):
+    u"""Describes the footprint of a Str variable."""
     
-    min = Field.Float(
-        title="Minimum",
-        description="The minimal numerical value accepted. If min is None, "
-                    "there is no minimum.",
-        required=0,
-        default=0)
+class IInt(IEnumeratable, IOrderable):
+    u"""Describes the footprint of an Int variable."""
+        
+class IFloat(IEnumeratable, IOrderable):
+    u"""Describes the footprint of a Float variable."""
 
-    max = Field.Float(
-        title="Maximum",
-        description="The masximal numerical value accepted. If min is None, "
-                    "there is no minimum.",
-        required=0,
-        default=None)
-    
-    decimals = Field.Int(
-        title="Decimal Places",
-        description="Defines the amount of decimal places the floating point "
-                    "can have. This value is also know as precision. If the "
-                    "value is None, no precision is required.",
-        required=0,
-        default=None)
+def _fields(values):
+    for value in values:
+        if not IField.isImplementedBy(value):
+            return 0
+    return 1
 
+class ISequence(ISized, IIteratable):
+    u"""Describes fields that can hold a sequence values
 
-class IMultipleValueField(IField):
-    """This field will contain some sort of collection of objects whose types
-    can be often defined through a finite set of types."""
-
-    value_types = Field.Tuple(
-        title="Value Types",
-        description="Defines the value types that are allowed in the list. "
-                    "If the list is empty, then all types are allowed.",
-        required=0,
-        default=())
-
-    min_values = Field.Int(
-        title="Minimum amount of values",
-        description="The minimum amount of values in the list. If min_values "
-                    "is None, there is no minimum.",
-        min=0,
-        required=0,
-        default=0)
+    These values may be constrained.
+    """
 
-    max_values = Field.Int(
-        title="Maximum amount of values",
-        description="The maximum amount of values in the list. If max_values "
-                    "is None, there is no maximum.",
-        min=0,
+    value_types = Iteratable(
+        title=u"Value Types",
+        description=(
+        u"""\
+        If set to a non-empty value, field value items must conform to one
+        of the given types, which are expressed via fields.
+        """),
         required=0,
-        default=None)
-
-
-class ITuple(IMultipleValueField):
-    """Describes the footprint of a Tuple variable."""
-
-    default = Field.Tuple(
-        title="Default",
-        description="Default.",
-        default=())    
-
+        constraint=_fields,
+        )
 
-class IList(ITuple):
-    """Describes the footprint of a List variable."""
 
-    default = Field.List(
-        title="Default",
-        description="Default.",
-        default=[])
+class ITuple(ISequence):
+    u"""Describes the footprint of a Tuple variable."""
 
+class IList(ISequence):
+    u"""Describes the footprint of a List variable."""
 
-class IDict(IMultipleValueField):
-    """Describes the footprint of a Dict variable."""
 
-    default = Field.Dict(
-        title="Default",
-        description="Default.",
-        default={})    
+class IDict(ISized, IIteratable):
+    u"""Describes the footprint of a Dict variable."""
+
+    key_types = Iteratable(
+        title=u"Value Types",
+        description=u"""\
+        If set to a non-empty value, field value keys must conform to one
+        of the given types, which are expressed via fields.
+        """,
+        constraint=_fields,
+        required=0,
+        )
 
-    key_types = Field.Tuple(
-        title="Value Types",
-        description="Defines the key types that are allowed in the "
-                    "dictionary. If the list is empty, then all types "
-                    "are allowed.",
+    value_types = Iteratable(
+        title=u"Value Types",
+        description=(
+        u"""\
+        If set to a non-empty value, field value values must conform to one
+        of the given types, which are expressed via fields.
+        """),
+        constraint=_fields,
         required=0,
-        default=())
+        )


=== Zope3/lib/python/Zope/Schema/_Field.py 1.2 => 1.3 ===
--- Zope3/lib/python/Zope/Schema/_Field.py:1.2	Sat Sep  7 12:18:51 2002
+++ Zope3/lib/python/Zope/Schema/_Field.py	Wed Sep 11 18:06:41 2002
@@ -14,80 +14,131 @@
 """
 $Id$
 """
+__metaclass__ = object
+
 from Interface.Attribute import Attribute
-from Interface.Implements import objectImplements
+from Interface.Implements import implements
 
 from Exceptions import StopValidation, ValidationError
 import ErrorNames
 
+import IField
+from _bootstrapFields import Field, Container, Iteratable, Orderable, Sized
+from _bootstrapFields import Enumeratable, Text, Bool, Int
+from FieldProperty import FieldProperty
+
+# Fix up bootstrap field types
+Field.title       = FieldProperty(IField.IField['title'])
+Field.description = FieldProperty(IField.IField['description'])
+Field.required    = FieldProperty(IField.IField['required'])
+Field.readonly    = FieldProperty(IField.IField['readonly'])
+# Default is already taken care of
+implements(Field, IField.IField)
+
+implements(Container, IField.IContainer)
+implements(Iteratable, IField.IIteratable)
+implements(Orderable, IField.IOrderable)
+
+Sized.min_length = FieldProperty(IField.ISized['min_length'])
+Sized.max_length = FieldProperty(IField.ISized['max_length'])
+implements(Sized, IField.ISized)
+
+implements(Enumeratable, IField.IEnumeratable)
+
+implements(Text, IField.IText)
+implements(Bool, IField.IBool)
+implements(Int, IField.IInt)
+            
+class Bytes(Sized, Enumeratable):
+    __doc__ = IField.IBytes.__doc__
+    __implements__ = IField.IBytes
+    
+    _type = str
+
+class Float(Enumeratable, Orderable):
+    __doc__ = IField.IFloat.__doc__
+    __implements__ = IField.IFloat
+    _type = float
+
+def _validate_sequence(value_types, value, errors=None):
+    if errors is None:
+        errors = []
+        
+    if value_types is None:
+        return errors
+
+    for item in value:
+
+        error = None
+
+        for t in value_types:
+            try:
+                t.validate(item)
+            except ValidationError, error:
+                pass
+            else:
+                # We validated, so clear error (if any) and done with
+                # this value
+                error = None
+                break
 
-class Field(Attribute):
-    # we don't implement the same interface Attribute
-    __implements__ = ()
-    type = None
-    default = None
-    setter = None
-    getter = None
-    required = 0
-    allowed_values = []
+        if error is not None:
+            errors.append(error)
+
+    return errors
     
-    def __init__(self, **kw):
-        """Pass in field values as keyword parameters."""
-        for key, value in kw.items():
-            setattr(self, key, value)
-        # __name__ to '', so interface should initialize this with
-        # name of attribute
-        super(Field, self).__init__('')
 
-    def validate(self, value):
+class Sequence(Sized, Iteratable):
+    __doc__ = IField.ISequence.__doc__
+    value_types = FieldProperty(IField.ISequence['value_types'])
+
+    def __init__(self, value_types=None, **kw):
+        super(Sequence, self).__init__(**kw)
+        self.value_types = value_types
+
+    def _validate(self, value):
+        super(Sequence, self)._validate(value)
         try:
-            self.validator(self).validate(value)
-        except StopValidation:
-            pass
-
-class Bytes(Field):
-    """A field representing a Str."""
-    type = str
-    min_length = None
-    max_length = None
-
-class Text(Field):
-    """A field representing a Str."""
-    type = unicode
-    min_length = None
-    max_length = None
-
-class Bool(Field):
-    """A field representing a Bool."""
-    # XXX Do we really expect this to be an int?
-    # The BoolTest only work if Bool corresponds to Python's int.
-    type = int
-
-class Int(Field):
-    """A field representing a Integer."""
-    type = int
-    min = max = None
-
-class Float(Field):
-    """A field representing a Floating Point."""
-    type = float, int
-    min = max = None
-    decimals = None
+            errors = _validate_sequence(self.value_types, value)
+            if errors:
+                raise ValidationError(ErrorNames.WrongContainedType, errors)
+                
+        finally:
+            errors = None
 
-class Tuple(Field):
+class Tuple(Sequence):
     """A field representing a Tuple."""
-    type = tuple
-    value_types = None
-    min_values = max_values = None
+    __implements__ = IField.ITuple
+    _type = tuple
 
-class List(Field):
+class List(Sequence):
     """A field representing a List."""
-    type = list
-    value_types = None
-    min_values = max_values = None
+    __implements__ = IField.IList
+    _type = list
 
-class Dict(Field):
+class Dict(Sized, Iteratable):
     """A field representing a Dict."""
-    type = dict
-    min_values = max_values = None
-    key_types = value_types = None
+    __implements__ = IField.IDict
+    _type = dict
+    key_types   = FieldProperty(IField.IDict['key_types'])
+    value_types = FieldProperty(IField.IDict['value_types'])
+
+    def __init__(self, key_types=None, value_types=None, **kw):
+        super(Dict, self).__init__(**kw)
+        self.key_types = key_types
+        self.value_types = value_types
+
+    def _validate(self, value):
+        super(Dict, self)._validate(value)
+        errors = []
+        try:
+            if self.value_types:
+                errors = _validate_sequence(self.value_types, value.values(),
+                                            errors)
+            errors = _validate_sequence(self.key_types, value, errors)
+
+            if errors:
+                raise ValidationError(ErrorNames.WrongContainedType, errors)
+                
+        finally:
+            errors = None


=== Zope3/lib/python/Zope/Schema/_Schema.py 1.2 => 1.3 ===
--- Zope3/lib/python/Zope/Schema/_Schema.py:1.2	Sat Sep  7 12:18:51 2002
+++ Zope3/lib/python/Zope/Schema/_Schema.py	Wed Sep 11 18:06:41 2002
@@ -15,9 +15,7 @@
 $Id$
 """
 from Interface import Interface
-import Validator
-from Zope.Schema.Exceptions import \
-     StopValidation, ValidationError, ValidationErrorsAll
+from Zope.Schema.Exceptions import ValidationError, ValidationErrorsAll
     
 def getFields(schema):
     """Get all fields on a schema.
@@ -60,57 +58,4 @@
                 errors.append((name, e))
     if errors:
         raise ValidationErrorsAll, errors
-
-# Now we can create the interesting interfaces and wire them up:
-def wire():
-    from Interface.Implements import implements
-
-    from IField import IField
-    from _Field import Field
-    implements(Field, IField, 0)
-    Field.validator = Validator.RequiredValidator
-
-    from IField import IBool
-    from _Field import Bool
-    implements(Bool, IBool, 0)
-    Bool.validator = Validator.BoolValidator
-
-    from IField import IBytes
-    from _Field import Bytes
-    implements(Bytes, IBytes, 0)
-    Bytes.validator = Validator.StrValidator
-
-    from IField import IText
-    from _Field import Text
-    implements(Text, IText, 0)
-    Text.validator = Validator.StrValidator
-
-    from IField import IInt
-    from _Field import Int
-    implements(Int, IInt, 0)
-    Int.validator = Validator.IntValidator
-
-    from IField import IFloat
-    from _Field import Float
-    implements(Float, IFloat, 0)
-    Float.validator = Validator.FloatValidator
-
-    from IField import ITuple
-    from _Field import Tuple
-    implements(Tuple, ITuple, 0)
-    Tuple.validator = Validator.TupleValidator
-
-    from IField import IList
-    from _Field import List
-    implements(List, IList, 0)
-    List.validator = Validator.ListValidator
-
-    from IField import IDict
-    from _Field import Dict
-    implements(Dict, IDict, 0)
-    Dict.validator = Validator.DictValidator
-
-
-wire()
-del wire
 

=== Removed File Zope3/lib/python/Zope/Schema/IValidator.py ===

=== Removed File Zope3/lib/python/Zope/Schema/Validator.py ===