nodes: 0, module; 1, function_definition; 2, function_name:hash_data; 3, parameters; 4, block; 5, identifier:data; 6, default_parameter; 7, default_parameter; 8, expression_statement; 9, if_statement; 10, if_statement; 11, if_statement; 12, identifier:hashlen; 13, None; 14, identifier:alphabet; 15, None; 16, comment:r"""
      Get a unique hash depending on the state of the data.
  
      Args:
          data (object): any sort of loosely organized data
          hashlen (None): (default = None)
          alphabet (None): (default = None)
  
      Returns:
          str: text -  hash string
  
      CommandLine:
          python -m utool.util_hash hash_data
  
      Example:
          >>> # ENABLE_DOCTEST
          >>> from utool.util_hash import *  # NOQA
          >>> import utool as ut
          >>> counter = [0]
          >>> failed = []
          >>> def check_hash(input_, want=None):
          >>>     count = counter[0] = counter[0] + 1
          >>>     got = ut.hash_data(input_)
          >>>     print('({}) {}'.format(count, got))
          >>>     if want is not None and not got.startswith(want):
          >>>         failed.append((got, input_, count, want))
          >>> check_hash('1', 'wuvrng')
          >>> check_hash(['1'], 'dekbfpby')
          >>> check_hash(tuple(['1']), 'dekbfpby')
          >>> check_hash(b'12', 'marreflbv')
          >>> check_hash([b'1', b'2'], 'nwfs')
          >>> check_hash(['1', '2', '3'], 'arfrp')
          >>> check_hash(['1', np.array([1,2,3]), '3'], 'uyqwcq')
          >>> check_hash('123', 'ehkgxk')
          >>> check_hash(zip([1, 2, 3], [4, 5, 6]), 'mjcpwa')
          >>> import numpy as np
          >>> rng = np.random.RandomState(0)
          >>> check_hash(rng.rand(100000), 'bdwosuey')
          >>> for got, input_, count, want in failed:
          >>>     print('failed {} on {}'.format(count, input_))
          >>>     print('got={}, want={}'.format(got, want))
          >>> assert not failed
      """; 17, comparison_operator:alphabet is None; 18, block; 19, comparison_operator:hashlen is None; 20, block; 21, boolean_operator; 22, comment:# Make a special hash for empty data; 23, block; 24, else_clause; 25, identifier:alphabet; 26, None; 27, expression_statement; 28, identifier:hashlen; 29, None; 30, expression_statement; 31, call; 32, comparison_operator:len(data) == 0; 33, expression_statement; 34, block; 35, assignment; 36, assignment; 37, identifier:isinstance; 38, argument_list; 39, call; 40, integer:0; 41, assignment; 42, expression_statement; 43, expression_statement; 44, comment:# Get a 128 character hex string; 45, expression_statement; 46, comment:# Shorten length of string (by increasing base); 47, expression_statement; 48, comment:# Truncate; 49, expression_statement; 50, return_statement; 51, identifier:alphabet; 52, identifier:ALPHABET_27; 53, identifier:hashlen; 54, identifier:HASH_LEN2; 55, identifier:data; 56, identifier:stringlike; 57, identifier:len; 58, argument_list; 59, identifier:text; 60, parenthesized_expression; 61, assignment; 62, call; 63, assignment; 64, assignment; 65, assignment; 66, identifier:text; 67, identifier:data; 68, binary_operator:alphabet[0] * hashlen; 69, identifier:hasher; 70, call; 71, identifier:_update_hasher; 72, argument_list; 73, identifier:text; 74, call; 75, identifier:hashstr2; 76, call; 77, identifier:text; 78, subscript; 79, subscript; 80, identifier:hashlen; 81, attribute; 82, argument_list; 83, identifier:hasher; 84, identifier:data; 85, attribute; 86, argument_list; 87, identifier:convert_hexstr_to_bigbase; 88, argument_list; 89, identifier:hashstr2; 90, slice; 91, identifier:alphabet; 92, integer:0; 93, identifier:hashlib; 94, identifier:sha512; 95, identifier:hasher; 96, identifier:hexdigest; 97, identifier:text; 98, identifier:alphabet; 99, keyword_argument; 100, identifier:hashlen; 101, identifier:bigbase; 102, call; 103, identifier:len; 104, argument_list; 105, identifier:alphabet
code: def hash_data(data, hashlen=None, alphabet=None):
      r"""
      Get a unique hash depending on the state of the data.
  
      Args:
          data (object): any sort of loosely organized data
          hashlen (None): (default = None)
          alphabet (None): (default = None)
  
      Returns:
          str: text -  hash string
  
      CommandLine:
          python -m utool.util_hash hash_data
  
      Example:
          >>> # ENABLE_DOCTEST
          >>> from utool.util_hash import *  # NOQA
          >>> import utool as ut
          >>> counter = [0]
          >>> failed = []
          >>> def check_hash(input_, want=None):
          >>>     count = counter[0] = counter[0] + 1
          >>>     got = ut.hash_data(input_)
          >>>     print('({}) {}'.format(count, got))
          >>>     if want is not None and not got.startswith(want):
          >>>         failed.append((got, input_, count, want))
          >>> check_hash('1', 'wuvrng')
          >>> check_hash(['1'], 'dekbfpby')
          >>> check_hash(tuple(['1']), 'dekbfpby')
          >>> check_hash(b'12', 'marreflbv')
          >>> check_hash([b'1', b'2'], 'nwfs')
          >>> check_hash(['1', '2', '3'], 'arfrp')
          >>> check_hash(['1', np.array([1,2,3]), '3'], 'uyqwcq')
          >>> check_hash('123', 'ehkgxk')
          >>> check_hash(zip([1, 2, 3], [4, 5, 6]), 'mjcpwa')
          >>> import numpy as np
          >>> rng = np.random.RandomState(0)
          >>> check_hash(rng.rand(100000), 'bdwosuey')
          >>> for got, input_, count, want in failed:
          >>>     print('failed {} on {}'.format(count, input_))
          >>>     print('got={}, want={}'.format(got, want))
          >>> assert not failed
      """
      if alphabet is None:
          alphabet = ALPHABET_27
      if hashlen is None:
          hashlen = HASH_LEN2
      if isinstance(data, stringlike) and len(data) == 0:
          # Make a special hash for empty data
          text = (alphabet[0] * hashlen)
      else:
          hasher = hashlib.sha512()
          _update_hasher(hasher, data)
          # Get a 128 character hex string
          text = hasher.hexdigest()
          # Shorten length of string (by increasing base)
          hashstr2 = convert_hexstr_to_bigbase(text, alphabet, bigbase=len(alphabet))
          # Truncate
          text = hashstr2[:hashlen]
          return text