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

Source Code for Module cssutils.css.property

  1  """Property is a single CSS property in a CSSStyleDeclaration 
  2   
  3  Internal use only, may be removed in the future! 
  4  """ 
  5  __all__ = ['Property'] 
  6  __docformat__ = 'restructuredtext' 
  7  __version__ = '$Id: property.py 1116 2008-03-05 13:52:23Z cthedot $' 
  8   
  9  import xml.dom 
 10  import cssutils 
 11  import cssproperties 
 12  from cssvalue import CSSValue 
 13  from cssutils.util import Deprecated 
14 15 -class Property(cssutils.util.Base):
16 """ 17 (cssutils) a CSS property in a StyleDeclaration of a CSSStyleRule 18 19 Properties 20 ========== 21 cssText 22 a parsable textual representation of this property 23 name 24 normalized name of the property, e.g. "color" when name is "c\olor" 25 (since 0.9.5) 26 literalname (since 0.9.5) 27 original name of the property in the source CSS which is not normalized 28 e.g. "C\\OLor" 29 cssValue 30 the relevant CSSValue instance for this property 31 value 32 the string value of the property, same as cssValue.cssText 33 priority 34 of the property (currently only u"important" or None) 35 literalpriority 36 original priority of the property in the source CSS which is not 37 normalized e.g. "IM\portant" 38 seqs 39 combination of a list for seq of name, a CSSValue object, and 40 a list for seq of priority (empty or [!important] currently) 41 valid 42 if this Property is valid 43 wellformed 44 if this Property is syntactically ok 45 46 DEPRECATED normalname (since 0.9.5) 47 normalized name of the property, e.g. "color" when name is "c\olor" 48 49 Format 50 ====== 51 :: 52 53 property = name 54 : IDENT S* 55 ; 56 57 expr = value 58 : term [ operator term ]* 59 ; 60 term 61 : unary_operator? 62 [ NUMBER S* | PERCENTAGE S* | LENGTH S* | EMS S* | EXS S* | ANGLE S* | 63 TIME S* | FREQ S* | function ] 64 | STRING S* | IDENT S* | URI S* | hexcolor 65 ; 66 function 67 : FUNCTION S* expr ')' S* 68 ; 69 /* 70 * There is a constraint on the color that it must 71 * have either 3 or 6 hex-digits (i.e., [0-9a-fA-F]) 72 * after the "#"; e.g., "#000" is OK, but "#abcd" is not. 73 */ 74 hexcolor 75 : HASH S* 76 ; 77 78 prio 79 : IMPORTANT_SYM S* 80 ; 81 82 """
83 - def __init__(self, name=None, value=None, priority=u'', _mediaQuery=False):
84 """ 85 inits property 86 87 name 88 a property name string (will be normalized) 89 value 90 a property value string 91 priority 92 an optional priority string which currently must be u'', 93 u'!important' or u'important' 94 _mediaQuery boolean 95 if True value is optional as used by MediaQuery objects 96 """ 97 super(Property, self).__init__() 98 99 self.seqs = [[], None, []] 100 self.valid = False 101 self.wellformed = False 102 self._mediaQuery = _mediaQuery 103 104 if name: 105 self.name = name 106 else: 107 self._name = u'' 108 self._literalname = u'' 109 self.__normalname = u'' # DEPRECATED 110 111 if value: 112 self.cssValue = value 113 else: 114 self.seqs[1] = CSSValue() 115 116 if priority: 117 self.priority = priority 118 else: 119 self._priority = u'' 120 self._literalpriority = u''
121
122 - def _getCssText(self):
123 """ 124 returns serialized property cssText 125 """ 126 return cssutils.ser.do_Property(self)
127
128 - def _setCssText(self, cssText):
129 """ 130 DOMException on setting 131 132 - NO_MODIFICATION_ALLOWED_ERR: (CSSRule) 133 Raised if the rule is readonly. 134 - SYNTAX_ERR: (self) 135 Raised if the specified CSS string value has a syntax error and 136 is unparsable. 137 """ 138 # check and prepare tokenlists for setting 139 tokenizer = self._tokenize2(cssText) 140 nametokens = self._tokensupto2(tokenizer, propertynameendonly=True) 141 if nametokens: 142 wellformed = True 143 144 valuetokens = self._tokensupto2(tokenizer, 145 propertyvalueendonly=True) 146 prioritytokens = self._tokensupto2(tokenizer, 147 propertypriorityendonly=True) 148 149 if self._mediaQuery and not valuetokens: 150 # MediaQuery may consist of name only 151 self.name = nametokens 152 self.cssValue = None 153 self.priority = None 154 return 155 156 # remove colon from nametokens 157 colontoken = nametokens.pop() 158 if self._tokenvalue(colontoken) != u':': 159 wellformed = False 160 self._log.error(u'Property: No ":" after name found: %r' % 161 self._valuestr(cssText), colontoken) 162 elif not nametokens: 163 wellformed = False 164 self._log.error(u'Property: No property name found: %r.' % 165 self._valuestr(cssText), colontoken) 166 167 if valuetokens: 168 if self._tokenvalue(valuetokens[-1]) == u'!': 169 # priority given, move "!" to prioritytokens 170 prioritytokens.insert(0, valuetokens.pop(-1)) 171 else: 172 wellformed = False 173 self._log.error(u'Property: No property value found: %r.' % 174 self._valuestr(cssText), colontoken) 175 176 if wellformed: 177 self.wellformed = True 178 self.name = nametokens 179 self.cssValue = valuetokens 180 self.priority = prioritytokens 181 182 else: 183 self._log.error(u'Property: No property name found: %r.' % 184 self._valuestr(cssText))
185 186 cssText = property(fget=_getCssText, fset=_setCssText, 187 doc="A parsable textual representation.") 188
189 - def _setName(self, name):
190 """ 191 DOMException on setting 192 193 - SYNTAX_ERR: (self) 194 Raised if the specified name has a syntax error and is 195 unparsable. 196 """ 197 # for closures: must be a mutable 198 new = {'literalname': None, 199 'wellformed': True} 200 201 def _ident(expected, seq, token, tokenizer=None): 202 # name 203 if 'name' == expected: 204 new['literalname'] = self._tokenvalue(token).lower() 205 seq.append(new['literalname']) 206 return 'EOF' 207 else: 208 new['wellformed'] = False 209 self._log.error(u'Property: Unexpected ident.', token) 210 return expected
211 212 newseq = [] 213 wellformed, expected = self._parse(expected='name', 214 seq=newseq, 215 tokenizer=self._tokenize2(name), 216 productions={'IDENT': _ident}) 217 wellformed = wellformed and new['wellformed'] 218 219 # post conditions 220 # define a token for error logging 221 if isinstance(name, list): 222 token = name[0] 223 else: 224 token = None 225 226 if not new['literalname']: 227 wellformed = False 228 self._log.error(u'Property: No name found: %r' % 229 self._valuestr(name), token=token) 230 231 if wellformed: 232 self.wellformed = True 233 self._literalname = new['literalname'] 234 self._name = self._normalize(self._literalname) 235 self.__normalname = self._name # DEPRECATED 236 self.seqs[0] = newseq 237 238 # validate 239 if self._name not in cssproperties.cssvalues: 240 self.valid = False 241 tokenizer=self._tokenize2(name) 242 self._log.info(u'Property: No CSS2 Property: %r.' % 243 new['literalname'], token=token, neverraise=True) 244 else: 245 self.valid = True 246 if self.cssValue: 247 self.cssValue._propertyName = self._name 248 self.valid = self.cssValue.valid 249 else: 250 self.wellformed = False
251 252 name = property(lambda self: self._name, _setName, 253 doc="Name of this property") 254 255 literalname = property(lambda self: self._literalname, 256 doc="Readonly literal (not normalized) name of this property") 257
258 - def _getCSSValue(self):
259 return self.seqs[1]
260
261 - def _setCSSValue(self, cssText):
262 """ 263 see css.CSSValue 264 265 DOMException on setting? 266 267 - SYNTAX_ERR: (self) 268 Raised if the specified CSS string value has a syntax error 269 (according to the attached property) or is unparsable. 270 - TODO: INVALID_MODIFICATION_ERR: 271 Raised if the specified CSS string value represents a different 272 type of values than the values allowed by the CSS property. 273 """ 274 if self._mediaQuery and not cssText: 275 self.seqs[1] = CSSValue() 276 else: 277 if not self.seqs[1]: 278 self.seqs[1] = CSSValue() 279 280 cssvalue = self.seqs[1] 281 cssvalue._propertyName = self.name 282 cssvalue.cssText = cssText 283 if cssvalue._value and cssvalue.wellformed: 284 self.seqs[1] = cssvalue 285 self.valid = self.valid and cssvalue.valid 286 self.wellformed = self.wellformed and cssvalue.wellformed
287 288 cssValue = property(_getCSSValue, _setCSSValue, 289 doc="(cssutils) CSSValue object of this property") 290
291 - def _getValue(self):
292 if self.cssValue: 293 return self.cssValue._value 294 else: 295 return u''
296
297 - def _setValue(self, value):
298 self.cssValue.cssText = value 299 self.valid = self.valid and self.cssValue.valid 300 self.wellformed = self.wellformed and self.cssValue.wellformed
301 302 value = property(_getValue, _setValue, 303 doc="The textual value of this Properties cssValue.") 304
305 - def _setPriority(self, priority):
306 """ 307 priority 308 a string, currently either u'', u'!important' or u'important' 309 310 Format 311 ====== 312 :: 313 314 prio 315 : IMPORTANT_SYM S* 316 ; 317 318 "!"{w}"important" {return IMPORTANT_SYM;} 319 320 DOMException on setting 321 322 - SYNTAX_ERR: (self) 323 Raised if the specified priority has a syntax error and is 324 unparsable. 325 In this case a priority not equal to None, "" or "!{w}important". 326 As CSSOM defines CSSStyleDeclaration.getPropertyPriority resulting in 327 u'important' this value is also allowed to set a Properties priority 328 """ 329 if self._mediaQuery: 330 self._priority = u'' 331 self._literalpriority = u'' 332 if priority: 333 self._log.error(u'Property: No priority in a MediaQuery - ignored.') 334 return 335 336 if isinstance(priority, basestring) and\ 337 u'important' == self._normalize(priority): 338 priority = u'!%s' % priority 339 340 # for closures: must be a mutable 341 new = {'literalpriority': u'', 342 'wellformed': True} 343 344 def _char(expected, seq, token, tokenizer=None): 345 # "!" 346 val = self._tokenvalue(token) 347 if u'!' == expected == val: 348 seq.append(val) 349 return 'important' 350 else: 351 new['wellformed'] = False 352 self._log.error(u'Property: Unexpected char.', token) 353 return expected
354 355 def _ident(expected, seq, token, tokenizer=None): 356 # "important" 357 val = self._tokenvalue(token) 358 normalval = self._tokenvalue(token, normalize=True) 359 if 'important' == expected == normalval: 360 new['literalpriority'] = val 361 seq.append(val) 362 return 'EOF' 363 else: 364 new['wellformed'] = False 365 self._log.error(u'Property: Unexpected ident.', token) 366 return expected 367 368 newseq = [] 369 wellformed, expected = self._parse(expected='!', 370 seq=newseq, 371 tokenizer=self._tokenize2(priority), 372 productions={'CHAR': _char, 373 'IDENT': _ident}) 374 wellformed = wellformed and new['wellformed'] 375 376 # post conditions 377 if priority and not new['literalpriority']: 378 wellformed = False 379 self._log.info(u'Property: Invalid priority: %r.' % 380 self._valuestr(priority)) 381 382 if wellformed: 383 self.wellformed = self.wellformed and wellformed 384 self._literalpriority = new['literalpriority'] 385 self._priority = self._normalize(self.literalpriority) 386 self.seqs[2] = newseq 387 388 # validate 389 if self._priority not in (u'', u'important'): 390 self.valid = False 391 self._log.info(u'Property: No CSS2 priority value: %r.' % 392 self._priority, neverraise=True) 393 394 priority = property(lambda self: self._priority, _setPriority, 395 doc="(cssutils) Priority of this property") 396 397 literalpriority = property(lambda self: self._literalpriority, 398 doc="Readonly literal (not normalized) priority of this property") 399
400 - def __repr__(self):
401 return "cssutils.css.%s(name=%r, value=%r, priority=%r)" % ( 402 self.__class__.__name__, 403 self.literalname, self.cssValue.cssText, self.priority)
404
405 - def __str__(self):
406 return "<%s.%s object name=%r value=%r priority=%r at 0x%x>" % ( 407 self.__class__.__module__, self.__class__.__name__, 408 self.name, self.cssValue.cssText, self.priority, id(self))
409 410 @Deprecated(u'Use property ``name`` instead (since cssutils 0.9.5).')
411 - def _getNormalname(self):
412 return self.__normalname
413 normalname = property(_getNormalname, 414 doc="DEPRECATED since 0.9.5, use name instead") 415