Commit 9d9f83c7 authored by Georgios Dagkakis's avatar Georgios Dagkakis

BusinessTemplates: Allow export of files like Python Script, Web Page, Web...

BusinessTemplates: Allow export of files like Python Script, Web Page, Web Script etc. separately from the xml
parent 307e4b74
...@@ -62,7 +62,7 @@ from Products.ERP5Type.Utils import readLocalTest, \ ...@@ -62,7 +62,7 @@ from Products.ERP5Type.Utils import readLocalTest, \
from Products.ERP5Type.Utils import convertToUpperCase from Products.ERP5Type.Utils import convertToUpperCase
from Products.ERP5Type import Permissions, PropertySheet, interfaces from Products.ERP5Type import Permissions, PropertySheet, interfaces
from Products.ERP5Type.XMLObject import XMLObject from Products.ERP5Type.XMLObject import XMLObject
from Products.ERP5Type.dynamic.lazy_class import ERP5BaseBroken from Products.ERP5Type.dynamic.lazy_class import ERP5BaseBroken, InitGhostBase
from Products.ERP5Type.dynamic.portal_type_class import synchronizeDynamicModules from Products.ERP5Type.dynamic.portal_type_class import synchronizeDynamicModules
from Products.ERP5Type.Core.PropertySheet import PropertySheet as PropertySheetDocument from Products.ERP5Type.Core.PropertySheet import PropertySheet as PropertySheetDocument
from Products.ERP5Type.TransactionalVariable import getTransactionalVariable from Products.ERP5Type.TransactionalVariable import getTransactionalVariable
...@@ -102,6 +102,12 @@ try: ...@@ -102,6 +102,12 @@ try:
except TypeError: except TypeError:
pass pass
cache_database = threading.local() cache_database = threading.local()
from mimetypes import guess_extension
from mimetypes import MimeTypes
from Products.MimetypesRegistry.common import MimeTypeException
import base64
import binascii
import imghdr
# those attributes from CatalogMethodTemplateItem are kept for # those attributes from CatalogMethodTemplateItem are kept for
# backward compatibility # backward compatibility
...@@ -686,20 +692,280 @@ class ObjectTemplateItem(BaseTemplateItem): ...@@ -686,20 +692,280 @@ class ObjectTemplateItem(BaseTemplateItem):
if id != '': if id != '':
self._archive["%s/%s" % (tool_id, id)] = None self._archive["%s/%s" % (tool_id, id)] = None
def export(self, context, bta, **kw): def getClassNameAndExportedExtensionDict(self):
class_name_and_exported_extension_dict = {
"Web Page": {"extension": None, "exported_property_type": "text_content"},
"Web Style": {"extension": None, "exported_property_type": "text_content"},
"Web Script": {"extension": None, "exported_property_type": "text_content"},
"ZopePageTemplate": {"extension": ".zpt", "exported_property_type": "_text"},
"OOoTemplate": {"extension": ".oot", "exported_property_type": "_text"},
"Extension Component": {"extension": ".py", "exported_property_type": "text_content"},
"Test Component": {"extension": ".py", "exported_property_type": "text_content"},
"Document Component": {"extension": ".py", "exported_property_type": "text_content"},
"PythonScript": {"extension": ".py", "exported_property_type": "_body"},
"Image": {"extension": None, "exported_property_type": "data"},
"File": {"extension": None, "exported_property_type": "data"},
"DTMLMethod": {"extension": None, "exported_property_type": "raw"},
"SQL": {"extension": '.sql', "exported_property_type": "src"},
"Spreadsheet": {"extension": None, "exported_property_type": "data"},
"PDF": {"extension": '.pdf', "exported_property_type": "data"}
}
return class_name_and_exported_extension_dict
def getPropertyAndExtensionExportedSeparatelyDict(self, document, key):
"""Returns a dictionary with one element in the type of
{exported_property_type: extension}
exported_property_type is the key of the document where the actual data
exists. E.g. for a Extension Component this is 'text_content', while for a
PythonScript it is'_body'.
The extension can be default for some Portal Types, e.g. for PythonScript it
is always '.py', but for others like File guessExtensionOfDocument is used
to identify it.
"""
class_name = document.__class__.__name__
class_name_and_exported_extension_dict = self.getClassNameAndExportedExtensionDict()
if class_name in class_name_and_exported_extension_dict.keys():
extension = class_name_and_exported_extension_dict[class_name]["extension"]
exported_property_type = class_name_and_exported_extension_dict[class_name]["exported_property_type"]
if extension:
return {exported_property_type: extension}
else:
extension = self.guessExtensionOfDocument(document, key, exported_property_type)
if extension:
# if the obtained extension was .xml, change it to ._xml so that it
# would not conflict with th .xml metadata document
if extension == '.xml':
extension = '._xml'
return {exported_property_type: extension}
return {}
def getMimetypesRegistryLookupResultOfContenType(self, content_type):
"""Returns a lookup in mimetypes_registry based on the content_type"""
mimetypes_registry = self.getPortalObject().mimetypes_registry
try:
return mimetypes_registry.lookup(content_type)
except MimeTypeException:
return
def guessExtensionOfDocument(self, document, key, exported_property_type=None):
"""Guesses and returns the extension of an ERP5 document.
The process followed is:
1. Try to guess extension by content type
2. Try to guess extension by the id of the document
3. Try to guess extension by the title of the document
4. Try to guess extension by the reference of the document
5. In the case of an image, try to guess extension by Base64 representation
In case everything fails then:
- '.bin' is returned for binary files
- '.txt' is returned for text
"""
# XXX Zope items like DTMLMethod would not
# implement getContentType method
extension = None
binary = 'not_identified'
if hasattr(document, 'getContentType'):
content_type = document.getContentType()
lookup_result = self.getMimetypesRegistryLookupResultOfContenType(content_type)
if lookup_result:
# return first registered Extension (if any)
if lookup_result[0].extensions:
extension = lookup_result[0].extensions[0]
# If there is no extension return the first registered Glob (if any)
elif lookup_result[0].globs:
extension = str(lookup_result[0].globs[0]).replace('*', '')
if hasattr(lookup_result[0], 'binary'):
binary = lookup_result[0].binary
if extension:
if not extension.startswith('.'):
extension = '.'+extension
return extension
# Try to guess the extension based on the id of the document
mime = MimeTypes()
mime_type = mime.guess_type(key)
if mime_type[0]:
extension = guess_extension(mime_type[0])
return extension
# Try to guess the extension based on the reference of the document
mime = MimeTypes()
if hasattr(document, 'getReference'):
reference = document.getReference()
if reference:
mime_type = mime.guess_type(reference)
if mime_type[0]:
extension = guess_extension(mime_type[0])
return extension
# Try to guess the extension based on the title of the document
if hasattr(document, 'title'):
mime_type = mime.guess_type(document.title)
if mime_type[0]:
extension = guess_extension(mime_type[0])
return extension
# Try to get type of image from its base64 encoding
if exported_property_type == 'data':
# XXX maybe decoding the whole file just for the extension is an overkill
data = str(document.__dict__.get('data'))
try:
decoded_data = base64.decodestring(data)
for test in imghdr.tests:
extension = test(decoded_data, None)
if extension:
return '.'+extension
except binascii.Error:
LOG('BusinessTemplate ', 0, 'data is not base 64')
# in case we could not read binary flag from mimetypes_registry then return
# '.bin' for all the Portal Types where exported_property_type is data
# (File, Image, Spreadsheet). Otherwise, return .bin if binary was returned
# as 1.
if (binary == 'not_identified' and exported_property_type == 'data') or \
binary == 1:
return '.bin'
# in all other cases return .txt
return '.txt'
def export(self, context, bta, catalog_method_template_item = 0, **kw):
""" """
Export the business template : fill the BusinessTemplateArchive with Export the business template : fill the BusinessTemplateArchive with
objects exported as XML, hierarchicaly organised. objects exported as XML, hierarchicaly organised.
""" """
if len(self._objects.keys()) == 0: if len(self._objects.keys()) == 0:
return return
path = self.__class__.__name__ path = self.__class__.__name__+ '/'
for key, obj in self._objects.iteritems(): for key, obj in self._objects.iteritems():
# export object in xml class_name=obj.__class__.__name__
property_and_extension_exported_separately_dict = self.getPropertyAndExtensionExportedSeparatelyDict(obj, key)
# Back compatibility with filesystem Documents
if isinstance(obj, str):
if not key.startswith(path):
key = path + key
bta.addObject(obj, name=key, ext='.py')
else:
if property_and_extension_exported_separately_dict:
for record_id, record in property_and_extension_exported_separately_dict.iteritems():
extension = record
exported_property_type = record_id
if hasattr(obj, exported_property_type):
exported_property = getattr(obj, exported_property_type)
if isinstance(exported_property, unicode):
exported_property = str(exported_property.encode('utf-8'))
elif not isinstance(exported_property, str):
exported_property = str(exported_property)
reset_output_encoding = False
if hasattr(obj, 'output_encoding'):
reset_output_encoding = True
output_encoding = obj.output_encoding
obj = obj._getCopy(context)
f = StringIO(exported_property)
bta.addObject(f, key, path=path, ext=extension)
# since we get the obj from context we should
# again remove useless properties
obj = self.removeProperties(obj, 1, keep_workflow_history = True)
# in case the related Portal Type does not exist, the object may be broken.
# So we cannot delattr, but we can delet the het of its its broken state
if isinstance(obj, ERP5BaseBroken):
del obj.__Broken_state__[exported_property_type]
if reset_output_encoding:
self._objects[obj_key].__Broken_state__['output_encoding'] = output_encoding
obj._p_changed = 1
else:
delattr(obj, exported_property_type)
if reset_output_encoding:
obj.output_encoding = output_encoding
transaction.savepoint(optimistic=True)
f = StringIO() f = StringIO()
XMLExportImport.exportXML(obj._p_jar, obj._p_oid, f) XMLExportImport.exportXML(obj._p_jar, obj._p_oid, f)
bta.addObject(f, key, path=path) bta.addObject(f, key, path=path)
if catalog_method_template_item:
# add all datas specific to catalog inside one file
xml_data = self.generateXml(key)
bta.addObject(xml_data, key + '.catalog_keys', path=path)
def _importFile(self, file_name, file_obj, catalog_method_template_item = 0):
transactional_variable = getTransactionalVariable()
obj_key, file_ext = os.path.splitext(file_name)
# id() for installing several bt5 in the same transaction
transactional_variable_obj_key = "%s-%s" % (id(self), obj_key)
if file_ext != '.xml':
# if the document has not been migrated yet (its class is file and
# it is not in portal_components) use legacy importer
if issubclass(self.__class__, FilesystemDocumentTemplateItem) and file_obj.name.rsplit(os.path.sep, 2)[-2] != 'portal_components':
FilesystemDocumentTemplateItem._importFile(self, file_name, file_obj)
else:
# For ZODB Components: if .xml have been processed before, set the
# source code property, otherwise store it in a transactional variable
# so that it can be set once the .xml has been processed
file_obj_content = file_obj.read()
try:
obj = self._objects[obj_key]
except KeyError:
transactional_variable[transactional_variable_obj_key] = file_obj_content
else:
obj_class_name = obj.__class__.__name__
exported_property_type = self.getClassNameAndExportedExtensionDict()[obj_class_name]['exported_property_type']
# if we have instance of InitGhostBase, 'unghost' it so we can
# identify if it is broken
if isinstance(self._objects[obj_key], InitGhostBase):
self._objects[obj_key].__class__.loadClass()
# in case the Portal Type does not exist, the object may be broken.
# So we cannot setattr, but we can change the attribute in its broken state
if isinstance(self._objects[obj_key], ERP5BaseBroken):
self._objects[obj_key].__Broken_state__[exported_property_type] = file_obj_content
self._objects[obj_key]._p_changed = 1
else:
setattr(self._objects[obj_key], exported_property_type, file_obj_content)
self._objects[obj_key] = self.removeProperties(self._objects[obj_key], 1, keep_workflow_history = True)
else:
connection = self.getConnection(self.aq_parent)
__traceback_info__ = 'Importing %s' % file_name
if hasattr(cache_database, 'db') and isinstance(file_obj, file):
obj = connection.importFile(self._compileXML(file_obj))
else:
# FIXME: Why not use the importXML function directly? Are there any BT5s
# with actual .zexp files on the wild?
obj = connection.importFile(file_obj, customImporters=customImporters)
self._objects[obj_key] = obj
if transactional_variable.get(transactional_variable_obj_key, None) != None:
obj_class_name = obj.__class__.__name__
exported_property_type = self.getClassNameAndExportedExtensionDict()[obj_class_name]['exported_property_type']
# if we have instance of InitGhostBase, 'unghost' it so we can
# identify if it is broken
if isinstance(self._objects[obj_key], InitGhostBase):
self._objects[obj_key].__class__.loadClass()
# in case the related Portal Type does not exist, the object may be broken.
# So we cannot setattr, but we can change the attribute in its broken state
if isinstance(self._objects[obj_key], ERP5BaseBroken):
self._objects[obj_key].__Broken_state__[exported_property_type] = transactional_variable[transactional_variable_obj_key]
self._objects[obj_key]._p_changed = 1
else:
setattr(self._objects[obj_key], exported_property_type, transactional_variable[transactional_variable_obj_key])
self._objects[obj_key] = self.removeProperties(self._objects[obj_key], 1, keep_workflow_history = True)
# When importing a Business Template, there is no way to determine if it
# has been already migrated or not in __init__() when it does not
# already exist, therefore BaseTemplateItem.__init__() is called which
# does not set _archive with portal_components/ like
# ObjectTemplateItem.__init__()
# XXX - the above comment is a bit unclear,
# still not sure if this is handled correctly
if file_obj.name.rsplit(os.path.sep, 2)[-2] == 'portal_components':
self._archive[obj_key] = None
try:
del self._archive[obj_key[len('portal_components/'):]]
except KeyError:
pass
if catalog_method_template_item:
self.removeProperties(obj, 0)
def build_sub_objects(self, context, id_list, url, **kw): def build_sub_objects(self, context, id_list, url, **kw):
# XXX duplicates code from build # XXX duplicates code from build
p = context.getPortalObject() p = context.getPortalObject()
...@@ -820,21 +1086,6 @@ class ObjectTemplateItem(BaseTemplateItem): ...@@ -820,21 +1086,6 @@ class ObjectTemplateItem(BaseTemplateItem):
return connection return connection
obj = obj.aq_parent obj = obj.aq_parent
def _importFile(self, file_name, file_obj):
# import xml file
if not file_name.endswith('.xml'):
LOG('Business Template', 0, 'Skipping file "%s"' % (file_name, ))
return
connection = self.getConnection(self.aq_parent)
__traceback_info__ = 'Importing %s' % file_name
if hasattr(cache_database, 'db') and isinstance(file_obj, file):
obj = connection.importFile(self._compileXML(file_obj))
else:
# FIXME: Why not use the importXML function directly? Are there any BT5s
# with actual .zexp files on the wild?
obj = connection.importFile(file_obj, customImporters=customImporters)
self._objects[file_name[:-4]] = obj
def preinstall(self, context, installed_item, **kw): def preinstall(self, context, installed_item, **kw):
modified_object_list = {} modified_object_list = {}
upgrade_list = [] upgrade_list = []
...@@ -2718,19 +2969,7 @@ class CatalogMethodTemplateItem(ObjectTemplateItem): ...@@ -2718,19 +2969,7 @@ class CatalogMethodTemplateItem(ObjectTemplateItem):
if catalog is None: if catalog is None:
LOG('BusinessTemplate, export', 0, 'no SQL catalog was available') LOG('BusinessTemplate, export', 0, 'no SQL catalog was available')
return return
ObjectTemplateItem.export(self, context, bta, catalog_method_template_item=1)
if len(self._objects.keys()) == 0:
return
path = self.__class__.__name__
for key in self._objects.keys():
obj = self._objects[key]
# export object in xml
f=StringIO()
XMLExportImport.exportXML(obj._p_jar, obj._p_oid, f)
bta.addObject(f, key, path=path)
# add all datas specific to catalog inside one file
xml_data = self.generateXml(key)
bta.addObject(xml_data, key + '.catalog_keys', path=path)
def install(self, context, trashbin, **kw): def install(self, context, trashbin, **kw):
ObjectTemplateItem.install(self, context, trashbin, **kw) ObjectTemplateItem.install(self, context, trashbin, **kw)
...@@ -2887,14 +3126,9 @@ class CatalogMethodTemplateItem(ObjectTemplateItem): ...@@ -2887,14 +3126,9 @@ class CatalogMethodTemplateItem(ObjectTemplateItem):
else: else:
# new style key # new style key
self._method_properties.setdefault(id, PersistentMapping())[key] = 1 self._method_properties.setdefault(id, PersistentMapping())[key] = 1
elif file_name.endswith('.xml'):
# just import xml object
connection = self.getConnection(self.aq_parent)
obj = connection.importFile(file, customImporters=customImporters)
self.removeProperties(obj, 0)
self._objects[file_name[:-4]] = obj
else: else:
LOG('Business Template', 0, 'Skipping file "%s"' % (file_name, )) ObjectTemplateItem._importFile(self, file_name, file, catalog_method_template_item=1)
class ActionTemplateItem(ObjectTemplateItem): class ActionTemplateItem(ObjectTemplateItem):
...@@ -3969,73 +4203,13 @@ class DocumentTemplateItem(FilesystemToZodbTemplateItem): ...@@ -3969,73 +4203,13 @@ class DocumentTemplateItem(FilesystemToZodbTemplateItem):
obj.workflow_history[wf_id] = WorkflowHistoryList([wf_history]) obj.workflow_history[wf_id] = WorkflowHistoryList([wf_history])
# XXX temporary should be eliminated from here
def _importFile(self, file_name, file_obj): def _importFile(self, file_name, file_obj):
"""
This will be called once for non-migrated Document and twice for ZODB
Components (for .xml (metadata) and .py (source code)). This code MUST
consider both bt5 folder (everything is on the FS) and tarball (where in
case of ZODB Components, .xml may have been processed before .py and vice
versa.
"""
tv = getTransactionalVariable()
obj_key, file_ext = os.path.splitext(file_name)
# id() for installing several bt5 in the same transaction
tv_obj_key = "%s-%s" % (id(self), obj_key)
if file_ext == '.py':
# If this Document has not been migrated yet (eg not matching
# "portal_components/XXX.py"), use legacy importer
if file_obj.name.rsplit(os.path.sep, 2)[-2] != 'portal_components':
FilesystemDocumentTemplateItem._importFile(self, file_name, file_obj)
# For ZODB Components: if .xml have been processed before, set the
# source code property, otherwise store it in a transactional variable
# so that it can be set once the .xml has been processed
else:
text_content = file_obj.read()
try:
obj = self._objects[obj_key]
except KeyError:
tv[tv_obj_key] = text_content
else:
obj.text_content = text_content
elif file_ext == '.xml':
ObjectTemplateItem._importFile(self, file_name, file_obj) ObjectTemplateItem._importFile(self, file_name, file_obj)
self._objects[obj_key].text_content = tv.get(tv_obj_key, None)
# When importing a Business Template, there is no way to determine if it
# has been already migrated or not in __init__() when it does not
# already exist, therefore BaseTemplateItem.__init__() is called which
# does not set _archive with portal_components/ like
# ObjectTemplateItem.__init__()
self._archive[obj_key] = None
del self._archive[obj_key[len('portal_components/'):]]
else:
LOG('Business Template', 0, 'Skipping file "%s"' % file_name)
# XXX temporary should be eliminated from here
def export(self, context, bta, **kw): def export(self, context, bta, **kw):
""" ObjectTemplateItem.export(self, context, bta, **kw)
Export a Document as two files for ZODB Components, one for metadata
(.xml) and the other for the Python source code (.py)
"""
path = self.__class__.__name__ + '/'
for key, obj in self._objects.iteritems():
# Back compatibility with filesystem Documents
if isinstance(obj, str):
if not key.startswith(path):
key = path + key
bta.addObject(obj, name=key, ext='.py')
else:
obj = obj._getCopy(context)
f = StringIO(obj.text_content)
bta.addObject(f, key, path=path, ext='.py')
del obj.text_content
transaction.savepoint(optimistic=True)
# export object in xml
f = StringIO()
XMLExportImport.exportXML(obj._p_jar, obj._p_oid, f)
bta.addObject(f, key, path=path)
def getTemplateIdList(self): def getTemplateIdList(self):
""" """
......
...@@ -62,7 +62,7 @@ from zLOG import LOG, INFO, WARNING ...@@ -62,7 +62,7 @@ from zLOG import LOG, INFO, WARNING
from base64 import decodestring from base64 import decodestring
import subprocess import subprocess
import time import time
from distutils.dir_util import copy_tree
WIN = os.name == 'nt' WIN = os.name == 'nt'
...@@ -461,6 +461,72 @@ class TemplateTool (BaseTool): ...@@ -461,6 +461,72 @@ class TemplateTool (BaseTool):
""" """
return self.getFilteredDiff(diff).toHTML() return self.getFilteredDiff(diff).toHTML()
def _cleanUpTemplateFolder(self, folder_path):
for file_object in os.listdir(folder_path):
file_object_path = os.path.join(folder_path, file_object)
if os.path.isfile(file_object_path):
os.unlink(file_object_path)
else:
shutil.rmtree(file_object_path)
def _importAndReExportBusinessTemplate(self, template_path):
"""
Imports the template that is in the template_path and exports it to the
same path.
We want to clean this directory, i.e. remove all files before
the export. Because this is called as activity though, it could cause
the following problem:
- Activity imports the template
- Activity removes all files from template_path
- Activity fails in export.
Then the folder contents will be changed, so when retrying the
activity may succeed without the user understanding that files were
erased. For this reason export is done in 3 steps:
- First to a temporary directory
- If there was no error delete contents of template_path
- Copy the contents of the temporary directory to the template_path
"""
import_template = self.download(url=template_path)
export_dir = mkdtemp()
try:
import_template.export(path=export_dir, local=True)
self._cleanUpTemplateFolder(template_path)
copy_tree(export_dir, template_path)
except:
raise
finally:
shutil.rmtree(export_dir)
security.declareProtected( 'Import/Export objects', 'importAndReExportBusinessTemplatesFromPath' )
def importAndReExportBusinessTemplatesFromPath(self, repository_list, REQUEST=None, **kw):
"""
Migrate business templates to new format where files like .py or .html
are exported seprately than the xml.
"""
repository_list = filter(bool, repository_list)
if REQUEST is None:
REQUEST = getattr(self, 'REQUEST', None)
if len(repository_list) == 0 and REQUEST:
ret_url = self.absolute_url()
REQUEST.RESPONSE.redirect("%s?portal_status_message=%s"
% (ret_url, 'No repository was defined'))
for repository in repository_list:
repository = repository.rstrip('\n')
repository = repository.rstrip('\r')
for business_template_id in os.listdir(repository):
template_path = os.path.join(repository, business_template_id)
if os.path.isfile(template_path):
LOG(business_template_id,0,'is file, so it is skipped')
else:
if not os.path.exists((os.path.join(template_path, 'bt'))):
LOG(business_template_id,0,'has no bt sub-folder, so it is skipped')
else:
self.activate(activity='SQLQueue')._importAndReExportBusinessTemplate(template_path)
security.declareProtected(Permissions.ManagePortal, 'getFilteredDiff') security.declareProtected(Permissions.ManagePortal, 'getFilteredDiff')
def getFilteredDiff(self, diff): def getFilteredDiff(self, diff):
""" """
......
...@@ -7546,10 +7546,6 @@ class TestDocumentTemplateItem(BusinessTemplateMixin): ...@@ -7546,10 +7546,6 @@ class TestDocumentTemplateItem(BusinessTemplateMixin):
self.assertNotEqual(wf_history_dict.get('actor'), None) self.assertNotEqual(wf_history_dict.get('actor'), None)
self.assertNotEqual(wf_history_dict.get('comment'), None) self.assertNotEqual(wf_history_dict.get('comment'), None)
def stepRemoveZodbDocument(self, sequence=None, **kw):
self.getPortalObject().portal_components.deleteContent(
sequence['document_id'])
def stepCheckZodbDocumentExistsAndValidated(self, sequence=None, **kw): def stepCheckZodbDocumentExistsAndValidated(self, sequence=None, **kw):
component = getattr(self.getPortalObject().portal_components, component = getattr(self.getPortalObject().portal_components,
sequence['document_id'], None) sequence['document_id'], None)
......
# -*- coding: utf-8 -*-
##############################################################################
#
# Copyright (c) 2005 Nexedi SARL and Contributors. All Rights Reserved.
# Aurelien Calonne <aurel@nexedi.com>
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsibility of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
# End users who are looking for a ready-to-use solution with commercial
# guarantees and support are strongly adviced to contract a Free Software
# Service Company
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
##############################################################################
from Products.ERP5Type.tests.ERP5TypeTestCase import ERP5TypeTestCase
from App.config import getConfiguration
import shutil
import os
import tempfile
class TestBusinessTemplateTwoFileExport(ERP5TypeTestCase):
"""
Test export and import of business templates with files (e.g. Web Script)
- Create a template
- Create a file
- Build and export the template
- Check that the expected files are exported
- Import the exported template and install it
- Check that the files are imported properly
"""
def getBusinessTemplateList(self):
return ['erp5_core_proxy_field_legacy',
'erp5_property_sheets',
'erp5_jquery',
'erp5_full_text_mroonga_catalog',
'erp5_base',
'erp5_core',
'erp5_ingestion_mysql_innodb_catalog',
'erp5_ingestion',
'erp5_xhtml_style',
'erp5_web',
'erp5_hal_json_style',
'erp5_dms',
'erp5_web_renderjs_ui'
]
def afterSetUp(self):
self.cfg = getConfiguration()
self.export_dir = tempfile.mkdtemp()
self.template_tool = self.getTemplateTool()
self.template = self._createNewBusinessTemplate(self.template_tool)
def beforeTearDown(self):
export_dir_path = os.path.join(self.cfg.instancehome, self.export_dir)
if os.path.exists(export_dir_path):
shutil.rmtree(self.export_dir)
def _createNewBusinessTemplate(self, template_tool):
template = template_tool.newContent(portal_type='Business Template')
self.assertTrue(template.getBuildingState() == 'draft')
self.assertTrue(template.getInstallationState() == 'not_installed')
template.edit(title ='test_template',
version='1.0',
description='bt for unit_test')
return template
def _buildAndExportBusinessTemplate(self):
self.tic()
self.template.build()
self.tic()
self.template.export(path=self.export_dir, local=True)
self.tic()
def _importBusinessTemplate(self):
template_id = self.template.getId()
template_path = os.path.join(self.cfg.instancehome, self.export_dir)
self.template_tool.manage_delObjects(template_id)
import_template = self.template_tool.download(url='file:'+template_path)
self.assertFalse(import_template is None)
self.assertEqual(import_template.getPortalType(), 'Business Template')
return import_template
def _exportAndReImport(self, xml_document_path,
file_document_path, data, removed_property_list):
self._buildAndExportBusinessTemplate()
self.assertTrue(os.path.exists(xml_document_path))
self.assertTrue(os.path.exists(file_document_path))
test_file=open(file_document_path,'r+')
self.assertEqual(test_file.read(), data)
test_file.close()
xml_file=open(xml_document_path,'r+')
xml_file_content = xml_file.read()
xml_file.close()
for exported_property in removed_property_list:
self.assertFalse('<string>'+exported_property+'</string>' in xml_file_content)
import_template = self._importBusinessTemplate()
return import_template
def test_twoFileImportExportForTestDocument(self):
"""Test Business Template Import And Export With Test Document"""
test_component_kw = {"title": "foo",
"text_content": "def dummy(): pass",
"portal_type": "Test Component"}
test_document_page = self.portal.portal_components.newContent(**test_component_kw)
test_component_kw['id'] = test_component_id = test_document_page.getId()
self.template.edit(template_test_id_list=['portal_components/'+test_component_id,])
test_component_path = os.path.join(self.cfg.instancehome, self.export_dir,
'TestTemplateItem', 'portal_components',
test_component_id)
import_template = self._exportAndReImport(
test_component_path + ".xml",
test_component_path +".py",
test_component_kw["text_content"],
['text_content'])
self.portal.portal_components.manage_delObjects([test_component_id])
import_template.install()
test_page = self.portal.portal_components[test_component_id]
for property_id, property_value in test_component_kw.iteritems():
self.assertEqual(test_page.getProperty(property_id), property_value)
def test_twoFileImportExportForWebPage(self):
"""Test Business Template Import And Export With Web Page"""
html_document_kw = {"title": "foo", "text_content": "<html></html>",
"portal_type": "Web Page"}
html_page = self.portal.web_page_module.newContent(**html_document_kw)
js_document_kw = {"title": "foo.js", "text_content": "// JavaScript",
"portal_type": "Web Script"}
js_page = self.portal.web_page_module.newContent(**js_document_kw)
css_document_kw = {"title": "foo.css", "text_content": "<style></style>",
"portal_type": "Web Style"}
css_page = self.portal.web_page_module.newContent(**css_document_kw)
html_document_kw['id'] = html_file_id = html_page.getId()
js_document_kw['id'] = js_file_id = js_page.getId()
css_document_kw['id'] = css_file_id = css_page.getId()
self.template.edit(template_path_list=['web_page_module/'+html_file_id,
'web_page_module/'+js_file_id,
'web_page_module/'+css_file_id,])
self._buildAndExportBusinessTemplate()
web_page_module_path = os.path.join(self.cfg.instancehome, self.export_dir,
'PathTemplateItem', 'web_page_module')
for web_file in [(html_file_id, '.html', html_document_kw),
(js_file_id, '.js', js_document_kw),
(css_file_id, '.css', css_document_kw)]:
xml_document_path = os.path.join(web_page_module_path, web_file[0]+'.xml')
file_document_path = os.path.join(web_page_module_path,
web_file[0]+web_file[1])
self.assertTrue(os.path.exists(xml_document_path))
self.assertTrue(os.path.exists(file_document_path))
file_content=open(file_document_path,'r+')
self.assertEqual(file_content.read(), web_file[2]["text_content"])
xml_file=open(xml_document_path,'r+')
self.assertFalse('<string>text_content</string>' in xml_file.read())
import_template = self._importBusinessTemplate()
self.portal.web_page_module.manage_delObjects([html_file_id])
self.portal.web_page_module.manage_delObjects([js_file_id])
self.portal.web_page_module.manage_delObjects([css_file_id])
import_template.install()
for web_file in [(html_file_id, html_document_kw),
(js_file_id, js_document_kw),
(css_file_id, css_document_kw)]:
web_page = self.portal.web_page_module[web_file[0]]
for property_id, property_value in web_file[1].iteritems():
self.assertEqual(web_page.getProperty(property_id), property_value)
def test_twoFileImportExportForPythonScript(self):
"""Test Business Template Import And Export With PythonScript"""
skin_folder_id = 'dummy_test_folder'
if skin_folder_id in self.portal.portal_skins.objectIds():
self.portal.portal_skins.manage_delObjects([skin_folder_id])
self.portal.portal_skins.manage_addProduct['OFSP'].manage_addFolder(skin_folder_id)
skin_folder = self.portal.portal_skins[skin_folder_id]
python_script_id = 'dummy_test_script'
if python_script_id in skin_folder.objectIds():
skin_folder.manage_delObjects([python_script_id])
skin_folder.manage_addProduct['PythonScripts'].manage_addPythonScript(id=python_script_id)
python_script = skin_folder[python_script_id]
python_script.ZPythonScript_edit('', "context.setTitle('foo')")
python_script_kw = {"_body": "context.setTitle('foo')\n",}
self.template.edit(template_skin_id_list=[skin_folder_id+'/'+python_script_id,])
python_script_path = os.path.join(self.cfg.instancehome, self.export_dir,
'SkinTemplateItem', 'portal_skins',skin_folder_id,python_script_id)
import_template = self._exportAndReImport(
python_script_path+".xml",
python_script_path+".py",
python_script_kw["_body"],
['_body','_code'])
self.portal.portal_skins[skin_folder_id].manage_delObjects([python_script_id])
import_template.install()
python_script_page = self.portal.portal_skins[skin_folder_id][python_script_id]
python_script_content = python_script_page.read()
self.assertTrue(python_script_content.endswith(python_script_kw['_body']))
def _checkTwoFileImportExportForImageInImageModule(self,
image_document_kw,
extension):
image_page = self.portal.image_module.newContent(**image_document_kw)
image_document_kw['id'] = image_file_id = image_page.getId()
self.template.edit(template_path_list=['image_module/'+image_file_id,])
image_document_path = os.path.join(self.cfg.instancehome, self.export_dir,
'PathTemplateItem', 'image_module',image_file_id)
import_template = self._exportAndReImport(
image_document_path+".xml",
image_document_path+extension,
image_document_kw["data"],
['data'])
self.portal.image_module.manage_delObjects([image_file_id])
import_template.install()
image_page = self.portal.image_module[image_file_id]
for property_id, property_value in image_document_kw.iteritems():
self.assertEqual(image_page.getProperty(property_id), property_value)
def test_twoFileImportExportForImageIdentifyingTypeByBase64(self):
"""
Test Business Template Import And Export With Image In Image Module
where extension is found by Base64 representation
"""
image_data = """iVBORw0KGgoAAAANSUhEUgAAAAUA
AAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO
9TXL0Y4OHwAAAABJRU5ErkJggg=="""
image_document_kw = {"title": "foo", "data": image_data,
"portal_type": "Image"}
self._checkTwoFileImportExportForImageInImageModule(image_document_kw, '.png')
def test_twoFileImportExportForImageIdentifyingTypeByContentType(self):
"""
Test Business Template Import And Export With Image In Image Module
where extension (.pjpg) is found by content_type
"""
image_data = """MalformedBase64HereiVBORw0KGgoAAAANSUhEUgAAAAUA
AAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO
9TXL0Y4OHwAAAABJRU5ErkJggg=="""
image_document_kw = {"title": "foo", "data": image_data,
"portal_type": "Image", "content_type": "image/jpeg"}
self._checkTwoFileImportExportForImageInImageModule(image_document_kw,
'.pjpg')
def test_twoFileImportExportForImageNotIdentifyingType(self):
"""
Test Business Template Import And Export With Image In Image Module
where extension is not identified, so it is exported as '.bin'
"""
image_data = """MalformedBase64HereiVBORw0KGgoAAAANSUhEUgAAAAUA
AAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO
9TXL0Y4OHwAAAABJRU5ErkJggg=="""
image_document_kw = {"title": "foo", "data": image_data,
"portal_type": "Image"}
self._checkTwoFileImportExportForImageInImageModule(image_document_kw,
'.bin')
def _checkTwoFileImportExportForDocumentInDocumentModule(self,
file_document_kw,
extension):
file_page = self.portal.document_module.newContent(**file_document_kw)
file_document_kw['id'] = file_id = file_page.getId()
self.template.edit(template_path_list=['document_module/'+file_id,])
file_document_path = os.path.join(self.cfg.instancehome, self.export_dir,
'PathTemplateItem', 'document_module',
file_id)
import_template = self._exportAndReImport(
file_document_path+".xml",
file_document_path+extension,
file_document_kw["data"],
['data'])
self.portal.document_module.manage_delObjects([file_id])
import_template.install()
file_page = self.portal.document_module[file_id]
for property_id, property_value in file_document_kw.iteritems():
self.assertEqual(getattr(file_page, property_id), property_value)
def test_twoFileImportExportForFileIdentifyingTypeByContentTypeJS(self):
"""
Test Business Template Import And Export With File
where extension (.js) is identified by the content_type
"""
file_content = "a test file"
file_content_type = "text/javascript"
file_title = "foo"
file_document_kw = {"title": file_title, "data": file_content,
"content_type": file_content_type,
"portal_type": "File"}
self._checkTwoFileImportExportForDocumentInDocumentModule(file_document_kw,
'.js')
def test_twoFileImportExportForFileIdentifyingTypeByContentTypeObj(self):
"""
Test Business Template Import And Export With File
where extension (.obj) is identified by the content_type
"""
file_content = "a test file"
file_content_type = "application/octet-stream"
file_title = "foo"
file_document_kw = {"title": file_title, "data": file_content,
"content_type": file_content_type,
"portal_type": "File"}
self._checkTwoFileImportExportForDocumentInDocumentModule(file_document_kw,
'.obj')
def test_twoFileImportExportForFileIdentifyingTypeByContentTypeEpub(self):
"""
Test Business Template Import And Export With File
where extension (.epub) is identified by the content_type
"""
file_content = "a test file"
file_content_type = "application/epub+zip"
file_title = "foo"
file_document_kw = {"title": file_title, "data": file_content,
"content_type": file_content_type,
"portal_type": "File"}
self._checkTwoFileImportExportForDocumentInDocumentModule(file_document_kw,
'.epub')
def test_twoFileImportExportForFileIdentifyingTypeByTitleJS(self):
"""
Test Business Template Import And Export With File
where extension (.js) is identified by the title
"""
file_content = "a test file"
file_title = "foo.js"
file_document_kw = {"title": file_title, "data": file_content,
"portal_type": "File"}
self._checkTwoFileImportExportForDocumentInDocumentModule(file_document_kw,
'.js')
def test_twoFileImportExportForFileIdentifyingTypeByReferenceJS(self):
"""
Test Business Template Import And Export With File
where extension (.js) is identified by the reference
"""
file_content = "<script> ... </script>"
file_title = "foo"
file_document_kw = {"title": file_title, "data": file_content,
"default_reference": file_title+".js",
"portal_type": "File"}
self._checkTwoFileImportExportForDocumentInDocumentModule(file_document_kw,
'.js')
def test_twoFileImportExportForFileNotIdentifyingTypeEmptyContentType(self):
"""
Test Business Template Import And Export With File
where extension is not identified, so it is exported as .bin
"""
file_content = "a test file"
file_content_type = None
file_title = "foo"
file_document_kw = {"title": file_title, "data": file_content,
"content_type": file_content_type,
"portal_type": "File"}
self._checkTwoFileImportExportForDocumentInDocumentModule(file_document_kw,
'.bin')
def test_twoFileImportExportForFileNotIdentifyingTypeBinaryContentType(self):
"""
Test Business Template Import And Export With File
where extension is not identified by content_type (video/wavelet)
but it is identified as binary in the mimetypes_registry so it is
exported as .bin.
"""
file_content = "a test file"
file_content_type = 'video/wavelet'
file_title = "foo"
file_document_kw = {"title": file_title, "data": file_content,
"content_type": file_content_type,
"portal_type": "File"}
self._checkTwoFileImportExportForDocumentInDocumentModule(file_document_kw,
'.bin')
def test_twoFileImportExportForFileNotIdentifyingTypeNonBinaryContentType(self):
"""
Test Business Template Import And Export With File
where extension is not identified by content_type (text/x-uri)
but it is identified as non-binary in the mimetypes_registry so it is
exported as .txt.
"""
file_content = "a test file"
file_content_type = 'text/x-uri'
file_title = "foo"
file_document_kw = {"title": file_title, "data": file_content,
"content_type": file_content_type,
"portal_type": "File"}
self._checkTwoFileImportExportForDocumentInDocumentModule(file_document_kw,
'.txt')
def test_twoFileImportExportForFileIdentifyingTypeByTitleXML(self):
"""
Test Business Template Import And Export With File in portal skins
where extension (.xml, exported as ._xml to avoid conflict with the meta-data file)
is identified by the title
"""
file_content = """<person>
<name>John</name>
<surname>Doe</surname>
</person>
"""
file_title = "foo.xml"
file_content_type = None
file_document_kw = {"title": file_title, "data": file_content,
"content_type": file_content_type,
"portal_type": "File"}
self._checkTwoFileImportExportForDocumentInDocumentModule(file_document_kw,
'._xml')
def test_twoFileImportExportForFileInPortalSkinsIdentifyingTypeByTitleXML(self):
"""
Test Business Template Import And Export With File in portal skins
where extension (.xml, exported as ._xml to avoid conflict with the meta-data file)
is identified by the title
"""
file_content = """<person>
<name>John</name>
<surname>Doe</surname>
</person>
"""
file_title = "foo.xml"
file_document_kw = {"title": file_title, "data": file_content,}
skin_folder_id = 'dummy_test_folder'
if skin_folder_id in self.portal.portal_skins.objectIds():
self.portal.portal_skins.manage_delObjects([skin_folder_id])
self.portal.portal_skins.manage_addProduct['OFSP'].\
manage_addFolder(skin_folder_id)
skin_folder = self.portal.portal_skins[skin_folder_id]
test_file_id = 'dummy_file_id'
if test_file_id in self.portal.objectIds():
self.portal.manage_delObjects([test_file_id])
skin_folder.manage_addProduct['OFSP'].manage_addFile(id=test_file_id)
zodb_file = skin_folder._getOb(test_file_id)
zodb_file.manage_edit(title=file_title,
content_type='',
filedata=file_content)
self.template.edit(template_skin_id_list=[skin_folder_id+'/'+test_file_id,])
file_document_path = os.path.join(self.cfg.instancehome, self.export_dir,
'SkinTemplateItem', 'portal_skins',
skin_folder_id,test_file_id)
import_template = self._exportAndReImport(
file_document_path+".xml",
file_document_path+"._xml",
file_document_kw["data"],
['data'])
self.portal.portal_skins[skin_folder_id].manage_delObjects([test_file_id])
import_template.install()
file_page = self.portal.portal_skins[skin_folder_id][test_file_id]
for property_id, property_value in file_document_kw.iteritems():
self.assertEqual(getattr(file_page, property_id), property_value)
def test_twoFileImportExportForPDF(self):
"""Test Business Template Import And Export With A PDF Document"""
pdf_data = """pdf content, maybe should update for base64 sample"""
pdf_document_kw = {"title": "foo.pdf", "data": pdf_data,
"portal_type": "PDF"}
self._checkTwoFileImportExportForDocumentInDocumentModule(pdf_document_kw,
'.pdf')
def test_twoFileImportExportForCatalogMethodInCatalog(self):
"""Test Business Template Import And Export With Catalog Method In Catalog"""
catalog_tool = self.getCatalogTool()
catalog = catalog_tool.getSQLCatalog()
catalog_id = catalog.id
self.assertTrue(catalog is not None)
method_id = "z_another_dummy_method"
if method_id in catalog.objectIds():
catalog.manage_delObjects([method_id])
method_document_kw = {'id': method_id, 'title': 'dummy_method_title',
'connection_id': 'erp5_sql_connection',
'arguments_src': 'args', 'src': 'dummy_method_template'}
addSQLMethod = catalog.manage_addProduct['ZSQLMethods'].manage_addZSQLMethod
addSQLMethod(id=method_id, title='dummy_method_title',
connection_id='erp5_sql_connection',
template='dummy_method_template',
arguments = 'args'
)
zsql_method = catalog._getOb(method_id, None)
self.assertTrue(zsql_method is not None)
self.template.edit(template_catalog_method_id_list=[catalog_id+'/'+method_id])
self._buildAndExportBusinessTemplate()
method_document_path = os.path.join(self.cfg.instancehome, self.export_dir,
'CatalogMethodTemplateItem',
'portal_catalog',
catalog_id, method_id)
import_template = self._exportAndReImport(
method_document_path + ".xml",
method_document_path +".sql",
'dummy_method_template',
['src'])
catalog.manage_delObjects([method_id])
import_template.install()
method_page = catalog[method_id]
for property_id, property_value in method_document_kw.iteritems():
self.assertEqual(getattr(method_page, property_id), property_value)
def test_twoFileImportExportForCatalogMethodInPortalSkins(self):
"""Test Business Template Import And Export With Catalog Method In Portal Skins"""
method_id = "z_another_dummy_method"
method_document_kw = {'id': method_id, 'title': 'dummy_method_title',
'connection_id': 'erp5_sql_connection',
'arguments_src': 'args', 'src': 'dummy_method_template'}
skin_folder_id = 'dummy_test_folder'
if skin_folder_id in self.portal.portal_skins.objectIds():
self.portal.portal_skins.manage_delObjects([skin_folder_id])
self.portal.portal_skins.manage_addProduct['OFSP'].\
manage_addFolder(skin_folder_id)
skin_folder = self.portal.portal_skins[skin_folder_id]
if method_id in self.portal.objectIds():
self.portal.manage_delObjects([method_id])
addSQLMethod = skin_folder.manage_addProduct['ZSQLMethods'].manage_addZSQLMethod
addSQLMethod(id=method_id, title='dummy_method_title',
connection_id='erp5_sql_connection',
template='dummy_method_template',
arguments = 'args'
)
self.template.edit(template_skin_id_list=[skin_folder_id+'/'+method_id,])
method_document_path = os.path.join(self.cfg.instancehome, self.export_dir,
'SkinTemplateItem', 'portal_skins',
skin_folder_id, method_id)
import_template = self._exportAndReImport(
method_document_path+".xml",
method_document_path+".sql",
'dummy_method_template',
['src'])
self.portal.portal_skins[skin_folder_id].manage_delObjects([method_id])
import_template.install()
method_page = skin_folder[method_id]
for property_id, property_value in method_document_kw.iteritems():
self.assertEqual(getattr(method_page, property_id), property_value)
def test_twoFileImportExportForZopePageTemplate(self):
"""Test Business Template Import And Export With ZopePageTemplate"""
skin_folder_id = 'dummy_test_folder'
if skin_folder_id in self.portal.portal_skins.objectIds():
self.portal.portal_skins.manage_delObjects([skin_folder_id])
self.portal.portal_skins.manage_addProduct['OFSP'].\
manage_addFolder(skin_folder_id)
skin_folder = self.portal.portal_skins[skin_folder_id]
page_template_id = 'dummy_page_template'
if page_template_id in skin_folder.objectIds():
skin_folder.manage_delObjects([page_template_id])
page_template_text = '<html></html>'
page_template_kw = {"id": page_template_id,
"_text": page_template_text,
"content_type": "text/html",
"output_encoding": "utf-8"}
skin_folder.manage_addProduct['PageTemplates'].\
manage_addPageTemplate(id=page_template_id,
text=page_template_text)
self.template.edit(template_skin_id_list=[skin_folder_id+'/'+page_template_id,])
page_template_path = os.path.join(self.cfg.instancehome, self.export_dir,
'SkinTemplateItem', 'portal_skins',skin_folder_id,page_template_id)
import_template = self._exportAndReImport(
page_template_path+".xml",
page_template_path+".zpt",
page_template_kw['_text'],
['_text'])
self.portal.portal_skins[skin_folder_id].manage_delObjects([page_template_id])
import_template.install()
page_template_page = self.portal.portal_skins[skin_folder_id][page_template_id]
for property_id, property_value in page_template_kw.iteritems():
self.assertEqual(getattr(page_template_page, property_id), property_value)
def test_twoFileImportExportForDTMLMethodIdentifyingTypeByTitle(self):
"""
Test Business Template Import And Export With DTMLMethod where the
extension is identified by the title
"""
skin_folder_id = 'dummy_test_folder'
if skin_folder_id in self.portal.portal_skins.objectIds():
self.portal.portal_skins.manage_delObjects([skin_folder_id])
self.portal.portal_skins.manage_addProduct['OFSP'].manage_addFolder(skin_folder_id)
skin_folder = self.portal.portal_skins[skin_folder_id]
dtml_method_id = 'dummy_dtml_method'
dtml_method_title = 'dummy_dtml_method.js'
dtml_method_data = 'dummy content'
dtml_method_kw = {"__name__": dtml_method_id,
"title": dtml_method_title,
"raw": dtml_method_data}
if dtml_method_id in skin_folder.objectIds():
skin_folder.manage_delObjects([dtml_method_id])
skin_folder.manage_addProduct['DTMLMethods'].\
manage_addDTMLMethod(id = dtml_method_id,
title = dtml_method_title)
dtml_method = skin_folder[dtml_method_id]
dtml_method.manage_edit(data=dtml_method_data, title = dtml_method_title)
self.template.edit(template_skin_id_list=[skin_folder_id+'/'+dtml_method_id,])
dtml_method_path = os.path.join(self.cfg.instancehome,
self.export_dir,
'SkinTemplateItem',
'portal_skins',
skin_folder_id,dtml_method_id)
import_template = self._exportAndReImport(
dtml_method_path+".xml",
dtml_method_path+".js",
dtml_method_kw['raw'],
['raw'])
self.portal.portal_skins[skin_folder_id].manage_delObjects([dtml_method_id])
import_template.install()
dtml_method_page = self.portal.portal_skins[skin_folder_id][dtml_method_id]
for property_id, property_value in dtml_method_kw.iteritems():
self.assertEqual(getattr(dtml_method_page, property_id), property_value)
def test_twoFileImportExportForDTMLMethodNotIdentifyingType(self):
"""
Test Business Template Import And Export With DTMLMethod where the
extension is not identified, so it is exported as '.txt'
"""
skin_folder_id = 'dummy_test_folder'
if skin_folder_id in self.portal.portal_skins.objectIds():
self.portal.portal_skins.manage_delObjects([skin_folder_id])
self.portal.portal_skins.manage_addProduct['OFSP'].\
manage_addFolder(skin_folder_id)
skin_folder = self.portal.portal_skins[skin_folder_id]
dtml_method_id = 'dummy_dtml_method'
dtml_method_title = 'dummy_dtml_method'
dtml_method_data = 'dummy content'
dtml_method_kw = {"__name__": dtml_method_id,
"title": dtml_method_title,
"raw": dtml_method_data}
if dtml_method_id in skin_folder.objectIds():
skin_folder.manage_delObjects([dtml_method_id])
skin_folder.manage_addProduct['DTMLMethods'].\
manage_addDTMLMethod(id = dtml_method_id,
title = dtml_method_title)
dtml_method = skin_folder[dtml_method_id]
dtml_method.manage_edit(data=dtml_method_data, title = dtml_method_title)
self.template.edit(template_skin_id_list=[skin_folder_id+'/'+dtml_method_id,])
dtml_method_path = os.path.join(self.cfg.instancehome, self.export_dir,
'SkinTemplateItem', 'portal_skins',
skin_folder_id,dtml_method_id)
import_template = self._exportAndReImport(
dtml_method_path+".xml",
dtml_method_path+".txt",
dtml_method_kw['raw'],
['raw'])
self.portal.portal_skins[skin_folder_id].manage_delObjects([dtml_method_id])
import_template.install()
dtml_method_page = self.portal.portal_skins[skin_folder_id][dtml_method_id]
for property_id, property_value in dtml_method_kw.iteritems():
self.assertEqual(getattr(dtml_method_page, property_id), property_value)
def test_twoFileImportExportForOOoTemplate(self):
"""Test Business Template Import And Export With OOoTemplate"""
skin_folder_id = 'dummy_test_folder'
if skin_folder_id in self.portal.portal_skins.objectIds():
self.portal.portal_skins.manage_delObjects([skin_folder_id])
self.portal.portal_skins.manage_addProduct['OFSP'].\
manage_addFolder(skin_folder_id)
skin_folder = self.portal.portal_skins[skin_folder_id]
OOo_template_id = 'dummy_OOo_template'
OOo_template_data = 'dummy OOotemplate content'
OOo_template_kw = {"id": OOo_template_id,
"_text": OOo_template_data,
"output_encoding": "utf-8",
"content_type": "text/html"}
if OOo_template_id in skin_folder.objectIds():
skin_folder.manage_delObjects([OOo_template_id])
addOOoTemplate =skin_folder.manage_addProduct['ERP5OOo'].addOOoTemplate
addOOoTemplate(id=OOo_template_id, title=OOo_template_data)
self.template.edit(template_skin_id_list=[skin_folder_id+'/'+OOo_template_id,])
OOo_template_path = os.path.join(self.cfg.instancehome, self.export_dir,
'SkinTemplateItem', 'portal_skins',
skin_folder_id, OOo_template_id)
import_template = self._exportAndReImport(
OOo_template_path+".xml",
OOo_template_path+".oot",
OOo_template_kw['_text'],
['_text'])
self.portal.portal_skins[skin_folder_id].manage_delObjects([OOo_template_id])
import_template.install()
OOo_template_page = self.portal.portal_skins[skin_folder_id][OOo_template_id]
for property_id, property_value in OOo_template_kw.iteritems():
self.assertEqual(getattr(OOo_template_page, property_id), property_value)
def test_twoFileImportExportForSpreadsheetNotIdentifyingType(self):
"""
Test Business Template Import And Export With Spreadsheed where the
extension is not identified, so it is exported as '.bin'
"""
# XXX addding a dummy string in data leads to 'NotConvertedError'
spreadsheet_data = ''
spreadsheet_document_kw = {"title": "foo", "data": spreadsheet_data,
"portal_type": "Spreadsheet"}
self._checkTwoFileImportExportForDocumentInDocumentModule(spreadsheet_document_kw,
'.bin')
def test_twoFileImportExportForSpreadsheetIdentifyingTypeByContentType(self):
"""
Test Business Template Import And Export With Spreadsheed where the
extension is identified by content_type, so it is exported as '.ods'
"""
# XXX addding a dummy string in data leads to 'NotConvertedError'
spreadsheet_data = ''
spreadsheet_document_kw = {"title": "foo", "data": spreadsheet_data,
"portal_type": "Spreadsheet",
"content_type": "application/vnd.oasis.opendocument.spreadsheet"}
self._checkTwoFileImportExportForDocumentInDocumentModule(spreadsheet_document_kw,
'.ods')
def test_twoFileImportExportForSpreadsheetIdentifyingTypeByTitle(self):
"""
Test Business Template Import And Export With Spreadsheed where the
extension is identified by title, so it is exported as '.xlsx'
"""
# XXX addding a dummy string in data leads to 'NotConvertedError'
spreadsheet_data = ''
spreadsheet_document_kw = {"title": "foo.xlsx", "data": spreadsheet_data,
"portal_type": "Spreadsheet"}
self._checkTwoFileImportExportForDocumentInDocumentModule(spreadsheet_document_kw,
'.xlsx')
def test_templateFolderIsCleanedUpInImportEndReexport(self):
"""
Test that when TemplateTool.importAndReExportBusinessTemplatesFromPath is
invoked the template folder is cleaned.
1. Create a bt and export it in a temporary folder
2. Add to the folder a text file
3. Add to the folder a sub-folder
4. Add to the sub-folder a second text file
5. Add a third file to portal_templates folder
6. Invoke TemplateTool.importAndReExportBusinessTemplatesFromPath in the
template folder
7. Assert that only the template elements are present
"""
test_component_kw = {"title": "foo",
"text_content": "def dummy(): pass",
"portal_type": "Test Component"}
test_document_page = self.portal.\
portal_components.newContent(**test_component_kw)
test_component_kw['id'] = test_component_id = test_document_page.getId()
self.template.edit(template_test_id_list=['portal_components/'+test_component_id,])
test_component_path = os.path.join(self.cfg.instancehome, self.export_dir,
'TestTemplateItem', 'portal_components',
test_component_id)
self._buildAndExportBusinessTemplate()
self.assertTrue(os.path.exists(os.path.join(self.export_dir, 'bt')))
self.assertTrue(os.path.exists(test_component_path+'.xml'))
self.assertTrue(os.path.exists(test_component_path+'.py'))
# create a text file in the root
text_file_name = "text_file.txt"
text_file_path = os.path.join(self.export_dir, text_file_name)
text_file = open(text_file_path, "w")
text_file.close()
self.assertTrue(os.path.exists(text_file_path))
# create a sub_folder
sub_folder_name = "subfolder"
sub_folder_path = os.path.join(self.export_dir, sub_folder_name)
os.mkdir(sub_folder_path)
self.assertTrue(os.path.exists(sub_folder_path))
# create another text file in the subfolder
text_file_in_sub_folder_name = "text_file_in_sub_folder.txt"
text_file_in_sub_folder_path = os.path.join(self.export_dir,
text_file_in_sub_folder_name)
text_file_in_sub_folder = open(text_file_in_sub_folder_path, "w")
text_file_in_sub_folder.close()
self.assertTrue(os.path.exists(text_file_in_sub_folder_path))
# create another text file inside portal components
text_file_in_portal_components_name = "text_file_in_sub_folder.txt"
text_file_in_portal_components_path = os.path.join(self.export_dir,
text_file_in_portal_components_name)
text_file_in_portal_components = open(text_file_in_sub_folder_path, "w")
text_file_in_portal_components.close()
self.assertTrue(os.path.exists(text_file_in_portal_components_path))
# invoke importAndReExportBusinessTemplatesFromPath
self.template_tool.importAndReExportBusinessTemplatesFromPath(repository_list=['/tmp'])
self.tic()
# assert that unrelated objects were deleted
self.assertFalse(os.path.exists(text_file_path))
self.assertFalse(os.path.exists(sub_folder_path))
self.assertFalse(os.path.exists(text_file_in_sub_folder_path))
self.assertFalse(os.path.exists(text_file_in_portal_components_path))
# assert that related objects exist
self.assertTrue(os.path.exists(os.path.join(self.export_dir, 'bt')))
self.assertTrue(os.path.exists(test_component_path+'.xml'))
self.assertTrue(os.path.exists(test_component_path+'.py'))
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