code: def get_input_nodes(
      data: Union[Data, HeteroData, Tuple[FeatureStore, GraphStore]],
      input_nodes: Union[InputNodes, TensorAttr],
      input_id: Optional[Tensor] = None,
  ) -> Tuple[Optional[str], Tensor, Optional[Tensor]]:
      def to_index(nodes, input_id) -> Tuple[Tensor, Optional[Tensor]]:
          if isinstance(nodes, Tensor) and nodes.dtype == torch.bool:
              nodes = nodes.nonzero(as_tuple=False).view(-1)
              if input_id is not None:
                  assert input_id.numel() == nodes.numel()
              else:
                  input_id = nodes
              return nodes, input_id
  
          if not isinstance(nodes, Tensor):
              nodes = torch.tensor(nodes, dtype=torch.long)
  
          if input_id is not None:
              assert input_id.numel() == nodes.numel()
  
          return nodes, input_id
  
      if isinstance(data, Data):
          if input_nodes is None:
              return None, torch.arange(data.num_nodes), None
          return None, *to_index(input_nodes, input_id)
  
      elif isinstance(data, HeteroData):
          assert input_nodes is not None
  
          if isinstance(input_nodes, str):
              return (
                  input_nodes,
                  torch.arange(data[input_nodes].num_nodes),
                  None,
              )
  
          assert isinstance(input_nodes, (list, tuple))
          assert len(input_nodes) == 2
          assert isinstance(input_nodes[0], str)
  
          node_type, input_nodes = input_nodes
          if input_nodes is None:
              return (
                  node_type,
                  torch.arange(data[node_type].num_nodes),
                  None,
              )
          return node_type, *to_index(input_nodes, input_id)
  
      else:  # Tuple[FeatureStore, GraphStore]
          feature_store, graph_store = data
          assert input_nodes is not None
  
          if isinstance(input_nodes, Tensor):
              return None, *to_index(input_nodes, input_id)
  
          if isinstance(input_nodes, str):
              num_nodes = remote_backend_utils.num_nodes(  #
                  feature_store, graph_store, input_nodes
              )
              return input_nodes, torch.arange(num_nodes), None
  
          if isinstance(input_nodes, (list, tuple)):
              assert len(input_nodes) == 2
              assert isinstance(input_nodes[0], str)
  
              node_type, input_nodes = input_nodes
              if input_nodes is None:
                  num_nodes = remote_backend_utils.num_nodes(  #
                      feature_store, graph_store, input_nodes
                  )
                  return node_type, torch.arange(num_nodes), None
  
              return node_type, *to_index(input_nodes, input_id)
  
imports: import copy
  import logging
  import math
  from typing import Any, Dict, Optional, Tuple, Union
  import numpy
  import torch
  from torch import Tensor
  import torch_geometric.typing
  from torch_geometric import EdgeIndex
  from torch_geometric.data import Data, FeatureStore, GraphStore, HeteroData, TensorAttr, remote_backend_utils
  from torch_geometric.data.storage import EdgeStorage, NodeStorage
  from torch_geometric.typing import EdgeType, FeatureTensorType, InputEdges, InputNodes, NodeType, OptTensor, SparseTensor, TensorFrame
label_desc: Use image node_id 8 for calling a global function with example usage: get_input_nodes(data, input_nodes, input_id) and returns: nodes,  input_id, None,  unknown, nodes,  input_id, None,  torch,  None, node_type,  unknown, input_nodes,  torch,  None, node_type,  torch,  None, None,  unknown, input_nodes,  torch,  None, node_type,  unknown, node_type,  torch,  None