We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Fix case in docs
As mentioned in https://github.com/kedro-org/kedro/pull/1760#pullrequestreview-1069581386_

Change `excel`(lowercase) to `Excel`(uppercase).

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `kedro/extras/datasets/pandas/excel_dataset.py`
Content:
```
1 """``ExcelDataSet`` loads/saves data from/to a Excel file using an underlying
2 filesystem (e.g.: local, S3, GCS). It uses pandas to handle the Excel file.
3 """
4 import logging
5 from copy import deepcopy
6 from io import BytesIO
7 from pathlib import PurePosixPath
8 from typing import Any, Dict, Union
9 
10 import fsspec
11 import pandas as pd
12 
13 from kedro.io.core import (
14     PROTOCOL_DELIMITER,
15     AbstractVersionedDataSet,
16     DataSetError,
17     Version,
18     get_filepath_str,
19     get_protocol_and_path,
20 )
21 
22 logger = logging.getLogger(__name__)
23 
24 
25 class ExcelDataSet(
26     AbstractVersionedDataSet[
27         Union[pd.DataFrame, Dict[str, pd.DataFrame]],
28         Union[pd.DataFrame, Dict[str, pd.DataFrame]],
29     ]
30 ):
31     """``ExcelDataSet`` loads/saves data from/to a Excel file using an underlying
32     filesystem (e.g.: local, S3, GCS). It uses pandas to handle the Excel file.
33 
34     Example adding a catalog entry with the ``YAML API``:
35 
36     .. code-block:: yaml
37 
38         >>> rockets:
39         >>>   type: pandas.ExcelDataSet
40         >>>   filepath: gcs://your_bucket/rockets.xlsx
41         >>>   fs_args:
42         >>>     project: my-project
43         >>>   credentials: my_gcp_credentials
44         >>>   save_args:
45         >>>     sheet_name: Sheet1
46         >>>   load_args:
47         >>>     sheet_name: Sheet1
48         >>>
49         >>> shuttles:
50         >>>   type: pandas.ExcelDataSet
51         >>>   filepath: data/01_raw/shuttles.xlsx
52 
53     Example using Python API:
54     ::
55 
56         >>> from kedro.extras.datasets.pandas import ExcelDataSet
57         >>> import pandas as pd
58         >>>
59         >>> data = pd.DataFrame({'col1': [1, 2], 'col2': [4, 5],
60         >>>                      'col3': [5, 6]})
61         >>>
62         >>> # data_set = ExcelDataSet(filepath="gcs://bucket/test.xlsx")
63         >>> data_set = ExcelDataSet(filepath="test.xlsx")
64         >>> data_set.save(data)
65         >>> reloaded = data_set.load()
66         >>> assert data.equals(reloaded)
67 
68     Note: To save a multi-sheet excel file, no special ``save_args`` are required.
69     Instead, return a dictionary of ``Dict[str, pd.DataFrame]`` where the string
70     keys are your sheet names.
71 
72     Example adding a catalog entry for multi-sheet excel file with the ``YAML API``:
73 
74     .. code-block:: yaml
75 
76         >>> trains:
77         >>>   type: pandas.ExcelDataSet
78         >>>   filepath: data/02_intermediate/company/trains.xlsx
79         >>>   load_args:
80         >>>     sheet_name: [Sheet1, Sheet2, Sheet3]
81 
82     Example multi-sheet excel file using Python API:
83     ::
84 
85         >>> from kedro.extras.datasets.pandas import ExcelDataSet
86         >>> import pandas as pd
87         >>>
88         >>> dataframe = pd.DataFrame({'col1': [1, 2], 'col2': [4, 5],
89         >>>                      'col3': [5, 6]})
90         >>> another_dataframe = pd.DataFrame({"x": [10, 20], "y": ["hello", "world"]})
91         >>> multiframe = {"Sheet1": dataframe, "Sheet2": another_dataframe}
92         >>> data_set = ExcelDataSet(filepath="test.xlsx", load_args = {"sheet_name": None})
93         >>> data_set.save(multiframe)
94         >>> reloaded = data_set.load()
95         >>> assert multiframe["Sheet1"].equals(reloaded["Sheet1"])
96         >>> assert multiframe["Sheet2"].equals(reloaded["Sheet2"])
97 
98     """
99 
100     DEFAULT_LOAD_ARGS = {"engine": "openpyxl"}
101     DEFAULT_SAVE_ARGS = {"index": False}
102 
103     # pylint: disable=too-many-arguments
104     def __init__(
105         self,
106         filepath: str,
107         engine: str = "openpyxl",
108         load_args: Dict[str, Any] = None,
109         save_args: Dict[str, Any] = None,
110         version: Version = None,
111         credentials: Dict[str, Any] = None,
112         fs_args: Dict[str, Any] = None,
113     ) -> None:
114         """Creates a new instance of ``ExcelDataSet`` pointing to a concrete Excel file
115         on a specific filesystem.
116 
117         Args:
118             filepath: Filepath in POSIX format to a Excel file prefixed with a protocol like
119                 `s3://`. If prefix is not provided, `file` protocol (local filesystem) will be used.
120                 The prefix should be any protocol supported by ``fsspec``.
121                 Note: `http(s)` doesn't support versioning.
122             engine: The engine used to write to excel files. The default
123                 engine is 'openpyxl'.
124             load_args: Pandas options for loading Excel files.
125                 Here you can find all available arguments:
126                 https://pandas.pydata.org/pandas-docs/stable/generated/pandas.read_excel.html
127                 All defaults are preserved, but "engine", which is set to "openpyxl".
128                 Supports multi-sheet Excel files (include `sheet_name = None` in `load_args`).
129             save_args: Pandas options for saving Excel files.
130                 Here you can find all available arguments:
131                 https://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.to_excel.html
132                 All defaults are preserved, but "index", which is set to False.
133                 If you would like to specify options for the `ExcelWriter`,
134                 you can include them under the "writer" key. Here you can
135                 find all available arguments:
136                 https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.ExcelWriter.html
137             version: If specified, should be an instance of
138                 ``kedro.io.core.Version``. If its ``load`` attribute is
139                 None, the latest version will be loaded. If its ``save``
140                 attribute is None, save version will be autogenerated.
141             credentials: Credentials required to get access to the underlying filesystem.
142                 E.g. for ``GCSFileSystem`` it should look like `{"token": None}`.
143             fs_args: Extra arguments to pass into underlying filesystem class constructor
144                 (e.g. `{"project": "my-project"}` for ``GCSFileSystem``).
145 
146         Raises:
147             DataSetError: If versioning is enabled while in append mode.
148         """
149         _fs_args = deepcopy(fs_args) or {}
150         _credentials = deepcopy(credentials) or {}
151 
152         protocol, path = get_protocol_and_path(filepath, version)
153         if protocol == "file":
154             _fs_args.setdefault("auto_mkdir", True)
155 
156         self._protocol = protocol
157         self._storage_options = {**_credentials, **_fs_args}
158         self._fs = fsspec.filesystem(self._protocol, **self._storage_options)
159 
160         super().__init__(
161             filepath=PurePosixPath(path),
162             version=version,
163             exists_function=self._fs.exists,
164             glob_function=self._fs.glob,
165         )
166 
167         # Handle default load arguments
168         self._load_args = deepcopy(self.DEFAULT_LOAD_ARGS)
169         if load_args is not None:
170             self._load_args.update(load_args)
171 
172         # Handle default save arguments
173         self._save_args = deepcopy(self.DEFAULT_SAVE_ARGS)
174         if save_args is not None:
175             self._save_args.update(save_args)
176         self._writer_args = self._save_args.pop("writer", {})  # type: ignore
177         self._writer_args.setdefault("engine", engine or "openpyxl")  # type: ignore
178 
179         if version and self._writer_args.get("mode") == "a":  # type: ignore
180             raise DataSetError(
181                 "'ExcelDataSet' doesn't support versioning in append mode."
182             )
183 
184         if "storage_options" in self._save_args or "storage_options" in self._load_args:
185             logger.warning(
186                 "Dropping 'storage_options' for %s, "
187                 "please specify them under 'fs_args' or 'credentials'.",
188                 self._filepath,
189             )
190             self._save_args.pop("storage_options", None)
191             self._load_args.pop("storage_options", None)
192 
193     def _describe(self) -> Dict[str, Any]:
194         return dict(
195             filepath=self._filepath,
196             protocol=self._protocol,
197             load_args=self._load_args,
198             save_args=self._save_args,
199             writer_args=self._writer_args,
200             version=self._version,
201         )
202 
203     def _load(self) -> Union[pd.DataFrame, Dict[str, pd.DataFrame]]:
204         load_path = str(self._get_load_path())
205         if self._protocol == "file":
206             # file:// protocol seems to misbehave on Windows
207             # (<urlopen error file not on local host>),
208             # so we don't join that back to the filepath;
209             # storage_options also don't work with local paths
210             return pd.read_excel(load_path, **self._load_args)
211 
212         load_path = f"{self._protocol}{PROTOCOL_DELIMITER}{load_path}"
213         return pd.read_excel(
214             load_path, storage_options=self._storage_options, **self._load_args
215         )
216 
217     def _save(self, data: Union[pd.DataFrame, Dict[str, pd.DataFrame]]) -> None:
218         output = BytesIO()
219         save_path = get_filepath_str(self._get_save_path(), self._protocol)
220 
221         # pylint: disable=abstract-class-instantiated
222         with pd.ExcelWriter(output, **self._writer_args) as writer:
223             if isinstance(data, dict):
224                 for sheet_name, sheet_data in data.items():
225                     sheet_data.to_excel(
226                         writer, sheet_name=sheet_name, **self._save_args
227                     )
228             else:
229                 data.to_excel(writer, **self._save_args)
230 
231         with self._fs.open(save_path, mode="wb") as fs_file:
232             fs_file.write(output.getvalue())
233 
234         self._invalidate_cache()
235 
236     def _exists(self) -> bool:
237         try:
238             load_path = get_filepath_str(self._get_load_path(), self._protocol)
239         except DataSetError:
240             return False
241 
242         return self._fs.exists(load_path)
243 
244     def _release(self) -> None:
245         super()._release()
246         self._invalidate_cache()
247 
248     def _invalidate_cache(self) -> None:
249         """Invalidate underlying filesystem caches."""
250         filepath = get_filepath_str(self._filepath, self._protocol)
251         self._fs.invalidate_cache(filepath)
252
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/kedro/extras/datasets/pandas/excel_dataset.py b/kedro/extras/datasets/pandas/excel_dataset.py
--- a/kedro/extras/datasets/pandas/excel_dataset.py
+++ b/kedro/extras/datasets/pandas/excel_dataset.py
@@ -65,11 +65,11 @@
         >>> reloaded = data_set.load()
         >>> assert data.equals(reloaded)
 
-    Note: To save a multi-sheet excel file, no special ``save_args`` are required.
+    Note: To save a multi-sheet Excel file, no special ``save_args`` are required.
     Instead, return a dictionary of ``Dict[str, pd.DataFrame]`` where the string
     keys are your sheet names.
 
-    Example adding a catalog entry for multi-sheet excel file with the ``YAML API``:
+    Example adding a catalog entry for multi-sheet Excel file with the ``YAML API``:
 
     .. code-block:: yaml
 
@@ -79,7 +79,7 @@
         >>>   load_args:
         >>>     sheet_name: [Sheet1, Sheet2, Sheet3]
 
-    Example multi-sheet excel file using Python API:
+    Example multi-sheet Excel file using Python API:
     ::
 
         >>> from kedro.extras.datasets.pandas import ExcelDataSet
@@ -119,7 +119,7 @@
                 `s3://`. If prefix is not provided, `file` protocol (local filesystem) will be used.
                 The prefix should be any protocol supported by ``fsspec``.
                 Note: `http(s)` doesn't support versioning.
-            engine: The engine used to write to excel files. The default
+            engine: The engine used to write to Excel files. The default
                 engine is 'openpyxl'.
             load_args: Pandas options for loading Excel files.
                 Here you can find all available arguments:

{"golden_diff": "diff --git a/kedro/extras/datasets/pandas/excel_dataset.py b/kedro/extras/datasets/pandas/excel_dataset.py\n--- a/kedro/extras/datasets/pandas/excel_dataset.py\n+++ b/kedro/extras/datasets/pandas/excel_dataset.py\n@@ -65,11 +65,11 @@\n         >>> reloaded = data_set.load()\n         >>> assert data.equals(reloaded)\n \n-    Note: To save a multi-sheet excel file, no special ``save_args`` are required.\n+    Note: To save a multi-sheet Excel file, no special ``save_args`` are required.\n     Instead, return a dictionary of ``Dict[str, pd.DataFrame]`` where the string\n     keys are your sheet names.\n \n-    Example adding a catalog entry for multi-sheet excel file with the ``YAML API``:\n+    Example adding a catalog entry for multi-sheet Excel file with the ``YAML API``:\n \n     .. code-block:: yaml\n \n@@ -79,7 +79,7 @@\n         >>>   load_args:\n         >>>     sheet_name: [Sheet1, Sheet2, Sheet3]\n \n-    Example multi-sheet excel file using Python API:\n+    Example multi-sheet Excel file using Python API:\n     ::\n \n         >>> from kedro.extras.datasets.pandas import ExcelDataSet\n@@ -119,7 +119,7 @@\n                 `s3://`. If prefix is not provided, `file` protocol (local filesystem) will be used.\n                 The prefix should be any protocol supported by ``fsspec``.\n                 Note: `http(s)` doesn't support versioning.\n-            engine: The engine used to write to excel files. The default\n+            engine: The engine used to write to Excel files. The default\n                 engine is 'openpyxl'.\n             load_args: Pandas options for loading Excel files.\n                 Here you can find all available arguments:\n", "issue": "Fix case in docs\nAs mentioned in https://github.com/kedro-org/kedro/pull/1760#pullrequestreview-1069581386_\r\n\r\nChange `excel`(lowercase) to `Excel`(uppercase).\n", "before_files": [{"content": "\"\"\"``ExcelDataSet`` loads/saves data from/to a Excel file using an underlying\nfilesystem (e.g.: local, S3, GCS). It uses pandas to handle the Excel file.\n\"\"\"\nimport logging\nfrom copy import deepcopy\nfrom io import BytesIO\nfrom pathlib import PurePosixPath\nfrom typing import Any, Dict, Union\n\nimport fsspec\nimport pandas as pd\n\nfrom kedro.io.core import (\n    PROTOCOL_DELIMITER,\n    AbstractVersionedDataSet,\n    DataSetError,\n    Version,\n    get_filepath_str,\n    get_protocol_and_path,\n)\n\nlogger = logging.getLogger(__name__)\n\n\nclass ExcelDataSet(\n    AbstractVersionedDataSet[\n        Union[pd.DataFrame, Dict[str, pd.DataFrame]],\n        Union[pd.DataFrame, Dict[str, pd.DataFrame]],\n    ]\n):\n    \"\"\"``ExcelDataSet`` loads/saves data from/to a Excel file using an underlying\n    filesystem (e.g.: local, S3, GCS). It uses pandas to handle the Excel file.\n\n    Example adding a catalog entry with the ``YAML API``:\n\n    .. code-block:: yaml\n\n        >>> rockets:\n        >>>   type: pandas.ExcelDataSet\n        >>>   filepath: gcs://your_bucket/rockets.xlsx\n        >>>   fs_args:\n        >>>     project: my-project\n        >>>   credentials: my_gcp_credentials\n        >>>   save_args:\n        >>>     sheet_name: Sheet1\n        >>>   load_args:\n        >>>     sheet_name: Sheet1\n        >>>\n        >>> shuttles:\n        >>>   type: pandas.ExcelDataSet\n        >>>   filepath: data/01_raw/shuttles.xlsx\n\n    Example using Python API:\n    ::\n\n        >>> from kedro.extras.datasets.pandas import ExcelDataSet\n        >>> import pandas as pd\n        >>>\n        >>> data = pd.DataFrame({'col1': [1, 2], 'col2': [4, 5],\n        >>>                      'col3': [5, 6]})\n        >>>\n        >>> # data_set = ExcelDataSet(filepath=\"gcs://bucket/test.xlsx\")\n        >>> data_set = ExcelDataSet(filepath=\"test.xlsx\")\n        >>> data_set.save(data)\n        >>> reloaded = data_set.load()\n        >>> assert data.equals(reloaded)\n\n    Note: To save a multi-sheet excel file, no special ``save_args`` are required.\n    Instead, return a dictionary of ``Dict[str, pd.DataFrame]`` where the string\n    keys are your sheet names.\n\n    Example adding a catalog entry for multi-sheet excel file with the ``YAML API``:\n\n    .. code-block:: yaml\n\n        >>> trains:\n        >>>   type: pandas.ExcelDataSet\n        >>>   filepath: data/02_intermediate/company/trains.xlsx\n        >>>   load_args:\n        >>>     sheet_name: [Sheet1, Sheet2, Sheet3]\n\n    Example multi-sheet excel file using Python API:\n    ::\n\n        >>> from kedro.extras.datasets.pandas import ExcelDataSet\n        >>> import pandas as pd\n        >>>\n        >>> dataframe = pd.DataFrame({'col1': [1, 2], 'col2': [4, 5],\n        >>>                      'col3': [5, 6]})\n        >>> another_dataframe = pd.DataFrame({\"x\": [10, 20], \"y\": [\"hello\", \"world\"]})\n        >>> multiframe = {\"Sheet1\": dataframe, \"Sheet2\": another_dataframe}\n        >>> data_set = ExcelDataSet(filepath=\"test.xlsx\", load_args = {\"sheet_name\": None})\n        >>> data_set.save(multiframe)\n        >>> reloaded = data_set.load()\n        >>> assert multiframe[\"Sheet1\"].equals(reloaded[\"Sheet1\"])\n        >>> assert multiframe[\"Sheet2\"].equals(reloaded[\"Sheet2\"])\n\n    \"\"\"\n\n    DEFAULT_LOAD_ARGS = {\"engine\": \"openpyxl\"}\n    DEFAULT_SAVE_ARGS = {\"index\": False}\n\n    # pylint: disable=too-many-arguments\n    def __init__(\n        self,\n        filepath: str,\n        engine: str = \"openpyxl\",\n        load_args: Dict[str, Any] = None,\n        save_args: Dict[str, Any] = None,\n        version: Version = None,\n        credentials: Dict[str, Any] = None,\n        fs_args: Dict[str, Any] = None,\n    ) -> None:\n        \"\"\"Creates a new instance of ``ExcelDataSet`` pointing to a concrete Excel file\n        on a specific filesystem.\n\n        Args:\n            filepath: Filepath in POSIX format to a Excel file prefixed with a protocol like\n                `s3://`. If prefix is not provided, `file` protocol (local filesystem) will be used.\n                The prefix should be any protocol supported by ``fsspec``.\n                Note: `http(s)` doesn't support versioning.\n            engine: The engine used to write to excel files. The default\n                engine is 'openpyxl'.\n            load_args: Pandas options for loading Excel files.\n                Here you can find all available arguments:\n                https://pandas.pydata.org/pandas-docs/stable/generated/pandas.read_excel.html\n                All defaults are preserved, but \"engine\", which is set to \"openpyxl\".\n                Supports multi-sheet Excel files (include `sheet_name = None` in `load_args`).\n            save_args: Pandas options for saving Excel files.\n                Here you can find all available arguments:\n                https://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.to_excel.html\n                All defaults are preserved, but \"index\", which is set to False.\n                If you would like to specify options for the `ExcelWriter`,\n                you can include them under the \"writer\" key. Here you can\n                find all available arguments:\n                https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.ExcelWriter.html\n            version: If specified, should be an instance of\n                ``kedro.io.core.Version``. If its ``load`` attribute is\n                None, the latest version will be loaded. If its ``save``\n                attribute is None, save version will be autogenerated.\n            credentials: Credentials required to get access to the underlying filesystem.\n                E.g. for ``GCSFileSystem`` it should look like `{\"token\": None}`.\n            fs_args: Extra arguments to pass into underlying filesystem class constructor\n                (e.g. `{\"project\": \"my-project\"}` for ``GCSFileSystem``).\n\n        Raises:\n            DataSetError: If versioning is enabled while in append mode.\n        \"\"\"\n        _fs_args = deepcopy(fs_args) or {}\n        _credentials = deepcopy(credentials) or {}\n\n        protocol, path = get_protocol_and_path(filepath, version)\n        if protocol == \"file\":\n            _fs_args.setdefault(\"auto_mkdir\", True)\n\n        self._protocol = protocol\n        self._storage_options = {**_credentials, **_fs_args}\n        self._fs = fsspec.filesystem(self._protocol, **self._storage_options)\n\n        super().__init__(\n            filepath=PurePosixPath(path),\n            version=version,\n            exists_function=self._fs.exists,\n            glob_function=self._fs.glob,\n        )\n\n        # Handle default load arguments\n        self._load_args = deepcopy(self.DEFAULT_LOAD_ARGS)\n        if load_args is not None:\n            self._load_args.update(load_args)\n\n        # Handle default save arguments\n        self._save_args = deepcopy(self.DEFAULT_SAVE_ARGS)\n        if save_args is not None:\n            self._save_args.update(save_args)\n        self._writer_args = self._save_args.pop(\"writer\", {})  # type: ignore\n        self._writer_args.setdefault(\"engine\", engine or \"openpyxl\")  # type: ignore\n\n        if version and self._writer_args.get(\"mode\") == \"a\":  # type: ignore\n            raise DataSetError(\n                \"'ExcelDataSet' doesn't support versioning in append mode.\"\n            )\n\n        if \"storage_options\" in self._save_args or \"storage_options\" in self._load_args:\n            logger.warning(\n                \"Dropping 'storage_options' for %s, \"\n                \"please specify them under 'fs_args' or 'credentials'.\",\n                self._filepath,\n            )\n            self._save_args.pop(\"storage_options\", None)\n            self._load_args.pop(\"storage_options\", None)\n\n    def _describe(self) -> Dict[str, Any]:\n        return dict(\n            filepath=self._filepath,\n            protocol=self._protocol,\n            load_args=self._load_args,\n            save_args=self._save_args,\n            writer_args=self._writer_args,\n            version=self._version,\n        )\n\n    def _load(self) -> Union[pd.DataFrame, Dict[str, pd.DataFrame]]:\n        load_path = str(self._get_load_path())\n        if self._protocol == \"file\":\n            # file:// protocol seems to misbehave on Windows\n            # (<urlopen error file not on local host>),\n            # so we don't join that back to the filepath;\n            # storage_options also don't work with local paths\n            return pd.read_excel(load_path, **self._load_args)\n\n        load_path = f\"{self._protocol}{PROTOCOL_DELIMITER}{load_path}\"\n        return pd.read_excel(\n            load_path, storage_options=self._storage_options, **self._load_args\n        )\n\n    def _save(self, data: Union[pd.DataFrame, Dict[str, pd.DataFrame]]) -> None:\n        output = BytesIO()\n        save_path = get_filepath_str(self._get_save_path(), self._protocol)\n\n        # pylint: disable=abstract-class-instantiated\n        with pd.ExcelWriter(output, **self._writer_args) as writer:\n            if isinstance(data, dict):\n                for sheet_name, sheet_data in data.items():\n                    sheet_data.to_excel(\n                        writer, sheet_name=sheet_name, **self._save_args\n                    )\n            else:\n                data.to_excel(writer, **self._save_args)\n\n        with self._fs.open(save_path, mode=\"wb\") as fs_file:\n            fs_file.write(output.getvalue())\n\n        self._invalidate_cache()\n\n    def _exists(self) -> bool:\n        try:\n            load_path = get_filepath_str(self._get_load_path(), self._protocol)\n        except DataSetError:\n            return False\n\n        return self._fs.exists(load_path)\n\n    def _release(self) -> None:\n        super()._release()\n        self._invalidate_cache()\n\n    def _invalidate_cache(self) -> None:\n        \"\"\"Invalidate underlying filesystem caches.\"\"\"\n        filepath = get_filepath_str(self._filepath, self._protocol)\n        self._fs.invalidate_cache(filepath)\n", "path": "kedro/extras/datasets/pandas/excel_dataset.py"}], "after_files": [{"content": "\"\"\"``ExcelDataSet`` loads/saves data from/to a Excel file using an underlying\nfilesystem (e.g.: local, S3, GCS). It uses pandas to handle the Excel file.\n\"\"\"\nimport logging\nfrom copy import deepcopy\nfrom io import BytesIO\nfrom pathlib import PurePosixPath\nfrom typing import Any, Dict, Union\n\nimport fsspec\nimport pandas as pd\n\nfrom kedro.io.core import (\n    PROTOCOL_DELIMITER,\n    AbstractVersionedDataSet,\n    DataSetError,\n    Version,\n    get_filepath_str,\n    get_protocol_and_path,\n)\n\nlogger = logging.getLogger(__name__)\n\n\nclass ExcelDataSet(\n    AbstractVersionedDataSet[\n        Union[pd.DataFrame, Dict[str, pd.DataFrame]],\n        Union[pd.DataFrame, Dict[str, pd.DataFrame]],\n    ]\n):\n    \"\"\"``ExcelDataSet`` loads/saves data from/to a Excel file using an underlying\n    filesystem (e.g.: local, S3, GCS). It uses pandas to handle the Excel file.\n\n    Example adding a catalog entry with the ``YAML API``:\n\n    .. code-block:: yaml\n\n        >>> rockets:\n        >>>   type: pandas.ExcelDataSet\n        >>>   filepath: gcs://your_bucket/rockets.xlsx\n        >>>   fs_args:\n        >>>     project: my-project\n        >>>   credentials: my_gcp_credentials\n        >>>   save_args:\n        >>>     sheet_name: Sheet1\n        >>>   load_args:\n        >>>     sheet_name: Sheet1\n        >>>\n        >>> shuttles:\n        >>>   type: pandas.ExcelDataSet\n        >>>   filepath: data/01_raw/shuttles.xlsx\n\n    Example using Python API:\n    ::\n\n        >>> from kedro.extras.datasets.pandas import ExcelDataSet\n        >>> import pandas as pd\n        >>>\n        >>> data = pd.DataFrame({'col1': [1, 2], 'col2': [4, 5],\n        >>>                      'col3': [5, 6]})\n        >>>\n        >>> # data_set = ExcelDataSet(filepath=\"gcs://bucket/test.xlsx\")\n        >>> data_set = ExcelDataSet(filepath=\"test.xlsx\")\n        >>> data_set.save(data)\n        >>> reloaded = data_set.load()\n        >>> assert data.equals(reloaded)\n\n    Note: To save a multi-sheet Excel file, no special ``save_args`` are required.\n    Instead, return a dictionary of ``Dict[str, pd.DataFrame]`` where the string\n    keys are your sheet names.\n\n    Example adding a catalog entry for multi-sheet Excel file with the ``YAML API``:\n\n    .. code-block:: yaml\n\n        >>> trains:\n        >>>   type: pandas.ExcelDataSet\n        >>>   filepath: data/02_intermediate/company/trains.xlsx\n        >>>   load_args:\n        >>>     sheet_name: [Sheet1, Sheet2, Sheet3]\n\n    Example multi-sheet Excel file using Python API:\n    ::\n\n        >>> from kedro.extras.datasets.pandas import ExcelDataSet\n        >>> import pandas as pd\n        >>>\n        >>> dataframe = pd.DataFrame({'col1': [1, 2], 'col2': [4, 5],\n        >>>                      'col3': [5, 6]})\n        >>> another_dataframe = pd.DataFrame({\"x\": [10, 20], \"y\": [\"hello\", \"world\"]})\n        >>> multiframe = {\"Sheet1\": dataframe, \"Sheet2\": another_dataframe}\n        >>> data_set = ExcelDataSet(filepath=\"test.xlsx\", load_args = {\"sheet_name\": None})\n        >>> data_set.save(multiframe)\n        >>> reloaded = data_set.load()\n        >>> assert multiframe[\"Sheet1\"].equals(reloaded[\"Sheet1\"])\n        >>> assert multiframe[\"Sheet2\"].equals(reloaded[\"Sheet2\"])\n\n    \"\"\"\n\n    DEFAULT_LOAD_ARGS = {\"engine\": \"openpyxl\"}\n    DEFAULT_SAVE_ARGS = {\"index\": False}\n\n    # pylint: disable=too-many-arguments\n    def __init__(\n        self,\n        filepath: str,\n        engine: str = \"openpyxl\",\n        load_args: Dict[str, Any] = None,\n        save_args: Dict[str, Any] = None,\n        version: Version = None,\n        credentials: Dict[str, Any] = None,\n        fs_args: Dict[str, Any] = None,\n    ) -> None:\n        \"\"\"Creates a new instance of ``ExcelDataSet`` pointing to a concrete Excel file\n        on a specific filesystem.\n\n        Args:\n            filepath: Filepath in POSIX format to a Excel file prefixed with a protocol like\n                `s3://`. If prefix is not provided, `file` protocol (local filesystem) will be used.\n                The prefix should be any protocol supported by ``fsspec``.\n                Note: `http(s)` doesn't support versioning.\n            engine: The engine used to write to Excel files. The default\n                engine is 'openpyxl'.\n            load_args: Pandas options for loading Excel files.\n                Here you can find all available arguments:\n                https://pandas.pydata.org/pandas-docs/stable/generated/pandas.read_excel.html\n                All defaults are preserved, but \"engine\", which is set to \"openpyxl\".\n                Supports multi-sheet Excel files (include `sheet_name = None` in `load_args`).\n            save_args: Pandas options for saving Excel files.\n                Here you can find all available arguments:\n                https://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.to_excel.html\n                All defaults are preserved, but \"index\", which is set to False.\n                If you would like to specify options for the `ExcelWriter`,\n                you can include them under the \"writer\" key. Here you can\n                find all available arguments:\n                https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.ExcelWriter.html\n            version: If specified, should be an instance of\n                ``kedro.io.core.Version``. If its ``load`` attribute is\n                None, the latest version will be loaded. If its ``save``\n                attribute is None, save version will be autogenerated.\n            credentials: Credentials required to get access to the underlying filesystem.\n                E.g. for ``GCSFileSystem`` it should look like `{\"token\": None}`.\n            fs_args: Extra arguments to pass into underlying filesystem class constructor\n                (e.g. `{\"project\": \"my-project\"}` for ``GCSFileSystem``).\n\n        Raises:\n            DataSetError: If versioning is enabled while in append mode.\n        \"\"\"\n        _fs_args = deepcopy(fs_args) or {}\n        _credentials = deepcopy(credentials) or {}\n\n        protocol, path = get_protocol_and_path(filepath, version)\n        if protocol == \"file\":\n            _fs_args.setdefault(\"auto_mkdir\", True)\n\n        self._protocol = protocol\n        self._storage_options = {**_credentials, **_fs_args}\n        self._fs = fsspec.filesystem(self._protocol, **self._storage_options)\n\n        super().__init__(\n            filepath=PurePosixPath(path),\n            version=version,\n            exists_function=self._fs.exists,\n            glob_function=self._fs.glob,\n        )\n\n        # Handle default load arguments\n        self._load_args = deepcopy(self.DEFAULT_LOAD_ARGS)\n        if load_args is not None:\n            self._load_args.update(load_args)\n\n        # Handle default save arguments\n        self._save_args = deepcopy(self.DEFAULT_SAVE_ARGS)\n        if save_args is not None:\n            self._save_args.update(save_args)\n        self._writer_args = self._save_args.pop(\"writer\", {})  # type: ignore\n        self._writer_args.setdefault(\"engine\", engine or \"openpyxl\")  # type: ignore\n\n        if version and self._writer_args.get(\"mode\") == \"a\":  # type: ignore\n            raise DataSetError(\n                \"'ExcelDataSet' doesn't support versioning in append mode.\"\n            )\n\n        if \"storage_options\" in self._save_args or \"storage_options\" in self._load_args:\n            logger.warning(\n                \"Dropping 'storage_options' for %s, \"\n                \"please specify them under 'fs_args' or 'credentials'.\",\n                self._filepath,\n            )\n            self._save_args.pop(\"storage_options\", None)\n            self._load_args.pop(\"storage_options\", None)\n\n    def _describe(self) -> Dict[str, Any]:\n        return dict(\n            filepath=self._filepath,\n            protocol=self._protocol,\n            load_args=self._load_args,\n            save_args=self._save_args,\n            writer_args=self._writer_args,\n            version=self._version,\n        )\n\n    def _load(self) -> Union[pd.DataFrame, Dict[str, pd.DataFrame]]:\n        load_path = str(self._get_load_path())\n        if self._protocol == \"file\":\n            # file:// protocol seems to misbehave on Windows\n            # (<urlopen error file not on local host>),\n            # so we don't join that back to the filepath;\n            # storage_options also don't work with local paths\n            return pd.read_excel(load_path, **self._load_args)\n\n        load_path = f\"{self._protocol}{PROTOCOL_DELIMITER}{load_path}\"\n        return pd.read_excel(\n            load_path, storage_options=self._storage_options, **self._load_args\n        )\n\n    def _save(self, data: Union[pd.DataFrame, Dict[str, pd.DataFrame]]) -> None:\n        output = BytesIO()\n        save_path = get_filepath_str(self._get_save_path(), self._protocol)\n\n        # pylint: disable=abstract-class-instantiated\n        with pd.ExcelWriter(output, **self._writer_args) as writer:\n            if isinstance(data, dict):\n                for sheet_name, sheet_data in data.items():\n                    sheet_data.to_excel(\n                        writer, sheet_name=sheet_name, **self._save_args\n                    )\n            else:\n                data.to_excel(writer, **self._save_args)\n\n        with self._fs.open(save_path, mode=\"wb\") as fs_file:\n            fs_file.write(output.getvalue())\n\n        self._invalidate_cache()\n\n    def _exists(self) -> bool:\n        try:\n            load_path = get_filepath_str(self._get_load_path(), self._protocol)\n        except DataSetError:\n            return False\n\n        return self._fs.exists(load_path)\n\n    def _release(self) -> None:\n        super()._release()\n        self._invalidate_cache()\n\n    def _invalidate_cache(self) -> None:\n        \"\"\"Invalidate underlying filesystem caches.\"\"\"\n        filepath = get_filepath_str(self._filepath, self._protocol)\n        self._fs.invalidate_cache(filepath)\n", "path": "kedro/extras/datasets/pandas/excel_dataset.py"}]}