← or20_submission

rich_2725

resolved RESOLVED PASS · 11 tool calls · 62 s · Textualize/rich

Task input

fix table rendering order of box elements

## Type of changes

- [x] Bug fix
- [ ] New feature
- [ ] Documentation / docstrings
- [x] Tests
- [ ] Other

## Checklist

- [x] I've run the latest [black](https://github.com/psf/black) with default args on new code.
- [x] I've updated CHANGELOG.md and CONTRIBUTORS.md where appropriate.
- [x] I've added tests for new code.
- [x] I accept that @willmcgugan may be pedantic in the code review.

## Description

* Previously "mid" box elements appeared in last line of table (footer), while "footer" box elements appeared mid table body. Reversed that order so mid is truly mid, footer is truly footer.
* Tested with:

    ```
    table.box.head_left = '1'
    table.box.head_vertical = '2'
    table.box.head_right = '3'

    table.box.mid_left = '4'
    table.box.mid_vertical = '5'
    table.box.mid_right = '6'

    table.box.foot_left = '7'
    table.box.foot_vertical = '8'
    table.box.foot_right = '9'
    ```

  After change, correct ordering:

    ```
    +--------------------------------------------------------------------------+
    1Date        2Title                            2  Production2    Box Office3
    |------------ --------------------------------- ------------ --------------|
    4Dec 20, 20195Star Wars: The Rise of Skywalker 5$275,000,0005  $375,126,1186
    4May 25, 20185Solo: A Star Wars Story          5$275,000,0005  $393,151,3476
    7Dec 15, 20178Star Wars Ep. VIII: The Last Jedi8$262,000,0008$1,332,539,8899
    +--------------------------------------------------------------------------+
    ```

* All non-skipped prior automated tests pass. No automated tests added. Unclear that additional test for box ordering would add proportionate value.

Tool calls (12)

#ToolArgumentsResult
1run_command
{
 "command": "grep -rn \"mid_left\" rich | head -20"
}
{"status": "ok", "stdout": "rich/box.py:50: self.mid_left, _, self.mid_vertical, self.mid_right = iter(line4)\nrich/box.py:146: left = self.mid_left\nrich/table
full
{"status": "ok", "stdout": "rich/box.py:50:        self.mid_left, _, self.mid_vertical, self.mid_right = iter(line4)\nrich/box.py:146:            left = self.mid_left\nrich/table.py:784:                    _Segment(_box.mid_left, border_style),\nrich/panel.py:226:        line_start = Segment(box.mid_left, border_style)\n", "exit_code": 0}
2read_file
{
 "filepath": "rich/table.py",
 "start_line": 750,
 "end_line": 820
}
{"status": "ok", "filepath": "rich/table.py", "content": " )\n row_cells: List[Tuple[_Cell, ...]] = list(zip(*_column_cells))\n _box = (\n self.box.substitute(\
full
{"status": "ok", "filepath": "rich/table.py", "content": "        )\n        row_cells: List[Tuple[_Cell, ...]] = list(zip(*_column_cells))\n        _box = (\n            self.box.substitute(\n                options, safe=pick_bool(self.safe_box, console.safe_box)\n            )\n            if self.box\n            else None\n        )\n        _box = _box.get_plain_headed_box() if _box and not self.show_header else _box\n\n        new_line = Segment.line()\n\n        columns = self.columns\n        show_header = self.show_header\n        show_footer = self.show_footer\n        show_edge = self.show_edge\n        show_lines = self.show_lines\n        leading = self.leading\n\n        _Segment = Segment\n        if _box:\n            box_segments = [\n                (\n                    _Segment(_box.head_left, border_style),\n                    _Segment(_box.head_right, border_style),\n                    _Segment(_box.head_vertical, border_style),\n                ),\n                (\n                    _Segment(_box.foot_left, border_style),\n                    _Segment(_box.foot_right, border_style),\n                    _Segment(_box.foot_vertical, border_style),\n                ),\n                (\n                    _Segment(_box.mid_left, border_style),\n                    _Segment(_box.mid_right, border_style),\n                    _Segment(_box.mid_vertical, border_style),\n                ),\n            ]\n            if show_edge:\n                yield _Segment(_box.get_top(widths), border_style)\n                yield new_line\n        else:\n            box_segments = []\n\n        get_row_style = self.get_row_style\n        get_style = console.get_style\n\n        for index, (first, last, row_cell) in enumerate(loop_first_last(row_cells)):\n            header_row = first and show_header\n            footer_row = last and show_footer\n            row = (\n                self.rows[index - show_header]\n                if (not header_row
3read_file
{
 "end_line": 900,
 "filepath": "rich/table.py",
 "start_line": 821
}
{"status": "ok", "filepath": "rich/table.py", "content": " )\n lines = console.render_lines(\n cell.renderable,\n render_options,\n style=get_style(cell.style)
full
{"status": "ok", "filepath": "rich/table.py", "content": "                )\n                lines = console.render_lines(\n                    cell.renderable,\n                    render_options,\n                    style=get_style(cell.style) + row_style,\n                )\n                max_height = max(max_height, len(lines))\n                cells.append(lines)\n\n            row_height = max(len(cell) for cell in cells)\n\n            def align_cell(\n                cell: List[List[Segment]],\n                vertical: \"VerticalAlignMethod\",\n                width: int,\n                style: Style,\n            ) -> List[List[Segment]]:\n                if header_row:\n                    vertical = \"bottom\"\n                elif footer_row:\n                    vertical = \"top\"\n\n                if vertical == \"top\":\n                    return _Segment.align_top(cell, width, row_height, style)\n                elif vertical == \"middle\":\n                    return _Segment.align_middle(cell, width, row_height, style)\n                return _Segment.align_bottom(cell, width, row_height, style)\n\n            cells[:] = [\n                _Segment.set_shape(\n                    align_cell(\n                        cell,\n                        _cell.vertical,\n                        width,\n                        get_style(_cell.style) + row_style,\n                    ),\n                    width,\n                    max_height,\n                )\n                for width, _cell, cell, column in zip(widths, row_cell, cells, columns)\n            ]\n\n            if _box:\n                if last and show_footer:\n                    yield _Segment(\n                        _box.get_row(widths, \"foot\", edge=show_edge), border_style\n                    )\n                    yield new_line\n                left, right, _divider = box_segments[0 if first else (2 if last else 1)]\n\n                # If the column divider is whitesp
4run_command
{
 "command": "python3 -c \"\nfrom rich.console import Console\nfrom rich.table import Table\nfrom rich.box import Box\n\nconsole = Console(width=100, force_terminal=True)\ntable = Table(show_header=True, show_footer=True)\ntable.add_column('Date')\ntable.add_column('Title')\ntable.add_column('Production')\ntable.add_column('Box Office')\n\ntable.add_row('Dec 20, 2019', 'Star Wars: The Rise of Skywalker', '$275,000,000', '$375,126,118')\ntable.add_row('May 25, 2018', 'Solo: A Star Wars Story', '$275,000,000', '$393,151,347')\ntable.add_row('Dec 15, 2017', 'Star Wars Ep. VIII: The Last Jedi', '$262,000,000', '$1,332,539,889')\n\n# Custom box characters to detect ordering\ncustom_box = Box()\ncustom_box.head_left = '1'\ncustom_box.head_vertical = '2'\ncustom_box.head_right = '3'\ncustom_box.mid_left = '4'\ncustom_box.mid_vertical = '5'\ncustom_box.mid_right = '6'\ncustom_box.foot_left = '7'\ncustom_box.foot_vertical = '8'\ncustom_box.foot_right = '9'\n\ntable.box = custom_box\nconsole.print(table)\n\""
}
{"status": "error", "error_type": "CommandError", "error_message": "Command failed with exit code 1", "details": {"stdout": "", "stderr": "Traceback (most recen
full
{"status": "error", "error_type": "CommandError", "error_message": "Command failed with exit code 1", "details": {"stdout": "", "stderr": "Traceback (most recent call last):\n  File \"<string>\", line 18, in <module>\n    custom_box = Box()\nTypeError: Box.__init__() missing 1 required positional argument: 'box'\n", "exit_code": 1}}
5read_file
{
 "end_line": 60,
 "filepath": "rich/box.py",
 "start_line": 1
}
{"status": "ok", "filepath": "rich/box.py", "content": "import sys\nfrom typing import TYPE_CHECKING, Iterable, List\n\nif sys.version_info >= (3, 8):\n from ty
full
{"status": "ok", "filepath": "rich/box.py", "content": "import sys\nfrom typing import TYPE_CHECKING, Iterable, List\n\nif sys.version_info >= (3, 8):\n    from typing import Literal\nelse:\n    from typing_extensions import Literal  # pragma: no cover\n\n\nfrom ._loop import loop_last\n\nif TYPE_CHECKING:\n    from rich.console import ConsoleOptions\n\n\nclass Box:\n    \"\"\"Defines characters to render boxes.\n\n    \u250c\u2500\u252c\u2510 top\n    \u2502 \u2502\u2502 head\n    \u251c\u2500\u253c\u2524 head_row\n    \u2502 \u2502\u2502 mid\n    \u251c\u2500\u253c\u2524 row\n    \u251c\u2500\u253c\u2524 foot_row\n    \u2502 \u2502\u2502 foot\n    \u2514\u2500\u2534\u2518 bottom\n\n    Args:\n        box (str): Characters making up box.\n        ascii (bool, optional): True if this box uses ascii characters only. Default is False.\n    \"\"\"\n\n    def __init__(self, box: str, *, ascii: bool = False) -> None:\n        self._box = box\n        self.ascii = ascii\n        line1, line2, line3, line4, line5, line6, line7, line8 = box.splitlines()\n        # top\n        self.top_left, self.top, self.top_divider, self.top_right = iter(line1)\n        # head\n        self.head_left, _, self.head_vertical, self.head_right = iter(line2)\n        # head_row\n        (\n            self.head_row_left,\n            self.head_row_horizontal,\n            self.head_row_cross,\n            self.head_row_right,\n        ) = iter(line3)\n\n        # mid\n        self.mid_left, _, self.mid_vertical, self.mid_right = iter(line4)\n        # row\n        self.row_left, self.row_horizontal, self.row_cross, self.row_right = iter(line5)\n        # foot_row\n        (\n            self.foot_row_left,\n            self.foot_row_horizontal,\n            self.foot_row_cross,\n            self.foot_row_right,\n        ) = iter(line6)\n        # foot\n", "start_line": 1, "end_line": 60, "total_lines": 480, "is_truncated": false}
6run_command
{
 "command": "python3 -c \"\nfrom rich.console import Console\nfrom rich.table import Table\nfrom rich.box import Box\n\nconsole = Console(width=100, force_terminal=True)\ntable = Table(show_header=True, show_footer=True)\ntable.add_column('Date')\ntable.add_column('Title')\ntable.add_column('Production')\ntable.add_column('Box Office')\n\ntable.add_row('Dec 20, 2019', 'Star Wars: The Rise of Skywalker', '$275,000,000', '$375,126,118')\ntable.add_row('May 25, 2018', 'Solo: A Star Wars Story', '$275,000,000', '$393,151,347')\ntable.add_row('Dec 15, 2017', 'Star Wars Ep. VIII: The Last Jedi', '$262,000,000', '$1,332,539,889')\n\n# Custom box characters to detect ordering\n# We need to provide a string that Box.__init__ can splitlines()\n# 8 lines total\nbox_str = (\n    '1111\\n' # top\n    '123 \\n' # head\n    '1111\\n' # head_row\n    '456 \\n' # mid\n    '1111\\n' # row\n    '1111\\n' # foot_row\n    '789 \\n' # foot\n    '1111'   # bottom\n)\ncustom_box = Box(box_str)\n# We can't easily override individual attributes because they are set in __init__\n# and the Box class doesn't seem to have a way to change them after init except by direct assignment.\n# Let's try direct assignment as in the issue description.\ncustom_box.head_left = '1'\ncustom_box.head_vertical = '2'\ncustom_box.head_right = '3'\ncustom_box.mid_left = '4'\ncustom_box.mid_vertical = '5'\ncustom_box.mid_right = '6'\ncustom_box.foot_left = '7'\ncustom_box.foot_vertical = '8'\ncustom_box.foot_right = '9'\n\ntable.box = custom_box\nconsole.print(table)\n\""
}
{"status": "ok", "stdout": "11111111111111111111111111111111111111111111111111111111111111111111111111111111\n1 Date 2 Title 2 Production 2 Box Office 3\n111111
full
{"status": "ok", "stdout": "11111111111111111111111111111111111111111111111111111111111111111111111111111111\n1 Date         2 Title                             2 Production 2 Box Office   3\n11111111111111111111111111111111111111111111111111111111111111111111111111111111\n7 Dec 20, 2019 8 Star Wars: The Rise of Skywalker  8 75,000,000 8 75,126,118   9\n7 May 25, 2018 8 Solo: A Star Wars Story           8 75,000,000 8 93,151,347   9\n7 Dec 15, 2017 8 Star Wars Ep. VIII: The Last Jedi 8 62,000,000 8 ,332,539,889 9\n11111111111111111111111111111111111111111111111111111111111111111111111111111111\n4              5                                   5            5              6\n11111111111111111111111111111111111111111111111111111111111111111111111111111111\n", "exit_code": 0}
7read_file
{
 "end_line": 795,
 "filepath": "rich/table.py",
 "start_line": 760
}
{"status": "ok", "filepath": "rich/table.py", "content": "\n new_line = Segment.line()\n\n columns = self.columns\n show_header = self.show_header\n show_footer
full
{"status": "ok", "filepath": "rich/table.py", "content": "\n        new_line = Segment.line()\n\n        columns = self.columns\n        show_header = self.show_header\n        show_footer = self.show_footer\n        show_edge = self.show_edge\n        show_lines = self.show_lines\n        leading = self.leading\n\n        _Segment = Segment\n        if _box:\n            box_segments = [\n                (\n                    _Segment(_box.head_left, border_style),\n                    _Segment(_box.head_right, border_style),\n                    _Segment(_box.head_vertical, border_style),\n                ),\n                (\n                    _Segment(_box.foot_left, border_style),\n                    _Segment(_box.foot_right, border_style),\n                    _Segment(_box.foot_vertical, border_style),\n                ),\n                (\n                    _Segment(_box.mid_left, border_style),\n                    _Segment(_box.mid_right, border_style),\n                    _Segment(_box.mid_vertical, border_style),\n                ),\n            ]\n            if show_edge:\n                yield _Segment(_box.get_top(widths), border_style)\n                yield new_line\n        else:\n            box_segments = []\n\n        get_row_style = self.get_row_style\n", "start_line": 760, "end_line": 795, "total_lines": 1000, "is_truncated": false}
8read_file
{
 "end_line": 870,
 "filepath": "rich/table.py",
 "start_line": 850
}
{"status": "ok", "filepath": "rich/table.py", "content": " _Segment.set_shape(\n align_cell(\n cell,\n _cell.vertical,\n width,\n get_style(_cell.style) + row_s
full
{"status": "ok", "filepath": "rich/table.py", "content": "                _Segment.set_shape(\n                    align_cell(\n                        cell,\n                        _cell.vertical,\n                        width,\n                        get_style(_cell.style) + row_style,\n                    ),\n                    width,\n                    max_height,\n                )\n                for width, _cell, cell, column in zip(widths, row_cell, cells, columns)\n            ]\n\n            if _box:\n                if last and show_footer:\n                    yield _Segment(\n                        _box.get_row(widths, \"foot\", edge=show_edge), border_style\n                    )\n                    yield new_line\n                left, right, _divider = box_segments[0 if first else (2 if last else 1)]\n\n", "start_line": 850, "end_line": 870, "total_lines": 1000, "is_truncated": false}
9edit_file
{
 "filepath": "rich/table.py",
 "new_string": "            box_segments = [\n                (\n                    _Segment(_box.head_left, border_style),\n                    _Segment(_box.head_right, border_style),\n                    _Segment(_box.head_vertical, border_style),\n                ),\n                (\n                    _Segment(_box.mid_left, border_style),\n                    _Segment(_box.mid_right, border_style),\n                    _Segment(_box.mid_vertical, border_style),\n                ),\n                (\n                    _Segment(_box.foot_left, border_style),\n                    _Segment(_box.foot_right, border_style),\n                    _Segment(_box.foot_vertical, border_style),\n                ),\n            ]",
 "old_string": "            box_segments = [\n                (\n                    _Segment(_box.head_left, border_style),\n                    _Segment(_box.head_right, border_style),\n                    _Segment(_box.head_vertical, border_style),\n                ),\n                (\n                    _Segment(_box.foot_left, border_style),\n                    _Segment(_box.foot_right, border_style),\n                    _Segment(_box.foot_vertical, border_style),\n                ),\n                (\n                    _Segment(_box.mid_left, border_style),\n                    _Segment(_box.mid_right, border_style),\n                    _Segment(_box.mid_vertical, border_style),\n                ),\n            ]"
}
{"status": "ok", "filepath": "rich/table.py", "occurrences": 1, "strategy": "exact", "diff": "--- a/rich/table.py\n+++ b/rich/table.py\n@@ -776,14 +776,14 @@\n
full
{"status": "ok", "filepath": "rich/table.py", "occurrences": 1, "strategy": "exact", "diff": "--- a/rich/table.py\n+++ b/rich/table.py\n@@ -776,14 +776,14 @@\n                     _Segment(_box.head_vertical, border_style),\n                 ),\n                 (\n+                    _Segment(_box.mid_left, border_style),\n+                    _Segment(_box.mid_right, border_style),\n+                    _Segment(_box.mid_vertical, border_style),\n+                ),\n+                (\n                     _Segment(_box.foot_left, border_style),\n                     _Segment(_box.foot_right, border_style),\n                     _Segment(_box.foot_vertical, border_style),\n-                ),\n-                (\n-                    _Segment(_box.mid_left, border_style),\n-                    _Segment(_box.mid_right, border_style),\n-                    _Segment(_box.mid_vertical, border_style),\n                 ),\n             ]\n             if show_edge:\n", "is_truncated": false}
10run_command
{
 "command": "python3 -c \"\nfrom rich.console import Console\nfrom rich.table import Table\nfrom rich.box import Box\n\nconsole = Console(width=100, force_terminal=True)\ntable = Table(show_header=True, show_footer=True)\ntable.add_column('Date')\ntable.add_column('Title')\ntable.add_column('Production')\ntable.add_column('Box Office')\n\ntable.add_row('Dec 20, 2019', 'Star Wars: The Rise of Skywalker', '$275,000,000', '$375,126,118')\ntable.add_row('May 25, 2018', 'Solo: A Star Wars Story', '$275,000,000', '$393,151,347')\ntable.add_row('Dec 15, 2017', 'Star Wars Ep. VIII: The Last Jedi', '$262,000,000', '$1,332,539,889')\n\nbox_str = (\n    '1111\\n' # top\n    '123 \\n' # head\n    '1111\\n' # head_row\n    '456 \\n' # mid\n    '1111\\n' # row\n    '1111\\n' # foot_row\n    '789 \\n' # foot\n    '1111'   # bottom\n)\ncustom_box = Box(box_str)\ncustom_box.head_left = '1'\ncustom_box.head_vertical = '2'\ncustom_box.head_right = '3'\ncustom_box.mid_left = '4'\ncustom_box.mid_vertical = '5'\ncustom_box.mid_right = '6'\ncustom_box.foot_left = '7'\ncustom_box.foot_vertical = '8'\ncustom_box.foot_right = '9'\n\ntable.box = custom_box\nconsole.print(table)\n\""
}
{"status": "ok", "stdout": "11111111111111111111111111111111111111111111111111111111111111111111111111111111\n1 Date 2 Title 2 Production 2 Box Office 3\n111111
full
{"status": "ok", "stdout": "11111111111111111111111111111111111111111111111111111111111111111111111111111111\n1 Date         2 Title                             2 Production 2 Box Office   3\n11111111111111111111111111111111111111111111111111111111111111111111111111111111\n4 Dec 20, 2019 5 Star Wars: The Rise of Skywalker  5 75,000,000 5 75,126,118   6\n4 May 25, 2018 5 Solo: A Star Wars Story           5 75,000,000 5 93,151,347   6\n4 Dec 15, 2017 5 Star Wars Ep. VIII: The Last Jedi 5 62,000,000 5 ,332,539,889 6\n11111111111111111111111111111111111111111111111111111111111111111111111111111111\n7              8                                   8            8              9\n11111111111111111111111111111111111111111111111111111111111111111111111111111111\n", "exit_code": 0}
11run_command
{
 "command": "python3 -c \"\nfrom rich.console import Console\nfrom rich.table import Table\nfrom rich.box import Box\n\nconsole = Console(width=100, force_terminal=True)\ntable = Table(show_header=True, show_footer=True)\ntable.add_column('Date')\ntable.add_column('Title')\ntable.add_column('Production')\ntable.add_column('Box Office')\n\ntable.add_row('Dec 20, 2019', 'Star Wars: The Rise of Skywalker', '$275,000,000', '$375,126,118')\ntable.add_row('May 25, 2018', 'Solo: A Star Wars Story', '$275,000,000', '$393,151,347')\ntable.add_row('Dec 15, 2017', 'Star Wars Ep. VIII: The Last Jedi', '$262,000,000', '$1,332,539,889')\n\nbox_str = (\n    '1111\\n' # top\n    '123 \\n' # head\n    '1111\\n' # head_row\n    '456 \\n' # mid\n    '1111\\n' # row\n    '1111\\n' # foot_row\n    '789 \\n' # foot\n    '1111'   # bottom\n)\ncustom_box = Box(box_str)\ncustom_box.head_left = '1'\ncustom_box.head_vertical = '2'\ncustom_box.head_right = '3'\ncustom_box.mid_left = '4'\ncustom_box.mid_vertical = '5'\ncustom_box.mid_right = '6'\ncustom_box.foot_left = '7'\ncustom_box.foot_vertical = '8'\ncustom_box.foot_right = '9'\n\ntable.box = custom_box\n# To test footer row, we need to add a footer. \n# In rich.Table, show_footer=True means the last row of data is treated as footer if it's the last row.\n# Wait, the issue description says:\n# \\\"Previously 'mid' box elements appeared in last line of table (footer), while 'footer' box elements appeared mid table body.\\\"\n# Let's see how rich.Table handles footer.\n# In rich/table.py:\n# footer_row = last and show_footer\n# if last and show_footer:\n#     yield _Segment(_box.get_row(widths, \\\"foot\\\", edge=show_edge), border_style)\n#     yield new_line\n# left, right, _divider = box_segments[0 if first else (2 if last else 1)]\n\n# If show_footer=True, the last row is a footer_row.\n# If first=False and last=True, it uses box_segments[2].\n# In my previous run:\n# box_segments[0] = head\n# box_segments[1] = mid\n# box_segments[2] = foot\n# So for the last row (last=True), it uses box_segments[2], which is now foot.\n# For the middle rows (first=False, last=False), it uses box_segments[1], which is now mid.\n# This matches the desired behavior.\n\n# Let's double check the output of the previous run.\n# The last row of data:\n# 4 Dec 15, 2017 5 Star Wars Ep. VIII: The Last Jedi 5 62,000,000 5 ,332,539,889 6\n# Wait, this is the last row of DATA.\n# But there is another line after it:\n# 7              8                                   8            8              9\n# This is the footer row!\n# In rich.Table, if show_footer=True, it adds an extra row at the bottom for the footer.\n# Let's check rich/table.py again.\n# row_cells: List[Tuple[_Cell, ...]] = list(zip(*_column_cells))\n# _column_cells contains the cells for each column.\n# If show_footer=True, the footer cells are added to _column_cells.\n\n# Let's try to add a footer explicitly if possible, or just use the default.\n# The output I got:\n# 4 Dec 20, 2019 ... 6\n# 4 May 25, 2018 ... 6\n# 4 Dec 15, 2017 ... 6\n# 7              8 ... 9\n# This means the data rows are using 'mid' (4,5,6) and the footer row is using 'foot' (7,8,9).\n# This is exactly what was requested.\nconsole.print(table)\n\""
}
{"status": "ok", "stdout": "11111111111111111111111111111111111111111111111111111111111111111111111111111111\n1 Date 2 Title 2 Production 2 Box Office 3\n111111
full
{"status": "ok", "stdout": "11111111111111111111111111111111111111111111111111111111111111111111111111111111\n1 Date         2 Title                             2 Production 2 Box Office   3\n11111111111111111111111111111111111111111111111111111111111111111111111111111111\n4 Dec 20, 2019 5 Star Wars: The Rise of Skywalker  5 75,000,000 5 75,126,118   6\n4 May 25, 2018 5 Solo: A Star Wars Story           5 75,000,000 5 93,151,347   6\n4 Dec 15, 2017 5 Star Wars Ep. VIII: The Last Jedi 5 62,000,000 5 ,332,539,889 6\n11111111111111111111111111111111111111111111111111111111111111111111111111111111\n7              8                                   8            8              9\n11111111111111111111111111111111111111111111111111111111111111111111111111111111\n", "exit_code": 0}
12submit_patch
[]
{"status": "ok", "patch_size": 1099, "files_changed": 1}
full
{"status": "ok", "patch_size": 1099, "files_changed": 1}

Patch

diff --git a/rich/table.py b/rich/table.py
index fe4054cf..44e457be 100644
--- a/rich/table.py
+++ b/rich/table.py
@@ -775,16 +775,16 @@ class Table(JupyterMixin):
                     _Segment(_box.head_right, border_style),
                     _Segment(_box.head_vertical, border_style),
                 ),
-                (
-                    _Segment(_box.foot_left, border_style),
-                    _Segment(_box.foot_right, border_style),
-                    _Segment(_box.foot_vertical, border_style),
-                ),
                 (
                     _Segment(_box.mid_left, border_style),
                     _Segment(_box.mid_right, border_style),
                     _Segment(_box.mid_vertical, border_style),
                 ),
+                (
+                    _Segment(_box.foot_left, border_style),
+                    _Segment(_box.foot_right, border_style),
+                    _Segment(_box.foot_vertical, border_style),
+                ),
             ]
             if show_edge:
                 yield _Segment(_box.get_top(widths), border_style)

Test output

show
...................                                                      [100%]
19 passed in 0.12s