source: CMIP6dreqbuild/trunk/src/framework/ptxt.py @ 1191

Subversion URL: http://proj.badc.rl.ac.uk/svn/exarch/CMIP6dreqbuild/trunk/src/framework/ptxt.py@1207
Revision 1191, 14.2 KB checked in by mjuckes, 2 years ago (diff)

01.00.23 corrected sample

Line 
1''' Generate vocabulary definition document and sample vocabulary document.
2USAGE
3.....
4ptxt.py [-f srcFile] [samp|defn]
5
6
7NB:
8Schema namespace implemented partially -- need to work through for update and vocabs.
9'''
10import string, re, collections, sys, uuid, utils_wb
11import time, datetime, xlrd, codecs
12from utils_wb import uniCleanFunc
13
14sys.path.append('dreqPy' )
15import packageConfig
16
17t = time.gmtime()
18d = datetime.date(t.tm_year, t.tm_mon, t.tm_mday)
19
20version = packageConfig.__version__
21
22##
23## for definitions of dublin core elements see:
24## see http://dublincore.org/documents/usageguide/elements.shtml
25##
26samplePrologue="""<prologue>
27<dc:title>Draft CMIP6 Data Request [%s]</dc:title>
28<dc:description>The CMIP6 Data Request will specify the variables requested for the CMIP6 archive, and the detail the experiments and time slices for which they are required.</dc:description>
29<dc:creator>Martin Juckes</dc:creator>
30<dc:date>%s</dc:date>
31<pav:version>%s</pav:version>
32</prologue>
33""" %  (version,d.isoformat(),version )
34
35samplePrologueVocab="""<prologue>
36<dc:title>Draft CMIP6 Vocabularies [%s]</dc:title>
37<dc:description>The CMIP6 Vocabularies will specify the controlled vocabularies for the CMIP6 archive.</dc:description>
38<dc:creator>Martin Juckes</dc:creator>
39<dc:date>%s</dc:date>
40<pav:version>%s</pav:version>
41</prologue>
42""" %  (version,d.isoformat(), version )
43
44re_it = re.compile( '{(.*)}' )
45re_is = re.compile( '\[(.*)\]' )
46re_atdef = re.compile( '^(?P<n>\S+)\s*(((?P<b>\[.*?])|(?P<a>\{.*?\})|(?P<c>\<.*?\>))\s*){0,3}$' )
47re_atdef = re.compile( '^(?P<n>\S+)\s*((\[(?P<b>.*?)\]|\{(?P<a>.*?)\}|\<(?P<c>.*?)\>|desc:(?P<desc>.*?)::)\s*){0,3}$' )
48
49### tuble to define attributes of an item
50nt__itematt = collections.namedtuple( 'itematt', ['name','type','title','clss','techn','uid','description','superclass','usage','required'] )
51
52vocab_elTmpl = '''<%(elementname)s label="%(label)s" uid="%(uid)s" title="%(title)s" id="%(id)s" itemLabelMode="%(ilm)s" level="%(sectLevel)s" maxOccurs="%(mxo)s" labUnique="%(labu)s" description="%(desc)s">
53%(itemAttrList)s
54</%(elementname)s>
55'''
56ial_elTmpl = '  <rowAttribute label="%(label)s"%(wrappedType)s%(wrappedTitle)s%(wrappedClass)s%(wrappedTechn)s%(wrappedDescription)s%(wrappedUid)s%(wrappedSuperclass)s%(wrappedUsage)s%(wrappedReq)s/>'
57
58expl_Tmpl = '''<%(label)s label="%(label)s" uid="%(uid)s" useClass="vocab" title="%(title)s" id="%(id)s">
59<!-- <info srcType="dummy" srcRef="ptxt.py">Dummy entries</info> -->
60%(exampleItem)s
61</%(label)s>
62'''
63item_Tmpl = '<item id="%(id)s" label="%(label)s" title="%(title)s"%(extras)s/>'
64
65def wrap( x,y):
66  if y == None:
67    return ''
68  else:
69    return x % y
70
71class vocab(object):
72
73  def __init__( self, line, kk=0, counter=None ):
74     if type(line) in [type(''),type(u'')]:
75       bits = map( string.strip, string.split(line, ';' ) )
76       assert len (bits) in [7,8], '[1] Cannot parse %s' % line
77       assert bits[0][:5] == 'vocab', '[2] Cannot parse %s' % line
78       self.label = string.split(bits[0], ' ')[1]
79       self.title = bits[1]
80       self.id = 'cmip.drv.%3.3i' % kk
81       self.ilt = bits[3]
82       self.level = int(bits[4] )
83       self.kk = kk
84       self.labu = bits[6]
85       self.mxo = int(bits[5])
86       self.description = '%s [%s]' % (self.title, self.label)
87     else:
88       self.label,self.title , self.id, self.ilt, self.level, self.kk, self.labu, self.mxo = tuple( line[1:9] )
89       if len(line) == 10:
90         self.description = line[9]
91       else:
92         self.description = ''
93       self.level = int( self.level )
94       self.mxo = int( self.mxo )
95     self.header = (self.label,self.title , self.id, self.ilt, self.level, self.kk, self.labu, self.mxo )
96     self.msg( '[%s] %s {%s:%s}' % (self.label, self.title, self.id, self.ilt) )
97###nt__itematt = collections.namedtuple( 'itematt', ['name','type','title','clss','techn'] )
98###nt__itematt = collections.namedtuple( 'itematt', ['name','type','title','clss','techn','uid','description','superclass','usage','required'] )
99     self.itematts = [  nt__itematt( 'label','xs:string','Record Label',None,None,None,'Mnemonic label for record',None,None,True ),
100                        nt__itematt( 'title','xs:string','Record Title',None,None,None,'Title of record',None,None,True ) ]
101     self.counter = counter
102
103  def tmpl(self,oo=None,mode="defn",cls='vocab'):
104     """Write out a section definition or a sample record"""
105     if mode in [ "defn","upd"]:
106       ss = []
107       for i in self.itematts:
108         if i.title in ['',None]:
109           print 'ERROR.tmpl.0001: empty title in: ',i.name,self.label
110         if i.name in ['',None]:
111           print 'ERROR.tmpl.0002: empty label in: ',i.name,self.label
112         wrappedClass = wrap( ' useClass="%s"' , i.clss )
113         wrappedTechn = wrap( ' techNote="%s"' , i.techn )
114         wrappedTitle = wrap( ' title="%s"' , i.title )
115         if i.name == 'uid':
116           wrappedType = ' type="aa:st__uid"'
117         else:
118           wrappedType = wrap( ' type="%s"' , i.type )
119         ##wrappedReq = wrap( ' required="%s"' , i.required )
120         if i.required != '':
121           wrappedReq = wrap( ' required="%s"' , i.required )
122         else:
123           wrappedReq = ' required="true"'
124
125         if i.usage != '':
126           wrappedUsage = wrap( ' usage="%s"' , i.usage )
127         else:
128           wrappedUsage = ''
129         if i.uid in [None,'']:
130           ##wrappedUid = wrap( ' uid="%s"' , str( uuid.uuid1() ) )
131           wrappedUid = wrap( ' uid="%s"' , 'ATTRIBUTE::%s.%s' % (self.label,i.name) )
132         else:
133           wrappedUid = wrap( ' uid="%s"' , i.uid )
134
135         wrappedDescription = wrap( ' description="%s"' , i.description )
136         wrappedSuperclass = wrap( ' superclass="%s"' , i.superclass )
137
138         label = i.name
139         ss.append(ial_elTmpl % locals())
140       sss = string.join( ss, '\n' )
141
142       if mode in [ 'upd','updsamp']:
143         label = '%sUpd' % self.label
144       else:
145         label = self.label
146       title = self.title
147       id = self.id
148       ilm =  self.ilt
149       sectLevel =  self.level
150       itemAttrList = sss
151       mxo = self.mxo
152       labu = self.labu
153       desc = self.description
154       uid = "SECTION:%s" % label
155       elementname = 'table'
156       if cls != 'vocab':
157         elementname = 'annextable'
158         label = label[1:]
159         id = id[1:]
160       if self.mxo > 1:
161         uid += '.xx'
162       self.vocab = vocab_elTmpl % locals()
163     else:
164## construct sample item ##
165       if self.ilt == 'an':
166         label = 'example01'
167       elif self.ilt == 'def':
168         label = 'example-01'
169       elif self.ilt == 'int':
170         label = '1'
171       elif self.ilt == 'und':
172         label = 'example_03'
173       title = 'dummy title string'
174
175       extras = ''
176       for i in self.itematts:
177         if i.name not in ['label','title']:
178           value = "noType"
179           if i.type == "xs:string":
180             if i.name == 'uid':
181               value = str( uuid.uuid1() )
182             else:
183               value = 'dummyAt'
184           elif i.type == "xs:integer":
185             value = '25'
186           elif i.type in ["aa:st__integerList","aa:st__integerListMonInc"]:
187             value = '25 30'
188           elif i.type in ["aa:st__stringList"]:
189             value = 'alpha beta'
190           elif i.type == "aa:st__floatList":
191             value = '5. 10.'
192           elif i.type == "aa:st__fortranType":
193             value = 'integer'
194           elif i.type == "aa:st__sliceType":
195             value = 'yearList'
196           elif i.type == "aa:st__configurationType":
197             value = 'size'
198           elif i.type == "xs:float":
199             value = '5.'
200           elif i.type == "xs:boolean":
201             value = 'false'
202           elif i.type == "xs:duration":
203             value = 'P1Y'
204
205           extras += ' %s="%s"' % (i.name,value)
206       id = '001.%3.3i.%3.3i' % (self.kk,1)
207       exampleItem = item_Tmpl % locals()
208       label = self.label
209       title = self.title
210       id = self.id
211       if cls != 'vocab':
212         label = label[1:]
213         id = id[1:]
214       ilm =  self.ilt
215       uid = "SECTION:%s" % label
216       self.counter[label] += 1
217       if self.mxo > 1:
218         uid += '.%2.2i' % self.counter[label]
219       self.vocab = expl_Tmpl % locals()
220##
221## print and write if needed
222##
223     if oo != None:
224       try:
225         oo.write( uniCleanFunc( self.vocab ) )
226       except:
227         print 'Failed to write ...'
228         print self.vocab
229         raise
230     self.msg( vocab )
231
232  def msg(self,txt):
233     swallow=True
234     if swallow:
235       return
236     print text
237
238  def attr02(self,line):
239         self.itematts.append( nt__itematt._make( line ) )
240         self.msg( '%s, %s, %s, %s, %s' % (line[0], line[1], line[2], line[3], line[4]) )
241
242  def attr(self,line):
243     bits = map( string.strip, string.split(line[3:], ';' ) )
244     for b in bits:
245       if string.strip(b) != '':
246         bn = string.split(b, ' ')[0]
247         x = self.pb(b)
248##nt__itematt = collections.namedtuple( 'itematt', ['name','type','title','clss','techn','uid','description','superclass','usage','required'] )
249         self.itematts.append( nt__itematt( bn, x[0], x[1], x[2], x[3], None,x[4], None, None, 'True' ) )
250         self.msg( '%s, %s, %s, %s, %s' % (bn, x[0], x[1], x[2], x[3]) )
251
252  def pb(self, b):
253    x = re_it.findall(b)
254    m = re_atdef.match( b )
255    if m == None:
256         print 'COULD NOT SCAN: ',b
257         assert False
258    else:
259      ee = m.groupdict()
260      for k in ['a','b','c','desc']:
261        if type( ee[k] ) == type( 'x' ):
262          assert string.find( ee[k], '"' ) == -1, 'unable to deal with quote in string: %s' % ee[k]
263      itemTitle = ee['a']
264      itemType = ee['b']
265      itemClass = ee['c']
266      itemDescription = ee['desc']
267      itemTechNote = None
268      if itemType == None:
269         itemType = 'xs:string'
270      if type(itemClass) == type('x'):
271        if string.find(itemClass, '|' ) != -1:
272          bits = string.split( itemClass, '|' )
273          assert len(bits) == 2, 'ERROR.001.0001: failed to parse attribute definition: %s' % b
274          itemClass = bits[0]
275          itemTechNote = bits[1]
276       
277    return [itemType, itemTitle,itemClass,itemTechNote, itemDescription] 
278
279class main(object):
280
281  def __init__(self,fn,mode):
282    if fn[-4:] == '.xls':
283      oo = codecs.open( '/tmp/ptxt_records.txt', 'wb', encoding='ascii' )
284      brec = []
285      imode = 0
286      ii = []
287      self.isect = {}
288      wb = utils_wb.workbook( '../../docs/%s' % fn )
289      s0 = wb.book.sheet_by_name( 'SECTIONS' )
290      ks = []
291      for j in range(1,s0.nrows):
292        rr = map( lambda x: x.value, s0.row(j) )
293        self.isect[str(rr[0]) ] = rr
294        ks.append( str(rr[0]) )
295      for k in ks:
296        if k[0:2] != '__':
297          if k[0] == '_':
298            ii.append( ['annexVocab',] + self.isect[k] )
299          else:
300            ii.append( ['vocab',] + self.isect[k] )
301          s = wb.book.sheet_by_name( k )
302          for j in range(1,s.nrows):
303            rr = map( lambda x: x.value, s.row(j) )
304            rr[6] = uniCleanFunc( rr[6] )
305            try:
306              for x in rr:
307                oo.write( x )
308                oo.write( '\t' )
309              oo.write( '\n' )
310            except:
311              brec.append((k,rr))
312            ii.append(rr)
313         
314      oo.close()
315      if len(brec) > 0:
316        print 'Un-printable records found in ../../docs/%s' % fn
317        for b in brec:
318          print brec
319        assert False, 'FATAL ERROR'
320    else: 
321      imode = 1
322      ii = []
323      for l in open('../../docs/%s' % fn).readlines():
324        if l[0] != '#':
325          ii.append(l)
326    kk= 0
327    this = None
328    fstem = string.split( fn, '.' )[0]
329    fns = {'defn':'%sDefn' % fstem, 'samp':'%sSample' % fstem, 'upd':'%sUpdDefn' % fstem, 'updsamp':'%sUpdSampl' % fstem }
330    fn = fns[mode]
331    oo = open( 'out/%s.xml' % fn, 'w' )
332    if mode in [ 'samp','updsamp']:
333      mainEl = "document"
334      mainElCont = '''
335xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
336xsi:noNamespaceSchemaLocation="out/dreqSchema.xsd"
337xmlns:dc="http://purl.org/dc/elements/1.1/"
338xmlns:pav="http://purl.org/pav/2.3"
339xmlns="urn:w3id.org:cmip6.dreq.dreq:a"'''
340    else:
341      mainEl = "defDoc"
342      mainElCont = '''
343xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
344xmlns="urn:w3id.org:cmip6.dreq.framework:a"
345xsi:schemaLocation="http://w3id.org/cmip6dr/ns vocabFrameworkSchema_v01beta.xsd"'''
346
347    oo.write( '''<?xml version="1.0" ?>
348<%s%s>\n''' % (mainEl,mainElCont) )
349    updExtra = ''' - srcid {Record to be copied/modified} <internalLink>
350 - updClass {Class of update: copy|change|delete|new}
351 - updComment {Comment on the proposed change}
352 - updDate {Date of update}
353 - updProv {Proposer of update}'''
354
355##    if l[:5] == 'vocab':
356      ##prolo = samplePrologueVocab
357    ##else:
358      ##prolo = samplePrologue
359
360    if mode in [ 'samp','updsamp']:
361      oo.write( '%s<main>\n' % samplePrologue )
362    annex = False
363    counter = collections.defaultdict(int)
364    self.sections = {}
365    for l in ii:
366      if (imode == 1 and l[:5] == 'vocab') or (imode == 0 and l[0] in ['vocab','annexVocab']):
367        if this != None:
368          this.tmpl(oo=oo,mode=mode,cls=cls)
369          self.sections[this.label] = (this.header, this.itematts)
370        if imode == 0:
371          cls = l[0]
372        else:
373          cls = l[:5]
374        if cls == 'annexVocab':
375          if not annex:
376             if mode in [ 'samp','updsamp']:
377                 oo.write( '</main><annex>\n' )
378          annex = True
379        kk+=1
380        this = vocab(l,kk=kk,counter=counter)
381        if mode in ['upd','updsamp']:
382          for l1 in string.split( updExtra, '\n' ):
383            this.attr( l1 )
384      else:
385        if imode == 1:
386          this.attr( l)
387        else:
388          while len(l) < 10:
389            l.append( '' )
390          this.attr02( l)
391
392    this.tmpl(oo=oo,mode=mode,cls=cls)
393    self.sections[this.label] = (this.header, this.itematts)
394    if mode in [ 'samp','updsamp']:
395      if annex:
396        oo.write( '</annex>\n' )
397      else:
398        oo.write( '</main>\n' )
399    oo.write( '</%s>\n' % mainEl )
400    oo.close()
401
402if __name__ == "__main__":
403  if len(sys.argv) == 1:
404    print __doc__
405    exit()
406
407  args = sys.argv[1:]
408  if args[0] == '-f':
409    srcFn = args[1]
410    args = args[2:]
411  elif args[0] == '-v':
412    srcFn = 'vocab.txt'
413    args = args[1:]
414  else:
415    srcFn = 'dreq.txt'
416 
417  mode = args[0]
418
419  assert mode in ["defn", "samp","upd","updsamp"]
420
421  print '###### srcFn : ',srcFn
422  m = main(srcFn,mode)
Note: See TracBrowser for help on using the repository browser.