Skip to content

Commit ab448ae

Browse files
committed
Convert date, datetime, time string to struct before response to user.
1 parent e0e4e52 commit ab448ae

File tree

3 files changed

+44
-95
lines changed

3 files changed

+44
-95
lines changed

Pipfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ name = "pypi"
55

66
[packages]
77
requests = "*"
8+
arrow = "*"
89

910
[dev-packages]
1011
pylint = "*"

pycovenantsql/connections.py

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -310,23 +310,25 @@ def read(self):
310310
self.insert_id = data['last_insert_id']
311311
return
312312

313-
rows = []
314-
for line in data['rows']:
315-
row = []
316-
for column in line:
317-
row.append(column)
318-
rows.append(tuple(row))
319-
self.rows = tuple(rows)
313+
self.field_count = len(data['columns'])
320314

321315
try:
322-
self.field_count = len(data['columns'])
323-
324316
description = []
325317
for i in range(self.field_count):
326318
fields = []
327319
fields.append(data['columns'][i])
328320
fields.append(data['types'][i])
329321
description.append(tuple(fields))
330322
self.description = tuple(description)
331-
except:
332-
raise err.InterfaceError("Proxy return column count and types count are not equal")
323+
324+
rows = []
325+
for line in data['rows']:
326+
row = []
327+
for i in range(self.field_count):
328+
column_data = converters.convert_column_data(self.description[i][1], line[i])
329+
row.append(column_data)
330+
rows.append(tuple(row))
331+
self.rows = tuple(rows)
332+
except Exception as error:
333+
raise err.InterfaceError("Read proxy return data err:" % error)
334+

pycovenantsql/converters.py

Lines changed: 30 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@
22

33
import datetime
44
from decimal import Decimal
5+
from .err import DataError
56
import re
67
import time
8+
import arrow
79

810
def escape_item(val, mapping=None):
911
if mapping is None:
@@ -137,9 +139,6 @@ def _convert_second_fraction(s):
137139
s = s.ljust(6, '0')
138140
return int(s[:6])
139141

140-
DATETIME_RE = re.compile(r"(\d{1,4})-(\d{1,2})-(\d{1,2})[T ](\d{1,2}):(\d{1,2}):(\d{1,2})(?:.(\d{1,6}))?")
141-
142-
143142
def convert_datetime(obj):
144143
"""Returns a DATETIME or TIMESTAMP column value as a datetime object:
145144
@@ -148,27 +147,17 @@ def convert_datetime(obj):
148147
>>> datetime_or_None('2007-02-25T23:06:20')
149148
datetime.datetime(2007, 2, 25, 23, 6, 20)
150149
151-
Illegal values are returned as None:
152-
153-
>>> datetime_or_None('2007-02-31T23:06:20') is None
154-
True
155-
>>> datetime_or_None('0000-00-00 00:00:00') is None
156-
True
150+
Illegal values are raise DataError
157151
158152
"""
159153
if not PY2 and isinstance(obj, (bytes, bytearray)):
160154
obj = obj.decode('ascii')
161155

162-
m = DATETIME_RE.match(obj)
163-
if not m:
164-
return convert_date(obj)
165-
166156
try:
167-
groups = list(m.groups())
168-
groups[-1] = _convert_second_fraction(groups[-1])
169-
return datetime.datetime(*[ int(x) for x in groups ])
170-
except ValueError:
171-
return convert_date(obj)
157+
return arrow.get(obj).datetime
158+
except ValueError as err:
159+
raise DataError("Not valid datetime struct: %s" % err)
160+
172161

173162
TIMEDELTA_RE = re.compile(r"(-)?(\d{1,3}):(\d{1,2}):(\d{1,2})(?:.(\d{1,6}))?")
174163

@@ -213,47 +202,22 @@ def convert_timedelta(obj):
213202
except ValueError:
214203
return obj
215204

216-
TIME_RE = re.compile(r"(\d{1,2}):(\d{1,2}):(\d{1,2})(?:.(\d{1,6}))?")
217-
218-
219205
def convert_time(obj):
220206
"""Returns a TIME column as a time object:
221207
222208
>>> time_or_None('15:06:17')
223209
datetime.time(15, 6, 17)
224210
225-
Illegal values are returned as None:
226-
227-
>>> time_or_None('-25:06:17') is None
228-
True
229-
>>> time_or_None('random crap') is None
230-
True
211+
Illegal values are returned DataError:
231212
232-
Note that MySQL always returns TIME columns as (+|-)HH:MM:SS, but
233-
can accept values as (+|-)DD HH:MM:SS. The latter format will not
234-
be parsed correctly by this function.
235-
236-
Also note that MySQL's TIME column corresponds more closely to
237-
Python's timedelta and not time. However if you want TIME columns
238-
to be treated as time-of-day and not a time offset, then you can
239-
use set this function as the converter for FIELD_TYPE.TIME.
240213
"""
241214
if not PY2 and isinstance(obj, (bytes, bytearray)):
242215
obj = obj.decode('ascii')
243216

244-
m = TIME_RE.match(obj)
245-
if not m:
246-
return obj
247-
248217
try:
249-
groups = list(m.groups())
250-
groups[-1] = _convert_second_fraction(groups[-1])
251-
hours, minutes, seconds, microseconds = groups
252-
return datetime.time(hour=int(hours), minute=int(minutes),
253-
second=int(seconds), microsecond=int(microseconds))
254-
except ValueError:
255-
return obj
256-
218+
return arrow.get(obj).time()
219+
except ValueError as err:
220+
raise DataError("Not valid time struct: %s" % err)
257221

258222
def convert_date(obj):
259223
"""Returns a DATE column as a date object:
@@ -272,45 +236,11 @@ def convert_date(obj):
272236
if not PY2 and isinstance(obj, (bytes, bytearray)):
273237
obj = obj.decode('ascii')
274238
try:
275-
return datetime.date(*[ int(x) for x in obj.split('-', 2) ])
276-
except ValueError:
277-
return obj
239+
return arrow.get(obj).date()
240+
except ValueError as err:
241+
raise DataError("Not valid date struct: %s" % err)
278242

279243

280-
#def convert_mysql_timestamp(timestamp):
281-
# """Convert a MySQL TIMESTAMP to a Timestamp object.
282-
#
283-
# MySQL >= 4.1 returns TIMESTAMP in the same format as DATETIME:
284-
#
285-
# >>> mysql_timestamp_converter('2007-02-25 22:32:17')
286-
# datetime.datetime(2007, 2, 25, 22, 32, 17)
287-
#
288-
# MySQL < 4.1 uses a big string of numbers:
289-
#
290-
# >>> mysql_timestamp_converter('20070225223217')
291-
# datetime.datetime(2007, 2, 25, 22, 32, 17)
292-
#
293-
# Illegal values are returned as None:
294-
#
295-
# >>> mysql_timestamp_converter('2007-02-31 22:32:17') is None
296-
# True
297-
# >>> mysql_timestamp_converter('00000000000000') is None
298-
# True
299-
#
300-
# """
301-
# if not PY2 and isinstance(timestamp, (bytes, bytearray)):
302-
# timestamp = timestamp.decode('ascii')
303-
# if timestamp[4] == '-':
304-
# return convert_datetime(timestamp)
305-
# timestamp += "0"*(14-len(timestamp)) # padding
306-
# year, month, day, hour, minute, second = \
307-
# int(timestamp[:4]), int(timestamp[4:6]), int(timestamp[6:8]), \
308-
# int(timestamp[8:10]), int(timestamp[10:12]), int(timestamp[12:14])
309-
# try:
310-
# return datetime.datetime(year, month, day, hour, minute, second)
311-
# except ValueError:
312-
# return timestamp
313-
314244
def convert_set(s):
315245
if isinstance(s, (bytes, bytearray)):
316246
return set(s.split(b","))
@@ -335,6 +265,22 @@ def convert_characters(connection, data):
335265
data = data.decode("utf8")
336266
return data
337267

268+
def convert_column_data(column_type, column_data):
269+
data = column_data
270+
271+
if not isinstance(column_type, text_type):
272+
return data
273+
274+
column_type = column_type.lower().strip()
275+
if column_type == 'time':
276+
data = convert_time(column_data)
277+
elif column_type == 'date':
278+
data = convert_date(column_data)
279+
elif column_type == 'datetime':
280+
data = convert_datetime(column_data)
281+
282+
return data
283+
338284
encoders = {
339285
bool: escape_bool,
340286
int: escape_int,

0 commit comments

Comments
 (0)