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

Source Code for Module cssutils.css.selector

  1  """Selector is a single Selector of a CSSStyleRule SelectorList. 
  2   
  3  Partly implements 
  4      http://www.w3.org/TR/css3-selectors/ 
  5   
  6  TODO 
  7      - .contains(selector) 
  8      - .isSubselector(selector) 
  9   
 10      - ??? CSS2 gives a special meaning to the comma (,) in selectors. 
 11          However, since it is not known if the comma may acquire other 
 12          meanings in future versions of CSS, the whole statement should be 
 13          ignored if there is an error anywhere in the selector, even though 
 14          the rest of the selector may look reasonable in CSS2. 
 15   
 16          Illegal example(s): 
 17   
 18          For example, since the "&" is not a valid token in a CSS2 selector, 
 19          a CSS2 user agent must ignore the whole second line, and not set 
 20          the color of H3 to red: 
 21  """ 
 22  __all__ = ['Selector'] 
 23  __docformat__ = 'restructuredtext' 
 24  __author__ = '$LastChangedBy: cthedot $' 
 25  __date__ = '$LastChangedDate: 2008-01-06 01:15:07 +0100 (So, 06 Jan 2008) $' 
 26  __version__ = '$LastChangedRevision: 821 $' 
 27   
 28  import xml.dom 
 29   
 30  import cssutils 
 31   
32 -class Selector(cssutils.util.Base2):
33 """ 34 (cssutils) a single selector in a SelectorList of a CSSStyleRule 35 36 Properties 37 ========== 38 selectorText 39 textual representation of this Selector 40 namespaces 41 **TODO:** 42 a dict of {prefix: namespaceURI} mapping, may also be a 43 CSSStyleSheet in which case the namespaces defined there 44 are used. If None cssutils tries to get the namespaces as 45 defined in a possible parent CSSStyleSheet. 46 parentRule: of type CSSRule, readonly 47 The CSS rule that contains this declaration block or None if this 48 CSSStyleDeclaration is not attached to a CSSRule. 49 prefixes 50 a set which prefixes have been used in this selector 51 seq 52 sequence of Selector parts including comments 53 specificity (READONLY) 54 tuple of (a, b, c, d) where: 55 56 a 57 presence of style in document, currently always 0 58 b 59 # of ID selectors 60 c 61 # of .class selectors 62 d 63 # of Element (type) selectors 64 65 wellformed 66 if this selector is wellformed regarding the Selector spec 67 68 Format 69 ====== 70 :: 71 72 # implemented in SelectorList 73 selectors_group 74 : selector [ COMMA S* selector ]* 75 ; 76 77 selector 78 : simple_selector_sequence [ combinator simple_selector_sequence ]* 79 ; 80 81 combinator 82 /* combinators can be surrounded by white space */ 83 : PLUS S* | GREATER S* | TILDE S* | S+ 84 ; 85 86 simple_selector_sequence 87 : [ type_selector | universal ] 88 [ HASH | class | attrib | pseudo | negation ]* 89 | [ HASH | class | attrib | pseudo | negation ]+ 90 ; 91 92 type_selector 93 : [ namespace_prefix ]? element_name 94 ; 95 96 namespace_prefix 97 : [ IDENT | '*' ]? '|' 98 ; 99 100 element_name 101 : IDENT 102 ; 103 104 universal 105 : [ namespace_prefix ]? '*' 106 ; 107 108 class 109 : '.' IDENT 110 ; 111 112 attrib 113 : '[' S* [ namespace_prefix ]? IDENT S* 114 [ [ PREFIXMATCH | 115 SUFFIXMATCH | 116 SUBSTRINGMATCH | 117 '=' | 118 INCLUDES | 119 DASHMATCH ] S* [ IDENT | STRING ] S* 120 ]? ']' 121 ; 122 123 pseudo 124 /* '::' starts a pseudo-element, ':' a pseudo-class */ 125 /* Exceptions: :first-line, :first-letter, :before and :after. */ 126 /* Note that pseudo-elements are restricted to one per selector and */ 127 /* occur only in the last simple_selector_sequence. */ 128 : ':' ':'? [ IDENT | functional_pseudo ] 129 ; 130 131 functional_pseudo 132 : FUNCTION S* expression ')' 133 ; 134 135 expression 136 /* In CSS3, the expressions are identifiers, strings, */ 137 /* or of the form "an+b" */ 138 : [ [ PLUS | '-' | DIMENSION | NUMBER | STRING | IDENT ] S* ]+ 139 ; 140 141 negation 142 : NOT S* negation_arg S* ')' 143 ; 144 145 negation_arg 146 : type_selector | universal | HASH | class | attrib | pseudo 147 ; 148 149 """
150 - def __init__(self, selectorText=None, namespaces=None, 151 parentRule=None, readonly=False):
152 """ 153 selectorText 154 initial value of this selector 155 parentRule 156 a CSSStyleRule 157 readonly 158 default to False 159 """ 160 super(Selector, self).__init__() 161 162 self._element = None 163 if not namespaces: 164 namespaces = {} 165 self.namespaces = namespaces 166 self.parentRule = parentRule 167 self.prefixes = set() 168 self._specificity = (0, 0, 0, 0) 169 self.wellformed = False 170 if selectorText: 171 self.selectorText = selectorText 172 self._readonly = readonly
173 174 element = property(lambda self: self._element, 175 doc="Element of this selector (READONLY).") 176
177 - def _getParentRule(self):
178 return self._parentRule
179
180 - def _setParentRule(self, parentRule):
181 self._parentRule = parentRule
182 183 parentRule = property(_getParentRule, _setParentRule, 184 doc="(DOM) The CSS rule that contains this Selector or\ 185 None if this Selector is not attached to a CSSRule.") 186
187 - def _getSelectorText(self):
188 """ 189 returns serialized format 190 """ 191 return cssutils.ser.do_css_Selector(self)
192
193 - def _setSelectorText(self, selectorText):
194 """ 195 sets this selectorText 196 197 TODO: 198 raises xml.dom.Exception 199 """ 200 self._checkReadonly() 201 tokenizer = self._tokenize2(selectorText) 202 if not tokenizer: 203 self._log.error(u'Selector: No selectorText given.') 204 else: 205 # prepare tokenlist: 206 # "*" -> type "universal" 207 # "*"|IDENT + "|" -> combined to "namespace_prefix" 208 # "|" -> type "namespace_prefix" 209 # "." + IDENT -> combined to "class" 210 # ":" + IDENT, ":" + FUNCTION -> pseudo-class 211 # FUNCTION "not(" -> negation 212 # "::" + IDENT, "::" + FUNCTION -> pseudo-element 213 tokens = [] 214 for t in tokenizer: 215 typ, val, lin, col = t 216 if val == u':' and tokens and\ 217 self._tokenvalue(tokens[-1]) == ':': 218 # combine ":" and ":" 219 tokens[-1] = (typ, u'::', lin, col) 220 221 elif typ == 'IDENT' and tokens\ 222 and self._tokenvalue(tokens[-1]) == u'.': 223 # class: combine to .IDENT 224 tokens[-1] = ('class', u'.'+val, lin, col) 225 elif typ == 'IDENT' and tokens and \ 226 self._tokenvalue(tokens[-1]).startswith(u':') and\ 227 not self._tokenvalue(tokens[-1]).endswith(u'('): 228 # pseudo-X: combine to :IDENT or ::IDENT but not ":a(" + "b" 229 if self._tokenvalue(tokens[-1]).startswith(u'::'): 230 t = 'pseudo-element' 231 else: 232 t = 'pseudo-class' 233 tokens[-1] = (t, self._tokenvalue(tokens[-1])+val, lin, col) 234 235 elif typ == 'FUNCTION' and val == u'not(' and tokens and \ 236 u':' == self._tokenvalue(tokens[-1]): 237 tokens[-1] = ('negation', u':' + val, lin, tokens[-1][3]) 238 elif typ == 'FUNCTION' and tokens\ 239 and self._tokenvalue(tokens[-1]).startswith(u':'): 240 # pseudo-X: combine to :FUNCTION( or ::FUNCTION( 241 if self._tokenvalue(tokens[-1]).startswith(u'::'): 242 t = 'pseudo-element' 243 else: 244 t = 'pseudo-class' 245 tokens[-1] = (t, self._tokenvalue(tokens[-1])+val, lin, col) 246 247 elif val == u'*' and tokens and\ 248 self._type(tokens[-1]) == 'namespace_prefix' and\ 249 self._tokenvalue(tokens[-1]).endswith(u'|'): 250 # combine prefix|* 251 tokens[-1] = ('universal', self._tokenvalue(tokens[-1])+val, 252 lin, col) 253 elif val == u'*': 254 # universal: "*" 255 tokens.append(('universal', val, lin, col)) 256 257 elif val == u'|' and tokens and\ 258 self._type(tokens[-1]) in ('IDENT', 'universal') and\ 259 self._tokenvalue(tokens[-1]).find(u'|') == -1: 260 # namespace_prefix: "IDENT|" or "*|" 261 tokens[-1] = ('namespace_prefix', 262 self._tokenvalue(tokens[-1])+u'|', lin, col) 263 elif val == u'|': 264 # namespace_prefix: "|" 265 tokens.append(('namespace_prefix', val, lin, col)) 266 267 else: 268 tokens.append(t) 269 270 # TODO: back to generator but not elegant at all! 271 tokenizer = (t for t in tokens) 272 273 # for closures: must be a mutable 274 new = {'context': [''], # stack of: 'attrib', 'negation', 'pseudo' 275 'element': None, 276 '_PREFIX': None, 277 'prefixes': set(), 278 'specificity': [0, 0, 0, 0], # mutable, finally a tuple! 279 'wellformed': True 280 } 281 # used for equality checks and setting of a space combinator 282 S = u' ' 283 284 def append(seq, val, typ=None, line=-1, col=0, context=None): 285 """ 286 appends to seq 287 288 namespace_prefix, IDENT will be combined to a tuple 289 (prefix, name) where prefix might be None, the empty string 290 or a prefix. 291 292 Saved are also: 293 - specificity definition: style, id, class, type 294 - element: the element this Selector is for 295 """ 296 if typ == '_PREFIX': 297 # SPECIAL TYPE: save prefix for combination with next 298 new['_PREFIX'] = val[:-1] 299 return 300 301 if new['_PREFIX'] is not None: 302 # as saved from before 303 prefix, new['_PREFIX'] = new['_PREFIX'], None 304 elif typ == 'universal' and '|' in val: 305 # val == *|* or prefix|* 306 prefix, val = val.split('|') 307 else: 308 prefix = u'' 309 310 # TODO: CHECK IF THIS IS REALLY OK! 311 if typ.endswith('-selector') or typ == 'universal': 312 # val is (namespaceprefix, name) tuple 313 if prefix == u'*': 314 namespaceURI = None 315 elif prefix == u'': 316 namespaceURI = self.namespaces.get(prefix, u'') 317 else: 318 try: 319 namespaceURI = self.namespaces[prefix] 320 except (KeyError,):# TypeError): 321 new['wellformed'] = False 322 self._log.error(u'No namespaceURI found for prefix %r' % 323 prefix, token=(typ, val, line, col), 324 error=xml.dom.NamespaceErr) 325 val = (namespaceURI, val) 326 327 if not context or context == 'negation': 328 # define specificity 329 if 'id' == typ: 330 new['specificity'][1] += 1 331 elif 'class' == typ or '[' == val: 332 new['specificity'][2] += 1 333 elif typ in ('type-selector', 'negation-type-selector', 334 'pseudo-element'): 335 new['specificity'][3] += 1 336 if not context and typ in ('type-selector', 'universal'): 337 # define element 338 new['element'] = val 339 340 seq.append(val, typ)
341 342 # expected constants 343 simple_selector_sequence = 'type_selector universal HASH class attrib pseudo negation ' 344 simple_selector_sequence2 = 'HASH class attrib pseudo negation ' 345 346 element_name = 'element_name' 347 348 negation_arg = 'type_selector universal HASH class attrib pseudo' 349 negationend = ')' 350 351 attname = 'prefix attribute' 352 attname2 = 'attribute' 353 attcombinator = 'combinator ]' # optional 354 attvalue = 'value' # optional 355 attend = ']' 356 357 expressionstart = 'PLUS - DIMENSION NUMBER STRING IDENT' 358 expression = expressionstart + ' )' 359 360 combinator = ' combinator' 361 362 def _COMMENT(expected, seq, token, tokenizer=None): 363 "special implementation for comment token" 364 append(seq, cssutils.css.CSSComment([token]), 'comment') 365 return expected
366 367 def _S(expected, seq, token, tokenizer=None): 368 # S 369 context = new['context'][-1] 370 val, typ = self._tokenvalue(token), self._type(token) 371 if context.startswith('pseudo-'): 372 append(seq, S, 'descendant', context=context) 373 return expected 374 375 elif context != 'attrib' and 'combinator' in expected: 376 append(seq, S, 'descendant', context=context) 377 return simple_selector_sequence + combinator 378 379 else: 380 return expected 381 382 def _universal(expected, seq, token, tokenizer=None): 383 # *|* or prefix|* 384 context = new['context'][-1] 385 val, typ = self._tokenvalue(token), self._type(token) 386 if 'universal' in expected: 387 append(seq, val, 'universal', context=context) 388 389 newprefix = val.split(u'|')[0] 390 if newprefix and newprefix != u'*': 391 new['prefixes'].add(newprefix) 392 393 if 'negation' == context: 394 return negationend 395 else: 396 return simple_selector_sequence2 + combinator 397 398 else: 399 new['wellformed'] = False 400 self._log.error( 401 u'Selector: Unexpected universal.', token=token) 402 return expected 403 404 def _namespace_prefix(expected, seq, token, tokenizer=None): 405 # prefix| => element_name 406 # or prefix| => attribute_name if attrib 407 context = new['context'][-1] 408 val, typ = self._tokenvalue(token), self._type(token) 409 if 'attrib' == context and 'prefix' in expected: 410 # [PREFIX|att] 411 append(seq, val, '_PREFIX', context=context) 412 413 newprefix = val.split(u'|')[0] 414 if newprefix and newprefix != u'*': 415 new['prefixes'].add(newprefix) 416 417 return attname2 418 elif 'type_selector' in expected: 419 # PREFIX|* 420 append(seq, val, '_PREFIX', context=context) 421 422 newprefix = val.split(u'|')[0] 423 if newprefix and newprefix != u'*': 424 new['prefixes'].add(newprefix) 425 426 return element_name 427 else: 428 new['wellformed'] = False 429 self._log.error( 430 u'Selector: Unexpected namespace prefix.', token=token) 431 return expected 432 433 def _pseudo(expected, seq, token, tokenizer=None): 434 # pseudo-class or pseudo-element :a ::a :a( ::a( 435 """ 436 /* '::' starts a pseudo-element, ':' a pseudo-class */ 437 /* Exceptions: :first-line, :first-letter, :before and :after. */ 438 /* Note that pseudo-elements are restricted to one per selector and */ 439 /* occur only in the last simple_selector_sequence. */ 440 """ 441 context = new['context'][-1] 442 val, typ = self._tokenvalue(token, normalize=True), self._type(token) 443 if 'pseudo' in expected: 444 if val in (':first-line', ':first-letter', ':before', ':after'): 445 # always pseudo-element ??? 446 typ = 'pseudo-element' 447 append(seq, val, typ, context=context) 448 449 if val.endswith(u'('): 450 # function 451 new['context'].append(typ) # "pseudo-" "class" or "element" 452 return expressionstart 453 elif 'negation' == context: 454 return negationend 455 elif 'pseudo-element' == typ: 456 # only one per element, check at ) also! 457 return combinator 458 else: 459 return simple_selector_sequence2 + combinator 460 461 else: 462 new['wellformed'] = False 463 self._log.error( 464 u'Selector: Unexpected start of pseudo.', token=token) 465 return expected 466 467 def _expression(expected, seq, token, tokenizer=None): 468 # [ [ PLUS | '-' | DIMENSION | NUMBER | STRING | IDENT ] S* ]+ 469 context = new['context'][-1] 470 val, typ = self._tokenvalue(token), self._type(token) 471 if context.startswith('pseudo-'): 472 append(seq, val, typ, context=context) 473 return expression 474 else: 475 new['wellformed'] = False 476 self._log.error( 477 u'Selector: Unexpected %s.' % typ, token=token) 478 return expected 479 480 def _attcombinator(expected, seq, token, tokenizer=None): 481 # context: attrib 482 # PREFIXMATCH | SUFFIXMATCH | SUBSTRINGMATCH | INCLUDES | 483 # DASHMATCH 484 context = new['context'][-1] 485 val, typ = self._tokenvalue(token), self._type(token) 486 if 'attrib' == context and 'combinator' in expected: 487 # combinator in attrib 488 append(seq, val, typ.lower(), context=context) 489 return attvalue 490 else: 491 new['wellformed'] = False 492 self._log.error( 493 u'Selector: Unexpected %s.' % typ, token=token) 494 return expected 495 496 def _string(expected, seq, token, tokenizer=None): 497 # identifier 498 context = new['context'][-1] 499 val, typ = self._tokenvalue(token), self._type(token) 500 501 # context: attrib 502 if 'attrib' == context and 'value' in expected: 503 # attrib: [...=VALUE] 504 append(seq, val, 'string', context=context) 505 return attend 506 507 # context: pseudo 508 elif context.startswith('pseudo-'): 509 # :func(...) 510 append(seq, val, 'string', context=context) 511 return expression 512 513 else: 514 new['wellformed'] = False 515 self._log.error( 516 u'Selector: Unexpected STRING.', token=token) 517 return expected 518 519 def _ident(expected, seq, token, tokenizer=None): 520 # identifier 521 context = new['context'][-1] 522 val, typ = self._tokenvalue(token), self._type(token) 523 524 # context: attrib 525 if 'attrib' == context and 'attribute' in expected: 526 # attrib: [...|ATT...] 527 append(seq, val, 'attribute-selector', context=context) 528 return attcombinator 529 530 elif 'attrib' == context and 'value' in expected: 531 # attrib: [...=VALUE] 532 append(seq, val, 'attribute-value', context=context) 533 return attend 534 535 # context: negation 536 elif 'negation' == context: 537 # negation: (prefix|IDENT) 538 append(seq, val, 'negation-type-selector', context=context) 539 return negationend 540 541 # context: pseudo 542 elif context.startswith('pseudo-'): 543 # :func(...) 544 append(seq, val, typ, context=context) 545 return expression 546 547 elif 'type_selector' in expected or element_name == expected: 548 # element name after ns or complete type_selector 549 append(seq, val, 'type-selector', context=context) 550 return simple_selector_sequence2 + combinator 551 552 else: 553 new['wellformed'] = False 554 self._log.error( 555 u'Selector: Unexpected IDENT.', 556 token=token) 557 return expected 558 559 def _class(expected, seq, token, tokenizer=None): 560 # .IDENT 561 context = new['context'][-1] 562 val, typ = self._tokenvalue(token), self._type(token) 563 if 'class' in expected: 564 append(seq, val, typ, context=context) 565 566 if 'negation' == context: 567 return negationend 568 else: 569 return simple_selector_sequence2 + combinator 570 571 else: 572 new['wellformed'] = False 573 self._log.error( 574 u'Selector: Unexpected class.', token=token) 575 return expected 576 577 def _hash(expected, seq, token, tokenizer=None): 578 # #IDENT 579 context = new['context'][-1] 580 val, typ = self._tokenvalue(token), self._type(token) 581 if 'HASH' in expected: 582 append(seq, val, 'id', context=context) 583 584 if 'negation' == context: 585 return negationend 586 else: 587 return simple_selector_sequence2 + combinator 588 589 else: 590 new['wellformed'] = False 591 self._log.error( 592 u'Selector: Unexpected HASH.', token=token) 593 return expected 594 595 def _char(expected, seq, token, tokenizer=None): 596 # + > ~ ) [ ] + - 597 context = new['context'][-1] 598 val, typ = self._tokenvalue(token), self._type(token) 599 600 # context: attrib 601 if u']' == val and 'attrib' == context and ']' in expected: 602 # end of attrib 603 append(seq, val, 'attribute-end', context=context) 604 context = new['context'].pop() # attrib is done 605 context = new['context'][-1] 606 if 'negation' == context: 607 return negationend 608 else: 609 return simple_selector_sequence2 + combinator 610 611 elif u'=' == val and 'attrib' == context and 'combinator' in expected: 612 # combinator in attrib 613 append(seq, val, 'equals', context=context) 614 return attvalue 615 616 # context: negation 617 elif u')' == val and 'negation' == context and u')' in expected: 618 # not(negation_arg)" 619 append(seq, val, 'negation-end', context=context) 620 new['context'].pop() # negation is done 621 context = new['context'][-1] 622 return simple_selector_sequence + combinator 623 624 # context: pseudo (at least one expression) 625 elif val in u'+-' and context.startswith('pseudo-'): 626 # :func(+ -)" 627 append(seq, val, {'+': 'plus', '-': 'minus'}[val], context=context) 628 return expression 629 630 elif u')' == val and context.startswith('pseudo-') and\ 631 expression == expected: 632 # :func(expression)" 633 append(seq, val, 'function-end', context=context) 634 new['context'].pop() # pseudo is done 635 if 'pseudo-element' == context: 636 return combinator 637 else: 638 return simple_selector_sequence + combinator 639 640 # context: ROOT 641 elif u'[' == val and 'attrib' in expected: 642 # start of [attrib] 643 new['context'].append('attrib') 644 append(seq, val, 'attribute-start', context=context) 645 return attname 646 647 elif val in u'+>~' and 'combinator' in expected: 648 # no other combinator except S may be following 649 _names = { 650 '>': 'child', 651 '+': 'adjacent-sibling', 652 '~': 'following-sibling'} 653 if seq and seq[-1].value == S: 654 seq.replace(-1, val, _names[val]) 655 else: 656 append(seq, val, _names[val], context=context) 657 return simple_selector_sequence 658 659 elif u',' == val: 660 # not a selectorlist 661 new['wellformed'] = False 662 self._log.error( 663 u'Selector: Single selector only.', 664 error=xml.dom.InvalidModificationErr, 665 token=token) 666 667 else: 668 new['wellformed'] = False 669 self._log.error( 670 u'Selector: Unexpected CHAR.', token=token) 671 return expected 672 673 def _negation(expected, seq, token, tokenizer=None): 674 # not( 675 context = new['context'][-1] 676 val = self._tokenvalue(token, normalize=True) 677 if 'negation' in expected: 678 new['context'].append('negation') 679 append(seq, val, 'negation-start', context=context) 680 return negation_arg 681 else: 682 new['wellformed'] = False 683 self._log.error( 684 u'Selector: Unexpected negation.', token=token) 685 return expected 686 687 # expected: only|not or mediatype, mediatype, feature, and 688 newseq = self._tempSeq() 689 690 wellformed, expected = self._parse(expected=simple_selector_sequence, 691 seq=newseq, tokenizer=tokenizer, 692 productions={'CHAR': _char, 693 'class': _class, 694 'HASH': _hash, 695 'STRING': _string, 696 'IDENT': _ident, 697 'namespace_prefix': _namespace_prefix, 698 'negation': _negation, 699 'pseudo-class': _pseudo, 700 'pseudo-element': _pseudo, 701 'universal': _universal, 702 # pseudo 703 'NUMBER': _expression, 704 'DIMENSION': _expression, 705 # attribute 706 'PREFIXMATCH': _attcombinator, 707 'SUFFIXMATCH': _attcombinator, 708 'SUBSTRINGMATCH': _attcombinator, 709 'DASHMATCH': _attcombinator, 710 'INCLUDES': _attcombinator, 711 712 'S': _S, 713 'COMMENT': _COMMENT}) 714 wellformed = wellformed and new['wellformed'] 715 716 # post condition 717 if len(new['context']) > 1: 718 wellformed = False 719 self._log.error(u'Selector: Incomplete selector: %s' % 720 self._valuestr(selectorText)) 721 722 if expected == 'element_name': 723 wellformed = False 724 self._log.error(u'Selector: No element name found: %s' % 725 self._valuestr(selectorText)) 726 727 if expected == simple_selector_sequence: 728 wellformed = False 729 self._log.error(u'Selector: Cannot end with combinator: %s' % 730 self._valuestr(selectorText)) 731 732 if newseq and hasattr(newseq[-1].value, 'strip') and \ 733 newseq[-1].value.strip() == u'': 734 del newseq[-1] 735 736 # set 737 if wellformed: 738 self._element = new['element'] 739 self.prefixes = new['prefixes'] 740 self.seq = newseq 741 self._specificity = tuple(new['specificity']) 742 self.wellformed = True 743 744 selectorText = property(_getSelectorText, _setSelectorText, 745 doc="(DOM) The parsable textual representation of the selector.") 746 747 specificity = property(lambda self: self._specificity, 748 doc="specificity of this selector (READONLY).") 749
750 - def __repr__(self):
751 return "cssutils.css.%s(selectorText=%r)" % ( 752 self.__class__.__name__, self.selectorText)
753
754 - def __str__(self):
755 return "<cssutils.css.%s object selectorText=%r specificity=%r at 0x%x>" % ( 756 self.__class__.__name__, self.selectorText, 757 self.specificity, id(self))
758