Commit 4450c7c2 authored by Arnaud Fontaine's avatar Arnaud Fontaine

py3: BusinessTemplate: Fix reading of BusinessTemplate files.

With Python2, properties were all str(). with Python3, we need to distinguish
binary-like properties from text-like properties.

This should ideally be implemented by checking PropertySheet elementary_type
(such as `data` for bytes() and `string` or `text` for str()) for each property.
For now (bootstrap/addERP5Site) though, let's consider all properties in .xml to
be UTF-8 str() and statically define which is which for non-.xml files.
parent ac8a3957
...@@ -29,7 +29,7 @@ ...@@ -29,7 +29,7 @@
import six import six
from six import string_types as basestring from six import string_types as basestring
from Products.ERP5Type.Utils import ensure_list from Products.ERP5Type.Utils import ensure_list, bytes2str
import fnmatch, gc, glob, imp, os, re, shutil, sys, time, tarfile import fnmatch, gc, glob, imp, os, re, shutil, sys, time, tarfile
from collections import defaultdict from collections import defaultdict
from Shared.DC.ZRDB import Aqueduct from Shared.DC.ZRDB import Aqueduct
...@@ -131,33 +131,38 @@ SEPARATELY_EXPORTED_PROPERTY_DICT = { ...@@ -131,33 +131,38 @@ SEPARATELY_EXPORTED_PROPERTY_DICT = {
# separate file, with extension specified by 'extension'. # separate file, with extension specified by 'extension'.
# 'extension' must be None for auto-detection. # 'extension' must be None for auto-detection.
# #
# class_name: (extension, unicode_data, property_name), # XXX-py3: `text` was added but what we should do is check the PropertySheet
"Document Component": ("py", 0, "text_content"), # ('string' (str) /'data' (bytes)) but for now, only work on
"DTMLDocument": (None, 0, "raw"), # bootstrap...
"DTMLMethod": (None, 0, "raw"), #
"Extension Component": ("py", 0, "text_content"), # class_name: (extension, unicode_data, property_name, text),
"File": (None, 0, "data"), "Document Component": ("py", 0, "text_content", True ),
"Image": (None, 0, "data"), "DTMLDocument": (None, 0, "raw", True ),
"Interface Component": ("py", 0, "text_content"), "DTMLMethod": (None, 0, "raw", True ),
"OOoTemplate": ("oot", 1, "_text"), "Extension Component": ("py", 0, "text_content", True ),
"Mixin Component": ("py", 0, "text_content"), # OFS.File raises ValueError("Must be bytes")
"Module Component": ("py", 0, "text_content"), "File": (None, 0, "data", False),
"PDF": ("pdf", 0, "data"), "Image": (None, 0, "data", False),
"PyData Script": ("py", 0, "_body"), "Interface Component": ("py", 0, "text_content", True ),
"Python Script": ("py", 0, "_body"), "OOoTemplate": ("oot", 1, "_text", True ),
"Workflow Script": ("py", 0, "_body"), "Mixin Component": ("py", 0, "text_content", True ),
"PythonScript": ("py", 0, "_body"), "Module Component": ("py", 0, "text_content", True ),
"Spreadsheet": (None, 0, "data"), "PDF": ("pdf", 0, "data", False),
"SQL": ("sql", 0, "src"), "PyData Script": ("py", 0, "_body", True ),
"SQL Method": ("sql", 0, "src"), "Python Script": ("py", 0, "_body", True ),
"Test Component": ("py", 0, "text_content"), "Workflow Script": ("py", 0, "_body", True ),
"Test Page": (None, 0, "text_content"), "PythonScript": ("py", 0, "_body", True ),
"Tool Component": ("py", 0, "text_content"), "Spreadsheet": (None, 0, "data", False),
"Web Illustration": ("svg", 0, "text_content"), "SQL": ("sql", 0, "src", True ),
"Web Page": (None, 0, "text_content"), "SQL Method": ("sql", 0, "src", True ),
"Web Script": (None, 0, "text_content"), "Test Component": ("py", 0, "text_content", True ),
"Web Style": (None, 0, "text_content"), "Test Page": (None, 0, "text_content", True ),
"ZopePageTemplate": ("zpt", 1, "_text"), "Tool Component": ("py", 0, "text_content", True ),
"Web Illustration": ("svg", 0, "text_content", True ),
"Web Page": (None, 0, "text_content", True ),
"Web Script": (None, 0, "text_content", True ),
"Web Style": (None, 0, "text_content", True ),
"ZopePageTemplate": ("zpt", 1, "_text", True ),
} }
def _getCatalog(acquisition_context): def _getCatalog(acquisition_context):
...@@ -812,7 +817,7 @@ class ObjectTemplateItem(BaseTemplateItem): ...@@ -812,7 +817,7 @@ class ObjectTemplateItem(BaseTemplateItem):
bta.addObject(obj, name=key, ext='.py') bta.addObject(obj, name=key, ext='.py')
else: else:
try: try:
extension, unicode_data, record_id = \ extension, unicode_data, record_id, _ = \
SEPARATELY_EXPORTED_PROPERTY_DICT[obj.__class__.__name__] SEPARATELY_EXPORTED_PROPERTY_DICT[obj.__class__.__name__]
except KeyError: except KeyError:
pass pass
...@@ -866,10 +871,15 @@ class ObjectTemplateItem(BaseTemplateItem): ...@@ -866,10 +871,15 @@ class ObjectTemplateItem(BaseTemplateItem):
bta.addObject(xml_data, key + '.catalog_keys', path=path) bta.addObject(xml_data, key + '.catalog_keys', path=path)
def _restoreSeparatelyExportedProperty(self, obj, data): def _restoreSeparatelyExportedProperty(self, obj, data):
unicode_data, property_name = SEPARATELY_EXPORTED_PROPERTY_DICT[ class_name = obj.__class__.__name__
obj.__class__.__name__][1:] unicode_data, property_name, is_text = SEPARATELY_EXPORTED_PROPERTY_DICT[
class_name][1:]
if unicode_data: if unicode_data:
data = data.decode(obj.output_encoding) data = data.decode(obj.output_encoding)
# With Python2, everything should be str() and not unicode() for
# backward-compatibility
elif six.PY3 and is_text:
data = data.decode('utf-8')
try: try:
setattr(obj, property_name, data) setattr(obj, property_name, data)
except BrokenModified: except BrokenModified:
...@@ -1027,6 +1037,7 @@ class ObjectTemplateItem(BaseTemplateItem): ...@@ -1027,6 +1037,7 @@ class ObjectTemplateItem(BaseTemplateItem):
F.binary=1 F.binary=1
F.file=outfile F.file=outfile
p=xml.parsers.expat.ParserCreate('utf-8') p=xml.parsers.expat.ParserCreate('utf-8')
if six.PY2:
p.returns_unicode = False p.returns_unicode = False
p.CharacterDataHandler=F.handle_data p.CharacterDataHandler=F.handle_data
p.StartElementHandler=F.unknown_starttag p.StartElementHandler=F.unknown_starttag
...@@ -5031,7 +5042,7 @@ class bt(dict): ...@@ -5031,7 +5042,7 @@ class bt(dict):
"""Fake 'bt' item to read bt/* files through BusinessTemplateArchive""" """Fake 'bt' item to read bt/* files through BusinessTemplateArchive"""
def _importFile(self, file_name, file): def _importFile(self, file_name, file):
self[file_name] = file.read() self[file_name] = bytes2str(file.read())
class BusinessTemplate(XMLObject): class BusinessTemplate(XMLObject):
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment