Ignore:
Timestamp:
05/01/07 14:46:31 (13 years ago)
Author:
lawrence
Message:

Refactoring discovery wsgi for cleaner service binding. (Done, but
there will be implications for wsgi browse which may now be broken,
but I can't test it til the database is updated).

Location:
TI07-MOLES/trunk/PythonCode/wsgi
Files:
1 added
8 edited

Legend:

Unmodified
Added
Removed
  • TI07-MOLES/trunk/PythonCode/wsgi/DIF.py

    r1955 r1958  
    66from geoUtilities import * 
    77from People import * 
    8 from ServiceBinding import ServiceBinding 
    98from AccessControl import AccessControl 
     9from ETxmlView import loadET, nsdumb 
    1010from renderEntity import renderEntity 
    11 from ETxmlView import loadET, nsdumb 
    1211 
     12class DIFService: 
     13    ''' A DIF only knows about a related URL ''' 
     14    def __init__(self,c,u,d): 
     15        ''' Take a related url tuple (content_type,url,description) and store it, using 
     16        an ndgModifier if necessary ''' 
     17        self.contentType,self.url,self.description=c,u,d 
     18    def __str__(self): 
     19        return '<a href="%s" title="%s">%s</a>'%self.contentType,self.url,self.description 
     20     
    1321class DIF: 
    1422    ''' Supports the NASA GCMD DIF format for python operations, 
    1523    note ... not a complete implementation, currently minimum to 
    1624    show a reasonable piece of content ''' 
    17     def __init__(self,xml,config,et=0): 
     25    def __init__(self,xml,et=0,debug=0,url=None): 
     26         
    1827        '''Initialise a python dif instance based on an xml document (expected 
    1928        to be an input string if et=0, otherwise an ElementTree instance) ''' 
    20         self.metadataType='DIF' 
    21         self.debug=1 
    22         self.config=config 
     29         
    2330        if et: 
    24             self.tree=xml 
    25             self.xml=ET.tostring(xml) 
     31            try: 
     32                self.tree=xml 
     33                self.xml=ET.tostring(xml) 
     34            except: 
     35                raise TypeError,'DIF input is not a valid ElementTree instance' 
    2636        else: 
    2737            try: 
    2838                self.tree=loadET(xml) 
    2939                self.xml=xml 
    30             except: 
    31                 # for some reason we can't parse the document ... 
    32                 self.tree=None 
    33                 self.xml=None 
    34              
    35         if self.tree is None: return None 
     40            except: # for some reason we can't parse the document, and it's worth knowing why 
     41                if isinstance(xml,str): 
     42                    l=min(len(xml),300)-1 
     43                    if l!=len(xml):xml=xml[0:l]+'\n...' 
     44                    raise ValueError,'DIF input cannot be parsed into an ElementTree instance:\n%s'%xml 
     45                else: 
     46                    raise TypeError,'DIF input of type [%s] needs to be a string!'%type(xml) 
     47         
     48        self.debug=debug 
     49         
     50        # now try and interpret it  
     51         
    3652        helper=nsdumb(self.tree) 
    37         self.type='DIF' 
    38         if helper.strip(self.tree.tag)!=self.type: self.tree=helper.find(self.tree,self.type) 
    39         if self.tree is None: raise TypeError, self.xml 
     53        self.metadataType='DIF' 
     54        if helper.strip(self.tree.tag)!=self.metadataType:  
     55            self.tree=helper.find(self.tree,self.metadataType) 
     56            if self.tree is None:  
     57                raise ValueError, 'DIF input does not include a DIF element:\n%s'%self.xml 
    4058         
    4159        self.entryID=helper.getText(self.tree,'Entry_ID') 
     
    4361        self.name=helper.getText(self.tree,'Entry_Title') 
    4462        self.abbreviation=self.name[0:min(5,len(self.name))] 
    45         self.binding=ServiceBinding(config,n=self.abbreviation, 
    46                     entryID=self.entryID) 
     63         
     64        # The binding is an external piece of information which says how discovery 
     65        # information for this DIF instance (or it's latest version) can be recovered  
     66        # from the Internet (of course, it may simply recover itself ...) 
     67         
     68        if url is not None: 
     69            self.binding=DIFService('DISCOVERY',url,'The discovery record for this dataset') 
     70        else: 
     71            self.binding=None 
     72                     
    4773        #Note that entity.constraints.html is about access control on the metadata, 
    4874        #and so we don't populate this here ... 
     
    76102        self.creators=[] 
    77103        # use author here because a full dif entry for creator wont necessarily exist in citation ... 
    78         self.getAuthors(helper) 
     104        self.authors=DIFAuthors(self.tree,helper) 
    79105        self.date=dateParse(helper.getText(self.tree,'Data_Set_Citation/Dataset_Release_Date'),'YYYY') 
    80106        if self.date=='': self.date='XXXX' 
     
    87113        self.services=[] 
    88114        for item in helper.findall(self.tree,'Related_URL'): 
    89             n=ServiceBinding(config,self.name) 
    90             self.services.append(n.fromRelated(item,self.entryID,helper=helper)) 
     115            self.services.append( 
     116                DIFService( 
     117                 helper.getText(item,'URL_Content_type'), 
     118                 helper.getText(item,'URL'), 
     119                 helper.getText(item,'Description') )) 
    91120          
    92121        if self.debug: 
     
    96125             
    97126             
    98     def toHTML(self): 
     127    def toHTML(self,config): 
     128 
    99129        if self.tree is not None: 
    100             renderer=renderEntity(self.config) 
     130            renderer=renderEntity(config) 
    101131            return renderer.render(self) 
    102132        else: 
    103133            return '<p>No Valid DIF</p>' 
    104134 
    105     def getAuthors(self,helper): 
    106         ''' Attempt to get dataset authorship information from a DIF ''' 
    107         # first try for an author entry in a citation 
    108         self.authors=helper.getText(self.tree,'Data_Set_Citation/Dataset_Creator') 
    109         if self.authors!='': return 
    110         # ok, now let's look for investigator(s) in the personnel section 
    111         a='' 
    112         people=helper.findall(self.tree,'Personnel') 
    113         for p in people: 
    114             role=helper.getText(p,'Role') 
    115             if role=='Investigator': 
    116                 a+='%s %s,'%(helper.getText(p,'First_Name'),helper.getText(p,'Last_Name')) 
    117         if a!='':a=a[0:-1] 
    118         self.authors=a 
    119         print a 
    120         return 
    121          
    122135 
    123136import unittest 
     
    134147        f=file(self.inputFile,'r') 
    135148        xml=f.read() 
    136         config=myConfig(self.configFile) 
    137         self.dif=DIF(xml,config) 
    138          
     149        self.dif=DIF(xml) 
     150        self.config=myConfig(self.configFile) 
    139151 
    140     def testEntryID(self): 
    141         ''' Testing the DIF object can be loaded an entry ID extracted ''' 
     152    def testEntries(self): 
     153        ''' Testing the DIF object can be loaded and some key entries extracted ''' 
    142154        print 'Entry ID [%s]'%self.dif.entryID 
     155        print 'Author [%s]'%self.dif.authors 
    143156         
    144157    def testrenderDIF(self): 
    145158        ''' Testing the conversion to html ''' 
    146159        print self.dif.timeCoverage 
    147         html=self.dif.toHTML() 
     160        html=self.dif.toHTML(self.config) 
    148161        g=file('difOutput.html','w') 
    149162        g.write(html) 
  • TI07-MOLES/trunk/PythonCode/wsgi/DiscoveryGUI.py

    r1955 r1958  
    129129            self.html+='<p> No records found </p>' 
    130130        else: 
    131             results=ws.getAllDocsAsElements() 
     131            results=ws.getLabelledDocs() 
    132132            difs=[] 
    133             for result in results: difs.append(DIF(result,self.config,et=1)) 
     133            for result in results:  
     134                url='%s?%s=%s'%(self.config.get('DISCOVERY','default'), 
     135                self.config.get('DISCOVERY','instance'),result[0]) 
     136                difs.append(DIF(result[1],url=url)) 
    134137            if results==[]: 
    135138               self.html+='<p>No results for "%s"!</p>'%searchString 
    136139            else: 
    137140               self.html+='<p>Search results for "%s":</p>'%searchString 
    138                self.html+=renderDiscoverySet(difs,state, 
     141               self.html+=renderDiscoverySet(difs,state,config=self.config, 
    139142                               summary=1,spatial=1,temporal=1,services=1) 
    140143                                
  • TI07-MOLES/trunk/PythonCode/wsgi/ETxmlView.py

    r1955 r1958  
    1212import re 
    1313 
    14  
     14class subAI: 
     15    ''' This is Alan Iwi's substitute and replace orphan <> code ''' 
     16    def __init__(self): 
     17        self.r1=re.compile('<([^>]*(<|$))') 
     18        self.r2=re.compile('((^|>)[^<]*)>') 
     19    def sub(self,s): 
     20        old='' 
     21        while s != old: 
     22            old=s 
     23            s=self.r1.sub(r'&lt;\1',s) 
     24            s=self.r2.sub(r'\1&gt;',s) 
     25        return s 
     26         
    1527class nsdumb: 
    1628    ''' provides an xpath interface to element tree nodes which 
     
    144156    < or > signs ... and that the unicode has been processed to something that  
    145157    might work''' 
    146     from sub_orphan import * 
     158     
    147159    if inputString is None: return None 
    148160    inputString=re.sub(r'&(?!\w+;)', '&amp;', inputString) 
  • TI07-MOLES/trunk/PythonCode/wsgi/People.py

    r1930 r1958  
    8181        else: 
    8282            self.data['personName'].name='Placeholder' 
     83             
     84             
     85class DIFAuthors: 
     86    ''' Attempt to get dataset authorship information from a DIF ''' 
     87    def __init__(self,elem,helper=None): 
     88        if helper is None: helper=nsdumb() 
     89        # first try for an investigator in the personnel section 
     90        authors=['Investigator','Dataset_Creator','Dataset_Author'] 
     91        people=helper.findall(elem,'Personnel') 
     92        a,e='','' 
     93        people=helper.findall(elem,'Personnel') 
     94        for p in people: 
     95            role=helper.getText(p,'Role') 
     96            if role=='Investigator': 
     97                a+='%s, %s;'%(helper.getText(p,'Last_Name'),helper.getText(p,'First_Name')) 
     98                e=helper.getText(p,'Email') 
     99        if a!='':a=a[0:-1] 
     100        if a=='': 
     101            # carry on looking in the citation element instead 
     102            a=helper.getText(elem,'Data_Set_Citation/Dataset_Creator') 
     103        self.authors,self.email=a,e 
     104    def __str__(self): 
     105        return self.authors 
     106     
     107             
     108             
  • TI07-MOLES/trunk/PythonCode/wsgi/Utilities.py

    r1955 r1958  
    151151 
    152152import unittest 
     153 
    153154class TestCase(unittest.TestCase): 
    154155    """ Tests as required """ 
  • TI07-MOLES/trunk/PythonCode/wsgi/ndgSearch.py

    r1905 r1958  
    2222    ''' Provides a client to the NDG discovery services methods exposed by the Discovery.wsdl ''' 
    2323     
    24     def __init__(self,logger=None): 
     24    def __init__(self,logger=None,tracefile=None): 
    2525        '''get an instance of the service''' 
    2626        #how do we get a different backend provider? 
    2727        loc=DiscoveryServiceLocator() 
    2828        #self.server=loc.getDiscovery(readerclass=ExpatReaderClass, 
    29         self.server=loc.getDiscoveryServicePortType(readerclass=ExpatReaderClass, 
    30         tracefile=sys.stdout) 
     29        self.server=loc.getDiscoveryServicePortType(readerclass=ExpatReaderClass,tracefile=tracefile) 
    3130        self.documents=None 
    3231        self.hits=None 
     
    9089        if response._status: 
    9190            self.serverSessionID=response._resultId 
    92             self.hits=response._hits 
     91            self.hits=response.Hits 
    9392            self.documents=response._documents 
     93        else: 
     94            self.hits=response.Hits 
    9495        self.status=[response._statusMessage,] 
     96        self.response=response 
    9597        return self.documents 
    9698 
     
    167169        return result 
    168170             
     171             
     172    def getLabelledDocs(self,format='original'): 
     173        ''' Returns all the documents in sequence in a labelled list of strings''' 
     174        if self.hits==0: return [] 
     175        filenames=self.documents.Document 
     176        responses=self.getAllDocs(format) 
     177        filenames=self.documents.Document 
     178        i=len(filenames) 
     179        j=len(responses) 
     180        if i!=j: 
     181            raise ValueError,'Internal inconsistency in search return [%s!=%s]'%(i,j) 
     182        indices=range(i) 
     183        results=[] 
     184        for i in indices: 
     185            results.append((filenames[i],responses[i])) 
     186        return results 
     187         
     188         
     189import unittest 
     190 
     191class TestCase(unittest.TestCase): 
     192     
     193    def testSearch(self): 
     194        ''' Test fundamental search capability ''' 
     195        term='temperature' 
     196        s=ndgSearch() 
     197        howmany=10 
     198        docs=s.search(term,start=1,howmany=howmany) 
     199        print 'Asked for ',howmany,' documents (there were %s hits):'%s.hits 
     200        print s.documents.Document 
     201        
     202    def testgetLabelledDocs(self): 
     203        ''' Test returning of labelled documents ''' 
     204        term='neodc' 
     205        s=ndgSearch() 
     206        r=s.search(term) 
     207        print s.status 
     208        output=s.getLabelledDocs() 
     209         
     210    def testNoReturn(self): 
     211        ''' Tests a search return with (hopefully nothing to be found)''' 
     212        term='xpabnl' 
     213        s=ndgSearch() 
     214        r=s.search(term) 
     215        print 'Hopefully this is zero: if not, expect the NoReturn test to fail:',s.hits 
     216        output=s.getLabelledDocs() 
     217        self.assertEqual(len(output),0) 
     218 
    169219if __name__=="__main__": 
    170      
    171     args=sys.argv 
    172     if len(args)>1: 
    173         term=args[1] 
    174     else: 
    175         term='temperature' 
    176      
    177     s=ndgSearch() 
    178     howmany=10 
    179     docs=s.search(term,start=1,howmany=howmany) 
    180     print s.status 
    181     print 'Asked for ',howmany,' documents, and got:' 
    182     j=0 
    183     for i in docs:  
    184         j+=1 
    185         print j,':',i 
    186          
    187      
    188     #docs=s.getAllDocs() 
    189     #print docs[0] 
    190     #print s.status 
    191      
    192     doc=s.documents[1] 
    193     r=s.getDocElement(doc) 
    194     #print et2text(r) 
     220    unittest.main() 
  • TI07-MOLES/trunk/PythonCode/wsgi/renderDiscoverySet.py

    r1955 r1958  
    33from DIF import DIF 
    44from htmlUtilities import * 
     5from renderService import * 
    56 
    6 def renderDiscoverySet(difSet,state,summary=0,services=0,spatial=0,temporal=0, 
     7def renderDiscoverySet(difSet,state,config,summary=0,services=0,spatial=0,temporal=0, 
    78    linkto='NDG_B_SERVICE',selector=None): 
    89    '''Takes a set of xml DIFS from a discovery search (difSet) and renders a  
     
    4142        ll=span(' Links: ','ndgem') 
    4243        ndg=0 
    43         ll+=d.binding.icon() 
     44        serviceRenderer=renderService(config) 
     45        if d.binding is not None: ll+=serviceRenderer.get(d.binding) 
    4446        for item in d.services: 
    4547            ll+=', ' 
    4648            #s=0 
    47             if item.serviceType == 'NDG_A_SERVICE':  
    48                 ll+=item.icon() 
     49            if item.contentType == 'NDG_A_SERVICE':  
    4950                ndg+=1 
    50             elif item.serviceType == 'NDG_B_SERVICE': 
     51            elif item.contentType == 'NDG_B_SERVICE': 
    5152                ndg+=1 
    52                 ll+=item.icon() 
    53             else: 
    54                 ll+=item.icon() 
     53            ll+=serviceRenderer.get(item) 
    5554         
    5655        if ndg<2: ndg=0 
     
    9291                    rlist[0]='%s: %s'%(span('Title','ndgem'),abbreviate(d.name,60)) 
    9392                rlist[0]+='<br/>%s: %s'%(span('Summary','ndgem'),abbreviate(d.abstract,200)) 
    94                 rlist[0]+=' '+hyperlink('(more)',d.binding.url) 
     93                if d.binding is not None: rlist[0]+=' '+hyperlink('(more)',d.binding.url) 
    9594            rlist[0]+='<br/>%s: %s.'%(span('Repository','ndgem'),d.centre.toHTML()) 
    96             if not summary: 
     95            if not summary and d.binding is not None: 
    9796                rlist[0]+=' '+hyperlink('(more)',d.binding.url) 
    9897            if services:rlist[0]+=slist 
  • TI07-MOLES/trunk/PythonCode/wsgi/renderEntity.py

    r1934 r1958  
    11from htmlUtilities import * 
     2from renderService import * 
    23 
    34class renderEntity: 
     
    3233                relatedHTML='' 
    3334 
    34         if entity.type=='dgDataEntity': 
     35        if entity.metadataType=='dgDataEntity': 
    3536                contentHTML=renderDataContent(entity) 
    3637                relatedHTML=renderGranules(entity)+relatedHTML 
    3738                serviceHTML=self.renderServices(entity) 
    38         elif entity.type=='DIF': 
     39        elif entity.metadataType=='DIF': 
    3940                contentHTML=renderDataContent(entity) 
    4041                relatedHTML=renderDataLinks(entity)+relatedHTML 
     
    6465                <tr><td class="lineHead" colspan="3"> 
    6566                <span class="headingO">Links and Services</span></td></tr>''' 
    66         xicon=hyperlink(image(self.config.get('layout','Xicon'),'[X]'),entity.binding.url+'&type=xml') 
    67         html+='<tr><td width="20%%">%s</td><td> This record rendered in XML </td></tr>'%xicon 
    68         picon=hyperlink(image(self.config.get('layout','printer'),'[Print]'),entity.binding.url+'&type=print') 
    69         html+='<tr><td>%s</td><td> Printable version of XML content</td></tr>'%picon 
     67        if entity.binding is not None: 
     68            xicon=hyperlink(image(self.config.get('layout','Xicon'),'[X]'),entity.binding.url+'&type=xml') 
     69            html+='<tr><td width="20%%">%s</td><td> This record rendered in XML </td></tr>'%xicon 
     70            picon=hyperlink(image(self.config.get('layout','printer'),'[Print]'),entity.binding.url+'&type=print') 
     71            html+='<tr><td>%s</td><td> Printable version of XML content</td></tr>'%picon 
     72        s=renderService(self.config) 
    7073        for item in entity.services: 
    71             html+='<tr><td>%s</td><td>%s</td></tr>'%(item.icon(),item.description) 
     74            html+='<tr><td>%s</td><td>%s</td></tr>'%(s.get(item),item.description) 
    7275        html+='</tbody></table>' 
    7376        
Note: See TracChangeset for help on using the changeset viewer.