signal.py 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. # -*- coding: utf-8 -*-
  2. """
  3. Created on Mon Mar 11 18:39:13 2013
  4. @author Vaclav Petras <wenzeslaus gmail.com>
  5. """
  6. from grass.pydispatch import dispatcher
  7. def _islambda(function):
  8. """Tests if object is a lambda function.
  9. Should work on the most of Python implementations where name of lambda
  10. function is not unique.
  11. """
  12. return isinstance(function, type(lambda: None)) and function.__name__== (lambda: None).__name__
  13. class Signal(object):
  14. """
  15. >>> signal1 = Signal('signal1')
  16. >>> def handler1():
  17. ... print "from handler1"
  18. >>> signal1.connect(handler1)
  19. >>> signal2 = Signal('signal2')
  20. >>> def handler2(text):
  21. ... print "handler2: %s" % text
  22. >>> signal2.connect(handler2)
  23. >>> signal1.emit()
  24. from handler1
  25. >>> signal2.emit(text="Hello")
  26. handler2: Hello
  27. >>> import sys
  28. >>> signal2.connect(lambda text: sys.stdout.write('lambda handler: %s\\n' % text))
  29. >>> signal2.emit(text="Hi")
  30. handler2: Hi
  31. lambda handler: Hi
  32. >>> def handler3():
  33. ... print "from handler3"
  34. >>> signal2.connect(handler3)
  35. >>> signal2.emit(text="Ciao")
  36. handler2: Ciao
  37. lambda handler: Ciao
  38. from handler3
  39. >>> signal3 = Signal('signal3')
  40. >>> signal3.connect(handler3)
  41. >>> signal1.connect(signal3)
  42. >>> signal1.emit()
  43. from handler1
  44. from handler3
  45. >>> signal3.disconnect(handler3)
  46. >>> signal1.emit()
  47. from handler1
  48. >>> signal2.disconnect(handler2)
  49. >>> signal2.disconnect(handler3)
  50. >>> signal2.emit(text='Hello')
  51. lambda handler: Hello
  52. """
  53. def __init__(self, name):
  54. self._name = name
  55. def connect(self, handler, weak=None):
  56. """
  57. >>> signal1 = Signal('signal1')
  58. >>> import sys
  59. >>> signal1.connect(lambda: sys.stdout.write('will print\\n'))
  60. >>> signal1.connect(lambda: sys.stdout.write('will print\\n'), weak=False)
  61. >>> signal1.connect(lambda: sys.stdout.write('will not print'), weak=True)
  62. >>> signal1.emit()
  63. will print
  64. will print
  65. """
  66. if weak is None:
  67. if _islambda(handler):
  68. weak = False
  69. else:
  70. weak = True
  71. dispatcher.connect(receiver=handler, signal=self, weak=weak)
  72. def disconnect(self, handler, weak=True):
  73. dispatcher.disconnect(receiver=handler, signal=self, weak=weak)
  74. def emit(self, *args, **kwargs):
  75. dispatcher.send(signal=self, *args, **kwargs)
  76. def __call__(self, *arguments, **named):
  77. if 'signal' in named:
  78. del named['signal']
  79. self.emit(*arguments, **named)
  80. if __name__ == '__main__':
  81. import doctest
  82. doctest.testmod()