@@ -597,8 +597,11 @@ def _field_is_complex(self, field: FieldInfo) -> tuple[bool, bool]:
597597
598598 return True , allow_parse_failure
599599
600+ # Default value of `case_sensitive` is `None`, because we don't want to break existing behavior.
601+ # We have to change the method to a non-static method and use
602+ # `self.case_sensitive` instead in V3.
600603 @staticmethod
601- def next_field (field : FieldInfo | Any | None , key : str ) -> FieldInfo | None :
604+ def next_field (field : FieldInfo | Any | None , key : str , case_sensitive : bool | None = None ) -> FieldInfo | None :
602605 """
603606 Find the field in a sub model by key(env name)
604607
@@ -623,6 +626,7 @@ class Cfg(BaseSettings):
623626 Args:
624627 field: The field.
625628 key: The key (env name).
629+ case_sensitive: Whether to search for key case sensitively.
626630
627631 Returns:
628632 Field if it finds the next field otherwise `None`.
@@ -633,11 +637,18 @@ class Cfg(BaseSettings):
633637 annotation = field .annotation if isinstance (field , FieldInfo ) else field
634638 if origin_is_union (get_origin (annotation )) or isinstance (annotation , WithArgsTypes ):
635639 for type_ in get_args (annotation ):
636- type_has_key = EnvSettingsSource .next_field (type_ , key )
640+ type_has_key = EnvSettingsSource .next_field (type_ , key , case_sensitive )
637641 if type_has_key :
638642 return type_has_key
639- elif is_model_class (annotation ) and annotation .model_fields .get (key ):
640- return annotation .model_fields [key ]
643+ elif is_model_class (annotation ):
644+ # `case_sensitive is None` is here to be compatible with the old behavior.
645+ # Has to be removed in V3.
646+ if (case_sensitive is None or case_sensitive ) and annotation .model_fields .get (key ):
647+ return annotation .model_fields [key ]
648+ elif not case_sensitive :
649+ for field_name , f in annotation .model_fields .items ():
650+ if field_name .lower () == key .lower ():
651+ return f
641652
642653 return None
643654
@@ -670,12 +681,12 @@ def explode_env_vars(self, field_name: str, field: FieldInfo, env_vars: Mapping[
670681 env_var = result
671682 target_field : FieldInfo | None = field
672683 for key in keys :
673- target_field = self .next_field (target_field , key )
684+ target_field = self .next_field (target_field , key , self . case_sensitive )
674685 if isinstance (env_var , dict ):
675686 env_var = env_var .setdefault (key , {})
676687
677688 # get proper field with last_key
678- target_field = self .next_field (target_field , last_key )
689+ target_field = self .next_field (target_field , last_key , self . case_sensitive )
679690
680691 # check if env_val maps to a complex field and if so, parse the env_val
681692 if (target_field or is_dict ) and env_val :
0 commit comments