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