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

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

added final CMIP experiments ... through to --sf

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 == "xs:float":
193             value = '5.'
194           elif i.type == "xs:boolean":
195             value = 'false'
196           elif i.type == "xs:duration":
197             value = 'P1Y'
198
199           extras += ' %s="%s"' % (i.name,value)
200       id = '001.%3.3i.%3.3i' % (self.kk,1)
201       exampleItem = item_Tmpl % locals()
202       label = self.label
203       title = self.title
204       id = self.id
205       if cls != 'vocab':
206         label = label[1:]
207         id = id[1:]
208       ilm =  self.ilt
209       uid = "SECTION:%s" % label
210       self.counter[label] += 1
211       if self.mxo > 1:
212         uid += '.%2.2i' % self.counter[label]
213       self.vocab = expl_Tmpl % locals()
214##
215## print and write if needed
216##
217     if oo != None:
218       try:
219         oo.write( uniCleanFunc( self.vocab ) )
220       except:
221         print 'Failed to write ...'
222         print self.vocab
223         raise
224     self.msg( vocab )
225
226  def msg(self,txt):
227     swallow=True
228     if swallow:
229       return
230     print text
231
232  def attr02(self,line):
233         self.itematts.append( nt__itematt._make( line ) )
234         self.msg( '%s, %s, %s, %s, %s' % (line[0], line[1], line[2], line[3], line[4]) )
235
236  def attr(self,line):
237     bits = map( string.strip, string.split(line[3:], ';' ) )
238     for b in bits:
239       if string.strip(b) != '':
240         bn = string.split(b, ' ')[0]
241         x = self.pb(b)
242##nt__itematt = collections.namedtuple( 'itematt', ['name','type','title','clss','techn','uid','description','superclass','usage','required'] )
243         self.itematts.append( nt__itematt( bn, x[0], x[1], x[2], x[3], None,x[4], None, None, 'True' ) )
244         self.msg( '%s, %s, %s, %s, %s' % (bn, x[0], x[1], x[2], x[3]) )
245
246  def pb(self, b):
247    x = re_it.findall(b)
248    m = re_atdef.match( b )
249    if m == None:
250         print 'COULD NOT SCAN: ',b
251         assert False
252    else:
253      ee = m.groupdict()
254      for k in ['a','b','c','desc']:
255        if type( ee[k] ) == type( 'x' ):
256          assert string.find( ee[k], '"' ) == -1, 'unable to deal with quote in string: %s' % ee[k]
257      itemTitle = ee['a']
258      itemType = ee['b']
259      itemClass = ee['c']
260      itemDescription = ee['desc']
261      itemTechNote = None
262      if itemType == None:
263         itemType = 'xs:string'
264      if type(itemClass) == type('x'):
265        if string.find(itemClass, '|' ) != -1:
266          bits = string.split( itemClass, '|' )
267          assert len(bits) == 2, 'ERROR.001.0001: failed to parse attribute definition: %s' % b
268          itemClass = bits[0]
269          itemTechNote = bits[1]
270       
271    return [itemType, itemTitle,itemClass,itemTechNote, itemDescription] 
272
273class main(object):
274
275  def __init__(self,fn,mode):
276    if fn[-4:] == '.xls':
277      oo = codecs.open( '/tmp/ptxt_records.txt', 'wb', encoding='ascii' )
278      brec = []
279      imode = 0
280      ii = []
281      self.isect = {}
282      wb = utils_wb.workbook( '../../docs/%s' % fn )
283      s0 = wb.book.sheet_by_name( 'SECTIONS' )
284      ks = []
285      for j in range(1,s0.nrows):
286        rr = map( lambda x: x.value, s0.row(j) )
287        self.isect[str(rr[0]) ] = rr
288        ks.append( str(rr[0]) )
289      for k in ks:
290        if k[0:2] != '__':
291          if k[0] == '_':
292            ii.append( ['annexVocab',] + self.isect[k] )
293          else:
294            ii.append( ['vocab',] + self.isect[k] )
295          s = wb.book.sheet_by_name( k )
296          for j in range(1,s.nrows):
297            rr = map( lambda x: x.value, s.row(j) )
298            try:
299              for x in rr:
300                oo.write( x )
301                oo.write( '\t' )
302              oo.write( '\n' )
303            except:
304              brec.append((k,rr))
305            ii.append(rr)
306         
307      oo.close()
308      if len(brec) > 0:
309        print 'Un-printable records found in ../../docs/%s' % fn
310        for b in brec:
311          print brec
312        assert False, 'FATAL ERROR'
313    else: 
314      imode = 1
315      ii = []
316      for l in open('../../docs/%s' % fn).readlines():
317        if l[0] != '#':
318          ii.append(l)
319    kk= 0
320    this = None
321    fstem = string.split( fn, '.' )[0]
322    fns = {'defn':'%sDefn' % fstem, 'samp':'%sSample' % fstem, 'upd':'%sUpdDefn' % fstem, 'updsamp':'%sUpdSampl' % fstem }
323    fn = fns[mode]
324    oo = open( 'out/%s.xml' % fn, 'w' )
325    if mode in [ 'samp','updsamp']:
326      mainEl = "document"
327      mainElCont = '''
328xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
329xsi:noNamespaceSchemaLocation="out/dreqSchema.xsd"
330xmlns:dc="http://purl.org/dc/elements/1.1/"
331xmlns:pav="http://purl.org/pav/2.3"
332xmlns="urn:w3id.org:cmip6.dreq.dreq:a"'''
333    else:
334      mainEl = "defDoc"
335      mainElCont = '''
336xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
337xmlns="urn:w3id.org:cmip6.dreq.framework:a"
338xsi:schemaLocation="http://w3id.org/cmip6dr/ns vocabFrameworkSchema_v01beta.xsd"'''
339
340    oo.write( '''<?xml version="1.0" ?>
341<%s%s>\n''' % (mainEl,mainElCont) )
342    updExtra = ''' - srcid {Record to be copied/modified} <internalLink>
343 - updClass {Class of update: copy|change|delete|new}
344 - updComment {Comment on the proposed change}
345 - updDate {Date of update}
346 - updProv {Proposer of update}'''
347
348##    if l[:5] == 'vocab':
349      ##prolo = samplePrologueVocab
350    ##else:
351      ##prolo = samplePrologue
352
353    if mode in [ 'samp','updsamp']:
354      oo.write( '%s<main>\n' % samplePrologue )
355    annex = False
356    counter = collections.defaultdict(int)
357    self.sections = {}
358    for l in ii:
359      if (imode == 1 and l[:5] == 'vocab') or (imode == 0 and l[0] in ['vocab','annexVocab']):
360        if this != None:
361          this.tmpl(oo=oo,mode=mode,cls=cls)
362          self.sections[this.label] = (this.header, this.itematts)
363        if imode == 0:
364          cls = l[0]
365        else:
366          cls = l[:5]
367        if cls == 'annexVocab':
368          if not annex:
369             if mode in [ 'samp','updsamp']:
370                 oo.write( '</main><annex>\n' )
371          annex = True
372        kk+=1
373        this = vocab(l,kk=kk,counter=counter)
374        if mode in ['upd','updsamp']:
375          for l1 in string.split( updExtra, '\n' ):
376            this.attr( l1 )
377      else:
378        if imode == 1:
379          this.attr( l)
380        else:
381          while len(l) < 10:
382            l.append( '' )
383          this.attr02( l)
384
385    this.tmpl(oo=oo,mode=mode,cls=cls)
386    self.sections[this.label] = (this.header, this.itematts)
387    if mode in [ 'samp','updsamp']:
388      if annex:
389        oo.write( '</annex>\n' )
390      else:
391        oo.write( '</main>\n' )
392    oo.write( '</%s>\n' % mainEl )
393    oo.close()
394
395if __name__ == "__main__":
396  if len(sys.argv) == 1:
397    print __doc__
398    exit()
399
400  args = sys.argv[1:]
401  if args[0] == '-f':
402    srcFn = args[1]
403    args = args[2:]
404  elif args[0] == '-v':
405    srcFn = 'vocab.txt'
406    args = args[1:]
407  else:
408    srcFn = 'dreq.txt'
409 
410  mode = args[0]
411
412  assert mode in ["defn", "samp","upd","updsamp"]
413
414  print '###### srcFn : ',srcFn
415  m = main(srcFn,mode)
Note: See TracBrowser for help on using the repository browser.