From 18ce4f9937c2d6753acbb054b4990c7da298a5d7 Mon Sep 17 00:00:00 2001 From: Federico Caselli Date: Sat, 18 Apr 2020 20:58:41 +0200 Subject: [PATCH] Deprecate unsupported dialects and dbapi - Deprecate dialects firebird and sybase. - Deprecate DBAPI - mxODBC for mssql - oursql for mysql - pygresql and py-postgresql for postgresql - Removed adodbapi DBAPI for mssql Fixes: #5189 Change-Id: Id9025f4f4de7e97d65aacd0eb4b0c21beb9a67b5 --- doc/build/changelog/unreleased_14/5189.rst | 10 +++ doc/build/dialects/index.rst | 9 +- doc/build/dialects/mssql.rst | 5 -- lib/sqlalchemy/connectors/mxodbc.py | 12 +++ lib/sqlalchemy/dialects/firebird/base.py | 15 +++- lib/sqlalchemy/dialects/mssql/__init__.py | 1 - lib/sqlalchemy/dialects/mssql/adodbapi.py | 90 ------------------- lib/sqlalchemy/dialects/mssql/mxodbc.py | 4 + lib/sqlalchemy/dialects/mysql/oursql.py | 10 +++ .../dialects/postgresql/pygresql.py | 11 +++ .../dialects/postgresql/pypostgresql.py | 16 ++++ lib/sqlalchemy/dialects/sqlite/pysqlcipher.py | 1 + lib/sqlalchemy/dialects/sybase/base.py | 11 +++ lib/sqlalchemy/dialects/sybase/mxodbc.py | 1 - lib/sqlalchemy/dialects/sybase/pyodbc.py | 5 +- lib/sqlalchemy/testing/warnings.py | 5 ++ test/dialect/mssql/test_engine.py | 27 ------ 17 files changed, 104 insertions(+), 129 deletions(-) create mode 100644 doc/build/changelog/unreleased_14/5189.rst delete mode 100644 lib/sqlalchemy/dialects/mssql/adodbapi.py diff --git a/doc/build/changelog/unreleased_14/5189.rst b/doc/build/changelog/unreleased_14/5189.rst new file mode 100644 index 0000000000..3a2c4bf8f6 --- /dev/null +++ b/doc/build/changelog/unreleased_14/5189.rst @@ -0,0 +1,10 @@ +.. change:: + :tags: dialects, deprecations + :tickets: 5189 + + Deprecate unsupported dialects and dbapi + - Deprecate dialects firefis and sybase. + - Deprecate DBAPI + - adodbapi and mxODBC for mssql + - oursql for mysql + - pygresql and py-postgresql for postgresql diff --git a/doc/build/dialects/index.rst b/doc/build/dialects/index.rst index 2d0755d28d..869c6a39cb 100644 --- a/doc/build/dialects/index.rst +++ b/doc/build/dialects/index.rst @@ -22,12 +22,12 @@ Included Dialects oracle mssql -Included, but not currently supported dialects ----------------------------------------------- +Deprecated, no longer supported dialects +---------------------------------------- The following dialects have implementations within SQLAlchemy, but they are not part of continuous integration testing nor are they actively developed. -These dialects may be removed in future major releases. +These dialects are deprecated and will be removed in future major releases. .. toctree:: :maxdepth: 1 @@ -62,6 +62,8 @@ Currently maintained external dialect projects for SQLAlchemy include: +---------------------------------------+-----------------------+ | Elasticsearch (readonly) | elasticsearch-dbapi_ | +---------------------------------------+-----------------------+ +| Firebird | sqlalchemy-firebird_ | ++---------------------------------------+-----------------------+ | Google BigQuery | pybigquery_ | +---------------------------------------+-----------------------+ | Google Sheets | gsheets_ | @@ -101,3 +103,4 @@ Currently maintained external dialect projects for SQLAlchemy include: .. _elasticsearch-dbapi: https://github.com/preset-io/elasticsearch-dbapi/ .. _pydruid: https://github.com/druid-io/pydruid .. _gsheets: https://github.com/betodealmeida/gsheets-db-api +.. _sqlalchemy-firebird: https://github.com/pauldex/sqlalchemy-firebird diff --git a/doc/build/dialects/mssql.rst b/doc/build/dialects/mssql.rst index 0ba4763b42..47bfdc52f4 100644 --- a/doc/build/dialects/mssql.rst +++ b/doc/build/dialects/mssql.rst @@ -124,8 +124,3 @@ pymssql ------- .. automodule:: sqlalchemy.dialects.mssql.pymssql - -AdoDBAPI --------- -.. automodule:: sqlalchemy.dialects.mssql.adodbapi - diff --git a/lib/sqlalchemy/connectors/mxodbc.py b/lib/sqlalchemy/connectors/mxodbc.py index 0a34cfe003..e243aba80f 100644 --- a/lib/sqlalchemy/connectors/mxodbc.py +++ b/lib/sqlalchemy/connectors/mxodbc.py @@ -17,6 +17,10 @@ possible for this to be used on other database platforms. For more info on mxODBC, see http://www.egenix.com/ +.. deprecated:: 1.4 The mxODBC DBAPI is deprecated and will be removed + in a future version. Please use one of the supported DBAPIs to + connect to mssql. + """ import re @@ -24,6 +28,7 @@ import sys import warnings from . import Connector +from ..util import warn_deprecated class MxODBCConnector(Connector): @@ -50,6 +55,13 @@ class MxODBCConnector(Connector): from mx.ODBC import iODBC as Module else: raise ImportError("Unrecognized platform for mxODBC import") + + warn_deprecated( + "The mxODBC DBAPI is deprecated and will be removed" + "in a future version. Please use one of the supported DBAPIs to" + "connect to mssql.", + version="1.4", + ) return Module @classmethod diff --git a/lib/sqlalchemy/dialects/firebird/base.py b/lib/sqlalchemy/dialects/firebird/base.py index 5779ac8858..b7260403af 100644 --- a/lib/sqlalchemy/dialects/firebird/base.py +++ b/lib/sqlalchemy/dialects/firebird/base.py @@ -16,6 +16,10 @@ r""" dialect is not tested within continuous integration and is likely to have many issues and caveats not currently handled. +.. deprecated:: 1.4 This dialect is deprecated and will be removed + in a future version. This dialect is superseded by the external + version available at external-dialect_. + Firebird Dialects ----------------- @@ -73,7 +77,7 @@ the SQLAlchemy ``returning()`` method, such as:: .. _dialects: http://mc-computing.com/Databases/Firebird/SQL_Dialect.html - +.. _external-dialect: https://github.com/pauldex/sqlalchemy-firebird """ import datetime @@ -648,6 +652,15 @@ class FBDialect(default.DefaultDialect): # first connect _version_two = True + def __init__(self, *args, **kwargs): + util.warn_deprecated( + "The firebird dialect is deprecated and will be removed " + "in a future version. This dialect is superseded by the external " + "dialect https://github.com/pauldex/sqlalchemy-firebird.", + version="1.4", + ) + super(FBDialect, self).__init__(*args, **kwargs) + def initialize(self, connection): super(FBDialect, self).initialize(connection) self._version_two = ( diff --git a/lib/sqlalchemy/dialects/mssql/__init__.py b/lib/sqlalchemy/dialects/mssql/__init__.py index 67830affe3..283c92eca5 100644 --- a/lib/sqlalchemy/dialects/mssql/__init__.py +++ b/lib/sqlalchemy/dialects/mssql/__init__.py @@ -5,7 +5,6 @@ # This module is part of SQLAlchemy and is released under # the MIT License: http://www.opensource.org/licenses/mit-license.php -from . import adodbapi # noqa from . import base # noqa from . import mxodbc # noqa from . import pymssql # noqa diff --git a/lib/sqlalchemy/dialects/mssql/adodbapi.py b/lib/sqlalchemy/dialects/mssql/adodbapi.py deleted file mode 100644 index 15f1b65118..0000000000 --- a/lib/sqlalchemy/dialects/mssql/adodbapi.py +++ /dev/null @@ -1,90 +0,0 @@ -# mssql/adodbapi.py -# Copyright (C) 2005-2020 the SQLAlchemy authors and contributors -# -# -# This module is part of SQLAlchemy and is released under -# the MIT License: http://www.opensource.org/licenses/mit-license.php - -""" -.. dialect:: mssql+adodbapi - :name: adodbapi - :dbapi: adodbapi - :connectstring: mssql+adodbapi://:@ - :url: http://adodbapi.sourceforge.net/ - -.. note:: - - The adodbapi dialect is not implemented in SQLAlchemy versions 0.6 and - above at this time. - -""" -import datetime -import sys - -from sqlalchemy import types as sqltypes -from sqlalchemy import util -from sqlalchemy.dialects.mssql.base import MSDateTime -from sqlalchemy.dialects.mssql.base import MSDialect - - -class MSDateTime_adodbapi(MSDateTime): - def result_processor(self, dialect, coltype): - def process(value): - # adodbapi will return datetimes with empty time - # values as datetime.date() objects. - # Promote them back to full datetime.datetime() - if type(value) is datetime.date: - return datetime.datetime(value.year, value.month, value.day) - return value - - return process - - -class MSDialect_adodbapi(MSDialect): - supports_sane_rowcount = True - supports_sane_multi_rowcount = True - supports_unicode = sys.maxunicode == 65535 - supports_unicode_statements = True - driver = "adodbapi" - - @classmethod - def import_dbapi(cls): - import adodbapi as module - - return module - - colspecs = util.update_copy( - MSDialect.colspecs, {sqltypes.DateTime: MSDateTime_adodbapi} - ) - - def create_connect_args(self, url): - def check_quote(token): - if ";" in str(token): - token = "'%s'" % token - return token - - keys = dict((k, check_quote(v)) for k, v in url.query.items()) - - connectors = ["Provider=SQLOLEDB"] - if "port" in keys: - connectors.append( - "Data Source=%s, %s" % (keys.get("host"), keys.get("port")) - ) - else: - connectors.append("Data Source=%s" % keys.get("host")) - connectors.append("Initial Catalog=%s" % keys.get("database")) - user = keys.get("user") - if user: - connectors.append("User Id=%s" % user) - connectors.append("Password=%s" % keys.get("password", "")) - else: - connectors.append("Integrated Security=SSPI") - return [[";".join(connectors)], {}] - - def is_disconnect(self, e, connection, cursor): - return isinstance( - e, self.dbapi.adodbapi.DatabaseError - ) and "'connection failure'" in str(e) - - -dialect = MSDialect_adodbapi diff --git a/lib/sqlalchemy/dialects/mssql/mxodbc.py b/lib/sqlalchemy/dialects/mssql/mxodbc.py index 5df1351d2b..998153d7a7 100644 --- a/lib/sqlalchemy/dialects/mssql/mxodbc.py +++ b/lib/sqlalchemy/dialects/mssql/mxodbc.py @@ -12,6 +12,10 @@ :connectstring: mssql+mxodbc://:@ :url: http://www.egenix.com/ +.. deprecated:: 1.4 The mxODBC DBAPI is deprecated and will be removed + in a future version. Please use one of the supported DBAPIs to + connect to mssql. + Execution Modes --------------- diff --git a/lib/sqlalchemy/dialects/mysql/oursql.py b/lib/sqlalchemy/dialects/mysql/oursql.py index d7334711b7..7c2b220b42 100644 --- a/lib/sqlalchemy/dialects/mysql/oursql.py +++ b/lib/sqlalchemy/dialects/mysql/oursql.py @@ -19,6 +19,10 @@ and is **not tested as part of SQLAlchemy's continuous integration**. The recommended MySQL dialects are mysqlclient and PyMySQL. +.. deprecated:: 1.4 The OurSQL DBAPI is deprecated and will be removed + in a future version. Please use one of the supported DBAPIs to + connect to mysql. + Unicode ------- @@ -68,6 +72,12 @@ class MySQLDialect_oursql(MySQLDialect): @classmethod def dbapi(cls): + util.warn_deprecated( + "The OurSQL DBAPI is deprecated and will be removed " + "in a future version. Please use one of the supported DBAPIs to " + "connect to mysql.", + version="1.4", + ) return __import__("oursql") def do_execute(self, cursor, statement, parameters, context=None): diff --git a/lib/sqlalchemy/dialects/postgresql/pygresql.py b/lib/sqlalchemy/dialects/postgresql/pygresql.py index 8666f41725..8dbd23fe94 100644 --- a/lib/sqlalchemy/dialects/postgresql/pygresql.py +++ b/lib/sqlalchemy/dialects/postgresql/pygresql.py @@ -17,6 +17,10 @@ integration** and may have unresolved issues. The recommended PostgreSQL dialect is psycopg2. +.. deprecated:: 1.4 The pygresql DBAPI is deprecated and will be removed + in a future version. Please use one of the supported DBAPIs to + connect to PostgreSQL. + """ # noqa import decimal @@ -197,6 +201,13 @@ class PGDialect_pygresql(PGDialect): def dbapi(cls): import pgdb + util.warn_deprecated( + "The pygresql DBAPI is deprecated and will be removed " + "in a future version. Please use one of the supported DBAPIs to " + "connect to PostgreSQL.", + version="1.4", + ) + return pgdb colspecs = util.update_copy( diff --git a/lib/sqlalchemy/dialects/postgresql/pypostgresql.py b/lib/sqlalchemy/dialects/postgresql/pypostgresql.py index 289a9a0971..bd015a5b8a 100644 --- a/lib/sqlalchemy/dialects/postgresql/pypostgresql.py +++ b/lib/sqlalchemy/dialects/postgresql/pypostgresql.py @@ -17,6 +17,13 @@ integration** and may have unresolved issues. The recommended PostgreSQL driver is psycopg2. +.. deprecated:: 1.4 The py-postgresql DBAPI is deprecated and will be removed + in a future version. This DBAPI is superseded by the external + version available at external-dialect_. Please use the external version or + one of the supported DBAPIs to connect to PostgreSQL. + +.. TODO update link +.. _external-dialect: https://github.com/PyGreSQL """ # noqa @@ -69,6 +76,15 @@ class PGDialect_pypostgresql(PGDialect): def dbapi(cls): from postgresql.driver import dbapi20 + # TODO update link + util.warn_deprecated( + "The py-postgresql DBAPI is deprecated and will be removed " + "in a future version. This DBAPI is superseded by the external" + "version available at https://github.com/PyGreSQL. Please " + "use one of the supported DBAPIs to connect to PostgreSQL.", + version="1.4", + ) + return dbapi20 _DBAPI_ERROR_NAMES = [ diff --git a/lib/sqlalchemy/dialects/sqlite/pysqlcipher.py b/lib/sqlalchemy/dialects/sqlite/pysqlcipher.py index 213cc55f2c..8f72e12fa3 100644 --- a/lib/sqlalchemy/dialects/sqlite/pysqlcipher.py +++ b/lib/sqlalchemy/dialects/sqlite/pysqlcipher.py @@ -99,6 +99,7 @@ class SQLiteDialect_pysqlcipher(SQLiteDialect_pysqlite): from pysqlcipher3 import dbapi2 as sqlcipher except ImportError: raise e + return sqlcipher @classmethod diff --git a/lib/sqlalchemy/dialects/sybase/base.py b/lib/sqlalchemy/dialects/sybase/base.py index 3920aff055..634cf0da4e 100644 --- a/lib/sqlalchemy/dialects/sybase/base.py +++ b/lib/sqlalchemy/dialects/sybase/base.py @@ -20,6 +20,9 @@ dialect is not tested within continuous integration and is likely to have many issues and caveats not currently handled. +.. deprecated:: 1.4 The Sybase dialect is deprecated and will be removed + in a future version. + """ import re @@ -648,6 +651,14 @@ class SybaseDialect(default.DefaultDialect): construct_arguments = [] + def __init__(self, *args, **kwargs): + util.warn_deprecated( + "The Sybase dialect is deprecated and will be removed " + "in a future version.", + version="1.4", + ) + super(SybaseDialect, self).__init__(*args, **kwargs) + def _get_default_schema_name(self, connection): return connection.scalar( text("SELECT user_name() as user_name").columns(username=Unicode) diff --git a/lib/sqlalchemy/dialects/sybase/mxodbc.py b/lib/sqlalchemy/dialects/sybase/mxodbc.py index 12dcc2cf7b..d234823578 100644 --- a/lib/sqlalchemy/dialects/sybase/mxodbc.py +++ b/lib/sqlalchemy/dialects/sybase/mxodbc.py @@ -16,7 +16,6 @@ This dialect is a stub only and is likely non functional at this time. - """ from sqlalchemy.connectors.mxodbc import MxODBCConnector from sqlalchemy.dialects.sybase.base import SybaseDialect diff --git a/lib/sqlalchemy/dialects/sybase/pyodbc.py b/lib/sqlalchemy/dialects/sybase/pyodbc.py index ff166feb10..d11aae1c5d 100644 --- a/lib/sqlalchemy/dialects/sybase/pyodbc.py +++ b/lib/sqlalchemy/dialects/sybase/pyodbc.py @@ -12,7 +12,6 @@ :connectstring: sybase+pyodbc://:@[/] :url: http://pypi.python.org/pypi/pyodbc/ - Unicode Support --------------- @@ -81,5 +80,9 @@ class SybaseDialect_pyodbc(PyODBCConnector, SybaseDialect): colspecs = {sqltypes.Numeric: _SybNumeric_pyodbc} + @classmethod + def dbapi(cls): + return PyODBCConnector.dbapi() + dialect = SybaseDialect_pyodbc diff --git a/lib/sqlalchemy/testing/warnings.py b/lib/sqlalchemy/testing/warnings.py index 39cffbf158..3850f65c8f 100644 --- a/lib/sqlalchemy/testing/warnings.py +++ b/lib/sqlalchemy/testing/warnings.py @@ -40,6 +40,11 @@ def setup_filters(): category=sa_exc.SADeprecationWarning, message=r".*\(deprecated since: 2.0\)$", ) + warnings.filterwarnings( + "ignore", + category=sa_exc.SADeprecationWarning, + message=r"^The (Sybase|firebird) dialect is deprecated and will be", + ) try: import pytest diff --git a/test/dialect/mssql/test_engine.py b/test/dialect/mssql/test_engine.py index 97e924feda..00babf8ce7 100644 --- a/test/dialect/mssql/test_engine.py +++ b/test/dialect/mssql/test_engine.py @@ -7,7 +7,6 @@ from sqlalchemy import Integer from sqlalchemy import String from sqlalchemy import Table from sqlalchemy import testing -from sqlalchemy.dialects.mssql import adodbapi from sqlalchemy.dialects.mssql import base from sqlalchemy.dialects.mssql import pymssql from sqlalchemy.dialects.mssql import pyodbc @@ -223,32 +222,6 @@ class ParseConnectTest(fixtures.TestBase): connection, ) - def test_adodbapi_token_injection(self): - token1 = "someuser%3BPORT%3D50001" - token2 = "somepw%3BPORT%3D50001" - token3 = "somehost%3BPORT%3D50001" - token4 = "someport%3BPORT%3D50001" - - # this URL format is all wrong - u = url.make_url( - "mssql+adodbapi://@/?user=%s&password=%s&host=%s&port=%s" - % (token1, token2, token3, token4) - ) - dialect = adodbapi.dialect() - connection = dialect.create_connect_args(u) - eq_( - [ - [ - "Provider=SQLOLEDB;" - "Data Source='somehost;PORT=50001', 'someport;PORT=50001';" - "Initial Catalog=None;User Id='someuser;PORT=50001';" - "Password='somepw;PORT=50001'" - ], - {}, - ], - connection, - ) - def test_pymssql_port_setting(self): dialect = pymssql.dialect() -- 2.39.5