SP/web2py/gluon/packages/dal/pydal/parsers/base.py
Saturneic 064f602b1a Add.
2018-10-25 23:33:13 +08:00

162 lines
4.6 KiB
Python

import json
from base64 import b64decode
from datetime import datetime, date, time, timedelta
from decimal import Decimal
from .._compat import PY2, integer_types, basestring, to_bytes, to_native
from ..adapters.base import SQLAdapter
from ..helpers.classes import Reference
from ..helpers.methods import bar_decode_string, bar_decode_integer
from . import Parser, parsers, for_type, before_parse
long = integer_types[-1]
class BasicParser(Parser):
@for_type('id')
def _id(self, value):
return long(value)
@for_type('integer')
def _integer(self, value):
return long(value)
@for_type('float')
def _float(self, value):
return float(value)
@for_type('double')
def _double(self, value):
return self.registered['float'](value, 'double')
@for_type('boolean')
def _boolean(self, value):
return value == self.dialect.true or str(value)[:1].lower() == 't'
@for_type('blob')
def _blob(self, value):
decoded = b64decode(to_bytes(value))
try:
decoded = to_native(decoded)
except:
pass
return decoded
@before_parse('reference')
def reference_extras(self, field_type):
return {'referee': field_type[10:].strip()}
@for_type('reference')
def _reference(self, value, referee):
if '.' not in referee:
value = Reference(value)
value._table, value._record = self.adapter.db[referee], None
return value
@before_parse('list:reference')
def referencelist_extras(self, field_type):
return {'field_type': field_type}
@for_type('list:reference')
def _list_references(self, value, field_type):
return [self.registered['reference'](
el, field_type[5:]) for el in value]
@for_type('bigint')
def _bigint(self, value):
return self.registered['integer'](value, 'bigint')
class DateParser(Parser):
@for_type('date')
def _date(self, value):
if isinstance(value, datetime):
return value.date()
(y, m, d) = map(int, str(value)[:10].strip().split('-'))
return date(y, m, d)
class TimeParser(Parser):
@for_type('time')
def _time(self, value):
if isinstance(value, datetime):
return value.time()
time_items = list(map(int, str(value)[:8].strip().split(':')[:3]))
if len(time_items) == 3:
(h, mi, s) = time_items
else:
(h, mi, s) = time_items + [0]
return time(h, mi, s)
class DateTimeParser(Parser):
@for_type('datetime')
def _datetime(self, value):
value = str(value)
date_part, time_part, timezone = value[:10], value[11:19], value[19:]
if '+' in timezone:
ms, tz = timezone.split('+')
h, m = tz.split(':')
dt = timedelta(seconds=3600 * int(h) + 60 * int(m))
elif '-' in timezone:
ms, tz = timezone.split('-')
h, m = tz.split(':')
dt = -timedelta(seconds=3600 * int(h) + 60 * int(m))
else:
ms = timezone.upper().split('Z')[0]
dt = None
(y, m, d) = map(int, date_part.split('-'))
time_parts = time_part and time_part.split(':')[:3] or (0, 0, 0)
while len(time_parts) < 3:
time_parts.append(0)
time_items = map(int, time_parts)
(h, mi, s) = time_items
if ms and ms[0] == '.':
ms = int(float('0' + ms) * 1000000)
else:
ms = 0
value = datetime(y, m, d, h, mi, s, ms)
if dt:
value = value + dt
return value
class DecimalParser(Parser):
@for_type('decimal')
def _decimal(self, value):
return Decimal(value)
class JSONParser(Parser):
@for_type('json')
def _json(self, value):
#if 'loads' not in self.driver_auto_json:
if not isinstance(value, basestring):
raise RuntimeError('json data not a string')
if PY2 and isinstance(value, unicode):
value = value.encode('utf-8')
return json.loads(value)
class ListsParser(BasicParser):
@for_type('list:integer')
def _list_integers(self, value):
return bar_decode_integer(value)
@for_type('list:string')
def _list_strings(self, value):
return bar_decode_string(value)
@for_type('list:reference')
def _list_references(self, value, field_type):
value = bar_decode_integer(value)
return [self.registered['reference'](
el, field_type[5:]) for el in value]
@parsers.register_for(SQLAdapter)
class Commonparser(
ListsParser, DateParser, TimeParser, DateTimeParser, DecimalParser,
JSONParser
):
pass