Cleaned up the batch processors (both cmd- and code processor) and homogenized their interfaces and APIs. Also test-ran the example codes and fixed some bugs.
This commit is contained in:
parent
e114c33d8a
commit
4d8fc05157
6 changed files with 373 additions and 316 deletions
|
|
@ -23,23 +23,46 @@ Example batch-code file: game/gamesrc/commands/examples/example_batch_code.py
|
||||||
"""
|
"""
|
||||||
from traceback import format_exc
|
from traceback import format_exc
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from src.utils import batchprocessors
|
from src.utils.batchprocessors import BATCHCMD, BATCHCODE
|
||||||
from game.gamesrc.commands.default.muxcommand import MuxCommand
|
from game.gamesrc.commands.default.muxcommand import MuxCommand
|
||||||
from src.commands.cmdset import CmdSet
|
from src.commands.cmdset import CmdSet
|
||||||
|
|
||||||
|
|
||||||
|
HEADER_WIDTH = 70
|
||||||
|
|
||||||
#global defines for storage
|
#global defines for storage
|
||||||
|
|
||||||
CWHITE = r"%cn%ch%cw"
|
|
||||||
CRED = r"%cn%ch%cr"
|
|
||||||
CGREEN = r"%cn%ci%cg"
|
|
||||||
CYELLOW = r"%cn%ch%cy"
|
|
||||||
CNORM = r"%cn"
|
|
||||||
|
|
||||||
|
|
||||||
#------------------------------------------------------------
|
#------------------------------------------------------------
|
||||||
# Helper functions
|
# Helper functions
|
||||||
#------------------------------------------------------------
|
#------------------------------------------------------------
|
||||||
|
|
||||||
|
def format_header(caller, entry):
|
||||||
|
"""
|
||||||
|
Formats a header
|
||||||
|
"""
|
||||||
|
width = HEADER_WIDTH - 10
|
||||||
|
entry = entry.strip()
|
||||||
|
header = entry[:min(width, min(len(entry), entry.find('\n')))]
|
||||||
|
if len(entry) > width:
|
||||||
|
header = "%s[...]" % header
|
||||||
|
ptr = caller.ndb.batch_stackptr + 1
|
||||||
|
stacklen = len(caller.ndb.batch_stack)
|
||||||
|
header = "{w%02i/%02i{G: %s{n" % (ptr, stacklen, header)
|
||||||
|
# add extra space to the side for padding.
|
||||||
|
header = "%s%s" % (header, " "*(width-len(header)))
|
||||||
|
header = header.replace('\n', '\\n')
|
||||||
|
|
||||||
|
return header
|
||||||
|
|
||||||
|
def format_code(entry):
|
||||||
|
"""
|
||||||
|
Formats the viewing of code and errors
|
||||||
|
"""
|
||||||
|
code = ""
|
||||||
|
for line in entry.split('\n'):
|
||||||
|
code += "\n{G>>>{n %s" % line
|
||||||
|
return code.strip()
|
||||||
|
|
||||||
def batch_cmd_exec(caller):
|
def batch_cmd_exec(caller):
|
||||||
"""
|
"""
|
||||||
Helper function for executing a single batch-command entry
|
Helper function for executing a single batch-command entry
|
||||||
|
|
@ -47,19 +70,14 @@ def batch_cmd_exec(caller):
|
||||||
ptr = caller.ndb.batch_stackptr
|
ptr = caller.ndb.batch_stackptr
|
||||||
stack = caller.ndb.batch_stack
|
stack = caller.ndb.batch_stack
|
||||||
command = stack[ptr]
|
command = stack[ptr]
|
||||||
cmdname = command[:command.find(" ")]
|
caller.msg(format_header(caller, command))
|
||||||
caller.msg("%s %02i/%02i: %s %s%s" % (CGREEN, ptr+1,
|
|
||||||
len(stack),
|
|
||||||
cmdname,
|
|
||||||
CGREEN, " "*(50-len(cmdname))))
|
|
||||||
try:
|
try:
|
||||||
caller.execute_cmd(command)
|
caller.execute_cmd(command)
|
||||||
except Exception:
|
except Exception:
|
||||||
caller.msg(format_exc())
|
caller.msg(format_code(format_exc()))
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
def batch_code_exec(caller):
|
def batch_code_exec(caller):
|
||||||
"""
|
"""
|
||||||
Helper function for executing a single batch-code entry
|
Helper function for executing a single batch-code entry
|
||||||
|
|
@ -67,20 +85,16 @@ def batch_code_exec(caller):
|
||||||
ptr = caller.ndb.batch_stackptr
|
ptr = caller.ndb.batch_stackptr
|
||||||
stack = caller.ndb.batch_stack
|
stack = caller.ndb.batch_stack
|
||||||
debug = caller.ndb.batch_debug
|
debug = caller.ndb.batch_debug
|
||||||
|
|
||||||
codedict = stack[ptr]
|
codedict = stack[ptr]
|
||||||
caller.msg("%s %02i/%02i: %s %s%s" % (CGREEN, ptr + 1,
|
|
||||||
len(stack),
|
caller.msg(format_header(caller, codedict['code']))
|
||||||
codedict["firstline"],
|
err = BATCHCODE.code_exec(codedict,
|
||||||
CGREEN, " "*(50-len(codedict["firstline"]))))
|
extra_environ={"caller":caller}, debug=debug)
|
||||||
err = batchprocessors.batch_code_exec(codedict,
|
|
||||||
extra_environ={"caller":caller}, debug=debug)
|
|
||||||
if err:
|
if err:
|
||||||
caller.msg(err)
|
caller.msg(format_code(err))
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
def step_pointer(caller, step=1):
|
def step_pointer(caller, step=1):
|
||||||
"""
|
"""
|
||||||
Step in stack, returning the item located.
|
Step in stack, returning the item located.
|
||||||
|
|
@ -93,13 +107,15 @@ def step_pointer(caller, step=1):
|
||||||
stack = caller.ndb.batch_stack
|
stack = caller.ndb.batch_stack
|
||||||
nstack = len(stack)
|
nstack = len(stack)
|
||||||
if ptr + step <= 0:
|
if ptr + step <= 0:
|
||||||
caller.msg("Beginning of batch file.")
|
caller.msg("{RBeginning of batch file.")
|
||||||
if ptr + step >= nstack:
|
if ptr + step >= nstack:
|
||||||
caller.msg("End of batch file.")
|
caller.msg("{REnd of batch file.")
|
||||||
caller.ndb.batch_stackptr = max(0, min(nstack-1, ptr + step))
|
caller.ndb.batch_stackptr = max(0, min(nstack-1, ptr + step))
|
||||||
|
|
||||||
def show_curr(caller, showall=False):
|
def show_curr(caller, showall=False):
|
||||||
"Show the current position in stack."
|
"""
|
||||||
|
Show the current position in stack
|
||||||
|
"""
|
||||||
stackptr = caller.ndb.batch_stackptr
|
stackptr = caller.ndb.batch_stackptr
|
||||||
stack = caller.ndb.batch_stack
|
stack = caller.ndb.batch_stack
|
||||||
|
|
||||||
|
|
@ -107,25 +123,39 @@ def show_curr(caller, showall=False):
|
||||||
caller.ndb.batch_stackptr = len(stack) - 1
|
caller.ndb.batch_stackptr = len(stack) - 1
|
||||||
show_curr(caller, showall)
|
show_curr(caller, showall)
|
||||||
return
|
return
|
||||||
|
|
||||||
entry = stack[stackptr]
|
entry = stack[stackptr]
|
||||||
|
|
||||||
if type(entry) == dict:
|
if type(entry) == dict:
|
||||||
# we first try the batch-code syntax
|
# this is a batch-code entry
|
||||||
firstline = entry['code'][:min(35, len(entry['code'])-1)]
|
string = format_header(caller, entry['code'])
|
||||||
codeall = entry['code']
|
codeall = entry['code'].strip()
|
||||||
else:
|
else:
|
||||||
# we try the batch-cmd syntax instead
|
# this is a batch-cmd entry
|
||||||
firstline = entry[:min(35, len(entry)-1)]
|
string = format_header(caller, entry)
|
||||||
codeall = entry
|
codeall = entry.strip()
|
||||||
string = "%s %02i/%02i: %s %s %s %s%s" % (CGREEN,
|
string += "{G(hh for help)"
|
||||||
stackptr+1, len(stack),
|
|
||||||
firstline, CGREEN,
|
|
||||||
"(hh for help)",
|
|
||||||
" "*(35-len(firstline.strip())),
|
|
||||||
CNORM)
|
|
||||||
if showall:
|
if showall:
|
||||||
string += "\n%s" % codeall
|
for line in codeall.split('\n'):
|
||||||
|
string += "\n{n>>> %s" % line
|
||||||
caller.msg(string)
|
caller.msg(string)
|
||||||
|
|
||||||
|
def purge_processor(caller):
|
||||||
|
"""
|
||||||
|
This purges all effects running
|
||||||
|
on the caller.
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
del caller.ndb.batch_stack
|
||||||
|
del caller.ndb.batch_stackptr
|
||||||
|
del caller.ndb.batch_pythonpath
|
||||||
|
del caller.ndb.batch_batchmode
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
# clear everything but the default cmdset.
|
||||||
|
caller.cmdset.delete(BatchSafeCmdSet)
|
||||||
|
caller.cmdset.clear()
|
||||||
|
caller.scripts.validate() # this will purge interactive mode
|
||||||
|
|
||||||
#------------------------------------------------------------
|
#------------------------------------------------------------
|
||||||
# main access commands
|
# main access commands
|
||||||
|
|
@ -164,7 +194,7 @@ class CmdBatchCommands(MuxCommand):
|
||||||
|
|
||||||
#parse indata file
|
#parse indata file
|
||||||
|
|
||||||
commands = batchprocessors.parse_batchcommand_file(python_path)
|
commands = BATCHCMD.parse_file(python_path)
|
||||||
if not commands:
|
if not commands:
|
||||||
string = "'%s' not found.\nYou have to supply the python path "
|
string = "'%s' not found.\nYou have to supply the python path "
|
||||||
string += "of the file relative to \nyour batch-file directory (%s)."
|
string += "of the file relative to \nyour batch-file directory (%s)."
|
||||||
|
|
@ -202,7 +232,8 @@ class CmdBatchCommands(MuxCommand):
|
||||||
del caller.ndb.batch_pythonpath
|
del caller.ndb.batch_pythonpath
|
||||||
del caller.ndb.batch_batchmode
|
del caller.ndb.batch_batchmode
|
||||||
string = " Batchfile '%s' applied." % python_path
|
string = " Batchfile '%s' applied." % python_path
|
||||||
caller.msg("%s%s%s" % (CGREEN, string, " "*(60-len(string))))
|
caller.msg("{G%s" % string)
|
||||||
|
purge_processor(caller)
|
||||||
|
|
||||||
class CmdBatchCode(MuxCommand):
|
class CmdBatchCode(MuxCommand):
|
||||||
"""
|
"""
|
||||||
|
|
@ -240,7 +271,7 @@ class CmdBatchCode(MuxCommand):
|
||||||
python_path = self.args
|
python_path = self.args
|
||||||
|
|
||||||
#parse indata file
|
#parse indata file
|
||||||
codes = batchprocessors.parse_batchcode_file(python_path)
|
codes = BATCHCODE.parse_file(python_path)
|
||||||
if not codes:
|
if not codes:
|
||||||
string = "'%s' not found.\nYou have to supply the python path "
|
string = "'%s' not found.\nYou have to supply the python path "
|
||||||
string += "of the file relative to \nyour batch-file directory (%s)."
|
string += "of the file relative to \nyour batch-file directory (%s)."
|
||||||
|
|
@ -283,7 +314,8 @@ class CmdBatchCode(MuxCommand):
|
||||||
del caller.ndb.batch_pythonpath
|
del caller.ndb.batch_pythonpath
|
||||||
del caller.ndb.batch_batchmode
|
del caller.ndb.batch_batchmode
|
||||||
string = " Batchfile '%s' applied." % python_path
|
string = " Batchfile '%s' applied." % python_path
|
||||||
caller.msg("%s%s%s" % (CGREEN, string, " "*(60-len(string))))
|
caller.msg("{G%s" % string)
|
||||||
|
purge_processor(caller)
|
||||||
|
|
||||||
#------------------------------------------------------------
|
#------------------------------------------------------------
|
||||||
# State-commands for the interactive batch processor modes
|
# State-commands for the interactive batch processor modes
|
||||||
|
|
@ -294,23 +326,17 @@ class CmdStateAbort(MuxCommand):
|
||||||
"""
|
"""
|
||||||
@abort
|
@abort
|
||||||
|
|
||||||
Exits back the default cmdset, regardless of what state
|
This is a safety feature. It force-ejects us out of the processor and to
|
||||||
we are currently in.
|
the default cmdset, regardless of what current cmdset the processor might
|
||||||
|
have put us in (e.g. when testing buggy scripts etc).
|
||||||
"""
|
"""
|
||||||
key = "@abort"
|
key = "@abort"
|
||||||
help_category = "BatchProcess"
|
help_category = "BatchProcess"
|
||||||
|
|
||||||
def func(self):
|
def func(self):
|
||||||
"Exit back to default."
|
"Exit back to default."
|
||||||
caller = self.caller
|
purge_processor(self.caller)
|
||||||
del caller.ndb.batch_stack
|
self.caller.msg("Exited processor and reset out active cmdset back to the default one.")
|
||||||
del caller.ndb.batch_stackptr
|
|
||||||
del caller.ndb.batch_pythonpath
|
|
||||||
del caller.ndb.batch_batchmode
|
|
||||||
# clear everything but the default cmdset.
|
|
||||||
caller.cmdset.delete(BatchSafeCmdSet)
|
|
||||||
caller.cmdset.clear()
|
|
||||||
caller.msg("Exit: Cleared back to default state.")
|
|
||||||
|
|
||||||
class CmdStateLL(MuxCommand):
|
class CmdStateLL(MuxCommand):
|
||||||
"""
|
"""
|
||||||
|
|
@ -358,10 +384,10 @@ class CmdStateRR(MuxCommand):
|
||||||
def func(self):
|
def func(self):
|
||||||
caller = self.caller
|
caller = self.caller
|
||||||
if caller.ndb.batch_batchmode == "batch_code":
|
if caller.ndb.batch_batchmode == "batch_code":
|
||||||
batchprocessors.read_batchcommand_file(caller.ndb.batch_pythonpath)
|
BATCHCODE.read_file(caller.ndb.batch_pythonpath)
|
||||||
else:
|
else:
|
||||||
batchprocessors.read_batchcode_file(caller.ndb.batch_pythonpath)
|
BATHCMD.read_file(caller.ndb.batch_pythonpath)
|
||||||
caller.msg("\nFile reloaded. Staying on same command.\n")
|
caller.msg(format_code("File reloaded. Staying on same command."))
|
||||||
show_curr(caller)
|
show_curr(caller)
|
||||||
|
|
||||||
class CmdStateRRR(MuxCommand):
|
class CmdStateRRR(MuxCommand):
|
||||||
|
|
@ -377,11 +403,11 @@ class CmdStateRRR(MuxCommand):
|
||||||
def func(self):
|
def func(self):
|
||||||
caller = self.caller
|
caller = self.caller
|
||||||
if caller.ndb.batch_batchmode == "batch_code":
|
if caller.ndb.batch_batchmode == "batch_code":
|
||||||
batchprocessors.read_batchcommand_file(caller.ndb.batch_pythonpath)
|
BATCHCODE.read_file(caller.ndb.batch_pythonpath)
|
||||||
else:
|
else:
|
||||||
batchprocessors.read_batchcode_file(caller.ndb.batch_pythonpath)
|
BATCHCMD.read_file(caller.ndb.batch_pythonpath)
|
||||||
caller.ndb.batch_stackptr = 0
|
caller.ndb.batch_stackptr = 0
|
||||||
caller.msg("\nFile reloaded. Restarting from top.\n")
|
caller.msg(format_code("File reloaded. Restarting from top."))
|
||||||
show_curr(caller)
|
show_curr(caller)
|
||||||
|
|
||||||
class CmdStateNN(MuxCommand):
|
class CmdStateNN(MuxCommand):
|
||||||
|
|
@ -545,7 +571,7 @@ class CmdStateCC(MuxCommand):
|
||||||
del caller.ndb.batch_stackptr
|
del caller.ndb.batch_stackptr
|
||||||
del caller.ndb.batch_pythonpath
|
del caller.ndb.batch_pythonpath
|
||||||
del caller.ndb.batch_batchmode
|
del caller.ndb.batch_batchmode
|
||||||
caller.msg("Finished processing batch file.")
|
caller.msg(format_code("Finished processing batch file."))
|
||||||
|
|
||||||
class CmdStateJJ(MuxCommand):
|
class CmdStateJJ(MuxCommand):
|
||||||
"""
|
"""
|
||||||
|
|
@ -562,7 +588,7 @@ class CmdStateJJ(MuxCommand):
|
||||||
if arg and arg.isdigit():
|
if arg and arg.isdigit():
|
||||||
number = int(self.args)-1
|
number = int(self.args)-1
|
||||||
else:
|
else:
|
||||||
caller.msg("You must give a number index.")
|
caller.msg(format_code("You must give a number index."))
|
||||||
return
|
return
|
||||||
ptr = caller.ndb.batch_stackptr
|
ptr = caller.ndb.batch_stackptr
|
||||||
step = number - ptr
|
step = number - ptr
|
||||||
|
|
@ -584,7 +610,7 @@ class CmdStateJL(MuxCommand):
|
||||||
if arg and arg.isdigit():
|
if arg and arg.isdigit():
|
||||||
number = int(self.args)-1
|
number = int(self.args)-1
|
||||||
else:
|
else:
|
||||||
caller.msg("You must give a number index.")
|
caller.msg(format_code("You must give a number index."))
|
||||||
return
|
return
|
||||||
ptr = caller.ndb.batch_stackptr
|
ptr = caller.ndb.batch_stackptr
|
||||||
step = number - ptr
|
step = number - ptr
|
||||||
|
|
@ -601,26 +627,19 @@ class CmdStateQQ(MuxCommand):
|
||||||
help_category = "BatchProcess"
|
help_category = "BatchProcess"
|
||||||
|
|
||||||
def func(self):
|
def func(self):
|
||||||
caller = self.caller
|
purge_processor(self.caller)
|
||||||
del caller.ndb.batch_stack
|
self.caller.msg("Aborted interactive batch mode.")
|
||||||
del caller.ndb.batch_stackptr
|
|
||||||
del caller.ndb.batch_pythonpath
|
|
||||||
del caller.ndb.batch_batchmode
|
|
||||||
caller.cmdset.delete(BatchSafeCmdSet)
|
|
||||||
caller.cmdset.delete(BatchInteractiveCmdSet)
|
|
||||||
caller.scripts.validate() # this will clear interactive mode.
|
|
||||||
caller.msg("Aborted interactive batch mode.")
|
|
||||||
|
|
||||||
class CmdStateHH(MuxCommand):
|
class CmdStateHH(MuxCommand):
|
||||||
"Help command"
|
"Help command"
|
||||||
|
|
||||||
key = "help"
|
key = "hh"
|
||||||
aliases = "hh"
|
|
||||||
help_category = "BatchProcess"
|
help_category = "BatchProcess"
|
||||||
|
|
||||||
def func(self):
|
def func(self):
|
||||||
string = """
|
string = """
|
||||||
Interactive batch processing commands:
|
Interactive batch processing commands:
|
||||||
|
|
||||||
nn [steps] - next command (no processing)
|
nn [steps] - next command (no processing)
|
||||||
nl [steps] - next & look
|
nl [steps] - next & look
|
||||||
bb [steps] - back to previous command (no processing)
|
bb [steps] - back to previous command (no processing)
|
||||||
|
|
@ -637,6 +656,11 @@ class CmdStateHH(MuxCommand):
|
||||||
|
|
||||||
cc - continue processing to end, then quit.
|
cc - continue processing to end, then quit.
|
||||||
qq - quit (abort all remaining commands)
|
qq - quit (abort all remaining commands)
|
||||||
|
|
||||||
|
@abort - this is a safety command that always is available
|
||||||
|
regardless of what cmdsets gets added to us during
|
||||||
|
batch-command processing. It immediately shuts down
|
||||||
|
the processor and returns us to the default cmdset.
|
||||||
"""
|
"""
|
||||||
self.caller.msg(string)
|
self.caller.msg(string)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -603,13 +603,13 @@ class CmdCreate(ObjManipCommand):
|
||||||
obj = create.create_object(typeclass, name, caller,
|
obj = create.create_object(typeclass, name, caller,
|
||||||
home=caller, aliases=aliases)
|
home=caller, aliases=aliases)
|
||||||
if not obj:
|
if not obj:
|
||||||
string += "\nError when creating object."
|
string = "Error when creating object."
|
||||||
continue
|
continue
|
||||||
if aliases:
|
if aliases:
|
||||||
string += "\nYou create a new %s: %s (aliases: %s)."
|
string = "You create a new %s: %s (aliases: %s)."
|
||||||
string = string % (obj.typeclass, obj.name, ", ".join(aliases))
|
string = string % (obj.typeclass, obj.name, ", ".join(aliases))
|
||||||
else:
|
else:
|
||||||
string += "\nYou create a new %s: %s."
|
string = "You create a new %s: %s."
|
||||||
string = string % (obj.typeclass, obj.name)
|
string = string % (obj.typeclass, obj.name)
|
||||||
if 'drop' in self.switches:
|
if 'drop' in self.switches:
|
||||||
if caller.location:
|
if caller.location:
|
||||||
|
|
@ -1189,21 +1189,22 @@ class CmdDestroy(MuxCommand):
|
||||||
for objname in self.lhslist:
|
for objname in self.lhslist:
|
||||||
obj = caller.search(objname)
|
obj = caller.search(objname)
|
||||||
if not obj:
|
if not obj:
|
||||||
continue
|
continue
|
||||||
objname = obj.name
|
objname = obj.name
|
||||||
if obj.player and not 'override' in self.switches:
|
if obj.player and not 'override' in self.switches:
|
||||||
string += "\n\rObject %s is a player object. Use /override to delete anyway." % objname
|
string = "Object %s is a player object. Use /override to delete anyway." % objname
|
||||||
continue
|
continue
|
||||||
if not has_perm(caller, obj, 'create'):
|
if not has_perm(caller, obj, 'create'):
|
||||||
string += "\n\rYou don't have permission to delete %s." % objname
|
string = "You don't have permission to delete %s." % objname
|
||||||
continue
|
continue
|
||||||
# do the deletion
|
# do the deletion
|
||||||
okay = obj.delete()
|
okay = obj.delete()
|
||||||
if not okay:
|
if not okay:
|
||||||
string += "\n\rERROR: %s NOT deleted, probably because at_obj_delete() returned False." % objname
|
string = "ERROR: %s NOT deleted, probably because at_obj_delete() returned False." % objname
|
||||||
else:
|
else:
|
||||||
string += "\n\r%s was deleted." % objname
|
string = "%s was deleted." % objname
|
||||||
caller.msg(string.strip('\n'))
|
if string:
|
||||||
|
caller.msg(string.strip())
|
||||||
|
|
||||||
|
|
||||||
#NOT VALID IN NEW SYSTEM!
|
#NOT VALID IN NEW SYSTEM!
|
||||||
|
|
|
||||||
|
|
@ -17,37 +17,43 @@
|
||||||
# automatically be made available for each block. Observe
|
# automatically be made available for each block. Observe
|
||||||
# that changes to these variables made in one block is not
|
# that changes to these variables made in one block is not
|
||||||
# preserved between blocks!)
|
# preserved between blocks!)
|
||||||
# #CODE [objname, objname, ...] - This designates a code block that will be executed like a
|
# #CODE (infotext) [objname, objname, ...] - This designates a code block that will be executed like a
|
||||||
# stand-alone piece of code together with any #HEADER
|
# stand-alone piece of code together with any #HEADER
|
||||||
# defined. <objname>s mark the (variable-)names of objects created in the code,
|
# defined.
|
||||||
|
# infotext is a describing text about what goes in in this block. It will be
|
||||||
|
# shown by the batchprocessing command.
|
||||||
|
# <objname>s mark the (variable-)names of objects created in the code,
|
||||||
# and which may be auto-deleted by the processor if desired (such as when
|
# and which may be auto-deleted by the processor if desired (such as when
|
||||||
# debugging the script). E.g., if the code contains the command
|
# debugging the script). E.g., if the code contains the command
|
||||||
# myobj = create.create_object(...), you could put 'myobj' in the #CODE header
|
# myobj = create.create_object(...), you could put 'myobj' in the #CODE header
|
||||||
# regardless of what the created object is actually called in-game.
|
# regardless of what the created object is actually called in-game.
|
||||||
|
|
||||||
# The following variables are automatically made available for the script:
|
# The following variable is automatically made available for the script:
|
||||||
|
|
||||||
# caller - the object executing the script
|
# caller - the object executing the script
|
||||||
#
|
#
|
||||||
#
|
|
||||||
|
|
||||||
#HEADER
|
#HEADER
|
||||||
|
|
||||||
# everything in this block will be imported to all CODE blocks when
|
# everything in this block will be appended to the beginning of
|
||||||
# they are executed.
|
# all other #CODE blocks when they are executed.
|
||||||
|
|
||||||
from src.utils import create, search
|
from src.utils import create, search
|
||||||
from game.gamesrc.typeclasses.examples import red_button
|
from game.gamesrc.objects.examples import red_button
|
||||||
from game.gamesrc.typeclasses import basetypes
|
from game.gamesrc.objects import baseobjects
|
||||||
|
|
||||||
#CODE
|
limbo = search.objects(caller, 'Limbo', global_search=True)[0]
|
||||||
|
|
||||||
|
|
||||||
|
#CODE (create red button)
|
||||||
|
|
||||||
# This is the first code block. Within each block, python
|
# This is the first code block. Within each block, python
|
||||||
# code works as normal.
|
# code works as normal. Note how we make use if imports and
|
||||||
|
# 'limbo' defined in the #HEADER block. This block's header
|
||||||
|
# offers no information about red_button variable, so it
|
||||||
|
# won't be able to be deleted in debug mode.
|
||||||
|
|
||||||
# get the limbo room.
|
|
||||||
limbo = search.objects(caller, 'Limbo', global_search=True)[0]
|
|
||||||
caller.msg(limbo)
|
|
||||||
# create a red button in limbo
|
# create a red button in limbo
|
||||||
red_button = create.create_object(red_button.RedButton, key="Red button",
|
red_button = create.create_object(red_button.RedButton, key="Red button",
|
||||||
location=limbo, aliases=["button"])
|
location=limbo, aliases=["button"])
|
||||||
|
|
@ -55,17 +61,22 @@ red_button = create.create_object(red_button.RedButton, key="Red button",
|
||||||
# we take a look at what we created
|
# we take a look at what we created
|
||||||
caller.msg("A %s was created." % red_button.key)
|
caller.msg("A %s was created." % red_button.key)
|
||||||
|
|
||||||
#CODE table, chair
|
|
||||||
|
#CODE (create table and chair) table, chair
|
||||||
|
|
||||||
# this code block has 'table' and 'chair' set as deletable
|
# this code block has 'table' and 'chair' set as deletable
|
||||||
# objects. This means that when the batchcode processor runs in
|
# objects. This means that when the batchcode processor runs in
|
||||||
# testing mode, objects created in these variables will be deleted
|
# testing mode, objects created in these variables will be deleted
|
||||||
# again (so as to avoid duplicate objects when testing the script).
|
# again (so as to avoid duplicate objects when testing the script many
|
||||||
|
# times).
|
||||||
|
|
||||||
limbo = search.objects(caller, 'Limbo', global_search=True)[0]
|
|
||||||
caller.msg(limbo.key)
|
caller.msg(limbo.key)
|
||||||
table = create.create_object(basetypes.Object, key="Table", location=limbo)
|
|
||||||
chair = create.create_object(basetypes.Object, key="Chair", location=limbo)
|
# the python variables we assign to must match the ones given in the
|
||||||
|
# header for the system to be able to delete them afterwards during a
|
||||||
|
# debugging run.
|
||||||
|
table = create.create_object(baseobjects.Object, key="Table", location=limbo)
|
||||||
|
chair = create.create_object(baseobjects.Object, key="Chair", location=limbo)
|
||||||
|
|
||||||
string = "A %s and %s were created. If debug was active, they were deleted again."
|
string = "A %s and %s were created. If debug was active, they were deleted again."
|
||||||
caller.msg(string % (table, chair))
|
caller.msg(string % (table, chair))
|
||||||
|
|
|
||||||
|
|
@ -504,6 +504,7 @@ class ObjectDB(TypedObject):
|
||||||
"""
|
"""
|
||||||
# This is an important function that must always work.
|
# This is an important function that must always work.
|
||||||
# we use a different __getattribute__ to avoid recursive loops.
|
# we use a different __getattribute__ to avoid recursive loops.
|
||||||
|
|
||||||
if from_obj:
|
if from_obj:
|
||||||
try:
|
try:
|
||||||
from_obj.at_msg_send(message, self)
|
from_obj.at_msg_send(message, self)
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ def handle_search_errors(emit_to_obj, ostring, results, global_search=False):
|
||||||
dbrefs instead of only numbers)
|
dbrefs instead of only numbers)
|
||||||
"""
|
"""
|
||||||
if not results:
|
if not results:
|
||||||
emit_to_obj.emit_to("Could not find '%s'." % ostring)
|
emit_to_obj.msg("Could not find '%s'." % ostring)
|
||||||
return None
|
return None
|
||||||
if len(results) > 1:
|
if len(results) > 1:
|
||||||
# we have more than one match. We will display a
|
# we have more than one match. We will display a
|
||||||
|
|
@ -47,8 +47,8 @@ def handle_search_errors(emit_to_obj, ostring, results, global_search=False):
|
||||||
if show_dbref:
|
if show_dbref:
|
||||||
dbreftext = "(#%i)" % result.id
|
dbreftext = "(#%i)" % result.id
|
||||||
string += "\n %i-%s%s%s" % (num+1, result.name,
|
string += "\n %i-%s%s%s" % (num+1, result.name,
|
||||||
dbreftext, invtext)
|
dbreftext, invtext)
|
||||||
emit_to_obj.emit_to(string)
|
emit_to_obj.msg(string.strip())
|
||||||
return None
|
return None
|
||||||
else:
|
else:
|
||||||
return results[0]
|
return results[0]
|
||||||
|
|
@ -101,4 +101,3 @@ def object_multimatch_parser(ostring):
|
||||||
return (None, ostring)
|
return (None, ostring)
|
||||||
except IndexError:
|
except IndexError:
|
||||||
return (None, ostring)
|
return (None, ostring)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -147,13 +147,6 @@ from game import settings as settings_module
|
||||||
from django.core.management import setup_environ
|
from django.core.management import setup_environ
|
||||||
from traceback import format_exc
|
from traceback import format_exc
|
||||||
|
|
||||||
# colours
|
|
||||||
|
|
||||||
WHITE = r"%cn%ch%cw"
|
|
||||||
RED = r"%cn%ch%cr"
|
|
||||||
GREEN = r"%cn%ci%cg"
|
|
||||||
YELLOW = r"%cn%ch%cy"
|
|
||||||
NORM = r"%cn"
|
|
||||||
|
|
||||||
#------------------------------------------------------------
|
#------------------------------------------------------------
|
||||||
#
|
#
|
||||||
|
|
@ -161,90 +154,96 @@ NORM = r"%cn"
|
||||||
#
|
#
|
||||||
#------------------------------------------------------------
|
#------------------------------------------------------------
|
||||||
|
|
||||||
def read_batchcommand_file(pythonpath):
|
class BatchCommandProcessor(object):
|
||||||
"""
|
"""
|
||||||
This reads the contents of a batch-command file.
|
This class implements a batch-command processor.
|
||||||
Filename is considered to be the name of the batch file
|
|
||||||
relative the directory specified in settings.py
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if pythonpath and not (pythonpath.startswith('src.') or
|
def read_file(self, pythonpath):
|
||||||
pythonpath.startswith('game.')):
|
|
||||||
pythonpath = "%s.%s" % (settings.BASE_BATCHPROCESS_PATH,
|
|
||||||
pythonpath)
|
|
||||||
abspath = utils.pypath_to_realpath(pythonpath, 'ev')
|
|
||||||
try:
|
|
||||||
fobj = open(abspath)
|
|
||||||
except IOError:
|
|
||||||
logger.log_errmsg("Could not open path '%s'." % pythonpath)
|
|
||||||
return None
|
|
||||||
lines = fobj.readlines()
|
|
||||||
fobj.close()
|
|
||||||
return lines
|
|
||||||
|
|
||||||
def parse_batchcommand_file(pythonpath):
|
|
||||||
"""
|
|
||||||
This parses the lines of a batchfile according to the following
|
|
||||||
rules:
|
|
||||||
1) # at the beginning of a line marks the end of the command before it.
|
|
||||||
It is also a comment and any number of # can exist on subsequent
|
|
||||||
lines (but not inside comments).
|
|
||||||
2) Commands are placed alone at the beginning of a line and their
|
|
||||||
arguments are considered to be everything following (on any
|
|
||||||
number of lines) until the next comment line beginning with #.
|
|
||||||
3) Newlines are ignored in command definitions
|
|
||||||
4) A completely empty line in a command line definition is condered
|
|
||||||
a newline (so two empty lines is a paragraph).
|
|
||||||
5) Excess spaces and indents inside arguments are stripped.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
#helper function
|
|
||||||
def identify_line(line):
|
|
||||||
"""
|
|
||||||
Identifies the line type (comment, commanddef or empty)
|
|
||||||
"""
|
"""
|
||||||
|
This reads the contents of a batch-command file.
|
||||||
|
Filename is considered to be the name of the batch file
|
||||||
|
relative the directory specified in settings.py
|
||||||
|
"""
|
||||||
|
|
||||||
|
if pythonpath and not (pythonpath.startswith('src.') or
|
||||||
|
pythonpath.startswith('game.')):
|
||||||
|
pythonpath = "%s.%s" % (settings.BASE_BATCHPROCESS_PATH,
|
||||||
|
pythonpath)
|
||||||
|
abspath = utils.pypath_to_realpath(pythonpath, 'ev')
|
||||||
try:
|
try:
|
||||||
if line.strip()[0] == '#':
|
fobj = open(abspath)
|
||||||
return "comment"
|
except IOError:
|
||||||
else:
|
logger.log_errmsg("Could not open path '%s'." % abspath)
|
||||||
return "commanddef"
|
return None
|
||||||
except IndexError:
|
lines = fobj.readlines()
|
||||||
return "empty"
|
fobj.close()
|
||||||
|
return lines
|
||||||
|
|
||||||
#read the indata, if possible.
|
def parse_file(self, pythonpath):
|
||||||
lines = read_batchcommand_file(pythonpath)
|
"""
|
||||||
if not lines:
|
This parses the lines of a batchfile according to the following
|
||||||
return None
|
rules:
|
||||||
|
1) # at the beginning of a line marks the end of the command before it.
|
||||||
|
It is also a comment and any number of # can exist on subsequent
|
||||||
|
lines (but not inside comments).
|
||||||
|
2) Commands are placed alone at the beginning of a line and their
|
||||||
|
arguments are considered to be everything following (on any
|
||||||
|
number of lines) until the next comment line beginning with #.
|
||||||
|
3) Newlines are ignored in command definitions
|
||||||
|
4) A completely empty line in a command line definition is condered
|
||||||
|
a newline (so two empty lines is a paragraph).
|
||||||
|
5) Excess spaces and indents inside arguments are stripped.
|
||||||
|
|
||||||
commands = []
|
"""
|
||||||
curr_cmd = ""
|
|
||||||
|
|
||||||
#purge all superfluous whitespace and newlines from lines
|
#helper function
|
||||||
reg1 = re.compile(r"\s+")
|
def identify_line(line):
|
||||||
lines = [reg1.sub(" ", l) for l in lines]
|
"""
|
||||||
|
Identifies the line type (comment, commanddef or empty)
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
if line.strip()[0] == '#':
|
||||||
|
return "comment"
|
||||||
|
else:
|
||||||
|
return "commanddef"
|
||||||
|
except IndexError:
|
||||||
|
return "empty"
|
||||||
|
|
||||||
#parse all command definitions into a list.
|
#read the indata, if possible.
|
||||||
for line in lines:
|
lines = self.read_file(pythonpath)
|
||||||
typ = identify_line(line)
|
if not lines:
|
||||||
if typ == "commanddef":
|
return None
|
||||||
curr_cmd += line
|
|
||||||
elif typ == "empty" and curr_cmd:
|
|
||||||
curr_cmd += "\r\n"
|
|
||||||
else: #comment
|
|
||||||
if curr_cmd:
|
|
||||||
commands.append(curr_cmd.strip())
|
|
||||||
curr_cmd = ""
|
|
||||||
if curr_cmd:
|
|
||||||
commands.append(curr_cmd.strip())
|
|
||||||
|
|
||||||
#second round to clean up now merged line edges etc.
|
commands = []
|
||||||
reg2 = re.compile(r"[ \t\f\v]+")
|
curr_cmd = ""
|
||||||
commands = [reg2.sub(" ", c) for c in commands]
|
|
||||||
|
|
||||||
#remove eventual newline at the end of commands
|
#purge all superfluous whitespace and newlines from lines
|
||||||
commands = [c.strip('\r\n') for c in commands]
|
reg1 = re.compile(r"\s+")
|
||||||
return commands
|
lines = [reg1.sub(" ", l) for l in lines]
|
||||||
|
|
||||||
|
#parse all command definitions into a list.
|
||||||
|
for line in lines:
|
||||||
|
typ = identify_line(line)
|
||||||
|
if typ == "commanddef":
|
||||||
|
curr_cmd += line
|
||||||
|
elif typ == "empty" and curr_cmd:
|
||||||
|
curr_cmd += "\r\n"
|
||||||
|
else: #comment
|
||||||
|
if curr_cmd:
|
||||||
|
commands.append(curr_cmd.strip())
|
||||||
|
curr_cmd = ""
|
||||||
|
if curr_cmd:
|
||||||
|
commands.append(curr_cmd.strip())
|
||||||
|
|
||||||
|
#second round to clean up now merged line edges etc.
|
||||||
|
reg2 = re.compile(r"[ \t\f\v]+")
|
||||||
|
commands = [reg2.sub(" ", c) for c in commands]
|
||||||
|
|
||||||
|
#remove eventual newline at the end of commands
|
||||||
|
commands = [c.strip('\r\n') for c in commands]
|
||||||
|
return commands
|
||||||
|
|
||||||
#------------------------------------------------------------
|
#------------------------------------------------------------
|
||||||
#
|
#
|
||||||
|
|
@ -252,148 +251,170 @@ def parse_batchcommand_file(pythonpath):
|
||||||
#
|
#
|
||||||
#------------------------------------------------------------
|
#------------------------------------------------------------
|
||||||
|
|
||||||
def read_batchcode_file(pythonpath):
|
|
||||||
|
class BatchCodeProcessor(object):
|
||||||
"""
|
"""
|
||||||
This reads the contents of batchfile.
|
This implements a batch-code processor
|
||||||
Filename is considered to be the name of the batch file
|
|
||||||
relative the directory specified in settings.py
|
|
||||||
"""
|
|
||||||
|
|
||||||
if pythonpath and not (pythonpath.startswith('src.') or
|
|
||||||
pythonpath.startswith('game.')):
|
|
||||||
pythonpath = "%s.%s" % (settings.BASE_BATCHPROCESS_PATH,
|
|
||||||
pythonpath)
|
|
||||||
abspath = utils.pypath_to_realpath(pythonpath)
|
|
||||||
try:
|
|
||||||
fobj = open(abspath)
|
|
||||||
except IOError:
|
|
||||||
logger.log_errmsg("Could not open path '%s'." % pythonpath)
|
|
||||||
return None
|
|
||||||
lines = fobj.readlines()
|
|
||||||
fobj.close()
|
|
||||||
return lines
|
|
||||||
|
|
||||||
|
|
||||||
def parse_batchcode_file(pythonpath):
|
|
||||||
"""
|
|
||||||
This parses the lines of a batchfile according to the following
|
|
||||||
rules:
|
|
||||||
|
|
||||||
1) Lines starting with #HEADER starts a header block (ends other blocks)
|
|
||||||
2) Lines starting with #CODE begins a code block (ends other blocks)
|
|
||||||
3) All lines outside blocks are stripped.
|
|
||||||
4) All excess whitespace beginning/ending a block is stripped.
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# helper function
|
def read_file(self, pythonpath):
|
||||||
def parse_line(line):
|
|
||||||
"""
|
"""
|
||||||
Identifies the line type: block command, comment, empty or normal code.
|
This reads the contents of batchfile.
|
||||||
|
Filename is considered to be the name of the batch file
|
||||||
|
relative the directory specified in settings.py
|
||||||
"""
|
"""
|
||||||
line = line.strip()
|
|
||||||
|
|
||||||
if line.startswith("#HEADER"):
|
|
||||||
return "header", ""
|
|
||||||
elif line.startswith("#CODE"):
|
|
||||||
# parse code command
|
|
||||||
line = line.lstrip("#CODE").strip()
|
|
||||||
objs = []
|
|
||||||
if line:
|
|
||||||
objs = [obj.strip() for obj in line.split(',')]
|
|
||||||
return "code", objs
|
|
||||||
elif line.startswith("#"):
|
|
||||||
return "comment", ""
|
|
||||||
else:
|
|
||||||
#normal line - return it with a line break.
|
|
||||||
return None, "\n%s" % line
|
|
||||||
|
|
||||||
# read indata
|
if pythonpath and not (pythonpath.startswith('src.') or
|
||||||
|
pythonpath.startswith('game.')):
|
||||||
|
pythonpath = "%s.%s" % (settings.BASE_BATCHPROCESS_PATH,
|
||||||
|
pythonpath)
|
||||||
|
abspath = utils.pypath_to_realpath(pythonpath, 'py')
|
||||||
|
try:
|
||||||
|
fobj = open(abspath)
|
||||||
|
except IOError:
|
||||||
|
logger.log_errmsg("Could not open path '%s'." % abspath)
|
||||||
|
return None
|
||||||
|
lines = fobj.readlines()
|
||||||
|
fobj.close()
|
||||||
|
return lines
|
||||||
|
|
||||||
lines = read_batchcode_file(pythonpath)
|
|
||||||
if not lines:
|
|
||||||
return None
|
|
||||||
|
|
||||||
# parse file into blocks
|
|
||||||
|
|
||||||
header = ""
|
|
||||||
codes = []
|
|
||||||
|
|
||||||
in_header = False
|
|
||||||
in_code = False
|
|
||||||
|
|
||||||
for line in lines:
|
def parse_file(self, pythonpath):
|
||||||
# parse line
|
"""
|
||||||
mode, line = parse_line(line)
|
This parses the lines of a batchfile according to the following
|
||||||
# try:
|
rules:
|
||||||
# print "::", in_header, in_code, mode, line.strip()
|
|
||||||
# except:
|
1) Lines starting with #HEADER starts a header block (ends other blocks)
|
||||||
# print "::", in_header, in_code, mode, line
|
2) Lines starting with #CODE begins a code block (ends other blocks)
|
||||||
if mode == 'comment':
|
3) #CODE headers may be of the following form: #CODE (info) objname, objname2, ...
|
||||||
continue
|
3) All lines outside blocks are stripped.
|
||||||
elif mode == 'header':
|
4) All excess whitespace beginning/ending a block is stripped.
|
||||||
in_header = True
|
|
||||||
in_code = False
|
"""
|
||||||
elif mode == 'code':
|
|
||||||
in_header = False
|
# helper function
|
||||||
in_code = True
|
def parse_line(line):
|
||||||
# the line is a list of object variable names
|
"""
|
||||||
# (or an empty list) at this point.
|
Identifies the line type: block command, comment, empty or normal code.
|
||||||
codedict = {'objs':line,
|
|
||||||
'code':""}
|
"""
|
||||||
codes.append(codedict)
|
line = line.strip()
|
||||||
else:
|
|
||||||
# another type of line (empty or code)
|
if line.startswith("#HEADER"):
|
||||||
if in_header:
|
return ("header", "", "")
|
||||||
header += line
|
elif line.startswith("#CODE"):
|
||||||
elif in_code:
|
# parse code command
|
||||||
codes[-1]['code'] += line
|
line = line.lstrip("#CODE").strip()
|
||||||
|
objs = []
|
||||||
|
info = ""
|
||||||
|
if line and '(' in line and ')' in line:
|
||||||
|
# a code description
|
||||||
|
lp = line.find('(')
|
||||||
|
rp = line.find(')')
|
||||||
|
info = line[lp:rp+1]
|
||||||
|
line = line[rp+1:]
|
||||||
|
if line:
|
||||||
|
objs = [obj.strip() for obj in line.split(',')]
|
||||||
|
return ("codeheader", info, objs)
|
||||||
|
elif line.startswith('#'):
|
||||||
|
return ('comment', "", "\n%s" % line)
|
||||||
else:
|
else:
|
||||||
# not in a block (e.g. first in file). Ignore.
|
#normal line - return it with a line break.
|
||||||
|
return ('line', "", "\n%s" % line)
|
||||||
|
|
||||||
|
# read indata
|
||||||
|
|
||||||
|
lines = self.read_file(pythonpath)
|
||||||
|
if not lines:
|
||||||
|
return None
|
||||||
|
|
||||||
|
# parse file into blocks
|
||||||
|
|
||||||
|
header = ""
|
||||||
|
codes = []
|
||||||
|
|
||||||
|
in_header = False
|
||||||
|
in_code = False
|
||||||
|
|
||||||
|
for line in lines:
|
||||||
|
# parse line
|
||||||
|
mode, info, line = parse_line(line)
|
||||||
|
# try:
|
||||||
|
# print "::", in_header, in_code, mode, line.strip()
|
||||||
|
# except:
|
||||||
|
# print "::", in_header, in_code, mode, line
|
||||||
|
if mode == 'header':
|
||||||
|
in_header = True
|
||||||
|
in_code = False
|
||||||
|
elif mode == 'codeheader':
|
||||||
|
in_header = False
|
||||||
|
in_code = True
|
||||||
|
# the line is a list of object variable names
|
||||||
|
# (or an empty list) at this point.
|
||||||
|
codedict = {'objs':line,
|
||||||
|
'info':info,
|
||||||
|
'code':""}
|
||||||
|
codes.append(codedict)
|
||||||
|
elif mode == 'comment' and in_header:
|
||||||
continue
|
continue
|
||||||
# last, we merge the headers with all codes.
|
else:
|
||||||
for codedict in codes:
|
# another type of line (empty, comment or code)
|
||||||
codedict["firstline"] = codedict["code"].strip()[:min(35, len(codedict['code'].strip())-1)]
|
if line and in_header:
|
||||||
codedict["code"] = "%s\n%s" % (header, codedict["code"])
|
header += line
|
||||||
return codes
|
elif line and in_code:
|
||||||
|
codes[-1]['code'] += line
|
||||||
|
else:
|
||||||
|
# not in a block (e.g. first in file). Ignore.
|
||||||
|
continue
|
||||||
|
|
||||||
def batch_code_exec(codedict, extra_environ=None, debug=False):
|
# last, we merge the headers with all codes.
|
||||||
"""
|
for codedict in codes:
|
||||||
Execute a single code block, including imports and appending global vars
|
codedict["code"] = "#CODE %s %s\n%s\n\n%s" % (codedict['info'],
|
||||||
|
", ".join(codedict["objs"]),
|
||||||
|
header.strip(),
|
||||||
|
codedict["code"].strip())
|
||||||
|
return codes
|
||||||
|
|
||||||
extra_environ - dict with environment variables
|
def code_exec(self, codedict, extra_environ=None, debug=False):
|
||||||
"""
|
"""
|
||||||
|
Execute a single code block, including imports and appending global vars
|
||||||
|
|
||||||
# define the execution environment
|
extra_environ - dict with environment variables
|
||||||
environ = "setup_environ(settings_module)"
|
"""
|
||||||
environdict = {"setup_environ":setup_environ,
|
|
||||||
"settings_module":settings_module}
|
|
||||||
if extra_environ:
|
|
||||||
for key, value in extra_environ.items():
|
|
||||||
environdict[key] = value
|
|
||||||
|
|
||||||
# merge all into one block
|
# define the execution environment
|
||||||
code = "%s\n%s" % (environ, codedict['code'])
|
environ = "setup_environ(settings_module)"
|
||||||
if debug:
|
environdict = {"setup_environ":setup_environ,
|
||||||
# try to delete marked objects
|
"settings_module":settings_module}
|
||||||
for obj in codedict['objs']:
|
if extra_environ:
|
||||||
code += "\ntry: %s.delete()\nexcept: pass" % obj
|
for key, value in extra_environ.items():
|
||||||
|
environdict[key] = value
|
||||||
# execute the block
|
|
||||||
try:
|
# merge all into one block
|
||||||
exec(code, environdict)
|
code = "%s\n%s" % (environ, codedict['code'])
|
||||||
except Exception:
|
|
||||||
errlist = format_exc().split('\n')
|
|
||||||
if len(errlist) > 4:
|
|
||||||
errlist = errlist[4:]
|
|
||||||
err = "\n".join("<<< %s" % line for line in errlist if line)
|
|
||||||
if debug:
|
if debug:
|
||||||
# try to delete objects again.
|
# try to delete marked objects
|
||||||
try:
|
for obj in codedict['objs']:
|
||||||
for obj in codedict['objs']:
|
code += "\ntry: %s.delete()\nexcept: pass" % obj
|
||||||
eval("%s.delete()" % obj, environdict)
|
|
||||||
except Exception:
|
# execute the block
|
||||||
pass
|
try:
|
||||||
return err
|
exec(code, environdict)
|
||||||
return None
|
except Exception:
|
||||||
|
errlist = format_exc().split('\n')
|
||||||
|
if len(errlist) > 4:
|
||||||
|
errlist = errlist[4:]
|
||||||
|
err = "\n".join(" %s" % line for line in errlist if line)
|
||||||
|
if debug:
|
||||||
|
# try to delete objects again.
|
||||||
|
try:
|
||||||
|
for obj in codedict['objs']:
|
||||||
|
eval("%s.delete()" % obj, environdict)
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
return err
|
||||||
|
return None
|
||||||
|
|
||||||
|
BATCHCMD = BatchCommandProcessor()
|
||||||
|
BATCHCODE = BatchCodeProcessor()
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue