DT_InSV.py
上传用户:gyjinxi
上传日期:2007-01-04
资源大小:159k
文件大小:15k
源码类别:

WEB邮件程序

开发平台:

Python

  1. ##############################################################################
  2. # Zope Public License (ZPL) Version 1.0
  3. # -------------------------------------
  4. # Copyright (c) Digital Creations.  All rights reserved.
  5. # This license has been certified as Open Source(tm).
  6. # Redistribution and use in source and binary forms, with or without
  7. # modification, are permitted provided that the following conditions are
  8. # met:
  9. # 1. Redistributions in source code must retain the above copyright
  10. #    notice, this list of conditions, and the following disclaimer.
  11. # 2. Redistributions in binary form must reproduce the above copyright
  12. #    notice, this list of conditions, and the following disclaimer in
  13. #    the documentation and/or other materials provided with the
  14. #    distribution.
  15. # 3. Digital Creations requests that attribution be given to Zope
  16. #    in any manner possible. Zope includes a "Powered by Zope"
  17. #    button that is installed by default. While it is not a license
  18. #    violation to remove this button, it is requested that the
  19. #    attribution remain. A significant investment has been put
  20. #    into Zope, and this effort will continue if the Zope community
  21. #    continues to grow. This is one way to assure that growth.
  22. # 4. All advertising materials and documentation mentioning
  23. #    features derived from or use of this software must display
  24. #    the following acknowledgement:
  25. #      "This product includes software developed by Digital Creations
  26. #      for use in the Z Object Publishing Environment
  27. #      (http://www.zope.org/)."
  28. #    In the event that the product being advertised includes an
  29. #    intact Zope distribution (with copyright and license included)
  30. #    then this clause is waived.
  31. # 5. Names associated with Zope or Digital Creations must not be used to
  32. #    endorse or promote products derived from this software without
  33. #    prior written permission from Digital Creations.
  34. # 6. Modified redistributions of any form whatsoever must retain
  35. #    the following acknowledgment:
  36. #      "This product includes software developed by Digital Creations
  37. #      for use in the Z Object Publishing Environment
  38. #      (http://www.zope.org/)."
  39. #    Intact (re-)distributions of any official Zope release do not
  40. #    require an external acknowledgement.
  41. # 7. Modifications are encouraged but must be packaged separately as
  42. #    patches to official Zope releases.  Distributions that do not
  43. #    clearly separate the patches from the original work must be clearly
  44. #    labeled as unofficial distributions.  Modifications which do not
  45. #    carry the name Zope may be packaged in any form, as long as they
  46. #    conform to all of the clauses above.
  47. # Disclaimer
  48. #   THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``AS IS'' AND ANY
  49. #   EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  50. #   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  51. #   PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL DIGITAL CREATIONS OR ITS
  52. #   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  53. #   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  54. #   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
  55. #   USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  56. #   ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  57. #   OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  58. #   OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  59. #   SUCH DAMAGE.
  60. # This software consists of contributions made by Digital Creations and
  61. # many individuals on behalf of Digital Creations.  Specific
  62. # attributions are listed in the accompanying credits file.
  63. ##############################################################################
  64. __doc__='''Sequence variables support
  65. $Id: DT_InSV.py,v 1.16 1999/11/02 16:51:32 brian Exp $'''
  66. __version__='$Revision: 1.16 $'[11:-2]
  67. from string import lower, rfind, split, join
  68. from math import sqrt
  69. TupleType=type(())
  70. try:
  71.     import Missing
  72.     mv=Missing.Value
  73. except: mv=None
  74. class sequence_variables:
  75.     def __init__(self,items=None,query_string='',start_name_re=None):
  76.         
  77.         self.items=items
  78.         self.query_string=query_string
  79.         self.start_name_re=start_name_re
  80.         self.data=data={
  81.             'previous-sequence': 0,
  82.             'next-sequence': 0,
  83.             'sequence-start': 1,
  84.             'sequence-end': 0,
  85.             }
  86.     def number(self,index): return index+1
  87.     def even(self,index): return index%2 == 0
  88.     def odd(self,index): return index%2
  89.     def letter(self,index): return chr(ord('a')+index)
  90.     def Letter(self,index): return chr(ord('A')+index)
  91.     def key(self,index):    return self.items[index][0]
  92.     def item(self,index, tt=type(())):
  93.         i=self.items[index]
  94.         if type(i) is tt and len(i)==2: return i[1]
  95.         return i
  96.     def roman(self,index): return lower(self.Roman(index))
  97.     def Roman(self,num):
  98.         # Force number to be an integer value
  99.         num = int(num)+1
  100.         # Initialize roman as an empty string
  101.         roman = ''
  102.         while num >= 1000:
  103.                 num = num - 1000
  104.                 roman = '%sM' % roman
  105.         while num >= 500:
  106.                 num = num - 500
  107.                 roman = '%sD' % roman
  108.         while num >= 100:
  109.                 num = num - 100
  110.                 roman = '%sC' % roman
  111.         while num >= 50:
  112.                 num = num - 50
  113.                 roman = '%sL' % roman
  114.         while num >= 10:
  115.                 num = num - 10
  116.                 roman = '%sX' % roman                 
  117.         while num >= 5:
  118.                 num = num - 5
  119.                 roman = '%sV' % roman
  120.         while num < 5 and num >= 1:
  121.                 num = num - 1
  122.                 roman = '%sI' % roman
  123.         # Replaces special cases in Roman Numerals
  124.         
  125.         roman = sub('DCCCC', 'CM', roman)
  126.         roman = sub('CCCC', 'CD', roman)
  127.         roman = sub('LXXXX', 'XC', roman)
  128.         roman = sub('XXXX', 'XL', roman)
  129.         roman = sub('VIIII', 'IX', roman)
  130.         roman = sub('IIII', 'IV', roman)
  131.         return roman
  132.     def value(self,index,name):
  133.         data=self.data
  134.         item=self.items[index]
  135.         if type(item)==TupleType and len(item)==2:
  136.             item=item[1]
  137.         if data['mapping']: return item[name]
  138.         return getattr(item,name)
  139.     def first(self,name,key=''):
  140.         data=self.data
  141.         if data['sequence-start']: return 1
  142.         index=data['sequence-index']
  143.         return self.value(index,name) != self.value(index-1,name)
  144.     def last(self,name,key=''):
  145.         data=self.data
  146.         if data['sequence-end']: return 1
  147.         index=data['sequence-index']
  148.         return self.value(index,name) != self.value(index+1,name)
  149.     def length(self, ignored):
  150.         l=self.data['sequence-length']=len(self.items)
  151.         return l
  152.     def query(self, *ignored):
  153.         if self.start_name_re is None: raise KeyError, 'sequence-query'
  154.         query_string=self.query_string
  155.         while query_string and query_string[:1] in '?&':
  156.             query_string=query_string[1:]
  157.         while query_string[-1:] == '&':
  158.             query_string=query_string[:-1]
  159.         if query_string:
  160.             query_string='&%s&' % query_string                  
  161.             re=self.start_name_re
  162.             l=re.search_group(query_string, (0,))
  163.             if l:
  164.                 v=l[1]
  165.                 l=l[0]
  166.                 query_string=(query_string[:l]+
  167.                               query_string[l+len(v)-1:])
  168.             query_string='?'+query_string[1:]
  169.         else: query_string='?'
  170.         self.data['sequence-query']=query_string
  171.         return query_string
  172.         
  173.     statistic_names=(
  174.         'total', 'count', 'min', 'max', 'median', 'mean',
  175.         'variance', 'variance-n','standard-deviation', 'standard-deviation-n',
  176.         )
  177.     def statistics(self,name,key):
  178.         items=self.items
  179.         data=self.data
  180.         mapping=data['mapping']
  181.         count=sum=sumsq=0
  182.         min=max=None
  183.         scount=smin=smax=None
  184.         values=[]
  185.         svalues=[]
  186.         for item in items:
  187.             try:
  188.                 if mapping: item=item[name]
  189.                 else: item=getattr(item,name)
  190.                 try:
  191.                     if item is mv:
  192.                         item = None
  193.                     s=item*item
  194.                     sum=sum+item
  195.                     sumsq=sumsq+s
  196.                     values.append(item)
  197.                     if min is None:
  198.                         min=max=item
  199.                     else:
  200.                         if item < min: min=item
  201.                         if item > max: max=item
  202.                 except:
  203.                     if item is not None and item is not mv:
  204.                         if smin is None: smin=smax=item
  205.                         else:
  206.                             if item < smin: smin=item
  207.                             if item > smax: smax=item
  208.                         svalues.append(item)
  209.             except: pass
  210.         # Initialize all stats to empty strings:
  211.         for stat in self.statistic_names: data['%s-%s' % (stat,name)]=''
  212.         count=len(values)
  213.         try: # Numeric statistics
  214.             n=float(count)
  215.             mean=sum/n
  216.             sumsq=sumsq/n - mean*mean
  217.             data['mean-%s' % name]=mean
  218.             data['total-%s' % name]=sum
  219.             data['variance-n-%s' % name]=sumsq
  220.             data['standard-deviation-n-%s' % name]=sqrt(sumsq)
  221.             if count > 1:
  222.                 sumsq=sumsq*n/(n-1)
  223.                 data['variance-%s' % name]=sumsq
  224.                 data['standard-deviation-%s' % name]=sqrt(sumsq)            
  225.             else:
  226.                 data['variance-%s' % name]=''
  227.                 data['standard-deviation-%s' % name]=''
  228.         except:
  229.             if min is None: min,max,values=smin,smax,svalues
  230.             else:
  231.                 if smin < min: min=smin
  232.                 if smax > max: max=smax
  233.                 values=values+svalues
  234.             count=len(values)
  235.         data['count-%s' % name]=count
  236.         # data['_values']=values
  237.         if min is not None:
  238.             data['min-%s' % name]=min
  239.             data['max-%s' % name]=max
  240.             values.sort()
  241.             if count==1:
  242.                 data['median-%s' % name]=min
  243.             else:
  244.                 n=count+1
  245.                 if n/2*2==n: data['median-%s' % name]=values[n/2-1]
  246.                 else:
  247.                     n=n/2
  248.                     try: data['median-%s' % name]=(values[n]+values[n-1])/2
  249.                     except:
  250.                         try: data['median-%s' % name]=(
  251.                             "between %s and %s" % (values[n],values[n-1]))
  252.                         except: pass
  253.         return data[key]
  254.     def next_batches(self, suffix='batches',key=''):
  255.         if suffix != 'batches': raise KeyError, key
  256.         data=self.data
  257.         sequence=self.items
  258.         try:
  259.             if not data['next-sequence']: return ()
  260.             sz=data['sequence-step-size']
  261.             start=data['sequence-step-start']
  262.             end=data['sequence-step-end']
  263.             l=len(sequence)
  264.             orphan=data['sequence-step-orphan']
  265.             overlap=data['sequence-step-overlap']
  266.         except: AttributeError, 'next-batches'
  267.         r=[]
  268.         while end < l:
  269.             start,end,spam=opt(end+1-overlap,0,sz,orphan,sequence)
  270.             v=sequence_variables(self.items,
  271.                                  self.query_string,self.start_name_re)
  272.             d=v.data
  273.             d['batch-start-index']=start-1
  274.             d['batch-end-index']=end-1
  275.             d['batch-size']=end+1-start
  276.             d['mapping']=data['mapping']
  277.             r.append(v)
  278.         data['next-batches']=r
  279.         return r
  280.     def previous_batches(self, suffix='batches',key=''):
  281.         if suffix != 'batches': raise KeyError, key
  282.         data=self.data
  283.         sequence=self.items
  284.         try:
  285.             if not data['previous-sequence']: return ()
  286.             sz=data['sequence-step-size']
  287.             start=data['sequence-step-start']
  288.             end=data['sequence-step-end']
  289.             l=len(sequence)
  290.             orphan=data['sequence-step-orphan']
  291.             overlap=data['sequence-step-overlap']
  292.         except: AttributeError, 'previous-batches'
  293.         r=[]
  294.         while start > 1:
  295.             start,end,spam=opt(0,start-1+overlap,sz,orphan,sequence)
  296.             v=sequence_variables(self.items,
  297.                                  self.query_string,self.start_name_re)
  298.             d=v.data
  299.             d['batch-start-index']=start-1
  300.             d['batch-end-index']=end-1
  301.             d['batch-size']=end+1-start
  302.             d['mapping']=data['mapping']
  303.             r.append(v)
  304.         r.reverse()
  305.         data['previous-batches']=r
  306.         return r
  307.     special_prefixes={
  308.         'first': first,
  309.         'last': last,
  310.         'previous': previous_batches,
  311.         'next': next_batches,
  312.         # These two are for backward compatability with a missfeature:
  313.         'sequence-index': lambda self, suffix, key: self['sequence-'+suffix],
  314.         'sequence-index-is': lambda self, suffix, key: self['sequence-'+suffix],
  315.         }
  316.     for n in statistic_names: special_prefixes[n]=statistics
  317.     def __getitem__(self,key,
  318.                     special_prefixes=special_prefixes,
  319.                     special_prefix=special_prefixes.has_key
  320.                     ):
  321.         data=self.data
  322.         if data.has_key(key): return data[key]
  323.         l=rfind(key,'-')
  324.         if l < 0: raise KeyError, key
  325.         suffix=key[l+1:]
  326.         prefix=key[:l]
  327.         if hasattr(self, suffix):
  328.             try: v=data[prefix+'-index']
  329.             except: pass
  330.             else: return getattr(self,suffix)(v)
  331.         if special_prefix(prefix):
  332.             return special_prefixes[prefix](self, suffix, key)
  333.         if prefix[-4:]=='-var':
  334.             prefix=prefix[:-4]
  335.             try: return self.value(data[prefix+'-index'],suffix)
  336.             except: pass
  337.         if key=='sequence-query': return self.query()
  338.             
  339.         raise KeyError, key
  340. def sub(s1, s2, src):
  341.     return join(split(src, s1), s2)
  342. def opt(start,end,size,orphan,sequence):
  343.     if size < 1:
  344.         if start > 0 and end > 0 and end >= start:
  345.             size=end+1-start
  346.         else: size=7
  347.     if start > 0:
  348.         try: sequence[start-1]
  349.         except: start=len(sequence)
  350.         # if start > l: start=l
  351.         if end > 0:
  352.             if end < start: end=start
  353.         else:
  354.             end=start+size-1
  355.             try: sequence[end+orphan-1]
  356.             except: end=len(sequence)
  357.             # if l - end < orphan: end=l
  358.     elif end > 0:
  359.         try: sequence[end-1]
  360.         except: end=len(sequence)
  361.         # if end > l: end=l
  362.         start=end+1-size
  363.         if start - 1 < orphan: start=1
  364.     else:
  365.         start=1
  366.         end=start+size-1
  367.         try: sequence[end+orphan-1]
  368.         except: end=len(sequence)
  369.         # if l - end < orphan: end=l
  370.     return start,end,size