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
This commit is contained in:
		@@ -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
 | 
			
		||||
 
 | 
			
		||||
@@ -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(
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,4 @@
 | 
			
		||||
from . import debug
 | 
			
		||||
from . import errordocument
 | 
			
		||||
from . import recursive
 | 
			
		||||
from . import static
 | 
			
		||||
 
 | 
			
		||||
@@ -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):
 | 
			
		||||
 
 | 
			
		||||
@@ -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):
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user