diff options
Diffstat (limited to 'lib/sqlalchemy/sql/schema.py')
-rw-r--r-- | lib/sqlalchemy/sql/schema.py | 1129 |
1 files changed, 664 insertions, 465 deletions
diff --git a/lib/sqlalchemy/sql/schema.py b/lib/sqlalchemy/sql/schema.py index 3e9aa174a..d6c3f5000 100644 --- a/lib/sqlalchemy/sql/schema.py +++ b/lib/sqlalchemy/sql/schema.py @@ -36,25 +36,31 @@ import operator from . import visitors from . import type_api from .base import _bind_or_error, ColumnCollection -from .elements import ClauseElement, ColumnClause, \ - _as_truncated, TextClause, _literal_as_text,\ - ColumnElement, quoted_name +from .elements import ( + ClauseElement, + ColumnClause, + _as_truncated, + TextClause, + _literal_as_text, + ColumnElement, + quoted_name, +) from .selectable import TableClause import collections import sqlalchemy from . import ddl -RETAIN_SCHEMA = util.symbol('retain_schema') +RETAIN_SCHEMA = util.symbol("retain_schema") BLANK_SCHEMA = util.symbol( - 'blank_schema', + "blank_schema", """Symbol indicating that a :class:`.Table` or :class:`.Sequence` should have 'None' for its schema, even if the parent :class:`.MetaData` has specified a schema. .. versionadded:: 1.0.14 - """ + """, ) @@ -69,11 +75,15 @@ def _get_table_key(name, schema): # break an import cycle def _copy_expression(expression, source_table, target_table): def replace(col): - if isinstance(col, Column) and \ - col.table is source_table and col.key in source_table.c: + if ( + isinstance(col, Column) + and col.table is source_table + and col.key in source_table.c + ): return target_table.c[col.key] else: return None + return visitors.replacement_traverse(expression, {}, replace) @@ -81,7 +91,7 @@ def _copy_expression(expression, source_table, target_table): class SchemaItem(SchemaEventTarget, visitors.Visitable): """Base class for items that define a database schema.""" - __visit_name__ = 'schema_item' + __visit_name__ = "schema_item" def _init_items(self, *args): """Initialize the list of child items for this SchemaItem.""" @@ -95,10 +105,10 @@ class SchemaItem(SchemaEventTarget, visitors.Visitable): return [] def __repr__(self): - return util.generic_repr(self, omit_kwarg=['info']) + return util.generic_repr(self, omit_kwarg=["info"]) @property - @util.deprecated('0.9', 'Use ``<obj>.name.quote``') + @util.deprecated("0.9", "Use ``<obj>.name.quote``") def quote(self): """Return the value of the ``quote`` flag passed to this schema object, for those schema items which @@ -121,7 +131,7 @@ class SchemaItem(SchemaEventTarget, visitors.Visitable): return {} def _schema_item_copy(self, schema_item): - if 'info' in self.__dict__: + if "info" in self.__dict__: schema_item.info = self.info.copy() schema_item.dispatch._update(self.dispatch) return schema_item @@ -396,7 +406,7 @@ class Table(DialectKWArgs, SchemaItem, TableClause): """ - __visit_name__ = 'table' + __visit_name__ = "table" def __new__(cls, *args, **kw): if not args: @@ -408,26 +418,26 @@ class Table(DialectKWArgs, SchemaItem, TableClause): except IndexError: raise TypeError("Table() takes at least two arguments") - schema = kw.get('schema', None) + schema = kw.get("schema", None) if schema is None: schema = metadata.schema elif schema is BLANK_SCHEMA: schema = None - keep_existing = kw.pop('keep_existing', False) - extend_existing = kw.pop('extend_existing', False) - if 'useexisting' in kw: + keep_existing = kw.pop("keep_existing", False) + extend_existing = kw.pop("extend_existing", False) + if "useexisting" in kw: msg = "useexisting is deprecated. Use extend_existing." util.warn_deprecated(msg) if extend_existing: msg = "useexisting is synonymous with extend_existing." raise exc.ArgumentError(msg) - extend_existing = kw.pop('useexisting', False) + extend_existing = kw.pop("useexisting", False) if keep_existing and extend_existing: msg = "keep_existing and extend_existing are mutually exclusive." raise exc.ArgumentError(msg) - mustexist = kw.pop('mustexist', False) + mustexist = kw.pop("mustexist", False) key = _get_table_key(name, schema) if key in metadata.tables: if not keep_existing and not extend_existing and bool(args): @@ -436,15 +446,15 @@ class Table(DialectKWArgs, SchemaItem, TableClause): "instance. Specify 'extend_existing=True' " "to redefine " "options and columns on an " - "existing Table object." % key) + "existing Table object." % key + ) table = metadata.tables[key] if extend_existing: table._init_existing(*args, **kw) return table else: if mustexist: - raise exc.InvalidRequestError( - "Table '%s' not defined" % (key)) + 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) @@ -457,7 +467,7 @@ class Table(DialectKWArgs, SchemaItem, TableClause): metadata._remove_table(name, schema) @property - @util.deprecated('0.9', 'Use ``table.schema.quote``') + @util.deprecated("0.9", "Use ``table.schema.quote``") def quote_schema(self): """Return the value of the ``quote_schema`` flag passed to this :class:`.Table`. @@ -478,23 +488,25 @@ class Table(DialectKWArgs, SchemaItem, TableClause): def _init(self, name, metadata, *args, **kwargs): super(Table, self).__init__( - quoted_name(name, kwargs.pop('quote', None))) + quoted_name(name, kwargs.pop("quote", None)) + ) self.metadata = metadata - self.schema = kwargs.pop('schema', None) + self.schema = kwargs.pop("schema", None) if self.schema is None: self.schema = metadata.schema elif self.schema is BLANK_SCHEMA: self.schema = None else: - quote_schema = kwargs.pop('quote_schema', None) + quote_schema = kwargs.pop("quote_schema", None) self.schema = quoted_name(self.schema, quote_schema) self.indexes = set() self.constraints = set() self._columns = ColumnCollection() - PrimaryKeyConstraint(_implicit_generated=True).\ - _set_parent_with_dispatch(self) + PrimaryKeyConstraint( + _implicit_generated=True + )._set_parent_with_dispatch(self) self.foreign_keys = set() self._extra_dependencies = set() if self.schema is not None: @@ -502,26 +514,26 @@ class Table(DialectKWArgs, SchemaItem, TableClause): else: self.fullname = self.name - autoload_with = kwargs.pop('autoload_with', None) - autoload = kwargs.pop('autoload', autoload_with is not None) + autoload_with = kwargs.pop("autoload_with", None) + autoload = kwargs.pop("autoload", autoload_with is not None) # this argument is only used with _init_existing() - kwargs.pop('autoload_replace', True) + kwargs.pop("autoload_replace", True) _extend_on = kwargs.pop("_extend_on", None) - include_columns = kwargs.pop('include_columns', None) + include_columns = kwargs.pop("include_columns", None) - self.implicit_returning = kwargs.pop('implicit_returning', True) + self.implicit_returning = kwargs.pop("implicit_returning", True) - self.comment = kwargs.pop('comment', None) + self.comment = kwargs.pop("comment", None) - if 'info' in kwargs: - self.info = kwargs.pop('info') - if 'listeners' in kwargs: - listeners = kwargs.pop('listeners') + 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', []) + self._prefixes = kwargs.pop("prefixes", []) self._extra_kwargs(**kwargs) @@ -530,21 +542,29 @@ class Table(DialectKWArgs, SchemaItem, TableClause): # circular foreign keys if autoload: self._autoload( - metadata, autoload_with, - include_columns, _extend_on=_extend_on) + metadata, autoload_with, include_columns, _extend_on=_extend_on + ) # initialize all the column, etc. objects. done after reflection to # allow user-overrides self._init_items(*args) - def _autoload(self, metadata, autoload_with, include_columns, - exclude_columns=(), _extend_on=None): + def _autoload( + self, + metadata, + autoload_with, + include_columns, + exclude_columns=(), + _extend_on=None, + ): if autoload_with: autoload_with.run_callable( autoload_with.dialect.reflecttable, - self, include_columns, exclude_columns, - _extend_on=_extend_on + self, + include_columns, + exclude_columns, + _extend_on=_extend_on, ) else: bind = _bind_or_error( @@ -553,11 +573,14 @@ class Table(DialectKWArgs, SchemaItem, TableClause): "Pass an engine to the Table via " "autoload_with=<someengine>, " "or associate the MetaData with an engine via " - "metadata.bind=<someengine>") + "metadata.bind=<someengine>", + ) bind.run_callable( bind.dialect.reflecttable, - self, include_columns, exclude_columns, - _extend_on=_extend_on + self, + include_columns, + exclude_columns, + _extend_on=_extend_on, ) @property @@ -582,34 +605,36 @@ class Table(DialectKWArgs, SchemaItem, TableClause): return set(fkc.constraint for fkc in self.foreign_keys) def _init_existing(self, *args, **kwargs): - autoload_with = kwargs.pop('autoload_with', None) - autoload = kwargs.pop('autoload', autoload_with is not None) - autoload_replace = kwargs.pop('autoload_replace', True) - schema = kwargs.pop('schema', None) - _extend_on = kwargs.pop('_extend_on', None) + autoload_with = kwargs.pop("autoload_with", None) + autoload = kwargs.pop("autoload", autoload_with is not None) + autoload_replace = kwargs.pop("autoload_replace", True) + schema = kwargs.pop("schema", None) + _extend_on = kwargs.pop("_extend_on", None) if schema and schema != self.schema: raise exc.ArgumentError( "Can't change schema of existing table from '%s' to '%s'", - (self.schema, schema)) + (self.schema, schema), + ) - include_columns = kwargs.pop('include_columns', None) + include_columns = kwargs.pop("include_columns", None) if include_columns is not None: for c in self.c: if c.name not in include_columns: self._columns.remove(c) - for key in ('quote', 'quote_schema'): + for key in ("quote", "quote_schema"): if key in kwargs: raise exc.ArgumentError( - "Can't redefine 'quote' or 'quote_schema' arguments") + "Can't redefine 'quote' or 'quote_schema' arguments" + ) - if 'comment' in kwargs: - self.comment = kwargs.pop('comment', None) + if "comment" in kwargs: + self.comment = kwargs.pop("comment", None) - if 'info' in kwargs: - self.info = kwargs.pop('info') + if "info" in kwargs: + self.info = kwargs.pop("info") if autoload: if not autoload_replace: @@ -620,8 +645,12 @@ class Table(DialectKWArgs, SchemaItem, TableClause): else: exclude_columns = () self._autoload( - self.metadata, autoload_with, - include_columns, exclude_columns, _extend_on=_extend_on) + self.metadata, + autoload_with, + include_columns, + exclude_columns, + _extend_on=_extend_on, + ) self._extra_kwargs(**kwargs) self._init_items(*args) @@ -653,10 +682,12 @@ class Table(DialectKWArgs, SchemaItem, TableClause): return _get_table_key(self.name, self.schema) def __repr__(self): - return "Table(%s)" % ', '.join( - [repr(self.name)] + [repr(self.metadata)] + - [repr(x) for x in self.columns] + - ["%s=%s" % (k, repr(getattr(self, k))) for k in ['schema']]) + return "Table(%s)" % ", ".join( + [repr(self.name)] + + [repr(self.metadata)] + + [repr(x) for x in self.columns] + + ["%s=%s" % (k, repr(getattr(self, k))) for k in ["schema"]] + ) def __str__(self): return _get_table_key(self.description, self.schema) @@ -735,17 +766,19 @@ class Table(DialectKWArgs, SchemaItem, TableClause): def adapt_listener(target, connection, **kw): listener(event_name, target, connection) - event.listen(self, "" + event_name.replace('-', '_'), adapt_listener) + event.listen(self, "" + event_name.replace("-", "_"), adapt_listener) def _set_parent(self, metadata): metadata._add_table(self.name, self.schema, self) self.metadata = metadata - def get_children(self, column_collections=True, - schema_visitor=False, **kw): + def get_children( + self, column_collections=True, schema_visitor=False, **kw + ): if not schema_visitor: return TableClause.get_children( - self, column_collections=column_collections, **kw) + self, column_collections=column_collections, **kw + ) else: if column_collections: return list(self.columns) @@ -758,8 +791,9 @@ class Table(DialectKWArgs, SchemaItem, TableClause): if bind is None: bind = _bind_or_error(self) - return bind.run_callable(bind.dialect.has_table, - self.name, schema=self.schema) + return bind.run_callable( + bind.dialect.has_table, self.name, schema=self.schema + ) def create(self, bind=None, checkfirst=False): """Issue a ``CREATE`` statement for this @@ -774,9 +808,7 @@ class Table(DialectKWArgs, SchemaItem, TableClause): if bind is None: bind = _bind_or_error(self) - bind._run_visitor(ddl.SchemaGenerator, - self, - checkfirst=checkfirst) + bind._run_visitor(ddl.SchemaGenerator, self, checkfirst=checkfirst) def drop(self, bind=None, checkfirst=False): """Issue a ``DROP`` statement for this @@ -790,12 +822,15 @@ class Table(DialectKWArgs, SchemaItem, TableClause): """ if bind is None: bind = _bind_or_error(self) - bind._run_visitor(ddl.SchemaDropper, - self, - checkfirst=checkfirst) - - def tometadata(self, metadata, schema=RETAIN_SCHEMA, - referred_schema_fn=None, name=None): + bind._run_visitor(ddl.SchemaDropper, self, checkfirst=checkfirst) + + def tometadata( + self, + metadata, + schema=RETAIN_SCHEMA, + referred_schema_fn=None, + name=None, + ): """Return a copy of this :class:`.Table` associated with a different :class:`.MetaData`. @@ -868,29 +903,37 @@ class Table(DialectKWArgs, SchemaItem, TableClause): schema = metadata.schema key = _get_table_key(name, schema) if key in metadata.tables: - util.warn("Table '%s' already exists within the given " - "MetaData - not copying." % self.description) + util.warn( + "Table '%s' already exists within the given " + "MetaData - not copying." % self.description + ) return metadata.tables[key] args = [] for c in self.columns: args.append(c.copy(schema=schema)) table = Table( - name, metadata, schema=schema, + name, + metadata, + schema=schema, comment=self.comment, - *args, **self.kwargs + *args, + **self.kwargs ) for c in self.constraints: if isinstance(c, ForeignKeyConstraint): referred_schema = c._referred_schema if referred_schema_fn: fk_constraint_schema = referred_schema_fn( - self, schema, c, referred_schema) + self, schema, c, referred_schema + ) else: fk_constraint_schema = ( - schema if referred_schema == self.schema else None) + schema if referred_schema == self.schema else None + ) table.append_constraint( - c.copy(schema=fk_constraint_schema, target_table=table)) + c.copy(schema=fk_constraint_schema, target_table=table) + ) elif not c._type_bound: # skip unique constraints that would be generated # by the 'unique' flag on Column @@ -898,25 +941,30 @@ class Table(DialectKWArgs, SchemaItem, TableClause): continue table.append_constraint( - c.copy(schema=schema, target_table=table)) + c.copy(schema=schema, target_table=table) + ) for index in self.indexes: # skip indexes that would be generated # by the 'index' flag on Column if index._column_flag: continue - Index(index.name, - unique=index.unique, - *[_copy_expression(expr, self, table) - for expr in index.expressions], - _table=table, - **index.kwargs) + Index( + index.name, + unique=index.unique, + *[ + _copy_expression(expr, self, table) + for expr in index.expressions + ], + _table=table, + **index.kwargs + ) return self._schema_item_copy(table) class Column(DialectKWArgs, SchemaItem, ColumnClause): """Represents a column in a database table.""" - __visit_name__ = 'column' + __visit_name__ = "column" def __init__(self, *args, **kwargs): r""" @@ -1192,14 +1240,15 @@ class Column(DialectKWArgs, SchemaItem, ColumnClause): """ - name = kwargs.pop('name', None) - type_ = kwargs.pop('type_', None) + name = kwargs.pop("name", None) + type_ = kwargs.pop("type_", None) args = list(args) if args: if isinstance(args[0], util.string_types): if name is not None: raise exc.ArgumentError( - "May not pass name positionally and as a keyword.") + "May not pass name positionally and as a keyword." + ) name = args.pop(0) if args: coltype = args[0] @@ -1207,40 +1256,42 @@ class Column(DialectKWArgs, SchemaItem, ColumnClause): if hasattr(coltype, "_sqla_type"): if type_ is not None: raise exc.ArgumentError( - "May not pass type_ positionally and as a keyword.") + "May not pass type_ positionally and as a keyword." + ) type_ = args.pop(0) if name is not None: - name = quoted_name(name, kwargs.pop('quote', None)) + name = quoted_name(name, kwargs.pop("quote", None)) elif "quote" in kwargs: - raise exc.ArgumentError("Explicit 'name' is required when " - "sending 'quote' argument") + raise exc.ArgumentError( + "Explicit 'name' is required when " "sending 'quote' argument" + ) super(Column, self).__init__(name, type_) - self.key = kwargs.pop('key', name) - self.primary_key = kwargs.pop('primary_key', False) - self.nullable = kwargs.pop('nullable', not self.primary_key) - self.default = kwargs.pop('default', None) - self.server_default = kwargs.pop('server_default', None) - self.server_onupdate = kwargs.pop('server_onupdate', None) + self.key = kwargs.pop("key", name) + self.primary_key = kwargs.pop("primary_key", False) + self.nullable = kwargs.pop("nullable", not self.primary_key) + self.default = kwargs.pop("default", None) + self.server_default = kwargs.pop("server_default", None) + self.server_onupdate = kwargs.pop("server_onupdate", None) # these default to None because .index and .unique is *not* # an informational flag about Column - there can still be an # Index or UniqueConstraint referring to this Column. - self.index = kwargs.pop('index', None) - self.unique = kwargs.pop('unique', None) + self.index = kwargs.pop("index", None) + self.unique = kwargs.pop("unique", None) - self.system = kwargs.pop('system', False) - self.doc = kwargs.pop('doc', None) - self.onupdate = kwargs.pop('onupdate', None) - self.autoincrement = kwargs.pop('autoincrement', "auto") + self.system = kwargs.pop("system", False) + self.doc = kwargs.pop("doc", None) + self.onupdate = kwargs.pop("onupdate", None) + self.autoincrement = kwargs.pop("autoincrement", "auto") self.constraints = set() self.foreign_keys = set() - self.comment = kwargs.pop('comment', None) + self.comment = kwargs.pop("comment", None) # check if this Column is proxying another column - if '_proxies' in kwargs: - self._proxies = kwargs.pop('_proxies') + if "_proxies" in kwargs: + self._proxies = kwargs.pop("_proxies") # otherwise, add DDL-related events elif isinstance(self.type, SchemaEventTarget): self.type._set_parent_with_dispatch(self) @@ -1249,14 +1300,13 @@ class Column(DialectKWArgs, SchemaItem, ColumnClause): if isinstance(self.default, (ColumnDefault, Sequence)): args.append(self.default) else: - if getattr(self.type, '_warn_on_bytestring', False): + if getattr(self.type, "_warn_on_bytestring", False): if isinstance(self.default, util.binary_type): util.warn( "Unicode column '%s' has non-unicode " - "default value %r specified." % ( - self.key, - self.default - )) + "default value %r specified." + % (self.key, self.default) + ) args.append(ColumnDefault(self.default)) if self.server_default is not None: @@ -1275,30 +1325,31 @@ class Column(DialectKWArgs, SchemaItem, ColumnClause): if isinstance(self.server_onupdate, FetchedValue): args.append(self.server_onupdate._as_for_update(True)) else: - args.append(DefaultClause(self.server_onupdate, - for_update=True)) + args.append( + DefaultClause(self.server_onupdate, for_update=True) + ) self._init_items(*args) util.set_creation_order(self) - if 'info' in kwargs: - self.info = kwargs.pop('info') + if "info" in kwargs: + self.info = kwargs.pop("info") self._extra_kwargs(**kwargs) def _extra_kwargs(self, **kwargs): self._validate_dialect_kwargs(kwargs) -# @property -# def quote(self): -# return getattr(self.name, "quote", None) + # @property + # def quote(self): + # return getattr(self.name, "quote", None) def __str__(self): if self.name is None: return "(no name)" elif self.table is not None: if self.table.named_with_column: - return (self.table.description + "." + self.description) + return self.table.description + "." + self.description else: return self.description else: @@ -1320,40 +1371,47 @@ class Column(DialectKWArgs, SchemaItem, ColumnClause): def __repr__(self): kwarg = [] if self.key != self.name: - kwarg.append('key') + kwarg.append("key") if self.primary_key: - kwarg.append('primary_key') + kwarg.append("primary_key") if not self.nullable: - kwarg.append('nullable') + kwarg.append("nullable") if self.onupdate: - kwarg.append('onupdate') + kwarg.append("onupdate") if self.default: - kwarg.append('default') + kwarg.append("default") if self.server_default: - kwarg.append('server_default') - return "Column(%s)" % ', '.join( - [repr(self.name)] + [repr(self.type)] + - [repr(x) for x in self.foreign_keys if x is not None] + - [repr(x) for x in self.constraints] + - [(self.table is not None and "table=<%s>" % - self.table.description or "table=None")] + - ["%s=%s" % (k, repr(getattr(self, k))) for k in kwarg]) + kwarg.append("server_default") + return "Column(%s)" % ", ".join( + [repr(self.name)] + + [repr(self.type)] + + [repr(x) for x in self.foreign_keys if x is not None] + + [repr(x) for x in self.constraints] + + [ + ( + self.table is not None + and "table=<%s>" % self.table.description + or "table=None" + ) + ] + + ["%s=%s" % (k, repr(getattr(self, k))) for k in kwarg] + ) def _set_parent(self, table): if not self.name: raise exc.ArgumentError( "Column must be constructed with a non-blank name or " - "assign a non-blank .name before adding to a Table.") + "assign a non-blank .name before adding to a Table." + ) if self.key is None: self.key = self.name - existing = getattr(self, 'table', None) + existing = getattr(self, "table", None) if existing is not None and existing is not table: raise exc.ArgumentError( - "Column object '%s' already assigned to Table '%s'" % ( - self.key, - existing.description - )) + "Column object '%s' already assigned to Table '%s'" + % (self.key, existing.description) + ) if self.key in table._columns: col = table._columns.get(self.key) @@ -1373,8 +1431,9 @@ class Column(DialectKWArgs, SchemaItem, ColumnClause): elif self.key in table.primary_key: raise exc.ArgumentError( "Trying to redefine primary-key column '%s' as a " - "non-primary-key column on table '%s'" % ( - self.key, table.fullname)) + "non-primary-key column on table '%s'" + % (self.key, table.fullname) + ) self.table = table @@ -1383,7 +1442,8 @@ class Column(DialectKWArgs, SchemaItem, ColumnClause): raise exc.ArgumentError( "The 'index' keyword argument on Column is boolean only. " "To create indexes with a specific name, create an " - "explicit Index object external to the Table.") + "explicit Index object external to the Table." + ) Index(None, self, unique=bool(self.unique), _column_flag=True) elif self.unique: if isinstance(self.unique, util.string_types): @@ -1392,9 +1452,11 @@ class Column(DialectKWArgs, SchemaItem, ColumnClause): "only. To create unique constraints or indexes with a " "specific name, append an explicit UniqueConstraint to " "the Table's list of elements, or create an explicit " - "Index object external to the Table.") + "Index object external to the Table." + ) table.append_constraint( - UniqueConstraint(self.key, _column_flag=True)) + UniqueConstraint(self.key, _column_flag=True) + ) self._setup_on_memoized_fks(lambda fk: fk._set_remote_table(table)) @@ -1413,7 +1475,7 @@ class Column(DialectKWArgs, SchemaItem, ColumnClause): if self.table is not None: fn(self, self.table) else: - event.listen(self, 'after_parent_attach', fn) + event.listen(self, "after_parent_attach", fn) def copy(self, **kw): """Create a copy of this ``Column``, unitialized. @@ -1423,9 +1485,9 @@ class Column(DialectKWArgs, SchemaItem, ColumnClause): """ # Constraint objects plus non-constraint-bound ForeignKey objects - args = \ - [c.copy(**kw) for c in self.constraints if not c._type_bound] + \ - [c.copy(**kw) for c in self.foreign_keys if not c.constraint] + args = [ + c.copy(**kw) for c in self.constraints if not c._type_bound + ] + [c.copy(**kw) for c in self.foreign_keys if not c.constraint] type_ = self.type if isinstance(type_, SchemaEventTarget): @@ -1452,8 +1514,9 @@ class Column(DialectKWArgs, SchemaItem, ColumnClause): ) return self._schema_item_copy(c) - def _make_proxy(self, selectable, name=None, key=None, - name_is_truncatable=False, **kw): + def _make_proxy( + self, selectable, name=None, key=None, name_is_truncatable=False, **kw + ): """Create a *proxy* for this column. This is a copy of this ``Column`` referenced by a different parent @@ -1462,22 +1525,28 @@ class Column(DialectKWArgs, SchemaItem, ColumnClause): information is not transferred. """ - fk = [ForeignKey(f.column, _constraint=f.constraint) - for f in self.foreign_keys] + fk = [ + ForeignKey(f.column, _constraint=f.constraint) + for f in self.foreign_keys + ] if name is None and self.name is None: raise exc.InvalidRequestError( "Cannot initialize a sub-selectable" " with this Column object until its 'name' has " - "been assigned.") + "been assigned." + ) try: c = self._constructor( - _as_truncated(name or self.name) if - name_is_truncatable else (name or self.name), + _as_truncated(name or self.name) + if name_is_truncatable + else (name or self.name), self.type, key=key if key else name if name else self.key, primary_key=self.primary_key, nullable=self.nullable, - _proxies=[self], *fk) + _proxies=[self], + *fk + ) except TypeError: util.raise_from_cause( TypeError( @@ -1485,7 +1554,8 @@ class Column(DialectKWArgs, SchemaItem, ColumnClause): "Ensure the class includes a _constructor() " "attribute or method which accepts the " "standard Column constructor arguments, or " - "references the Column class itself." % self.__class__) + "references the Column class itself." % self.__class__ + ) ) c.table = selectable @@ -1499,9 +1569,11 @@ class Column(DialectKWArgs, SchemaItem, ColumnClause): def get_children(self, schema_visitor=False, **kwargs): if schema_visitor: - return [x for x in (self.default, self.onupdate) - if x is not None] + \ - list(self.foreign_keys) + list(self.constraints) + return ( + [x for x in (self.default, self.onupdate) if x is not None] + + list(self.foreign_keys) + + list(self.constraints) + ) else: return ColumnClause.get_children(self, **kwargs) @@ -1543,13 +1615,23 @@ class ForeignKey(DialectKWArgs, SchemaItem): """ - __visit_name__ = 'foreign_key' - - def __init__(self, column, _constraint=None, use_alter=False, name=None, - onupdate=None, ondelete=None, deferrable=None, - initially=None, link_to_name=False, match=None, - info=None, - **dialect_kw): + __visit_name__ = "foreign_key" + + def __init__( + self, + column, + _constraint=None, + use_alter=False, + name=None, + onupdate=None, + ondelete=None, + deferrable=None, + initially=None, + link_to_name=False, + match=None, + info=None, + **dialect_kw + ): r""" Construct a column-level FOREIGN KEY. @@ -1626,7 +1708,7 @@ class ForeignKey(DialectKWArgs, SchemaItem): if isinstance(self._colspec, util.string_types): self._table_column = None else: - if hasattr(self._colspec, '__clause_element__'): + if hasattr(self._colspec, "__clause_element__"): self._table_column = self._colspec.__clause_element__() else: self._table_column = self._colspec @@ -1634,9 +1716,11 @@ class ForeignKey(DialectKWArgs, SchemaItem): if not isinstance(self._table_column, ColumnClause): raise exc.ArgumentError( "String, Column, or Column-bound argument " - "expected, got %r" % self._table_column) + "expected, got %r" % self._table_column + ) elif not isinstance( - self._table_column.table, (util.NoneType, TableClause)): + self._table_column.table, (util.NoneType, TableClause) + ): raise exc.ArgumentError( "ForeignKey received Column not bound " "to a Table, got: %r" % self._table_column.table @@ -1715,7 +1799,9 @@ class ForeignKey(DialectKWArgs, SchemaItem): return "%s.%s" % (table_name, colname) elif self._table_column is not None: return "%s.%s" % ( - self._table_column.table.fullname, self._table_column.key) + self._table_column.table.fullname, + self._table_column.key, + ) else: return self._colspec @@ -1756,12 +1842,12 @@ class ForeignKey(DialectKWArgs, SchemaItem): def _column_tokens(self): """parse a string-based _colspec into its component parts.""" - m = self._get_colspec().split('.') + m = self._get_colspec().split(".") if m is None: raise exc.ArgumentError( - "Invalid foreign key column specification: %s" % - self._colspec) - if (len(m) == 1): + "Invalid foreign key column specification: %s" % self._colspec + ) + if len(m) == 1: tname = m.pop() colname = None else: @@ -1777,8 +1863,8 @@ class ForeignKey(DialectKWArgs, SchemaItem): # indirectly related -- Ticket #594. This assumes that '.' # will never appear *within* any component of the FK. - if (len(m) > 0): - schema = '.'.join(m) + if len(m) > 0: + schema = ".".join(m) else: schema = None return schema, tname, colname @@ -1787,12 +1873,14 @@ class ForeignKey(DialectKWArgs, SchemaItem): if self.parent is None: raise exc.InvalidRequestError( "this ForeignKey object does not yet have a " - "parent Column associated with it.") + "parent Column associated with it." + ) elif self.parent.table is None: raise exc.InvalidRequestError( "this ForeignKey's parent column is not yet associated " - "with a Table.") + "with a Table." + ) parenttable = self.parent.table @@ -1817,7 +1905,7 @@ class ForeignKey(DialectKWArgs, SchemaItem): return parenttable, tablekey, colname def _link_to_col_by_colstring(self, parenttable, table, colname): - if not hasattr(self.constraint, '_referred_table'): + if not hasattr(self.constraint, "_referred_table"): self.constraint._referred_table = table else: assert self.constraint._referred_table is table @@ -1843,9 +1931,11 @@ class ForeignKey(DialectKWArgs, SchemaItem): raise exc.NoReferencedColumnError( "Could not initialize target column " "for ForeignKey '%s' on table '%s': " - "table '%s' has no column named '%s'" % - (self._colspec, parenttable.name, table.name, key), - table.name, key) + "table '%s' has no column named '%s'" + % (self._colspec, parenttable.name, table.name, key), + table.name, + key, + ) self._set_target_column(_column) @@ -1861,6 +1951,7 @@ class ForeignKey(DialectKWArgs, SchemaItem): def set_type(fk): if fk.parent.type._isnull: fk.parent.type = column.type + self.parent._setup_on_memoized_fks(set_type) self.column = column @@ -1888,21 +1979,25 @@ class ForeignKey(DialectKWArgs, SchemaItem): raise exc.NoReferencedTableError( "Foreign key associated with column '%s' could not find " "table '%s' with which to generate a " - "foreign key to target column '%s'" % - (self.parent, tablekey, colname), - tablekey) + "foreign key to target column '%s'" + % (self.parent, tablekey, colname), + tablekey, + ) elif parenttable.key not in parenttable.metadata: raise exc.InvalidRequestError( "Table %s is no longer associated with its " - "parent MetaData" % parenttable) + "parent MetaData" % parenttable + ) else: raise exc.NoReferencedColumnError( "Could not initialize target column for " "ForeignKey '%s' on table '%s': " - "table '%s' has no column named '%s'" % ( - self._colspec, parenttable.name, tablekey, colname), - tablekey, colname) - elif hasattr(self._colspec, '__clause_element__'): + "table '%s' has no column named '%s'" + % (self._colspec, parenttable.name, tablekey, colname), + tablekey, + colname, + ) + elif hasattr(self._colspec, "__clause_element__"): _column = self._colspec.__clause_element__() return _column else: @@ -1912,7 +2007,8 @@ class ForeignKey(DialectKWArgs, SchemaItem): def _set_parent(self, column): if self.parent is not None and self.parent is not column: raise exc.InvalidRequestError( - "This ForeignKey already has a parent !") + "This ForeignKey already has a parent !" + ) self.parent = column self.parent.foreign_keys.add(self) self.parent._on_table_attach(self._set_table) @@ -1935,9 +2031,14 @@ class ForeignKey(DialectKWArgs, SchemaItem): # on the hosting Table when attached to the Table. if self.constraint is None and isinstance(table, Table): self.constraint = ForeignKeyConstraint( - [], [], use_alter=self.use_alter, name=self.name, - onupdate=self.onupdate, ondelete=self.ondelete, - deferrable=self.deferrable, initially=self.initially, + [], + [], + use_alter=self.use_alter, + name=self.name, + onupdate=self.onupdate, + ondelete=self.ondelete, + deferrable=self.deferrable, + initially=self.initially, match=self.match, **self._unvalidated_dialect_kw ) @@ -1953,13 +2054,12 @@ class ForeignKey(DialectKWArgs, SchemaItem): if table_key in parenttable.metadata.tables: table = parenttable.metadata.tables[table_key] try: - self._link_to_col_by_colstring( - parenttable, table, colname) + self._link_to_col_by_colstring(parenttable, table, colname) except exc.NoReferencedColumnError: # this is OK, we'll try later pass parenttable.metadata._fk_memos[fk_key].append(self) - elif hasattr(self._colspec, '__clause_element__'): + elif hasattr(self._colspec, "__clause_element__"): _column = self._colspec.__clause_element__() self._set_target_column(_column) else: @@ -1971,7 +2071,8 @@ class _NotAColumnExpr(object): def _not_a_column_expr(self): raise exc.InvalidRequestError( "This %s cannot be used directly " - "as a column expression." % self.__class__.__name__) + "as a column expression." % self.__class__.__name__ + ) __clause_element__ = self_group = lambda self: self._not_a_column_expr() _from_objects = property(lambda self: self._not_a_column_expr()) @@ -1980,7 +2081,7 @@ class _NotAColumnExpr(object): class DefaultGenerator(_NotAColumnExpr, SchemaItem): """Base class for column *default* values.""" - __visit_name__ = 'default_generator' + __visit_name__ = "default_generator" is_sequence = False is_server_default = False @@ -2007,7 +2108,7 @@ class DefaultGenerator(_NotAColumnExpr, SchemaItem): @property def bind(self): """Return the connectable associated with this default.""" - if getattr(self, 'column', None) is not None: + if getattr(self, "column", None) is not None: return self.column.table.bind else: return None @@ -2064,7 +2165,8 @@ class ColumnDefault(DefaultGenerator): super(ColumnDefault, self).__init__(**kwargs) if isinstance(arg, FetchedValue): raise exc.ArgumentError( - "ColumnDefault may not be a server-side default type.") + "ColumnDefault may not be a server-side default type." + ) if util.callable(arg): arg = self._maybe_wrap_callable(arg) self.arg = arg @@ -2079,9 +2181,11 @@ class ColumnDefault(DefaultGenerator): @util.memoized_property def is_scalar(self): - return not self.is_callable and \ - not self.is_clause_element and \ - not self.is_sequence + return ( + not self.is_callable + and not self.is_clause_element + and not self.is_sequence + ) @util.memoized_property @util.dependencies("sqlalchemy.sql.sqltypes") @@ -2114,17 +2218,19 @@ class ColumnDefault(DefaultGenerator): else: raise exc.ArgumentError( "ColumnDefault Python function takes zero or one " - "positional arguments") + "positional arguments" + ) def _visit_name(self): if self.for_update: return "column_onupdate" else: return "column_default" + __visit_name__ = property(_visit_name) def __repr__(self): - return "ColumnDefault(%r)" % (self.arg, ) + return "ColumnDefault(%r)" % (self.arg,) class Sequence(DefaultGenerator): @@ -2157,15 +2263,29 @@ class Sequence(DefaultGenerator): """ - __visit_name__ = 'sequence' + __visit_name__ = "sequence" is_sequence = True - def __init__(self, name, start=None, increment=None, minvalue=None, - maxvalue=None, nominvalue=None, nomaxvalue=None, cycle=None, - schema=None, cache=None, order=None, optional=False, - quote=None, metadata=None, quote_schema=None, - for_update=False): + def __init__( + self, + name, + start=None, + increment=None, + minvalue=None, + maxvalue=None, + nominvalue=None, + nomaxvalue=None, + cycle=None, + schema=None, + cache=None, + order=None, + optional=False, + quote=None, + metadata=None, + quote_schema=None, + for_update=False, + ): """Construct a :class:`.Sequence` object. :param name: The name of the sequence. @@ -2353,27 +2473,22 @@ class Sequence(DefaultGenerator): if bind is None: bind = _bind_or_error(self) - bind._run_visitor(ddl.SchemaGenerator, - self, - checkfirst=checkfirst) + bind._run_visitor(ddl.SchemaGenerator, self, checkfirst=checkfirst) def drop(self, bind=None, checkfirst=True): """Drops this sequence from the database.""" if bind is None: bind = _bind_or_error(self) - bind._run_visitor(ddl.SchemaDropper, - self, - checkfirst=checkfirst) + bind._run_visitor(ddl.SchemaDropper, self, checkfirst=checkfirst) def _not_a_column_expr(self): raise exc.InvalidRequestError( "This %s cannot be used directly " "as a column expression. Use func.next_value(sequence) " "to produce a 'next value' function that's usable " - "as a column element." - % self.__class__.__name__) - + "as a column element." % self.__class__.__name__ + ) @inspection._self_inspects @@ -2396,6 +2511,7 @@ class FetchedValue(_NotAColumnExpr, SchemaEventTarget): :ref:`triggered_columns` """ + is_server_default = True reflected = False has_argument = False @@ -2412,7 +2528,7 @@ class FetchedValue(_NotAColumnExpr, SchemaEventTarget): def _clone(self, for_update): n = self.__class__.__new__(self.__class__) n.__dict__.update(self.__dict__) - n.__dict__.pop('column', None) + n.__dict__.pop("column", None) n.for_update = for_update return n @@ -2452,16 +2568,15 @@ class DefaultClause(FetchedValue): has_argument = True def __init__(self, arg, for_update=False, _reflected=False): - util.assert_arg_type(arg, (util.string_types[0], - ClauseElement, - TextClause), 'arg') + util.assert_arg_type( + arg, (util.string_types[0], ClauseElement, TextClause), "arg" + ) super(DefaultClause, self).__init__(for_update) self.arg = arg self.reflected = _reflected def __repr__(self): - return "DefaultClause(%r, for_update=%r)" % \ - (self.arg, self.for_update) + return "DefaultClause(%r, for_update=%r)" % (self.arg, self.for_update) class PassiveDefault(DefaultClause): @@ -2471,10 +2586,13 @@ class PassiveDefault(DefaultClause): :class:`.PassiveDefault` is deprecated. Use :class:`.DefaultClause`. """ - @util.deprecated("0.6", - ":class:`.PassiveDefault` is deprecated. " - "Use :class:`.DefaultClause`.", - False) + + @util.deprecated( + "0.6", + ":class:`.PassiveDefault` is deprecated. " + "Use :class:`.DefaultClause`.", + False, + ) def __init__(self, *arg, **kw): DefaultClause.__init__(self, *arg, **kw) @@ -2482,11 +2600,18 @@ class PassiveDefault(DefaultClause): class Constraint(DialectKWArgs, SchemaItem): """A table-level SQL constraint.""" - __visit_name__ = 'constraint' - - def __init__(self, name=None, deferrable=None, initially=None, - _create_rule=None, info=None, _type_bound=False, - **dialect_kw): + __visit_name__ = "constraint" + + def __init__( + self, + name=None, + deferrable=None, + initially=None, + _create_rule=None, + info=None, + _type_bound=False, + **dialect_kw + ): r"""Create a SQL constraint. :param name: @@ -2548,7 +2673,8 @@ class Constraint(DialectKWArgs, SchemaItem): pass raise exc.InvalidRequestError( "This constraint is not bound to a table. Did you " - "mean to call table.append_constraint(constraint) ?") + "mean to call table.append_constraint(constraint) ?" + ) def _set_parent(self, parent): self.parent = parent @@ -2559,7 +2685,7 @@ class Constraint(DialectKWArgs, SchemaItem): def _to_schema_column(element): - if hasattr(element, '__clause_element__'): + if hasattr(element, "__clause_element__"): element = element.__clause_element__() if not isinstance(element, Column): raise exc.ArgumentError("schema.Column object expected") @@ -2567,9 +2693,9 @@ def _to_schema_column(element): def _to_schema_column_or_string(element): - if hasattr(element, '__clause_element__'): + if hasattr(element, "__clause_element__"): element = element.__clause_element__() - if not isinstance(element, util.string_types + (ColumnElement, )): + if not isinstance(element, util.string_types + (ColumnElement,)): msg = "Element %r is not a string name or column element" raise exc.ArgumentError(msg % element) return element @@ -2588,11 +2714,12 @@ class ColumnCollectionMixin(object): _allow_multiple_tables = False def __init__(self, *columns, **kw): - _autoattach = kw.pop('_autoattach', True) - self._column_flag = kw.pop('_column_flag', False) + _autoattach = kw.pop("_autoattach", True) + self._column_flag = kw.pop("_column_flag", False) self.columns = ColumnCollection() - self._pending_colargs = [_to_schema_column_or_string(c) - for c in columns] + self._pending_colargs = [ + _to_schema_column_or_string(c) for c in columns + ] if _autoattach and self._pending_colargs: self._check_attach() @@ -2601,7 +2728,7 @@ class ColumnCollectionMixin(object): for expr in expressions: strname = None column = None - if hasattr(expr, '__clause_element__'): + if hasattr(expr, "__clause_element__"): expr = expr.__clause_element__() if not isinstance(expr, (ColumnElement, TextClause)): @@ -2609,21 +2736,16 @@ class ColumnCollectionMixin(object): strname = expr else: cols = [] - visitors.traverse(expr, {}, {'column': cols.append}) + visitors.traverse(expr, {}, {"column": cols.append}) if cols: column = cols[0] add_element = column if column is not None else strname yield expr, column, strname, add_element def _check_attach(self, evt=False): - col_objs = [ - c for c in self._pending_colargs - if isinstance(c, Column) - ] + col_objs = [c for c in self._pending_colargs if isinstance(c, Column)] - cols_w_table = [ - c for c in col_objs if isinstance(c.table, Table) - ] + cols_w_table = [c for c in col_objs if isinstance(c.table, Table)] cols_wo_table = set(col_objs).difference(cols_w_table) @@ -2636,6 +2758,7 @@ class ColumnCollectionMixin(object): # columns are specified as strings. has_string_cols = set(self._pending_colargs).difference(col_objs) if not has_string_cols: + def _col_attached(column, table): # this isinstance() corresponds with the # isinstance() above; only want to count Table-bound @@ -2644,6 +2767,7 @@ class ColumnCollectionMixin(object): cols_wo_table.discard(column) if not cols_wo_table: self._check_attach(evt=True) + self._cols_wo_table = cols_wo_table for col in cols_wo_table: col._on_table_attach(_col_attached) @@ -2659,9 +2783,11 @@ class ColumnCollectionMixin(object): others = [c for c in columns[1:] if c.table is not table] if others: raise exc.ArgumentError( - "Column(s) %s are not part of table '%s'." % - (", ".join("'%s'" % c for c in others), - table.description) + "Column(s) %s are not part of table '%s'." + % ( + ", ".join("'%s'" % c for c in others), + table.description, + ) ) def _set_parent(self, table): @@ -2694,11 +2820,12 @@ class ColumnCollectionConstraint(ColumnCollectionMixin, Constraint): arguments are propagated to the :class:`.Constraint` superclass. """ - _autoattach = kw.pop('_autoattach', True) - _column_flag = kw.pop('_column_flag', False) + _autoattach = kw.pop("_autoattach", True) + _column_flag = kw.pop("_column_flag", False) Constraint.__init__(self, **kw) ColumnCollectionMixin.__init__( - self, *columns, _autoattach=_autoattach, _column_flag=_column_flag) + self, *columns, _autoattach=_autoattach, _column_flag=_column_flag + ) columns = None """A :class:`.ColumnCollection` representing the set of columns @@ -2714,8 +2841,12 @@ class ColumnCollectionConstraint(ColumnCollectionMixin, Constraint): return x in self.columns def copy(self, **kw): - c = self.__class__(name=self.name, deferrable=self.deferrable, - initially=self.initially, *self.columns.keys()) + c = self.__class__( + name=self.name, + deferrable=self.deferrable, + initially=self.initially, + *self.columns.keys() + ) return self._schema_item_copy(c) def contains_column(self, col): @@ -2747,9 +2878,19 @@ class CheckConstraint(ColumnCollectionConstraint): _allow_multiple_tables = True - def __init__(self, sqltext, name=None, deferrable=None, - initially=None, table=None, info=None, _create_rule=None, - _autoattach=True, _type_bound=False, **kw): + def __init__( + self, + sqltext, + name=None, + deferrable=None, + initially=None, + table=None, + info=None, + _create_rule=None, + _autoattach=True, + _type_bound=False, + **kw + ): r"""Construct a CHECK constraint. :param sqltext: @@ -2781,14 +2922,19 @@ class CheckConstraint(ColumnCollectionConstraint): self.sqltext = _literal_as_text(sqltext, warn=False) columns = [] - visitors.traverse(self.sqltext, {}, {'column': columns.append}) - - super(CheckConstraint, self).\ - __init__( - name=name, deferrable=deferrable, - initially=initially, _create_rule=_create_rule, info=info, - _type_bound=_type_bound, _autoattach=_autoattach, - *columns, **kw) + visitors.traverse(self.sqltext, {}, {"column": columns.append}) + + super(CheckConstraint, self).__init__( + name=name, + deferrable=deferrable, + initially=initially, + _create_rule=_create_rule, + info=info, + _type_bound=_type_bound, + _autoattach=_autoattach, + *columns, + **kw + ) if table is not None: self._set_parent_with_dispatch(table) @@ -2797,22 +2943,24 @@ class CheckConstraint(ColumnCollectionConstraint): return "check_constraint" else: return "column_check_constraint" + __visit_name__ = property(__visit_name__) def copy(self, target_table=None, **kw): if target_table is not None: - sqltext = _copy_expression( - self.sqltext, self.table, target_table) + sqltext = _copy_expression(self.sqltext, self.table, target_table) else: sqltext = self.sqltext - c = CheckConstraint(sqltext, - name=self.name, - initially=self.initially, - deferrable=self.deferrable, - _create_rule=self._create_rule, - table=target_table, - _autoattach=False, - _type_bound=self._type_bound) + c = CheckConstraint( + sqltext, + name=self.name, + initially=self.initially, + deferrable=self.deferrable, + _create_rule=self._create_rule, + table=target_table, + _autoattach=False, + _type_bound=self._type_bound, + ) return self._schema_item_copy(c) @@ -2828,12 +2976,25 @@ class ForeignKeyConstraint(ColumnCollectionConstraint): Examples of foreign key configuration are in :ref:`metadata_foreignkeys`. """ - __visit_name__ = 'foreign_key_constraint' - def __init__(self, columns, refcolumns, name=None, onupdate=None, - ondelete=None, deferrable=None, initially=None, - use_alter=False, link_to_name=False, match=None, - table=None, info=None, **dialect_kw): + __visit_name__ = "foreign_key_constraint" + + def __init__( + self, + columns, + refcolumns, + name=None, + onupdate=None, + ondelete=None, + deferrable=None, + initially=None, + use_alter=False, + link_to_name=False, + match=None, + table=None, + info=None, + **dialect_kw + ): r"""Construct a composite-capable FOREIGN KEY. :param columns: A sequence of local column names. The named columns @@ -2905,8 +3066,13 @@ class ForeignKeyConstraint(ColumnCollectionConstraint): """ Constraint.__init__( - self, name=name, deferrable=deferrable, initially=initially, - info=info, **dialect_kw) + self, + name=name, + deferrable=deferrable, + initially=initially, + info=info, + **dialect_kw + ) self.onupdate = onupdate self.ondelete = ondelete self.link_to_name = link_to_name @@ -2927,7 +3093,8 @@ class ForeignKeyConstraint(ColumnCollectionConstraint): raise exc.ArgumentError( "ForeignKeyConstraint number " "of constrained columns must match the number of " - "referenced columns.") + "referenced columns." + ) # standalone ForeignKeyConstraint - create # associated ForeignKey objects which will be applied to hosted @@ -2946,7 +3113,8 @@ class ForeignKeyConstraint(ColumnCollectionConstraint): deferrable=self.deferrable, initially=self.initially, **self.dialect_kwargs - ) for refcol in refcolumns + ) + for refcol in refcolumns ] ColumnCollectionMixin.__init__(self, *columns) @@ -2978,9 +3146,7 @@ class ForeignKeyConstraint(ColumnCollectionConstraint): @property def _elements(self): # legacy - provide a dictionary view of (column_key, fk) - return util.OrderedDict( - zip(self.column_keys, self.elements) - ) + return util.OrderedDict(zip(self.column_keys, self.elements)) @property def _referred_schema(self): @@ -3004,18 +3170,14 @@ class ForeignKeyConstraint(ColumnCollectionConstraint): return self.elements[0].column.table def _validate_dest_table(self, table): - table_keys = set([elem._table_key() - for elem in self.elements]) + table_keys = set([elem._table_key() for elem in self.elements]) if None not in table_keys and len(table_keys) > 1: elem0, elem1 = sorted(table_keys)[0:2] raise exc.ArgumentError( - 'ForeignKeyConstraint on %s(%s) refers to ' - 'multiple remote tables: %s and %s' % ( - table.fullname, - self._col_description, - elem0, - elem1 - )) + "ForeignKeyConstraint on %s(%s) refers to " + "multiple remote tables: %s and %s" + % (table.fullname, self._col_description, elem0, elem1) + ) @property def column_keys(self): @@ -3034,8 +3196,8 @@ class ForeignKeyConstraint(ColumnCollectionConstraint): return self.columns.keys() else: return [ - col.key if isinstance(col, ColumnElement) - else str(col) for col in self._pending_colargs + col.key if isinstance(col, ColumnElement) else str(col) + for col in self._pending_colargs ] @property @@ -3051,11 +3213,11 @@ class ForeignKeyConstraint(ColumnCollectionConstraint): raise exc.ArgumentError( "Can't create ForeignKeyConstraint " "on table '%s': no column " - "named '%s' is present." % (table.description, ke.args[0])) + "named '%s' is present." % (table.description, ke.args[0]) + ) for col, fk in zip(self.columns, self.elements): - if not hasattr(fk, 'parent') or \ - fk.parent is not col: + if not hasattr(fk, "parent") or fk.parent is not col: fk._set_parent_with_dispatch(col) self._validate_dest_table(table) @@ -3063,13 +3225,16 @@ class ForeignKeyConstraint(ColumnCollectionConstraint): def copy(self, schema=None, target_table=None, **kw): fkc = ForeignKeyConstraint( [x.parent.key for x in self.elements], - [x._get_colspec( - schema=schema, - table_name=target_table.name - if target_table is not None - and x._table_key() == x.parent.table.key - else None) - for x in self.elements], + [ + x._get_colspec( + schema=schema, + table_name=target_table.name + if target_table is not None + and x._table_key() == x.parent.table.key + else None, + ) + for x in self.elements + ], name=self.name, onupdate=self.onupdate, ondelete=self.ondelete, @@ -3077,11 +3242,9 @@ class ForeignKeyConstraint(ColumnCollectionConstraint): deferrable=self.deferrable, initially=self.initially, link_to_name=self.link_to_name, - match=self.match + match=self.match, ) - for self_fk, other_fk in zip( - self.elements, - fkc.elements): + for self_fk, other_fk in zip(self.elements, fkc.elements): self_fk._schema_item_copy(other_fk) return self._schema_item_copy(fkc) @@ -3160,10 +3323,10 @@ class PrimaryKeyConstraint(ColumnCollectionConstraint): """ - __visit_name__ = 'primary_key_constraint' + __visit_name__ = "primary_key_constraint" def __init__(self, *columns, **kw): - self._implicit_generated = kw.pop('_implicit_generated', False) + self._implicit_generated = kw.pop("_implicit_generated", False) super(PrimaryKeyConstraint, self).__init__(*columns, **kw) def _set_parent(self, table): @@ -3175,18 +3338,21 @@ class PrimaryKeyConstraint(ColumnCollectionConstraint): table.constraints.add(self) table_pks = [c for c in table.c if c.primary_key] - if self.columns and table_pks and \ - set(table_pks) != set(self.columns.values()): + if ( + self.columns + and table_pks + and set(table_pks) != set(self.columns.values()) + ): util.warn( "Table '%s' specifies columns %s as primary_key=True, " "not matching locally specified columns %s; setting the " "current primary key columns to %s. This warning " - "may become an exception in a future release" % - ( + "may become an exception in a future release" + % ( table.name, ", ".join("'%s'" % c.name for c in table_pks), ", ".join("'%s'" % c.name for c in self.columns), - ", ".join("'%s'" % c.name for c in self.columns) + ", ".join("'%s'" % c.name for c in self.columns), ) ) table_pks[:] = [] @@ -3241,28 +3407,28 @@ class PrimaryKeyConstraint(ColumnCollectionConstraint): @util.memoized_property def _autoincrement_column(self): - def _validate_autoinc(col, autoinc_true): if col.type._type_affinity is None or not issubclass( - col.type._type_affinity, - type_api.INTEGERTYPE._type_affinity): + col.type._type_affinity, type_api.INTEGERTYPE._type_affinity + ): if autoinc_true: raise exc.ArgumentError( "Column type %s on column '%s' is not " - "compatible with autoincrement=True" % ( - col.type, - col - )) + "compatible with autoincrement=True" % (col.type, col) + ) else: return False - elif not isinstance(col.default, (type(None), Sequence)) and \ - not autoinc_true: - return False + elif ( + not isinstance(col.default, (type(None), Sequence)) + and not autoinc_true + ): + return False elif col.server_default is not None and not autoinc_true: return False - elif ( - col.foreign_keys and col.autoincrement - not in (True, 'ignore_fk')): + elif col.foreign_keys and col.autoincrement not in ( + True, + "ignore_fk", + ): return False return True @@ -3272,10 +3438,10 @@ class PrimaryKeyConstraint(ColumnCollectionConstraint): if col.autoincrement is True: _validate_autoinc(col, True) return col - elif ( - col.autoincrement in ('auto', 'ignore_fk') and - _validate_autoinc(col, False) - ): + elif col.autoincrement in ( + "auto", + "ignore_fk", + ) and _validate_autoinc(col, False): return col else: @@ -3286,8 +3452,8 @@ class PrimaryKeyConstraint(ColumnCollectionConstraint): if autoinc is not None: raise exc.ArgumentError( "Only one Column may be marked " - "autoincrement=True, found both %s and %s." % - (col.name, autoinc.name) + "autoincrement=True, found both %s and %s." + % (col.name, autoinc.name) ) else: autoinc = col @@ -3304,7 +3470,7 @@ class UniqueConstraint(ColumnCollectionConstraint): UniqueConstraint. """ - __visit_name__ = 'unique_constraint' + __visit_name__ = "unique_constraint" class Index(DialectKWArgs, ColumnCollectionMixin, SchemaItem): @@ -3382,7 +3548,7 @@ class Index(DialectKWArgs, ColumnCollectionMixin, SchemaItem): """ - __visit_name__ = 'index' + __visit_name__ = "index" def __init__(self, name, *expressions, **kw): r"""Construct an index object. @@ -3420,30 +3586,35 @@ class Index(DialectKWArgs, ColumnCollectionMixin, SchemaItem): columns = [] processed_expressions = [] - for expr, column, strname, add_element in self.\ - _extract_col_expression_collection(expressions): + for ( + expr, + column, + strname, + add_element, + ) in self._extract_col_expression_collection(expressions): if add_element is not None: columns.append(add_element) processed_expressions.append(expr) self.expressions = processed_expressions self.name = quoted_name(name, kw.pop("quote", None)) - self.unique = kw.pop('unique', False) - _column_flag = kw.pop('_column_flag', False) - if 'info' in kw: - self.info = kw.pop('info') + self.unique = kw.pop("unique", False) + _column_flag = kw.pop("_column_flag", False) + if "info" in kw: + self.info = kw.pop("info") # TODO: consider "table" argument being public, but for # the purpose of the fix here, it starts as private. - if '_table' in kw: - table = kw.pop('_table') + if "_table" in kw: + table = kw.pop("_table") self._validate_dialect_kwargs(kw) # will call _set_parent() if table-bound column # objects are present ColumnCollectionMixin.__init__( - self, *columns, _column_flag=_column_flag) + self, *columns, _column_flag=_column_flag + ) if table is not None: self._set_parent(table) @@ -3454,20 +3625,17 @@ class Index(DialectKWArgs, ColumnCollectionMixin, SchemaItem): if self.table is not None and table is not self.table: raise exc.ArgumentError( "Index '%s' is against table '%s', and " - "cannot be associated with table '%s'." % ( - self.name, - self.table.description, - table.description - ) + "cannot be associated with table '%s'." + % (self.name, self.table.description, table.description) ) self.table = table table.indexes.add(self) self.expressions = [ - expr if isinstance(expr, ClauseElement) - else colexpr - for expr, colexpr in util.zip_longest(self.expressions, - self.columns) + expr if isinstance(expr, ClauseElement) else colexpr + for expr, colexpr in util.zip_longest( + self.expressions, self.columns + ) ] @property @@ -3506,17 +3674,16 @@ class Index(DialectKWArgs, ColumnCollectionMixin, SchemaItem): bind._run_visitor(ddl.SchemaDropper, self) def __repr__(self): - return 'Index(%s)' % ( + return "Index(%s)" % ( ", ".join( - [repr(self.name)] + - [repr(e) for e in self.expressions] + - (self.unique and ["unique=True"] or []) - )) + [repr(self.name)] + + [repr(e) for e in self.expressions] + + (self.unique and ["unique=True"] or []) + ) + ) -DEFAULT_NAMING_CONVENTION = util.immutabledict({ - "ix": 'ix_%(column_0_label)s' -}) +DEFAULT_NAMING_CONVENTION = util.immutabledict({"ix": "ix_%(column_0_label)s"}) class MetaData(SchemaItem): @@ -3542,13 +3709,17 @@ class MetaData(SchemaItem): """ - __visit_name__ = 'metadata' - - def __init__(self, bind=None, reflect=False, schema=None, - quote_schema=None, - naming_convention=DEFAULT_NAMING_CONVENTION, - info=None - ): + __visit_name__ = "metadata" + + def __init__( + self, + bind=None, + reflect=False, + schema=None, + quote_schema=None, + naming_convention=DEFAULT_NAMING_CONVENTION, + info=None, + ): """Create a new MetaData object. :param bind: @@ -3712,12 +3883,15 @@ class MetaData(SchemaItem): self.bind = bind if reflect: - util.warn_deprecated("reflect=True is deprecate; please " - "use the reflect() method.") + util.warn_deprecated( + "reflect=True is deprecate; please " + "use the reflect() method." + ) if not bind: raise exc.ArgumentError( "A bind must be supplied in conjunction " - "with reflect=True") + "with reflect=True" + ) self.reflect() tables = None @@ -3735,7 +3909,7 @@ class MetaData(SchemaItem): """ def __repr__(self): - return 'MetaData(bind=%r)' % self.bind + return "MetaData(bind=%r)" % self.bind def __contains__(self, table_or_key): if not isinstance(table_or_key, util.string_types): @@ -3755,27 +3929,32 @@ class MetaData(SchemaItem): for fk in removed.foreign_keys: fk._remove_from_metadata(self) if self._schemas: - self._schemas = set([t.schema - for t in self.tables.values() - if t.schema is not None]) + self._schemas = set( + [ + t.schema + for t in self.tables.values() + if t.schema is not None + ] + ) def __getstate__(self): - return {'tables': self.tables, - 'schema': self.schema, - 'schemas': self._schemas, - 'sequences': self._sequences, - 'fk_memos': self._fk_memos, - 'naming_convention': self.naming_convention - } + return { + "tables": self.tables, + "schema": self.schema, + "schemas": self._schemas, + "sequences": self._sequences, + "fk_memos": self._fk_memos, + "naming_convention": self.naming_convention, + } def __setstate__(self, state): - self.tables = state['tables'] - self.schema = state['schema'] - self.naming_convention = state['naming_convention'] + self.tables = state["tables"] + self.schema = state["schema"] + self.naming_convention = state["naming_convention"] self._bind = None - self._sequences = state['sequences'] - self._schemas = state['schemas'] - self._fk_memos = state['fk_memos'] + self._sequences = state["sequences"] + self._schemas = state["schemas"] + self._fk_memos = state["fk_memos"] def is_bound(self): """True if this MetaData is bound to an Engine or Connection.""" @@ -3805,10 +3984,11 @@ class MetaData(SchemaItem): def _bind_to(self, url, bind): """Bind this MetaData to an Engine, Connection, string or URL.""" - if isinstance(bind, util.string_types + (url.URL, )): + if isinstance(bind, util.string_types + (url.URL,)): self._bind = sqlalchemy.create_engine(bind) else: self._bind = bind + bind = property(bind, _bind_to) def clear(self): @@ -3858,12 +4038,20 @@ class MetaData(SchemaItem): """ - return ddl.sort_tables(sorted(self.tables.values(), key=lambda t: t.key)) + return ddl.sort_tables( + sorted(self.tables.values(), key=lambda t: t.key) + ) - def reflect(self, bind=None, schema=None, views=False, only=None, - extend_existing=False, - autoload_replace=True, - **dialect_kwargs): + def reflect( + self, + bind=None, + schema=None, + views=False, + only=None, + extend_existing=False, + autoload_replace=True, + **dialect_kwargs + ): r"""Load all available table definitions from the database. Automatically creates ``Table`` entries in this ``MetaData`` for any @@ -3926,11 +4114,11 @@ class MetaData(SchemaItem): with bind.connect() as conn: reflect_opts = { - 'autoload': True, - 'autoload_with': conn, - 'extend_existing': extend_existing, - 'autoload_replace': autoload_replace, - '_extend_on': set() + "autoload": True, + "autoload_with": conn, + "extend_existing": extend_existing, + "autoload_replace": autoload_replace, + "_extend_on": set(), } reflect_opts.update(dialect_kwargs) @@ -3939,42 +4127,49 @@ class MetaData(SchemaItem): schema = self.schema if schema is not None: - reflect_opts['schema'] = schema + reflect_opts["schema"] = schema available = util.OrderedSet( - bind.engine.table_names(schema, connection=conn)) + bind.engine.table_names(schema, connection=conn) + ) if views: - available.update( - bind.dialect.get_view_names(conn, schema) - ) + available.update(bind.dialect.get_view_names(conn, schema)) if schema is not None: - available_w_schema = util.OrderedSet(["%s.%s" % (schema, name) - for name in available]) + available_w_schema = util.OrderedSet( + ["%s.%s" % (schema, name) for name in available] + ) else: available_w_schema = available current = set(self.tables) if only is None: - load = [name for name, schname in - zip(available, available_w_schema) - if extend_existing or schname not in current] + load = [ + name + for name, schname in zip(available, available_w_schema) + if extend_existing or schname not in current + ] elif util.callable(only): - load = [name for name, schname in - zip(available, available_w_schema) - if (extend_existing or schname not in current) - and only(name, self)] + load = [ + name + for name, schname in zip(available, available_w_schema) + if (extend_existing or schname not in current) + and only(name, self) + ] else: missing = [name for name in only if name not in available] if missing: - s = schema and (" schema '%s'" % schema) or '' + s = schema and (" schema '%s'" % schema) or "" raise exc.InvalidRequestError( - 'Could not reflect: requested table(s) not available ' - 'in %r%s: (%s)' % - (bind.engine, s, ', '.join(missing))) - load = [name for name in only if extend_existing or - name not in current] + "Could not reflect: requested table(s) not available " + "in %r%s: (%s)" % (bind.engine, s, ", ".join(missing)) + ) + load = [ + name + for name in only + if extend_existing or name not in current + ] for name in load: try: @@ -3989,11 +4184,12 @@ class MetaData(SchemaItem): See :class:`.DDLEvents`. """ + def adapt_listener(target, connection, **kw): - tables = kw['tables'] + tables = kw["tables"] listener(event, target, connection, tables=tables) - event.listen(self, "" + event_name.replace('-', '_'), adapt_listener) + event.listen(self, "" + event_name.replace("-", "_"), adapt_listener) def create_all(self, bind=None, tables=None, checkfirst=True): """Create all tables stored in this metadata. @@ -4017,10 +4213,9 @@ class MetaData(SchemaItem): """ if bind is None: bind = _bind_or_error(self) - bind._run_visitor(ddl.SchemaGenerator, - self, - checkfirst=checkfirst, - tables=tables) + bind._run_visitor( + ddl.SchemaGenerator, self, checkfirst=checkfirst, tables=tables + ) def drop_all(self, bind=None, tables=None, checkfirst=True): """Drop all tables stored in this metadata. @@ -4044,10 +4239,9 @@ class MetaData(SchemaItem): """ if bind is None: bind = _bind_or_error(self) - bind._run_visitor(ddl.SchemaDropper, - self, - checkfirst=checkfirst, - tables=tables) + bind._run_visitor( + ddl.SchemaDropper, self, checkfirst=checkfirst, tables=tables + ) class ThreadLocalMetaData(MetaData): @@ -4064,7 +4258,7 @@ class ThreadLocalMetaData(MetaData): """ - __visit_name__ = 'metadata' + __visit_name__ = "metadata" def __init__(self): """Construct a ThreadLocalMetaData.""" @@ -4080,13 +4274,13 @@ class ThreadLocalMetaData(MetaData): string or URL to automatically create a basic Engine for this bind with ``create_engine()``.""" - return getattr(self.context, '_engine', None) + return getattr(self.context, "_engine", None) @util.dependencies("sqlalchemy.engine.url") def _bind_to(self, url, bind): """Bind to a Connectable in the caller's thread.""" - if isinstance(bind, util.string_types + (url.URL, )): + if isinstance(bind, util.string_types + (url.URL,)): try: self.context._engine = self.__engines[bind] except KeyError: @@ -4104,14 +4298,16 @@ class ThreadLocalMetaData(MetaData): def is_bound(self): """True if there is a bind for this thread.""" - return (hasattr(self.context, '_engine') and - self.context._engine is not None) + return ( + hasattr(self.context, "_engine") + and self.context._engine is not None + ) def dispose(self): """Dispose all bound engines, in all thread contexts.""" for e in self.__engines.values(): - if hasattr(e, 'dispose'): + if hasattr(e, "dispose"): e.dispose() @@ -4128,22 +4324,25 @@ class _SchemaTranslateMap(object): """ - __slots__ = 'map_', '__call__', 'hash_key', 'is_default' + + __slots__ = "map_", "__call__", "hash_key", "is_default" _default_schema_getter = operator.attrgetter("schema") def __init__(self, map_): self.map_ = map_ if map_ is not None: + def schema_for_object(obj): effective_schema = self._default_schema_getter(obj) effective_schema = obj._translate_schema( - effective_schema, map_) + effective_schema, map_ + ) return effective_schema + self.__call__ = schema_for_object self.hash_key = ";".join( - "%s=%s" % (k, map_[k]) - for k in sorted(map_, key=str) + "%s=%s" % (k, map_[k]) for k in sorted(map_, key=str) ) self.is_default = False else: @@ -4160,6 +4359,6 @@ class _SchemaTranslateMap(object): else: return _SchemaTranslateMap(map_) + _default_schema_map = _SchemaTranslateMap(None) _schema_getter = _SchemaTranslateMap._schema_getter - |