[Checkins] SVN: zope.schema/trunk/src/zope/schema/ Add FieldProperty class that uses Field.get and Field.set methods instead of storing directly on the instance __dict__
Jean-Francois Roche
jfroche at jfroche.be
Tue Nov 24 09:42:21 EST 2009
Log message for revision 105992:
Add FieldProperty class that uses Field.get and Field.set methods instead of storing directly on the instance __dict__
Changed:
U zope.schema/trunk/src/zope/schema/fieldproperty.py
U zope.schema/trunk/src/zope/schema/tests/test_fieldproperty.py
-=-
Modified: zope.schema/trunk/src/zope/schema/fieldproperty.py
===================================================================
--- zope.schema/trunk/src/zope/schema/fieldproperty.py 2009-11-24 14:31:11 UTC (rev 105991)
+++ zope.schema/trunk/src/zope/schema/fieldproperty.py 2009-11-24 14:42:21 UTC (rev 105992)
@@ -15,8 +15,10 @@
$Id$
"""
+from copy import copy
_marker = object()
+
class FieldProperty(object):
"""Computed attributes based on schema fields
@@ -56,3 +58,52 @@
def __getattr__(self, name):
return getattr(self.__field, name)
+
+
+class FieldPropertyStoredThroughField(object):
+
+ def __init__(self, field, name=None):
+ if name is None:
+ name = field.__name__
+
+ self.__field = copy(field)
+ self.__field.__name__ = "__st_%s_st" % self.__field.__name__
+ self.__name = name
+
+ def setValue(self, inst, field, value):
+ field.set(inst, value)
+
+ def getValue(self, inst, field):
+ return field.query(inst, _marker)
+
+ def queryValue(self, inst, field, default):
+ return field.query(inst, default)
+
+ def __getattr__(self, name):
+ return getattr(self.__field, name)
+
+ def __get__(self, inst, klass):
+ if inst is None:
+ return self
+
+ field = self.__field.bind(inst)
+ value = self.getValue(inst, field)
+ if value is _marker:
+ value = getattr(field, 'default', _marker)
+ if value is _marker:
+ raise AttributeError(self.__name)
+
+ return value
+
+ def __set__(self, inst, value):
+ field = self.__field.bind(inst)
+ field.validate(value)
+ if field.readonly:
+ if self.queryValue(inst, field, _marker) is _marker:
+ field.readonly = False
+ self.setValue(inst, field, value)
+ field.readonly = True
+ return
+ else:
+ raise ValueError(self.__name, 'field is readonly')
+ self.setValue(inst, field, value)
Modified: zope.schema/trunk/src/zope/schema/tests/test_fieldproperty.py
===================================================================
--- zope.schema/trunk/src/zope/schema/tests/test_fieldproperty.py 2009-11-24 14:31:11 UTC (rev 105991)
+++ zope.schema/trunk/src/zope/schema/tests/test_fieldproperty.py 2009-11-24 14:42:21 UTC (rev 105992)
@@ -20,9 +20,11 @@
from zope.interface import Interface
from zope.schema import Float, Text, Bytes
-from zope.schema.fieldproperty import FieldProperty
from zope.schema.interfaces import ValidationError
+from zope.schema.fieldproperty import (FieldProperty,
+ FieldPropertyStoredThroughField)
+
class I(Interface):
title = Text(description=u"Short summary", default=u'say something')
@@ -38,10 +40,12 @@
code = FieldProperty(I['code'])
date = FieldProperty(I['date'])
+
class Test(TestCase):
+ klass = C
def test_basic(self):
- c = C()
+ c = self.klass()
self.assertEqual(c.title, u'say something')
self.assertEqual(c.weight, None)
self.assertEqual(c.code, 'xxxxxx')
@@ -62,17 +66,30 @@
self.assertEqual(c.code, 'abcdef')
def test_readonly(self):
- c = C()
+ c = self.klass()
# The date should be only settable once
c.date = 0.0
# Setting the value a second time should fail.
self.assertRaises(ValueError, setattr, c, 'date', 1.0)
+class D(object):
+
+ title = FieldPropertyStoredThroughField(I['title'])
+ weight = FieldPropertyStoredThroughField(I['weight'])
+ code = FieldPropertyStoredThroughField(I['code'])
+ date = FieldPropertyStoredThroughField(I['date'])
+
+
+class TestStoredThroughField(Test):
+ klass = D
+
+
def test_suite():
return TestSuite((
makeSuite(Test),
+ makeSuite(TestStoredThroughField),
))
-if __name__=='__main__':
+if __name__ == '__main__':
main(defaultTest='test_suite')
More information about the checkins
mailing list