Repository: OpenAssetIO/OpenAssetIO (language: python)

Issue:
Hybrid Plugin System
## What

Add a plugin system that combines multiple plugin systemss and dispatches based on advertised capability, or priority order if multiple factories advertise a capability.

## ACs

- Uses a shared identifier to locate the conceptual same manager across each plugin system.
- Make sure this is generic so it composes the output of N plugin systems.
- Uses `hasCapability` to route.
- Picks the first if present in both.

## Implementation notes

- Ideally have a internally `RoutingManagerInterface(vector<ManagerInterfacePtr> interfaces)` as this allows eg: Cpp, GPRC Python, in-process Python.




Discussion / hints:
https://lucascheller.github.io/VFX-UsdAssetResolver/resolvers/production.html
https://forum.aousd.org/t/batching-ar2-queries/818/2?u=foundrytom

Fix patch:
diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md
index 7b79951ed..f1b77b5d4 100644
--- a/RELEASE_NOTES.md
+++ b/RELEASE_NOTES.md
@@ -10,6 +10,12 @@ v1.0.0-beta.x.x
   version is now Python 3.9.
   [#1365](https://github.com/OpenAssetIO/OpenAssetIO/pull/1365)
 
+- Updated the API contract to no longer require that managers throw an
+  exception when an unrecognized setting is given during initialization.
+  The `openassetio.test.manager` API Compliance test suite no longer
+  asserts that this is the case.
+  [#1202](https://github.com/OpenAssetIO/OpenAssetIO/issues/1202)
+
 ### New Features
 
 - Added SimpleCppManager - a minimal C++ manager and plugin example


Test patch:
diff --git a/src/openassetio-python/package/openassetio/test/manager/apiComplianceSuite.py b/src/openassetio-python/package/openassetio/test/manager/apiComplianceSuite.py
index 966f66afe..b02b15a11 100644
--- a/src/openassetio-python/package/openassetio/test/manager/apiComplianceSuite.py
+++ b/src/openassetio-python/package/openassetio/test/manager/apiComplianceSuite.py
@@ -143,27 +143,6 @@ def test_when_settings_are_empty_then_all_settings_unchanged(self):
 
         self.assertEqual(self._manager.settings(), expected)
 
-    def test_when_settings_have_invalid_keys_then_raises_KeyError(self):
-        invalid_settings = self.requireFixture(
-            "some_settings_with_new_values_and_invalid_keys", skipTestIfMissing=True
-        )
-
-        with self.assertRaises(KeyError):
-            self._manager.initialize(invalid_settings)
-
-    def test_when_settings_have_invalid_keys_then_all_settings_unchanged(self):
-        expected = self._manager.settings()
-        invalid_settings = self.requireFixture(
-            "some_settings_with_new_values_and_invalid_keys", skipTestIfMissing=True
-        )
-
-        try:
-            self._manager.initialize(invalid_settings)
-        except Exception:  # pylint: disable=broad-except
-            pass
-
-        self.assertEqual(self._manager.settings(), expected)
-
     def test_when_settings_have_all_keys_then_all_settings_updated(self):
         updated = self.requireFixture("some_settings_with_all_keys", skipTestIfMissing=True)