o
    _�¿j†;  ã                   @  s
  d dl mZ d dlZd dlmZmZ d dlmZ d dl	m
Z
mZ d dlmZ ddlmZ d	d
lmZ d	dlmZ ddlmZ e
rYd dlma d dlma d dlma d dlmZ ndadadaddd„Zd dd„Z G dd„ dee!e!dB f ƒZ"G dd„ deƒZ#ddgZ$dS )!é    )ÚannotationsN)ÚIteratorÚMapping)Úcached_property)ÚTYPE_CHECKINGÚAny)Ú	FieldInfoé   )ÚSettingsErroré   )ÚSecretVersion)Ú	InitStateé   )ÚEnvSettingsSource©Údefault©ÚCredentials©ÚSecretManagerServiceClient)ÚBaseSettingsÚreturnÚNonec               
   C  sˆ   z2ddl ma ddlma t ¡ � tjdtd� ddl	m
a
 W d   ƒ W d S 1 s+w   Y  W d S  tyC }  ztdƒ| ‚d } ~ ww )Nr   r   r   Úignore)Úcategoryr   zjGCP Secret Manager dependencies are not installed, run `pip install pydantic-settings[gcp-secret-manager]`)Úgoogle.authr   Úgoogle_auth_defaultÚgoogle.auth.credentialsr   ÚwarningsÚcatch_warningsÚfilterwarningsÚFutureWarningÚgoogle.cloud.secretmanagerr   ÚImportError)Úe© r%   úb/home/dinkstrade/pdmp/venv/lib/python3.10/site-packages/pydantic_settings/sources/providers/gcp.pyÚimport_gcp_secret_manager   s   
&þÿþ€ÿr'   ÚexcÚ	ExceptionÚboolc                 C  s.   zddl m} t| |ƒW S  ty   Y dS w )Nr   )ÚNotFoundF)Úgoogle.api_core.exceptionsr+   Ú
isinstancer#   )r(   r+   r%   r%   r&   Ú_is_not_found_error-   s   ÿr.   c                   @  sœ   e Zd ZU ded< ded< d.dd„Zed/dd„ƒZd0dd„Zed1dd„ƒZ	ed2dd„ƒZ
d3d4dd„Zd3d5d!d"„Zd6d#d$„Zd7d%d&„Zd8d(d)„Zd9d+d,„Zd-S ):ÚGoogleSecretManagerMappingzdict[str, str | None]Ú_loaded_secretsr   Ú_secret_clientÚsecret_clientÚ
project_idÚstrÚcase_sensitiver*   r   r   c                 C  s   i | _ || _|| _|| _d S ©N)r0   r1   Ú_project_idÚ_case_sensitive)Úselfr2   r3   r5   r%   r%   r&   Ú__init__:   s   
z#GoogleSecretManagerMapping.__init__c                 C  s   | j  | j¡S r6   )r1   Úcommon_project_pathr7   ©r9   r%   r%   r&   Ú_gcp_project_path@   ó   z,GoogleSecretManagerMapping._gcp_project_pathÚ
lower_nameÚ
candidatesú	list[str]c                 C  sL   t |ƒdkr
|d S | ¡  |d }tjd|› d|› d|› d�tdd	� |S )
Nr   r   éÿÿÿÿz)Secret collision: Found multiple secrets z normalizing to 'z
'. Using 'z' for case-insensitive lookup.r   )Ú
stacklevel)ÚlenÚsortr   ÚwarnÚUserWarning)r9   r?   r@   Úwinnerr%   r%   r&   Ú_select_case_insensitive_secretD   s   ÿüz:GoogleSecretManagerMapping._select_case_insensitive_secretúdict[str, str]c                 C  s˜   i }i }| j j| jd�}|D ]'}| j  |j¡ dd¡}|||< | js5| ¡ }||vr.g ||< ||  |¡ q| jsJ| 	¡ D ]\}}|  
||¡||< q=|S )N)ÚparentÚsecretÚ )r1   Úlist_secretsr=   Úparse_secret_pathÚnameÚgetr8   ÚlowerÚappendÚitemsrI   )r9   ÚmappingÚnormalized_groupsÚsecretsrL   rP   r?   r@   r%   r%   r&   Ú_secret_name_mapS   s    €z+GoogleSecretManagerMapping._secret_name_mapc                 C  s   t | j ¡ ƒS r6   )ÚlistrX   Úkeysr<   r%   r%   r&   Ú_secret_namesj   r>   z(GoogleSecretManagerMapping._secret_namesÚlatestÚkeyÚversionc                 C  s   | j  | j||¡S r6   )r1   Úsecret_version_pathr7   )r9   r]   r^   r%   r%   r&   Ú_secret_version_pathn   s   z/GoogleSecretManagerMapping._secret_version_pathÚgcp_secret_nameú
str | Nonec                 C  s8   z| j j|  ||¡d�jj d¡W S  ty   Y d S w ©N)rP   zUTF-8)r1   Úaccess_secret_versionr`   ÚpayloadÚdataÚdecoder)   )r9   ra   r^   r%   r%   r&   Ú_get_secret_valueq   s   
ÿ
þÿz,GoogleSecretManagerMapping._get_secret_valuec              
   C  sZ   z| j j|  |¡d�jj d¡W S  ty, } zt|ƒr!t|ƒ|‚W Y d }~d S d }~ww rc   )	r1   rd   r`   re   rf   rg   r)   r.   ÚKeyError)r9   ra   r$   r%   r%   r&   Ú_get_secret_value_or_raisey   s   ÿ
þ
€ýz5GoogleSecretManagerMapping._get_secret_value_or_raisec                 C  s€   || j v r
| j | S | jr|  |¡| j |< | j | S | j |¡}|d u r,| j | ¡ ¡}|r7|  |¡| j |< nt|ƒ‚| j | S r6   )r0   r8   rj   rX   rQ   rR   rh   ri   )r9   r]   ra   r%   r%   r&   Ú__getitem__ƒ   s   



z&GoogleSecretManagerMapping.__getitem__Úintc                 C  ó
   t | jƒS r6   )rD   r[   r<   r%   r%   r&   Ú__len__–   ó   
z"GoogleSecretManagerMapping.__len__úIterator[str]c                 C  rm   r6   )Úiterr[   r<   r%   r%   r&   Ú__iter__™   ro   z#GoogleSecretManagerMapping.__iter__N)r2   r   r3   r4   r5   r*   r   r   ©r   r4   )r?   r4   r@   rA   r   r4   )r   rJ   )r   rA   )r\   )r]   r4   r^   r4   r   r4   )ra   r4   r^   r4   r   rb   )ra   r4   r   rb   )r]   r4   r   rb   )r   rl   )r   rp   )Ú__name__Ú
__module__Ú__qualname__Ú__annotations__r:   Úpropertyr=   rI   r   rX   r[   r`   rh   rj   rk   rn   rr   r%   r%   r%   r&   r/   6   s"   
 





r/   c                      sŽ   e Zd ZU ded< ded< ded< ded< 									
	d,d-‡ fdd„Zd.‡ fd d!„Zd/d"d#„Zd0d%d&„Zd1‡ fd(d)„Zd2d*d+„Z	‡  Z
S )3Ú!GoogleSecretManagerSettingsSourceúCredentials | NoneÚ_credentialsú!SecretManagerServiceClient | Noner1   rb   r7   Ú_explicit_project_idNTr3   Úsettings_clsútype[BaseSettings]ÚcredentialsÚ
env_prefixÚenv_parse_none_strÚenv_parse_enumsúbool | Noner2   r5   Úproject_id_fieldr4   Ú_init_stateúInitState | Noner   r   c              	     sf   t du stdu stdu rtƒ  || _d| _|| _|| _|	| _d| _	t
ƒ j|||d|||
d� d| _	dS )a¹  Settings source that reads secrets from Google Cloud Secret Manager.

        Args:
            project_id: The GCP project to read secrets from. If not provided, it is
                resolved lazily (see below).
            project_id_field: The key, populated by a previous (higher priority)
                settings source, to use as the ``project_id`` when one is not passed
                explicitly. This must match the key used in ``current_state`` by the
                previous source (typically the field name or its preferred alias).
                For example, with ``some_field: str = Field(alias='GCP_PROJECT')``,
                previous env sources will expose the value under ``'GCP_PROJECT'``.
                Defaults to ``'project_id'``.

        The ``project_id`` is resolved lazily in :meth:`__call__` rather than at
        construction time so that it can be sourced from settings resolved by previous
        sources (only available via ``current_state`` once the source is called).
        Resolution order is:

        1. the explicit ``project_id`` argument
        2. the ``project_id_field`` value from previous settings sources
        3. ``google.auth.default()``
        NF)r5   r�   Úenv_ignore_emptyr‚   rƒ   r†   T)r   r   r   r'   r}   r7   r{   r1   Ú_project_id_fieldÚ_env_vars_loadedÚsuperr:   )r9   r~   r€   r3   r�   r‚   rƒ   r2   r5   r…   r†   ©Ú	__class__r%   r&   r:   £   s$   $ù

z*GoogleSecretManagerSettingsSource.__init__Úfieldr   Ú
field_nameútuple[Any, str, bool]c                   sþ   t dd„ |jD ƒdƒ}|r`t| jtƒr`|  ||¡D ]A\}}}| jr$|}n| jj |¡}|du r8| jj | 	¡ ¡}|rZ| j 
||¡}|durZ| jj d¡rS|||f  S |||f  S qd|dfS tƒ  ||¡\}	}
}| jj d¡rz|	durz|	||fS |	|
|fS )aü  Override get_field_value to get the secret value from GCP Secret Manager.
        Look for a SecretVersion metadata field to specify a particular SecretVersion.

        Args:
            field: The field to get the value for
            field_name: The declared name of the field

        Returns:
            A tuple of (value, key, value_is_complex), where `key` is the identifier used
            to populate the model (either the field name or an alias, depending on
            configuration).
        c                 s  s    � | ]}t |tƒr|jV  qd S r6   )r-   r   r^   )Ú.0Úmr%   r%   r&   Ú	<genexpr>î   s   € zDGoogleSecretManagerSettingsSource.get_field_value.<locals>.<genexpr>NÚpopulate_by_nameF)ÚnextÚmetadatar-   Úenv_varsr/   Ú_extract_field_infor5   rX   rQ   rR   rh   r~   Úmodel_configr‹   Úget_field_value)r9   rŽ   r�   Úsecret_versionÚ	field_keyÚenv_nameÚvalue_is_complexra   Úenv_valÚvalr]   Ú
is_complexrŒ   r%   r&   rš   à   s(   €


z1GoogleSecretManagerSettingsSource.get_field_valuec                 C  sÀ   | j durdS | j}| j}|du r| j | j¡}t|tƒr|}| jdu o'|du }|du }|s0|rBt	ƒ \}}|r9|}|rBt|tƒrB|}|du rJt
dƒ‚|| _|| _ | jdu r^t| jd�| _dS dS )a:  Resolve the credentials, project_id and Secret Manager client.

        ``project_id`` is resolved, in order of precedence, from: the explicit
        ``project_id`` argument, the ``project_id_field`` value from previous settings
        sources (``current_state``), and finally ``google.auth.default()``.
        NzÚproject_id is required to be specified either as an argument, via a previous settings source, or from google.auth.default. See https://google-auth.readthedocs.io/en/master/reference/google.auth.html#google.auth.default)r€   )r7   r}   r{   Úcurrent_staterQ   r‰   r-   r4   r1   r   ÚAttributeErrorr   )r9   r3   r€   Ústate_project_idÚneed_credentialsÚneed_projectÚ_credsr7   r%   r%   r&   Ú_resolve_gcp_project  s2   


ÿ
ÿz6GoogleSecretManagerSettingsSource._resolve_gcp_projectúMapping[str, str | None]c                 C  sB   | j si S |  ¡  | jd u s| jd u rtdƒ‚t| j| j| jd�S )NzæGoogleSecretManagerSettingsSource: could not determine GCP project_id or initialize the Secret Manager client. Pass project_id explicitly or ensure it is available via application default credentials or a previous settings source.)r3   r5   )rŠ   r¨   r7   r1   r
   r/   r5   r<   r%   r%   r&   Ú_load_env_vars=  s   ÿÿz0GoogleSecretManagerSettingsSource._load_env_varsúdict[str, Any]c                   s   d| _ |  ¡ | _tƒ  ¡ S )NT)rŠ   rª   r—   r‹   Ú__call__r<   rŒ   r%   r&   r¬   M  s   

z*GoogleSecretManagerSettingsSource.__call__c                 C  s2   | j d ur| j n| j}| jj› d|›d| j›d�S )Nz(project_id=z, env_nested_delimiter=ú))r7   r}   r�   rt   Úenv_nested_delimiter)r9   r3   r%   r%   r&   Ú__repr__T  s   ÿz*GoogleSecretManagerSettingsSource.__repr__)	NNNNNNTr3   N)r~   r   r€   rz   r3   rb   r�   rb   r‚   rb   rƒ   r„   r2   r|   r5   r„   r…   r4   r†   r‡   r   r   )rŽ   r   r�   r4   r   r�   ©r   r   )r   r©   )r   r«   rs   )rt   ru   rv   rw   r:   rš   r¨   rª   r¬   r¯   Ú__classcell__r%   r%   rŒ   r&   ry   �   s(   
 õ=
1
,ry   r°   )r(   r)   r   r*   )%Ú
__future__r   Ú_annotationsr   Úcollections.abcr   r   Ú	functoolsr   Útypingr   r   Úpydantic.fieldsr   Ú
exceptionsr
   Útypesr   Úutilsr   Úenvr   r   r   r   r   r   r"   r   Úpydantic_settings.mainr   r'   r.   r4   r/   ry   Ú__all__r%   r%   r%   r&   Ú<module>   s0    

	g A