3939 ConfigurationError ,
4040 ConfigurationKeyError ,
4141 DuplicatedConfigurationError ,
42- DuplicateKeysInYAMLError ,
4342 ImproperAccessError ,
4443)
4544from layered_config_tree .types import InputData
@@ -711,10 +710,22 @@ class SafeLoader(yaml.SafeLoader):
711710 """A yaml.SafeLoader that restricts duplicate keys."""
712711
713712 def construct_mapping (
714- self , node : yaml .MappingNode , deep : bool = False
713+ self ,
714+ node : yaml .MappingNode ,
715+ deep : bool = False ,
716+ path : list [str ] | None = None ,
715717 ) -> dict [Hashable , Any ]:
716718 """Constructs the standard mapping after checking for duplicates.
717719
720+ Parameters
721+ ----------
722+ node
723+ The YAML mapping node to construct.
724+ deep
725+ Whether or not to recursively construct mappings.
726+ path
727+ The path to the current node in the YAML document.
728+
718729 Raises
719730 ------
720731 DuplicateKeysInYAMLError
@@ -729,15 +740,28 @@ def construct_mapping(
729740 fixing a duplicate in one level of the document will not prevent this method
730741 from raising an error for duplicates in another upon subsequent loads.
731742 """
732- mapping = []
733- duplicates = []
734- for key_node , _value_node in node .value :
743+ path = [] if path is None else path
744+ seen = set ()
745+ duplicates = {}
746+ for key_node , value_node in node .value :
735747 key = self .construct_object (key_node , deep = deep ) # type: ignore[no-untyped-call]
736- if key in mapping :
737- duplicates .append (key )
738- mapping .append (key )
748+ full_path = path + [key ]
749+ if key in seen :
750+ duplicates [key ] = full_path
751+ else :
752+ seen .add (key )
753+ # update path
754+ if isinstance (value_node , yaml .MappingNode ):
755+ self .construct_mapping (value_node , deep , full_path )
739756 if duplicates :
740- raise DuplicateKeysInYAMLError (
741- f"Duplicate key(s) detected in YAML file being loaded: { duplicates } "
757+ formatted_duplicates = "\n " .join (
758+ [f"* { '-' .join (map (str , v ))} " for v in duplicates .values ()]
759+ )
760+ raise DuplicatedConfigurationError (
761+ f"Duplicate key(s) detected in YAML file being loaded:\n { formatted_duplicates } " ,
762+ name = f"duplicates_{ '_' .join (duplicates )} " ,
763+ layer = None ,
764+ source = None ,
765+ value = None ,
742766 )
743767 return super ().construct_mapping (node , deep )
0 commit comments