nodes: 0, module; 1, function_definition; 2, function_name:get_html_attrs; 3, parameters; 4, block; 5, default_parameter; 6, expression_statement; 7, expression_statement; 8, expression_statement; 9, expression_statement; 10, expression_statement; 11, if_statement; 12, try_statement; 13, for_statement; 14, expression_statement; 15, expression_statement; 16, expression_statement; 17, return_statement; 18, identifier:kwargs; 19, None; 20, comment:"""Generate HTML attributes from the provided keyword arguments.
  
      The output value is sorted by the passed keys, to provide consistent
      output.  Because of the frequent use of the normally reserved keyword
      `class`, `classes` is used instead. Also, all underscores are translated
      to regular dashes.
  
      Set any property with a `True` value.
  
      >>> _get_html_attrs({'id': 'text1', 'classes': 'myclass',
          'data_id': 1, 'checked': True})
      u'class="myclass" data-id="1" id="text1" checked'
  
      """; 21, assignment; 22, assignment; 23, assignment; 24, assignment; 25, identifier:classes; 26, block; 27, block; 28, except_clause; 29, pattern_list; 30, call; 31, block; 32, call; 33, call; 34, call; 35, call; 36, identifier:kwargs; 37, boolean_operator; 38, identifier:attrs; 39, list; 40, identifier:props; 41, list; 42, identifier:classes; 43, call; 44, expression_statement; 45, expression_statement; 46, expression_statement; 47, delete_statement; 48, identifier:KeyError; 49, block; 50, identifier:key; 51, identifier:value; 52, identifier:iteritems; 53, argument_list; 54, expression_statement; 55, expression_statement; 56, if_statement; 57, attribute; 58, argument_list; 59, attribute; 60, argument_list; 61, attribute; 62, argument_list; 63, attribute; 64, argument_list; 65, identifier:kwargs; 66, dictionary; 67, attribute; 68, argument_list; 69, assignment; 70, assignment; 71, call; 72, subscript; 73, pass_statement; 74, identifier:kwargs; 75, assignment; 76, assignment; 77, call; 78, block; 79, else_clause; 80, identifier:attrs; 81, identifier:sort; 82, identifier:props; 83, identifier:sort; 84, identifier:attrs; 85, identifier:extend; 86, identifier:props; 87, string; 88, identifier:join; 89, identifier:attrs; 90, call; 91, identifier:strip; 92, identifier:classes; 93, call; 94, identifier:classes; 95, call; 96, attribute; 97, argument_list; 98, identifier:kwargs; 99, string; 100, identifier:key; 101, call; 102, identifier:key; 103, call; 104, identifier:isinstance; 105, argument_list; 106, if_statement; 107, block; 108, string_content:; 109, attribute; 110, argument_list; 111, attribute; 112, argument_list; 113, identifier:to_unicode; 114, argument_list; 115, identifier:attrs; 116, identifier:append; 117, binary_operator:'class=%s' % classes; 118, string_content:classes; 119, attribute; 120, argument_list; 121, identifier:to_unicode; 122, argument_list; 123, identifier:value; 124, identifier:bool; 125, comparison_operator:value is True; 126, block; 127, expression_statement; 128, expression_statement; 129, identifier:kwargs; 130, identifier:get; 131, string; 132, string; 133, string; 134, identifier:join; 135, call; 136, call; 137, string; 138, identifier:classes; 139, identifier:key; 140, identifier:replace; 141, string; 142, string; 143, identifier:key; 144, identifier:value; 145, True; 146, expression_statement; 147, assignment; 148, call; 149, string_content:classes; 150, string_content:; 151, attribute; 152, argument_list; 153, identifier:quoteattr; 154, argument_list; 155, string_content:class=%s; 156, string_content:_; 157, string_content:-; 158, call; 159, identifier:value; 160, call; 161, attribute; 162, argument_list; 163, identifier:re; 164, identifier:split; 165, string; 166, identifier:classes; 167, identifier:classes; 168, attribute; 169, argument_list; 170, identifier:quoteattr; 171, argument_list; 172, identifier:attrs; 173, identifier:append; 174, binary_operator:u'%s=%s' % (key, value); 175, string_content:\s+; 176, identifier:props; 177, identifier:append; 178, identifier:key; 179, call; 180, string; 181, tuple; 182, identifier:Markup; 183, argument_list; 184, string_content:%s=%s; 185, identifier:key; 186, identifier:value; 187, identifier:value
code: def get_html_attrs(kwargs=None):
      """Generate HTML attributes from the provided keyword arguments.
  
      The output value is sorted by the passed keys, to provide consistent
      output.  Because of the frequent use of the normally reserved keyword
      `class`, `classes` is used instead. Also, all underscores are translated
      to regular dashes.
  
      Set any property with a `True` value.
  
      >>> _get_html_attrs({'id': 'text1', 'classes': 'myclass',
          'data_id': 1, 'checked': True})
      u'class="myclass" data-id="1" id="text1" checked'
  
      """
      kwargs = kwargs or {}
      attrs = []
      props = []
  
      classes = kwargs.get('classes', '').strip()
      if classes:
          classes = ' '.join(re.split(r'\s+', classes))
          classes = to_unicode(quoteattr(classes))
          attrs.append('class=%s' % classes)
      try:
          del kwargs['classes']
      except KeyError:
          pass
  
      for key, value in iteritems(kwargs):
          key = key.replace('_', '-')
          key = to_unicode(key)
          if isinstance(value, bool):
              if value is True:
                  props.append(key)
          else:
              value = quoteattr(Markup(value))
              attrs.append(u'%s=%s' % (key, value))
  
      attrs.sort()
      props.sort()
      attrs.extend(props)
      return u' '.join(attrs)