Home | History | Annotate | Download | only in dom
      1 """Python version compatibility support for minidom."""
      2 
      3 # This module should only be imported using "import *".
      4 #
      5 # The following names are defined:
      6 #
      7 #   NodeList      -- lightest possible NodeList implementation
      8 #
      9 #   EmptyNodeList -- lightest possible NodeList that is guaranteed to
     10 #                    remain empty (immutable)
     11 #
     12 #   StringTypes   -- tuple of defined string types
     13 #
     14 #   defproperty   -- function used in conjunction with GetattrMagic;
     15 #                    using these together is needed to make them work
     16 #                    as efficiently as possible in both Python 2.2+
     17 #                    and older versions.  For example:
     18 #
     19 #                        class MyClass(GetattrMagic):
     20 #                            def _get_myattr(self):
     21 #                                return something
     22 #
     23 #                        defproperty(MyClass, "myattr",
     24 #                                    "return some value")
     25 #
     26 #                    For Python 2.2 and newer, this will construct a
     27 #                    property object on the class, which avoids
     28 #                    needing to override __getattr__().  It will only
     29 #                    work for read-only attributes.
     30 #
     31 #                    For older versions of Python, inheriting from
     32 #                    GetattrMagic will use the traditional
     33 #                    __getattr__() hackery to achieve the same effect,
     34 #                    but less efficiently.
     35 #
     36 #                    defproperty() should be used for each version of
     37 #                    the relevant _get_<property>() function.
     38 
     39 __all__ = ["NodeList", "EmptyNodeList", "StringTypes", "defproperty"]
     40 
     41 import xml.dom
     42 
     43 try:
     44     unicode
     45 except NameError:
     46     StringTypes = type(''),
     47 else:
     48     StringTypes = type(''), type(unicode(''))
     49 
     50 
     51 class NodeList(list):
     52     __slots__ = ()
     53 
     54     def item(self, index):
     55         if 0 <= index < len(self):
     56             return self[index]
     57 
     58     def _get_length(self):
     59         return len(self)
     60 
     61     def _set_length(self, value):
     62         raise xml.dom.NoModificationAllowedErr(
     63             "attempt to modify read-only attribute 'length'")
     64 
     65     length = property(_get_length, _set_length,
     66                       doc="The number of nodes in the NodeList.")
     67 
     68     # For backward compatibility
     69     def __setstate__(self, state):
     70         if state is None:
     71             state = []
     72         self[:] = state
     73 
     74 
     75 class EmptyNodeList(tuple):
     76     __slots__ = ()
     77 
     78     def __add__(self, other):
     79         NL = NodeList()
     80         NL.extend(other)
     81         return NL
     82 
     83     def __radd__(self, other):
     84         NL = NodeList()
     85         NL.extend(other)
     86         return NL
     87 
     88     def item(self, index):
     89         return None
     90 
     91     def _get_length(self):
     92         return 0
     93 
     94     def _set_length(self, value):
     95         raise xml.dom.NoModificationAllowedErr(
     96             "attempt to modify read-only attribute 'length'")
     97 
     98     length = property(_get_length, _set_length,
     99                       doc="The number of nodes in the NodeList.")
    100 
    101 
    102 def defproperty(klass, name, doc):
    103     get = getattr(klass, ("_get_" + name)).im_func
    104     def set(self, value, name=name):
    105         raise xml.dom.NoModificationAllowedErr(
    106             "attempt to modify read-only attribute " + repr(name))
    107     assert not hasattr(klass, "_set_" + name), \
    108            "expected not to find _set_" + name
    109     prop = property(get, set, doc=doc)
    110     setattr(klass, name, prop)
    111