o
    
j4                     @  s  d dl mZ d dlZd dlZd dlmZ d dlmZm	Z	m
Z
mZ d dlmZmZ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 ddlmZmZ ddlm Z m!Z!m"Z"m#Z#m$Z$m%Z%m&Z&m'Z' ertd dl(m)Z) G dd deZ*dgZ+dS )    )annotationsN)Mapping)TYPE_CHECKINGAnyget_args
get_origin)JsonTypeAdapterValidationError)deep_updateis_model_class)is_pydantic_dataclass)	FieldInfo)is_union_origin   )_lenient_issubclass   )PydanticBaseEnvSettingsSource)EnvNoneTypeEnvPrefixTarget)_annotation_contains_types_annotation_enum_name_to_val_annotation_is_complex_get_model_fields_literal_has_numeric_enum_union_has_strict_types_union_is_complexparse_env_vars)BaseSettingsc                      s   e Zd ZdZ								d5d6 fddZd7ddZd8ddZd9d#d$Zd:d&d'Z	d;d<d+d,Z	d=d/d0Z
d>d1d2Zd?d3d4Z  ZS )@EnvSettingsSourcezN
    Source class for loading settings values from environment variables.
    Nsettings_clstype[BaseSettings]case_sensitivebool | None
env_prefix
str | Noneenv_prefix_targetEnvPrefixTarget | Noneenv_nested_delimiterenv_nested_max_split
int | Noneenv_ignore_emptyenv_parse_none_strenv_parse_enumsreturnNonec
           
   	     sv   t  |||||||	 |d ur|n| jd| _|d ur|n| jd| _| jp*dd | _t| j| _	| 
 | _d S )Nr(   r)   r      )super__init__configgetr(   r)   maxsplitlenr$   env_prefix_len_load_env_varsenv_vars)
selfr    r"   r$   r&   r(   r)   r+   r,   r-   	__class__ Z/home/kuhnn/.local/lib/python3.10/site-packages/pydantic_settings/sources/providers/env.pyr2   *   s    
zEnvSettingsSource.__init__Mapping[str, str | None]c                 C  s   t tj| j| j| jS N)r   osenvironr"   r+   r,   r:   r=   r=   r>   r8   J   s   z EnvSettingsSource._load_env_varsfieldr   
field_namestrtuple[Any, str, bool]c                 C  s>   d}|  ||D ]\}}}| j|}|dur nq|||fS )ah  
        Gets the value for field from environment variables and a flag to determine whether value is complex.

        Args:
            field: The field.
            field_name: The field name.

        Returns:
            A tuple that contains the value (`None` if not found), key, and
                a flag to determine whether value is complex.
        N)_extract_field_infor9   r4   )r:   rD   rE   env_val	field_keyenv_namevalue_is_complexr=   r=   r>   get_field_valueM   s   
z!EnvSettingsSource.get_field_valuevaluer   rL   boolc           
   
   C  s   |  |\}}| jrt|j|}|du r|n|}|s|rgt|tr#|S |du r5| ||| j}|r3|S dS z	| |||}W n t	yT }	 z
|sJ|	W Y d}	~	nd}	~	ww t|t
ret|| ||| jS |S |durq| ||S dS )a  
        Prepare value for the field.

        * Extract value for nested field.
        * Deserialize value to python object for complex field.

        Args:
            field: The field.
            field_name: The field name.

        Returns:
            A tuple contains prepared value for the field.

        Raises:
            ValuesError: When There is an error in deserializing value for complex field.
        N)_field_is_complexr-   r   
annotation
isinstancer   explode_env_varsr9   decode_complex_value
ValueErrordictr   _coerce_env_val_strict)
r:   rE   rD   rN   rL   
is_complexallow_parse_failureenum_valenv_val_builter=   r=   r>   prepare_field_valueb   s4   

z%EnvSettingsSource.prepare_field_valuetuple[bool, bool]c                 C  sB   |  |rd}d|fS tt|jrt|j|jrd}d|fS dS )za
        Find out if a field is complex, and if so whether JSON errors should be ignored
        FT)FF)field_is_complexr   r   rQ   r   metadata)r:   rD   rY   r=   r=   r>   rP      s   
z#EnvSettingsSource._field_is_complexFieldInfo | Any | NonekeyFieldInfo | Nonec                 C  s   |sdS t |tr|jn|}t|D ]}| |||}|r!|  S qtt|tr/t|d S t|s7t	|r{t
|}| D ];\}}	| |	|D ]0\}
}}
|du sT|rc||ks\||krb|	    S qI| | kss| | kry|	    S qIq?dS )aK  
        Find the field in a sub model by key(env name)

        By having the following models:

            ```py
            class SubSubModel(BaseSettings):
                dvals: Dict

            class SubModel(BaseSettings):
                vals: list[str]
                sub_sub_model: SubSubModel

            class Cfg(BaseSettings):
                sub_model: SubModel
            ```

        Then:
            next_field(sub_model, 'vals') Returns the `vals` field of `SubModel` class
            next_field(sub_model, 'sub_sub_model') Returns `sub_sub_model` field of `SubModel` class

        Args:
            field: The field.
            key: The key (env name).
            case_sensitive: Whether to search for key case sensitively.

        Returns:
            Field if it finds the next field otherwise `None`.
        N)rR   r   rQ   r   
next_fieldr   r   rV   r   r   r   itemsrH   lower)r:   rD   rb   r"   rQ   type_type_has_keyfieldsrE   f_rK   r=   r=   r>   re      s.     zEnvSettingsSource.next_fieldr9   dict[str, Any]c                   s  j si S |j}|tu ptt|t}fdd||D }i }| D ]\ }zt fdd|D }	W n	 ty@   Y q&w  t	|	d }
|

j j^ }}|}|}|D ]}||j}t|tro||i }qZ||j}|s||r|rt|tr|\}}jrt|j|}|du r|n|}n|rt|g }d}nd\}}|rzt|tr|nd}|||}W n ty } z
|s|W Y d}~nd}~ww t|tr||vst|tr|| i kr||||< q&|S )a  
        Process env_vars and extract the values of keys containing env_nested_delimiter into nested dictionaries.

        This is applied to a single field, hence filtering by env_var prefix.

        Args:
            field_name: The field name.
            field: The field.
            env_vars: Environment variables.

        Returns:
            A dictionary contains extracted values from nested env values.
        c                   s    g | ]\}}}|  j  qS r=   )r(   ).0rl   rK   rC   r=   r>   
<listcomp>   s    z6EnvSettingsSource.explode_env_vars.<locals>.<listcomp>c                 3  s    | ]
}  |r|V  qd S r@   )
startswith)rn   prefix)rK   r=   r>   	<genexpr>   s    z5EnvSettingsSource.explode_env_vars.<locals>.<genexpr>NT)TT)r(   rQ   rV   r   r   rH   rf   nextStopIterationr6   splitr5   re   r"   rR   
setdefaultr   rP   r-   r   r   rT   rU   r   rW   )r:   rE   rD   r9   annis_dictprefixesresultrI   rq   env_name_without_prefixkeyslast_keyenv_vartarget_fieldrb   rX   allow_json_failurerZ   
field_infor\   r=   )rK   r:   r>   rS      sd   





z"EnvSettingsSource.explode_env_varsc                 C  s  z}| j d}|st|trtt|jot|jpt|j}|rrt|t	rut|trx|| j
kr3|W S t|jtfdds{z
t|j|W W S  tyq   zt|}W n ttjfy_    w t|t	spt|j| Y W S  w W |S W |S W |S W |S  ty   Y |S w )a  
        Coerce environment string values based on field annotation if model config is `strict=True`
        or if the field annotation contains strict-annotated types (e.g. Optional[StrictBool]).

        Args:
            field: The field.
            value: The value to coerce.

        Returns:
            The coerced value if successful, otherwise the original value.
        strictT)is_instance)r3   r4   rR   r   r   r   rQ   r   r   rF   r,   r   r   r	   validate_pythonr
   jsonloadsrU   JSONDecodeError)r:   rD   rN   should_coercedecodedr=   r=   r>   rW     sF   

z(EnvSettingsSource._coerce_env_val_strictc                 C  s   | j j d| jd| jdS )Nz(env_nested_delimiter=z, env_prefix_len=))r<   __name__r(   r7   rC   r=   r=   r>   __repr__B  s   zEnvSettingsSource.__repr__)NNNNNNNN)r    r!   r"   r#   r$   r%   r&   r'   r(   r%   r)   r*   r+   r#   r,   r%   r-   r#   r.   r/   )r.   r?   )rD   r   rE   rF   r.   rG   )
rE   rF   rD   r   rN   r   rL   rO   r.   r   )rD   r   r.   r^   r@   )rD   ra   rb   rF   r"   r#   r.   rc   )rE   rF   rD   r   r9   r?   r.   rm   )rD   rc   rN   r   r.   r   )r.   rF   )r   
__module____qualname____doc__r2   r8   rM   r]   rP   re   rS   rW   r   __classcell__r=   r=   r;   r>   r   %   s(    
 


.
8
D&r   ),
__future__r   _annotationsr   rA   collections.abcr   typingr   r   r   r   pydanticr   r	   r
   pydantic._internal._utilsr   r   pydantic.dataclassesr   pydantic.fieldsr   typing_inspection.introspectionr   utilsr   baser   typesr   r   r   r   r   r   r   r   r   r   pydantic_settings.mainr   r   __all__r=   r=   r=   r>   <module>   s(    (  
&