diff options
-rw-r--r-- | docs/source/development.rst | 15 | ||||
-rw-r--r-- | pecan/__init__.py | 26 | ||||
-rw-r--r-- | pecan/middleware/__init__.py | 4 | ||||
-rw-r--r-- | pecan/middleware/debug.py | 7 | ||||
-rw-r--r-- | pecan/tests/test_base.py | 36 |
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): |