summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoe D'Andrea <jdandrea@research.att.com>2015-04-28 11:33:49 -0400
committerJoe D'Andrea <jdandrea@research.att.com>2015-04-29 12:09:09 -0400
commitec7bdc432dd8be86a4d9e9d20cf35013ca295e86 (patch)
tree251160fdaa62d6b905ca0a068a957862843682a5
parent87b8d00a2ebcb6b2ff3af567249d5065ed135bbd (diff)
downloadpecan-ec7bdc432dd8be86a4d9e9d20cf35013ca295e86.tar.gz
make_app() now uses the debugger param in DebugMiddleware()
Setting app.debugger in setup.py now takes proper effect. A warning is issued if the entry point is not callable. Change-Id: I58a860b8ef0e1cb956b4554071275c024a1949d2 Closes-Bug: #1449573
-rw-r--r--docs/source/development.rst15
-rw-r--r--pecan/__init__.py26
-rw-r--r--pecan/middleware/__init__.py4
-rw-r--r--pecan/middleware/debug.py7
-rw-r--r--pecan/tests/test_base.py36
5 files changed, 76 insertions, 12 deletions
diff --git a/docs/source/development.rst b/docs/source/development.rst
index f4e3217..db9bd84 100644
--- a/docs/source/development.rst
+++ b/docs/source/development.rst
@@ -29,11 +29,24 @@ browser for easy debugging:
To further aid in debugging, the middleware includes the ability to repeat the
offending request, automatically inserting a breakpoint, and dropping your
-console into the Python debugger, ``pdb``:
+console into the Python debugger, ``pdb.post_mortem``:
.. figure:: debug-middleware-2.png
:alt: Pecan debug middleware request debugger.
+You can also use any debugger with a suitable ``post_mortem`` entry point.
+For example, to use the `PuDB Debugger <http://pypi.python.org/pypi/pudb>`_,
+set ``debugger`` like so::
+
+ import pudb
+
+ app = {
+ ...
+ 'debug': True,
+ 'debugger': pudb.post_mortem,
+ ...
+ }
+
.. seealso::
Refer to the `pdb documentation
diff --git a/pecan/__init__.py b/pecan/__init__.py
index 4c52713..83ff059 100644
--- a/pecan/__init__.py
+++ b/pecan/__init__.py
@@ -4,19 +4,16 @@ from .core import (
)
from .decorators import expose
from .hooks import RequestViewerHook
-from .middleware.debug import DebugMiddleware
-from .middleware.errordocument import ErrorDocumentMiddleware
-from .middleware.recursive import RecursiveMiddleware
-from .middleware.static import StaticFileMiddleware
-
from .configuration import set_config, Config
from .configuration import _runtime_conf as conf
+from . import middleware
try:
from logging.config import dictConfig as load_logging_config
except ImportError:
from logutils.dictconfig import dictConfig as load_logging_config # noqa
+import six
import warnings
@@ -40,6 +37,8 @@ def make_app(root, **kw):
debug mode is set.
:param debug: A flag to enable debug mode. This enables the debug
middleware and serving static files.
+ :param debugger: A callable to start debugging, defaulting to the Python
+ debugger entry point ``pdb.post_mortem``.
:param wrap_app: A function or middleware class to wrap the Pecan app.
This must either be a wsgi middleware class or a
function that returns a wsgi application. This wrapper
@@ -90,19 +89,28 @@ def make_app(root, **kw):
# Configuration for serving custom error messages
errors = kw.get('errors', getattr(conf.app, 'errors', {}))
if errors:
- app = ErrorDocumentMiddleware(app, errors)
+ app = middleware.errordocument.ErrorDocumentMiddleware(app, errors)
# Included for internal redirect support
- app = RecursiveMiddleware(app)
+ app = middleware.recursive.RecursiveMiddleware(app)
# When in debug mode, load our exception dumping middleware
static_root = kw.get('static_root', None)
if debug:
- app = DebugMiddleware(app)
+ debugger = kw.get('debugger', None)
+ debugger_kwargs = {}
+ if six.callable(debugger):
+ debugger_kwargs['debugger'] = debugger
+ elif debugger:
+ warnings.warn(
+ "`app.debugger` is not callable, ignoring",
+ RuntimeWarning
+ )
+ app = middleware.debug.DebugMiddleware(app, **debugger_kwargs)
# Support for serving static files (for development convenience)
if static_root:
- app = StaticFileMiddleware(app, static_root)
+ app = middleware.static.StaticFileMiddleware(app, static_root)
elif static_root:
warnings.warn(
diff --git a/pecan/middleware/__init__.py b/pecan/middleware/__init__.py
index e69de29..d95b453 100644
--- a/pecan/middleware/__init__.py
+++ b/pecan/middleware/__init__.py
@@ -0,0 +1,4 @@
+from . import debug
+from . import errordocument
+from . import recursive
+from . import static
diff --git a/pecan/middleware/debug.py b/pecan/middleware/debug.py
index 764e8e9..ec2faa0 100644
--- a/pecan/middleware/debug.py
+++ b/pecan/middleware/debug.py
@@ -253,7 +253,10 @@ class DebugMiddleware(object):
To further aid in debugging, the middleware includes the ability to repeat
the offending request, automatically inserting a breakpoint, and dropping
- your console into the Python debugger, ``pdb``.
+ your console into the Python debugger, ``pdb.post_mortem``.
+
+ You can also use any debugger with a suitable ``post_mortem`` entry point
+ such as the `PuDB Debugger <http://pypi.python.org/pypi/pudb>`_,
For more information, refer to the `documentation for pdb
<http://docs.python.org/library/pdb.html>`_ available on the Python
@@ -261,7 +264,7 @@ class DebugMiddleware(object):
:param app: the application to wrap.
:param debugger: a callable to start debugging, defaulting to the Python
- debugger, ``pdb``.
+ debugger entry point ``pdb.post_mortem``.
"""
def __init__(self, app, debugger=pdb.post_mortem):
diff --git a/pecan/tests/test_base.py b/pecan/tests/test_base.py
index a886a94..58b5734 100644
--- a/pecan/tests/test_base.py
+++ b/pecan/tests/test_base.py
@@ -5,6 +5,7 @@ import warnings
import webob
from webob.exc import HTTPNotFound
+import mock
from webtest import TestApp
import six
from six import b as b_
@@ -1616,6 +1617,41 @@ class TestNonCanonical(PecanTestCase):
assert len(wrapped_apps) == 1
+class TestDebugging(PecanTestCase):
+ def test_debugger_setup(self):
+ class RootController(object):
+ pass
+
+ def debugger():
+ pass
+
+ app_conf = dict(
+ debug=True,
+ debugger=debugger
+ )
+ with mock.patch('pecan.middleware.debug.DebugMiddleware') \
+ as patched_debug_middleware:
+ app = make_app(RootController(), **app_conf)
+ args, kwargs = patched_debug_middleware.call_args
+ assert kwargs.get('debugger') == debugger
+
+ def test_invalid_debugger_setup(self):
+ class RootController(object):
+ pass
+
+ debugger = 'not_a_valid_entry_point'
+
+ app_conf = dict(
+ debug=True,
+ debugger=debugger
+ )
+ with mock.patch('pecan.middleware.debug.DebugMiddleware') \
+ as patched_debug_middleware:
+ app = make_app(RootController(), **app_conf)
+ args, kwargs = patched_debug_middleware.call_args
+ assert kwargs.get('debugger') is None
+
+
class TestLogging(PecanTestCase):
def test_logging_setup(self):