Add pagination support for xml
Fixes bug 1130622 Change-Id: Id9f39daf634906ee222315586fc9a93916160c3f
This commit is contained in:
parent
c1c1cdec15
commit
2ee33f1c51
@ -42,6 +42,9 @@ XML_NS_V20 = 'http://openstack.org/quantum/api/v2.0'
|
|||||||
XSI_NAMESPACE = "http://www.w3.org/2001/XMLSchema-instance"
|
XSI_NAMESPACE = "http://www.w3.org/2001/XMLSchema-instance"
|
||||||
XSI_ATTR = "xsi:nil"
|
XSI_ATTR = "xsi:nil"
|
||||||
XSI_NIL_ATTR = "xmlns:xsi"
|
XSI_NIL_ATTR = "xmlns:xsi"
|
||||||
|
ATOM_NAMESPACE = "http://www.w3.org/2005/Atom"
|
||||||
|
ATOM_XMLNS = "xmlns:atom"
|
||||||
|
ATOM_LINK_NOTATION = "{%s}link" % ATOM_NAMESPACE
|
||||||
TYPE_XMLNS = "xmlns:quantum"
|
TYPE_XMLNS = "xmlns:quantum"
|
||||||
TYPE_ATTR = "quantum:type"
|
TYPE_ATTR = "quantum:type"
|
||||||
VIRTUAL_ROOT_KEY = "_v_root"
|
VIRTUAL_ROOT_KEY = "_v_root"
|
||||||
|
@ -287,8 +287,6 @@ class LoadBalancerPluginDbTestCase(testlib_api.WebTestCase):
|
|||||||
|
|
||||||
def _test_list_with_pagination(self, collection, items, sort,
|
def _test_list_with_pagination(self, collection, items, sort,
|
||||||
limit, expected_page_num, query_params=''):
|
limit, expected_page_num, query_params=''):
|
||||||
if self.fmt == 'xml':
|
|
||||||
self.skipTest("Skip xml test for pagination")
|
|
||||||
query_str = query_params + '&' if query_params else ''
|
query_str = query_params + '&' if query_params else ''
|
||||||
query_str = query_str + ("limit=%s&sort_key=%s&"
|
query_str = query_str + ("limit=%s&sort_key=%s&"
|
||||||
"sort_dir=%s") % (limit, sort[0], sort[1])
|
"sort_dir=%s") % (limit, sort[0], sort[1])
|
||||||
@ -317,8 +315,6 @@ class LoadBalancerPluginDbTestCase(testlib_api.WebTestCase):
|
|||||||
def _test_list_with_pagination_reverse(self, collection, items, sort,
|
def _test_list_with_pagination_reverse(self, collection, items, sort,
|
||||||
limit, expected_page_num,
|
limit, expected_page_num,
|
||||||
query_params=''):
|
query_params=''):
|
||||||
if self.fmt == 'xml':
|
|
||||||
self.skipTest("Skip xml test for pagination")
|
|
||||||
resources = '%ss' % collection
|
resources = '%ss' % collection
|
||||||
collection = collection.replace('-', '_')
|
collection = collection.replace('-', '_')
|
||||||
api = self._api_for_resource(resources)
|
api = self._api_for_resource(resources)
|
||||||
|
@ -555,8 +555,6 @@ class QuantumDbPluginV2TestCase(testlib_api.WebTestCase):
|
|||||||
def _test_list_with_pagination(self, collection, items, sort,
|
def _test_list_with_pagination(self, collection, items, sort,
|
||||||
limit, expected_page_num, query_params='',
|
limit, expected_page_num, query_params='',
|
||||||
verify_key='id'):
|
verify_key='id'):
|
||||||
if self.fmt == 'xml':
|
|
||||||
self.skipTest("Skip xml test for pagination")
|
|
||||||
query_str = query_params + '&' if query_params else ''
|
query_str = query_params + '&' if query_params else ''
|
||||||
query_str = query_str + ("limit=%s&sort_key=%s&"
|
query_str = query_str + ("limit=%s&sort_key=%s&"
|
||||||
"sort_dir=%s") % (limit, sort[0], sort[1])
|
"sort_dir=%s") % (limit, sort[0], sort[1])
|
||||||
@ -586,8 +584,6 @@ class QuantumDbPluginV2TestCase(testlib_api.WebTestCase):
|
|||||||
def _test_list_with_pagination_reverse(self, collection, items, sort,
|
def _test_list_with_pagination_reverse(self, collection, items, sort,
|
||||||
limit, expected_page_num,
|
limit, expected_page_num,
|
||||||
query_params=''):
|
query_params=''):
|
||||||
if self.fmt == 'xml':
|
|
||||||
self.skipTest("Skip xml test for pagination")
|
|
||||||
resources = '%ss' % collection
|
resources = '%ss' % collection
|
||||||
collection = collection.replace('-', '_')
|
collection = collection.replace('-', '_')
|
||||||
api = self._api_for_resource(resources)
|
api = self._api_for_resource(resources)
|
||||||
|
@ -255,21 +255,33 @@ class XMLDictSerializer(DictSerializer):
|
|||||||
self.xmlns = xmlns
|
self.xmlns = xmlns
|
||||||
|
|
||||||
def default(self, data):
|
def default(self, data):
|
||||||
# We expect data to contain a single key which is the XML root or
|
"""
|
||||||
# non root
|
:param data: expect data to contain a single key as XML root, or
|
||||||
|
contain another '*_links' key as atom links. Other
|
||||||
|
case will use 'VIRTUAL_ROOT_KEY' as XML root.
|
||||||
|
"""
|
||||||
try:
|
try:
|
||||||
key_len = data and len(data.keys()) or 0
|
links = None
|
||||||
if (key_len == 1):
|
has_atom = False
|
||||||
root_key = data.keys()[0]
|
if data is None:
|
||||||
root_value = data[root_key]
|
|
||||||
else:
|
|
||||||
root_key = constants.VIRTUAL_ROOT_KEY
|
root_key = constants.VIRTUAL_ROOT_KEY
|
||||||
root_value = data
|
root_value = None
|
||||||
|
else:
|
||||||
|
link_keys = [k for k in data.iterkeys() or []
|
||||||
|
if k.endswith('_links')]
|
||||||
|
if link_keys:
|
||||||
|
links = data.pop(link_keys[0], None)
|
||||||
|
has_atom = True
|
||||||
|
root_key = (len(data) == 1 and
|
||||||
|
data.keys()[0] or constants.VIRTUAL_ROOT_KEY)
|
||||||
|
root_value = data.get(root_key, data)
|
||||||
doc = etree.Element("_temp_root")
|
doc = etree.Element("_temp_root")
|
||||||
used_prefixes = []
|
used_prefixes = []
|
||||||
self._to_xml_node(doc, self.metadata, root_key,
|
self._to_xml_node(doc, self.metadata, root_key,
|
||||||
root_value, used_prefixes)
|
root_value, used_prefixes)
|
||||||
return self.to_xml_string(list(doc)[0], used_prefixes)
|
if links:
|
||||||
|
self._create_link_nodes(list(doc)[0], links)
|
||||||
|
return self.to_xml_string(list(doc)[0], used_prefixes, has_atom)
|
||||||
except AttributeError as e:
|
except AttributeError as e:
|
||||||
LOG.exception(str(e))
|
LOG.exception(str(e))
|
||||||
return ''
|
return ''
|
||||||
@ -292,7 +304,7 @@ class XMLDictSerializer(DictSerializer):
|
|||||||
node.set('xmlns', self.xmlns)
|
node.set('xmlns', self.xmlns)
|
||||||
node.set(constants.TYPE_XMLNS, self.xmlns)
|
node.set(constants.TYPE_XMLNS, self.xmlns)
|
||||||
if has_atom:
|
if has_atom:
|
||||||
node.set('xmlns:atom', "http://www.w3.org/2005/Atom")
|
node.set(constants.ATOM_XMLNS, constants.ATOM_NAMESPACE)
|
||||||
node.set(constants.XSI_NIL_ATTR, constants.XSI_NAMESPACE)
|
node.set(constants.XSI_NIL_ATTR, constants.XSI_NAMESPACE)
|
||||||
ext_ns = self.metadata.get(constants.EXT_NS, {})
|
ext_ns = self.metadata.get(constants.EXT_NS, {})
|
||||||
for prefix in used_prefixes:
|
for prefix in used_prefixes:
|
||||||
@ -359,6 +371,12 @@ class XMLDictSerializer(DictSerializer):
|
|||||||
result.text = str(data)
|
result.text = str(data)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
def _create_link_nodes(self, xml_doc, links):
|
||||||
|
for link in links:
|
||||||
|
link_node = etree.SubElement(xml_doc, 'atom:link')
|
||||||
|
link_node.set('rel', link['rel'])
|
||||||
|
link_node.set('href', link['href'])
|
||||||
|
|
||||||
|
|
||||||
class ResponseHeaderSerializer(ActionDispatcher):
|
class ResponseHeaderSerializer(ActionDispatcher):
|
||||||
"""Default response headers serialization"""
|
"""Default response headers serialization"""
|
||||||
@ -462,18 +480,35 @@ class XMLDeserializer(TextDeserializer):
|
|||||||
else:
|
else:
|
||||||
return tag
|
return tag
|
||||||
|
|
||||||
|
def _get_links(self, root_tag, node):
|
||||||
|
link_nodes = node.findall(constants.ATOM_LINK_NOTATION)
|
||||||
|
root_tag = self._get_key(node.tag)
|
||||||
|
link_key = "%s_links" % root_tag
|
||||||
|
link_list = []
|
||||||
|
for link in link_nodes:
|
||||||
|
link_list.append({'rel': link.get('rel'),
|
||||||
|
'href': link.get('href')})
|
||||||
|
# Remove link node in order to avoid link node process as
|
||||||
|
# an item in _from_xml_node
|
||||||
|
node.remove(link)
|
||||||
|
return link_list and {link_key: link_list} or {}
|
||||||
|
|
||||||
def _from_xml(self, datastring):
|
def _from_xml(self, datastring):
|
||||||
if datastring is None:
|
if datastring is None:
|
||||||
return None
|
return None
|
||||||
plurals = set(self.metadata.get('plurals', {}))
|
plurals = set(self.metadata.get('plurals', {}))
|
||||||
try:
|
try:
|
||||||
node = etree.fromstring(datastring)
|
node = etree.fromstring(datastring)
|
||||||
result = self._from_xml_node(node, plurals)
|
|
||||||
root_tag = self._get_key(node.tag)
|
root_tag = self._get_key(node.tag)
|
||||||
|
# Deserialize link node was needed by unit test for verifying
|
||||||
|
# the request's response
|
||||||
|
links = self._get_links(root_tag, node)
|
||||||
|
result = self._from_xml_node(node, plurals)
|
||||||
|
# root_tag = constants.VIRTUAL_ROOT_KEY and links is not None
|
||||||
|
# is not possible because of the way data are serialized.
|
||||||
if root_tag == constants.VIRTUAL_ROOT_KEY:
|
if root_tag == constants.VIRTUAL_ROOT_KEY:
|
||||||
return result
|
return result
|
||||||
else:
|
return dict({root_tag: result}, **links)
|
||||||
return {root_tag: result}
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
parseError = False
|
parseError = False
|
||||||
# Python2.7
|
# Python2.7
|
||||||
|
Loading…
Reference in New Issue
Block a user