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 1305 2008-06-22 18:42:51Z cthedot $'
9
10 import xml.dom
11 import cssrule
12 import cssutils
13 from cssutils.helper import Deprecated
14
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 = property(lambda self: 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
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
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
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
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
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
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
204 wellformed = wellformed and new['wellformed']
205
206
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
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
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
240 self._namespaceURI = namespaceURI
241 tempseq = self._tempSeq()
242 tempseq.append(namespaceURI, 'namespaceURI')
243 self._setSeq(tempseq)
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
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
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
283 self._seq[0] = (prefix, 'prefix', None, None)
284
285
286 self._prefix = prefix
287
288 prefix = property(lambda self: self._prefix, _setPrefix,
289 doc="Prefix used for the defined namespace.")
290
291
292
293
294
295
296
297
298 wellformed = property(lambda self: self.namespaceURI is not None)
299
301 return "cssutils.css.%s(namespaceURI=%r, prefix=%r)" % (
302 self.__class__.__name__, self.namespaceURI, self.prefix)
303
305 return "<cssutils.css.%s object namespaceURI=%r prefix=%r at 0x%x>" % (
306 self.__class__.__name__, self.namespaceURI, self.prefix, id(self))
307