Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.
 
 
 
 

181 řádky
6.2 KiB

  1. # Parser target context (ET target interface)
  2. cdef object inspect_getargspec
  3. try:
  4. from inspect import getfullargspec as inspect_getargspec
  5. except ImportError:
  6. from inspect import getargspec as inspect_getargspec
  7. class _TargetParserResult(Exception):
  8. # Admittedly, this is somewhat ugly, but it's the easiest way
  9. # to push the Python level parser result through the parser
  10. # machinery towards the API level functions
  11. def __init__(self, result):
  12. self.result = result
  13. @cython.final
  14. @cython.internal
  15. cdef class _PythonSaxParserTarget(_SaxParserTarget):
  16. cdef object _target_start
  17. cdef object _target_end
  18. cdef object _target_data
  19. cdef object _target_start_ns
  20. cdef object _target_end_ns
  21. cdef object _target_doctype
  22. cdef object _target_pi
  23. cdef object _target_comment
  24. cdef bint _start_takes_nsmap
  25. def __cinit__(self, target):
  26. cdef int event_filter
  27. event_filter = 0
  28. self._start_takes_nsmap = 0
  29. try:
  30. self._target_start = target.start
  31. if self._target_start is not None:
  32. event_filter |= SAX_EVENT_START
  33. except AttributeError:
  34. pass
  35. else:
  36. try:
  37. arguments = inspect_getargspec(self._target_start)
  38. if len(arguments[0]) > 3 or arguments[1] is not None:
  39. self._start_takes_nsmap = 1
  40. except TypeError:
  41. pass
  42. try:
  43. self._target_end = target.end
  44. if self._target_end is not None:
  45. event_filter |= SAX_EVENT_END
  46. except AttributeError:
  47. pass
  48. try:
  49. self._target_start_ns = target.start_ns
  50. if self._target_start_ns is not None:
  51. event_filter |= SAX_EVENT_START_NS
  52. except AttributeError:
  53. pass
  54. try:
  55. self._target_end_ns = target.end_ns
  56. if self._target_end_ns is not None:
  57. event_filter |= SAX_EVENT_END_NS
  58. except AttributeError:
  59. pass
  60. try:
  61. self._target_data = target.data
  62. if self._target_data is not None:
  63. event_filter |= SAX_EVENT_DATA
  64. except AttributeError:
  65. pass
  66. try:
  67. self._target_doctype = target.doctype
  68. if self._target_doctype is not None:
  69. event_filter |= SAX_EVENT_DOCTYPE
  70. except AttributeError:
  71. pass
  72. try:
  73. self._target_pi = target.pi
  74. if self._target_pi is not None:
  75. event_filter |= SAX_EVENT_PI
  76. except AttributeError:
  77. pass
  78. try:
  79. self._target_comment = target.comment
  80. if self._target_comment is not None:
  81. event_filter |= SAX_EVENT_COMMENT
  82. except AttributeError:
  83. pass
  84. self._sax_event_filter = event_filter
  85. cdef _handleSaxStart(self, tag, attrib, nsmap):
  86. if self._start_takes_nsmap:
  87. return self._target_start(tag, attrib, nsmap)
  88. else:
  89. return self._target_start(tag, attrib)
  90. cdef _handleSaxEnd(self, tag):
  91. return self._target_end(tag)
  92. cdef _handleSaxStartNs(self, prefix, uri):
  93. return self._target_start_ns(prefix, uri)
  94. cdef _handleSaxEndNs(self, prefix):
  95. return self._target_end_ns(prefix)
  96. cdef int _handleSaxData(self, data) except -1:
  97. self._target_data(data)
  98. cdef int _handleSaxDoctype(self, root_tag, public_id, system_id) except -1:
  99. self._target_doctype(root_tag, public_id, system_id)
  100. cdef _handleSaxPi(self, target, data):
  101. return self._target_pi(target, data)
  102. cdef _handleSaxComment(self, comment):
  103. return self._target_comment(comment)
  104. @cython.final
  105. @cython.internal
  106. @cython.no_gc_clear # Required because parent class uses it - Cython bug.
  107. cdef class _TargetParserContext(_SaxParserContext):
  108. """This class maps SAX2 events to the ET parser target interface.
  109. """
  110. cdef object _python_target
  111. cdef int _setTarget(self, target) except -1:
  112. self._python_target = target
  113. if not isinstance(target, _SaxParserTarget) or \
  114. hasattr(target, '__dict__'):
  115. target = _PythonSaxParserTarget(target)
  116. self._setSaxParserTarget(target)
  117. return 0
  118. cdef _ParserContext _copy(self):
  119. cdef _TargetParserContext context
  120. context = _ParserContext._copy(self)
  121. context._setTarget(self._python_target)
  122. return context
  123. cdef void _cleanupTargetParserContext(self, xmlDoc* result) noexcept:
  124. if self._c_ctxt.myDoc is not NULL:
  125. if self._c_ctxt.myDoc is not result and \
  126. self._c_ctxt.myDoc._private is NULL:
  127. # no _Document proxy => orphen
  128. tree.xmlFreeDoc(self._c_ctxt.myDoc)
  129. self._c_ctxt.myDoc = NULL
  130. cdef object _handleParseResult(self, _BaseParser parser, xmlDoc* result,
  131. filename):
  132. cdef bint recover
  133. recover = parser._parse_options & xmlparser.XML_PARSE_RECOVER
  134. try:
  135. if self._has_raised():
  136. self._cleanupTargetParserContext(result)
  137. self._raise_if_stored()
  138. if not self._c_ctxt.wellFormed and not recover:
  139. _raiseParseError(self._c_ctxt, filename, self._error_log)
  140. except:
  141. self._python_target.close()
  142. raise
  143. return self._python_target.close()
  144. cdef xmlDoc* _handleParseResultDoc(self, _BaseParser parser,
  145. xmlDoc* result, filename) except NULL:
  146. cdef bint recover
  147. recover = parser._parse_options & xmlparser.XML_PARSE_RECOVER
  148. if result is not NULL and result._private is NULL:
  149. # no _Document proxy => orphen
  150. tree.xmlFreeDoc(result)
  151. try:
  152. self._cleanupTargetParserContext(result)
  153. self._raise_if_stored()
  154. if not self._c_ctxt.wellFormed and not recover:
  155. _raiseParseError(self._c_ctxt, filename, self._error_log)
  156. except:
  157. self._python_target.close()
  158. raise
  159. parse_result = self._python_target.close()
  160. raise _TargetParserResult(parse_result)