| | |
| | | =============================== |
| | | |
| | | 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. |
| | | 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 |
| | |
| | | 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. |
| | | 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: |
| | | 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: |
| | |
| | | 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: |
| | | then call the added directive by its given name as if it were a built-in method |
| | | of the Configurator: |
| | | |
| | | .. code-block:: python |
| | | :linenos: |
| | |
| | | |
| | | 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 |
| | | 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``: |
| | | |
| | |
| | | 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: |
| | | The user of the add-on package ``pyramid_subscriberhelpers`` would then be able |
| | | to install it and subsequently do: |
| | | |
| | | .. code-block:: python |
| | | :linenos: |
| | |
| | | |
| | | 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. |
| | | :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: |
| | | |
| | |
| | | |
| | | 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 |
| | | 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 :exc:`pyramid.exceptions.ConfigurationConflictError` is raised |
| | | and application startup is prevented. |
| | | potentially automatically resolved as per :ref:`automatic_conflict_resolution`. |
| | | If a conflict cannot be automatically resolved, a |
| | | :exc:`pyramid.exceptions.ConfigurationConflictError` is raised and application |
| | | startup is prevented. |
| | | |
| | | In our above example, therefore, if a consumer of our ``add_jammyjam`` |
| | | directive did this: |
| | |
| | | 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. |
| | | ``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 |
| | | 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.* |
| | | |
| | |
| | | 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*. |
| | | 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``. |
| | | 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: |
| | | ``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: |
| | |
| | | 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. |
| | | ``{'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 |
| | | 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). |
| | | ``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. |
| | | :meth:`~pyramid.config.Configurator.action` method, which allows you to augment |
| | | Pyramid's configuration introspection system. |
| | | |
| | | .. _introspection: |
| | | |
| | |
| | | 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. |
| | | values for the arguments passed into it. 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 against which |
| | | routes a particular view is registered. 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: |
| | | 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: |
| | |
| | | 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 |
| | | 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 |
| | |
| | | within its category 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 |
| | | 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`` keyword argument. This associates this introspectable with |
| | | the action. Introspection tools will then display this introspectable in their |
| | | index. |
| | | |
| | | Introspectable Relationships |
| | | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| | |
| | | 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. |
| | | introspectables: the first is related to the ``value`` passed to the directive, |
| | | and 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. |
| | | (: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. |
| | | 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. |
| | | 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 and vice versa. |