Update FuncParser docs
This commit is contained in:
parent
f5d0018c8e
commit
517ec5d4d5
3 changed files with 85 additions and 29 deletions
|
|
@ -152,8 +152,8 @@ mv-local:
|
||||||
@echo "Documentation built (multiversion + autodocs)."
|
@echo "Documentation built (multiversion + autodocs)."
|
||||||
@echo "To see result, open evennia/docs/build/html/<version>/index.html in a browser."
|
@echo "To see result, open evennia/docs/build/html/<version>/index.html in a browser."
|
||||||
|
|
||||||
# note - don't run the following manually, the result will clash with the result
|
# note - don't run deploy/release manually, the result will clash with the
|
||||||
# of the github actions!
|
# result of the github actions!
|
||||||
deploy:
|
deploy:
|
||||||
make _multiversion-deploy
|
make _multiversion-deploy
|
||||||
@echo "Documentation deployed."
|
@echo "Documentation deployed."
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ git checkout gh-pages
|
||||||
# with the build/ directory available since this is not in git
|
# with the build/ directory available since this is not in git
|
||||||
|
|
||||||
# remove all but the build dir
|
# remove all but the build dir
|
||||||
|
# TODO don't delete old branches after 1.0 release; they will get harder and harder to rebuild
|
||||||
ls -Q | grep -v build | xargs rm -Rf
|
ls -Q | grep -v build | xargs rm -Rf
|
||||||
|
|
||||||
cp -Rf build/html/* .
|
cp -Rf build/html/* .
|
||||||
|
|
|
||||||
|
|
@ -10,14 +10,15 @@ the return from the function.
|
||||||
from evennia.utils.funcparser import FuncParser
|
from evennia.utils.funcparser import FuncParser
|
||||||
|
|
||||||
def _power_callable(*args, **kwargs):
|
def _power_callable(*args, **kwargs):
|
||||||
"""This will be callable as $square(number, power=<num>) in string"""
|
"""This will be callable as $pow(number, power=<num>) in string"""
|
||||||
pow = int(kwargs.get('power', 2))
|
pow = int(kwargs.get('power', 2))
|
||||||
return float(args[0]) ** pow
|
return float(args[0]) ** pow
|
||||||
|
|
||||||
|
# create a parser and tell it that '$pow' means using _power_callable
|
||||||
parser = FuncParser({"pow": _power_callable})
|
parser = FuncParser({"pow": _power_callable})
|
||||||
|
|
||||||
```
|
```
|
||||||
Next, just pass a string into the parser, optionally containing `$func(...)` markers:
|
Next, just pass a string into the parser, containing `$func(...)` markers:
|
||||||
|
|
||||||
```python
|
```python
|
||||||
parser.parse("We have that 4 x 4 x 4 is $pow(4, power=3).")
|
parser.parse("We have that 4 x 4 x 4 is $pow(4, power=3).")
|
||||||
|
|
@ -71,7 +72,7 @@ You can apply inline function parsing to any string. The
|
||||||
from evennia.utils import funcparser
|
from evennia.utils import funcparser
|
||||||
|
|
||||||
parser = FuncParser(callables, **default_kwargs)
|
parser = FuncParser(callables, **default_kwargs)
|
||||||
parsed_string = parser.parser(input_string, raise_errors=False,
|
parsed_string = parser.parse(input_string, raise_errors=False,
|
||||||
escape=False, strip=False,
|
escape=False, strip=False,
|
||||||
return_str=True, **reserved_kwargs)
|
return_str=True, **reserved_kwargs)
|
||||||
|
|
||||||
|
|
@ -90,8 +91,12 @@ available to the parser as you parse strings with it. It can either be
|
||||||
an underscore `_`) will be considered a suitable callable. The name of the function will be the `$funcname`
|
an underscore `_`) will be considered a suitable callable. The name of the function will be the `$funcname`
|
||||||
by which it can be called.
|
by which it can be called.
|
||||||
- A `list` of modules/paths. This allows you to pull in modules from many sources for your parsing.
|
- A `list` of modules/paths. This allows you to pull in modules from many sources for your parsing.
|
||||||
|
- The `**default` kwargs are optional kwargs that will be passed to _all_
|
||||||
|
callables every time this parser is used - unless the user overrides it explicitly in
|
||||||
|
their call. This is great for providing sensible standards that the user can
|
||||||
|
tweak as needed.
|
||||||
|
|
||||||
The other arguments to the parser:
|
`FuncParser.parse` takes further arguments, and can vary for every string parsed.
|
||||||
|
|
||||||
- `raise_errors` - By default, any errors from a callable will be quietly ignored and the result
|
- `raise_errors` - By default, any errors from a callable will be quietly ignored and the result
|
||||||
will be that the failing function call will show verbatim. If `raise_errors` is set,
|
will be that the failing function call will show verbatim. If `raise_errors` is set,
|
||||||
|
|
@ -102,12 +107,14 @@ The other arguments to the parser:
|
||||||
- `return_str` - When `True` (default), `parser` always returns a string. If `False`, it may return
|
- `return_str` - When `True` (default), `parser` always returns a string. If `False`, it may return
|
||||||
the return value of a single function call in the string. This is the same as using the `.parse_to_any`
|
the return value of a single function call in the string. This is the same as using the `.parse_to_any`
|
||||||
method.
|
method.
|
||||||
- The `**default/reserved_keywords` are optional and allow you to pass custom data into _every_ function
|
- The `**reserved_keywords` are _always_ passed to every callable in the string.
|
||||||
call. This is great for including things like the current session or config options. Defaults can be
|
They override any `**defaults` given when instantiating the parser and cannot
|
||||||
replaced if the user gives the same-named kwarg in the string's function call. Reserved kwargs are always passed,
|
be overridden by the user - if they enter the same kwarg it will be ignored.
|
||||||
ignoring defaults or what the user passed. In addition, the `funcparser` and `raise_errors`
|
This is great for providing the current session, settings etc.
|
||||||
reserved kwargs are always passed - the first is a back-reference to the `FuncParser` instance and the second
|
- The `funcparser` and `raise_errors`
|
||||||
is the `raise_errors` boolean passed into `FuncParser.parse`.
|
are always added as reserved keywords - the first is a
|
||||||
|
back-reference to the `FuncParser` instance and the second
|
||||||
|
is the `raise_errors` boolean given to `FuncParser.parse`.
|
||||||
|
|
||||||
Here's an example of using the default/reserved keywords:
|
Here's an example of using the default/reserved keywords:
|
||||||
|
|
||||||
|
|
@ -158,7 +165,8 @@ created the parser.
|
||||||
|
|
||||||
However, if you _nest_ functions, the return of the innermost function may be something other than
|
However, if you _nest_ functions, the return of the innermost function may be something other than
|
||||||
a string. Let's introduce the `$eval` function, which evaluates simple expressions using
|
a string. Let's introduce the `$eval` function, which evaluates simple expressions using
|
||||||
Python's `literal_eval` and/or `simple_eval`.
|
Python's `literal_eval` and/or `simple_eval`. It returns whatever data type it
|
||||||
|
evaluates to.
|
||||||
|
|
||||||
"There's a $toint($eval(10 * 2.2))% chance of survival."
|
"There's a $toint($eval(10 * 2.2))% chance of survival."
|
||||||
|
|
||||||
|
|
@ -177,23 +185,66 @@ will be a string:
|
||||||
"There's a 22% chance of survival."
|
"There's a 22% chance of survival."
|
||||||
```
|
```
|
||||||
|
|
||||||
However, if you use the `parse_to_any` (or `parse(..., return_str=True)`) and _don't add any extra string around the outermost function call_,
|
However, if you use the `parse_to_any` (or `parse(..., return_str=False)`) and
|
||||||
|
_don't add any extra string around the outermost function call_,
|
||||||
you'll get the return type of the outermost callable back:
|
you'll get the return type of the outermost callable back:
|
||||||
|
|
||||||
```python
|
```python
|
||||||
parser.parse_to_any("$toint($eval(10 * 2.2)%")
|
|
||||||
"22%"
|
|
||||||
parser.parse_to_any("$toint($eval(10 * 2.2)")
|
parser.parse_to_any("$toint($eval(10 * 2.2)")
|
||||||
22
|
22
|
||||||
|
parser.parse_to_any("the number $toint($eval(10 * 2.2).")
|
||||||
|
"the number 22"
|
||||||
|
parser.parse_to_any("$toint($eval(10 * 2.2)%")
|
||||||
|
"22%"
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Escaping special character
|
||||||
|
|
||||||
|
When entering funcparser callables in strings, it looks like a regular
|
||||||
|
function call inside a string:
|
||||||
|
|
||||||
|
```python
|
||||||
|
"This is a $myfunc(arg1, arg2, kwarg=foo)."
|
||||||
|
```
|
||||||
|
|
||||||
|
Commas (`,`) and equal-signs (`=`) are considered to separate the arguments and
|
||||||
|
kwargs. In the same way, the right parenthesis (`)`) closes the argument list.
|
||||||
|
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."
|
||||||
|
```
|
||||||
|
|
||||||
|
You can escape in various ways.
|
||||||
|
|
||||||
|
- Prepending 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
|
||||||
|
"There is a $format('beautiful meadow, with dandelions') to the west."
|
||||||
|
```
|
||||||
|
- If you want verbatim quotes in your string, you can escape them too.
|
||||||
|
|
||||||
|
```python
|
||||||
|
"There is a $format('beautiful meadow, with \'dandelions\'') to the west."
|
||||||
|
```
|
||||||
|
|
||||||
### Safe convertion of inputs
|
### Safe convertion of inputs
|
||||||
|
|
||||||
Since you don't know in which order users may use your callables, they should always check the types
|
Since you don't know in which order users may use your callables, they should
|
||||||
of its inputs and convert to the type the callable needs. Note also that when converting from strings,
|
always check the types of its inputs and convert to the type the callable needs.
|
||||||
there are limits what inputs you can support. This is because FunctionParser strings are often used by
|
Note also that when converting from strings, there are limits what inputs you
|
||||||
non-developer players/builders and some things (such as complex classes/callables etc) are just not
|
can support. This is because FunctionParser strings can be used by
|
||||||
safe/possible to convert from string representation.
|
non-developer players/builders and some things (such as complex
|
||||||
|
classes/callables etc) are just not safe/possible to convert from string
|
||||||
|
representation.
|
||||||
|
|
||||||
In `evennia.utils.utils` is a helper called
|
In `evennia.utils.utils` is a helper called
|
||||||
[safe_convert_to_types](evennia.utils.utils.safe_convert_to_types). This function
|
[safe_convert_to_types](evennia.utils.utils.safe_convert_to_types). This function
|
||||||
|
|
@ -204,19 +255,24 @@ from evennia.utils.utils import safe_convert_to_types
|
||||||
|
|
||||||
def _process_callable(*args, **kwargs):
|
def _process_callable(*args, **kwargs):
|
||||||
"""
|
"""
|
||||||
A callable with a lot of custom options
|
$process(expression, local, extra1=34, extra2=foo)
|
||||||
|
|
||||||
$process(expression, local, extra=34, extra2=foo)
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
args, kwargs = safe_convert_to_type(
|
args, kwargs = safe_convert_to_type(
|
||||||
(('py', 'py'), {'extra1': int, 'extra2': str}),
|
(('py', str), {'extra1': int, 'extra2': str}),
|
||||||
*args, **kwargs)
|
*args, **kwargs)
|
||||||
|
|
||||||
# args/kwargs should be correct types now
|
# args/kwargs should be correct types now
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
In other words, in the callable `$process(expression, local, extra1=..,
|
||||||
|
extra2=...)`, the first argument will be handled by the 'py' converter
|
||||||
|
(described below), the second will passed through regular Python `str`,
|
||||||
|
kwargs will be handled by `int` and `str` respectively. You can supply
|
||||||
|
your own converter function as long as it takes one argument and returns
|
||||||
|
the converted result.
|
||||||
|
|
||||||
In other words,
|
In other words,
|
||||||
|
|
||||||
```python
|
```python
|
||||||
|
|
@ -224,8 +280,7 @@ args, kwargs = safe_convert_to_type(
|
||||||
(tuple_of_arg_converters, dict_of_kwarg_converters), *args, **kwargs)
|
(tuple_of_arg_converters, dict_of_kwarg_converters), *args, **kwargs)
|
||||||
```
|
```
|
||||||
|
|
||||||
Each converter should be a callable taking one argument - this will be the arg/kwarg-value to convert. The
|
The special converter `"py"` will try to convert a string argument to a Python structure with the help of the
|
||||||
special converter `"py"` will try to convert a string argument to a Python structure with the help of the
|
|
||||||
following tools (which you may also find useful to experiment with on your own):
|
following tools (which you may also find useful to experiment with on your own):
|
||||||
|
|
||||||
- [ast.literal_eval](https://docs.python.org/3.8/library/ast.html#ast.literal_eval) is an in-built Python
|
- [ast.literal_eval](https://docs.python.org/3.8/library/ast.html#ast.literal_eval) is an in-built Python
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue