@@ -387,24 +387,26 @@ def get_class_attribute_type(cls: Union[type, Any], attribute_name: str):
387387 return None
388388
389389
390- def get_matching_class_attribute_name (
390+ def get_all_matching_class_attribute_name (
391391 cls : Union [type , Any ],
392392 attribute_name : str ,
393393 re_flags = re .IGNORECASE ,
394- ) -> Optional [str ]:
394+ ) -> List [str ]:
395395 """
396- From an object and an attribute name, returns the correct attribute name of the class.
397- Example : "ObjectVersion " --> object_version.
398- This method doesn't only transform to snake case but search into the obj class attributes (or dict keys)
396+ From an object and an attribute name, returns all the correct attribute names of the class matching with the attribute_name .
397+ Example : "\\ w*.Version " --> [" object_version", "ObjectVersion", "obj_version", ...]
398+ This method doesn't only transform to snake case but search into the obj class attributes (or dict keys)
399399 """
400+ matching_names = []
400401 if isinstance (cls , dict ):
401402 for name in cls .keys ():
402403 if snake_case (name ) == snake_case (attribute_name ):
403- return name
404+ matching_names . append ( name )
404405 pattern = re .compile (attribute_name , flags = re_flags )
405406 for name in cls .keys ():
406407 if pattern .match (name ):
407- return name
408+ matching_names .append (name )
409+ return matching_names
408410 else :
409411 class_fields = get_class_fields (cls )
410412 try :
@@ -413,7 +415,7 @@ def get_matching_class_attribute_name(
413415 if snake_case (name ) == snake_case (attribute_name ) or (
414416 hasattr (cf , "metadata" ) and "name" in cf .metadata and cf .metadata ["name" ] == attribute_name
415417 ):
416- return name
418+ matching_names . append ( name )
417419
418420 # search regex after to avoid shadowing perfect match
419421 pattern = re .compile (attribute_name , flags = re_flags )
@@ -422,11 +424,27 @@ def get_matching_class_attribute_name(
422424 if pattern .match (name ) or (
423425 hasattr (cf , "metadata" ) and "name" in cf .metadata and pattern .match (cf .metadata ["name" ])
424426 ):
425- return name
427+ matching_names . append ( name )
426428 except Exception as e :
427429 logging .error (f"Failed to get attribute { attribute_name } from class { cls } " )
428430 logging .error (e )
429431
432+ return matching_names
433+
434+
435+ def get_matching_class_attribute_name (
436+ cls : Union [type , Any ],
437+ attribute_name : str ,
438+ re_flags = re .IGNORECASE ,
439+ ) -> Optional [str ]:
440+ """
441+ From an object and an attribute name, returns the correct attribute name of the class.
442+ Example : "ObjectVersion" --> object_version.
443+ This method doesn't only transform to snake case but search into the obj class attributes (or dict keys)
444+ """
445+ matched = get_all_matching_class_attribute_name (cls , attribute_name , re_flags )
446+ if len (matched ) > 0 :
447+ return matched [0 ]
430448 return None
431449
432450
@@ -931,22 +949,24 @@ def search_attribute_matching_name_with_path(
931949 else :
932950 not_match_path_and_obj .append ((f"{ current_path } { k } " , s_o ))
933951 elif not is_primitive (obj ):
934- match_value = get_matching_class_attribute_name (obj , current_match .replace ("\\ ." , "." ))
935- if match_value is not None :
952+ # logging.debug(f"searching {current_match} in {type(obj)} with path {current_path} and next match {next_match}")
953+ match_values = get_all_matching_class_attribute_name (obj , current_match , re_flags )
954+ for match_value in match_values :
936955 match_path_and_obj .append (
937956 (
938957 f"{ current_path } { match_value } " ,
939958 get_object_attribute_no_verif (obj , match_value ),
940959 )
941960 )
942961 for att_name in get_class_attributes (obj ):
943- if att_name != match_value :
962+ if att_name not in match_values :
944963 not_match_path_and_obj .append (
945964 (
946965 f"{ current_path } { att_name } " ,
947966 get_object_attribute_no_verif (obj , att_name ),
948967 )
949968 )
969+ # logging.debug(f"\tmatch_path_and_obj: {match_path_and_obj}")
950970
951971 for matched_path , matched in match_path_and_obj :
952972 if next_match is not None : # next_match is different, match is not final
0 commit comments