66If the platform supports SIGALRM this is used to raise an exception in
77the test, otherwise os._exit(1) is used.
88"""
9+
910import inspect
1011import os
1112import signal
1718
1819import pytest
1920
20-
21- __all__ = ("is_debugging" , "Settings" )
21+ __all__ = ("Settings" , "is_debugging" )
2222SESSION_TIMEOUT_KEY = pytest .StashKey [float ]()
2323SESSION_EXPIRE_KEY = pytest .StashKey [float ]()
2424PYTEST_FAILURE_MESSAGE = "Timeout (>%ss) from pytest-timeout."
2525
2626HAVE_SIGALRM = hasattr (signal , "SIGALRM" )
27- if HAVE_SIGALRM :
28- DEFAULT_METHOD = "signal"
29- else :
30- DEFAULT_METHOD = "thread"
27+ DEFAULT_METHOD = "signal" if HAVE_SIGALRM else "thread"
3128TIMEOUT_DESC = """
3229Timeout in seconds before dumping the stacks. Default is 0 which
3330means no timeout.
@@ -112,7 +109,7 @@ class TimeoutHooks:
112109 """Timeout specific hooks."""
113110
114111 @pytest .hookspec (firstresult = True )
115- def pytest_timeout_set_timer (item , settings ):
112+ def pytest_timeout_set_timer (self , item , settings ):
116113 """Called at timeout setup.
117114
118115 'item' is a pytest node to setup timeout for.
@@ -122,7 +119,7 @@ def pytest_timeout_set_timer(item, settings):
122119 """
123120
124121 @pytest .hookspec (firstresult = True )
125- def pytest_timeout_cancel_timer (item ):
122+ def pytest_timeout_cancel_timer (self , item ):
126123 """Called at timeout teardown.
127124
128125 'item' is a pytest node which was used for timeout setup.
@@ -223,19 +220,17 @@ def pytest_report_header(config):
223220
224221 if config ._env_timeout :
225222 timeout_header .append (
226- "timeout: %ss\n timeout method: %s\n timeout func_only: %s"
227- % (
228- config ._env_timeout ,
229- config ._env_timeout_method ,
230- config ._env_timeout_func_only ,
231- )
223+ f"timeout: { config ._env_timeout } s\n "
224+ f"timeout method: { config ._env_timeout_method } \n "
225+ f"timeout func_only: { config ._env_timeout_func_only } "
232226 )
233227
234228 session_timeout = config .getoption ("session_timeout" )
235229 if session_timeout :
236- timeout_header .append ("session timeout: %ss" % session_timeout )
230+ timeout_header .append (f "session timeout: { session_timeout } s" )
237231 if timeout_header :
238232 return timeout_header
233+ return None
239234
240235
241236@pytest .hookimpl (tryfirst = True )
@@ -249,10 +244,10 @@ def pytest_exception_interact(node):
249244def pytest_enter_pdb ():
250245 """Stop the timeouts when we entered pdb.
251246
252- This stops timeouts from triggering when pytest's builting pdb
247+ This stops timeouts from triggering when pytest's builtin pdb
253248 support notices we entered pdb.
254249 """
255- # Since pdb.set_trace happens outside of any pytest control, we don't have
250+ # Since pdb.set_trace happens outside any pytest control, we don't have
256251 # any pytest ``item`` here, so we cannot use timeout_teardown. Thus, we
257252 # need another way to signify that the timeout should not be performed.
258253 global SUPPRESS_TIMEOUT
@@ -326,7 +321,7 @@ def cancel():
326321 signal .setitimer (signal .ITIMER_REAL , settings .timeout )
327322 elif timeout_method == "thread" :
328323 timer = threading .Timer (settings .timeout , timeout_timer , (item , settings ))
329- timer .name = "%s %s" % ( __name__ , item .nodeid )
324+ timer .name = f" { __name__ } { item .nodeid } "
330325
331326 def cancel ():
332327 timer .cancel ()
@@ -427,14 +422,15 @@ def _parse_marker(marker):
427422 elif kw == "func_only" :
428423 func_only = val
429424 else :
430- raise TypeError ("Invalid keyword argument for timeout marker: %s" % kw )
425+ msg = f"Invalid keyword argument for timeout marker: { kw } "
426+ raise TypeError (msg )
431427 if len (marker .args ) >= 1 and timeout is not NOTSET :
432428 raise TypeError ("Multiple values for timeout argument of timeout marker" )
433- elif len (marker .args ) >= 1 :
429+ if len (marker .args ) >= 1 :
434430 timeout = marker .args [0 ]
435431 if len (marker .args ) >= 2 and method is not NOTSET :
436432 raise TypeError ("Multiple values for method argument of timeout marker" )
437- elif len (marker .args ) >= 2 :
433+ if len (marker .args ) >= 2 :
438434 method = marker .args [1 ]
439435 if len (marker .args ) > 2 :
440436 raise TypeError ("Too many arguments for timeout marker" )
@@ -453,22 +449,25 @@ def _validate_timeout(timeout, where):
453449 try :
454450 return float (timeout )
455451 except ValueError :
456- raise ValueError ("Invalid timeout %s from %s" % (timeout , where ))
452+ msg = f"Invalid timeout { timeout } from { where } "
453+ raise ValueError (msg )
457454
458455
459456def _validate_method (method , where ):
460457 if method is None :
461458 return None
462459 if method not in ["signal" , "thread" ]:
463- raise ValueError ("Invalid method %s from %s" % (method , where ))
460+ msg = f"Invalid method { method } from { where } "
461+ raise ValueError (msg )
464462 return method
465463
466464
467465def _validate_func_only (func_only , where ):
468466 if func_only is None :
469467 return None
470468 if not isinstance (func_only , bool ):
471- raise ValueError ("Invalid func_only value %s from %s" % (func_only , where ))
469+ msg = f"Invalid func_only value { func_only } from { where } "
470+ raise ValueError (msg )
472471 return func_only
473472
474473
@@ -555,5 +554,5 @@ def dump_stacks(terminal):
555554 break
556555 else :
557556 thread_name = "<unknown>"
558- terminal .sep ("~" , title = "Stack of %s (%s)" % ( thread_name , thread_ident ) )
557+ terminal .sep ("~" , title = f "Stack of { thread_name } ( { thread_ident } )" )
559558 terminal .write ("" .join (traceback .format_stack (frame )))
0 commit comments