Honor whitespace in funcparser unparsed strings. Resolve #2927
This commit is contained in:
parent
b37ce26005
commit
443aae7f20
2 changed files with 30 additions and 8 deletions
|
|
@ -85,6 +85,7 @@ class _ParsedFunc:
|
||||||
# state storage
|
# state storage
|
||||||
fullstr: str = ""
|
fullstr: str = ""
|
||||||
infuncstr: str = ""
|
infuncstr: str = ""
|
||||||
|
rawstr: str = ""
|
||||||
double_quoted: int = -1
|
double_quoted: int = -1
|
||||||
current_kwarg: str = ""
|
current_kwarg: str = ""
|
||||||
open_lparens: int = 0
|
open_lparens: int = 0
|
||||||
|
|
@ -96,7 +97,7 @@ class _ParsedFunc:
|
||||||
return self.funcname, self.args, self.kwargs
|
return self.funcname, self.args, self.kwargs
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.fullstr + self.infuncstr
|
return self.prefix + self.rawstr + self.infuncstr
|
||||||
|
|
||||||
|
|
||||||
class ParsingError(RuntimeError):
|
class ParsingError(RuntimeError):
|
||||||
|
|
@ -369,6 +370,8 @@ class FuncParser:
|
||||||
curr_func.open_lparens = open_lparens
|
curr_func.open_lparens = open_lparens
|
||||||
curr_func.open_lsquare = open_lsquare
|
curr_func.open_lsquare = open_lsquare
|
||||||
curr_func.open_lcurly = open_lcurly
|
curr_func.open_lcurly = open_lcurly
|
||||||
|
# we must strip the remaining funcstr so it's not counted twice
|
||||||
|
curr_func.rawstr = curr_func.rawstr[: -len(infuncstr)]
|
||||||
current_kwarg = ""
|
current_kwarg = ""
|
||||||
infuncstr = ""
|
infuncstr = ""
|
||||||
double_quoted = -1
|
double_quoted = -1
|
||||||
|
|
@ -392,6 +395,8 @@ class FuncParser:
|
||||||
|
|
||||||
# in a function def (can be nested)
|
# in a function def (can be nested)
|
||||||
|
|
||||||
|
curr_func.rawstr += char
|
||||||
|
|
||||||
if exec_return != "" and char not in (",=)"):
|
if exec_return != "" and char not in (",=)"):
|
||||||
# if exec_return is followed by any other character
|
# if exec_return is followed by any other character
|
||||||
# than one demarking an arg,kwarg or function-end
|
# than one demarking an arg,kwarg or function-end
|
||||||
|
|
@ -552,8 +557,15 @@ class FuncParser:
|
||||||
# these are malformed (no closing bracket) and we should get their
|
# these are malformed (no closing bracket) and we should get their
|
||||||
# strings as-is.
|
# strings as-is.
|
||||||
callstack.append(curr_func)
|
callstack.append(curr_func)
|
||||||
for _ in range(len(callstack)):
|
for inum, _ in enumerate(range(len(callstack))):
|
||||||
infuncstr = str(callstack.pop()) + infuncstr
|
funcstr = str(callstack.pop())
|
||||||
|
if inum == 0 and funcstr.endswith(infuncstr):
|
||||||
|
# avoid double-echo of nested function calls. This should
|
||||||
|
# produce a good result most of the time, but it's not 100%
|
||||||
|
# guaranteed to, since it can ignore genuine duplicates
|
||||||
|
infuncstr = funcstr
|
||||||
|
else:
|
||||||
|
infuncstr = funcstr + infuncstr
|
||||||
|
|
||||||
if not return_str and exec_return != "":
|
if not return_str and exec_return != "":
|
||||||
# return explicit return
|
# return explicit return
|
||||||
|
|
|
||||||
|
|
@ -82,6 +82,12 @@ def _raises_callable(*args, **kwargs):
|
||||||
raise RuntimeError("Test exception raised by test callable")
|
raise RuntimeError("Test exception raised by test callable")
|
||||||
|
|
||||||
|
|
||||||
|
def _pass_callable(*args, **kwargs):
|
||||||
|
kwargs.pop("funcparser", None)
|
||||||
|
kwargs.pop("raise_errors", None)
|
||||||
|
return str(args) + str(kwargs)
|
||||||
|
|
||||||
|
|
||||||
_test_callables = {
|
_test_callables = {
|
||||||
"foo": _test_callable,
|
"foo": _test_callable,
|
||||||
"bar": _test_callable,
|
"bar": _test_callable,
|
||||||
|
|
@ -95,6 +101,7 @@ _test_callables = {
|
||||||
"lit": _lit_callable,
|
"lit": _lit_callable,
|
||||||
"sum": _lsum_callable,
|
"sum": _lsum_callable,
|
||||||
"raise": _raises_callable,
|
"raise": _raises_callable,
|
||||||
|
"pass": _pass_callable,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -184,8 +191,8 @@ class TestFuncParser(TestCase):
|
||||||
("Test with color |r$foo(a,b)|n is ok", "Test with color |r_test(a, b)|n is ok"),
|
("Test with color |r$foo(a,b)|n is ok", "Test with color |r_test(a, b)|n is ok"),
|
||||||
("Test malformed1 This is $foo( and $bar(", "Test malformed1 This is $foo( and $bar("),
|
("Test malformed1 This is $foo( and $bar(", "Test malformed1 This is $foo( and $bar("),
|
||||||
(
|
(
|
||||||
"Test malformed2 This is $foo( and $bar()",
|
"Test malformed2 This is $foo( and $bar()",
|
||||||
"Test malformed2 This is $foo( and _test()",
|
"Test malformed2 This is $foo( and _test()",
|
||||||
),
|
),
|
||||||
("Test malformed3 $", "Test malformed3 $"),
|
("Test malformed3 $", "Test malformed3 $"),
|
||||||
(
|
(
|
||||||
|
|
@ -304,11 +311,14 @@ class TestFuncParser(TestCase):
|
||||||
ret = self.parser.parse(string, strip=True)
|
ret = self.parser.parse(string, strip=True)
|
||||||
self.assertEqual("Test and things", ret)
|
self.assertEqual("Test and things", ret)
|
||||||
|
|
||||||
@unittest.skip("broken due to https://github.com/evennia/evennia/issues/2927")
|
|
||||||
def test_parse_whitespace_preserved(self):
|
def test_parse_whitespace_preserved(self):
|
||||||
string = "The answer is $add(1, x)"
|
string = "The answer is $foobar(1, x)" # not found, so should be preserved
|
||||||
ret = self.parser.parse(string)
|
ret = self.parser.parse(string)
|
||||||
self.assertEqual("The answer is $add(1, x)", ret)
|
self.assertEqual("The answer is $foobar(1, x)", ret)
|
||||||
|
|
||||||
|
string = 'The $pass(testing, bar= $dum(b = "test2" , a), ) $pass('
|
||||||
|
ret = self.parser.parse(string)
|
||||||
|
self.assertEqual("The ('testing',){'bar': '$dum(b = \"test2\" , a)'} $pass(", ret)
|
||||||
|
|
||||||
def test_parse_escape(self):
|
def test_parse_escape(self):
|
||||||
"""
|
"""
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue