[Checkins] SVN: zope.schema/trunk/ Avoid maximum recursion when validating Object field that points to cycles
Godefroid Chapelle
gotcha at bubblenet.be
Fri Apr 30 09:36:09 EDT 2010
Log message for revision 111614:
Avoid maximum recursion when validating Object field that points to cycles
Changed:
U zope.schema/trunk/CHANGES.txt
U zope.schema/trunk/src/zope/schema/_field.py
U zope.schema/trunk/src/zope/schema/tests/test_objectfield.py
-=-
Modified: zope.schema/trunk/CHANGES.txt
===================================================================
--- zope.schema/trunk/CHANGES.txt 2010-04-30 13:27:49 UTC (rev 111613)
+++ zope.schema/trunk/CHANGES.txt 2010-04-30 13:36:09 UTC (rev 111614)
@@ -5,6 +5,8 @@
3.6.2 (unreleased)
------------------
+- Avoid maximum recursion when validating Object field that points to cycles
+
- Made the dependency on ``zope.i18nmessageid`` optional.
3.6.1 (2010-01-05)
Modified: zope.schema/trunk/src/zope/schema/_field.py
===================================================================
--- zope.schema/trunk/src/zope/schema/_field.py 2010-04-30 13:27:49 UTC (rev 111613)
+++ zope.schema/trunk/src/zope/schema/_field.py 2010-04-30 13:36:09 UTC (rev 111614)
@@ -168,7 +168,7 @@
>>> f.fromUnicode("1.25")
1.25
>>> f.fromUnicode("1.25.6") #doctest: +IGNORE_EXCEPTION_DETAIL
- Traceback (most recent call last):
+ Traceback (most recent call last):
...
ValueError: invalid literal for float(): 1.25.6
"""
@@ -457,6 +457,9 @@
def _validate_fields(schema, value, errors=None):
if errors is None:
errors = []
+ if hasattr(value, '__validating_schema'):
+ return errors
+ value.__validating_schema = True
for name in schema.names(all=True):
if not IMethod.providedBy(schema[name]):
try:
@@ -469,6 +472,7 @@
except AttributeError, error:
# property for the given name is not implemented
errors.append(SchemaNotFullyImplemented(error))
+ delattr(value, '__validating_schema')
return errors
Modified: zope.schema/trunk/src/zope/schema/tests/test_objectfield.py
===================================================================
--- zope.schema/trunk/src/zope/schema/tests/test_objectfield.py 2010-04-30 13:27:49 UTC (rev 111613)
+++ zope.schema/trunk/src/zope/schema/tests/test_objectfield.py 2010-04-30 13:36:09 UTC (rev 111614)
@@ -1,3 +1,4 @@
+from zope.schema import List
##############################################################################
#
# Copyright (c) 2001, 2002 Zope Foundation and Contributors.
@@ -49,6 +50,55 @@
attribute = Attribute("Test attribute, an attribute can't be validated.")
+class ICyclic(Interface):
+ """A test schema"""
+
+ baz = Object(
+ schema=Interface,
+ title=_(u"Baz"),
+ description=_(u"Baz description"),
+ required=False,
+ )
+
+ baz_list = List(
+ value_type=Object(schema=Interface),
+ title=_(u"Baz List"),
+ description=_(u"Baz description"),
+ required=False,
+ )
+
+
+class IBaz(Interface):
+ """A test schema"""
+
+ cyclic = Object(
+ schema=ICyclic,
+ title=_(u"Cyclic"),
+ description=_(u"Cyclic description"),
+ required=False,
+ )
+
+ICyclic['baz'].schema = IBaz
+ICyclic['baz_list'].value_type.schema = IBaz
+
+
+class Cyclic(object):
+
+ implements(ICyclic)
+
+ def __init__(self, baz, baz_list):
+ self.baz = baz
+ self.baz_list = baz_list
+
+
+class Baz(object):
+
+ implements(IBaz)
+
+ def __init__(self, cyclic):
+ self.cyclic = cyclic
+
+
class TestClass(object):
implements(ITestSchema)
@@ -103,6 +153,7 @@
class ObjectTest(CleanUp, FieldTestBase):
"""Test the Object Field."""
+
def getErrors(self, f, *args, **kw):
try:
f(*args, **kw)
@@ -136,7 +187,7 @@
def test_init(self):
for schema in self.validSchemas():
- field = Object(schema=schema)
+ Object(schema=schema)
for schema in self.invalidSchemas():
self.assertRaises(ValidationError, Object, schema=schema)
self.assertRaises(WrongType, Object, schema=schema)
@@ -189,9 +240,11 @@
__name__='object_field')
data = self.makeTestData()
events = []
+
def register_event(event):
events.append(event)
zope.event.subscribers.append(register_event)
+
class Dummy(object):
pass
context = Dummy()
@@ -203,7 +256,40 @@
self.assertEquals('object_field', event.name)
self.assertEquals(context, event.context)
+ # cycles
+ def test_with_cycles_validate(self):
+ field = self.makeTestObject(schema=ICyclic)
+ baz1 = Baz(None)
+ baz2 = Baz(None)
+ cyclic = Cyclic(baz1, [baz1, baz2])
+ baz1.cyclic = cyclic
+ baz2.cyclic = cyclic
+ field.validate(cyclic)
+
+ def test_with_cycles_object_not_valid(self):
+ field = self.makeTestObject(schema=ICyclic)
+ data = self.makeTestData()
+ baz1 = Baz(None)
+ baz2 = Baz(None)
+ baz3 = Baz(data)
+ cyclic = Cyclic(baz3, [baz1, baz2])
+ baz1.cyclic = cyclic
+ baz2.cyclic = cyclic
+ self.assertRaises(WrongContainedType, field.validate, cyclic)
+
+ def test_with_cycles_collection_not_valid(self):
+ field = self.makeTestObject(schema=ICyclic)
+ data = self.makeTestData()
+ baz1 = Baz(None)
+ baz2 = Baz(None)
+ baz3 = Baz(data)
+ cyclic = Cyclic(baz1, [baz2, baz3])
+ baz1.cyclic = cyclic
+ baz2.cyclic = cyclic
+ self.assertRaises(WrongContainedType, field.validate, cyclic)
+
+
def test_suite():
suite = TestSuite()
suite.addTest(makeSuite(ObjectTest))
More information about the checkins
mailing list