diff options
| author | shadchin <[email protected]> | 2022-02-10 16:44:39 +0300 |
|---|---|---|
| committer | Daniil Cherednik <[email protected]> | 2022-02-10 16:44:39 +0300 |
| commit | e9656aae26e0358d5378e5b63dcac5c8dbe0e4d0 (patch) | |
| tree | 64175d5cadab313b3e7039ebaa06c5bc3295e274 /contrib/python/pytest/py2/_pytest/logging.py | |
| parent | 2598ef1d0aee359b4b6d5fdd1758916d5907d04f (diff) | |
Restoring authorship annotation for <[email protected]>. Commit 2 of 2.
Diffstat (limited to 'contrib/python/pytest/py2/_pytest/logging.py')
| -rw-r--r-- | contrib/python/pytest/py2/_pytest/logging.py | 306 |
1 files changed, 153 insertions, 153 deletions
diff --git a/contrib/python/pytest/py2/_pytest/logging.py b/contrib/python/pytest/py2/_pytest/logging.py index 0f94f361db7..2400737ee4e 100644 --- a/contrib/python/pytest/py2/_pytest/logging.py +++ b/contrib/python/pytest/py2/_pytest/logging.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +# -*- coding: utf-8 -*- """ Access and control log capturing. """ from __future__ import absolute_import from __future__ import division @@ -14,17 +14,17 @@ import six import pytest from _pytest.compat import dummy_context_manager from _pytest.config import create_terminal_writer -from _pytest.pathlib import Path +from _pytest.pathlib import Path -DEFAULT_LOG_FORMAT = "%(levelname)-8s %(name)s:%(filename)s:%(lineno)d %(message)s" +DEFAULT_LOG_FORMAT = "%(levelname)-8s %(name)s:%(filename)s:%(lineno)d %(message)s" DEFAULT_LOG_DATE_FORMAT = "%H:%M:%S" -_ANSI_ESCAPE_SEQ = re.compile(r"\x1b\[[\d;]+m") +_ANSI_ESCAPE_SEQ = re.compile(r"\x1b\[[\d;]+m") + + +def _remove_ansi_escape_sequences(text): + return _ANSI_ESCAPE_SEQ.sub("", text) -def _remove_ansi_escape_sequences(text): - return _ANSI_ESCAPE_SEQ.sub("", text) - - class ColoredLevelFormatter(logging.Formatter): """ Colorize the %(levelname)..s part of the log format passed to __init__. @@ -77,36 +77,36 @@ class ColoredLevelFormatter(logging.Formatter): return super(ColoredLevelFormatter, self).format(record) -if not six.PY2: - # Formatter classes don't support format styles in PY2 - - class PercentStyleMultiline(logging.PercentStyle): - """A logging style with special support for multiline messages. - - If the message of a record consists of multiple lines, this style - formats the message as if each line were logged separately. - """ - - @staticmethod - def _update_message(record_dict, message): - tmp = record_dict.copy() - tmp["message"] = message - return tmp - - def format(self, record): - if "\n" in record.message: - lines = record.message.splitlines() - formatted = self._fmt % self._update_message(record.__dict__, lines[0]) - # TODO optimize this by introducing an option that tells the - # logging framework that the indentation doesn't - # change. This allows to compute the indentation only once. - indentation = _remove_ansi_escape_sequences(formatted).find(lines[0]) - lines[0] = formatted - return ("\n" + " " * indentation).join(lines) - else: - return self._fmt % record.__dict__ - - +if not six.PY2: + # Formatter classes don't support format styles in PY2 + + class PercentStyleMultiline(logging.PercentStyle): + """A logging style with special support for multiline messages. + + If the message of a record consists of multiple lines, this style + formats the message as if each line were logged separately. + """ + + @staticmethod + def _update_message(record_dict, message): + tmp = record_dict.copy() + tmp["message"] = message + return tmp + + def format(self, record): + if "\n" in record.message: + lines = record.message.splitlines() + formatted = self._fmt % self._update_message(record.__dict__, lines[0]) + # TODO optimize this by introducing an option that tells the + # logging framework that the indentation doesn't + # change. This allows to compute the indentation only once. + indentation = _remove_ansi_escape_sequences(formatted).find(lines[0]) + lines[0] = formatted + return ("\n" + " " * indentation).join(lines) + else: + return self._fmt % record.__dict__ + + def get_option_ini(config, *names): for name in names: ret = config.getoption(name) # 'default' arg won't work as expected @@ -253,7 +253,7 @@ class LogCaptureFixture(object): """Creates a new funcarg.""" self._item = item # dict of log name -> log level - self._initial_log_levels = {} # Dict[str, int] + self._initial_log_levels = {} # Dict[str, int] def _finalize(self): """Finalizes the fixture. @@ -292,8 +292,8 @@ class LogCaptureFixture(object): @property def text(self): - """Returns the formatted log text.""" - return _remove_ansi_escape_sequences(self.handler.stream.getvalue()) + """Returns the formatted log text.""" + return _remove_ansi_escape_sequences(self.handler.stream.getvalue()) @property def records(self): @@ -406,8 +406,8 @@ def get_actual_log_level(config, *setting_names): ) -# run after terminalreporter/capturemanager are configured [email protected](trylast=True) +# run after terminalreporter/capturemanager are configured [email protected](trylast=True) def pytest_configure(config): config.pluginmanager.register(LoggingPlugin(config), "logging-plugin") @@ -425,99 +425,99 @@ class LoggingPlugin(object): self._config = config self.print_logs = get_option_ini(config, "log_print") - self.formatter = self._create_formatter( + self.formatter = self._create_formatter( get_option_ini(config, "log_format"), get_option_ini(config, "log_date_format"), ) self.log_level = get_actual_log_level(config, "log_level") - self.log_file_level = get_actual_log_level(config, "log_file_level") - self.log_file_format = get_option_ini(config, "log_file_format", "log_format") - self.log_file_date_format = get_option_ini( - config, "log_file_date_format", "log_date_format" - ) - self.log_file_formatter = logging.Formatter( - self.log_file_format, datefmt=self.log_file_date_format - ) - + self.log_file_level = get_actual_log_level(config, "log_file_level") + self.log_file_format = get_option_ini(config, "log_file_format", "log_format") + self.log_file_date_format = get_option_ini( + config, "log_file_date_format", "log_date_format" + ) + self.log_file_formatter = logging.Formatter( + self.log_file_format, datefmt=self.log_file_date_format + ) + log_file = get_option_ini(config, "log_file") if log_file: self.log_file_handler = logging.FileHandler( log_file, mode="w", encoding="UTF-8" ) - self.log_file_handler.setFormatter(self.log_file_formatter) + self.log_file_handler.setFormatter(self.log_file_formatter) else: self.log_file_handler = None self.log_cli_handler = None - self.live_logs_context = lambda: dummy_context_manager() - # Note that the lambda for the live_logs_context is needed because - # live_logs_context can otherwise not be entered multiple times due - # to limitations of contextlib.contextmanager. - - if self._log_cli_enabled(): - self._setup_cli_logging() - - def _create_formatter(self, log_format, log_date_format): - # color option doesn't exist if terminal plugin is disabled - color = getattr(self._config.option, "color", "no") - if color != "no" and ColoredLevelFormatter.LEVELNAME_FMT_REGEX.search( - log_format - ): - formatter = ColoredLevelFormatter( - create_terminal_writer(self._config), log_format, log_date_format - ) - else: - formatter = logging.Formatter(log_format, log_date_format) - - if not six.PY2: - formatter._style = PercentStyleMultiline(formatter._style._fmt) - return formatter - - def _setup_cli_logging(self): - config = self._config - terminal_reporter = config.pluginmanager.get_plugin("terminalreporter") - if terminal_reporter is None: - # terminal reporter is disabled e.g. by pytest-xdist. - return - - capture_manager = config.pluginmanager.get_plugin("capturemanager") - # if capturemanager plugin is disabled, live logging still works. - log_cli_handler = _LiveLoggingStreamHandler(terminal_reporter, capture_manager) - - log_cli_formatter = self._create_formatter( - get_option_ini(config, "log_cli_format", "log_format"), - get_option_ini(config, "log_cli_date_format", "log_date_format"), - ) - - log_cli_level = get_actual_log_level(config, "log_cli_level", "log_level") - self.log_cli_handler = log_cli_handler - self.live_logs_context = lambda: catching_logs( - log_cli_handler, formatter=log_cli_formatter, level=log_cli_level - ) - - def set_log_path(self, fname): - """Public method, which can set filename parameter for - Logging.FileHandler(). Also creates parent directory if - it does not exist. - - .. warning:: - Please considered as an experimental API. - """ - fname = Path(fname) - - if not fname.is_absolute(): - fname = Path(self._config.rootdir, fname) - - if not fname.parent.exists(): - fname.parent.mkdir(exist_ok=True, parents=True) - - self.log_file_handler = logging.FileHandler( - str(fname), mode="w", encoding="UTF-8" - ) - self.log_file_handler.setFormatter(self.log_file_formatter) - + self.live_logs_context = lambda: dummy_context_manager() + # Note that the lambda for the live_logs_context is needed because + # live_logs_context can otherwise not be entered multiple times due + # to limitations of contextlib.contextmanager. + + if self._log_cli_enabled(): + self._setup_cli_logging() + + def _create_formatter(self, log_format, log_date_format): + # color option doesn't exist if terminal plugin is disabled + color = getattr(self._config.option, "color", "no") + if color != "no" and ColoredLevelFormatter.LEVELNAME_FMT_REGEX.search( + log_format + ): + formatter = ColoredLevelFormatter( + create_terminal_writer(self._config), log_format, log_date_format + ) + else: + formatter = logging.Formatter(log_format, log_date_format) + + if not six.PY2: + formatter._style = PercentStyleMultiline(formatter._style._fmt) + return formatter + + def _setup_cli_logging(self): + config = self._config + terminal_reporter = config.pluginmanager.get_plugin("terminalreporter") + if terminal_reporter is None: + # terminal reporter is disabled e.g. by pytest-xdist. + return + + capture_manager = config.pluginmanager.get_plugin("capturemanager") + # if capturemanager plugin is disabled, live logging still works. + log_cli_handler = _LiveLoggingStreamHandler(terminal_reporter, capture_manager) + + log_cli_formatter = self._create_formatter( + get_option_ini(config, "log_cli_format", "log_format"), + get_option_ini(config, "log_cli_date_format", "log_date_format"), + ) + + log_cli_level = get_actual_log_level(config, "log_cli_level", "log_level") + self.log_cli_handler = log_cli_handler + self.live_logs_context = lambda: catching_logs( + log_cli_handler, formatter=log_cli_formatter, level=log_cli_level + ) + + def set_log_path(self, fname): + """Public method, which can set filename parameter for + Logging.FileHandler(). Also creates parent directory if + it does not exist. + + .. warning:: + Please considered as an experimental API. + """ + fname = Path(fname) + + if not fname.is_absolute(): + fname = Path(self._config.rootdir, fname) + + if not fname.parent.exists(): + fname.parent.mkdir(exist_ok=True, parents=True) + + self.log_file_handler = logging.FileHandler( + str(fname), mode="w", encoding="UTF-8" + ) + self.log_file_handler.setFormatter(self.log_file_formatter) + def _log_cli_enabled(self): """Return True if log_cli should be considered enabled, either explicitly or because --log-cli-level was given in the command-line. @@ -540,15 +540,15 @@ class LoggingPlugin(object): @contextmanager def _runtest_for(self, item, when): - with self._runtest_for_main(item, when): - if self.log_file_handler is not None: - with catching_logs(self.log_file_handler, level=self.log_file_level): - yield - else: - yield - - @contextmanager - def _runtest_for_main(self, item, when): + with self._runtest_for_main(item, when): + if self.log_file_handler is not None: + with catching_logs(self.log_file_handler, level=self.log_file_level): + yield + else: + yield + + @contextmanager + def _runtest_for_main(self, item, when): """Implements the internals of pytest_runtest_xxx() hook.""" with catching_logs( LogCaptureHandler(), formatter=self.formatter, level=self.log_level @@ -603,26 +603,26 @@ class LoggingPlugin(object): with self._runtest_for(None, "finish"): yield - @pytest.hookimpl(hookwrapper=True) - def pytest_runtest_logreport(self): - with self._runtest_for(None, "logreport"): - yield - + @pytest.hookimpl(hookwrapper=True) + def pytest_runtest_logreport(self): + with self._runtest_for(None, "logreport"): + yield + @pytest.hookimpl(hookwrapper=True, tryfirst=True) def pytest_sessionfinish(self): with self.live_logs_context(): if self.log_cli_handler: self.log_cli_handler.set_when("sessionfinish") if self.log_file_handler is not None: - try: - with catching_logs( - self.log_file_handler, level=self.log_file_level - ): - yield - finally: - # Close the FileHandler explicitly. - # (logging.shutdown might have lost the weakref?!) - self.log_file_handler.close() + try: + with catching_logs( + self.log_file_handler, level=self.log_file_level + ): + yield + finally: + # Close the FileHandler explicitly. + # (logging.shutdown might have lost the weakref?!) + self.log_file_handler.close() else: yield @@ -640,15 +640,15 @@ class LoggingPlugin(object): @pytest.hookimpl(hookwrapper=True) def pytest_runtestloop(self, session): """Runs all collected test items.""" - - if session.config.option.collectonly: - yield - return - - if self._log_cli_enabled() and self._config.getoption("verbose") < 1: - # setting verbose flag is needed to avoid messy test progress output - self._config.option.verbose = 1 - + + if session.config.option.collectonly: + yield + return + + if self._log_cli_enabled() and self._config.getoption("verbose") < 1: + # setting verbose flag is needed to avoid messy test progress output + self._config.option.verbose = 1 + with self.live_logs_context(): if self.log_file_handler is not None: with catching_logs(self.log_file_handler, level=self.log_file_level): |
