def auto_table_layout(context, box, containing_block):
    """Run the auto table layout and return a list of column widths.

    https://www.w3.org/TR/CSS21/tables.html#auto-table-layout

    """
    table = box.get_wrapped_table()
    (table_min_content_width, table_max_content_width,
     column_min_content_widths, column_max_content_widths,
     column_intrinsic_percentages, constrainedness,
     total_horizontal_border_spacing, grid) = table_and_columns_preferred_widths(
         context, box, outer=False)

    margins = 0
    if box.margin_left != 'auto':
        margins += box.margin_left
    if box.margin_right != 'auto':
        margins += box.margin_right
    paddings = table.padding_left + table.padding_right
    borders = table.border_left_width + table.border_right_width

    cb_width, _ = containing_block
    available_width = cb_width - margins - paddings - borders

    if table.width == 'auto':
        if available_width <= table_min_content_width:
            table.width = table_min_content_width
        elif available_width < table_max_content_width:
            table.width = available_width
        else:
            table.width = table_max_content_width
    else:
        if table.width < table_min_content_width:
            table.width = table_min_content_width

    if not grid:
        table.column_widths = []
        return

    assignable_width = table.width - total_horizontal_border_spacing
    min_content_guess = column_min_content_widths[:]
    min_content_percentage_guess = column_min_content_widths[:]
    min_content_specified_guess = column_min_content_widths[:]
    max_content_guess = column_max_content_widths[:]
    guesses = (
        min_content_guess, min_content_percentage_guess,
        min_content_specified_guess, max_content_guess)
    # See https://www.w3.org/TR/css-tables-3/#width-distribution-algorithm.
    for i in range(len(grid)):
        if column_intrinsic_percentages[i]:
            min_content_percentage_guess[i] = max(
                column_intrinsic_percentages[i] / 100 * assignable_width,
                column_min_content_widths[i])
            min_content_specified_guess[i] = min_content_percentage_guess[i]
            max_content_guess[i] = min_content_percentage_guess[i]
        elif constrainedness[i]:
            # Any other column that is constrained is assigned its max-content
            # width.
            min_content_specified_guess[i] = column_max_content_widths[i]

    if assignable_width < sum(max_content_guess):
        # Default values shouldn't be used, but we never know.
        # See https://github.com/Kozea/WeasyPrint/issues/770
        lower_guess = guesses[0]
        upper_guess = guesses[-1]

        # We have to work around floating point rounding errors here.
        # The 1e-9 value comes from PEP 485.
        for guess in guesses:
            if sum(guess) <= assignable_width * (1 + 1e-9):
                lower_guess = guess
            else:
                break
        for guess in guesses[::-1]:
            if sum(guess) >= assignable_width * (1 - 1e-9):
                upper_guess = guess
            else:
                break
        if upper_guess == lower_guess:
            table.column_widths = upper_guess
        else:
            added_widths = [
                upper_guess[i] - lower_guess[i] for i in range(len(grid))]
            available_ratio = (assignable_width - sum(lower_guess)) / sum(added_widths)
            table.column_widths = [
                lower_guess[i] + added_widths[i] * available_ratio
                for i in range(len(grid))]
    else:
        table.column_widths = max_content_guess
        excess_width = assignable_width - sum(max_content_guess)
        distribute_excess_width(
            context, grid, excess_width, table.column_widths, constrainedness,
            column_intrinsic_percentages, column_max_content_widths)
Run the auto table layout and return a list of column widths.

https://www.w3.org/TR/CSS21/tables.html#auto-table-layout
weasyprint/layout/table.py