U
    ¶ÜŸjüF  ã                   @   sØ  d Z ddlZddlZddlZddlmZ ddlmZ zddlmZ W n e	k
rX   Y nX 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 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�rVddl(m-Z- ddl.m/Z/m0Z0 eddd�Z1eed df Z2G dd„ dƒZ3dddddgZ4edƒZ5ej6dk�rVeej7e$fd�edddddddddd d!œ
e8e8e8e8e8e8eeee9 df ee8 ee8 e8eee5 gd"f d#œd$d„ƒƒZ:eej7e$fd�edddddddddd d!œ
ee5 e8e8e8e8e8e8eeee9 df ee8 ee8 e8d"d%œd&d„ƒƒZ:nÔeej7e$fd�edddddddddd'œ	e8e8e8e8e8e8eeee9 df ee8 ee8 eee5 gd"f d(œ
d)d„ƒƒZ:eej7e$fd�edddddddddd'œ	ee5 e8e8e8e8e8e8eeee9 df ee8 ee8 d"d*œd+d„ƒƒZ:eej7e$fd�dLddddddddddd!œ
eee5  e8e8e8e8e8e8eeee9 df ee8 ee8 e8eeee5 gd"f d"f d%œd,d„ƒZ:eed e8eed ddf d-œd.d„ƒZ;G d/d„ dƒZ<ed ee e8e=dd0œd1d2„Z>d"d3d4œd5d6„Z?ed edd7œd8d9„Z@edfed ee ee= ed: d;œd<d„ZAej6d=k�rpde=e8d>œd?d@„ZBnde=e8d>œdAd@„ZBdddBœdCdD„ZCde=eddEœdFdG„ZDee e8dHœdId„ZEed ee d3dJœdKd„ZFdS )MaX  
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)Úcached_property)ÚTYPE_CHECKINGÚAnyÚCallableÚClassVarÚDictÚ	GeneratorÚOptionalÚ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© ©Úselfr0   r1   r4   r4   ú;/tmp/pip-unpacked-wheel-3sxb4rlg/pydantic/v1/dataclasses.pyÚ__init__P   s    zDataclass.__init__r    ©Úclsr2   c                 C   s   d S r3   r4   ©r:   r4   r4   r7   Ú__get_validators__S   s    zDataclass.__get_validators__r"   ©r:   Úvr2   c                 C   s   d S r3   r4   ©r:   r>   r4   r4   r7   Ú__validate__W   s    zDataclass.__validate__)Ú__name__Ú
__module__Ú__qualname__r   r	   Ústrr   Ú__annotations__r   Úboolr   r   Úobjectr8   Úclassmethodr<   r@   r4   r4   r4   r7   r#   B   s   
Ú	dataclassÚset_validationÚ$create_pydantic_model_from_dataclassÚis_builtin_dataclassÚmake_dataclass_validatorÚ_T©é   é
   )Úfield_specifiersTF.©
ÚinitÚreprÚeqÚorderÚunsafe_hashÚfrozenÚconfigÚvalidate_on_initÚ	use_proxyÚkw_onlyÚDataclassClassOrWrapper)rT   rU   rV   rW   rX   rY   rZ   r[   r\   r]   r2   c        
   
      C   s   d S r3   r4   rS   r4   r4   r7   rI   h   s    )Ú_clsrT   rU   rV   rW   rX   rY   rZ   r[   r\   r]   r2   c       
         C   s   d S r3   r4   )r_   rT   rU   rV   rW   rX   rY   rZ   r[   r\   r]   r4   r4   r7   rI   y   s    ©	rT   rU   rV   rW   rX   rY   rZ   r[   r\   )
rT   rU   rV   rW   rX   rY   rZ   r[   r\   r2   c        	   	      C   s   d S r3   r4   r`   r4   r4   r7   rI   �   s    )r_   rT   rU   rV   rW   rX   rY   rZ   r[   r\   r2   c       	   
      C   s   d S r3   r4   )
r_   rT   rU   rV   rW   rX   rY   rZ   r[   r\   r4   r4   r7   rI   �   s    c       
            sF   t |ƒ‰tt ddœ‡ ‡‡‡‡‡‡‡‡‡	f
dd„}| dk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^   r9   c              
      sØ   ˆd k	rˆn2t | ƒo>| jd tkp>tt| ƒƒtt| jd ƒƒk}|rVd}t| ƒ}d}nL| jp^d}tjdkr†t	j
| ˆˆˆ ˆˆˆˆd�}nt	j
| ˆˆˆ ˆˆˆd�}d}ˆ	d kr®|nˆ	}t| ˆ||ƒ |jjf | j| iŽ |S )Nr   Ú FrO   )rT   rU   rV   rW   rX   rY   r]   )rT   rU   rV   rW   rX   rY   T)rL   Ú	__bases__rG   ÚsetÚdirr%   Ú__doc__ÚsysÚversion_infoÚdataclassesrI   Ú#_add_pydantic_validation_attributesr,   Z__try_update_forward_refs__rA   )r:   Zshould_use_proxyÚ
dc_cls_docÚdc_clsZdefault_validate_on_initZshould_validate_on_init©
rV   rY   rT   r]   rW   rU   Z
the_configrX   r\   r[   r4   r7   ÚwrapÆ   sF    ÿ*û

ø      ÿzdataclass.<locals>.wrapN)r   r   r   )r_   rT   rU   rV   rW   rX   rY   rZ   r[   r\   r]   rm   r4   rl   r7   rI   ¯   s
    *%)r:   Úvaluer2   c                 c   s$   | j }z|| _ | V  W 5 || _ X d S r3   )r)   )r:   rn   Zoriginal_run_validationr4   r4   r7   rJ   ñ   s
    
c                   @   s†   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d„Z
eedœdd„Zd dœdd„Zed dœdd„ZdS )r%   Ú__dataclass__r#   N)rk   r2   c                 C   s   t  | d|¡ d S )Nro   )rG   Ú__setattr__)r6   rk   r4   r4   r7   r8   þ   s    zDataclassProxy.__init__r/   c              
   O   s0   t | jdƒ� | j||ŽW  5 Q R £ S Q R X d S )NT)rJ   ro   r5   r4   r4   r7   Ú__call__  s    zDataclassProxy.__call__)Únamer2   c                 C   s   t | j|ƒS r3   )Úgetattrro   )r6   rr   r4   r4   r7   Ú__getattr__  s    zDataclassProxy.__getattr__)Ú_DataclassProxy__nameÚ_DataclassProxy__valuer2   c                 C   s   t | j||ƒS r3   )Úsetattrro   )r6   ru   rv   r4   r4   r7   rp     s    zDataclassProxy.__setattr__)Úinstancer2   c                 C   s   t || jƒS r3   )Ú
isinstancero   )r6   rx   r4   r4   r7   Ú__instancecheck__  s    z DataclassProxy.__instancecheck__)r2   c                 C   s   t t | j¡ƒS r3   )r%   Úcopyro   ©r6   r4   r4   r7   Ú__copy__  s    zDataclassProxy.__copy__)Úmemor2   c                 C   s   t t | j|¡ƒS r3   )r%   r{   Údeepcopyro   )r6   r~   r4   r4   r7   Ú__deepcopy__  s    zDataclassProxy.__deepcopy__)rA   rB   rC   Ú	__slots__r   r8   r   rq   rD   rt   rp   rF   rz   r}   r€   r4   r4   r4   r7   r%   û   s   )rk   rZ   r[   rj   r2   c                    sF  | j ‰tˆƒdttddœ‡ ‡fdd„ƒ‰t| dƒr–z| jj‰W n tk
rX   | j‰Y nX 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�rB| jj�sBt| 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)r6   r0   r1   r2   c                    s”   ˆj tjkr0ˆˆ f|ž‡ fdd„| ¡ D ƒŽ n`ˆj tjkr€| ¡ D ]\}}ˆ j ||¡ qDˆˆ f|ž‡ fdd„| ¡ D ƒŽ nˆˆ f|ž|Ž d S )Nc                    s    i | ]\}}|ˆ j kr||“qS r4   ©r&   ©Ú.0Úkr>   r|   r4   r7   Ú
<dictcomp>%  s     
  zR_add_pydantic_validation_attributes.<locals>.handle_extra_init.<locals>.<dictcomp>c                    s    i | ]\}}|ˆ j kr||“qS r4   r‚   rƒ   r|   r4   r7   r†   *  s     
  )Úextrar   ÚignoreÚitemsZallowÚ__dict__Ú
setdefault)r6   r0   r1   r…   r>   )rZ   rT   r|   r7   Úhandle_extra_init"  s    $$z>_add_pydantic_validation_attributes.<locals>.handle_extra_initr(   c                    s^   ˆ j dkrˆ| f|ž|Ž | jjr@|  ¡  t| dƒr@| j||Ž ˆ j dkrZˆ| f|ž|Ž d S )NZbefore_validationr*   Zafter_validation)Zpost_init_callÚ	__class__r)   r-   Úhasattrr*   r5   )rZ   Ú	post_initr4   r7   Únew_post_init5  s    


z:_add_pydantic_validation_attributes.<locals>.new_post_initr8   c              	      s¢   ˆ | f|ž|Ž | j jr |  ¡  t| dƒrži }t| j j ¡ ƒD ]R\}}|jtj	kr>z|| ||j
< W q> tk
rŽ   | |j
|j¡||j
< Y q>X q>| jf |Ž d S )Nr*   )r�   r)   r-   rŽ   Ú	enumerater&   ÚvaluesÚ_field_typerh   Ú_FIELD_INITVARrr   Ú
IndexErrorÚgetÚdefaultr*   )r6   r0   r1   Zinitvars_and_valuesÚiÚf)rŒ   r4   r7   Únew_initG  s    
z5_add_pydantic_validation_attributes.<locals>.new_initr)   r+   Fr,   r-   r@   r<   rp   )r8   r   r   rŽ   r(   Ú__wrapped__ÚAttributeErrorrw   r   rK   Ú_dataclass_validate_valuesrH   Ú_validate_dataclassÚ_get_validatorsr,   Ú
__config__Zvalidate_assignmentr'   rY   Ú&_dataclass_validate_assignment_setattr)rk   rZ   r[   rj   r�   rš   r4   )rZ   rŒ   rT   r�   r7   ri     s.    
ri   r    r9   c                 c   s   | j V  d S r3   )r@   r;   r4   r4   r7   rŸ   k  s    rŸ   r=   c              
   C   sŠ   t | dƒ�v t|| ƒr.| ¡  |W  5 Q R £ S t|ttfƒrP| |Ž W  5 Q R £ S t|tƒrp| f |ŽW  5 Q R £ S t| jd�‚W 5 Q R X d S )NT)Ú
class_name)rJ   ry   r-   ÚlistÚtupleÚdictr   rA   r?   r4   r4   r7   rž   o  s    

rž   r   )rk   rZ   rj   r2   c           
      C   sÊ   i }t  | ¡D ]t}t}d }|jt jk	r.|j}n|jt jk	rB|j}nt}t|tƒr\|}d| _	nt
f ||dœ|j—Ž}|j|f||j< qt| ƒ}t| jf|| j|ddidœ|—Ž}	|d k	rº|n| jpÂd|	_|	S )NT)r—   Údefault_factoryZ__resolve_forward_refs__F)r    rB   Z__validators__Z__cls_kwargs__ra   )rh   Úfieldsr   r—   ÚMISSINGr¦   r   ry   r   r.   r   ÚmetadataÚtyperr   r   r   rA   rB   re   )
rk   rZ   rj   Zfield_definitionsÚfieldr—   r¦   Z
field_infoZ
validatorsÚmodelr4   r4   r7   rK   |  s6    
ÿûú)rP   é   )Úobjr…   r2   c                 C   s   t tt| ƒ|d ƒtƒS r3   )ry   rs   rª   r   ©r®   r…   r4   r4   r7   Ú_is_field_cached_property¥  s    r°   c                 C   s   dS )NFr4   r¯   r4   r4   r7   r°   ª  s    )r6   r2   c                    sŠ   t ˆ dƒrd S t ˆ ddƒr4‡ fdd„ˆ j ¡ D ƒ}n‡ fdd„ˆ j ¡ D ƒ}tˆ j|ˆ jd�\}}}|rl|‚ˆ j |¡ t ˆ dd¡ d S )	Nr+   r.   Fc                    s*   i | ]"\}}t |tƒstˆ |ƒs||“qS r4   )ry   r   r°   rƒ   r|   r4   r7   r†   ¶  s
   
 
þ z._dataclass_validate_values.<locals>.<dictcomp>c                    s    i | ]\}}t ˆ |ƒs||“qS r4   )r°   rƒ   r|   r4   r7   r†   ¼  s     
  r;   T)	rs   rŠ   r‰   r   r,   r�   ÚupdaterG   rp   )r6   Z
input_dataÚdÚ_Zvalidation_errorr4   r|   r7   r�   ®  s    

þr�   )r6   rr   rn   r2   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   rG   rp   )r6   rr   rn   r²   Zknown_fieldZerror_r4   r4   r7   r¡   Ä  s    
r¡   )r_   r2   c                 C   s2   t  | ¡o0t| dƒ o0t| 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,   rE   )rh   Úis_dataclassrŽ   rc   r&   Ú
issupersetrs   )r_   r4   r4   r7   rL   Ñ  s
    

ÿý)rk   rZ   r2   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
    T)rZ   r\   N)rŸ   rI   )rk   rZ   r4   r4   r7   rM   î  s    )N)Gre   r{   rh   rf   Ú
contextlibr   Ú	functoolsr   r   ÚImportErrorÚtypingr   r   r   r   r	   r
   r   r   r   r   r   Útyping_extensionsr   Zpydantic.v1.class_validatorsr   Zpydantic.v1.configr   r   r   r   Zpydantic.v1.error_wrappersr   Zpydantic.v1.errorsr   Zpydantic.v1.fieldsr   r   r   r   Zpydantic.v1.mainr   r   Zpydantic.v1.utilsr   r   Zpydantic.v1.typingr    r!   r"   r^   r#   Ú__all__rN   rg   r«   rF   rG   rI   rJ   r%   rD   ri   rŸ   rž   rK   r°   r�   r¡   rL   rM   r4   r4   r4   r7   Ú<module>   sn  !4ûõôôóöõõô ÿô
óA&	ûVýü'