nodes: 0, module; 1, function_definition; 2, function_name:canonical_headers; 3, parameters; 4, block; 5, identifier:self; 6, identifier:headers_to_sign; 7, expression_statement; 8, expression_statement; 9, expression_statement; 10, return_statement; 11, comment:"""
          Return the headers that need to be included in the StringToSign
          in their canonical form by converting all header keys to lower
          case, sorting them in alphabetical order and then joining
          them into a string, separated by newlines.
          """; 12, assignment; 13, call; 14, call; 15, identifier:l; 16, list_comprehension; 17, attribute; 18, argument_list; 19, attribute; 20, argument_list; 21, binary_operator:'%s:%s'%(n.lower().strip(),
                        headers_to_sign[n].strip()); 22, for_in_clause; 23, identifier:l; 24, identifier:sort; 25, string; 26, identifier:join; 27, identifier:l; 28, string; 29, tuple; 30, identifier:n; 31, identifier:headers_to_sign; 32, string_content; 33, string_content:%s:%s; 34, call; 35, call; 36, escape_sequence:\n; 37, attribute; 38, argument_list; 39, attribute; 40, argument_list; 41, call; 42, identifier:strip; 43, subscript; 44, identifier:strip; 45, attribute; 46, argument_list; 47, identifier:headers_to_sign; 48, identifier:n; 49, identifier:n; 50, identifier:lower
code: def canonical_headers(self, headers_to_sign):
          """
          Return the headers that need to be included in the StringToSign
          in their canonical form by converting all header keys to lower
          case, sorting them in alphabetical order and then joining
          them into a string, separated by newlines.
          """
          l = ['%s:%s'%(n.lower().strip(),
                        headers_to_sign[n].strip()) for n in headers_to_sign]
          l.sort()
          return '\n'.join(l)