1#!/usr/bin/env python
2from boto.mws.connection import MWSConnection
3from boto.mws.response import (ResponseFactory, ResponseElement, Element,
4                               MemberList, ElementList, SimpleList)
5
6
7from tests.unit import AWSMockServiceTestCase
8from boto.compat import filter, map
9from tests.compat import unittest
10
11
12class TestMWSResponse(AWSMockServiceTestCase):
13    connection_class = MWSConnection
14    mws = True
15
16    def test_parsing_nested_elements(self):
17        class Test9one(ResponseElement):
18            Nest = Element()
19            Zoom = Element()
20
21        class Test9Result(ResponseElement):
22            Item = Element(Test9one)
23
24        text = b"""<Test9Response><Test9Result>
25                  <Item>
26                        <Foo>Bar</Foo>
27                        <Nest>
28                            <Zip>Zap</Zip>
29                            <Zam>Zoo</Zam>
30                        </Nest>
31                        <Bif>Bam</Bif>
32                  </Item>
33                  </Test9Result></Test9Response>"""
34        obj = self.check_issue(Test9Result, text)
35        Item = obj._result.Item
36        useful = lambda x: not x[0].startswith('_')
37        nest = dict(filter(useful, Item.Nest.__dict__.items()))
38        self.assertEqual(nest, dict(Zip='Zap', Zam='Zoo'))
39        useful = lambda x: not x[0].startswith('_') and not x[0] == 'Nest'
40        item = dict(filter(useful, Item.__dict__.items()))
41        self.assertEqual(item, dict(Foo='Bar', Bif='Bam', Zoom=None))
42
43    def test_parsing_member_list_specification(self):
44        class Test8extra(ResponseElement):
45            Foo = SimpleList()
46
47        class Test8Result(ResponseElement):
48            Item = MemberList(SimpleList)
49            Extra = MemberList(Test8extra)
50
51        text = b"""<Test8Response><Test8Result>
52                  <Item>
53                        <member>0</member>
54                        <member>1</member>
55                        <member>2</member>
56                        <member>3</member>
57                  </Item>
58                  <Extra>
59                        <member><Foo>4</Foo><Foo>5</Foo></member>
60                        <member></member>
61                        <member><Foo>6</Foo><Foo>7</Foo></member>
62                  </Extra>
63                  </Test8Result></Test8Response>"""
64        obj = self.check_issue(Test8Result, text)
65        self.assertSequenceEqual(
66            list(map(int, obj._result.Item)),
67            list(range(4)),
68        )
69        self.assertSequenceEqual(
70            list(map(lambda x: list(map(int, x.Foo)), obj._result.Extra)),
71            [[4, 5], [], [6, 7]],
72        )
73
74    def test_parsing_nested_lists(self):
75        class Test7Result(ResponseElement):
76            Item = MemberList(Nest=MemberList(),
77                              List=ElementList(Simple=SimpleList()))
78
79        text = b"""<Test7Response><Test7Result>
80                  <Item>
81                        <member>
82                            <Value>One</Value>
83                            <Nest>
84                                <member><Data>2</Data></member>
85                                <member><Data>4</Data></member>
86                                <member><Data>6</Data></member>
87                            </Nest>
88                        </member>
89                        <member>
90                            <Value>Two</Value>
91                            <Nest>
92                                <member><Data>1</Data></member>
93                                <member><Data>3</Data></member>
94                                <member><Data>5</Data></member>
95                            </Nest>
96                            <List>
97                                <Simple>4</Simple>
98                                <Simple>5</Simple>
99                                <Simple>6</Simple>
100                            </List>
101                            <List>
102                                <Simple>7</Simple>
103                                <Simple>8</Simple>
104                                <Simple>9</Simple>
105                            </List>
106                        </member>
107                        <member>
108                            <Value>Six</Value>
109                            <List>
110                                <Complex>Foo</Complex>
111                                <Simple>1</Simple>
112                                <Simple>2</Simple>
113                                <Simple>3</Simple>
114                            </List>
115                            <List>
116                                <Complex>Bar</Complex>
117                            </List>
118                        </member>
119                  </Item>
120                  </Test7Result></Test7Response>"""
121        obj = self.check_issue(Test7Result, text)
122        item = obj._result.Item
123        self.assertEqual(len(item), 3)
124        nests = [z.Nest for z in filter(lambda x: x.Nest, item)]
125        self.assertSequenceEqual(
126            [[y.Data for y in nest] for nest in nests],
127            [[u'2', u'4', u'6'], [u'1', u'3', u'5']],
128        )
129        self.assertSequenceEqual(
130            [element.Simple for element in item[1].List],
131            [[u'4', u'5', u'6'], [u'7', u'8', u'9']],
132        )
133        self.assertSequenceEqual(
134            item[-1].List[0].Simple,
135            ['1', '2', '3'],
136        )
137        self.assertEqual(item[-1].List[1].Simple, [])
138        self.assertSequenceEqual(
139            [e.Value for e in obj._result.Item],
140            ['One', 'Two', 'Six'],
141        )
142
143    def test_parsing_member_list(self):
144        class Test6Result(ResponseElement):
145            Item = MemberList()
146
147        text = b"""<Test6Response><Test6Result>
148                  <Item>
149                        <member><Value>One</Value></member>
150                        <member><Value>Two</Value>
151                                <Error>Four</Error>
152                        </member>
153                        <member><Value>Six</Value></member>
154                  </Item>
155                  </Test6Result></Test6Response>"""
156        obj = self.check_issue(Test6Result, text)
157        self.assertSequenceEqual(
158            [e.Value for e in obj._result.Item],
159            ['One', 'Two', 'Six'],
160        )
161        self.assertTrue(obj._result.Item[1].Error == 'Four')
162        with self.assertRaises(AttributeError) as e:
163            obj._result.Item[2].Error
164
165    def test_parsing_empty_member_list(self):
166        class Test5Result(ResponseElement):
167            Item = MemberList(Nest=MemberList())
168
169        text = b"""<Test5Response><Test5Result>
170                  <Item/>
171                  </Test5Result></Test5Response>"""
172        obj = self.check_issue(Test5Result, text)
173        self.assertSequenceEqual(obj._result.Item, [])
174
175    def test_parsing_missing_member_list(self):
176        class Test4Result(ResponseElement):
177            Item = MemberList(NestedItem=MemberList())
178
179        text = b"""<Test4Response><Test4Result>
180                  </Test4Result></Test4Response>"""
181        obj = self.check_issue(Test4Result, text)
182        self.assertSequenceEqual(obj._result.Item, [])
183
184    def test_parsing_element_lists(self):
185        class Test1Result(ResponseElement):
186            Item = ElementList()
187
188        text = b"""<Test1Response><Test1Result>
189            <Item><Foo>Bar</Foo></Item>
190            <Item><Zip>Bif</Zip></Item>
191            <Item><Foo>Baz</Foo>
192                      <Zam>Zoo</Zam></Item>
193        </Test1Result></Test1Response>"""
194        obj = self.check_issue(Test1Result, text)
195        self.assertTrue(len(obj._result.Item) == 3)
196        elements = lambda x: getattr(x, 'Foo', getattr(x, 'Zip', '?'))
197        elements = list(map(elements, obj._result.Item))
198        self.assertSequenceEqual(elements, ['Bar', 'Bif', 'Baz'])
199
200    def test_parsing_missing_lists(self):
201        class Test2Result(ResponseElement):
202            Item = ElementList()
203
204        text = b"""<Test2Response><Test2Result>
205        </Test2Result></Test2Response>"""
206        obj = self.check_issue(Test2Result, text)
207        self.assertEqual(obj._result.Item, [])
208
209    def test_parsing_simple_lists(self):
210        class Test3Result(ResponseElement):
211            Item = SimpleList()
212
213        text = b"""<Test3Response><Test3Result>
214            <Item>Bar</Item>
215            <Item>Bif</Item>
216            <Item>Baz</Item>
217        </Test3Result></Test3Response>"""
218        obj = self.check_issue(Test3Result, text)
219        self.assertSequenceEqual(obj._result.Item, ['Bar', 'Bif', 'Baz'])
220
221    def check_issue(self, klass, text):
222        action = klass.__name__[:-len('Result')]
223        factory = ResponseFactory(scopes=[{klass.__name__: klass}])
224        parser = factory(action, connection=self.service_connection)
225        return self.service_connection._parse_response(parser, 'text/xml', text)
226
227
228if __name__ == "__main__":
229    unittest.main()
230