launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #05233
[Merge] lp:~lifeless/python-oops-twisted/non_log_oopses into lp:python-oops-twisted
Robert Collins has proposed merging lp:~lifeless/python-oops-twisted/non_log_oopses into lp:python-oops-twisted.
Requested reviews:
Launchpad code reviewers (launchpad-reviewers)
For more details, see:
https://code.launchpad.net/~lifeless/python-oops-twisted/non_log_oopses/+merge/79202
I missed a point in our code where we geenrate an oops without calling log.err() [twisted code that is] - this branch permits that to be done and will let LP migrate onto using oops-twisted.
--
https://code.launchpad.net/~lifeless/python-oops-twisted/non_log_oopses/+merge/79202
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~lifeless/python-oops-twisted/non_log_oopses into lp:python-oops-twisted.
=== added file 'MANIFEST.in'
=== modified file 'NEWS'
--- NEWS 2011-10-07 13:00:44 +0000
+++ NEWS 2011-10-13 03:19:49 +0000
@@ -9,6 +9,9 @@
* Ensure that OOPObserver fallback argument is None or callable to
help prevent a cpu/memory eating situation. (Gavin Panella, #869463)
+* Make the logic for creating an OOPS report from a Failure reusable outside of
+ the log handling logic. (Robert Collins)
+
0.0.3
-----
=== modified file 'oops_twisted/__init__.py'
--- oops_twisted/__init__.py 2011-09-28 09:00:46 +0000
+++ oops_twisted/__init__.py 2011-10-13 03:19:49 +0000
@@ -83,6 +83,15 @@
failure events (this stops them getting lost). If there are publishers but the
OOPS is filtered, the fallback will not be invoked at all (this permits e.g.
rate limiting of failutes via filters).
+
+Creating OOPSes without using log.err
++++++++++++++++++++++++++++++++++++++
+
+You can directly create an OOPS if you have a twisted failure object::
+
+ >>> from twisted.python.failure import Failure
+ >>> report = config.create(dict(twisted_failure=Failure()))
+ >>> config.publish(report)
"""
@@ -97,7 +106,7 @@
# established at this point, and setup.py will use a version of next-$(revno).
# If the releaselevel is 'final', then the tarball will be major.minor.micro.
# Otherwise it is major.minor.micro~$(revno).
-__version__ = (0, 0, 3, 'beta', 0)
+__version__ = (0, 0, 4, 'beta', 0)
__all__ = [
'Config',
=== modified file 'oops_twisted/config.py'
--- oops_twisted/config.py 2011-09-23 07:44:42 +0000
+++ oops_twisted/config.py 2011-10-13 03:19:49 +0000
@@ -31,6 +31,8 @@
import oops
+from createhooks import failure_to_context
+
__all__ = [
'Config',
'defer_publisher',
@@ -46,6 +48,10 @@
For more information see the oops.Config documentation.
"""
+ def __init__(self, *args, **kwargs):
+ oops.Config.__init__(self)
+ self.on_create.insert(0, failure_to_context)
+
def publish(self, report):
"""Publish a report.
=== added file 'oops_twisted/createhooks.py'
--- oops_twisted/createhooks.py 1970-01-01 00:00:00 +0000
+++ oops_twisted/createhooks.py 2011-10-13 03:19:49 +0000
@@ -0,0 +1,36 @@
+# Copyright (c) 2011, Canonical Ltd
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+# GNU Affero General Public License version 3 (see the file LICENSE).
+
+"""Extensions to permit creatings OOPS reports with twisted types."""
+
+__metaclass__ = type
+
+__all__ = [
+ 'failure_to_context',
+ ]
+
+
+def failure_to_context(report, context):
+ """If a twisted_failure key is present, use it to set context['exc_info'].
+
+ This permits using regular python hooks with a twisted failure.
+ """
+ failure = context.get('twisted_failure')
+ if not failure:
+ return
+ exc_info=(failure.type, failure.value, failure.getTraceback())
+ context['exc_info'] = exc_info
+ del exc_info # prevent cycles
=== modified file 'oops_twisted/log.py'
--- oops_twisted/log.py 2011-10-06 20:40:41 +0000
+++ oops_twisted/log.py 2011-10-13 03:19:49 +0000
@@ -57,11 +57,7 @@
self.fallback(eventDict)
return None, None
context = {}
- if 'failure' in eventDict:
- failure = eventDict['failure']
- exc_info=(failure.type, failure.value, failure.getTraceback())
- context['exc_info'] = exc_info
- del exc_info # prevent cycles
+ context['twisted_failure'] = eventDict.get('failure')
report = self.config.create(context)
report['time'] = datetime.datetime.fromtimestamp(
eventDict['time'], utc)
=== modified file 'oops_twisted/tests/__init__.py'
--- oops_twisted/tests/__init__.py 2011-09-23 07:44:42 +0000
+++ oops_twisted/tests/__init__.py 2011-10-13 03:19:49 +0000
@@ -22,6 +22,7 @@
def test_suite():
test_mod_names = [
'config',
+ 'createhooks',
'log',
]
return TestLoader().loadTestsFromNames(
=== modified file 'oops_twisted/tests/test_config.py'
--- oops_twisted/tests/test_config.py 2011-09-23 07:44:42 +0000
+++ oops_twisted/tests/test_config.py 2011-10-13 03:19:49 +0000
@@ -27,12 +27,22 @@
defer_publisher,
OOPSObserver,
)
+from oops_twisted.createhooks import (
+ failure_to_context,
+ )
class TestConfig(TestCase):
run_tests_with = AsynchronousDeferredRunTest
+ def test_twisted_hooks_installed(self):
+ # One hooks is present: one that enhances the context if a failure is
+ # present, and is installed first so that the regular oops hooks can
+ # pick it up.
+ config = Config()
+ self.assertEqual(0, config.on_create.index(failure_to_context))
+
def test_no_publishers_publish_returns_success_empty_list(self):
config = Config()
d = config.publish({})
=== added file 'oops_twisted/tests/test_createhooks.py'
--- oops_twisted/tests/test_createhooks.py 1970-01-01 00:00:00 +0000
+++ oops_twisted/tests/test_createhooks.py 2011-10-13 03:19:49 +0000
@@ -0,0 +1,36 @@
+# Copyright (c) 2011, Canonical Ltd
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+# GNU Affero General Public License version 3 (see the file LICENSE).
+
+"""Tests for the twisted specific creation hooks."""
+
+from testtools import TestCase
+from twisted.python.failure import Failure
+
+from oops_twisted.createhooks import failure_to_context
+
+
+class TestHooks(TestCase):
+
+ def test_failure_to_context(self):
+ try:
+ raise ValueError('foo')
+ except ValueError:
+ failure = Failure()
+ context = {'twisted_failure': failure}
+ report = {}
+ failure_to_context(report, context)
+ exc_info=(failure.type, failure.value, failure.getTraceback())
+ self.assertEqual(exc_info, context['exc_info'])
=== modified file 'oops_twisted/tests/test_log.py'
--- oops_twisted/tests/test_log.py 2011-09-28 09:00:46 +0000
+++ oops_twisted/tests/test_log.py 2011-10-13 03:19:49 +0000
@@ -79,12 +79,9 @@
event = dict(isError=True, message=None, time=now,
failure=failure.Failure(), why='testing')
report, d = observer.emit(event)
- expected_report = {
- 'type': 'ValueError',
- 'value': 'exception message',
- 'time': datetime.datetime.fromtimestamp(now, utc),
- 'tb_text': textFromEventDict(event),
- }
+ expected_report = config.create(dict(twisted_failure=event['failure']))
+ expected_report['time'] = datetime.datetime.fromtimestamp(now, utc)
+ expected_report['tb_text'] = textFromEventDict(event)
self.assertEqual(expected_report, report)
expected_report['id'] = 33
d.addCallback(lambda result: self.assertEqual([22, 33], result))
=== modified file 'setup.py'
--- setup.py 2011-09-28 09:00:46 +0000
+++ setup.py 2011-10-13 03:19:49 +0000
@@ -23,7 +23,7 @@
os.path.join(os.path.dirname(__file__), 'README'), 'rb').read()
setup(name="oops_twisted",
- version="0.0.3",
+ version="0.0.4",
description=\
"Translate twisted error logs into OOPS error reports.",
long_description=description,