Repository: kedro-org/kedro

Issue:
OmegaConfigLoader's `__repr__` is not implemented correctly, and it does not behave similar to a `UserDict`
## Description
<!-- Short description of the problem here. -->
Currently, `base_env` and `default_run_env` is not included in the `__repr__`.

When it is printed, it shows something like this

> In [11]: c
> Out[11]: OmegaConfigLoader(conf_source=/Users/Nok_Lam_Chan/dev/kedro-inspect/demo-project/conf, env=None, config_patterns={'catalog': ['catalog*', 'catalog*/**', '**/catalog*'], 'parameters': ['parameters*', 'parameters*/**', '**/parameters*'], 'credentials': ['credentials*', 'credentials*/**', '**/credentials*'], 'globals': ['globals.yml']})
> 

## Context
<!-- How has this bug affected you? What were you trying to accomplish? -->
Even it inherits from `UserDict`, but the dictionary interface seems broken. For example:
```
for key in config_loader.keys():
  print(key)
```
will print nothing even though `config_loader["parameters"]` exist. For the context, I was trying to build a plugin that iterate the config loader and "compile" the configuration.

I need to use a workaround looks like this:
```python
keys = config_loader.config_patterns.keys()
for key in keys:
   config = config_loader[key] 
   ...
```

 In addition, if `__repr__` is removed, the config_loader will be printed as if it is a "dictionary". Right now it always print the `__repr__` regardless of the `keys`, `values`, `items` or `print` method.

Cc @merelcht 



Discussion:

Patch:
diff --git a/RELEASE.md b/RELEASE.md
index cc8b9032c9..f3eeec104d 100644
--- a/RELEASE.md
+++ b/RELEASE.md
@@ -11,6 +11,8 @@
 * Made [kedro-telemetry](https://github.com/kedro-org/kedro-plugins/tree/main/kedro-telemetry) a core dependency.
 * Implemented dataset pretty printing.
 * Implemented `DataCatalog` pretty printing.
+* Fixed a bug when `OmegaConfigLoader` is printed, there are few missing arguments.
+* Fixed a bug when where iterating `OmegaConfigLoader`'s `keys` return empty dictionary.
 
 ## Breaking changes to the API
 
diff --git a/kedro/config/omegaconf_config.py b/kedro/config/omegaconf_config.py
index 0afc43cfa4..a74c0a1351 100644
--- a/kedro/config/omegaconf_config.py
+++ b/kedro/config/omegaconf_config.py
@@ -7,6 +7,7 @@
 import logging
 import mimetypes
 import typing
+from collections.abc import KeysView
 from pathlib import Path
 from typing import Any, Callable, Iterable
 
@@ -124,6 +125,7 @@ def __init__(  # noqa: PLR0913
         # Deactivate oc.env built-in resolver for OmegaConf
         OmegaConf.clear_resolver("oc.env")
         # Register user provided custom resolvers
+        self._custom_resolvers = custom_resolvers
         if custom_resolvers:
             self._register_new_resolvers(custom_resolvers)
         # Register globals resolver
@@ -255,9 +257,17 @@ def __getitem__(self, key: str) -> dict[str, Any]:  # noqa: PLR0912
     def __repr__(self) -> str:  # pragma: no cover
         return (
             f"OmegaConfigLoader(conf_source={self.conf_source}, env={self.env}, "
-            f"config_patterns={self.config_patterns})"
+            f"runtime_params={self.runtime_params}, "
+            f"config_patterns={self.config_patterns}, "
+            f"base_env={self.base_env}), "
+            f"default_run_env={self.default_run_env}), "
+            f"custom_resolvers={self._custom_resolvers}), "
+            f"merge_strategy={self.merge_strategy})"
         )
 
+    def keys(self) -> KeysView:
+        return KeysView(self.config_patterns)
+
     @typing.no_type_check
     def load_and_merge_dir_config(  # noqa: PLR0913
         self,


Test patch:
diff --git a/tests/config/test_omegaconf_config.py b/tests/config/test_omegaconf_config.py
index 676963ee18..cf64c4c7c7 100644
--- a/tests/config/test_omegaconf_config.py
+++ b/tests/config/test_omegaconf_config.py
@@ -1482,3 +1482,7 @@ def test_runtime_params_default_global(self, tmp_path):
         conf = OmegaConfigLoader(tmp_path, runtime_params=runtime_params)
         # runtime params are resolved correctly in catalog using global default
         assert conf["catalog"]["companies"]["type"] == globals_config["dataset"]["type"]
+
+    def test_keys_exist(self):
+        conf = OmegaConfigLoader(conf_source="")
+        assert list(conf.keys()) == ["catalog", "parameters", "credentials", "globals"]