Fixes @set to be more accepting of various Python structures. It will now instead convert to string on a ValueError (commonly because a string was not enclosed in quotes) while giving a error string to the user informing of this. This should fix Issue 256.
This commit is contained in:
parent
23ba17debe
commit
a30029472b
1 changed files with 33 additions and 16 deletions
|
|
@ -19,6 +19,13 @@ __all__ = ("ObjManipCommand", "CmdSetObjAlias", "CmdCopy",
|
||||||
"CmdLock", "CmdExamine", "CmdFind", "CmdTeleport",
|
"CmdLock", "CmdExamine", "CmdFind", "CmdTeleport",
|
||||||
"CmdScript")
|
"CmdScript")
|
||||||
|
|
||||||
|
try:
|
||||||
|
# used by @set
|
||||||
|
from ast import literal_eval as _LITERAL_EVAL
|
||||||
|
except ImportError:
|
||||||
|
# literal_eval is not available before Python 2.6
|
||||||
|
_LITERAL_EVAL = None
|
||||||
|
|
||||||
# used by @find
|
# used by @find
|
||||||
CHAR_TYPECLASS = settings.BASE_CHARACTER_TYPECLASS
|
CHAR_TYPECLASS = settings.BASE_CHARACTER_TYPECLASS
|
||||||
|
|
||||||
|
|
@ -1176,11 +1183,19 @@ class CmdSetAttribute(ObjManipCommand):
|
||||||
def convert_from_string(self, strobj):
|
def convert_from_string(self, strobj):
|
||||||
"""
|
"""
|
||||||
Converts a single object in *string form* to its equivalent python
|
Converts a single object in *string form* to its equivalent python
|
||||||
type. Handles floats, ints, and limited nested lists and dicts
|
type.
|
||||||
|
|
||||||
|
Python earlier than 2.6:
|
||||||
|
Handles floats, ints, and limited nested lists and dicts
|
||||||
(can't handle lists in a dict, for example, this is mainly due to
|
(can't handle lists in a dict, for example, this is mainly due to
|
||||||
the complexity of parsing this rather than any technical difficulty -
|
the complexity of parsing this rather than any technical difficulty -
|
||||||
if there is a need for @set-ing such complex structures on the
|
if there is a need for @set-ing such complex structures on the
|
||||||
command line we might consider adding it).
|
command line we might consider adding it).
|
||||||
|
Python 2.6 and later:
|
||||||
|
Supports all Python structures through literal_eval as long as they
|
||||||
|
are valid Python syntax. If they are not (such as [test, test2], ie
|
||||||
|
withtout the quotes around the strings), the entire structure will
|
||||||
|
be converted to a string and a warning will be given.
|
||||||
|
|
||||||
We need to convert like this since all data being sent over the
|
We need to convert like this since all data being sent over the
|
||||||
telnet connection by the Player is text - but we will want to
|
telnet connection by the Player is text - but we will want to
|
||||||
|
|
@ -1191,7 +1206,8 @@ class CmdSetAttribute(ObjManipCommand):
|
||||||
|
|
||||||
def rec_convert(obj):
|
def rec_convert(obj):
|
||||||
"""
|
"""
|
||||||
Helper function of recursive conversion calls.
|
Helper function of recursive conversion calls. This is only
|
||||||
|
used for Python <=2.5. After that literal_eval is available.
|
||||||
"""
|
"""
|
||||||
# simple types
|
# simple types
|
||||||
try: return int(obj)
|
try: return int(obj)
|
||||||
|
|
@ -1211,18 +1227,20 @@ class CmdSetAttribute(ObjManipCommand):
|
||||||
for pair in obj[1:-1].split(',') if ":" in pair])
|
for pair in obj[1:-1].split(',') if ":" in pair])
|
||||||
# if nothing matches, return as-is
|
# if nothing matches, return as-is
|
||||||
return obj
|
return obj
|
||||||
if strobj.strip() and strobj.strip()[0] in ("'", '"', "(", "{ ", "["):
|
|
||||||
# this is a structure starting with a proper python structure,
|
if _LITERAL_EVAL:
|
||||||
# so treat it as such.
|
# Use literal_eval to parse python structure exactly.
|
||||||
try:
|
try:
|
||||||
# under python 2.6, literal_eval can do this for us.
|
return _LITERAL_EVAL(strobj)
|
||||||
from ast import literal_eval
|
except ValueError:
|
||||||
return literal_eval(strobj)
|
# treat as string
|
||||||
except ImportError:
|
string = "{RNote: Value was converted to string. If you don't want this, "
|
||||||
# fall back to old recursive solution (don't support nested lists/dicts)
|
string += "use proper Python syntax, like enclosing strings in quotes.{n"
|
||||||
return rec_convert(strobj.strip())
|
self.caller.msg(string)
|
||||||
|
return utils.to_str(strobj)
|
||||||
else:
|
else:
|
||||||
return strobj
|
# fall back to old recursive solution (does not support nested lists/dicts)
|
||||||
|
return rec_convert(strobj.strip())
|
||||||
|
|
||||||
def func(self):
|
def func(self):
|
||||||
"Implement the set attribute - a limited form of @py."
|
"Implement the set attribute - a limited form of @py."
|
||||||
|
|
@ -1272,10 +1290,9 @@ class CmdSetAttribute(ObjManipCommand):
|
||||||
string += "\nCreated attribute %s/%s = %s" % (obj.name, attr, value)
|
string += "\nCreated attribute %s/%s = %s" % (obj.name, attr, value)
|
||||||
except SyntaxError:
|
except SyntaxError:
|
||||||
# this means literal_eval tried to parse a faulty string
|
# this means literal_eval tried to parse a faulty string
|
||||||
string = "{RPython syntax error in your value. By assigning a value starting with"
|
string = "{RCritical Python syntax error in your value. Only primitive Python structures"
|
||||||
string += "\none of {r'{R, {r\"{R, {r[{R, {r({R or {r{{R we assume you are entering a proper Python"
|
string += "\nare allowed. You also need to use correct Python syntax. Remember especially"
|
||||||
string += "\nprimitive such as a list or a dictionary. You must then also use correct"
|
string += "\nto put quotes around all strings inside lists and dicts.{n"
|
||||||
string += "\nPython syntax. Remember especially to put quotes around all strings.{n"
|
|
||||||
# send feedback
|
# send feedback
|
||||||
caller.msg(string.strip('\n'))
|
caller.msg(string.strip('\n'))
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue