lxml 5.2.0__cp310-cp310-win32.whl → 5.2.2__cp310-cp310-win32.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (89) hide show
  1. lxml/ElementInclude.py +244 -244
  2. lxml/__init__.py +22 -22
  3. lxml/_elementpath.cp310-win32.pyd +0 -0
  4. lxml/_elementpath.py +341 -341
  5. lxml/apihelpers.pxi +1793 -1793
  6. lxml/builder.cp310-win32.pyd +0 -0
  7. lxml/builder.py +232 -232
  8. lxml/classlookup.pxi +580 -580
  9. lxml/cleanup.pxi +215 -215
  10. lxml/cssselect.py +101 -101
  11. lxml/debug.pxi +90 -90
  12. lxml/docloader.pxi +178 -178
  13. lxml/doctestcompare.py +488 -488
  14. lxml/dtd.pxi +478 -478
  15. lxml/etree.cp310-win32.pyd +0 -0
  16. lxml/etree.h +6 -6
  17. lxml/etree.pyx +3732 -3711
  18. lxml/extensions.pxi +833 -833
  19. lxml/html/ElementSoup.py +10 -10
  20. lxml/html/__init__.py +1923 -1923
  21. lxml/html/_diffcommand.py +86 -86
  22. lxml/html/_html5builder.py +100 -100
  23. lxml/html/_setmixin.py +56 -56
  24. lxml/html/builder.py +133 -133
  25. lxml/html/clean.py +21 -21
  26. lxml/html/defs.py +135 -135
  27. lxml/html/diff.cp310-win32.pyd +0 -0
  28. lxml/html/diff.py +878 -878
  29. lxml/html/formfill.py +299 -299
  30. lxml/html/html5parser.py +260 -260
  31. lxml/html/soupparser.py +314 -314
  32. lxml/html/usedoctest.py +13 -13
  33. lxml/includes/c14n.pxd +25 -25
  34. lxml/includes/config.pxd +3 -3
  35. lxml/includes/dtdvalid.pxd +18 -18
  36. lxml/includes/etree_defs.h +379 -379
  37. lxml/includes/etreepublic.pxd +237 -237
  38. lxml/includes/htmlparser.pxd +56 -56
  39. lxml/includes/lxml-version.h +1 -1
  40. lxml/includes/relaxng.pxd +64 -64
  41. lxml/includes/schematron.pxd +34 -34
  42. lxml/includes/tree.pxd +494 -494
  43. lxml/includes/uri.pxd +5 -5
  44. lxml/includes/xinclude.pxd +22 -22
  45. lxml/includes/xmlerror.pxd +852 -852
  46. lxml/includes/xmlparser.pxd +265 -265
  47. lxml/includes/xmlschema.pxd +35 -35
  48. lxml/includes/xpath.pxd +136 -136
  49. lxml/includes/xslt.pxd +190 -190
  50. lxml/isoschematron/__init__.py +348 -348
  51. lxml/isoschematron/resources/rng/iso-schematron.rng +709 -709
  52. lxml/isoschematron/resources/xsl/RNG2Schtrn.xsl +75 -75
  53. lxml/isoschematron/resources/xsl/iso-schematron-xslt1/iso_abstract_expand.xsl +312 -312
  54. lxml/isoschematron/resources/xsl/iso-schematron-xslt1/iso_dsdl_include.xsl +1159 -1159
  55. lxml/isoschematron/resources/xsl/iso-schematron-xslt1/iso_schematron_message.xsl +54 -54
  56. lxml/isoschematron/resources/xsl/iso-schematron-xslt1/iso_schematron_skeleton_for_xslt1.xsl +1796 -1796
  57. lxml/isoschematron/resources/xsl/iso-schematron-xslt1/iso_svrl_for_xslt1.xsl +588 -588
  58. lxml/iterparse.pxi +438 -438
  59. lxml/lxml.etree.h +6 -6
  60. lxml/nsclasses.pxi +281 -281
  61. lxml/objectify.cp310-win32.pyd +0 -0
  62. lxml/objectify.pyx +2145 -2145
  63. lxml/objectpath.pxi +332 -332
  64. lxml/parser.pxi +1994 -1994
  65. lxml/parsertarget.pxi +180 -180
  66. lxml/proxy.pxi +619 -619
  67. lxml/public-api.pxi +178 -178
  68. lxml/pyclasslookup.py +3 -3
  69. lxml/readonlytree.pxi +565 -565
  70. lxml/relaxng.pxi +165 -165
  71. lxml/sax.cp310-win32.pyd +0 -0
  72. lxml/sax.py +275 -275
  73. lxml/saxparser.pxi +875 -875
  74. lxml/schematron.pxi +168 -168
  75. lxml/serializer.pxi +1871 -1871
  76. lxml/usedoctest.py +13 -13
  77. lxml/xinclude.pxi +67 -67
  78. lxml/xmlerror.pxi +1654 -1654
  79. lxml/xmlid.pxi +179 -179
  80. lxml/xmlschema.pxi +215 -215
  81. lxml/xpath.pxi +487 -487
  82. lxml/xslt.pxi +950 -950
  83. lxml/xsltext.pxi +242 -242
  84. {lxml-5.2.0.dist-info → lxml-5.2.2.dist-info}/LICENSE.txt +29 -29
  85. {lxml-5.2.0.dist-info → lxml-5.2.2.dist-info}/LICENSES.txt +29 -29
  86. {lxml-5.2.0.dist-info → lxml-5.2.2.dist-info}/METADATA +9 -17
  87. {lxml-5.2.0.dist-info → lxml-5.2.2.dist-info}/RECORD +89 -89
  88. {lxml-5.2.0.dist-info → lxml-5.2.2.dist-info}/WHEEL +0 -0
  89. {lxml-5.2.0.dist-info → lxml-5.2.2.dist-info}/top_level.txt +0 -0
lxml/lxml.etree.h CHANGED
@@ -13,7 +13,7 @@ struct LxmlElementBase;
13
13
  struct LxmlElementClassLookup;
14
14
  struct LxmlFallbackElementClassLookup;
15
15
 
16
- /* "lxml/etree.pyx":333
16
+ /* "lxml/etree.pyx":353
17
17
  *
18
18
  * # type of a function that steps from node to node
19
19
  * ctypedef public xmlNode* (*_node_to_node_function)(xmlNode*) # <<<<<<<<<<<<<<
@@ -22,7 +22,7 @@ struct LxmlFallbackElementClassLookup;
22
22
  */
23
23
  typedef xmlNode *(*_node_to_node_function)(xmlNode *);
24
24
 
25
- /* "lxml/etree.pyx":349
25
+ /* "lxml/etree.pyx":369
26
26
  * @cython.final
27
27
  * @cython.freelist(8)
28
28
  * cdef public class _Document [ type LxmlDocumentType, object LxmlDocument ]: # <<<<<<<<<<<<<<
@@ -38,7 +38,7 @@ struct LxmlDocument {
38
38
  struct __pyx_obj_4lxml_5etree__BaseParser *_parser;
39
39
  };
40
40
 
41
- /* "lxml/etree.pyx":698
41
+ /* "lxml/etree.pyx":718
42
42
  *
43
43
  * @cython.no_gc_clear
44
44
  * cdef public class _Element [ type LxmlElementType, object LxmlElement ]: # <<<<<<<<<<<<<<
@@ -52,7 +52,7 @@ struct LxmlElement {
52
52
  PyObject *_tag;
53
53
  };
54
54
 
55
- /* "lxml/etree.pyx":1872
55
+ /* "lxml/etree.pyx":1892
56
56
  *
57
57
  *
58
58
  * cdef public class _ElementTree [ type LxmlElementTreeType, # <<<<<<<<<<<<<<
@@ -66,7 +66,7 @@ struct LxmlElementTree {
66
66
  struct LxmlElement *_context_node;
67
67
  };
68
68
 
69
- /* "lxml/etree.pyx":2645
69
+ /* "lxml/etree.pyx":2666
70
70
  *
71
71
  *
72
72
  * cdef public class _ElementTagMatcher [ object LxmlElementTagMatcher, # <<<<<<<<<<<<<<
@@ -82,7 +82,7 @@ struct LxmlElementTagMatcher {
82
82
  char *_name;
83
83
  };
84
84
 
85
- /* "lxml/etree.pyx":2676
85
+ /* "lxml/etree.pyx":2697
86
86
  * self._name = NULL
87
87
  *
88
88
  * cdef public class _ElementIterator(_ElementTagMatcher) [ # <<<<<<<<<<<<<<
lxml/nsclasses.pxi CHANGED
@@ -1,281 +1,281 @@
1
- # module-level API for namespace implementations
2
-
3
- cdef class LxmlRegistryError(LxmlError):
4
- """Base class of lxml registry errors.
5
- """
6
-
7
- cdef class NamespaceRegistryError(LxmlRegistryError):
8
- """Error registering a namespace extension.
9
- """
10
-
11
-
12
- @cython.internal
13
- cdef class _NamespaceRegistry:
14
- "Dictionary-like namespace registry"
15
- cdef object _ns_uri
16
- cdef bytes _ns_uri_utf
17
- cdef dict _entries
18
- cdef char* _c_ns_uri_utf
19
- def __cinit__(self, ns_uri):
20
- self._ns_uri = ns_uri
21
- if ns_uri is None:
22
- self._ns_uri_utf = None
23
- self._c_ns_uri_utf = NULL
24
- else:
25
- self._ns_uri_utf = _utf8(ns_uri)
26
- self._c_ns_uri_utf = _cstr(self._ns_uri_utf)
27
- self._entries = {}
28
-
29
- def update(self, class_dict_iterable):
30
- """update(self, class_dict_iterable)
31
-
32
- Forgivingly update the registry.
33
-
34
- ``class_dict_iterable`` may be a dict or some other iterable
35
- that yields (name, value) pairs.
36
-
37
- If a value does not match the required type for this registry,
38
- or if the name starts with '_', it will be silently discarded.
39
- This allows registrations at the module or class level using
40
- vars(), globals() etc."""
41
- if hasattr(class_dict_iterable, 'items'):
42
- class_dict_iterable = class_dict_iterable.items()
43
- for name, item in class_dict_iterable:
44
- if (name is None or name[:1] != '_') and callable(item):
45
- self[name] = item
46
-
47
- def __getitem__(self, name):
48
- if name is not None:
49
- name = _utf8(name)
50
- return self._get(name)
51
-
52
- def __delitem__(self, name):
53
- if name is not None:
54
- name = _utf8(name)
55
- del self._entries[name]
56
-
57
- cdef object _get(self, object name):
58
- cdef python.PyObject* dict_result
59
- dict_result = python.PyDict_GetItem(self._entries, name)
60
- if dict_result is NULL:
61
- raise KeyError, "Name not registered."
62
- return <object>dict_result
63
-
64
- cdef object _getForString(self, char* name):
65
- cdef python.PyObject* dict_result
66
- dict_result = python.PyDict_GetItem(self._entries, name)
67
- if dict_result is NULL:
68
- raise KeyError, "Name not registered."
69
- return <object>dict_result
70
-
71
- def __iter__(self):
72
- return iter(self._entries)
73
-
74
- def items(self):
75
- return list(self._entries.items())
76
-
77
- def iteritems(self):
78
- return iter(self._entries.items())
79
-
80
- def clear(self):
81
- self._entries.clear()
82
-
83
- def __call__(self, obj):
84
- # Usage as decorator:
85
- # ns = lookup.get_namespace("...")
86
- # @ns('abc')
87
- # class element(ElementBase): pass
88
- #
89
- # @ns
90
- # class elementname(ElementBase): pass
91
-
92
- if obj is None or python._isString(obj):
93
- # @ns(None) or @ns('tag')
94
- return partial(self.__deco, obj)
95
- # plain @ns decorator
96
- self[obj.__name__] = obj
97
- return obj
98
-
99
- def __deco(self, name, obj):
100
- self[name] = obj
101
- return obj
102
-
103
-
104
- @cython.final
105
- @cython.internal
106
- cdef class _ClassNamespaceRegistry(_NamespaceRegistry):
107
- "Dictionary-like registry for namespace implementation classes"
108
- def __setitem__(self, name, item):
109
- if not isinstance(item, type) or not issubclass(item, ElementBase):
110
- raise NamespaceRegistryError, \
111
- "Registered element classes must be subtypes of ElementBase"
112
- if name is not None:
113
- name = _utf8(name)
114
- self._entries[name] = item
115
-
116
- def __repr__(self):
117
- return "Namespace(%r)" % self._ns_uri
118
-
119
-
120
- cdef class ElementNamespaceClassLookup(FallbackElementClassLookup):
121
- """ElementNamespaceClassLookup(self, fallback=None)
122
-
123
- Element class lookup scheme that searches the Element class in the
124
- Namespace registry.
125
-
126
- Usage:
127
-
128
- >>> lookup = ElementNamespaceClassLookup()
129
- >>> ns_elements = lookup.get_namespace("http://schema.org/Movie")
130
-
131
- >>> @ns_elements
132
- ... class movie(ElementBase):
133
- ... "Element implementation for 'movie' tag (using class name) in schema namespace."
134
-
135
- >>> @ns_elements("movie")
136
- ... class MovieElement(ElementBase):
137
- ... "Element implementation for 'movie' tag (explicit tag name) in schema namespace."
138
- """
139
- cdef dict _namespace_registries
140
- def __cinit__(self):
141
- self._namespace_registries = {}
142
-
143
- def __init__(self, ElementClassLookup fallback=None):
144
- FallbackElementClassLookup.__init__(self, fallback)
145
- self._lookup_function = _find_nselement_class
146
-
147
- def get_namespace(self, ns_uri):
148
- """get_namespace(self, ns_uri)
149
-
150
- Retrieve the namespace object associated with the given URI.
151
- Pass None for the empty namespace.
152
-
153
- Creates a new namespace object if it does not yet exist."""
154
- if ns_uri:
155
- ns_utf = _utf8(ns_uri)
156
- else:
157
- ns_utf = None
158
- try:
159
- return self._namespace_registries[ns_utf]
160
- except KeyError:
161
- registry = self._namespace_registries[ns_utf] = \
162
- _ClassNamespaceRegistry(ns_uri)
163
- return registry
164
-
165
- cdef object _find_nselement_class(state, _Document doc, xmlNode* c_node):
166
- cdef python.PyObject* dict_result
167
- cdef ElementNamespaceClassLookup lookup
168
- cdef _NamespaceRegistry registry
169
- if state is None:
170
- return _lookupDefaultElementClass(None, doc, c_node)
171
-
172
- lookup = <ElementNamespaceClassLookup>state
173
- if c_node.type != tree.XML_ELEMENT_NODE:
174
- return _callLookupFallback(lookup, doc, c_node)
175
-
176
- c_namespace_utf = _getNs(c_node)
177
- if c_namespace_utf is not NULL:
178
- dict_result = python.PyDict_GetItem(
179
- lookup._namespace_registries, <unsigned char*>c_namespace_utf)
180
- else:
181
- dict_result = python.PyDict_GetItem(
182
- lookup._namespace_registries, None)
183
- if dict_result is not NULL:
184
- registry = <_NamespaceRegistry>dict_result
185
- classes = registry._entries
186
-
187
- if c_node.name is not NULL:
188
- dict_result = python.PyDict_GetItem(
189
- classes, <unsigned char*>c_node.name)
190
- else:
191
- dict_result = NULL
192
-
193
- if dict_result is NULL:
194
- dict_result = python.PyDict_GetItem(classes, None)
195
-
196
- if dict_result is not NULL:
197
- return <object>dict_result
198
- return _callLookupFallback(lookup, doc, c_node)
199
-
200
-
201
- ################################################################################
202
- # XPath extension functions
203
-
204
- cdef dict __FUNCTION_NAMESPACE_REGISTRIES
205
- __FUNCTION_NAMESPACE_REGISTRIES = {}
206
-
207
- def FunctionNamespace(ns_uri):
208
- """FunctionNamespace(ns_uri)
209
-
210
- Retrieve the function namespace object associated with the given
211
- URI.
212
-
213
- Creates a new one if it does not yet exist. A function namespace
214
- can only be used to register extension functions.
215
-
216
- Usage:
217
-
218
- >>> ns_functions = FunctionNamespace("http://schema.org/Movie")
219
-
220
- >>> @ns_functions # uses function name
221
- ... def add2(x):
222
- ... return x + 2
223
-
224
- >>> @ns_functions("add3") # uses explicit name
225
- ... def add_three(x):
226
- ... return x + 3
227
- """
228
- ns_utf = _utf8(ns_uri) if ns_uri else None
229
- try:
230
- return __FUNCTION_NAMESPACE_REGISTRIES[ns_utf]
231
- except KeyError:
232
- registry = __FUNCTION_NAMESPACE_REGISTRIES[ns_utf] = \
233
- _XPathFunctionNamespaceRegistry(ns_uri)
234
- return registry
235
-
236
- @cython.internal
237
- cdef class _FunctionNamespaceRegistry(_NamespaceRegistry):
238
- def __setitem__(self, name, item):
239
- if not callable(item):
240
- raise NamespaceRegistryError, \
241
- "Registered functions must be callable."
242
- if not name:
243
- raise ValueError, \
244
- "extensions must have non empty names"
245
- self._entries[_utf8(name)] = item
246
-
247
- def __repr__(self):
248
- return "FunctionNamespace(%r)" % self._ns_uri
249
-
250
- @cython.final
251
- @cython.internal
252
- cdef class _XPathFunctionNamespaceRegistry(_FunctionNamespaceRegistry):
253
- cdef object _prefix
254
- cdef bytes _prefix_utf
255
-
256
- property prefix:
257
- "Namespace prefix for extension functions."
258
- def __del__(self):
259
- self._prefix = None # no prefix configured
260
- self._prefix_utf = None
261
- def __get__(self):
262
- if self._prefix is None:
263
- return ''
264
- else:
265
- return self._prefix
266
- def __set__(self, prefix):
267
- if prefix == '':
268
- prefix = None # empty prefix
269
- self._prefix_utf = _utf8(prefix) if prefix is not None else None
270
- self._prefix = prefix
271
-
272
- cdef list _find_all_extension_prefixes():
273
- "Internal lookup function to find all function prefixes for XSLT/XPath."
274
- cdef _XPathFunctionNamespaceRegistry registry
275
- cdef list ns_prefixes = []
276
- for registry in __FUNCTION_NAMESPACE_REGISTRIES.itervalues():
277
- if registry._prefix_utf is not None:
278
- if registry._ns_uri_utf is not None:
279
- ns_prefixes.append(
280
- (registry._prefix_utf, registry._ns_uri_utf))
281
- return ns_prefixes
1
+ # module-level API for namespace implementations
2
+
3
+ cdef class LxmlRegistryError(LxmlError):
4
+ """Base class of lxml registry errors.
5
+ """
6
+
7
+ cdef class NamespaceRegistryError(LxmlRegistryError):
8
+ """Error registering a namespace extension.
9
+ """
10
+
11
+
12
+ @cython.internal
13
+ cdef class _NamespaceRegistry:
14
+ "Dictionary-like namespace registry"
15
+ cdef object _ns_uri
16
+ cdef bytes _ns_uri_utf
17
+ cdef dict _entries
18
+ cdef char* _c_ns_uri_utf
19
+ def __cinit__(self, ns_uri):
20
+ self._ns_uri = ns_uri
21
+ if ns_uri is None:
22
+ self._ns_uri_utf = None
23
+ self._c_ns_uri_utf = NULL
24
+ else:
25
+ self._ns_uri_utf = _utf8(ns_uri)
26
+ self._c_ns_uri_utf = _cstr(self._ns_uri_utf)
27
+ self._entries = {}
28
+
29
+ def update(self, class_dict_iterable):
30
+ """update(self, class_dict_iterable)
31
+
32
+ Forgivingly update the registry.
33
+
34
+ ``class_dict_iterable`` may be a dict or some other iterable
35
+ that yields (name, value) pairs.
36
+
37
+ If a value does not match the required type for this registry,
38
+ or if the name starts with '_', it will be silently discarded.
39
+ This allows registrations at the module or class level using
40
+ vars(), globals() etc."""
41
+ if hasattr(class_dict_iterable, 'items'):
42
+ class_dict_iterable = class_dict_iterable.items()
43
+ for name, item in class_dict_iterable:
44
+ if (name is None or name[:1] != '_') and callable(item):
45
+ self[name] = item
46
+
47
+ def __getitem__(self, name):
48
+ if name is not None:
49
+ name = _utf8(name)
50
+ return self._get(name)
51
+
52
+ def __delitem__(self, name):
53
+ if name is not None:
54
+ name = _utf8(name)
55
+ del self._entries[name]
56
+
57
+ cdef object _get(self, object name):
58
+ cdef python.PyObject* dict_result
59
+ dict_result = python.PyDict_GetItem(self._entries, name)
60
+ if dict_result is NULL:
61
+ raise KeyError, "Name not registered."
62
+ return <object>dict_result
63
+
64
+ cdef object _getForString(self, char* name):
65
+ cdef python.PyObject* dict_result
66
+ dict_result = python.PyDict_GetItem(self._entries, name)
67
+ if dict_result is NULL:
68
+ raise KeyError, "Name not registered."
69
+ return <object>dict_result
70
+
71
+ def __iter__(self):
72
+ return iter(self._entries)
73
+
74
+ def items(self):
75
+ return list(self._entries.items())
76
+
77
+ def iteritems(self):
78
+ return iter(self._entries.items())
79
+
80
+ def clear(self):
81
+ self._entries.clear()
82
+
83
+ def __call__(self, obj):
84
+ # Usage as decorator:
85
+ # ns = lookup.get_namespace("...")
86
+ # @ns('abc')
87
+ # class element(ElementBase): pass
88
+ #
89
+ # @ns
90
+ # class elementname(ElementBase): pass
91
+
92
+ if obj is None or python._isString(obj):
93
+ # @ns(None) or @ns('tag')
94
+ return partial(self.__deco, obj)
95
+ # plain @ns decorator
96
+ self[obj.__name__] = obj
97
+ return obj
98
+
99
+ def __deco(self, name, obj):
100
+ self[name] = obj
101
+ return obj
102
+
103
+
104
+ @cython.final
105
+ @cython.internal
106
+ cdef class _ClassNamespaceRegistry(_NamespaceRegistry):
107
+ "Dictionary-like registry for namespace implementation classes"
108
+ def __setitem__(self, name, item):
109
+ if not isinstance(item, type) or not issubclass(item, ElementBase):
110
+ raise NamespaceRegistryError, \
111
+ "Registered element classes must be subtypes of ElementBase"
112
+ if name is not None:
113
+ name = _utf8(name)
114
+ self._entries[name] = item
115
+
116
+ def __repr__(self):
117
+ return "Namespace(%r)" % self._ns_uri
118
+
119
+
120
+ cdef class ElementNamespaceClassLookup(FallbackElementClassLookup):
121
+ """ElementNamespaceClassLookup(self, fallback=None)
122
+
123
+ Element class lookup scheme that searches the Element class in the
124
+ Namespace registry.
125
+
126
+ Usage:
127
+
128
+ >>> lookup = ElementNamespaceClassLookup()
129
+ >>> ns_elements = lookup.get_namespace("http://schema.org/Movie")
130
+
131
+ >>> @ns_elements
132
+ ... class movie(ElementBase):
133
+ ... "Element implementation for 'movie' tag (using class name) in schema namespace."
134
+
135
+ >>> @ns_elements("movie")
136
+ ... class MovieElement(ElementBase):
137
+ ... "Element implementation for 'movie' tag (explicit tag name) in schema namespace."
138
+ """
139
+ cdef dict _namespace_registries
140
+ def __cinit__(self):
141
+ self._namespace_registries = {}
142
+
143
+ def __init__(self, ElementClassLookup fallback=None):
144
+ FallbackElementClassLookup.__init__(self, fallback)
145
+ self._lookup_function = _find_nselement_class
146
+
147
+ def get_namespace(self, ns_uri):
148
+ """get_namespace(self, ns_uri)
149
+
150
+ Retrieve the namespace object associated with the given URI.
151
+ Pass None for the empty namespace.
152
+
153
+ Creates a new namespace object if it does not yet exist."""
154
+ if ns_uri:
155
+ ns_utf = _utf8(ns_uri)
156
+ else:
157
+ ns_utf = None
158
+ try:
159
+ return self._namespace_registries[ns_utf]
160
+ except KeyError:
161
+ registry = self._namespace_registries[ns_utf] = \
162
+ _ClassNamespaceRegistry(ns_uri)
163
+ return registry
164
+
165
+ cdef object _find_nselement_class(state, _Document doc, xmlNode* c_node):
166
+ cdef python.PyObject* dict_result
167
+ cdef ElementNamespaceClassLookup lookup
168
+ cdef _NamespaceRegistry registry
169
+ if state is None:
170
+ return _lookupDefaultElementClass(None, doc, c_node)
171
+
172
+ lookup = <ElementNamespaceClassLookup>state
173
+ if c_node.type != tree.XML_ELEMENT_NODE:
174
+ return _callLookupFallback(lookup, doc, c_node)
175
+
176
+ c_namespace_utf = _getNs(c_node)
177
+ if c_namespace_utf is not NULL:
178
+ dict_result = python.PyDict_GetItem(
179
+ lookup._namespace_registries, <unsigned char*>c_namespace_utf)
180
+ else:
181
+ dict_result = python.PyDict_GetItem(
182
+ lookup._namespace_registries, None)
183
+ if dict_result is not NULL:
184
+ registry = <_NamespaceRegistry>dict_result
185
+ classes = registry._entries
186
+
187
+ if c_node.name is not NULL:
188
+ dict_result = python.PyDict_GetItem(
189
+ classes, <unsigned char*>c_node.name)
190
+ else:
191
+ dict_result = NULL
192
+
193
+ if dict_result is NULL:
194
+ dict_result = python.PyDict_GetItem(classes, None)
195
+
196
+ if dict_result is not NULL:
197
+ return <object>dict_result
198
+ return _callLookupFallback(lookup, doc, c_node)
199
+
200
+
201
+ ################################################################################
202
+ # XPath extension functions
203
+
204
+ cdef dict __FUNCTION_NAMESPACE_REGISTRIES
205
+ __FUNCTION_NAMESPACE_REGISTRIES = {}
206
+
207
+ def FunctionNamespace(ns_uri):
208
+ """FunctionNamespace(ns_uri)
209
+
210
+ Retrieve the function namespace object associated with the given
211
+ URI.
212
+
213
+ Creates a new one if it does not yet exist. A function namespace
214
+ can only be used to register extension functions.
215
+
216
+ Usage:
217
+
218
+ >>> ns_functions = FunctionNamespace("http://schema.org/Movie")
219
+
220
+ >>> @ns_functions # uses function name
221
+ ... def add2(x):
222
+ ... return x + 2
223
+
224
+ >>> @ns_functions("add3") # uses explicit name
225
+ ... def add_three(x):
226
+ ... return x + 3
227
+ """
228
+ ns_utf = _utf8(ns_uri) if ns_uri else None
229
+ try:
230
+ return __FUNCTION_NAMESPACE_REGISTRIES[ns_utf]
231
+ except KeyError:
232
+ registry = __FUNCTION_NAMESPACE_REGISTRIES[ns_utf] = \
233
+ _XPathFunctionNamespaceRegistry(ns_uri)
234
+ return registry
235
+
236
+ @cython.internal
237
+ cdef class _FunctionNamespaceRegistry(_NamespaceRegistry):
238
+ def __setitem__(self, name, item):
239
+ if not callable(item):
240
+ raise NamespaceRegistryError, \
241
+ "Registered functions must be callable."
242
+ if not name:
243
+ raise ValueError, \
244
+ "extensions must have non empty names"
245
+ self._entries[_utf8(name)] = item
246
+
247
+ def __repr__(self):
248
+ return "FunctionNamespace(%r)" % self._ns_uri
249
+
250
+ @cython.final
251
+ @cython.internal
252
+ cdef class _XPathFunctionNamespaceRegistry(_FunctionNamespaceRegistry):
253
+ cdef object _prefix
254
+ cdef bytes _prefix_utf
255
+
256
+ property prefix:
257
+ "Namespace prefix for extension functions."
258
+ def __del__(self):
259
+ self._prefix = None # no prefix configured
260
+ self._prefix_utf = None
261
+ def __get__(self):
262
+ if self._prefix is None:
263
+ return ''
264
+ else:
265
+ return self._prefix
266
+ def __set__(self, prefix):
267
+ if prefix == '':
268
+ prefix = None # empty prefix
269
+ self._prefix_utf = _utf8(prefix) if prefix is not None else None
270
+ self._prefix = prefix
271
+
272
+ cdef list _find_all_extension_prefixes():
273
+ "Internal lookup function to find all function prefixes for XSLT/XPath."
274
+ cdef _XPathFunctionNamespaceRegistry registry
275
+ cdef list ns_prefixes = []
276
+ for registry in __FUNCTION_NAMESPACE_REGISTRIES.itervalues():
277
+ if registry._prefix_utf is not None:
278
+ if registry._ns_uri_utf is not None:
279
+ ns_prefixes.append(
280
+ (registry._prefix_utf, registry._ns_uri_utf))
281
+ return ns_prefixes
Binary file