Skip to content

Instantly share code, notes, and snippets.

@aelaguiz
Created November 28, 2013 13:22
Show Gist options
  • Save aelaguiz/7691751 to your computer and use it in GitHub Desktop.
Save aelaguiz/7691751 to your computer and use it in GitHub Desktop.
Dispatching model pattern with sqlalchemy
import sqlalchemy as sqla
import sqlalchemy.ext.declarative as decl
from .signals import signaler
class _hooked(object):
def __init__(self, validate_func, normalize_func, field_name, private_name):
self.validate_func = validate_func
self.normalize_func = normalize_func
self.field_name = field_name
self.private_name = private_name
def __get__(self, instance, owner):
if not instance:
return getattr(owner, self.private_name)
val = getattr(instance, self.private_name)
return val
def __set__(self, instance, val):
namespace = instance.__class__.__name__ + "." + self.field_name
if self.normalize_func:
val = self.normalize_func(val)
if self.validate_func:
assert self.validate_func(val)
old_value = None
if hasattr(instance, self.private_name):
old_value = getattr(instance, self.private_name)
signaler.signal(namespace + ":before_update", instance=instance, new_value=val, old_value=old_value)
setattr(instance, self.private_name, val)
signaler.signal(namespace + ":after_update", instance=instance, new_value=val, old_value=old_value)
class DispatchingModelMeta(decl.DeclarativeMeta):
def __new__(cls, name, bases, attrs):
new_attrs = {}
for key, val in attrs.iteritems():
if isinstance(val, sqla.Column):
log.debug(u"{} Column {} {}".format(name, key, val))
if not val.name:
val.name = key
val.key = key
validator_name = 'validate_' + key
normalize_name = 'normalize_' + key
private_name = '_' + key
validator_func = None
normalize_func = None
if validator_name in attrs:
validator_func = attrs[validator_name]
if normalize_name in attrs:
normalize_func = attrs[normalize_name]
new_attrs[private_name] = val
new_attrs[key] = _hooked(validate_func=validator_func, normalize_func=normalize_func, field_name=key, private_name=private_name)
else:
new_attrs[key] = val
return super(DispatchingModelMeta, cls).__new__(cls, name, bases, new_attrs)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment