88
99import re
1010from collections import defaultdict
11- from typing import TYPE_CHECKING , Any , ClassVar , Literal , NamedTuple , Optional
11+ from typing import TYPE_CHECKING , Any , ClassVar , Optional
1212
13- from pydantic import Field , ValidationError , field_validator , model_validator
13+ from pydantic import ValidationError , field_validator , model_validator
1414
1515from datamodel_code_generator import Error
16- from datamodel_code_generator .enums import TargetPydanticVersion
1716from datamodel_code_generator .imports import IMPORT_ANY , IMPORT_DICT , Import
1817from datamodel_code_generator .model import _rebuild_model_with_datamodel_namespace
1918from datamodel_code_generator .model .base import (
2322 DataModelFieldBase ,
2423)
2524from datamodel_code_generator .model .imports import IMPORT_CLASSVAR
25+ from datamodel_code_generator .model .pydantic_base import BaseModelBase
2626from datamodel_code_generator .model .pydantic_base import (
27- BaseModelBase ,
27+ DataModelField as _PydanticBaseDataModelField ,
2828)
2929from datamodel_code_generator .model .pydantic_base import (
30- Constraints as _Constraints ,
30+ PatternConstraints as _Constraints ,
3131)
32- from datamodel_code_generator .model .pydantic_base import (
33- DataModelField as _PydanticBaseDataModelField ,
32+ from datamodel_code_generator .model .pydantic_v2 ._config import (
33+ ConfigAttribute ,
34+ ConfigDict ,
35+ build_base_config_parameters ,
3436)
3537from datamodel_code_generator .model .pydantic_v2 .imports import (
3638 IMPORT_ALIAS_CHOICES ,
@@ -68,10 +70,6 @@ def __repr__(self) -> str:
6870class Constraints (_Constraints ):
6971 """Pydantic v2 field constraints with pattern support."""
7072
71- # To override existing pattern alias
72- regex : Optional [str ] = Field (None , alias = "regex" ) # noqa: UP045
73- pattern : Optional [str ] = Field (None , alias = "pattern" ) # noqa: UP045
74-
7573 @model_validator (mode = "before" ) # ty: ignore
7674 def validate_min_max_items (cls , values : Any ) -> dict [str , Any ]: # noqa: N805
7775 """Validate and convert minItems/maxItems to minLength/maxLength."""
@@ -273,14 +271,6 @@ def imports(self) -> tuple[Import, ...]:
273271 return base_imports
274272
275273
276- class ConfigAttribute (NamedTuple ):
277- """Configuration attribute mapping for ConfigDict conversion."""
278-
279- from_ : str
280- to : str
281- invert : bool
282-
283-
284274class BaseModel (BaseModelBase ):
285275 """Pydantic v2 BaseModel with ConfigDict and pattern-based regex_engine support."""
286276
@@ -356,30 +346,19 @@ def __init__( # noqa: PLR0913
356346 keyword_only = keyword_only ,
357347 treat_dot_as_module = treat_dot_as_module ,
358348 )
359- config_parameters : dict [str , Any ] = {}
360-
361- extra = self ._get_config_extra ()
362- if extra :
363- config_parameters ["extra" ] = extra
364-
365- # Select CONFIG_ATTRIBUTES based on target_pydantic_version
366- config_attributes = self ._get_config_attributes ()
367- for from_ , to , invert in config_attributes :
368- if from_ in self .extra_template_data :
369- config_parameters [to ] = (
370- not self .extra_template_data [from_ ] if invert else self .extra_template_data [from_ ]
371- )
372- for data_type in self .all_data_types :
373- if data_type .is_custom_type : # pragma: no cover
374- config_parameters ["arbitrary_types_allowed" ] = True
375- break
349+ config_parameters = build_base_config_parameters (
350+ extra_template_data = self .extra_template_data ,
351+ all_data_types = self .all_data_types ,
352+ config_attributes_v2 = self ._CONFIG_ATTRIBUTES_V2 ,
353+ config_attributes_v2_11 = self ._CONFIG_ATTRIBUTES_V2_11 ,
354+ )
376355
377356 if self ._has_lookaround_pattern ():
378357 config_parameters ["regex_engine" ] = '"python-re"'
379358
380359 if isinstance (self .extra_template_data .get ("config" ), dict ):
381360 for key , value in self .extra_template_data ["config" ].items ():
382- config_parameters [key ] = value # noqa: PERF403
361+ config_parameters [key ] = value
383362
384363 # Handle json_schema_extra from schema extensions (x-* fields)
385364 model_extras = self .extra_template_data .get ("model_extras" )
@@ -388,47 +367,11 @@ def __init__( # noqa: PLR0913
388367 config_parameters ["json_schema_extra" ] = {** existing , ** model_extras }
389368
390369 if config_parameters :
391- from datamodel_code_generator .model .pydantic_v2 import ConfigDict # noqa: PLC0415
392-
393370 self .extra_template_data ["config" ] = ConfigDict .model_validate (config_parameters ) # ty: ignore
394371 self ._additional_imports .append (IMPORT_CONFIG_DICT )
395372
396373 self ._process_validators ()
397374
398- def _get_config_extra (self ) -> Literal ["'allow'" , "'forbid'" , "'ignore'" ] | None :
399- additional_properties = self .extra_template_data .get ("additionalProperties" )
400- unevaluated_properties = self .extra_template_data .get ("unevaluatedProperties" )
401- allow_extra_fields = self .extra_template_data .get ("allow_extra_fields" )
402- extra_fields = self .extra_template_data .get ("extra_fields" )
403-
404- config_extra = None
405- if allow_extra_fields or extra_fields == "allow" :
406- config_extra = "'allow'"
407- elif extra_fields == "forbid" :
408- config_extra = "'forbid'"
409- elif extra_fields == "ignore" :
410- config_extra = "'ignore'"
411- elif additional_properties is True :
412- config_extra = "'allow'"
413- elif additional_properties is False :
414- config_extra = "'forbid'"
415- elif unevaluated_properties is True :
416- config_extra = "'allow'"
417- elif unevaluated_properties is False :
418- config_extra = "'forbid'"
419- return config_extra
420-
421- def _get_config_attributes (self ) -> list [ConfigAttribute ]:
422- """Get config attributes based on target Pydantic version.
423-
424- If target_pydantic_version is V2_11, use validate_by_name.
425- Otherwise (V2 or not specified), use populate_by_name for compatibility.
426- """
427- target_version = self .extra_template_data .get ("target_pydantic_version" )
428- if target_version == TargetPydanticVersion .V2_11 :
429- return self ._CONFIG_ATTRIBUTES_V2_11
430- return self ._CONFIG_ATTRIBUTES_V2
431-
432375 def _has_lookaround_pattern (self ) -> bool :
433376 """Check if any field has a regex pattern with lookaround assertions."""
434377 lookaround_regex = re .compile (r"\(\?<?[=!]" )
0 commit comments