nodes: 0, module; 1, function_definition; 2, function_name:languages; 3, parameters; 4, block; 5, identifier:self; 6, expression_statement; 7, expression_statement; 8, expression_statement; 9, return_statement; 10, comment:"""
          Retrieve languages, sorted by most common to least common. The
          Accept-Languages header sometimes looks weird, i.e.
          "en-US,en;q=0.8,is;q=0.6,da;q=0.4" We will split on the first semi-
          colon.
          """; 11, assignment; 12, assignment; 13, parenthesized_expression; 14, identifier:language; 15, subscript; 16, identifier:first_language; 17, call; 18, call; 19, attribute; 20, string; 21, attribute; 22, argument_list; 23, attribute; 24, argument_list; 25, identifier:PageView; 26, identifier:headers; 27, string_content:Accept-Language; 28, identifier:fn; 29, identifier:SubStr; 30, identifier:language; 31, comment:# String to slice.; 32, integer:1; 33, comment:# Left index.; 34, call; 35, call; 36, identifier:tuples; 37, attribute; 38, argument_list; 39, attribute; 40, argument_list; 41, identifier:fn; 42, identifier:StrPos; 43, identifier:language; 44, string; 45, call; 46, identifier:order_by; 47, call; 48, string_content:;; 49, attribute; 50, argument_list; 51, attribute; 52, argument_list; 53, call; 54, identifier:group_by; 55, identifier:first_language; 56, call; 57, identifier:desc; 58, attribute; 59, argument_list; 60, attribute; 61, argument_list; 62, call; 63, identifier:select; 64, identifier:first_language; 65, call; 66, identifier:fn; 67, identifier:Count; 68, attribute; 69, attribute; 70, argument_list; 71, attribute; 72, argument_list; 73, identifier:PageView; 74, identifier:id; 75, identifier:self; 76, identifier:get_query; 77, identifier:fn; 78, identifier:Count; 79, attribute; 80, identifier:PageView; 81, identifier:id
code: def languages(self):
          """
          Retrieve languages, sorted by most common to least common. The
          Accept-Languages header sometimes looks weird, i.e.
          "en-US,en;q=0.8,is;q=0.6,da;q=0.4" We will split on the first semi-
          colon.
          """
          language = PageView.headers['Accept-Language']
          first_language = fn.SubStr(
              language,  # String to slice.
              1,  # Left index.
              fn.StrPos(language, ';'))
          return (self.get_query()
                  .select(first_language, fn.Count(PageView.id))
                  .group_by(first_language)
                  .order_by(fn.Count(PageView.id).desc())
                  .tuples())