1212import pprint
1313import uuid
1414from abc import abstractmethod
15+ from difflib import get_close_matches
1516from functools import cached_property
1617from typing import List , Optional , Tuple , Union
1718
@@ -700,16 +701,18 @@ def getReferencesListForJson(self) -> List[str]:
700701 def mapNamesToSecurityContentObjects (
701702 cls , v : list [str ], director : Union [DirectorOutputDto , None ]
702703 ) -> list [Self ]:
703- if director is not None :
704- name_map = director .name_to_content_map
705- else :
706- name_map = {}
704+ if director is None :
705+ raise Exception (
706+ "Direction was 'None' when passed to "
707+ "'mapNamesToSecurityContentObjects'. This is "
708+ "an error in the contentctl codebase which must be resolved."
709+ )
707710
708711 mappedObjects : list [Self ] = []
709712 mistyped_objects : list [SecurityContentObject_Abstract ] = []
710713 missing_objects : list [str ] = []
711714 for object_name in v :
712- found_object = name_map .get (object_name , None )
715+ found_object = director . name_to_content_map .get (object_name , None )
713716 if not found_object :
714717 missing_objects .append (object_name )
715718 elif not isinstance (found_object , cls ):
@@ -718,22 +721,40 @@ def mapNamesToSecurityContentObjects(
718721 mappedObjects .append (found_object )
719722
720723 errors : list [str ] = []
721- if len (missing_objects ) > 0 :
724+ for missing_object in missing_objects :
725+ if missing_object .endswith ("_filter" ):
726+ # Most filter macros are defined as empty at runtime, so we do not
727+ # want to make any suggestions. It is time consuming and not helpful
728+ # to make these suggestions, so we just skip them in this check.
729+ continue
730+ matches = get_close_matches (
731+ missing_object ,
732+ director .name_to_content_map .keys (),
733+ n = 3 ,
734+ )
735+ if matches == []:
736+ matches = ["NO SUGGESTIONS" ]
737+
738+ matches_string = ", " .join (matches )
722739 errors .append (
723- f"Failed to find the following '{ cls .__name__ } ': { missing_objects } "
740+ f"Unable to find: { missing_object } \n Suggestions: { matches_string } "
741+ )
742+
743+ for mistyped_object in mistyped_objects :
744+ matches = get_close_matches (
745+ mistyped_object .name , director .name_to_content_map .keys (), n = 3
746+ )
747+
748+ errors .append (
749+ f"'{ mistyped_object .name } ' expected to have type '{ cls .__name__ } ', but actually "
750+ f"had type '{ type (mistyped_object ).__name__ } '"
724751 )
725- if len (mistyped_objects ) > 0 :
726- for mistyped_object in mistyped_objects :
727- errors .append (
728- f"'{ mistyped_object .name } ' expected to have type '{ cls } ', but actually "
729- f"had type '{ type (mistyped_object )} '"
730- )
731752
732753 if len (errors ) > 0 :
733- error_string = "\n - " .join (errors )
754+ error_string = "\n \n - " .join (errors )
734755 raise ValueError (
735- f"Found { len (errors )} issues when resolving references Security Content Object "
736- f"names: \n - { error_string } "
756+ f"Found { len (errors )} issues when resolving references to ' { cls . __name__ } ' objects: \n "
757+ f" - { error_string } "
737758 )
738759
739760 # Sort all objects sorted by name
0 commit comments