1edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep"""Registration facilities for DOM. This module should not be used
2edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoepdirectly. Instead, the functions getDOMImplementation and
3edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander StoepregisterDOMImplementation should be imported from xml.dom."""
4edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep
5edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoepfrom xml.dom.minicompat import *  # isinstance, StringTypes
6edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep
7edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep# This is a list of well-known implementations.  Well-known names
8edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep# should be published by posting to xml-sig@python.org, and are
9edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep# subsequently recorded in this file.
10edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep
11edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoepwell_known_implementations = {
12edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    'minidom':'xml.dom.minidom',
13edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    '4DOM': 'xml.dom.DOMImplementation',
14edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    }
15edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep
16edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep# DOM implementations not officially registered should register
17edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep# themselves with their
18edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep
19edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoepregistered = {}
20edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep
21edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoepdef registerDOMImplementation(name, factory):
22edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    """registerDOMImplementation(name, factory)
23edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep
24edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    Register the factory function with the name. The factory function
25edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    should return an object which implements the DOMImplementation
26edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    interface. The factory function can either return the same object,
27edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    or a new one (e.g. if that implementation supports some
28edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    customization)."""
29edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep
30edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    registered[name] = factory
31edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep
32edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoepdef _good_enough(dom, features):
33edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    "_good_enough(dom, features) -> Return 1 if the dom offers the features"
34edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    for f,v in features:
35edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        if not dom.hasFeature(f,v):
36edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep            return 0
37edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    return 1
38edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep
39edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoepdef getDOMImplementation(name = None, features = ()):
40edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    """getDOMImplementation(name = None, features = ()) -> DOM implementation.
41edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep
42edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    Return a suitable DOM implementation. The name is either
43edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    well-known, the module name of a DOM implementation, or None. If
44edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    it is not None, imports the corresponding module and returns
45edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    DOMImplementation object if the import succeeds.
46edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep
47edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    If name is not given, consider the available implementations to
48edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    find one with the required feature set. If no implementation can
49edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    be found, raise an ImportError. The features list must be a sequence
50edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    of (feature, version) pairs which are passed to hasFeature."""
51edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep
52edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    import os
53edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    creator = None
54edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    mod = well_known_implementations.get(name)
55edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    if mod:
56edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        mod = __import__(mod, {}, {}, ['getDOMImplementation'])
57edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        return mod.getDOMImplementation()
58edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    elif name:
59edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        return registered[name]()
60edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    elif "PYTHON_DOM" in os.environ:
61edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        return getDOMImplementation(name = os.environ["PYTHON_DOM"])
62edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep
63edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    # User did not specify a name, try implementations in arbitrary
64edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    # order, returning the one that has the required features
65edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    if isinstance(features, StringTypes):
66edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        features = _parse_feature_string(features)
67edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    for creator in registered.values():
68edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        dom = creator()
69edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        if _good_enough(dom, features):
70edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep            return dom
71edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep
72edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    for creator in well_known_implementations.keys():
73edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        try:
74edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep            dom = getDOMImplementation(name = creator)
75edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        except StandardError: # typically ImportError, or AttributeError
76edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep            continue
77edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        if _good_enough(dom, features):
78edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep            return dom
79edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep
80edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    raise ImportError,"no suitable DOM implementation found"
81edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep
82edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoepdef _parse_feature_string(s):
83edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    features = []
84edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    parts = s.split()
85edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    i = 0
86edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    length = len(parts)
87edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    while i < length:
88edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        feature = parts[i]
89edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        if feature[0] in "0123456789":
90edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep            raise ValueError, "bad feature name: %r" % (feature,)
91edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        i = i + 1
92edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        version = None
93edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        if i < length:
94edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep            v = parts[i]
95edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep            if v[0] in "0123456789":
96edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep                i = i + 1
97edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep                version = v
98edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        features.append((feature, version))
99edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    return tuple(features)
100