test_signals.py 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. import re
  2. from unittest import mock
  3. import pytest
  4. from aiosignal import Signal
  5. class Owner:
  6. def __repr__(self) -> str:
  7. return "<Owner 0xdeadbeef>"
  8. @pytest.fixture
  9. def owner() -> Owner:
  10. return Owner()
  11. @pytest.mark.asyncio
  12. async def test_add_signal_handler_not_a_callable(owner: Owner) -> None:
  13. callback = True
  14. signal = Signal(owner)
  15. signal.append(callback)
  16. signal.freeze()
  17. with pytest.raises(TypeError):
  18. await signal.send()
  19. @pytest.mark.asyncio
  20. async def test_function_signal_dispatch_kwargs(owner: Owner) -> None:
  21. signal = Signal(owner)
  22. kwargs = {"foo": 1, "bar": 2}
  23. callback_mock = mock.Mock()
  24. async def callback(**kwargs):
  25. callback_mock(**kwargs)
  26. signal.append(callback)
  27. signal.freeze()
  28. await signal.send(**kwargs)
  29. callback_mock.assert_called_once_with(**kwargs)
  30. @pytest.mark.asyncio
  31. async def test_function_signal_dispatch_args_kwargs(owner: Owner) -> None:
  32. signal = Signal(owner)
  33. args = {"a", "b"}
  34. kwargs = {"foo": 1, "bar": 2}
  35. callback_mock = mock.Mock()
  36. async def callback(*args, **kwargs):
  37. callback_mock(*args, **kwargs)
  38. signal.append(callback)
  39. signal.freeze()
  40. await signal.send(*args, **kwargs)
  41. callback_mock.assert_called_once_with(*args, **kwargs)
  42. @pytest.mark.asyncio
  43. async def test_non_coroutine(owner: Owner) -> None:
  44. signal = Signal(owner)
  45. kwargs = {"foo": 1, "bar": 2}
  46. callback = mock.Mock()
  47. signal.append(callback)
  48. signal.freeze()
  49. with pytest.raises(TypeError):
  50. await signal.send(**kwargs)
  51. def test_setitem(owner: Owner) -> None:
  52. signal = Signal(owner)
  53. m1 = mock.Mock()
  54. signal.append(m1)
  55. assert signal[0] is m1
  56. m2 = mock.Mock()
  57. signal[0] = m2
  58. assert signal[0] is m2
  59. def test_delitem(owner: Owner) -> None:
  60. signal = Signal(owner)
  61. m1 = mock.Mock()
  62. signal.append(m1)
  63. assert len(signal) == 1
  64. del signal[0]
  65. assert len(signal) == 0
  66. def test_cannot_append_to_frozen_signal(owner: Owner) -> None:
  67. signal = Signal(owner)
  68. m1 = mock.Mock()
  69. m2 = mock.Mock()
  70. signal.append(m1)
  71. signal.freeze()
  72. with pytest.raises(RuntimeError):
  73. signal.append(m2)
  74. assert list(signal) == [m1]
  75. def test_cannot_setitem_in_frozen_signal(owner: Owner) -> None:
  76. signal = Signal(owner)
  77. m1 = mock.Mock()
  78. m2 = mock.Mock()
  79. signal.append(m1)
  80. signal.freeze()
  81. with pytest.raises(RuntimeError):
  82. signal[0] = m2
  83. assert list(signal) == [m1]
  84. def test_cannot_delitem_in_frozen_signal(owner: Owner) -> None:
  85. signal = Signal(owner)
  86. m1 = mock.Mock()
  87. signal.append(m1)
  88. signal.freeze()
  89. with pytest.raises(RuntimeError):
  90. del signal[0]
  91. assert list(signal) == [m1]
  92. @pytest.mark.asyncio
  93. async def test_cannot_send_non_frozen_signal(owner: Owner) -> None:
  94. signal = Signal(owner)
  95. callback_mock = mock.Mock()
  96. async def callback(**kwargs):
  97. callback_mock(**kwargs)
  98. signal.append(callback)
  99. with pytest.raises(RuntimeError):
  100. await signal.send()
  101. assert not callback_mock.called
  102. def test_repr(owner: Owner) -> None:
  103. signal = Signal(owner)
  104. signal.append(mock.Mock(__repr__=lambda *a: "<callback>"))
  105. assert (
  106. re.match(
  107. r"<Signal owner=<Owner 0xdeadbeef>, frozen=False, " r"\[<callback>\]>",
  108. repr(signal),
  109. )
  110. is not None
  111. )