[Checkins] SVN: Zope/trunk/ Launchpad #363780: preserve interfaces and class of cloned request.

Tres Seaver tseaver at palladion.com
Sun Apr 19 16:41:20 EDT 2009


Log message for revision 99298:
  Launchpad #363780:  preserve interfaces and class of cloned request.
  
  o Preserve response class as well.
  

Changed:
  U   Zope/trunk/doc/CHANGES.rst
  U   Zope/trunk/src/ZPublisher/HTTPRequest.py
  U   Zope/trunk/src/ZPublisher/tests/testHTTPRequest.py

-=-
Modified: Zope/trunk/doc/CHANGES.rst
===================================================================
--- Zope/trunk/doc/CHANGES.rst	2009-04-19 20:31:16 UTC (rev 99297)
+++ Zope/trunk/doc/CHANGES.rst	2009-04-19 20:41:20 UTC (rev 99298)
@@ -27,6 +27,8 @@
 Bugs Fixed
 ++++++++++
 
+- Launchpad #363780:  preserve request interfaces and class, as well as
+  response class, when cloning an HTTPRequest.
 
 2.12.0a3 (2009-04-19)
 ---------------------

Modified: Zope/trunk/src/ZPublisher/HTTPRequest.py
===================================================================
--- Zope/trunk/src/ZPublisher/HTTPRequest.py	2009-04-19 20:31:16 UTC (rev 99297)
+++ Zope/trunk/src/ZPublisher/HTTPRequest.py	2009-04-19 20:41:20 UTC (rev 99298)
@@ -32,6 +32,8 @@
 
 from zope.i18n.interfaces import IUserPreferredLanguages
 from zope.i18n.locales import locales, LoadLocaleError
+from zope.interface import directlyProvidedBy
+from zope.interface import directlyProvides
 from zope.interface import implements
 from zope.publisher.base import DebugFlags
 from zope.publisher.interfaces.browser import IBrowserRequest
@@ -268,9 +270,7 @@
         if path[:vhbl] == vhbase:
             path = path[vhbl:]
         else:
-            raise ValueError, (
-                'Url does not match virtual hosting context'
-                )
+            raise ValueError('Url does not match virtual hosting context')
         vrpp = other.get('VirtualRootPhysicalPath', ('',))
         return list(vrpp) + map(unquote, path)
 
@@ -1150,7 +1150,7 @@
         # match that of the current request), a ValueError will
         # be raised.
         if url.find(self.script) != 0:
-            raise ValueError, 'Different namespace.'
+            raise ValueError('Different namespace.')
         path = url[len(self.script):]
         while path and path[0] == '/':
             path = path[1:]
@@ -1201,8 +1201,13 @@
         environ['REQUEST_METHOD'] = 'GET'
         if self._auth:
             environ['HTTP_AUTHORIZATION'] = self._auth
-        clone = HTTPRequest(None, environ, HTTPResponse(), clean=1)
+        if self.response is not None:
+            response = self.response.__class__()
+        else:
+            response = None
+        clone = self.__class__(None, environ, response, clean=1)
         clone['PARENTS'] = [self['PARENTS'][-1]]
+        directlyProvides(clone, *directlyProvidedBy(self))
         return clone
 
     def getHeader(self, name, default = None, literal = False):

Modified: Zope/trunk/src/ZPublisher/tests/testHTTPRequest.py
===================================================================
--- Zope/trunk/src/ZPublisher/tests/testHTTPRequest.py	2009-04-19 20:31:16 UTC (rev 99297)
+++ Zope/trunk/src/ZPublisher/tests/testHTTPRequest.py	2009-04-19 20:41:20 UTC (rev 99298)
@@ -921,6 +921,61 @@
         self.assertEqual(request.getHeader('Not-existant', default='Whatever'),
                          'Whatever')
 
+    def test_clone_updates_method_to_GET(self):
+        request = self._makeOne(environ={'REQUEST_METHOD': 'POST'})
+        request['PARENTS'] = [object()]
+        clone = request.clone()
+        self.assertEqual(clone.method, 'GET')
+
+    def test_clone_keeps_preserves__auth(self):
+        request = self._makeOne()
+        request['PARENTS'] = [object()]
+        request._auth = 'foobar'
+        clone = request.clone()
+        self.assertEqual(clone._auth, 'foobar')
+
+    def test_clone_doesnt_re_clean_environ(self):
+        request = self._makeOne()
+        request.environ['HTTP_CGI_AUTHORIZATION'] = 'lalalala'
+        request['PARENTS'] = [object()]
+        clone = request.clone()
+        self.assertEqual(clone.environ['HTTP_CGI_AUTHORIZATION'], 'lalalala')
+
+    def test_clone_keeps_only_last_PARENT(self):
+        PARENTS = [object(), object()]
+        request = self._makeOne()
+        request['PARENTS'] = PARENTS
+        clone = request.clone()
+        self.assertEqual(clone['PARENTS'], PARENTS[1:])
+
+    def test_clone_preserves_response_class(self):
+        class DummyResponse:
+            pass
+        request = self._makeOne(None, TEST_ENVIRON.copy(), DummyResponse())
+        request['PARENTS'] = [object()]
+        clone = request.clone()
+        self.failUnless(isinstance(clone.response, DummyResponse))
+
+    def test_clone_preserves_request_subclass(self):
+        class SubRequest(self._getTargetClass()):
+            pass
+        request = SubRequest(None, TEST_ENVIRON.copy(), None)
+        request['PARENTS'] = [object()]
+        clone = request.clone()
+        self.failUnless(isinstance(clone, SubRequest))
+
+    def test_clone_preserves_direct_interfaces(self):
+        from zope.interface import directlyProvides
+        from zope.interface import Interface
+        class IFoo(Interface):
+            pass
+        request = self._makeOne()
+        request['PARENTS'] = [object()]
+        directlyProvides(request, IFoo)
+        clone = request.clone()
+        self.failUnless(IFoo.providedBy(clone))
+
+
 TEST_ENVIRON = {
     'CONTENT_TYPE': 'multipart/form-data; boundary=12345',
     'REQUEST_METHOD': 'POST',



More information about the Checkins mailing list