nodes: 0, module; 1, function_definition; 2, function_name:toposort_classes; 3, parameters; 4, block; 5, identifier:classes; 6, expression_statement; 7, function_definition; 8, comment:# Map names to classes; 9, expression_statement; 10, expression_statement; 11, expression_statement; 12, for_statement; 13, return_statement; 14, comment:"""Sort class metadatas so that a superclass is always before the subclass"""; 15, function_name:get_class_topolist; 16, parameters; 17, block; 18, assignment; 19, assignment; 20, assignment; 21, identifier:name; 22, call; 23, block; 24, identifier:toposorted; 25, identifier:class_name; 26, identifier:name_to_class; 27, identifier:processed_classes; 28, identifier:current_trace; 29, expression_statement; 30, comment:# Check if this class has already been handled; 31, if_statement; 32, if_statement; 33, expression_statement; 34, comment:# Collect the dependency classes; 35, comment:# These are bases and classes from linked properties; 36, expression_statement; 37, comment:# Recursively process linked edges; 38, expression_statement; 39, for_statement; 40, expression_statement; 41, comment:# Recursively process superclasses; 42, expression_statement; 43, for_statement; 44, expression_statement; 45, comment:# Do the bookkeeping; 46, expression_statement; 47, expression_statement; 48, return_statement; 49, identifier:class_map; 50, dictionary_comprehension; 51, identifier:seen_classes; 52, call; 53, identifier:toposorted; 54, list; 55, attribute; 56, argument_list; 57, expression_statement; 58, comment:"""Return a topologically sorted list of this class's dependencies and class itself
  
          Args:
              class_name: string, name of the class to process
              name_to_class: dict, class_name -> descriptor
              processed_classes: set of strings, a set of classes that have already been processed
              current_trace: list of strings, list of classes traversed during the recursion
  
          Returns:
              list of dicts, list of classes sorted in topological order
          """; 59, comparison_operator:class_name in processed_classes; 60, block; 61, comparison_operator:class_name in current_trace; 62, block; 63, assignment; 64, assignment; 65, assignment; 66, identifier:prop; 67, identifier:properties; 68, block; 69, assignment; 70, call; 71, identifier:dependency; 72, identifier:dependencies; 73, block; 74, call; 75, call; 76, call; 77, identifier:class_list; 78, pair; 79, for_in_clause; 80, identifier:set; 81, argument_list; 82, identifier:class_map; 83, identifier:keys; 84, call; 85, identifier:class_name; 86, identifier:processed_classes; 87, return_statement; 88, identifier:class_name; 89, identifier:current_trace; 90, raise_statement; 91, identifier:cls; 92, subscript; 93, identifier:dependencies; 94, call; 95, identifier:properties; 96, conditional_expression:cls['properties'] if 'properties' in cls else []; 97, if_statement; 98, identifier:class_list; 99, list; 100, attribute; 101, argument_list; 102, expression_statement; 103, attribute; 104, argument_list; 105, attribute; 106, argument_list; 107, attribute; 108, argument_list; 109, subscript; 110, identifier:c; 111, identifier:c; 112, identifier:classes; 113, attribute; 114, argument_list; 115, list; 116, call; 117, identifier:name_to_class; 118, identifier:class_name; 119, identifier:_list_superclasses; 120, argument_list; 121, subscript; 122, comparison_operator:'properties' in cls; 123, list; 124, comparison_operator:'linkedClass' in prop; 125, block; 126, identifier:current_trace; 127, identifier:add; 128, identifier:class_name; 129, call; 130, identifier:current_trace; 131, identifier:remove; 132, identifier:class_name; 133, identifier:class_list; 134, identifier:append; 135, subscript; 136, identifier:processed_classes; 137, identifier:add; 138, identifier:class_name; 139, identifier:c; 140, string; 141, identifier:toposorted; 142, identifier:extend; 143, call; 144, identifier:AssertionError; 145, argument_list; 146, identifier:cls; 147, identifier:cls; 148, string; 149, string; 150, identifier:cls; 151, string; 152, identifier:prop; 153, expression_statement; 154, attribute; 155, argument_list; 156, identifier:name_to_class; 157, identifier:class_name; 158, string_content:name; 159, identifier:get_class_topolist; 160, argument_list; 161, call; 162, string_content:properties; 163, string_content:properties; 164, string_content:linkedClass; 165, call; 166, identifier:class_list; 167, identifier:extend; 168, call; 169, identifier:name; 170, identifier:class_map; 171, identifier:seen_classes; 172, call; 173, attribute; 174, argument_list; 175, attribute; 176, argument_list; 177, identifier:get_class_topolist; 178, argument_list; 179, identifier:set; 180, argument_list; 181, string; 182, identifier:format; 183, identifier:class_name; 184, identifier:dependencies; 185, identifier:append; 186, subscript; 187, identifier:dependency; 188, identifier:name_to_class; 189, identifier:processed_classes; 190, identifier:current_trace; 191, string_content:Encountered self-reference in dependency chain of {}; 192, identifier:prop; 193, string; 194, string_content:linkedClass
code: def toposort_classes(classes):
      """Sort class metadatas so that a superclass is always before the subclass"""
      def get_class_topolist(class_name, name_to_class, processed_classes, current_trace):
          """Return a topologically sorted list of this class's dependencies and class itself
  
          Args:
              class_name: string, name of the class to process
              name_to_class: dict, class_name -> descriptor
              processed_classes: set of strings, a set of classes that have already been processed
              current_trace: list of strings, list of classes traversed during the recursion
  
          Returns:
              list of dicts, list of classes sorted in topological order
          """
          # Check if this class has already been handled
          if class_name in processed_classes:
              return []
  
          if class_name in current_trace:
              raise AssertionError(
                  'Encountered self-reference in dependency chain of {}'.format(class_name))
  
          cls = name_to_class[class_name]
          # Collect the dependency classes
          # These are bases and classes from linked properties
          dependencies = _list_superclasses(cls)
          # Recursively process linked edges
          properties = cls['properties'] if 'properties' in cls else []
          for prop in properties:
              if 'linkedClass' in prop:
                  dependencies.append(prop['linkedClass'])
  
          class_list = []
          # Recursively process superclasses
          current_trace.add(class_name)
          for dependency in dependencies:
              class_list.extend(get_class_topolist(
                  dependency, name_to_class, processed_classes, current_trace))
          current_trace.remove(class_name)
          # Do the bookkeeping
          class_list.append(name_to_class[class_name])
          processed_classes.add(class_name)
  
          return class_list
  
      # Map names to classes
      class_map = {c['name']: c for c in classes}
      seen_classes = set()
  
      toposorted = []
      for name in class_map.keys():
          toposorted.extend(get_class_topolist(name, class_map, seen_classes, set()))
      return toposorted