fix: remove frozen=True from Field() to fix Pydantic warning (#12518)

Co-authored-by: openhands <openhands@all-hands.dev>
This commit is contained in:
Graham Neubig
2026-01-21 08:50:49 -05:00
committed by GitHub
parent 0d740925c5
commit b3137e7ae8
3 changed files with 61 additions and 2 deletions

View File

@@ -19,8 +19,8 @@ from openhands.storage.data_models.settings import Settings
class ConversationInitData(Settings):
"""Session initialization data for the web environment - a deep copy of the global config is made and then overridden with this data."""
git_provider_tokens: PROVIDER_TOKEN_TYPE | None = Field(default=None, frozen=True)
custom_secrets: CUSTOM_SECRETS_TYPE | None = Field(default=None, frozen=True)
git_provider_tokens: PROVIDER_TOKEN_TYPE | None = Field(default=None)
custom_secrets: CUSTOM_SECRETS_TYPE | None = Field(default=None)
selected_repository: str | None = Field(default=None)
replay_json: str | None = Field(default=None)
selected_branch: str | None = Field(default=None)
@@ -29,6 +29,7 @@ class ConversationInitData(Settings):
model_config = ConfigDict(
arbitrary_types_allowed=True,
frozen=True,
)
@field_validator('git_provider_tokens', 'custom_secrets')

View File

@@ -4,6 +4,7 @@ These tests verify that the immutable_validator correctly converts dict to Mappi
for git_provider_tokens and custom_secrets fields, ensuring type safety.
"""
import warnings
from types import MappingProxyType
import pytest
@@ -270,3 +271,31 @@ class TestConversationInitDataValidator:
init_data.custom_secrets['SECRET'].secret.get_secret_value()
== 'secret_proxy'
)
def test_conversation_init_data_no_pydantic_frozen_field_warning():
"""Test that ConversationInitData model does not trigger Pydantic UnsupportedFieldAttributeWarning.
This test ensures that the 'frozen' parameter is not incorrectly used in Field()
definitions, which would cause warnings in Pydantic v2 for union types.
See: https://github.com/All-Hands-AI/infra/issues/860
"""
with warnings.catch_warnings(record=True) as w:
warnings.simplefilter('always')
# Re-import to trigger any warnings during model definition
import importlib
import openhands.server.session.conversation_init_data
importlib.reload(openhands.server.session.conversation_init_data)
# Check for warnings containing 'frozen' which would indicate
# incorrect usage of frozen=True in Field()
frozen_warnings = [
warning for warning in w if 'frozen' in str(warning.message).lower()
]
assert len(frozen_warnings) == 0, (
f'Pydantic frozen field warnings found: {[str(w.message) for w in frozen_warnings]}'
)

View File

@@ -1,3 +1,4 @@
import warnings
from unittest.mock import patch
from pydantic import SecretStr
@@ -98,3 +99,31 @@ def test_convert_to_settings():
settings = convert_to_settings(settings_with_token_data)
assert settings.llm_api_key.get_secret_value() == 'test-key'
def test_settings_no_pydantic_frozen_field_warning():
"""Test that Settings model does not trigger Pydantic UnsupportedFieldAttributeWarning.
This test ensures that the 'frozen' parameter is not incorrectly used in Field()
definitions, which would cause warnings in Pydantic v2 for union types.
See: https://github.com/All-Hands-AI/infra/issues/860
"""
with warnings.catch_warnings(record=True) as w:
warnings.simplefilter('always')
# Re-import to trigger any warnings during model definition
import importlib
import openhands.storage.data_models.settings
importlib.reload(openhands.storage.data_models.settings)
# Check for warnings containing 'frozen' which would indicate
# incorrect usage of frozen=True in Field()
frozen_warnings = [
warning for warning in w if 'frozen' in str(warning.message).lower()
]
assert len(frozen_warnings) == 0, (
f'Pydantic frozen field warnings found: {[str(w.message) for w in frozen_warnings]}'
)