Commit a82324ca by Julien Muchembled

BT: read metadata (bt/* files) through BusinessTemplateArchive

1 parent b9483c71
...@@ -76,7 +76,6 @@ customImporters={ ...@@ -76,7 +76,6 @@ customImporters={
from zLOG import LOG, WARNING, INFO from zLOG import LOG, WARNING, INFO
from warnings import warn from warnings import warn
from gzip import GzipFile
from lxml.etree import parse from lxml.etree import parse
from xml.sax.saxutils import escape from xml.sax.saxutils import escape
from Products.CMFCore.Expression import Expression from Products.CMFCore.Expression import Expression
...@@ -360,7 +359,7 @@ class BusinessTemplateFolder(BusinessTemplateArchive): ...@@ -360,7 +359,7 @@ class BusinessTemplateFolder(BusinessTemplateArchive):
d.setdefault(klass, []).append(f) d.setdefault(klass, []).append(f)
self.file_list_dict = d self.file_list_dict = d
def importFiles(self, item, **kw): def importFiles(self, item):
""" """
Import file from a local folder Import file from a local folder
""" """
...@@ -415,7 +414,7 @@ class BusinessTemplateTarball(BusinessTemplateArchive): ...@@ -415,7 +414,7 @@ class BusinessTemplateTarball(BusinessTemplateArchive):
return self.fobj return self.fobj
def _initImport(self, file, **kw): def _initImport(self, file, **kw):
self.tar = tarfile.TarFile(fileobj=StringIO(GzipFile(fileobj=file).read())) self.tar = tarfile.open(file, 'r:gz')
self.item_dict = {} self.item_dict = {}
setdefault = self.item_dict.setdefault setdefault = self.item_dict.setdefault
for info in self.tar.getmembers(): for info in self.tar.getmembers():
...@@ -428,7 +427,7 @@ class BusinessTemplateTarball(BusinessTemplateArchive): ...@@ -428,7 +427,7 @@ class BusinessTemplateTarball(BusinessTemplateArchive):
file_name = unquote(file_name) file_name = unquote(file_name)
setdefault(path[1], []).append((file_name, info)) setdefault(path[1], []).append((file_name, info))
def importFiles(self, item, **kw): def importFiles(self, item):
""" """
Import all file from the archive to the site Import all file from the archive to the site
""" """
...@@ -535,7 +534,7 @@ class BaseTemplateItem(Implicit, Persistent): ...@@ -535,7 +534,7 @@ class BaseTemplateItem(Implicit, Persistent):
return self._objects.keys() return self._objects.keys()
def importFile(self, bta, **kw): def importFile(self, bta, **kw):
bta.importFiles(item=self) bta.importFiles(self)
def removeProperties(self, obj, export, keep_workflow_history=False): def removeProperties(self, obj, export, keep_workflow_history=False):
""" """
...@@ -4704,6 +4703,13 @@ class LocalRolesTemplateItem(BaseTemplateItem): ...@@ -4704,6 +4703,13 @@ class LocalRolesTemplateItem(BaseTemplateItem):
delattr(obj, '__ac_local_roles_group_id_dict__') delattr(obj, '__ac_local_roles_group_id_dict__')
obj.reindexObject() obj.reindexObject()
class bt(dict):
"""Fake 'bt' item to read bt/* files through BusinessTemplateArchive"""
def _importFile(self, file_name, file):
self[file_name] = file.read()
class BusinessTemplate(XMLObject): class BusinessTemplate(XMLObject):
""" """
A business template allows to construct ERP5 modules A business template allows to construct ERP5 modules
...@@ -5615,6 +5621,22 @@ Business Template is a set of definitions, such as skins, portal types and categ ...@@ -5615,6 +5621,22 @@ Business Template is a set of definitions, such as skins, portal types and categ
else: else:
bta = BusinessTemplateTarball(importing=1, file=file) bta = BusinessTemplateTarball(importing=1, file=file)
bt_item = bt()
bta.importFiles(bt_item)
prop_dict = {}
for prop in self.propertyMap():
pid = prop['id']
if pid != 'id':
prop_type = prop['type']
value = bt_item.get(pid)
if prop_type in ('text', 'string'):
prop_dict[pid] = value or ''
elif prop_type in ('int', 'boolean'):
prop_dict[pid] = value or 0
elif prop_type in ('lines', 'tokens'):
prop_dict[pid[:-5]] = (value or '').splitlines()
self._edit(**prop_dict)
self.storeTemplateItemData() self.storeTemplateItemData()
# Create temporary modules/classes for classes defined by this BT. # Create temporary modules/classes for classes defined by this BT.
......
...@@ -33,7 +33,6 @@ from App.config import getConfiguration ...@@ -33,7 +33,6 @@ from App.config import getConfiguration
import os import os
import shutil import shutil
import sys import sys
import tarfile
from Acquisition import Implicit, Explicit from Acquisition import Implicit, Explicit
from AccessControl import ClassSecurityInfo from AccessControl import ClassSecurityInfo
...@@ -56,7 +55,6 @@ from xml.dom.minidom import parse ...@@ -56,7 +55,6 @@ from xml.dom.minidom import parse
from xml.parsers.expat import ExpatError from xml.parsers.expat import ExpatError
import struct import struct
import cPickle import cPickle
import posixpath
from base64 import b64encode, b64decode from base64 import b64encode, b64decode
from Products.ERP5Type.Message import translateString from Products.ERP5Type.Message import translateString
from zLOG import LOG, INFO, WARNING from zLOG import LOG, INFO, WARNING
...@@ -298,58 +296,6 @@ class TemplateTool (BaseTool): ...@@ -298,58 +296,6 @@ class TemplateTool (BaseTool):
self.deleteContent(id) self.deleteContent(id)
self._importObjectFromFile(StringIO(export_string), id=id) self._importObjectFromFile(StringIO(export_string), id=id)
def _importBT(self, path=None, id=id):
"""
Import template from a temp file (as uploaded by the user)
"""
with open(path, 'rb') as file:
# read magic key to determine wich kind of bt we use
file.seek(0)
magic = file.read(5)
if magic == '<?xml': # old version
self._importObjectFromFile(path, id=id)
bt = self[id]
bt.id = id # Make sure id is consistent
bt.setProperty('template_format_version', 0, type='int')
else: # new version
# XXX: should really check for a magic and offer a falback if it
# doens't correspond to anything handled.
tar = tarfile.open(path, 'r:gz')
dir_name = tar.members[0].name.split(posixpath.sep, 1)[0]
try:
# create bt object
bt = self.newContent(portal_type='Business Template', id=id)
prop_dict = {}
for prop in bt.propertyMap():
prop_type = prop['type']
pid = prop['id']
prop_path = posixpath.join(dir_name, 'bt', pid)
try:
info = tar.getmember(prop_path)
value = tar.extractfile(info).read()
except KeyError:
value = None
if value is 'None':
# At export time, we used to export non-existent properties:
# str(obj.getProperty('non-existing')) == 'None'
# Discard them
continue
if prop_type in ('text', 'string'):
prop_dict[pid] = value or ''
elif prop_type in ('int', 'boolean'):
prop_dict[pid] = value or 0
elif prop_type in ('lines', 'tokens'):
prop_dict[pid[:-5]] = (value or '').splitlines()
prop_dict.pop('id', '')
bt.edit(**prop_dict)
# import all other files from bt
with open(path, 'rb') as fobj:
bt.importFile(file=fobj)
finally:
tar.close()
return bt
security.declareProtected( Permissions.ManagePortal, 'manage_download' ) security.declareProtected( Permissions.ManagePortal, 'manage_download' )
def manage_download(self, url, id=None, REQUEST=None): def manage_download(self, url, id=None, REQUEST=None):
"""The management interface for download. """The management interface for download.
...@@ -368,6 +314,7 @@ class TemplateTool (BaseTool): ...@@ -368,6 +314,7 @@ class TemplateTool (BaseTool):
def _download_local(self, path, bt_id): def _download_local(self, path, bt_id):
"""Download Business Template from local directory or file """Download Business Template from local directory or file
""" """
bt = self.newContent(portal_type='Business Template', id=bt_id)
if os.path.isdir(os.path.normpath(path)): if os.path.isdir(os.path.normpath(path)):
path = os.path.normpath(path) path = os.path.normpath(path)
def callback(file_list, directory, files): def callback(file_list, directory, files):
...@@ -385,39 +332,11 @@ class TemplateTool (BaseTool): ...@@ -385,39 +332,11 @@ class TemplateTool (BaseTool):
os.path.walk(path, callback, file_list) os.path.walk(path, callback, file_list)
file_list.sort() file_list.sort()
# import bt object # import bt object
bt = self.newContent(portal_type='Business Template', id=bt_id)
bt_path = os.path.join(path, 'bt')
# import properties
prop_dict = {}
for prop in bt.propertyMap():
prop_type = prop['type']
pid = prop['id']
prop_path = os.path.join('.', bt_path, pid)
if not os.path.exists(prop_path):
value = None
else:
with open(prop_path, 'rb') as f:
value = f.read()
if value is 'None':
# At export time, we used to export non-existent properties:
# str(obj.getProperty('non-existing')) == 'None'
# Discard them
value = None
if prop_type in ('text', 'string'):
prop_dict[pid] = value or ''
elif prop_type in ('int', 'boolean'):
prop_dict[pid] = value or 0
elif prop_type in ('lines', 'tokens'):
prop_dict[pid[:-5]] = (value or '').splitlines()
prop_dict.pop('id', '')
bt.edit(**prop_dict)
# import all others objects
bt.importFile(dir=True, file=file_list, root_path=path) bt.importFile(dir=True, file=file_list, root_path=path)
return bt
else: else:
# this should be a file # this should be a file
return self._importBT(path, bt_id) bt.importFile(file=path)
return bt
def _download_url(self, url, bt_id): def _download_url(self, url, bt_id):
tempid, temppath = mkstemp() tempid, temppath = mkstemp()
......
Styling with Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!