diff options
author | Jason Kirtland <jek@discorporate.us> | 2008-02-14 20:02:10 +0000 |
---|---|---|
committer | Jason Kirtland <jek@discorporate.us> | 2008-02-14 20:02:10 +0000 |
commit | 71e745e96b8c5be990b3dc949cb99310dd055609 (patch) | |
tree | 00c748e65e7e85e0231a1c7c504dec6cfcab8e87 /lib/sqlalchemy/sql/util.py | |
parent | 8dd5eb402ef65194af4c54a6fd33a181b7d5eaf0 (diff) | |
download | sqlalchemy-71e745e96b8c5be990b3dc949cb99310dd055609.tar.gz |
- Fixed a couple pyflakes, cleaned up imports & whitespace
Diffstat (limited to 'lib/sqlalchemy/sql/util.py')
-rw-r--r-- | lib/sqlalchemy/sql/util.py | 78 |
1 files changed, 38 insertions, 40 deletions
diff --git a/lib/sqlalchemy/sql/util.py b/lib/sqlalchemy/sql/util.py index 2cd0a26fd..70a1dcc96 100644 --- a/lib/sqlalchemy/sql/util.py +++ b/lib/sqlalchemy/sql/util.py @@ -1,5 +1,5 @@ -from sqlalchemy import util, schema, topological -from sqlalchemy.sql import expression, visitors, operators +from sqlalchemy import exceptions, schema, topological, util +from sqlalchemy.sql import expression, operators, visitors from itertools import chain """Utility functions that build upon SQL and Schema constructs.""" @@ -30,16 +30,16 @@ def find_tables(clause, check_columns=False, include_aliases=False): def visit_alias(alias): tables.append(alias) kwargs['visit_alias'] = visit_alias - + if check_columns: def visit_column(column): tables.append(column.table) kwargs['visit_column'] = visit_column - + def visit_table(table): tables.append(table) kwargs['visit_table'] = visit_table - + visitors.traverse(clause, traverse_options= {'column_collections':False}, **kwargs) return tables @@ -49,26 +49,26 @@ def find_columns(clause): cols.add(col) visitors.traverse(clause, visit_column=visit_column) return cols - - + + def reduce_columns(columns, *clauses): """given a list of columns, return a 'reduced' set based on natural equivalents. the set is reduced to the smallest list of columns which have no natural equivalent present in the list. A "natural equivalent" means that two columns will ultimately represent the same value because they are related by a foreign key. - + \*clauses is an optional list of join clauses which will be traversed to further identify columns that are "equivalent". - + This function is primarily used to determine the most minimal "primary key" from a selectable, by reducing the set of primary key columns present in the the selectable to just those that are not repeated. - + """ - + columns = util.OrderedSet(columns) - + omit = util.Set() for col in columns: for fk in col.foreign_keys: @@ -78,7 +78,7 @@ def reduce_columns(columns, *clauses): if fk.column.shares_lineage(c): omit.add(col) break - + if clauses: def visit_binary(binary): if binary.operator == operators.eq: @@ -90,7 +90,7 @@ def reduce_columns(columns, *clauses): break for clause in clauses: visitors.traverse(clause, visit_binary=visit_binary) - + return expression.ColumnSet(columns.difference(omit)) def row_adapter(from_, to, equivalent_columns=None): @@ -133,7 +133,7 @@ def row_adapter(from_, to, equivalent_columns=None): return map.keys() AliasedRow.map = map return AliasedRow - + class ColumnsInClause(visitors.ClauseVisitor): """Given a selectable, visit clauses and determine if any columns from the clause are in the selectable. @@ -149,16 +149,16 @@ class ColumnsInClause(visitors.ClauseVisitor): class AbstractClauseProcessor(object): """Traverse and copy a ClauseElement, replacing selected elements based on rules. - + This class implements its own visit-and-copy strategy but maintains the same public interface as visitors.ClauseVisitor. """ - + __traverse_options__ = {'column_collections':False} - + def __init__(self, stop_on=None): self.stop_on = stop_on - + def convert_element(self, elem): """Define the *conversion* method for this ``AbstractClauseProcessor``.""" @@ -166,14 +166,14 @@ class AbstractClauseProcessor(object): def chain(self, visitor): # chaining AbstractClauseProcessor and other ClauseVisitor - # objects separately. All the ACP objects are chained on + # objects separately. All the ACP objects are chained on # their convert_element() method whereas regular visitors # chain on their visit_XXX methods. if isinstance(visitor, AbstractClauseProcessor): attr = '_next_acp' else: attr = '_next' - + tail = self while getattr(tail, attr, None) is not None: tail = getattr(tail, attr) @@ -182,7 +182,7 @@ class AbstractClauseProcessor(object): def copy_and_process(self, list_): """Copy the given list to a new list, with each element traversed individually.""" - + list_ = list(list_) stop_on = util.Set(self.stop_on or []) cloned = {} @@ -198,44 +198,44 @@ class AbstractClauseProcessor(object): stop_on.add(newelem) return newelem v = getattr(v, '_next_acp', None) - + if elem not in cloned: # the full traversal will only make a clone of a particular element # once. cloned[elem] = elem._clone() return cloned[elem] - + def traverse(self, elem, clone=True): if not clone: raise exceptions.ArgumentError("AbstractClauseProcessor 'clone' argument must be True") - + return self._traverse(elem, util.Set(self.stop_on or []), {}, _clone_toplevel=True) - + def _traverse(self, elem, stop_on, cloned, _clone_toplevel=False): if elem in stop_on: return elem - + if _clone_toplevel: elem = self._convert_element(elem, stop_on, cloned) if elem in stop_on: return elem - + def clone(element): return self._convert_element(element, stop_on, cloned) elem._copy_internals(clone=clone) - + v = getattr(self, '_next', None) while v is not None: meth = getattr(v, "visit_%s" % elem.__visit_name__, None) if meth: meth(elem) v = getattr(v, '_next', None) - + for e in elem.get_children(**self.__traverse_options__): if e not in stop_on: self._traverse(e, stop_on, cloned) return elem - + class ClauseAdapter(AbstractClauseProcessor): """Given a clause (like as in a WHERE criterion), locate columns which are embedded within a given selectable, and changes those @@ -273,23 +273,23 @@ class ClauseAdapter(AbstractClauseProcessor): def copy_and_chain(self, adapter): """create a copy of this adapter and chain to the given adapter. - + currently this adapter must be unchained to start, raises - an exception if it's already chained. - + an exception if it's already chained. + Does not modify the given adapter. """ - + if adapter is None: return self - + if hasattr(self, '_next_acp') or hasattr(self, '_next'): raise NotImplementedError("Can't chain_to on an already chained ClauseAdapter (yet)") - + ca = ClauseAdapter(self.selectable, self.include, self.exclude, self.equivalents) ca._next_acp = adapter return ca - + def convert_element(self, col): if isinstance(col, expression.FromClause): if self.selectable.is_derived_from(col): @@ -309,5 +309,3 @@ class ClauseAdapter(AbstractClauseProcessor): if newcol: return newcol return newcol - - |