diff --git a/spyder/widgets/variableexplorer/dataframeeditor.py b/spyder/widgets/variableexplorer/dataframeeditor.py index e76263682b0..fd1edd9846e 100644 --- a/spyder/widgets/variableexplorer/dataframeeditor.py +++ b/spyder/widgets/variableexplorer/dataframeeditor.py @@ -43,6 +43,9 @@ # Used to convert bool intrance to false since bool('False') will return True _bool_false = ['false', '0'] +# Default format for data frames with floats +DEFAULT_FORMAT = '%.3g' + # Limit at which dataframe is considered so large that it is loaded on demand LARGE_SIZE = 5e5 LARGE_NROWS = 1e5 @@ -83,7 +86,7 @@ class DataFrameModel(QAbstractTableModel): ROWS_TO_LOAD = 500 COLS_TO_LOAD = 40 - def __init__(self, dataFrame, format="%.3g", parent=None): + def __init__(self, dataFrame, format=DEFAULT_FORMAT, parent=None): QAbstractTableModel.__init__(self) self.dialog = parent self.df = dataFrame @@ -274,7 +277,12 @@ def data(self, index, role=Qt.DisplayRole): else: value = self.get_value(row, column-1) if isinstance(value, float): - return to_qvariant(self._format % value) + try: + return to_qvariant(self._format % value) + except (ValueError, TypeError): + # may happen if format = '%d' and value = NaN; + # see issue 4139 + return to_qvariant(DEFAULT_FORMAT % value) else: try: return to_qvariant(to_text_string(value)) diff --git a/spyder/widgets/variableexplorer/tests/test_dataframeeditor.py b/spyder/widgets/variableexplorer/tests/test_dataframeeditor.py index b9cd6591bda..b2c165520e9 100644 --- a/spyder/widgets/variableexplorer/tests/test_dataframeeditor.py +++ b/spyder/widgets/variableexplorer/tests/test_dataframeeditor.py @@ -20,6 +20,7 @@ from pandas import DataFrame, date_range, read_csv from qtpy.QtGui import QColor from qtpy.QtCore import Qt +import numpy import pytest # Local imports @@ -156,6 +157,19 @@ def test_dataframemodel_get_bgcolor_with_object(): a = dataframeeditor.BACKGROUND_MISC_ALPHA assert colorclose(bgcolor(dfm, 0, 1), (h, s, v, a)) +def test_dataframemodel_with_format_percent_d_and_nan(): + """ + Test DataFrameModel with format `%d` and dataframe containing NaN + + Regression test for issue 4139. + """ + np_array = numpy.zeros(2) + np_array[1] = numpy.nan + dataframe = DataFrame(np_array) + dfm = DataFrameModel(dataframe, format='%d') + assert data(dfm, 0, 1) == '0' + assert data(dfm, 1, 1) == 'nan' + def test_change_format_emits_signal(qtbot, monkeypatch): mockQInputDialog = Mock() mockQInputDialog.getText = lambda parent, title, label, mode, text: ('%10.3e', True)