Differences

This shows you the differences between two versions of the page.

tinyoai [2010/10/04 11:37]
yamamoto
— (current)
Line 1: Line 1:
-OAI-PMHプロバイダ用フレームワークを昔phpで書いた。pythonに移植してみる。(ドキュメント執筆中) 
- 
-<code python tinyoai.py> 
-# 
-# tinyoai for python 
-# 
- 
-import sys 
-import datetime 
-import time 
-import cgi 
- 
-# internal exception 
-class BadParams(Exception): 
-  def __init__(self, code, mes): 
-    self.code, self.mes = code, mes 
- 
-# exception for implementation 
-class OAIException(Exception): 
-  def __init__(self, code): 
-    self.code = code 
- 
-# easy tag 
-def tagged(t, v): 
-  #vv = str(v).replace("&", "&amp;").replace("<", "&lt;").replace(">", "&gt;") 
-  return "<%s>%s</%s>" % (t, v, t) 
- 
-# dict -> record header XML 
-def record_header(d): 
-  if d.has_key('deleted'): 
-    buf = ['<header status="deleted">'] 
-  else: 
-    buf = ['<header>'] 
-  buf.append(tagged("identifier", d['id'])) 
-  buf.append(tagged("datestamp", d['datestamp'])) 
-  if d.has_key('set'): 
-    for i in d['set']: 
-      buf.append(tagged("setSpec", i)) 
-  buf.append("</header>") 
-  return "".join(buf) 
- 
-# dict -> full record XML 
-def full_record(d): 
-  buf = ["<record>"] 
-  buf.append(record_header(d)) 
-  if not d.has_key('deleted'): 
-    buf.append(tagged("metadata", d['metadata'])) 
-  buf.append("</record>") 
-  return "".join(buf) 
- 
-# date string validation(yyyy-mm-dd) 
-def validate_date(s): 
-  if not s: 
-    return True 
-  try: 
-    time.strptime(s, '%Y-%m-%d') 
-  except ValueError: 
-    return False 
-  return True 
- 
-def has_key_any(d, attrs): 
-  for i in attrs: 
-    if d.has_key(i): 
-      return True 
-  return False 
- 
-def missing_key_any(d, attrs): 
-  for i in attrs: 
-    if not d.has_key(i): 
-      return True 
-  return False 
- 
- 
-# base handler class 
-class OAIPMHHandler(object): 
- 
-  def __init__(self, req, env={}): 
-    self.writer = sys.stdout 
-    self.response_body = [] 
-    self.req = req 
-    # default values 
-    self.REPOSITORY_NAME = 'My Repository' 
-    self.ADMIN_EMAIL = 'anonymous@localhost' 
-    self.DELETED_RECORD = 'transient' 
-    self.EARLIEST_DATE = '1900-01-01' 
-    self.LIST_MAX = 50 
-    if env.has_key('SERVER_NAME') and env.has_key('SCRIPT_NAME'): 
-      self.BASEURL = 'http://%s%s' % (env['SERVER_NAME'], env['SCRIPT_NAME']) 
-    else: 
-      self.BASEURL = 'http://ha.te.na/oaipmh/' 
- 
-  def set_writer(self, writer): 
-    self.writer = writer 
- 
-  def fw_initialize(self): 
-    pass 
- 
-  def fw_finalize(self): 
-    pass 
- 
-  def fw_identify(self): 
-    return [] 
- 
-  def fw_listmetadataformats(self, identifier): 
-    raise BadParams('noMetadataFormats', 'ListMetadataFormats not implemented') 
- 
-  def fw_listsets(self): 
-    raise BadParams('noSetHierarchy', 'ListSets not implemented') 
- 
-  def fw_getrecord(self, identifier, format): 
-    raise BadParams('idDoesNotExist', 'GetRecord not implemented') 
- 
-  def fw_getrecords(self, format, r_from, r_until, r_set, offset, maxrecords): 
-    raise BadParams('noRecordsMatch', 'ListRecords(ListIdentifiers) not implemented') 
- 
-  def check_request_params(self): 
-    r = self.req 
-    verb = r.get('verb', '?') 
-    if verb == 'Identify': 
-      if has_key_any(r, ('identifier', 'from', 'until', 'set', 'resumptionToken')): 
-        raise BadParams('badArgument', 'illegal argument for Identify') 
-    elif verb == 'ListMetadataFormats': 
-      if has_key_any(r, ('from', 'until', 'set', 'resumptionToken')): 
-        raise BadParams('badArgument', 'illegal argument for ListMetadataFormat') 
-      r.setdefault('identifier', '') 
-    elif verb == 'ListSets': 
-      if has_key_any(r, ('identifier', 'from', 'until', 'set', 'resumptionToken')): 
-        raise BadParams('badArgument', 'illegal argument for ListSets') 
-    elif verb == 'GetRecord': 
-      if missing_key_any(r, ('identifier', 'metadataPrefix')): 
-        raise BadParams('badArgument', 'some argument missing') 
-      if has_key_any(r, ('from', 'until', 'set', 'resumptionToken')): 
-        raise BadParams('badArgument', 'illegal argument for GetRecord') 
-      if r['identifier'].find('"') > -1: 
-        raise BadParams('badArgument', 'malformed identifier') 
-    elif verb in ('ListRecords', 'ListIdentifiers'): 
-      if r.has_key('identifier'): 
-        raise BadParams('badArgument', 'illegal argument for ListRecords(ListIdentifiers)') 
-      if r.has_key('resumptionToken'): 
-        if has_key_any(r, ('metadataPrefix', 'from', 'until', 'set')): 
-          raise BadParams('badArgument', 'illegal argument (query redundant)') 
-        else: 
-          (r['metadataPrefix'], r['offset'], r['from'], r['until'], r['set'], dummy) = (r['resumptionToken']+"!!!!!").split("!", 5) 
-          try: 
-            r['offset'] = int(r['offset']) 
-          except: 
-            raise BadParams('badResumptionToken', 'malformed resumptionToken') 
-          if not r.has_key('offset'): 
-            raise BadParams('badResumptionToken', 'malformed resumptionToken') 
-          #r['resumptionToken'] = None 
-      else: 
-        if not r.has_key('metadataPrefix'): 
-          raise BadParams('badArgument', 'metadataPrefix missing') 
-        r['offset'] = 1 
- 
-      r.setdefault('from', '') 
-      r.setdefault('until', '') 
-      r.setdefault('set', '') 
-      if not validate_date(r['from']): 
-         raise BadParams('badArgument', 'malformed date') 
-      if not validate_date(r['until']): 
-         raise BadParams('badArgument', 'malformed date') 
-      if r['until']: 
-        if (r['until'] < self.EARLIEST_DATE): 
-          raise BadParams('noRecordsMatch', 'too old record requested') 
-    else: 
-      raise BadParams('badVerb', 'illegal OAI verb') 
- 
-  def identify(self): 
-    self.response_body.append(tagged("repositoryName", self.REPOSITORY_NAME)) 
-    self.response_body.append(tagged("baseURL", self.BASEURL)) 
-    self.response_body.append(tagged("protocolVersion", "2.0")) 
-    self.response_body.append(tagged("earliestDatestamp", self.EARLIEST_DATE)) 
-    self.response_body.append(tagged("deletedRecord", self.DELETED_RECORD)) 
-    self.response_body.append(tagged("granularity", "YYYY-MM-DD")) 
-    self.response_body.append(tagged("adminEmail", self.ADMIN_EMAIL)) 
-    self.response_body.extend(self.fw_identify()) 
- 
-  def listmetadataformats(self): 
-    r = self.req 
-    try: 
-      self.response_body.extend(self.fw_listmetadataformats(r['identifier'])) 
-    except OAIException, e: 
-      if e.code == "OAI_ERROR_NO_FORMAT": 
-        raise BadParams('noMetadataFormats', 'no format available') 
-      elif e.code == "OAI_ERROR_NO_HIT": 
-        raise BadParams('idDoesNotExist', 'no such identifier available') 
- 
-  def listsets(self): 
-    try: 
-      self.response_body.extend(self.fw_listsets()) 
-    except OAIException, e: 
-      if e.code == "OAI_ERROR_NO_SET": 
-        raise BadParams('noSetHierarchy', 'no set') 
- 
-  def getrecord(self): 
-    r = self.req 
-    try: 
-      rec = self.fw_getrecord(r['identifier'], r['metadataPrefix']) 
-    except OAIException, e: 
-      if e.code == "OAI_ERROR_NO_FORMAT": 
-        raise BadParams('noMetadataFormats', 'no format available') 
-      elif e.code == "OAI_ERROR_NO_HIT": 
-        raise BadParams('idDoesNotExist', 'no such identifier available') 
-    self.response_body.append(full_record(rec)) 
- 
-  def listrecords(self, mode="r"): 
-    r = self.req 
-    if r['from']: 
-      param_from = r['from'] 
-    else: 
-      param_from = self.EARLIEST_DATE 
-    try: 
-      recs = self.fw_getrecords( 
-        r['metadataPrefix'], param_from, r['until'], 
-        r['set'], r['offset'], self.LIST_MAX + 1) 
-    except OAIException, e: 
-      if e.code == "OAI_ERROR_NO_SET": 
-        raise BadParams('noSetHierarchy', 'no set') 
-      elif e.code == "OAI_ERROR_NO_HIT": 
-        raise BadParams('noRecordsMatch', 'no records hit') 
-      elif e.code == "OAI_ERROR_NO_FORMAT": 
-        raise BadParams('noMetadataFormats', 'no such format available') 
- 
-    if len(recs) == 0: 
-      raise BadParams('noRecordsMatch', 'no records hit') 
- 
-    max_recs = min(self.LIST_MAX, len(recs)) 
- 
-    for i in xrange(max_recs): 
-      if (mode == 'i'): 
-        self.response_body.append(record_header(recs[i])) 
-      else:  ##mode == 'r' 
-        self.response_body.append(full_record(recs[i])) 
- 
-    if len(recs) > self.LIST_MAX: 
-      self.response_body.append("<resumptionToken>" + \ 
-            "!".join( 
-              (r['metadataPrefix'], str(r['offset'] + self.LIST_MAX), 
-               r['from'], r['until'], r['set'])).rstrip("!") + \ 
-            "</resumptionToken>") 
-    elif (r['offset'] > 1): 
-      self.response_body.append("<resumptionToken/>") 
- 
-  def listidentifiers(self): 
-    self.listrecords(mode="i") 
- 
-  def mainroutine(self): 
-    r = self.req 
-    self.fw_initialize() 
-    err = None 
-    try: 
-      self.check_request_params() 
-      if r['verb'] == 'Identify': 
-        self.identify() 
-      elif r['verb'] == 'ListMetadataFormats': 
-        self.listmetadataformats() 
-      elif r['verb'] == 'ListSets': 
-        self.listsets() 
-      elif r['verb'] == 'ListIdentifiers': 
-        self.listidentifiers() 
-      elif r['verb'] == 'GetRecord': 
-        self.getrecord() 
-      elif r['verb'] == 'ListRecords': 
-        self.listrecords() 
-      else: 
-        r['verb'] = None 
-        raise BadParams('badVerb', 'illegal OAI verb') 
-    except BadParams, e: 
-      err = e 
-    self.fw_finalize() 
- 
-    _w = self.writer.write 
-    _w("""<?xml version="1.0" encoding="utf-8"?> 
-<OAI-PMH xmlns="http://www.openarchives.org/OAI/2.0/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.openarchives.org/OAI/2.0/ http://www.openarchives.org/OAI/2.0/OAI-PMH.xsd">""") 
-    _w(tagged("responseDate", time.strftime('%Y-%m-%dT%H:%M:%SZ', time.gmtime()))) 
- 
-    if r.has_key('verb'): 
-      _w('<request verb="%s"' % r['verb']) 
-      if not err: 
-        if r.get('resumptionToken', ''): 
-          _w(' resumptionToken="%s" ' % cgi.escape(r['resumptionToken'])) 
-        else: 
-          for i in ('set', 'identifier', 'from', 'until', 'metadataPrefix'): 
-            if r.get(i, ''): 
-              _w(' %s="%s" ' % (i, cgi.escape(r[i]))) 
-      _w(">%s</request>" % self.BASEURL) 
-    else: 
-      _w(tagged("request", self.BASEURL)) 
- 
-    if err: 
-      _w('<error code="%s">%s</error>' % (err.code, err.mes)) 
-    else: 
-      _w(tagged(r['verb'], "".join(self.response_body))) 
- 
-    _w("</OAI-PMH>"+"\r\n") 
- 
-if __name__ == '__main__': 
-  o = OAIPMHHandler({'verb':'Identify'}) 
-  o.mainroutine() 
-</code> 
 
Recent changes RSS feed Donate Powered by PHP Valid XHTML 1.0 Valid CSS Driven by DokuWiki