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.

hooks.py 3.6KB

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