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
12
13 DOC_NAME = b'libxml2:xmlDoc'
14 DESTRUCTOR_NAME = b'destructor:xmlFreeDoc'
15
16
19 try:
20 import ctypes
21 from ctypes import pythonapi
22 from ctypes.util import find_library
23 except ImportError:
24 raise unittest.SkipTest("ctypes support missing")
25
26 def wrap(func, restype, *argtypes):
27 func.restype = restype
28 func.argtypes = list(argtypes)
29 return func
30
31 self.get_capsule_name = wrap(pythonapi.PyCapsule_GetName,
32 ctypes.c_char_p, ctypes.py_object)
33 self.capsule_is_valid = wrap(pythonapi.PyCapsule_IsValid, ctypes.c_int,
34 ctypes.py_object, ctypes.c_char_p)
35 self.new_capsule = wrap(pythonapi.PyCapsule_New, ctypes.py_object,
36 ctypes.c_void_p, ctypes.c_char_p,
37 ctypes.c_void_p)
38 self.set_capsule_name = wrap(pythonapi.PyCapsule_SetName, ctypes.c_int,
39 ctypes.py_object, ctypes.c_char_p)
40 self.set_capsule_context = wrap(pythonapi.PyCapsule_SetContext,
41 ctypes.c_int, ctypes.py_object,
42 ctypes.c_char_p)
43 self.get_capsule_context = wrap(pythonapi.PyCapsule_GetContext,
44 ctypes.c_char_p, ctypes.py_object)
45 self.get_capsule_pointer = wrap(pythonapi.PyCapsule_GetPointer,
46 ctypes.c_void_p, ctypes.py_object,
47 ctypes.c_char_p)
48 self.set_capsule_pointer = wrap(pythonapi.PyCapsule_SetPointer,
49 ctypes.c_int, ctypes.py_object,
50 ctypes.c_void_p)
51 self.set_capsule_destructor = wrap(pythonapi.PyCapsule_SetDestructor,
52 ctypes.c_int, ctypes.py_object,
53 ctypes.c_void_p)
54 self.PyCapsule_Destructor = ctypes.CFUNCTYPE(None, ctypes.py_object)
55 libxml2 = ctypes.CDLL(find_library('xml2'))
56 self.create_doc = wrap(libxml2.xmlReadMemory, ctypes.c_void_p,
57 ctypes.c_char_p, ctypes.c_int, ctypes.c_char_p,
58 ctypes.c_char_p, ctypes.c_int)
59 self.free_doc = wrap(libxml2.xmlFreeDoc, None, ctypes.c_void_p)
60
62 if not isinstance(text, bytes):
63 text = text.encode('utf-8')
64 doc = self.create_doc(text, len(text), b'base.xml', b'utf-8', 0)
65 ans = self.new_capsule(doc, capsule_name, None)
66 self.set_capsule_context(ans, DESTRUCTOR_NAME)
67 return ans
68
70 xml = '<r a="1">t</r>'
71 self.assertRaises(TypeError, etree.adopt_external_document, None)
72 capsule = self.as_capsule(xml)
73 self.assertTrue(self.capsule_is_valid(capsule, DOC_NAME))
74 self.assertEqual(DOC_NAME, self.get_capsule_name(capsule))
75
76 root = etree.adopt_external_document(capsule).getroot()
77 self.assertIsNone(self.get_capsule_name(capsule))
78 self.assertEqual(root.text, 't')
79 root.text = 'new text'
80
81 self.assertEqual(0, self.set_capsule_name(capsule, DOC_NAME))
82 self.assertEqual(0, self.set_capsule_context(capsule, b'invalid'))
83
84 root2 = etree.adopt_external_document(capsule).getroot()
85 self.assertEqual(self.get_capsule_context(capsule), b'invalid')
86
87
88 self.assertEqual(root.text, root2.text)
89
90
91 root.text = 'other text'
92 self.assertNotEqual(root.text, root2.text)
93
94 del root
95 self.assertEqual(root2.text, 'new text')
96
97
99 suite = unittest.TestSuite()
100 if sys.platform != 'win32':
101 suite.addTests([unittest.makeSuite(ExternalDocumentTestCase)])
102 return suite
103
104
105 if __name__ == '__main__':
106 print('to test use test.py %s' % __file__)
107