code: def assert_dataclass_signature_match(
      cls: "class_type",
      datacls: "dataclass",
      ignore_args: Optional[List[str]] = None,
      remap_args: Optional[Dict[str, str]] = None,
  ):
      """
      Analyses the signature of a provided class and its respective data class,
      asserting that the dataclass signature matches the class __init__ signature.
  
      Note:
          This is not a value based check. This function only checks if all argument
          names exist on both class and dataclass and logs mismatches.
  
      Args:
          cls: Any class type - but not an instance of a class. Pass type(x) where x is an instance
              if class type is not easily available.
          datacls: A corresponding dataclass for the above class.
          ignore_args: (Optional) A list of string argument names which are forcibly ignored,
              even if mismatched in the signature. Useful when a dataclass is a superset of the
              arguments of a class.
          remap_args: (Optional) A dictionary, mapping an argument name that exists (in either the
              class or its dataclass), to another name. Useful when argument names are mismatched between
              a class and its dataclass due to indirect instantiation via a helper method.
  
      Returns:
          A tuple containing information about the analysis:
          1) A bool value which is True if the signatures matched exactly / after ignoring values.
              False otherwise.
          2) A set of arguments names that exist in the class, but *do not* exist in the dataclass.
              If exact signature match occurs, this will be None instead.
          3) A set of argument names that exist in the data class, but *do not* exist in the class itself.
              If exact signature match occurs, this will be None instead.
      """
      class_sig = inspect.signature(cls.__init__)
  
      class_params = dict(**class_sig.parameters)
      class_params.pop("self")
  
      dataclass_sig = inspect.signature(datacls)
  
      dataclass_params = dict(**dataclass_sig.parameters)
      dataclass_params.pop("_target_", None)
  
      class_params = set(class_params.keys())
      dataclass_params = set(dataclass_params.keys())
  
      if remap_args is not None:
          for original_arg, new_arg in remap_args.items():
              if original_arg in class_params:
                  class_params.remove(original_arg)
                  class_params.add(new_arg)
                  logging.info(
                      f"Remapped {original_arg} -> {new_arg} in {cls.__name__}"
                  )
  
              if original_arg in dataclass_params:
                  dataclass_params.remove(original_arg)
                  dataclass_params.add(new_arg)
                  logging.info(
                      f"Remapped {original_arg} -> {new_arg} in {datacls.__name__}"
                  )
  
      if ignore_args is not None:
          ignore_args = set(ignore_args)
  
          class_params = class_params - ignore_args
          dataclass_params = dataclass_params - ignore_args
          logging.info(f"Removing ignored arguments - {ignore_args}")
  
      intersection = set.intersection(class_params, dataclass_params)
      subset_cls = class_params - intersection
      subset_datacls = dataclass_params - intersection
  
      if (
          (len(class_params) != len(dataclass_params))
          or len(subset_cls) > 0
          or len(subset_datacls) > 0
      ):
          logging.error(
              f"Class {cls.__name__} arguments do not match "
              f"Dataclass {datacls.__name__}!"
          )
  
          if len(subset_cls) > 0:
              logging.error(
                  f"Class {cls.__name__} has additional arguments :\n"
                  f"{subset_cls}"
              )
  
          if len(subset_datacls):
              logging.error(
                  f"Dataclass {datacls.__name__} has additional arguments :\n{subset_datacls}"
              )
  
          return False, subset_cls, subset_datacls
  
      else:
          return True, None, None
  
file_path: NeMo/nemo/utils/config_utils.py
imports: import copy
  import inspect
  from dataclasses import is_dataclass
  from typing import Dict, List, Optional
  from nemo.utils import logging
label_desc: Use image node_id 4 for calling a global function with example usage: assert_dataclass_signature_match(cls, datacls, ignore_args, remap_args) and returns: False,  subset_cls,  subset_datacls, True,  None,  None