manager.py 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. # -*- coding: utf-8 -*-
  2. """
  3. flaskbb.plugins.manager
  4. ~~~~~~~~~~~~~~~~~~~~~~~
  5. The Plugin manager.
  6. :copyright: (c) 2014 by the FlaskBB Team.
  7. :license: BSD, see LICENSE for more details.
  8. """
  9. import os
  10. from werkzeug.utils import import_string
  11. class PluginManager(object):
  12. def __init__(self, app=None, **kwargs):
  13. """Initializes the PluginManager. It is also possible to initialize the
  14. PluginManager via a factory. For example::
  15. plugin_manager = PluginManager()
  16. plugin_manager.init_app(app)
  17. :param app: The flask application. It is needed to do plugin
  18. specific things like registering additional views or
  19. doing things where the application context is needed.
  20. :param plugin_folder: The plugin folder where the plugins resides.
  21. :param base_plugin_package: The plugins package name. It is usually the
  22. same like the plugin_folder.
  23. """
  24. if app is not None:
  25. self.init_app(app, **kwargs)
  26. # All loaded plugins
  27. self._plugins = []
  28. # All found plugins
  29. self._found_plugins = []
  30. def init_app(self, app, plugin_folder="plugins",
  31. base_plugin_package="plugins"):
  32. self.app = app
  33. self.plugin_folder = os.path.join(self.app.root_path, plugin_folder)
  34. self.base_plugin_package = ".".join(
  35. [self.app.name, base_plugin_package]
  36. )
  37. @property
  38. def plugins(self):
  39. """Returns all loaded plugins. You still need to enable them."""
  40. if not len(self._plugins):
  41. self._plugins = self.load_plugins()
  42. return self._plugins
  43. def __getitem__(self, name):
  44. for plugin in self.plugins:
  45. if plugin.name == name:
  46. return plugin
  47. raise KeyError("Plugin %s is not known" % name)
  48. def load_plugins(self):
  49. """Loads all plugins. They are still disabled.
  50. Returns a list with all loaded plugins. They should now be accessible
  51. via self.plugins.
  52. """
  53. plugins = []
  54. for plugin in self.iter_plugins():
  55. plugins.append(plugin)
  56. return plugins
  57. def iter_plugins(self):
  58. """Iterates over all possible plugins found in ``self.find_plugins()``,
  59. imports them and if the import succeeded it will yield the plugin class.
  60. """
  61. for plugin in self.find_plugins():
  62. plugin_class = import_string(plugin)
  63. if plugin_class is not None:
  64. yield plugin_class
  65. def find_plugins(self):
  66. """Find all possible plugins in the plugin folder."""
  67. for item in os.listdir(self.plugin_folder):
  68. if os.path.isdir(os.path.join(self.plugin_folder, item)) and \
  69. os.path.exists(
  70. os.path.join(self.plugin_folder, item, "__init__.py")):
  71. plugin = ".".join([self.base_plugin_package, item])
  72. # Same like from flaskbb.plugins.pluginname import __plugin__
  73. tmp = __import__(
  74. plugin, globals(), locals(), ["__plugin__"], -1
  75. )
  76. try:
  77. plugin = "{}.{}".format(plugin, tmp.__plugin__)
  78. self._found_plugins.append(plugin)
  79. except AttributeError:
  80. pass
  81. return self._found_plugins
  82. def install_plugins(self, plugins=None):
  83. """Install all or selected plugins.
  84. :param plugins: An iterable with plugins. If no plugins are passed
  85. it will try to install all plugins.
  86. """
  87. for plugin in plugins or self.plugins:
  88. with self.app.app_context():
  89. plugin().install()
  90. def uninstall_plugins(self, plugins=None):
  91. """Uninstall the plugin.
  92. :param plugins: An iterable with plugins. If no plugins are passed
  93. it will try to uninstall all plugins.
  94. """
  95. for plugin in plugins or self.plugins:
  96. with self.app.app_context():
  97. plugin().uninstall()
  98. def enable_plugins(self, plugins=None):
  99. """Enable all or selected plugins.
  100. :param plugins: An iterable with plugins. If no plugins are passed
  101. it will try to enable all plugins.
  102. """
  103. for plugin in plugins or self.plugins:
  104. with self.app.app_context():
  105. plugin().enable()
  106. def disable_plugins(self, plugins=None):
  107. """Disable all or selected plugins.
  108. :param plugins: An iterable with plugins. If no plugins are passed
  109. it will try to disable all plugins.
  110. """
  111. for plugin in plugins or self.plugins:
  112. with self.app.app_context():
  113. plugin().disable()