diff --git a/Products/CMFPlomino/PlominoDesignManager.py b/Products/CMFPlomino/PlominoDesignManager.py index 371b81b3a..1a71981fb 100644 --- a/Products/CMFPlomino/PlominoDesignManager.py +++ b/Products/CMFPlomino/PlominoDesignManager.py @@ -702,18 +702,37 @@ def compileFormulaScript(self, script_id, formula, with_args=False): ) import_list = ";".join(import_list) - r = re.compile('^#Plomino import (.+)$', re.MULTILINE) - for i in r.findall(formula): - scriptname = i.strip() - try: - script_code = self.resources._getOb(scriptname).read() - except: - logger.warning("compileFormulaScript> %s not found in resources" % scriptname) - script_code = ( - "#ALERT: %s not found in resources" % scriptname) - formula = formula.replace( - '#Plomino import '+scriptname, - script_code) + # Match any include + r = re.compile('^#Plomino (import|include) (.+)$', re.MULTILINE) + + matches = r.findall(formula) + seen = [] + while matches: + for include, scriptname in matches: + + scriptname = scriptname.strip() + # Match only this include; don't match script names that are + # prefixes of other script names + exact_r = re.compile( + '^#Plomino %s %s\\b' % (include, scriptname), + re.MULTILINE) + + if scriptname in seen: + # Included already, blank the include statement + formula = exact_r.sub('', formula) + continue + + seen.append(scriptname) + try: + script_code = self.resources._getOb(scriptname).read() + except: + logger.warning("compileFormulaScript> %s not found in resources" % scriptname) + script_code = ( + "#ALERT: %s not found in resources" % scriptname) + + formula = exact_r.sub(script_code, formula) + + matches = r.findall(formula) if (formula.strip().count('\n') == 0 and not formula.startswith('return ')): diff --git a/Products/CMFPlomino/tests/plomino.txt b/Products/CMFPlomino/tests/plomino.txt index 6ce225c65..c57f3423b 100644 --- a/Products/CMFPlomino/tests/plomino.txt +++ b/Products/CMFPlomino/tests/plomino.txt @@ -127,6 +127,59 @@ Let's set a layout which contains our fields:: ... field4

""") +Formulas can include scripts from resources +-------------------------------------------- + +A formula can include scripts from ``resources``:: + + >>> from Products.PythonScripts.PythonScript import PythonScript + >>> ps = PythonScript('script') + >>> script_id = db.resources._setObject('script', ps) + >>> ps.write('return "hello"') + >>> id = db.frm1.invokeFactory('PlominoField', + ... id='field5', + ... title='Field with import', + ... FieldType="TEXT", + ... FieldMode="DISPLAY", + ... Formula="#Plomino import script") + >>> db.frm1.field5.at_post_create_script() + >>> db.frm1.computeFieldValue('field5', db.frm1) + 'hello' + +Scripts can also include other scripts (including themselves; i.e. +recursive includes), and script names can be prefixes of other scripts:: + + >>> ps = PythonScript('script_too') + >>> script_id = db.resources._setObject('script_too', ps) + >>> ps.write('#Plomino import script\n#Plomino import script_too') + >>> id = db.frm1.invokeFactory('PlominoField', + ... id='field6', + ... title='Field with import', + ... FieldType="TEXT", + ... FieldMode="DISPLAY", + ... Formula="#Plomino import script_too") + >>> db.frm1.field6.at_post_create_script() + >>> db.frm1.computeFieldValue('field6', db.frm1) + 'hello' + +You can also spell it ``include`` (because what we're doing is really +not much like Python's ``import``, it's straight string interpolation). +And scripts can include scripts that include scripts ...:: + + >>> ps = PythonScript('script_three') + >>> script_id = db.resources._setObject('script_three', ps) + >>> ps.write('#Plomino include script_too') + >>> id = db.frm1.invokeFactory('PlominoField', + ... id='field7', + ... title='Field with import', + ... FieldType="TEXT", + ... FieldMode="DISPLAY", + ... Formula="#Plomino include script_three") + >>> db.frm1.field7.at_post_create_script() + >>> db.frm1.computeFieldValue('field7', db.frm1) + 'hello' + + Documents ---------------