From c034cc5dfb0229a788b3197ff27ac66e705d6d34 Mon Sep 17 00:00:00 2001 From: Rohit Malhotra Date: Fri, 10 Oct 2025 12:40:03 -0400 Subject: [PATCH] Refactor: move helper function to avoid circular imports (#11310) Co-authored-by: openhands --- enterprise/integrations/github/github_solvability.py | 2 +- enterprise/integrations/github/github_view.py | 3 ++- enterprise/integrations/gitlab/gitlab_view.py | 3 ++- enterprise/server/auth/saas_user_auth.py | 3 ++- enterprise/server/auth/token_manager.py | 12 +----------- enterprise/server/config.py | 11 +++++++++++ enterprise/tests/unit/test_offline_token_store.py | 2 +- enterprise/tests/unit/test_token_manager_extended.py | 2 +- 8 files changed, 21 insertions(+), 17 deletions(-) diff --git a/enterprise/integrations/github/github_solvability.py b/enterprise/integrations/github/github_solvability.py index 0ab7b80b94..cdc6af05ec 100644 --- a/enterprise/integrations/github/github_solvability.py +++ b/enterprise/integrations/github/github_solvability.py @@ -13,7 +13,7 @@ from integrations.solvability.models.report import SolvabilityReport from integrations.solvability.models.summary import SolvabilitySummary from integrations.utils import ENABLE_SOLVABILITY_ANALYSIS from pydantic import ValidationError -from server.auth.token_manager import get_config +from server.config import get_config from storage.database import session_maker from storage.saas_settings_store import SaasSettingsStore diff --git a/enterprise/integrations/github/github_view.py b/enterprise/integrations/github/github_view.py index 69124cc09b..208ad12365 100644 --- a/enterprise/integrations/github/github_view.py +++ b/enterprise/integrations/github/github_view.py @@ -19,7 +19,8 @@ from integrations.utils import ( from jinja2 import Environment from pydantic.dataclasses import dataclass from server.auth.constants import GITHUB_APP_CLIENT_ID, GITHUB_APP_PRIVATE_KEY -from server.auth.token_manager import TokenManager, get_config +from server.auth.token_manager import TokenManager +from server.config import get_config from storage.database import session_maker from storage.proactive_conversation_store import ProactiveConversationStore from storage.saas_secrets_store import SaasSecretsStore diff --git a/enterprise/integrations/gitlab/gitlab_view.py b/enterprise/integrations/gitlab/gitlab_view.py index 9dd34b2821..29d4f18850 100644 --- a/enterprise/integrations/gitlab/gitlab_view.py +++ b/enterprise/integrations/gitlab/gitlab_view.py @@ -4,7 +4,8 @@ from integrations.models import Message from integrations.types import ResolverViewInterface, UserData from integrations.utils import HOST, get_oh_labels, has_exact_mention from jinja2 import Environment -from server.auth.token_manager import TokenManager, get_config +from server.auth.token_manager import TokenManager +from server.config import get_config from storage.database import session_maker from storage.saas_secrets_store import SaasSecretsStore diff --git a/enterprise/server/auth/saas_user_auth.py b/enterprise/server/auth/saas_user_auth.py index 185fece4cd..4b908767f6 100644 --- a/enterprise/server/auth/saas_user_auth.py +++ b/enterprise/server/auth/saas_user_auth.py @@ -13,7 +13,8 @@ from server.auth.auth_error import ( ExpiredError, NoCredentialsError, ) -from server.auth.token_manager import TokenManager, get_config +from server.auth.token_manager import TokenManager +from server.config import get_config from server.logger import logger from server.rate_limit import RateLimiter, create_redis_rate_limiter from storage.api_key_store import ApiKeyStore diff --git a/enterprise/server/auth/token_manager.py b/enterprise/server/auth/token_manager.py index 8189375c79..7033dab1d8 100644 --- a/enterprise/server/auth/token_manager.py +++ b/enterprise/server/auth/token_manager.py @@ -26,6 +26,7 @@ from server.auth.constants import ( KEYCLOAK_SERVER_URL_EXT, ) from server.auth.keycloak_manager import get_keycloak_admin, get_keycloak_openid +from server.config import get_config from server.logger import logger from sqlalchemy import String as SQLString from sqlalchemy import type_coerce @@ -35,19 +36,8 @@ from storage.github_app_installation import GithubAppInstallation from storage.offline_token_store import OfflineTokenStore from tenacity import RetryCallState, retry, retry_if_exception_type, stop_after_attempt -from openhands.core.config import load_openhands_config from openhands.integrations.service_types import ProviderType -# Create a function to get config to avoid circular imports -_config = None - - -def get_config(): - global _config - if _config is None: - _config = load_openhands_config() - return _config - def _before_sleep_callback(retry_state: RetryCallState) -> None: logger.info(f'Retry attempt {retry_state.attempt_number} for Keycloak operation') diff --git a/enterprise/server/config.py b/enterprise/server/config.py index d88182d06f..b978aee268 100644 --- a/enterprise/server/config.py +++ b/enterprise/server/config.py @@ -19,10 +19,21 @@ from server.auth.constants import ( GITLAB_APP_CLIENT_ID, ) +from openhands.core.config.utils import load_openhands_config from openhands.integrations.service_types import ProviderType from openhands.server.config.server_config import ServerConfig from openhands.server.types import AppMode +# Create a function to get config to avoid circular imports +_config = None + + +def get_config(): + global _config + if _config is None: + _config = load_openhands_config() + return _config + def sign_token(payload: dict[str, object], jwt_secret: str, algorithm='HS256') -> str: """Signs a JWT token.""" diff --git a/enterprise/tests/unit/test_offline_token_store.py b/enterprise/tests/unit/test_offline_token_store.py index 22f2c17bb2..b3830ff814 100644 --- a/enterprise/tests/unit/test_offline_token_store.py +++ b/enterprise/tests/unit/test_offline_token_store.py @@ -20,7 +20,7 @@ def token_store(session_maker, mock_config): @pytest.fixture def token_manager(): - with patch('server.auth.token_manager.get_config') as mock_get_config: + with patch('server.config.get_config') as mock_get_config: mock_config = mock_get_config.return_value mock_config.jwt_secret.get_secret_value.return_value = 'test_secret' return TokenManager(external=False) diff --git a/enterprise/tests/unit/test_token_manager_extended.py b/enterprise/tests/unit/test_token_manager_extended.py index 1cce2faada..744f208b02 100644 --- a/enterprise/tests/unit/test_token_manager_extended.py +++ b/enterprise/tests/unit/test_token_manager_extended.py @@ -8,7 +8,7 @@ from openhands.integrations.service_types import ProviderType @pytest.fixture def token_manager(): - with patch('server.auth.token_manager.get_config') as mock_get_config: + with patch('server.config.get_config') as mock_get_config: mock_config = mock_get_config.return_value mock_config.jwt_secret.get_secret_value.return_value = 'test_secret' return TokenManager(external=False)