Skip to content

Commit

Permalink
More Python 3 fixes.
Browse files Browse the repository at this point in the history
  • Loading branch information
hannosch committed May 13, 2017
1 parent dbfc120 commit bb5c184
Show file tree
Hide file tree
Showing 25 changed files with 302 additions and 235 deletions.
2 changes: 2 additions & 0 deletions buildout.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,11 @@ parts =
requirements
sources-dir = develop
auto-checkout =
DocumentTemplate
Products.BTreeFolder2
Products.MailHost
Products.ZCatalog
zExceptions


[tox]
Expand Down
13 changes: 7 additions & 6 deletions src/OFS/DTMLDocument.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
from AccessControl.class_init import InitializeClass
from DocumentTemplate.permissions import change_dtml_methods
from DocumentTemplate.permissions import change_dtml_documents
from six import binary_type
from six.moves.urllib.parse import quote
from zExceptions import ResourceLockedError
from zExceptions.TracebackSupplement import PathTracebackSupplement
Expand Down Expand Up @@ -54,7 +55,7 @@ def manage_upload(self, file='', REQUEST=None):
if self.wl_isLocked():
raise ResourceLockedError('This document has been locked.')

if not isinstance(file, str):
if not isinstance(file, binary_type):
if REQUEST and not file:
raise ValueError('No file specified')
file = file.read()
Expand Down Expand Up @@ -101,15 +102,15 @@ def __call__(self, client=None, REQUEST={}, RESPONSE=None, **kw):

r = HTML.__call__(self, (client, bself), REQUEST, **kw)

if RESPONSE is None or not isinstance(r, str):
if RESPONSE is None or not isinstance(r, binary_type):
if not self._cache_namespace_keys:
self.ZCacheable_set(r)
return r

finally:
security.removeContext(self)

have_key = RESPONSE.headers.has_key
have_key = RESPONSE.headers.__contains__
if not (have_key('content-type') or have_key('Content-Type')):
if 'content_type' in self.__dict__:
c = self.content_type
Expand All @@ -125,7 +126,7 @@ def __call__(self, client=None, REQUEST={}, RESPONSE=None, **kw):
InitializeClass(DTMLDocument)


default_dd_html = """\
default_dd_html = b"""\
<!DOCTYPE html>
<html>
<head>
Expand All @@ -143,11 +144,11 @@ def __call__(self, client=None, REQUEST={}, RESPONSE=None, **kw):
addForm = DTMLFile('dtml/documentAdd', globals())


def addDTMLDocument(self, id, title='', file='', REQUEST=None, submit=None):
def addDTMLDocument(self, id, title='', file=b'', REQUEST=None, submit=None):
"""Add a DTML Document object with the contents of file. If
'file' is empty, default document text is used.
"""
if not isinstance(file, str):
if not isinstance(file, binary_type):
file = file.read()
if not file:
file = default_dd_html
Expand Down
16 changes: 9 additions & 7 deletions src/OFS/DTMLMethod.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
from Acquisition import Implicit
from DocumentTemplate.permissions import change_dtml_methods
from DocumentTemplate.security import RestrictedDTML
from six import binary_type
from six.moves.urllib.parse import quote
from zExceptions import Forbidden
from zExceptions import ResourceLockedError
Expand Down Expand Up @@ -141,7 +142,7 @@ def __call__(self, client=None, REQUEST={}, RESPONSE=None, **kw):
return result

r = HTML.__call__(self, client, REQUEST, **kw)
if RESPONSE is None or not isinstance(r, str):
if RESPONSE is None or not isinstance(r, binary_type):
if not self._cache_namespace_keys:
self.ZCacheable_set(r)
return r
Expand All @@ -151,7 +152,7 @@ def __call__(self, client=None, REQUEST={}, RESPONSE=None, **kw):
if first_time_through:
del self.__dict__['validate']

have_key = RESPONSE.headers.has_key
have_key = RESPONSE.headers.__contains__
if not (have_key('content-type') or have_key('Content-Type')):
if 'content_type' in self.__dict__:
c = self.content_type
Expand Down Expand Up @@ -247,7 +248,8 @@ def manage_edit(self, data, title, SUBMIT='Change', REQUEST=None):
self.title = str(title)
if isinstance(data, TaintedString):
data = data.quoted()
if not isinstance(data, basestring):

if not isinstance(data, binary_type):
data = data.read()
self.munge(data)
self.ZCacheable_invalidate()
Expand All @@ -263,7 +265,7 @@ def manage_upload(self, file='', REQUEST=None):
if self.wl_isLocked():
raise ResourceLockedError('This DTML Method is locked.')

if not isinstance(file, str):
if not isinstance(file, binary_type):
if REQUEST and not file:
raise ValueError('No file specified')
file = file.read()
Expand Down Expand Up @@ -385,7 +387,7 @@ def decapitate(html, RESPONSE=None):
return html[spos + eolen:]


default_dm_html = """\
default_dm_html = b"""\
<!DOCTYPE html>
<html>
<head>
Expand All @@ -404,11 +406,11 @@ def decapitate(html, RESPONSE=None):
addForm = DTMLFile('dtml/methodAdd', globals())


def addDTMLMethod(self, id, title='', file='', REQUEST=None, submit=None):
def addDTMLMethod(self, id, title='', file=b'', REQUEST=None, submit=None):
"""Add a DTML Method object with the contents of file. If
'file' is empty, default document text is used.
"""
if not isinstance(file, str):
if not isinstance(file, binary_type):
file = file.read()
if not file:
file = default_dm_html
Expand Down
97 changes: 64 additions & 33 deletions src/OFS/Image.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
"""Image object
"""

from cgi import escape
from email.generator import _make_boundary
from io import BytesIO
import struct
Expand All @@ -27,6 +26,8 @@
from Acquisition import Implicit
from DateTime.DateTime import DateTime
from Persistence import Persistent
from six import binary_type
from six import PY2
from six import text_type
from zExceptions import Redirect, ResourceLockedError
from zope.contenttype import guess_content_type
Expand All @@ -46,6 +47,11 @@
from ZPublisher import HTTPRangeSupport
from ZPublisher.HTTPRequest import FileUpload

try:
from html import escape
except ImportError: # PY2
from cgi import escape


manage_addFileForm = DTMLFile(
'dtml/imageAdd', globals(), Kind='File', kind='file')
Expand Down Expand Up @@ -238,7 +244,7 @@ def _range_request_handler(self, REQUEST, RESPONSE):
RESPONSE.setStatus(206) # Partial content

data = self.data
if isinstance(data, str):
if isinstance(data, binary_type):
RESPONSE.write(data[start:end])
return True

Expand Down Expand Up @@ -303,14 +309,17 @@ def _range_request_handler(self, REQUEST, RESPONSE):
pdata_map[0] = data

for start, end in ranges:
RESPONSE.write('\r\n--%s\r\n' % boundary)
RESPONSE.write(
'Content-Type: %s\r\n' % self.content_type)
b'\r\n--' + boundary.encode('ascii') + b'\r\n')
RESPONSE.write(
b'Content-Type: ' +
self.content_type.encode('ascii') + b'\r\n')
RESPONSE.write(
'Content-Range: bytes %d-%d/%d\r\n\r\n' % (
start, end - 1, self.size))
b'Content-Range: bytes ' + bytes(start) +
b'-' + bytes(end - 1) +
b'/' + bytes(self.size) + b'\r\n\r\n')

if isinstance(data, str):
if isinstance(data, binary_type):
RESPONSE.write(data[start:end])

else:
Expand Down Expand Up @@ -359,7 +368,8 @@ def _range_request_handler(self, REQUEST, RESPONSE):
# Do not keep the link references around.
del pdata_map

RESPONSE.write('\r\n--%s--\r\n' % boundary)
RESPONSE.write(
b'\r\n--' + boundary.encode('ascii') + b'--\r\n')
return True

security.declareProtected(View, 'index_html')
Expand All @@ -379,7 +389,7 @@ def index_html(self, REQUEST, RESPONSE):
# This is nonsensical for caches other than the HTTP cache manager
# unfortunately.
self.ZCacheable_set(None)
return ''
return b''

if self.precondition and hasattr(self, str(self.precondition)):
# Grab whatever precondition was defined and then
Expand All @@ -393,7 +403,7 @@ def index_html(self, REQUEST, RESPONSE):

if self._range_request_handler(REQUEST, RESPONSE):
# we served a chunk of content in response to a range request.
return ''
return b''

RESPONSE.setHeader('Last-Modified', rfc1123_date(self._p_mtime))
RESPONSE.setHeader('Content-Type', self.content_type)
Expand All @@ -412,15 +422,15 @@ def index_html(self, REQUEST, RESPONSE):
self.ZCacheable_set(None)

data = self.data
if isinstance(data, str):
if isinstance(data, binary_type):
RESPONSE.setBase(None)
return data

while data is not None:
RESPONSE.write(data.data)
data = data.next

return ''
return b''

security.declareProtected(View, 'view_image_or_file')
def view_image_or_file(self, URL1):
Expand All @@ -433,8 +443,8 @@ def view_image_or_file(self, URL1):
def PrincipiaSearchSource(self):
# Allow file objects to be searched.
if self.content_type.startswith('text/'):
return str(self.data)
return ''
return bytes(self.data)
return b''

security.declarePrivate('update_data')
def update_data(self, data, content_type=None, size=None):
Expand Down Expand Up @@ -603,11 +613,21 @@ def getContentType(self):
# Returns the content type (MIME type) of a file or image.
return self.content_type

def __str__(self):
return str(self.data)
def __bytes__(self):
return bytes(self.data)

if PY2:
def __str__(self):
return str(self.data)

def __bool__(self):
return True

__nonzero__ = __bool__

def __len__(self):
return 1
data = bytes(self.data)
return len(data)

if bbb.HAS_ZSERVER:
security.declareProtected(change_images_and_files, 'PUT')
Expand Down Expand Up @@ -647,15 +667,15 @@ def manage_FTPget(self):
return result

data = self.data
if isinstance(data, str):
if isinstance(data, binary_type):
RESPONSE.setBase(None)
return data

while data is not None:
RESPONSE.write(data.data)
data = data.next

return ''
return b''

InitializeClass(File)

Expand All @@ -682,7 +702,7 @@ def manage_addImage(self, id, file, title='', precondition='', content_type='',
self = self.this()

# First, we create the image without data:
self._setObject(id, Image(id, title, '', content_type, precondition))
self._setObject(id, Image(id, title, b'', content_type, precondition))

newFile = self._getOb(id)

Expand All @@ -705,14 +725,14 @@ def manage_addImage(self, id, file, title='', precondition='', content_type='',


def getImageInfo(data):
data = str(data)
data = bytes(data)
size = len(data)
height = -1
width = -1
content_type = ''

# handle GIFs
if (size >= 10) and data[:6] in ('GIF87a', 'GIF89a'):
if (size >= 10) and data[:6] in (b'GIF87a', b'GIF89a'):
# Check to see if content_type is correct
content_type = 'image/gif'
w, h = struct.unpack("<HH", data[6:10])
Expand All @@ -722,23 +742,23 @@ def getImageInfo(data):
# See PNG v1.2 spec (http://www.cdrom.com/pub/png/spec/)
# Bytes 0-7 are below, 4-byte chunk length, then 'IHDR'
# and finally the 4-byte width, height
elif ((size >= 24) and (data[:8] == '\211PNG\r\n\032\n') and
(data[12:16] == 'IHDR')):
elif ((size >= 24) and (data[:8] == b'\211PNG\r\n\032\n') and
(data[12:16] == b'IHDR')):
content_type = 'image/png'
w, h = struct.unpack(">LL", data[16:24])
width = int(w)
height = int(h)

# Maybe this is for an older PNG version.
elif (size >= 16) and (data[:8] == '\211PNG\r\n\032\n'):
elif (size >= 16) and (data[:8] == b'\211PNG\r\n\032\n'):
# Check to see if we have the right content type
content_type = 'image/png'
w, h = struct.unpack(">LL", data[8:16])
width = int(w)
height = int(h)

# handle JPEGs
elif (size >= 2) and (data[:2] == '\377\330'):
elif (size >= 2) and (data[:2] == b'\377\330'):
content_type = 'image/jpeg'
jpeg = BytesIO(data)
jpeg.read(2)
Expand Down Expand Up @@ -845,8 +865,12 @@ def update_data(self, data, content_type=None, size=None):
self.ZCacheable_set(None)
self.http__refreshEtag()

def __str__(self):
return self.tag()
def __bytes__(self):
return self.tag().encode('utf-8')

if PY2:
def __str__(self):
return self.tag()

security.declareProtected(View, 'tag')
def tag(self, height=None, width=None, alt=None,
Expand Down Expand Up @@ -926,14 +950,18 @@ class Pdata(Persistent, Implicit):
def __init__(self, data):
self.data = data

def __getslice__(self, i, j):
return self.data[i:j]
if PY2:
def __getslice__(self, i, j):
return self.data[i:j]

def __getitem__(self, key):
return self.data[key]

def __len__(self):
data = str(self)
data = bytes(self)
return len(data)

def __str__(self):
def __bytes__(self):
_next = self.next
if _next is None:
return self.data
Expand All @@ -944,4 +972,7 @@ def __str__(self):
r.append(self.data)
_next = self.next

return ''.join(r)
return b''.join(r)

if PY2:
__str__ = __bytes__
Loading

0 comments on commit bb5c184

Please sign in to comment.