docs: def insensitive_comparison(item1, item2, type_insensitive=False, string_insensitive=False):
      """Compare two items without regard to order.
  
      The following rules are used to determine equivalence:
          * Items that are not of the same type can be equivalent only when ``type_insensitive=True``.
          * Mapping objects are equal iff the keys in each item exist in both items and have
            the same value (with the same ``insensitive_comparison``).
          * Other containers except for strings are equal iff every element in each item exists
            in both items (duplicate items must be present the same number of times).
          * Containers must be ``Iterable`` to be compared in this way.
          * Non-containers are equivalent if the equality operator returns ``True``.
          * Strings are treated as non-containers when ``string_insensitive=False``,
            and are treated as containers when ``string_insensitive=True``. When treated as
            containers, each (case-insensitive) character is treated as an element and
            whitespace is ignored.
          * If the items are in different categories above, they are never equivalent,
            even when ``type_insensitive=True``.
  
      Arguments:
          item1 (any): The first item to compare.
          item2 (any): The second item to compare.
          type_insensitive (bool): When ``True``, items of a different type are not automatically
                  unequivalent. When ``False``, items must be the same type to be equivalent.
                  **Default**: ``False``.
          string_insensitive (bool): When ``True``, strings are treated as containers, with each
                  character being one element in the container.
                  When ``False``, strings are treated as non-containers and compared directly.
                  **Default**: ``False``.
  
      Returns:
          bool: ``True`` iff the two items are equivalent (see above).
                  ``False`` otherwise.
      """
      # If type-sensitive, check types
      if not type_insensitive and type(item1) != type(item2):
          return False
  
      # Handle Mapping objects (dict)
      if isinstance(item1, Mapping):
          # Second item must be Mapping
          if not isinstance(item2, Mapping):
              return False
          # Items must have the same number of elements
          if not len(item1) == len(item2):
              return False
          # Keys must be the same
          if not insensitive_comparison(list(item1.keys()), list(item2.keys()),
                                        type_insensitive=True):
              return False
          # Each key's value must be the same
          # We can just check item1.items because the keys are the same
          for key, val in item1.items():
              if not insensitive_comparison(item1[key], item2[key],
                                            type_insensitive=type_insensitive,
                                            string_insensitive=string_insensitive):
                  return False
          # Keys and values are the same
          return True
      # Handle strings
      elif isinstance(item1, str):
          # Second item must be string
          if not isinstance(item2, str):
              return False
          # Items must have the same number of elements (except string_insensitive)
          if not len(item1) == len(item2) and not string_insensitive:
              return False
          # If we're insensitive to case, spaces, and order, compare characters
          if string_insensitive:
              # If the string is one character long, skip additional comparison
              if len(item1) <= 1:
                  return item1.lower() == item2.lower()
              # Make strings into containers (lists) and discard whitespace
              item1_list = [c for c in item1.lower() if not c.isspace()]
              item2_list = [c for c in item2.lower() if not c.isspace()]
              # The insensitive args shouldn't matter, but they're here just in case
              return insensitive_comparison(item1_list, item2_list,
                                            type_insensitive=type_insensitive,
                                            string_insensitive=string_insensitive)
          # Otherwise, case and order matter
          else:
              return item1 == item2
      # Handle other Iterable Containers
      elif isinstance(item1, Container) and isinstance(item1, Iterable):
          # Second item must be an Iterable Container
          if not isinstance(item2, Container) or not isinstance(item2, Iterable):
              return False
          # Items must have the same number of elements
          if not len(item1) == len(item2):
              return False
          # Every element in item1 must be in item2, and vice-versa
          # Painfully slow, but unavoidable for deep comparison
          # Each match in item1 removes the corresponding element from item2_copy
          # If they're the same, item2_copy should be empty at the end,
          #   unless a .remove() failed, in which case we have to re-match using item2
          item2_copy = list(deepcopy(item2))
          remove_failed = False
          for elem in item1:
              matched = False
              # Try every element
              for candidate in item2:
                  # If comparison succeeds, flag a match, remove match from copy, and dump out
                  if insensitive_comparison(elem, candidate,
                                            type_insensitive=type_insensitive,
                                            string_insensitive=string_insensitive):
                      matched = True
                      try:
                          item2_copy.remove(candidate)
                      except ValueError:  # list.remove(x): x not in list
                          remove_failed = True
                      break
              # One failure indicates unequivalence
              if not matched:
                  return False
          # If all removes succeeded, we can shortcut checking all item2 elements in item1
          if not remove_failed:
              # If the Containers are equivalent, all elements in item2_copy should be removed
              # Otherwise
              return len(item2_copy) == 0
          # If something failed, we have to verify all of item2
          # We can't assume item2 != item1, because removal is comparative
          else:
              for elem in item2:
                  matched = False
                  # Try every element
                  for candidate in item1:
                      # If comparison succeeds, flag a match, remove match from copy, and dump out
                      if insensitive_comparison(elem, candidate,
                                                type_insensitive=type_insensitive,
                                                string_insensitive=string_insensitive):
                          matched = True
                          break
                  # One failure indicates unequivalence
                  if not matched:
                      return False
              # All elements have a match
              return True
      # Handle otherwise unhandled type (catchall)
      else:
          return item1 == item2