mirror of
https://github.com/evennia/evennia.git
synced 2026-03-16 21:06:30 +01:00
Stop escape ' in funcparser; req double quotes. Resolve #2737.
This commit is contained in:
parent
a92214354b
commit
6a0df97c16
3 changed files with 47 additions and 58 deletions
|
|
@ -213,28 +213,31 @@ Sometimes you want to include commas in the argument without it breaking the
|
|||
argument list.
|
||||
|
||||
```python
|
||||
"There is a $format(beautiful meadow, with dandelions) to the west."
|
||||
"The $format(forest's smallest meadow, with dandelions) is to the west."
|
||||
```
|
||||
|
||||
You can escape in various ways.
|
||||
|
||||
- Prepending with the escape character `\`
|
||||
- Prepending special characters like `,` and `=` with the escape character `\`
|
||||
|
||||
```python
|
||||
"There is a $format(beautiful meadow\, with dandelions) to the west."
|
||||
```
|
||||
- Wrapping your strings in quotes. This works like Python, and you can nest
|
||||
double and single quotes inside each other if so needed. The result will
|
||||
be a verbatim string that contains everything but the outermost quotes.
|
||||
```python
|
||||
"The $format(forest's smallest meadow\, with dandelions) is to the west."
|
||||
```
|
||||
|
||||
```python
|
||||
"There is a $format('beautiful meadow, with dandelions') to the west."
|
||||
```
|
||||
- If you want verbatim quotes in your string, you can escape them too.
|
||||
- Wrapping your strings in double quotes. Unlike in raw Python, you
|
||||
can't escape with single quotes `'` since these could also be apostrophes (like
|
||||
`forest's` above). The result will be a verbatim string that contains
|
||||
everything but the outermost double quotes.
|
||||
|
||||
```python
|
||||
"There is a $format('beautiful meadow, with \'dandelions\'') to the west."
|
||||
```
|
||||
```python
|
||||
'The $format("forest's smallest meadow, with dandelions") is to the west.'
|
||||
```
|
||||
- If you want verbatim double-quotes to appear in your string, you can escape
|
||||
them with `\"` in turn.
|
||||
|
||||
```python
|
||||
'The $format("forest's smallest meadow, with \"dandelions\"') is to the west.'
|
||||
```
|
||||
|
||||
### Safe convertion of inputs
|
||||
|
||||
|
|
|
|||
|
|
@ -85,7 +85,6 @@ class _ParsedFunc:
|
|||
# state storage
|
||||
fullstr: str = ""
|
||||
infuncstr: str = ""
|
||||
single_quoted: int = -1
|
||||
double_quoted: int = -1
|
||||
current_kwarg: str = ""
|
||||
open_lparens: int = 0
|
||||
|
|
@ -319,7 +318,6 @@ class FuncParser:
|
|||
# parsing state
|
||||
callstack = []
|
||||
|
||||
single_quoted = -1
|
||||
double_quoted = -1
|
||||
open_lparens = 0 # open (
|
||||
open_lsquare = 0 # open [
|
||||
|
|
@ -367,14 +365,12 @@ class FuncParser:
|
|||
# store state for the current func and stack it
|
||||
curr_func.current_kwarg = current_kwarg
|
||||
curr_func.infuncstr = infuncstr
|
||||
curr_func.single_quoted = single_quoted
|
||||
curr_func.double_quoted = double_quoted
|
||||
curr_func.open_lparens = open_lparens
|
||||
curr_func.open_lsquare = open_lsquare
|
||||
curr_func.open_lcurly = open_lcurly
|
||||
current_kwarg = ""
|
||||
infuncstr = ""
|
||||
single_quoted = -1
|
||||
double_quoted = -1
|
||||
open_lparens = 0
|
||||
open_lsquare = 0
|
||||
|
|
@ -403,24 +399,7 @@ class FuncParser:
|
|||
infuncstr += str(exec_return)
|
||||
exec_return = ""
|
||||
|
||||
if char == "'" and double_quoted < 0: # note that this is the same as "\'"
|
||||
# a single quote - flip status
|
||||
if single_quoted == 0:
|
||||
infuncstr = infuncstr[1:]
|
||||
single_quoted = -1
|
||||
elif single_quoted > 0:
|
||||
prefix = infuncstr[0:single_quoted]
|
||||
infuncstr = prefix + infuncstr[single_quoted + 1 :]
|
||||
single_quoted = -1
|
||||
else:
|
||||
infuncstr += char
|
||||
infuncstr = infuncstr.strip()
|
||||
single_quoted = len(infuncstr) - 1
|
||||
literal_infuncstr = True
|
||||
|
||||
continue
|
||||
|
||||
if char == '"' and single_quoted < 0: # note that this is the same as '\"'
|
||||
if char == '"': # note that this is the same as '\"'
|
||||
# a double quote = flip status
|
||||
if double_quoted == 0:
|
||||
infuncstr = infuncstr[1:]
|
||||
|
|
@ -437,7 +416,7 @@ class FuncParser:
|
|||
|
||||
continue
|
||||
|
||||
if double_quoted >= 0 or single_quoted >= 0:
|
||||
if double_quoted >= 0:
|
||||
# inside a string definition - this escapes everything else
|
||||
infuncstr += char
|
||||
continue
|
||||
|
|
@ -551,7 +530,6 @@ class FuncParser:
|
|||
infuncstr = curr_func.infuncstr + str(exec_return)
|
||||
exec_return = ""
|
||||
curr_func.infuncstr = ""
|
||||
single_quoted = curr_func.single_quoted
|
||||
double_quoted = curr_func.double_quoted
|
||||
open_lparens = curr_func.open_lparens
|
||||
open_lsquare = curr_func.open_lsquare
|
||||
|
|
|
|||
|
|
@ -134,8 +134,8 @@ class TestFuncParser(TestCase):
|
|||
("$foo() Test noargs5", "_test() Test noargs5"),
|
||||
("Test args1 $foo(a,b,c)", "Test args1 _test(a, b, c)"),
|
||||
("Test args2 $bar(foo, bar, too)", "Test args2 _test(foo, bar, too)"),
|
||||
(r"Test args3 $bar(foo, bar, ' too')", "Test args3 _test(foo, bar, too)"),
|
||||
("Test args4 $foo('')", "Test args4 _test()"),
|
||||
(r'Test args3 $bar(foo, bar, " too")', "Test args3 _test(foo, bar, too)"),
|
||||
("Test args4 $foo('')", "Test args4 _test('')"), # ' treated as literal
|
||||
('Test args4 $foo("")', "Test args4 _test()"),
|
||||
("Test args5 $foo(\(\))", "Test args5 _test(())"),
|
||||
("Test args6 $foo(\()", "Test args6 _test(()"),
|
||||
|
|
@ -143,16 +143,16 @@ class TestFuncParser(TestCase):
|
|||
("Test args8 $foo())", "Test args8 _test())"),
|
||||
("Test args9 $foo(=)", "Test args9 _test(=)"),
|
||||
("Test args10 $foo(\,)", "Test args10 _test(,)"),
|
||||
("Test args10 $foo(',')", "Test args10 _test(,)"),
|
||||
(r'Test args10 $foo(",")', "Test args10 _test(,)"),
|
||||
("Test args11 $foo(()", "Test args11 $foo(()"), # invalid syntax
|
||||
(
|
||||
"Test kwarg1 $bar(foo=1, bar='foo', too=ere)",
|
||||
r'Test kwarg1 $bar(foo=1, bar="foo", too=ere)',
|
||||
"Test kwarg1 _test(foo=1, bar=foo, too=ere)",
|
||||
),
|
||||
("Test kwarg2 $bar(foo,bar,too=ere)", "Test kwarg2 _test(foo, bar, too=ere)"),
|
||||
("test kwarg3 $foo(foo = bar, bar = ere )", "test kwarg3 _test(foo=bar, bar=ere)"),
|
||||
(
|
||||
r"test kwarg4 $foo(foo =\' bar \',\" bar \"= ere )",
|
||||
r"test kwarg4 $foo(foo =' bar ',\" bar \"= ere )",
|
||||
"test kwarg4 _test(foo=' bar ', \" bar \"=ere)",
|
||||
),
|
||||
(
|
||||
|
|
@ -202,7 +202,7 @@ class TestFuncParser(TestCase):
|
|||
("Test eval1 $eval(21 + 21 - 10)", "Test eval1 32"),
|
||||
("Test eval2 $eval((21 + 21) / 2)", "Test eval2 21.0"),
|
||||
("Test eval3 $eval(\"'21' + 'foo' + 'bar'\")", "Test eval3 21foobar"),
|
||||
(r"Test eval4 $eval(\'21\' + \'$repl()\' + \"''\" + str(10 // 2))", "Test eval4 21rr5"),
|
||||
(r"Test eval4 $eval('21' + '$repl()' + \"\" + str(10 // 2))", "Test eval4 21rr5"),
|
||||
(
|
||||
r"Test eval5 $eval(\'21\' + \'\$repl()\' + \'\' + str(10 // 2))",
|
||||
"Test eval5 21$repl()5",
|
||||
|
|
@ -519,10 +519,10 @@ class TestDefaultCallables(TestCase):
|
|||
("There is $an(thing) here", "There is a thing here"),
|
||||
("Some $eval(\"'-'*20\")Hello", "Some --------------------Hello"),
|
||||
('$crop("spider\'s silk", 5)', "spide"),
|
||||
("$crop(spider's silk, 5)", "spide"),
|
||||
("$an(apple)", "an apple"),
|
||||
# These two are broken because of https://github.com/evennia/evennia/issues/2912
|
||||
# ("$round(2.9) apples", "3.0 apples"),
|
||||
# ("$round(2.967, 1) apples", "3.0 apples"),
|
||||
("$round(2.9) apples", "3.0 apples"),
|
||||
("$round(2.967, 1) apples", "3.0 apples"),
|
||||
# Degenerate cases
|
||||
("$int2str() apples", " apples"),
|
||||
("$int2str(x) apples", "x apples"),
|
||||
|
|
@ -616,6 +616,24 @@ class TestDefaultCallables(TestCase):
|
|||
ret = self.parser.parse_to_any(string)
|
||||
self.assertIn(ret, (1, 2))
|
||||
|
||||
def test_choice_quotes(self):
|
||||
"""
|
||||
Test choice, but also commas embedded.
|
||||
"""
|
||||
|
||||
string = "$choice(spider's, devil's, mummy's, zombie's)"
|
||||
ret = self.parser.parse(string)
|
||||
self.assertIn(ret, ("spider's", "devil's", "mummy's", "zombie's"))
|
||||
|
||||
string = '$choice("Tiamat, queen of dragons", "Dracula, lord of the night")'
|
||||
ret = self.parser.parse(string)
|
||||
self.assertIn(ret, ("Tiamat, queen of dragons", "Dracula, lord of the night"))
|
||||
|
||||
# single quotes are ignored, so this becomes many entries
|
||||
string = "$choice('Tiamat, queen of dragons', 'Dracula, lord of the night')"
|
||||
ret = self.parser.parse(string)
|
||||
self.assertIn(ret, ("'Tiamat", "queen of dragons'", "'Dracula", " lord of the night'"))
|
||||
|
||||
def test_randint(self):
|
||||
string = "$randint(1.0, 3.0)"
|
||||
ret = self.parser.parse_to_any(string, raise_errors=True)
|
||||
|
|
@ -649,16 +667,6 @@ class TestDefaultCallables(TestCase):
|
|||
)
|
||||
|
||||
def test_escaped(self):
|
||||
self.assertEqual(
|
||||
self.parser.parse(
|
||||
"this should be $pad('''escaped,''' and '''instead,''' cropped $crop(with a long,5)"
|
||||
" text., 80)"
|
||||
),
|
||||
"this should be escaped, and instead, cropped with text. "
|
||||
" ",
|
||||
)
|
||||
|
||||
def test_escaped2(self):
|
||||
raw_str = (
|
||||
'this should be $pad("""escaped,""" and """instead,""" cropped $crop(with a long,5)'
|
||||
" text., 80)"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue