Coverage for src/robotide/parserlog/parserlog.py: 45%
75 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 2019- Robot Framework Foundation
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
15import atexit
16import builtins
17import glob
18import io
19import os
20import sys
21import tempfile
22import uuid
24import wx
26from .. import context
27from .. import widgets
28from ..log import LogWindow, message_to_string
29from ..pluginapi import Plugin
30from ..action import ActionInfo
31from ..publish.messages import RideParserLogMessage
33_ = wx.GetTranslation # To keep linter/code analyser happy
34builtins.__dict__['_'] = wx.GetTranslation
37class ParserLogPlugin(Plugin):
38 """Viewer for parser 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 = _('Parser Log')
46 self._log = []
47 self._panel = None
48 self._path = os.path.join(
49 tempfile.gettempdir(), '{}-ride_parser.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( 60 ↛ 62line 60 didn't jump to line 62 because the loop on line 60 never started
61 os.path.join(tempfile.gettempdir(), '*-ride_parser.log')):
62 try:
63 os.remove(fname)
64 except (OSError, IOError) as e:
65 sys.stderr.write(f"Removing old *-ride_parser.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()
75 self.subscribe(self._log_message, RideParserLogMessage)
77 def disable(self):
78 self.unsubscribe_all()
79 self.unregister_actions()
80 if self._panel:
81 self._panel.close(self.notebook)
83 def _create_menu(self):
84 self.unregister_actions()
85 self.register_action(ActionInfo(_('Tools'), _('View Parser Log'), self.on_view_log, position=83))
87 def _log_message(self, message):
88 self._log.append(message)
89 if self._panel:
90 self._panel.update_log()
91 if self.log_to_console:
92 print("{}".format(message_to_string(message, True))) # >> sys.stdout, _message_to_string(message)
93 if self.log_to_file:
94 self._logfile.write(message_to_string(message, True))
95 self._outfile.flush()
96 if message.notify_user:
97 font_size = 13 if context.IS_MAC else -1
98 widgets.HtmlDialog(message.level, message.message,
99 padding=10, font_size=font_size).Show()
100 self.on_view_log(message, show_tab=False)
102 def on_view_log(self, event, show_tab=True):
103 __ = event
104 if not self._panel:
105 self._panel = LogWindow(self.notebook, self.title, self._log)
106 self.notebook.SetPageTextColour(self.notebook.GetPageCount()-1, wx.Colour(255, 165, 0))
107 self._panel.update_log()
108 self.register_shortcut('CtrlCmd-C', lambda e: self._panel.Copy())
109 if show_tab:
110 self.notebook.show_tab(self._panel)