=== modified file 'twisted/web/_flatten.py'
|
|
|
|
| 179 | 179 | yield root.addCallback( |
| 180 | 180 | lambda result: (result, _flattenElement(request, result, slotData, |
| 181 | 181 | renderFactory, inAttribute))) |
| 182 | | elif IRenderable.providedBy(root): |
| 183 | | result = root.render(request) |
| 184 | | yield _flattenElement(request, result, slotData, root, inAttribute) |
| 185 | 182 | else: |
| 186 | | raise UnsupportedType(root) |
| | 183 | try: |
| | 184 | renderer = IRenderable(root) |
| | 185 | except TypeError: |
| | 186 | raise UnsupportedType(root) |
| | 187 | result = renderer.render(request) |
| | 188 | yield _flattenElement(request, result, slotData, renderer, inAttribute) |
| 187 | 189 | |
| 188 | 190 | |
| 189 | 191 | def _flattenTree(request, root): |
=== modified file 'twisted/web/test/test_flatten.py'
|
|
|
|
| 1 | | |
| 2 | 1 | # Copyright (c) Twisted Matrix Laboratories. |
| 3 | 2 | # See LICENSE for details. |
| 4 | 3 | |
| … |
… |
|
| 9 | 8 | |
| 10 | 9 | from twisted.trial.unittest import TestCase |
| 11 | 10 | from twisted.internet.defer import succeed, gatherResults |
| | 11 | from twisted.python import components |
| | 12 | from twisted.python.test.test_components import RegistryUsingMixin |
| 12 | 13 | from twisted.web._stan import Tag |
| 13 | 14 | from twisted.web._flatten import flattenString |
| 14 | 15 | from twisted.web.error import UnfilledSlot, UnsupportedType, FlattenerError |
| … |
… |
|
| 17 | 18 | from twisted.web.test._util import FlattenTestCase |
| 18 | 19 | |
| 19 | 20 | |
| | 21 | |
| | 22 | class FakeElement(object): |
| | 23 | """ |
| | 24 | A fake L{IRenderable} that returns a document with a specified |
| | 25 | hole, to test both parts of the L{IRenderable} interface. |
| | 26 | |
| | 27 | @type testcase: L{TestCase} |
| | 28 | @ivar testcase: the test case to which asserts should be directed |
| | 29 | """ |
| | 30 | |
| | 31 | implements(IRenderable) |
| | 32 | |
| | 33 | def __init__(self, testcase): |
| | 34 | self.testcae = testcase |
| | 35 | |
| | 36 | |
| | 37 | def render(self, req): |
| | 38 | """ |
| | 39 | Returns a document with holes to be filled by |
| | 40 | C{lookupRenderMethod}. |
| | 41 | |
| | 42 | @param req: (ignored) |
| | 43 | |
| | 44 | @return: a document |
| | 45 | """ |
| | 46 | return tags.p( |
| | 47 | 'hello, ', |
| | 48 | tags.transparent(render='test'), ' - ', |
| | 49 | tags.transparent(render='test')) |
| | 50 | |
| | 51 | |
| | 52 | def lookupRenderMethod(self, name): |
| | 53 | """ |
| | 54 | Returns a method to handle the hole C{test}, and asserts that the hole |
| | 55 | is in fact C{test}. |
| | 56 | |
| | 57 | @param name: the string C{"test"} |
| | 58 | @return: render method for C{test} hole |
| | 59 | """ |
| | 60 | self.testcase.assertEqual(name, 'test') |
| | 61 | return lambda ign, node: node('world') |
| | 62 | |
| | 63 | |
| | 64 | |
| 20 | 65 | class TestSerialization(FlattenTestCase): |
| 21 | 66 | """ |
| 22 | 67 | Tests for flattening various things. |
| … |
… |
|
| 163 | 208 | """ |
| 164 | 209 | Test that flattening respects all of the IRenderable interface. |
| 165 | 210 | """ |
| 166 | | class FakeElement(object): |
| 167 | | implements(IRenderable) |
| 168 | | def render(ign,ored): |
| 169 | | return tags.p( |
| 170 | | 'hello, ', |
| 171 | | tags.transparent(render='test'), ' - ', |
| 172 | | tags.transparent(render='test')) |
| 173 | | def lookupRenderMethod(ign, name): |
| 174 | | self.assertEqual(name, 'test') |
| 175 | | return lambda ign, node: node('world') |
| 176 | | |
| 177 | 211 | return gatherResults([ |
| 178 | | self.assertFlattensTo(FakeElement(), '<p>hello, world - world</p>'), |
| | 212 | self.assertFlattensTo(FakeElement(self), '<p>hello, world - world</p>'), |
| 179 | 213 | ]) |
| 180 | 214 | |
| 181 | 215 | |
| … |
… |
|
| 209 | 243 | return self.assertFlatteningRaises(None, UnsupportedType) |
| 210 | 244 | |
| 211 | 245 | |
| | 246 | |
| | 247 | class TestAdapterSerialization(RegistryUsingMixin, FlattenTestCase): |
| | 248 | """ |
| | 249 | Tests for flattening various things that use the global adapter registry. |
| | 250 | """ |
| | 251 | |
| | 252 | def test_serializeAdaptableRender(self): |
| | 253 | """ |
| | 254 | Tests that flattening an object adaptable to an L{IRenderable} uses |
| | 255 | the adapter. |
| | 256 | """ |
| | 257 | class FakeAdaptee(object): |
| | 258 | pass |
| | 259 | |
| | 260 | components.registerAdapter(lambda _: FakeElement(self), FakeAdaptee, IRenderable) |
| | 261 | |
| | 262 | return gatherResults([ |
| | 263 | self.assertFlattensTo(FakeAdaptee(), '<p>hello, world - world</p>'), |
| | 264 | ]) |
| | 265 | |
| | 266 | |
| | 267 | |
| | 268 | |
| 212 | 269 | # Use the co_filename mechanism (instead of the __file__ mechanism) because |
| 213 | 270 | # it is the mechanism traceback formatting uses. The two do not necessarily |
| 214 | 271 | # agree with each other. This requires a code object compiled in this file. |