Statistics
| Revision:

gvsig-scripting / org.gvsig.scripting / trunk / org.gvsig.scripting / org.gvsig.scripting.app / org.gvsig.scripting.app.mainplugin / src / main / resources-plugin / scripting / lib / cssutils / css / cssnamespacerule.py @ 475

History | View | Annotate | Download (11.1 KB)

1
"""CSSNamespaceRule currently implements http://dev.w3.org/csswg/css3-namespace/
2
"""
3
__all__ = ['CSSNamespaceRule']
4
__docformat__ = 'restructuredtext'
5
__version__ = '$Id$'
6

    
7
import cssrule
8
import cssutils
9
import xml.dom
10

    
11
class CSSNamespaceRule(cssrule.CSSRule):
12
    """
13
    Represents an @namespace rule within a CSS style sheet.
14

15
    The @namespace at-rule declares a namespace prefix and associates
16
    it with a given namespace (a string). This namespace prefix can then be
17
    used in namespace-qualified names such as those described in the
18
    Selectors Module [SELECT] or the Values and Units module [CSS3VAL].
19
    
20
    Dealing with these rules directly is not needed anymore, easier is 
21
    the use of :attr:`cssutils.css.CSSStyleSheet.namespaces`.
22

23
    Format::
24

25
        namespace
26
          : NAMESPACE_SYM S* [namespace_prefix S*]? [STRING|URI] S* ';' S*
27
          ;
28
        namespace_prefix
29
          : IDENT
30
          ;
31
    """
32
    def __init__(self, namespaceURI=None, prefix=None, cssText=None, 
33
                 parentRule=None, parentStyleSheet=None, readonly=False):
34
        """
35
        :Parameters:
36
            namespaceURI
37
                The namespace URI (a simple string!) which is bound to the
38
                given prefix. If no prefix is set
39
                (``CSSNamespaceRule.prefix==''``) the namespace defined by
40
                namespaceURI is set as the default namespace
41
            prefix
42
                The prefix used in the stylesheet for the given
43
                ``CSSNamespaceRule.uri``.
44
            cssText
45
                if no namespaceURI is given cssText must be given to set
46
                a namespaceURI as this is readonly later on
47
            parentStyleSheet
48
                sheet where this rule belongs to
49

50
        Do not use as positional but as keyword parameters only!
51

52
        If readonly allows setting of properties in constructor only
53

54
        format namespace::
55

56
            namespace
57
              : NAMESPACE_SYM S* [namespace_prefix S*]? [STRING|URI] S* ';' S*
58
              ;
59
            namespace_prefix
60
              : IDENT
61
              ;
62
        """
63
        super(CSSNamespaceRule, self).__init__(parentRule=parentRule, 
64
                                               parentStyleSheet=parentStyleSheet)
65
        self._atkeyword = u'@namespace'
66
        self._prefix = u''
67
        self._namespaceURI = None
68
        
69
        if namespaceURI:
70
            self.namespaceURI = namespaceURI
71
            self.prefix = prefix
72
            tempseq = self._tempSeq()
73
            tempseq.append(self.prefix, 'prefix')
74
            tempseq.append(self.namespaceURI, 'namespaceURI')
75
            self._setSeq(tempseq)
76
            
77
        elif cssText is not None:
78
            self.cssText = cssText
79

    
80
        if parentStyleSheet:
81
            self._parentStyleSheet = parentStyleSheet
82

    
83
        self._readonly = readonly
84

    
85
    def __repr__(self):
86
        return u"cssutils.css.%s(namespaceURI=%r, prefix=%r)" % (
87
                self.__class__.__name__,
88
                self.namespaceURI,
89
                self.prefix)
90

    
91
    def __str__(self):
92
        return u"<cssutils.css.%s object namespaceURI=%r prefix=%r at 0x%x>" % (
93
                self.__class__.__name__,
94
                self.namespaceURI,
95
                self.prefix,
96
                id(self))
97

    
98
    def _getCssText(self):
99
        """Return serialized property cssText"""
100
        return cssutils.ser.do_CSSNamespaceRule(self)
101

    
102
    def _setCssText(self, cssText):
103
        """
104
        :param cssText: initial value for this rules cssText which is parsed
105
        :exceptions:
106
            - :exc:`~xml.dom.HierarchyRequestErr`:
107
              Raised if the rule cannot be inserted at this point in the
108
              style sheet.
109
            - :exc:`~xml.dom.InvalidModificationErr`:
110
              Raised if the specified CSS string value represents a different
111
              type of rule than the current one.
112
            - :exc:`~xml.dom.NoModificationAllowedErr`:
113
              Raised if the rule is readonly.
114
            - :exc:`~xml.dom.SyntaxErr`:
115
              Raised if the specified CSS string value has a syntax error and
116
              is unparsable.
117
        """
118
        super(CSSNamespaceRule, self)._setCssText(cssText)
119
        tokenizer = self._tokenize2(cssText)
120
        attoken = self._nexttoken(tokenizer, None)
121
        if self._type(attoken) != self._prods.NAMESPACE_SYM:
122
            self._log.error(u'CSSNamespaceRule: No CSSNamespaceRule found: %s' %
123
                            self._valuestr(cssText),
124
                            error=xml.dom.InvalidModificationErr)
125
        else:
126
            # for closures: must be a mutable
127
            new = {'keyword': self._tokenvalue(attoken),
128
                   'prefix': u'',
129
                   'uri': None,
130
                   'wellformed': True
131
                   }
132

    
133
            def _ident(expected, seq, token, tokenizer=None):
134
                # the namespace prefix, optional
135
                if 'prefix or uri' == expected:
136
                    new['prefix'] = self._tokenvalue(token)
137
                    seq.append(new['prefix'], 'prefix')
138
                    return 'uri'
139
                else:
140
                    new['wellformed'] = False
141
                    self._log.error(
142
                        u'CSSNamespaceRule: Unexpected ident.', token)
143
                    return expected
144

    
145
            def _string(expected, seq, token, tokenizer=None):
146
                # the namespace URI as a STRING
147
                if expected.endswith('uri'):
148
                    new['uri'] = self._stringtokenvalue(token)
149
                    seq.append(new['uri'], 'namespaceURI')
150
                    return ';'
151

    
152
                else:
153
                    new['wellformed'] = False
154
                    self._log.error(
155
                        u'CSSNamespaceRule: Unexpected string.', token)
156
                    return expected
157

    
158
            def _uri(expected, seq, token, tokenizer=None):
159
                # the namespace URI as URI which is DEPRECATED
160
                if expected.endswith('uri'):
161
                    uri = self._uritokenvalue(token)
162
                    new['uri'] = uri
163
                    seq.append(new['uri'], 'namespaceURI')
164
                    return ';'
165
                else:
166
                    new['wellformed'] = False
167
                    self._log.error(
168
                        u'CSSNamespaceRule: Unexpected URI.', token)
169
                    return expected
170

    
171
            def _char(expected, seq, token, tokenizer=None):
172
                # final ;
173
                val = self._tokenvalue(token)
174
                if ';' == expected and u';' == val:
175
                    return 'EOF'
176
                else:
177
                    new['wellformed'] = False
178
                    self._log.error(
179
                        u'CSSNamespaceRule: Unexpected char.', token)
180
                    return expected
181

    
182
            # "NAMESPACE_SYM S* [namespace_prefix S*]? [STRING|URI] S* ';' S*"
183
            newseq = self._tempSeq()
184
            wellformed, expected = self._parse(expected='prefix or uri',
185
                seq=newseq, tokenizer=tokenizer,
186
                productions={'IDENT': _ident,
187
                             'STRING': _string,
188
                             'URI': _uri,
189
                             'CHAR': _char},
190
                new=new)
191

    
192
            # wellformed set by parse
193
            wellformed = wellformed and new['wellformed']
194

    
195
            # post conditions
196
            if new['uri'] is None:
197
                wellformed = False
198
                self._log.error(u'CSSNamespaceRule: No namespace URI found: %s'
199
                                % self._valuestr(cssText))
200

    
201
            if expected != 'EOF':
202
                wellformed = False
203
                self._log.error(u'CSSNamespaceRule: No ";" found: %s' %
204
                                self._valuestr(cssText))
205

    
206
            # set all
207
            if wellformed:
208
                self.atkeyword = new['keyword']
209
                self._prefix = new['prefix']
210
                self.namespaceURI = new['uri']
211
                self._setSeq(newseq)
212

    
213
    cssText = property(fget=_getCssText, fset=_setCssText,
214
                       doc=u"(DOM) The parsable textual representation of this "
215
                           u"rule.")
216

    
217
    def _setNamespaceURI(self, namespaceURI):
218
        """
219
        :param namespaceURI: the initial value for this rules namespaceURI
220
        :exceptions:
221
            - :exc:`~xml.dom.NoModificationAllowedErr`:
222
              (CSSRule) Raised if this rule is readonly or a namespaceURI is 
223
              already set in this rule.
224
        """
225
        self._checkReadonly()
226
        if not self._namespaceURI:
227
            # initial setting
228
            self._namespaceURI = namespaceURI
229
            tempseq = self._tempSeq()
230
            tempseq.append(namespaceURI, 'namespaceURI')
231
            self._setSeq(tempseq) # makes seq readonly!
232
        elif self._namespaceURI != namespaceURI:
233
            self._log.error(u'CSSNamespaceRule: namespaceURI is readonly.',
234
                            error=xml.dom.NoModificationAllowedErr)
235

    
236
    namespaceURI = property(lambda self: self._namespaceURI, _setNamespaceURI,
237
        doc="URI (handled as simple string) of the defined namespace.")
238

    
239
    def _replaceNamespaceURI(self, namespaceURI):
240
        """Used during parse of new sheet only!
241
        
242
        :param namespaceURI: the new value for this rules namespaceURI
243
        """
244
        self._namespaceURI = namespaceURI
245
        for i, x in enumerate(self._seq):
246
            if 'namespaceURI' == x.type:
247
                self._seq._readonly = False 
248
                self._seq.replace(i, namespaceURI, 'namespaceURI')
249
                self._seq._readonly = True
250
                break
251

    
252
    def _setPrefix(self, prefix=None):
253
        """
254
        :param prefix: the new prefix 
255
        :exceptions:
256
            - :exc:`~xml.dom.SyntaxErr`:
257
              Raised if the specified CSS string value has a syntax error and
258
              is unparsable.
259
            - :exc:`~xml.dom.NoModificationAllowedErr`:
260
              Raised if this rule is readonly.
261
        """
262
        self._checkReadonly()
263
        if not prefix:
264
            prefix = u''
265
        else:        
266
            tokenizer = self._tokenize2(prefix)
267
            prefixtoken = self._nexttoken(tokenizer, None)
268
            if not prefixtoken or self._type(prefixtoken) != self._prods.IDENT:
269
                self._log.error(u'CSSNamespaceRule: No valid prefix "%s".' %
270
                                self._valuestr(prefix),
271
                                error=xml.dom.SyntaxErr)
272
                return
273
            else:
274
                prefix = self._tokenvalue(prefixtoken)
275
        # update seq
276
        for i, x in enumerate(self._seq):
277
            if x == self._prefix:
278
                self._seq[i] = (prefix, 'prefix', None, None)
279
                break
280
        else:
281
            # put prefix at the beginning!
282
            self._seq[0] = (prefix, 'prefix', None, None) 
283

    
284
        # set new prefix
285
        self._prefix = prefix
286

    
287
    prefix = property(lambda self: self._prefix, _setPrefix,
288
                      doc=u"Prefix used for the defined namespace.")
289

    
290
    type = property(lambda self: self.NAMESPACE_RULE, 
291
                    doc=u"The type of this rule, as defined by a CSSRule "
292
                        u"type constant.")
293
    
294
    wellformed = property(lambda self: self.namespaceURI is not None)
295