diff options
| author | Chris McDonough <chrism@plope.com> | 2011-12-04 19:27:46 -0500 |
|---|---|---|
| committer | Chris McDonough <chrism@plope.com> | 2011-12-04 19:27:46 -0500 |
| commit | 5d462f0c660f939c773862b0fab81728c9ba62c7 (patch) | |
| tree | 658df249d53de844c2f422ab04c4c26ee4feb86d /docs | |
| parent | d5666e630a08c943a22682540aa51174cee6851f (diff) | |
| parent | a78b58dd5cf665f7a7aaa18e9e7f6cae3fc7f749 (diff) | |
| download | pyramid-5d462f0c660f939c773862b0fab81728c9ba62c7.tar.gz pyramid-5d462f0c660f939c773862b0fab81728c9ba62c7.tar.bz2 pyramid-5d462f0c660f939c773862b0fab81728c9ba62c7.zip | |
merge feature.introspection branch
Diffstat (limited to 'docs')
| -rw-r--r-- | docs/api/config.rst | 17 | ||||
| -rw-r--r-- | docs/api/interfaces.rst | 8 | ||||
| -rw-r--r-- | docs/api/registry.rst | 30 | ||||
| -rw-r--r-- | docs/glossary.rst | 42 | ||||
| -rw-r--r-- | docs/index.rst | 6 | ||||
| -rw-r--r-- | docs/latexindex.rst | 7 | ||||
| -rw-r--r-- | docs/narr/advconfig.rst | 79 | ||||
| -rw-r--r-- | docs/narr/extconfig.rst | 366 | ||||
| -rw-r--r-- | docs/narr/introspector.rst | 542 | ||||
| -rw-r--r-- | docs/narr/tb_introspector.png | bin | 0 -> 46164 bytes |
10 files changed, 1015 insertions, 82 deletions
diff --git a/docs/api/config.rst b/docs/api/config.rst index a8c193b60..dbfbb1761 100644 --- a/docs/api/config.rst +++ b/docs/api/config.rst @@ -94,6 +94,23 @@ .. automethod:: set_renderer_globals_factory(factory) + .. attribute:: introspectable + + A shortcut attribute which points to the + :class:`pyramid.registry.Introspectable` class (used during + directives to provide introspection to actions). + + This attribute is new as of :app:`Pyramid` 1.3. + + .. attribute:: introspector + + The :term:`introspector` related to this configuration. It is an + instance implementing the :class:`pyramid.interfaces.IIntrospector` + interface. If the Configurator constructor was supplied with an + ``introspector`` argument, this attribute will be that value. + Otherwise, it will be an instance of a default introspector type. + + This attribute is new as of :app:`Pyramid` 1.3. .. attribute:: global_registries diff --git a/docs/api/interfaces.rst b/docs/api/interfaces.rst index b336e549d..5b190b53b 100644 --- a/docs/api/interfaces.rst +++ b/docs/api/interfaces.rst @@ -68,3 +68,11 @@ Other Interfaces .. autointerface:: IResponse :members: + .. autointerface:: IIntrospectable + :members: + + .. autointerface:: IIntrospector + :members: + + .. autointerface:: IActionInfo + :members: diff --git a/docs/api/registry.rst b/docs/api/registry.rst index 4d327370a..25192f3ed 100644 --- a/docs/api/registry.rst +++ b/docs/api/registry.rst @@ -14,3 +14,33 @@ accessed as ``request.registry.settings`` or ``config.registry.settings`` in a typical Pyramid application. + .. attribute:: introspector + + When a registry is set up (or created) by a :term:`Configurator`, the + registry will be decorated with an instance named ``introspector`` + implementing the :class:`pyramid.interfaces.IIntrospector` interface. + See also :attr:`pyramid.config.Configurator.introspector``. + + When a registry is created "by hand", however, this attribute will not + exist until set up by a configurator. + + This attribute is often accessed as ``request.registry.introspector`` in + a typical Pyramid application. + + This attribute is new as of :app:`Pyramid` 1.3. + +.. class:: Introspectable + + The default implementation of the interface + :class:`pyramid.interfaces.IIntrospectable` used by framework exenders. + An instance of this class is is created when + :attr:`pyramid.config.Configurator.introspectable` is called. + + This class is new as of :app:`Pyramid` 1.3. + +.. class:: noop_introspector + + An introspector which throws away all registrations, useful for disabling + introspection altogether (pass as ``introspector`` to the + :term:`Configurator` constructor). + diff --git a/docs/glossary.rst b/docs/glossary.rst index 0d69fbb0d..399b78cdf 100644 --- a/docs/glossary.rst +++ b/docs/glossary.rst @@ -563,9 +563,8 @@ Glossary also `PEP 318 <http://www.python.org/dev/peps/pep-0318/>`_. configuration declaration - An individual method call made to an instance of a :app:`Pyramid` - :term:`Configurator` object which performs an arbitrary action, such as - registering a :term:`view configuration` (via the + An individual method call made to a :term:`configuration directive`, + such as registering a :term:`view configuration` (via the :meth:`~pyramid.config.Configurator.add_view` method of the configurator) or :term:`route configuration` (via the :meth:`~pyramid.config.Configurator.add_route` method of the @@ -941,3 +940,40 @@ Glossary directory of a Python installation or virtualenv as the result of running ``setup.py install`` or ``setup.py develop``. + introspector + An object with the methods described by + :class:`pyramid.interfaces.IIntrospector` that is available in both + configuration code (for registration) and at runtime (for querying) that + allows a developer to introspect configuration statements and + relationships between those statements. + + conflict resolution + Pyramid attempts to resolve ambiguous configuration statements made by + application developers via automatic conflict resolution. Automatic + conflict resolution is described in + :ref:`automatic_conflict_resolution`. If Pyramid cannot resolve + ambiguous configuration statements, it is possible to manually resolve + them as described in :ref:`manually_resolving_conflicts`. + + configuration directive + A method of the :term:`Configurator` which causes a configuration action + to occur. The method :meth:`pyramid.config.Configurator.add_view` is a + configuration directive, and application developers can add their own + directives as necessary (see :ref:`add_directive`). + + action + Represents a pending configuration statement generated by a call to a + :term:`configuration directive`. The set of pending configuration + actions are processed when :meth:`pyramid.config.Configurator.commit` is + called. + + discriminator + The unique identifier of an :term:`action`. + + introspectable + An object which implements the attributes and methods described in + :class:`pyramid.interfaces.IIntrospectable`. Introspectables are used + by the :term:`introspector` to display configuration information about + a running Pyramid application. An introspectable is associated with a + :term:`action` by virtue of the + :meth:`pyramid.config.Configurator.action` method. diff --git a/docs/index.rst b/docs/index.rst index e4de8b0c8..ceb29d108 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -65,6 +65,7 @@ Narrative documentation in chapter form explaining how to use narr/configuration narr/project narr/startup + narr/router narr/urldispatch narr/views narr/renderers @@ -87,9 +88,10 @@ Narrative documentation in chapter form explaining how to use narr/security narr/hybrid narr/hooks - narr/advconfig + narr/introspector narr/extending - narr/router + narr/advconfig + narr/extconfig narr/threadlocals narr/zca diff --git a/docs/latexindex.rst b/docs/latexindex.rst index 584dd3825..4db5b64b2 100644 --- a/docs/latexindex.rst +++ b/docs/latexindex.rst @@ -31,6 +31,8 @@ Narrative Documentation narr/configuration narr/firstapp narr/project + narr/startup + narr/router narr/urldispatch narr/views narr/renderers @@ -53,9 +55,10 @@ Narrative Documentation narr/security narr/hybrid narr/hooks - narr/advconfig + narr/introspector narr/extending - narr/startup + narr/advconfig + narr/extconfig narr/threadlocals narr/zca diff --git a/docs/narr/advconfig.rst b/docs/narr/advconfig.rst index 7b62b1a73..3a7bf2805 100644 --- a/docs/narr/advconfig.rst +++ b/docs/narr/advconfig.rst @@ -87,8 +87,8 @@ that ends something like this: Conflicting configuration actions For: ('view', None, '', None, <InterfaceClass pyramid.interfaces.IView>, None, None, None, None, None, False, None, None, None) - ('app.py', 14, '<module>', 'config.add_view(hello_world)') - ('app.py', 17, '<module>', 'config.add_view(hello_world)') + Line 14 of file app.py in <module>: 'config.add_view(hello_world)' + Line 17 of file app.py in <module>: 'config.add_view(goodbye_world)' This traceback is trying to tell us: @@ -115,6 +115,8 @@ Conflict detection happens for any kind of configuration: imperative configuration or configuration that results from the execution of a :term:`scan`. +.. _manually_resolving_conflicts: + Manually Resolving Conflicts ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -397,76 +399,3 @@ constraints: the routes they imply require relative ordering. Such ordering constraints are not absolved by two-phase configuration. Routes are still added in configuration execution order. -.. index:: - single: add_directive - pair: configurator; adding directives - -.. _add_directive: - -Adding Methods to the Configurator via ``add_directive`` --------------------------------------------------------- - -Framework extension writers can add arbitrary methods to a -:term:`Configurator` by using the -:meth:`pyramid.config.Configurator.add_directive` method of the configurator. -This makes it possible to extend a Pyramid configurator in arbitrary ways, -and allows it to perform application-specific tasks more succinctly. - -The :meth:`~pyramid.config.Configurator.add_directive` method accepts two -positional arguments: a method name and a callable object. The callable -object is usually a function that takes the configurator instance as its -first argument and accepts other arbitrary positional and keyword arguments. -For example: - -.. code-block:: python - :linenos: - - from pyramid.events import NewRequest - from pyramid.config import Configurator - - def add_newrequest_subscriber(config, subscriber): - config.add_subscriber(subscriber, NewRequest). - - if __name__ == '__main__': - config = Configurator() - config.add_directive('add_newrequest_subscriber', - add_newrequest_subscriber) - -Once :meth:`~pyramid.config.Configurator.add_directive` is called, a user can -then call the method by its given name as if it were a built-in method of the -Configurator: - -.. code-block:: python - :linenos: - - def mysubscriber(event): - print event.request - - config.add_newrequest_subscriber(mysubscriber) - -A call to :meth:`~pyramid.config.Configurator.add_directive` is often -"hidden" within an ``includeme`` function within a "frameworky" package meant -to be included as per :ref:`including_configuration` via -:meth:`~pyramid.config.Configurator.include`. For example, if you put this -code in a package named ``pyramid_subscriberhelpers``: - -.. code-block:: python - :linenos: - - def includeme(config) - config.add_directive('add_newrequest_subscriber', - add_newrequest_subscriber) - -The user of the add-on package ``pyramid_subscriberhelpers`` would then be -able to install it and subsequently do: - -.. code-block:: python - :linenos: - - def mysubscriber(event): - print event.request - - from pyramid.config import Configurator - config = Configurator() - config.include('pyramid_subscriberhelpers') - config.add_newrequest_subscriber(mysubscriber) diff --git a/docs/narr/extconfig.rst b/docs/narr/extconfig.rst new file mode 100644 index 000000000..856654377 --- /dev/null +++ b/docs/narr/extconfig.rst @@ -0,0 +1,366 @@ +.. index:: + single: extending configuration + +.. _extconfig_narr: + +Extending Pyramid Configuration +=============================== + +Pyramid allows you to extend its Configurator with custom directives. Custom +directives can use other directives, they can add a custom :term:`action`, +they can participate in :term:`conflict resolution`, and they can provide +some number of :term:`introspectable` objects. + +.. index:: + single: add_directive + pair: configurator; adding directives + +.. _add_directive: + +Adding Methods to the Configurator via ``add_directive`` +-------------------------------------------------------- + +Framework extension writers can add arbitrary methods to a +:term:`Configurator` by using the +:meth:`pyramid.config.Configurator.add_directive` method of the configurator. +Using :meth:`~pyramid.config.Configurator.add_directive` makes it possible to +extend a Pyramid configurator in arbitrary ways, and allows it to perform +application-specific tasks more succinctly. + +The :meth:`~pyramid.config.Configurator.add_directive` method accepts two +positional arguments: a method name and a callable object. The callable +object is usually a function that takes the configurator instance as its +first argument and accepts other arbitrary positional and keyword arguments. +For example: + +.. code-block:: python + :linenos: + + from pyramid.events import NewRequest + from pyramid.config import Configurator + + def add_newrequest_subscriber(config, subscriber): + config.add_subscriber(subscriber, NewRequest). + + if __name__ == '__main__': + config = Configurator() + config.add_directive('add_newrequest_subscriber', + add_newrequest_subscriber) + +Once :meth:`~pyramid.config.Configurator.add_directive` is called, a user can +then call the added directive by its given name as if it were a built-in +method of the Configurator: + +.. code-block:: python + :linenos: + + def mysubscriber(event): + print event.request + + config.add_newrequest_subscriber(mysubscriber) + +A call to :meth:`~pyramid.config.Configurator.add_directive` is often +"hidden" within an ``includeme`` function within a "frameworky" package meant +to be included as per :ref:`including_configuration` via +:meth:`~pyramid.config.Configurator.include`. For example, if you put this +code in a package named ``pyramid_subscriberhelpers``: + +.. code-block:: python + :linenos: + + def includeme(config) + config.add_directive('add_newrequest_subscriber', + add_newrequest_subscriber) + +The user of the add-on package ``pyramid_subscriberhelpers`` would then be +able to install it and subsequently do: + +.. code-block:: python + :linenos: + + def mysubscriber(event): + print event.request + + from pyramid.config import Configurator + config = Configurator() + config.include('pyramid_subscriberhelpers') + config.add_newrequest_subscriber(mysubscriber) + +Using ``config.action`` in a Directive +-------------------------------------- + +If a custom directive can't do its work exclusively in terms of existing +configurator methods (such as +:meth:`pyramid.config.Configurator.add_subscriber`, as above), the directive +may need to make use of the :meth:`pyramid.config.Configurator.action` +method. This method adds an entry to the list of "actions" that Pyramid will +attempt to process when :meth:`pyramid.config.Configurator.commit` is called. +An action is simply a dictionary that includes a :term:`discriminator`, +possibly a callback function, and possibly other metadata used by Pyramid's +action system. + +Here's an example directive which uses the "action" method: + +.. code-block:: python + :linenos: + + def add_jammyjam(config, jammyjam): + def register(): + config.registry.jammyjam = jammyjam + config.action('jammyjam', register) + + if __name__ == '__main__': + config = Configurator() + config.add_directive('add_jammyjam', add_jammyjam) + +Fancy, but what does it do? The action method accepts a number of arguments. +In the above directive named ``add_jammyjam``, we call +:meth:`~pyramid.config.Configurator.action` with two arguments: the string +``jammyjam`` is passed as the first argument named ``discriminator``, and the +closure function named ``register`` is passed as the second argument named +``callable``. + +When the :meth:`~pyramid.config.Configurator.action` method is called, it +appends an action to the list of pending configuration actions. All pending +actions with the same discriminator value are potentially in conflict with +one another (see :ref:`conflict_detection`). When the +:meth:`~pyramid.config.Configurator.commit` method of the Configurator is +called (either explicitly or as the result of calling +:meth:`~pyramid.config.Configurator.make_wsgi_app`), conflicting actions are +potentially automatically resolved as per +:ref:`automatic_conflict_resolution`. If a conflict cannot be automatically +resolved, a ConfigurationConflictError is raised and application startup is +prevented. + +In our above example, therefore, if a consumer of our ``add_jammyjam`` +directive did this: + +.. code-block:: python + :linenos: + + config.add_jammyjam('first') + config.add_jammyjam('second') + +When the action list was committed resulting from the set of calls above, our +user's application would not start, because the discriminators of the actions +generated by the two calls are in direct conflict. Automatic conflict +resolution cannot resolve the conflict (because no ``config.include`` is +involved), and the user provided no intermediate +:meth:`pyramid.config.Configurator.commit` call between the calls to +``add_jammyjam`` to ensure that the successive calls did not conflict with +each other. + +This demonstrates the purpose of the discriminator argument to the action +method: it's used to indicate a uniqueness constraint for an action. Two +actions with the same discriminator will conflict unless the conflict is +automatically or manually resolved. A discriminator can be any hashable +object, but it is generally a string or a tuple. *You use a discriminator to +declaratively ensure that the user doesn't provide ambiguous configuration +statements.* + +But let's imagine that a consumer of ``add_jammyjam`` used it in such a way +that no configuration conflicts are generated. + +.. code-block:: python + :linenos: + + config.add_jammyjam('first') + +What happens now? When the ``add_jammyjam`` method is called, an action is +appended to the pending actions list. When the pending configuration actions +are processed during :meth:`~pyramid.config.Configurator.commit`, and no +conflicts occur, the *callable* provided as the second argument to the +:meth:`~pyramid.config.Configurator.action` method within ``add_jammyjam`` is +called with no arguments. The callable in ``add_jammyjam`` is the +``register`` closure function. It simply sets the value +``config.registry.jammyjam`` to whatever the user passed in as the +``jammyjam`` argument to the ``add_jammyjam`` function. Therefore, the +result of the user's call to our directive will set the ``jammyjam`` +attribute of the registry to the string ``first``. *A callable is used by a +directive to defer the result of a user's call to the directive until +conflict detection has had a chance to do its job*. + +Other arguments exist to the :meth:`~pyramid.config.Configurator.action` +method, including ``args``, ``kw``, ``order``, and ``introspectables``. + +``args`` and ``kw`` exist as values, which, if passed, will be used as +arguments to the ``callable`` function when it is called back. For example +our directive might use them like so: + +.. code-block:: python + :linenos: + + def add_jammyjam(config, jammyjam): + def register(*arg, **kw): + config.registry.jammyjam_args = arg + config.registry.jammyjam_kw = kw + config.registry.jammyjam = jammyjam + config.action('jammyjam', register, args=('one',), kw={'two':'two'}) + +In the above example, when this directive is used to generate an action, and +that action is committed, ``config.registry.jammyjam_args`` will be set to +``('one',)`` and ``config.registry.jammyjam_kw`` will be set to +``{'two':'two'}``. ``args`` and ``kw`` are honestly not very useful when +your ``callable`` is a closure function, because you already usually have +access to every local in the directive without needing them to be passed +back. They can be useful, however, if you don't use a closure as a callable. + +``order`` is a crude order control mechanism. ``order`` defaults to the +integer ``0``; it can be set to any other integer. All actions that share an +order will be called before other actions that share a higher order. This +makes it possible to write a directive with callable logic that relies on the +execution of the callable of another directive being done first. For +example, Pyramid's :meth:`pyramid.config.Configurator.add_view` directive +registers an action with a higher order than the +:meth:`pyramid.config.Configurator.add_route` method. Due to this, the +``add_view`` method's callable can assume that, if a ``route_name`` was +passed to it, that a route by this name was already registered by +``add_route``, and if such a route has not already been registered, it's a +configuration error (a view that names a nonexistent route via its +``route_name`` parameter will never be called). + +``introspectables`` is a sequence of :term:`introspectable` objects. You can +pass a sequence of introspectables to the +:meth:`~pyramid.config.Configurator.action` method, which allows you to +augment Pyramid's configuration introspection system. + +.. _introspection: + +Configuration Introspection +--------------------------- + +.. warning:: + + The introspection subsystem is new in Pyramid 1.3. + +Pyramid provides a configuration introspection system that can be used by +debugging tools to provide visibility into the configuration of a running +application. + +All built-in Pyramid directives (such as +:meth:`pyramid.config.Configurator.add_view` and +:meth:`pyramid.config.Configurator.add_route`) register a set of +introspectables when called. For example, when you register a view via +``add_view``, the directive registers at least one introspectable: an +introspectable about the view registration itself, providing human-consumable +values for the arguments it was passed. You can later use the introspection +query system to determine whether a particular view uses a renderer, or +whether a particular view is limited to a particular request method, or which +routes a particular view is registered against. The Pyramid "debug toolbar" +makes use of the introspection system in various ways to display information +to Pyramid developers. + +Introspection values are set when a sequence of :term:`introspectable` +objects is passed to the :meth:`~pyramid.config.Configurator.action` method. +Here's an example of a directive which uses introspectables: + +.. code-block:: python + :linenos: + + def add_jammyjam(config, value): + def register(): + config.registry.jammyjam = value + intr = config.introspectable(category_name='jammyjams', + discriminator='jammyjam', + title='a jammyjam', + type_name=None) + intr['value'] = value + config.action('jammyjam', register, introspectables=(intr,)) + + if __name__ == '__main__': + config = Configurator() + config.add_directive('add_jammyjam', add_jammyjam) + +If you notice, the above directive uses the ``introspectable`` attribute of a +Configurator (:attr:`pyramid.config.Configurator.introspectable`) to create +an introspectable object. The introspectable object's constructor requires +at least four arguments: the ``category_name``, the ``discriminator``, the +``title``, and the ``type_name``. + +The ``category_name`` is a string representing the logical category for this +introspectable. Usually the category_name is a pluralization of the type of +object being added via the action. + +The ``discriminator`` is a value unique **within the category** (unlike the +action discriminator, which must be unique within the entire set of actions). +It is typically a string or tuple representing the values unique to this +introspectable within the category. It is used to generate links and as part +of a relationship-forming target for other introspectables. + +The ``title`` is a human-consumable string that can be used by introspection +system frontends to show a friendly summary of this introspectable. + +The ``type_name`` is a value that can be used to subtype this introspectable +within its category for for sorting and presentation purposes. It can be any +value. + +An introspectable is also dictionary-like. It can contain any set of +key/value pairs, typically related to the arguments passed to its related +directive. While the category_name, discriminator, title and type_name are +*metadata* about the introspectable, the values provided as key/value pairs +are the actual data provided by the introspectable. In the above example, we +set the ``value`` key to the value of the ``value`` argument passed to the +directive. + +Our directive above mutates the introspectable, and passes it in to the +``action`` method as the first element of a tuple as the value of the +``introspectable`` keyword argument. This associates this introspectable +with the action. Introspection tools will then display this introspectable +in their index. + +Introspectable Relationships +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Two introspectables may have relationships between each other. + +.. code-block:: python + :linenos: + + def add_jammyjam(config, value, template): + def register(): + config.registry.jammyjam = (value, template) + intr = config.introspectable(category_name='jammyjams', + discriminator='jammyjam', + title='a jammyjam', + type_name=None) + intr['value'] = value + tmpl_intr = config.introspectable(category_name='jammyjam templates', + discriminator=template, + title=template, + type_name=None) + tmpl_intr['value'] = template + intr.relate('jammyjam templates', template) + config.action('jammyjam', register, introspectables=(intr, tmpl_intr)) + + if __name__ == '__main__': + config = Configurator() + config.add_directive('add_jammyjam', add_jammyjam) + +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 +own introspectable, you can cause the same directive to register more than +one introspectable, registering one introspectable for the "main idea" and +another for a related concept. + +The call to ``intr.relate`` above +(:meth:`pyramid.interfaces.IIntrospectable.relate`) is passed two arguments: +a category name and a directive. The example above effectively indicates +that the directive wishes to form a relationship between the ``intr`` +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 to which it relates to and vice versa. diff --git a/docs/narr/introspector.rst b/docs/narr/introspector.rst new file mode 100644 index 000000000..cfc6144dd --- /dev/null +++ b/docs/narr/introspector.rst @@ -0,0 +1,542 @@ +.. index:: + single: introspection + single: introspector + +.. _using_introspection: + +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`. 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. + +.. warning:: + + Introspection is new in Pyramid 1.3. + +Using the Introspector +---------------------- + +Here's an example of using Pyramid's introspector from within a view +callable: + +.. code-block:: python + :linenos: + + from pyramid.view import view_config + from pyramid.response import Response + + @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['pattern'])) + +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 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. + +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`` + + 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. + +``action_info`` + + An object describing the directive call site which caused this + introspectable to be registered; contains attributes described in + :class:`pyramid.interfaces.IActionInfo`. + +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:`pyramid.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`` + + 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`` + + 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`` + + 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`` or the value ``None`` if a + ``request_method`` argument was not supplied. + + ``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`` + + 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`` + + 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`` or the value ``None`` if a + ``request_method`` argument was not supplied. + + ``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`` + + 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`` + + Each introspectable in the ``asset overrides`` category represents a call + to :meth:`pyramid.config.Configurator.override_asset`; each will have the + following data. + + ``to_override`` + + The ``to_override`` argument (an asset spec) passed to + ``override_asset``. + + ``override_with`` + + The ``override_with`` argument (an asset spec) passed to + ``override_asset``. + +``translation directories`` + + Each introspectable in the ``asset overrides`` category represents an + individual element in a ``specs`` argument passed to to + :meth:`pyramid.config.Configurator.add_translation_dirs`; each will have + the following data. + + ``directory`` + + The absolute path of the translation directory. + + ``spec`` + + The asset specification passed to ``add_translation_dirs``. + +``tweens`` + + Each introspectable in the ``tweens`` category represents a call to + :meth:`pyramid.config.Configurator.add_tween`; each will have the following + data. + + ``name`` + + The dotted name to the tween factory as a string (passed as + the ``tween_factory`` argument to ``add_tween``). + + ``factory`` + + The (resolved) tween factory object. + + ``type`` + + ``implict`` or ``explicit`` as a string. + + ``under`` + + The ``under`` argument passed to ``add_tween`` (a string). + + ``over`` + + The ``over`` argument passed to ``add_tween`` (a string). + +Introspection in the Toolbar +---------------------------- + +The Pyramid debug toolbar (part of the ``pyramid_debugtoolbar`` package) +provides a canned view of all registered introspectables and their +relationships. It looks something like this: + +.. image:: tb_introspector.png + +Disabling Introspection +----------------------- + +You can disable Pyramid introspection by passing the object +:attr:`pyramid.registry.noop_introspector` to the :term:`Configurator` +constructor in your application setup: + +.. code-block:: python + + from pyramid.config import Configurator + from pyramid.registry import noop_introspector + config = Configurator(..., introspector=noop_introspector) + +When the noop introspector is active, all introspectables generated by +configuration directives are thrown away. A noop introspector behaves just +like a "real" introspector, but the methods of a noop introspector do nothing +and return null values. diff --git a/docs/narr/tb_introspector.png b/docs/narr/tb_introspector.png Binary files differnew file mode 100644 index 000000000..231a094f7 --- /dev/null +++ b/docs/narr/tb_introspector.png |
