code: def test_hetero_neighbor_loader_basic(subgraph_type, dtype):
      if dtype != torch.int64 and not torch_geometric.typing.WITH_PT20:
          return
      induced = SubgraphType.induced
      if (
          subgraph_type == SubgraphType.induced
          and not WITH_TORCH_SPARSE
      ):
          return
      if dtype != torch.int64 and (
          not WITH_PYG_LIB or subgraph_type == induced
      ):
          return
  
      torch.manual_seed(12345)
  
      data = HeteroData()
  
      data["paper"].x = torch.arange(100)
      data["author"].x = torch.arange(100, 300)
  
      edge_index = get_random_edge_index(100, 100, 500, dtype)
      data["paper", "paper"].edge_index = edge_index
      data["paper", "paper"].edge_attr = torch.arange(500)
      edge_index = get_random_edge_index(100, 200, 1000, dtype)
      data["paper", "author"].edge_index = edge_index
      data["paper", "author"].edge_attr = torch.arange(500, 1500)
      edge_index = get_random_edge_index(200, 100, 1000, dtype)
      data["author", "paper"].edge_index = edge_index
      data["author", "paper"].edge_attr = torch.arange(1500, 2500)
  
      r1, c1 = data["paper", "paper"].edge_index
      r2, c2 = data["paper", "author"].edge_index + torch.tensor(
          [[0], [100]]
      )
      r3, c3 = data["author", "paper"].edge_index + torch.tensor(
          [[100], [0]]
      )
  
      batch_size = 20
  
      with pytest.raises(
          ValueError, match="hops must be the same across all"
      ):
          loader = NeighborLoader(
              data,
              num_neighbors={
                  ("paper", "to", "paper"): [-1],
                  ("paper", "to", "author"): [-1, -1],
                  ("author", "to", "paper"): [-1, -1],
              },
              input_nodes="paper",
              batch_size=batch_size,
              subgraph_type=subgraph_type,
          )
          next(iter(loader))
  
      loader = NeighborLoader(
          data,
          num_neighbors=[10] * 2,
          input_nodes="paper",
          batch_size=batch_size,
          subgraph_type=subgraph_type,
      )
  
      assert str(loader) == "NeighborLoader()"
      assert len(loader) == (100 + batch_size - 1) // batch_size
  
      for batch in loader:
          assert isinstance(batch, HeteroData)
  
          # Test node type selection:
          assert set(batch.node_types) == {"paper", "author"}
  
          assert batch["paper"].n_id.size() == (
              batch["paper"].num_nodes,
          )
          assert batch["paper"].x.size(0) <= 100
          assert batch["paper"].input_id.numel() == batch_size
          assert batch["paper"].batch_size == batch_size
          assert (
              batch["paper"].x.min() >= 0
              and batch["paper"].x.max() < 100
          )
  
          assert batch["author"].n_id.size() == (
              batch["author"].num_nodes,
          )
          assert batch["author"].x.size(0) <= 200
          assert (
              batch["author"].x.min() >= 100
              and batch["author"].x.max() < 300
          )
  
          # Test edge type selection:
          assert set(batch.edge_types) == {
              ("paper", "to", "paper"),
              ("paper", "to", "author"),
              ("author", "to", "paper"),
          }
  
          for edge_type, edge_index in batch.edge_index_dict.items():
              src, _, dst = edge_type
              assert isinstance(edge_index, EdgeIndex)
              edge_index.validate()
              size = (batch[src].num_nodes, batch[dst].num_nodes)
              assert edge_index.sparse_size() == size
              assert edge_index.sort_order == "col"
  
          row, col = batch["paper", "paper"].edge_index
          assert row.min() >= 0 and row.max() < batch["paper"].num_nodes
          assert col.min() >= 0 and col.max() < batch["paper"].num_nodes
  
          if subgraph_type != SubgraphType.bidirectional:
              assert batch["paper", "paper"].e_id.size() == (
                  row.numel(),
              )
              value = batch["paper", "paper"].edge_attr
              assert value.min() >= 0 and value.max() < 500
  
              assert is_subset(
                  batch["paper", "paper"].edge_index.to(torch.int64),
                  data["paper", "paper"].edge_index.to(torch.int64),
                  batch["paper"].x,
                  batch["paper"].x,
              )
          elif subgraph_type != SubgraphType.directional:
              assert "e_id" not in batch["paper", "paper"]
              assert "edge_attr" not in batch["paper", "paper"]
  
              assert is_undirected(batch["paper", "paper"].edge_index)
  
          row, col = batch["paper", "author"].edge_index
          assert row.min() >= 0 and row.max() < batch["paper"].num_nodes
          assert (
              col.min() >= 0 and col.max() < batch["author"].num_nodes
          )
  
          if subgraph_type != SubgraphType.bidirectional:
              assert batch["paper", "author"].e_id.size() == (
                  row.numel(),
              )
              value = batch["paper", "author"].edge_attr
              assert value.min() >= 500 and value.max() < 1500
  
              assert is_subset(
                  batch["paper", "author"].edge_index.to(torch.int64),
                  data["paper", "author"].edge_index.to(torch.int64),
                  batch["paper"].x,
                  batch["author"].x - 100,
              )
          elif subgraph_type != SubgraphType.directional:
              assert "e_id" not in batch["paper", "author"]
              assert "edge_attr" not in batch["paper", "author"]
  
              edge_index1 = batch["paper", "author"].edge_index
              edge_index2 = batch["author", "paper"].edge_index
              assert torch.equal(
                  edge_index1,
                  sort_edge_index(
                      edge_index2.flip([0]), sort_by_row=False
                  ),
              )
  
          row, col = batch["author", "paper"].edge_index
          assert (
              row.min() >= 0 and row.max() < batch["author"].num_nodes
          )
          assert col.min() >= 0 and col.max() < batch["paper"].num_nodes
  
          if subgraph_type != SubgraphType.bidirectional:
              assert batch["author", "paper"].e_id.size() == (
                  row.numel(),
              )
              value = batch["author", "paper"].edge_attr
              assert value.min() >= 1500 and value.max() < 2500
  
              assert is_subset(
                  batch["author", "paper"].edge_index.to(torch.int64),
                  data["author", "paper"].edge_index.to(torch.int64),
                  batch["author"].x - 100,
                  batch["paper"].x,
              )
          elif subgraph_type != SubgraphType.directional:
              assert "e_id" not in batch["author", "paper"]
              assert "edge_attr" not in batch["author", "paper"]
  
              edge_index1 = batch["author", "paper"].edge_index
              edge_index2 = batch["paper", "author"].edge_index
              assert torch.equal(
                  edge_index1,
                  sort_edge_index(
                      edge_index2.flip([0]), sort_by_row=False
                  ),
              )
  
          # Test for isolated nodes (there shouldn't exist any):
          assert not batch.has_isolated_nodes()
  
imports: import os.path
  import numpy
  import pytest
  import torch
  import torch_geometric.typing
  from torch_geometric import EdgeIndex
  from torch_geometric.data import Data, HeteroData
  from torch_geometric.loader import NeighborLoader
  from torch_geometric.nn import GraphConv, to_hetero
  from torch_geometric.sampler.base import SubgraphType
  from torch_geometric.testing import MyFeatureStore, MyGraphStore, get_random_edge_index, get_random_tensor_frame, onlyLinux, onlyNeighborSampler, onlyOnline, withCUDA, withPackage
  from torch_geometric.typing import WITH_EDGE_TIME_NEIGHBOR_SAMPLE, WITH_PYG_LIB, WITH_TORCH_SPARSE, WITH_WEIGHTED_NEIGHBOR_SAMPLE, TensorFrame
  from torch_geometric.utils import is_undirected, sort_edge_index, to_torch_csr_tensor, to_undirected
label_desc: Use image node_id 3 for calling a global function with example usage: test_hetero_neighbor_loader_basic(subgraph_type, dtype) without return types