Coverage for src/robotide/log/log.py: 73%
72 statements
« prev ^ index » next coverage.py v7.8.0, created at 2025-05-06 10:40 +0100
« prev ^ index » next coverage.py v7.8.0, created at 2025-05-06 10:40 +0100
1# Copyright 2008-2015 Nokia Networks
2# Copyright 2016- Robot Framework Foundation
3#
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
16import atexit
17import builtins
18import glob
19import io
20import os
21import sys
22import tempfile
23import uuid
24import wx
26from .logwindow import LogWindow, message_to_string
27from .. import context
28from .. import widgets
29from ..pluginapi import Plugin
30from ..action import ActionInfo
31from ..publish.messages import RideLog
33_ = wx.GetTranslation # To keep linter/code analyser happy
34builtins.__dict__['_'] = wx.GetTranslation
37class LogPlugin(Plugin):
38 """Viewer for internal log messages."""
40 def __init__(self, app):
41 Plugin.__init__(self, app, default_settings={
42 'log_to_console': False,
43 'log_to_file': True
44 })
45 self.title = _('RIDE Log')
46 self._log = []
47 self._panel = None
48 self._path = os.path.join(
49 tempfile.gettempdir(), '{}-ride.log'.format(uuid.uuid4()))
50 self._outfile = None
51 self._remove_old_log_files()
52 atexit.register(self._close)
54 def _close(self):
55 if self._outfile is not None:
56 self._outfile.close()
58 @staticmethod
59 def _remove_old_log_files():
60 for fname in glob.glob(
61 os.path.join(tempfile.gettempdir(), '*-ride.log')):
62 try:
63 os.remove(fname)
64 except (OSError, IOError) as e:
65 sys.stderr.write(f"Removing old *-ride.log files failed with: {repr(e)}\n")
67 @property
68 def _logfile(self):
69 if self._outfile is None:
70 self._outfile = io.open(self._path, 'w', encoding='utf8')
71 return self._outfile
73 def enable(self):
74 self._create_menu() 1ab
75 self.subscribe(self._log_message, RideLog) 1ab
77 def disable(self):
78 self.unsubscribe_all()
79 self.unregister_actions()
80 if self._panel: 80 ↛ 81line 80 didn't jump to line 81 because the condition on line 80 was never true
81 self._panel.close(self.notebook)
83 def _create_menu(self):
84 self.unregister_actions() 1ab
85 self.register_action(ActionInfo( 1ab
86 _('Tools'), _('View RIDE Log'), self.on_view_log, position=84))
88 def _log_message(self, message):
89 self._log.append(message)
90 if self._panel: 90 ↛ 91line 90 didn't jump to line 91 because the condition on line 90 was never true
91 self._panel.update_log()
92 if self.log_to_console: 92 ↛ 93line 92 didn't jump to line 93 because the condition on line 92 was never true
93 print('{}'.format(message_to_string(message)))
94 if self.log_to_file: 94 ↛ 97line 94 didn't jump to line 97 because the condition on line 94 was always true
95 self._logfile.write(message_to_string(message))
96 self._outfile.flush()
97 if message.notify_user: 97 ↛ 98line 97 didn't jump to line 98 because the condition on line 97 was never true
98 font_size = 13 if context.IS_MAC else -1
99 widgets.HtmlDialog(message.level, message.message,
100 padding=10, font_size=font_size).Show()
102 def on_view_log(self, event):
103 __ = event
104 if not self._panel:
105 self._panel = LogWindow(self.notebook, self.title, self._log)
106 self._panel.update_log()
107 self.register_shortcut('CtrlCmd-C', lambda e: self._panel.Copy())
108 else:
109 self.notebook.show_tab(self._panel)