diff options
author | Mike Bayer <mike_mp@zzzcomputing.com> | 2011-01-30 20:29:48 -0500 |
---|---|---|
committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2011-01-30 20:29:48 -0500 |
commit | 12073e281eebdece0fe4e24c6704d57eafdc9247 (patch) | |
tree | 1c831d73551c5a2e490bae41af390bd44d6391b5 /lib/sqlalchemy/schema.py | |
parent | 41d222b5f85d81c3cb7c33be284b9b5507463cb2 (diff) | |
download | sqlalchemy-12073e281eebdece0fe4e24c6704d57eafdc9247.tar.gz |
- SchemaItem, SchemaType now descend from common type
SchemaEventTarget, which supplies dispatch
- the dispatch now provides before_parent_attach(),
after_parent_attach(), events which generally bound the _set_parent()
event. [ticket:2037]
- the _on_table_attach mechanism now usually uses the
event dispatch
- fixed class-level event dispatch to propagate to all subclasses, not just
immediate subclasses
- fixed class-level event unpickling to handle more involved
inheritance hierarchies, needed by the new schema event dispatch.
- ForeignKeyConstraint doesn't re-call the column attach event
on ForeignKey objects that are already associated with the correct
Column
- we still need that ImportError on mysqldb CLIENT FLAGS to support
mock DBAPIs
Diffstat (limited to 'lib/sqlalchemy/schema.py')
-rw-r--r-- | lib/sqlalchemy/schema.py | 61 |
1 files changed, 23 insertions, 38 deletions
diff --git a/lib/sqlalchemy/schema.py b/lib/sqlalchemy/schema.py index cfed00610..9cf5c7f14 100644 --- a/lib/sqlalchemy/schema.py +++ b/lib/sqlalchemy/schema.py @@ -48,7 +48,7 @@ __all__.sort() RETAIN_SCHEMA = util.symbol('retain_schema') -class SchemaItem(visitors.Visitable): +class SchemaItem(events.SchemaEventTarget, visitors.Visitable): """Base class for items that define a database schema.""" __visit_name__ = 'schema_item' @@ -59,12 +59,7 @@ class SchemaItem(visitors.Visitable): for item in args: if item is not None: - item._set_parent(self) - - def _set_parent(self, parent): - """Associate with this SchemaItem's parent object.""" - - raise NotImplementedError() + item._set_parent_with_dispatch(self) def get_children(self, **kwargs): """used to allow SchemaVisitor access""" @@ -177,8 +172,6 @@ class Table(SchemaItem, expression.TableClause): __visit_name__ = 'table' - dispatch = event.dispatcher(events.DDLEvents) - def __new__(cls, *args, **kw): if not args: # python3k pickle seems to call this @@ -207,9 +200,11 @@ class Table(SchemaItem, expression.TableClause): raise exc.InvalidRequestError( "Table '%s' not defined" % (key)) table = object.__new__(cls) + table.dispatch.before_parent_attach(table, metadata) metadata._add_table(name, schema, table) try: table._init(name, metadata, *args, **kw) + table.dispatch.after_parent_attach(table, metadata) return table except: metadata._remove_table(name, schema) @@ -365,12 +360,12 @@ class Table(SchemaItem, expression.TableClause): def append_column(self, column): """Append a ``Column`` to this ``Table``.""" - column._set_parent(self) + column._set_parent_with_dispatch(self) def append_constraint(self, constraint): """Append a ``Constraint`` to this ``Table``.""" - constraint._set_parent(self) + constraint._set_parent_with_dispatch(self) def append_ddl_listener(self, event_name, listener): """Append a DDL event listener to this ``Table``. @@ -708,14 +703,13 @@ class Column(SchemaItem, expression.ColumnClause): self.autoincrement = kwargs.pop('autoincrement', True) self.constraints = set() self.foreign_keys = set() - self._table_events = set() # check if this Column is proxying another column if '_proxies' in kwargs: self.proxies = kwargs.pop('_proxies') # otherwise, add DDL-related events elif isinstance(self.type, types.SchemaType): - self.type._set_parent(self) + self.type._set_parent_with_dispatch(self) if self.default is not None: if isinstance(self.default, (ColumnDefault, Sequence)): @@ -777,7 +771,7 @@ class Column(SchemaItem, expression.ColumnClause): return False def append_foreign_key(self, fk): - fk._set_parent(self) + fk._set_parent_with_dispatch(self) def __repr__(self): kwarg = [] @@ -851,15 +845,10 @@ class Column(SchemaItem, expression.ColumnClause): "Index object external to the Table.") table.append_constraint(UniqueConstraint(self.key)) - for fn in self._table_events: - fn(table, self) - del self._table_events - def _on_table_attach(self, fn): if self.table is not None: - fn(self.table, self) - else: - self._table_events.add(fn) + fn(self, self.table) + event.listen(self, 'after_parent_attach', fn) def copy(self, **kw): """Create a copy of this ``Column``, unitialized. @@ -873,7 +862,7 @@ class Column(SchemaItem, expression.ColumnClause): [c.copy(**kw) for c in self.constraints] + \ [c.copy(**kw) for c in self.foreign_keys if not c.constraint] - c = Column( + return Column( name=self.name, type_=self.type, key = self.key, @@ -891,9 +880,6 @@ class Column(SchemaItem, expression.ColumnClause): doc=self.doc, *args ) - if hasattr(self, '_table_events'): - c._table_events = list(self._table_events) - return c def _make_proxy(self, selectable, name=None): """Create a *proxy* for this column. @@ -920,9 +906,7 @@ class Column(SchemaItem, expression.ColumnClause): selectable._columns.add(c) if self.primary_key: selectable.primary_key.add(c) - for fn in c._table_events: - fn(selectable, c) - del c._table_events + c.dispatch.after_parent_attach(c, selectable) return c def get_children(self, schema_visitor=False, **kwargs): @@ -1210,7 +1194,7 @@ class ForeignKey(SchemaItem): self.parent.foreign_keys.add(self) self.parent._on_table_attach(self._set_table) - def _set_table(self, table, column): + def _set_table(self, column, table): # standalone ForeignKey - create ForeignKeyConstraint # on the hosting Table when attached to the Table. if self.constraint is None and isinstance(table, Table): @@ -1220,7 +1204,7 @@ class ForeignKey(SchemaItem): deferrable=self.deferrable, initially=self.initially, ) self.constraint._elements[self.parent] = self - self.constraint._set_parent(table) + self.constraint._set_parent_with_dispatch(table) table.foreign_keys.add(self) class DefaultGenerator(SchemaItem): @@ -1382,7 +1366,7 @@ class Sequence(DefaultGenerator): super(Sequence, self)._set_parent(column) column._on_table_attach(self._set_table) - def _set_table(self, table, column): + def _set_table(self, column, table): self.metadata = table.metadata @property @@ -1407,7 +1391,7 @@ class Sequence(DefaultGenerator): bind.drop(self, checkfirst=checkfirst) -class FetchedValue(object): +class FetchedValue(events.SchemaEventTarget): """A marker for a transparent database-side default. Use :class:`.FetchedValue` when the database is configured @@ -1556,7 +1540,7 @@ class ColumnCollectionMixin(object): if self._pending_colargs and \ isinstance(self._pending_colargs[0], Column) and \ self._pending_colargs[0].table is not None: - self._set_parent(self._pending_colargs[0].table) + self._set_parent_with_dispatch(self._pending_colargs[0].table) def _set_parent(self, table): for col in self._pending_colargs: @@ -1643,7 +1627,7 @@ class CheckConstraint(Constraint): __init__(name, deferrable, initially, _create_rule) self.sqltext = expression._literal_as_text(sqltext) if table is not None: - self._set_parent(table) + self._set_parent_with_dispatch(table) def __visit_name__(self): if isinstance(self.parent, Table): @@ -1744,7 +1728,7 @@ class ForeignKeyConstraint(Constraint): ) if table is not None: - self._set_parent(table) + self._set_parent_with_dispatch(table) @property def columns(self): @@ -1761,7 +1745,10 @@ class ForeignKeyConstraint(Constraint): # resolved to Column objects if isinstance(col, basestring): col = table.c[col] - fk._set_parent(col) + + if not hasattr(fk, 'parent') or \ + fk.parent is not col: + fk._set_parent_with_dispatch(col) if self.use_alter: def supports_alter(ddl, event, schema_item, bind, **kw): @@ -1924,8 +1911,6 @@ class MetaData(SchemaItem): __visit_name__ = 'metadata' - dispatch = event.dispatcher(events.DDLEvents) - def __init__(self, bind=None, reflect=False): """Create a new MetaData object. |