[DEV] Escapable curly braces (#955)

This commit is contained in:
Jesse Bannon 2024-04-01 22:40:56 -07:00 committed by GitHub
parent 598c574b8a
commit c622cf68b5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 30 additions and 3 deletions

View file

@ -88,6 +88,12 @@ triple-quotes can be used to avoid *closing* the String.
%string("""This has both " and ' in it.""")
}
If you want a plain string that contains literal curly braces, you can escape them like so:
.. code-block:: yaml
string_variable: "This contains \\{ literal curly braces \\}"
Integer
~~~~~~~

View file

@ -73,6 +73,8 @@ CUSTOM_FUNCTION_ARGUMENTS_ONLY_ARGS = InvalidSyntaxException(
FUNCTION_INVALID_CHAR = InvalidSyntaxException("Invalid value when parsing a function")
BRACKET_INVALID_CHAR = InvalidSyntaxException("Invalid value within brackets")
def _UNEXPECTED_CHAR_ARGUMENT(arg_type: ParsedArgType):
return InvalidSyntaxException(f"Unexpected character when parsing {arg_type.value} arguments")
@ -505,6 +507,10 @@ class _Parser:
raise UNREACHABLE
def _parse_main_loop(self, ch: str) -> bool:
if ch == "\\" and self._read(increment_pos=False) in {"{", "}"}:
# Escape brackets are \{ and \}, only add the second char
self._literal_str += self._read()
return True
if ch == "}":
if self._bracket_counter == 0:
raise BRACKET_NOT_CLOSED
@ -558,9 +564,9 @@ class _Parser:
elif self._bracket_counter == 0:
# Only accumulate literal str if not in brackets
self._literal_str += ch
else:
# Should only be possible to get here if it's a space
assert ch.isspace()
elif not ch.isspace():
self._set_highlight_position(pos=self._pos - 1)
raise BRACKET_INVALID_CHAR
return True

View file

@ -5,6 +5,7 @@ from typing import Union
import pytest
from ytdl_sub.script.parser import _UNEXPECTED_CHAR_ARGUMENT
from ytdl_sub.script.parser import BRACKET_INVALID_CHAR
from ytdl_sub.script.parser import BRACKET_NOT_CLOSED
from ytdl_sub.script.parser import ParsedArgType
from ytdl_sub.script.parser import parse
@ -192,6 +193,15 @@ class TestParser:
]
)
def test_escaped_bracket(self):
assert parse("\\{ This is escape {%string('{}')} and here \\}") == SyntaxTree(
[
String(value="{ This is escape "),
BuiltInFunction(name="string", args=[String(value="{}")]),
String(value=" and here }"),
]
)
class TestParserBracketFailures:
def test_bracket_open(self):
@ -208,3 +218,8 @@ class TestParserBracketFailures:
match=re.escape(str(_UNEXPECTED_CHAR_ARGUMENT(ParsedArgType.MAP_KEY))),
):
parse("hello {%capitalize({as_arg)}")
@pytest.mark.parametrize("char", [")", ",", "*", "]"])
def test_extra_char_in_brackets(self, char: str):
with pytest.raises(InvalidSyntaxException, match=re.escape(str(BRACKET_INVALID_CHAR))):
parse(f"{{ %string('hi') {char} }}")