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

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 

16import atexit 

17import builtins 

18import glob 

19import io 

20import os 

21import sys 

22import tempfile 

23import uuid 

24import wx 

25 

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 

32 

33_ = wx.GetTranslation # To keep linter/code analyser happy 

34builtins.__dict__['_'] = wx.GetTranslation 

35 

36 

37class LogPlugin(Plugin): 

38 """Viewer for internal log messages.""" 

39 

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) 

53 

54 def _close(self): 

55 if self._outfile is not None: 

56 self._outfile.close() 

57 

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") 

66 

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 

72 

73 def enable(self): 

74 self._create_menu() 1ab

75 self.subscribe(self._log_message, RideLog) 1ab

76 

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) 

82 

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)) 

87 

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() 

101 

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)