code: def deep_update(
      original: dict,
      new_dict: dict,
      new_keys_allowed: bool = False,
      allow_new_subkey_list: Optional[List[str]] = None,
      override_all_if_type_changes: Optional[List[str]] = None,
      override_all_key_list: Optional[List[str]] = None,
  ) -> dict:
      """Updates original dict with values from new_dict recursively.
  
      If new key is introduced in new_dict, then if new_keys_allowed is not
      True, an error will be thrown. Further, for sub-dicts, if the key is
      in the allow_new_subkey_list, then new subkeys can be introduced.
  
      Args:
          original: Dictionary with default values.
          new_dict: Dictionary with values to be updated
          new_keys_allowed: Whether new keys are allowed.
          allow_new_subkey_list: List of keys that
              correspond to dict values where new subkeys can be introduced.
              This is only at the top level.
          override_all_if_type_changes: List of top level
              keys with value=dict, for which we always simply override the
              entire value (dict), iff the "type" key in that value dict changes.
          override_all_key_list: List of top level keys
              for which we override the entire value if the key is in the new_dict.
      """
      allow_new_subkey_list = allow_new_subkey_list or []
      override_all_if_type_changes = override_all_if_type_changes or []
      override_all_key_list = override_all_key_list or []
  
      for k, value in new_dict.items():
          if k not in original and not new_keys_allowed:
              raise Exception(
                  "Unknown config parameter `{}` ".format(k)
              )
  
          # Both orginal value and new one are dicts.
          if (
              isinstance(original.get(k), dict)
              and isinstance(value, dict)
              and k not in override_all_key_list
          ):
              # Check old type vs old one. If different, override entire value.
              if (
                  k in override_all_if_type_changes
                  and "type" in value
                  and "type" in original[k]
                  and value["type"] != original[k]["type"]
              ):
                  original[k] = value
              # Allowed key -> ok to add new subkeys.
              elif k in allow_new_subkey_list:
                  deep_update(
                      original[k],
                      value,
                      True,
                      override_all_key_list=override_all_key_list,
                  )
              # Non-allowed key.
              else:
                  deep_update(
                      original[k],
                      value,
                      new_keys_allowed,
                      override_all_key_list=override_all_key_list,
                  )
          # Original value not a dict OR new value not a dict:
          # Override entire value.
          else:
              original[k] = value
      return original
  
file_path: ray/python/ray/_private/dict.py
imports: import copy
  from collections import deque
  from collections.abc import Mapping, Sequence
  from typing import Dict, List, Optional, TypeVar, Union
  from ray.util.annotations import Deprecated
label_desc: Use image node_id 2 for calling a global function with example usage: deep_update(original, new_dict, new_keys_allowed, allow_new_subkey_list, override_all_if_type_changes, override_all_key_list) and returns: original