source: TI07-MOLES/trunk/PythonCode/wsgi/Utilities.py @ 2394

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/TI07-MOLES/trunk/PythonCode/wsgi/Utilities.py@2394
Revision 2394, 6.6 KB checked in by lawrence, 12 years ago (diff)

Improved error handling, including gross error mailing

Line 
1from collections import deque # python 2.4
2try: #python 2.5
3    from xml.etree import ElementTree as ET
4except ImportError:
5    try:
6        # if you've installed it yourself it comes this way
7        import ElementTree as ET
8    except ImportError:
9        # if you've egged it this is the way it comes
10        from elementtree import ElementTree as ET
11from ETxmlView import *
12import ConfigParser
13import os
14import re
15import urllib
16import logging
17import smtplib
18
19class myConfig:
20   
21   ''' Handle missing sections and variables in a config file a bit gracefully. Also
22   instantiates a logger if necessary '''
23   
24   def __init__(self,configfile,logName='NDGLOG'):
25       self.config=ConfigParser.ConfigParser()
26       if not os.path.exists(configfile): 
27           raise ValueError("Config file doesn't exist [%s]"%configfile)
28       self.config.read(configfile)
29       logfile=self.get('logging','debugLog',None)
30       self.logfile=None #deprecated
31       self.logger=None
32       if logfile is not None:
33           logger=logging.getLogger(logName)
34           handler=logging.FileHandler(logfile)
35           formatter=logging.Formatter('%(asctime)s %(levelname)s %(message)s')
36           handler.setFormatter(formatter)
37           logger.addHandler(handler)
38           logger.setLevel(logging.INFO)
39           self.logger=logger
40       
41   def get(self,section,key,default=None):
42       ''' Return a config file value for key frm section '''
43       try:
44           return self.config.get(section,key)
45       except:
46           return default
47       
48   def log(self,string):
49       ''' Log some debug information '''
50       if self.logger is None: return
51       if string is not None:
52          self.logger.info(string)
53       else:
54          self.logger.info('empty log entry')
55         
56   def getLog(self):
57       return self.logger
58
59class RingBuffer(deque):
60    #deque is a python 2.4 class!
61    #credit http://www.onlamp.com/pub/a/python/excerpt/pythonckbk_chap1/index1.html
62    def __init__(self, size_max):
63        deque.__init__(self)
64        self.size_max = size_max
65    def append(self, datum):
66        deque.append(self, datum)
67        if len(self) > self.size_max:
68            self.popleft( )
69    def tolist(self):
70        return list(self)
71
72def wrapGetText(element,xpathExpression,multiple=0):
73        ''' Wraps a call to ET to get a text object in an error handler '''
74        def none2txt(i):
75            if i is None: return ''
76            return i
77        if element is None:
78            if multiple:
79                 return ['',]
80            else: return ''
81        if multiple:
82                r=element.findall(xpathExpression)
83        else:
84                r=[element.find(xpathExpression),]
85        try:
86                rr=[i.text for i in r]
87        except:
88                rr=['',]
89        rr=map(none2txt,rr) 
90        if multiple: 
91                return rr
92        else: return rr[0] 
93
94def getURLdict(cgiFieldStorage):
95    ''' takes a cgi field storage object and converts it to a dictionary '''
96    result={}
97    for item in cgiFieldStorage:
98            result[item]=cgiFieldStorage[item].value
99    return result
100##
101### convert the followign two methods into one class that can handle
102## xml directly too if necessary
103##
104def DIFid2NDGid(string):
105    ''' takes a dif thing parses it and produces an ET ndg element id ...
106    and use this in dif ... '''
107    s=string.split(':')
108    try:
109        r='''<DIFid><schemeIdentifier>%s</schemeIdentifier>
110         <repositoryIdentifier>%s</repositoryIdentifier>
111         <localIdentifier>%s</localIdentifier></DIFid>'''%(s[1],s[0],s[2])
112        return ET.fromstring(r)
113    except:
114        r='''<DIFid><schemeIdentifier>DIF</schemeIdentifier>
115        <repositoryIdentifier>Unknown</repositoryIdentifier>
116        <localIdentifier>%s</localIdentifier></DIFid>'''%string
117        return ET.fromstring(r)
118
119def EnumerateString(string):
120    ''' Takes a string, and if it's got a number on the end, increments it,
121    otherwise adds a number on the end, used to differentiate strings which
122    would otherwise be identical '''
123    def addNum(matchObj):
124        s=matchObj.group()
125        return str(int(s)+1)
126    r=re.sub('\d+$',addNum,string)
127    if r==string: r=r+'1'
128    return r
129
130def dateParse(string,instruction):
131    ''' Simple date manipulations on a string, if it is understood ...
132       if instruction = YYYY, return the year '''
133    s=string.split('-')
134    if instruction=='YYYY':
135        if len(s)==3: # expecting year,mon,day or day,mon,year ...
136            if int(s[0])>int(s[2]): 
137                return s[0]
138            else:
139                return s[2]
140        else:
141            return string # unknown format as yet ...
142    else:
143        return 'unknown instruction to dateParse %s'%instruction
144
145def idget(xml,dataType='DIF'):
146    ''' Given an xml document (string), parse it using ElementTree and
147    find the identifier within it. Supports dataTypes of 'DIF' ...
148    (actually only DIF for now).
149    '''
150    et=loadET(xml)
151    helper=nsdumb(et)
152    if dataType=='DIF':
153        return helper.getText(et,'Entry_ID')
154    else:
155        raise TypeError,'idget does not support datatype [%s]'%dataType
156   
157
158def mailError(recipients,subject,body,sender='ndg@badc.nerc.ac.uk',testing=0,server='localhost'):
159    try:
160        server=smtplib.SMTP(server)
161        server.set_debuglevel(1)
162        toaddr=recipients
163        fromaddr="From: %s\n"% sender
164        message="To: %s\n" % toaddr
165        message+=fromaddr
166        message+="Subject: %s\n" % subject
167        message+=body
168        server.sendmail(fromaddr, toaddr, message)
169        server.quit()
170    except:
171        if testing:
172            raise
173        else:
174            #no failing in real life
175            pass
176       
177import unittest
178
179class TestCase(unittest.TestCase):
180    """ Tests as required """
181
182    configFile='examples/example.config'
183    difFile='examples/neodc.eg1.dif'
184   
185    def setUp(self):
186        # If pkg_resources is available assume the module is eggified and
187        # get a stream to the input data from the egg.
188        #try:
189        #    import pkg_resources
190        #    f = pkg_resources.resource_stream(__name__, self.configFile)
191        #except ImportError:
192            # Else take the input file from __file__
193            #import os
194        self.config=myConfig(self.configFile)
195        f=file(self.difFile,'r')
196        self.difxml=f.read()
197            #f=file(os.path.join(os.path.basepath(__file__), self.configFile))
198
199        #self.config=myConfig(f)
200
201    def testConfig(self):
202        print 'Discovery Icon [%s]'%self.config.get('DISCOVERY','icon')
203       
204    def testidget(self):
205        self.assertEqual(idget(self.difxml),'NOCSDAT192')
206   
207    def testMailError(self):
208        target='b.n.lawrence@rl.ac.uk'
209        subject='test from Utilities'
210        body='some information'
211        mailError(target,subject,body,server='outbox.rl.ac.uk',testing=1)
212
213if __name__=="__main__":
214    unittest.main()
215
216
217
Note: See TracBrowser for help on using the repository browser.