← eval5_submission_v1s

rich_2725

resolved RESOLVED LOOP PASS · 23 tool calls · 163 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 (24)

#ToolArgumentsResult
1run_command
{
 "command": "grep -rn \"table.box\" . | head -20"
}
{"status": "ok", "stdout": "./examples/table_movie.py:172: table.box = box_style\n./rich/box.py:475: table.box = getattr(box, box_name)\n", "stderr": "", "exit_
full
{"status": "ok", "stdout": "./examples/table_movie.py:172:            table.box = box_style\n./rich/box.py:475:        table.box = getattr(box, box_name)\n", "stderr": "", "exit_code": 0}
2run_command
{
 "command": "grep -rn \"mid_left\" . | head -20"
}
{"status": "ok", "stdout": "./rich/table.py:784: _Segment(_box.mid_left, border_style),\n./rich/box.py:50: self.mid_left, _, self.mid_vertical, self.mid_right =
full
{"status": "ok", "stdout": "./rich/table.py:784:                    _Segment(_box.mid_left, border_style),\n./rich/box.py:50:        self.mid_left, _, self.mid_vertical, self.mid_right = iter(line4)\n./rich/box.py:146:            left = self.mid_left\n./rich/panel.py:226:        line_start = Segment(box.mid_left, border_style)\n", "stderr": "", "exit_code": 0}
3-5 ×3read_file
{
 "filepath": "rich/table.py",
 "start_line": "700",
 "end_line": "850"
}
{"status": "error", "error_type": "FileReadError", "error_message": "'>' not supported between instances of 'int' and 'str'"}
full
{"status": "error", "error_type": "FileReadError", "error_message": "'>' not supported between instances of 'int' and 'str'"}
6run_command
{
 "command": "grep -n \"mid_left\" rich/table.py"
}
{"status": "ok", "stdout": "784: _Segment(_box.mid_left, border_style),\n", "stderr": "", "exit_code": 0}
full
{"status": "ok", "stdout": "784:                    _Segment(_box.mid_left, border_style),\n", "stderr": "", "exit_code": 0}
7read_file
{
 "end_line": "820",
 "filepath": "rich/table.py",
 "start_line": "750"
}
{"status": "error", "error_type": "FileReadError", "error_message": "'>' not supported between instances of 'int' and 'str'"}
full
{"status": "error", "error_type": "FileReadError", "error_message": "'>' not supported between instances of 'int' and 'str'"}
8run_command
{
 "command": "sed -n '750,820p' rich/table.py"
}
{"status": "ok", "stdout": " )\n row_cells: List[Tuple[_Cell, ...]] = list(zip(*_column_cells))\n _box = (\n self.box.substitute(\n options, safe=pick_bool(self
full
{"status": "ok", "stdout": "        )\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 and not footer_row)\n        
9run_command
{
 "command": "sed -n '821,900p' rich/table.py"
}
{"status": "ok", "stdout": " )\n lines = console.render_lines(\n cell.renderable,\n render_options,\n style=get_style(cell.style) + row_style,\n )\n max_height
full
{"status": "ok", "stdout": "                )\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 whitespace also style it with the row
10run_command
{
 "command": "sed -n '770,795p' rich/table.py"
}
{"status": "ok", "stdout": " _Segment = Segment\n if _box:\n box_segments = [\n (\n _Segment(_box.head_left, border_style),\n _Segment(_box.head_right, border_s
full
{"status": "ok", "stdout": "        _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", "stderr": "", "exit_code": 0}
11run_command
{
 "command": "sed -n '850,865p' rich/table.py"
}
{"status": "ok", "stdout": " _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_heig
full
{"status": "ok", "stdout": "                _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", "stderr": "", "exit_code": 0}
12run_command
{
 "command": "sed -n '866,875p' rich/table.py"
}
{"status": "ok", "stdout": " _box.get_row(widths, \"foot\", edge=show_edge), border_style\n )\n yield new_line\n left, right, _divider = box_segments[0 if first
full
{"status": "ok", "stdout": "                        _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 whitespace also style it with the row background\n                divider = (\n                    _divider\n                    if _divider.text.strip()\n                    else _Segment(\n", "stderr": "", "exit_code": 0}
13run_command
{
 "command": "cat <<EOF > reproduce_issue.py\nfrom rich.table import Table\nfrom rich.console import Console\nfrom rich import print as rprint\n\ntable = Table()\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 identify them\nclass CustomBox:\n    head_left = '1'\n    head_vertical = '2'\n    head_right = '3'\n    mid_left = '4'\n    mid_vertical = '5'\n    mid_right = '6'\n    foot_left = '7'\n    foot_vertical = '8'\n    foot_right = '9'\n    \n    def substitute(self, options, safe):\n        return self\n    def get_plain_headed_box(self):\n        return self\n    def get_top(self, widths):\n        return \"+\" + \"-\" * (sum(widths) + len(widths) - 1) + \"+\"\n    def get_row(self, widths, type, edge):\n        if type == \"head\":\n            return \"H\" * (sum(widths) + len(widths) - 1)\n        if type == \"foot\":\n            return \"F\" * (sum(widths) + len(widths) - 1)\n        return \"R\" * (sum(widths) + len(widths) - 1)\n\ntable.box = CustomBox()\nconsole = Console(force_terminal=True, width=100)\nconsole.print(table)\nEOF\npython reproduce_issue.py\n"
}
{"status": "error", "error_type": "CommandError", "error_message": "Traceback (most recent call last):\n File \"/workspace/reproduce_issue.py\", line 42, in <mo
full
{"status": "error", "error_type": "CommandError", "error_message": "Traceback (most recent call last):\n  File \"/workspace/reproduce_issue.py\", line 42, in <module>\n    console.print(table)\n    ~~~~~~~~~~~~~^^^^^^^\n  File \"/workspace/rich/console.py\", line 1699, in print\n    extend(render(renderable, render_options))\n    ~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n  File \"/workspace/rich/console.py\", line 1331, in render\n    for render_output in iter_render:\n                         ^^^^^^^^^^^\n  File \"/workspace/rich/table.py\", line 509, in __rich_console__\n    yield from self._render(console, render_options, widths)\n  File \"/workspace/rich/table.py\", line 918, in _render\n    yield _Segment(_box.get_bottom(widths), border_style)\n                   ^^^^^^^^^^^^^^^\nAttributeError: 'CustomBox' object has no attribute 'get_bottom'\n", "details": {"stdout": "", "stderr": "Traceback (most recent call last):\n  File \"/workspace/reproduce_issue.py\", line 42, in <module>\n    console.print(table)\n    ~~~~~~~~~~~~~^^^^^^^\n  File \"/workspace/rich/console.py\", line 1699, in print\n    extend(render(renderable, render_options))\n    ~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n  File \"/workspace/rich/console.py\", line 1331, in render\n    for render_output in iter_render:\n                         ^^^^^^^^^^^\n  File \"/workspace/rich/table.py\", line 509, in __rich_console__\n    yield from self._render(console, render_options, widths)\n  File \"/workspace/rich/table.py\", line 918, in _render\n    yield _Segment(_box.get_bottom(widths), border_style)\n                   ^^^^^^^^^^^^^^^\nAttributeError: 'CustomBox' object has no attribute 'get_bottom'\n", "exit_code": 1}}
14run_command
{
 "command": "cat <<EOF > reproduce_issue.py\nfrom rich.table import Table\nfrom rich.console import Console\nfrom rich.box import Box\n\ntable = Table()\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# We can't easily create a CustomBox because it's a complex object.\n# Instead, let's use a real Box object and modify its attributes.\nbox = Box()\nbox.head_left = '1'\nbox.head_vertical = '2'\nbox.head_right = '3'\nbox.mid_left = '4'\nbox.mid_vertical = '5'\nbox.mid_right = '6'\nbox.foot_left = '7'\nbox.foot_vertical = '8'\nbox.foot_right = '9'\n\ntable.box = box\nconsole = Console(force_terminal=True, width=100)\nconsole.print(table)\nEOF\npython reproduce_issue.py\n"
}
{"status": "error", "error_type": "CommandError", "error_message": "Traceback (most recent call last):\n File \"/workspace/reproduce_issue.py\", line 17, in <mo
full
{"status": "error", "error_type": "CommandError", "error_message": "Traceback (most recent call last):\n  File \"/workspace/reproduce_issue.py\", line 17, in <module>\n    box = Box()\nTypeError: Box.__init__() missing 1 required positional argument: 'box'\n", "details": {"stdout": "", "stderr": "Traceback (most recent call last):\n  File \"/workspace/reproduce_issue.py\", line 17, in <module>\n    box = Box()\nTypeError: Box.__init__() missing 1 required positional argument: 'box'\n", "exit_code": 1}}
15run_command
{
 "command": "cat <<EOF > reproduce_issue.py\nfrom rich.table import Table\nfrom rich.console import Console\nfrom rich.box import ROUNDED\n\ntable = Table()\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# Use ROUNDED as a template and modify it.\n# Since Box objects are likely immutable or shared, we should be careful.\n# But for a reproduction script, it's fine.\nimport copy\nbox = copy.deepcopy(ROUNDED)\nbox.head_left = '1'\nbox.head_vertical = '2'\nbox.head_right = '3'\nbox.mid_left = '4'\nbox.mid_vertical = '5'\nbox.mid_right = '6'\nbox.foot_left = '7'\nbox.foot_vertical = '8'\nbox.foot_right = '9'\n\ntable.box = box\nconsole = Console(force_terminal=True, width=100)\nconsole.print(table)\nEOF\npython reproduce_issue.py\n"
}
{"status": "ok", "stdout": "\u256d\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500
full
{"status": "ok", "stdout": "\u256d\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u256e\n1 Date         2 Title                         2 Production   2 Box Office     3\n\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n7 Dec 20, 2019 8 Star Wars: The Rise of        8 $275,000,000 8 $375,126,118   9\n7              8 Skywalker                     8              8                9\n7 May 25, 2018 8 Solo: A Star Wars Story       8 $275,000,000 8 $393,151,347   9\n4 Dec 15, 2017 5 Star Wars Ep. VIII: The Last  5 $262,000,000 5 $1,332,539,889 6\n4              5 Jedi                          5              5                6\n\u2570\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u256f\n", "stderr": "", "exit_code": 0}
16run_command
{
 "command": "python reproduce_issue.py"
}
{"status": "ok", "stdout": "\u256d\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500
full
{"status": "ok", "stdout": "\u256d\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u256e\n1 Date         2 Title                         2 Production   2 Box Office     3\n\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n7 Dec 20, 2019 8 Star Wars: The Rise of        8 $275,000,000 8 $375,126,118   9\n7              8 Skywalker                     8              8                9\n7 May 25, 2018 8 Solo: A Star Wars Story       8 $275,000,000 8 $393,151,347   9\n4 Dec 15, 2017 5 Star Wars Ep. VIII: The Last  5 $262,000,000 5 $1,332,539,889 6\n4              5 Jedi                          5              5                6\n\u2570\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u256f\n", "stderr": "", "exit_code": 0}
17run_command
{
 "command": "python reproduce_issue.py | cat -A"
}
{"status": "ok", "stdout": "M-bM-^UM--M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M
full
{"status": "ok", "stdout": "M-bM-^UM--M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-,M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-,M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-,M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^UM-.$\n1 Date         2 Title                         2 Production   2 Box Office     3$\nM-bM-^TM-^\\M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-<M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-<M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-<M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-^@M-bM-^TM-$$\n7 Dec 20, 2019 8 Star Wars: The Rise of        8 $275,000,000 8 $375,126,118   9$\n7              8 Skywalker                     8
18run_command
{
 "command": "python reproduce_issue.py | grep -E '^[47]'"
}
{"status": "ok", "stdout": "7 Dec 20, 2019 8 Star Wars: The Rise of 8 $275,000,000 8 $375,126,118 9\n7 8 Skywalker 8 8 9\n7 May 25, 2018 8 Solo: A Star Wars Sto
full
{"status": "ok", "stdout": "7 Dec 20, 2019 8 Star Wars: The Rise of        8 $275,000,000 8 $375,126,118   9\n7              8 Skywalker                     8              8                9\n7 May 25, 2018 8 Solo: A Star Wars Story       8 $275,000,000 8 $393,151,347   9\n4 Dec 15, 2017 5 Star Wars Ep. VIII: The Last  5 $262,000,000 5 $1,332,539,889 6\n4              5 Jedi                          5              5                6\n", "stderr": "", "exit_code": 0}
19run_command
{
 "command": "sed -n '775,790p' rich/table.py"
}
{"status": "ok", "stdout": " _Segment(_box.head_right, border_style),\n _Segment(_box.head_vertical, border_style),\n ),\n (\n _Segment(_box.foot_left, border_s
full
{"status": "ok", "stdout": "                    _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", "stderr": "", "exit_code": 0}
20run_command
{
 "command": "sed -n '865,875p' rich/table.py"
}
{"status": "ok", "stdout": " yield _Segment(\n _box.get_row(widths, \"foot\", edge=show_edge), border_style\n )\n yield new_line\n left, right, _divider = box_s
full
{"status": "ok", "stdout": "                    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 whitespace also style it with the row background\n                divider = (\n                    _divider\n                    if _divider.text.strip()\n                    else _Segment(\n", "stderr": "", "exit_code": 0}
21run_command
{
 "command": "sed -n '866,870p' rich/table.py"
}
{"status": "ok", "stdout": " _box.get_row(widths, \"foot\", edge=show_edge), border_style\n )\n yield new_line\n left, right, _divider = box_segments[0 if first
full
{"status": "ok", "stdout": "                        _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", "stderr": "", "exit_code": 0}
22edit_file
{
 "filepath": "rich/table.py",
 "new_string": "                left, right, _divider = box_segments[0 if first else (1 if last else 2)]",
 "old_string": "                left, right, _divider = box_segments[0 if first else (2 if last else 1)]"
}
{"status": "ok", "filepath": "rich/table.py", "occurrences": 1, "strategy": "exact", "diff": "--- a/rich/table.py\n+++ b/rich/table.py\n@@ -866,7 +866,7 @@\n _b
full
{"status": "ok", "filepath": "rich/table.py", "occurrences": 1, "strategy": "exact", "diff": "--- a/rich/table.py\n+++ b/rich/table.py\n@@ -866,7 +866,7 @@\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+                left, right, _divider = box_segments[0 if first else (1 if last else 2)]\n \n                 # If the column divider is whitespace also style it with the row background\n                 divider = (\n", "is_truncated": false}
23run_command
{
 "command": "python reproduce_issue.py | grep -E '^[47]'"
}
{"status": "ok", "stdout": "4 Dec 20, 2019 5 Star Wars: The Rise of 5 $275,000,000 5 $375,126,118 6\n4 5 Skywalker 5 5 6\n4 May 25, 2018 5 Solo: A Star Wars Sto
full
{"status": "ok", "stdout": "4 Dec 20, 2019 5 Star Wars: The Rise of        5 $275,000,000 5 $375,126,118   6\n4              5 Skywalker                     5              5                6\n4 May 25, 2018 5 Solo: A Star Wars Story       5 $275,000,000 5 $393,151,347   6\n7 Dec 15, 2017 8 Star Wars Ep. VIII: The Last  8 $262,000,000 8 $1,332,539,889 9\n7              8 Jedi                          8              8                9\n", "stderr": "", "exit_code": 0}
24submit_patch
{}
{"status": "ok", "patch_size": 1789, "files_changed": 2}
full
{"status": "ok", "patch_size": 1789, "files_changed": 2}

Patch

diff --git a/reproduce_issue.py b/reproduce_issue.py
new file mode 100644
index 00000000..3796693c
--- /dev/null
+++ b/reproduce_issue.py
@@ -0,0 +1,32 @@
+from rich.table import Table
+from rich.console import Console
+from rich.box import ROUNDED
+
+table = Table()
+table.add_column("Date")
+table.add_column("Title")
+table.add_column("Production")
+table.add_column("Box Office")
+
+table.add_row("Dec 20, 2019", "Star Wars: The Rise of Skywalker", "$275,000,000", "$375,126,118")
+table.add_row("May 25, 2018", "Solo: A Star Wars Story", "$275,000,000", "$393,151,347")
+table.add_row("Dec 15, 2017", "Star Wars Ep. VIII: The Last Jedi", "$262,000,000", "$1,332,539,889")
+
+# Use ROUNDED as a template and modify it.
+# Since Box objects are likely immutable or shared, we should be careful.
+# But for a reproduction script, it's fine.
+import copy
+box = copy.deepcopy(ROUNDED)
+box.head_left = '1'
+box.head_vertical = '2'
+box.head_right = '3'
+box.mid_left = '4'
+box.mid_vertical = '5'
+box.mid_right = '6'
+box.foot_left = '7'
+box.foot_vertical = '8'
+box.foot_right = '9'
+
+table.box = box
+console = Console(force_terminal=True, width=100)
+console.print(table)
diff --git a/rich/table.py b/rich/table.py
index fe4054cf..6268cba4 100644
--- a/rich/table.py
+++ b/rich/table.py
@@ -866,7 +866,7 @@ class Table(JupyterMixin):
                         _box.get_row(widths, "foot", edge=show_edge), border_style
                     )
                     yield new_line
-                left, right, _divider = box_segments[0 if first else (2 if last else 1)]
+                left, right, _divider = box_segments[0 if first else (1 if last else 2)]
 
                 # If the column divider is whitespace also style it with the row background
                 divider = (

Test output

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