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