Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package python-pytest-timeout for openSUSE:Factory checked in at 2024-03-18 16:44:22 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-pytest-timeout (Old) and /work/SRC/openSUSE:Factory/.python-pytest-timeout.new.1905 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-pytest-timeout" Mon Mar 18 16:44:22 2024 rev:15 rq:1158473 version:2.3.1 Changes: -------- --- /work/SRC/openSUSE:Factory/python-pytest-timeout/python-pytest-timeout.changes 2023-11-08 22:17:32.662768661 +0100 +++ /work/SRC/openSUSE:Factory/.python-pytest-timeout.new.1905/python-pytest-timeout.changes 2024-03-18 16:44:35.695038317 +0100 @@ -1,0 +2,15 @@ +Sat Mar 16 13:01:47 UTC 2024 - Dirk Müller <dmuel...@suse.com> + +- update to 2.3.1: + * Fixup some build errors, mostly README syntax which stopped + twine from uploading. + * Fix debugger detection for recent VSCode, this compiles pydevd + using cython which is now correctly detected. + * Switched to using Pytest's ``TerminalReporter`` instead + of writing directly to ``sys.{stdout,stderr}``. + * This change also switches all output from ``sys.stderr`` to + ``sys.stdout``. + * Pytest 7.0.0 is now the minimum supported version. + * Add ``--session-timeout`` option and ``session_timeout`` setting. + +------------------------------------------------------------------- Old: ---- pytest-timeout-2.2.0.tar.gz New: ---- pytest-timeout-2.3.1.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-pytest-timeout.spec ++++++ --- /var/tmp/diff_new_pack.F7K0QC/_old 2024-03-18 16:44:36.875081845 +0100 +++ /var/tmp/diff_new_pack.F7K0QC/_new 2024-03-18 16:44:36.875081845 +0100 @@ -1,7 +1,7 @@ # # spec file for package python-pytest-timeout # -# Copyright (c) 2023 SUSE LLC +# Copyright (c) 2024 SUSE LLC # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -19,17 +19,17 @@ %bcond_with ringdisabled %{?sle15_python_module_pythons} Name: python-pytest-timeout -Version: 2.2.0 +Version: 2.3.1 Release: 0 Summary: Pytest plugin to abort hanging tests License: MIT URL: https://github.com/pytest-dev/pytest-timeout/ Source: https://files.pythonhosted.org/packages/source/p/pytest-timeout/pytest-timeout-%{version}.tar.gz -BuildRequires: %{python_module pytest >= 5.0.0} +BuildRequires: %{python_module pytest >= 7.0.0} BuildRequires: %{python_module setuptools} BuildRequires: fdupes BuildRequires: python-rpm-macros -Requires: python-pytest >= 5.0.0 +Requires: python-pytest >= 7.0.0 # SECTION test %if !%{with ringdisabled} BuildRequires: %{python_module pytest-cov} ++++++ pytest-timeout-2.2.0.tar.gz -> pytest-timeout-2.3.1.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pytest-timeout-2.2.0/PKG-INFO new/pytest-timeout-2.3.1/PKG-INFO --- old/pytest-timeout-2.2.0/PKG-INFO 2023-10-08 12:13:57.969030000 +0200 +++ new/pytest-timeout-2.3.1/PKG-INFO 2024-03-07 22:03:27.609297800 +0100 @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: pytest-timeout -Version: 2.2.0 +Version: 2.3.1 Summary: pytest plugin to abort hanging tests Home-page: https://github.com/pytest-dev/pytest-timeout Author: Floris Bruynooghe @@ -26,8 +26,9 @@ Classifier: Topic :: Software Development :: Testing Classifier: Framework :: Pytest Requires-Python: >=3.7 +Description-Content-Type: text/x-rst License-File: LICENSE -Requires-Dist: pytest>=5.0.0 +Requires-Dist: pytest>=7.0.0 ============== pytest-timeout @@ -258,6 +259,17 @@ exists which can be set in the pytest ini configuration file, as documented in ``pytest --help``. +For the decorated function, a decorator will override +``timeout_func_only = true`` in the pytest ini file to the default +value. If you need to keep this option for a decorated test, you +must specify the option explicitly again: + +.. code:: python + + @pytest.mark.timeout(60, func_only=True) + def test_foo(): + pass + Debugger Detection ================== @@ -360,9 +372,77 @@ pytest.fail("+++ Timeout +++") + +Session Timeout +=============== + +The above mentioned timeouts are all per test function. +The "per test function" timeouts will stop an individual test +from taking too long. We may also want to limit the time of the entire +set of tests running in one session. A session all of the tests +that will be run with one invokation of pytest. + +A session timeout is set with `--session-timeout` and is in seconds. + +The following example shows a session timeout of 10 minutes (600 seconds):: + + pytest --session-timeout=600 + +You can also set the session timeout the pytest configuration file using the ``session_timeout`` option: + + .. code:: ini + + [pytest] + session_timeout = 600 + +Cooperative timeouts +-------------------- + +Session timeouts are cooperative timeouts. pytest-timeout checks the +session time at the end of each test function, and stops further tests +from running if the session timeout is exceeded. The session will +results in a test failure if this occurs. + +In particular this means if a test does not finish of itself, it will +only be interrupted if there is also a function timeout set. A +session timeout is not enough to ensure that a test-suite is +guaranteed to finish. + +Combining session and function timeouts +--------------------------------------- + +It works fine to combine both session and function timeouts. In fact +when using a session timeout it is recommended to also provide a +function timeout. + +For example, to limit test functions to 5 seconds and the full session +to 100 seconds:: + + pytest --timeout=5 --session-timeout=100 + + Changelog ========= +2.3.1 +----- + +- Fixup some build errors, mostly README syntax which stopped twine + from uploading. + +2.3.0 +----- + +- Fix debugger detection for recent VSCode, this compiles pydevd using + cython which is now correctly detected. Thanks Adrian Gielniewski. +- Switched to using Pytest's ``TerminalReporter`` instead of writing + directly to ``sys.{stdout,stderr}``. + This change also switches all output from ``sys.stderr`` to ``sys.stdout``. + Thanks Pedro Algarvio. +- Pytest 7.0.0 is now the minimum supported version. Thanks Pedro Algarvio. +- Add ``--session-timeout`` option and ``session_timeout`` setting. + Thanks Brian Okken. + 2.2.0 ----- diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pytest-timeout-2.2.0/README.rst new/pytest-timeout-2.3.1/README.rst --- old/pytest-timeout-2.2.0/README.rst 2023-10-04 21:07:44.000000000 +0200 +++ new/pytest-timeout-2.3.1/README.rst 2024-03-07 22:02:37.000000000 +0100 @@ -227,6 +227,17 @@ exists which can be set in the pytest ini configuration file, as documented in ``pytest --help``. +For the decorated function, a decorator will override +``timeout_func_only = true`` in the pytest ini file to the default +value. If you need to keep this option for a decorated test, you +must specify the option explicitly again: + +.. code:: python + + @pytest.mark.timeout(60, func_only=True) + def test_foo(): + pass + Debugger Detection ================== @@ -329,9 +340,77 @@ pytest.fail("+++ Timeout +++") + +Session Timeout +=============== + +The above mentioned timeouts are all per test function. +The "per test function" timeouts will stop an individual test +from taking too long. We may also want to limit the time of the entire +set of tests running in one session. A session all of the tests +that will be run with one invokation of pytest. + +A session timeout is set with `--session-timeout` and is in seconds. + +The following example shows a session timeout of 10 minutes (600 seconds):: + + pytest --session-timeout=600 + +You can also set the session timeout the pytest configuration file using the ``session_timeout`` option: + + .. code:: ini + + [pytest] + session_timeout = 600 + +Cooperative timeouts +-------------------- + +Session timeouts are cooperative timeouts. pytest-timeout checks the +session time at the end of each test function, and stops further tests +from running if the session timeout is exceeded. The session will +results in a test failure if this occurs. + +In particular this means if a test does not finish of itself, it will +only be interrupted if there is also a function timeout set. A +session timeout is not enough to ensure that a test-suite is +guaranteed to finish. + +Combining session and function timeouts +--------------------------------------- + +It works fine to combine both session and function timeouts. In fact +when using a session timeout it is recommended to also provide a +function timeout. + +For example, to limit test functions to 5 seconds and the full session +to 100 seconds:: + + pytest --timeout=5 --session-timeout=100 + + Changelog ========= +2.3.1 +----- + +- Fixup some build errors, mostly README syntax which stopped twine + from uploading. + +2.3.0 +----- + +- Fix debugger detection for recent VSCode, this compiles pydevd using + cython which is now correctly detected. Thanks Adrian Gielniewski. +- Switched to using Pytest's ``TerminalReporter`` instead of writing + directly to ``sys.{stdout,stderr}``. + This change also switches all output from ``sys.stderr`` to ``sys.stdout``. + Thanks Pedro Algarvio. +- Pytest 7.0.0 is now the minimum supported version. Thanks Pedro Algarvio. +- Add ``--session-timeout`` option and ``session_timeout`` setting. + Thanks Brian Okken. + 2.2.0 ----- diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pytest-timeout-2.2.0/pytest_timeout.egg-info/PKG-INFO new/pytest-timeout-2.3.1/pytest_timeout.egg-info/PKG-INFO --- old/pytest-timeout-2.2.0/pytest_timeout.egg-info/PKG-INFO 2023-10-08 12:13:57.000000000 +0200 +++ new/pytest-timeout-2.3.1/pytest_timeout.egg-info/PKG-INFO 2024-03-07 22:03:27.000000000 +0100 @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: pytest-timeout -Version: 2.2.0 +Version: 2.3.1 Summary: pytest plugin to abort hanging tests Home-page: https://github.com/pytest-dev/pytest-timeout Author: Floris Bruynooghe @@ -26,8 +26,9 @@ Classifier: Topic :: Software Development :: Testing Classifier: Framework :: Pytest Requires-Python: >=3.7 +Description-Content-Type: text/x-rst License-File: LICENSE -Requires-Dist: pytest>=5.0.0 +Requires-Dist: pytest>=7.0.0 ============== pytest-timeout @@ -258,6 +259,17 @@ exists which can be set in the pytest ini configuration file, as documented in ``pytest --help``. +For the decorated function, a decorator will override +``timeout_func_only = true`` in the pytest ini file to the default +value. If you need to keep this option for a decorated test, you +must specify the option explicitly again: + +.. code:: python + + @pytest.mark.timeout(60, func_only=True) + def test_foo(): + pass + Debugger Detection ================== @@ -360,9 +372,77 @@ pytest.fail("+++ Timeout +++") + +Session Timeout +=============== + +The above mentioned timeouts are all per test function. +The "per test function" timeouts will stop an individual test +from taking too long. We may also want to limit the time of the entire +set of tests running in one session. A session all of the tests +that will be run with one invokation of pytest. + +A session timeout is set with `--session-timeout` and is in seconds. + +The following example shows a session timeout of 10 minutes (600 seconds):: + + pytest --session-timeout=600 + +You can also set the session timeout the pytest configuration file using the ``session_timeout`` option: + + .. code:: ini + + [pytest] + session_timeout = 600 + +Cooperative timeouts +-------------------- + +Session timeouts are cooperative timeouts. pytest-timeout checks the +session time at the end of each test function, and stops further tests +from running if the session timeout is exceeded. The session will +results in a test failure if this occurs. + +In particular this means if a test does not finish of itself, it will +only be interrupted if there is also a function timeout set. A +session timeout is not enough to ensure that a test-suite is +guaranteed to finish. + +Combining session and function timeouts +--------------------------------------- + +It works fine to combine both session and function timeouts. In fact +when using a session timeout it is recommended to also provide a +function timeout. + +For example, to limit test functions to 5 seconds and the full session +to 100 seconds:: + + pytest --timeout=5 --session-timeout=100 + + Changelog ========= +2.3.1 +----- + +- Fixup some build errors, mostly README syntax which stopped twine + from uploading. + +2.3.0 +----- + +- Fix debugger detection for recent VSCode, this compiles pydevd using + cython which is now correctly detected. Thanks Adrian Gielniewski. +- Switched to using Pytest's ``TerminalReporter`` instead of writing + directly to ``sys.{stdout,stderr}``. + This change also switches all output from ``sys.stderr`` to ``sys.stdout``. + Thanks Pedro Algarvio. +- Pytest 7.0.0 is now the minimum supported version. Thanks Pedro Algarvio. +- Add ``--session-timeout`` option and ``session_timeout`` setting. + Thanks Brian Okken. + 2.2.0 ----- diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pytest-timeout-2.2.0/pytest_timeout.egg-info/requires.txt new/pytest-timeout-2.3.1/pytest_timeout.egg-info/requires.txt --- old/pytest-timeout-2.2.0/pytest_timeout.egg-info/requires.txt 2023-10-08 12:13:57.000000000 +0200 +++ new/pytest-timeout-2.3.1/pytest_timeout.egg-info/requires.txt 2024-03-07 22:03:27.000000000 +0100 @@ -1 +1 @@ -pytest>=5.0.0 +pytest>=7.0.0 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pytest-timeout-2.2.0/pytest_timeout.py new/pytest-timeout-2.3.1/pytest_timeout.py --- old/pytest-timeout-2.2.0/pytest_timeout.py 2023-10-04 21:07:44.000000000 +0200 +++ new/pytest-timeout-2.3.1/pytest_timeout.py 2024-03-07 21:51:08.000000000 +0100 @@ -8,10 +8,10 @@ """ import inspect import os -import shutil import signal import sys import threading +import time import traceback from collections import namedtuple @@ -19,6 +19,8 @@ __all__ = ("is_debugging", "Settings") +SESSION_TIMEOUT_KEY = pytest.StashKey[float]() +SESSION_EXPIRE_KEY = pytest.StashKey[float]() HAVE_SIGALRM = hasattr(signal, "SIGALRM") @@ -44,6 +46,11 @@ When specified, disables debugger detection. breakpoint(), pdb.set_trace(), etc. will be interrupted by the timeout. """.strip() +SESSION_TIMEOUT_DESC = """ +Timeout in seconds for entire session. Default is None which +means no timeout. Timeout is checked between tests, and will not interrupt a test +in progress. +""".strip() # bdb covers pdb, ipdb, and possibly others # pydevd covers PyCharm, VSCode, and possibly others @@ -80,6 +87,15 @@ action="store_true", help=DISABLE_DEBUGGER_DETECTION_DESC, ) + group.addoption( + "--session-timeout", + action="store", + dest="session_timeout", + default=None, + type=float, + metavar="SECONDS", + help=SESSION_TIMEOUT_DESC, + ) parser.addini("timeout", TIMEOUT_DESC) parser.addini("timeout_method", METHOD_DESC) parser.addini("timeout_func_only", FUNC_ONLY_DESC, type="bool", default=False) @@ -89,6 +105,7 @@ type="bool", default=False, ) + parser.addini("session_timeout", SESSION_TIMEOUT_DESC) class TimeoutHooks: @@ -144,6 +161,19 @@ config._env_timeout_func_only = settings.func_only config._env_timeout_disable_debugger_detection = settings.disable_debugger_detection + timeout = config.getoption("session_timeout") + if timeout is None: + ini = config.getini("session_timeout") + if ini: + timeout = _validate_timeout(config.getini("session_timeout"), "config file") + if timeout is not None: + expire_time = time.time() + timeout + else: + expire_time = 0 + timeout = 0 + config.stash[SESSION_TIMEOUT_KEY] = timeout + config.stash[SESSION_EXPIRE_KEY] = expire_time + @pytest.hookimpl(hookwrapper=True) def pytest_runtest_protocol(item): @@ -162,6 +192,12 @@ if is_timeout and settings.func_only is False: hooks.pytest_timeout_cancel_timer(item=item) + # check session timeout + expire_time = item.session.config.stash[SESSION_EXPIRE_KEY] + if expire_time and (expire_time < time.time()): + timeout = item.session.config.stash[SESSION_TIMEOUT_KEY] + item.session.shouldfail = f"session-timeout: {timeout} sec exceeded" + @pytest.hookimpl(hookwrapper=True) def pytest_runtest_call(item): @@ -183,15 +219,23 @@ @pytest.hookimpl(tryfirst=True) def pytest_report_header(config): """Add timeout config to pytest header.""" + timeout_header = [] + if config._env_timeout: - return [ + timeout_header.append( "timeout: %ss\ntimeout method: %s\ntimeout func_only: %s" % ( config._env_timeout, config._env_timeout_method, config._env_timeout_func_only, ) - ] + ) + + session_timeout = config.getoption("session_timeout") + if session_timeout: + timeout_header.append("session timeout: %ss" % session_timeout) + if timeout_header: + return timeout_header @pytest.hookimpl(tryfirst=True) @@ -236,8 +280,13 @@ return True if trace_func is None: trace_func = sys.gettrace() - if trace_func and inspect.getmodule(trace_func): - parts = inspect.getmodule(trace_func).__name__.split(".") + trace_module = None + if trace_func: + trace_module = inspect.getmodule(trace_func) or inspect.getmodule( + trace_func.__class__ + ) + if trace_module: + parts = trace_module.__name__.split(".") for name in KNOWN_DEBUGGING_MODULES: if any(part.startswith(name) for part in parts): return True @@ -440,11 +489,12 @@ return __tracebackhide__ = True nthreads = len(threading.enumerate()) + terminal = item.config.get_terminal_writer() if nthreads > 1: - write_title("Timeout", sep="+") - dump_stacks() + terminal.sep("+", title="Timeout") + dump_stacks(terminal) if nthreads > 1: - write_title("Timeout", sep="+") + terminal.sep("+", title="Timeout") pytest.fail("Timeout >%ss" % settings.timeout) @@ -456,6 +506,7 @@ """ if not settings.disable_debugger_detection and is_debugging(): return + terminal = item.config.get_terminal_writer() try: capman = item.config.pluginmanager.getplugin("capturemanager") if capman: @@ -463,30 +514,31 @@ stdout, stderr = capman.read_global_capture() else: stdout, stderr = None, None - write_title("Timeout", sep="+") + terminal.sep("+", title="Timeout") caplog = item.config.pluginmanager.getplugin("_capturelog") if caplog and hasattr(item, "capturelog_handler"): log = item.capturelog_handler.stream.getvalue() if log: - write_title("Captured log") - write(log) + terminal.sep("~", title="Captured log") + terminal.write(log) if stdout: - write_title("Captured stdout") - write(stdout) + terminal.sep("~", title="Captured stdout") + terminal.write(stdout) if stderr: - write_title("Captured stderr") - write(stderr) - dump_stacks() - write_title("Timeout", sep="+") + terminal.sep("~", title="Captured stderr") + terminal.write(stderr) + dump_stacks(terminal) + terminal.sep("+", title="Timeout") except Exception: traceback.print_exc() finally: + terminal.flush() sys.stdout.flush() sys.stderr.flush() os._exit(1) -def dump_stacks(): +def dump_stacks(terminal): """Dump the stacks of all threads except the current thread.""" current_ident = threading.current_thread().ident for thread_ident, frame in sys._current_frames().items(): @@ -498,31 +550,5 @@ break else: thread_name = "<unknown>" - write_title("Stack of %s (%s)" % (thread_name, thread_ident)) - write("".join(traceback.format_stack(frame))) - - -def write_title(title, stream=None, sep="~"): - """Write a section title. - - If *stream* is None sys.stderr will be used, *sep* is used to - draw the line. - """ - if stream is None: - stream = sys.stderr - width, height = shutil.get_terminal_size() - fill = int((width - len(title) - 2) / 2) - line = " ".join([sep * fill, title, sep * fill]) - if len(line) < width: - line += sep * (width - len(line)) - stream.write("\n" + line + "\n") - - -def write(text, stream=None): - """Write text to stream. - - Pretty stupid really, only here for symmetry with .write_title(). - """ - if stream is None: - stream = sys.stderr - stream.write(text) + terminal.sep("~", title="Stack of %s (%s)" % (thread_name, thread_ident)) + terminal.write("".join(traceback.format_stack(frame))) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pytest-timeout-2.2.0/setup.cfg new/pytest-timeout-2.3.1/setup.cfg --- old/pytest-timeout-2.2.0/setup.cfg 2023-10-08 12:13:57.969030000 +0200 +++ new/pytest-timeout-2.3.1/setup.cfg 2024-03-07 22:03:27.609297800 +0100 @@ -2,7 +2,8 @@ name = pytest-timeout description = pytest plugin to abort hanging tests long_description = file: README.rst -version = 2.2.0 +long_description_content_type = text/x-rst +version = 2.3.1 author = Floris Bruynooghe author_email = f...@devork.be url = https://github.com/pytest-dev/pytest-timeout @@ -31,7 +32,7 @@ [options] py_modules = pytest_timeout install_requires = - pytest>=5.0.0 + pytest>=7.0.0 python_requires = >=3.7 [options.entry_points] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pytest-timeout-2.2.0/test_pytest_timeout.py new/pytest-timeout-2.3.1/test_pytest_timeout.py --- old/pytest-timeout-2.2.0/test_pytest_timeout.py 2023-10-04 21:07:44.000000000 +0200 +++ new/pytest-timeout-2.3.1/test_pytest_timeout.py 2024-03-07 21:51:08.000000000 +0100 @@ -16,30 +16,26 @@ ) -@pytest.fixture -def testdir(testdir): - if hasattr(testdir, "runpytest_subprocess"): - # on pytest-2.8 runpytest runs inline by default - # patch the testdir instance to use the subprocess method - testdir.runpytest = testdir.runpytest_subprocess - return testdir - - -def test_header(testdir): - testdir.makepyfile( +def test_header(pytester): + pytester.makepyfile( """ def test_x(): pass """ ) - result = testdir.runpytest("--timeout=1") + result = pytester.runpytest_subprocess("--timeout=1", "--session-timeout=2") result.stdout.fnmatch_lines( - ["timeout: 1.0s", "timeout method:*", "timeout func_only:*"] + [ + "timeout: 1.0s", + "timeout method:*", + "timeout func_only:*", + "session timeout: 2.0s", + ] ) @have_sigalrm -def test_sigalrm(testdir): - testdir.makepyfile( +def test_sigalrm(pytester): + pytester.makepyfile( """ import time @@ -47,12 +43,12 @@ time.sleep(2) """ ) - result = testdir.runpytest("--timeout=1") + result = pytester.runpytest_subprocess("--timeout=1") result.stdout.fnmatch_lines(["*Failed: Timeout >1.0s*"]) -def test_thread(testdir): - testdir.makepyfile( +def test_thread(pytester): + pytester.makepyfile( """ import time @@ -60,8 +56,8 @@ time.sleep(2) """ ) - result = testdir.runpytest("--timeout=1", "--timeout-method=thread") - result.stderr.fnmatch_lines( + result = pytester.runpytest_subprocess("--timeout=1", "--timeout-method=thread") + result.stdout.fnmatch_lines( [ "*++ Timeout ++*", "*~~ Stack of MainThread* ~~*", @@ -69,16 +65,16 @@ "*++ Timeout ++*", ] ) - assert "++ Timeout ++" in result.stderr.lines[-1] + assert "++ Timeout ++" in result.stdout.lines[-1] @pytest.mark.skipif( hasattr(sys, "pypy_version_info"), reason="pypy coverage seems broken currently" ) -def test_cov(testdir): +def test_cov(pytester): # This test requires pytest-cov pytest.importorskip("pytest_cov") - testdir.makepyfile( + pytester.makepyfile( """ import time @@ -86,10 +82,10 @@ time.sleep(2) """ ) - result = testdir.runpytest( + result = pytester.runpytest_subprocess( "--timeout=1", "--cov=test_cov", "--timeout-method=thread" ) - result.stderr.fnmatch_lines( + result.stdout.fnmatch_lines( [ "*++ Timeout ++*", "*~~ Stack of MainThread* ~~*", @@ -97,11 +93,11 @@ "*++ Timeout ++*", ] ) - assert "++ Timeout ++" in result.stderr.lines[-1] + assert "++ Timeout ++" in result.stdout.lines[-1] -def test_timeout_env(testdir, monkeypatch): - testdir.makepyfile( +def test_timeout_env(pytester, monkeypatch): + pytester.makepyfile( """ import time @@ -110,13 +106,13 @@ """ ) monkeypatch.setitem(os.environ, "PYTEST_TIMEOUT", "1") - result = testdir.runpytest() + result = pytester.runpytest_subprocess() assert result.ret > 0 # @pytest.mark.parametrize('meth', [have_sigalrm('signal'), 'thread']) -# def test_func_fix(meth, testdir): -# testdir.makepyfile(""" +# def test_func_fix(meth, pytester): +# pytester.makepyfile(""" # import time, pytest # @pytest.fixture(scope='function') @@ -126,7 +122,7 @@ # def test_foo(fix): # pass # """) -# result = testdir.runpytest('--timeout=1', +# result = pytester.runpytest_subprocess('--timeout=1', # '--timeout-method={0}'.format(meth)) # assert result.ret > 0 # assert 'Timeout' in result.stdout.str() + result.stderr.str() @@ -134,8 +130,8 @@ @pytest.mark.parametrize("meth", [pytest.param("signal", marks=have_sigalrm), "thread"]) @pytest.mark.parametrize("scope", ["function", "class", "module", "session"]) -def test_fix_setup(meth, scope, testdir): - testdir.makepyfile( +def test_fix_setup(meth, scope, pytester): + pytester.makepyfile( """ import time, pytest @@ -151,13 +147,13 @@ scope=scope ) ) - result = testdir.runpytest("--timeout=1", f"--timeout-method={meth}") + result = pytester.runpytest_subprocess("--timeout=1", f"--timeout-method={meth}") assert result.ret > 0 assert "Timeout" in result.stdout.str() + result.stderr.str() -def test_fix_setup_func_only(testdir): - testdir.makepyfile( +def test_fix_setup_func_only(pytester): + pytester.makepyfile( """ import time, pytest @@ -172,15 +168,15 @@ pass """ ) - result = testdir.runpytest("--timeout=1") + result = pytester.runpytest_subprocess("--timeout=1") assert result.ret == 0 assert "Timeout" not in result.stdout.str() + result.stderr.str() @pytest.mark.parametrize("meth", [pytest.param("signal", marks=have_sigalrm), "thread"]) @pytest.mark.parametrize("scope", ["function", "class", "module", "session"]) -def test_fix_finalizer(meth, scope, testdir): - testdir.makepyfile( +def test_fix_finalizer(meth, scope, pytester): + pytester.makepyfile( """ import time, pytest @@ -198,13 +194,15 @@ pass """ ) - result = testdir.runpytest("--timeout=1", "-s", f"--timeout-method={meth}") + result = pytester.runpytest_subprocess( + "--timeout=1", "-s", f"--timeout-method={meth}" + ) assert result.ret > 0 assert "Timeout" in result.stdout.str() + result.stderr.str() -def test_fix_finalizer_func_only(testdir): - testdir.makepyfile( +def test_fix_finalizer_func_only(pytester): + pytester.makepyfile( """ import time, pytest @@ -223,14 +221,14 @@ pass """ ) - result = testdir.runpytest("--timeout=1", "-s") + result = pytester.runpytest_subprocess("--timeout=1", "-s") assert result.ret == 0 assert "Timeout" not in result.stdout.str() + result.stderr.str() @have_sigalrm -def test_timeout_mark_sigalrm(testdir): - testdir.makepyfile( +def test_timeout_mark_sigalrm(pytester): + pytester.makepyfile( """ import time, pytest @@ -240,12 +238,12 @@ assert False """ ) - result = testdir.runpytest() + result = pytester.runpytest_subprocess() result.stdout.fnmatch_lines(["*Failed: Timeout >1.0s*"]) -def test_timeout_mark_timer(testdir): - testdir.makepyfile( +def test_timeout_mark_timer(pytester): + pytester.makepyfile( """ import time, pytest @@ -254,12 +252,12 @@ time.sleep(2) """ ) - result = testdir.runpytest("--timeout-method=thread") - result.stderr.fnmatch_lines(["*++ Timeout ++*"]) + result = pytester.runpytest_subprocess("--timeout-method=thread") + result.stdout.fnmatch_lines(["*++ Timeout ++*"]) -def test_timeout_mark_non_int(testdir): - testdir.makepyfile( +def test_timeout_mark_non_int(pytester): + pytester.makepyfile( """ import time, pytest @@ -268,12 +266,12 @@ time.sleep(1) """ ) - result = testdir.runpytest("--timeout-method=thread") - result.stderr.fnmatch_lines(["*++ Timeout ++*"]) + result = pytester.runpytest_subprocess("--timeout-method=thread") + result.stdout.fnmatch_lines(["*++ Timeout ++*"]) -def test_timeout_mark_non_number(testdir): - testdir.makepyfile( +def test_timeout_mark_non_number(pytester): + pytester.makepyfile( """ import pytest @@ -282,12 +280,12 @@ pass """ ) - result = testdir.runpytest() + result = pytester.runpytest_subprocess() result.stdout.fnmatch_lines(["*ValueError*"]) -def test_timeout_mark_args(testdir): - testdir.makepyfile( +def test_timeout_mark_args(pytester): + pytester.makepyfile( """ import pytest @@ -296,12 +294,12 @@ pass """ ) - result = testdir.runpytest() + result = pytester.runpytest_subprocess() result.stdout.fnmatch_lines(["*ValueError*"]) -def test_timeout_mark_method_nokw(testdir): - testdir.makepyfile( +def test_timeout_mark_method_nokw(pytester): + pytester.makepyfile( """ import time, pytest @@ -310,12 +308,12 @@ time.sleep(2) """ ) - result = testdir.runpytest() - result.stderr.fnmatch_lines(["*+ Timeout +*"]) + result = pytester.runpytest_subprocess() + result.stdout.fnmatch_lines(["*+ Timeout +*"]) -def test_timeout_mark_noargs(testdir): - testdir.makepyfile( +def test_timeout_mark_noargs(pytester): + pytester.makepyfile( """ import pytest @@ -324,12 +322,12 @@ pass """ ) - result = testdir.runpytest() + result = pytester.runpytest_subprocess() result.stdout.fnmatch_lines(["*TypeError*"]) -def test_ini_timeout(testdir): - testdir.makepyfile( +def test_ini_timeout(pytester): + pytester.makepyfile( """ import time @@ -337,18 +335,18 @@ time.sleep(2) """ ) - testdir.makeini( + pytester.makeini( """ [pytest] timeout = 1 """ ) - result = testdir.runpytest() + result = pytester.runpytest_subprocess() assert result.ret -def test_ini_timeout_func_only(testdir): - testdir.makepyfile( +def test_ini_timeout_func_only(pytester): + pytester.makepyfile( """ import time, pytest @@ -359,19 +357,19 @@ pass """ ) - testdir.makeini( + pytester.makeini( """ [pytest] timeout = 1 timeout_func_only = true """ ) - result = testdir.runpytest() + result = pytester.runpytest_subprocess() assert result.ret == 0 -def test_ini_timeout_func_only_marker_override(testdir): - testdir.makepyfile( +def test_ini_timeout_func_only_marker_override(pytester): + pytester.makepyfile( """ import time, pytest @@ -383,19 +381,19 @@ pass """ ) - testdir.makeini( + pytester.makeini( """ [pytest] timeout = 1 timeout_func_only = true """ ) - result = testdir.runpytest() + result = pytester.runpytest_subprocess() assert result.ret == 0 -def test_ini_method(testdir): - testdir.makepyfile( +def test_ini_method(pytester): + pytester.makepyfile( """ import time @@ -403,19 +401,19 @@ time.sleep(2) """ ) - testdir.makeini( + pytester.makeini( """ [pytest] timeout = 1 timeout_method = thread """ ) - result = testdir.runpytest() + result = pytester.runpytest_subprocess() assert "=== 1 failed in " not in result.outlines[-1] -def test_timeout_marker_inheritance(testdir): - testdir.makepyfile( +def test_timeout_marker_inheritance(pytester): + pytester.makepyfile( """ import time, pytest @@ -430,13 +428,13 @@ time.sleep(1) """ ) - result = testdir.runpytest("--timeout=1", "-s") + result = pytester.runpytest_subprocess("--timeout=1", "-s") assert result.ret == 0 assert "Timeout" not in result.stdout.str() + result.stderr.str() -def test_marker_help(testdir): - result = testdir.runpytest("--markers") +def test_marker_help(pytester): + result = pytester.runpytest_subprocess("--markers") result.stdout.fnmatch_lines(["@pytest.mark.timeout(*"]) @@ -461,9 +459,9 @@ ) @have_spawn def test_suppresses_timeout_when_debugger_is_entered( - testdir, debugging_module, debugging_set_trace + pytester, debugging_module, debugging_set_trace ): - p1 = testdir.makepyfile( + p1 = pytester.makepyfile( """ import pytest, {debugging_module} @@ -474,7 +472,7 @@ debugging_module=debugging_module, debugging_set_trace=debugging_set_trace ) ) - child = testdir.spawn_pytest(str(p1)) + child = pytester.spawn_pytest(str(p1)) child.expect("test_foo") time.sleep(0.2) child.send("c\n") @@ -507,9 +505,9 @@ ) @have_spawn def test_disable_debugger_detection_flag( - testdir, debugging_module, debugging_set_trace + pytester, debugging_module, debugging_set_trace ): - p1 = testdir.makepyfile( + p1 = pytester.makepyfile( """ import pytest, {debugging_module} @@ -520,7 +518,7 @@ debugging_module=debugging_module, debugging_set_trace=debugging_set_trace ) ) - child = testdir.spawn_pytest(f"{p1} --timeout-disable-debugger-detection") + child = pytester.spawn_pytest(f"{p1} --timeout-disable-debugger-detection") child.expect("test_foo") time.sleep(1.2) result = child.read().decode().lower() @@ -551,8 +549,9 @@ assert pytest_timeout.is_debugging(custom_trace) -def test_not_main_thread(testdir): - testdir.makepyfile( +def test_not_main_thread(pytester): + pytest.skip("The 'pytest_timeout.timeout_setup' function no longer exists") + pytester.makepyfile( """ import threading import pytest_timeout @@ -569,14 +568,14 @@ def test_x(): pass """ ) - result = testdir.runpytest("--timeout=1") + result = pytester.runpytest_subprocess("--timeout=1") result.stdout.fnmatch_lines( ["timeout: 1.0s", "timeout method:*", "timeout func_only:*"] ) -def test_plugin_interface(testdir): - testdir.makeconftest( +def test_plugin_interface(pytester): + pytester.makeconftest( """ import pytest @@ -593,7 +592,7 @@ return True """ ) - testdir.makepyfile( + pytester.makepyfile( """ import pytest @@ -602,10 +601,60 @@ pass """ ) - result = testdir.runpytest("-s") + result = pytester.runpytest_subprocess("-s") result.stdout.fnmatch_lines( [ "pytest_timeout_set_timer", "pytest_timeout_cancel_timer", ] ) + + +def test_session_timeout(pytester): + # This is designed to timeout during hte first test to ensure + # - the first test still runs to completion + # - the second test is not started + pytester.makepyfile( + """ + import time, pytest + + @pytest.fixture() + def slow_setup_and_teardown(): + time.sleep(1) + yield + time.sleep(1) + + def test_one(slow_setup_and_teardown): + time.sleep(1) + + def test_two(slow_setup_and_teardown): + time.sleep(1) + """ + ) + result = pytester.runpytest_subprocess("--session-timeout", "2") + result.stdout.fnmatch_lines(["*!! session-timeout: 2.0 sec exceeded !!!*"]) + # This would be 2 passed if the second test was allowed to run + result.assert_outcomes(passed=1) + + +def test_ini_session_timeout(pytester): + pytester.makepyfile( + """ + import time + + def test_one(): + time.sleep(2) + + def test_two(): + time.sleep(2) + """ + ) + pytester.makeini( + """ + [pytest] + session_timeout = 1 + """ + ) + result = pytester.runpytest_subprocess() + result.stdout.fnmatch_lines(["*!! session-timeout: 1.0 sec exceeded !!!*"]) + result.assert_outcomes(passed=1) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pytest-timeout-2.2.0/tox.ini new/pytest-timeout-2.3.1/tox.ini --- old/pytest-timeout-2.2.0/tox.ini 2023-10-04 21:07:44.000000000 +0200 +++ new/pytest-timeout-2.3.1/tox.ini 2024-02-08 20:02:43.000000000 +0100 @@ -1,9 +1,9 @@ [pytest] -minversion = 2.8 +minversion = 7.0 addopts = -ra [tox] -envlist = py37,py38,py39,py310,py311,pypy3 +envlist = py37,py38,py39,py310,py311,py312,pypy3 [testenv] deps = pytest @@ -23,5 +23,3 @@ [flake8] disable-noqa = True max-line-length = 88 -extend-ignore = - E203 # whitespace before : is not PEP8 compliant (& conflicts with black)