datatable.py (10837B)
1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\carbon\common\script\util\datatable.py 2 import datetime 3 4 class DataTableException(Exception): 5 pass 6 7 8 class DataTableQuery(object): 9 10 def __init__(self): 11 self.__query_list = {} 12 13 def filter(self, tq): 14 utq = tq.upper() 15 pos_list = [] 16 i = utq.find('SELECT') 17 if i > -1: 18 pos_list.append((i, 'SELECT')) 19 i = utq.find('WHERE') 20 if i > -1: 21 pos_list.append((i, 'WHERE')) 22 i = utq.find('ORDER BY') 23 if i > -1: 24 pos_list.append((i, 'ORDER BY')) 25 i = utq.find('LIMIT') 26 if i > -1: 27 pos_list.append((i, 'LIMIT')) 28 i = utq.find('OFFSET') 29 if i > -1: 30 pos_list.append((i, 'OFFSET')) 31 pos_list.sort(lambda x, y: cmp(x[0], y[0])) 32 for x in range(0, len(pos_list)): 33 if x < len(pos_list) - 1: 34 t1, t2 = pos_list[x], pos_list[x + 1] 35 self.__query_list[t1[1]] = tq[t1[0]:t2[0]].replace(t1[1], '').strip() 36 else: 37 t1 = pos_list[x] 38 self.__query_list[t1[1]] = tq[int(t1[0]):].replace(t1[1], '').strip() 39 40 return self 41 42 def query(self, table_def, table_rows): 43 if len(self.__query_list) == 0: 44 return (table_def, table_rows) 45 if 'SELECT' in self.__query_list: 46 sel = self.__query_list['SELECT'].replace(' ', '').split(',') 47 skip_idx = [] 48 columns = {} 49 for x in range(0, len(table_def)): 50 columns[table_def[x][0]] = x 51 if table_def[x][0] not in sel: 52 skip_idx.append(x) 53 54 table_def = filter(lambda x: x[0] in sel, table_def) 55 if 'ORDER BY' in self.__query_list: 56 idx = columns[self.__query_list['ORDER BY']] 57 table_rows.sort(lambda x, y: cmp(x[idx], y[idx])) 58 if len(skip_idx) > 0: 59 t_rows = [] 60 for tr in table_rows: 61 t_row = [] 62 idx = 0 63 for t in tr: 64 if idx not in skip_idx: 65 t_row.append(t) 66 idx += 1 67 68 t_rows.append(t_row) 69 70 table_rows = t_rows 71 limit = int(self.__query_list['LIMIT']) if 'LIMIT' in self.__query_list else len(table_rows) 72 offset = 0 if 'OFFSET' not in self.__query_list else int(self.__query_list['OFFSET']) 73 return (table_def, table_rows[offset:offset + limit]) 74 75 76 class DataTable(object): 77 78 def __init__(self, table_def = None, table_rows = [], version = '0.6', tqx = None, tq = None): 79 self.__allowedColumn = ['boolean', 80 'number', 81 'string', 82 'date', 83 'datetime', 84 'timeofday'] 85 if tq is not None and table_def is not None: 86 tableQuery = DataTableQuery() 87 self.__table_def, self.__rows = tableQuery.filter(tq).query(table_def, table_rows) 88 else: 89 self.__table_def = table_def 90 self.__rows = table_rows 91 self.__version = version 92 self.__tqxdict = {} 93 if tqx is not None: 94 for x in tqx.split(';'): 95 args = x.split(':') 96 self.__tqxdict[args[0]] = args[1] 97 98 self.__errors = [] 99 self.__output = [] 100 101 def Render(self, response, output = 'datatable'): 102 output = output.lower() 103 if output == 'xml': 104 response.contentType = 'application/xml; charset=utf-8' 105 return self.toXml() 106 elif output == 'csv': 107 return self.toCsv() 108 elif output == 'datatable': 109 response.contentType = 'text/HTML; charset=utf-8' 110 return self.toDataTable() 111 elif output == 'htmltable': 112 response.contentType = 'text/HTML; charset=utf-8' 113 return self.toHtmlTable() 114 elif output == 'rss': 115 response.contentType = 'application/xml; charset=utf-8' 116 return self.toRss() 117 else: 118 return 'unknown output(%s)' % output 119 120 def toRss(self, title, description, link): 121 reply = [] 122 reply.append('<?xml version="1.0" encoding="UTF-8" ?>') 123 reply.append('<rss version="2.0">') 124 reply.append('<channel>') 125 reply.append('\t<title>%s</title>' % title) 126 reply.append('\t<description>%s</description>' % description) 127 reply.append(' <link>%s</link>' % link) 128 for r in self.__rows: 129 if len(r) is not 5: 130 raise DataTableException('RSS feed must contain [title,link,description,uniqueId,pubDate]') 131 reply.append('\t<item>') 132 if r[0] is not None: 133 reply.append(' <title>%s</title>' % r[0]) 134 if r[1] is not None: 135 reply.append(' <link>%s</link>' % r[1]) 136 if r[2] is not None: 137 reply.append(' <description><![CDATA[\n%s\n]]></description>' % r[2]) 138 if r[3] is not None: 139 reply.append(' <guid>%s</guid>' % r[3]) 140 if r[4] is not None: 141 reply.append(' <pubDate>%s</pubDate>' % r[4]) 142 reply.append('\t</item>') 143 144 reply.append('</channel>') 145 reply.append('</rss>') 146 return '\n'.join(reply) 147 148 def toDataTable(self): 149 reply = [] 150 reply.append(self.__Column(self.__table_def)) 151 reply.append(',') 152 reply.append(self.__Rows(self.__rows)) 153 return self.__Wrapper(reply) 154 155 def toCsv(self): 156 reply = [] 157 reply.append(', '.join(map(lambda x: x[0], self.__table_def))) 158 reply.append('\n'.join([ ', '.join([ unicode(y) for y in x ]) for x in self.__rows ])) 159 return '\n'.join(reply) 160 161 def toHtmlTable(self): 162 reply = [] 163 reply.append('<table>') 164 reply.append('<tr><td>' + '</td><td>'.join(map(lambda x: x[0], self.__table_def)) + '</td></tr>\n') 165 reply.append('\n'.join([ '<tr><td>%s</td></tr>' % '</td><td>'.join(x) for x in self.__rows ])) 166 reply.append('</table>') 167 return '\n'.join(reply) 168 169 def toXml(self): 170 reply = [] 171 reply.append('<?xml version="1.0" encoding="UTF-8" ?>') 172 reply.append('<root>\n<rows>') 173 for r in self.__rows: 174 reply.append('<row>') 175 row_idx = 0 176 for x in self.__table_def: 177 reply.append('<%(name)s>%(row)s</%(name)s>' % {'name': x[0], 178 'row': r[row_idx]}) 179 row_idx += 1 180 181 reply.append('</row>') 182 183 reply.append('</rows>\n</root>') 184 return '\n'.join(reply) 185 186 def __Column(self, columns): 187 temp = [] 188 if not columns or not isinstance(columns, (list, tuple)): 189 raise DataTableException('Table definition is wrong!') 190 for h in self.__table_def: 191 if len(h) != 4 or h[2] not in self.__allowedColumn: 192 raise DataTableException('Table column %s definition is wrong!' % h) 193 temp.append("{id:'%s',label:'%s',type:'%s',pattern:'%s'}" % (h[0], 194 h[1], 195 h[2], 196 h[3])) 197 198 return ''.join(['cols:[', ','.join(temp), ']']) 199 200 def __Row(self, row, rownum): 201 temp = [] 202 if not row or not isinstance(row, (list, tuple)) or len(row) != len(self.__table_def): 203 raise DataTableException('Table row has problems! %s' % row) 204 cidx = 0 205 td = self.__table_def 206 for r in row: 207 typeName = td[cidx][2] 208 if typeName == 'boolean': 209 if not isinstance(r, bool): 210 raise DataTableException("Row doesn't contain bool '%s'. Line(column): %i(%i)" % (row, cidx, rownum)) 211 temp.append('{v:%s}' % str(r).lower()) 212 elif typeName == 'number': 213 if isinstance(r, (int, long, float)): 214 temp.append('{{v:{}}}'.format(r)) 215 else: 216 raise DataTableException("Row doesn't contain number '%s'. Line(column): %i(%i). Value: %s" % (row, 217 cidx, 218 rownum, 219 r)) 220 elif typeName == 'string': 221 temp.append("{v:'%s'}" % str(r)) 222 elif typeName == 'date': 223 if not isinstance(r, datetime.date): 224 raise DataTableException("Row doesn't contain date '%s'. Line(column): %i(%i)" % (row, cidx, rownum)) 225 temp.append('{v:new Date(%(year)s,%(month)s,%(day)s)}' % {'year': r.year, 226 'month': r.month - 1, 227 'day': r.day}) 228 elif typeName == 'datetime': 229 if not isinstance(r, datetime.datetime): 230 raise DataTableException("Row doesn't contain date '%s'. Line(column): %i(%i)" % (row, cidx, rownum)) 231 temp.append('{v:new Date(%(year)s,%(month)s,%(day)s,%(hour)s,%(minute)s,%(second)s)}' % {'year': r.year, 232 'month': r.month - 1, 233 'day': r.day, 234 'hour': r.hour, 235 'minute': r.minute, 236 'second': r.second}) 237 elif typeName == 'timeofday': 238 if not isinstance(r, datetime.datetime): 239 raise DataTableException("Row doesn't contain date '%s'. Line(column): %i(%i)" % (row, cidx, rownum)) 240 temp.append('{v:[%(hour)s,%(minute)s,%(second)s]}' % {'year': r.year, 241 'month': r.month - 1, 242 'day': r.day, 243 'hour': r.hour, 244 'minute': r.minute, 245 'second': r.second}) 246 cidx += 1 247 248 return ''.join(['{c:[', ','.join(temp), ']}']) 249 250 def __Rows(self, rows): 251 temp = [] 252 ridx = 0 253 for row in rows: 254 temp.append(self.__Row(row, ridx)) 255 ridx += 1 256 257 return ''.join(['rows:[', ','.join(temp), ']']) 258 259 def __Wrapper(self, data): 260 version = "version:'%s'" % self.__version 261 reqId = "reqId:'%s'" % self.__tqxdict['reqId'] if 'reqId' in self.__tqxdict else '' 262 status = "status:'ok'" if len(self.__errors) == 0 else "status:'error'" 263 errors = ''.join(['errors:[{', ','.join(self.__errors), '}]']) if len(self.__errors) > 0 else '' 264 table = 'table:{%s}' % ''.join(data) if len(self.__errors) == 0 else '' 265 return ''.join(['google.visualization.Query.setResponse({', ','.join([version, 266 reqId, 267 status, 268 table if errors == '' else errors]), '});']) 269 270 def __Error(self, error_number, error_message): 271 self.__errors.append("{reason:'internal_error',message:'Error in line:%(line)s. Error: %(message)s'}" % {'line': error_number, 272 'message': error_message})