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

# Source Code for Module cssutils.css.cssimportrule

      1  """CSSImportRule implements DOM Level 2 CSS CSSImportRule.
      2
      3  plus:
      4      name
      5          http://www.w3.org/TR/css3-cascade/#cascading
      6
      7  TODO:
      8      - stylesheet: read and parse linked stylesheet
      9  """
     10  __all__ = ['CSSImportRule']
     11  __docformat__ = 'restructuredtext'
     12  __author__ = '$LastChangedBy: cthedot $'
     13  __date__ = '$LastChangedDate: 2008-02-19 22:56:27 +0100 (Di, 19 Feb 2008) $'
     14  __version__ = '$LastChangedRevision: 1068 $'
     15
     16  import xml.dom
     17  import cssrule
     18  import cssutils
     19
     20 -class CSSImportRule(cssrule.CSSRule):
     21      """
     22      Represents an @import rule within a CSS style sheet.  The @import rule
     23      is used to import style rules from other style sheets.
     24
     25      Properties
     26      ==========
     27      atkeyword: (cssutils only)
     28          the literal keyword used
     29      cssText: of type DOMString
     30          The parsable textual representation of this rule
     31      href: of type DOMString, (DOM readonly, cssutils also writable)
     32          The location of the style sheet to be imported. The attribute will
     33          not contain the url(...) specifier around the URI.
     34      hreftype: 'uri' (serializer default) or 'string' (cssutils only)
     35          The original type of href, not really relevant as it may be
     36          reconfigured in the serializer but it is kept anyway
     37      media: of type stylesheets::MediaList (DOM readonly)
     38          A list of media types for this rule of type MediaList.
     39      name:
     40          An optional name used for cascading
     41      stylesheet: of type CSSStyleSheet (DOM readonly)
     42          The style sheet referred to by this rule. The value of this
     43          attribute is None if the style sheet has not yet been loaded or if
     44          it will not be loaded (e.g. if the stylesheet is for a media type
     45          not supported by the user agent).
     46
     47          Currently always None
     48
     49      Inherits properties from CSSRule
     50
     51      Format
     52      ======
     53      import
     54        : IMPORT_SYM S*
     55        [STRING|URI] S* [ medium [ COMMA S* medium]* ]? S* STRING? S* ';' S*
     56        ;
     57      """
     58      type = cssrule.CSSRule.IMPORT_RULE
     59
     60 -    def __init__(self, href=None, mediaText=u'all', name=None,
     61                   parentRule=None, parentStyleSheet=None, readonly=False):
     62          """
     63          if readonly allows setting of properties in constructor only
     64
     65          Do not use as positional but as keyword attributes only!
     66
     67          href
     68              location of the style sheet to be imported.
     69          mediaText
     70              A list of media types for which this style sheet may be used
     71              as a string
     72          """
     73          super(CSSImportRule, self).__init__(parentRule=parentRule,
     74                                              parentStyleSheet=parentStyleSheet)
     75          self.atkeyword = u'@import'
     76          self.hreftype = None
     77
     78          self._href = None
     79          self.href = href
     80
     81          self._media = cssutils.stylesheets.MediaList(
     82              mediaText, readonly=readonly)
     83          self._name = name
     84          if not self.media.wellformed:
     85              self._media = cssutils.stylesheets.MediaList()
     86
     87          seq = self._tempSeq()
     88          seq.append(self.href, 'href')
     89          seq.append(self.media, 'media')
     90          seq.append(self.name, 'name')
     91          self._setSeq(seq)
     92
     93          # TODO: load stylesheet from href automatically?
     94          self._styleSheet = None
     95
     96          self._readonly = readonly
     97
     98 -    def _getCssText(self):
     99          """
    100          returns serialized property cssText
    101          """
    102          return cssutils.ser.do_CSSImportRule(self)
    103
    104 -    def _setCssText(self, cssText):
    105          """
    106          DOMException on setting
    107
    108          - HIERARCHY_REQUEST_ERR: (CSSStylesheet)
    109            Raised if the rule cannot be inserted at this point in the
    110            style sheet.
    111          - INVALID_MODIFICATION_ERR: (self)
    112            Raised if the specified CSS string value represents a different
    113            type of rule than the current one.
    114          - NO_MODIFICATION_ALLOWED_ERR: (CSSRule)
    115            Raised if the rule is readonly.
    116          - SYNTAX_ERR: (self)
    117            Raised if the specified CSS string value has a syntax error and
    118            is unparsable.
    119          """
    120          super(CSSImportRule, self)._setCssText(cssText)
    121          tokenizer = self._tokenize2(cssText)
    122          attoken = self._nexttoken(tokenizer, None)
    123          if self._type(attoken) != self._prods.IMPORT_SYM:
    124              self._log.error(u'CSSImportRule: No CSSImportRule found: %s' %
    125                  self._valuestr(cssText),
    126                  error=xml.dom.InvalidModificationErr)
    127          else:
    128              # for closures: must be a mutable
    129              new = {'keyword': self._tokenvalue(attoken),
    130                     'href': None,
    131                     'hreftype': None,
    132                     'media': cssutils.stylesheets.MediaList(),
    133                     'name': None,
    134                     'wellformed': True
    135                     }
    136
    137              def __doname(seq, token):
    138                  # called by _string or _ident
    139                  new['name'] = self._stringtokenvalue(token)
    140                  seq.append(new['name'], 'name')
    141                  return ';'
    142
    143              def _string(expected, seq, token, tokenizer=None):
    144                  if 'href' == expected:
    145                      # href
    146                      new['href'] = self._stringtokenvalue(token)
    147                      new['hreftype'] = 'string'
    148                      seq.append(new['href'], 'href')
    149                      return 'media name ;'
    150                  elif 'name' in expected:
    151                      # name
    152                      return __doname(seq, token)
    153                  else:
    154                      new['wellformed'] = False
    155                      self._log.error(
    156                          u'CSSImportRule: Unexpected string.', token)
    157                      return expected
    158
    159              def _uri(expected, seq, token, tokenizer=None):
    160                  # href
    161                  if 'href' == expected:
    162                      uri = self._uritokenvalue(token)
    163                      new['hreftype'] = 'uri'
    164                      new['href'] = uri
    165                      seq.append(new['href'], 'href')
    166                      return 'media name ;'
    167                  else:
    168                      new['wellformed'] = False
    169                      self._log.error(
    170                          u'CSSImportRule: Unexpected URI.', token)
    171                      return expected
    172
    173              def _ident(expected, seq, token, tokenizer=None):
    174                  # medialist ending with ; which is checked upon too
    175                  if expected.startswith('media'):
    176                      mediatokens = self._tokensupto2(
    177                          tokenizer, importmediaqueryendonly=True)
    178                      mediatokens.insert(0, token) # push found token
    179
    180                      last = mediatokens.pop() # retrieve ;
    181                      lastval, lasttyp = self._tokenvalue(last), self._type(last)
    182                      if lastval != u';' and lasttyp not in ('EOF', self._prods.STRING):
    183                          new['wellformed'] = False
    184                          self._log.error(u'CSSImportRule: No ";" found: %s' %
    185                                          self._valuestr(cssText), token=token)
    186
    187                      media = cssutils.stylesheets.MediaList()
    188                      media.mediaText = mediatokens
    189                      if media.wellformed:
    190                          new['media'] = media
    191                          seq.append(media, 'media')
    192                      else:
    193                          new['wellformed'] = False
    194                          self._log.error(u'CSSImportRule: Invalid MediaList: %s' %
    195                                          self._valuestr(cssText), token=token)
    196
    197                      if lasttyp == self._prods.STRING:
    198                          # name
    199                          return __doname(seq, last)
    200                      else:
    201                          return 'EOF' # ';' is token "last"
    202                  else:
    203                      new['wellformed'] = False
    204                      self._log.error(
    205                          u'CSSImportRule: Unexpected ident.', token)
    206                      return expected
    207
    208              def _char(expected, seq, token, tokenizer=None):
    209                  # final ;
    210                  val = self._tokenvalue(token)
    211                  if expected.endswith(';') and u';' == val:
    212                      return 'EOF'
    213                  else:
    214                      new['wellformed'] = False
    215                      self._log.error(
    216                          u'CSSImportRule: Unexpected char.', token)
    217                      return expected
    218
    219              # import : IMPORT_SYM S* [STRING|URI]
    220              #            S* [ medium [ ',' S* medium]* ]? ';' S*
    221              #         STRING? # see http://www.w3.org/TR/css3-cascade/#cascading
    222              #        ;
    223              newseq = self._tempSeq()
    224              wellformed, expected = self._parse(expected='href',
    225                  seq=newseq, tokenizer=tokenizer,
    226                  productions={'STRING': _string,
    227                               'URI': _uri,
    228                               #'FUNCTION': _function,
    229                               'IDENT': _ident,
    230                               'CHAR': _char})
    231
    232              # wellformed set by parse
    233              wellformed = wellformed and new['wellformed']
    234
    235              # post conditions
    236              if not new['href']:
    237                  wellformed = False
    238                  self._log.error(u'CSSImportRule: No href found: %s' %
    239                      self._valuestr(cssText))
    240
    241              if expected != 'EOF':
    242                  wellformed = False
    243                  self._log.error(u'CSSImportRule: No ";" found: %s' %
    244                      self._valuestr(cssText))
    245
    246              # set all
    247              if wellformed:
    248                  self.atkeyword = new['keyword']
    249                  self.href = new['href']
    250                  self.hreftype = new['hreftype']
    251                  self._media = new['media']
    252                  self.name = new['name']
    253                  self._setSeq(newseq)
    254
    255      cssText = property(fget=_getCssText, fset=_setCssText,
    256          doc="(DOM attribute) The parsable textual representation.")
    257
    258 -    def _setHref(self, href):
    259          # update seq
    260          for i, item in enumerate(self.seq):
    261              val, typ = item.value, item.type
    262              if 'href' == typ:
    263                  self._seq[i] = (href, typ, item.line, item.col)
    264                  break
    265          else:
    266              seq = self._tempSeq()
    267              seq.append(self.href, 'href')
    268              self._setSeq(seq)
    269          # set new href
    270          self._href = href
    271
    272      href = property(lambda self: self._href, _setHref,
    273                      doc="Location of the style sheet to be imported.")
    274
    275      media = property(lambda self: self._media,
    276                       doc=u"(DOM readonly) A list of media types for this rule"
    277                       " of type MediaList")
    278
    279 -    def _setName(self, name):
    280          # update seq
    281          for i, item in enumerate(self.seq):
    282              val, typ = item.value, item.type
    283              if 'name' == typ:
    284                  self._seq[i] = (name, typ, item.line, item.col)
    285                  break
    286          else:
    287              # append
    288              seq = self._tempSeq()
    289              for item in self.seq:
    290                  # copy current seq
    291                  seq.append(item.value, item.type, item.line, item.col)
    292              seq.append(self.href, 'href')
    293              self._setSeq(seq)
    294          self._name = name
    295
    296      name = property(lambda self: self._name, _setName,
    297                      doc=u"An optional name for the imported sheet")
    298
    299      styleSheet = property(lambda self: self._styleSheet,
    300                            doc="(readonly) The style sheet referred to by this rule.")
    301
    302      wellformed = property(lambda self: bool(self.href and self.media.wellformed))
    303
    304 -    def __repr__(self):
    305          return "cssutils.css.%s(href=%r, mediaText=%r, name=%r)" % (
    306                  self.__class__.__name__,
    307                  self.href, self.media.mediaText, self.name)
    308
    309 -    def __str__(self):
    310          return "<cssutils.css.%s object href=%r at 0x%x>" % (
    311                  self.__class__.__name__, self.href, id(self))
    312