Commit f537d4e9 authored by Julien Muchembled's avatar Julien Muchembled

BT: fix severe regression when installing objects that were exported in 2 files

For example, Python Scripts were:
- dirty in the imported BT (causing all of them to be reinstalled on upgrade)
- compiled to return None
parent d34d719c
......@@ -888,6 +888,12 @@ class ObjectTemplateItem(BaseTemplateItem):
except BrokenModified:
obj.__Broken_state__[property_name] = data
obj._p_changed = 1
else:
# Revert any work done by __setstate__.
# XXX: This is enough for all objects we currently split in 2 files,
# but __setstate__ could behave badly with the missing attribute
# and newly added types may require more than this.
self.removeProperties(obj, 1, keep_workflow_history=True)
def _importFile(self, file_name, file_obj, catalog_method_template_item = 0):
obj_key, file_ext = os.path.splitext(file_name)
......
......@@ -26,7 +26,8 @@
#
##############################################################################
from Products.ERP5Type.tests.ERP5TypeTestCase import ERP5TypeTestCase
from Products.ERP5Type.tests.ERP5TypeTestCase import \
ERP5TypeTestCase, immediateCompilation
from Products.PageTemplates.ZopePageTemplate import ZopePageTemplate
from runUnitTest import tests_home
import glob
......@@ -223,13 +224,11 @@ class TestBusinessTemplateTwoFileExport(ERP5TypeTestCase):
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')")
skin_folder.manage_addProduct['PythonScripts'].manage_addPythonScript(
id=python_script_id)
skin_folder[python_script_id].ZPythonScript_edit('', "return 1")
python_script_kw = {"_body": "context.setTitle('foo')\n",}
python_script_kw = {"_body": "return 1\n",}
self.template.edit(template_skin_id_list=[skin_folder_id+'/'+python_script_id,])
......@@ -237,20 +236,21 @@ class TestBusinessTemplateTwoFileExport(ERP5TypeTestCase):
'SkinTemplateItem', 'portal_skins', skin_folder_id, python_script_id)
import_template = self._exportAndReImport(
with immediateCompilation():
import_template = self._exportAndReImport(
python_script_path,
".py",
python_script_kw["_body"],
['_body','_code'])
self.portal.portal_skins[skin_folder_id].manage_delObjects([python_script_id])
skin_folder.manage_delObjects(python_script_id)
import_template.install()
import_template.install()
python_script_page = self.portal.portal_skins[skin_folder_id][python_script_id]
script = skin_folder[python_script_id]
python_script_content = python_script_page.read()
self.assertTrue(python_script_content.endswith(python_script_kw['_body']))
self.assertTrue(script.read().endswith(python_script_kw['_body']))
self.assertEqual(1, script())
def _checkTwoFileImportExportForImageInImageModule(self,
image_document_kw,
......
......@@ -19,6 +19,7 @@ import time
import traceback
import urllib
import ConfigParser
from contextlib import contextmanager
from cStringIO import StringIO
from cPickle import dumps
from glob import glob
......@@ -57,6 +58,7 @@ from Testing import ZopeTestCase
from Testing.ZopeTestCase import PortalTestCase, user_name
from Products.CMFCore.utils import getToolByName
from Products.DCWorkflow.DCWorkflow import ValidationFailed
from Products.PythonScripts.PythonScript import PythonScript
from Products.ERP5Type.Accessor.Constant import PropertyGetter as ConstantGetter
from zLOG import LOG, DEBUG
......@@ -1323,13 +1325,27 @@ class lazy_func_prop(object):
self.default_dict[name] = default
def __get__(self, instance, owner):
if self.name not in instance.__dict__:
instance.__dict__.update(self.default_dict)
instance._orig_compile()
self.compile(instance)
return instance.__dict__[self.name]
def __set__(self, instance, value):
instance.__dict__[self.name] = value
def __delete__(self, instance):
del instance.__dict__[self.name]
@classmethod
def compile(cls, instance, _compile=PythonScript._compile):
instance.__dict__.update(cls.default_dict)
_compile(instance)
immediate_compilation = 0
@contextmanager
def immediateCompilation():
global immediate_compilation
immediate_compilation += 1
try:
yield
finally:
immediate_compilation -= 1
@onsetup
def optimize():
......@@ -1341,13 +1357,13 @@ def optimize():
Expression.__init__ = __init__
# Delay the compilations of Python Scripts until they are really executed.
from Products.PythonScripts.PythonScript import PythonScript
# Python Scripts are exported without those 2 attributes:
PythonScript.func_code = lazy_func_prop('func_code', None)
PythonScript.func_defaults = lazy_func_prop('func_defaults', None)
PythonScript._orig_compile = PythonScript._compile
def _compile(self):
if immediate_compilation:
return lazy_func_prop.compile(self)
# mark the script as being not compiled
for name in lazy_func_prop.default_dict:
self.__dict__.pop(name, None)
......@@ -1360,8 +1376,7 @@ def optimize():
from Acquisition import aq_parent
def _makeFunction(self, dummy=0): # CMFCore.FSPythonScript uses dummy arg.
self.ZCacheable_invalidate()
self.__dict__.update(lazy_func_prop.default_dict)
self._orig_compile()
lazy_func_prop.compile(self)
if not (aq_parent(self) is None or hasattr(self, '_filepath')):
# It needs a _filepath, and has an acquisition wrapper.
self._filepath = self.get_filepath()
......
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