17db96d56Sopenharmony_ci"""Registration facilities for DOM. This module should not be used
27db96d56Sopenharmony_cidirectly. Instead, the functions getDOMImplementation and
37db96d56Sopenharmony_ciregisterDOMImplementation should be imported from xml.dom."""
47db96d56Sopenharmony_ci
57db96d56Sopenharmony_ci# This is a list of well-known implementations.  Well-known names
67db96d56Sopenharmony_ci# should be published by posting to xml-sig@python.org, and are
77db96d56Sopenharmony_ci# subsequently recorded in this file.
87db96d56Sopenharmony_ci
97db96d56Sopenharmony_ciimport sys
107db96d56Sopenharmony_ci
117db96d56Sopenharmony_ciwell_known_implementations = {
127db96d56Sopenharmony_ci    'minidom':'xml.dom.minidom',
137db96d56Sopenharmony_ci    '4DOM': 'xml.dom.DOMImplementation',
147db96d56Sopenharmony_ci    }
157db96d56Sopenharmony_ci
167db96d56Sopenharmony_ci# DOM implementations not officially registered should register
177db96d56Sopenharmony_ci# themselves with their
187db96d56Sopenharmony_ci
197db96d56Sopenharmony_ciregistered = {}
207db96d56Sopenharmony_ci
217db96d56Sopenharmony_cidef registerDOMImplementation(name, factory):
227db96d56Sopenharmony_ci    """registerDOMImplementation(name, factory)
237db96d56Sopenharmony_ci
247db96d56Sopenharmony_ci    Register the factory function with the name. The factory function
257db96d56Sopenharmony_ci    should return an object which implements the DOMImplementation
267db96d56Sopenharmony_ci    interface. The factory function can either return the same object,
277db96d56Sopenharmony_ci    or a new one (e.g. if that implementation supports some
287db96d56Sopenharmony_ci    customization)."""
297db96d56Sopenharmony_ci
307db96d56Sopenharmony_ci    registered[name] = factory
317db96d56Sopenharmony_ci
327db96d56Sopenharmony_cidef _good_enough(dom, features):
337db96d56Sopenharmony_ci    "_good_enough(dom, features) -> Return 1 if the dom offers the features"
347db96d56Sopenharmony_ci    for f,v in features:
357db96d56Sopenharmony_ci        if not dom.hasFeature(f,v):
367db96d56Sopenharmony_ci            return 0
377db96d56Sopenharmony_ci    return 1
387db96d56Sopenharmony_ci
397db96d56Sopenharmony_cidef getDOMImplementation(name=None, features=()):
407db96d56Sopenharmony_ci    """getDOMImplementation(name = None, features = ()) -> DOM implementation.
417db96d56Sopenharmony_ci
427db96d56Sopenharmony_ci    Return a suitable DOM implementation. The name is either
437db96d56Sopenharmony_ci    well-known, the module name of a DOM implementation, or None. If
447db96d56Sopenharmony_ci    it is not None, imports the corresponding module and returns
457db96d56Sopenharmony_ci    DOMImplementation object if the import succeeds.
467db96d56Sopenharmony_ci
477db96d56Sopenharmony_ci    If name is not given, consider the available implementations to
487db96d56Sopenharmony_ci    find one with the required feature set. If no implementation can
497db96d56Sopenharmony_ci    be found, raise an ImportError. The features list must be a sequence
507db96d56Sopenharmony_ci    of (feature, version) pairs which are passed to hasFeature."""
517db96d56Sopenharmony_ci
527db96d56Sopenharmony_ci    import os
537db96d56Sopenharmony_ci    creator = None
547db96d56Sopenharmony_ci    mod = well_known_implementations.get(name)
557db96d56Sopenharmony_ci    if mod:
567db96d56Sopenharmony_ci        mod = __import__(mod, {}, {}, ['getDOMImplementation'])
577db96d56Sopenharmony_ci        return mod.getDOMImplementation()
587db96d56Sopenharmony_ci    elif name:
597db96d56Sopenharmony_ci        return registered[name]()
607db96d56Sopenharmony_ci    elif not sys.flags.ignore_environment and "PYTHON_DOM" in os.environ:
617db96d56Sopenharmony_ci        return getDOMImplementation(name = os.environ["PYTHON_DOM"])
627db96d56Sopenharmony_ci
637db96d56Sopenharmony_ci    # User did not specify a name, try implementations in arbitrary
647db96d56Sopenharmony_ci    # order, returning the one that has the required features
657db96d56Sopenharmony_ci    if isinstance(features, str):
667db96d56Sopenharmony_ci        features = _parse_feature_string(features)
677db96d56Sopenharmony_ci    for creator in registered.values():
687db96d56Sopenharmony_ci        dom = creator()
697db96d56Sopenharmony_ci        if _good_enough(dom, features):
707db96d56Sopenharmony_ci            return dom
717db96d56Sopenharmony_ci
727db96d56Sopenharmony_ci    for creator in well_known_implementations.keys():
737db96d56Sopenharmony_ci        try:
747db96d56Sopenharmony_ci            dom = getDOMImplementation(name = creator)
757db96d56Sopenharmony_ci        except Exception: # typically ImportError, or AttributeError
767db96d56Sopenharmony_ci            continue
777db96d56Sopenharmony_ci        if _good_enough(dom, features):
787db96d56Sopenharmony_ci            return dom
797db96d56Sopenharmony_ci
807db96d56Sopenharmony_ci    raise ImportError("no suitable DOM implementation found")
817db96d56Sopenharmony_ci
827db96d56Sopenharmony_cidef _parse_feature_string(s):
837db96d56Sopenharmony_ci    features = []
847db96d56Sopenharmony_ci    parts = s.split()
857db96d56Sopenharmony_ci    i = 0
867db96d56Sopenharmony_ci    length = len(parts)
877db96d56Sopenharmony_ci    while i < length:
887db96d56Sopenharmony_ci        feature = parts[i]
897db96d56Sopenharmony_ci        if feature[0] in "0123456789":
907db96d56Sopenharmony_ci            raise ValueError("bad feature name: %r" % (feature,))
917db96d56Sopenharmony_ci        i = i + 1
927db96d56Sopenharmony_ci        version = None
937db96d56Sopenharmony_ci        if i < length:
947db96d56Sopenharmony_ci            v = parts[i]
957db96d56Sopenharmony_ci            if v[0] in "0123456789":
967db96d56Sopenharmony_ci                i = i + 1
977db96d56Sopenharmony_ci                version = v
987db96d56Sopenharmony_ci        features.append((feature, version))
997db96d56Sopenharmony_ci    return tuple(features)
100