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

Code before:
            other.config_resolver.list_patterns(),
        )

    def keys(self, regex_search: str | None = None) -> List[str]:  # noqa: UP006
        return self._filter_keys(regex_search)

    def values(self, regex_search: str | None = None) -> List[AbstractDataset]:  # noqa: UP006
        return [self._datasets[key] for key in self._filter_keys(regex_search)]

    def items(
        self, regex_search: str | None = None
    ) -> List[tuple[str, AbstractDataset]]:  # noqa: UP006
        return [(key, self._datasets[key]) for key in self._filter_keys(regex_search)]

    def __iter__(self) -> str:
        yield from self._datasets.keys()

    def __getitem__(self, ds_name: str) -> AbstractDataset | None:
        return self.get_dataset(ds_name)

    def __setitem__(self, key: str, value: Any) -> None:
        if key in self._datasets:
            self._logger.warning("Replacing dataset '%s'", key)
        if isinstance(value, AbstractDataset):
            self._datasets[key] = value
        else:
            self._datasets[key] = MemoryDataset(data=value)  # type: ignore[abstract]

    def __len__(self) -> int:
        return len(self.keys())

    def get(
        self, key: str, default: AbstractDataset | None = None
    ) -> AbstractDataset | None:
        """Get a dataset by name from an internal collection of datasets."""
        if key not in self._datasets:
            ds_config = self._config_resolver.resolve_pattern(key)
            if ds_config:
                self._add_from_config(key, ds_config)

        dataset = self._datasets.get(key, None)

        return dataset or default

    def _ipython_key_completions_(self) -> list[str]:
        return list(self._datasets.keys())

    @property
    def _logger(self) -> logging.Logger:
        return logging.getLogger(__name__)


Review comment (suggestion):
I really (really) think we should have at least logger.info() here to explain this behaviour. I expect silent error due to people assigning a malformed dataset manually which end up assigned as a MemoryDataset, opening a room for a lot of headache.  

Code after:
            other.config_resolver.list_patterns(),
        )

    def keys(self) -> List[str]:  # noqa: UP006
        return list(self.__iter__())

    def values(self) -> List[AbstractDataset]:  # noqa: UP006
        return [self._datasets[key] for key in self]

    def items(self) -> List[tuple[str, AbstractDataset]]:  # noqa: UP006
        return [(key, self._datasets[key]) for key in self]

    def __iter__(self) -> Iterator[str]:
        yield from self._datasets.keys()

    def __getitem__(self, ds_name: str) -> AbstractDataset:
        return self.get_dataset(ds_name)

    def __setitem__(self, key: str, value: Any) -> None:
        if key in self._datasets:
            self._logger.warning("Replacing dataset '%s'", key)
        if isinstance(value, AbstractDataset):
            self._datasets[key] = value
        else:
            self._logger.info(f"Adding input data as a MemoryDataset - {key}")
            self._datasets[key] = MemoryDataset(data=value)  # type: ignore[abstract]

    def __len__(self) -> int:
        return len(self.keys())

    def get(
        self, key: str, default: AbstractDataset | None = None
    ) -> AbstractDataset | None:
        """Get a dataset by name from an internal collection of datasets."""
        if key not in self._datasets:
            ds_config = self._config_resolver.resolve_pattern(key)
            if ds_config:
                self._add_from_config(key, ds_config)

        dataset = self._datasets.get(key, None)

        return dataset or default

    def _ipython_key_completions_(self) -> list[str]:
        return list(self._datasets.keys())

    @property
    def _logger(self) -> logging.Logger:
        return logging.getLogger(__name__)

    @classmethod