Tang Cheng | 53ca487 | 2012-11-05 14:00:43 +0800 | [diff] [blame] | 1 | # -*- coding: utf-8 -*-
|
| 2 | """ 一卡通后台通讯协议包封装
|
| 3 | 所有数据都是 unicode utf-8 编码
|
| 4 | """
|
| 5 | import traceback
|
| 6 | import simplejson as json
|
| 7 |
|
Tang Cheng | d36592e | 2012-12-20 14:24:27 +0800 | [diff] [blame] | 8 | """
|
| 9 | 后台服务的字符编码
|
| 10 | """
|
| 11 | SERVICE_ENCODING = 'utf-8'
|
Tang Cheng | 53ca487 | 2012-11-05 14:00:43 +0800 | [diff] [blame] | 12 |
|
| 13 |
|
| 14 | class message_writer:
|
| 15 | """ 后台消息写接口
|
| 16 | """
|
| 17 | def __init__(self):
|
| 18 | self.clear()
|
| 19 |
|
Tang Cheng | df8e994 | 2012-12-21 10:23:57 +0800 | [diff] [blame] | 20 | def _unicode_str(self, value):
|
Tang Cheng | d36592e | 2012-12-20 14:24:27 +0800 | [diff] [blame] | 21 | if isinstance(value, str):
|
| 22 | return value.decode('utf-8')
|
| 23 | elif isinstance(value, unicode):
|
| 24 | return value
|
| 25 | else:
|
| 26 | return unicode(value)
|
| 27 |
|
Tang Cheng | 53ca487 | 2012-11-05 14:00:43 +0800 | [diff] [blame] | 28 | def clear(self):
|
| 29 | self._attr = {}
|
| 30 | self._row_data = []
|
| 31 | self._col_names = []
|
| 32 | self._row = {}
|
| 33 | self._frozen = False
|
| 34 |
|
| 35 | def attr(self, name, value):
|
| 36 | if name in self._attr:
|
| 37 | raise ValueError('Attribute [%s] already exists' % name)
|
Tang Cheng | d36592e | 2012-12-20 14:24:27 +0800 | [diff] [blame] | 38 | self._attr[name] = self._unicode_str(value)
|
Tang Cheng | 53ca487 | 2012-11-05 14:00:43 +0800 | [diff] [blame] | 39 | return self
|
| 40 |
|
| 41 | def row(self, name, value):
|
| 42 | if not (name in self._col_names):
|
| 43 | self._col_names.append(name)
|
Tang Cheng | d36592e | 2012-12-20 14:24:27 +0800 | [diff] [blame] | 44 | self._row[name] = self._unicode_str(value)
|
Tang Cheng | 53ca487 | 2012-11-05 14:00:43 +0800 | [diff] [blame] | 45 |
|
| 46 | def add_row(self):
|
| 47 | if not self._row:
|
| 48 | raise ValueError('Row has no values')
|
| 49 | self._row_data.append(self._row)
|
| 50 | self._row = {}
|
| 51 | return len(self._row_data)
|
| 52 |
|
| 53 | def append_row(self, row):
|
| 54 | if not self._col_names:
|
| 55 | for k, v in row.iteritems():
|
| 56 | self._col_names.append(k)
|
| 57 | self._row_data.append(row)
|
| 58 | else:
|
| 59 | new_row = dict([(v, row.get(v, None)) for v in self._col_names])
|
| 60 | self._row_data.append(new_row)
|
| 61 |
|
| 62 | def _normalize(self):
|
| 63 | colcnt = len(self._col_names)
|
| 64 | rowcnt = len(self._row_data)
|
| 65 | self._attr["colcnt"] = colcnt
|
| 66 | self._attr["rowcnt"] = rowcnt
|
| 67 | if colcnt > 0:
|
| 68 | self._attr["colname"] = self._col_names
|
| 69 | self._attr["coldesc"] = self._col_names
|
| 70 |
|
| 71 | if rowcnt > 0 and colcnt <= 0:
|
| 72 | raise ValueError(u'数据没有列值')
|
| 73 |
|
| 74 | if rowcnt > 0:
|
| 75 | self._attr["rowdata"] = [[row.get(colname, u"") for colname in self._col_names]
|
| 76 | for row in self._row_data]
|
| 77 | self._frozen = True
|
| 78 |
|
| 79 | def serialize(self):
|
| 80 | """ 返回 unicode utf-8编码
|
| 81 | """
|
| 82 | if not self._frozen:
|
| 83 | self._normalize()
|
Tang Cheng | d36592e | 2012-12-20 14:24:27 +0800 | [diff] [blame] | 84 | seri = json.dumps(self._attr, ensure_ascii=False, encoding=SERVICE_ENCODING)
|
Tang Cheng | 53ca487 | 2012-11-05 14:00:43 +0800 | [diff] [blame] | 85 | return seri
|
| 86 |
|
| 87 | def root(self):
|
| 88 | if not self._frozen:
|
| 89 | self._normalize()
|
| 90 | return self._attr
|
| 91 |
|
| 92 |
|
| 93 | class message_reader:
|
| 94 | """ 后台消息读接口
|
| 95 | """
|
| 96 | def __init__(self):
|
| 97 | self.clear()
|
| 98 |
|
Tang Cheng | df8e994 | 2012-12-21 10:23:57 +0800 | [diff] [blame] | 99 | def _unicode_str(self, value):
|
Tang Cheng | d36592e | 2012-12-20 14:24:27 +0800 | [diff] [blame] | 100 | if isinstance(value, str):
|
| 101 | return value.decode(SERVICE_ENCODING)
|
| 102 | elif isinstance(value, unicode):
|
| 103 | return value
|
| 104 | else:
|
| 105 | return unicode(value)
|
| 106 |
|
Tang Cheng | 53ca487 | 2012-11-05 14:00:43 +0800 | [diff] [blame] | 107 | def clear(self):
|
| 108 | """ 清空数据
|
| 109 | """
|
| 110 | self._attr = {}
|
| 111 | self._row_data = None
|
| 112 | self._col_names = []
|
| 113 | self._col_desc = []
|
| 114 | self._row_no = -1
|
| 115 | self._frozen = False
|
| 116 |
|
| 117 | def unserialize(self, message):
|
| 118 | """ 解析报文
|
| 119 | """
|
| 120 | self.clear()
|
| 121 | try:
|
Tang Cheng | d36592e | 2012-12-20 14:24:27 +0800 | [diff] [blame] | 122 | message = self._unicode_str(message)
|
Tang Cheng | 53ca487 | 2012-11-05 14:00:43 +0800 | [diff] [blame] | 123 | obj = json.loads(message)
|
| 124 | #obj = json.loads(msg.replace('\\',"\\\\"))
|
| 125 | except Exception, ex:
|
| 126 | traceback.print_exc()
|
Cheng Tang | d524c15 | 2013-02-27 09:57:47 +0800 | [diff] [blame^] | 127 | raise ValueError(u'解析报文错误,' + unicode(ex))
|
Tang Cheng | 53ca487 | 2012-11-05 14:00:43 +0800 | [diff] [blame] | 128 |
|
| 129 | if u"colname" in obj:
|
| 130 | colname = obj[u"colname"]
|
| 131 | colcnt = obj[u"colcnt"]
|
| 132 | rowcnt = obj[u"rowcnt"]
|
| 133 |
|
| 134 | if colcnt != len(colname):
|
| 135 | raise ValueError(u'记录列数定义不符')
|
| 136 |
|
| 137 | rowdata = obj[u"rowdata"]
|
| 138 | if rowcnt != len(rowdata):
|
| 139 | raise ValueError(u'记录行数定义不符')
|
| 140 |
|
| 141 | self._row_data = [dict(zip(colname, row)) for row in rowdata]
|
| 142 | self._col_names = colname
|
| 143 | self._col_desc = obj["coldesc"]
|
| 144 | else:
|
| 145 | pass
|
| 146 |
|
| 147 | for n, v in obj.iteritems():
|
| 148 | if n in (u"colname", u"colcnt", u"rowcnt", u"coldesc", u"rowdata"):
|
| 149 | continue
|
| 150 | self._attr[n] = v
|
| 151 | self._frozen = True
|
| 152 | #print self._attr
|
| 153 |
|
| 154 | def attr(self, name):
|
| 155 | """ 获取属性值,如果没有改属性返回空字符串
|
| 156 | """
|
| 157 | assert self._frozen == True
|
| 158 | if name not in self._attr:
|
| 159 | return ""
|
| 160 | return self._attr[name]
|
| 161 |
|
| 162 | def has_more_row(self):
|
| 163 | """ 判断是否有后续行
|
| 164 | """
|
| 165 | assert self._frozen == True
|
| 166 | if not self._row_data:
|
| 167 | return False
|
Tang Cheng | bee49e4 | 2012-11-19 10:56:07 +0800 | [diff] [blame] | 168 | if (self._row_no + 1) < len(self._row_data):
|
Tang Cheng | 53ca487 | 2012-11-05 14:00:43 +0800 | [diff] [blame] | 169 | return True
|
| 170 | return False
|
| 171 |
|
| 172 | def next_row(self):
|
| 173 | """ 将读取指针移到下一行
|
| 174 | """
|
| 175 | assert self._frozen == True
|
| 176 | assert self.has_more_row()
|
| 177 | self._row_no += 1
|
| 178 |
|
| 179 | _ARG_DEFAULT = []
|
| 180 |
|
| 181 | def col(self, name, default=[], strip=True):
|
| 182 | """ 获取当前行的字段值
|
| 183 | """
|
| 184 | assert self._row_no >= 0
|
| 185 | arg = self._row_data[self._row_no].get(name, None)
|
Tang Cheng | 3e7feba | 2012-11-09 16:51:27 +0800 | [diff] [blame] | 186 | if arg is None:
|
Tang Cheng | 53ca487 | 2012-11-05 14:00:43 +0800 | [diff] [blame] | 187 | if strip and default == message_reader._ARG_DEFAULT:
|
| 188 | raise IndexError(u'no such column %s' % name)
|
| 189 | return default
|
| 190 | return arg
|
| 191 |
|
| 192 | def is_eof(self):
|
| 193 | """判断是否到记录尾
|
| 194 | """
|
| 195 | if self._row_no >= len(self._row_data):
|
| 196 | return True
|
| 197 | return False
|
| 198 |
|
| 199 | def fetch_rows(self):
|
| 200 | """ 读取所有行记录
|
| 201 | """
|
| 202 | if not self.has_more_row():
|
| 203 | return
|
| 204 | self._row_no = 0
|
| 205 | for row in self._row_data:
|
| 206 | self._row_no += 1
|
| 207 | yield row
|