diff options
Diffstat (limited to 'addons/metadata.tvshows.themoviedb.org.python/libs/debugger.py')
-rw-r--r-- | addons/metadata.tvshows.themoviedb.org.python/libs/debugger.py | 115 |
1 files changed, 115 insertions, 0 deletions
diff --git a/addons/metadata.tvshows.themoviedb.org.python/libs/debugger.py b/addons/metadata.tvshows.themoviedb.org.python/libs/debugger.py new file mode 100644 index 0000000..6414722 --- /dev/null +++ b/addons/metadata.tvshows.themoviedb.org.python/libs/debugger.py @@ -0,0 +1,115 @@ +# -*- coding: UTF-8 -*- +# +# Copyright (C) 2020, Team Kodi +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. +# pylint: disable=missing-docstring +# +# This is based on the metadata.tvmaze scrapper by Roman Miroshnychenko aka Roman V.M. + +""" +Provides a context manager that writes extended debugging info +in the Kodi log on unhandled exceptions +""" +from __future__ import absolute_import, unicode_literals + +import inspect +from contextlib import contextmanager +from platform import uname +from pprint import pformat + +import xbmc + +from .utils import logger + +try: + from typing import Text, Generator, Callable, Dict, Any # pylint: disable=unused-import +except ImportError: + pass + + +def _format_vars(variables): + # type: (Dict[Text, Any]) -> Text + """ + Format variables dictionary + + :param variables: variables dict + :type variables: dict + :return: formatted string with sorted ``var = val`` pairs + :rtype: str + """ + var_list = [(var, val) for var, val in variables.items() + if not (var.startswith('__') or var.endswith('__'))] + var_list.sort(key=lambda i: i[0]) + lines = [] + for var, val in var_list: + lines.append('{0} = {1}'.format(var, pformat(val))) + return '\n'.join(lines) + + +@contextmanager +def debug_exception(logger_func=logger.error): + # type: (Callable[[Text], None]) -> Generator[None] + """ + Diagnostic helper context manager + + It controls execution within its context and writes extended + diagnostic info to the Kodi log if an unhandled exception + happens within the context. The info includes the following items: + + - System info + - Kodi version + - Module path. + - Code fragment where the exception has happened. + - Global variables. + - Local variables. + + After logging the diagnostic info the exception is re-raised. + + Example:: + + with debug_exception(): + # Some risky code + raise RuntimeError('Fatal error!') + + :param logger_func: logger function which must accept a single argument + which is a log message. + """ + try: + yield + except Exception as exc: + frame_info = inspect.trace(5)[-1] + logger_func( + '*** Unhandled exception detected: {} {} ***'.format(type(exc), exc)) + logger_func('*** Start diagnostic info ***') + logger_func('System info: {0}'.format(uname())) + logger_func('OS info: {0}'.format( + xbmc.getInfoLabel('System.OSVersionInfo'))) + logger_func('Kodi version: {0}'.format( + xbmc.getInfoLabel('System.BuildVersion'))) + logger_func('File: {0}'.format(frame_info[1])) + context = '' + if frame_info[4] is not None: + for i, line in enumerate(frame_info[4], frame_info[2] - frame_info[5]): + if i == frame_info[2]: + context += '{0}:>{1}'.format(str(i).rjust(5), line) + else: + context += '{0}: {1}'.format(str(i).rjust(5), line) + logger_func('Code context:\n' + context) + logger_func('Global variables:\n' + + _format_vars(frame_info[0].f_globals)) + logger_func('Local variables:\n' + + _format_vars(frame_info[0].f_locals)) + logger_func('**** End diagnostic info ****') + raise exc |