Skip to content

Commit 06452d2

Browse files
committed
refactor(cursor): check pandas, numpy available before use
1 parent 9b9d1a7 commit 06452d2

File tree

2 files changed

+36
-8
lines changed

2 files changed

+36
-8
lines changed

redshift_connector/cursor.py

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,23 @@
44
from typing import TYPE_CHECKING
55
from warnings import warn
66

7-
import numpy # type: ignore
8-
import pandas # type: ignore
9-
107
import redshift_connector
118
from redshift_connector.config import table_type_clauses
12-
from redshift_connector.error import InterfaceError, ProgrammingError
9+
from redshift_connector.error import (
10+
MISSING_MODULE_ERROR_MSG,
11+
InterfaceError,
12+
ProgrammingError,
13+
)
1314

1415
if TYPE_CHECKING:
1516
from redshift_connector.core import Connection
1617

18+
try:
19+
import numpy
20+
import pandas
21+
except:
22+
pass
23+
1724

1825
class Cursor:
1926
"""A cursor object is returned by the :meth:`~Connection.cursor` method of
@@ -275,8 +282,13 @@ def __next__(self: "Cursor"):
275282
else:
276283
raise StopIteration()
277284

278-
def fetch_dataframe(self: "Cursor", num: typing.Optional[int] = None) -> typing.Optional[pandas.DataFrame]:
285+
def fetch_dataframe(self: "Cursor", num: typing.Optional[int] = None) -> typing.Optional["pandas.DataFrame"]:
279286
"""Return a dataframe of the last query results."""
287+
try:
288+
import pandas
289+
except ModuleNotFoundError:
290+
raise ModuleNotFoundError(MISSING_MODULE_ERROR_MSG.format(module="pandas"))
291+
280292
columns: typing.Optional[typing.List[typing.Union[str, bytes]]] = None
281293
try:
282294
columns = [column[0].decode().lower() for column in self.description]
@@ -299,18 +311,28 @@ def fetch_dataframe(self: "Cursor", num: typing.Optional[int] = None) -> typing.
299311
return None
300312
return pandas.DataFrame(result, columns=columns)
301313

302-
def write_dataframe(self: "Cursor", df: pandas.DataFrame, table: str) -> None:
314+
def write_dataframe(self: "Cursor", df: "pandas.DataFrame", table: str) -> None:
303315
"""write same structure dataframe into Redshift database"""
304-
arrays: numpy.ndarray = df.values
316+
try:
317+
import pandas
318+
except ModuleNotFoundError:
319+
raise ModuleNotFoundError(MISSING_MODULE_ERROR_MSG.format(module="pandas"))
320+
321+
arrays: "numpy.ndarray" = df.values
305322
placeholder: str = ", ".join(["%s"] * len(arrays[0]))
306323
sql: str = "insert into {table} values ({placeholder})".format(table=table, placeholder=placeholder)
307324
if len(arrays) == 1:
308325
self.execute(sql, arrays[0])
309326
elif len(arrays) > 1:
310327
self.executemany(sql, arrays)
311328

312-
def fetch_numpy_array(self: "Cursor", num: typing.Optional[int] = None) -> numpy.ndarray:
329+
def fetch_numpy_array(self: "Cursor", num: typing.Optional[int] = None) -> "numpy.ndarray":
313330
"""Return a numpy array of the last query results."""
331+
try:
332+
import numpy
333+
except ModuleNotFoundError:
334+
raise ModuleNotFoundError(MISSING_MODULE_ERROR_MSG.format(module="numpy"))
335+
314336
if num:
315337
fetched: typing.Tuple = self.fetchmany(num)
316338
else:

redshift_connector/error.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,3 +140,9 @@ class ArrayDimensionsNotConsistentError(ProgrammingError):
140140
"""
141141

142142
pass
143+
144+
145+
MISSING_MODULE_ERROR_MSG: str = (
146+
"redshift_connector requires {module} support for this functionality. "
147+
"Please install redshfit_connector[full] for {module} support"
148+
)

0 commit comments

Comments
 (0)