U
    h1                     @  s  U d dl mZ d dlZd dlZd dl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mZ zd dlZdZW n ek
r   d	ZY nX d d
lmZ ddddgZi Zded< i Zded< dddddZG dd deZG dd dedZd<ddddddZ d=ddd d!d"d#Z!d>ddd d$d%dZ"dd&d'd(d)Z#d*d*d+d,d-Z$d?dd/ddd&d0d1dZ%d@d/ddd2d3d4dZ&d&d5d6d7Z'd8dd9d:d;Z(dS )A    )annotationsN)ABCABCMetaabstractmethod)MappingSequence)Enum)Path)AnyTextIOTF)__version__to_dict	from_dictsaveloadzdict[str, SerializableMeta]SERIALIZABLE_REGISTRYNON_SERIALIZABLE_REGISTRYstr)class_fullnamereturnc                 C  s6   |  d}t|dkr| S |^}}}|dkr2|S | S )N.   albumentations)splitlen)r   r   Z
top_module_
class_name r   E/tmp/pip-unpacked-wheel-e8onvpoz/albumentations/core/serialization.pyshorten_class_name   s    
r   c                      sd   e Zd ZdZddddd d fddZedd	d
dZedd	ddZedd	ddZ  Z	S )SerializableMetazA metaclass that is used to register classes in `SERIALIZABLE_REGISTRY` or `NON_SERIALIZABLE_REGISTRY`
    so they can be found later while deserializing transformation pipeline using classes full names.
    r   ztuple[type, ...]r
   )namebasesargskwargsr   c                   sN   t  j| ||f||}|dkrJt|krJ| r>|t| < n|t| < |S )NSerializable)super__new__r   is_serializabler   get_class_fullnamer   )clsr!   r"   r#   r$   Zcls_obj	__class__r   r   r'   ,   s    zSerializableMeta.__new__boolr   c                 C  s   dS )NFr   r*   r   r   r   r(   5   s    z SerializableMeta.is_serializablec                 C  s   t | S N)get_shortest_class_fullnamer/   r   r   r   r)   9   s    z#SerializableMeta.get_class_fullnamedict[str, Any]c                 C  s   i S r0   r   r/   r   r   r   _to_dict=   s    zSerializableMeta._to_dict)
__name__
__module____qualname____doc__r'   classmethodr(   r)   r3   __classcell__r   r   r+   r   r    '   s   	r    c                   @  s\   e Zd ZeeddddZeeddddZeddd	d
ZddddddZdS )r%   r-   r.   c                 C  s   t d S r0   NotImplementedErrorr/   r   r   r   r(   C   s    zSerializable.is_serializabler   c                 C  s   t d S r0   r:   r/   r   r   r   r)   H   s    zSerializable.get_class_fullnamer2   c                 C  s   t d S r0   r:   )selfr   r   r   to_dict_privateM   s    zSerializable.to_dict_privateraise)on_not_implemented_errorr   c                 C  s   |dkrd| d}t |z|  }W nL tk
rt   |dkrB i }tjd|  d| jj d| jj dd	d
 Y nX t|dS )a  Take a transform pipeline and convert it to a serializable representation that uses only standard
        python data types: dictionaries, lists, strings, integers, and floats.

        Args:
            self: A transform that should be serialized. If the transform doesn't implement the `to_dict`
                method and `on_not_implemented_error` equals to 'raise' then `NotImplementedError` is raised.
                If `on_not_implemented_error` equals to 'warn' then `NotImplementedError` will be ignored
                but no transform parameters will be serialized.
            on_not_implemented_error (str): `raise` or `warn`.

        >   r>   warnz(Unknown on_not_implemented_error value: z . Supported values are: 'raise' r>   z2Got NotImplementedError while trying to serialize z8. Object arguments are not preserved. Implement either 'z$.get_transform_init_args_names' or 'zC.get_transform_init_args' method to make the transform serializable   )
stacklevel)r   	transform)
ValueErrorr=   r;   warningsr@   r,   r4   r   )r<   r?   msgtransform_dictr   r   r   r   Q   s    zSerializable.to_dictN)r>   )	r4   r5   r6   r8   r   r(   r)   r=   r   r   r   r   r   r%   B   s   r%   )	metaclassr>   r2   )rC   r?   r   c                 C  s
   |  |S )ao  Take a transform pipeline and convert it to a serializable representation that uses only standard
    python data types: dictionaries, lists, strings, integers, and floats.

    Args:
        transform: A transform that should be serialized. If the transform doesn't implement the `to_dict`
            method and `on_not_implemented_error` equals to 'raise' then `NotImplementedError` is raised.
            If `on_not_implemented_error` equals to 'warn' then `NotImplementedError` will be ignored
            but no transform parameters will be serialized.
        on_not_implemented_error (str): `raise` or `warn`.

    )r   )rC   r?   r   r   r   r   r   s    zdict[str, Any] | NonezSerializable | None)rC   nonserializabler   c                 C  s\   |  dtkrX| d }|d kr2d| d}t|| |}| d krTtd| d|S d S )N__class_fullname__r4   z6To deserialize a non-serializable transform with name z you need to pass a dict withz Non-serializable transform with z# was not found in `nonserializable`)getr   rD   )rC   rI   r!   rF   Zresult_transformr   r   r   instantiate_nonserializable   s    
rL   )rG   rI   r   c                   sr   t   | d }t| }|r |S |d }dd | D }tt| }d|krh fdd|d D |d< |f |S )a  Args:
    transform_dict: A dictionary with serialized transform pipeline.
    nonserializable (dict): A dictionary that contains non-serializable transforms.
        This dictionary is required when you are restoring a pipeline that contains non-serializable transforms.
        Keys in that dictionary should be named same as `name` arguments in respective transforms from
        a serialized pipeline.

    rC   rJ   c                 S  s   i | ]\}}|d kr||qS )rJ   r   .0kvr   r   r   
<dictcomp>   s       zfrom_dict.<locals>.<dictcomp>Z
transformsc                   s   g | ]}t d |i dqS )rC   rI   )r   )rN   trR   r   r   
<listcomp>   s     zfrom_dict.<locals>.<listcomp>)register_additional_transformsrL   itemsr   r   )rG   rI   rC   Zlmbdr!   r#   r*   r   rR   r   r      s    
None)data_formatr   c                 C  s   | dkrt d|  dd S )N>   yamljsonzUnknown data_format z*. Supported formats are: 'json' and 'yaml')rD   )rX   r   r   r   check_data_format   s    r[   r
   )objr   c                 C  sR   t | trdd |  D S t | tr>t | ts>dd | D S t | trN| jS | S )zxRecursively search for Enum objects and convert them to their value.
    Also handle any Mapping or Sequence types.
    c                 S  s   i | ]\}}|t |qS r   serialize_enumrM   r   r   r   rQ      s      z"serialize_enum.<locals>.<dictcomp>c                 S  s   g | ]}t |qS r   r]   )rN   rP   r   r   r   rT      s     z"serialize_enum.<locals>.<listcomp>)
isinstancer   rV   r   r   r   value)r\   r   r   r   r^      s
    
r^   rZ   zstr | Path | TextIO)rC   filepath_or_bufferrX   r?   r   c              	   C  s   t | | j|d}t|}t|ttfrt|dD}|dkr`tsNd}t|t	j
||dd n|dkrtt|| W 5 Q R X nB|dkrtsd}t|t	j
||dd n|dkrtj||dd	 d
S )a   Serialize a transform pipeline and save it to either a file specified by a path or a file-like object
    in either JSON or YAML format.

    Args:
        transform (Serializable): The transform pipeline to serialize.
        filepath_or_buffer (Union[str, Path, TextIO]): The file path or file-like object to write the serialized
            data to.
            If a string is provided, it is interpreted as a path to a file. If a file-like object is provided,
            the serialized data will be written to it directly.
        data_format (str): The format to serialize the data in. Valid options are 'json' and 'yaml'.
            Defaults to 'json'.
        on_not_implemented_error (str): Determines the behavior if a transform does not implement the `to_dict` method.
            If set to 'raise', a `NotImplementedError` is raised. If set to 'warn', the exception is ignored, and
            no transform arguments are saved. Defaults to 'raise'.

    Raises:
        ValueError: If `data_format` is 'yaml' but PyYAML is not installed.

    )r?   wrY   z<You need to install PyYAML to save a pipeline in YAML formatF)Zdefault_flow_stylerZ   rA   )indentN)r[   r   r^   r_   r   r	   openyaml_availablerD   rY   Z	safe_dumprZ   dump)rC   ra   rX   r?   rG   frF   r   r   r   r      s&    object)ra   rX   rI   r   c              	   C  s   t | t| ttfrZt| 4}|dkr4t|}ntsDd}t|t	
|}W 5 Q R X n.|dkrnt| }nts~d}t|t	
| }t||dS )aE  Load a serialized pipeline from a file or file-like object and construct a transform pipeline.

    Args:
        filepath_or_buffer (Union[str, Path, TextIO]): The file path or file-like object to read the serialized
            data from.
            If a string is provided, it is interpreted as a path to a file. If a file-like object is provided,
            the serialized data will be read from it directly.
        data_format (str): The format of the serialized data. Valid options are 'json' and 'yaml'.
            Defaults to 'json'.
        nonserializable (Optional[dict[str, Any]]): A dictionary that contains non-serializable transforms.
            This dictionary is required when restoring a pipeline that contains non-serializable transforms.
            Keys in the dictionary should be named the same as the `name` arguments in respective transforms
            from the serialized pipeline. Defaults to None.

    Returns:
        object: The deserialized transform pipeline.

    Raises:
        ValueError: If `data_format` is 'yaml' but PyYAML is not installed.

    rZ   z<You need to install PyYAML to load a pipeline in yaml formatrR   )r[   r_   r   r	   rd   rZ   r   re   rD   rY   Z	safe_loadr   )ra   rX   rI   rg   rG   rF   r   r   r   r      s     

r.   c                  C  s>   t jddk	r:zddl} | jj}W n tk
r8   Y nX dS )zRegister transforms that are not imported directly into the `albumentations` module by checking
    the availability of optional dependencies.
    ZtorchNr   )	importlibutil	find_specZalbumentations.pytorchZpytorchZ
ToTensorV2ImportError)r   r   r   r   r   rU     s    rU   z	type[Any])r*   r   c                 C  s   | j  d| j }t|S )at  The function `get_shortest_class_fullname` takes a class object as input and returns its shortened
    full name.

    :param cls: The parameter `cls` is of type `Type[BasicCompose]`, which means it expects a class that
    is a subclass of `BasicCompose`
    :type cls: Type[BasicCompose]
    :return: a string, which is the shortened version of the full class name.
    r   )r5   r4   r   )r*   r   r   r   r   r1   *  s    	r1   )r>   )N)N)rZ   r>   )rZ   N))
__future__r   importlib.utilri   rZ   rE   abcr   r   r   collections.abcr   r   enumr   pathlibr	   typingr
   r   rY   re   rl   Zalbumentations._versionr   __all__r   __annotations__r   r   r    r%   r   rL   r   r[   r^   r   r   rU   r1   r   r   r   r   <module>   sH    

0    2  0