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_nested_default_namespace_and_other(self):
    113          with etree.xmlfile(self._file) as xf:
    114              with xf.element('{nsURI}test', nsmap={None: 'nsURI', 'p': 'ns2'}):
    115                  with xf.element('{nsURI}toast'):
    116                      pass
    117                  with xf.element('{ns2}toast'):
    118                      pass
    119          self.assertXml(
    120              '<test xmlns="nsURI" xmlns:p="ns2"><toast></toast><p:toast></p:toast></test>')
    121
    122 -    def test_pi(self):
    123          with etree.xmlfile(self._file) as xf:
    124              xf.write(etree.ProcessingInstruction('pypi'))
    125              with xf.element('test'):
    126                  pass
    127          self.assertXml('<?pypi ?><test></test>')
    128
    129 -    def test_comment(self):
    130          with etree.xmlfile(self._file) as xf:
    131              xf.write(etree.Comment('a comment'))
    132              with xf.element('test'):
    133                  pass
    134          self.assertXml('<!--a comment--><test></test>')
    135
    136 -    def test_attribute(self):
    137          with etree.xmlfile(self._file) as xf:
    138              with xf.element('test', attrib={'k': 'v'}):
    139                  pass
    140          self.assertXml('<test k="v"></test>')
    141
    142 -    def test_escaping(self):
    143          with etree.xmlfile(self._file) as xf:
    144              with xf.element('test'):
    145                  xf.write('Comments: <!-- text -->\n')
    146                  xf.write('Entities: &amp;')
    147          self.assertXml(
    148              '<test>Comments: &lt;!-- text --&gt;\nEntities: &amp;amp;</test>')
    149
    150 -    def test_encoding(self):
    151          with etree.xmlfile(self._file, encoding='utf16') as xf:
    152              with xf.element('test'):
    153                  xf.write('toast')
    154          self.assertXml('<test>toast</test>', encoding='utf16')
    155
    156 -    def test_buffering(self):
    157          with etree.xmlfile(self._file, buffered=False) as xf:
    158              with xf.element('test'):
    159                  self.assertXml("<test>")
    160                  xf.write('toast')
    161                  self.assertXml("<test>toast")
    162                  with xf.element('taste'):
    163                      self.assertXml("<test>toast<taste>")
    164                      xf.write('some', etree.Element("more"), "toast")
    165                      self.assertXml("<test>toast<taste>some<more/>toast")
    166                  self.assertXml("<test>toast<taste>some<more/>toast</taste>")
    167                  xf.write('end')
    168                  self.assertXml("<test>toast<taste>some<more/>toast</taste>end")
    169              self.assertXml("<test>toast<taste>some<more/>toast</taste>end</test>")
    170          self.assertXml("<test>toast<taste>some<more/>toast</taste>end</test>")
    171
    172 -    def test_flush(self):
    173          with etree.xmlfile(self._file, buffered=True) as xf:
    174              with xf.element('test'):
    175                  self.assertXml("")
    176                  xf.write('toast')
    177                  self.assertXml("")
    178                  with xf.element('taste'):
    179                      self.assertXml("")
    180                      xf.flush()
    181                      self.assertXml("<test>toast<taste>")
    182                  self.assertXml("<test>toast<taste>")
    183              self.assertXml("<test>toast<taste>")
    184          self.assertXml("<test>toast<taste></taste></test>")
    185
    186 -    def test_failure_preceding_text(self):
    187          try:
    188              with etree.xmlfile(self._file) as xf:
    189                  xf.write('toast')
    190          except etree.LxmlSyntaxError:
    191              self.assertTrue(True)
    192          else:
    193              self.assertTrue(False)
    194
    195 -    def test_failure_trailing_text(self):
    196          with etree.xmlfile(self._file) as xf:
    197              with xf.element('test'):
    198                  pass
    199              try:
    200                  xf.write('toast')
    201              except etree.LxmlSyntaxError:
    202                  self.assertTrue(True)
    203              else:
    204                  self.assertTrue(False)
    205
    206 -    def test_failure_trailing_Element(self):
    207          with etree.xmlfile(self._file) as xf:
    208              with xf.element('test'):
    209                  pass
    210              try:
    211                  xf.write(etree.Element('test'))
    212              except etree.LxmlSyntaxError:
    213                  self.assertTrue(True)
    214              else:
    215                  self.assertTrue(False)
    216
    217 -    def test_closing_out_of_order_in_error_case(self):
    218          cm_exit = None
    219          try:
    220              with etree.xmlfile(self._file) as xf:
    221                  x = xf.element('test')
    222                  cm_exit = x.__exit__
    223                  x.__enter__()
    224                  raise ValueError('123')
    225          except ValueError:
    226              self.assertTrue(cm_exit)
    227              try:
    228                  cm_exit(ValueError, ValueError("huhu"), None)
    229              except etree.LxmlSyntaxError:
    230                  self.assertTrue(True)
    231              else:
    232                  self.assertTrue(False)
    233          else:
    234              self.assertTrue(False)
    235
    236 -    def _read_file(self):
    237          pos = self._file.tell()
    238          self._file.seek(0)
    239          try:
    240              return self._file.read()
    241          finally:
    242              self._file.seek(pos)
    243
    244 -    def _parse_file(self):
    245          pos = self._file.tell()
    246          self._file.seek(0)
    247          try:
    248              return etree.parse(self._file)
    249          finally:
    250              self._file.seek(pos)
    251
    252 -    def tearDown(self):
    253          if self._file is not None:
    254              self._file.close()
    255
    256 -    def assertXml(self, expected, encoding='utf8'):
    257          self.assertEqual(self._read_file().decode(encoding), expected)
    258
    259
    260 -class BytesIOXmlFileTestCase(_XmlFileTestCaseBase):
    261 -    def setUp(self):
    262          self._file = BytesIO()
    263
    264 -    def test_filelike_close(self):
    265          with etree.xmlfile(self._file, close=True) as xf:
    266              with xf.element('test'):
    267                  pass
    268          self.assertRaises(ValueError, self._file.getvalue)
    269
    270
    271 -class TempXmlFileTestCase(_XmlFileTestCaseBase):
    272 -    def setUp(self):
    273          self._file = tempfile.TemporaryFile()
    274
    275
    276 -class TempPathXmlFileTestCase(_XmlFileTestCaseBase):
    277 -    def setUp(self):
    278          self._tmpfile = tempfile.NamedTemporaryFile()
    279          self._file = self._tmpfile.name
    280
    281 -    def tearDown(self):
    282          try:
    283              self._tmpfile.close()
    284          finally:
    285              if os.path.exists(self._tmpfile.name):
    286                  os.unlink(self._tmpfile.name)
    287
    288 -    def _read_file(self):
    289          self._tmpfile.seek(0)
    290          return self._tmpfile.read()
    291
    292 -    def _parse_file(self):
    293          self._tmpfile.seek(0)
    294          return etree.parse(self._tmpfile)
    295
    296      @skipIf(True, "temp file behaviour is too platform specific here")
    297 -    def test_buffering(self):
    298          pass
    299
    300      @skipIf(True, "temp file behaviour is too platform specific here")
    301 -    def test_flush(self):
    302          pass
    303
    304
    305 -class SimpleFileLikeXmlFileTestCase(_XmlFileTestCaseBase):
    306 -    class SimpleFileLike(object):
    307 -        def __init__(self, target):
    308              self._target = target
    309              self.write = target.write
    310              self.tell = target.tell
    311              self.seek = target.seek
    312              self.closed = False
    313
    314 -        def close(self):
    315              assert not self.closed
    316              self.closed = True
    317              self._target.close()
    318
    319 -    def setUp(self):
    320          self._target = BytesIO()
    321          self._file = self.SimpleFileLike(self._target)
    322
    323 -    def _read_file(self):
    324          return self._target.getvalue()
    325
    326 -    def _parse_file(self):
    327          pos = self._file.tell()
    328          self._target.seek(0)
    329          try:
    330              return etree.parse(self._target)
    331          finally:
    332              self._target.seek(pos)
    333
    334 -    def test_filelike_not_closing(self):
    335          with etree.xmlfile(self._file) as xf:
    336              with xf.element('test'):
    337                  pass
    338          self.assertFalse(self._file.closed)
    339
    340 -    def test_filelike_close(self):
    341          with etree.xmlfile(self._file, close=True) as xf:
    342              with xf.element('test'):
    343                  pass
    344          self.assertTrue(self._file.closed)
    345          self._file = None  # prevent closing in tearDown()
    346
    347
    348 -class HtmlFileTestCase(_XmlFileTestCaseBase):
    349 -    def setUp(self):
    350          self._file = BytesIO()
    351
    352 -    def test_void_elements(self):
    353          # http://www.w3.org/TR/html5/syntax.html#elements-0
    354          void_elements = set([
    355              "area", "base", "br", "col", "embed", "hr", "img",
    356              "input", "keygen", "link", "meta", "param",
    357              "source", "track", "wbr"
    358          ])
    359
    360          # FIXME: These don't get serialized as void elements.
    361          void_elements.difference_update([
    362              'area', 'embed', 'keygen', 'source', 'track', 'wbr'
    363          ])
    364
    365          for tag in sorted(void_elements):
    366              with etree.htmlfile(self._file) as xf:
    367                  xf.write(etree.Element(tag))
    368              self.assertXml('<%s>' % tag)
    369              self._file = BytesIO()
    370
    371 -    def test_write_declaration(self):
    372          with etree.htmlfile(self._file) as xf:
    373              try:
    374                  xf.write_declaration()
    375              except etree.LxmlSyntaxError:
    376                  self.assertTrue(True)
    377              else:
    378                  self.assertTrue(False)
    379              xf.write(etree.Element('html'))
    380
    381 -    def test_write_namespaced_element(self):
    382          with etree.htmlfile(self._file) as xf:
    383              xf.write(etree.Element('{some_ns}some_tag'))
    384          self.assertXml('<ns0:some_tag xmlns:ns0="some_ns"></ns0:some_tag>')
    385
    386 -    def test_open_namespaced_element(self):
    387          with etree.htmlfile(self._file) as xf:
    388              with xf.element("{some_ns}some_tag"):
    389                  pass
    390          self.assertXml('<ns0:some_tag xmlns:ns0="some_ns"></ns0:some_tag>')
    391
    392
    393 -def test_suite():
    394      suite = unittest.TestSuite()
    395      suite.addTests([unittest.makeSuite(BytesIOXmlFileTestCase),
    396                      unittest.makeSuite(TempXmlFileTestCase),
    397                      unittest.makeSuite(TempPathXmlFileTestCase),
    398                      unittest.makeSuite(SimpleFileLikeXmlFileTestCase),
    399                      unittest.makeSuite(HtmlFileTestCase),
    400                      ])
    401      return suite
    402
    403  if __name__ == '__main__':
    404      print('to test use test.py %s' % __file__)
    405