Skip to content

Commit 348b278

Browse files
authored
Merge pull request #495 from sadsfae/master
fix: event_loop for strict Py314 and beyond.
2 parents eb20b8f + bb0d39d commit 348b278

File tree

2 files changed

+65
-1
lines changed

2 files changed

+65
-1
lines changed

src/badfish/main.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2674,7 +2674,11 @@ def main(argv=None):
26742674
output = _args["output"]
26752675
bfl = BadfishLogger(_args["verbose"], multi_host, _args["log"], output)
26762676

2677-
loop = asyncio.get_event_loop()
2677+
try:
2678+
loop = asyncio.get_event_loop()
2679+
except RuntimeError:
2680+
loop = asyncio.new_event_loop()
2681+
asyncio.set_event_loop(loop)
26782682
tasks = []
26792683
host_order = {}
26802684
if host_list:

tests/test_async_loop.py

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import unittest
2+
from unittest.mock import patch, MagicMock
3+
from badfish.main import main
4+
5+
6+
class TestAsyncioFix(unittest.TestCase):
7+
@patch('badfish.main.execute_badfish')
8+
@patch('badfish.main.BadfishLogger')
9+
@patch('badfish.main.parse_arguments')
10+
@patch('asyncio.set_event_loop')
11+
@patch('asyncio.new_event_loop')
12+
@patch('asyncio.get_event_loop')
13+
def test_main_handles_no_event_loop(self, mock_get_loop, mock_new_loop,
14+
mock_set_loop, mock_parse_args,
15+
mock_logger, mock_execute):
16+
mock_get_loop.side_effect = RuntimeError("No event loop")
17+
18+
mock_loop_instance = MagicMock()
19+
mock_new_loop.return_value = mock_loop_instance
20+
mock_loop_instance.run_until_complete.return_value = ("localhost", True)
21+
22+
mock_parse_args.return_value = {
23+
"verbose": False, "host": "localhost", "delta": None,
24+
"firmware_inventory": None, "host_list": None, "log": None,
25+
"output": None
26+
}
27+
28+
main()
29+
30+
mock_get_loop.assert_called_once()
31+
mock_new_loop.assert_called_once()
32+
mock_set_loop.assert_called_once_with(mock_loop_instance)
33+
mock_loop_instance.run_until_complete.assert_called()
34+
35+
@patch('badfish.main.execute_badfish')
36+
@patch('badfish.main.BadfishLogger')
37+
@patch('badfish.main.parse_arguments')
38+
@patch('asyncio.set_event_loop')
39+
@patch('asyncio.new_event_loop')
40+
@patch('asyncio.get_event_loop')
41+
def test_main_uses_existing_loop(self, mock_get_loop, mock_new_loop,
42+
mock_set_loop, mock_parse_args,
43+
mock_logger, mock_execute):
44+
existing_loop = MagicMock()
45+
mock_get_loop.return_value = existing_loop
46+
mock_get_loop.side_effect = None
47+
existing_loop.run_until_complete.return_value = ("localhost", True)
48+
49+
mock_parse_args.return_value = {
50+
"verbose": False, "host": "localhost", "delta": None,
51+
"firmware_inventory": None, "host_list": None, "log": None,
52+
"output": None
53+
}
54+
55+
main()
56+
57+
mock_get_loop.assert_called_once()
58+
mock_new_loop.assert_not_called()
59+
mock_set_loop.assert_not_called()
60+
existing_loop.run_until_complete.assert_called()

0 commit comments

Comments
 (0)