# HG changeset patch # User Edouard Tisserant # Date 1336814470 -7200 # Node ID e0424e96e3fd654c29517a0a6601840d1ac731e3 # Parent 3edd2f19bce2371e49ff90cbc0a1fc43878d57b4 refactoring - library support is not anymore attached to configtree nodes, but handles by project controller diff -r 3edd2f19bce2 -r e0424e96e3fd ConfigTreeNode.py --- a/ConfigTreeNode.py Wed May 09 00:39:54 2012 +0200 +++ b/ConfigTreeNode.py Sat May 12 11:21:10 2012 +0200 @@ -61,7 +61,6 @@ self._View = None # copy ConfNodeMethods so that it can be later customized self.ConfNodeMethods = [dic.copy() for dic in self.ConfNodeMethods] - self.LoadSTLibrary() def ConfNodeBaseXmlFilePath(self, CTNName=None): return os.path.join(self.CTNPath(CTNName), "baseconfnode.xml") @@ -69,9 +68,6 @@ def ConfNodeXmlFilePath(self, CTNName=None): return os.path.join(self.CTNPath(CTNName), "confnode.xml") - def ConfNodeLibraryFilePath(self): - return os.path.join(self.ConfNodePath(), "pous.xml") - def ConfNodePath(self): return os.path.join(self.CTNParent.ConfNodePath(), self.CTNType) @@ -252,32 +248,6 @@ return LocationCFilesAndCFLAGS, LDFLAGS, extra_files - def ConfNodeTypesFactory(self): - if self.LibraryControler is not None: - return [{"name" : self.CTNType, "types": self.LibraryControler.Project}] - return [] - - def ParentsTypesFactory(self): - return self.CTNParent.ParentsTypesFactory() + self.ConfNodeTypesFactory() - - def ConfNodesTypesFactory(self): - list = self.ConfNodeTypesFactory() - for CTNChild in self.IterChildren(): - list += CTNChild.ConfNodesTypesFactory() - return list - - def STLibraryFactory(self): - if self.LibraryControler is not None: - program, errors, warnings = self.LibraryControler.GenerateProgram() - return program + "\n" - return "" - - def ConfNodesSTLibraryFactory(self): - program = self.STLibraryFactory() - for CTNChild in self.IECSortedChildren(): - program += CTNChild.ConfNodesSTLibraryFactory() - return program - def IterChildren(self): for CTNType, Children in self.Children.items(): for CTNInstance in Children: @@ -563,15 +533,6 @@ child.ClearChildren() self.Children = {} - def LoadSTLibrary(self): - # Get library blocks if plcopen library exist - library_path = self.ConfNodeLibraryFilePath() - if os.path.isfile(library_path): - self.LibraryControler = PLCControler() - self.LibraryControler.OpenXMLFile(library_path) - self.LibraryControler.ClearConfNodeTypes() - self.LibraryControler.AddConfNodeTypesList(self.ParentsTypesFactory()) - def LoadXMLParams(self, CTNName = None): methode_name = os.path.join(self.CTNPath(CTNName), "methods.py") if os.path.isfile(methode_name): diff -r 3edd2f19bce2 -r e0424e96e3fd POULibrary.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/POULibrary.py Sat May 12 11:21:10 2012 +0200 @@ -0,0 +1,27 @@ +from PLCControler import PLCControler + +class POULibrary: + def __init__(self, TypeStack): + self.LibraryControler = PLCControler() + self.LibraryControler.OpenXMLFile(self.GetLibraryPath()) + self.LibraryControler.ClearConfNodeTypes() + self.LibraryControler.AddConfNodeTypesList(TypeStack) + self.program = None; + + def GetSTCode(self): + if not self.program: + self.program = self.LibraryControler.GenerateProgram()[0]+"\n" + return self.program + + def GetName(): + raise Exception("Not implemented") + + def GetTypes(self): + return {"name" : self.GetName(), "types": self.LibraryControler.Project} + + def GetLibraryPath(self): + raise Exception("Not implemented") + + def Generate_C(self, buildpath, varlist, IECCFLAGS): + # Pure python or IEC libs doesn't produce C code + return ((""), [], False), "" diff -r 3edd2f19bce2 -r e0424e96e3fd ProjectController.py --- a/ProjectController.py Wed May 09 00:39:54 2012 +0200 +++ b/ProjectController.py Sat May 12 11:21:10 2012 +0200 @@ -1,5 +1,5 @@ """ -Base definitions for beremiz confnodes +Beremiz Project Controller """ import os,sys,traceback @@ -61,7 +61,8 @@ - + + """+"\n".join(['' for lib in features.libraries])+""" @@ -84,10 +85,6 @@ self.DebugTimer=None self.ResetIECProgramsAndVariables() - - #This method are not called here... but in NewProject and OpenProject - #self._AddParamsMembers() - #self.Children = {} # In both new or load scenario, no need to save self.ChangesToSave = False @@ -104,7 +101,15 @@ self.previous_plcstate = None # copy ConfNodeMethods so that it can be later customized self.ConfNodeMethods = [dic.copy() for dic in self.ConfNodeMethods] - self.LoadSTLibrary() + + def LoadLibraries(self): + self.Libraries = [] + TypeStack=[] + for clsname in features.libraries: + if getattr(self.BeremizRoot, "Enable_"+clsname.rsplit('.',1)[-1]): + Lib = GetClassImporter(clsname)()(TypeStack) + TypeStack.append(Lib.GetTypes()) + self.Libraries.append(Lib) def __del__(self): if self.DebugTimer: @@ -132,9 +137,6 @@ self.logger = logger - def ConfNodeLibraryFilePath(self): - return os.path.join(os.path.split(__file__)[0], "pous.xml") - def CTNTestModified(self): return self.ChangesToSave or not self.ProjectIsSaved() @@ -311,12 +313,31 @@ self._setBuildPath(self.BuildPath) return True return False + + def GetLibrariesTypes(self): + self.LoadLibraries() + return [ lib.GetTypes() for lib in self.Libraries ] + + def GetLibrariesSTCode(self): + return "\n".join([ lib.GetSTCode() for lib in self.Libraries ]) + + def GetLibrariesCCode(self, buildpath): + self.GetIECProgramsAndVariables() + LibIECCflags = '"-I%s"'%os.path.abspath(self.GetIECLibPath()) + LocatedCCodeAndFlags=[] + Extras=[] + for lib in self.Libraries: + res=lib.Generate_C(buildpath,self._VariablesList,LibIECCflags) + LocatedCCodeAndFlags.append(res[:2]) + if len(res)>2: + Extras.append(res[2:]) + return map(list,zip(*LocatedCCodeAndFlags))+[tuple(Extras)] # Update PLCOpenEditor ConfNode Block types from loaded confnodes def RefreshConfNodesBlockLists(self): if getattr(self, "Children", None) is not None: self.ClearConfNodeTypes() - self.AddConfNodeTypesList(self.ConfNodesTypesFactory()) + self.AddConfNodeTypesList(self.GetLibrariesTypes()) if self.AppFrame is not None: self.AppFrame.RefreshLibraryPanel() self.AppFrame.RefreshEditor() @@ -449,7 +470,7 @@ return False plc_file = open(self._getIECcodepath(), "w") # Add ST Library from confnodes - plc_file.write(self.ConfNodesSTLibraryFactory()) + plc_file.write(self.GetLibrariesSTCode()) if os.path.isfile(self._getIECrawcodepath()): plc_file.write(open(self._getIECrawcodepath(), "r").read()) plc_file.write("\n") @@ -708,7 +729,7 @@ [loc for loc,Cfiles,DoCalls in self.LocationCFilesAndCFLAGS if loc and DoCalls]) # Generate main, based on template - if self.BeremizRoot.getEnable_ConfNodes(): + if not self.BeremizRoot.getDisable_Extensions(): plc_main_code = targets.code("plc_common_main") % { "calls_prototypes":"\n".join([( "int __init_%(s)s(int argc,char **argv);\n"+ @@ -774,7 +795,7 @@ # Generate C code and compilation params from confnode hierarchy try: - self.LocationCFilesAndCFLAGS, self.LDFLAGS, ExtraFiles = self._Generate_C( + CTNLocationCFilesAndCFLAGS, CTNLDFLAGS, CTNExtraFiles = self._Generate_C( buildpath, self.PLCGeneratedLocatedVars) except Exception, exc: @@ -783,6 +804,19 @@ self.ResetBuildMD5() return False + # Generate C code and compilation params from liraries + try: + LibCFilesAndCFLAGS, LibLDFLAGS, LibExtraFiles = self.GetLibrariesCCode(buildpath) + except Exception, exc: + self.logger.write_error(_("Runtime extensions C code generation failed !\n")) + self.logger.write_error(traceback.format_exc()) + self.ResetBuildMD5() + return False + + self.LocationCFilesAndCFLAGS = CTNLocationCFilesAndCFLAGS + LibCFilesAndCFLAGS + self.LDFLAGS = CTNLDFLAGS + LibLDFLAGS + ExtraFiles = CTNExtraFiles + LibExtraFiles + # Get temporary directory path extrafilespath = self._getExtraFilesPath() # Remove old directory diff -r 3edd2f19bce2 -r e0424e96e3fd features.py --- a/features.py Wed May 09 00:39:54 2012 +0200 +++ b/features.py Sat May 12 11:21:10 2012 +0200 @@ -1,7 +1,10 @@ -from os import listdir, path +libraries = ['py_ext.PythonLibrary', + 'svgui.SVGUILibrary'] catalog = [ ('canfestival', _('CANopen support'), _('Map located variables over CANopen'), 'canfestival.canfestival.RootClass'), - ('c_ext', _('C extention'), _('Extend project with C code accessing located variables'), 'c_ext.c_ext.RootClass'), - ('py_ext', _('Python extention'), _('Extend project with Pyhon code executed asynchronously'), 'py_ext.py_ext.RootClass')] + ('c_ext', _('C extention'), _('Add C code accessing located variables synchronously'), 'c_ext.c_ext.RootClass'), + ('py_ext', _('Python file'), _('Add Python code executed asynchronously'), 'py_ext.PythonFile'), + ('wxglade_hmi', _('WxGlade GUI'), _('Add a simple WxGlade based GUI.'), 'wxglade_hmi.WxGladeHMI'), + ('svgui', _('SVGUI'), _('Experimental web based HMI'), 'svgui.SVGUI')] diff -r 3edd2f19bce2 -r e0424e96e3fd py_ext/PythonFileCTNMixin.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/py_ext/PythonFileCTNMixin.py Sat May 12 11:21:10 2012 +0200 @@ -0,0 +1,118 @@ +import os +from util import opjimg +from PLCControler import UndoBuffer +from PythonEditor import PythonEditor + +from xml.dom import minidom +from xmlclass import * +import cPickle + +PythonClasses = GenerateClassesFromXSD(os.path.join(os.path.dirname(__file__), "py_ext_xsd.xsd")) + +class PythonFileCTNMixin: + + EditorType = PythonEditor + + def __init__(self): + + self.ConfNodeMethods.insert(0, + {"bitmap" : opjimg("editPYTHONcode"), + "name" : _("Edit Python File"), + "tooltip" : _("Edit Python File"), + "method" : "_OpenView"}, + ) + + filepath = self.PythonFileName() + + self.PythonCode = PythonClasses["Python"]() + if os.path.isfile(filepath): + xmlfile = open(filepath, 'r') + tree = minidom.parse(xmlfile) + xmlfile.close() + + for child in tree.childNodes: + if child.nodeType == tree.ELEMENT_NODE and child.nodeName == "Python": + self.PythonCode.loadXMLTree(child, ["xmlns", "xmlns:xsi", "xsi:schemaLocation"]) + self.CreatePythonBuffer(True) + else: + self.CreatePythonBuffer(False) + self.OnCTNSave() + + def PythonFileName(self): + return os.path.join(self.CTNPath(), "py_ext.xml") + + def GetFilename(self): + if self.PythonBuffer.IsCurrentSaved(): + return "py_ext" + else: + return "~py_ext~" + + def SetPythonCode(self, text): + self.PythonCode.settext(text) + + def GetPythonCode(self): + return self.PythonCode.gettext() + + def CTNTestModified(self): + return self.ChangesToSave or not self.PythonIsSaved() + + def OnCTNSave(self): + filepath = self.PythonFileName() + + text = "\n" + extras = {"xmlns":"http://www.w3.org/2001/XMLSchema", + "xmlns:xsi":"http://www.w3.org/2001/XMLSchema-instance", + "xsi:schemaLocation" : "py_ext_xsd.xsd"} + text += self.PythonCode.generateXMLText("Python", 0, extras) + + xmlfile = open(filepath,"w") + xmlfile.write(text.encode("utf-8")) + xmlfile.close() + + self.MarkPythonAsSaved() + return True + +#------------------------------------------------------------------------------- +# Current Buffering Management Functions +#------------------------------------------------------------------------------- + + """ + Return a copy of the project + """ + def Copy(self, model): + return cPickle.loads(cPickle.dumps(model)) + + def CreatePythonBuffer(self, saved): + self.Buffering = False + self.PythonBuffer = UndoBuffer(cPickle.dumps(self.PythonCode), saved) + + def BufferPython(self): + self.PythonBuffer.Buffering(cPickle.dumps(self.PythonCode)) + + def StartBuffering(self): + self.Buffering = True + + def EndBuffering(self): + if self.Buffering: + self.PythonBuffer.Buffering(cPickle.dumps(self.PythonCode)) + self.Buffering = False + + def MarkPythonAsSaved(self): + self.EndBuffering() + self.PythonBuffer.CurrentSaved() + + def PythonIsSaved(self): + return self.PythonBuffer.IsCurrentSaved() and not self.Buffering + + def LoadPrevious(self): + self.EndBuffering() + self.PythonCode = cPickle.loads(self.PythonBuffer.Previous()) + + def LoadNext(self): + self.PythonCode = cPickle.loads(self.PythonBuffer.Next()) + + def GetBufferState(self): + first = self.PythonBuffer.IsFirst() and not self.Buffering + last = self.PythonBuffer.IsLast() + return not first, not last + diff -r 3edd2f19bce2 -r e0424e96e3fd py_ext/__init__.py --- a/py_ext/__init__.py Wed May 09 00:39:54 2012 +0200 +++ b/py_ext/__init__.py Sat May 12 11:21:10 2012 +0200 @@ -1,1 +1,3 @@ from py_ext import * +from PythonEditor import PythonEditor +from PythonFileCTNMixin import PythonFileCTNMixin diff -r 3edd2f19bce2 -r e0424e96e3fd py_ext/modules/__init__.py --- a/py_ext/modules/__init__.py Wed May 09 00:39:54 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,13 +0,0 @@ -from os import listdir, path - -_base_path = path.split(__file__)[0] - -__all__ = [name for name in listdir(_base_path) if path.isdir(path.join(_base_path, name)) and name.upper() != "CVS" or name.endswith(".py") and not name.startswith("__")] - -helps = [] -for name in __all__: - helpfilename = path.join(_base_path, name, "README") - if path.isfile(helpfilename): - helps.append(open(helpfilename).readline().strip()) - else: - helps.append(name) diff -r 3edd2f19bce2 -r e0424e96e3fd py_ext/modules/svgui/README --- a/py_ext/modules/svgui/README Wed May 09 00:39:54 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -SVGUI HMI \ No newline at end of file diff -r 3edd2f19bce2 -r e0424e96e3fd py_ext/modules/svgui/__init__.py --- a/py_ext/modules/svgui/__init__.py Wed May 09 00:39:54 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -from svgui import * diff -r 3edd2f19bce2 -r e0424e96e3fd py_ext/modules/svgui/livesvg.js --- a/py_ext/modules/svgui/livesvg.js Wed May 09 00:39:54 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,59 +0,0 @@ -// import Nevow.Athena -// import Divmod.Base - -function updateAttr(id, param, value) { - Nevow.Athena.Widget.fromAthenaID(1).callRemote('HMIexec', 'setattr', id, param, value); -} - -var svguiWidgets = new Array(); - -var currentObject = null; -function setCurrentObject(obj) { - currentObject = obj; -} -function isCurrentObject(obj) { - return currentObject == obj; -} - -function getSVGElementById(id) { - return document.getElementById(id); -} - -function blockSVGElementDrag(element) { - element.addEventListener("draggesture", function(event){event.stopPropagation()}, true); -} - -LiveSVGPage.LiveSVGWidget = Nevow.Athena.Widget.subclass('LiveSVGPage.LiveSVGWidget'); -LiveSVGPage.LiveSVGWidget.methods( - - function handleEvent(self, evt) { - if (currentObject != null) { - currentObject.handleEvent(evt); - } - }, - - function receiveData(self, data){ - dataReceived = json_parse(data); - gadget = svguiWidgets[dataReceived.id] - if (gadget) { - gadget.updateValues(json_parse(dataReceived.kwargs)); - } - //console.log("OBJET : " + dataReceived.back_id + " STATE : " + newState); - }, - - function init(self, arg1){ - //console.log("Object received : " + arg1); - for (ind in arg1) { - gad = json_parse(arg1[ind]); - args = json_parse(gad.kwargs); - gadget = new svguilib[gad.__class__](self, gad.id, args); - svguiWidgets[gadget.id]=gadget; - //console.log('GADGET :' + gadget); - } - var elements = document.getElementsByTagName("svg"); - for (var i = 0; i < elements.length; i++) { - elements[i].addEventListener("mouseup", self, false); - } - //console.log("SVGUIWIDGETS : " + svguiWidgets); - } -); diff -r 3edd2f19bce2 -r e0424e96e3fd py_ext/modules/svgui/pous.xml --- a/py_ext/modules/svgui/pous.xml Wed May 09 00:39:54 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1428 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 'createSVGUIControl("textControl", back_id="' - - - - - - - back_id - - - - - - - '")' - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - BOOL#1 - - - - - - - - - - - ID - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ID - - - - - - - set_text - - - - - - - 'setAttr(' - - - - - - - ',"text","' - - - - - - - '")' - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 'createSVGUIControl("button",back_id="' - - - - - - - '",sele_id="' - - - - - - - ',active=True)' - - - - - - - BOOL#1 - - - - - - - back_id - - - - - - - sele_id - - - - - - - set_state - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ID - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - state_in - - - - - - - - - - - state_out - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ID - - - - - - - 'setAttr(' - - - - - - - ',"state",' - - - - - - - ')' - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ID - - - - - - - 'int(getAttr(' - - - - - - - ',"state",False))' - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - '",toggle=' - - - - - - - - - - - - - - - - - - - - - - - - - - - - - toggle - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 'createSVGUIControl("button",back_id="' - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - '",sele_id="' - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ID - - - - - - - '",toggle=True,active=False)' - - - - - - - BOOL#1 - - - - - - - back_id - - - - - - - sele_id - - - - - - - 'setAttr(' - - - - - - - ',"state",' - - - - - - - ')' - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ID - - - - - - - - - - - - - - - - - state_in - - - - - - - - - - diff -r 3edd2f19bce2 -r e0424e96e3fd py_ext/modules/svgui/pyjs/__init__.py --- a/py_ext/modules/svgui/pyjs/__init__.py Wed May 09 00:39:54 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,2 +0,0 @@ -from pyjs import * - diff -r 3edd2f19bce2 -r e0424e96e3fd py_ext/modules/svgui/pyjs/build.py --- a/py_ext/modules/svgui/pyjs/build.py Wed May 09 00:39:54 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,724 +0,0 @@ -#!/usr/bin/env python - -import sys -import os -import shutil -from copy import copy -from os.path import join, dirname, basename, abspath, split, isfile, isdir -from optparse import OptionParser -import pyjs -from cStringIO import StringIO -try: - # Python 2.5 and above - from hashlib import md5 -except: - import md5 -import re - -usage = """ - usage: %prog [options] - -This is the command line builder for the pyjamas project, which can -be used to build Ajax applications from Python. -For more information, see the website at http://pyjs.org/ -""" - -# GWT1.2 Impl | GWT1.2 Output | Pyjamas 0.2 Platform | Pyjamas 0.2 Output -# -------------+-----------------------+----------------------+---------------------- -# IE6 | ie6 | IE6 | ie6 -# Opera | opera | Opera | opera -# Safari | safari | Safari | safari -# -- | gecko1_8 | Mozilla | mozilla -# -- | gecko | OldMoz | oldmoz -# Standard | all | (default code) | all -# Mozilla | gecko1_8, gecko | -- | -- -# Old | safari, gecko, opera | -- | -- - -version = "%prog pyjamas version 2006-08-19" - -# these names in lowercase need match the strings -# returned by "provider$user.agent" in order to be selected corretly -app_platforms = ['IE6', 'Opera', 'OldMoz', 'Safari', 'Mozilla'] - -# usually defaults to e.g. /usr/share/pyjamas -_data_dir = os.path.join(pyjs.prefix, "share/pyjamas") - - -# .cache.html files produces look like this -CACHE_HTML_PAT=re.compile('^[a-z]*.[0-9a-f]{32}\.cache\.html$') - -# ok these are the three "default" library directories, containing -# the builtins (str, List, Dict, ord, round, len, range etc.) -# the main pyjamas libraries (pyjamas.ui, pyjamas.Window etc.) -# and the contributed addons - -for p in ["library/builtins", - "library", - "addons"]: - p = os.path.join(_data_dir, p) - if os.path.isdir(p): - pyjs.path.append(p) - - -def read_boilerplate(data_dir, filename): - return open(join(data_dir, "builder/boilerplate", filename)).read() - -def copy_boilerplate(data_dir, filename, output_dir): - filename = join(data_dir, "builder/boilerplate", filename) - shutil.copy(filename, output_dir) - - -# taken and modified from python2.4 -def copytree_exists(src, dst, symlinks=False): - if not os.path.exists(src): - return - - names = os.listdir(src) - try: - os.mkdir(dst) - except: - pass - - errors = [] - for name in names: - if name.startswith('CVS'): - continue - if name.startswith('.git'): - continue - if name.startswith('.svn'): - continue - - srcname = os.path.join(src, name) - dstname = os.path.join(dst, name) - try: - if symlinks and os.path.islink(srcname): - linkto = os.readlink(srcname) - os.symlink(linkto, dstname) - elif isdir(srcname): - copytree_exists(srcname, dstname, symlinks) - else: - shutil.copy2(srcname, dstname) - except (IOError, os.error), why: - errors.append((srcname, dstname, why)) - if errors: - print errors - -def check_html_file(source_file, dest_path): - """ Checks if a base HTML-file is available in the PyJamas - output directory. - If the HTML-file isn't available, it will be created. - - If a CSS-file with the same name is available - in the output directory, a reference to this CSS-file - is included. - - If no CSS-file is found, this function will look for a special - CSS-file in the output directory, with the name - "pyjamas_default.css", and if found it will be referenced - in the generated HTML-file. - - [thank you to stef mientki for contributing this function] - """ - - base_html = """\ - - - - - %(css)s - %(title)s - - - - - -""" - - filename = os.path.split ( source_file )[1] - mod_name = os.path.splitext ( filename )[0] - file_name = os.path.join ( dest_path, mod_name + '.html' ) - - # if html file in output directory exists, leave it alone. - if os.path.exists ( file_name ): - return 0 - - if os.path.exists ( - os.path.join ( dest_path, mod_name + '.css' ) ) : - css = "" - elif os.path.exists ( - os.path.join ( dest_path, 'pyjamas_default.css' ) ) : - css = "" - - else: - css = '' - - title = 'PyJamas Auto-Generated HTML file ' + mod_name - - base_html = base_html % {'modulename': mod_name, 'title': title, 'css': css} - - fh = open (file_name, 'w') - fh.write (base_html) - fh.close () - - return 1 - - -def build(app_name, output, js_includes=(), debug=False, dynamic=0, - data_dir=None, cache_buster=False, optimize=False): - - # make sure the output directory is always created in the current working - # directory or at the place given if it is an absolute path. - output = os.path.abspath(output) - msg = "Building '%(app_name)s' to output directory '%(output)s'" % locals() - if debug: - msg += " with debugging statements" - print msg - - # check the output directory - if os.path.exists(output) and not os.path.isdir(output): - print >>sys.stderr, "Output destination %s exists and is not a directory" % output - return - if not os.path.isdir(output): - try: - print "Creating output directory" - os.mkdir(output) - except StandardError, e: - print >>sys.stderr, "Exception creating output directory %s: %s" % (output, e) - - ## public dir - for p in pyjs.path: - pub_dir = join(p, 'public') - if isdir(pub_dir): - print "Copying: public directory of library %r" % p - copytree_exists(pub_dir, output) - - ## AppName.html - can be in current or public directory - html_input_filename = app_name + ".html" - html_output_filename = join(output, basename(html_input_filename)) - if os.path.isfile(html_input_filename): - if not os.path.isfile(html_output_filename) or \ - os.path.getmtime(html_input_filename) > \ - os.path.getmtime(html_output_filename): - try: - shutil.copy(html_input_filename, html_output_filename) - except: - print >>sys.stderr, "Warning: Missing module HTML file %s" % html_input_filename - - print "Copying: %(html_input_filename)s" % locals() - - if check_html_file(html_input_filename, output): - print >>sys.stderr, "Warning: Module HTML file %s has been auto-generated" % html_input_filename - - ## pygwt.js - - print "Copying: pygwt.js" - - pygwt_js_template = read_boilerplate(data_dir, "pygwt.js") - pygwt_js_output = open(join(output, "pygwt.js"), "w") - - print >>pygwt_js_output, pygwt_js_template - - pygwt_js_output.close() - - ## Images - - print "Copying: Images and History" - copy_boilerplate(data_dir, "corner_dialog_topleft_black.png", output) - copy_boilerplate(data_dir, "corner_dialog_topright_black.png", output) - copy_boilerplate(data_dir, "corner_dialog_bottomright_black.png", output) - copy_boilerplate(data_dir, "corner_dialog_bottomleft_black.png", output) - copy_boilerplate(data_dir, "corner_dialog_edge_black.png", output) - copy_boilerplate(data_dir, "corner_dialog_topleft.png", output) - copy_boilerplate(data_dir, "corner_dialog_topright.png", output) - copy_boilerplate(data_dir, "corner_dialog_bottomright.png", output) - copy_boilerplate(data_dir, "corner_dialog_bottomleft.png", output) - copy_boilerplate(data_dir, "corner_dialog_edge.png", output) - copy_boilerplate(data_dir, "tree_closed.gif", output) - copy_boilerplate(data_dir, "tree_open.gif", output) - copy_boilerplate(data_dir, "tree_white.gif", output) - copy_boilerplate(data_dir, "history.html", output) - - - ## all.cache.html - app_files = generateAppFiles(data_dir, js_includes, app_name, debug, - output, dynamic, cache_buster, optimize) - - ## AppName.nocache.html - - print "Creating: %(app_name)s.nocache.html" % locals() - - home_nocache_html_template = read_boilerplate(data_dir, "home.nocache.html") - home_nocache_html_output = open(join(output, app_name + ".nocache.html"), - "w") - - # the selector templ is added to the selectScript function - select_tmpl = """O(["true","%s"],"%s");""" - script_selectors = StringIO() - - for platform, file_prefix in app_files: - print >> script_selectors, select_tmpl % (platform, file_prefix) - - print >>home_nocache_html_output, home_nocache_html_template % dict( - app_name = app_name, - script_selectors = script_selectors.getvalue(), - ) - - home_nocache_html_output.close() - - print "Done. You can run your app by opening '%(html_output_filename)s' in a browser" % locals() - - -def generateAppFiles(data_dir, js_includes, app_name, debug, output, dynamic, - cache_buster, optimize): - - all_cache_html_template = read_boilerplate(data_dir, "all.cache.html") - mod_cache_html_template = read_boilerplate(data_dir, "mod.cache.html") - - # clean out the old ones first - for name in os.listdir(output): - if CACHE_HTML_PAT.match(name): - p = join(output, name) - print "Deleting existing app file %s" % p - os.unlink(p) - - app_files = [] - tmpl = read_boilerplate(data_dir, "all.cache.html") - parser = pyjs.PlatformParser("platform") - app_headers = '' - scripts = [''%script \ - for script in js_includes] - app_body = '\n'.join(scripts) - - mod_code = {} - mod_libs = {} - modules = {} - app_libs = {} - early_app_libs = {} - app_code = {} - overrides = {} - pover = {} - app_modnames = {} - mod_levels = {} - - # First, generate all the code. - # Second, (dynamic only), post-analyse the places where modules - # haven't changed - # Third, write everything out. - - for platform in app_platforms: - - mod_code[platform] = {} - mod_libs[platform] = {} - modules[platform] = [] - pover[platform] = {} - app_libs[platform] = '' - early_app_libs[platform] = '' - app_code[platform] = {} - app_modnames[platform] = {} - - # Application.Platform.cache.html - - parser.setPlatform(platform) - app_translator = pyjs.AppTranslator( - parser=parser, dynamic=dynamic, optimize=optimize) - early_app_libs[platform], appcode = \ - app_translator.translate(None, is_app=False, - debug=debug, - library_modules=['dynamicajax.js', - '_pyjs.js', 'sys', - 'pyjslib']) - pover[platform].update(app_translator.overrides.items()) - for mname, name in app_translator.overrides.items(): - pd = overrides.setdefault(mname, {}) - pd[platform] = name - - print appcode - #mod_code[platform][app_name] = appcode - - # platform.Module.cache.js - - modules_done = ['pyjslib', 'sys', '_pyjs.js'] - #modules_to_do = [app_name] + app_translator.library_modules - modules_to_do = [app_name] + app_translator.library_modules - - dependencies = {} - - deps = map(pyjs.strip_py, modules_to_do) - for d in deps: - sublist = add_subdeps(dependencies, d) - modules_to_do += sublist - deps = uniquify(deps) - #dependencies[app_name] = deps - - modules[platform] = modules_done + modules_to_do - - while modules_to_do: - - #print "modules to do", modules_to_do - - mn = modules_to_do.pop() - mod_name = pyjs.strip_py(mn) - - if mod_name in modules_done: - continue - - modules_done.append(mod_name) - - mod_cache_name = "%s.%s.cache.js" % (platform.lower(), mod_name) - - parser.setPlatform(platform) - mod_translator = pyjs.AppTranslator(parser=parser, optimize=optimize) - mod_libs[platform][mod_name], mod_code[platform][mod_name] = \ - mod_translator.translate(mod_name, - is_app=False, - debug=debug) - pover[platform].update(mod_translator.overrides.items()) - for mname, name in mod_translator.overrides.items(): - pd = overrides.setdefault(mname, {}) - pd[platform] = name - - mods = mod_translator.library_modules - modules_to_do += mods - modules[platform] += mods - - deps = map(pyjs.strip_py, mods) - sd = subdeps(mod_name) - if len(sd) > 1: - deps += sd[:-1] - while mod_name in deps: - deps.remove(mod_name) - - #print - #print - #print "modname preadd:", mod_name, deps - #print - #print - for d in deps: - sublist = add_subdeps(dependencies, d) - modules_to_do += sublist - modules_to_do += add_subdeps(dependencies, mod_name) - #print "modname:", mod_name, deps - deps = uniquify(deps) - #print "modname:", mod_name, deps - dependencies[mod_name] = deps - - # work out the dependency ordering of the modules - - mod_levels[platform] = make_deps(None, dependencies, modules_done) - - # now write everything out - - for platform in app_platforms: - - early_app_libs_ = early_app_libs[platform] - app_libs_ = app_libs[platform] - app_code_ = app_code[platform] - #modules_ = filter_mods(app_name, modules[platform]) - mods = flattenlist(mod_levels[platform]) - mods.reverse() - modules_ = filter_mods(None, mods) - - for mod_name in modules_: - - mod_code_ = mod_code[platform][mod_name] - - mod_name = pyjs.strip_py(mod_name) - - override_name = "%s.%s" % (platform.lower(), mod_name) - if pover[platform].has_key(override_name): - mod_cache_name = "%s.cache.js" % (override_name) - else: - mod_cache_name = "%s.cache.js" % (mod_name) - - print "Creating: " + mod_cache_name - - modlevels = make_deps(None, dependencies, dependencies[mod_name]) - - modnames = [] - - for md in modlevels: - mnames = map(lambda x: "'%s'" % x, md) - mnames = "new pyjslib.List([\n\t\t\t%s])" % ',\n\t\t\t'.join(mnames) - modnames.append(mnames) - - modnames.reverse() - modnames = "new pyjslib.List([\n\t\t%s\n\t])" % ',\n\t\t'.join(modnames) - - # convert the overrides - - overnames = map(lambda x: "'%s': '%s'" % x, pover[platform].items()) - overnames = "new pyjslib.Dict({\n\t\t%s\n\t})" % ',\n\t\t'.join(overnames) - - if dynamic: - mod_cache_html_output = open(join(output, mod_cache_name), "w") - else: - mod_cache_html_output = StringIO() - - print >>mod_cache_html_output, mod_cache_html_template % dict( - mod_name = mod_name, - app_name = app_name, - modnames = modnames, - overrides = overnames, - mod_libs = mod_libs[platform][mod_name], - dynamic = dynamic, - mod_code = mod_code_, - ) - - if dynamic: - mod_cache_html_output.close() - else: - mod_cache_html_output.seek(0) - app_libs_ += mod_cache_html_output.read() - - # write out the dependency ordering of the modules - - app_modnames = [] - - for md in mod_levels[platform]: - mnames = map(lambda x: "'%s'" % x, md) - mnames = "new pyjslib.List([\n\t\t\t%s])" % ',\n\t\t\t'.join(mnames) - app_modnames.append(mnames) - - app_modnames.reverse() - app_modnames = "new pyjslib.List([\n\t\t%s\n\t])" % ',\n\t\t'.join(app_modnames) - - # convert the overrides - - overnames = map(lambda x: "'%s': '%s'" % x, pover[platform].items()) - overnames = "new pyjslib.Dict({\n\t\t%s\n\t})" % ',\n\t\t'.join(overnames) - - #print "platform names", platform, overnames - #print pover - - # now write app.allcache including dependency-ordered list of - # library modules - - file_contents = all_cache_html_template % dict( - app_name = app_name, - early_app_libs = early_app_libs_, - app_libs = app_libs_, - app_code = app_code_, - app_body = app_body, - overrides = overnames, - platform = platform.lower(), - dynamic = dynamic, - app_modnames = app_modnames, - app_headers = app_headers - ) - if cache_buster: - digest = md5.new(file_contents).hexdigest() - file_name = "%s.%s.%s" % (platform.lower(), app_name, digest) - else: - file_name = "%s.%s" % (platform.lower(), app_name) - file_name += ".cache.html" - out_path = join(output, file_name) - out_file = open(out_path, 'w') - out_file.write(file_contents) - out_file.close() - app_files.append((platform.lower(), file_name)) - print "Created app file %s:%s: %s" % ( - app_name, platform, out_path) - - return app_files - -def flattenlist(ll): - res = [] - for l in ll: - res += l - return res - -# creates sub-dependencies e.g. pyjamas.ui.Widget -# creates pyjamas.ui.Widget, pyjamas.ui and pyjamas. -def subdeps(m): - d = [] - m = m.split(".") - for i in range(0, len(m)): - d.append('.'.join(m[:i+1])) - return d - -import time - -def add_subdeps(deps, mod_name): - sd = subdeps(mod_name) - if len(sd) == 1: - return [] - #print "subdeps", mod_name, sd - #print "deps", deps - res = [] - for i in range(0, len(sd)-1): - parent = sd[i] - child = sd[i+1] - l = deps.get(child, []) - l.append(parent) - deps[child] = l - if parent not in res: - res.append(parent) - #print deps - return res - -# makes unique and preserves list order -def uniquify(md): - res = [] - for m in md: - if m not in res: - res.append(m) - return res - -def filter_mods(app_name, md): - while 'sys' in md: - md.remove('sys') - while 'pyjslib' in md: - md.remove('pyjslib') - while app_name in md: - md.remove(app_name) - md = filter(lambda x: not x.endswith('.js'), md) - md = map(pyjs.strip_py, md) - - return uniquify(md) - -def filter_deps(app_name, deps): - - res = {} - for (k, l) in deps.items(): - mods = filter_mods(k, l) - while k in mods: - mods.remove(k) - res[k] = mods - return res - -def has_nodeps(mod, deps): - if not deps.has_key(mod) or not deps[mod]: - return True - return False - -def nodeps_list(mod_list, deps): - res = [] - for mod in mod_list: - if has_nodeps(mod, deps): - res.append(mod) - return res - -# this function takes a dictionary of dependent modules and -# creates a list of lists. the first list will be modules -# that have no dependencies; the second list will be those -# modules that have the first list as dependencies; the -# third will be those modules that have the first and second... -# etc. - - -def make_deps(app_name, deps, mod_list): - print "Calculating Dependencies ..." - mod_list = filter_mods(app_name, mod_list) - deps = filter_deps(app_name, deps) - - if not mod_list: - return [] - - #print mod_list - #print deps - - ordered_deps = [] - last_len = -1 - while deps: - l_deps = len(deps) - #print l_deps - if l_deps==last_len: - for m, dl in deps.items(): - for d in dl: - if m in deps.get(d, []): - raise Exception('Circular Imports found: \n%s %s -> %s %s' - % (m, dl, d, deps[d])) - #raise Exception('Could not calculate dependencies: \n%s' % deps) - break - last_len = l_deps - #print "modlist", mod_list - nodeps = nodeps_list(mod_list, deps) - #print "nodeps", nodeps - mod_list = filter(lambda x: x not in nodeps, mod_list) - newdeps = {} - for k in deps.keys(): - depslist = deps[k] - depslist = filter(lambda x: x not in nodeps, depslist) - if depslist: - newdeps[k] = depslist - #print "newdeps", newdeps - deps = newdeps - ordered_deps.append(nodeps) - #time.sleep(0) - - if mod_list: - ordered_deps.append(mod_list) # last dependencies - usually the app(s) - - ordered_deps.reverse() - - return ordered_deps - -def main(): - global app_platforms - - parser = OptionParser(usage = usage, version = version) - parser.add_option("-o", "--output", dest="output", - help="directory to which the webapp should be written") - parser.add_option("-j", "--include-js", dest="js_includes", action="append", - help="javascripts to load into the same frame as the rest of the script") - parser.add_option("-I", "--library_dir", dest="library_dirs", - action="append", help="additional paths appended to PYJSPATH") - parser.add_option("-D", "--data_dir", dest="data_dir", - help="path for data directory") - parser.add_option("-m", "--dynamic-modules", action="store_true", - dest="dynamic", default=False, - help="Split output into separate dynamically-loaded modules (experimental)") - parser.add_option("-P", "--platforms", dest="platforms", - help="platforms to build for, comma-separated") - parser.add_option("-d", "--debug", action="store_true", dest="debug") - parser.add_option("-O", "--optimize", action="store_true", - dest="optimize", default=False, - help="Optimize generated code (removes all print statements)", - ) - parser.add_option("-c", "--cache_buster", action="store_true", - dest="cache_buster", - help="Enable browser cache-busting (MD5 hash added to output filenames)") - - parser.set_defaults(output = "output", js_includes=[], library_dirs=[], - platforms=(','.join(app_platforms)), - data_dir=os.path.join(sys.prefix, "share/pyjamas"), - dynamic=False, - cache_buster=False, - debug=False) - (options, args) = parser.parse_args() - if len(args) != 1: - parser.error("incorrect number of arguments") - - data_dir = abspath(options.data_dir) - - app_path = args[0] - if app_path.endswith('.py'): - app_path = abspath(app_path) - if not isfile(app_path): - parser.error("Application file not found %r" % app_path) - app_path, app_name = split(app_path) - app_name = app_name[:-3] - pyjs.path.append(app_path) - elif os.path.sep in app_path: - parser.error("Not a valid module declaration %r" % app_path) - else: - app_name = app_path - - for d in options.library_dirs: - pyjs.path.append(abspath(d)) - - if options.platforms: - app_platforms = options.platforms.split(',') - - # this is mostly for getting boilerplate stuff - data_dir = os.path.abspath(options.data_dir) - - build(app_name, options.output, options.js_includes, - options.debug, options.dynamic and 1 or 0, data_dir, - options.cache_buster, options.optimize) - -if __name__ == "__main__": - main() - diff -r 3edd2f19bce2 -r e0424e96e3fd py_ext/modules/svgui/pyjs/jsonrpc/README.txt --- a/py_ext/modules/svgui/pyjs/jsonrpc/README.txt Wed May 09 00:39:54 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,12 +0,0 @@ -These classes are intended for use server-side. - -e.g. in a django view.py : - - from pyjs.jsonrpc.django import JSONService, jsonremote - - jsonservice = JSONRPCService() - - @jsonremote(jsonservice) - def test(request, echo_param): - return "echoing the param back: %s" % echo_param - diff -r 3edd2f19bce2 -r e0424e96e3fd py_ext/modules/svgui/pyjs/jsonrpc/django/jsonrpc.py --- a/py_ext/modules/svgui/pyjs/jsonrpc/django/jsonrpc.py Wed May 09 00:39:54 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,226 +0,0 @@ -# jsonrpc.py -# original code: http://trac.pyworks.org/pyjamas/wiki/DjangoWithPyJamas -# also from: http://www.pimentech.fr/technologies/outils -from django.utils import simplejson -from django.http import HttpResponse -import sys - -from pyjs.jsonrpc import JSONRPCServiceBase -# JSONRPCService and jsonremote are used in combination to drastically -# simplify the provision of JSONRPC services. use as follows: -# -# jsonservice = JSONRPCService() -# -# @jsonremote(jsonservice) -# def test(request, echo_param): -# return "echoing the param back: %s" % echo_param -# -# dump jsonservice into urlpatterns: -# (r'^service1/$', 'djangoapp.views.jsonservice'), - -class JSONRPCService(JSONRPCServiceBase): - - def __call__(self, request, extra=None): - return self.process(request.raw_post_data) - -def jsonremote(service): - """Make JSONRPCService a decorator so that you can write : - - from jsonrpc import JSONRPCService - chatservice = JSONRPCService() - - @jsonremote(chatservice) - def login(request, user_name): - (...) - """ - def remotify(func): - if isinstance(service, JSONRPCService): - service.add_method(func.__name__, func) - else: - emsg = 'Service "%s" not found' % str(service.__name__) - raise NotImplementedError, emsg - return func - return remotify - - -# FormProcessor provides a mechanism for turning Django Forms into JSONRPC -# Services. If you have an existing Django app which makes prevalent -# use of Django Forms it will save you rewriting the app. -# use as follows. in djangoapp/views.py : -# -# class SimpleForm(forms.Form): -# testfield = forms.CharField(max_length=100) -# -# class SimpleForm2(forms.Form): -# testfield = forms.CharField(max_length=20) -# -# processor = FormProcessor({'processsimpleform': SimpleForm, -# 'processsimpleform2': SimpleForm2}) -# -# this will result in a JSONRPC service being created with two -# RPC functions. dump "processor" into urlpatterns to make it -# part of the app: -# (r'^formsservice/$', 'djangoapp.views.processor'), - -from django import forms - -def builderrors(form): - d = {} - for error in form.errors.keys(): - if error not in d: - d[error] = [] - for errorval in form.errors[error]: - d[error].append(unicode(errorval)) - return d - - -# contains the list of arguments in each field -field_names = { - 'CharField': ['max_length', 'min_length'], - 'IntegerField': ['max_value', 'min_value'], - 'FloatField': ['max_value', 'min_value'], - 'DecimalField': ['max_value', 'min_value', 'max_digits', 'decimal_places'], - 'DateField': ['input_formats'], - 'DateTimeField': ['input_formats'], - 'TimeField': ['input_formats'], - 'RegexField': ['max_length', 'min_length'], # sadly we can't get the expr - 'EmailField': ['max_length', 'min_length'], - 'URLField': ['max_length', 'min_length', 'verify_exists', 'user_agent'], - 'ChoiceField': ['choices'], - 'FilePathField': ['path', 'match', 'recursive', 'choices'], - 'IPAddressField': ['max_length', 'min_length'], - } - -def describe_field_errors(field): - res = {} - field_type = field.__class__.__name__ - msgs = {} - for n, m in field.error_messages.items(): - msgs[n] = unicode(m) - res['error_messages'] = msgs - if field_type in ['ComboField', 'MultiValueField', 'SplitDateTimeField']: - res['fields'] = map(describe_field, field.fields) - return res - -def describe_fields_errors(fields, field_names): - res = {} - if not field_names: - field_names = fields.keys() - for name in field_names: - field = fields[name] - res[name] = describe_field_errors(field) - return res - -def describe_field(field): - res = {} - field_type = field.__class__.__name__ - for fname in field_names.get(field_type, []) + \ - ['help_text', 'label', 'initial', 'required']: - res[fname] = getattr(field, fname) - if field_type in ['ComboField', 'MultiValueField', 'SplitDateTimeField']: - res['fields'] = map(describe_field, field.fields) - return res - -def describe_fields(fields, field_names): - res = {} - if not field_names: - field_names = fields.keys() - for name in field_names: - field = fields[name] - res[name] = describe_field(field) - return res - -class FormProcessor(JSONRPCService): - def __init__(self, forms, _formcls=None): - - if _formcls is None: - JSONRPCService.__init__(self) - for k in forms.keys(): - s = FormProcessor({}, forms[k]) - self.add_method(k, s.__process) - else: - JSONRPCService.__init__(self, forms) - self.formcls = _formcls - - def __process(self, request, params, command=None): - - f = self.formcls(params) - - if command is None: # just validate - if not f.is_valid(): - return {'success':False, 'errors': builderrors(f)} - return {'success':True} - - elif command.has_key('describe_errors'): - field_names = command['describe_errors'] - return describe_fields_errors(f.fields, field_names) - - elif command.has_key('describe'): - field_names = command['describe'] - return describe_fields(f.fields, field_names) - - elif command.has_key('save'): - if not f.is_valid(): - return {'success':False, 'errors': builderrors(f)} - instance = f.save() # XXX: if you want more, over-ride save. - return {'success': True, 'instance': json_convert(instance) } - - elif command.has_key('html'): - return {'success': True, 'html': f.as_table()} - - return "unrecognised command" - - - - -# The following is incredibly convenient for saving vast amounts of -# coding, avoiding doing silly things like this: -# jsonresult = {'field1': djangoobject.field1, -# 'field2': djangoobject.date.strftime('%Y.%M'), -# ..... } -# -# The date/time flatten function is there because JSONRPC doesn't -# support date/time objects or formats, so conversion to a string -# is the most logical choice. pyjamas, being python, can easily -# be used to parse the string result at the other end. -# -# use as follows: -# -# jsonservice = JSONRPCService() -# -# @jsonremote(jsonservice) -# def list_some_model(request, start=0, count=10): -# l = SomeDjangoModelClass.objects.filter() -# res = json_convert(l[start:end]) -# -# @jsonremote(jsonservice) -# def list_another_model(request, start=0, count=10): -# l = AnotherDjangoModelClass.objects.filter() -# res = json_convert(l[start:end]) -# -# dump jsonservice into urlpatterns to make the two RPC functions, -# list_some_model and list_another_model part of the django app: -# (r'^service1/$', 'djangoapp.views.jsonservice'), - -from django.core.serializers import serialize -import datetime -from datetime import date - -def dict_datetimeflatten(item): - d = {} - for k, v in item.items(): - k = str(k) - if isinstance(v, datetime.date): - d[k] = str(v) - elif isinstance(v, dict): - d[k] = dict_datetimeflatten(v) - else: - d[k] = v - return d - -def json_convert(l, fields=None): - res = [] - for item in serialize('python', l, fields=fields): - res.append(dict_datetimeflatten(item)) - return res - diff -r 3edd2f19bce2 -r e0424e96e3fd py_ext/modules/svgui/pyjs/jsonrpc/jsonrpc.py --- a/py_ext/modules/svgui/pyjs/jsonrpc/jsonrpc.py Wed May 09 00:39:54 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,43 +0,0 @@ -import gluon.contrib.simplejson as simplejson -import types -import sys - -class JSONRPCServiceBase: - - def __init__(self): - self.methods={} - - def response(self, id, result): - return simplejson.dumps({'version': '1.1', 'id':id, - 'result':result, 'error':None}) - def error(self, id, code, message): - return simplejson.dumps({'id': id, - 'version': '1.1', - 'error': {'name': 'JSONRPCError', - 'code': code, - 'message': message - } - }) - - def add_method(self, name, method): - self.methods[name] = method - - def process(self, data): - data = simplejson.loads(data) - id, method, params = data["id"], data["method"], data["params"] - if method in self.methods: - try: - result =self.methods[method](*params) - return self.response(id, result) - except BaseException: - etype, eval, etb = sys.exc_info() - return self.error(id, 100, '%s: %s' %(etype.__name__, eval)) - except: - etype, eval, etb = sys.exc_info() - return self.error(id, 100, 'Exception %s: %s' %(etype, eval)) - else: - return self.error(id, 100, 'method "%s" does not exist' % method) - - def listmethods(self): - return self.methods.keys() - diff -r 3edd2f19bce2 -r e0424e96e3fd py_ext/modules/svgui/pyjs/jsonrpc/web2py/jsonrpc.py --- a/py_ext/modules/svgui/pyjs/jsonrpc/web2py/jsonrpc.py Wed May 09 00:39:54 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,11 +0,0 @@ -from pyjs.jsonrpc import JSONRPCServiceBase - -class JSONRPCService(JSONRPCServiceBase): - - def serve(self): - return self.process(request.body.read()) - - def __call__(self,func): - self.methods[func.__name__]=func - return func - diff -r 3edd2f19bce2 -r e0424e96e3fd py_ext/modules/svgui/pyjs/lib/_pyjs.js --- a/py_ext/modules/svgui/pyjs/lib/_pyjs.js Wed May 09 00:39:54 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,160 +0,0 @@ -function pyjs_extend(klass, base) { - function klass_object_inherit() {} - klass_object_inherit.prototype = base.prototype; - klass_object = new klass_object_inherit(); - for (var i in base.prototype.__class__) { - v = base.prototype.__class__[i]; - if (typeof v == "function" && (v.class_method || v.static_method || v.unbound_method)) - { - klass_object[i] = v; - } - } - - function klass_inherit() {} - klass_inherit.prototype = klass_object; - klass.prototype = new klass_inherit(); - klass_object.constructor = klass; - klass.prototype.__class__ = klass_object; - - for (var i in base.prototype) { - v = base.prototype[i]; - if (typeof v == "function" && v.instance_method) - { - klass.prototype[i] = v; - } - } -} - -/* creates a class, derived from bases, with methods and variables */ -function pyjs_type(clsname, bases, methods) -{ - var fn_cls = function() {}; - fn_cls.__name__ = clsname; - var fn = function() { - var instance = new fn_cls(); - if(instance.__init__) instance.__init__.apply(instance, arguments); - return instance; - } - fn_cls.__initialize__ = function() { - if (fn_cls.__was_initialized__) return; - fn_cls.__was_initialized__ = true; - fn_cls.__extend_baseclasses(); - fn_cls.prototype.__class__.__new__ = fn; - fn_cls.prototype.__class__.__name__ = clsname; - } - fn_cls.__extend_baseclasses = function() { - var bi; - for (bi in fn_cls.__baseclasses) - { - var b = fn_cls.__baseclasses[bi]; - if (b.__was_initialized__) - { - continue; - } - b.__initialize__(); - } - for (bi in fn_cls.__baseclasses) - { - var b = fn_cls.__baseclasses[bi]; - pyjs_extend(fn_cls, b); - } - } - if (!bases) { - bases = [pyjslib.__Object]; - } - fn_cls.__baseclasses = bases; - - fn_cls.__initialize__(); - - for (k in methods) { - var mth = methods[k]; - var mtype = typeof mth; - if (mtype == "function" ) { - fn_cls.prototype[k] = mth; - fn_cls.prototype.__class__[k] = function () { - return fn_cls.prototype[k].call.apply( - fn_cls.prototype[k], arguments); - }; - fn_cls.prototype.__class__[k].unbound_method = true; - fn_cls.prototype.instance_method = true; - fn_cls.prototype.__class__[k].__name__ = k; - fn_cls.prototype[k].__name__ = k; - } else { - fn_cls.prototype.__class__[k] = mth; - } - } - return fn; -} -function pyjs_kwargs_call(obj, func, star_args, args) -{ - var call_args; - - if (star_args) - { - if (!pyjslib.isIteratable(star_args)) - { - throw (pyjslib.TypeError(func.__name__ + "() arguments after * must be a sequence" + pyjslib.repr(star_args))); - } - call_args = Array(); - var __i = star_args.__iter__(); - var i = 0; - try { - while (true) { - call_args[i]=__i.next(); - i++; - } - } catch (e) { - if (e != pyjslib.StopIteration) { - throw e; - } - } - - if (args) - { - var n = star_args.length; - for (var i=0; i < args.length; i++) { - call_args[n+i]=args[i]; - } - } - } - else - { - call_args = args; - } - return func.apply(obj, call_args); -} - -function pyjs_kwargs_function_call(func, star_args, args) -{ - return pyjs_kwargs_call(null, func, star_args, args); -} - -function pyjs_kwargs_method_call(obj, method_name, star_args, args) -{ - var method = obj[method_name]; - if (method.parse_kwargs) - { - args = method.parse_kwargs.apply(null, args); - } - return pyjs_kwargs_call(obj, method, star_args, args); -} - -//String.prototype.__getitem__ = String.prototype.charAt; -//String.prototype.upper = String.prototype.toUpperCase; -//String.prototype.lower = String.prototype.toLowerCase; -//String.prototype.find=pyjslib.String_find; -//String.prototype.join=pyjslib.String_join; -//String.prototype.isdigit=pyjslib.String_isdigit; -//String.prototype.__iter__=pyjslib.String___iter__; -// -//String.prototype.__replace=String.prototype.replace; -//String.prototype.replace=pyjslib.String_replace; -// -//String.prototype.split=pyjslib.String_split; -//String.prototype.strip=pyjslib.String_strip; -//String.prototype.lstrip=pyjslib.String_lstrip; -//String.prototype.rstrip=pyjslib.String_rstrip; -//String.prototype.startswith=pyjslib.String_startswith; - -var str = String; - diff -r 3edd2f19bce2 -r e0424e96e3fd py_ext/modules/svgui/pyjs/lib/json.js --- a/py_ext/modules/svgui/pyjs/lib/json.js Wed May 09 00:39:54 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,293 +0,0 @@ -json_parse = (function () { - -// This is a function that can parse a JSON text, producing a JavaScript -// data structure. It is a simple, recursive descent parser. It does not use -// eval or regular expressions, so it can be used as a model for implementing -// a JSON parser in other languages. - -// We are defining the function inside of another function to avoid creating -// global variables. - - var at, // The index of the current character - ch, // The current character - escapee = { - '"': '"', - '\\': '\\', - '/': '/', - b: '\b', - f: '\f', - n: '\n', - r: '\r', - t: '\t' - }, - text, - - error = function (m) { - -// Call error when something is wrong. - - throw { - name: 'SyntaxError', - message: m, - at: at, - text: text - }; - }, - - next = function (c) { - -// If a c parameter is provided, verify that it matches the current character. - - if (c && c !== ch) { - error("Expected '" + c + "' instead of '" + ch + "'"); - } - -// Get the next character. When there are no more characters, -// return the empty string. - - ch = text.charAt(at); - at += 1; - return ch; - }, - - number = function () { - -// Parse a number value. - - var number, - string = ''; - - if (ch === '-') { - string = '-'; - next('-'); - } - while (ch >= '0' && ch <= '9') { - string += ch; - next(); - } - if (ch === '.') { - string += '.'; - while (next() && ch >= '0' && ch <= '9') { - string += ch; - } - } - if (ch === 'e' || ch === 'E') { - string += ch; - next(); - if (ch === '-' || ch === '+') { - string += ch; - next(); - } - while (ch >= '0' && ch <= '9') { - string += ch; - next(); - } - } - number = +string; - if (isNaN(number)) { - error("Bad number"); - } else { - return number; - } - }, - - string = function () { - -// Parse a string value. - - var hex, - i, - string = '', - uffff; - -// When parsing for string values, we must look for " and \ characters. - - if (ch === '"') { - while (next()) { - if (ch === '"') { - next(); - return string; - } else if (ch === '\\') { - next(); - if (ch === 'u') { - uffff = 0; - for (i = 0; i < 4; i += 1) { - hex = parseInt(next(), 16); - if (!isFinite(hex)) { - break; - } - uffff = uffff * 16 + hex; - } - string += String.fromCharCode(uffff); - } else if (typeof escapee[ch] === 'string') { - string += escapee[ch]; - } else { - break; - } - } else { - string += ch; - } - } - } - error("Bad string"); - }, - - white = function () { - -// Skip whitespace. - - while (ch && ch <= ' ') { - next(); - } - }, - - word = function () { - -// true, false, or null. - - switch (ch) { - case 't': - next('t'); - next('r'); - next('u'); - next('e'); - return true; - case 'f': - next('f'); - next('a'); - next('l'); - next('s'); - next('e'); - return false; - case 'n': - next('n'); - next('u'); - next('l'); - next('l'); - return null; - } - error("Unexpected '" + ch + "'"); - }, - - value, // Place holder for the value function. - - array = function () { - -// Parse an array value. - - var array = []; - - if (ch === '[') { - next('['); - white(); - if (ch === ']') { - next(']'); - return array; // empty array - } - while (ch) { - array.push(value()); - white(); - if (ch === ']') { - next(']'); - return array; - } - next(','); - white(); - } - } - error("Bad array"); - }, - - object = function () { - -// Parse an object value. - - var key, - object = {}; - - if (ch === '{') { - next('{'); - white(); - if (ch === '}') { - next('}'); - return object; // empty object - } - while (ch) { - key = string(); - white(); - next(':'); - if (Object.hasOwnProperty.call(object, key)) { - error('Duplicate key "' + key + '"'); - } - object[key] = value(); - white(); - if (ch === '}') { - next('}'); - return object; - } - next(','); - white(); - } - } - error("Bad object"); - }; - - value = function () { - -// Parse a JSON value. It could be an object, an array, a string, a number, -// or a word. - - white(); - switch (ch) { - case '{': - return object(); - case '[': - return array(); - case '"': - return string(); - case '-': - return number(); - default: - return ch >= '0' && ch <= '9' ? number() : word(); - } - }; - -// Return the json_parse function. It will have access to all of the above -// functions and variables. - - return function (source, reviver) { - var result; - - text = source; - at = 0; - ch = ' '; - result = value(); - white(); - if (ch) { - error("Syntax error"); - } - -// If there is a reviver function, we recursively walk the new structure, -// passing each name/value pair to the reviver function for possible -// transformation, starting with a temporary root object that holds the result -// in an empty key. If there is not a reviver function, we simply return the -// result. - - return typeof reviver === 'function' ? (function walk(holder, key) { - var k, v, value = holder[key]; - if (value && typeof value === 'object') { - for (k in value) { - if (Object.hasOwnProperty.call(value, k)) { - v = walk(value, k); - if (v !== undefined) { - value[k] = v; - } else { - delete value[k]; - } - } - } - } - return reviver.call(holder, key, value); - }({'': result}, '')) : result; - }; -}()); diff -r 3edd2f19bce2 -r e0424e96e3fd py_ext/modules/svgui/pyjs/lib/pyjslib.py --- a/py_ext/modules/svgui/pyjs/lib/pyjslib.py Wed May 09 00:39:54 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1365 +0,0 @@ -# Copyright 2006 James Tauber and contributors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - - -# iteration from Bob Ippolito's Iteration in JavaScript - -from __pyjamas__ import JS - -# must declare import _before_ importing sys - -def import_module(path, parent_module, module_name, dynamic=1, async=False): - """ - """ - - JS(""" - var cache_file; - - if (module_name == "sys" || module_name == 'pyjslib') - { - /*module_load_request[module_name] = 1;*/ - return; - } - - if (path == null) - { - path = './'; - } - - var override_name = sys.platform + "." + module_name; - if (((sys.overrides != null) && - (sys.overrides.has_key(override_name)))) - { - cache_file = sys.overrides.__getitem__(override_name) ; - } - else - { - cache_file = module_name ; - } - - cache_file = (path + cache_file + '.cache.js' ) ; - - //alert("cache " + cache_file + " " + module_name + " " + parent_module); - - /* already loaded? */ - if (module_load_request[module_name]) - { - if (module_load_request[module_name] >= 3 && parent_module != null) - { - //onload_fn = parent_module + '.' + module_name + ' = ' + module_name + ';'; - //pyjs_eval(onload_fn); /* set up the parent-module namespace */ - } - return; - } - if (typeof (module_load_request[module_name]) == 'undefined') - { - module_load_request[module_name] = 1; - } - - /* following a load, this first executes the script - * "preparation" function MODULENAME_loaded_fn() - * and then sets up the loaded module in the namespace - * of the parent. - */ - - onload_fn = ''; // module_name + "_loaded_fn();" - - if (parent_module != null) - { - //onload_fn += parent_module + '.' + module_name + ' = ' + module_name + ';'; - /*pmod = parent_module + '.' + module_name; - onload_fn += 'alert("' + pmod + '"+' + pmod+');';*/ - } - - - if (dynamic) - { - /* this one tacks the script onto the end of the DOM - */ - - pyjs_load_script(cache_file, onload_fn, async); - - /* this one actually RUNS the script (eval) into the page. - my feeling is that this would be better for non-async - but i can't get it to work entirely yet. - */ - /*pyjs_ajax_eval(cache_file, onload_fn, async);*/ - } - else - { - if (module_name != "pyjslib" && - module_name != "sys") - pyjs_eval(onload_fn); - } - - """) - -JS(""" -function import_wait(proceed_fn, parent_mod, dynamic) { - - var data = ''; - var element = $doc.createElement("div"); - $doc.body.appendChild(element); - function write_dom(txt) { - element.innerHTML = txt + '
'; - } - - var timeoutperiod = 1; - if (dynamic) - var timeoutperiod = 1; - - var wait = function() { - - var status = ''; - for (l in module_load_request) - { - var m = module_load_request[l]; - if (l == "sys" || l == 'pyjslib') - continue; - status += l + m + " "; - } - - //write_dom( " import wait " + wait_count + " " + status + " parent_mod " + parent_mod); - wait_count += 1; - - if (status == '') - { - setTimeout(wait, timeoutperiod); - return; - } - - for (l in module_load_request) - { - var m = module_load_request[l]; - if (l == "sys" || l == 'pyjslib') - { - module_load_request[l] = 4; - continue; - } - if ((parent_mod != null) && (l == parent_mod)) - { - if (m == 1) - { - setTimeout(wait, timeoutperiod); - return; - } - if (m == 2) - { - /* cheat and move app on to next stage */ - module_load_request[l] = 3; - } - } - if (m == 1 || m == 2) - { - setTimeout(wait, timeoutperiod); - return; - } - if (m == 3) - { - //alert("waited for module " + l + ": loaded"); - module_load_request[l] = 4; - mod_fn = modules[l]; - } - } - //alert("module wait done"); - - if (proceed_fn.importDone) - proceed_fn.importDone(proceed_fn); - else - proceed_fn(); - } - - wait(); -} -""") - -class Object: - pass - -object = Object - -class Modload: - - def __init__(self, path, app_modlist, app_imported_fn, dynamic, - parent_mod): - self.app_modlist = app_modlist - self.app_imported_fn = app_imported_fn - self.path = path - self.idx = 0; - self.dynamic = dynamic - self.parent_mod = parent_mod - - def next(self): - - for i in range(len(self.app_modlist[self.idx])): - app = self.app_modlist[self.idx][i] - import_module(self.path, self.parent_mod, app, self.dynamic, True); - self.idx += 1 - - if self.idx >= len(self.app_modlist): - import_wait(self.app_imported_fn, self.parent_mod, self.dynamic) - else: - import_wait(getattr(self, "next"), self.parent_mod, self.dynamic) - -def get_module(module_name): - ev = "__mod = %s;" % module_name - JS("pyjs_eval(ev);") - return __mod - -def preload_app_modules(path, app_modnames, app_imported_fn, dynamic, - parent_mod=None): - - loader = Modload(path, app_modnames, app_imported_fn, dynamic, parent_mod) - loader.next() - -import sys - -class BaseException: - - name = "BaseException" - - def __init__(self, *args): - self.args = args - - def __str__(self): - if len(self.args) is 0: - return '' - elif len(self.args) is 1: - return repr(self.args[0]) - return repr(self.args) - - def toString(self): - return str(self) - -class Exception(BaseException): - - name = "Exception" - -class TypeError(BaseException): - name = "TypeError" - -class StandardError(Exception): - name = "StandardError" - -class LookupError(StandardError): - name = "LookupError" - - def toString(self): - return self.name + ": " + self.args[0] - -class KeyError(LookupError): - name = "KeyError" - -class AttributeError(StandardError): - - name = "AttributeError" - - def toString(self): - return "AttributeError: %s of %s" % (self.args[1], self.args[0]) - -JS(""" -pyjslib.StopIteration = function () { }; -pyjslib.StopIteration.prototype = new Error(); -pyjslib.StopIteration.name = 'StopIteration'; -pyjslib.StopIteration.message = 'StopIteration'; - -pyjslib.String_find = function(sub, start, end) { - var pos=this.indexOf(sub, start); - if (pyjslib.isUndefined(end)) return pos; - - if (pos + sub.length>end) return -1; - return pos; -} - -pyjslib.String_join = function(data) { - var text=""; - - if (pyjslib.isArray(data)) { - return data.join(this); - } - else if (pyjslib.isIteratable(data)) { - var iter=data.__iter__(); - try { - text+=iter.next(); - while (true) { - var item=iter.next(); - text+=this + item; - } - } - catch (e) { - if (e != pyjslib.StopIteration) throw e; - } - } - - return text; -} - -pyjslib.String_isdigit = function() { - return (this.match(/^\d+$/g) != null); -} - -pyjslib.String_replace = function(old, replace, count) { - var do_max=false; - var start=0; - var new_str=""; - var pos=0; - - if (!pyjslib.isString(old)) return this.__replace(old, replace); - if (!pyjslib.isUndefined(count)) do_max=true; - - while (start= s.length) { - throw pyjslib.StopIteration; - } - return s.substring(i++, i, 1); - }, - '__iter__': function() { - return this; - } - }; -} - -pyjslib.String_strip = function(chars) { - return this.lstrip(chars).rstrip(chars); -} - -pyjslib.String_lstrip = function(chars) { - if (pyjslib.isUndefined(chars)) return this.replace(/^\s+/, ""); - - return this.replace(new RegExp("^[" + chars + "]+"), ""); -} - -pyjslib.String_rstrip = function(chars) { - if (pyjslib.isUndefined(chars)) return this.replace(/\s+$/, ""); - - return this.replace(new RegExp("[" + chars + "]+$"), ""); -} - -pyjslib.String_startswith = function(prefix, start) { - if (pyjslib.isUndefined(start)) start = 0; - - if (this.substring(start, prefix.length) == prefix) return true; - return false; -} - -pyjslib.abs = Math.abs; - -""") - -class Class: - def __init__(self, name): - self.name = name - - def __str___(self): - return self.name - -def eq(a,b): - JS(""" - if (pyjslib.hasattr(a, "__cmp__")) { - return a.__cmp__(b) == 0; - } else if (pyjslib.hasattr(b, "__cmp__")) { - return b.__cmp__(a) == 0; - } - return a == b; - """) - -def cmp(a,b): - if hasattr(a, "__cmp__"): - return a.__cmp__(b) - elif hasattr(b, "__cmp__"): - return -b.__cmp__(a) - if a > b: - return 1 - elif b > a: - return -1 - else: - return 0 - -def bool(v): - # this needs to stay in native code without any dependencies here, - # because this is used by if and while, we need to prevent - # recursion - JS(""" - if (!v) return false; - switch(typeof v){ - case 'boolean': - return v; - case 'object': - if (v.__nonzero__){ - return v.__nonzero__(); - }else if (v.__len__){ - return v.__len__()>0; - } - return true; - } - return Boolean(v); - """) - -class List: - def __init__(self, data=None): - JS(""" - this.l = []; - this.extend(data); - """) - - def append(self, item): - JS(""" this.l[this.l.length] = item;""") - - def extend(self, data): - JS(""" - if (pyjslib.isArray(data)) { - n = this.l.length; - for (var i=0; i < data.length; i++) { - this.l[n+i]=data[i]; - } - } - else if (pyjslib.isIteratable(data)) { - var iter=data.__iter__(); - var i=this.l.length; - try { - while (true) { - var item=iter.next(); - this.l[i++]=item; - } - } - catch (e) { - if (e != pyjslib.StopIteration) throw e; - } - } - """) - - def remove(self, value): - JS(""" - var index=this.index(value); - if (index<0) return false; - this.l.splice(index, 1); - return true; - """) - - def index(self, value, start=0): - JS(""" - var length=this.l.length; - for (var i=start; i= 0 - - def __iter__(self): - JS(""" - var i = 0; - var l = this.l; - return { - 'next': function() { - if (i >= l.length) { - throw pyjslib.StopIteration; - } - return l[i++]; - }, - '__iter__': function() { - return this; - } - }; - """) - - def reverse(self): - JS(""" this.l.reverse();""") - - def sort(self, compareFunc=None, keyFunc=None, reverse=False): - if not compareFunc: - global cmp - compareFunc = cmp - if keyFunc and reverse: - def thisSort1(a,b): - return -compareFunc(keyFunc(a), keyFunc(b)) - self.l.sort(thisSort1) - elif keyFunc: - def thisSort2(a,b): - return compareFunc(keyFunc(a), keyFunc(b)) - self.l.sort(thisSort2) - elif reverse: - def thisSort3(a,b): - return -compareFunc(a, b) - self.l.sort(thisSort3) - else: - self.l.sort(compareFunc) - - def getArray(self): - """ - Access the javascript Array that is used internally by this list - """ - return self.l - - def __str__(self): - return repr(self) - -list = List - -class Tuple: - def __init__(self, data=None): - JS(""" - this.l = []; - this.extend(data); - """) - - def append(self, item): - JS(""" this.l[this.l.length] = item;""") - - def extend(self, data): - JS(""" - if (pyjslib.isArray(data)) { - n = this.l.length; - for (var i=0; i < data.length; i++) { - this.l[n+i]=data[i]; - } - } - else if (pyjslib.isIteratable(data)) { - var iter=data.__iter__(); - var i=this.l.length; - try { - while (true) { - var item=iter.next(); - this.l[i++]=item; - } - } - catch (e) { - if (e != pyjslib.StopIteration) throw e; - } - } - """) - - def remove(self, value): - JS(""" - var index=this.index(value); - if (index<0) return false; - this.l.splice(index, 1); - return true; - """) - - def index(self, value, start=0): - JS(""" - var length=this.l.length; - for (var i=start; i= 0 - - def __iter__(self): - JS(""" - var i = 0; - var l = this.l; - return { - 'next': function() { - if (i >= l.length) { - throw pyjslib.StopIteration; - } - return l[i++]; - }, - '__iter__': function() { - return this; - } - }; - """) - - def reverse(self): - JS(""" this.l.reverse();""") - - def sort(self, compareFunc=None, keyFunc=None, reverse=False): - if not compareFunc: - global cmp - compareFunc = cmp - if keyFunc and reverse: - def thisSort1(a,b): - return -compareFunc(keyFunc(a), keyFunc(b)) - self.l.sort(thisSort1) - elif keyFunc: - def thisSort2(a,b): - return compareFunc(keyFunc(a), keyFunc(b)) - self.l.sort(thisSort2) - elif reverse: - def thisSort3(a,b): - return -compareFunc(a, b) - self.l.sort(thisSort3) - else: - self.l.sort(compareFunc) - - def getArray(self): - """ - Access the javascript Array that is used internally by this list - """ - return self.l - - def __str__(self): - return repr(self) - -tuple = Tuple - - -class Dict: - def __init__(self, data=None): - JS(""" - this.d = {}; - - if (pyjslib.isArray(data)) { - for (var i in data) { - var item=data[i]; - this.__setitem__(item[0], item[1]); - //var sKey=pyjslib.hash(item[0]); - //this.d[sKey]=item[1]; - } - } - else if (pyjslib.isIteratable(data)) { - var iter=data.__iter__(); - try { - while (true) { - var item=iter.next(); - this.__setitem__(item.__getitem__(0), item.__getitem__(1)); - } - } - catch (e) { - if (e != pyjslib.StopIteration) throw e; - } - } - else if (pyjslib.isObject(data)) { - for (var key in data) { - this.__setitem__(key, data[key]); - } - } - """) - - def __setitem__(self, key, value): - JS(""" - var sKey = pyjslib.hash(key); - this.d[sKey]=[key, value]; - """) - - def __getitem__(self, key): - JS(""" - var sKey = pyjslib.hash(key); - var value=this.d[sKey]; - if (pyjslib.isUndefined(value)){ - throw pyjslib.KeyError(key); - } - return value[1]; - """) - - def __nonzero__(self): - JS(""" - for (var i in this.d){ - return true; - } - return false; - """) - - def __len__(self): - JS(""" - var size=0; - for (var i in this.d) size++; - return size; - """) - - def has_key(self, key): - return self.__contains__(key) - - def __delitem__(self, key): - JS(""" - var sKey = pyjslib.hash(key); - delete this.d[sKey]; - """) - - def __contains__(self, key): - JS(""" - var sKey = pyjslib.hash(key); - return (pyjslib.isUndefined(this.d[sKey])) ? false : true; - """) - - def keys(self): - JS(""" - var keys=new pyjslib.List(); - for (var key in this.d) { - keys.append(this.d[key][0]); - } - return keys; - """) - - def values(self): - JS(""" - var values=new pyjslib.List(); - for (var key in this.d) values.append(this.d[key][1]); - return values; - """) - - def items(self): - JS(""" - var items = new pyjslib.List(); - for (var key in this.d) { - var kv = this.d[key]; - items.append(new pyjslib.List(kv)) - } - return items; - """) - - def __iter__(self): - return self.keys().__iter__() - - def iterkeys(self): - return self.__iter__() - - def itervalues(self): - return self.values().__iter__(); - - def iteritems(self): - return self.items().__iter__(); - - def setdefault(self, key, default_value): - if not self.has_key(key): - self[key] = default_value - - def get(self, key, default_=None): - if not self.has_key(key): - return default_ - return self[key] - - def update(self, d): - for k,v in d.iteritems(): - self[k] = v - - def getObject(self): - """ - Return the javascript Object which this class uses to store - dictionary keys and values - """ - return self.d - - def copy(self): - return Dict(self.items()) - - def __str__(self): - return repr(self) - -dict = Dict - -# taken from mochikit: range( [start,] stop[, step] ) -def range(): - JS(""" - var start = 0; - var stop = 0; - var step = 1; - - if (arguments.length == 2) { - start = arguments[0]; - stop = arguments[1]; - } - else if (arguments.length == 3) { - start = arguments[0]; - stop = arguments[1]; - step = arguments[2]; - } - else if (arguments.length>0) stop = arguments[0]; - - return { - 'next': function() { - if ((step > 0 && start >= stop) || (step < 0 && start <= stop)) throw pyjslib.StopIteration; - var rval = start; - start += step; - return rval; - }, - '__iter__': function() { - return this; - } - } - """) - -def slice(object, lower, upper): - JS(""" - if (pyjslib.isString(object)) { - if (lower < 0) { - lower = object.length + lower; - } - if (upper < 0) { - upper = object.length + upper; - } - if (pyjslib.isNull(upper)) upper=object.length; - return object.substring(lower, upper); - } - if (pyjslib.isObject(object) && object.slice) - return object.slice(lower, upper); - - return null; - """) - -def str(text): - JS(""" - if (pyjslib.hasattr(text,"__str__")) { - return text.__str__(); - } - return String(text); - """) - -def ord(x): - if(isString(x) and len(x) is 1): - JS(""" - return x.charCodeAt(0); - """) - else: - JS(""" - throw pyjslib.TypeError(); - """) - return None - -def chr(x): - JS(""" - return String.fromCharCode(x) - """) - -def is_basetype(x): - JS(""" - var t = typeof(x); - return t == 'boolean' || - t == 'function' || - t == 'number' || - t == 'string' || - t == 'undefined' - ; - """) - -def get_pyjs_classtype(x): - JS(""" - if (pyjslib.hasattr(x, "__class__")) - if (pyjslib.hasattr(x.__class__, "__new__")) - var src = x.__class__.__name__; - return src; - return null; - """) - -def repr(x): - """ Return the string representation of 'x'. - """ - JS(""" - if (x === null) - return "null"; - - if (x === undefined) - return "undefined"; - - var t = typeof(x); - - //alert("repr typeof " + t + " : " + x); - - if (t == "boolean") - return x.toString(); - - if (t == "function") - return ""; - - if (t == "number") - return x.toString(); - - if (t == "string") { - if (x.indexOf("'") == -1) - return "'" + x + "'"; - if (x.indexOf('"') == -1) - return '"' + x + '"'; - var s = x.replace(new RegExp('"', "g"), '\\\\"'); - return '"' + s + '"'; - }; - - if (t == "undefined") - return "undefined"; - - // If we get here, x is an object. See if it's a Pyjamas class. - - if (!pyjslib.hasattr(x, "__init__")) - return "<" + x.toString() + ">"; - - // Handle the common Pyjamas data types. - - var constructor = "UNKNOWN"; - - constructor = pyjslib.get_pyjs_classtype(x); - - //alert("repr constructor: " + constructor); - - if (constructor == "Tuple") { - var contents = x.getArray(); - var s = "("; - for (var i=0; i < contents.length; i++) { - s += pyjslib.repr(contents[i]); - if (i < contents.length - 1) - s += ", "; - }; - s += ")" - return s; - }; - - if (constructor == "List") { - var contents = x.getArray(); - var s = "["; - for (var i=0; i < contents.length; i++) { - s += pyjslib.repr(contents[i]); - if (i < contents.length - 1) - s += ", "; - }; - s += "]" - return s; - }; - - if (constructor == "Dict") { - var keys = new Array(); - for (var key in x.d) - keys.push(key); - - var s = "{"; - for (var i=0; i return the class name. - // Note that we replace underscores with dots so that the name will - // (hopefully!) look like the original Python name. - - //var s = constructor.replace(new RegExp('_', "g"), '.'); - return "<" + constructor + " object>"; - """) - -def float(text): - JS(""" - return parseFloat(text); - """) - -def int(text, radix=0): - JS(""" - return parseInt(text, radix); - """) - -def len(object): - JS(""" - if (object==null) return 0; - if (pyjslib.isObject(object) && object.__len__) return object.__len__(); - return object.length; - """) - -def isinstance(object_, classinfo): - if pyjslib.isUndefined(object_): - return False - if not pyjslib.isObject(object_): - - return False - if _isinstance(classinfo, Tuple): - for ci in classinfo: - if isinstance(object_, ci): - return True - return False - else: - return _isinstance(object_, classinfo) - -def _isinstance(object_, classinfo): - if not pyjslib.isObject(object_): - return False - JS(""" - if (object_.__class__){ - var res = object_ instanceof classinfo.constructor; - return res; - } - return false; - """) - -def getattr(obj, name, default_): - JS(""" - if ((!pyjslib.isObject(obj))||(pyjslib.isUndefined(obj[name]))){ - if (pyjslib.isUndefined(default_)){ - throw pyjslib.AttributeError(obj, name); - }else{ - return default_; - } - } - if (!pyjslib.isFunction(obj[name])) return obj[name]; - var fnwrap = function() { - var args = []; - for (var i = 0; i < arguments.length; i++) { - args.push(arguments[i]); - } - return obj[name].apply(obj,args); - } - fnwrap.__name__ = name; - return fnwrap; - """) - -def setattr(obj, name, value): - JS(""" - if (!pyjslib.isObject(obj)) return null; - - obj[name] = value; - - """) - -def hasattr(obj, name): - JS(""" - if (!pyjslib.isObject(obj)) return false; - if (pyjslib.isUndefined(obj[name])) return false; - - return true; - """) - -def dir(obj): - JS(""" - var properties=new pyjslib.List(); - for (property in obj) properties.append(property); - return properties; - """) - -def filter(obj, method, sequence=None): - # object context is LOST when a method is passed, hence object must be passed separately - # to emulate python behaviour, should generate this code inline rather than as a function call - items = [] - if sequence is None: - sequence = method - method = obj - - for item in sequence: - if method(item): - items.append(item) - else: - for item in sequence: - if method.call(obj, item): - items.append(item) - - return items - - -def map(obj, method, sequence=None): - items = [] - - if sequence is None: - sequence = method - method = obj - - for item in sequence: - items.append(method(item)) - else: - for item in sequence: - items.append(method.call(obj, item)) - - return items - - -def enumerate(sequence): - enumeration = [] - nextIndex = 0 - for item in sequence: - enumeration.append([nextIndex, item]) - nextIndex = nextIndex + 1 - return enumeration - - -def min(*sequence): - minValue = None - for item in sequence: - if minValue is None: - minValue = item - elif item < minValue: - minValue = item - return minValue - - -def max(*sequence): - maxValue = None - for item in sequence: - if maxValue is None: - maxValue = item - elif item > maxValue: - maxValue = item - return maxValue - - -next_hash_id = 0 - -def hash(obj): - JS(""" - if (obj == null) return null; - - if (obj.$H) return obj.$H; - if (obj.__hash__) return obj.__hash__(); - if (obj.constructor == String || obj.constructor == Number || obj.constructor == Date) return obj; - - obj.$H = ++pyjslib.next_hash_id; - return obj.$H; - """) - - -# type functions from Douglas Crockford's Remedial Javascript: http://www.crockford.com/javascript/remedial.html -def isObject(a): - JS(""" - return (a != null && (typeof a == 'object')) || pyjslib.isFunction(a); - """) - -def isFunction(a): - JS(""" - return typeof a == 'function'; - """) - -def isString(a): - JS(""" - return typeof a == 'string'; - """) - -def isNull(a): - JS(""" - return typeof a == 'object' && !a; - """) - -def isArray(a): - JS(""" - return pyjslib.isObject(a) && a.constructor == Array; - """) - -def isUndefined(a): - JS(""" - return typeof a == 'undefined'; - """) - -def isIteratable(a): - JS(""" - return pyjslib.isString(a) || (pyjslib.isObject(a) && a.__iter__); - """) - -def isNumber(a): - JS(""" - return typeof a == 'number' && isFinite(a); - """) - -def toJSObjects(x): - """ - Convert the pyjs pythonic List and Dict objects into javascript Object and Array - objects, recursively. - """ - if isArray(x): - JS(""" - var result = []; - for(var k=0; k < x.length; k++) { - var v = x[k]; - var tv = pyjslib.toJSObjects(v); - result.push(tv); - } - return result; - """) - if isObject(x): - if isinstance(x, Dict): - JS(""" - var o = x.getObject(); - var result = {}; - for (var i in o) { - result[o[i][0].toString()] = o[i][1]; - } - return pyjslib.toJSObjects(result) - """) - elif isinstance(x, List): - return toJSObjects(x.l) - elif hasattr(x, '__class__'): - # we do not have a special implementation for custom - # classes, just pass it on - return x - if isObject(x): - JS(""" - var result = {}; - for(var k in x) { - var v = x[k]; - var tv = pyjslib.toJSObjects(v) - result[k] = tv; - } - return result; - """) - return x - -def printFunc(objs): - JS(""" - if ($wnd.console==undefined) return; - var s = ""; - for(var i=0; i < objs.length; i++) { - if(s != "") s += " "; - s += objs[i]; - } - console.debug(s) - """) - -def type(clsname, bases=None, methods=None): - """ creates a class, derived from bases, with methods and variables - """ - - JS(" var mths = {}; ") - if methods: - for k in methods.keys(): - mth = methods[k] - JS(" mths[k] = mth; ") - - JS(" var bss = null; ") - if bases: - JS("bss = bases.l;") - JS(" return pyjs_type(clsname, bss, mths); ") - diff -r 3edd2f19bce2 -r e0424e96e3fd py_ext/modules/svgui/pyjs/lib/sys.py --- a/py_ext/modules/svgui/pyjs/lib/sys.py Wed May 09 00:39:54 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,59 +0,0 @@ -# the platform name (PyV8, smjs, Mozilla, IE6, Opera, Safari etc.) -platform = '' # to be updated by app, on compile - -# a dictionary of module override names (platform-specific) -overrides = None # to be updated by app, on compile - -# the remote path for loading modules -loadpath = None - -stacktrace = None - -appname = None - -def setloadpath(lp): - global loadpath - loadpath = lp - -def setappname(an): - global appname - appname = an - -def getloadpath(): - global loadpath - return loadpath - -def addoverride(module_name, path): - global overrides - overrides[module_name] = path - -def addstack(linedebug): - JS(""" - if (pyjslib.bool((sys.stacktrace === null))) { - sys.stacktrace = new pyjslib.List([]); - } - sys.stacktrace.append(linedebug); - """) -def popstack(): - JS(""" - sys.stacktrace.pop() - """) - -def printstack(): - JS(""" - var res = ''; - - var __l = sys.stacktrace.__iter__(); - try { - while (true) { - var l = __l.next(); - res += ( l + '\\n' ) ; - } - } catch (e) { - if (e != pyjslib.StopIteration) { - throw e; - } - } - - return res; - """) diff -r 3edd2f19bce2 -r e0424e96e3fd py_ext/modules/svgui/pyjs/pyjs.py --- a/py_ext/modules/svgui/pyjs/pyjs.py Wed May 09 00:39:54 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1777 +0,0 @@ -#!/usr/bin/env python -# Copyright 2006 James Tauber and contributors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - - -import sys -from types import StringType -import compiler -from compiler import ast -import os -import copy - -# the standard location for builtins (e.g. pyjslib) can be -# over-ridden by changing this. it defaults to sys.prefix -# so that on a system-wide install of pyjamas the builtins -# can be found in e.g. {sys.prefix}/share/pyjamas -# -# over-rides can be done by either explicitly modifying -# pyjs.prefix or by setting an environment variable, PYJSPREFIX. - -prefix = sys.prefix - -if os.environ.has_key('PYJSPREFIX'): - prefix = os.environ['PYJSPREFIX'] - -# pyjs.path is the list of paths, just like sys.path, from which -# library modules will be searched for, for compile purposes. -# obviously we don't want to use sys.path because that would result -# in compiling standard python modules into javascript! - -path = [os.path.abspath('')] - -if os.environ.has_key('PYJSPATH'): - for p in os.environ['PYJSPATH'].split(os.pathsep): - p = os.path.abspath(p) - if os.path.isdir(p): - path.append(p) - -# this is the python function used to wrap native javascript -NATIVE_JS_FUNC_NAME = "JS" - -UU = "" - -PYJSLIB_BUILTIN_FUNCTIONS=("cmp", - "map", - "filter", - "dir", - "getattr", - "setattr", - "hasattr", - "int", - "float", - "str", - "repr", - "range", - "len", - "hash", - "abs", - "ord", - "chr", - "enumerate", - "min", - "max", - "bool", - "type", - "isinstance") - -PYJSLIB_BUILTIN_CLASSES=("BaseException", - "Exception", - "StandardError", - "StopIteration", - "AttributeError", - "TypeError", - "KeyError", - "LookupError", - "list", - "dict", - "object", - "tuple", - ) - -def pyjs_builtin_remap(name): - # XXX HACK! - if name == 'list': - name = 'List' - if name == 'object': - name = '__Object' - if name == 'dict': - name = 'Dict' - if name == 'tuple': - name = 'Tuple' - return name - -# XXX: this is a hack: these should be dealt with another way -# however, console is currently the only global name which is causing -# problems. -PYJS_GLOBAL_VARS=("console") - -# This is taken from the django project. -# Escape every ASCII character with a value less than 32. -JS_ESCAPES = ( - ('\\', r'\x5C'), - ('\'', r'\x27'), - ('"', r'\x22'), - ('>', r'\x3E'), - ('<', r'\x3C'), - ('&', r'\x26'), - (';', r'\x3B') - ) + tuple([('%c' % z, '\\x%02X' % z) for z in range(32)]) - -def escapejs(value): - """Hex encodes characters for use in JavaScript strings.""" - for bad, good in JS_ESCAPES: - value = value.replace(bad, good) - return value - -def uuprefix(name, leave_alone=0): - name = name.split(".") - name = name[:leave_alone] + map(lambda x: "__%s" % x, name[leave_alone:]) - return '.'.join(name) - -class Klass: - - klasses = {} - - def __init__(self, name, name_): - self.name = name - self.name_ = name_ - self.klasses[name] = self - self.functions = set() - - def set_base(self, base_name): - self.base = self.klasses.get(base_name) - - def add_function(self, function_name): - self.functions.add(function_name) - - -class TranslationError(Exception): - def __init__(self, message, node): - self.message = "line %s:\n%s\n%s" % (node.lineno, message, node) - - def __str__(self): - return self.message - -def strip_py(name): - return name - -def mod_var_name_decl(raw_module_name): - """ function to get the last component of the module e.g. - pyjamas.ui.DOM into the "namespace". i.e. doing - "import pyjamas.ui.DOM" actually ends up with _two_ - variables - one pyjamas.ui.DOM, the other just "DOM". - but "DOM" is actually local, hence the "var" prefix. - - for PyV8, this might end up causing problems - we'll have - to see: gen_mod_import and mod_var_name_decl might have - to end up in a library-specific module, somewhere. - """ - name = raw_module_name.split(".") - if len(name) == 1: - return '' - child_name = name[-1] - return "var %s = %s;\n" % (child_name, raw_module_name) - -def gen_mod_import(parentName, importName, dynamic=1): - #pyjs_ajax_eval("%(n)s.cache.js", null, true); - return """ - pyjslib.import_module(sys.loadpath, '%(p)s', '%(n)s', %(d)d, false); - """ % ({'p': parentName, 'd': dynamic, 'n': importName}) + \ - mod_var_name_decl(importName) - -class Translator: - - def __init__(self, mn, module_name, raw_module_name, src, debug, mod, output, - dynamic=0, optimize=False, - findFile=None): - - if module_name: - self.module_prefix = module_name + "." - else: - self.module_prefix = "" - self.raw_module_name = raw_module_name - src = src.replace("\r\n", "\n") - src = src.replace("\n\r", "\n") - src = src.replace("\r", "\n") - self.src = src.split("\n") - self.debug = debug - self.imported_modules = [] - self.imported_modules_as = [] - self.imported_js = set() - self.top_level_functions = set() - self.top_level_classes = set() - self.top_level_vars = set() - self.local_arg_stack = [[]] - self.output = output - self.imported_classes = {} - self.method_imported_globals = set() - self.method_self = None - self.nextTupleAssignID = 1 - self.dynamic = dynamic - self.optimize = optimize - self.findFile = findFile - - if module_name.find(".") >= 0: - vdec = '' - else: - vdec = 'var ' - print >>self.output, UU+"%s%s = function (__mod_name__) {" % (vdec, module_name) - - print >>self.output, " if("+module_name+".__was_initialized__) return;" - print >>self.output, " "+UU+module_name+".__was_initialized__ = true;" - print >>self.output, UU+"if (__mod_name__ == null) __mod_name__ = '%s';" % (mn) - print >>self.output, UU+"%s.__name__ = __mod_name__;" % (raw_module_name) - - decl = mod_var_name_decl(raw_module_name) - if decl: - print >>self.output, decl - - - if self.debug: - haltException = self.module_prefix + "HaltException" - print >>self.output, haltException + ' = function () {' - print >>self.output, ' this.message = "Program Halted";' - print >>self.output, ' this.name = "' + haltException + '";' - print >>self.output, '}' - print >>self.output, '' - print >>self.output, haltException + ".prototype.__str__ = function()" - print >>self.output, '{' - print >>self.output, 'return this.message ;' - print >>self.output, '}' - - print >>self.output, haltException + ".prototype.toString = function()" - print >>self.output, '{' - print >>self.output, 'return this.name + ": \\"" + this.message + "\\"";' - print >>self.output, '}' - - isHaltFunction = self.module_prefix + "IsHaltException" - print >>self.output, """ - %s = function (s) { - var suffix="HaltException"; - if (s.length < suffix.length) { - //alert(s + " " + suffix); - return false; - } else { - var ss = s.substring(s.length, (s.length - suffix.length)); - //alert(s + " " + suffix + " " + ss); - return ss == suffix; - } - } - """ % isHaltFunction - for child in mod.node: - if isinstance(child, ast.Function): - self.top_level_functions.add(child.name) - elif isinstance(child, ast.Class): - self.top_level_classes.add(child.name) - - for child in mod.node: - if isinstance(child, ast.Function): - self._function(child, False) - elif isinstance(child, ast.Class): - self._class(child) - elif isinstance(child, ast.Import): - importName = child.names[0][0] - if importName == '__pyjamas__': # special module to help make pyjamas modules loadable in the python interpreter - pass - elif importName.endswith('.js'): - self.imported_js.add(importName) - else: - self.add_imported_module(strip_py(importName)) - elif isinstance(child, ast.From): - if child.modname == '__pyjamas__': # special module to help make pyjamas modules loadable in the python interpreter - pass - else: - self.add_imported_module(child.modname) - self._from(child) - elif isinstance(child, ast.Discard): - self._discard(child, None) - elif isinstance(child, ast.Assign): - self._assign(child, None, True) - elif isinstance(child, ast.AugAssign): - self._augassign(child, None) - elif isinstance(child, ast.If): - self._if(child, None) - elif isinstance(child, ast.For): - self._for(child, None) - elif isinstance(child, ast.While): - self._while(child, None) - elif isinstance(child, ast.Subscript): - self._subscript_stmt(child, None) - elif isinstance(child, ast.Global): - self._global(child, None) - elif isinstance(child, ast.Printnl): - self._print(child, None) - elif isinstance(child, ast.Print): - self._print(child, None) - elif isinstance(child, ast.TryExcept): - self._tryExcept(child, None) - elif isinstance(child, ast.Raise): - self._raise(child, None) - elif isinstance(child, ast.Stmt): - self._stmt(child, None) - else: - raise TranslationError("unsupported type (in __init__)", child) - - # Initialize all classes for this module - #print >> self.output, "__"+self.modpfx()+\ - # "classes_initialize = function() {\n" - #for className in self.top_level_classes: - # print >> self.output, "\t"+UU+self.modpfx()+"__"+className+"_initialize();" - #print >> self.output, "};\n" - - print >> self.output, "return this;\n" - print >> self.output, "}; /* end %s */ \n" % module_name - - def module_imports(self): - return self.imported_modules + self.imported_modules_as - - def add_local_arg(self, varname): - local_vars = self.local_arg_stack[-1] - if varname not in local_vars: - local_vars.append(varname) - - def add_imported_module(self, importName): - - if importName in self.imported_modules: - return - self.imported_modules.append(importName) - name = importName.split(".") - if len(name) != 1: - # add the name of the module to the namespace, - # but don't add the short name to imported_modules - # because then the short name would be attempted to be - # added to the dependencies, and it's half way up the - # module import directory structure! - child_name = name[-1] - self.imported_modules_as.append(child_name) - print >> self.output, gen_mod_import(self.raw_module_name, - strip_py(importName), - self.dynamic) - - def _default_args_handler(self, node, arg_names, current_klass, - output=None): - if len(node.defaults): - output = output or self.output - default_pos = len(arg_names) - len(node.defaults) - if arg_names and arg_names[0] == self.method_self: - default_pos -= 1 - for default_node in node.defaults: - if isinstance(default_node, ast.Const): - default_value = self._const(default_node) - elif isinstance(default_node, ast.Name): - default_value = self._name(default_node, current_klass) - elif isinstance(default_node, ast.UnarySub): - default_value = self._unarysub(default_node, current_klass) - else: - raise TranslationError("unsupported type (in _method)", default_node) - - default_name = arg_names[default_pos] - default_pos += 1 - print >> output, " if (typeof %s == 'undefined') %s=%s;" % (default_name, default_name, default_value) - - def _varargs_handler(self, node, varargname, arg_names, current_klass): - print >>self.output, " var", varargname, '= new pyjslib.Tuple();' - print >>self.output, " for(var __va_arg="+str(len(arg_names))+"; __va_arg < arguments.length; __va_arg++) {" - print >>self.output, " var __arg = arguments[__va_arg];" - print >>self.output, " "+varargname+".append(__arg);" - print >>self.output, " }" - - def _kwargs_parser(self, node, function_name, arg_names, current_klass): - if len(node.defaults) or node.kwargs: - default_pos = len(arg_names) - len(node.defaults) - if arg_names and arg_names[0] == self.method_self: - default_pos -= 1 - print >>self.output, function_name+'.parse_kwargs = function (', ", ".join(["__kwargs"]+arg_names), ") {" - for default_node in node.defaults: - default_value = self.expr(default_node, current_klass) -# if isinstance(default_node, ast.Const): -# default_value = self._const(default_node) -# elif isinstance(default_node, ast.Name): -# default_value = self._name(default_node) -# elif isinstance(default_node, ast.UnarySub): -# default_value = self._unarysub(default_node, current_klass) -# else: -# raise TranslationError("unsupported type (in _method)", default_node) - - default_name = arg_names[default_pos] - print >>self.output, " if (typeof %s == 'undefined')"%(default_name) - print >>self.output, " %s=__kwargs.%s;"% (default_name, default_name) - default_pos += 1 - - #self._default_args_handler(node, arg_names, current_klass) - if node.kwargs: arg_names += ["pyjslib.Dict(__kwargs)"] - print >>self.output, " var __r = "+"".join(["[", ", ".join(arg_names), "]"])+";" - if node.varargs: - self._varargs_handler(node, "__args", arg_names, current_klass) - print >>self.output, " __r.push.apply(__r, __args.getArray())" - print >>self.output, " return __r;" - print >>self.output, "};" - - def _function(self, node, local=False): - if local: - function_name = node.name - self.add_local_arg(function_name) - else: - function_name = UU + self.modpfx() + node.name - - arg_names = list(node.argnames) - normal_arg_names = list(arg_names) - if node.kwargs: kwargname = normal_arg_names.pop() - if node.varargs: varargname = normal_arg_names.pop() - declared_arg_names = list(normal_arg_names) - if node.kwargs: declared_arg_names.append(kwargname) - - function_args = "(" + ", ".join(declared_arg_names) + ")" - print >>self.output, "%s = function%s {" % (function_name, function_args) - self._default_args_handler(node, normal_arg_names, None) - - local_arg_names = normal_arg_names + declared_arg_names - - if node.varargs: - self._varargs_handler(node, varargname, declared_arg_names, None) - local_arg_names.append(varargname) - - # stack of local variable names for this function call - self.local_arg_stack.append(local_arg_names) - - for child in node.code: - self._stmt(child, None) - - # remove the top local arg names - self.local_arg_stack.pop() - - # we need to return null always, so it is not undefined - lastStmt = [p for p in node.code][-1] - if not isinstance(lastStmt, ast.Return): - if not self._isNativeFunc(lastStmt): - print >>self.output, " return null;" - - print >>self.output, "};" - print >>self.output, "%s.__name__ = '%s';\n" % (function_name, node.name) - - - self._kwargs_parser(node, function_name, normal_arg_names, None) - - - def _return(self, node, current_klass): - expr = self.expr(node.value, current_klass) - # in python a function call always returns None, so we do it - # here too - print >>self.output, " return " + expr + ";" - - - def _break(self, node, current_klass): - print >>self.output, " break;" - - - def _continue(self, node, current_klass): - print >>self.output, " continue;" - - - def _callfunc(self, v, current_klass): - - if isinstance(v.node, ast.Name): - if v.node.name in self.top_level_functions: - call_name = self.modpfx() + v.node.name - elif v.node.name in self.top_level_classes: - call_name = self.modpfx() + v.node.name - elif self.imported_classes.has_key(v.node.name): - call_name = self.imported_classes[v.node.name] + '.' + v.node.name - elif v.node.name in PYJSLIB_BUILTIN_FUNCTIONS: - call_name = 'pyjslib.' + v.node.name - elif v.node.name in PYJSLIB_BUILTIN_CLASSES: - name = pyjs_builtin_remap(v.node.name) - call_name = 'pyjslib.' + name - elif v.node.name == "callable": - call_name = "pyjslib.isFunction" - else: - call_name = v.node.name - call_args = [] - elif isinstance(v.node, ast.Getattr): - attr_name = v.node.attrname - - if isinstance(v.node.expr, ast.Name): - call_name = self._name2(v.node.expr, current_klass, attr_name) - call_args = [] - elif isinstance(v.node.expr, ast.Getattr): - call_name = self._getattr2(v.node.expr, current_klass, attr_name) - call_args = [] - elif isinstance(v.node.expr, ast.CallFunc): - call_name = self._callfunc(v.node.expr, current_klass) + "." + v.node.attrname - call_args = [] - elif isinstance(v.node.expr, ast.Subscript): - call_name = self._subscript(v.node.expr, current_klass) + "." + v.node.attrname - call_args = [] - elif isinstance(v.node.expr, ast.Const): - call_name = self.expr(v.node.expr, current_klass) + "." + v.node.attrname - call_args = [] - else: - raise TranslationError("unsupported type (in _callfunc)", v.node.expr) - else: - raise TranslationError("unsupported type (in _callfunc)", v.node) - - call_name = strip_py(call_name) - - kwargs = [] - star_arg_name = None - if v.star_args: - star_arg_name = self.expr(v.star_args, current_klass) - - for ch4 in v.args: - if isinstance(ch4, ast.Keyword): - kwarg = ch4.name + ":" + self.expr(ch4.expr, current_klass) - kwargs.append(kwarg) - else: - arg = self.expr(ch4, current_klass) - call_args.append(arg) - - if kwargs: - fn_args = ", ".join(['{' + ', '.join(kwargs) + '}']+call_args) - else: - fn_args = ", ".join(call_args) - - if kwargs or star_arg_name: - if not star_arg_name: - star_arg_name = 'null' - try: call_this, method_name = call_name.rsplit(".", 1) - except ValueError: - # Must be a function call ... - return ("pyjs_kwargs_function_call("+call_name+", " - + star_arg_name - + ", ["+fn_args+"]" - + ")" ) - else: - return ("pyjs_kwargs_method_call("+call_this+", '"+method_name+"', " - + star_arg_name - + ", ["+fn_args+"]" - + ")") - else: - return call_name + "(" + ", ".join(call_args) + ")" - - def _print(self, node, current_klass): - if self.optimize: - return - call_args = [] - for ch4 in node.nodes: - arg = self.expr(ch4, current_klass) - call_args.append(arg) - - print >>self.output, "pyjslib.printFunc([", ', '.join(call_args), "],", int(isinstance(node, ast.Printnl)), ");" - - def _tryExcept(self, node, current_klass): - if len(node.handlers) != 1: - raise TranslationError("except statements in this form are" + - " not supported", node) - - expr = node.handlers[0][0] - as_ = node.handlers[0][1] - if as_: - errName = as_.name - else: - errName = 'err' - - # XXX TODO: check that this should instead be added as a _separate_ - # local scope, temporary to the function. oh dearie me. - self.add_local_arg(errName) - - print >>self.output, " try {" - for stmt in node.body.nodes: - self._stmt(stmt, current_klass) - print >> self.output, " } catch(%s) {" % errName - if expr: - l = [] - if isinstance(expr, ast.Tuple): - for x in expr.nodes: - l.append("(%(err)s.__name__ == %(expr)s.__name__)" % dict (err=errName, expr=self.expr(x, current_klass))) - else: - l = [ " (%(err)s.__name__ == %(expr)s.__name__) " % dict (err=errName, expr=self.expr(expr, current_klass)) ] - print >> self.output, " if(%s) {" % '||\n\t\t'.join(l) - for stmt in node.handlers[0][2]: - self._stmt(stmt, current_klass) - if expr: - #print >> self.output, "} else { throw(%s); } " % errName - print >> self.output, "}" - if node.else_ != None: - print >>self.output, " } finally {" - for stmt in node.else_: - self._stmt(stmt, current_klass) - print >>self.output, " }" - - # XXX: change use_getattr to True to enable "strict" compilation - # but incurring a 100% performance penalty. oops. - def _getattr(self, v, current_klass, use_getattr=False): - attr_name = v.attrname - if isinstance(v.expr, ast.Name): - obj = self._name(v.expr, current_klass, return_none_for_module=True) - if obj == None and v.expr.name in self.module_imports(): - # XXX TODO: distinguish between module import classes - # and variables. right now, this is a hack to get - # the sys module working. - #if v.expr.name == 'sys': - return v.expr.name+'.'+attr_name - #return v.expr.name+'.__'+attr_name+'.prototype.__class__' - if not use_getattr or attr_name == '__class__' or \ - attr_name == '__name__': - return obj + "." + attr_name - return "pyjslib.getattr(%s, '%s')" % (obj, attr_name) - elif isinstance(v.expr, ast.Getattr): - return self._getattr(v.expr, current_klass) + "." + attr_name - elif isinstance(v.expr, ast.Subscript): - return self._subscript(v.expr, self.modpfx()) + "." + attr_name - elif isinstance(v.expr, ast.CallFunc): - return self._callfunc(v.expr, self.modpfx()) + "." + attr_name - else: - raise TranslationError("unsupported type (in _getattr)", v.expr) - - - def modpfx(self): - return strip_py(self.module_prefix) - - def _name(self, v, current_klass, top_level=False, - return_none_for_module=False): - - if v.name == 'ilikesillynamesfornicedebugcode': - print top_level, current_klass, repr(v) - print self.top_level_vars - print self.top_level_functions - print self.local_arg_stack - print "error..." - - local_var_names = None - las = len(self.local_arg_stack) - if las > 0: - local_var_names = self.local_arg_stack[-1] - - if v.name == "True": - return "true" - elif v.name == "False": - return "false" - elif v.name == "None": - return "null" - elif v.name == '__name__' and current_klass is None: - return self.modpfx() + v.name - elif v.name == self.method_self: - return "this" - elif v.name in self.top_level_functions: - return UU+self.modpfx() + v.name - elif v.name in self.method_imported_globals: - return UU+self.modpfx() + v.name - elif not current_klass and las == 1 and v.name in self.top_level_vars: - return UU+self.modpfx() + v.name - elif v.name in local_var_names: - return v.name - elif self.imported_classes.has_key(v.name): - return UU+self.imported_classes[v.name] + '.__' + v.name + ".prototype.__class__" - elif v.name in self.top_level_classes: - return UU+self.modpfx() + "__" + v.name + ".prototype.__class__" - elif v.name in self.module_imports() and return_none_for_module: - return None - elif v.name in PYJSLIB_BUILTIN_CLASSES: - return "pyjslib." + pyjs_builtin_remap( v.name ) - elif current_klass: - if v.name not in local_var_names and \ - v.name not in self.top_level_vars and \ - v.name not in PYJS_GLOBAL_VARS and \ - v.name not in self.top_level_functions: - - cls_name = current_klass - if hasattr(cls_name, "name"): - cls_name_ = cls_name.name_ - cls_name = cls_name.name - else: - cls_name_ = current_klass + "_" # XXX ??? - name = UU+cls_name_ + ".prototype.__class__." \ - + v.name - if v.name == 'listener': - name = 'listener+' + name - return name - - return v.name - - def _name2(self, v, current_klass, attr_name): - obj = v.name - - if obj in self.method_imported_globals: - call_name = UU+self.modpfx() + obj + "." + attr_name - elif self.imported_classes.has_key(obj): - #attr_str = "" - #if attr_name != "__init__": - attr_str = ".prototype.__class__." + attr_name - call_name = UU+self.imported_classes[obj] + '.__' + obj + attr_str - elif obj in self.module_imports(): - call_name = obj + "." + attr_name - elif obj[0] == obj[0].upper(): # XXX HACK ALERT - call_name = UU + self.modpfx() + "__" + obj + ".prototype.__class__." + attr_name - else: - call_name = UU+self._name(v, current_klass) + "." + attr_name - - return call_name - - - def _getattr2(self, v, current_klass, attr_name): - if isinstance(v.expr, ast.Getattr): - call_name = self._getattr2(v.expr, current_klass, v.attrname + "." + attr_name) - elif isinstance(v.expr, ast.Name) and v.expr.name in self.module_imports(): - call_name = UU+v.expr.name + '.__' +v.attrname+".prototype.__class__."+attr_name - else: - obj = self.expr(v.expr, current_klass) - call_name = obj + "." + v.attrname + "." + attr_name - - return call_name - - - def _class(self, node): - """ - Handle a class definition. - - In order to translate python semantics reasonably well, the following - structure is used: - - A special object is created for the class, which inherits attributes - from the superclass, or Object if there's no superclass. This is the - class object; the object which you refer to when specifying the - class by name. Static, class, and unbound methods are copied - from the superclass object. - - A special constructor function is created with the same name as the - class, which is used to create instances of that class. - - A javascript class (e.g. a function with a prototype attribute) is - created which is the javascript class of created instances, and - which inherits attributes from the class object. Bound methods are - copied from the superclass into this class rather than inherited, - because the class object contains unbound, class, and static methods - that we don't necessarily want to inherit. - - The type of a method can now be determined by inspecting its - static_method, unbound_method, class_method, or instance_method - attribute; only one of these should be true. - - Much of this work is done in pyjs_extend, is pyjslib.py - """ - class_name = self.modpfx() + uuprefix(node.name, 1) - class_name_ = self.modpfx() + uuprefix(node.name) - current_klass = Klass(class_name, class_name_) - init_method = None - for child in node.code: - if isinstance(child, ast.Function): - current_klass.add_function(child.name) - if child.name == "__init__": - init_method = child - - - if len(node.bases) == 0: - base_class = "pyjslib.__Object" - elif len(node.bases) == 1: - if isinstance(node.bases[0], ast.Name): - if self.imported_classes.has_key(node.bases[0].name): - base_class_ = self.imported_classes[node.bases[0].name] + '.__' + node.bases[0].name - base_class = self.imported_classes[node.bases[0].name] + '.' + node.bases[0].name - else: - base_class_ = self.modpfx() + "__" + node.bases[0].name - base_class = self.modpfx() + node.bases[0].name - elif isinstance(node.bases[0], ast.Getattr): - # the bases are not in scope of the class so do not - # pass our class to self._name - base_class_ = self._name(node.bases[0].expr, None) + \ - ".__" + node.bases[0].attrname - base_class = self._name(node.bases[0].expr, None) + \ - "." + node.bases[0].attrname - else: - raise TranslationError("unsupported type (in _class)", node.bases[0]) - - current_klass.set_base(base_class) - else: - raise TranslationError("more than one base (in _class)", node) - - print >>self.output, UU+class_name_ + " = function () {" - # call superconstructor - #if base_class: - # print >>self.output, " __" + base_class + ".call(this);" - print >>self.output, "}" - - if not init_method: - init_method = ast.Function([], "__init__", ["self"], [], 0, None, []) - #self._method(init_method, current_klass, class_name) - - # Generate a function which constructs the object - clsfunc = ast.Function([], - node.name, - init_method.argnames[1:], - init_method.defaults, - init_method.flags, - None, - [ast.Discard(ast.CallFunc(ast.Name("JS"), [ast.Const( -# I attempted lazy initialization, but then you can't access static class members -# " if(!__"+base_class+".__was_initialized__)"+ -# " __" + class_name + "_initialize();\n" + - " var instance = new " + UU + class_name_ + "();\n" + - " if(instance.__init__) instance.__init__.apply(instance, arguments);\n" + - " return instance;" - )]))]) - - self._function(clsfunc, False) - print >>self.output, UU+class_name_ + ".__initialize__ = function () {" - print >>self.output, " if("+UU+class_name_+".__was_initialized__) return;" - print >>self.output, " "+UU+class_name_+".__was_initialized__ = true;" - cls_obj = UU+class_name_ + '.prototype.__class__' - - if class_name == "pyjslib.__Object": - print >>self.output, " "+cls_obj+" = {};" - else: - if base_class and base_class not in ("object", "pyjslib.__Object"): - print >>self.output, " if(!"+UU+base_class_+".__was_initialized__)" - print >>self.output, " "+UU+base_class_+".__initialize__();" - print >>self.output, " pyjs_extend(" + UU+class_name_ + ", "+UU+base_class_+");" - else: - print >>self.output, " pyjs_extend(" + UU+class_name_ + ", "+UU+"pyjslib.__Object);" - - print >>self.output, " "+cls_obj+".__new__ = "+UU+class_name+";" - print >>self.output, " "+cls_obj+".__name__ = '"+UU+node.name+"';" - - for child in node.code: - if isinstance(child, ast.Pass): - pass - elif isinstance(child, ast.Function): - self._method(child, current_klass, class_name, class_name_) - elif isinstance(child, ast.Assign): - self.classattr(child, current_klass) - elif isinstance(child, ast.Discard) and isinstance(child.expr, ast.Const): - # Probably a docstring, turf it - pass - else: - raise TranslationError("unsupported type (in _class)", child) - print >>self.output, "}" - - print >> self.output, class_name_+".__initialize__();" - - - def classattr(self, node, current_klass): - self._assign(node, current_klass, True) - - def _raise(self, node, current_klass): - if node.expr2: - raise TranslationError("More than one expression unsupported", - node) - print >> self.output, "throw (%s);" % self.expr( - node.expr1, current_klass) - - def _method(self, node, current_klass, class_name, class_name_): - # reset global var scope - self.method_imported_globals = set() - - arg_names = list(node.argnames) - - classmethod = False - staticmethod = False - if node.decorators: - for d in node.decorators: - if d.name == "classmethod": - classmethod = True - elif d.name == "staticmethod": - staticmethod = True - - if staticmethod: - staticfunc = ast.Function([], class_name_+"."+node.name, node.argnames, node.defaults, node.flags, node.doc, node.code, node.lineno) - self._function(staticfunc, True) - print >>self.output, " " + UU+class_name_ + ".prototype.__class__." + node.name + " = " + class_name_+"."+node.name+";"; - print >>self.output, " " + UU+class_name_ + ".prototype.__class__." + node.name + ".static_method = true;"; - return - else: - if len(arg_names) == 0: - raise TranslationError("methods must take an argument 'self' (in _method)", node) - self.method_self = arg_names[0] - - #if not classmethod and arg_names[0] != "self": - # raise TranslationError("first arg not 'self' (in _method)", node) - - normal_arg_names = arg_names[1:] - if node.kwargs: kwargname = normal_arg_names.pop() - if node.varargs: varargname = normal_arg_names.pop() - declared_arg_names = list(normal_arg_names) - if node.kwargs: declared_arg_names.append(kwargname) - - function_args = "(" + ", ".join(declared_arg_names) + ")" - - if classmethod: - fexpr = UU + class_name_ + ".prototype.__class__." + node.name - else: - fexpr = UU + class_name_ + ".prototype." + node.name - print >>self.output, " "+fexpr + " = function" + function_args + " {" - - # default arguments - self._default_args_handler(node, normal_arg_names, current_klass) - - local_arg_names = normal_arg_names + declared_arg_names - - if node.varargs: - self._varargs_handler(node, varargname, declared_arg_names, current_klass) - local_arg_names.append(varargname) - - - # stack of local variable names for this function call - self.local_arg_stack.append(local_arg_names) - - for child in node.code: - self._stmt(child, current_klass) - - # remove the top local arg names - self.local_arg_stack.pop() - - print >>self.output, " };" - - self._kwargs_parser(node, fexpr, normal_arg_names, current_klass) - - if classmethod: - # Have to create a version on the instances which automatically passes the - # class as "self" - altexpr = UU + class_name_ + ".prototype." + node.name - print >>self.output, " "+altexpr + " = function() {" - print >>self.output, " return " + fexpr + ".apply(this.__class__, arguments);" - print >>self.output, " };" - print >>self.output, " "+fexpr+".class_method = true;" - print >>self.output, " "+altexpr+".instance_method = true;" - else: - # For instance methods, we need an unbound version in the class object - altexpr = UU + class_name_ + ".prototype.__class__." + node.name - print >>self.output, " "+altexpr + " = function() {" - print >>self.output, " return " + fexpr + ".call.apply("+fexpr+", arguments);" - print >>self.output, " };" - print >>self.output, " "+altexpr+".unbound_method = true;" - print >>self.output, " "+fexpr+".instance_method = true;" - print >>self.output, " "+altexpr+".__name__ = '%s';" % node.name - - print >>self.output, UU + class_name_ + ".prototype.%s.__name__ = '%s';" % \ - (node.name, node.name) - - if node.kwargs or len(node.defaults): - print >>self.output, " "+altexpr + ".parse_kwargs = " + fexpr + ".parse_kwargs;" - - self.method_self = None - self.method_imported_globals = set() - - def _isNativeFunc(self, node): - if isinstance(node, ast.Discard): - if isinstance(node.expr, ast.CallFunc): - if isinstance(node.expr.node, ast.Name) and \ - node.expr.node.name == NATIVE_JS_FUNC_NAME: - return True - return False - - def _stmt(self, node, current_klass): - debugStmt = self.debug and not self._isNativeFunc(node) - if debugStmt: - print >>self.output, ' try {' - - if isinstance(node, ast.Return): - self._return(node, current_klass) - elif isinstance(node, ast.Break): - self._break(node, current_klass) - elif isinstance(node, ast.Continue): - self._continue(node, current_klass) - elif isinstance(node, ast.Assign): - self._assign(node, current_klass) - elif isinstance(node, ast.AugAssign): - self._augassign(node, current_klass) - elif isinstance(node, ast.Discard): - self._discard(node, current_klass) - elif isinstance(node, ast.If): - self._if(node, current_klass) - elif isinstance(node, ast.For): - self._for(node, current_klass) - elif isinstance(node, ast.While): - self._while(node, current_klass) - elif isinstance(node, ast.Subscript): - self._subscript_stmt(node, current_klass) - elif isinstance(node, ast.Global): - self._global(node, current_klass) - elif isinstance(node, ast.Pass): - pass - elif isinstance(node, ast.Function): - self._function(node, True) - elif isinstance(node, ast.Printnl): - self._print(node, current_klass) - elif isinstance(node, ast.Print): - self._print(node, current_klass) - elif isinstance(node, ast.TryExcept): - self._tryExcept(node, current_klass) - elif isinstance(node, ast.Raise): - self._raise(node, current_klass) - else: - raise TranslationError("unsupported type (in _stmt)", node) - - if debugStmt: - - lt = self.get_line_trace(node) - - haltException = self.module_prefix + "HaltException" - isHaltFunction = self.module_prefix + "IsHaltException" - - print >>self.output, ' } catch (__err) {' - print >>self.output, ' if (' + isHaltFunction + '(__err.name)) {' - print >>self.output, ' throw __err;' - print >>self.output, ' } else {' - print >>self.output, " st = sys.printstack() + "\ - + '"%s"' % lt + "+ '\\n' ;" - print >>self.output, ' alert("' + "Error in " \ - + lt + '"' \ - + '+"\\n"+__err.name+": "+__err.message'\ - + '+"\\n\\nStack trace:\\n"' \ - + '+st' \ - + ');' - print >>self.output, ' debugger;' - - print >>self.output, ' throw new ' + self.module_prefix + "HaltException();" - print >>self.output, ' }' - print >>self.output, ' }' - - - def get_line_trace(self, node): - lineNum = "Unknown" - srcLine = "" - if hasattr(node, "lineno"): - if node.lineno != None: - lineNum = node.lineno - srcLine = self.src[min(lineNum, len(self.src))-1] - srcLine = srcLine.replace('\\', '\\\\') - srcLine = srcLine.replace('"', '\\"') - srcLine = srcLine.replace("'", "\\'") - - return self.raw_module_name + ".py, line " \ - + str(lineNum) + ":"\ - + "\\n" \ - + " " + srcLine - - def _augassign(self, node, current_klass): - v = node.node - if isinstance(v, ast.Getattr): - # XXX HACK! don't allow += on return result of getattr. - # TODO: create a temporary variable or something. - lhs = self._getattr(v, current_klass, False) - else: - lhs = self._name(node.node, current_klass) - op = node.op - rhs = self.expr(node.expr, current_klass) - print >>self.output, " " + lhs + " " + op + " " + rhs + ";" - - - def _assign(self, node, current_klass, top_level = False): - if len(node.nodes) != 1: - tempvar = '__temp'+str(node.lineno) - tnode = ast.Assign([ast.AssName(tempvar, "OP_ASSIGN", node.lineno)], node.expr, node.lineno) - self._assign(tnode, current_klass, top_level) - for v in node.nodes: - tnode2 = ast.Assign([v], ast.Name(tempvar, node.lineno), node.lineno) - self._assign(tnode2, current_klass, top_level) - return - - local_var_names = None - if len(self.local_arg_stack) > 0: - local_var_names = self.local_arg_stack[-1] - - def _lhsFromAttr(v, current_klass): - attr_name = v.attrname - if isinstance(v.expr, ast.Name): - obj = v.expr.name - lhs = self._name(v.expr, current_klass) + "." + attr_name - elif isinstance(v.expr, ast.Getattr): - lhs = self._getattr(v, current_klass) - elif isinstance(v.expr, ast.Subscript): - lhs = self._subscript(v.expr, current_klass) + "." + attr_name - else: - raise TranslationError("unsupported type (in _assign)", v.expr) - return lhs - - def _lhsFromName(v, top_level, current_klass): - if top_level: - if current_klass: - lhs = UU+current_klass.name_ + ".prototype.__class__." \ - + v.name - else: - self.top_level_vars.add(v.name) - vname = self.modpfx() + v.name - if not self.modpfx() and v.name not in\ - self.method_imported_globals: - lhs = "var " + vname - else: - lhs = UU + vname - self.add_local_arg(v.name) - else: - if v.name in local_var_names: - lhs = v.name - elif v.name in self.method_imported_globals: - lhs = self.modpfx() + v.name - else: - lhs = "var " + v.name - self.add_local_arg(v.name) - return lhs - - dbg = 0 - v = node.nodes[0] - if isinstance(v, ast.AssAttr): - lhs = _lhsFromAttr(v, current_klass) - if v.flags == "OP_ASSIGN": - op = "=" - else: - raise TranslationError("unsupported flag (in _assign)", v) - - elif isinstance(v, ast.AssName): - lhs = _lhsFromName(v, top_level, current_klass) - if v.flags == "OP_ASSIGN": - op = "=" - else: - raise TranslationError("unsupported flag (in _assign)", v) - elif isinstance(v, ast.Subscript): - if v.flags == "OP_ASSIGN": - obj = self.expr(v.expr, current_klass) - if len(v.subs) != 1: - raise TranslationError("must have one sub (in _assign)", v) - idx = self.expr(v.subs[0], current_klass) - value = self.expr(node.expr, current_klass) - print >>self.output, " " + obj + ".__setitem__(" + idx + ", " + value + ");" - return - else: - raise TranslationError("unsupported flag (in _assign)", v) - elif isinstance(v, (ast.AssList, ast.AssTuple)): - uniqueID = self.nextTupleAssignID - self.nextTupleAssignID += 1 - tempName = "__tupleassign" + str(uniqueID) + "__" - print >>self.output, " var " + tempName + " = " + \ - self.expr(node.expr, current_klass) + ";" - for index,child in enumerate(v.getChildNodes()): - rhs = tempName + ".__getitem__(" + str(index) + ")" - - if isinstance(child, ast.AssAttr): - lhs = _lhsFromAttr(child, current_klass) - elif isinstance(child, ast.AssName): - lhs = _lhsFromName(child, top_level, current_klass) - elif isinstance(child, ast.Subscript): - if child.flags == "OP_ASSIGN": - obj = self.expr(child.expr, current_klass) - if len(child.subs) != 1: - raise TranslationError("must have one sub " + - "(in _assign)", child) - idx = self.expr(child.subs[0], current_klass) - value = self.expr(node.expr, current_klass) - print >>self.output, " " + obj + ".__setitem__(" \ - + idx + ", " + rhs + ");" - continue - print >>self.output, " " + lhs + " = " + rhs + ";" - return - else: - raise TranslationError("unsupported type (in _assign)", v) - - rhs = self.expr(node.expr, current_klass) - if dbg: - print "b", repr(node.expr), rhs - print >>self.output, " " + lhs + " " + op + " " + rhs + ";" - - - def _discard(self, node, current_klass): - - if isinstance(node.expr, ast.CallFunc): - debugStmt = self.debug and not self._isNativeFunc(node) - if debugStmt and isinstance(node.expr.node, ast.Name) and \ - node.expr.node.name == 'import_wait': - debugStmt = False - if debugStmt: - st = self.get_line_trace(node) - print >>self.output, "sys.addstack('%s');\n" % st - if isinstance(node.expr.node, ast.Name) and node.expr.node.name == NATIVE_JS_FUNC_NAME: - if len(node.expr.args) != 1: - raise TranslationError("native javascript function %s must have one arg" % NATIVE_JS_FUNC_NAME, node.expr) - if not isinstance(node.expr.args[0], ast.Const): - raise TranslationError("native javascript function %s must have constant arg" % NATIVE_JS_FUNC_NAME, node.expr) - raw_js = node.expr.args[0].value - print >>self.output, raw_js - else: - expr = self._callfunc(node.expr, current_klass) - print >>self.output, " " + expr + ";" - - if debugStmt: - print >>self.output, "sys.popstack();\n" - - elif isinstance(node.expr, ast.Const): - if node.expr.value is not None: # Empty statements generate ignore None - print >>self.output, self._const(node.expr) - else: - raise TranslationError("unsupported type (in _discard)", node.expr) - - - def _if(self, node, current_klass): - for i in range(len(node.tests)): - test, consequence = node.tests[i] - if i == 0: - keyword = "if" - else: - keyword = "else if" - - self._if_test(keyword, test, consequence, current_klass) - - if node.else_: - keyword = "else" - test = None - consequence = node.else_ - - self._if_test(keyword, test, consequence, current_klass) - - - def _if_test(self, keyword, test, consequence, current_klass): - if test: - expr = self.expr(test, current_klass) - - print >>self.output, " " + keyword + " (pyjslib.bool(" + expr + ")) {" - else: - print >>self.output, " " + keyword + " {" - - if isinstance(consequence, ast.Stmt): - for child in consequence.nodes: - self._stmt(child, current_klass) - else: - raise TranslationError("unsupported type (in _if_test)", consequence) - - print >>self.output, " }" - - - def _from(self, node): - for name in node.names: - # look up "hack" in AppTranslator as to how findFile gets here - module_name = node.modname + "." + name[0] - try: - ff = self.findFile(module_name + ".py") - except Exception: - ff = None - if ff: - self.add_imported_module(module_name) - else: - self.imported_classes[name[0]] = node.modname - - - def _compare(self, node, current_klass): - lhs = self.expr(node.expr, current_klass) - - if len(node.ops) != 1: - raise TranslationError("only one ops supported (in _compare)", node) - - op = node.ops[0][0] - rhs_node = node.ops[0][1] - rhs = self.expr(rhs_node, current_klass) - - if op == "==": - return "pyjslib.eq(%s, %s)" % (lhs, rhs) - if op == "in": - return rhs + ".__contains__(" + lhs + ")" - elif op == "not in": - return "!" + rhs + ".__contains__(" + lhs + ")" - elif op == "is": - op = "===" - elif op == "is not": - op = "!==" - - return "(" + lhs + " " + op + " " + rhs + ")" - - - def _not(self, node, current_klass): - expr = self.expr(node.expr, current_klass) - - return "!(" + expr + ")" - - def _or(self, node, current_klass): - expr = "("+(") || (".join([self.expr(child, current_klass) for child in node.nodes]))+')' - return expr - - def _and(self, node, current_klass): - expr = "("+(") && (".join([self.expr(child, current_klass) for child in node.nodes]))+")" - return expr - - def _for(self, node, current_klass): - assign_name = "" - assign_tuple = "" - - # based on Bob Ippolito's Iteration in Javascript code - if isinstance(node.assign, ast.AssName): - assign_name = node.assign.name - self.add_local_arg(assign_name) - if node.assign.flags == "OP_ASSIGN": - op = "=" - elif isinstance(node.assign, ast.AssTuple): - op = "=" - i = 0 - for child in node.assign: - child_name = child.name - if assign_name == "": - assign_name = "temp_" + child_name - self.add_local_arg(child_name) - assign_tuple += """ - var %(child_name)s %(op)s %(assign_name)s.__getitem__(%(i)i); - """ % locals() - i += 1 - else: - raise TranslationError("unsupported type (in _for)", node.assign) - - if isinstance(node.list, ast.Name): - list_expr = self._name(node.list, current_klass) - elif isinstance(node.list, ast.Getattr): - list_expr = self._getattr(node.list, current_klass) - elif isinstance(node.list, ast.CallFunc): - list_expr = self._callfunc(node.list, current_klass) - else: - raise TranslationError("unsupported type (in _for)", node.list) - - lhs = "var " + assign_name - iterator_name = "__" + assign_name - - print >>self.output, """ - var %(iterator_name)s = %(list_expr)s.__iter__(); - try { - while (true) { - %(lhs)s %(op)s %(iterator_name)s.next(); - %(assign_tuple)s - """ % locals() - for node in node.body.nodes: - self._stmt(node, current_klass) - print >>self.output, """ - } - } catch (e) { - if (e.__name__ != pyjslib.StopIteration.__name__) { - throw e; - } - } - """ % locals() - - - def _while(self, node, current_klass): - test = self.expr(node.test, current_klass) - print >>self.output, " while (pyjslib.bool(" + test + ")) {" - if isinstance(node.body, ast.Stmt): - for child in node.body.nodes: - self._stmt(child, current_klass) - else: - raise TranslationError("unsupported type (in _while)", node.body) - print >>self.output, " }" - - - def _const(self, node): - if isinstance(node.value, int): - return str(node.value) - elif isinstance(node.value, float): - return str(node.value) - elif isinstance(node.value, basestring): - v = node.value - if isinstance(node.value, unicode): - v = v.encode('utf-8') - return "String('%s')" % escapejs(v) - elif node.value is None: - return "null" - else: - raise TranslationError("unsupported type (in _const)", node) - - def _unaryadd(self, node, current_klass): - return self.expr(node.expr, current_klass) - - def _unarysub(self, node, current_klass): - return "-" + self.expr(node.expr, current_klass) - - def _add(self, node, current_klass): - return self.expr(node.left, current_klass) + " + " + self.expr(node.right, current_klass) - - def _sub(self, node, current_klass): - return self.expr(node.left, current_klass) + " - " + self.expr(node.right, current_klass) - - def _div(self, node, current_klass): - return self.expr(node.left, current_klass) + " / " + self.expr(node.right, current_klass) - - def _mul(self, node, current_klass): - return self.expr(node.left, current_klass) + " * " + self.expr(node.right, current_klass) - - def _mod(self, node, current_klass): - if isinstance(node.left, ast.Const) and isinstance(node.left.value, StringType): - self.imported_js.add("sprintf.js") # Include the sprintf functionality if it is used - return "sprintf("+self.expr(node.left, current_klass) + ", " + self.expr(node.right, current_klass)+")" - return self.expr(node.left, current_klass) + " % " + self.expr(node.right, current_klass) - - def _invert(self, node, current_klass): - return "~" + self.expr(node.expr, current_klass) - - def _bitand(self, node, current_klass): - return " & ".join([self.expr(child, current_klass) for child in node.nodes]) - - def _bitshiftleft(self, node, current_klass): - return self.expr(node.left, current_klass) + " << " + self.expr(node.right, current_klass) - - def _bitshiftright(self, node, current_klass): - return self.expr(node.left, current_klass) + " >>> " + self.expr(node.right, current_klass) - - def _bitxor(self,node, current_klass): - return " ^ ".join([self.expr(child, current_klass) for child in node.nodes]) - - def _bitor(self, node, current_klass): - return " | ".join([self.expr(child, current_klass) for child in node.nodes]) - - def _subscript(self, node, current_klass): - if node.flags == "OP_APPLY": - if len(node.subs) == 1: - return self.expr(node.expr, current_klass) + ".__getitem__(" + self.expr(node.subs[0], current_klass) + ")" - else: - raise TranslationError("must have one sub (in _subscript)", node) - else: - raise TranslationError("unsupported flag (in _subscript)", node) - - def _subscript_stmt(self, node, current_klass): - if node.flags == "OP_DELETE": - print >>self.output, " " + self.expr(node.expr, current_klass) + ".__delitem__(" + self.expr(node.subs[0], current_klass) + ");" - else: - raise TranslationError("unsupported flag (in _subscript)", node) - - def _list(self, node, current_klass): - return "new pyjslib.List([" + ", ".join([self.expr(x, current_klass) for x in node.nodes]) + "])" - - def _dict(self, node, current_klass): - items = [] - for x in node.items: - key = self.expr(x[0], current_klass) - value = self.expr(x[1], current_klass) - items.append("[" + key + ", " + value + "]") - return "new pyjslib.Dict([" + ", ".join(items) + "])" - - def _tuple(self, node, current_klass): - return "new pyjslib.Tuple([" + ", ".join([self.expr(x, current_klass) for x in node.nodes]) + "])" - - def _lambda(self, node, current_klass): - if node.varargs: - raise TranslationError("varargs are not supported in Lambdas", node) - if node.kwargs: - raise TranslationError("kwargs are not supported in Lambdas", node) - res = cStringIO.StringIO() - arg_names = list(node.argnames) - function_args = ", ".join(arg_names) - for child in node.getChildNodes(): - expr = self.expr(child, None) - print >> res, "function (%s){" % function_args - self._default_args_handler(node, arg_names, None, - output=res) - print >> res, 'return %s;}' % expr - return res.getvalue() - - def _slice(self, node, current_klass): - if node.flags == "OP_APPLY": - lower = "null" - upper = "null" - if node.lower != None: - lower = self.expr(node.lower, current_klass) - if node.upper != None: - upper = self.expr(node.upper, current_klass) - return "pyjslib.slice(" + self.expr(node.expr, current_klass) + ", " + lower + ", " + upper + ")" - else: - raise TranslationError("unsupported flag (in _slice)", node) - - def _global(self, node, current_klass): - for name in node.names: - self.method_imported_globals.add(name) - - def expr(self, node, current_klass): - if isinstance(node, ast.Const): - return self._const(node) - # @@@ not sure if the parentheses should be here or in individual operator functions - JKT - elif isinstance(node, ast.Mul): - return " ( " + self._mul(node, current_klass) + " ) " - elif isinstance(node, ast.Add): - return " ( " + self._add(node, current_klass) + " ) " - elif isinstance(node, ast.Sub): - return " ( " + self._sub(node, current_klass) + " ) " - elif isinstance(node, ast.Div): - return " ( " + self._div(node, current_klass) + " ) " - elif isinstance(node, ast.Mod): - return self._mod(node, current_klass) - elif isinstance(node, ast.UnaryAdd): - return self._unaryadd(node, current_klass) - elif isinstance(node, ast.UnarySub): - return self._unarysub(node, current_klass) - elif isinstance(node, ast.Not): - return self._not(node, current_klass) - elif isinstance(node, ast.Or): - return self._or(node, current_klass) - elif isinstance(node, ast.And): - return self._and(node, current_klass) - elif isinstance(node, ast.Invert): - return self._invert(node, current_klass) - elif isinstance(node, ast.Bitand): - return "("+self._bitand(node, current_klass)+")" - elif isinstance(node,ast.LeftShift): - return self._bitshiftleft(node, current_klass) - elif isinstance(node, ast.RightShift): - return self._bitshiftright(node, current_klass) - elif isinstance(node, ast.Bitxor): - return "("+self._bitxor(node, current_klass)+")" - elif isinstance(node, ast.Bitor): - return "("+self._bitor(node, current_klass)+")" - elif isinstance(node, ast.Compare): - return self._compare(node, current_klass) - elif isinstance(node, ast.CallFunc): - return self._callfunc(node, current_klass) - elif isinstance(node, ast.Name): - return self._name(node, current_klass) - elif isinstance(node, ast.Subscript): - return self._subscript(node, current_klass) - elif isinstance(node, ast.Getattr): - return self._getattr(node, current_klass) - elif isinstance(node, ast.List): - return self._list(node, current_klass) - elif isinstance(node, ast.Dict): - return self._dict(node, current_klass) - elif isinstance(node, ast.Tuple): - return self._tuple(node, current_klass) - elif isinstance(node, ast.Slice): - return self._slice(node, current_klass) - elif isinstance(node, ast.Lambda): - return self._lambda(node, current_klass) - else: - raise TranslationError("unsupported type (in expr)", node) - - - -import cStringIO - -def translate(file_name, module_name, debug=False): - f = file(file_name, "r") - src = f.read() - f.close() - output = cStringIO.StringIO() - mod = compiler.parseFile(file_name) - t = Translator(module_name, module_name, module_name, src, debug, mod, output) - return output.getvalue() - - -class PlatformParser: - def __init__(self, platform_dir = "", verbose=True): - self.platform_dir = platform_dir - self.parse_cache = {} - self.platform = "" - self.verbose = verbose - - def setPlatform(self, platform): - self.platform = platform - - def parseModule(self, module_name, file_name): - - importing = False - if not self.parse_cache.has_key(file_name): - importing = True - mod = compiler.parseFile(file_name) - self.parse_cache[file_name] = mod - else: - mod = self.parse_cache[file_name] - - override = False - platform_file_name = self.generatePlatformFilename(file_name) - if self.platform and os.path.isfile(platform_file_name): - mod = copy.deepcopy(mod) - mod_override = compiler.parseFile(platform_file_name) - self.merge(mod, mod_override) - override = True - - if self.verbose: - if override: - print "Importing %s (Platform %s)" % (module_name, self.platform) - elif importing: - print "Importing %s" % (module_name) - - return mod, override - - def generatePlatformFilename(self, file_name): - (module_name, extension) = os.path.splitext(os.path.basename(file_name)) - platform_file_name = module_name + self.platform + extension - - return os.path.join(os.path.dirname(file_name), self.platform_dir, platform_file_name) - - def merge(self, tree1, tree2): - for child in tree2.node: - if isinstance(child, ast.Function): - self.replaceFunction(tree1, child.name, child) - elif isinstance(child, ast.Class): - self.replaceClassMethods(tree1, child.name, child) - - return tree1 - - def replaceFunction(self, tree, function_name, function_node): - # find function to replace - for child in tree.node: - if isinstance(child, ast.Function) and child.name == function_name: - self.copyFunction(child, function_node) - return - raise TranslationError("function not found: " + function_name, function_node) - - def replaceClassMethods(self, tree, class_name, class_node): - # find class to replace - old_class_node = None - for child in tree.node: - if isinstance(child, ast.Class) and child.name == class_name: - old_class_node = child - break - - if not old_class_node: - raise TranslationError("class not found: " + class_name, class_node) - - # replace methods - for function_node in class_node.code: - if isinstance(function_node, ast.Function): - found = False - for child in old_class_node.code: - if isinstance(child, ast.Function) and child.name == function_node.name: - found = True - self.copyFunction(child, function_node) - break - - if not found: - raise TranslationError("class method not found: " + class_name + "." + function_node.name, function_node) - - def copyFunction(self, target, source): - target.code = source.code - target.argnames = source.argnames - target.defaults = source.defaults - target.doc = source.doc # @@@ not sure we need to do this any more - -def dotreplace(fname): - path, ext = os.path.splitext(fname) - return path.replace(".", "/") + ext - -class AppTranslator: - - def __init__(self, library_dirs=[], parser=None, dynamic=False, - optimize=False, verbose=True): - self.extension = ".py" - self.optimize = optimize - self.library_modules = [] - self.overrides = {} - self.library_dirs = path + library_dirs - self.dynamic = dynamic - self.verbose = verbose - - if not parser: - self.parser = PlatformParser() - else: - self.parser = parser - - self.parser.dynamic = dynamic - - def findFile(self, file_name): - if os.path.isfile(file_name): - return file_name - - for library_dir in self.library_dirs: - file_name = dotreplace(file_name) - full_file_name = os.path.join( - os.path.abspath(os.path.dirname(__file__)), library_dir, file_name) - if os.path.isfile(full_file_name): - return full_file_name - - fnameinit, ext = os.path.splitext(file_name) - fnameinit = fnameinit + "/__init__.py" - - full_file_name = os.path.join( - os.path.abspath(os.path.dirname(__file__)), library_dir, fnameinit) - if os.path.isfile(full_file_name): - return full_file_name - - raise Exception("file not found: " + file_name) - - def _translate(self, module_name, is_app=True, debug=False, - imported_js=set()): - if module_name not in self.library_modules: - self.library_modules.append(module_name) - - file_name = self.findFile(module_name + self.extension) - - output = cStringIO.StringIO() - - f = file(file_name, "r") - src = f.read() - f.close() - - mod, override = self.parser.parseModule(module_name, file_name) - if override: - override_name = "%s.%s" % (self.parser.platform.lower(), - module_name) - self.overrides[override_name] = override_name - if is_app: - mn = '__main__' - else: - mn = module_name - t = Translator(mn, module_name, module_name, - src, debug, mod, output, self.dynamic, self.optimize, - self.findFile) - - module_str = output.getvalue() - imported_js.update(set(t.imported_js)) - imported_modules_str = "" - for module in t.imported_modules: - if module not in self.library_modules: - self.library_modules.append(module) - #imported_js.update(set(t.imported_js)) - #imported_modules_str += self._translate( - # module, False, debug=debug, imported_js=imported_js) - - return imported_modules_str + module_str - - - def translate(self, module_name, is_app=True, debug=False, - library_modules=[]): - app_code = cStringIO.StringIO() - lib_code = cStringIO.StringIO() - imported_js = set() - self.library_modules = [] - self.overrides = {} - for library in library_modules: - if library.endswith(".js"): - imported_js.add(library) - continue - self.library_modules.append(library) - if self.verbose: - print 'Including LIB', library - print >> lib_code, '\n//\n// BEGIN LIB '+library+'\n//\n' - print >> lib_code, self._translate( - library, False, debug=debug, imported_js=imported_js) - - print >> lib_code, "/* initialize static library */" - print >> lib_code, "%s%s();\n" % (UU, library) - - print >> lib_code, '\n//\n// END LIB '+library+'\n//\n' - if module_name: - print >> app_code, self._translate( - module_name, is_app, debug=debug, imported_js=imported_js) - for js in imported_js: - path = self.findFile(js) - if os.path.isfile(path): - if self.verbose: - print 'Including JS', js - print >> lib_code, '\n//\n// BEGIN JS '+js+'\n//\n' - print >> lib_code, file(path).read() - print >> lib_code, '\n//\n// END JS '+js+'\n//\n' - else: - print >>sys.stderr, 'Warning: Unable to find imported javascript:', js - return lib_code.getvalue(), app_code.getvalue() - -usage = """ - usage: %s file_name [module_name] -""" - -def main(): - import sys - if len(sys.argv)<2: - print >> sys.stderr, usage % sys.argv[0] - sys.exit(1) - file_name = os.path.abspath(sys.argv[1]) - if not os.path.isfile(file_name): - print >> sys.stderr, "File not found %s" % file_name - sys.exit(1) - if len(sys.argv) > 2: - module_name = sys.argv[2] - else: - module_name = None - print translate(file_name, module_name), - -if __name__ == "__main__": - main() - diff -r 3edd2f19bce2 -r e0424e96e3fd py_ext/modules/svgui/svgui.py --- a/py_ext/modules/svgui/svgui.py Wed May 09 00:39:54 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,112 +0,0 @@ -import wx -import os, sys, shutil - -from ConfigTreeNode import opjimg -from py_ext import PythonCodeTemplate - -from pyjs import translate - -from docutils import * - -class RootClass: - - ConfNodeMethods = [ - {"bitmap" : os.path.join("images","ImportSVG"), - "name" : _("Import SVG"), - "tooltip" : _("Import SVG"), - "method" : "_ImportSVG"}, - {"bitmap" : os.path.join("images","ImportSVG"), - "name" : _("Inkscape"), - "tooltip" : _("Create HMI"), - "method" : "_StartInkscape"}, - ] - - def ConfNodePath(self): - return os.path.join(self.CTNParent.ConfNodePath(), "modules", self.CTNType) - - def _getSVGpath(self): - # define name for IEC raw code file - return os.path.join(self.CTNPath(), "gui.svg") - - def _getSVGUIserverpath(self): - return os.path.join(os.path.dirname(__file__), "svgui_server.py") - - def CTNGenerate_C(self, buildpath, locations): - """ - Return C code generated by iec2c compiler - when _generate_softPLC have been called - @param locations: ignored - @return: [(C_file_name, CFLAGS),...] , LDFLAGS_TO_APPEND - """ - - current_location = self.GetCurrentLocation() - # define a unique name for the generated C file - location_str = "_".join(map(lambda x:str(x), current_location)) - - res = ([], "", False) - - svgfile=self._getSVGpath() - if os.path.exists(svgfile): - res += (("gui.svg", file(svgfile,"rb")),) - - svguiserverfile = open(self._getSVGUIserverpath(), 'r') - svguiservercode = svguiserverfile.read() - svguiserverfile.close() - - svguilibpath = os.path.join(self._getBuildPath(), "svguilib.js") - svguilibfile = open(svguilibpath, 'w') - svguilibfile.write(translate(os.path.join(os.path.dirname(__file__), "pyjs", "lib", "sys.py"), "sys")) - svguilibfile.write(open(os.path.join(os.path.dirname(__file__), "pyjs", "lib", "_pyjs.js"), 'r').read()) - svguilibfile.write(translate(os.path.join(os.path.dirname(__file__), "pyjs", "lib", "pyjslib.py"), "pyjslib")) - svguilibfile.write(translate(os.path.join(os.path.dirname(__file__), "svguilib.py"), "svguilib")) - svguilibfile.write("pyjslib();\nsvguilib();\n") - svguilibfile.write(open(os.path.join(os.path.dirname(__file__), "pyjs", "lib", "json.js"), 'r').read()) - svguilibfile.write(open(os.path.join(os.path.dirname(__file__), "livesvg.js"), 'r').read()) - svguilibfile.close() - jsmodules = {"LiveSVGPage": "svguilib.js"} - res += (("svguilib.js", file(svguilibpath,"rb")),) - - runtimefile_path = os.path.join(buildpath, "runtime_%s.py"%location_str) - runtimefile = open(runtimefile_path, 'w') - runtimefile.write(svguiservercode % {"svgfile" : "gui.svg"}) - runtimefile.write(""" -def _runtime_%(location)s_begin(): - website.LoadHMI(%(svgui_class)s, %(jsmodules)s) - -def _runtime_%(location)s_cleanup(): - website.UnLoadHMI() - -""" % {"location": location_str, - "svgui_class": "SVGUI_HMI", - "jsmodules" : str(jsmodules), - }) - runtimefile.close() - - res += (("runtime_%s.py"%location_str, file(runtimefile_path,"rb")),) - - return res - - def _ImportSVG(self): - dialog = wx.FileDialog(self.GetCTRoot().AppFrame, _("Choose a SVG file"), os.getcwd(), "", _("SVG files (*.svg)|*.svg|All files|*.*"), wx.OPEN) - if dialog.ShowModal() == wx.ID_OK: - svgpath = dialog.GetPath() - if os.path.isfile(svgpath): - shutil.copy(svgpath, self._getSVGpath()) - else: - self.GetCTRoot().logger.write_error(_("No such SVG file: %s\n")%svgpath) - dialog.Destroy() - - def _StartInkscape(self): - svgfile = self._getSVGpath() - open_inkscape = True - if not self.GetCTRoot().CheckProjectPathPerm(): - dialog = wx.MessageDialog(self.GetCTRoot().AppFrame, - _("You don't have write permissions.\nOpen Inkscape anyway ?"), - _("Open Inkscape"), - wx.YES_NO|wx.ICON_QUESTION) - open_inkscape = dialog.ShowModal() == wx.ID_YES - dialog.Destroy() - if open_inkscape: - if not os.path.isfile(svgfile): - svgfile = None - open_svg(svgfile) diff -r 3edd2f19bce2 -r e0424e96e3fd py_ext/modules/svgui/svgui_server.py --- a/py_ext/modules/svgui/svgui_server.py Wed May 09 00:39:54 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,130 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -import os - -from nevow import rend, appserver, inevow, tags, loaders, athena -import simplejson as json - -svgfile = '%(svgfile)s' - -svguiWidgets = {} - -currentId = 0 -def getNewId(): - global currentId - currentId += 1 - return currentId - -class SvguiWidget: - - def __init__(self, classname, id, **kwargs): - self.classname = classname - self.id = id - self.attrs = kwargs.copy() - self.inputs = {} - self.outputs = {} - self.inhibit = False - self.changed = False - - def setinput(self, attrname, value): - self.inputs[attrname] = value - - def getinput(self, attrname, default=None): - if not self.inputs.has_key(attrname): - self.inputs[attrname] = default - return self.inputs[attrname] - - def setoutput(self, attrname, value): - if self.outputs.get(attrname) != value: - self.outputs[attrname] = value - self.changed = True - self.RefreshInterface() - - def updateoutputs(self, **kwargs): - for attrname, value in kwargs.iteritems(): - if self.outputs.get(attrname) != value: - self.outputs[attrname] = value - self.changed = True - self.RefreshInterface() - - def RefreshInterface(self): - interface = website.getHMI() - if isinstance(interface, SVGUI_HMI) and self.changed and not self.inhibit: - self.changed = False - d = interface.sendData(self) - if d is not None: - self.inhibit = True - d.addCallback(self.InterfaceRefreshed) - - def InterfaceRefreshed(self, result): - self.inhibit = False - if self.changed: - self.RefreshInterface() - -def get_object_init_state(obj): - # Convert objects to a dictionary of their representation - attrs = obj.attrs.copy() - attrs.update(obj.inputs) - d = { '__class__': obj.classname, - 'id': obj.id, - 'kwargs': json.dumps(attrs), - } - return d - -def get_object_current_state(obj): - # Convert objects to a dictionary of their representation - d = { '__class__': obj.classname, - 'id': obj.id, - 'kwargs': json.dumps(obj.outputs), - } - return d - -class SVGUI_HMI(website.PLCHMI): - jsClass = u"LiveSVGPage.LiveSVGWidget" - - docFactory = loaders.stan(tags.div(render=tags.directive('liveElement'))[ - tags.xml(loaders.xmlfile(os.path.join(WorkingDir, svgfile))), - ]) - - def HMIinitialisation(self): - gadgets = [] - for gadget in svguiWidgets.values(): - gadgets.append(unicode(json.dumps(gadget, default=get_object_init_state, indent=2), 'ascii')) - d = self.callRemote('init', gadgets) - d.addCallback(self.HMIinitialised) - - def sendData(self,data): - if self.initialised: - return self.callRemote('receiveData',unicode(json.dumps(data, default=get_object_current_state, indent=2), 'ascii')) - return None - - def setattr(self, id, attrname, value): - svguiWidgets[id].setinput(attrname, value) - -def createSVGUIControl(*args, **kwargs): - id = getNewId() - gad = SvguiWidget(args[0], id, **kwargs) - svguiWidgets[id] = gad - gadget = [unicode(json.dumps(gad, default=get_object_init_state, indent=2), 'ascii')] - interface = website.getHMI() - if isinstance(interface, SVGUI_HMI) and interface.initialised: - interface.callRemote('init', gadget) - return id - -def setAttr(id, attrname, value): - gad = svguiWidgets.get(id, None) - if gad is not None: - gad.setoutput(attrname, value) - -def updateAttr(id, **kwargs): - gad = svguiWidgets.get(id, None) - if gad is not None: - gad.updateoutput(**kwargs) - -def getAttr(id, attrname, default=None): - gad = svguiWidgets.get(id, None) - if gad is not None: - return gad.getinput(attrname, default) - return default - diff -r 3edd2f19bce2 -r e0424e96e3fd py_ext/modules/svgui/svguilib.py --- a/py_ext/modules/svgui/svguilib.py Wed May 09 00:39:54 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,117 +0,0 @@ - -class button: - - def __init__(self, parent, id, args): - self.parent = parent - self.id = id - self.back_elt = getSVGElementById(args.back_id) - self.sele_elt = getSVGElementById(args.sele_id) - self.toggle = args.toggle - self.active = args.active - if args.state != undefined: - self.state = args.state - else: - self.state = False - self.dragging = False - if self.toggle: - self.up = not self.state - else: - self.up = True - - # Add event on each element of the button - if self.active: - self.back_elt.addEventListener("mouseup", self, False) - self.back_elt.addEventListener("mousedown", self, False) - self.back_elt.addEventListener("mouseover", self, False) - self.back_elt.addEventListener("mouseout", self, False) - - self.sele_elt.addEventListener("mouseup", self, False) - self.sele_elt.addEventListener("mousedown", self, False) - self.sele_elt.addEventListener("mouseover", self, False) - self.sele_elt.addEventListener("mouseout", self, False) - - blockSVGElementDrag(self.back_elt) - blockSVGElementDrag(self.sele_elt) - - self.updateElements() - - # method to display the current state of interface - def updateElements(self): - if self.up: - self.sele_elt.setAttribute("display", "none") - self.back_elt.removeAttribute("display") - else: - self.sele_elt.removeAttribute("display") - self.back_elt.setAttribute("display", "none") - - def updateValues(self, values): - if values.state != self.state: - self.state = values.state - self.up = not self.state - updateAttr(self.id, 'state', self.state) - self.updateElements() - - def handleEvent(self, evt): - # Quand le bouton de la souris est presse - if evt.type == "mousedown": - evt.stopPropagation() - setCurrentObject(self) - - self.dragging = True - - if self.toggle: - self.up = self.state - else: - self.up = False - self.state = True - updateAttr(self.id, 'state', self.state) - self.updateElements() - - if isCurrentObject(self) and self.dragging: - # Quand le bouton est survole - if evt.type == "mouseover" and self.toggle: - self.up = self.state - self.updateElements() - - # Quand le curseur quitte la zone du bouton - elif evt.type == "mouseout" and self.toggle: - self.up = not self.state - self.updateElements() - - # Quand le bouton de la souris est relache - elif evt.type == "mouseup": - evt.stopPropagation() - if self.toggle and self.up == self.state: - self.state = not self.state - updateAttr(self.id, 'state', self.state) - elif not self.toggle: - self.up = True - self.state = False - updateAttr(self.id, 'state', self.state) - self.updateElements() - self.dragging = False - -class textControl: - - def __init__(self, parent, id, args): - self.parent = parent - self.id = id - self.back_elt = getSVGElementById(args.back_id) - if args.text != undefined: - self.text = args.text - else: - self.text = "" - self.updateElements() - - def updateValues(self, values): - if values.text != self.value: - self.text = values.text - updateAttr(self.id, 'text', self.text) - self.updateElements() - - def updateElements(self): - self.back_elt.firstChild.firstChild.textContent = self.text - - def handleEvent(self, evt): - pass - \ No newline at end of file diff -r 3edd2f19bce2 -r e0424e96e3fd py_ext/modules/wxglade_hmi/README --- a/py_ext/modules/wxglade_hmi/README Wed May 09 00:39:54 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -WxGlade HMI \ No newline at end of file diff -r 3edd2f19bce2 -r e0424e96e3fd py_ext/modules/wxglade_hmi/__init__.py --- a/py_ext/modules/wxglade_hmi/__init__.py Wed May 09 00:39:54 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -from wxglade_hmi import * diff -r 3edd2f19bce2 -r e0424e96e3fd py_ext/modules/wxglade_hmi/wxglade_hmi.py --- a/py_ext/modules/wxglade_hmi/wxglade_hmi.py Wed May 09 00:39:54 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,124 +0,0 @@ -import wx -import os, sys -from xml.dom import minidom - -from ConfigTreeNode import opjimg -from py_ext import PythonCodeTemplate - -class RootClass(PythonCodeTemplate): - - ConfNodeMethods = [ - {"bitmap" : opjimg("editWXGLADE"), - "name" : _("WXGLADE GUI"), - "tooltip" : _("Edit a WxWidgets GUI with WXGlade"), - "method" : "_editWXGLADE"}, - ] - - def _getWXGLADEpath(self): - # define name for IEC raw code file - return os.path.join(self.CTNPath(), "hmi.wxg") - - def launch_wxglade(self, options, wait=False): - from wxglade import __file__ as fileName - path = os.path.dirname(fileName) - glade = os.path.join(path, 'wxglade.py') - if wx.Platform == '__WXMSW__': - glade = "\"%s\""%glade - mode = {False:os.P_NOWAIT, True:os.P_WAIT}[wait] - os.spawnv(mode, sys.executable, ["\"%s\""%sys.executable] + [glade] + options) - - - def CTNGenerate_C(self, buildpath, locations): - """ - Return C code generated by iec2c compiler - when _generate_softPLC have been called - @param locations: ignored - @return: [(C_file_name, CFLAGS),...] , LDFLAGS_TO_APPEND - """ - - current_location = self.GetCurrentLocation() - # define a unique name for the generated C file - location_str = "_".join(map(lambda x:str(x), current_location)) - - runtimefile_path = os.path.join(buildpath, "runtime_%s.py"%location_str) - runtimefile = open(runtimefile_path, 'w') - - hmi_frames = {} - - wxgfile_path=self._getWXGLADEpath() - if os.path.exists(wxgfile_path): - wxgfile = open(wxgfile_path, 'r') - wxgtree = minidom.parse(wxgfile) - wxgfile.close() - - for node in wxgtree.childNodes[1].childNodes: - if node.nodeType == wxgtree.ELEMENT_NODE: - hmi_frames[node._attrs["name"].value] = node._attrs["class"].value - - hmipyfile_path=os.path.join(self._getBuildPath(), "hmi.py") - if wx.Platform == '__WXMSW__': - wxgfile_path = "\"%s\""%wxgfile_path - wxghmipyfile_path = "\"%s\""%hmipyfile_path - else: - wxghmipyfile_path = hmipyfile_path - self.launch_wxglade(['-o', wxghmipyfile_path, '-g', 'python', wxgfile_path], wait=True) - - hmipyfile = open(hmipyfile_path, 'r') - runtimefile.write(hmipyfile.read()) - hmipyfile.close() - - runtimefile.write(self.GetPythonCode()) - runtimefile.write(""" -%(declare)s - -def _runtime_%(location)s_begin(): - global %(global)s - - def OnCloseFrame(evt): - wx.MessageBox(_("Please stop PLC to close")) - - %(init)s - -def _runtime_%(location)s_cleanup(): - global %(global)s - - %(cleanup)s - -""" % {"location": location_str, - "declare": "\n".join(map(lambda x:"%s = None" % x, hmi_frames.keys())), - "global": ",".join(hmi_frames.keys()), - "init": "\n".join(map(lambda x: """ - %(name)s = %(class)s(None) - %(name)s.Bind(wx.EVT_CLOSE, OnCloseFrame) - %(name)s.Show() -""" % {"name": x[0], "class": x[1]}, - hmi_frames.items())), - "cleanup": "\n ".join(map(lambda x:"%s.Destroy()" % x, hmi_frames.keys()))}) - runtimefile.close() - - return [], "", False, ("runtime_%s.py"%location_str, file(runtimefile_path,"rb")) - - def _editWXGLADE(self): - wxg_filename = self._getWXGLADEpath() - open_wxglade = True - if not self.GetCTRoot().CheckProjectPathPerm(): - dialog = wx.MessageDialog(self.GetCTRoot().AppFrame, - _("You don't have write permissions.\nOpen wxGlade anyway ?"), - _("Open wxGlade"), - wx.YES_NO|wx.ICON_QUESTION) - open_wxglade = dialog.ShowModal() == wx.ID_YES - dialog.Destroy() - if open_wxglade: - if not os.path.exists(wxg_filename): - hmi_name = self.BaseParams.getName() - open(wxg_filename,"w").write(""" - - - - frame_1 - - - """ % {"name": hmi_name, "class": "Class_%s" % hmi_name}) - if wx.Platform == '__WXMSW__': - wxg_filename = "\"%s\""%wxg_filename - self.launch_wxglade([wxg_filename]) diff -r 3edd2f19bce2 -r e0424e96e3fd py_ext/plc_python.c --- a/py_ext/plc_python.c Wed May 09 00:39:54 2012 +0200 +++ b/py_ext/plc_python.c Sat May 12 11:21:10 2012 +0200 @@ -43,7 +43,7 @@ void UnLockPython(void); void LockPython(void); -int __init_%(location)s() +int __init_py_ext() { int i; /* Initialize cursors */ @@ -55,13 +55,13 @@ return 0; } -void __cleanup_%(location)s() +void __cleanup_py_ext() { PythonState = PYTHON_FINISHED; UnBlockPythonCommands(); } -void __retrieve_%(location)s() +void __retrieve_py_ext() { /* Check Python thread is not being * modifying internal python_eval data */ @@ -72,7 +72,7 @@ * and python_eval will no do anything */ } -void __publish_%(location)s() +void __publish_py_ext() { if(PythonState & PYTHON_LOCKED_BY_PLC){ /* If runnig PLC did push something in the fifo*/ diff -r 3edd2f19bce2 -r e0424e96e3fd py_ext/py_ext.py --- a/py_ext/py_ext.py Wed May 09 00:39:54 2012 +0200 +++ b/py_ext/py_ext.py Sat May 12 11:21:10 2012 +0200 @@ -1,185 +1,46 @@ -import wx import os -import modules -from ConfigTreeNode import ConfigTreeNode, opjimg -from PLCControler import UndoBuffer -from PythonEditor import PythonEditor +from POULibrary import POULibrary +from PythonFileCTNMixin import PythonFileCTNMixin -from xml.dom import minidom -from xmlclass import * -import cPickle +class PythonLibrary(POULibrary): + def GetName(self): + return "Python" -PythonClasses = GenerateClassesFromXSD(os.path.join(os.path.dirname(__file__), "py_ext_xsd.xsd")) + def GetLibraryPath(self): + return os.path.join(os.path.split(__file__)[0], "pous.xml") -class PythonCodeTemplate: - - EditorType = PythonEditor - - def __init__(self): - - self.ConfNodeMethods.insert(0, - {"bitmap" : opjimg("editPYTHONcode"), - "name" : _("Edit Python File"), - "tooltip" : _("Edit Python File"), - "method" : "_OpenView"}, - ) - - filepath = self.PythonFileName() - - self.PythonCode = PythonClasses["Python"]() - if os.path.isfile(filepath): - xmlfile = open(filepath, 'r') - tree = minidom.parse(xmlfile) - xmlfile.close() - - for child in tree.childNodes: - if child.nodeType == tree.ELEMENT_NODE and child.nodeName == "Python": - self.PythonCode.loadXMLTree(child, ["xmlns", "xmlns:xsi", "xsi:schemaLocation"]) - self.CreatePythonBuffer(True) - else: - self.CreatePythonBuffer(False) - self.OnCTNSave() - - def ConfNodePath(self): - return os.path.join(self.CTNParent.ConfNodePath(), "modules", self.CTNType) - - def PythonFileName(self): - return os.path.join(self.CTNPath(), "py_ext.xml") - - def GetFilename(self): - if self.PythonBuffer.IsCurrentSaved(): - return "py_ext" - else: - return "~py_ext~" - - def SetPythonCode(self, text): - self.PythonCode.settext(text) - - def GetPythonCode(self): - return self.PythonCode.gettext() - - def CTNTestModified(self): - return self.ChangesToSave or not self.PythonIsSaved() - - def OnCTNSave(self): - filepath = self.PythonFileName() - - text = "\n" - extras = {"xmlns":"http://www.w3.org/2001/XMLSchema", - "xmlns:xsi":"http://www.w3.org/2001/XMLSchema-instance", - "xsi:schemaLocation" : "py_ext_xsd.xsd"} - text += self.PythonCode.generateXMLText("Python", 0, extras) - - xmlfile = open(filepath,"w") - xmlfile.write(text.encode("utf-8")) - xmlfile.close() - - self.MarkPythonAsSaved() - return True - -#------------------------------------------------------------------------------- -# Current Buffering Management Functions -#------------------------------------------------------------------------------- - - """ - Return a copy of the project - """ - def Copy(self, model): - return cPickle.loads(cPickle.dumps(model)) - - def CreatePythonBuffer(self, saved): - self.Buffering = False - self.PythonBuffer = UndoBuffer(cPickle.dumps(self.PythonCode), saved) - - def BufferPython(self): - self.PythonBuffer.Buffering(cPickle.dumps(self.PythonCode)) - - def StartBuffering(self): - self.Buffering = True - - def EndBuffering(self): - if self.Buffering: - self.PythonBuffer.Buffering(cPickle.dumps(self.PythonCode)) - self.Buffering = False - - def MarkPythonAsSaved(self): - self.EndBuffering() - self.PythonBuffer.CurrentSaved() - - def PythonIsSaved(self): - return self.PythonBuffer.IsCurrentSaved() and not self.Buffering - - def LoadPrevious(self): - self.EndBuffering() - self.PythonCode = cPickle.loads(self.PythonBuffer.Previous()) - - def LoadNext(self): - self.PythonCode = cPickle.loads(self.PythonBuffer.Next()) - - def GetBufferState(self): - first = self.PythonBuffer.IsFirst() and not self.Buffering - last = self.PythonBuffer.IsLast() - return not first, not last - -def _GetClassFunction(name): - def GetRootClass(): - __import__("py_ext.modules." + name) - return getattr(modules, name).RootClass - return GetRootClass - -class RootClass(PythonCodeTemplate): - - # For root object, available Children Types are modules of the modules packages. - CTNChildrenTypes = [(name, _GetClassFunction(name), help) for name, help in zip(modules.__all__,modules.helps)] - - def ConfNodePath(self): - return os.path.join(self.CTNParent.ConfNodePath(), self.CTNType) - - def CTNGenerate_C(self, buildpath, locations): - """ - Generate C code - @param current_location: Tupple containing confnode IEC location : %I0.0.4.5 => (0,0,4,5) - @param locations: List of complete variables locations \ - [{"IEC_TYPE" : the IEC type (i.e. "INT", "STRING", ...) - "NAME" : name of the variable (generally "__IW0_1_2" style) - "DIR" : direction "Q","I" or "M" - "SIZE" : size "X", "B", "W", "D", "L" - "LOC" : tuple of interger for IEC location (0,1,2,...) - }, ...] - @return: [(C_file_name, CFLAGS),...] , LDFLAGS_TO_APPEND - """ - current_location = self.GetCurrentLocation() - # define a unique name for the generated C file - location_str = "_".join(map(lambda x:str(x), current_location)) - - ctr = self.GetCTRoot() - ctr.GetIECProgramsAndVariables() + def Generate_C(self, buildpath, varlist, IECCFLAGS): plc_python_filepath = os.path.join(os.path.split(__file__)[0], "plc_python.c") plc_python_file = open(plc_python_filepath, 'r') plc_python_code = plc_python_file.read() plc_python_file.close() python_eval_fb_list = [] - for v in ctr._VariablesList: + for v in varlist: if v["vartype"] == "FB" and v["type"] in ["PYTHON_EVAL","PYTHON_POLL"]: python_eval_fb_list.append(v) python_eval_fb_count = max(1, len(python_eval_fb_list)) # prepare python code - plc_python_code = plc_python_code % { - "python_eval_fb_count": python_eval_fb_count, - "location": location_str} + plc_python_code = plc_python_code % { "python_eval_fb_count": python_eval_fb_count } - Gen_Pythonfile_path = os.path.join(buildpath, "python_%s.c"%location_str) + Gen_Pythonfile_path = os.path.join(buildpath, "py_ext.c") pythonfile = open(Gen_Pythonfile_path,'w') pythonfile.write(plc_python_code) pythonfile.close() + return (["py_ext"], [(Gen_Pythonfile_path, IECCFLAGS)], True), "" + +class PythonFile(PythonFileCTNMixin): + def CTNGenerate_C(self, buildpath, locations): + current_location = self.GetCurrentLocation() + # define a unique name for the generated C file + location_str = "_".join(map(lambda x:str(x), current_location)) + runtimefile_path = os.path.join(buildpath, "runtime_%s.py"%location_str) runtimefile = open(runtimefile_path, 'w') runtimefile.write(self.GetPythonCode()) runtimefile.close() - matiec_flags = '"-I%s"'%os.path.abspath(self.GetCTRoot().GetIECLibPath()) - - return [(Gen_Pythonfile_path, matiec_flags)], "", True, ("runtime_%s.py"%location_str, file(runtimefile_path,"rb")) + return [], "", False, ("runtime_%s.py"%location_str, file(runtimefile_path,"rb")) + diff -r 3edd2f19bce2 -r e0424e96e3fd svgui/README --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/svgui/README Sat May 12 11:21:10 2012 +0200 @@ -0,0 +1,1 @@ +SVGUI HMI \ No newline at end of file diff -r 3edd2f19bce2 -r e0424e96e3fd svgui/__init__.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/svgui/__init__.py Sat May 12 11:21:10 2012 +0200 @@ -0,0 +1,1 @@ +from svgui import * diff -r 3edd2f19bce2 -r e0424e96e3fd svgui/livesvg.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/svgui/livesvg.js Sat May 12 11:21:10 2012 +0200 @@ -0,0 +1,59 @@ +// import Nevow.Athena +// import Divmod.Base + +function updateAttr(id, param, value) { + Nevow.Athena.Widget.fromAthenaID(1).callRemote('HMIexec', 'setattr', id, param, value); +} + +var svguiWidgets = new Array(); + +var currentObject = null; +function setCurrentObject(obj) { + currentObject = obj; +} +function isCurrentObject(obj) { + return currentObject == obj; +} + +function getSVGElementById(id) { + return document.getElementById(id); +} + +function blockSVGElementDrag(element) { + element.addEventListener("draggesture", function(event){event.stopPropagation()}, true); +} + +LiveSVGPage.LiveSVGWidget = Nevow.Athena.Widget.subclass('LiveSVGPage.LiveSVGWidget'); +LiveSVGPage.LiveSVGWidget.methods( + + function handleEvent(self, evt) { + if (currentObject != null) { + currentObject.handleEvent(evt); + } + }, + + function receiveData(self, data){ + dataReceived = json_parse(data); + gadget = svguiWidgets[dataReceived.id] + if (gadget) { + gadget.updateValues(json_parse(dataReceived.kwargs)); + } + //console.log("OBJET : " + dataReceived.back_id + " STATE : " + newState); + }, + + function init(self, arg1){ + //console.log("Object received : " + arg1); + for (ind in arg1) { + gad = json_parse(arg1[ind]); + args = json_parse(gad.kwargs); + gadget = new svguilib[gad.__class__](self, gad.id, args); + svguiWidgets[gadget.id]=gadget; + //console.log('GADGET :' + gadget); + } + var elements = document.getElementsByTagName("svg"); + for (var i = 0; i < elements.length; i++) { + elements[i].addEventListener("mouseup", self, false); + } + //console.log("SVGUIWIDGETS : " + svguiWidgets); + } +); diff -r 3edd2f19bce2 -r e0424e96e3fd svgui/pous.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/svgui/pous.xml Sat May 12 11:21:10 2012 +0200 @@ -0,0 +1,1428 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 'createSVGUIControl("textControl", back_id="' + + + + + + + back_id + + + + + + + '")' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + BOOL#1 + + + + + + + + + + + ID + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ID + + + + + + + set_text + + + + + + + 'setAttr(' + + + + + + + ',"text","' + + + + + + + '")' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 'createSVGUIControl("button",back_id="' + + + + + + + '",sele_id="' + + + + + + + ',active=True)' + + + + + + + BOOL#1 + + + + + + + back_id + + + + + + + sele_id + + + + + + + set_state + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ID + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + state_in + + + + + + + + + + + state_out + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ID + + + + + + + 'setAttr(' + + + + + + + ',"state",' + + + + + + + ')' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ID + + + + + + + 'int(getAttr(' + + + + + + + ',"state",False))' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + '",toggle=' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + toggle + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 'createSVGUIControl("button",back_id="' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + '",sele_id="' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ID + + + + + + + '",toggle=True,active=False)' + + + + + + + BOOL#1 + + + + + + + back_id + + + + + + + sele_id + + + + + + + 'setAttr(' + + + + + + + ',"state",' + + + + + + + ')' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ID + + + + + + + + + + + + + + + + + state_in + + + + + + + + + + diff -r 3edd2f19bce2 -r e0424e96e3fd svgui/pyjs/__init__.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/svgui/pyjs/__init__.py Sat May 12 11:21:10 2012 +0200 @@ -0,0 +1,2 @@ +from pyjs import * + diff -r 3edd2f19bce2 -r e0424e96e3fd svgui/pyjs/build.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/svgui/pyjs/build.py Sat May 12 11:21:10 2012 +0200 @@ -0,0 +1,724 @@ +#!/usr/bin/env python + +import sys +import os +import shutil +from copy import copy +from os.path import join, dirname, basename, abspath, split, isfile, isdir +from optparse import OptionParser +import pyjs +from cStringIO import StringIO +try: + # Python 2.5 and above + from hashlib import md5 +except: + import md5 +import re + +usage = """ + usage: %prog [options] + +This is the command line builder for the pyjamas project, which can +be used to build Ajax applications from Python. +For more information, see the website at http://pyjs.org/ +""" + +# GWT1.2 Impl | GWT1.2 Output | Pyjamas 0.2 Platform | Pyjamas 0.2 Output +# -------------+-----------------------+----------------------+---------------------- +# IE6 | ie6 | IE6 | ie6 +# Opera | opera | Opera | opera +# Safari | safari | Safari | safari +# -- | gecko1_8 | Mozilla | mozilla +# -- | gecko | OldMoz | oldmoz +# Standard | all | (default code) | all +# Mozilla | gecko1_8, gecko | -- | -- +# Old | safari, gecko, opera | -- | -- + +version = "%prog pyjamas version 2006-08-19" + +# these names in lowercase need match the strings +# returned by "provider$user.agent" in order to be selected corretly +app_platforms = ['IE6', 'Opera', 'OldMoz', 'Safari', 'Mozilla'] + +# usually defaults to e.g. /usr/share/pyjamas +_data_dir = os.path.join(pyjs.prefix, "share/pyjamas") + + +# .cache.html files produces look like this +CACHE_HTML_PAT=re.compile('^[a-z]*.[0-9a-f]{32}\.cache\.html$') + +# ok these are the three "default" library directories, containing +# the builtins (str, List, Dict, ord, round, len, range etc.) +# the main pyjamas libraries (pyjamas.ui, pyjamas.Window etc.) +# and the contributed addons + +for p in ["library/builtins", + "library", + "addons"]: + p = os.path.join(_data_dir, p) + if os.path.isdir(p): + pyjs.path.append(p) + + +def read_boilerplate(data_dir, filename): + return open(join(data_dir, "builder/boilerplate", filename)).read() + +def copy_boilerplate(data_dir, filename, output_dir): + filename = join(data_dir, "builder/boilerplate", filename) + shutil.copy(filename, output_dir) + + +# taken and modified from python2.4 +def copytree_exists(src, dst, symlinks=False): + if not os.path.exists(src): + return + + names = os.listdir(src) + try: + os.mkdir(dst) + except: + pass + + errors = [] + for name in names: + if name.startswith('CVS'): + continue + if name.startswith('.git'): + continue + if name.startswith('.svn'): + continue + + srcname = os.path.join(src, name) + dstname = os.path.join(dst, name) + try: + if symlinks and os.path.islink(srcname): + linkto = os.readlink(srcname) + os.symlink(linkto, dstname) + elif isdir(srcname): + copytree_exists(srcname, dstname, symlinks) + else: + shutil.copy2(srcname, dstname) + except (IOError, os.error), why: + errors.append((srcname, dstname, why)) + if errors: + print errors + +def check_html_file(source_file, dest_path): + """ Checks if a base HTML-file is available in the PyJamas + output directory. + If the HTML-file isn't available, it will be created. + + If a CSS-file with the same name is available + in the output directory, a reference to this CSS-file + is included. + + If no CSS-file is found, this function will look for a special + CSS-file in the output directory, with the name + "pyjamas_default.css", and if found it will be referenced + in the generated HTML-file. + + [thank you to stef mientki for contributing this function] + """ + + base_html = """\ + + + + + %(css)s + %(title)s + + + + + +""" + + filename = os.path.split ( source_file )[1] + mod_name = os.path.splitext ( filename )[0] + file_name = os.path.join ( dest_path, mod_name + '.html' ) + + # if html file in output directory exists, leave it alone. + if os.path.exists ( file_name ): + return 0 + + if os.path.exists ( + os.path.join ( dest_path, mod_name + '.css' ) ) : + css = "" + elif os.path.exists ( + os.path.join ( dest_path, 'pyjamas_default.css' ) ) : + css = "" + + else: + css = '' + + title = 'PyJamas Auto-Generated HTML file ' + mod_name + + base_html = base_html % {'modulename': mod_name, 'title': title, 'css': css} + + fh = open (file_name, 'w') + fh.write (base_html) + fh.close () + + return 1 + + +def build(app_name, output, js_includes=(), debug=False, dynamic=0, + data_dir=None, cache_buster=False, optimize=False): + + # make sure the output directory is always created in the current working + # directory or at the place given if it is an absolute path. + output = os.path.abspath(output) + msg = "Building '%(app_name)s' to output directory '%(output)s'" % locals() + if debug: + msg += " with debugging statements" + print msg + + # check the output directory + if os.path.exists(output) and not os.path.isdir(output): + print >>sys.stderr, "Output destination %s exists and is not a directory" % output + return + if not os.path.isdir(output): + try: + print "Creating output directory" + os.mkdir(output) + except StandardError, e: + print >>sys.stderr, "Exception creating output directory %s: %s" % (output, e) + + ## public dir + for p in pyjs.path: + pub_dir = join(p, 'public') + if isdir(pub_dir): + print "Copying: public directory of library %r" % p + copytree_exists(pub_dir, output) + + ## AppName.html - can be in current or public directory + html_input_filename = app_name + ".html" + html_output_filename = join(output, basename(html_input_filename)) + if os.path.isfile(html_input_filename): + if not os.path.isfile(html_output_filename) or \ + os.path.getmtime(html_input_filename) > \ + os.path.getmtime(html_output_filename): + try: + shutil.copy(html_input_filename, html_output_filename) + except: + print >>sys.stderr, "Warning: Missing module HTML file %s" % html_input_filename + + print "Copying: %(html_input_filename)s" % locals() + + if check_html_file(html_input_filename, output): + print >>sys.stderr, "Warning: Module HTML file %s has been auto-generated" % html_input_filename + + ## pygwt.js + + print "Copying: pygwt.js" + + pygwt_js_template = read_boilerplate(data_dir, "pygwt.js") + pygwt_js_output = open(join(output, "pygwt.js"), "w") + + print >>pygwt_js_output, pygwt_js_template + + pygwt_js_output.close() + + ## Images + + print "Copying: Images and History" + copy_boilerplate(data_dir, "corner_dialog_topleft_black.png", output) + copy_boilerplate(data_dir, "corner_dialog_topright_black.png", output) + copy_boilerplate(data_dir, "corner_dialog_bottomright_black.png", output) + copy_boilerplate(data_dir, "corner_dialog_bottomleft_black.png", output) + copy_boilerplate(data_dir, "corner_dialog_edge_black.png", output) + copy_boilerplate(data_dir, "corner_dialog_topleft.png", output) + copy_boilerplate(data_dir, "corner_dialog_topright.png", output) + copy_boilerplate(data_dir, "corner_dialog_bottomright.png", output) + copy_boilerplate(data_dir, "corner_dialog_bottomleft.png", output) + copy_boilerplate(data_dir, "corner_dialog_edge.png", output) + copy_boilerplate(data_dir, "tree_closed.gif", output) + copy_boilerplate(data_dir, "tree_open.gif", output) + copy_boilerplate(data_dir, "tree_white.gif", output) + copy_boilerplate(data_dir, "history.html", output) + + + ## all.cache.html + app_files = generateAppFiles(data_dir, js_includes, app_name, debug, + output, dynamic, cache_buster, optimize) + + ## AppName.nocache.html + + print "Creating: %(app_name)s.nocache.html" % locals() + + home_nocache_html_template = read_boilerplate(data_dir, "home.nocache.html") + home_nocache_html_output = open(join(output, app_name + ".nocache.html"), + "w") + + # the selector templ is added to the selectScript function + select_tmpl = """O(["true","%s"],"%s");""" + script_selectors = StringIO() + + for platform, file_prefix in app_files: + print >> script_selectors, select_tmpl % (platform, file_prefix) + + print >>home_nocache_html_output, home_nocache_html_template % dict( + app_name = app_name, + script_selectors = script_selectors.getvalue(), + ) + + home_nocache_html_output.close() + + print "Done. You can run your app by opening '%(html_output_filename)s' in a browser" % locals() + + +def generateAppFiles(data_dir, js_includes, app_name, debug, output, dynamic, + cache_buster, optimize): + + all_cache_html_template = read_boilerplate(data_dir, "all.cache.html") + mod_cache_html_template = read_boilerplate(data_dir, "mod.cache.html") + + # clean out the old ones first + for name in os.listdir(output): + if CACHE_HTML_PAT.match(name): + p = join(output, name) + print "Deleting existing app file %s" % p + os.unlink(p) + + app_files = [] + tmpl = read_boilerplate(data_dir, "all.cache.html") + parser = pyjs.PlatformParser("platform") + app_headers = '' + scripts = [''%script \ + for script in js_includes] + app_body = '\n'.join(scripts) + + mod_code = {} + mod_libs = {} + modules = {} + app_libs = {} + early_app_libs = {} + app_code = {} + overrides = {} + pover = {} + app_modnames = {} + mod_levels = {} + + # First, generate all the code. + # Second, (dynamic only), post-analyse the places where modules + # haven't changed + # Third, write everything out. + + for platform in app_platforms: + + mod_code[platform] = {} + mod_libs[platform] = {} + modules[platform] = [] + pover[platform] = {} + app_libs[platform] = '' + early_app_libs[platform] = '' + app_code[platform] = {} + app_modnames[platform] = {} + + # Application.Platform.cache.html + + parser.setPlatform(platform) + app_translator = pyjs.AppTranslator( + parser=parser, dynamic=dynamic, optimize=optimize) + early_app_libs[platform], appcode = \ + app_translator.translate(None, is_app=False, + debug=debug, + library_modules=['dynamicajax.js', + '_pyjs.js', 'sys', + 'pyjslib']) + pover[platform].update(app_translator.overrides.items()) + for mname, name in app_translator.overrides.items(): + pd = overrides.setdefault(mname, {}) + pd[platform] = name + + print appcode + #mod_code[platform][app_name] = appcode + + # platform.Module.cache.js + + modules_done = ['pyjslib', 'sys', '_pyjs.js'] + #modules_to_do = [app_name] + app_translator.library_modules + modules_to_do = [app_name] + app_translator.library_modules + + dependencies = {} + + deps = map(pyjs.strip_py, modules_to_do) + for d in deps: + sublist = add_subdeps(dependencies, d) + modules_to_do += sublist + deps = uniquify(deps) + #dependencies[app_name] = deps + + modules[platform] = modules_done + modules_to_do + + while modules_to_do: + + #print "modules to do", modules_to_do + + mn = modules_to_do.pop() + mod_name = pyjs.strip_py(mn) + + if mod_name in modules_done: + continue + + modules_done.append(mod_name) + + mod_cache_name = "%s.%s.cache.js" % (platform.lower(), mod_name) + + parser.setPlatform(platform) + mod_translator = pyjs.AppTranslator(parser=parser, optimize=optimize) + mod_libs[platform][mod_name], mod_code[platform][mod_name] = \ + mod_translator.translate(mod_name, + is_app=False, + debug=debug) + pover[platform].update(mod_translator.overrides.items()) + for mname, name in mod_translator.overrides.items(): + pd = overrides.setdefault(mname, {}) + pd[platform] = name + + mods = mod_translator.library_modules + modules_to_do += mods + modules[platform] += mods + + deps = map(pyjs.strip_py, mods) + sd = subdeps(mod_name) + if len(sd) > 1: + deps += sd[:-1] + while mod_name in deps: + deps.remove(mod_name) + + #print + #print + #print "modname preadd:", mod_name, deps + #print + #print + for d in deps: + sublist = add_subdeps(dependencies, d) + modules_to_do += sublist + modules_to_do += add_subdeps(dependencies, mod_name) + #print "modname:", mod_name, deps + deps = uniquify(deps) + #print "modname:", mod_name, deps + dependencies[mod_name] = deps + + # work out the dependency ordering of the modules + + mod_levels[platform] = make_deps(None, dependencies, modules_done) + + # now write everything out + + for platform in app_platforms: + + early_app_libs_ = early_app_libs[platform] + app_libs_ = app_libs[platform] + app_code_ = app_code[platform] + #modules_ = filter_mods(app_name, modules[platform]) + mods = flattenlist(mod_levels[platform]) + mods.reverse() + modules_ = filter_mods(None, mods) + + for mod_name in modules_: + + mod_code_ = mod_code[platform][mod_name] + + mod_name = pyjs.strip_py(mod_name) + + override_name = "%s.%s" % (platform.lower(), mod_name) + if pover[platform].has_key(override_name): + mod_cache_name = "%s.cache.js" % (override_name) + else: + mod_cache_name = "%s.cache.js" % (mod_name) + + print "Creating: " + mod_cache_name + + modlevels = make_deps(None, dependencies, dependencies[mod_name]) + + modnames = [] + + for md in modlevels: + mnames = map(lambda x: "'%s'" % x, md) + mnames = "new pyjslib.List([\n\t\t\t%s])" % ',\n\t\t\t'.join(mnames) + modnames.append(mnames) + + modnames.reverse() + modnames = "new pyjslib.List([\n\t\t%s\n\t])" % ',\n\t\t'.join(modnames) + + # convert the overrides + + overnames = map(lambda x: "'%s': '%s'" % x, pover[platform].items()) + overnames = "new pyjslib.Dict({\n\t\t%s\n\t})" % ',\n\t\t'.join(overnames) + + if dynamic: + mod_cache_html_output = open(join(output, mod_cache_name), "w") + else: + mod_cache_html_output = StringIO() + + print >>mod_cache_html_output, mod_cache_html_template % dict( + mod_name = mod_name, + app_name = app_name, + modnames = modnames, + overrides = overnames, + mod_libs = mod_libs[platform][mod_name], + dynamic = dynamic, + mod_code = mod_code_, + ) + + if dynamic: + mod_cache_html_output.close() + else: + mod_cache_html_output.seek(0) + app_libs_ += mod_cache_html_output.read() + + # write out the dependency ordering of the modules + + app_modnames = [] + + for md in mod_levels[platform]: + mnames = map(lambda x: "'%s'" % x, md) + mnames = "new pyjslib.List([\n\t\t\t%s])" % ',\n\t\t\t'.join(mnames) + app_modnames.append(mnames) + + app_modnames.reverse() + app_modnames = "new pyjslib.List([\n\t\t%s\n\t])" % ',\n\t\t'.join(app_modnames) + + # convert the overrides + + overnames = map(lambda x: "'%s': '%s'" % x, pover[platform].items()) + overnames = "new pyjslib.Dict({\n\t\t%s\n\t})" % ',\n\t\t'.join(overnames) + + #print "platform names", platform, overnames + #print pover + + # now write app.allcache including dependency-ordered list of + # library modules + + file_contents = all_cache_html_template % dict( + app_name = app_name, + early_app_libs = early_app_libs_, + app_libs = app_libs_, + app_code = app_code_, + app_body = app_body, + overrides = overnames, + platform = platform.lower(), + dynamic = dynamic, + app_modnames = app_modnames, + app_headers = app_headers + ) + if cache_buster: + digest = md5.new(file_contents).hexdigest() + file_name = "%s.%s.%s" % (platform.lower(), app_name, digest) + else: + file_name = "%s.%s" % (platform.lower(), app_name) + file_name += ".cache.html" + out_path = join(output, file_name) + out_file = open(out_path, 'w') + out_file.write(file_contents) + out_file.close() + app_files.append((platform.lower(), file_name)) + print "Created app file %s:%s: %s" % ( + app_name, platform, out_path) + + return app_files + +def flattenlist(ll): + res = [] + for l in ll: + res += l + return res + +# creates sub-dependencies e.g. pyjamas.ui.Widget +# creates pyjamas.ui.Widget, pyjamas.ui and pyjamas. +def subdeps(m): + d = [] + m = m.split(".") + for i in range(0, len(m)): + d.append('.'.join(m[:i+1])) + return d + +import time + +def add_subdeps(deps, mod_name): + sd = subdeps(mod_name) + if len(sd) == 1: + return [] + #print "subdeps", mod_name, sd + #print "deps", deps + res = [] + for i in range(0, len(sd)-1): + parent = sd[i] + child = sd[i+1] + l = deps.get(child, []) + l.append(parent) + deps[child] = l + if parent not in res: + res.append(parent) + #print deps + return res + +# makes unique and preserves list order +def uniquify(md): + res = [] + for m in md: + if m not in res: + res.append(m) + return res + +def filter_mods(app_name, md): + while 'sys' in md: + md.remove('sys') + while 'pyjslib' in md: + md.remove('pyjslib') + while app_name in md: + md.remove(app_name) + md = filter(lambda x: not x.endswith('.js'), md) + md = map(pyjs.strip_py, md) + + return uniquify(md) + +def filter_deps(app_name, deps): + + res = {} + for (k, l) in deps.items(): + mods = filter_mods(k, l) + while k in mods: + mods.remove(k) + res[k] = mods + return res + +def has_nodeps(mod, deps): + if not deps.has_key(mod) or not deps[mod]: + return True + return False + +def nodeps_list(mod_list, deps): + res = [] + for mod in mod_list: + if has_nodeps(mod, deps): + res.append(mod) + return res + +# this function takes a dictionary of dependent modules and +# creates a list of lists. the first list will be modules +# that have no dependencies; the second list will be those +# modules that have the first list as dependencies; the +# third will be those modules that have the first and second... +# etc. + + +def make_deps(app_name, deps, mod_list): + print "Calculating Dependencies ..." + mod_list = filter_mods(app_name, mod_list) + deps = filter_deps(app_name, deps) + + if not mod_list: + return [] + + #print mod_list + #print deps + + ordered_deps = [] + last_len = -1 + while deps: + l_deps = len(deps) + #print l_deps + if l_deps==last_len: + for m, dl in deps.items(): + for d in dl: + if m in deps.get(d, []): + raise Exception('Circular Imports found: \n%s %s -> %s %s' + % (m, dl, d, deps[d])) + #raise Exception('Could not calculate dependencies: \n%s' % deps) + break + last_len = l_deps + #print "modlist", mod_list + nodeps = nodeps_list(mod_list, deps) + #print "nodeps", nodeps + mod_list = filter(lambda x: x not in nodeps, mod_list) + newdeps = {} + for k in deps.keys(): + depslist = deps[k] + depslist = filter(lambda x: x not in nodeps, depslist) + if depslist: + newdeps[k] = depslist + #print "newdeps", newdeps + deps = newdeps + ordered_deps.append(nodeps) + #time.sleep(0) + + if mod_list: + ordered_deps.append(mod_list) # last dependencies - usually the app(s) + + ordered_deps.reverse() + + return ordered_deps + +def main(): + global app_platforms + + parser = OptionParser(usage = usage, version = version) + parser.add_option("-o", "--output", dest="output", + help="directory to which the webapp should be written") + parser.add_option("-j", "--include-js", dest="js_includes", action="append", + help="javascripts to load into the same frame as the rest of the script") + parser.add_option("-I", "--library_dir", dest="library_dirs", + action="append", help="additional paths appended to PYJSPATH") + parser.add_option("-D", "--data_dir", dest="data_dir", + help="path for data directory") + parser.add_option("-m", "--dynamic-modules", action="store_true", + dest="dynamic", default=False, + help="Split output into separate dynamically-loaded modules (experimental)") + parser.add_option("-P", "--platforms", dest="platforms", + help="platforms to build for, comma-separated") + parser.add_option("-d", "--debug", action="store_true", dest="debug") + parser.add_option("-O", "--optimize", action="store_true", + dest="optimize", default=False, + help="Optimize generated code (removes all print statements)", + ) + parser.add_option("-c", "--cache_buster", action="store_true", + dest="cache_buster", + help="Enable browser cache-busting (MD5 hash added to output filenames)") + + parser.set_defaults(output = "output", js_includes=[], library_dirs=[], + platforms=(','.join(app_platforms)), + data_dir=os.path.join(sys.prefix, "share/pyjamas"), + dynamic=False, + cache_buster=False, + debug=False) + (options, args) = parser.parse_args() + if len(args) != 1: + parser.error("incorrect number of arguments") + + data_dir = abspath(options.data_dir) + + app_path = args[0] + if app_path.endswith('.py'): + app_path = abspath(app_path) + if not isfile(app_path): + parser.error("Application file not found %r" % app_path) + app_path, app_name = split(app_path) + app_name = app_name[:-3] + pyjs.path.append(app_path) + elif os.path.sep in app_path: + parser.error("Not a valid module declaration %r" % app_path) + else: + app_name = app_path + + for d in options.library_dirs: + pyjs.path.append(abspath(d)) + + if options.platforms: + app_platforms = options.platforms.split(',') + + # this is mostly for getting boilerplate stuff + data_dir = os.path.abspath(options.data_dir) + + build(app_name, options.output, options.js_includes, + options.debug, options.dynamic and 1 or 0, data_dir, + options.cache_buster, options.optimize) + +if __name__ == "__main__": + main() + diff -r 3edd2f19bce2 -r e0424e96e3fd svgui/pyjs/jsonrpc/README.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/svgui/pyjs/jsonrpc/README.txt Sat May 12 11:21:10 2012 +0200 @@ -0,0 +1,12 @@ +These classes are intended for use server-side. + +e.g. in a django view.py : + + from pyjs.jsonrpc.django import JSONService, jsonremote + + jsonservice = JSONRPCService() + + @jsonremote(jsonservice) + def test(request, echo_param): + return "echoing the param back: %s" % echo_param + diff -r 3edd2f19bce2 -r e0424e96e3fd svgui/pyjs/jsonrpc/django/jsonrpc.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/svgui/pyjs/jsonrpc/django/jsonrpc.py Sat May 12 11:21:10 2012 +0200 @@ -0,0 +1,226 @@ +# jsonrpc.py +# original code: http://trac.pyworks.org/pyjamas/wiki/DjangoWithPyJamas +# also from: http://www.pimentech.fr/technologies/outils +from django.utils import simplejson +from django.http import HttpResponse +import sys + +from pyjs.jsonrpc import JSONRPCServiceBase +# JSONRPCService and jsonremote are used in combination to drastically +# simplify the provision of JSONRPC services. use as follows: +# +# jsonservice = JSONRPCService() +# +# @jsonremote(jsonservice) +# def test(request, echo_param): +# return "echoing the param back: %s" % echo_param +# +# dump jsonservice into urlpatterns: +# (r'^service1/$', 'djangoapp.views.jsonservice'), + +class JSONRPCService(JSONRPCServiceBase): + + def __call__(self, request, extra=None): + return self.process(request.raw_post_data) + +def jsonremote(service): + """Make JSONRPCService a decorator so that you can write : + + from jsonrpc import JSONRPCService + chatservice = JSONRPCService() + + @jsonremote(chatservice) + def login(request, user_name): + (...) + """ + def remotify(func): + if isinstance(service, JSONRPCService): + service.add_method(func.__name__, func) + else: + emsg = 'Service "%s" not found' % str(service.__name__) + raise NotImplementedError, emsg + return func + return remotify + + +# FormProcessor provides a mechanism for turning Django Forms into JSONRPC +# Services. If you have an existing Django app which makes prevalent +# use of Django Forms it will save you rewriting the app. +# use as follows. in djangoapp/views.py : +# +# class SimpleForm(forms.Form): +# testfield = forms.CharField(max_length=100) +# +# class SimpleForm2(forms.Form): +# testfield = forms.CharField(max_length=20) +# +# processor = FormProcessor({'processsimpleform': SimpleForm, +# 'processsimpleform2': SimpleForm2}) +# +# this will result in a JSONRPC service being created with two +# RPC functions. dump "processor" into urlpatterns to make it +# part of the app: +# (r'^formsservice/$', 'djangoapp.views.processor'), + +from django import forms + +def builderrors(form): + d = {} + for error in form.errors.keys(): + if error not in d: + d[error] = [] + for errorval in form.errors[error]: + d[error].append(unicode(errorval)) + return d + + +# contains the list of arguments in each field +field_names = { + 'CharField': ['max_length', 'min_length'], + 'IntegerField': ['max_value', 'min_value'], + 'FloatField': ['max_value', 'min_value'], + 'DecimalField': ['max_value', 'min_value', 'max_digits', 'decimal_places'], + 'DateField': ['input_formats'], + 'DateTimeField': ['input_formats'], + 'TimeField': ['input_formats'], + 'RegexField': ['max_length', 'min_length'], # sadly we can't get the expr + 'EmailField': ['max_length', 'min_length'], + 'URLField': ['max_length', 'min_length', 'verify_exists', 'user_agent'], + 'ChoiceField': ['choices'], + 'FilePathField': ['path', 'match', 'recursive', 'choices'], + 'IPAddressField': ['max_length', 'min_length'], + } + +def describe_field_errors(field): + res = {} + field_type = field.__class__.__name__ + msgs = {} + for n, m in field.error_messages.items(): + msgs[n] = unicode(m) + res['error_messages'] = msgs + if field_type in ['ComboField', 'MultiValueField', 'SplitDateTimeField']: + res['fields'] = map(describe_field, field.fields) + return res + +def describe_fields_errors(fields, field_names): + res = {} + if not field_names: + field_names = fields.keys() + for name in field_names: + field = fields[name] + res[name] = describe_field_errors(field) + return res + +def describe_field(field): + res = {} + field_type = field.__class__.__name__ + for fname in field_names.get(field_type, []) + \ + ['help_text', 'label', 'initial', 'required']: + res[fname] = getattr(field, fname) + if field_type in ['ComboField', 'MultiValueField', 'SplitDateTimeField']: + res['fields'] = map(describe_field, field.fields) + return res + +def describe_fields(fields, field_names): + res = {} + if not field_names: + field_names = fields.keys() + for name in field_names: + field = fields[name] + res[name] = describe_field(field) + return res + +class FormProcessor(JSONRPCService): + def __init__(self, forms, _formcls=None): + + if _formcls is None: + JSONRPCService.__init__(self) + for k in forms.keys(): + s = FormProcessor({}, forms[k]) + self.add_method(k, s.__process) + else: + JSONRPCService.__init__(self, forms) + self.formcls = _formcls + + def __process(self, request, params, command=None): + + f = self.formcls(params) + + if command is None: # just validate + if not f.is_valid(): + return {'success':False, 'errors': builderrors(f)} + return {'success':True} + + elif command.has_key('describe_errors'): + field_names = command['describe_errors'] + return describe_fields_errors(f.fields, field_names) + + elif command.has_key('describe'): + field_names = command['describe'] + return describe_fields(f.fields, field_names) + + elif command.has_key('save'): + if not f.is_valid(): + return {'success':False, 'errors': builderrors(f)} + instance = f.save() # XXX: if you want more, over-ride save. + return {'success': True, 'instance': json_convert(instance) } + + elif command.has_key('html'): + return {'success': True, 'html': f.as_table()} + + return "unrecognised command" + + + + +# The following is incredibly convenient for saving vast amounts of +# coding, avoiding doing silly things like this: +# jsonresult = {'field1': djangoobject.field1, +# 'field2': djangoobject.date.strftime('%Y.%M'), +# ..... } +# +# The date/time flatten function is there because JSONRPC doesn't +# support date/time objects or formats, so conversion to a string +# is the most logical choice. pyjamas, being python, can easily +# be used to parse the string result at the other end. +# +# use as follows: +# +# jsonservice = JSONRPCService() +# +# @jsonremote(jsonservice) +# def list_some_model(request, start=0, count=10): +# l = SomeDjangoModelClass.objects.filter() +# res = json_convert(l[start:end]) +# +# @jsonremote(jsonservice) +# def list_another_model(request, start=0, count=10): +# l = AnotherDjangoModelClass.objects.filter() +# res = json_convert(l[start:end]) +# +# dump jsonservice into urlpatterns to make the two RPC functions, +# list_some_model and list_another_model part of the django app: +# (r'^service1/$', 'djangoapp.views.jsonservice'), + +from django.core.serializers import serialize +import datetime +from datetime import date + +def dict_datetimeflatten(item): + d = {} + for k, v in item.items(): + k = str(k) + if isinstance(v, datetime.date): + d[k] = str(v) + elif isinstance(v, dict): + d[k] = dict_datetimeflatten(v) + else: + d[k] = v + return d + +def json_convert(l, fields=None): + res = [] + for item in serialize('python', l, fields=fields): + res.append(dict_datetimeflatten(item)) + return res + diff -r 3edd2f19bce2 -r e0424e96e3fd svgui/pyjs/jsonrpc/jsonrpc.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/svgui/pyjs/jsonrpc/jsonrpc.py Sat May 12 11:21:10 2012 +0200 @@ -0,0 +1,43 @@ +import gluon.contrib.simplejson as simplejson +import types +import sys + +class JSONRPCServiceBase: + + def __init__(self): + self.methods={} + + def response(self, id, result): + return simplejson.dumps({'version': '1.1', 'id':id, + 'result':result, 'error':None}) + def error(self, id, code, message): + return simplejson.dumps({'id': id, + 'version': '1.1', + 'error': {'name': 'JSONRPCError', + 'code': code, + 'message': message + } + }) + + def add_method(self, name, method): + self.methods[name] = method + + def process(self, data): + data = simplejson.loads(data) + id, method, params = data["id"], data["method"], data["params"] + if method in self.methods: + try: + result =self.methods[method](*params) + return self.response(id, result) + except BaseException: + etype, eval, etb = sys.exc_info() + return self.error(id, 100, '%s: %s' %(etype.__name__, eval)) + except: + etype, eval, etb = sys.exc_info() + return self.error(id, 100, 'Exception %s: %s' %(etype, eval)) + else: + return self.error(id, 100, 'method "%s" does not exist' % method) + + def listmethods(self): + return self.methods.keys() + diff -r 3edd2f19bce2 -r e0424e96e3fd svgui/pyjs/jsonrpc/web2py/jsonrpc.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/svgui/pyjs/jsonrpc/web2py/jsonrpc.py Sat May 12 11:21:10 2012 +0200 @@ -0,0 +1,11 @@ +from pyjs.jsonrpc import JSONRPCServiceBase + +class JSONRPCService(JSONRPCServiceBase): + + def serve(self): + return self.process(request.body.read()) + + def __call__(self,func): + self.methods[func.__name__]=func + return func + diff -r 3edd2f19bce2 -r e0424e96e3fd svgui/pyjs/lib/_pyjs.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/svgui/pyjs/lib/_pyjs.js Sat May 12 11:21:10 2012 +0200 @@ -0,0 +1,160 @@ +function pyjs_extend(klass, base) { + function klass_object_inherit() {} + klass_object_inherit.prototype = base.prototype; + klass_object = new klass_object_inherit(); + for (var i in base.prototype.__class__) { + v = base.prototype.__class__[i]; + if (typeof v == "function" && (v.class_method || v.static_method || v.unbound_method)) + { + klass_object[i] = v; + } + } + + function klass_inherit() {} + klass_inherit.prototype = klass_object; + klass.prototype = new klass_inherit(); + klass_object.constructor = klass; + klass.prototype.__class__ = klass_object; + + for (var i in base.prototype) { + v = base.prototype[i]; + if (typeof v == "function" && v.instance_method) + { + klass.prototype[i] = v; + } + } +} + +/* creates a class, derived from bases, with methods and variables */ +function pyjs_type(clsname, bases, methods) +{ + var fn_cls = function() {}; + fn_cls.__name__ = clsname; + var fn = function() { + var instance = new fn_cls(); + if(instance.__init__) instance.__init__.apply(instance, arguments); + return instance; + } + fn_cls.__initialize__ = function() { + if (fn_cls.__was_initialized__) return; + fn_cls.__was_initialized__ = true; + fn_cls.__extend_baseclasses(); + fn_cls.prototype.__class__.__new__ = fn; + fn_cls.prototype.__class__.__name__ = clsname; + } + fn_cls.__extend_baseclasses = function() { + var bi; + for (bi in fn_cls.__baseclasses) + { + var b = fn_cls.__baseclasses[bi]; + if (b.__was_initialized__) + { + continue; + } + b.__initialize__(); + } + for (bi in fn_cls.__baseclasses) + { + var b = fn_cls.__baseclasses[bi]; + pyjs_extend(fn_cls, b); + } + } + if (!bases) { + bases = [pyjslib.__Object]; + } + fn_cls.__baseclasses = bases; + + fn_cls.__initialize__(); + + for (k in methods) { + var mth = methods[k]; + var mtype = typeof mth; + if (mtype == "function" ) { + fn_cls.prototype[k] = mth; + fn_cls.prototype.__class__[k] = function () { + return fn_cls.prototype[k].call.apply( + fn_cls.prototype[k], arguments); + }; + fn_cls.prototype.__class__[k].unbound_method = true; + fn_cls.prototype.instance_method = true; + fn_cls.prototype.__class__[k].__name__ = k; + fn_cls.prototype[k].__name__ = k; + } else { + fn_cls.prototype.__class__[k] = mth; + } + } + return fn; +} +function pyjs_kwargs_call(obj, func, star_args, args) +{ + var call_args; + + if (star_args) + { + if (!pyjslib.isIteratable(star_args)) + { + throw (pyjslib.TypeError(func.__name__ + "() arguments after * must be a sequence" + pyjslib.repr(star_args))); + } + call_args = Array(); + var __i = star_args.__iter__(); + var i = 0; + try { + while (true) { + call_args[i]=__i.next(); + i++; + } + } catch (e) { + if (e != pyjslib.StopIteration) { + throw e; + } + } + + if (args) + { + var n = star_args.length; + for (var i=0; i < args.length; i++) { + call_args[n+i]=args[i]; + } + } + } + else + { + call_args = args; + } + return func.apply(obj, call_args); +} + +function pyjs_kwargs_function_call(func, star_args, args) +{ + return pyjs_kwargs_call(null, func, star_args, args); +} + +function pyjs_kwargs_method_call(obj, method_name, star_args, args) +{ + var method = obj[method_name]; + if (method.parse_kwargs) + { + args = method.parse_kwargs.apply(null, args); + } + return pyjs_kwargs_call(obj, method, star_args, args); +} + +//String.prototype.__getitem__ = String.prototype.charAt; +//String.prototype.upper = String.prototype.toUpperCase; +//String.prototype.lower = String.prototype.toLowerCase; +//String.prototype.find=pyjslib.String_find; +//String.prototype.join=pyjslib.String_join; +//String.prototype.isdigit=pyjslib.String_isdigit; +//String.prototype.__iter__=pyjslib.String___iter__; +// +//String.prototype.__replace=String.prototype.replace; +//String.prototype.replace=pyjslib.String_replace; +// +//String.prototype.split=pyjslib.String_split; +//String.prototype.strip=pyjslib.String_strip; +//String.prototype.lstrip=pyjslib.String_lstrip; +//String.prototype.rstrip=pyjslib.String_rstrip; +//String.prototype.startswith=pyjslib.String_startswith; + +var str = String; + diff -r 3edd2f19bce2 -r e0424e96e3fd svgui/pyjs/lib/json.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/svgui/pyjs/lib/json.js Sat May 12 11:21:10 2012 +0200 @@ -0,0 +1,293 @@ +json_parse = (function () { + +// This is a function that can parse a JSON text, producing a JavaScript +// data structure. It is a simple, recursive descent parser. It does not use +// eval or regular expressions, so it can be used as a model for implementing +// a JSON parser in other languages. + +// We are defining the function inside of another function to avoid creating +// global variables. + + var at, // The index of the current character + ch, // The current character + escapee = { + '"': '"', + '\\': '\\', + '/': '/', + b: '\b', + f: '\f', + n: '\n', + r: '\r', + t: '\t' + }, + text, + + error = function (m) { + +// Call error when something is wrong. + + throw { + name: 'SyntaxError', + message: m, + at: at, + text: text + }; + }, + + next = function (c) { + +// If a c parameter is provided, verify that it matches the current character. + + if (c && c !== ch) { + error("Expected '" + c + "' instead of '" + ch + "'"); + } + +// Get the next character. When there are no more characters, +// return the empty string. + + ch = text.charAt(at); + at += 1; + return ch; + }, + + number = function () { + +// Parse a number value. + + var number, + string = ''; + + if (ch === '-') { + string = '-'; + next('-'); + } + while (ch >= '0' && ch <= '9') { + string += ch; + next(); + } + if (ch === '.') { + string += '.'; + while (next() && ch >= '0' && ch <= '9') { + string += ch; + } + } + if (ch === 'e' || ch === 'E') { + string += ch; + next(); + if (ch === '-' || ch === '+') { + string += ch; + next(); + } + while (ch >= '0' && ch <= '9') { + string += ch; + next(); + } + } + number = +string; + if (isNaN(number)) { + error("Bad number"); + } else { + return number; + } + }, + + string = function () { + +// Parse a string value. + + var hex, + i, + string = '', + uffff; + +// When parsing for string values, we must look for " and \ characters. + + if (ch === '"') { + while (next()) { + if (ch === '"') { + next(); + return string; + } else if (ch === '\\') { + next(); + if (ch === 'u') { + uffff = 0; + for (i = 0; i < 4; i += 1) { + hex = parseInt(next(), 16); + if (!isFinite(hex)) { + break; + } + uffff = uffff * 16 + hex; + } + string += String.fromCharCode(uffff); + } else if (typeof escapee[ch] === 'string') { + string += escapee[ch]; + } else { + break; + } + } else { + string += ch; + } + } + } + error("Bad string"); + }, + + white = function () { + +// Skip whitespace. + + while (ch && ch <= ' ') { + next(); + } + }, + + word = function () { + +// true, false, or null. + + switch (ch) { + case 't': + next('t'); + next('r'); + next('u'); + next('e'); + return true; + case 'f': + next('f'); + next('a'); + next('l'); + next('s'); + next('e'); + return false; + case 'n': + next('n'); + next('u'); + next('l'); + next('l'); + return null; + } + error("Unexpected '" + ch + "'"); + }, + + value, // Place holder for the value function. + + array = function () { + +// Parse an array value. + + var array = []; + + if (ch === '[') { + next('['); + white(); + if (ch === ']') { + next(']'); + return array; // empty array + } + while (ch) { + array.push(value()); + white(); + if (ch === ']') { + next(']'); + return array; + } + next(','); + white(); + } + } + error("Bad array"); + }, + + object = function () { + +// Parse an object value. + + var key, + object = {}; + + if (ch === '{') { + next('{'); + white(); + if (ch === '}') { + next('}'); + return object; // empty object + } + while (ch) { + key = string(); + white(); + next(':'); + if (Object.hasOwnProperty.call(object, key)) { + error('Duplicate key "' + key + '"'); + } + object[key] = value(); + white(); + if (ch === '}') { + next('}'); + return object; + } + next(','); + white(); + } + } + error("Bad object"); + }; + + value = function () { + +// Parse a JSON value. It could be an object, an array, a string, a number, +// or a word. + + white(); + switch (ch) { + case '{': + return object(); + case '[': + return array(); + case '"': + return string(); + case '-': + return number(); + default: + return ch >= '0' && ch <= '9' ? number() : word(); + } + }; + +// Return the json_parse function. It will have access to all of the above +// functions and variables. + + return function (source, reviver) { + var result; + + text = source; + at = 0; + ch = ' '; + result = value(); + white(); + if (ch) { + error("Syntax error"); + } + +// If there is a reviver function, we recursively walk the new structure, +// passing each name/value pair to the reviver function for possible +// transformation, starting with a temporary root object that holds the result +// in an empty key. If there is not a reviver function, we simply return the +// result. + + return typeof reviver === 'function' ? (function walk(holder, key) { + var k, v, value = holder[key]; + if (value && typeof value === 'object') { + for (k in value) { + if (Object.hasOwnProperty.call(value, k)) { + v = walk(value, k); + if (v !== undefined) { + value[k] = v; + } else { + delete value[k]; + } + } + } + } + return reviver.call(holder, key, value); + }({'': result}, '')) : result; + }; +}()); diff -r 3edd2f19bce2 -r e0424e96e3fd svgui/pyjs/lib/pyjslib.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/svgui/pyjs/lib/pyjslib.py Sat May 12 11:21:10 2012 +0200 @@ -0,0 +1,1365 @@ +# Copyright 2006 James Tauber and contributors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +# iteration from Bob Ippolito's Iteration in JavaScript + +from __pyjamas__ import JS + +# must declare import _before_ importing sys + +def import_module(path, parent_module, module_name, dynamic=1, async=False): + """ + """ + + JS(""" + var cache_file; + + if (module_name == "sys" || module_name == 'pyjslib') + { + /*module_load_request[module_name] = 1;*/ + return; + } + + if (path == null) + { + path = './'; + } + + var override_name = sys.platform + "." + module_name; + if (((sys.overrides != null) && + (sys.overrides.has_key(override_name)))) + { + cache_file = sys.overrides.__getitem__(override_name) ; + } + else + { + cache_file = module_name ; + } + + cache_file = (path + cache_file + '.cache.js' ) ; + + //alert("cache " + cache_file + " " + module_name + " " + parent_module); + + /* already loaded? */ + if (module_load_request[module_name]) + { + if (module_load_request[module_name] >= 3 && parent_module != null) + { + //onload_fn = parent_module + '.' + module_name + ' = ' + module_name + ';'; + //pyjs_eval(onload_fn); /* set up the parent-module namespace */ + } + return; + } + if (typeof (module_load_request[module_name]) == 'undefined') + { + module_load_request[module_name] = 1; + } + + /* following a load, this first executes the script + * "preparation" function MODULENAME_loaded_fn() + * and then sets up the loaded module in the namespace + * of the parent. + */ + + onload_fn = ''; // module_name + "_loaded_fn();" + + if (parent_module != null) + { + //onload_fn += parent_module + '.' + module_name + ' = ' + module_name + ';'; + /*pmod = parent_module + '.' + module_name; + onload_fn += 'alert("' + pmod + '"+' + pmod+');';*/ + } + + + if (dynamic) + { + /* this one tacks the script onto the end of the DOM + */ + + pyjs_load_script(cache_file, onload_fn, async); + + /* this one actually RUNS the script (eval) into the page. + my feeling is that this would be better for non-async + but i can't get it to work entirely yet. + */ + /*pyjs_ajax_eval(cache_file, onload_fn, async);*/ + } + else + { + if (module_name != "pyjslib" && + module_name != "sys") + pyjs_eval(onload_fn); + } + + """) + +JS(""" +function import_wait(proceed_fn, parent_mod, dynamic) { + + var data = ''; + var element = $doc.createElement("div"); + $doc.body.appendChild(element); + function write_dom(txt) { + element.innerHTML = txt + '
'; + } + + var timeoutperiod = 1; + if (dynamic) + var timeoutperiod = 1; + + var wait = function() { + + var status = ''; + for (l in module_load_request) + { + var m = module_load_request[l]; + if (l == "sys" || l == 'pyjslib') + continue; + status += l + m + " "; + } + + //write_dom( " import wait " + wait_count + " " + status + " parent_mod " + parent_mod); + wait_count += 1; + + if (status == '') + { + setTimeout(wait, timeoutperiod); + return; + } + + for (l in module_load_request) + { + var m = module_load_request[l]; + if (l == "sys" || l == 'pyjslib') + { + module_load_request[l] = 4; + continue; + } + if ((parent_mod != null) && (l == parent_mod)) + { + if (m == 1) + { + setTimeout(wait, timeoutperiod); + return; + } + if (m == 2) + { + /* cheat and move app on to next stage */ + module_load_request[l] = 3; + } + } + if (m == 1 || m == 2) + { + setTimeout(wait, timeoutperiod); + return; + } + if (m == 3) + { + //alert("waited for module " + l + ": loaded"); + module_load_request[l] = 4; + mod_fn = modules[l]; + } + } + //alert("module wait done"); + + if (proceed_fn.importDone) + proceed_fn.importDone(proceed_fn); + else + proceed_fn(); + } + + wait(); +} +""") + +class Object: + pass + +object = Object + +class Modload: + + def __init__(self, path, app_modlist, app_imported_fn, dynamic, + parent_mod): + self.app_modlist = app_modlist + self.app_imported_fn = app_imported_fn + self.path = path + self.idx = 0; + self.dynamic = dynamic + self.parent_mod = parent_mod + + def next(self): + + for i in range(len(self.app_modlist[self.idx])): + app = self.app_modlist[self.idx][i] + import_module(self.path, self.parent_mod, app, self.dynamic, True); + self.idx += 1 + + if self.idx >= len(self.app_modlist): + import_wait(self.app_imported_fn, self.parent_mod, self.dynamic) + else: + import_wait(getattr(self, "next"), self.parent_mod, self.dynamic) + +def get_module(module_name): + ev = "__mod = %s;" % module_name + JS("pyjs_eval(ev);") + return __mod + +def preload_app_modules(path, app_modnames, app_imported_fn, dynamic, + parent_mod=None): + + loader = Modload(path, app_modnames, app_imported_fn, dynamic, parent_mod) + loader.next() + +import sys + +class BaseException: + + name = "BaseException" + + def __init__(self, *args): + self.args = args + + def __str__(self): + if len(self.args) is 0: + return '' + elif len(self.args) is 1: + return repr(self.args[0]) + return repr(self.args) + + def toString(self): + return str(self) + +class Exception(BaseException): + + name = "Exception" + +class TypeError(BaseException): + name = "TypeError" + +class StandardError(Exception): + name = "StandardError" + +class LookupError(StandardError): + name = "LookupError" + + def toString(self): + return self.name + ": " + self.args[0] + +class KeyError(LookupError): + name = "KeyError" + +class AttributeError(StandardError): + + name = "AttributeError" + + def toString(self): + return "AttributeError: %s of %s" % (self.args[1], self.args[0]) + +JS(""" +pyjslib.StopIteration = function () { }; +pyjslib.StopIteration.prototype = new Error(); +pyjslib.StopIteration.name = 'StopIteration'; +pyjslib.StopIteration.message = 'StopIteration'; + +pyjslib.String_find = function(sub, start, end) { + var pos=this.indexOf(sub, start); + if (pyjslib.isUndefined(end)) return pos; + + if (pos + sub.length>end) return -1; + return pos; +} + +pyjslib.String_join = function(data) { + var text=""; + + if (pyjslib.isArray(data)) { + return data.join(this); + } + else if (pyjslib.isIteratable(data)) { + var iter=data.__iter__(); + try { + text+=iter.next(); + while (true) { + var item=iter.next(); + text+=this + item; + } + } + catch (e) { + if (e != pyjslib.StopIteration) throw e; + } + } + + return text; +} + +pyjslib.String_isdigit = function() { + return (this.match(/^\d+$/g) != null); +} + +pyjslib.String_replace = function(old, replace, count) { + var do_max=false; + var start=0; + var new_str=""; + var pos=0; + + if (!pyjslib.isString(old)) return this.__replace(old, replace); + if (!pyjslib.isUndefined(count)) do_max=true; + + while (start= s.length) { + throw pyjslib.StopIteration; + } + return s.substring(i++, i, 1); + }, + '__iter__': function() { + return this; + } + }; +} + +pyjslib.String_strip = function(chars) { + return this.lstrip(chars).rstrip(chars); +} + +pyjslib.String_lstrip = function(chars) { + if (pyjslib.isUndefined(chars)) return this.replace(/^\s+/, ""); + + return this.replace(new RegExp("^[" + chars + "]+"), ""); +} + +pyjslib.String_rstrip = function(chars) { + if (pyjslib.isUndefined(chars)) return this.replace(/\s+$/, ""); + + return this.replace(new RegExp("[" + chars + "]+$"), ""); +} + +pyjslib.String_startswith = function(prefix, start) { + if (pyjslib.isUndefined(start)) start = 0; + + if (this.substring(start, prefix.length) == prefix) return true; + return false; +} + +pyjslib.abs = Math.abs; + +""") + +class Class: + def __init__(self, name): + self.name = name + + def __str___(self): + return self.name + +def eq(a,b): + JS(""" + if (pyjslib.hasattr(a, "__cmp__")) { + return a.__cmp__(b) == 0; + } else if (pyjslib.hasattr(b, "__cmp__")) { + return b.__cmp__(a) == 0; + } + return a == b; + """) + +def cmp(a,b): + if hasattr(a, "__cmp__"): + return a.__cmp__(b) + elif hasattr(b, "__cmp__"): + return -b.__cmp__(a) + if a > b: + return 1 + elif b > a: + return -1 + else: + return 0 + +def bool(v): + # this needs to stay in native code without any dependencies here, + # because this is used by if and while, we need to prevent + # recursion + JS(""" + if (!v) return false; + switch(typeof v){ + case 'boolean': + return v; + case 'object': + if (v.__nonzero__){ + return v.__nonzero__(); + }else if (v.__len__){ + return v.__len__()>0; + } + return true; + } + return Boolean(v); + """) + +class List: + def __init__(self, data=None): + JS(""" + this.l = []; + this.extend(data); + """) + + def append(self, item): + JS(""" this.l[this.l.length] = item;""") + + def extend(self, data): + JS(""" + if (pyjslib.isArray(data)) { + n = this.l.length; + for (var i=0; i < data.length; i++) { + this.l[n+i]=data[i]; + } + } + else if (pyjslib.isIteratable(data)) { + var iter=data.__iter__(); + var i=this.l.length; + try { + while (true) { + var item=iter.next(); + this.l[i++]=item; + } + } + catch (e) { + if (e != pyjslib.StopIteration) throw e; + } + } + """) + + def remove(self, value): + JS(""" + var index=this.index(value); + if (index<0) return false; + this.l.splice(index, 1); + return true; + """) + + def index(self, value, start=0): + JS(""" + var length=this.l.length; + for (var i=start; i= 0 + + def __iter__(self): + JS(""" + var i = 0; + var l = this.l; + return { + 'next': function() { + if (i >= l.length) { + throw pyjslib.StopIteration; + } + return l[i++]; + }, + '__iter__': function() { + return this; + } + }; + """) + + def reverse(self): + JS(""" this.l.reverse();""") + + def sort(self, compareFunc=None, keyFunc=None, reverse=False): + if not compareFunc: + global cmp + compareFunc = cmp + if keyFunc and reverse: + def thisSort1(a,b): + return -compareFunc(keyFunc(a), keyFunc(b)) + self.l.sort(thisSort1) + elif keyFunc: + def thisSort2(a,b): + return compareFunc(keyFunc(a), keyFunc(b)) + self.l.sort(thisSort2) + elif reverse: + def thisSort3(a,b): + return -compareFunc(a, b) + self.l.sort(thisSort3) + else: + self.l.sort(compareFunc) + + def getArray(self): + """ + Access the javascript Array that is used internally by this list + """ + return self.l + + def __str__(self): + return repr(self) + +list = List + +class Tuple: + def __init__(self, data=None): + JS(""" + this.l = []; + this.extend(data); + """) + + def append(self, item): + JS(""" this.l[this.l.length] = item;""") + + def extend(self, data): + JS(""" + if (pyjslib.isArray(data)) { + n = this.l.length; + for (var i=0; i < data.length; i++) { + this.l[n+i]=data[i]; + } + } + else if (pyjslib.isIteratable(data)) { + var iter=data.__iter__(); + var i=this.l.length; + try { + while (true) { + var item=iter.next(); + this.l[i++]=item; + } + } + catch (e) { + if (e != pyjslib.StopIteration) throw e; + } + } + """) + + def remove(self, value): + JS(""" + var index=this.index(value); + if (index<0) return false; + this.l.splice(index, 1); + return true; + """) + + def index(self, value, start=0): + JS(""" + var length=this.l.length; + for (var i=start; i= 0 + + def __iter__(self): + JS(""" + var i = 0; + var l = this.l; + return { + 'next': function() { + if (i >= l.length) { + throw pyjslib.StopIteration; + } + return l[i++]; + }, + '__iter__': function() { + return this; + } + }; + """) + + def reverse(self): + JS(""" this.l.reverse();""") + + def sort(self, compareFunc=None, keyFunc=None, reverse=False): + if not compareFunc: + global cmp + compareFunc = cmp + if keyFunc and reverse: + def thisSort1(a,b): + return -compareFunc(keyFunc(a), keyFunc(b)) + self.l.sort(thisSort1) + elif keyFunc: + def thisSort2(a,b): + return compareFunc(keyFunc(a), keyFunc(b)) + self.l.sort(thisSort2) + elif reverse: + def thisSort3(a,b): + return -compareFunc(a, b) + self.l.sort(thisSort3) + else: + self.l.sort(compareFunc) + + def getArray(self): + """ + Access the javascript Array that is used internally by this list + """ + return self.l + + def __str__(self): + return repr(self) + +tuple = Tuple + + +class Dict: + def __init__(self, data=None): + JS(""" + this.d = {}; + + if (pyjslib.isArray(data)) { + for (var i in data) { + var item=data[i]; + this.__setitem__(item[0], item[1]); + //var sKey=pyjslib.hash(item[0]); + //this.d[sKey]=item[1]; + } + } + else if (pyjslib.isIteratable(data)) { + var iter=data.__iter__(); + try { + while (true) { + var item=iter.next(); + this.__setitem__(item.__getitem__(0), item.__getitem__(1)); + } + } + catch (e) { + if (e != pyjslib.StopIteration) throw e; + } + } + else if (pyjslib.isObject(data)) { + for (var key in data) { + this.__setitem__(key, data[key]); + } + } + """) + + def __setitem__(self, key, value): + JS(""" + var sKey = pyjslib.hash(key); + this.d[sKey]=[key, value]; + """) + + def __getitem__(self, key): + JS(""" + var sKey = pyjslib.hash(key); + var value=this.d[sKey]; + if (pyjslib.isUndefined(value)){ + throw pyjslib.KeyError(key); + } + return value[1]; + """) + + def __nonzero__(self): + JS(""" + for (var i in this.d){ + return true; + } + return false; + """) + + def __len__(self): + JS(""" + var size=0; + for (var i in this.d) size++; + return size; + """) + + def has_key(self, key): + return self.__contains__(key) + + def __delitem__(self, key): + JS(""" + var sKey = pyjslib.hash(key); + delete this.d[sKey]; + """) + + def __contains__(self, key): + JS(""" + var sKey = pyjslib.hash(key); + return (pyjslib.isUndefined(this.d[sKey])) ? false : true; + """) + + def keys(self): + JS(""" + var keys=new pyjslib.List(); + for (var key in this.d) { + keys.append(this.d[key][0]); + } + return keys; + """) + + def values(self): + JS(""" + var values=new pyjslib.List(); + for (var key in this.d) values.append(this.d[key][1]); + return values; + """) + + def items(self): + JS(""" + var items = new pyjslib.List(); + for (var key in this.d) { + var kv = this.d[key]; + items.append(new pyjslib.List(kv)) + } + return items; + """) + + def __iter__(self): + return self.keys().__iter__() + + def iterkeys(self): + return self.__iter__() + + def itervalues(self): + return self.values().__iter__(); + + def iteritems(self): + return self.items().__iter__(); + + def setdefault(self, key, default_value): + if not self.has_key(key): + self[key] = default_value + + def get(self, key, default_=None): + if not self.has_key(key): + return default_ + return self[key] + + def update(self, d): + for k,v in d.iteritems(): + self[k] = v + + def getObject(self): + """ + Return the javascript Object which this class uses to store + dictionary keys and values + """ + return self.d + + def copy(self): + return Dict(self.items()) + + def __str__(self): + return repr(self) + +dict = Dict + +# taken from mochikit: range( [start,] stop[, step] ) +def range(): + JS(""" + var start = 0; + var stop = 0; + var step = 1; + + if (arguments.length == 2) { + start = arguments[0]; + stop = arguments[1]; + } + else if (arguments.length == 3) { + start = arguments[0]; + stop = arguments[1]; + step = arguments[2]; + } + else if (arguments.length>0) stop = arguments[0]; + + return { + 'next': function() { + if ((step > 0 && start >= stop) || (step < 0 && start <= stop)) throw pyjslib.StopIteration; + var rval = start; + start += step; + return rval; + }, + '__iter__': function() { + return this; + } + } + """) + +def slice(object, lower, upper): + JS(""" + if (pyjslib.isString(object)) { + if (lower < 0) { + lower = object.length + lower; + } + if (upper < 0) { + upper = object.length + upper; + } + if (pyjslib.isNull(upper)) upper=object.length; + return object.substring(lower, upper); + } + if (pyjslib.isObject(object) && object.slice) + return object.slice(lower, upper); + + return null; + """) + +def str(text): + JS(""" + if (pyjslib.hasattr(text,"__str__")) { + return text.__str__(); + } + return String(text); + """) + +def ord(x): + if(isString(x) and len(x) is 1): + JS(""" + return x.charCodeAt(0); + """) + else: + JS(""" + throw pyjslib.TypeError(); + """) + return None + +def chr(x): + JS(""" + return String.fromCharCode(x) + """) + +def is_basetype(x): + JS(""" + var t = typeof(x); + return t == 'boolean' || + t == 'function' || + t == 'number' || + t == 'string' || + t == 'undefined' + ; + """) + +def get_pyjs_classtype(x): + JS(""" + if (pyjslib.hasattr(x, "__class__")) + if (pyjslib.hasattr(x.__class__, "__new__")) + var src = x.__class__.__name__; + return src; + return null; + """) + +def repr(x): + """ Return the string representation of 'x'. + """ + JS(""" + if (x === null) + return "null"; + + if (x === undefined) + return "undefined"; + + var t = typeof(x); + + //alert("repr typeof " + t + " : " + x); + + if (t == "boolean") + return x.toString(); + + if (t == "function") + return ""; + + if (t == "number") + return x.toString(); + + if (t == "string") { + if (x.indexOf("'") == -1) + return "'" + x + "'"; + if (x.indexOf('"') == -1) + return '"' + x + '"'; + var s = x.replace(new RegExp('"', "g"), '\\\\"'); + return '"' + s + '"'; + }; + + if (t == "undefined") + return "undefined"; + + // If we get here, x is an object. See if it's a Pyjamas class. + + if (!pyjslib.hasattr(x, "__init__")) + return "<" + x.toString() + ">"; + + // Handle the common Pyjamas data types. + + var constructor = "UNKNOWN"; + + constructor = pyjslib.get_pyjs_classtype(x); + + //alert("repr constructor: " + constructor); + + if (constructor == "Tuple") { + var contents = x.getArray(); + var s = "("; + for (var i=0; i < contents.length; i++) { + s += pyjslib.repr(contents[i]); + if (i < contents.length - 1) + s += ", "; + }; + s += ")" + return s; + }; + + if (constructor == "List") { + var contents = x.getArray(); + var s = "["; + for (var i=0; i < contents.length; i++) { + s += pyjslib.repr(contents[i]); + if (i < contents.length - 1) + s += ", "; + }; + s += "]" + return s; + }; + + if (constructor == "Dict") { + var keys = new Array(); + for (var key in x.d) + keys.push(key); + + var s = "{"; + for (var i=0; i return the class name. + // Note that we replace underscores with dots so that the name will + // (hopefully!) look like the original Python name. + + //var s = constructor.replace(new RegExp('_', "g"), '.'); + return "<" + constructor + " object>"; + """) + +def float(text): + JS(""" + return parseFloat(text); + """) + +def int(text, radix=0): + JS(""" + return parseInt(text, radix); + """) + +def len(object): + JS(""" + if (object==null) return 0; + if (pyjslib.isObject(object) && object.__len__) return object.__len__(); + return object.length; + """) + +def isinstance(object_, classinfo): + if pyjslib.isUndefined(object_): + return False + if not pyjslib.isObject(object_): + + return False + if _isinstance(classinfo, Tuple): + for ci in classinfo: + if isinstance(object_, ci): + return True + return False + else: + return _isinstance(object_, classinfo) + +def _isinstance(object_, classinfo): + if not pyjslib.isObject(object_): + return False + JS(""" + if (object_.__class__){ + var res = object_ instanceof classinfo.constructor; + return res; + } + return false; + """) + +def getattr(obj, name, default_): + JS(""" + if ((!pyjslib.isObject(obj))||(pyjslib.isUndefined(obj[name]))){ + if (pyjslib.isUndefined(default_)){ + throw pyjslib.AttributeError(obj, name); + }else{ + return default_; + } + } + if (!pyjslib.isFunction(obj[name])) return obj[name]; + var fnwrap = function() { + var args = []; + for (var i = 0; i < arguments.length; i++) { + args.push(arguments[i]); + } + return obj[name].apply(obj,args); + } + fnwrap.__name__ = name; + return fnwrap; + """) + +def setattr(obj, name, value): + JS(""" + if (!pyjslib.isObject(obj)) return null; + + obj[name] = value; + + """) + +def hasattr(obj, name): + JS(""" + if (!pyjslib.isObject(obj)) return false; + if (pyjslib.isUndefined(obj[name])) return false; + + return true; + """) + +def dir(obj): + JS(""" + var properties=new pyjslib.List(); + for (property in obj) properties.append(property); + return properties; + """) + +def filter(obj, method, sequence=None): + # object context is LOST when a method is passed, hence object must be passed separately + # to emulate python behaviour, should generate this code inline rather than as a function call + items = [] + if sequence is None: + sequence = method + method = obj + + for item in sequence: + if method(item): + items.append(item) + else: + for item in sequence: + if method.call(obj, item): + items.append(item) + + return items + + +def map(obj, method, sequence=None): + items = [] + + if sequence is None: + sequence = method + method = obj + + for item in sequence: + items.append(method(item)) + else: + for item in sequence: + items.append(method.call(obj, item)) + + return items + + +def enumerate(sequence): + enumeration = [] + nextIndex = 0 + for item in sequence: + enumeration.append([nextIndex, item]) + nextIndex = nextIndex + 1 + return enumeration + + +def min(*sequence): + minValue = None + for item in sequence: + if minValue is None: + minValue = item + elif item < minValue: + minValue = item + return minValue + + +def max(*sequence): + maxValue = None + for item in sequence: + if maxValue is None: + maxValue = item + elif item > maxValue: + maxValue = item + return maxValue + + +next_hash_id = 0 + +def hash(obj): + JS(""" + if (obj == null) return null; + + if (obj.$H) return obj.$H; + if (obj.__hash__) return obj.__hash__(); + if (obj.constructor == String || obj.constructor == Number || obj.constructor == Date) return obj; + + obj.$H = ++pyjslib.next_hash_id; + return obj.$H; + """) + + +# type functions from Douglas Crockford's Remedial Javascript: http://www.crockford.com/javascript/remedial.html +def isObject(a): + JS(""" + return (a != null && (typeof a == 'object')) || pyjslib.isFunction(a); + """) + +def isFunction(a): + JS(""" + return typeof a == 'function'; + """) + +def isString(a): + JS(""" + return typeof a == 'string'; + """) + +def isNull(a): + JS(""" + return typeof a == 'object' && !a; + """) + +def isArray(a): + JS(""" + return pyjslib.isObject(a) && a.constructor == Array; + """) + +def isUndefined(a): + JS(""" + return typeof a == 'undefined'; + """) + +def isIteratable(a): + JS(""" + return pyjslib.isString(a) || (pyjslib.isObject(a) && a.__iter__); + """) + +def isNumber(a): + JS(""" + return typeof a == 'number' && isFinite(a); + """) + +def toJSObjects(x): + """ + Convert the pyjs pythonic List and Dict objects into javascript Object and Array + objects, recursively. + """ + if isArray(x): + JS(""" + var result = []; + for(var k=0; k < x.length; k++) { + var v = x[k]; + var tv = pyjslib.toJSObjects(v); + result.push(tv); + } + return result; + """) + if isObject(x): + if isinstance(x, Dict): + JS(""" + var o = x.getObject(); + var result = {}; + for (var i in o) { + result[o[i][0].toString()] = o[i][1]; + } + return pyjslib.toJSObjects(result) + """) + elif isinstance(x, List): + return toJSObjects(x.l) + elif hasattr(x, '__class__'): + # we do not have a special implementation for custom + # classes, just pass it on + return x + if isObject(x): + JS(""" + var result = {}; + for(var k in x) { + var v = x[k]; + var tv = pyjslib.toJSObjects(v) + result[k] = tv; + } + return result; + """) + return x + +def printFunc(objs): + JS(""" + if ($wnd.console==undefined) return; + var s = ""; + for(var i=0; i < objs.length; i++) { + if(s != "") s += " "; + s += objs[i]; + } + console.debug(s) + """) + +def type(clsname, bases=None, methods=None): + """ creates a class, derived from bases, with methods and variables + """ + + JS(" var mths = {}; ") + if methods: + for k in methods.keys(): + mth = methods[k] + JS(" mths[k] = mth; ") + + JS(" var bss = null; ") + if bases: + JS("bss = bases.l;") + JS(" return pyjs_type(clsname, bss, mths); ") + diff -r 3edd2f19bce2 -r e0424e96e3fd svgui/pyjs/lib/sys.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/svgui/pyjs/lib/sys.py Sat May 12 11:21:10 2012 +0200 @@ -0,0 +1,59 @@ +# the platform name (PyV8, smjs, Mozilla, IE6, Opera, Safari etc.) +platform = '' # to be updated by app, on compile + +# a dictionary of module override names (platform-specific) +overrides = None # to be updated by app, on compile + +# the remote path for loading modules +loadpath = None + +stacktrace = None + +appname = None + +def setloadpath(lp): + global loadpath + loadpath = lp + +def setappname(an): + global appname + appname = an + +def getloadpath(): + global loadpath + return loadpath + +def addoverride(module_name, path): + global overrides + overrides[module_name] = path + +def addstack(linedebug): + JS(""" + if (pyjslib.bool((sys.stacktrace === null))) { + sys.stacktrace = new pyjslib.List([]); + } + sys.stacktrace.append(linedebug); + """) +def popstack(): + JS(""" + sys.stacktrace.pop() + """) + +def printstack(): + JS(""" + var res = ''; + + var __l = sys.stacktrace.__iter__(); + try { + while (true) { + var l = __l.next(); + res += ( l + '\\n' ) ; + } + } catch (e) { + if (e != pyjslib.StopIteration) { + throw e; + } + } + + return res; + """) diff -r 3edd2f19bce2 -r e0424e96e3fd svgui/pyjs/pyjs.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/svgui/pyjs/pyjs.py Sat May 12 11:21:10 2012 +0200 @@ -0,0 +1,1777 @@ +#!/usr/bin/env python +# Copyright 2006 James Tauber and contributors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +import sys +from types import StringType +import compiler +from compiler import ast +import os +import copy + +# the standard location for builtins (e.g. pyjslib) can be +# over-ridden by changing this. it defaults to sys.prefix +# so that on a system-wide install of pyjamas the builtins +# can be found in e.g. {sys.prefix}/share/pyjamas +# +# over-rides can be done by either explicitly modifying +# pyjs.prefix or by setting an environment variable, PYJSPREFIX. + +prefix = sys.prefix + +if os.environ.has_key('PYJSPREFIX'): + prefix = os.environ['PYJSPREFIX'] + +# pyjs.path is the list of paths, just like sys.path, from which +# library modules will be searched for, for compile purposes. +# obviously we don't want to use sys.path because that would result +# in compiling standard python modules into javascript! + +path = [os.path.abspath('')] + +if os.environ.has_key('PYJSPATH'): + for p in os.environ['PYJSPATH'].split(os.pathsep): + p = os.path.abspath(p) + if os.path.isdir(p): + path.append(p) + +# this is the python function used to wrap native javascript +NATIVE_JS_FUNC_NAME = "JS" + +UU = "" + +PYJSLIB_BUILTIN_FUNCTIONS=("cmp", + "map", + "filter", + "dir", + "getattr", + "setattr", + "hasattr", + "int", + "float", + "str", + "repr", + "range", + "len", + "hash", + "abs", + "ord", + "chr", + "enumerate", + "min", + "max", + "bool", + "type", + "isinstance") + +PYJSLIB_BUILTIN_CLASSES=("BaseException", + "Exception", + "StandardError", + "StopIteration", + "AttributeError", + "TypeError", + "KeyError", + "LookupError", + "list", + "dict", + "object", + "tuple", + ) + +def pyjs_builtin_remap(name): + # XXX HACK! + if name == 'list': + name = 'List' + if name == 'object': + name = '__Object' + if name == 'dict': + name = 'Dict' + if name == 'tuple': + name = 'Tuple' + return name + +# XXX: this is a hack: these should be dealt with another way +# however, console is currently the only global name which is causing +# problems. +PYJS_GLOBAL_VARS=("console") + +# This is taken from the django project. +# Escape every ASCII character with a value less than 32. +JS_ESCAPES = ( + ('\\', r'\x5C'), + ('\'', r'\x27'), + ('"', r'\x22'), + ('>', r'\x3E'), + ('<', r'\x3C'), + ('&', r'\x26'), + (';', r'\x3B') + ) + tuple([('%c' % z, '\\x%02X' % z) for z in range(32)]) + +def escapejs(value): + """Hex encodes characters for use in JavaScript strings.""" + for bad, good in JS_ESCAPES: + value = value.replace(bad, good) + return value + +def uuprefix(name, leave_alone=0): + name = name.split(".") + name = name[:leave_alone] + map(lambda x: "__%s" % x, name[leave_alone:]) + return '.'.join(name) + +class Klass: + + klasses = {} + + def __init__(self, name, name_): + self.name = name + self.name_ = name_ + self.klasses[name] = self + self.functions = set() + + def set_base(self, base_name): + self.base = self.klasses.get(base_name) + + def add_function(self, function_name): + self.functions.add(function_name) + + +class TranslationError(Exception): + def __init__(self, message, node): + self.message = "line %s:\n%s\n%s" % (node.lineno, message, node) + + def __str__(self): + return self.message + +def strip_py(name): + return name + +def mod_var_name_decl(raw_module_name): + """ function to get the last component of the module e.g. + pyjamas.ui.DOM into the "namespace". i.e. doing + "import pyjamas.ui.DOM" actually ends up with _two_ + variables - one pyjamas.ui.DOM, the other just "DOM". + but "DOM" is actually local, hence the "var" prefix. + + for PyV8, this might end up causing problems - we'll have + to see: gen_mod_import and mod_var_name_decl might have + to end up in a library-specific module, somewhere. + """ + name = raw_module_name.split(".") + if len(name) == 1: + return '' + child_name = name[-1] + return "var %s = %s;\n" % (child_name, raw_module_name) + +def gen_mod_import(parentName, importName, dynamic=1): + #pyjs_ajax_eval("%(n)s.cache.js", null, true); + return """ + pyjslib.import_module(sys.loadpath, '%(p)s', '%(n)s', %(d)d, false); + """ % ({'p': parentName, 'd': dynamic, 'n': importName}) + \ + mod_var_name_decl(importName) + +class Translator: + + def __init__(self, mn, module_name, raw_module_name, src, debug, mod, output, + dynamic=0, optimize=False, + findFile=None): + + if module_name: + self.module_prefix = module_name + "." + else: + self.module_prefix = "" + self.raw_module_name = raw_module_name + src = src.replace("\r\n", "\n") + src = src.replace("\n\r", "\n") + src = src.replace("\r", "\n") + self.src = src.split("\n") + self.debug = debug + self.imported_modules = [] + self.imported_modules_as = [] + self.imported_js = set() + self.top_level_functions = set() + self.top_level_classes = set() + self.top_level_vars = set() + self.local_arg_stack = [[]] + self.output = output + self.imported_classes = {} + self.method_imported_globals = set() + self.method_self = None + self.nextTupleAssignID = 1 + self.dynamic = dynamic + self.optimize = optimize + self.findFile = findFile + + if module_name.find(".") >= 0: + vdec = '' + else: + vdec = 'var ' + print >>self.output, UU+"%s%s = function (__mod_name__) {" % (vdec, module_name) + + print >>self.output, " if("+module_name+".__was_initialized__) return;" + print >>self.output, " "+UU+module_name+".__was_initialized__ = true;" + print >>self.output, UU+"if (__mod_name__ == null) __mod_name__ = '%s';" % (mn) + print >>self.output, UU+"%s.__name__ = __mod_name__;" % (raw_module_name) + + decl = mod_var_name_decl(raw_module_name) + if decl: + print >>self.output, decl + + + if self.debug: + haltException = self.module_prefix + "HaltException" + print >>self.output, haltException + ' = function () {' + print >>self.output, ' this.message = "Program Halted";' + print >>self.output, ' this.name = "' + haltException + '";' + print >>self.output, '}' + print >>self.output, '' + print >>self.output, haltException + ".prototype.__str__ = function()" + print >>self.output, '{' + print >>self.output, 'return this.message ;' + print >>self.output, '}' + + print >>self.output, haltException + ".prototype.toString = function()" + print >>self.output, '{' + print >>self.output, 'return this.name + ": \\"" + this.message + "\\"";' + print >>self.output, '}' + + isHaltFunction = self.module_prefix + "IsHaltException" + print >>self.output, """ + %s = function (s) { + var suffix="HaltException"; + if (s.length < suffix.length) { + //alert(s + " " + suffix); + return false; + } else { + var ss = s.substring(s.length, (s.length - suffix.length)); + //alert(s + " " + suffix + " " + ss); + return ss == suffix; + } + } + """ % isHaltFunction + for child in mod.node: + if isinstance(child, ast.Function): + self.top_level_functions.add(child.name) + elif isinstance(child, ast.Class): + self.top_level_classes.add(child.name) + + for child in mod.node: + if isinstance(child, ast.Function): + self._function(child, False) + elif isinstance(child, ast.Class): + self._class(child) + elif isinstance(child, ast.Import): + importName = child.names[0][0] + if importName == '__pyjamas__': # special module to help make pyjamas modules loadable in the python interpreter + pass + elif importName.endswith('.js'): + self.imported_js.add(importName) + else: + self.add_imported_module(strip_py(importName)) + elif isinstance(child, ast.From): + if child.modname == '__pyjamas__': # special module to help make pyjamas modules loadable in the python interpreter + pass + else: + self.add_imported_module(child.modname) + self._from(child) + elif isinstance(child, ast.Discard): + self._discard(child, None) + elif isinstance(child, ast.Assign): + self._assign(child, None, True) + elif isinstance(child, ast.AugAssign): + self._augassign(child, None) + elif isinstance(child, ast.If): + self._if(child, None) + elif isinstance(child, ast.For): + self._for(child, None) + elif isinstance(child, ast.While): + self._while(child, None) + elif isinstance(child, ast.Subscript): + self._subscript_stmt(child, None) + elif isinstance(child, ast.Global): + self._global(child, None) + elif isinstance(child, ast.Printnl): + self._print(child, None) + elif isinstance(child, ast.Print): + self._print(child, None) + elif isinstance(child, ast.TryExcept): + self._tryExcept(child, None) + elif isinstance(child, ast.Raise): + self._raise(child, None) + elif isinstance(child, ast.Stmt): + self._stmt(child, None) + else: + raise TranslationError("unsupported type (in __init__)", child) + + # Initialize all classes for this module + #print >> self.output, "__"+self.modpfx()+\ + # "classes_initialize = function() {\n" + #for className in self.top_level_classes: + # print >> self.output, "\t"+UU+self.modpfx()+"__"+className+"_initialize();" + #print >> self.output, "};\n" + + print >> self.output, "return this;\n" + print >> self.output, "}; /* end %s */ \n" % module_name + + def module_imports(self): + return self.imported_modules + self.imported_modules_as + + def add_local_arg(self, varname): + local_vars = self.local_arg_stack[-1] + if varname not in local_vars: + local_vars.append(varname) + + def add_imported_module(self, importName): + + if importName in self.imported_modules: + return + self.imported_modules.append(importName) + name = importName.split(".") + if len(name) != 1: + # add the name of the module to the namespace, + # but don't add the short name to imported_modules + # because then the short name would be attempted to be + # added to the dependencies, and it's half way up the + # module import directory structure! + child_name = name[-1] + self.imported_modules_as.append(child_name) + print >> self.output, gen_mod_import(self.raw_module_name, + strip_py(importName), + self.dynamic) + + def _default_args_handler(self, node, arg_names, current_klass, + output=None): + if len(node.defaults): + output = output or self.output + default_pos = len(arg_names) - len(node.defaults) + if arg_names and arg_names[0] == self.method_self: + default_pos -= 1 + for default_node in node.defaults: + if isinstance(default_node, ast.Const): + default_value = self._const(default_node) + elif isinstance(default_node, ast.Name): + default_value = self._name(default_node, current_klass) + elif isinstance(default_node, ast.UnarySub): + default_value = self._unarysub(default_node, current_klass) + else: + raise TranslationError("unsupported type (in _method)", default_node) + + default_name = arg_names[default_pos] + default_pos += 1 + print >> output, " if (typeof %s == 'undefined') %s=%s;" % (default_name, default_name, default_value) + + def _varargs_handler(self, node, varargname, arg_names, current_klass): + print >>self.output, " var", varargname, '= new pyjslib.Tuple();' + print >>self.output, " for(var __va_arg="+str(len(arg_names))+"; __va_arg < arguments.length; __va_arg++) {" + print >>self.output, " var __arg = arguments[__va_arg];" + print >>self.output, " "+varargname+".append(__arg);" + print >>self.output, " }" + + def _kwargs_parser(self, node, function_name, arg_names, current_klass): + if len(node.defaults) or node.kwargs: + default_pos = len(arg_names) - len(node.defaults) + if arg_names and arg_names[0] == self.method_self: + default_pos -= 1 + print >>self.output, function_name+'.parse_kwargs = function (', ", ".join(["__kwargs"]+arg_names), ") {" + for default_node in node.defaults: + default_value = self.expr(default_node, current_klass) +# if isinstance(default_node, ast.Const): +# default_value = self._const(default_node) +# elif isinstance(default_node, ast.Name): +# default_value = self._name(default_node) +# elif isinstance(default_node, ast.UnarySub): +# default_value = self._unarysub(default_node, current_klass) +# else: +# raise TranslationError("unsupported type (in _method)", default_node) + + default_name = arg_names[default_pos] + print >>self.output, " if (typeof %s == 'undefined')"%(default_name) + print >>self.output, " %s=__kwargs.%s;"% (default_name, default_name) + default_pos += 1 + + #self._default_args_handler(node, arg_names, current_klass) + if node.kwargs: arg_names += ["pyjslib.Dict(__kwargs)"] + print >>self.output, " var __r = "+"".join(["[", ", ".join(arg_names), "]"])+";" + if node.varargs: + self._varargs_handler(node, "__args", arg_names, current_klass) + print >>self.output, " __r.push.apply(__r, __args.getArray())" + print >>self.output, " return __r;" + print >>self.output, "};" + + def _function(self, node, local=False): + if local: + function_name = node.name + self.add_local_arg(function_name) + else: + function_name = UU + self.modpfx() + node.name + + arg_names = list(node.argnames) + normal_arg_names = list(arg_names) + if node.kwargs: kwargname = normal_arg_names.pop() + if node.varargs: varargname = normal_arg_names.pop() + declared_arg_names = list(normal_arg_names) + if node.kwargs: declared_arg_names.append(kwargname) + + function_args = "(" + ", ".join(declared_arg_names) + ")" + print >>self.output, "%s = function%s {" % (function_name, function_args) + self._default_args_handler(node, normal_arg_names, None) + + local_arg_names = normal_arg_names + declared_arg_names + + if node.varargs: + self._varargs_handler(node, varargname, declared_arg_names, None) + local_arg_names.append(varargname) + + # stack of local variable names for this function call + self.local_arg_stack.append(local_arg_names) + + for child in node.code: + self._stmt(child, None) + + # remove the top local arg names + self.local_arg_stack.pop() + + # we need to return null always, so it is not undefined + lastStmt = [p for p in node.code][-1] + if not isinstance(lastStmt, ast.Return): + if not self._isNativeFunc(lastStmt): + print >>self.output, " return null;" + + print >>self.output, "};" + print >>self.output, "%s.__name__ = '%s';\n" % (function_name, node.name) + + + self._kwargs_parser(node, function_name, normal_arg_names, None) + + + def _return(self, node, current_klass): + expr = self.expr(node.value, current_klass) + # in python a function call always returns None, so we do it + # here too + print >>self.output, " return " + expr + ";" + + + def _break(self, node, current_klass): + print >>self.output, " break;" + + + def _continue(self, node, current_klass): + print >>self.output, " continue;" + + + def _callfunc(self, v, current_klass): + + if isinstance(v.node, ast.Name): + if v.node.name in self.top_level_functions: + call_name = self.modpfx() + v.node.name + elif v.node.name in self.top_level_classes: + call_name = self.modpfx() + v.node.name + elif self.imported_classes.has_key(v.node.name): + call_name = self.imported_classes[v.node.name] + '.' + v.node.name + elif v.node.name in PYJSLIB_BUILTIN_FUNCTIONS: + call_name = 'pyjslib.' + v.node.name + elif v.node.name in PYJSLIB_BUILTIN_CLASSES: + name = pyjs_builtin_remap(v.node.name) + call_name = 'pyjslib.' + name + elif v.node.name == "callable": + call_name = "pyjslib.isFunction" + else: + call_name = v.node.name + call_args = [] + elif isinstance(v.node, ast.Getattr): + attr_name = v.node.attrname + + if isinstance(v.node.expr, ast.Name): + call_name = self._name2(v.node.expr, current_klass, attr_name) + call_args = [] + elif isinstance(v.node.expr, ast.Getattr): + call_name = self._getattr2(v.node.expr, current_klass, attr_name) + call_args = [] + elif isinstance(v.node.expr, ast.CallFunc): + call_name = self._callfunc(v.node.expr, current_klass) + "." + v.node.attrname + call_args = [] + elif isinstance(v.node.expr, ast.Subscript): + call_name = self._subscript(v.node.expr, current_klass) + "." + v.node.attrname + call_args = [] + elif isinstance(v.node.expr, ast.Const): + call_name = self.expr(v.node.expr, current_klass) + "." + v.node.attrname + call_args = [] + else: + raise TranslationError("unsupported type (in _callfunc)", v.node.expr) + else: + raise TranslationError("unsupported type (in _callfunc)", v.node) + + call_name = strip_py(call_name) + + kwargs = [] + star_arg_name = None + if v.star_args: + star_arg_name = self.expr(v.star_args, current_klass) + + for ch4 in v.args: + if isinstance(ch4, ast.Keyword): + kwarg = ch4.name + ":" + self.expr(ch4.expr, current_klass) + kwargs.append(kwarg) + else: + arg = self.expr(ch4, current_klass) + call_args.append(arg) + + if kwargs: + fn_args = ", ".join(['{' + ', '.join(kwargs) + '}']+call_args) + else: + fn_args = ", ".join(call_args) + + if kwargs or star_arg_name: + if not star_arg_name: + star_arg_name = 'null' + try: call_this, method_name = call_name.rsplit(".", 1) + except ValueError: + # Must be a function call ... + return ("pyjs_kwargs_function_call("+call_name+", " + + star_arg_name + + ", ["+fn_args+"]" + + ")" ) + else: + return ("pyjs_kwargs_method_call("+call_this+", '"+method_name+"', " + + star_arg_name + + ", ["+fn_args+"]" + + ")") + else: + return call_name + "(" + ", ".join(call_args) + ")" + + def _print(self, node, current_klass): + if self.optimize: + return + call_args = [] + for ch4 in node.nodes: + arg = self.expr(ch4, current_klass) + call_args.append(arg) + + print >>self.output, "pyjslib.printFunc([", ', '.join(call_args), "],", int(isinstance(node, ast.Printnl)), ");" + + def _tryExcept(self, node, current_klass): + if len(node.handlers) != 1: + raise TranslationError("except statements in this form are" + + " not supported", node) + + expr = node.handlers[0][0] + as_ = node.handlers[0][1] + if as_: + errName = as_.name + else: + errName = 'err' + + # XXX TODO: check that this should instead be added as a _separate_ + # local scope, temporary to the function. oh dearie me. + self.add_local_arg(errName) + + print >>self.output, " try {" + for stmt in node.body.nodes: + self._stmt(stmt, current_klass) + print >> self.output, " } catch(%s) {" % errName + if expr: + l = [] + if isinstance(expr, ast.Tuple): + for x in expr.nodes: + l.append("(%(err)s.__name__ == %(expr)s.__name__)" % dict (err=errName, expr=self.expr(x, current_klass))) + else: + l = [ " (%(err)s.__name__ == %(expr)s.__name__) " % dict (err=errName, expr=self.expr(expr, current_klass)) ] + print >> self.output, " if(%s) {" % '||\n\t\t'.join(l) + for stmt in node.handlers[0][2]: + self._stmt(stmt, current_klass) + if expr: + #print >> self.output, "} else { throw(%s); } " % errName + print >> self.output, "}" + if node.else_ != None: + print >>self.output, " } finally {" + for stmt in node.else_: + self._stmt(stmt, current_klass) + print >>self.output, " }" + + # XXX: change use_getattr to True to enable "strict" compilation + # but incurring a 100% performance penalty. oops. + def _getattr(self, v, current_klass, use_getattr=False): + attr_name = v.attrname + if isinstance(v.expr, ast.Name): + obj = self._name(v.expr, current_klass, return_none_for_module=True) + if obj == None and v.expr.name in self.module_imports(): + # XXX TODO: distinguish between module import classes + # and variables. right now, this is a hack to get + # the sys module working. + #if v.expr.name == 'sys': + return v.expr.name+'.'+attr_name + #return v.expr.name+'.__'+attr_name+'.prototype.__class__' + if not use_getattr or attr_name == '__class__' or \ + attr_name == '__name__': + return obj + "." + attr_name + return "pyjslib.getattr(%s, '%s')" % (obj, attr_name) + elif isinstance(v.expr, ast.Getattr): + return self._getattr(v.expr, current_klass) + "." + attr_name + elif isinstance(v.expr, ast.Subscript): + return self._subscript(v.expr, self.modpfx()) + "." + attr_name + elif isinstance(v.expr, ast.CallFunc): + return self._callfunc(v.expr, self.modpfx()) + "." + attr_name + else: + raise TranslationError("unsupported type (in _getattr)", v.expr) + + + def modpfx(self): + return strip_py(self.module_prefix) + + def _name(self, v, current_klass, top_level=False, + return_none_for_module=False): + + if v.name == 'ilikesillynamesfornicedebugcode': + print top_level, current_klass, repr(v) + print self.top_level_vars + print self.top_level_functions + print self.local_arg_stack + print "error..." + + local_var_names = None + las = len(self.local_arg_stack) + if las > 0: + local_var_names = self.local_arg_stack[-1] + + if v.name == "True": + return "true" + elif v.name == "False": + return "false" + elif v.name == "None": + return "null" + elif v.name == '__name__' and current_klass is None: + return self.modpfx() + v.name + elif v.name == self.method_self: + return "this" + elif v.name in self.top_level_functions: + return UU+self.modpfx() + v.name + elif v.name in self.method_imported_globals: + return UU+self.modpfx() + v.name + elif not current_klass and las == 1 and v.name in self.top_level_vars: + return UU+self.modpfx() + v.name + elif v.name in local_var_names: + return v.name + elif self.imported_classes.has_key(v.name): + return UU+self.imported_classes[v.name] + '.__' + v.name + ".prototype.__class__" + elif v.name in self.top_level_classes: + return UU+self.modpfx() + "__" + v.name + ".prototype.__class__" + elif v.name in self.module_imports() and return_none_for_module: + return None + elif v.name in PYJSLIB_BUILTIN_CLASSES: + return "pyjslib." + pyjs_builtin_remap( v.name ) + elif current_klass: + if v.name not in local_var_names and \ + v.name not in self.top_level_vars and \ + v.name not in PYJS_GLOBAL_VARS and \ + v.name not in self.top_level_functions: + + cls_name = current_klass + if hasattr(cls_name, "name"): + cls_name_ = cls_name.name_ + cls_name = cls_name.name + else: + cls_name_ = current_klass + "_" # XXX ??? + name = UU+cls_name_ + ".prototype.__class__." \ + + v.name + if v.name == 'listener': + name = 'listener+' + name + return name + + return v.name + + def _name2(self, v, current_klass, attr_name): + obj = v.name + + if obj in self.method_imported_globals: + call_name = UU+self.modpfx() + obj + "." + attr_name + elif self.imported_classes.has_key(obj): + #attr_str = "" + #if attr_name != "__init__": + attr_str = ".prototype.__class__." + attr_name + call_name = UU+self.imported_classes[obj] + '.__' + obj + attr_str + elif obj in self.module_imports(): + call_name = obj + "." + attr_name + elif obj[0] == obj[0].upper(): # XXX HACK ALERT + call_name = UU + self.modpfx() + "__" + obj + ".prototype.__class__." + attr_name + else: + call_name = UU+self._name(v, current_klass) + "." + attr_name + + return call_name + + + def _getattr2(self, v, current_klass, attr_name): + if isinstance(v.expr, ast.Getattr): + call_name = self._getattr2(v.expr, current_klass, v.attrname + "." + attr_name) + elif isinstance(v.expr, ast.Name) and v.expr.name in self.module_imports(): + call_name = UU+v.expr.name + '.__' +v.attrname+".prototype.__class__."+attr_name + else: + obj = self.expr(v.expr, current_klass) + call_name = obj + "." + v.attrname + "." + attr_name + + return call_name + + + def _class(self, node): + """ + Handle a class definition. + + In order to translate python semantics reasonably well, the following + structure is used: + + A special object is created for the class, which inherits attributes + from the superclass, or Object if there's no superclass. This is the + class object; the object which you refer to when specifying the + class by name. Static, class, and unbound methods are copied + from the superclass object. + + A special constructor function is created with the same name as the + class, which is used to create instances of that class. + + A javascript class (e.g. a function with a prototype attribute) is + created which is the javascript class of created instances, and + which inherits attributes from the class object. Bound methods are + copied from the superclass into this class rather than inherited, + because the class object contains unbound, class, and static methods + that we don't necessarily want to inherit. + + The type of a method can now be determined by inspecting its + static_method, unbound_method, class_method, or instance_method + attribute; only one of these should be true. + + Much of this work is done in pyjs_extend, is pyjslib.py + """ + class_name = self.modpfx() + uuprefix(node.name, 1) + class_name_ = self.modpfx() + uuprefix(node.name) + current_klass = Klass(class_name, class_name_) + init_method = None + for child in node.code: + if isinstance(child, ast.Function): + current_klass.add_function(child.name) + if child.name == "__init__": + init_method = child + + + if len(node.bases) == 0: + base_class = "pyjslib.__Object" + elif len(node.bases) == 1: + if isinstance(node.bases[0], ast.Name): + if self.imported_classes.has_key(node.bases[0].name): + base_class_ = self.imported_classes[node.bases[0].name] + '.__' + node.bases[0].name + base_class = self.imported_classes[node.bases[0].name] + '.' + node.bases[0].name + else: + base_class_ = self.modpfx() + "__" + node.bases[0].name + base_class = self.modpfx() + node.bases[0].name + elif isinstance(node.bases[0], ast.Getattr): + # the bases are not in scope of the class so do not + # pass our class to self._name + base_class_ = self._name(node.bases[0].expr, None) + \ + ".__" + node.bases[0].attrname + base_class = self._name(node.bases[0].expr, None) + \ + "." + node.bases[0].attrname + else: + raise TranslationError("unsupported type (in _class)", node.bases[0]) + + current_klass.set_base(base_class) + else: + raise TranslationError("more than one base (in _class)", node) + + print >>self.output, UU+class_name_ + " = function () {" + # call superconstructor + #if base_class: + # print >>self.output, " __" + base_class + ".call(this);" + print >>self.output, "}" + + if not init_method: + init_method = ast.Function([], "__init__", ["self"], [], 0, None, []) + #self._method(init_method, current_klass, class_name) + + # Generate a function which constructs the object + clsfunc = ast.Function([], + node.name, + init_method.argnames[1:], + init_method.defaults, + init_method.flags, + None, + [ast.Discard(ast.CallFunc(ast.Name("JS"), [ast.Const( +# I attempted lazy initialization, but then you can't access static class members +# " if(!__"+base_class+".__was_initialized__)"+ +# " __" + class_name + "_initialize();\n" + + " var instance = new " + UU + class_name_ + "();\n" + + " if(instance.__init__) instance.__init__.apply(instance, arguments);\n" + + " return instance;" + )]))]) + + self._function(clsfunc, False) + print >>self.output, UU+class_name_ + ".__initialize__ = function () {" + print >>self.output, " if("+UU+class_name_+".__was_initialized__) return;" + print >>self.output, " "+UU+class_name_+".__was_initialized__ = true;" + cls_obj = UU+class_name_ + '.prototype.__class__' + + if class_name == "pyjslib.__Object": + print >>self.output, " "+cls_obj+" = {};" + else: + if base_class and base_class not in ("object", "pyjslib.__Object"): + print >>self.output, " if(!"+UU+base_class_+".__was_initialized__)" + print >>self.output, " "+UU+base_class_+".__initialize__();" + print >>self.output, " pyjs_extend(" + UU+class_name_ + ", "+UU+base_class_+");" + else: + print >>self.output, " pyjs_extend(" + UU+class_name_ + ", "+UU+"pyjslib.__Object);" + + print >>self.output, " "+cls_obj+".__new__ = "+UU+class_name+";" + print >>self.output, " "+cls_obj+".__name__ = '"+UU+node.name+"';" + + for child in node.code: + if isinstance(child, ast.Pass): + pass + elif isinstance(child, ast.Function): + self._method(child, current_klass, class_name, class_name_) + elif isinstance(child, ast.Assign): + self.classattr(child, current_klass) + elif isinstance(child, ast.Discard) and isinstance(child.expr, ast.Const): + # Probably a docstring, turf it + pass + else: + raise TranslationError("unsupported type (in _class)", child) + print >>self.output, "}" + + print >> self.output, class_name_+".__initialize__();" + + + def classattr(self, node, current_klass): + self._assign(node, current_klass, True) + + def _raise(self, node, current_klass): + if node.expr2: + raise TranslationError("More than one expression unsupported", + node) + print >> self.output, "throw (%s);" % self.expr( + node.expr1, current_klass) + + def _method(self, node, current_klass, class_name, class_name_): + # reset global var scope + self.method_imported_globals = set() + + arg_names = list(node.argnames) + + classmethod = False + staticmethod = False + if node.decorators: + for d in node.decorators: + if d.name == "classmethod": + classmethod = True + elif d.name == "staticmethod": + staticmethod = True + + if staticmethod: + staticfunc = ast.Function([], class_name_+"."+node.name, node.argnames, node.defaults, node.flags, node.doc, node.code, node.lineno) + self._function(staticfunc, True) + print >>self.output, " " + UU+class_name_ + ".prototype.__class__." + node.name + " = " + class_name_+"."+node.name+";"; + print >>self.output, " " + UU+class_name_ + ".prototype.__class__." + node.name + ".static_method = true;"; + return + else: + if len(arg_names) == 0: + raise TranslationError("methods must take an argument 'self' (in _method)", node) + self.method_self = arg_names[0] + + #if not classmethod and arg_names[0] != "self": + # raise TranslationError("first arg not 'self' (in _method)", node) + + normal_arg_names = arg_names[1:] + if node.kwargs: kwargname = normal_arg_names.pop() + if node.varargs: varargname = normal_arg_names.pop() + declared_arg_names = list(normal_arg_names) + if node.kwargs: declared_arg_names.append(kwargname) + + function_args = "(" + ", ".join(declared_arg_names) + ")" + + if classmethod: + fexpr = UU + class_name_ + ".prototype.__class__." + node.name + else: + fexpr = UU + class_name_ + ".prototype." + node.name + print >>self.output, " "+fexpr + " = function" + function_args + " {" + + # default arguments + self._default_args_handler(node, normal_arg_names, current_klass) + + local_arg_names = normal_arg_names + declared_arg_names + + if node.varargs: + self._varargs_handler(node, varargname, declared_arg_names, current_klass) + local_arg_names.append(varargname) + + + # stack of local variable names for this function call + self.local_arg_stack.append(local_arg_names) + + for child in node.code: + self._stmt(child, current_klass) + + # remove the top local arg names + self.local_arg_stack.pop() + + print >>self.output, " };" + + self._kwargs_parser(node, fexpr, normal_arg_names, current_klass) + + if classmethod: + # Have to create a version on the instances which automatically passes the + # class as "self" + altexpr = UU + class_name_ + ".prototype." + node.name + print >>self.output, " "+altexpr + " = function() {" + print >>self.output, " return " + fexpr + ".apply(this.__class__, arguments);" + print >>self.output, " };" + print >>self.output, " "+fexpr+".class_method = true;" + print >>self.output, " "+altexpr+".instance_method = true;" + else: + # For instance methods, we need an unbound version in the class object + altexpr = UU + class_name_ + ".prototype.__class__." + node.name + print >>self.output, " "+altexpr + " = function() {" + print >>self.output, " return " + fexpr + ".call.apply("+fexpr+", arguments);" + print >>self.output, " };" + print >>self.output, " "+altexpr+".unbound_method = true;" + print >>self.output, " "+fexpr+".instance_method = true;" + print >>self.output, " "+altexpr+".__name__ = '%s';" % node.name + + print >>self.output, UU + class_name_ + ".prototype.%s.__name__ = '%s';" % \ + (node.name, node.name) + + if node.kwargs or len(node.defaults): + print >>self.output, " "+altexpr + ".parse_kwargs = " + fexpr + ".parse_kwargs;" + + self.method_self = None + self.method_imported_globals = set() + + def _isNativeFunc(self, node): + if isinstance(node, ast.Discard): + if isinstance(node.expr, ast.CallFunc): + if isinstance(node.expr.node, ast.Name) and \ + node.expr.node.name == NATIVE_JS_FUNC_NAME: + return True + return False + + def _stmt(self, node, current_klass): + debugStmt = self.debug and not self._isNativeFunc(node) + if debugStmt: + print >>self.output, ' try {' + + if isinstance(node, ast.Return): + self._return(node, current_klass) + elif isinstance(node, ast.Break): + self._break(node, current_klass) + elif isinstance(node, ast.Continue): + self._continue(node, current_klass) + elif isinstance(node, ast.Assign): + self._assign(node, current_klass) + elif isinstance(node, ast.AugAssign): + self._augassign(node, current_klass) + elif isinstance(node, ast.Discard): + self._discard(node, current_klass) + elif isinstance(node, ast.If): + self._if(node, current_klass) + elif isinstance(node, ast.For): + self._for(node, current_klass) + elif isinstance(node, ast.While): + self._while(node, current_klass) + elif isinstance(node, ast.Subscript): + self._subscript_stmt(node, current_klass) + elif isinstance(node, ast.Global): + self._global(node, current_klass) + elif isinstance(node, ast.Pass): + pass + elif isinstance(node, ast.Function): + self._function(node, True) + elif isinstance(node, ast.Printnl): + self._print(node, current_klass) + elif isinstance(node, ast.Print): + self._print(node, current_klass) + elif isinstance(node, ast.TryExcept): + self._tryExcept(node, current_klass) + elif isinstance(node, ast.Raise): + self._raise(node, current_klass) + else: + raise TranslationError("unsupported type (in _stmt)", node) + + if debugStmt: + + lt = self.get_line_trace(node) + + haltException = self.module_prefix + "HaltException" + isHaltFunction = self.module_prefix + "IsHaltException" + + print >>self.output, ' } catch (__err) {' + print >>self.output, ' if (' + isHaltFunction + '(__err.name)) {' + print >>self.output, ' throw __err;' + print >>self.output, ' } else {' + print >>self.output, " st = sys.printstack() + "\ + + '"%s"' % lt + "+ '\\n' ;" + print >>self.output, ' alert("' + "Error in " \ + + lt + '"' \ + + '+"\\n"+__err.name+": "+__err.message'\ + + '+"\\n\\nStack trace:\\n"' \ + + '+st' \ + + ');' + print >>self.output, ' debugger;' + + print >>self.output, ' throw new ' + self.module_prefix + "HaltException();" + print >>self.output, ' }' + print >>self.output, ' }' + + + def get_line_trace(self, node): + lineNum = "Unknown" + srcLine = "" + if hasattr(node, "lineno"): + if node.lineno != None: + lineNum = node.lineno + srcLine = self.src[min(lineNum, len(self.src))-1] + srcLine = srcLine.replace('\\', '\\\\') + srcLine = srcLine.replace('"', '\\"') + srcLine = srcLine.replace("'", "\\'") + + return self.raw_module_name + ".py, line " \ + + str(lineNum) + ":"\ + + "\\n" \ + + " " + srcLine + + def _augassign(self, node, current_klass): + v = node.node + if isinstance(v, ast.Getattr): + # XXX HACK! don't allow += on return result of getattr. + # TODO: create a temporary variable or something. + lhs = self._getattr(v, current_klass, False) + else: + lhs = self._name(node.node, current_klass) + op = node.op + rhs = self.expr(node.expr, current_klass) + print >>self.output, " " + lhs + " " + op + " " + rhs + ";" + + + def _assign(self, node, current_klass, top_level = False): + if len(node.nodes) != 1: + tempvar = '__temp'+str(node.lineno) + tnode = ast.Assign([ast.AssName(tempvar, "OP_ASSIGN", node.lineno)], node.expr, node.lineno) + self._assign(tnode, current_klass, top_level) + for v in node.nodes: + tnode2 = ast.Assign([v], ast.Name(tempvar, node.lineno), node.lineno) + self._assign(tnode2, current_klass, top_level) + return + + local_var_names = None + if len(self.local_arg_stack) > 0: + local_var_names = self.local_arg_stack[-1] + + def _lhsFromAttr(v, current_klass): + attr_name = v.attrname + if isinstance(v.expr, ast.Name): + obj = v.expr.name + lhs = self._name(v.expr, current_klass) + "." + attr_name + elif isinstance(v.expr, ast.Getattr): + lhs = self._getattr(v, current_klass) + elif isinstance(v.expr, ast.Subscript): + lhs = self._subscript(v.expr, current_klass) + "." + attr_name + else: + raise TranslationError("unsupported type (in _assign)", v.expr) + return lhs + + def _lhsFromName(v, top_level, current_klass): + if top_level: + if current_klass: + lhs = UU+current_klass.name_ + ".prototype.__class__." \ + + v.name + else: + self.top_level_vars.add(v.name) + vname = self.modpfx() + v.name + if not self.modpfx() and v.name not in\ + self.method_imported_globals: + lhs = "var " + vname + else: + lhs = UU + vname + self.add_local_arg(v.name) + else: + if v.name in local_var_names: + lhs = v.name + elif v.name in self.method_imported_globals: + lhs = self.modpfx() + v.name + else: + lhs = "var " + v.name + self.add_local_arg(v.name) + return lhs + + dbg = 0 + v = node.nodes[0] + if isinstance(v, ast.AssAttr): + lhs = _lhsFromAttr(v, current_klass) + if v.flags == "OP_ASSIGN": + op = "=" + else: + raise TranslationError("unsupported flag (in _assign)", v) + + elif isinstance(v, ast.AssName): + lhs = _lhsFromName(v, top_level, current_klass) + if v.flags == "OP_ASSIGN": + op = "=" + else: + raise TranslationError("unsupported flag (in _assign)", v) + elif isinstance(v, ast.Subscript): + if v.flags == "OP_ASSIGN": + obj = self.expr(v.expr, current_klass) + if len(v.subs) != 1: + raise TranslationError("must have one sub (in _assign)", v) + idx = self.expr(v.subs[0], current_klass) + value = self.expr(node.expr, current_klass) + print >>self.output, " " + obj + ".__setitem__(" + idx + ", " + value + ");" + return + else: + raise TranslationError("unsupported flag (in _assign)", v) + elif isinstance(v, (ast.AssList, ast.AssTuple)): + uniqueID = self.nextTupleAssignID + self.nextTupleAssignID += 1 + tempName = "__tupleassign" + str(uniqueID) + "__" + print >>self.output, " var " + tempName + " = " + \ + self.expr(node.expr, current_klass) + ";" + for index,child in enumerate(v.getChildNodes()): + rhs = tempName + ".__getitem__(" + str(index) + ")" + + if isinstance(child, ast.AssAttr): + lhs = _lhsFromAttr(child, current_klass) + elif isinstance(child, ast.AssName): + lhs = _lhsFromName(child, top_level, current_klass) + elif isinstance(child, ast.Subscript): + if child.flags == "OP_ASSIGN": + obj = self.expr(child.expr, current_klass) + if len(child.subs) != 1: + raise TranslationError("must have one sub " + + "(in _assign)", child) + idx = self.expr(child.subs[0], current_klass) + value = self.expr(node.expr, current_klass) + print >>self.output, " " + obj + ".__setitem__(" \ + + idx + ", " + rhs + ");" + continue + print >>self.output, " " + lhs + " = " + rhs + ";" + return + else: + raise TranslationError("unsupported type (in _assign)", v) + + rhs = self.expr(node.expr, current_klass) + if dbg: + print "b", repr(node.expr), rhs + print >>self.output, " " + lhs + " " + op + " " + rhs + ";" + + + def _discard(self, node, current_klass): + + if isinstance(node.expr, ast.CallFunc): + debugStmt = self.debug and not self._isNativeFunc(node) + if debugStmt and isinstance(node.expr.node, ast.Name) and \ + node.expr.node.name == 'import_wait': + debugStmt = False + if debugStmt: + st = self.get_line_trace(node) + print >>self.output, "sys.addstack('%s');\n" % st + if isinstance(node.expr.node, ast.Name) and node.expr.node.name == NATIVE_JS_FUNC_NAME: + if len(node.expr.args) != 1: + raise TranslationError("native javascript function %s must have one arg" % NATIVE_JS_FUNC_NAME, node.expr) + if not isinstance(node.expr.args[0], ast.Const): + raise TranslationError("native javascript function %s must have constant arg" % NATIVE_JS_FUNC_NAME, node.expr) + raw_js = node.expr.args[0].value + print >>self.output, raw_js + else: + expr = self._callfunc(node.expr, current_klass) + print >>self.output, " " + expr + ";" + + if debugStmt: + print >>self.output, "sys.popstack();\n" + + elif isinstance(node.expr, ast.Const): + if node.expr.value is not None: # Empty statements generate ignore None + print >>self.output, self._const(node.expr) + else: + raise TranslationError("unsupported type (in _discard)", node.expr) + + + def _if(self, node, current_klass): + for i in range(len(node.tests)): + test, consequence = node.tests[i] + if i == 0: + keyword = "if" + else: + keyword = "else if" + + self._if_test(keyword, test, consequence, current_klass) + + if node.else_: + keyword = "else" + test = None + consequence = node.else_ + + self._if_test(keyword, test, consequence, current_klass) + + + def _if_test(self, keyword, test, consequence, current_klass): + if test: + expr = self.expr(test, current_klass) + + print >>self.output, " " + keyword + " (pyjslib.bool(" + expr + ")) {" + else: + print >>self.output, " " + keyword + " {" + + if isinstance(consequence, ast.Stmt): + for child in consequence.nodes: + self._stmt(child, current_klass) + else: + raise TranslationError("unsupported type (in _if_test)", consequence) + + print >>self.output, " }" + + + def _from(self, node): + for name in node.names: + # look up "hack" in AppTranslator as to how findFile gets here + module_name = node.modname + "." + name[0] + try: + ff = self.findFile(module_name + ".py") + except Exception: + ff = None + if ff: + self.add_imported_module(module_name) + else: + self.imported_classes[name[0]] = node.modname + + + def _compare(self, node, current_klass): + lhs = self.expr(node.expr, current_klass) + + if len(node.ops) != 1: + raise TranslationError("only one ops supported (in _compare)", node) + + op = node.ops[0][0] + rhs_node = node.ops[0][1] + rhs = self.expr(rhs_node, current_klass) + + if op == "==": + return "pyjslib.eq(%s, %s)" % (lhs, rhs) + if op == "in": + return rhs + ".__contains__(" + lhs + ")" + elif op == "not in": + return "!" + rhs + ".__contains__(" + lhs + ")" + elif op == "is": + op = "===" + elif op == "is not": + op = "!==" + + return "(" + lhs + " " + op + " " + rhs + ")" + + + def _not(self, node, current_klass): + expr = self.expr(node.expr, current_klass) + + return "!(" + expr + ")" + + def _or(self, node, current_klass): + expr = "("+(") || (".join([self.expr(child, current_klass) for child in node.nodes]))+')' + return expr + + def _and(self, node, current_klass): + expr = "("+(") && (".join([self.expr(child, current_klass) for child in node.nodes]))+")" + return expr + + def _for(self, node, current_klass): + assign_name = "" + assign_tuple = "" + + # based on Bob Ippolito's Iteration in Javascript code + if isinstance(node.assign, ast.AssName): + assign_name = node.assign.name + self.add_local_arg(assign_name) + if node.assign.flags == "OP_ASSIGN": + op = "=" + elif isinstance(node.assign, ast.AssTuple): + op = "=" + i = 0 + for child in node.assign: + child_name = child.name + if assign_name == "": + assign_name = "temp_" + child_name + self.add_local_arg(child_name) + assign_tuple += """ + var %(child_name)s %(op)s %(assign_name)s.__getitem__(%(i)i); + """ % locals() + i += 1 + else: + raise TranslationError("unsupported type (in _for)", node.assign) + + if isinstance(node.list, ast.Name): + list_expr = self._name(node.list, current_klass) + elif isinstance(node.list, ast.Getattr): + list_expr = self._getattr(node.list, current_klass) + elif isinstance(node.list, ast.CallFunc): + list_expr = self._callfunc(node.list, current_klass) + else: + raise TranslationError("unsupported type (in _for)", node.list) + + lhs = "var " + assign_name + iterator_name = "__" + assign_name + + print >>self.output, """ + var %(iterator_name)s = %(list_expr)s.__iter__(); + try { + while (true) { + %(lhs)s %(op)s %(iterator_name)s.next(); + %(assign_tuple)s + """ % locals() + for node in node.body.nodes: + self._stmt(node, current_klass) + print >>self.output, """ + } + } catch (e) { + if (e.__name__ != pyjslib.StopIteration.__name__) { + throw e; + } + } + """ % locals() + + + def _while(self, node, current_klass): + test = self.expr(node.test, current_klass) + print >>self.output, " while (pyjslib.bool(" + test + ")) {" + if isinstance(node.body, ast.Stmt): + for child in node.body.nodes: + self._stmt(child, current_klass) + else: + raise TranslationError("unsupported type (in _while)", node.body) + print >>self.output, " }" + + + def _const(self, node): + if isinstance(node.value, int): + return str(node.value) + elif isinstance(node.value, float): + return str(node.value) + elif isinstance(node.value, basestring): + v = node.value + if isinstance(node.value, unicode): + v = v.encode('utf-8') + return "String('%s')" % escapejs(v) + elif node.value is None: + return "null" + else: + raise TranslationError("unsupported type (in _const)", node) + + def _unaryadd(self, node, current_klass): + return self.expr(node.expr, current_klass) + + def _unarysub(self, node, current_klass): + return "-" + self.expr(node.expr, current_klass) + + def _add(self, node, current_klass): + return self.expr(node.left, current_klass) + " + " + self.expr(node.right, current_klass) + + def _sub(self, node, current_klass): + return self.expr(node.left, current_klass) + " - " + self.expr(node.right, current_klass) + + def _div(self, node, current_klass): + return self.expr(node.left, current_klass) + " / " + self.expr(node.right, current_klass) + + def _mul(self, node, current_klass): + return self.expr(node.left, current_klass) + " * " + self.expr(node.right, current_klass) + + def _mod(self, node, current_klass): + if isinstance(node.left, ast.Const) and isinstance(node.left.value, StringType): + self.imported_js.add("sprintf.js") # Include the sprintf functionality if it is used + return "sprintf("+self.expr(node.left, current_klass) + ", " + self.expr(node.right, current_klass)+")" + return self.expr(node.left, current_klass) + " % " + self.expr(node.right, current_klass) + + def _invert(self, node, current_klass): + return "~" + self.expr(node.expr, current_klass) + + def _bitand(self, node, current_klass): + return " & ".join([self.expr(child, current_klass) for child in node.nodes]) + + def _bitshiftleft(self, node, current_klass): + return self.expr(node.left, current_klass) + " << " + self.expr(node.right, current_klass) + + def _bitshiftright(self, node, current_klass): + return self.expr(node.left, current_klass) + " >>> " + self.expr(node.right, current_klass) + + def _bitxor(self,node, current_klass): + return " ^ ".join([self.expr(child, current_klass) for child in node.nodes]) + + def _bitor(self, node, current_klass): + return " | ".join([self.expr(child, current_klass) for child in node.nodes]) + + def _subscript(self, node, current_klass): + if node.flags == "OP_APPLY": + if len(node.subs) == 1: + return self.expr(node.expr, current_klass) + ".__getitem__(" + self.expr(node.subs[0], current_klass) + ")" + else: + raise TranslationError("must have one sub (in _subscript)", node) + else: + raise TranslationError("unsupported flag (in _subscript)", node) + + def _subscript_stmt(self, node, current_klass): + if node.flags == "OP_DELETE": + print >>self.output, " " + self.expr(node.expr, current_klass) + ".__delitem__(" + self.expr(node.subs[0], current_klass) + ");" + else: + raise TranslationError("unsupported flag (in _subscript)", node) + + def _list(self, node, current_klass): + return "new pyjslib.List([" + ", ".join([self.expr(x, current_klass) for x in node.nodes]) + "])" + + def _dict(self, node, current_klass): + items = [] + for x in node.items: + key = self.expr(x[0], current_klass) + value = self.expr(x[1], current_klass) + items.append("[" + key + ", " + value + "]") + return "new pyjslib.Dict([" + ", ".join(items) + "])" + + def _tuple(self, node, current_klass): + return "new pyjslib.Tuple([" + ", ".join([self.expr(x, current_klass) for x in node.nodes]) + "])" + + def _lambda(self, node, current_klass): + if node.varargs: + raise TranslationError("varargs are not supported in Lambdas", node) + if node.kwargs: + raise TranslationError("kwargs are not supported in Lambdas", node) + res = cStringIO.StringIO() + arg_names = list(node.argnames) + function_args = ", ".join(arg_names) + for child in node.getChildNodes(): + expr = self.expr(child, None) + print >> res, "function (%s){" % function_args + self._default_args_handler(node, arg_names, None, + output=res) + print >> res, 'return %s;}' % expr + return res.getvalue() + + def _slice(self, node, current_klass): + if node.flags == "OP_APPLY": + lower = "null" + upper = "null" + if node.lower != None: + lower = self.expr(node.lower, current_klass) + if node.upper != None: + upper = self.expr(node.upper, current_klass) + return "pyjslib.slice(" + self.expr(node.expr, current_klass) + ", " + lower + ", " + upper + ")" + else: + raise TranslationError("unsupported flag (in _slice)", node) + + def _global(self, node, current_klass): + for name in node.names: + self.method_imported_globals.add(name) + + def expr(self, node, current_klass): + if isinstance(node, ast.Const): + return self._const(node) + # @@@ not sure if the parentheses should be here or in individual operator functions - JKT + elif isinstance(node, ast.Mul): + return " ( " + self._mul(node, current_klass) + " ) " + elif isinstance(node, ast.Add): + return " ( " + self._add(node, current_klass) + " ) " + elif isinstance(node, ast.Sub): + return " ( " + self._sub(node, current_klass) + " ) " + elif isinstance(node, ast.Div): + return " ( " + self._div(node, current_klass) + " ) " + elif isinstance(node, ast.Mod): + return self._mod(node, current_klass) + elif isinstance(node, ast.UnaryAdd): + return self._unaryadd(node, current_klass) + elif isinstance(node, ast.UnarySub): + return self._unarysub(node, current_klass) + elif isinstance(node, ast.Not): + return self._not(node, current_klass) + elif isinstance(node, ast.Or): + return self._or(node, current_klass) + elif isinstance(node, ast.And): + return self._and(node, current_klass) + elif isinstance(node, ast.Invert): + return self._invert(node, current_klass) + elif isinstance(node, ast.Bitand): + return "("+self._bitand(node, current_klass)+")" + elif isinstance(node,ast.LeftShift): + return self._bitshiftleft(node, current_klass) + elif isinstance(node, ast.RightShift): + return self._bitshiftright(node, current_klass) + elif isinstance(node, ast.Bitxor): + return "("+self._bitxor(node, current_klass)+")" + elif isinstance(node, ast.Bitor): + return "("+self._bitor(node, current_klass)+")" + elif isinstance(node, ast.Compare): + return self._compare(node, current_klass) + elif isinstance(node, ast.CallFunc): + return self._callfunc(node, current_klass) + elif isinstance(node, ast.Name): + return self._name(node, current_klass) + elif isinstance(node, ast.Subscript): + return self._subscript(node, current_klass) + elif isinstance(node, ast.Getattr): + return self._getattr(node, current_klass) + elif isinstance(node, ast.List): + return self._list(node, current_klass) + elif isinstance(node, ast.Dict): + return self._dict(node, current_klass) + elif isinstance(node, ast.Tuple): + return self._tuple(node, current_klass) + elif isinstance(node, ast.Slice): + return self._slice(node, current_klass) + elif isinstance(node, ast.Lambda): + return self._lambda(node, current_klass) + else: + raise TranslationError("unsupported type (in expr)", node) + + + +import cStringIO + +def translate(file_name, module_name, debug=False): + f = file(file_name, "r") + src = f.read() + f.close() + output = cStringIO.StringIO() + mod = compiler.parseFile(file_name) + t = Translator(module_name, module_name, module_name, src, debug, mod, output) + return output.getvalue() + + +class PlatformParser: + def __init__(self, platform_dir = "", verbose=True): + self.platform_dir = platform_dir + self.parse_cache = {} + self.platform = "" + self.verbose = verbose + + def setPlatform(self, platform): + self.platform = platform + + def parseModule(self, module_name, file_name): + + importing = False + if not self.parse_cache.has_key(file_name): + importing = True + mod = compiler.parseFile(file_name) + self.parse_cache[file_name] = mod + else: + mod = self.parse_cache[file_name] + + override = False + platform_file_name = self.generatePlatformFilename(file_name) + if self.platform and os.path.isfile(platform_file_name): + mod = copy.deepcopy(mod) + mod_override = compiler.parseFile(platform_file_name) + self.merge(mod, mod_override) + override = True + + if self.verbose: + if override: + print "Importing %s (Platform %s)" % (module_name, self.platform) + elif importing: + print "Importing %s" % (module_name) + + return mod, override + + def generatePlatformFilename(self, file_name): + (module_name, extension) = os.path.splitext(os.path.basename(file_name)) + platform_file_name = module_name + self.platform + extension + + return os.path.join(os.path.dirname(file_name), self.platform_dir, platform_file_name) + + def merge(self, tree1, tree2): + for child in tree2.node: + if isinstance(child, ast.Function): + self.replaceFunction(tree1, child.name, child) + elif isinstance(child, ast.Class): + self.replaceClassMethods(tree1, child.name, child) + + return tree1 + + def replaceFunction(self, tree, function_name, function_node): + # find function to replace + for child in tree.node: + if isinstance(child, ast.Function) and child.name == function_name: + self.copyFunction(child, function_node) + return + raise TranslationError("function not found: " + function_name, function_node) + + def replaceClassMethods(self, tree, class_name, class_node): + # find class to replace + old_class_node = None + for child in tree.node: + if isinstance(child, ast.Class) and child.name == class_name: + old_class_node = child + break + + if not old_class_node: + raise TranslationError("class not found: " + class_name, class_node) + + # replace methods + for function_node in class_node.code: + if isinstance(function_node, ast.Function): + found = False + for child in old_class_node.code: + if isinstance(child, ast.Function) and child.name == function_node.name: + found = True + self.copyFunction(child, function_node) + break + + if not found: + raise TranslationError("class method not found: " + class_name + "." + function_node.name, function_node) + + def copyFunction(self, target, source): + target.code = source.code + target.argnames = source.argnames + target.defaults = source.defaults + target.doc = source.doc # @@@ not sure we need to do this any more + +def dotreplace(fname): + path, ext = os.path.splitext(fname) + return path.replace(".", "/") + ext + +class AppTranslator: + + def __init__(self, library_dirs=[], parser=None, dynamic=False, + optimize=False, verbose=True): + self.extension = ".py" + self.optimize = optimize + self.library_modules = [] + self.overrides = {} + self.library_dirs = path + library_dirs + self.dynamic = dynamic + self.verbose = verbose + + if not parser: + self.parser = PlatformParser() + else: + self.parser = parser + + self.parser.dynamic = dynamic + + def findFile(self, file_name): + if os.path.isfile(file_name): + return file_name + + for library_dir in self.library_dirs: + file_name = dotreplace(file_name) + full_file_name = os.path.join( + os.path.abspath(os.path.dirname(__file__)), library_dir, file_name) + if os.path.isfile(full_file_name): + return full_file_name + + fnameinit, ext = os.path.splitext(file_name) + fnameinit = fnameinit + "/__init__.py" + + full_file_name = os.path.join( + os.path.abspath(os.path.dirname(__file__)), library_dir, fnameinit) + if os.path.isfile(full_file_name): + return full_file_name + + raise Exception("file not found: " + file_name) + + def _translate(self, module_name, is_app=True, debug=False, + imported_js=set()): + if module_name not in self.library_modules: + self.library_modules.append(module_name) + + file_name = self.findFile(module_name + self.extension) + + output = cStringIO.StringIO() + + f = file(file_name, "r") + src = f.read() + f.close() + + mod, override = self.parser.parseModule(module_name, file_name) + if override: + override_name = "%s.%s" % (self.parser.platform.lower(), + module_name) + self.overrides[override_name] = override_name + if is_app: + mn = '__main__' + else: + mn = module_name + t = Translator(mn, module_name, module_name, + src, debug, mod, output, self.dynamic, self.optimize, + self.findFile) + + module_str = output.getvalue() + imported_js.update(set(t.imported_js)) + imported_modules_str = "" + for module in t.imported_modules: + if module not in self.library_modules: + self.library_modules.append(module) + #imported_js.update(set(t.imported_js)) + #imported_modules_str += self._translate( + # module, False, debug=debug, imported_js=imported_js) + + return imported_modules_str + module_str + + + def translate(self, module_name, is_app=True, debug=False, + library_modules=[]): + app_code = cStringIO.StringIO() + lib_code = cStringIO.StringIO() + imported_js = set() + self.library_modules = [] + self.overrides = {} + for library in library_modules: + if library.endswith(".js"): + imported_js.add(library) + continue + self.library_modules.append(library) + if self.verbose: + print 'Including LIB', library + print >> lib_code, '\n//\n// BEGIN LIB '+library+'\n//\n' + print >> lib_code, self._translate( + library, False, debug=debug, imported_js=imported_js) + + print >> lib_code, "/* initialize static library */" + print >> lib_code, "%s%s();\n" % (UU, library) + + print >> lib_code, '\n//\n// END LIB '+library+'\n//\n' + if module_name: + print >> app_code, self._translate( + module_name, is_app, debug=debug, imported_js=imported_js) + for js in imported_js: + path = self.findFile(js) + if os.path.isfile(path): + if self.verbose: + print 'Including JS', js + print >> lib_code, '\n//\n// BEGIN JS '+js+'\n//\n' + print >> lib_code, file(path).read() + print >> lib_code, '\n//\n// END JS '+js+'\n//\n' + else: + print >>sys.stderr, 'Warning: Unable to find imported javascript:', js + return lib_code.getvalue(), app_code.getvalue() + +usage = """ + usage: %s file_name [module_name] +""" + +def main(): + import sys + if len(sys.argv)<2: + print >> sys.stderr, usage % sys.argv[0] + sys.exit(1) + file_name = os.path.abspath(sys.argv[1]) + if not os.path.isfile(file_name): + print >> sys.stderr, "File not found %s" % file_name + sys.exit(1) + if len(sys.argv) > 2: + module_name = sys.argv[2] + else: + module_name = None + print translate(file_name, module_name), + +if __name__ == "__main__": + main() + diff -r 3edd2f19bce2 -r e0424e96e3fd svgui/svgui.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/svgui/svgui.py Sat May 12 11:21:10 2012 +0200 @@ -0,0 +1,116 @@ +import wx +import os, sys, shutil + +from pyjs import translate + +from POULibrary import POULibrary +from docutils import * + +class SVGUILibrary(POULibrary): + def GetName(self): + return "SVGUI" + def GetLibraryPath(self): + return os.path.join(os.path.split(__file__)[0], "pous.xml") + +class SVGUI: + + ConfNodeMethods = [ + {"bitmap" : os.path.join("images","ImportSVG"), + "name" : _("Import SVG"), + "tooltip" : _("Import SVG"), + "method" : "_ImportSVG"}, + {"bitmap" : os.path.join("images","ImportSVG"), + "name" : _("Inkscape"), + "tooltip" : _("Create HMI"), + "method" : "_StartInkscape"}, + ] + + def ConfNodePath(self): + return os.path.join(os.path.dirname(__file__)) + + def _getSVGpath(self): + # define name for IEC raw code file + return os.path.join(self.CTNPath(), "gui.svg") + + def _getSVGUIserverpath(self): + return os.path.join(os.path.dirname(__file__), "svgui_server.py") + + def CTNGenerate_C(self, buildpath, locations): + """ + Return C code generated by iec2c compiler + when _generate_softPLC have been called + @param locations: ignored + @return: [(C_file_name, CFLAGS),...] , LDFLAGS_TO_APPEND + """ + + current_location = self.GetCurrentLocation() + # define a unique name for the generated C file + location_str = "_".join(map(lambda x:str(x), current_location)) + + res = ([], "", False) + + svgfile=self._getSVGpath() + if os.path.exists(svgfile): + res += (("gui.svg", file(svgfile,"rb")),) + + svguiserverfile = open(self._getSVGUIserverpath(), 'r') + svguiservercode = svguiserverfile.read() + svguiserverfile.close() + + svguilibpath = os.path.join(self._getBuildPath(), "svguilib.js") + svguilibfile = open(svguilibpath, 'w') + svguilibfile.write(translate(os.path.join(os.path.dirname(__file__), "pyjs", "lib", "sys.py"), "sys")) + svguilibfile.write(open(os.path.join(os.path.dirname(__file__), "pyjs", "lib", "_pyjs.js"), 'r').read()) + svguilibfile.write(translate(os.path.join(os.path.dirname(__file__), "pyjs", "lib", "pyjslib.py"), "pyjslib")) + svguilibfile.write(translate(os.path.join(os.path.dirname(__file__), "svguilib.py"), "svguilib")) + svguilibfile.write("pyjslib();\nsvguilib();\n") + svguilibfile.write(open(os.path.join(os.path.dirname(__file__), "pyjs", "lib", "json.js"), 'r').read()) + svguilibfile.write(open(os.path.join(os.path.dirname(__file__), "livesvg.js"), 'r').read()) + svguilibfile.close() + jsmodules = {"LiveSVGPage": "svguilib.js"} + res += (("svguilib.js", file(svguilibpath,"rb")),) + + runtimefile_path = os.path.join(buildpath, "runtime_%s.py"%location_str) + runtimefile = open(runtimefile_path, 'w') + runtimefile.write(svguiservercode % {"svgfile" : "gui.svg"}) + runtimefile.write(""" +def _runtime_%(location)s_begin(): + website.LoadHMI(%(svgui_class)s, %(jsmodules)s) + +def _runtime_%(location)s_cleanup(): + website.UnLoadHMI() + +""" % {"location": location_str, + "svgui_class": "SVGUI_HMI", + "jsmodules" : str(jsmodules), + }) + runtimefile.close() + + res += (("runtime_%s.py"%location_str, file(runtimefile_path,"rb")),) + + return res + + def _ImportSVG(self): + dialog = wx.FileDialog(self.GetCTRoot().AppFrame, _("Choose a SVG file"), os.getcwd(), "", _("SVG files (*.svg)|*.svg|All files|*.*"), wx.OPEN) + if dialog.ShowModal() == wx.ID_OK: + svgpath = dialog.GetPath() + if os.path.isfile(svgpath): + shutil.copy(svgpath, self._getSVGpath()) + else: + self.GetCTRoot().logger.write_error(_("No such SVG file: %s\n")%svgpath) + dialog.Destroy() + + def _StartInkscape(self): + svgfile = self._getSVGpath() + open_inkscape = True + if not self.GetCTRoot().CheckProjectPathPerm(): + dialog = wx.MessageDialog(self.GetCTRoot().AppFrame, + _("You don't have write permissions.\nOpen Inkscape anyway ?"), + _("Open Inkscape"), + wx.YES_NO|wx.ICON_QUESTION) + open_inkscape = dialog.ShowModal() == wx.ID_YES + dialog.Destroy() + if open_inkscape: + if not os.path.isfile(svgfile): + svgfile = None + open_svg(svgfile) diff -r 3edd2f19bce2 -r e0424e96e3fd svgui/svgui_server.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/svgui/svgui_server.py Sat May 12 11:21:10 2012 +0200 @@ -0,0 +1,130 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +import os + +from nevow import rend, appserver, inevow, tags, loaders, athena +import simplejson as json + +svgfile = '%(svgfile)s' + +svguiWidgets = {} + +currentId = 0 +def getNewId(): + global currentId + currentId += 1 + return currentId + +class SvguiWidget: + + def __init__(self, classname, id, **kwargs): + self.classname = classname + self.id = id + self.attrs = kwargs.copy() + self.inputs = {} + self.outputs = {} + self.inhibit = False + self.changed = False + + def setinput(self, attrname, value): + self.inputs[attrname] = value + + def getinput(self, attrname, default=None): + if not self.inputs.has_key(attrname): + self.inputs[attrname] = default + return self.inputs[attrname] + + def setoutput(self, attrname, value): + if self.outputs.get(attrname) != value: + self.outputs[attrname] = value + self.changed = True + self.RefreshInterface() + + def updateoutputs(self, **kwargs): + for attrname, value in kwargs.iteritems(): + if self.outputs.get(attrname) != value: + self.outputs[attrname] = value + self.changed = True + self.RefreshInterface() + + def RefreshInterface(self): + interface = website.getHMI() + if isinstance(interface, SVGUI_HMI) and self.changed and not self.inhibit: + self.changed = False + d = interface.sendData(self) + if d is not None: + self.inhibit = True + d.addCallback(self.InterfaceRefreshed) + + def InterfaceRefreshed(self, result): + self.inhibit = False + if self.changed: + self.RefreshInterface() + +def get_object_init_state(obj): + # Convert objects to a dictionary of their representation + attrs = obj.attrs.copy() + attrs.update(obj.inputs) + d = { '__class__': obj.classname, + 'id': obj.id, + 'kwargs': json.dumps(attrs), + } + return d + +def get_object_current_state(obj): + # Convert objects to a dictionary of their representation + d = { '__class__': obj.classname, + 'id': obj.id, + 'kwargs': json.dumps(obj.outputs), + } + return d + +class SVGUI_HMI(website.PLCHMI): + jsClass = u"LiveSVGPage.LiveSVGWidget" + + docFactory = loaders.stan(tags.div(render=tags.directive('liveElement'))[ + tags.xml(loaders.xmlfile(os.path.join(WorkingDir, svgfile))), + ]) + + def HMIinitialisation(self): + gadgets = [] + for gadget in svguiWidgets.values(): + gadgets.append(unicode(json.dumps(gadget, default=get_object_init_state, indent=2), 'ascii')) + d = self.callRemote('init', gadgets) + d.addCallback(self.HMIinitialised) + + def sendData(self,data): + if self.initialised: + return self.callRemote('receiveData',unicode(json.dumps(data, default=get_object_current_state, indent=2), 'ascii')) + return None + + def setattr(self, id, attrname, value): + svguiWidgets[id].setinput(attrname, value) + +def createSVGUIControl(*args, **kwargs): + id = getNewId() + gad = SvguiWidget(args[0], id, **kwargs) + svguiWidgets[id] = gad + gadget = [unicode(json.dumps(gad, default=get_object_init_state, indent=2), 'ascii')] + interface = website.getHMI() + if isinstance(interface, SVGUI_HMI) and interface.initialised: + interface.callRemote('init', gadget) + return id + +def setAttr(id, attrname, value): + gad = svguiWidgets.get(id, None) + if gad is not None: + gad.setoutput(attrname, value) + +def updateAttr(id, **kwargs): + gad = svguiWidgets.get(id, None) + if gad is not None: + gad.updateoutput(**kwargs) + +def getAttr(id, attrname, default=None): + gad = svguiWidgets.get(id, None) + if gad is not None: + return gad.getinput(attrname, default) + return default + diff -r 3edd2f19bce2 -r e0424e96e3fd svgui/svguilib.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/svgui/svguilib.py Sat May 12 11:21:10 2012 +0200 @@ -0,0 +1,117 @@ + +class button: + + def __init__(self, parent, id, args): + self.parent = parent + self.id = id + self.back_elt = getSVGElementById(args.back_id) + self.sele_elt = getSVGElementById(args.sele_id) + self.toggle = args.toggle + self.active = args.active + if args.state != undefined: + self.state = args.state + else: + self.state = False + self.dragging = False + if self.toggle: + self.up = not self.state + else: + self.up = True + + # Add event on each element of the button + if self.active: + self.back_elt.addEventListener("mouseup", self, False) + self.back_elt.addEventListener("mousedown", self, False) + self.back_elt.addEventListener("mouseover", self, False) + self.back_elt.addEventListener("mouseout", self, False) + + self.sele_elt.addEventListener("mouseup", self, False) + self.sele_elt.addEventListener("mousedown", self, False) + self.sele_elt.addEventListener("mouseover", self, False) + self.sele_elt.addEventListener("mouseout", self, False) + + blockSVGElementDrag(self.back_elt) + blockSVGElementDrag(self.sele_elt) + + self.updateElements() + + # method to display the current state of interface + def updateElements(self): + if self.up: + self.sele_elt.setAttribute("display", "none") + self.back_elt.removeAttribute("display") + else: + self.sele_elt.removeAttribute("display") + self.back_elt.setAttribute("display", "none") + + def updateValues(self, values): + if values.state != self.state: + self.state = values.state + self.up = not self.state + updateAttr(self.id, 'state', self.state) + self.updateElements() + + def handleEvent(self, evt): + # Quand le bouton de la souris est presse + if evt.type == "mousedown": + evt.stopPropagation() + setCurrentObject(self) + + self.dragging = True + + if self.toggle: + self.up = self.state + else: + self.up = False + self.state = True + updateAttr(self.id, 'state', self.state) + self.updateElements() + + if isCurrentObject(self) and self.dragging: + # Quand le bouton est survole + if evt.type == "mouseover" and self.toggle: + self.up = self.state + self.updateElements() + + # Quand le curseur quitte la zone du bouton + elif evt.type == "mouseout" and self.toggle: + self.up = not self.state + self.updateElements() + + # Quand le bouton de la souris est relache + elif evt.type == "mouseup": + evt.stopPropagation() + if self.toggle and self.up == self.state: + self.state = not self.state + updateAttr(self.id, 'state', self.state) + elif not self.toggle: + self.up = True + self.state = False + updateAttr(self.id, 'state', self.state) + self.updateElements() + self.dragging = False + +class textControl: + + def __init__(self, parent, id, args): + self.parent = parent + self.id = id + self.back_elt = getSVGElementById(args.back_id) + if args.text != undefined: + self.text = args.text + else: + self.text = "" + self.updateElements() + + def updateValues(self, values): + if values.text != self.value: + self.text = values.text + updateAttr(self.id, 'text', self.text) + self.updateElements() + + def updateElements(self): + self.back_elt.firstChild.firstChild.textContent = self.text + + def handleEvent(self, evt): + pass + \ No newline at end of file diff -r 3edd2f19bce2 -r e0424e96e3fd targets/toolchain_gcc.py --- a/targets/toolchain_gcc.py Wed May 09 00:39:54 2012 +0200 +++ b/targets/toolchain_gcc.py Sat May 12 11:21:10 2012 +0200 @@ -100,10 +100,11 @@ objs = [] relink = False for Location, CFilesAndCFLAGS, DoCalls in self.CTRInstance.LocationCFilesAndCFLAGS: - if Location: - self.CTRInstance.logger.write(_("ConfNode : ") + self.CTRInstance.GetChildByIECLocation(Location).GetCurrentName() + " " + str(Location)+"\n") - else: - self.CTRInstance.logger.write(_("PLC :\n")) + if CFilesAndCFLAGS: + if Location : + self.CTRInstance.logger.write(".".join(map(str,Location))+" :\n") + else: + self.CTRInstance.logger.write(_("PLC :\n")) for CFile, CFLAGS in CFilesAndCFLAGS: if CFile.endswith(".c"): diff -r 3edd2f19bce2 -r e0424e96e3fd tests/python/beremiz.xml --- a/tests/python/beremiz.xml Wed May 09 00:39:54 2012 +0200 +++ b/tests/python/beremiz.xml Sat May 12 11:21:10 2012 +0200 @@ -1,4 +1,4 @@ - - - - + + + + diff -r 3edd2f19bce2 -r e0424e96e3fd tests/python/plc.xml --- a/tests/python/plc.xml Wed May 09 00:39:54 2012 +0200 +++ b/tests/python/plc.xml Sat May 12 11:21:10 2012 +0200 @@ -8,7 +8,7 @@ productVersion="0.0" creationDateTime="2008-12-14T16:21:19"/> + modificationDateTime="2012-05-12T10:42:17"> diff -r 3edd2f19bce2 -r e0424e96e3fd tests/python/python@py_ext/py_ext.xml --- a/tests/python/python@py_ext/py_ext.xml Wed May 09 00:39:54 2012 +0200 +++ b/tests/python/python@py_ext/py_ext.xml Sat May 12 11:21:10 2012 +0200 @@ -1,5 +1,5 @@ - + - diff -r 3edd2f19bce2 -r e0424e96e3fd tests/svgui/python@py_ext/py_ext.xml --- a/tests/svgui/python@py_ext/py_ext.xml Wed May 09 00:39:54 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,8 +0,0 @@ - - - - diff -r 3edd2f19bce2 -r e0424e96e3fd tests/svgui/python@py_ext/svgui@svgui/baseconfnode.xml --- a/tests/svgui/python@py_ext/svgui@svgui/baseconfnode.xml Wed May 09 00:39:54 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,2 +0,0 @@ - - diff -r 3edd2f19bce2 -r e0424e96e3fd tests/svgui/python@py_ext/svgui@svgui/gui.svg --- a/tests/svgui/python@py_ext/svgui@svgui/gui.svg Wed May 09 00:39:54 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,723 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - Default - - - - Start - - - - Stop - - - - - - - - - diff -r 3edd2f19bce2 -r e0424e96e3fd tests/svgui/python@py_ext/svgui@svgui/py_ext.xml --- a/tests/svgui/python@py_ext/svgui@svgui/py_ext.xml Wed May 09 00:39:54 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,4 +0,0 @@ - - - - diff -r 3edd2f19bce2 -r e0424e96e3fd tests/svgui/svgui@svgui/baseconfnode.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/svgui/svgui@svgui/baseconfnode.xml Sat May 12 11:21:10 2012 +0200 @@ -0,0 +1,2 @@ + + diff -r 3edd2f19bce2 -r e0424e96e3fd tests/svgui/svgui@svgui/gui.svg --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/svgui/svgui@svgui/gui.svg Sat May 12 11:21:10 2012 +0200 @@ -0,0 +1,723 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + Default + + + + Start + + + + Stop + + + + + + + + + diff -r 3edd2f19bce2 -r e0424e96e3fd tests/svgui/svgui@svgui/py_ext.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/svgui/svgui@svgui/py_ext.xml Sat May 12 11:21:10 2012 +0200 @@ -0,0 +1,4 @@ + + + + diff -r 3edd2f19bce2 -r e0424e96e3fd tests/wxGlade/HMIFrame@wxglade_hmi/baseconfnode.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/wxGlade/HMIFrame@wxglade_hmi/baseconfnode.xml Sat May 12 11:21:10 2012 +0200 @@ -0,0 +1,2 @@ + + diff -r 3edd2f19bce2 -r e0424e96e3fd tests/wxGlade/HMIFrame@wxglade_hmi/hmi.wxg --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/wxGlade/HMIFrame@wxglade_hmi/hmi.wxg Sat May 12 11:21:10 2012 +0200 @@ -0,0 +1,34 @@ + + + + + + + HMIFrame + + wxVERTICAL + + 0 + + + 0, 10000 + + + + 0 + + + + + + + 0 + + + 1 + + + + + + diff -r 3edd2f19bce2 -r e0424e96e3fd tests/wxGlade/HMIFrame@wxglade_hmi/py_ext.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/wxGlade/HMIFrame@wxglade_hmi/py_ext.xml Sat May 12 11:21:10 2012 +0200 @@ -0,0 +1,4 @@ + + + + diff -r 3edd2f19bce2 -r e0424e96e3fd tests/wxGlade/python@py_ext/HMIFrame@wxglade_hmi/baseconfnode.xml --- a/tests/wxGlade/python@py_ext/HMIFrame@wxglade_hmi/baseconfnode.xml Wed May 09 00:39:54 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,2 +0,0 @@ - - diff -r 3edd2f19bce2 -r e0424e96e3fd tests/wxGlade/python@py_ext/HMIFrame@wxglade_hmi/hmi.wxg --- a/tests/wxGlade/python@py_ext/HMIFrame@wxglade_hmi/hmi.wxg Wed May 09 00:39:54 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,34 +0,0 @@ - - - - - - - HMIFrame - - wxVERTICAL - - 0 - - - 0, 10000 - - - - 0 - - - - - - - 0 - - - 1 - - - - - - diff -r 3edd2f19bce2 -r e0424e96e3fd tests/wxGlade/python@py_ext/HMIFrame@wxglade_hmi/py_ext.xml --- a/tests/wxGlade/python@py_ext/HMIFrame@wxglade_hmi/py_ext.xml Wed May 09 00:39:54 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,4 +0,0 @@ - - - - diff -r 3edd2f19bce2 -r e0424e96e3fd tests/wxGlade/python@py_ext/baseconfnode.xml --- a/tests/wxGlade/python@py_ext/baseconfnode.xml Wed May 09 00:39:54 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,2 +0,0 @@ - - diff -r 3edd2f19bce2 -r e0424e96e3fd tests/wxGlade/python@py_ext/py_ext.xml --- a/tests/wxGlade/python@py_ext/py_ext.xml Wed May 09 00:39:54 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,4 +0,0 @@ - - - - diff -r 3edd2f19bce2 -r e0424e96e3fd util/misc.py --- a/util/misc.py Wed May 09 00:39:54 2012 +0200 +++ b/util/misc.py Sat May 12 11:21:10 2012 +0200 @@ -25,5 +25,5 @@ return reduce(getattr, classpath.split('.')[1:], mod) return fac else: - return lambda:classpath + return lambda:classpath diff -r 3edd2f19bce2 -r e0424e96e3fd wxglade_hmi/README --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wxglade_hmi/README Sat May 12 11:21:10 2012 +0200 @@ -0,0 +1,1 @@ +WxGlade HMI \ No newline at end of file diff -r 3edd2f19bce2 -r e0424e96e3fd wxglade_hmi/__init__.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wxglade_hmi/__init__.py Sat May 12 11:21:10 2012 +0200 @@ -0,0 +1,1 @@ +from wxglade_hmi import * diff -r 3edd2f19bce2 -r e0424e96e3fd wxglade_hmi/wxglade_hmi.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wxglade_hmi/wxglade_hmi.py Sat May 12 11:21:10 2012 +0200 @@ -0,0 +1,127 @@ +import wx +import os, sys +from xml.dom import minidom + +from util import opjimg +from py_ext import PythonFileCTNMixin + +class WxGladeHMI(PythonFileCTNMixin): + + ConfNodeMethods = [ + {"bitmap" : opjimg("editWXGLADE"), + "name" : _("WXGLADE GUI"), + "tooltip" : _("Edit a WxWidgets GUI with WXGlade"), + "method" : "_editWXGLADE"}, + ] + + def ConfNodePath(self): + return os.path.join(os.path.dirname(__file__)) + + def _getWXGLADEpath(self): + # define name for IEC raw code file + return os.path.join(self.CTNPath(), "hmi.wxg") + + def launch_wxglade(self, options, wait=False): + from wxglade import __file__ as fileName + path = os.path.dirname(fileName) + glade = os.path.join(path, 'wxglade.py') + if wx.Platform == '__WXMSW__': + glade = "\"%s\""%glade + mode = {False:os.P_NOWAIT, True:os.P_WAIT}[wait] + os.spawnv(mode, sys.executable, ["\"%s\""%sys.executable] + [glade] + options) + + + def CTNGenerate_C(self, buildpath, locations): + """ + Return C code generated by iec2c compiler + when _generate_softPLC have been called + @param locations: ignored + @return: [(C_file_name, CFLAGS),...] , LDFLAGS_TO_APPEND + """ + + current_location = self.GetCurrentLocation() + # define a unique name for the generated C file + location_str = "_".join(map(lambda x:str(x), current_location)) + + runtimefile_path = os.path.join(buildpath, "runtime_%s.py"%location_str) + runtimefile = open(runtimefile_path, 'w') + + hmi_frames = {} + + wxgfile_path=self._getWXGLADEpath() + if os.path.exists(wxgfile_path): + wxgfile = open(wxgfile_path, 'r') + wxgtree = minidom.parse(wxgfile) + wxgfile.close() + + for node in wxgtree.childNodes[1].childNodes: + if node.nodeType == wxgtree.ELEMENT_NODE: + hmi_frames[node._attrs["name"].value] = node._attrs["class"].value + + hmipyfile_path=os.path.join(self._getBuildPath(), "hmi.py") + if wx.Platform == '__WXMSW__': + wxgfile_path = "\"%s\""%wxgfile_path + wxghmipyfile_path = "\"%s\""%hmipyfile_path + else: + wxghmipyfile_path = hmipyfile_path + self.launch_wxglade(['-o', wxghmipyfile_path, '-g', 'python', wxgfile_path], wait=True) + + hmipyfile = open(hmipyfile_path, 'r') + runtimefile.write(hmipyfile.read()) + hmipyfile.close() + + runtimefile.write(self.GetPythonCode()) + runtimefile.write(""" +%(declare)s + +def _runtime_%(location)s_begin(): + global %(global)s + + def OnCloseFrame(evt): + wx.MessageBox(_("Please stop PLC to close")) + + %(init)s + +def _runtime_%(location)s_cleanup(): + global %(global)s + + %(cleanup)s + +""" % {"location": location_str, + "declare": "\n".join(map(lambda x:"%s = None" % x, hmi_frames.keys())), + "global": ",".join(hmi_frames.keys()), + "init": "\n".join(map(lambda x: """ + %(name)s = %(class)s(None) + %(name)s.Bind(wx.EVT_CLOSE, OnCloseFrame) + %(name)s.Show() +""" % {"name": x[0], "class": x[1]}, + hmi_frames.items())), + "cleanup": "\n ".join(map(lambda x:"%s.Destroy()" % x, hmi_frames.keys()))}) + runtimefile.close() + + return [], "", False, ("runtime_%s.py"%location_str, file(runtimefile_path,"rb")) + + def _editWXGLADE(self): + wxg_filename = self._getWXGLADEpath() + open_wxglade = True + if not self.GetCTRoot().CheckProjectPathPerm(): + dialog = wx.MessageDialog(self.GetCTRoot().AppFrame, + _("You don't have write permissions.\nOpen wxGlade anyway ?"), + _("Open wxGlade"), + wx.YES_NO|wx.ICON_QUESTION) + open_wxglade = dialog.ShowModal() == wx.ID_YES + dialog.Destroy() + if open_wxglade: + if not os.path.exists(wxg_filename): + hmi_name = self.BaseParams.getName() + open(wxg_filename,"w").write(""" + + + + frame_1 + + + """ % {"name": hmi_name, "class": "Class_%s" % hmi_name}) + if wx.Platform == '__WXMSW__': + wxg_filename = "\"%s\""%wxg_filename + self.launch_wxglade([wxg_filename])