Robot Framework Integrated Development Environment (RIDE)
log.py
Go to the documentation of this file.
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.
15 
16 import atexit
17 import glob
18 import io
19 import os
20 import sys
21 import tempfile
22 import uuid
23 
24 import wx
25 from wx import Colour
26 
27 from .. import context
28 from .. import widgets
29 from ..pluginapi import Plugin
30 from ..action import ActionInfo
31 from ..publish.messages import RideLog
32 from ..widgets import RIDEDialog
33 
34 
36  return '%s [%s]: %s\n\n' % (msg.timestamp, msg.level, msg.message)
37 
38 
39 
40 class LogPlugin(Plugin):
41 
42  def __init__(self, app):
43  Plugin.__init__(self, app, default_settings={
44  'log_to_console': False,
45  'log_to_file': True
46  })
47  self._log_log = []
48  self._panel_panel = None
49  self._path_path = os.path.join(
50  tempfile.gettempdir(), '{}-ride.log'.format(uuid.uuid4()))
51  self._outfile_outfile = None
52  self._remove_old_log_files_remove_old_log_files()
53  atexit.register(self._close_close)
54 
55  def _close(self):
56  if self._outfile_outfile is not None:
57  self._outfile_outfile.close()
58 
60  for fname in glob.glob(
61  os.path.join(tempfile.gettempdir(), '*-ride.log')):
62  try:
63  os.remove(fname)
64  except OSError or IOError or PermissionError as e:
65  sys.stderr.write(f"Removing old *-ride.log files failed with: {repr(e)}\n")
66  finally:
67  pass
68 
69  @property
70  _logfile = property
71 
72  def _logfile(self):
73  if self._outfile_outfile is None:
74  self._outfile_outfile = io.open(self._path_path, 'w', encoding='utf8')
75  return self._outfile_outfile
76 
77  def enable(self):
78  self._create_menu_create_menu()
79  self.subscribe(self._log_message_log_message, RideLog)
80 
81  def disable(self):
82  self.unsubscribe_all()
83  self.unregister_actions()
84  if self._panel_panel:
85  self._panel_panel.close(self.notebook)
86 
87  def _create_menu(self):
88  self.unregister_actions()
89  self.register_action(ActionInfo(
90  'Tools', 'View RIDE Log', self.OnViewLogOnViewLog, position=84))
91 
92  def _log_message(self, message):
93  self._log_log.append(message)
94  if self._panel_panel:
95  self._panel_panel.update_log()
96  if self.log_to_console:
97  print('{}'.format(_message_to_string(message)))
98  if self.log_to_file:
99  self._logfile_logfile_logfile.write(_message_to_string(message))
100  self._outfile_outfile.flush()
101  if message.notify_user:
102  font_size = 13 if context.IS_MAC else -1
103  widgets.HtmlDialog(message.level, message.message,
104  padding=10, font_size=font_size).Show()
105 
106  def OnViewLog(self, event):
107  if not self._panel_panel:
108  self._panel_panel = _LogWindow(self.notebook, self._log_log)
109  self._panel_panel.update_log()
110  self.register_shortcut('CtrlCmd-C', lambda e: self._panel_panel.Copy())
111  else:
112  self.notebook.show_tab(self._panel_panel)
113 
114 
115 class _LogWindow(wx.Panel):
116 
117  def __init__(self, notebook, log):
118  wx.Panel.__init__(self, notebook)
119  self.dlgdlg = RIDEDialog()
120  self._output_output = wx.TextCtrl(self, style=wx.TE_READONLY | wx.TE_MULTILINE | wx.TE_NOHIDESEL)
121  self._output_output.SetBackgroundColour(Colour(self.dlgdlg.color_background))
122  self._output_output.SetForegroundColour(Colour(self.dlgdlg.color_foreground))
123  self._output_output.Bind(wx.EVT_KEY_DOWN, self.OnKeyDownOnKeyDown)
124  self._log_log = log
125  self._add_to_notebook_add_to_notebook(notebook)
126  self.SetFont(widgets.Font().fixed_log)
127  self.Bind(wx.EVT_SIZE, self.OnSizeOnSize)
128 
129  def _create_ui(self):
130  self.SetSizer(widgets.VerticalSizer())
131  self.Sizer.add_expanding(self._output_output)
132 
133  def _add_to_notebook(self, notebook):
134  notebook.add_tab(self, 'RIDE Log', allow_closing=True)
135  notebook.show_tab(self)
136  self._output_output.SetSize(self.Size)
137 
138  def close(self, notebook):
139  notebook.delete_tab(self)
140 
141  def update_log(self):
142  self._output_output.SetValue(self._decode_log_decode_log(self._log_log))
143 
144  def _decode_log(self, log):
145  result = ''
146  for msg in log:
147  result += _message_to_string(msg)
148  return result
149 
150  def OnSize(self, evt):
151  self._output_output.SetSize(self.Size)
152 
153  def OnKeyDown(self, event):
154  keycode = event.GetKeyCode()
155 
156  if event.ControlDown() and keycode == ord('A'):
157  self.SelectAllSelectAll()
158  else:
159  event.Skip()
160 
161  def Copy(self):
162  pass
163 
164  def SelectAll(self):
165  self._output.SetSelection(-1, -1)
Used to create menu entries, keyboard shortcuts and/or toolbar buttons.
Definition: actioninfo.py:176
Viewer for internal log messages.
Definition: log.py:40
def __init__(self, app)
Definition: log.py:42
def _remove_old_log_files(self)
Definition: log.py:59
def _logfile(self)
Definition: log.py:72
def _create_menu(self)
Definition: log.py:87
def _close(self)
Definition: log.py:55
def disable(self)
Definition: log.py:81
def OnViewLog(self, event)
Definition: log.py:106
def enable(self)
Definition: log.py:77
def _log_message(self, message)
Definition: log.py:92
def OnSize(self, evt)
Definition: log.py:150
def _add_to_notebook(self, notebook)
Definition: log.py:133
def _decode_log(self, log)
Definition: log.py:144
def OnKeyDown(self, event)
Definition: log.py:153
def update_log(self)
Definition: log.py:141
def _create_ui(self)
Definition: log.py:129
def close(self, notebook)
Definition: log.py:138
def __init__(self, notebook, log)
Definition: log.py:117
def write(msg, level='INFO', html=False)
Writes the message to the log file using the given level.
Definition: logger.py:86
def _message_to_string(msg)
Definition: log.py:35