diff --git a/src/allmydata/test/common_nevow.py b/src/allmydata/test/common_nevow.py new file mode 100644 index 000000000..dcf4dc095 --- /dev/null +++ b/src/allmydata/test/common_nevow.py @@ -0,0 +1,46 @@ +""" +General helpers related to Nevow. +""" + +from nevow.context import WebContext +from nevow.testutil import FakeRequest +from nevow.appserver import ( + processingFailed, + DefaultExceptionHandler, +) +from nevow.inevow import ( + ICanHandleException, + IRequest, + IResource as INevowResource, + IData, +) + +def render(resource, query_args): + """ + Render (in the manner of the Nevow appserver) a Nevow ``Page`` or a + Twisted ``Resource`` against a request with the given query arguments . + + :param resource: The page or resource to render. + + :param query_args: The query arguments to put into the request being + rendered. A mapping from ``bytes`` to ``list`` of ``bytes``. + + :return Deferred: A Deferred that fires with the rendered response body as + ``bytes``. + """ + ctx = WebContext(tag=resource) + req = FakeRequest(args=query_args) + ctx.remember(DefaultExceptionHandler(), ICanHandleException) + ctx.remember(req, IRequest) + ctx.remember(None, IData) + + def maybe_concat(res): + if isinstance(res, bytes): + return req.v + res + return req.v + + resource = INevowResource(resource) + d = maybeDeferred(resource.renderHTTP, ctx) + d.addErrback(processingFailed, req, ctx) + d.addCallback(maybe_concat) + return d diff --git a/src/allmydata/test/common_tweb.py b/src/allmydata/test/common_tweb.py new file mode 100644 index 000000000..2af9d4f53 --- /dev/null +++ b/src/allmydata/test/common_tweb.py @@ -0,0 +1,54 @@ +from zope.interface import ( + classImplements, +) +from twisted.python.reflect import ( + fullyQualifiedName, +) +from twisted.internet.defer import ( + succeed, +) +from twisted.web.test.requesthelper import ( + DummyRequest, +) +from twisted.web.iweb import ( + IRequest, +) +from twisted.web.server import ( + NOT_DONE_YET, +) + +classImplements(DummyRequest, IRequest) + +def render(resource, query_args): + """ + Render (in the manner of the Twisted Web Site) a Twisted ``Resource`` + against a request with the given query arguments . + + :param resource: The page or resource to render. + + :param query_args: The query arguments to put into the request being + rendered. A mapping from ``bytes`` to ``list`` of ``bytes``. + + :return Deferred: A Deferred that fires with the rendered response body as + ``bytes``. + """ + request = DummyRequest([]) + request.args = query_args + result = resource.render(request) + if isinstance(result, bytes): + request.write(result) + done = succeed(None) + elif result == NOT_DONE_YET: + if request.finished: + done = succeed(None) + else: + done = request.notifyFinish() + else: + raise ValueError( + "{!r} returned {!r}, required bytes or NOT_DONE_YET.".format( + fullyQualifiedName(resource.render), + result, + ), + ) + done.addCallback(lambda ignored: b"".join(request.written)) + return done diff --git a/src/allmydata/test/common_web.py b/src/allmydata/test/common_web.py index e2ea57539..829eef153 100644 --- a/src/allmydata/test/common_web.py +++ b/src/allmydata/test/common_web.py @@ -1,3 +1,4 @@ +from future.utils import PY2 import treq from twisted.internet.defer import ( @@ -7,19 +8,6 @@ from twisted.internet.defer import ( ) from twisted.web.error import Error -from nevow.context import WebContext -from nevow.testutil import FakeRequest -from nevow.appserver import ( - processingFailed, - DefaultExceptionHandler, -) -from nevow.inevow import ( - ICanHandleException, - IRequest, - IResource as INevowResource, - IData, -) - @inlineCallbacks def do_http(method, url, **kwargs): response = yield treq.request(method, url, persistent=False, **kwargs) @@ -31,32 +19,16 @@ def do_http(method, url, **kwargs): returnValue(body) -def render(resource, query_args): - """ - Render (in the manner of the Nevow appserver) a Nevow ``Page`` or a - Twisted ``Resource`` against a request with the given query arguments . - - :param resource: The page or resource to render. - - :param query_args: The query arguments to put into the request being - rendered. A mapping from ``bytes`` to ``list`` of ``bytes``. - - :return Deferred: A Deferred that fires with the rendered response body as - ``bytes``. - """ - ctx = WebContext(tag=resource) - req = FakeRequest(args=query_args) - ctx.remember(DefaultExceptionHandler(), ICanHandleException) - ctx.remember(req, IRequest) - ctx.remember(None, IData) - - def maybe_concat(res): - if isinstance(res, bytes): - return req.v + res - return req.v - - resource = INevowResource(resource) - d = maybeDeferred(resource.renderHTTP, ctx) - d.addErrback(processingFailed, req, ctx) - d.addCallback(maybe_concat) - return d +if PY2: + # We can only use Nevow on Python 2 and Tahoe-LAFS still *does* use Nevow + # so prefer the Nevow-based renderer if we can get it. + from .common_nevow import ( + render, + ) +else: + # However, Tahoe-LAFS *will* use Twisted Web before too much longer so go + # ahead and let some tests run against the Twisted Web-based renderer on + # Python 3. Later this will become the only codepath. + from .common_tweb import ( + render, + )