code: def _merge_with_dotlist(
      config: DictConfig,
      opts: List[str],
      skip_missing: bool = False,
      log_info: bool = True,
  ):
      # TODO: To remove technical debt, a possible solution is to use
      # struct mode to update with dotlist OmegaConf node. Look into this
      # in next iteration
      # TODO: Simplify this function
      if opts is None:
          opts = []
  
      if len(opts) == 0:
          return config
  
      # Support equal e.g. model=visual_bert for better future hydra support
      has_equal = opts[0].find("=") != -1
      if has_equal:
          opt_values = [opt.split("=", maxsplit=1) for opt in opts]
          if not all(len(opt) == 2 for opt in opt_values):
              for opt in opt_values:
                  assert len(opt) == 2, f"{opt} has no value"
      else:
          assert (
              len(opts) % 2 == 0
          ), "Number of opts should be multiple of 2"
          opt_values = zip(opts[0::2], opts[1::2])
  
      for opt, value in opt_values:
          if opt == "dataset":
              opt = "datasets"
  
          splits = opt.split(".")
          current = config
          for idx, field in enumerate(splits):
              array_index = -1
              if field.find("[") != -1 and field.find("]") != -1:
                  stripped_field = field[: field.find("[")]
                  array_index = int(
                      field[field.find("[") + 1 : field.find("]")]
                  )
              else:
                  stripped_field = field
              if stripped_field not in current:
                  if skip_missing is True:
                      break
                  raise AttributeError(
                      "While updating configuration"
                      " option {} is missing from"
                      " configuration at field {}".format(
                          opt, stripped_field
                      )
                  )
              if isinstance(
                  current[stripped_field], collections.abc.Mapping
              ):
                  current = current[stripped_field]
              elif (
                  isinstance(
                      current[stripped_field], collections.abc.Sequence
                  )
                  and array_index != -1
              ):
                  try:
                      current_value = current[stripped_field][
                          array_index
                      ]
                  except OCErrors.ConfigIndexError:
                      if skip_missing:
                          break
                      raise
  
                  # Case where array element to be updated is last element
                  if (
                      not isinstance(
                          current_value,
                          (
                              collections.abc.Mapping,
                              collections.abc.Sequence,
                          ),
                      )
                      or idx == len(splits) - 1
                  ):
                      if log_info:
                          logger.info(
                              f"Overriding option {opt} to {value}"
                          )
                      current[stripped_field][
                          array_index
                      ] = _decode_value(value)
                  else:
                      # Otherwise move on down the chain
                      current = current_value
              else:
                  if idx == len(splits) - 1:
                      if log_info:
                          logger.info(
                              f"Overriding option {opt} to {value}"
                          )
                      current[stripped_field] = _decode_value(value)
                  else:
                      if skip_missing:
                          break
  
                      raise AttributeError(
                          "While updating configuration",
                          "option {} is not present "
                          "after field {}".format(opt, stripped_field),
                      )
  
      return config
  
imports: import collections
  import json
  import logging
  import os
  import warnings
  from ast import literal_eval
  from typing import List
  import torch
  from mmf.common.registry import registry
  from mmf.utils.env import import_user_module
  from mmf.utils.file_io import PathManager
  from mmf.utils.general import get_absolute_path, get_mmf_root
  from omegaconf import DictConfig, errors, OmegaConf
label_desc: Use image node_id 9 for calling a global function with example usage: _merge_with_dotlist(config, opts, skip_missing, log_info) and returns: config, config