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

Source Code for Module cssutils.css.cssstylesheet

  1  """ 
  2  CSSStyleSheet implements DOM Level 2 CSS CSSStyleSheet. 
  3   
  4  Partly also: 
  5      - http://dev.w3.org/csswg/cssom/#the-cssstylesheet 
  6      - http://www.w3.org/TR/2006/WD-css3-namespace-20060828/ 
  7   
  8  TODO: 
  9      - ownerRule and ownerNode 
 10  """ 
 11  __all__ = ['CSSStyleSheet'] 
 12  __docformat__ = 'restructuredtext' 
 13  __version__ = '$Id: cssstylesheet.py 1395 2008-07-27 13:30:13Z cthedot $' 
 14   
 15  import xml.dom 
 16  import cssutils.stylesheets 
 17  from cssutils.util import _Namespaces, _SimpleNamespaces, _readUrl 
 18  from cssutils.helper import Deprecated 
19 20 -class CSSStyleSheet(cssutils.stylesheets.StyleSheet):
21 """ 22 The CSSStyleSheet interface represents a CSS style sheet. 23 24 Properties 25 ========== 26 CSSOM 27 ----- 28 cssRules 29 of type CSSRuleList, (DOM readonly) 30 encoding 31 reflects the encoding of an @charset rule or 'utf-8' (default) 32 if set to ``None`` 33 ownerRule 34 of type CSSRule, readonly. If this sheet is imported this is a ref 35 to the @import rule that imports it. 36 37 Inherits properties from stylesheet.StyleSheet 38 39 cssutils 40 -------- 41 cssText: string 42 a textual representation of the stylesheet 43 namespaces 44 reflects set @namespace rules of this rule. 45 A dict of {prefix: namespaceURI} mapping. 46 47 Format 48 ====== 49 stylesheet 50 : [ CHARSET_SYM S* STRING S* ';' ]? 51 [S|CDO|CDC]* [ import [S|CDO|CDC]* ]* 52 [ namespace [S|CDO|CDC]* ]* # according to @namespace WD 53 [ [ ruleset | media | page ] [S|CDO|CDC]* ]* 54 """
55 - def __init__(self, href=None, media=None, title=u'', disabled=None, 56 ownerNode=None, parentStyleSheet=None, readonly=False, 57 ownerRule=None):
58 """ 59 init parameters are the same as for stylesheets.StyleSheet 60 """ 61 super(CSSStyleSheet, self).__init__( 62 'text/css', href, media, title, disabled, 63 ownerNode, parentStyleSheet) 64 65 self._ownerRule = ownerRule 66 self.cssRules = cssutils.css.CSSRuleList() 67 self.cssRules.append = self.insertRule 68 self.cssRules.extend = self.insertRule 69 self._namespaces = _Namespaces(parentStyleSheet=self) 70 self._readonly = readonly 71 72 # used only during setting cssText by parse*() 73 self.__encodingOverride = None 74 self._fetcher = None
75
76 - def __iter__(self):
77 "generator which iterates over cssRules." 78 for rule in self.cssRules: 79 yield rule
80
81 - def _cleanNamespaces(self):
82 "removes all namespace rules with same namespaceURI but last one set" 83 rules = self.cssRules 84 namespaceitems = self.namespaces.items() 85 i = 0 86 while i < len(rules): 87 rule = rules[i] 88 if rule.type == rule.NAMESPACE_RULE and \ 89 (rule.prefix, rule.namespaceURI) not in namespaceitems: 90 self.deleteRule(i) 91 else: 92 i += 1
93
94 - def _getUsedURIs(self):
95 "returns set of URIs used in the sheet" 96 useduris = set() 97 for r1 in self: 98 if r1.STYLE_RULE == r1.type: 99 useduris.update(r1.selectorList._getUsedUris()) 100 elif r1.MEDIA_RULE == r1.type: 101 for r2 in r1: 102 if r2.type == r2.STYLE_RULE: 103 useduris.update(r2.selectorList._getUsedUris()) 104 return useduris
105
106 - def _getCssText(self):
107 return cssutils.ser.do_CSSStyleSheet(self)
108
109 - def _setCssText(self, cssText):
110 """ 111 (cssutils) 112 Parses ``cssText`` and overwrites the whole stylesheet. 113 114 :param cssText: 115 a parseable string or a tuple of (cssText, dict-of-namespaces) 116 :Exceptions: 117 - `NAMESPACE_ERR`: 118 If a namespace prefix is found which is not declared. 119 - `NO_MODIFICATION_ALLOWED_ERR`: (self) 120 Raised if the rule is readonly. 121 - `SYNTAX_ERR`: 122 Raised if the specified CSS string value has a syntax error and 123 is unparsable. 124 """ 125 self._checkReadonly() 126 127 cssText, namespaces = self._splitNamespacesOff(cssText) 128 if not namespaces: 129 namespaces = _SimpleNamespaces() 130 131 tokenizer = self._tokenize2(cssText) 132 newseq = [] #cssutils.css.CSSRuleList() 133 134 # for closures: must be a mutable 135 new = {'encoding': None, # needed for setting encoding of @import rules 136 'namespaces': namespaces} 137 def S(expected, seq, token, tokenizer=None): 138 # @charset must be at absolute beginning of style sheet 139 if expected == 0: 140 return 1 141 else: 142 return expected
143 144 def COMMENT(expected, seq, token, tokenizer=None): 145 "special: sets parent*" 146 comment = cssutils.css.CSSComment([token], 147 parentStyleSheet=self.parentStyleSheet) 148 seq.append(comment) 149 return expected
150 151 def charsetrule(expected, seq, token, tokenizer): 152 rule = cssutils.css.CSSCharsetRule(parentStyleSheet=self) 153 rule.cssText = self._tokensupto2(tokenizer, token) 154 if expected > 0 or len(seq) > 0: 155 self._log.error( 156 u'CSSStylesheet: CSSCharsetRule only allowed at beginning of stylesheet.', 157 token, xml.dom.HierarchyRequestErr) 158 else: 159 if rule.wellformed: 160 seq.append(rule) 161 new['encoding'] = rule.encoding 162 return 1 163 164 def importrule(expected, seq, token, tokenizer): 165 if new['encoding']: 166 # set temporarily as used by _resolveImport 167 # save newEncoding which have been set by resolveImport 168 self.__newEncoding = new['encoding'] 169 170 rule = cssutils.css.CSSImportRule(parentStyleSheet=self) 171 rule.cssText = self._tokensupto2(tokenizer, token) 172 if expected > 1: 173 self._log.error( 174 u'CSSStylesheet: CSSImportRule not allowed here.', 175 token, xml.dom.HierarchyRequestErr) 176 else: 177 if rule.wellformed: 178 #del rule._parentEncoding # remove as later it is read from this sheet! 179 seq.append(rule) 180 181 try: 182 # remove as only used temporarily but may not be set at all 183 del self.__newEncoding 184 except AttributeError, e: 185 pass 186 187 return 1 188 189 def namespacerule(expected, seq, token, tokenizer): 190 rule = cssutils.css.CSSNamespaceRule( 191 cssText=self._tokensupto2(tokenizer, token), 192 parentStyleSheet=self) 193 if expected > 2: 194 self._log.error( 195 u'CSSStylesheet: CSSNamespaceRule not allowed here.', 196 token, xml.dom.HierarchyRequestErr) 197 else: 198 if rule.wellformed: 199 seq.append(rule) 200 # temporary namespaces given to CSSStyleRule and @media 201 new['namespaces'][rule.prefix] = rule.namespaceURI 202 return 2 203 204 def fontfacerule(expected, seq, token, tokenizer): 205 rule = cssutils.css.CSSFontFaceRule(parentStyleSheet=self) 206 rule.cssText = self._tokensupto2(tokenizer, token) 207 if rule.wellformed: 208 seq.append(rule) 209 return 3 210 211 def mediarule(expected, seq, token, tokenizer): 212 rule = cssutils.css.CSSMediaRule() 213 rule.cssText = (self._tokensupto2(tokenizer, token), 214 new['namespaces']) 215 if rule.wellformed: 216 rule._parentStyleSheet=self 217 for r in rule: 218 r._parentStyleSheet=self 219 seq.append(rule) 220 return 3 221 222 def pagerule(expected, seq, token, tokenizer): 223 rule = cssutils.css.CSSPageRule(parentStyleSheet=self) 224 rule.cssText = self._tokensupto2(tokenizer, token) 225 if rule.wellformed: 226 seq.append(rule) 227 return 3 228 229 def unknownrule(expected, seq, token, tokenizer): 230 self._log.warn( 231 u'CSSStylesheet: Unknown @rule found.', 232 token, neverraise=True) 233 rule = cssutils.css.CSSUnknownRule(parentStyleSheet=self) 234 rule.cssText = self._tokensupto2(tokenizer, token) 235 if rule.wellformed: 236 seq.append(rule) 237 return expected 238 239 def ruleset(expected, seq, token, tokenizer): 240 rule = cssutils.css.CSSStyleRule() 241 rule.cssText = (self._tokensupto2(tokenizer, token), 242 new['namespaces']) 243 if rule.wellformed: 244 rule._parentStyleSheet=self 245 seq.append(rule) 246 return 3 247 248 # expected: 249 # ['CHARSET', 'IMPORT', 'NAMESPACE', ('PAGE', 'MEDIA', ruleset)] 250 wellformed, expected = self._parse(0, newseq, tokenizer, 251 {'S': S, 252 'COMMENT': COMMENT, 253 'CDO': lambda *ignored: None, 254 'CDC': lambda *ignored: None, 255 'CHARSET_SYM': charsetrule, 256 'FONT_FACE_SYM': fontfacerule, 257 'IMPORT_SYM': importrule, 258 'NAMESPACE_SYM': namespacerule, 259 'PAGE_SYM': pagerule, 260 'MEDIA_SYM': mediarule, 261 'ATKEYWORD': unknownrule 262 }, 263 default=ruleset) 264 265 if wellformed: 266 del self.cssRules[:] 267 for rule in newseq: 268 self.insertRule(rule, _clean=False) 269 self._cleanNamespaces() 270 271 cssText = property(_getCssText, _setCssText, 272 "(cssutils) a textual representation of the stylesheet") 273
274 - def _resolveImport(self, url):
275 """Read (encoding, enctype, decodedContent) from ``url`` for @import 276 sheets.""" 277 try: 278 # only available during parse of a complete sheet 279 selfAsParentEncoding = self.__newEncoding 280 except AttributeError: 281 try: 282 # explicit @charset 283 selfAsParentEncoding = self.cssRules[0].encoding 284 except (IndexError, AttributeError): 285 # default not UTF-8 but None! 286 selfAsParentEncoding = None 287 288 return _readUrl(url, fetcher=self._fetcher, 289 overrideEncoding=self.__encodingOverride, 290 parentEncoding=selfAsParentEncoding)
291
292 - def _setCssTextWithEncodingOverride(self, cssText, encodingOverride=None, 293 encoding=None):
294 """Set cssText but use ``encodingOverride`` to overwrite detected 295 encoding. This is used by parse and @import during setting of cssText. 296 297 If ``encoding`` is given use this but do not save it as encodingOverride""" 298 if encodingOverride: 299 # encoding during resolving of @import 300 self.__encodingOverride = encodingOverride 301 302 self.__newEncoding = encoding # save for nested @import 303 self.cssText = cssText 304 305 if encodingOverride: 306 # set encodingOverride explicit again! 307 self.encoding = self.__encodingOverride 308 # remove? 309 self.__encodingOverride = None 310 elif encoding: 311 # may e.g. be httpEncoding 312 self.encoding = encoding
313
314 - def _setFetcher(self, fetcher=None):
315 """sets @import URL loader, if None the default is used""" 316 self._fetcher = fetcher
317
318 - def _setEncoding(self, encoding):
319 """ 320 sets encoding of charset rule if present or inserts new charsetrule 321 with given encoding. If encoding if None removes charsetrule if 322 present. 323 """ 324 try: 325 rule = self.cssRules[0] 326 except IndexError: 327 rule = None 328 if rule and rule.CHARSET_RULE == rule.type: 329 if encoding: 330 rule.encoding = encoding 331 else: 332 self.deleteRule(0) 333 elif encoding: 334 self.insertRule(cssutils.css.CSSCharsetRule(encoding=encoding), 0)
335
336 - def _getEncoding(self):
337 "return encoding if @charset rule if given or default of 'utf-8'" 338 try: 339 return self.cssRules[0].encoding 340 except (IndexError, AttributeError): 341 return 'utf-8'
342 343 encoding = property(_getEncoding, _setEncoding, 344 "(cssutils) reflects the encoding of an @charset rule or 'UTF-8' (default) if set to ``None``") 345 346 namespaces = property(lambda self: self._namespaces, 347 doc="Namespaces used in this CSSStyleSheet.") 348
349 - def add(self, rule):
350 """ 351 Adds rule to stylesheet at appropriate position. 352 Same as ``sheet.insertRule(rule, inOrder=True)``. 353 """ 354 return self.insertRule(rule, index=None, inOrder=True)
355
356 - def deleteRule(self, index):
357 """ 358 Used to delete a rule from the style sheet. 359 360 :param index: 361 of the rule to remove in the StyleSheet's rule list. For an 362 index < 0 **no** INDEX_SIZE_ERR is raised but rules for 363 normal Python lists are used. E.g. ``deleteRule(-1)`` removes 364 the last rule in cssRules. 365 :Exceptions: 366 - `INDEX_SIZE_ERR`: (self) 367 Raised if the specified index does not correspond to a rule in 368 the style sheet's rule list. 369 - `NAMESPACE_ERR`: (self) 370 Raised if removing this rule would result in an invalid StyleSheet 371 - `NO_MODIFICATION_ALLOWED_ERR`: (self) 372 Raised if this style sheet is readonly. 373 """ 374 self._checkReadonly() 375 376 try: 377 rule = self.cssRules[index] 378 except IndexError: 379 raise xml.dom.IndexSizeErr( 380 u'CSSStyleSheet: %s is not a valid index in the rulelist of length %i' % ( 381 index, self.cssRules.length)) 382 else: 383 if rule.type == rule.NAMESPACE_RULE: 384 # check all namespacerules if used 385 uris = [r.namespaceURI for r in self if r.type == r.NAMESPACE_RULE] 386 useduris = self._getUsedURIs() 387 if rule.namespaceURI in useduris and\ 388 uris.count(rule.namespaceURI) == 1: 389 raise xml.dom.NoModificationAllowedErr( 390 u'CSSStyleSheet: NamespaceURI defined in this rule is used, cannot remove.') 391 return 392 393 rule._parentStyleSheet = None # detach 394 del self.cssRules[index] # delete from StyleSheet
395
396 - def insertRule(self, rule, index=None, inOrder=False, _clean=True):
397 """ 398 Used to insert a new rule into the style sheet. The new rule now 399 becomes part of the cascade. 400 401 :Parameters: 402 rule 403 a parsable DOMString, in cssutils also a CSSRule or a 404 CSSRuleList 405 index 406 of the rule before the new rule will be inserted. 407 If the specified index is equal to the length of the 408 StyleSheet's rule collection, the rule will be added to the end 409 of the style sheet. 410 If index is not given or None rule will be appended to rule 411 list. 412 inOrder 413 if True the rule will be put to a proper location while 414 ignoring index but without raising HIERARCHY_REQUEST_ERR. 415 The resulting index is returned nevertheless 416 :returns: the index within the stylesheet's rule collection 417 :Exceptions: 418 - `HIERARCHY_REQUEST_ERR`: (self) 419 Raised if the rule cannot be inserted at the specified index 420 e.g. if an @import rule is inserted after a standard rule set 421 or other at-rule. 422 - `INDEX_SIZE_ERR`: (self) 423 Raised if the specified index is not a valid insertion point. 424 - `NO_MODIFICATION_ALLOWED_ERR`: (self) 425 Raised if this style sheet is readonly. 426 - `SYNTAX_ERR`: (rule) 427 Raised if the specified rule has a syntax error and is 428 unparsable. 429 """ 430 self._checkReadonly() 431 432 # check position 433 if index is None: 434 index = len(self.cssRules) 435 elif index < 0 or index > self.cssRules.length: 436 raise xml.dom.IndexSizeErr( 437 u'CSSStyleSheet: Invalid index %s for CSSRuleList with a length of %s.' % ( 438 index, self.cssRules.length)) 439 return 440 441 if isinstance(rule, basestring): 442 # init a temp sheet which has the same properties as self 443 tempsheet = CSSStyleSheet(href=self.href, 444 media=self.media, 445 title=self.title, 446 parentStyleSheet=self.parentStyleSheet, 447 ownerRule=self.ownerRule) 448 tempsheet._ownerNode = self.ownerNode 449 tempsheet._fetcher = self._fetcher 450 451 # prepend encoding if in this sheet to be able to use it in 452 # @import rules encoding resolution 453 # do not add if new rule startswith "@charset" (which is exact!) 454 if not rule.startswith(u'@charset') and (self.cssRules and 455 self.cssRules[0].type == self.cssRules[0].CHARSET_RULE): 456 # rule 0 is @charset! 457 newrulescount, newruleindex = 2, 1 458 rule = self.cssRules[0].cssText + rule 459 else: 460 newrulescount, newruleindex = 1, 0 461 462 # parse the new rule(s) 463 tempsheet.cssText = (rule, self._namespaces) 464 465 if len(tempsheet.cssRules) != newrulescount or (not isinstance( 466 tempsheet.cssRules[newruleindex], cssutils.css.CSSRule)): 467 self._log.error(u'CSSStyleSheet: Not a CSSRule: %s' % rule) 468 return 469 rule = tempsheet.cssRules[newruleindex] 470 rule._parentStyleSheet = None # done later? 471 472 # TODO: 473 #tempsheet._namespaces = self._namespaces 474 475 elif isinstance(rule, cssutils.css.CSSRuleList): 476 # insert all rules 477 for i, r in enumerate(rule): 478 self.insertRule(r, index + i) 479 return index 480 481 if not rule.wellformed: 482 self._log.error(u'CSSStyleSheet: Invalid rules cannot be added.') 483 return 484 485 # CHECK HIERARCHY 486 # @charset 487 if rule.type == rule.CHARSET_RULE: 488 if inOrder: 489 index = 0 490 # always first and only 491 if (self.cssRules and self.cssRules[0].type == rule.CHARSET_RULE): 492 self.cssRules[0].encoding = rule.encoding 493 else: 494 self.cssRules.insert(0, rule) 495 elif index != 0 or (self.cssRules and 496 self.cssRules[0].type == rule.CHARSET_RULE): 497 self._log.error( 498 u'CSSStylesheet: @charset only allowed once at the beginning of a stylesheet.', 499 error=xml.dom.HierarchyRequestErr) 500 return 501 else: 502 self.cssRules.insert(index, rule) 503 504 # @unknown or comment 505 elif rule.type in (rule.UNKNOWN_RULE, rule.COMMENT) and not inOrder: 506 if index == 0 and self.cssRules and\ 507 self.cssRules[0].type == rule.CHARSET_RULE: 508 self._log.error( 509 u'CSSStylesheet: @charset must be the first rule.', 510 error=xml.dom.HierarchyRequestErr) 511 return 512 else: 513 self.cssRules.insert(index, rule) 514 515 # @import 516 elif rule.type == rule.IMPORT_RULE: 517 if inOrder: 518 # automatic order 519 if rule.type in (r.type for r in self): 520 # find last of this type 521 for i, r in enumerate(reversed(self.cssRules)): 522 if r.type == rule.type: 523 index = len(self.cssRules) - i 524 break 525 else: 526 # find first point to insert 527 if self.cssRules and self.cssRules[0].type in (rule.CHARSET_RULE, 528 rule.COMMENT): 529 index = 1 530 else: 531 index = 0 532 else: 533 # after @charset 534 if index == 0 and self.cssRules and\ 535 self.cssRules[0].type == rule.CHARSET_RULE: 536 self._log.error( 537 u'CSSStylesheet: Found @charset at index 0.', 538 error=xml.dom.HierarchyRequestErr) 539 return 540 # before @namespace, @page, @font-face, @media and stylerule 541 for r in self.cssRules[:index]: 542 if r.type in (r.NAMESPACE_RULE, r.MEDIA_RULE, r.PAGE_RULE, 543 r.STYLE_RULE, r.FONT_FACE_RULE): 544 self._log.error( 545 u'CSSStylesheet: Cannot insert @import here, found @namespace, @media, @page or CSSStyleRule before index %s.' % 546 index, 547 error=xml.dom.HierarchyRequestErr) 548 return 549 self.cssRules.insert(index, rule) 550 551 # @namespace 552 elif rule.type == rule.NAMESPACE_RULE: 553 if inOrder: 554 if rule.type in (r.type for r in self): 555 # find last of this type 556 for i, r in enumerate(reversed(self.cssRules)): 557 if r.type == rule.type: 558 index = len(self.cssRules) - i 559 break 560 else: 561 # find first point to insert 562 for i, r in enumerate(self.cssRules): 563 if r.type in (r.MEDIA_RULE, r.PAGE_RULE, r.STYLE_RULE, 564 r.FONT_FACE_RULE, r.UNKNOWN_RULE, r.COMMENT): 565 index = i # before these 566 break 567 else: 568 # after @charset and @import 569 for r in self.cssRules[index:]: 570 if r.type in (r.CHARSET_RULE, r.IMPORT_RULE): 571 self._log.error( 572 u'CSSStylesheet: Cannot insert @namespace here, found @charset or @import after index %s.' % 573 index, 574 error=xml.dom.HierarchyRequestErr) 575 return 576 # before @media and stylerule 577 for r in self.cssRules[:index]: 578 if r.type in (r.MEDIA_RULE, r.PAGE_RULE, r.STYLE_RULE, 579 r.FONT_FACE_RULE): 580 self._log.error( 581 u'CSSStylesheet: Cannot insert @namespace here, found @media, @page or CSSStyleRule before index %s.' % 582 index, 583 error=xml.dom.HierarchyRequestErr) 584 return 585 586 if not (rule.prefix in self.namespaces and 587 self.namespaces[rule.prefix] == rule.namespaceURI): 588 # no doublettes 589 self.cssRules.insert(index, rule) 590 if _clean: 591 self._cleanNamespaces() 592 593 # all other where order is not important 594 else: 595 if inOrder: 596 # simply add to end as no specific order 597 self.cssRules.append(rule) 598 index = len(self.cssRules) - 1 599 else: 600 for r in self.cssRules[index:]: 601 if r.type in (r.CHARSET_RULE, r.IMPORT_RULE, r.NAMESPACE_RULE): 602 self._log.error( 603 u'CSSStylesheet: Cannot insert rule here, found @charset, @import or @namespace before index %s.' % 604 index, 605 error=xml.dom.HierarchyRequestErr) 606 return 607 self.cssRules.insert(index, rule) 608 609 # post settings, TODO: for other rules which contain @rules 610 rule._parentStyleSheet = self 611 if rule.MEDIA_RULE == rule.type: 612 for r in rule: 613 r._parentStyleSheet = self 614 # ? 615 elif rule.IMPORT_RULE == rule.type: 616 rule.href = rule.href # try to reload stylesheet 617 618 return index
619 620 ownerRule = property(lambda self: self._ownerRule, 621 doc="(DOM attribute) NOT IMPLEMENTED YET") 622 623 @Deprecated('Use cssutils.replaceUrls(sheet, replacer) instead.')
624 - def replaceUrls(self, replacer):
625 """ 626 **EXPERIMENTAL** 627 628 Utility method to replace all ``url(urlstring)`` values in 629 ``CSSImportRules`` and ``CSSStyleDeclaration`` objects (properties). 630 631 ``replacer`` must be a function which is called with a single 632 argument ``urlstring`` which is the current value of url() 633 excluding ``url(`` and ``)``. It still may have surrounding 634 single or double quotes though. 635 """ 636 cssutils.replaceUrls(self, replacer)
637
638 - def setSerializer(self, cssserializer):
639 """ 640 Sets the global Serializer used for output of all stylesheet 641 output. 642 """ 643 if isinstance(cssserializer, cssutils.CSSSerializer): 644 cssutils.ser = cssserializer 645 else: 646 raise ValueError(u'Serializer must be an instance of cssutils.CSSSerializer.')
647
648 - def setSerializerPref(self, pref, value):
649 """ 650 Sets Preference of CSSSerializer used for output of this 651 stylesheet. See cssutils.serialize.Preferences for possible 652 preferences to be set. 653 """ 654 cssutils.ser.prefs.__setattr__(pref, value)
655
656 - def __repr__(self):
657 if self.media: 658 mediaText = self.media.mediaText 659 else: 660 mediaText = None 661 return "cssutils.css.%s(href=%r, media=%r, title=%r)" % ( 662 self.__class__.__name__, 663 self.href, mediaText, self.title)
664
665 - def __str__(self):
666 if self.media: 667 mediaText = self.media.mediaText 668 else: 669 mediaText = None 670 return "<cssutils.css.%s object encoding=%r href=%r "\ 671 "media=%r title=%r namespaces=%r at 0x%x>" % ( 672 self.__class__.__name__, self.encoding, self.href, 673 mediaText, self.title, self.namespaces.namespaces, 674 id(self))
675