a
    g=icB                     @   s^  d Z 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mZmZmZ ddlmZ ddlmZ dd	lmZmZmZmZ dd
lmZ ddlmZ ddl m!Z!m"Z"m#Z#m$Z$ ddl%m&Z&m'Z' ddl(m)Z) er$ddl%m*Z* ddlm+Z+m,Z, edddZ-eed df Z.G dd dZ/g dZ0edZ1ej2dkrede!e"fdedddddddddd	e3e3e3e3e3e3eeee4 df ee3 e3e	ee1 gdf d
d d!Z5ede!e"fdedddddddddd	ee1 e3e3e3e3e3e3eeee4 df ee3 e3dd"d#d!Z5nede!e"fdeddddddddd$e3e3e3e3e3e3eeee4 df ee3 e	ee1 gdf d%	d&d!Z5ede!e"fdeddddddddd$ee1 e3e3e3e3e3e3eeee4 df ee3 dd'
d(d!Z5ede!e"fddJdddddddddd	eee1  e3e3e3e3e3e3eeee4 df ee3 e3ee	ee1 gdf df d"d)d!Z5eed e3eed ddf d*d+d,Z6G d-d dZ7ed ee e3e8dd.d/d0Z9dd1d2d3d4Z:ed edd5d6d7Z;edfed ee ee8 ed8 d9d:d;Z<ddd<d=d>Z=de8edd?d@dAZ>ee ee8 d2dBdCZ?ee e3dDdEdFZ@ed ee d1dGdHdIZAdS )KaX  
The main purpose is to enhance stdlib dataclasses by adding validation
A pydantic dataclass can be generated from scratch or from a stdlib one.

Behind the scene, a pydantic dataclass is just like a regular one on which we attach
a `BaseModel` and magic methods to trigger the validation of the data.
`__init__` and `__post_init__` are hence overridden and have extra logic to be
able to validate input data.

When a pydantic dataclass is generated from scratch, it's just a plain dataclass
with validation triggered at initialization

The tricky part if for stdlib dataclasses that are converted after into pydantic ones e.g.

```py
@dataclasses.dataclass
class M:
    x: int

ValidatedM = pydantic.dataclasses.dataclass(M)
```

We indeed still want to support equality, hashing, repr, ... as if it was the stdlib one!

```py
assert isinstance(ValidatedM(x=1), M)
assert ValidatedM(x=1) == M(x=1)
```

This means we **don't want to create a new dataclass that inherits from it**
The trick is to create a wrapper around `M` that will act as a proxy to trigger
validation without altering default `M` behaviour.
    N)contextmanager)wraps)TYPE_CHECKINGAnyCallableClassVarDict	GeneratorOptionalSetTypeTypeVarUnionoverload)dataclass_transform   )gather_all_validators)
BaseConfig
ConfigDictExtra
get_config)ValidationError)DataclassTypeError)Field	FieldInfoRequired	Undefined)create_modelvalidate_model)ClassAttribute)	BaseModel)CallableGeneratorNoArgAnyCallable
DataclassT	Dataclass)boundDataclassProxyc                   @   s   e Zd ZU eeeef  ed< ee ed< eed  ed< ee	 ed< eed  ed< ee	 ed< ee
e  ed< eed gd	f  ed
< ee	 ed< eed	dddZee
d  ddddZee
d eddddZd	S )r$   __dataclass_fields____dataclass_params__).N__post_init____pydantic_run_validation____post_init_post_parse____pydantic_initialised____pydantic_model__N__pydantic_validate_values__#__pydantic_has_field_info_default__argskwargsreturnc                 O   s   d S N selfr1   r2   r5   r5   e/home/droni/.local/share/virtualenvs/DPS-5Je3_V2c/lib/python3.9/site-packages/pydantic/dataclasses.py__init__T   s    zDataclass.__init__r!   clsr3   c                 C   s   d S r4   r5   r;   r5   r5   r8   __get_validators__W   s    zDataclass.__get_validators__r#   r;   vr3   c                 C   s   d S r4   r5   r;   r?   r5   r5   r8   __validate__[   s    zDataclass.__validate__)__name__
__module____qualname__r   r   strr   __annotations__r   boolr   r    objectr9   classmethodr=   rA   r5   r5   r5   r8   r$   F   s   
)	dataclassset_validation$create_pydantic_model_from_dataclassis_builtin_dataclassmake_dataclass_validator_T   
   T)Zkw_only_defaultZfield_descriptorsF.	initrepreqorderunsafe_hashfrozenconfigvalidate_on_initkw_onlyDataclassClassOrWrapper)
rT   rU   rV   rW   rX   rY   rZ   r[   r\   r3   c        	   	      C   s   d S r4   r5   rS   r5   r5   r8   rJ   l   s    rJ   )_clsrT   rU   rV   rW   rX   rY   rZ   r[   r\   r3   c       	   
      C   s   d S r4   r5   )
r^   rT   rU   rV   rW   rX   rY   rZ   r[   r\   r5   r5   r8   rJ   |   s    rT   rU   rV   rW   rX   rY   rZ   r[   )	rT   rU   rV   rW   rX   rY   rZ   r[   r3   c                 C   s   d S r4   r5   r_   r5   r5   r8   rJ      s    )
r^   rT   rU   rV   rW   rX   rY   rZ   r[   r3   c          	      C   s   d S r4   r5   )	r^   rT   rU   rV   rW   rX   rY   rZ   r[   r5   r5   r8   rJ      s    c       	            sF   t |tt dd 	f
dd}
 du r>|
S |
 S )a  
    Like the python standard lib dataclasses but with type validation.
    The result is either a pydantic dataclass that will validate input data
    or a wrapper that will trigger validation around a stdlib dataclass
    to avoid modifying it directly
    r]   r:   c              
      s   dd l }t| r8t t jd kr8d}t| }d}nL| jp@d}tjdkrh|j| d}n|j| d}d}	d u r|n	}t	| || |j
jf i | j| i |S )Nr    FrP   )rT   rU   rV   rW   rX   rY   r\   )rT   rU   rV   rW   rX   rY   T)dataclassesrM   _extra_dc_args	__bases__r&   __doc__sysversion_inforJ   #_add_pydantic_validation_attributesr-   Z__try_update_forward_refs__rB   )r;   ra   
dc_cls_docdc_clsZdefault_validate_on_initZshould_validate_on_init
r^   rV   rY   rT   r\   rW   rU   Z
the_configrX   r[   r5   r8   wrap   s2    

zdataclass.<locals>.wrapN)r   r   r   )r^   rT   rU   rV   rW   rX   rY   rZ   r[   r\   rk   r5   rj   r8   rJ      s
    *)r;   valuer3   c                 c   s*   | j }z|| _ | V  W || _ n|| _ 0 d S r4   )r*   )r;   rl   Zoriginal_run_validationr5   r5   r8   rK      s
    rK   c                   @   sV   e Zd ZdZed ddddZeeeddd	Zeed
ddZ	ee
dddZdS )r&   __dataclass__r$   N)ri   r3   c                 C   s   t | d| d S )Nrm   )rH   __setattr__)r7   ri   r5   r5   r8   r9      s    zDataclassProxy.__init__r0   c                 O   s@   t | jd  | j|i |W  d    S 1 s20    Y  d S )NT)rK   rm   r6   r5   r5   r8   __call__   s    zDataclassProxy.__call__)namer3   c                 C   s   t | j|S r4   )getattrrm   )r7   rp   r5   r5   r8   __getattr__   s    zDataclassProxy.__getattr__)instancer3   c                 C   s   t || jS r4   )
isinstancerm   )r7   rs   r5   r5   r8   __instancecheck__  s    z DataclassProxy.__instancecheck__)rB   rC   rD   	__slots__r   r9   r   ro   rE   rr   rG   ru   r5   r5   r5   r8   r&      s
   )ri   rZ   r[   rh   r3   c                    s$  | j tdttdd fddt| drt| jtdttdd fdd}t| d	 t| d| n,tdttddfd
d}t| d	| t| dtd| t| dd t| dt|  | t| dt t| dt	t
 t| dt	t | jjjr | jjs t| dt dS )a  
    We need to replace the right method. If no `__post_init__` has been set in the stdlib dataclass
    it won't even exist (code is generated on the fly by `dataclasses`)
    By default, we run validation after `__init__` or `__post_init__` if defined
    r$   N)r7   r1   r2   r3   c                    s   j tjkr6 g|R i  fdd| D  nlj tjkr| D ]\}} j|| qJ g|R i  fdd| D  n g|R i | d S )Nc                    s    i | ]\}}| j v r||qS r5   r'   .0kr?   r7   r5   r8   
<dictcomp>      zR_add_pydantic_validation_attributes.<locals>.handle_extra_init.<locals>.<dictcomp>c                    s    i | ]\}}| j v r||qS r5   rw   rx   r{   r5   r8   r|     r}   )extrar   ignoreitemsZallow__dict__
setdefault)r7   r1   r2   rz   r?   )rZ   rT   r{   r8   handle_extra_init  s    **z>_add_pydantic_validation_attributes.<locals>.handle_extra_initr)   c                    sn    j dkr | g|R i | | jjrJ|   t| drJ| j|i |  j dkrj| g|R i | d S )NZbefore_validationr+   Zafter_validation)Zpost_init_call	__class__r*   r.   hasattrr+   r6   )rZ   	post_initr5   r8   new_post_init"  s    


z:_add_pydantic_validation_attributes.<locals>.new_post_initr9   c              	      s    | g|R i | | j jr&|   t| drdd l}i }t| j j D ]P\}}|j|j	u rLz|| ||j
< W qL ty   ||j
|j||j
< Y qL0 qL| jf i | d S )Nr+   r   )r   r*   r.   r   ra   	enumerater'   values_field_type_FIELD_INITVARrp   
IndexErrorgetdefaultr+   )r7   r1   r2   ra   Zinitvars_and_valuesif)r   r5   r8   new_init4  s    
z5_add_pydantic_validation_attributes.<locals>.new_initr*   r,   Fr-   r.   rA   r=   rn   )r9   r   r   r   r)   setattrr   rL   _dataclass_validate_valuesrI   _validate_dataclass_get_validatorsr-   
__config__Zvalidate_assignmentr(   rY   &_dataclass_validate_assignment_setattr)ri   rZ   r[   rh   r   r   r5   )rZ   r   rT   r   r8   rg     s(    
rg   r!   r:   c                 c   s   | j V  d S r4   )rA   r<   r5   r5   r8   r   Y  s    r   r>   c                 C   s   t | d t|| r0|  |W  d    S t|ttfrT| | W  d    S t|trz| f i |W  d    S t| jdW d    n1 s0    Y  d S )NT)
class_name)rK   rt   r.   listtupledictr   rB   r@   r5   r5   r8   r   ]  s    

r   r    )ri   rZ   rh   r3   c                 C   s   dd l }i }|| D ]t}t}d }|j|jur6|j}n|j|jurJ|j}nt}t|trd|}d| _	nt
f ||d|j}|j|f||j< qt| }	t| jf|| j|	ddid|}
|d ur|n| jpd|
_|
S )Nr   T)r   default_factoryZ__resolve_forward_refs__F)r   rC   Z__validators__Z__cls_kwargs__r`   )ra   fieldsr   r   MISSINGr   r   rt   r   r/   r   metadatatyperp   r   r   rB   rC   rd   )ri   rZ   rh   ra   Zfield_definitionsfieldr   r   Z
field_info
validatorsmodelr5   r5   r8   rL   j  s8    
rL   )r7   r3   c                 C   st   t | drd S t | ddr0dd | j D }n| j}t| j|| jd\}}}|rV|| j| t| dd d S )Nr,   r/   Fc                 S   s    i | ]\}}t |ts||qS r5   )rt   r   rx   r5   r5   r8   r|     r}   z._dataclass_validate_values.<locals>.<dictcomp>r<   T)	rq   r   r   r   r-   r   updaterH   rn   )r7   Z
input_datad_Zvalidation_errorr5   r5   r8   r     s    
r   )r7   rp   rl   r3   c                 C   sl   | j rZt| j}||d  | jj|d }|rZ|j|||| jd\}}|rZt	|g| jt
| || d S )N)locr;   )r,   r   r   popr-   Z
__fields__r   validater   r   rH   rn   )r7   rp   rl   r   Zknown_fieldZerror_r5   r5   r8   r     s    
r   c                    s    fddt  D S )Nc                    s4   h | ],}|t  d i vr|dr,|ds|qS )r'   __)rq   
startswithendswith)ry   xr<   r5   r8   	<setcomp>  s   $z!_extra_dc_args.<locals>.<setcomp>)dirr<   r5   r<   r8   rb     s    
rb   )r^   r3   c                 C   s:   ddl }|| o8t| d o8t| jtt| di S )a  
    Whether a class is a stdlib dataclass
    (useful to discriminated a pydantic dataclass that is actually a wrapper around a stdlib dataclass)

    we check that
    - `_cls` is a dataclass
    - `_cls` is not a processed pydantic dataclass (with a basemodel attached)
    - `_cls` is not a pydantic dataclass inheriting directly from a stdlib dataclass
    e.g.
    ```
    @dataclasses.dataclass
    class A:
        x: int

    @pydantic.dataclasses.dataclass
    class B(A):
        y: int
    ```
    In this case, when we first check `B`, we make an extra check and look at the annotations ('y'),
    which won't be a superset of all the dataclass fields (only the stdlib fields i.e. 'x')
    r   Nr-   rF   )ra   is_dataclassr   setr'   
issupersetrq   )r^   ra   r5   r5   r8   rM     s    

rM   )ri   rZ   r3   c                 c   s   t t| |ddE dH  dS )z
    Create a pydantic.dataclass from a builtin dataclass to add type validation
    and yield the validators
    It retrieves the parameters of the dataclass and forwards them to the newly created dataclass
    F)rZ   r[   N)r   rJ   )ri   rZ   r5   r5   r8   rN     s    rN   )N)Brd   re   
contextlibr   	functoolsr   typingr   r   r   r   r   r	   r
   r   r   r   r   r   Ztyping_extensionsr   Zclass_validatorsr   rZ   r   r   r   r   Zerror_wrappersr   errorsr   r   r   r   r   r   mainr   r   utilsr   r    r!   r"   r#   r]   r$   __all__rO   rf   rG   rH   rJ   rK   r&   rE   rg   r   r   rL   r   r   rb   rM   rN   r5   r5   r5   r8   <module>   s@  !8 
:&	T)