-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Python: Replace Pydantic Settings with TypedDict + load_settings() #3843
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Python: Replace Pydantic Settings with TypedDict + load_settings() #3843
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
Replaces the Python settings system across Agent Framework packages by removing pydantic-settings/AFBaseSettings and introducing a lightweight TypedDict + load_settings() approach, with updates to all consumers and tests.
Changes:
- Added
agent_framework._settings.load_settings()+SecretString, plusSettingNotFoundErrorfor required settings resolution failures. - Migrated multiple packages’ settings schemas from
AFBaseSettingstoTypedDictand updated consumers to dict-style access. - Updated dependency set (
pydantic-settings→python-dotenv) and adjusted tests for the new settings patterns.
Reviewed changes
Copilot reviewed 60 out of 61 changed files in this pull request and generated 8 comments.
Show a summary per file
| File | Description |
|---|---|
| python/uv.lock | Swaps lockfile dependency from pydantic-settings to python-dotenv. |
| python/packages/purview/tests/purview/test_settings.py | Updates Purview settings tests for dict-style access and new helper for scopes. |
| python/packages/purview/tests/purview/test_purview_client.py | Updates Purview client tests for new settings shape. |
| python/packages/purview/tests/purview/test_processor.py | Removes obsolete Purview settings field usage in tests. |
| python/packages/purview/tests/purview/test_middleware.py | Updates middleware tests to mutate settings via dict keys. |
| python/packages/purview/tests/purview/test_chat_middleware.py | Updates chat middleware test to use dict-style settings mutation. |
| python/packages/purview/agent_framework_purview/_settings.py | Converts Purview settings to TypedDict and adds get_purview_scopes(). |
| python/packages/purview/agent_framework_purview/_processor.py | Updates Purview processor to read settings via dict access / fallbacks. |
| python/packages/purview/agent_framework_purview/_middleware.py | Updates Purview middleware to use dict-based settings with defaults. |
| python/packages/purview/agent_framework_purview/_client.py | Uses dict-based Purview settings and shared scope helper. |
| python/packages/purview/agent_framework_purview/init.py | Exposes get_purview_scopes in package exports. |
| python/packages/ollama/tests/test_ollama_chat_client.py | Updates invalid-settings expectation to SettingNotFoundError. |
| python/packages/ollama/agent_framework_ollama/_chat_client.py | Converts Ollama settings to TypedDict and loads via load_settings(). |
| python/packages/github_copilot/tests/test_github_copilot_agent.py | Updates tests for dict-style settings access. |
| python/packages/github_copilot/agent_framework_github_copilot/_settings.py | Converts GitHub Copilot settings schema to TypedDict. |
| python/packages/github_copilot/agent_framework_github_copilot/_agent.py | Loads settings via load_settings() and switches to dict access. |
| python/packages/foundry_local/tests/test_foundry_local_client.py | Updates Foundry Local tests to use load_settings() and new error type. |
| python/packages/foundry_local/agent_framework_foundry_local/_foundry_local_client.py | Converts Foundry Local settings to TypedDict + load_settings(). |
| python/packages/core/tests/openai/test_openai_responses_client.py | Adjusts OpenAI Responses client validation-failure test expectations. |
| python/packages/core/tests/openai/test_openai_chat_client.py | Adjusts OpenAI Chat client validation-failure test expectations. |
| python/packages/core/tests/openai/test_openai_assistants_client.py | Adjusts OpenAI Assistants client validation-failure test expectations. |
| python/packages/core/tests/openai/test_assistant_provider.py | Updates mocking strategy to patch load_settings() results. |
| python/packages/core/tests/core/test_settings.py | Adds focused unit tests for load_settings() behavior. |
| python/packages/core/tests/azure/test_azure_responses_client.py | Adjusts Azure Responses client validation-failure test expectations. |
| python/packages/core/tests/azure/test_azure_chat_client.py | Updates invalid-endpoint test to reflect removed URL validation. |
| python/packages/core/tests/azure/test_azure_assistants_client.py | Updates tests to mock load_settings() and Entra token helper path. |
| python/packages/core/pyproject.toml | Replaces pydantic-settings dependency with python-dotenv. |
| python/packages/core/agent_framework/openai/_shared.py | Converts OpenAI settings to TypedDict and migrates Secret type to SecretString. |
| python/packages/core/agent_framework/openai/_responses_client.py | Uses load_settings() and dict access for OpenAI Responses client init. |
| python/packages/core/agent_framework/openai/_chat_client.py | Uses load_settings() and dict access for OpenAI Chat client init. |
| python/packages/core/agent_framework/openai/_assistants_client.py | Uses load_settings() and dict access for OpenAI Assistants client init. |
| python/packages/core/agent_framework/openai/_assistant_provider.py | Uses load_settings() and SecretString for Assistant provider init. |
| python/packages/core/agent_framework/observability.py | Replaces AFBaseSettings with load_settings()-backed data object. |
| python/packages/core/agent_framework/exceptions.py | Adds SettingNotFoundError. |
| python/packages/core/agent_framework/azure/_shared.py | Converts Azure OpenAI settings to TypedDict and adds _apply_azure_defaults(). |
| python/packages/core/agent_framework/azure/_responses_client.py | Uses load_settings() + defaults helper; keeps base_url hack with urlparse. |
| python/packages/core/agent_framework/azure/_chat_client.py | Uses load_settings() + defaults helper for Azure OpenAI chat client init. |
| python/packages/core/agent_framework/azure/_assistants_client.py | Uses load_settings() + defaults helper; switches Entra token acquisition path. |
| python/packages/core/agent_framework/_settings.py | Adds the new generic load_settings() implementation and SecretString. |
| python/packages/core/agent_framework/_pydantic.py | Removes the old pydantic-settings-based AFBaseSettings implementation. |
| python/packages/copilotstudio/tests/test_copilot_agent.py | Updates tests to patch load_settings() instead of settings classes. |
| python/packages/copilotstudio/agent_framework_copilotstudio/_agent.py | Converts settings to TypedDict and loads via load_settings(). |
| python/packages/claude/tests/test_claude_agent.py | Updates Claude tests for load_settings() + dict access. |
| python/packages/claude/agent_framework_claude/_settings.py | Converts Claude settings schema to TypedDict. |
| python/packages/claude/agent_framework_claude/_agent.py | Loads Claude settings via load_settings() and switches to dict access. |
| python/packages/bedrock/tests/test_bedrock_settings.py | Updates Bedrock settings test to call load_settings(). |
| python/packages/bedrock/agent_framework_bedrock/_chat_client.py | Converts Bedrock settings to TypedDict and loads via load_settings(). |
| python/packages/azure-ai/tests/test_provider.py | Updates Azure AI provider tests to mock load_settings() results. |
| python/packages/azure-ai/tests/test_azure_ai_client.py | Updates AzureAIClient tests for load_settings() + dict access. |
| python/packages/azure-ai/tests/test_azure_ai_agent_client.py | Updates AzureAIAgentClient tests for load_settings() + dict access. |
| python/packages/azure-ai/tests/test_agent_provider.py | Updates agent provider tests to mock load_settings() results. |
| python/packages/azure-ai/agent_framework_azure_ai/_shared.py | Converts Azure AI settings schema to TypedDict. |
| python/packages/azure-ai/agent_framework_azure_ai/_project_provider.py | Uses load_settings() and dict access for provider initialization. |
| python/packages/azure-ai/agent_framework_azure_ai/_client.py | Uses load_settings() and dict access for client initialization. |
| python/packages/azure-ai/agent_framework_azure_ai/_chat_client.py | Uses load_settings() and dict access for agent chat client initialization. |
| python/packages/azure-ai/agent_framework_azure_ai/_agent_provider.py | Uses load_settings() and dict access for agent provider initialization. |
| python/packages/azure-ai-search/tests/test_search_provider.py | Updates Azure AI Search tests to use load_settings() and dict access. |
| python/packages/azure-ai-search/agent_framework_azure_ai_search/_search_provider.py | Converts settings to TypedDict and loads via load_settings(). |
| python/packages/azure-ai-search/agent_framework_azure_ai_search/_context_provider.py | Loads search settings via load_settings() and switches to dict access. |
| python/packages/anthropic/tests/test_anthropic_client.py | Updates Anthropic tests for load_settings() + dict access. |
| python/packages/anthropic/agent_framework_anthropic/_chat_client.py | Converts Anthropic settings to TypedDict and loads via load_settings(). |
- Remove pydantic-settings dependency, add python-dotenv - Delete _pydantic.py (AFBaseSettings, HTTPsUrl) - Add _settings.py with generic load_settings() function, SecretString, type coercion, and Required field validation (SettingNotFoundError) - Convert all 13 settings classes from AFBaseSettings subclasses to TypedDict definitions with load_settings() calls - Update all consumers from attribute access to dict access - Add 20 unit tests for load_settings() covering basic loading, dotenv, SecretString, type coercion, and required field validation - Update all existing tests for new settings patterns
- Fix str | None attribute access in responses_client (walrus operator) - Fix SecretString | None narrowing in bedrock (type: ignore after guard) - Convert _context_provider.py attribute access to dict access (missed file) - Fix endpoint type narrowing in search_provider and context_provider - Fix purview: str | None .rstrip(), int | None defaults, urlparse bytes
- Move required field validation from TypedDict annotations (Required) to a required_fields parameter on load_settings(), enabling runtime decisions about which fields are required - Remove Required imports and restore from __future__ import annotations in ollama and foundry_local - Add _check_override_type() for deterministic ServiceInitializationError on invalid override types (e.g. dict passed for str field) - Fix all multi-exception test catches back to single exception type - Fix Ollama host=None: use .get() so None is passed through to SDK default - Fix Purview processor: use explicit is-None checks instead of or operator - Remove unused BaseModel import from openai/_shared.py - Add 4 new tests (24 total): required_fields param, type validation
_check_override_type now permits int values for float-typed fields, matching Python's standard numeric promotion behavior.
f21e1e6 to
281693a
Compare
Summary
Replace the
pydantic-settings-basedAFBaseSettingsclass with a lightweight, function-based settings system usingTypedDict+load_settings().Changes
New:
_settings.pyload_settings(settings_type, *, env_prefix, **overrides)function that populates a TypedDict from environment variables,.envfiles, and explicit overridesSecretString(str)subclass that masksrepr()to prevent accidental secret exposureint,float,bool,SecretStringtyping.Required— raisesSettingNotFoundErrorif a required field cannot be resolved from any sourceNew:
SettingNotFoundErrorexceptionagent_framework.exceptionsfor required field validation failuresRemoved
_pydantic.py(AFBaseSettings,HTTPsUrl)pydantic-settingsdependency (replaced withpython-dotenv)Converted (13 settings classes → TypedDict)
All settings subclasses converted from
AFBaseSettingsinheritance toTypedDict(total=False)definitions:OpenAISettings,AzureOpenAISettings,AzureAISettings,AzureAISearchSettingsAnthropicSettings,BedrockSettings,ClaudeAgentSettingsOllamaSettings,FoundryLocalSettings,CopilotStudioSettingsGitHubCopilotSettings,PurviewSettings,ObservabilitySettingsAll consumer code updated from
settings.fieldattribute access tosettings["field"]dict access.Required fields
Fields using
Required[str]are validated at load time:OllamaSettings.model_idFoundryLocalSettings.model_idPurviewSettings.app_nameTesting