diff --git a/openhands/integrations/azure_devops/azure_devops_service.py b/openhands/integrations/azure_devops/azure_devops_service.py index 8d719cbb54..e93bd650c9 100644 --- a/openhands/integrations/azure_devops/azure_devops_service.py +++ b/openhands/integrations/azure_devops/azure_devops_service.py @@ -28,7 +28,7 @@ from openhands.integrations.service_types import ( from openhands.utils.import_utils import get_impl -class AzureDevOpsServiceImpl( +class AzureDevOpsService( AzureDevOpsResolverMixin, AzureDevOpsReposMixin, AzureDevOpsBranchesMixin, @@ -242,8 +242,34 @@ class AzureDevOpsServiceImpl( # Dynamic class loading to support custom implementations (e.g., SaaS) azure_devops_service_cls = os.environ.get( 'OPENHANDS_AZURE_DEVOPS_SERVICE_CLS', - 'openhands.integrations.azure_devops.azure_devops_service.AzureDevOpsServiceImpl', -) -AzureDevOpsServiceImpl = get_impl( # type: ignore[misc] - AzureDevOpsServiceImpl, azure_devops_service_cls + 'openhands.integrations.azure_devops.azure_devops_service.AzureDevOpsService', ) + +# Lazy loading to avoid circular imports +_azure_devops_service_impl = None + + +def get_azure_devops_service_impl(): + """Get the Azure DevOps service implementation with lazy loading.""" + global _azure_devops_service_impl + if _azure_devops_service_impl is None: + _azure_devops_service_impl = get_impl( # type: ignore[misc] + AzureDevOpsService, azure_devops_service_cls + ) + return _azure_devops_service_impl + + +# For backward compatibility, provide the implementation as a property +class _AzureDevOpsServiceImplProxy: + """Proxy class to provide lazy loading for AzureDevOpsServiceImpl.""" + + def __getattr__(self, name): + impl = get_azure_devops_service_impl() + return getattr(impl, name) + + def __call__(self, *args, **kwargs): + impl = get_azure_devops_service_impl() + return impl(*args, **kwargs) + + +AzureDevOpsServiceImpl: type[AzureDevOpsService] = _AzureDevOpsServiceImplProxy() # type: ignore[assignment] diff --git a/openhands/integrations/bitbucket/bitbucket_service.py b/openhands/integrations/bitbucket/bitbucket_service.py index da9de96873..8d7eb48e81 100644 --- a/openhands/integrations/bitbucket/bitbucket_service.py +++ b/openhands/integrations/bitbucket/bitbucket_service.py @@ -64,4 +64,30 @@ bitbucket_service_cls = os.environ.get( 'OPENHANDS_BITBUCKET_SERVICE_CLS', 'openhands.integrations.bitbucket.bitbucket_service.BitBucketService', ) -BitBucketServiceImpl = get_impl(BitBucketService, bitbucket_service_cls) + +# Lazy loading to avoid circular imports +_bitbucket_service_impl = None + + +def get_bitbucket_service_impl(): + """Get the BitBucket service implementation with lazy loading.""" + global _bitbucket_service_impl + if _bitbucket_service_impl is None: + _bitbucket_service_impl = get_impl(BitBucketService, bitbucket_service_cls) + return _bitbucket_service_impl + + +# For backward compatibility, provide the implementation as a property +class _BitBucketServiceImplProxy: + """Proxy class to provide lazy loading for BitBucketServiceImpl.""" + + def __getattr__(self, name): + impl = get_bitbucket_service_impl() + return getattr(impl, name) + + def __call__(self, *args, **kwargs): + impl = get_bitbucket_service_impl() + return impl(*args, **kwargs) + + +BitBucketServiceImpl: type[BitBucketService] = _BitBucketServiceImplProxy() # type: ignore[assignment] diff --git a/openhands/integrations/github/github_service.py b/openhands/integrations/github/github_service.py index 4d0eb6080f..c56940a0af 100644 --- a/openhands/integrations/github/github_service.py +++ b/openhands/integrations/github/github_service.py @@ -75,4 +75,30 @@ github_service_cls = os.environ.get( 'OPENHANDS_GITHUB_SERVICE_CLS', 'openhands.integrations.github.github_service.GitHubService', ) -GithubServiceImpl = get_impl(GitHubService, github_service_cls) + +# Lazy loading to avoid circular imports +_github_service_impl = None + + +def get_github_service_impl(): + """Get the GitHub service implementation with lazy loading.""" + global _github_service_impl + if _github_service_impl is None: + _github_service_impl = get_impl(GitHubService, github_service_cls) + return _github_service_impl + + +# For backward compatibility, provide the implementation as a property +class _GitHubServiceImplProxy: + """Proxy class to provide lazy loading for GithubServiceImpl.""" + + def __getattr__(self, name): + impl = get_github_service_impl() + return getattr(impl, name) + + def __call__(self, *args, **kwargs): + impl = get_github_service_impl() + return impl(*args, **kwargs) + + +GithubServiceImpl: type[GitHubService] = _GitHubServiceImplProxy() # type: ignore[assignment] diff --git a/openhands/integrations/gitlab/gitlab_service.py b/openhands/integrations/gitlab/gitlab_service.py index 7c672b7f19..31f0d7929d 100644 --- a/openhands/integrations/gitlab/gitlab_service.py +++ b/openhands/integrations/gitlab/gitlab_service.py @@ -79,4 +79,30 @@ gitlab_service_cls = os.environ.get( 'OPENHANDS_GITLAB_SERVICE_CLS', 'openhands.integrations.gitlab.gitlab_service.GitLabService', ) -GitLabServiceImpl = get_impl(GitLabService, gitlab_service_cls) + +# Lazy loading to avoid circular imports +_gitlab_service_impl = None + + +def get_gitlab_service_impl(): + """Get the GitLab service implementation with lazy loading.""" + global _gitlab_service_impl + if _gitlab_service_impl is None: + _gitlab_service_impl = get_impl(GitLabService, gitlab_service_cls) + return _gitlab_service_impl + + +# For backward compatibility, provide the implementation as a property +class _GitLabServiceImplProxy: + """Proxy class to provide lazy loading for GitLabServiceImpl.""" + + def __getattr__(self, name): + impl = get_gitlab_service_impl() + return getattr(impl, name) + + def __call__(self, *args, **kwargs): + impl = get_gitlab_service_impl() + return impl(*args, **kwargs) + + +GitLabServiceImpl: type[GitLabService] = _GitLabServiceImplProxy() # type: ignore[assignment]