Added type hints to parse_registries.py

Added type hints to reduce possibility of mistakes caused by using wrong
types and make changes safer/faster to make. Fixed bugs related to types
in the script.

Testing:
Ran the script, made sure it did not change anything in the repo (i.e.
produces the same results as before).

Change-Id: Ia7be551705a9eeabb2dd762bf709b113f8f1405b
Signed-off-by: Igor Kanyuka <ifelmail@gmail.com>
diff --git a/scripts/parse_registries.py b/scripts/parse_registries.py
index b57d7c4..992bdc8 100755
--- a/scripts/parse_registries.py
+++ b/scripts/parse_registries.py
@@ -2,11 +2,14 @@
 import argparse
 import json
 import os
+import typing as t
 from collections import OrderedDict
 
 import requests
 
-PRAGMA_ONCE = """#pragma once
+PRAGMA_ONCE: t.Final[
+    str
+] = """#pragma once
 """
 
 WARNING = """/****************************************************************
@@ -20,7 +23,9 @@
  * github organization.
  ***************************************************************/"""
 
-COPYRIGHT = """// SPDX-License-Identifier: Apache-2.0
+COPYRIGHT: t.Final[
+    str
+] = """// SPDX-License-Identifier: Apache-2.0
 // SPDX-FileCopyrightText: Copyright OpenBMC Authors
 """
 
@@ -35,18 +40,24 @@
 {{
 """
 
-REGISTRY_HEADER = f"{COPYRIGHT}{PRAGMA_ONCE}{WARNING}{INCLUDES}"
+REGISTRY_HEADER: t.Final[str] = f"{COPYRIGHT}{PRAGMA_ONCE}{WARNING}{INCLUDES}"
 
-SCRIPT_DIR = os.path.dirname(os.path.realpath(__file__))
+SCRIPT_DIR: t.Final[str] = os.path.dirname(os.path.realpath(__file__))
 
-INCLUDE_PATH = os.path.realpath(
+INCLUDE_PATH: t.Final[str] = os.path.realpath(
     os.path.join(SCRIPT_DIR, "..", "redfish-core", "include", "registries")
 )
 
-PROXIES = {"https": os.environ.get("https_proxy", None)}
+PROXIES: t.Final[t.Dict[str, str]] = {
+    "https": os.environ.get("https_proxy", "")
+}
+
+RegistryInfo: t.TypeAlias = t.Tuple[str, t.Dict[str, t.Any], str, str]
 
 
-def make_getter(dmtf_name, header_name, type_name):
+def make_getter(
+    dmtf_name: str, header_name: str, type_name: str
+) -> RegistryInfo:
     url = "https://redfish.dmtf.org/registries/{}".format(dmtf_name)
     dmtf = requests.get(url, proxies=PROXIES)
     dmtf.raise_for_status()
@@ -55,7 +66,7 @@
     return (path, json_file, type_name, url)
 
 
-def openbmc_local_getter():
+def openbmc_local_getter() -> RegistryInfo:
     url = "https://raw.githubusercontent.com/openbmc/bmcweb/refs/heads/master/redfish-core/include/registries/openbmc.json"
     with open(
         os.path.join(
@@ -74,7 +85,7 @@
     return (path, json_file, "openbmc", url)
 
 
-def update_registries(files):
+def update_registries(files: t.List[RegistryInfo]) -> None:
     # Remove the old files
     for file, json_dict, namespace, url in files:
         try:
@@ -83,7 +94,6 @@
             print("{} not found".format(file))
 
         with open(file, "w") as registry:
-
             version_split = json_dict["RegistryVersion"].split(".")
 
             registry.write(REGISTRY_HEADER.format(namespace))
@@ -136,8 +146,9 @@
                 else:
                     registry.write("},\n")
                 registry.write(
-                    '            "{message[Resolution]}",\n'
-                    "        }}}},\n".format(message=message)
+                    '            "{message[Resolution]}",\n        }}}},\n'.format(
+                        message=message
+                    )
                 )
 
             registry.write("\n};\n\nenum class Index\n{\n")
@@ -151,18 +162,22 @@
             )
 
 
-def get_privilege_string_from_list(privilege_list):
+def get_privilege_string_from_list(
+    privilege_list: t.List[t.Dict[str, t.Any]],
+) -> str:
     privilege_string = "{{\n"
     for privilege_json in privilege_list:
         privileges = privilege_json["Privilege"]
         privilege_string += "    {"
+        last_privelege = ""
         for privilege in privileges:
+            last_privelege = privilege
             if privilege == "NoAuth":
                 continue
             privilege_string += '"'
             privilege_string += privilege
             privilege_string += '",\n'
-        if privilege != "NoAuth":
+        if last_privelege != "NoAuth":
             privilege_string = privilege_string[:-2]
         privilege_string += "}"
         privilege_string += ",\n"
@@ -171,7 +186,9 @@
     return privilege_string
 
 
-def get_variable_name_for_privilege_set(privilege_list):
+def get_variable_name_for_privilege_set(
+    privilege_list: t.List[t.Dict[str, t.Any]],
+) -> str:
     names = []
     for privilege_json in privilege_list:
         privileges = privilege_json["Privilege"]
@@ -196,7 +213,7 @@
 )
 
 
-def get_response_code(entry_id):
+def get_response_code(entry_id: str) -> str | None:
     codes = {
         "InternalError": "internal_server_error",
         "OperationTimeout": "internal_server_error",
@@ -241,8 +258,12 @@
 
 
 def make_error_function(
-    entry_id, entry, is_header, registry_name, namespace_name
-):
+    entry_id: str,
+    entry: t.Dict[str, t.Any],
+    is_header: bool,
+    registry_name: str,
+    namespace_name: str,
+) -> str:
     arg_nonstring_types = {
         "const boost::urls::url_view_base&": {
             "AccessDenied": [1],
@@ -302,6 +323,7 @@
     else:
         out += "\n{\n"
         to_array_type = ""
+        arg_param = "{}"
         if argtypes:
             outargs = []
             for index, typename in enumerate(argtypes):
@@ -325,11 +347,7 @@
                 else:
                     outargs.append(f"arg{index}")
             argstring = ", ".join(outargs)
-
-        if argtypes:
             arg_param = f"std::to_array{to_array_type}({{{argstring}}})"
-        else:
-            arg_param = "{}"
         out += f"    return getLog(redfish::registries::{namespace_name}::Index::{function_name}, {arg_param});"
         out += "\n}\n\n"
     if registry_name == "Base":
@@ -358,7 +376,7 @@
             res = get_response_code(entry_id)
             if res:
                 out += f"    res.result(boost::beast::http::status::{res});\n"
-            args_out = ", ".join([f"arg{x+1}" for x in range(len(argtypes))])
+            args_out = ", ".join([f"arg{x + 1}" for x in range(len(argtypes))])
 
             addMessageToJson = {
                 "PropertyDuplicate": 1,
@@ -394,9 +412,12 @@
 
 
 def create_error_registry(
-    entry, registry_version, registry_name, namespace_name, filename
-):
-    file, json_dict, namespace, url = entry
+    registry_info: RegistryInfo,
+    registry_name: str,
+    namespace_name: str,
+    filename: str,
+) -> None:
+    file, json_dict, namespace, url = registry_info
     base_filename = filename + "_messages"
 
     error_messages_hpp = os.path.join(
@@ -556,7 +577,7 @@
     os.system(f"clang-format -i {error_messages_hpp} {error_messages_cpp}")
 
 
-def make_privilege_registry():
+def make_privilege_registry() -> None:
     path, json_file, type_name, url = make_getter(
         "Redfish_1.5.0_PrivilegeRegistry.json",
         "privilege_registry.hpp",
@@ -565,15 +586,18 @@
     with open(path, "w") as registry:
         registry.write(PRIVILEGE_HEADER)
 
-        privilege_dict = {}
+        privilege_dict: t.Dict[str, t.Tuple[t.Any, str | None]] = {}
         for mapping in json_file["Mappings"]:
             # first pass, identify all the unique privilege sets
             for operation, privilege_list in mapping["OperationMap"].items():
                 privilege_dict[
                     get_privilege_string_from_list(privilege_list)
-                ] = (privilege_list,)
+                ] = (
+                    privilege_list,
+                    None,
+                )
         for index, key in enumerate(privilege_dict):
-            (privilege_list,) = privilege_dict[key]
+            (privilege_list, _) = privilege_dict[key]
             name = get_variable_name_for_privilege_set(privilege_list)
             registry.write(
                 "const std::array<Privileges, {length}> "
@@ -603,15 +627,15 @@
         )
 
 
-def to_pascal_case(text):
+def to_pascal_case(text: str) -> str:
     s = text.replace("_", " ")
-    s = s.split()
+    s1 = s.split()
     if len(text) == 0:
         return text
-    return "".join(i.capitalize() for i in s[0:])
+    return "".join(i.capitalize() for i in s1[0:])
 
 
-def main():
+def main() -> None:
     dmtf_registries = OrderedDict(
         [
             ("base", "1.19.0"),
@@ -647,7 +671,7 @@
     args = parser.parse_args()
 
     registries = set(args.registries.split(","))
-    registries_map = OrderedDict()
+    registries_map: t.OrderedDict[str, RegistryInfo] = OrderedDict()
 
     for registry, version in dmtf_registries.items():
         if registry in registries:
@@ -660,12 +684,11 @@
     if "openbmc" in registries:
         registries_map["openbmc"] = openbmc_local_getter()
 
-    update_registries(registries_map.values())
+    update_registries(list(registries_map.values()))
 
     if "base" in registries_map:
         create_error_registry(
             registries_map["base"],
-            dmtf_registries["base"],
             "Base",
             "base",
             "error",
@@ -673,7 +696,6 @@
     if "heartbeat_event" in registries_map:
         create_error_registry(
             registries_map["heartbeat_event"],
-            dmtf_registries["heartbeat_event"],
             "HeartbeatEvent",
             "heartbeat_event",
             "heartbeat",
@@ -681,7 +703,6 @@
     if "resource_event" in registries_map:
         create_error_registry(
             registries_map["resource_event"],
-            dmtf_registries["resource_event"],
             "ResourceEvent",
             "resource_event",
             "resource",
@@ -689,7 +710,6 @@
     if "task_event" in registries_map:
         create_error_registry(
             registries_map["task_event"],
-            dmtf_registries["task_event"],
             "TaskEvent",
             "task_event",
             "task",