We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
[BUG] `Panel.fit` forgot `height` and `highlight` parameters
- [x] I've checked [docs](https://rich.readthedocs.io/en/latest/introduction.html) and [closed issues](https://github.com/Textualize/rich/issues?q=is%3Aissue+is%3Aclosed) for possible solutions.
- [x] I can't find my issue in the [FAQ](https://github.com/Textualize/rich/blob/master/FAQ.md).

**Describe the bug**

`Panel.fit` forgot `height` and `highlight` parameters. It should be updated to synchronize with the constructor.

```python
class Panel(JupyterMixin):
    def __init__(
        self,
        renderable: "RenderableType",
        box: Box = ROUNDED,
        *,
        title: Optional[TextType] = None,
        title_align: AlignMethod = "center",
        subtitle: Optional[TextType] = None,
        subtitle_align: AlignMethod = "center",
        safe_box: Optional[bool] = None,
        expand: bool = True,
        style: StyleType = "none",
        border_style: StyleType = "none",
        width: Optional[int] = None,
        height: Optional[int] = None,
        padding: PaddingDimensions = (0, 1),
        highlight: bool = False,
    ) -> None:
        ...

    @classmethod
    def fit(
        cls,
        renderable: "RenderableType",
        box: Box = ROUNDED,
        *,
        title: Optional[TextType] = None,
        title_align: AlignMethod = "center",
        subtitle: Optional[TextType] = None,
        subtitle_align: AlignMethod = "center",
        safe_box: Optional[bool] = None,
        style: StyleType = "none",
        border_style: StyleType = "none",
        width: Optional[int] = None,
        padding: PaddingDimensions = (0, 1),
    ) -> "Panel":
        ...
```

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `rich/panel.py`
Content:
```
1 from typing import TYPE_CHECKING, Optional
2 
3 from .align import AlignMethod
4 from .box import ROUNDED, Box
5 from .cells import cell_len
6 from .jupyter import JupyterMixin
7 from .measure import Measurement, measure_renderables
8 from .padding import Padding, PaddingDimensions
9 from .segment import Segment
10 from .style import Style, StyleType
11 from .text import Text, TextType
12 
13 if TYPE_CHECKING:
14     from .console import Console, ConsoleOptions, RenderableType, RenderResult
15 
16 
17 class Panel(JupyterMixin):
18     """A console renderable that draws a border around its contents.
19 
20     Example:
21         >>> console.print(Panel("Hello, World!"))
22 
23     Args:
24         renderable (RenderableType): A console renderable object.
25         box (Box, optional): A Box instance that defines the look of the border (see :ref:`appendix_box`.
26             Defaults to box.ROUNDED.
27         safe_box (bool, optional): Disable box characters that don't display on windows legacy terminal with *raster* fonts. Defaults to True.
28         expand (bool, optional): If True the panel will stretch to fill the console
29             width, otherwise it will be sized to fit the contents. Defaults to True.
30         style (str, optional): The style of the panel (border and contents). Defaults to "none".
31         border_style (str, optional): The style of the border. Defaults to "none".
32         width (Optional[int], optional): Optional width of panel. Defaults to None to auto-detect.
33         height (Optional[int], optional): Optional height of panel. Defaults to None to auto-detect.
34         padding (Optional[PaddingDimensions]): Optional padding around renderable. Defaults to 0.
35         highlight (bool, optional): Enable automatic highlighting of panel title (if str). Defaults to False.
36     """
37 
38     def __init__(
39         self,
40         renderable: "RenderableType",
41         box: Box = ROUNDED,
42         *,
43         title: Optional[TextType] = None,
44         title_align: AlignMethod = "center",
45         subtitle: Optional[TextType] = None,
46         subtitle_align: AlignMethod = "center",
47         safe_box: Optional[bool] = None,
48         expand: bool = True,
49         style: StyleType = "none",
50         border_style: StyleType = "none",
51         width: Optional[int] = None,
52         height: Optional[int] = None,
53         padding: PaddingDimensions = (0, 1),
54         highlight: bool = False,
55     ) -> None:
56         self.renderable = renderable
57         self.box = box
58         self.title = title
59         self.title_align: AlignMethod = title_align
60         self.subtitle = subtitle
61         self.subtitle_align = subtitle_align
62         self.safe_box = safe_box
63         self.expand = expand
64         self.style = style
65         self.border_style = border_style
66         self.width = width
67         self.height = height
68         self.padding = padding
69         self.highlight = highlight
70 
71     @classmethod
72     def fit(
73         cls,
74         renderable: "RenderableType",
75         box: Box = ROUNDED,
76         *,
77         title: Optional[TextType] = None,
78         title_align: AlignMethod = "center",
79         subtitle: Optional[TextType] = None,
80         subtitle_align: AlignMethod = "center",
81         safe_box: Optional[bool] = None,
82         style: StyleType = "none",
83         border_style: StyleType = "none",
84         width: Optional[int] = None,
85         padding: PaddingDimensions = (0, 1),
86     ) -> "Panel":
87         """An alternative constructor that sets expand=False."""
88         return cls(
89             renderable,
90             box,
91             title=title,
92             title_align=title_align,
93             subtitle=subtitle,
94             subtitle_align=subtitle_align,
95             safe_box=safe_box,
96             style=style,
97             border_style=border_style,
98             width=width,
99             padding=padding,
100             expand=False,
101         )
102 
103     @property
104     def _title(self) -> Optional[Text]:
105         if self.title:
106             title_text = (
107                 Text.from_markup(self.title)
108                 if isinstance(self.title, str)
109                 else self.title.copy()
110             )
111             title_text.end = ""
112             title_text.plain = title_text.plain.replace("\n", " ")
113             title_text.no_wrap = True
114             title_text.expand_tabs()
115             title_text.pad(1)
116             return title_text
117         return None
118 
119     @property
120     def _subtitle(self) -> Optional[Text]:
121         if self.subtitle:
122             subtitle_text = (
123                 Text.from_markup(self.subtitle)
124                 if isinstance(self.subtitle, str)
125                 else self.subtitle.copy()
126             )
127             subtitle_text.end = ""
128             subtitle_text.plain = subtitle_text.plain.replace("\n", " ")
129             subtitle_text.no_wrap = True
130             subtitle_text.expand_tabs()
131             subtitle_text.pad(1)
132             return subtitle_text
133         return None
134 
135     def __rich_console__(
136         self, console: "Console", options: "ConsoleOptions"
137     ) -> "RenderResult":
138         _padding = Padding.unpack(self.padding)
139         renderable = (
140             Padding(self.renderable, _padding) if any(_padding) else self.renderable
141         )
142         style = console.get_style(self.style)
143         border_style = style + console.get_style(self.border_style)
144         width = (
145             options.max_width
146             if self.width is None
147             else min(options.max_width, self.width)
148         )
149 
150         safe_box: bool = console.safe_box if self.safe_box is None else self.safe_box
151         box = self.box.substitute(options, safe=safe_box)
152 
153         def align_text(
154             text: Text, width: int, align: str, character: str, style: Style
155         ) -> Text:
156             """Gets new aligned text.
157 
158             Args:
159                 text (Text): Title or subtitle text.
160                 width (int): Desired width.
161                 align (str): Alignment.
162                 character (str): Character for alignment.
163                 style (Style): Border style
164 
165             Returns:
166                 Text: New text instance
167             """
168             text = text.copy()
169             text.truncate(width)
170             excess_space = width - cell_len(text.plain)
171             if excess_space:
172                 if align == "left":
173                     return Text.assemble(
174                         text,
175                         (character * excess_space, style),
176                         no_wrap=True,
177                         end="",
178                     )
179                 elif align == "center":
180                     left = excess_space // 2
181                     return Text.assemble(
182                         (character * left, style),
183                         text,
184                         (character * (excess_space - left), style),
185                         no_wrap=True,
186                         end="",
187                     )
188                 else:
189                     return Text.assemble(
190                         (character * excess_space, style),
191                         text,
192                         no_wrap=True,
193                         end="",
194                     )
195             return text
196 
197         title_text = self._title
198         if title_text is not None:
199             title_text.stylize_before(border_style)
200 
201         child_width = (
202             width - 2
203             if self.expand
204             else console.measure(
205                 renderable, options=options.update_width(width - 2)
206             ).maximum
207         )
208         child_height = self.height or options.height or None
209         if child_height:
210             child_height -= 2
211         if title_text is not None:
212             child_width = min(
213                 options.max_width - 2, max(child_width, title_text.cell_len + 2)
214             )
215 
216         width = child_width + 2
217         child_options = options.update(
218             width=child_width, height=child_height, highlight=self.highlight
219         )
220         lines = console.render_lines(renderable, child_options, style=style)
221 
222         line_start = Segment(box.mid_left, border_style)
223         line_end = Segment(f"{box.mid_right}", border_style)
224         new_line = Segment.line()
225         if title_text is None or width <= 4:
226             yield Segment(box.get_top([width - 2]), border_style)
227         else:
228             title_text = align_text(
229                 title_text,
230                 width - 4,
231                 self.title_align,
232                 box.top,
233                 border_style,
234             )
235             yield Segment(box.top_left + box.top, border_style)
236             yield from console.render(title_text, child_options.update_width(width - 4))
237             yield Segment(box.top + box.top_right, border_style)
238 
239         yield new_line
240         for line in lines:
241             yield line_start
242             yield from line
243             yield line_end
244             yield new_line
245 
246         subtitle_text = self._subtitle
247         if subtitle_text is not None:
248             subtitle_text.stylize_before(border_style)
249 
250         if subtitle_text is None or width <= 4:
251             yield Segment(box.get_bottom([width - 2]), border_style)
252         else:
253             subtitle_text = align_text(
254                 subtitle_text,
255                 width - 4,
256                 self.subtitle_align,
257                 box.bottom,
258                 border_style,
259             )
260             yield Segment(box.bottom_left + box.bottom, border_style)
261             yield from console.render(
262                 subtitle_text, child_options.update_width(width - 4)
263             )
264             yield Segment(box.bottom + box.bottom_right, border_style)
265 
266         yield new_line
267 
268     def __rich_measure__(
269         self, console: "Console", options: "ConsoleOptions"
270     ) -> "Measurement":
271         _title = self._title
272         _, right, _, left = Padding.unpack(self.padding)
273         padding = left + right
274         renderables = [self.renderable, _title] if _title else [self.renderable]
275 
276         if self.width is None:
277             width = (
278                 measure_renderables(
279                     console,
280                     options.update_width(options.max_width - padding - 2),
281                     renderables,
282                 ).maximum
283                 + padding
284                 + 2
285             )
286         else:
287             width = self.width
288         return Measurement(width, width)
289 
290 
291 if __name__ == "__main__":  # pragma: no cover
292     from .console import Console
293 
294     c = Console()
295 
296     from .box import DOUBLE, ROUNDED
297     from .padding import Padding
298 
299     p = Panel(
300         "Hello, World!",
301         title="rich.Panel",
302         style="white on blue",
303         box=DOUBLE,
304         padding=1,
305     )
306 
307     c.print()
308     c.print(p)
309
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/rich/panel.py b/rich/panel.py
--- a/rich/panel.py
+++ b/rich/panel.py
@@ -82,7 +82,9 @@
         style: StyleType = "none",
         border_style: StyleType = "none",
         width: Optional[int] = None,
+        height: Optional[int] = None,
         padding: PaddingDimensions = (0, 1),
+        highlight: bool = False,
     ) -> "Panel":
         """An alternative constructor that sets expand=False."""
         return cls(
@@ -96,7 +98,9 @@
             style=style,
             border_style=border_style,
             width=width,
+            height=height,
             padding=padding,
+            highlight=highlight,
             expand=False,
         )

{"golden_diff": "diff --git a/rich/panel.py b/rich/panel.py\n--- a/rich/panel.py\n+++ b/rich/panel.py\n@@ -82,7 +82,9 @@\n         style: StyleType = \"none\",\n         border_style: StyleType = \"none\",\n         width: Optional[int] = None,\n+        height: Optional[int] = None,\n         padding: PaddingDimensions = (0, 1),\n+        highlight: bool = False,\n     ) -> \"Panel\":\n         \"\"\"An alternative constructor that sets expand=False.\"\"\"\n         return cls(\n@@ -96,7 +98,9 @@\n             style=style,\n             border_style=border_style,\n             width=width,\n+            height=height,\n             padding=padding,\n+            highlight=highlight,\n             expand=False,\n         )\n", "issue": "[BUG] `Panel.fit` forgot `height` and `highlight` parameters\n- [x] I've checked [docs](https://rich.readthedocs.io/en/latest/introduction.html) and [closed issues](https://github.com/Textualize/rich/issues?q=is%3Aissue+is%3Aclosed) for possible solutions.\r\n- [x] I can't find my issue in the [FAQ](https://github.com/Textualize/rich/blob/master/FAQ.md).\r\n\r\n**Describe the bug**\r\n\r\n`Panel.fit` forgot `height` and `highlight` parameters. It should be updated to synchronize with the constructor.\r\n\r\n```python\r\nclass Panel(JupyterMixin):\r\n    def __init__(\r\n        self,\r\n        renderable: \"RenderableType\",\r\n        box: Box = ROUNDED,\r\n        *,\r\n        title: Optional[TextType] = None,\r\n        title_align: AlignMethod = \"center\",\r\n        subtitle: Optional[TextType] = None,\r\n        subtitle_align: AlignMethod = \"center\",\r\n        safe_box: Optional[bool] = None,\r\n        expand: bool = True,\r\n        style: StyleType = \"none\",\r\n        border_style: StyleType = \"none\",\r\n        width: Optional[int] = None,\r\n        height: Optional[int] = None,\r\n        padding: PaddingDimensions = (0, 1),\r\n        highlight: bool = False,\r\n    ) -> None:\r\n        ...\r\n\r\n    @classmethod\r\n    def fit(\r\n        cls,\r\n        renderable: \"RenderableType\",\r\n        box: Box = ROUNDED,\r\n        *,\r\n        title: Optional[TextType] = None,\r\n        title_align: AlignMethod = \"center\",\r\n        subtitle: Optional[TextType] = None,\r\n        subtitle_align: AlignMethod = \"center\",\r\n        safe_box: Optional[bool] = None,\r\n        style: StyleType = \"none\",\r\n        border_style: StyleType = \"none\",\r\n        width: Optional[int] = None,\r\n        padding: PaddingDimensions = (0, 1),\r\n    ) -> \"Panel\":\r\n        ...\r\n```\n", "before_files": [{"content": "from typing import TYPE_CHECKING, Optional\n\nfrom .align import AlignMethod\nfrom .box import ROUNDED, Box\nfrom .cells import cell_len\nfrom .jupyter import JupyterMixin\nfrom .measure import Measurement, measure_renderables\nfrom .padding import Padding, PaddingDimensions\nfrom .segment import Segment\nfrom .style import Style, StyleType\nfrom .text import Text, TextType\n\nif TYPE_CHECKING:\n    from .console import Console, ConsoleOptions, RenderableType, RenderResult\n\n\nclass Panel(JupyterMixin):\n    \"\"\"A console renderable that draws a border around its contents.\n\n    Example:\n        >>> console.print(Panel(\"Hello, World!\"))\n\n    Args:\n        renderable (RenderableType): A console renderable object.\n        box (Box, optional): A Box instance that defines the look of the border (see :ref:`appendix_box`.\n            Defaults to box.ROUNDED.\n        safe_box (bool, optional): Disable box characters that don't display on windows legacy terminal with *raster* fonts. Defaults to True.\n        expand (bool, optional): If True the panel will stretch to fill the console\n            width, otherwise it will be sized to fit the contents. Defaults to True.\n        style (str, optional): The style of the panel (border and contents). Defaults to \"none\".\n        border_style (str, optional): The style of the border. Defaults to \"none\".\n        width (Optional[int], optional): Optional width of panel. Defaults to None to auto-detect.\n        height (Optional[int], optional): Optional height of panel. Defaults to None to auto-detect.\n        padding (Optional[PaddingDimensions]): Optional padding around renderable. Defaults to 0.\n        highlight (bool, optional): Enable automatic highlighting of panel title (if str). Defaults to False.\n    \"\"\"\n\n    def __init__(\n        self,\n        renderable: \"RenderableType\",\n        box: Box = ROUNDED,\n        *,\n        title: Optional[TextType] = None,\n        title_align: AlignMethod = \"center\",\n        subtitle: Optional[TextType] = None,\n        subtitle_align: AlignMethod = \"center\",\n        safe_box: Optional[bool] = None,\n        expand: bool = True,\n        style: StyleType = \"none\",\n        border_style: StyleType = \"none\",\n        width: Optional[int] = None,\n        height: Optional[int] = None,\n        padding: PaddingDimensions = (0, 1),\n        highlight: bool = False,\n    ) -> None:\n        self.renderable = renderable\n        self.box = box\n        self.title = title\n        self.title_align: AlignMethod = title_align\n        self.subtitle = subtitle\n        self.subtitle_align = subtitle_align\n        self.safe_box = safe_box\n        self.expand = expand\n        self.style = style\n        self.border_style = border_style\n        self.width = width\n        self.height = height\n        self.padding = padding\n        self.highlight = highlight\n\n    @classmethod\n    def fit(\n        cls,\n        renderable: \"RenderableType\",\n        box: Box = ROUNDED,\n        *,\n        title: Optional[TextType] = None,\n        title_align: AlignMethod = \"center\",\n        subtitle: Optional[TextType] = None,\n        subtitle_align: AlignMethod = \"center\",\n        safe_box: Optional[bool] = None,\n        style: StyleType = \"none\",\n        border_style: StyleType = \"none\",\n        width: Optional[int] = None,\n        padding: PaddingDimensions = (0, 1),\n    ) -> \"Panel\":\n        \"\"\"An alternative constructor that sets expand=False.\"\"\"\n        return cls(\n            renderable,\n            box,\n            title=title,\n            title_align=title_align,\n            subtitle=subtitle,\n            subtitle_align=subtitle_align,\n            safe_box=safe_box,\n            style=style,\n            border_style=border_style,\n            width=width,\n            padding=padding,\n            expand=False,\n        )\n\n    @property\n    def _title(self) -> Optional[Text]:\n        if self.title:\n            title_text = (\n                Text.from_markup(self.title)\n                if isinstance(self.title, str)\n                else self.title.copy()\n            )\n            title_text.end = \"\"\n            title_text.plain = title_text.plain.replace(\"\\n\", \" \")\n            title_text.no_wrap = True\n            title_text.expand_tabs()\n            title_text.pad(1)\n            return title_text\n        return None\n\n    @property\n    def _subtitle(self) -> Optional[Text]:\n        if self.subtitle:\n            subtitle_text = (\n                Text.from_markup(self.subtitle)\n                if isinstance(self.subtitle, str)\n                else self.subtitle.copy()\n            )\n            subtitle_text.end = \"\"\n            subtitle_text.plain = subtitle_text.plain.replace(\"\\n\", \" \")\n            subtitle_text.no_wrap = True\n            subtitle_text.expand_tabs()\n            subtitle_text.pad(1)\n            return subtitle_text\n        return None\n\n    def __rich_console__(\n        self, console: \"Console\", options: \"ConsoleOptions\"\n    ) -> \"RenderResult\":\n        _padding = Padding.unpack(self.padding)\n        renderable = (\n            Padding(self.renderable, _padding) if any(_padding) else self.renderable\n        )\n        style = console.get_style(self.style)\n        border_style = style + console.get_style(self.border_style)\n        width = (\n            options.max_width\n            if self.width is None\n            else min(options.max_width, self.width)\n        )\n\n        safe_box: bool = console.safe_box if self.safe_box is None else self.safe_box\n        box = self.box.substitute(options, safe=safe_box)\n\n        def align_text(\n            text: Text, width: int, align: str, character: str, style: Style\n        ) -> Text:\n            \"\"\"Gets new aligned text.\n\n            Args:\n                text (Text): Title or subtitle text.\n                width (int): Desired width.\n                align (str): Alignment.\n                character (str): Character for alignment.\n                style (Style): Border style\n\n            Returns:\n                Text: New text instance\n            \"\"\"\n            text = text.copy()\n            text.truncate(width)\n            excess_space = width - cell_len(text.plain)\n            if excess_space:\n                if align == \"left\":\n                    return Text.assemble(\n                        text,\n                        (character * excess_space, style),\n                        no_wrap=True,\n                        end=\"\",\n                    )\n                elif align == \"center\":\n                    left = excess_space // 2\n                    return Text.assemble(\n                        (character * left, style),\n                        text,\n                        (character * (excess_space - left), style),\n                        no_wrap=True,\n                        end=\"\",\n                    )\n                else:\n                    return Text.assemble(\n                        (character * excess_space, style),\n                        text,\n                        no_wrap=True,\n                        end=\"\",\n                    )\n            return text\n\n        title_text = self._title\n        if title_text is not None:\n            title_text.stylize_before(border_style)\n\n        child_width = (\n            width - 2\n            if self.expand\n            else console.measure(\n                renderable, options=options.update_width(width - 2)\n            ).maximum\n        )\n        child_height = self.height or options.height or None\n        if child_height:\n            child_height -= 2\n        if title_text is not None:\n            child_width = min(\n                options.max_width - 2, max(child_width, title_text.cell_len + 2)\n            )\n\n        width = child_width + 2\n        child_options = options.update(\n            width=child_width, height=child_height, highlight=self.highlight\n        )\n        lines = console.render_lines(renderable, child_options, style=style)\n\n        line_start = Segment(box.mid_left, border_style)\n        line_end = Segment(f\"{box.mid_right}\", border_style)\n        new_line = Segment.line()\n        if title_text is None or width <= 4:\n            yield Segment(box.get_top([width - 2]), border_style)\n        else:\n            title_text = align_text(\n                title_text,\n                width - 4,\n                self.title_align,\n                box.top,\n                border_style,\n            )\n            yield Segment(box.top_left + box.top, border_style)\n            yield from console.render(title_text, child_options.update_width(width - 4))\n            yield Segment(box.top + box.top_right, border_style)\n\n        yield new_line\n        for line in lines:\n            yield line_start\n            yield from line\n            yield line_end\n            yield new_line\n\n        subtitle_text = self._subtitle\n        if subtitle_text is not None:\n            subtitle_text.stylize_before(border_style)\n\n        if subtitle_text is None or width <= 4:\n            yield Segment(box.get_bottom([width - 2]), border_style)\n        else:\n            subtitle_text = align_text(\n                subtitle_text,\n                width - 4,\n                self.subtitle_align,\n                box.bottom,\n                border_style,\n            )\n            yield Segment(box.bottom_left + box.bottom, border_style)\n            yield from console.render(\n                subtitle_text, child_options.update_width(width - 4)\n            )\n            yield Segment(box.bottom + box.bottom_right, border_style)\n\n        yield new_line\n\n    def __rich_measure__(\n        self, console: \"Console\", options: \"ConsoleOptions\"\n    ) -> \"Measurement\":\n        _title = self._title\n        _, right, _, left = Padding.unpack(self.padding)\n        padding = left + right\n        renderables = [self.renderable, _title] if _title else [self.renderable]\n\n        if self.width is None:\n            width = (\n                measure_renderables(\n                    console,\n                    options.update_width(options.max_width - padding - 2),\n                    renderables,\n                ).maximum\n                + padding\n                + 2\n            )\n        else:\n            width = self.width\n        return Measurement(width, width)\n\n\nif __name__ == \"__main__\":  # pragma: no cover\n    from .console import Console\n\n    c = Console()\n\n    from .box import DOUBLE, ROUNDED\n    from .padding import Padding\n\n    p = Panel(\n        \"Hello, World!\",\n        title=\"rich.Panel\",\n        style=\"white on blue\",\n        box=DOUBLE,\n        padding=1,\n    )\n\n    c.print()\n    c.print(p)\n", "path": "rich/panel.py"}], "after_files": [{"content": "from typing import TYPE_CHECKING, Optional\n\nfrom .align import AlignMethod\nfrom .box import ROUNDED, Box\nfrom .cells import cell_len\nfrom .jupyter import JupyterMixin\nfrom .measure import Measurement, measure_renderables\nfrom .padding import Padding, PaddingDimensions\nfrom .segment import Segment\nfrom .style import Style, StyleType\nfrom .text import Text, TextType\n\nif TYPE_CHECKING:\n    from .console import Console, ConsoleOptions, RenderableType, RenderResult\n\n\nclass Panel(JupyterMixin):\n    \"\"\"A console renderable that draws a border around its contents.\n\n    Example:\n        >>> console.print(Panel(\"Hello, World!\"))\n\n    Args:\n        renderable (RenderableType): A console renderable object.\n        box (Box, optional): A Box instance that defines the look of the border (see :ref:`appendix_box`.\n            Defaults to box.ROUNDED.\n        safe_box (bool, optional): Disable box characters that don't display on windows legacy terminal with *raster* fonts. Defaults to True.\n        expand (bool, optional): If True the panel will stretch to fill the console\n            width, otherwise it will be sized to fit the contents. Defaults to True.\n        style (str, optional): The style of the panel (border and contents). Defaults to \"none\".\n        border_style (str, optional): The style of the border. Defaults to \"none\".\n        width (Optional[int], optional): Optional width of panel. Defaults to None to auto-detect.\n        height (Optional[int], optional): Optional height of panel. Defaults to None to auto-detect.\n        padding (Optional[PaddingDimensions]): Optional padding around renderable. Defaults to 0.\n        highlight (bool, optional): Enable automatic highlighting of panel title (if str). Defaults to False.\n    \"\"\"\n\n    def __init__(\n        self,\n        renderable: \"RenderableType\",\n        box: Box = ROUNDED,\n        *,\n        title: Optional[TextType] = None,\n        title_align: AlignMethod = \"center\",\n        subtitle: Optional[TextType] = None,\n        subtitle_align: AlignMethod = \"center\",\n        safe_box: Optional[bool] = None,\n        expand: bool = True,\n        style: StyleType = \"none\",\n        border_style: StyleType = \"none\",\n        width: Optional[int] = None,\n        height: Optional[int] = None,\n        padding: PaddingDimensions = (0, 1),\n        highlight: bool = False,\n    ) -> None:\n        self.renderable = renderable\n        self.box = box\n        self.title = title\n        self.title_align: AlignMethod = title_align\n        self.subtitle = subtitle\n        self.subtitle_align = subtitle_align\n        self.safe_box = safe_box\n        self.expand = expand\n        self.style = style\n        self.border_style = border_style\n        self.width = width\n        self.height = height\n        self.padding = padding\n        self.highlight = highlight\n\n    @classmethod\n    def fit(\n        cls,\n        renderable: \"RenderableType\",\n        box: Box = ROUNDED,\n        *,\n        title: Optional[TextType] = None,\n        title_align: AlignMethod = \"center\",\n        subtitle: Optional[TextType] = None,\n        subtitle_align: AlignMethod = \"center\",\n        safe_box: Optional[bool] = None,\n        style: StyleType = \"none\",\n        border_style: StyleType = \"none\",\n        width: Optional[int] = None,\n        height: Optional[int] = None,\n        padding: PaddingDimensions = (0, 1),\n        highlight: bool = False,\n    ) -> \"Panel\":\n        \"\"\"An alternative constructor that sets expand=False.\"\"\"\n        return cls(\n            renderable,\n            box,\n            title=title,\n            title_align=title_align,\n            subtitle=subtitle,\n            subtitle_align=subtitle_align,\n            safe_box=safe_box,\n            style=style,\n            border_style=border_style,\n            width=width,\n            height=height,\n            padding=padding,\n            highlight=highlight,\n            expand=False,\n        )\n\n    @property\n    def _title(self) -> Optional[Text]:\n        if self.title:\n            title_text = (\n                Text.from_markup(self.title)\n                if isinstance(self.title, str)\n                else self.title.copy()\n            )\n            title_text.end = \"\"\n            title_text.plain = title_text.plain.replace(\"\\n\", \" \")\n            title_text.no_wrap = True\n            title_text.expand_tabs()\n            title_text.pad(1)\n            return title_text\n        return None\n\n    @property\n    def _subtitle(self) -> Optional[Text]:\n        if self.subtitle:\n            subtitle_text = (\n                Text.from_markup(self.subtitle)\n                if isinstance(self.subtitle, str)\n                else self.subtitle.copy()\n            )\n            subtitle_text.end = \"\"\n            subtitle_text.plain = subtitle_text.plain.replace(\"\\n\", \" \")\n            subtitle_text.no_wrap = True\n            subtitle_text.expand_tabs()\n            subtitle_text.pad(1)\n            return subtitle_text\n        return None\n\n    def __rich_console__(\n        self, console: \"Console\", options: \"ConsoleOptions\"\n    ) -> \"RenderResult\":\n        _padding = Padding.unpack(self.padding)\n        renderable = (\n            Padding(self.renderable, _padding) if any(_padding) else self.renderable\n        )\n        style = console.get_style(self.style)\n        border_style = style + console.get_style(self.border_style)\n        width = (\n            options.max_width\n            if self.width is None\n            else min(options.max_width, self.width)\n        )\n\n        safe_box: bool = console.safe_box if self.safe_box is None else self.safe_box\n        box = self.box.substitute(options, safe=safe_box)\n\n        def align_text(\n            text: Text, width: int, align: str, character: str, style: Style\n        ) -> Text:\n            \"\"\"Gets new aligned text.\n\n            Args:\n                text (Text): Title or subtitle text.\n                width (int): Desired width.\n                align (str): Alignment.\n                character (str): Character for alignment.\n                style (Style): Border style\n\n            Returns:\n                Text: New text instance\n            \"\"\"\n            text = text.copy()\n            text.truncate(width)\n            excess_space = width - cell_len(text.plain)\n            if excess_space:\n                if align == \"left\":\n                    return Text.assemble(\n                        text,\n                        (character * excess_space, style),\n                        no_wrap=True,\n                        end=\"\",\n                    )\n                elif align == \"center\":\n                    left = excess_space // 2\n                    return Text.assemble(\n                        (character * left, style),\n                        text,\n                        (character * (excess_space - left), style),\n                        no_wrap=True,\n                        end=\"\",\n                    )\n                else:\n                    return Text.assemble(\n                        (character * excess_space, style),\n                        text,\n                        no_wrap=True,\n                        end=\"\",\n                    )\n            return text\n\n        title_text = self._title\n        if title_text is not None:\n            title_text.stylize_before(border_style)\n\n        child_width = (\n            width - 2\n            if self.expand\n            else console.measure(\n                renderable, options=options.update_width(width - 2)\n            ).maximum\n        )\n        child_height = self.height or options.height or None\n        if child_height:\n            child_height -= 2\n        if title_text is not None:\n            child_width = min(\n                options.max_width - 2, max(child_width, title_text.cell_len + 2)\n            )\n\n        width = child_width + 2\n        child_options = options.update(\n            width=child_width, height=child_height, highlight=self.highlight\n        )\n        lines = console.render_lines(renderable, child_options, style=style)\n\n        line_start = Segment(box.mid_left, border_style)\n        line_end = Segment(f\"{box.mid_right}\", border_style)\n        new_line = Segment.line()\n        if title_text is None or width <= 4:\n            yield Segment(box.get_top([width - 2]), border_style)\n        else:\n            title_text = align_text(\n                title_text,\n                width - 4,\n                self.title_align,\n                box.top,\n                border_style,\n            )\n            yield Segment(box.top_left + box.top, border_style)\n            yield from console.render(title_text, child_options.update_width(width - 4))\n            yield Segment(box.top + box.top_right, border_style)\n\n        yield new_line\n        for line in lines:\n            yield line_start\n            yield from line\n            yield line_end\n            yield new_line\n\n        subtitle_text = self._subtitle\n        if subtitle_text is not None:\n            subtitle_text.stylize_before(border_style)\n\n        if subtitle_text is None or width <= 4:\n            yield Segment(box.get_bottom([width - 2]), border_style)\n        else:\n            subtitle_text = align_text(\n                subtitle_text,\n                width - 4,\n                self.subtitle_align,\n                box.bottom,\n                border_style,\n            )\n            yield Segment(box.bottom_left + box.bottom, border_style)\n            yield from console.render(\n                subtitle_text, child_options.update_width(width - 4)\n            )\n            yield Segment(box.bottom + box.bottom_right, border_style)\n\n        yield new_line\n\n    def __rich_measure__(\n        self, console: \"Console\", options: \"ConsoleOptions\"\n    ) -> \"Measurement\":\n        _title = self._title\n        _, right, _, left = Padding.unpack(self.padding)\n        padding = left + right\n        renderables = [self.renderable, _title] if _title else [self.renderable]\n\n        if self.width is None:\n            width = (\n                measure_renderables(\n                    console,\n                    options.update_width(options.max_width - padding - 2),\n                    renderables,\n                ).maximum\n                + padding\n                + 2\n            )\n        else:\n            width = self.width\n        return Measurement(width, width)\n\n\nif __name__ == \"__main__\":  # pragma: no cover\n    from .console import Console\n\n    c = Console()\n\n    from .box import DOUBLE, ROUNDED\n    from .padding import Padding\n\n    p = Panel(\n        \"Hello, World!\",\n        title=\"rich.Panel\",\n        style=\"white on blue\",\n        box=DOUBLE,\n        padding=1,\n    )\n\n    c.print()\n    c.print(p)\n", "path": "rich/panel.py"}]}