U
    nË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-zvl9l234/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©é   é
   )Zfield_specifiersTF.©
ÚinitÚreprÚeqÚorderÚunsafe_hashÚfrozenÚconfigÚvalidate_on_initÚ	use_proxyÚkw_onlyÚDataclassClassOrWrapper)rS   rT   rU   rV   rW   rX   rY   rZ   r[   r\   r2   c        
   
      C   s   d S r3   r4   rR   r4   r4   r7   rI   h   s    )Ú_clsrS   rT   rU   rV   rW   rX   rY   rZ   r[   r\   r2   c       
         C   s   d S r3   r4   )r^   rS   rT   rU   rV   rW   rX   rY   rZ   r[   r\   r4   r4   r7   rI   y   s    ©	rS   rT   rU   rV   rW   rX   rY   rZ   r[   )
rS   rT   rU   rV   rW   rX   rY   rZ   r[   r2   c        	   	      C   s   d S r3   r4   r_   r4   r4   r7   rI   �   s    )r^   rS   rT   rU   rV   rW   rX   rY   rZ   r[   r2   c       	   
      C   s   d S r3   r4   )
r^   rS   rT   rU   rV   rW   rX   rY   rZ   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   )rS   rT   rU   rV   rW   rX   r\   )rS   rT   rU   rV   rW   rX   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©
rU   rX   rS   r\   rV   rT   Z
the_configrW   r[   rZ   r4   r7   ÚwrapÆ   sF    ÿ*û

ø      ÿzdataclass.<locals>.wrapN)r   r   r   )r^   rS   rT   rU   rV   rW   rX   rY   rZ   r[   r\   rl   r4   rk   r7   rI   ¯   s
    *%)r:   Úvaluer2   c                 c   s$   | j }z|| _ | V  W 5 || _ X d S r3   )r)   )r:   rm   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)rj   r2   c                 C   s   t  | d|¡ d S )Nrn   )rG   Ú__setattr__)r6   rj   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   rn   r5   r4   r4   r7   Ú__call__  s    zDataclassProxy.__call__)Únamer2   c                 C   s   t | j|ƒS r3   )Úgetattrrn   )r6   rq   r4   r4   r7   Ú__getattr__  s    zDataclassProxy.__getattr__)Ú_DataclassProxy__nameÚ_DataclassProxy__valuer2   c                 C   s   t | j||ƒS r3   )Úsetattrrn   )r6   rt   ru   r4   r4   r7   ro     s    zDataclassProxy.__setattr__)Úinstancer2   c                 C   s   t || jƒS r3   )Ú
isinstancern   )r6   rw   r4   r4   r7   Ú__instancecheck__  s    z DataclassProxy.__instancecheck__)r2   c                 C   s   t t | j¡ƒS r3   )r%   Úcopyrn   ©r6   r4   r4   r7   Ú__copy__  s    zDataclassProxy.__copy__)Úmemor2   c                 C   s   t t | j|¡ƒS r3   )r%   rz   Údeepcopyrn   )r6   r}   r4   r4   r7   Ú__deepcopy__  s    zDataclassProxy.__deepcopy__)rA   rB   rC   Ú	__slots__r   r8   r   rp   rD   rs   ro   rF   ry   r|   r   r4   r4   r4   r7   r%   û   s   )rj   rY   rZ   ri   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>   )rY   rS   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   )rY   Ú	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&   ÚvaluesZ_field_typerg   Z_FIELD_INITVARrq   Ú
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<   ro   )r8   r   r   r�   r(   Ú__wrapped__ÚAttributeErrorrv   r   rK   Ú_dataclass_validate_valuesrH   Ú_validate_dataclassÚ_get_validatorsr,   Ú
__config__Zvalidate_assignmentr'   rX   Ú&_dataclass_validate_assignment_setattr)rj   rY   rZ   ri   r�   r—   r4   )rY   r‹   rS   rŽ   r7   rh     s.    
rh   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   rx   r-   ÚlistÚtupleÚdictr   rA   r?   r4   r4   r7   r›   o  s    

r›   r   )rj   rY   ri   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__r`   )rg   Úfieldsr   r”   ÚMISSINGr£   r   rx   r   r.   r   ÚmetadataÚtyperq   r   r   rA   rB   rd   )
rj   rY   ri   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   )rx   rr   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   )rx   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)	rr   r‰   rˆ   r   r,   rŒ   ÚupdaterG   ro   )r6   Z
input_dataÚdÚ_Zvalidation_errorr4   r{   r7   rš   ®  s    

þrš   )r6   rq   rm   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   ro   )r6   rq   rm   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   )rg   Zis_dataclassr�   rb   r&   Ú
issupersetrr   )r^   r4   r4   r7   rL   Ñ  s
    

ÿý)rj   rY   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)rY   r[   N)rœ   rI   )rj   rY   r4   r4   r7   rM   î  s    )N)Grd   rz   rg   re   Ú
contextlibr   Ú	functoolsr   r   ÚImportErrorÚtypingr   r   r   r   r	   r
   r   r   r   r   r   Z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   rf   r¨   rF   rG   rI   rJ   r%   rD   rh   rœ   r›   rK   r­   rš   rž   rL   rM   r4   r4   r4   r7   Ú<module>   sn  !4ûõôôóöõõô ÿô
óA&	ûVýü'