Display a toolkit repr according to some simple rules.

    Parameters
    ----------
    model : Turi Create model

    fields: List of lists of tuples
        Each tuple should be (display_name, field_name), where field_name can
        be a string or a _precomputed_field object.


    section_titles: List of section titles, one per list in the fields arg.

    Example
    -------

        model_fields = [
            ("L1 penalty", 'l1_penalty'),
            ("L2 penalty", 'l2_penalty'),
            ("Examples", 'num_examples'),
            ("Features", 'num_features'),
            ("Coefficients", 'num_coefficients')]

        solver_fields = [
            ("Solver", 'solver'),
            ("Solver iterations", 'training_iterations'),
            ("Solver status", 'training_solver_status'),
            ("Training time (sec)", 'training_time')]

        training_fields = [
            ("Log-likelihood", 'training_loss')]

        fields = [model_fields, solver_fields, training_fields]:

        section_titles = ['Model description',
                          'Solver description',
                          'Training information']

        _toolkit_repr_print(model, fields, section_titles)

def _toolkit_repr_print(model, fields, section_titles, width = None):
    """
    Display a toolkit repr according to some simple rules.

    Parameters
    ----------
    model : Turi Create model

    fields: List of lists of tuples
        Each tuple should be (display_name, field_name), where field_name can
        be a string or a _precomputed_field object.


    section_titles: List of section titles, one per list in the fields arg.

    Example
    -------

        model_fields = [
            ("L1 penalty", 'l1_penalty'),
            ("L2 penalty", 'l2_penalty'),
            ("Examples", 'num_examples'),
            ("Features", 'num_features'),
            ("Coefficients", 'num_coefficients')]

        solver_fields = [
            ("Solver", 'solver'),
            ("Solver iterations", 'training_iterations'),
            ("Solver status", 'training_solver_status'),
            ("Training time (sec)", 'training_time')]

        training_fields = [
            ("Log-likelihood", 'training_loss')]

        fields = [model_fields, solver_fields, training_fields]:

        section_titles = ['Model description',
                          'Solver description',
                          'Training information']

        _toolkit_repr_print(model, fields, section_titles)
    """

    assert len(section_titles) == len(fields), \
        "The number of section titles ({0}) ".format(len(section_titles)) +\
        "doesn't match the number of groups of fields, {0}.".format(len(fields))

    out_fields = [ ("Class", model.__class__.__name__), ""]

    # Record the max_width so that if width is not provided, we calculate it.
    max_width = len("Class")

    for index, (section_title, field_list) in enumerate(zip(section_titles, fields)):

        # Add in the section header.
        out_fields += [section_title, "-"*len(section_title)]

        # Add in all the key-value pairs
        for f in field_list:
            if isinstance(f, tuple):
                f = (str(f[0]), f[1])
                out_fields.append( (f[0], __extract_model_summary_value(model, f[1])) )
                max_width = max(max_width, len(f[0]))
            elif isinstance(f, _SFrame):
                out_fields.append("")
                out_fields += _make_repr_table_from_sframe(f)
                out_fields.append("")
            else:
                raise TypeError("Type of field %s not recognized." % str(f))

        # Add in the empty footer.
        out_fields.append("")

    if width is None:
        width = max_width

    # Now, go through and format the key_value pairs nicely.
    def format_key_pair(key, value):
        if type(key) is list:
            key = ','.join(str(k) for k in key)

        return key.ljust(width, ' ') + ' : ' + str(value)
    out_fields = [s if type(s) is str else format_key_pair(*s) for s in out_fields]

    return '\n'.join(out_fields)