Add type annotations to analyze_outcomes.py

Signed-off-by: Pengyu Lv <pengyu.lv@arm.com>
diff --git a/tests/scripts/analyze_outcomes.py b/tests/scripts/analyze_outcomes.py
index 4e925a1..018d941 100755
--- a/tests/scripts/analyze_outcomes.py
+++ b/tests/scripts/analyze_outcomes.py
@@ -16,10 +16,32 @@
 
 import check_test_cases
 
+
+# `CompoentOutcomes` is a named tuple which is defined as:
+# ComponentOutcomes(
+#     successes = {
+#         "<suite_case>",
+#         ...
+#     },
+#     failures = {
+#         "<suite_case>",
+#         ...
+#     }
+# )
+# suite_case = "<suite>;<case>"
 ComponentOutcomes = typing.NamedTuple('ComponentOutcomes',
                                       [('successes', typing.Set[str]),
                                        ('failures', typing.Set[str])])
 
+# `Outcomes` is a representation of the outcomes file,
+# which defined as:
+# Outcomes = {
+#     "<component>": ComponentOutcomes,
+#     ...
+# }
+Outcomes = typing.Dict[str, ComponentOutcomes]
+
+
 class Results:
     """Process analysis results."""
 
@@ -45,8 +67,8 @@
     def _print_line(fmt, *args, **kwargs):
         sys.stderr.write((fmt + '\n').format(*args, **kwargs))
 
-def execute_reference_driver_tests(results: Results, ref_component, driver_component, \
-                                   outcome_file):
+def execute_reference_driver_tests(results: Results, ref_component: str, driver_component: str, \
+                                   outcome_file: str) -> None:
     """Run the tests specified in ref_component and driver_component. Results
     are stored in the output_file and they will be used for the following
     coverage analysis"""
@@ -60,7 +82,8 @@
     if ret_val != 0:
         results.error("failed to run reference/driver components")
 
-def analyze_coverage(results, outcomes, allow_list, full_coverage):
+def analyze_coverage(results: Results, outcomes: Outcomes,
+                     allow_list: typing.List[str], full_coverage: bool) -> None:
     """Check that all available test cases are executed at least once."""
     available = check_test_cases.collect_available_test_cases()
     for suite_case in available:
@@ -83,7 +106,7 @@
             else:
                 results.warning('Allow listed test case was executed: {}', suite_case)
 
-def name_matches_pattern(name, str_or_re):
+def name_matches_pattern(name: str, str_or_re) -> bool:
     """Check if name matches a pattern, that may be a string or regex.
     - If the pattern is a string, name must be equal to match.
     - If the pattern is a regex, name must fully match.
@@ -91,13 +114,13 @@
     # The CI's python is too old for re.Pattern
     #if isinstance(str_or_re, re.Pattern):
     if not isinstance(str_or_re, str):
-        return str_or_re.fullmatch(name)
+        return str_or_re.fullmatch(name) is not None
     else:
         return str_or_re == name
 
-def analyze_driver_vs_reference(results: Results, outcomes,
-                                component_ref, component_driver,
-                                ignored_suites, ignored_tests=None):
+def analyze_driver_vs_reference(results: Results, outcomes: Outcomes,
+                                component_ref: str, component_driver: str,
+                                ignored_suites: typing.List[str], ignored_tests=None) -> None:
     """Check that all tests passing in the reference component are also
     passing in the corresponding driver component.
     Skip:
@@ -139,37 +162,14 @@
         if ignored and suite_case in driver_outcomes.successes:
             results.error("uselessly ignored: {}", suite_case)
 
-def analyze_outcomes(results: Results, outcomes, args):
+def analyze_outcomes(results: Results, outcomes: Outcomes, args) -> None:
     """Run all analyses on the given outcome collection."""
     analyze_coverage(results, outcomes, args['allow_list'],
                      args['full_coverage'])
 
-def read_outcome_file(outcome_file):
+def read_outcome_file(outcome_file: str) -> Outcomes:
     """Parse an outcome file and return an outcome collection.
-
-An outcome collection is a dictionary presentation of the outcome file:
-```
-outcomes = {
-    "<component>": ComponentOutcomes,
-    ...
-}
-
-CompoentOutcomes is a named tuple which is defined as:
-
-ComponentOutcomes(
-    successes = {
-        <suite_case>,
-        ...
-    },
-    failures = {
-        <suite_case>,
-        ...
-    }
-)
-
-suite_case = "<suite>;<case>"
-```
-"""
+    """
     outcomes = {}
     with open(outcome_file, 'r', encoding='utf-8') as input_file:
         for line in input_file:
@@ -184,12 +184,12 @@
 
     return outcomes
 
-def do_analyze_coverage(results: Results, outcomes, args):
+def do_analyze_coverage(results: Results, outcomes: Outcomes, args) -> None:
     """Perform coverage analysis."""
     results.new_section("Analyze coverage")
     analyze_outcomes(results, outcomes, args)
 
-def do_analyze_driver_vs_reference(results: Results, outcomes, args):
+def do_analyze_driver_vs_reference(results: Results, outcomes: Outcomes, args) -> None:
     """Perform driver vs reference analyze."""
     results.new_section("Analyze driver {} vs reference {}",
                         args['component_driver'], args['component_ref'])
@@ -502,7 +502,7 @@
 
             task_name = tasks_list[0]
             task = KNOWN_TASKS[task_name]
-            if task['test_function'] != do_analyze_driver_vs_reference:
+            if task['test_function'] != do_analyze_driver_vs_reference: # pylint: disable=comparison-with-callable
                 sys.stderr.write("please provide valid outcomes file for {}.\n".format(task_name))
                 sys.exit(2)