Skip to content

Commit d59b588

Browse files
committed
Merge pull request web2py#348 from gi0baro/master
Optimizations in parsing
2 parents 29681fd + 15f2b49 commit d59b588

File tree

5 files changed

+25
-18
lines changed

5 files changed

+25
-18
lines changed

pydal/adapters/base.py

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
import copy
22
import sys
33
import types
4+
from collections import defaultdict
45
from .._compat import PY2, with_metaclass, iterkeys, iteritems, hashlib_md5, \
56
integer_types
67
from .._globals import IDENTITY
78
from ..connection import ConnectionPool
89
from ..exceptions import NotOnNOSQLError
910
from ..helpers.classes import Reference, ExecutionHandler, SQLCustomType, \
10-
SQLALL, NullDriver, BasicStorage
11+
SQLALL, NullDriver
1112
from ..helpers.methods import use_common_filters, xorify
1213
from ..helpers.regex import REGEX_SELECT_AS_PARSER
1314
from ..migrator import Migrator
@@ -210,8 +211,7 @@ def _regex_select_as_parser(self, colname):
210211

211212
def _parse(self, row, tmps, fields, colnames, blob_decode,
212213
cacheable, fields_virtual, fields_lazy):
213-
new_row = self.db.Row(dict(
214-
(tablename, self.db.Row()) for tablename in fields_virtual.keys()))
214+
new_row = defaultdict(self.db.Row)
215215
extras = self.db.Row()
216216
#: let's loop over columns
217217
for (j, colname) in enumerate(colnames):
@@ -221,10 +221,7 @@ def _parse(self, row, tmps, fields, colnames, blob_decode,
221221
#: do we have a real column?
222222
if tmp:
223223
(tablename, fieldname, table, field, ft) = tmp
224-
#: add table to row object if needed
225-
colset = new_row.get(tablename, None)
226-
if colset is None:
227-
colset = new_row[tablename] = self.db.Row()
224+
colset = new_row[tablename]
228225
#: parse value
229226
value = self.parse_value(value, ft, blob_decode)
230227
if field.filter_out:
@@ -246,11 +243,12 @@ def _parse(self, row, tmps, fields, colnames, blob_decode,
246243
new_column_name = self._regex_select_as_parser(colname)
247244
if new_column_name is not None:
248245
column_name = new_column_name.groups(0)
249-
setattr(new_row, column_name[0], value)
246+
new_row[column_name[0]] = value
250247
#: add extras if needed (eg. operations results)
251248
if extras:
252249
new_row['_extra'] = extras
253250
#: add virtuals
251+
new_row = self.db.Row(**new_row)
254252
for tablename in fields_virtual.keys():
255253
for f, v in fields_virtual[tablename]:
256254
try:

pydal/parsers/__init__.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
from collections import defaultdict
12
from .._compat import with_metaclass, iteritems
23
from .._gae import gae
34
from ..helpers._internals import Dispatcher
@@ -82,7 +83,7 @@ def __init__(self, adapter):
8283
self._before_registry_ = {}
8384
for name, obj in iteritems(self._declared_before_):
8485
self._before_registry_[obj.field_type] = obj.f
85-
self.registered = {}
86+
self.registered = defaultdict(lambda self=self: self._default)
8687
for name, obj in iteritems(self._declared_parsers_):
8788
if obj.field_type in self._before_registry_:
8889
self.registered[obj.field_type] = ParserMethodWrapper(
@@ -98,7 +99,7 @@ def _default(self, value, field_type):
9899

99100
def get_parser(self, field_type):
100101
key = REGEX_TYPE.match(field_type).group(0)
101-
return self.registered.get(key, self._default)
102+
return self.registered[key]
102103

103104
def parse(self, value, field_type):
104105
return self.get_parser(field_type)(value, field_type)

pydal/parsers/base.py

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -62,14 +62,16 @@ def _bigint(self, value):
6262
return self.registered['integer'](value, 'bigint')
6363

6464

65-
class DateTimeParser(Parser):
65+
class DateParser(Parser):
6666
@for_type('date')
6767
def _date(self, value):
6868
if isinstance(value, datetime):
6969
return value.date()
7070
(y, m, d) = map(int, str(value)[:10].strip().split('-'))
7171
return date(y, m, d)
7272

73+
74+
class TimeParser(Parser):
7375
@for_type('time')
7476
def _time(self, value):
7577
if isinstance(value, datetime):
@@ -81,18 +83,20 @@ def _time(self, value):
8183
(h, mi, s) = time_items + [0]
8284
return time(h, mi, s)
8385

86+
87+
class DateTimeParser(Parser):
8488
@for_type('datetime')
8589
def _datetime(self, value):
8690
value = str(value)
8791
date_part, time_part, timezone = value[:10], value[11:19], value[19:]
8892
if '+' in timezone:
8993
ms, tz = timezone.split('+')
9094
h, m = tz.split(':')
91-
dt = timedelta(seconds=3600*int(h)+60*int(m))
95+
dt = timedelta(seconds=3600 * int(h) + 60 * int(m))
9296
elif '-' in timezone:
9397
ms, tz = timezone.split('-')
9498
h, m = tz.split(':')
95-
dt = -timedelta(seconds=3600*int(h)+60*int(m))
99+
dt = -timedelta(seconds=3600 * int(h) + 60 * int(m))
96100
else:
97101
ms = timezone.upper().split('Z')[0]
98102
dt = None
@@ -146,5 +150,8 @@ def _list_references(self, value, field_type):
146150

147151

148152
@parsers.register_for(SQLAdapter)
149-
class Commonparser(ListsParser, DateTimeParser, DecimalParser, JSONParser):
153+
class Commonparser(
154+
ListsParser, DateParser, TimeParser, DateTimeParser, DecimalParser,
155+
JSONParser
156+
):
150157
pass

pydal/parsers/sqlite.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
from decimal import Decimal
22
from ..adapters.sqlite import SQLite
3-
from .base import ListsParser, DateTimeParser, JSONParser
3+
from .base import ListsParser, TimeParser, JSONParser
44
from . import parsers, for_type, before_parse
55

66

77
@parsers.register_for(SQLite)
8-
class SQLiteParser(ListsParser, DateTimeParser, JSONParser):
8+
class SQLiteParser(ListsParser, TimeParser, JSONParser):
99
@before_parse('decimal')
1010
def decimal_extras(self, field_type):
1111
return {'decimals': field_type[8:-1].split(',')[-1]}

pydal/representers/__init__.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
from collections import defaultdict
12
from .._compat import PY2, with_metaclass, iteritems, to_unicode
23
from .._gae import gae
34
from ..helpers._internals import Dispatcher
@@ -182,7 +183,7 @@ def __init__(self, adapter):
182183
self._tbefore_registry_ = {}
183184
for name, obj in iteritems(self._declared_tbefore_):
184185
self._tbefore_registry_[obj.field_type] = obj.f
185-
self.registered_t = {}
186+
self.registered_t = defaultdict(lambda self=self: self._default)
186187
for name, obj in iteritems(self._declared_trepresenters_):
187188
if obj.field_type in self._tbefore_registry_:
188189
self.registered_t[obj.field_type] = TReprMethodWrapper(
@@ -217,7 +218,7 @@ def get_representer_for_instance(self, value):
217218

218219
def get_representer_for_type(self, field_type):
219220
key = REGEX_TYPE.match(field_type).group(0)
220-
return self.registered_t.get(key, self._default)
221+
return self.registered_t[key]
221222

222223
def adapt(self, value):
223224
if PY2:

0 commit comments

Comments
 (0)