From 8c748b47d9a619bb6a2336946e8e39cda94dc21a Mon Sep 17 00:00:00 2001 From: Richard Shadrach Date: Sat, 5 Dec 2020 08:57:50 -0500 Subject: [PATCH 1/3] DEPR: xlwt for writing excel files --- doc/source/user_guide/io.rst | 7 +++++++ doc/source/user_guide/options.rst | 9 +++++++++ doc/source/whatsnew/v1.2.0.rst | 25 ++++++++++++++++++++----- pandas/core/config_init.py | 7 +++++++ pandas/core/generic.py | 7 +++++++ pandas/io/excel/_base.py | 26 +++++++++++++++++++++++++- pandas/io/formats/excel.py | 7 +++++++ pandas/tests/io/excel/__init__.py | 5 +++++ pandas/tests/io/excel/test_xlwt.py | 23 ++++++++++++++++++++++- 9 files changed, 109 insertions(+), 7 deletions(-) diff --git a/doc/source/user_guide/io.rst b/doc/source/user_guide/io.rst index 2b324a74fffaf..d9d0662394bd9 100644 --- a/doc/source/user_guide/io.rst +++ b/doc/source/user_guide/io.rst @@ -3200,6 +3200,13 @@ pandas supports writing Excel files to buffer-like objects such as ``StringIO`` Excel writer engines '''''''''''''''''''' +.. deprecated:: 1.2.0 + + The `xlwt `__ + engine, the only engine that supports writing + in an xls format, is no longer maintained and + will be removed in a future version of pandas. + pandas chooses an Excel writer via two methods: 1. the ``engine`` keyword argument diff --git a/doc/source/user_guide/options.rst b/doc/source/user_guide/options.rst index c828bc28826b1..0bd6ce26389a8 100644 --- a/doc/source/user_guide/options.rst +++ b/doc/source/user_guide/options.rst @@ -432,6 +432,15 @@ display.html.use_mathjax True When True, Jupyter notebook dollar symbol. io.excel.xls.writer xlwt The default Excel writer engine for 'xls' files. + + .. deprecated:: 1.2.0 + + The `xlwt `__ + engine, the only engine that supports writing + in an xls format, is no longer maintained and + will be removed in a future version of pandas. + This option will also be removed. + io.excel.xlsm.writer openpyxl The default Excel writer engine for 'xlsm' files. Available options: 'openpyxl' (the default). diff --git a/doc/source/whatsnew/v1.2.0.rst b/doc/source/whatsnew/v1.2.0.rst index 94eb9a0b3fc58..6b572a6e4f1be 100644 --- a/doc/source/whatsnew/v1.2.0.rst +++ b/doc/source/whatsnew/v1.2.0.rst @@ -10,12 +10,27 @@ including other versions of pandas. .. warning:: + The engine `xlrd `_ for reading excel + files and the engine `xlwt `_ for + writing excel files are no longer maintained. + These are the only engines that support the xls format. + Users are recommended to write excel files in the xlsx format using the + `openpyxl `_ engine instead. + Attempting to use the the ``xlwt`` engine will raise a ``FutureWarning`` + unless the option :attr:`io.excel.xls.writer` is set to ``"xlwt"``. + Previously, the default argument ``engine=None`` to ``pd.read_excel`` - would result in using the `xlrd `_ engine in - many cases. The engine ``xlrd`` is no longer maintained, and is not supported with - python >= 3.9. If `openpyxl `_ is installed, - many of these cases will now default to using the ``openpyxl`` engine. See the - :func:`read_excel` documentation for more details. + would result in using the ``xlrd`` engine in many cases. If + ``openpyxl`` is installed, + many of these cases will now default to using the ``openpyxl`` engine. + See the :func:`read_excel` documentation for more details. + + Attempting to read xls files or specifying ``engine="xlrd"`` to + ``pd.read_excel`` will not raise + a ``FutureWarning``. However, users should be aware that ``xlrd`` is + broken with certain configurations of packages, for example with Python 3.9 + when `defusedxml `_ is installed. It + is anticipated to be unusable in the future. .. --------------------------------------------------------------------------- diff --git a/pandas/core/config_init.py b/pandas/core/config_init.py index 541ecd9df6fc7..d4450d32c320c 100644 --- a/pandas/core/config_init.py +++ b/pandas/core/config_init.py @@ -581,6 +581,13 @@ def use_inf_as_na_cb(key): writer_engine_doc.format(ext="xls", others=", ".join(_xls_options)), validator=str, ) +cf.deprecate_option( + "io.excel.xls.writer", + msg="The xlwt engine, the only engine that supports writing in " + "an xls format, is no longer maintained and will be removed in " + "a future version of pandas. This option will also be removed. " + "Install openpyxl and write to an xlsx file instead.", +) with cf.config_prefix("io.excel.xlsm"): cf.register_option( diff --git a/pandas/core/generic.py b/pandas/core/generic.py index 4a9e020a0fe46..e20dcb0d5ec89 100644 --- a/pandas/core/generic.py +++ b/pandas/core/generic.py @@ -2093,6 +2093,13 @@ def to_excel( Write engine to use, 'openpyxl' or 'xlsxwriter'. You can also set this via the options ``io.excel.xlsx.writer``, ``io.excel.xls.writer``, and ``io.excel.xlsm.writer``. + + .. deprecated:: 1.2.0 + + The `xlwt `__ engine, the only engine + that supports writing in an xls format, is no longer maintained and + will be removed in a future version of pandas. + merge_cells : bool, default True Write MultiIndex and Hierarchical Rows as merged cells. encoding : str, optional diff --git a/pandas/io/excel/_base.py b/pandas/io/excel/_base.py index 626c3df196380..1076543b00e58 100644 --- a/pandas/io/excel/_base.py +++ b/pandas/io/excel/_base.py @@ -587,6 +587,13 @@ class ExcelWriter(metaclass=abc.ABCMeta): Engine to use for writing. If None, defaults to ``io.excel..writer``. NOTE: can only be passed as a keyword argument. + + .. deprecated:: 1.2.0 + + The `xlwt `__ engine, the only engine + that supports writing in an xls format, is no longer maintained and + will be removed in a future version of pandas. + date_format : str, default None Format string for dates written into Excel files (e.g. 'YYYY-MM-DD'). datetime_format : str, default None @@ -691,11 +698,28 @@ def __new__(cls, path, engine=None, **kwargs): ext = "xlsx" try: - engine = config.get_option(f"io.excel.{ext}.writer") + engine = config.get_option(f"io.excel.{ext}.writer", silent=True) if engine == "auto": engine = get_default_writer(ext) except KeyError as err: raise ValueError(f"No engine for filetype: '{ext}'") from err + + if engine == "xlwt": + xls_config_engine = config.get_option( + "io.excel.xls.writer", silent=True + ) + # Don't warn a 2nd time if user has changed the default engine for xls + if xls_config_engine != "xlwt": + warnings.warn( + "The xlwt engine, the only engine that supports writing in " + "an xls format, is no longer maintained and will be removed in " + "a future version of pandas. Install openpyxl and write to an " + "xlsx file instead. You can set the option " + "io.excel.xls.writer to 'xlwt' to silence this warning.", + FutureWarning, + stacklevel=4, + ) + cls = get_writer(engine) return object.__new__(cls) diff --git a/pandas/io/formats/excel.py b/pandas/io/formats/excel.py index bded853f383e0..bb62fb644f62e 100644 --- a/pandas/io/formats/excel.py +++ b/pandas/io/formats/excel.py @@ -805,6 +805,13 @@ def write( write engine to use if writer is a path - you can also set this via the options ``io.excel.xlsx.writer``, ``io.excel.xls.writer``, and ``io.excel.xlsm.writer``. + + .. deprecated:: 1.2.0 + + The `xlwt `__ engine, the only engine + that supports writing in an xls format, is no longer maintained and + will be removed in a future version of pandas. + {storage_options} .. versionadded:: 1.2.0 diff --git a/pandas/tests/io/excel/__init__.py b/pandas/tests/io/excel/__init__.py index 419761cbe1d6d..6f80462a08488 100644 --- a/pandas/tests/io/excel/__init__.py +++ b/pandas/tests/io/excel/__init__.py @@ -9,4 +9,9 @@ pytest.mark.filterwarnings( "ignore:This method will be removed in future versions:DeprecationWarning" ), + # GH 26552 + pytest.mark.filterwarnings( + "ignore:The xlwt engine, the only engine that supports writing in an xls " + "format, is no longer maintained" + ), ] diff --git a/pandas/tests/io/excel/test_xlwt.py b/pandas/tests/io/excel/test_xlwt.py index 6bfd71beed0ca..b93008c086d78 100644 --- a/pandas/tests/io/excel/test_xlwt.py +++ b/pandas/tests/io/excel/test_xlwt.py @@ -1,7 +1,7 @@ import numpy as np import pytest -from pandas import DataFrame, MultiIndex +from pandas import DataFrame, MultiIndex, options import pandas._testing as tm from pandas.io.excel import ExcelWriter, _XlwtWriter @@ -69,3 +69,24 @@ def test_write_append_mode_raises(ext): with tm.ensure_clean(ext) as f: with pytest.raises(ValueError, match=msg): ExcelWriter(f, engine="xlwt", mode="a") + + +def test_to_excel_xlwt_warning(ext): + # GH 26552 + df = DataFrame(np.random.randn(3, 10)) + with tm.ensure_clean(ext) as path: + with tm.assert_produces_warning( + FutureWarning, + match="The xlwt engine", + ): + df.to_excel(path) + + +def test_option_xls_writer_deprecated(ext): + # GH 26552 + with tm.assert_produces_warning( + FutureWarning, + match="The xlwt engine", + check_stacklevel=False, + ): + options.io.excel.xls.writer = "xlwt" From 15ca786c7044e116364c00f117492c963b2a2866 Mon Sep 17 00:00:00 2001 From: Richard Shadrach Date: Mon, 7 Dec 2020 07:30:21 -0500 Subject: [PATCH 2/3] Doc changes --- doc/source/user_guide/io.rst | 8 ++++---- doc/source/user_guide/options.rst | 11 +++++----- doc/source/whatsnew/v1.2.0.rst | 32 ++++++++++++++++-------------- pandas/core/config_init.py | 8 ++++---- pandas/core/generic.py | 6 +++--- pandas/io/excel/_base.py | 19 ++++++++++-------- pandas/io/formats/excel.py | 6 +++--- pandas/tests/io/excel/__init__.py | 3 +-- pandas/tests/io/excel/test_xlwt.py | 4 ++-- 9 files changed, 51 insertions(+), 46 deletions(-) diff --git a/doc/source/user_guide/io.rst b/doc/source/user_guide/io.rst index d9d0662394bd9..570eccffea704 100644 --- a/doc/source/user_guide/io.rst +++ b/doc/source/user_guide/io.rst @@ -3202,10 +3202,10 @@ Excel writer engines .. deprecated:: 1.2.0 - The `xlwt `__ - engine, the only engine that supports writing - in an xls format, is no longer maintained and - will be removed in a future version of pandas. + As the `xlwt `__ package is no longer + maintained, the ``xlwt`` engine will be removed from a future version + of pandas. This is the only engine in pandas that supports writing in + the ``xls`` format. pandas chooses an Excel writer via two methods: diff --git a/doc/source/user_guide/options.rst b/doc/source/user_guide/options.rst index 0bd6ce26389a8..bfec8273620c8 100644 --- a/doc/source/user_guide/options.rst +++ b/doc/source/user_guide/options.rst @@ -435,11 +435,12 @@ io.excel.xls.writer xlwt The default Excel writer en .. deprecated:: 1.2.0 - The `xlwt `__ - engine, the only engine that supports writing - in an xls format, is no longer maintained and - will be removed in a future version of pandas. - This option will also be removed. + As `xlwt `__ + package is no longer maintained, the ``xlwt`` + engine will be removed in a future version of + pandas. As this is the only engine in pandas + that supports writing in the xls format, + this option will also be removed. io.excel.xlsm.writer openpyxl The default Excel writer engine for 'xlsm' files. Available options: diff --git a/doc/source/whatsnew/v1.2.0.rst b/doc/source/whatsnew/v1.2.0.rst index 6b572a6e4f1be..55b3a05098e7d 100644 --- a/doc/source/whatsnew/v1.2.0.rst +++ b/doc/source/whatsnew/v1.2.0.rst @@ -10,28 +10,30 @@ including other versions of pandas. .. warning:: - The engine `xlrd `_ for reading excel - files and the engine `xlwt `_ for - writing excel files are no longer maintained. - These are the only engines that support the xls format. - Users are recommended to write excel files in the xlsx format using the - `openpyxl `_ engine instead. - Attempting to use the the ``xlwt`` engine will raise a ``FutureWarning`` - unless the option :attr:`io.excel.xls.writer` is set to ``"xlwt"``. + The packages `xlrd `_ for reading excel + files and `xlwt `_ for + writing excel files are no longer maintained. These are the only engines in pandas + that support the xls format. Previously, the default argument ``engine=None`` to ``pd.read_excel`` would result in using the ``xlrd`` engine in many cases. If - ``openpyxl`` is installed, + `openpyxl `_ is installed, many of these cases will now default to using the ``openpyxl`` engine. - See the :func:`read_excel` documentation for more details. - - Attempting to read xls files or specifying ``engine="xlrd"`` to + See the :func:`read_excel` documentation for more details. Attempting to read + xls files or specifying ``engine="xlrd"`` to ``pd.read_excel`` will not raise - a ``FutureWarning``. However, users should be aware that ``xlrd`` is - broken with certain configurations of packages, for example with Python 3.9 - when `defusedxml `_ is installed. It + a warning. However users should be aware that ``xlrd`` is already + broken with certain package configurations, for example with Python 3.9 + when `defusedxml `_ is installed, and is anticipated to be unusable in the future. + Attempting to use the the ``xlwt`` engine will raise a + ``FutureWarning`` unless the option :attr:`io.excel.xls.writer` is set to + ``"xlwt"``. While this option is now deprecated and will also raise a + ``FutureWarning``, it can be globally set and the warning suppressed. Users + are recommended to write excel files in the ``xlsx`` format using the + ``openpyxl`` engine instead. + .. --------------------------------------------------------------------------- Enhancements diff --git a/pandas/core/config_init.py b/pandas/core/config_init.py index d4450d32c320c..7d9664bd9f965 100644 --- a/pandas/core/config_init.py +++ b/pandas/core/config_init.py @@ -583,10 +583,10 @@ def use_inf_as_na_cb(key): ) cf.deprecate_option( "io.excel.xls.writer", - msg="The xlwt engine, the only engine that supports writing in " - "an xls format, is no longer maintained and will be removed in " - "a future version of pandas. This option will also be removed. " - "Install openpyxl and write to an xlsx file instead.", + msg="As the xlwt package is no longer maintained, the xlwt engine will be " + "removed in a future version of pandas. This is the only engine in pandas that " + "supports writing in the xls format. Install openpyxl and write to an " + "xlsx file instead.", ) with cf.config_prefix("io.excel.xlsm"): diff --git a/pandas/core/generic.py b/pandas/core/generic.py index e20dcb0d5ec89..16b68c9d995f5 100644 --- a/pandas/core/generic.py +++ b/pandas/core/generic.py @@ -2096,9 +2096,9 @@ def to_excel( .. deprecated:: 1.2.0 - The `xlwt `__ engine, the only engine - that supports writing in an xls format, is no longer maintained and - will be removed in a future version of pandas. + As `xlwt `__ package is no longer + maintained, the ``xlwt`` engine will be removed in a future version + of pandas. merge_cells : bool, default True Write MultiIndex and Hierarchical Rows as merged cells. diff --git a/pandas/io/excel/_base.py b/pandas/io/excel/_base.py index 1076543b00e58..f8392952df427 100644 --- a/pandas/io/excel/_base.py +++ b/pandas/io/excel/_base.py @@ -590,9 +590,9 @@ class ExcelWriter(metaclass=abc.ABCMeta): .. deprecated:: 1.2.0 - The `xlwt `__ engine, the only engine - that supports writing in an xls format, is no longer maintained and - will be removed in a future version of pandas. + The `xlwt `__ package is no longer + maintained and the ``xlwt`` engine will be removed in a future + version of pandas. date_format : str, default None Format string for dates written into Excel files (e.g. 'YYYY-MM-DD'). @@ -711,11 +711,14 @@ def __new__(cls, path, engine=None, **kwargs): # Don't warn a 2nd time if user has changed the default engine for xls if xls_config_engine != "xlwt": warnings.warn( - "The xlwt engine, the only engine that supports writing in " - "an xls format, is no longer maintained and will be removed in " - "a future version of pandas. Install openpyxl and write to an " - "xlsx file instead. You can set the option " - "io.excel.xls.writer to 'xlwt' to silence this warning.", + "As the xlwt package is no longer maintained, the xlwt " + "engine will be removed in a future version of pandas. " + "This is the only engine in pandas that supports writing " + "in the xls format. Install openpyxl and write to an xlsx " + "file instead. You can set the option io.excel.xls.writer " + "to 'xlwt' to silence this warning. While this option is " + "deprecated as well and will also raise a warning, it can " + "be globally set and the warning suppressed.", FutureWarning, stacklevel=4, ) diff --git a/pandas/io/formats/excel.py b/pandas/io/formats/excel.py index bb62fb644f62e..be8f2de1d53fb 100644 --- a/pandas/io/formats/excel.py +++ b/pandas/io/formats/excel.py @@ -808,9 +808,9 @@ def write( .. deprecated:: 1.2.0 - The `xlwt `__ engine, the only engine - that supports writing in an xls format, is no longer maintained and - will be removed in a future version of pandas. + As the `xlwt `__ package is no longer + maintained, the ``xlwt`` engine will be removed in a future + version of pandas. {storage_options} diff --git a/pandas/tests/io/excel/__init__.py b/pandas/tests/io/excel/__init__.py index 6f80462a08488..384f1006c44df 100644 --- a/pandas/tests/io/excel/__init__.py +++ b/pandas/tests/io/excel/__init__.py @@ -11,7 +11,6 @@ ), # GH 26552 pytest.mark.filterwarnings( - "ignore:The xlwt engine, the only engine that supports writing in an xls " - "format, is no longer maintained" + "ignore:As the xlwt package is no longer maintained:FutureWarning" ), ] diff --git a/pandas/tests/io/excel/test_xlwt.py b/pandas/tests/io/excel/test_xlwt.py index b93008c086d78..ac53a7d5aee69 100644 --- a/pandas/tests/io/excel/test_xlwt.py +++ b/pandas/tests/io/excel/test_xlwt.py @@ -77,7 +77,7 @@ def test_to_excel_xlwt_warning(ext): with tm.ensure_clean(ext) as path: with tm.assert_produces_warning( FutureWarning, - match="The xlwt engine", + match="As the xlwt package is no longer maintained", ): df.to_excel(path) @@ -86,7 +86,7 @@ def test_option_xls_writer_deprecated(ext): # GH 26552 with tm.assert_produces_warning( FutureWarning, - match="The xlwt engine", + match="As the xlwt package is no longer maintained", check_stacklevel=False, ): options.io.excel.xls.writer = "xlwt" From 595de4cffa940c22d34646d6530c1fb89c584f7d Mon Sep 17 00:00:00 2001 From: Richard Shadrach Date: Mon, 7 Dec 2020 16:43:26 -0500 Subject: [PATCH 3/3] Docs --- doc/source/user_guide/io.rst | 4 ++-- doc/source/user_guide/options.rst | 4 ++-- doc/source/whatsnew/v1.2.0.rst | 16 +++++++--------- pandas/core/generic.py | 2 +- pandas/io/excel/_base.py | 6 +++--- 5 files changed, 15 insertions(+), 17 deletions(-) diff --git a/doc/source/user_guide/io.rst b/doc/source/user_guide/io.rst index 570eccffea704..965833c013c03 100644 --- a/doc/source/user_guide/io.rst +++ b/doc/source/user_guide/io.rst @@ -3204,8 +3204,8 @@ Excel writer engines As the `xlwt `__ package is no longer maintained, the ``xlwt`` engine will be removed from a future version - of pandas. This is the only engine in pandas that supports writing in - the ``xls`` format. + of pandas. This is the only engine in pandas that supports writing to + ``.xls`` files. pandas chooses an Excel writer via two methods: diff --git a/doc/source/user_guide/options.rst b/doc/source/user_guide/options.rst index bfec8273620c8..b8e75b0535823 100644 --- a/doc/source/user_guide/options.rst +++ b/doc/source/user_guide/options.rst @@ -438,8 +438,8 @@ io.excel.xls.writer xlwt The default Excel writer en As `xlwt `__ package is no longer maintained, the ``xlwt`` engine will be removed in a future version of - pandas. As this is the only engine in pandas - that supports writing in the xls format, + pandas. Since this is the only engine in pandas + that supports writing to ``.xls`` files, this option will also be removed. io.excel.xlsm.writer openpyxl The default Excel writer engine for diff --git a/doc/source/whatsnew/v1.2.0.rst b/doc/source/whatsnew/v1.2.0.rst index 4f6cfb588f289..ef50389ea9f44 100644 --- a/doc/source/whatsnew/v1.2.0.rst +++ b/doc/source/whatsnew/v1.2.0.rst @@ -20,19 +20,17 @@ including other versions of pandas. `openpyxl `_ is installed, many of these cases will now default to using the ``openpyxl`` engine. See the :func:`read_excel` documentation for more details. Attempting to read - xls files or specifying ``engine="xlrd"`` to - ``pd.read_excel`` will not raise - a warning. However users should be aware that ``xlrd`` is already + ``.xls`` files or specifying ``engine="xlrd"`` to ``pd.read_excel`` will not + raise a warning. However users should be aware that ``xlrd`` is already broken with certain package configurations, for example with Python 3.9 when `defusedxml `_ is installed, and is anticipated to be unusable in the future. - Attempting to use the the ``xlwt`` engine will raise a - ``FutureWarning`` unless the option :attr:`io.excel.xls.writer` is set to - ``"xlwt"``. While this option is now deprecated and will also raise a - ``FutureWarning``, it can be globally set and the warning suppressed. Users - are recommended to write excel files in the ``xlsx`` format using the - ``openpyxl`` engine instead. + Attempting to use the the ``xlwt`` engine will raise a ``FutureWarning`` + unless the option :attr:`io.excel.xls.writer` is set to ``"xlwt"``. + While this option is now deprecated and will also raise a ``FutureWarning``, + it can be globally set and the warning suppressed. Users are recommended to + write ``.xlsx`` files using the ``openpyxl`` engine instead. .. --------------------------------------------------------------------------- diff --git a/pandas/core/generic.py b/pandas/core/generic.py index 16b68c9d995f5..c5ecda408557b 100644 --- a/pandas/core/generic.py +++ b/pandas/core/generic.py @@ -2096,7 +2096,7 @@ def to_excel( .. deprecated:: 1.2.0 - As `xlwt `__ package is no longer + As the `xlwt `__ package is no longer maintained, the ``xlwt`` engine will be removed in a future version of pandas. diff --git a/pandas/io/excel/_base.py b/pandas/io/excel/_base.py index f8392952df427..bf1011176693f 100644 --- a/pandas/io/excel/_base.py +++ b/pandas/io/excel/_base.py @@ -590,8 +590,8 @@ class ExcelWriter(metaclass=abc.ABCMeta): .. deprecated:: 1.2.0 - The `xlwt `__ package is no longer - maintained and the ``xlwt`` engine will be removed in a future + As the `xlwt `__ package is no longer + maintained, the ``xlwt`` engine will be removed in a future version of pandas. date_format : str, default None @@ -717,7 +717,7 @@ def __new__(cls, path, engine=None, **kwargs): "in the xls format. Install openpyxl and write to an xlsx " "file instead. You can set the option io.excel.xls.writer " "to 'xlwt' to silence this warning. While this option is " - "deprecated as well and will also raise a warning, it can " + "deprecated and will also raise a warning, it can " "be globally set and the warning suppressed.", FutureWarning, stacklevel=4,