Michael Merickel
2018-10-15 bda1306749c62ef4f11cfe567ed7d56c8ad94240
commit | author | age
31c20b 1 from pyramid.config import global_registries
8ac4c9 2 from pyramid.exceptions import ConfigurationError
0c1c39 3
0c29cf 4 from pyramid.interfaces import IRequestFactory, IRootFactory
04cc91 5 from pyramid.request import Request
MM 6 from pyramid.request import apply_request_extensions
0c1c39 7
e49227 8 from pyramid.threadlocal import RequestContext
359906 9 from pyramid.traversal import DefaultRootFactory
0c29cf 10
98ea38 11
CM 12 def get_root(app, request=None):
82fefc 13     """ Return a tuple composed of ``(root, closer)`` when provided a
83df8b 14     :term:`router` instance as the ``app`` argument.  The ``root``
CM 15     returned is the application root object.  The ``closer`` returned
16     is a callable (accepting no arguments) that should be called when
31c20b 17     your scripting application is finished using the root.
MM 18
8ac4c9 19     ``request`` is passed to the :app:`Pyramid` application root
MM 20     factory to compute the root. If ``request`` is None, a default
21     will be constructed using the registry's :term:`Request Factory`
22     via the :meth:`pyramid.interfaces.IRequestFactory.blank` method.
23     """
54376a 24     registry = app.registry
6fec21 25     if request is None:
8ac4c9 26         request = _make_request('/', registry)
e49227 27     request.registry = registry
MM 28     ctx = RequestContext(request)
29     ctx.begin()
0c29cf 30
e49227 31     def closer():
MM 32         ctx.end()
0c29cf 33
98ea38 34     root = app.root_factory(request)
359906 35     return root, closer
0c29cf 36
359906 37
c515d7 38 def prepare(request=None, registry=None):
8ac4c9 39     """ This function pushes data onto the Pyramid threadlocal stack
MM 40     (request and registry), making those objects 'current'.  It
41     returns a dictionary useful for bootstrapping a Pyramid
42     application in a scripting environment.
359906 43
8ac4c9 44     ``request`` is passed to the :app:`Pyramid` application root
MM 45     factory to compute the root. If ``request`` is None, a default
46     will be constructed using the registry's :term:`Request Factory`
47     via the :meth:`pyramid.interfaces.IRequestFactory.blank` method.
359906 48
MM 49     If ``registry`` is not supplied, the last registry loaded from
8ac4c9 50     :attr:`pyramid.config.global_registries` will be used. If you
MM 51     have loaded more than one :app:`Pyramid` application in the
52     current process, you may not want to use the last registry
53     loaded, thus you can search the ``global_registries`` and supply
54     the appropriate one based on your own criteria.
c515d7 55
8ac4c9 56     The function returns a dictionary composed of ``root``,
MM 57     ``closer``, ``registry``, ``request`` and ``root_factory``.  The
58     ``root`` returned is the application's root resource object.  The
59     ``closer`` returned is a callable (accepting no arguments) that
60     should be called when your scripting application is finished
b36dd8 61     using the root.  ``registry`` is the resolved registry object.
8ac4c9 62     ``request`` is the request object passed or the constructed request
MM 63     if no request is passed.  ``root_factory`` is the root factory used
64     to construct the root.
b36dd8 65
MM 66     This function may be used as a context manager to call the ``closer``
67     automatically:
68
69     .. code-block:: python
70
71        registry = config.registry
72        with prepare(registry) as env:
73            request = env['request']
74            # ...
75
76     .. versionchanged:: 1.8
77
78        Added the ability to use the return value as a context manager.
79
359906 80     """
MM 81     if registry is None:
82         registry = getattr(request, 'registry', global_registries.last)
8ac4c9 83     if registry is None:
0c29cf 84         raise ConfigurationError(
MM 85             'No valid Pyramid applications could be '
86             'found, make sure one has been created '
87             'before trying to activate it.'
88         )
359906 89     if request is None:
8ac4c9 90         request = _make_request('/', registry)
d6fb00 91     # NB: even though _make_request might have already set registry on
CM 92     # request, we reset it in case someone has passed in their own
93     # request.
e49227 94     request.registry = registry
MM 95     ctx = RequestContext(request)
96     ctx.begin()
04cc91 97     apply_request_extensions(request)
0c29cf 98
c515d7 99     def closer():
e49227 100         ctx.end()
0c29cf 101
MM 102     root_factory = registry.queryUtility(
103         IRootFactory, default=DefaultRootFactory
104     )
359906 105     root = root_factory(request)
5d0859 106     if getattr(request, 'context', None) is None:
CM 107         request.context = root
b36dd8 108     return AppEnvironment(
MM 109         root=root,
110         closer=closer,
111         registry=registry,
112         request=request,
113         root_factory=root_factory,
114     )
115
0c29cf 116
b36dd8 117 class AppEnvironment(dict):
MM 118     def __enter__(self):
119         return self
120
121     def __exit__(self, type, value, traceback):
122         self['closer']()
82fefc 123
0c29cf 124
8ac4c9 125 def _make_request(path, registry=None):
31c20b 126     """ Return a :meth:`pyramid.request.Request` object anchored at a
a02407 127     given path. The object returned will be generated from the supplied
31c20b 128     registry's :term:`Request Factory` using the
MM 129     :meth:`pyramid.interfaces.IRequestFactory.blank` method.
130
8ac4c9 131     This request object can be passed to :meth:`pyramid.scripting.get_root`
MM 132     or :meth:`pyramid.scripting.prepare` to initialize an application in
31c20b 133     preparation for executing a script with a proper environment setup.
MM 134     URLs can then be generated with the object, as well as rendering
135     templates.
136
137     If ``registry`` is not supplied, the last registry loaded from
37e3be 138     :attr:`pyramid.config.global_registries` will be used. If you have
31c20b 139     loaded more than one :app:`Pyramid` application in the current
MM 140     process, you may not want to use the last registry loaded, thus
141     you can search the ``global_registries`` and supply the appropriate
142     one based on your own criteria.
143     """
144     if registry is None:
145         registry = global_registries.last
146     request_factory = registry.queryUtility(IRequestFactory, default=Request)
a02407 147     request = request_factory.blank(path)
31c20b 148     request.registry = registry
MM 149     return request