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

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

cleaned scope.py

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