Package cssutils :: Package stylesheets :: Module medialist |
[hide private]
[frames] | no frames]

# Source Code for Module cssutils.stylesheets.medialist

      1  """
      2  MediaList implements DOM Level 2 Style Sheets MediaList.
      3
      4  TODO:
      5      delete: maybe if deleting from all, replace *all* with all others?
      6      is unknown media an exception?
      7  """
      8  __all__ = ['MediaList']
      9  __docformat__ = 'restructuredtext'
     10  __author__ = '$LastChangedBy: cthedot $'
     11  __date__ = '$LastChangedDate: 2007-08-20 22:07:12 +0200 (Mo, 20 Aug 2007) $'
     12  __version__ = '$LastChangedRevision: 257 $'
     13
     14  import xml.dom
     15  import cssutils
     16  from cssutils.css import csscomment
     17
     18 -class MediaList(cssutils.util.Base, list):
     19      """
     20      Provides the abstraction of an ordered collection of media,
     21      without defining or constraining how this collection is
     22      implemented.
     23      An empty list is the same as a list that contains the medium "all".
     24
     25      Properties
     26      ==========
     27      length:
     28          The number of media in the list.
     29      mediaText: of type DOMString
     30          The parsable textual representation of this medialist
     31      seq: a list (cssutils)
     32          All parts of this MediaList including CSSComments
     33      valid:
     34          if this list is valid
     35
     36      Format
     37      ======
     38      medium [ COMMA S* medium ]*
     39      """
     40
     41      _MEDIA = [u'all', u'aural', u'braille', u'embossed', u'handheld',
     42          u'print', u'projection', u'screen', u'tty', u'tv']
     43      "available media types"
     44
     45 -    def __init__(self, mediaText=None, readonly=False):
     46          """
     47          mediaText
     48              unicodestring of parsable comma separared media
     49          """
     50          super(MediaList, self).__init__()
     51
     52          self.valid = True
     53
     54          if isinstance(mediaText, list):
     55              mediaText = ", ".join(mediaText)
     56
     57          if mediaText:
     58              self._seq = []
     59              self.mediaText = mediaText
     60          else:
     61              self.seq = []
     62          self._readonly = readonly
     63
     64 -    def _getLength(self):
     65          """
     66          returns count of media in this list which is not the same as
     67          len(MediaListInstance) which also contains CSSComments
     68          """
     69          return len(self)
     70
     71      length = property(_getLength,
     72          doc="(DOM readonly) The number of media in the list.")
     73
     74 -    def _getSeq(self):
     75          return self._seq
     76
     77 -    def _setSeq(self, seq):
     78          self._seq = seq
     79
     80      seq = property(_getSeq, _setSeq,
     81          doc="All parts of this MediaList including CSSComments")
     82
     83 -    def _getMediaText(self):
     84          """
     85          returns serialized property mediaText
     86          """
     87          return cssutils.ser.do_stylesheets_medialist(self)
     88
     89 -    def _setMediaText(self, mediaText):
     90          """
     91          mediaText
     92              simple value or comma-separated list of media
     93
     94          DOMException
     95
     96          - SYNTAX_ERR: (self)
     97            Raised if the specified string value has a syntax error and is
     98            unparsable.
     99          - NO_MODIFICATION_ALLOWED_ERR: (self)
    100            Raised if this media list is readonly.
    101          """
    102          self._checkReadonly()
    103          tokens = self._tokenize(mediaText)
    104
    105          newseq = []
    106          del self[:] # reset
    107          expected = 'medium1'
    108          valid = True
    109          for i in range(len(tokens)):
    110              t = tokens[i]
    111              if self._ttypes.S == t.type: # ignore
    112                  pass
    113
    114              elif self._ttypes.COMMENT == t.type: # just add
    115                  newseq.append(csscomment.CSSComment(t))
    116
    117              elif expected.startswith('medium') and self._ttypes.IDENT == t.type:
    118                  _newmed = t.value.lower()
    119                  self.appendMedium(_newmed)
    120                  newseq.append(_newmed)
    121                  expected = 'comma'
    122
    123              elif self._ttypes.IDENT == t.type:
    124                  valid = False
    125                  self._log.error(
    126                      u'MediaList: Syntax Error, expected ",".', t)
    127
    128              elif 'comma' == expected and self._ttypes.COMMA == t.type:
    129                  newseq.append(t.value)
    130                  expected = 'medium'
    131
    132              elif self._ttypes.COMMA == t.type:
    133                  valid = False
    134                  self._log.error(u'MediaList: Syntax Error, expected ",".', t)
    135
    136              else:
    137                  self._log.error(u'MediaList: Syntax Error in "%s".' %
    138                            self._valuestr(tokens), t)
    139
    140          if 'medium' == expected:
    141              valid = False
    142              self._log.error(
    143                  u'MediaList: Syntax Error, cannot end with ",".')
    144          self.seq = newseq
    145          self.valid = valid
    146
    147      mediaText = property(_getMediaText, _setMediaText,
    148          doc="""(DOM) The parsable textual representation of the media list.
    149              This is a comma-separated list of media.""")
    150
    151 -    def appendMedium(self, newMedium):
    152          """
    153          (DOM)
    154          Adds the medium newMedium to the end of the list. If the newMedium
    155          is already used, it is first removed.
    156
    157          returns if newMedium is valid
    158
    159          DOMException
    160
    161          - INVALID_CHARACTER_ERR: (self)
    162            If the medium contains characters that are invalid in the
    163            underlying style language.
    164          - NO_MODIFICATION_ALLOWED_ERR: (self)
    165            Raised if this list is readonly.
    166          """
    167          self._checkReadonly()
    168          tokens = self._tokenize(newMedium)
    169
    170          valid = True
    171
    172          # ? should check format only?
    173          try:
    174              newMedium = tokens[0].value.lower()
    175          except (IndexError, AttributeError):
    176              self._log.error(
    177                  u'MediaList: "%s" is not a valid medium.' % self._valuestr(
    178                      newMedium), error=xml.dom.InvalidCharacterErr)
    179              return
    180
    181          if newMedium not in self._MEDIA:
    182              valid = False
    183              self._log.error(
    184                  u'MediaList: "%s" is not a valid medium.' % newMedium,
    185                  tokens[0], xml.dom.InvalidCharacterErr)
    186
    187          # all contains every other (except handheld!)
    188          if u'all' in self and newMedium != u'handheld':
    189              return valid
    190          if newMedium == u'all':
    191              if u'handheld' in self:
    192                  addhandheld2seq = True
    193              else:
    194                  addhandheld2seq = False
    195              del self[:]
    196              self.append(u'all')
    197              self._seq = [u'all']
    198              if addhandheld2seq:
    199                  #self.append(u'handheld')
    200                  self._seq.append(u',')
    201                  self._seq.append(u'handheld')
    202          else:
    203              if newMedium in self:
    204                  self.remove(newMedium)
    205
    206                  # remove medium and possible ,!
    207                  look4comma = False
    208                  newseq = []
    209                  for x in self._seq:
    210                      if newMedium == x:
    211                          look4comma = True
    212                          continue # remove
    213                      if u',' == x and look4comma:
    214                          look4comma = False
    215                          continue
    216                      else:
    217                          newseq.append(x)
    218                  self._seq = newseq
    219
    220              if len(self) > 0: # already 1 there, add "," + medium 2 seq
    221                  self._seq.append(u',')
    222
    223              self._seq.append(newMedium)
    224              self.append(newMedium)
    225          return valid
    226
    227 -    def deleteMedium(self, oldMedium):
    228          """
    229          (DOM)
    230          Deletes the medium indicated by oldMedium from the list.
    231
    232          DOMException
    233
    234          - NO_MODIFICATION_ALLOWED_ERR: (self)
    235            Raised if this list is readonly.
    236          - NOT_FOUND_ERR: (self)
    237            Raised if oldMedium is not in the list.
    238          """
    239          self._checkReadonly()
    240          oldMedium = oldMedium.lower()
    241          try:
    242              self.remove(oldMedium)
    243              self._seq.remove(oldMedium)
    244          except ValueError:
    245              raise xml.dom.NotFoundErr(
    246                  u'"%s" not in this MediaList' % oldMedium)
    247
    248 -    def item(self, index):
    249          """
    250          (DOM)
    251          Returns the index'th element in the list. If index is greater than
    252          or equal to the number of media in the list, this returns None.
    253          """
    254          try:
    255              return self[index]
    256          except IndexError:
    257              return None
    258
    259 -    def __repr__(self):
    260          return "cssutils.stylesheets.%s(mediaText=%r)" % (
    261                  self.__class__.__name__, self.mediaText)
    262
    263 -    def __str__(self):
    264          return "<cssutils.stylesheets.%s object mediaText=%r at 0x%x>" % (
    265                  self.__class__.__name__, self.mediaText, id(self))
    266
    267
    268  if __name__ == '__main__':
    269      m = MediaList()
    270      m.mediaText = u'all; @x'
    271      print m.mediaText
    272