__init__.py 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. #!/usr/bin/python2 -O
  2. '''Qubes extensions
  3. Extensions provide additional features (like application menus) found only on
  4. some systems. They may be OS- or architecture-dependent or custom-developed for
  5. particular customer.
  6. .. autoclass:: Extension
  7. :members:
  8. :show-inheritance:
  9. .. autoclass:: ExtensionPlugin
  10. :members:
  11. :show-inheritance:
  12. '''
  13. import inspect
  14. import qubes.events
  15. import qubes.plugins
  16. class ExtensionPlugin(qubes.plugins.Plugin):
  17. '''Metaclass for :py:class:`Extension`'''
  18. def __init__(cls, name, bases, dict_):
  19. super(ExtensionPlugin, cls).__init__(name, bases, dict_)
  20. cls._instance = None
  21. def __call__(cls, *args, **kwargs):
  22. if cls._instance is None:
  23. cls._instance = super(ExtensionPlugin, cls).__call__(*args, **kwargs)
  24. return cls._instance
  25. class Extension(object):
  26. '''Base class for all extensions
  27. :param qubes.Qubes app: application object
  28. '''
  29. __metaclass__ = ExtensionPlugin
  30. def __init__(self, app):
  31. self.app = app
  32. for name in dir(self):
  33. attr = getattr(self, name)
  34. if not qubes.events.ishandler(attr):
  35. continue
  36. if attr.ha_vm is not None:
  37. attr.ha_vm.add_hook(attr.ha_event, attr)
  38. else:
  39. # global hook
  40. self.app.add_hook(attr.ha_event, attr)
  41. def handler(*events, **kwargs):
  42. '''Event handler decorator factory.
  43. To hook an event, decorate a method in your plugin class with this
  44. decorator. You may hook both per-vm-class and global events.
  45. .. note::
  46. This decorator is intended only for extensions! For regular use in the
  47. core, see py:func:`qubes.events.handler`.
  48. :param str event: event type
  49. :param type vm: VM to hook (leave as None to hook all VMs)
  50. :param bool system: when :py:obj:`True`, hook is system-wide (not attached to any VM)
  51. '''
  52. def decorator(f):
  53. f.ha_events = events
  54. if kwargs.get('system', False):
  55. f.ha_vm = None
  56. elif 'vm' in kwargs:
  57. f.ha_vm = kwargs['vm']
  58. else:
  59. f.ha_vm = qubes.vm.BaseVM
  60. return f
  61. return decorator
  62. __all__ = qubes.plugins.load(__file__)