[Zope3-checkins] CVS: Zope3/src/zope/schema - _field.py:1.33

Stephan Richter srichter at cosmos.phy.tufts.edu
Sat Apr 24 19:20:46 EDT 2004


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

Modified Files:
	_field.py 
Log Message:


Added Choice field.



Upgraded Sequence field to handle Choice fields as value_type values better.



Added Set field.



Remove Enumerated Field.




=== Zope3/src/zope/schema/_field.py 1.32 => 1.33 ===
--- Zope3/src/zope/schema/_field.py:1.32	Sun Apr 11 06:35:04 2004
+++ Zope3/src/zope/schema/_field.py	Sat Apr 24 19:20:46 2004
@@ -16,38 +16,39 @@
 
 $Id$
 """
-__metaclass__ = type
-
 import warnings
 import re
+from datetime import datetime, date
 
-from zope.interface import classImplements, implements
-from zope.interface.interfaces import IInterface
-from zope.interface.interfaces import IMethod
+from zope.interface import classImplements, implements, directlyProvides
+from zope.interface.interfaces import IInterface, IMethod
 
 from zope.schema.interfaces import IField
 from zope.schema.interfaces import IMinMaxLen, IText, ITextLine
 from zope.schema.interfaces import ISourceText
 from zope.schema.interfaces import IInterfaceField
 from zope.schema.interfaces import IBytes, IASCII, IBytesLine
-from zope.schema.interfaces import IBool, IInt, IFloat
-from zope.schema.interfaces import IDatetime, ISequence, ITuple, IList, IDict
-from zope.schema.interfaces import IPassword, IObject, IDate, IEnumeratedDate
-from zope.schema.interfaces import IEnumeratedDatetime, IEnumeratedTextLine
-from zope.schema.interfaces import IEnumeratedInt, IEnumeratedFloat
+from zope.schema.interfaces import IBool, IInt, IFloat, IDatetime
+from zope.schema.interfaces import IChoice, IChoiceSequence
+from zope.schema.interfaces import ISequence, ITuple, IList, ISet, IDict
+from zope.schema.interfaces import IPassword, IObject, IDate
 from zope.schema.interfaces import IURI, IId, IFromUnicode
+from zope.schema.interfaces import IVocabulary
 
 from zope.schema.interfaces import ValidationError, InvalidValue
-from zope.schema.interfaces import WrongType, WrongContainedType
+from zope.schema.interfaces import WrongType, WrongContainedType, NotUnique
 from zope.schema.interfaces import SchemaNotProvided, SchemaNotFullyImplemented
 from zope.schema.interfaces import InvalidURI, InvalidId, InvalidDottedName
+from zope.schema.interfaces import ConstraintNotSatisfied
+from zope.schema.interfaces import Unbound
 
 from zope.schema._bootstrapfields import Field, Container, Iterable, Orderable
-from zope.schema._bootstrapfields import MinMaxLen, Enumerated
+from zope.schema._bootstrapfields import MinMaxLen
 from zope.schema._bootstrapfields import Text, TextLine, Bool, Int, Password
-from zope.schema._bootstrapfields import EnumeratedTextLine, EnumeratedInt
+from zope.schema._bootstrapfields import MinMaxLen, ValidatedProperty
 from zope.schema.fieldproperty import FieldProperty
-from datetime import datetime, date
+from zope.schema.vocabulary import getVocabularyRegistry
+from zope.schema.vocabulary import SimpleTerm, SimpleVocabulary
 
 # Fix up bootstrap field types
 Field.title       = FieldProperty(IField['title'])
@@ -65,8 +66,6 @@
 classImplements(Password, IPassword)
 classImplements(Bool, IBool)
 classImplements(Int, IInt)
-classImplements(EnumeratedInt, IEnumeratedInt)
-classImplements(EnumeratedTextLine, IEnumeratedTextLine)
 
 class SourceText(Text):
     __doc__ = ISourceText.__doc__
@@ -157,10 +156,6 @@
         self.validate(v)
         return v
 
-class EnumeratedFloat(Enumerated, Float):
-    __doc__ = IEnumeratedFloat.__doc__
-    implements(IEnumeratedFloat)
-
 class Datetime(Orderable, Field):
     __doc__ = IDatetime.__doc__
     implements(IDatetime)
@@ -169,18 +164,87 @@
     def __init__(self, *args, **kw):
         super(Datetime, self).__init__(*args, **kw)
 
-class EnumeratedDatetime(Enumerated, Datetime):
-    __doc__ = IEnumeratedDatetime.__doc__
-    implements(IEnumeratedDatetime)
-
 class Date(Orderable, Field):
     __doc__ = IDate.__doc__
     implements(IDate)
     _type = date
 
-class EnumeratedDate(Enumerated, Date):
-    __doc__ = IEnumeratedDate.__doc__
-    implements(IEnumeratedDate)
+class Choice(Field):
+    """Choice fields can have a value found in a constant or dynamic set of
+    values given by the field definition.
+    """
+    implements(IChoice)
+
+    def __init__(self, values=None, vocabulary=None, **kw):
+        """Initialize object."""
+        assert not (values is None and vocabulary is None), \
+               "You must specify either values or vocabulary."
+        assert values is None or vocabulary is None, \
+               "You cannot specify both, values and vocabulary."
+        
+        self.vocabulary = None
+        self.vocabularyName = None
+
+        if values is not None:
+            terms = [SimpleTerm(value) for value in values]
+            self.vocabulary = SimpleVocabulary(terms)
+        elif isinstance(vocabulary, (unicode, str)):
+            self.vocabularyName = vocabulary
+        else:
+            assert IVocabulary.providedBy(vocabulary)
+            self.vocabulary = vocabulary
+
+        # Before a default value is checked, it is validated. However, a
+        # vocabulary is usually not complete when these fields are
+        # initialized. Therefore signalize to the validation method to ignore
+        # default value checks during initialization.
+        self._init_field = True
+        super(Choice, self).__init__(**kw)
+        self._init_field = False
+
+    def bind(self, object):
+        """See zope.schema._bootstrapinterfaces.IField."""
+        clone = super(Choice, self).bind(object)
+        # get registered vocabulary if needed:
+        if clone.vocabulary is None and self.vocabularyName is not None:
+            vr = getVocabularyRegistry()
+            clone.vocabulary = vr.get(object, self.vocabularyName)
+        return clone
+
+    def fromUnicode(self, str):
+        """
+        >>> from vocabulary import SimpleVocabulary
+        >>> t = Choice(
+        ...     vocabulary=SimpleVocabulary.fromValues([u'foo',u'bar']))
+        >>> t.fromUnicode(u"baz")
+        Traceback (most recent call last):
+        ...
+        ConstraintNotSatisfied: baz
+        >>> t.fromUnicode(u"foo")
+        u'foo'
+        """
+        self.validate(str)
+        return str
+        
+    def _validate(self, value):
+        # Pass all validations during initialization
+        if self._init_field:
+            return
+
+        super(Choice, self)._validate(value)
+
+        vocabulary = self.vocabulary
+        
+        if vocabulary is None:
+            vr = getVocabularyRegistry()
+            try:
+                vocabulary = vr.get(None, self.vocabularyName)
+            except VocabularyRegistryError:
+                raise ValueError("can't validate value without vocabulary")
+
+        if value not in vocabulary:
+            raise ConstraintNotSatisfied, value
+
 
 class InterfaceField(Field):
     __doc__ = IInterfaceField.__doc__
@@ -215,18 +279,39 @@
 
     return errors
 
+def _validate_uniqueness(value):
+    temp_values = []
+    for item in value:
+        if item in temp_values:
+            raise NotUnique, item
+
+        temp_values.append(item)
+
 
 class Sequence(MinMaxLen, Iterable, Field):
     __doc__ = ISequence.__doc__
     implements(ISequence)
     value_type = None
 
-    def __init__(self, value_type=None, **kw):
+    def __init__(self, value_type=None, unique=False, **kw):
         super(Sequence, self).__init__(**kw)
         # whine if value_type is not a field
         if value_type is not None and not IField.providedBy(value_type):
             raise ValueError, "'value_type' must be field instance."
         self.value_type = value_type
+        # When a choice is used for the sequence, signalize this through an
+        # interface, so that special views can be provided. 
+        if IChoice.providedBy(value_type):
+            directlyProvides(self, IChoiceSequence)
+        self.unique = unique
+
+    def bind(self, object):
+        """See zope.schema._bootstrapinterfaces.IField."""
+        clone = super(Sequence, self).bind(object)
+        # We need to bin the choice as well, so the vocabulary is generated.
+        if IChoiceSequence.providedBy(self):
+           clone.value_type = clone.value_type.bind(object) 
+        return clone
 
     def _validate(self, value):
         super(Sequence, self)._validate(value)
@@ -234,16 +319,22 @@
         if errors:
             raise WrongContainedType, errors
 
+        if self.unique:
+            _validate_uniqueness(value)
+
 class Tuple(Sequence):
     """A field representing a Tuple."""
     implements(ITuple)
     _type = tuple
 
-
 class List(Sequence):
     """A field representing a List."""
     implements(IList)
     _type = list
+
+class Set(Sequence):
+    """A field representing a set."""
+    implements(ISet)
 
 
 def _validate_fields(schema, value, errors=None):




More information about the Zope3-Checkins mailing list