Package sword2 :: Module deposit_receipt
[hide private]
[frames] | no frames]

Source Code for Module sword2.deposit_receipt

  1  #!/usr/bin/env python 
  2  # -*- coding: utf-8 -*- 
  3   
  4  """ 
  5  This module provides `Deposit_Receipt`, a convenient class for extracting information from the Deposit Receipts sent back by the  
  6  SWORD2-compliant server for many transactions. 
  7   
  8  #BETASWORD2URL 
  9  See Section 10. Deposit Receipt: http://sword-app.svn.sourceforge.net/viewvc/sword-app/spec/trunk/SWORDProfile.html?revision=HEAD#depositreceipt 
 10   
 11  """ 
 12   
 13  from sword2_logging import logging 
 14  d_l = logging.getLogger(__name__) 
 15   
 16  from atom_objects import Category 
 17   
 18  from compatible_libs import etree 
 19  from utils import NS, get_text 
 20   
21 -class Deposit_Receipt(object):
22 - def __init__(self, xml_deposit_receipt=None, dom=None, response_headers={}, location=None, code=0):
23 """ 24 `Deposit_Receipt` - provides convenience methods for extracting information from the Deposit Receipts sent back by the 25 SWORD2-compliant server for many transactions. 26 27 #BETASWORD2URL 28 See Section 10. Deposit Receipt: http://sword-app.svn.sourceforge.net/viewvc/sword-app/spec/trunk/SWORDProfile.html?revision=HEAD#depositreceipt 29 30 Transactions carried out by `sword2.Connection` will return a `Deposit_Receipt` object, if a deposit receipt document is sent back by the server. 31 32 Usage: 33 34 >>> from sword2 import Deposit_Receipt 35 36 .... get the XML text for a Deposit Receipt in the variable `doc` 37 38 # Parse the response: 39 >>> dr = Deposit_Receipt(xml_deposit_receipt = doc) 40 41 # Check that the response is parsable (valid XML) and is SWORD2-compliant 42 >>> assert dr.parsed == True 43 >>> assert dr.valid == True 44 45 Availible attributes: 46 47 Atom convenience attribs -- corresponds to (type of object that is held) 48 `self.title` -- <atom:title> (`str`) 49 `self.id` -- <id> (`str`) 50 `self.updated` -- <updated> (`str`) 51 `self.summary` -- <atom:summary> (`str`) 52 `self.categories` -- <category> (`list` of `sword2.Category`) 53 54 IRI/URIs 55 `self.edit` -- The Edit-IRI (`str`) 56 <link rel="edit"> 57 `self.edit_media` -- The Edit-Media-IRI (`str`) 58 <link rel="edit-media"> 59 `self.edit_media_feed` -- The Edit-Media-IRI [Atom Feed] (`str`) 60 <link rel="edit-media" type="application/atom+xml;type=feed"> 61 `self.alternate` -- A link which, according to the spec, (`str`) 62 "points to the splash page of the item on the server" 63 `self.se_iri` -- The SWORD2 Edit IRI (SE-IRI), defined by (`str`) 64 <link rel="http://purl.org/net/sword/terms/add"> 65 which MAY be the same as the Edit-IRI 66 67 `self.cont_iri` -- The Content-IRI (`str`) 68 eg `src` from <content type="application/zip" src="http://swordapp.org/cont-IRI/43/my_deposit"/> 69 `self.content` -- All Content-IRIs (`dict` with the src or Content-IRI as the key, with a `dict` of the other attributes as its value 70 71 `self.links` -- All links elements in a `dict`, with the 'rel' value being used as its key. The values of this are `list`s 72 with a `dict` of attributes for each item, corresponding to the information in a single <link> element. 73 74 SWORD2 links for "http://purl.org/net/sword/terms/originalDeposit" and "http://purl.org.net/sword/terms/derivedResource" 75 are to be found in `self.links` 76 77 eg 78 >>> dr.links.get("http://purl.org.net/sword/terms/derivedResource") 79 {'href': "....", 'type':'application/pdf'} 80 81 82 General metadata: 83 `self.metadata` -- Simple metadata access. 84 A `dict` where the keys are equivalent to the prefixed element names, with an underscore(_) replacing the colon (:) 85 eg "<dcterms:title>" in the deposit receipt would be accessible in this attribute, under 86 the key of 'dcterms_title' 87 88 eg 89 >>> dr.metadata.get("dcterms_title") 90 "The Origin of Species" 91 92 >>> dr.metadata.get("dcterms_madeupelement") 93 `None` 94 95 `self.packaging` -- sword:packaging elements declaring the formats that the Media Resource can be retrieved in (`list` of `str`) 96 97 `self.response_headers` -- The HTTP response headers that accompanied this receipt 98 99 `self.location` -- The location, if given (from HTTP Header: "Location: ....") 100 """ 101 self.parsed = False 102 self.response_headers=response_headers 103 self.location = location 104 self.content = None 105 self.code = code 106 self.metadata = {} 107 self.links = {} 108 self.edit = None 109 self.edit_media = None 110 self.edit_media_feed = None 111 self.alternate = None 112 self.se_iri = None 113 # Atom convenience attribs 114 self.title = None 115 self.id = None 116 self.updated = None 117 self.summary = None 118 119 self.packaging = [] 120 self.categories = [] 121 self.content = {} 122 self.cont_iri = None 123 124 if xml_deposit_receipt: 125 try: 126 self.dom = etree.fromstring(xml_deposit_receipt) 127 self.parsed = True 128 except Exception, e: 129 d_l.error("Was not able to parse the deposit receipt as XML.") 130 return 131 self.handle_metadata() 132 elif dom != None: 133 self.dom = dom 134 self.parsed = True 135 self.handle_metadata()
136
137 - def handle_metadata(self):
138 """Method that walks the `etree.SubElement`, assigning the information to the objects attributes.""" 139 for e in self.dom.getchildren(): 140 for nmsp, prefix in NS.iteritems(): 141 if str(e.tag).startswith(prefix % ""): 142 _, tagname = e.tag.rsplit("}", 1) 143 field = "%s_%s" % (nmsp, tagname) 144 d_l.debug("Attempting to intepret field: '%s'" % field) 145 if field == "atom_link": 146 self.handle_link(e) 147 elif field == "atom_content": 148 self.handle_content(e) 149 elif field == "atom_generator": 150 for ak,av in e.attrib.iteritems(): 151 if not e.text: 152 e.text = "" 153 e.text += " %s:\"%s\"" % (ak, av) 154 self.metadata[field] = e.text.strip() 155 elif field == "sword_packaging": 156 self.packaging.append(e.text) 157 else: 158 if field == "atom_title": 159 self.title = e.text 160 if field == "atom_id": 161 self.id = e.text 162 if field == "atom_updated": 163 self.updated = e.text 164 if field == "atom_summary": 165 self.summary = e.text 166 if field == "atom_category": 167 self.categories.append(Category(dom=e)) 168 if self.metadata.has_key(field): 169 if isinstance(self.metadata[field], list): 170 self.metadata[field].append(e.text) 171 else: 172 self.metadata[field] = [self.metadata[field], e.text] 173 else: 174 self.metadata[field] = e.text
175 203 204
205 - def handle_content(self, e):
206 """Method to intepret the <atom:content> elements.""" 207 # eg <content type="application/zip" src="http://swordapp.org/cont-IRI/43/my_deposit"/> 208 if e.attrib.has_key("src"): 209 src = e.attrib['src'] 210 info = dict(e.attrib).copy() 211 del info['src'] 212 self.content[src] = info 213 self.cont_iri = src
214
215 - def to_xml(self):
216 """Convenience method for outputing the DOM as a (byte)string.""" 217 return etree.tostring(self.dom)
218
219 - def __str__(self):
220 """Method for producing a human-readable report about the information in this object, suitable 221 for CLI or other logging. 222 223 NB does not report all information, just key parts.""" 224 _s = [] 225 for k in sorted(self.metadata.keys()): 226 _s.append("%s: '%s'" % (k, self.metadata[k])) 227 if self.edit: 228 _s.append("Edit IRI: %s" % self.edit) 229 if self.edit_media: 230 _s.append("Edit-Media IRI: %s" % self.edit_media) 231 if self.se_iri: 232 _s.append("SWORD2 Add IRI: %s" % self.se_iri) 233 for c in self.categories: 234 _s.append(str(c)) 235 if self.packaging: 236 _s.append("SWORD2 Package formats available: %s" % self.packaging) 237 if self.alternate: 238 _s.append("Alternate IRI: %s" % self.alternate) 239 for k, v in self.links.iteritems(): 240 _s.append("Link rel:'%s' -- %s" % (k, v)) 241 return "\n".join(_s)
242