diff options
Diffstat (limited to 'bot/MeetBot/supybotconfig.py')
-rw-r--r-- | bot/MeetBot/supybotconfig.py | 174 |
1 files changed, 174 insertions, 0 deletions
diff --git a/bot/MeetBot/supybotconfig.py b/bot/MeetBot/supybotconfig.py new file mode 100644 index 0000000..d4921a9 --- /dev/null +++ b/bot/MeetBot/supybotconfig.py @@ -0,0 +1,174 @@ +# Richard Darst, June 2009 + +### +# Copyright (c) 2009, Richard Darst +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions, and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions, and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of the author of this software nor the name of +# contributors to this software may be used to endorse or promote products +# derived from this software without specific prior written consent. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +### + + +import types + +import supybot.conf as conf +import supybot.registry as registry + +import ircmeeting.meeting as meeting +import ircmeeting.writers as writers + +# The plugin group for configuration +MeetBotConfigGroup = conf.registerPlugin('MeetBot') + +class WriterMap(registry.String): + """List of output formats to write. This is a space-separated + list of 'WriterName:.ext' pairs. WriterName must be from the + writers.py module, '.ext' must be a extension ending in a . + """ + def set(self, s): + s = s.split() + writer_map = { } + for writer in s: + #from fitz import interact ; interact.interact() + writer, ext = writer.split(':', 1) + if not hasattr(writers, writer): + raise ValueError("Writer name not found: %s"%writer) + #if len(ext) < 2 or ext[0] != '.': + # raise ValueError("Extension must start with '.' and have " + # "at least one more character.") + writer_map[ext] = getattr(writers, writer) + self.setValue(writer_map) + def setValue(self, writer_map): + for e, w in writer_map.iteritems(): + if not hasattr(w, "format"): + raise ValueError("Writer %s must have method .format()"% + w.__name__) + self.value = writer_map + def __str__(self): + writers_string = [ ] + for ext, w in self.value.iteritems(): + name = w.__name__ + writers_string.append("%s:%s"%(name, ext)) + return " ".join(writers_string) + + +class SupybotConfigProxy(object): + def __init__(self, *args, **kwargs): + """Do the regular default configuration, and sta""" + OriginalConfig = self.__OriginalConfig + self.__C = OriginalConfig.__new__(OriginalConfig, *args, **kwargs) + # We need to call the __init__ *after* we have rebound the + # method to get variables from the config proxy. + old_init = self.__C.__init__ + new_init = types.MethodType(old_init.im_func, self, old_init.im_class) + new_init(*args, **kwargs) + + def __getattr__(self, attrname): + """Try to get the value from the supybot registry. If it's in + the registry, return it. If it's not, then proxy it to th. + """ + if attrname in settable_attributes: + M = self.M + value = M._registryValue(attrname, channel=M.channel) + if not isinstance(value, (str, unicode)): + return value + # '.' is used to mean "this is not set, use the default + # value from the python config class. + if value != '.': + value = value.replace('\\n', '\n') + return value + # If the attribute is a _property_, we need to rebind the + # "fget" method to the proxy class. + # See http://docs.python.org/library/functions.html#property + # http://docs.python.org/reference/datamodel.html#descriptors + C = self.__C + # is this a class attribute AND does it have a fget ? + if hasattr(C.__class__, attrname) and \ + hasattr(getattr(C.__class__, attrname), 'fget'): + # Get the 'fget' descriptor, rebind it to self, return its + # value. + fget = getattr(C.__class__, attrname).fget + fget = types.MethodType(fget, self, C.__class__) + return fget() + # We don't have this value in the registry. So, proxy it to + # the normal config object. This is also the path that all + # functions take. + value = getattr(self.__C, attrname) + # If the value is an instance method, we need to re-bind it to + # the new config class so that we will get the data values + # defined in supydot (otherwise attribute lookups in the + # method will bypass the supybot proxy and just use default + # values). This will slow things down a little bit, but + # that's just the cost of duing business. + if hasattr(value, 'im_func'): + return types.MethodType(value.im_func, self, value.im_class) + return value + + + +#conf.registerGlobalValue(MeetBot +use_supybot_config = conf.registerGlobalValue(MeetBotConfigGroup, + 'enableSupybotBasedConfig', + registry.Boolean(False, '')) +def is_supybotconfig_enabled(OriginalConfig): + return (use_supybot_config.value and + not getattr(OriginalConfig, 'dontBotConfig', False)) + +settable_attributes = [ ] +def setup_config(OriginalConfig): + # Set all string variables in the default Config class as supybot + # registry variables. + for attrname in dir(OriginalConfig): + # Don't configure attributs starting with '_' + if attrname[0] == '_': + continue + attr = getattr(OriginalConfig, attrname) + # Don't configure attributes that aren't strings. + if isinstance(attr, (str, unicode)): + attr = attr.replace('\n', '\\n') + # For a global value: conf.registerGlobalValue and remove the + # channel= option from registryValue call above. + conf.registerChannelValue(MeetBotConfigGroup, attrname, + registry.String(attr,"")) + settable_attributes.append(attrname) + if isinstance(attr, bool): + conf.registerChannelValue(MeetBotConfigGroup, attrname, + registry.Boolean(attr,"")) + settable_attributes.append(attrname) + + # writer_map + # (doing the commented out commands below will erase the previously + # stored value of a config variable) + #if 'writer_map' in MeetBotConfigGroup._children: + # MeetBotConfigGroup.unregister('writer_map') + conf.registerChannelValue(MeetBotConfigGroup, 'writer_map', + WriterMap(OriginalConfig.writer_map, "")) + settable_attributes.append('writer_map') + +def get_config_proxy(OriginalConfig): + # Here is where the real proxying occurs. + SupybotConfigProxy._SupybotConfigProxy__OriginalConfig = OriginalConfig + return SupybotConfigProxy + + |