Parse attributes according to their types

Follow OCCI 1.2 text rendering to parse attributes as string, number,
boolean or enum.

Change-Id: I7b78509a276abc6d77e72598f5da234be2e72a00
This commit is contained in:
Enol Fernandez 2016-06-14 10:50:24 +02:00 committed by Enol Fernández
parent 32ef451892
commit 1df2897254
4 changed files with 55 additions and 15 deletions

View File

@ -212,7 +212,8 @@ def create_header_occi(params, category, project=None):
att = ""
if params is not None:
for k, v in params.items():
att = "%s, %s=%s" % (att, k, v)
# FIXME(enolfc): this assumes all attributes are strings
att = "%s, %s=\"%s\"" % (att, k, v)
headers["X_OCCI_Attribute"] = att
if category is not None:
cat = ""

View File

@ -147,8 +147,8 @@ class TestNetNeutronController(test_middleware.TestMiddleware):
'"http://schemas.ogf.org/occi/infrastructure/'
'network#";'
'class="mixin",',
'X-OCCI-Attribute': '"occi.core.title"="%s",'
'"occi.network.address"="%s"' %
'X-OCCI-Attribute': 'occi.core.title="%s",'
'occi.network.address="%s"' %
(name, address)
}
req = self._build_req(path="/network",
@ -295,8 +295,8 @@ class TestNetNovaController(test_middleware.TestMiddleware):
'"http://schemas.ogf.org/occi/'
'infrastructure/network#";'
'class="mixin",',
'X-OCCI-Attribute': '"occi.core.title"="%s",'
'"occi.network.address"="%s"' %
'X-OCCI-Attribute': 'occi.core.title="%s",'
'occi.network.address="%s"' %
(name, address)
}
req = self._build_req(path="/network",

View File

@ -13,6 +13,7 @@
# under the License.
import collections
import numbers
from ooi import exception
@ -60,13 +61,15 @@ class BaseParserTest(object):
self.assertEqual({}, res["attributes"])
def test_attributes(self):
expected_attrs = {"foo": "bar", "baz": 1234, "bazonk": "foo=123",
"boolt": True, "enum": "whatev", "boolf": False,
"float": 3.14}
h, b = self.get_test_attributes(
{"term": "foo", "scheme": "http://example.com/scheme#"},
[("foo", '"bar"'), ("baz", 1234), ("bazonk", '"foo=123"')]
expected_attrs
)
parser = self._get_parser(h, b)
res = parser.parse()
expected_attrs = {"foo": "bar", "baz": "1234", "bazonk": "foo=123"}
self.assertEqual(expected_attrs, res["attributes"])
def test_link(self):
@ -74,12 +77,12 @@ class BaseParserTest(object):
{"term": "foo", "scheme": "http://example.com/scheme#"},
{
"id": "bar",
"attributes": [("foo", "bar"), ("bazonk", '"foo=123"')]
"attributes": {"foo": 1234, "bazonk": "foo=123"}
}
)
parser = self._get_parser(h, b)
res = parser.parse()
expected_links = {"bar": {"foo": "bar", "bazonk": "foo=123"}}
expected_links = {"bar": {"foo": 1234, "bazonk": "foo=123"}}
self.assertEqual(expected_links, res["links"])
@ -103,17 +106,27 @@ class TestHeaderParser(BaseParserTest, base.TestCase):
h["Category"] = ",".join(c)
return h, b
def _get_attribute_value(self, value):
if isinstance(value, bool):
return '"%s"' % str(value).lower()
elif isinstance(value, numbers.Number):
return "%s" % value
else:
return '"%s"' % value
def get_test_attributes(self, kind, attributes):
h, b = self.get_test_kind(kind)
attrs = ["%s=%s" % (a[0], a[1]) for a in attributes]
attrs = []
for n, v in attributes.items():
attrs.append("%s=%s" % (n, self._get_attribute_value(v)))
h["X-OCCI-Attribute"] = ", ".join(attrs)
return h, b
def get_test_link(self, kind, link):
h, b = self.get_test_kind(kind)
l = ["<%(id)s>" % link]
for a in link["attributes"]:
l.append('"%s"=%s' % (a[0], a[1]))
for n, v in link["attributes"].items():
l.append('"%s"=%s' % (n, self._get_attribute_value(v)))
h["Link"] = "; ".join(l)
return h, b

View File

@ -108,13 +108,36 @@ class TextParser(BaseParser):
"schemes": schemes,
}
def parse_attribute_value(self, value):
v = value.strip()
# quoted: string or bool
if v[0] == '"':
v = v.strip('"')
if v == "true":
return True
elif v == "false":
return False
else:
return v
# unquoted: number or enum-val
try:
return int(v)
except ValueError:
try:
return float(v)
except ValueError:
return v
def parse_attributes(self, headers):
attrs = {}
try:
header_attrs = headers["X-OCCI-Attribute"]
for attr in _quoted_split(header_attrs):
l = _split_unquote(attr)
attrs[l[0].strip()] = l[1]
try:
n, v = attr.split("=", 1)
attrs[n.strip()] = self.parse_attribute_value(v)
except ValueError:
raise exception.OCCIInvalidSchema("Unable to parse")
except KeyError:
pass
return attrs
@ -131,8 +154,11 @@ class TextParser(BaseParser):
if ll[0][1] != "<" and ll[0][-1] != ">":
raise exception.OCCIInvalidSchema("Unable to parse link")
link_dest = ll[0][1:-1]
d = {}
try:
d = dict([_split_unquote(i) for i in ll[1:]])
for attr in ll[1:]:
n, v = attr.split("=", 1)
d[n.strip().strip('"')] = self.parse_attribute_value(v)
except ValueError:
raise exception.OCCIInvalidSchema("Unable to parse link")
links[link_dest] = d