From: Gord Thompson Date: Mon, 8 Nov 2021 18:03:54 +0000 (-0700) Subject: De-emphasize notion of "default driver" (DBAPI) X-Git-Tag: rel_2_0_0b1~662 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=bd1be0b7e0ecd76bdf6d26fd11cc42e1a473b319;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git De-emphasize notion of "default driver" (DBAPI) Fixes: #6960 Even though a default driver still exists for each dialect, remove most usages of `dialect://` to encourage users to explicitly specify `dialect+driver://` Change-Id: I0ad42167582df509138fca64996bbb53e379b1af --- diff --git a/README.unittests.rst b/README.unittests.rst index 37238b7a1e..32b7446123 100644 --- a/README.unittests.rst +++ b/README.unittests.rst @@ -83,17 +83,29 @@ a pre-set URL. These can be seen using --dbs:: $ pytest --dbs Available --db options (use --dburi to override) + aiomysql mysql+aiomysql://scott:tiger@127.0.0.1:3306/test?charset=utf8mb4 + aiomysql_fallback mysql+aiomysql://scott:tiger@127.0.0.1:3306/test?charset=utf8mb4&async_fallback=true + aiosqlite sqlite+aiosqlite:///:memory: + aiosqlite_file sqlite+aiosqlite:///async_querytest.db + asyncmy mysql+asyncmy://scott:tiger@127.0.0.1:3306/test?charset=utf8mb4 + asyncmy_fallback mysql+asyncmy://scott:tiger@127.0.0.1:3306/test?charset=utf8mb4&async_fallback=true + asyncpg postgresql+asyncpg://scott:tiger@192.168.0.199/test + asyncpg_async_fallback postgresql+asyncpg://scott:tiger@192.168.0.199/test?async_fallback=true + asyncpg_fallback postgresql+asyncpg://scott:tiger@127.0.0.1:5432/test?async_fallback=true default sqlite:///:memory: - mariadb mariadb://scott:tiger@192.168.0.199:3307/test - mssql mssql+pyodbc://scott:tiger^5HHH@mssql2017:1433/test?driver=ODBC+Driver+13+for+SQL+Server + docker_mssql mssql+pymssql://scott:tiger^5HHH@127.0.0.1:1433/test + mariadb mariadb+mysqldb://scott:tiger@127.0.0.1:3306/test + mssql mssql+pyodbc://scott:tiger^5HHH@localhost:1433/test?driver=ODBC+Driver+17+for+SQL+Server + mssql_199 mssql+pyodbc://scott:tiger^5HHH@192.168.0.199:1433/test?driver=ODBC+Driver+17+for+SQL+Server mssql_pymssql mssql+pymssql://scott:tiger@ms_2008 - mysql mysql://scott:tiger@127.0.0.1:3306/test?charset=utf8mb4 - oracle oracle://scott:tiger@127.0.0.1:1521 - oracle8 oracle://scott:tiger@127.0.0.1:1521/?use_ansi=0 + mysql mysql+mysqldb://scott:tiger@127.0.0.1:3306/test?charset=utf8mb4 + oracle oracle+cx_oracle://scott:tiger@127.0.0.1:1521 + oracle8 oracle+cx_oracle://scott:tiger@127.0.0.1:1521/?use_ansi=0 pg8000 postgresql+pg8000://scott:tiger@127.0.0.1:5432/test - postgresql postgresql://scott:tiger@127.0.0.1:5432/test + postgresql postgresql+psycopg2://scott:tiger@192.168.0.199/test postgresql_psycopg2cffi postgresql+psycopg2cffi://scott:tiger@127.0.0.1:5432/test pymysql mysql+pymysql://scott:tiger@127.0.0.1:3306/test?charset=utf8mb4 + pysqlcipher_file sqlite+pysqlcipher://:test@/querytest.db.enc sqlite sqlite:///:memory: sqlite_file sqlite:///querytest.db @@ -110,7 +122,7 @@ creating a new file called ``test.cfg`` and adding your own ``[db]`` section:: # test.cfg file [db] - my_postgresql=postgresql://username:pass@hostname/dbname + my_postgresql=postgresql+psycopg2://username:pass@hostname/dbname Above, we can now run the tests with ``my_postgresql``:: @@ -121,7 +133,7 @@ with the tox runner also:: # test.cfg file [db] - postgresql=postgresql://username:pass@hostname/dbname + postgresql=postgresql+psycopg2://username:pass@hostname/dbname Now when we run ``tox -e py27-postgresql``, it will use our custom URL instead of the fixed one in setup.cfg. diff --git a/doc/build/changelog/migration_20.rst b/doc/build/changelog/migration_20.rst index f2752b3def..afca522df3 100644 --- a/doc/build/changelog/migration_20.rst +++ b/doc/build/changelog/migration_20.rst @@ -318,7 +318,7 @@ The new engine is described at :class:`_future.Engine` which delivers a new from sqlalchemy import create_engine - engine = create_engine("postgresql:///") + engine = create_engine("postgresql+psycopg2:///") with engine.connect() as conn: conn.execute(text("insert into table (x) values (:some_x)"), {"some_x": 10}) diff --git a/doc/build/core/connections.rst b/doc/build/core/connections.rst index d485008d8a..0cf3c2e2a3 100644 --- a/doc/build/core/connections.rst +++ b/doc/build/core/connections.rst @@ -21,7 +21,7 @@ Basic Usage Recall from :doc:`/core/engines` that an :class:`_engine.Engine` is created via the :func:`_sa.create_engine` call:: - engine = create_engine('mysql://scott:tiger@localhost/test') + engine = create_engine('mysql+mysqldb://scott:tiger@localhost/test') The typical usage of :func:`_sa.create_engine` is once per particular database URL, held globally for the lifetime of a single application process. A single @@ -328,7 +328,7 @@ parameter to :func:`_sa.create_engine`:: from sqlalchemy import create_engine eng = create_engine( - "postgresql://scott:tiger@localhost/test", + "postgresql+psycopg2://scott:tiger@localhost/test", execution_options={ "isolation_level": "REPEATABLE READ" } @@ -348,7 +348,7 @@ separated off from the main engine:: from sqlalchemy import create_engine - eng = create_engine("postgresql://scott:tiger@localhost/test") + eng = create_engine("postgresql+psycopg2://scott:tiger@localhost/test") autocommit_engine = eng.execution_options(isolation_level="AUTOCOMMIT") @@ -789,7 +789,7 @@ used items when the size of the cache reaches a certain threshold. The size of this cache defaults to 500 and may be configured using the :paramref:`_sa.create_engine.query_cache_size` parameter:: - engine = create_engine("postgresql://scott:tiger@localhost/test", query_cache_size=1200) + engine = create_engine("postgresql+psycopg2://scott:tiger@localhost/test", query_cache_size=1200) The size of the cache can grow to be a factor of 150% of the size given, before it's pruned back down to the target size. A cache of size 1200 above can therefore diff --git a/doc/build/core/custom_types.rst b/doc/build/core/custom_types.rst index 6ec31ce089..e7564957ed 100644 --- a/doc/build/core/custom_types.rst +++ b/doc/build/core/custom_types.rst @@ -446,7 +446,7 @@ transparently:: PGPString("this is my passphrase")), ) - engine = create_engine("postgresql://scott:tiger@localhost/test", echo=True) + engine = create_engine("postgresql+psycopg2://scott:tiger@localhost/test", echo=True) with engine.begin() as conn: metadata_obj.create_all(conn) diff --git a/doc/build/core/engines.rst b/doc/build/core/engines.rst index cb114ef7f9..c277e7b237 100644 --- a/doc/build/core/engines.rst +++ b/doc/build/core/engines.rst @@ -22,7 +22,7 @@ Creating an engine is just a matter of issuing a single call, :func:`_sa.create_engine()`:: from sqlalchemy import create_engine - engine = create_engine('postgresql://scott:tiger@localhost:5432/mydatabase') + engine = create_engine('postgresql+psycopg2://scott:tiger@localhost:5432/mydatabase') The above engine creates a :class:`.Dialect` object tailored towards PostgreSQL, as well as a :class:`_pool.Pool` object which will establish a DBAPI @@ -243,7 +243,7 @@ Engine Creation API for keys and either strings or tuples of strings for values, e.g.:: >>> from sqlalchemy.engine import make_url - >>> url = make_url("postgresql://user:pass@host/dbname?alt_host=host1&alt_host=host2&ssl_cipher=%2Fpath%2Fto%2Fcrt") + >>> url = make_url("postgresql+psycopg2://user:pass@host/dbname?alt_host=host1&alt_host=host2&ssl_cipher=%2Fpath%2Fto%2Fcrt") >>> url.query immutabledict({'alt_host': ('host1', 'host2'), 'ssl_cipher': '/path/to/crt'}) @@ -360,7 +360,7 @@ underlying implementation the connection:: engine = create_engine( - "postgresql://user:pass@hostname/dbname", + "postgresql+psycopg2://user:pass@hostname/dbname", connect_args={"connection_factory": MyConnectionFactory} ) @@ -387,7 +387,7 @@ collections can then be modified in place to alter how they are used:: from sqlalchemy import event - engine = create_engine("postgresql://user:pass@hostname/dbname") + engine = create_engine("postgresql+psycopg2://user:pass@hostname/dbname") @event.listens_for(engine, "do_connect") def receive_do_connect(dialect, conn_rec, cargs, cparams): @@ -406,7 +406,7 @@ parameter, this could be implemented as:: from sqlalchemy import event - engine = create_engine("postgresql://user@hostname/dbname") + engine = create_engine("postgresql+psycopg2://user@hostname/dbname") @event.listens_for(engine, "do_connect") def provide_token(dialect, conn_rec, cargs, cparams): @@ -430,7 +430,7 @@ SQLAlchemy:: from sqlalchemy import event engine = create_engine( - "postgresql://user:pass@hostname/dbname" + "postgresql+psycopg2://user:pass@hostname/dbname" ) @event.listens_for(engine, "connect") @@ -450,7 +450,7 @@ and returning it:: from sqlalchemy import event engine = create_engine( - "postgresql://user:pass@hostname/dbname" + "postgresql+psycopg2://user:pass@hostname/dbname" ) @event.listens_for(engine, "do_connect") diff --git a/doc/build/core/event.rst b/doc/build/core/event.rst index af4e33ba9a..0f1f87cb24 100644 --- a/doc/build/core/event.rst +++ b/doc/build/core/event.rst @@ -99,7 +99,7 @@ and objects:: return psycopg2.connect(user='ed', host='127.0.0.1', dbname='test') my_pool = QueuePool(connect) - my_engine = create_engine('postgresql://ed@localhost/test') + my_engine = create_engine('postgresql+psycopg2://ed@localhost/test') # associate listener with all instances of Pool listen(Pool, 'connect', my_on_connect) diff --git a/doc/build/core/pooling.rst b/doc/build/core/pooling.rst index d0629a4a16..3e13d9ab97 100644 --- a/doc/build/core/pooling.rst +++ b/doc/build/core/pooling.rst @@ -35,7 +35,7 @@ directly to :func:`~sqlalchemy.create_engine` as keyword arguments: ``pool_size``, ``max_overflow``, ``pool_recycle`` and ``pool_timeout``. For example:: - engine = create_engine('postgresql://me@localhost/mydb', + engine = create_engine('postgresql+psycopg2://me@localhost/mydb', pool_size=20, max_overflow=0) In the case of SQLite, the :class:`.SingletonThreadPool` or @@ -358,7 +358,7 @@ such as MySQL that automatically close connections that have been stale after a period of time:: from sqlalchemy import create_engine - e = create_engine("mysql://scott:tiger@localhost/test", pool_recycle=3600) + e = create_engine("mysql+mysqldb://scott:tiger@localhost/test", pool_recycle=3600) Above, any DBAPI connection that has been open for more than one hour will be invalidated and replaced, upon next checkout. Note that the invalidation **only** occurs during checkout - not on @@ -469,7 +469,7 @@ are three general approaches to this: more than once:: from sqlalchemy.pool import NullPool - engine = create_engine("mysql://user:pass@host/dbname", poolclass=NullPool) + engine = create_engine("mysql+mysqldb://user:pass@host/dbname", poolclass=NullPool) 2. Call :meth:`_engine.Engine.dispose` on any given :class:`_engine.Engine` as @@ -480,7 +480,7 @@ are three general approaches to this: single call to :meth:`_engine.Engine.dispose` will ensure any remaining connections are flushed. **This is the recommended approach**:: - engine = create_engine("mysql://user:pass@host/dbname") + engine = create_engine("mysql+mysqldb://user:pass@host/dbname") def run_in_process(): # process starts. ensure engine.dispose() is called just once diff --git a/doc/build/core/reflection.rst b/doc/build/core/reflection.rst index 0660823eb0..796bd414f9 100644 --- a/doc/build/core/reflection.rst +++ b/doc/build/core/reflection.rst @@ -182,7 +182,7 @@ and options: .. sourcecode:: pycon+sql >>> from sqlalchemy import MetaData, Table, create_engine - >>> mysql_engine = create_engine("mysql://scott:tiger@localhost/test") + >>> mysql_engine = create_engine("mysql+mysqldb://scott:tiger@localhost/test") >>> metadata_obj = MetaData() >>> my_mysql_table = Table("my_table", metadata_obj, autoload_with=mysql_engine) @@ -233,7 +233,7 @@ We now get a new :class:`_schema.Table` that is generic and uses .. sourcecode:: pycon+sql - >>> pg_engine = create_engine("postgresql://scott:tiger@localhost/test", echo=True) + >>> pg_engine = create_engine("postgresql+psycopg2://scott:tiger@localhost/test", echo=True) >>> my_generic_table.create(pg_engine) {opensql}CREATE TABLE my_table ( id SERIAL NOT NULL, diff --git a/doc/build/errors.rst b/doc/build/errors.rst index 2318d39b03..41802240ac 100644 --- a/doc/build/errors.rst +++ b/doc/build/errors.rst @@ -421,7 +421,7 @@ familiar with. **pool size plus the max overflow**. That means if you have configured your engine as:: - engine = create_engine("mysql://u:p@host/db", pool_size=10, max_overflow=20) + engine = create_engine("mysql+mysqldb://u:p@host/db", pool_size=10, max_overflow=20) The above :class:`_engine.Engine` will allow **at most 30 connections** to be in play at any time, not including connections that were detached from the diff --git a/doc/build/faq/connections.rst b/doc/build/faq/connections.rst index 1bee24c324..f8c4e5bcaa 100644 --- a/doc/build/faq/connections.rst +++ b/doc/build/faq/connections.rst @@ -27,13 +27,13 @@ How do I pass custom connect arguments to my database API? The :func:`_sa.create_engine` call accepts additional arguments either directly via the ``connect_args`` keyword argument:: - e = create_engine("mysql://scott:tiger@localhost/test", + e = create_engine("mysql+mysqldb://scott:tiger@localhost/test", connect_args={"encoding": "utf8"}) Or for basic string and integer arguments, they can usually be specified in the query string of the URL:: - e = create_engine("mysql://scott:tiger@localhost/test?encoding=utf8") + e = create_engine("mysql+mysqldb://scott:tiger@localhost/test?encoding=utf8") .. seealso:: @@ -312,7 +312,7 @@ using the following proof of concept script. Once run, it will emit a if __name__ == "__main__": - engine = create_engine("mysql://scott:tiger@localhost/test", echo_pool=True) + engine = create_engine("mysql+mysqldb://scott:tiger@localhost/test", echo_pool=True) def do_a_thing(engine): with engine.begin() as conn: @@ -322,7 +322,7 @@ using the following proof of concept script. Once run, it will emit a e = reconnecting_engine( create_engine( - "mysql://scott:tiger@localhost/test", echo_pool=True + "mysql+mysqldb://scott:tiger@localhost/test", echo_pool=True ), num_retries=5, retry_interval=2, @@ -379,7 +379,7 @@ configured using ``reset_on_return``:: from sqlalchemy import create_engine from sqlalchemy.pool import QueuePool - engine = create_engine('mysql://scott:tiger@localhost/myisam_database', pool=QueuePool(reset_on_return=False)) + engine = create_engine('mysql+mysqldb://scott:tiger@localhost/myisam_database', pool=QueuePool(reset_on_return=False)) I'm on SQL Server - how do I turn those ROLLBACKs into COMMITs? ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -388,7 +388,7 @@ I'm on SQL Server - how do I turn those ROLLBACKs into COMMITs? to ``True``, ``False``, and ``None``. Setting to ``commit`` will cause a COMMIT as any connection is returned to the pool:: - engine = create_engine('mssql://scott:tiger@mydsn', pool=QueuePool(reset_on_return='commit')) + engine = create_engine('mssql+pyodbc://scott:tiger@mydsn', pool=QueuePool(reset_on_return='commit')) I am using multiple connections with a SQLite database (typically to test transaction operation), and my test program is not working! diff --git a/doc/build/faq/metadata_schema.rst b/doc/build/faq/metadata_schema.rst index 2556db60c1..ab879b0aec 100644 --- a/doc/build/faq/metadata_schema.rst +++ b/doc/build/faq/metadata_schema.rst @@ -90,7 +90,7 @@ metadata creation sequence as a string, using this recipe:: def dump(sql, *multiparams, **params): print(sql.compile(dialect=engine.dialect)) - engine = create_mock_engine('postgresql://', dump) + engine = create_mock_engine('postgresql+psycopg2://', dump) metadata_obj.create_all(engine, checkfirst=False) The `Alembic `_ tool also supports diff --git a/doc/build/glossary.rst b/doc/build/glossary.rst index 88980195be..57c0b2c90e 100644 --- a/doc/build/glossary.rst +++ b/doc/build/glossary.rst @@ -37,7 +37,7 @@ Glossary from sqlalchemy.orm import sessionmaker - engine = create_engine("mysql://user:pass@host/dbname", future=True) + engine = create_engine("mysql+mysqldb://user:pass@host/dbname", future=True) Session = sessionmaker(bind=engine, future=True) **ORM Queries in 2.0 style** diff --git a/doc/build/orm/declarative_tables.rst b/doc/build/orm/declarative_tables.rst index e935193c7d..3c28ee4e47 100644 --- a/doc/build/orm/declarative_tables.rst +++ b/doc/build/orm/declarative_tables.rst @@ -337,7 +337,7 @@ use a declarative hybrid mapping, passing the :paramref:`_schema.Table.autoload_with` parameter to the :class:`_schema.Table`:: - engine = create_engine("postgresql://user:pass@hostname/my_existing_database") + engine = create_engine("postgresql+psycopg2://user:pass@hostname/my_existing_database") class MyClass(Base): __table__ = Table( @@ -387,7 +387,7 @@ the ``Reflected.prepare`` method is called. The above mapping is not complete until we do so, given an :class:`_engine.Engine`:: - engine = create_engine("postgresql://user:pass@hostname/my_existing_database") + engine = create_engine("postgresql+psycopg2://user:pass@hostname/my_existing_database") Reflected.prepare(engine) The purpose of the ``Reflected`` class is to define the scope at which diff --git a/doc/build/orm/persistence_techniques.rst b/doc/build/orm/persistence_techniques.rst index 38f289058b..18bb984cdd 100644 --- a/doc/build/orm/persistence_techniques.rst +++ b/doc/build/orm/persistence_techniques.rst @@ -49,7 +49,7 @@ part of the object's primary key:: pk = Column(Integer, primary_key=True) bar = Column(Integer) - e = create_engine("postgresql://scott:tiger@localhost/test", echo=True) + e = create_engine("postgresql+psycopg2://scott:tiger@localhost/test", echo=True) Base.metadata.create_all(e) session = Session(e) @@ -663,8 +663,8 @@ The dictionary is consulted whenever the :class:`.Session` needs to emit SQL on behalf of a particular kind of mapped class in order to locate the appropriate source of database connectivity:: - engine1 = create_engine('postgresql://db1') - engine2 = create_engine('postgresql://db2') + engine1 = create_engine('postgresql+psycopg2://db1') + engine2 = create_engine('postgresql+psycopg2://db2') Session = sessionmaker() diff --git a/doc/build/orm/session_basics.rst b/doc/build/orm/session_basics.rst index a4faed69db..8102832d20 100644 --- a/doc/build/orm/session_basics.rst +++ b/doc/build/orm/session_basics.rst @@ -61,7 +61,7 @@ may look like:: # an Engine, which the Session will use for connection # resources - engine = create_engine('postgresql://scott:tiger@localhost/') + engine = create_engine('postgresql+psycopg2://scott:tiger@localhost/') # create session and add objects with Session(engine) as session: @@ -144,7 +144,7 @@ scope, the :class:`_orm.sessionmaker` can provide a factory for # an Engine, which the Session will use for connection # resources, typically in module scope - engine = create_engine('postgresql://scott:tiger@localhost/') + engine = create_engine('postgresql+psycopg2://scott:tiger@localhost/') # a sessionmaker(), also in the same scope as the engine Session = sessionmaker(engine) @@ -169,7 +169,7 @@ and also maintains a begin/commit/rollback block:: # an Engine, which the Session will use for connection # resources - engine = create_engine('postgresql://scott:tiger@localhost/') + engine = create_engine('postgresql+psycopg2://scott:tiger@localhost/') # a sessionmaker(), also in the same scope as the engine Session = sessionmaker(engine) diff --git a/doc/build/orm/session_transaction.rst b/doc/build/orm/session_transaction.rst index 199e76b43c..465668c1b5 100644 --- a/doc/build/orm/session_transaction.rst +++ b/doc/build/orm/session_transaction.rst @@ -216,7 +216,7 @@ methods. Using SQLAlchemy 2.0-style operation, these methods affect the Engine:: - engine = create_engine("postgresql://user:pass@host/dbname", future=True) + engine = create_engine("postgresql+psycopg2://user:pass@host/dbname", future=True) with engine.connect() as conn: conn.execute( @@ -252,7 +252,7 @@ that will maintain a begin/commit/rollback context for that object. Engine:: - engine = create_engine("postgresql://user:pass@host/dbname", future=True) + engine = create_engine("postgresql+psycopg2://user:pass@host/dbname", future=True) with engine.begin() as conn: conn.execute( @@ -290,7 +290,7 @@ specific behavior that is reversed from the 1.x series. Engine:: - engine = create_engine("postgresql://user:pass@host/dbname", future=True) + engine = create_engine("postgresql+psycopg2://user:pass@host/dbname", future=True) with engine.begin() as conn: savepoint = conn.begin_nested() @@ -383,8 +383,8 @@ also :meth:`_orm.Session.prepare` the session for interacting with transactions not managed by SQLAlchemy. To use two phase transactions set the flag ``twophase=True`` on the session:: - engine1 = create_engine('postgresql://db1') - engine2 = create_engine('postgresql://db2') + engine1 = create_engine('postgresql+psycopg2://db1') + engine2 = create_engine('postgresql+psycopg2://db2') Session = sessionmaker(twophase=True) @@ -448,7 +448,7 @@ in all cases, which is then used as the source of connectivity for a from sqlalchemy.orm import sessionmaker eng = create_engine( - "postgresql://scott:tiger@localhost/test", + "postgresql+psycopg2://scott:tiger@localhost/test", isolation_level='REPEATABLE READ' ) @@ -465,7 +465,7 @@ operations:: from sqlalchemy import create_engine from sqlalchemy.orm import sessionmaker - eng = create_engine("postgresql://scott:tiger@localhost/test") + eng = create_engine("postgresql+psycopg2://scott:tiger@localhost/test") autocommit_engine = eng.execution_options(isolation_level="AUTOCOMMIT") @@ -505,7 +505,7 @@ we can pass the ``bind`` argument directly, overriding the pre-existing bind. We can for example create our :class:`_orm.Session` from a default :class:`.sessionmaker` and pass an engine set for autocommit:: - plain_engine = create_engine("postgresql://scott:tiger@localhost/test") + plain_engine = create_engine("postgresql+psycopg2://scott:tiger@localhost/test") autocommit_engine = plain_engine.execution_options(isolation_level="AUTOCOMMIT") @@ -630,7 +630,7 @@ are reverted:: # global application scope. create Session class, engine Session = sessionmaker() - engine = create_engine('postgresql://...') + engine = create_engine('postgresql+psycopg2://...') class SomeTest(TestCase): def setUp(self): diff --git a/examples/large_collection/large_collection.py b/examples/large_collection/large_collection.py index 0f34c54dc7..2b8c57232a 100644 --- a/examples/large_collection/large_collection.py +++ b/examples/large_collection/large_collection.py @@ -69,7 +69,7 @@ mapper(Member, member_table) if __name__ == "__main__": engine = create_engine( - "postgresql://scott:tiger@localhost/test", echo=True + "postgresql+psycopg2://scott:tiger@localhost/test", echo=True ) meta.create_all(engine) diff --git a/examples/materialized_paths/materialized_paths.py b/examples/materialized_paths/materialized_paths.py index 37e91684c1..ad2a4f4a9a 100644 --- a/examples/materialized_paths/materialized_paths.py +++ b/examples/materialized_paths/materialized_paths.py @@ -106,7 +106,7 @@ class Node(Base): if __name__ == "__main__": engine = create_engine( - "postgresql://scott:tiger@localhost/test", echo=True + "postgresql+psycopg2://scott:tiger@localhost/test", echo=True ) Base.metadata.create_all(engine) diff --git a/examples/postgis/postgis.py b/examples/postgis/postgis.py index a12b824ba1..2b45b98f56 100644 --- a/examples/postgis/postgis.py +++ b/examples/postgis/postgis.py @@ -233,7 +233,7 @@ if __name__ == "__main__": from sqlalchemy.ext.declarative import declarative_base engine = create_engine( - "postgresql://scott:tiger@localhost/test", echo=True + "postgresql+psycopg2://scott:tiger@localhost/test", echo=True ) metadata = MetaData(engine) Base = declarative_base(metadata=metadata) diff --git a/lib/sqlalchemy/dialects/mysql/base.py b/lib/sqlalchemy/dialects/mysql/base.py index 63a11fcc71..5382e00db8 100644 --- a/lib/sqlalchemy/dialects/mysql/base.py +++ b/lib/sqlalchemy/dialects/mysql/base.py @@ -213,7 +213,7 @@ techniques are used. To set isolation level using :func:`_sa.create_engine`:: engine = create_engine( - "mysql://scott:tiger@localhost/test", + "mysql+mysqldb://scott:tiger@localhost/test", isolation_level="READ UNCOMMITTED" ) @@ -423,7 +423,7 @@ the ``first_connect`` and ``connect`` events:: from sqlalchemy import create_engine, event - eng = create_engine("mysql://scott:tiger@localhost/test", echo='debug') + eng = create_engine("mysql+mysqldb://scott:tiger@localhost/test", echo='debug') # `insert=True` will ensure this is the very first listener to run @event.listens_for(eng, "connect", insert=True) @@ -950,7 +950,7 @@ SQLAlchemy also emits NOT NULL for TIMESTAMP columns that do specify from sqlalchemy import create_engine - e = create_engine("mysql://scott:tiger@localhost/test", echo=True) + e = create_engine("mysql+mysqldb://scott:tiger@localhost/test", echo=True) m.create_all(e) output:: diff --git a/lib/sqlalchemy/dialects/oracle/base.py b/lib/sqlalchemy/dialects/oracle/base.py index 9e62b931d9..5a43205dff 100644 --- a/lib/sqlalchemy/dialects/oracle/base.py +++ b/lib/sqlalchemy/dialects/oracle/base.py @@ -306,7 +306,7 @@ an INSERT in order to increment a sequence within an INSERT statement and get the value back at the same time. To disable this feature across the board, specify ``implicit_returning=False`` to :func:`_sa.create_engine`:: - engine = create_engine("oracle://scott:tiger@dsn", + engine = create_engine("oracle+cx_oracle://scott:tiger@dsn", implicit_returning=False) Implicit returning can also be disabled on a table-by-table basis as a table @@ -450,7 +450,7 @@ the ``exclude_tablespaces`` parameter:: # exclude SYSAUX and SOME_TABLESPACE, but not SYSTEM e = create_engine( - "oracle://scott:tiger@xe", + "oracle+cx_oracle://scott:tiger@xe", exclude_tablespaces=["SYSAUX", "SOME_TABLESPACE"]) .. versionadded:: 1.1 diff --git a/lib/sqlalchemy/dialects/oracle/cx_oracle.py b/lib/sqlalchemy/dialects/oracle/cx_oracle.py index 38e8648989..590c9d47c6 100644 --- a/lib/sqlalchemy/dialects/oracle/cx_oracle.py +++ b/lib/sqlalchemy/dialects/oracle/cx_oracle.py @@ -158,7 +158,7 @@ SQLAlchemy's pooling:: encoding="UTF-8", nencoding="UTF-8" ) - engine = create_engine("oracle://", creator=pool.acquire, poolclass=NullPool) + engine = create_engine("oracle+cx_oracle://", creator=pool.acquire, poolclass=NullPool) The above engine may then be used normally where cx_Oracle's pool handles connection pooling:: @@ -196,7 +196,7 @@ This can be achieved by wrapping ``pool.acquire()``:: def creator(): return pool.acquire(cclass="MYCLASS", purity=cx_Oracle.ATTR_PURITY_SELF) - engine = create_engine("oracle://", creator=creator, poolclass=NullPool) + engine = create_engine("oracle+cx_oracle://", creator=creator, poolclass=NullPool) The above engine may then be used normally where cx_Oracle handles session pooling and Oracle Database additionally uses DRCP:: diff --git a/lib/sqlalchemy/dialects/postgresql/base.py b/lib/sqlalchemy/dialects/postgresql/base.py index 87afa02936..a00c26e87d 100644 --- a/lib/sqlalchemy/dialects/postgresql/base.py +++ b/lib/sqlalchemy/dialects/postgresql/base.py @@ -346,7 +346,7 @@ were set to include ``test_schema``, and we invoked a table reflection process as follows:: >>> from sqlalchemy import Table, MetaData, create_engine, text - >>> engine = create_engine("postgresql://scott:tiger@localhost/test") + >>> engine = create_engine("postgresql+psycopg2://scott:tiger@localhost/test") >>> with engine.connect() as conn: ... conn.execute(text("SET search_path TO test_schema, public")) ... meta = MetaData() diff --git a/lib/sqlalchemy/dialects/postgresql/json.py b/lib/sqlalchemy/dialects/postgresql/json.py index 2acf177f53..ef046e3aec 100644 --- a/lib/sqlalchemy/dialects/postgresql/json.py +++ b/lib/sqlalchemy/dialects/postgresql/json.py @@ -159,7 +159,7 @@ class JSON(sqltypes.JSON): using psycopg2, the DBAPI only allows serializers at the per-cursor or per-connection level. E.g.:: - engine = create_engine("postgresql://scott:tiger@localhost/test", + engine = create_engine("postgresql+psycopg2://scott:tiger@localhost/test", json_serializer=my_serialize_fn, json_deserializer=my_deserialize_fn ) diff --git a/lib/sqlalchemy/engine/base.py b/lib/sqlalchemy/engine/base.py index 41c5f4753e..ef62825251 100644 --- a/lib/sqlalchemy/engine/base.py +++ b/lib/sqlalchemy/engine/base.py @@ -1887,7 +1887,7 @@ class Transaction(TransactionalContext): :class:`_engine.Connection`:: from sqlalchemy import create_engine - engine = create_engine("postgresql://scott:tiger@localhost/test") + engine = create_engine("postgresql+psycopg2://scott:tiger@localhost/test") connection = engine.connect() trans = connection.begin() connection.execute(text("insert into x (a, b) values (1, 2)")) @@ -1914,7 +1914,7 @@ class Transaction(TransactionalContext): .. index:: single: thread safety; Transaction - """ + """ # noqa __slots__ = () @@ -2413,7 +2413,7 @@ class Engine(ConnectionEventsTarget, log.Identified): from sqlalchemy import event from sqlalchemy.engine import Engine - primary_engine = create_engine("mysql://") + primary_engine = create_engine("mysql+mysqldb://") shard1 = primary_engine.execution_options(shard_id="shard1") shard2 = primary_engine.execution_options(shard_id="shard2") diff --git a/lib/sqlalchemy/engine/create.py b/lib/sqlalchemy/engine/create.py index 6e5a07098d..bb657202ff 100644 --- a/lib/sqlalchemy/engine/create.py +++ b/lib/sqlalchemy/engine/create.py @@ -42,7 +42,7 @@ def create_engine(url, **kwargs): first positional argument, usually a string that indicates database dialect and connection arguments:: - engine = create_engine("postgresql://scott:tiger@localhost/test") + engine = create_engine("postgresql+psycopg2://scott:tiger@localhost/test") .. note:: @@ -55,7 +55,7 @@ def create_engine(url, **kwargs): and its underlying :class:`.Dialect` and :class:`_pool.Pool` constructs:: - engine = create_engine("mysql://scott:tiger@hostname/dbname", + engine = create_engine("mysql+mysqldb://scott:tiger@hostname/dbname", encoding='latin1', echo=True) The string form of the URL is diff --git a/lib/sqlalchemy/engine/events.py b/lib/sqlalchemy/engine/events.py index cfb616affc..57628066d8 100644 --- a/lib/sqlalchemy/engine/events.py +++ b/lib/sqlalchemy/engine/events.py @@ -30,7 +30,7 @@ class ConnectionEvents(event.Events): executemany): log.info("Received statement: %s", statement) - engine = create_engine('postgresql://scott:tiger@localhost/test') + engine = create_engine('postgresql+psycopg2://scott:tiger@localhost/test') event.listen(engine, "before_cursor_execute", before_cursor_execute) or with a specific :class:`_engine.Connection`:: @@ -88,7 +88,7 @@ class ConnectionEvents(event.Events): and parameters. See those methods for a description of specific return arguments. - """ + """ # noqa _target_class_doc = "SomeEngine" _dispatch_target = ConnectionEventsTarget diff --git a/lib/sqlalchemy/engine/mock.py b/lib/sqlalchemy/engine/mock.py index 5da716b6b6..731dacc33a 100644 --- a/lib/sqlalchemy/engine/mock.py +++ b/lib/sqlalchemy/engine/mock.py @@ -62,7 +62,7 @@ def create_mock_engine(url, executor, **kw): def dump(sql, *multiparams, **params): print(sql.compile(dialect=engine.dialect)) - engine = create_mock_engine('postgresql://', dump) + engine = create_mock_engine('postgresql+psycopg2://', dump) metadata.create_all(engine, checkfirst=False) :param url: A string URL which typically needs to contain only the diff --git a/lib/sqlalchemy/engine/url.py b/lib/sqlalchemy/engine/url.py index be330eb6c7..7f09b1eac3 100644 --- a/lib/sqlalchemy/engine/url.py +++ b/lib/sqlalchemy/engine/url.py @@ -286,10 +286,10 @@ class URL( E.g.:: >>> from sqlalchemy.engine import make_url - >>> url = make_url("postgresql://user:pass@host/dbname") + >>> url = make_url("postgresql+psycopg2://user:pass@host/dbname") >>> url = url.update_query_string("alt_host=host1&alt_host=host2&ssl_cipher=%2Fpath%2Fto%2Fcrt") >>> str(url) - 'postgresql://user:pass@host/dbname?alt_host=host1&alt_host=host2&ssl_cipher=%2Fpath%2Fto%2Fcrt' + 'postgresql+psycopg2://user:pass@host/dbname?alt_host=host1&alt_host=host2&ssl_cipher=%2Fpath%2Fto%2Fcrt' :param query_string: a URL escaped query string, not including the question mark. @@ -320,10 +320,10 @@ class URL( E.g.:: >>> from sqlalchemy.engine import make_url - >>> url = make_url("postgresql://user:pass@host/dbname") + >>> url = make_url("postgresql+psycopg2://user:pass@host/dbname") >>> url = url.update_query_pairs([("alt_host", "host1"), ("alt_host", "host2"), ("ssl_cipher", "/path/to/crt")]) >>> str(url) - 'postgresql://user:pass@host/dbname?alt_host=host1&alt_host=host2&ssl_cipher=%2Fpath%2Fto%2Fcrt' + 'postgresql+psycopg2://user:pass@host/dbname?alt_host=host1&alt_host=host2&ssl_cipher=%2Fpath%2Fto%2Fcrt' :param key_value_pairs: A sequence of tuples containing two strings each. @@ -389,10 +389,10 @@ class URL( >>> from sqlalchemy.engine import make_url - >>> url = make_url("postgresql://user:pass@host/dbname") + >>> url = make_url("postgresql+psycopg2://user:pass@host/dbname") >>> url = url.update_query_dict({"alt_host": ["host1", "host2"], "ssl_cipher": "/path/to/crt"}) >>> str(url) - 'postgresql://user:pass@host/dbname?alt_host=host1&alt_host=host2&ssl_cipher=%2Fpath%2Fto%2Fcrt' + 'postgresql+psycopg2://user:pass@host/dbname?alt_host=host1&alt_host=host2&ssl_cipher=%2Fpath%2Fto%2Fcrt' :param query_parameters: A dictionary with string keys and values @@ -485,7 +485,7 @@ class URL( >>> from sqlalchemy.engine import make_url - >>> url = make_url("postgresql://user:pass@host/dbname?alt_host=host1&alt_host=host2&ssl_cipher=%2Fpath%2Fto%2Fcrt") + >>> url = make_url("postgresql+psycopg2://user:pass@host/dbname?alt_host=host1&alt_host=host2&ssl_cipher=%2Fpath%2Fto%2Fcrt") >>> url.query immutabledict({'alt_host': ('host1', 'host2'), 'ssl_cipher': '/path/to/crt'}) >>> url.normalized_query diff --git a/lib/sqlalchemy/orm/session.py b/lib/sqlalchemy/orm/session.py index c76ece5de5..95d329ab0d 100644 --- a/lib/sqlalchemy/orm/session.py +++ b/lib/sqlalchemy/orm/session.py @@ -1001,10 +1001,10 @@ class Session(_SessionClassMethods): described at :meth:`.Session.get_bind`. Usage looks like:: Session = sessionmaker(binds={ - SomeMappedClass: create_engine('postgresql://engine1'), - SomeDeclarativeBase: create_engine('postgresql://engine2'), - some_mapper: create_engine('postgresql://engine3'), - some_table: create_engine('postgresql://engine4'), + SomeMappedClass: create_engine('postgresql+psycopg2://engine1'), + SomeDeclarativeBase: create_engine('postgresql+psycopg2://engine2'), + some_mapper: create_engine('postgresql+psycopg2://engine3'), + some_table: create_engine('postgresql+psycopg2://engine4'), }) .. seealso:: @@ -1086,7 +1086,7 @@ class Session(_SessionClassMethods): :param autocommit: the "autocommit" keyword is present for backwards compatibility but must remain at its default value of ``False``. - """ + """ # noqa # considering allowing the "autocommit" keyword to still be accepted # as long as it's False, so that external test suites, oslo.db etc @@ -3906,7 +3906,7 @@ class sessionmaker(_SessionClassMethods): # an Engine, which the Session will use for connection # resources - engine = create_engine('postgresql://scott:tiger@localhost/') + engine = create_engine('postgresql+psycopg2://scott:tiger@localhost/') Session = sessionmaker(engine) diff --git a/lib/sqlalchemy/pool/events.py b/lib/sqlalchemy/pool/events.py index 7c2cae7c5e..57e3893b02 100644 --- a/lib/sqlalchemy/pool/events.py +++ b/lib/sqlalchemy/pool/events.py @@ -32,12 +32,12 @@ class PoolEvents(event.Events): targets, which will be resolved to the ``.pool`` attribute of the given engine or the :class:`_pool.Pool` class:: - engine = create_engine("postgresql://scott:tiger@localhost/test") + engine = create_engine("postgresql+psycopg2://scott:tiger@localhost/test") # will associate with engine.pool event.listen(engine, 'checkout', my_on_checkout) - """ + """ # noqa _target_class_doc = "SomeEngineOrPool" _dispatch_target = Pool diff --git a/lib/sqlalchemy/sql/schema.py b/lib/sqlalchemy/sql/schema.py index dbd50d5d8c..a600960cac 100644 --- a/lib/sqlalchemy/sql/schema.py +++ b/lib/sqlalchemy/sql/schema.py @@ -1431,7 +1431,7 @@ class Column(DialectKWArgs, SchemaItem, ColumnClause): from sqlalchemy.dialects.postgresql import array engine = create_engine( - 'postgresql://scott:tiger@localhost/mydatabase' + 'postgresql+psycopg2://scott:tiger@localhost/mydatabase' ) metadata_obj = MetaData() tbl = Table( diff --git a/setup.cfg b/setup.cfg index e886b69233..624ace1bdf 100644 --- a/setup.cfg +++ b/setup.cfg @@ -156,20 +156,20 @@ aiosqlite = sqlite+aiosqlite:///:memory: sqlite_file = sqlite:///querytest.db aiosqlite_file = sqlite+aiosqlite:///async_querytest.db pysqlcipher_file = sqlite+pysqlcipher://:test@/querytest.db.enc -postgresql = postgresql://scott:tiger@127.0.0.1:5432/test +postgresql = postgresql+psycopg2://scott:tiger@127.0.0.1:5432/test asyncpg = postgresql+asyncpg://scott:tiger@127.0.0.1:5432/test asyncpg_fallback = postgresql+asyncpg://scott:tiger@127.0.0.1:5432/test?async_fallback=true pg8000 = postgresql+pg8000://scott:tiger@127.0.0.1:5432/test postgresql_psycopg2cffi = postgresql+psycopg2cffi://scott:tiger@127.0.0.1:5432/test -mysql = mysql://scott:tiger@127.0.0.1:3306/test?charset=utf8mb4 +mysql = mysql+mysqldb://scott:tiger@127.0.0.1:3306/test?charset=utf8mb4 pymysql = mysql+pymysql://scott:tiger@127.0.0.1:3306/test?charset=utf8mb4 aiomysql = mysql+aiomysql://scott:tiger@127.0.0.1:3306/test?charset=utf8mb4 aiomysql_fallback = mysql+aiomysql://scott:tiger@127.0.0.1:3306/test?charset=utf8mb4&async_fallback=true asyncmy = mysql+asyncmy://scott:tiger@127.0.0.1:3306/test?charset=utf8mb4 asyncmy_fallback = mysql+asyncmy://scott:tiger@127.0.0.1:3306/test?charset=utf8mb4&async_fallback=true -mariadb = mariadb://scott:tiger@127.0.0.1:3306/test +mariadb = mariadb+mysqldb://scott:tiger@127.0.0.1:3306/test mssql = mssql+pyodbc://scott:tiger^5HHH@mssql2017:1433/test?driver=ODBC+Driver+13+for+SQL+Server mssql_pymssql = mssql+pymssql://scott:tiger@ms_2008 docker_mssql = mssql+pymssql://scott:tiger^5HHH@127.0.0.1:1433/test -oracle = oracle://scott:tiger@127.0.0.1:1521 -oracle8 = oracle://scott:tiger@127.0.0.1:1521/?use_ansi=0 +oracle = oracle+cx_oracle://scott:tiger@127.0.0.1:1521 +oracle8 = oracle+cx_oracle://scott:tiger@127.0.0.1:1521/?use_ansi=0 diff --git a/test/dialect/mssql/test_deprecations.py b/test/dialect/mssql/test_deprecations.py index aecb813fa1..24625d65c7 100644 --- a/test/dialect/mssql/test_deprecations.py +++ b/test/dialect/mssql/test_deprecations.py @@ -64,14 +64,14 @@ class LegacySchemaAliasingTest(fixtures.TestBase, AssertsCompiledSQL): @testing.combinations( ( { - "sqlalchemy.url": "mssql://foodsn", + "sqlalchemy.url": "mssql+pyodbc://foodsn", "sqlalchemy.legacy_schema_aliasing": "true", }, True, ), ( { - "sqlalchemy.url": "mssql://foodsn", + "sqlalchemy.url": "mssql+pyodbc://foodsn", "sqlalchemy.legacy_schema_aliasing": "false", }, False, diff --git a/test/dialect/mssql/test_engine.py b/test/dialect/mssql/test_engine.py index 5482e26167..e14fd164a0 100644 --- a/test/dialect/mssql/test_engine.py +++ b/test/dialect/mssql/test_engine.py @@ -32,26 +32,27 @@ from sqlalchemy.testing.mock import Mock class ParseConnectTest(fixtures.TestBase): def test_pyodbc_connect_dsn_trusted(self): dialect = pyodbc.dialect() - u = url.make_url("mssql://mydsn") + u = url.make_url("mssql+pyodbc://mydsn") connection = dialect.create_connect_args(u) eq_([["dsn=mydsn;Trusted_Connection=Yes"], {}], connection) def test_pyodbc_connect_old_style_dsn_trusted(self): dialect = pyodbc.dialect() - u = url.make_url("mssql:///?dsn=mydsn") + u = url.make_url("mssql+pyodbc:///?dsn=mydsn") connection = dialect.create_connect_args(u) eq_([["dsn=mydsn;Trusted_Connection=Yes"], {}], connection) def test_pyodbc_connect_dsn_non_trusted(self): dialect = pyodbc.dialect() - u = url.make_url("mssql://username:password@mydsn") + u = url.make_url("mssql+pyodbc://username:password@mydsn") connection = dialect.create_connect_args(u) eq_([["dsn=mydsn;UID=username;PWD=password"], {}], connection) def test_pyodbc_connect_dsn_extra(self): dialect = pyodbc.dialect() u = url.make_url( - "mssql://username:password@mydsn/?LANGUAGE=us_" "english&foo=bar" + "mssql+pyodbc://username:password@mydsn/?LANGUAGE=us_" + "english&foo=bar" ) connection = dialect.create_connect_args(u) dsn_string = connection[0][0] @@ -61,7 +62,7 @@ class ParseConnectTest(fixtures.TestBase): def test_pyodbc_hostname(self): dialect = pyodbc.dialect() u = url.make_url( - "mssql://username:password@hostspec/database?driver=SQL+Server" + "mssql+pyodbc://username:password@hostspec/database?driver=SQL+Server" # noqa ) connection = dialect.create_connect_args(u) eq_( @@ -84,7 +85,7 @@ class ParseConnectTest(fixtures.TestBase): def test_pyodbc_host_no_driver(self): dialect = pyodbc.dialect() - u = url.make_url("mssql://username:password@hostspec/database") + u = url.make_url("mssql+pyodbc://username:password@hostspec/database") def go(): return dialect.create_connect_args(u) @@ -111,7 +112,7 @@ class ParseConnectTest(fixtures.TestBase): def test_pyodbc_connect_comma_port(self): dialect = pyodbc.dialect() u = url.make_url( - "mssql://username:password@hostspec:12345/data" + "mssql+pyodbc://username:password@hostspec:12345/data" "base?driver=SQL Server" ) connection = dialect.create_connect_args(u) @@ -129,7 +130,7 @@ class ParseConnectTest(fixtures.TestBase): def test_pyodbc_connect_config_port(self): dialect = pyodbc.dialect() u = url.make_url( - "mssql://username:password@hostspec/database?p" + "mssql+pyodbc://username:password@hostspec/database?p" "ort=12345&driver=SQL+Server" ) connection = dialect.create_connect_args(u) @@ -147,7 +148,7 @@ class ParseConnectTest(fixtures.TestBase): def test_pyodbc_extra_connect(self): dialect = pyodbc.dialect() u = url.make_url( - "mssql://username:password@hostspec/database?L" + "mssql+pyodbc://username:password@hostspec/database?L" "ANGUAGE=us_english&foo=bar&driver=SQL+Server" ) connection = dialect.create_connect_args(u) @@ -186,7 +187,7 @@ class ParseConnectTest(fixtures.TestBase): def test_pyodbc_odbc_connect(self): dialect = pyodbc.dialect() u = url.make_url( - "mssql:///?odbc_connect=DRIVER%3D%7BSQL+Server" + "mssql+pyodbc:///?odbc_connect=DRIVER%3D%7BSQL+Server" "%7D%3BServer%3Dhostspec%3BDatabase%3Ddatabase" "%3BUID%3Dusername%3BPWD%3Dpassword" ) @@ -205,7 +206,7 @@ class ParseConnectTest(fixtures.TestBase): def test_pyodbc_odbc_connect_with_dsn(self): dialect = pyodbc.dialect() u = url.make_url( - "mssql:///?odbc_connect=dsn%3Dmydsn%3BDatabase" + "mssql+pyodbc:///?odbc_connect=dsn%3Dmydsn%3BDatabase" "%3Ddatabase%3BUID%3Dusername%3BPWD%3Dpassword" ) connection = dialect.create_connect_args(u) @@ -217,7 +218,7 @@ class ParseConnectTest(fixtures.TestBase): def test_pyodbc_odbc_connect_ignores_other_values(self): dialect = pyodbc.dialect() u = url.make_url( - "mssql://userdiff:passdiff@localhost/dbdiff?od" + "mssql+pyodbc://userdiff:passdiff@localhost/dbdiff?od" "bc_connect=DRIVER%3D%7BSQL+Server%7D%3BServer" "%3Dhostspec%3BDatabase%3Ddatabase%3BUID%3Duse" "rname%3BPWD%3Dpassword" diff --git a/test/dialect/mysql/test_dialect.py b/test/dialect/mysql/test_dialect.py index 834e1874c5..9a0f2bc0df 100644 --- a/test/dialect/mysql/test_dialect.py +++ b/test/dialect/mysql/test_dialect.py @@ -202,7 +202,7 @@ class DialectTest(fixtures.TestBase): dialect = mysqldb.dialect() connect_args = dialect.create_connect_args( make_url( - "mysql://scott:tiger@localhost:3306/test" + "mysql+mysqldb://scott:tiger@localhost:3306/test" "?%s=%s" % (kwarg, value) ) ) @@ -262,7 +262,7 @@ class DialectTest(fixtures.TestBase): def test_random_arg(self): dialect = testing.db.dialect kw = dialect.create_connect_args( - make_url("mysql://u:p@host/db?foo=true") + make_url("mysql+mysqldb://u:p@host/db?foo=true") )[1] eq_(kw["foo"], "true") @@ -303,7 +303,7 @@ class DialectTest(fixtures.TestBase): class ParseVersionTest(fixtures.TestBase): def test_mariadb_madness(self): - mysql_dialect = make_url("mysql://").get_dialect()() + mysql_dialect = make_url("mysql+mysqldb://").get_dialect()() is_(mysql_dialect.is_mariadb, False) diff --git a/test/dialect/postgresql/test_dialect.py b/test/dialect/postgresql/test_dialect.py index e7c4ebb7ce..fe3700bbbc 100644 --- a/test/dialect/postgresql/test_dialect.py +++ b/test/dialect/postgresql/test_dialect.py @@ -171,42 +171,44 @@ $$ LANGUAGE plpgsql;""" def test_psycopg2_empty_connection_string(self): dialect = psycopg2_dialect.dialect() - u = url.make_url("postgresql://") + u = url.make_url("postgresql+psycopg2://") cargs, cparams = dialect.create_connect_args(u) eq_(cargs, [""]) eq_(cparams, {}) def test_psycopg2_nonempty_connection_string(self): dialect = psycopg2_dialect.dialect() - u = url.make_url("postgresql://host") + u = url.make_url("postgresql+psycopg2://host") cargs, cparams = dialect.create_connect_args(u) eq_(cargs, []) eq_(cparams, {"host": "host"}) def test_psycopg2_empty_connection_string_w_query_one(self): dialect = psycopg2_dialect.dialect() - u = url.make_url("postgresql:///?service=swh-log") + u = url.make_url("postgresql+psycopg2:///?service=swh-log") cargs, cparams = dialect.create_connect_args(u) eq_(cargs, []) eq_(cparams, {"service": "swh-log"}) def test_psycopg2_empty_connection_string_w_query_two(self): dialect = psycopg2_dialect.dialect() - u = url.make_url("postgresql:///?any_random_thing=yes") + u = url.make_url("postgresql+psycopg2:///?any_random_thing=yes") cargs, cparams = dialect.create_connect_args(u) eq_(cargs, []) eq_(cparams, {"any_random_thing": "yes"}) def test_psycopg2_nonempty_connection_string_w_query(self): dialect = psycopg2_dialect.dialect() - u = url.make_url("postgresql://somehost/?any_random_thing=yes") + u = url.make_url( + "postgresql+psycopg2://somehost/?any_random_thing=yes" + ) cargs, cparams = dialect.create_connect_args(u) eq_(cargs, []) eq_(cparams, {"host": "somehost", "any_random_thing": "yes"}) def test_psycopg2_nonempty_connection_string_w_query_two(self): dialect = psycopg2_dialect.dialect() - url_string = "postgresql://USER:PASS@/DB?host=hostA" + url_string = "postgresql+psycopg2://USER:PASS@/DB?host=hostA" u = url.make_url(url_string) cargs, cparams = dialect.create_connect_args(u) eq_(cargs, []) @@ -215,7 +217,7 @@ $$ LANGUAGE plpgsql;""" def test_psycopg2_nonempty_connection_string_w_query_three(self): dialect = psycopg2_dialect.dialect() url_string = ( - "postgresql://USER:PASS@/DB" + "postgresql+psycopg2://USER:PASS@/DB" "?host=hostA:portA&host=hostB&host=hostC" ) u = url.make_url(url_string) diff --git a/test/engine/test_deprecations.py b/test/engine/test_deprecations.py index 6e7169d12f..956524abd1 100644 --- a/test/engine/test_deprecations.py +++ b/test/engine/test_deprecations.py @@ -278,7 +278,7 @@ class CreateEngineTest(fixtures.TestBase): "only argument accepted is 'mock'" ): e = create_engine( - "postgresql://", strategy="mock", executor=executor + "postgresql+psycopg2://", strategy="mock", executor=executor ) assert isinstance(e, MockConnection) @@ -292,7 +292,7 @@ class CreateEngineTest(fixtures.TestBase): tsa.exc.ArgumentError, "unknown strategy: 'threadlocal'", create_engine, - "postgresql://", + "postgresql+psycopg2://", strategy="threadlocal", ) @@ -302,7 +302,7 @@ class CreateEngineTest(fixtures.TestBase): "and no longer has any effect." ): create_engine( - "postgresql://", + "postgresql+psycopg2://", empty_in_strategy="static", module=Mock(), _initialize=False, diff --git a/test/engine/test_execute.py b/test/engine/test_execute.py index afe95ba826..3b691ebc9e 100644 --- a/test/engine/test_execute.py +++ b/test/engine/test_execute.py @@ -1161,7 +1161,7 @@ class MockStrategyTest(fixtures.TestBase): def dump(sql, *multiparams, **params): buf.write(util.text_type(sql.compile(dialect=engine.dialect))) - engine = create_mock_engine("postgresql://", executor=dump) + engine = create_mock_engine("postgresql+psycopg2://", executor=dump) return engine, buf def test_sequence_not_duped(self): diff --git a/test/engine/test_parseconnect.py b/test/engine/test_parseconnect.py index 044dc2cbdc..f0a1dba4bb 100644 --- a/test/engine/test_parseconnect.py +++ b/test/engine/test_parseconnect.py @@ -16,6 +16,7 @@ from sqlalchemy.testing import is_ from sqlalchemy.testing import is_false from sqlalchemy.testing import is_true from sqlalchemy.testing import mock +from sqlalchemy.testing import ne_ from sqlalchemy.testing.assertions import expect_deprecated from sqlalchemy.testing.assertions import expect_raises_message from sqlalchemy.testing.mock import call @@ -447,7 +448,7 @@ class CreateEngineTest(fixtures.TestBase): def test_connect_query(self): dbapi = MockDBAPI(foober="12", lala="18", fooz="somevalue") e = create_engine( - "postgresql://scott:tiger@somehost/test?foobe" + "postgresql+psycopg2://scott:tiger@somehost/test?foobe" "r=12&lala=18&fooz=somevalue", module=dbapi, _initialize=False, @@ -459,7 +460,8 @@ class CreateEngineTest(fixtures.TestBase): foober=12, lala=18, hoho={"this": "dict"}, fooz="somevalue" ) e = create_engine( - "postgresql://scott:tiger@somehost/test?fooz=" "somevalue", + "postgresql+psycopg2://scott:tiger@somehost/test?fooz=" + "somevalue", connect_args={"foober": 12, "lala": 18, "hoho": {"this": "dict"}}, module=dbapi, _initialize=False, @@ -470,7 +472,7 @@ class CreateEngineTest(fixtures.TestBase): dbapi = mock_dbapi config = { - "sqlalchemy.url": "postgresql://scott:tiger@somehost/test" + "sqlalchemy.url": "postgresql+psycopg2://scott:tiger@somehost/test" "?fooz=somevalue", "sqlalchemy.pool_recycle": "50", "sqlalchemy.echo": "true", @@ -479,7 +481,7 @@ class CreateEngineTest(fixtures.TestBase): e = engine_from_config(config, module=dbapi, _initialize=False) assert e.pool._recycle == 50 assert e.url == url.make_url( - "postgresql://scott:tiger@somehost/test?foo" "z=somevalue" + "postgresql+psycopg2://scott:tiger@somehost/test?foo" "z=somevalue" ) assert e.echo is True @@ -487,7 +489,7 @@ class CreateEngineTest(fixtures.TestBase): dbapi = mock_dbapi config = { - "sqlalchemy.url": "postgresql://scott:tiger@somehost/test" + "sqlalchemy.url": "postgresql+psycopg2://scott:tiger@somehost/test" "?fooz=somevalue", "sqlalchemy.future": "true", } @@ -498,7 +500,7 @@ class CreateEngineTest(fixtures.TestBase): dbapi = mock_dbapi config = { - "sqlalchemy.url": "postgresql://scott:tiger@somehost/test" + "sqlalchemy.url": "postgresql+psycopg2://scott:tiger@somehost/test" "?fooz=somevalue", "sqlalchemy.future": "false", } @@ -519,7 +521,7 @@ class CreateEngineTest(fixtures.TestBase): ("none", pool.reset_none), ]: config = { - "sqlalchemy.url": "postgresql://scott:tiger@somehost/test", + "sqlalchemy.url": "postgresql+psycopg2://scott:tiger@somehost/test", # noqa "sqlalchemy.pool_reset_on_return": value, } @@ -603,7 +605,10 @@ class CreateEngineTest(fixtures.TestBase): # module instead of psycopg e = create_engine( - "postgresql://", creator=connect, module=dbapi, _initialize=False + "postgresql+psycopg2://", + creator=connect, + module=dbapi, + _initialize=False, ) e.connect() @@ -612,7 +617,10 @@ class CreateEngineTest(fixtures.TestBase): foober=12, lala=18, hoho={"this": "dict"}, fooz="somevalue" ) e = create_engine( - "postgresql://", pool_recycle=472, module=dbapi, _initialize=False + "postgresql+psycopg2://", + pool_recycle=472, + module=dbapi, + _initialize=False, ) assert e.pool._recycle == 472 @@ -628,7 +636,7 @@ class CreateEngineTest(fixtures.TestBase): (False, pool.reset_none), ]: e = create_engine( - "postgresql://", + "postgresql+psycopg2://", pool_reset_on_return=value, module=dbapi, _initialize=False, @@ -638,7 +646,7 @@ class CreateEngineTest(fixtures.TestBase): assert_raises( exc.ArgumentError, create_engine, - "postgresql://", + "postgresql+psycopg2://", pool_reset_on_return="hi", module=dbapi, _initialize=False, @@ -654,7 +662,7 @@ class CreateEngineTest(fixtures.TestBase): assert_raises( TypeError, create_engine, - "postgresql://", + "postgresql+psycopg2://", use_ansi=True, module=mock_dbapi, ) @@ -672,7 +680,7 @@ class CreateEngineTest(fixtures.TestBase): assert_raises( TypeError, create_engine, - "postgresql://", + "postgresql+psycopg2://", lala=5, module=mock_dbapi, ) @@ -695,25 +703,25 @@ class CreateEngineTest(fixtures.TestBase): """test the url attribute on ``Engine``.""" e = create_engine( - "mysql://scott:tiger@localhost/test", + "mysql+mysqldb://scott:tiger@localhost/test", module=mock_dbapi, _initialize=False, ) - u = url.make_url("mysql://scott:tiger@localhost/test") + u = url.make_url("mysql+mysqldb://scott:tiger@localhost/test") e2 = create_engine(u, module=mock_dbapi, _initialize=False) - assert e.url.drivername == e2.url.drivername == "mysql" + assert e.url.drivername == e2.url.drivername == "mysql+mysqldb" assert e.url.username == e2.url.username == "scott" assert e2.url is u - assert str(u) == "mysql://scott:tiger@localhost/test" - assert repr(u) == "mysql://scott:***@localhost/test" - assert repr(e) == "Engine(mysql://scott:***@localhost/test)" - assert repr(e2) == "Engine(mysql://scott:***@localhost/test)" + assert str(u) == "mysql+mysqldb://scott:tiger@localhost/test" + assert repr(u) == "mysql+mysqldb://scott:***@localhost/test" + assert repr(e) == "Engine(mysql+mysqldb://scott:***@localhost/test)" + assert repr(e2) == "Engine(mysql+mysqldb://scott:***@localhost/test)" def test_poolargs(self): """test that connection pool args make it thru""" e = create_engine( - "postgresql://", + "postgresql+psycopg2://", creator=None, pool_recycle=50, echo_pool=None, @@ -725,7 +733,7 @@ class CreateEngineTest(fixtures.TestBase): # these args work for QueuePool e = create_engine( - "postgresql://", + "postgresql+psycopg2://", max_overflow=8, pool_timeout=60, poolclass=tsa.pool.QueuePool, @@ -783,6 +791,26 @@ class CreateEngineTest(fixtures.TestBase): e.connect() eq_(sp.called, 1) + def test_default_driver(self): + successes = 0 + for url_prefix, driver_name in [ + ("mariadb://", "mysqldb"), + ("mssql://", "pyodbc"), + ("mysql://", "mysqldb"), + ("oracle://", "cx_oracle"), + ("postgresql://", "psycopg2"), + ("sqlite://", "pysqlite"), + ]: + try: + en = create_engine(url_prefix) + eq_(en.dialect.driver, driver_name) + successes += 1 + except ModuleNotFoundError: + # not all test environments will have every driver installed + pass + # but we should at least find one + ne_(successes, 0, "No default drivers found.") + class TestRegNewDBAPI(fixtures.TestBase): def test_register_base(self): diff --git a/test/engine/test_reconnect.py b/test/engine/test_reconnect.py index 0c7f86a623..c9894b0f28 100644 --- a/test/engine/test_reconnect.py +++ b/test/engine/test_reconnect.py @@ -166,7 +166,7 @@ class PrePingMockTest(fixtures.TestBase): def _pool_fixture(self, pre_ping, pool_kw=None): dialect = url.make_url( - "postgresql://foo:bar@localhost/test" + "postgresql+psycopg2://foo:bar@localhost/test" ).get_dialect()() dialect.dbapi = self.dbapi _pool = pool.QueuePool( @@ -360,7 +360,7 @@ class MockReconnectTest(fixtures.TestBase): self.dbapi = MockDBAPI() self.db = testing_engine( - "postgresql://foo:bar@localhost/test", + "postgresql+psycopg2://foo:bar@localhost/test", options=dict(module=self.dbapi, _initialize=False), ) diff --git a/test/sql/test_deprecations.py b/test/sql/test_deprecations.py index 22b743434f..93e280d4e1 100644 --- a/test/sql/test_deprecations.py +++ b/test/sql/test_deprecations.py @@ -178,7 +178,9 @@ class DeprecationWarningsTest(fixtures.TestBase, AssertsCompiledSQL): "The create_engine.convert_unicode parameter and " "corresponding dialect-level" ): - create_engine("mysql://", convert_unicode=True, module=mock.Mock()) + create_engine( + "mysql+mysqldb://", convert_unicode=True, module=mock.Mock() + ) def test_empty_and_or(self): with testing.expect_deprecated(