views:

439

answers:

2

I'm writing a plugin system for my program and I can't get past one thing:

class ThingLoader(object):
'''
Loader class
'''

    def loadPlugins(self):
        '''
        Get all the plugins from plugins folder
        '''
        from diones.thingpad.plugin.IntrospectionHelper import loadClasses

        classList=loadClasses('./plugins', IPlugin)#Gets a list of 
        #plugin classes
        self.plugins={}#Dictionary that should be filled with 
        #touples of objects and theirs states, activated, deactivated.
        classList[0](self)#Runs nicelly
        foo = classList[1]
        print foo#prints <class 'TestPlugin.TestPlugin'>
        foo(self)#Raise an exception

The test plugin looks like this:

import diones.thingpad.plugin.IPlugin as plugin
   class TestPlugin(plugin.IPlugin):
       '''
     classdocs
    '''
    def __init__(self, loader):
        self.name='Test Plugin'
        super(TestPlugin, self).__init__(loader)

Now the IPlugin looks like this:

class IPlugin(object):
    '''
    classdocs
    '''
    name=''
    def __init__(self, loader):
        self.loader=loader
    def activate(self):
        pass

All the IPlugin classes works flawlessy by them selves, but when called by ThingLoader the program gets an exception:

File "./plugins\TestPlugin.py", line 13, in __init__
    super(TestPlugin, self).__init__(loader) NameError: 
global name 'super' is not defined

I looked all around and I simply don't know what is going on.

+17  A: 

‘super’ is a builtin. Unless you went out of your way to delete builtins, you shouldn't ever see “global name 'super' is not defined”.

I'm looking at your user web link where there is a dump of IntrospectionHelper. It's very hard to read without the indentation, but it looks like you may be doing exactly that:

built_in_list = ['__builtins__', '__doc__', '__file__', '__name__']

for i in built_in_list:
    if i in module.__dict__:
        del module.__dict__[i]

That's the original module dict you're changing there, not an informational copy you are about to return! Delete these members from a live module and you can expect much more than ‘super’ to break.

It's very hard to keep track of what that module is doing, but my reaction is there is far too much magic in it. The average Python program should never need to be messing around with the import system, sys.path, and monkey-patching __magic__ module members. A little bit of magic can be a neat trick, but this is extremely fragile. Just off the top of my head from browsing it, the code could be broken by things like:

  • name clashes with top-level modules
  • any use of new-style classes
  • modules supplied only as compiled bytecode
  • zipimporter

From the incredibly round-about functions like getClassDefinitions, extractModuleNames and isFromBase, it looks to me like you still have quite a bit to learn about the basics of how Python works. (Clues: getattr, module.__name__ and issubclass, respectively.)

In this case now is not the time to be diving into import magic! It's hard. Instead, do things The Normal Python Way. It may be a little more typing to say at the bottom of a package's mypackage/__init__.py:

from mypackage import fooplugin, barplugin, bazplugin
plugins= [fooplugin.FooPlugin, barplugin.BarPlugin, bazplugin.BazPlugin]

but it'll work and be understood everywhere without relying on a nest of complex, fragile magic.

Incidentally, unless you are planning on some in-depth multiple inheritance work (and again, now may not be the time for that), you probably don't even need to use super(). The usual “IPlugin.__init__(self, ...)” method of calling a known superclass is the straightforward thing to do; super() is not always “the newer, better way of doing things” and there are things you should understand about it before you go charging into using it.

bobince
+1 for actually following a user page link to locate a copy of the code, and then debugging it. This must be one of the most thoroughly-researched answers ever.
DNS
He should get a prize out of that!
Diones
It must've been very enjoyable to write this answer. +1
nosklo
A: 

Unless you're running a version of Python earlier than 2.2 (pretty unlikely), super() is definitely a built-in function (available in every scope, and without importing anything).

May be worth checking your version of Python (just start up the interactive prompt by typing python at the command line).

Triptych