nodes: 0, module; 1, function_definition; 2, function_name:_get_sorted_methods; 3, parameters; 4, block; 5, identifier:self; 6, identifier:methods; 7, expression_statement; 8, if_statement; 9, comment:# Comparison function we'll use to sort the methods:; 10, function_definition; 11, return_statement; 12, comment:"""Get a copy of 'methods' sorted the way they would be on the live server.
  
      Args:
        methods: JSON configuration of an API's methods.
  
      Returns:
        The same configuration with the methods sorted based on what order
        they'll be checked by the server.
      """; 13, not_operator; 14, block; 15, function_name:_sorted_methods_comparison; 16, parameters; 17, block; 18, call; 19, identifier:methods; 20, return_statement; 21, identifier:method_info1; 22, identifier:method_info2; 23, expression_statement; 24, function_definition; 25, comment:# Higher path scores come first.; 26, expression_statement; 27, expression_statement; 28, if_statement; 29, comment:# Compare by path text next, sorted alphabetically.; 30, expression_statement; 31, if_statement; 32, comment:# All else being equal, sort by HTTP method.; 33, expression_statement; 34, return_statement; 35, identifier:sorted; 36, argument_list; 37, identifier:methods; 38, comment:"""Sort method info by path and http_method.
  
        Args:
          method_info1: Method name and info for the first method to compare.
          method_info2: Method name and info for the method to compare to.
  
        Returns:
          Negative if the first method should come first, positive if the
          first method should come after the second.  Zero if they're
          equivalent.
        """; 39, function_name:_score_path; 40, parameters; 41, block; 42, assignment; 43, assignment; 44, comparison_operator:path_score1 != path_score2; 45, block; 46, assignment; 47, comparison_operator:path_result != 0; 48, block; 49, assignment; 50, identifier:method_result; 51, call; 52, identifier:_sorted_methods_comparison; 53, identifier:path; 54, expression_statement; 55, expression_statement; 56, expression_statement; 57, for_statement; 58, comment:# Shift by 31 instead of 32 because some (!) versions of Python like; 59, comment:# to convert the int to a long if we shift by 32, and the sorted(); 60, comment:# function that uses this blows up if it receives anything but an int.; 61, expression_statement; 62, return_statement; 63, identifier:path_score1; 64, call; 65, identifier:path_score2; 66, call; 67, identifier:path_score1; 68, identifier:path_score2; 69, return_statement; 70, identifier:path_result; 71, call; 72, identifier:path_result; 73, integer:0; 74, return_statement; 75, identifier:method_result; 76, call; 77, attribute; 78, argument_list; 79, comment:"""Calculate the score for this path, used for comparisons.
  
          Higher scores have priority, and if scores are equal, the path text
          is sorted alphabetically.  Scores are based on the number and location
          of the constant parts of the path.  The server has some special handling
          for variables with regexes, which we don't handle here.
  
          Args:
            path: The request path that we're calculating a score for.
  
          Returns:
            The score for the given path.
          """; 80, assignment; 81, assignment; 82, identifier:part; 83, identifier:parts; 84, block; 85, augmented_assignment; 86, identifier:score; 87, identifier:_score_path; 88, argument_list; 89, identifier:_score_path; 90, argument_list; 91, binary_operator:path_score2 - path_score1; 92, identifier:cmp; 93, argument_list; 94, identifier:path_result; 95, identifier:cmp; 96, argument_list; 97, identifier:methods; 98, identifier:items; 99, identifier:score; 100, integer:0; 101, identifier:parts; 102, call; 103, expression_statement; 104, if_statement; 105, identifier:score; 106, binary_operator:31 - len(parts); 107, call; 108, call; 109, identifier:path_score2; 110, identifier:path_score1; 111, call; 112, call; 113, call; 114, call; 115, attribute; 116, argument_list; 117, augmented_assignment; 118, boolean_operator; 119, comment:# Found a constant.; 120, block; 121, integer:31; 122, call; 123, attribute; 124, argument_list; 125, attribute; 126, argument_list; 127, attribute; 128, argument_list; 129, attribute; 130, argument_list; 131, attribute; 132, argument_list; 133, attribute; 134, argument_list; 135, identifier:path; 136, identifier:split; 137, string; 138, identifier:score; 139, integer:1; 140, not_operator; 141, comparison_operator:part[0] != '{'; 142, expression_statement; 143, identifier:len; 144, argument_list; 145, subscript; 146, identifier:get; 147, string; 148, string; 149, subscript; 150, identifier:get; 151, string; 152, string; 153, subscript; 154, identifier:get; 155, string; 156, string; 157, subscript; 158, identifier:get; 159, string; 160, string; 161, subscript; 162, identifier:get; 163, string; 164, string; 165, subscript; 166, identifier:get; 167, string; 168, string; 169, string_content:/; 170, identifier:part; 171, subscript; 172, string; 173, augmented_assignment; 174, identifier:parts; 175, identifier:method_info1; 176, integer:1; 177, string_content:path; 178, identifier:method_info2; 179, integer:1; 180, string_content:path; 181, identifier:method_info1; 182, integer:1; 183, string_content:path; 184, identifier:method_info2; 185, integer:1; 186, string_content:path; 187, identifier:method_info1; 188, integer:1; 189, string_content:httpMethod; 190, identifier:method_info2; 191, integer:1; 192, string_content:httpMethod; 193, identifier:part; 194, integer:0; 195, string_content:{; 196, identifier:score; 197, integer:1
code: def _get_sorted_methods(self, methods):
      """Get a copy of 'methods' sorted the way they would be on the live server.
  
      Args:
        methods: JSON configuration of an API's methods.
  
      Returns:
        The same configuration with the methods sorted based on what order
        they'll be checked by the server.
      """
      if not methods:
        return methods
  
      # Comparison function we'll use to sort the methods:
      def _sorted_methods_comparison(method_info1, method_info2):
        """Sort method info by path and http_method.
  
        Args:
          method_info1: Method name and info for the first method to compare.
          method_info2: Method name and info for the method to compare to.
  
        Returns:
          Negative if the first method should come first, positive if the
          first method should come after the second.  Zero if they're
          equivalent.
        """
  
        def _score_path(path):
          """Calculate the score for this path, used for comparisons.
  
          Higher scores have priority, and if scores are equal, the path text
          is sorted alphabetically.  Scores are based on the number and location
          of the constant parts of the path.  The server has some special handling
          for variables with regexes, which we don't handle here.
  
          Args:
            path: The request path that we're calculating a score for.
  
          Returns:
            The score for the given path.
          """
          score = 0
          parts = path.split('/')
          for part in parts:
            score <<= 1
            if not part or part[0] != '{':
              # Found a constant.
              score += 1
          # Shift by 31 instead of 32 because some (!) versions of Python like
          # to convert the int to a long if we shift by 32, and the sorted()
          # function that uses this blows up if it receives anything but an int.
          score <<= 31 - len(parts)
          return score
  
        # Higher path scores come first.
        path_score1 = _score_path(method_info1[1].get('path', ''))
        path_score2 = _score_path(method_info2[1].get('path', ''))
        if path_score1 != path_score2:
          return path_score2 - path_score1
  
        # Compare by path text next, sorted alphabetically.
        path_result = cmp(method_info1[1].get('path', ''),
                          method_info2[1].get('path', ''))
        if path_result != 0:
          return path_result
  
        # All else being equal, sort by HTTP method.
        method_result = cmp(method_info1[1].get('httpMethod', ''),
                            method_info2[1].get('httpMethod', ''))
        return method_result
  
      return sorted(methods.items(), _sorted_methods_comparison)