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  __author__ = '$LastChangedBy: cthedot $' 
 13  __date__ = '$LastChangedDate: 2008-02-22 19:03:20 +0100 (Fr, 22 Feb 2008) $' 
 14  __version__ = '$LastChangedRevision: 1070 $' 
 15   
 16  import xml.dom 
 17  import cssutils 
 18  from cssutils.util import _SimpleNamespaces 
 19   
20 -class Selector(cssutils.util.Base2):
21 """ 22 (cssutils) a single selector in a SelectorList of a CSSStyleRule 23 24 Properties 25 ========== 26 element 27 Effective element target of this selector 28 parentList: of type SelectorList, readonly 29 The SelectorList that contains this selector or None if this 30 Selector is not attached to a SelectorList. 31 selectorText 32 textual representation of this Selector 33 seq 34 sequence of Selector parts including comments 35 specificity (READONLY) 36 tuple of (a, b, c, d) where: 37 38 a 39 presence of style in document, always 0 if not used on a document 40 b 41 number of ID selectors 42 c 43 number of .class selectors 44 d 45 number of Element (type) selectors 46 47 wellformed 48 if this selector is wellformed regarding the Selector spec 49 50 Format 51 ====== 52 :: 53 54 # implemented in SelectorList 55 selectors_group 56 : selector [ COMMA S* selector ]* 57 ; 58 59 selector 60 : simple_selector_sequence [ combinator simple_selector_sequence ]* 61 ; 62 63 combinator 64 /* combinators can be surrounded by white space */ 65 : PLUS S* | GREATER S* | TILDE S* | S+ 66 ; 67 68 simple_selector_sequence 69 : [ type_selector | universal ] 70 [ HASH | class | attrib | pseudo | negation ]* 71 | [ HASH | class | attrib | pseudo | negation ]+ 72 ; 73 74 type_selector 75 : [ namespace_prefix ]? element_name 76 ; 77 78 namespace_prefix 79 : [ IDENT | '*' ]? '|' 80 ; 81 82 element_name 83 : IDENT 84 ; 85 86 universal 87 : [ namespace_prefix ]? '*' 88 ; 89 90 class 91 : '.' IDENT 92 ; 93 94 attrib 95 : '[' S* [ namespace_prefix ]? IDENT S* 96 [ [ PREFIXMATCH | 97 SUFFIXMATCH | 98 SUBSTRINGMATCH | 99 '=' | 100 INCLUDES | 101 DASHMATCH ] S* [ IDENT | STRING ] S* 102 ]? ']' 103 ; 104 105 pseudo 106 /* '::' starts a pseudo-element, ':' a pseudo-class */ 107 /* Exceptions: :first-line, :first-letter, :before and :after. */ 108 /* Note that pseudo-elements are restricted to one per selector and */ 109 /* occur only in the last simple_selector_sequence. */ 110 : ':' ':'? [ IDENT | functional_pseudo ] 111 ; 112 113 functional_pseudo 114 : FUNCTION S* expression ')' 115 ; 116 117 expression 118 /* In CSS3, the expressions are identifiers, strings, */ 119 /* or of the form "an+b" */ 120 : [ [ PLUS | '-' | DIMENSION | NUMBER | STRING | IDENT ] S* ]+ 121 ; 122 123 negation 124 : NOT S* negation_arg S* ')' 125 ; 126 127 negation_arg 128 : type_selector | universal | HASH | class | attrib | pseudo 129 ; 130 131 """
132 - def __init__(self, selectorText=None, parentList=None, 133 readonly=False):
134 """ 135 :Parameters: 136 selectorText 137 initial value of this selector 138 parentList 139 a SelectorList 140 readonly 141 default to False 142 """ 143 super(Selector, self).__init__() 144 145 self.__namespaces = _SimpleNamespaces() 146 self._element = None 147 self._parent = parentList 148 self._specificity = (0, 0, 0, 0) 149 150 if selectorText: 151 self.selectorText = selectorText 152 153 self._readonly = readonly
154
155 - def __getNamespaces(self):
156 "uses own namespaces if not attached to a sheet, else the sheet's ones" 157 try: 158 return self._parent.parentRule.parentStyleSheet.namespaces 159 except AttributeError: 160 return self.__namespaces
161 162 _namespaces = property(__getNamespaces, doc="""if this Selector is attached 163 to a CSSStyleSheet the namespaces of that sheet are mirrored here. 164 While the Selector (or parent SelectorList or parentRule(s) of that are 165 not attached a own dict of {prefix: namespaceURI} is used.""") 166 167 168 element = property(lambda self: self._element, 169 doc=u"Effective element target of this selector.") 170 171 parentList = property(lambda self: self._parent, 172 doc="(DOM) The SelectorList that contains this Selector or\ 173 None if this Selector is not attached to a SelectorList.") 174
175 - def _getSelectorText(self):
176 """ 177 returns serialized format 178 """ 179 return cssutils.ser.do_css_Selector(self)
180
181 - def _setSelectorText(self, selectorText):
182 """ 183 :param selectorText: 184 parsable string or a tuple of (selectorText, dict-of-namespaces). 185 Given namespaces are ignored if this object is attached to a 186 CSSStyleSheet! 187 188 :Exceptions: 189 - `NAMESPACE_ERR`: (self) 190 Raised if the specified selector uses an unknown namespace 191 prefix. 192 - `SYNTAX_ERR`: (self) 193 Raised if the specified CSS string value has a syntax error 194 and is unparsable. 195 - `NO_MODIFICATION_ALLOWED_ERR`: (self) 196 Raised if this rule is readonly. 197 """ 198 self._checkReadonly() 199 200 # might be (selectorText, namespaces) 201 selectorText, namespaces = self._splitNamespacesOff(selectorText) 202 try: 203 # uses parent stylesheets namespaces if available, otherwise given ones 204 namespaces = self.parentList.parentRule.parentStyleSheet.namespaces 205 except AttributeError: 206 pass 207 tokenizer = self._tokenize2(selectorText) 208 if not tokenizer: 209 self._log.error(u'Selector: No selectorText given.') 210 else: 211 # prepare tokenlist: 212 # "*" -> type "universal" 213 # "*"|IDENT + "|" -> combined to "namespace_prefix" 214 # "|" -> type "namespace_prefix" 215 # "." + IDENT -> combined to "class" 216 # ":" + IDENT, ":" + FUNCTION -> pseudo-class 217 # FUNCTION "not(" -> negation 218 # "::" + IDENT, "::" + FUNCTION -> pseudo-element 219 tokens = [] 220 for t in tokenizer: 221 typ, val, lin, col = t 222 if val == u':' and tokens and\ 223 self._tokenvalue(tokens[-1]) == ':': 224 # combine ":" and ":" 225 tokens[-1] = (typ, u'::', lin, col) 226 227 elif typ == 'IDENT' and tokens\ 228 and self._tokenvalue(tokens[-1]) == u'.': 229 # class: combine to .IDENT 230 tokens[-1] = ('class', u'.'+val, lin, col) 231 elif typ == 'IDENT' and tokens and \ 232 self._tokenvalue(tokens[-1]).startswith(u':') and\ 233 not self._tokenvalue(tokens[-1]).endswith(u'('): 234 # pseudo-X: combine to :IDENT or ::IDENT but not ":a(" + "b" 235 if self._tokenvalue(tokens[-1]).startswith(u'::'): 236 t = 'pseudo-element' 237 else: 238 t = 'pseudo-class' 239 tokens[-1] = (t, self._tokenvalue(tokens[-1])+val, lin, col) 240 241 elif typ == 'FUNCTION' and val == u'not(' and tokens and \ 242 u':' == self._tokenvalue(tokens[-1]): 243 tokens[-1] = ('negation', u':' + val, lin, tokens[-1][3]) 244 elif typ == 'FUNCTION' and tokens\ 245 and self._tokenvalue(tokens[-1]).startswith(u':'): 246 # pseudo-X: combine to :FUNCTION( or ::FUNCTION( 247 if self._tokenvalue(tokens[-1]).startswith(u'::'): 248 t = 'pseudo-element' 249 else: 250 t = 'pseudo-class' 251 tokens[-1] = (t, self._tokenvalue(tokens[-1])+val, lin, col) 252 253 elif val == u'*' and tokens and\ 254 self._type(tokens[-1]) == 'namespace_prefix' and\ 255 self._tokenvalue(tokens[-1]).endswith(u'|'): 256 # combine prefix|* 257 tokens[-1] = ('universal', self._tokenvalue(tokens[-1])+val, 258 lin, col) 259 elif val == u'*': 260 # universal: "*" 261 tokens.append(('universal', val, lin, col)) 262 263 elif val == u'|' and tokens and\ 264 self._type(tokens[-1]) in (self._prods.IDENT, 'universal') and\ 265 self._tokenvalue(tokens[-1]).find(u'|') == -1: 266 # namespace_prefix: "IDENT|" or "*|" 267 tokens[-1] = ('namespace_prefix', 268 self._tokenvalue(tokens[-1])+u'|', lin, col) 269 elif val == u'|': 270 # namespace_prefix: "|" 271 tokens.append(('namespace_prefix', val, lin, col)) 272 273 else: 274 tokens.append(t) 275 276 # TODO: back to generator but not elegant at all! 277 tokenizer = (t for t in tokens) 278 279 # for closures: must be a mutable 280 new = {'context': [''], # stack of: 'attrib', 'negation', 'pseudo' 281 'element': None, 282 '_PREFIX': None, 283 'specificity': [0, 0, 0, 0], # mutable, finally a tuple! 284 'wellformed': True 285 } 286 # used for equality checks and setting of a space combinator 287 S = u' ' 288 289 def append(seq, val, typ=None, token=None): 290 """ 291 appends to seq 292 293 namespace_prefix, IDENT will be combined to a tuple 294 (prefix, name) where prefix might be None, the empty string 295 or a prefix. 296 297 Saved are also: 298 - specificity definition: style, id, class/att, type 299 - element: the element this Selector is for 300 """ 301 context = new['context'][-1] 302 if token: 303 line, col = token[2], token[3] 304 else: 305 line, col = None, None 306 307 if typ == '_PREFIX': 308 # SPECIAL TYPE: save prefix for combination with next 309 new['_PREFIX'] = val[:-1] 310 # handle next time 311 return 312 313 if new['_PREFIX'] is not None: 314 # as saved from before and reset to None 315 prefix, new['_PREFIX'] = new['_PREFIX'], None 316 elif typ == 'universal' and '|' in val: 317 # val == *|* or prefix|* 318 prefix, val = val.split('|') 319 else: 320 prefix = None 321 322 # namespace 323 if (typ.endswith('-selector') or typ == 'universal') and not ( 324 'attribute-selector' == typ and not prefix): 325 # att **IS NOT** in default ns 326 if prefix == u'*': 327 # *|name: in ANY_NS 328 namespaceURI = cssutils._ANYNS 329 elif prefix is None: 330 # e or *: default namespace with prefix u'' or local-name() 331 namespaceURI = namespaces.get(u'', None) 332 elif prefix == u'': 333 # |name or |*: in no (or the empty) namespace 334 namespaceURI = u'' 335 else: 336 # explicit namespace prefix 337 try: 338 namespaceURI = namespaces[prefix] 339 except KeyError: 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 682 else: 683 new['wellformed'] = False 684 self._log.error( 685 u'Selector: Unexpected CHAR.', token=token) 686 return expected 687 688 def _negation(expected, seq, token, tokenizer=None): 689 # not( 690 context = new['context'][-1] 691 val = self._tokenvalue(token, normalize=True) 692 if 'negation' in expected: 693 new['context'].append('negation') 694 append(seq, val, 'negation-start', token=token) 695 return negation_arg 696 else: 697 new['wellformed'] = False 698 self._log.error( 699 u'Selector: Unexpected negation.', token=token) 700 return expected 701 702 # expected: only|not or mediatype, mediatype, feature, and 703 newseq = self._tempSeq() 704 705 wellformed, expected = self._parse(expected=simple_selector_sequence, 706 seq=newseq, tokenizer=tokenizer, 707 productions={'CHAR': _char, 708 'class': _class, 709 'HASH': _hash, 710 'STRING': _string, 711 'IDENT': _ident, 712 'namespace_prefix': _namespace_prefix, 713 'negation': _negation, 714 'pseudo-class': _pseudo, 715 'pseudo-element': _pseudo, 716 'universal': _universal, 717 # pseudo 718 'NUMBER': _expression, 719 'DIMENSION': _expression, 720 # attribute 721 'PREFIXMATCH': _attcombinator, 722 'SUFFIXMATCH': _attcombinator, 723 'SUBSTRINGMATCH': _attcombinator, 724 'DASHMATCH': _attcombinator, 725 'INCLUDES': _attcombinator, 726 727 'S': _S, 728 'COMMENT': _COMMENT}) 729 wellformed = wellformed and new['wellformed'] 730 731 # post condition 732 if len(new['context']) > 1: 733 wellformed = False 734 self._log.error(u'Selector: Incomplete selector: %s' % 735 self._valuestr(selectorText)) 736 737 if expected == 'element_name': 738 wellformed = False 739 self._log.error(u'Selector: No element name found: %s' % 740 self._valuestr(selectorText)) 741 742 if expected == simple_selector_sequence: 743 wellformed = False 744 self._log.error(u'Selector: Cannot end with combinator: %s' % 745 self._valuestr(selectorText)) 746 747 if newseq and hasattr(newseq[-1].value, 'strip') and \ 748 newseq[-1].value.strip() == u'': 749 del newseq[-1] 750 751 # set 752 if wellformed: 753 self.__namespaces = namespaces 754 self._element = new['element'] 755 self._specificity = tuple(new['specificity']) 756 self._setSeq(newseq) 757 # filter that only used ones are kept 758 self.__namespaces = self._getUsedNamespaces() 759 760 selectorText = property(_getSelectorText, _setSelectorText, 761 doc="(DOM) The parsable textual representation of the selector.") 762 763 764 specificity = property(lambda self: self._specificity, 765 doc="Specificity of this selector (READONLY).") 766 767 wellformed = property(lambda self: bool(len(self.seq))) 768
769 - def __repr__(self):
770 if self.__getNamespaces(): 771 st = (self.selectorText, self._getUsedNamespaces()) 772 else: 773 st = self.selectorText 774 return u"cssutils.css.%s(selectorText=%r)" % ( 775 self.__class__.__name__, st)
776
777 - def __str__(self):
778 return u"<cssutils.css.%s object selectorText=%r specificity=%r _namespaces=%r at 0x%x>" % ( 779 self.__class__.__name__, self.selectorText, self.specificity, 780 self._getUsedNamespaces(), id(self))
781
782 - def _getUsedUris(self):
783 "returns list of actually used URIs in this Selector" 784 uris = set() 785 for item in self.seq: 786 type_, val = item.type, item.value 787 if type_.endswith(u'-selector') or type_ == u'universal' and \ 788 type(val) == tuple and val[0] not in (None, u'*'): 789 uris.add(val[0]) 790 return uris
791
792 - def _getUsedNamespaces(self):
793 "returns actually used namespaces only" 794 useduris = self._getUsedUris() 795 namespaces = _SimpleNamespaces() 796 for p, uri in self._namespaces.items(): 797 if uri in useduris: 798 namespaces[p] = uri 799 return namespaces
800