o
    i_J                  	   @   s  d dl Z d dlmZ d dlmZ d dlmZmZmZm	Z	m
Z
mZmZmZmZ d dlmZmZmZmZ d dlmZ g dZejZG dd	 d	Ze Z	 G d
d dZdedefddZde	eeeef defddZG dd deZdedefddZdedefddZ dddededefdd Z!d!ed"edefd#d$Z"dedee fd%d&Z#dedee fd'd(Z$dddededeeef fd)d*Z%d+ed,edefd-d.Z&dS )/    N)partial)JSONEncoder)	DictListOptionalUnioncastAnyTypeCallableTuple)datetimedatetime	timedelta)timezone)NULLAzureJSONEncoderis_generated_modelas_attribute_dictattribute_listTypeHandlerRegistryget_backcompat_attr_namec                   @   s   e Zd ZdZdefddZdS )_NullzTo create a Falsy objectreturnc                 C   s   dS )NF selfr   r   O/home/app/Keep/.python/lib/python3.10/site-packages/azure/core/serialization.py__bool__   s   z_Null.__bool__N)__name__
__module____qualname____doc__boolr   r   r   r   r   r      s    r   c                
   @   s  e Zd ZdZdddZdeeeege	f f deeege
eef f geege
eef f f fddZdeeeege	f f deeee
eef gef geee
eef gef f fd	d
Zdedeeege
eef f  fddZdedeee
eef gef  fddZdS )r   zUA registry for custom serializers and deserializers for specific types or conditions.r   Nc                 C   s(   i | _ i | _g | _g | _i | _i | _d S N)_serializer_types_deserializer_types_serializer_predicates_deserializer_predicates_serializer_cache_deserializer_cacher   r   r   r   __init__-   s   
zTypeHandlerRegistry.__init__	conditionc                    s@   dt tgtttf f dt tgtttf f f fdd}|S )a  Decorator to register a serializer.

        The handler function is expected to take a single argument, the object to serialize,
        and return a dictionary representation of that object.

        Examples:

        .. code-block:: python

            @registry.register_serializer(CustomModel)
            def serialize_single_type(value: CustomModel) -> dict:
                return value.to_dict()

            @registry.register_serializer(lambda x: isinstance(x, BaseModel))
            def serialize_with_condition(value: BaseModel) -> dict:
                return value.to_dict()

            # Called manually for a specific type
            def custom_serializer(value: CustomModel) -> Dict[str, Any]:
                return {"custom": value.custom}

            registry.register_serializer(CustomModel)(custom_serializer)

        :param condition: A type or a callable predicate function that takes an object and returns a bool.
        :type condition: Union[Type, Callable[[Any], bool]]
        :return: A decorator that registers the handler function.
        :rtype: Callable[[Callable[[Any], Dict[str, Any]]], Callable[[Any], Dict[str, Any]]]
        :raises TypeError: If the condition is neither a type nor a callable.
        handler_funcr   c                    F   t  tr| j < nt rj | f ntdj  | S Nz:Condition must be a type or a callable predicate function.)	
isinstancetyper&   callabler(   append	TypeErrorr*   clearr.   r-   r   r   r   	decoratorW      

z:TypeHandlerRegistry.register_serializer.<locals>.decorator)r   r	   r   strr   r-   r9   r   r8   r   register_serializer6   s   <!z'TypeHandlerRegistry.register_serializerc                    sD   dt ttttf gtf dt ttttf gtf f fdd}|S )a<  Decorator to register a deserializer.

        The handler function is expected to take two arguments: the target type and the data dictionary,
        and return an instance of the target type.

        Examples:

        .. code-block:: python

            @registry.register_deserializer(CustomModel)
            def deserialize_single_type(cls: Type[CustomModel], data: dict) -> CustomModel:
                return cls(**data)

            @registry.register_deserializer(lambda t: issubclass(t, BaseModel))
            def deserialize_with_condition(cls: Type[BaseModel], data: dict) -> BaseModel:
                return cls(**data)

            # Called manually for a specific type
            def custom_deserializer(cls: Type[CustomModel], data: Dict[str, Any]) -> CustomModel:
                return cls(custom=data["custom"])

            registry.register_deserializer(CustomModel)(custom_deserializer)

        :param condition: A type or a callable predicate function that takes an object and returns a bool.
        :type condition: Union[Type, Callable[[Any], bool]]
        :return: A decorator that registers the handler function.
        :rtype: Callable[[Callable[[Type, Dict[str, Any]], Any]], Callable[[Type, Dict[str, Any]], Any]]
        :raises TypeError: If the condition is neither a type nor a callable.
        r.   r   c                    r/   r0   )	r1   r2   r'   r3   r)   r4   r5   r+   r6   r7   r8   r   r   r9      r:   z<TypeHandlerRegistry.register_deserializer.<locals>.decorator)r   r
   r   r;   r	   r<   r   r8   r   register_deserializerd   s   @!z)TypeHandlerRegistry.register_deserializerobjc                 C   s^   t |}|| jv r| j| S | jt |}|s(| jD ]\}}||r'|} nq|| j|< |S )a  Gets the appropriate serializer for an object.

        It first checks the type dictionary for a direct type match.
        If no match is found, it iterates through the predicate list to find a match.

        Results of the lookup are cached for performance based on the object's type.

        :param obj: The object to serialize.
        :type obj: any
        :return: The serializer function if found, otherwise None.
        :rtype: Optional[Callable[[Any], Dict[str, Any]]]
        )r2   r*   r&   getr(   )r   r?   obj_typehandler	predicatepred_handlerr   r   r   get_serializer   s   


z"TypeHandlerRegistry.get_serializerclsc                 C   sf   || j v r
| j | S | j|}|s"| jD ]\}}||r!|} nq|r)t||nd| j |< | j | S )aX  Gets the appropriate deserializer for a class.

        It first checks the type dictionary for a direct type match.
        If no match is found, it iterates through the predicate list to find a match.

        Results of the lookup are cached for performance based on the class.

        :param cls: The class to deserialize.
        :type cls: type
        :return: A deserializer function bound to the specified class that takes a dictionary and returns
            an instance of that class, or None if no deserializer is found.
        :rtype: Optional[Callable[[Dict[str, Any]], Any]]
        N)r+   r'   r@   r)   r   )r   rF   rB   rC   rD   r   r   r   get_deserializer   s   


z$TypeHandlerRegistry.get_deserializer)r   N)r    r!   r"   r#   r,   r   r
   r   r	   r$   r   r;   r=   r>   r   rE   rG   r   r   r   r   r   *   s    
	0
.4
(.,r   tdr   c           	      C   s  |   }t|d\}}t|d\}}t|d\}}ttt|||f\}}}t|d}d}|r3d| }d}|p8|}|rB|d|7 }|pE|}|rO|d|7 }z| r\d	t|}n	d
| }|d}W n t	yt   d	|}Y nw |d|7 }d| | S )au  Converts a datetime.timedelta object into an ISO 8601 formatted string, e.g. 'P4DT12H30M05S'

    Function adapted from the Tin Can Python project: https://github.com/RusticiSoftware/TinCanPython

    :param td: The timedelta object to convert
    :type td: datetime.timedelta
    :return: An ISO 8601 formatted string representing the timedelta object
    :rtype: str
    <          z%sDTz{:02}Hz{:02}Mz{:02}z%09.6f0z{}SP)
total_secondsdivmodlistmapintroundformat
is_integerrstripAttributeError)	rH   secondsminuteshoursdaysZdate_strZtime_strZbigger_existsZseconds_stringr   r   r   _timedelta_as_isostr   s6   

r^   dtc                 C   s   t | dr(t | dr(tt| } | js| jtd }n| t }|ddS zttt	t
f | } |  W S  tyH   tt| } t|  Y S w )aC  Converts a datetime.(datetime|date|time|timedelta) object into an ISO 8601 formatted string.

    :param dt: The datetime object to convert
    :type dt: datetime.datetime or datetime.date or datetime.time or datetime.timedelta
    :return: An ISO 8601 formatted string representing the datetime object
    :rtype: str
    yearhour)tzinfoz+00:00Z)hasattrr   r   rb   replaceTZ_UTC	isoformat
astimezoner   r   r   rY   r   r^   )r_   Ziso_formattedr   r   r   _datetime_as_isostr   s   	


ri   c                       s*   e Zd ZdZdedef fddZ  ZS )r   zHA JSON encoder that's capable of serializing datetime objects and bytes.or   c                    sJ   t |ttfrt| S zt|W S  ty   Y nw tt	| 
|S )zOverride the default method to handle datetime and bytes serialization.
        :param o: The object to serialize.
        :type o: any
        :return: A JSON-serializable representation of the object.
        :rtype: any
        )r1   bytes	bytearraybase64	b64encodedecoderi   rY   superr   default)r   rj   	__class__r   r   rq     s   
zAzureJSONEncoder.default)r    r!   r"   r#   r	   rq   __classcell__r   r   rr   r   r     s    r   r?   c                 C   s   t t| ddpt| dS )zCheck if the object is a generated SDK model.

    :param obj: The object to check.
    :type obj: any
    :return: True if the object is a generated SDK model, False otherwise.
    :rtype: bool
    Z	_is_modelF_attribute_map)r$   getattrrd   )r?   r   r   r   r   /  s   r   pc                 C   s$   z| j dgkW S  ty   Y dS w )zCheck if an attribute is readonly.

    :param any p: The property to check.
    :return: True if the property is readonly, False otherwise.
    :rtype: bool
    readF)Z_visibilityrY   )rw   r   r   r   _is_readonly:  s
   ry   Fexclude_readonlyvr{   c                   sx   | d u s	t | trd S t | tttfr t|  fdd| D S t | tr0 fdd|  D S t| r:t	|  dS | S )Nc                 3   s    | ]	}t | d V  qdS )rz   N_as_attribute_dict_value).0xrz   r   r   	<genexpr>K      z+_as_attribute_dict_value.<locals>.<genexpr>c                    s   i | ]\}}|t | d qS )rz   r}   )r   ZdkZdvrz   r   r   
<dictcomp>M  s    z,_as_attribute_dict_value.<locals>.<dictcomp>rz   )
r1   r   rR   tuplesetr2   dictitemsr   r   )r|   r{   r   rz   r   r~   G  s   
r~   
rest_fielddefault_attr_namec                 C   s$   z| j p|W S  ty   | Y S w )a  Get the backcompat name for an attribute.

    :param any rest_field: The rest field to get the backcompat name from.
    :param str default_attr_name: The default attribute name to use if no backcompat name
    :return: The backcompat name.
    :rtype: str
    )Z_original_tsp_namerY   )r   r   r   r   r   _get_backcompat_nameQ  s
   r   c              	   C   s   d}zt | tdd t| D d}W n
 ty   Y dS w |du r$dS | j D ]!\}}zt|jj 	t|r@|W   S W q) t
yJ   Y q)w dS )zGet the name of the flattened attribute in a generated TypeSpec model if one exists.

    :param any obj: The object to check.
    :return: The name of the flattened attribute if it exists, otherwise None.
    :rtype: Optional[str]
    Nc                 s   s    | ]	}d |v r|V  qdS )Z__flattened_itemsNr   )r   ar   r   r   r   h  r   z+_get_flattened_attribute.<locals>.<genexpr>)rv   nextdirStopIteration_attr_to_rest_fieldr   r   _class_typekeysintersectionrY   )r?   Zflattened_itemskr|   r   r   r   _get_flattened_attribute_  s"   "
r   c                 C   sp   t | stdt| drt| j S t| }g }| j D ]\}}||kr0|	t
|j q|| q|S )zGet a list of attribute names for a generated SDK model.

    :param obj: The object to get attributes from.
    :type obj: any
    :return: A list of attribute names.
    :rtype: List[str]
    z$Object is not a generated SDK model.ru   )r   r5   rd   rR   ru   r   r   r   r   extendr   r   r4   )r?   flattened_attributeretval	attr_namer   r   r   r   r   y  s   
r   c             
      sv  t | stdt| dr| j| dS zi }t }i }t| }| j D ]*\}}|r5t|r5|	|j
 ||krJ|jj D ]	\}}	|||	j
< q?q%|||j
< q%|  D ]R\ }
|r_ |v r_qT |kry|
 D ]\}}	t|	|d||||< qgqTd}zt fdd| j D j}W n	 ty   Y nw |r|
nt|
|d||  < qT|W S  ty } ztd|d}~ww )	a  Convert an object to a dictionary of its attributes.

    Made solely for backcompatibility with the legacy `.as_dict()` on msrest models.

    .. deprecated::1.35.0
        This function is added for backcompat purposes only.

    :param any obj: The object to convert to a dictionary
    :keyword bool exclude_readonly: Whether to exclude readonly properties
    :return: A dictionary containing the object's attributes
    :rtype: dict[str, any]
    :raises TypeError: If the object is not a generated model instance
    *Object must be a generated model instance.ru   )Zkeep_readonlyrz   Fc                 3   s    | ]
}|j  kr|V  qd S r%   )
_rest_name)r   rfr   r   r   r     s    z$as_attribute_dict.<locals>.<genexpr>N)r   r5   rd   as_dictr   r   r   r   ry   addr   r   r~   r@   r   valuesZ_is_multipart_file_inputr   rY   )r?   r{   resultZreadonly_propsZrest_to_attrr   r   r   fkfvr|   Zis_multipart_file_inputexcr   r   r   r     sR   

r   modelr   c                 C   s~   t | stdt| }| j D ]+\}}||kr t||  S ||kr<|jj D ]\}}||kr;t||    S q*q|S )a  Get the backcompat attribute name for a given attribute.

    This function takes an attribute name and returns the backcompat name (original TSP name)
    if one exists, otherwise returns the attribute name itself.

    :param any model: The model instance.
    :param str attr_name: The attribute name to get the backcompat name for.
    :return: The backcompat attribute name (original TSP name) or the attribute name itself.
    :rtype: str
    r   )r   r5   r   r   r   r   r   )r   r   r   Zfield_attr_namer   r   r   r   r   r   r     s   r   )'rm   	functoolsr   jsonr   typingr   r   r   r   r   r	   r
   r   r   r   r   r   r   r   __all__utcrf   r   r   r   r;   r^   ri   r   r$   r   ry   r~   r   r   r   r   r   r   r   r   r   <module>   s0   ,	  7
$=