ВУЗ: Не указан

Категория: Не указан

Дисциплина: Не указана

Добавлен: 02.01.2026

Просмотров: 2775

Скачиваний: 0

ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.

29. USING HOOKS

29.13 Registering “Tweens”

latex-note.png

Tweens are a feature which were added in Pyramid 1.2. They are not available in any previous version.

A tween (a contraction of the word “between”) is a bit of code that sits between the Pyramid router’s main request handling function and the upstream WSGI component that uses Pyramid as its “app”. This is a feature that may be used by Pyramid framework extensions, to provide, for example, Pyramid-specific view timing support bookkeeping code that examines exceptions before they are returned to the upstream WSGI application. Tweens behave a bit like WSGI middleware but they have the benefit of running in a context in which they have access to the Pyramid application registry as well as the Pyramid rendering machinery.

29.13.1 Creating a Tween Factory

To make use of tweens, you must construct a “tween factory”. A tween factory must be a globally importable callable which accepts two arguments: handler and registry. handler will be the either the main Pyramid request handling function or another tween. registry will be the Pyramid application registry represented by this Configurator. A tween factory must return a tween when it is called.

A tween is a callable which accepts a request object and returns a response object.

Here’s an example of a tween factory:

1

2

3

4

5

6

7

8

9

# in a module named myapp.tweens

import time

from pyramid.settings import asbool import logging

log = logging.getLogger(__name__)

def timing_tween_factory(handler, registry):

334

29.13. REGISTERING “TWEENS”

10if asbool(registry.settings.get(’do_timing’)):

11# if timing support is enabled, return a wrapper

12def timing_tween(request):

13

start = time.time()

14

try:

15

response = handler(request)

16

finally:

17

end = time.time()

18

log.debug(’The request took %s seconds’ %

19

(end - start))

20

return response

21return timing_tween

22# if timing support is not enabled, return the original

23# handler

24return handler

If you remember, a tween is an object which accepts a request object and which returns a response argument. The request argument to a tween will be the request created by Pyramid’s router when it receives a WSGI request. The response object will be generated by the downstream Pyramid application and it should be returned by the tween.

In the above example, the tween factory defines a timing_tween tween and returns it if asbool(registry.settings.get(’do_timing’)) is true. It otherwise simply returns the handler it was given. The registry.settings attribute is a handle to the deployment settings provided by the user (usually in an .ini file). In this case, if the user has defined a do_timing setting, and that setting is True, the user has said she wants to do timing, so the tween factory returns the timing tween; it otherwise just returns the handler it has been provided, preventing any timing.

The example timing tween simply records the start time, calls the downstream handler, logs the number of seconds consumed by the downstream handler, and returns the response.

29.13.2 Registering an Implicit Tween Factory

Once you’ve created a tween factory, you can register it into the implicit tween chain using the pyramid.config.Configurator.add_tween() method using its dotted Python name.

Here’s an example of registering the a tween factory as an “implicit” tween in a Pyramid application:

1

2

3

from pyramid.config import Configurator config = Configurator()

config.add_tween(’myapp.tweens.timing_tween_factory’)

335


29. USING HOOKS

Note that you must use a dotted Python name as the first argument to pyramid.config.Configurator.add_tween(); this must point at a tween factory. You cannot pass the tween factory object itself to the method: it must be dotted Python name that points to a globally importable object. In the above example, we assume that a timing_tween_factory tween factory was defined in a module named myapp.tweens, so the tween factory is importable as myapp.tweens.timing_tween_factory.

When you use pyramid.config.Configurator.add_tween(), you’re instructing the system to use your tween factory at startup time unless the user has provided an explicit tween list in his configuration. This is what’s meant by an “implicit” tween. A user can always elect to supply an explicit tween list, reordering or disincluding implicitly added tweens. See Explicit Tween Ordering for more information about explicit tween ordering.

If more than one call to pyramid.config.Configurator.add_tween() is made within a single application configuration, the tweens will be chained together at application startup time. The first tween factory added via add_tween will be called with the Pyramid exception view tween factory as its handler argument, then the tween factory added directly after that one will be called with the result of the first tween factory as its handler argument, and so on, ad infinitum until all tween factories have been called. The Pyramid router will use the outermost tween produced by this chain (the tween generated by the very last tween factory added) as its request handler function. For example:

1

2

3

4

5

from pyramid.config import Configurator

config = Configurator() config.add_tween(’myapp.tween_factory1’) config.add_tween(’myapp.tween_factory2’)

The above example will generate an implicit tween chain that looks like this:

INGRESS (implicit) myapp.tween_factory2 myapp.tween_factory1

pyramid.tweens.excview_tween_factory (implicit) MAIN (implicit)

29.13.3 Suggesting Implicit Tween Ordering

By default, as described above, the ordering of the chain is controlled entirely by the relative ordering of calls to pyramid.config.Configurator.add_tween(). However, the caller of add_tween can provide an optional hint that can influence the implicit tween chain ordering by supplying under or over (or both) arguments to add_tween(). These hints are only used used when an explicit tween

336

29.13. REGISTERING “TWEENS”

ordering is not used. See Explicit Tween Ordering for a description of how to set an explicit tween ordering.

Allowable values for under or over (or both) are:

None (the default).

A dotted Python name to a tween factory: a string representing the predicted dotted name of a tween factory added in a call to add_tween in the same configuration session.

One of the constants pyramid.tweens.MAIN, pyramid.tweens.INGRESS, or pyramid.tweens.EXCVIEW.

An iterable of any combination of the above. This allows the user to specify fallbacks if the desired tween is not included, as well as compatibility with multiple other tweens.

Effectively, under means “closer to the main Pyramid application than”, over means “closer to the request ingress than”.

For example, the following call to add_tween() will attempt to place the tween factory represented by myapp.tween_factory directly ‘above’ (in ptweens order) the main Pyramid request handler.

1

2

3

import pyramid.tweens

config.add_tween(’myapp.tween_factory’, over=pyramid.tweens.MAIN)

The above example will generate an implicit tween chain that looks like this:

INGRESS (implicit) pyramid.tweens.excview_tween_factory (implicit) myapp.tween_factory

MAIN (implicit)

Likewise, calling the following call to add_tween() will attempt to place this tween factory ‘above’ the main handler but ‘below’ a separately added tween factory:

1

2

3

4

5

6

7

import pyramid.tweens

config.add_tween(’myapp.tween_factory1’, over=pyramid.tweens.MAIN)

config.add_tween(’myapp.tween_factory2’, over=pyramid.tweens.MAIN, under=’myapp.tween_factory1’)

The above example will generate an implicit tween chain that looks like this:

337



29. USING HOOKS

INGRESS (implicit) pyramid.tweens.excview_tween_factory (implicit) myapp.tween_factory1

myapp.tween_factory2 MAIN (implicit)

Specifying neither over nor under is equivalent to specifying under=INGRESS.

If all options for under (or over) cannot be found in the current configuration, it is an error. If some options are specified purely for compatibilty with other tweens, just add a fallback of MAIN or INGRESS. For example, under=(’someothertween’, ’someothertween2’, INGRESS). This constraint will require the tween to be located under both the ‘someothertween’ tween, the ‘someothertween2’ tween, and INGRESS. If any of these is not in the current configuration, this constraint will only organize itself based on the tweens that are present.

29.13.4 Explicit Tween Ordering

Implicit tween ordering is obviously only best-effort. Pyramid will attempt to provide an implicit order of tweens as best it can using hints provided by calls to add_tween(), but because it’s only best-effort, if very precise tween ordering is required, the only surefire way to get it is to use an explicit tween order. The deploying user can override the implicit tween inclusion and ordering implied by calls to add_tween() entirely by using the pyramid.tweens settings value. When used, this settings value must be a list of Python dotted names which will override the ordering (and inclusion) of tween factories in the implicit tween chain. For example:

1

[app:main]

2

use = egg:MyApp

3

pyramid.reload_templates = true

4

pyramid.debug_authorization = false

5

pyramid.debug_notfound = false

6

pyramid.debug_routematch = false

7

pyramid.debug_templates = true

8

pyramid.tweens = myapp.my_cool_tween_factory

9

pyramid.tweens.excview_tween_factory

 

 

In the above configuration, calls made during configuration to pyramid.config.Configurator.add_tween() are ignored, and the user is telling the system to use the tween factories he has listed in the pyramid.tweens configuration setting (each is a dotted Python name which points to a tween factory) instead of any tween factories added via pyramid.config.Configurator.add_tween(). The first tween factory in the

338


29.13. REGISTERING “TWEENS”

pyramid.tweens list will be used as the producer of the effective Pyramid request handling function; it will wrap the tween factory declared directly “below” it, ad infinitum. The “main” Pyramid request handler is implicit, and always “at the bottom”.

latex-note.png

Pyramid’s own exception view handling logic is implemented as a tween factory function: pyramid.tweens.excview_tween_factory(). If Pyramid exception view handling is desired, and tween factories are specified via the pyramid.tweens configuration setting, the pyramid.tweens.excview_tween_factory() function must be added to the pyramid.tweens configuration setting list explicitly. If it is not present, Pyramid will not perform exception view handling.

29.13.5 Tween Conflicts and Ordering Cycles

Pyramid will prevent the same tween factory from being added to the tween chain more than once using configuration conflict detection. If you wish to add the same tween factory more than once in a configuration, you should either: a) use a tween factory that is a separate globally importable instance object from the factory that it conflicts with b) use a function or class as a tween factory with the same logic as the other tween factory it conflicts with but with a different

__name__ attribute or c) call pyramid.config.Configurator.commit() between calls to pyramid.config.Configurator.add_tween().

If a cycle is detected in implicit tween ordering when over and under are used in any call to “add_tween”, an exception will be raised at startup time.

29.13.6 Displaying Tween Ordering

The ptweens command-line utility can be used to report the current implict and explicit tween chains used by an application. See Displaying “Tweens”.

339

29. USING HOOKS

340