1   
  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') 
 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) 
 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   
 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           
 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           
 80          self.assertEqual(0, self.set_capsule_name(capsule, DOC_NAME)) 
 81          self.assertEqual(0, self.set_capsule_context(capsule, b'invalid')) 
 82           
 83          root2 = etree.adopt_external_document(capsule).getroot() 
 84          self.assertEqual(self.get_capsule_context(capsule), b'invalid') 
 85           
 86           
 87          self.assertEqual(root.text, root2.text) 
 88           
 89           
 90          root.text = 'other text' 
 91          self.assertNotEqual(root.text, root2.text) 
 92           
 93          del root 
 94          self.assertEqual(root2.text, 'new text') 
  95   
101   
102   
103  if __name__ == '__main__': 
104      print('to test use test.py %s' % __file__) 
105