o
    Thr:                     @   s  d Z ddlZddlZddlZddlZddlZddlZddlmZmZm	Z	m
Z
mZmZ ddlZddlZddlZddlmZ ddlmZ ddlmZ edZd	e	eeef  d
ee deddfddZd	ed
ee defddZdedefddZdedefddZdedeeef ddfddZ ej!dddZ"G dd dej#Z#G dd  d eej$Z%defd!d"Z&d	eeef deeef fd#d$Z'd%edeed&ef ged&ef f fd'd(Z(d)edefd*d+Z)d,eeef d-eeef deeef fd.d/Z*d,eeef d-eeef ddfd0d1Z+dS )2zCommon utilities for the SDK.    N)AnyCallableOptionalUnion
get_originget_args)alias_generators   )_api_client)errorszgoogle_genai._commondatakeysvaluereturnc           	      C   s  |du rdS t |dd D ]\}}|dr|dd }| durB|| vrBt|tr8dd tt|D | |< n
td| d| t|trg| durgt | | D ]\}}t|||d	 d ||  qQ dS | dur~| | D ]}t|||d	 d | qo dS |d
r|dd }| dur|| vri g| |< | durt| | d ||d	 d |  dS | dur| |i } q| dur| 	|d }|dur|sdS ||krdS t|t
rt|t
r|| dS td|d  d| d| d|| |d < dS dS )a9  Examples:

  set_value_by_path({}, ['a', 'b'], v)
    -> {'a': {'b': v}}
  set_value_by_path({}, ['a', 'b[]', c], [v1, v2])
    -> {'a': {'b': [{'c': v1}, {'c': v2}]}}
  set_value_by_path({'a': {'b': [{'c': v1}, {'c': v2}]}}, ['a', 'b[]', 'd'], v3)
    -> {'a': {'b': [{'c': v1, 'd': v3}, {'c': v2, 'd': v3}]}}
  N[]c                 S   s   g | ]}i qS  r   ).0_r   r   W/home/air/segue/gemini/backup/venv/lib/python3.10/site-packages/google/genai/_common.py
<listcomp>5   s    z%set_value_by_path.<locals>.<listcomp>zvalue z$ must be a list given an array path r	   [0]r   z+Cannot set value for an existing key. Key: z; Existing value: z; New value: .)	enumerateendswith
isinstancelistrangelen
ValueErrorset_value_by_path
setdefaultgetdictupdate)	r   r   r   ikeykey_namejdexisting_datar   r   r   r"   $   s^   




 r"   c                    s   dgkr| S t D ]k\ }| s dS |dr4|dd }|| v r1 fdd| | D   S  dS |dr[|dd }|| v rX| | rXt| | d	  d
 d   S  dS || v rd| | } qt| trtt| |rtt| |} q dS | S )zExamples:

  get_value_by_path({'a': {'b': v}}, ['a', 'b'])
    -> v
  get_value_by_path({'a': {'b': [{'c': v1}, {'c': v2}]}}, ['a', 'b[]', 'c'])
    -> [v1, v2]
  _selfNr   r   c                    s"   g | ]}t | d  d qS )r	   N)get_value_by_path)r   r+   r'   r   r   r   r   u   s   " z%get_value_by_path.<locals>.<listcomp>r   r   r   r	   )r   r   r.   r   	BaseModelhasattrgetattr)r   r   r(   r)   r   r/   r   r.   e   s*   


"
r.   objc                 C   sP   t | tjr| jddS t | trdd |  D S t | tr&dd | D S | S )ad  Recursively converts a given object to a dictionary.

  If the object is a Pydantic model, it uses the model's `model_dump()` method.

  Args:
    obj: The object to convert.

  Returns:
    A dictionary representation of the object, a list of objects if a list is
    passed, or the object itself if it is not a dictionary, list, or Pydantic
    model.
  T)exclude_nonec                 S   s   i | ]	\}}|t |qS r   convert_to_dict)r   r(   r   r   r   r   
<dictcomp>   s    z#convert_to_dict.<locals>.<dictcomp>c                 S      g | ]}t |qS r   r5   )r   itemr   r   r   r          z#convert_to_dict.<locals>.<listcomp>)r   pydanticr0   
model_dumpr%   itemsr   )r3   r   r   r   r6      s   

r6   
annotationc                 C   s   t | }t| }|turdS |rt|dkrdS |d }t |}t|}|tur*dS |r2t|dkr4dS |\}}|tu o@|tju S )zChecks if the given annotation is list[dict[str, typing.Any]]
  or typing.List[typing.Dict[str, typing.Any]].

  This maps to Struct type in the API.
  Fr	   r      )r   r   r   r    r%   strtypingr   )r>   outer_origin
outer_argsinner_annotationinner_origin
inner_argskey_type
value_typer   r   r   _is_struct_type   s   rI   modelresponsec                 C   s   t | }|D ]g\}}dd | j D }|| jvr%||vr%|| q|||}| j| j}t|tu r?t	|d }t
|trQt|turQt|| qt
|t rot|r[q|D ]}t
|trntt	|d | q]qdS )zfRemoves extra fields from the response that are not in the model.

  Mutates the response in place.
  c                 S   s   i | ]\}}|j |qS r   )alias)r   r(   
field_infor   r   r   r7      s    z(_remove_extra_fields.<locals>.<dictcomp>r   N)r   r=   model_fieldspopr$   r>   rA   r   r   r   r   r%   _remove_extra_fieldsrI   )rJ   rK   
key_valuesr(   r   	alias_mapr>   r9   r   r   r   rP      s,   


rP   Tr0   )boundc                   @   sx   e Zd Zejejdddddddejfd	Z	e
deje deeef deeef d	efd
dZd	eeef fddZdS )r0   Tr   forbidbase64)	alias_generatorpopulate_by_namefrom_attributesprotected_namespacesextraarbitrary_types_allowedser_json_bytesval_json_bytesignored_typesclsrK   kwargsr   c                C   s^   |d uo d|v o |d d uo t |d to d|d v o |d d }|s(t| | | |}|S )Nconfiginclude_all_fields)r   r%   rP   model_validate)r`   rK   ra   should_skip_removing_fieldsvalidated_responser   r   r   _from_response   s   


	

zBaseModel._from_responsec                 C   s   | j dddS )NTjson)r4   mode)r<   )selfr   r   r   to_json_dict  s   zBaseModel.to_json_dictN)__name__
__module____qualname__r;   
ConfigDictr   to_camelrA   TypeVarmodel_configclassmethodTyperS   r%   r@   objectrg   rk   r   r   r   r   r0      s.    

c                       s.   e Zd ZdZededef fddZ  ZS )CaseInSensitiveEnumzCase insensitive enum.r   r   c                    s   z| |   W S  tyI   z	| |  W  Y S  tyH   t| d| j  zt | |}t||_	||_
|W  Y  Y S    Y Y Y d S w w )Nz is not a valid )upperKeyErrorlowerwarningswarnrl   super__new__r@   _name__value_)r`   r   unknown_enum_val	__class__r   r   	_missing_  s    

zCaseInSensitiveEnum._missing_)rl   rm   rn   __doc__rs   r   r   __classcell__r   r   r   r   rv     s     rv   c                  C   s0   t j  d} t jdd }|  d| S )z]Composes a timestamped unique name.

  Returns:
      A string representing a unique name.
  z%Y%m%d%H%M%Sr      r   )datetimenowstrftimeuuiduuid4hex)	timestamp	unique_idr   r   r   timestamped_unique_name/  s   r   c                 C   s   i }t | ts	| S |  D ]e\}}t |tr!t|d||< qt |tjr.| ||< qt |tr:t	|||< qt |t
rntdd |D rQdd |D ||< tdd |D rddd |D ||< qdd |D ||< q|||< q|S )	a  Converts unserializable types in dict to json.dumps() compatible types.

  This function is called in models.py after calling convert_to_dict(). The
  convert_to_dict() can convert pydantic object to dict. However, the input to
  convert_to_dict() is dict mixed of pydantic object and nested dict(the output
  of converters). So they may be bytes in the dict and they are out of
  `ser_json_bytes` control in model_dump(mode='json') called in
  `convert_to_dict`, as well as datetime deserialization in Pydantic json mode.

  Returns:
    A dictionary with json.dumps() incompatible type (e.g. bytes datetime)
    to compatible type (e.g. base64 encoded string, isoformat date string).
  asciic                 s   s    | ]}t |tV  qd S N)r   bytesr   vr   r   r   	<genexpr>S  s    z.encode_unserializable_types.<locals>.<genexpr>c                 S   s   g | ]
}t |d qS )r   )rV   urlsafe_b64encodedecoder   r   r   r   r   T  s    z/encode_unserializable_types.<locals>.<listcomp>c                 s   s    | ]	}t |tjV  qd S r   )r   r   r   r   r   r   r   W  s    c                 S   s   g | ]}|  qS r   )	isoformatr   r   r   r   r   X  r:   c                 S   r8   r   )encode_unserializable_typesr   r   r   r   r   Z  r:   )r   r%   r=   r   rV   r   r   r   r   r   r   all)r   processed_datar(   r   r   r   r   r   :  s(   





r   message.c                    s*   dt dtf dt dtf f fdd}|S )z&Experimental warning, only warns once.func.r   c                    s0   dt  dtdtdtf fdd}|S )NFargsra   r   c                     s(   sdt jtjdd  | i |S )NTr?   )r   category
stacklevel)rz   r{   r   ExperimentalWarning)r   ra   )r   r   warning_doner   r   wrapperd  s   z8experimental_warning.<locals>.decorator.<locals>.wrapper)	functoolswrapsr   )r   r   r   )r   r   r   	decoratorb  s    
z'experimental_warning.<locals>.decorator)r   r   )r   r   r   r   r   experimental_warning`  s   &r   key_strc                 C   s   |  dd S )z?Normalizes a key for case-insensitive and snake/camel matching.r    )replacery   )r   r   r   r   _normalize_key_for_matchings  s   r   target_dictupdate_dictc                 C   s   i }dd |   D }| D ]@\}}t|}||v r || }n|}t|tr9t| |tr9t| | |||< qt|trKt| |trK|||< q|||< q|S )a  Aligns the keys of update_dict to the case of target_dict keys.

  Args:
      target_dict: The dictionary with the target key casing.
      update_dict: The dictionary whose keys need to be aligned.

  Returns:
      A new dictionary with keys aligned to target_dict's key casing.
  c                 S   s   i | ]}t ||qS r   )r   )r   r(   r   r   r   r7     s    z"align_key_case.<locals>.<dictcomp>)r   r=   r   r   r%   r$   align_key_caser   )r   r   aligned_update_dicttarget_keys_mapr(   r   normalized_update_keyaligned_keyr   r   r   r   x  s   



r   c              
   C   s   t | |}| D ]G\}}|| v r%t| | tr%t|tr%t| | | q	|| v rLt| | t|sLtd| dt| |  dt| d || |< q	|| |< q	dS )a  Recursively updates a target dictionary with values from an update dictionary.

  We don't enforce the updated dict values to have the same type with the
  target_dict values except log warnings.
  Users providing the update_dict should be responsible for constructing correct
  data.

  Args:
      target_dict (dict): The dictionary to be updated.
      update_dict (dict): The dictionary containing updates.
  zType mismatch for key 'z'. Existing type: z, new type: z. Overwriting.N)r   r=   r   r%   recursive_dict_updatetypeloggerwarning)r   r   r   r(   r   r   r   r   r     s&   



r   ),r   rV   r   enumr   loggingrA   r   r   r   r   r   r   r   rz   r;   r   r   r
   r   	getLoggerr   r%   r   r@   r"   r.   ru   r6   r   boolrI   rP   rq   rS   r0   Enumrv   r   r   r   r   r   r   r   r   r   r   <module>   sR    
*A# 

*,",&.

