lxml.tests.common_imports

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

# Source Code for Module lxml.tests.common_imports

      1  import gc
      2  import os
      3  import os.path
      4  import re
      5  import sys
      6  import tempfile
      7  import unittest
      8  from contextlib import contextmanager
      9
     10  try:
     11      import urlparse
     12  except ImportError:
     13      import urllib.parse as urlparse
     14
     15  try:
     16      from urllib import pathname2url
     17  except:
     18      from urllib.request import pathname2url
     19
     20  from lxml import etree, html
     21
     22 -def make_version_tuple(version_string):
     23      return tuple(
     24          int(part) if part.isdigit() else part
     25          for part in re.findall('([0-9]+|[^0-9.]+)', version_string)
     26      )
     27
     28  IS_PYPY = (getattr(sys, 'implementation', None) == 'pypy' or
     29             getattr(sys, 'pypy_version_info', None) is not None)
     30
     31  IS_PYTHON3 = sys.version_info[0] >= 3
     32  IS_PYTHON2 = sys.version_info[0] < 3
     33
     34  from xml.etree import ElementTree
     35
     36  if hasattr(ElementTree, 'VERSION'):
     37      ET_VERSION = make_version_tuple(ElementTree.VERSION)
     38  else:
     39      ET_VERSION = (0,0,0)
     40
     41  if IS_PYTHON2:
     42      from xml.etree import cElementTree
     43
     44      if hasattr(cElementTree, 'VERSION'):
     45          CET_VERSION = make_version_tuple(cElementTree.VERSION)
     46      else:
     47          CET_VERSION = (0,0,0)
     48  else:
     49      CET_VERSION = (0, 0, 0)
     50      cElementTree = None
     51
     52
     53 -def filter_by_version(test_class, version_dict, current_version):
     54      """Remove test methods that do not work with the current lib version.
     55      """
     56      find_required_version = version_dict.get
     57      def dummy_test_method(self):
     58          pass
     59      for name in dir(test_class):
     60          expected_version = find_required_version(name, (0,0,0))
     61          if expected_version > current_version:
     62              setattr(test_class, name, dummy_test_method)
     63
     64  import doctest
     65
     66  try:
     67      next
     68  except NameError:
     69 -    def next(it):
     70          return it.next()
     71  else:
     72      locals()['next'] = next
     73
     74
     75  try:
     76      import pytest
     77  except ImportError:
     78 -    class skipif(object):
     79          "Using a class because a function would bind into a method when used in classes"
     80 -        def __init__(self, *args): pass
     81 -        def __call__(self, func, *args): return func
     82  else:
     83      skipif = pytest.mark.skipif
     84
     85 -def _get_caller_relative_path(filename, frame_depth=2):
     86      module = sys.modules[sys._getframe(frame_depth).f_globals['__name__']]
     87      return os.path.normpath(os.path.join(
     88              os.path.dirname(getattr(module, '__file__', '')), filename))
     89
     90  from io import StringIO
     91
     92  unichr_escape = re.compile(r'\\u[0-9a-fA-F]{4}|\\U[0-9a-fA-F]{8}')
     93
     94  if sys.version_info[0] >= 3:
     95      # Python 3
     96      from builtins import str as unicode
     97      from codecs import unicode_escape_decode
     98      _chr = chr
     99 -    def _str(s, encoding="UTF-8"):
    100          return unichr_escape.sub(lambda x: unicode_escape_decode(x.group(0))[0], s)
    101 -    def _bytes(s, encoding="UTF-8"):
    102          return s.encode(encoding)
    103      from io import BytesIO as _BytesIO
    104 -    def BytesIO(*args):
    105          if args and isinstance(args[0], str):
    106              args = (args[0].encode("UTF-8"),)
    107          return _BytesIO(*args)
    108
    109      doctest_parser = doctest.DocTestParser()
    110      _fix_unicode = re.compile(r'(\s+)u(["\'])').sub
    111      _fix_exceptions = re.compile(r'(.*except [^(]*),\s*(.*:)').sub
    112 -    def make_doctest(filename):
    113          filename = _get_caller_relative_path(filename)
    114          doctests = read_file(filename)
    115          doctests = _fix_unicode(r'\1\2', doctests)
    116          doctests = _fix_exceptions(r'\1 as \2', doctests)
    117          return doctest.DocTestCase(
    118              doctest_parser.get_doctest(
    119                  doctests, {}, os.path.basename(filename), filename, 0))
    120  else:
    121      # Python 2
    122      from __builtin__ import unicode
    123      _chr = unichr
    124 -    def _str(s, encoding="UTF-8"):
    125          s = unicode(s, encoding=encoding)
    126          return unichr_escape.sub(lambda x:
    127                                       x.group(0).decode('unicode-escape'),
    128                                   s)
    129 -    def _bytes(s, encoding="UTF-8"):
    130          return s
    131      from io import BytesIO
    132
    133      doctest_parser = doctest.DocTestParser()
    134      _fix_traceback = re.compile(r'^(\s*)(?:\w+\.)+(\w*(?:Error|Exception|Invalid):)', re.M).sub
    135      _fix_exceptions = re.compile(r'(.*except [^(]*)\s+as\s+(.*:)').sub
    136      _fix_bytes = re.compile(r'(\s+)b(["\'])').sub
    137 -    def make_doctest(filename):
    138          filename = _get_caller_relative_path(filename)
    139          doctests = read_file(filename)
    140          doctests = _fix_traceback(r'\1\2', doctests)
    141          doctests = _fix_exceptions(r'\1, \2', doctests)
    142          doctests = _fix_bytes(r'\1\2', doctests)
    143          return doctest.DocTestCase(
    144              doctest_parser.get_doctest(
    145                  doctests, {}, os.path.basename(filename), filename, 0))
    146
    147  try:
    148      skipIf = unittest.skipIf
    149  except AttributeError:
    150 -    def skipIf(condition, why):
    151          def _skip(thing):
    152              import types
    153              if isinstance(thing, (type, types.ClassType)):
    154                  return type(thing.__name__, (object,), {})
    155              else:
    156                  return None
    157          if condition:
    158              return _skip
    159          return lambda thing: thing
    160
    161
    162 -class HelperTestCase(unittest.TestCase):
    163 -    def tearDown(self):
    164          gc.collect()
    165
    166 -    def parse(self, text, parser=None):
    167          f = BytesIO(text) if isinstance(text, bytes) else StringIO(text)
    168          return etree.parse(f, parser=parser)
    169
    170 -    def _rootstring(self, tree):
    171          return etree.tostring(tree.getroot()).replace(
    172              _bytes(' '), _bytes('')).replace(_bytes('\n'), _bytes(''))
    173
    174
    175 -class SillyFileLike:
    176 -    def __init__(self, xml_data=_bytes('<foo><bar/></foo>')):
    177          self.xml_data = xml_data
    178
    179 -    def read(self, amount=None):
    180          if self.xml_data:
    181              if amount:
    182                  data = self.xml_data[:amount]
    183                  self.xml_data = self.xml_data[amount:]
    184              else:
    185                  data = self.xml_data
    186                  self.xml_data = _bytes('')
    187              return data
    188          return _bytes('')
    189
    190 -class LargeFileLike:
    191 -    def __init__(self, charlen=100, depth=4, children=5):
    192          self.data = BytesIO()
    193          self.chars  = _bytes('a') * charlen
    194          self.children = range(children)
    195          self.more = self.iterelements(depth)
    196
    197 -    def iterelements(self, depth):
    198          yield _bytes('<root>')
    199          depth -= 1
    200          if depth > 0:
    201              for child in self.children:
    202                  for element in self.iterelements(depth):
    203                      yield element
    204                  yield self.chars
    205          else:
    206              yield self.chars
    207          yield _bytes('</root>')
    208
    209 -    def read(self, amount=None):
    210          data = self.data
    211          append = data.write
    212          if amount:
    213              for element in self.more:
    214                  append(element)
    215                  if data.tell() >= amount:
    216                      break
    217          else:
    218              for element in self.more:
    219                  append(element)
    220          result = data.getvalue()
    221          data.seek(0)
    222          data.truncate()
    223          if amount:
    224              append(result[amount:])
    225              result = result[:amount]
    226          return result
    227
    228 -class LargeFileLikeUnicode(LargeFileLike):
    229 -    def __init__(self, charlen=100, depth=4, children=5):
    230          LargeFileLike.__init__(self, charlen, depth, children)
    231          self.data = StringIO()
    232          self.chars  = _str('a') * charlen
    233          self.more = self.iterelements(depth)
    234
    235 -    def iterelements(self, depth):
    236          yield _str('<root>')
    237          depth -= 1
    238          if depth > 0:
    239              for child in self.children:
    240                  for element in self.iterelements(depth):
    241                      yield element
    242                  yield self.chars
    243          else:
    244              yield self.chars
    245          yield _str('</root>')
    246
    247 -def fileInTestDir(name):
    248      _testdir = os.path.dirname(__file__)
    249      return os.path.join(_testdir, name)
    250
    251 -def path2url(path):
    252      return urlparse.urljoin(
    253          'file:', pathname2url(path))
    254
    255 -def fileUrlInTestDir(name):
    256      return path2url(fileInTestDir(name))
    257
    258 -def read_file(name, mode='r'):
    259      with open(name, mode) as f:
    260          data = f.read()
    261      return data
    262
    263 -def write_to_file(name, data, mode='w'):
    264      with open(name, mode) as f:
    265          f.write(data)
    266
    267 -def readFileInTestDir(name, mode='r'):
    268      return read_file(fileInTestDir(name), mode)
    269
    270 -def canonicalize(xml):
    271      tree = etree.parse(BytesIO(xml) if isinstance(xml, bytes) else StringIO(xml))
    272      f = BytesIO()
    273      tree.write_c14n(f)
    274      return f.getvalue()
    275
    276
    277  @contextmanager
    278 -def tmpfile(**kwargs):
    279      handle, filename = tempfile.mkstemp(**kwargs)
    280      try:
    281          yield filename
    282      finally:
    283          os.close(handle)
    284          os.remove(filename)
    285