docs: def get_pretty_type_str(object_type) -> str:
      """
      Utility method to check if a type is a subclass of typing.{List,Dict,Set,Tuple}. In that case returns a
      user-friendly character string with the inner item types, such as Dict[str, int].
  
      :param object_type:
      :return: type.__name__ if type is not a subclass of typing.{List,Dict,Set,Tuple}, otherwise
      type__name__[list of inner_types.__name__]
      """
  
      try:
          # DO NOT resolve forward references otherwise this can lead to infinite recursion
          contents_item_type, contents_key_type = _extract_collection_base_type(object_type, resolve_fwd_refs=False)
          if isinstance(contents_item_type, tuple):
              return object_type.__name__ + '[' \
                     + ', '.join([get_pretty_type_str(item_type) for item_type in contents_item_type]) + ']'
          else:
              if contents_key_type is not None:
                  return object_type.__name__ + '[' + get_pretty_type_str(contents_key_type) + ', ' \
                         + get_pretty_type_str(contents_item_type) + ']'
              elif contents_item_type is not None:
                  return object_type.__name__ + '[' + get_pretty_type_str(contents_item_type) + ']'
      except Exception as e:
          pass
  
      if is_union_type(object_type):
          return 'Union[' + ', '.join([get_pretty_type_str(item_type) 
                                       for item_type in get_args(object_type, evaluate=True)]) + ']'
      elif is_typevar(object_type):
          # typevars usually do not display their namespace so str() is compact. And it displays the cov/contrav symbol
          return str(object_type)
      else:
          try:
              return object_type.__name__
          except:
              return str(object_type)