]> git.ipfire.org Git - thirdparty/sqlalchemy/alembic.git/commitdiff
Bump to Alembic 1.1, bump requirements
authorMike Bayer <mike_mp@zzzcomputing.com>
Sun, 21 Jul 2019 16:56:20 +0000 (12:56 -0400)
committerMike Bayer <mike_mp@zzzcomputing.com>
Sun, 21 Jul 2019 18:44:38 +0000 (14:44 -0400)
Alembic 1.1 bumps the minimum version of SQLAlchemy to 1.1.   As was the
case before, Python requirements remain at Python 2.7, or in the 3.x series
Python 3.4.

Change-Id: I68074fb4b59c96c4a596396a69aa143c65d048b5

32 files changed:
alembic/__init__.py
alembic/autogenerate/compare.py
alembic/autogenerate/render.py
alembic/ddl/base.py
alembic/ddl/mysql.py
alembic/ddl/postgresql.py
alembic/ddl/sqlite.py
alembic/testing/assertions.py
alembic/testing/fixtures.py
alembic/testing/plugin/bootstrap.py
alembic/testing/plugin/noseplugin.py [deleted file]
alembic/testing/plugin/plugin_base.py
alembic/testing/requirements.py
alembic/testing/runner.py [deleted file]
alembic/testing/warnings.py
alembic/util/__init__.py
alembic/util/compat.py
alembic/util/sqla_compat.py
docs/build/changelog.rst
docs/build/unreleased/bump.rst [new file with mode: 0644]
setup.py
tests/_autogen_fixtures.py
tests/requirements.py
tests/test_autogen_diffs.py
tests/test_autogen_indexes.py
tests/test_autogen_render.py
tests/test_batch.py
tests/test_mssql.py
tests/test_op.py
tests/test_op_naming_convention.py
tests/test_postgresql.py
tox.ini

index 78d16cd27f59c52de4f131d57bba13c223ca369e..5396c6c3929d193c65cf6ba9a8f7edcccf6ae443 100644 (file)
@@ -6,7 +6,7 @@ from . import op  # noqa
 from .runtime import environment
 from .runtime import migration
 
-__version__ = '1.0.12'
+__version__ = "1.1.0"
 
 package_dir = path.abspath(path.dirname(__file__))
 
index 37371eb6ae041651a1681396576b58d078dd7e8c..49ceb21ecb24ed3e0a5c2ec4044ed9ad6352fcb0 100644 (file)
@@ -809,7 +809,7 @@ def _setup_autoincrement(
 
     if metadata_col.table._autoincrement_column is metadata_col:
         alter_column_op.kw["autoincrement"] = True
-    elif util.sqla_110 and metadata_col.autoincrement is True:
+    elif metadata_col.autoincrement is True:
         alter_column_op.kw["autoincrement"] = True
     elif metadata_col.autoincrement is False:
         alter_column_op.kw["autoincrement"] = False
index 0e3b2d872f09099b534bba6b616dacf3018ebb29..24eeb4e7ac431040d58d4cf4d1bf7340bdb476b6 100644 (file)
@@ -476,7 +476,7 @@ def _ident(name):
     """
     if name is None:
         return name
-    elif util.sqla_09 and isinstance(name, sql.elements.quoted_name):
+    elif isinstance(name, sql.elements.quoted_name):
         if compat.py2k:
             # the attempt to encode to ascii here isn't super ideal,
             # however we are trying to cut down on an explosion of
index 90573cf5de7a3de2330cf49cd0a8590339c82371..c654c838d6c6f2f891c16c2cf49a859df98fe543 100644 (file)
@@ -5,19 +5,14 @@ from sqlalchemy import types as sqltypes
 from sqlalchemy.ext.compiler import compiles
 from sqlalchemy.schema import Column
 from sqlalchemy.schema import DDLElement
+from sqlalchemy.sql.elements import quoted_name
 
-from .. import util
 from ..util.sqla_compat import _columns_for_constraint  # noqa
 from ..util.sqla_compat import _find_columns  # noqa
 from ..util.sqla_compat import _fk_spec  # noqa
 from ..util.sqla_compat import _is_type_bound  # noqa
 from ..util.sqla_compat import _table_for_constraint  # noqa
 
-# backwards compat
-
-if util.sqla_09:
-    from sqlalchemy.sql.elements import quoted_name
-
 
 class AlterTable(DDLElement):
 
@@ -169,7 +164,7 @@ def visit_column_default(element, compiler, **kw):
 def quote_dotted(name, quote):
     """quote the elements of a dotted name"""
 
-    if util.sqla_09 and isinstance(name, quoted_name):
+    if isinstance(name, quoted_name):
         return quote(name)
     result = ".".join([quote(x) for x in name.split(".")])
     return result
index b51414993d79df1dafd1588e77b5a54abf14d05f..17ae2de737047480942b91486b221bda30849c06 100644 (file)
@@ -18,7 +18,6 @@ from ..autogenerate import compare
 from ..util.compat import string_types
 from ..util.sqla_compat import _is_mariadb
 from ..util.sqla_compat import _is_type_bound
-from ..util.sqla_compat import sqla_100
 
 
 class MySQLImpl(DefaultImpl):
@@ -212,14 +211,6 @@ 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,
index 255c7e6238a042c0e7605e17fc76fb918be31195..d5bcd1772fc4ae1124b347d0ab80b6dfe62b2c54 100644 (file)
@@ -6,6 +6,7 @@ from sqlalchemy import Numeric
 from sqlalchemy import text
 from sqlalchemy import types as sqltypes
 from sqlalchemy.dialects.postgresql import BIGINT
+from sqlalchemy.dialects.postgresql import ExcludeConstraint
 from sqlalchemy.dialects.postgresql import INTEGER
 from sqlalchemy.sql.expression import ColumnClause
 from sqlalchemy.sql.expression import UnaryExpression
@@ -29,9 +30,6 @@ from ..operations.base import Operations
 from ..util import compat
 from ..util import sqla_compat
 
-if util.sqla_100:
-    from sqlalchemy.dialects.postgresql import ExcludeConstraint
-
 
 log = logging.getLogger(__name__)
 
@@ -76,8 +74,8 @@ class PostgresqlImpl(DefaultImpl):
 
         # check for unquoted string and quote for PG String types
         if (
-            not isinstance(inspector_column.type, Numeric) and
-            metadata_column.server_default is not None
+            not isinstance(inspector_column.type, Numeric)
+            and metadata_column.server_default is not None
             and isinstance(
                 metadata_column.server_default.arg, compat.string_types
             )
@@ -187,24 +185,13 @@ class PostgresqlImpl(DefaultImpl):
         metadata_indexes,
     ):
 
-        conn_uniques_by_name = dict(
-            (c.name, c) for c in conn_unique_constraints
-        )
         conn_indexes_by_name = dict((c.name, c) for c in conn_indexes)
 
-        if not util.sqla_100:
-            doubled_constraints = set(
-                conn_indexes_by_name[name]
-                for name in set(conn_uniques_by_name).intersection(
-                    conn_indexes_by_name
-                )
-            )
-        else:
-            doubled_constraints = set(
-                index
-                for index in conn_indexes
-                if index.info.get("duplicates_constraint")
-            )
+        doubled_constraints = set(
+            index
+            for index in conn_indexes
+            if index.info.get("duplicates_constraint")
+        )
 
         for ix in doubled_constraints:
             conn_indexes.remove(ix)
@@ -344,10 +331,6 @@ class CreateExcludeConstraintOp(ops.AddConstraintOp):
         )
 
     def to_constraint(self, migration_context=None):
-        if not util.sqla_100:
-            raise NotImplementedError(
-                "ExcludeConstraint not supported until SQLAlchemy 1.0"
-            )
         if self._orig_constraint is not None:
             return self._orig_constraint
         schema_obj = schemaobj.SchemaObjects(migration_context)
@@ -435,17 +418,15 @@ def _add_exclude_constraint(autogen_context, op):
     return _exclude_constraint(op.to_constraint(), autogen_context, alter=True)
 
 
-if util.sqla_100:
-
-    @render._constraint_renderers.dispatch_for(ExcludeConstraint)
-    def _render_inline_exclude_constraint(constraint, autogen_context):
-        rendered = render._user_defined_render(
-            "exclude", constraint, autogen_context
-        )
-        if rendered is not False:
-            return rendered
+@render._constraint_renderers.dispatch_for(ExcludeConstraint)
+def _render_inline_exclude_constraint(constraint, autogen_context):
+    rendered = render._user_defined_render(
+        "exclude", constraint, autogen_context
+    )
+    if rendered is not False:
+        return rendered
 
-        return _exclude_constraint(constraint, autogen_context, False)
+    return _exclude_constraint(constraint, autogen_context, False)
 
 
 def _postgresql_autogenerate_prefix(autogen_context):
index 95f814a0efd0bb15e0e91ed0a2af987dd30cbc7c..5a6977869088dd09b83ee010f965ce8b7ed57cca 100644 (file)
@@ -70,32 +70,6 @@ class SQLiteImpl(DefaultImpl):
 
         return rendered_inspector_default != rendered_metadata_default
 
-    def correct_for_autogen_constraints(
-        self,
-        conn_unique_constraints,
-        conn_indexes,
-        metadata_unique_constraints,
-        metadata_indexes,
-    ):
-
-        if util.sqla_100:
-            return
-
-        # adjustments to accommodate for SQLite unnamed unique constraints
-        # not being reported from the backend; this was updated in
-        # SQLA 1.0.
-
-        def uq_sig(uq):
-            return tuple(sorted(uq.columns.keys()))
-
-        conn_unique_sigs = set(uq_sig(uq) for uq in conn_unique_constraints)
-
-        for idx in list(metadata_unique_constraints):
-            # SQLite backend can't report on unnamed UNIQUE constraints,
-            # so remove these, unless we see an exact signature match
-            if idx.name is None and uq_sig(idx) not in conn_unique_sigs:
-                metadata_unique_constraints.remove(idx)
-
     def _guess_if_default_is_unparenthesized_sql_expr(self, expr):
         """Determine if a server default is a SQL expression or a constant.
 
index 865408300e63aa81e8fb43e3b8a842c820336a5f..2ad9dba4336832f876f176212e7448cd5c1ae3e1 100644 (file)
@@ -6,6 +6,12 @@ import warnings
 
 from sqlalchemy import exc as sa_exc
 from sqlalchemy.engine import default
+from sqlalchemy.testing.assertions import assert_raises  # noqa
+from sqlalchemy.testing.assertions import assert_raises_message  # noqa
+from sqlalchemy.testing.assertions import eq_  # noqa
+from sqlalchemy.testing.assertions import is_  # noqa
+from sqlalchemy.testing.assertions import is_not_  # noqa
+from sqlalchemy.testing.assertions import ne_  # noqa
 from sqlalchemy.util import decorator
 
 from . import config
@@ -16,55 +22,6 @@ from ..util.compat import py3k
 from ..util.compat import text_type
 
 
-if not util.sqla_094:
-
-    def eq_(a, b, msg=None):
-        """Assert a == b, with repr messaging on failure."""
-        assert a == b, msg or "%r != %r" % (a, b)
-
-    def ne_(a, b, msg=None):
-        """Assert a != b, with repr messaging on failure."""
-        assert a != b, msg or "%r == %r" % (a, b)
-
-    def is_(a, b, msg=None):
-        """Assert a is b, with repr messaging on failure."""
-        assert a is b, msg or "%r is not %r" % (a, b)
-
-    def is_not_(a, b, msg=None):
-        """Assert a is not b, with repr messaging on failure."""
-        assert a is not b, msg or "%r is %r" % (a, b)
-
-    def assert_raises(except_cls, callable_, *args, **kw):
-        try:
-            callable_(*args, **kw)
-            success = False
-        except except_cls:
-            success = True
-
-        # assert outside the block so it works for AssertionError too !
-        assert success, "Callable did not raise an exception"
-
-    def assert_raises_message(except_cls, msg, callable_, *args, **kwargs):
-        try:
-            callable_(*args, **kwargs)
-            assert False, "Callable did not raise an exception"
-        except except_cls as e:
-            assert re.search(msg, text_type(e), re.UNICODE), "%r !~ %s" % (
-                msg,
-                e,
-            )
-            print(text_type(e).encode("utf-8"))
-
-
-else:
-    from sqlalchemy.testing.assertions import assert_raises  # noqa
-    from sqlalchemy.testing.assertions import assert_raises_message  # noqa
-    from sqlalchemy.testing.assertions import eq_  # noqa
-    from sqlalchemy.testing.assertions import is_  # noqa
-    from sqlalchemy.testing.assertions import is_not_  # noqa
-    from sqlalchemy.testing.assertions import ne_  # noqa
-
-
 def eq_ignore_whitespace(a, b, msg=None):
     a = re.sub(r"^\s+?|\n", "", a)
     a = re.sub(r" {2,}", " ", a)
index 624346724475e6f3b98b77d3764ca72b8e487171..46a77ca54de9262f66014567f15d22bd426378ec 100644 (file)
@@ -10,14 +10,13 @@ from sqlalchemy import MetaData
 from sqlalchemy import String
 from sqlalchemy import Table
 from sqlalchemy import text
+from sqlalchemy.testing.fixtures import TestBase  # noqa
 
 import alembic
 from . import config
 from . import mock
 from .assertions import _get_dialect
 from .assertions import eq_
-from .plugin.plugin_base import SkipTest
-from .. import util
 from ..environment import EnvironmentContext
 from ..migration import MigrationContext
 from ..operations import Operations
@@ -29,44 +28,6 @@ testing_config = configparser.ConfigParser()
 testing_config.read(["test.cfg"])
 
 
-if not util.sqla_094:
-
-    class TestBase(object):
-        # A sequence of database names to always run, regardless of the
-        # constraints below.
-        __whitelist__ = ()
-
-        # A sequence of requirement names matching testing.requires decorators
-        __requires__ = ()
-
-        # A sequence of dialect names to exclude from the test class.
-        __unsupported_on__ = ()
-
-        # If present, test class is only runnable for the *single* specified
-        # dialect.  If you need multiple, use __unsupported_on__ and invert.
-        __only_on__ = None
-
-        # A sequence of no-arg callables. If any are True, the entire
-        # testcase is skipped.
-        __skip_if__ = None
-
-        def assert_(self, val, msg=None):
-            assert val, msg
-
-        # apparently a handful of tests are doing this....OK
-        def setup(self):
-            if hasattr(self, "setUp"):
-                self.setUp()
-
-        def teardown(self):
-            if hasattr(self, "tearDown"):
-                self.tearDown()
-
-
-else:
-    from sqlalchemy.testing.fixtures import TestBase  # noqa
-
-
 def capture_db():
     buf = []
 
@@ -108,10 +69,6 @@ def op_fixture(
 
     opts = {}
     if naming_convention:
-        if not util.sqla_092:
-            raise SkipTest(
-                "naming_convention feature requires " "sqla 0.9.2 or greater"
-            )
         opts["target_metadata"] = MetaData(naming_convention=naming_convention)
 
     class buffer_(object):
index 4bd415d193ed7f82d8e45d55f5db022e8960a24d..ed8fa82393c9dccd19b1e9a96ce3b939e94c7d07 100644 (file)
@@ -1,5 +1,5 @@
 """
-Bootstrapper for nose/pytest plugins.
+Bootstrapper for test framework plugins.
 
 The entire rationale for this system is to get the modules in plugin/
 imported without importing all of the supporting library, so that we can
@@ -40,8 +40,5 @@ def load_file_as_module(name):
 if to_bootstrap == "pytest":
     sys.modules["alembic_plugin_base"] = load_file_as_module("plugin_base")
     sys.modules["alembic_pytestplugin"] = load_file_as_module("pytestplugin")
-elif to_bootstrap == "nose":
-    sys.modules["alembic_plugin_base"] = load_file_as_module("plugin_base")
-    sys.modules["alembic_noseplugin"] = load_file_as_module("noseplugin")
 else:
     raise Exception("unknown bootstrap: %s" % to_bootstrap)  # noqa
diff --git a/alembic/testing/plugin/noseplugin.py b/alembic/testing/plugin/noseplugin.py
deleted file mode 100644 (file)
index fafb9e1..0000000
+++ /dev/null
@@ -1,106 +0,0 @@
-# plugin/noseplugin.py
-# Copyright (C) 2005-2017 the SQLAlchemy authors and contributors
-# <see AUTHORS file>
-#
-# This module is part of SQLAlchemy and is released under
-# the MIT License: http://www.opensource.org/licenses/mit-license.php
-
-"""
-Enhance nose with extra options and behaviors for running SQLAlchemy tests.
-
-
-NOTE:  copied/adapted from SQLAlchemy master for backwards compatibility;
-this should be removable when Alembic targets SQLAlchemy 1.0.0.
-
-"""
-
-try:
-    # installed by bootstrap.py
-    import alembic_plugin_base as plugin_base
-except ImportError:
-    # assume we're a package, use traditional import
-    from . import plugin_base
-
-import os
-import sys
-
-from nose.plugins import Plugin
-
-fixtures = None
-
-py3k = sys.version_info.major >= 3
-
-
-class NoseSQLAlchemy(Plugin):
-    enabled = True
-
-    name = "sqla_testing"
-    score = 100
-
-    def options(self, parser, env=os.environ):
-        Plugin.options(self, parser, env)
-        opt = parser.add_option
-
-        def make_option(name, **kw):
-            callback_ = kw.pop("callback", None)
-            if callback_:
-
-                def wrap_(option, opt_str, value, parser):
-                    callback_(opt_str, value, parser)
-
-                kw["callback"] = wrap_
-            opt(name, **kw)
-
-        plugin_base.setup_options(make_option)
-        plugin_base.read_config()
-
-    def configure(self, options, conf):
-        super(NoseSQLAlchemy, self).configure(options, conf)
-        plugin_base.pre_begin(options)
-
-        plugin_base.set_coverage_flag(options.enable_plugin_coverage)
-
-    def begin(self):
-        global fixtures
-        from alembic.testing import fixtures  # noqa
-
-        plugin_base.post_begin()
-
-    def describeTest(self, test):
-        return ""
-
-    def wantFunction(self, fn):
-        return False
-
-    def wantMethod(self, fn):
-        if py3k:
-            if not hasattr(fn.__self__, "cls"):
-                return False
-            cls = fn.__self__.cls
-        else:
-            cls = fn.im_class
-        return plugin_base.want_method(cls, fn)
-
-    def wantClass(self, cls):
-        return plugin_base.want_class(cls)
-
-    def beforeTest(self, test):
-        plugin_base.before_test(
-            test,
-            test.test.cls.__module__,
-            test.test.cls,
-            test.test.method.__name__,
-        )
-
-    def afterTest(self, test):
-        plugin_base.after_test(test)
-
-    def startContext(self, ctx):
-        if not isinstance(ctx, type) or not issubclass(ctx, fixtures.TestBase):
-            return
-        plugin_base.start_test_class(ctx)
-
-    def stopContext(self, ctx):
-        if not isinstance(ctx, type) or not issubclass(ctx, fixtures.TestBase):
-            return
-        plugin_base.stop_test_class(ctx)
index 44930c8415153b4febaf9c7c91a74217045a6fb3..20aa34e43089fd395bbc58470ec3e9c2b0491961 100644 (file)
@@ -7,11 +7,7 @@
 """Testing extensions.
 
 this module is designed to work as a testing-framework-agnostic library,
-so that we can continue to support nose and also begin adding new
-functionality via py.test.
-
-NOTE:  copied/adapted from SQLAlchemy master for backwards compatibility;
-this should be removable when Alembic targets SQLAlchemy 1.0.0
+however it currenty targets only py.test.
 
 
 """
@@ -21,14 +17,9 @@ from __future__ import absolute_import
 import re
 import sys
 
-try:
-    # unitttest has a SkipTest also but pytest doesn't
-    # honor it unless nose is imported too...
-    from nose import SkipTest
-except ImportError:
-    from pytest import skip
+from pytest import skip
 
-    SkipTest = skip.Exception
+SkipTest = skip.Exception
 
 py3k = sys.version_info.major >= 3
 
@@ -234,8 +225,6 @@ def post_begin():
     for fn in post_configure:
         fn(options, file_config)
 
-    # late imports, has to happen after config as well
-    # as nose plugins like coverage
     global util, fixtures, engines, exclusions, assertions
     global warnings, profiling, config, testing
     from alembic.testing import config, warnings, exclusions  # noqa
@@ -373,8 +362,6 @@ def _prep_testing_database(options, file_config):
     from alembic.testing import config
     from alembic.testing.exclusions import against
     from sqlalchemy import schema
-    from alembic import util
-
     from sqlalchemy import inspect
 
     if options.dropfirst:
@@ -431,7 +418,7 @@ def _prep_testing_database(options, file_config):
                         )
                     )
 
-            if against(cfg, "postgresql") and util.sqla_100:
+            if against(cfg, "postgresql"):
                 from sqlalchemy.dialects import postgresql
 
                 for enum in inspector.get_enums("*"):
index b4c147beb654eae32cb59dc09071d0164f665274..bbb2ca207f3b68befb8b5375098681e2d05e9325 100644 (file)
@@ -1,16 +1,11 @@
 import sys
 
+from sqlalchemy.testing.requirements import Requirements
+
 from alembic import util
 from alembic.util import sqla_compat
 from . import exclusions
 
-if util.sqla_094:
-    from sqlalchemy.testing.requirements import Requirements
-else:
-
-    class Requirements(object):
-        pass
-
 
 class SuiteRequirements(Requirements):
     @property
@@ -76,76 +71,6 @@ class SuiteRequirements(Requirements):
             "SQLAlchemy 1.2.16 or greater required",
         )
 
-    @property
-    def sqlalchemy_10(self):
-        return exclusions.skip_if(
-            lambda config: not util.sqla_100,
-            "SQLAlchemy 1.0.0 or greater required",
-        )
-
-    @property
-    def fail_before_sqla_100(self):
-        return exclusions.fails_if(
-            lambda config: not util.sqla_100,
-            "SQLAlchemy 1.0.0 or greater required",
-        )
-
-    @property
-    def fail_before_sqla_1010(self):
-        return exclusions.fails_if(
-            lambda config: not util.sqla_1010,
-            "SQLAlchemy 1.0.10 or greater required",
-        )
-
-    @property
-    def fail_before_sqla_099(self):
-        return exclusions.fails_if(
-            lambda config: not util.sqla_099,
-            "SQLAlchemy 0.9.9 or greater required",
-        )
-
-    @property
-    def fail_before_sqla_110(self):
-        return exclusions.fails_if(
-            lambda config: not util.sqla_110,
-            "SQLAlchemy 1.1.0 or greater required",
-        )
-
-    @property
-    def sqlalchemy_092(self):
-        return exclusions.skip_if(
-            lambda config: not util.sqla_092,
-            "SQLAlchemy 0.9.2 or greater required",
-        )
-
-    @property
-    def sqlalchemy_094(self):
-        return exclusions.skip_if(
-            lambda config: not util.sqla_094,
-            "SQLAlchemy 0.9.4 or greater required",
-        )
-
-    @property
-    def sqlalchemy_099(self):
-        return exclusions.skip_if(
-            lambda config: not util.sqla_099,
-            "SQLAlchemy 0.9.9 or greater required",
-        )
-
-    @property
-    def sqlalchemy_100(self):
-        return exclusions.skip_if(
-            lambda config: not util.sqla_100,
-            "SQLAlchemy 1.0.0 or greater required",
-        )
-
-    @property
-    def sqlalchemy_1014(self):
-        return exclusions.skip_if(
-            lambda config: not util.sqla_1014,
-            "SQLAlchemy 1.0.14 or greater required",
-        )
-
     @property
     def sqlalchemy_1115(self):
         return exclusions.skip_if(
diff --git a/alembic/testing/runner.py b/alembic/testing/runner.py
deleted file mode 100644 (file)
index da5e0f4..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-#!/usr/bin/env python
-# testing/runner.py
-# Copyright (C) 2005-2017 the SQLAlchemy authors and contributors
-# <see AUTHORS file>
-#
-# This module is part of SQLAlchemy and is released under
-# the MIT License: http://www.opensource.org/licenses/mit-license.php
-"""
-Nose test runner module.
-
-This script is a front-end to "nosetests" which
-installs SQLAlchemy's testing plugin into the local environment.
-
-The script is intended to be used by third-party dialects and extensions
-that run within SQLAlchemy's testing framework.    The runner can
-be invoked via::
-
-    python -m alembic.testing.runner
-
-The script is then essentially the same as the "nosetests" script, including
-all of the usual Nose options.   The test environment requires that a
-setup.cfg is locally present including various required options.
-
-Note that when using this runner, Nose's "coverage" plugin will not be
-able to provide coverage for SQLAlchemy itself, since SQLAlchemy is
-imported into sys.modules before coverage is started.   The special
-script sqla_nose.py is provided as a top-level script which loads the
-plugin in a special (somewhat hacky) way so that coverage against
-SQLAlchemy itself is possible.
-
-"""
-import nose
-
-from .plugin.noseplugin import NoseSQLAlchemy
-
-
-def main():
-    nose.main(addplugins=[NoseSQLAlchemy()])
-
-
-def setup_py_test():
-    """Runner to use for the 'test_suite' entry of your setup.py.
-
-    Prevents any name clash shenanigans from the command line
-    argument "test" that the "setup.py test" command sends
-    to nose.
-
-    """
-    nose.main(addplugins=[NoseSQLAlchemy()], argv=["runner"])
index 27ba706e5469830db1f6f134157796f133ca7398..7689e17d5c129e85ba046ea8dada07c30c498347 100644 (file)
@@ -25,6 +25,11 @@ def setup_filters():
     warnings.filterwarnings("error", category=sa_exc.SAWarning)
     warnings.filterwarnings("error", category=DeprecationWarning)
 
+    # temporary to allow SQLAlchemy 1.1 to pass under python 3
+    warnings.filterwarnings(
+        "ignore", category=DeprecationWarning, message=".*formatargspec"
+    )
+
 
 def assert_warnings(fn, warning_msgs, regex=False):
     """Assert that each of the given warnings are emitted by fn."""
index 88b743195aad9b62dfa656f6e4ebd0a2c5ced186..5a765fee89fd9b4a954fdb3ef69ac0a7757c7d3f 100644 (file)
@@ -21,19 +21,11 @@ from .pyfiles import edit  # noqa
 from .pyfiles import load_python_file  # noqa
 from .pyfiles import pyc_file_from_path  # noqa
 from .pyfiles import template_to_file  # noqa
-from .sqla_compat import sqla_09  # noqa
-from .sqla_compat import sqla_092  # noqa
-from .sqla_compat import sqla_094  # noqa
-from .sqla_compat import sqla_099  # noqa
-from .sqla_compat import sqla_100  # noqa
-from .sqla_compat import sqla_1010  # noqa
-from .sqla_compat import sqla_1014  # noqa
-from .sqla_compat import sqla_105  # noqa
 from .sqla_compat import sqla_110  # noqa
 from .sqla_compat import sqla_1115  # noqa
 from .sqla_compat import sqla_120  # noqa
 from .sqla_compat import sqla_1216  # noqa
 
 
-if not sqla_09:
-    raise CommandError("SQLAlchemy 0.9.0 or greater is required. ")
+if not sqla_110:
+    raise CommandError("SQLAlchemy 1.1.0 or greater is required. ")
index e0269b75bb58e3d74efe986516a3da01aae893cb..a08b1017b1cceb9553f21602749479236a118c3b 100644 (file)
@@ -3,9 +3,6 @@ import inspect
 import io
 import sys
 
-if sys.version_info < (2, 7):
-    raise NotImplementedError("Python 2.7 or greater is required.")
-
 py27 = sys.version_info >= (2, 7)
 py2k = sys.version_info.major < 3
 py3k = sys.version_info.major >= 3
@@ -327,7 +324,7 @@ class EncodedIO(io.TextIOWrapper):
 if py2k:
     # in Py2K, the io.* package is awkward because it does not
     # easily wrap the file type (e.g. sys.stdout) and I can't
-    # figure out at all how to wrap StringIO.StringIO (used by nosetests)
+    # figure out at all how to wrap StringIO.StringIO
     # and also might be user specified too.  So create a full
     # adapter.
 
index 52d4e018161049b3e1a47343aa9f41f9db612a89..5fa433241fbf8cbd2fe0b35a70a45dc50b120aa6 100644 (file)
@@ -25,25 +25,13 @@ def _safe_int(value):
 _vers = tuple(
     [_safe_int(x) for x in re.findall(r"(\d+|[abc]\d)", __version__)]
 )
-sqla_09 = _vers >= (0, 9, 0)
-sqla_092 = _vers >= (0, 9, 2)
-sqla_094 = _vers >= (0, 9, 4)
-sqla_094 = _vers >= (0, 9, 4)
-sqla_099 = _vers >= (0, 9, 9)
-sqla_100 = _vers >= (1, 0, 0)
-sqla_105 = _vers >= (1, 0, 5)
-sqla_1010 = _vers >= (1, 0, 10)
 sqla_110 = _vers >= (1, 1, 0)
-sqla_1014 = _vers >= (1, 0, 14)
 sqla_1115 = _vers >= (1, 1, 15)
 sqla_120 = _vers >= (1, 2, 0)
 sqla_1216 = _vers >= (1, 2, 16)
 
 
-if sqla_110:
-    AUTOINCREMENT_DEFAULT = "auto"
-else:
-    AUTOINCREMENT_DEFAULT = True
+AUTOINCREMENT_DEFAULT = "auto"
 
 
 def _table_for_constraint(constraint):
@@ -63,14 +51,9 @@ def _columns_for_constraint(constraint):
 
 
 def _fk_spec(constraint):
-    if sqla_100:
-        source_columns = [
-            constraint.columns[key].name for key in constraint.column_keys
-        ]
-    else:
-        source_columns = [
-            element.parent.name for element in constraint.elements
-        ]
+    source_columns = [
+        constraint.columns[key].name for key in constraint.column_keys
+    ]
 
     source_table = constraint.parent.name
     source_schema = constraint.parent.schema
@@ -106,15 +89,8 @@ def _fk_is_self_referential(constraint):
 def _is_type_bound(constraint):
     # this deals with SQLAlchemy #3260, don't copy CHECK constraints
     # that will be generated by the type.
-    if sqla_100:
-        # new feature added for #3260
-        return constraint._type_bound
-    else:
-        # old way, look at what we know Boolean/Enum to use
-        return constraint._create_rule is not None and isinstance(
-            getattr(constraint._create_rule, "target", None),
-            sqltypes.SchemaType,
-        )
+    # new feature added for #3260
+    return constraint._type_bound
 
 
 def _find_columns(clause):
index b05177a94954ed27cee1674c5fb7ce08ea043c4a..a242b85ee91b2e82726d30d452c0467f2a10f9da 100644 (file)
@@ -4,7 +4,7 @@ Changelog
 ==========
 
 .. changelog::
-    :version: 1.0.12
+    :version: 1.1.0
     :include_notes_from: unreleased
 
 .. changelog::
diff --git a/docs/build/unreleased/bump.rst b/docs/build/unreleased/bump.rst
new file mode 100644 (file)
index 0000000..7e04c9c
--- /dev/null
@@ -0,0 +1,6 @@
+.. change::
+    :tags: change
+
+    Alembic 1.1 bumps the minimum version of SQLAlchemy to 1.1.   As was the
+    case before, Python requirements remain at Python 2.7, or in the 3.x series
+    Python 3.4.
index b1555fe0fb3bcebb1d3bb6a04c64588e1869e0c7..ae875764e42deb025e21ac0161e4a82dbafef2e9 100644 (file)
--- a/setup.py
+++ b/setup.py
@@ -19,7 +19,7 @@ v.close()
 readme = os.path.join(os.path.dirname(__file__), "README.rst")
 
 requires = [
-    "SQLAlchemy>=0.9.0",
+    "SQLAlchemy>=1.1.0",
     "Mako",
     "python-editor>=0.3",
     "python-dateutil",
index e9047f663ef2cbfe2bfb9431286ea4b455de8599..a417a0edb70250ebaa0ebab4f931bb18f05b1cfa 100644 (file)
@@ -186,9 +186,7 @@ class _ComparesFKs(object):
 
         eq_([elem.column.name for elem in diff[1].elements], target_columns)
         if conditional_name is not None:
-            if config.requirements.no_fk_names.enabled:
-                eq_(diff[1].name, None)
-            elif conditional_name == "servergenerated":
+            if conditional_name == "servergenerated":
                 fks = Inspector.from_engine(self.bind).get_foreign_keys(
                     source_table
                 )
index a4e7f59f7a822db2d34cf88fe1ee3211a8d16b8e..bcfadbd0256c0e21b111a525da0fb8f086abb543 100644 (file)
@@ -1,4 +1,3 @@
-from alembic import util
 from alembic.testing import exclusions
 from alembic.testing.requirements import SuiteRequirements
 from alembic.util import sqla_compat
@@ -32,15 +31,6 @@ class DefaultRequirements(SuiteRequirements):
             )
         )
 
-    @property
-    def no_fk_names(self):
-        """foreign key constraints *never* have names in the DB"""
-
-        return exclusions.only_if(
-            lambda config: exclusions.against(config, "sqlite")
-            and not util.sqla_100
-        )
-
     @property
     def check_constraints_w_enforcement(self):
         return exclusions.fails_on("mysql")
@@ -63,14 +53,7 @@ class DefaultRequirements(SuiteRequirements):
 
     @property
     def reflects_fk_options(self):
-        return exclusions.only_on(
-            [
-                "postgresql",
-                "mysql",
-                lambda config: util.sqla_110
-                and exclusions.against(config, "sqlite"),
-            ]
-        )
+        return exclusions.only_on(["postgresql", "mysql", "sqlite"])
 
     @property
     def fk_initially(self):
@@ -100,13 +83,7 @@ class DefaultRequirements(SuiteRequirements):
         """Target driver reflects the name of primary key constraints."""
 
         return exclusions.fails_on_everything_except(
-            "postgresql",
-            "oracle",
-            "mssql",
-            "sybase",
-            lambda config: (
-                util.sqla_110 and exclusions.against(config, "sqlite")
-            ),
+            "postgresql", "oracle", "mssql", "sybase", "sqlite"
         )
 
     @property
index d7d043085d10039ebf56d075aa86709734b73ade..f02dbb80025048418e1dd6a76298c0f3fb2f4bd9 100644 (file)
@@ -751,11 +751,6 @@ class AutogenSystemColTest(AutogenTest, TestBase):
 class AutogenerateVariantCompareTest(AutogenTest, TestBase):
     __backend__ = True
 
-    # 1.0.13 and lower fail on Postgresql due to variant / bigserial issue
-    # #3739
-
-    __requires__ = ("sqlalchemy_1014",)
-
     @classmethod
     def _get_db_schema(cls):
         m = MetaData()
@@ -1544,7 +1539,6 @@ class AutoincrementTest(AutogenFixtureTest, TestBase):
         ops = self._fixture(m1, m2, return_ops=True)
         assert "autoincrement" not in ops.ops[0].ops[0].kw
 
-    @config.requirements.fail_before_sqla_110
     def test_alter_column_autoincrement_nonpk_explicit_true(self):
         m1 = MetaData()
         m2 = MetaData()
index 12f705f9076aa89ed5a043c642b25201e05b8482..c8eaffb5684808de24c4faa30f3fe95ac8b66e77 100644 (file)
@@ -536,9 +536,6 @@ class AutogenerateUniqueIndexTest(AutogenFixtureTest, TestBase):
             set([diffs[0][1].name, diffs[1][1].name]), set(["xy_idx", "y_idx"])
         )
 
-    # this simply doesn't fully work before we had
-    # effective deduping of indexes/uniques.
-    @config.requirements.sqlalchemy_100
     def test_drop_table_w_uq_constraint(self):
         m1 = MetaData()
         m2 = MetaData()
@@ -830,7 +827,6 @@ class PGUniqueIndexTest(AutogenerateUniqueIndexTest):
         diffs = self._fixture(m1, m2, include_schemas=True)
         eq_(diffs, [])
 
-    @config.requirements.sqlalchemy_100
     @config.requirements.btree_gist
     def test_exclude_const_unchanged(self):
         from sqlalchemy.dialects.postgresql import TSRANGE, ExcludeConstraint
index d17ed28091e5bd0f4700f852418b181077931258..037a05f24c70be197f756416c0e88c6c23a30faf 100644 (file)
@@ -181,18 +181,11 @@ class AutogenRenderTest(TestBase):
         idx = Index("test_lower_code_idx", cast(t.c.code, String))
         op_obj = ops.CreateIndexOp.from_index(idx)
 
-        if config.requirements.sqlalchemy_110.enabled:
-            eq_ignore_whitespace(
-                autogenerate.render_op_text(self.autogen_context, op_obj),
-                "op.create_index('test_lower_code_idx', 'test', "
-                "[sa.text(!U'CAST(code AS VARCHAR)')], unique=False)",
-            )
-        else:
-            eq_ignore_whitespace(
-                autogenerate.render_op_text(self.autogen_context, op_obj),
-                "op.create_index('test_lower_code_idx', 'test', "
-                "[sa.text(!U'CAST(code AS VARCHAR)')], unique=False)",
-            )
+        eq_ignore_whitespace(
+            autogenerate.render_op_text(self.autogen_context, op_obj),
+            "op.create_index('test_lower_code_idx', 'test', "
+            "[sa.text(!U'CAST(code AS VARCHAR)')], unique=False)",
+        )
 
     def test_render_add_index_desc(self):
         m = MetaData()
@@ -1035,7 +1028,6 @@ class AutogenRenderTest(TestBase):
             "sa.PrimaryKeyConstraint('x'))",
         )
 
-    @config.requirements.fail_before_sqla_110
     def test_render_table_w_autoincrement(self):
         m = MetaData()
         t = Table(
@@ -1164,7 +1156,7 @@ class AutogenRenderTest(TestBase):
             result,
             "sa.Column('some_key', sa.Integer(), "
             "nullable=True, "
-            "comment=\"This is a john's comment\")",
+            'comment="This is a john\'s comment")',
         )
 
     def test_render_col_autoinc_false_mysql(self):
@@ -1587,7 +1579,6 @@ class AutogenRenderTest(TestBase):
             "sa.Enum('one', 'two', 'three')",
         )
 
-    @config.requirements.sqlalchemy_099
     def test_render_non_native_enum(self):
         eq_ignore_whitespace(
             autogenerate.render._repr_type(
@@ -1604,7 +1595,6 @@ class AutogenRenderTest(TestBase):
             "sa.Integer()",
         )
 
-    @config.requirements.sqlalchemy_110
     def test_generic_array_type(self):
 
         eq_ignore_whitespace(
@@ -1621,7 +1611,6 @@ class AutogenRenderTest(TestBase):
             "sa.ARRAY(sa.DateTime(timezone=True))",
         )
 
-    @config.requirements.sqlalchemy_110
     def test_render_array_no_context(self):
         uo = ops.UpgradeOps(
             ops=[
@@ -1908,8 +1897,6 @@ class AutogenRenderTest(TestBase):
 
 
 class RenderNamingConventionTest(TestBase):
-    __requires__ = ("sqlalchemy_094",)
-
     def setUp(self):
 
         convention = {
index c8c5b33d6c4ac8ddbde0fb076ebcc8f5cbc196bc..5454771296c596e72aa4fb1ec67d8fc8d052d8f5 100644 (file)
@@ -1438,7 +1438,6 @@ class BatchRoundTripTest(TestBase):
             {"id": 6, "data": 5, "x": -2},
         )
 
-    @config.requirements.sqlalchemy_094
     @config.requirements.unnamed_constraints
     def test_drop_foreign_key(self):
         bar = Table(
index 23577b0f78950a25fe14f6e4731b50fb61e17950..94182711a6e9b09cfe21169d97c026058e43d38c 100644 (file)
@@ -21,10 +21,7 @@ class FullEnvironmentTests(TestBase):
     @classmethod
     def setup_class(cls):
         staging_env()
-        if util.sqla_105:
-            directives = "sqlalchemy.legacy_schema_aliasing=false"
-        else:
-            directives = ""
+        directives = "sqlalchemy.legacy_schema_aliasing=false"
         cls.cfg = cfg = _no_sql_testing_config("mssql", directives)
 
         cls.a, cls.b, cls.c = three_rev_fixture(cfg)
index 0312790be1d90f0f84f14357ab17bbbf29b22c55..26feeb40b33d4a45eb7ff077141f311cb98fa785 100644 (file)
@@ -10,6 +10,7 @@ from sqlalchemy import Table
 from sqlalchemy.sql import column
 from sqlalchemy.sql import func
 from sqlalchemy.sql import text
+from sqlalchemy.sql.schema import quoted_name
 
 from alembic import op
 from alembic.operations import ops
@@ -53,7 +54,6 @@ class OpTest(TestBase):
         )
 
     def test_add_column_schema_hard_quoting(self):
-        from sqlalchemy.sql.schema import quoted_name
 
         context = op_fixture("postgresql")
         op.add_column(
@@ -67,7 +67,6 @@ class OpTest(TestBase):
         )
 
     def test_rename_table_schema_hard_quoting(self):
-        from sqlalchemy.sql.schema import quoted_name
 
         context = op_fixture("postgresql")
         op.rename_table(
@@ -77,7 +76,6 @@ class OpTest(TestBase):
         context.assert_('ALTER TABLE "some.schema".t1 RENAME TO t2')
 
     def test_add_constraint_schema_hard_quoting(self):
-        from sqlalchemy.sql.schema import quoted_name
 
         context = op_fixture("postgresql")
         op.create_check_constraint(
index 88c761fa1d8b43e190fb700b7b29fd102dfbcb9e..b83b3af464f5471925df2c756f5e2179ba9ac609 100644 (file)
@@ -13,8 +13,6 @@ from alembic.testing.fixtures import TestBase
 
 
 class AutoNamingConventionTest(TestBase):
-    __requires__ = ("sqlalchemy_094",)
-
     def test_add_check_constraint(self):
         context = op_fixture(
             naming_convention={"ck": "ck_%(table_name)s_%(constraint_name)s"}
index 6c9838a7c4a495f8fc5ee97fe0d6845317df8f76..13ced304abb8c7fb4f5b29e4cab7d9eaf9ce760b 100644 (file)
@@ -16,6 +16,9 @@ from sqlalchemy import text
 from sqlalchemy import types
 from sqlalchemy.dialects.postgresql import ARRAY
 from sqlalchemy.dialects.postgresql import BYTEA
+from sqlalchemy.dialects.postgresql import HSTORE
+from sqlalchemy.dialects.postgresql import JSON
+from sqlalchemy.dialects.postgresql import JSONB
 from sqlalchemy.dialects.postgresql import UUID
 from sqlalchemy.engine.reflection import Inspector
 from sqlalchemy.sql import column
@@ -47,10 +50,6 @@ from alembic.testing.fixtures import op_fixture
 from alembic.testing.fixtures import TestBase
 
 
-if util.sqla_09:
-    from sqlalchemy.dialects.postgresql import JSON, JSONB, HSTORE
-
-
 class PostgresqlOpTest(TestBase):
     def test_rename_table_postgresql(self):
         context = op_fixture("postgresql")
@@ -88,7 +87,6 @@ class PostgresqlOpTest(TestBase):
             "WHERE locations.coordinates != Null"
         )
 
-    @config.requirements.fail_before_sqla_099
     def test_create_index_postgresql_concurrently(self):
         context = op_fixture("postgresql")
         op.create_index(
@@ -101,7 +99,6 @@ class PostgresqlOpTest(TestBase):
             "CREATE INDEX CONCURRENTLY geocoded ON locations (coordinates)"
         )
 
-    @config.requirements.fail_before_sqla_110
     def test_drop_index_postgresql_concurrently(self):
         context = op_fixture("postgresql")
         op.drop_index("geocoded", "locations", postgresql_concurrently=True)
@@ -119,7 +116,6 @@ class PostgresqlOpTest(TestBase):
         op.add_column("some_table", Column("q", Integer, primary_key=True))
         context.assert_("ALTER TABLE some_table ADD COLUMN q SERIAL NOT NULL")
 
-    @config.requirements.fail_before_sqla_100
     def test_create_exclude_constraint(self):
         context = op_fixture("postgresql")
         op.create_exclude_constraint(
@@ -130,7 +126,6 @@ class PostgresqlOpTest(TestBase):
             "WHERE (x > 5)"
         )
 
-    @config.requirements.fail_before_sqla_100
     def test_create_exclude_constraint_quoted_literal(self):
         context = op_fixture("postgresql")
         op.create_exclude_constraint(
@@ -145,7 +140,6 @@ class PostgresqlOpTest(TestBase):
             '("SomeColumn" WITH >) WHERE ("SomeColumn" > 5)'
         )
 
-    @config.requirements.fail_before_sqla_1010
     def test_create_exclude_constraint_quoted_column(self):
         context = op_fixture("postgresql")
         op.create_exclude_constraint(
@@ -535,7 +529,6 @@ class PostgresqlDefaultCompareTest(TestBase):
             DateTime(), text("TIMEZONE('utc', CURRENT_TIMESTAMP)")
         )
 
-    @config.requirements.sqlalchemy_10
     def test_compare_current_timestamp_fn_w_binds(self):
         self._compare_default_roundtrip(
             DateTime(), func.timezone("utc", func.current_timestamp())
@@ -799,7 +792,6 @@ class PostgresqlAutogenRenderTest(TestBase):
             in self.autogen_context.imports
         )
 
-    @config.requirements.sqlalchemy_110
     def test_postgresql_hstore_subtypes(self):
         eq_ignore_whitespace(
             autogenerate.render._repr_type(HSTORE(), self.autogen_context),
@@ -825,7 +817,6 @@ class PostgresqlAutogenRenderTest(TestBase):
             in self.autogen_context.imports
         )
 
-    @config.requirements.sqlalchemy_110
     def test_generic_array_type(self):
 
         eq_ignore_whitespace(
@@ -876,7 +867,6 @@ class PostgresqlAutogenRenderTest(TestBase):
             "postgresql.ARRAY(foobar.MYVARCHAR)",
         )
 
-    @config.requirements.fail_before_sqla_100
     def test_add_exclude_constraint(self):
         from sqlalchemy.dialects.postgresql import ExcludeConstraint
 
@@ -898,7 +888,6 @@ class PostgresqlAutogenRenderTest(TestBase):
             "where=sa.text(!U'x != 2'), using='gist')",
         )
 
-    @config.requirements.fail_before_sqla_100
     def test_add_exclude_constraint_case_sensitive(self):
         from sqlalchemy.dialects.postgresql import ExcludeConstraint
 
@@ -925,7 +914,6 @@ class PostgresqlAutogenRenderTest(TestBase):
             "where=sa.text(!U'\"XColumn\" != 2'), using='gist')",
         )
 
-    @config.requirements.fail_before_sqla_100
     def test_inline_exclude_constraint(self):
         from sqlalchemy.dialects.postgresql import ExcludeConstraint
 
@@ -956,7 +944,6 @@ class PostgresqlAutogenRenderTest(TestBase):
             ")",
         )
 
-    @config.requirements.fail_before_sqla_100
     def test_inline_exclude_constraint_case_sensitive(self):
         from sqlalchemy.dialects.postgresql import ExcludeConstraint
 
@@ -986,25 +973,13 @@ class PostgresqlAutogenRenderTest(TestBase):
         )
 
     def test_json_type(self):
-        if config.requirements.sqlalchemy_110.enabled:
-            eq_ignore_whitespace(
-                autogenerate.render._repr_type(JSON(), self.autogen_context),
-                "postgresql.JSON(astext_type=sa.Text())",
-            )
-        else:
-            eq_ignore_whitespace(
-                autogenerate.render._repr_type(JSON(), self.autogen_context),
-                "postgresql.JSON()",
-            )
+        eq_ignore_whitespace(
+            autogenerate.render._repr_type(JSON(), self.autogen_context),
+            "postgresql.JSON(astext_type=sa.Text())",
+        )
 
     def test_jsonb_type(self):
-        if config.requirements.sqlalchemy_110.enabled:
-            eq_ignore_whitespace(
-                autogenerate.render._repr_type(JSONB(), self.autogen_context),
-                "postgresql.JSONB(astext_type=sa.Text())",
-            )
-        else:
-            eq_ignore_whitespace(
-                autogenerate.render._repr_type(JSONB(), self.autogen_context),
-                "postgresql.JSONB()",
-            )
+        eq_ignore_whitespace(
+            autogenerate.render._repr_type(JSONB(), self.autogen_context),
+            "postgresql.JSONB(astext_type=sa.Text())",
+        )
diff --git a/tox.ini b/tox.ini
index bfe1d6a762ac7962b94b56b8147e291e32b9d69c..a6fd78c799b80415e1f80de9548932d63a6545d3 100644 (file)
--- a/tox.ini
+++ b/tox.ini
@@ -1,8 +1,6 @@
 [tox]
 
-# current mysqlclient fails with <=SQLA 0.9 on py3k due to
-# old unicode statements flag
-envlist = py{27,34,35,36,37}-sqla{10,11,12,13,master}, py{27}-sqla{079,084,09}
+envlist = py{27,34,35,36,37}-sqla{11,12,13,master}
 
 SQLA_REPO = {env:SQLA_REPO:git+https://github.com/sqlalchemy/sqlalchemy.git}
 
@@ -12,10 +10,6 @@ cov_args=--cov=alembic --cov-report term --cov-report xml
 deps=pytest!=3.9.1,!=3.9.2
      pytest-xdist
      mock
-     sqla079: {[tox]SQLA_REPO}@rel_0_7_9
-     sqla084: {[tox]SQLA_REPO}@rel_0_8_4
-     sqla09: {[tox]SQLA_REPO}@rel_0_9
-     sqla10: {[tox]SQLA_REPO}@rel_1_0
      sqla11: {[tox]SQLA_REPO}@rel_1_1
      sqla12: {[tox]SQLA_REPO}@rel_1_2
      sqla13: {[tox]SQLA_REPO}@rel_1_3