nodes: 0, module; 1, function_definition; 2, function_name:make_key_hippie; 3, parameters; 4, block; 5, identifier:obj; 6, default_parameter; 7, expression_statement; 8, expression_statement; 9, if_statement; 10, comment:## should we try to convert to frozen{set,dict} to get the C; 11, comment:## hashing function speed ? But the convertion has a cost also.; 12, if_statement; 13, if_statement; 14, if_statement; 15, raise_statement; 16, identifier:typed; 17, True; 18, comment:"""Return hashable structure from non-hashable structure using hippie means
  
      dict and set are sorted and their content subjected to same hippie means.
  
      Note that the key identifies the current content of the structure.
  
      """; 19, assignment; 20, call; 21, comment:## DO NOT RETURN hash(obj), as hash collision would generate bad; 22, comment:## cache collisions.; 23, block; 24, call; 25, block; 26, call; 27, block; 28, call; 29, block; 30, call; 31, identifier:ftype; 32, conditional_expression:type if typed else lambda o: None; 33, identifier:is_hashable; 34, argument_list; 35, return_statement; 36, identifier:isinstance; 37, argument_list; 38, expression_statement; 39, identifier:isinstance; 40, argument_list; 41, return_statement; 42, identifier:isinstance; 43, argument_list; 44, return_statement; 45, identifier:ValueError; 46, argument_list; 47, identifier:type; 48, identifier:typed; 49, lambda; 50, identifier:obj; 51, expression_list; 52, identifier:obj; 53, identifier:set; 54, assignment; 55, identifier:obj; 56, tuple; 57, call; 58, identifier:obj; 59, identifier:dict; 60, call; 61, binary_operator:"%r can not be hashed. Try providing a custom key function."
          % obj; 62, lambda_parameters; 63, None; 64, identifier:obj; 65, call; 66, identifier:obj; 67, call; 68, identifier:list; 69, identifier:tuple; 70, identifier:tuple; 71, generator_expression; 72, identifier:tuple; 73, argument_list; 74, string:"%r can not be hashed. Try providing a custom key function."; 75, identifier:obj; 76, identifier:o; 77, identifier:ftype; 78, argument_list; 79, identifier:sorted; 80, argument_list; 81, call; 82, for_in_clause; 83, call; 84, identifier:obj; 85, identifier:obj; 86, identifier:make_key_hippie; 87, argument_list; 88, identifier:e; 89, identifier:obj; 90, identifier:sorted; 91, argument_list; 92, identifier:e; 93, identifier:typed; 94, generator_expression; 95, tuple; 96, for_in_clause; 97, call; 98, call; 99, pattern_list; 100, call; 101, identifier:make_key_hippie; 102, argument_list; 103, identifier:make_key_hippie; 104, argument_list; 105, identifier:k; 106, identifier:v; 107, attribute; 108, argument_list; 109, identifier:k; 110, identifier:typed; 111, identifier:v; 112, identifier:typed; 113, identifier:obj; 114, identifier:items
code: def make_key_hippie(obj, typed=True):
      """Return hashable structure from non-hashable structure using hippie means
  
      dict and set are sorted and their content subjected to same hippie means.
  
      Note that the key identifies the current content of the structure.
  
      """
      ftype = type if typed else lambda o: None
      if is_hashable(obj):
          ## DO NOT RETURN hash(obj), as hash collision would generate bad
          ## cache collisions.
          return obj, ftype(obj)
      ## should we try to convert to frozen{set,dict} to get the C
      ## hashing function speed ? But the convertion has a cost also.
      if isinstance(obj, set):
          obj = sorted(obj)
      if isinstance(obj, (list, tuple)):
          return tuple(make_key_hippie(e, typed) for e in obj)
      if isinstance(obj, dict):
          return tuple(sorted(((make_key_hippie(k, typed),
                                make_key_hippie(v, typed))
                               for k, v in obj.items())))
      raise ValueError(
          "%r can not be hashed. Try providing a custom key function."
          % obj)