From a725cf098e6bd258ba79b80ee5e702459053a217 Mon Sep 17 00:00:00 2001 From: phofl Date: Sat, 23 May 2020 13:25:50 +0200 Subject: [PATCH 1/7] BUG: Fix render as column name in to_excel --- pandas/io/formats/excel.py | 3 ++- pandas/tests/io/excel/test_openpyxl.py | 5 +++-- pandas/tests/io/excel/test_writers.py | 8 ++++++++ 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/pandas/io/formats/excel.py b/pandas/io/formats/excel.py index 4ec20977a5e7f..4d32587c0a904 100644 --- a/pandas/io/formats/excel.py +++ b/pandas/io/formats/excel.py @@ -23,6 +23,7 @@ from pandas.io.formats.css import CSSResolver, CSSWarning from pandas.io.formats.format import get_level_lengths from pandas.io.formats.printing import pprint_thing +from pandas.io.formats.style import Styler class ExcelCell: @@ -385,7 +386,7 @@ def __init__( ): self.rowcounter = 0 self.na_rep = na_rep - if hasattr(df, "render"): + if hasattr(df, "render") and isinstance(df, Styler): self.styler = df df = df.data if style_converter is None: diff --git a/pandas/tests/io/excel/test_openpyxl.py b/pandas/tests/io/excel/test_openpyxl.py index 5f8d58ea1f105..6168a2adaef22 100644 --- a/pandas/tests/io/excel/test_openpyxl.py +++ b/pandas/tests/io/excel/test_openpyxl.py @@ -107,10 +107,11 @@ def test_write_append_mode(ext, mode, expected): assert wb2.worksheets[index]["A1"].value == cell_value -def test_to_excel_with_openpyxl_engine(ext, tmpdir): +@pytest.mark.parametrize("col", ["B", "render"]) +def test_to_excel_with_openpyxl_engine(ext, tmpdir, col): # GH 29854 df1 = DataFrame({"A": np.linspace(1, 10, 10)}) - df2 = DataFrame({"B": np.linspace(1, 20, 10)}) + df2 = DataFrame({col: np.linspace(1, 20, 10)}) df = pd.concat([df1, df2], axis=1) styled = df.style.applymap( lambda val: "color: %s" % ("red" if val < 0 else "black") diff --git a/pandas/tests/io/excel/test_writers.py b/pandas/tests/io/excel/test_writers.py index 1692e1a8a0dd3..ff366036714e4 100644 --- a/pandas/tests/io/excel/test_writers.py +++ b/pandas/tests/io/excel/test_writers.py @@ -1201,6 +1201,14 @@ def test_write_lists_dict(self, path): tm.assert_frame_equal(read, expected) + def test_render_as_column_name(self, path): + # see gh-34331 + df = DataFrame({"render": [1, 2], "data": [3, 4]}) + df.to_excel(path, "Sheet1") + read = pd.read_excel(path, "Sheet1", index_col=0) + expected = df + tm.assert_frame_equal(read, expected) + def test_true_and_false_value_options(self, path): # see gh-13347 df = pd.DataFrame([["foo", "bar"]], columns=["col1", "col2"]) From 7e2e0fcab48e3019cb6e9556458cad45639189a4 Mon Sep 17 00:00:00 2001 From: phofl Date: Sat, 23 May 2020 15:06:10 +0200 Subject: [PATCH 2/7] Revert check to not DataFrame --- pandas/io/formats/excel.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/pandas/io/formats/excel.py b/pandas/io/formats/excel.py index 4d32587c0a904..f42c361cebfac 100644 --- a/pandas/io/formats/excel.py +++ b/pandas/io/formats/excel.py @@ -16,14 +16,13 @@ from pandas.core.dtypes.common import is_float, is_scalar from pandas.core.dtypes.generic import ABCIndex -from pandas import Index, MultiIndex, PeriodIndex +from pandas import Index, MultiIndex, PeriodIndex, DataFrame import pandas.core.common as com from pandas.io.common import stringify_path from pandas.io.formats.css import CSSResolver, CSSWarning from pandas.io.formats.format import get_level_lengths from pandas.io.formats.printing import pprint_thing -from pandas.io.formats.style import Styler class ExcelCell: @@ -386,7 +385,7 @@ def __init__( ): self.rowcounter = 0 self.na_rep = na_rep - if hasattr(df, "render") and isinstance(df, Styler): + if hasattr(df, "render") and not isinstance(df, DataFrame): self.styler = df df = df.data if style_converter is None: From 17187eebbf5d98b6d462796cfddb1627c8d3bec3 Mon Sep 17 00:00:00 2001 From: phofl Date: Sat, 23 May 2020 15:36:14 +0200 Subject: [PATCH 3/7] Fix import order --- pandas/io/formats/excel.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas/io/formats/excel.py b/pandas/io/formats/excel.py index f42c361cebfac..54d60ab999429 100644 --- a/pandas/io/formats/excel.py +++ b/pandas/io/formats/excel.py @@ -16,7 +16,7 @@ from pandas.core.dtypes.common import is_float, is_scalar from pandas.core.dtypes.generic import ABCIndex -from pandas import Index, MultiIndex, PeriodIndex, DataFrame +from pandas import DataFrame, Index, MultiIndex, PeriodIndex import pandas.core.common as com from pandas.io.common import stringify_path From 66c531d561213c49c21066f5959d422afd9f2caf Mon Sep 17 00:00:00 2001 From: phofl Date: Sun, 24 May 2020 17:50:06 +0200 Subject: [PATCH 4/7] Add whats new entry --- doc/source/whatsnew/v1.1.0.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/source/whatsnew/v1.1.0.rst b/doc/source/whatsnew/v1.1.0.rst index 41d519e0765dc..ee7ead19faec9 100644 --- a/doc/source/whatsnew/v1.1.0.rst +++ b/doc/source/whatsnew/v1.1.0.rst @@ -794,6 +794,7 @@ I/O - Bug in :meth:`~DataFrame.read_feather` was raising an `ArrowIOError` when reading an s3 or http file path (:issue:`29055`) - Bug in :meth:`read_parquet` was raising a ``FileNotFoundError`` when passed an s3 directory path. (:issue:`26388`) - Bug in :meth:`~DataFrame.to_parquet` was throwing an ``AttributeError`` when writing a partitioned parquet file to s3 (:issue:`27596`) +- Bug in :meth:`~DataFrame.to_excel` could not handle the column name `render` and was raising an ``KeyError`` (:issue:`34331`) Plotting ^^^^^^^^ From f99a3272c2b7bb59ed747138a4aea7c93112dfdd Mon Sep 17 00:00:00 2001 From: phofl Date: Mon, 25 May 2020 20:55:38 +0200 Subject: [PATCH 5/7] Delete hasattr check --- pandas/io/formats/excel.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas/io/formats/excel.py b/pandas/io/formats/excel.py index 54d60ab999429..bf4586a4b5b96 100644 --- a/pandas/io/formats/excel.py +++ b/pandas/io/formats/excel.py @@ -385,7 +385,7 @@ def __init__( ): self.rowcounter = 0 self.na_rep = na_rep - if hasattr(df, "render") and not isinstance(df, DataFrame): + if not isinstance(df, DataFrame): self.styler = df df = df.data if style_converter is None: From c525854baee425c9bb0cc028414a7aa6d3424fa0 Mon Sep 17 00:00:00 2001 From: phofl Date: Tue, 26 May 2020 09:31:30 +0200 Subject: [PATCH 6/7] Split tests --- pandas/tests/io/excel/test_openpyxl.py | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/pandas/tests/io/excel/test_openpyxl.py b/pandas/tests/io/excel/test_openpyxl.py index 6168a2adaef22..15bc3f280e6d2 100644 --- a/pandas/tests/io/excel/test_openpyxl.py +++ b/pandas/tests/io/excel/test_openpyxl.py @@ -107,11 +107,10 @@ def test_write_append_mode(ext, mode, expected): assert wb2.worksheets[index]["A1"].value == cell_value -@pytest.mark.parametrize("col", ["B", "render"]) -def test_to_excel_with_openpyxl_engine(ext, tmpdir, col): +def test_to_excel_with_openpyxl_engine(ext, tmpdir): # GH 29854 df1 = DataFrame({"A": np.linspace(1, 10, 10)}) - df2 = DataFrame({col: np.linspace(1, 20, 10)}) + df2 = DataFrame({"B": np.linspace(1, 20, 10)}) df = pd.concat([df1, df2], axis=1) styled = df.style.applymap( lambda val: "color: %s" % ("red" if val < 0 else "black") @@ -122,3 +121,14 @@ def test_to_excel_with_openpyxl_engine(ext, tmpdir, col): assert filename.exists() os.remove(filename) + + +def test_to_excel_with_column_render(ext, tmpdir): + # GH 34331 + df = DataFrame({"render": [1], "testcolumn": [2]}) + + filename = tmpdir / "render.xlsx" + df.to_excel(filename, engine="openpyxl") + + assert filename.exists() + os.remove(filename) From f0c90a4bcd53770583c41ed1a62590d1dd7f61f2 Mon Sep 17 00:00:00 2001 From: phofl Date: Tue, 26 May 2020 15:16:16 +0200 Subject: [PATCH 7/7] Remove unnecessary test --- pandas/tests/io/excel/test_openpyxl.py | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/pandas/tests/io/excel/test_openpyxl.py b/pandas/tests/io/excel/test_openpyxl.py index 15bc3f280e6d2..5f8d58ea1f105 100644 --- a/pandas/tests/io/excel/test_openpyxl.py +++ b/pandas/tests/io/excel/test_openpyxl.py @@ -121,14 +121,3 @@ def test_to_excel_with_openpyxl_engine(ext, tmpdir): assert filename.exists() os.remove(filename) - - -def test_to_excel_with_column_render(ext, tmpdir): - # GH 34331 - df = DataFrame({"render": [1], "testcolumn": [2]}) - - filename = tmpdir / "render.xlsx" - df.to_excel(filename, engine="openpyxl") - - assert filename.exists() - os.remove(filename)