a c E@srdZddlZddlZddlmZddlmZddlmZm Z m Z m Z m Z m Z mZmZmZmZmZddlmZddlmZdd lmZmZmZmZdd lmZdd lmZdd l m!Z!m"Z"m#Z#m$Z$dd l%m&Z&m'Z'ddl(m)Z)er(ddl%m*Z*ddlm+Z+m,Z,edddZ-eeddfZ.GdddZ/gdZ0edZ1ej2dkr"ede!e"fdeddddddddddd e3e3e3e3e3e3eeee4dfee3ee3e3e ee1gdfd d d!Z5ede!e"fdeddddddddddd ee1e3e3e3e3e3e3eeee4dfee3ee3e3dd" d#d!Z5nede!e"fdedddddddddd$ e3e3e3e3e3e3eeee4dfee3ee3e ee1gdfd% d&d!Z5ede!e"fdedddddddddd$ ee1e3e3e3e3e3e3eeee4dfee3ee3dd' d(d!Z5ede!e"fddHddddddddddd eee1e3e3e3e3e3e3eeee4dfee3ee3e3ee ee1gdfdfd" d)d!Z5eede3e edddfd*d+d,Z6Gd-ddZ7edeee3e8dd.d/d0Z9dd1d2d3d4Z:ede dd5d6d7Z;edfedee ee8ed8d9d:d;ZZ=de8e dd?d@dAZ>ee e3dBdCdDZ?edeed1dEdFdGZ@dS)IaX 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_CHECKINGAnyCallableClassVarDict GeneratorOptionalTypeTypeVarUnionoverload)dataclass_transform)gather_all_validators) BaseConfig ConfigDictExtra get_config)ValidationError)DataclassTypeError)Field FieldInfoRequired Undefined) create_modelvalidate_model)ClassAttribute) BaseModel)CallableGeneratorNoArgAnyCallable DataclassT Dataclass)boundDataclassProxyc@seZdZUeeeefed<eeed<eeded<ee ed<eeded<ee ed<ee e ed<eedgd fed <ee ed <e e d d d dZ ee dddddZee deddddZd 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__argskwargsreturncOsdSNselfr0r1r4r4a/workspaces/shunt/resources/test-fastapi/venv/lib/python3.9/site-packages/pydantic/dataclasses.py__init__HszDataclass.__init__r clsr2cCsdSr3r4r:r4r4r7__get_validators__KszDataclass.__get_validators__r"r:vr2cCsdSr3r4r:r>r4r4r7 __validate__OszDataclass.__validate__)__name__ __module__ __qualname__rrstrr__annotations__rboolr robjectr8 classmethodr<r@r4r4r4r7r#:s     ) dataclassset_validation$create_pydantic_model_from_dataclassis_builtin_dataclassmake_dataclass_validator_T T)Zkw_only_defaultZfield_specifiersF. initrepreqorder unsafe_hashfrozenconfigvalidate_on_init use_proxykw_onlyDataclassClassOrWrapper) rSrTrUrVrWrXrYrZr[r\r2c CsdSr3r4rRr4r4r7rI`srI) _clsrSrTrUrVrWrXrYrZr[r\r2c CsdSr3r4) r^rSrTrUrVrWrXrYrZr[r\r4r4r7rIqs rSrTrUrVrWrXrYrZr[) rSrTrUrVrWrXrYrZr[r2c CsdSr3r4r_r4r4r7rIs) r^rSrTrUrVrWrXrYrZr[r2c CsdSr3r4) r^rSrTrUrVrWrXrYrZr[r4r4r7rIsc sFt|ttdd f dd } |dur>| 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]r9c sddl}durn2t|oF|jdtupFtt|tt|jdk}|r^d}t|}d}nL|jpfd}tj dkr|j |d}n|j |d}d} dur|n }t ||||j j fi|j|i|S)NrFrO)rSrTrUrVrWrXr\)rSrTrUrVrWrXT) dataclassesrL __bases__rGsetdirr%__doc__sys version_inforI#_add_pydantic_validation_attributesr,Z__try_update_forward_refs__rA)r:raZshould_use_proxy dc_cls_docdc_clsZdefault_validate_on_initZshould_validate_on_init rUrXrSr\rVrTZ the_configrWr[rZr4r7wraps<*   zdataclass..wrapN)rr r) r^rSrTrUrVrWrXrYrZr[r\rlr4rkr7rIs *')r:valuer2ccs*|j}z||_|VW||_n||_0dSr3)r))r:rmZoriginal_run_validationr4r4r7rJs rJc@seZdZdZedddddZeeeddd Zeed d d Z eedd ddZ ee dddZ ddddZ eddddZdS)r% __dataclass__r#N)rjr2cCst|d|dS)Nrn)rG __setattr__)r6rjr4r4r7r8szDataclassProxy.__init__r/cOs@t|jd |j|i|WdS1s20YdS)NT)rJrnr5r4r4r7__call__szDataclassProxy.__call__)namer2cCs t|j|Sr3)getattrrn)r6rqr4r4r7 __getattr__szDataclassProxy.__getattr__)_DataclassProxy__name_DataclassProxy__valuer2cCst|j||Sr3)setattrrn)r6rtrur4r4r7roszDataclassProxy.__setattr__)instancer2cCs t||jSr3) isinstancern)r6rwr4r4r7__instancecheck__sz DataclassProxy.__instancecheck__)r2cCstt|jSr3)r%copyrnr6r4r4r7__copy__szDataclassProxy.__copy__)memor2cCstt|j|Sr3)r%rzdeepcopyrn)r6r}r4r4r7 __deepcopy__ szDataclassProxy.__deepcopy__)rArBrC __slots__r r8rrprDrsrorFryr|rr4r4r4r7r%s)rjrYrZrir2csD|jtdttddfdd t|drz |jjWntyV|jYn0tdttddfdd }t|d t|d|n,tdttddfd d }t|d |t|d td |t|d dt|dt ||t|dt t|dt t t|dt t |jjjr@|jjs@t|dtdS)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)r6r0r1r2csjtjkr6g|Rifdd|Dnljtjkr|D]\}}j||qJg|Rifdd|Dng|Ri|dS)Ncs i|]\}}|jvr||qSr4r&.0kr>r{r4r7 zR_add_pydantic_validation_attributes..handle_extra_init..cs i|]\}}|jvr||qSr4rrr{r4r7r$r)extrarignoreitemsZallow__dict__ setdefault)r6r0r1rr>)rYrSr{r7handle_extra_inits * *z>_add_pydantic_validation_attributes..handle_extra_initr(csnjdkr |g|Ri||jjrJ|t|drJ|j|i|jdkrj|g|Ri|dS)NZbefore_validationr*Zafter_validation)Zpost_init_call __class__r)r-hasattrr*r5)rY post_initr4r7 new_post_init/s   z:_add_pydantic_validation_attributes..new_post_initr8c s|g|Ri||jjr&|t|drddl}i}t|jjD]P\}}|j|j urLz||||j <WqLt y| |j |j ||j <YqL0qL|jfi|dS)Nr*r)rr)r-rra enumerater&valuesZ _field_typeZ_FIELD_INITVARrq IndexErrorgetdefaultr*)r6r0r1raZinitvars_and_valuesif)rr4r7new_initAs   z5_add_pydantic_validation_attributes..new_initr)r+Fr,r-r@r<ro)r8rrrr( __wrapped__AttributeErrorrvrrK_dataclass_validate_valuesrH_validate_dataclass_get_validatorsr, __config__Zvalidate_assignmentr'rX&_dataclass_validate_assignment_setattr)rjrYrZrirrr4)rYrrSrr7rhs.         rhr r9ccs |jVdSr3)r@r;r4r4r7rfsrr=cCst|dt||r0||WdSt|ttfrT||WdSt|trz|fi|WdSt|jdWdn1s0YdS)NT) class_name)rJrxr-listtupledictrrAr?r4r4r7rjs   rr)rjrYrir2c Csddl}i}||D]t}t}d}|j|jur6|j}n|j|jurJ|j}nt}t|trd|}d|_ nt f||d|j }|j |f||j <qt|} t|jf||j| ddid|} |dur|n|jpd| _| S)NrT)rdefault_factoryZ__resolve_forward_refs__F)rrBZ__validators__Z__cls_kwargs__r`)rafieldsrrMISSINGrrrxrr.rmetadatatyperqrrrArBre) rjrYriraZfield_definitionsfieldrrZ field_infoZ validatorsmodelr4r4r7rKws8   rK)r6r2cCstt|drdSt|ddr0dd|jD}n|j}t|j||jd\}}}|rV||j|t|dddS)Nr+r.FcSs i|]\}}t|ts||qSr4)rxrrr4r4r7rrz._dataclass_validate_values..r;T) rrrrrr,rupdaterGro)r6Z input_datad_Zvalidation_errorr4r4r7rs   r)r6rqrmr2cCsl|jrZt|j}||d|jj|d}|rZ|j||||jd\}}|rZt |g|jt |||dS)N)locr:) r+rrpopr,Z __fields__rvalidaterrrGro)r6rqrmrZ known_fieldZerror_r4r4r7rs  r)r^r2cCs:ddl}||o8t|d o8t|jtt|diS)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') rNr,rE)raZ is_dataclassrrcr& issupersetrr)r^rar4r4r7rLs   rL)rjrYr2ccstt||ddEdHdS)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)rYr[N)rrI)rjrYr4r4r7rMsrM)N)Arerzrf contextlibr functoolsrtypingrrrrrr r r r r rZtyping_extensionsrZclass_validatorsrrYrrrrZerror_wrappersrerrorsrrrrrrmainrrutilsrrr r!r"r]r#__all__rNrgrFrGrIrJr%rDrhrrrKrrrLrMr4r4r4r7sT!  4         C&  W )