1 """CSSImportRule implements DOM Level 2 CSS CSSImportRule.
2
3 plus:
4
5 ``name`` property
6 http://www.w3.org/TR/css3-cascade/#cascading
7
8 """
9 __all__ = ['CSSImportRule']
10 __docformat__ = 'restructuredtext'
11 __version__ = '$Id: cssimportrule.py 1298 2008-06-22 15:47:08Z cthedot $'
12
13 import os
14 import urllib
15 import urlparse
16 import xml.dom
17 import cssrule
18 import cssutils
19
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 Inherits properties from CSSRule
48
49 Format
50 ======
51 import
52 : IMPORT_SYM S*
53 [STRING|URI] S* [ medium [ COMMA S* medium]* ]? S* STRING? S* ';' S*
54 ;
55 """
56 type = property(lambda self: cssrule.CSSRule.IMPORT_RULE)
57
58 - def __init__(self, href=None, mediaText=u'all', name=None,
59 parentRule=None, parentStyleSheet=None, readonly=False):
93
94 - def _getCssText(self):
95 """
96 returns serialized property cssText
97 """
98 return cssutils.ser.do_CSSImportRule(self)
99
100 - def _setCssText(self, cssText):
101 """
102 DOMException on setting
103
104 - HIERARCHY_REQUEST_ERR: (CSSStylesheet)
105 Raised if the rule cannot be inserted at this point in the
106 style sheet.
107 - INVALID_MODIFICATION_ERR: (self)
108 Raised if the specified CSS string value represents a different
109 type of rule than the current one.
110 - NO_MODIFICATION_ALLOWED_ERR: (CSSRule)
111 Raised if the rule is readonly.
112 - SYNTAX_ERR: (self)
113 Raised if the specified CSS string value has a syntax error and
114 is unparsable.
115 """
116 super(CSSImportRule, self)._setCssText(cssText)
117 tokenizer = self._tokenize2(cssText)
118 attoken = self._nexttoken(tokenizer, None)
119 if self._type(attoken) != self._prods.IMPORT_SYM:
120 self._log.error(u'CSSImportRule: No CSSImportRule found: %s' %
121 self._valuestr(cssText),
122 error=xml.dom.InvalidModificationErr)
123 else:
124
125 new = {'keyword': self._tokenvalue(attoken),
126 'href': None,
127 'hreftype': None,
128 'media': cssutils.stylesheets.MediaList(),
129 'name': None,
130 'wellformed': True
131 }
132
133 def __doname(seq, token):
134
135 new['name'] = self._stringtokenvalue(token)
136 seq.append(new['name'], 'name')
137 return ';'
138
139 def _string(expected, seq, token, tokenizer=None):
140 if 'href' == expected:
141
142 new['href'] = self._stringtokenvalue(token)
143 new['hreftype'] = 'string'
144 seq.append(new['href'], 'href')
145 return 'media name ;'
146 elif 'name' in expected:
147
148 return __doname(seq, token)
149 else:
150 new['wellformed'] = False
151 self._log.error(
152 u'CSSImportRule: Unexpected string.', token)
153 return expected
154
155 def _uri(expected, seq, token, tokenizer=None):
156
157 if 'href' == expected:
158 uri = self._uritokenvalue(token)
159 new['hreftype'] = 'uri'
160 new['href'] = uri
161 seq.append(new['href'], 'href')
162 return 'media name ;'
163 else:
164 new['wellformed'] = False
165 self._log.error(
166 u'CSSImportRule: Unexpected URI.', token)
167 return expected
168
169 def _ident(expected, seq, token, tokenizer=None):
170
171 if expected.startswith('media'):
172 mediatokens = self._tokensupto2(
173 tokenizer, importmediaqueryendonly=True)
174 mediatokens.insert(0, token)
175
176 last = mediatokens.pop()
177 lastval, lasttyp = self._tokenvalue(last), self._type(last)
178 if lastval != u';' and lasttyp not in ('EOF', self._prods.STRING):
179 new['wellformed'] = False
180 self._log.error(u'CSSImportRule: No ";" found: %s' %
181 self._valuestr(cssText), token=token)
182
183 media = cssutils.stylesheets.MediaList()
184 media.mediaText = mediatokens
185 if media.wellformed:
186 new['media'] = media
187 seq.append(media, 'media')
188 else:
189 new['wellformed'] = False
190 self._log.error(u'CSSImportRule: Invalid MediaList: %s' %
191 self._valuestr(cssText), token=token)
192
193 if lasttyp == self._prods.STRING:
194
195 return __doname(seq, last)
196 else:
197 return 'EOF'
198 else:
199 new['wellformed'] = False
200 self._log.error(
201 u'CSSImportRule: Unexpected ident.', token)
202 return expected
203
204 def _char(expected, seq, token, tokenizer=None):
205
206 val = self._tokenvalue(token)
207 if expected.endswith(';') and u';' == val:
208 return 'EOF'
209 else:
210 new['wellformed'] = False
211 self._log.error(
212 u'CSSImportRule: Unexpected char.', token)
213 return expected
214
215
216
217
218
219 newseq = self._tempSeq()
220 wellformed, expected = self._parse(expected='href',
221 seq=newseq, tokenizer=tokenizer,
222 productions={'STRING': _string,
223 'URI': _uri,
224 'IDENT': _ident,
225 'CHAR': _char},
226 new=new)
227
228
229 wellformed = wellformed and new['wellformed']
230
231
232 if not new['href']:
233 wellformed = False
234 self._log.error(u'CSSImportRule: No href found: %s' %
235 self._valuestr(cssText))
236
237 if expected != 'EOF':
238 wellformed = False
239 self._log.error(u'CSSImportRule: No ";" found: %s' %
240 self._valuestr(cssText))
241
242
243 if wellformed:
244 self.atkeyword = new['keyword']
245 self.hreftype = new['hreftype']
246 self._media = new['media']
247 self.name = new['name']
248 self._setSeq(newseq)
249 self.href = new['href']
250
251 if self.styleSheet:
252
253
254 self.styleSheet._parentStyleSheet = self.parentStyleSheet
255
256 cssText = property(fget=_getCssText, fset=_setCssText,
257 doc="(DOM attribute) The parsable textual representation.")
258
275
276 href = property(lambda self: self._href, _setHref,
277 doc="Location of the style sheet to be imported.")
278
279 media = property(lambda self: self._media,
280 doc=u"(DOM readonly) A list of media types for this rule"
281 " of type MediaList")
282
284 """raises xml.dom.SyntaxErr if name is not a string"""
285 if isinstance(name, basestring) or name is None:
286
287 if not name:
288 name = None
289
290 for i, item in enumerate(self.seq):
291 val, typ = item.value, item.type
292 if 'name' == typ:
293 self._seq[i] = (name, typ, item.line, item.col)
294 break
295 else:
296
297 seq = self._tempSeq()
298 for item in self.seq:
299
300 seq.append(item.value, item.type, item.line, item.col)
301 seq.append(name, 'name')
302 self._setSeq(seq)
303 self._name = name
304
305 if self.styleSheet:
306 self.styleSheet.title = name
307 else:
308 self._log.error(u'CSSImportRule: Not a valid name: %s' % name)
309
310 name = property(lambda self: self._name, _setName,
311 doc=u"An optional name for the imported sheet")
312
314 """Read new CSSStyleSheet cssText from href using parentStyleSheet.href
315
316 indirectly called if setting ``href``
317 """
318
319 if self.parentStyleSheet and self.href:
320
321 parentHref = self.parentStyleSheet.href
322 if parentHref is None:
323
324 parentHref = u'file:' + urllib.pathname2url(os.getcwd()) + '/'
325 href = urlparse.urljoin(parentHref, self.href)
326
327
328 try:
329 overrideEncoding, cssText = self.parentStyleSheet._resolveImport(href)
330 if cssText is None:
331 raise IOError('Cannot read Stylesheet or it is empty.')
332
333 refsheet = cssutils.css.CSSStyleSheet(href=href,
334 media=self.media,
335 ownerRule=self,
336 title=self.name)
337
338 refsheet._setFetcher(self.parentStyleSheet._fetcher)
339
340
341 refsheet._setCssTextWithEncodingOverride(cssText,
342 overrideEncoding)
343
344 except (OSError, IOError, ValueError), e:
345 self._log.warn(u'CSSImportRule: While processing imported style sheet href=%r: %r'
346 % (self.href, e), neverraise=True)
347 else:
348 self._styleSheet = refsheet
349
350 styleSheet = property(lambda self: self._styleSheet,
351 doc="(readonly) The style sheet referred to by this rule.")
352
353 wellformed = property(lambda self: bool(self.href and self.media.wellformed))
354
363
371