diff options
| author | Mike Bayer <mike_mp@zzzcomputing.com> | 2010-02-22 20:37:44 +0000 |
|---|---|---|
| committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2010-02-22 20:37:44 +0000 |
| commit | c8e8d77fdc0503bd1ac48ba35921745ff61f4cc3 (patch) | |
| tree | fc26f76c17077b177fc9381db10b3d05983b1a6f /lib | |
| parent | 258acbeb72f012abcba1618e6930dda58307c5cc (diff) | |
| download | sqlalchemy-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.py | 17 | ||||
| -rw-r--r-- | lib/sqlalchemy/types.py | 53 | ||||
| -rw-r--r-- | lib/sqlalchemy/util.py | 12 |
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. |
