diff options
author | Mike Bayer <mike_mp@zzzcomputing.com> | 2019-01-06 01:14:26 -0500 |
---|---|---|
committer | mike bayer <mike_mp@zzzcomputing.com> | 2019-01-06 17:34:50 +0000 |
commit | 1e1a38e7801f410f244e4bbb44ec795ae152e04e (patch) | |
tree | 28e725c5c8188bd0cfd133d1e268dbca9b524978 /lib/sqlalchemy/sql/selectable.py | |
parent | 404e69426b05a82d905cbb3ad33adafccddb00dd (diff) | |
download | sqlalchemy-1e1a38e7801f410f244e4bbb44ec795ae152e04e.tar.gz |
Run black -l 79 against all source files
This is a straight reformat run using black as is, with no edits
applied at all.
The black run will format code consistently, however in
some cases that are prevalent in SQLAlchemy code it produces
too-long lines. The too-long lines will be resolved in the
following commit that will resolve all remaining flake8 issues
including shadowed builtins, long lines, import order, unused
imports, duplicate imports, and docstring issues.
Change-Id: I7eda77fed3d8e73df84b3651fd6cfcfe858d4dc9
Diffstat (limited to 'lib/sqlalchemy/sql/selectable.py')
-rw-r--r-- | lib/sqlalchemy/sql/selectable.py | 812 |
1 files changed, 500 insertions, 312 deletions
diff --git a/lib/sqlalchemy/sql/selectable.py b/lib/sqlalchemy/sql/selectable.py index f64f152c4..1f1800514 100644 --- a/lib/sqlalchemy/sql/selectable.py +++ b/lib/sqlalchemy/sql/selectable.py @@ -10,15 +10,39 @@ SQL tables and derived rowsets. """ -from .elements import ClauseElement, TextClause, ClauseList, \ - and_, Grouping, UnaryExpression, literal_column, BindParameter -from .elements import _clone, \ - _literal_as_text, _interpret_as_column_or_from, _expand_cloned,\ - _select_iterables, _anonymous_label, _clause_element_as_expr,\ - _cloned_intersection, _cloned_difference, True_, \ - _literal_as_label_reference, _literal_and_labels_as_label_reference -from .base import Immutable, Executable, _generative, \ - ColumnCollection, ColumnSet, _from_objects, Generative +from .elements import ( + ClauseElement, + TextClause, + ClauseList, + and_, + Grouping, + UnaryExpression, + literal_column, + BindParameter, +) +from .elements import ( + _clone, + _literal_as_text, + _interpret_as_column_or_from, + _expand_cloned, + _select_iterables, + _anonymous_label, + _clause_element_as_expr, + _cloned_intersection, + _cloned_difference, + True_, + _literal_as_label_reference, + _literal_and_labels_as_label_reference, +) +from .base import ( + Immutable, + Executable, + _generative, + ColumnCollection, + ColumnSet, + _from_objects, + Generative, +) from . import type_api from .. import inspection from .. import util @@ -40,7 +64,8 @@ def _interpret_as_from(element): "Textual SQL FROM expression %(expr)r should be " "explicitly declared as text(%(expr)r), " "or use table(%(expr)r) for more specificity", - {"expr": util.ellipses_string(element)}) + {"expr": util.ellipses_string(element)}, + ) return TextClause(util.text_type(element)) try: @@ -73,7 +98,7 @@ def _offset_or_limit_clause(element, name=None, type_=None): """ if element is None: return None - elif hasattr(element, '__clause_element__'): + elif hasattr(element, "__clause_element__"): return element.__clause_element__() elif isinstance(element, Visitable): return element @@ -97,7 +122,8 @@ def _offset_or_limit_clause_asint(clause, attrname): except AttributeError: raise exc.CompileError( "This SELECT structure does not use a simple " - "integer value for %s" % attrname) + "integer value for %s" % attrname + ) else: return util.asint(value) @@ -225,12 +251,14 @@ def tablesample(selectable, sampling, name=None, seed=None): """ return _interpret_as_from(selectable).tablesample( - sampling, name=name, seed=seed) + sampling, name=name, seed=seed + ) class Selectable(ClauseElement): """mark a class as being selectable""" - __visit_name__ = 'selectable' + + __visit_name__ = "selectable" is_selectable = True @@ -265,15 +293,17 @@ class HasPrefixes(object): limit rendering of this prefix to only that dialect. """ - dialect = kw.pop('dialect', None) + dialect = kw.pop("dialect", None) if kw: - raise exc.ArgumentError("Unsupported argument(s): %s" % - ",".join(kw)) + raise exc.ArgumentError( + "Unsupported argument(s): %s" % ",".join(kw) + ) self._setup_prefixes(expr, dialect) def _setup_prefixes(self, prefixes, dialect=None): self._prefixes = self._prefixes + tuple( - [(_literal_as_text(p, warn=False), dialect) for p in prefixes]) + [(_literal_as_text(p, warn=False), dialect) for p in prefixes] + ) class HasSuffixes(object): @@ -301,15 +331,17 @@ class HasSuffixes(object): limit rendering of this suffix to only that dialect. """ - dialect = kw.pop('dialect', None) + dialect = kw.pop("dialect", None) if kw: - raise exc.ArgumentError("Unsupported argument(s): %s" % - ",".join(kw)) + raise exc.ArgumentError( + "Unsupported argument(s): %s" % ",".join(kw) + ) self._setup_suffixes(expr, dialect) def _setup_suffixes(self, suffixes, dialect=None): self._suffixes = self._suffixes + tuple( - [(_literal_as_text(p, warn=False), dialect) for p in suffixes]) + [(_literal_as_text(p, warn=False), dialect) for p in suffixes] + ) class FromClause(Selectable): @@ -330,7 +362,8 @@ class FromClause(Selectable): """ - __visit_name__ = 'fromclause' + + __visit_name__ = "fromclause" named_with_column = False _hide_froms = [] @@ -359,13 +392,14 @@ class FromClause(Selectable): _memoized_property = util.group_expirable_memoized_property(["_columns"]) @util.deprecated( - '1.1', + "1.1", message="``FromClause.count()`` is deprecated. Counting " "rows requires that the correct column expression and " "accommodations for joins, DISTINCT, etc. must be made, " "otherwise results may not be what's expected. " "Please use an appropriate ``func.count()`` expression " - "directly.") + "directly.", + ) @util.dependencies("sqlalchemy.sql.functions") def count(self, functions, whereclause=None, **params): """return a SELECT COUNT generated against this @@ -392,10 +426,11 @@ class FromClause(Selectable): else: col = list(self.columns)[0] return Select( - [functions.func.count(col).label('tbl_row_count')], + [functions.func.count(col).label("tbl_row_count")], whereclause, from_obj=[self], - **params) + **params + ) def select(self, whereclause=None, **params): """return a SELECT of this :class:`.FromClause`. @@ -603,8 +638,9 @@ class FromClause(Selectable): def embedded(expanded_proxy_set, target_set): for t in target_set.difference(expanded_proxy_set): - if not set(_expand_cloned([t]) - ).intersection(expanded_proxy_set): + if not set(_expand_cloned([t])).intersection( + expanded_proxy_set + ): return False return True @@ -617,8 +653,10 @@ class FromClause(Selectable): for c in cols: expanded_proxy_set = set(_expand_cloned(c.proxy_set)) i = target_set.intersection(expanded_proxy_set) - if i and (not require_embedded - or embedded(expanded_proxy_set, target_set)): + if i and ( + not require_embedded + or embedded(expanded_proxy_set, target_set) + ): if col is None: # no corresponding column yet, pick this one. @@ -646,12 +684,20 @@ class FromClause(Selectable): col_distance = util.reduce( operator.add, - [sc._annotations.get('weight', 1) for sc in - col.proxy_set if sc.shares_lineage(column)]) + [ + sc._annotations.get("weight", 1) + for sc in col.proxy_set + if sc.shares_lineage(column) + ], + ) c_distance = util.reduce( operator.add, - [sc._annotations.get('weight', 1) for sc in - c.proxy_set if sc.shares_lineage(column)]) + [ + sc._annotations.get("weight", 1) + for sc in c.proxy_set + if sc.shares_lineage(column) + ], + ) if c_distance < col_distance: col, intersect = c, i return col @@ -663,7 +709,7 @@ class FromClause(Selectable): Used primarily for error message formatting. """ - return getattr(self, 'name', self.__class__.__name__ + " object") + return getattr(self, "name", self.__class__.__name__ + " object") def _reset_exported(self): """delete memoized collections when a FromClause is cloned.""" @@ -683,7 +729,7 @@ class FromClause(Selectable): """ - if '_columns' not in self.__dict__: + if "_columns" not in self.__dict__: self._init_collections() self._populate_column_collection() return self._columns.as_immutable() @@ -706,14 +752,16 @@ class FromClause(Selectable): self._populate_column_collection() return self.foreign_keys - c = property(attrgetter('columns'), - doc="An alias for the :attr:`.columns` attribute.") - _select_iterable = property(attrgetter('columns')) + c = property( + attrgetter("columns"), + doc="An alias for the :attr:`.columns` attribute.", + ) + _select_iterable = property(attrgetter("columns")) def _init_collections(self): - assert '_columns' not in self.__dict__ - assert 'primary_key' not in self.__dict__ - assert 'foreign_keys' not in self.__dict__ + assert "_columns" not in self.__dict__ + assert "primary_key" not in self.__dict__ + assert "foreign_keys" not in self.__dict__ self._columns = ColumnCollection() self.primary_key = ColumnSet() @@ -721,7 +769,7 @@ class FromClause(Selectable): @property def _cols_populated(self): - return '_columns' in self.__dict__ + return "_columns" in self.__dict__ def _populate_column_collection(self): """Called on subclasses to establish the .c collection. @@ -758,8 +806,7 @@ class FromClause(Selectable): """ if not self._cols_populated: return None - elif (column.key in self.columns and - self.columns[column.key] is column): + elif column.key in self.columns and self.columns[column.key] is column: return column else: return None @@ -780,7 +827,8 @@ class Join(FromClause): :meth:`.FromClause.join` """ - __visit_name__ = 'join' + + __visit_name__ = "join" _is_join = True @@ -829,8 +877,9 @@ class Join(FromClause): return cls(left, right, onclause, isouter=True, full=full) @classmethod - def _create_join(cls, left, right, onclause=None, isouter=False, - full=False): + def _create_join( + cls, left, right, onclause=None, isouter=False, full=False + ): """Produce a :class:`.Join` object, given two :class:`.FromClause` expressions. @@ -882,26 +931,34 @@ class Join(FromClause): self.left.description, id(self.left), self.right.description, - id(self.right)) + id(self.right), + ) def is_derived_from(self, fromclause): - return fromclause is self or \ - self.left.is_derived_from(fromclause) or \ - self.right.is_derived_from(fromclause) + return ( + fromclause is self + or self.left.is_derived_from(fromclause) + or self.right.is_derived_from(fromclause) + ) def self_group(self, against=None): return FromGrouping(self) @util.dependencies("sqlalchemy.sql.util") def _populate_column_collection(self, sqlutil): - columns = [c for c in self.left.columns] + \ - [c for c in self.right.columns] + columns = [c for c in self.left.columns] + [ + c for c in self.right.columns + ] - self.primary_key.extend(sqlutil.reduce_columns( - (c for c in columns if c.primary_key), self.onclause)) + self.primary_key.extend( + sqlutil.reduce_columns( + (c for c in columns if c.primary_key), self.onclause + ) + ) self._columns.update((col._label, col) for col in columns) - self.foreign_keys.update(itertools.chain( - *[col.foreign_keys for col in columns])) + self.foreign_keys.update( + itertools.chain(*[col.foreign_keys for col in columns]) + ) def _refresh_for_new_column(self, column): col = self.left._refresh_for_new_column(column) @@ -933,9 +990,14 @@ class Join(FromClause): return self._join_condition(left, right, a_subset=left_right) @classmethod - def _join_condition(cls, a, b, ignore_nonexistent_tables=False, - a_subset=None, - consider_as_foreign_keys=None): + def _join_condition( + cls, + a, + b, + ignore_nonexistent_tables=False, + a_subset=None, + consider_as_foreign_keys=None, + ): """create a join condition between two tables or selectables. e.g.:: @@ -963,26 +1025,31 @@ class Join(FromClause): """ constraints = cls._joincond_scan_left_right( - a, a_subset, b, consider_as_foreign_keys) + a, a_subset, b, consider_as_foreign_keys + ) if len(constraints) > 1: cls._joincond_trim_constraints( - a, b, constraints, consider_as_foreign_keys) + a, b, constraints, consider_as_foreign_keys + ) if len(constraints) == 0: if isinstance(b, FromGrouping): - hint = " Perhaps you meant to convert the right side to a "\ + hint = ( + " Perhaps you meant to convert the right side to a " "subquery using alias()?" + ) else: hint = "" raise exc.NoForeignKeysError( "Can't find any foreign key relationships " - "between '%s' and '%s'.%s" % - (a.description, b.description, hint)) + "between '%s' and '%s'.%s" + % (a.description, b.description, hint) + ) crit = [(x == y) for x, y in list(constraints.values())[0]] if len(crit) == 1: - return (crit[0]) + return crit[0] else: return and_(*crit) @@ -994,24 +1061,30 @@ class Join(FromClause): left_right = None constraints = cls._joincond_scan_left_right( - a=left, b=right, a_subset=left_right, - consider_as_foreign_keys=consider_as_foreign_keys) + a=left, + b=right, + a_subset=left_right, + consider_as_foreign_keys=consider_as_foreign_keys, + ) return bool(constraints) @classmethod def _joincond_scan_left_right( - cls, a, a_subset, b, consider_as_foreign_keys): + cls, a, a_subset, b, consider_as_foreign_keys + ): constraints = collections.defaultdict(list) for left in (a_subset, a): if left is None: continue for fk in sorted( - b.foreign_keys, - key=lambda fk: fk.parent._creation_order): - if consider_as_foreign_keys is not None and \ - fk.parent not in consider_as_foreign_keys: + b.foreign_keys, key=lambda fk: fk.parent._creation_order + ): + if ( + consider_as_foreign_keys is not None + and fk.parent not in consider_as_foreign_keys + ): continue try: col = fk.get_referent(left) @@ -1025,10 +1098,12 @@ class Join(FromClause): constraints[fk.constraint].append((col, fk.parent)) if left is not b: for fk in sorted( - left.foreign_keys, - key=lambda fk: fk.parent._creation_order): - if consider_as_foreign_keys is not None and \ - fk.parent not in consider_as_foreign_keys: + left.foreign_keys, key=lambda fk: fk.parent._creation_order + ): + if ( + consider_as_foreign_keys is not None + and fk.parent not in consider_as_foreign_keys + ): continue try: col = fk.get_referent(b) @@ -1046,14 +1121,16 @@ class Join(FromClause): @classmethod def _joincond_trim_constraints( - cls, a, b, constraints, consider_as_foreign_keys): + cls, a, b, constraints, consider_as_foreign_keys + ): # more than one constraint matched. narrow down the list # to include just those FKCs that match exactly to # "consider_as_foreign_keys". if consider_as_foreign_keys: for const in list(constraints): if set(f.parent for f in const.elements) != set( - consider_as_foreign_keys): + consider_as_foreign_keys + ): del constraints[const] # if still multiple constraints, but @@ -1070,8 +1147,8 @@ class Join(FromClause): "tables have more than one foreign key " "constraint relationship between them. " "Please specify the 'onclause' of this " - "join explicitly." % (a.description, b.description)) - + "join explicitly." % (a.description, b.description) + ) def select(self, whereclause=None, **kwargs): r"""Create a :class:`.Select` from this :class:`.Join`. @@ -1200,27 +1277,37 @@ class Join(FromClause): """ if flat: assert name is None, "Can't send name argument with flat" - left_a, right_a = self.left.alias(flat=True), \ - self.right.alias(flat=True) - adapter = sqlutil.ClauseAdapter(left_a).\ - chain(sqlutil.ClauseAdapter(right_a)) + left_a, right_a = ( + self.left.alias(flat=True), + self.right.alias(flat=True), + ) + adapter = sqlutil.ClauseAdapter(left_a).chain( + sqlutil.ClauseAdapter(right_a) + ) - return left_a.join(right_a, adapter.traverse(self.onclause), - isouter=self.isouter, full=self.full) + return left_a.join( + right_a, + adapter.traverse(self.onclause), + isouter=self.isouter, + full=self.full, + ) else: return self.select(use_labels=True, correlate=False).alias(name) @property def _hide_froms(self): - return itertools.chain(*[_from_objects(x.left, x.right) - for x in self._cloned_set]) + return itertools.chain( + *[_from_objects(x.left, x.right) for x in self._cloned_set] + ) @property def _from_objects(self): - return [self] + \ - self.onclause._from_objects + \ - self.left._from_objects + \ - self.right._from_objects + return ( + [self] + + self.onclause._from_objects + + self.left._from_objects + + self.right._from_objects + ) class Alias(FromClause): @@ -1236,7 +1323,7 @@ class Alias(FromClause): """ - __visit_name__ = 'alias' + __visit_name__ = "alias" named_with_column = True _is_from_container = True @@ -1252,15 +1339,16 @@ class Alias(FromClause): self.element = selectable if name is None: if self.original.named_with_column: - name = getattr(self.original, 'name', None) - name = _anonymous_label('%%(%d %s)s' % (id(self), name - or 'anon')) + name = getattr(self.original, "name", None) + name = _anonymous_label("%%(%d %s)s" % (id(self), name or "anon")) self.name = name def self_group(self, against=None): - if isinstance(against, CompoundSelect) and \ - isinstance(self.original, Select) and \ - self.original._needs_parens_for_grouping(): + if ( + isinstance(against, CompoundSelect) + and isinstance(self.original, Select) + and self.original._needs_parens_for_grouping() + ): return FromGrouping(self) return super(Alias, self).self_group(against=against) @@ -1270,14 +1358,15 @@ class Alias(FromClause): if util.py3k: return self.name else: - return self.name.encode('ascii', 'backslashreplace') + return self.name.encode("ascii", "backslashreplace") def as_scalar(self): try: return self.element.as_scalar() except AttributeError: - raise AttributeError("Element %s does not support " - "'as_scalar()'" % self.element) + raise AttributeError( + "Element %s does not support " "'as_scalar()'" % self.element + ) def is_derived_from(self, fromclause): if fromclause in self._cloned_set: @@ -1344,7 +1433,7 @@ class Lateral(Alias): """ - __visit_name__ = 'lateral' + __visit_name__ = "lateral" _is_lateral = True @@ -1363,11 +1452,9 @@ class TableSample(Alias): """ - __visit_name__ = 'tablesample' + __visit_name__ = "tablesample" - def __init__(self, selectable, sampling, - name=None, - seed=None): + def __init__(self, selectable, sampling, name=None, seed=None): self.sampling = sampling self.seed = seed super(TableSample, self).__init__(selectable, name=name) @@ -1390,14 +1477,18 @@ class CTE(Generative, HasSuffixes, Alias): .. versionadded:: 0.7.6 """ - __visit_name__ = 'cte' - - def __init__(self, selectable, - name=None, - recursive=False, - _cte_alias=None, - _restates=frozenset(), - _suffixes=None): + + __visit_name__ = "cte" + + def __init__( + self, + selectable, + name=None, + recursive=False, + _cte_alias=None, + _restates=frozenset(), + _suffixes=None, + ): self.recursive = recursive self._cte_alias = _cte_alias self._restates = _restates @@ -1409,9 +1500,9 @@ class CTE(Generative, HasSuffixes, Alias): super(CTE, self)._copy_internals(clone, **kw) if self._cte_alias is not None: self._cte_alias = clone(self._cte_alias, **kw) - self._restates = frozenset([ - clone(elem, **kw) for elem in self._restates - ]) + self._restates = frozenset( + [clone(elem, **kw) for elem in self._restates] + ) @util.dependencies("sqlalchemy.sql.dml") def _populate_column_collection(self, dml): @@ -1428,7 +1519,7 @@ class CTE(Generative, HasSuffixes, Alias): name=name, recursive=self.recursive, _cte_alias=self, - _suffixes=self._suffixes + _suffixes=self._suffixes, ) def union(self, other): @@ -1437,7 +1528,7 @@ class CTE(Generative, HasSuffixes, Alias): name=self.name, recursive=self.recursive, _restates=self._restates.union([self]), - _suffixes=self._suffixes + _suffixes=self._suffixes, ) def union_all(self, other): @@ -1446,7 +1537,7 @@ class CTE(Generative, HasSuffixes, Alias): name=self.name, recursive=self.recursive, _restates=self._restates.union([self]), - _suffixes=self._suffixes + _suffixes=self._suffixes, ) @@ -1620,7 +1711,8 @@ class HasCTE(object): class FromGrouping(FromClause): """Represent a grouping of a FROM clause""" - __visit_name__ = 'grouping' + + __visit_name__ = "grouping" def __init__(self, element): self.element = element @@ -1651,7 +1743,7 @@ class FromGrouping(FromClause): return self.element._hide_froms def get_children(self, **kwargs): - return self.element, + return (self.element,) def _copy_internals(self, clone=_clone, **kw): self.element = clone(self.element, **kw) @@ -1664,10 +1756,10 @@ class FromGrouping(FromClause): return getattr(self.element, attr) def __getstate__(self): - return {'element': self.element} + return {"element": self.element} def __setstate__(self, state): - self.element = state['element'] + self.element = state["element"] class TableClause(Immutable, FromClause): @@ -1699,7 +1791,7 @@ class TableClause(Immutable, FromClause): """ - __visit_name__ = 'table' + __visit_name__ = "table" named_with_column = True @@ -1744,7 +1836,7 @@ class TableClause(Immutable, FromClause): if util.py3k: return self.name else: - return self.name.encode('ascii', 'backslashreplace') + return self.name.encode("ascii", "backslashreplace") def append_column(self, c): self._columns[c.key] = c @@ -1773,7 +1865,8 @@ class TableClause(Immutable, FromClause): @util.dependencies("sqlalchemy.sql.dml") def update( - self, dml, whereclause=None, values=None, inline=False, **kwargs): + self, dml, whereclause=None, values=None, inline=False, **kwargs + ): """Generate an :func:`.update` construct against this :class:`.TableClause`. @@ -1785,8 +1878,13 @@ class TableClause(Immutable, FromClause): """ - return dml.Update(self, whereclause=whereclause, - values=values, inline=inline, **kwargs) + return dml.Update( + self, + whereclause=whereclause, + values=values, + inline=inline, + **kwargs + ) @util.dependencies("sqlalchemy.sql.dml") def delete(self, dml, whereclause=None, **kwargs): @@ -1809,7 +1907,6 @@ class TableClause(Immutable, FromClause): class ForUpdateArg(ClauseElement): - @classmethod def parse_legacy_select(self, arg): """Parse the for_update argument of :func:`.select`. @@ -1836,11 +1933,11 @@ class ForUpdateArg(ClauseElement): return None nowait = read = False - if arg == 'nowait': + if arg == "nowait": nowait = True - elif arg == 'read': + elif arg == "read": read = True - elif arg == 'read_nowait': + elif arg == "read_nowait": read = nowait = True elif arg is not True: raise exc.ArgumentError("Unknown for_update argument: %r" % arg) @@ -1860,12 +1957,12 @@ class ForUpdateArg(ClauseElement): def __eq__(self, other): return ( - isinstance(other, ForUpdateArg) and - other.nowait == self.nowait and - other.read == self.read and - other.skip_locked == self.skip_locked and - other.key_share == self.key_share and - other.of is self.of + isinstance(other, ForUpdateArg) + and other.nowait == self.nowait + and other.read == self.read + and other.skip_locked == self.skip_locked + and other.key_share == self.key_share + and other.of is self.of ) def __hash__(self): @@ -1876,8 +1973,13 @@ class ForUpdateArg(ClauseElement): self.of = [clone(col, **kw) for col in self.of] def __init__( - self, nowait=False, read=False, of=None, - skip_locked=False, key_share=False): + self, + nowait=False, + read=False, + of=None, + skip_locked=False, + key_share=False, + ): """Represents arguments specified to :meth:`.Select.for_update`. .. versionadded:: 0.9.0 @@ -1889,8 +1991,9 @@ class ForUpdateArg(ClauseElement): self.skip_locked = skip_locked self.key_share = key_share if of is not None: - self.of = [_interpret_as_column_or_from(elem) - for elem in util.to_list(of)] + self.of = [ + _interpret_as_column_or_from(elem) for elem in util.to_list(of) + ] else: self.of = None @@ -1930,17 +2033,20 @@ class SelectBase(HasCTE, Executable, FromClause): return self.as_scalar().label(name) @_generative - @util.deprecated('0.6', - message="``autocommit()`` is deprecated. Use " - ":meth:`.Executable.execution_options` with the " - "'autocommit' flag.") + @util.deprecated( + "0.6", + message="``autocommit()`` is deprecated. Use " + ":meth:`.Executable.execution_options` with the " + "'autocommit' flag.", + ) def autocommit(self): """return a new selectable with the 'autocommit' flag set to True. """ - self._execution_options = \ - self._execution_options.union({'autocommit': True}) + self._execution_options = self._execution_options.union( + {"autocommit": True} + ) def _generate(self): """Override the default _generate() method to also clear out @@ -1973,34 +2079,38 @@ class GenerativeSelect(SelectBase): used for other SELECT-like objects, e.g. :class:`.TextAsFrom`. """ + _order_by_clause = ClauseList() _group_by_clause = ClauseList() _limit_clause = None _offset_clause = None _for_update_arg = None - def __init__(self, - use_labels=False, - for_update=False, - limit=None, - offset=None, - order_by=None, - group_by=None, - bind=None, - autocommit=None): + def __init__( + self, + use_labels=False, + for_update=False, + limit=None, + offset=None, + order_by=None, + group_by=None, + bind=None, + autocommit=None, + ): self.use_labels = use_labels if for_update is not False: - self._for_update_arg = (ForUpdateArg. - parse_legacy_select(for_update)) + self._for_update_arg = ForUpdateArg.parse_legacy_select(for_update) if autocommit is not None: - util.warn_deprecated('autocommit on select() is ' - 'deprecated. Use .execution_options(a' - 'utocommit=True)') - self._execution_options = \ - self._execution_options.union( - {'autocommit': autocommit}) + util.warn_deprecated( + "autocommit on select() is " + "deprecated. Use .execution_options(a" + "utocommit=True)" + ) + self._execution_options = self._execution_options.union( + {"autocommit": autocommit} + ) if limit is not None: self._limit_clause = _offset_or_limit_clause(limit) if offset is not None: @@ -2010,11 +2120,13 @@ class GenerativeSelect(SelectBase): if order_by is not None: self._order_by_clause = ClauseList( *util.to_list(order_by), - _literal_as_text=_literal_and_labels_as_label_reference) + _literal_as_text=_literal_and_labels_as_label_reference + ) if group_by is not None: self._group_by_clause = ClauseList( *util.to_list(group_by), - _literal_as_text=_literal_as_label_reference) + _literal_as_text=_literal_as_label_reference + ) @property def for_update(self): @@ -2030,8 +2142,14 @@ class GenerativeSelect(SelectBase): self._for_update_arg = ForUpdateArg.parse_legacy_select(value) @_generative - def with_for_update(self, nowait=False, read=False, of=None, - skip_locked=False, key_share=False): + def with_for_update( + self, + nowait=False, + read=False, + of=None, + skip_locked=False, + key_share=False, + ): """Specify a ``FOR UPDATE`` clause for this :class:`.GenerativeSelect`. E.g.:: @@ -2079,9 +2197,13 @@ class GenerativeSelect(SelectBase): .. versionadded:: 1.1.0 """ - self._for_update_arg = ForUpdateArg(nowait=nowait, read=read, of=of, - skip_locked=skip_locked, - key_share=key_share) + self._for_update_arg = ForUpdateArg( + nowait=nowait, + read=read, + of=of, + skip_locked=skip_locked, + key_share=key_share, + ) @_generative def apply_labels(self): @@ -2209,11 +2331,12 @@ class GenerativeSelect(SelectBase): if len(clauses) == 1 and clauses[0] is None: self._order_by_clause = ClauseList() else: - if getattr(self, '_order_by_clause', None) is not None: + if getattr(self, "_order_by_clause", None) is not None: clauses = list(self._order_by_clause) + list(clauses) self._order_by_clause = ClauseList( *clauses, - _literal_as_text=_literal_and_labels_as_label_reference) + _literal_as_text=_literal_and_labels_as_label_reference + ) def append_group_by(self, *clauses): """Append the given GROUP BY criterion applied to this selectable. @@ -2228,10 +2351,11 @@ class GenerativeSelect(SelectBase): if len(clauses) == 1 and clauses[0] is None: self._group_by_clause = ClauseList() else: - if getattr(self, '_group_by_clause', None) is not None: + if getattr(self, "_group_by_clause", None) is not None: clauses = list(self._group_by_clause) + list(clauses) self._group_by_clause = ClauseList( - *clauses, _literal_as_text=_literal_as_label_reference) + *clauses, _literal_as_text=_literal_as_label_reference + ) @property def _label_resolve_dict(self): @@ -2265,19 +2389,19 @@ class CompoundSelect(GenerativeSelect): """ - __visit_name__ = 'compound_select' + __visit_name__ = "compound_select" - UNION = util.symbol('UNION') - UNION_ALL = util.symbol('UNION ALL') - EXCEPT = util.symbol('EXCEPT') - EXCEPT_ALL = util.symbol('EXCEPT ALL') - INTERSECT = util.symbol('INTERSECT') - INTERSECT_ALL = util.symbol('INTERSECT ALL') + UNION = util.symbol("UNION") + UNION_ALL = util.symbol("UNION ALL") + EXCEPT = util.symbol("EXCEPT") + EXCEPT_ALL = util.symbol("EXCEPT ALL") + INTERSECT = util.symbol("INTERSECT") + INTERSECT_ALL = util.symbol("INTERSECT ALL") _is_from_container = True def __init__(self, keyword, *selects, **kwargs): - self._auto_correlate = kwargs.pop('correlate', False) + self._auto_correlate = kwargs.pop("correlate", False) self.keyword = keyword self.selects = [] @@ -2291,12 +2415,16 @@ class CompoundSelect(GenerativeSelect): numcols = len(s.c._all_columns) elif len(s.c._all_columns) != numcols: raise exc.ArgumentError( - 'All selectables passed to ' - 'CompoundSelect must have identical numbers of ' - 'columns; select #%d has %d columns, select ' - '#%d has %d' % - (1, len(self.selects[0].c._all_columns), - n + 1, len(s.c._all_columns)) + "All selectables passed to " + "CompoundSelect must have identical numbers of " + "columns; select #%d has %d columns, select " + "#%d has %d" + % ( + 1, + len(self.selects[0].c._all_columns), + n + 1, + len(s.c._all_columns), + ) ) self.selects.append(s.self_group(against=self)) @@ -2305,9 +2433,7 @@ class CompoundSelect(GenerativeSelect): @property def _label_resolve_dict(self): - d = dict( - (c.key, c) for c in self.c - ) + d = dict((c.key, c) for c in self.c) return d, d, d @classmethod @@ -2416,8 +2542,7 @@ class CompoundSelect(GenerativeSelect): :func:`select`. """ - return CompoundSelect( - CompoundSelect.INTERSECT_ALL, *selects, **kwargs) + return CompoundSelect(CompoundSelect.INTERSECT_ALL, *selects, **kwargs) def _scalar_type(self): return self.selects[0]._scalar_type() @@ -2445,8 +2570,10 @@ class CompoundSelect(GenerativeSelect): # those fks too. proxy = cols[0]._make_proxy( - self, name=cols[0]._label if self.use_labels else None, - key=cols[0]._key_label if self.use_labels else None) + self, + name=cols[0]._label if self.use_labels else None, + key=cols[0]._key_label if self.use_labels else None, + ) # hand-construct the "_proxies" collection to include all # derived columns place a 'weight' annotation corresponding @@ -2455,7 +2582,8 @@ class CompoundSelect(GenerativeSelect): # conflicts proxy._proxies = [ - c._annotate({'weight': i + 1}) for (i, c) in enumerate(cols)] + c._annotate({"weight": i + 1}) for (i, c) in enumerate(cols) + ] def _refresh_for_new_column(self, column): for s in self.selects: @@ -2464,25 +2592,32 @@ class CompoundSelect(GenerativeSelect): if not self._cols_populated: return None - raise NotImplementedError("CompoundSelect constructs don't support " - "addition of columns to underlying " - "selectables") + raise NotImplementedError( + "CompoundSelect constructs don't support " + "addition of columns to underlying " + "selectables" + ) def _copy_internals(self, clone=_clone, **kw): super(CompoundSelect, self)._copy_internals(clone, **kw) self._reset_exported() self.selects = [clone(s, **kw) for s in self.selects] - if hasattr(self, '_col_map'): + if hasattr(self, "_col_map"): del self._col_map for attr in ( - '_order_by_clause', '_group_by_clause', '_for_update_arg'): + "_order_by_clause", + "_group_by_clause", + "_for_update_arg", + ): if getattr(self, attr) is not None: setattr(self, attr, clone(getattr(self, attr), **kw)) def get_children(self, column_collections=True, **kwargs): - return (column_collections and list(self.c) or []) \ - + [self._order_by_clause, self._group_by_clause] \ + return ( + (column_collections and list(self.c) or []) + + [self._order_by_clause, self._group_by_clause] + list(self.selects) + ) def bind(self): if self._bind: @@ -2496,6 +2631,7 @@ class CompoundSelect(GenerativeSelect): def _set_bind(self, bind): self._bind = bind + bind = property(bind, _set_bind) @@ -2504,7 +2640,7 @@ class Select(HasPrefixes, HasSuffixes, GenerativeSelect): """ - __visit_name__ = 'select' + __visit_name__ = "select" _prefixes = () _suffixes = () @@ -2517,16 +2653,18 @@ class Select(HasPrefixes, HasSuffixes, GenerativeSelect): _memoized_property = SelectBase._memoized_property _is_select = True - def __init__(self, - columns=None, - whereclause=None, - from_obj=None, - distinct=False, - having=None, - correlate=True, - prefixes=None, - suffixes=None, - **kwargs): + def __init__( + self, + columns=None, + whereclause=None, + from_obj=None, + distinct=False, + having=None, + correlate=True, + prefixes=None, + suffixes=None, + **kwargs + ): """Construct a new :class:`.Select`. Similar functionality is also available via the @@ -2729,22 +2867,23 @@ class Select(HasPrefixes, HasSuffixes, GenerativeSelect): self._distinct = True else: self._distinct = [ - _literal_as_text(e) - for e in util.to_list(distinct) + _literal_as_text(e) for e in util.to_list(distinct) ] if from_obj is not None: self._from_obj = util.OrderedSet( - _interpret_as_from(f) - for f in util.to_list(from_obj)) + _interpret_as_from(f) for f in util.to_list(from_obj) + ) else: self._from_obj = util.OrderedSet() try: cols_present = bool(columns) except TypeError: - raise exc.ArgumentError("columns argument to select() must " - "be a Python list or other iterable") + raise exc.ArgumentError( + "columns argument to select() must " + "be a Python list or other iterable" + ) if cols_present: self._raw_columns = [] @@ -2757,14 +2896,16 @@ class Select(HasPrefixes, HasSuffixes, GenerativeSelect): self._raw_columns = [] if whereclause is not None: - self._whereclause = _literal_as_text( - whereclause).self_group(against=operators._asbool) + self._whereclause = _literal_as_text(whereclause).self_group( + against=operators._asbool + ) else: self._whereclause = None if having is not None: - self._having = _literal_as_text( - having).self_group(against=operators._asbool) + self._having = _literal_as_text(having).self_group( + against=operators._asbool + ) else: self._having = None @@ -2789,12 +2930,14 @@ class Select(HasPrefixes, HasSuffixes, GenerativeSelect): for item in itertools.chain( _from_objects(*self._raw_columns), _from_objects(self._whereclause) - if self._whereclause is not None else (), - self._from_obj + if self._whereclause is not None + else (), + self._from_obj, ): if item is self: raise exc.InvalidRequestError( - "select() construct refers to itself as a FROM") + "select() construct refers to itself as a FROM" + ) if translate and item in translate: item = translate[item] if not seen.intersection(item._cloned_set): @@ -2803,8 +2946,9 @@ class Select(HasPrefixes, HasSuffixes, GenerativeSelect): return froms - def _get_display_froms(self, explicit_correlate_froms=None, - implicit_correlate_froms=None): + def _get_display_froms( + self, explicit_correlate_froms=None, implicit_correlate_froms=None + ): """Return the full list of 'from' clauses to be displayed. Takes into account a set of existing froms which may be @@ -2815,17 +2959,17 @@ class Select(HasPrefixes, HasSuffixes, GenerativeSelect): """ froms = self._froms - toremove = set(itertools.chain(*[ - _expand_cloned(f._hide_froms) - for f in froms])) + toremove = set( + itertools.chain(*[_expand_cloned(f._hide_froms) for f in froms]) + ) if toremove: # if we're maintaining clones of froms, # add the copies out to the toremove list. only include # clones that are lexical equivalents. if self._from_cloned: toremove.update( - self._from_cloned[f] for f in - toremove.intersection(self._from_cloned) + self._from_cloned[f] + for f in toremove.intersection(self._from_cloned) if self._from_cloned[f]._is_lexical_equivalent(f) ) # filter out to FROM clauses not in the list, @@ -2836,41 +2980,53 @@ class Select(HasPrefixes, HasSuffixes, GenerativeSelect): to_correlate = self._correlate if to_correlate: froms = [ - f for f in froms if f not in - _cloned_intersection( + f + for f in froms + if f + not in _cloned_intersection( _cloned_intersection( - froms, explicit_correlate_froms or ()), - to_correlate + froms, explicit_correlate_froms or () + ), + to_correlate, ) ] if self._correlate_except is not None: froms = [ - f for f in froms if f not in - _cloned_difference( + f + for f in froms + if f + not in _cloned_difference( _cloned_intersection( - froms, explicit_correlate_froms or ()), - self._correlate_except + froms, explicit_correlate_froms or () + ), + self._correlate_except, ) ] - if self._auto_correlate and \ - implicit_correlate_froms and \ - len(froms) > 1: + if ( + self._auto_correlate + and implicit_correlate_froms + and len(froms) > 1 + ): froms = [ - f for f in froms if f not in - _cloned_intersection(froms, implicit_correlate_froms) + f + for f in froms + if f + not in _cloned_intersection(froms, implicit_correlate_froms) ] if not len(froms): - raise exc.InvalidRequestError("Select statement '%s" - "' returned no FROM clauses " - "due to auto-correlation; " - "specify correlate(<tables>) " - "to control correlation " - "manually." % self) + raise exc.InvalidRequestError( + "Select statement '%s" + "' returned no FROM clauses " + "due to auto-correlation; " + "specify correlate(<tables>) " + "to control correlation " + "manually." % self + ) return froms @@ -2885,7 +3041,7 @@ class Select(HasPrefixes, HasSuffixes, GenerativeSelect): return self._get_display_froms() - def with_statement_hint(self, text, dialect_name='*'): + def with_statement_hint(self, text, dialect_name="*"): """add a statement hint to this :class:`.Select`. This method is similar to :meth:`.Select.with_hint` except that @@ -2906,7 +3062,7 @@ class Select(HasPrefixes, HasSuffixes, GenerativeSelect): return self.with_hint(None, text, dialect_name) @_generative - def with_hint(self, selectable, text, dialect_name='*'): + def with_hint(self, selectable, text, dialect_name="*"): r"""Add an indexing or other executional context hint for the given selectable to this :class:`.Select`. @@ -2940,17 +3096,18 @@ class Select(HasPrefixes, HasSuffixes, GenerativeSelect): """ if selectable is None: - self._statement_hints += ((dialect_name, text), ) + self._statement_hints += ((dialect_name, text),) else: - self._hints = self._hints.union( - {(selectable, dialect_name): text}) + self._hints = self._hints.union({(selectable, dialect_name): text}) @property def type(self): - raise exc.InvalidRequestError("Select objects don't have a type. " - "Call as_scalar() on this Select " - "object to return a 'scalar' version " - "of this Select.") + raise exc.InvalidRequestError( + "Select objects don't have a type. " + "Call as_scalar() on this Select " + "object to return a 'scalar' version " + "of this Select." + ) @_memoized_property.method def locate_all_froms(self): @@ -2977,10 +3134,13 @@ class Select(HasPrefixes, HasSuffixes, GenerativeSelect): with_cols = dict( (c._resolve_label or c._label or c.key, c) for c in _select_iterables(self._raw_columns) - if c._allow_label_resolve) + if c._allow_label_resolve + ) only_froms = dict( - (c.key, c) for c in - _select_iterables(self.froms) if c._allow_label_resolve) + (c.key, c) + for c in _select_iterables(self.froms) + if c._allow_label_resolve + ) only_cols = with_cols.copy() for key, value in only_froms.items(): with_cols.setdefault(key, value) @@ -3011,11 +3171,13 @@ class Select(HasPrefixes, HasSuffixes, GenerativeSelect): # gets cleared on each generation. previously we were "baking" # _froms into self._from_obj. self._from_cloned = from_cloned = dict( - (f, clone(f, **kw)) for f in self._from_obj.union(self._froms)) + (f, clone(f, **kw)) for f in self._from_obj.union(self._froms) + ) # 3. update persistent _from_obj with the cloned versions. - self._from_obj = util.OrderedSet(from_cloned[f] for f in - self._from_obj) + self._from_obj = util.OrderedSet( + from_cloned[f] for f in self._from_obj + ) # the _correlate collection is done separately, what can happen # here is the same item is _correlate as in _from_obj but the @@ -3023,16 +3185,22 @@ class Select(HasPrefixes, HasSuffixes, GenerativeSelect): # RelationshipProperty.Comparator._criterion_exists() does # this). Also keep _correlate liberally open with its previous # contents, as this set is used for matching, not rendering. - self._correlate = set(clone(f) for f in - self._correlate).union(self._correlate) + self._correlate = set(clone(f) for f in self._correlate).union( + self._correlate + ) # 4. clone other things. The difficulty here is that Column # objects are not actually cloned, and refer to their original # .table, resulting in the wrong "from" parent after a clone # operation. Hence _from_cloned and _from_obj supersede what is # present here. self._raw_columns = [clone(c, **kw) for c in self._raw_columns] - for attr in '_whereclause', '_having', '_order_by_clause', \ - '_group_by_clause', '_for_update_arg': + for attr in ( + "_whereclause", + "_having", + "_order_by_clause", + "_group_by_clause", + "_for_update_arg", + ): if getattr(self, attr) is not None: setattr(self, attr, clone(getattr(self, attr), **kw)) @@ -3043,12 +3211,21 @@ class Select(HasPrefixes, HasSuffixes, GenerativeSelect): def get_children(self, column_collections=True, **kwargs): """return child elements as per the ClauseElement specification.""" - return (column_collections and list(self.columns) or []) + \ - self._raw_columns + list(self._froms) + \ - [x for x in - (self._whereclause, self._having, - self._order_by_clause, self._group_by_clause) - if x is not None] + return ( + (column_collections and list(self.columns) or []) + + self._raw_columns + + list(self._froms) + + [ + x + for x in ( + self._whereclause, + self._having, + self._order_by_clause, + self._group_by_clause, + ) + if x is not None + ] + ) @_generative def column(self, column): @@ -3094,7 +3271,7 @@ class Select(HasPrefixes, HasSuffixes, GenerativeSelect): sqlutil.reduce_columns( self.inner_columns, only_synonyms=only_synonyms, - *(self._whereclause, ) + tuple(self._from_obj) + *(self._whereclause,) + tuple(self._from_obj) ) ) @@ -3307,7 +3484,8 @@ class Select(HasPrefixes, HasSuffixes, GenerativeSelect): self._correlate = () else: self._correlate = set(self._correlate).union( - _interpret_as_from(f) for f in fromclauses) + _interpret_as_from(f) for f in fromclauses + ) @_generative def correlate_except(self, *fromclauses): @@ -3349,7 +3527,8 @@ class Select(HasPrefixes, HasSuffixes, GenerativeSelect): self._correlate_except = () else: self._correlate_except = set(self._correlate_except or ()).union( - _interpret_as_from(f) for f in fromclauses) + _interpret_as_from(f) for f in fromclauses + ) def append_correlation(self, fromclause): """append the given correlation expression to this select() @@ -3363,7 +3542,8 @@ class Select(HasPrefixes, HasSuffixes, GenerativeSelect): self._auto_correlate = False self._correlate = set(self._correlate).union( - _interpret_as_from(f) for f in fromclause) + _interpret_as_from(f) for f in fromclause + ) def append_column(self, column): """append the given column expression to the columns clause of this @@ -3415,8 +3595,7 @@ class Select(HasPrefixes, HasSuffixes, GenerativeSelect): """ self._reset_exported() - self._whereclause = and_( - True_._ifnone(self._whereclause), whereclause) + self._whereclause = and_(True_._ifnone(self._whereclause), whereclause) def append_having(self, having): """append the given expression to this select() construct's HAVING @@ -3463,19 +3642,17 @@ class Select(HasPrefixes, HasSuffixes, GenerativeSelect): return [ name_for_col(c) - for c in util.unique_list( - _select_iterables(self._raw_columns)) + for c in util.unique_list(_select_iterables(self._raw_columns)) ] else: return [ (None, c) - for c in util.unique_list( - _select_iterables(self._raw_columns)) + for c in util.unique_list(_select_iterables(self._raw_columns)) ] def _populate_column_collection(self): for name, c in self._columns_plus_names: - if not hasattr(c, '_make_proxy'): + if not hasattr(c, "_make_proxy"): continue if name is None: key = None @@ -3486,9 +3663,7 @@ class Select(HasPrefixes, HasSuffixes, GenerativeSelect): else: key = None - c._make_proxy(self, key=key, - name=name, - name_is_truncatable=True) + c._make_proxy(self, key=key, name=name, name_is_truncatable=True) def _refresh_for_new_column(self, column): for fromclause in self._froms: @@ -3501,15 +3676,16 @@ class Select(HasPrefixes, HasSuffixes, GenerativeSelect): self, name=col._label if self.use_labels else None, key=col._key_label if self.use_labels else None, - name_is_truncatable=True) + name_is_truncatable=True, + ) return None return None def _needs_parens_for_grouping(self): return ( - self._limit_clause is not None or - self._offset_clause is not None or - bool(self._order_by_clause.clauses) + self._limit_clause is not None + or self._offset_clause is not None + or bool(self._order_by_clause.clauses) ) def self_group(self, against=None): @@ -3521,8 +3697,10 @@ class Select(HasPrefixes, HasSuffixes, GenerativeSelect): expressions and should not require explicit use. """ - if isinstance(against, CompoundSelect) and \ - not self._needs_parens_for_grouping(): + if ( + isinstance(against, CompoundSelect) + and not self._needs_parens_for_grouping() + ): return self return FromGrouping(self) @@ -3586,6 +3764,7 @@ class Select(HasPrefixes, HasSuffixes, GenerativeSelect): def _set_bind(self, bind): self._bind = bind + bind = property(bind, _set_bind) @@ -3600,9 +3779,12 @@ class ScalarSelect(Generative, Grouping): @property def columns(self): - raise exc.InvalidRequestError('Scalar Select expression has no ' - 'columns; use this object directly ' - 'within a column-level expression.') + raise exc.InvalidRequestError( + "Scalar Select expression has no " + "columns; use this object directly " + "within a column-level expression." + ) + c = columns @_generative @@ -3621,6 +3803,7 @@ class Exists(UnaryExpression): """Represent an ``EXISTS`` clause. """ + __visit_name__ = UnaryExpression.__visit_name__ _from_objects = [] @@ -3646,12 +3829,16 @@ class Exists(UnaryExpression): s = args[0] else: if not args: - args = ([literal_column('*')],) + args = ([literal_column("*")],) s = Select(*args, **kwargs).as_scalar().self_group() - UnaryExpression.__init__(self, s, operator=operators.exists, - type_=type_api.BOOLEANTYPE, - wraps_column_expression=True) + UnaryExpression.__init__( + self, + s, + operator=operators.exists, + type_=type_api.BOOLEANTYPE, + wraps_column_expression=True, + ) def select(self, whereclause=None, **params): return Select([self], whereclause, **params) @@ -3706,6 +3893,7 @@ class TextAsFrom(SelectBase): :meth:`.TextClause.columns` """ + __visit_name__ = "text_as_from" _textual = True |