from __future__ import annotations as _annotations # important for BaseSettings import to work import json from collections.abc import Mapping from typing import TYPE_CHECKING from ..utils import InitState, parse_env_vars from .env import EnvSettingsSource if TYPE_CHECKING: from types_boto3_secretsmanager.client import SecretsManagerClient from pydantic_settings.main import BaseSettings boto3_client = None def import_aws_secrets_manager() -> None: global boto3_client try: from boto3 import client as boto3_client except ImportError as e: # pragma: no cover raise ImportError( 'AWS Secrets Manager dependencies are not installed, run `pip install pydantic-settings[aws-secrets-manager]`' ) from e class AWSSecretsManagerSettingsSource(EnvSettingsSource): _secret_id: str _secretsmanager_client: SecretsManagerClient def __init__( self, settings_cls: type[BaseSettings], secret_id: str, region_name: str | None = None, endpoint_url: str | None = None, case_sensitive: bool | None = True, env_prefix: str | None = None, env_nested_delimiter: str | None = '--', env_parse_none_str: str | None = None, env_parse_enums: bool | None = None, version_id: str | None = None, _init_state: InitState | None = None, ) -> None: import_aws_secrets_manager() self._secretsmanager_client = boto3_client('secretsmanager', region_name=region_name, endpoint_url=endpoint_url) # type: ignore self._secret_id = secret_id self._version_id = version_id super().__init__( settings_cls, case_sensitive=case_sensitive, env_prefix=env_prefix, env_nested_delimiter=env_nested_delimiter, env_ignore_empty=False, env_parse_none_str=env_parse_none_str, env_parse_enums=env_parse_enums, _init_state=_init_state, ) def _load_env_vars(self) -> Mapping[str, str | None]: request = {'SecretId': self._secret_id} if self._version_id: request['VersionId'] = self._version_id response = self._secretsmanager_client.get_secret_value(**request) return parse_env_vars( json.loads(response['SecretString']), self.case_sensitive, self.env_ignore_empty, self.env_parse_none_str, ) def __repr__(self) -> str: return ( f'{self.__class__.__name__}(secret_id={self._secret_id!r}, ' f'env_nested_delimiter={self.env_nested_delimiter!r})' ) __all__ = [ 'AWSSecretsManagerSettingsSource', ]