1-
21import os
32import re
43import signal
1110import irods .helpers
1211from irods .test import modules as test_modules
1312
14- OBJECT_SIZE = 2 * 1024 ** 3
15- OBJECT_NAME = ' data_get_issue__722'
16- LOCAL_TEMPFILE_NAME = ' data_object_for_issue_722.dat'
13+ OBJECT_SIZE = 2 * 1024 ** 3
14+ OBJECT_NAME = " data_get_issue__722"
15+ LOCAL_TEMPFILE_NAME = " data_object_for_issue_722.dat"
1716
1817
19- _clock_polling_interval = max (.01 , time .clock_getres (time .CLOCK_BOOTTIME ))
18+ _clock_polling_interval = max (0 .01 , time .clock_getres (time .CLOCK_BOOTTIME ))
2019
2120
2221def wait_till_true (function , timeout = None ):
2322 start_time = time .clock_gettime_ns (time .CLOCK_BOOTTIME )
2423 while not (truth_value := function ()):
25- if timeout is not None and (time .clock_gettime_ns (time .CLOCK_BOOTTIME )- start_time )* 1e-9 > timeout :
24+ if (
25+ timeout is not None
26+ and (time .clock_gettime_ns (time .CLOCK_BOOTTIME ) - start_time ) * 1e-9
27+ > timeout
28+ ):
2629 break
2730 time .sleep (_clock_polling_interval )
2831 return truth_value
2932
3033
31- def test (test_case , signal_names = ("SIGTERM" , "SIGINT" )):
34+ def test (test_case , signal_names = ("SIGTERM" , "SIGINT" )):
3235 """Creates a child process executing a long get() and ensures the process can be
3336 terminated using SIGINT or SIGTERM.
3437 """
@@ -37,52 +40,68 @@ def test(test_case, signal_names = ("SIGTERM", "SIGINT")):
3740 for signal_name in signal_names :
3841 # Call into this same module as a command. This will initiate another Python process that
3942 # performs a lengthy data object "get" operation (see the main body of the script, below.)
40- process = subprocess .Popen ([sys .executable , program ],
41- stderr = subprocess .PIPE ,
42- stdout = subprocess .PIPE ,
43- text = True )
43+ process = subprocess .Popen (
44+ [sys .executable , program ],
45+ stderr = subprocess .PIPE ,
46+ stdout = subprocess .PIPE ,
47+ text = True ,
48+ )
4449
4550 # Wait for download process to reach the point of spawning data transfer threads. In Python 3.9+ versions
4651 # of the concurrent.futures module, these are nondaemon threads and will block the exit of the main thread
4752 # unless measures are taken (#722).
4853 localfile = process .stdout .readline ().strip ()
49- test_case .assertTrue (wait_till_true (lambda :os .path .exists (localfile ) and os .stat (localfile ).st_size > OBJECT_SIZE // 2 ),
50- "Parallel download from data_objects.get() probably experienced a fatal error before spawning auxiliary data transfer threads."
51- )
54+ test_case .assertTrue (
55+ wait_till_true (
56+ lambda : os .path .exists (localfile )
57+ and os .stat (localfile ).st_size > OBJECT_SIZE // 2
58+ ),
59+ "Parallel download from data_objects.get() probably experienced a fatal error before spawning auxiliary data transfer threads." ,
60+ )
5261
5362 signal_message_info = f"While testing signal { signal_name } "
5463 sig = getattr (signal , signal_name )
5564
5665 # Interrupt the subprocess with the given signal.
5766 process .send_signal (sig )
58- # Assert that this signal is what killed the subprocess, rather than a timed out process "wait" or a natural exit
67+ # Assert that this signal is what killed the subprocess, rather than a timed out process "wait" or a natural exit
5968 # due to misproper or incomplete handling of the signal.
6069 try :
61- test_case .assertEqual (process .wait (timeout = 15 ), - sig , "{signal_message_info}: unexpected subprocess return code." )
70+ test_case .assertEqual (
71+ process .wait (timeout = 15 ),
72+ - sig ,
73+ "{signal_message_info}: unexpected subprocess return code." ,
74+ )
6275 except subprocess .TimeoutExpired as timeout_exc :
63- test_case .fail (f"{ signal_message_info } : subprocess timed out before terminating. "
64- "Non-daemon thread(s) probably prevented subprocess's main thread from exiting." )
76+ test_case .fail (
77+ f"{ signal_message_info } : subprocess timed out before terminating. "
78+ "Non-daemon thread(s) probably prevented subprocess's main thread from exiting."
79+ )
6580 # Assert that in the case of SIGINT, the process registered a KeyboardInterrupt.
6681 if sig == signal .SIGINT :
67- test_case .assertTrue (re .search ('KeyboardInterrupt' , process .stderr .read ()),
68- "{signal_message_info}: Expected 'KeyboardInterrupt' in log output." )
82+ test_case .assertTrue (
83+ re .search ("KeyboardInterrupt" , process .stderr .read ()),
84+ "{signal_message_info}: Expected 'KeyboardInterrupt' in log output." ,
85+ )
6986
7087
7188if __name__ == "__main__" :
7289 # These lines are run only if the module is launched as a process.
7390 session = irods .helpers .make_session ()
7491 hc = irods .helpers .home_collection (session )
75- TESTFILE_FILL = b'_' * (1024 * 1024 )
76- object_path = f' { hc } /{ OBJECT_NAME } '
92+ TESTFILE_FILL = b"_" * (1024 * 1024 )
93+ object_path = f" { hc } /{ OBJECT_NAME } "
7794
7895 # Create the object to be downloaded.
79- with session .data_objects .open (object_path ,'w' ) as f :
80- for y in range (OBJECT_SIZE // len (TESTFILE_FILL )):
96+ with session .data_objects .open (object_path , "w" ) as f :
97+ for y in range (OBJECT_SIZE // len (TESTFILE_FILL )):
8198 f .write (TESTFILE_FILL )
8299 local_path = None
83100 # Establish where (ie absolute path) to place the downloaded file, i.e. the get() target.
84101 try :
85- with tempfile .NamedTemporaryFile (prefix = 'local_file_issue_722.dat' , delete = True ) as t :
102+ with tempfile .NamedTemporaryFile (
103+ prefix = "local_file_issue_722.dat" , delete = True
104+ ) as t :
86105 local_path = t .name
87106
88107 # Tell the parent process the name of the local file being "get"ted (got) from iRODS
0 commit comments