# -*- coding: utf-8 -*- """ tknorris shared module Copyright (C) 2016 tknorris 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 . """ import cProfile import simplejson as json import os import pstats import time from datetime import datetime import xbmc import six from resources.lib.modules import control LOGDEBUG = xbmc.LOGDEBUG LOGERROR = xbmc.LOGERROR LOGFATAL = xbmc.LOGFATAL LOGINFO = xbmc.LOGINFO LOGNONE = xbmc.LOGNONE LOGNOTICE = xbmc.LOGNOTICE if int(control.getKodiVersion()) < 19 else xbmc.LOGINFO LOGWARNING = xbmc.LOGWARNING name = control.addonInfo('name') DEBUGPREFIX = '[COLOR red][The Crew - DEBUG ][/COLOR]' LOGPATH = xbmc.translatePath('special://logpath/') addonName = "The Crew" def log(msg, level=LOGNOTICE): debug_enabled = control.setting('addon_debug') debug_log = control.setting('debug.location') print(DEBUGPREFIX + ' Debug Enabled?: ' + str(debug_enabled)) print(DEBUGPREFIX + ' Debug Log?: ' + str(debug_log)) if not control.setting('addon_debug') == 'true': return try: if isinstance(msg, six.text_type): msg = '%s (ENCODED)' % (six.ensure_str(msg)) if not control.setting('debug.location') == '0': log_file = os.path.join(LOGPATH, 'the_crew.log') if not os.path.exists(log_file): f = open(log_file, 'w') f.close() with open(log_file, 'a') as f: line = '[%s %s] %s: %s' % (datetime.now().date(), str(datetime.now().time())[:8], DEBUGPREFIX, msg) f.write(line.rstrip('\r\n')+'\n') else: print('%s: %s' % (DEBUGPREFIX, msg)) except Exception as e: try: xbmc.log('Logging Failure: %s' % (e), level) except: pass class Profiler(object): def __init__(self, file_path, sort_by='time', builtins=False): self._profiler = cProfile.Profile(builtins=builtins) self.file_path = file_path self.sort_by = sort_by def profile(self, f): def method_profile_on(*args, **kwargs): try: self._profiler.enable() result = self._profiler.runcall(f, *args, **kwargs) self._profiler.disable() return result except Exception as e: log('Profiler Error: %s' % (e), LOGWARNING) return f(*args, **kwargs) def method_profile_off(*args, **kwargs): return f(*args, **kwargs) if _is_debugging(): return method_profile_on else: return method_profile_off def __del__(self): self.dump_stats() def dump_stats(self): if self._profiler is not None: s = six.BytesIO params = (self.sort_by,) if isinstance(self.sort_by, six.string_types) else self.sort_by ps = pstats.Stats(self._profiler, stream=s).sort_stats(*params) ps.print_stats() if self.file_path is not None: with open(self.file_path, 'w') as f: f.write(s.getvalue()) def trace(method): def method_trace_on(*args, **kwargs): start = time.time() result = method(*args, **kwargs) end = time.time() log('{name!r} time: {time:2.4f}s args: |{args!r}| kwargs: |{kwargs!r}|'.format( name=method.__name__, time=end - start, args=args, kwargs=kwargs), LOGDEBUG) return result def method_trace_off(*args, **kwargs): return method(*args, **kwargs) if _is_debugging(): return method_trace_on else: return method_trace_off def _is_debugging(): command = {'jsonrpc': '2.0', 'id': 1, 'method': 'Settings.getSettings', 'params': {'filter': {'section': 'system', 'category': 'logging'}}} js_data = execute_jsonrpc(command) for item in js_data.get('result', {}).get('settings', {}): if item['id'] == 'debug.showloginfo': return item['value'] return False def execute_jsonrpc(command): if not isinstance(command, six.string_types): command = json.dumps(command) response = control.jsonrpc(command) return json.loads(response)