def test_render(): layout = Layout(name="root") repr(layout) layout.split_column(Layout(name="top"), Layout(name="bottom")) top = layout["top"] top.update(Panel("foo")) print(type(top._renderable)) assert isinstance(top.renderable, Panel) layout["bottom"].split_row(Layout(name="left"), Layout(name="right")) assert layout["root"].name == "root" assert layout["left"].name == "left" with pytest.raises(KeyError): top["asdasd"] layout["left"].update("foobar") print(layout["left"].children) console = Console(width=60, color_system=None) with console.capture() as capture: console.print(layout, height=10) result = capture.get() print(repr(result)) expected = "╭──────────────────────────────────────────────────────────╮\n│ foo │\n│ │\n│ │\n╰──────────────────────────────────────────────────────────╯\nfoobar ╭───── 'right' (30 x 5) ─────╮\n │ │\n │ Layout(name='right') │\n │ │\n ╰────────────────────────────╯\n" assert result == expected
def test_abc(): foo = Foo() assert isinstance(foo, RichRenderable) assert isinstance(Text("hello"), RichRenderable) assert isinstance(Panel("hello"), RichRenderable) assert not isinstance(foo, str) assert not isinstance("foo", RichRenderable) assert not isinstance([], RichRenderable)
def __rich__(self) -> Panel: grid = Table.grid(expand=True) grid.add_column(justify="center", ratio=1) grid.add_column(justify="right") grid.add_row( "[b]Rich[/b] Layout application", datetime.now().ctime().replace(":", "[blink]:[/]"), ) return Panel(grid, style="white on blue")
def test_justify_renderable_center(): console = Console( file=io.StringIO(), force_terminal=True, width=10, legacy_windows=False, _environ={}, ) console.print(Panel("FOO", expand=False, padding=0), justify="center") assert console.file.getvalue() == " ╭───╮ \n │FOO│ \n ╰───╯ \n"
def test_python_render(): syntax = Panel.fit( Syntax( CODE, lexer_name="python", line_numbers=True, line_range=(2, 10), theme="foo", code_width=60, word_wrap=True, ), padding=0, ) rendered_syntax = render(syntax) print(repr(rendered_syntax)) expected = '╭────────────────────────────────────────────────────────────────╮\n│\x1b[1;38;2;24;24;24;48;2;248;248;248m \x1b[0m\x1b[38;2;173;173;173;48;2;248;248;248m 2 \x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[3;38;2;186;33;33;48;2;248;248;248m"""Iterate and generate a tuple with a flag for first \x1b[0m\x1b[48;2;248;248;248m \x1b[0m│\n│\x1b[48;2;248;248;248m \x1b[0m\x1b[3;38;2;186;33;33;48;2;248;248;248mand last value."""\x1b[0m\x1b[48;2;248;248;248m \x1b[0m│\n│\x1b[1;38;2;24;24;24;48;2;248;248;248m \x1b[0m\x1b[38;2;173;173;173;48;2;248;248;248m 3 \x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248miter_values\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;102;102;102;48;2;248;248;248m=\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;0;128;0;48;2;248;248;248miter\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m(\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248mvalues\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m)\x1b[0m\x1b[48;2;248;248;248m \x1b[0m│\n│\x1b[1;38;2;24;24;24;48;2;248;248;248m \x1b[0m\x1b[38;2;173;173;173;48;2;248;248;248m 4 \x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[1;38;2;0;128;0;48;2;248;248;248mtry\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m:\x1b[0m\x1b[48;2;248;248;248m \x1b[0m│\n│\x1b[1;38;2;24;24;24;48;2;248;248;248m \x1b[0m\x1b[38;2;173;173;173;48;2;248;248;248m 5 \x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248mprevious_value\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;102;102;102;48;2;248;248;248m=\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;0;128;0;48;2;248;248;248mnext\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m(\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248miter_values\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m)\x1b[0m\x1b[48;2;248;248;248m \x1b[0m│\n│\x1b[1;38;2;24;24;24;48;2;248;248;248m \x1b[0m\x1b[38;2;173;173;173;48;2;248;248;248m 6 \x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[1;38;2;0;128;0;48;2;248;248;248mexcept\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[1;38;2;210;65;58;48;2;248;248;248mStopIteration\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m:\x1b[0m\x1b[48;2;248;248;248m \x1b[0m│\n│\x1b[1;38;2;24;24;24;48;2;248;248;248m \x1b[0m\x1b[38;2;173;173;173;48;2;248;248;248m 7 \x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[1;38;2;0;128;0;48;2;248;248;248mreturn\x1b[0m\x1b[48;2;248;248;248m \x1b[0m│\n│\x1b[1;38;2;24;24;24;48;2;248;248;248m \x1b[0m\x1b[38;2;173;173;173;48;2;248;248;248m 8 \x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248mfirst\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;102;102;102;48;2;248;248;248m=\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[1;38;2;0;128;0;48;2;248;248;248mTrue\x1b[0m\x1b[48;2;248;248;248m \x1b[0m│\n│\x1b[1;38;2;24;24;24;48;2;248;248;248m \x1b[0m\x1b[38;2;173;173;173;48;2;248;248;248m 9 \x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[1;38;2;0;128;0;48;2;248;248;248mfor\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248mvalue\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[1;38;2;170;34;255;48;2;248;248;248min\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248miter_values\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m:\x1b[0m\x1b[48;2;248;248;248m \x1b[0m│\n│\x1b[1;38;2;24;24;24;48;2;248;248;248m \x1b[0m\x1b[38;2;173;173;173;48;2;248;248;248m10 \x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[1;38;2;0;128;0;48;2;248;248;248myield\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248mfirst\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m,\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[1;38;2;0;128;0;48;2;248;248;248mFalse\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m,\x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248m \x1b[0m\x1b[38;2;0;0;0;48;2;248;248;248mprevious_value\x1b[0m\x1b[48;2;248;248;248m \x1b[0m│\n╰────────────────────────────────────────────────────────────────╯\n' assert rendered_syntax == expected
def make_sponsor_message() -> Panel: """Some example content.""" sponsor_message = Table.grid(padding=1) sponsor_message.add_column(style="green", justify="right") sponsor_message.add_column(no_wrap=True) sponsor_message.add_row( "Sponsor me", "[u blue link=https://github.com/sponsors/willmcgugan]https://github.com/sponsors/willmcgugan", ) sponsor_message.add_row( "Buy me a :coffee:", "[u blue link=https://ko-fi.com/willmcgugan]https://ko-fi.com/willmcgugan", ) sponsor_message.add_row( "Twitter", "[u blue link=https://twitter.com/willmcgugan]https://twitter.com/willmcgugan", ) sponsor_message.add_row( "Blog", "[u blue link=https://www.willmcgugan.com]https://www.willmcgugan.com") intro_message = Text.from_markup( """Consider supporting my work via Github Sponsors (ask your company / organization), or buy me a coffee to say thanks. - Will McGugan""" ) message = Table.grid(padding=1) message.add_column() message.add_column(no_wrap=True) message.add_row(intro_message, sponsor_message) message_panel = Panel( Align.center( RenderGroup(intro_message, "\n", Align.center(sponsor_message)), vertical="middle", ), box=box.ROUNDED, padding=(1, 2), title="[b red]Thanks for trying out Rich!", border_style="bright_blue", ) return message_panel
def render(): console = Console(file=io.StringIO(), width=100, legacy_windows=False) panel = Panel.fit("foo", box=box.SQUARE, padding=0) columns = Columns([panel] * 4) columns.expand = True console.rule("no align") console.print(columns) columns.align = "left" console.rule("left align") console.print(columns) columns.align = "center" console.rule("center align") console.print(columns) columns.align = "right" console.rule("right align") console.print(columns) return console.file.getvalue()
"MINIMAL", "MINIMAL_HEAVY_HEAD", "MINIMAL_DOUBLE_HEAD", "SIMPLE", "SIMPLE_HEAD", "SIMPLE_HEAVY", "HORIZONTALS", "ROUNDED", "HEAVY", "HEAVY_EDGE", "HEAVY_HEAD", "DOUBLE", "DOUBLE_EDGE", ] console.print(Panel("[bold green]Box Constants", style="green"), justify="center") console.print() columns = Columns(expand=True, padding=2) for box_name in sorted(BOXES): table = Table(show_footer=True, style="dim", border_style="not dim", expand=True) table.add_column("Header 1", "Footer 1") table.add_column("Header 2", "Footer 2") table.add_row("Cell", "Cell") table.add_row("Cell", "Cell") table.box = getattr(box, box_name) table.title = Text(f"box.{box_name}", style="magenta")
BarColumn(), TextColumn("[progress.percentage]{task.percentage:>3.0f}%"), ) job_progress.add_task("[green]Cooking") job_progress.add_task("[magenta]Baking", total=200) job_progress.add_task("[cyan]Mixing", total=400) total = sum(task.total for task in job_progress.tasks) overall_progress = Progress() overall_task = overall_progress.add_task("All Jobs", total=int(total)) progress_table = Table.grid(expand=True) progress_table.add_row( Panel( overall_progress, title="Overall Progress", border_style="green", padding=(2, 2), ), Panel(job_progress, title="[b]Jobs", border_style="red", padding=(1, 2)), ) layout = make_layout() layout["header"].update(Header()) layout["body"].update(make_sponsor_message()) layout["box2"].update(Panel(make_syntax(), border_style="green")) layout["box1"].update(Panel(layout.tree, border_style="red")) layout["footer"].update(progress_table) from mudrich.live import Live from time import sleep
from mudrich.console import Console from mudrich.panel import Panel from mudrich.pretty import Pretty DATA = { "foo": [1, 2, 3, (), {}, (1, 2, 3), {4, 5, 6, (7, 8, 9)}, "Hello, World"], "bar": [None, (False, True)] * 2, "Dune": { "names": { "Paul Atreides", "Vladimir Harkonnen", "Thufir Hawat", "Duncan Idaho", } }, } console = Console() for w in range(130): console.print(Panel(Pretty(DATA, indent_guides=True), width=w))
""" syntax = Syntax(code, "python", theme="monokai", line_numbers=True) markdown = Markdown( """\ ### example.md > Hello, World! > > Markdown _all_ the things """ ) root = Tree("🌲 [b green]Rich Tree", highlight=True) node = root.add(":file_folder: Renderables", guide_style="red") simple_node = node.add(":file_folder: [bold yellow]Atomic", guide_style="uu green") simple_node.add(RenderGroup("📄 Syntax", syntax)) simple_node.add(RenderGroup("📄 Markdown", Panel(markdown, border_style="green"))) containers_node = node.add( ":file_folder: [bold magenta]Containers", guide_style="bold magenta" ) containers_node.expanded = True panel = Panel.fit("Just a panel", border_style="red") containers_node.add(RenderGroup("📄 Panels", panel)) containers_node.add(RenderGroup("📄 [b magenta]Table", table)) console = Console() console.print(root)
from time import sleep from mudrich.panel import Panel from mudrich.progress import Progress JOBS = [100, 150, 25, 70, 110, 90] progress = Progress(auto_refresh=False) master_task = progress.add_task("overall", total=sum(JOBS)) jobs_task = progress.add_task("jobs") progress.console.print( Panel( "[bold blue]A demonstration of progress with a current task and overall progress.", padding=1, )) with progress: for job_no, job in enumerate(JOBS): progress.log(f"Starting job #{job_no}") sleep(0.2) progress.reset(jobs_task, total=job, description=f"job [bold yellow]#{job_no}") progress.start_task(jobs_task) for wait in progress.track(range(job), task_id=jobs_task): sleep(0.01) progress.advance(master_task, job) progress.log(f"Job #{job_no} is complete") progress.log( Panel(":sparkle: All done! :sparkle:", border_style="green", padding=1))
sponsor_message.add_row( "Twitter", "[u blue link=https://twitter.com/willmcgugan]https://twitter.com/willmcgugan", ) sponsor_message.add_row( "Blog", "[u blue link=https://www.willmcgugan.com]https://www.willmcgugan.com") intro_message = Text.from_markup("""\ It takes a lot of time to develop Rich and to provide support. Consider supporting my work via Github Sponsors (ask your company / organization), or buy me a coffee to say thanks. - Will McGugan""") message = Table.grid(padding=2) message.add_column() message.add_column(no_wrap=True) message.add_row(intro_message, sponsor_message) console.print( Panel.fit( message, box=box.ROUNDED, padding=(1, 2), title="[b red]Thanks for trying out Rich!", border_style="bright_blue", ), justify="center", )
from time import sleep from mudrich.columns import Columns from mudrich.panel import Panel from mudrich.live import Live from mudrich.text import Text from mudrich.spinner import Spinner, SPINNERS all_spinners = Columns( [ Spinner(spinner_name, text=Text(repr(spinner_name), style="green")) for spinner_name in sorted(SPINNERS) ], column_first=True, expand=True, ) with Live( Panel(all_spinners, title="Spinners", border_style="blue"), refresh_per_second=20, ) as live: while True: sleep(0.1)
class Styled: """Apply a style to a renderable. Args: renderable (RenderableType): Any renderable. style (StyleType): A style to apply across the entire renderable. """ def __init__(self, renderable: "RenderableType", style: "StyleType") -> None: self.renderable = renderable self.style = style def __rich_console__(self, console: "Console", options: "ConsoleOptions") -> "RenderResult": style = console.get_style(self.style) rendered_segments = console.render(self.renderable, options) segments = Segment.apply_style(rendered_segments, style) return segments def __rich_measure__(self, console: "Console", options: "ConsoleOptions") -> Measurement: return Measurement.get(console, options, self.renderable) if __name__ == "__main__": # pragma: no cover from mudrich import print from mudrich.panel import Panel panel = Styled(Panel("hello"), "on blue") print(panel)
def test_console_width(): console = Console(file=io.StringIO(), width=50, legacy_windows=False) panel = Panel("Hello, World", expand=False) min_width, max_width = panel.__rich_measure__(console, console.options) assert min_width == 16 assert max_width == 16
""" This example demonstrates the justify argument to print. """ from mudrich.console import Console from mudrich.panel import Panel console = Console(width=20) style = "bold white on blue" panel = Panel("Rich", style="on red", expand=False) console.print(panel, style=style) console.print(panel, style=style, justify="left") console.print(panel, style=style, justify="center") console.print(panel, style=style, justify="right")
from mudrich import print from mudrich.console import render_group from mudrich.panel import Panel @render_group() def get_panels(): yield Panel("Hello", style="on blue") yield Panel("World", style="on red") print(Panel(get_panels()))
@pytest.mark.skipif(sys.platform == "win32", reason="permissions error on Windows") def test_from_file_unknown_lexer(): fh, path = tempfile.mkstemp("example.nosuchtype") try: os.write(fh, b"import this\n") syntax = Syntax.from_path(path) assert syntax.lexer_name == "default" assert syntax.code == "import this\n" finally: os.remove(path) if __name__ == "__main__": syntax = Panel.fit( Syntax( CODE, lexer_name="python", line_numbers=True, line_range=(2, 10), theme="foo", code_width=60, word_wrap=True, ), padding=0, ) rendered = render(markdown) print(rendered) print(repr(rendered))
""" This example shows how to display content in columns. The data is pulled from https://randomuser.me """ import json from urllib.request import urlopen from mudrich.console import Console from mudrich.columns import Columns from mudrich.panel import Panel def get_content(user): """Extract text from user dict.""" country = user["location"]["country"] name = f"{user['name']['first']} {user['name']['last']}" return f"[b]{name}[/b]\n[yellow]{country}" console = Console() users = json.loads(urlopen("https://randomuser.me/api/?results=30").read())["results"] console.print(users, overflow="ignore", crop=False) user_renderables = [Panel(get_content(user), expand=True) for user in users] console.print(Columns(user_renderables))
def get_panels(): yield Panel("Hello", style="on blue") yield Panel("World", style="on red")
def __rich_measure__( self, console: "Console", options: "ConsoleOptions" ) -> Measurement: measurement = Measurement.get(console, options, self.renderable) return measurement if __name__ == "__main__": # pragma: no cover from mudrich.console import Console, RenderGroup from mudrich.highlighter import ReprHighlighter from mudrich.panel import Panel highlighter = ReprHighlighter() console = Console() panel = Panel( RenderGroup( Align.left(highlighter("align='left'")), Align.center(highlighter("align='center'")), Align.right(highlighter("align='right'")), ), width=60, style="on dark_blue", title="Algin", ) console.print( Align.center(panel, vertical="middle", style="on red", height=console.height) )
from mudrich import print from mudrich.console import RenderGroup from mudrich.panel import Panel panel_group = RenderGroup( Panel("Hello", style="on blue"), Panel("World", style="on red"), ) print(Panel(panel_group))
import io from mudrich.console import Console from mudrich.measure import Measurement from mudrich.panel import Panel import pytest tests = [ Panel("Hello, World", padding=0), Panel("Hello, World", expand=False, padding=0), Panel.fit("Hello, World", padding=0), Panel("Hello, World", width=8, padding=0), Panel(Panel("Hello, World", padding=0), padding=0), Panel("Hello, World", title="FOO", padding=0), ] expected = [ "╭────────────────────────────────────────────────╮\n│Hello, World │\n╰────────────────────────────────────────────────╯\n", "╭────────────╮\n│Hello, World│\n╰────────────╯\n", "╭────────────╮\n│Hello, World│\n╰────────────╯\n", "╭──────╮\n│Hello,│\n│World │\n╰──────╯\n", "╭────────────────────────────────────────────────╮\n│╭──────────────────────────────────────────────╮│\n││Hello, World ││\n│╰──────────────────────────────────────────────╯│\n╰────────────────────────────────────────────────╯\n", "╭───────────────────── FOO ──────────────────────╮\n│Hello, World │\n╰────────────────────────────────────────────────╯\n", ] def render(panel, width=50) -> str: console = Console(file=io.StringIO(), width=50, legacy_windows=False) console.print(panel) return console.file.getvalue()
SpinnerColumn(), BarColumn(), TextColumn("[progress.percentage]{task.percentage:>3.0f}%"), ) job1 = job_progress.add_task("[green]Cooking") job2 = job_progress.add_task("[magenta]Baking", total=200) job3 = job_progress.add_task("[cyan]Mixing", total=400) total = sum(task.total for task in job_progress.tasks) overall_progress = Progress() overall_task = overall_progress.add_task("All Jobs", total=int(total)) progress_table = Table.grid() progress_table.add_row( Panel.fit(overall_progress, title="Overall Progress", border_style="green", padding=(2, 2)), Panel.fit(job_progress, title="[b]Jobs", border_style="red", padding=(1, 2)), ) with Live(progress_table, refresh_per_second=10): while not overall_progress.finished: sleep(0.1) for job in job_progress.tasks: if not job.finished: job_progress.advance(job.id) completed = sum(task.completed for task in job_progress.tasks)
def test_fixed_width(): console = Console(file=io.StringIO(), width=50, legacy_windows=False) panel = Panel("Hello World", width=20) min_width, max_width = panel.__rich_measure__(console, console.options) assert min_width == 20 assert max_width == 20
def test_rich_cast_container(): foo = Foo() console = Console(file=io.StringIO(), legacy_windows=False) console.print(Panel.fit(foo, padding=0)) assert console.file.getvalue() == "╭───╮\n│Foo│\n╰───╯\n"