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

Source Code for Module lxml.tests.test_external_document

  1  # -*- coding: utf-8 -*- 
  2  """ 
  3  Test cases related to direct loading of external libxml2 documents 
  4  """ 
  5   
  6  from __future__ import absolute_import 
  7   
  8  import sys 
  9  import unittest 
 10   
 11  from .common_imports import HelperTestCase, etree, skipIf 
 12   
 13  DOC_NAME = b'libxml2:xmlDoc' 
 14  DESTRUCTOR_NAME = b'destructor:xmlFreeDoc' 
 15   
 16   
 17  @skipIf(sys.version_info[:2] < (2, 7), 
 18          'Not supported for python < 2.7') 
19 -class ExternalDocumentTestCase(HelperTestCase):
20 - def setUp(self):
21 import ctypes 22 from ctypes import pythonapi 23 from ctypes.util import find_library 24 25 def wrap(func, restype, *argtypes): 26 func.restype = restype 27 func.argtypes = list(argtypes) 28 return func
29 30 self.get_capsule_name = wrap(pythonapi.PyCapsule_GetName, 31 ctypes.c_char_p, ctypes.py_object) 32 self.capsule_is_valid = wrap(pythonapi.PyCapsule_IsValid, ctypes.c_int, 33 ctypes.py_object, ctypes.c_char_p) 34 self.new_capsule = wrap(pythonapi.PyCapsule_New, ctypes.py_object, 35 ctypes.c_void_p, ctypes.c_char_p, 36 ctypes.c_void_p) 37 self.set_capsule_name = wrap(pythonapi.PyCapsule_SetName, ctypes.c_int, 38 ctypes.py_object, ctypes.c_char_p) 39 self.set_capsule_context = wrap(pythonapi.PyCapsule_SetContext, 40 ctypes.c_int, ctypes.py_object, 41 ctypes.c_char_p) 42 self.get_capsule_context = wrap(pythonapi.PyCapsule_GetContext, 43 ctypes.c_char_p, ctypes.py_object) 44 self.get_capsule_pointer = wrap(pythonapi.PyCapsule_GetPointer, 45 ctypes.c_void_p, ctypes.py_object, 46 ctypes.c_char_p) 47 self.set_capsule_pointer = wrap(pythonapi.PyCapsule_SetPointer, 48 ctypes.c_int, ctypes.py_object, 49 ctypes.c_void_p) 50 self.set_capsule_destructor = wrap(pythonapi.PyCapsule_SetDestructor, 51 ctypes.c_int, ctypes.py_object, 52 ctypes.c_void_p) 53 self.PyCapsule_Destructor = ctypes.CFUNCTYPE(None, ctypes.py_object) 54 libxml2 = ctypes.CDLL(find_library('xml2')) 55 self.create_doc = wrap(libxml2.xmlReadMemory, ctypes.c_void_p, 56 ctypes.c_char_p, ctypes.c_int, ctypes.c_char_p, 57 ctypes.c_char_p, ctypes.c_int) 58 self.free_doc = wrap(libxml2.xmlFreeDoc, None, ctypes.c_void_p)
59
60 - def as_capsule(self, text, capsule_name=DOC_NAME):
61 if not isinstance(text, bytes): 62 text = text.encode('utf-8') 63 doc = self.create_doc(text, len(text), b'base.xml', b'utf-8', 0) 64 ans = self.new_capsule(doc, capsule_name, None) 65 self.set_capsule_context(ans, DESTRUCTOR_NAME) 66 return ans
67
68 - def test_external_document_adoption(self):
69 xml = '<r a="1">t</r>' 70 self.assertRaises(TypeError, etree.adopt_external_document, None) 71 capsule = self.as_capsule(xml) 72 self.assertTrue(self.capsule_is_valid(capsule, DOC_NAME)) 73 self.assertEqual(DOC_NAME, self.get_capsule_name(capsule)) 74 # Create an lxml tree from the capsule (this is a move not a copy) 75 root = etree.adopt_external_document(capsule).getroot() 76 self.assertIsNone(self.get_capsule_name(capsule)) 77 self.assertEqual(root.text, 't') 78 root.text = 'new text' 79 # Now reset the capsule so we can copy it 80 self.assertEqual(0, self.set_capsule_name(capsule, DOC_NAME)) 81 self.assertEqual(0, self.set_capsule_context(capsule, b'invalid')) 82 # Create an lxml tree from the capsule (this is a copy not a move) 83 root2 = etree.adopt_external_document(capsule).getroot() 84 self.assertEqual(self.get_capsule_context(capsule), b'invalid') 85 # Check that the modification to the tree using the transferred 86 # document was successful 87 self.assertEqual(root.text, root2.text) 88 # Check that further modifications do not show up in the copy (they are 89 # disjoint) 90 root.text = 'other text' 91 self.assertNotEqual(root.text, root2.text) 92 # delete root and ensure root2 survives 93 del root 94 self.assertEqual(root2.text, 'new text')
95
96 97 -def test_suite():
98 suite = unittest.TestSuite() 99 suite.addTests([unittest.makeSuite(ExternalDocumentTestCase)]) 100 return suite
101 102 103 if __name__ == '__main__': 104 print('to test use test.py %s' % __file__) 105