summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Merickel <michael@merickel.org>2017-07-08 12:00:30 -0500
committerMichael Merickel <michael@merickel.org>2017-07-08 12:00:30 -0500
commit49815841fbdc67298b2a239f79be154343d4bcb8 (patch)
tree289ae10b87c92f3e07f7c2db28d813798750ae81
parenta0aaf09c7e7792cd8103fbe9843650203c1d73b5 (diff)
downloadpyramid-49815841fbdc67298b2a239f79be154343d4bcb8.tar.gz
pyramid-49815841fbdc67298b2a239f79be154343d4bcb8.tar.bz2
pyramid-49815841fbdc67298b2a239f79be154343d4bcb8.zip
add _depth and _category arguments to all decorators
``subscriber``, ``response_adapter``, ``exception_view_config``, ``notfound_view_config``, ``forbidden_view_config`` This is an extension of #3105 to add support to the remaining decorators.
-rw-r--r--pyramid/events.py25
-rw-r--r--pyramid/response.py30
-rw-r--r--pyramid/tests/test_events.py15
-rw-r--r--pyramid/tests/test_response.py21
-rw-r--r--pyramid/tests/test_view.py45
-rw-r--r--pyramid/view.py29
6 files changed, 143 insertions, 22 deletions
diff --git a/pyramid/events.py b/pyramid/events.py
index 35da2fa6f..d3b068bd3 100644
--- a/pyramid/events.py
+++ b/pyramid/events.py
@@ -68,12 +68,34 @@ class subscriber(object):
:ref:`subscriber_predicates` for a description of how predicates can
narrow the set of circumstances in which a subscriber will be called.
+ Two additional keyword arguments which will be passed to the
+ :term:`venusian` ``attach`` function are ``_depth`` and ``_category``.
+
+ ``_depth`` is provided for people who wish to reuse this class from another
+ decorator. The default value is ``0`` and should be specified relative to
+ the ``subscriber`` invocation. It will be passed in to the
+ :term:`venusian` ``attach`` function as the depth of the callstack when
+ Venusian checks if the decorator is being used in a class or module
+ context. It's not often used, but it can be useful in this circumstance.
+
+ ``_category`` sets the decorator category name. It can be useful in
+ combination with the ``category`` argument of ``scan`` to control which
+ views should be processed.
+
+ See the :py:func:`venusian.attach` function in Venusian for more
+ information about the ``_depth`` and ``_category`` arguments.
+
+ .. versionchanged:: 1.9.1
+ Added the ``_depth`` and ``_category`` arguments.
+
"""
venusian = venusian # for unit testing
def __init__(self, *ifaces, **predicates):
self.ifaces = ifaces
self.predicates = predicates
+ self.depth = predicates.pop('_depth', 0)
+ self.category = predicates.pop('_category', 'pyramid')
def register(self, scanner, name, wrapped):
config = scanner.config
@@ -81,7 +103,8 @@ class subscriber(object):
config.add_subscriber(wrapped, iface, **self.predicates)
def __call__(self, wrapped):
- self.venusian.attach(wrapped, self.register, category='pyramid')
+ self.venusian.attach(wrapped, self.register, category=self.category,
+ depth=self.depth + 1)
return wrapped
@implementer(INewRequest)
diff --git a/pyramid/response.py b/pyramid/response.py
index 1d9daae7d..1e2546ed0 100644
--- a/pyramid/response.py
+++ b/pyramid/response.py
@@ -145,19 +145,43 @@ class response_adapter(object):
config = Configurator()
config.scan('somepackage_containing_adapters')
+ Two additional keyword arguments which will be passed to the
+ :term:`venusian` ``attach`` function are ``_depth`` and ``_category``.
+
+ ``_depth`` is provided for people who wish to reuse this class from another
+ decorator. The default value is ``0`` and should be specified relative to
+ the ``response_adapter`` invocation. It will be passed in to the
+ :term:`venusian` ``attach`` function as the depth of the callstack when
+ Venusian checks if the decorator is being used in a class or module
+ context. It's not often used, but it can be useful in this circumstance.
+
+ ``_category`` sets the decorator category name. It can be useful in
+ combination with the ``category`` argument of ``scan`` to control which
+ views should be processed.
+
+ See the :py:func:`venusian.attach` function in Venusian for more
+ information about the ``_depth`` and ``_category`` arguments.
+
+ .. versionchanged:: 1.9.1
+ Added the ``_depth`` and ``_category`` arguments.
+
"""
venusian = venusian # for unit testing
- def __init__(self, *types_or_ifaces):
+ def __init__(self, *types_or_ifaces, **kwargs):
self.types_or_ifaces = types_or_ifaces
+ self.depth = kwargs.pop('_depth', 0)
+ self.category = kwargs.pop('_category', 'pyramid')
+ self.kwargs = kwargs
def register(self, scanner, name, wrapped):
config = scanner.config
for type_or_iface in self.types_or_ifaces:
- config.add_response_adapter(wrapped, type_or_iface)
+ config.add_response_adapter(wrapped, type_or_iface, **self.kwargs)
def __call__(self, wrapped):
- self.venusian.attach(wrapped, self.register, category='pyramid')
+ self.venusian.attach(wrapped, self.register, category=self.category,
+ depth=self.depth + 1)
return wrapped
diff --git a/pyramid/tests/test_events.py b/pyramid/tests/test_events.py
index 52e53c34e..4f9011cc0 100644
--- a/pyramid/tests/test_events.py
+++ b/pyramid/tests/test_events.py
@@ -209,7 +209,16 @@ class TestSubscriber(unittest.TestCase):
def foo(): pass
dec(foo)
self.assertEqual(dummy_venusian.attached,
- [(foo, dec.register, 'pyramid')])
+ [(foo, dec.register, 'pyramid', 1)])
+
+ def test___call___with_venusian_args(self):
+ dec = self._makeOne(_category='foo', _depth=1)
+ dummy_venusian = DummyVenusian()
+ dec.venusian = dummy_venusian
+ def foo(): pass
+ dec(foo)
+ self.assertEqual(dummy_venusian.attached,
+ [(foo, dec.register, 'foo', 2)])
def test_regsister_with_predicates(self):
from zope.interface import Interface
@@ -308,8 +317,8 @@ class DummyVenusian(object):
def __init__(self):
self.attached = []
- def attach(self, wrapped, fn, category=None):
- self.attached.append((wrapped, fn, category))
+ def attach(self, wrapped, fn, category=None, depth=None):
+ self.attached.append((wrapped, fn, category, depth))
class Dummy:
pass
diff --git a/pyramid/tests/test_response.py b/pyramid/tests/test_response.py
index ad55882c9..53e3ce17a 100644
--- a/pyramid/tests/test_response.py
+++ b/pyramid/tests/test_response.py
@@ -136,9 +136,9 @@ class TestResponseAdapter(unittest.TestCase):
def tearDown(self):
self.config.end()
- def _makeOne(self, *types_or_ifaces):
+ def _makeOne(self, *types_or_ifaces, **kw):
from pyramid.response import response_adapter
- return response_adapter(*types_or_ifaces)
+ return response_adapter(*types_or_ifaces, **kw)
def test_register_single(self):
from zope.interface import Interface
@@ -172,7 +172,18 @@ class TestResponseAdapter(unittest.TestCase):
def foo(): pass
dec(foo)
self.assertEqual(dummy_venusian.attached,
- [(foo, dec.register, 'pyramid')])
+ [(foo, dec.register, 'pyramid', 1)])
+
+ def test___call___with_venusian_args(self):
+ from zope.interface import Interface
+ class IFoo(Interface): pass
+ dec = self._makeOne(IFoo, _category='foo', _depth=1)
+ dummy_venusian = DummyVenusian()
+ dec.venusian = dummy_venusian
+ def foo(): pass
+ dec(foo)
+ self.assertEqual(dummy_venusian.attached,
+ [(foo, dec.register, 'foo', 2)])
class TestGetResponseFactory(unittest.TestCase):
@@ -199,5 +210,5 @@ class DummyVenusian(object):
def __init__(self):
self.attached = []
- def attach(self, wrapped, fn, category=None):
- self.attached.append((wrapped, fn, category))
+ def attach(self, wrapped, fn, category=None, depth=None):
+ self.attached.append((wrapped, fn, category, depth))
diff --git a/pyramid/tests/test_view.py b/pyramid/tests/test_view.py
index 7a1c90deb..0124ce632 100644
--- a/pyramid/tests/test_view.py
+++ b/pyramid/tests/test_view.py
@@ -91,6 +91,18 @@ class Test_notfound_view_config(BaseTest, unittest.TestCase):
self.assertEqual(settings[0]['attr'], 'view')
self.assertEqual(settings[0]['_info'], 'codeinfo')
+ def test_call_with_venusian_args(self):
+ decorator = self._makeOne(_depth=1, _category='foo')
+ venusian = DummyVenusian()
+ decorator.venusian = venusian
+ def foo(): pass
+ decorator(foo)
+ attachments = venusian.attachments
+ category = attachments[0][2]
+ depth = attachments[0][3]
+ self.assertEqual(depth, 2)
+ self.assertEqual(category, 'foo')
+
class Test_forbidden_view_config(BaseTest, unittest.TestCase):
def _makeOne(self, **kw):
from pyramid.view import forbidden_view_config
@@ -133,6 +145,18 @@ class Test_forbidden_view_config(BaseTest, unittest.TestCase):
self.assertEqual(settings[0]['attr'], 'view')
self.assertEqual(settings[0]['_info'], 'codeinfo')
+ def test_call_with_venusian_args(self):
+ decorator = self._makeOne(_depth=1, _category='foo')
+ venusian = DummyVenusian()
+ decorator.venusian = venusian
+ def foo(): pass
+ decorator(foo)
+ attachments = venusian.attachments
+ category = attachments[0][2]
+ depth = attachments[0][3]
+ self.assertEqual(depth, 2)
+ self.assertEqual(category, 'foo')
+
class Test_exception_view_config(BaseTest, unittest.TestCase):
def _makeOne(self, *args, **kw):
from pyramid.view import exception_view_config
@@ -184,6 +208,18 @@ class Test_exception_view_config(BaseTest, unittest.TestCase):
self.assertEqual(settings[0]['attr'], 'view')
self.assertEqual(settings[0]['_info'], 'codeinfo')
+ def test_call_with_venusian_args(self):
+ decorator = self._makeOne(_depth=1, _category='foo')
+ venusian = DummyVenusian()
+ decorator.venusian = venusian
+ def foo(): pass
+ decorator(foo)
+ attachments = venusian.attachments
+ category = attachments[0][2]
+ depth = attachments[0][3]
+ self.assertEqual(depth, 2)
+ self.assertEqual(category, 'foo')
+
class RenderViewToResponseTests(BaseTest, unittest.TestCase):
def _callFUT(self, *arg, **kw):
from pyramid.view import render_view_to_response
@@ -564,7 +600,9 @@ class TestViewConfigDecorator(unittest.TestCase):
decorator.venusian = venusian
def foo(): pass
decorator(foo)
- self.assertEqual(venusian.depth, 2)
+ attachments = venusian.attachments
+ depth = attachments[0][3]
+ self.assertEqual(depth, 2)
def test_call_withoutcategory(self):
decorator = self._makeOne()
@@ -1000,8 +1038,7 @@ class DummyVenusian(object):
self.attachments = []
def attach(self, wrapped, callback, category=None, depth=1):
- self.attachments.append((wrapped, callback, category))
- self.depth = depth
+ self.attachments.append((wrapped, callback, category, depth))
return self.info
class DummyRegistry(object):
@@ -1028,7 +1065,7 @@ class DummyVenusianContext(object):
def call_venusian(venusian, context=None):
if context is None:
context = DummyVenusianContext()
- for wrapped, callback, category in venusian.attachments:
+ for wrapped, callback, category, depth in venusian.attachments:
callback(context, None, None)
return context.config
diff --git a/pyramid/view.py b/pyramid/view.py
index 3b2bafa27..46aec45f1 100644
--- a/pyramid/view.py
+++ b/pyramid/view.py
@@ -199,7 +199,8 @@ class view_config(object):
combination with the ``category`` argument of ``scan`` to control which
views should be processed.
- See the :py:func:`venusian.attach` function in Venusian for more information.
+ See the :py:func:`venusian.attach` function in Venusian for more
+ information about the ``_depth`` and ``_category`` arguments.
.. seealso::
@@ -395,10 +396,11 @@ class notfound_view_config(object):
being used, :class:`~pyramid.httpexceptions.HTTPMovedPermanently will
be used` for the redirect response if a slash-appended route is found.
- .. versionchanged:: 1.6
-
See :ref:`changing_the_notfound_view` for detailed usage information.
+ .. versionchanged:: 1.9.1
+ Added the ``_depth`` and ``_category`` arguments.
+
"""
venusian = venusian
@@ -408,12 +410,15 @@ class notfound_view_config(object):
def __call__(self, wrapped):
settings = self.__dict__.copy()
+ depth = settings.pop('_depth', 0)
+ category = settings.pop('_category', 'pyramid')
def callback(context, name, ob):
config = context.config.with_package(info.module)
config.add_notfound_view(view=ob, **settings)
- info = self.venusian.attach(wrapped, callback, category='pyramid')
+ info = self.venusian.attach(wrapped, callback, category=category,
+ depth=depth + 1)
if info.scope == 'class':
# if the decorator was attached to a method in a class, or
@@ -455,6 +460,9 @@ class forbidden_view_config(object):
See :ref:`changing_the_forbidden_view` for detailed usage information.
+ .. versionchanged:: 1.9.1
+ Added the ``_depth`` and ``_category`` arguments.
+
"""
venusian = venusian
@@ -464,12 +472,15 @@ class forbidden_view_config(object):
def __call__(self, wrapped):
settings = self.__dict__.copy()
+ depth = settings.pop('_depth', 0)
+ category = settings.pop('_category', 'pyramid')
def callback(context, name, ob):
config = context.config.with_package(info.module)
config.add_forbidden_view(view=ob, **settings)
- info = self.venusian.attach(wrapped, callback, category='pyramid')
+ info = self.venusian.attach(wrapped, callback, category=category,
+ depth=depth + 1)
if info.scope == 'class':
# if the decorator was attached to a method in a class, or
@@ -511,6 +522,9 @@ class exception_view_config(object):
:meth:`pyramid.view.view_config`, and each predicate argument restricts
the set of circumstances under which this exception view will be invoked.
+ .. versionchanged:: 1.9.1
+ Added the ``_depth`` and ``_category`` arguments.
+
"""
venusian = venusian
@@ -524,12 +538,15 @@ class exception_view_config(object):
def __call__(self, wrapped):
settings = self.__dict__.copy()
+ depth = settings.pop('_depth', 0)
+ category = settings.pop('_category', 'pyramid')
def callback(context, name, ob):
config = context.config.with_package(info.module)
config.add_exception_view(view=ob, **settings)
- info = self.venusian.attach(wrapped, callback, category='pyramid')
+ info = self.venusian.attach(wrapped, callback, category=category,
+ depth=depth + 1)
if info.scope == 'class':
# if the decorator was attached to a method in a class, or