Package cssutils :: Package css :: Module selectorlist |
[hide private]
[frames] | no frames]

# Source Code for Module cssutils.css.selectorlist

      1  """SelectorList is a list of CSS Selector objects.
      2
      3  TODO
      4      - ??? CSS2 gives a special meaning to the comma (,) in selectors.
      5          However, since it is not known if the comma may acquire other
      6          meanings in future versions of CSS, the whole statement should be
      7          ignored if there is an error anywhere in the selector, even though
      8          the rest of the selector may look reasonable in CSS2.
      9
     10          Illegal example(s):
     11
     12          For example, since the "&" is not a valid token in a CSS2 selector,
     13          a CSS2 user agent must ignore the whole second line, and not set
     14          the color of H3 to red:
     15  """
     16  __all__ = ['SelectorList']
     17  __docformat__ = 'restructuredtext'
     18  __author__ = '$LastChangedBy: cthedot $'
     19  __date__ = '$LastChangedDate: 2008-01-06 01:14:26 +0100 (So, 06 Jan 2008) $'
     20  __version__ = '$LastChangedRevision: 820 $'
     21
     22  import xml.dom
     23  import cssutils
     24  from selector import Selector
     25
     26 -class SelectorList(cssutils.util.Base, cssutils.util.ListSeq):
     27      """
     28      (cssutils) a list of Selectors of a CSSStyleRule
     29
     30      Properties
     31      ==========
     32      length: of type unsigned long, readonly
     33          The number of Selector elements in the list.
     34      namespaces
     35          **TODO:**
     36          a dict of {prefix: namespaceURI} mapping, may also be a
     37          CSSStyleSheet in which case the namespaces defined there
     38          are used. If None cssutils tries to get the namespaces as
     39          defined in a possible parent CSSStyleSheet.
     40      parentRule: of type CSSRule, readonly
     41          The CSS rule that contains this declaration block or None if this
     42          CSSStyleDeclaration is not attached to a CSSRule.
     43      selectorText: of type DOMString
     44          The textual representation of the selector for the rule set. The
     45          implementation may have stripped out insignificant whitespace while
     46          parsing the selector.
     47      seq:
     48          A list of interwoven Selector objects and u','
     49      wellformed
     50          if this selectorlist is wellformed regarding the Selector spec
     51      """
     52 -    def __init__(self, selectorText=None, namespaces=None,
     53                   parentRule=None, readonly=False):
     54          """
     55          initializes SelectorList with optional selectorText
     56          """
     57          super(SelectorList, self).__init__()
     58
     59          self.wellformed = False
     60          if not namespaces:
     61              namespaces = {}
     62          self.namespaces = namespaces
     63          self.parentRule = parentRule
     64          if selectorText:
     65              self.selectorText = selectorText
     66          self._readonly = readonly
     67
     68 -    def __prepareset(self, newSelector):
     69          # used by appendSelector and __setitem__
     70          self._checkReadonly()
     71
     72          if not isinstance(newSelector, Selector):
     73              newSelector = Selector(newSelector, namespaces=self.namespaces)
     74
     75          if newSelector.wellformed:
     76              newSelector.parentRule = self
     77              return newSelector
     78
     79 -    def __setitem__(self, index, newSelector):
     80          """
     81          overwrites ListSeq.__setitem__
     82
     83          Any duplicate Selectors are **not** removed.
     84          """
     85          newSelector = self.__prepareset(newSelector)
     86          if newSelector:
     87              self.seq[index] = newSelector
     88          # TODO: remove duplicates?
     89
     90 -    def appendSelector(self, newSelector):
     91          """
     92          Append newSelector (is a string will be converted to a new
     93          Selector. A duplicate Selector is removed.
     94
     95          Returns new Selector or None if newSelector is no wellformed
     96          Selector.
     97
     98          DOMException on setting
     99
    100          - SYNTAX_ERR: (self)
    101            Raised if the specified CSS string value has a syntax error
    102            and is unparsable.
    103          - NO_MODIFICATION_ALLOWED_ERR: (self)
    104            Raised if this rule is readonly.
    105          """
    106          newSelector = self.__prepareset(newSelector)
    107          if newSelector:
    108              self.wellformed = True
    109              seq = self.seq[:]
    110              del self.seq[:]
    111              for s in seq:
    112                  if s.selectorText != newSelector.selectorText:
    113                      self.seq.append(s)
    114              self.seq.append(newSelector)
    115              return newSelector
    116
    117 -    def append(self, newSelector):
    118          "overwrites ListSeq.append"
    119          self.appendSelector(newSelector)
    120
    121      length = property(lambda self: len(self),
    122          doc="The number of Selector elements in the list.")
    123
    124 -    def _getSelectorText(self):
    125          "returns serialized format"
    126          return cssutils.ser.do_css_SelectorList(self)
    127
    128 -    def _setSelectorText(self, selectorText):
    129          """
    130          selectortext
    131              comma-separated list of selectors
    132
    133          DOMException on setting
    134
    135          - SYNTAX_ERR: (self)
    136            Raised if the specified CSS string value has a syntax error
    137            and is unparsable.
    138          - NO_MODIFICATION_ALLOWED_ERR: (self)
    139            Raised if this rule is readonly.
    140          """
    141          self._checkReadonly()
    142          wellformed = True
    143          tokenizer = self._tokenize2(selectorText)
    144          newseq = []
    145
    146          expected = True
    147          while True:
    148              # find all upto and including next ",", EOF or nothing
    149              selectortokens = self._tokensupto2(tokenizer, listseponly=True)
    150              if selectortokens:
    151                  if self._tokenvalue(selectortokens[-1]) == ',':
    152                      expected = selectortokens.pop()
    153                  else:
    154                      expected = None
    155
    156                  selector = Selector(selectortokens, namespaces=self.namespaces)
    157                  if selector.wellformed:
    158                      selector.parentRule = self.parentRule
    159                      newseq.append(selector)
    160                  else:
    161                      wellformed = False
    162                      self._log.error(u'SelectorList: Invalid Selector: %s' %
    163                                      self._valuestr(selectortokens))
    164              else:
    165                  break
    166
    167          # post condition
    168          if u',' == expected:
    169              wellformed = False
    170              self._log.error(u'SelectorList: Cannot end with ",": %r' %
    171                              self._valuestr(selectorText))
    172          elif expected:
    173              wellformed = False
    174              self._log.error(u'SelectorList: Unknown Syntax: %r' %
    175                              self._valuestr(selectorText))
    176          if wellformed:
    177              self.wellformed = wellformed
    178              self.seq = newseq
    179  #            for selector in newseq:
    180  #                 self.appendSelector(selector)
    181
    182 -    def _getParentRule(self):
    183          return self._parentRule
    184
    185 -    def _setParentRule(self, parentRule):
    186          self._parentRule = parentRule
    187          for sel in self.seq:
    188              sel.parentRule = parentRule
    189
    190      parentRule = property(_getParentRule, _setParentRule,
    191          doc="(DOM) The CSS rule that contains this SelectorList or\
    192          None if this SelectorList is not attached to a CSSRule.")
    193
    194      selectorText = property(_getSelectorText, _setSelectorText,
    195          doc="""(cssutils) The textual representation of the selector for
    196              a rule set.""")
    197
    198 -    def __repr__(self):
    199          return "cssutils.css.%s(selectorText=%r)" % (
    200                  self.__class__.__name__, self.selectorText)
    201
    202 -    def __str__(self):
    203          return "<cssutils.css.%s object selectorText=%r at 0x%x>" % (
    204                  self.__class__.__name__, self.selectorText, id(self))
    205