Skip to content

Commit

Permalink
Improve debugging info from view_config decorator
Browse files Browse the repository at this point in the history
Backports #3483
  • Loading branch information
luhn committed Apr 11, 2019
1 parent 31e99c3 commit 1585689
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 10 deletions.
2 changes: 2 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
- Fix docs build for Sphinx 2.0.
See https://github.com/Pylons/pyramid/pull/3481

- Improve debugging info from ``pyramid.view.view_config`` decorator.
See https://github.com/Pylons/pyramid/pull/3485

1.10.2 (2019-01-30)
===================
Expand Down
3 changes: 1 addition & 2 deletions docs/api/view.rst
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,7 @@
.. autoclass:: view_config
:members:

.. autoclass:: view_defaults
:members:
.. autofunction:: view_defaults

.. autoclass:: notfound_view_config
:members:
Expand Down
17 changes: 13 additions & 4 deletions src/pyramid/view.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import itertools
import sys
import inspect

import venusian

Expand Down Expand Up @@ -218,6 +219,13 @@ def __init__(self, **settings):
if settings.get('context') is None:
settings['context'] = settings['for_']
self.__dict__.update(settings)
self._get_info()

def _get_info(self):
depth = self.__dict__.get('_depth', 0)
frameinfo = inspect.stack()[depth + 2]
sourceline = frameinfo[4][0].strip()
self._info = frameinfo[1], frameinfo[2], frameinfo[3], sourceline

def __call__(self, wrapped):
settings = self.__dict__.copy()
Expand All @@ -239,14 +247,13 @@ def callback(context, name, ob):
if settings.get('attr') is None:
settings['attr'] = wrapped.__name__

settings['_info'] = info.codeinfo # fbo "action_method"
return wrapped


bfg_view = view_config # bw compat (forever)


class view_defaults(view_config):
def view_defaults(**settings):
""" A class :term:`decorator` which, when applied to a class, will
provide defaults for all view configurations that use the class. This
decorator accepts all the arguments accepted by
Expand All @@ -255,10 +262,12 @@ class view_defaults(view_config):
See :ref:`view_defaults` for more information.
"""

def __call__(self, wrapped):
wrapped.__view_defaults__ = self.__dict__.copy()
def wrap(wrapped):
wrapped.__view_defaults__ = settings
return wrapped

return wrap


class AppendSlashNotFoundViewFactory(object):
""" There can only be one :term:`Not Found view` in any
Expand Down
23 changes: 19 additions & 4 deletions tests/test_view.py
Original file line number Diff line number Diff line change
Expand Up @@ -508,7 +508,25 @@ def _makeOne(self, *arg, **kw):

def test_create_defaults(self):
decorator = self._makeOne()
self.assertEqual(decorator.__dict__, {})
self.assertEqual(list(decorator.__dict__.keys()), ['_info'])

def test_create_info(self):
target = self._getTargetClass()
decorator = target()
info = decorator._info
self.assertEqual(info[2], 'test_create_info')
self.assertEqual(info[3], 'decorator = target()')

def test_create_info_depth(self):
target = self._getTargetClass()

def make():
return target(_depth=1)

decorator = make()
info = decorator._info
self.assertEqual(info[2], 'test_create_info_depth')
self.assertEqual(info[3], 'decorator = make()')

def test_create_context_trumps_for(self):
decorator = self._makeOne(context='123', for_='456')
Expand Down Expand Up @@ -561,7 +579,6 @@ def foo(): # pragma: no cover
self.assertEqual(len(settings[0]), 3)
self.assertEqual(settings[0]['venusian'], venusian)
self.assertEqual(settings[0]['view'], None) # comes from call_venusian
self.assertEqual(settings[0]['_info'], 'codeinfo')

def test_call_class(self):
decorator = self._makeOne()
Expand All @@ -581,7 +598,6 @@ class foo(object):
self.assertEqual(settings[0]['venusian'], venusian)
self.assertEqual(settings[0]['view'], None) # comes from call_venusian
self.assertEqual(settings[0]['attr'], 'foo')
self.assertEqual(settings[0]['_info'], 'codeinfo')

def test_call_class_attr_already_set(self):
decorator = self._makeOne(attr='abc')
Expand All @@ -601,7 +617,6 @@ class foo(object):
self.assertEqual(settings[0]['venusian'], venusian)
self.assertEqual(settings[0]['view'], None) # comes from call_venusian
self.assertEqual(settings[0]['attr'], 'abc')
self.assertEqual(settings[0]['_info'], 'codeinfo')

def test_stacking(self):
decorator1 = self._makeOne(name='1')
Expand Down

0 comments on commit 1585689

Please sign in to comment.