Skip to content

Commit 96ff043

Browse files
abowden1989phofl
authored andcommitted
BUG: Do not error on other dbapi2 connections (pandas-dev#45679)
1 parent 659edbf commit 96ff043

File tree

3 files changed

+25
-5
lines changed

3 files changed

+25
-5
lines changed

doc/source/whatsnew/v1.4.1.rst

+2-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@ Fixed regressions
2020
- Regression in :meth:`DataFrame.iat` setting values leading to not propagating correctly in subsequent lookups (:issue:`45684`)
2121
- Regression in :meth:`DataFrame.loc.__setitem__` losing :class:`Index` name if :class:`DataFrame` was empty before (:issue:`45621`)
2222
- Regression in :func:`join` with overlapping :class:`IntervalIndex` raising an ``InvalidIndexError`` (:issue:`45661`)
23-
23+
- Regression in :func:`read_sql` with a DBAPI2 connection that is not an instance of ``sqlite3.Connection`` incorrectly requiring SQLAlchemy be installed (:issue:`45660`)
24+
-
2425

2526
.. ---------------------------------------------------------------------------
2627

pandas/io/sql.py

+6-3
Original file line numberDiff line numberDiff line change
@@ -736,12 +736,15 @@ def pandasSQL_builder(con, schema: str | None = None):
736736
if isinstance(con, sqlite3.Connection) or con is None:
737737
return SQLiteDatabase(con)
738738

739-
sqlalchemy = import_optional_dependency("sqlalchemy")
739+
sqlalchemy = import_optional_dependency("sqlalchemy", errors="ignore")
740740

741741
if isinstance(con, str):
742-
con = sqlalchemy.create_engine(con)
742+
if sqlalchemy is None:
743+
raise ImportError("Using URI string without sqlalchemy installed.")
744+
else:
745+
con = sqlalchemy.create_engine(con)
743746

744-
if isinstance(con, sqlalchemy.engine.Connectable):
747+
if sqlalchemy is not None and isinstance(con, sqlalchemy.engine.Connectable):
745748
return SQLDatabase(con, schema=schema)
746749

747750
warnings.warn(

pandas/tests/io/test_sql.py

+17-1
Original file line numberDiff line numberDiff line change
@@ -1532,9 +1532,25 @@ def test_sql_open_close(self, test_frame3):
15321532
@pytest.mark.skipif(SQLALCHEMY_INSTALLED, reason="SQLAlchemy is installed")
15331533
def test_con_string_import_error(self):
15341534
conn = "mysql://root@localhost/pandas"
1535-
with pytest.raises(ImportError, match="SQLAlchemy"):
1535+
msg = "Using URI string without sqlalchemy installed"
1536+
with pytest.raises(ImportError, match=msg):
15361537
sql.read_sql("SELECT * FROM iris", conn)
15371538

1539+
@pytest.mark.skipif(SQLALCHEMY_INSTALLED, reason="SQLAlchemy is installed")
1540+
def test_con_unknown_dbapi2_class_does_not_error_without_sql_alchemy_installed(
1541+
self,
1542+
):
1543+
class MockSqliteConnection:
1544+
def __init__(self, *args, **kwargs):
1545+
self.conn = sqlite3.Connection(*args, **kwargs)
1546+
1547+
def __getattr__(self, name):
1548+
return getattr(self.conn, name)
1549+
1550+
conn = MockSqliteConnection(":memory:")
1551+
with tm.assert_produces_warning(UserWarning):
1552+
sql.read_sql("SELECT 1", conn)
1553+
15381554
def test_read_sql_delegate(self):
15391555
iris_frame1 = sql.read_sql_query("SELECT * FROM iris", self.conn)
15401556
iris_frame2 = sql.read_sql("SELECT * FROM iris", self.conn)

0 commit comments

Comments
 (0)