ŕ œXž`¸‹ '¸ş”  "5k> Jů * /=¸ş”I Qauthor David Brown authorEmailddb@namshub.orgbuildNum descriptionŤA Python IDE and Web Services Framework. Edit and debug Python Scripts within the Radio UserLand environment. Interactively develop and deploy Python-based Web Services. homePageUrl!http://radio.weblogs.com/0100039/name Python IDE releaseDateversion1.0a1ÂáKVerdana ¸‹ ¸ŒnSË]“ŢLAND˙˙˙˙˙˙mac on expand() try pythonSuite.file.expand() else dialog.alert("oops.") €€€€€á™Verdana ¸˜ä¸žýśáŠ”LAND˙˙˙˙˙˙mac pythonSuite.file.execute() €™Ľ'Verdana ¸Îo¸žýÎ'ďLAND˙˙˙˙˙˙mac pythonSuite.file.executeInBackground() €ĽŸ!Verdana ¸ä¸™*'ďLAND˙˙˙˙˙˙mac pythonSuite.file.newPythonFile() €Ÿ›Verdana ¸ä-¸ôĚ'ďLAND˙˙˙˙˙˙mac pythonSuite.file.newFolder() €›˜Verdana P¸;˸;ŃÖž”LAND˙˙˙˙˙˙mac pythonSuite.file.rename() €˜Ÿ Verdana ¸;˸?ŇÖž”LAND˙˙˙˙˙˙mac pythonSuite.file.delete() €€Ÿg‚mVerdana ¸˜É¸?ÍRኔLAND˙˙˙˙˙˙mac pythonFile Execute Execute in Background - New Python File... New Folder... - Rename... Delete... - €€ € ¸€ € i€ €€ ť€ _€gp NŒlwVerdana —e‹ip°V$¸‹ >¸˜É  "expandx&rightClickMenux}VVerdana Ť‚5@xÖ°ăMVerdana ¸‹ ¸Œk¤Ë]“ŢLAND˙˙˙˙˙˙mac on expand() try pythonSuite.folder.expand() else dialog.alert("oops.") €€€€€ăšVerdana ¸ŒŻ?¸ŒŻO 'ďLAND˙˙˙˙˙˙mac pythonSuite.folder.expand() €šŻ +Verdana ¸Œxƒ¸ŒŞ\'ďLAND˙˙˙˙˙˙mac pythonSuite.menuCommands.folder.newFile() €€ŻŞ,Verdana T¸Œxú¸Œy 'ďLAND˙˙˙˙˙˙mac pythonSuite.menuCommands.folder.newFolder() €ŞšVerdana P¸>}¸>‰Öž”LAND˙˙˙˙˙˙mac pythonSuite.folder.rename() €ššVerdana ¸>}¸?äÖž”LAND˙˙˙˙˙˙mac pythonSuite.folder.delete() €šRFVerdana ¸Œxb¸?Ţ9'ďLAND˙˙˙˙˙˙mac python New Python File... New Folder... - Rename... Delete... - €€ J€ €€ ť€ a€pi˛NVerdana ”!_pws.¸‹ N¸ŒŻ?  & 5expand( ľreturn( ¤rightClickMenu(#w`\$¸‹ &¸žýđ  ( pythonFileřůpythonFileFolderřŸ`VŔVerdana ¸‹ &¸‹ & 'ďLAND˙˙˙˙˙˙mac on any (pta) //boilerplate for your responder pta^.responseHeaders.["Content-Type"] = "text/html" pta^.code = 200 //everything was OK pta^.responseBody = "" //build response return (true) €€€€€V2.¸‹ &¸‹ & anyŽ2‹‡.¸‹ &¸‹ & 9A I condition+(string.lower (path) beginsWith "/python/")enabledmethodsˆđ‹§ #Verdana ¸ŒĹ$¸ŒĹ/'ďLAND˙˙˙˙˙˙mac on dialogAlert(s) dialog.alert(s) €€§-*‹Verdana ¸ŒĆ¸ŒÇ€ 'ďLAND˙˙˙˙˙˙mac on fileDialog(s) local (fname) local (result = file.getFileDialog(s, @fname, 0)) if result return (string(fname)) else return ("") €€€€€€€- "Verdana ¸ŒŽj¸ŒŽy'ďLAND˙˙˙˙˙˙mac dialog.alert("Hello from Python") € Tlp Verdana ¸Š”ő¸ş‡3šĹîWLAND˙˙˙˙˙˙mac on showOutput(result, name="python script") local (dataptr = pythonSuite.init()) if not defined(dataptr^.transcript) new (tabletype, @dataptr^.transcript) local (oldTarget = target.set(@dataptr^.transcript)) op.setDisplay(false) op.firstsummit() op.collapse() op.insert("Executed " + name + " at " + clock.now(), up) if result != "" result = string.replaceAll(result, "\r\n", "\n") result = string.replaceAll(result, "\n", "\r") local (pythonOutput) op.newOutlineObject(result, @pythonOutput) op.insertOutline(@pythonOutput, right) op.setDisplay(true) target.set(oldTarget) edit(@dataptr^.transcript) €€€€€€€€€€€€€€€€€€T˜”8¸‹ &¸Š•  #/ 5A L dialogAlertřĹ fileDialogřxhellořą showOutputř]˜ ¸‹ &¸‹ & ›Verdana ¸‹ &¸‹ &'ďLAND˙˙˙˙˙˙mac This script runs every hour. „›Verdana ¸‹ &¸‹ &'ďLAND˙˙˙˙˙˙mac This script runs every minute. „œVerdana ¸‹ &¸‹ &'ďLAND˙˙˙˙˙˙mac This script runs every night. „œ{w.¸‹ &¸‹ &  ". 9 everyHour everyMinute4 everyNightÝ{ ¸‹ '¸R¨ ¸‹ '¸‹ ' RN$¸‹ '¸‹ '  fileMenu( user(8R™Verdana ¸-l¸‘ŢzÓƒLAND˙˙˙˙˙˙mac pythonSuite.file.execute() €™;7¸-l¸-l 00000001 Run(Â;şŠ¸Verdana ˇî?'¸ŠYH|ĘźÍLAND˙˙˙˙˙˙mac Changes 2/24/02; 4:48:22 pm by ddb borrowed and adapted for the python tool 1/15/02; 5:21:20 PM by DW Runs on the user's machine, when refreshing. local (adrtable = @system.temp.pythonSnapshot) pythonInfo = adrtable^.info pythonSuite = adrtable^.suite pythonThread = adrtable^.thread pythonWebsite = adrtable^.website pythonWindowTypes = adrtable^.windowTypes pythonResponder = adrtable^.responder pythonNodeTypes = adrtable^.nodeTypes pythonRpcHandlers = adrtable^.rpcHandlers filemenu.savemyroot (@pythonSuite) local (x = string.parseAddress (@pythonSuite), f = x [1]) frontier.tools.install (f) dialog.notify ("Thanks for updating. The new build number is " + pythonInfo.buildNum) „€€„€€€€€€„€€„€€€€€€€€€şąNëVerdana ˇî?ޏžĘËn4“ěLAND˙˙˙˙˙˙mac 2/24/02; 4:52:14 pm by ddb borrowed and adapted for the python tool 1/15/02; 5:18:06 PM by DW This is the Refresh menu command. local (url = "http://radio.weblogs.com/0100039/gems/pythonToolFreshener.fttb") local (urllist = string.urlsplit (url)) local (s = tcp.httpclient (server:urllist [2], path:urllist [3])) local (f = frontier.pathstring + "pythonToolFreshener.fttb") file.writewholefile (f, s) fatpages.importfatfile (f) thread.callscript (@system.temp.pythonSnapshot.loader, {}) „€„€€€€€€€€€€ą˛X$¸RŽ?¸žŃ  $ loadNewCode(Ž refreshCode(!tVArial Ş‚3x¤1˛ö0NVerdana ¸Oň¸çœňŤĐĆLAND˙˙˙˙˙˙mac on fixLocation(adr, path) for (d in adr) local (newLocation = path + file.getPathChar() + nameOf(d^)) d^.location = newLocation if d^.nodeType == "pythonFileFolder" pythonSuite.db.fixLocation(@d^.contents, newLocation) bundle fixLocation(@pythonData.test.radio.contents, "osx:Users:ddb:Applications:Radio UserLand:Python") €€€€€€„€öšTíVerdana ¸ů#¸™tî-sLAND˙˙˙˙˙˙mac on isSystem(adr) return true if this address points at something we want to mark as essential to the system. 2/13/02; 11:07:01 AM by DB created local (dataptr = frontier.openDataFile("pythonData")) while (adr != @dataptr^.code) if defined(adr^.flSystem) if adr^.flSystem return (true) adr = parentOf(adr^) return (false) bundle dialog.alert(isSystem(@pythonData.code.contents.["phi.py"])) dialog.alert(isSystem(@pythonData.code.contents.radio.contents.["framework.py"])) €„€€€€€€€€€€€€šĺ<1Verdana ¸ăY¸”œHV].[LAND˙˙˙˙˙˙mac on writeTree(adr) for (d in adr) case d^.nodeType "pythonFile" pythonSuite.file.saveFile(@d^.contents, d^.location) "pythonFileFolder" file.sureFolder(d^.location) pythonSuite.db.writeTree(@d^.contents) else scriptError("unknown nodeType: " + d^.nodeType + " at: " + nameOf(d^)) €€€€€€€€€€ĺyu.¸O۸ů#  !- 7 fixLocation $ďisSystem &ń writeTree )śyÂ<Verdana śżꏙLa† ´3LAND˙˙˙˙˙˙mac 1/13/01; 9:13:34 AM by DW Visit all objects in all open databases looking for objects that contain a string you enter in a dialog. Create a list in scratchpad.objectsThatContainString. Changes: 2/22/01; 3:07:24 PM by PBS Do a case-inensitive search. if dialog.ask ("What string would you like to search for?", @scratchpad.lastsearchstring) local (lowerSearchString = string.lower (scratchpad.lastsearchstring)) //PBS 02/22/01: case-insensitive local (ct = 0) local (adroutline = @scratchpad.objectsThatContainString, insertdir = right) bundle //set up the outline new (outlinetype, adroutline); edit (adroutline) target.set (adroutline) op.firstsummit () op.setlinetext ("Objects that contain \"" + scratchpad.lastsearchstring + "\" on " + clock.now () + ":") window.about () on dotable (adrtable) on addadr (adr) if adr == @scratchpad.lastsearchstring return local (s = string (adr)) local (pattern = "\"].") local (ix = string.patternmatch (pattern, s)) if ix > 0 s = string.delete (s, 1, ix + sizeof (pattern) - 1) op.insert (s + " (" + sizeof (adr^) + ")", insertdir); insertdir = down local (adr) for adr in adrtable case typeof (adr^) tabletype dotable (adr) else try if string.lower (string (adr^)) contains lowerSearchString //PBS 02/22/01: case-inensitive addadr (adr) if (++ct % 1000) == 0 msg (ct) filemenu.save () return (true) dotable (@pythonSuite) dotable (@pythonNodeTypes) dotable (@pythonRpcHandlers) dotable (@pythonWindowTypes) op.firstsummit () edit (adroutline) msg ("") „€€€€€€€€€€€€€€€€€€€€€€€€€€€€Â6qVerdana ¸+„¸›Ţą8LAND˙˙˙˙˙˙mac local (adrButtonTable = @pythonSuite.codeButtons) new (tableType, adrButtonTable) local (ix = 0) on addScript (name, scriptText) ix++ name = "0000000" + ix + "\t" + name script.newScriptObject (scriptText, @adrButtonTable^.[name]) addScript ("Run", "pythonSuite.menuCommands.file.execute()") addScript ("Save", "pythonSuite.menuCommands.file.executeInBackground()") €€€€€€€„„ENVerdana¸+„¸Ffŕą4LAND˙˙˙˙˙˙mac local (adrButtonTable = @pythonSuite.outlineButtons) new (tableType, adrButtonTable) local (ix = 0) on addScript (name) local (scriptText = "dialog.alert(\"" + name + "\")") ix++ name = "0000000" + ix + "\t" + name script.newScriptObject (scriptText, @adrButtonTable^.[name]) addScript("Run") addScript("New File") addScript("New Folder") addScript("Rename") addScript("Delete") €€€€€€€€€€€€€EBYVerdana ¸+„¸›öŕđĂLAND˙˙˙˙˙˙mac local (adrButtonTable = @pythonSuite.projectButtons) new (tableType, adrButtonTable) local (ix = 0) on addScript (name) local (scriptText = "dialog.alert(\"" + name + "\")") ix++ name = "0000000" + ix + "\t" + name script.newScriptObject (scriptText, @adrButtonTable^.[name]) addScript("New Project") addScript("Rename") addScript("Delete") €€€€€€€€€€€ąNëVerdana ˇî?ޏ 'šr4“ěLAND˙˙˙˙˙˙mac 2/24/02; 4:52:14 pm by ddb borrowed and adapted for the python tool 1/15/02; 5:18:06 PM by DW This is the Refresh menu command. local (url = "http://radio.weblogs.com/0101072/gems/pythonToolFreshener.fttb") local (urllist = string.urlsplit (url)) local (s = tcp.httpclient (server:urllist [2], path:urllist [3])) local (f = frontier.pathstring + "pythonToolFreshener.fttb") file.writewholefile (f, s) fatpages.importfatfile (f) thread.callscript (@system.temp.pythonSnapshot.loader, {}) „€„€€€€€€€€€€ąŮ UVerdana ¸žĐń¸žĐö'ďLAND˙˙˙˙˙˙mac local (x = string.parseAddress (@pythonSuite), f = x [1]) frontier.tools.install (f) €€Ů >2”!Verdana ˇî=÷¸ŠY 6 xLLAND˙˙˙˙˙˙mac on releaseNewCode(g, r) Changes 2/24/02; 6:23:11 pm by ddb factored to create unique release scripts for OS X and Win32, added tool versioning code. Each new release also stashes the current version of the tool at pythonData.toolVersions.[date of release] for archival purposes. It makes it easier to return to a previous version some script. 2/24/02; 4:53:05 pm by ddb borrowed and adapted for the python tool. Oh, and what he says below is accurate. 1/15/02; 5:08:55 PM by DW Created. I run this on my machine to create a package for refreshCode to load. Talk about a Mobius Strip. It's really simple code, but it's fun to walk your mind through it. bundle in the python tool, a separate data file is used, so this part isn't necessary. local (oldpythonData) bundle //get pythonData ready for ship oldpythonData = pythonData new (tabletype, @pythonData) pythonThread.enabled = true pythonInfo.releaseDate = clock.now () local (adrtable = @system.temp.pythonSnapshot) new (tabletype, adrtable) pythonInfo.buildNum++ adrtable^.info = pythonInfo adrtable^.suite = pythonSuite adrtable^.thread = pythonThread adrtable^.windowTypes = pythonWindowTypes adrtable^.responder = pythonResponder adrtable^.nodeTypes = pythonNodeTypes adrtable^.website = pythonWebsite adrtable^.rpcHandlers = pythonRpcHandlers adrtable^.loader = pythonSuite.codeFreshener.loadNewCode bundle // version the tool code local (dataptr = pythonSuite.init()) if not defined(dataptr^.toolVersions) new (tabletype, @dataptr^.toolVersions) local (versionAdr = @dataptr^.toolVersions.[clock.now()]) versionAdr^ = adrtable^ local (f = g) file.surefilepath (f) export.sendobject (adrtable, f) f = r target.set (this) fileMenu.saveCopy (f) pythonData = oldpythonData dialog.alert (file.filefrompath (f) + " is " + string.megabytestring (file.size (f)) + ", version is " + pythonInfo.buildNum) €„€„€„€€€€€€€„€„€€€€€€€€€€€€€€€€„€ >VĚVerdana ˇî=÷¸žŃúC`…LAND˙˙˙˙˙˙mac local (g = "osx:Users:ddb:Applications:Radio UserLand:www:gems:pythonToolFreshener.fttb") local (r = "osx:Users:ddb:Applications:Radio UserLand:www:gems:python.root") pythonSuite.dev.releaseNewCode(g, r) €€€VLÂVerdana ˇî=÷¸žŃ/ţq­"9LAND˙˙˙˙˙˙mac local (g = "c:\\Program Files\\Radio UserLand\\www\\gems\\pythonToolFreshener.fttb") local (r = "c:\\Program Files\\Radio UserLand\\www\\gems\\python.root") pythonSuite.dev.releaseNewCode(g, r) €€€LýsVerdana¸!H¸AŠýhELAND˙˙˙˙˙˙mac pythonSuite.initialData.code = pythonData.code pythonSuite.initialData.code.source.contents.radio.flSystem = true €€€ý)ŸVerdana ¸!H¸cĆűhILAND˙˙˙˙˙˙mac pythonSuite.initialData.code.source.contents.radio = pythonData.code.source.contents.radio pythonSuite.initialData.code.source.contents.radio.flSystem = true €€€)ˇł~¸!<¸ '­  '3 FR eq …‘ Ľą ŔĚ Ůĺ ö   % findString,,makeCodeButtons3úmakeOutlineButtons6%makeProjectButtons8vrefreshCodeFromWork:•reinstallPythonTool=RreleaseNewCode>7 releaseOnOSXGreleaseOnWindowsHăsaveCodeJ; saveFrameworkKDˇő0MVerdana ¸E¸aŤě§­LAND˙˙˙˙˙˙mac local (svr = "xmlrpc://127.0.0.1:" + pythonData.prefs.portCurrent + "/RPC2") try [svr].ping() else if dialog.confirm("To run a Python Script, we need to launch the Framework. Should we do this now?") pythonSuite.exec.launchFramework() else scriptError("Cannot execute the Python Script because the framework isn't running.") €€€€€€€€őf<Verdana ¸ѸU¸ULuLAND˙˙˙˙˙˙mac local (dataptr = pythonSuite.init()) bundle // testing if defined (dataptr^.code) if defined (dataptr^.code.contents) if defined (dataptr^.code.contents.radio) if defined (dataptr^.code.contents.radio.contents) msg("it's all here") else dialog.alert("dataptr^.code.contents.radio.contents") else dialog.alert("dataptr^.code.contents.radio") else dialog.alert("dataptr^.code.contents") else dialog.alert("dataptr^.code") pythonSuite.file.launchFile(@dataptr^.code.source.contents.radio.contents.["framework.py"]) clock.waitSeconds(5) €„€€c_$¸8¸Ń  +checkFramework N<launchFramework P=cš6 Verdana ¸:۸ŸŽ(<âM7LAND˙˙˙˙˙˙mac local (adr); op.attributes.getOne("address", @adr) op.setDisplay(false) if dialog.confirm("Are you sure you wish to delete " + op.getLineText() + "?") try file.delete(adr^.location) delete(adr) if op.go(left, 1) pythonSuite.folder.expand() op.setDisplay(true) €€€€€€€€€šK”?#Verdana +¸‘ܸş2 )čŻ^@LAND˙˙˙˙˙˙mac on execute() local (adr = pythonSuite.util.getAddressFromWindow()) pythonSuite.file.saveFile(@adr^.contents, adr^.location) local (filePath = adr^.location) local (dataptr = pythonSuite.init()) local (et = pythonSuite.initialData.executionTemplate) local (template = @et) bundle // insert code to execute into the template local (oldTarget = target.set(template)) op.firstSummit() while op.getLineText() != "{code}" op.go(flatdown, 1) op.insertOutline(@adr^.contents, down) op.deleteLine() target.set(oldTarget) on saveFile(adrOutline, file, fileName) local (s = "") local (scriptName = file.fileFromPath(fileName)) fileName = pythonSuite.file.hackPath(fileName) on visitList(adrList, level = 0, isComment = false, commentLevel = 0) for (oadr in adrList) local (comment = isComment) try if xml.getAttributeValue(oadr, "isComment") == "true" comment = true if not isComment commentLevel = level if comment s = (s + string.filledString(" ", commentLevel) + "## " + string.filledString(" ", level - commentLevel)); else s = (s + string.filledString(" ", level)); local (text = xml.entityDecode(xml.getAttributeValue(oadr, "text"), true)) if not comment and text beginsWith "bundle:" just eat the bundle and write out the next level without increasing the indent local (bci = string.patternMatch("#", text)) if (bci != 0) text = string.mid(text, bci, string.length(text) - bci + 1) s = (s + text + "\n") visitList(xml.getAddressList(oadr, "outline"), level, comment, commentLevel) else s = (s + text + "\n"); s = string.replaceAll(s, "{filePath}", fileName) s = string.replaceAll(s, "{scriptName}", scriptName) visitList(xml.getAddressList(oadr, "outline"), level + 1, comment, commentLevel) local (xmlTable) xml.compile(op.outlineToXML(adrOutline), @xmlTable) local (body = xml.getAddress(@xmlTable, "opml")) body = xml.getAddress(body, "body") visitList(xml.getAddressList(body, "outline")) file.writeWholeFile(file, s) local (pc = file.getPathChar()) local (snippet = string.popSuffix(adr^.location) + "__execScript__.py") saveFile(template, snippet, filePath) case sys.os() "WinNT" "Win95" launch.appWithDocument(dataptr^.prefs.pythonApp, "\"" + snippet + "\"") "MacOS" launch.appWithDocument(dataptr^.prefs.pythonApp, snippet) on execute() local (adr = pythonSuite.util.getAddressFromWindow()) pythonSuite.file.saveFile(@adr^.contents, adr^.location) local (filePath = adr^.location) local (dataptr = pythonSuite.init()) local (template = @pythonSuite.initialData.executionTemplate) on saveFile(adrOutline, file, fileName) local (s = "") local (scriptName = file.fileFromPath(fileName)) fileName = pythonSuite.file.hackPath(fileName) on visitList(adrList, level = 0, isComment = false, commentLevel = 0) for (oadr in adrList) local (comment = isComment) try if xml.getAttributeValue(oadr, "isComment") == "true" comment = true if not isComment commentLevel = level if comment s = (s + string.filledString(" ", commentLevel) + "## " + string.filledString(" ", level - commentLevel)); else s = (s + string.filledString(" ", level)); s = (s + xml.entityDecode(xml.getAttributeValue(oadr, "text"), true) + "\n"); s = string.replaceAll(s, "{filePath}", fileName) s = string.replaceAll(s, "{scriptName}", scriptName) visitList(xml.getAddressList(oadr, "outline"), level + 1, comment, commentLevel) local (xmlTable) xml.compile(op.outlineToXML(adrOutline), @xmlTable) local (body = xml.getAddress(@xmlTable, "opml")) body = xml.getAddress(body, "body") visitList(xml.getAddressList(body, "outline")) file.writeWholeFile(file, s) local (pc = file.getPathChar()) local (snippet = string.popSuffix(adr^.location) + "__execScript__.py") saveFile(template, snippet, filePath) case sys.os() "WinNT" "Win95" launch.appWithDocument(dataptr^.prefs.pythonApp, "\"" + snippet + "\"") "MacOS" launch.appWithDocument(dataptr^.prefs.pythonApp, snippet) €€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€„€€€€€€€€€€€€€€€€€€€€€„€K|Verdana ¸Œ‹ľ¸ŸÍ2“ĘʼnLAND˙˙˙˙˙˙mac local (dataptr = pythonSuite.init()) local (adr = pythonSuite.util.getAddressFromWindow()) pythonSuite.file.launchFile(adr) €€€ŻBőVerdana ¸‹ ¸›!ä*ş1—ŃLAND˙˙˙˙˙˙mac on expand() local (adr); op.attributes.getOne("address", @adr) local (location); op.attributes.getOne("location", @location) local (title = nameOf(adr^)) local (contentAdr = @adr^.contents) edit(contentAdr, title, false, adrButtonTable:@pythonSuite.codeButtons) edit(contentAdr, title, pythonSuite.db.isSystem(contentAdr), adrButtonTable:@pythonSuite.codeButtons) window.attributes.setOne("type", "pythonFile", contentAdr) window.attributes.setOne("address", adr, contentAdr) bundle expand() €€€€€€„€€€€Ż\B˘ Verdana ¸‘Űx¸žü$'†sLAND˙˙˙˙˙˙mac on hackPath(location) if system.environment.isMac if system.environment.isCarbon local (sd = file.getSystemDisk()) if location beginsWith sd local (len = string.length(sd)) location = string.mid(location, len, string.length(location) - len + 1) location = string.replaceAll(location, ":", "/") if system.environment.isWindows location = string.replaceAll(location, "\\", "/") return (location) €€€€€€€€€€€\Í`őVerdana ¸ę¸‘ň“‡wÍĐLAND˙˙˙˙˙˙mac on launchFile(adr) local (validEntry = false) try if adr^.nodeType == "pythonFile" validEntry = true if validEntry local (dataptr = pythonSuite.init()) pythonSuite.file.save(@adr^.contents) case sys.os() "WinNT" "Win95" launch.appWithDocument(dataptr^.prefs.pythonApp, "\"" + adr^.location + "\"") "MacOS" launch.appWithDocument(dataptr^.prefs.pythonApp, adr^.location) else scriptError("Cannot run script because " + nameOf(adr^) + " is not a valid Python script.") €€€€€€€€€€€€€€€€Í€<ĚVerdana ¸îí¸™5!' uLAND˙˙˙˙˙˙mac on newFile(adr, location, newFileName) local (fileAddr = @adr^.contents.[newFileName]) if defined(fileAddr^) scriptError("Cannot create " + newFileName + " because a file of that name already exists.") return (false) new (tabletype, fileAddr) fileAddr^.nodeType = "pythonFile" fileAddr^.location = location + file.getPathChar() + newFileName new (outlinetype, @fileAddr^.contents) pythonSuite.getPythonFileTemplate(newFileName, @fileAddr^.contents) €€€€€€€€€€€óB9Verdana ¸ô{¸Ÿă",‹MłLAND˙˙˙˙˙˙mac local (adr); op.attributes.getOne("address", @adr) if dialog.ask("Name of new folder?", @newFolder) adr = parentOf(adr^) adr = parentOf(adr^) pythonSuite.folder.newFolder(adr, adr^.location, newFolder) if op.go(left, 1) pythonSuite.folder.expand() else pythonSuite.openCodeOutline() op.find(newFolder) €€€€€€€€€€€ó•ZĂ Verdana ¸ň¸Ÿ<#P”ęŘLAND˙˙˙˙˙˙mac local (addr); op.attributes.getOne("address", @addr) if dialog.ask("Name of new file?", @newFile) if not (newFile endsWith ".py") newFile = newFile + ".py" addr = parentOf(parentOf(addr^)^) local (addr1 = parentOf(addr^)) local (addr2 = parentOf(addr1^)) pythonSuite.file.newFile(addr, addr^.location, newFile) if op.go(left, 1) pythonSuite.folder.expand() else pythonSuite.openCodeOutline() op.find(newFile) pythonSuite.file.expand() €€€€€„„‚€€€€€€€•[N•Verdana ¸:۸Ÿţ$6âyFLAND˙˙˙˙˙˙mac local (adr); op.attributes.getOne("address", @adr) op.setDisplay(false) local (newName) if dialog.ask("What would you like the new name of " + op.getLineText() + " to be?", @newName) if not (newName endsWith ".py") newName = newName + ".py" try file.delete(adr^.location) pythonSuite.renameThing(adr, newName) if op.go(left, 1) pythonSuite.folder.expand() op.find(newName) op.setDisplay(true) €€€€€€€€€€€€€[™<ĺVerdana ¸Œ¤!¸é'H \CLAND˙˙˙˙˙˙mac on save(adr, flClosing = false) try local (fileAdr = parentOf(adr^)) if fileAdr^.nodeType == "pythonFile" pythonSuite.file.saveFile(adr, fileAdr^.location) return (true) else return (false) else return (false) €€€€€€€€€€™NŔVerdana ¸čţ¸•ăć„•“€LAND˙˙˙˙˙˙mac on saveFile(adrOutline, file) local (s = "") on visitList(adrList, level = 0, isComment = false, commentLevel = 0) for (oadr in adrList) local (comment = isComment) local (text = xml.entityDecode(xml.getAttributeValue(oadr, "text"), true)) try if xml.getAttributeValue(oadr, "isComment") == "true" comment = true if not isComment commentLevel = level if comment s = (s + string.filledString(" ", commentLevel) + "## " + string.filledString(" ", level - commentLevel)); else s = (s + string.filledString(" ", level)); if not comment and text beginsWith "bundle:" just eat the bundle and write out the next level without increasing the indent local (bci = string.patternMatch("#", text)) if (bci != 0) text = string.mid(text, bci, string.length(text) - bci + 1) s = (s + text + "\n") visitList(xml.getAddressList(oadr, "outline"), level, comment, commentLevel) else s = (s + text + "\n"); visitList(xml.getAddressList(oadr, "outline"), level + 1, comment, commentLevel) local (xmlTable) xml.compile(op.outlineToXML(adrOutline), @xmlTable) local (body = xml.getAddress(@xmlTable, "opml")) body = xml.getAddress(body, "body") visitList(xml.getAddressList(body, "outline")) file.writeWholeFile(file, s) €€€€€€€€€€€€€€€€„€€€€€€€€€€€€€€€N“ˆ¸‹ ︊’o  ' ;G NZ co z† Žš ¤° žĘ ŃÝ âî ÷deleteSŇexecuteU—executeInBackgroundhîexpandjhackPathlť launchFileo#newFileqü newFoldertˆ newPythonFilev‡renamey(save{saveFile}4“ż6Verdana ¸:۸Ÿ1(ůŔ LAND˙˙˙˙˙˙mac local (adr); op.attributes.getOne("address", @adr) op.setDisplay(false) if dialog.confirm("Are you sure you wish to delete " + op.getLineText() + "?") try file.deleteFolder(adr^.location) delete(adr) if op.go(left, 1) pythonSuite.folder.expand() op.setDisplay(true) €€€€€€€€€żp„tVerdana ¸‹ ݏ™)°JuŘLAND˙˙˙˙˙˙mac on expand() local (adr); op.attributes.getOne("address", @adr) local (location); op.attributes.getOne("location", @location) local (o); new (outlinetype, @o) local (oldTarget = target.set(@o)) local (doInsert = false) for (cptr in @adr^.contents) doInsert = true local (name = nameOf(cptr^)) op.insertAtEndOfList(name) op.reorg(left, 1) op.attributes.setOne("type", cptr^.nodeType) op.attributes.setOne("location", cptr^.location) op.attributes.setOne("address", cptr) if doInsert op.firstSummit() op.deleteLine() target.set(oldTarget) op.deleteSubs() op.insertOutline(@o, right) bundle expand() €€€€€€€€€€€€€€€€€€€€€€pd<°Verdana ¸óR¸™Cŕ˝JLAND˙˙˙˙˙˙mac on newFolder(adr, location, newFolderName) local (fileAddr = @adr^.contents.[newFolderName]) if defined(fileAddr^) scriptError("Cannot create folder " + newFolderName + " because it already exists.") return (false) new (tabletype, fileAddr) fileAddr^.nodeType = "pythonFileFolder" fileAddr^.location = location + file.getPathChar() + newFolderName file.sureFolder(fileAddr^.location) new (tabletype, @fileAddr^.contents) €€€€€€€€€€dB^Verdana ¸:۸ŸE%ńŔ$LAND˙˙˙˙˙˙mac local (adr); op.attributes.getOne("address", @adr) op.setDisplay(false) local (newName) if dialog.ask("What would you like the new name of " + op.getLineText() + " to be?", @newName) try file.deleteFolder(adr^.location) pythonSuite.renameThing(adr, newName) if op.go(left, 1) pythonSuite.folder.expand() op.find(newName) op.setDisplay(true) €€€€€€€€€€€‹8¸‹ ö¸?ž  & 0< Cdelete(…-expand(†ř newFolder(Štrename(ŒäżœŤVerdana ¸F¸‘Ü*ƒipdLAND˙˙˙˙˙˙mac on getPythonFileTemplate(newFile, adr) pythonSuite.init() local (dataptr = pythonSuite.init()) local (template = @dataptr^.prefs.pythonTemplate) local (xml); xml.compile(op.outlineToXML(template), @xml) local (outlineBody) on visitList(adrList) for (oadr in adrList) local (s = xml.entityDecode(xml.getAttributeValue(oadr, "text"), true)) s = string.replaceAll(s, "{filename}", newFile) s = string.replaceAll(s, "{timestamp}", clock.now()) s = string.replaceAll(s, "{initials}", user.prefs.initials) local (sadr = xml.getAttribute(oadr, "text")) sadr^ = xml.entityEncode(s, true) visitList(xml.getAddressList(oadr, "outline")) local (t = xml.getAddress(@xml, "opml")) outlineBody = xml.getAddress(t, "body") visitList(xml.getAddressList(outlineBody, "outline")) local (o); op.xmlToOutline(xml.decompile(@xml), @o) local (oldTarget = target.set(@o)) op.fullExpand() target.set(oldTarget) adr^ = o €€€€€€€€€€€€€€€€€€€€€€€€€€ż ŕt ôVerdana ¸‹%•¸Śu(Nib#]LAND˙˙˙˙˙˙mac ensure sane environment 2/11/02; 11:19:51 AM by DB created bundle // write icons out local (icons = file.folderfrompath(frontier.getprogrampath()) + "Appearance" + file.getPathChar() + "icons") case sys.os() "Win95" "WinNT" local (pythonFile = icons + file.getPathChar() + "pythonFile.bmp") local (pythonFileFolder = icons + file.getPathChar() + "pythonFileFolder.bmp") if not file.exists(pythonFile) file.writeWholeFile(pythonFile, pythonSuite.initialData.icons.windows.pythonFile) if not file.exists(pythonFileFolder) file.writeWholeFile(pythonFileFolder, pythonSuite.initialData.icons.windows.pythonFileFolder) "MacOS" need macos code local (dataptr = frontier.openDataFile("pythonData")) local (location = file.folderfrompath(frontier.getprogrampath()) + "Python") bundle // check for prefs table if not defined(dataptr^.prefs) new (tabletype, @dataptr^.prefs) local (prefs = @dataptr^.prefs) bundle // get location of python interpreter if not defined(prefs^.pythonApp) if not file.getFileDialog("Where is Python?", @dataptr^.prefs.pythonApp, 0) if dialog.confirm("You will not be able to execute your Python Scripts until you download and install a Python Interpreter. Press OK to open your web browser to a page that will allow you to download a Python Interpreter. After installing the interpreter, try your action again.") webBrowser.openURL("http://www.python.org/download") scriptError("No Python Interpreter") bundle // set up initial Python template if not defined(prefs^.pythonTemplate) prefs^.pythonTemplate = pythonSuite.initialData.pythonTemplate bundle // set up initial execution template if not defined(prefs^.executionTemplate) prefs^.executionTemplate = pythonSuite.initialData.executionTemplate bundle // set up the transcript if not defined(dataptr^.transcript) new (outlinetype, @dataptr^.transcript) bundle // turn off dev mode prefs^.flToolDev = false bundle // set up port rotation code if not defined (prefs^.portLower) prefs^.portLower = 8000 prefs^.portUpper = 8010 prefs^.portCurrent = 8000 bundle // save the location of the Python folder if not defined(dataptr^.prefs.pythonFolder) dataptr^.prefs.pythonFolder = location bundle // set up code repository local (initialDataPtr = @pythonSuite.initialData) bundle // set up Python code folder file.sureFolder(location) bundle // set up initial code table if not defined(dataptr^.code) dataptr^.code = initialDataPtr^.code dataptr^.code.source.location = location pythonSuite.db.fixLocation(@dataptr^.code.source.contents, location) pythonSuite.db.writeTree(@dataptr^.code.source.contents) bundle // project stuff if not defined(dataptr^.projects) new (tabletype, @dataptr^.projects) return (dataptr) „€€€€€€€€€€€€€€€„€€€€€€€€€€€€ ŕ´°$¸ ¸ Â u zaddressl["C:\\Program Files\\Radio UserLand\\Data Files\\pythonData.root"].pythonData.code.radio.contents.["phi.py"]type pythonFile´ü” Verdana ¸ ¸´ą~TÝ~LAND˙˙˙˙˙˙mac phi.py, managed by Radio UserLand Illustrate the relationship between the Fibonacci Sequence and the Golden Mean (phi) 2/11/2002; 4:21:27 PM, by DB created version = """phi.py, v0.1, by DB""" first = 1.0 second = 1.0 print "- " * 20 for i in range(25): print "first:", first, "second:", second, \ "ratio:", second / first, first / second next = first + second first = second second = next „$datatabl¸ ¸ €€$datatabl¸ ¸ €$datatabl¸ ¸ €$datatabl¸ ¸ €€€€€€€€€€€€€tp.¸ ¸Ł°  ' 0/atts ĄZcontents ˘nodeType pythonFilet51¸íЏ‘ç˘ phi.pyĽ.5^Z$¸%¸%  contents ĽŽnodeTypepythonFileFolder^51¸ĺú¸% sourceĽď5 Z; Verdana ¸‘Ř\¸ş3M(RH4ęLAND˙˙˙˙˙˙mac import sys, traceback, StringIO import xmlrpclib _ptexec_radio = xmlrpclib.ServerProxy("http://127.0.0.1:5335/RPC2") _ptexec_out = StringIO.StringIO() _ptexec_result = "" try: sys.stdout = _ptexec_out {code} _ptexec_result = _ptexec_out.getvalue() except: errorMessage = "error: %s\n" % str(sys.exc_info()[0]) lineNumber = "reason: %s\n" % str(sys.exc_info()[1]) trace = "trace: %s" % traceback.format_tb(sys.exc_info()[2]) _ptexec_result = _ptexec_out.getvalue() + errorMessage + lineNumber + trace _ptexec_radio.python.showOutput(_ptexec_result, "{scriptName}") €€€€€€€€€€€€€€€ XT$¸ŒŹ€¸Œ­ $ pythonFile????pythonFileFolder????XÄŔ$¸ŒŹŠ¸Vo IZ pythonFile:????BM66(˙˙˙˙˙˙˙˙˙_ ?˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙Ÿ ż@ß ż@@Ÿ ż@ż@@@˙˙˙˙˙˙˙˙˙ż@ß €€€€€€€€€€€€€€``@@˙˙˙˙˙˙ż˙€€€€````€€`` €€````@@˙˙˙?˙˙˙ @ß €€€€``˙˙˙ @@˙Ÿ`€€``˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙żż?ß  Ÿ Ÿ`€€``˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙ż?_ ß ?ß Ÿ`€€ ˙˙˙˙˙˙˙˙˙˙˙˙?ß ß ß ??ż@?ż@ż@€€@@˙˙˙˙˙˙˙˙˙˙˙˙_ Ÿ`Ÿ`Ÿ`ß ż?ß €€€€@@˙˙˙˙˙˙˙˙˙˙˙˙@@````€€€€Ÿ`ß ˙€€€€˙˙˙˙˙˙˙˙˙˙˙˙@@€€€€€€€€€€@```` ˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙__`` ˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙@@˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙??``˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙ @@ ˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙pythonFileFolder:????BM66(˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙ööößßßÖÖÖÖÖÖÖÖÖÖÖÖÖÖÖÖÖÖÖÖÖÖÖÖÖÖÖÖÖÖÖÖÖßßßööööööČČȃƒƒmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmƒƒƒČČČßßß‚ľł~°|ŽyŤv¨ sĽ qŁn lžjœhšg™LLLƒƒƒ"‡şgĚ˙ …¸™˙˙oÔ˙oÔ˙oÔ˙oÔ˙oÔ˙oÔ˙oÔ˙oÔ˙; Ó™˙˙g™nnn%Š˝gĚ˙'Œż™˙˙{ŕ˙{ŕ˙{ŕ˙{ŕ˙{ŕ˙{ŕ˙{ŕ˙{ŕ˙DŠÜ™˙˙hšmmm(ŔgĚ˙-’Ĺ™˙˙…ë˙…ë˙…ë˙…ë˙…ë˙…ë˙…ë˙…ë˙Nłć™˙˙jœmmm*ÂgĚ˙3˜Ë™˙˙‘÷˙‘÷˙‘÷˙‘÷˙‘÷˙‘÷˙‘÷˙‘÷˙Wźď™˙˙lžmmm-’ĹoÔ˙4™Ě™˙˙™˙˙™˙˙™˙˙™˙˙™˙˙™˙˙™˙˙™˙˙`Ĺř™˙˙n nnn/”Ç{ŕ˙-’Ĺ˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙ć˙˙˙˙ qٌŒŒ1–É…ë˙ć˙-’Ĺ-’Ĺ-’Ĺ-’Ĺ-’Ĺ-’Ĺ(Ŕ$‰ź …¸´łłßßß3˜Ë‘÷˙Žô˙Žô˙Žô˙Žô˙Žô˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙|ތŒŒŢŢŢ˙˙˙4™Ě˙˙˙™˙˙™˙˙™˙˙™˙˙˙˙˙%Š˝"‡ş„ˇ‚ľł~°ßßß÷÷÷˙˙˙˙˙˙4™Ě˙˙˙˙˙˙˙˙˙˙˙˙*ÂČČČööö˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙4™Ě3˜Ë1–É/”Çßßßööö˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙ÄPL$¸ŒŹt¸ŒŹŠ  mac Šłwindows ŞPArW Verdana ¸‘Ř\¸ĽšF(ŁbbLAND˙˙˙˙˙˙mac import sys, traceback, StringIO def runcode(path): result = "nothing yet" out = StringIO.StringIO() try: sys.stdout = out execfile(path) result = out.getvalue() except: errorMessage = "error: %s\n" % str(sys.exc_info()[0]) lineNumber = "reason: %s\n" % str(sys.exc_info()[1]) trace = "trace: %s" % traceback.format_tb(sys.exc_info()[2]) result = out.getvalue() + errorMessage + lineNumber + trace return result import xmlrpclib radio = xmlrpclib.ServerProxy("http://127.0.0.1:5335/RPC2") result = runcode("{filePath}") print result radio.python.showOutput(result, "{scriptName}") €€€€€€€€€€€€€€€€€€€A}Verdana ¸JN¸ŸWěn˛ëLAND˙˙˙˙˙˙mac {filename}, managed by Radio UserLand {timestamp}, by {initials} created version = """{filename}, v0.1, by {initials}""" „€€€€ÇĂB¸ŒŹb¸ŚS  #/ 5A Vb qcode(ŚYexecutionTemplate(ښicons(°çoldExecutionTemplate(ąCpythonTemplate(´ÇœVerdana ¸‹ '¸žČ´'ďLAND˙˙˙˙˙˙mac pythonSuite.openCodeOutline() €œË;Verdana ¸Œv¸‘ĺD'ďLAND˙˙˙˙˙˙mac try pythonSuite.file.execute() else dialog.alert("OOPS") €€„€ËĽ'Verdana ¸Ěٸ‘ĺ›'ďLAND˙˙˙˙˙˙mac pythonSuite.file.executeInBackground() €ĽŚ(Verdana T¸žÍF¸žÍe'ďLAND˙˙˙˙˙˙mac pythonSuite.codeFreshener.refreshCode() €ŚĄ#Verdana ¸ë.¸ěÖž”LAND˙˙˙˙˙˙mac pythonSuite.exec.launchFramework() €Ąß [Verdana ¸Ěü¸ađ'ďLAND˙˙˙˙˙˙mac try ["xmlrpc://127.0.0.1:" + pythonData.prefs.portCurrent + "/RPC2"].execution.shutdown() €€ßsxƒVerdana ¸‹ '¸žÖ~ś'ďLAND˙˙˙˙˙˙mac Python Open Code Outline Execute Python File - Execute In Background - Refresh Code... - Launch Framework Shutdown Framework €€ ś‚€ 0ˇ*€€ =¸€€ ¸˛„„ šd„ şspşüŇ*@ŇVerdana Č "pXČVerdana ¸Œ‹ľ¸ŸX5–ĘRÚLAND˙˙˙˙˙˙mac local (dataptr = pythonSuite.init()) local (adr = pythonSuite.util.getAddressFromWindow()) pythonSuite.file.save(@adr^.contents) thread.callscript("pythonSuite.file.executeInThread", {adr^.location}) €€€€X|Verdana ¸Œ‹ľ¸Ÿd1“Ę´‰LAND˙˙˙˙˙˙mac local (dataptr = pythonSuite.init()) local (adr = pythonSuite.util.getAddressFromWindow()) pythonSuite.file.launchFile(adr) €€€`\$¸Œy4¸ňœ  (execute ź÷executeInBackground ž[`<hVerdana ¸Œw7¸ŸoJwޘĂLAND˙˙˙˙˙˙mac local (adr); op.attributes.getOne("address", @adr) local (newFile) if dialog.ask("Name of new file?", @newFile) if not (newFile endsWith ".py") newFile = newFile + ".py" local (location); op.attributes.getOne("location", @location) pythonSuite.file.newFile(adr, location, newFile) pythonSuite.folder.expand() op.find(newFile) pythonSuite.file.expand() €€€€€€€€€€¸*Verdana ¸ŒwP¸Ÿzc`QˆLAND˙˙˙˙˙˙mac local (adr); op.attributes.getOne("address", @adr) local (newFile) if dialog.ask("Name of new folder?", @newFile) local (location); op.attributes.getOne("location", @location) pythonSuite.folder.newFolder(adr, location, newFile) pythonSuite.folder.expand() op.find(newFile) €€€€€€€¸VR$¸Œy/¸ŒŞx  newFileżŮ newFolderÂVPL$¸Œw&¸ŒyK  filePżmfolderPĂĹP´°$¸ ¸ Â u zaddressl["C:\\Program Files\\Radio UserLand\\Data Files\\pythonData.root"].pythonData.code.radio.contents.["phi.py"]type pythonFile´ü” Verdana ¸ ¸´ą~TÝ~LAND˙˙˙˙˙˙mac phi.py, managed by Radio UserLand Illustrate the relationship between the Fibonacci Sequence and the Golden Mean (phi) 2/11/2002; 4:21:27 PM, by DB created version = """phi.py, v0.1, by DB""" first = 1.0 second = 1.0 print "- " * 20 for i in range(25): print "first:", first, "second:", second, \ "ratio:", second / first, first / second next = first + second first = second second = next „$datatabl¸ ¸ €€$datatabl¸ ¸ €$datatabl¸ ¸ €$datatabl¸ ¸ €€€€€€€€€€€€€tp.¸ ¸Ł°  ' 0/attsăcontentsĹCnodeType pythonFiletäŕ.¸yݏ}“ ‘¸}’›  addressˆ["osx:Users:ddb:Applications:Radio UserLand:Data Files:pythonData.root"].pythonData.code.source.contents.radio.contents.["framework.py"] lastSavedtype pythonFileä>ČţVerdana ¸yݏ}’Z+ÂýLAND˙˙˙˙˙˙mac framework.py, managed by Radio UserLand 2/11/2002; 1:37:50 PM, by DB created version = """framework.py, v0.1, by DB""" import server, sys, os, StringIO, xmlrpclib, traceback stillRunning = 1 class ExecutionFramework: def shutdown(self): print "shutdown" global stillRunning stillRunning = 0 return ("ok") def runcode(self, path): oldstdout = sys.stdout result = "nothing yet" try: out = StringIO.StringIO() sys.stdout = out g = globals().copy() l = locals().copy() execfile(path) sys.stdout = oldstdout print "after" result = out.getvalue() except: sys.stdout = oldstdout errorMessage = "error: %s\n" % str(sys.exc_info()[0]) lineNumber = "reason: %s\n" % str(sys.exc_info()[1]) trace = "trace: %s" % traceback.format_tb(sys.exc_info()[2]) result = errorMessage + lineNumber + trace return result class RadioFramework: def __init__(self): self.execution = ExecutionFramework() def ping(self): return "ping" if __name__ == "__main__": radio = xmlrpclib.ServerProxy("http://127.0.0.1:5335/RPC2") port = radio.python.getFrameworkPort() svr = server.SimpleXMLRPCServer(("127.0.0.1", port)) svr.register_instance(RadioFramework()) print "starting up" while stillRunning: svr.handle_request() „$datatabl¸yޏyŽ€$datatabl¸yޏyŽ€$datatabl¸yޏyŽ€$datatabl¸yޏyŽ€€€€€€€€€€€€€„„€€„€€€€€€€€€€€€>ÎĘ8¸yޏg>  ' 0w €/attsČ×contentsÉÇlocationCosx:Users:ddb:Applications:Radio UserLand:Python:radio:framework.pynodeType pythonFileΡł$¸sُsŁ x }addresso["C:\\Program Files\\Radio UserLand\\Data Files\\pythonData.root"].pythonData.code.radio.contents.["server.py"]type pythonFileˇ%b~lVerdana ¸sُ´5)›hOçLAND˙˙˙˙˙˙mac server.py, managed by Radio UserLand 2/11/2002; 1:12:03 PM, by DB created Taken from the SimpleXMLRPCServer.py code available in the PythonLabs XML-RPC distribution. version = """server.py, v0.1, by DB""" """Simple XML-RPC Server. This module can be used to create simple XML-RPC servers by creating a server and either installing functions, a class instance, or by extending the SimpleXMLRPCRequestHandler class. A list of possible usage patterns follows: 1. Install functions: server = SimpleXMLRPCServer(("localhost", 8000)) server.register_function(pow) server.register_function(lambda x,y: x+y, 'add') server.serve_forever() 2. Install an instance: class MyFuncs: def __init__(self): # make all of the string functions available through # string.func_name import string self.string = string def pow(self, x, y): return pow(x, y) def add(self, x, y) : return x + y server = SimpleXMLRPCServer(("localhost", 8000)) server.register_instance(MyFuncs()) server.serve_forever() 3. Install an instance with custom dispatch method: class Math: def _dispatch(self, method, params): if method == 'pow': return apply(pow, params) elif method == 'add': return params[0] + params[1] else: raise 'bad method' server = SimpleXMLRPCServer(("localhost", 8000)) server.register_instance(Math()) server.serve_forever() 4. Subclass SimpleXMLRPCRequestHandler: class MathHandler(SimpleXMLRPCRequestHandler): def _dispatch(self, method, params): try: # We are forcing the 'export_' prefix on methods that are # callable through XML-RPC to prevent potential security # problems func = getattr(self, 'export_' + method) except AttributeError: raise Exception('method "%s" is not supported' % method) else: return apply(func, params) def log_message(self, format, *args): pass # maybe do something fancy like write the messages to a file def export_add(self, x, y): return x + y server = SimpleXMLRPCServer(("localhost", 8000), MathHandler) server.serve_forever() """ Written by Brian Quinlan (brian@sweetapp.com). Based on code written by Fredrik Lundh. import xmlrpclib import SocketServer import BaseHTTPServer import sys class SimpleXMLRPCRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler): """Simple XML-RPC request handler class. Handles all HTTP POST requests and attempts to decode them as XML-RPC requests. XML-RPC requests are dispatched to the _dispatch method, which may be overriden by subclasses. The default implementation attempts to dispatch XML-RPC calls to the functions or instance installed in the server. """ def do_POST(self): """Handles the HTTP POST request. Attempts to interpret all HTTP POST requests as XML-RPC calls, which are forwarded to the _dispatch method for handling. """ try: get arguments data = self.rfile.read(int(self.headers["content-length"])) params, method = xmlrpclib.loads(data) generate response try: response = self._dispatch(method, params) wrap response in a singleton tuple response = (response,) except: report exception back to server response = xmlrpclib.dumps( xmlrpclib.Fault(1, "%s:%s" % (sys.exc_type, sys.exc_value)) ) else: response = xmlrpclib.dumps(response, methodresponse=1) except: internal error, report as HTTP server error self.send_response(500) self.end_headers() else: got a valid XML RPC response self.send_response(200) self.send_header("Content-type", "text/xml") self.send_header("Content-length", str(len(response))) self.end_headers() self.wfile.write(response) shut down the connection self.wfile.flush() self.connection.shutdown(1) def _dispatch(self, method, params): """Dispatches the XML-RPC method. XML-RPC calls are forwarded to a registered function that matches the called XML-RPC method name. If no such function exists then the call is forwarded to the registered instance, if available. If the registered instance has a _dispatch method then that method will be called with the name of the XML-RPC method and it's parameters as a tuple e.g. instance._dispatch('add',(2,3)) If the registered instance does not have a _dispatch method then the instance will be searched to find a matching method and, if found, will be called. Methods beginning with an '_' are considered private and will not be called by SimpleXMLRPCServer. """ def resolve_dotted_attribute(obj, attr): """resolve_dotted_attribute(math, 'cos.__doc__') => math.cos.__doc__ Resolves a dotted attribute name to an object. Raises an AttributeError if any attribute in the chain starts with a '_'. """ for i in attr.split('.'): if i.startswith('_'): raise AttributeError( 'attempt to access private attribute "%s"' % i ) else: obj = getattr(obj,i) return obj func = None try: check to see if a matching function has been registered func = self.server.funcs[method] except KeyError: if self.server.instance is not None: check for a _dispatch method if hasattr(self.server.instance, '_dispatch'): return apply( getattr(self.server.instance,'_dispatch'), (method, params) ) else: call instance method directly try: func = resolve_dotted_attribute( self.server.instance, method ) except AttributeError: pass if func is not None: return apply(func, params) else: raise Exception('method "%s" is not supported' % method) def log_request(self, code='-', size='-'): """Selectively log an accepted request.""" if self.server.logRequests: BaseHTTPServer.BaseHTTPRequestHandler.log_request(self, code, size) class SimpleXMLRPCServer(SocketServer.TCPServer): """Simple XML-RPC server. Simple XML-RPC server that allows functions and a single instance to be installed to handle requests. """ def __init__(self, addr, requestHandler=SimpleXMLRPCRequestHandler, logRequests=1): self.funcs = {} self.logRequests = logRequests self.instance = None SocketServer.TCPServer.__init__(self, addr, requestHandler) def register_instance(self, instance): """Registers an instance to respond to XML-RPC requests. Only one instance can be installed at a time. If the registered instance has a _dispatch method then that method will be called with the name of the XML-RPC method and it's parameters as a tuple e.g. instance._dispatch('add',(2,3)) If the registered instance does not have a _dispatch method then the instance will be searched to find a matching method and, if found, will be called. Methods beginning with an '_' are considered private and will not be called by SimpleXMLRPCServer. If a registered function matches a XML-RPC request, then it will be called instead of the registered instance. """ self.instance = instance def register_function(self, function, name = None): """Registers a function to respond to XML-RPC requests. The optional name argument can be used to set a Unicode name for the function. If an instance is also registered then it will only be called if a matching function is not found. """ if name is None: name = function.__name__ self.funcs[name] = function if __name__ == '__main__': server = SimpleXMLRPCServer(("localhost", 8000)) server.register_function(pow) server.register_function(lambda x,y: x+y, 'add') server.serve_forever() „$datatabl¸sُsŁ€$datatabl¸sُsŁ€$datatabl¸sُsŁ€€$datatabl¸sُsŁ€€€€€€€€€€€€„€€€€€€€€€€€€€%bËÇ8¸sُg>  ' 0t }/attsŃëcontentsŇŽlocation@osx:Users:ddb:Applications:Radio UserLand:Python:radio:server.pynodeType pythonFileË[W$¸NH¸ćX  # framework.py Ń server.py ř[žş8¸NH¸}ş  'a jcontentsřóflSystemlocation6osx:Users:ddb:Applications:Radio UserLand:Python:radionodeTypepythonFileFolderžQM$¸íЏ}ş  phi.pyČWradioůZQ^Z$¸%¸%  contents ú$nodeTypepythonFileFolder^51¸ĺú¸% sourceú5ŠVerdana ¸‘Ř\¸‘â9"źŇ‘LAND˙˙˙˙˙˙mac import sys, traceback, StringIO def runcode(path): result = "nothing yet" out = StringIO.StringIO() sys.stdout = out execfile(path) result = out.getvalue() try: out = StringIO.StringIO() sys.stdout = out execfile(path) result = out.getvalue() except: errorMessage = "error: %s\n" % str(sys.exc_info()[0]) lineNumber = "reason: %s\n" % str(sys.exc_info()[1]) trace = "trace: %s" % traceback.format_tb(sys.exc_info()[2]) result = errorMessage + lineNumber + trace return result import xmlrpclib radio = xmlrpclib.ServerProxy("http://127.0.0.1:5335/RPC2") result = runcode("{filePath}") print result radio.python.showOutput(result) €€€€€€€„„€€€€€€XT$¸ŒŹ€¸Œ­ $ pythonFile????pythonFileFolder????XÄŔ$¸ŒŹŠ¸Vo IZ pythonFile:????BM66(˙˙˙˙˙˙˙˙˙_ ?˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙Ÿ ż@ß ż@@Ÿ ż@ż@@@˙˙˙˙˙˙˙˙˙ż@ß €€€€€€€€€€€€€€``@@˙˙˙˙˙˙ż˙€€€€````€€`` €€````@@˙˙˙?˙˙˙ @ß €€€€``˙˙˙ @@˙Ÿ`€€``˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙żż?ß  Ÿ Ÿ`€€``˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙ż?_ ß ?ß Ÿ`€€ ˙˙˙˙˙˙˙˙˙˙˙˙?ß ß ß ??ż@?ż@ż@€€@@˙˙˙˙˙˙˙˙˙˙˙˙_ Ÿ`Ÿ`Ÿ`ß ż?ß €€€€@@˙˙˙˙˙˙˙˙˙˙˙˙@@````€€€€Ÿ`ß ˙€€€€˙˙˙˙˙˙˙˙˙˙˙˙@@€€€€€€€€€€@```` ˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙__`` ˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙@@˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙??``˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙ @@ ˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙pythonFileFolder:????BM66(˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙ööößßßÖÖÖÖÖÖÖÖÖÖÖÖÖÖÖÖÖÖÖÖÖÖÖÖÖÖÖÖÖÖÖÖÖßßßööööööČČȃƒƒmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmƒƒƒČČČßßß‚ľł~°|ŽyŤv¨ sĽ qŁn lžjœhšg™LLLƒƒƒ"‡şgĚ˙ …¸™˙˙oÔ˙oÔ˙oÔ˙oÔ˙oÔ˙oÔ˙oÔ˙oÔ˙; Ó™˙˙g™nnn%Š˝gĚ˙'Œż™˙˙{ŕ˙{ŕ˙{ŕ˙{ŕ˙{ŕ˙{ŕ˙{ŕ˙{ŕ˙DŠÜ™˙˙hšmmm(ŔgĚ˙-’Ĺ™˙˙…ë˙…ë˙…ë˙…ë˙…ë˙…ë˙…ë˙…ë˙Nłć™˙˙jœmmm*ÂgĚ˙3˜Ë™˙˙‘÷˙‘÷˙‘÷˙‘÷˙‘÷˙‘÷˙‘÷˙‘÷˙Wźď™˙˙lžmmm-’ĹoÔ˙4™Ě™˙˙™˙˙™˙˙™˙˙™˙˙™˙˙™˙˙™˙˙™˙˙`Ĺř™˙˙n nnn/”Ç{ŕ˙-’Ĺ˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙ć˙˙˙˙ qٌŒŒ1–É…ë˙ć˙-’Ĺ-’Ĺ-’Ĺ-’Ĺ-’Ĺ-’Ĺ(Ŕ$‰ź …¸´łłßßß3˜Ë‘÷˙Žô˙Žô˙Žô˙Žô˙Žô˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙|ތŒŒŢŢŢ˙˙˙4™Ě˙˙˙™˙˙™˙˙™˙˙™˙˙˙˙˙%Š˝"‡ş„ˇ‚ľł~°ßßß÷÷÷˙˙˙˙˙˙4™Ě˙˙˙˙˙˙˙˙˙˙˙˙*ÂČČČööö˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙4™Ě3˜Ë1–É/”Çßßßööö˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙ÄPL$¸ŒŹt¸ŒŹŠ  mac ţÇwindows ˙+P |Verdana¸JN¸JŚěn˛ëLAND˙˙˙˙˙˙mac {filename}, managed by Radio UserLand {timestamp}, by {initials} created version = """{filename}, v0.1, by {initials}""" „€€€ œ˜8¸ŒŹb¸‘äˇ  #/ 5A Pcode úëexecutionTemplate ű,icons űpythonTemplate WœLlhVerdana ¸Œc˘¸žČœ9fËHLAND˙˙˙˙˙˙mac local (dataptr = pythonSuite.init()) local (o) new (outlineType, @o) target.set(@o) for (pd in @dataptr^.code) op.insertAtEndOfList(nameOf(pd^)) op.attributes.setOne("type", pd^.nodeType) op.attributes.setOne("address", pd) op.attributes.setOne("location", pd^.location) op.reorg(left, 1) op.firstSummit() op.deleteLine() dataptr^.codeOutline = o edit(@dataptr^.codeOutline, true, "Python Code Outline", @pythonSuite.outlineButtons) window.attributes.setOne("type", "pythonCodeOutline") window.setTitle(@dataptr^.codeOutline, "Python Code Outline") target.set(@dataptr^.codeOutline) pythonSuite.folder.expand() €€€€€€€€€€€€€€€€€€L\lxVerdana ¸Œc˘¸›"t<d§WLAND˙˙˙˙˙˙mac local (dataptr = pythonSuite.init()) local (o) new (outlineType, @o) local (oldtarget = target.set(@o)) for (pd in @dataptr^.projects) op.insertAtEndOfList(pd^) op.attributes.setOne("type", "pythonProjectFolder") op.attributes.setOne("name", pd^) op.reorg(left, 1) op.firstSummit() op.deleteLine() dataptr^.projectOutline = o edit(@dataptr^.projectOutline, "Python Project Outline", true, @pythonSuite.projectButtons) window.attributes.setOne("type", "pythonProjectOutline") target.set(oldtarget) window.setTitle(@scratchpad.codeOutline, "Python Project Outline") target.set(@scratchpad.codeOutline) pythonSuite.folder.expand() €€€€€€€€€€€€€€€„„„\sVerdana ¸Ff¸‘ĺÜSĽLAND˙˙˙˙˙˙mac local (nodeType); op.attributes.getOne("type", @nodeType) case nodeType "pythonFile" pythonSuite.file.execute() €€€€t*ŇVerdana ¸Fg¸y†Š&S¸LAND˙˙˙˙˙˙mac dialog.alert("New File") local (nodeType); op.attributes.getOne("type", @nodeType) case nodeType "pythonFile" pythonSuite.file.newPythonFile() "pythonFileFolder" pythonSuite.menuCommands.folder.newFile() „€€€€€€tt*ŇVerdana¸Fg¸IÜ…žGLAND˙˙˙˙˙˙mac dialog.alert("New Folder") local (nodeType); op.attributes.getOne("type", @nodeType) case nodeType "pythonFile" pythonSuite.file.newFolder() "pythonFileFolder" pythonSuite.menuCommands.folder.newFolder() „€€€€€€t‹.¸Ff¸ŸŘˇ  -9 M 00000001 Run×00000002 New Scriptć00000003 New FolderfĆ BVerdana ¸”–ˇ¸”—'ďLAND˙˙˙˙˙˙mac on load(projectName) return (frontier.openDataFile(projectName)) €€Ć]`… Verdana ¸”–޸›4ÂÝLAND˙˙˙˙˙˙mac on newProject(projectName) local (dataptr = pythonSuite.project.load(projectName)) if defined (dataptr^.code) dialog.alert("Cannot create new project " + projectName + " because a project of that name already exists.") return (false) new (tabletype, @dataptr^.code) local (codeptr = @dataptr^.code.[projectName]) new (tabletype, codeptr) codeptr^.nodeType = "pythonFileFolder" new (tabletype, @codeptr^.contents) local (dptr = pythonSuite.init()) pythonSuite.db.fixLocation(@dataptr^.code, dptr^.prefs.pythonFolder) pythonSuite.db.writeTree(@dataptr^.code) pythonSuite.project.open(projectName) bundle newProject("testProject2") €€€€€€€€€€€€€„€€]x Verdana ¸”™/¸”ą¸‰ţLAND˙˙˙˙˙˙mac on open(projectName) pythonSuite.init() local (projptr = pythonSuite.project.load(projectName)) local (o) new (outlineType, @o) target.set(@o) for (pd in @projptr^.code) op.insertAtEndOfList(nameOf(pd^)) op.attributes.setOne("type", pd^.nodeType) op.attributes.setOne("address", pd) op.attributes.setOne("location", pd^.location) op.reorg(left, 1) op.firstSummit() op.deleteLine() projptr^.codeOutline = o edit(@projptr^.codeOutline, nameOf(projptr^), true, @pythonSuite.outlineButtons) window.attributes.setOne("type", "pythonCodeOutline") window.attributes.setOne("project", projptr) target.set(@projptr^.codeOutline) pythonSuite.folder.expand() €€€€€€€€€€€€€€€€€€€€Verdana ¸”–ł¸”–ł'ďLAND˙˙˙˙˙˙mac €ŕ†8¸”–•¸”ší  ( -9 >loadЁ newProjectĐSopenĐźsaveĐXVVerdana Ť‚5@xÖŕ¤0üVerdana ¸›ř¸›ü(ĂâLAND˙˙˙˙˙˙mac dialog.alert("New Project") local (name) if dialog.ask("New project name:", @name) local (adr = table.uniqueName("project", @pythonData.projects, 4)) adr^ = name pythonSuite.openProjectOutline() op.find(name) pythonSuite.project.newProject(name) €€€€€€€€¤•Verdana ¸›ř¸›ř'ďLAND˙˙˙˙˙˙mac dialog.alert("Rename") €••Verdana ¸›ř¸›ů'ďLAND˙˙˙˙˙˙mac dialog.alert("Delete") €•‹.¸›ř¸›ř ! 1= M00000001 New Project Ď00000002 Rename 00000003 Delete  iÓVerdana¸9[¸<K  LAND˙˙˙˙˙˙mac on renameThing(adr, newName) local (newadr = parentOf(parentOf(adr^)^)) table.rename(adr, newName) pythonSuite.db.fixLocation(@newadr^.contents, newadr^.location) pythonSuite.db.writeTree(@newadr^.contents) €€€€€iÔVVerdana ¸†C¸b ď˘SLAND˙˙˙˙˙˙mac ["xmlrpc://127.0.0.1:" + pythonData.prefs.portCurrent + "/RPC2"].execution.shutdown() €Ô+ §Verdana ¸‹ '¸¨L!'ďLAND˙˙˙˙˙˙mac This script returns a string which appears in the Status Center on the Radio UserLand home page. return ("Build " + pythonInfo.buildNum + ". Why aren't you coding?") „€+f8Verdana ¸ŒCř¸ŒNG)š<xLAND˙˙˙˙˙˙mac local (importDirectory) local (dataptr = frontier.openDataFile("pythonData")) if not defined(dataptr^.test) new (tabletype, @dataptr^.test) local (start = @dataptr^.test) file.getFolderDialog("Which Package to Import?", @importDirectory) dialog.alert(importDirectory) fileloop (f in importDirectory) local (fname = file.fileFromPath(f)) if not file.isFolder(f) and (fname endsWith ".py") msg(fname) clock.waitSixtieths(30) local (s = string(file.readWholeFile(f))) s = string.replaceAll(s, "\n", "\r") op.newOutlineObject(s, @start^.[fname]) edit(start) €€€€€€„€€€€„€€€€€`< Verdana ¸ŒCř¸ŒM~0Á`ŕLAND˙˙˙˙˙˙mac local (importDirectory) local (dataptr = frontier.openDataFile("pythonData")) if not defined(dataptr^.test) new (tabletype, @dataptr^.test) local (start = @dataptr^.test) file.getFileDialog("Which Package to Import?", @importDirectory, 0) dialog.alert(importDirectory) local (fname = file.fileFromPath(importDirectory)) if not file.isFolder(importDirectory) and (fname endsWith ".py") msg(fname) clock.waitSixtieths(30) local (s = string(file.readWholeFile(importDirectory))) s = string.replaceAll(s, "\n", "\r") op.newOutlineObject(s, @start^.[fname]) edit(start) €€€€€€„€€€€€€€€€¤Verdana ¸ŒŹŹ¸Œ­'ďLAND˙˙˙˙˙˙mac local (fname) file.getFileDialog("pick pythonFile", @fname, 0) pythonSuite.initialData.icons.mac.pythonFile = file.readWholeFile(fname) file.getFileDialog("pick pythonFileFolder", @fname, 0) pythonSuite.initialData.icons.mac.pythonFileFolder = file.readWholeFile(fname) €€€€€¤ŹVerdana ¸ŒŹŹ¸VUA§éDLAND˙˙˙˙˙˙mac local (fname) file.getFileDialog("pick pythonFile", @fname, 0) pythonSuite.initialData.icons.windows.pythonFile = file.readWholeFile(fname) file.getFileDialog("pick pythonFileFolder", @fname, 0) pythonSuite.initialData.icons.windows.pythonFileFolder = file.readWholeFile(fname) €€€€€Ź‹0ăVerdana ¸ŒO揌TÁŽĘŔƒLAND˙˙˙˙˙˙mac on testSaveOutline() system.temp.s = "" op.visitAll(@workspace.testOutline, @pythonSuite.testSaveVisit) local (dest) file.getFileDialog("where", @dest, 0) file.writeWholeFile(dest, system.temp.s) bundle testSaveOutline() €€€€€€€€‹š6ěVerdana ¸ŒSH¸ŒTę'ďLAND˙˙˙˙˙˙mac on testSaveVisit() if not defined(system.temp.s) system.temp.s = "" local (s = system.temp.s) s = s + string.filledString(" ", op.level() - 1) if script.isComment() s = s + "## " system.temp.s = s + op.getLineText() + "\n" €€€€€€€€€šž0öVerdana ¸ĹP¸Ĺ}'H.LAND˙˙˙˙˙˙mac local (icons = file.folderfrompath(frontier.getprogrampath()) + "Appearance" + file.getPathChar() + "icons") local (pythonFile = icons + file.getPathChar() + "pythonFile.bmp") local (pythonFileFolder = icons + file.getPathChar() + "pythonFileFolder.bmp") if not file.exists(pythonFile) file.writeWholeFile(pythonFile, pythonSuite.initialData.icons.windows.pythonFile) if not file.exists(pythonFileFolder) file.writeWholeFile(pythonFileFolder, pythonSuite.initialData.icons.windows.pythonFileFolder) €€€€€€€€ž<˘"Verdana ¸ŒUŐ¸Œ^T+´’˛œLAND˙˙˙˙˙˙mac on xmlOutput(adrOutline = @workspace.testOutline) local (s = "") on visitList(adrList, level = 0, isComment = false) for (oadr in adrList) local (comment = isComment) s = s + string.filledString(" ", level) try if xml.getAttributeValue(oadr, "isComment") == "true" comment = true if comment s = s + "## " s = s + xml.entityDecode(xml.getAttributeValue(oadr, "text"), true) + "\n" visitList(xml.getAddressList(oadr, "outline"), level + 1, comment) local (xmlTable) xml.compile(op.outlineToXML(adrOutline), @xmlTable) local (body = xml.getAddress(@xmlTable, "opml")) body = xml.getAddress(body, "body") visitList(xml.getAddressList(body, "outline")) local (dest) file.getFileDialog("where", @dest, 0) file.writeWholeFile(dest, s) bundle xmlOutput() €€€€€€€€€€€€€€€€€€€€€€€€€€€<œB`¸ŒU޸ĹP  *6 GS ht „ žŞ źČ Ň importPythonĐ#čimportPythonFileĐ' readIconFilesMacĐ**readIconFilesWindowsĐ+ÚtestSaveOutlineĐ-’ testSaveVisitĐ/)writeWindowsIconsĐ0Ď xmlOutputĐ3yVVerdana Ť‚5@xÖœ]*ťVerdana¸Fg¸JB‡ŚILAND˙˙˙˙˙˙mac dialog.alert("Rename") local (nodeType); op.attributes.getOne("type", @nodeType) case nodeType "pythonFile" pythonSuite.file.rename() "pythonFileFolder" pythonSuite.folder.rename() „€€€€€€]]*ťVerdana ¸Fg¸Ÿ‰…/ŚLAND˙˙˙˙˙˙mac dialog.alert("Delete") local (nodeType); op.attributes.getOne("type", @nodeType) case nodeType "pythonFile" pythonSuite.file.delete() "pythonFileFolder" pythonSuite.folder.delete() „€€€€€€],˘Verdana ¸™¸9"ČĚÁLAND˙˙˙˙˙˙mac local (location); op.attributes.getOne("location", @location) pythonSuite.exec.checkFramework() thread.callScript("pythonSuite.file.executeInThread", {location}) €€€,mf Verdana ¸Ęa¸aĘÚ .%LAND˙˙˙˙˙˙mac on executeInThread(location) if system.environment.isMac if system.environment.isCarbon local (sd = file.getSystemDisk()) if location beginsWith sd local (len = string.length(sd)) location = string.mid(location, len + 1, string.length(location) - len) location = string.replaceAll(location, ":", "/") local (frmwrk = "xmlrpc://127.0.0.1:" + pythonData.prefs.portCurrent + "/RPC2") op.newOutlineObject("", @scratchpad.pythonOutput) try local (result = [frmwrk].execution.runcode(location)) result = string.replaceAll(result, "\n", "\r") op.newOutlineObject(result, @scratchpad.pythonOutput) edit(@scratchpad.pythonOutput) €€€€€€€€€€€€€€€€€m$ńVerdana ¸_ż¸a'ďLAND˙˙˙˙˙˙mac on getFrameworkPort() local (dataptr = pythonSuite.init()) dataptr^.prefs.portCurrent++ if dataptr^.prefs.portCurrent > dataptr^.prefs.portUpper dataptr^.prefs.portCurrent = dataptr^.prefs.portLower return (dataptr^.prefs.portCurrent) €€€€€€ ¨€Verdana ¸Œ‡x¸™ä$2KA6LAND˙˙˙˙˙˙mac on save() on saveFile(adrOutline, file) local (s = "") on visitList(adrList, level = 0, isComment = false, commentLevel = 0) dialog.alert("commentLevel: " + commentLevel) for (oadr in adrList) local (comment = isComment) s = s + string.filledString(" ", level) try if xml.getAttributeValue(oadr, "isComment") == "true" comment = true if not isComment commentLevel = level if comment s = (s + string.filledString(" ", commentLevel) + "## " + string.filledString(" ", level - commentLevel)); else s = (s + string.filledString(" ", level)); s = (s + xml.entityDecode(xml.getAttributeValue(oadr, "text"), true) + "\n"); visitList(xml.getAddressList(oadr, "outline"), level + 1, comment, commentLevel) local (xmlTable) xml.compile(op.outlineToXML(adrOutline), @xmlTable) local (body = xml.getAddress(@xmlTable, "opml")) body = xml.getAddress(body, "body") visitList(xml.getAddressList(body, "outline")) file.writeWholeFile(file, s) local (adr); window.attributes.getOne("address", @adr) local (location = adr^.location); saveFile(@adr^.contents, location) €€€€€€€„€€€€€€€€€€€€€€€€€€€€ řôL¸T’¸ŸŘˇ  ,8 KW gs „ ˜00000004 Rename9i00000005 Delete:ŇexecuteInFramework<;executeInThread=sgetFrameworkPort@ěsaveOldB…řĄ6óVerdana ¸™ H¸™ |AJ  LAND˙˙˙˙˙˙mac on getAddressFromWindow() local (adr, winType) window.attributes.getOne("type", @winType) case winType "pythonFile" window.attributes.getOne("address", @adr) "pythonCodeOutline" op.attributes.getOne("address", @adr) return (adr) €€€€€€€€€ĄC?¸™ 4¸™ H getAddressFromWindowI5C ‚k¸‹ &¸Š•Z  !- 9E S_ bn r~ ƒ ”  §ł ÉŐ Úć ňţ  ( 7C S_ r~ ™ Ą­ źČ Ôŕ ňţ  #/ 6B G backgroundř… callbacksřd codeButtonsřg codeFreshenerř$1dbř+§devřLyexecřScfileřƒŽfolderřgetPythonFileTemplateřŁinitř”n initialDatařľŻmenuřź{ menuCommandsřÄ'oldInitialDatařoopenCodeOutlineřopenProjectOutlineř ooutlineButtonsřćprojectřăprojectButtonsřÁ renameThingř \shutdownFrameworkř!ŃstatusCenterMessageř"ątestř7ÁunusedřH1utilřJâV Lucida GrandeŽ@FXyűŰ’łVerdana ¸Oø•śO'ďLAND˙˙˙˙˙˙mac background callbacks codeButtons 00000001 Run db dev exec file delete execute executeInBackground expand hackPath launchFile newFile newFolder newPythonFile rename save saveFile folder getPythonFileTemplate init initialData menu menuCommands oldInitialData openCodeOutline outlineButtons project renameThing shutdownFramework statusCenterMessage test unused executeInFramework executeInThread getFrameworkPort saveOld €k,$k,€k,$k,€k,$k,€k,$bšX€k,$k,€k,$k,€k,$k,€k,$k,€k,$k€k,$k€k,$k€k,$k€k,$k€k,$k€k,$k€k,$k€k,$k€k,$k€k,$k€k,$k€k,$k,€k,$k,€k,$k,€k,$k,€k,$k,€k,$k,€k,$k,€k,$k,€k,$k,€k,$k,€k,$k,€k,$k,€k,$k,€k,$k,€k,$k,€k,$t9,€k,$t9,€k,$t9,€k,$t9, ‚Verdana ¸‹ '¸‹ ''ďLAND˙˙˙˙˙˙mac This script runs in its own thread. loop //loop until the application quits Add your code here. thread.sleepFor (10) //sleep for ten seconds „€„€TP.¸‹ '¸™– ctenabledscriptřUżTţtArial śFűśFű9 2ŽLAND˙˙˙˙˙˙mac on finalFilter (pta) pta^.renderedText = string.replace (pta^.renderedText, "[[title]]", "") return (true) €�����€�����€��������ţ���ą�������� ���-����Geneva���������������������������� ��������������­ÂEu´`ŢQ���Ć��� �2LAND˙˙˙˙˙˙������mac ������������on firstFilter (adrPageTable) return (true) €�����€��������ą��ý��������*��[����Geneva���������������������������� ��������������­ÂEuľü7a���–���L�3*lLAND˙˙˙˙˙˙������mac ������������on pageFilter (pta) if typeOf (pta^.template) == outlineType or typeOf (pta^.template) == wpTextType table.assign (@pta^.template, string (pta^.template)) if typeOf (pta^.template) == stringType and not pta^.indirectTemplate pta^.template = string.replace (pta^.template, "<title>", "[[title]]") html.addPageToGlossary (pta) return (true) €�����€�����€�����€�����€�����€�����€�������ý���Ó�������y���.���­ÂEźśFű�������� ���� ��� ����$���0 ����; finalFilter����Ř�WJ firstFilter����Ř�XT pagefilter����Ř�Y��VGeneva���������������������������� ����������č�P�E��$Ď�������������������������Ó���B�������>������ľü7¨¸‹ '�������� ����url���http://127.0.0.1/python/���B���O�������K���$���¸őW¸őW�������� ���� ��� ����linetext���Homepath��� index.wsf���O���V�������R���$���¸÷ø÷Ă�������� ���� ��� ����linetext��� Python Toolpath��� index.wsf���V���j�������f���$���¸XݏXŻ�������� ���� ���, ����1linetext���Python Tool Quick Documentationpath��� docs.html���j���á�������‡���.�������¸XŻ�������� ������� �������) ����IHome����Ř�\G Python Tool����Ř�\˘Python Tool Quick Documentation����Ř�]��VArial����������������������������� ������������������������������������������������á���ą�������W����������¸›$é������������space���/GIFfGIF89a��€��˙˙˙���!ů����,�������D�;��VArial����������������������������� ������������������������������������������������ą���������Ĺ���V�������´ž†�������� ������� �������"�������+ ����0���: ����C���L ����Q���[ ����aalink���008000bgcolor���FFFFFFflRenderlink���0000FFspaceGif���spacetext���000000vlink���800080��VArial����������������������������� ��������������������������������������������������n�����������������¸ö<������VArial����������������������������� ������������������������������������������������n��‹�������n��Ľ����Verdana��������������������������� �����]��������¸W¸›$0��� ���NWĚLAND˙˙˙˙˙˙������mac ������������#title "Radio as a Python IDE" #postTime "2/13/02; 8:53:02 pm" <rules> <rule level="1" to="infinity"> <outlineSpacing>1.5</outlineSpacing> </rule> </rules> The Python Tool allows Radio UserLand to be used as a Python IDE. Radio's integrated outliner turns out to be a wonderful tool for Python editting, and the Tool provides an efficient way to write, debug, and deploy Python code. After dropping the <a href="http://radio.weblogs.com/0100039/gems/python.root">python.root</a> file into your Tools directory (Macintosh users see additional information <a href="#mac">below</a>) and restarting Radio, you will find a new menu in the Tools menu. <% radio.macros.imageRef("images/menu2.jpg") %> Select 'Open Code Outline.' If this is the first time you've run the Python Tool, you will be prompted to locate your copy of Python. Use the standard folder selection dialog to navigate to your copy of Python, and accept it. If you do not have a copy of Python, you can hit 'cancel,' and you will be given the option of having your Web Browser openned to a page that will allow you to download the proper Python interpreter for your platform. Once the tool has been configured, an outline of all the Python source files being managed by the Python Tool will be displayed. If this is the first time you've run the tool, your code outline will look similar to this (this is on OS X, the Python Tool has also been tested on Windows XP, not yet on 2K/NT/95). <% radio.macros.imageRef("images/codeOutline.jpg") %> These files are mirrored into a 'Python' folder in your Radio UserLand application directory. The Python Tool expects to control all activity that happens in the Python directory. It stores all Python Source code internally, and echos it onto the disk for execution. If you edit any of the generated Python source files in an external editor, your edits will be lost the next time the Python Tool regenerates the source code. Double-click on 'phi.py.' <% radio.macros.imageRef("images/phi.jpg") %> This is an example Python source file being editted in Radio UserLand. It is a simple program that shows how the Fibonacci Sequence relates to the Golden Mean (phi). Notice that the outline indentation mirrors the source code indentation in the Python code. You can use all of the outliner's functionality to manipulate Python code. You can even use comments in the same way you would use them in UserTalk. Just hit ctrl/cmd-\, and the line (plus any children) are commented out. When writing out the code to be executed, the Python Tool automatically converts the outline comments into Python comments. To run the Python script, hit the 'Run' toolbar button. <% radio.macros.imageRef("images/pythonOutput.jpg") %> The output appears in an outline window. Using the Code Outline, you can create more scripts and packages. Currently that is all the functionality that exists. More example code is needed. There are some rpc responders that allow Python Scripts to use Radio's file dialog functionality. There will soon be a Python Web Services framework, as well as some UserTalk glue code that allows Python access to Radio's unique ODB. I'm sure that Murphy has provided some road blocks that limit the kinds of scripts that you can develop in this IDE, but I can't think of any. When a script is executed, it is executed in a Radio thread, so you could even do wxPython programming if you wanted. If it runs on Python, it should run in the IDE. I can see even doing ZODB development with it. It excites me that Radio allows me to develop an IDE that feels as useful as a Smalltalk IDE. For me, that is high praise. <a name="mac">Mac Tips:</a> You must grab <a href="http://www.namshub.org/pythonIcons.sit">this archive of icon files</a> and unpack it in 'Radio Userland/Appearance/Icons' to see the icons. I'm not sure how to read in and write out a resource file, so I have to pack them separately. <a href="<% radio.macros.imageUrl("images/pythonTool.jpg") %>">screenshot</a> €����$datatabl����������¸›$¸›$����€����$datatabl����������¸›$¸›$����€����$datatabl����������¸›$¸›$���������$datatabl����������¸›$¸›$���������$datatabl����������¸›$¸›$���������$datatabl����������¸›$¸›$���������$datatabl����������¸›$¸›$����€����$datatabl����������¸›$¸›$����€����$datatabl����������¸›$¸›$����€����$datatabl����������¸›$¸›$����€����$datatabl����������¸›$¸›$����€����$datatabl����������¸›$¸›$����€����$datatabl����������¸›$¸›$����€����$datatabl����������¸›$¸›$����€����$datatabl����������¸›$¸›$����€����$datatabl����������¸›$¸›$����€����$datatabl����������¸›$¸›$����€����$datatabl����������¸›$¸›$����€����$datatabl����������¸›$¸›$����€����$datatabl����������¸›$¸›$����€����$datatabl����������¸›$¸›$����€����$datatabl����������¸›$¸›$����€����$datatabl����������¸›$¸›$����€����$datatabl����������¸›$¸›$����€����$datatabl����������¸›$¸›$����€����$datatabl����������¸›$¸›$����€����$datatabl����������¸›$¸›$������‹���������€�� ���Verdana��������������������������� �������������¸ř@¸ű���*��/íéLAND˙˙˙˙˙˙������mac ������������#title "Python Tool" #renderoutlinewith "pikeRenderer" <rules> <rule level="1" to="infinity"> <outlineSpacing>1.5</outlineSpacing> </rule> <rule level="2" to="infinity"> <leftIndent>15</leftIndent> </rule> </rules> python IDE goal state: A Radio Tool for general Python scripting and Python Web Service Creation and Management. tasks write python with Radio store code outline in odb, mirror code to disk. Directory defaults to "python" within the radio installation directory, actual mirroring location can be configured through tool web pages. Multiple directories can eventually be managed. write web framework At first, the web framework will be there to execute new code and capture output. Eventually it will serve as a general web services framework, with the ability to configure which codes is being served, as well as whether the service is available locally, or globally, or to a limitted subset of clients. Perhaps even define and deploy a service directory framework -- someone could query a service and recieve a list and description of services made available by other users of the tool (and make the api open so that other tools can register their presence. Hmmm. Presence. Perhaps Jabber figures into all of this.) I see being able to go into an outline view of the Python Packages being managed by Radio and marking services to be made available, with a visual indication that a particular package is currently being served. write radio connectivity provide get/set ability for the UserTalk data types that are useable within XML-RPC. Provide iteration methods for the python side. include simple interaction capabilities, i.e. dialogs, simple alerting more IDE features senders with bar cursor on method definition, open a new outline with a list of all known methods that call this method implementers with bar cursor on a method call, open a new outline with a list of all known methods that implement the method beign called. docstring browsing browse class definitions along the PYTHONPATH, open an outline for each class that has a list of methods implemented in each class, with the docstring for each method (and the class) as children in the outline. instance inspecting open an outline representing the named object, with slots as children, and slot values as children of the slot name. Allow drilling down if the slot value type allows (lists, dictionaries, classes) allow read-only importation of the PYTHONPATH be able to browse definitions and files along PYTHONPATH in a read only manner, allowing all previous functionality specified narrative convert usertalk comment marks to and from python comment marks, this allows the same coding conventions within the outline -- you can hit comment on an entire outline branch and it will get converted at first there will be a menu command that invokes launch.anything() on the python code being editted. Eventually we will be able to install and run code on the fly, with output being displayed in an outline window. €�����€�����€�����€�����€�����€�����€�����€�����€�����€�����€����$datatabl�x���������¸řx¸řx���������$datatabl�x���������¸řx¸řx���������$datatabl�x���������¸řx¸řx���������$datatabl�x���������¸řx¸řx���������$datatabl�x���������¸řx¸řx���������$datatabl�x���������¸řx¸řx���������$datatabl�x���������¸řx¸řx���������$datatabl�y���������¸řx¸řy���������$datatabl�y���������¸řx¸řy���������$datatabl�y���������¸řx¸řy���������$datatabl�y���������¸řx¸řy���������$datatabl�y���������¸řx¸řy���������$datatabl�y���������¸řx¸řy���������$datatabl�y���������¸řx¸řy���������$datatabl�y���������¸řx¸řy���������$datatabl�y���������¸řx¸řy���������$datatabl�y���������¸řx¸řy���������$datatabl�y���������¸řx¸řy���������$datatabl�y���������¸řx¸řy���������$datatabl�y���������¸řx¸řy���������$datatabl�y���������¸řx¸řy���������$datatabl�y���������¸řx¸řy���������$datatabl�y���������¸řx¸řy���������$datatabl�y���������¸řx¸řy���������$datatabl�y���������¸řx¸řy���������$datatabl�y���������¸řx¸řy��������`���������`���ľü7¸›$A�������� ���� ��� �������* ����4���@ ����H���T ����[���g ����n���z ����€���Œ ����–#filters����ř�[#ftpSite����ř�[ů #glossary����ř�]z#images����ř�^g#prefs����ř�_$#tools����ř�`Oindex�����ř�`É index.old�����ř�u`��VVerdana��������������������������� ����������ş�“�??8“ň������������������������`���ú�����������j���Verdana��������������������������� ��������������¸Œ†<¸RŔ�����cŮÜLAND˙˙˙˙˙˙������mac ������������on save(adr, flClosing=false) dialog.alert("save") pythonSuite.file.save(adr, flClosing) return (true) €�����„�����€�����€��������ú���3�������/������¸Œ†/¸Œ†<�������� ����save�����‡Ú���3���9�������5������¸‹ &¸Œ†6�������� ���� pythonFile����ř�ˆŕ���9��p������c���j���¸‹ &¸Š•Z�������� ���� ��� ����'���3 ����C���O ����a���m ����€���Œ ����˜���¤ ����ą���˝ ����Ë���× ����é pythonInfo��������XpythonNodeTypes�������"pythonResponder�������.pythonRpcHandlers�������˝pythonSoapHandlers�������a pythonSuite������K1 pythonThread������Vę pythonWebsite������†npythonWindowTypes������‰��V Lucida Grande��������������������������������9�2��LZě������������������������†���ľ���Verdana��������������������������� ��������������¸Š%¸ş‡ �����'ď�LAND˙˙˙˙˙˙������mac ������������pythonInfo pythonNodeTypes pythonResponder pythonRpcHandlers dialogAlert fileDialog hello showOutput pythonSoapHandlers pythonSuite pythonThread pythonWebsite pythonWindowTypes €������lô�l›0�������������€������lô�l›0�������������€������lô�l›0�������������€������lô�l›0�������������€�������lô�l›8��������������€�������lô�l›8��������������€�������lô�l›8��������������€�������lô�l›8��������������€������lô�l›0�������������€������lô�l›0�������������€������lô�l›0�������������€������lô�l›0�������������€������lô�l›0���������������p��ş������‰d@xÖGenevas Serif���������������������� ���������������˙˙˙˙˙˙˙˙Genevas Serif���������������������� �����������������A�š�čŕGenevas Serif���������������������� ����������������^}¸Genevas Serif���������������������� ����������������mnŠGenevas Serif���������������������� ����������������˙˙˙˙˙˙˙˙Genevas Serif���������������������� ����������������������˙˙����������������������������������������������������������ş