11"""
22Tests that verify the wrapping and delegation patterns for async methods.
33
4- These tests verify that async methods (like aconnect(), arun(), arun_login())
5- properly delegate through the execute(), wrap_lock(), and sync_run() chain to
4+ These tests verify that async methods (like aconnect(), arun(), arun_login())
5+ properly delegate through the execute(), wrap_lock(), and sync_run() chain to
66reach the underlying synchronous methods.
77"""
88
1919 sys .path .insert (0 , str (__file__ ).rsplit ("tests" , 1 )[0 ] + "src" )
2020 try :
2121 import p4async as _p4async_source
22+
2223 SIMPLE_WRAP_METHODS = list (_p4async_source .P4Async .simple_wrap_methods )
2324 RUN_WRAP_METHODS = list (_p4async_source .P4Async .run_wrap_methods )
2425 except ImportError :
2526 # Fallback if import fails
2627 SIMPLE_WRAP_METHODS = ["connect" , "disconnect" , "run_tickets" ]
27- RUN_WRAP_METHODS = ["run_submit" , "run_shelve" , "delete_shelve" , "run_login" ,
28- "run_password" , "run_filelog" , "run_print" , "run_resolve" ]
28+ RUN_WRAP_METHODS = [
29+ "run_submit" ,
30+ "run_shelve" ,
31+ "delete_shelve" ,
32+ "run_login" ,
33+ "run_password" ,
34+ "run_filelog" ,
35+ "run_print" ,
36+ "run_resolve" ,
37+ ]
2938else :
3039 SIMPLE_WRAP_METHODS = list (sys .modules ["p4async" ].P4Async .simple_wrap_methods )
3140 RUN_WRAP_METHODS = list (sys .modules ["p4async" ].P4Async .run_wrap_methods )
@@ -36,7 +45,9 @@ class TestSimpleWrapMethods:
3645
3746 @pytest .mark .asyncio
3847 @pytest .mark .parametrize ("method_name" , SIMPLE_WRAP_METHODS )
39- async def test_async_method_calls_through_execute_and_wrap_lock (self , p4async_module , method_name ):
48+ async def test_async_method_calls_through_execute_and_wrap_lock (
49+ self , p4async_module , method_name
50+ ):
4051 """Verify that async wrapper -> execute() -> wrap_lock(method) -> method()"""
4152 p4async = p4async_module
4253 p4 = p4async .P4Async ()
@@ -125,23 +136,23 @@ async def test_arun_calls_through_execute_and_sync_run(self, p4async_module):
125136 # We can't easily mock the parent class method due to super() behavior
126137 # Instead, let's verify that sync_run is called correctly, which is sufficient
127138 # to prove the call chain
128-
139+
129140 # Call arun
130141 result = await p4 .arun ("info" )
131142
132143 # Verify execute was called
133144 assert execute_mock .call_count == 1 , "execute() not called"
134-
145+
135146 # Verify execute was called with sync_run
136147 execute_call_args = execute_mock .call_args
137148 assert execute_call_args [0 ][0 ] == p4 .sync_run , "execute() should be called with sync_run"
138149
139150 # Verify sync_run was called
140151 assert sync_run_mock .call_count == 1 , "sync_run() not called"
141-
152+
142153 # Verify sync_run was called with the command
143154 sync_run_mock .assert_called_once_with ("info" )
144-
155+
145156 # Verify the result is correct (which proves super().run() was called)
146157 assert result == {"userName" : "testuser" }
147158
@@ -169,17 +180,17 @@ async def test_run_with_async_true_calls_through_execute_and_sync_run(self, p4as
169180
170181 # Verify execute was called
171182 assert execute_mock .call_count == 1 , "execute() not called"
172-
183+
173184 # Verify execute was called with sync_run
174185 execute_call_args = execute_mock .call_args
175186 assert execute_call_args [0 ][0 ] == p4 .sync_run , "execute() should be called with sync_run"
176187
177188 # Verify sync_run was called
178189 assert sync_run_mock .call_count == 1 , "sync_run() not called"
179-
190+
180191 # Verify sync_run was called with the command (with_async is NOT passed to sync_run)
181192 sync_run_mock .assert_called_once_with ("changes" )
182-
193+
183194 # Verify the result is correct (which proves super().run() was called)
184195 assert result == [{"change" : "12345" }]
185196
@@ -243,11 +254,11 @@ async def test_simple_wrap_method_with_arguments(self, p4async_module):
243254
244255 # Add a test method to simple_wrap_methods
245256 p4 .simple_wrap_methods .add ("test_method" )
246-
257+
247258 # Create a mock method that accepts arguments
248259 def test_method (arg1 , arg2 , kwarg1 = None ):
249260 return f"called with { arg1 } , { arg2 } , { kwarg1 } "
250-
261+
251262 p4 .test_method = Mock (side_effect = test_method )
252263
253264 # Call the async version
@@ -265,6 +276,7 @@ async def test_execute_runs_in_thread_pool(self, p4async_module):
265276
266277 # Track the thread ID where the connect method runs
267278 import threading
279+
268280 main_thread_id = threading .get_ident ()
269281 execution_thread_id = None
270282
@@ -313,14 +325,18 @@ class TestRunWrapMethods:
313325
314326 @pytest .mark .asyncio
315327 @pytest .mark .parametrize ("method_name" , RUN_WRAP_METHODS )
316- async def test_async_method_calls_sync_method_which_calls_run (self , p4async_module , method_name ):
328+ async def test_async_method_calls_sync_method_which_calls_run (
329+ self , p4async_module , method_name
330+ ):
317331 """Verify that async wrapper -> sync method -> run(with_async=True)"""
318332 p4async = p4async_module
319333 p4 = p4async .P4Async ()
320334
321335 # Register appropriate responses for methods that need them
322336 if "submit" in method_name or "shelve" in method_name :
323- p4 .register_response ("submit" if "submit" in method_name else "shelve" , {"status" : "ok" })
337+ p4 .register_response (
338+ "submit" if "submit" in method_name else "shelve" , {"status" : "ok" }
339+ )
324340 elif "login" in method_name :
325341 p4 .register_response ("login" , {"status" : "ok" })
326342 elif "password" in method_name :
@@ -344,7 +360,7 @@ async def test_async_method_calls_sync_method_which_calls_run(self, p4async_modu
344360 # Call the async version
345361 async_method_name = f"a{ method_name } "
346362 async_method = getattr (p4 , async_method_name )
347-
363+
348364 # Call with some test arguments (method-specific)
349365 if "password" in method_name :
350366 result = await async_method ("oldpass" , "newpass" )
@@ -353,41 +369,48 @@ async def test_async_method_calls_sync_method_which_calls_run(self, p4async_modu
353369
354370 # Verify the sync method (e.g., run_login) was called
355371 assert method_mock .call_count == 1 , f"{ method_name } not called for { async_method_name } "
356-
372+
357373 # Verify that with_async=True was passed to the sync method
358374 method_call_kwargs = method_mock .call_args .kwargs
359375 assert "with_async" in method_call_kwargs , f"with_async not passed to { method_name } "
360376 assert method_call_kwargs ["with_async" ] is True , f"with_async is not True for { method_name } "
361377
362378 # Verify run() was called (by the sync method)
363379 assert run_mock .call_count >= 1 , f"run() not called by { method_name } "
364-
380+
365381 # Verify that run() was called WITH with_async=True
366382 # The sync method receives with_async=True and passes it through to run()
367383 found_with_async = False
368384 for call in run_mock .call_args_list :
369385 if "with_async" in call .kwargs and call .kwargs ["with_async" ] is True :
370386 found_with_async = True
371387 break
372-
388+
373389 assert found_with_async , f"run() should receive with_async=True from { method_name } "
374390
375391 @pytest .mark .asyncio
376- @pytest .mark .parametrize ("method_name,args,kwargs" , [
377- ("run_submit" , ("arg1" ,), {}),
378- ("run_shelve" , ("arg1" , "arg2" ), {}),
379- ("delete_shelve" , ("changelist" ,), {}),
380- ("run_login" , (), {}),
381- ("run_password" , ("old" , "new" ), {}),
382- ])
383- async def test_run_wrap_methods_pass_arguments_correctly (self , p4async_module , method_name , args , kwargs ):
392+ @pytest .mark .parametrize (
393+ "method_name,args,kwargs" ,
394+ [
395+ ("run_submit" , ("arg1" ,), {}),
396+ ("run_shelve" , ("arg1" , "arg2" ), {}),
397+ ("delete_shelve" , ("changelist" ,), {}),
398+ ("run_login" , (), {}),
399+ ("run_password" , ("old" , "new" ), {}),
400+ ],
401+ )
402+ async def test_run_wrap_methods_pass_arguments_correctly (
403+ self , p4async_module , method_name , args , kwargs
404+ ):
384405 """Verify that arguments are passed correctly through run_wrap_methods"""
385406 p4async = p4async_module
386407 p4 = p4async .P4Async ()
387408
388409 # Register appropriate responses
389410 if "submit" in method_name or "shelve" in method_name :
390- p4 .register_response ("submit" if "submit" in method_name else "shelve" , {"status" : "ok" })
411+ p4 .register_response (
412+ "submit" if "submit" in method_name else "shelve" , {"status" : "ok" }
413+ )
391414 elif "login" in method_name :
392415 p4 .register_response ("login" , {"status" : "ok" })
393416 elif "password" in method_name :
@@ -405,11 +428,10 @@ async def test_run_wrap_methods_pass_arguments_correctly(self, p4async_module, m
405428
406429 # Verify run() was called (it will be called by the sync method)
407430 assert run_mock .call_count >= 1 , f"run() not called for { async_method_name } "
408-
431+
409432 # Verify with_async=True was passed to at least one call
410433 found_with_async = any (
411- call .kwargs .get ("with_async" ) is True
412- for call in run_mock .call_args_list
434+ call .kwargs .get ("with_async" ) is True for call in run_mock .call_args_list
413435 )
414436 assert found_with_async , f"run() was not called with with_async=True for { method_name } "
415437
0 commit comments