Misc cleanup and clarification

This commit is contained in:
dpedu 2015-06-20 00:30:12 -07:00
parent aa90608e93
commit 2751eb3d16
4 changed files with 41 additions and 25 deletions

View File

@ -30,15 +30,17 @@ class IRCCore(asynchat.async_chat):
"""Reference to logger object""" """Reference to logger object"""
self.buffer = StringIO() self.buffer = StringIO()
"""cSTringIO used as a buffer""" """cStringIO used as a buffer"""
self.alive = True self.alive = True
""" True if we should try to stay connected""" """True if we should try to stay connected"""
# Connection details
self.server = None self.server = None
"""Server address"""
self.port = 0 self.port = 0
"""Server port"""
self.ipv6 = False self.ipv6 = False
"""Use IPv6?"""
# IRC Messages are terminated with \r\n # IRC Messages are terminated with \r\n
self.set_terminator(b"\r\n") self.set_terminator(b"\r\n")
@ -54,7 +56,7 @@ class IRCCore(asynchat.async_chat):
def kill(self): def kill(self):
"""TODO close the socket""" """TODO close the socket"""
pass self.act_QUIT("Help! Another thread is killing me :(")
" Net related code here on down " " Net related code here on down "
@ -88,7 +90,7 @@ class IRCCore(asynchat.async_chat):
self.process_data(line) self.process_data(line)
def handle_close(self): def handle_close(self):
"""Called when the socket is disconnected. We will want to reconnect. """ """Called when the socket is disconnected. Triggers the _DISCONNECT hook"""
self.log.debug("handle_close") self.log.debug("handle_close")
self.connected=False self.connected=False
self.close() self.close()
@ -96,7 +98,10 @@ class IRCCore(asynchat.async_chat):
def handle_error(self, *args, **kwargs): def handle_error(self, *args, **kwargs):
"""Called on fatal network errors.""" """Called on fatal network errors."""
self.log.warning("Connection failed.") self.log.error("Connection failed (handle_error)")
self.log.error(str(args))
self.log.error(str(kwargs))
self.log(IRCCore.trace());
def _connect(self): def _connect(self):
"""Connect to IRC""" """Connect to IRC"""
@ -112,10 +117,9 @@ class IRCCore(asynchat.async_chat):
self.asynmap[self._fileno] = self # http://willpython.blogspot.com/2010/08/multiple-event-loops-with-asyncore-and.html self.asynmap[self._fileno] = self # http://willpython.blogspot.com/2010/08/multiple-event-loops-with-asyncore-and.html
def handle_connect(self): def handle_connect(self):
"""When asynchat indicates our socket is connected, fire the connect hook""" """When asynchat indicates our socket is connected, fire the _CONNECT hook"""
self.connected=True self.connected=True
# TODO move to an event self.log.debug("handle_connect: connected")
self.log.debug("handle_connect: setting USER and NICK")
self.fire_hook("_CONNECT") self.fire_hook("_CONNECT")
self.log.debug("handle_connect: complete") self.log.debug("handle_connect: complete")

View File

@ -30,19 +30,19 @@ class ModuleBase:
"""Hooks (aka listeners) this module has""" """Hooks (aka listeners) this module has"""
self.services=[] self.services=[]
"""If this module provides services usable by another module, they're stored """If this module provides services usable by another module, they're listed
here""" here"""
self.config={} self.config={}
"""Configuration dictionary. Blank until loadConfig is called""" """Configuration dictionary. Autoloaded from `%(datadir)s/%(modulename)s.yml`"""
self.log = logging.getLogger("Module.%s" % self.moduleName) self.log = logging.getLogger("Module.%s" % self.moduleName)
"""Logger object for this module""" """Logger object for this module"""
# Autoload config if available
self.loadConfig() self.loadConfig()
self.log.info("Loaded module %s" % self.moduleName) self.log.info("Loaded module %s" % self.moduleName)
def loadConfig(self): def loadConfig(self):
"""Loads this module's config into self.config""" """Loads this module's config into self.config"""
@ -68,8 +68,8 @@ class ModuleBase:
:Warning: .. Warning:: this does no error checking if the file exists or is\ :Warning: .. Warning:: this does no error checking if the file exists or is\
writable. The bot's data dir *should* always be writable""" writable. The bot's data dir *should* always be writable"""
return self.bot.getDataPath(self.moduleName) + (f if f else '') return self.bot.getDataPath(self.moduleName) + (f if f else '')
class ModuleHook: class ModuleHook:
def __init__(self, hook, method): def __init__(self, hook, method):
self.hook=hook self.hook=hook
self.method=method self.method=method

View File

@ -25,6 +25,13 @@ class PyIRCBot:
self.botconfig = botconfig self.botconfig = botconfig
"""saved copy of the instance config""" """saved copy of the instance config"""
"""storage of imported modules"""
self.modules = {}
"""instances of modules"""
self.moduleInstances = {}
self.rpc = BotRPC(self) self.rpc = BotRPC(self)
"""Reference to BotRPC thread""" """Reference to BotRPC thread"""
@ -34,7 +41,7 @@ class PyIRCBot:
self.irc.port = self.botconfig["connection"]["port"] self.irc.port = self.botconfig["connection"]["port"]
self.irc.ipv6 = True if self.botconfig["connection"]["ipv6"]=="on" else False self.irc.ipv6 = True if self.botconfig["connection"]["ipv6"]=="on" else False
self.irc.addHook("_DISCONNECT", self.handle_close) self.irc.addHook("_DISCONNECT", self.connection_closed)
# legacy support # legacy support
self.act_PONG = self.irc.act_PONG self.act_PONG = self.irc.act_PONG
@ -69,11 +76,7 @@ class PyIRCBot:
sys.exit(0) sys.exit(0)
def connection_closed(self):
" Net related code here on down "
# TODO move handle_close to an event hook
def handle_close(self):
"""Called when the socket is disconnected. We will want to reconnect. """ """Called when the socket is disconnected. We will want to reconnect. """
if self.alive: if self.alive:
self.log.warning("Connection was lost. Reconnecting in 5 seconds.") self.log.warning("Connection was lost. Reconnecting in 5 seconds.")
@ -82,10 +85,6 @@ class PyIRCBot:
def initModules(self): def initModules(self):
"""load modules specified in instance config""" """load modules specified in instance config"""
" storage of imported modules "
self.modules = {}
" instances of modules "
self.moduleInstances = {}
" append module location to path " " append module location to path "
sys.path.append(os.path.dirname(__file__)+"/modules/") sys.path.append(os.path.dirname(__file__)+"/modules/")
for modulename in self.botconfig["modules"]: for modulename in self.botconfig["modules"]:
@ -354,6 +353,7 @@ class PyIRCBot:
:param filepath: path to a file of json or yaml format. filename must end with .json or .yml :param filepath: path to a file of json or yaml format. filename must end with .json or .yml
:type filepath: str :type filepath: str
:Returns: | dict
""" """
if filepath.endswith(".yml"): if filepath.endswith(".yml"):
from yaml import load from yaml import load

View File

@ -12,11 +12,23 @@ from pyircbot import jsonrpc
from threading import Thread from threading import Thread
class BotRPC(Thread): class BotRPC(Thread):
""":param main: A reference to the PyIRCBot instance this instance will control
:type main: PyIRCBot
"""
def __init__(self, main): def __init__(self, main):
Thread.__init__(self, daemon=True) Thread.__init__(self, daemon=True)
self.bot = main self.bot = main
self.log = logging.getLogger('RPC') self.log = logging.getLogger('RPC')
self.server = jsonrpc.Server(jsonrpc.JsonRpc20(), jsonrpc.TransportTcpIp(addr=(self.bot.botconfig["bot"]["rpcbind"], self.bot.botconfig["bot"]["rpcport"]))) self.server = jsonrpc.Server(
jsonrpc.JsonRpc20(),
jsonrpc.TransportTcpIp(
addr=(
self.bot.botconfig["bot"]["rpcbind"],
self.bot.botconfig["bot"]["rpcport"]
)
)
)
self.server.register_function( self.importModule ) self.server.register_function( self.importModule )
self.server.register_function( self.deportModule ) self.server.register_function( self.deportModule )