No Description
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.

core_scripts.py 9.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  1. import operator
  2. import shutil
  3. import tempfile
  4. import os, os.path
  5. from lodel.context import LodelContext
  6. LodelContext.expose_modules(globals(), {
  7. 'lodel.plugin.scripts': 'lodel_script',
  8. 'lodel.logger': 'logger'})
  9. ##@package lodel.plugin.core_scripts
  10. #@brief Lodel2 internal scripts declaration
  11. #@ingroup lodel2_plugins
  12. #@ingroup lodel2_script
  13. ##@brief Implements lodel_admin.py list-plugins action
  14. #@ingroup lodel2_plugins
  15. #@ingroup lodel2_script
  16. #
  17. class ListPlugins(lodel_script.LodelScript):
  18. _action = 'plugins-list'
  19. _description = "List all installed plugins"
  20. @classmethod
  21. def argparser_config(cls, parser):
  22. parser.add_argument('-v', '--verbose',
  23. help="Display more informations on installed plugins",
  24. action='store_true')
  25. parser.add_argument('-c', '--csv',
  26. help="Format output in CSV format",
  27. action='store_true')
  28. @classmethod
  29. def run(cls, args):
  30. import lodel.plugin.plugins
  31. from lodel.plugin.plugins import Plugin
  32. if args.verbose:
  33. #_discover do not returns duplicated names
  34. tmp_plist = Plugin._discover(lodel.plugin.plugins.PLUGINS_PATH)
  35. plist = []
  36. #ordering the list by plugin's name
  37. for pname in sorted(set([d['name'] for d in tmp_plist])):
  38. for pinfos in tmp_plist:
  39. if pinfos['name'] == pname:
  40. plist.append(pinfos)
  41. else:
  42. pdict = Plugin.discover()
  43. #casting to a list ordered by names
  44. plist = []
  45. for pname in sorted(pdict.keys()):
  46. plist.append(pdict[pname])
  47. if args.csv:
  48. if args.verbose:
  49. res = "name,version,path\n"
  50. fmt = "%s,%s,%s\n"
  51. else:
  52. res = "name,version\n"
  53. fmt = "%s,%s\n"
  54. else:
  55. res = "Installed plugins list :\n"
  56. if args.verbose:
  57. fmt = "\t- %s(%s) in %s\n"
  58. else:
  59. fmt = "\t- %s(%s)\n"
  60. for pinfos in plist:
  61. if args.verbose:
  62. res += fmt % (
  63. pinfos['name'], pinfos['version'], pinfos['path'])
  64. else:
  65. res += fmt % (pinfos['name'], pinfos['version'])
  66. print(res)
  67. ##@brief Handle install & uninstall of lodel plugins
  68. class PluginManager(lodel_script.LodelScript):
  69. _action = 'plugins'
  70. _description = "Install/Uninstall plugins"
  71. @classmethod
  72. def argparser_config(cls, parser):
  73. parser.add_argument('-u', '--uninstall',
  74. help="Uninstall specified plugin",
  75. action='store_true')
  76. parser.add_argument('-c', '--clean',
  77. help="Uninstall duplicated plugins with smallest version number",
  78. action="store_true")
  79. parser.add_argument('-n', '--plugin-name', nargs='*',
  80. default = list(),
  81. help="Indicate a plugin name to uninstall",
  82. type=str)
  83. parser.add_argument('-f', '--file', nargs='*',
  84. default = list(),
  85. help="Specify a tarball containing a plugin to install",
  86. type=str)
  87. parser.add_argument('-d', '--directory', nargs='*',
  88. default = list(),
  89. help="Specify a plugin by its directory",
  90. type=str)
  91. @classmethod
  92. def run(cls, args):
  93. if args.clean:
  94. if args.uninstall or len(args.directory) > 0 or len(args.file) > 0:
  95. raise RuntimeError("When using -c --clean option you can \
  96. only use option -n --name to clean plugins with specified names")
  97. return cls.clean(args)
  98. if args.uninstall:
  99. return cls.uninstall(args)
  100. return cls.install(args)
  101. ##@brief Handles plugins install
  102. @classmethod
  103. def install(cls, args):
  104. import lodel.plugin.plugins
  105. from lodel.plugin.plugins import Plugin
  106. from lodel.plugin.exceptions import PluginError
  107. if len(args.plugin_name) > 0:
  108. raise RuntimeError("Unable to install a plugin from its name !\
  109. We do not know where to find it...")
  110. plist = Plugin.discover()
  111. errors = dict()
  112. if len(args.file) > 0:
  113. raise NotImplementedError("Not supported yet")
  114. plugins_infos = {}
  115. for cur_dir in args.directory:
  116. try:
  117. res = Plugin.dir_is_plugin(cur_dir, assert_in_package = False)
  118. if res is False:
  119. errors[cur_dir] = PluginError("Not a plugin")
  120. else:
  121. plugins_infos[res['name']] = res
  122. except Exception as e:
  123. errors[cur_dir] = e
  124. #Abording because of previous errors
  125. if len(errors) > 0:
  126. msg = "Abording installation because of following errors :\n"
  127. for path, expt in errors.items():
  128. msg += ("\t- For path '%s' : %s\n" % (path, expt))
  129. raise RuntimeError(msg)
  130. #No errors continuing to install
  131. for pname, pinfos in plugins_infos.items():
  132. if pname in plist:
  133. #Found an installed plugin with the same name
  134. #Cehcking both versions
  135. if plist[pname]['version'] == pinfos['version']:
  136. errors[pinfos['path']] = 'Abording installation of %s \
  137. found in %s because it seems to be allready installed in %s' % (
  138. pname, pinfos['path'], plist[pname]['path'])
  139. continue
  140. if plist[pname]['version'] > pinfos['version']:
  141. errors[pinfos['path']] = 'Abording installation of %s \
  142. found in %s because the same plugins with a greater version seems to be \
  143. installed in %s' % (pname, pinfos['path'], plist[pname]['path'])
  144. continue
  145. logger.info("Found a plugin with the same name but with an \
  146. inferior version. Continuing to install")
  147. #Checking that we can safely copy our plugin
  148. dst_path = os.path.join(lodel.plugin.plugins.PLUGINS_PATH,
  149. os.path.basename(os.path.dirname(pinfos['path'])))
  150. orig_path = dst_path
  151. if os.path.isdir(dst_path):
  152. dst_path = tempfile.mkdtemp(
  153. prefix = os.path.basename(dst_path)+'_',
  154. dir = lodel.plugin.plugins.PLUGINS_PATH)
  155. logger.warning("A plugin allready exists in %s. Installing \
  156. in %s" % (orig_path, dst_path))
  157. shutil.rmtree(dst_path)
  158. #Installing the plugin
  159. shutil.copytree(pinfos['path'], dst_path, symlinks = False)
  160. print("%s(%s) installed in %s" % (
  161. pname, pinfos['version'], dst_path))
  162. if len(errors) > 0:
  163. msg = "Following errors occurs during instalation process :\n"
  164. for path, error_msg in errors.items():
  165. msg += "\t- For '%s' : %s" % (path, error_msg)
  166. print(msg)
  167. ##@brief Handles plugins uninstall
  168. @classmethod
  169. def uninstall(cls, args):
  170. raise NotImplementedError("Not yet implemented")
  171. ##@brief Handles plugins clean
  172. @classmethod
  173. def clean(cls, args):
  174. import lodel.plugin.plugins
  175. from lodel.plugin.plugins import Plugin
  176. if len(args.file) > 0:
  177. raise RuntimeError("Cannot specify plugins to uninstall using \
  178. -f --file option. You have to use -d --directory or -n --name")
  179. if len(args.plugin_name) > 0:
  180. names = args.plugin_name
  181. else:
  182. names = list(Plugin.discover().keys())
  183. #_dicover do not remove duplicated names
  184. full_list = Plugin._discover(lodel.plugin.plugins.PLUGINS_PATH)
  185. #Casting into a dict with list of plugins infos
  186. pdict = dict()
  187. for pinfos in full_list:
  188. if pinfos['name'] in names:
  189. if pinfos['name'] in pdict:
  190. pdict[pinfos['name']].append(pinfos)
  191. else:
  192. pdict[pinfos['name']] = [pinfos]
  193. to_clean = list()
  194. clean_count = 0
  195. for pname, pinfos_l in pdict.items():
  196. if len(pinfos_l) > 1:
  197. #There are some plugins to clean
  198. tmp_l = sorted(pinfos_l, key=lambda item: item['version'])
  199. to_clean += tmp_l[:-1]
  200. msg = "Found %s(%s). Cleaning " % (
  201. pname, tmp_l[-1]['version'])
  202. for pinfos in to_clean:
  203. clean_count += 1
  204. str_info = '%s(%s)' % (pname, pinfos['version'])
  205. msg += "%s, " % (str_info)
  206. shutil.rmtree(pinfos['path'])
  207. print(msg)
  208. if clean_count > 0:
  209. print("%d plugins were uninstalled" % clean_count)
  210. else:
  211. print("Allready clean")
  212. ##@brief Implements lodel_admin.py **hooks-list** action
  213. #@ingroup lodel2_script
  214. #@ingroup lodel2_hooks
  215. class ListHooks(lodel_script.LodelScript):
  216. _action = 'hooks-list'
  217. _description = 'Generate a list of registered hooks once instance started'
  218. @classmethod
  219. def argparser_config(cls, parser):
  220. pass
  221. @classmethod
  222. def run(cls, args):
  223. import loader
  224. loader.start()
  225. from lodel.plugin.hooks import LodelHook
  226. hlist = LodelHook.hook_list()
  227. print("Registered hooks : ")
  228. for name in sorted(hlist.keys()):
  229. print("\t- %s is registered by :" % name)
  230. for hfun, priority in hlist[name]:
  231. msg = "\t\t- {modname}.{funname} with priority : {priority}"
  232. print(msg.format(
  233. modname = hfun.__module__,
  234. funname = hfun.__name__,
  235. priority = priority))
  236. print("\n")