summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGES.txt7
-rw-r--r--pyramid/config/views.py3
-rw-r--r--pyramid/interfaces.py3
-rw-r--r--pyramid/tests/test_config/test_views.py16
4 files changed, 28 insertions, 1 deletions
diff --git a/CHANGES.txt b/CHANGES.txt
index 9b10c0831..b7a8f4764 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -169,6 +169,13 @@ Bug Fixes
- Prevent "parameters to load are deprecated" ``DeprecationWarning``
from setuptools>=11.3. See https://github.com/Pylons/pyramid/pull/1541
+- Avoiding sharing the ``IRenderer`` objects across threads when attached to
+ a view using the `renderer=` argument. These renderers were instantiated
+ at time of first render and shared between requests, causing potentially
+ subtle effects like `pyramid.reload_templates = true` failing to work
+ in `pyramid_mako`. See https://github.com/Pylons/pyramid/pull/1575
+ and https://github.com/Pylons/pyramid/issues/1268
+
- Avoiding timing attacks against CSRF tokens.
See https://github.com/Pylons/pyramid/pull/1574
diff --git a/pyramid/config/views.py b/pyramid/config/views.py
index 24c592f7a..aba28467d 100644
--- a/pyramid/config/views.py
+++ b/pyramid/config/views.py
@@ -349,7 +349,6 @@ class ViewDeriver(object):
def _rendered_view(self, view, view_renderer):
def rendered_view(context, request):
- renderer = view_renderer
result = view(context, request)
if result.__class__ is Response: # potential common case
response = result
@@ -367,6 +366,8 @@ class ViewDeriver(object):
name=renderer_name,
package=self.kw.get('package'),
registry = registry)
+ else:
+ renderer = view_renderer.clone()
if '__view__' in attrs:
view_inst = attrs.pop('__view__')
else:
diff --git a/pyramid/interfaces.py b/pyramid/interfaces.py
index 4c171f9cc..bab91b0ee 100644
--- a/pyramid/interfaces.py
+++ b/pyramid/interfaces.py
@@ -382,6 +382,9 @@ class IRendererInfo(Interface):
settings = Attribute('The deployment settings dictionary related '
'to the current application')
+ def clone():
+ """ Return a shallow copy that does not share any mutable state."""
+
class IRendererFactory(Interface):
def __call__(info):
""" Return an object that implements
diff --git a/pyramid/tests/test_config/test_views.py b/pyramid/tests/test_config/test_views.py
index 36c86f78c..180050941 100644
--- a/pyramid/tests/test_config/test_views.py
+++ b/pyramid/tests/test_config/test_views.py
@@ -2548,6 +2548,8 @@ class TestViewDeriver(unittest.TestCase):
self.assertEqual(view_inst, view)
self.assertEqual(ctx, context)
return response
+ def clone(self):
+ return self
def view(request):
return 'OK'
deriver = self._makeOne(renderer=moo())
@@ -2585,6 +2587,8 @@ class TestViewDeriver(unittest.TestCase):
self.assertEqual(view_inst, 'view')
self.assertEqual(ctx, context)
return response
+ def clone(self):
+ return self
def view(request):
return 'OK'
deriver = self._makeOne(renderer=moo())
@@ -3179,6 +3183,8 @@ class TestViewDeriver(unittest.TestCase):
self.assertEqual(view_inst.__class__, View)
self.assertEqual(ctx, context)
return response
+ def clone(self):
+ return self
class View(object):
def __init__(self, context, request):
pass
@@ -3203,6 +3209,8 @@ class TestViewDeriver(unittest.TestCase):
self.assertEqual(view_inst.__class__, View)
self.assertEqual(ctx, context)
return response
+ def clone(self):
+ return self
class View(object):
def __init__(self, request):
pass
@@ -3227,6 +3235,8 @@ class TestViewDeriver(unittest.TestCase):
self.assertEqual(view_inst.__class__, View)
self.assertEqual(ctx, context)
return response
+ def clone(self):
+ return self
class View:
def __init__(self, context, request):
pass
@@ -3251,6 +3261,8 @@ class TestViewDeriver(unittest.TestCase):
self.assertEqual(view_inst.__class__, View)
self.assertEqual(ctx, context)
return response
+ def clone(self):
+ return self
class View:
def __init__(self, request):
pass
@@ -3275,6 +3287,8 @@ class TestViewDeriver(unittest.TestCase):
self.assertEqual(view_inst, view)
self.assertEqual(ctx, context)
return response
+ def clone(self):
+ return self
class View:
def index(self, context, request):
return {'a':'1'}
@@ -3297,6 +3311,8 @@ class TestViewDeriver(unittest.TestCase):
self.assertEqual(view_inst, view)
self.assertEqual(ctx, context)
return response
+ def clone(self):
+ return self
class View:
def index(self, request):
return {'a':'1'}