code: def datasets_from_paths(
      train_list,
      test_list,
      complete_test_set_only=False,
      train_transform=None,
      train_target_transform=None,
      test_transform=None,
      test_target_transform=None,
  ):
      """
      This utility takes, for each dataset to generate, a list of tuples each
      containing two elements: the full path to the pattern and its class label.
      Optionally, the tuple may contain a third element describing the bounding
      box to use for cropping.
  
      This is equivalent to `datasets_from_filelists`, which description
      contains more details on the behaviour of this utility. The two utilities
      differ in which `datasets_from_filelists` accepts paths to Caffe-style
      filelists while this one is able to create the datasets from an in-memory
      list.
  
      Note: this utility may try to detect (and strip) the common root path of
      all patterns in order to save some RAM memory.
  
      :param train_list: list of lists. Each list must contain tuples of two
          elements: the full path to the pattern and its class label. Optionally,
          the tuple may contain a third element describing the bounding box to use
          for cropping (top, left, height, width).
      :param test_list: list of lists. Each list must contain tuples of two
          elements: the full path to the pattern and its class label. Optionally,
          the tuple may contain a third element describing the bounding box to use
          for cropping (top, left, height, width). It can be also a single list
          when the test dataset is the same for each experience.
      :param complete_test_set_only: if True, test_list must contain a single list
          that will serve as the complete test set. If False, train_list and
          test_list must describe the same amount of datasets. Defaults to False.
      :param train_transform: The transformation to apply to training patterns.
          Defaults to None.
      :param train_target_transform: The transformation to apply to training
          patterns targets. Defaults to None.
      :param test_transform: The transformation to apply to test patterns.
          Defaults to None.
      :param test_target_transform: The transformation to apply to test
          patterns targets. Defaults to None.
  
      :return: A list of tuples (train dataset, test dataset).
      """
  
      if complete_test_set_only:
          # Check if the single dataset was passed as [Tuple1, Tuple2, ...]
          # or as [[Tuple1, Tuple2, ...]]
          if not isinstance(test_list[0], tuple):
              if len(test_list) > 1:
                  raise ValueError(
                      "When complete_test_set_only is True, test_list must "
                      "be a single list of tuples or a nested list containing "
                      "a single lis of tuples"
                  )
              else:
                  test_list = test_list[0]
          else:
              test_list = [test_list]
      else:
          if len(test_list) != len(train_list):
              raise ValueError(
                  "When complete_test_set_only is False, test_list and "
                  "train_list must contain the same number of elements."
              )
  
      transform_groups = dict(
          train=(train_transform, train_target_transform),
          eval=(test_transform, test_target_transform),
      )
  
      common_root = None
  
      # Detect common root
      try:
          all_paths = [
              pattern_tuple[0]
              for exp_list in train_list
              for pattern_tuple in exp_list
          ] + [
              pattern_tuple[0]
              for exp_list in test_list
              for pattern_tuple in exp_list
          ]
  
          common_root = os.path.commonpath(all_paths)
      except ValueError:
          # commonpath may throw a ValueError in different situations!
          # See the official documentation for more details
          pass
  
      if (
          common_root is not None
          and len(common_root) > 0
          and common_root != "/"
      ):
          has_common_root = True
          common_root = str(common_root)
      else:
          has_common_root = False
          common_root = None
  
      if has_common_root:
          # print(f'Common root found: {common_root}!')
          # All paths have a common filesystem root
          # Remove it from all paths!
          single_path_case = False
          tr_list = list()
          te_list = list()
  
          for idx_exp_list in range(len(train_list)):
              if single_path_case:
                  break
              st_list = list()
              for x in train_list[idx_exp_list]:
                  rel = os.path.relpath(x[0], common_root)
                  if len(rel) == 0 or rel == ".":
                      # May happen if the dataset has a single path
                      single_path_case = True
                      break
                  st_list.append((rel, *x[1:]))
              tr_list.append(st_list)
  
          for idx_exp_list in range(len(test_list)):
              if single_path_case:
                  break
              st_list = list()
              for x in test_list[idx_exp_list]:
                  rel = os.path.relpath(x[0], common_root)
                  if len(rel) == 0 or rel == ".":
                      # May happen if the dataset has a single path
                      single_path_case = True
                      break
                  st_list.append((rel, *x[1:]))
              te_list.append(st_list)
          if not single_path_case:
              train_list = tr_list
              test_list = te_list
          else:
              has_common_root = False
              common_root = None
  
      from avalanche.benchmarks.utils import (
          as_taskaware_classification_dataset,
      )
  
      train_inc_datasets = [
          as_taskaware_classification_dataset(
              PathsDataset(common_root, tr_flist),
              transform_groups=transform_groups,
              initial_transform_group="train",
          )
          for tr_flist in train_list
      ]
      test_inc_datasets = [
          as_taskaware_classification_dataset(
              PathsDataset(common_root, te_flist),
              transform_groups=transform_groups,
              initial_transform_group="eval",
          )
          for te_flist in test_list
      ]
  
      return train_inc_datasets, test_inc_datasets
  
imports: from pathlib import Path
  from typing import Callable, Generic, List, Tuple, Sequence, Optional, TypeVar, Union
  import torch.utils.data
  from PIL import Image
  import os
  import os.path
  from torch import Tensor
  from torchvision.transforms.functional import crop
  from .transform_groups import XTransform, YTransform
label_desc: Use image node_id 4 for calling a global function with example usage: datasets_from_paths(train_list, test_list, complete_test_set_only, train_transform, train_target_transform, test_transform, test_target_transform) and returns: train_inc_datasets,  test_inc_datasets