diff options
author | S. Solomon Darnell | 2025-03-28 21:52:21 -0500 |
---|---|---|
committer | S. Solomon Darnell | 2025-03-28 21:52:21 -0500 |
commit | 4a52a71956a8d46fcb7294ac71734504bb09bcc2 (patch) | |
tree | ee3dc5af3b6313e921cd920906356f5d4febc4ed /.venv/lib/python3.12/site-packages/lxml/nsclasses.pxi | |
parent | cc961e04ba734dd72309fb548a2f97d67d578813 (diff) | |
download | gn-ai-master.tar.gz |
Diffstat (limited to '.venv/lib/python3.12/site-packages/lxml/nsclasses.pxi')
-rw-r--r-- | .venv/lib/python3.12/site-packages/lxml/nsclasses.pxi | 281 |
1 files changed, 281 insertions, 0 deletions
diff --git a/.venv/lib/python3.12/site-packages/lxml/nsclasses.pxi b/.venv/lib/python3.12/site-packages/lxml/nsclasses.pxi new file mode 100644 index 00000000..a3c86f0e --- /dev/null +++ b/.venv/lib/python3.12/site-packages/lxml/nsclasses.pxi @@ -0,0 +1,281 @@ +# module-level API for namespace implementations + +cdef class LxmlRegistryError(LxmlError): + """Base class of lxml registry errors. + """ + +cdef class NamespaceRegistryError(LxmlRegistryError): + """Error registering a namespace extension. + """ + + +@cython.internal +cdef class _NamespaceRegistry: + "Dictionary-like namespace registry" + cdef object _ns_uri + cdef bytes _ns_uri_utf + cdef dict _entries + cdef char* _c_ns_uri_utf + def __cinit__(self, ns_uri): + self._ns_uri = ns_uri + if ns_uri is None: + self._ns_uri_utf = None + self._c_ns_uri_utf = NULL + else: + self._ns_uri_utf = _utf8(ns_uri) + self._c_ns_uri_utf = _cstr(self._ns_uri_utf) + self._entries = {} + + def update(self, class_dict_iterable): + """update(self, class_dict_iterable) + + Forgivingly update the registry. + + ``class_dict_iterable`` may be a dict or some other iterable + that yields (name, value) pairs. + + If a value does not match the required type for this registry, + or if the name starts with '_', it will be silently discarded. + This allows registrations at the module or class level using + vars(), globals() etc.""" + if hasattr(class_dict_iterable, 'items'): + class_dict_iterable = class_dict_iterable.items() + for name, item in class_dict_iterable: + if (name is None or name[:1] != '_') and callable(item): + self[name] = item + + def __getitem__(self, name): + if name is not None: + name = _utf8(name) + return self._get(name) + + def __delitem__(self, name): + if name is not None: + name = _utf8(name) + del self._entries[name] + + cdef object _get(self, object name): + cdef python.PyObject* dict_result + dict_result = python.PyDict_GetItem(self._entries, name) + if dict_result is NULL: + raise KeyError, "Name not registered." + return <object>dict_result + + cdef object _getForString(self, char* name): + cdef python.PyObject* dict_result + dict_result = python.PyDict_GetItem(self._entries, name) + if dict_result is NULL: + raise KeyError, "Name not registered." + return <object>dict_result + + def __iter__(self): + return iter(self._entries) + + def items(self): + return list(self._entries.items()) + + def iteritems(self): + return iter(self._entries.items()) + + def clear(self): + self._entries.clear() + + def __call__(self, obj): + # Usage as decorator: + # ns = lookup.get_namespace("...") + # @ns('abc') + # class element(ElementBase): pass + # + # @ns + # class elementname(ElementBase): pass + + if obj is None or python._isString(obj): + # @ns(None) or @ns('tag') + return partial(self.__deco, obj) + # plain @ns decorator + self[obj.__name__] = obj + return obj + + def __deco(self, name, obj): + self[name] = obj + return obj + + +@cython.final +@cython.internal +cdef class _ClassNamespaceRegistry(_NamespaceRegistry): + "Dictionary-like registry for namespace implementation classes" + def __setitem__(self, name, item): + if not isinstance(item, type) or not issubclass(item, ElementBase): + raise NamespaceRegistryError, \ + "Registered element classes must be subtypes of ElementBase" + if name is not None: + name = _utf8(name) + self._entries[name] = item + + def __repr__(self): + return "Namespace(%r)" % self._ns_uri + + +cdef class ElementNamespaceClassLookup(FallbackElementClassLookup): + """ElementNamespaceClassLookup(self, fallback=None) + + Element class lookup scheme that searches the Element class in the + Namespace registry. + + Usage: + + >>> lookup = ElementNamespaceClassLookup() + >>> ns_elements = lookup.get_namespace("http://schema.org/Movie") + + >>> @ns_elements + ... class movie(ElementBase): + ... "Element implementation for 'movie' tag (using class name) in schema namespace." + + >>> @ns_elements("movie") + ... class MovieElement(ElementBase): + ... "Element implementation for 'movie' tag (explicit tag name) in schema namespace." + """ + cdef dict _namespace_registries + def __cinit__(self): + self._namespace_registries = {} + + def __init__(self, ElementClassLookup fallback=None): + FallbackElementClassLookup.__init__(self, fallback) + self._lookup_function = _find_nselement_class + + def get_namespace(self, ns_uri): + """get_namespace(self, ns_uri) + + Retrieve the namespace object associated with the given URI. + Pass None for the empty namespace. + + Creates a new namespace object if it does not yet exist.""" + if ns_uri: + ns_utf = _utf8(ns_uri) + else: + ns_utf = None + try: + return self._namespace_registries[ns_utf] + except KeyError: + registry = self._namespace_registries[ns_utf] = \ + _ClassNamespaceRegistry(ns_uri) + return registry + +cdef object _find_nselement_class(state, _Document doc, xmlNode* c_node): + cdef python.PyObject* dict_result + cdef ElementNamespaceClassLookup lookup + cdef _NamespaceRegistry registry + if state is None: + return _lookupDefaultElementClass(None, doc, c_node) + + lookup = <ElementNamespaceClassLookup>state + if c_node.type != tree.XML_ELEMENT_NODE: + return _callLookupFallback(lookup, doc, c_node) + + c_namespace_utf = _getNs(c_node) + if c_namespace_utf is not NULL: + dict_result = python.PyDict_GetItem( + lookup._namespace_registries, <unsigned char*>c_namespace_utf) + else: + dict_result = python.PyDict_GetItem( + lookup._namespace_registries, None) + if dict_result is not NULL: + registry = <_NamespaceRegistry>dict_result + classes = registry._entries + + if c_node.name is not NULL: + dict_result = python.PyDict_GetItem( + classes, <unsigned char*>c_node.name) + else: + dict_result = NULL + + if dict_result is NULL: + dict_result = python.PyDict_GetItem(classes, None) + + if dict_result is not NULL: + return <object>dict_result + return _callLookupFallback(lookup, doc, c_node) + + +################################################################################ +# XPath extension functions + +cdef dict __FUNCTION_NAMESPACE_REGISTRIES +__FUNCTION_NAMESPACE_REGISTRIES = {} + +def FunctionNamespace(ns_uri): + """FunctionNamespace(ns_uri) + + Retrieve the function namespace object associated with the given + URI. + + Creates a new one if it does not yet exist. A function namespace + can only be used to register extension functions. + + Usage: + + >>> ns_functions = FunctionNamespace("http://schema.org/Movie") + + >>> @ns_functions # uses function name + ... def add2(x): + ... return x + 2 + + >>> @ns_functions("add3") # uses explicit name + ... def add_three(x): + ... return x + 3 + """ + ns_utf = _utf8(ns_uri) if ns_uri else None + try: + return __FUNCTION_NAMESPACE_REGISTRIES[ns_utf] + except KeyError: + registry = __FUNCTION_NAMESPACE_REGISTRIES[ns_utf] = \ + _XPathFunctionNamespaceRegistry(ns_uri) + return registry + +@cython.internal +cdef class _FunctionNamespaceRegistry(_NamespaceRegistry): + def __setitem__(self, name, item): + if not callable(item): + raise NamespaceRegistryError, \ + "Registered functions must be callable." + if not name: + raise ValueError, \ + "extensions must have non empty names" + self._entries[_utf8(name)] = item + + def __repr__(self): + return "FunctionNamespace(%r)" % self._ns_uri + +@cython.final +@cython.internal +cdef class _XPathFunctionNamespaceRegistry(_FunctionNamespaceRegistry): + cdef object _prefix + cdef bytes _prefix_utf + + property prefix: + "Namespace prefix for extension functions." + def __del__(self): + self._prefix = None # no prefix configured + self._prefix_utf = None + def __get__(self): + if self._prefix is None: + return '' + else: + return self._prefix + def __set__(self, prefix): + if prefix == '': + prefix = None # empty prefix + self._prefix_utf = _utf8(prefix) if prefix is not None else None + self._prefix = prefix + +cdef list _find_all_extension_prefixes(): + "Internal lookup function to find all function prefixes for XSLT/XPath." + cdef _XPathFunctionNamespaceRegistry registry + cdef list ns_prefixes = [] + for registry in __FUNCTION_NAMESPACE_REGISTRIES.itervalues(): + if registry._prefix_utf is not None: + if registry._ns_uri_utf is not None: + ns_prefixes.append( + (registry._prefix_utf, registry._ns_uri_utf)) + return ns_prefixes |