Source code for bag.sqlalchemy.json_col
"""A transparent JSON column for SQLAlchemy models.
The content of this module was basically pasted from
http://docs.sqlalchemy.org/en/latest/orm/extensions/mutable.html
and altered such that the value is never None.
"""
from sqlalchemy.ext.mutable import Mutable
from sqlalchemy.types import TypeDecorator, Unicode
import json
[docs]class JSONEncodedDict(TypeDecorator):
"""Represents an immutable structure as a json-encoded string."""
impl = Unicode
[docs] def process_bind_param(self, value, dialect):
if value is None:
value = {}
return json.dumps(value)
[docs] def process_result_value(self, value, dialect):
if value is None:
value = {}
return json.loads(value)
[docs]class MutableDict(Mutable, dict):
"""A dict that knows when it gets changed.
Usage in a SQLAlchemy model::
data = Column(MutableDict.as_mutable(JSONEncodedDict))
"""
[docs] @classmethod
def coerce(cls, key, value):
"""Convert plain dictionaries to MutableDict."""
if value is None:
value = {}
if not isinstance(value, MutableDict):
if isinstance(value, dict):
return MutableDict(value)
# This call will raise ValueError
return Mutable.coerce(key, value)
else:
return value
def __setitem__(self, key, value):
"""Detect dictionary set events and emit change events."""
dict.__setitem__(self, key, value)
self.changed()
def __delitem__(self, key):
"""Detect dictionary del events and emit change events."""
dict.__delitem__(self, key)
self.changed()