From: Mike Bayer Date: Mon, 14 Mar 2011 20:36:08 +0000 (-0400) Subject: initial work on column reflect X-Git-Tag: rel_0_7b3~25 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=9337fb939e51f8b15c23c396a344e857321ff602;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git initial work on column reflect --- diff --git a/lib/sqlalchemy/engine/reflection.py b/lib/sqlalchemy/engine/reflection.py index 00b2fd1bf1..72eb27c4eb 100644 --- a/lib/sqlalchemy/engine/reflection.py +++ b/lib/sqlalchemy/engine/reflection.py @@ -381,6 +381,8 @@ class Inspector(object): found_table = False for col_d in self.get_columns(table_name, schema, **tblkw): found_table = True + table.dispatch.column_reflect(table, col_d) + name = col_d['name'] if include_columns and name not in include_columns: continue @@ -389,10 +391,9 @@ class Inspector(object): col_kw = { 'nullable':col_d['nullable'], } - if 'autoincrement' in col_d: - col_kw['autoincrement'] = col_d['autoincrement'] - if 'quote' in col_d: - col_kw['quote'] = col_d['quote'] + for k in ('autoincrement', 'quote', 'info', 'key'): + if k in col_d: + col_kw[k] = col_d[k] colargs = [] if col_d.get('default') is not None: diff --git a/lib/sqlalchemy/events.py b/lib/sqlalchemy/events.py index 6435ff3f2e..e29e7c2d83 100644 --- a/lib/sqlalchemy/events.py +++ b/lib/sqlalchemy/events.py @@ -159,6 +159,56 @@ class DDLEvents(event.Events): """ + def column_reflect(self, table, column_info): + """Called for each unit of 'column info' retrieved when + a :class:`.Table` is being reflected. + + The dictionary of column information as returned by the + dialect is passed, and can be modified. The dictionary + is that returned in each element of the list returned + by :meth:`.reflection.Inspector.get_columns`. + + The event is called before any action is taken against + this dictionary, and the contents can be modified. + The :class:`.Column` specific arguments `info`, `key`, + and `quote` can also be added to the dictionary and + will be passed to the constructor of :class:`.Column`. + + Note that this event is only meaningful if either + associated with the :class:`.Table` class across the + board, e.g.:: + + from sqlalchemy.schema import Table + from sqlalchemy import event + + def listen_for_reflect(table, column_info): + "receive a column_reflect event" + # ... + + event.listen( + Table, + 'column_reflect', + listen_for_reflect) + + ...or with a specific :class:`.Table` instance using + the ``listeners`` argument:: + + def listen_for_reflect(table, column_info): + "receive a column_reflect event" + # ... + + t = Table( + 'sometable', + autoload=True, + listeners=[ + ('column_reflect', listen_for_reflect) + ]) + + This because the reflection process initiated by ``autoload=True`` + completes within the scope of the constructor for :class:`.Table`. + + """ + class SchemaEventTarget(object): """Base class for elements that are the targets of :class:`.DDLEvents` events. diff --git a/lib/sqlalchemy/schema.py b/lib/sqlalchemy/schema.py index 68e8179f94..d1eb12f4f8 100644 --- a/lib/sqlalchemy/schema.py +++ b/lib/sqlalchemy/schema.py @@ -141,6 +141,23 @@ class Table(SchemaItem, expression.TableClause): :param info: A dictionary which defaults to ``{}``. A space to store application specific data. This must be a dictionary. + :param listeners: A list of tuples of the form ``(, )`` + which will be passed to :func:`.event.listen` upon construction. + This alternate hook to :func:`.event.listen` allows the establishment + of a listener function specific to this :class:`.Table` before + the "autoload" process begins. Particularly useful for + the :meth:`.events.column_reflect` event:: + + def listen_for_reflect(table, column_info): + # ... + + t = Table( + 'sometable', + autoload=True, + listeners=[ + ('column_reflect', listen_for_reflect) + ]) + :param mustexist: When ``True``, indicates that this Table must already be present in the given :class:`MetaData`` collection. @@ -240,6 +257,10 @@ class Table(SchemaItem, expression.TableClause): self.quote_schema = kwargs.pop('quote_schema', None) if 'info' in kwargs: self.info = kwargs.pop('info') + if 'listeners' in kwargs: + listeners = kwargs.pop('listeners') + for evt, fn in listeners: + event.listen(self, evt, fn) self._prefixes = kwargs.pop('prefixes', [])