changeset 5663:87dae5077cae

make moin compatible to werkzeug 0.5 .. 0.6.2 (details below) The previous approach we had to avoid trouble because of mixing Request and Response was causing issues with xmlrpc and werkzeug 0.6.x. See: http://moinmo.in/MoinMoinBugs/1.9.2XMLRPCContext_object_has_no_attribute_in-data We inherit .stream now from Request base class and use a modified Response base class that has .out_stream (instead of .stream, which would collide). We don't use .in_stream because werkzeug base class code expects it to be .stream.
author Thomas Waldmann <tw AT waldmann-edv DOT de>
date Mon, 03 May 2010 23:48:41 +0200
parents 64d0629dd835
children 01978e51e524
files MoinMoin/web/contexts.py MoinMoin/web/request.py
diffstat 2 files changed, 27 insertions(+), 20 deletions(-) [+]
line wrap: on
line diff
--- a/MoinMoin/web/contexts.py	Sun May 02 19:29:59 2010 +0200
+++ b/MoinMoin/web/contexts.py	Mon May 03 23:48:41 2010 +0200
@@ -227,9 +227,9 @@
     def read(self, n=None):
         """ Read n bytes (or everything) from input stream. """
         if n is None:
-            return self.request.in_stream.read()
+            return self.request.stream.read()
         else:
-            return self.request.in_stream.read(n)
+            return self.request.stream.read(n)
 
     def makeForbidden(self, resultcode, msg):
         status = {401: Unauthorized,
--- a/MoinMoin/web/request.py	Sun May 02 19:29:59 2010 +0200
+++ b/MoinMoin/web/request.py	Mon May 03 23:48:41 2010 +0200
@@ -10,7 +10,9 @@
 from StringIO import StringIO
 
 from werkzeug import Request as RequestBase
-from werkzeug import Response as ResponseBase
+from werkzeug import BaseResponse, ETagResponseMixin, \
+                     CommonResponseDescriptorsMixin, WWWAuthenticateMixin
+from werkzeug.wrappers import ResponseStream
 from werkzeug import EnvironHeaders, Headers, HeaderSet
 from werkzeug import Href, create_environ, url_encode, cached_property
 from werkzeug import Client # used by tests
@@ -23,6 +25,24 @@
 class MoinMoinFinish(Exception):
     """ Raised to jump directly to end of run() function, where finish is called """
 
+class ModifiedResponseStreamMixin(object):
+    """
+    to avoid .stream attributes name collision when we mix together Request
+    and Response, we use "out_stream" instead of "stream" in the original
+    ResponseStreamMixin
+    """
+    @cached_property
+    def out_stream(self):
+        """The response iterable as write-only stream."""
+        return ResponseStream(self)
+
+class ResponseBase(BaseResponse, ETagResponseMixin, ModifiedResponseStreamMixin,
+                   CommonResponseDescriptorsMixin,
+                   WWWAuthenticateMixin):
+    """
+    similar to werkzeug.Response, but with ModifiedResponseStreamMixin
+    """
+
 class Request(ResponseBase, RequestBase):
     """ A full featured Request/Response object.
 
@@ -47,24 +67,11 @@
         self.response = []
         self.status_code = 200
 
-    # XXX ugly hack begin - works by sheer luck
+    # Note: we inherit a .stream attribute from RequestBase and this needs
+    # to refer to the input stream because inherited functionality of werkzeug
+    # base classes will access it as .stream.
+    # The output stream is .out_stream (see above).
     # TODO keep request and response separate, don't mix them together
-    stream = property() # protect inherited .stream attr from accessing
-
-    try:
-        # for werkzeug 0.6
-        in_stream = cached_property(RequestBase.stream.func, 'in_stream')
-    except AttributeError:
-        # no .func -> werkzeug 0.5
-        in_stream = RequestBase.stream
-
-    try:
-        # for werkzeug 0.6
-        out_stream = cached_property(ResponseBase.stream.func, 'out_stream')
-    except AttributeError:
-        # no .func -> werkzeug 0.5
-        out_stream = ResponseBase.stream
-    # XXX ugly hack end
 
     @cached_property
     def in_headers(self):