Finding and loading subclasses dynamically. issubclass(x, base_plugin.Plugin) fails.
Peter Otten
__peter__ at web.de
Sun Aug 29 07:06:33 EDT 2010
Osmo Maatta wrote:
> Hello,
>
> Sub class test fails.
> ======================
> I have a program that needs to load plugin-classes during runtime.
>
> The program has these subdirectories (modules).
>
> $ tree
> .
> `-- test.py
> |
> |-- plugins
> | |-- base_plugin.py
> | |-- base_plugin.pyc
> | |-- __init__.py
> | `-- oca
> | |-- __init__.py
> | |-- open_clipart.py
>
>
> The plugins (sub directory) contains one or more plugin modules, in this
> test-case there is only one; oca/open_clipart.py.
>
> The plugins/base_plugin.py (contains class Plugin()) is a base class of
> all plugins.
>
> I want to list and load all plugin-classes (that inherit from
> base_plugin.Plugin). I have a Python code that successfully browses the
> plugins, but the the test issubclass(x, base_plugin.Plugin) fails.
>
> Please see this Python code:
> http://futuredesktop.com/tmp/test6.tar.gz
>
> Why the issubclass(entry, cls) test fails?
base_plugin.py is imported twice, once as plugins.base_plugin and a second
time as base_plugin. You can see that when you add a bit more debug code
into your test.py:
--- a/test.py Sun Aug 29 12:57:25 2010 +0200
+++ b/test.py Sun Aug 29 12:58:25 2010 +0200
@@ -24,6 +24,8 @@
#print "entry's class<%s> -- cls's class=<%s>" %
(obj1.get_name(), obj2.get_name(), )
print "Check %s against %s" % (entry, cls, )
+ print entry.__bases__
+ print cls
if issubclass(entry, cls):
print "Found a subclass: " + key
$ python test.py
Importing plugins.base_plugin
Importing plugins.oca.open_clipart
Check <class 'plugins.oca.open_clipart.OpenClipArt'> against <class
'plugins.base_plugin.Plugin'>
(<class 'base_plugin.Plugin'>,)
<class 'plugins.base_plugin.Plugin'>
Got subclasses= []
The solution is to remove all sys.path gymnastics and to adapt your import
statements accordingly:
$ hg diff
diff -r 9fe6129ba8fc plugins/oca/open_clipart.py
--- a/plugins/oca/open_clipart.py Sun Aug 29 12:51:51 2010 +0200
+++ b/plugins/oca/open_clipart.py Sun Aug 29 13:02:55 2010 +0200
@@ -2,9 +2,7 @@
import os
import threading, thread
-sys.path.insert(0, '..')
-import base_plugin
-#sys.path.insert(0, '../..')
+from .. import base_plugin
# ------------------------------------------
# class OpenClipArt
diff -r 9fe6129ba8fc test.py
--- a/test.py Sun Aug 29 12:51:51 2010 +0200
+++ b/test.py Sun Aug 29 13:02:55 2010 +0200
@@ -1,7 +1,6 @@
import os, sys
import inspect
-sys.path.insert(0, "plugins")
# Thanks to http://www.luckydonkey.com/2008/01/02/python-style-plugins-
made-easy/
def find_subclasses(path, cls):
$ python test.py
Importing plugins.base_plugin
Importing plugins.oca.open_clipart
Check <class 'plugins.oca.open_clipart.OpenClipArt'> against <class
'plugins.base_plugin.Plugin'>
Found a subclass: OpenClipArt
Got subclasses= [<class 'plugins.oca.open_clipart.OpenClipArt'>]
You should also remove the __init__.py from the folder containing test.py
which is just begging for the same problem when you import your plugins as
test.plugins.whatever.
Peter
More information about the Python-list
mailing list