ext_alarm.py 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. """
  2. The Alarm Extension provides easy access to setting an application alarm to
  3. handle timing out operations. See the
  4. `Python Signal Library <https://docs.python.org/3.5/library/signal.html>`_.
  5. Requirements
  6. ------------
  7. * No external dependencies.
  8. * Only available on Unix/Linux
  9. Configuration
  10. -------------
  11. This extension does not honor any application configuration settings.
  12. Usage
  13. -----
  14. .. code-block:: python
  15. import time
  16. from cement.core.foundation import CementApp
  17. from cement.core.exc import CaughtSignal
  18. class MyApp(CementApp):
  19. class Meta:
  20. label = 'myapp'
  21. exit_on_close = True
  22. extensions = ['alarm']
  23. with MyApp() as app:
  24. try:
  25. app.run()
  26. app.alarm.set(3, "The operation timed out after 3 seconds!")
  27. # do something that takes time to operate
  28. time.sleep(5)
  29. app.alarm.stop()
  30. except CaughtSignal as e:
  31. print(e.msg)
  32. app.exit_code = 1
  33. Looks like:
  34. .. code-block:: console
  35. $ python myapp.py
  36. ERROR: The operation timed out after 3 seconds!
  37. Caught signal 14
  38. """
  39. import signal
  40. from ..utils.misc import minimal_logger
  41. LOG = minimal_logger(__name__)
  42. def alarm_handler(app, signum, frame):
  43. if signum == signal.SIGALRM:
  44. app.log.error(app.alarm.msg)
  45. class AlarmManager(object):
  46. """
  47. Lets the developer easily set and stop an alarm. If the
  48. alarm exceeds the given time it will raise ``signal.SIGALRM``.
  49. """
  50. def __init__(self, *args, **kw):
  51. super(AlarmManager, self).__init__(*args, **kw)
  52. self.msg = None
  53. def set(self, time, msg):
  54. """
  55. Set the application alarm to ``time`` seconds. If the time is
  56. exceeded ``signal.SIGALRM`` is raised.
  57. :param time: The time in seconds to set the alarm to.
  58. :param msg: The message to display if the alarm is triggered.
  59. """
  60. LOG.debug('setting application alarm for %s seconds' % time)
  61. self.msg = msg
  62. signal.alarm(int(time))
  63. def stop(self):
  64. """
  65. Stop the application alarm.
  66. """
  67. LOG.debug('stopping application alarm')
  68. signal.alarm(0)
  69. def load(app):
  70. app.catch_signal(signal.SIGALRM)
  71. app.extend('alarm', AlarmManager())
  72. app.hook.register('signal', alarm_handler)