111 lines
3.4 KiB
Python
111 lines
3.4 KiB
Python
from collections import defaultdict
|
|
from .._compat import with_metaclass, iteritems
|
|
from .._gae import gae
|
|
from ..helpers._internals import Dispatcher
|
|
from ..helpers.regex import REGEX_TYPE
|
|
|
|
|
|
parsers = Dispatcher("parser")
|
|
|
|
|
|
class for_type(object):
|
|
def __init__(self, field_type):
|
|
self.field_type = field_type
|
|
|
|
def __call__(self, f):
|
|
self.f = f
|
|
return self
|
|
|
|
|
|
class before_parse(object):
|
|
def __init__(self, field_type):
|
|
self.field_type = field_type
|
|
|
|
def __call__(self, f):
|
|
self.f = f
|
|
return self
|
|
|
|
|
|
class MetaParser(type):
|
|
def __new__(cls, name, bases, attrs):
|
|
new_class = type.__new__(cls, name, bases, attrs)
|
|
if bases == (object,):
|
|
return new_class
|
|
#: collect declared attributes
|
|
parsers = {}
|
|
before = {}
|
|
for key, value in list(attrs.items()):
|
|
if isinstance(value, for_type):
|
|
parsers[key] = value
|
|
elif isinstance(value, before_parse):
|
|
before[key] = value
|
|
#: get super declared attributes
|
|
declared_parsers = {}
|
|
declared_before = {}
|
|
for base in reversed(new_class.__mro__[1:]):
|
|
if hasattr(base, '_declared_parsers_'):
|
|
declared_parsers.update(base._declared_parsers_)
|
|
if hasattr(base, '_declared_before_'):
|
|
declared_before.update(base._declared_before_)
|
|
#: set parsers
|
|
declared_parsers.update(parsers)
|
|
declared_before.update(before)
|
|
new_class._declared_parsers_ = declared_parsers
|
|
new_class._declared_before_ = declared_before
|
|
return new_class
|
|
|
|
|
|
class ParserMethodWrapper(object):
|
|
def __init__(self, parser, f, extra=None):
|
|
self.parser = parser
|
|
self.f = f
|
|
if extra:
|
|
self.extra = extra
|
|
self.call = self._call_with_extras
|
|
else:
|
|
self.call = self._call
|
|
|
|
def _call_with_extras(self, value, field_type):
|
|
extras = self.extra(self.parser, field_type)
|
|
return self.f(self.parser, value, **extras)
|
|
|
|
def _call(self, value, field_type):
|
|
return self.f(self.parser, value)
|
|
|
|
def __call__(self, value, field_type):
|
|
return self.call(value, field_type)
|
|
|
|
|
|
class Parser(with_metaclass(MetaParser)):
|
|
def __init__(self, adapter):
|
|
self.adapter = adapter
|
|
self.dialect = adapter.dialect
|
|
self._before_registry_ = {}
|
|
for name, obj in iteritems(self._declared_before_):
|
|
self._before_registry_[obj.field_type] = obj.f
|
|
self.registered = defaultdict(lambda self=self: self._default)
|
|
for name, obj in iteritems(self._declared_parsers_):
|
|
if obj.field_type in self._before_registry_:
|
|
self.registered[obj.field_type] = ParserMethodWrapper(
|
|
self, obj.f, self._before_registry_[obj.field_type]
|
|
)
|
|
else:
|
|
self.registered[obj.field_type] = ParserMethodWrapper(
|
|
self, obj.f
|
|
)
|
|
|
|
def _default(self, value, field_type):
|
|
return value
|
|
|
|
def parse(self, value, field_itype, field_type):
|
|
return self.registered[field_itype](value, field_type)
|
|
|
|
|
|
from .base import BasicParser
|
|
from .sqlite import SQLiteParser
|
|
from .postgre import PostgreParser
|
|
from .mongo import MongoParser
|
|
|
|
if gae is not None:
|
|
from .google import GoogleDatastoreParser
|