Skip to content

Commit

Permalink
Replace pecan's homegrown interactive debugging middleware with backlash
Browse files Browse the repository at this point in the history
backlash is a port of Werkzeug's debugger middleware to Webob.  It has no
additional dependencies beyond Webob and is being used by the TurboGears2 team
as an alternative to the antiquated Paste/WebError.  Leveraging this as an
*optional* dependency to pecan would:

* Remove a sizable chunk of code from pecan, some of which is embedded
  JavaScript that packagers have traditionally balked at.
* Improve the interactive debugging experience for developers in a very
  meaningful way (the Werkzeug-based middleware provides features like an
  in-browser console debugger, the ability to load source code on
  a frame-by-frame basis).
* Improve the unified debugging experience amongst several popular Python
  frameworks (some form of the debugging interface will be in use by Flask,
  Pecan, and TurboGears2).

Change-Id: I85f50f677c6052bd2afd32811dedf33835135e12
  • Loading branch information
ryanpetrello committed Jun 11, 2015
1 parent d3159f1 commit 177c566
Show file tree
Hide file tree
Showing 16 changed files with 120 additions and 3,315 deletions.
Binary file removed docs/source/debug-middleware-1.png
Binary file not shown.
Binary file removed docs/source/debug-middleware-2.png
Binary file not shown.
37 changes: 9 additions & 28 deletions docs/source/development.rst
Expand Up @@ -21,37 +21,18 @@ in your applications. To enable the debugging middleware, simply set the

Once enabled, the middleware will automatically catch exceptions raised by your
application and display the Python stack trace and WSGI environment in your
browser for easy debugging:
browser when runtime exceptions are raised.

.. figure:: debug-middleware-1.png
:alt: Pecan debug middleware sample output.
:width: 90%
To improve debugging, including support for an interactive browser-based
console, Pecan makes use of the Python `backlash
<https://pypi.python.org/pypi/backlash>` library. You’ll need to install it
for development use before continuing::

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.post_mortem``:
$ pip install backlash
Downloading/unpacking backlash
...
Successfully installed backlash

.. 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
<http://docs.python.org/library/pdb.html>`_ for more information on
using the Python debugger.

Serving Static Files
--------------------
Expand Down
25 changes: 11 additions & 14 deletions pecan/__init__.py
Expand Up @@ -20,7 +20,6 @@
except ImportError:
from logutils.dictconfig import dictConfig as load_logging_config # noqa

import six
import warnings


Expand All @@ -44,8 +43,6 @@ 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
Expand Down Expand Up @@ -101,19 +98,19 @@ def make_app(root, **kw):
# Included for internal redirect support
app = middleware.recursive.RecursiveMiddleware(app)

# When in debug mode, load our exception dumping middleware
# When in debug mode, load exception debugging middleware
static_root = kw.get('static_root', None)
if debug:
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)
debug_kwargs = getattr(conf, 'debug', {})
debug_kwargs.setdefault('context_injectors', []).append(
lambda environ: {
'request': environ.get('pecan.locals', {}).get('request')
}
)
app = DebugMiddleware(
app,
**debug_kwargs
)

# Support for serving static files (for development convenience)
if static_root:
Expand Down
4 changes: 4 additions & 0 deletions pecan/core.py
Expand Up @@ -660,6 +660,10 @@ def __call__(self, environ, start_response):
req = self.request_cls(environ)
resp = self.response_cls()
state = RoutingState(req, resp, self)
environ['pecan.locals'] = {
'request': req,
'response': resp
}
controller = None

# handle the request
Expand Down
1 change: 0 additions & 1 deletion pecan/middleware/__init__.py
@@ -1,4 +1,3 @@
from . import debug
from . import errordocument
from . import recursive
from . import static

0 comments on commit 177c566

Please sign in to comment.