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 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   
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 self._media = cssutils.stylesheets.MediaList( 81 mediaText, readonly=readonly) 82 self._name = name 83 if not self.media.wellformed: 84 self._media = cssutils.stylesheets.MediaList() 85 86 seq = self._tempSeq() 87 seq.append(self.href, 'href') 88 seq.append(self.media, 'media') 89 seq.append(self.name, 'name') 90 self._setSeq(seq) 91 92 self._readonly = readonly
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 # for closures: must be a mutable 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 # called by _string or _ident 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 # href 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 # name 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 # href 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 # medialist ending with ; which is checked upon too 171 if expected.startswith('media'): 172 mediatokens = self._tokensupto2( 173 tokenizer, importmediaqueryendonly=True) 174 mediatokens.insert(0, token) # push found token 175 176 last = mediatokens.pop() # retrieve ; 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 # name 195 return __doname(seq, last) 196 else: 197 return 'EOF' # ';' is token "last" 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 # final ; 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 # import : IMPORT_SYM S* [STRING|URI] 216 # S* [ medium [ ',' S* medium]* ]? ';' S* 217 # STRING? # see http://www.w3.org/TR/css3-cascade/#cascading 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 # wellformed set by parse 229 wellformed = wellformed and new['wellformed'] 230 231 # post conditions 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 # set all 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 # title is set by href 253 #self.styleSheet._href = self.href 254 self.styleSheet._parentStyleSheet = self.parentStyleSheet 255 256 cssText = property(fget=_getCssText, fset=_setCssText, 257 doc="(DOM attribute) The parsable textual representation.") 258
259 - def _setHref(self, href):
260 # update seq 261 for i, item in enumerate(self.seq): 262 val, typ = item.value, item.type 263 if 'href' == typ: 264 self._seq[i] = (href, typ, item.line, item.col) 265 break 266 else: 267 seq = self._tempSeq() 268 seq.append(self.href, 'href') 269 self._setSeq(seq) 270 # set new href 271 self._href = href 272 if not self.styleSheet: 273 # set only if not set before 274 self.__setStyleSheet()
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
283 - def _setName(self, name):
284 """raises xml.dom.SyntaxErr if name is not a string""" 285 if isinstance(name, basestring) or name is None: 286 # "" or '' 287 if not name: 288 name = None 289 # update seq 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 # append 297 seq = self._tempSeq() 298 for item in self.seq: 299 # copy current seq 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 # set title of referred sheet 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
313 - def __setStyleSheet(self):
314 """Read new CSSStyleSheet cssText from href using parentStyleSheet.href 315 316 indirectly called if setting ``href`` 317 """ 318 # should simply fail so all errors are catched! 319 if self.parentStyleSheet and self.href: 320 # relative href 321 parentHref = self.parentStyleSheet.href 322 if parentHref is None: 323 # use cwd instead 324 parentHref = u'file:' + urllib.pathname2url(os.getcwd()) + '/' 325 href = urlparse.urljoin(parentHref, self.href) 326 327 # all possible exceptions are ignored and styleSheet is None 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 # inherit fetcher for @imports in refsheet 338 refsheet._setFetcher(self.parentStyleSheet._fetcher) 339 # overrideEncoding with parentStyleSheet.overrideEncoding, 340 # HTTP or parent 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
355 - def __repr__(self):
356 if self.media: 357 mediaText = self.media.mediaText 358 else: 359 mediaText = None 360 return "cssutils.css.%s(href=%r, mediaText=%r, name=%r)" % ( 361 self.__class__.__name__, 362 self.href, self.media.mediaText, self.name)
363
364 - def __str__(self):
365 if self.media: 366 mediaText = self.media.mediaText 367 else: 368 mediaText = None 369 return "<cssutils.css.%s object href=%r mediaText=%r name=%r at 0x%x>" % ( 370 self.__class__.__name__, self.href, mediaText, self.name, id(self))
371