Merge tag '0.8.10' into debian/ocata
Change-Id: I7bc453ba285514e10b38803a77634b9cf08bcfe0
This commit is contained in:
commit
0d2a1dc76b
2
LICENSE
2
LICENSE
|
@ -1,6 +1,6 @@
|
|||
This is the MIT license: http://www.opensource.org/licenses/mit-license.php
|
||||
|
||||
Copyright (C) 2009-2016 by Michael Bayer.
|
||||
Copyright (C) 2009-2017 by Michael Bayer.
|
||||
Alembic is a trademark of Michael Bayer.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
from os import path
|
||||
|
||||
__version__ = '0.8.8'
|
||||
__version__ = '0.8.10'
|
||||
|
||||
package_dir = path.abspath(path.dirname(__file__))
|
||||
|
||||
|
|
|
@ -195,11 +195,14 @@ def _make_index(params, conn_table):
|
|||
|
||||
|
||||
def _make_unique_constraint(params, conn_table):
|
||||
# TODO: add .info such as 'duplicates_index'
|
||||
return sa_schema.UniqueConstraint(
|
||||
uq = sa_schema.UniqueConstraint(
|
||||
*[conn_table.c[cname] for cname in params['column_names']],
|
||||
name=params['name']
|
||||
)
|
||||
if 'duplicates_index' in params:
|
||||
uq.info['duplicates_index'] = params['duplicates_index']
|
||||
|
||||
return uq
|
||||
|
||||
|
||||
def _make_foreign_key(params, conn_table):
|
||||
|
@ -364,6 +367,8 @@ def _compare_indexes_and_uniques(
|
|||
|
||||
supports_unique_constraints = False
|
||||
|
||||
unique_constraints_duplicate_unique_indexes = False
|
||||
|
||||
if conn_table is not None:
|
||||
# 1b. ... and from connection, if the table exists
|
||||
if hasattr(inspector, "get_unique_constraints"):
|
||||
|
@ -373,6 +378,15 @@ def _compare_indexes_and_uniques(
|
|||
supports_unique_constraints = True
|
||||
except NotImplementedError:
|
||||
pass
|
||||
except TypeError:
|
||||
# number of arguments is off for the base
|
||||
# method in SQLAlchemy due to the cache decorator
|
||||
# not being present
|
||||
pass
|
||||
else:
|
||||
for uq in conn_uniques:
|
||||
if uq.get('duplicates_index'):
|
||||
unique_constraints_duplicate_unique_indexes = True
|
||||
try:
|
||||
conn_indexes = inspector.get_indexes(tname, schema=schema)
|
||||
except NotImplementedError:
|
||||
|
@ -384,6 +398,16 @@ def _compare_indexes_and_uniques(
|
|||
for uq_def in conn_uniques)
|
||||
conn_indexes = set(_make_index(ix, conn_table) for ix in conn_indexes)
|
||||
|
||||
# 2a. if the dialect dupes unique indexes as unique constraints
|
||||
# (mysql and oracle), correct for that
|
||||
|
||||
if unique_constraints_duplicate_unique_indexes:
|
||||
_correct_for_uq_duplicates_uix(
|
||||
conn_uniques, conn_indexes,
|
||||
metadata_unique_constraints,
|
||||
metadata_indexes
|
||||
)
|
||||
|
||||
# 3. give the dialect a chance to omit indexes and constraints that
|
||||
# we know are either added implicitly by the DB or that the DB
|
||||
# can't accurately report on
|
||||
|
@ -581,6 +605,48 @@ def _compare_indexes_and_uniques(
|
|||
obj_added(unnamed_metadata_uniques[uq_sig])
|
||||
|
||||
|
||||
def _correct_for_uq_duplicates_uix(
|
||||
conn_unique_constraints,
|
||||
conn_indexes,
|
||||
metadata_unique_constraints,
|
||||
metadata_indexes):
|
||||
|
||||
# dedupe unique indexes vs. constraints, since MySQL / Oracle
|
||||
# doesn't really have unique constraints as a separate construct.
|
||||
# but look in the metadata and try to maintain constructs
|
||||
# that already seem to be defined one way or the other
|
||||
# on that side. This logic was formerly local to MySQL dialect,
|
||||
# generalized to Oracle and others. See #276
|
||||
metadata_uq_names = set([
|
||||
cons.name for cons in metadata_unique_constraints
|
||||
if cons.name is not None])
|
||||
|
||||
unnamed_metadata_uqs = set([
|
||||
_uq_constraint_sig(cons).sig
|
||||
for cons in metadata_unique_constraints
|
||||
if cons.name is None
|
||||
])
|
||||
|
||||
metadata_ix_names = set([
|
||||
cons.name for cons in metadata_indexes if cons.unique])
|
||||
conn_ix_names = dict(
|
||||
(cons.name, cons) for cons in conn_indexes if cons.unique
|
||||
)
|
||||
|
||||
uqs_dupe_indexes = dict(
|
||||
(cons.name, cons) for cons in conn_unique_constraints
|
||||
if cons.info['duplicates_index']
|
||||
)
|
||||
for overlap in uqs_dupe_indexes:
|
||||
if overlap not in metadata_uq_names:
|
||||
if _uq_constraint_sig(uqs_dupe_indexes[overlap]).sig \
|
||||
not in unnamed_metadata_uqs:
|
||||
|
||||
conn_unique_constraints.discard(uqs_dupe_indexes[overlap])
|
||||
elif overlap not in metadata_ix_names:
|
||||
conn_indexes.discard(conn_ix_names[overlap])
|
||||
|
||||
|
||||
@comparators.dispatch_for("column")
|
||||
def _compare_nullable(
|
||||
autogen_context, alter_column_op, schema, tname, cname, conn_col,
|
||||
|
|
|
@ -52,8 +52,7 @@ def _render_cmd_body(op_container, autogen_context):
|
|||
printer = PythonPrinter(buf)
|
||||
|
||||
printer.writeline(
|
||||
"### commands auto generated by Alembic - "
|
||||
"please adjust! ###"
|
||||
"# ### commands auto generated by Alembic - please adjust! ###"
|
||||
)
|
||||
|
||||
if not op_container.ops:
|
||||
|
@ -65,7 +64,7 @@ def _render_cmd_body(op_container, autogen_context):
|
|||
for line in lines:
|
||||
printer.writeline(line)
|
||||
|
||||
printer.writeline("### end Alembic commands ###")
|
||||
printer.writeline("# ### end Alembic commands ###")
|
||||
|
||||
return buf.getvalue()
|
||||
|
||||
|
|
|
@ -256,7 +256,7 @@ class DefaultImpl(with_metaclass(ImplMeta)):
|
|||
):
|
||||
comparator = _type_comparators.get(conn_type._type_affinity, None)
|
||||
|
||||
return comparator and comparator(metadata_type, conn_type)
|
||||
return comparator and comparator(metadata_impl, conn_type)
|
||||
else:
|
||||
return True
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ from .base import ColumnNullable, ColumnName, ColumnDefault, \
|
|||
format_server_default
|
||||
from .base import alter_table
|
||||
from ..autogenerate import compare
|
||||
from ..util.sqla_compat import _is_type_bound
|
||||
from ..util.sqla_compat import _is_type_bound, sqla_100
|
||||
|
||||
|
||||
class MySQLImpl(DefaultImpl):
|
||||
|
@ -132,6 +132,19 @@ class MySQLImpl(DefaultImpl):
|
|||
if idx.name in removed:
|
||||
metadata_indexes.remove(idx)
|
||||
|
||||
if not sqla_100:
|
||||
self._legacy_correct_for_dupe_uq_uix(
|
||||
conn_unique_constraints,
|
||||
conn_indexes,
|
||||
metadata_unique_constraints,
|
||||
metadata_indexes
|
||||
)
|
||||
|
||||
def _legacy_correct_for_dupe_uq_uix(self, conn_unique_constraints,
|
||||
conn_indexes,
|
||||
metadata_unique_constraints,
|
||||
metadata_indexes):
|
||||
|
||||
# then dedupe unique indexes vs. constraints, since MySQL
|
||||
# doesn't really have unique constraints as a separate construct.
|
||||
# but look in the metadata and try to maintain constructs
|
||||
|
|
|
@ -162,7 +162,9 @@ class PostgresqlImpl(DefaultImpl):
|
|||
else:
|
||||
exprs = idx.columns
|
||||
for expr in exprs:
|
||||
if not isinstance(expr, (Column, UnaryExpression)):
|
||||
while isinstance(expr, UnaryExpression):
|
||||
expr = expr.element
|
||||
if not isinstance(expr, Column):
|
||||
util.warn(
|
||||
"autogenerate skipping functional index %s; "
|
||||
"not supported by SQLAlchemy reflection" % idx.name
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
from sqlalchemy import Table, MetaData, Index, select, Column, \
|
||||
ForeignKeyConstraint, cast, CheckConstraint
|
||||
ForeignKeyConstraint, PrimaryKeyConstraint, cast, CheckConstraint
|
||||
from sqlalchemy import types as sqltypes
|
||||
from sqlalchemy import schema as sql_schema
|
||||
from sqlalchemy.util import OrderedDict
|
||||
|
@ -301,6 +301,10 @@ class ApplyBatchImpl(object):
|
|||
existing.type._create_events = \
|
||||
existing.type.create_constraint = False
|
||||
|
||||
if existing.type._type_affinity is not type_._type_affinity:
|
||||
existing_transfer["expr"] = cast(
|
||||
existing_transfer["expr"], type_)
|
||||
|
||||
existing.type = type_
|
||||
|
||||
# we *dont* however set events for the new type, because
|
||||
|
@ -308,7 +312,6 @@ class ApplyBatchImpl(object):
|
|||
# Operations.implementation_for(alter_column) which already
|
||||
# will emit an add_constraint()
|
||||
|
||||
existing_transfer["expr"] = cast(existing_transfer["expr"], type_)
|
||||
if nullable is not None:
|
||||
existing.nullable = nullable
|
||||
if server_default is not False:
|
||||
|
@ -342,7 +345,7 @@ class ApplyBatchImpl(object):
|
|||
if not const.name:
|
||||
raise ValueError("Constraint must have a name")
|
||||
try:
|
||||
del self.named_constraints[const.name]
|
||||
const = self.named_constraints.pop(const.name)
|
||||
except KeyError:
|
||||
if _is_type_bound(const):
|
||||
# type-bound constraints are only included in the new
|
||||
|
@ -351,6 +354,10 @@ class ApplyBatchImpl(object):
|
|||
# Operations.implementation_for(alter_column)
|
||||
return
|
||||
raise ValueError("No such constraint: '%s'" % const.name)
|
||||
else:
|
||||
if isinstance(const, PrimaryKeyConstraint):
|
||||
for col in const.columns:
|
||||
self.columns[col.name].primary_key = False
|
||||
|
||||
def create_index(self, idx):
|
||||
self.new_indexes[idx.name] = idx
|
||||
|
|
|
@ -405,6 +405,16 @@ class EnvironmentContext(util.ModuleClsProxy):
|
|||
The default is ``'alembic_version'``.
|
||||
:param version_table_schema: Optional schema to place version
|
||||
table within.
|
||||
:param version_table_pk: boolean, whether the Alembic version table
|
||||
should use a primary key constraint for the "value" column; this
|
||||
only takes effect when the table is first created.
|
||||
Defaults to True; setting to False should not be necessary and is
|
||||
here for backwards compatibility reasons.
|
||||
|
||||
.. versionadded:: 0.8.10 Added the
|
||||
:paramref:`.EnvironmentContext.configure.version_table_pk`
|
||||
flag and additionally established that the Alembic version table
|
||||
has a primary key constraint by default.
|
||||
|
||||
Parameters specific to the autogenerate feature, when
|
||||
``alembic revision`` is run with the ``--autogenerate`` feature:
|
||||
|
|
|
@ -2,7 +2,8 @@ import logging
|
|||
import sys
|
||||
from contextlib import contextmanager
|
||||
|
||||
from sqlalchemy import MetaData, Table, Column, String, literal_column
|
||||
from sqlalchemy import MetaData, Table, Column, String, literal_column,\
|
||||
PrimaryKeyConstraint
|
||||
from sqlalchemy.engine.strategies import MockEngineStrategy
|
||||
from sqlalchemy.engine import url as sqla_url
|
||||
|
||||
|
@ -98,6 +99,12 @@ class MigrationContext(object):
|
|||
version_table, MetaData(),
|
||||
Column('version_num', String(32), nullable=False),
|
||||
schema=version_table_schema)
|
||||
if opts.get("version_table_pk", True):
|
||||
self._version.append_constraint(
|
||||
PrimaryKeyConstraint(
|
||||
'version_num', name="%s_pkc" % version_table
|
||||
)
|
||||
)
|
||||
|
||||
self._start_from_rev = opts.get("starting_rev")
|
||||
self.impl = ddl.DefaultImpl.get_by_dialect(dialect)(
|
||||
|
@ -230,7 +237,9 @@ class MigrationContext(object):
|
|||
"""
|
||||
if self.as_sql:
|
||||
start_from_rev = self._start_from_rev
|
||||
if start_from_rev is not None and self.script:
|
||||
if start_from_rev == 'base':
|
||||
start_from_rev = None
|
||||
elif start_from_rev is not None and self.script:
|
||||
start_from_rev = \
|
||||
self.script.get_revision(start_from_rev).revision
|
||||
|
||||
|
|
|
@ -9,8 +9,8 @@ from ..runtime import migration
|
|||
|
||||
from contextlib import contextmanager
|
||||
|
||||
_sourceless_rev_file = re.compile(r'(?!__init__)(.*\.py)(c|o)?$')
|
||||
_only_source_rev_file = re.compile(r'(?!__init__)(.*\.py)$')
|
||||
_sourceless_rev_file = re.compile(r'(?!\.\#|__init__)(.*\.py)(c|o)?$')
|
||||
_only_source_rev_file = re.compile(r'(?!\.\#|__init__)(.*\.py)$')
|
||||
_legacy_rev = re.compile(r'([a-f0-9]+)\.py$')
|
||||
_mod_def_re = re.compile(r'(upgrade|downgrade)_([a-z0-9]+)')
|
||||
_slug_re = re.compile(r'\w+')
|
||||
|
@ -82,8 +82,17 @@ class ScriptDirectory(object):
|
|||
else:
|
||||
paths = [self.versions]
|
||||
|
||||
dupes = set()
|
||||
for vers in paths:
|
||||
for file_ in os.listdir(vers):
|
||||
path = os.path.realpath(os.path.join(vers, file_))
|
||||
if path in dupes:
|
||||
util.warn(
|
||||
"File %s loaded twice! ignoring. Please ensure "
|
||||
"version_locations is unique." % path
|
||||
)
|
||||
continue
|
||||
dupes.add(path)
|
||||
script = Script._from_filename(self, vers, file_)
|
||||
if script is None:
|
||||
continue
|
||||
|
|
|
@ -15,6 +15,7 @@ down_revision = ${repr(down_revision)}
|
|||
branch_labels = ${repr(branch_labels)}
|
||||
depends_on = ${repr(depends_on)}
|
||||
|
||||
|
||||
def upgrade():
|
||||
${upgrades if upgrades else "pass"}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# testing/config.py
|
||||
# Copyright (C) 2005-2016 the SQLAlchemy authors and contributors
|
||||
# Copyright (C) 2005-2017 the SQLAlchemy authors and contributors
|
||||
# <see AUTHORS file>
|
||||
#
|
||||
# This module is part of SQLAlchemy and is released under
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# testing/engines.py
|
||||
# Copyright (C) 2005-2016 the SQLAlchemy authors and contributors
|
||||
# Copyright (C) 2005-2017 the SQLAlchemy authors and contributors
|
||||
# <see AUTHORS file>
|
||||
#
|
||||
# This module is part of SQLAlchemy and is released under
|
||||
|
|
|
@ -115,7 +115,7 @@ datefmt = %%H:%%M:%%S
|
|||
|
||||
|
||||
|
||||
def _multi_dir_testing_config(sourceless=False):
|
||||
def _multi_dir_testing_config(sourceless=False, extra_version_location=''):
|
||||
dir_ = os.path.join(_get_staging_directory(), 'scripts')
|
||||
url = "sqlite:///%s/foo.db" % dir_
|
||||
|
||||
|
@ -124,7 +124,7 @@ def _multi_dir_testing_config(sourceless=False):
|
|||
script_location = %s
|
||||
sqlalchemy.url = %s
|
||||
sourceless = %s
|
||||
version_locations = %%(here)s/model1/ %%(here)s/model2/ %%(here)s/model3/
|
||||
version_locations = %%(here)s/model1/ %%(here)s/model2/ %%(here)s/model3/ %s
|
||||
|
||||
[loggers]
|
||||
keys = root
|
||||
|
@ -149,7 +149,8 @@ keys = generic
|
|||
[formatter_generic]
|
||||
format = %%(levelname)-5.5s [%%(name)s] %%(message)s
|
||||
datefmt = %%H:%%M:%%S
|
||||
""" % (dir_, url, "true" if sourceless else "false"))
|
||||
""" % (dir_, url, "true" if sourceless else "false",
|
||||
extra_version_location))
|
||||
|
||||
|
||||
def _no_sql_testing_config(dialect="postgresql", directives=""):
|
||||
|
@ -256,9 +257,11 @@ down_revision = None
|
|||
|
||||
from alembic import op
|
||||
|
||||
|
||||
def upgrade():
|
||||
op.execute("CREATE STEP 1")
|
||||
|
||||
|
||||
def downgrade():
|
||||
op.execute("DROP STEP 1")
|
||||
|
||||
|
@ -272,9 +275,11 @@ down_revision = '%s'
|
|||
|
||||
from alembic import op
|
||||
|
||||
|
||||
def upgrade():
|
||||
op.execute("CREATE STEP 2")
|
||||
|
||||
|
||||
def downgrade():
|
||||
op.execute("DROP STEP 2")
|
||||
|
||||
|
@ -288,9 +293,11 @@ down_revision = '%s'
|
|||
|
||||
from alembic import op
|
||||
|
||||
|
||||
def upgrade():
|
||||
op.execute("CREATE STEP 3")
|
||||
|
||||
|
||||
def downgrade():
|
||||
op.execute("DROP STEP 3")
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# testing/exclusions.py
|
||||
# Copyright (C) 2005-2016 the SQLAlchemy authors and contributors
|
||||
# Copyright (C) 2005-2017 the SQLAlchemy authors and contributors
|
||||
# <see AUTHORS file>
|
||||
#
|
||||
# This module is part of SQLAlchemy and is released under
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# testing/mock.py
|
||||
# Copyright (C) 2005-2016 the SQLAlchemy authors and contributors
|
||||
# Copyright (C) 2005-2017 the SQLAlchemy authors and contributors
|
||||
# <see AUTHORS file>
|
||||
#
|
||||
# This module is part of SQLAlchemy and is released under
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# plugin/noseplugin.py
|
||||
# Copyright (C) 2005-2016 the SQLAlchemy authors and contributors
|
||||
# Copyright (C) 2005-2017 the SQLAlchemy authors and contributors
|
||||
# <see AUTHORS file>
|
||||
#
|
||||
# This module is part of SQLAlchemy and is released under
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# plugin/plugin_base.py
|
||||
# Copyright (C) 2005-2016 the SQLAlchemy authors and contributors
|
||||
# Copyright (C) 2005-2017 the SQLAlchemy authors and contributors
|
||||
# <see AUTHORS file>
|
||||
#
|
||||
# This module is part of SQLAlchemy and is released under
|
||||
|
@ -22,7 +22,8 @@ try:
|
|||
# honor it unless nose is imported too...
|
||||
from nose import SkipTest
|
||||
except ImportError:
|
||||
from _pytest.runner import Skipped as SkipTest
|
||||
from pytest import skip
|
||||
SkipTest = skip.Exception
|
||||
|
||||
import sys
|
||||
import re
|
||||
|
@ -75,6 +76,9 @@ def setup_options(make_option):
|
|||
dest="low_connections",
|
||||
help="Use a low number of distinct connections - "
|
||||
"i.e. for Oracle TNS")
|
||||
make_option("--write-idents", type="string", dest="write_idents",
|
||||
help="write out generated follower idents to <file>, "
|
||||
"when -n<num> is used")
|
||||
make_option("--reversetop", action="store_true",
|
||||
dest="reversetop", default=False,
|
||||
help="Use a random-ordering set implementation in the ORM "
|
||||
|
|
|
@ -17,7 +17,7 @@ import pytest
|
|||
import argparse
|
||||
import inspect
|
||||
import collections
|
||||
import itertools
|
||||
import os
|
||||
|
||||
try:
|
||||
import xdist # noqa
|
||||
|
@ -50,6 +50,14 @@ def pytest_configure(config):
|
|||
plugin_base.configure_follower(
|
||||
config.slaveinput["follower_ident"]
|
||||
)
|
||||
if config.option.write_idents:
|
||||
with open(config.option.write_idents, "a") as file_:
|
||||
file_.write(config.slaveinput["follower_ident"] + "\n")
|
||||
else:
|
||||
if config.option.write_idents and \
|
||||
os.path.exists(config.option.write_idents):
|
||||
os.remove(config.option.write_idents)
|
||||
|
||||
|
||||
plugin_base.pre_begin(config.option)
|
||||
|
||||
|
|
|
@ -275,9 +275,14 @@ def _oracle_drop_db(cfg, eng, ident):
|
|||
_ora_drop_ignore(conn, "%s_ts2" % ident)
|
||||
|
||||
|
||||
def reap_oracle_dbs(eng):
|
||||
def reap_oracle_dbs(eng, idents_file):
|
||||
log.info("Reaping Oracle dbs...")
|
||||
with eng.connect() as conn:
|
||||
with open(idents_file) as file_:
|
||||
idents = set(line.strip() for line in file_)
|
||||
|
||||
log.info("identifiers in file: %s", ", ".join(idents))
|
||||
|
||||
to_reap = conn.execute(
|
||||
"select u.username from all_users u where username "
|
||||
"like 'TEST_%' and not exists (select username "
|
||||
|
@ -287,7 +292,7 @@ def reap_oracle_dbs(eng):
|
|||
for name in all_names:
|
||||
if name.endswith("_ts1") or name.endswith("_ts2"):
|
||||
continue
|
||||
else:
|
||||
elif name in idents:
|
||||
to_drop.add(name)
|
||||
if "%s_ts1" % name in all_names:
|
||||
to_drop.add("%s_ts1" % name)
|
||||
|
|
|
@ -19,10 +19,25 @@ class SuiteRequirements(Requirements):
|
|||
|
||||
@property
|
||||
def unique_constraint_reflection(self):
|
||||
def doesnt_have_check_uq_constraints(config):
|
||||
if not util.sqla_084:
|
||||
return True
|
||||
from sqlalchemy import inspect
|
||||
insp = inspect(config.db)
|
||||
try:
|
||||
insp.get_unique_constraints('x')
|
||||
except NotImplementedError:
|
||||
return True
|
||||
except TypeError:
|
||||
return True
|
||||
except Exception:
|
||||
pass
|
||||
return False
|
||||
|
||||
return exclusions.skip_if(
|
||||
lambda config: not util.sqla_084,
|
||||
"SQLAlchemy 0.8.4 or greater required"
|
||||
)
|
||||
) + exclusions.skip_if(doesnt_have_check_uq_constraints)
|
||||
|
||||
@property
|
||||
def foreign_key_match(self):
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#!/usr/bin/env python
|
||||
# testing/runner.py
|
||||
# Copyright (C) 2005-2016 the SQLAlchemy authors and contributors
|
||||
# Copyright (C) 2005-2017 the SQLAlchemy authors and contributors
|
||||
# <see AUTHORS file>
|
||||
#
|
||||
# This module is part of SQLAlchemy and is released under
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# testing/warnings.py
|
||||
# Copyright (C) 2005-2016 the SQLAlchemy authors and contributors
|
||||
# Copyright (C) 2005-2017 the SQLAlchemy authors and contributors
|
||||
# <see AUTHORS file>
|
||||
#
|
||||
# This module is part of SQLAlchemy and is released under
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
alembic (0.8.8-3) UNRELEASED; urgency=medium
|
||||
alembic (0.8.10-1) UNRELEASED; urgency=medium
|
||||
|
||||
* New upstream release
|
||||
* d/control + d/gbp.conf: Change branch to debian/ocata
|
||||
* d/copyright: Bump copyright years
|
||||
|
||||
-- Ondřej Nový <onovy@debian.org> Sun, 26 Feb 2017 11:33:46 +0100
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ Upstream-Contact: Mike Bayer
|
|||
Source: https://pypi.python.org/pypi/alembic
|
||||
|
||||
Files: *
|
||||
Copyright: 2009-2016, Michael Bayer
|
||||
Copyright: 2009-2017, Michael Bayer
|
||||
License: MIT
|
||||
|
||||
Files: alembic/testing/config.py
|
||||
|
@ -15,7 +15,7 @@ Files: alembic/testing/config.py
|
|||
alembic/testing/plugin/plugin_base.py
|
||||
alembic/testing/warnings.py
|
||||
alembic/testing/runner.py
|
||||
Copyright: (c) 2005-2016 the SQLAlchemy authors and contributors
|
||||
Copyright: (c) 2005-2017 the SQLAlchemy authors and contributors
|
||||
License: MIT
|
||||
|
||||
Files: debian/*
|
||||
|
@ -25,7 +25,7 @@ Copyright: (c) 2012, Matthias Kümmerer <matthias@matthias-k.org>
|
|||
(c) 2014, Thomas Bechtold <toabctl@debian.org>
|
||||
(c) 2014, Piotr Ożarowski <piotr@debian.org>
|
||||
(c) 2013-2015, Thomas Goirand <zigo@debian.org>
|
||||
(c) 2016, Ondřej Nový <onovy@debian.org>
|
||||
(c) 2016-2017, Ondřej Nový <onovy@debian.org>
|
||||
License: MIT
|
||||
|
||||
License: MIT
|
||||
|
|
|
@ -3,6 +3,112 @@
|
|||
Changelog
|
||||
==========
|
||||
|
||||
.. changelog::
|
||||
:version: 0.8.10
|
||||
:released: January 17, 2017
|
||||
|
||||
.. change:: 406
|
||||
:tags: bug, versioning
|
||||
:tickets: 406
|
||||
|
||||
The alembic_version table, when initially created, now establishes a
|
||||
primary key constraint on the "version_num" column, to suit database
|
||||
engines that don't support tables without primary keys. This behavior
|
||||
can be controlled using the parameter
|
||||
:paramref:`.EnvironmentContext.configure.version_table_pk`. Note that
|
||||
this change only applies to the initial creation of the alembic_version
|
||||
table; it does not impact any existing alembic_version table already
|
||||
present.
|
||||
|
||||
.. change:: 402
|
||||
:tags: bug, batch
|
||||
:tickets: 402
|
||||
|
||||
Fixed bug where doing ``batch_op.drop_constraint()`` against the
|
||||
primary key constraint would fail to remove the "primary_key" flag
|
||||
from the column, resulting in the constraint being recreated.
|
||||
|
||||
.. change:: update_uq_dedupe
|
||||
:tags: bug, autogenerate, oracle
|
||||
|
||||
Adjusted the logic originally added for :ticket:`276` that detects MySQL
|
||||
unique constraints which are actually unique indexes to be generalized
|
||||
for any dialect that has this behavior, for SQLAlchemy version 1.0 and
|
||||
greater. This is to allow for upcoming SQLAlchemy support for unique
|
||||
constraint reflection for Oracle, which also has no dedicated concept of
|
||||
"unique constraint" and instead establishes a unique index.
|
||||
|
||||
.. change:: 356
|
||||
:tags: bug, versioning
|
||||
:tickets: 356
|
||||
|
||||
Added a file ignore for Python files of the form ``.#<name>.py``,
|
||||
which are generated by the Emacs editor. Pull request courtesy
|
||||
Markus Mattes.
|
||||
|
||||
.. changelog::
|
||||
:version: 0.8.9
|
||||
:released: November 28, 2016
|
||||
|
||||
.. change:: 393
|
||||
:tags: bug, autogenerate
|
||||
:tickets: 393
|
||||
|
||||
Adjustment to the "please adjust!" comment in the script.py.mako
|
||||
template so that the generated comment starts with a single pound
|
||||
sign, appeasing flake8.
|
||||
|
||||
.. change::
|
||||
:tags: bug, batch
|
||||
:tickets: 391
|
||||
|
||||
Batch mode will not use CAST() to copy data if type_ is given, however
|
||||
the basic type affinity matches that of the existing type. This to
|
||||
avoid SQLite's CAST of TIMESTAMP which results in truncation of the
|
||||
data, in those cases where the user needs to add redundant type_ for
|
||||
other reasons.
|
||||
|
||||
.. change::
|
||||
:tags: bug, autogenerate
|
||||
:tickets: 393
|
||||
|
||||
Continued pep8 improvements by adding appropriate whitespace in
|
||||
the base template for generated migrations. Pull request courtesy
|
||||
Markus Mattes.
|
||||
|
||||
.. change::
|
||||
:tags: bug, revisioning
|
||||
|
||||
Added an additional check when reading in revision files to detect
|
||||
if the same file is being read twice; this can occur if the same directory
|
||||
or a symlink equivalent is present more than once in version_locations.
|
||||
A warning is now emitted and the file is skipped. Pull request courtesy
|
||||
Jiri Kuncar.
|
||||
|
||||
.. change::
|
||||
:tags: bug, autogenerate
|
||||
:tickets: 395
|
||||
|
||||
Fixed bug where usage of a custom TypeDecorator which returns a
|
||||
per-dialect type via :meth:`.TypeDecorator.load_dialect_impl` that differs
|
||||
significantly from the default "impl" for the type decorator would fail
|
||||
to compare correctly during autogenerate.
|
||||
|
||||
.. change::
|
||||
:tags: bug, autogenerate, postgresql
|
||||
:tickets: 392
|
||||
|
||||
Fixed bug in Postgresql "functional index skip" behavior where a
|
||||
functional index that ended in ASC/DESC wouldn't be detected as something
|
||||
we can't compare in autogenerate, leading to duplicate definitions
|
||||
in autogenerated files.
|
||||
|
||||
.. change::
|
||||
:tags: bug, versioning
|
||||
|
||||
Fixed bug where the "base" specifier, as in "base:head", could not
|
||||
be used explicitly when ``--sql`` mode was present.
|
||||
|
||||
.. changelog::
|
||||
:version: 0.8.8
|
||||
:released: September 12, 2016
|
||||
|
|
|
@ -63,7 +63,7 @@ master_doc = 'index'
|
|||
|
||||
# General information about the project.
|
||||
project = u'Alembic'
|
||||
copyright = u'2010-2016, Mike Bayer'
|
||||
copyright = u'2010-2017, Mike Bayer'
|
||||
|
||||
# The version info for the project you're documenting, acts as replacement for
|
||||
# |version| and |release|, also used in various other places throughout the
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
changelog>=0.3.4
|
||||
changelog>=0.3.5
|
||||
sphinx-paramlinks>=0.3.2
|
||||
git+https://bitbucket.org/zzzeek/sqlalchemy.git
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
"""Drop Oracle databases that are left over from a
|
||||
"""Drop Oracle databases that are left over from a
|
||||
multiprocessing test run.
|
||||
|
||||
Currently the cx_Oracle driver seems to sometimes not release a
|
||||
|
@ -6,19 +6,19 @@ TCP connection even if close() is called, which prevents the provisioning
|
|||
system from dropping a database in-process.
|
||||
|
||||
"""
|
||||
from sqlalchemy.testing.plugin import plugin_base
|
||||
from sqlalchemy.testing import engines
|
||||
from sqlalchemy.testing import provision
|
||||
from alembic.testing.plugin import plugin_base
|
||||
from alembic.testing import engines
|
||||
from alembic.testing import provision
|
||||
import logging
|
||||
import sys
|
||||
|
||||
logging.basicConfig()
|
||||
logging.getLogger(provision.__name__).setLevel(logging.INFO)
|
||||
|
||||
plugin_base.read_config()
|
||||
oracle = plugin_base.file_config.get('db', 'oracle')
|
||||
from sqlalchemy.testing import provision
|
||||
|
||||
engine = engines.testing_engine(oracle, {})
|
||||
provision.reap_oracle_dbs(engine)
|
||||
provision.reap_oracle_dbs(engine, sys.argv[1])
|
||||
|
||||
|
||||
|
|
|
@ -34,7 +34,7 @@ oracle8=oracle://scott:tiger@127.0.0.1:1521/?use_ansi=0
|
|||
[alembic]
|
||||
|
||||
|
||||
[pytest]
|
||||
[tool:pytest]
|
||||
addopts= --tb native -v -r fxX
|
||||
python_files=tests/test_*.py
|
||||
|
||||
|
|
|
@ -54,6 +54,12 @@ class DefaultRequirements(SuiteRequirements):
|
|||
"""foreign key constraints always have names in the DB"""
|
||||
return exclusions.fails_on('sqlite')
|
||||
|
||||
@property
|
||||
def no_name_normalize(self):
|
||||
return exclusions.skip_if(
|
||||
lambda config: config.db.dialect.requires_name_normalize
|
||||
)
|
||||
|
||||
@property
|
||||
def reflects_fk_options(self):
|
||||
return exclusions.only_on([
|
||||
|
@ -71,6 +77,16 @@ class DefaultRequirements(SuiteRequirements):
|
|||
"""backend supports DEFERRABLE option in foreign keys"""
|
||||
return exclusions.only_on(['postgresql'])
|
||||
|
||||
@property
|
||||
def flexible_fk_cascades(self):
|
||||
"""target database must support ON UPDATE/DELETE..CASCADE with the
|
||||
full range of keywords (e.g. NO ACTION, etc.)"""
|
||||
|
||||
return exclusions.skip_if(
|
||||
['oracle'],
|
||||
'target backend has poor FK cascade syntax'
|
||||
)
|
||||
|
||||
@property
|
||||
def reflects_unique_constraints_unambiguously(self):
|
||||
return exclusions.fails_on("mysql")
|
||||
|
|
|
@ -26,13 +26,13 @@ class AutogenerateDiffTest(ModelOne, AutogenTest, TestBase):
|
|||
autogenerate._render_migration_diffs(context, template_args)
|
||||
|
||||
eq_(re.sub(r"u'", "'", template_args['upgrades']),
|
||||
"""### commands auto generated by Alembic - please adjust! ###
|
||||
"""# ### commands auto generated by Alembic - please adjust! ###
|
||||
pass
|
||||
### end Alembic commands ###""")
|
||||
# ### end Alembic commands ###""")
|
||||
eq_(re.sub(r"u'", "'", template_args['downgrades']),
|
||||
"""### commands auto generated by Alembic - please adjust! ###
|
||||
"""# ### commands auto generated by Alembic - please adjust! ###
|
||||
pass
|
||||
### end Alembic commands ###""")
|
||||
# ### end Alembic commands ###""")
|
||||
|
||||
def test_render_nothing_batch(self):
|
||||
context = MigrationContext.configure(
|
||||
|
@ -53,13 +53,13 @@ class AutogenerateDiffTest(ModelOne, AutogenTest, TestBase):
|
|||
autogenerate._render_migration_diffs(context, template_args)
|
||||
|
||||
eq_(re.sub(r"u'", "'", template_args['upgrades']),
|
||||
"""### commands auto generated by Alembic - please adjust! ###
|
||||
"""# ### commands auto generated by Alembic - please adjust! ###
|
||||
pass
|
||||
### end Alembic commands ###""")
|
||||
# ### end Alembic commands ###""")
|
||||
eq_(re.sub(r"u'", "'", template_args['downgrades']),
|
||||
"""### commands auto generated by Alembic - please adjust! ###
|
||||
"""# ### commands auto generated by Alembic - please adjust! ###
|
||||
pass
|
||||
### end Alembic commands ###""")
|
||||
# ### end Alembic commands ###""")
|
||||
|
||||
def test_render_diffs_standard(self):
|
||||
"""test a full render including indentation"""
|
||||
|
@ -67,7 +67,7 @@ class AutogenerateDiffTest(ModelOne, AutogenTest, TestBase):
|
|||
template_args = {}
|
||||
autogenerate._render_migration_diffs(self.context, template_args)
|
||||
eq_(re.sub(r"u'", "'", template_args['upgrades']),
|
||||
"""### commands auto generated by Alembic - please adjust! ###
|
||||
"""# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.create_table('item',
|
||||
sa.Column('id', sa.Integer(), nullable=False),
|
||||
sa.Column('description', sa.String(length=100), nullable=True),
|
||||
|
@ -96,10 +96,10 @@ nullable=True))
|
|||
nullable=False)
|
||||
op.drop_index('pw_idx', table_name='user')
|
||||
op.drop_column('user', 'pw')
|
||||
### end Alembic commands ###""")
|
||||
# ### end Alembic commands ###""")
|
||||
|
||||
eq_(re.sub(r"u'", "'", template_args['downgrades']),
|
||||
"""### commands auto generated by Alembic - please adjust! ###
|
||||
"""# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.add_column('user', sa.Column('pw', sa.VARCHAR(length=50), \
|
||||
nullable=True))
|
||||
op.create_index('pw_idx', 'user', ['pw'], unique=False)
|
||||
|
@ -125,7 +125,7 @@ nullable=True))
|
|||
sa.ForeignKeyConstraint(['uid'], ['user.id'], )
|
||||
)
|
||||
op.drop_table('item')
|
||||
### end Alembic commands ###""")
|
||||
# ### end Alembic commands ###""")
|
||||
|
||||
def test_render_diffs_batch(self):
|
||||
"""test a full render in batch mode including indentation"""
|
||||
|
@ -135,7 +135,7 @@ nullable=True))
|
|||
autogenerate._render_migration_diffs(self.context, template_args)
|
||||
|
||||
eq_(re.sub(r"u'", "'", template_args['upgrades']),
|
||||
"""### commands auto generated by Alembic - please adjust! ###
|
||||
"""# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.create_table('item',
|
||||
sa.Column('id', sa.Integer(), nullable=False),
|
||||
sa.Column('description', sa.String(length=100), nullable=True),
|
||||
|
@ -169,10 +169,10 @@ nullable=True))
|
|||
batch_op.drop_index('pw_idx')
|
||||
batch_op.drop_column('pw')
|
||||
|
||||
### end Alembic commands ###""")
|
||||
# ### end Alembic commands ###""")
|
||||
|
||||
eq_(re.sub(r"u'", "'", template_args['downgrades']),
|
||||
"""### commands auto generated by Alembic - please adjust! ###
|
||||
"""# ### commands auto generated by Alembic - please adjust! ###
|
||||
with op.batch_alter_table('user', schema=None) as batch_op:
|
||||
batch_op.add_column(sa.Column('pw', sa.VARCHAR(length=50), nullable=True))
|
||||
batch_op.create_index('pw_idx', ['pw'], unique=False)
|
||||
|
@ -203,7 +203,7 @@ nullable=True))
|
|||
sa.ForeignKeyConstraint(['uid'], ['user.id'], )
|
||||
)
|
||||
op.drop_table('item')
|
||||
### end Alembic commands ###""")
|
||||
# ### end Alembic commands ###""")
|
||||
|
||||
def test_imports_maintined(self):
|
||||
template_args = {}
|
||||
|
@ -252,13 +252,13 @@ class AutogenerateDiffTestWSchema(ModelOne, AutogenTest, TestBase):
|
|||
autogenerate._render_migration_diffs(context, template_args)
|
||||
|
||||
eq_(re.sub(r"u'", "'", template_args['upgrades']),
|
||||
"""### commands auto generated by Alembic - please adjust! ###
|
||||
"""# ### commands auto generated by Alembic - please adjust! ###
|
||||
pass
|
||||
### end Alembic commands ###""")
|
||||
# ### end Alembic commands ###""")
|
||||
eq_(re.sub(r"u'", "'", template_args['downgrades']),
|
||||
"""### commands auto generated by Alembic - please adjust! ###
|
||||
"""# ### commands auto generated by Alembic - please adjust! ###
|
||||
pass
|
||||
### end Alembic commands ###""")
|
||||
# ### end Alembic commands ###""")
|
||||
|
||||
def test_render_diffs_extras(self):
|
||||
"""test a full render including indentation (include and schema)"""
|
||||
|
@ -271,7 +271,7 @@ class AutogenerateDiffTestWSchema(ModelOne, AutogenTest, TestBase):
|
|||
autogenerate._render_migration_diffs(self.context, template_args)
|
||||
|
||||
eq_(re.sub(r"u'", "'", template_args['upgrades']),
|
||||
"""### commands auto generated by Alembic - please adjust! ###
|
||||
"""# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.create_table('item',
|
||||
sa.Column('id', sa.Integer(), nullable=False),
|
||||
sa.Column('description', sa.String(length=100), nullable=True),
|
||||
|
@ -307,10 +307,10 @@ source_schema='%(schema)s', referent_schema='%(schema)s')
|
|||
schema='%(schema)s')
|
||||
op.drop_index('pw_idx', table_name='user', schema='test_schema')
|
||||
op.drop_column('user', 'pw', schema='%(schema)s')
|
||||
### end Alembic commands ###""" % {"schema": self.schema})
|
||||
# ### end Alembic commands ###""" % {"schema": self.schema})
|
||||
|
||||
eq_(re.sub(r"u'", "'", template_args['downgrades']),
|
||||
"""### commands auto generated by Alembic - please adjust! ###
|
||||
"""# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.add_column('user', sa.Column('pw', sa.VARCHAR(length=50), \
|
||||
autoincrement=False, nullable=True), schema='%(schema)s')
|
||||
op.create_index('pw_idx', 'user', ['pw'], unique=False, schema='%(schema)s')
|
||||
|
@ -341,5 +341,5 @@ name='extra_uid_fkey'),
|
|||
schema='%(schema)s'
|
||||
)
|
||||
op.drop_table('item', schema='%(schema)s')
|
||||
### end Alembic commands ###""" % {"schema": self.schema})
|
||||
# ### end Alembic commands ###""" % {"schema": self.schema})
|
||||
|
||||
|
|
|
@ -5,7 +5,8 @@ from sqlalchemy import MetaData, Column, Table, Integer, String, Text, \
|
|||
TypeDecorator, CheckConstraint, text, PrimaryKeyConstraint, \
|
||||
ForeignKeyConstraint, VARCHAR, DECIMAL, DateTime, BigInteger, BIGINT, \
|
||||
SmallInteger
|
||||
from sqlalchemy.types import NULLTYPE
|
||||
from sqlalchemy.dialects import sqlite
|
||||
from sqlalchemy.types import NULLTYPE, VARBINARY
|
||||
from sqlalchemy.engine.reflection import Inspector
|
||||
|
||||
from alembic.operations import ops
|
||||
|
@ -592,6 +593,26 @@ class CompareTypeSpecificityTest(TestBase):
|
|||
return impl.DefaultImpl(
|
||||
default.DefaultDialect(), None, False, True, None, {})
|
||||
|
||||
def test_typedec_to_nonstandard(self):
|
||||
|
||||
class PasswordType(TypeDecorator):
|
||||
impl = VARBINARY
|
||||
|
||||
def copy(self, **kw):
|
||||
return PasswordType(self.impl.length)
|
||||
|
||||
def load_dialect_impl(self, dialect):
|
||||
if dialect.name == 'default':
|
||||
impl = sqlite.NUMERIC(self.length)
|
||||
else:
|
||||
impl = VARBINARY(self.length)
|
||||
return dialect.type_descriptor(impl)
|
||||
|
||||
impl = self._fixture()
|
||||
impl.compare_type(
|
||||
Column('x', sqlite.NUMERIC(50)),
|
||||
Column('x', PasswordType(50)))
|
||||
|
||||
def test_string(self):
|
||||
t1 = String(30)
|
||||
t2 = String(40)
|
||||
|
|
|
@ -17,7 +17,7 @@ class AutogenerateForeignKeysTest(AutogenFixtureTest, TestBase):
|
|||
m1 = MetaData()
|
||||
m2 = MetaData()
|
||||
|
||||
Table('table', m1,
|
||||
Table('some_table', m1,
|
||||
Column('test', String(10), primary_key=True),
|
||||
mysql_engine='InnoDB')
|
||||
|
||||
|
@ -26,10 +26,10 @@ class AutogenerateForeignKeysTest(AutogenFixtureTest, TestBase):
|
|||
Column('name', String(50), nullable=False),
|
||||
Column('a1', String(10), server_default="x"),
|
||||
Column('test2', String(10)),
|
||||
ForeignKeyConstraint(['test2'], ['table.test']),
|
||||
ForeignKeyConstraint(['test2'], ['some_table.test']),
|
||||
mysql_engine='InnoDB')
|
||||
|
||||
Table('table', m2,
|
||||
Table('some_table', m2,
|
||||
Column('test', String(10), primary_key=True),
|
||||
mysql_engine='InnoDB')
|
||||
|
||||
|
@ -46,7 +46,7 @@ class AutogenerateForeignKeysTest(AutogenFixtureTest, TestBase):
|
|||
self._assert_fk_diff(
|
||||
diffs[0], "remove_fk",
|
||||
"user", ['test2'],
|
||||
'table', ['test'],
|
||||
'some_table', ['test'],
|
||||
conditional_name="servergenerated"
|
||||
)
|
||||
|
||||
|
@ -54,7 +54,7 @@ class AutogenerateForeignKeysTest(AutogenFixtureTest, TestBase):
|
|||
m1 = MetaData()
|
||||
m2 = MetaData()
|
||||
|
||||
Table('table', m1,
|
||||
Table('some_table', m1,
|
||||
Column('id', Integer, primary_key=True),
|
||||
Column('test', String(10)),
|
||||
mysql_engine='InnoDB')
|
||||
|
@ -66,7 +66,7 @@ class AutogenerateForeignKeysTest(AutogenFixtureTest, TestBase):
|
|||
Column('test2', String(10)),
|
||||
mysql_engine='InnoDB')
|
||||
|
||||
Table('table', m2,
|
||||
Table('some_table', m2,
|
||||
Column('id', Integer, primary_key=True),
|
||||
Column('test', String(10)),
|
||||
mysql_engine='InnoDB')
|
||||
|
@ -76,7 +76,7 @@ class AutogenerateForeignKeysTest(AutogenFixtureTest, TestBase):
|
|||
Column('name', String(50), nullable=False),
|
||||
Column('a1', String(10), server_default="x"),
|
||||
Column('test2', String(10)),
|
||||
ForeignKeyConstraint(['test2'], ['table.test']),
|
||||
ForeignKeyConstraint(['test2'], ['some_table.test']),
|
||||
mysql_engine='InnoDB')
|
||||
|
||||
diffs = self._fixture(m1, m2)
|
||||
|
@ -84,14 +84,14 @@ class AutogenerateForeignKeysTest(AutogenFixtureTest, TestBase):
|
|||
self._assert_fk_diff(
|
||||
diffs[0], "add_fk",
|
||||
"user", ["test2"],
|
||||
"table", ["test"]
|
||||
"some_table", ["test"]
|
||||
)
|
||||
|
||||
def test_no_change(self):
|
||||
m1 = MetaData()
|
||||
m2 = MetaData()
|
||||
|
||||
Table('table', m1,
|
||||
Table('some_table', m1,
|
||||
Column('id', Integer, primary_key=True),
|
||||
Column('test', String(10)),
|
||||
mysql_engine='InnoDB')
|
||||
|
@ -101,10 +101,10 @@ class AutogenerateForeignKeysTest(AutogenFixtureTest, TestBase):
|
|||
Column('name', String(50), nullable=False),
|
||||
Column('a1', String(10), server_default="x"),
|
||||
Column('test2', Integer),
|
||||
ForeignKeyConstraint(['test2'], ['table.id']),
|
||||
ForeignKeyConstraint(['test2'], ['some_table.id']),
|
||||
mysql_engine='InnoDB')
|
||||
|
||||
Table('table', m2,
|
||||
Table('some_table', m2,
|
||||
Column('id', Integer, primary_key=True),
|
||||
Column('test', String(10)),
|
||||
mysql_engine='InnoDB')
|
||||
|
@ -114,7 +114,7 @@ class AutogenerateForeignKeysTest(AutogenFixtureTest, TestBase):
|
|||
Column('name', String(50), nullable=False),
|
||||
Column('a1', String(10), server_default="x"),
|
||||
Column('test2', Integer),
|
||||
ForeignKeyConstraint(['test2'], ['table.id']),
|
||||
ForeignKeyConstraint(['test2'], ['some_table.id']),
|
||||
mysql_engine='InnoDB')
|
||||
|
||||
diffs = self._fixture(m1, m2)
|
||||
|
@ -125,7 +125,7 @@ class AutogenerateForeignKeysTest(AutogenFixtureTest, TestBase):
|
|||
m1 = MetaData()
|
||||
m2 = MetaData()
|
||||
|
||||
Table('table', m1,
|
||||
Table('some_table', m1,
|
||||
Column('id_1', String(10), primary_key=True),
|
||||
Column('id_2', String(10), primary_key=True),
|
||||
mysql_engine='InnoDB')
|
||||
|
@ -137,10 +137,10 @@ class AutogenerateForeignKeysTest(AutogenFixtureTest, TestBase):
|
|||
Column('other_id_1', String(10)),
|
||||
Column('other_id_2', String(10)),
|
||||
ForeignKeyConstraint(['other_id_1', 'other_id_2'],
|
||||
['table.id_1', 'table.id_2']),
|
||||
['some_table.id_1', 'some_table.id_2']),
|
||||
mysql_engine='InnoDB')
|
||||
|
||||
Table('table', m2,
|
||||
Table('some_table', m2,
|
||||
Column('id_1', String(10), primary_key=True),
|
||||
Column('id_2', String(10), primary_key=True),
|
||||
mysql_engine='InnoDB'
|
||||
|
@ -153,7 +153,7 @@ class AutogenerateForeignKeysTest(AutogenFixtureTest, TestBase):
|
|||
Column('other_id_1', String(10)),
|
||||
Column('other_id_2', String(10)),
|
||||
ForeignKeyConstraint(['other_id_1', 'other_id_2'],
|
||||
['table.id_1', 'table.id_2']),
|
||||
['some_table.id_1', 'some_table.id_2']),
|
||||
mysql_engine='InnoDB')
|
||||
|
||||
diffs = self._fixture(m1, m2)
|
||||
|
@ -164,7 +164,7 @@ class AutogenerateForeignKeysTest(AutogenFixtureTest, TestBase):
|
|||
m1 = MetaData()
|
||||
m2 = MetaData()
|
||||
|
||||
Table('table', m1,
|
||||
Table('some_table', m1,
|
||||
Column('id_1', String(10), primary_key=True),
|
||||
Column('id_2', String(10), primary_key=True),
|
||||
mysql_engine='InnoDB')
|
||||
|
@ -177,7 +177,7 @@ class AutogenerateForeignKeysTest(AutogenFixtureTest, TestBase):
|
|||
Column('other_id_2', String(10)),
|
||||
mysql_engine='InnoDB')
|
||||
|
||||
Table('table', m2,
|
||||
Table('some_table', m2,
|
||||
Column('id_1', String(10), primary_key=True),
|
||||
Column('id_2', String(10), primary_key=True),
|
||||
mysql_engine='InnoDB')
|
||||
|
@ -189,7 +189,7 @@ class AutogenerateForeignKeysTest(AutogenFixtureTest, TestBase):
|
|||
Column('other_id_1', String(10)),
|
||||
Column('other_id_2', String(10)),
|
||||
ForeignKeyConstraint(['other_id_1', 'other_id_2'],
|
||||
['table.id_1', 'table.id_2'],
|
||||
['some_table.id_1', 'some_table.id_2'],
|
||||
name='fk_test_name'),
|
||||
mysql_engine='InnoDB')
|
||||
|
||||
|
@ -198,15 +198,16 @@ class AutogenerateForeignKeysTest(AutogenFixtureTest, TestBase):
|
|||
self._assert_fk_diff(
|
||||
diffs[0], "add_fk",
|
||||
"user", ['other_id_1', 'other_id_2'],
|
||||
'table', ['id_1', 'id_2'],
|
||||
'some_table', ['id_1', 'id_2'],
|
||||
name="fk_test_name"
|
||||
)
|
||||
|
||||
@config.requirements.no_name_normalize
|
||||
def test_remove_composite_fk(self):
|
||||
m1 = MetaData()
|
||||
m2 = MetaData()
|
||||
|
||||
Table('table', m1,
|
||||
Table('some_table', m1,
|
||||
Column('id_1', String(10), primary_key=True),
|
||||
Column('id_2', String(10), primary_key=True),
|
||||
mysql_engine='InnoDB')
|
||||
|
@ -218,11 +219,11 @@ class AutogenerateForeignKeysTest(AutogenFixtureTest, TestBase):
|
|||
Column('other_id_1', String(10)),
|
||||
Column('other_id_2', String(10)),
|
||||
ForeignKeyConstraint(['other_id_1', 'other_id_2'],
|
||||
['table.id_1', 'table.id_2'],
|
||||
['some_table.id_1', 'some_table.id_2'],
|
||||
name='fk_test_name'),
|
||||
mysql_engine='InnoDB')
|
||||
|
||||
Table('table', m2,
|
||||
Table('some_table', m2,
|
||||
Column('id_1', String(10), primary_key=True),
|
||||
Column('id_2', String(10), primary_key=True),
|
||||
mysql_engine='InnoDB')
|
||||
|
@ -240,7 +241,7 @@ class AutogenerateForeignKeysTest(AutogenFixtureTest, TestBase):
|
|||
self._assert_fk_diff(
|
||||
diffs[0], "remove_fk",
|
||||
"user", ['other_id_1', 'other_id_2'],
|
||||
"table", ['id_1', 'id_2'],
|
||||
"some_table", ['id_1', 'id_2'],
|
||||
conditional_name="fk_test_name"
|
||||
)
|
||||
|
||||
|
@ -248,7 +249,7 @@ class AutogenerateForeignKeysTest(AutogenFixtureTest, TestBase):
|
|||
m1 = MetaData()
|
||||
m2 = MetaData()
|
||||
|
||||
Table('table', m1,
|
||||
Table('some_table', m1,
|
||||
Column('id_1', String(10), primary_key=True),
|
||||
Column('id_2', String(10), primary_key=True),
|
||||
mysql_engine='InnoDB')
|
||||
|
@ -259,7 +260,7 @@ class AutogenerateForeignKeysTest(AutogenFixtureTest, TestBase):
|
|||
Column('other_id_2', String(10)),
|
||||
mysql_engine='InnoDB')
|
||||
|
||||
Table('table', m2,
|
||||
Table('some_table', m2,
|
||||
Column('id_1', String(10), key='tid1', primary_key=True),
|
||||
Column('id_2', String(10), key='tid2', primary_key=True),
|
||||
mysql_engine='InnoDB')
|
||||
|
@ -269,7 +270,7 @@ class AutogenerateForeignKeysTest(AutogenFixtureTest, TestBase):
|
|||
Column('other_id_1', String(10), key='oid1'),
|
||||
Column('other_id_2', String(10), key='oid2'),
|
||||
ForeignKeyConstraint(['oid1', 'oid2'],
|
||||
['table.tid1', 'table.tid2'],
|
||||
['some_table.tid1', 'some_table.tid2'],
|
||||
name='fk_test_name'),
|
||||
mysql_engine='InnoDB')
|
||||
|
||||
|
@ -278,7 +279,7 @@ class AutogenerateForeignKeysTest(AutogenFixtureTest, TestBase):
|
|||
self._assert_fk_diff(
|
||||
diffs[0], "add_fk",
|
||||
"user", ['other_id_1', 'other_id_2'],
|
||||
'table', ['id_1', 'id_2'],
|
||||
'some_table', ['id_1', 'id_2'],
|
||||
name="fk_test_name"
|
||||
)
|
||||
|
||||
|
@ -286,7 +287,7 @@ class AutogenerateForeignKeysTest(AutogenFixtureTest, TestBase):
|
|||
m1 = MetaData()
|
||||
m2 = MetaData()
|
||||
|
||||
Table('table', m1,
|
||||
Table('some_table', m1,
|
||||
Column('id_1', String(10), primary_key=True),
|
||||
Column('id_2', String(10), primary_key=True),
|
||||
mysql_engine='InnoDB')
|
||||
|
@ -296,10 +297,10 @@ class AutogenerateForeignKeysTest(AutogenFixtureTest, TestBase):
|
|||
Column('other_id_1', String(10)),
|
||||
Column('other_id_2', String(10)),
|
||||
ForeignKeyConstraint(['other_id_1', 'other_id_2'],
|
||||
['table.id_1', 'table.id_2']),
|
||||
['some_table.id_1', 'some_table.id_2']),
|
||||
mysql_engine='InnoDB')
|
||||
|
||||
Table('table', m2,
|
||||
Table('some_table', m2,
|
||||
Column('id_1', String(10), key='tid1', primary_key=True),
|
||||
Column('id_2', String(10), key='tid2', primary_key=True),
|
||||
mysql_engine='InnoDB')
|
||||
|
@ -309,7 +310,7 @@ class AutogenerateForeignKeysTest(AutogenFixtureTest, TestBase):
|
|||
Column('other_id_1', String(10), key='oid1'),
|
||||
Column('other_id_2', String(10), key='oid2'),
|
||||
ForeignKeyConstraint(['oid1', 'oid2'],
|
||||
['table.tid1', 'table.tid2']),
|
||||
['some_table.tid1', 'some_table.tid2']),
|
||||
mysql_engine='InnoDB')
|
||||
|
||||
diffs = self._fixture(m1, m2)
|
||||
|
@ -321,6 +322,7 @@ class IncludeHooksTest(AutogenFixtureTest, TestBase):
|
|||
__backend__ = True
|
||||
__requires__ = 'fk_names',
|
||||
|
||||
@config.requirements.no_name_normalize
|
||||
def test_remove_connection_fk(self):
|
||||
m1 = MetaData()
|
||||
m2 = MetaData()
|
||||
|
@ -399,6 +401,7 @@ class IncludeHooksTest(AutogenFixtureTest, TestBase):
|
|||
)
|
||||
eq_(len(diffs), 1)
|
||||
|
||||
@config.requirements.no_name_normalize
|
||||
def test_change_fk(self):
|
||||
m1 = MetaData()
|
||||
m2 = MetaData()
|
||||
|
@ -473,13 +476,13 @@ class IncludeHooksTest(AutogenFixtureTest, TestBase):
|
|||
|
||||
class AutogenerateFKOptionsTest(AutogenFixtureTest, TestBase):
|
||||
__backend__ = True
|
||||
__requires__ = ('sqlalchemy_09', )
|
||||
__requires__ = ('sqlalchemy_09', 'flexible_fk_cascades')
|
||||
|
||||
def _fk_opts_fixture(self, old_opts, new_opts):
|
||||
m1 = MetaData()
|
||||
m2 = MetaData()
|
||||
|
||||
Table('table', m1,
|
||||
Table('some_table', m1,
|
||||
Column('id', Integer, primary_key=True),
|
||||
Column('test', String(10)),
|
||||
mysql_engine='InnoDB')
|
||||
|
@ -488,10 +491,10 @@ class AutogenerateFKOptionsTest(AutogenFixtureTest, TestBase):
|
|||
Column('id', Integer, primary_key=True),
|
||||
Column('name', String(50), nullable=False),
|
||||
Column('tid', Integer),
|
||||
ForeignKeyConstraint(['tid'], ['table.id'], **old_opts),
|
||||
ForeignKeyConstraint(['tid'], ['some_table.id'], **old_opts),
|
||||
mysql_engine='InnoDB')
|
||||
|
||||
Table('table', m2,
|
||||
Table('some_table', m2,
|
||||
Column('id', Integer, primary_key=True),
|
||||
Column('test', String(10)),
|
||||
mysql_engine='InnoDB')
|
||||
|
@ -500,7 +503,7 @@ class AutogenerateFKOptionsTest(AutogenFixtureTest, TestBase):
|
|||
Column('id', Integer, primary_key=True),
|
||||
Column('name', String(50), nullable=False),
|
||||
Column('tid', Integer),
|
||||
ForeignKeyConstraint(['tid'], ['table.id'], **new_opts),
|
||||
ForeignKeyConstraint(['tid'], ['some_table.id'], **new_opts),
|
||||
mysql_engine='InnoDB')
|
||||
|
||||
return self._fixture(m1, m2)
|
||||
|
@ -526,7 +529,7 @@ class AutogenerateFKOptionsTest(AutogenFixtureTest, TestBase):
|
|||
self._assert_fk_diff(
|
||||
diffs[0], "remove_fk",
|
||||
"user", ["tid"],
|
||||
"table", ["id"],
|
||||
"some_table", ["id"],
|
||||
ondelete=None,
|
||||
conditional_name="servergenerated"
|
||||
)
|
||||
|
@ -534,7 +537,7 @@ class AutogenerateFKOptionsTest(AutogenFixtureTest, TestBase):
|
|||
self._assert_fk_diff(
|
||||
diffs[1], "add_fk",
|
||||
"user", ["tid"],
|
||||
"table", ["id"],
|
||||
"some_table", ["id"],
|
||||
ondelete="cascade"
|
||||
)
|
||||
else:
|
||||
|
@ -549,7 +552,7 @@ class AutogenerateFKOptionsTest(AutogenFixtureTest, TestBase):
|
|||
self._assert_fk_diff(
|
||||
diffs[0], "remove_fk",
|
||||
"user", ["tid"],
|
||||
"table", ["id"],
|
||||
"some_table", ["id"],
|
||||
ondelete="CASCADE",
|
||||
conditional_name="servergenerated"
|
||||
)
|
||||
|
@ -557,7 +560,7 @@ class AutogenerateFKOptionsTest(AutogenFixtureTest, TestBase):
|
|||
self._assert_fk_diff(
|
||||
diffs[1], "add_fk",
|
||||
"user", ["tid"],
|
||||
"table", ["id"],
|
||||
"some_table", ["id"],
|
||||
ondelete=None
|
||||
)
|
||||
else:
|
||||
|
@ -579,7 +582,7 @@ class AutogenerateFKOptionsTest(AutogenFixtureTest, TestBase):
|
|||
self._assert_fk_diff(
|
||||
diffs[0], "remove_fk",
|
||||
"user", ["tid"],
|
||||
"table", ["id"],
|
||||
"some_table", ["id"],
|
||||
onupdate=None,
|
||||
conditional_name="servergenerated"
|
||||
)
|
||||
|
@ -587,7 +590,7 @@ class AutogenerateFKOptionsTest(AutogenFixtureTest, TestBase):
|
|||
self._assert_fk_diff(
|
||||
diffs[1], "add_fk",
|
||||
"user", ["tid"],
|
||||
"table", ["id"],
|
||||
"some_table", ["id"],
|
||||
onupdate="cascade"
|
||||
)
|
||||
else:
|
||||
|
@ -602,7 +605,7 @@ class AutogenerateFKOptionsTest(AutogenFixtureTest, TestBase):
|
|||
self._assert_fk_diff(
|
||||
diffs[0], "remove_fk",
|
||||
"user", ["tid"],
|
||||
"table", ["id"],
|
||||
"some_table", ["id"],
|
||||
onupdate="CASCADE",
|
||||
conditional_name="servergenerated"
|
||||
)
|
||||
|
@ -610,7 +613,7 @@ class AutogenerateFKOptionsTest(AutogenFixtureTest, TestBase):
|
|||
self._assert_fk_diff(
|
||||
diffs[1], "add_fk",
|
||||
"user", ["tid"],
|
||||
"table", ["id"],
|
||||
"some_table", ["id"],
|
||||
onupdate=None
|
||||
)
|
||||
else:
|
||||
|
@ -667,7 +670,7 @@ class AutogenerateFKOptionsTest(AutogenFixtureTest, TestBase):
|
|||
self._assert_fk_diff(
|
||||
diffs[0], "remove_fk",
|
||||
"user", ["tid"],
|
||||
"table", ["id"],
|
||||
"some_table", ["id"],
|
||||
onupdate=None,
|
||||
ondelete=mock.ANY, # MySQL reports None, PG reports RESTRICT
|
||||
conditional_name="servergenerated"
|
||||
|
@ -676,7 +679,7 @@ class AutogenerateFKOptionsTest(AutogenFixtureTest, TestBase):
|
|||
self._assert_fk_diff(
|
||||
diffs[1], "add_fk",
|
||||
"user", ["tid"],
|
||||
"table", ["id"],
|
||||
"some_table", ["id"],
|
||||
onupdate=None,
|
||||
ondelete="cascade"
|
||||
)
|
||||
|
@ -695,7 +698,7 @@ class AutogenerateFKOptionsTest(AutogenFixtureTest, TestBase):
|
|||
self._assert_fk_diff(
|
||||
diffs[0], "remove_fk",
|
||||
"user", ["tid"],
|
||||
"table", ["id"],
|
||||
"some_table", ["id"],
|
||||
onupdate=mock.ANY, # MySQL reports None, PG reports RESTRICT
|
||||
ondelete=None,
|
||||
conditional_name="servergenerated"
|
||||
|
@ -704,7 +707,7 @@ class AutogenerateFKOptionsTest(AutogenFixtureTest, TestBase):
|
|||
self._assert_fk_diff(
|
||||
diffs[1], "add_fk",
|
||||
"user", ["tid"],
|
||||
"table", ["id"],
|
||||
"some_table", ["id"],
|
||||
onupdate="cascade",
|
||||
ondelete=None
|
||||
)
|
||||
|
@ -721,7 +724,7 @@ class AutogenerateFKOptionsTest(AutogenFixtureTest, TestBase):
|
|||
self._assert_fk_diff(
|
||||
diffs[0], "remove_fk",
|
||||
"user", ["tid"],
|
||||
"table", ["id"],
|
||||
"some_table", ["id"],
|
||||
onupdate="CASCADE",
|
||||
ondelete="SET NULL",
|
||||
conditional_name="servergenerated"
|
||||
|
@ -730,7 +733,7 @@ class AutogenerateFKOptionsTest(AutogenFixtureTest, TestBase):
|
|||
self._assert_fk_diff(
|
||||
diffs[1], "add_fk",
|
||||
"user", ["tid"],
|
||||
"table", ["id"],
|
||||
"some_table", ["id"],
|
||||
onupdate="RESTRICT",
|
||||
ondelete="RESTRICT"
|
||||
)
|
||||
|
@ -746,7 +749,7 @@ class AutogenerateFKOptionsTest(AutogenFixtureTest, TestBase):
|
|||
self._assert_fk_diff(
|
||||
diffs[0], "remove_fk",
|
||||
"user", ["tid"],
|
||||
"table", ["id"],
|
||||
"some_table", ["id"],
|
||||
initially=None,
|
||||
conditional_name="servergenerated"
|
||||
)
|
||||
|
@ -754,7 +757,7 @@ class AutogenerateFKOptionsTest(AutogenFixtureTest, TestBase):
|
|||
self._assert_fk_diff(
|
||||
diffs[1], "add_fk",
|
||||
"user", ["tid"],
|
||||
"table", ["id"],
|
||||
"some_table", ["id"],
|
||||
initially="deferred"
|
||||
)
|
||||
|
||||
|
@ -767,7 +770,7 @@ class AutogenerateFKOptionsTest(AutogenFixtureTest, TestBase):
|
|||
self._assert_fk_diff(
|
||||
diffs[0], "remove_fk",
|
||||
"user", ["tid"],
|
||||
"table", ["id"],
|
||||
"some_table", ["id"],
|
||||
initially="DEFERRED",
|
||||
deferrable=True,
|
||||
conditional_name="servergenerated"
|
||||
|
@ -776,7 +779,7 @@ class AutogenerateFKOptionsTest(AutogenFixtureTest, TestBase):
|
|||
self._assert_fk_diff(
|
||||
diffs[1], "add_fk",
|
||||
"user", ["tid"],
|
||||
"table", ["id"],
|
||||
"some_table", ["id"],
|
||||
initially=None
|
||||
)
|
||||
|
||||
|
@ -790,7 +793,7 @@ class AutogenerateFKOptionsTest(AutogenFixtureTest, TestBase):
|
|||
self._assert_fk_diff(
|
||||
diffs[0], "remove_fk",
|
||||
"user", ["tid"],
|
||||
"table", ["id"],
|
||||
"some_table", ["id"],
|
||||
initially=None,
|
||||
conditional_name="servergenerated"
|
||||
)
|
||||
|
@ -798,7 +801,7 @@ class AutogenerateFKOptionsTest(AutogenFixtureTest, TestBase):
|
|||
self._assert_fk_diff(
|
||||
diffs[1], "add_fk",
|
||||
"user", ["tid"],
|
||||
"table", ["id"],
|
||||
"some_table", ["id"],
|
||||
initially="immediate",
|
||||
deferrable=True
|
||||
)
|
||||
|
@ -813,7 +816,7 @@ class AutogenerateFKOptionsTest(AutogenFixtureTest, TestBase):
|
|||
self._assert_fk_diff(
|
||||
diffs[0], "remove_fk",
|
||||
"user", ["tid"],
|
||||
"table", ["id"],
|
||||
"some_table", ["id"],
|
||||
initially=None, # immediate is the default
|
||||
deferrable=True,
|
||||
conditional_name="servergenerated"
|
||||
|
@ -822,7 +825,7 @@ class AutogenerateFKOptionsTest(AutogenFixtureTest, TestBase):
|
|||
self._assert_fk_diff(
|
||||
diffs[1], "add_fk",
|
||||
"user", ["tid"],
|
||||
"table", ["id"],
|
||||
"some_table", ["id"],
|
||||
initially=None,
|
||||
deferrable=None
|
||||
)
|
||||
|
@ -866,7 +869,7 @@ class AutogenerateFKOptionsTest(AutogenFixtureTest, TestBase):
|
|||
self._assert_fk_diff(
|
||||
diffs[0], "remove_fk",
|
||||
"user", ["tid"],
|
||||
"table", ["id"],
|
||||
"some_table", ["id"],
|
||||
deferrable=None,
|
||||
conditional_name="servergenerated"
|
||||
)
|
||||
|
@ -874,7 +877,7 @@ class AutogenerateFKOptionsTest(AutogenFixtureTest, TestBase):
|
|||
self._assert_fk_diff(
|
||||
diffs[1], "add_fk",
|
||||
"user", ["tid"],
|
||||
"table", ["id"],
|
||||
"some_table", ["id"],
|
||||
deferrable=True
|
||||
)
|
||||
|
||||
|
@ -887,7 +890,7 @@ class AutogenerateFKOptionsTest(AutogenFixtureTest, TestBase):
|
|||
self._assert_fk_diff(
|
||||
diffs[0], "remove_fk",
|
||||
"user", ["tid"],
|
||||
"table", ["id"],
|
||||
"some_table", ["id"],
|
||||
deferrable=True,
|
||||
conditional_name="servergenerated"
|
||||
)
|
||||
|
@ -895,6 +898,6 @@ class AutogenerateFKOptionsTest(AutogenFixtureTest, TestBase):
|
|||
self._assert_fk_diff(
|
||||
diffs[1], "add_fk",
|
||||
"user", ["tid"],
|
||||
"table", ["id"],
|
||||
"some_table", ["id"],
|
||||
deferrable=None
|
||||
)
|
||||
|
|
|
@ -640,7 +640,7 @@ class PGUniqueIndexTest(AutogenerateUniqueIndexTest):
|
|||
eq_(diffs[0][1].name, "uq_name")
|
||||
eq_(len(diffs), 1)
|
||||
|
||||
def test_functional_ix(self):
|
||||
def test_functional_ix_one(self):
|
||||
m1 = MetaData()
|
||||
m2 = MetaData()
|
||||
|
||||
|
@ -665,6 +665,37 @@ class PGUniqueIndexTest(AutogenerateUniqueIndexTest):
|
|||
diffs = self._fixture(m1, m2)
|
||||
eq_(diffs, [])
|
||||
|
||||
def test_functional_ix_two(self):
|
||||
m1 = MetaData()
|
||||
m2 = MetaData()
|
||||
|
||||
t1 = Table(
|
||||
'foo', m1,
|
||||
Column('id', Integer, primary_key=True),
|
||||
Column('email', String(50)),
|
||||
Column('name', String(50))
|
||||
)
|
||||
Index(
|
||||
"email_idx",
|
||||
func.coalesce(t1.c.email, t1.c.name).desc(), unique=True)
|
||||
|
||||
t2 = Table(
|
||||
'foo', m2,
|
||||
Column('id', Integer, primary_key=True),
|
||||
Column('email', String(50)),
|
||||
Column('name', String(50))
|
||||
)
|
||||
Index(
|
||||
"email_idx",
|
||||
func.coalesce(t2.c.email, t2.c.name).desc(), unique=True)
|
||||
|
||||
with assertions.expect_warnings(
|
||||
"Skipped unsupported reflection",
|
||||
"autogenerate skipping functional index"
|
||||
):
|
||||
diffs = self._fixture(m1, m2)
|
||||
eq_(diffs, [])
|
||||
|
||||
|
||||
class MySQLUniqueIndexTest(AutogenerateUniqueIndexTest):
|
||||
reports_unnamed_constraints = True
|
||||
|
@ -681,6 +712,12 @@ class MySQLUniqueIndexTest(AutogenerateUniqueIndexTest):
|
|||
assert False, "unexpected success"
|
||||
|
||||
|
||||
class OracleUniqueIndexTest(AutogenerateUniqueIndexTest):
|
||||
reports_unnamed_constraints = True
|
||||
reports_unique_constraints_as_indexes = True
|
||||
__only_on__ = "oracle"
|
||||
|
||||
|
||||
class NoUqReflectionIndexTest(NoUqReflection, AutogenerateUniqueIndexTest):
|
||||
reports_unique_constraints = False
|
||||
__only_on__ = 'sqlite'
|
||||
|
|
|
@ -1674,7 +1674,7 @@ class RenderNamingConventionTest(TestBase):
|
|||
|
||||
eq_(
|
||||
autogenerate.render_python_code(uo, render_as_batch=True),
|
||||
"### commands auto generated by Alembic - please adjust! ###\n"
|
||||
"# ### commands auto generated by Alembic - please adjust! ###\n"
|
||||
" op.create_table('sometable',\n"
|
||||
" sa.Column('x', sa.Integer(), nullable=True),\n"
|
||||
" sa.Column('y', sa.Integer(), nullable=True)\n"
|
||||
|
@ -1683,5 +1683,5 @@ class RenderNamingConventionTest(TestBase):
|
|||
"as batch_op:\n"
|
||||
" batch_op.create_index("
|
||||
"'ix1', ['x', 'y'], unique=False)\n\n"
|
||||
" ### end Alembic commands ###"
|
||||
" # ### end Alembic commands ###"
|
||||
)
|
||||
|
|
|
@ -13,9 +13,9 @@ from alembic.runtime.migration import MigrationContext
|
|||
|
||||
from sqlalchemy import Integer, Table, Column, String, MetaData, ForeignKey, \
|
||||
UniqueConstraint, ForeignKeyConstraint, Index, Boolean, CheckConstraint, \
|
||||
Enum
|
||||
Enum, DateTime, PrimaryKeyConstraint
|
||||
from sqlalchemy.engine.reflection import Inspector
|
||||
from sqlalchemy.sql import column, text
|
||||
from sqlalchemy.sql import column, text, select
|
||||
from sqlalchemy.schema import CreateTable, CreateIndex
|
||||
from sqlalchemy import exc
|
||||
|
||||
|
@ -58,6 +58,17 @@ class BatchApplyTest(TestBase):
|
|||
)
|
||||
return ApplyBatchImpl(t, table_args, table_kwargs, False)
|
||||
|
||||
def _pk_fixture(self):
|
||||
m = MetaData()
|
||||
t = Table(
|
||||
'tname', m,
|
||||
Column('id', Integer),
|
||||
Column('x', String()),
|
||||
Column('y', Integer),
|
||||
PrimaryKeyConstraint('id', name="mypk")
|
||||
)
|
||||
return ApplyBatchImpl(t, (), {}, False)
|
||||
|
||||
def _literal_ck_fixture(
|
||||
self, copy_from=None, table_args=(), table_kwargs={}):
|
||||
m = MetaData()
|
||||
|
@ -215,6 +226,7 @@ class BatchApplyTest(TestBase):
|
|||
impl.new_table.c[name].name
|
||||
for name in colnames
|
||||
if name in impl.table.c])
|
||||
|
||||
args['tname_colnames'] = ", ".join(
|
||||
"CAST(%(schema)stname.%(name)s AS %(type)s) AS anon_1" % {
|
||||
'schema': args['schema'],
|
||||
|
@ -243,9 +255,9 @@ class BatchApplyTest(TestBase):
|
|||
|
||||
def test_change_type(self):
|
||||
impl = self._simple_fixture()
|
||||
impl.alter_column('tname', 'x', type_=Integer)
|
||||
impl.alter_column('tname', 'x', type_=String)
|
||||
new_table = self._assert_impl(impl)
|
||||
assert new_table.c.x.type._type_affinity is Integer
|
||||
assert new_table.c.x.type._type_affinity is String
|
||||
|
||||
def test_rename_col(self):
|
||||
impl = self._simple_fixture()
|
||||
|
@ -533,6 +545,14 @@ class BatchApplyTest(TestBase):
|
|||
dialect='mysql'
|
||||
)
|
||||
|
||||
def test_drop_pk(self):
|
||||
impl = self._pk_fixture()
|
||||
pk = self.op.schema_obj.primary_key_constraint("mypk", "tname", ["id"])
|
||||
impl.drop_constraint(pk)
|
||||
new_table = self._assert_impl(impl)
|
||||
assert not new_table.c.id.primary_key
|
||||
assert not len(new_table.primary_key)
|
||||
|
||||
|
||||
class BatchAPITest(TestBase):
|
||||
__requires__ = ('sqlalchemy_08', )
|
||||
|
@ -751,7 +771,6 @@ class CopyFromTest(TestBase):
|
|||
with self.op.batch_alter_table(
|
||||
"foo", copy_from=self.table) as batch_op:
|
||||
batch_op.alter_column('data', type_=Integer)
|
||||
|
||||
context.assert_(
|
||||
'CREATE TABLE _alembic_batch_temp (id INTEGER NOT NULL, '
|
||||
'data INTEGER, x INTEGER, PRIMARY KEY (id))',
|
||||
|
@ -889,7 +908,7 @@ class CopyFromTest(TestBase):
|
|||
'CREATE TABLE _alembic_batch_temp (id INTEGER NOT NULL, '
|
||||
'data VARCHAR, x INTEGER, PRIMARY KEY (id))',
|
||||
'INSERT INTO _alembic_batch_temp (id, data, x) SELECT foo.id, '
|
||||
'CAST(foo.data AS VARCHAR) AS anon_1, foo.x FROM foo',
|
||||
'foo.data, foo.x FROM foo',
|
||||
'DROP TABLE foo',
|
||||
'ALTER TABLE _alembic_batch_temp RENAME TO foo'
|
||||
)
|
||||
|
@ -970,6 +989,14 @@ class BatchRoundTripTest(TestBase):
|
|||
)
|
||||
t.create(self.conn)
|
||||
|
||||
def _timestamp_fixture(self):
|
||||
t = Table(
|
||||
'hasts', self.metadata,
|
||||
Column('x', DateTime()),
|
||||
)
|
||||
t.create(self.conn)
|
||||
return t
|
||||
|
||||
def _int_to_boolean_fixture(self):
|
||||
t = Table(
|
||||
'hasbool', self.metadata,
|
||||
|
@ -993,6 +1020,23 @@ class BatchRoundTripTest(TestBase):
|
|||
[Integer]
|
||||
)
|
||||
|
||||
def test_no_net_change_timestamp(self):
|
||||
t = self._timestamp_fixture()
|
||||
|
||||
import datetime
|
||||
self.conn.execute(
|
||||
t.insert(),
|
||||
{"x": datetime.datetime(2012, 5, 18, 15, 32, 5)}
|
||||
)
|
||||
|
||||
with self.op.batch_alter_table("hasts") as batch_op:
|
||||
batch_op.alter_column("x", type_=DateTime())
|
||||
|
||||
eq_(
|
||||
self.conn.execute(select([t.c.x])).fetchall(),
|
||||
[(datetime.datetime(2012, 5, 18, 15, 32, 5),)]
|
||||
)
|
||||
|
||||
def test_drop_col_schematype(self):
|
||||
self._boolean_fixture()
|
||||
with self.op.batch_alter_table(
|
||||
|
|
|
@ -5,10 +5,11 @@ from alembic.testing.fixtures import TestBase, capture_context_buffer
|
|||
from alembic.testing.env import staging_env, _sqlite_testing_config, \
|
||||
three_rev_fixture, clear_staging_env, _no_sql_testing_config, \
|
||||
_sqlite_file_db, write_script, env_file_fixture
|
||||
from alembic.testing import eq_, assert_raises_message, mock
|
||||
from alembic.testing import eq_, assert_raises_message, mock, assert_raises
|
||||
from alembic import util
|
||||
from contextlib import contextmanager
|
||||
import re
|
||||
from sqlalchemy import exc as sqla_exc
|
||||
|
||||
|
||||
class _BufMixin(object):
|
||||
|
@ -163,7 +164,7 @@ class RevisionTest(TestBase):
|
|||
def tearDown(self):
|
||||
clear_staging_env()
|
||||
|
||||
def _env_fixture(self):
|
||||
def _env_fixture(self, version_table_pk=True):
|
||||
env_file_fixture("""
|
||||
|
||||
from sqlalchemy import MetaData, engine_from_config
|
||||
|
@ -175,7 +176,10 @@ engine = engine_from_config(
|
|||
|
||||
connection = engine.connect()
|
||||
|
||||
context.configure(connection=connection, target_metadata=target_metadata)
|
||||
context.configure(
|
||||
connection=connection, target_metadata=target_metadata,
|
||||
version_table_pk=%r
|
||||
)
|
||||
|
||||
try:
|
||||
with context.begin_transaction():
|
||||
|
@ -183,7 +187,7 @@ try:
|
|||
finally:
|
||||
connection.close()
|
||||
|
||||
""")
|
||||
""" % (version_table_pk, ))
|
||||
|
||||
def test_create_rev_plain_db_not_up_to_date(self):
|
||||
self._env_fixture()
|
||||
|
@ -249,12 +253,24 @@ finally:
|
|||
command.revision, self.cfg, autogenerate=True
|
||||
)
|
||||
|
||||
def test_err_correctly_raised_on_dupe_rows(self):
|
||||
def test_pk_constraint_normally_prevents_dupe_rows(self):
|
||||
self._env_fixture()
|
||||
command.revision(self.cfg)
|
||||
r2 = command.revision(self.cfg)
|
||||
db = _sqlite_file_db()
|
||||
command.upgrade(self.cfg, "head")
|
||||
assert_raises(
|
||||
sqla_exc.IntegrityError,
|
||||
db.execute,
|
||||
"insert into alembic_version values ('%s')" % r2.revision
|
||||
)
|
||||
|
||||
def test_err_correctly_raised_on_dupe_rows_no_pk(self):
|
||||
self._env_fixture(version_table_pk=False)
|
||||
command.revision(self.cfg)
|
||||
r2 = command.revision(self.cfg)
|
||||
db = _sqlite_file_db()
|
||||
command.upgrade(self.cfg, "head")
|
||||
db.execute("insert into alembic_version values ('%s')" % r2.revision)
|
||||
assert_raises_message(
|
||||
util.CommandError,
|
||||
|
@ -434,6 +450,24 @@ class UpgradeDowngradeStampTest(TestBase):
|
|||
assert "DROP STEP 2" in buf.getvalue()
|
||||
assert "DROP STEP 1" not in buf.getvalue()
|
||||
|
||||
def test_none_to_head_sql(self):
|
||||
with capture_context_buffer() as buf:
|
||||
command.upgrade(self.cfg, "head", sql=True)
|
||||
assert "CREATE TABLE alembic_version" in buf.getvalue()
|
||||
assert "UPDATE alembic_version" in buf.getvalue()
|
||||
assert "CREATE STEP 1" in buf.getvalue()
|
||||
assert "CREATE STEP 2" in buf.getvalue()
|
||||
assert "CREATE STEP 3" in buf.getvalue()
|
||||
|
||||
def test_base_to_head_sql(self):
|
||||
with capture_context_buffer() as buf:
|
||||
command.upgrade(self.cfg, "base:head", sql=True)
|
||||
assert "CREATE TABLE alembic_version" in buf.getvalue()
|
||||
assert "UPDATE alembic_version" in buf.getvalue()
|
||||
assert "CREATE STEP 1" in buf.getvalue()
|
||||
assert "CREATE STEP 2" in buf.getvalue()
|
||||
assert "CREATE STEP 3" in buf.getvalue()
|
||||
|
||||
def test_sql_stamp_from_rev(self):
|
||||
with capture_context_buffer() as buf:
|
||||
command.stamp(self.cfg, "%s:head" % self.a, sql=True)
|
||||
|
|
|
@ -90,11 +90,13 @@ from alembic import op
|
|||
from sqlalchemy.dialects.postgresql import ENUM
|
||||
from sqlalchemy import Column
|
||||
|
||||
|
||||
def upgrade():
|
||||
op.create_table("sometable",
|
||||
Column("data", ENUM("one", "two", "three", name="pgenum"))
|
||||
)
|
||||
|
||||
|
||||
def downgrade():
|
||||
op.drop_table("sometable")
|
||||
""" % self.rid)
|
||||
|
@ -108,6 +110,7 @@ from alembic import op
|
|||
from sqlalchemy.dialects.postgresql import ENUM
|
||||
from sqlalchemy import Column
|
||||
|
||||
|
||||
def upgrade():
|
||||
enum = ENUM("one", "two", "three", name="pgenum", create_type=False)
|
||||
enum.create(op.get_bind(), checkfirst=False)
|
||||
|
@ -115,6 +118,7 @@ def upgrade():
|
|||
Column("data", enum)
|
||||
)
|
||||
|
||||
|
||||
def downgrade():
|
||||
op.drop_table("sometable")
|
||||
ENUM(name="pgenum").drop(op.get_bind(), checkfirst=False)
|
||||
|
|
|
@ -47,9 +47,11 @@ class ApplyVersionsFunctionalTest(TestBase):
|
|||
|
||||
from alembic import op
|
||||
|
||||
|
||||
def upgrade():
|
||||
op.execute("CREATE TABLE foo(id integer)")
|
||||
|
||||
|
||||
def downgrade():
|
||||
op.execute("DROP TABLE foo")
|
||||
|
||||
|
@ -62,9 +64,11 @@ class ApplyVersionsFunctionalTest(TestBase):
|
|||
|
||||
from alembic import op
|
||||
|
||||
|
||||
def upgrade():
|
||||
op.execute("CREATE TABLE bar(id integer)")
|
||||
|
||||
|
||||
def downgrade():
|
||||
op.execute("DROP TABLE bar")
|
||||
|
||||
|
@ -77,9 +81,11 @@ class ApplyVersionsFunctionalTest(TestBase):
|
|||
|
||||
from alembic import op
|
||||
|
||||
|
||||
def upgrade():
|
||||
op.execute("CREATE TABLE bat(id integer)")
|
||||
|
||||
|
||||
def downgrade():
|
||||
op.execute("DROP TABLE bat")
|
||||
|
||||
|
@ -221,9 +227,11 @@ class VersionNameTemplateTest(TestBase):
|
|||
|
||||
from alembic import op
|
||||
|
||||
|
||||
def upgrade():
|
||||
op.execute("CREATE TABLE foo(id integer)")
|
||||
|
||||
|
||||
def downgrade():
|
||||
op.execute("DROP TABLE foo")
|
||||
|
||||
|
@ -244,9 +252,11 @@ class VersionNameTemplateTest(TestBase):
|
|||
|
||||
from alembic import op
|
||||
|
||||
|
||||
def upgrade():
|
||||
op.execute("CREATE TABLE foo(id integer)")
|
||||
|
||||
|
||||
def downgrade():
|
||||
op.execute("DROP TABLE foo")
|
||||
|
||||
|
@ -270,11 +280,14 @@ down_revision = None
|
|||
|
||||
from alembic import op
|
||||
|
||||
|
||||
def upgrade():
|
||||
op.execute("CREATE TABLE foo(id integer)")
|
||||
|
||||
|
||||
def downgrade():
|
||||
op.execute("DROP TABLE foo")
|
||||
|
||||
""")
|
||||
pyc_path = util.pyc_file_from_path(path)
|
||||
if os.access(pyc_path, os.F_OK):
|
||||
|
@ -288,7 +301,7 @@ def downgrade():
|
|||
Script._from_path, script, path)
|
||||
|
||||
|
||||
class IgnoreInitTest(TestBase):
|
||||
class IgnoreFilesTest(TestBase):
|
||||
sourceless = False
|
||||
|
||||
def setUp(self):
|
||||
|
@ -299,12 +312,11 @@ class IgnoreInitTest(TestBase):
|
|||
def tearDown(self):
|
||||
clear_staging_env()
|
||||
|
||||
def _test_ignore_init_py(self, ext):
|
||||
"""test that __init__.py is ignored."""
|
||||
def _test_ignore_file_py(self, fname):
|
||||
|
||||
command.revision(self.cfg, message="some rev")
|
||||
script = ScriptDirectory.from_config(self.cfg)
|
||||
path = os.path.join(script.versions, "__init__.%s" % ext)
|
||||
path = os.path.join(script.versions, fname)
|
||||
with open(path, 'w') as f:
|
||||
f.write(
|
||||
"crap, crap -> crap"
|
||||
|
@ -313,20 +325,42 @@ class IgnoreInitTest(TestBase):
|
|||
|
||||
script.get_revision('head')
|
||||
|
||||
def test_ignore_py(self):
|
||||
def _test_ignore_init_py(self, ext):
|
||||
"""test that __init__.py is ignored."""
|
||||
|
||||
self._test_ignore_file_py("__init__.%s" % ext)
|
||||
|
||||
def _test_ignore_dot_hash_py(self, ext):
|
||||
"""test that .#test.py is ignored."""
|
||||
|
||||
self._test_ignore_file_py(".#test.%s" % ext)
|
||||
|
||||
def test_ignore_init_py(self):
|
||||
self._test_ignore_init_py("py")
|
||||
|
||||
def test_ignore_pyc(self):
|
||||
def test_ignore_init_pyc(self):
|
||||
self._test_ignore_init_py("pyc")
|
||||
|
||||
def test_ignore_pyx(self):
|
||||
def test_ignore_init_pyx(self):
|
||||
self._test_ignore_init_py("pyx")
|
||||
|
||||
def test_ignore_pyo(self):
|
||||
def test_ignore_init_pyo(self):
|
||||
self._test_ignore_init_py("pyo")
|
||||
|
||||
def test_ignore_dot_hash_py(self):
|
||||
self._test_ignore_dot_hash_py("py")
|
||||
|
||||
class SourcelessIgnoreInitTest(IgnoreInitTest):
|
||||
def test_ignore_dot_hash_pyc(self):
|
||||
self._test_ignore_dot_hash_py("pyc")
|
||||
|
||||
def test_ignore_dot_hash_pyx(self):
|
||||
self._test_ignore_dot_hash_py("pyx")
|
||||
|
||||
def test_ignore_dot_hash_pyo(self):
|
||||
self._test_ignore_dot_hash_py("pyo")
|
||||
|
||||
|
||||
class SourcelessIgnoreFilesTest(IgnoreFilesTest):
|
||||
sourceless = True
|
||||
|
||||
|
||||
|
@ -350,9 +384,11 @@ class SourcelessNeedsFlagTest(TestBase):
|
|||
|
||||
from alembic import op
|
||||
|
||||
|
||||
def upgrade():
|
||||
op.execute("CREATE TABLE foo(id integer)")
|
||||
|
||||
|
||||
def downgrade():
|
||||
op.execute("DROP TABLE foo")
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
from alembic.testing.fixtures import TestBase
|
||||
from alembic.testing import eq_, ne_, assert_raises_message, is_
|
||||
from alembic.testing import eq_, ne_, assert_raises_message, is_, assertions
|
||||
from alembic.testing.env import clear_staging_env, staging_env, \
|
||||
_get_staging_directory, _no_sql_testing_config, env_file_fixture, \
|
||||
script_file_fixture, _testing_config, _sqlite_testing_config, \
|
||||
|
@ -201,7 +201,7 @@ class RevisionCommandTest(TestBase):
|
|||
file_.write(
|
||||
"<%text>#</%text> ${message}\n"
|
||||
"revision = ${repr(up_revision)}\n"
|
||||
"down_revision = ${repr(down_revision)}\n"
|
||||
"down_revision = ${repr(down_revision)}\n\n"
|
||||
"def upgrade():\n"
|
||||
" ${upgrades if upgrades else 'pass'}\n\n"
|
||||
"def downgrade():\n"
|
||||
|
@ -252,9 +252,11 @@ branch_labels = ['%s']
|
|||
|
||||
from alembic import op
|
||||
|
||||
|
||||
def upgrade():
|
||||
pass
|
||||
|
||||
|
||||
def downgrade():
|
||||
pass
|
||||
|
||||
|
@ -708,14 +710,14 @@ class RewriterTest(TestBase):
|
|||
|
||||
eq_(
|
||||
autogenerate.render_python_code(directives[0].upgrade_ops),
|
||||
"### commands auto generated by Alembic - please adjust! ###\n"
|
||||
"# ### commands auto generated by Alembic - please adjust! ###\n"
|
||||
" op.add_column('t1', "
|
||||
"sa.Column('x', sa.Integer(), nullable=True))\n"
|
||||
" op.create_index('ixt', 't1', ['x'], unique=False)\n"
|
||||
" op.alter_column('t1', 'x',\n"
|
||||
" existing_type=sa.Integer(),\n"
|
||||
" nullable=False)\n"
|
||||
" ### end Alembic commands ###"
|
||||
" # ### end Alembic commands ###"
|
||||
)
|
||||
|
||||
|
||||
|
@ -837,3 +839,65 @@ context.configure(dialect_name='sqlite', template_args={"somearg":"somevalue"})
|
|||
contents = open(m.group(1)).read()
|
||||
os.remove(m.group(1))
|
||||
assert "<% z = x + y %>" in contents
|
||||
|
||||
|
||||
class DuplicateVersionLocationsTest(TestBase):
|
||||
|
||||
def setUp(self):
|
||||
self.env = staging_env()
|
||||
self.cfg = _multi_dir_testing_config(
|
||||
# this is a duplicate of one of the paths
|
||||
# already present in this fixture
|
||||
extra_version_location='%(here)s/model1'
|
||||
)
|
||||
|
||||
script = ScriptDirectory.from_config(self.cfg)
|
||||
self.model1 = util.rev_id()
|
||||
self.model2 = util.rev_id()
|
||||
self.model3 = util.rev_id()
|
||||
for model, name in [
|
||||
(self.model1, "model1"),
|
||||
(self.model2, "model2"),
|
||||
(self.model3, "model3"),
|
||||
]:
|
||||
script.generate_revision(
|
||||
model, name, refresh=True,
|
||||
version_path=os.path.join(_get_staging_directory(), name),
|
||||
head="base")
|
||||
write_script(script, model, """\
|
||||
"%s"
|
||||
revision = '%s'
|
||||
down_revision = None
|
||||
branch_labels = ['%s']
|
||||
|
||||
from alembic import op
|
||||
|
||||
|
||||
def upgrade():
|
||||
pass
|
||||
|
||||
|
||||
def downgrade():
|
||||
pass
|
||||
|
||||
""" % (name, model, name))
|
||||
|
||||
def tearDown(self):
|
||||
clear_staging_env()
|
||||
|
||||
def test_env_emits_warning(self):
|
||||
with assertions.expect_warnings(
|
||||
"File %s loaded twice! ignoring. "
|
||||
"Please ensure version_locations is unique" % (
|
||||
os.path.realpath(os.path.join(
|
||||
_get_staging_directory(),
|
||||
"model1",
|
||||
"%s_model1.py" % self.model1
|
||||
)))
|
||||
):
|
||||
script = ScriptDirectory.from_config(self.cfg)
|
||||
script.revision_map.heads
|
||||
eq_(
|
||||
[rev.revision for rev in script.walk_revisions()],
|
||||
[self.model1, self.model2, self.model3]
|
||||
)
|
|
@ -35,8 +35,8 @@ class TestMigrationContext(TestBase):
|
|||
self.transaction = self.connection.begin()
|
||||
|
||||
def tearDown(self):
|
||||
version_table.drop(self.connection, checkfirst=True)
|
||||
self.transaction.rollback()
|
||||
version_table.drop(self.connection, checkfirst=True)
|
||||
self.connection.close()
|
||||
|
||||
def make_one(self, **kwargs):
|
||||
|
@ -58,12 +58,24 @@ class TestMigrationContext(TestBase):
|
|||
context = self.make_one(dialect_name='sqlite',
|
||||
opts={'version_table': 'explicit'})
|
||||
eq_(context._version.name, 'explicit')
|
||||
eq_(context._version.primary_key.name, 'explicit_pkc')
|
||||
|
||||
def test_config_explicit_version_table_schema(self):
|
||||
context = self.make_one(dialect_name='sqlite',
|
||||
opts={'version_table_schema': 'explicit'})
|
||||
eq_(context._version.schema, 'explicit')
|
||||
|
||||
def test_config_explicit_no_pk(self):
|
||||
context = self.make_one(dialect_name='sqlite',
|
||||
opts={'version_table_pk': False})
|
||||
eq_(len(context._version.primary_key), 0)
|
||||
|
||||
def test_config_explicit_w_pk(self):
|
||||
context = self.make_one(dialect_name='sqlite',
|
||||
opts={'version_table_pk': True})
|
||||
eq_(len(context._version.primary_key), 1)
|
||||
eq_(context._version.primary_key.name, "alembic_version_pkc")
|
||||
|
||||
def test_get_current_revision_doesnt_create_version_table(self):
|
||||
context = self.make_one(connection=self.connection,
|
||||
opts={'version_table': 'version_table'})
|
||||
|
|
10
tox.ini
10
tox.ini
|
@ -1,6 +1,8 @@
|
|||
[tox]
|
||||
minversion=1.8.dev1
|
||||
envlist = py{27,33,34,35}-sqla{09,10,11}, py{27}-sqla{079,084}
|
||||
|
||||
# current mysqlclient fails with <=SQLA 0.9 on py3k due to
|
||||
# old unicode statements flag
|
||||
envlist = py{27,33,34,35,36}-sqla{10,11}, py{27}-sqla{079,084,09}
|
||||
|
||||
SQLA_REPO = {env:SQLA_REPO:git+http://git.sqlalchemy.org/sqlalchemy.git}
|
||||
|
||||
|
@ -36,7 +38,7 @@ setenv=
|
|||
sqlite: SQLITE=--db sqlite
|
||||
postgresql: POSTGRESQL=--db postgresql
|
||||
mysql: MYSQL=--db mysql
|
||||
oracle: ORACLE=--db oracle --low-connections
|
||||
oracle: ORACLE=--db oracle --low-connections --write-idents oracle_idents.txt
|
||||
mssql: MSSQL=--db pymssql
|
||||
|
||||
# tox as of 2.0 blocks all environment variables from the
|
||||
|
@ -46,7 +48,7 @@ passenv=ORACLE_HOME NLS_LANG
|
|||
|
||||
commands=
|
||||
{env:BASECOMMAND} {env:WORKERS} {env:SQLITE:} {env:POSTGRESQL:} {env:MYSQL:} {env:ORACLE:} {env:MSSQL:} {env:BACKENDONLY:} {env:COVERAGE:} {posargs}
|
||||
{oracle}: python reap_oracle_dbs.py
|
||||
{oracle}: python reap_oracle_dbs.py oracle_idents.txt
|
||||
|
||||
|
||||
[testenv:pep8]
|
||||
|
|
Loading…
Reference in New Issue