src/dubbo/extension/extension_loader.py (31 lines of code) (raw):
#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import importlib
from typing import Any
from dubbo.classes import SingletonBase
from dubbo.extension import registries as registries_module
class ExtensionError(Exception):
"""
Extension error.
"""
def __init__(self, message: str):
"""
Initialize the extension error.
:param message: The error message.
:type message: str
"""
super().__init__(message)
class ExtensionLoader(SingletonBase):
"""
Singleton class for loading extension implementations.
"""
def __init__(self):
"""
Initialize the extension loader.
Load all the registries from the registries module.
"""
if not hasattr(self, "_initialized"): # Ensure __init__ runs only once
self._registries = {}
for name in registries_module.registries:
registry = getattr(registries_module, name)
self._registries[registry.interface] = registry.impls
self._initialized = True
def get_extension(self, interface: Any, impl_name: str) -> Any:
"""
Get the extension implementation for the interface.
:param interface: Interface class.
:type interface: Any
:param impl_name: Implementation name.
:type impl_name: str
:return: Extension implementation class.
:rtype: Any
:raises ExtensionError: If the interface or implementation is not found.
"""
# Get the registry for the interface
impls = self._registries.get(interface)
if not impls:
raise ExtensionError(f"Interface '{interface.__name__}' is not supported.")
# Get the full name of the implementation
full_name = impls.get(impl_name)
if not full_name:
raise ExtensionError(f"Implementation '{impl_name}' for interface '{interface.__name__}' is not exist.")
try:
# Split the full name into module and class
module_name, class_name = full_name.rsplit(".", 1)
# Load the module and get the class
module = importlib.import_module(module_name)
subclass = getattr(module, class_name)
# Return the subclass
return subclass
except Exception as e:
raise ExtensionError(
f"Failed to load extension '{impl_name}' for interface '{interface.__name__}'. \nDetail: {e}"
)