From 7956d7edafc804c7fa39019959a42912be19c3fc Mon Sep 17 00:00:00 2001 From: Ben Kurtovic Date: Thu, 9 Aug 2012 13:50:34 -0400 Subject: [PATCH] Splitting config.py into three files. --- earwigbot/{config.py => config/__init__.py} | 98 ++++------------------------- earwigbot/config/formatter.py | 51 +++++++++++++++ earwigbot/config/node.py | 73 +++++++++++++++++++++ 3 files changed, 135 insertions(+), 87 deletions(-) rename earwigbot/{config.py => config/__init__.py} (81%) create mode 100644 earwigbot/config/formatter.py create mode 100644 earwigbot/config/node.py diff --git a/earwigbot/config.py b/earwigbot/config/__init__.py similarity index 81% rename from earwigbot/config.py rename to earwigbot/config/__init__.py index df19d6b..b491b76 100644 --- a/earwigbot/config.py +++ b/earwigbot/config/__init__.py @@ -41,6 +41,8 @@ try: except ImportError: yaml = None +from earwigbot.config.formatter import BotFormatter +from earwigbot.config.node import ConfigNode from earwigbot.exceptions import NoConfigError __all__ = ["BotConfig"] @@ -80,12 +82,12 @@ class BotConfig(object): self._decryption_cipher = None self._data = None - self._components = _ConfigNode() - self._wiki = _ConfigNode() - self._irc = _ConfigNode() - self._commands = _ConfigNode() - self._tasks = _ConfigNode() - self._metadata = _ConfigNode() + self._components = ConfigNode() + self._wiki = ConfigNode() + self._irc = ConfigNode() + self._commands = ConfigNode() + self._tasks = ConfigNode() + self._metadata = ConfigNode() self._nodes = [self._components, self._wiki, self._irc, self._commands, self._tasks, self._metadata] @@ -123,8 +125,8 @@ class BotConfig(object): logger = logging.getLogger("earwigbot") logger.handlers = [] # Remove any handlers already attached to us logger.setLevel(logging.DEBUG) - color_formatter = _BotFormatter(color=True) - formatter = _BotFormatter() + color_formatter = BotFormatter(color=True) + formatter = BotFormatter() if self.metadata.get("enableLogging"): hand = logging.handlers.TimedRotatingFileHandler @@ -253,7 +255,7 @@ class BotConfig(object): exit. Data from the config file is stored in six - :py:class:`~earwigbot.config._ConfigNode`\ s (:py:attr:`components`, + :py:class:`~earwigbot.config.ConfigNode`\ s (:py:attr:`components`, :py:attr:`wiki`, :py:attr:`irc`, :py:attr:`commands`, :py:attr:`tasks`, :py:attr:`metadata`) for easy access (as well as the lower-level :py:attr:`data` attribute). If passwords are encrypted, we'll use @@ -342,81 +344,3 @@ class BotConfig(object): pass return tasks - - -class _ConfigNode(object): - def __iter__(self): - for key in self.__dict__: - yield key - - def __getitem__(self, item): - return self.__dict__.__getitem__(item) - - def _dump(self): - data = self.__dict__.copy() - for key, val in data.iteritems(): - if isinstance(val, _ConfigNode): - data[key] = val._dump() - return data - - def _load(self, data): - self.__dict__ = data.copy() - - def _decrypt(self, cipher, intermediates, item): - base = self.__dict__ - for inter in intermediates: - try: - base = base[inter] - except KeyError: - return - if item in base: - ciphertext = base[item].decode("hex") - base[item] = cipher.decrypt(ciphertext).rstrip("\x00") - - def get(self, *args, **kwargs): - return self.__dict__.get(*args, **kwargs) - - def keys(self): - return self.__dict__.keys() - - def values(self): - return self.__dict__.values() - - def items(self): - return self.__dict__.items() - - def iterkeys(self): - return self.__dict__.iterkeys() - - def itervalues(self): - return self.__dict__.itervalues() - - def iteritems(self): - return self.__dict__.iteritems() - - -class _BotFormatter(logging.Formatter): - def __init__(self, color=False): - self._format = super(_BotFormatter, self).format - if color: - fmt = "[%(asctime)s %(lvl)s] %(name)s: %(message)s" - self.format = lambda record: self._format(self.format_color(record)) - else: - fmt = "[%(asctime)s %(levelname)-8s] %(name)s: %(message)s" - self.format = self._format - datefmt = "%Y-%m-%d %H:%M:%S" - super(_BotFormatter, self).__init__(fmt=fmt, datefmt=datefmt) - - def format_color(self, record): - l = record.levelname.ljust(8) - if record.levelno == logging.DEBUG: - record.lvl = l.join(("\x1b[34m", "\x1b[0m")) # Blue - if record.levelno == logging.INFO: - record.lvl = l.join(("\x1b[32m", "\x1b[0m")) # Green - if record.levelno == logging.WARNING: - record.lvl = l.join(("\x1b[33m", "\x1b[0m")) # Yellow - if record.levelno == logging.ERROR: - record.lvl = l.join(("\x1b[31m", "\x1b[0m")) # Red - if record.levelno == logging.CRITICAL: - record.lvl = l.join(("\x1b[1m\x1b[31m", "\x1b[0m")) # Bold red - return record diff --git a/earwigbot/config/formatter.py b/earwigbot/config/formatter.py new file mode 100644 index 0000000..561db21 --- /dev/null +++ b/earwigbot/config/formatter.py @@ -0,0 +1,51 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2009-2012 Ben Kurtovic +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +import logging + +__all__ = ["BotFormatter"] + +class BotFormatter(logging.Formatter): + def __init__(self, color=False): + self._format = super(BotFormatter, self).format + if color: + fmt = "[%(asctime)s %(lvl)s] %(name)s: %(message)s" + self.format = lambda rec: self._format(self.format_color(rec)) + else: + fmt = "[%(asctime)s %(levelname)-8s] %(name)s: %(message)s" + self.format = self._format + datefmt = "%Y-%m-%d %H:%M:%S" + super(BotFormatter, self).__init__(fmt=fmt, datefmt=datefmt) + + def format_color(self, record): + l = record.levelname.ljust(8) + if record.levelno == logging.DEBUG: + record.lvl = l.join(("\x1b[34m", "\x1b[0m")) # Blue + if record.levelno == logging.INFO: + record.lvl = l.join(("\x1b[32m", "\x1b[0m")) # Green + if record.levelno == logging.WARNING: + record.lvl = l.join(("\x1b[33m", "\x1b[0m")) # Yellow + if record.levelno == logging.ERROR: + record.lvl = l.join(("\x1b[31m", "\x1b[0m")) # Red + if record.levelno == logging.CRITICAL: + record.lvl = l.join(("\x1b[1m\x1b[31m", "\x1b[0m")) # Bold red + return record diff --git a/earwigbot/config/node.py b/earwigbot/config/node.py new file mode 100644 index 0000000..345e181 --- /dev/null +++ b/earwigbot/config/node.py @@ -0,0 +1,73 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2009-2012 Ben Kurtovic +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +__all__ = ["ConfigNode"] + +class ConfigNode(object): + def __iter__(self): + for key in self.__dict__: + yield key + + def __getitem__(self, item): + return self.__dict__.__getitem__(item) + + def _dump(self): + data = self.__dict__.copy() + for key, val in data.iteritems(): + if isinstance(val, ConfigNode): + data[key] = val._dump() + return data + + def _load(self, data): + self.__dict__ = data.copy() + + def _decrypt(self, cipher, intermediates, item): + base = self.__dict__ + for inter in intermediates: + try: + base = base[inter] + except KeyError: + return + if item in base: + ciphertext = base[item].decode("hex") + base[item] = cipher.decrypt(ciphertext).rstrip("\x00") + + def get(self, *args, **kwargs): + return self.__dict__.get(*args, **kwargs) + + def keys(self): + return self.__dict__.keys() + + def values(self): + return self.__dict__.values() + + def items(self): + return self.__dict__.items() + + def iterkeys(self): + return self.__dict__.iterkeys() + + def itervalues(self): + return self.__dict__.itervalues() + + def iteritems(self): + return self.__dict__.iteritems()