Package qm :: Package external :: Package DocumentTemplate :: Module DT_InSV
[hide private]
[frames] | no frames]

Source Code for Module qm.external.DocumentTemplate.DT_InSV

  1  ############################################################################## 
  2  # 
  3  # Copyright (c) 2002 Zope Corporation and Contributors. All Rights Reserved. 
  4  # 
  5  # This software is subject to the provisions of the Zope Public License, 
  6  # Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution. 
  7  # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED 
  8  # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
  9  # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS 
 10  # FOR A PARTICULAR PURPOSE 
 11  # 
 12  ############################################################################## 
 13  __doc__='''Sequence variables support 
 14   
 15   
 16  $Id: DT_InSV.py 1069 2008-11-13 21:55:43Z stefan $''' 
 17  __version__='$Revision: 1069 $'[11:-2] 
 18   
 19  from string import lower, rfind, split, join 
 20  from math import sqrt 
 21  TupleType=type(()) 
 22  try: 
 23      import Missing 
 24      mv=Missing.Value 
 25  except: mv=None 
 26   
 27   
28 -class sequence_variables:
29
30 - def __init__(self,items=None,query_string='',start_name_re=None):
31 32 self.items=items 33 self.query_string=query_string 34 self.start_name_re=start_name_re 35 36 self.data=data={ 37 'previous-sequence': 0, 38 'next-sequence': 0, 39 'sequence-start': 1, 40 'sequence-end': 0, 41 }
42 43
44 - def __len__(self): return 1
45 - def number(self,index): return index+1
46 - def even(self,index): return index%2 == 0
47 - def odd(self,index): return index%2
48 - def letter(self,index): return chr(ord('a')+index)
49 - def Letter(self,index): return chr(ord('A')+index)
50 - def key(self,index): return self.items[index][0]
51 - def item(self,index, tt=type(())):
52 i=self.items[index] 53 if type(i) is tt and len(i)==2: return i[1] 54 return i
55
56 - def roman(self,index): return lower(self.Roman(index))
57
58 - def Roman(self,num):
59 # Force number to be an integer value 60 num = int(num)+1 61 62 # Initialize roman as an empty string 63 roman = '' 64 65 while num >= 1000: 66 num = num - 1000 67 roman = '%sM' % roman 68 69 while num >= 500: 70 num = num - 500 71 roman = '%sD' % roman 72 73 while num >= 100: 74 num = num - 100 75 roman = '%sC' % roman 76 77 while num >= 50: 78 num = num - 50 79 roman = '%sL' % roman 80 81 while num >= 10: 82 num = num - 10 83 roman = '%sX' % roman 84 85 while num >= 5: 86 num = num - 5 87 roman = '%sV' % roman 88 89 while num < 5 and num >= 1: 90 num = num - 1 91 roman = '%sI' % roman 92 93 # Replaces special cases in Roman Numerals 94 95 roman = sub('DCCCC', 'CM', roman) 96 roman = sub('CCCC', 'CD', roman) 97 roman = sub('LXXXX', 'XC', roman) 98 roman = sub('XXXX', 'XL', roman) 99 roman = sub('VIIII', 'IX', roman) 100 roman = sub('IIII', 'IV', roman) 101 102 return roman
103 104
105 - def value(self,index,name):
106 data=self.data 107 item=self.items[index] 108 if type(item)==TupleType and len(item)==2: 109 item=item[1] 110 if data['mapping']: return item[name] 111 return getattr(item,name)
112
113 - def first(self,name,key=''):
114 data=self.data 115 if data['sequence-start']: return 1 116 index=data['sequence-index'] 117 return self.value(index,name) != self.value(index-1,name)
118
119 - def last(self,name,key=''):
120 data=self.data 121 if data['sequence-end']: return 1 122 index=data['sequence-index'] 123 return self.value(index,name) != self.value(index+1,name)
124
125 - def length(self, ignored):
126 l=self.data['sequence-length']=len(self.items) 127 return l
128
129 - def query(self, *ignored):
130 131 if self.start_name_re is None: raise KeyError, 'sequence-query' 132 query_string=self.query_string 133 while query_string and query_string[:1] in '?&': 134 query_string=query_string[1:] 135 while query_string[-1:] == '&': 136 query_string=query_string[:-1] 137 if query_string: 138 query_string='&%s&' % query_string 139 re=self.start_name_re 140 l=re.search_group(query_string, (0,)) 141 if l: 142 v=l[1] 143 l=l[0] 144 query_string=(query_string[:l]+ 145 query_string[l+len(v)-1:]) 146 query_string='?'+query_string[1:] 147 else: query_string='?' 148 self.data['sequence-query']=query_string 149 return query_string
150 151 152 statistic_names=( 153 'total', 'count', 'min', 'max', 'median', 'mean', 154 'variance', 'variance-n','standard-deviation', 'standard-deviation-n', 155 ) 156
157 - def statistics(self,name,key):
158 items=self.items 159 data=self.data 160 mapping=data['mapping'] 161 count=sum=sumsq=0 162 min=max=None 163 scount=smin=smax=None 164 values=[] 165 svalues=[] 166 for item in items: 167 try: 168 if mapping: item=item[name] 169 else: item=getattr(item,name) 170 try: 171 if item is mv: 172 item = None 173 if type(item)==type(1): 174 s=item*long(item) 175 else: 176 s=item*item 177 sum=sum+item 178 sumsq=sumsq+s 179 values.append(item) 180 if min is None: 181 min=max=item 182 else: 183 if item < min: min=item 184 if item > max: max=item 185 except: 186 if item is not None and item is not mv: 187 if smin is None: smin=smax=item 188 else: 189 if item < smin: smin=item 190 if item > smax: smax=item 191 svalues.append(item) 192 except: pass 193 194 # Initialize all stats to empty strings: 195 for stat in self.statistic_names: data['%s-%s' % (stat,name)]='' 196 197 count=len(values) 198 try: # Numeric statistics 199 n=float(count) 200 mean=sum/n 201 sumsq=sumsq/n - mean*mean 202 data['mean-%s' % name]=mean 203 data['total-%s' % name]=sum 204 data['variance-n-%s' % name]=sumsq 205 data['standard-deviation-n-%s' % name]=sqrt(sumsq) 206 if count > 1: 207 sumsq=sumsq*n/(n-1) 208 data['variance-%s' % name]=sumsq 209 data['standard-deviation-%s' % name]=sqrt(sumsq) 210 else: 211 data['variance-%s' % name]='' 212 data['standard-deviation-%s' % name]='' 213 except: 214 if min is None: min,max,values=smin,smax,svalues 215 else: 216 if smin < min: min=smin 217 if smax > max: max=smax 218 values=values+svalues 219 count=len(values) 220 221 data['count-%s' % name]=count 222 # data['_values']=values 223 if min is not None: 224 data['min-%s' % name]=min 225 data['max-%s' % name]=max 226 values.sort() 227 if count==1: 228 data['median-%s' % name]=min 229 else: 230 n=count+1 231 if n/2*2==n: data['median-%s' % name]=values[n/2-1] 232 else: 233 n=n/2 234 try: data['median-%s' % name]=(values[n]+values[n-1])/2 235 except: 236 try: data['median-%s' % name]=( 237 "between %s and %s" % (values[n],values[n-1])) 238 except: pass 239 240 return data[key]
241
242 - def next_batches(self, suffix='batches',key=''):
243 if suffix != 'batches': raise KeyError, key 244 data=self.data 245 sequence=self.items 246 try: 247 if not data['next-sequence']: return () 248 sz=data['sequence-step-size'] 249 start=data['sequence-step-start'] 250 end=data['sequence-step-end'] 251 l=len(sequence) 252 orphan=data['sequence-step-orphan'] 253 overlap=data['sequence-step-overlap'] 254 except: AttributeError, 'next-batches' 255 r=[] 256 while end < l: 257 start,end,spam=opt(end+1-overlap,0,sz,orphan,sequence) 258 v=sequence_variables(self.items, 259 self.query_string,self.start_name_re) 260 d=v.data 261 d['batch-start-index']=start-1 262 d['batch-end-index']=end-1 263 d['batch-size']=end+1-start 264 d['mapping']=data['mapping'] 265 r.append(v) 266 data['next-batches']=r 267 return r
268
269 - def previous_batches(self, suffix='batches',key=''):
270 if suffix != 'batches': raise KeyError, key 271 data=self.data 272 sequence=self.items 273 try: 274 if not data['previous-sequence']: return () 275 sz=data['sequence-step-size'] 276 start=data['sequence-step-start'] 277 end=data['sequence-step-end'] 278 l=len(sequence) 279 orphan=data['sequence-step-orphan'] 280 overlap=data['sequence-step-overlap'] 281 except: AttributeError, 'previous-batches' 282 r=[] 283 while start > 1: 284 start,end,spam=opt(0,start-1+overlap,sz,orphan,sequence) 285 v=sequence_variables(self.items, 286 self.query_string,self.start_name_re) 287 d=v.data 288 d['batch-start-index']=start-1 289 d['batch-end-index']=end-1 290 d['batch-size']=end+1-start 291 d['mapping']=data['mapping'] 292 r.append(v) 293 r.reverse() 294 data['previous-batches']=r 295 return r
296 297 298 special_prefixes={ 299 'first': first, 300 'last': last, 301 'previous': previous_batches, 302 'next': next_batches, 303 # These two are for backward compatability with a missfeature: 304 'sequence-index': lambda self, suffix, key: self['sequence-'+suffix], 305 'sequence-index-is': lambda self, suffix, key: self['sequence-'+suffix], 306 } 307 for n in statistic_names: special_prefixes[n]=statistics 308
309 - def __getitem__(self,key, 310 special_prefixes=special_prefixes, 311 special_prefix=special_prefixes.has_key 312 ):
313 data=self.data 314 if data.has_key(key): return data[key] 315 316 l=rfind(key,'-') 317 if l < 0: raise KeyError, key 318 319 suffix=key[l+1:] 320 prefix=key[:l] 321 322 if hasattr(self, suffix): 323 try: v=data[prefix+'-index'] 324 except: pass 325 else: return getattr(self,suffix)(v) 326 327 if special_prefix(prefix): 328 return special_prefixes[prefix](self, suffix, key) 329 330 if prefix[-4:]=='-var': 331 prefix=prefix[:-4] 332 try: return self.value(data[prefix+'-index'],suffix) 333 except: pass 334 335 if key=='sequence-query': return self.query() 336 337 raise KeyError, key
338 339 340 341
342 -def sub(s1, s2, src):
343 return join(split(src, s1), s2)
344
345 -def opt(start,end,size,orphan,sequence):
346 if size < 1: 347 if start > 0 and end > 0 and end >= start: 348 size=end+1-start 349 else: size=7 350 351 if start > 0: 352 353 try: sequence[start-1] 354 except: start=len(sequence) 355 # if start > l: start=l 356 357 if end > 0: 358 if end < start: end=start 359 else: 360 end=start+size-1 361 try: sequence[end+orphan-1] 362 except: end=len(sequence) 363 # if l - end < orphan: end=l 364 elif end > 0: 365 try: sequence[end-1] 366 except: end=len(sequence) 367 # if end > l: end=l 368 start=end+1-size 369 if start - 1 < orphan: start=1 370 else: 371 start=1 372 end=start+size-1 373 try: sequence[end+orphan-1] 374 except: end=len(sequence) 375 # if l - end < orphan: end=l 376 return start,end,size
377