Skip to content

Commit

Permalink
DEPR: **kwargs in ExcelWriter (#40430)
Browse files Browse the repository at this point in the history
  • Loading branch information
rhshadrach authored Mar 17, 2021
1 parent 8588651 commit 7e0f5ca
Show file tree
Hide file tree
Showing 7 changed files with 98 additions and 14 deletions.
1 change: 1 addition & 0 deletions doc/source/whatsnew/v1.3.0.rst
Original file line number Diff line number Diff line change
Expand Up @@ -405,6 +405,7 @@ Deprecations
- Deprecated :meth:`.Styler.set_na_rep` and :meth:`.Styler.set_precision` in favour of :meth:`.Styler.format` with ``na_rep`` and ``precision`` as existing and new input arguments respectively (:issue:`40134`, :issue:`40425`)
- Deprecated allowing partial failure in :meth:`Series.transform` and :meth:`DataFrame.transform` when ``func`` is list-like or dict-like; will raise if any function fails on a column in a future version (:issue:`40211`)
- Deprecated support for ``np.ma.mrecords.MaskedRecords`` in the :class:`DataFrame` constructor, pass ``{name: data[name] for name in data.dtype.names}`` instead (:issue:`40363`)
- Deprecated the use of ``**kwargs`` in :class:`.ExcelWriter`; use the keyword argument ``engine_kwargs`` instead (:issue:`40430`)

.. ---------------------------------------------------------------------------
Expand Down
34 changes: 32 additions & 2 deletions pandas/io/excel/_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -667,6 +667,16 @@ class ExcelWriter(metaclass=abc.ABCMeta):
be parsed by ``fsspec``, e.g., starting "s3://", "gcs://".
.. versionadded:: 1.2.0
engine_kwargs : dict, optional
Keyword arguments to be passed into the engine.
.. versionadded:: 1.3.0
**kwargs : dict, optional
Keyword arguments to be passed into the engine.
.. deprecated:: 1.3.0
Use engine_kwargs instead.
Attributes
----------
Expand Down Expand Up @@ -745,7 +755,26 @@ class ExcelWriter(metaclass=abc.ABCMeta):
# You also need to register the class with ``register_writer()``.
# Technically, ExcelWriter implementations don't need to subclass
# ExcelWriter.
def __new__(cls, path, engine=None, **kwargs):
def __new__(
cls,
path: Union[FilePathOrBuffer, ExcelWriter],
engine=None,
date_format=None,
datetime_format=None,
mode: str = "w",
storage_options: StorageOptions = None,
engine_kwargs: Optional[Dict] = None,
**kwargs,
):
if kwargs:
if engine_kwargs is not None:
raise ValueError("Cannot use both engine_kwargs and **kwargs")
warnings.warn(
"Use of **kwargs is deprecated, use engine_kwargs instead.",
FutureWarning,
stacklevel=2,
)

# only switch class if generic(ExcelWriter)

if cls is ExcelWriter:
Expand Down Expand Up @@ -835,7 +864,8 @@ def __init__(
datetime_format=None,
mode: str = "w",
storage_options: StorageOptions = None,
**engine_kwargs,
engine_kwargs: Optional[Dict] = None,
**kwargs,
):
# validate that this engine can handle the extension
if isinstance(path, str):
Expand Down
11 changes: 7 additions & 4 deletions pandas/io/excel/_odswriter.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,19 +26,22 @@ def __init__(
self,
path: str,
engine: Optional[str] = None,
date_format=None,
datetime_format=None,
mode: str = "w",
storage_options: StorageOptions = None,
**engine_kwargs,
engine_kwargs: Optional[Dict[str, Any]] = None,
):
from odf.opendocument import OpenDocumentSpreadsheet

engine_kwargs["engine"] = engine

if mode == "a":
raise ValueError("Append mode is not supported with odf!")

super().__init__(
path, mode=mode, storage_options=storage_options, **engine_kwargs
path,
mode=mode,
storage_options=storage_options,
engine_kwargs=engine_kwargs,
)

self.book = OpenDocumentSpreadsheet()
Expand Down
10 changes: 8 additions & 2 deletions pandas/io/excel/_openpyxl.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import mmap
from typing import (
TYPE_CHECKING,
Any,
Dict,
List,
Optional,
Expand Down Expand Up @@ -35,15 +36,20 @@ def __init__(
self,
path,
engine=None,
date_format=None,
datetime_format=None,
mode: str = "w",
storage_options: StorageOptions = None,
**engine_kwargs,
engine_kwargs: Optional[Dict[str, Any]] = None,
):
# Use the openpyxl module as the Excel writer.
from openpyxl.workbook import Workbook

super().__init__(
path, mode=mode, storage_options=storage_options, **engine_kwargs
path,
mode=mode,
storage_options=storage_options,
engine_kwargs=engine_kwargs,
)

# ExcelWriter replaced "a" by "r+" to allow us to first read the excel file from
Expand Down
8 changes: 6 additions & 2 deletions pandas/io/excel/_xlsxwriter.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
from typing import (
Any,
Dict,
List,
Optional,
Tuple,
)

Expand Down Expand Up @@ -175,11 +177,13 @@ def __init__(
datetime_format=None,
mode: str = "w",
storage_options: StorageOptions = None,
**engine_kwargs,
engine_kwargs: Optional[Dict[str, Any]] = None,
):
# Use the xlsxwriter module as the Excel writer.
from xlsxwriter import Workbook

engine_kwargs = engine_kwargs or {}

if mode == "a":
raise ValueError("Append mode is not supported with xlsxwriter!")

Expand All @@ -190,7 +194,7 @@ def __init__(
datetime_format=datetime_format,
mode=mode,
storage_options=storage_options,
**engine_kwargs,
engine_kwargs=engine_kwargs,
)

self.book = Workbook(self.handles.handle, **engine_kwargs)
Expand Down
13 changes: 9 additions & 4 deletions pandas/io/excel/_xlwt.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
from typing import (
TYPE_CHECKING,
Any,
Dict,
Optional,
)

import pandas._libs.json as json
Expand All @@ -21,21 +23,24 @@ def __init__(
self,
path,
engine=None,
date_format=None,
datetime_format=None,
encoding=None,
mode: str = "w",
storage_options: StorageOptions = None,
**engine_kwargs,
engine_kwargs: Optional[Dict[str, Any]] = None,
):
# Use the xlwt module as the Excel writer.
import xlwt

engine_kwargs["engine"] = engine

if mode == "a":
raise ValueError("Append mode is not supported with xlwt!")

super().__init__(
path, mode=mode, storage_options=storage_options, **engine_kwargs
path,
mode=mode,
storage_options=storage_options,
engine_kwargs=engine_kwargs,
)

if encoding is None:
Expand Down
35 changes: 35 additions & 0 deletions pandas/tests/io/excel/test_writers.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from functools import partial
from io import BytesIO
import os
import re

import numpy as np
import pytest
Expand Down Expand Up @@ -1382,6 +1383,40 @@ def check_called(func):
with tm.ensure_clean("something.xls") as filepath:
check_called(lambda: df.to_excel(filepath, engine="dummy"))

@pytest.mark.parametrize(
"ext",
[
pytest.param(".xlsx", marks=td.skip_if_no("xlsxwriter")),
pytest.param(".xlsx", marks=td.skip_if_no("openpyxl")),
pytest.param(".ods", marks=td.skip_if_no("odf")),
],
)
def test_kwargs_deprecated(self, ext):
# GH 40430
msg = re.escape("Use of **kwargs is deprecated")
with tm.assert_produces_warning(FutureWarning, match=msg):
with tm.ensure_clean(ext) as path:
try:
with ExcelWriter(path, kwarg=1):
pass
except TypeError:
pass

@pytest.mark.parametrize(
"ext",
[
pytest.param(".xlsx", marks=td.skip_if_no("xlsxwriter")),
pytest.param(".xlsx", marks=td.skip_if_no("openpyxl")),
pytest.param(".ods", marks=td.skip_if_no("odf")),
],
)
def test_engine_kwargs_and_kwargs_raises(self, ext):
# GH 40430
msg = re.escape("Cannot use both engine_kwargs and **kwargs")
with pytest.raises(ValueError, match=msg):
with ExcelWriter("", engine_kwargs={"a": 1}, b=2):
pass


@td.skip_if_no("xlrd")
@td.skip_if_no("openpyxl")
Expand Down

0 comments on commit 7e0f5ca

Please sign in to comment.