Package biblio :: Package webquery :: Module isbndb
[hide private]
[frames] | no frames]

Source Code for Module biblio.webquery.isbndb

  1  #! /usr/bin/env python
 
  2  # -*- coding: utf-8 -*-
 
  3  """
 
  4  Querying the ISBNDb for bibliographic information.
 
  5  """ 
  6  # TODO: error-handling logic is correct?
 
  7  
 
  8  __docformat__ = 'restructuredtext en' 
  9  
 
 10  
 
 11  ### IMPORTS ###
 
 12  
 
 13  from impl import ElementTree, assert_or_raise 
 14  from basewebquery import BaseKeyedWebQuery 
 15  import errors 
 16  import utils 
 17  from bibrecord import * 
 18  
 
 19  __all__ = [
 
 20     'IsbndbQuery',
 
 21     'isbndb_xml_to_bibrecords',
 
 22  ] 
 23  
 
 24  
 
 25  ### CONSTANTS & DEFINES ###
 
 26  
 
 27  ISBNDB_ROOTURL = 'http://isbndb.com/api/books.xml?access_key=%(key)s&' 
 28  ISBNDB_KEY = 'OPNH8HG2' 
 29  
 
 30  FORMATS = [
 
 31     'xml',
 
 32     'bibrecord',
 
 33  ] 
 34  
 
 35  
 
 36  ### IMPLEMENTATION ###
 
 37  
 
38 -class IsbndbQuery (BaseKeyedWebQuery):
39
40 - def __init__ (self, key, timeout=5.0, limits=None):
41 """ 42 C'tor, accepting an access key. 43 """ 44 BaseKeyedWebQuery.__init__ (self, root_url=ISBNDB_ROOTURL, key=key, 45 timeout=timeout, limits=limits)
46
47 - def query_service (self, index, value, results):
48 """ 49 A generalised query for ISBNdb. 50 51 :Parameters: 52 index : string 53 The index to search in ISBNdb. 54 value : string 55 The value to search for in the index.. 56 results : iterable 57 A list of the data to include in the response. 58 59 :Returns: 60 The response received from the service. 61 62 This serves a general way of accessing all the methods available for 63 ISBNdb. It also normalises the ISBN to a suitable form for submission. 64 Note that it is probably possible to form a bad query with the wrong 65 combination of parameters. 66 67 """ 68 ## Preconditions & preparation: 69 if (index == 'isbn'): 70 value = utils.normalize_isbn (value) 71 ## Main: 72 sub_url = 'index1=%(indx)s&value1=%(val)s' % { 73 'indx': index, 74 'val': value, 75 } 76 if (results): 77 res_str = ','.join (list(results)) 78 sub_url += '&results=' + res_str 79 return self.request (sub_url)
80
81 - def query_bibdata_by_isbn (self, isbn, format='bibrecord'):
82 """ 83 Return publication data based on ISBN. 84 85 :Parameters: 86 isbn : string 87 An ISBN-10 or ISBN-13. 88 89 format : string 90 The desired format for the results. 91 92 :Returns: 93 Publication data in Xisbn XML format. 94 95 """ 96 ## Preconditions & preparation: 97 # check and select appropriate format 98 assert (format in FORMATS), \ 99 "unrecognised format '%s', must be one of %s" % (format, FORMATS) 100 ## Main: 101 results = self.query_service (index='isbn', value=isbn, results=[ 102 'authors', 'subjects', 'texts', 'details']) 103 if (format is 'bibrecord'): 104 results = isbndb_xml_to_bibrecords (results) 105 ## Postconditions & return: 106 return results
107
108 - def query_author_by_name (self, name, fields=None):
109 """ 110 Search author data based on name. 111 112 :Parameters: 113 name : string 114 The name to search for. 115 116 fields : iterable 117 What result blocks to return.. 118 119 :Returns: 120 Publication data in ISBNdb XML format. 121 122 """ 123 ## Main: 124 results = self.query_service (index='name', value=name, results=fields) 125 ## Postconditions & return: 126 return results
127
128 - def query_author_by_id (self, auth_id, fields=None):
129 """ 130 Search author data based on ID. 131 132 :Parameters: 133 auth_id : string 134 The ISBN "person_id" to search for. 135 136 fields : iterable 137 What result blocks to return.. 138 139 :Returns: 140 Publication data in ISBNdb XML format. 141 142 """ 143 ## Main: 144 results = self.query_service (index='person_id', value=name, results=fields) 145 ## Postconditions & return: 146 return results
147 148
149 -def isbndb_xml_to_bibrecords (xml_txt):
150 ## Main: 151 # turn into an xml tree 152 root = ElementTree.fromstring (xml_txt) 153 assert_or_raise (root.tag == 'ISBNdb', errors.ParseError, 154 "ISBNdb document root should be 'ISBNdb', not '%s'" % root.tag) 155 assert_or_raise (len (root) == 1, errors.ParseError, 156 "ISBNdb document root has wrong number of children (%s)" % len (root)) 157 # grab list result 158 booklist_elem = root[0] 159 assert_or_raise (booklist_elem.tag == 'BookList', errors.ParseError, 160 "ISBNdb document should contain 'BookList', not '%s'" % 161 booklist_elem.tag) 162 # for every result ... 163 bibrecs = [] 164 for bdata in booklist_elem.findall ('BookData'): 165 newrec = BibRecord() 166 newrec.pubtype = 'book' 167 newrec.title = (bdata.findtext ('TitleLong') or u'').strip() 168 newrec.abstract = (bdata.findtext ('Summary') or u'').strip() 169 newrec.note = (bdata.findtext ('Notes') or u'').strip() 170 newrec.keywords = [e.text.strip() for e in bdata.findall ('Subject')] 171 authors = [] 172 author_elem = bdata.find ('Authors') 173 if (author_elem): 174 author_strs = [e.text.strip() for e in author_elem.findall 175 ('Person')] 176 authors = [utils.parse_single_name (a) for a in author_strs] 177 else: 178 author_elem = bdata.find ('AuthorsText') 179 if (author_elem): 180 edited, authors_str = utils.parse_editing_info (author_elem.text) 181 newrec.edited = edited 182 authors = utils.parse_names (authors_str) 183 newrec.authors = authors 184 newrec.id = bdata.attrib['isbn'] 185 pub_elem = bdata.find ('PublisherText') 186 if (pub_elem): 187 newrec.publisher, newrec.city, newrec.year = \ 188 parse_publisher (pub_elem.text) 189 bibrecs.append (newrec) 190 ## Postconditions & return: 191 return bibrecs
192 193 194 195 ### TEST & DEBUG ### 196
197 -def _doctest ():
198 import doctest 199 doctest.testmod()
200 201 202 ### MAIN ### 203 204 if __name__ == '__main__': 205 _doctest() 206 207 208 ### END ###################################################################### 209