source: hdldemo/trunk/hdldemo.py @ 564

Subversion URL: http://proj.badc.rl.ac.uk/svn/exarch/hdldemo/trunk/hdldemo.py@564
Revision 564, 7.5 KB checked in by mjuckes, 5 years ago (diff)

Improved code structure

Line 
1"""
2Demonstration handle dump for CMIP/ESGF files ..
3
4 -h: print this message;
5 -v: print version;
6 -t: run a test;
7 -f <file name>: examine file, print path to replacement if this file is obsolete, print path to sibling files.
8 -id <tracking id>: examine handle record of tracking id.
9"""
10## see https://www.handle.net/proxy_servlet.html for info on restfull API
11
12import string, collections, os
13import ncq3
14import xml
15from xml.dom import minidom
16
17try:
18 import urllib
19 from urllib import request
20except:
21 import requests
22
23from testdata import *
24
25class phandle(object):
26 
27  def __init__(self, hdlDict, k='values'):
28    self.h = hdlDict
29    self.d = {}
30    try:
31      for r in hdlDict[k]:
32        self.d[r['type']] = r['data']
33    except:
34      print ( hdlDict[k] )
35      raise
36
37class ghandle(object):
38  htmpl = 'http://hdl.handle.net/api/handles/%s'
39  dh = dummyHandles()
40  def __init__(self,hdl,url=None):
41
42     if hdl[:5] == 'xxxxx':
43       self.msg = self.dh.hh[hdl]
44     else:
45       if url == None:
46         thisid = string.replace(hdl,'hdl:999999', '10876.test' )
47         url = self.htmpl % thisid
48       self.fetch(url)
49
50  def fetch(self,url):
51     ##print url
52
53     try:
54       fh = request.urlopen( url )
55       msg = eval( fh.read() )
56     except:
57       r = requests.get( url )
58       msg = r.json()
59     assert type( msg ) == type( {} ), 'Response of wrong type'
60     for k in ['responseCode', 'handle']:
61       assert k in msg, 'Required key %s not found: %s' % (k, str( msg.keys() ) )
62
63     ###print ( 'url read ok' )
64     self.msg = msg
65
66class GHandles(object):
67  def __init__(self):
68    self.hh = {}
69  def __call__(self,hdl):
70    if hdl not in self.hh:
71      self.hh[hdl] = ghandle(hdl)
72    return self.hh[hdl]
73
74ghandles = GHandles()
75
76class pyhandle(object):
77  def __init__(self,id):
78    self.REC_id = id
79    self.REC_got = False
80
81  def get(self):
82    if self.REC_got:
83      return
84
85    g = ghandles( self.REC_id )
86    for r in g.msg['values']:
87        if str(r['type']) in ['replaces', 'replacedBy', 'isReplacedBy','parent']:
88          self.__dict__[r['type']] = pyhandle( r['data']['value'] )
89
90        elif r['type']  == 'children':
91          cl = eval( r['data']['value'] )
92          self.__dict__['children'] = [pyhandle(c) for c in cl]
93
94        else:
95          self.__dict__[r['type']] = r['data']['value']
96
97    self.obsolete = 'replaced_by' in self.__dict__
98    if 'URL' in self.__dict__:
99      fn = string.split( self.__dict__['URL'], '/' )[-1]
100      self.__dict__['filename'] = fn
101    else:
102      self.__dict__['filename'] = '__unnamed__'
103
104  def getSiblings(self):
105     if self.aggregation_level != 'file':
106       print 'No known siblings .....'
107       return
108
109     if 'parent' not in self.__dict__:
110       print 'No parent'
111       return
112
113     self.parent.get()
114     self.siblings = []
115     for c in self.parent.children:
116       if c.REC_id != self.REC_id:
117         self.siblings.append( c )
118
119class main(object):
120  knownargs0 = ['-h','-v','-t']
121  knownargs1 = ['-f','-id']
122  def __init__(self, args):
123    self.htmpl = 'http://hdl.handle.net/api/handles/%s'
124    self.version = '0.01.01'
125    self.args = args
126    self.parseArgs()
127    if self.d.get( '-v', False ):
128      print ( self.version )
129      return
130
131    if self.d.get( '-h', False ):
132      print (self.version)
133      print ( __doc__ )
134      return
135
136    if self.d.get( '-t', False ):
137      self.runTest()
138      return
139
140    if '-f' in self.d:
141      fn = self.d['-f']
142      self.dumpF(fn)
143
144    if '-id' in self.d:
145      id = self.d['-id']
146      self.dumpF('',id=id)
147
148  def dumpF(self,fn, id=None):
149    if id == None:
150      assert os.path.isfile( fn ), 'File %s not found' % fn
151      f = ncHead( fn )
152      thisid = string.replace(f.ga['tracking_id'], 'hdl:999999', '10876.test' )
153    else:
154      thisid = string.replace(id,'hdl:999999', '10876.test' )
155
156    self.p = pyhandle(  thisid )
157    self.p.get()
158    self.p.parent.get()
159    if self.p.obsolete:
160      print '******* OBSOLETE FILE ******'
161      this = self.p
162      while this.obsolete:
163        this.replaced_by.get()
164        print 'REPLACED BY: ',this.replaced_by.URL, this.replaced_by.REC_id
165        this = this.replaced_by
166    else:
167      print '****** File is current'
168
169    self.p.getSiblings()
170    print '------- SIBLINGS -------'
171    for c in self.p.siblings:
172        c.get()
173        if c.obsolete:
174          while c.obsolete:
175            c.replaced_by.get()
176            print '>>>', c.replaced_by.URL
177        else:
178            print c.URL
179
180  def dumpFxx(self,fn, id=None):
181    if id == None:
182      assert os.path.isfile( fn ), 'File %s not found' % fn
183      f = ncHead( fn )
184      thisid = string.replace(f.ga['tracking_id'], 'hdl:999999', '10876.test' )
185    else:
186      thisid = string.replace(id,'hdl:999999', '10876.test' )
187
188    url = self.htmpl % thisid
189    g = ghandle( thisid )
190    self.p = phandle(  g.msg )
191    gp = ghandle(  self.p.d['parent']['value'] )
192    self.pp = phandle(  gp.msg )
193    isReplaced = 'replaced_by' in self.p.d
194    if isReplaced:
195      print '******* OBSOLETE FILE ******'
196      pr = self.p
197      while isReplaced:
198        h2 = pr.d['replaced_by']['value']
199        pr = phandle(  ghandle( pr.d['replaced_by']['value'] ).msg )
200        isReplaced = 'replaced_by' in pr.d
201        print 'REPLACED BY: ',pr.d['URL']['value'],h2
202    else:
203      print 'File is current'
204
205    cl = eval( self.pp.d['children']['value'] )
206    thisfound=False
207    print '------- SIBLINGS -------'
208    for c in cl:
209      if c == thisid:
210        thisfound = True
211      else:
212        gc = ghandle(  c )
213        pc = phandle( gc.msg )
214        isReplaced = 'replaced_by' in pc.d
215        rsq = [pc,]
216        if isReplaced:
217          while isReplaced:
218            pc = phandle(  ghandle( pc.d['replaced_by']['value'] ).msg )
219            isReplaced = 'replaced_by' in pc.d
220            print '>>>', pc.d['URL']['value']
221        elif 'URL' in pc.d:
222          print pc.d['URL']['value']
223        else:
224          print 'Sibling url not found',pc.d.keys()
225
226  def runTest(self):
227    f = ncHead( fn1 )
228    url = self.htmpl % f.ga['tracking_id']
229    hdl = string.replace( f.ga['tracking_id'], 'hdl:999999', '10876.test' )
230    g = ghandle( hdl )
231    self.p = phandle(  g.msg )
232    expected= ['creation_date', 'aggregation_level', 'HS_ADMIN', '10320/loc', 'checksum', 'URL', 'parent']
233    ## 'replaced_by' if obsolete
234    for k in expected:
235      assert k in self.p.d, 'Expected handle content key %s not found:: %s' % (k,str(self.p.d.keys()))
236    assert 'tracking_id' in self.p.d or 'trackingID' in self.p.d, 'No tracking id found: %s' % str(self.p.d.keys())
237    for k in expected:
238      print ('%s: %s' % (k,self.p.d[k]))
239
240    print ('PARSING PARENT ..... ' )
241    print ( self.htmpl % self.p.d['parent']['value'] )
242    g = ghandle( self.p.d['parent']['value'] )
243    self.pp = phandle(  g.msg )
244    for k in self.pp.d.keys():
245      print ('%s: %s' % (k,self.pp.d[k]))
246    #'isReplacedBy' if obsolete
247    expected= ['creation_date', 'aggregation_level', 'HS_ADMIN', '10320/loc', 'checksum', 'URL', 'children', 'tracking_id']
248
249  def parseArgs(self):
250    self.d = {}
251    kn = self.knownargs0 + self.knownargs1
252    xx = []
253    al = self.args[1:]
254    while len(al) > 0:
255      a = al.pop(0)
256      if a not in kn:
257        xx.append(a)
258      elif a in self.knownargs1:
259         self.d[a] = al.pop(0)
260      else:
261         self.d[a] = True
262    if len(xx) > 0:
263      print ('ARGUMENTS NOT RECOGNISED: %s' % str(xx) )
264       
265class ncHead(object):
266  def __init__(self, fn):
267    nc0 = ncq3.open( fn )
268    nc0.getDigest()
269    self.ga = {}
270    for a in nc0.alla:
271      self.ga[a.name] = a.value
272     
273     
274if __name__ == "__main__":
275  import sys
276  m = main( sys.argv )
277
278
Note: See TracBrowser for help on using the repository browser.