| [7] | 1 | |
|---|
| 2 | import unittest |
|---|
| 3 | import syck |
|---|
| [16] | 4 | import test_parser |
|---|
| [9] | 5 | import os |
|---|
| [7] | 6 | |
|---|
| [9] | 7 | try: |
|---|
| 8 | import datetime |
|---|
| 9 | except ImportError: |
|---|
| 10 | pass |
|---|
| 11 | |
|---|
| 12 | try: |
|---|
| 13 | import mx.DateTime |
|---|
| 14 | except ImportError: |
|---|
| 15 | pass |
|---|
| 16 | |
|---|
| 17 | try: |
|---|
| 18 | import sets |
|---|
| 19 | except ImportError: |
|---|
| [18] | 20 | class _sets: |
|---|
| 21 | def Set(self, items): |
|---|
| 22 | set = {} |
|---|
| 23 | for items in items: |
|---|
| 24 | set[items] = None |
|---|
| 25 | return set |
|---|
| 26 | sets = _sets() |
|---|
| [9] | 27 | |
|---|
| [7] | 28 | INF = 1e300000 |
|---|
| 29 | NAN = INF/INF |
|---|
| 30 | |
|---|
| 31 | ARROW = "GIF89a\x0c\x00\x0c\x00\x84\x00\x00\xff\xff\xf7\xf5\xf5\xee\xe9\xe9\xe5fff\x00\x00\x00\xe7\xe7\xe7^^^\xf3\xf3\xed\x8e\x8e\x8e\xe0\xe0\xe0\x9f\x9f\x9f\x93\x93\x93\xa7\xa7\xa7\x9e\x9e\x9eiiiccc\xa3\xa3\xa3\x84\x84\x84\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9\xff\xfe\xf9!\xfe\x0eMade with GIMP\x00,\x00\x00\x00\x00\x0c\x00\x0c\x00\x00\x05, \x8e\x810\x9e\xe3@\x14\xe8i\x10\xc4\xd1\x8a\x08\x1c\xcf\x80M$z\xef\xff0\x85p\xb8\xb01f\r\x1b\xce\x01\xc3\x01\x1e\x10' \x82\n\x01\x00;" |
|---|
| 32 | BINARY = r""" |
|---|
| 33 | - !binary "\ |
|---|
| 34 | R0lGODlhDAAMAIQAAP//9/X17unp5WZmZgAAAOfn515eXvPz7Y6OjuDg4J+fn5\ |
|---|
| 35 | OTk6enp56enmlpaWNjY6Ojo4SEhP/++f/++f/++f/++f/++f/++f/++f/++f/+\ |
|---|
| 36 | +f/++f/++f/++f/++f/++SH+Dk1hZGUgd2l0aCBHSU1QACwAAAAADAAMAAAFLC\ |
|---|
| 37 | AgjoEwnuNAFOhpEMTRiggcz4BNJHrv/zCFcLiwMWYNG84BwwEeECcgggoBADs=" |
|---|
| 38 | - |
|---|
| 39 | !binary | |
|---|
| 40 | R0lGODlhDAAMAIQAAP//9/X17unp5WZmZgAAAOfn515eXvPz7Y6OjuDg4J+fn5 |
|---|
| 41 | OTk6enp56enmlpaWNjY6Ojo4SEhP/++f/++f/++f/++f/++f/++f/++f/++f/+ |
|---|
| 42 | +f/++f/++f/++f/++f/++SH+Dk1hZGUgd2l0aCBHSU1QACwAAAAADAAMAAAFLC |
|---|
| 43 | AgjoEwnuNAFOhpEMTRiggcz4BNJHrv/zCFcLiwMWYNG84BwwEeECcgggoBADs= |
|---|
| 44 | """ |
|---|
| 45 | |
|---|
| [8] | 46 | MERGE = """ |
|---|
| 47 | --- |
|---|
| 48 | - &CENTER { x: 1, y: 2 } |
|---|
| 49 | - &LEFT { x: 0, y: 2 } |
|---|
| 50 | - &BIG { r: 10 } |
|---|
| 51 | - &SMALL { r: 1 } |
|---|
| 52 | |
|---|
| 53 | # All the following maps are equal: |
|---|
| 54 | |
|---|
| 55 | - # Explicit keys |
|---|
| 56 | x: 1 |
|---|
| 57 | y: 2 |
|---|
| 58 | r: 10 |
|---|
| 59 | label: center/big |
|---|
| 60 | |
|---|
| 61 | - # Merge one map |
|---|
| 62 | << : *CENTER |
|---|
| 63 | r: 10 |
|---|
| 64 | label: center/big |
|---|
| 65 | |
|---|
| 66 | - # Merge multiple maps |
|---|
| 67 | << : [ *CENTER, *BIG ] |
|---|
| 68 | label: center/big |
|---|
| 69 | |
|---|
| 70 | - # Override |
|---|
| 71 | << : [ *BIG, *LEFT, *SMALL ] |
|---|
| 72 | x: 1 |
|---|
| 73 | label: center/big |
|---|
| 74 | """, { 'x': 1, 'y': 2, 'r': 10, 'label': 'center/big' } |
|---|
| 75 | |
|---|
| 76 | OMAP = """ |
|---|
| 77 | # Explicitly typed ordered map (dictionary). |
|---|
| 78 | Bestiary: !omap |
|---|
| 79 | - aardvark: African pig-like ant eater. Ugly. |
|---|
| 80 | - anteater: South-American ant eater. Two species. |
|---|
| 81 | - anaconda: South-American constrictor snake. Scaly. |
|---|
| 82 | # Etc. |
|---|
| 83 | # Flow style |
|---|
| 84 | Numbers: !omap [ one: 1, two: 2, three : 3 ] |
|---|
| 85 | """, { |
|---|
| 86 | 'Bestiary': [ |
|---|
| 87 | ('aardvark', 'African pig-like ant eater. Ugly.'), |
|---|
| 88 | ('anteater', 'South-American ant eater. Two species.'), |
|---|
| 89 | ('anaconda', 'South-American constrictor snake. Scaly.'), |
|---|
| 90 | ], |
|---|
| 91 | 'Numbers': [ |
|---|
| 92 | ('one', 1), |
|---|
| 93 | ('two', 2), |
|---|
| 94 | ('three', 3), |
|---|
| 95 | ], |
|---|
| 96 | } |
|---|
| 97 | |
|---|
| 98 | PAIRS = """ |
|---|
| 99 | # Explicitly typed pairs. |
|---|
| 100 | Block tasks: !pairs |
|---|
| 101 | - meeting: with team. |
|---|
| 102 | - meeting: with boss. |
|---|
| 103 | - break: lunch. |
|---|
| 104 | - meeting: with client. |
|---|
| 105 | Flow tasks: !pairs [ meeting: with team, meeting: with boss ] |
|---|
| 106 | """, { |
|---|
| 107 | 'Block tasks': [ |
|---|
| 108 | ('meeting', 'with team.'), |
|---|
| 109 | ('meeting', 'with boss.'), |
|---|
| 110 | ('break', 'lunch.'), |
|---|
| 111 | ('meeting', 'with client.'), |
|---|
| 112 | ], |
|---|
| 113 | 'Flow tasks': [ |
|---|
| 114 | ('meeting', 'with team'), |
|---|
| 115 | ('meeting', 'with boss'), |
|---|
| 116 | ], |
|---|
| 117 | } |
|---|
| 118 | |
|---|
| 119 | SET = """ |
|---|
| 120 | # Syck does not understand it |
|---|
| 121 | ## Explicitly typed set. |
|---|
| 122 | #baseball players: !set |
|---|
| 123 | # ? Mark McGwire |
|---|
| 124 | # ? Sammy Sosa |
|---|
| 125 | # ? Ken Griffey |
|---|
| 126 | # Flow style |
|---|
| 127 | baseball teams: !set { Boston Red Sox, Detroit Tigers, New York Yankees } |
|---|
| 128 | """, { |
|---|
| 129 | # 'baseball players': sets.Set(['Mark McGwire', 'Sammy Sosa', 'Ken Griffey']), |
|---|
| 130 | 'baseball teams': sets.Set(['Boston Red Sox', 'Detroit Tigers', 'New York Yankees']), |
|---|
| 131 | } |
|---|
| 132 | |
|---|
| [20] | 133 | ALIASES = """ |
|---|
| 134 | foo: &bar baz |
|---|
| 135 | bar: *bar |
|---|
| 136 | """ |
|---|
| 137 | |
|---|
| [22] | 138 | MUTABLE_KEY = """ |
|---|
| 139 | ? [] |
|---|
| 140 | : [] |
|---|
| 141 | """ |
|---|
| 142 | |
|---|
| [16] | 143 | class TestDocuments(test_parser.TestDocuments): |
|---|
| [7] | 144 | |
|---|
| 145 | def _testDocuments(self, source, length): |
|---|
| [16] | 146 | actual_length = len(list(syck.load_documents(source))) |
|---|
| [7] | 147 | self.assertEqual(actual_length, length) |
|---|
| [16] | 148 | actual_length = len(list(syck.parse_documents(source))) |
|---|
| [7] | 149 | self.assertEqual(actual_length, length) |
|---|
| 150 | |
|---|
| [16] | 151 | class TestValuesAndSources(test_parser.TestValuesAndSources): |
|---|
| [7] | 152 | |
|---|
| 153 | def testValues1(self): |
|---|
| [16] | 154 | self._testValues(test_parser.COMPARE1) |
|---|
| [7] | 155 | |
|---|
| 156 | def testValues2(self): |
|---|
| [16] | 157 | self._testValues(test_parser.COMPARE2) |
|---|
| [7] | 158 | |
|---|
| 159 | def testValues3(self): |
|---|
| [16] | 160 | self._testValues(test_parser.COMPARE3) |
|---|
| [7] | 161 | |
|---|
| 162 | def testFileValues1(self): |
|---|
| [16] | 163 | self._testFileValues(test_parser.COMPARE1) |
|---|
| [7] | 164 | |
|---|
| 165 | def testFileValues2(self): |
|---|
| [16] | 166 | self._testFileValues(test_parser.COMPARE2) |
|---|
| [7] | 167 | |
|---|
| 168 | def testFileValues3(self): |
|---|
| [16] | 169 | self._testFileValues(test_parser.COMPARE3) |
|---|
| [7] | 170 | |
|---|
| 171 | def testNonsense(self): |
|---|
| 172 | class MyFile1: |
|---|
| 173 | def read(self, max_length): |
|---|
| 174 | return ' '*(max_length+1) |
|---|
| 175 | class MyFile2: |
|---|
| 176 | def read(self, max_length): |
|---|
| 177 | return None |
|---|
| 178 | self.assertRaises(ValueError, lambda: syck.parse(MyFile1())) |
|---|
| 179 | self.assertRaises(ValueError, lambda: syck.load(MyFile1())) |
|---|
| 180 | self.assertRaises(TypeError, lambda: syck.parse(MyFile2())) |
|---|
| 181 | self.assertRaises(TypeError, lambda: syck.load(MyFile2())) |
|---|
| 182 | |
|---|
| 183 | def _testValues(self, (source, structure)): |
|---|
| 184 | self.assertEqualStructure(syck.parse(source), structure) |
|---|
| 185 | self.assertEqual(syck.load(source), structure) |
|---|
| 186 | |
|---|
| 187 | def _testFileValues(self, (source, structure)): |
|---|
| [22] | 188 | tempfile = os.tmpfile() |
|---|
| 189 | tempfile.write(source) |
|---|
| 190 | tempfile.seek(0) |
|---|
| [23] | 191 | self.assertEqualStructure(syck.parse(tempfile), structure) |
|---|
| 192 | tempfile.seek(0) |
|---|
| 193 | self.assertEqual(syck.load(tempfile), structure) |
|---|
| 194 | tempfile.seek(0) |
|---|
| [7] | 195 | |
|---|
| 196 | class TestImplicitScalars(unittest.TestCase): |
|---|
| 197 | |
|---|
| 198 | |
|---|
| 199 | def testBinary(self): |
|---|
| 200 | self.assertEqual(syck.load(BINARY), [ARROW, ARROW]) |
|---|
| 201 | |
|---|
| 202 | def testBoolean(self): |
|---|
| 203 | # Syck does not recognize 'y'. |
|---|
| 204 | #self.assertEqual(syck.load('- y\n- NO\n- True\n- on\n'), [True, False, True, True]) |
|---|
| 205 | self.assertEqual(syck.load('- yes\n- NO\n- True\n- on\n'), [True, False, True, True]) |
|---|
| 206 | |
|---|
| 207 | def testFloat(self): |
|---|
| [23] | 208 | self.assertEqual(syck.load('6.8523015e+5'), 685230.15) |
|---|
| [7] | 209 | # Syck does not understand '_'. |
|---|
| 210 | #self.assertAlmostEqual(syck.load('685.230_15e+03'), 685230.15) |
|---|
| 211 | #self.assertAlmostEqual(syck.load('685_230.15'), 685230.15) |
|---|
| [23] | 212 | self.assertEqual(syck.load('685.23015e+03'), 685230.15) |
|---|
| 213 | self.assertEqual(syck.load('685230.15'), 685230.15) |
|---|
| 214 | self.assertEqual(syck.load('190:20:30.15'), 685230.15) |
|---|
| 215 | self.assertEqual(repr(syck.load('-.inf')), repr(-INF)) |
|---|
| 216 | self.assertEqual(repr(syck.load('.nan')), repr(NAN)) |
|---|
| [7] | 217 | |
|---|
| 218 | def testInteger(self): |
|---|
| 219 | # Syck does not understand '_' and binary integer. |
|---|
| 220 | #self.assertEqual(syck.load( |
|---|
| 221 | # '- 685230\n- +685_230\n- 02472256\n- 0x_0A_74_AE\n' |
|---|
| 222 | # '- 0b1010_0111_0100_1010_1110\n- 190:20:30\n'), [685230]*6) |
|---|
| 223 | self.assertEqual(syck.load( |
|---|
| 224 | '- 685230\n- +685230\n- 02472256\n- 0x0A74AE\n' |
|---|
| 225 | '- 190:20:30\n'), [685230]*5) |
|---|
| 226 | |
|---|
| 227 | def testNull(self): |
|---|
| 228 | self.assertEqual(syck.load('-\n- NULL\n- ~\n'), [None]*3) |
|---|
| 229 | |
|---|
| 230 | def testTimestamp(self): |
|---|
| 231 | # Again, Syck does not understand the latest two forms. |
|---|
| 232 | #self.assertEqual(syck.load( |
|---|
| 233 | # '- 2001-12-15T02:59:43.1Z\n' |
|---|
| 234 | # '- 2001-12-14t21:59:43.10-05:00\n' |
|---|
| 235 | # '- 2001-12-14 21:59:43.10 -5\n' |
|---|
| 236 | # '- 2001-12-15 2:59:43.10\n'), |
|---|
| 237 | # [datetime.datetime(2001, 12, 15, 2, 59, 43, 100000)]*4) |
|---|
| 238 | self.assertEqual(syck.load( |
|---|
| 239 | '- 2001-12-15T02:59:43.1Z\n' |
|---|
| 240 | '- 2001-12-14t21:59:43.10-05:00\n' |
|---|
| 241 | '- 2001-12-14 21:59:43.10 -05\n' |
|---|
| 242 | '- 2001-12-15 02:59:43.10 Z\n'), |
|---|
| 243 | [datetime.datetime(2001, 12, 15, 2, 59, 43, 100000)]*4) |
|---|
| 244 | self.assertEqual(syck.load('2002-12-14'), datetime.datetime(2002, 12, 14)) |
|---|
| 245 | |
|---|
| 246 | def testString(self): |
|---|
| 247 | self.assertEqual('abcd', 'abcd') |
|---|
| 248 | |
|---|
| [8] | 249 | class TestMerge(unittest.TestCase): |
|---|
| 250 | |
|---|
| 251 | def testMerge(self): |
|---|
| 252 | document = syck.load(MERGE[0]) |
|---|
| 253 | self.assertEqual(document[4], MERGE[1]) |
|---|
| 254 | self.assertEqual(document[5], MERGE[1]) |
|---|
| 255 | self.assertEqual(document[6], MERGE[1]) |
|---|
| 256 | self.assertEqual(document[7], MERGE[1]) |
|---|
| 257 | |
|---|
| 258 | class TestCollections(unittest.TestCase): |
|---|
| 259 | |
|---|
| 260 | def testOmap(self): |
|---|
| 261 | self.assertEqual(syck.load(OMAP[0]), OMAP[1]) |
|---|
| 262 | |
|---|
| 263 | def testPairs(self): |
|---|
| 264 | self.assertEqual(syck.load(PAIRS[0]), PAIRS[1]) |
|---|
| 265 | |
|---|
| 266 | def testSet(self): |
|---|
| 267 | self.assertEqual(syck.load(SET[0]), SET[1]) |
|---|
| 268 | |
|---|
| [20] | 269 | class TestAliasesParsingAndLoading(unittest.TestCase): |
|---|
| 270 | |
|---|
| 271 | def testAliasesParsing(self): |
|---|
| 272 | node = syck.parse(ALIASES) |
|---|
| 273 | values = node.value.values() |
|---|
| 274 | self.assert_(values[0] is values[1]) |
|---|
| 275 | |
|---|
| 276 | def testAliasesLoading(self): |
|---|
| 277 | document = syck.load(ALIASES) |
|---|
| 278 | self.assert_(document['foo'] is document['bar']) |
|---|
| 279 | |
|---|
| [22] | 280 | class TestMutableKey(unittest.TestCase): |
|---|
| 281 | |
|---|
| 282 | def testMutableKey(self): |
|---|
| 283 | document = syck.load(MUTABLE_KEY) |
|---|
| 284 | self.assertEqual(type(document), list) |
|---|
| 285 | self.assertEqual(len(document), 1) |
|---|
| 286 | self.assertEqual(type(document[0]), tuple) |
|---|
| 287 | self.assertEqual(len(document[0]), 2) |
|---|
| 288 | self.assertEqual(document[0][0], document[0][1]) |
|---|