nodes: 0, module; 1, function_definition; 2, function_name:multi_sort; 3, parameters; 4, block; 5, identifier:remotes; 6, identifier:sort; 7, expression_statement; 8, expression_statement; 9, expression_statement; 10, comment:# Convert name to int if alpha is in sort.; 11, if_statement; 12, comment:# Parse versions if semver is in sort.; 13, if_statement; 14, comment:# Build sort_mapping dict.; 15, expression_statement; 16, for_statement; 17, comment:# Sort.; 18, expression_statement; 19, comment:"""Sort `remotes` in place. Allows sorting by multiple conditions.
  
      This is needed because Python 3 no longer supports sorting lists of multiple types. Sort keys must all be of the
      same type.
  
      Problem: the user expects versions to be sorted latest first and timelogical to be most recent first (when viewing
      the HTML documentation), yet expects alphabetical sorting to be A before Z.
      Solution: invert integers (dates and parsed versions).
  
      :param iter remotes: List of dicts from Versions().remotes.
      :param iter sort: What to sort by. May be one or more of: alpha, time, semver
      """; 20, assignment; 21, assignment; 22, comparison_operator:'alpha' in sort; 23, block; 24, comparison_operator:'semver' in sort; 25, block; 26, assignment; 27, pattern_list; 28, call; 29, block; 30, call; 31, identifier:exploded_alpha; 32, call; 33, identifier:exploded_semver; 34, call; 35, string; 36, identifier:sort; 37, expression_statement; 38, for_statement; 39, string; 40, identifier:sort; 41, expression_statement; 42, identifier:sort_mapping; 43, call; 44, identifier:i; 45, identifier:remote; 46, identifier:enumerate; 47, argument_list; 48, expression_statement; 49, for_statement; 50, expression_statement; 51, attribute; 52, argument_list; 53, identifier:list; 54, argument_list; 55, identifier:list; 56, argument_list; 57, string_content:alpha; 58, assignment; 59, identifier:name; 60, generator_expression; 61, block; 62, string_content:semver; 63, assignment; 64, identifier:dict; 65, argument_list; 66, identifier:remotes; 67, assignment; 68, identifier:sort_by; 69, identifier:sort; 70, block; 71, assignment; 72, identifier:remotes; 73, identifier:sort; 74, keyword_argument; 75, identifier:alpha_max_len; 76, call; 77, subscript; 78, for_in_clause; 79, expression_statement; 80, identifier:exploded_semver; 81, call; 82, identifier:key; 83, call; 84, if_statement; 85, subscript; 86, identifier:key; 87, identifier:key; 88, lambda; 89, identifier:max; 90, generator_expression; 91, identifier:r; 92, string; 93, identifier:r; 94, identifier:remotes; 95, call; 96, identifier:semvers; 97, generator_expression; 98, identifier:list; 99, argument_list; 100, comparison_operator:sort_by == 'alpha'; 101, block; 102, elif_clause; 103, elif_clause; 104, identifier:sort_mapping; 105, call; 106, lambda_parameters; 107, call; 108, call; 109, for_in_clause; 110, string_content:name; 111, attribute; 112, argument_list; 113, subscript; 114, for_in_clause; 115, identifier:sort_by; 116, string; 117, expression_statement; 118, comparison_operator:sort_by == 'time'; 119, block; 120, comparison_operator:sort_by == 'semver'; 121, block; 122, identifier:id; 123, argument_list; 124, identifier:k; 125, attribute; 126, argument_list; 127, identifier:len; 128, argument_list; 129, identifier:r; 130, identifier:remotes; 131, identifier:exploded_alpha; 132, identifier:append; 133, binary_operator:[ord(i) for i in name] + [0] * (alpha_max_len - len(name)); 134, identifier:r; 135, string; 136, identifier:r; 137, identifier:remotes; 138, string_content:alpha; 139, call; 140, identifier:sort_by; 141, string; 142, expression_statement; 143, identifier:sort_by; 144, string; 145, expression_statement; 146, identifier:remote; 147, identifier:sort_mapping; 148, identifier:get; 149, call; 150, subscript; 151, list_comprehension; 152, binary_operator:[0] * (alpha_max_len - len(name)); 153, string_content:name; 154, attribute; 155, argument_list; 156, string_content:time; 157, call; 158, string_content:semver; 159, call; 160, identifier:id; 161, argument_list; 162, identifier:r; 163, string; 164, call; 165, for_in_clause; 166, list; 167, parenthesized_expression; 168, identifier:key; 169, identifier:extend; 170, subscript; 171, attribute; 172, argument_list; 173, attribute; 174, argument_list; 175, identifier:k; 176, string_content:name; 177, identifier:ord; 178, argument_list; 179, identifier:i; 180, identifier:name; 181, integer:0; 182, binary_operator:alpha_max_len - len(name); 183, identifier:exploded_alpha; 184, identifier:i; 185, identifier:key; 186, identifier:append; 187, unary_operator; 188, identifier:key; 189, identifier:extend; 190, subscript; 191, identifier:i; 192, identifier:alpha_max_len; 193, call; 194, subscript; 195, identifier:exploded_semver; 196, identifier:i; 197, identifier:len; 198, argument_list; 199, identifier:remote; 200, string; 201, identifier:name; 202, string_content:date
code: def multi_sort(remotes, sort):
      """Sort `remotes` in place. Allows sorting by multiple conditions.
  
      This is needed because Python 3 no longer supports sorting lists of multiple types. Sort keys must all be of the
      same type.
  
      Problem: the user expects versions to be sorted latest first and timelogical to be most recent first (when viewing
      the HTML documentation), yet expects alphabetical sorting to be A before Z.
      Solution: invert integers (dates and parsed versions).
  
      :param iter remotes: List of dicts from Versions().remotes.
      :param iter sort: What to sort by. May be one or more of: alpha, time, semver
      """
      exploded_alpha = list()
      exploded_semver = list()
  
      # Convert name to int if alpha is in sort.
      if 'alpha' in sort:
          alpha_max_len = max(len(r['name']) for r in remotes)
          for name in (r['name'] for r in remotes):
              exploded_alpha.append([ord(i) for i in name] + [0] * (alpha_max_len - len(name)))
  
      # Parse versions if semver is in sort.
      if 'semver' in sort:
          exploded_semver = semvers(r['name'] for r in remotes)
  
      # Build sort_mapping dict.
      sort_mapping = dict()
      for i, remote in enumerate(remotes):
          key = list()
          for sort_by in sort:
              if sort_by == 'alpha':
                  key.extend(exploded_alpha[i])
              elif sort_by == 'time':
                  key.append(-remote['date'])
              elif sort_by == 'semver':
                  key.extend(exploded_semver[i])
          sort_mapping[id(remote)] = key
  
      # Sort.
      remotes.sort(key=lambda k: sort_mapping.get(id(k)))