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.5KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  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. ## @brief Class designed to handle a hook's callback with a priority
  6. class DecoratedWrapper(object):
  7. ##
  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 Calls 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. ## @brief Returns the string representation of the class
  21. # It shows the name and the priority of the hook
  22. def __str__(self):
  23. return "<LodelHook '%s' priority = %s>" % (
  24. self._hook.__name__, self._priority)
  25. ## @brief Decorator designed to register hook's callbacks
  26. # @ingroup lodel2_plugins
  27. #
  28. # @note Decorated functions are expected to take 3 arguments :
  29. #  - hook_name : the called hook name
  30. # - caller : the hook caller (depends on the hook)
  31. # - payload : datas depending on the hook
  32. class LodelHook(object):
  33. ## @brief Stores all hooks (DecoratedWrapper instances)
  34. _hooks = dict()
  35. ##
  36. # @param hook_name str : the name of the hook to register to
  37. # @param priority int : the hook priority (default value : None)
  38. def __init__(self, hook_name, priority = None):
  39. self._hook_name = hook_name
  40. self._priority = 0xFFFF if priority is None else priority
  41. ## @brief called just after __init__
  42. # @param hook function : the decorated function
  43. # @return the hook argument
  44. def __call__(self, hook):
  45. if not self._hook_name in self._hooks:
  46. self._hooks[self._hook_name] = list()
  47. wrapped = DecoratedWrapper(hook, self._priority)
  48. self._hooks[self._hook_name].append(wrapped)
  49. self._hooks[self._hook_name] = sorted(self._hooks[self._hook_name], key = lambda h: h._priority)
  50. return hook
  51. ## @brief Calls a hook
  52. # @param hook_name str : the hook's name
  53. # @param caller * : the hook caller (depends on the hook)
  54. # @param payload * : datas for the hook
  55. # @return modified payload
  56. @classmethod
  57. def call_hook(cls, hook_name, caller, payload):
  58. from lodel.logger import logger
  59. logger.debug("Calling hook '%s'" % hook_name)
  60. if hook_name in cls._hooks:
  61. for hook in cls._hooks[hook_name]:
  62. logger.debug("Lodel hook '%s' calls %s" % (
  63. hook_name, hook))
  64. payload = hook(hook_name, caller, payload)
  65. return payload
  66. ## @brief Fetches registered hooks
  67. # @param names list | None : optionnal filter on name (default value : None)
  68. # @return dict containing for each name a list of the hooks and their priorities
  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. # @warning REALLY NOT a good idea !
  79. # @note implemented for testing purpose
  80. @classmethod
  81. def __reset__(cls):
  82. cls._hooks = dict()