1from pyramid.config import global_registries
2from pyramid.exceptions import ConfigurationError
3
4from pyramid.interfaces import (
5    IRequestFactory,
6    IRootFactory,
7    )
8from pyramid.request import Request
9from pyramid.request import apply_request_extensions
10
11from pyramid.threadlocal import manager as threadlocal_manager
12from pyramid.traversal import DefaultRootFactory
13
14def get_root(app, request=None):
15    """ Return a tuple composed of ``(root, closer)`` when provided a
16    :term:`router` instance as the ``app`` argument.  The ``root``
17    returned is the application root object.  The ``closer`` returned
18    is a callable (accepting no arguments) that should be called when
19    your scripting application is finished using the root.
20
21    ``request`` is passed to the :app:`Pyramid` application root
22    factory to compute the root. If ``request`` is None, a default
23    will be constructed using the registry's :term:`Request Factory`
24    via the :meth:`pyramid.interfaces.IRequestFactory.blank` method.
25    """
26    registry = app.registry
27    if request is None:
28        request = _make_request('/', registry)
29    threadlocals = {'registry':registry, 'request':request}
30    app.threadlocal_manager.push(threadlocals)
31    def closer(request=request): # keep request alive via this function default
32        app.threadlocal_manager.pop()
33    root = app.root_factory(request)
34    return root, closer
35
36def prepare(request=None, registry=None):
37    """ This function pushes data onto the Pyramid threadlocal stack
38    (request and registry), making those objects 'current'.  It
39    returns a dictionary useful for bootstrapping a Pyramid
40    application in a scripting environment.
41
42    ``request`` is passed to the :app:`Pyramid` application root
43    factory to compute the root. If ``request`` is None, a default
44    will be constructed using the registry's :term:`Request Factory`
45    via the :meth:`pyramid.interfaces.IRequestFactory.blank` method.
46
47    If ``registry`` is not supplied, the last registry loaded from
48    :attr:`pyramid.config.global_registries` will be used. If you
49    have loaded more than one :app:`Pyramid` application in the
50    current process, you may not want to use the last registry
51    loaded, thus you can search the ``global_registries`` and supply
52    the appropriate one based on your own criteria.
53
54    The function returns a dictionary composed of ``root``,
55    ``closer``, ``registry``, ``request`` and ``root_factory``.  The
56    ``root`` returned is the application's root resource object.  The
57    ``closer`` returned is a callable (accepting no arguments) that
58    should be called when your scripting application is finished
59    using the root.  ``registry`` is the registry object passed or
60    the last registry loaded into
61    :attr:`pyramid.config.global_registries` if no registry is passed.
62    ``request`` is the request object passed or the constructed request
63    if no request is passed.  ``root_factory`` is the root factory used
64    to construct the root.
65    """
66    if registry is None:
67        registry = getattr(request, 'registry', global_registries.last)
68    if registry is None:
69        raise ConfigurationError('No valid Pyramid applications could be '
70                                 'found, make sure one has been created '
71                                 'before trying to activate it.')
72    if request is None:
73        request = _make_request('/', registry)
74    # NB: even though _make_request might have already set registry on
75    # request, we reset it in case someone has passed in their own
76    # request.
77    request.registry = registry
78    threadlocals = {'registry':registry, 'request':request}
79    threadlocal_manager.push(threadlocals)
80    apply_request_extensions(request)
81    def closer():
82        threadlocal_manager.pop()
83    root_factory = registry.queryUtility(IRootFactory,
84                                         default=DefaultRootFactory)
85    root = root_factory(request)
86    if getattr(request, 'context', None) is None:
87        request.context = root
88    return {'root':root, 'closer':closer, 'registry':registry,
89            'request':request, 'root_factory':root_factory}
90
91def _make_request(path, registry=None):
92    """ Return a :meth:`pyramid.request.Request` object anchored at a
93    given path. The object returned will be generated from the supplied
94    registry's :term:`Request Factory` using the
95    :meth:`pyramid.interfaces.IRequestFactory.blank` method.
96
97    This request object can be passed to :meth:`pyramid.scripting.get_root`
98    or :meth:`pyramid.scripting.prepare` to initialize an application in
99    preparation for executing a script with a proper environment setup.
100    URLs can then be generated with the object, as well as rendering
101    templates.
102
103    If ``registry`` is not supplied, the last registry loaded from
104    :attr:`pyramid.config.global_registries` will be used. If you have
105    loaded more than one :app:`Pyramid` application in the current
106    process, you may not want to use the last registry loaded, thus
107    you can search the ``global_registries`` and supply the appropriate
108    one based on your own criteria.
109    """
110    if registry is None:
111        registry = global_registries.last
112    request_factory = registry.queryUtility(IRequestFactory, default=Request)
113    request = request_factory.blank(path)
114    request.registry = registry
115    return request
116