[Checkins] SVN: zope.schema/trunk/ Added helper methods for schema validation: `getValidationErrors` and

Christian Zagrodnick cz at gocept.com
Fri Aug 24 04:47:14 EDT 2007


Log message for revision 79215:
  Added helper methods for schema validation: `getValidationErrors` and
  `getSchemaValidationErrors`.
  
  

Changed:
  U   zope.schema/trunk/CHANGES.txt
  U   zope.schema/trunk/src/zope/schema/__init__.py
  U   zope.schema/trunk/src/zope/schema/_schema.py
  U   zope.schema/trunk/src/zope/schema/tests/test_docs.py
  A   zope.schema/trunk/src/zope/schema/validation.txt

-=-
Modified: zope.schema/trunk/CHANGES.txt
===================================================================
--- zope.schema/trunk/CHANGES.txt	2007-08-24 08:45:51 UTC (rev 79214)
+++ zope.schema/trunk/CHANGES.txt	2007-08-24 08:47:13 UTC (rev 79215)
@@ -2,7 +2,13 @@
 Changes
 =======
 
+3.5a1
+=====
 
+ - Added helper methods for schema validation: `getValidationErrors` and
+   `getSchemaValidationErrors`.
+
+
 3.4.0b1
 =======
 

Modified: zope.schema/trunk/src/zope/schema/__init__.py
===================================================================
--- zope.schema/trunk/src/zope/schema/__init__.py	2007-08-24 08:45:51 UTC (rev 79214)
+++ zope.schema/trunk/src/zope/schema/__init__.py	2007-08-24 08:47:13 UTC (rev 79215)
@@ -24,7 +24,8 @@
 from zope.schema._field import Time, SourceText
 from zope.schema._field import Object, URI, Id, DottedName
 from zope.schema._field import InterfaceField
-from zope.schema._schema import getFields, getFieldsInOrder
-from zope.schema._schema import getFieldNames, getFieldNamesInOrder
+from zope.schema._schema import (
+    getFields, getFieldsInOrder, getFieldNames, getFieldNamesInOrder,
+    getValidationErrors, getSchemaValidationErrors)
 from zope.schema.accessors import accessors
 from zope.schema.interfaces import ValidationError

Modified: zope.schema/trunk/src/zope/schema/_schema.py
===================================================================
--- zope.schema/trunk/src/zope/schema/_schema.py	2007-08-24 08:45:51 UTC (rev 79214)
+++ zope.schema/trunk/src/zope/schema/_schema.py	2007-08-24 08:47:13 UTC (rev 79215)
@@ -16,6 +16,9 @@
 $Id$
 """
 
+import zope.interface.verify
+
+
 def getFieldNames(schema):
     """Return a list of all the Field names in a schema.
     """
@@ -48,3 +51,46 @@
     """Return a list of all the Field names in a schema in schema order.
     """
     return [ name for name, field in getFieldsInOrder(schema) ]
+
+
+def getValidationErrors(schema, object):
+    """Return a list of all validation errors.
+
+    """
+    errors = getSchemaValidationErrors(schema, object)
+    if errors:
+        return errors
+
+    # Only validate invariants if there were no previous errors. Previous
+    # errors could be missing attributes which would most likely make an
+    # invariant raise an AttributeError.
+    invariant_errors = []
+    try:
+        schema.validateInvariants(object, invariant_errors)
+    except zope.interface.exceptions.Invalid:
+        # Just collect errors
+        pass
+    errors = [(None, e) for e in invariant_errors]
+    return errors
+
+
+def getSchemaValidationErrors(schema, object):
+    errors = []
+    for name in schema.names(all=True):
+        if zope.interface.interfaces.IMethod.providedBy(schema[name]):
+            continue
+        attribute = schema[name]
+        if not zope.schema.interfaces.IField.providedBy(attribute):
+            continue
+        try:
+            value = getattr(object, name)
+        except AttributeError, error:
+            # property for the given name is not implemented
+            errors.append((
+                name, zope.schema.interfaces.SchemaNotFullyImplemented(error)))
+        else:
+            try:
+                attribute.bind(object).validate(value)
+            except zope.schema.ValidationError, e:
+                errors.append((name, e))
+    return errors

Modified: zope.schema/trunk/src/zope/schema/tests/test_docs.py
===================================================================
--- zope.schema/trunk/src/zope/schema/tests/test_docs.py	2007-08-24 08:45:51 UTC (rev 79214)
+++ zope.schema/trunk/src/zope/schema/tests/test_docs.py	2007-08-24 08:47:13 UTC (rev 79215)
@@ -13,7 +13,7 @@
 ##############################################################################
 """Tests for the schema package's documentation files
 
-$Id: tests.py 29143 2005-02-14 22:43:16Z srichter $
+$Id$
 """
 import unittest
 from zope.testing import doctest
@@ -23,6 +23,9 @@
         doctest.DocFileSuite('../sources.txt', optionflags=doctest.ELLIPSIS),
         doctest.DocFileSuite('../fields.txt'),
         doctest.DocFileSuite('../README.txt'),
+        doctest.DocFileSuite(
+            '../validation.txt',
+            optionflags=doctest.NORMALIZE_WHITESPACE|doctest.ELLIPSIS),
         ))
 
 if __name__ == '__main__':

Added: zope.schema/trunk/src/zope/schema/validation.txt
===================================================================
--- zope.schema/trunk/src/zope/schema/validation.txt	                        (rev 0)
+++ zope.schema/trunk/src/zope/schema/validation.txt	2007-08-24 08:47:13 UTC (rev 79215)
@@ -0,0 +1,93 @@
+================
+Schema Valiation
+================
+
+
+There are two helper methods to verify schemas and interfaces:
+
+getValidationErrors
+    first validates via the zope.schema field validators. If that succeeds the
+    invariants are checked.
+getSchemaValidationErrors
+    *only* validateds via the zope.schema field validators. The invariants are
+    *not* checked.
+
+
+Create an interface to validate against:
+
+>>> import zope.interface
+>>> import zope.schema
+>>> class ITwoInts(zope.interface.Interface):
+...     a = zope.schema.Int(max=10)
+...     b = zope.schema.Int(min=5)
+...
+...     @zope.interface.invariant
+...     def a_greater_b(obj):
+...         print "Checking if a > b"
+...         if obj.a <= obj.b:
+...             raise zope.interface.Invalid("%s<=%s" % (obj.a, obj.b))
+...     
+
+Create a silly model:
+
+>>> class TwoInts(object):
+...     pass
+
+
+Create an instance of TwoInts but do not set attributes. We get two errors:
+
+>>> ti = TwoInts()
+>>> zope.schema.getValidationErrors(ITwoInts, ti)
+[('a', 'TwoInts' object has no attribute 'a'),
+ ('b', 'TwoInts' object has no attribute 'b')]
+
+The `getSchemaValidationErrors` function returns the same result:
+
+>>> zope.schema.getSchemaValidationErrors(ITwoInts, ti)
+[('a', 'TwoInts' object has no attribute 'a'),
+ ('b', 'TwoInts' object has no attribute 'b')]
+
+Note that see no error from the invariant because the invariants are not
+vaildated if there are other schema errors.
+
+When we set an invalid value for `a` we still get the same error for `b`:
+
+>>> ti.a = 11
+>>> errors = zope.schema.getValidationErrors(ITwoInts, ti)
+>>> errors
+[('a', 11 10),
+ ('b', 'TwoInts' object has no attribute 'b')]
+>>> errors[0][1].doc()
+u'Value is too big'
+
+
+After setting a valid value for `a` there is only the error for the missing `b`
+left:
+
+>>> ti.a = 8
+>>> zope.schema.getValidationErrors(ITwoInts, ti)
+[('b', 'TwoInts' object has no attribute 'b')]
+
+
+After setting valid value for `b` the schema is valid so the invariants are
+checked. As `b>a` the invariant fails:
+
+>>> ti.b = 10
+>>> errors = zope.schema.getValidationErrors(ITwoInts, ti)
+Checking if a > b
+>>> errors
+[(None, <zope.interface.exceptions.Invalid instance at 0x...>)]
+
+
+When using `getSchemaValidationErrors` we do not get an error any more:
+
+>>> zope.schema.getSchemaValidationErrors(ITwoInts, ti)
+[]
+
+
+Set `b=5` so everything is fine:
+
+>>> ti.b = 5
+>>> zope.schema.getValidationErrors(ITwoInts, ti)
+Checking if a > b
+[]


Property changes on: zope.schema/trunk/src/zope/schema/validation.txt
___________________________________________________________________
Name: svn:keywords
   + Id Rev Date
Name: svn:eol-style
   + native



More information about the Checkins mailing list