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
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
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
36 n = {}
37 for k, v in val.items():
38 quoted = escape_item(v, charset)
39 n[k] = quoted
40 return n
41
43 n = []
44 for item in val:
45 quoted = escape_item(item, charset)
46 n.append(quoted)
47 return tuple(n)
48
52
54 return str(int(value))
55
58
59 escape_int = escape_long = escape_object
60
62 return ('%.15g' % value)
63
67
70
73
79
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
90
93
96
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
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
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
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
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))
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
248 return set(s.split(","))
249
251
252
253
254
255
256 return b
257
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
276
279
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
327
328
329
330 }
331 conversions = decoders
332
333 try:
334
335 from decimal import Decimal
338 decoders[FIELD_TYPE.DECIMAL] = convert_decimal
339 decoders[FIELD_TYPE.NEWDECIMAL] = convert_decimal
340
343 encoders[Decimal] = escape_decimal
344
345 except ImportError:
346 pass
347