summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2010-02-22 20:37:44 +0000
committerMike Bayer <mike_mp@zzzcomputing.com>2010-02-22 20:37:44 +0000
commitc8e8d77fdc0503bd1ac48ba35921745ff61f4cc3 (patch)
treefc26f76c17077b177fc9381db10b3d05983b1a6f /lib
parent258acbeb72f012abcba1618e6930dda58307c5cc (diff)
downloadsqlalchemy-c8e8d77fdc0503bd1ac48ba35921745ff61f4cc3.tar.gz
- added util.portable_instancemethod to provide a quick way to make an instancemethod "serializable"
- SchemaType and subclasses Boolean, Enum are now serializable, including their ddl listener and other event callables. [ticket:1694] [ticket:1698] - AddConstraint/DropConstraint use the wrapper for _create_rule - added test coverage for AddConstraint override of _create_rule
Diffstat (limited to 'lib')
-rw-r--r--lib/sqlalchemy/schema.py17
-rw-r--r--lib/sqlalchemy/types.py53
-rw-r--r--lib/sqlalchemy/util.py12
3 files changed, 60 insertions, 22 deletions
diff --git a/lib/sqlalchemy/schema.py b/lib/sqlalchemy/schema.py
index d51ae3a45..c68d1f135 100644
--- a/lib/sqlalchemy/schema.py
+++ b/lib/sqlalchemy/schema.py
@@ -1426,7 +1426,8 @@ class CheckConstraint(Constraint):
Can be included in the definition of a Table or Column.
"""
- def __init__(self, sqltext, name=None, deferrable=None, initially=None, table=None, _create_rule=None):
+ def __init__(self, sqltext, name=None, deferrable=None,
+ initially=None, table=None, _create_rule=None):
"""Construct a CHECK constraint.
sqltext
@@ -2291,6 +2292,16 @@ class _CreateDropBase(DDLElement):
self.on = on
self.bind = bind
+ def _create_rule_disable(self, compiler):
+ """Allow disable of _create_rule using a callable.
+
+ Pass to _create_rule using
+ util.portable_instancemethod(self._create_rule_disable)
+ to retain serializability.
+
+ """
+ return False
+
class CreateTable(_CreateDropBase):
"""Represent a CREATE TABLE statement."""
@@ -2332,7 +2343,7 @@ class AddConstraint(_CreateDropBase):
def __init__(self, element, *args, **kw):
super(AddConstraint, self).__init__(element, *args, **kw)
- element._create_rule = lambda compiler: False
+ element._create_rule = util.portable_instancemethod(self._create_rule_disable)
class DropConstraint(_CreateDropBase):
"""Represent an ALTER TABLE DROP CONSTRAINT statement."""
@@ -2342,7 +2353,7 @@ class DropConstraint(_CreateDropBase):
def __init__(self, element, cascade=False, **kw):
self.cascade = cascade
super(DropConstraint, self).__init__(element, **kw)
- element._create_rule = lambda compiler: False
+ element._create_rule = util.portable_instancemethod(self._create_rule_disable)
def _bind_or_error(schemaitem, msg=None):
bind = schemaitem.bind
diff --git a/lib/sqlalchemy/types.py b/lib/sqlalchemy/types.py
index a52ffe59c..356edecd8 100644
--- a/lib/sqlalchemy/types.py
+++ b/lib/sqlalchemy/types.py
@@ -1038,22 +1038,36 @@ class SchemaType(object):
self.schema = kw.pop('schema', None)
self.metadata = kw.pop('metadata', None)
if self.metadata:
- self.metadata.append_ddl_listener('before-create',
- self._on_metadata_create)
- self.metadata.append_ddl_listener('after-drop',
- self._on_metadata_drop)
+ self.metadata.append_ddl_listener(
+ 'before-create',
+ util.portable_instancemethod(self._on_metadata_create)
+ )
+ self.metadata.append_ddl_listener(
+ 'after-drop',
+ util.portable_instancemethod(self._on_metadata_drop)
+ )
def _set_parent(self, column):
- column._on_table_attach(self._set_table)
+ column._on_table_attach(util.portable_instancemethod(self._set_table))
def _set_table(self, table, column):
- table.append_ddl_listener('before-create', self._on_table_create)
- table.append_ddl_listener('after-drop', self._on_table_drop)
+ table.append_ddl_listener(
+ 'before-create',
+ util.portable_instancemethod(self._on_table_create)
+ )
+ table.append_ddl_listener(
+ 'after-drop',
+ util.portable_instancemethod(self._on_table_drop)
+ )
if self.metadata is None:
- table.metadata.append_ddl_listener('before-create',
- self._on_metadata_create)
- table.metadata.append_ddl_listener('after-drop',
- self._on_metadata_drop)
+ table.metadata.append_ddl_listener(
+ 'before-create',
+ util.portable_instancemethod(self._on_metadata_create)
+ )
+ table.metadata.append_ddl_listener(
+ 'after-drop',
+ util.portable_instancemethod(self._on_metadata_drop)
+ )
@property
def bind(self):
@@ -1178,19 +1192,20 @@ class Enum(String, SchemaType):
assert_unicode=assert_unicode
)
SchemaType.__init__(self, **kw)
+
+ def _should_create_constraint(self, compiler):
+ return not self.native_enum or \
+ not compiler.dialect.supports_native_enum
def _set_table(self, table, column):
if self.native_enum:
SchemaType._set_table(self, table, column)
- def should_create_constraint(compiler):
- return not self.native_enum or \
- not compiler.dialect.supports_native_enum
e = schema.CheckConstraint(
column.in_(self.enums),
name=self.name,
- _create_rule=should_create_constraint
+ _create_rule=util.portable_instancemethod(self._should_create_constraint)
)
table.append_constraint(e)
@@ -1314,18 +1329,18 @@ class Boolean(TypeEngine, SchemaType):
"""
self.create_constraint = create_constraint
self.name = name
+
+ def _should_create_constraint(self, compiler):
+ return not compiler.dialect.supports_native_boolean
def _set_table(self, table, column):
if not self.create_constraint:
return
- def should_create_constraint(compiler):
- return not compiler.dialect.supports_native_boolean
-
e = schema.CheckConstraint(
column.in_([0, 1]),
name=self.name,
- _create_rule=should_create_constraint
+ _create_rule=util.portable_instancemethod(self._should_create_constraint)
)
table.append_constraint(e)
diff --git a/lib/sqlalchemy/util.py b/lib/sqlalchemy/util.py
index 07b8269a9..873243de1 100644
--- a/lib/sqlalchemy/util.py
+++ b/lib/sqlalchemy/util.py
@@ -453,6 +453,18 @@ def unbound_method_to_callable(func_or_cls):
else:
return func_or_cls
+class portable_instancemethod(object):
+ """Turn an instancemethod into a (parent, name) pair
+ to produce a serializable callable.
+
+ """
+ def __init__(self, meth):
+ self.target = meth.im_self
+ self.name = meth.__name__
+
+ def __call__(self, *arg, **kw):
+ return getattr(self.target, self.name)(*arg, **kw)
+
def class_hierarchy(cls):
"""Return an unordered sequence of all classes related to cls.