mirror of
https://github.com/OpenHands/OpenHands.git
synced 2025-12-25 21:36:52 +08:00
Co-authored-by: openhands <openhands@all-hands.dev> Co-authored-by: sp.wack <83104063+amanape@users.noreply.github.com> Co-authored-by: Engel Nyst <enyst@users.noreply.github.com>
79 lines
2.7 KiB
Python
79 lines
2.7 KiB
Python
import importlib
|
|
from functools import lru_cache
|
|
from typing import TypeVar
|
|
|
|
T = TypeVar('T')
|
|
|
|
|
|
def import_from(qual_name: str):
|
|
"""Import a value from its fully qualified name.
|
|
|
|
This function is a utility to dynamically import any Python value (class,
|
|
function, variable) from its fully qualified name. For example,
|
|
'openhands.server.user_auth.UserAuth' would import the UserAuth class from the
|
|
openhands.server.user_auth module.
|
|
|
|
Args:
|
|
qual_name: A fully qualified name in the format 'module.submodule.name'
|
|
e.g. 'openhands.server.user_auth.UserAuth'
|
|
|
|
Returns:
|
|
The imported value (class, function, or variable)
|
|
|
|
Example:
|
|
>>> UserAuth = import_from('openhands.server.user_auth.UserAuth')
|
|
>>> auth = UserAuth()
|
|
"""
|
|
parts = qual_name.split('.')
|
|
module_name = '.'.join(parts[:-1])
|
|
module = importlib.import_module(module_name)
|
|
result = getattr(module, parts[-1])
|
|
return result
|
|
|
|
|
|
@lru_cache()
|
|
def _get_impl(cls: type[T], impl_name: str | None) -> type[T]:
|
|
if impl_name is None:
|
|
return cls
|
|
impl_class = import_from(impl_name)
|
|
assert cls == impl_class or issubclass(impl_class, cls)
|
|
return impl_class
|
|
|
|
|
|
def get_impl(cls: type[T], impl_name: str | None) -> type[T]:
|
|
"""Import and validate a named implementation of a base class.
|
|
|
|
This function is an extensibility mechanism in OpenHands that allows runtime
|
|
substitution of implementations. It enables applications to customize behavior by
|
|
providing their own implementations of OpenHands base classes.
|
|
|
|
The function ensures type safety by validating that the imported class is either
|
|
the same as or a subclass of the specified base class.
|
|
|
|
Args:
|
|
cls: The base class that defines the interface
|
|
impl_name: Fully qualified name of the implementation class, or None to use
|
|
the base class
|
|
e.g. 'openhands.server.conversation_service.'
|
|
'StandaloneConversationService'
|
|
|
|
Returns:
|
|
The implementation class, which is guaranteed to be a subclass of cls
|
|
|
|
Example:
|
|
>>> # Get default implementation
|
|
>>> ConversationService = get_impl(ConversationService, None)
|
|
>>> # Get custom implementation
|
|
>>> CustomService = get_impl(
|
|
... ConversationService, 'myapp.CustomConversationService'
|
|
... )
|
|
|
|
Common Use Cases:
|
|
- Server components (ConversationService, UserAuth, etc.)
|
|
- Storage implementations (ConversationStore, SettingsStore, etc.)
|
|
- Service integrations (GitHub, GitLab, Bitbucket services)
|
|
|
|
The implementation is cached to avoid repeated imports of the same class.
|
|
"""
|
|
return _get_impl(cls, impl_name) # type: ignore
|