Merge lp:~facundo/magicicada-gui/log-exceptions into lp:magicicada-gui

Proposed by Facundo Batista
Status: Merged
Approved by: Natalia Bidart
Approved revision: 69
Merged at revision: 69
Proposed branch: lp:~facundo/magicicada-gui/log-exceptions
Merge into: lp:magicicada-gui
Diff against target: 160 lines (+108/-8)
3 files modified
magicicada/logger.py (+17/-0)
magicicada/tests/helpers.py (+8/-8)
magicicada/tests/test_logger.py (+83/-0)
To merge this branch: bzr merge lp:~facundo/magicicada-gui/log-exceptions
Reviewer Review Type Date Requested Status
Natalia Bidart Approve
Review via email: mp+32806@code.launchpad.net

Description of the change

Log unhandled exceptions.

To post a comment you must log in.
68. By Facundo Batista

Tested the logging

69. By Facundo Batista

Make pylint and pep8 happy

Revision history for this message
Natalia Bidart (nataliabidart) wrote :

Lovely.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'magicicada/logger.py'
--- magicicada/logger.py 2010-06-20 19:50:46 +0000
+++ magicicada/logger.py 2010-08-18 21:20:58 +0000
@@ -21,6 +21,8 @@
2121
22import logging22import logging
23import os23import os
24import sys
25import traceback
2426
25from logging.handlers import RotatingFileHandler27from logging.handlers import RotatingFileHandler
2628
@@ -35,6 +37,18 @@
35 self.doRollover()37 self.doRollover()
3638
3739
40def exception_handler(exc_type, exc_value, tb):
41 """Handle an unhandled exception."""
42 # stderr
43 exception = traceback.format_exception(exc_type, exc_value, tb)
44 exception = "".join(exception)
45 print >> sys.stderr, exception
46
47 # log
48 logger = logging.getLogger('magicicada')
49 logger.error("Unhandled exception!\n%s", exception)
50
51
38def set_up():52def set_up():
39 """Set up the logging."""53 """Set up the logging."""
4054
@@ -53,3 +67,6 @@
53 '%Y-%m-%d %H:%M:%S')67 '%Y-%m-%d %H:%M:%S')
54 handler.setFormatter(formatter)68 handler.setFormatter(formatter)
55 logger.setLevel(logging.DEBUG)69 logger.setLevel(logging.DEBUG)
70
71 # hook the exception handler
72 sys.excepthook = exception_handler
5673
=== modified file 'magicicada/tests/helpers.py'
--- magicicada/tests/helpers.py 2010-06-19 18:55:01 +0000
+++ magicicada/tests/helpers.py 2010-08-18 21:20:58 +0000
@@ -33,21 +33,21 @@
33 """Just add the record to self.records."""33 """Just add the record to self.records."""
34 self.records.append(record)34 self.records.append(record)
3535
36 def check(self, level, msg):36 def check(self, level, *msgs):
37 """Check that something is logged."""37 """Check that something is logged."""
38 for rec in self.records:38 for rec in self.records:
39 if rec.levelname == level and str(msg) in rec.message:39 if rec.levelname == level and all(m in rec.message for m in msgs):
40 return True40 return True
41 return False41 return False
4242
43 def check_error(self, msg):43 def check_error(self, *msgs):
44 """Shortcut for ERROR check."""44 """Shortcut for ERROR check."""
45 return self.check('ERROR', msg)45 return self.check('ERROR', *msgs)
4646
47 def check_info(self, msg):47 def check_info(self, *msgs):
48 """Shortcut for INFO check."""48 """Shortcut for INFO check."""
49 return self.check('INFO', msg)49 return self.check('INFO', *msgs)
5050
51 def check_debug(self, msg):51 def check_debug(self, *msgs):
52 """Shortcut for DEBUG check."""52 """Shortcut for DEBUG check."""
53 return self.check('DEBUG', msg)53 return self.check('DEBUG', *msgs)
5454
=== added file 'magicicada/tests/test_logger.py'
--- magicicada/tests/test_logger.py 1970-01-01 00:00:00 +0000
+++ magicicada/tests/test_logger.py 2010-08-18 21:20:58 +0000
@@ -0,0 +1,83 @@
1# Tests some logging functions
2#
3# Author: Facundo Batista <facundo@taniquetil.com.ar>
4#
5# Copyright 2010 Chicharreros
6#
7# This program is free software: you can redistribute it and/or modify it
8# under the terms of the GNU General Public License version 3, as published
9# by the Free Software Foundation.
10#
11# This program is distributed in the hope that it will be useful, but
12# WITHOUT ANY WARRANTY; without even the implied warranties of
13# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
14# PURPOSE. See the GNU General Public License for more details.
15#
16# You should have received a copy of the GNU General Public License along
17# with this program. If not, see <http://www.gnu.org/licenses/>.
18
19"""Tests some logging functions."""
20
21import cStringIO
22import logging
23import sys
24import unittest
25
26from magicicada.logger import exception_handler
27from magicicada.tests.helpers import MementoHandler
28
29
30# It's ok to access private data in the test suite
31# pylint: disable=W0212
32
33
34class ExceptionTests(unittest.TestCase):
35 """Test that we log on unhandled exceptions."""
36
37 def _get_exception_data(self):
38 """Return data from a real exception."""
39 try:
40 1 / 0
41 except ZeroDivisionError:
42 return sys.exc_info()
43
44 def test_hook(self):
45 """Check that we're hooked in sys."""
46 self.assertTrue(sys.excepthook is exception_handler)
47
48 def test_logs(self):
49 """Unhandled exceptions logs in error."""
50 # set up logger
51 handler = MementoHandler()
52 handler.setLevel(logging.DEBUG)
53 l = logging.getLogger('magicicada')
54
55 # call
56 l.addHandler(handler)
57 exc = self._get_exception_data()
58 try:
59 exception_handler(*exc)
60 finally:
61 l.removeHandler(handler)
62
63 # check
64 self.assertTrue(handler.check_error("Unhandled exception",
65 "ZeroDivisionError"))
66
67 def test_stderr(self):
68 """Unhandled exceptions are also sent to stderr."""
69 fh = cStringIO.StringIO()
70
71 # call
72 orig_stderr = sys.stderr
73 sys.stderr = fh
74 exc = self._get_exception_data()
75 try:
76 exception_handler(*exc)
77 finally:
78 sys.stderr = orig_stderr
79
80 # check
81 shown = fh.getvalue()
82 self.assertTrue("Traceback" in shown)
83 self.assertTrue("ZeroDivisionError" in shown)

Subscribers

People subscribed via source and target branches