123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356 |
- from __future__ import absolute_import
- """
- Tests for the incremental XML serialisation API.
- Adapted from the tests from lxml.etree.xmlfile
- """
- try:
- import lxml
- except ImportError:
- raise ImportError("lxml is required to run the tests.")
- from io import BytesIO
- import unittest
- import tempfile, os, sys
- from .common_imports import HelperTestCase, skipIf
- from et_xmlfile import xmlfile
- from et_xmlfile.xmlfile import LxmlSyntaxError
- import pytest
- from .helper import compare_xml
- import xml.etree.ElementTree
- from xml.etree.ElementTree import Element, parse
- class _XmlFileTestCaseBase(HelperTestCase):
- _file = None # to be set by specific subtypes below
- def setUp(self):
- self._file = BytesIO()
- def test_element(self):
- with xmlfile(self._file) as xf:
- with xf.element('test'):
- pass
- self.assertXml('<test></test>')
- def test_element_write_text(self):
- with xmlfile(self._file) as xf:
- with xf.element('test'):
- xf.write('toast')
- self.assertXml('<test>toast</test>')
- def test_element_nested(self):
- with xmlfile(self._file) as xf:
- with xf.element('test'):
- with xf.element('toast'):
- with xf.element('taste'):
- xf.write('conTent')
- self.assertXml('<test><toast><taste>conTent</taste></toast></test>')
- def test_element_nested_with_text(self):
- with xmlfile(self._file) as xf:
- with xf.element('test'):
- xf.write('con')
- with xf.element('toast'):
- xf.write('tent')
- with xf.element('taste'):
- xf.write('inside')
- xf.write('tnet')
- xf.write('noc')
- self.assertXml('<test>con<toast>tent<taste>inside</taste>'
- 'tnet</toast>noc</test>')
- def test_write_Element(self):
- with xmlfile(self._file) as xf:
- xf.write(Element('test'))
- self.assertXml('<test/>')
- def test_write_Element_repeatedly(self):
- element = Element('test')
- with xmlfile(self._file) as xf:
- with xf.element('test'):
- for i in range(100):
- xf.write(element)
- tree = self._parse_file()
- self.assertTrue(tree is not None)
- self.assertEqual(100, len(tree.getroot()))
- self.assertEqual(set(['test']), set(el.tag for el in tree.getroot()))
- def test_namespace_nsmap(self):
- with xmlfile(self._file) as xf:
- with xf.element('{nsURI}test', nsmap={'x': 'nsURI'}):
- pass
- self.assertXml('<x:test xmlns:x="nsURI"></x:test>')
- def test_namespace_nested_nsmap(self):
- with xmlfile(self._file) as xf:
- with xf.element('test', nsmap={'x': 'nsURI'}):
- with xf.element('{nsURI}toast'):
- pass
- self.assertXml('<test xmlns:x="nsURI"><x:toast></x:toast></test>')
- def test_anonymous_namespace(self):
- with xmlfile(self._file) as xf:
- with xf.element('{nsURI}test'):
- pass
- self.assertXml('<ns0:test xmlns:ns0="nsURI"></ns0:test>')
- def test_namespace_nested_anonymous(self):
- with xmlfile(self._file) as xf:
- with xf.element('test'):
- with xf.element('{nsURI}toast'):
- pass
- self.assertXml('<test><ns0:toast xmlns:ns0="nsURI"></ns0:toast></test>')
- def test_default_namespace(self):
- with xmlfile(self._file) as xf:
- with xf.element('{nsURI}test', nsmap={None: 'nsURI'}):
- pass
- self.assertXml('<test xmlns="nsURI"></test>')
- def test_nested_default_namespace(self):
- with xmlfile(self._file) as xf:
- with xf.element('{nsURI}test', nsmap={None: 'nsURI'}):
- with xf.element('{nsURI}toast'):
- pass
- self.assertXml('<test xmlns="nsURI"><toast></toast></test>')
- @pytest.mark.xfail
- def test_pi(self):
- from et_xmlfile.xmlfile import ProcessingInstruction
- with xmlfile(self._file) as xf:
- xf.write(ProcessingInstruction('pypi'))
- with xf.element('test'):
- pass
- self.assertXml('<?pypi ?><test></test>')
- @pytest.mark.xfail
- def test_comment(self):
- with xmlfile(self._file) as xf:
- xf.write(etree.Comment('a comment'))
- with xf.element('test'):
- pass
- self.assertXml('<!--a comment--><test></test>')
- def test_attribute(self):
- with xmlfile(self._file) as xf:
- with xf.element('test', attrib={'k': 'v'}):
- pass
- self.assertXml('<test k="v"></test>')
- def test_escaping(self):
- with xmlfile(self._file) as xf:
- with xf.element('test'):
- xf.write('Comments: <!-- text -->\n')
- xf.write('Entities: &')
- self.assertXml(
- '<test>Comments: <!-- text -->\nEntities: &amp;</test>')
- @pytest.mark.xfail
- def test_encoding(self):
- with xmlfile(self._file, encoding='utf16') as xf:
- with xf.element('test'):
- xf.write('toast')
- self.assertXml('<test>toast</test>', encoding='utf16')
- @pytest.mark.xfail
- def test_buffering(self):
- with xmlfile(self._file, buffered=False) as xf:
- with xf.element('test'):
- self.assertXml("<test>")
- xf.write('toast')
- self.assertXml("<test>toast")
- with xf.element('taste'):
- self.assertXml("<test>toast<taste>")
- xf.write('some', etree.Element("more"), "toast")
- self.assertXml("<test>toast<taste>some<more/>toast")
- self.assertXml("<test>toast<taste>some<more/>toast</taste>")
- xf.write('end')
- self.assertXml("<test>toast<taste>some<more/>toast</taste>end")
- self.assertXml("<test>toast<taste>some<more/>toast</taste>end</test>")
- self.assertXml("<test>toast<taste>some<more/>toast</taste>end</test>")
- @pytest.mark.xfail
- def test_flush(self):
- with xmlfile(self._file, buffered=True) as xf:
- with xf.element('test'):
- self.assertXml("")
- xf.write('toast')
- self.assertXml("")
- with xf.element('taste'):
- self.assertXml("")
- xf.flush()
- self.assertXml("<test>toast<taste>")
- self.assertXml("<test>toast<taste>")
- self.assertXml("<test>toast<taste>")
- self.assertXml("<test>toast<taste></taste></test>")
- def test_failure_preceding_text(self):
- try:
- with xmlfile(self._file) as xf:
- xf.write('toast')
- except LxmlSyntaxError:
- self.assertTrue(True)
- else:
- self.assertTrue(False)
- def test_failure_trailing_text(self):
- with xmlfile(self._file) as xf:
- with xf.element('test'):
- pass
- try:
- xf.write('toast')
- except LxmlSyntaxError:
- self.assertTrue(True)
- else:
- self.assertTrue(False)
- def test_failure_trailing_Element(self):
- with xmlfile(self._file) as xf:
- with xf.element('test'):
- pass
- try:
- xf.write(Element('test'))
- except LxmlSyntaxError:
- self.assertTrue(True)
- else:
- self.assertTrue(False)
- @pytest.mark.xfail
- def test_closing_out_of_order_in_error_case(self):
- cm_exit = None
- try:
- with xmlfile(self._file) as xf:
- x = xf.element('test')
- cm_exit = x.__exit__
- x.__enter__()
- raise ValueError('123')
- except ValueError:
- self.assertTrue(cm_exit)
- try:
- cm_exit(ValueError, ValueError("huhu"), None)
- except LxmlSyntaxError:
- self.assertTrue(True)
- else:
- self.assertTrue(False)
- else:
- self.assertTrue(False)
- def _read_file(self):
- pos = self._file.tell()
- self._file.seek(0)
- try:
- return self._file.read()
- finally:
- self._file.seek(pos)
- def _parse_file(self):
- pos = self._file.tell()
- self._file.seek(0)
- try:
- return parse(self._file)
- finally:
- self._file.seek(pos)
- def tearDown(self):
- if self._file is not None:
- self._file.close()
- def assertXml(self, expected, encoding='utf8'):
- diff = compare_xml(self._read_file().decode(encoding), expected)
- assert diff is None, diff
- class BytesIOXmlFileTestCase(_XmlFileTestCaseBase):
- def setUp(self):
- self._file = BytesIO()
- def test_filelike_close(self):
- with xmlfile(self._file, close=True) as xf:
- with xf.element('test'):
- pass
- self.assertRaises(ValueError, self._file.getvalue)
- class TempXmlFileTestCase(_XmlFileTestCaseBase):
- def setUp(self):
- self._file = tempfile.TemporaryFile()
- class TempPathXmlFileTestCase(_XmlFileTestCaseBase):
- def setUp(self):
- self._tmpfile = tempfile.NamedTemporaryFile(delete=False)
- self._file = self._tmpfile.name
- def tearDown(self):
- try:
- self._tmpfile.close()
- finally:
- if os.path.exists(self._tmpfile.name):
- os.unlink(self._tmpfile.name)
- def _read_file(self):
- self._tmpfile.seek(0)
- return self._tmpfile.read()
- def _parse_file(self):
- self._tmpfile.seek(0)
- return parse(self._tmpfile)
- @skipIf(True, "temp file behaviour is too platform specific here")
- def test_buffering(self):
- pass
- @skipIf(True, "temp file behaviour is too platform specific here")
- def test_flush(self):
- pass
- class SimpleFileLikeXmlFileTestCase(_XmlFileTestCaseBase):
- class SimpleFileLike(object):
- def __init__(self, target):
- self._target = target
- self.write = target.write
- self.tell = target.tell
- self.seek = target.seek
- self.closed = False
- def close(self):
- assert not self.closed
- self.closed = True
- self._target.close()
- def setUp(self):
- self._target = BytesIO()
- self._file = self.SimpleFileLike(self._target)
- def _read_file(self):
- return self._target.getvalue()
- def _parse_file(self):
- pos = self._file.tell()
- self._target.seek(0)
- try:
- return parse(self._target)
- finally:
- self._target.seek(pos)
- def test_filelike_not_closing(self):
- with xmlfile(self._file) as xf:
- with xf.element('test'):
- pass
- self.assertFalse(self._file.closed)
- def test_filelike_close(self):
- with xmlfile(self._file, close=True) as xf:
- with xf.element('test'):
- pass
- self.assertTrue(self._file.closed)
- self._file = None # prevent closing in tearDown()
|