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