[Checkins] SVN: zope.publisher/branches/py3-attempt2/src/zope/publisher/ test_browserrequest passes

Andrey Lebedev cvs-admin at zope.org
Wed Feb 20 14:17:14 UTC 2013


Log message for revision 129538:
  test_browserrequest passes
  
  

Changed:
  U   zope.publisher/branches/py3-attempt2/src/zope/publisher/_compat.py
  U   zope.publisher/branches/py3-attempt2/src/zope/publisher/browser.py
  U   zope.publisher/branches/py3-attempt2/src/zope/publisher/http.py
  U   zope.publisher/branches/py3-attempt2/src/zope/publisher/publish.py
  U   zope.publisher/branches/py3-attempt2/src/zope/publisher/tests/test_browserrequest.py
  U   zope.publisher/branches/py3-attempt2/src/zope/publisher/tests/test_http.py

-=-
Modified: zope.publisher/branches/py3-attempt2/src/zope/publisher/_compat.py
===================================================================
--- zope.publisher/branches/py3-attempt2/src/zope/publisher/_compat.py	2013-02-20 14:15:24 UTC (rev 129537)
+++ zope.publisher/branches/py3-attempt2/src/zope/publisher/_compat.py	2013-02-20 14:17:14 UTC (rev 129538)
@@ -25,7 +25,10 @@
 if PYTHON2:
     _u = unicode
     from xmlrpclib import *
+    import types
+    CLASS_TYPES = (type, types.ClassType)
 else:
     _u = str
+    CLASS_TYPES = (type,)
     from xmlrpc.client import *
 

Modified: zope.publisher/branches/py3-attempt2/src/zope/publisher/browser.py
===================================================================
--- zope.publisher/branches/py3-attempt2/src/zope/publisher/browser.py	2013-02-20 14:15:24 UTC (rev 129537)
+++ zope.publisher/branches/py3-attempt2/src/zope/publisher/browser.py	2013-02-20 14:17:14 UTC (rev 129538)
@@ -51,7 +51,9 @@
 from zope.publisher.skinnable import applySkin #BBB import
 from zope.publisher.skinnable import SkinChangedEvent #BBB import
 
+from zope.publisher._compat import PYTHON2, _u
 
+
 __ArrayTypes = (list, tuple)
 
 start_of_header_search=re.compile('(<head[^>]*>)', re.I).search
@@ -245,13 +247,19 @@
 
     def _decode(self, text):
         """Try to decode the text using one of the available charsets."""
+        # According to PEP-3333, in python-3, QUERY_STRING is a string,
+        # representing 'latin-1' encoded byte array. So, if we are in python-3
+        # context, encode text as 'latin-1' first, to try to decode
+        # resulting byte array using user-supplied charset.
+        if not isinstance(text, bytes):
+            text = text.encode('latin-1')
         if self.charsets is None:
             envadapter = IUserPreferredCharsets(self)
             self.charsets = envadapter.getPreferredCharsets() or ['utf-8']
             self.charsets = [c for c in self.charsets if c != '*']
         for charset in self.charsets:
             try:
-                text = unicode(text, charset)
+                text = _u(text, charset)
                 break
             except UnicodeError:
                 pass
@@ -291,8 +299,9 @@
             del env['QUERY_STRING']
 
 
+        args = {'encoding': 'utf-8'} if not PYTHON2 else {}
         fs = ZopeFieldStorage(fp=fp, environ=env,
-                              keep_blank_values=1)
+                              keep_blank_values=1, **args)
 
         fslist = getattr(fs, 'list', None)
         if fslist is not None:
@@ -388,11 +397,10 @@
                 # skip over empty fields
                 return
 
-        # Make it unicode if not None
         if key is not None:
             key = self._decode(key)
 
-        if type(item) == str:
+        if isinstance(item, (str, bytes)):
             item = self._decode(item)
 
         if flags:
@@ -515,7 +523,7 @@
         """Insert defaults into form dictionary."""
         form = self.form
 
-        for keys, values in self.__defaults.iteritems():
+        for keys, values in self.__defaults.items():
             if not keys in form:
                 form[keys] = values
             else:
@@ -629,7 +637,9 @@
                 d[m] = getattr(file,m)
 
         self.headers = aFieldStorage.headers
-        filename = unicode(aFieldStorage.filename, 'UTF-8')
+        filename = aFieldStorage.filename
+        if isinstance(aFieldStorage.filename, bytes):
+            filename = _u(aFieldStorage.filename, 'UTF-8')
         # fix for IE full paths
         filename = filename[filename.rfind('\\')+1:].strip()
         self.filename = filename

Modified: zope.publisher/branches/py3-attempt2/src/zope/publisher/http.py
===================================================================
--- zope.publisher/branches/py3-attempt2/src/zope/publisher/http.py	2013-02-20 14:15:24 UTC (rev 129537)
+++ zope.publisher/branches/py3-attempt2/src/zope/publisher/http.py	2013-02-20 14:17:14 UTC (rev 129538)
@@ -42,8 +42,9 @@
 import zope.event
 import zope.interface
 
-PY2 = sys.version_info[0] == 2
-if PY2:
+from zope.publisher._compat import PYTHON2, CLASS_TYPES, _u
+
+if PYTHON2:
     import Cookie as cookies
     from urllib import splitport, quote
     from urlparse import urlsplit
@@ -79,8 +80,11 @@
         dict[key] = val
     if 'HTTP_CGI_AUTHORIZATION' in dict:
         dict['HTTP_AUTHORIZATION'] = dict.pop('HTTP_CGI_AUTHORIZATION')
-    if 'PATH_INFO' in dict and isinstance('PATH_INFO', bytes):
-        dict['PATH_INFO'] = dict['PATH_INFO'].decode('utf-8')
+    if 'PATH_INFO' in dict:
+        # Recode PATH_INFO to UTF-8 from original latin1
+        pi = dict['PATH_INFO']
+        pi = pi if isinstance(pi, bytes) else pi.encode('latin1')
+        dict['PATH_INFO'] = pi.decode(ENCODING)
     return dict
 
 @zope.interface.implementer(IHTTPVirtualHostChangedEvent)
@@ -185,7 +189,7 @@
             else:
                 return self.__request.getApplicationURL(i)
         except IndexError as v:
-            if v[0] == i:
+            if v.args[0] == i:
                 return default
             raise
 
@@ -415,7 +419,12 @@
             return result
 
         for k,v in c.items():
-            result[unicode(k, ENCODING)] = unicode(v.value, ENCODING)
+            # recode cookie value to ENCODING (UTF-8)
+            rk = _u(k if type(k) == bytes
+                    else k.encode('latin1'), ENCODING)
+            rv = _u(v.value if type(v.value) == bytes
+                    else v.value.encode('latin1'), ENCODING)
+            result[rk] = rv
 
         return result
 
@@ -792,7 +801,7 @@
 
     def consumeBody(self):
         'See IHTTPResponse'
-        return ''.join(self._result)
+        return b''.join(self._result)
 
 
     def consumeBodyIter(self):
@@ -841,13 +850,13 @@
         Calls self.setBody() with an error response.
         """
         t, v = exc_info[:2]
-        if isinstance(t, (types.ClassType, type)):
+        if isinstance(t, CLASS_TYPES):
             if issubclass(t, Redirect):
                 self.redirect(v.getLocation())
                 return
             title = tname = t.__name__
         else:
-            title = tname = unicode(t)
+            title = tname = _u(t)
 
         # Throwing non-protocol-specific exceptions is a good way
         # for apps to control the status code.

Modified: zope.publisher/branches/py3-attempt2/src/zope/publisher/publish.py
===================================================================
--- zope.publisher/branches/py3-attempt2/src/zope/publisher/publish.py	2013-02-20 14:15:24 UTC (rev 129537)
+++ zope.publisher/branches/py3-attempt2/src/zope/publisher/publish.py	2013-02-20 14:17:14 UTC (rev 129538)
@@ -41,11 +41,11 @@
         if bases is not None:
             raise TypeError("mapply() can not call class constructors")
 
-        im_func = getattr(unwrapped, 'im_func', None)
+        im_func = getattr(unwrapped, '__func__', None)
         if im_func is not None:
             unwrapped = im_func
             wrapperCount += 1
-        elif getattr(unwrapped, 'func_code', None) is not None:
+        elif getattr(unwrapped, '__code__', None) is not None:
             break
         else:
             unwrapped = getattr(unwrapped, '__call__' , None)

Modified: zope.publisher/branches/py3-attempt2/src/zope/publisher/tests/test_browserrequest.py
===================================================================
--- zope.publisher/branches/py3-attempt2/src/zope/publisher/tests/test_browserrequest.py	2013-02-20 14:15:24 UTC (rev 129537)
+++ zope.publisher/branches/py3-attempt2/src/zope/publisher/tests/test_browserrequest.py	2013-02-20 14:17:14 UTC (rev 129538)
@@ -29,6 +29,7 @@
 from zope.publisher.interfaces.browser import IBrowserPublication
 from zope.publisher.base import DefaultPublication
 
+from zope.publisher._compat import PYTHON2
 from zope.publisher.tests.test_http import HTTPTests
 from zope.publisher.tests.publication import TestPublication
 
@@ -39,15 +40,15 @@
 from zope.publisher.tests.basetestiapplicationrequest \
      import BaseTestIApplicationRequest
 
-LARGE_FILE_BODY = """-----------------------------1
+LARGE_FILE_BODY = b''.join([b"""-----------------------------1
 Content-Disposition: form-data; name="upload"; filename="test"
 Content-Type: text/plain
 
-Here comes some text! %s
+Here comes some text! """, (b'test'*1000), b"""
 -----------------------------1--
-""" % ('test' * 1000)
+"""])
 
-IE_FILE_BODY = """-----------------------------1
+IE_FILE_BODY = b"""-----------------------------1
 Content-Disposition: form-data; name="upload"; filename="C:\\Windows\\notepad.exe"
 Content-Type: text/plain
 
@@ -55,7 +56,10 @@
 -----------------------------1--
 """
 
+if not PYTHON2:
+    unicode = str
 
+
 def publish(request):
     publish_(request, handle_errors=0)
 
@@ -101,7 +105,7 @@
         class Item(object):
             """Required docstring for the publisher."""
             def __call__(self, a, b):
-                return u"%s, %s" % (repr(a), repr(b))
+                return u"%s, %s" % (repr(a).lstrip('u'), repr(b).lstrip('u'))
 
         class Item3(object):
             """Required docstring for the publisher."""
@@ -115,7 +119,7 @@
 
             def index(self, a, b):
                 """Required docstring for the publisher."""
-                return u"%s, %s" % (repr(a), repr(b))
+                return u"%s, %s" % (repr(a).lstrip('u'), repr(b).lstrip('u'))
 
         class Item2(object):
             """Required docstring for the publisher."""
@@ -148,12 +152,12 @@
         self.failUnlessEqual(
             res,
             "Status: 200 Ok\r\n"
-            "Content-Length: 7\r\n"
+            "Content-Length: 6\r\n"
             "Content-Type: text/plain;charset=utf-8\r\n"
             "X-Content-Type-Warning: guessed from content\r\n"
             "X-Powered-By: Zope (www.zope.org), Python (www.python.org)\r\n"
             "\r\n"
-            "u'5', 6")
+            "'5', 6")
 
     def testNoDefault(self):
         request = self._createRequest()
@@ -171,7 +175,7 @@
 
     def testDefaultPOST(self):
         extra = {'PATH_INFO': '/folder/item2', "REQUEST_METHOD": "POST"}
-        request = self._createRequest(extra, body='a=5&b:int=6')
+        request = self._createRequest(extra, body=b'a=5&b:int=6')
         response = request.response
         publish(request)
         self.assertEqual(response.getBase(),
@@ -187,7 +191,7 @@
                  'CONTENT_TYPE': 'multipart/form-data;\
                  boundary=---------------------------1'}
 
-        body = """-----------------------------1
+        body = b"""-----------------------------1
         Content-Disposition: form-data; name="field.contentType"
         ...
         application/octet-stream
@@ -261,7 +265,7 @@
                          {u'a':u'5', u'b':6})
 
     def testFormNoEncodingUsesUTF8(self):
-        encoded = 'K\xc3\x83\xc2\xb6hlerstra\xc3\x83\xc2\x9fe'
+        encoded = 'K\xc3\xb6hlerstra\xc3\x9fe'
         extra = {
             # if nothing else is specified, form data should be
             # interpreted as UTF-8, as this stub query string is
@@ -272,7 +276,7 @@
         del request._environ['HTTP_ACCEPT_CHARSET']
         publish(request)
         self.assert_(isinstance(request.form[u'street'], unicode))
-        self.assertEqual(unicode(encoded, 'utf-8'), request.form['street'])
+        self.assertEqual(u'K\xf6hlerstra\xdfe', request.form['street'])
 
     def testFormAcceptsStarButNotUTF8(self):
         extra = {
@@ -292,7 +296,7 @@
     def testQueryStringIgnoredForPOST(self):
         request = self._createRequest(
             {"REQUEST_METHOD": "POST",
-             'PATH_INFO': '/folder/item3'}, body='c=5&d:int=6')
+             'PATH_INFO': '/folder/item3'}, body=b'c=5&d:int=6')
         publish(request)
         self.assertEqual(request.form, {u'c': u'5', u'd': 6})
         self.assertEqual(request.get('QUERY_STRING'), 'a=5&b:int=6')
@@ -307,22 +311,22 @@
         extra = {'QUERY_STRING':'a.x:tuple:record=5&a.x:tuple:record=6&b=1'}
         request = self._createRequest(extra)
         publish(request)
-        keys = request.form.keys()
-        keys.sort()
+        keys = sorted(request.form.keys())
         self.assertEqual(keys, [u'a',u'b'])
         self.assertEqual(request.form[u'b'], u'1')
-        self.assertEqual(request.form[u'a'].keys(), [u'x'])
+        self.assertEqual(list(request.form[u'a'].keys()), [u'x'])
         self.assertEqual(request.form[u'a'][u'x'], (u'5',u'6'))
         self.assertEqual(request.form[u'a'].x, (u'5',u'6'))
-        self.assertEqual(str(request.form[u'a']), "{x: (u'5', u'6')}")
-        self.assertEqual(repr(request.form[u'a']), "{x: (u'5', u'6')}")
+        self.assertEqual(str(request.form[u'a']).replace("u'", "'"),
+                         "{x: ('5', '6')}")
+        self.assertEqual(repr(request.form[u'a']).replace("u'", "'"),
+                         "{x: ('5', '6')}")
 
     def testFormRecordsTypes(self):
         extra = {'QUERY_STRING':'a.x:records=5&a.x:records=6&b=1'}
         request = self._createRequest(extra)
         publish(request)
-        keys = request.form.keys()
-        keys.sort()
+        keys = sorted(request.form.keys())
         self.assertEqual(keys, [u'a',u'b'])
         self.assertEqual(request.form[u'b'], u'1')
         self.assertEqual(len(request.form[u'a']), 2)
@@ -330,16 +334,17 @@
         self.assertEqual(request.form[u'a'][0].x, u'5')
         self.assertEqual(request.form[u'a'][1][u'x'], u'6')
         self.assertEqual(request.form[u'a'][1].x, u'6')
-        self.assertEqual(str(request.form[u'a']), "[{x: u'5'}, {x: u'6'}]")
-        self.assertEqual(repr(request.form[u'a']), "[{x: u'5'}, {x: u'6'}]")
+        self.assertEqual(str(request.form[u'a']).replace("u'", "'"),
+                         "[{x: '5'}, {x: '6'}]")
+        self.assertEqual(repr(request.form[u'a']).replace("u'", "'"),
+                         "[{x: '5'}, {x: '6'}]")
 
     def testFormMultipleRecordsTypes(self):
         extra = {'QUERY_STRING':'a.x:records:int=5&a.y:records:int=51'
             '&a.x:records:int=6&a.y:records:int=61&b=1'}
         request = self._createRequest(extra)
         publish(request)
-        keys = request.form.keys()
-        keys.sort()
+        keys = sorted(request.form.keys())
         self.assertEqual(keys, [u'a',u'b'])
         self.assertEqual(request.form[u'b'], u'1')
         self.assertEqual(len(request.form[u'a']), 2)
@@ -360,15 +365,16 @@
         extra = {'QUERY_STRING':'a.x:list:record=5&a.x:list:record=6&b=1'}
         request = self._createRequest(extra)
         publish(request)
-        keys = request.form.keys()
-        keys.sort()
+        keys = sorted(request.form.keys())
         self.assertEqual(keys, [u'a',u'b'])
         self.assertEqual(request.form[u'b'], u'1')
-        self.assertEqual(request.form[u'a'].keys(), [u'x'])
+        self.assertEqual(list(request.form[u'a'].keys()), [u'x'])
         self.assertEqual(request.form[u'a'][u'x'], [u'5',u'6'])
         self.assertEqual(request.form[u'a'].x, [u'5',u'6'])
-        self.assertEqual(str(request.form[u'a']), "{x: [u'5', u'6']}")
-        self.assertEqual(repr(request.form[u'a']), "{x: [u'5', u'6']}")
+        self.assertEqual(str(request.form[u'a']).replace("u'", "'"),
+                         "{x: ['5', '6']}")
+        self.assertEqual(repr(request.form[u'a']).replace("u'", "'"),
+                         "{x: ['5', '6']}")
 
     def testFormListTypes2(self):
         extra = {'QUERY_STRING':'a=5&a=6&b=1'}
@@ -514,9 +520,9 @@
             dict(REQUEST_METHOD='POST',
                  CONTENT_TYPE='application/x-foo',
                  ),
-            'test body')
+            b'test body')
         request.processInputs()
-        self.assertEqual(request.bodyStream.read(), 'test body')
+        self.assertEqual(request.bodyStream.read(), b'test body')
 
     def test_post_body_not_necessarily(self):
         request = self._createRequest(
@@ -524,9 +530,9 @@
                  CONTENT_TYPE='application/x-www-form-urlencoded',
                  QUERY_STRING='',
                  ),
-            'x=1&y=2')
+            b'x=1&y=2')
         request.processInputs()
-        self.assertEqual(request.bodyStream.read(), '')
+        self.assertEqual(request.bodyStream.read(), b'')
         self.assertEqual(dict(request.form), dict(x='1', y='2'))
 
         request = self._createRequest(
@@ -535,9 +541,9 @@
                                '; charset=UTF-8'),
                  QUERY_STRING='',
                  ),
-            'x=1&y=2')
+            b'x=1&y=2')
         request.processInputs()
-        self.assertEqual(request.bodyStream.read(), '')
+        self.assertEqual(request.bodyStream.read(), b'')
         self.assertEqual(dict(request.form), dict(x='1', y='2'))
 
 @implementer(IBrowserPublication)

Modified: zope.publisher/branches/py3-attempt2/src/zope/publisher/tests/test_http.py
===================================================================
--- zope.publisher/branches/py3-attempt2/src/zope/publisher/tests/test_http.py	2013-02-20 14:15:24 UTC (rev 129537)
+++ zope.publisher/branches/py3-attempt2/src/zope/publisher/tests/test_http.py	2013-02-20 14:17:14 UTC (rev 129538)
@@ -228,7 +228,7 @@
             +
             "\r\n".join([("%s: %s" % h) for h in headers]) + "\r\n\r\n"
             +
-            ''.join(response.consumeBody())
+            response.consumeBody().decode('utf8')
             )
 
     def test_double_dots(self):
@@ -691,7 +691,7 @@
         self.assertEquals(request.response.getHeader('Content-Type'),
                           'text/plain;charset=utf-8')
         self.assertEquals(body,
-                          'Latin a with ogonek\xc4\x85 Cyrillic ya \xd1\x8f')
+                          b'Latin a with ogonek\xc4\x85 Cyrillic ya \xd1\x8f')
 
 class ConcreteHTTPTests(HTTPTests):
     """Tests that we don't have to worry about subclasses inheriting and



More information about the checkins mailing list