Package lxml :: Package tests :: Module test_io

[hide private]
[frames] | no frames]

# Source Code for Module lxml.tests.test_io

      1  # -*- coding: utf-8 -*-
      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, sys, gc, shutil
      9
     10  this_dir = os.path.dirname(__file__)
     11  if this_dir not in sys.path:
     12      sys.path.insert(0, this_dir) # needed for Py3
     13
     14  from common_imports import etree, ElementTree, fileInTestDir, _str, _bytes
     15  from common_imports import SillyFileLike, LargeFileLike, HelperTestCase
     16  from common_imports import read_file, write_to_file
     17
     18 -class _IOTestCaseBase(HelperTestCase):
     19      """(c)ElementTree compatibility for IO functions/methods
     20      """
     21      etree = None
     22
     23 -    def setUp(self):
     24          """Setting up a minimal tree
     25          """
     26          self.root = self.etree.Element('a')
     27          self.root_str = self.etree.tostring(self.root)
     28          self.tree = self.etree.ElementTree(self.root)
     29          self._temp_dir = tempfile.mkdtemp()
     30
     31 -    def tearDown(self):
     32          gc.collect()
     33          shutil.rmtree(self._temp_dir)
     34
     35 -    def getTestFilePath(self, name):
     36          return os.path.join(self._temp_dir, name)
     37
     38 -    def buildNodes(self, element, children, depth):
     39          Element = self.etree.Element
     40
     41          if depth == 0:
     42              return
     43          for i in range(children):
     44              new_element = Element('element_%s_%s' % (depth, i))
     45              self.buildNodes(new_element, children, depth - 1)
     46              element.append(new_element)
     47
     48 -    def test_tree_io(self):
     49          Element = self.etree.Element
     50          ElementTree = self.etree.ElementTree
     51
     52          element = Element('top')
     53          element.text = _str("qwrtioüöä\uAABB")
     54          tree = ElementTree(element)
     55          self.buildNodes(element, 10, 3)
     56          f = open(self.getTestFilePath('testdump.xml'), 'wb')
     57          tree.write(f, encoding='UTF-8')
     58          f.close()
     59          f = open(self.getTestFilePath('testdump.xml'), 'rb')
     60          tree = ElementTree(file=f)
     61          f.close()
     62          f = open(self.getTestFilePath('testdump2.xml'), 'wb')
     63          tree.write(f, encoding='UTF-8')
     64          f.close()
     65          f = open(self.getTestFilePath('testdump.xml'), 'rb')
     66          data1 = f.read()
     67          f.close()
     68          f = open(self.getTestFilePath('testdump2.xml'), 'rb')
     69          data2 = f.read()
     70          f.close()
     71          self.assertEqual(data1, data2)
     72
     73 -    def test_tree_io_latin1(self):
     74          Element = self.etree.Element
     75          ElementTree = self.etree.ElementTree
     76
     77          element = Element('top')
     78          element.text = _str("qwrtioüöäßÃ¡")
     79          tree = ElementTree(element)
     80          self.buildNodes(element, 10, 3)
     81          f = open(self.getTestFilePath('testdump.xml'), 'wb')
     82          tree.write(f, encoding='iso-8859-1')
     83          f.close()
     84          f = open(self.getTestFilePath('testdump.xml'), 'rb')
     85          tree = ElementTree(file=f)
     86          f.close()
     87          f = open(self.getTestFilePath('testdump2.xml'), 'wb')
     88          tree.write(f, encoding='iso-8859-1')
     89          f.close()
     90          f = open(self.getTestFilePath('testdump.xml'), 'rb')
     91          data1 = f.read()
     92          f.close()
     93          f = open(self.getTestFilePath('testdump2.xml'), 'rb')
     94          data2 = f.read()
     95          f.close()
     96          self.assertEqual(data1, data2)
     97
     98 -    def test_write_filename(self):
     99          # (c)ElementTree  supports filename strings as write argument
    100
    101          handle, filename = tempfile.mkstemp(suffix=".xml")
    102          self.tree.write(filename)
    103          try:
    104              self.assertEqual(read_file(filename, 'rb').replace(_bytes('\n'), _bytes('')),
    105                               self.root_str)
    106          finally:
    107              os.close(handle)
    108              os.remove(filename)
    109
    110 -    def test_write_invalid_filename(self):
    111          filename = os.path.join(
    112              os.path.join('hopefullynonexistingpathname'),
    113              'invalid_file.xml')
    114          try:
    115              self.tree.write(filename)
    116          except IOError:
    117              pass
    118          else:
    119              self.assertTrue(
    120                  False, "writing to an invalid file path should fail")
    121
    122 -    def test_module_parse_gzipobject(self):
    123          # (c)ElementTree supports gzip instance as parse argument
    124          handle, filename = tempfile.mkstemp(suffix=".xml.gz")
    125          f = gzip.open(filename, 'wb')
    126          f.write(self.root_str)
    127          f.close()
    128          try:
    129              f_gz = gzip.open(filename, 'rb')
    130              tree = self.etree.parse(f_gz)
    131              f_gz.close()
    132              self.assertEqual(self.etree.tostring(tree.getroot()), self.root_str)
    133          finally:
    134              os.close(handle)
    135              os.remove(filename)
    136
    137 -    def test_class_parse_filename(self):
    138          # (c)ElementTree class ElementTree has a 'parse' method that returns
    139          # the root of the tree
    140
    141          # parse from filename
    142
    143          handle, filename = tempfile.mkstemp(suffix=".xml")
    144          write_to_file(filename, self.root_str, 'wb')
    145          try:
    146              tree = self.etree.ElementTree()
    147              root = tree.parse(filename)
    148              self.assertEqual(self.etree.tostring(root), self.root_str)
    149          finally:
    150              os.close(handle)
    151              os.remove(filename)
    152
    153 -    def test_class_parse_filename_remove_previous(self):
    154          handle, filename = tempfile.mkstemp(suffix=".xml")
    155          write_to_file(filename, self.root_str, 'wb')
    156          try:
    157              tree = self.etree.ElementTree()
    158              root = tree.parse(filename)
    159              # and now do it again; previous content should still be there
    160              root2 = tree.parse(filename)
    161              self.assertEqual('a', root.tag)
    162              self.assertEqual('a', root2.tag)
    163              # now remove all references to root2, and parse again
    164              del root2
    165              root3 = tree.parse(filename)
    166              self.assertEqual('a', root.tag)
    167              self.assertEqual('a', root3.tag)
    168              # root2's memory should've been freed here
    169              # XXX how to check?
    170          finally:
    171              os.close(handle)
    172              os.remove(filename)
    173
    174 -    def test_class_parse_fileobject(self):
    175          # (c)ElementTree class ElementTree has a 'parse' method that returns
    176          # the root of the tree
    177
    178          # parse from file object
    179
    180          handle, filename = tempfile.mkstemp(suffix=".xml")
    181          try:
    182              os.write(handle, self.root_str)
    183              f = open(filename, 'rb')
    184              tree = self.etree.ElementTree()
    185              root = tree.parse(f)
    186              f.close()
    187              self.assertEqual(self.etree.tostring(root), self.root_str)
    188          finally:
    189              os.close(handle)
    190              os.remove(filename)
    191
    192 -    def test_class_parse_unamed_fileobject(self):
    193          # (c)ElementTree class ElementTree has a 'parse' method that returns
    194          # the root of the tree
    195
    196          # parse from unamed file object
    197          f = SillyFileLike()
    198          root = self.etree.ElementTree().parse(f)
    199          self.assertTrue(root.tag.endswith('foo'))
    200
    201 -    def test_module_parse_large_fileobject(self):
    202          # parse from unamed file object
    203          f = LargeFileLike()
    204          tree = self.etree.parse(f)
    205          root = tree.getroot()
    206          self.assertTrue(root.tag.endswith('root'))
    207
    208 -    def test_module_parse_fileobject_error(self):
    209          class LocalError(Exception):
    210              pass
    211          class TestFile:
    212              def read(*args):
    213                  raise LocalError
    214          f = TestFile()
    215          self.assertRaises(LocalError, self.etree.parse, f)
    216
    217 -    def test_module_parse_fileobject_late_error(self):
    218          class LocalError(Exception):
    219              pass
    220          class TestFile:
    221              data = '<root>test</'
    222              try:
    223                  next_char = iter(data).next
    224              except AttributeError:
    225                  # Python 3
    226                  next_char = iter(data).__next__
    227              counter = 0
    228              def read(self, amount=None):
    229                  if amount is None:
    230                      while True:
    231                          self.read(1)
    232                  else:
    233                      try:
    234                          self.counter += 1
    235                          return _bytes(self.next_char())
    236                      except StopIteration:
    237                          raise LocalError
    238          f = TestFile()
    239          self.assertRaises(LocalError, self.etree.parse, f)
    240          self.assertEqual(f.counter, len(f.data)+1)
    241
    242 -    def test_module_parse_fileobject_type_error(self):
    243          class TestFile:
    244              def read(*args):
    245                  return 1
    246          f = TestFile()
    247
    248          try:
    249              expect_exc = (TypeError, self.etree.ParseError)
    250          except AttributeError:
    251              expect_exc = TypeError
    252          self.assertRaises(expect_exc, self.etree.parse, f)
    253
    254 -    def test_etree_parse_io_error(self):
    255          # this is a directory name that contains characters beyond latin-1
    256          dirnameEN = _str('Directory')
    257          dirnameRU = _str('ÐšÐ°Ñ‚Ð°Ð»Ð¾Ð³')
    258          filename = _str('nosuchfile.xml')
    259          try:
    260              dn = tempfile.mkdtemp(prefix=dirnameEN)
    261              self.assertRaises(IOError, self.etree.parse, os.path.join(dn, filename))
    262          finally:
    263              os.rmdir(dn)
    264          try:
    265              dn = tempfile.mkdtemp(prefix=dirnameRU)
    266              self.assertRaises(IOError, self.etree.parse, os.path.join(dn, filename))
    267          finally:
    268              os.rmdir(dn)
    269
    270
    271 -class ETreeIOTestCase(_IOTestCaseBase):
    272      etree = etree
    273
    274  if ElementTree:
    275 -    class ElementTreeIOTestCase(_IOTestCaseBase):
    276          etree = ElementTree
    277
    278 -def test_suite():
    279      suite = unittest.TestSuite()
    280      suite.addTests([unittest.makeSuite(ETreeIOTestCase)])
    281      if ElementTree:
    282          suite.addTests([unittest.makeSuite(ElementTreeIOTestCase)])
    283      return suite
    284
    285  if __name__ == '__main__':
    286      print('to test use test.py %s' % __file__)
    287