1
2
3 """
4 IO test cases that apply to both etree and ElementTree
5 """
6
7 import unittest
8 import tempfile, gzip, os, os.path, gc, shutil
9
10 from lxml.tests.common_imports import (
11 etree, ElementTree, _str, _bytes,
12 SillyFileLike, LargeFileLike, HelperTestCase,
13 read_file, write_to_file, BytesIO, tmpfile
14 )
15
16
18 """(c)ElementTree compatibility for IO functions/methods
19 """
20 etree = None
21
29
31 gc.collect()
32 shutil.rmtree(self._temp_dir)
33
35 return os.path.join(self._temp_dir, name)
36
46
48 Element = self.etree.Element
49 ElementTree = self.etree.ElementTree
50
51 element = Element('top')
52 element.text = _str("qwrtioüöä\uAABB")
53 tree = ElementTree(element)
54 self.buildNodes(element, 10, 3)
55 with open(self.getTestFilePath('testdump.xml'), 'wb') as f:
56 tree.write(f, encoding='UTF-8')
57 with open(self.getTestFilePath('testdump.xml'), 'rb') as f:
58 tree = ElementTree(file=f)
59 with open(self.getTestFilePath('testdump2.xml'), 'wb') as f:
60 tree.write(f, encoding='UTF-8')
61 with open(self.getTestFilePath('testdump.xml'), 'rb') as f:
62 data1 = f.read()
63 with open(self.getTestFilePath('testdump2.xml'), 'rb') as f:
64 data2 = f.read()
65 self.assertEqual(data1, data2)
66
68 Element = self.etree.Element
69 ElementTree = self.etree.ElementTree
70
71 element = Element('top')
72 element.text = _str("qwrtioüöäßá")
73 tree = ElementTree(element)
74 self.buildNodes(element, 10, 3)
75 with open(self.getTestFilePath('testdump.xml'), 'wb') as f:
76 tree.write(f, encoding='iso-8859-1')
77 with open(self.getTestFilePath('testdump.xml'), 'rb') as f:
78 tree = ElementTree(file=f)
79 with open(self.getTestFilePath('testdump2.xml'), 'wb') as f:
80 tree.write(f, encoding='iso-8859-1')
81 with open(self.getTestFilePath('testdump.xml'), 'rb') as f:
82 data1 = f.read()
83 with open(self.getTestFilePath('testdump2.xml'), 'rb') as f:
84 data2 = f.read()
85 self.assertEqual(data1, data2)
86
93
95
96 before_test = os.listdir(tempfile.gettempdir())
97
98 def difference(filenames):
99 return sorted(
100 fn for fn in set(filenames).difference(before_test)
101 if fn.startswith('lxmltmp-')
102 )
103
104 with tmpfile(prefix="lxmltmp-p%20p", suffix=".xml") as filename:
105 try:
106 before_write = os.listdir(tempfile.gettempdir())
107 self.tree.write(filename)
108 after_write = os.listdir(tempfile.gettempdir())
109 self.assertEqual(read_file(filename, 'rb').replace(b'\n', b''),
110 self.root_str)
111 except (AssertionError, IOError, OSError):
112 print("Before write: %s, after write: %s" % (
113 difference(before_write), difference(after_write))
114 )
115 raise
116
123
125 filename = os.path.join(
126 os.path.join('hopefullynonexistingpathname'),
127 'invalid_file.xml')
128 try:
129 self.tree.write(filename)
130 except IOError:
131 pass
132 else:
133 self.assertTrue(
134 False, "writing to an invalid file path should fail")
135
144
155
170
171
172
188
197
204
206 class LocalError(Exception):
207 pass
208 class TestFile:
209 def read(*args):
210 raise LocalError
211 f = TestFile()
212 self.assertRaises(LocalError, self.etree.parse, f)
213
215 class LocalError(Exception):
216 pass
217 class TestFile:
218 data = '<root>test</'
219 try:
220 next_char = iter(data).next
221 except AttributeError:
222
223 next_char = iter(data).__next__
224 counter = 0
225 def read(self, amount=None):
226 if amount is None:
227 while True:
228 self.read(1)
229 else:
230 try:
231 self.counter += 1
232 return _bytes(self.next_char())
233 except StopIteration:
234 raise LocalError
235 f = TestFile()
236 self.assertRaises(LocalError, self.etree.parse, f)
237 self.assertEqual(f.counter, len(f.data)+1)
238
240 class TestFile:
241 def read(*args):
242 return 1
243 f = TestFile()
244
245 try:
246 expect_exc = (TypeError, self.etree.ParseError)
247 except AttributeError:
248 expect_exc = TypeError
249 self.assertRaises(expect_exc, self.etree.parse, f)
250
252
253 dirnameEN = _str('Directory')
254 dirnameRU = _str('Каталог')
255 filename = _str('nosuchfile.xml')
256 dn = tempfile.mkdtemp(prefix=dirnameEN)
257 try:
258 self.assertRaises(IOError, self.etree.parse, os.path.join(dn, filename))
259 finally:
260 os.rmdir(dn)
261 dn = tempfile.mkdtemp(prefix=dirnameRU)
262 try:
263 self.assertRaises(IOError, self.etree.parse, os.path.join(dn, filename))
264 finally:
265 os.rmdir(dn)
266
268 utext = _str('Søk på nettet')
269 uxml = '<?xml version="1.0" encoding="UTF-8"?><p>%s</p>' % utext
270 bom = _bytes('\\xEF\\xBB\\xBF').decode(
271 "unicode_escape").encode("latin1")
272 self.assertEqual(3, len(bom))
273 f = tempfile.NamedTemporaryFile(delete=False)
274 try:
275 try:
276 f.write(bom)
277 f.write(uxml.encode("utf-8"))
278 finally:
279 f.close()
280 tree = self.etree.parse(f.name)
281 finally:
282 os.unlink(f.name)
283 self.assertEqual(utext, tree.getroot().text)
284
286 utext = _str('Søk på nettet')
287 uxml = '<?xml version="1.0" encoding="UTF-8"?><p>%s</p>' % utext
288 bom = _bytes('\\xEF\\xBB\\xBF').decode(
289 "unicode_escape").encode("latin1")
290 self.assertEqual(3, len(bom))
291 f = tempfile.NamedTemporaryFile(delete=False)
292 try:
293 try:
294 f.write(bom)
295 f.write(uxml.encode("utf-8"))
296 finally:
297 f.close()
298 elements = [el for _, el in self.etree.iterparse(f.name)]
299 self.assertEqual(1, len(elements))
300 root = elements[0]
301 finally:
302 os.unlink(f.name)
303 self.assertEqual(utext, root.text)
304
306 utext = _str('Søk på nettet')
307 uxml = '<?xml version="1.0" encoding="UTF-16"?><p>%s</p>' % utext
308 boms = _bytes('\\xFE\\xFF \\xFF\\xFE').decode(
309 "unicode_escape").encode("latin1")
310 self.assertEqual(5, len(boms))
311 xml = uxml.encode("utf-16")
312 self.assertTrue(xml[:2] in boms, repr(xml[:2]))
313
314 f = tempfile.NamedTemporaryFile(delete=False)
315 try:
316 try:
317 f.write(xml)
318 finally:
319 f.close()
320 elements = [el for _, el in self.etree.iterparse(f.name)]
321 self.assertEqual(1, len(elements))
322 root = elements[0]
323 finally:
324 os.unlink(f.name)
325 self.assertEqual(utext, root.text)
326
327
355
356
357 if ElementTree:
360
361
368
369
370 if __name__ == '__main__':
371 print('to test use test.py %s' % __file__)
372