U nf@szUddlZddlZddlmZddlmZddlmZmZmZm Z ddl m Z ddl m Z ddlmZmZmZmZmZmZddlmZdd lmZmZmZmZmZmZmZmZm Z m!Z!m"Z"m#Z#m$Z$m%Z%m&Z&m'Z'm(Z(m)Z)dd l*m+Z+dd l,m-Z-m.Z.dd l/m0Z0m1Z1m2Z2m3Z3m4Z4m5Z5m6Z6m7Z7m8Z8m9Z9m:Z:m;Z;mZ>ddl?m@Z@mAZAddlBmCZCmDZDmEZEmFZFmGZGmHZHmIZImJZJmKZKmLZLmMZMmNZNmOZOmPZPmQZQmRZRmSZSmTZTmUZUddlVmWZWmXZXmYZYmZZZm[Z[m\Z\m]Z]m^Z^m_Z_ddl`maZambZbmcZcerddldmeZeddlfmgZgdZhdZie(e&de&e fZje$ejZkede!e<eelefddddZmddddeide#e(e&de&dfene!ele!ele!eleleelefddd Zoddeife(e&de&dfene!eleleelefd!d"d#Zpde<e|| d<|D]6} t| ||||d\} } }| | || }| | |<qB| r| | d<| S)a Process a list of models and generate a single JSON Schema with all of them defined in the ``definitions`` top-level JSON key, including their sub-models. :param models: a list of models to include in the generated JSON Schema :param by_alias: generate the schemas using the aliases defined, if any :param title: title for the generated schema that includes the definitions :param description: description for the generated schema :param ref_prefix: the JSON Pointer prefix for schema references with ``$ref``, if None, will be set to the default of ``#/definitions/``. Update it if you want the schemas to reference the definitions somewhere else, e.g. for OpenAPI use ``#/components/schemas/``. The resulting generated schemas will still be at the top-level key ``definitions``, so you can extract them from there. But all the references will have the set prefix. :param ref_template: Use a ``string.format()`` template for ``$ref`` instead of a prefix. This can be useful for references that cannot be represented by ``ref_prefix`` such as a definition stored in another file. For a sibling json file in a ``/schemas`` directory use ``"/schemas/${model}.json#"``. :return: dict with the JSON Schema with a ``definitions`` top-level key including the schema definitions for the models and sub-models passed in ``models``. cSsg|] }t|qSre)rS).0modelrererf szschema..rirjrhmodel_name_maprkrl definitions)get_flat_models_from_modelsget_model_name_mapmodel_process_schemaupdate)rmrhrirjrkrlZ clean_models flat_modelsrrrsZ output_schemarom_schema m_definitionsZm_nested_models model_namerererfschemams.   r|)rorhrkrlr[c Cslt|}t|}t|}||}t|||||d\}}} || krV|||<t|||d}|rh|d|i|S)aa Generate a JSON Schema for one model. With all the sub-models defined in the ``definitions`` top-level JSON key. :param model: a Pydantic model (a class that inherits from BaseModel) :param by_alias: generate the schemas using the aliases defined, if any :param ref_prefix: the JSON Pointer prefix for schema references with ``$ref``, if None, will be set to the default of ``#/definitions/``. Update it if you want the schemas to reference the definitions somewhere else, e.g. for OpenAPI use ``#/components/schemas/``. The resulting generated schemas will still be at the top-level key ``definitions``, so you can extract them from there. But all the references will have the set prefix. :param ref_template: Use a ``string.format()`` template for ``$ref`` instead of a prefix. This can be useful for references that cannot be represented by ``ref_prefix`` such as a definition stored in another file. For a sibling json file in a ``/schemas`` directory use ``"/schemas/${model}.json#"``. :return: dict with the JSON Schema for the passed ``model`` rqFrs)rSget_flat_models_from_modelrurvget_schema_refrw) rorhrkrlrxrrr{ryrz nested_modelsrererf model_schemas" rF)rYschema_overridesr[cCsi}|jjst|jts6|jjp0|jdd|d<|jjrBd}|jjrZ|jj|d<d}|js|j dk rt |j st |j |d<d}||fS)N_ riTrjdefault) field_inforirTtype_r aliasreplacerjrequiredrrM outer_type_encode_default)rYrschema_rererfget_field_info_schemas r)rhrkrl known_models)rYrhrrrkrlrr[c Csrt|\}}t|}|r&||d}t|||||||p|||<q>t|jt rt |jt stD]*\}}}t |j|d}t ||r|||<q|jdk r|jjr|j|d<|jjr||jjt |jdd}|rt||||S)z Get the JSON Schema validation keywords for a ``field`` with an annotation of a Pydantic ``FieldInfo`` with validation arguments. Nconst__modify_schema__)rTrr rextrarwstrbytesrgetattr isinstance numeric_types issubclassboolrrrrrg)rYr attr_nametkeywordattrrXrererfr!s.       r) unique_modelsr[cCsi}t}|D]f}t|j}||kr6t|}|||<q||krl||||}||t|<||t|<q|||<qdd|DS)a Process a set of models and generate unique names for them to be used as keys in the JSON Schema definitions. By default the names are the same as the class name. But if two models in different Python modules have the same name (e.g. "users.Model" and "items.Model"), the generated names will be based on the Python module path for those conflicting models to prevent name collisions. :param unique_models: a Python set of models :return: dict mapping models to names cSsi|]\}}||qSrerernkvrererf Zsz&get_model_name_map..)r`normalize_name__name__get_long_model_nameaddpopitems)rZname_model_mapZconflicting_namesror{Zconflicting_modelrererfruBs       ru)rorr[cCsJ|pt}t}||||O}ttt|j}|t||dO}|S)a? Take a single ``model`` and generate a set with itself and all the sub-models in the tree. I.e. if you pass model ``Foo`` (subclass of Pydantic ``BaseModel``) as ``model``, and it has a field of type ``Bar`` (also subclass of ``BaseModel``) and that model ``Bar`` has a field of type ``Baz`` (also subclass of ``BaseModel``), the return value will be ``set([Foo, Bar, Baz])``. :param model: a Pydantic ``BaseModel`` subclass :param known_models: used to solve circular references :return: a set with the initial model and all its sub-models r)r`rr"rr2 __fields__valuesget_flat_models_from_fields)rorrxfieldsrererfr}]s  r})rYrr[cCsddlm}t}|j}tt|dd|r0|j}|jrTt||sT|t|j|dO}n8t||rx||krx|t ||dO}nt|t r| ||S)a Take a single Pydantic ``ModelField`` (from a model) that could have been declared as a subclass of BaseModel (so, it could be a submodel), and generate a set with its model and all the sub-models in the tree. I.e. if you pass a field that was declared to be of type ``Foo`` (subclass of BaseModel) as ``field``, and that model ``Foo`` has a field of type ``Bar`` (also subclass of ``BaseModel``) and that model ``Bar`` has a field of type ``Baz`` (also subclass of ``BaseModel``), the return value will be ``set([Foo, Bar, Baz])``. :param field: a Pydantic ``ModelField`` :param known_models: used to solve circular references :return: a set with the model used in the declaration for this field, if any, and all its sub-models rrV__pydantic_model__Nr) pydantic.v1.mainrWr`rrTrr sub_fieldsrr}r r)rYrrWrx field_typerererfget_flat_models_from_fieldqs   r)rrr[cCs$t}|D]}|t||dO}q |S)a Take a list of Pydantic ``ModelField``s (from a model) that could have been declared as subclasses of ``BaseModel`` (so, any of them could be a submodel), and generate a set with their models and all the sub-models in the tree. I.e. if you pass a the fields of a model ``Foo`` (subclass of ``BaseModel``) as ``fields``, and on of them has a field of type ``Bar`` (also subclass of ``BaseModel``) and that model ``Bar`` has a field of type ``Baz`` (also subclass of ``BaseModel``), the return value will be ``set([Foo, Bar, Baz])``. :param fields: a list of Pydantic ``ModelField``s :param known_models: used to solve circular references :return: a set with any model declared in the fields, and all their sub-models r)r`r)rrrxrYrererfrs r)rmr[cCs t}|D]}|t|O}q |S)a_ Take a list of ``models`` and generate a set with them and all their sub-models in their trees. I.e. if you pass a list of two models, ``Foo`` and ``Bar``, both subclasses of Pydantic ``BaseModel`` as models, and ``Bar`` has a field of type ``Baz`` (also subclass of ``BaseModel``), the return value will be ``set([Foo, Bar, Baz])``. )r`r})rmrxrorererfrtsrt)ror[cCs|jd|jddS)N__.) __module__ __qualname__rrorererfrsr)rrk)rYrhrrrlrrkrr[c Csvddlm}i}t} |jtttttt t hkrt ||||||d\} } } | | | | d| d} |jtthkr|d| d<n|jt krdd i} tt|j}t|jd d }t ||||||d\} } } | | | | |rt|| i| d <| r| | d <n$|jtks(|jtkrt|j|sg}ttt|j}|D]>}t||||||d\}}}| || |||q@t|}|jtkr|dkr|dnd|d}d|gi} nd||d} |dkr&|| d<nJ|jtthkst|jt |||||||d\} } } | | | | |j|jkrl|jtkrH|j}n|j}t|dd }|rlt ||| | || fS)a  Used by ``field_schema()``, you probably should be using that function. Take a single ``field`` and generate the schema for its type only, not including additional information as title, etc. Also return additional schema definitions, from sub-models. rrVrhrrrkrlrarraytyperT uniqueItemsrobjectrNZpatternPropertiesadditionalPropertiesallOf)rminItemsmaxItemsrrr)!rrWr`shaper+r0r,r-r(r*r'field_singleton_schemarwr&r"r2 key_fieldrrr<Z _get_patternr/r)rrrrappendlenr.AssertionErrorrrg)rYrhrrrlrrkrrWrsrZ items_schemarrrrr sub_schemarsfZ sf_schemaZsf_definitionsZsf_nested_modelsZsub_fields_lenZall_of_schemasrrXrererfrs             &            r)rhrkrlrrY)rorhrrrkrlrrYr[cCsddlm}m}|pt}t|trJttt|}t||d} | itfSttd|}d|j j pf|j i} ||} | r~| | d<| |t ||||||d\} } } | | |j j}t|rt||jdkr|| q|| |n | || | | fS) au Used by ``model_schema()``, you probably should be using that function. Take a single ``model`` and generate its schema. Also return additional schema definitions, from sub-models. The sub-models of the returned schema will be referenced, but their definitions will not be included in the schema. All the definitions are returned as the second value. r)getdocr\r^rWrirjrr)r_rr\r`rTr r"renum_process_schema __config__rirrmodel_type_schemarw schema_extracallablerra)rorhrrrkrlrrYrr\rdocryrzrrrererfrv's8          rv)rk)rorhrrrlrkrr[c Cs(i}g}i}t} |jD]\} } zt| |||||d\} } }Wn8tk rz}zt|jtWYqW5d}~XYnX| | | ||r| || j <| j r| | j q| || <| j r| | qt |kr|t }|jjp|j|d<nd|d}|r||d<|jjdkrd|d <||| fS) a) You probably should be using ``model_schema()``, this function is indirectly used by that function. Take a single ``model`` and generate the schema for its type only, not including additional information as title, etc. Also return additional schema definitions, from sub-models. rNrir)r propertiesrZforbidFr)r`rrrZ SkipFieldwarningswarnmessage UserWarningrwrrrrRrrirr)rorhrrrlrkrrrrsrrfrrrskipZ out_schemarererfrYsF     rr^)enumrYr[cCs`ddl}|j||jpdddttt|Dd}t||t|dd}|r\t ||||S)z Take a single `enum` and generate its schema. This is similar to the `model_process_schema` function, but applies to ``Enum`` objects. rNzAn enumeration.cSsg|] }|jqSre)value)rnitemrererfrpsz'enum_process_schema..)rirjrr) r_rcleandoc__doc__r"rr add_field_type_to_schemarrg)rrYr_rrXrererfrs   rc sttt|j}i}t} t|dkr@t|d|||dSi} |jdk } | r |jdk sbt i} |j D]\} }t | t rt | j} tt|jrt|j}fdd|D| | <qp|j}t|dr|j}|}t|d}|d | | <qp|j| d | d <g}|D]x}t||||d\}}}|||rXd |krX|d d}|d d hkrt|d ||| |q|| | rd nd<| || fSdS)aA This function is indirectly used by ``field_schema()``, you probably should be using that function. Take a list of Pydantic ``ModelField`` from the declaration of a type with parameters, and generate their schema. I.e., fields used as "type parameters", like ``str`` and ``int`` in ``Tuple[str, int]``. rrrNcs$i|]}|t|dqS)F)r~)rnZ sub_modelrrrkrlrerfrsz5field_singleton_sub_fields_schema..rFr)Z propertyNamemappingZ discriminatorrZoneOfZanyOf)r"rr2rr`rrZdiscriminator_keyZsub_fields_mappingrrrr rrrQrKrrLhasattrrr~Zdiscriminator_aliasrwrbrr)rYrhrrrlrrkrrrsrrZfield_has_discriminatorZdiscriminator_models_refsZdiscriminator_valueZ sub_fieldZ sub_modelsZsub_field_typeZdiscriminator_model_nameZdiscriminator_model_refZsub_field_schemasrrsub_definitionssub_nested_modelsrerrf!field_singleton_sub_fields_schemasn             rstringpath)rformatz date-timerrnumberz time-deltaZ ipv4networkZ ipv6networkZ ipv4interfaceZ ipv6interfaceZipv4Zipv6rbinarybooleanintegeruuidrrr)rrrfield_class_to_schemaz json-string)rrr[cCsBtD]8\}}t||s.||kr*tkrnq||q>qdS)a Update the given `schema` with the type-specific metadata for the given `field_type`. This function looks through `field_class_to_schema` for a class that matches the given `field_type`, and then modifies the given `schema` with the information from that type. N)rrTrrw)rrrZt_schemarererfr$s " r)namerkrlrr[cCs4|rd||i}nd|j|di}|r0d|giS|S)Nrrr)r)rrkrlr schema_refrererfr~2sr~c Csddlm}i}t} |j} |jrP|jr0|jjs:t| |sPt|||||||dS| t ksv| t ksv| j t ksvt | tkri|| fSt| rddi|| fSt| rtd|jdi} |jdk r|jjr|j| d <t| rDtd d t| D} td d | Ddkr"tt| ||||||dS| dj } t| | d<t| | nt| tr|| } t||\} }| t| |||t | |d|| <nt!| rt"| j#||||||d^}}t|d$}| d|t|t|dn4t%| dst| | t&| dd}|rt'||| | r$| || fStt&| dd|r>| j#} t(| |r|| }| |krt"| ||||||d\}}}|||||<| |n | )|t||||}||| fSt*| }|dk r|st+| j,kr| || fSt-d|dS)z This function is indirectly used by ``field_schema()``, you should probably be using that function. Take a single Pydantic ``ModelField``, and return its schema and any additional definitions from sub-models. rrVrrnullz Callable zC was excluded from schema since JSON schema has no equivalent type.Nrcss"|]}t|tr|jn|VqdSN)rr r)rnxrererf hsz)field_singleton_schema..cSsh|] }|jqSre) __class__rnrrererf jsz)field_singleton_schema..rrrr^)rhrrrkrlrrYrr)rrrrrrz.Value not declarable with JSON Schema, field: ).rrWr`rrrrrTrrrr r rKrrPrMrrrrNtuplerIrrZ#multitypes_literal_field_for_schemalistrr rrwr~rrOrvrrrrrgrrrJr __bases__ ValueError)rYrhrrrlrrkrrWrsrrrrZ enum_namerrZ items_schemasrXr{rrrrdrererfr:s  &                     r)rrYr[c Csbtt}|D]}||j|q dd|D}t|jtt||j |j |j |j |j |jdS)z To support `Literal` with values of different types, we split it into multiple `Literal` with same type e.g. `Literal['qwe', 'asd', 1, 2]` becomes `Union[Literal['qwe', 'asd'], Literal[1, 2]]` css|]}tt|VqdSr)r%r )rnZsame_type_valuesrererfrsz6multitypes_literal_field_for_schema..)rrclass_validators model_configrrrr)rrr rrr2rr!r rrrrrr)rrYZliteral_distinct_typesrZdistinct_literalsrererfr s r )dftr[cCsddlm}t||st|r,tdt|}t|trHdd|DSt|trX|j St|t t t frl|St|t tfr|j}dd|D}t|r||S||S|dkrdSt|SdS)NrrVzdict[str, Any]cSsi|]\}}t|t|qSrerrrererfrsz"encode_default..css|]}t|VqdSrrr rererfrsz!encode_default..)rrWrrr"r3dictrr rintfloatrrr r rO)rrWrZseq_argsrererfrs    r_map_types_constraint) annotationr field_namevalidate_assignmentr[cCsZ|}t}|r t||\}}|r.|d||}|rVtd|dd|d|S)a= Get an annotation with validation implemented for numbers and strings based on the field_info. :param annotation: an annotation from a field specification, as ``str``, ``ConstrainedStr`` :param field_info: an instance of FieldInfo, possibly with declarations for validations and JSON Schema :param field_name: name of the field for use in error messages :param validate_assignment: default False, flag for BaseModel Config value of validate_assignment :return: the same ``annotation`` if unmodified or a new annotation with validation in place Zallow_mutationz On field "z<" the following field constraints are set but not enforced: z, z\. For more details see https://docs.pydantic.dev/usage/schema/#unenforced-field-constraints)Zget_constraintsr`get_annotation_with_constraintsrrjoin)rrrr constraintsused_constraintsZunused_constraintsrererfget_annotation_from_field_infos  r )rrr[cs.ttttdfdd |fS)a Get an annotation with used constraints implemented for numbers and strings based on the field_info. :param annotation: an annotation from a field specification, as ``str``, ``ConstrainedStr`` :param field_info: an instance of FieldInfo, possibly with declarations for validations and JSON Schema :return: the same ``annotation`` if unmodified or a new annotation along with the used constraints. )rr[c snts"tts"ttttfr&St}|dk rt}t dd|DrVS|t krj|dSt |rt t fdd|DSt|trjdk sjdk sjdk rdddht|djjjdSt|tr.jdk sjdk r.ddht|djjd St|trzjdk sRjdk rzddht|djjd StttttfD]0}t||r|t fd d|DSqt|trt|d|d fSd}d}ttrtttfr d }tt td fdd }ntt!rltt"t#fsld}tt$rftt td fdd }nt%}ntt&rd}tt'rtt td fdd }nt(}nptt)rtt*t+t,tttt-fsd}tt.r|d7}tt/r|d7}t0fddt)D}t1|}|rjt2|ddfdd|DD}|rjt3t4dtf|}|f|SS)Ncss|]}t|tVqdSr)rrrnarererfrsz>get_annotation_with_constraints..go..rc3s|]}|VqdSrrer!gorerfr!s min_items max_items unique_items)r%r&r')r%r&c3s|]}|VqdSrrer!r#rerfr:sr)rr)kwr[cstjf|Srrrr(rrerfconstraint_funcEszDget_annotation_with_constraints..go..constraint_func)rrrcstjf|Srr)r*r+rerfr,Lscstjf|Srr)r*r+rerfr,Us)rrrrr)Z allow_inf_nan)Z max_digitsZdecimal_placesc3s|]}t|r|VqdSr)r)rnrr+rerfrls cSsi|]\}}|dk r||qSrre)rnrrrererfrqsz?get_annotation_with_constraints..go..c3s|]}|t|fVqdSr)r)rnr)rrerfrss.)5rNrrrTr:r;r8rKrJanyr$rQr!r rrr%r&r'rwrFrrGrrDrrrrr>r=rrrr5r4r@rHrr?rArr9r7r6rrrnextrr`r"r)roriginrdrattrsr,Z numeric_typer]rr$rr+rfr$s    $$ "         z+get_annotation_with_constraints..go)r`rr)rrrer1rfrskr)rr[cCstdd|S)zU Normalizes the given name. This can be applied to either a model *or* enum. z[^a-zA-Z0-9.\-_]r)resub)rrererfr~src@s eZdZdZeddddZdS)rz? Utility exception used to exclude fields from schema. N)rr[cCs ||_dSr)r)selfrrererf__init__szSkipField.__init__)rrrrrr5rerererfrsr)F)N)F)r2r collectionsr dataclassesrrrrrdecimalrrr ipaddressr r r r rrpathlibrtypingrrrrrrrrrrrrrrrr r!r"rr#typing_extensionsr$r%Zpydantic.v1.fieldsr&r'r(r)r*r+r,r-r.r/r0r1r2Zpydantic.v1.jsonr3Zpydantic.v1.networksr4r5Zpydantic.v1.typesr6r7r8r9r:r;r<r=r>r?r@rArBrCrDrErFrGrHZpydantic.v1.typingrIrJrKrLrMrNrOrPrQZpydantic.v1.utilsrRrSrTZpydantic.v1.dataclassesrUrrWdefault_prefixZdefault_ref_templateZTypeModelOrEnumZ TypeModelSetrrgrr|rrrZrrrrr__annotations__rrrur}rrrtrrrvrrrrrrr r` frozensetrZ json_schemerr~rr rrr rr Exceptionrrerererfs~      P < T,      7 &$  3 .. !    z  8  6(   ^                      $ "  ( "x