Merge "Add next links to images requests"
This commit is contained in:
		@@ -13,7 +13,6 @@
 | 
			
		||||
#    License for the specific language governing permissions and limitations
 | 
			
		||||
#    under the License.
 | 
			
		||||
 | 
			
		||||
import urlparse
 | 
			
		||||
import os.path
 | 
			
		||||
 | 
			
		||||
from lxml import etree
 | 
			
		||||
@@ -149,8 +148,7 @@ class ControllerV10(Controller):
 | 
			
		||||
        filters = self._get_filters(req)
 | 
			
		||||
        images = self._image_service.index(context, filters=filters)
 | 
			
		||||
        images = common.limited(images, req)
 | 
			
		||||
        builder = self.get_builder(req).build
 | 
			
		||||
        return dict(images=[builder(image, detail=False) for image in images])
 | 
			
		||||
        return self.get_builder(req).build_list(images)
 | 
			
		||||
 | 
			
		||||
    def detail(self, req):
 | 
			
		||||
        """Return a detailed index listing of images available to the request.
 | 
			
		||||
@@ -183,11 +181,14 @@ class ControllerV11(Controller):
 | 
			
		||||
        """
 | 
			
		||||
        context = req.environ['nova.context']
 | 
			
		||||
        filters = self._get_filters(req)
 | 
			
		||||
        params = req.GET.copy()
 | 
			
		||||
        page_params = common.get_pagination_params(req)
 | 
			
		||||
        for key, val in page_params.iteritems():
 | 
			
		||||
            params[key] = val
 | 
			
		||||
 | 
			
		||||
        images = self._image_service.index(context, filters=filters,
 | 
			
		||||
                                           **page_params)
 | 
			
		||||
        builder = self.get_builder(req).build
 | 
			
		||||
        return dict(images=[builder(image, detail=False) for image in images])
 | 
			
		||||
        return self.get_builder(req).build_list(images, **params)
 | 
			
		||||
 | 
			
		||||
    def detail(self, req):
 | 
			
		||||
        """Return a detailed index listing of images available to the request.
 | 
			
		||||
@@ -197,11 +198,14 @@ class ControllerV11(Controller):
 | 
			
		||||
        """
 | 
			
		||||
        context = req.environ['nova.context']
 | 
			
		||||
        filters = self._get_filters(req)
 | 
			
		||||
        params = req.GET.copy()
 | 
			
		||||
        page_params = common.get_pagination_params(req)
 | 
			
		||||
        for key, val in page_params.iteritems():
 | 
			
		||||
            params[key] = val
 | 
			
		||||
        images = self._image_service.detail(context, filters=filters,
 | 
			
		||||
                                            **page_params)
 | 
			
		||||
        builder = self.get_builder(req).build
 | 
			
		||||
        return dict(images=[builder(image, detail=True) for image in images])
 | 
			
		||||
 | 
			
		||||
        return self.get_builder(req).build_list(images, detail=True, **params)
 | 
			
		||||
 | 
			
		||||
    def create(self, *args, **kwargs):
 | 
			
		||||
        raise webob.exc.HTTPMethodNotAllowed()
 | 
			
		||||
@@ -253,20 +257,23 @@ class ImageXMLSerializer(wsgi.XMLDictSerializer):
 | 
			
		||||
                            image_dict.get('metadata', {}))
 | 
			
		||||
            image_elem.append(meta_elem)
 | 
			
		||||
 | 
			
		||||
        for link in image_dict.get('links', []):
 | 
			
		||||
            elem = etree.SubElement(image_elem,
 | 
			
		||||
                                    '{%s}link' % xmlutil.XMLNS_ATOM)
 | 
			
		||||
        self._populate_links(image_elem, image_dict.get('links', []))
 | 
			
		||||
 | 
			
		||||
    def _populate_links(self, parent, links):
 | 
			
		||||
        for link in links:
 | 
			
		||||
            elem = etree.SubElement(parent, '{%s}link' % xmlutil.XMLNS_ATOM)
 | 
			
		||||
            elem.set('rel', link['rel'])
 | 
			
		||||
            if 'type' in link:
 | 
			
		||||
                elem.set('type', link['type'])
 | 
			
		||||
            elem.set('href', link['href'])
 | 
			
		||||
        return image_elem
 | 
			
		||||
 | 
			
		||||
    def index(self, images_dict):
 | 
			
		||||
        images = etree.Element('images', nsmap=self.NSMAP)
 | 
			
		||||
        for image_dict in images_dict['images']:
 | 
			
		||||
            image = etree.SubElement(images, 'image')
 | 
			
		||||
            self._populate_image(image, image_dict, False)
 | 
			
		||||
 | 
			
		||||
        self._populate_links(images, images_dict.get('images_links', []))
 | 
			
		||||
        return self._to_xml(images)
 | 
			
		||||
 | 
			
		||||
    def detail(self, images_dict):
 | 
			
		||||
 
 | 
			
		||||
@@ -9,4 +9,7 @@
 | 
			
		||||
      </zeroOrMore>
 | 
			
		||||
    </element>
 | 
			
		||||
  </zeroOrMore>
 | 
			
		||||
  <zeroOrMore>
 | 
			
		||||
    <externalRef href="../atom-link.rng"/>
 | 
			
		||||
  </zeroOrMore>
 | 
			
		||||
</element>
 | 
			
		||||
 
 | 
			
		||||
@@ -59,6 +59,15 @@ class ViewBuilder(object):
 | 
			
		||||
        """Return an href string pointing to this object."""
 | 
			
		||||
        return os.path.join(self.base_url, "images", str(image_id))
 | 
			
		||||
 | 
			
		||||
    def build_list(self, image_objs, detail=False, **kwargs):
 | 
			
		||||
        """Return a standardized image list structure for display."""
 | 
			
		||||
        images = []
 | 
			
		||||
        for image_obj in image_objs:
 | 
			
		||||
            image = self.build(image_obj, detail=detail)
 | 
			
		||||
            images.append(image)
 | 
			
		||||
 | 
			
		||||
        return dict(images=images)
 | 
			
		||||
 | 
			
		||||
    def build(self, image_obj, detail=False):
 | 
			
		||||
        """Return a standardized image structure for display by the API."""
 | 
			
		||||
        self._format_dates(image_obj)
 | 
			
		||||
@@ -135,6 +144,33 @@ class ViewBuilderV11(ViewBuilder):
 | 
			
		||||
        return os.path.join(self.base_url, self.project_id,
 | 
			
		||||
                            "images", str(image_id))
 | 
			
		||||
 | 
			
		||||
    def generate_next_link(self, image_id, params):
 | 
			
		||||
        """ Return an href string with proper limit and marker params"""
 | 
			
		||||
        params['marker'] = image_id
 | 
			
		||||
        return "%s?%s" % (
 | 
			
		||||
            os.path.join(self.base_url, self.project_id, "images"),
 | 
			
		||||
            common.dict_to_query_str(params))
 | 
			
		||||
 | 
			
		||||
    def build_list(self, image_objs, detail=False, **kwargs):
 | 
			
		||||
        """Return a standardized image list structure for display."""
 | 
			
		||||
        limit = kwargs.get('limit', None)
 | 
			
		||||
        images = []
 | 
			
		||||
        images_links = []
 | 
			
		||||
 | 
			
		||||
        for image_obj in image_objs:
 | 
			
		||||
            image = self.build(image_obj, detail=detail)
 | 
			
		||||
            images.append(image)
 | 
			
		||||
 | 
			
		||||
        if (len(images) and limit) and (limit == len(images)):
 | 
			
		||||
            next_link = self.generate_next_link(images[-1]["id"], kwargs)
 | 
			
		||||
            images_links = [dict(rel="next", href=next_link)]
 | 
			
		||||
 | 
			
		||||
        reval = dict(images=images)
 | 
			
		||||
        if len(images_links) > 0:
 | 
			
		||||
            reval['images_links'] = images_links
 | 
			
		||||
 | 
			
		||||
        return reval
 | 
			
		||||
 | 
			
		||||
    def build(self, image_obj, detail=False):
 | 
			
		||||
        """Return a standardized image structure for display by the API."""
 | 
			
		||||
        image = ViewBuilder.build(self, image_obj, detail)
 | 
			
		||||
 
 | 
			
		||||
@@ -21,12 +21,12 @@ and as a WSGI layer
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
import copy
 | 
			
		||||
from lxml import etree
 | 
			
		||||
import json
 | 
			
		||||
import xml.dom.minidom as minidom
 | 
			
		||||
 | 
			
		||||
from lxml import etree
 | 
			
		||||
import mox
 | 
			
		||||
import stubout
 | 
			
		||||
import urlparse
 | 
			
		||||
import webob
 | 
			
		||||
 | 
			
		||||
from nova import context
 | 
			
		||||
@@ -284,10 +284,12 @@ class ImagesTest(test.TestCase):
 | 
			
		||||
        app = fakes.wsgi_app(fake_auth_context=self._get_fake_context())
 | 
			
		||||
        response = request.get_response(app)
 | 
			
		||||
 | 
			
		||||
        print response.body
 | 
			
		||||
        response_dict = json.loads(response.body)
 | 
			
		||||
        response_list = response_dict["images"]
 | 
			
		||||
        self.assertTrue('images_links' not in response_dict)
 | 
			
		||||
 | 
			
		||||
        expected = [
 | 
			
		||||
        expected_images = [
 | 
			
		||||
            {
 | 
			
		||||
                "id": "123",
 | 
			
		||||
                "name": "public image",
 | 
			
		||||
@@ -450,7 +452,118 @@ class ImagesTest(test.TestCase):
 | 
			
		||||
            },
 | 
			
		||||
        ]
 | 
			
		||||
 | 
			
		||||
        self.assertDictListMatch(response_list, expected)
 | 
			
		||||
        self.assertDictListMatch(response_list, expected_images)
 | 
			
		||||
 | 
			
		||||
    def test_get_image_index_v1_1_with_limit(self):
 | 
			
		||||
        request = webob.Request.blank('/v1.1/fake/images?limit=3')
 | 
			
		||||
        app = fakes.wsgi_app(fake_auth_context=self._get_fake_context())
 | 
			
		||||
        response = request.get_response(app)
 | 
			
		||||
 | 
			
		||||
        print response.body
 | 
			
		||||
        response_dict = json.loads(response.body)
 | 
			
		||||
        response_list = response_dict["images"]
 | 
			
		||||
        response_links = response_dict["images_links"]
 | 
			
		||||
        alternate = "%s/fake/images/%s"
 | 
			
		||||
 | 
			
		||||
        expected_images = [
 | 
			
		||||
            {
 | 
			
		||||
                "id": "123",
 | 
			
		||||
                "name": "public image",
 | 
			
		||||
                "links": [
 | 
			
		||||
                    {
 | 
			
		||||
                        "rel": "self",
 | 
			
		||||
                        "href": "http://localhost/v1.1/fake/images/123",
 | 
			
		||||
                    },
 | 
			
		||||
                    {
 | 
			
		||||
                        "rel": "bookmark",
 | 
			
		||||
                        "href": "http://localhost/fake/images/123",
 | 
			
		||||
                    },
 | 
			
		||||
                    {
 | 
			
		||||
                        "rel": "alternate",
 | 
			
		||||
                        "type": "application/vnd.openstack.image",
 | 
			
		||||
                        "href": alternate % (utils.generate_glance_url(), 123),
 | 
			
		||||
                    },
 | 
			
		||||
                ],
 | 
			
		||||
            },
 | 
			
		||||
            {
 | 
			
		||||
                "id": "124",
 | 
			
		||||
                "name": "queued snapshot",
 | 
			
		||||
                "links": [
 | 
			
		||||
                    {
 | 
			
		||||
                        "rel": "self",
 | 
			
		||||
                        "href": "http://localhost/v1.1/fake/images/124",
 | 
			
		||||
                    },
 | 
			
		||||
                    {
 | 
			
		||||
                        "rel": "bookmark",
 | 
			
		||||
                        "href": "http://localhost/fake/images/124",
 | 
			
		||||
                    },
 | 
			
		||||
                    {
 | 
			
		||||
                        "rel": "alternate",
 | 
			
		||||
                        "type": "application/vnd.openstack.image",
 | 
			
		||||
                        "href": alternate % (utils.generate_glance_url(), 124),
 | 
			
		||||
                    },
 | 
			
		||||
                ],
 | 
			
		||||
            },
 | 
			
		||||
            {
 | 
			
		||||
                "id": "125",
 | 
			
		||||
                "name": "saving snapshot",
 | 
			
		||||
                "links": [
 | 
			
		||||
                    {
 | 
			
		||||
                        "rel": "self",
 | 
			
		||||
                        "href": "http://localhost/v1.1/fake/images/125",
 | 
			
		||||
                    },
 | 
			
		||||
                    {
 | 
			
		||||
                        "rel": "bookmark",
 | 
			
		||||
                        "href": "http://localhost/fake/images/125",
 | 
			
		||||
                    },
 | 
			
		||||
                    {
 | 
			
		||||
                        "rel": "alternate",
 | 
			
		||||
                        "type": "application/vnd.openstack.image",
 | 
			
		||||
                        "href": alternate % (utils.generate_glance_url(), 125),
 | 
			
		||||
                    },
 | 
			
		||||
                ],
 | 
			
		||||
            },
 | 
			
		||||
        ]
 | 
			
		||||
 | 
			
		||||
        self.assertDictListMatch(response_list, expected_images)
 | 
			
		||||
        self.assertEqual(response_links[0]['rel'], 'next')
 | 
			
		||||
 | 
			
		||||
        href_parts = urlparse.urlparse(response_links[0]['href'])
 | 
			
		||||
        self.assertEqual('/v1.1/fake/images', href_parts.path)
 | 
			
		||||
        params = urlparse.parse_qs(href_parts.query)
 | 
			
		||||
        self.assertDictMatch({'limit': ['3'], 'marker': ['125']}, params)
 | 
			
		||||
 | 
			
		||||
    def test_get_image_index_v1_1_with_limit_and_extra_params(self):
 | 
			
		||||
        request = webob.Request.blank('/v1.1/fake/images?limit=3&extra=boo')
 | 
			
		||||
        app = fakes.wsgi_app(fake_auth_context=self._get_fake_context())
 | 
			
		||||
        response = request.get_response(app)
 | 
			
		||||
 | 
			
		||||
        response_dict = json.loads(response.body)
 | 
			
		||||
        response_links = response_dict["images_links"]
 | 
			
		||||
 | 
			
		||||
        self.assertEqual(response_links[0]['rel'], 'next')
 | 
			
		||||
 | 
			
		||||
        href_parts = urlparse.urlparse(response_links[0]['href'])
 | 
			
		||||
        self.assertEqual('/v1.1/fake/images', href_parts.path)
 | 
			
		||||
        params = urlparse.parse_qs(href_parts.query)
 | 
			
		||||
        self.assertDictMatch(
 | 
			
		||||
            {'limit': ['3'], 'marker': ['125'], 'extra': ['boo']},
 | 
			
		||||
            params)
 | 
			
		||||
 | 
			
		||||
    def test_get_image_index_v1_1_with_big_limit(self):
 | 
			
		||||
        """
 | 
			
		||||
        Make sure we don't get images_links if limit is set
 | 
			
		||||
        and the number of images returned is < limit
 | 
			
		||||
        """
 | 
			
		||||
        request = webob.Request.blank('/v1.1/fake/images?limit=30')
 | 
			
		||||
        app = fakes.wsgi_app(fake_auth_context=self._get_fake_context())
 | 
			
		||||
        response = request.get_response(app)
 | 
			
		||||
 | 
			
		||||
        response_dict = json.loads(response.body)
 | 
			
		||||
        response_list = response_dict["images"]
 | 
			
		||||
 | 
			
		||||
        self.assertTrue('images_links' not in response_dict)
 | 
			
		||||
        self.assertEqual(len(response_list), 8)
 | 
			
		||||
 | 
			
		||||
    def test_get_image_details(self):
 | 
			
		||||
        request = webob.Request.blank('/v1.0/images/detail')
 | 
			
		||||
@@ -536,6 +649,7 @@ class ImagesTest(test.TestCase):
 | 
			
		||||
        response_list = response_dict["images"]
 | 
			
		||||
        server_href = "http://localhost/v1.1/servers/42"
 | 
			
		||||
        server_bookmark = "http://localhost/servers/42"
 | 
			
		||||
        alternate = "%s/fake/images/%s"
 | 
			
		||||
 | 
			
		||||
        expected = [{
 | 
			
		||||
            'id': '123',
 | 
			
		||||
@@ -558,7 +672,7 @@ class ImagesTest(test.TestCase):
 | 
			
		||||
            {
 | 
			
		||||
                "rel": "alternate",
 | 
			
		||||
                "type": "application/vnd.openstack.image",
 | 
			
		||||
                "href": "%s/fake/images/123" % utils.generate_glance_url()
 | 
			
		||||
                "href": alternate % (utils.generate_glance_url(), 123),
 | 
			
		||||
            }],
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
@@ -596,7 +710,7 @@ class ImagesTest(test.TestCase):
 | 
			
		||||
            {
 | 
			
		||||
                "rel": "alternate",
 | 
			
		||||
                "type": "application/vnd.openstack.image",
 | 
			
		||||
                "href": "%s/fake/images/124" % utils.generate_glance_url()
 | 
			
		||||
                "href": alternate % (utils.generate_glance_url(), 124),
 | 
			
		||||
            }],
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
@@ -817,6 +931,89 @@ class ImagesTest(test.TestCase):
 | 
			
		||||
 | 
			
		||||
        self.assertDictListMatch(expected, response_list)
 | 
			
		||||
 | 
			
		||||
    def test_get_image_details_with_limit_v1_1(self):
 | 
			
		||||
        request = webob.Request.blank('/v1.1/fake/images/detail?limit=2')
 | 
			
		||||
        app = fakes.wsgi_app(fake_auth_context=self._get_fake_context())
 | 
			
		||||
        response = request.get_response(app)
 | 
			
		||||
 | 
			
		||||
        response_dict = json.loads(response.body)
 | 
			
		||||
        response_list = response_dict["images"]
 | 
			
		||||
        response_links = response_dict["images_links"]
 | 
			
		||||
        server_href = "http://localhost/v1.1/servers/42"
 | 
			
		||||
        server_bookmark = "http://localhost/servers/42"
 | 
			
		||||
        alternate = "%s/fake/images/%s"
 | 
			
		||||
 | 
			
		||||
        expected = [{
 | 
			
		||||
            'id': '123',
 | 
			
		||||
            'name': 'public image',
 | 
			
		||||
            'metadata': {'key1': 'value1'},
 | 
			
		||||
            'updated': NOW_API_FORMAT,
 | 
			
		||||
            'created': NOW_API_FORMAT,
 | 
			
		||||
            'status': 'ACTIVE',
 | 
			
		||||
            'minDisk': 0,
 | 
			
		||||
            'progress': 100,
 | 
			
		||||
            'minRam': 0,
 | 
			
		||||
            "links": [{
 | 
			
		||||
                "rel": "self",
 | 
			
		||||
                "href": "http://localhost/v1.1/fake/images/123",
 | 
			
		||||
            },
 | 
			
		||||
            {
 | 
			
		||||
                "rel": "bookmark",
 | 
			
		||||
                "href": "http://localhost/fake/images/123",
 | 
			
		||||
            },
 | 
			
		||||
            {
 | 
			
		||||
                "rel": "alternate",
 | 
			
		||||
                "type": "application/vnd.openstack.image",
 | 
			
		||||
                "href": alternate % (utils.generate_glance_url(), 123),
 | 
			
		||||
            }],
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
            'id': '124',
 | 
			
		||||
            'name': 'queued snapshot',
 | 
			
		||||
            'metadata': {
 | 
			
		||||
                u'instance_ref': u'http://localhost/v1.1/servers/42',
 | 
			
		||||
                u'user_id': u'fake',
 | 
			
		||||
            },
 | 
			
		||||
            'updated': NOW_API_FORMAT,
 | 
			
		||||
            'created': NOW_API_FORMAT,
 | 
			
		||||
            'status': 'SAVING',
 | 
			
		||||
            'minDisk': 0,
 | 
			
		||||
            'progress': 0,
 | 
			
		||||
            'minRam': 0,
 | 
			
		||||
            'server': {
 | 
			
		||||
                'id': '42',
 | 
			
		||||
                "links": [{
 | 
			
		||||
                    "rel": "self",
 | 
			
		||||
                    "href": server_href,
 | 
			
		||||
                },
 | 
			
		||||
                {
 | 
			
		||||
                    "rel": "bookmark",
 | 
			
		||||
                    "href": server_bookmark,
 | 
			
		||||
                }],
 | 
			
		||||
            },
 | 
			
		||||
            "links": [{
 | 
			
		||||
                "rel": "self",
 | 
			
		||||
                "href": "http://localhost/v1.1/fake/images/124",
 | 
			
		||||
            },
 | 
			
		||||
            {
 | 
			
		||||
                "rel": "bookmark",
 | 
			
		||||
                "href": "http://localhost/fake/images/124",
 | 
			
		||||
            },
 | 
			
		||||
            {
 | 
			
		||||
                "rel": "alternate",
 | 
			
		||||
                "type": "application/vnd.openstack.image",
 | 
			
		||||
                "href": alternate % (utils.generate_glance_url(), 124),
 | 
			
		||||
            }],
 | 
			
		||||
        }]
 | 
			
		||||
 | 
			
		||||
        self.assertDictListMatch(expected, response_list)
 | 
			
		||||
 | 
			
		||||
        href_parts = urlparse.urlparse(response_links[0]['href'])
 | 
			
		||||
        self.assertEqual('/v1.1/fake/images', href_parts.path)
 | 
			
		||||
        params = urlparse.parse_qs(href_parts.query)
 | 
			
		||||
 | 
			
		||||
        self.assertDictMatch({'limit': ['2'], 'marker': ['124']}, params)
 | 
			
		||||
 | 
			
		||||
    def test_image_filter_with_name(self):
 | 
			
		||||
        image_service = self.mox.CreateMockAnything()
 | 
			
		||||
        context = self._get_fake_context()
 | 
			
		||||
@@ -1115,6 +1312,7 @@ class ImageXMLSerializationTest(test.TestCase):
 | 
			
		||||
    SERVER_HREF = 'http://localhost/v1.1/servers/123'
 | 
			
		||||
    SERVER_BOOKMARK = 'http://localhost/servers/123'
 | 
			
		||||
    IMAGE_HREF = 'http://localhost/v1.1/fake/images/%s'
 | 
			
		||||
    IMAGE_NEXT = 'http://localhost/v1.1/fake/images?limit=%s&marker=%s'
 | 
			
		||||
    IMAGE_BOOKMARK = 'http://localhost/fake/images/%s'
 | 
			
		||||
 | 
			
		||||
    def test_xml_declaration(self):
 | 
			
		||||
@@ -1612,6 +1810,72 @@ class ImageXMLSerializationTest(test.TestCase):
 | 
			
		||||
                for key, value in link.items():
 | 
			
		||||
                    self.assertEqual(link_nodes[i].get(key), value)
 | 
			
		||||
 | 
			
		||||
    def test_index_with_links(self):
 | 
			
		||||
        serializer = images.ImageXMLSerializer()
 | 
			
		||||
 | 
			
		||||
        fixture = {
 | 
			
		||||
            'images': [
 | 
			
		||||
                {
 | 
			
		||||
                    'id': 1,
 | 
			
		||||
                    'name': 'Image1',
 | 
			
		||||
                    'links': [
 | 
			
		||||
                        {
 | 
			
		||||
                            'href': self.IMAGE_HREF % 1,
 | 
			
		||||
                            'rel': 'self',
 | 
			
		||||
                        },
 | 
			
		||||
                        {
 | 
			
		||||
                            'href': self.IMAGE_BOOKMARK % 1,
 | 
			
		||||
                            'rel': 'bookmark',
 | 
			
		||||
                        },
 | 
			
		||||
                    ],
 | 
			
		||||
                },
 | 
			
		||||
                {
 | 
			
		||||
                    'id': 2,
 | 
			
		||||
                    'name': 'Image2',
 | 
			
		||||
                    'links': [
 | 
			
		||||
                        {
 | 
			
		||||
                            'href': self.IMAGE_HREF % 2,
 | 
			
		||||
                            'rel': 'self',
 | 
			
		||||
                        },
 | 
			
		||||
                        {
 | 
			
		||||
                            'href': self.IMAGE_BOOKMARK % 2,
 | 
			
		||||
                            'rel': 'bookmark',
 | 
			
		||||
                        },
 | 
			
		||||
                    ],
 | 
			
		||||
                },
 | 
			
		||||
            ],
 | 
			
		||||
            'images_links': [
 | 
			
		||||
                {
 | 
			
		||||
                    'rel': 'next',
 | 
			
		||||
                    'href': self.IMAGE_NEXT % (2, 2),
 | 
			
		||||
                }
 | 
			
		||||
            ],
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        output = serializer.serialize(fixture, 'index')
 | 
			
		||||
        print output
 | 
			
		||||
        root = etree.XML(output)
 | 
			
		||||
        xmlutil.validate_schema(root, 'images_index')
 | 
			
		||||
        image_elems = root.findall('{0}image'.format(NS))
 | 
			
		||||
        self.assertEqual(len(image_elems), 2)
 | 
			
		||||
        for i, image_elem in enumerate(image_elems):
 | 
			
		||||
            image_dict = fixture['images'][i]
 | 
			
		||||
 | 
			
		||||
            for key in ['name', 'id']:
 | 
			
		||||
                self.assertEqual(image_elem.get(key), str(image_dict[key]))
 | 
			
		||||
 | 
			
		||||
            link_nodes = image_elem.findall('{0}link'.format(ATOMNS))
 | 
			
		||||
            self.assertEqual(len(link_nodes), 2)
 | 
			
		||||
            for i, link in enumerate(image_dict['links']):
 | 
			
		||||
                for key, value in link.items():
 | 
			
		||||
                    self.assertEqual(link_nodes[i].get(key), value)
 | 
			
		||||
 | 
			
		||||
            # Check images_links
 | 
			
		||||
            images_links = root.findall('{0}link'.format(ATOMNS))
 | 
			
		||||
            for i, link in enumerate(fixture['images_links']):
 | 
			
		||||
                for key, value in link.items():
 | 
			
		||||
                    self.assertEqual(images_links[i].get(key), value)
 | 
			
		||||
 | 
			
		||||
    def test_index_zero_images(self):
 | 
			
		||||
        serializer = images.ImageXMLSerializer()
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user