Repository: kedro-org/kedro
File: kedro/io/core.py (Python)

Code before:
        Raises:
            DatasetError: When underlying load method raises error.

        """

        self._logger.debug("Loading %s", str(self))

        try:
            return self._load()
        except DatasetError:
            raise
        except Exception as exc:
            # This exception handling is by design as the composed data sets
            # can throw any type of exception.
            message = (
                f"Failed while loading data from data set {str(self)}.\n{str(exc)}"
            )
            raise DatasetError(message) from exc

    def save(self, data: _DI) -> None:
        """Saves data by delegation to the provided save method.

        Args:
            data: the value to be saved by provided save method.

        Raises:
            DatasetError: when underlying save method raises error.
            FileNotFoundError: when save method got file instead of dir, on Windows.
            NotADirectoryError: when save method got file instead of dir, on Unix.
        """

        if data is None:
            raise DatasetError("Saving 'None' to a 'Dataset' is not allowed")

        try:
            self._logger.debug("Saving %s", str(self))
            self._save(data)
        except (DatasetError, FileNotFoundError, NotADirectoryError):
            raise
        except Exception as exc:
            message = f"Failed while saving data to data set {str(self)}.\n{str(exc)}"
            raise DatasetError(message) from exc

    def __str__(self) -> str:
        def _to_str(obj: Any, is_root: bool = False) -> str:
            """Returns a string representation where
            1. The root level (i.e. the Dataset.__init__ arguments) are
            formatted like Dataset(key=value).
            2. Dictionaries have the keys alphabetically sorted recursively.
            3. None values are not shown.
            """

Review comment (refactor):
The test on ``__qualname__.startswith`` exist in MlflowArtifactDataset but I think there is no test on ``MlflowAbstractDataset`` which could conflict, so hopefully we are fine 🤞 

Code after:
            except Exception as exc:
                message = (
                    f"Failed while saving data to data set {str(self)}.\n{str(exc)}"
                )
                raise DatasetError(message) from exc

        save.__annotations__["data"] = save_func.__annotations__.get("data", Any)
        save.__annotations__["return"] = save_func.__annotations__.get("return")
        save.__savewrapped__ = True  # type: ignore[attr-defined]
        return save

    def __init_subclass__(cls, **kwargs: Any) -> None:
        """Decorate the `load` and `save` methods provided by the class.

        If `_load` or `_save` are defined, alias them as a prerequisite.

        """
        super().__init_subclass__(**kwargs)

        if hasattr(cls, "_load") and not cls._load.__qualname__.startswith("Abstract"):
            cls.load = cls._load  # type: ignore[method-assign]

        if hasattr(cls, "_save") and not cls._save.__qualname__.startswith("Abstract"):
            cls.save = cls._save  # type: ignore[method-assign]

        if hasattr(cls, "load") and not cls.load.__qualname__.startswith("Abstract"):
            cls.load = cls._load_wrapper(  # type: ignore[assignment]
                cls.load
                if not getattr(cls.load, "__loadwrapped__", False)
                else cls.load.__wrapped__  # type: ignore[attr-defined]
            )

        if hasattr(cls, "save") and not cls.save.__qualname__.startswith("Abstract"):
            cls.save = cls._save_wrapper(  # type: ignore[assignment]
                cls.save
                if not getattr(cls.save, "__savewrapped__", False)
                else cls.save.__wrapped__  # type: ignore[attr-defined]
            )

    def _pretty_repr(self, object_description: dict[str, Any]) -> str:
        str_keys = []
        for arg_name, arg_descr in object_description.items():
            if arg_descr is not None:
                descr = pprint.pformat(
                    arg_descr,
                    sort_dicts=False,
                    compact=True,
                    depth=2,
                    width=sys.maxsize,
                )
                str_keys.append(f"{arg_name}={descr}")