Homogenize funcparser calls
This commit is contained in:
parent
adb370b1d3
commit
a3a57314a1
11 changed files with 293 additions and 993 deletions
|
|
@ -2115,7 +2115,8 @@ def _apply_diff(caller, **kwargs):
|
|||
objects = kwargs["objects"]
|
||||
back_node = kwargs["back_node"]
|
||||
diff = kwargs.get("diff", None)
|
||||
num_changed = spawner.batch_update_objects_with_prototype(prototype, diff=diff, objects=objects)
|
||||
num_changed = spawner.batch_update_objects_with_prototype(prototype, diff=diff, objects=objects,
|
||||
caller=caller)
|
||||
caller.msg("|g{num} objects were updated successfully.|n".format(num=num_changed))
|
||||
return back_node
|
||||
|
||||
|
|
@ -2483,7 +2484,7 @@ def _spawn(caller, **kwargs):
|
|||
if not prototype.get("location"):
|
||||
prototype["location"] = caller
|
||||
|
||||
obj = spawner.spawn(prototype)
|
||||
obj = spawner.spawn(prototype, caller=caller)
|
||||
if obj:
|
||||
obj = obj[0]
|
||||
text = "|gNew instance|n {key} ({dbref}) |gspawned at location |n{loc}|n|g.|n".format(
|
||||
|
|
|
|||
|
|
@ -1,33 +1,28 @@
|
|||
"""
|
||||
Protfuncs are function-strings embedded in a prototype and allows for a builder to create a
|
||||
prototype with custom logics without having access to Python. The Protfunc is parsed using the
|
||||
inlinefunc parser but is fired at the moment the spawning happens, using the creating object's
|
||||
session as input.
|
||||
Protfuncs are FuncParser-callables that can be embedded in a prototype to
|
||||
provide custom logic without having access to Python. The protfunc is parsed at
|
||||
the time of spawning, using the creating object's session as input. If the
|
||||
protfunc returns a non-string, this is what will be added to the prototype.
|
||||
|
||||
In the prototype dict, the protfunc is specified as a string inside the prototype, e.g.:
|
||||
|
||||
{ ...
|
||||
|
||||
"key": "$funcname(arg1, arg2, ...)"
|
||||
"key": "$funcname(args, kwargs)"
|
||||
|
||||
... }
|
||||
|
||||
and multiple functions can be nested (no keyword args are supported). The result will be used as the
|
||||
value for that prototype key for that individual spawn.
|
||||
|
||||
Available protfuncs are callables in one of the modules of `settings.PROT_FUNC_MODULES`. They
|
||||
are specified as functions
|
||||
Available protfuncs are either all callables in one of the modules of `settings.PROT_FUNC_MODULES`
|
||||
or all callables added to a dict FUNCPARSER_CALLABLES in such a module.
|
||||
|
||||
def funcname (*args, **kwargs)
|
||||
|
||||
where *args are the arguments given in the prototype, and **kwargs are inserted by Evennia:
|
||||
At spawn-time the spawner passes the following extra kwargs into each callable (in addition to
|
||||
what is added in the call itself):
|
||||
|
||||
- session (Session): The Session of the entity spawning using this prototype.
|
||||
- prototype (dict): The dict this protfunc is a part of.
|
||||
- current_key (str): The active key this value belongs to in the prototype.
|
||||
- testing (bool): This is set if this function is called as part of the prototype validation; if
|
||||
set, the protfunc should take care not to perform any persistent actions, such as operate on
|
||||
objects or add things to the database.
|
||||
|
||||
Any traceback raised by this function will be handled at the time of spawning and abort the spawn
|
||||
before any object is created/updated. It must otherwise return the value to store for the specified
|
||||
|
|
@ -35,312 +30,26 @@ prototype key (this value must be possible to serialize in an Attribute).
|
|||
|
||||
"""
|
||||
|
||||
from ast import literal_eval
|
||||
from random import randint as base_randint, random as base_random, choice as base_choice
|
||||
import re
|
||||
|
||||
from evennia.utils import search
|
||||
from evennia.utils.utils import justify as base_justify, is_iter, to_str
|
||||
|
||||
_PROTLIB = None
|
||||
|
||||
_RE_DBREF = re.compile(r"\#[0-9]+")
|
||||
from evennia.utils import funcparser
|
||||
|
||||
|
||||
# default protfuncs
|
||||
|
||||
|
||||
def random(*args, **kwargs):
|
||||
def protfunc_callable_protkey(*args, **kwargs):
|
||||
"""
|
||||
Usage: $random()
|
||||
Returns a random value in the interval [0, 1)
|
||||
|
||||
"""
|
||||
return base_random()
|
||||
|
||||
|
||||
def randint(*args, **kwargs):
|
||||
"""
|
||||
Usage: $randint(start, end)
|
||||
Returns random integer in interval [start, end]
|
||||
|
||||
"""
|
||||
if len(args) != 2:
|
||||
raise TypeError("$randint needs two arguments - start and end.")
|
||||
start, end = int(args[0]), int(args[1])
|
||||
return base_randint(start, end)
|
||||
|
||||
|
||||
def left_justify(*args, **kwargs):
|
||||
"""
|
||||
Usage: $left_justify(<text>)
|
||||
Returns <text> left-justified.
|
||||
|
||||
"""
|
||||
if args:
|
||||
return base_justify(args[0], align="l")
|
||||
return ""
|
||||
|
||||
|
||||
def right_justify(*args, **kwargs):
|
||||
"""
|
||||
Usage: $right_justify(<text>)
|
||||
Returns <text> right-justified across screen width.
|
||||
|
||||
"""
|
||||
if args:
|
||||
return base_justify(args[0], align="r")
|
||||
return ""
|
||||
|
||||
|
||||
def center_justify(*args, **kwargs):
|
||||
|
||||
"""
|
||||
Usage: $center_justify(<text>)
|
||||
Returns <text> centered in screen width.
|
||||
|
||||
"""
|
||||
if args:
|
||||
return base_justify(args[0], align="c")
|
||||
return ""
|
||||
|
||||
|
||||
def choice(*args, **kwargs):
|
||||
"""
|
||||
Usage: $choice(val, val, val, ...)
|
||||
Returns one of the values randomly
|
||||
"""
|
||||
if args:
|
||||
return base_choice(args)
|
||||
return ""
|
||||
|
||||
|
||||
def full_justify(*args, **kwargs):
|
||||
|
||||
"""
|
||||
Usage: $full_justify(<text>)
|
||||
Returns <text> filling up screen width by adding extra space.
|
||||
|
||||
"""
|
||||
if args:
|
||||
return base_justify(args[0], align="f")
|
||||
return ""
|
||||
|
||||
|
||||
def protkey(*args, **kwargs):
|
||||
"""
|
||||
Usage: $protkey(<key>)
|
||||
Usage: $protkey(keyname)
|
||||
Returns the value of another key in this prototoype. Will raise an error if
|
||||
the key is not found in this prototype.
|
||||
|
||||
"""
|
||||
if args:
|
||||
prototype = kwargs["prototype"]
|
||||
return prototype[args[0].strip()]
|
||||
if not args:
|
||||
return ""
|
||||
|
||||
prototype = kwargs.get("prototype", {})
|
||||
return prototype[args[0].strip()]
|
||||
|
||||
|
||||
def add(*args, **kwargs):
|
||||
"""
|
||||
Usage: $add(val1, val2)
|
||||
Returns the result of val1 + val2. Values must be
|
||||
valid simple Python structures possible to add,
|
||||
such as numbers, lists etc.
|
||||
|
||||
"""
|
||||
if len(args) > 1:
|
||||
val1, val2 = args[0], args[1]
|
||||
# try to convert to python structures, otherwise, keep as strings
|
||||
try:
|
||||
val1 = literal_eval(val1.strip())
|
||||
except Exception:
|
||||
pass
|
||||
try:
|
||||
val2 = literal_eval(val2.strip())
|
||||
except Exception:
|
||||
pass
|
||||
return val1 + val2
|
||||
raise ValueError("$add requires two arguments.")
|
||||
|
||||
|
||||
def sub(*args, **kwargs):
|
||||
"""
|
||||
Usage: $del(val1, val2)
|
||||
Returns the value of val1 - val2. Values must be
|
||||
valid simple Python structures possible to
|
||||
subtract.
|
||||
|
||||
"""
|
||||
if len(args) > 1:
|
||||
val1, val2 = args[0], args[1]
|
||||
# try to convert to python structures, otherwise, keep as strings
|
||||
try:
|
||||
val1 = literal_eval(val1.strip())
|
||||
except Exception:
|
||||
pass
|
||||
try:
|
||||
val2 = literal_eval(val2.strip())
|
||||
except Exception:
|
||||
pass
|
||||
return val1 - val2
|
||||
raise ValueError("$sub requires two arguments.")
|
||||
|
||||
|
||||
def mult(*args, **kwargs):
|
||||
"""
|
||||
Usage: $mul(val1, val2)
|
||||
Returns the value of val1 * val2. The values must be
|
||||
valid simple Python structures possible to
|
||||
multiply, like strings and/or numbers.
|
||||
|
||||
"""
|
||||
if len(args) > 1:
|
||||
val1, val2 = args[0], args[1]
|
||||
# try to convert to python structures, otherwise, keep as strings
|
||||
try:
|
||||
val1 = literal_eval(val1.strip())
|
||||
except Exception:
|
||||
pass
|
||||
try:
|
||||
val2 = literal_eval(val2.strip())
|
||||
except Exception:
|
||||
pass
|
||||
return val1 * val2
|
||||
raise ValueError("$mul requires two arguments.")
|
||||
|
||||
|
||||
def div(*args, **kwargs):
|
||||
"""
|
||||
Usage: $div(val1, val2)
|
||||
Returns the value of val1 / val2. Values must be numbers and
|
||||
the result is always a float.
|
||||
|
||||
"""
|
||||
if len(args) > 1:
|
||||
val1, val2 = args[0], args[1]
|
||||
# try to convert to python structures, otherwise, keep as strings
|
||||
try:
|
||||
val1 = literal_eval(val1.strip())
|
||||
except Exception:
|
||||
pass
|
||||
try:
|
||||
val2 = literal_eval(val2.strip())
|
||||
except Exception:
|
||||
pass
|
||||
return val1 / float(val2)
|
||||
raise ValueError("$mult requires two arguments.")
|
||||
|
||||
|
||||
def toint(*args, **kwargs):
|
||||
"""
|
||||
Usage: $toint(<number>)
|
||||
Returns <number> as an integer.
|
||||
"""
|
||||
if args:
|
||||
val = args[0]
|
||||
try:
|
||||
return int(literal_eval(val.strip()))
|
||||
except ValueError:
|
||||
return val
|
||||
raise ValueError("$toint requires one argument.")
|
||||
|
||||
|
||||
def eval(*args, **kwargs):
|
||||
"""
|
||||
Usage $eval(<expression>)
|
||||
Returns evaluation of a simple Python expression. The string may *only* consist of the following
|
||||
Python literal structures: strings, numbers, tuples, lists, dicts, booleans,
|
||||
and None. The strings can also contain #dbrefs. Escape embedded protfuncs as $$protfunc(..)
|
||||
- those will then be evaluated *after* $eval.
|
||||
|
||||
"""
|
||||
global _PROTLIB
|
||||
if not _PROTLIB:
|
||||
from evennia.prototypes import prototypes as _PROTLIB
|
||||
|
||||
string = ",".join(args)
|
||||
struct = literal_eval(string)
|
||||
|
||||
if isinstance(struct, str):
|
||||
# we must shield the string, otherwise it will be merged as a string and future
|
||||
# literal_evas will pick up e.g. '2' as something that should be converted to a number
|
||||
struct = '"{}"'.format(struct)
|
||||
|
||||
# convert any #dbrefs to objects (also in nested structures)
|
||||
struct = _PROTLIB.value_to_obj_or_any(struct)
|
||||
|
||||
return struct
|
||||
|
||||
|
||||
def _obj_search(*args, **kwargs):
|
||||
"Helper function to search for an object"
|
||||
|
||||
query = "".join(args)
|
||||
session = kwargs.get("session", None)
|
||||
return_list = kwargs.pop("return_list", False)
|
||||
account = None
|
||||
|
||||
if session:
|
||||
account = session.account
|
||||
|
||||
targets = search.search_object(query)
|
||||
|
||||
if return_list:
|
||||
retlist = []
|
||||
if account:
|
||||
for target in targets:
|
||||
if target.access(account, target, "control"):
|
||||
retlist.append(target)
|
||||
else:
|
||||
retlist = targets
|
||||
return retlist
|
||||
else:
|
||||
# single-match
|
||||
if not targets:
|
||||
raise ValueError("$obj: Query '{}' gave no matches.".format(query))
|
||||
if len(targets) > 1:
|
||||
raise ValueError(
|
||||
"$obj: Query '{query}' gave {nmatches} matches. Limit your "
|
||||
"query or use $objlist instead.".format(query=query, nmatches=len(targets))
|
||||
)
|
||||
target = targets[0]
|
||||
if account:
|
||||
if not target.access(account, target, "control"):
|
||||
raise ValueError(
|
||||
"$obj: Obj {target}(#{dbref} cannot be added - "
|
||||
"Account {account} does not have 'control' access.".format(
|
||||
target=target.key, dbref=target.id, account=account
|
||||
)
|
||||
)
|
||||
return target
|
||||
|
||||
|
||||
def obj(*args, **kwargs):
|
||||
"""
|
||||
Usage $obj(<query>)
|
||||
Returns one Object searched globally by key, alias or #dbref. Error if more than one.
|
||||
|
||||
"""
|
||||
obj = _obj_search(return_list=False, *args, **kwargs)
|
||||
if obj:
|
||||
return "#{}".format(obj.id)
|
||||
return "".join(args)
|
||||
|
||||
|
||||
def objlist(*args, **kwargs):
|
||||
"""
|
||||
Usage $objlist(<query>)
|
||||
Returns list with one or more Objects searched globally by key, alias or #dbref.
|
||||
|
||||
"""
|
||||
return ["#{}".format(obj.id) for obj in _obj_search(return_list=True, *args, **kwargs)]
|
||||
|
||||
|
||||
def dbref(*args, **kwargs):
|
||||
"""
|
||||
Usage $dbref(<#dbref>)
|
||||
Validate that a #dbref input is valid.
|
||||
"""
|
||||
if not args or len(args) < 1 or _RE_DBREF.match(args[0]) is None:
|
||||
raise ValueError("$dbref requires a valid #dbref argument.")
|
||||
|
||||
return obj(args[0])
|
||||
# this is picked up by FuncParser
|
||||
FUNCPARSER_CALLABLES = {
|
||||
"protkey": protfunc_callable_protkey,
|
||||
**funcparser.FUNCPARSER_CALLABLES,
|
||||
**funcparser.SEARCHING_CALLABLES,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ from evennia.utils.utils import (
|
|||
from evennia.locks.lockhandler import validate_lockstring, check_lockstring
|
||||
from evennia.utils import logger
|
||||
from evennia.utils.funcparser import FuncParser
|
||||
from evennia.utils import inlinefuncs, dbserialize
|
||||
from evennia.utils import dbserialize
|
||||
from evennia.utils.evtable import EvTable
|
||||
|
||||
|
||||
|
|
@ -721,7 +721,7 @@ for mod in settings.PROT_FUNC_MODULES:
|
|||
raise
|
||||
|
||||
|
||||
def protfunc_parser(value, available_functions=None, testing=False, stacktrace=False, **kwargs):
|
||||
def protfunc_parser(value, available_functions=None, testing=False, stacktrace=False, caller=None, **kwargs):
|
||||
"""
|
||||
Parse a prototype value string for a protfunc and process it.
|
||||
|
||||
|
|
@ -741,6 +741,8 @@ def protfunc_parser(value, available_functions=None, testing=False, stacktrace=F
|
|||
session (Session): Passed to protfunc. Session of the entity spawning the prototype.
|
||||
protototype (dict): Passed to protfunc. The dict this protfunc is a part of.
|
||||
current_key(str): Passed to protfunc. The key in the prototype that will hold this value.
|
||||
caller (Object or Account): This is necessary for certain protfuncs that perform object
|
||||
searches and have to check permissions.
|
||||
any (any): Passed on to the protfunc.
|
||||
|
||||
Returns:
|
||||
|
|
@ -759,11 +761,8 @@ def protfunc_parser(value, available_functions=None, testing=False, stacktrace=F
|
|||
|
||||
available_functions = PROT_FUNCS if available_functions is None else available_functions
|
||||
|
||||
result = FuncParser(available_functions).parse(value, raise_errors=True, **kwargs)
|
||||
|
||||
# result = inlinefuncs.parse_inlinefunc(
|
||||
# value, available_funcs=available_functions, stacktrace=stacktrace, testing=testing, **kwargs
|
||||
# )
|
||||
result = FuncParser(available_functions).parse(
|
||||
value, raise_errors=True, caller=caller, **kwargs)
|
||||
|
||||
err = None
|
||||
try:
|
||||
|
|
|
|||
|
|
@ -607,7 +607,8 @@ def format_diff(diff, minimal=True):
|
|||
return "\n ".join(line for line in texts if line)
|
||||
|
||||
|
||||
def batch_update_objects_with_prototype(prototype, diff=None, objects=None, exact=False):
|
||||
def batch_update_objects_with_prototype(prototype, diff=None, objects=None,
|
||||
exact=False, caller=None):
|
||||
"""
|
||||
Update existing objects with the latest version of the prototype.
|
||||
|
||||
|
|
@ -624,6 +625,7 @@ def batch_update_objects_with_prototype(prototype, diff=None, objects=None, exac
|
|||
if it's not set in the prototype. With `exact=True`, all un-specified properties of the
|
||||
objects will be removed if they exist. This will lead to a more accurate 1:1 correlation
|
||||
between the object and the prototype but is usually impractical.
|
||||
caller (Object or Account, optional): This may be used by protfuncs to do permission checks.
|
||||
Returns:
|
||||
changed (int): The number of objects that had changes applied to them.
|
||||
|
||||
|
|
@ -675,33 +677,33 @@ def batch_update_objects_with_prototype(prototype, diff=None, objects=None, exac
|
|||
do_save = True
|
||||
|
||||
if key == "key":
|
||||
obj.db_key = init_spawn_value(val, str)
|
||||
obj.db_key = init_spawn_value(val, str, caller=caller)
|
||||
elif key == "typeclass":
|
||||
obj.db_typeclass_path = init_spawn_value(val, str)
|
||||
obj.db_typeclass_path = init_spawn_value(val, str, caller=caller)
|
||||
elif key == "location":
|
||||
obj.db_location = init_spawn_value(val, value_to_obj)
|
||||
obj.db_location = init_spawn_value(val, value_to_obj, caller=caller)
|
||||
elif key == "home":
|
||||
obj.db_home = init_spawn_value(val, value_to_obj)
|
||||
obj.db_home = init_spawn_value(val, value_to_obj, caller=caller)
|
||||
elif key == "destination":
|
||||
obj.db_destination = init_spawn_value(val, value_to_obj)
|
||||
obj.db_destination = init_spawn_value(val, value_to_obj, caller=caller)
|
||||
elif key == "locks":
|
||||
if directive == "REPLACE":
|
||||
obj.locks.clear()
|
||||
obj.locks.add(init_spawn_value(val, str))
|
||||
obj.locks.add(init_spawn_value(val, str, caller=caller))
|
||||
elif key == "permissions":
|
||||
if directive == "REPLACE":
|
||||
obj.permissions.clear()
|
||||
obj.permissions.batch_add(*(init_spawn_value(perm, str) for perm in val))
|
||||
obj.permissions.batch_add(*(init_spawn_value(perm, str, caller=caller) for perm in val))
|
||||
elif key == "aliases":
|
||||
if directive == "REPLACE":
|
||||
obj.aliases.clear()
|
||||
obj.aliases.batch_add(*(init_spawn_value(alias, str) for alias in val))
|
||||
obj.aliases.batch_add(*(init_spawn_value(alias, str, caller=caller) for alias in val))
|
||||
elif key == "tags":
|
||||
if directive == "REPLACE":
|
||||
obj.tags.clear()
|
||||
obj.tags.batch_add(
|
||||
*(
|
||||
(init_spawn_value(ttag, str), tcategory, tdata)
|
||||
(init_spawn_value(ttag, str, caller=caller), tcategory, tdata)
|
||||
for ttag, tcategory, tdata in val
|
||||
)
|
||||
)
|
||||
|
|
@ -711,8 +713,8 @@ def batch_update_objects_with_prototype(prototype, diff=None, objects=None, exac
|
|||
obj.attributes.batch_add(
|
||||
*(
|
||||
(
|
||||
init_spawn_value(akey, str),
|
||||
init_spawn_value(aval, value_to_obj),
|
||||
init_spawn_value(akey, str, caller=caller),
|
||||
init_spawn_value(aval, value_to_obj, caller=caller),
|
||||
acategory,
|
||||
alocks,
|
||||
)
|
||||
|
|
@ -723,7 +725,7 @@ def batch_update_objects_with_prototype(prototype, diff=None, objects=None, exac
|
|||
# we don't auto-rerun exec statements, it would be huge security risk!
|
||||
pass
|
||||
else:
|
||||
obj.attributes.add(key, init_spawn_value(val, value_to_obj))
|
||||
obj.attributes.add(key, init_spawn_value(val, value_to_obj, caller=caller))
|
||||
elif directive == "REMOVE":
|
||||
do_save = True
|
||||
if key == "key":
|
||||
|
|
@ -836,7 +838,7 @@ def batch_create_object(*objparams):
|
|||
# Spawner mechanism
|
||||
|
||||
|
||||
def spawn(*prototypes, **kwargs):
|
||||
def spawn(*prototypes, caller=None, **kwargs):
|
||||
"""
|
||||
Spawn a number of prototyped objects.
|
||||
|
||||
|
|
@ -845,6 +847,7 @@ def spawn(*prototypes, **kwargs):
|
|||
prototype_key (will be used to find the prototype) or a full prototype
|
||||
dictionary. These will be batched-spawned as one object each.
|
||||
Keyword Args:
|
||||
caller (Object or Account, optional): This may be used by protfuncs to do access checks.
|
||||
prototype_modules (str or list): A python-path to a prototype
|
||||
module, or a list of such paths. These will be used to build
|
||||
the global protparents dictionary accessible by the input
|
||||
|
|
@ -910,39 +913,39 @@ def spawn(*prototypes, **kwargs):
|
|||
"key",
|
||||
"Spawned-{}".format(hashlib.md5(bytes(str(time.time()), "utf-8")).hexdigest()[:6]),
|
||||
)
|
||||
create_kwargs["db_key"] = init_spawn_value(val, str)
|
||||
create_kwargs["db_key"] = init_spawn_value(val, str, caller=caller)
|
||||
|
||||
val = prot.pop("location", None)
|
||||
create_kwargs["db_location"] = init_spawn_value(val, value_to_obj)
|
||||
create_kwargs["db_location"] = init_spawn_value(val, value_to_obj, caller=caller)
|
||||
|
||||
val = prot.pop("home", None)
|
||||
if val:
|
||||
create_kwargs["db_home"] = init_spawn_value(val, value_to_obj)
|
||||
create_kwargs["db_home"] = init_spawn_value(val, value_to_obj, caller=caller)
|
||||
else:
|
||||
try:
|
||||
create_kwargs["db_home"] = init_spawn_value(settings.DEFAULT_HOME, value_to_obj)
|
||||
create_kwargs["db_home"] = init_spawn_value(settings.DEFAULT_HOME, value_to_obj, caller=caller)
|
||||
except ObjectDB.DoesNotExist:
|
||||
# settings.DEFAULT_HOME not existing is common for unittests
|
||||
pass
|
||||
|
||||
val = prot.pop("destination", None)
|
||||
create_kwargs["db_destination"] = init_spawn_value(val, value_to_obj)
|
||||
create_kwargs["db_destination"] = init_spawn_value(val, value_to_obj, caller=caller)
|
||||
|
||||
val = prot.pop("typeclass", settings.BASE_OBJECT_TYPECLASS)
|
||||
create_kwargs["db_typeclass_path"] = init_spawn_value(val, str)
|
||||
create_kwargs["db_typeclass_path"] = init_spawn_value(val, str, caller=caller)
|
||||
|
||||
# extract calls to handlers
|
||||
val = prot.pop("permissions", [])
|
||||
permission_string = init_spawn_value(val, make_iter)
|
||||
permission_string = init_spawn_value(val, make_iter, caller=caller)
|
||||
val = prot.pop("locks", "")
|
||||
lock_string = init_spawn_value(val, str)
|
||||
lock_string = init_spawn_value(val, str, caller=caller)
|
||||
val = prot.pop("aliases", [])
|
||||
alias_string = init_spawn_value(val, make_iter)
|
||||
alias_string = init_spawn_value(val, make_iter, caller=caller)
|
||||
|
||||
val = prot.pop("tags", [])
|
||||
tags = []
|
||||
for (tag, category, *data) in val:
|
||||
tags.append((init_spawn_value(tag, str), category, data[0] if data else None))
|
||||
tags.append((init_spawn_value(tag, str, caller=caller), category, data[0] if data else None))
|
||||
|
||||
prototype_key = prototype.get("prototype_key", None)
|
||||
if prototype_key:
|
||||
|
|
@ -950,11 +953,11 @@ def spawn(*prototypes, **kwargs):
|
|||
tags.append((prototype_key, PROTOTYPE_TAG_CATEGORY))
|
||||
|
||||
val = prot.pop("exec", "")
|
||||
execs = init_spawn_value(val, make_iter)
|
||||
execs = init_spawn_value(val, make_iter, caller=caller)
|
||||
|
||||
# extract ndb assignments
|
||||
nattributes = dict(
|
||||
(key.split("_", 1)[1], init_spawn_value(val, value_to_obj))
|
||||
(key.split("_", 1)[1], init_spawn_value(val, value_to_obj, caller=caller))
|
||||
for key, val in prot.items()
|
||||
if key.startswith("ndb_")
|
||||
)
|
||||
|
|
@ -963,7 +966,7 @@ def spawn(*prototypes, **kwargs):
|
|||
val = make_iter(prot.pop("attrs", []))
|
||||
attributes = []
|
||||
for (attrname, value, *rest) in val:
|
||||
attributes.append((attrname, init_spawn_value(value),
|
||||
attributes.append((attrname, init_spawn_value(value, caller=caller),
|
||||
rest[0] if rest else None, rest[1] if len(rest) > 1 else None))
|
||||
|
||||
simple_attributes = []
|
||||
|
|
@ -975,7 +978,7 @@ def spawn(*prototypes, **kwargs):
|
|||
continue
|
||||
else:
|
||||
simple_attributes.append(
|
||||
(key, init_spawn_value(value, value_to_obj_or_any), None, None)
|
||||
(key, init_spawn_value(value, value_to_obj_or_any, caller=caller), None, None)
|
||||
)
|
||||
|
||||
attributes = attributes + simple_attributes
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue