diff --git a/aspen/resources/simplate.py b/aspen/resources/simplate.py index 6a865bd47..01bfab17d 100644 --- a/aspen/resources/simplate.py +++ b/aspen/resources/simplate.py @@ -48,19 +48,15 @@ def __init__(self, *a, **kw): def respond(self, state): - state.update(self.pages[0]) - response = state.setdefault('response', Response(charset=self.website.charset_dynamic)) - spt_locals = {} + state.setdefault('response', Response(charset=self.website.charset_dynamic)) + spt_context = dict(state, **self.pages[0]) # copy the state dict to avoid accidentally + exec(self.pages[1], spt_context) # mutating it - exec(self.pages[1], state, spt_locals) + if '__all__' in spt_context: + # templates will only see variables named in __all__ + spt_context = dict([ (k, spt_context[k]) for k in spt_context['__all__'] ]) - # if __all__ is defined, only pass those local variables to templates - # if __all__ is not defined, pass all locals to templates - - if '__all__' in spt_locals: - spt_locals = dict([ (k, spt_locals[k]) for k in spt_locals['__all__'] ]) - - return self.get_response(state, spt_locals) + return self.get_response(state, spt_context) def parse_into_pages(self, raw, is_bound): @@ -148,7 +144,7 @@ def compile_page(self, page): return (renderer, media_type) # back to parent class - def get_response(self, state, spt_locals): + def get_response(self, state, spt_context): """Given two context dicts, return a response object. """ dispatch_result = state['dispatch_result'] @@ -170,7 +166,9 @@ def get_response(self, state, spt_locals): media_type = mimeparse.best_match(self.available_types, accept) except: # exception means don't override the defaults - log("Problem with mimeparse.best_match(%r, %r): %r " % (self.available_types, accept, sys.exc_info())) + log( "Problem with mimeparse.best_match(%r, %r): %r " + % (self.available_types, accept, sys.exc_info()) + ) else: if media_type == '': # breakdown in negotiations raise failure @@ -178,7 +176,7 @@ def get_response(self, state, spt_locals): render = self.renderers[media_type] # KeyError is a bug response = state['response'] - response.body = render(dict(state, **spt_locals)) + response.body = render(spt_context) if 'Content-Type' not in response.headers: response.headers['Content-Type'] = media_type if media_type.startswith('text/'): diff --git a/tests/test_simplates.py b/tests/test_simplates.py index 0e63883ea..18d3f7af3 100644 --- a/tests/test_simplates.py +++ b/tests/test_simplates.py @@ -78,3 +78,14 @@ def test_can_explicitly_override_state(harness): ) assert response.code == 299 assert response.body == 'bar' + + +def test_but_python_sections_exhibit_module_scoping_behavior(harness): + response = harness.simple(""" +bar = 'baz' +def foo(): + return bar +foo = foo() +[---] text/html via stdlib_format +{foo}""") + assert response.body == 'baz'