@@ -204,6 +204,23 @@ def wrapper(tag, *args, severity=default_severity, **kwargs):
204204schema_error_messages .mark_as_used = True
205205
206206
207+ def separate_issues (issues_list : list [dict ]) -> tuple [list [dict ], list [dict ]]:
208+ """Separate a list of issues into errors and warnings.
209+
210+ Parameters:
211+ issues_list (list[dict]): A list of issue dictionaries. The 'severity' key is
212+ optional; issues that omit it are treated as errors (ErrorSeverity.ERROR).
213+
214+ Returns:
215+ tuple[list[dict], list[dict]]: A tuple of (errors, warnings) where errors contains
216+ issues with severity <= ErrorSeverity.ERROR and warnings contains issues with
217+ severity > ErrorSeverity.ERROR.
218+ """
219+ errors = [issue for issue in issues_list if issue .get ("severity" , ErrorSeverity .ERROR ) <= ErrorSeverity .ERROR ]
220+ warnings = [issue for issue in issues_list if issue .get ("severity" , ErrorSeverity .ERROR ) > ErrorSeverity .ERROR ]
221+ return errors , warnings
222+
223+
207224class ErrorHandler :
208225 """Class to hold error context and having general error functions."""
209226
@@ -274,20 +291,6 @@ def format_error_with_context(self, *args, **kwargs):
274291
275292 return error_object
276293
277- @staticmethod
278- def filter_issues_by_severity (issues_list : list [dict ], severity : int ) -> list [dict ]:
279- """Gather all issues matching or below a given severity.
280-
281- Parameters:
282- issues_list (list[dict]): A list of dictionaries containing the full issue list.
283- severity (int): The level of issues to keep.
284-
285- Returns:
286- list[dict]: A list of dictionaries containing the issue list after filtering by severity.
287-
288- """
289- return [issue for issue in issues_list if issue ["severity" ] <= severity ]
290-
291294 @staticmethod
292295 def format_error (error_type : str , * args , actual_error = None , ** kwargs ) -> list [dict ]:
293296 """Format an error based on the parameters, which vary based on what type of error this is.
@@ -423,13 +426,46 @@ def val_error_unknown(*args, **kwargs) -> str:
423426 return f"Unknown error. Args: { str (args ), str (kwargs )} "
424427
425428 @staticmethod
426- def filter_issues_by_count (issues , count , by_file = False ) -> tuple [list [dict ], dict [str , int ]]:
429+ def filter_issues_by_severity (issues_list : list [dict ], severity : int ) -> list [dict ]:
430+ """Gather all issues matching or below a given severity.
431+
432+ Parameters:
433+ issues_list (list[dict]): A list of dictionaries containing the full issue list.
434+ severity (int): The level of issues to keep.
435+
436+ Returns:
437+ list[dict]: A list of dictionaries containing the issue list after filtering by severity.
438+
439+ """
440+ return [issue for issue in issues_list if issue .get ("severity" , ErrorSeverity .ERROR ) <= severity ]
441+
442+ @staticmethod
443+ def aggregate_code_counts (file_code_dict : dict ) -> dict :
444+ """Aggregate the counts of codes across multiple files.
445+
446+ Parameters:
447+ file_code_dict (dict): A dictionary where keys are filenames and values are
448+ dictionaries of code counts.
449+
450+ Returns:
451+ dict: A dictionary with the aggregated counts of codes across all files.
452+ """
453+ total_counts = defaultdict (int )
454+ for file_dict in file_code_dict .values ():
455+ for code , count in file_dict .items ():
456+ total_counts [code ] += count
457+ return dict (total_counts )
458+
459+ @staticmethod
460+ def filter_issues_by_count (
461+ issues : list [dict ], count : int , by_file : bool = False
462+ ) -> tuple [list [dict ], dict [str , int ]]:
427463 """Filter the issues list to only include the first count issues of each code.
428464
429- Parameters:
430- issues (list): A list of dictionaries containing the full issue list.
431- count (int): The number of issues to keep for each code.
432- by_file (bool): If True, group by file name.
465+ Parameters:
466+ issues (list[dict] ): A list of dictionaries containing the full issue list.
467+ count (int): The number of issues to keep for each code.
468+ by_file (bool): If True, group by file name.
433469
434470 Returns:
435471 tuple[list[dict], dict[str, int]]: A tuple containing:
@@ -457,22 +493,6 @@ def filter_issues_by_count(issues, count, by_file=False) -> tuple[list[dict], di
457493
458494 return filtered_issues , ErrorHandler .aggregate_code_counts (file_dicts )
459495
460- @staticmethod
461- def aggregate_code_counts (file_code_dict ) -> dict :
462- """Aggregate the counts of codes across multiple files.
463-
464- Parameters:
465- file_code_dict (dict): A dictionary where keys are filenames and values are dictionaries of code counts.
466-
467- Returns:
468- dict: A dictionary with the aggregated counts of codes across all files.
469- """
470- total_counts = defaultdict (int )
471- for file_dict in file_code_dict .values ():
472- for code , count in file_dict .items ():
473- total_counts [code ] += count
474- return dict (total_counts )
475-
476496 @staticmethod
477497 def get_code_counts (issues : list [dict ]) -> dict [str , int ]:
478498 """Count the occurrences of each error code in the issues list.
@@ -490,6 +510,34 @@ def get_code_counts(issues: list[dict]) -> dict[str, int]:
490510 code_counts [code ] += 1
491511 return dict (code_counts )
492512
513+ @staticmethod
514+ def replace_tag_references (list_or_dict ):
515+ """Utility function to remove any references to tags, strings, etc. from any type of nested list or dict.
516+
517+ Use this if you want to save out issues to a file.
518+
519+ If you'd prefer a copy returned, use ErrorHandler.replace_tag_references(list_or_dict.copy()).
520+
521+ Parameters:
522+ list_or_dict (list or dict): An arbitrarily nested list/dict structure
523+ """
524+ if isinstance (list_or_dict , dict ):
525+ for key , value in list_or_dict .items ():
526+ if isinstance (value , (dict , list )):
527+ ErrorHandler .replace_tag_references (value )
528+ elif isinstance (value , (bool , float , int )):
529+ list_or_dict [key ] = value
530+ else :
531+ list_or_dict [key ] = str (value )
532+ elif isinstance (list_or_dict , list ):
533+ for key , value in enumerate (list_or_dict ):
534+ if isinstance (value , (dict , list )):
535+ ErrorHandler .replace_tag_references (value )
536+ elif isinstance (value , (bool , float , int )):
537+ list_or_dict [key ] = value
538+ else :
539+ list_or_dict [key ] = str (value )
540+
493541
494542def sort_issues (issues , reverse = False ) -> list [dict ]:
495543 """Sort a list of issues by the error context values.
@@ -822,31 +870,3 @@ def _create_error_tree(error_dict, parent_element=None, add_link=True):
822870 _create_error_tree (value , context_ul , add_link )
823871
824872 return parent_element
825-
826-
827- def replace_tag_references (list_or_dict ):
828- """Utility function to remove any references to tags, strings, etc. from any type of nested list or dict.
829-
830- Use this if you want to save out issues to a file.
831-
832- If you'd prefer a copy returned, use replace_tag_references(list_or_dict.copy()).
833-
834- Parameters:
835- list_or_dict (list or dict): An arbitrarily nested list/dict structure
836- """
837- if isinstance (list_or_dict , dict ):
838- for key , value in list_or_dict .items ():
839- if isinstance (value , (dict , list )):
840- replace_tag_references (value )
841- elif isinstance (value , (bool , float , int )):
842- list_or_dict [key ] = value
843- else :
844- list_or_dict [key ] = str (value )
845- elif isinstance (list_or_dict , list ):
846- for key , value in enumerate (list_or_dict ):
847- if isinstance (value , (dict , list )):
848- replace_tag_references (value )
849- elif isinstance (value , (bool , float , int )):
850- list_or_dict [key ] = value
851- else :
852- list_or_dict [key ] = str (value )
0 commit comments