[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