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.

hooks.py 3.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. #-*- coding: utf-8 -*-
  2. import os
  3. import copy
  4. from importlib.machinery import SourceFileLoader
  5. ##@brief Class designed to handle a hook's callback with a priority
  6. class DecoratedWrapper(object):
  7. ##@brief Constructor
  8. # @param hook function : the function to wrap
  9. # @param priority int : the callbacl priority
  10. def __init__(self, hook, priority):
  11. self._priority = priority
  12. self._hook = hook
  13. ##@brief Call the callback
  14. # @param hook_name str : The name of the called hook
  15. # @param caller * : The caller (depends on the hook)
  16. # @param payload * : Datas that depends on the hook
  17. # @return modified payload
  18. def __call__(self, hook_name, caller, payload):
  19. return self._hook(hook_name, caller, payload)
  20. def __str__(self):
  21. return "<LodelHook '%s' priority = %s>" % (
  22. self._hook.__name__, self._priority)
  23. ##@brief Decorator designed to register hook's callbacks
  24. #@ingroup lodel2_plugins
  25. #
  26. # @note Decorated functions are expected to take 3 arguments :
  27. #  - hook_name : the called hook name
  28. # - caller : the hook caller (depends on the hook)
  29. # - payload : datas depending on the hook
  30. class LodelHook(object):
  31. ##@brief Stores all hooks (DecoratedWrapper instances)
  32. _hooks = dict()
  33. ##@brief Decorator constructor
  34. # @param hook_name str : the name of the hook to register to
  35. # @param priority int : the hook priority
  36. def __init__(self, hook_name, priority = None):
  37. self._hook_name = hook_name
  38. self._priority = 0xFFFF if priority is None else priority
  39. ##@brief called just after __init__
  40. # @param hook function : the decorated function
  41. # @return the hook argument
  42. def __call__(self, hook):
  43. if not self._hook_name in self._hooks:
  44. self._hooks[self._hook_name] = list()
  45. wrapped = DecoratedWrapper(hook, self._priority)
  46. self._hooks[self._hook_name].append(wrapped)
  47. self._hooks[self._hook_name] = sorted(self._hooks[self._hook_name], key = lambda h: h._priority)
  48. return hook
  49. ##@brief Call hooks
  50. # @param hook_name str : the hook's name
  51. # @param caller * : the hook caller (depends on the hook)
  52. # @param payload * : datas for the hook
  53. # @param cls
  54. # @return modified payload
  55. @classmethod
  56. def call_hook(cls, hook_name, caller, payload):
  57. from lodel import logger
  58. logger.info("Calling hook '%s'" % hook_name)
  59. if hook_name in cls._hooks:
  60. for hook in cls._hooks[hook_name]:
  61. logger.info("Lodel hook '%s' calls %s" % (
  62. hook_name, hook))
  63. payload = hook(hook_name, caller, payload)
  64. return payload
  65. ##@brief Fetch registered hooks
  66. # @param names list | None : optionnal filter on name
  67. # @param cls
  68. # @return a list of functions
  69. @classmethod
  70. def hook_list(cls, names = None):
  71. res = None
  72. if names is not None:
  73. res = { name: copy.copy(cls._hooks[name]) for name in cls._hooks if name in names}
  74. else:
  75. res = copy.copy(cls._hooks)
  76. return { name: [(hook._hook, hook._priority) for hook in hooks] for name, hooks in res.items() }
  77. ##@brief Unregister all hooks
  78. # @param cls
  79. # @warning REALLY NOT a good idea !
  80. # @note implemented for testing purpose
  81. @classmethod
  82. def __reset__(cls):
  83. cls._hooks = dict()