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

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

updates

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