docs: def dict_str(dict_, **dictkw):
      r"""
      Makes a pretty printable / human-readable string representation of a
      dictionary. In most cases this string could be evaled.
  
      Args:
          dict_ (dict_): a dictionary
  
      Args:
          dict_ (dict_):  a dictionary
          **dictkw: stritems, strkeys, strvals, nl, newlines, truncate, nobr,
                    nobraces, align, trailing_sep, explicit, itemsep,
                    truncatekw, sorted_, indent_, key_order, precision,
                    with_comma, key_order_metric, maxlen, recursive, use_numpy,
                    with_dtype, force_dtype, packed
  
      Kwargs:
          sorted_ (None): returns str sorted by a metric (default = None)
          nl (int): prefered alias for newline. can be a coundown variable
              (default = None)
          key_order (None): overrides default ordering (default = None)
          key_order_metric (str): special sorting of items. Accepted values:
                  None, 'strlen', 'val'
          precision (int): (default = 8)
          explicit (int): can be a countdown variable. if True, uses
              dict(a=b) syntax instead of {'a': b}
          nobr (bool): removes outer braces (default = False)
  
      Ignore:
          python -m utool.util_inspect recursive_parse_kwargs:2 --mod utool.util_str --func dict_str --verbinspect
  
      CommandLine:
          python -m utool.util_str --test-dict_str:1
          python -m utool.util_str --test-dict_str --truncate=False --no-checkwant
          python -m utool.util_str --test-dict_str --truncate=1 --no-checkwant
          python -m utool.util_str --test-dict_str --truncate=2 --no-checkwant
  
      Example:
          >>> # ENABLE_DOCTEST
          >>> from utool.util_str import dict_str, dict_itemstr_list
          >>> import utool as ut
          >>> dict_ = {'foo': {'spam': 'barbarbarbarbar' * 3, 'eggs': 'jam'},
          >>>          'baz': 'barbarbarbarbar' * 3}
          >>> truncate = ut.get_argval('--truncate', type_=None, default=1)
          >>> result = dict_str(dict_, strvals=True, truncate=truncate,
          >>>                    truncatekw={'maxlen': 20})
          >>> print(result)
          {
              'baz': barbarbarbarbarbarbarbarbarbarbarbarbarbarbar,
              'foo': {
                  'eggs': jam,
                  's ~~~TRUNCATED~~~ r,
              },
          }
  
      Example:
          >>> # ENABLE_DOCTEST
          >>> import utool as ut
          >>> import numpy as np
          >>> a, b, c = 'a', 'b', 'c'
          >>> dict_ = {
          >>>     'float': 2.3333,
          >>>     'slice': slice(1, 2, None),
          >>>     'arr': np.eye(3),
          >>>     'list1': [1, 2, 3, 2.3333, a, b, c],
          >>>     'dict1': {2.3333: 2.3333, a: b, c: [a, b]},
          >>>     't': {c: {c: {c: {c : c}}}},
          >>>     'set1': {c, a, b},
          >>>     'set2': ut.oset([c, a, b]),
          >>>     'list2': [
          >>>         {a: {c, a, b}, 1: slice(1, 2, 3)},
          >>>         [1, 2, {c, a, 2.333}, {a: [b], b: {c}, c: 2.333}]
          >>>     ],
          >>> }
          >>> dictkw = dict(stritems=True, itemsep='', precision=2, nl=1,
          >>>               nobr=True, explicit=True)
          >>> result = ut.dict_str(dict_, **dictkw)
          >>> print(result)
          >>> dictkw = dict(stritems=0, precision=2, nl=True, nobr=False,
          >>>                  explicit=0)
          >>> result = ut.dict_str(dict_, **dictkw)
          >>> print(result)
      """
      import utool as ut
  
      stritems = dictkw.pop('si', dictkw.pop('stritems', False))
      if stritems:
          dictkw['strkeys'] = True
          dictkw['strvals'] = True
  
      dictkw['strkeys'] = dictkw.pop('sk', dictkw.pop('strkeys', False))
      dictkw['strvals'] = dictkw.pop('sv', dictkw.pop('strvals', False))
  
      newlines = dictkw.pop('nl', dictkw.pop('newlines', True))
      truncate = dictkw.pop('truncate', False)
      dictkw['nl'] = _rectify_countdown_or_bool(newlines)
      dictkw['truncate'] = _rectify_countdown_or_bool(truncate)
  
      nobraces = dictkw.pop('nobr', dictkw.pop('nobraces', False))
      align = dictkw.pop('align', False)
  
      # Doesn't actually put in trailing comma if on same line
      trailing_sep = dictkw.get('trailing_sep', True)
      explicit = dictkw.get('explicit', False)
      with_comma  = True
      itemsep = dictkw.get('itemsep', ' ')
  
      if len(dict_) == 0:
          return 'dict()' if explicit else '{}'
  
      itemstr_list = dict_itemstr_list(dict_, **dictkw)
  
      do_truncate = truncate is not False and (truncate is True or truncate == 0)
      if do_truncate:
          truncatekw = dictkw.get('truncatekw', {})
          itemstr_list = [truncate_str(item, **truncatekw) for item in itemstr_list]
  
      if nobraces:
          lbr, rbr = '', ''
      elif explicit:
          lbr, rbr = 'dict(', ')'
      else:
          lbr, rbr = '{', '}'
  
      if newlines:
          sep = ',\n' if with_comma else '\n'
          if nobraces:
              retstr =  sep.join(itemstr_list)
              if trailing_sep:
                  retstr += ','
          else:
              parts = [ut.indent(itemstr, '    ') for itemstr in itemstr_list]
              body_str = sep.join(parts)
              if trailing_sep:
                  body_str += ','
              retstr =  (lbr + '\n' + body_str + '\n' + rbr)
              if align:
                  retstr = ut.align(retstr, ':')
      else:
          sep = ',' + itemsep if with_comma else itemsep
          # hack away last trailing comma
          sequence_str = sep.join(itemstr_list)
          retstr = lbr +  sequence_str + rbr
      # Is there a way to make truncate for dict_str compatible with list_str?
      return retstr