From b3acec03c8ae47e7d6e12cae782a66ae1aa1b4f2 Mon Sep 17 00:00:00 2001 From: Julien Muchembled <jm@nexedi.com> Date: Thu, 4 Mar 2010 15:08:39 +0000 Subject: [PATCH] Unit tests: allow to download built BT from a running ERP5 instance --bt5_path cmdline option now allows to specify the URL of a running template tool. For example: $ runUnitTest.py --bt5_path='http://zope:zope@localhost:9001/erp5/portal_templates',/fallback_fs_path/bt5 testBug This will try to download non-deleted built business templates, with the highest revision number. --bt5_path is also changed to apply to core BT during creation of the site. git-svn-id: https://svn.erp5.org/repos/public/erp5/trunk@33393 20353a03-c40f-0410-a6d1-a30d3c3de9de --- product/ERP5/ERP5Site.py | 24 ++--- product/ERP5/Tool/TemplateTool.py | 21 +++- product/ERP5Type/tests/ERP5TypeTestCase.py | 109 +++++++++------------ 3 files changed, 77 insertions(+), 77 deletions(-) diff --git a/product/ERP5/ERP5Site.py b/product/ERP5/ERP5Site.py index 5080f25709..5eec78ea9d 100644 --- a/product/ERP5/ERP5Site.py +++ b/product/ERP5/ERP5Site.py @@ -1279,6 +1279,14 @@ def getBootstrapDirectory(): product_path = package_home(globals()) return os.path.join(product_path, 'bootstrap') +def getBootstrapBusinessTemplateUrl(bt_title): + """ + Return the path to download the given bootstrap business template + """ + path = os.path.join(getBootstrapDirectory(), bt_title) + if not os.path.exists(path): + path += '.bt5' + return path # This PortalGenerator class was copied wholesale from CMF 1.5 which is # identical to the one on 1.6, and hasn't been used by CMF itself since even @@ -1443,9 +1451,6 @@ class ERP5Generator(PortalGenerator): klass = ERP5Site - def getBootstrapDirectory(self): - return getBootstrapDirectory() - def create(self, parent, id, @@ -1806,7 +1811,7 @@ class ERP5Generator(PortalGenerator): 'business_template_installation_workflow'): if wf_id in tool.objectIds(): tool.manage_delObjects([wf_id]) - bootstrap_dir = self.getBootstrapDirectory() + bootstrap_dir = getBootstrapDirectory() business_template_building_workflow = os.path.join( bootstrap_dir, 'business_template_building_workflow.xml') @@ -1984,14 +1989,9 @@ class ERP5Generator(PortalGenerator): if template_tool is None: return if template_tool.getInstalledBusinessTemplate('erp5_core') is None: - bootstrap_dir = self.getBootstrapDirectory() for bt in ('erp5_core', p.erp5_catalog_storage, 'erp5_xhtml_style'): if not bt: continue - template = os.path.join(bootstrap_dir, bt) - if not os.path.exists(template): - template = os.path.join(bootstrap_dir, '%s.bt5' % bt) - - id = template_tool.generateNewId() - template_tool.download(template, id=id) - template_tool[id].install(**kw) + url = getBootstrapBusinessTemplateUrl(bt) + bt = template_tool.download(url) + bt.install(**kw) diff --git a/product/ERP5/Tool/TemplateTool.py b/product/ERP5/Tool/TemplateTool.py index 787f23c11c..ca7bbd62c4 100644 --- a/product/ERP5/Tool/TemplateTool.py +++ b/product/ERP5/Tool/TemplateTool.py @@ -124,7 +124,7 @@ class TemplateTool (BaseTool): """Get the list of installed business templates. """ installed_bts = [] - for bt in self.contentValues(filter={'portal_type':'Business Template'}): + for bt in self.contentValues(portal_type='Business Template'): if bt.getInstallationState() == 'installed': installed_bts.append(bt) return installed_bts @@ -139,11 +139,22 @@ class TemplateTool (BaseTool): """Get the list of built and not installed business templates. """ built_bts = [] - for bt in self.contentValues(filter={'portal_type':'Business Template'}): + for bt in self.contentValues(portal_type='Business Template'): if bt.getInstallationState() == 'not_installed' and bt.getBuildingState() == 'built': built_bts.append(bt) return built_bts + def getLastBusinessTemplateId(self, title): + """Get the id of the business template with the highest revision number + """ + last_bt = None, None + for bt in self.contentValues(portal_type='Business Template'): + if bt.getTitle() == title and bt.getBuildingState() == 'built': + revision = bt.getRevision() + if last_bt[0] < revision and bt.getInstallationState() != 'deleted': + last_bt = revision, bt.getId() + return last_bt[1] + security.declareProtected(Permissions.ManagePortal, 'getDefaultBusinessTemplateDownloadURL') def getDefaultBusinessTemplateDownloadURL(self): @@ -401,6 +412,12 @@ class TemplateTool (BaseTool): name = os.path.normpath(url) if urltype and urltype != 'file': + if '/manage_exportObject?' in url: + # In this case, the downloaded BT is already built. + bt = self._p_jar.importFile(urlopen(url)) + bt.id = id + del bt.uid + return self[self._setObject(id, bt)] bt = self._download_url(url, id) else: bt = self._download_local(name, id) diff --git a/product/ERP5Type/tests/ERP5TypeTestCase.py b/product/ERP5Type/tests/ERP5TypeTestCase.py index 338f4eeb7e..6605e9d29e 100644 --- a/product/ERP5Type/tests/ERP5TypeTestCase.py +++ b/product/ERP5Type/tests/ERP5TypeTestCase.py @@ -20,8 +20,9 @@ import traceback from cStringIO import StringIO from cPickle import dumps from glob import glob -from urllib import urlretrieve +from urllib import urlopen from warnings import warn +from ZTUtils import make_query # XXX make sure that get_request works. current_app = None @@ -386,56 +387,42 @@ class ERP5TypeTestCase(backportUnittest.TestCase, PortalTestCase): self.run(*args, **kw) - def _getBTPathAndIdList(self, template_list): - INSTANCE_HOME = os.environ['INSTANCE_HOME'] - erp5_tests_bt5_path = os.environ.get('erp5_tests_bt5_path', - os.path.join(INSTANCE_HOME, 'bt5')) - erp5_product_path = os.path.dirname(Products.ERP5.__file__) - bootstrap_path = os.environ.get('erp5_tests_bootstrap_path', - os.path.join(erp5_product_path, - 'bootstrap')) + @staticmethod + def _getBTPathAndIdList(template_list): + bootstrap_path = os.environ.get('erp5_tests_bootstrap_path') or \ + ERP5Site.getBootstrapDirectory() + bt5_path = os.environ.get('erp5_tests_bt5_path') + if bt5_path: + bt5_path_list = bt5_path.split(',') + else: + bt5_path = os.path.join(os.environ['INSTANCE_HOME'], 'bt5') + bt5_path_list = bt5_path, os.path.join(bt5_path, '*') + + not_found_list = [] new_template_list = [] for template in template_list: id = template.split('/')[-1] - try : - file, headers = urlretrieve(template) - except IOError : - # First, try the bt5 directory itself. - original_template = template - for bt5_path in erp5_tests_bt5_path.split(','): - template = original_template - path = os.path.join(bt5_path, template) - alternate_path = os.path.join(bootstrap_path, template) - if os.path.exists(path): - template = path - break - elif os.path.exists(alternate_path): - template = alternate_path - break - else: - path = '%s.bt5' % path - if os.path.exists(path): - template = path - break - else: - # Otherwise, look at sub-directories. - # This is for backward-compatibility. - path = os.path.join(INSTANCE_HOME, 'bt5', '*', template) - template_list = glob(path) - if len(template_list) == 0: - template_list = glob('%s.bt5' % path) - if len(template_list) and template_list[0]: - template = template_list[0] - else: - # The last resort is current directory. - template = '%s' % id - if not os.path.exists(template): - template = '%s.bt5' % id + for path in bt5_path_list: + if path.endswith('/portal_templates'): + bt_id = urlopen('%s/getLastBusinessTemplateId?title=%s' + % (path, template)).read() + path = bt_id and '%s/manage_exportObject?%s' % (path, + make_query(id=bt_id, download=1, to_xml=0)) + else: + path = os.path.join(path, template) + path_list = glob(path) + glob(path + '.bt5') + path = path_list and path_list[0] + if path: + break else: - template = '%s' % template - if not os.path.exists(template): - template = '%s.bt5' % template - new_template_list.append((template,id)) + path = os.path.join(bootstrap_path, template) + if not os.path.exists(path): + not_found_list.append(template) + continue + new_template_list.append((path, id)) + if not_found_list: + raise RuntimeError("Following BT can't be found on your system : %s" + % ', '.join(not_found_list)) return new_template_list def manuallyInstallBusinessTemplate(self, *template_list): @@ -500,7 +487,6 @@ class ERP5TypeTestCase(backportUnittest.TestCase, PortalTestCase): if re.search(expression, business_template): matching_template_list.append(business_template) template_list = matching_template_list - new_template_list = self._getBTPathAndIdList(template_list) # keep a mapping type info name -> property sheet list, to remove them in # tear down. @@ -508,7 +494,7 @@ class ERP5TypeTestCase(backportUnittest.TestCase, PortalTestCase): light_install = self.enableLightInstall() create_activities = self.enableActivityTool() hot_reindexing = self.enableHotReindexing() - self.setUpERP5Site(business_template_list=new_template_list, + self.setUpERP5Site(business_template_list=template_list, light_install=light_install, create_activities=create_activities, quiet=install_bt5_quiet, @@ -838,25 +824,16 @@ class ERP5TypeTestCase(backportUnittest.TestCase, PortalTestCase): def _installBusinessTemplateList(self, business_template_list, light_install=True, quiet=True): - portal = self.portal + template_tool = self.portal.portal_templates update_business_templates = os.environ.get('update_business_templates') is not None - BusinessTemplate_getModifiedObject = aq_base(getattr(portal, 'BusinessTemplate_getModifiedObject', None)) - - # check that all bt5 exist, saving time in case of missing bt - missing_bt_list = [] - for url, bt_title in business_template_list: - # if the bt is not found, an error is raised - if not portal.portal_templates.assertBtPathExists(url): - missing_bt_list.append(bt_title) - if len(missing_bt_list): - raise RuntimeError("Some BT can't be found on your system : %s" - % ', '.join(missing_bt_list)) + BusinessTemplate_getModifiedObject = aq_base( + getattr(self.portal, 'BusinessTemplate_getModifiedObject', None)) # Add some business templates for url, bt_title in business_template_list: start = time.time() get_install_kw = False - if bt_title in [x.getTitle() for x in portal.portal_templates.getInstalledBusinessTemplateList()]: + if bt_title in [x.getTitle() for x in template_tool.getInstalledBusinessTemplateList()]: if update_business_templates: if not quiet: ZopeTestCase._print('Updating %s business template ... ' % bt_title) @@ -867,7 +844,7 @@ class ERP5TypeTestCase(backportUnittest.TestCase, PortalTestCase): else: if not quiet: ZopeTestCase._print('Adding %s business template ... ' % bt_title) - bt = portal.portal_templates.download(url) + bt = template_tool.download(url) if not quiet: ZopeTestCase._print('(imported in %.3fs) ' % (time.time() - start)) install_kw = None @@ -915,6 +892,8 @@ class ERP5TypeTestCase(backportUnittest.TestCase, PortalTestCase): if not (hasattr(aq_base(app), portal_name) and setup_done.get(tuple(business_template_list))): setup_done[tuple(business_template_list)] = 1 + business_template_list = \ + self._getBTPathAndIdList(business_template_list) try: _start = time.time() # Add user and log in @@ -1135,6 +1114,10 @@ class ERP5TypeTestCase(backportUnittest.TestCase, PortalTestCase): return ResponseWrapper(response, outstream, path) +from Products.ERP5 import ERP5Site +ERP5Site.getBootstrapBusinessTemplateUrl = lambda bt_title: \ + ERP5TypeTestCase._getBTPathAndIdList((bt_title,))[0][0] + class ResponseWrapper: '''Decorates a response object with additional introspective methods.''' -- 2.30.9