Repository: kedro-org/kedro

Issue:
MatplotlibWriter overwrite list of figures does not work.
## Description
The latest MatplotlibWriter (which has not been released as stable yet) has an error here:
(https://github.com/quantumblacklabs/kedro/blob/b76707669cde0b860389cd24a4397cbce001d13c/kedro/extras/datasets/matplotlib/matplotlib_writer.py#L149)

Where self._filepath is an object of 'PurePosixPath' which is not iterable.

## Context
I wanted to output a list of matplotlib figures using this dataset and using the new attribute **overwrite=True**.

## Steps to Reproduce
Here is a snippet that reproduces the error:
```
from kedro.extras.datasets.matplotlib import MatplotlibWriter
import matplotlib.pyplot as plt

# We run save twice so that the figure is overwritten the second time:
for i in range(2):

    dataset = MatplotlibWriter(filepath='test', overwrite=True)
    figs = []
    for i in range(3):
        fig,ax=plt.subplots()
        ax.plot([1,2,3])
        figs.append(fig)
        
    dataset.save(figs)
```


```
TypeError: 'PurePosixPath' object is not iterable
```

# Solution suggestion:
Convert the PurePosixPath object to string solves the problem:
`self._fs.rm(str(self._filepath), recursive=True)`

## Your Environment
Include as many relevant details about the environment in which you experienced the bug:

* Kedro (latest) (current stable 0.17.5 does not have **overwrite** attribute):
* Python version used 3.7
* Operating system and version: Win10




Discussion:
Hi @martinlarsalbert, thanks very much for this bug report. I can confirm this is a definite problem, and actually now I'm looking at it again I think there might be a couple of other things we need to check about this new `overwrite` functionality.

* I think the fix here would be to use `get_filepath_str(self._filepath, self._protocol)` rather than just `self._filepath` in the call to `rm`
* BUT we need to be careful we're using the actual right filepath here. What should happen if versioning is enabled in the dataset? Should we delete the whole folder containing all saved versions? I think probably not.
* why did our tests not catch this in the first place?

Whatever fix we do here will presumably need to be made for `PartitionedDataSet` where we also added the `overwrite` option.

cc @deepyaman 
I think that the test must first create a file and then overwrite it (running the method twice), perhaps the test just created the file?

Resolving patch:
diff --git a/kedro/extras/datasets/matplotlib/matplotlib_writer.py b/kedro/extras/datasets/matplotlib/matplotlib_writer.py
--- a/kedro/extras/datasets/matplotlib/matplotlib_writer.py
+++ b/kedro/extras/datasets/matplotlib/matplotlib_writer.py
@@ -5,6 +5,7 @@
 from copy import deepcopy
 from pathlib import PurePosixPath
 from typing import Any, Dict, List, Union
+from warnings import warn
 
 import fsspec
 import matplotlib.pyplot as plt
@@ -123,6 +124,13 @@ def __init__(
         if save_args is not None:
             self._save_args.update(save_args)
 
+        if overwrite and version is not None:
+            warn(
+                "Setting `overwrite=True` is ineffective if versioning "
+                "is enabled, since the versioned path must not already "
+                "exist; overriding flag with `overwrite=False` instead."
+            )
+            overwrite = False
         self._overwrite = overwrite
 
     def _describe(self) -> Dict[str, Any]:
@@ -141,12 +149,8 @@ def _save(
     ) -> None:
         save_path = self._get_save_path()
 
-        if (
-            isinstance(data, (list, dict))
-            and self._overwrite
-            and self._fs.exists(self._filepath)
-        ):
-            self._fs.rm(self._filepath, recursive=True)
+        if isinstance(data, (list, dict)) and self._overwrite and self._exists():
+            self._fs.rm(get_filepath_str(save_path, self._protocol), recursive=True)
 
         if isinstance(data, list):
             for index, plot in enumerate(data):
diff --git a/kedro/io/core.py b/kedro/io/core.py
--- a/kedro/io/core.py
+++ b/kedro/io/core.py
@@ -704,7 +704,7 @@ def get_protocol_and_path(filepath: str, version: Version = None) -> Tuple[str,
     protocol = options_dict["protocol"]
 
     if protocol in HTTP_PROTOCOLS:
-        if version:
+        if version is not None:
             raise DataSetError(
                 "HTTP(s) DataSet doesn't support versioning. "
                 "Please remove version flag from the dataset configuration."
diff --git a/kedro/io/partitioned_data_set.py b/kedro/io/partitioned_data_set.py
--- a/kedro/io/partitioned_data_set.py
+++ b/kedro/io/partitioned_data_set.py
@@ -258,8 +258,8 @@ def _load(self) -> Dict[str, Callable[[], Any]]:
         return partitions
 
     def _save(self, data: Dict[str, Any]) -> None:
-        if self._overwrite and self._filesystem.exists(self._path):
-            self._filesystem.rm(self._path, recursive=True)
+        if self._overwrite and self._filesystem.exists(self._normalized_path):
+            self._filesystem.rm(self._normalized_path, recursive=True)
 
         for partition_id, partition_data in sorted(data.items()):
             kwargs = deepcopy(self._dataset_config)
@@ -439,8 +439,9 @@ def _parse_checkpoint_config(
         if self._credentials:
             default_config[CREDENTIALS_KEY] = deepcopy(self._credentials)
 
-        # pylint: disable=consider-iterating-dictionary
-        if CREDENTIALS_KEY in default_config.keys() & checkpoint_config.keys():
+        if (  # pylint: disable=consider-iterating-dictionary
+            CREDENTIALS_KEY in default_config.keys() & checkpoint_config.keys()
+        ):
             self._logger.warning(
                 KEY_PROPAGATION_WARNING,
                 {"keys": CREDENTIALS_KEY, "target": "checkpoint"},


Test patch:
diff --git a/tests/extras/datasets/matplotlib/test_matplotlib_writer.py b/tests/extras/datasets/matplotlib/test_matplotlib_writer.py
--- a/tests/extras/datasets/matplotlib/test_matplotlib_writer.py
+++ b/tests/extras/datasets/matplotlib/test_matplotlib_writer.py
@@ -284,6 +284,20 @@ def test_prevent_overwrite(self, mock_single_plot, versioned_plot_writer):
         with pytest.raises(DataSetError, match=pattern):
             versioned_plot_writer.save(mock_single_plot)
 
+    def test_ineffective_overwrite(self, load_version, save_version):
+        pattern = (
+            "Setting `overwrite=True` is ineffective if versioning "
+            "is enabled, since the versioned path must not already "
+            "exist; overriding flag with `overwrite=False` instead."
+        )
+        with pytest.warns(UserWarning, match=pattern):
+            versioned_plot_writer = MatplotlibWriter(
+                filepath="/tmp/file.txt",
+                version=Version(load_version, save_version),
+                overwrite=True,
+            )
+        assert not versioned_plot_writer._overwrite
+
     @pytest.mark.parametrize(
         "load_version", ["2019-01-01T23.59.59.999Z"], indirect=True
     )