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