summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYuriy Zveryanskyy <yzveryanskyy@mirantis.com>2013-12-12 17:23:05 +0200
committerYuriy Zveryanskyy <yzveryanskyy@mirantis.com>2013-12-12 18:14:57 +0200
commite26d1b608cc5a05940c0b6b7fc176a0d587ba611 (patch)
tree6560b082cc3f3e3a07e932c8bd19850830244a35
parent9751ccebfa8c3cfbbc6b38e398f35ab557d7747c (diff)
downloadwsme-e26d1b608cc5a05940c0b6b7fc176a0d587ba611.tar.gz
Add 'readonly' parameter to wsattr0.6
'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
-rw-r--r--wsme/rest/json.py7
-rw-r--r--wsme/rest/xml.py6
-rw-r--r--wsme/tests/test_api.py19
-rw-r--r--wsme/types.py5
4 files changed, 33 insertions, 4 deletions
diff --git a/wsme/rest/json.py b/wsme/rest/json.py
index 42a9559..9adfd6b 100644
--- a/wsme/rest/json.py
+++ b/wsme/rest/json.py
@@ -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.")
diff --git a/wsme/rest/xml.py b/wsme/rest/xml.py
index 9a836c3..286afa7 100644
--- a/wsme/rest/xml.py
+++ b/wsme/rest/xml.py
@@ -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.")
diff --git a/wsme/tests/test_api.py b/wsme/tests/test_api.py
index db85c51..9149cf9 100644
--- a/wsme/tests/test_api.py
+++ b/wsme/tests/test_api.py
@@ -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'),
diff --git a/wsme/types.py b/wsme/types.py
index 7adef83..9701a61 100644
--- a/wsme/types.py
+++ b/wsme/types.py
@@ -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