tags:

views:

71

answers:

4

I am having a weird problem with a chatbot I am writing that supports plugin extensions. The base extension class have attributes and methods predefined that will be inherited and can be overloaded and set. Here is the base class:

class Ext:
    # Info about the extension
    Name    = 'Unnamed'
    Author  = 'Nobody'
    Version = 0
    Desc    = 'This extension has no description'
    Webpage = ''

    # Determines whether the extension will automatically be on when added or not
    OnByDefault = False

    def __init__(self): 
        # Overwrite me! You can use me to load files and set attributes at startup
        raise Exception('AbstractClassError: This class must be overloaded')

    def SetName(self, name):
        name = name.split(' ')
        name = ''.join(name)
        self.Name = name

    def Load(self, file): 
        # Loads a file
        return Misc.read_obj(file)

    def Save(self, file, obj): 
        # Saves a file
        return Misc.write_obj(file, obj)

    def Activate(self, Komodo):
        # When the extension is turned on, this is called
        pass

    def add_cmd(self, Komodo, name, callback, default=False, link=''):
        # Add a command to the bot
        if name in Komodo.Ext.commands:
            Komodo.logger(msg = ">> Command '{0}' was already defined, so {1}'s version of the command couldn't be added".format(
                name, self.meta.name))
        else:
            Komodo.Ext.commands[name] = callback
            if default:
                Komodo.Ext.default_commands.append(name)
            if len(link) > 0:
                Komodo.Ext.links[name] = link

    def add_event(self, Komodo, type, callback):
        # Add an event to the bot
        if type not in Komodo.Ext.trigs:
            Komodo.logger(msg = 
                ">> Could not add '{0}' to event type '{1}' from extension '{2}' because that type does not exist".format(
                str(callback), type, self.name))
        else:
            Komodo.Ext.trigs[type].append(callback)

This is what an extension normally looks like:

class Extension(Ext):
    def __init__(self, K):  
        self.file = 'Storage/Extensions/AI.txt'
        self.SetName('AI')

        self.Version = 1.1
        self.Author  = 'blazer-flamewing'
        self.Desc    = 'An extension that lets you talk to an Artificial Intelligence program online called Kato.'
        self.Webpage = 'http://botdom.com/wiki/Komodo/Extensions/AI'

        try:    self.AI = self.Load(file)
        except: self.AI = {}

    def Activate(self, K):
        print(self.Version)
        self.add_cmd(K, 'ai', self.cmd_AI, False, 'http://botdom.com/wiki/Komodo/Extensions/AI')
        self.add_event(K, 'msg', self.msg_AI)


    ...more methods down here that aren't part of the base class

Every extension written like this works... except for one, the one mentioned above. It only succeeds when setting it's Name attribute, and when the other attributes are read they are still what the base class was set. At startup, I looped through every extension to print the dict entry, the actual name, the version, the author, and whether the extension was on or not and got this result:

Responses Responses 1.2 blazer-flamewing OFF
Ai AI 0 Nobody ON
Notes Notes 1.2 blazer-flamewing OFF
Misc Misc 1.5 blazer-flamewing OFF
System System 2.2 blazer-flamewing ON
Helloworld HelloWorld 1.3 blazer-flamewing OFF
Goodbyes Goodbyes 0 blazer-flamewing OFF
Spamfilter Spamfilter 1.2 blazer-flamewing OFF
Damn dAmn 2.2 blazer-flamewing ON
Bds BDS 0.2 blazer-flamewing OFF
Fun Fun 1.6 blazer-flamewing OFF
Welcomes Welcomes 1.5 blazer-flamewing OFF
Cursefilter Cursefilter 1.7 blazer-flamewing OFF

Similarly, Extension.Activate() isn't working for AI when it is turned on. I assume that has to do with the same sort of problem (not being set properly)

Any ideas as to why the class's attributes aren't setting? I've been stuck on this for hours and the extension is set up the exact same way other extensions are

EDIT: Here is another extension for comparison. This one actually works, Activate() actually calls. everything is pretty much exactly the same other than content

from komodo.extension import Ext
import time

class Extension(Ext):        
    def __init__(self, K):
        self.SetName('dAmn')
        self.Version = 2.2
        self.Author  = 'blazer-flamewing'
        self.Desc    = 'Module for all standard dAmn commands such as join, part, and say.'
        self.Webpage = 'http://botdom.com/wiki/Komodo/Extensions/dAmn'
        self.OnByDefault = True

    def Activate(self, K):
        self.add_cmd(K, 'action',       self.cmd_action,       False, "http://botdom.com/wiki/Komodo/Extensions/dAmn#Me_or_Action")
        self.add_cmd(K, 'ban',          self.cmd_ban,          False, "http://botdom.com/wiki/Komodo/Extensions/dAmn#Ban_and_Unban")
        self.add_cmd(K, 'chat',         self.cmd_chat,         True,  "http://botdom.com/wiki/Komodo/Extensions/dAmn#Chat")
        self.add_cmd(K, 'demote',       self.cmd_demote,       False, "http://botdom.com/wiki/Komodo/Extensions/dAmn#Demote_and_Promote")
        self.add_cmd(K, 'join',         self.cmd_join,         False, "http://botdom.com/wiki/Komodo/Extensions/dAmn#Join_and_Part")
        ...etc
+1  A: 

Is it possible that the block below the SetName call is actually indented differently (say, with tabs instead of spaces) and the following lines are not actually part of __init__?

Ben Jackson
No, there are only spaces in the indentations
Blazer
+1  A: 

I don't think this is your problem, as you get what you want with the other classes - but I hope you can see you are not setting any "class" attributes on the inherited classes - you are setting just instance attributes for them. (therefore, if you try to get Extension.Version - it will pick the attribute from the base class "Ext" -- only when you have an Extension Object it's Version attribute is overriden with the instance attribute "Version".

That does not cover why "Activate" would not be working though.

jsbueno
The classes are instantiated when they are loaded. Activate() isn't working because it is running the original Activate(), which is only a 'pass'
Blazer
+2  A: 

You forgot a 'self' in class Extension:

try:    self.AI = self.Load(self.file)

also, maybe your printing test is inaccurate. Have you tried unit tests?

möter
that shouldn't be relevent. self.AI is simply a storage for the extension's data (stores whether or not a chatroom has AI on). if the file doesnt exist then it's off for all chatrooms. fixed now though, I missed that typo.
Blazer
A: 

I solved my own question. Turns out I had an extension overwriting AI, so it wasn't the AI extension itself. thanks alot for trying to help though, guys. one up for all of you

Blazer