From c06fb69c8b5323d18a31bb8312cd95f50034e917 Mon Sep 17 00:00:00 2001 From: nemunaire Date: Tue, 3 Nov 2015 08:08:39 +0100 Subject: [PATCH] Extract tools.config as config module --- nemubot/__init__.py | 5 + nemubot/bot.py | 11 +- nemubot/config/__init__.py | 47 ++++++++ nemubot/config/include.py | 20 ++++ nemubot/config/module.py | 26 ++++ nemubot/config/nemubot.py | 46 +++++++ nemubot/config/server.py | 45 +++++++ nemubot/tools/config.py | 159 ------------------------- nemubot/tools/xmlparser/genericnode.py | 73 ++++++++++++ 9 files changed, 271 insertions(+), 161 deletions(-) create mode 100644 nemubot/config/__init__.py create mode 100644 nemubot/config/include.py create mode 100644 nemubot/config/module.py create mode 100644 nemubot/config/nemubot.py create mode 100644 nemubot/config/server.py delete mode 100644 nemubot/tools/config.py create mode 100644 nemubot/tools/xmlparser/genericnode.py diff --git a/nemubot/__init__.py b/nemubot/__init__.py index 193ad53..d0a2072 100644 --- a/nemubot/__init__.py +++ b/nemubot/__init__.py @@ -47,6 +47,11 @@ def reload(): import nemubot.channel imp.reload(nemubot.channel) + import nemubot.config + imp.reload(nemubot.config) + + nemubot.config.reload() + import nemubot.consumer imp.reload(nemubot.consumer) diff --git a/nemubot/bot.py b/nemubot/bot.py index b3dfbc1..54acdee 100644 --- a/nemubot/bot.py +++ b/nemubot/bot.py @@ -225,11 +225,18 @@ class Bot(threading.Thread): if not os.path.isfile(filename): return self.import_module(filename) - from nemubot.tools.config import config_nodes + from nemubot.channel import Channel + from nemubot import config from nemubot.tools.xmlparser import XMLParser try: - p = XMLParser(config_nodes) + p = XMLParser({ + "nemubotconfig": config.Nemubot, + "server": config.Server, + "channel": Channel, + "module": config.Module, + "include": config.Include, + }) config = p.parse_file(filename) except: logger.exception("Can't load `%s'; this is not a valid nemubot " diff --git a/nemubot/config/__init__.py b/nemubot/config/__init__.py new file mode 100644 index 0000000..497bd9e --- /dev/null +++ b/nemubot/config/__init__.py @@ -0,0 +1,47 @@ +# Nemubot is a smart and modulable IM bot. +# Copyright (C) 2012-2015 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 . + +def get_boolean(s): + if isinstance(s, bool): + return s + else: + return (s and s != "0" and s.lower() != "false" and s.lower() != "off") + +from nemubot.config.include import Include +from nemubot.config.module import Module +from nemubot.config.nemubot import Nemubot +from nemubot.config.server import Server + +def reload(): + global Include, Module, Nemubot, Server + + import imp + + import nemubot.config.include + imp.reload(nemubot.config.include) + Include = nemubot.config.include.Include + + import nemubot.config.module + imp.reload(nemubot.config.module) + Module = nemubot.config.module.Module + + import nemubot.config.nemubot + imp.reload(nemubot.config.nemubot) + Nemubot = nemubot.config.nemubot.Nemubot + + import nemubot.config.server + imp.reload(nemubot.config.server) + Server = nemubot.config.server.Server diff --git a/nemubot/config/include.py b/nemubot/config/include.py new file mode 100644 index 0000000..40bea9a --- /dev/null +++ b/nemubot/config/include.py @@ -0,0 +1,20 @@ +# Nemubot is a smart and modulable IM bot. +# Copyright (C) 2012-2015 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 . + +class Include: + + def __init__(self, path): + self.path = path diff --git a/nemubot/config/module.py b/nemubot/config/module.py new file mode 100644 index 0000000..670e97b --- /dev/null +++ b/nemubot/config/module.py @@ -0,0 +1,26 @@ +# Nemubot is a smart and modulable IM bot. +# Copyright (C) 2012-2015 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 . + +from nemubot.config import get_boolean +from nemubot.tools.xmlparser.genericnode import GenericNode + + +class Module(GenericNode): + + def __init__(self, name, autoload=True, **kwargs): + super().__init__(None, **kwargs) + self.name = name + self.autoload = get_boolean(autoload) diff --git a/nemubot/config/nemubot.py b/nemubot/config/nemubot.py new file mode 100644 index 0000000..a2548a4 --- /dev/null +++ b/nemubot/config/nemubot.py @@ -0,0 +1,46 @@ +# Nemubot is a smart and modulable IM bot. +# Copyright (C) 2012-2015 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 . + +from nemubot.config.include import Include +from nemubot.config.module import Module +from nemubot.config.server import Server + + +class Nemubot: + + def __init__(self, nick="nemubot", realname="nemubot", owner=None, + ip=None, ssl=False, caps=None, encoding="utf-8"): + self.nick = nick + self.realname = realname + self.owner = owner + self.ip = ip + self.caps = caps.split(" ") if caps is not None else [] + self.encoding = encoding + self.servers = [] + self.modules = [] + self.includes = [] + + + def addChild(self, name, child): + if name == "module" and isinstance(child, Module): + self.modules.append(child) + return True + elif name == "server" and isinstance(child, Server): + self.servers.append(child) + return True + elif name == "include" and isinstance(child, Include): + self.includes.append(child) + return True diff --git a/nemubot/config/server.py b/nemubot/config/server.py new file mode 100644 index 0000000..c856649 --- /dev/null +++ b/nemubot/config/server.py @@ -0,0 +1,45 @@ +# Nemubot is a smart and modulable IM bot. +# Copyright (C) 2012-2015 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 . + +from nemubot.channel import Channel + + +class Server: + + def __init__(self, uri="irc://nemubot@localhost/", autoconnect=True, caps=None, **kwargs): + self.uri = uri + self.autoconnect = autoconnect + self.caps = caps.split(" ") if caps is not None else [] + self.args = kwargs + self.channels = [] + + + def addChild(self, name, child): + if name == "channel" and isinstance(child, Channel): + self.channels.append(child) + return True + + + def server(self, parent): + from nemubot.server import factory + + for a in ["nick", "owner", "realname", "encoding"]: + if a not in self.args: + self.args[a] = getattr(parent, a) + + self.caps += parent.caps + + return factory(self.uri, caps=self.caps, channels=self.channels, **self.args) diff --git a/nemubot/tools/config.py b/nemubot/tools/config.py deleted file mode 100644 index f1305a7..0000000 --- a/nemubot/tools/config.py +++ /dev/null @@ -1,159 +0,0 @@ -# Nemubot is a smart and modulable IM bot. -# Copyright (C) 2012-2015 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 . - -def get_boolean(s): - if isinstance(s, bool): - return s - else: - return (s and s != "0" and s.lower() != "false" and s.lower() != "off") - - -class GenericNode: - - def __init__(self, tag, **kwargs): - self.tag = tag - self.attrs = kwargs - self.content = "" - self.children = [] - self._cur = None - self._deep_cur = 0 - - - def startElement(self, name, attrs): - if self._cur is None: - self._cur = GenericNode(name, **attrs) - self._deep_cur = 0 - else: - self._deep_cur += 1 - self._cur.startElement(name, attrs) - return True - - - def characters(self, content): - if self._cur is None: - self.content += content - else: - self._cur.characters(content) - - - def endElement(self, name): - if name is None: - return - - if self._deep_cur: - self._deep_cur -= 1 - self._cur.endElement(name) - else: - self.children.append(self._cur) - self._cur = None - return True - - - def hasNode(self, nodename): - return self.getNode(nodename) is not None - - - def getNode(self, nodename): - for c in self.children: - if c is not None and c.tag == nodename: - return c - return None - - - def __getitem__(self, item): - return self.attrs[item] - - def __contains__(self, item): - return item in self.attrs - - -class NemubotConfig: - - def __init__(self, nick="nemubot", realname="nemubot", owner=None, - ip=None, ssl=False, caps=None, encoding="utf-8"): - self.nick = nick - self.realname = realname - self.owner = owner - self.ip = ip - self.caps = caps.split(" ") if caps is not None else [] - self.encoding = encoding - self.servers = [] - self.modules = [] - self.includes = [] - - - def addChild(self, name, child): - if name == "module" and isinstance(child, ModuleConfig): - self.modules.append(child) - return True - elif name == "server" and isinstance(child, ServerConfig): - self.servers.append(child) - return True - elif name == "include" and isinstance(child, IncludeConfig): - self.includes.append(child) - return True - - -class ServerConfig: - - def __init__(self, uri="irc://nemubot@localhost/", autoconnect=True, caps=None, **kwargs): - self.uri = uri - self.autoconnect = autoconnect - self.caps = caps.split(" ") if caps is not None else [] - self.args = kwargs - self.channels = [] - - - def addChild(self, name, child): - if name == "channel" and isinstance(child, Channel): - self.channels.append(child) - return True - - - def server(self, parent): - from nemubot.server import factory - - for a in ["nick", "owner", "realname", "encoding"]: - if a not in self.args: - self.args[a] = getattr(parent, a) - - self.caps += parent.caps - - return factory(self.uri, caps=self.caps, channels=self.channels, **self.args) - - -class IncludeConfig: - - def __init__(self, path): - self.path = path - - -class ModuleConfig(GenericNode): - - def __init__(self, name, autoload=True, **kwargs): - super(ModuleConfig, self).__init__(None, **kwargs) - self.name = name - self.autoload = get_boolean(autoload) - -from nemubot.channel import Channel - -config_nodes = { - "nemubotconfig": NemubotConfig, - "server": ServerConfig, - "channel": Channel, - "module": ModuleConfig, - "include": IncludeConfig, -} diff --git a/nemubot/tools/xmlparser/genericnode.py b/nemubot/tools/xmlparser/genericnode.py new file mode 100644 index 0000000..efbdda9 --- /dev/null +++ b/nemubot/tools/xmlparser/genericnode.py @@ -0,0 +1,73 @@ +# Nemubot is a smart and modulable IM bot. +# Copyright (C) 2012-2015 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 . + +class GenericNode: + + def __init__(self, tag, **kwargs): + self.tag = tag + self.attrs = kwargs + self.content = "" + self.children = [] + self._cur = None + self._deep_cur = 0 + + + def startElement(self, name, attrs): + if self._cur is None: + self._cur = GenericNode(name, **attrs) + self._deep_cur = 0 + else: + self._deep_cur += 1 + self._cur.startElement(name, attrs) + return True + + + def characters(self, content): + if self._cur is None: + self.content += content + else: + self._cur.characters(content) + + + def endElement(self, name): + if name is None: + return + + if self._deep_cur: + self._deep_cur -= 1 + self._cur.endElement(name) + else: + self.children.append(self._cur) + self._cur = None + return True + + + def hasNode(self, nodename): + return self.getNode(nodename) is not None + + + def getNode(self, nodename): + for c in self.children: + if c is not None and c.tag == nodename: + return c + return None + + + def __getitem__(self, item): + return self.attrs[item] + + def __contains__(self, item): + return item in self.attrs