Package cssutils :: Package css :: Module cssimportrule
[hide private]
[frames] | no frames]

Source Code for Module cssutils.css.cssimportrule

  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   
20 -class CSSImportRule(cssrule.CSSRule):
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):
60 """ 61 if readonly allows setting of properties in constructor only 62 63 Do not use as positional but as keyword attributes only! 64 65 href 66 location of the style sheet to be imported. 67 mediaText 68 A list of media types for which this style sheet may be used 69 as a string 70 """ 71 super(CSSImportRule, self).__init__(parentRule=parentRule, 72 parentStyleSheet=parentStyleSheet) 73 self._atkeyword = u'@import' 74 self.hreftype = None 75 self._styleSheet = None 76 77 self._href = None 78 self.href = href 79 80 # if self._media is used (simply empty) 81 self._usemedia = False 82 self._media = cssutils.stylesheets.MediaList() 83 if mediaText: 84 self._usemedia = True 85 self._media.mediaText = mediaText 86 87 self._name = name 88 89 seq = self._tempSeq() 90 seq.append(self.href, 'href') 91 seq.append(self.media, 'media') 92 seq.append(self.name, 'name') 93 self._setSeq(seq) 94 95 self._readonly = readonly
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 # for closures: must be a mutable 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 # called by _string or _ident 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 # href 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 # name 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 # href 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 # medialist ending with ; which is checked upon too 174 if expected.startswith('media'): 175 mediatokens = self._tokensupto2( 176 tokenizer, importmediaqueryendonly=True) 177 mediatokens.insert(0, token) # push found token 178 179 last = mediatokens.pop() # retrieve ; 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 # name 198 return __doname(seq, last) 199 else: 200 return 'EOF' # ';' is token "last" 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 # final ; 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 # import : IMPORT_SYM S* [STRING|URI] 219 # S* [ medium [ ',' S* medium]* ]? ';' S* 220 # STRING? # see http://www.w3.org/TR/css3-cascade/#cascading 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 # wellformed set by parse 232 wellformed = wellformed and new['wellformed'] 233 234 # post conditions 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 # set all 246 if wellformed: 247 self.atkeyword = new['keyword'] 248 self.hreftype = new['hreftype'] 249 if new['media']: 250 # use same object 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 # title is set by href 261 #self.styleSheet._href = self.href 262 self.styleSheet._parentStyleSheet = self.parentStyleSheet 263 264 cssText = property(fget=_getCssText, fset=_setCssText, 265 doc="(DOM attribute) The parsable textual representation.") 266
267 - def _setHref(self, href):
268 # update seq 269 for i, item in enumerate(self.seq): 270 val, typ = item.value, item.type 271 if 'href' == typ: 272 self._seq[i] = (href, typ, item.line, item.col) 273 break 274 else: 275 seq = self._tempSeq() 276 seq.append(self.href, 'href') 277 self._setSeq(seq) 278 # set new href 279 self._href = href 280 if not self.styleSheet: 281 # set only if not set before 282 self.__setStyleSheet()
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
291 - def _setName(self, name):
292 """raises xml.dom.SyntaxErr if name is not a string""" 293 if isinstance(name, basestring) or name is None: 294 # "" or '' 295 if not name: 296 name = None 297 # update seq 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 # append 305 seq = self._tempSeq() 306 for item in self.seq: 307 # copy current seq 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 # set title of referred sheet 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
321 - def __setStyleSheet(self):
322 """Read new CSSStyleSheet cssText from href using parentStyleSheet.href 323 324 indirectly called if setting ``href`` 325 """ 326 # should simply fail so all errors are catched! 327 if self.parentStyleSheet and self.href: 328 # relative href 329 parentHref = self.parentStyleSheet.href 330 if parentHref is None: 331 # use cwd instead 332 parentHref = u'file:' + urllib.pathname2url(os.getcwd()) + '/' 333 href = urlparse.urljoin(parentHref, self.href) 334 335 # all possible exceptions are ignored and styleSheet is None 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 # inherit fetcher for @imports in refsheet 346 refsheet._setFetcher(self.parentStyleSheet._fetcher) 347 # overrideEncoding with parentStyleSheet.overrideEncoding, 348 # HTTP or parent 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
361 - def _getWellformed(self):
362 "depending if media is used at all" 363 if self._usemedia: 364 return bool(self.href and self.media.wellformed) 365 else: 366 return bool(self.href)
367 368 wellformed = property(_getWellformed) 369
370 - def __repr__(self):
371 if self._usemedia: 372 mediaText = self.media.mediaText 373 else: 374 mediaText = None 375 return "cssutils.css.%s(href=%r, mediaText=%r, name=%r)" % ( 376 self.__class__.__name__, 377 self.href, self.media.mediaText, self.name)
378
379 - def __str__(self):
380 if self._usemedia: 381 mediaText = self.media.mediaText 382 else: 383 mediaText = None 384 return "<cssutils.css.%s object href=%r mediaText=%r name=%r at 0x%x>" % ( 385 self.__class__.__name__, self.href, mediaText, self.name, id(self))
386