NovaBryan/EVE_Dump
Log | Files | 📦 下载最新源码 (.zip) | Refs | README

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})