summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris McDonough <chrism@plope.com>2011-12-03 16:24:34 -0500
committerChris McDonough <chrism@plope.com>2011-12-03 16:24:34 -0500
commit5224059f71d0ad592a611c196a3af7cbd1dc828f (patch)
tree636c2c2b0613d8350629e1a85a43f1b1ccf05e41
parent9d97b654057e621c4928fe597053d54aa5f63a8c (diff)
downloadpyramid-5224059f71d0ad592a611c196a3af7cbd1dc828f.tar.gz
pyramid-5224059f71d0ad592a611c196a3af7cbd1dc828f.tar.bz2
pyramid-5224059f71d0ad592a611c196a3af7cbd1dc828f.zip
add more content to the introspectables narr chapter; adjust introspection registrations while doing so
-rw-r--r--docs/narr/extconfig.rst13
-rw-r--r--docs/narr/introspector.rst425
-rw-r--r--pyramid/config/factories.py3
-rw-r--r--pyramid/config/i18n.py3
-rw-r--r--pyramid/config/rendering.py7
-rw-r--r--pyramid/config/routes.py21
-rw-r--r--pyramid/config/security.py6
-rw-r--r--pyramid/config/tweens.py9
-rw-r--r--pyramid/config/views.py17
-rw-r--r--pyramid/interfaces.py9
-rw-r--r--pyramid/tests/test_config/test_views.py14
11 files changed, 481 insertions, 46 deletions
diff --git a/docs/narr/extconfig.rst b/docs/narr/extconfig.rst
index ac8b83baa..856654377 100644
--- a/docs/narr/extconfig.rst
+++ b/docs/narr/extconfig.rst
@@ -336,7 +336,7 @@ Two introspectables may have relationships between each other.
config = Configurator()
config.add_directive('add_jammyjam', add_jammyjam)
-In the above example, the ``add_jammyjam`` directive registers *two*
+In the above example, the ``add_jammyjam`` directive registers two
introspectables. The first is related to the ``value`` passed to the
directive; the second is related to the ``template`` passed to the directive.
If you believe a concept within a directive is important enough to have its
@@ -352,8 +352,15 @@ introspectable and the ``tmpl_intr`` introspectable; the arguments passed to
``relate`` are the category name and discriminator of the ``tmpl_intr``
introspectable.
+Relationships need not be made between two introspectables created by the
+same directive. Instead, a relationship can be formed between an
+introspectable created in one directive and another introspectable created in
+another by calling ``relate`` on either side with the other directive's
+category name and discriminator. An error will be raised at configuration
+commit time if you attempt to relate an introspectable with another
+nonexistent introspectable, however.
+
Introspectable relationships will show up in frontend system renderings of
introspection values. For example, if a view registration names a route
name, the introspectable related to the view callable will show a reference
-to the route it relates to and vice versa.
-
+to the route to which it relates to and vice versa.
diff --git a/docs/narr/introspector.rst b/docs/narr/introspector.rst
index 3cbafa010..8adfde7d1 100644
--- a/docs/narr/introspector.rst
+++ b/docs/narr/introspector.rst
@@ -9,16 +9,17 @@ Pyramid Configuration Introspection
When Pyramid starts up, each call to a :term:`configuration directive` causes
one or more :term:`introspectable` objects to be registered with an
-:term:`introspector`. This introspector can be queried by application code
-to obtain information about the configuration of the running application.
-This feature is useful for debug toolbars, command-line scripts which show
-some aspect of configuration, and for runtime reporting of startup-time
+:term:`introspector`. The introspector can be queried by application code to
+obtain information about the configuration of the running application. This
+feature is useful for debug toolbars, command-line scripts which show some
+aspect of configuration, and for runtime reporting of startup-time
configuration settings.
Using the Introspector
----------------------
-Here's an example of using Pyramid's introspector:
+Here's an example of using Pyramid's introspector from within a view
+callable:
.. code-block:: python
:linenos:
@@ -26,64 +27,440 @@ Here's an example of using Pyramid's introspector:
from pyramid.view import view_config
from pyramid.response import Response
- @view_config(route_name='foo')
@view_config(route_name='bar')
def route_accepts(request):
introspector = request.registry.introspector
route_name = request.matched_route.name
route_intr = introspector.get('routes', route_name)
- return Response(str(route_intr['accept']))
+ return Response(str(route_intr['pattern']))
-This view will return a response that contains the "accept" argument provided
-to the ``add_route`` method of the route which matched when the view was
-called. It used the :meth:`pyramid.interfaces.IIntrospector.get` method to
-return an introspectable in the category ``routes`` with a
-:term:`discriminator` equal to the matched route name. It then used the
-returned introspectable to obtain an "accept" value.
+This view will return a response that contains the "pattern" argument
+provided to the ``add_route`` method of the route which matched when the view
+was called. It uses the :meth:`pyramid.interfaces.IIntrospector.get` method
+to return an introspectable in the category ``routes`` with a
+:term:`discriminator` equal to the matched route name. It then uses the
+returned introspectable to obtain an "pattern" value.
-The introspector has a number of other query-related methods: see
-:class:`pyramid.interfaces.IIntrospector` for more information. The
-introspectable returned by the query methods of the introspector has methods
-and attributes described by :class:`pyramid.interfaces.IIntrospectable`.
+The introspectable returned by the query methods of the introspector has
+methods and attributes described by
+:class:`pyramid.interfaces.IIntrospectable`. In particular, the
+:meth:`~pyramid.interfaces.IIntrospector.get`,
+:meth:`~pyramid.interfaces.IIntrospector.get_category`,
+:meth:`~pyramid.interfaces.IIntrospector.categories`,
+:meth:`~pyramid.interfaces.IIntrospector.categorized`, and
+:meth:`~pyramid.interfaces.IIntrospector.related` methods of an introspector
+can be used to query for introspectables.
-Concrete Introspection Categories
----------------------------------
+Introspectable Objects
+----------------------
+
+Introspectable objects are returned from query methods of an introspector.
+Each introspectable object implements the attributes and methods the
+documented at :class:`pyramid.interfaces.IIntrospectable`.
+
+The important attributes shared by all introspectables are the following:
+
+``title``
+
+ A human-readable text title describing the introspectable
+
+``category_name``
+
+ A text category name describing the introspection category to which this
+ introspectable belongs. It is often a plural if there are expected to be
+ more than one introspectable registered within the category.
+
+``discriminator``
+
+ A hashable object representing the unique value of this introspectable
+ within its category.
+
+``discriminator_hash``
-This is a list of concrete introspection categories provided by Pyramid.
+ The integer hash of the discriminator (useful for using in HTML links).
+
+``type_name``
+
+ The text name of a subtype within this introspectable's category. If there
+ is only one type name in this introspectable's category, this value will
+ often be a singular version of the category name but it can be an arbitrary
+ value.
+
+Besides having the attributes described above, an introspectable is a
+dictionary-like object. An introspectable can be queried for data values via
+its ``__getitem__``, ``get``, ``keys``, ``values``, or ``items`` methods.
+For example:
+
+.. code-block:: python
+ :linenos:
+
+ route_intr = introspector.get('routes', 'edit_user')
+ pattern = route_intr['pattern']
+
+Pyramid Introspection Categories
+--------------------------------
+
+The list of concrete introspection categories provided by built-in Pyramid
+configuration directives follows. Add-on packages may supply other
+introspectables in categories not described here.
``subscribers``
+ Each introspectable in the ``subscribers`` category represents a call to
+ :meth:`pryamid.config.Configurator.add_subscriber` (or the decorator
+ equivalent); each will have the following data.
+
+ ``subscriber``
+
+ The subscriber callable object (the resolution of the ``subscriber``
+ argument passed to ``add_susbcriber``).
+
+ ``interfaces``
+
+ A sequence of interfaces (or classes) that are subscribed to (the
+ resolution of the ``ifaces`` argument passed to ``add_subscriber``).
+
``response adapters``
-``asset overrides``
+ Each introspectable in the ``response adapters`` category represents a call
+ to :meth:`pyramid.config.Configurator.add_response_adapter` (or a decorator
+ equivalent); each will have the following data.
+
+ ``adapter``
+
+ The adapter object (the resolved ``adapter`` argument to
+ ``add_response_adapter``).
+
+ ``type``
+
+ The resolved ``type_or_iface`` argument passed to
+ ``add_response_adapter``.
``root factories``
+ XXX ``default root factory`` category?
+
+ Each introspectable in the ``root factories`` category represents a call to
+ :meth:`pyramid.config.Configurator.set_root_factory` (or the Configurator
+ constructor equivalent) *or* a ``factory`` argument passed to
+ :meth:`pyramid.config.Configurator.add_route`; each will have the following
+ data.
+
+ ``factory``
+
+ The factory object (the resolved ``factory`` argument to
+ ``set_root_factory``).
+
+ ``route_name``
+
+ The name of the route which will use this factory. If this is the
+ *default* root factory (if it's registered during a call to
+ ``set_root_factory``), this value will be ``None``.
+
``session factory``
+ Only one introspectable will exist in the ``session factory`` category. It
+ represents a call to :meth:`pyramid.config.Configurator.set_session_factory`
+ (or the Configurator constructor equivalent); it will have the following
+ data.
+
+ ``factory``
+
+ The factory object (the resolved ``factory`` argument to
+ ``set_session_factory``).
+
``request factory``
+ Only one introspectable will exist in the ``request factory`` category. It
+ represents a call to :meth:`pyramid.config.Configurator.set_request_factory`
+ (or the Configurator constructor equivalent); it will have the following
+ data.
+
+ ``factory``
+
+ The factory object (the resolved ``factory`` argument to
+ ``set_request_factory``).
+
``locale negotiator``
-``translation directories``
+ Only one introspectable will exist in the ``locale negotiator`` category.
+ It represents a call to
+ :meth:`pyramid.config.Configurator.set_locale_negotiator` (or the
+ Configurator constructor equivalent); it will have the following data.
+
+ ``negotiator``
+
+ The factory object (the resolved ``negotiator`` argument to
+ ``set_locale_negotiator``).
``renderer factories``
+ Each introspectable in the ``renderer factories`` category represents a
+ call to :meth:`pyramid.config.Configurator.add_renderer` (or the
+ Configurator constructor equivalent); each will have the following data.
+
+ ``name``
+
+ The name of the renderer (the value of the ``name`` argument to
+ ``add_renderer``).
+
+ ``factory``
+
+ The factory object (the resolved ``factory`` argument to
+ ``add_renderer``).
+
+``renderer globals factory``
+
+ There will be one and only one introspectable in the ``renderer globals
+ factory`` category. It represents a call to
+ :meth:`pyramid.config.Configurator.set_renderer_globals_factory`; it will
+ have the following data.
+
+ ``factory``
+
+ The factory object (the resolved ``factory`` argument to
+ ``set_renderer_globals_factory``).
+
``routes``
+ Each introspectable in the ``routes`` category represents a call to
+ :meth:`pyramid.config.Configurator.add_route`; each will have the following
+ data.
+
+ ``name``
+
+ The ``name`` argument passed to ``add_route``.
+
+ ``pattern``
+
+ The ``pattern`` argument passed to ``add_route``.
+
+ ``factory``
+
+ The (resolved) ``factory`` argument passed to ``add_route``.
+
+ ``xhr``
+
+ The ``xhr`` argument passed to ``add_route``.
+
+ ``request_method``
+
+ The ``request_method`` argument passed to ``add_route``.
+
+ ``request_methods``
+
+ A sequence of request method names implied by the ``request_method``
+ argument passed to ``add_route``.
+
+ ``path_info``
+
+ The ``path_info`` argument passed to ``add_route``.
+
+ ``request_param``
+
+ The ``request_param`` argument passed to ``add_route``.
+
+ ``header``
+
+ The ``header`` argument passed to ``add_route``.
+
+ ``accept``
+
+ The ``accept`` argument passed to ``add_route``.
+
+ ``traverse``
+
+ The ``traverse`` argument passed to ``add_route``.
+
+ ``custom_predicates``
+
+ The ``custom_predicates`` argument passed to ``add_route``.
+
+ ``pregenerator``
+
+ The ``pregenerator`` argument passed to ``add_route``.
+
+ ``pregenerator``
+
+ The ``static`` argument passed to ``add_route``.
+
+ ``pregenerator``
+
+ The ``use_global_views`` argument passed to ``add_route``.
+
+ ``object``
+
+ The :class:`pyramid.interfaces.IRoute` object that is used to perform
+ matching and generation for this route.
+
``authentication policy``
+ There will be one and only one introspectable in the ``authentication
+ policy`` category. It represents a call to the
+ :meth:`pyramid.config.Configurator.set_authentication_policy` method (or
+ its Configurator constructor equivalent); it will have the following data.
+
+ ``policy``
+
+ The policy object (the resolved ``policy`` argument to
+ ``set_authentication_policy``).
+
``authorization policy``
+ There will be one and only one introspectable in the ``authorization
+ policy`` category. It represents a call to the
+ :meth:`pyramid.config.Configurator.set_authorization_policy` method (or its
+ Configurator constructor equivalent); it will have the following data.
+
+ ``policy``
+
+ The policy object (the resolved ``policy`` argument to
+ ``set_authorization_policy``).
+
``default permission``
-``tweens (implicit)``
+ There will be one and only one introspectable in the ``default permission``
+ category. It represents a call to the
+ :meth:`pyramid.config.Configurator.set_default_permission` method (or its
+ Configurator constructor equivalent); it will have the following data.
+
+ ``value``
+
+ The permission name passed to ``set_default_permission``.
``views``
-``templates``
+ Each introspectable in the ``views`` category represents a call to
+ :meth:`pyramid.config.Configurator.add_view`; each will have the following
+ data.
+
+ ``name``
+
+ The ``name`` argument passed to ``add_view``.
+
+ ``context``
+
+ The (resolved) ``context`` argument passed to ``add_view``.
+
+ ``containment``
+
+ The (resolved) ``containment`` argument passed to ``add_view``.
+
+ ``request_param``
+
+ The ``request_param`` argument passed to ``add_view``.
+
+ ``request_methods``
+
+ A sequence of request method names implied by the ``request_method``
+ argument passed to ``add_view``.
+
+ ``route_name``
+
+ The ``route_name`` argument passed to ``add_view``.
+
+ ``attr``
+
+ The ``attr`` argument passed to ``add_view``.
+
+ ``xhr``
+
+ The ``xhr`` argument passed to ``add_view``.
+
+ ``accept``
+
+ The ``accept`` argument passed to ``add_view``.
+
+ ``header``
+
+ The ``header`` argument passed to ``add_view``.
+
+ ``path_info``
+
+ The ``path_info`` argument passed to ``add_view``.
+
+ ``match_param``
+
+ The ``match_param`` argument passed to ``add_view``.
+
+ ``callable``
+
+ The (resolved) ``view`` argument passed to ``add_view``. Represents the
+ "raw" view callable.
+
+ ``derived_callable``
+
+ The view callable derived from the ``view`` argument passed to
+ ``add_view``. Represents the view callable which Pyramid itself calls
+ (wrapped in security and other wrappers).
+
+ ``mapper``
+
+ The (resolved) ``mapper`` argument passed to ``add_view``.
+
+ ``decorator``
+
+ The (resolved) ``decorator`` argument passed to ``add_view``.
``permissions``
+ Each introspectable in the ``permissions`` category represents a call to
+ :meth:`pyramid.config.Configurator.add_view` that has an explicit
+ ``permission`` argument to *or* a call to
+ :meth:`pyramid.config.Configurator.set_default_permission`; each will have
+ the following data.
+
+ ``value``
+
+ The permission name passed to ``add_view`` or ``set_default_permission``.
+
+``templates``
+
+ Each introspectable in the ``templates`` category represents a call to
+ :meth:`pyramid.config.Configurator.add_view` that has a ``renderer``
+ argument which points to a template; each will have the following data.
+
+ ``name``
+
+ The renderer's name (a string).
+
+ ``type``
+
+ The renderer's type (a string).
+
+ ``renderer``
+
+ The :class:`pyramid.interfaces.IRendererInfo` object which represents
+ this template's renderer.
+
``view mapper``
+ XXX default view mapper category?
+
+ Each introspectable in the ``permissions`` category represents a call to
+ :meth:`pyramid.config.Configurator.add_view` that has an explicit
+ ``mapper`` argument to *or* a call to
+ :meth:`pyramid.config.Configurator.set_view_mapper`; each will have
+ the following data.
+
+ ``mapper``
+
+ The (resolved) ``mapper`` argument passed to ``add_view`` or
+ ``set_view_mapper``.
+
+``asset overrides``
+
+ XXX
+
+``translation directories``
+
+ XXX
+
+``tweens (implicit)``
+
+ XXX
+
+``tweens (explicit)``
+
+ XXX
+
diff --git a/pyramid/config/factories.py b/pyramid/config/factories.py
index cfa91d6d9..530b6cc28 100644
--- a/pyramid/config/factories.py
+++ b/pyramid/config/factories.py
@@ -29,7 +29,8 @@ class FactoriesConfiguratorMixin(object):
self.registry.registerUtility(factory, IRootFactory)
self.registry.registerUtility(factory, IDefaultRootFactory) # b/c
- intr = self.introspectable('root factories', None,
+ intr = self.introspectable('root factories',
+ None,
self.object_description(factory),
'root factory')
intr['factory'] = factory
diff --git a/pyramid/config/i18n.py b/pyramid/config/i18n.py
index 2c149923c..5770f84c8 100644
--- a/pyramid/config/i18n.py
+++ b/pyramid/config/i18n.py
@@ -40,7 +40,8 @@ class I18NConfiguratorMixin(object):
"""
def register():
self._set_locale_negotiator(negotiator)
- intr = self.introspectable('locale negotiator', None, repr(negotiator),
+ intr = self.introspectable('locale negotiator', None,
+ self.object_description(negotiator),
'locale negotiator')
intr['negotiator'] = negotiator
self.action(ILocaleNegotiator, register, introspectables=(intr,))
diff --git a/pyramid/config/rendering.py b/pyramid/config/rendering.py
index 0d37e201f..926511b7b 100644
--- a/pyramid/config/rendering.py
+++ b/pyramid/config/rendering.py
@@ -48,7 +48,8 @@ class RenderingConfiguratorMixin(object):
name = ''
def register():
self.registry.registerUtility(factory, IRendererFactory, name=name)
- intr = self.introspectable('renderer factories', name,
+ intr = self.introspectable('renderer factories',
+ name,
self.object_description(factory),
'renderer factory')
intr['factory'] = factory
@@ -74,7 +75,9 @@ class RenderingConfiguratorMixin(object):
.. warning::
- This method is deprecated as of Pyramid 1.1.
+ This method is deprecated as of Pyramid 1.1. Use a BeforeRender
+ event subscriber as documented in the :ref:`hooks_chapter` chapter
+ instead.
.. note::
diff --git a/pyramid/config/routes.py b/pyramid/config/routes.py
index 35ad0f8c4..2628f9cac 100644
--- a/pyramid/config/routes.py
+++ b/pyramid/config/routes.py
@@ -14,6 +14,7 @@ from pyramid.urldispatch import RoutesMapper
from pyramid.config.util import (
action_method,
make_predicates,
+ as_sorted_tuple,
)
class RoutesConfiguratorMixin(object):
@@ -369,14 +370,17 @@ class RoutesConfiguratorMixin(object):
mapper = self.get_routes_mapper()
- intr = self.introspectable('routes', name,
+ introspectables = []
+
+ intr = self.introspectable('routes',
+ name,
'%s (pattern: %r)' % (name, pattern),
'route')
intr['name'] = name
intr['pattern'] = pattern
intr['factory'] = factory
intr['xhr'] = xhr
- intr['request_method'] = request_method
+ intr['request_methods'] = as_sorted_tuple(request_method)
intr['path_info'] = path_info
intr['request_param'] = request_param
intr['header'] = header
@@ -386,6 +390,17 @@ class RoutesConfiguratorMixin(object):
intr['pregenerator'] = pregenerator
intr['static'] = static
intr['use_global_views'] = use_global_views
+ introspectables.append(intr)
+
+ if factory:
+ factory_intr = self.introspectable('root factories',
+ name,
+ self.object_description(factory),
+ 'root factory')
+ factory_intr['factory'] = factory
+ factory_intr['route_name'] = name
+ factory_intr.relate('routes', name)
+ introspectables.append(factory_intr)
def register_route_request_iface():
request_iface = self.registry.queryUtility(IRouteRequest, name=name)
@@ -414,7 +429,7 @@ class RoutesConfiguratorMixin(object):
# But IRouteRequest interfaces must be registered before we begin to
# process view registrations (in phase 3)
self.action(('route', name), register_route_request_iface,
- order=PHASE2_CONFIG, introspectables=(intr,))
+ order=PHASE2_CONFIG, introspectables=introspectables)
# deprecated adding views from add_route; must come after
# route registration for purposes of autocommit ordering
diff --git a/pyramid/config/security.py b/pyramid/config/security.py
index 1830fb900..a0ea173ba 100644
--- a/pyramid/config/security.py
+++ b/pyramid/config/security.py
@@ -126,8 +126,10 @@ class SecurityConfiguratorMixin(object):
permission,
'default permission')
intr['value'] = permission
- perm_intr = self.introspectable('permissions', permission,
- permission, 'permission')
+ perm_intr = self.introspectable('permissions',
+ permission,
+ permission,
+ 'permission')
perm_intr['value'] = permission
# default permission used during view registration (phase 3)
self.action(IDefaultPermission, register, order=PHASE1_CONFIG,
diff --git a/pyramid/config/tweens.py b/pyramid/config/tweens.py
index 22ea21a57..e36e9e84e 100644
--- a/pyramid/config/tweens.py
+++ b/pyramid/config/tweens.py
@@ -146,7 +146,8 @@ class TweensConfiguratorMixin(object):
registry.registerUtility(tweens, ITweens)
ex_intr = self.introspectable('tweens (implicit)',
('tween', EXCVIEW, False),
- EXCVIEW, 'implicit tween')
+ EXCVIEW,
+ 'implicit tween')
ex_intr['factory'] = excview_tween_factory
ex_intr['type'] = 'implicit'
ex_intr['under'] = None
@@ -163,8 +164,10 @@ class TweensConfiguratorMixin(object):
discriminator = ('tween', name, explicit)
tween_type = explicit and 'explicit' or 'implicit'
- intr = self.introspectable('tweens (%s)' % tween_type, discriminator,
- name, '%s tween' % tween_type)
+ intr = self.introspectable('tweens (%s)' % tween_type,
+ discriminator,
+ name,
+ '%s tween' % tween_type)
intr['factory'] = tween_factory
intr['type'] = tween_type
intr['under'] = under
diff --git a/pyramid/config/views.py b/pyramid/config/views.py
index 5c4470834..02dcbf2ee 100644
--- a/pyramid/config/views.py
+++ b/pyramid/config/views.py
@@ -962,7 +962,7 @@ class ViewsConfiguratorMixin(object):
context=context,
containment=containment,
request_param=request_param,
- request_method=request_method,
+ request_methods=request_method,
route_name=route_name,
attr=attr,
xhr=xhr,
@@ -1116,9 +1116,18 @@ class ViewsConfiguratorMixin(object):
(IExceptionViewClassifier, request_iface, context),
IMultiView, name=name)
+ if mapper:
+ mapper_intr = self.introspectable('view mappers',
+ discriminator,
+ view_desc,
+ 'view mapper')
+ mapper_intr['mapper'] = mapper
+ mapper_intr.relate('views', discriminator)
+ introspectables.append(mapper_intr)
if route_name:
view_intr.relate('routes', route_name) # see add_route
if renderer is not None and renderer.name and '.' in renderer.name:
+ # it's a template
tmpl_intr = self.introspectable('templates', discriminator,
renderer.name, 'template')
tmpl_intr.relate('views', discriminator)
@@ -1360,9 +1369,11 @@ class ViewsConfiguratorMixin(object):
self.registry.registerUtility(mapper, IViewMapperFactory)
# IViewMapperFactory is looked up as the result of view config
# in phase 3
- intr = self.introspectable('view mapper', IViewMapperFactory,
+ intr = self.introspectable('view mappers',
+ IViewMapperFactory,
self.object_description(mapper),
- 'view mapper')
+ 'default view mapper')
+ intr['mapper'] = mapper
self.action(IViewMapperFactory, register, order=PHASE1_CONFIG,
introspectables=(intr,))
diff --git a/pyramid/interfaces.py b/pyramid/interfaces.py
index 05881571e..a8a9cc55a 100644
--- a/pyramid/interfaces.py
+++ b/pyramid/interfaces.py
@@ -946,14 +946,15 @@ class IIntrospectable(Interface):
title = Attribute('Text title describing this introspectable')
type_name = Attribute('Text type name describing this introspectable')
order = Attribute('integer order in which registered with introspector '
- '(managed by introspector, usually')
+ '(managed by introspector, usually)')
category_name = Attribute('introspection category name')
discriminator = Attribute('introspectable discriminator (within category) '
'(must be hashable)')
discriminator_hash = Attribute('an integer hash of the discriminator')
- action_info = Attribute('An object representing the caller that invoked '
- 'the creation of this introspectable (usually '
- 'a sentinel until updated during self.register)')
+ action_info = Attribute('An IActionInfo object representing the caller '
+ 'that invoked the creation of this introspectable '
+ '(usually a sentinel until updated during '
+ 'self.register)')
def relate(category_name, discriminator):
""" Indicate an intent to relate this IIntrospectable with another
diff --git a/pyramid/tests/test_config/test_views.py b/pyramid/tests/test_config/test_views.py
index a9a4d5836..d80a6bb64 100644
--- a/pyramid/tests/test_config/test_views.py
+++ b/pyramid/tests/test_config/test_views.py
@@ -1362,6 +1362,20 @@ class TestViewsConfigurationMixin(unittest.TestCase):
request = self._makeRequest(config)
self.assertEqual(view(None, request), 'OK')
+ def test_add_view_with_mapper(self):
+ from pyramid.renderers import null_renderer
+ class Mapper(object):
+ def __init__(self, **kw):
+ self.__class__.kw = kw
+ def __call__(self, view):
+ return view
+ config = self._makeOne(autocommit=True)
+ def view(context, request): return 'OK'
+ config.add_view(view=view, mapper=Mapper, renderer=null_renderer)
+ view = self._getViewCallable(config)
+ self.assertEqual(view(None, None), 'OK')
+ self.assertEqual(Mapper.kw['mapper'], Mapper)
+
def test_derive_view_function(self):
from pyramid.renderers import null_renderer
def view(request):