Ignore:
Timestamp:
24/09/15 17:00:19 (5 years ago)
Author:
mjuckes
Message:

Moved to dreq2..

File:
1 edited

Legend:

Unmodified
Added
Removed
  • CMIP6dreq/trunk/src/dreq.py

    r369 r388  
    77import xml.dom 
    88import xml.dom.minidom 
     9import re 
     10 
     11class rechecks(object): 
     12  def __init__(self): 
     13    self.__isInt = re.compile( '-{0,1}[0-9]+' ) 
     14 
     15  def isIntStr( self, tv ): 
     16    if type( tv ) not in {type(''),type(u'')}: 
     17      self.reason = 'NOT STRING' 
     18      return False 
     19    ok = self.__isInt.match( tv ) != None 
     20    if not ok: 
     21      self.reason = 'Failed to match regular expression for integers' 
     22    else: 
     23      self.reason = '' 
     24    return ok 
    925 
    1026class dreqItemBase(object): 
    1127       __doc__ = """A base class used in the definition of records. Designed to be used via a class factory which sets "itemLabelMode" and "attributes" before the class is instantiated: attempting to instantiate the class before setting these will trigger an exception.""" 
     28       _indexInitialised = False 
     29       _inx = None 
     30       _urlBase = '' 
     31       _htmlStyle = {} 
     32 
    1233       def __init__(self,dict=None,xmlMiniDom=None,id='defaultId'): 
    1334         dictMode = dict != None 
     
    1536         assert not( dictMode and mdMode), 'Mode must be either dictionary of minidom: both assigned' 
    1637         assert dictMode or mdMode, 'Mode must be either dictionary of minidom: neither assigned' 
    17          self.defaults = { } 
    18          self.globalDefault = '__unset__' 
     38         ##self._defaults = { } 
     39         ##self._globalDefault = '__unset__' 
     40         self._contentInitialised = False 
    1941         if dictMode: 
    2042           self.dictInit( dict ) 
     
    2244           self.mdInit( xmlMiniDom ) 
    2345 
     46       def __repr__(self): 
     47         """Provide a one line summary of identifying the object.""" 
     48         if self._contentInitialised: 
     49           return 'Item <%s>: [%s] %s' % (self._h.title,self.label,self.title) 
     50         else: 
     51           return 'Item <%s>: uninitialised' % self._h.title 
     52 
     53       def __info__(self,full=False): 
     54         """Print a summary of the data held in the object as a list of key/value pairs""" 
     55         if self._contentInitialised: 
     56           print 'Item <%s>: [%s] %s' % (self._h.title,self.label,self.title) 
     57           for a in self.__dict__.keys(): 
     58             if a[0] != '_' or full: 
     59               if self._a[a].rClass == 'internalLink' and self._base._indexInitialised: 
     60                 targ = self._base._inx.uid[ self.__dict__[a] ][1] 
     61                 print '   %s: [%s]%s [%s]' % ( a, targ._h.label, targ.label, self.__dict__[a] ) 
     62               else: 
     63                 print '    %s: %s' % ( a, self.__dict__[a] ) 
     64         else: 
     65           print 'Item <%s>: uninitialised' % self.sectionLabel 
     66 
     67       def __href__(self,odir=""): 
     68         igns =  {'','__unset__'} 
     69         if self.__dict__.has_key( 'description' ) and string.strip( self.description ) not in igns: 
     70           ttl = self.description 
     71         elif self.__dict__.has_key( 'title' ) and string.strip( self.title ) not in igns: 
     72           ttl = self.title 
     73         else: 
     74           ttl = self.label 
     75         return '<span title="%s"><a href="%s%s.html">%s</a></span>' % (ttl,odir,self.uid,self.uid) 
     76 
     77       def __html__(self): 
     78         """Create html view""" 
     79         msg = [] 
     80         if self._contentInitialised: 
     81           sect = self._h.label 
     82           msg.append( '<h1>%s: [%s] %s</h1>' % (self._h.title,self.label,self.title) ) 
     83           msg.append( '<a href="../index.html">Home</a> &rarr; <a href="../index/%s.html">%s section index</a><br/>\n' % (sect, self._h.title) ) 
     84           msg.append( '<ul>' ) 
     85           for a in self.__dict__.keys(): 
     86             if a[0] != '_': 
     87               if self._a[a].rClass == 'internalLink' and self._base._indexInitialised: 
     88                 if self.__dict__[a] == '__unset__': 
     89                   m = '<li>%s: %s [missing link]</li>' % ( a, self.__dict__[a] ) 
     90                 else: 
     91                   targ = self._base._inx.uid[ self.__dict__[a] ][1] 
     92                   m = '<li>%s: [%s] %s [%s]</li>' % ( a, targ._h.label, targ.label, targ.__href__() ) 
     93               else: 
     94                 m = '<li>%s: %s</li>' % ( a, self.__dict__[a] ) 
     95               msg.append( m ) 
     96           msg.append( '</ul>' ) 
     97## 
     98## add list of inward references 
     99## 
     100           if self._base._indexInitialised: 
     101             f1 = self._htmlStyle.get( sect, {} ).get( 'getIrefs', None ) != None 
     102             if f1: 
     103               tl = [] 
     104               if f1: 
     105                 tl = self._htmlStyle[sect]['getIrefs'] 
     106               doall = '__all__' in tl 
     107               if doall: 
     108                 tl = self._inx.iref_by_sect[self.uid].a.keys() 
     109               am = [] 
     110               for t in tl: 
     111                 if self._inx.iref_by_sect[self.uid].a.has_key(t): 
     112                   am.append( '<h3>%s</h3>' % t ) 
     113                   am.append( '<ul>' ) 
     114                   items = [self._inx.uid[u][1] for  u in self._inx.iref_by_sect[self.uid].a[t] ] 
     115                   items.sort( ds('label').cmp ) 
     116                   for targ in items: 
     117                     m = '<li>%s:%s [%s]</li>' % ( targ._h.label, targ.label, targ.__href__() ) 
     118                     am.append( m ) 
     119                   am.append( '</ul>' ) 
     120               if len(am) > 0: 
     121                  msg.append( '<h2>Links from other sections</h2>' ) 
     122                  for m in am: 
     123                    msg.append(m) 
     124                
     125         else: 
     126           msg.append( '<b>Item %s: uninitialised</b>' % self.sectionLabel ) 
     127         return msg 
     128 
     129 
    24130       def dictInit( self, dict ): 
    25131         __doc__ = """Initialise from a dictionary.""" 
    26          for a in self.attributes: 
     132         for a in self._a.keys(): 
    27133           if dict.has_key(a): 
    28134             self.__dict__[a] = dict[a] 
    29135           else: 
    30              self.__dict__[a] = self.defaults.get( a, self.globalDefault ) 
     136             self.__dict__[a] = self._d.defaults.get( a, self._d.glob ) 
     137         self._contentInitialised = True 
    31138 
    32139       def mdInit( self, el ): 
    33140         __doc__ = """Initialisation from a mindom XML element. The list of attributes must be set by the class factory before the class is initialised""" 
    34          for a in self.attributes: 
     141         deferredHandling=False 
     142         nw1 = 0 
     143         for a in self._a.keys(): 
    35144           if el.hasAttribute( a ): 
    36              v = el.getAttribute( a ) 
     145             v = str( el.getAttribute( a ) ) 
     146             if self._a[a].type == u'xs:integer': 
     147               if self._rc.isIntStr( v ): 
     148                 v = int(v) 
     149               else: 
     150                 v = string.strip(v) 
     151                 thissect = '%s [%s]' % (self._h.title,self._h.tag) 
     152                 if v in { '',u'',' ', u' '}: 
     153                   if nw1 < 20: 
     154                     print 'WARN.050.0001: input integer non-compliant: %s: %s: "%s" -- set to zero' % (thissect,a,v) 
     155                     nw1 += 1 
     156                   v = 0 
     157                 else: 
     158                   try: 
     159                     v = int(float(v)) 
     160                     print 'WARN: input integer non-compliant: %s: %s: %s' % (thissect,a,v) 
     161                   except: 
     162                     msg = 'ERROR: failed to convert integer: %s: %s: %s' % (thissect,a,v) 
     163                     deferredHandling=True 
     164             elif self._a[a].type == u'xs:boolean': 
     165               v = v in {'true','1'} 
    37166             self.__dict__[a] = v 
    38167           else: 
    39              self.__dict__[a] = self.defaults.get( a, self.globalDefault ) 
     168             if a in {'uid'}: 
     169               thissect = '%s [%s]' % (self._h.title,self._h.tag) 
     170               print 'ERROR.020.0001: missing uid: %s' % thissect 
     171             self.__dict__[a] = self._d.defaults.get( a, self._d.glob ) 
     172 
     173           if type( self.__dict__.get( 'rowIndex', 0 ) ) != type(0): 
     174             print 'Bad row index ', el.hasAttribute( 'rowIndex' ) 
     175             raise 
     176           if deferredHandling: 
     177             print msg 
     178 
     179         self._contentInitialised = True 
    40180 
    41181     
     
    44184 
    45185  def __init__(self, configdoc='out/dreqDefn.xml', thisdoc='../workbook/trial_20150724.xml'): 
     186    self.rc = rechecks() 
    46187    self.silent = True 
    47188    self.vdef = configdoc 
     
    49190    self.nts = collections.namedtuple( 'sectdef', ['tag','label','title','id','itemLabelMode','level'] ) 
    50191    self.nti = collections.namedtuple( 'itemdef', ['tag','label','title','type','rClass','techNote'] ) 
    51     self.ntt = collections.namedtuple( 'sectinit', ['header','attributes'] ) 
     192    self.ntt = collections.namedtuple( 'sectinit', ['header','attributes','defaults'] ) 
     193    self.nt__default = collections.namedtuple( 'deflt', ['defaults','glob'] ) 
    52194    self.ntf = collections.namedtuple( 'sect', ['header','attDefn','items'] ) 
    53195 
    54196    self.coll = {} 
    55197    doc = xml.dom.minidom.parse( self.vdef  ) 
    56     self.contentDoc = xml.dom.minidom.parse( self.vsamp ) 
    57198    vl = doc.getElementsByTagName( 'table' ) 
    58     self.slist = [] 
    59199    self.tables = {} 
    60200    tables = {} 
     
    64204      t = self.parsevcfg(v) 
    65205      tables[t[0].label] = t 
    66       self.tableClasses[t[0].label] = self.itemClassFact( t.header.itemLabelMode, t.attributes.keys() ) 
    67       self.slist.append( t ) 
    68  
     206      self.tableClasses[t[0].label] = self.itemClassFact( t ) 
     207 
     208    self.contentDoc = xml.dom.minidom.parse( self.vsamp ) 
    69209    self.recordAttributeDefn = tables 
    70210    for k in tables.keys(): 
     
    108248    return self.coll 
    109249 
    110   def itemClassFact(self,itemLabelMode,attributes): 
     250  def itemClassFact(self, sectionInfo): 
    111251     class dreqItem(dreqItemBase): 
    112        """Inherits all methods from dreqItemBase""" 
     252       """Inherits all methods from dreqItemBase. 
     253 
     254USAGE 
     255----- 
     256The instanstiated object contains a single data record. The "_h" attribute links to information about the record and the section it belongs to.  
     257 
     258object._a: a python dictionary defining the attributes in each record. The keys in the dictionary correspond to the attribute names and the values are python "named tuples" (from the "collections" module). E.g. object._a['priority'].type contains the type of the 'priority' attribute. Type is expressed using XSD schema language, so "xs:integer" implies integer.  The "rClass" attribute carries information about usage. If object._a['xxx'].rClass = u'internalLink' then the record attribute provides a link to another element and object.xxx is the unique identifier of that element. 
     259 
     260object._h: a python named tuple describing the section. E.g. object.parent.header.title is the section title (E.g. "CMOR Variables") 
     261""" 
     262       _base=dreqItemBase 
    113263        
    114      dreqItem.itemLabelMode = itemLabelMode 
    115      dreqItem.attributes = attributes 
     264     dreqItem._h = sectionInfo.header 
     265     dreqItem._a = sectionInfo.attributes 
     266     dreqItem._d = sectionInfo.defaults 
     267     ##dreqItem.itemLabelMode = itemLabelMode 
     268     ##dreqItem.attributes = attributes 
     269     dreqItem._rc = self.rc 
    116270     return dreqItem 
    117271          
     
    129283        tt = self.parseicfg(i) 
    130284        idict[tt.label] = tt 
    131       return self.ntt( vtt, idict ) 
     285      deflt = self.nt__default( {}, '__unset__' ) 
     286      return self.ntt( vtt, idict, deflt ) 
    132287 
    133288  def parseicfg(self,i): 
     
    147302  """Simple container class, to hold a set of dictionaries of lists.""" 
    148303  def __init__(self, atl ): 
    149     self.uuid = {} 
     304    self.uid = {} 
    150305    for a in atl: 
    151306      self.__dict__[a] =  collections.defaultdict( list ) 
     
    156311class index(object): 
    157312  """Create an index of the document. Cross-references are generated from attributes with class 'internalLink'.  
    158 This version assumes that each record is identified by an "uuid" attribute and that there is a "var" section.  
     313This version assumes that each record is identified by an "uid" attribute and that there is a "var" section.  
    159314Invalid internal links are recorded in tme "missingIds" dictionary.  
    160 For any record, with identifier u, iref_by_uuid[u] gives a list of the section and identifier of records linking to that record. 
     315For any record, with identifier u, iref_by_uid[u] gives a list of the section and identifier of records linking to that record. 
    161316""" 
    162317 
    163318  def __init__(self, dreq): 
    164319    self.silent = True 
    165     self.uuid = {} 
    166     nativeAtts = ['uuid','iref_by_uuid','iref_by_sect','missingIds'] 
     320    self.uid = {} 
     321    self.uid2 = collections.defaultdict( list ) 
     322    nativeAtts = ['uid','iref_by_uid','iref_by_sect','missingIds'] 
    167323    naok = map( lambda x: not dreq.has_key(x), nativeAtts ) 
    168324    assert all(naok), 'This version cannot index collections containing sections with names: %s' % str( nativeAtts ) 
    169     self.var_uuid = {} 
     325    self.var_uid = {} 
    170326    self.var_by_name = collections.defaultdict( list ) 
    171327    self.var_by_sn = collections.defaultdict( list ) 
    172     self.iref_by_uuid = collections.defaultdict( list ) 
     328    self.iref_by_uid = collections.defaultdict( list ) 
    173329    irefdict = collections.defaultdict( list ) 
    174330    for k in dreq.keys(): 
     
    186342    for k in dreq.keys(): 
    187343        for i in dreq[k].items: 
    188           self.uuid[i.uuid] = (k,i) 
     344          assert i.__dict__.has_key('uid'), 'uid not found::\n%s\n%s' % (str(i._h),str(i.__dict__) ) 
     345          if self.uid.has_key(i.uid): 
     346            print 'ERROR.100.0001: Duplicate uid: %s [%s]' % (i.uid,i._h.title) 
     347            self.uid2[i.uid].append( (k,i) ) 
     348          else: 
     349            self.uid[i.uid] = (k,i) 
    189350 
    190351    self.missingIds = collections.defaultdict( list ) 
     
    197358            id2 = i.__dict__.get( k2 ) 
    198359            if id2 != '__unset__': 
    199               self.iref_by_uuid[ id2 ].append( (k2,i.uuid) ) 
    200               self.iref_by_sect[ id2 ].a[k2].append( i.uuid ) 
    201               if self.uuid.has_key( id2 ): 
     360              sect = i._h.label 
     361              self.iref_by_uid[ id2 ].append( (sect,i.uid) ) 
     362              self.iref_by_sect[ id2 ].a[sect].append( i.uid ) 
     363              if self.uid.has_key( id2 ): 
    202364                n1 += 1 
    203365              else: 
    204366                n2 += 1 
    205                 self.missingIds[id2].append( (k,k2,i.uuid) ) 
     367                self.missingIds[id2].append( (k,k2,i.uid) ) 
    206368          self.info(  'INFO:: %s, %s:  %s (%s)' % (k,k2,n1,n2) ) 
    207369 
    208370    for k in dreq.keys(): 
    209371      for i in dreq[k].items: 
    210         self.__dict__[k].uuid[i.uuid] = i 
    211         self.__dict__[k].label[i.label].append( i.uuid ) 
     372        self.__dict__[k].uid[i.uid] = i 
     373        self.__dict__[k].label[i.label].append( i.uid ) 
    212374        if dreq[k].attDefn.has_key('sn'): 
    213           self.__dict__[k].sn[i.sn].append( i.uuid ) 
     375          self.__dict__[k].sn[i.sn].append( i.uid ) 
    214376 
    215377  def info(self,ss): 
     
    217379      print ss 
    218380 
    219  
     381class ds(object): 
     382  def __init__(self,k): 
     383    self.k = k 
     384  def cmp(self,x,y): 
     385    return cmp( x.__dict__[self.k], y.__dict__[self.k] ) 
     386 
     387src1 = '../workbook/trial_20150831.xml' 
    220388class loadDreq(object): 
    221   def __init__(self,dreqXML='../docs/dreq.xml',configdoc='../docs/dreqDefn.xml' ): 
     389  def __init__(self, dreqXML='../docs/dreq.xml',configdoc='../docs/dreq2Defn.xml' ): 
    222390    self.c = config( thisdoc=dreqXML, configdoc=configdoc) 
    223391    self.coll = self.c.get() 
    224392    self.inx = index(self.coll) 
    225  
     393## 
     394## add index to Item base class .. so that it can be accessed by item instances 
     395## 
     396    dreqItemBase._inx = self.inx 
     397    dreqItemBase._indexInitialised = True 
     398    dreqItemBase._htmlStyle['CMORvar'] = {'getIrefs':['requestVar']} 
     399    dreqItemBase._htmlStyle['requestVarGroup'] = {'getIrefs':['requestVar','requestLink']} 
     400    dreqItemBase._htmlStyle['var'] = {'getIrefs':['CMORvar']} 
     401    dreqItemBase._htmlStyle['objective'] = {'getIrefs':['objectiveLink']} 
     402    dreqItemBase._htmlStyle['requestLink'] = {'getIrefs':['objectiveLink','requestItem']} 
     403    dreqItemBase._htmlStyle['exptgroup'] = {'getIrefs':['experiment']} 
     404    dreqItemBase._htmlStyle['remarks'] = {'getIrefs':['__all__']} 
     405##    dreqItemBase._htmlStyle['__general__'] = {'addRemarks':True} 
     406 
     407    self.pageTmpl = """<html><head><title>%s</title></head><body>%s</body></html>""" 
     408 
     409  def makeHtml(self,odir='./html'): 
     410    for k in self.inx.uid.keys(): 
     411      i = self.inx.uid[k][1] 
     412      ttl = 'Data Request Record: [%s]%s' % (i._h.label,i.label) 
     413      bdy = string.join( i.__html__( ), '\n' ) 
     414      oo = open( '%s/u/%s.html' % (odir,i.uid), 'w' ) 
     415      oo.write( self.pageTmpl % (ttl, bdy ) ) 
     416      oo.close() 
     417 
     418    ttl0 = 'Data Request Index' 
     419    msg0 = ['<h1>%s</h1>' % ttl0, '<ul>',] 
     420    ks = sorted( self.coll.keys() ) 
     421    for k in ks: 
     422## 
     423## sort on item label 
     424## 
     425      self.coll[k].items.sort( ds('label').cmp ) 
     426      ttl = 'Data Request Section: %s' % k 
     427      msg0.append( '<li><a href="index/%s.html">%s [%s]</a></li>\n' % (k,self.coll[k].header.title,k) ) 
     428      msg = ['<h1>%s</h1>\n' % ttl, '<ul>',] 
     429      msg.append( '<a href="../index.html">Home</a><br/>\n' ) 
     430      for i in self.coll[k].items: 
     431        m = '<li>%s: %s</li>' % ( i.label, i.__href__(odir='../u/') ) 
     432        msg.append( m ) 
     433      msg.append( '</ul>' ) 
     434      bdy = string.join( msg, '\n' ) 
     435      oo = open( '%s/index/%s.html' % (odir,k), 'w' ) 
     436      oo.write( self.pageTmpl % (ttl, bdy ) ) 
     437      oo.close() 
     438    msg0.append( '</ul>' ) 
     439    bdy = string.join( msg0, '\n' ) 
     440    oo = open( '%s/index.html' % odir, 'w' ) 
     441    oo.write( self.pageTmpl % (ttl, bdy ) ) 
     442    oo.close() 
     443     
    226444if __name__ == '__main__': 
    227445  dreq = loadDreq( ) 
Note: See TracChangeset for help on using the changeset viewer.