Package acis_xmlrpc :: Module responses
[hide private]
[frames] | no frames]

Source Code for Module acis_xmlrpc.responses

  1  """ 
  2  Definition of ACIS XML-RPC response classes. 
  3  @since: May 2007 
  4  @author: Grant Kelly 
  5  """ 
  6   
  7  from mx import DateTime 
  8  from cStringIO import StringIO 
  9  import simplejson 
 10   
 11  from acis_xmlrpc.config import * 
 12  from acis_xmlrpc.var_table import global_var_dict 
 13   
14 -class ACISResponse(object):
15 """ 16 Base class for ACIS XML-RPC Responses. 17 """
18 - def as_format(self, fmt):
19 """ 20 A wrapper to the available output formats. 21 """ 22 if fmt in DELIMITED_FORMATS.keys(): 23 return self.as_delimited(DELIMITED_FORMATS[fmt]) 24 elif hasattr(self, 'as_%s'%fmt): 25 f = getattr(self, 'as_%s'%fmt) 26 return f() 27 else: 28 return self.__str__()
29 30
31 -class ACISErrorResponse(ACISResponse):
32 """ 33 Accepts exceptions and returns error messages. 34 Acts as a wrapper to delivering exceptions. 35 """ 36 error_code = 400
37 - def __init__(self, exc):
38 """ 39 @param exc: The exception instance. 40 @type exc: Exception 41 """ 42 self.exc = exc
43 - def __str__(self):
44 return self.as_json()
45 - def as_json(self):
46 d = { 'code': self.error_code, 'msg': str(self.exc) } 47 return simplejson.dumps(d)
48 - def as_string(self):
49 return str(self.exc)
50
51 -class ACISDataResponse(ACISResponse):
52 """ 53 Acts as a wrapper to delivering data in different formats. 54 @todo: Add flags to output 55 """ 56 status_code = 200
57 - def __init__(self, data, options):
58 """ 59 @param data: The data dictionary. 60 @param options: The options used to create the data. 61 62 C{data} should have the following structure:: 63 64 data = { 65 'code': # Status code 66 'data': { 67 'dates': # List of date tuples corresponding to vars 68 <stn>: { 69 '<var>_code': # Status code for this variable 70 '<var>': # List of variable vaules (actual data) 71 '<var>_valid_flags': # List of valid flags for <var> 72 '<var>_flags': # List of measurement flags for <var> 73 } 74 } 75 } 76 """ 77 self.data = data 78 self.options = options
79
80 - def __str__(self):
81 return self.as_json()
82
83 - def as_json(self):
84 """ 85 @return: data as a json string 86 """ 87 return simplejson.dumps({ 88 'code': self.status_code, 89 'data': self.data, 90 })
91
92 - def as_delimited(self, delim=','):
93 """ 94 @param delim: The string delimiter 95 @returns: A string of data delimited by C{delim}. 96 @rtype: string 97 """ 98 data = self.data 99 options = self.options 100 numdays = (options.end - options.start).days # TODO: should handle any time interval 101 vars = options.var 102 var_flags = ["%s_flag" % v for v in vars] 103 ret = StringIO() 104 # write headers 105 headers = ['stn','stntype','date'] 106 for v,vf in zip(vars, var_flags): 107 headers.append(v) 108 headers.append(vf) 109 ret.write(delim.join(headers)) 110 ret.write(LINE_ENDS) 111 for stn,stntype in zip(options.stn,options.stntype): 112 if data[stn]['code'] != CODE_STN_NOT_FOUND: 113 for day in xrange(numdays): 114 line = [stn,stntype] 115 if data.has_key('dates'): 116 try: 117 daydate = DateTime.Date(*data['dates'][day]) 118 line.append(daydate.strftime(options.dateformat[1])) 119 except IndexError: # numdays is wrong because given date was invalid 120 continue 121 else: 122 line.append('') 123 for v in xrange(len(vars)): 124 d = data[stn] 125 var = vars[v] 126 127 try: 128 if d[var + '_valid_flag'][day]: 129 line.append(global_var_dict[var]['fmt'] % d[var][day]) 130 else: 131 line.append('') 132 except: 133 line.append('') 134 # Always print a flag column 135 try: 136 line.append(str(d[var + '_flag'][day])) 137 except: 138 line.append('') 139 140 ret.write(delim.join(line)) 141 ret.write(LINE_ENDS) 142 return ret.getvalue()
143
144 -class ACISMetaDataResponse(ACISResponse):
145 """ 146 Acts as a wrapper to delivering metadata in different formats. 147 """ 148 status_code = 200
149 - def __init__(self, data, options):
150 """ 151 @param data: The metadata dictionary. 152 @param options: The options used to create the metadata. 153 154 C{data} should have the following structure:: 155 156 data = { 157 'code': # Status code 158 'data': { 159 'ucan_id': {<meta dictionary>} 160 } 161 } 162 """ 163 self.data = data 164 self.options = options
165
166 - def __str__(self):
167 return self.as_json()
168
169 - def as_json(self):
170 """ 171 @return: metadata as json string. 172 """ 173 return simplejson.dumps({ 174 'code': self.status_code, 175 'data': self.data, 176 })
177
178 - def as_delimited(self, delim=','):
179 """ 180 @param delim: The string delimiter 181 @returns: A string of metadata delimited by C{delim}. 182 @rtype: string 183 """ 184 data = self.data 185 ret = StringIO() 186 first = True # write headers if first line 187 for ucan_id, meta in data.iteritems(): 188 if first: 189 first = False 190 keys = meta.keys() 191 keys.sort() # use some order? 192 ret.write(delim.join(keys)) 193 ret.write(LINE_ENDS) 194 line = [] 195 for key in keys: 196 try: 197 line.append(str(meta[key])) 198 except KeyError: 199 line.append('') 200 ret.write(delim.join(line)) 201 ret.write(LINE_ENDS) 202 return ret.getvalue()
203