1############################################################################## 2# 3# Copyright (c) 2001, 2002 Zope Foundation and Contributors. 4# All Rights Reserved. 5# 6# This software is subject to the provisions of the Zope Public License, 7# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. 8# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED 9# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 10# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS 11# FOR A PARTICULAR PURPOSE. 12# 13############################################################################## 14"""Field Properties tests 15""" 16 17import unittest 18 19 20class _Base(unittest.TestCase): 21 22 def _makeOne(self, field=None, name=None): 23 from zope.schema import Text 24 if field is None: 25 field = Text(__name__='testing') 26 if name is None: 27 return self._getTargetClass()(field) 28 return self._getTargetClass()(field, name) 29 30 31class _Integration(object): 32 33 def _makeImplementer(self): 34 schema = _getSchema() 35 class _Implementer(object): 36 title = self._makeOne(schema['title']) 37 weight = self._makeOne(schema['weight']) 38 code = self._makeOne(schema['code']) 39 date = self._makeOne(schema['date']) 40 return _Implementer() 41 42 def test_basic(self): 43 from zope.schema._compat import b 44 from zope.schema._compat import u 45 from zope.schema.interfaces import ValidationError 46 c = self._makeImplementer() 47 self.assertEqual(c.title, u('say something')) 48 self.assertEqual(c.weight, None) 49 self.assertEqual(c.code, b('xxxxxx')) 50 self.assertRaises(ValidationError, setattr, c, 'title', b('foo')) 51 self.assertRaises(ValidationError, setattr, c, 'weight', b('foo')) 52 self.assertRaises(ValidationError, setattr, c, 'weight', -1.0) 53 self.assertRaises(ValidationError, setattr, c, 'weight', 2) 54 self.assertRaises(ValidationError, setattr, c, 'code', -1) 55 self.assertRaises(ValidationError, setattr, c, 'code', b('xxxx')) 56 self.assertRaises(ValidationError, setattr, c, 'code', u('xxxxxx')) 57 58 c.title = u('c is good') 59 c.weight = 10.0 60 c.code = b('abcdef') 61 62 self.assertEqual(c.title, u('c is good')) 63 self.assertEqual(c.weight, 10) 64 self.assertEqual(c.code, b('abcdef')) 65 66 def test_readonly(self): 67 c = self._makeImplementer() 68 # The date should be only settable once 69 c.date = 0.0 70 # Setting the value a second time should fail. 71 self.assertRaises(ValueError, setattr, c, 'date', 1.0) 72 73 74class FieldPropertyTests(_Base, _Integration): 75 76 def _getTargetClass(self): 77 from zope.schema.fieldproperty import FieldProperty 78 return FieldProperty 79 80 def test_ctor_defaults(self): 81 from zope.schema import Text 82 field = Text(__name__='testing') 83 cname = self._getTargetClass().__name__ 84 prop = self._makeOne(field) 85 self.assertTrue(getattr(prop, '_%s__field' % cname) is field) 86 self.assertEqual(getattr(prop, '_%s__name' % cname), 'testing') 87 self.assertEqual(prop.__name__, 'testing') 88 self.assertEqual(prop.description, field.description) 89 self.assertEqual(prop.default, field.default) 90 self.assertEqual(prop.readonly, field.readonly) 91 self.assertEqual(prop.required, field.required) 92 93 def test_ctor_explicit(self): 94 from zope.schema import Text 95 from zope.schema._compat import u 96 field = Text(__name__='testing', 97 description=u('DESCRIPTION'), 98 default=u('DEFAULT'), 99 readonly=True, 100 required=True, 101 ) 102 cname = self._getTargetClass().__name__ 103 prop = self._makeOne(field, name='override') 104 self.assertTrue(getattr(prop, '_%s__field' % cname) is field) 105 self.assertEqual(getattr(prop, '_%s__name' % cname), 'override') 106 self.assertEqual(prop.description, field.description) 107 self.assertEqual(prop.default, field.default) 108 self.assertEqual(prop.readonly, field.readonly) 109 self.assertEqual(prop.required, field.required) 110 111 def test___get___from_class(self): 112 prop = self._makeOne() 113 class Foo(object): 114 testing = prop 115 self.assertTrue(Foo.testing is prop) 116 117 def test___get___from_instance_pseudo_field_wo_default(self): 118 class _Faux(object): 119 def bind(self, other): 120 return self 121 prop = self._makeOne(_Faux(), 'nonesuch') 122 class Foo(object): 123 testing = prop 124 foo = Foo() 125 self.assertRaises(AttributeError, getattr, foo, 'testing') 126 127 def test___get___from_instance_miss_uses_field_default(self): 128 prop = self._makeOne() 129 class Foo(object): 130 testing = prop 131 foo = Foo() 132 self.assertEqual(foo.testing, None) 133 134 def test___get___from_instance_hit(self): 135 prop = self._makeOne(name='other') 136 class Foo(object): 137 testing = prop 138 foo = Foo() 139 foo.other = '123' 140 self.assertEqual(foo.testing, '123') 141 142 def test___get___from_instance_hit_after_bind(self): 143 class _Faux(object): 144 default = '456' 145 def bind(self, other): 146 return self 147 prop = self._makeOne(_Faux(), 'testing') 148 class Foo(object): 149 testing = prop 150 foo = Foo() 151 self.assertEqual(foo.testing, '456') 152 153 def test___set___not_readonly(self): 154 class _Faux(object): 155 readonly = False 156 default = '456' 157 def bind(self, other): 158 return self 159 faux = _Faux() 160 _validated = [] 161 faux.validate = _validated.append 162 prop = self._makeOne(faux, 'testing') 163 class Foo(object): 164 testing = prop 165 foo = Foo() 166 foo.testing = '123' 167 self.assertEqual(foo.__dict__['testing'], '123') 168 169 def test___set___w_readonly_not_already_set(self): 170 class _Faux(object): 171 readonly = True 172 default = '456' 173 def bind(self, other): 174 return self 175 faux = _Faux() 176 _validated = [] 177 faux.validate = _validated.append 178 prop = self._makeOne(faux, 'testing') 179 class Foo(object): 180 testing = prop 181 foo = Foo() 182 foo.testing = '123' 183 self.assertEqual(foo.__dict__['testing'], '123') 184 self.assertEqual(_validated, ['123']) 185 186 def test___set___w_readonly_and_already_set(self): 187 class _Faux(object): 188 readonly = True 189 default = '456' 190 def bind(self, other): 191 return self 192 faux = _Faux() 193 _validated = [] 194 faux.validate = _validated.append 195 prop = self._makeOne(faux, 'testing') 196 class Foo(object): 197 testing = prop 198 foo = Foo() 199 foo.__dict__['testing'] = '789' 200 self.assertRaises(ValueError, setattr, foo, 'testing', '123') 201 self.assertEqual(_validated, ['123']) 202 203 204class FieldPropertyStoredThroughFieldTests(_Base, _Integration): 205 206 def _getTargetClass(self): 207 from zope.schema.fieldproperty import FieldPropertyStoredThroughField 208 return FieldPropertyStoredThroughField 209 210 def test_ctor_defaults(self): 211 from zope.schema import Text 212 field = Text(__name__='testing') 213 cname = self._getTargetClass().__name__ 214 prop = self._makeOne(field) 215 self.assertTrue(isinstance(prop.field, field.__class__)) 216 self.assertFalse(prop.field is field) 217 self.assertEqual(prop.field.__name__, '__st_testing_st') 218 self.assertEqual(prop.__name__, '__st_testing_st') 219 self.assertEqual(getattr(prop, '_%s__name' % cname), 'testing') 220 self.assertEqual(prop.description, field.description) 221 self.assertEqual(prop.default, field.default) 222 self.assertEqual(prop.readonly, field.readonly) 223 self.assertEqual(prop.required, field.required) 224 225 def test_ctor_explicit(self): 226 from zope.schema import Text 227 from zope.schema._compat import u 228 field = Text(__name__='testing', 229 description=u('DESCRIPTION'), 230 default=u('DEFAULT'), 231 readonly=True, 232 required=True, 233 ) 234 cname = self._getTargetClass().__name__ 235 prop = self._makeOne(field, name='override') 236 self.assertTrue(isinstance(prop.field, field.__class__)) 237 self.assertFalse(prop.field is field) 238 self.assertEqual(prop.field.__name__, '__st_testing_st') 239 self.assertEqual(prop.__name__, '__st_testing_st') 240 self.assertEqual(getattr(prop, '_%s__name' % cname), 'override') 241 self.assertEqual(prop.description, field.description) 242 self.assertEqual(prop.default, field.default) 243 self.assertEqual(prop.readonly, field.readonly) 244 self.assertEqual(prop.required, field.required) 245 246 def test_setValue(self): 247 from zope.schema import Text 248 class Foo(object): 249 pass 250 foo = Foo() 251 prop = self._makeOne() 252 field = Text(__name__='testing') 253 prop.setValue(foo, field, '123') 254 self.assertEqual(foo.testing, '123') 255 256 def test_getValue_miss(self): 257 from zope.schema import Text 258 from zope.schema.fieldproperty import _marker 259 class Foo(object): 260 pass 261 foo = Foo() 262 prop = self._makeOne() 263 field = Text(__name__='testing') 264 value = prop.getValue(foo, field) 265 self.assertTrue(value is _marker) 266 267 def test_getValue_hit(self): 268 from zope.schema import Text 269 class Foo(object): 270 pass 271 foo = Foo() 272 foo.testing = '123' 273 prop = self._makeOne() 274 field = Text(__name__='testing') 275 value = prop.getValue(foo, field) 276 self.assertEqual(value, '123') 277 278 def test_queryValue_miss(self): 279 from zope.schema import Text 280 class Foo(object): 281 pass 282 foo = Foo() 283 prop = self._makeOne() 284 field = Text(__name__='testing') 285 default = object() 286 value = prop.queryValue(foo, field, default) 287 self.assertTrue(value is default) 288 289 def test_queryValue_hit(self): 290 from zope.schema import Text 291 class Foo(object): 292 pass 293 foo = Foo() 294 foo.testing = '123' 295 prop = self._makeOne() 296 field = Text(__name__='testing') 297 default = object() 298 value = prop.queryValue(foo, field, default) 299 self.assertEqual(value, '123') 300 301 def test___get___from_class(self): 302 prop = self._makeOne() 303 class Foo(object): 304 testing = prop 305 self.assertTrue(Foo.testing is prop) 306 307 def test___get___from_instance_pseudo_field_wo_default(self): 308 class _Faux(object): 309 __name__ = 'Faux' 310 def bind(self, other): 311 return self 312 def query(self, inst, default): 313 return default 314 prop = self._makeOne(_Faux(), 'nonesuch') 315 class Foo(object): 316 testing = prop 317 foo = Foo() 318 self.assertRaises(AttributeError, getattr, foo, 'testing') 319 320 def test___get___from_instance_miss_uses_field_default(self): 321 prop = self._makeOne() 322 class Foo(object): 323 testing = prop 324 foo = Foo() 325 self.assertEqual(foo.testing, None) 326 327 def test___get___from_instance_hit(self): 328 from zope.schema import Text 329 field = Text(__name__='testing') 330 prop = self._makeOne(field, name='other') 331 class Foo(object): 332 testing = prop 333 foo = Foo() 334 foo.__dict__['__st_testing_st'] = '456' 335 foo.other = '123' 336 self.assertEqual(foo.testing, '456') 337 338 def test___set___not_readonly(self): 339 class _Faux(object): 340 __name__ = 'Faux' 341 readonly = False 342 default = '456' 343 def bind(self, other): 344 return self 345 def set(self, inst, value): 346 setattr(inst, 'faux', value) 347 faux = _Faux() 348 _validated = [] 349 faux.validate = _validated.append 350 prop = self._makeOne(faux, 'testing') 351 class Foo(object): 352 testing = prop 353 foo = Foo() 354 foo.testing = '123' 355 self.assertEqual(foo.__dict__['faux'], '123') 356 self.assertEqual(_validated, ['123']) 357 358 def test___set___w_readonly_not_already_set(self): 359 class _Faux(object): 360 __name__ = 'Faux' 361 readonly = True 362 default = '456' 363 def bind(self, other): 364 return self 365 def query(self, inst, default): 366 return default 367 def set(self, inst, value): 368 if self.readonly: 369 raise ValueError 370 setattr(inst, 'faux', value) 371 faux = _Faux() 372 _validated = [] 373 faux.validate = _validated.append 374 prop = self._makeOne(faux, 'testing') 375 class Foo(object): 376 testing = prop 377 foo = Foo() 378 foo.testing = '123' 379 self.assertEqual(foo.__dict__['faux'], '123') 380 self.assertEqual(_validated, ['123']) 381 382 def test___set___w_readonly_and_already_set(self): 383 class _Faux(object): 384 __name__ = 'Faux' 385 readonly = True 386 default = '456' 387 def bind(self, other): 388 return self 389 def query(self, inst, default): 390 return '789' 391 faux = _Faux() 392 _validated = [] 393 faux.validate = _validated.append 394 prop = self._makeOne(faux, 'testing') 395 class Foo(object): 396 testing = prop 397 foo = Foo() 398 foo.__dict__['testing'] = '789' 399 self.assertRaises(ValueError, setattr, foo, 'testing', '123') 400 401 402def _getSchema(): 403 from zope.interface import Interface 404 from zope.schema import Bytes 405 from zope.schema import Float 406 from zope.schema import Text 407 from zope.schema._compat import b 408 from zope.schema._compat import u 409 410 class Schema(Interface): 411 title = Text(description=u("Short summary"), 412 default=u('say something')) 413 weight = Float(min=0.0) 414 code = Bytes(min_length=6, max_length=6, default=b('xxxxxx')) 415 date = Float(title=u('Date'), readonly=True) 416 417 return Schema 418 419 420def test_suite(): 421 return unittest.TestSuite(( 422 unittest.makeSuite(FieldPropertyTests), 423 unittest.makeSuite(FieldPropertyStoredThroughFieldTests), 424 )) 425