Skip to content

Commit

Permalink
Updated with Flask 0.8 structure and 0.9 _app_ctx_stack
Browse files Browse the repository at this point in the history
  • Loading branch information
jzempel committed Apr 9, 2012
1 parent 2270a8e commit eef0f24
Show file tree
Hide file tree
Showing 7 changed files with 42 additions and 32 deletions.
6 changes: 6 additions & 0 deletions CHANGES
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
Changelog
---------

Version 0.5
~~~~~~~~~~~

* Updated with Flask 0.8 extension structure recommendations and 0.9
_app_ctx_stack.

Version 0.4.9
^^^^^^^^^^^^^

Expand Down
4 changes: 2 additions & 2 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@

# General information about the project.
project = u'Flask-Exceptional'
copyright = u'2011, Jonathan Zempel'
copyright = u'2012, Jonathan Zempel'

# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
Expand Down Expand Up @@ -225,4 +225,4 @@
man_pages = [
('index', 'flask-exceptional', u'Flask-Exceptional Documentation',
[u'Jonathan Zempel'], 1)
]
]
4 changes: 2 additions & 2 deletions docs/index.rst
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Flask-Exceptional
=================

.. module:: flaskext.exceptional
.. module:: flask.ext.exceptional

Flask-Exceptional adds `Exceptional`_ support to `Flask`_. Exceptional
tracks errors in your application, reports them real-time, and gathers
Expand All @@ -28,7 +28,7 @@ application, configure the Exceptional API key, and create the
:class:`Exceptional` object. It's this easy::

from flask import Flask
from flaskext.exceptional import Exceptional
from flask.ext.exceptional import Exceptional

app = Flask(__name__)
app.config["EXCEPTIONAL_API_KEY"] = "exceptional_forty_character_unique_key"
Expand Down
51 changes: 28 additions & 23 deletions flaskext/exceptional.py → flask_exceptional.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
# -*- coding: utf-8 -*-
"""
flaskext.exceptional
~~~~~~~~~~~~~~~~~~~~
flask_exceptional
~~~~~~~~~~~~~~~~~
Adds Exceptional support to Flask.
:copyright: (c) 2011 by Jonathan Zempel.
:copyright: (c) 2012 by Jonathan Zempel.
:license: BSD, see LICENSE for more details.
"""

from __future__ import with_statement
from Cookie import SimpleCookie
from datetime import datetime
from flask import _request_ctx_stack, Config, Flask, g, json
from flask import Config, Flask, g, json
from functools import wraps
from re import match
from urllib2 import HTTPError, Request, urlopen, URLError
Expand All @@ -22,6 +22,11 @@
import os
import sys

try:
from flask import _app_ctx_stack as stack
except ImportError:
from flask import _request_ctx_stack as stack

EXCEPTIONAL_URL = "http://api.exceptional.io/api/errors"


Expand All @@ -40,8 +45,6 @@ def __init__(self, app=None):
"""
if app is not None:
self.init_app(app)
else:
self.app = None

@property
def __version__(self):
Expand All @@ -59,8 +62,6 @@ def init_app(self, app):
:param app: The Flask application to track errors for.
"""
self.app = app

if "EXCEPTIONAL_API_KEY" in app.config:
app.config.setdefault("EXCEPTIONAL_COOKIE_FILTER", None)
app.config.setdefault("EXCEPTIONAL_ENVIRONMENT_FILTER",
Expand Down Expand Up @@ -90,8 +91,8 @@ def init_app(self, app):
if "exceptional" in app.extensions:
app.logger.warning("Repeated Exceptional initialization attempt.")
else:
app.handle_exception = self._get_exception_handler()
app.handle_http_exception = self._get_http_exception_handler()
app.handle_exception = self._get_exception_handler(app)
app.handle_http_exception = self._get_http_exception_handler(app)
app.extensions["exceptional"] = self
else:
app.logger.warning("Missing 'EXCEPTIONAL_API_KEY' configuration.")
Expand All @@ -105,11 +106,11 @@ def context(data=None, **kwargs):
:param data: Default ``None``. A dictionary of context data.
:param kwargs: A series of keyword arguments to use as context data.
"""
context = getattr(_request_ctx_stack.top, "exceptional_context", None)
context = getattr(stack.top, "exceptional_context", None)

if context is None:
context = {}
setattr(_request_ctx_stack.top, "exceptional_context", context)
setattr(stack.top, "exceptional_context", context)

if data is not None:
context.update(data)
Expand Down Expand Up @@ -151,7 +152,7 @@ def test(config):
Accepts either :class:`flask.Config` or the object
types allowed by :meth:`flask.Config.from_object`.
"""
context = getattr(_request_ctx_stack.top, "exceptional_context", None)
context = getattr(stack.top, "exceptional_context", None)
app = Flask(__name__)
exceptional = Exceptional()

Expand All @@ -168,7 +169,7 @@ def test(config):

@app.route("/exception")
def exception():
setattr(_request_ctx_stack.top, "exceptional_context", context)
setattr(stack.top, "exceptional_context", context)
message = "Congratulations! Your application is configured for Exceptional error tracking."

raise Exception(message)
Expand All @@ -177,34 +178,38 @@ def exception():
client.get("/exception")
json.loads(g.exceptional)

def _get_exception_handler(self):
def _get_exception_handler(self, app):
"""Get a wrapped exception handler. Returns a handler that can be
used to override Flask's ``app.handle_exception``. The wrapped
handler posts error data to Exceptional and then passes the exception
to the wrapped method.
:param app: The app for which the exception handler is being wrapped.
"""
handle_exception = self.app.handle_exception
handle_exception = app.handle_exception

@wraps(handle_exception)
def ret_val(exception):
context = _request_ctx_stack.top
self._post_data(context)
self._post_data(stack.top)

return handle_exception(exception)

return ret_val

def _get_http_exception_handler(self):
def _get_http_exception_handler(self, app):
"""Get a wrapped HTTP exception handler. Returns a handler that can
be used to override Flask's ``app.handle_http_exception``. The wrapped
handler posts HTTP error (i.e. '400: Bad Request') data to Exceptional
and then passes the exception to the wrapped method.
:param app: The app for which the HTTP exception handler is being
wrapped.
"""
handle_http_exception = self.app.handle_http_exception
handle_http_exception = app.handle_http_exception

@wraps(handle_http_exception)
def ret_val(exception):
context = _request_ctx_stack.top
context = stack.top

if exception.code in context.app.config["EXCEPTIONAL_HTTP_CODES"]:
self._post_data(context)
Expand All @@ -222,7 +227,7 @@ def _post_data(self, context=None, traceback=None):
:param context: Default ``None``. The current application context.
:param traceback: Default ``None``. The exception stack trace.
"""
app = context.app if context else self.app
app = context.app if context else stack.top.app
application_data = self.__get_application_data(app)
client_data = {
"name": "flask-exceptional",
Expand Down Expand Up @@ -286,7 +291,7 @@ def _encode_basestring(value):
except URLError:
message = "Unable to connect to %s. See \
http://status.exceptional.io for details. Error data:\n%s" % (self.url, error_data)
self.app.logger.warning(message, exc_info=True)
stack.top.app.logger.warning(message, exc_info=True)

@staticmethod
def __filter(app, data, filter_name):
Expand Down
1 change: 0 additions & 1 deletion flaskext/__init__.py

This file was deleted.

5 changes: 2 additions & 3 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,14 @@

setup(
name='Flask-Exceptional',
version='0.4.9',
version='0.5',
url='http://github.com/jzempel/flask-exceptional',
license='BSD',
author='Jonathan Zempel',
author_email='jzempel@gmail.com',
description='Adds Exceptional support to Flask applications',
long_description=__doc__,
packages=['flaskext'],
namespace_packages=['flaskext'],
py_modules=['flask_exceptional'],
zip_safe=False,
platforms='any',
install_requires=install_requires,
Expand Down
3 changes: 2 additions & 1 deletion tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,15 @@
from __future__ import with_statement
from contextlib import closing
from flask import abort, Flask, g, json
from flaskext.exceptional import Exceptional
from flask.ext.exceptional import Exceptional
from functools import wraps
from os import environ
from sys import exc_info
from urllib2 import urlopen
from werkzeug.debug.tbtools import Traceback
import unittest


class ExceptionalTestCase(unittest.TestCase):
"""Exceptional extension test cases.
"""
Expand Down

0 comments on commit eef0f24

Please sign in to comment.