def test_constructContent(self): from Products.CMFCore.TypesTool \ import ScriptableTypeInformation as STI site = self.site acl_users = self.acl_users ttool = self.ttool setSecurityPolicy(self._oldPolicy) newSecurityManager(None, acl_users.all_powerful_Oz) self.site._owner = (['acl_users'], 'all_powerful_Oz') sti_baz = STI('Baz', permission='Add portal content', constructor_path='addBaz') ttool._setObject('Baz', sti_baz) ttool._setObject('addBaz', PythonScript('addBaz')) s = ttool.addBaz s.write(STI_SCRIPT) f = site._setObject('folder', PortalFolder(id='folder')) f.manage_addProduct = {'FooProduct': DummyFactory(f)} f._owner = (['acl_users'], 'user_foo') self.assertEqual(f.getOwner(), acl_users.user_foo) ttool.constructContent('Dummy Content', container=f, id='page1') try: ttool.constructContent('Baz', container=f, id='page2') except Unauthorized: self.fail('CMF Collector issue #165 (Ownership bug): ' 'Unauthorized raised')
def PUT_factory( self, name, typ, body ): """ Dispatcher for PUT requests to non-existent IDs. Returns an object of the appropriate type (or None, if we don't know what to do). """ major, minor = split( typ, '/' ) if major == 'image': return Image( id=name , title='' , file='' , content_type=typ ) if major == 'text': if minor == 'x-python': return PythonScript( id=name ) if minor in ( 'html', 'xml' ) and SUPPORTS_PAGE_TEMPLATES: return ZopePageTemplate( name ) return DTMLMethod( __name__=name ) return None
def _createObjectByType( self, name, body, content_type ): if isinstance( body, unicode ): encoding = self.getEncoding() if encoding is None: body = body.encode() else: body = body.encode( encoding ) if name.endswith('.py'): ob = PythonScript( name ) ob.write( body ) elif name.endswith('.dtml'): ob = DTMLDocument( '', __name__=name ) ob.munge( body ) elif content_type in ('text/html', 'text/xml' ): ob = ZopePageTemplate( name, body , content_type=content_type ) elif content_type[:6]=='image/': ob=Image( name, '', body, content_type=content_type ) else: ob=File( name, '', body, content_type=content_type ) return ob
def _initDCWorkflowScripts(workflow, scripts, context): """ Initialize DCWorkflow scripts """ for s_info in scripts: id = str(s_info['script_id']) # no unicode! meta_type = s_info['meta_type'] filename = s_info['filename'] file = '' if filename: file = context.readDataFile(filename) if meta_type == PythonScript.meta_type: script = PythonScript(id) script.write(file) elif meta_type == ExternalMethod.meta_type: script = ExternalMethod(id, '', s_info['module'], s_info['function']) elif meta_type == DTMLMethod.meta_type: script = DTMLMethod(file, __name__=id) if workflow.scripts.has_key(id): workflow.scripts._delObject(id) workflow.scripts._setObject(id, script)
def test_constructContent_simple_STI(self): from AccessControl import Unauthorized from AccessControl.SecurityManagement import newSecurityManager from AccessControl.SecurityManager import setSecurityPolicy from Products.CMFCore.PortalFolder import PortalFolder from Products.CMFCore.TypesTool import ScriptableTypeInformation as STI from Products.CMFCore.tests.base.dummy import DummyFactoryDispatcher from Products.CMFCore.tests.base.tidata import STI_SCRIPT from Products.PythonScripts.PythonScript import PythonScript site = self._makeSite().__of__(self.app) acl_users = site.acl_users setSecurityPolicy(self._oldPolicy) newSecurityManager(None, acl_users.all_powerful_Oz) tool = self._makeOne().__of__(site) sti_baz = STI('Baz', permission='Add portal content', constructor_path='addBaz') tool._setObject('Baz', sti_baz) script = PythonScript('addBaz') script.write(STI_SCRIPT) tool._setObject('addBaz', script) folder = site._setObject('folder', PortalFolder(id='folder')) folder.manage_addProduct = { 'FooProduct': DummyFactoryDispatcher(folder) } folder._owner = (['acl_users'], 'user_foo') self.assertEqual(folder.getOwner(), acl_users.user_foo) try: tool.constructContent('Baz', container=folder, id='page2') except Unauthorized: self.fail('CMF Collector issue #165 (Ownership bug): ' 'Unauthorized raised') self.assertEqual(folder.page2.portal_type, 'Baz')
def recompileScript(self, baseName): "recompile python script" scriptName = '%sScript' % baseName pyscript = getattr(self, scriptName, None) if pyscript is None: pyscript = PythonScript(scriptName) self.setObject(scriptName, pyscript) pyscript.ZPythonScript_edit('', getattr(self, baseName))
def _filePS(self, fname, bind=None): ps = PythonScript(fname) ps.ZBindings_edit(bind or {}) ps.write(readf(fname)) ps._makeFunction() if ps.errors: raise SyntaxError(ps.errors[0]) return ps
def createPythonScript(self, id_, title, code): """Creare new Python Script object.""" ps = PythonScript(id_) if title: ps.ZPythonScript_setTitle(title) ps.write(code) ps._makeFunction() return ps
def _newPS(self, txt, bind=None): ps = PythonScript('ps') ps.ZBindings_edit(bind or {}) ps.write(txt) ps._makeFunction() if ps.errors: raise SyntaxError(ps.errors[0]) return ps
def setUp(self): import Products.GenericSetup.PythonScripts from Products.PythonScripts.PythonScript import PythonScript BodyAdapterTestCase.setUp(self) zcml.load_config('configure.zcml', Products.GenericSetup.PythonScripts) self._obj = PythonScript('foo_script') self._BODY = _PYTHONSCRIPT_BODY
def Base_runPythonScript(self, code): script = PythonScript('Python Shell Script').__of__(self) code_line_list = code.split('\r\n') code = '\n'.join(code_line_list) script.write(code) if script._code is None: raise ValueError(repr(script.errors)) return script()
def _test_list_items(self, list_field_type): """ test if a list of values returned by TALES (override) expressions is interpreted properly. If a TALES tab returns a sequence of items and some item is actually a string of length 2 (e.g. "ok"), this previously has lead to a item text of 'o' and a display value of 'k' (as the this is actually a sequence of length 2 ...) See http://sourceforge.net/mailarchive/forum.php?thread_id=1359918&forum_id=1702 """ self.form.manage_addField('list_field', 'Test List Field', list_field_type) self.form.override_test = PythonScript('override_test') self.form.override_test.write("return ['ok', 'no']\n") list_field = self.form.list_field list_field.values['items'] = [('ok', 'ok'), ('no', 'no')] list_field.values['first_item'] = 'on' items1 = list_field.render() # test TALES list_field.tales['items'] = TALESMethod("python:['ok', 'no']") items2 = list_field.render() # test render self.assertEquals(items1, items2) # test render_view self.assertEquals('ok', list_field.render_view('ok')) # test validation ... fake request with a dictionary ... list_field.validate({'field_list_field': 'ok'}) # test override (most probably superfluous) del list_field.tales['items'] list_field.overrides['items'] = Method('override_test') items2 = list_field.render() self.assertEquals(items1, items2) # missing: if returning a list of int, # rendering does work here, but validation fails. # maybe it should fail, but on the other hand this is a FAQ on the list ... del list_field.overrides['items'] # test when TALES returns a list of e.g. int list_field.values['items'] = [('42', '42'), ('88', '88')] items1 = list_field.render() list_field.tales['items'] = TALESMethod("python:[42, 88]") items2 = list_field.render() self.assertEquals(items1, items2) list_field.validate({'field_list_field': '42'})
def test_PT_allow_module_not_available_in_RestrictedPython_2(self): src = ''' from Products.PlacelessTranslationService import allow_module allow_module('os') ''' from Products.PythonScripts.PythonScript import PythonScript script = makerequest(PythonScript('barscript')) script._filepath = 'barscript' script.write(src) self.assertRaises((ImportError, Unauthorized), script)
def _write(self, text): ps = PythonScript(self.id) ps.write(text) ps._makeFunction() ps._editedBindings() self._v_f = f = ps._v_f self._body = ps._body self._params = ps._params fc = f.func_code self._setFuncSignature(f.func_defaults, fc.co_varnames, fc.co_argcount)
def test_import_zipfile_with_directory_entry(self): mydb = self.layer['portal'].mydb # Create resource script, to test 'importDesignFromZip' replace ps = PythonScript('script') script_id = mydb.resources._setObject('script', ps) ps.write('return "hello"') dir, _f = os.path.split(os.path.abspath(__file__)) zip_file = ZipFile(os.path.join(dir, 'samples', 'testdirentry.zip')) mydb.importDesignFromZip(zip_file, replace=True) self.assertTrue('libConfig' in mydb.resources)
def PUT_factory(self, name, typ, body): """ Hook PUT creation to make objects of the right type when new item uploaded via FTP/WebDAV. """ if typ is None: typ, enc = guess_content_type() if typ == 'text/x-python': return PythonScript(name) if typ[:4] == 'text': return DTMLMethod('', __name__=name) return None # take the default, then
def compileFormulaScript(self, script_id, formula, with_args=False): # disable CSRF to allow script saving if hasattr(self, "REQUEST"): alsoProvides(self.REQUEST, IDisableCSRFProtection) # Remember the current user member = self.getCurrentMember() if member.__class__.__name__ == "SpecialUser": user = member else: user = member.getUser() # Switch to the db's owner (formula must be compiled with the higher # access rights, but their execution will always be perform with the # current access rights) owner = self.getOwner() newSecurityManager(None, owner) ps = self.getFormulaScript(script_id) if not ps: ps = PythonScript(script_id) self.scripts._setObject(script_id, ps) ps = self.getFormulaScript(script_id) if with_args: ps._params = "*args" safe_utils = get_utils() import_list = [] for module in safe_utils: import_list.append("from %s import %s" % (module, ", ".join(safe_utils[module]))) import_list = ";".join(import_list) formula = _expandIncludes(self, formula) if (formula.strip().count('\n') == 0 and not formula.startswith('return ')): formula = "return " + formula str_formula = STR_FORMULA % { 'script_id': script_id, 'import_list': import_list, 'formula': formula } ps.write(str_formula) if self.debugMode: logger.info(script_id + " compiled") # Switch back to the original user newSecurityManager(None, user) return ps
def updateScript(self, body): # Regenerate Python script object # Sync set of script source code and # creation of Python Script object. bodyField = self.schema["mipago_payment_amountOverride"] script = PythonScript(self.title_or_id()) script = script.__of__(self) script.ZPythonScript_edit("fields, ploneformgen, request", body) PythonField.set(bodyField, self, script)
def createFilesFromFsFolder(self, f, dir): """ Recursively put the files from a fs folder into a ZODB folder. """ filenames = os.listdir(dir) for filename in filenames: if re.match(r'(?:\..*|CVS|_darcs)', filename): continue id, type = os.path.splitext(filename) type = type.lstrip('.') this_path = os.path.join(dir, filename) if os.path.isdir(this_path): f.manage_addFolder(filename) # add folder createFilesFromFsFolder(self, f[filename], this_path) # recurse else: text = open(this_path, 'r').read() if type == 'dtml': addDTMLMethod(f, filename[:-5], title='', file=text) elif re.match(r'(?:(?:rst|stx|html|latex)(?:dtml)?|txt)', type): headers, body = parseHeadersBody(text) if headers.has_key('title'): title = headers['title'] else: title = '' if headers.has_key('parents'): parents = headers['parents'] parents = parents.split(',') else: parents = [] addZWikiPage(f, id, title=title, page_type=type, file=body, parents=parents) elif type == 'pt': f._setObject(id, ZopePageTemplate(id, text, 'text/html')) elif type == 'py': f._setObject(id, PythonScript(id)) f._getOb(id).write(text) elif type == 'zexp' or type == 'xml': connection = self.getPhysicalRoot()._p_jar f._setObject( id, connection.importFile(dir + os.sep + filename, customImporters=customImporters)) #self._getOb(id).manage_changeOwnershipType(explicit=0) elif type in ['jpg', 'jpeg', 'gif', 'png']: f._setObject(filename, Image(filename, '', text)) else: id = f._setObject(filename, File(filename, '', text)) if type == 'css': f[filename].content_type = 'text/css'
def test_auto_rename_on_extension_conflict(self): # When you create a Python Script called "script0", Ape adds a # .py extension. If, in a second transaction, you add # "script0.py", Ape must rename the current "script0.py" to # "script0" to make room for the new "script0.py". conn = self.db.open() try: app = conn.root()['Application'] f = Folder() f.id = 'folder' app._setObject(f.id, f, set_owner=0) # Can't write to 'script0' then 'script0.py'. script = PythonScript('script0') script.write('##title=test script\nreturn "OK"') f._setObject(script.id, script, set_owner=0) transaction.commit() dir = os.path.join(self.conn.basepath, 'folder') names = os.listdir(dir) self.assert_(('script0.py') in names, names) self.assert_(('script0') not in names, names) # script0.py already exists, so Ape should automatically rename. script = PythonScript('script0.py') script.write('##title=test script\nreturn "Hello, world!"') f._setObject(script.id, script, set_owner=0) transaction.commit() # Did it write them correctly? text = open(os.path.join(dir, 'script0')).read() self.assert_(text.find('OK') > 0, text) self.assert_(text.find('Hello, world!') < 0, text) text = open(os.path.join(dir, 'script0.py')).read() self.assert_(text.find('OK') < 0, text) self.assert_(text.find('Hello, world!') > 0, text) finally: conn.close()
def applyChanges(self, data): changes = super(SolrControlPanelForm, self).applyChanges(data) boost_script = data.get('boost_script', '').encode('utf-8') if "##parameters=data\n" not in boost_script: boost_script = "##parameters=data\n" + boost_script portal = self.context if self.boost_script_id not in self.context: # "special" documents get boosted during indexing... portal[self.boost_script_id] = PythonScript(self.boost_script_id) # since we create a PythonScript in ZODB we need to # disable CSRF protection alsoProvides(self.request, IDisableCSRFProtection) portal[self.boost_script_id].write(boost_script) return changes
def test_PT_allow_module_not_available_in_RestrictedPython_1(self): src = ''' from AccessControl import Unauthorized try: import Products.PlacelessTranslationService except (ImportError, Unauthorized): raise AssertionError("Failed to import Products.PTS") Products.PlacelessTranslationService.allow_module('os') ''' from Products.PythonScripts.PythonScript import PythonScript script = makerequest(PythonScript('fooscript')) script._filepath = 'fooscript' script.write(src) self.assertRaises((ImportError, Unauthorized), script)
def _test_list_values(self): """ test if a list of values returned by TALES (override) expressions is interpreted properly. If a TALES tab returns a sequence of items and some item is actually a string of length 2 (e.g. "ok"), this previously has lead to a item text of 'o' and a display value of 'k' (as the this is actually a sequence of length 2 ...) See http://sourceforge.net/mailarchive/forum.php?thread_id=1359918&forum_id=1702 Actually the original problem still does not work, as passing a list of int's is not yet supported. If it should, please uncomment the second part of the test. """ # XXX deactivated: this maybe should not be fixed at all self.form.manage_addField('list_field', 'Test List Field', 'ListField') # adding a python script to be called by the override tab # FIXME: the following does not work, as the fake-request # does not have a "form" atribute (?) #self.root.manage_addProduct['PythonScripts'] \ # .manage_addPythonScript('override_test', 'Test for override') # #self.root._getOb('override_test').write("return ['ok', 'no']\n") self.form.override_test = PythonScript('override_test') self.form.override_test.write("return ['ok', 'no']\n") # ps._makeFunction() list_field = getattr(self.form, 'list_field') list_field.values['items'] = [ ('ok', 'ok'), ('no', 'no') ] items1 = list_field.render() # test TALES list_field.tales['items'] = TALESMethod("python:['ok', 'no']") items2 = list_field.render() self.assertEquals(items1, items2) # test override del list_field.tales['items'] list_field.overrides['items'] = Method('override_test') items2 = list_field.render() self.assertEquals(items1, items2)
def installUi(self): '''Installs the user interface.''' # Delete the existing folder if it existed. zopeContent = self.app.objectIds() if 'ui' in zopeContent: self.app.manage_delObjects(['ui']) self.app.manage_addFolder('ui') # Some useful imports from Products.PythonScripts.PythonScript import PythonScript from Products.PageTemplates.ZopePageTemplate import \ manage_addPageTemplate # Browse the physical folder and re-create it in the Zope folder j = os.path.join ui = j(j(appy.getPath(), 'gen'), 'ui') for root, dirs, files in os.walk(ui): folderName = root[len(ui):] # Get the Zope folder that corresponds to this name zopeFolder = self.app.ui if folderName: for name in folderName.strip(os.sep).split(os.sep): zopeFolder = zopeFolder._getOb(name) # Create sub-folders at this level for name in dirs: zopeFolder.manage_addFolder(name) # Create files at this level for name in files: baseName, ext = os.path.splitext(name) f = file(j(root, name)) if ext in gen.File.imageExts: zopeFolder.manage_addImage(name, f) elif ext == '.pt': manage_addPageTemplate(zopeFolder, baseName, '', f.read()) elif ext == '.py': obj = PythonScript(baseName) zopeFolder._setObject(baseName, obj) zopeFolder._getOb(baseName).write(f.read()) else: zopeFolder.manage_addFile(name, f) f.close() # Update the home page if 'index_html' in zopeContent: self.app.manage_delObjects(['index_html']) manage_addPageTemplate(self.app, 'index_html', '', homePage) # Update the error page if 'standard_error_message' in zopeContent: self.app.manage_delObjects(['standard_error_message']) manage_addPageTemplate(self.app, 'standard_error_message', '',errorPage)
def _write(self, text, compile): ''' Parses the source, storing the body, params, title, bindings, and source in self. If compile is set, compiles the function. ''' ps = PythonScript(self.id) ps.write(text) if compile: ps._makeFunction() self._v_ft = ps._v_ft self.func_code = ps.func_code self.func_defaults = ps.func_defaults self._body = ps._body self._params = ps._params self.title = ps.title self._setupBindings(ps.getBindingAssignments().getAssignedNames()) self._source = ps.read() # Find out what the script sees.
def manage_doCustomize(self, folder_path, body=None, RESPONSE=None): ''' Makes a PythonScript with the same code. ''' custFolder = self.getCustomizableObject() fpath = tuple(split(folder_path, '/')) folder = self.restrictedTraverse(fpath) if body is None: body = self.read() id = self.getId() obj = PythonScript(id) folder._verifyObjectPaste(obj, validate_src=0) folder._setObject(id, obj) obj = folder._getOb(id) obj.write(body) if RESPONSE is not None: RESPONSE.redirect('%s/%s/manage_main' % (folder.absolute_url(), id))
def updateScript(self, body, role): # Regenerate Python script object # Sync set of script source code, proxy role and # creation of Python Script object. bodyField = self.schema["ScriptBody"] proxyField = self.schema["ProxyRole"] script = PythonScript(self.title_or_id()) script = script.__of__(self) # Force proxy role if role != "none": script.manage_proxy((role, )) script.ZPythonScript_edit("fields, ploneformgen, request", body) PythonField.set(bodyField, self, script) StringField.set(proxyField, self, role)
def test_constructContent(self): from AccessControl.SecurityManagement import newSecurityManager from AccessControl.SecurityManager import setSecurityPolicy from AccessControl.unauthorized import Unauthorized from Products.PythonScripts.PythonScript import PythonScript from Products.CMFCore.PortalFolder import PortalFolder from Products.CMFCore.TypesTool \ import ScriptableTypeInformation as STI from Products.CMFCore.tests.base.dummy import DummyFactoryDispatcher from Products.CMFCore.tests.base.tidata import STI_SCRIPT site = self.site acl_users = self.acl_users ttool = self.ttool setSecurityPolicy(self._oldPolicy) newSecurityManager(None, acl_users.all_powerful_Oz) self.site._owner = (['acl_users'], 'all_powerful_Oz') sti_baz = STI('Baz', permission='Add portal content', constructor_path='addBaz') ttool._setObject('Baz', sti_baz) ttool._setObject('addBaz', PythonScript('addBaz')) s = ttool.addBaz s.write(STI_SCRIPT) f = site._setObject('folder', PortalFolder(id='folder')) f.manage_addProduct = {'FooProduct': DummyFactoryDispatcher(f)} f._owner = (['acl_users'], 'user_foo') self.assertEqual(f.getOwner(), acl_users.user_foo) ttool.constructContent('Dummy Content', container=f, id='page1') try: ttool.constructContent('Baz', container=f, id='page2') except Unauthorized: self.fail('CMF Collector issue #165 (Ownership bug): ' 'Unauthorized raised') wf = site.portal_workflow.wf wf.creation_guard.changeFromProperties({'guard_expr': 'python:False'}) try: ttool.constructContent('Dummy Content', container=f, id='page3') except Unauthorized, e: self.assertEqual(str(e), "Cannot create Dummy Content")
def _initDCWorkflowScripts( workflow, scripts, context ): """ Initialize DCWorkflow scripts """ for s_info in scripts: id = str( s_info[ 'script_id' ] ) # no unicode! meta_type = s_info[ 'meta_type' ] filename = s_info[ 'filename' ] file = '' if filename: file = context.readDataFile( filename ) if meta_type == PythonScript.meta_type: script = PythonScript( id ) script.write( file ) elif meta_type == ExternalMethod.meta_type: script = ExternalMethod( id , '' , s_info['module'] , s_info['function'] ) elif meta_type == DTMLMethod.meta_type: script = DTMLMethod( file, __name__=id ) else: for mt in workflow.scripts.filtered_meta_types(): if mt['name']==meta_type: if hasattr(mt['instance'], 'write'): script = mt['instance'](id) script.write(file) else: script = mt['instance'](file, __name__=id) break else: raise ValueError, 'Invalid type: %s' % meta_type if workflow.scripts.has_key(id): workflow.scripts._delObject(id) workflow.scripts._setObject( id, script )
def getScript(self, context): # Generate Python script object body = self.ScriptBody role = self.ProxyRole script = PythonScript(self.__name__) script = script.__of__(context) # Skip check roles script._validateProxy = lambda i=None: None # Force proxy role if role != u'none': script.manage_proxy((role, )) body = body.encode('utf-8') params = 'fields, easyform, request' script.ZPythonScript_edit(params, body) return script