Skip to content

Commit

Permalink
REGR: ExcelWriter.book not settable (pandas-dev#48943)
Browse files Browse the repository at this point in the history
  • Loading branch information
rhshadrach authored and noatamir committed Nov 9, 2022
1 parent 5f66c14 commit 0395255
Show file tree
Hide file tree
Showing 7 changed files with 79 additions and 4 deletions.
1 change: 1 addition & 0 deletions doc/source/whatsnew/v1.5.1.rst
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ Fixed regressions
- Fixed Regression in :meth:`DataFrameGroupBy.apply` when user defined function is called on an empty dataframe (:issue:`47985`)
- Fixed regression in :meth:`DataFrame.apply` when passing non-zero ``axis`` via keyword argument (:issue:`48656`)
- Fixed regression in :meth:`Series.groupby` and :meth:`DataFrame.groupby` when the grouper is a nullable data type (e.g. :class:`Int64`) or a PyArrow-backed string array, contains null values, and ``dropna=False`` (:issue:`48794`)
- Fixed regression in :class:`ExcelWriter` where the ``book`` attribute could no longer be set; however setting this attribute is now deprecated and this ability will be removed in a future version of pandas (:issue:`48780`)

.. ---------------------------------------------------------------------------
Expand Down
22 changes: 21 additions & 1 deletion pandas/io/excel/_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -1203,6 +1203,14 @@ def book(self):
"""
pass

@book.setter
@abc.abstractmethod
def book(self, other) -> None:
"""
Set book instance. Class type will depend on the engine used.
"""
pass

def write_cells(
self,
cells,
Expand Down Expand Up @@ -1332,12 +1340,24 @@ def _deprecate(self, attr: str) -> None:
Deprecate attribute or method for ExcelWriter.
"""
warnings.warn(
f"{attr} is not part of the public API, usage can give in unexpected "
f"{attr} is not part of the public API, usage can give unexpected "
"results and will be removed in a future version",
FutureWarning,
stacklevel=find_stack_level(inspect.currentframe()),
)

def _deprecate_set_book(self) -> None:
"""
Deprecate setting the book attribute - GH#48780.
"""
warnings.warn(
"Setting the `book` attribute is not part of the public API, "
"usage can give unexpected or corrupted results and will be "
"removed in a future version",
FutureWarning,
stacklevel=find_stack_level(inspect.currentframe()),
)

@property
def date_format(self) -> str:
"""
Expand Down
10 changes: 10 additions & 0 deletions pandas/io/excel/_odswriter.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
)

if TYPE_CHECKING:
from odf.opendocument import OpenDocumentSpreadsheet

from pandas.io.formats.excel import ExcelCell


Expand Down Expand Up @@ -70,6 +72,14 @@ def book(self):
"""
return self._book

@book.setter
def book(self, other: OpenDocumentSpreadsheet) -> None:
"""
Set book instance. Class type will depend on the engine used.
"""
self._deprecate_set_book()
self._book = other

@property
def sheets(self) -> dict[str, Any]:
"""Mapping of sheet names to sheet objects."""
Expand Down
8 changes: 8 additions & 0 deletions pandas/io/excel/_openpyxl.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,14 @@ def book(self) -> Workbook:
"""
return self._book

@book.setter
def book(self, other: Workbook) -> None:
"""
Set book instance. Class type will depend on the engine used.
"""
self._deprecate_set_book()
self._book = other

@property
def sheets(self) -> dict[str, Any]:
"""Mapping of sheet names to sheet objects."""
Expand Down
16 changes: 15 additions & 1 deletion pandas/io/excel/_xlsxwriter.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
from __future__ import annotations

from typing import Any
from typing import (
TYPE_CHECKING,
Any,
)

import pandas._libs.json as json
from pandas._typing import (
Expand All @@ -15,6 +18,9 @@
validate_freeze_panes,
)

if TYPE_CHECKING:
from xlsxwriter import Workbook


class _XlsxStyler:
# Map from openpyxl-oriented styles to flatter xlsxwriter representation
Expand Down Expand Up @@ -218,6 +224,14 @@ def book(self):
"""
return self._book

@book.setter
def book(self, other: Workbook) -> None:
"""
Set book instance. Class type will depend on the engine used.
"""
self._deprecate_set_book()
self._book = other

@property
def sheets(self) -> dict[str, Any]:
result = self.book.sheetnames
Expand Down
15 changes: 13 additions & 2 deletions pandas/io/excel/_xlwt.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,10 @@
)

if TYPE_CHECKING:
from xlwt import XFStyle
from xlwt import (
Workbook,
XFStyle,
)


class XlwtWriter(ExcelWriter):
Expand Down Expand Up @@ -64,14 +67,22 @@ def __init__(
self._fm_date = xlwt.easyxf(num_format_str=self._date_format)

@property
def book(self):
def book(self) -> Workbook:
"""
Book instance of class xlwt.Workbook.
This attribute can be used to access engine-specific features.
"""
return self._book

@book.setter
def book(self, other: Workbook) -> None:
"""
Set book instance. Class type will depend on the engine used.
"""
self._deprecate_set_book()
self._book = other

@property
def sheets(self) -> dict[str, Any]:
"""Mapping of sheet names to sheet objects."""
Expand Down
11 changes: 11 additions & 0 deletions pandas/tests/io/excel/test_writers.py
Original file line number Diff line number Diff line change
Expand Up @@ -1301,6 +1301,17 @@ def test_deprecated_method(self, engine, ext, attr, args):
with tm.assert_produces_warning(FutureWarning, match=msg):
getattr(writer, attr)(*args)

def test_deprecated_book_setter(self, engine, ext):
# GH#48780
with tm.ensure_clean(ext) as path:
with ExcelWriter(path) as writer:
msg = "Setting the `book` attribute is not part of the public API"
# Some engines raise if nothing is written
DataFrame().to_excel(writer)
book = writer.book
with tm.assert_produces_warning(FutureWarning, match=msg):
writer.book = book


class TestExcelWriterEngineTests:
@pytest.mark.parametrize(
Expand Down

0 comments on commit 0395255

Please sign in to comment.