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

Code before:
                raise DatasetError("Saving 'None' to a 'Dataset' is not allowed")

            try:
                self._logger.debug("Saving %s", str(self))
                save_func(self, 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

        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:
        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]
            )

    @abc.abstractmethod
    def load(self) -> _DO:
        """Loads data by delegation to the provided load method.

        Returns:
            Data returned by the provided load method.

        Raises:
            DatasetError: When underlying load method raises error.


Review comment (bug):
This looks like a clever solution, but it's also quite hard to read.. I'm also concerned whether we can be sure that all edge cases are tested. Is there a way this can be rewritten to make it easier to follow (and therefore maintain)? 

Code after:
        cls, save_func: Callable[[Self, _DI], None]
    ) -> Callable[[Self, _DI], None]:
        """Decorate `save_func` with logging and error handling code."""

        @wraps(save_func)
        def save(self: Self, data: _DI) -> None:
            if data is None:
                raise DatasetError("Saving 'None' to a 'Dataset' is not allowed")

            try:
                self._logger.debug("Saving %s", str(self))
                save_func(self, 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

        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]