1111
1212def async_run (coro ):
1313 """Helper function to run coroutines in tests with a fresh event loop."""
14- loop = asyncio .new_event_loop ()
15- asyncio .set_event_loop (loop )
14+ try :
15+ # Try to get an existing event loop
16+ loop = asyncio .get_event_loop ()
17+ if loop .is_closed ():
18+ loop = asyncio .new_event_loop ()
19+ asyncio .set_event_loop (loop )
20+ except RuntimeError :
21+ # Create a new event loop if there isn't one
22+ loop = asyncio .new_event_loop ()
23+ asyncio .set_event_loop (loop )
24+
1625 try :
1726 return loop .run_until_complete (coro )
1827 finally :
19- loop . close ()
20- asyncio . set_event_loop ( None )
28+ # Clean up but don't close the loop as it might be reused
29+ pass
2130
2231
2332class TestCrawler (unittest .TestCase ):
2433 """Tests for the Crawler class."""
2534
2635 def setUp (self ):
2736 """Set up test fixtures."""
37+ # Create and set an event loop for Python 3.9 compatibility
38+ try :
39+ asyncio .get_event_loop ()
40+ except RuntimeError :
41+ asyncio .set_event_loop (asyncio .new_event_loop ())
42+
2843 self .crawler = Crawler (
2944 max_depth = 2 ,
3045 concurrency_limit = 5 ,
@@ -35,6 +50,20 @@ def setUp(self):
3550 def tearDown (self ):
3651 """Clean up after tests."""
3752 self .crawler .close ()
53+ # Reset the event loop for next test
54+ try :
55+ # Get the current event loop
56+ loop = asyncio .get_event_loop ()
57+ # If the loop is running, stop it
58+ if loop .is_running ():
59+ loop .stop ()
60+ # Close it
61+ loop .close ()
62+ except RuntimeError :
63+ pass # No event loop exists
64+ finally :
65+ # Reset to None to clean up
66+ asyncio .set_event_loop (None )
3867
3968 def test_is_allowed_domain_same_domain (self ):
4069 """Test that same domain is always allowed."""
0 commit comments