Skip to content

Commit

Permalink
allow prepare/bootstrap to be used as a context manager
Browse files Browse the repository at this point in the history
closes #1822
  • Loading branch information
mmerickel committed Sep 4, 2016
1 parent 44e0fca commit b36dd80
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 5 deletions.
14 changes: 14 additions & 0 deletions pyramid/paster.py
Original file line number Diff line number Diff line change
Expand Up @@ -129,8 +129,22 @@ def bootstrap(config_uri, request=None, options=None):
{'http_port': 8080} and then use %(http_port)s in the
config file.
This function may be used as a context manager to call the ``closer``
automatically:
.. code-block:: python
with bootstrap('development.ini') as env:
request = env['request']
# ...
See :ref:`writing_a_script` for more information about how to use this
function.
.. versionchanged:: 1.8
Added the ability to use the return value as a context manager.
"""
app = get_app(config_uri, options=options)
env = prepare(request)
Expand Down
35 changes: 30 additions & 5 deletions pyramid/scripting.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,12 +56,25 @@ def prepare(request=None, registry=None):
``root`` returned is the application's root resource object. The
``closer`` returned is a callable (accepting no arguments) that
should be called when your scripting application is finished
using the root. ``registry`` is the registry object passed or
the last registry loaded into
:attr:`pyramid.config.global_registries` if no registry is passed.
using the root. ``registry`` is the resolved registry object.
``request`` is the request object passed or the constructed request
if no request is passed. ``root_factory`` is the root factory used
to construct the root.
This function may be used as a context manager to call the ``closer``
automatically:
.. code-block:: python
registry = config.registry
with prepare(registry) as env:
request = env['request']
# ...
.. versionchanged:: 1.8
Added the ability to use the return value as a context manager.
"""
if registry is None:
registry = getattr(request, 'registry', global_registries.last)
Expand All @@ -85,8 +98,20 @@ def closer():
root = root_factory(request)
if getattr(request, 'context', None) is None:
request.context = root
return {'root':root, 'closer':closer, 'registry':registry,
'request':request, 'root_factory':root_factory}
return AppEnvironment(
root=root,
closer=closer,
registry=registry,
request=request,
root_factory=root_factory,
)

class AppEnvironment(dict):
def __enter__(self):
return self

def __exit__(self, type, value, traceback):
self['closer']()

def _make_request(path, registry=None):
""" Return a :meth:`pyramid.request.Request` object anchored at a
Expand Down
21 changes: 21 additions & 0 deletions pyramid/tests/test_scripting.py
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,27 @@ def test_it_with_extensions(self):
root, closer = info['root'], info['closer']
closer()

def test_it_is_a_context_manager(self):
request = DummyRequest({})
registry = request.registry = self._makeRegistry()
closer_called = [False]
with self._callFUT(request=request) as info:
root, request = info['root'], info['request']
pushed = self.manager.get()
self.assertEqual(pushed['request'], request)
self.assertEqual(pushed['registry'], registry)
self.assertEqual(pushed['request'].registry, registry)
self.assertEqual(root.a, (request,))
orig_closer = info['closer']
def closer():
orig_closer()
closer_called[0] = True
info['closer'] = closer
self.assertTrue(closer_called[0])
self.assertEqual(self.default, self.manager.get())
self.assertEqual(request.context, root)
self.assertEqual(request.registry, registry)

class Test__make_request(unittest.TestCase):
def _callFUT(self, path='/', registry=None):
from pyramid.scripting import _make_request
Expand Down

0 comments on commit b36dd80

Please sign in to comment.