rich/tests/test_markup.py

200 lines
5.6 KiB
Python
Raw Normal View History

2020-04-13 11:24:21 +00:00
import pytest
2021-01-06 21:23:24 +00:00
from rich.console import Console
2020-08-01 20:23:51 +00:00
from rich.markup import escape, MarkupError, _parse, render, Tag, RE_TAGS
2020-04-13 11:24:21 +00:00
from rich.text import Span
2020-08-01 20:23:51 +00:00
def test_re_no_match():
assert RE_TAGS.match("[True]") == None
assert RE_TAGS.match("[False]") == None
assert RE_TAGS.match("[None]") == None
assert RE_TAGS.match("[1]") == None
assert RE_TAGS.match("[2]") == None
assert RE_TAGS.match("[]") == None
def test_re_match():
assert RE_TAGS.match("[true]")
assert RE_TAGS.match("[false]")
assert RE_TAGS.match("[none]")
assert RE_TAGS.match("[color(1)]")
assert RE_TAGS.match("[#ff00ff]")
assert RE_TAGS.match("[/]")
2022-01-02 16:53:27 +00:00
assert RE_TAGS.match("[@]")
assert RE_TAGS.match("[@foo]")
assert RE_TAGS.match("[@foo=bar]")
2020-08-01 20:23:51 +00:00
2020-05-08 12:36:12 +00:00
def test_escape():
2021-01-07 11:49:02 +00:00
# Potential tags
assert escape("foo[bar]") == r"foo\[bar]"
2021-01-06 21:23:24 +00:00
assert escape(r"foo\[bar]") == r"foo\\\[bar]"
2021-01-07 11:49:02 +00:00
# Not tags (escape not required)
assert escape("[5]") == "[5]"
assert escape("\\[5]") == "\\[5]"
2022-01-02 16:51:41 +00:00
# Test @ escape
assert escape("[@foo]") == "\\[@foo]"
assert escape("[@]") == "\\[@]"
2021-01-06 21:23:24 +00:00
def test_render_escape():
2021-01-06 21:34:35 +00:00
console = Console(width=80, color_system=None)
2021-01-06 21:23:24 +00:00
console.begin_capture()
console.print(
escape(r"[red]"), escape(r"\[red]"), escape(r"\\[red]"), escape(r"\\\[red]")
)
result = console.end_capture()
expected = r"[red] \[red] \\[red] \\\[red]" + "\n"
assert result == expected
2020-05-08 12:36:12 +00:00
2020-04-13 11:24:21 +00:00
def test_parse():
result = list(_parse(r"[foo]hello[/foo][bar]world[/]\[escaped]"))
2020-04-13 11:24:21 +00:00
expected = [
2020-05-10 11:22:22 +00:00
(0, None, Tag(name="foo", parameters=None)),
(10, "hello", None),
(10, None, Tag(name="/foo", parameters=None)),
(16, None, Tag(name="bar", parameters=None)),
(26, "world", None),
(26, None, Tag(name="/", parameters=None)),
2021-01-05 21:23:13 +00:00
(29, "[escaped]", None),
2020-05-10 11:22:22 +00:00
]
2021-01-05 21:23:13 +00:00
print(repr(result))
2020-05-10 11:22:22 +00:00
assert result == expected
def test_parse_link():
result = list(_parse("[link=foo]bar[/link]"))
expected = [
(0, None, Tag(name="link", parameters="foo")),
(13, "bar", None),
(13, None, Tag(name="/link", parameters=None)),
2020-04-13 11:24:21 +00:00
]
assert result == expected
def test_render():
result = render("[bold]FOO[/bold]")
assert str(result) == "FOO"
assert result.spans == [Span(0, 3, "bold")]
2020-08-01 16:45:40 +00:00
def test_render_not_tags():
2020-08-02 10:55:40 +00:00
result = render('[[1], [1,2,3,4], ["hello"], [None], [False], [True]] []')
assert str(result) == '[[1], [1,2,3,4], ["hello"], [None], [False], [True]] []'
2020-08-01 16:45:40 +00:00
assert result.spans == []
2020-05-10 11:22:22 +00:00
def test_render_link():
result = render("[link=foo]FOO[/link]")
assert str(result) == "FOO"
assert result.spans == [Span(0, 3, "link foo")]
2020-05-08 12:36:12 +00:00
def test_render_combine():
result = render("[green]X[blue]Y[/blue]Z[/green]")
assert str(result) == "XYZ"
assert result.spans == [
Span(0, 3, "green"),
Span(1, 2, "blue"),
]
def test_render_overlap():
result = render("[green]X[bold]Y[/green]Z[/bold]")
assert str(result) == "XYZ"
assert result.spans == [
Span(0, 2, "green"),
Span(1, 3, "bold"),
]
2021-07-09 21:02:14 +00:00
def test_adjoint():
result = render("[red][blue]B[/blue]R[/red]")
print(repr(result))
assert result.spans == [Span(0, 2, "red"), Span(0, 1, "blue")]
2020-05-08 12:36:12 +00:00
def test_render_close():
result = render("[bold]X[/]Y")
assert str(result) == "XY"
assert result.spans == [Span(0, 1, "bold")]
def test_render_close_ambiguous():
result = render("[green]X[bold]Y[/]Z[/]")
assert str(result) == "XYZ"
assert result.spans == [Span(0, 3, "green"), Span(1, 2, "bold")]
2020-04-13 11:24:21 +00:00
def test_markup_error():
with pytest.raises(MarkupError):
assert render("foo[/]")
with pytest.raises(MarkupError):
assert render("foo[/bar]")
with pytest.raises(MarkupError):
assert render("[foo]hello[/bar]")
2021-01-05 18:08:44 +00:00
def test_escape_escape():
2021-01-06 21:23:24 +00:00
# Escaped escapes (i.e. double backslash)should be treated as literal
result = render(r"\\[bold]FOO")
assert str(result) == r"\FOO"
2021-01-05 18:08:44 +00:00
2021-01-06 21:23:24 +00:00
# Single backslash makes the tag literal
result = render(r"\[bold]FOO")
assert str(result) == "[bold]FOO"
2021-01-05 18:08:44 +00:00
2021-01-06 21:23:24 +00:00
# Double backslash produces a backslash
2021-01-05 18:08:44 +00:00
result = render(r"\\[bold]some text[/]")
2021-01-06 21:23:24 +00:00
assert str(result) == r"\some text"
# Triple backslash parsed as literal backslash plus escaped tag
result = render(r"\\\[bold]some text\[/]")
assert str(result) == r"\[bold]some text[/]"
2021-01-05 18:08:44 +00:00
2021-01-06 21:23:24 +00:00
# Backslash escaping only happens when preceding a tag
2021-01-05 18:08:44 +00:00
result = render(r"\\")
2021-01-05 21:23:13 +00:00
assert str(result) == r"\\"
2021-01-05 18:08:44 +00:00
result = render(r"\\\\")
2021-01-05 21:23:13 +00:00
assert str(result) == r"\\\\"
2021-06-18 19:37:33 +00:00
def test_events():
result = render("[@click]Hello[/@click] [@click='view.toggle', 'left']World[/]")
assert str(result) == "Hello World"
def test_events_broken():
with pytest.raises(MarkupError):
2021-08-03 12:25:18 +00:00
render("[@click=sdfwer(sfs)]foo[/]")
2021-06-18 19:37:33 +00:00
with pytest.raises(MarkupError):
render("[@click='view.toggle]foo[/]")
2021-08-03 12:25:18 +00:00
def test_render_meta():
console = Console()
text = render("foo[@click=close]bar[/]baz")
assert text.get_style_at_offset(console, 3).meta == {"@click": ("close", ())}
text = render("foo[@click=close()]bar[/]baz")
assert text.get_style_at_offset(console, 3).meta == {"@click": ("close", ())}
text = render("foo[@click=close('dialog')]bar[/]baz")
assert text.get_style_at_offset(console, 3).meta == {
"@click": ("close", ("dialog",))
}
text = render("foo[@click=close('dialog', 3)]bar[/]baz")
assert text.get_style_at_offset(console, 3).meta == {
"@click": ("close", ("dialog", 3))
}
text = render("foo[@click=(1, 2, 3)]bar[/]baz")
assert text.get_style_at_offset(console, 3).meta == {"@click": (1, 2, 3)}