@@ -361,3 +361,58 @@ def validate_annotated(value, typehint: type):
361361 from pydantic import TypeAdapter
362362
363363 return TypeAdapter (typehint ).validate_python (value )
364+
365+
366+ def get_pydantic_extra_config (class_type ) -> Optional [str ]:
367+ """Get the 'extra' configuration from a Pydantic model.
368+
369+ Args:
370+ class_type: The class to check for Pydantic extra configuration.
371+
372+ Returns:
373+ The extra configuration ('allow', 'forbid', 'ignore') or None if not a Pydantic model.
374+ """
375+ pydantic_model_version = is_pydantic_model (class_type )
376+ if not pydantic_model_version :
377+ return None
378+
379+ try :
380+
381+ # Handle Pydantic v2 models
382+ if pydantic_model_version > 1 :
383+ # Check for model_config attribute (Pydantic v2 style)
384+ if hasattr (class_type , "model_config" ):
385+ config = class_type .model_config
386+ if hasattr (config , "get" ):
387+ # ConfigDict case
388+ return config .get ("extra" )
389+ elif hasattr (config , "extra" ):
390+ # Direct attribute access
391+ return config .extra
392+
393+ # Check for __config__ attribute (legacy support in v2)
394+ if hasattr (class_type , "__config__" ):
395+ config = class_type .__config__
396+ if hasattr (config , "extra" ):
397+ return config .extra
398+
399+ # Handle Pydantic v1 models (including v1 compatibility mode in v2)
400+ else :
401+ if hasattr (class_type , "__config__" ):
402+ config = class_type .__config__
403+ if hasattr (config , "extra" ):
404+ extra_value = config .extra
405+ # Handle Pydantic v1 Extra enum
406+ if hasattr (extra_value , "value" ):
407+ return extra_value .value
408+ elif isinstance (extra_value , str ):
409+ return extra_value
410+ else :
411+ # Convert enum to string by taking the last part after the dot
412+ return str (extra_value ).split ("." )[- 1 ]
413+
414+ except Exception :
415+ # If anything goes wrong, return None to fall back to default behavior
416+ pass
417+
418+ return None
0 commit comments