Skip to content

Defer GoogleSecretManagerSettingsSource client initialization to __call__#866

Draft
ecerulm wants to merge 1 commit into
pydantic:mainfrom
ecerulm:pydantic-settings-defer-secret-manager
Draft

Defer GoogleSecretManagerSettingsSource client initialization to __call__#866
ecerulm wants to merge 1 commit into
pydantic:mainfrom
ecerulm:pydantic-settings-defer-secret-manager

Conversation

@ecerulm
Copy link
Copy Markdown

@ecerulm ecerulm commented May 15, 2026

Summary

  • Lazy GCP client init: All GCP setup (google_auth_default, SecretManagerServiceClient) is moved out of __init__ into a new _initialize_client() method, called from __call__. This avoids side-effects (network calls, credential resolution) at import/construction time.
  • project_id from previous sources: If project_id is not explicitly passed, _initialize_client() checks self.current_state.get('project_id') — which is populated by previously-run settings sources — before falling back to google_auth_default(). This enables patterns like placing the GCP project ID in environment variables or init kwargs and having the GCP source pick it up automatically.
  • _load_env_vars() guard: Returns an empty dict during __init__ (before the client exists); __call__ repopulates self.env_vars with the real GoogleSecretManagerMapping before delegating to the parent.
  • Idiomatic None check: Replaced isinstance(_project_id, str) with _project_id is not None.
  • Test updates: Two existing tests updated to call _initialize_client() explicitly (since resolution is now deferred); new test_project_id_from_current_state verifies the end-to-end flow.

- Move all GCP client setup (google_auth_default, SecretManagerServiceClient)
  out of __init__ and into a new _initialize_client() method called lazily
  from __call__.
- Allow project_id to be resolved from self.current_state (populated by
  previous settings sources) when not explicitly provided, enabling patterns
  like storing the GCP project ID in env vars or init kwargs and having the
  GCP source pick it up automatically.
- _load_env_vars() returns an empty dict during __init__ (before the client
  is initialized); __call__ overwrites self.env_vars with the real
  GoogleSecretManagerMapping before delegating to the parent.
- Replace isinstance(_project_id, str) guard with an idiomatic None check.
- Update tests to reflect deferred initialization: assertions on _project_id
  now call _initialize_client() first; the AttributeError test now expects
  the error at _initialize_client() time rather than __init__ time.
- Add test_project_id_from_current_state to verify the new end-to-end flow.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant