Nenhuma descrição
Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

hooks.py 3.0KB

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