diff options
author | shadchin <shadchin@yandex-team.ru> | 2022-02-10 16:44:39 +0300 |
---|---|---|
committer | Daniil Cherednik <dcherednik@yandex-team.ru> | 2022-02-10 16:44:39 +0300 |
commit | e9656aae26e0358d5378e5b63dcac5c8dbe0e4d0 (patch) | |
tree | 64175d5cadab313b3e7039ebaa06c5bc3295e274 /contrib/python/pytest/py3/_pytest/faulthandler.py | |
parent | 2598ef1d0aee359b4b6d5fdd1758916d5907d04f (diff) | |
download | ydb-e9656aae26e0358d5378e5b63dcac5c8dbe0e4d0.tar.gz |
Restoring authorship annotation for <shadchin@yandex-team.ru>. Commit 2 of 2.
Diffstat (limited to 'contrib/python/pytest/py3/_pytest/faulthandler.py')
-rw-r--r-- | contrib/python/pytest/py3/_pytest/faulthandler.py | 232 |
1 files changed, 116 insertions, 116 deletions
diff --git a/contrib/python/pytest/py3/_pytest/faulthandler.py b/contrib/python/pytest/py3/_pytest/faulthandler.py index 43eb5f3ff2..ff673b5b16 100644 --- a/contrib/python/pytest/py3/_pytest/faulthandler.py +++ b/contrib/python/pytest/py3/_pytest/faulthandler.py @@ -1,116 +1,116 @@ -import io -import os -import sys -from typing import Generator -from typing import TextIO - -import pytest -from _pytest.config import Config -from _pytest.config.argparsing import Parser -from _pytest.nodes import Item -from _pytest.store import StoreKey - - -fault_handler_stderr_key = StoreKey[TextIO]() - - -def pytest_addoption(parser: Parser) -> None: - help = ( - "Dump the traceback of all threads if a test takes " - "more than TIMEOUT seconds to finish." - ) - parser.addini("faulthandler_timeout", help, default=0.0) - - -def pytest_configure(config: Config) -> None: - import faulthandler - - if not faulthandler.is_enabled(): - # faulthhandler is not enabled, so install plugin that does the actual work - # of enabling faulthandler before each test executes. - config.pluginmanager.register(FaultHandlerHooks(), "faulthandler-hooks") - else: - # Do not handle dumping to stderr if faulthandler is already enabled, so warn - # users that the option is being ignored. - timeout = FaultHandlerHooks.get_timeout_config_value(config) - if timeout > 0: - config.issue_config_time_warning( - pytest.PytestConfigWarning( - "faulthandler module enabled before pytest configuration step, " - "'faulthandler_timeout' option ignored" - ), - stacklevel=2, - ) - - -class FaultHandlerHooks: - """Implements hooks that will actually install fault handler before tests execute, - as well as correctly handle pdb and internal errors.""" - - def pytest_configure(self, config: Config) -> None: - import faulthandler - - stderr_fd_copy = os.dup(self._get_stderr_fileno()) - config._store[fault_handler_stderr_key] = open(stderr_fd_copy, "w") - faulthandler.enable(file=config._store[fault_handler_stderr_key]) - - def pytest_unconfigure(self, config: Config) -> None: - import faulthandler - - faulthandler.disable() - # close our dup file installed during pytest_configure - # re-enable the faulthandler, attaching it to the default sys.stderr - # so we can see crashes after pytest has finished, usually during - # garbage collection during interpreter shutdown - config._store[fault_handler_stderr_key].close() - del config._store[fault_handler_stderr_key] - faulthandler.enable(file=self._get_stderr_fileno()) - - @staticmethod - def _get_stderr_fileno(): - try: - fileno = sys.stderr.fileno() - # The Twisted Logger will return an invalid file descriptor since it is not backed - # by an FD. So, let's also forward this to the same code path as with pytest-xdist. - if fileno == -1: - raise AttributeError() - return fileno - except (AttributeError, io.UnsupportedOperation): - # pytest-xdist monkeypatches sys.stderr with an object that is not an actual file. - # https://docs.python.org/3/library/faulthandler.html#issue-with-file-descriptors - # This is potentially dangerous, but the best we can do. - return sys.__stderr__.fileno() - - @staticmethod - def get_timeout_config_value(config): - return float(config.getini("faulthandler_timeout") or 0.0) - - @pytest.hookimpl(hookwrapper=True, trylast=True) - def pytest_runtest_protocol(self, item: Item) -> Generator[None, None, None]: - timeout = self.get_timeout_config_value(item.config) - stderr = item.config._store[fault_handler_stderr_key] - if timeout > 0 and stderr is not None: - import faulthandler - - faulthandler.dump_traceback_later(timeout, file=stderr) - try: - yield - finally: - faulthandler.cancel_dump_traceback_later() - else: - yield - - @pytest.hookimpl(tryfirst=True) - def pytest_enter_pdb(self) -> None: - """Cancel any traceback dumping due to timeout before entering pdb.""" - import faulthandler - - faulthandler.cancel_dump_traceback_later() - - @pytest.hookimpl(tryfirst=True) - def pytest_exception_interact(self) -> None: - """Cancel any traceback dumping due to an interactive exception being - raised.""" - import faulthandler - - faulthandler.cancel_dump_traceback_later() +import io +import os +import sys +from typing import Generator +from typing import TextIO + +import pytest +from _pytest.config import Config +from _pytest.config.argparsing import Parser +from _pytest.nodes import Item +from _pytest.store import StoreKey + + +fault_handler_stderr_key = StoreKey[TextIO]() + + +def pytest_addoption(parser: Parser) -> None: + help = ( + "Dump the traceback of all threads if a test takes " + "more than TIMEOUT seconds to finish." + ) + parser.addini("faulthandler_timeout", help, default=0.0) + + +def pytest_configure(config: Config) -> None: + import faulthandler + + if not faulthandler.is_enabled(): + # faulthhandler is not enabled, so install plugin that does the actual work + # of enabling faulthandler before each test executes. + config.pluginmanager.register(FaultHandlerHooks(), "faulthandler-hooks") + else: + # Do not handle dumping to stderr if faulthandler is already enabled, so warn + # users that the option is being ignored. + timeout = FaultHandlerHooks.get_timeout_config_value(config) + if timeout > 0: + config.issue_config_time_warning( + pytest.PytestConfigWarning( + "faulthandler module enabled before pytest configuration step, " + "'faulthandler_timeout' option ignored" + ), + stacklevel=2, + ) + + +class FaultHandlerHooks: + """Implements hooks that will actually install fault handler before tests execute, + as well as correctly handle pdb and internal errors.""" + + def pytest_configure(self, config: Config) -> None: + import faulthandler + + stderr_fd_copy = os.dup(self._get_stderr_fileno()) + config._store[fault_handler_stderr_key] = open(stderr_fd_copy, "w") + faulthandler.enable(file=config._store[fault_handler_stderr_key]) + + def pytest_unconfigure(self, config: Config) -> None: + import faulthandler + + faulthandler.disable() + # close our dup file installed during pytest_configure + # re-enable the faulthandler, attaching it to the default sys.stderr + # so we can see crashes after pytest has finished, usually during + # garbage collection during interpreter shutdown + config._store[fault_handler_stderr_key].close() + del config._store[fault_handler_stderr_key] + faulthandler.enable(file=self._get_stderr_fileno()) + + @staticmethod + def _get_stderr_fileno(): + try: + fileno = sys.stderr.fileno() + # The Twisted Logger will return an invalid file descriptor since it is not backed + # by an FD. So, let's also forward this to the same code path as with pytest-xdist. + if fileno == -1: + raise AttributeError() + return fileno + except (AttributeError, io.UnsupportedOperation): + # pytest-xdist monkeypatches sys.stderr with an object that is not an actual file. + # https://docs.python.org/3/library/faulthandler.html#issue-with-file-descriptors + # This is potentially dangerous, but the best we can do. + return sys.__stderr__.fileno() + + @staticmethod + def get_timeout_config_value(config): + return float(config.getini("faulthandler_timeout") or 0.0) + + @pytest.hookimpl(hookwrapper=True, trylast=True) + def pytest_runtest_protocol(self, item: Item) -> Generator[None, None, None]: + timeout = self.get_timeout_config_value(item.config) + stderr = item.config._store[fault_handler_stderr_key] + if timeout > 0 and stderr is not None: + import faulthandler + + faulthandler.dump_traceback_later(timeout, file=stderr) + try: + yield + finally: + faulthandler.cancel_dump_traceback_later() + else: + yield + + @pytest.hookimpl(tryfirst=True) + def pytest_enter_pdb(self) -> None: + """Cancel any traceback dumping due to timeout before entering pdb.""" + import faulthandler + + faulthandler.cancel_dump_traceback_later() + + @pytest.hookimpl(tryfirst=True) + def pytest_exception_interact(self) -> None: + """Cancel any traceback dumping due to an interactive exception being + raised.""" + import faulthandler + + faulthandler.cancel_dump_traceback_later() |