pluginmanager.py 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. import imp
  2. import glob
  3. import os
  4. import sys
  5. import inspect
  6. from plugintemplates import *
  7. class PluginManager(object):
  8. def __init__(self, plugindir, logger):
  9. self.logger = logger
  10. self.plugindir = plugindir
  11. self.plugins = []
  12. def loadPlugins(self, baseclass):
  13. self.logger.logInfo("* Loading plugins started")
  14. if self.plugindir is None:
  15. raise Exception('Invalid plugins directory')
  16. directory = os.path.abspath(self.plugindir)
  17. if not os.path.isdir(directory):
  18. self.logger.logWarn(
  19. "! Plugins directory '%s' doesn't exists."
  20. "Plugins not loaded." % directory
  21. )
  22. return 0
  23. plugins = glob.glob(directory + "/*.py")
  24. self.logger.logInfo("** Checking plugins in %s" % directory)
  25. if directory not in sys.path:
  26. sys.path.insert(0, directory)
  27. for p in plugins:
  28. try:
  29. name = p.split("/")[-1]
  30. name = name.split(".py")[0]
  31. if name.startswith('_'):
  32. continue
  33. self.logger.logDebug("** Inspecting file '%s.py'" % name)
  34. f, file, desc = imp.find_module(name, [directory])
  35. plugin = __import__(name)
  36. for k, v in inspect.getmembers(plugin):
  37. if not inspect.isclass(v):
  38. continue
  39. if k.startswith('_'):
  40. continue
  41. if not issubclass(v, baseclass) or v is baseclass:
  42. continue
  43. instance = v(self.logger)
  44. # fixme, use a plugin meta name ?
  45. self.logger.logInfo("** Adding plugin '%s'" % k)
  46. self.plugins.append((k, instance))
  47. except Exception as e:
  48. self.logger.logError("!-- failed to load: %s" % p)
  49. self.logger.logError("!-- error: %s " % e)
  50. self.logger.logInfo("* Loading plugins done")
  51. return len(self.plugins)
  52. def processPluginFunction(self, functionname, *args):
  53. plugins = []
  54. self.logger.logInfo("* %s processing started" % functionname)
  55. # get the priority of the plugin function
  56. for (name, i) in self.plugins:
  57. if hasattr(i, 'prio' + functionname):
  58. prio = getattr(i, 'prio' + functionname)
  59. else:
  60. prio = 9999
  61. plugins.append((functionname, prio, name, i))
  62. # sort the plugins on function name and prio
  63. sortedlist = sorted(plugins, key=lambda a: (a[0], a[1]))
  64. retval = MP_CONTINUE,
  65. for (fname, prio, cname, i) in sortedlist:
  66. if (fname != functionname):
  67. continue
  68. try:
  69. self.logger.logInfo("** Plugin '%s.%s' priority (%d)" % (
  70. cname, fname, prio
  71. ))
  72. retval = getattr(i, fname)(*args)
  73. self.logger.logDebug("** Plugin '%s.%s' return result %s" % (
  74. cname, fname, repr(retval)
  75. ))
  76. if (type(retval) == int or type(retval) == long):
  77. self.logger.logDebug(
  78. "!- Plugin '%s.%s' convert return value type "
  79. "'%s' to a 'tuple'" % (cname, fname, type(retval))
  80. )
  81. retval = retval,
  82. if (type(retval) != tuple):
  83. self.logger.logWarn(
  84. "!- Plugin '%s.%s' returned a wrong"
  85. "return value type '%s' except 'tuple'. "
  86. "Fallback on defaults" % (cname, fname, type(retval))
  87. )
  88. retval = MP_CONTINUE,
  89. elif (type(retval[0]) != int and type(retval[0]) != long):
  90. self.logger.logWarn(
  91. "!- Plugin '%s.%s' returned a wrong return value "
  92. "type '%s' expect 'int' or 'long' type. Fallback "
  93. "on defaults" % (cname, fname, type(retval[0]))
  94. )
  95. retval = MP_CONTINUE,
  96. self.logger.logInfo(
  97. "** Plugin '%s.%s' returncode %d" % (
  98. cname, fname, retval[0]
  99. )
  100. )
  101. except NotImplementedError as e:
  102. # Most likely the function is not implemented
  103. self.logger.logDebug("!---------- %s" % e)
  104. except Exception as e:
  105. self.logger.logError("!-- error: %s " % e)
  106. self.logger.logError(
  107. "!- Plugin '%s.%s' call ignored please "
  108. "check the plugin" % (cname, fname)
  109. )
  110. retval = MP_CONTINUE,
  111. if (retval[0] == MP_EXIT):
  112. break
  113. self.logger.logInfo("* %s processing done" % functionname)
  114. return retval