source: pyyaml/trunk/tests/test_structure.py @ 222

Revision 222, 8.7 KB checked in by xi, 8 years ago (diff)

Subclass all base classes from object.

Hold references to the objects being represented (should fix #22).

The value of a mapping node is represented as a list of pairs (key, value)
now.

Sort dictionary items (fix #23).

Recursive structures are now loaded and dumped correctly, including complex
structures like recursive tuples (fix #5). Thanks Peter Murphy for the patches.
To make it possible, representer functions are allowed to be generators.
In this case, the first generated value is an object. Other values produced
by the representer are ignored.

Make Representer not try to guess !!pairs when a list is represented.
You need to construct a !!pairs node explicitly now.

Do not check for duplicate mapping keys as it didn't work correctly anyway.

RevLine 
[44]1
2import test_appliance
3
[57]4from yaml import *
[44]5
6class TestStructure(test_appliance.TestAppliance):
7
8    def _testStructure(self, test_name, data_filename, structure_filename):
9        node1 = None
10        node2 = eval(file(structure_filename, 'rb').read())
11        try:
[136]12            loader = Loader(file(data_filename, 'rb'))
[51]13            node1 = []
[136]14            while not loader.check_event(StreamEndEvent):
15                if not loader.check_event(StreamStartEvent, DocumentStartEvent, DocumentEndEvent):
16                    node1.append(self._convert(loader))
[118]17                else:
[136]18                    loader.get_event()
19            loader.get_event()
[44]20            if len(node1) == 1:
21                node1 = node1[0]
22            self.failUnlessEqual(node1, node2)
23        except:
24            print
25            print "DATA:"
26            print file(data_filename, 'rb').read()
27            print "NODE1:", node1
28            print "NODE2:", node2
29            raise
30
[136]31    def _convert(self, loader):
32        if loader.check_event(ScalarEvent):
33            event = loader.get_event()
[51]34            if event.tag or event.anchor or event.value:
35                return True
36            else:
37                return None
[136]38        elif loader.check_event(SequenceStartEvent):
39            loader.get_event()
[44]40            sequence = []
[136]41            while not loader.check_event(SequenceEndEvent):
42                sequence.append(self._convert(loader))
43            loader.get_event()
[44]44            return sequence
[136]45        elif loader.check_event(MappingStartEvent):
46            loader.get_event()
[44]47            mapping = []
[136]48            while not loader.check_event(MappingEndEvent):
49                key = self._convert(loader)
50                value = self._convert(loader)
[51]51                mapping.append((key, value))
[136]52            loader.get_event()
[44]53            return mapping
[136]54        elif loader.check_event(AliasEvent):
55            loader.get_event()
[44]56            return '*'
57        else:
[136]58            loader.get_event()
[51]59            return '?'
[44]60
61TestStructure.add_tests('testStructure', '.data', '.structure')
62
63class TestParser(test_appliance.TestAppliance):
64
65    def _testParser(self, test_name, data_filename, canonical_filename):
[51]66        events1 = None
67        events2 = None
[44]68        try:
[136]69            events1 = list(parse(file(data_filename, 'rb')))
70            events2 = list(test_appliance.canonical_parse(file(canonical_filename, 'rb')))
[51]71            self._compare(events1, events2)
[44]72        except:
73            print
74            print "DATA1:"
75            print file(data_filename, 'rb').read()
76            print "DATA2:"
77            print file(canonical_filename, 'rb').read()
[51]78            print "EVENTS1:", events1
79            print "EVENTS2:", events2
[44]80            raise
81
[51]82    def _compare(self, events1, events2):
83        self.failUnlessEqual(len(events1), len(events2))
84        for event1, event2 in zip(events1, events2):
85            self.failUnlessEqual(event1.__class__, event2.__class__)
86            if isinstance(event1, AliasEvent):
87                #self.failUnlessEqual(event1.name, event2.name)
88                pass
89            elif isinstance(event1, ScalarEvent):
90                #self.failUnlessEqual(event1.anchor, event2.anchor)
91                #self.failUnlessEqual(event1.tag, event2.tag)
92                self.failUnlessEqual(event1.value, event2.value)
[130]93            if isinstance(event1, CollectionStartEvent):
[51]94                #self.failUnlessEqual(event1.anchor, event2.anchor)
95                #self.failUnlessEqual(event1.tag, event2.tag)
96                pass
[44]97
98TestParser.add_tests('testParser', '.data', '.canonical')
99
[54]100class TestResolver(test_appliance.TestAppliance):
101
102    def _testResolver(self, test_name, data_filename, canonical_filename):
103        nodes1 = None
104        nodes2 = None
105        try:
[136]106            nodes1 = list(compose_all(file(data_filename, 'rb')))
107            nodes2 = list(test_appliance.canonical_compose_all(file(canonical_filename, 'rb')))
[54]108            self.failUnlessEqual(len(nodes1), len(nodes2))
109            for node1, node2 in zip(nodes1, nodes2):
110                self._compare(node1, node2)
111        except:
112            print
113            print "DATA1:"
114            print file(data_filename, 'rb').read()
115            print "DATA2:"
116            print file(canonical_filename, 'rb').read()
117            print "NODES1:", nodes1
118            print "NODES2:", nodes2
119            raise
120
121    def _compare(self, node1, node2):
122        self.failUnlessEqual(node1.__class__, node2.__class__)
123        if isinstance(node1, ScalarNode):
124            #self.failUnlessEqual(node1.tag, node2.tag)
125            self.failUnlessEqual(node1.value, node2.value)
126        elif isinstance(node1, SequenceNode):
127            self.failUnlessEqual(len(node1.value), len(node2.value))
128            for item1, item2 in zip(node1.value, node2.value):
129                self._compare(item1, item2)
130        elif isinstance(node1, MappingNode):
131            self.failUnlessEqual(len(node1.value), len(node2.value))
[55]132            items1 = node1.value.items()
133            items1.sort(lambda (k1,v1), (k2,v2): cmp((k1.tag,k1.value,v1.tag,v1.value),
134                                                    (k2.tag,k2.value,v2.tag,v2.value)))
135            items2 = node2.value.items()
136            items2.sort(lambda (k1,v1), (k2,v2): cmp((k1.tag,k1.value,v1.tag,v1.value),
137                                                    (k2.tag,k2.value,v2.tag,v2.value)))
138            for (key1, value1), (key2, value2) in zip(items1, items2):
[54]139                self._compare(key1, key2)
140                self._compare(value1, value2)
141
142TestResolver.add_tests('testResolver', '.data', '.canonical')
143
[146]144class MyLoader(Loader):
[55]145    def construct_sequence(self, node):
[146]146        return tuple(Loader.construct_sequence(self, node))
[55]147
148    def construct_mapping(self, node):
149        pairs = self.construct_pairs(node)
150        pairs.sort()
151        return pairs
152
[136]153    def construct_undefined(self, node):
154        return self.construct_scalar(node)
[57]155
[222]156MyLoader.add_constructor(u'tag:yaml.org,2002:map', MyLoader.construct_mapping)
[136]157MyLoader.add_constructor(None, MyLoader.construct_undefined)
158
[146]159class MyCanonicalLoader(test_appliance.CanonicalLoader):
160
161    def construct_sequence(self, node):
162        return tuple(test_appliance.CanonicalLoader.construct_sequence(self, node))
163
164    def construct_mapping(self, node):
165        pairs = self.construct_pairs(node)
166        pairs.sort()
167        return pairs
168
169    def construct_undefined(self, node):
170        return self.construct_scalar(node)
171
[222]172MyCanonicalLoader.add_constructor(u'tag:yaml.org,2002:map', MyCanonicalLoader.construct_mapping)
[136]173MyCanonicalLoader.add_constructor(None, MyCanonicalLoader.construct_undefined)
174
[55]175class TestConstructor(test_appliance.TestAppliance):
176
177    def _testConstructor(self, test_name, data_filename, canonical_filename):
[136]178        data1 = None
179        data2 = None
[55]180        try:
[136]181            data1 = list(load_all(file(data_filename, 'rb'), Loader=MyLoader))
182            data2 = list(load_all(file(canonical_filename, 'rb'), Loader=MyCanonicalLoader))
183            self.failUnlessEqual(data1, data2)
[55]184        except:
185            print
186            print "DATA1:"
187            print file(data_filename, 'rb').read()
188            print "DATA2:"
189            print file(canonical_filename, 'rb').read()
[136]190            print "NATIVES1:", data1
191            print "NATIVES2:", data2
[55]192            raise
193
194TestConstructor.add_tests('testConstructor', '.data', '.canonical')
195
[48]196class TestParserOnCanonical(test_appliance.TestAppliance):
197
198    def _testParserOnCanonical(self, test_name, canonical_filename):
[51]199        events1 = None
200        events2 = None
[48]201        try:
[136]202            events1 = list(parse(file(canonical_filename, 'rb')))
203            events2 = list(test_appliance.canonical_parse(file(canonical_filename, 'rb')))
[51]204            self._compare(events1, events2)
[48]205        except:
206            print
207            print "DATA:"
208            print file(canonical_filename, 'rb').read()
[51]209            print "EVENTS1:", events1
210            print "EVENTS2:", events2
[48]211            raise
212
[51]213    def _compare(self, events1, events2):
214        self.failUnlessEqual(len(events1), len(events2))
215        for event1, event2 in zip(events1, events2):
216            self.failUnlessEqual(event1.__class__, event2.__class__)
217            if isinstance(event1, AliasEvent):
[53]218                self.failUnlessEqual(event1.anchor, event2.anchor)
[51]219            elif isinstance(event1, ScalarEvent):
220                self.failUnlessEqual(event1.anchor, event2.anchor)
221                self.failUnlessEqual(event1.tag, event2.tag)
222                self.failUnlessEqual(event1.value, event2.value)
[130]223            if isinstance(event1, CollectionStartEvent):
[51]224                self.failUnlessEqual(event1.anchor, event2.anchor)
225                self.failUnlessEqual(event1.tag, event2.tag)
[48]226
227TestParserOnCanonical.add_tests('testParserOnCanonical', '.canonical')
228
Note: See TracBrowser for help on using the repository browser.