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

# Source Code for Module cssutils.css.cssnamespacerule

      1  """CSSNamespaceRule currently implements
      2  http://dev.w3.org/csswg/css3-namespace/
      3
      4  (until 0.9.5a2: http://www.w3.org/TR/2006/WD-css3-namespace-20060828/)
      5  """
      6  __all__ = ['CSSNamespaceRule']
      7  __docformat__ = 'restructuredtext'
      8  __version__ = '$Id: cssnamespacerule.py 1116 2008-03-05 13:52:23Z cthedot $'
      9
     10  import xml.dom
     11  import cssrule
     12  import cssutils
     13  from cssutils.util import Deprecated
     14
     15 -class CSSNamespaceRule(cssrule.CSSRule):
     16      """
     17      Represents an @namespace rule within a CSS style sheet.
     18
     19      The @namespace at-rule declares a namespace prefix and associates
     20      it with a given namespace (a string). This namespace prefix can then be
     21      used in namespace-qualified names such as those described in the
     22      Selectors Module [SELECT] or the Values and Units module [CSS3VAL].
     23
     24      Properties
     25      ==========
     26      atkeyword (cssutils only)
     27          the literal keyword used
     28      cssText: of type DOMString
     29          The parsable textual representation of this rule
     30      namespaceURI: of type DOMString
     31          The namespace URI (a simple string!) which is bound to the given
     32          prefix. If no prefix is set (``CSSNamespaceRule.prefix==''``)
     33          the namespace defined by ``namespaceURI`` is set as the default
     34          namespace.
     35      prefix: of type DOMString
     36          The prefix used in the stylesheet for the given
     37          ``CSSNamespaceRule.nsuri``. If prefix is empty namespaceURI sets a
     38          default namespace for the stylesheet.
     39
     40      Inherits properties from CSSRule
     41
     42      Format
     43      ======
     44      namespace
     45        : NAMESPACE_SYM S* [namespace_prefix S*]? [STRING|URI] S* ';' S*
     46        ;
     47      namespace_prefix
     48        : IDENT
     49        ;
     50      """
     51      type = cssrule.CSSRule.NAMESPACE_RULE
     52
     53 -    def __init__(self, namespaceURI=None, prefix=None, cssText=None,
     54                   parentRule=None, parentStyleSheet=None, readonly=False):
     55          """
     56          :Parameters:
     57              namespaceURI
     58                  The namespace URI (a simple string!) which is bound to the
     59                  given prefix. If no prefix is set
     60                  (``CSSNamespaceRule.prefix==''``) the namespace defined by
     61                  namespaceURI is set as the default namespace
     62              prefix
     63                  The prefix used in the stylesheet for the given
     64                  ``CSSNamespaceRule.uri``.
     65              cssText
     66                  if no namespaceURI is given cssText must be given to set
     67                  a namespaceURI as this is readonly later on
     68              parentStyleSheet
     69                  sheet where this rule belongs to
     70
     71          Do not use as positional but as keyword parameters only!
     72
     73          If readonly allows setting of properties in constructor only
     74
     75          format namespace::
     76
     77              namespace
     78                : NAMESPACE_SYM S* [namespace_prefix S*]? [STRING|URI] S* ';' S*
     79                ;
     80              namespace_prefix
     81                : IDENT
     82                ;
     83          """
     84          super(CSSNamespaceRule, self).__init__(parentRule=parentRule,
     85                                                 parentStyleSheet=parentStyleSheet)
     86          self.atkeyword = u'@namespace'
     87          self._prefix = u''
     88          self._namespaceURI = None
     89
     90          if namespaceURI:
     91              self.namespaceURI = namespaceURI
     92              self.prefix = prefix
     93              tempseq = self._tempSeq()
     94              tempseq.append(self.prefix, 'prefix')
     95              tempseq.append(self.namespaceURI, 'namespaceURI')
     96              self._setSeq(tempseq)
     97          elif cssText is not None:
     98              self.cssText = cssText
     99
    100          if parentStyleSheet:
    101              self._parentStyleSheet = parentStyleSheet
    102
    103          self._readonly = readonly
    104
    105 -    def _getCssText(self):
    106          """
    107          returns serialized property cssText
    108          """
    109          return cssutils.ser.do_CSSNamespaceRule(self)
    110
    111 -    def _setCssText(self, cssText):
    112          """
    113          DOMException on setting
    114
    115          :param cssText: initial value for this rules cssText which is parsed
    116          :Exceptions:
    117              - `HIERARCHY_REQUEST_ERR`: (CSSStylesheet)
    118                Raised if the rule cannot be inserted at this point in the
    119                style sheet.
    120              - `INVALID_MODIFICATION_ERR`: (self)
    121                Raised if the specified CSS string value represents a different
    122                type of rule than the current one.
    123              - `NO_MODIFICATION_ALLOWED_ERR`: (CSSRule)
    124                Raised if the rule is readonly.
    125              - `SYNTAX_ERR`: (self)
    126                Raised if the specified CSS string value has a syntax error and
    127                is unparsable.
    128          """
    129          super(CSSNamespaceRule, self)._setCssText(cssText)
    130          tokenizer = self._tokenize2(cssText)
    131          attoken = self._nexttoken(tokenizer, None)
    132          if self._type(attoken) != self._prods.NAMESPACE_SYM:
    133              self._log.error(u'CSSNamespaceRule: No CSSNamespaceRule found: %s' %
    134                  self._valuestr(cssText),
    135                  error=xml.dom.InvalidModificationErr)
    136          else:
    137              # for closures: must be a mutable
    138              new = {'keyword': self._tokenvalue(attoken),
    139                     'prefix': u'',
    140                     'uri': None,
    141                     'wellformed': True
    142                     }
    143
    144              def _ident(expected, seq, token, tokenizer=None):
    145                  # the namespace prefix, optional
    146                  if 'prefix or uri' == expected:
    147                      new['prefix'] = self._tokenvalue(token)
    148                      seq.append(new['prefix'], 'prefix')
    149                      return 'uri'
    150                  else:
    151                      new['wellformed'] = False
    152                      self._log.error(
    153                          u'CSSNamespaceRule: Unexpected ident.', token)
    154                      return expected
    155
    156              def _string(expected, seq, token, tokenizer=None):
    157                  # the namespace URI as a STRING
    158                  if expected.endswith('uri'):
    159                      new['uri'] = self._stringtokenvalue(token)
    160                      seq.append(new['uri'], 'namespaceURI')
    161                      return ';'
    162
    163                  else:
    164                      new['wellformed'] = False
    165                      self._log.error(
    166                          u'CSSNamespaceRule: Unexpected string.', token)
    167                      return expected
    168
    169              def _uri(expected, seq, token, tokenizer=None):
    170                  # the namespace URI as URI which is DEPRECATED
    171                  if expected.endswith('uri'):
    172                      uri = self._uritokenvalue(token)
    173                      new['uri'] = uri
    174                      seq.append(new['uri'], 'namespaceURI')
    175                      return ';'
    176                  else:
    177                      new['wellformed'] = False
    178                      self._log.error(
    179                          u'CSSNamespaceRule: Unexpected URI.', token)
    180                      return expected
    181
    182              def _char(expected, seq, token, tokenizer=None):
    183                  # final ;
    184                  val = self._tokenvalue(token)
    185                  if ';' == expected and u';' == val:
    186                      return 'EOF'
    187                  else:
    188                      new['wellformed'] = False
    189                      self._log.error(
    190                          u'CSSNamespaceRule: Unexpected char.', token)
    191                      return expected
    192
    193              # "NAMESPACE_SYM S* [namespace_prefix S*]? [STRING|URI] S* ';' S*"
    194              newseq = self._tempSeq()
    195              wellformed, expected = self._parse(expected='prefix or uri',
    196                  seq=newseq, tokenizer=tokenizer,
    197                  productions={'IDENT': _ident,
    198                               'STRING': _string,
    199                               'URI': _uri,
    200                               'CHAR': _char},
    201                  new=new)
    202
    203              # wellformed set by parse
    204              wellformed = wellformed and new['wellformed']
    205
    206              # post conditions
    207              if new['uri'] is None:
    208                  wellformed = False
    209                  self._log.error(u'CSSNamespaceRule: No namespace URI found: %s' %
    210                      self._valuestr(cssText))
    211
    212              if expected != 'EOF':
    213                  wellformed = False
    214                  self._log.error(u'CSSNamespaceRule: No ";" found: %s' %
    215                      self._valuestr(cssText))
    216
    217              # set all
    218              if wellformed:
    219                  self.atkeyword = new['keyword']
    220                  self._prefix = new['prefix']
    221                  self.namespaceURI = new['uri']
    222                  self._setSeq(newseq)
    223
    224      cssText = property(fget=_getCssText, fset=_setCssText,
    225          doc="(DOM attribute) The parsable textual representation.")
    226
    227 -    def _setNamespaceURI(self, namespaceURI):
    228          """
    229          DOMException on setting
    230
    231          :param namespaceURI: the initial value for this rules namespaceURI
    232          :Exceptions:
    233              - `NO_MODIFICATION_ALLOWED_ERR`:
    234                (CSSRule) Raised if this rule is readonly or a namespaceURI is
    235                already set in this rule.
    236          """
    237          self._checkReadonly()
    238          if not self._namespaceURI:
    239              # initial setting
    240              self._namespaceURI = namespaceURI
    241              tempseq = self._tempSeq()
    242              tempseq.append(namespaceURI, 'namespaceURI')
    243              self._setSeq(tempseq) # makes seq readonly!
    244          elif self._namespaceURI != namespaceURI:
    245              self._log.error(u'CSSNamespaceRule: namespaceURI is readonly.',
    246                              error=xml.dom.NoModificationAllowedErr)
    247
    248      namespaceURI = property(lambda self: self._namespaceURI, _setNamespaceURI,
    249          doc="URI (string!) of the defined namespace.")
    250
    251 -    def _setPrefix(self, prefix=None):
    252          """
    253          DOMException on setting
    254
    255          :param prefix: the new prefix
    256          :Exceptions:
    257              - `SYNTAX_ERR`: (TODO)
    258                Raised if the specified CSS string value has a syntax error and
    259                is unparsable.
    260              - `NO_MODIFICATION_ALLOWED_ERR`: CSSRule)
    261                Raised if this rule is readonly.
    262          """
    263          self._checkReadonly()
    264          if not prefix:
    265              prefix = u''
    266          else:
    267              tokenizer = self._tokenize2(prefix)
    268              prefixtoken = self._nexttoken(tokenizer, None)
    269              if not prefixtoken or self._type(prefixtoken) != self._prods.IDENT:
    270                  self._log.error(u'CSSNamespaceRule: No valid prefix "%s".' %
    271                      self._valuestr(prefix),
    272                      error=xml.dom.SyntaxErr)
    273                  return
    274              else:
    275                  prefix = self._tokenvalue(prefixtoken)
    276          # update seg
    277          for i, x in enumerate(self._seq):
    278              if x == self._prefix:
    279                  self._seq[i] = (prefix, 'prefix', None, None)
    280                  break
    281          else:
    282              # put prefix at the beginning!
    283              self._seq[0] = (prefix, 'prefix', None, None)
    284
    285          # set new prefix
    286          self._prefix = prefix
    287
    288      prefix = property(lambda self: self._prefix, _setPrefix,
    289          doc="Prefix used for the defined namespace.")
    290
    291 -    def _setParentStyleSheet(self, parentStyleSheet):
    292          self._parentStyleSheet = parentStyleSheet
    293
    294      parentStyleSheet = property(lambda self: self._parentStyleSheet,
    295                                  _setParentStyleSheet,
    296                                  doc=u"Containing CSSStyleSheet.")
    297
    298      wellformed = property(lambda self: self.namespaceURI is not None)
    299
    300 -    def __repr__(self):
    301          return "cssutils.css.%s(namespaceURI=%r, prefix=%r)" % (
    302                  self.__class__.__name__, self.namespaceURI, self.prefix)
    303
    304 -    def __str__(self):
    305          return "<cssutils.css.%s object namespaceURI=%r prefix=%r at 0x%x>" % (
    306                  self.__class__.__name__, self.namespaceURI, self.prefix, id(self))
    307