Package lxml :: Package tests :: Module test_incremental_xmlfile |
[hide private]
[frames] | no frames]

# Source Code for Module lxml.tests.test_incremental_xmlfile

      1  # -*- coding: utf-8 -*-
      2
      3  """
      4  Tests for the incremental XML serialisation API.
      5
      6  Tests require Python 2.5 or later.
      7  """
      8
      9  from __future__ import with_statement
     10
     11  import unittest
     12  import tempfile, os, sys
     13
     14  this_dir = os.path.dirname(__file__)
     15  if this_dir not in sys.path:
     16      sys.path.insert(0, this_dir) # needed for Py3
     17
     18  from common_imports import etree, BytesIO, HelperTestCase, skipIf
     19
     20 -class _XmlFileTestCaseBase(HelperTestCase):
     21      _file = None  # to be set by specific subtypes below
     22
     23 -    def test_element(self):
     24          with etree.xmlfile(self._file) as xf:
     25              with xf.element('test'):
     26                  pass
     27          self.assertXml('<test></test>')
     28
     29 -    def test_element_write_text(self):
     30          with etree.xmlfile(self._file) as xf:
     31              with xf.element('test'):
     32                  xf.write('toast')
     33          self.assertXml('<test>toast</test>')
     34
     35 -    def test_element_nested(self):
     36          with etree.xmlfile(self._file) as xf:
     37              with xf.element('test'):
     38                  with xf.element('toast'):
     39                      with xf.element('taste'):
     40                          xf.write('conTent')
     41          self.assertXml('<test><toast><taste>conTent</taste></toast></test>')
     42
     43 -    def test_element_nested_with_text(self):
     44          with etree.xmlfile(self._file) as xf:
     45              with xf.element('test'):
     46                  xf.write('con')
     47                  with xf.element('toast'):
     48                      xf.write('tent')
     49                      with xf.element('taste'):
     50                          xf.write('inside')
     51                      xf.write('tnet')
     52                  xf.write('noc')
     53          self.assertXml('<test>con<toast>tent<taste>inside</taste>'
     54                         'tnet</toast>noc</test>')
     55
     56 -    def test_write_Element(self):
     57          with etree.xmlfile(self._file) as xf:
     58              xf.write(etree.Element('test'))
     59          self.assertXml('<test/>')
     60
     61 -    def test_write_Element_repeatedly(self):
     62          element = etree.Element('test')
     63          with etree.xmlfile(self._file) as xf:
     64              with xf.element('test'):
     65                  for i in range(100):
     66                      xf.write(element)
     67
     68          tree = self._parse_file()
     69          self.assertTrue(tree is not None)
     70          self.assertEqual(100, len(tree.getroot()))
     71          self.assertEqual(set(['test']), set(el.tag for el in tree.getroot()))
     72
     73 -    def test_namespace_nsmap(self):
     74          with etree.xmlfile(self._file) as xf:
     75              with xf.element('{nsURI}test', nsmap={'x': 'nsURI'}):
     76                  pass
     77          self.assertXml('<x:test xmlns:x="nsURI"></x:test>')
     78
     79 -    def test_namespace_nested_nsmap(self):
     80          with etree.xmlfile(self._file) as xf:
     81              with xf.element('test', nsmap={'x': 'nsURI'}):
     82                  with xf.element('{nsURI}toast'):
     83                      pass
     84          self.assertXml('<test xmlns:x="nsURI"><x:toast></x:toast></test>')
     85
     86 -    def test_anonymous_namespace(self):
     87          with etree.xmlfile(self._file) as xf:
     88              with xf.element('{nsURI}test'):
     89                  pass
     90          self.assertXml('<ns0:test xmlns:ns0="nsURI"></ns0:test>')
     91
     92 -    def test_namespace_nested_anonymous(self):
     93          with etree.xmlfile(self._file) as xf:
     94              with xf.element('test'):
     95                  with xf.element('{nsURI}toast'):
     96                      pass
     97          self.assertXml('<test><ns0:toast xmlns:ns0="nsURI"></ns0:toast></test>')
     98
     99 -    def test_default_namespace(self):
    100          with etree.xmlfile(self._file) as xf:
    101              with xf.element('{nsURI}test', nsmap={None: 'nsURI'}):
    102                  pass
    103          self.assertXml('<test xmlns="nsURI"></test>')
    104
    105 -    def test_nested_default_namespace(self):
    106          with etree.xmlfile(self._file) as xf:
    107              with xf.element('{nsURI}test', nsmap={None: 'nsURI'}):
    108                  with xf.element('{nsURI}toast'):
    109                      pass
    110          self.assertXml('<test xmlns="nsURI"><toast></toast></test>')
    111
    112 -    def test_pi(self):
    113          with etree.xmlfile(self._file) as xf:
    114              xf.write(etree.ProcessingInstruction('pypi'))
    115              with xf.element('test'):
    116                  pass
    117          self.assertXml('<?pypi ?><test></test>')
    118
    119 -    def test_comment(self):
    120          with etree.xmlfile(self._file) as xf:
    121              xf.write(etree.Comment('a comment'))
    122              with xf.element('test'):
    123                  pass
    124          self.assertXml('<!--a comment--><test></test>')
    125
    126 -    def test_attribute(self):
    127          with etree.xmlfile(self._file) as xf:
    128              with xf.element('test', attrib={'k': 'v'}):
    129                  pass
    130          self.assertXml('<test k="v"></test>')
    131
    132 -    def test_escaping(self):
    133          with etree.xmlfile(self._file) as xf:
    134              with xf.element('test'):
    135                  xf.write('Comments: <!-- text -->\n')
    136                  xf.write('Entities: &amp;')
    137          self.assertXml(
    138              '<test>Comments: &lt;!-- text --&gt;\nEntities: &amp;amp;</test>')
    139
    140 -    def test_encoding(self):
    141          with etree.xmlfile(self._file, encoding='utf16') as xf:
    142              with xf.element('test'):
    143                  xf.write('toast')
    144          self.assertXml('<test>toast</test>', encoding='utf16')
    145
    146 -    def test_buffering(self):
    147          with etree.xmlfile(self._file, buffered=False) as xf:
    148              with xf.element('test'):
    149                  self.assertXml("<test>")
    150                  xf.write('toast')
    151                  self.assertXml("<test>toast")
    152                  with xf.element('taste'):
    153                      self.assertXml("<test>toast<taste>")
    154                      xf.write('some', etree.Element("more"), "toast")
    155                      self.assertXml("<test>toast<taste>some<more/>toast")
    156                  self.assertXml("<test>toast<taste>some<more/>toast</taste>")
    157                  xf.write('end')
    158                  self.assertXml("<test>toast<taste>some<more/>toast</taste>end")
    159              self.assertXml("<test>toast<taste>some<more/>toast</taste>end</test>")
    160          self.assertXml("<test>toast<taste>some<more/>toast</taste>end</test>")
    161
    162 -    def test_flush(self):
    163          with etree.xmlfile(self._file, buffered=True) as xf:
    164              with xf.element('test'):
    165                  self.assertXml("")
    166                  xf.write('toast')
    167                  self.assertXml("")
    168                  with xf.element('taste'):
    169                      self.assertXml("")
    170                      xf.flush()
    171                      self.assertXml("<test>toast<taste>")
    172                  self.assertXml("<test>toast<taste>")
    173              self.assertXml("<test>toast<taste>")
    174          self.assertXml("<test>toast<taste></taste></test>")
    175
    176 -    def test_failure_preceding_text(self):
    177          try:
    178              with etree.xmlfile(self._file) as xf:
    179                  xf.write('toast')
    180          except etree.LxmlSyntaxError:
    181              self.assertTrue(True)
    182          else:
    183              self.assertTrue(False)
    184
    185 -    def test_failure_trailing_text(self):
    186          with etree.xmlfile(self._file) as xf:
    187              with xf.element('test'):
    188                  pass
    189              try:
    190                  xf.write('toast')
    191              except etree.LxmlSyntaxError:
    192                  self.assertTrue(True)
    193              else:
    194                  self.assertTrue(False)
    195
    196 -    def test_failure_trailing_Element(self):
    197          with etree.xmlfile(self._file) as xf:
    198              with xf.element('test'):
    199                  pass
    200              try:
    201                  xf.write(etree.Element('test'))
    202              except etree.LxmlSyntaxError:
    203                  self.assertTrue(True)
    204              else:
    205                  self.assertTrue(False)
    206
    207 -    def test_closing_out_of_order_in_error_case(self):
    208          cm_exit = None
    209          try:
    210              with etree.xmlfile(self._file) as xf:
    211                  x = xf.element('test')
    212                  cm_exit = x.__exit__
    213                  x.__enter__()
    214                  raise ValueError('123')
    215          except ValueError:
    216              self.assertTrue(cm_exit)
    217              try:
    218                  cm_exit(ValueError, ValueError("huhu"), None)
    219              except etree.LxmlSyntaxError:
    220                  self.assertTrue(True)
    221              else:
    222                  self.assertTrue(False)
    223          else:
    224              self.assertTrue(False)
    225
    226 -    def _read_file(self):
    227          pos = self._file.tell()
    228          self._file.seek(0)
    229          try:
    230              return self._file.read()
    231          finally:
    232              self._file.seek(pos)
    233
    234 -    def _parse_file(self):
    235          pos = self._file.tell()
    236          self._file.seek(0)
    237          try:
    238              return etree.parse(self._file)
    239          finally:
    240              self._file.seek(pos)
    241
    242 -    def tearDown(self):
    243          if self._file is not None:
    244              self._file.close()
    245
    246 -    def assertXml(self, expected, encoding='utf8'):
    247          self.assertEqual(self._read_file().decode(encoding), expected)
    248
    249
    250 -class BytesIOXmlFileTestCase(_XmlFileTestCaseBase):
    251 -    def setUp(self):
    252          self._file = BytesIO()
    253
    254 -    def test_filelike_close(self):
    255          with etree.xmlfile(self._file, close=True) as xf:
    256              with xf.element('test'):
    257                  pass
    258          self.assertRaises(ValueError, self._file.getvalue)
    259
    260
    261 -class TempXmlFileTestCase(_XmlFileTestCaseBase):
    262 -    def setUp(self):
    263          self._file = tempfile.TemporaryFile()
    264
    265
    266 -class TempPathXmlFileTestCase(_XmlFileTestCaseBase):
    267 -    def setUp(self):
    268          self._tmpfile = tempfile.NamedTemporaryFile()
    269          self._file = self._tmpfile.name
    270
    271 -    def tearDown(self):
    272          try:
    273              self._tmpfile.close()
    274          finally:
    275              if os.path.exists(self._tmpfile.name):
    276                  os.unlink(self._tmpfile.name)
    277
    278 -    def _read_file(self):
    279          self._tmpfile.seek(0)
    280          return self._tmpfile.read()
    281
    282 -    def _parse_file(self):
    283          self._tmpfile.seek(0)
    284          return etree.parse(self._tmpfile)
    285
    286      @skipIf(True, "temp file behaviour is too platform specific here")
    287 -    def test_buffering(self):
    288          pass
    289
    290      @skipIf(True, "temp file behaviour is too platform specific here")
    291 -    def test_flush(self):
    292          pass
    293
    294
    295 -class SimpleFileLikeXmlFileTestCase(_XmlFileTestCaseBase):
    296 -    class SimpleFileLike(object):
    297 -        def __init__(self, target):
    298              self._target = target
    299              self.write = target.write
    300              self.tell = target.tell
    301              self.seek = target.seek
    302              self.closed = False
    303
    304 -        def close(self):
    305              assert not self.closed
    306              self.closed = True
    307              self._target.close()
    308
    309 -    def setUp(self):
    310          self._target = BytesIO()
    311          self._file = self.SimpleFileLike(self._target)
    312
    313 -    def _read_file(self):
    314          return self._target.getvalue()
    315
    316 -    def _parse_file(self):
    317          pos = self._file.tell()
    318          self._target.seek(0)
    319          try:
    320              return etree.parse(self._target)
    321          finally:
    322              self._target.seek(pos)
    323
    324 -    def test_filelike_not_closing(self):
    325          with etree.xmlfile(self._file) as xf:
    326              with xf.element('test'):
    327                  pass
    328          self.assertFalse(self._file.closed)
    329
    330 -    def test_filelike_close(self):
    331          with etree.xmlfile(self._file, close=True) as xf:
    332              with xf.element('test'):
    333                  pass
    334          self.assertTrue(self._file.closed)
    335          self._file = None  # prevent closing in tearDown()
    336
    337
    338 -class HtmlFileTestCase(_XmlFileTestCaseBase):
    339 -    def setUp(self):
    340          self._file = BytesIO()
    341
    342 -    def test_void_elements(self):
    343          # http://www.w3.org/TR/html5/syntax.html#elements-0
    344          void_elements = set([
    345              "area", "base", "br", "col", "embed", "hr", "img",
    346              "input", "keygen", "link", "meta", "param",
    347              "source", "track", "wbr"
    348          ])
    349
    350          # FIXME: These don't get serialized as void elements.
    351          void_elements.difference_update([
    352              'area', 'embed', 'keygen', 'source', 'track', 'wbr'
    353          ])
    354
    355          for tag in sorted(void_elements):
    356              with etree.htmlfile(self._file) as xf:
    357                  xf.write(etree.Element(tag))
    358              self.assertXml('<%s>' % tag)
    359              self._file = BytesIO()
    360
    361 -    def test_write_declaration(self):
    362          with etree.htmlfile(self._file) as xf:
    363              try:
    364                  xf.write_declaration()
    365              except etree.LxmlSyntaxError:
    366                  self.assertTrue(True)
    367              else:
    368                  self.assertTrue(False)
    369              xf.write(etree.Element('html'))
    370
    371 -    def test_write_namespaced_element(self):
    372          with etree.htmlfile(self._file) as xf:
    373              xf.write(etree.Element('{some_ns}some_tag'))
    374          self.assertXml('<ns0:some_tag xmlns:ns0="some_ns"></ns0:some_tag>')
    375
    376 -    def test_open_namespaced_element(self):
    377          with etree.htmlfile(self._file) as xf:
    378              with xf.element("{some_ns}some_tag"):
    379                  pass
    380          self.assertXml('<ns0:some_tag xmlns:ns0="some_ns"></ns0:some_tag>')
    381
    382
    383 -def test_suite():
    384      suite = unittest.TestSuite()
    385      suite.addTests([unittest.makeSuite(BytesIOXmlFileTestCase),
    386                      unittest.makeSuite(TempXmlFileTestCase),
    387                      unittest.makeSuite(TempPathXmlFileTestCase),
    388                      unittest.makeSuite(SimpleFileLikeXmlFileTestCase),
    389                      unittest.makeSuite(HtmlFileTestCase),
    390                      ])
    391      return suite
    392
    393  if __name__ == '__main__':
    394      print('to test use test.py %s' % __file__)
    395