Package cssutils :: Package stylesheets :: Module medialist
[hide private]
[frames] | no frames]

Source Code for Module cssutils.stylesheets.medialist

  1  """ 
  2  MediaList implements DOM Level 2 Style Sheets MediaList. 
  3   
  4  TODO: 
  5      - delete: maybe if deleting from all, replace *all* with all others? 
  6      - is unknown media an exception? 
  7  """ 
  8  __all__ = ['MediaList'] 
  9  __docformat__ = 'restructuredtext' 
 10  __version__ = '$Id: medialist.py 1402 2008-07-29 21:35:23Z cthedot $' 
 11   
 12  import xml.dom 
 13  import cssutils 
 14  from cssutils.css import csscomment 
 15  from mediaquery import MediaQuery 
 16   
17 -class MediaList(cssutils.util.Base, cssutils.util.ListSeq):
18 """ 19 Provides the abstraction of an ordered collection of media, 20 without defining or constraining how this collection is 21 implemented. 22 23 A media is always an instance of MediaQuery. 24 25 An empty list is the same as a list that contains the medium "all". 26 27 Properties 28 ========== 29 length: 30 The number of MediaQuery objects in the list. 31 mediaText: of type DOMString 32 The parsable textual representation of this MediaList 33 self: a list (cssutils) 34 All MediaQueries in this MediaList 35 wellformed: 36 if this list is wellformed 37 38 Format 39 ====== 40 :: 41 42 medium [ COMMA S* medium ]* 43 44 New:: 45 46 <media_query> [, <media_query> ]* 47 """
48 - def __init__(self, mediaText=None, readonly=False):
49 """ 50 mediaText 51 unicodestring of parsable comma separared media 52 or a list of media 53 """ 54 super(MediaList, self).__init__() 55 self._wellformed = False 56 57 if isinstance(mediaText, list): 58 mediaText = u','.join(mediaText) 59 60 if mediaText: 61 self.mediaText = mediaText 62 63 self._readonly = readonly
64 65 length = property(lambda self: len(self), 66 doc="(DOM readonly) The number of media in the list.") 67
68 - def _getMediaText(self):
69 """ 70 returns serialized property mediaText 71 """ 72 return cssutils.ser.do_stylesheets_medialist(self)
73
74 - def _setMediaText(self, mediaText):
75 """ 76 mediaText 77 simple value or comma-separated list of media 78 79 DOMException 80 81 - SYNTAX_ERR: (MediaQuery) 82 Raised if the specified string value has a syntax error and is 83 unparsable. 84 - NO_MODIFICATION_ALLOWED_ERR: (self) 85 Raised if this media list is readonly. 86 """ 87 self._checkReadonly() 88 wellformed = True 89 tokenizer = self._tokenize2(mediaText) 90 newseq = [] 91 92 expected = None 93 while True: 94 # find all upto and including next ",", EOF or nothing 95 mqtokens = self._tokensupto2(tokenizer, listseponly=True) 96 if mqtokens: 97 if self._tokenvalue(mqtokens[-1]) == ',': 98 expected = mqtokens.pop() 99 else: 100 expected = None 101 102 mq = MediaQuery(mqtokens) 103 if mq.wellformed: 104 newseq.append(mq) 105 else: 106 wellformed = False 107 self._log.error(u'MediaList: Invalid MediaQuery: %s' % 108 self._valuestr(mqtokens)) 109 else: 110 break 111 112 # post condition 113 if expected: 114 wellformed = False 115 self._log.error(u'MediaList: Cannot end with ",".') 116 117 if wellformed: 118 del self[:] 119 for mq in newseq: 120 self.appendMedium(mq) 121 self._wellformed = True
122 123 mediaText = property(_getMediaText, _setMediaText, 124 doc="""(DOM) The parsable textual representation of the media list. 125 This is a comma-separated list of media.""") 126 127 wellformed = property(lambda self: self._wellformed) 128
129 - def __prepareset(self, newMedium):
130 # used by appendSelector and __setitem__ 131 self._checkReadonly() 132 133 if not isinstance(newMedium, MediaQuery): 134 newMedium = MediaQuery(newMedium) 135 136 if newMedium.wellformed: 137 return newMedium
138
139 - def __setitem__(self, index, newMedium):
140 """ 141 overwrites ListSeq.__setitem__ 142 143 Any duplicate items are **not** removed. 144 """ 145 newMedium = self.__prepareset(newMedium) 146 if newMedium: 147 self.seq[index] = newMedium
148 # TODO: remove duplicates? 149
150 - def appendMedium(self, newMedium):
151 """ 152 (DOM) 153 Adds the medium newMedium to the end of the list. If the newMedium 154 is already used, it is first removed. 155 156 newMedium 157 a string or a MediaQuery object 158 159 returns if newMedium is wellformed 160 161 DOMException 162 163 - INVALID_CHARACTER_ERR: (self) 164 If the medium contains characters that are invalid in the 165 underlying style language. 166 - INVALID_MODIFICATION_ERR (self) 167 If mediaText is "all" and a new medium is tried to be added. 168 Exception is "handheld" which is set in any case (Opera does handle 169 "all, handheld" special, this special case might be removed in the 170 future). 171 - NO_MODIFICATION_ALLOWED_ERR: (self) 172 Raised if this list is readonly. 173 """ 174 newMedium = self.__prepareset(newMedium) 175 176 if newMedium: 177 mts = [self._normalize(mq.mediaType) for mq in self] 178 newmt = self._normalize(newMedium.mediaType) 179 180 if newmt in mts: 181 self.deleteMedium(newmt) 182 self.seq.append(newMedium) 183 elif u'all' == newmt: 184 # remove all except handheld (Opera) 185 h = None 186 for mq in self: 187 if mq.mediaType == u'handheld': 188 h = mq 189 del self[:] 190 self.seq.append(newMedium) 191 if h: 192 self.append(h) 193 elif u'all' in mts: 194 if u'handheld' == newmt: 195 self.seq.append(newMedium) 196 self._log.warn(u'MediaList: Already specified "all" but still setting new medium: %r' % 197 newMedium, error=xml.dom.InvalidModificationErr, neverraise=True) 198 else: 199 self._log.warn(u'MediaList: Ignoring new medium %r as already specified "all" (set ``mediaText`` instead).' % 200 newMedium, error=xml.dom.InvalidModificationErr) 201 xml.com 202 else: 203 self.seq.append(newMedium) 204 205 return True 206 207 else: 208 return False
209
210 - def append(self, newMedium):
211 "overwrites ListSeq.append" 212 self.appendMedium(newMedium)
213
214 - def deleteMedium(self, oldMedium):
215 """ 216 (DOM) 217 Deletes the medium indicated by oldMedium from the list. 218 219 DOMException 220 221 - NO_MODIFICATION_ALLOWED_ERR: (self) 222 Raised if this list is readonly. 223 - NOT_FOUND_ERR: (self) 224 Raised if oldMedium is not in the list. 225 """ 226 self._checkReadonly() 227 oldMedium = self._normalize(oldMedium) 228 229 for i, mq in enumerate(self): 230 if self._normalize(mq.mediaType) == oldMedium: 231 del self[i] 232 break 233 else: 234 self._log.error(u'"%s" not in this MediaList' % oldMedium, 235 error=xml.dom.NotFoundErr)
236 # raise xml.dom.NotFoundErr( 237 # u'"%s" not in this MediaList' % oldMedium) 238
239 - def item(self, index):
240 """ 241 (DOM) 242 Returns the mediaType of the index'th element in the list. 243 If index is greater than or equal to the number of media in the 244 list, returns None. 245 """ 246 try: 247 return self[index].mediaType 248 except IndexError: 249 return None
250
251 - def __repr__(self):
252 return "cssutils.stylesheets.%s(mediaText=%r)" % ( 253 self.__class__.__name__, self.mediaText)
254
255 - def __str__(self):
256 return "<cssutils.stylesheets.%s object mediaText=%r at 0x%x>" % ( 257 self.__class__.__name__, self.mediaText, id(self))
258