Rework prompt: add exception classes for errors and reload/quit

This commit is contained in:
nemunaire 2015-01-01 23:17:02 +01:00
parent 0d21b1fa2c
commit fd6d9288f7
6 changed files with 89 additions and 19 deletions

View file

@ -26,6 +26,7 @@ import sys
import bot
import prompt
from prompt.builtins import load_file
from prompt.reset import PromptReset
import importer
if __name__ == "__main__":
@ -116,7 +117,13 @@ if __name__ == "__main__":
print ("Nemubot v%s ready, my PID is %i!" % (bot.__version__,
os.getpid()))
context.start()
while prmpt.run(context):
while True:
try:
prmpt.run(context)
except PromptReset as e:
if e.type == "quit":
break
try:
# Reload context
imp.reload(bot)

View file

@ -23,6 +23,8 @@ import shlex
import sys
import traceback
from .error import PromptError
from .reset import PromptReset
from . import builtins
@ -30,12 +32,14 @@ class Prompt:
def __init__(self):
self.selectedServer = None
self.lastretcode = 0
self.HOOKS_CAPS = dict()
self.HOOKS_LIST = dict()
def add_cap_hook(self, name, call, data=None):
self.HOOKS_CAPS[name] = (lambda d, t, c, p: call(d, t, c, p), data)
self.HOOKS_CAPS[name] = lambda t, c: call(t, data=data,
context=c, prompt=self)
def add_list_hook(self, name, call):
self.HOOKS_LIST[name] = call
@ -77,13 +81,12 @@ class Prompt:
"""
if toks[0] in builtins.CAPS:
return builtins.CAPS[toks[0]](toks, context, self)
self.lastretcode = builtins.CAPS[toks[0]](toks, context, self)
elif toks[0] in self.HOOKS_CAPS:
f, d = self.HOOKS_CAPS[toks[0]]
return f(d, toks, context, self)
self.lastretcode = self.HOOKS_CAPS[toks[0]](toks, context)
else:
print("Unknown command: `%s'" % toks[0])
return ""
self.lastretcode = 127
def getPS1(self):
"""Get the PS1 associated to the selected server"""
@ -99,14 +102,19 @@ class Prompt:
context -- current bot context
"""
ret = ""
while ret != "quit" and ret != "reset" and ret != "refresh":
while True: # Stopped by exception
try:
line = input("\033[0;33m%s§\033[0m " % self.getPS1())
line = input("\033[0;33m%s\033[0;%d\033[0m " %
(self.getPS1(), 31 if self.lastretcode else 32))
cmds = self.lex_cmd(line.strip())
for toks in cmds:
try:
ret = self.exec_cmd(toks, context)
self.exec_cmd(toks, context)
except PromptReset:
raise
except PromptError as e:
print(e.message)
self.lastretcode = 128
except:
exc_type, exc_value, exc_traceback = sys.exc_info()
traceback.print_exception(exc_type, exc_value,
@ -114,9 +122,8 @@ class Prompt:
except KeyboardInterrupt:
print("")
except EOFError:
ret = "quit"
print("quit")
return ret != "quit"
raise PromptReset("quit")
def hotswap(bak):

View file

@ -18,6 +18,7 @@
import logging
from .reset import PromptReset
from tools.config import load_file
logger = logging.getLogger("nemubot.prompt.builtins")
@ -26,12 +27,10 @@ logger = logging.getLogger("nemubot.prompt.builtins")
def end(toks, context, prompt):
"""Quit the prompt for reload or exit"""
if toks[0] == "refresh":
return "refresh"
raise PromptReset("refresh")
elif toks[0] == "reset":
return "reset"
else:
context.quit()
return "quit"
raise PromptReset("reset")
raise PromptReset("quit")
def liste(toks, context, prompt):
@ -58,8 +57,11 @@ def liste(toks, context, prompt):
else:
print (" Unknown list `%s'" % l)
return 2
return 0
else:
print (" Please give a list to show: servers, ...")
return 1
def load(toks, context, prompt):
@ -69,7 +71,7 @@ def load(toks, context, prompt):
load_file(filename, context)
else:
print ("Not enough arguments. `load' takes a filename.")
return
return 1
def select(toks, context, prompt):
@ -80,9 +82,9 @@ def select(toks, context, prompt):
prompt.selectedServer = context.servers[toks[1]]
else:
print ("select: server `%s' not found." % toks[1])
return 1
else:
prompt.selectedServer = None
return
def unload(toks, context, prompt):
@ -96,8 +98,10 @@ def unload(toks, context, prompt):
print (" Module `%s' successfully unloaded." % name)
else:
print (" No module `%s' loaded, can't unload!" % name)
return 2
else:
print ("Not enough arguments. `unload' takes a module name.")
return 1
def debug(toks, context, prompt):
@ -112,8 +116,10 @@ def debug(toks, context, prompt):
print (" Debug for module module `%s' disabled." % name)
else:
print (" No module `%s' loaded, can't debug!" % name)
return 2
else:
print ("Not enough arguments. `debug' takes a module name.")
return 1
# Register build-ins

23
prompt/error.py Normal file
View file

@ -0,0 +1,23 @@
# coding=utf-8
# Nemubot is a modulable IRC bot, built around XML configuration files.
# Copyright (C) 2012 Mercier Pierre-Olivier
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
class PromptError(Exception):
def __init__(self, message):
super(PromptError, self).__init__(message)
self.message = message

23
prompt/reset.py Normal file
View file

@ -0,0 +1,23 @@
# coding=utf-8
# Nemubot is a modulable IRC bot, built around XML configuration files.
# Copyright (C) 2012 Mercier Pierre-Olivier
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
class PromptReset(Exception):
def __init__(self, type):
super(PromptReset, self).__init__("Prompt reset asked")
self.type = type

View file

@ -69,6 +69,8 @@ class AbstractServer(io.IOBase):
if not hasattr(self, "_open") or self._open():
_rlist.append(self)
_xlist.append(self)
return True
return False
def close(self):
@ -82,6 +84,8 @@ class AbstractServer(io.IOBase):
_wlist.remove(self)
if self in _xlist:
_xlist.remove(self)
return True
return False
# Writes