nodes: 0, module; 1, function_definition; 2, function_name:sort_strings; 3, parameters; 4, block; 5, identifier:strings; 6, default_parameter; 7, default_parameter; 8, default_parameter; 9, default_parameter; 10, expression_statement; 11, if_statement; 12, expression_statement; 13, function_definition; 14, return_statement; 15, identifier:sort_order; 16, None; 17, identifier:reverse; 18, False; 19, identifier:case_sensitive; 20, False; 21, identifier:sort_order_first; 22, True; 23, comment:"""Sort a list of strings according to the provided sorted list of string prefixes
  
      TODO:
          - Provide an option to use `.startswith()` rather than a fixed prefix length (will be much slower)
  
      Arguments:
          sort_order_first (bool): Whether strings in sort_order should always preceed "unknown" strings
          sort_order (sequence of str): Desired ordering as a list of prefixes to the strings
              If sort_order strings have varying length, the max length will determine the prefix length compared
          reverse (bool): whether to reverse the sort orded. Passed through to `sorted(strings, reverse=reverse)`
          case_senstive (bool): Whether to sort in lexographic rather than alphabetic order
           and whether the prefixes  in sort_order are checked in a case-sensitive way
  
      Examples:
          >>> sort_strings(['morn32', 'morning', 'unknown', 'date', 'dow', 'doy', 'moy'],
          ...              ('dat', 'dow', 'moy', 'dom', 'doy', 'mor'))
          ['date', 'dow', 'moy', 'doy', 'morn32', 'morning', 'unknown']
          >>> sort_strings(['morn32', 'morning', 'unknown', 'less unknown', 'lucy', 'date', 'dow', 'doy', 'moy'],
          ...              ('dat', 'dow', 'moy', 'dom', 'doy', 'mor'), reverse=True)
          ['unknown', 'lucy', 'less unknown', 'morning', 'morn32', 'doy', 'moy', 'dow', 'date']
  
          Strings whose prefixes don't exist in `sort_order` sequence can be interleaved into the
          sorted list in lexical order by setting `sort_order_first=False`
          >>> sort_strings(['morn32', 'morning', 'unknown', 'lucy', 'less unknown', 'date', 'dow', 'doy', 'moy'],
          ...              ('dat', 'dow', 'moy', 'dom', 'moy', 'mor'),
          ...              sort_order_first=False)  # doctest: +NORMALIZE_WHITESPACE
          ['date', 'dow', 'doy', 'less unknown', 'lucy', 'moy', 'morn32', 'morning', 'unknown']
      """; 24, not_operator; 25, block; 26, assignment; 27, function_name:compare; 28, parameters; 29, block; 30, call; 31, identifier:case_sensitive; 32, expression_statement; 33, expression_statement; 34, identifier:prefix_len; 35, call; 36, identifier:a; 37, identifier:b; 38, default_parameter; 39, if_statement; 40, return_statement; 41, identifier:sorted; 42, argument_list; 43, assignment; 44, assignment; 45, identifier:max; 46, generator_expression; 47, identifier:prefix_len; 48, identifier:prefix_len; 49, identifier:prefix_len; 50, block; 51, binary_operator:(-1 * (a < b) + 1 * (a > b)) * (-2 * reverse + 1); 52, identifier:strings; 53, keyword_argument; 54, identifier:sort_order; 55, call; 56, identifier:strings; 57, call; 58, call; 59, for_in_clause; 60, if_statement; 61, parenthesized_expression; 62, parenthesized_expression; 63, identifier:key; 64, call; 65, identifier:tuple; 66, generator_expression; 67, identifier:tuple; 68, generator_expression; 69, identifier:len; 70, argument_list; 71, identifier:s; 72, identifier:sort_order; 73, comparison_operator:a[:prefix_len] in sort_order; 74, block; 75, comment:# b may be in sort_order list, so it should be first; 76, elif_clause; 77, binary_operator:-1 * (a < b) + 1 * (a > b); 78, binary_operator:-2 * reverse + 1; 79, attribute; 80, argument_list; 81, call; 82, for_in_clause; 83, call; 84, for_in_clause; 85, identifier:s; 86, subscript; 87, identifier:sort_order; 88, if_statement; 89, boolean_operator; 90, block; 91, binary_operator:-1 * (a < b); 92, binary_operator:1 * (a > b); 93, binary_operator:-2 * reverse; 94, integer:1; 95, identifier:functools; 96, identifier:cmp_to_key; 97, identifier:compare; 98, attribute; 99, argument_list; 100, identifier:s; 101, identifier:sort_order; 102, attribute; 103, argument_list; 104, identifier:s; 105, identifier:strings; 106, identifier:a; 107, slice; 108, comparison_operator:b[:prefix_len] in sort_order; 109, block; 110, elif_clause; 111, identifier:sort_order_first; 112, comparison_operator:b[:prefix_len] in sort_order; 113, return_statement; 114, unary_operator; 115, parenthesized_expression; 116, integer:1; 117, parenthesized_expression; 118, unary_operator; 119, identifier:reverse; 120, identifier:s; 121, identifier:lower; 122, identifier:s; 123, identifier:lower; 124, identifier:prefix_len; 125, subscript; 126, identifier:sort_order; 127, expression_statement; 128, expression_statement; 129, if_statement; 130, identifier:sort_order_first; 131, block; 132, subscript; 133, identifier:sort_order; 134, binary_operator:-2 * reverse + 1; 135, integer:1; 136, comparison_operator:a < b; 137, comparison_operator:a > b; 138, integer:2; 139, identifier:b; 140, slice; 141, assignment; 142, assignment; 143, identifier:comparison; 144, block; 145, return_statement; 146, identifier:b; 147, slice; 148, binary_operator:-2 * reverse; 149, integer:1; 150, identifier:a; 151, identifier:b; 152, identifier:a; 153, identifier:b; 154, identifier:prefix_len; 155, identifier:comparison; 156, binary_operator:sort_order.index(a[:prefix_len]) - sort_order.index(b[:prefix_len]); 157, identifier:comparison; 158, call; 159, return_statement; 160, binary_operator:-1 * (-2 * reverse + 1); 161, identifier:prefix_len; 162, unary_operator; 163, identifier:reverse; 164, call; 165, call; 166, identifier:int; 167, argument_list; 168, binary_operator:comparison * (-2 * reverse + 1); 169, unary_operator; 170, parenthesized_expression; 171, integer:2; 172, attribute; 173, argument_list; 174, attribute; 175, argument_list; 176, binary_operator:comparison / abs(comparison or 1); 177, identifier:comparison; 178, parenthesized_expression; 179, integer:1; 180, binary_operator:-2 * reverse + 1; 181, identifier:sort_order; 182, identifier:index; 183, subscript; 184, identifier:sort_order; 185, identifier:index; 186, subscript; 187, identifier:comparison; 188, call; 189, binary_operator:-2 * reverse + 1; 190, binary_operator:-2 * reverse; 191, integer:1; 192, identifier:a; 193, slice; 194, identifier:b; 195, slice; 196, identifier:abs; 197, argument_list; 198, binary_operator:-2 * reverse; 199, integer:1; 200, unary_operator; 201, identifier:reverse; 202, identifier:prefix_len; 203, identifier:prefix_len; 204, boolean_operator; 205, unary_operator; 206, identifier:reverse; 207, integer:2; 208, identifier:comparison; 209, integer:1; 210, integer:2
code: def sort_strings(strings, sort_order=None, reverse=False, case_sensitive=False, sort_order_first=True):
      """Sort a list of strings according to the provided sorted list of string prefixes
  
      TODO:
          - Provide an option to use `.startswith()` rather than a fixed prefix length (will be much slower)
  
      Arguments:
          sort_order_first (bool): Whether strings in sort_order should always preceed "unknown" strings
          sort_order (sequence of str): Desired ordering as a list of prefixes to the strings
              If sort_order strings have varying length, the max length will determine the prefix length compared
          reverse (bool): whether to reverse the sort orded. Passed through to `sorted(strings, reverse=reverse)`
          case_senstive (bool): Whether to sort in lexographic rather than alphabetic order
           and whether the prefixes  in sort_order are checked in a case-sensitive way
  
      Examples:
          >>> sort_strings(['morn32', 'morning', 'unknown', 'date', 'dow', 'doy', 'moy'],
          ...              ('dat', 'dow', 'moy', 'dom', 'doy', 'mor'))
          ['date', 'dow', 'moy', 'doy', 'morn32', 'morning', 'unknown']
          >>> sort_strings(['morn32', 'morning', 'unknown', 'less unknown', 'lucy', 'date', 'dow', 'doy', 'moy'],
          ...              ('dat', 'dow', 'moy', 'dom', 'doy', 'mor'), reverse=True)
          ['unknown', 'lucy', 'less unknown', 'morning', 'morn32', 'doy', 'moy', 'dow', 'date']
  
          Strings whose prefixes don't exist in `sort_order` sequence can be interleaved into the
          sorted list in lexical order by setting `sort_order_first=False`
          >>> sort_strings(['morn32', 'morning', 'unknown', 'lucy', 'less unknown', 'date', 'dow', 'doy', 'moy'],
          ...              ('dat', 'dow', 'moy', 'dom', 'moy', 'mor'),
          ...              sort_order_first=False)  # doctest: +NORMALIZE_WHITESPACE
          ['date', 'dow', 'doy', 'less unknown', 'lucy', 'moy', 'morn32', 'morning', 'unknown']
      """
      if not case_sensitive:
          sort_order = tuple(s.lower() for s in sort_order)
          strings = tuple(s.lower() for s in strings)
      prefix_len = max(len(s) for s in sort_order)
  
      def compare(a, b, prefix_len=prefix_len):
          if prefix_len:
              if a[:prefix_len] in sort_order:
                  if b[:prefix_len] in sort_order:
                      comparison = sort_order.index(a[:prefix_len]) - sort_order.index(b[:prefix_len])
                      comparison = int(comparison / abs(comparison or 1))
                      if comparison:
                          return comparison * (-2 * reverse + 1)
                  elif sort_order_first:
                      return -1 * (-2 * reverse + 1)
              # b may be in sort_order list, so it should be first
              elif sort_order_first and b[:prefix_len] in sort_order:
                  return -2 * reverse + 1
          return (-1 * (a < b) + 1 * (a > b)) * (-2 * reverse + 1)
  
      return sorted(strings, key=functools.cmp_to_key(compare))