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.

scripts.py 5.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. import argparse
  2. import sys
  3. from lodel import logger
  4. from lodel.exceptions import *
  5. ##@brief Stores registered scripts
  6. __registered_scripts = dict()
  7. ##@brief LodelScript metaclass that allows to "catch" child class
  8. #declaration
  9. #
  10. #Automatic script registration on child class declaration
  11. class MetaLodelScript(type):
  12. def __init__(self, name, bases, attrs):
  13. #Here we can store all child classes of LodelScript
  14. super().__init__(name, bases, attrs)
  15. if len(bases) == 1 and bases[0] == object:
  16. return
  17. self.__register_script(name)
  18. #_action initialization
  19. if self._action is None:
  20. logger.warning("%s._action is None. Trying to use class name as \
  21. action identifier" % name)
  22. self._action = name
  23. self._action = self._action.lower()
  24. if self._description is None:
  25. self._description = self._default_description()
  26. self._parser = argparse.ArgumentParser(
  27. prog = self._prog_name(),
  28. description = self._description)
  29. self.argparser_config(self._parser)
  30. ##@brief Handles script registration
  31. #@note Script list is maitained in
  32. #lodel.plugin.admin_script.__registered_scripts
  33. def __register_script(self, name):
  34. if self._action is None:
  35. logger.warning("%s._action is None. Trying to use class name as \
  36. action identifier" % name)
  37. self._action = name
  38. self._action = self._action.lower()
  39. script_registration(self._action, self)
  40. def __str__(self):
  41. return '%s : %s' % (self._action, self._description)
  42. class LodelScript(object, metaclass=MetaLodelScript):
  43. ##@brief A string to identify the action
  44. _action = None
  45. ##@brief Script descripiton (argparse argument)
  46. _description = None
  47. ##@brief argparse.ArgumentParser instance
  48. _parser = None
  49. ##@brief No instanciation
  50. def __init__(self):
  51. raise NotImplementedError("Static class")
  52. ##@brief Virtual method. Designed to initialize arguement parser.
  53. #@param argparser ArgumentParser : Child class argument parser instance
  54. #@return MUST return the argument parser (NOT SURE ABOUT THAT !! Maybe it \
  55. #works by reference)
  56. @classmethod
  57. def argparser_config(cls, parser):
  58. raise LodelScriptError("LodelScript.argparser_config() is a pure \
  59. virtual method! MUST be implemented by ALL child classes")
  60. ##@brief Virtual method. Run the script
  61. #@return None or an integer that will be the script return code
  62. @classmethod
  63. def run(cls, args):
  64. raise LodelScriptError("LodelScript.run() is a pure virtual method. \
  65. MUST be implemented by ALL child classes")
  66. ##@brief Called by main_run() to execute a script.
  67. #
  68. #Handles argument parsing and then call LodelScript.run()
  69. @classmethod
  70. def _run(cls):
  71. args = cls._parser.parse_args()
  72. return cls.run(args)
  73. ##@brief Append action name to the prog name
  74. #@note See argparse.ArgumentParser() prog argument
  75. @classmethod
  76. def _prog_name(cls):
  77. return '%s %s' % (sys.argv[0], cls._action)
  78. ##@brief Return the default description for an action
  79. @classmethod
  80. def _default_description(cls):
  81. return "Lodel2 script : %s" % cls._action
  82. @classmethod
  83. def help_exit(cls,msg = None, return_code = 1, exit_after = True):
  84. if not (msg is None):
  85. print(msg, file=sys.stderr)
  86. cls._parser.print_help()
  87. if exit_after:
  88. exit(1)
  89. def script_registration(action_name, cls):
  90. __registered_scripts[action_name] = cls
  91. logger.info("New script registered : %s" % action_name)
  92. ##@brief Return a list containing all available actions
  93. def _available_actions():
  94. return [ act for act in __registered_scripts ]
  95. ##@brief Returns default runner argument parser
  96. def _default_parser():
  97. action_list = _available_actions()
  98. if len(action_list) > 0:
  99. action_list = ', '.join(sorted(action_list))
  100. else:
  101. action_list = 'NO SCRIPT FOUND !'
  102. parser = argparse.ArgumentParser(description = "Lodel2 script runner")
  103. parser.add_argument('-L', '--list-actions', action='store_true',
  104. default=False, help="List available actions")
  105. parser.add_argument('action', metavar="ACTION", type=str,
  106. help="One of the following actions : %s" % action_list, nargs='?')
  107. parser.add_argument('option', metavar="OPTIONS", type=str, nargs='*',
  108. help="Action options. Use %s ACTION -h to have help on a specific \
  109. action" % sys.argv[0])
  110. return parser
  111. ##@brief Main function of lodel_admin.py script
  112. #
  113. #This function take care to run the good plugins and clean sys.argv from
  114. #action name before running script
  115. #
  116. #@return DO NOT RETURN BUT exit() ONCE SCRIPT EXECUTED !!
  117. def main_run():
  118. default_parser = _default_parser()
  119. if len(sys.argv) == 1:
  120. default_parser.print_help()
  121. exit(1)
  122. args = default_parser.parse_args()
  123. if args.list_actions:
  124. print("Available actions :")
  125. for sname in sorted(__registered_scripts.keys()):
  126. print("\t- %s" % __registered_scripts[sname])
  127. exit(0)
  128. #preparing sys.argv (deleting action)
  129. action = sys.argv[1].lower()
  130. del(sys.argv[1])
  131. if action not in __registered_scripts:
  132. print("Unknow action '%s'\n" % action, file=sys.stderr)
  133. default_parser.print_help()
  134. exit(1)
  135. script = __registered_scripts[action]
  136. ret = script._run()
  137. ret = 0 if ret is None else ret
  138. exit(ret)