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

Source Code for Module cssutils.css.cssmediarule

  1  """CSSMediaRule implements DOM Level 2 CSS CSSMediaRule. 
  2  """ 
  3  __all__ = ['CSSMediaRule'] 
  4  __docformat__ = 'restructuredtext' 
  5  __author__ = '$LastChangedBy: cthedot $' 
  6  __date__ = '$LastChangedDate: 2008-02-03 15:08:53 +0100 (So, 03 Feb 2008) $' 
  7  __version__ = '$LastChangedRevision: 978 $' 
  8   
  9  import xml.dom 
 10  import cssrule 
 11  import cssutils 
 12   
13 -class CSSMediaRule(cssrule.CSSRule):
14 """ 15 Objects implementing the CSSMediaRule interface can be identified by the 16 MEDIA_RULE constant. On these objects the type attribute must return the 17 value of that constant. 18 19 Properties 20 ========== 21 cssRules: A css::CSSRuleList of all CSS rules contained within the 22 media block. 23 media: of type stylesheets::MediaList, (DOM readonly) 24 A list of media types for this rule of type MediaList. 25 inherited from CSSRule 26 cssText 27 28 cssutils only 29 ------------- 30 atkeyword: 31 the literal keyword used 32 33 Format 34 ====== 35 media 36 : MEDIA_SYM S* medium [ COMMA S* medium ]* LBRACE S* ruleset* '}' S*; 37 """ 38 # CONSTANT 39 type = cssrule.CSSRule.MEDIA_RULE 40
41 - def __init__(self, mediaText='all', parentRule=None, 42 parentStyleSheet=None, readonly=False):
43 """ 44 constructor 45 """ 46 super(CSSMediaRule, self).__init__(parentRule=parentRule, 47 parentStyleSheet=parentStyleSheet) 48 self.atkeyword = u'@media' 49 self._media = cssutils.stylesheets.MediaList( 50 mediaText, readonly=readonly) 51 if not self.media.valid: 52 self._media = cssutils.stylesheets.MediaList() 53 54 self.cssRules = cssutils.css.cssrulelist.CSSRuleList() 55 self.cssRules.append = self.insertRule 56 self.cssRules.extend = self.insertRule 57 self.cssRules.__delitem__ == self.deleteRule 58 59 self._readonly = readonly
60
61 - def __iter__(self):
62 """ 63 generator which iterates over cssRules. 64 """ 65 for rule in self.cssRules: 66 yield rule
67
68 - def _getCssText(self):
69 """ 70 returns serialized property cssText 71 """ 72 return cssutils.ser.do_CSSMediaRule(self)
73
74 - def _setCssText(self, cssText):
75 """ 76 :param cssText: 77 a parseable string or a tuple of (cssText, dict-of-namespaces) 78 :Exceptions: 79 - `NAMESPACE_ERR`: (Selector) 80 Raised if a specified selector uses an unknown namespace 81 prefix. 82 - `SYNTAX_ERR`: (self, StyleDeclaration, etc) 83 Raised if the specified CSS string value has a syntax error and 84 is unparsable. 85 - `INVALID_MODIFICATION_ERR`: (self) 86 Raised if the specified CSS string value represents a different 87 type of rule than the current one. 88 - `HIERARCHY_REQUEST_ERR`: (CSSStylesheet) 89 Raised if the rule cannot be inserted at this point in the 90 style sheet. 91 - `NO_MODIFICATION_ALLOWED_ERR`: (CSSRule) 92 Raised if the rule is readonly. 93 """ 94 super(CSSMediaRule, self)._setCssText(cssText) 95 96 # might be (cssText, namespaces) 97 cssText, namespaces = self._splitNamespacesOff(cssText) 98 try: 99 # use parent style sheet ones if available 100 namespaces = self.parentStyleSheet.namespaces 101 except AttributeError: 102 pass 103 104 tokenizer = self._tokenize2(cssText) 105 attoken = self._nexttoken(tokenizer, None) 106 if not attoken or u'@media' != self._tokenvalue( 107 attoken, normalize=True): 108 self._log.error(u'CSSMediaRule: No CSSMediaRule found: %s' % 109 self._valuestr(cssText), 110 error=xml.dom.InvalidModificationErr) 111 else: 112 # media 113 valid = True 114 mediatokens = self._tokensupto2(tokenizer, blockstartonly=True) 115 if len(mediatokens) < 1 or\ 116 u'{' != self._tokenvalue(mediatokens[-1]): 117 self._log.error(u'CSSMediaRule: No "{" found.') 118 else: 119 newmedia = cssutils.stylesheets.MediaList() 120 newmedia.mediaText = mediatokens[:-1] # omit { 121 122 # cssRules 123 cssrulestokens = self._tokensupto2(tokenizer, mediaendonly=True) 124 newcssrules = [] #cssutils.css.CSSRuleList() 125 if len(cssrulestokens) < 1 or ( 126 u'}' != self._tokenvalue(cssrulestokens[-1]) and 127 'EOF' != self._type(cssrulestokens[-1])): 128 self._log.error(u'CSSMediaRule: No "}" found.') 129 elif self._nexttoken(tokenizer, None): 130 self._log.error(u'CSSMediaRule: Content after "}" found.') 131 else: 132 brace = cssrulestokens.pop() 133 134 # for closures: must be a mutable 135 new = {'valid': True } 136 137 def COMMENT(expected, seq, token, tokenizer=None): 138 "special: sets parent*" 139 comment = cssutils.css.CSSComment([token], parentRule=self, 140 parentStyleSheet=self.parentStyleSheet) 141 seq.append(comment) 142 return expected
143 144 def ruleset(expected, seq, token, tokenizer): 145 rule = cssutils.css.CSSStyleRule(parentRule=self) 146 rule.cssText = (self._tokensupto2(tokenizer, token), 147 namespaces) 148 if rule.valid: 149 rule._parentStyleSheet=self.parentStyleSheet 150 seq.append(rule) 151 return expected
152 153 def atrule(expected, seq, token, tokenizer): 154 # TODO: get complete rule! 155 tokens = self._tokensupto2(tokenizer, token) 156 atval = self._tokenvalue(token) 157 if atval in ('@charset ', '@font-face', '@import', '@namespace', 158 '@page', '@media'): 159 self._log.error( 160 u'CSSMediaRule: This rule is not allowed in CSSMediaRule - ignored: %s.' 161 % self._valuestr(tokens), 162 token = token, 163 error=xml.dom.HierarchyRequestErr) 164 else: 165 rule = cssutils.css.CSSUnknownRule(parentRule=self, 166 parentStyleSheet=self.parentStyleSheet) 167 rule.cssText = tokens 168 if rule.valid: 169 seq.append(rule) 170 return expected 171 172 tokenizer = (t for t in cssrulestokens) # TODO: not elegant! 173 valid, expected = self._parse('}', newcssrules, tokenizer, { 174 'COMMENT': COMMENT, 175 'CHARSET_SYM': atrule, 176 'FONT_FACE_SYM': atrule, 177 'IMPORT_SYM': atrule, 178 'NAMESPACE_SYM': atrule, 179 'PAGE_SYM': atrule, 180 'MEDIA_SYM': atrule, 181 'ATKEYWORD': atrule 182 }, 183 default=ruleset) 184 185 # no post condition 186 187 if newmedia.valid and valid: 188 self._media = newmedia 189 del self.cssRules[:]# = newcssrules 190 for r in newcssrules: 191 self.cssRules.append(r) 192 193 cssText = property(_getCssText, _setCssText, 194 doc="(DOM attribute) The parsable textual representation.") 195
196 - def _getMedia(self):
197 "returns MediaList" 198 return self._media
199 200 media = property(_getMedia, 201 doc=u"(DOM readonly) A list of media types for this rule of type\ 202 MediaList") 203
204 - def deleteRule(self, index):
205 """ 206 index 207 within the media block's rule collection of the rule to remove. 208 209 Used to delete a rule from the media block. 210 211 DOMExceptions 212 213 - INDEX_SIZE_ERR: (self) 214 Raised if the specified index does not correspond to a rule in 215 the media rule list. 216 - NO_MODIFICATION_ALLOWED_ERR: (self) 217 Raised if this media rule is readonly. 218 """ 219 self._checkReadonly() 220 221 try: 222 self.cssRules[index]._parentRule = None # detach 223 del self.cssRules[index] # remove from @media 224 except IndexError: 225 raise xml.dom.IndexSizeErr( 226 u'CSSMediaRule: %s is not a valid index in the rulelist of length %i' % ( 227 index, self.cssRules.length))
228
229 - def add(self, rule):
230 """ 231 Adds rule to end of this mediarule. Same as ``.insertRule(rule)``. 232 """ 233 self.insertRule(rule, index=None)
234
235 - def insertRule(self, rule, index=None):
236 """ 237 rule 238 The parsable text representing the rule. For rule sets this 239 contains both the selector and the style declaration. For 240 at-rules, this specifies both the at-identifier and the rule 241 content. 242 243 cssutils also allows rule to be a valid **CSSRule** object 244 245 index 246 within the media block's rule collection of the rule before 247 which to insert the specified rule. If the specified index is 248 equal to the length of the media blocks's rule collection, the 249 rule will be added to the end of the media block. 250 If index is not given or None rule will be appended to rule 251 list. 252 253 Used to insert a new rule into the media block. 254 255 DOMException on setting 256 257 - HIERARCHY_REQUEST_ERR: 258 (no use case yet as no @charset or @import allowed)) 259 Raised if the rule cannot be inserted at the specified index, 260 e.g., if an @import rule is inserted after a standard rule set 261 or other at-rule. 262 - INDEX_SIZE_ERR: (self) 263 Raised if the specified index is not a valid insertion point. 264 - NO_MODIFICATION_ALLOWED_ERR: (self) 265 Raised if this media rule is readonly. 266 - SYNTAX_ERR: (CSSStyleRule) 267 Raised if the specified rule has a syntax error and is 268 unparsable. 269 270 returns the index within the media block's rule collection of the 271 newly inserted rule. 272 273 """ 274 self._checkReadonly() 275 276 # check position 277 if index is None: 278 index = len(self.cssRules) 279 elif index < 0 or index > self.cssRules.length: 280 raise xml.dom.IndexSizeErr( 281 u'CSSMediaRule: Invalid index %s for CSSRuleList with a length of %s.' % ( 282 index, self.cssRules.length)) 283 284 # parse 285 if isinstance(rule, basestring): 286 tempsheet = cssutils.css.CSSStyleSheet() 287 tempsheet.cssText = rule 288 if len(tempsheet.cssRules) != 1 or (tempsheet.cssRules and 289 not isinstance(tempsheet.cssRules[0], cssutils.css.CSSRule)): 290 self._log.error(u'CSSMediaRule: Invalid Rule: %s' % rule) 291 return 292 rule = tempsheet.cssRules[0] 293 elif not isinstance(rule, cssutils.css.CSSRule): 294 self._log.error(u'CSSMediaRule: Not a CSSRule: %s' % rule) 295 return 296 297 # CHECK HIERARCHY 298 # @charset @import @page @namespace @media 299 if isinstance(rule, cssutils.css.CSSCharsetRule) or \ 300 isinstance(rule, cssutils.css.CSSFontFaceRule) or \ 301 isinstance(rule, cssutils.css.CSSImportRule) or \ 302 isinstance(rule, cssutils.css.CSSNamespaceRule) or \ 303 isinstance(rule, cssutils.css.CSSPageRule) or \ 304 isinstance(rule, CSSMediaRule): 305 self._log.error(u'CSSMediaRule: This type of rule is not allowed here: %s' % 306 rule.cssText, 307 error=xml.dom.HierarchyRequestErr) 308 return 309 310 self.cssRules.insert(index, rule) 311 rule._parentRule = self 312 rule._parentStyleSheet = self.parentStyleSheet 313 return index
314
315 - def __repr__(self):
316 return "cssutils.css.%s(mediaText=%r)" % ( 317 self.__class__.__name__, self.media.mediaText)
318
319 - def __str__(self):
320 return "<cssutils.css.%s object mediaText=%r at 0x%x>" % ( 321 self.__class__.__name__, self.media.mediaText, id(self))
322