Add 'readonly' parameter to wsattr

'readonly' parameter added to wsattr. If True value cannot be set from
input data. This is intended for attributes which should be only
exposed to user without possibility of change.

Change-Id: I767a29c5113891f89676c5e78adf018d5e0e4f26
This commit is contained in:
Yuriy Zveryanskyy 2013-12-12 17:23:05 +02:00
parent 9751ccebfa
commit e26d1b608c
4 changed files with 33 additions and 4 deletions

View File

@ -135,8 +135,11 @@ def fromjson(datatype, value):
obj = datatype()
for attrdef in wsme.types.list_attributes(datatype):
if attrdef.name in value:
setattr(obj, attrdef.key,
fromjson(attrdef.datatype, value[attrdef.name]))
val_fromjson = fromjson(attrdef.datatype, value[attrdef.name])
if getattr(attrdef, 'readonly', False):
raise InvalidInput(attrdef.name, val_fromjson,
"Cannot set read only field.")
setattr(obj, attrdef.key, val_fromjson)
elif attrdef.mandatory:
raise InvalidInput(attrdef.name, None,
"Mandatory field missing.")

View File

@ -101,7 +101,11 @@ def fromxml(datatype, element):
for attrdef in wsme.types.list_attributes(datatype):
sub = element.find(attrdef.name)
if sub is not None:
setattr(obj, attrdef.key, fromxml(attrdef.datatype, sub))
val_fromxml = fromxml(attrdef.datatype, sub)
if getattr(attrdef, 'readonly', False):
raise InvalidInput(attrdef.name, val_fromxml,
"Cannot set read only field.")
setattr(obj, attrdef.key, val_fromxml)
elif attrdef.mandatory:
raise InvalidInput(attrdef.name, None,
"Mandatory field missing.")

View File

@ -287,6 +287,25 @@ Value should be one of:"))
headers={'Accept': 'application/json'})
self.assertEqual(res.status_int, 400)
def test_wsattr_readonly(self):
class ComplexType(object):
attr = wsme.types.wsattr(int, readonly=True)
class MyRoot(WSRoot):
@expose(int, body=ComplexType)
@validate(ComplexType)
def clx(self, a):
return a.attr
r = MyRoot(['restjson'])
app = webtest.TestApp(r.wsgiapp())
res = app.post_json('/clx', params={'attr': 1005}, expect_errors=True,
headers={'Accept': 'application/json'})
self.assertIn('Cannot set read only field.',
res.json_body['faultstring'])
self.assertIn('1005', res.json_body['faultstring'])
self.assertEqual(res.status_int, 400)
def test_wsattr_default(self):
class ComplexType(object):
attr = wsme.types.wsattr(wsme.types.Enum(str, 'or', 'and'),

View File

@ -447,7 +447,8 @@ class wsattr(object):
mandatoryvalue = wsattr(int, mandatory=True)
"""
def __init__(self, datatype, mandatory=False, name=None, default=Unset):
def __init__(self, datatype, mandatory=False, name=None, default=Unset,
readonly=False):
#: The attribute name in the parent python class.
#: Set by :func:`inspect_class`
self.key = None # will be set by class inspection
@ -460,6 +461,8 @@ class wsattr(object):
#: Default value. The attribute will return this instead
#: of :data:`Unset` if no value has been set.
self.default = default
#: If True value cannot be set from json/xml input data
self.readonly = readonly
self.complextype = None