Package web2py :: Package gluon :: Package contrib :: Package pymysql :: Module converters
[hide private]
[frames] | no frames]

Source Code for Module web2py.gluon.contrib.pymysql.converters

  1  import re 
  2  import datetime 
  3  import time 
  4   
  5  from constants import FIELD_TYPE, FLAG 
  6  from charset import charset_by_id 
  7   
  8  try: 
  9      set 
 10  except NameError: 
 11      try: 
 12          from sets import BaseSet as set 
 13      except ImportError: 
 14          from sets import Set as set 
 15   
 16  ESCAPE_REGEX = re.compile(r"[\0\n\r\032\'\"\\]") 
 17  ESCAPE_MAP = {'\0': '\\0', '\n': '\\n', '\r': '\\r', '\032': '\\Z', 
 18                '\'': '\\\'', '"': '\\"', '\\': '\\\\'} 
 19   
20 -def escape_item(val, charset):
21 if type(val) in [tuple, list, set]: 22 return escape_sequence(val, charset) 23 if type(val) is dict: 24 return escape_dict(val, charset) 25 if hasattr(val, "decode") and not isinstance(val, unicode): 26 # deal with py3k bytes 27 val = val.decode(charset) 28 encoder = encoders[type(val)] 29 val = encoder(val) 30 if type(val) is str: 31 return val 32 val = val.encode(charset) 33 return val
34
35 -def escape_dict(val, charset):
36 n = {} 37 for k, v in val.items(): 38 quoted = escape_item(v, charset) 39 n[k] = quoted 40 return n
41
42 -def escape_sequence(val, charset):
43 n = [] 44 for item in val: 45 quoted = escape_item(item, charset) 46 n.append(quoted) 47 return tuple(n)
48
49 -def escape_set(val, charset):
50 val = map(lambda x: escape_item(x, charset), val) 51 return ','.join(val)
52
53 -def escape_bool(value):
54 return str(int(value))
55
56 -def escape_object(value):
57 return str(value)
58 59 escape_int = escape_long = escape_object 60
61 -def escape_float(value):
62 return ('%.15g' % value)
63
64 -def escape_string(value):
65 return ("'%s'" % ESCAPE_REGEX.sub( 66 lambda match: ESCAPE_MAP.get(match.group(0)), value))
67
68 -def escape_unicode(value):
69 return escape_string(value)
70
71 -def escape_None(value):
72 return 'NULL'
73
74 -def escape_timedelta(obj):
75 seconds = int(obj.seconds) % 60 76 minutes = int(obj.seconds // 60) % 60 77 hours = int(obj.seconds // 3600) % 24 + int(obj.days) * 24 78 return escape_string('%02d:%02d:%02d' % (hours, minutes, seconds))
79
80 -def escape_time(obj):
81 s = "%02d:%02d:%02d" % (int(obj.hour), int(obj.minute), 82 int(obj.second)) 83 if obj.microsecond: 84 s += ".%f" % obj.microsecond 85 86 return escape_string(s)
87
88 -def escape_datetime(obj):
89 return escape_string(obj.strftime("%Y-%m-%d %H:%M:%S"))
90
91 -def escape_date(obj):
92 return escape_string(obj.strftime("%Y-%m-%d"))
93
94 -def escape_struct_time(obj):
95 return escape_datetime(datetime.datetime(*obj[:6]))
96
97 -def convert_datetime(connection, field, obj):
98 """Returns a DATETIME or TIMESTAMP column value as a datetime object: 99 100 >>> datetime_or_None('2007-02-25 23:06:20') 101 datetime.datetime(2007, 2, 25, 23, 6, 20) 102 >>> datetime_or_None('2007-02-25T23:06:20') 103 datetime.datetime(2007, 2, 25, 23, 6, 20) 104 105 Illegal values are returned as None: 106 107 >>> datetime_or_None('2007-02-31T23:06:20') is None 108 True 109 >>> datetime_or_None('0000-00-00 00:00:00') is None 110 True 111 112 """ 113 if not isinstance(obj, unicode): 114 obj = obj.decode(connection.charset) 115 if ' ' in obj: 116 sep = ' ' 117 elif 'T' in obj: 118 sep = 'T' 119 else: 120 return convert_date(connection, field, obj) 121 122 try: 123 ymd, hms = obj.split(sep, 1) 124 return datetime.datetime(*[ int(x) for x in ymd.split('-')+hms.split(':') ]) 125 except ValueError: 126 return convert_date(connection, field, obj)
127
128 -def convert_timedelta(connection, field, obj):
129 """Returns a TIME column as a timedelta object: 130 131 >>> timedelta_or_None('25:06:17') 132 datetime.timedelta(1, 3977) 133 >>> timedelta_or_None('-25:06:17') 134 datetime.timedelta(-2, 83177) 135 136 Illegal values are returned as None: 137 138 >>> timedelta_or_None('random crap') is None 139 True 140 141 Note that MySQL always returns TIME columns as (+|-)HH:MM:SS, but 142 can accept values as (+|-)DD HH:MM:SS. The latter format will not 143 be parsed correctly by this function. 144 """ 145 from math import modf 146 try: 147 if not isinstance(obj, unicode): 148 obj = obj.decode(connection.charset) 149 hours, minutes, seconds = tuple([int(x) for x in obj.split(':')]) 150 tdelta = datetime.timedelta( 151 hours = int(hours), 152 minutes = int(minutes), 153 seconds = int(seconds), 154 microseconds = int(modf(float(seconds))[0]*1000000), 155 ) 156 return tdelta 157 except ValueError: 158 return None
159
160 -def convert_time(connection, field, obj):
161 """Returns a TIME column as a time object: 162 163 >>> time_or_None('15:06:17') 164 datetime.time(15, 6, 17) 165 166 Illegal values are returned as None: 167 168 >>> time_or_None('-25:06:17') is None 169 True 170 >>> time_or_None('random crap') is None 171 True 172 173 Note that MySQL always returns TIME columns as (+|-)HH:MM:SS, but 174 can accept values as (+|-)DD HH:MM:SS. The latter format will not 175 be parsed correctly by this function. 176 177 Also note that MySQL's TIME column corresponds more closely to 178 Python's timedelta and not time. However if you want TIME columns 179 to be treated as time-of-day and not a time offset, then you can 180 use set this function as the converter for FIELD_TYPE.TIME. 181 """ 182 from math import modf 183 try: 184 hour, minute, second = obj.split(':') 185 return datetime.time(hour=int(hour), minute=int(minute), 186 second=int(second), 187 microsecond=int(modf(float(second))[0]*1000000)) 188 except ValueError: 189 return None
190
191 -def convert_date(connection, field, obj):
192 """Returns a DATE column as a date object: 193 194 >>> date_or_None('2007-02-26') 195 datetime.date(2007, 2, 26) 196 197 Illegal values are returned as None: 198 199 >>> date_or_None('2007-02-31') is None 200 True 201 >>> date_or_None('0000-00-00') is None 202 True 203 204 """ 205 try: 206 if not isinstance(obj, unicode): 207 obj = obj.decode(connection.charset) 208 return datetime.date(*[ int(x) for x in obj.split('-', 2) ]) 209 except ValueError: 210 return None
211
212 -def convert_mysql_timestamp(connection, field, timestamp):
213 """Convert a MySQL TIMESTAMP to a Timestamp object. 214 215 MySQL >= 4.1 returns TIMESTAMP in the same format as DATETIME: 216 217 >>> mysql_timestamp_converter('2007-02-25 22:32:17') 218 datetime.datetime(2007, 2, 25, 22, 32, 17) 219 220 MySQL < 4.1 uses a big string of numbers: 221 222 >>> mysql_timestamp_converter('20070225223217') 223 datetime.datetime(2007, 2, 25, 22, 32, 17) 224 225 Illegal values are returned as None: 226 227 >>> mysql_timestamp_converter('2007-02-31 22:32:17') is None 228 True 229 >>> mysql_timestamp_converter('00000000000000') is None 230 True 231 232 """ 233 if not isinstance(timestamp, unicode): 234 timestamp = timestamp.decode(connection.charset) 235 236 if timestamp[4] == '-': 237 return convert_datetime(connection, field, timestamp) 238 timestamp += "0"*(14-len(timestamp)) # padding 239 year, month, day, hour, minute, second = \ 240 int(timestamp[:4]), int(timestamp[4:6]), int(timestamp[6:8]), \ 241 int(timestamp[8:10]), int(timestamp[10:12]), int(timestamp[12:14]) 242 try: 243 return datetime.datetime(year, month, day, hour, minute, second) 244 except ValueError: 245 return None
246
247 -def convert_set(s):
248 return set(s.split(","))
249
250 -def convert_bit(connection, field, b):
251 #b = "\x00" * (8 - len(b)) + b # pad w/ zeroes 252 #return struct.unpack(">Q", b)[0] 253 # 254 # the snippet above is right, but MySQLdb doesn't process bits, 255 # so we shouldn't either 256 return b
257
258 -def convert_characters(connection, field, data):
259 field_charset = charset_by_id(field.charsetnr).name 260 if field.flags & FLAG.SET: 261 return convert_set(data.decode(field_charset)) 262 if field.flags & FLAG.BINARY: 263 return data 264 265 if connection.use_unicode: 266 data = data.decode(field_charset) 267 elif connection.charset != field_charset: 268 data = data.decode(field_charset) 269 data = data.encode(connection.charset) 270 else: 271 data = data.decode(connection.charset) 272 return data
273
274 -def convert_int(connection, field, data):
275 return int(data)
276
277 -def convert_long(connection, field, data):
278 return long(data)
279
280 -def convert_float(connection, field, data):
281 return float(data)
282 283 encoders = { 284 bool: escape_bool, 285 int: escape_int, 286 long: escape_long, 287 float: escape_float, 288 str: escape_string, 289 unicode: escape_unicode, 290 tuple: escape_sequence, 291 list:escape_sequence, 292 set:escape_sequence, 293 dict:escape_dict, 294 type(None):escape_None, 295 datetime.date: escape_date, 296 datetime.datetime : escape_datetime, 297 datetime.timedelta : escape_timedelta, 298 datetime.time : escape_time, 299 time.struct_time : escape_struct_time, 300 } 301 302 decoders = { 303 FIELD_TYPE.BIT: convert_bit, 304 FIELD_TYPE.TINY: convert_int, 305 FIELD_TYPE.SHORT: convert_int, 306 FIELD_TYPE.LONG: convert_long, 307 FIELD_TYPE.FLOAT: convert_float, 308 FIELD_TYPE.DOUBLE: convert_float, 309 FIELD_TYPE.DECIMAL: convert_float, 310 FIELD_TYPE.NEWDECIMAL: convert_float, 311 FIELD_TYPE.LONGLONG: convert_long, 312 FIELD_TYPE.INT24: convert_int, 313 FIELD_TYPE.YEAR: convert_int, 314 FIELD_TYPE.TIMESTAMP: convert_mysql_timestamp, 315 FIELD_TYPE.DATETIME: convert_datetime, 316 FIELD_TYPE.TIME: convert_timedelta, 317 FIELD_TYPE.DATE: convert_date, 318 FIELD_TYPE.SET: convert_set, 319 FIELD_TYPE.BLOB: convert_characters, 320 FIELD_TYPE.TINY_BLOB: convert_characters, 321 FIELD_TYPE.MEDIUM_BLOB: convert_characters, 322 FIELD_TYPE.LONG_BLOB: convert_characters, 323 FIELD_TYPE.STRING: convert_characters, 324 FIELD_TYPE.VAR_STRING: convert_characters, 325 FIELD_TYPE.VARCHAR: convert_characters, 326 #FIELD_TYPE.BLOB: str, 327 #FIELD_TYPE.STRING: str, 328 #FIELD_TYPE.VAR_STRING: str, 329 #FIELD_TYPE.VARCHAR: str 330 } 331 conversions = decoders # for MySQLdb compatibility 332 333 try: 334 # python version > 2.3 335 from decimal import Decimal
336 - def convert_decimal(connection, field, data):
337 return Decimal(data)
338 decoders[FIELD_TYPE.DECIMAL] = convert_decimal 339 decoders[FIELD_TYPE.NEWDECIMAL] = convert_decimal 340
341 - def escape_decimal(obj):
342 return unicode(obj)
343 encoders[Decimal] = escape_decimal 344 345 except ImportError: 346 pass 347