Skip to content

Commit

Permalink
Even more Python 3 fixes.
Browse files Browse the repository at this point in the history
  • Loading branch information
hannosch committed May 17, 2017
1 parent 6064463 commit 91fd97d
Show file tree
Hide file tree
Showing 6 changed files with 89 additions and 29 deletions.
9 changes: 8 additions & 1 deletion src/Products/Five/browser/metaconfigure.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

import os
import sys
from inspect import isfunction
from inspect import ismethod

from zope.component import queryMultiAdapter
Expand Down Expand Up @@ -56,6 +57,11 @@
from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile


def is_method(func):
# Under Python 3, there are no unbound methods
return isfunction(func) or ismethod(func)


def _configure_z2security(_context, new_class, required):
_context.action(
discriminator=('five:protectClass', new_class),
Expand All @@ -69,10 +75,11 @@ def _configure_z2security(_context, new_class, required):
args=(new_class, attr, permission)
)
# Make everything else private
# if not _context:
private_attrs = [name for name in dir(new_class)
if ((not name.startswith('_')) and
(name not in required) and
ismethod(getattr(new_class, name)))]
is_method(getattr(new_class, name)))]
for attr in private_attrs:
_context.action(
discriminator=('five:protectName', new_class, attr),
Expand Down
12 changes: 12 additions & 0 deletions src/ZPublisher/Converters.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,16 @@ def field2string(v):
return str(v)


def field2bytes(v):
# Converts value to bytes.
if hasattr(v, 'read'):
return v.read()
elif isinstance(v, text_type):
return v.encode(default_encoding)
else:
return bytes(v)


def field2text(value, nl=re.compile('\r\n|\n\r').search):
value = field2string(value)
match_object = nl(value)
Expand Down Expand Up @@ -212,11 +222,13 @@ def convert_unicode(self, v):

field2ulines = field2ulines()


type_converters = {
'float': field2float,
'int': field2int,
'long': field2long,
'string': field2string, # to native str
'bytes': field2bytes,
'date': field2date,
'date_international': field2date_international,
'required': field2required,
Expand Down
22 changes: 11 additions & 11 deletions src/ZPublisher/HTTPRequest.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
from os.path import isfile
import random
import re
import sys
from tempfile import (
mkstemp,
_TemporaryFileWrapper,
Expand All @@ -34,6 +33,7 @@
import pkg_resources
from six import binary_type
from six import PY3
from six import string_types
from six import text_type
from six.moves.urllib.parse import unquote
from zope.i18n.interfaces import IUserPreferredLanguages
Expand Down Expand Up @@ -108,6 +108,8 @@
tainting_env = str(os.environ.get('ZOPE_DTML_REQUEST_AUTOQUOTE', '')).lower()
TAINTING_ENABLED = tainting_env not in ('disabled', '0', 'no')

search_type = re.compile(r'(:[a-zA-Z][-a-zA-Z0-9_]+|\\.[xy])$').search

_marker = []

# The trusted_proxies configuration setting contains a sequence
Expand Down Expand Up @@ -239,7 +241,7 @@ def setServerURL(self, protocol=None, hostname=None, port=None):
def setVirtualRoot(self, path, hard=0):
""" Treat the current publishing object as a VirtualRoot """
other = self.other
if isinstance(path, str) or isinstance(path, text_type):
if isinstance(path, string_types):
path = path.split('/')
self._script[:] = list(map(quote, [_p for _p in path if _p]))
del self._steps[:]
Expand All @@ -258,7 +260,7 @@ def getVirtualRoot(self):

def physicalPathToVirtualPath(self, path):
""" Remove the path to the VirtualRoot from a physical path """
if isinstance(path, str):
if isinstance(path, string_types):
path = path.split('/')
rpp = self.other.get('VirtualRootPhysicalPath', ('',))
i = 0
Expand Down Expand Up @@ -482,9 +484,7 @@ def processInputs(
CONVERTED=32,
hasattr=hasattr,
getattr=getattr,
setattr=setattr,
search_type=re.compile(
'(:[a-zA-Z][-a-zA-Z0-9_]+|\\.[xy])$').search):
setattr=setattr):
"""Process request inputs
We need to delay input parsing so that it is done under
Expand Down Expand Up @@ -1204,11 +1204,11 @@ def resolve_url(self, url):
# method is called on the response).
try:
object = req.traverse(path)
except Exception:
except Exception as exc:
rsp.exception()
if object is None:
req.clear()
raise sys.exc_info()[0](rsp.errmsg)
if object is None:
req.clear()
raise exc.__class__(rsp.errmsg)

# The traversal machinery may return a "default object"
# like an index_html document. This is not appropriate
Expand Down Expand Up @@ -1836,6 +1836,6 @@ def _decode(value, charset):
return tuple(_decode(v, charset) for v in value)
elif isinstance(value, dict):
return dict((k, _decode(v, charset)) for k, v in value.items())
elif isinstance(value, str):
elif isinstance(value, binary_type):
return text_type(value, charset, 'replace')
return value
23 changes: 16 additions & 7 deletions src/ZPublisher/tests/test_Converters.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,9 @@
#
##############################################################################

import sys
import unittest

if sys.version_info >= (3, ):
unicode = str
from six import text_type


class ConvertersTests(unittest.TestCase):
Expand All @@ -28,8 +26,8 @@ def test_field2string_with_string(self):
def test_field2string_with_unicode_default_encoding(self):
from ZPublisher.Converters import field2string
to_convert = u'to_convert'
self.assertEqual(field2string(to_convert),
to_convert.encode('utf-8'))
expected = 'to_convert'
self.assertEqual(field2string(to_convert), expected)

def test_field2string_with_filelike_object(self):
from ZPublisher.Converters import field2string
Expand All @@ -40,6 +38,17 @@ def read(self):
return to_convert
self.assertEqual(field2string(Filelike()), to_convert)

def test_field2bytes_with_bytes(self):
from ZPublisher.Converters import field2bytes
to_convert = b'to_convert'
self.assertEqual(field2bytes(to_convert), to_convert)

def test_field2bytes_with_text(self):
from ZPublisher.Converters import field2bytes
to_convert = u'to_convert'
expected = b'to_convert'
self.assertEqual(field2bytes(to_convert), expected)

def test_field2lines_with_list(self):
from ZPublisher.Converters import field2lines
to_convert = ['one', 'two']
Expand Down Expand Up @@ -69,13 +78,13 @@ def test_field2ulines_with_list(self):
from ZPublisher.Converters import field2ulines
to_convert = [u'one', 'two']
self.assertEqual(field2ulines(to_convert),
[unicode(x) for x in to_convert])
[text_type(x) for x in to_convert])

def test_field2ulines_with_tuple(self):
from ZPublisher.Converters import field2ulines
to_convert = (u'one', 'two')
self.assertEqual(field2ulines(to_convert),
[unicode(x) for x in to_convert])
[text_type(x) for x in to_convert])

def test_field2ulines_with_empty_string(self):
from ZPublisher.Converters import field2ulines
Expand Down
18 changes: 14 additions & 4 deletions src/ZTUtils/Zope.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
from AccessControl.unauthorized import Unauthorized
from AccessControl.ZopeGuards import guarded_getitem
from DateTime.DateTime import DateTime
from six import binary_type
from six import PY2
from six import text_type
from six.moves.urllib.parse import quote, unquote

Expand Down Expand Up @@ -151,6 +153,7 @@ def cookieTree(self, root_object, default_state=None):
req.RESPONSE.setCookie(state_name, encodeExpansion(rows))
return tree, rows


# Make the Batch class test security, and let it skip unauthorized.
_Batch = Batch

Expand All @@ -170,10 +173,12 @@ def __init__(self, sequence, size, start=0, end=0,
# "make_query(bstart=batch.end)" to the other.


#Do not do this at import time.
#Call '_default_encoding()' at run time to retrieve it from config, if present
#If not configured, will be 'utf8' by default.
# Do not do this at import time.
# Call '_default_encoding()' at run time to retrieve it from config, if present
# If not configured, will be 'utf8' by default.
_DEFAULT_ENCODING = None


def _default_encoding():
''' Retreive default encoding from config '''
global _DEFAULT_ENCODING
Expand All @@ -186,6 +191,7 @@ def _default_encoding():
_DEFAULT_ENCODING = 'utf8'
return _DEFAULT_ENCODING


def make_query(*args, **kwargs):
'''Construct a URL query string, with marshalling markup.
Expand All @@ -208,7 +214,7 @@ def make_query(*args, **kwargs):
qlist = complex_marshal(list(d.items()))
for i in range(len(qlist)):
k, m, v = qlist[i]
if isinstance(v, text_type):
if PY2 and isinstance(v, text_type):
v = v.encode(_default_encoding())
qlist[i] = '%s%s=%s' % (quote(k), m, quote(str(v)))

Expand Down Expand Up @@ -297,7 +303,11 @@ def complex_marshal(pairs):
def simple_marshal(v):
if isinstance(v, str):
return ''
if isinstance(v, binary_type):
# Py 3 only
return ':bytes'
if isinstance(v, text_type):
# Py 2 only
encoding = _default_encoding()
return ':%s:ustring' % (encoding,)
if isinstance(v, bool):
Expand Down
34 changes: 28 additions & 6 deletions src/ZTUtils/tests/testZope.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import unittest

from DateTime import DateTime
from six import PY2
from six.moves.urllib.parse import quote

from ZTUtils.Zope import (
Expand Down Expand Up @@ -29,17 +30,26 @@ def testMarshalDate(self):
self.assertEqual(simple_marshal(DateTime()), ":date")

def testMarshalUnicode(self):
self.assertEqual(simple_marshal(u'unic\xF3de'), ":utf8:ustring")
if PY2:
arg_type = ':utf8:ustring'
else:
arg_type = ''
self.assertEqual(simple_marshal(u'unic\xF3de'), arg_type)

def testMarshallLists(self):
'''Test marshalling lists'''
test_date = DateTime()
list_ = [1, test_date, 'str', u'unic\xF3de']
result = complex_marshal([('list', list_), ])
assert result == [('list', ':int:list', 1),
if PY2:
arg4_type = ':utf8:ustring:list'
else:
arg4_type = ':list'
self.assertEqual(result,
[('list', ':int:list', 1),
('list', ':date:list', test_date),
('list', ':list', 'str'),
('list', ':utf8:ustring:list', u'unic\xF3de')]
('list', arg4_type, u'unic\xF3de')])

def testMarshallRecords(self):
'''Test marshalling records'''
Expand All @@ -49,24 +59,32 @@ def testMarshallRecords(self):
'arg3': 'str', 'arg4': u'unic\xF3de',
}
result = complex_marshal([('record', record), ])
if PY2:
arg4_type = ':utf8:ustring:record'
else:
arg4_type = ':record'
self.assertEqual(
set(result),
set([('record.arg1', ':int:record', 1),
('record.arg2', ':date:record', test_date),
('record.arg3', ':record', 'str'),
('record.arg4', ':utf8:ustring:record', u'unic\xF3de')]))
('record.arg4', arg4_type, u'unic\xF3de')]))

def testMarshallListsInRecords(self):
'''Test marshalling lists inside of records'''
test_date = DateTime()
record = {'arg1': [1, test_date, 'str', u'unic\xF3de'], 'arg2': 1}
result = complex_marshal([('record', record), ])
if PY2:
arg1_type = ':utf8:ustring:list:record'
else:
arg1_type = ':list:record'
self.assertEqual(
set(result),
set([('record.arg1', ':int:list:record', 1),
('record.arg1', ':date:list:record', test_date),
('record.arg1', ':list:record', 'str'),
('record.arg1', ':utf8:ustring:list:record', u'unic\xF3de'),
('record.arg1', arg1_type, u'unic\xF3de'),
('record.arg2', ':int:record', 1)]))

def testMakeComplexQuery(self):
Expand Down Expand Up @@ -100,7 +118,11 @@ def testMakeQueryUnicode(self):
https://github.com/zopefoundation/Zope/issues/15
'''
query = make_query(search_text=u'unic\xF3de')
self.assertEqual('search_text:utf8:ustring=unic%C3%B3de', query)
if PY2:
arg_type = 'search_text:utf8:ustring='
else:
arg_type = 'search_text='
self.assertEqual(arg_type + 'unic%C3%B3de', query)

def testMakeHiddenInput(self):
tag = make_hidden_input(foo='bar')
Expand Down

0 comments on commit 91fd97d

Please sign in to comment.