class_docstr: An interface which endows module with neural types
class_docstr_tok: ["An","interface","which","endows","module","with","neural","types"]
docstr: This function does a few things.
  
  1) It ensures that len(self.input_types <non-optional>) <= len(kwargs) <= len(self.input_types).
  2) For each (keyword name, keyword value) passed as input to the wrapped function:
      - Check if the keyword name exists in the list of valid self.input_types names.
      - Check if keyword value has the `neural_type` property.
          - If it does, then perform a comparative check and assert that neural types
              are compatible (SAME or GREATER).
      - Check if keyword value is a container type (list or tuple). If yes,
          then perform the elementwise test of neural type above on each element
          of the nested structure, recursively.
  
  Args:
      input_types: Either the `input_types` defined at class level, or the local function
          overridden type definition.
      ignore_collections: For backward compatibility, container support can be disabled explicitly
          using this flag. When set to True, all nesting is ignored and nest-depth checks are skipped.
      kwargs: Dictionary of argument_name:argument_value pairs passed to the wrapped
          function upon call.
docstr_tok: ["This","function","does","a","few","things",".","1",")","It","ensures","that","len","(","self.input_types","<","non-optional",">",")","<","=","len","(","kwargs",")","<","=","len","(","self.input_types",")",".","2",")","For","each","(","keyword","name",",","keyword","value",")","passed","as","input","to","the","wrapped","function",":","-","Check","if","the","keyword","name","exists","in","the","list","of","valid","self.input_types","names",".","-","Check","if","keyword","value","has","the","`","neural_type","`","property",".","-","If","it","does",",","then","perform","a","comparative","check","and","assert","that","neural","types","are","compatible","(","SAME","or","GREATER",")",".","-","Check","if","keyword","value","is","a","container","type","(","list","or","tuple",")",".","If","yes",",","then","perform","the","elementwise","test","of","neural","type","above","on","each","element","of","the","nested","structure",",","recursively",".","Args",":","input_types",":","Either","the","`","input_types","`","defined","at","class","level",",","or","the","local","function","overridden","type","definition",".","ignore_collections",":","For","backward","compatibility",",","container","support","can","be","disabled","explicitly","using","this","flag",".","When","set","to","True",",","all","nesting","is","ignored","and","nest-depth","checks","are","skipped",".","kwargs",":","Dictionary","of","argument_name",":","argument_value","pairs","passed","to","the","wrapped","function","upon","call","."]
code: def _validate_input_types(
      self, input_types=None, ignore_collections=False, **kwargs
  ):
      """
      This function does a few things.
  
      1) It ensures that len(self.input_types <non-optional>) <= len(kwargs) <= len(self.input_types).
      2) For each (keyword name, keyword value) passed as input to the wrapped function:
          - Check if the keyword name exists in the list of valid self.input_types names.
          - Check if keyword value has the `neural_type` property.
              - If it does, then perform a comparative check and assert that neural types
                  are compatible (SAME or GREATER).
          - Check if keyword value is a container type (list or tuple). If yes,
              then perform the elementwise test of neural type above on each element
              of the nested structure, recursively.
  
      Args:
          input_types: Either the `input_types` defined at class level, or the local function
              overridden type definition.
          ignore_collections: For backward compatibility, container support can be disabled explicitly
              using this flag. When set to True, all nesting is ignored and nest-depth checks are skipped.
          kwargs: Dictionary of argument_name:argument_value pairs passed to the wrapped
              function upon call.
      """
      # TODO: Properly implement this
      if input_types is not None:
          # Precompute metadata
          metadata = TypecheckMetadata(
              original_types=input_types,
              ignore_collections=ignore_collections,
          )
  
          total_input_types = len(input_types)
          mandatory_input_types = len(metadata.mandatory_types)
  
          # Allow number of input arguments to be <= total input neural types.
          if (
              len(kwargs) < mandatory_input_types
              or len(kwargs) > total_input_types
          ):
              raise TypeError(
                  f"Number of input arguments provided ({len(kwargs)}) is not as expected. Function has "
                  f"{total_input_types} total inputs with {mandatory_input_types} mandatory inputs."
              )
  
          for key, value in kwargs.items():
              # Check if keys exists in the defined input types
              if key not in input_types:
                  raise TypeError(
                      f"Input argument {key} has no corresponding input_type match. "
                      f"Existing input_types = {input_types.keys()}"
                  )
  
              # Perform neural type check
              if hasattr(
                  value, "neural_type"
              ) and not metadata.base_types[key].compare(
                  value.neural_type
              ) in (
                  NeuralTypeComparisonResult.SAME,
                  NeuralTypeComparisonResult.GREATER,
              ):
                  error_msg = [
                      f"{input_types[key].compare(value.neural_type)} :",
                      f"Input type expected : {input_types[key]}",
                      f"Input type found : {value.neural_type}",
                      f"Argument: {key}",
                  ]
                  for i, dict_tuple in enumerate(
                      metadata.base_types[
                          key
                      ].elements_type.type_parameters.items()
                  ):
                      error_msg.insert(
                          i + 2,
                          f"  input param_{i} : {dict_tuple[0]}: {dict_tuple[1]}",
                      )
                  for i, dict_tuple in enumerate(
                      value.neural_type.elements_type.type_parameters.items()
                  ):
                      error_msg.append(
                          f"  input param_{i} : {dict_tuple[0]}: {dict_tuple[1]}"
                      )
                  raise TypeError("\n".join(error_msg))
  
              # Perform input ndim check
              if hasattr(value, "shape"):
                  value_shape = value.shape
                  type_shape = metadata.base_types[key].axes
                  name = key
  
                  if type_shape is not None and len(value_shape) != len(
                      type_shape
                  ):
                      raise TypeError(
                          f"Input shape mismatch occured for {name} in module {self.__class__.__name__} : \n"
                          f"Input shape expected = {metadata.base_types[key].axes} | \n"
                          f"Input shape found : {value_shape}"
                      )
  
              # Perform recursive neural type check for homogeneous elements
              elif isinstance(value, list) or isinstance(value, tuple):
                  for ind, val in enumerate(value):
                      """
                      This initiates a DFS, tracking the depth count as it goes along the nested structure.
                      Initial depth is 1 as we consider the current loop to be the 1st step inside the nest.
                      """
                      self.__check_neural_type(
                          val, metadata, depth=1, name=key
                      )
  
imports: import hashlib
  import inspect
  import traceback
  from abc import ABC, abstractmethod
  from contextlib import contextmanager
  from dataclasses import dataclass, field
  from enum import Enum
  from functools import total_ordering
  from pathlib import Path
  from typing import Dict, Iterable, List, Optional, Tuple, Union
  import hydra
  import torch
  import wrapt
  from huggingface_hub import HfApi, HfFolder, ModelFilter, hf_hub_download
  from huggingface_hub.hf_api import ModelInfo
  from omegaconf import DictConfig, OmegaConf
  import nemo
  from nemo.core.connectors.save_restore_connector import SaveRestoreConnector
  from nemo.core.neural_types import NeuralType, NeuralTypeComparisonResult
  from nemo.utils import logging
  from nemo.utils.cloud import maybe_download_from_cloud
  from nemo.utils.data_utils import resolve_cache_dir
  from nemo.utils.model_utils import import_class_by_path, maybe_update_config_version
label_desc: Use image node_id 3 for calling the Typing obj's underlying member method code with example usage: obj._validate_input_types(input_types, ignore_collections) without return types