Refactor yield-mechanism to be present on top of the module, removing dependence on utils.delay and optimizing some imports.
This commit is contained in:
parent
dea72caf3f
commit
5fa084c976
1 changed files with 73 additions and 52 deletions
|
|
@ -39,6 +39,8 @@ from traceback import format_exc
|
||||||
from itertools import chain
|
from itertools import chain
|
||||||
from copy import copy
|
from copy import copy
|
||||||
import types
|
import types
|
||||||
|
from twisted.internet import reactor
|
||||||
|
from twisted.internet.task import deferLater
|
||||||
from twisted.internet.defer import inlineCallbacks, returnValue
|
from twisted.internet.defer import inlineCallbacks, returnValue
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from evennia.comms.channelhandler import CHANNELHANDLER
|
from evennia.comms.channelhandler import CHANNELHANDLER
|
||||||
|
|
@ -128,6 +130,12 @@ _ERROR_RECURSION_LIMIT = "Command recursion limit ({recursion_limit}) " \
|
||||||
"reached for '{raw_string}' ({cmdclass})."
|
"reached for '{raw_string}' ({cmdclass})."
|
||||||
|
|
||||||
|
|
||||||
|
# delayed imports
|
||||||
|
_GET_INPUT = None
|
||||||
|
|
||||||
|
|
||||||
|
# helper functions
|
||||||
|
|
||||||
def _msg_err(receiver, stringtuple):
|
def _msg_err(receiver, stringtuple):
|
||||||
"""
|
"""
|
||||||
Helper function for returning an error to the caller.
|
Helper function for returning an error to the caller.
|
||||||
|
|
@ -152,12 +160,77 @@ def _msg_err(receiver, stringtuple):
|
||||||
errmsg=stringtuple[1].strip(),
|
errmsg=stringtuple[1].strip(),
|
||||||
timestamp=timestamp).strip())
|
timestamp=timestamp).strip())
|
||||||
|
|
||||||
|
|
||||||
|
def _progressive_cmd_run(cmd, generator, response=None):
|
||||||
|
"""
|
||||||
|
Progressively call the command that was given in argument. Used
|
||||||
|
when `yield` is present in the Command's `func()` method.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
cmd (Command): the command itself.
|
||||||
|
generator (GeneratorType): the generator describing the processing.
|
||||||
|
reponse (str, optional): the response to send to the generator.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
ValueError: If the func call yields something not identifiable as a
|
||||||
|
time-delay or a string prompt.
|
||||||
|
|
||||||
|
Note:
|
||||||
|
This function is responsible for executing the command, if
|
||||||
|
the func() method contains 'yield' instructions. The yielded
|
||||||
|
value will be accessible at each step and will affect the
|
||||||
|
process. If the value is a number, just delay the execution
|
||||||
|
of the command. If it's a string, wait for the user input.
|
||||||
|
|
||||||
|
"""
|
||||||
|
global _GET_INPUT
|
||||||
|
if not _GET_INPUT:
|
||||||
|
from evennia.utils.evmenu import get_input as _GET_INPUT
|
||||||
|
|
||||||
|
try:
|
||||||
|
if response is None:
|
||||||
|
value = generator.next()
|
||||||
|
else:
|
||||||
|
value = generator.send(response)
|
||||||
|
except StopIteration:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
if isinstance(value, (int, float)):
|
||||||
|
utils.delay(value, _progressive_cmd_run, cmd, generator)
|
||||||
|
elif isinstance(value, basestring):
|
||||||
|
_GET_INPUT(cmd.caller, value, _process_input, cmd=cmd, generator=generator)
|
||||||
|
else:
|
||||||
|
raise ValueError("unknown type for a yielded value in command: {}".format(type(value)))
|
||||||
|
|
||||||
|
|
||||||
|
def _process_input(caller, prompt, result, cmd, generator):
|
||||||
|
"""
|
||||||
|
Specifically handle the get_input value to send to _progressive_cmd_run as
|
||||||
|
part of yielding from a Command's `func`.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
caller (Character, Player or Session): the caller.
|
||||||
|
prompt (basestring): The sent prompt.
|
||||||
|
result (basestring): The unprocessed answer.
|
||||||
|
cmd (Command): The command itself.
|
||||||
|
generator (GeneratorType): The generator.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
result (bool): Always `False` (stop processing).
|
||||||
|
|
||||||
|
"""
|
||||||
|
# We call it using a Twisted deferLater to make sure the input is properly closed.
|
||||||
|
deferLater(reactor, 0, _progressive_cmd_run, cmd, generator, response=result)
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
# custom Exceptions
|
# custom Exceptions
|
||||||
|
|
||||||
class NoCmdSets(Exception):
|
class NoCmdSets(Exception):
|
||||||
"No cmdsets found. Critical error."
|
"No cmdsets found. Critical error."
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class ExecSystemCommand(Exception):
|
class ExecSystemCommand(Exception):
|
||||||
"Run a system command"
|
"Run a system command"
|
||||||
def __init__(self, syscmd, sysarg):
|
def __init__(self, syscmd, sysarg):
|
||||||
|
|
@ -676,55 +749,3 @@ def cmdhandler(called_by, raw_string, _testing=False, callertype="session", sess
|
||||||
# This catches exceptions in cmdhandler exceptions themselves
|
# This catches exceptions in cmdhandler exceptions themselves
|
||||||
_msg_err(error_to, _ERROR_CMDHANDLER)
|
_msg_err(error_to, _ERROR_CMDHANDLER)
|
||||||
|
|
||||||
def _progressive_cmd_run(cmd, generator, response=None):
|
|
||||||
"""
|
|
||||||
Progressively call the command that was given in argument.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
cmd (Command): the command itself.
|
|
||||||
generator (GeneratorType): the generator describing the processing.
|
|
||||||
reponse (str, optional): the response to send to the generator.
|
|
||||||
|
|
||||||
Note:
|
|
||||||
This function is responsible for executing the command, if
|
|
||||||
the func() method contains 'yield' instructions. The yielded
|
|
||||||
value will be accessible at each step and will affect the
|
|
||||||
process. If the value is a number, just delay the execution
|
|
||||||
of the command. If it's a string, wait for the user input.
|
|
||||||
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
if response is None:
|
|
||||||
value = generator.next()
|
|
||||||
else:
|
|
||||||
value = generator.send(response)
|
|
||||||
except StopIteration:
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
if isinstance(value, (int, float)):
|
|
||||||
utils.delay(value, _progressive_cmd_run, cmd, generator)
|
|
||||||
elif isinstance(value, basestring):
|
|
||||||
from evennia.utils.evmenu import get_input
|
|
||||||
get_input(cmd.caller, value, _process_input, cmd=cmd, generator=generator)
|
|
||||||
else:
|
|
||||||
raise ValueError("unknown type for a yielded value in command: {}".format(type(value)))
|
|
||||||
|
|
||||||
def _process_input(caller, prompt, result, cmd, generator):
|
|
||||||
"""
|
|
||||||
Specifically handle the get_input value to send to _progressive_cmd_run.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
caller (Character, Player or Session): the caller.
|
|
||||||
prompt (basestring): the sent prompt.
|
|
||||||
result (basestring): the unprocessed answer.
|
|
||||||
cmd (Command): the command itself.
|
|
||||||
generator (GeneratorType): the generator.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
Always False (stop processing).
|
|
||||||
|
|
||||||
"""
|
|
||||||
# We call it in a 'utils.delay()' to make sure the input is properly closed.
|
|
||||||
utils.delay(0, _progressive_cmd_run, cmd, generator, response=result)
|
|
||||||
|
|
||||||
return False
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue