Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I discover classes in a specific package in python?

I have a package of plug-in style modules. It looks like this:

/Plugins 
/Plugins/__init__.py
/Plugins/Plugin1.py
/Plugins/Plugin2.py 
etc...

Each .py file contains a class that derives from PluginBaseClass. So I need to list every module in the Plugins package and then search for any classes that implement PluginBaseClass. Ideally I want to be able to do something like this:

for klass in iter_plugins(project.Plugins):
    action = klass()
    action.run()

I have seen some other answers out there, but my situation is different. I have an actual import to the base package (ie: import project.Plugins) and I need to find the classes after discovering the modules.

like image 831
Jason Webb Avatar asked Aug 17 '10 21:08

Jason Webb


1 Answers

Scanning modules isn't good idea. If you need class registry you should look at metaclasses or use existing solutions like zope.interface. Simple solution through metaclasses may look like that:

from functools import reduce
class DerivationRegistry(type):
    def __init__(cls,name,bases,cls_dict):
        type.__init__(cls,name,bases,cls_dict)
        cls._subclasses = set()
        for base in bases:
            if isinstance(base,DerivationRegistry):
                base._subclasses.add(cls)

    def getSubclasses(cls):
        return reduce( set.union,
                       ( succ.getSubclasses() for succ  in cls._subclasses if isinstance(succ,DerivationRegistry)),
                       cls._subclasses)

class Base(object):
    __metaclass__ = DerivationRegistry

class Cls1(object):
    pass

class Cls2(Base):
    pass

class Cls3(Cls2,Cls1):
    pass

class Cls4(Cls3):
    pass

print(Base.getSubclasses())
like image 119
Odomontois Avatar answered Oct 15 '22 12:10

Odomontois