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 |
|