Brak opisu
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

plugins.py 3.5KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. #-*- coding: utf-8 -*-
  2. import os.path
  3. from importlib.machinery import SourceFileLoader, SourcelessFileLoader
  4. ## @package lodel.plugins Lodel2 plugins management
  5. #
  6. # Lodel2 plugins are stored in directories
  7. # A typicall lodel2 plugin directory structure looks like :
  8. # - {{__init__.py}}} containing informations like full_name, authors, licence etc.
  9. # - main.py containing hooks registration etc
  10. # - confspec.py containing a configuration specification dictionary named CONFSPEC
  11. ##@brief The package in wich we will load plugins modules
  12. VIRTUAL_PACKAGE_NAME = 'lodel.plugins_pkg'
  13. CONFSPEC_FILENAME = 'confspec.py'
  14. MAIN_FILENAME = 'main.py'
  15. CONFSPEC_VARNAME = 'CONFSPEC'
  16. class PluginError(Exception):
  17. pass
  18. class Plugins(object):
  19. ##@brief Stores plugin directories paths
  20. _plugin_directories = None
  21. ##@brief Optimisation cache storage for plugin paths
  22. _plugin_paths = dict()
  23. def __init__(self): # may be useless
  24. self.started()
  25. ##@brief Given a plugin name returns the plugin path
  26. # @param plugin_name str : The plugin name
  27. # @return the plugin directory path
  28. @classmethod
  29. def plugin_path(cls, plugin_name):
  30. cls.started()
  31. try:
  32. return cls._plugin_paths[plugin_name]
  33. except KeyError:
  34. pass
  35. path = None
  36. for cur_path in cls._plugin_directories:
  37. plugin_path = os.path.join(cur_path, plugin_name)+'/'
  38. if os.path.isdir(plugin_path):
  39. return plugin_path
  40. raise NameError("No plugin named '%s'" % plugin_name)
  41. ##@brief Fetch a confspec given a plugin_name
  42. # @param plugin_name str : The plugin name
  43. # @return a dict of conf spec
  44. # @throw PluginError if plugin_name is not valid
  45. @classmethod
  46. def get_confspec(cls, plugin_name):
  47. cls.started()
  48. plugin_path = cls.plugin_path(plugin_name)
  49. plugin_module = '%s.%s' % ( VIRTUAL_PACKAGE_NAME,
  50. plugin_name)
  51. conf_spec_module = plugin_module + '.confspec'
  52. conf_spec_source = plugin_path + CONFSPEC_FILENAME
  53. try:
  54. loader = SourceFileLoader(conf_spec_module, conf_spec_source)
  55. confspec_module = loader.load_module()
  56. except ImportError:
  57. raise PluginError("Failed to load plugin '%s'. It seems that the plugin name is not valid" % plugin_name)
  58. return getattr(confspec_module, CONFSPEC_VARNAME)
  59. ##@brief Load a module to register plugin's hooks
  60. # @param plugin_name str : The plugin name
  61. @classmethod
  62. def load_plugin(cls, plugin_name):
  63. cls.started()
  64. plugin_path = cls.plugin_path(plugin_name)
  65. plugin_module = '%s.%s' % ( VIRTUAL_PACKAGE_NAME,
  66. plugin_name)
  67. main_module = plugin_module + '.main'
  68. main_source = plugin_path + MAIN_FILENAME
  69. try:
  70. loader = SourceFileLoader(main_module, main_source)
  71. main_module = loader.load_module()
  72. except ImportError:
  73. raise PluginError("Failed to load plugin '%s'. It seems that the plugin name is not valid" % plugin_name)
  74. ##@brief Bootstrap the Plugins class
  75. @classmethod
  76. def bootstrap(cls, plugins_directories):
  77. cls._plugin_directories = plugins_directories
  78. @classmethod
  79. def started(cls, raise_if_not = True):
  80. res = cls._plugin_directories is not None
  81. if raise_if_not and not res:
  82. raise RuntimeError("Class Plugins is not initialized")