We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Project templating using TemplatedConfigLoader raises ValidationError in 0.18.0
## Description
When following the guide for [Template configuration](https://kedro.readthedocs.io/en/stable/kedro_project_setup/configuration.html#template-configuration), Kedro 0.18.0 raises ValidationError as `kedro.config.templated_config.TemplatedConfigLoader` is not recognized as a subclass of `kedro.config.config.ConfigLoader`.

## Context
This bug hinders me from using the `TemplatedConfigLoader`, according to the documentation.

## Steps to Reproduce
1. Create new Kedro project
```
kedro new --starter=pandas-iris
cd new-kedro-project
```
2. Create and activate venv. Install requirements.
```
python -m venv my_venv
source my_venv/bin/activate
pip install -r src/requirements.txt
```
3. Open the `settings.py` file.
```
nano src/new_kedro_project/settings.py
```
Uncomment lines 28,29,31,32,33 as suggested in the guide. Expected config:
```
# Class that manages how configuration is loaded.
from kedro.config import TemplatedConfigLoader
CONFIG_LOADER_CLASS = TemplatedConfigLoader
# Keyword arguments to pass to the `CONFIG_LOADER_CLASS` constructor.
CONFIG_LOADER_ARGS = {
    "globals_pattern": "*globals.yml",
}
```
4. Run the default pipeline
```
kedro run
```

## Expected Result
Defeault pipeline should run with global config keys overwritten.

## Actual Result
ValidationError is raised.

```
Traceback (most recent call last):
  File "/usr/local/bin/kedro", line 8, in <module>
    sys.exit(main())
  File "/usr/local/lib/python3.9/site-packages/kedro/framework/cli/cli.py", line 205, in main
    cli_collection = KedroCLI(project_path=Path.cwd())
  File "/usr/local/lib/python3.9/site-packages/kedro/framework/cli/cli.py", line 114, in __init__
    self._metadata = bootstrap_project(project_path)
  File "/usr/local/lib/python3.9/site-packages/kedro/framework/startup.py", line 155, in bootstrap_project
    configure_project(metadata.package_name)
  File "/usr/local/lib/python3.9/site-packages/kedro/framework/project/__init__.py", line 166, in configure_project
    settings.configure(settings_module)
  File "/usr/local/lib/python3.9/site-packages/dynaconf/base.py", line 182, in configure
    self._wrapped = Settings(settings_module=settings_module, **kwargs)
  File "/usr/local/lib/python3.9/site-packages/dynaconf/base.py", line 235, in __init__
    self.validators.validate(
  File "/usr/local/lib/python3.9/site-packages/dynaconf/validator.py", line 417, in validate
    validator.validate(self.settings, only=only, exclude=exclude)
  File "/usr/local/lib/python3.9/site-packages/kedro/framework/project/__init__.py", line 35, in validate
    raise ValidationError(
dynaconf.validator.ValidationError: Invalid value `kedro.config.templated_config.TemplatedConfigLoader` received for setting `CONFIG_LOADER_CLASS`. It must be a subclass of `kedro.config.config.ConfigLoader`.
```

## Your Environment
* Kedro version used (`pip show kedro` or `kedro -V`): `0.18.0`
* Python version used (`python -V`): `3.9.10`
* Operating system and version: `macOS 12.3`


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `kedro/framework/project/__init__.py`
Content:
```
1 """``kedro.framework.project`` module provides utitlity to
2 configure a Kedro project and access its settings."""
3 # pylint: disable=redefined-outer-name,unused-argument,global-statement
4 import importlib
5 import logging.config
6 import operator
7 from collections.abc import MutableMapping
8 from typing import Any, Dict, Optional
9 
10 from dynaconf import LazySettings
11 from dynaconf.validator import ValidationError, Validator
12 
13 from kedro.pipeline import Pipeline
14 
15 
16 def _get_default_class(class_import_path):
17     module, _, class_name = class_import_path.rpartition(".")
18 
19     def validator_func(settings, validators):
20         return getattr(importlib.import_module(module), class_name)
21 
22     return validator_func
23 
24 
25 class _IsSubclassValidator(Validator):
26     """A validator to check if the supplied setting value is a subclass of the default class"""
27 
28     def validate(self, settings, *args, **kwargs):
29         super().validate(settings, *args, **kwargs)
30 
31         default_class = self.default(settings, self)
32         for name in self.names:
33             setting_value = getattr(settings, name)
34             if not issubclass(setting_value, default_class):
35                 raise ValidationError(
36                     f"Invalid value `{setting_value.__module__}.{setting_value.__qualname__}` "
37                     f"received for setting `{name}`. It must be a subclass of "
38                     f"`{default_class.__module__}.{default_class.__qualname__}`."
39                 )
40 
41 
42 class _ProjectSettings(LazySettings):
43     """Define all settings available for users to configure in Kedro,
44     along with their validation rules and default values.
45     Use Dynaconf's LazySettings as base.
46     """
47 
48     _CONF_SOURCE = Validator("CONF_SOURCE", default="conf")
49     _HOOKS = Validator("HOOKS", default=tuple())
50     _CONTEXT_CLASS = _IsSubclassValidator(
51         "CONTEXT_CLASS",
52         default=_get_default_class("kedro.framework.context.KedroContext"),
53     )
54     _SESSION_STORE_CLASS = _IsSubclassValidator(
55         "SESSION_STORE_CLASS",
56         default=_get_default_class("kedro.framework.session.session.BaseSessionStore"),
57     )
58     _SESSION_STORE_ARGS = Validator("SESSION_STORE_ARGS", default={})
59     _DISABLE_HOOKS_FOR_PLUGINS = Validator("DISABLE_HOOKS_FOR_PLUGINS", default=tuple())
60     _CONFIG_LOADER_CLASS = _IsSubclassValidator(
61         "CONFIG_LOADER_CLASS", default=_get_default_class("kedro.config.ConfigLoader")
62     )
63     _CONFIG_LOADER_ARGS = Validator("CONFIG_LOADER_ARGS", default={})
64     _DATA_CATALOG_CLASS = _IsSubclassValidator(
65         "DATA_CATALOG_CLASS", default=_get_default_class("kedro.io.DataCatalog")
66     )
67 
68     def __init__(self, *args, **kwargs):
69 
70         kwargs.update(
71             validators=[
72                 self._CONF_SOURCE,
73                 self._HOOKS,
74                 self._CONTEXT_CLASS,
75                 self._SESSION_STORE_CLASS,
76                 self._SESSION_STORE_ARGS,
77                 self._DISABLE_HOOKS_FOR_PLUGINS,
78                 self._CONFIG_LOADER_CLASS,
79                 self._CONFIG_LOADER_ARGS,
80                 self._DATA_CATALOG_CLASS,
81             ]
82         )
83         super().__init__(*args, **kwargs)
84 
85 
86 def _load_data_wrapper(func):
87     """Wrap a method in _ProjectPipelines so that data is loaded on first access.
88     Taking inspiration from dynaconf.utils.functional.new_method_proxy
89     """
90     # pylint: disable=protected-access
91     def inner(self, *args, **kwargs):
92         self._load_data()
93         return func(self._content, *args, **kwargs)
94 
95     return inner
96 
97 
98 class _ProjectPipelines(MutableMapping):
99     """A read-only lazy dictionary-like object to hold the project pipelines.
100     On configure it will store the pipelines module.
101     On first data access, e.g. through __getitem__, it will load the registered pipelines and merge
102     them with pipelines defined from hooks.
103     """
104 
105     def __init__(self) -> None:
106         self._pipelines_module: Optional[str] = None
107         self._is_data_loaded = False
108         self._content: Dict[str, Pipeline] = {}
109 
110     @staticmethod
111     def _get_pipelines_registry_callable(pipelines_module: str):
112         module_obj = importlib.import_module(pipelines_module)
113         register_pipelines = getattr(module_obj, "register_pipelines")
114         return register_pipelines
115 
116     def _load_data(self):
117         """Lazily read pipelines defined in the pipelines registry module"""
118 
119         # If the pipelines dictionary has not been configured with a pipelines module
120         # or if data has been loaded
121         if self._pipelines_module is None or self._is_data_loaded:
122             return
123 
124         register_pipelines = self._get_pipelines_registry_callable(
125             self._pipelines_module
126         )
127         project_pipelines = register_pipelines()
128 
129         self._content = project_pipelines
130         self._is_data_loaded = True
131 
132     def configure(self, pipelines_module: Optional[str] = None) -> None:
133         """Configure the pipelines_module to load the pipelines dictionary.
134         Reset the data loading state so that after every `configure` call,
135         data are reloaded.
136         """
137         self._pipelines_module = pipelines_module
138         self._is_data_loaded = False
139         self._content = {}
140 
141     # Dict-like interface
142     __getitem__ = _load_data_wrapper(operator.getitem)
143     __setitem__ = _load_data_wrapper(operator.setitem)
144     __delitem__ = _load_data_wrapper(operator.delitem)
145     __iter__ = _load_data_wrapper(iter)
146     __len__ = _load_data_wrapper(len)
147 
148     # Presentation methods
149     __repr__ = _load_data_wrapper(repr)
150     __str__ = _load_data_wrapper(str)
151 
152 
153 PACKAGE_NAME = None
154 LOGGING = None
155 
156 settings = _ProjectSettings()
157 
158 pipelines = _ProjectPipelines()
159 
160 
161 def configure_project(package_name: str):
162     """Configure a Kedro project by populating its settings with values
163     defined in user's settings.py and pipeline_registry.py.
164     """
165     settings_module = f"{package_name}.settings"
166     settings.configure(settings_module)
167 
168     pipelines_module = f"{package_name}.pipeline_registry"
169     pipelines.configure(pipelines_module)
170 
171     # Once the project is successfully configured once, store PACKAGE_NAME as a
172     # global variable to make it easily accessible. This is used by validate_settings()
173     # below, and also by ParallelRunner on Windows, as package_name is required every
174     # time a new subprocess is spawned.
175     global PACKAGE_NAME
176     PACKAGE_NAME = package_name
177 
178 
179 def configure_logging(logging_config: Dict[str, Any]) -> None:
180     """Configure logging to make it available as a global variable."""
181     logging.config.dictConfig(logging_config)
182     global LOGGING
183     LOGGING = logging_config
184 
185 
186 def validate_settings():
187     """Eagerly validate that the settings module is importable. This is desirable to
188     surface any syntax or import errors early. In particular, without eagerly importing
189     the settings module, dynaconf would silence any import error (e.g. missing
190     dependency, missing/mislabelled pipeline), and users would instead get a cryptic
191     error message ``Expected an instance of `ConfigLoader`, got `NoneType` instead``.
192     More info on the dynaconf issue: https://github.com/rochacbruno/dynaconf/issues/460
193     """
194     importlib.import_module(f"{PACKAGE_NAME}.settings")
195
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/kedro/framework/project/__init__.py b/kedro/framework/project/__init__.py
--- a/kedro/framework/project/__init__.py
+++ b/kedro/framework/project/__init__.py
@@ -39,6 +39,35 @@
                 )
 
 
+class _HasSharedParentClassValidator(Validator):
+    """A validator to check that the parent of the default class is an ancestor of
+    the settings value."""
+
+    def validate(self, settings, *args, **kwargs):
+        super().validate(settings, *args, **kwargs)
+
+        default_class = self.default(settings, self)
+        for name in self.names:
+            setting_value = getattr(settings, name)
+            # In the case of ConfigLoader, default_class.mro() will be:
+            # [kedro.config.config.ConfigLoader,
+            # kedro.config.abstract_config.AbstractConfigLoader,
+            # abc.ABC,
+            # object]
+            # We pick out the direct parent and check if it's in any of the ancestors of
+            # the supplied setting_value. This assumes that the direct parent is
+            # the abstract class that must be inherited from.
+            # A more general check just for a shared ancestor would be:
+            # set(default_class.mro()) & set(setting_value.mro()) - {abc.ABC, object}
+            default_class_parent = default_class.mro()[1]
+            if default_class_parent not in setting_value.mro():
+                raise ValidationError(
+                    f"Invalid value `{setting_value.__module__}.{setting_value.__qualname__}` "
+                    f"received for setting `{name}`. It must be a subclass of "
+                    f"`{default_class_parent.__module__}.{default_class_parent.__qualname__}`."
+                )
+
+
 class _ProjectSettings(LazySettings):
     """Define all settings available for users to configure in Kedro,
     along with their validation rules and default values.
@@ -57,7 +86,7 @@
     )
     _SESSION_STORE_ARGS = Validator("SESSION_STORE_ARGS", default={})
     _DISABLE_HOOKS_FOR_PLUGINS = Validator("DISABLE_HOOKS_FOR_PLUGINS", default=tuple())
-    _CONFIG_LOADER_CLASS = _IsSubclassValidator(
+    _CONFIG_LOADER_CLASS = _HasSharedParentClassValidator(
         "CONFIG_LOADER_CLASS", default=_get_default_class("kedro.config.ConfigLoader")
     )
     _CONFIG_LOADER_ARGS = Validator("CONFIG_LOADER_ARGS", default={})

{"golden_diff": "diff --git a/kedro/framework/project/__init__.py b/kedro/framework/project/__init__.py\n--- a/kedro/framework/project/__init__.py\n+++ b/kedro/framework/project/__init__.py\n@@ -39,6 +39,35 @@\n                 )\n \n \n+class _HasSharedParentClassValidator(Validator):\n+    \"\"\"A validator to check that the parent of the default class is an ancestor of\n+    the settings value.\"\"\"\n+\n+    def validate(self, settings, *args, **kwargs):\n+        super().validate(settings, *args, **kwargs)\n+\n+        default_class = self.default(settings, self)\n+        for name in self.names:\n+            setting_value = getattr(settings, name)\n+            # In the case of ConfigLoader, default_class.mro() will be:\n+            # [kedro.config.config.ConfigLoader,\n+            # kedro.config.abstract_config.AbstractConfigLoader,\n+            # abc.ABC,\n+            # object]\n+            # We pick out the direct parent and check if it's in any of the ancestors of\n+            # the supplied setting_value. This assumes that the direct parent is\n+            # the abstract class that must be inherited from.\n+            # A more general check just for a shared ancestor would be:\n+            # set(default_class.mro()) & set(setting_value.mro()) - {abc.ABC, object}\n+            default_class_parent = default_class.mro()[1]\n+            if default_class_parent not in setting_value.mro():\n+                raise ValidationError(\n+                    f\"Invalid value `{setting_value.__module__}.{setting_value.__qualname__}` \"\n+                    f\"received for setting `{name}`. It must be a subclass of \"\n+                    f\"`{default_class_parent.__module__}.{default_class_parent.__qualname__}`.\"\n+                )\n+\n+\n class _ProjectSettings(LazySettings):\n     \"\"\"Define all settings available for users to configure in Kedro,\n     along with their validation rules and default values.\n@@ -57,7 +86,7 @@\n     )\n     _SESSION_STORE_ARGS = Validator(\"SESSION_STORE_ARGS\", default={})\n     _DISABLE_HOOKS_FOR_PLUGINS = Validator(\"DISABLE_HOOKS_FOR_PLUGINS\", default=tuple())\n-    _CONFIG_LOADER_CLASS = _IsSubclassValidator(\n+    _CONFIG_LOADER_CLASS = _HasSharedParentClassValidator(\n         \"CONFIG_LOADER_CLASS\", default=_get_default_class(\"kedro.config.ConfigLoader\")\n     )\n     _CONFIG_LOADER_ARGS = Validator(\"CONFIG_LOADER_ARGS\", default={})\n", "issue": "Project templating using TemplatedConfigLoader raises ValidationError in 0.18.0\n## Description\r\nWhen following the guide for [Template configuration](https://kedro.readthedocs.io/en/stable/kedro_project_setup/configuration.html#template-configuration), Kedro 0.18.0 raises ValidationError as `kedro.config.templated_config.TemplatedConfigLoader` is not recognized as a subclass of `kedro.config.config.ConfigLoader`.\r\n\r\n## Context\r\nThis bug hinders me from using the `TemplatedConfigLoader`, according to the documentation.\r\n\r\n## Steps to Reproduce\r\n1. Create new Kedro project\r\n```\r\nkedro new --starter=pandas-iris\r\ncd new-kedro-project\r\n```\r\n2. Create and activate venv. Install requirements.\r\n```\r\npython -m venv my_venv\r\nsource my_venv/bin/activate\r\npip install -r src/requirements.txt\r\n```\r\n3. Open the `settings.py` file.\r\n```\r\nnano src/new_kedro_project/settings.py\r\n```\r\nUncomment lines 28,29,31,32,33 as suggested in the guide. Expected config:\r\n```\r\n# Class that manages how configuration is loaded.\r\nfrom kedro.config import TemplatedConfigLoader\r\nCONFIG_LOADER_CLASS = TemplatedConfigLoader\r\n# Keyword arguments to pass to the `CONFIG_LOADER_CLASS` constructor.\r\nCONFIG_LOADER_ARGS = {\r\n    \"globals_pattern\": \"*globals.yml\",\r\n}\r\n```\r\n4. Run the default pipeline\r\n```\r\nkedro run\r\n```\r\n\r\n## Expected Result\r\nDefeault pipeline should run with global config keys overwritten.\r\n\r\n## Actual Result\r\nValidationError is raised.\r\n\r\n```\r\nTraceback (most recent call last):\r\n  File \"/usr/local/bin/kedro\", line 8, in <module>\r\n    sys.exit(main())\r\n  File \"/usr/local/lib/python3.9/site-packages/kedro/framework/cli/cli.py\", line 205, in main\r\n    cli_collection = KedroCLI(project_path=Path.cwd())\r\n  File \"/usr/local/lib/python3.9/site-packages/kedro/framework/cli/cli.py\", line 114, in __init__\r\n    self._metadata = bootstrap_project(project_path)\r\n  File \"/usr/local/lib/python3.9/site-packages/kedro/framework/startup.py\", line 155, in bootstrap_project\r\n    configure_project(metadata.package_name)\r\n  File \"/usr/local/lib/python3.9/site-packages/kedro/framework/project/__init__.py\", line 166, in configure_project\r\n    settings.configure(settings_module)\r\n  File \"/usr/local/lib/python3.9/site-packages/dynaconf/base.py\", line 182, in configure\r\n    self._wrapped = Settings(settings_module=settings_module, **kwargs)\r\n  File \"/usr/local/lib/python3.9/site-packages/dynaconf/base.py\", line 235, in __init__\r\n    self.validators.validate(\r\n  File \"/usr/local/lib/python3.9/site-packages/dynaconf/validator.py\", line 417, in validate\r\n    validator.validate(self.settings, only=only, exclude=exclude)\r\n  File \"/usr/local/lib/python3.9/site-packages/kedro/framework/project/__init__.py\", line 35, in validate\r\n    raise ValidationError(\r\ndynaconf.validator.ValidationError: Invalid value `kedro.config.templated_config.TemplatedConfigLoader` received for setting `CONFIG_LOADER_CLASS`. It must be a subclass of `kedro.config.config.ConfigLoader`.\r\n```\r\n\r\n## Your Environment\r\n* Kedro version used (`pip show kedro` or `kedro -V`): `0.18.0`\r\n* Python version used (`python -V`): `3.9.10`\r\n* Operating system and version: `macOS 12.3`\r\n\n", "before_files": [{"content": "\"\"\"``kedro.framework.project`` module provides utitlity to\nconfigure a Kedro project and access its settings.\"\"\"\n# pylint: disable=redefined-outer-name,unused-argument,global-statement\nimport importlib\nimport logging.config\nimport operator\nfrom collections.abc import MutableMapping\nfrom typing import Any, Dict, Optional\n\nfrom dynaconf import LazySettings\nfrom dynaconf.validator import ValidationError, Validator\n\nfrom kedro.pipeline import Pipeline\n\n\ndef _get_default_class(class_import_path):\n    module, _, class_name = class_import_path.rpartition(\".\")\n\n    def validator_func(settings, validators):\n        return getattr(importlib.import_module(module), class_name)\n\n    return validator_func\n\n\nclass _IsSubclassValidator(Validator):\n    \"\"\"A validator to check if the supplied setting value is a subclass of the default class\"\"\"\n\n    def validate(self, settings, *args, **kwargs):\n        super().validate(settings, *args, **kwargs)\n\n        default_class = self.default(settings, self)\n        for name in self.names:\n            setting_value = getattr(settings, name)\n            if not issubclass(setting_value, default_class):\n                raise ValidationError(\n                    f\"Invalid value `{setting_value.__module__}.{setting_value.__qualname__}` \"\n                    f\"received for setting `{name}`. It must be a subclass of \"\n                    f\"`{default_class.__module__}.{default_class.__qualname__}`.\"\n                )\n\n\nclass _ProjectSettings(LazySettings):\n    \"\"\"Define all settings available for users to configure in Kedro,\n    along with their validation rules and default values.\n    Use Dynaconf's LazySettings as base.\n    \"\"\"\n\n    _CONF_SOURCE = Validator(\"CONF_SOURCE\", default=\"conf\")\n    _HOOKS = Validator(\"HOOKS\", default=tuple())\n    _CONTEXT_CLASS = _IsSubclassValidator(\n        \"CONTEXT_CLASS\",\n        default=_get_default_class(\"kedro.framework.context.KedroContext\"),\n    )\n    _SESSION_STORE_CLASS = _IsSubclassValidator(\n        \"SESSION_STORE_CLASS\",\n        default=_get_default_class(\"kedro.framework.session.session.BaseSessionStore\"),\n    )\n    _SESSION_STORE_ARGS = Validator(\"SESSION_STORE_ARGS\", default={})\n    _DISABLE_HOOKS_FOR_PLUGINS = Validator(\"DISABLE_HOOKS_FOR_PLUGINS\", default=tuple())\n    _CONFIG_LOADER_CLASS = _IsSubclassValidator(\n        \"CONFIG_LOADER_CLASS\", default=_get_default_class(\"kedro.config.ConfigLoader\")\n    )\n    _CONFIG_LOADER_ARGS = Validator(\"CONFIG_LOADER_ARGS\", default={})\n    _DATA_CATALOG_CLASS = _IsSubclassValidator(\n        \"DATA_CATALOG_CLASS\", default=_get_default_class(\"kedro.io.DataCatalog\")\n    )\n\n    def __init__(self, *args, **kwargs):\n\n        kwargs.update(\n            validators=[\n                self._CONF_SOURCE,\n                self._HOOKS,\n                self._CONTEXT_CLASS,\n                self._SESSION_STORE_CLASS,\n                self._SESSION_STORE_ARGS,\n                self._DISABLE_HOOKS_FOR_PLUGINS,\n                self._CONFIG_LOADER_CLASS,\n                self._CONFIG_LOADER_ARGS,\n                self._DATA_CATALOG_CLASS,\n            ]\n        )\n        super().__init__(*args, **kwargs)\n\n\ndef _load_data_wrapper(func):\n    \"\"\"Wrap a method in _ProjectPipelines so that data is loaded on first access.\n    Taking inspiration from dynaconf.utils.functional.new_method_proxy\n    \"\"\"\n    # pylint: disable=protected-access\n    def inner(self, *args, **kwargs):\n        self._load_data()\n        return func(self._content, *args, **kwargs)\n\n    return inner\n\n\nclass _ProjectPipelines(MutableMapping):\n    \"\"\"A read-only lazy dictionary-like object to hold the project pipelines.\n    On configure it will store the pipelines module.\n    On first data access, e.g. through __getitem__, it will load the registered pipelines and merge\n    them with pipelines defined from hooks.\n    \"\"\"\n\n    def __init__(self) -> None:\n        self._pipelines_module: Optional[str] = None\n        self._is_data_loaded = False\n        self._content: Dict[str, Pipeline] = {}\n\n    @staticmethod\n    def _get_pipelines_registry_callable(pipelines_module: str):\n        module_obj = importlib.import_module(pipelines_module)\n        register_pipelines = getattr(module_obj, \"register_pipelines\")\n        return register_pipelines\n\n    def _load_data(self):\n        \"\"\"Lazily read pipelines defined in the pipelines registry module\"\"\"\n\n        # If the pipelines dictionary has not been configured with a pipelines module\n        # or if data has been loaded\n        if self._pipelines_module is None or self._is_data_loaded:\n            return\n\n        register_pipelines = self._get_pipelines_registry_callable(\n            self._pipelines_module\n        )\n        project_pipelines = register_pipelines()\n\n        self._content = project_pipelines\n        self._is_data_loaded = True\n\n    def configure(self, pipelines_module: Optional[str] = None) -> None:\n        \"\"\"Configure the pipelines_module to load the pipelines dictionary.\n        Reset the data loading state so that after every `configure` call,\n        data are reloaded.\n        \"\"\"\n        self._pipelines_module = pipelines_module\n        self._is_data_loaded = False\n        self._content = {}\n\n    # Dict-like interface\n    __getitem__ = _load_data_wrapper(operator.getitem)\n    __setitem__ = _load_data_wrapper(operator.setitem)\n    __delitem__ = _load_data_wrapper(operator.delitem)\n    __iter__ = _load_data_wrapper(iter)\n    __len__ = _load_data_wrapper(len)\n\n    # Presentation methods\n    __repr__ = _load_data_wrapper(repr)\n    __str__ = _load_data_wrapper(str)\n\n\nPACKAGE_NAME = None\nLOGGING = None\n\nsettings = _ProjectSettings()\n\npipelines = _ProjectPipelines()\n\n\ndef configure_project(package_name: str):\n    \"\"\"Configure a Kedro project by populating its settings with values\n    defined in user's settings.py and pipeline_registry.py.\n    \"\"\"\n    settings_module = f\"{package_name}.settings\"\n    settings.configure(settings_module)\n\n    pipelines_module = f\"{package_name}.pipeline_registry\"\n    pipelines.configure(pipelines_module)\n\n    # Once the project is successfully configured once, store PACKAGE_NAME as a\n    # global variable to make it easily accessible. This is used by validate_settings()\n    # below, and also by ParallelRunner on Windows, as package_name is required every\n    # time a new subprocess is spawned.\n    global PACKAGE_NAME\n    PACKAGE_NAME = package_name\n\n\ndef configure_logging(logging_config: Dict[str, Any]) -> None:\n    \"\"\"Configure logging to make it available as a global variable.\"\"\"\n    logging.config.dictConfig(logging_config)\n    global LOGGING\n    LOGGING = logging_config\n\n\ndef validate_settings():\n    \"\"\"Eagerly validate that the settings module is importable. This is desirable to\n    surface any syntax or import errors early. In particular, without eagerly importing\n    the settings module, dynaconf would silence any import error (e.g. missing\n    dependency, missing/mislabelled pipeline), and users would instead get a cryptic\n    error message ``Expected an instance of `ConfigLoader`, got `NoneType` instead``.\n    More info on the dynaconf issue: https://github.com/rochacbruno/dynaconf/issues/460\n    \"\"\"\n    importlib.import_module(f\"{PACKAGE_NAME}.settings\")\n", "path": "kedro/framework/project/__init__.py"}], "after_files": [{"content": "\"\"\"``kedro.framework.project`` module provides utitlity to\nconfigure a Kedro project and access its settings.\"\"\"\n# pylint: disable=redefined-outer-name,unused-argument,global-statement\nimport importlib\nimport logging.config\nimport operator\nfrom collections.abc import MutableMapping\nfrom typing import Any, Dict, Optional\n\nfrom dynaconf import LazySettings\nfrom dynaconf.validator import ValidationError, Validator\n\nfrom kedro.pipeline import Pipeline\n\n\ndef _get_default_class(class_import_path):\n    module, _, class_name = class_import_path.rpartition(\".\")\n\n    def validator_func(settings, validators):\n        return getattr(importlib.import_module(module), class_name)\n\n    return validator_func\n\n\nclass _IsSubclassValidator(Validator):\n    \"\"\"A validator to check if the supplied setting value is a subclass of the default class\"\"\"\n\n    def validate(self, settings, *args, **kwargs):\n        super().validate(settings, *args, **kwargs)\n\n        default_class = self.default(settings, self)\n        for name in self.names:\n            setting_value = getattr(settings, name)\n            if not issubclass(setting_value, default_class):\n                raise ValidationError(\n                    f\"Invalid value `{setting_value.__module__}.{setting_value.__qualname__}` \"\n                    f\"received for setting `{name}`. It must be a subclass of \"\n                    f\"`{default_class.__module__}.{default_class.__qualname__}`.\"\n                )\n\n\nclass _HasSharedParentClassValidator(Validator):\n    \"\"\"A validator to check that the parent of the default class is an ancestor of\n    the settings value.\"\"\"\n\n    def validate(self, settings, *args, **kwargs):\n        super().validate(settings, *args, **kwargs)\n\n        default_class = self.default(settings, self)\n        for name in self.names:\n            setting_value = getattr(settings, name)\n            # In the case of ConfigLoader, default_class.mro() will be:\n            # [kedro.config.config.ConfigLoader,\n            # kedro.config.abstract_config.AbstractConfigLoader,\n            # abc.ABC,\n            # object]\n            # We pick out the direct parent and check if it's in any of the ancestors of\n            # the supplied setting_value. This assumes that the direct parent is\n            # the abstract class that must be inherited from.\n            # A more general check just for a shared ancestor would be:\n            # set(default_class.mro()) & set(setting_value.mro()) - {abc.ABC, object}\n            default_class_parent = default_class.mro()[1]\n            if default_class_parent not in setting_value.mro():\n                raise ValidationError(\n                    f\"Invalid value `{setting_value.__module__}.{setting_value.__qualname__}` \"\n                    f\"received for setting `{name}`. It must be a subclass of \"\n                    f\"`{default_class_parent.__module__}.{default_class_parent.__qualname__}`.\"\n                )\n\n\nclass _ProjectSettings(LazySettings):\n    \"\"\"Define all settings available for users to configure in Kedro,\n    along with their validation rules and default values.\n    Use Dynaconf's LazySettings as base.\n    \"\"\"\n\n    _CONF_SOURCE = Validator(\"CONF_SOURCE\", default=\"conf\")\n    _HOOKS = Validator(\"HOOKS\", default=tuple())\n    _CONTEXT_CLASS = _IsSubclassValidator(\n        \"CONTEXT_CLASS\",\n        default=_get_default_class(\"kedro.framework.context.KedroContext\"),\n    )\n    _SESSION_STORE_CLASS = _IsSubclassValidator(\n        \"SESSION_STORE_CLASS\",\n        default=_get_default_class(\"kedro.framework.session.session.BaseSessionStore\"),\n    )\n    _SESSION_STORE_ARGS = Validator(\"SESSION_STORE_ARGS\", default={})\n    _DISABLE_HOOKS_FOR_PLUGINS = Validator(\"DISABLE_HOOKS_FOR_PLUGINS\", default=tuple())\n    _CONFIG_LOADER_CLASS = _HasSharedParentClassValidator(\n        \"CONFIG_LOADER_CLASS\", default=_get_default_class(\"kedro.config.ConfigLoader\")\n    )\n    _CONFIG_LOADER_ARGS = Validator(\"CONFIG_LOADER_ARGS\", default={})\n    _DATA_CATALOG_CLASS = _IsSubclassValidator(\n        \"DATA_CATALOG_CLASS\", default=_get_default_class(\"kedro.io.DataCatalog\")\n    )\n\n    def __init__(self, *args, **kwargs):\n\n        kwargs.update(\n            validators=[\n                self._CONF_SOURCE,\n                self._HOOKS,\n                self._CONTEXT_CLASS,\n                self._SESSION_STORE_CLASS,\n                self._SESSION_STORE_ARGS,\n                self._DISABLE_HOOKS_FOR_PLUGINS,\n                self._CONFIG_LOADER_CLASS,\n                self._CONFIG_LOADER_ARGS,\n                self._DATA_CATALOG_CLASS,\n            ]\n        )\n        super().__init__(*args, **kwargs)\n\n\ndef _load_data_wrapper(func):\n    \"\"\"Wrap a method in _ProjectPipelines so that data is loaded on first access.\n    Taking inspiration from dynaconf.utils.functional.new_method_proxy\n    \"\"\"\n    # pylint: disable=protected-access\n    def inner(self, *args, **kwargs):\n        self._load_data()\n        return func(self._content, *args, **kwargs)\n\n    return inner\n\n\nclass _ProjectPipelines(MutableMapping):\n    \"\"\"A read-only lazy dictionary-like object to hold the project pipelines.\n    On configure it will store the pipelines module.\n    On first data access, e.g. through __getitem__, it will load the registered pipelines and merge\n    them with pipelines defined from hooks.\n    \"\"\"\n\n    def __init__(self) -> None:\n        self._pipelines_module: Optional[str] = None\n        self._is_data_loaded = False\n        self._content: Dict[str, Pipeline] = {}\n\n    @staticmethod\n    def _get_pipelines_registry_callable(pipelines_module: str):\n        module_obj = importlib.import_module(pipelines_module)\n        register_pipelines = getattr(module_obj, \"register_pipelines\")\n        return register_pipelines\n\n    def _load_data(self):\n        \"\"\"Lazily read pipelines defined in the pipelines registry module\"\"\"\n\n        # If the pipelines dictionary has not been configured with a pipelines module\n        # or if data has been loaded\n        if self._pipelines_module is None or self._is_data_loaded:\n            return\n\n        register_pipelines = self._get_pipelines_registry_callable(\n            self._pipelines_module\n        )\n        project_pipelines = register_pipelines()\n\n        self._content = project_pipelines\n        self._is_data_loaded = True\n\n    def configure(self, pipelines_module: Optional[str] = None) -> None:\n        \"\"\"Configure the pipelines_module to load the pipelines dictionary.\n        Reset the data loading state so that after every `configure` call,\n        data are reloaded.\n        \"\"\"\n        self._pipelines_module = pipelines_module\n        self._is_data_loaded = False\n        self._content = {}\n\n    # Dict-like interface\n    __getitem__ = _load_data_wrapper(operator.getitem)\n    __setitem__ = _load_data_wrapper(operator.setitem)\n    __delitem__ = _load_data_wrapper(operator.delitem)\n    __iter__ = _load_data_wrapper(iter)\n    __len__ = _load_data_wrapper(len)\n\n    # Presentation methods\n    __repr__ = _load_data_wrapper(repr)\n    __str__ = _load_data_wrapper(str)\n\n\nPACKAGE_NAME = None\nLOGGING = None\n\nsettings = _ProjectSettings()\n\npipelines = _ProjectPipelines()\n\n\ndef configure_project(package_name: str):\n    \"\"\"Configure a Kedro project by populating its settings with values\n    defined in user's settings.py and pipeline_registry.py.\n    \"\"\"\n    settings_module = f\"{package_name}.settings\"\n    settings.configure(settings_module)\n\n    pipelines_module = f\"{package_name}.pipeline_registry\"\n    pipelines.configure(pipelines_module)\n\n    # Once the project is successfully configured once, store PACKAGE_NAME as a\n    # global variable to make it easily accessible. This is used by validate_settings()\n    # below, and also by ParallelRunner on Windows, as package_name is required every\n    # time a new subprocess is spawned.\n    global PACKAGE_NAME\n    PACKAGE_NAME = package_name\n\n\ndef configure_logging(logging_config: Dict[str, Any]) -> None:\n    \"\"\"Configure logging to make it available as a global variable.\"\"\"\n    logging.config.dictConfig(logging_config)\n    global LOGGING\n    LOGGING = logging_config\n\n\ndef validate_settings():\n    \"\"\"Eagerly validate that the settings module is importable. This is desirable to\n    surface any syntax or import errors early. In particular, without eagerly importing\n    the settings module, dynaconf would silence any import error (e.g. missing\n    dependency, missing/mislabelled pipeline), and users would instead get a cryptic\n    error message ``Expected an instance of `ConfigLoader`, got `NoneType` instead``.\n    More info on the dynaconf issue: https://github.com/rochacbruno/dynaconf/issues/460\n    \"\"\"\n    importlib.import_module(f\"{PACKAGE_NAME}.settings\")\n", "path": "kedro/framework/project/__init__.py"}]}