Ei kuvausta
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.1KB

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